morley-client 0.3.0 → 0.3.1
raw patch · 38 files changed
+1043/−417 lines, 38 filesPVP: major bump suggested
API removals or changes: PVP suggests a major version bump
API changes (from Hackage documentation)
- Morley.Client: AliasTxRollup :: Text -> KindedAddress 'AddressKindTxRollup -> TezosClientError
- Morley.Client: revealKey :: HasTezosClient m => ImplicitAlias -> Maybe ScrubbedBytes -> m ()
- Morley.Client.Action: revealKeyUnlessRevealed :: (WithClientLog env m, HasTezosRpc m, HasTezosClient m) => ImplicitAddress -> Maybe ScrubbedBytes -> m ()
- Morley.Client.Action.Common: revealKeyUnlessRevealed :: (WithClientLog env m, HasTezosRpc m, HasTezosClient m) => ImplicitAddress -> Maybe ScrubbedBytes -> m ()
- Morley.Client.TezosClient: AliasTxRollup :: Text -> KindedAddress 'AddressKindTxRollup -> TezosClientError
- Morley.Client.TezosClient.Class: revealKey :: HasTezosClient m => ImplicitAlias -> Maybe ScrubbedBytes -> m ()
- Morley.Client.TezosClient.Impl: AliasTxRollup :: Text -> KindedAddress 'AddressKindTxRollup -> TezosClientError
- Morley.Client.Types: instance Universum.TypeOps.Each '[Morley.Client.Types.ToJSONObject] '[Morley.Client.Types.TransferInfo i, Morley.Client.Types.OriginationInfo i, Morley.Client.Types.RevealInfo i, Morley.Client.Types.DelegationInfo i] => Data.Aeson.Types.ToJSON.ToJSON (Morley.Client.Types.OperationInfo i)
+ Morley.Client: AddressWithAlias :: KindedAddress kind -> Alias kind -> AddressWithAlias kind
+ Morley.Client: GetAllTicketBalancesResponse :: ContractAddress -> Expression -> Expression -> TezosNat -> GetAllTicketBalancesResponse
+ Morley.Client: GetTicketBalance :: ContractAddress -> Expression -> Expression -> GetTicketBalance
+ Morley.Client: OpTransferTicket :: TransferTicketInfo i -> OperationInfo i
+ Morley.Client: REEmptyImplicitContract :: ImplicitAddress -> RunError
+ Morley.Client: [awaAddress] :: AddressWithAlias kind -> KindedAddress kind
+ Morley.Client: [awaAlias] :: AddressWithAlias kind -> Alias kind
+ Morley.Client: [gatbrAmount] :: GetAllTicketBalancesResponse -> TezosNat
+ Morley.Client: [gatbrContentType] :: GetAllTicketBalancesResponse -> Expression
+ Morley.Client: [gatbrContent] :: GetAllTicketBalancesResponse -> Expression
+ Morley.Client: [gatbrTicketer] :: GetAllTicketBalancesResponse -> ContractAddress
+ Morley.Client: [gtbContentType] :: GetTicketBalance -> Expression
+ Morley.Client: [gtbContent] :: GetTicketBalance -> Expression
+ Morley.Client: [gtbTicketer] :: GetTicketBalance -> ContractAddress
+ Morley.Client: data AddressWithAlias kind
+ Morley.Client: data GetAllTicketBalancesResponse
+ Morley.Client: data GetTicketBalance
+ Morley.Client: getAllTicketBalances :: HasTezosRpc m => ContractAddress -> m [GetAllTicketBalancesResponse]
+ Morley.Client: getAllTicketBalancesAtBlock :: HasTezosRpc m => BlockId -> ContractAddress -> m [GetAllTicketBalancesResponse]
+ Morley.Client: getPublicKey :: HasTezosClient m => ImplicitAddressWithAlias -> m PublicKey
+ Morley.Client: getTicketBalance :: HasTezosRpc m => L1Address -> GetTicketBalance -> m Natural
+ Morley.Client: getTicketBalanceAtBlock :: HasTezosRpc m => BlockId -> Address -> GetTicketBalance -> m Natural
+ Morley.Client: resolveAddressWithAlias :: forall addressOrAlias m env. (HasTezosClient m, MonadThrow m, WithClientLog env m, Resolve addressOrAlias) => addressOrAlias -> m (ResolvedAddressAndAlias addressOrAlias)
+ Morley.Client: resolveAddressWithAliasMaybe :: forall addressOrAlias m env. (HasTezosClient m, MonadThrow m, WithClientLog env m, Resolve addressOrAlias) => addressOrAlias -> m (Maybe (ResolvedAddressAndAlias addressOrAlias))
+ Morley.Client: type ContractAddressWithAlias = AddressWithAlias 'AddressKindContract
+ Morley.Client: type ImplicitAddressWithAlias = AddressWithAlias 'AddressKindImplicit
+ Morley.Client.Action.Batched: delegateM :: DelegationData -> OperationsBatch ()
+ Morley.Client.Action.Common: TransferTicketData :: Value t -> Address -> Natural -> Address -> EpName -> Maybe Mutez -> TransferTicketData
+ Morley.Client.Action.Common: [ttdDestination] :: TransferTicketData -> Address
+ Morley.Client.Action.Common: [ttdEntrypoint] :: TransferTicketData -> EpName
+ Morley.Client.Action.Common: [ttdMbFee] :: TransferTicketData -> Maybe Mutez
+ Morley.Client.Action.Common: [ttdTicketAmount] :: TransferTicketData -> Natural
+ Morley.Client.Action.Common: [ttdTicketContents] :: TransferTicketData -> Value t
+ Morley.Client.Action.Common: [ttdTicketTicketer] :: TransferTicketData -> Address
+ Morley.Client.Action.Common: buildTxTicketDataWithAlias :: Maybe Text -> TransferTicketData -> Builder
+ Morley.Client.Action.Common: data TransferTicketData
+ Morley.Client.Action.Reveal: revealKeyOp :: forall m env. (HasTezosRpc m, HasTezosClient m, WithClientLog env m) => PublicKey -> Maybe Mutez -> m OperationHash
+ Morley.Client.Action.Reveal: revealKeyUnlessRevealedOp :: forall m env. (HasTezosRpc m, HasTezosClient m, WithClientLog env m) => PublicKey -> Maybe Mutez -> m ()
+ Morley.Client.Action.Reveal: revealKeyUnlessRevealedWithFee :: (HasTezosRpc m, HasTezosClient m, WithClientLog env m) => ImplicitAddressWithAlias -> Maybe Mutez -> m ()
+ Morley.Client.Action.Reveal: revealKeyWithFee :: (HasTezosRpc m, HasTezosClient m, WithClientLog env m) => ImplicitAddressWithAlias -> Maybe Mutez -> m OperationHash
+ Morley.Client.Action.Transaction: TransferTicketData :: Value t -> Address -> Natural -> Address -> EpName -> Maybe Mutez -> TransferTicketData
+ Morley.Client.Action.Transaction: [ttdDestination] :: TransferTicketData -> Address
+ Morley.Client.Action.Transaction: [ttdEntrypoint] :: TransferTicketData -> EpName
+ Morley.Client.Action.Transaction: [ttdMbFee] :: TransferTicketData -> Maybe Mutez
+ Morley.Client.Action.Transaction: [ttdTicketAmount] :: TransferTicketData -> Natural
+ Morley.Client.Action.Transaction: [ttdTicketContents] :: TransferTicketData -> Value t
+ Morley.Client.Action.Transaction: [ttdTicketTicketer] :: TransferTicketData -> Address
+ Morley.Client.Action.Transaction: data TransferTicketData
+ Morley.Client.Action.Transaction: transferTicket :: forall m t env kind. (HasTezosRpc m, HasTezosClient m, WithClientLog env m, ParameterScope t, Comparable t) => ImplicitAddressWithAlias -> KindedAddress kind -> ContractAddress -> Value t -> Natural -> EpName -> Maybe Mutez -> m (OperationHash, [IntOpEvent])
+ Morley.Client.App: getAllTicketBalancesAtBlockImpl :: (RunClient m, MonadUnliftIO m, MonadCatch m) => BlockId -> ContractAddress -> m [GetAllTicketBalancesResponse]
+ Morley.Client.App: getTicketBalanceAtBlockImpl :: (RunClient m, MonadUnliftIO m, MonadCatch m) => BlockId -> Address -> GetTicketBalance -> m Natural
+ Morley.Client.Parser: TicketBalanceArgs :: ContractAddress -> Value -> Ty -> TicketBalanceArgs
+ Morley.Client.Parser: TransferTicketArgs :: ImplicitAddressOrAlias -> Value -> Ty -> ContractAddressOrAlias -> Natural -> SomeAddressOrAlias -> Maybe Mutez -> TransferTicketArgs
+ Morley.Client.Parser: [AllTicketBalances] :: ContractAddressOrAlias -> ClientArgsRaw
+ Morley.Client.Parser: [TicketBalance] :: SomeAddressOrAlias -> TicketBalanceArgs -> ClientArgsRaw
+ Morley.Client.Parser: [TransferTicket] :: TransferTicketArgs -> ClientArgsRaw
+ Morley.Client.Parser: [tbaContentType] :: TicketBalanceArgs -> Ty
+ Morley.Client.Parser: [tbaContent] :: TicketBalanceArgs -> Value
+ Morley.Client.Parser: [tbaTicketer] :: TicketBalanceArgs -> ContractAddress
+ Morley.Client.Parser: [ttaDestination] :: TransferTicketArgs -> SomeAddressOrAlias
+ Morley.Client.Parser: [ttaMbFee] :: TransferTicketArgs -> Maybe Mutez
+ Morley.Client.Parser: [ttaSender] :: TransferTicketArgs -> ImplicitAddressOrAlias
+ Morley.Client.Parser: [ttaTicketAmount] :: TransferTicketArgs -> Natural
+ Morley.Client.Parser: [ttaTicketContents] :: TransferTicketArgs -> Value
+ Morley.Client.Parser: [ttaTicketTicketer] :: TransferTicketArgs -> ContractAddressOrAlias
+ Morley.Client.Parser: [ttaTicketType] :: TransferTicketArgs -> Ty
+ Morley.Client.Parser: data TicketBalanceArgs
+ Morley.Client.Parser: data TransferTicketArgs
+ Morley.Client.RPC.API: [getAllTicketBalancesAtBlock] :: NodeMethods m -> BlockId -> ContractAddress -> m [GetAllTicketBalancesResponse]
+ Morley.Client.RPC.API: [getTicketBalanceAtBlock] :: NodeMethods m -> BlockId -> Address -> GetTicketBalance -> m TezosNat
+ Morley.Client.RPC.Class: getAllTicketBalancesAtBlock :: HasTezosRpc m => BlockId -> ContractAddress -> m [GetAllTicketBalancesResponse]
+ Morley.Client.RPC.Class: getTicketBalanceAtBlock :: HasTezosRpc m => BlockId -> Address -> GetTicketBalance -> m Natural
+ Morley.Client.RPC.Getters: contractStateResolver :: HasTezosRpc m => BlockId -> ContractAddress -> m (Maybe ContractState)
+ Morley.Client.RPC.Getters: getAllTicketBalances :: HasTezosRpc m => ContractAddress -> m [GetAllTicketBalancesResponse]
+ Morley.Client.RPC.Getters: getTicketBalance :: HasTezosRpc m => L1Address -> GetTicketBalance -> m Natural
+ Morley.Client.RPC.Types: GetAllTicketBalancesResponse :: ContractAddress -> Expression -> Expression -> TezosNat -> GetAllTicketBalancesResponse
+ Morley.Client.RPC.Types: GetTicketBalance :: ContractAddress -> Expression -> Expression -> GetTicketBalance
+ Morley.Client.RPC.Types: REEmptyImplicitContract :: ImplicitAddress -> RunError
+ Morley.Client.RPC.Types: TransferTicketOperation :: Expression -> Expression -> Address -> TezosNat -> Address -> Text -> TransferTicketOperation
+ Morley.Client.RPC.Types: [gatbrAmount] :: GetAllTicketBalancesResponse -> TezosNat
+ Morley.Client.RPC.Types: [gatbrContentType] :: GetAllTicketBalancesResponse -> Expression
+ Morley.Client.RPC.Types: [gatbrContent] :: GetAllTicketBalancesResponse -> Expression
+ Morley.Client.RPC.Types: [gatbrTicketer] :: GetAllTicketBalancesResponse -> ContractAddress
+ Morley.Client.RPC.Types: [gtbContentType] :: GetTicketBalance -> Expression
+ Morley.Client.RPC.Types: [gtbContent] :: GetTicketBalance -> Expression
+ Morley.Client.RPC.Types: [gtbTicketer] :: GetTicketBalance -> ContractAddress
+ Morley.Client.RPC.Types: [ttoDestination] :: TransferTicketOperation -> Address
+ Morley.Client.RPC.Types: [ttoEntrypoint] :: TransferTicketOperation -> Text
+ Morley.Client.RPC.Types: [ttoTicketAmount] :: TransferTicketOperation -> TezosNat
+ Morley.Client.RPC.Types: [ttoTicketContents] :: TransferTicketOperation -> Expression
+ Morley.Client.RPC.Types: [ttoTicketTicketer] :: TransferTicketOperation -> Address
+ Morley.Client.RPC.Types: [ttoTicketTy] :: TransferTicketOperation -> Expression
+ Morley.Client.RPC.Types: data GetAllTicketBalancesResponse
+ Morley.Client.RPC.Types: data GetTicketBalance
+ Morley.Client.RPC.Types: data TransferTicketOperation
+ Morley.Client.RPC.Types: instance Data.Aeson.Types.FromJSON.FromJSON Morley.Client.RPC.Types.GetAllTicketBalancesResponse
+ Morley.Client.RPC.Types: instance Data.Aeson.Types.ToJSON.ToJSON Morley.Client.RPC.Types.GetTicketBalance
+ Morley.Client.RPC.Types: instance Data.Aeson.Types.ToJSON.ToJSON Morley.Client.RPC.Types.TransferTicketOperation
+ Morley.Client.RPC.Types: instance Morley.Client.Types.ToJSONObject Morley.Client.RPC.Types.TransferTicketOperation
+ Morley.Client.TezosClient: resolveAddressWithAlias :: forall addressOrAlias m env. (HasTezosClient m, MonadThrow m, WithClientLog env m, Resolve addressOrAlias) => addressOrAlias -> m (ResolvedAddressAndAlias addressOrAlias)
+ Morley.Client.TezosClient: resolveAddressWithAliasMaybe :: forall addressOrAlias m env. (HasTezosClient m, MonadThrow m, WithClientLog env m, Resolve addressOrAlias) => addressOrAlias -> m (Maybe (ResolvedAddressAndAlias addressOrAlias))
+ Morley.Client.TezosClient.Class: getPublicKey :: HasTezosClient m => ImplicitAddressWithAlias -> m PublicKey
+ Morley.Client.TezosClient.Impl: resolveAddressWithAlias :: forall addressOrAlias m env. (HasTezosClient m, MonadThrow m, WithClientLog env m, Resolve addressOrAlias) => addressOrAlias -> m (ResolvedAddressAndAlias addressOrAlias)
+ Morley.Client.TezosClient.Impl: resolveAddressWithAliasEither :: forall m env. (Resolve addressOrAlias, HasTezosClient m, MonadThrow m, WithClientLog env m) => addressOrAlias -> m (Either ResolveError (ResolvedAddressAndAlias addressOrAlias))
+ Morley.Client.TezosClient.Impl: resolveAddressWithAliasMaybe :: forall addressOrAlias m env. (HasTezosClient m, MonadThrow m, WithClientLog env m, Resolve addressOrAlias) => addressOrAlias -> m (Maybe (ResolvedAddressAndAlias addressOrAlias))
+ Morley.Client.TezosClient.Impl: revealKeyUnlessRevealed :: (WithClientLog env m, HasTezosRpc m, MonadIO m, HasTezosClientEnv env) => ImplicitAddressWithAlias -> Maybe ScrubbedBytes -> m ()
+ Morley.Client.Types: AddressWithAlias :: KindedAddress kind -> Alias kind -> AddressWithAlias kind
+ Morley.Client.Types: OpTransferTicket :: TransferTicketInfo i -> OperationInfo i
+ Morley.Client.Types: [awaAddress] :: AddressWithAlias kind -> KindedAddress kind
+ Morley.Client.Types: [awaAlias] :: AddressWithAlias kind -> Alias kind
+ Morley.Client.Types: _OpTransferTicket :: forall i_aGJ8. Prism' (OperationInfo i_aGJ8) (TransferTicketInfo i_aGJ8)
+ Morley.Client.Types: data AddressWithAlias kind
+ Morley.Client.Types: instance Formatting.Buildable.Buildable (Morley.Client.Types.AddressWithAlias kind)
+ Morley.Client.Types: instance GHC.Classes.Eq (Morley.Client.Types.AddressWithAlias kind)
+ Morley.Client.Types: instance GHC.Show.Show (Morley.Client.Types.AddressWithAlias kind)
+ Morley.Client.Types: instance Lorentz.Address.ToAddress (Morley.Client.Types.AddressWithAlias kind)
+ Morley.Client.Types: instance Lorentz.Address.ToTAddress cp vd (Morley.Tezos.Address.KindedAddress kind) => Lorentz.Address.ToTAddress cp vd (Morley.Client.Types.AddressWithAlias kind)
+ Morley.Client.Types: instance Universum.TypeOps.Each '[Morley.Client.Types.ToJSONObject] '[Morley.Client.Types.TransferInfo i, Morley.Client.Types.TransferTicketInfo i, Morley.Client.Types.OriginationInfo i, Morley.Client.Types.RevealInfo i, Morley.Client.Types.DelegationInfo i] => Data.Aeson.Types.ToJSON.ToJSON (Morley.Client.Types.OperationInfo i)
+ Morley.Client.Types: type ContractAddressWithAlias = AddressWithAlias 'AddressKindContract
+ Morley.Client.Types: type ImplicitAddressWithAlias = AddressWithAlias 'AddressKindImplicit
- Morley.Client: genFreshKey :: HasTezosClient m => ImplicitAlias -> m ImplicitAddress
+ Morley.Client: genFreshKey :: HasTezosClient m => ImplicitAlias -> m ImplicitAddressWithAlias
- Morley.Client: genKey :: HasTezosClient m => ImplicitAlias -> m ImplicitAddress
+ Morley.Client: genKey :: HasTezosClient m => ImplicitAlias -> m ImplicitAddressWithAlias
- Morley.Client: getKeyPassword :: HasTezosClient m => ImplicitAddress -> m (Maybe ScrubbedBytes)
+ Morley.Client: getKeyPassword :: HasTezosClient m => ImplicitAddressWithAlias -> m (Maybe ScrubbedBytes)
- Morley.Client: signBytes :: HasTezosClient m => ImplicitAddressOrAlias -> Maybe ScrubbedBytes -> ByteString -> m Signature
+ Morley.Client: signBytes :: HasTezosClient m => ImplicitAddressWithAlias -> Maybe ScrubbedBytes -> ByteString -> m Signature
- Morley.Client.Action.Batched: runOperationsBatch :: (HasTezosRpc m, HasTezosClient m, WithClientLog env m) => ImplicitAddressOrAlias -> OperationsBatch a -> m (Maybe OperationHash, a)
+ Morley.Client.Action.Batched: runOperationsBatch :: (HasTezosRpc m, HasTezosClient m, WithClientLog env m) => ImplicitAddressWithAlias -> OperationsBatch a -> m (Maybe OperationHash, a)
- Morley.Client.Action.Delegation: registerDelegateOp :: (HasTezosRpc m, HasTezosClient m, MonadReader env m, HasLog env Message m) => KeyHash -> m OperationHash
+ Morley.Client.Action.Delegation: registerDelegateOp :: (HasTezosRpc m, HasTezosClient m, MonadReader env m, HasLog env Message m) => ImplicitAddressWithAlias -> m OperationHash
- Morley.Client.Action.Delegation: setDelegateOp :: (HasTezosRpc m, HasTezosClient m, MonadReader env m, HasLog env Message m) => ImplicitAddressOrAlias -> Maybe KeyHash -> m OperationHash
+ Morley.Client.Action.Delegation: setDelegateOp :: (HasTezosRpc m, HasTezosClient m, MonadReader env m, HasLog env Message m) => ImplicitAddressWithAlias -> Maybe KeyHash -> m OperationHash
- Morley.Client.Action.Operation: dryRunOperationsNonEmpty :: forall m env. (HasTezosRpc m, HasTezosClient m, WithClientLog env m) => ImplicitAddressOrAlias -> NonEmpty (OperationInfo ClientInput) -> m (NonEmpty (AppliedResult, TezosMutez))
+ Morley.Client.Action.Operation: dryRunOperationsNonEmpty :: forall m env. (HasTezosRpc m, HasTezosClient m, WithClientLog env m) => ImplicitAddressWithAlias -> NonEmpty (OperationInfo ClientInput) -> m (NonEmpty (AppliedResult, TezosMutez))
- Morley.Client.Action.Operation: runOperations :: forall m env. (HasTezosRpc m, HasTezosClient m, WithClientLog env m) => ImplicitAddressOrAlias -> [OperationInfo ClientInput] -> m (Maybe OperationHash, [OperationInfo Result])
+ Morley.Client.Action.Operation: runOperations :: forall m env. (HasTezosRpc m, HasTezosClient m, WithClientLog env m) => ImplicitAddressWithAlias -> [OperationInfo ClientInput] -> m (Maybe OperationHash, [OperationInfo Result])
- Morley.Client.Action.Operation: runOperationsNonEmpty :: forall m env. (HasTezosRpc m, HasTezosClient m, WithClientLog env m) => ImplicitAddressOrAlias -> NonEmpty (OperationInfo ClientInput) -> m (OperationHash, NonEmpty (OperationInfo Result))
+ Morley.Client.Action.Operation: runOperationsNonEmpty :: forall m env. (HasTezosRpc m, HasTezosClient m, WithClientLog env m) => ImplicitAddressWithAlias -> NonEmpty (OperationInfo ClientInput) -> m (OperationHash, NonEmpty (OperationInfo Result))
- Morley.Client.Action.Origination: lOriginateContract :: forall m cp st vd env. (HasTezosRpc m, HasTezosClient m, WithClientLog env m, NiceStorage st, NiceParameterFull cp) => AliasBehavior -> ContractAlias -> ImplicitAddressOrAlias -> Mutez -> Contract cp st vd -> st -> Maybe Mutez -> Maybe KeyHash -> m (OperationHash, ContractAddress)
+ Morley.Client.Action.Origination: lOriginateContract :: forall m cp st vd env. (HasTezosRpc m, HasTezosClient m, WithClientLog env m, NiceStorage st, NiceParameterFull cp) => AliasBehavior -> ContractAlias -> ImplicitAddressWithAlias -> Mutez -> Contract cp st vd -> st -> Maybe Mutez -> Maybe KeyHash -> m (OperationHash, ContractAddress)
- Morley.Client.Action.Origination: lOriginateContracts :: forall m env. (HasTezosRpc m, HasTezosClient m, WithClientLog env m) => ImplicitAddressOrAlias -> [LOriginationData] -> m (Maybe OperationHash, [ContractAddress])
+ Morley.Client.Action.Origination: lOriginateContracts :: forall m env. (HasTezosRpc m, HasTezosClient m, WithClientLog env m) => ImplicitAddressWithAlias -> [LOriginationData] -> m (Maybe OperationHash, [ContractAddress])
- Morley.Client.Action.Origination: lOriginateLargeContract :: forall m cp st vd env. (HasTezosRpc m, HasTezosClient m, WithClientLog env m, NiceStorage st, NiceParameterFull cp) => AliasBehavior -> ContractAlias -> ImplicitAddressOrAlias -> Mutez -> Contract cp st vd -> st -> Maybe Mutez -> Maybe KeyHash -> m (OperationHash, ContractAddress)
+ Morley.Client.Action.Origination: lOriginateLargeContract :: forall m cp st vd env. (HasTezosRpc m, HasTezosClient m, WithClientLog env m, NiceStorage st, NiceParameter cp) => AliasBehavior -> ContractAlias -> ImplicitAddressWithAlias -> Mutez -> Contract cp st vd -> st -> Maybe Mutez -> Maybe KeyHash -> m (OperationHash, ContractAddress)
- Morley.Client.Action.Origination: lOriginateLargeContracts :: forall m env. (HasTezosRpc m, HasTezosClient m, WithClientLog env m) => ImplicitAddressOrAlias -> [LOriginationData] -> m (Maybe OperationHash, [ContractAddress])
+ Morley.Client.Action.Origination: lOriginateLargeContracts :: forall m env. (HasTezosRpc m, HasTezosClient m, WithClientLog env m) => ImplicitAddressWithAlias -> [LOriginationData] -> m (Maybe OperationHash, [ContractAddress])
- Morley.Client.Action.Origination: originateContract :: forall m cp st env. (HasTezosRpc m, HasTezosClient m, WithClientLog env m, StorageScope st, ParameterScope cp) => AliasBehavior -> ContractAlias -> ImplicitAddressOrAlias -> Mutez -> Contract cp st -> Value st -> Maybe Mutez -> Maybe KeyHash -> m (OperationHash, ContractAddress)
+ Morley.Client.Action.Origination: originateContract :: forall m cp st env. (HasTezosRpc m, HasTezosClient m, WithClientLog env m, StorageScope st, ParameterScope cp) => AliasBehavior -> ContractAlias -> ImplicitAddressWithAlias -> Mutez -> Contract cp st -> Value st -> Maybe Mutez -> Maybe KeyHash -> m (OperationHash, ContractAddress)
- Morley.Client.Action.Origination: originateContracts :: forall m env. (HasTezosRpc m, HasTezosClient m, WithClientLog env m) => ImplicitAddressOrAlias -> [OriginationData] -> m (Maybe OperationHash, [ContractAddress])
+ Morley.Client.Action.Origination: originateContracts :: forall m env. (HasTezosRpc m, HasTezosClient m, WithClientLog env m) => ImplicitAddressWithAlias -> [OriginationData] -> m (Maybe OperationHash, [ContractAddress])
- Morley.Client.Action.Origination: originateLargeContract :: forall m cp st env. (HasTezosRpc m, HasTezosClient m, WithClientLog env m, StorageScope st, ParameterScope cp) => AliasBehavior -> ContractAlias -> ImplicitAddressOrAlias -> Mutez -> Contract cp st -> Value st -> Maybe Mutez -> Maybe KeyHash -> m (OperationHash, ContractAddress)
+ Morley.Client.Action.Origination: originateLargeContract :: forall m cp st env. (HasTezosRpc m, HasTezosClient m, WithClientLog env m, StorageScope st, ParameterScope cp) => AliasBehavior -> ContractAlias -> ImplicitAddressWithAlias -> Mutez -> Contract cp st -> Value st -> Maybe Mutez -> Maybe KeyHash -> m (OperationHash, ContractAddress)
- Morley.Client.Action.Origination: originateLargeContracts :: forall m env. (HasTezosRpc m, HasTezosClient m, WithClientLog env m) => ImplicitAddressOrAlias -> [OriginationData] -> m (Maybe OperationHash, [ContractAddress])
+ Morley.Client.Action.Origination: originateLargeContracts :: forall m env. (HasTezosRpc m, HasTezosClient m, WithClientLog env m) => ImplicitAddressWithAlias -> [OriginationData] -> m (Maybe OperationHash, [ContractAddress])
- Morley.Client.Action.Origination: originateLargeUntypedContract :: forall m env. (HasTezosRpc m, HasTezosClient m, WithClientLog env m) => AliasBehavior -> ContractAlias -> ImplicitAddressOrAlias -> Mutez -> Contract -> Value -> Maybe Mutez -> Maybe KeyHash -> m (OperationHash, ContractAddress)
+ Morley.Client.Action.Origination: originateLargeUntypedContract :: forall m env. (HasTezosRpc m, HasTezosClient m, WithClientLog env m) => AliasBehavior -> ContractAlias -> ImplicitAddressWithAlias -> Mutez -> Contract -> Value -> Maybe Mutez -> Maybe KeyHash -> m (OperationHash, ContractAddress)
- Morley.Client.Action.Origination: originateUntypedContract :: forall m env. (HasTezosRpc m, HasTezosClient m, WithClientLog env m) => AliasBehavior -> ContractAlias -> ImplicitAddressOrAlias -> Mutez -> Contract -> Value -> Maybe Mutez -> Maybe KeyHash -> m (OperationHash, ContractAddress)
+ Morley.Client.Action.Origination: originateUntypedContract :: forall m env. (HasTezosRpc m, HasTezosClient m, WithClientLog env m) => AliasBehavior -> ContractAlias -> ImplicitAddressWithAlias -> Mutez -> Contract -> Value -> Maybe Mutez -> Maybe KeyHash -> m (OperationHash, ContractAddress)
- Morley.Client.Action.Reveal: revealKey :: forall m env. (HasTezosRpc m, HasTezosClient m, WithClientLog env m) => PublicKey -> Maybe Mutez -> m OperationHash
+ Morley.Client.Action.Reveal: revealKey :: (HasTezosRpc m, HasTezosClient m, WithClientLog env m) => ImplicitAddressWithAlias -> m OperationHash
- Morley.Client.Action.Reveal: revealKeyUnlessRevealed :: forall m env. (HasTezosRpc m, HasTezosClient m, WithClientLog env m) => PublicKey -> Maybe Mutez -> m ()
+ Morley.Client.Action.Reveal: revealKeyUnlessRevealed :: (HasTezosRpc m, HasTezosClient m, WithClientLog env m) => ImplicitAddressWithAlias -> m ()
- Morley.Client.Action.Transaction: lRunTransactions :: forall m env. (HasTezosRpc m, HasTezosClient m, WithClientLog env m) => ImplicitAddress -> [LTransactionData] -> m (Maybe (OperationHash, [OperationInfo Result]))
+ Morley.Client.Action.Transaction: lRunTransactions :: forall m env. (HasTezosRpc m, HasTezosClient m, WithClientLog env m) => ImplicitAddressWithAlias -> [LTransactionData] -> m (Maybe (OperationHash, [OperationInfo Result]))
- Morley.Client.Action.Transaction: lTransfer :: forall m t env kind. (HasTezosRpc m, HasTezosClient m, WithClientLog env m, NiceParameter t, L1AddressKind kind) => ImplicitAddress -> KindedAddress kind -> Mutez -> EpName -> t -> Maybe Mutez -> m (OperationHash, [IntOpEvent])
+ Morley.Client.Action.Transaction: lTransfer :: forall m t env kind. (HasTezosRpc m, HasTezosClient m, WithClientLog env m, NiceParameter t, L1AddressKind kind) => ImplicitAddressWithAlias -> KindedAddress kind -> Mutez -> EpName -> t -> Maybe Mutez -> m (OperationHash, [IntOpEvent])
- Morley.Client.Action.Transaction: runTransactions :: forall m env. (HasTezosRpc m, HasTezosClient m, WithClientLog env m) => ImplicitAddress -> [TransactionData] -> m (Maybe (OperationHash, [OperationInfo Result]))
+ Morley.Client.Action.Transaction: runTransactions :: forall m env. (HasTezosRpc m, HasTezosClient m, WithClientLog env m) => ImplicitAddressWithAlias -> [TransactionData] -> m (Maybe (OperationHash, [OperationInfo Result]))
- Morley.Client.Action.Transaction: transfer :: forall m t env kind. (HasTezosRpc m, HasTezosClient m, WithClientLog env m, ParameterScope t, L1AddressKind kind) => ImplicitAddress -> KindedAddress kind -> Mutez -> EpName -> Value t -> Maybe Mutez -> m (OperationHash, [IntOpEvent])
+ Morley.Client.Action.Transaction: transfer :: forall m t env kind. (HasTezosRpc m, HasTezosClient m, WithClientLog env m, ParameterScope t, L1AddressKind kind) => ImplicitAddressWithAlias -> KindedAddress kind -> Mutez -> EpName -> Value t -> Maybe Mutez -> m (OperationHash, [IntOpEvent])
- Morley.Client.RPC.API: NodeMethods :: (BlockId -> m Text) -> (BlockId -> ImplicitAddress -> m TezosInt64) -> (BlockId -> ContractAddress -> m OriginationScript) -> (BlockId -> ContractAddress -> m Expression) -> (BlockId -> m BlockConstants) -> (BlockId -> m BlockHeader) -> (BlockId -> m ProtocolParameters) -> (BlockId -> m [[BlockOperation]]) -> (BlockId -> m [[OperationHash]]) -> (BlockId -> ContractAddress -> GetBigMap -> m GetBigMapResult) -> (BlockId -> Natural -> Text -> m Expression) -> (BlockId -> Natural -> Maybe Natural -> Maybe Natural -> m Expression) -> (BlockId -> Address -> m TezosMutez) -> (BlockId -> L1Address -> m (Maybe KeyHash)) -> (BlockId -> CalcSize -> m ScriptSize) -> (BlockId -> ForgeOperation -> m HexJSONByteString) -> (BlockId -> RunOperation -> m RunOperationResult) -> (BlockId -> [PreApplyOperation] -> m [RunOperationResult]) -> (BlockId -> RunCode -> m RunCodeResult) -> (BlockId -> ImplicitAddress -> m (Maybe PublicKey)) -> m Text -> (HexJSONByteString -> m OperationHash) -> NodeMethods m
+ Morley.Client.RPC.API: NodeMethods :: (BlockId -> m Text) -> (BlockId -> ImplicitAddress -> m TezosInt64) -> (BlockId -> ContractAddress -> m OriginationScript) -> (BlockId -> ContractAddress -> m Expression) -> (BlockId -> Address -> GetTicketBalance -> m TezosNat) -> (BlockId -> ContractAddress -> m [GetAllTicketBalancesResponse]) -> (BlockId -> m BlockConstants) -> (BlockId -> m BlockHeader) -> (BlockId -> m ProtocolParameters) -> (BlockId -> m [[BlockOperation]]) -> (BlockId -> m [[OperationHash]]) -> (BlockId -> ContractAddress -> GetBigMap -> m GetBigMapResult) -> (BlockId -> Natural -> Text -> m Expression) -> (BlockId -> Natural -> Maybe Natural -> Maybe Natural -> m Expression) -> (BlockId -> Address -> m TezosMutez) -> (BlockId -> L1Address -> m (Maybe KeyHash)) -> (BlockId -> CalcSize -> m ScriptSize) -> (BlockId -> ForgeOperation -> m HexJSONByteString) -> (BlockId -> RunOperation -> m RunOperationResult) -> (BlockId -> [PreApplyOperation] -> m [RunOperationResult]) -> (BlockId -> RunCode -> m RunCodeResult) -> (BlockId -> ImplicitAddress -> m (Maybe PublicKey)) -> m Text -> (HexJSONByteString -> m OperationHash) -> NodeMethods m
- Morley.Client.TezosClient.Class: genFreshKey :: HasTezosClient m => ImplicitAlias -> m ImplicitAddress
+ Morley.Client.TezosClient.Class: genFreshKey :: HasTezosClient m => ImplicitAlias -> m ImplicitAddressWithAlias
- Morley.Client.TezosClient.Class: genKey :: HasTezosClient m => ImplicitAlias -> m ImplicitAddress
+ Morley.Client.TezosClient.Class: genKey :: HasTezosClient m => ImplicitAlias -> m ImplicitAddressWithAlias
- Morley.Client.TezosClient.Class: getKeyPassword :: HasTezosClient m => ImplicitAddress -> m (Maybe ScrubbedBytes)
+ Morley.Client.TezosClient.Class: getKeyPassword :: HasTezosClient m => ImplicitAddressWithAlias -> m (Maybe ScrubbedBytes)
- Morley.Client.TezosClient.Class: signBytes :: HasTezosClient m => ImplicitAddressOrAlias -> Maybe ScrubbedBytes -> ByteString -> m Signature
+ Morley.Client.TezosClient.Class: signBytes :: HasTezosClient m => ImplicitAddressWithAlias -> Maybe ScrubbedBytes -> ByteString -> m Signature
- Morley.Client.TezosClient.Impl: getKeyPassword :: (WithClientLog env m, HasTezosClientEnv env, MonadIO m, MonadMask m, HasTezosClient m) => ImplicitAddress -> m (Maybe ScrubbedBytes)
+ Morley.Client.TezosClient.Impl: getKeyPassword :: (WithClientLog env m, HasTezosClientEnv env, MonadIO m, MonadMask m) => ImplicitAlias -> m (Maybe ScrubbedBytes)
- Morley.Client.TezosClient.Impl: getPublicKey :: (WithClientLog env m, HasTezosClientEnv env, MonadIO m, MonadCatch m, HasTezosClient m) => ImplicitAddressOrAlias -> m PublicKey
+ Morley.Client.TezosClient.Impl: getPublicKey :: (WithClientLog env m, HasTezosClientEnv env, MonadIO m, MonadCatch m) => ImplicitAlias -> m PublicKey
- Morley.Client.TezosClient.Impl: getSecretKey :: (WithClientLog env m, HasTezosClientEnv env, MonadIO m, MonadCatch m, HasTezosClient m) => ImplicitAddressOrAlias -> m SecretKey
+ Morley.Client.TezosClient.Impl: getSecretKey :: (WithClientLog env m, HasTezosClientEnv env, MonadIO m, MonadCatch m) => ImplicitAlias -> m SecretKey
- Morley.Client.TezosClient.Impl: importKey :: (WithClientLog env m, HasTezosClientEnv env, MonadIO m, MonadCatch m) => Bool -> ImplicitAlias -> SecretKey -> m ImplicitAlias
+ Morley.Client.TezosClient.Impl: importKey :: (WithClientLog env m, HasTezosClientEnv env, MonadIO m, MonadCatch m) => Bool -> ImplicitAlias -> SecretKey -> m ImplicitAddressWithAlias
- Morley.Client.TezosClient.Impl: signBytes :: (WithClientLog env m, HasTezosClientEnv env, MonadIO m, MonadCatch m, HasTezosClient m) => ImplicitAddressOrAlias -> Maybe ScrubbedBytes -> ByteString -> m Signature
+ Morley.Client.TezosClient.Impl: signBytes :: (WithClientLog env m, HasTezosClientEnv env, MonadIO m, MonadCatch m) => ImplicitAlias -> Maybe ScrubbedBytes -> ByteString -> m Signature
- Morley.Client.TezosClient.Impl: type family ResolvedAlias addressOrAlias :: Type;
+ Morley.Client.TezosClient.Impl: type family ResolvedAddressAndAlias addressOrAlias :: Type;
- Morley.Client.Types: _OpDelegation :: forall i_aNUu. Prism' (OperationInfo i_aNUu) (DelegationInfo i_aNUu)
+ Morley.Client.Types: _OpDelegation :: forall i_aGJ8. Prism' (OperationInfo i_aGJ8) (DelegationInfo i_aGJ8)
- Morley.Client.Types: _OpOriginate :: forall i_aNUu. Prism' (OperationInfo i_aNUu) (OriginationInfo i_aNUu)
+ Morley.Client.Types: _OpOriginate :: forall i_aGJ8. Prism' (OperationInfo i_aGJ8) (OriginationInfo i_aGJ8)
- Morley.Client.Types: _OpReveal :: forall i_aNUu. Prism' (OperationInfo i_aNUu) (RevealInfo i_aNUu)
+ Morley.Client.Types: _OpReveal :: forall i_aGJ8. Prism' (OperationInfo i_aGJ8) (RevealInfo i_aGJ8)
- Morley.Client.Types: _OpTransfer :: forall i_aNUu. Prism' (OperationInfo i_aNUu) (TransferInfo i_aNUu)
+ Morley.Client.Types: _OpTransfer :: forall i_aGJ8. Prism' (OperationInfo i_aGJ8) (TransferInfo i_aGJ8)
- Morley.Client.Util: withAmount :: forall cp_a1HvI st_a1HvJ. Lens' (RunContractParameters cp_a1HvI st_a1HvJ) Mutez
+ Morley.Client.Util: withAmount :: forall cp_a1MRU st_a1MRV. Lens' (RunContractParameters cp_a1MRU st_a1MRV) Mutez
- Morley.Client.Util: withBalance :: forall cp_a1HvI st_a1HvJ. Lens' (RunContractParameters cp_a1HvI st_a1HvJ) Mutez
+ Morley.Client.Util: withBalance :: forall cp_a1MRU st_a1MRV. Lens' (RunContractParameters cp_a1MRU st_a1MRV) Mutez
- Morley.Client.Util: withLevel :: forall cp_a1HvI st_a1HvJ. Lens' (RunContractParameters cp_a1HvI st_a1HvJ) (Maybe Natural)
+ Morley.Client.Util: withLevel :: forall cp_a1MRU st_a1MRV. Lens' (RunContractParameters cp_a1MRU st_a1MRV) (Maybe Natural)
- Morley.Client.Util: withNow :: forall cp_a1HvI st_a1HvJ. Lens' (RunContractParameters cp_a1HvI st_a1HvJ) (Maybe Timestamp)
+ Morley.Client.Util: withNow :: forall cp_a1MRU st_a1MRV. Lens' (RunContractParameters cp_a1MRU st_a1MRV) (Maybe Timestamp)
- Morley.Client.Util: withSender :: forall cp_a1HvI st_a1HvJ. Lens' (RunContractParameters cp_a1HvI st_a1HvJ) (Maybe ImplicitAddress)
+ Morley.Client.Util: withSender :: forall cp_a1MRU st_a1MRV. Lens' (RunContractParameters cp_a1MRU st_a1MRV) (Maybe ImplicitAddress)
- Morley.Client.Util: withSource :: forall cp_a1HvI st_a1HvJ. Lens' (RunContractParameters cp_a1HvI st_a1HvJ) (Maybe ImplicitAddress)
+ Morley.Client.Util: withSource :: forall cp_a1MRU st_a1MRV. Lens' (RunContractParameters cp_a1MRU st_a1MRV) (Maybe ImplicitAddress)
Files
- CHANGES.md +43/−0
- LICENSE +1/−1
- README.md +4/−0
- app/Main.hs +81/−25
- morley-client.cabal +4/−3
- src/Morley/Client.hs +9/−0
- src/Morley/Client/Action.hs +3/−2
- src/Morley/Client/Action/Batched.hs +6/−2
- src/Morley/Client/Action/Common.hs +33/−19
- src/Morley/Client/Action/Delegation.hs +5/−4
- src/Morley/Client/Action/Operation.hs +68/−46
- src/Morley/Client/Action/Origination.hs +18/−18
- src/Morley/Client/Action/Origination/Large.hs +1/−1
- src/Morley/Client/Action/Reveal.hs +64/−11
- src/Morley/Client/Action/Transaction.hs +34/−7
- src/Morley/Client/App.hs +14/−1
- src/Morley/Client/Full.hs +8/−7
- src/Morley/Client/OnlyRPC.hs +10/−9
- src/Morley/Client/Parser.hs +76/−0
- src/Morley/Client/RPC/API.hs +19/−16
- src/Morley/Client/RPC/Class.hs +9/−0
- src/Morley/Client/RPC/Getters.hs +31/−0
- src/Morley/Client/RPC/Types.hs +47/−3
- src/Morley/Client/TezosClient.hs +2/−0
- src/Morley/Client/TezosClient/Class.hs +11/−6
- src/Morley/Client/TezosClient/Impl.hs +85/−46
- src/Morley/Client/TezosClient/Types.hs +0/−2
- src/Morley/Client/Types.hs +33/−1
- test/Test/BigMapGet.hs +6/−6
- test/Test/Fees.hs +8/−6
- test/Test/KeyRevealing.hs +10/−13
- test/Test/Origination.hs +8/−7
- test/Test/ParameterTypeGet.hs +2/−4
- test/Test/Resolve.hs +117/−0
- test/Test/Transaction.hs +9/−8
- test/Test/Util.hs +96/−95
- test/TestM.hs +34/−16
- test/data/constants.json +34/−32
CHANGES.md view
@@ -1,5 +1,48 @@ <!-- Unreleased: append new entries here --> ++0.3.1+=====+* [!1331](https://gitlab.com/morley-framework/morley/-/merge_requests/1331)+ Support implicit account tickets+ + New `transfer-ticket` CLI command;+ + New operation type, `OpTransferTicket`;+ + Add `ToTAddress` instance for `AddressWithAlias`;+* [!1330](https://gitlab.com/morley-framework/morley/-/merge_requests/1330)+ Support ticket balance queries+* [!1328](https://gitlab.com/morley-framework/morley/-/merge_requests/1328)+ Kill support for TORUs, minimal sr1 address support, tz4 address support+* [!1329](https://gitlab.com/morley-framework/morley/-/merge_requests/1329)+ Fix gas limit computation+ + Fixes a bug where in some cases batched transfer could exceed hard gas+ limit.+* [!1313](https://gitlab.com/morley-framework/morley/-/merge_requests/1313)+ Add `contractStateResolver` getter to build Morley interpreter's+ `ContractState` from chain.+* [!1315](https://gitlab.com/morley-framework/morley/-/merge_requests/1315)+ Avoid redundant calls to octez-client address store+ + Introduce `AddressWithAlias` and ways to resolve it (i.e.+ `resolveAddressWithAlias`/`-Either`/`-Maybe`)+ + Make RPC revelation and delegation more efficient, deprecate less efficient+ `revealKeyOp` and `revealKeyUnlessRevealedOp`+ + Use `AddressWithAlias` in critical code paths and key generators+ + Add batched delegation+* [!1304](https://gitlab.com/morley-framework/morley/-/merge_requests/1304)+ Relax lOriginateLargeContract constraints+ + Now requires `NiceParameter` like other origination functions instead of+ `NiceParameterFull`+* [!1286](https://gitlab.com/morley-framework/morley/-/merge_requests/1286)+ Use RPC revealing in `runOperationsNonEmptyHelper`+ + Replace `revealKey` with `getPublicKey` in `HasTezosClient`.+ + Move `Morley.Client.Action.Common.revealKeyUnlessRevealed` to+ `TezosClient.Impl`.+ + Implement key revealing in `runOperationsNonEmptyHelper` via prepending the+ reveal operation to the batch.+ + Rename `Morley.Client.Action.Reveal.revealKey*` to `*Op`, since those inject+ raw revelation **op**erations.+ + Introduce utility versions of `Morley.Client.Action.Reveal.revealKey*` that+ get the key using `getPublicKey`.+ 0.3.0 ===== * [!1281](https://gitlab.com/morley-framework/morley/-/merge_requests/1281)
LICENSE view
@@ -1,5 +1,5 @@ MIT License-Copyright (c) 2021-2022 Oxhead Alpha+Copyright (c) 2021-2023 Oxhead Alpha Copyright (c) 2019-2021 Tocqueville Group Permission is hereby granted, free of charge, to any person obtaining a copy
README.md view
@@ -1,3 +1,7 @@+> :warning: **Note: this project is being deprecated.**+>+> It will no longer be maintained after the activation of protocol "N" on the Tezos mainnet.+ # Morley-client This package implements a client to interact with the Tezos blockchain.
app/Main.hs view
@@ -8,7 +8,9 @@ import Control.Exception.Safe (throwString) import Data.Aeson qualified as Aeson import Data.Default (def)-import Fmt (blockListF, pretty)+import Data.Singletons (demote, fromSing)+import Data.Type.Equality (pattern Refl)+import Fmt (blockListF, build, nameF, pretty, (+|), (|+)) import GHC.IO.Encoding (setFileSystemEncoding) import Options.Applicative qualified as Opt import System.IO (utf8)@@ -17,14 +19,16 @@ import Morley.Client.Parser import Morley.Client.RPC import Morley.Client.Util (extractAddressesFromValue)+import Morley.Micheline (fromExpression, toExpression, unStringEncode) import Morley.Michelson.Runtime (prepareContract)-import Morley.Michelson.TypeCheck- (typeCheckContract, typeCheckContractAndStorage, typeCheckingWith, typeVerifyParameter)+import Morley.Michelson.TypeCheck qualified as TC import Morley.Michelson.Typed (Contract, Contract'(..), SomeContract(..))+import Morley.Michelson.Typed qualified as T import Morley.Michelson.Typed.Value (Value'(..)) import Morley.Michelson.Untyped qualified as U import Morley.Tezos.Address import Morley.Tezos.Core (prettyTez)+import Morley.Util.Constrained import Morley.Util.Exception (throwLeft) import Morley.Util.Main (wrapMain) @@ -34,8 +38,9 @@ Originate OriginateArgs{..} -> do contract <- liftIO $ prepareContract oaMbContractFile let originator = oaOriginateFrom+ originatorAA <- resolveAddressWithAlias originator (operationHash, contractAddr) <-- originateUntypedContract OverwriteDuplicateAlias oaContractName originator oaInitialBalance+ originateUntypedContract OverwriteDuplicateAlias oaContractName originatorAA oaInitialBalance contract oaInitialStorage oaMbFee oaDelegate putTextLn "Contract was successfully deployed."@@ -43,32 +48,64 @@ putTextLn $ "Contract address: " <> formatAddress contractAddr Transfer TransferArgs{..} -> do- sendAddress <- resolveAddress taSender+ sendAddress <- resolveAddressWithAlias taSender destAddress <- resolveAddress taDestination- (operationHash :: OperationHash, contractEvents :: [IntOpEvent]) <- case destAddress of- Constrained destContract@ContractAddress{} -> do- contract <- getContract destContract- SomeContract fullContract <-- throwLeft $ pure $ typeCheckingWith def $ typeCheckContract contract- case fullContract of- (Contract{} :: Contract cp st) -> do- let addrs = extractAddressesFromValue taParameter & mapMaybe \case- MkAddress x@ContractAddress{} -> Just x- _ -> Nothing- tcOriginatedContracts <- getContractsParameterTypes addrs- parameter <- throwLeft $ pure $ typeCheckingWith def $- typeVerifyParameter @cp tcOriginatedContracts taParameter- transfer sendAddress destContract taAmount U.DefEpName parameter taMbFee- Constrained destImplicit@ImplicitAddress {} -> case taParameter of- U.ValueUnit -> transfer sendAddress destImplicit taAmount U.DefEpName VUnit Nothing- _ -> throwString ("The transaction parameter must be 'Unit' "- <> "when transferring to an implicit account")+ (operationHash, contractEvents) :: (OperationHash, [IntOpEvent]) <-+ withConstrained destAddress \case+ destContract@ContractAddress{} -> do+ contract <- getContract destContract+ SomeContract (Contract{} :: Contract cp st) <-+ throwLeft $ pure $ TC.typeCheckingWith def $ TC.typeCheckContract contract+ let addrs = extractAddressesFromValue taParameter & mapMaybe \case+ MkAddress x@ContractAddress{} -> Just x+ _ -> Nothing+ tcOriginatedContracts <- getContractsParameterTypes addrs+ parameter <- throwLeft $ pure $ TC.typeCheckingWith def $+ TC.typeVerifyParameter @cp tcOriginatedContracts taParameter+ transfer sendAddress destContract taAmount U.DefEpName parameter taMbFee+ destImplicit@ImplicitAddress {} -> case taParameter of+ U.ValueUnit -> transfer sendAddress destImplicit taAmount U.DefEpName VUnit Nothing+ _ -> throwString ("The transaction parameter must be 'Unit' "+ <> "when transferring to an implicit account") putTextLn $ "Transaction was successfully sent.\nOperation hash " <> pretty operationHash <> "." unless (null contractEvents) do putTextLn $ "Additionally, the following contract events were emitted:" putTextLn $ pretty $ blockListF contractEvents + TransferTicket TransferTicketArgs{..} -> T.withUType ttaTicketType \(_ :: T.Notes t) -> do+ T.Dict <- throwLeft $ pure $ first (TC.UnsupportedTypeForScope (demote @t))+ $ T.checkScope @(T.ParameterScope t, T.Comparable t)+ sendAddress <- resolveAddressWithAlias ttaSender+ destAddress <- resolveAddress ttaDestination+ ticketer <- resolveAddress ttaTicketTicketer+ (operationHash, contractEvents) :: (OperationHash, [IntOpEvent]) <-+ withConstrained destAddress \case+ destContract@ContractAddress{} -> do+ contract <- getContract destContract+ SomeContract (Contract{} :: Contract cp st) <-+ throwLeft $ pure $ TC.typeCheckingWith def $ TC.typeCheckContract contract+ Constrained (_ :: T.SingT t') :: Constrained T.SingI T.SingT <- case T.sing @cp of+ T.STTicket x -> pure $ Constrained @T.SingI x+ x -> throwM $ TC.TcContractError @U.ExpandedOp+ ("Expected contract to accept tickets, but it had type " <> pretty (fromSing x))+ $ Just $ TC.UnexpectedType (one $ one $ "ticket 'a")+ Refl <- T.requireEq @t @t' $ throwM . TC.TypeEqError+ parameter <- throwLeft $ pure $ TC.typeCheckingWith def $ do+ TC.typeCheckValue @t' ttaTicketContents+ transferTicket @_ @t' sendAddress destContract ticketer parameter ttaTicketAmount+ U.DefEpName ttaMbFee+ destImplicit@ImplicitAddress{} -> do+ parameter <- throwLeft $ pure $ TC.typeCheckingWith def $+ TC.typeCheckValue @t ttaTicketContents+ transferTicket sendAddress destImplicit ticketer parameter ttaTicketAmount+ U.DefEpName ttaMbFee++ putTextLn $ "Tickets successfully sent.\nOperation hash " <> pretty operationHash <> "."+ unless (null contractEvents) do+ putTextLn $ "Additionally, the following contract events were emitted:"+ putTextLn $ pretty $ blockListF contractEvents+ GetBalance addrOrAlias -> do balance <- getBalance =<< resolveAddress addrOrAlias putTextLn $ prettyTez balance@@ -79,8 +116,8 @@ GetScriptSize GetScriptSizeArgs{..} -> do contract <- liftIO $ prepareContract (Just ssScriptFile)- void . throwLeft . pure . typeCheckingWith def $- typeCheckContractAndStorage contract ssStorage+ void . throwLeft . pure . TC.typeCheckingWith def $+ TC.typeCheckContractAndStorage contract ssStorage size <- computeUntypedContractSize contract ssStorage print size @@ -95,6 +132,25 @@ OtherOpResp -> putTextLn "Non-transaction operation" putTextLn "" putTextLn "——————————————————————————————————————————————————\n"+ TicketBalance owner' TicketBalanceArgs{..} -> do+ owner <- resolveAddress owner'+ bal <- getTicketBalance owner GetTicketBalance+ { gtbContent = toExpression tbaContent+ , gtbContentType = toExpression tbaContentType+ , gtbTicketer = tbaTicketer+ }+ print bal+ AllTicketBalances owner' -> do+ owner <- resolveAddress owner'+ bals <- getAllTicketBalances owner+ forM_ bals \GetAllTicketBalancesResponse{..} -> do+ content <- either throwM pure $ fromExpression @U.Value gatbrContent+ ty <- either throwM pure $ fromExpression @U.Ty gatbrContentType+ putTextLn $ pretty @Text $+ nameF "Ticketer" (build gatbrTicketer) |+ ", "+ +| nameF "content" (build content) |+ ", "+ +| nameF "type" (build ty) |+ ", "+ +| nameF "amount" (build $ unStringEncode gatbrAmount) main :: IO () main = wrapMain $ do
morley-client.cabal view
@@ -5,7 +5,7 @@ -- see: https://github.com/sol/hpack name: morley-client-version: 0.3.0+version: 0.3.1 synopsis: Client to interact with the Tezos blockchain description: A client to interact with the Tezos blockchain, by use of the octez-node RPC and/or of the octez-client binary. category: Blockchain@@ -13,7 +13,7 @@ bug-reports: https://gitlab.com/morley-framework/morley/-/issues author: Serokell, Tocqueville Group maintainer: Serokell <hi@serokell.io>-copyright: 2019-2021 Tocqueville Group, 2021-2022 Oxhead Alpha+copyright: 2019-2021 Tocqueville Group, 2021-2023 Oxhead Alpha license: MIT license-file: LICENSE build-type: Simple@@ -228,6 +228,7 @@ , morley-prelude , optparse-applicative , safe-exceptions+ , singletons default-language: Haskell2010 test-suite morley-client-test@@ -245,6 +246,7 @@ Test.ParameterTypeGet Test.Parser Test.ReadBigMapValue+ Test.Resolve Test.Transaction Test.Util TestM@@ -313,7 +315,6 @@ , bytestring , co-log , co-log-core- , containers , exceptions , fmt , hex-text
src/Morley/Client.hs view
@@ -51,6 +51,10 @@ , getDelegate , runCode , getManagerKey+ , getTicketBalance+ , getAllTicketBalances+ , GetTicketBalance (..)+ , GetAllTicketBalancesResponse (..) -- ** Errors , ClientRpcError (..)@@ -74,11 +78,16 @@ , getAliasMaybe , resolveAddress , resolveAddressMaybe+ , resolveAddressWithAlias+ , resolveAddressWithAliasMaybe , TezosClientError (..) , AliasBehavior (..) -- * Util , disableAlphanetWarning+ , AddressWithAlias(..)+ , ImplicitAddressWithAlias+ , ContractAddressWithAlias -- * Reexports , Opt.ParserInfo -- Needed for tests
src/Morley/Client/Action.hs view
@@ -10,13 +10,14 @@ , module Morley.Client.Action.Origination , module Morley.Client.Action.Transaction , module Morley.Client.Action.SizeCalculation+ , module Morley.Client.Action.Reveal , ClientInput- , revealKeyUnlessRevealed ) where -import Morley.Client.Action.Common (ClientInput, revealKeyUnlessRevealed)+import Morley.Client.Action.Common (ClientInput) import Morley.Client.Action.Delegation import Morley.Client.Action.Operation import Morley.Client.Action.Origination+import Morley.Client.Action.Reveal import Morley.Client.Action.SizeCalculation import Morley.Client.Action.Transaction
src/Morley/Client/Action/Batched.hs view
@@ -7,6 +7,7 @@ , originateContractM , runTransactionM , revealKeyM+ , delegateM , runOperationsBatch ) where @@ -21,7 +22,6 @@ import Morley.Client.TezosClient import Morley.Client.Types import Morley.Tezos.Address-import Morley.Tezos.Address.Alias import Morley.Util.Batching {- | Where the batched operations occur.@@ -79,13 +79,17 @@ revealKeyM :: RevealData -> OperationsBatch () revealKeyM = runOperationM OpReveal _OpReveal +-- | Perform delegation within a batch.+delegateM :: DelegationData -> OperationsBatch ()+delegateM = runOperationM OpDelegation _OpDelegation+ -- | Execute a batch. runOperationsBatch :: ( HasTezosRpc m , HasTezosClient m , WithClientLog env m )- => ImplicitAddressOrAlias+ => ImplicitAddressWithAlias -> OperationsBatch a -> m (Maybe OperationHash, a) runOperationsBatch sender (OperationsBatch batch) =
src/Morley/Client/Action/Common.hs view
@@ -8,11 +8,13 @@ , TD (..) , TransactionData(..) , OriginationData(..)+ , TransferTicketData(..) , RevealData(..) , DelegationData(..) , ClientInput , addOperationPrefix , buildTxDataWithAlias+ , buildTxTicketDataWithAlias , getAppliedResults , computeFee , computeStorageLimit@@ -23,18 +25,15 @@ , updateCommonData , toParametersInternals , mkOriginationScript- , revealKeyUnlessRevealed , handleOperationResult , runErrorsToClientError ) where import Control.Lens (Prism')-import Data.ByteArray (ScrubbedBytes) import Data.ByteString (cons) import Data.Default (def) import Fmt (Buildable(..), Builder, (+|), (|+)) -import Morley.Client.Logging (WithClientLog, logDebug) import Morley.Client.RPC.Class import Morley.Client.RPC.Error import Morley.Client.RPC.Getters@@ -92,6 +91,19 @@ buildMbAlias :: Maybe Text -> Builder buildMbAlias = maybe "" $ \a -> " (" +| a |+ ")" +-- | Builds 'TransactionData' with additional info about receiver's alias, if present.+buildTxTicketDataWithAlias :: Maybe Text -> TransferTicketData -> Builder+buildTxTicketDataWithAlias mbAlias+ (TransferTicketData contents ticketer amount dest ep _mbFee) =+ "To: " +| dest |+ buildMbAlias mbAlias |+ ". EP: " +| ep+ |+ ". Ticketer: " +| ticketer+ |+ " contents: " +| contents+ |+ " amount: " +| amount+ |+ ""+ where+ buildMbAlias :: Maybe Text -> Builder+ buildMbAlias = maybe "" $ \a -> " (" +| a |+ ")"+ -- | Data for a single origination in a batch data OriginationData = forall cp st. (ParameterScope cp, StorageScope st) => OriginationData@@ -116,10 +128,20 @@ , rdMbFee :: Maybe Mutez } +data TransferTicketData = forall t. (ParameterScope t, Comparable t) => TransferTicketData+ { ttdTicketContents :: T.Value t+ , ttdTicketTicketer :: Address+ , ttdTicketAmount :: Natural+ , ttdDestination :: Address+ , ttdEntrypoint :: EpName+ , ttdMbFee :: Maybe Mutez+ }+ -- | Standard operation input in morley-client interface. data ClientInput instance OperationInfoDescriptor ClientInput where type TransferInfo ClientInput = TransactionData+ type TransferTicketInfo ClientInput = TransferTicketData type OriginationInfo ClientInput = OriginationData type RevealInfo ClientInput = RevealData type DelegationInfo ClientInput = DelegationData@@ -253,21 +275,6 @@ findError :: Prism' RunError a -> Maybe a findError prism = fmap head . nonEmpty . mapMaybe (preview prism) $ errs --- | Reveal key for implicit address if necessary.------ Throws an error if given address is a contract address.-revealKeyUnlessRevealed- :: (WithClientLog env m, HasTezosRpc m, HasTezosClient m)- => ImplicitAddress- -> Maybe ScrubbedBytes- -> m ()-revealKeyUnlessRevealed addr mbPassword = do- alias <- getAlias $ AddressResolved addr- mbManagerKey <- getManagerKey addr- case mbManagerKey of- Nothing -> revealKey alias mbPassword- Just _ -> logDebug $ alias |+ " alias has already revealed key"- -- | Compute fee for operation. computeFee :: FeeConstants -> Int -> TezosInt64 -> Mutez computeFee FeeConstants{..} opSize gasLimit =@@ -342,4 +349,11 @@ prepareOpForInjection :: ByteString -> Signature -> ByteString prepareOpForInjection operationHex signature' =- operationHex <> signatureToBytes signature'+ operationHex <> prefix <> signatureToBytes signature'+ where+ prefix+ -- Apparently, because BLS signature is longer than other ones, this hacky+ -- workaround is employed. This may or may not come up elsewhere.+ -- see https://gitlab.com/tezos/tezos/-/merge_requests/5444+ | SignatureBLS{} <- signature' = "\xff\x03"+ | otherwise = mempty
src/Morley/Client/Action/Delegation.hs view
@@ -16,7 +16,6 @@ import Morley.Client.TezosClient.Class import Morley.Client.Types import Morley.Tezos.Address-import Morley.Tezos.Address.Alias import Morley.Tezos.Crypto -- | Set or revoke a delegate for the sender.@@ -47,7 +46,7 @@ , HasTezosClient m , MonadReader env m , HasLog env Message m)- => ImplicitAddressOrAlias+ => ImplicitAddressWithAlias -> Maybe KeyHash -> m OperationHash setDelegateOp sender delegate =@@ -60,6 +59,8 @@ , HasTezosClient m , MonadReader env m , HasLog env Message m)- => KeyHash+ => ImplicitAddressWithAlias -> m OperationHash-registerDelegateOp sender = setDelegateOp (AddressResolved . ImplicitAddress $ sender) (Just sender)+registerDelegateOp sender = do+ let senderKh = unImplicitAddress $ awaAddress sender+ setDelegateOp sender (Just senderKh)
src/Morley/Client/Action/Operation.hs view
@@ -13,8 +13,9 @@ import Control.Lens (has, (%=), (&~)) import Data.List (zipWith4) import Data.List.NonEmpty qualified as NE+import Data.Map qualified as Map import Data.Ratio ((%))-import Data.Singletons (Sing, SingI, sing)+import Data.Singletons (Sing, SingI, demote, sing) import Data.Text qualified as T import Fmt (blockListF, blockListF', listF, nameF, pretty, (+|), (|+)) @@ -26,7 +27,9 @@ import Morley.Client.RPC.Types import Morley.Client.TezosClient import Morley.Client.Types-import Morley.Micheline (StringEncode(..), TezosInt64, TezosMutez(..))+import Morley.Client.Util (epNameToTezosEp)+import Morley.Micheline (StringEncode(..), TezosInt64, TezosMutez(..), toExpression)+import Morley.Michelson.Typed (Value) import Morley.Tezos.Address import Morley.Tezos.Address.Alias import Morley.Tezos.Core@@ -39,33 +42,32 @@ data Result instance OperationInfoDescriptor Result where type TransferInfo Result = [IntOpEvent]+ type TransferTicketInfo Result = [IntOpEvent] type OriginationInfo Result = ContractAddress type RevealInfo Result = () type DelegationInfo Result = () logOperations- :: forall (runMode :: RunMode) env m kind.+ :: forall env m kind. ( WithClientLog env m , HasTezosClient m- , MonadThrow m- , SingI runMode -- We don't ask aliases with @octez-client@ in 'DryRun' mode- , L1AddressKind kind )- => AddressOrAlias kind+ => AddressWithAlias kind -> NonEmpty (OperationInfo ClientInput) -> m () logOperations sender ops = do- let runMode = sing @runMode-- opName =+ let opName = if | all (has _OpTransfer) ops -> "transactions" | all (has _OpOriginate) ops -> "originations" | all (has _OpReveal) ops -> "reveals"+ | all (has _OpTransferTicket) ops -> "ticket transfers" | otherwise -> "operations" buildOp = \case (OpTransfer tx, mbAlias) -> buildTxDataWithAlias mbAlias tx+ (OpTransferTicket tx, mbAlias) ->+ buildTxTicketDataWithAlias mbAlias tx (OpOriginate orig, _) -> odName orig |+ " (temporary alias)" (OpReveal rv, mbAlias) ->@@ -73,28 +75,29 @@ (OpDelegation delegate, mbAlias) -> "Key Hash " +| ddDelegate delegate |+ maybe "" (\a -> " (" +| a |+ ")") mbAlias - sender' <- case sender of- addr@AddressResolved{} -> case runMode of- SRealRun -> AddressAlias <$> getAlias sender- SDryRun -> pure addr- alias -> pure alias+ let needsAliasStore = (`any` ops) \case+ OpTransfer{} -> True+ OpTransferTicket{} -> True+ OpOriginate{} -> False+ OpReveal{} -> True+ OpDelegation{} -> True - aliases <- case runMode of- SRealRun ->- forM ops $ \case- OpTransfer (TransactionData tx) -> withConstrained (tdReceiver tx) $- fmap (Just . pretty) . getAlias . AddressResolved- OpOriginate _ ->- pure Nothing- OpReveal r ->- Just . pretty <$> (getAlias . AddressResolved . mkKeyAddress $ rdPublicKey r)- OpDelegation d ->- maybe (pure Nothing)- (fmap (Just . pretty) . getAlias . AddressResolved . ImplicitAddress) $ ddDelegate d- SDryRun -> pure $ ops $> Nothing+ anas <- if needsAliasStore+ then Map.fromList . fmap swap <$> getAliasesAndAddresses+ else pure mempty + let mbAlias :: KindedAddress k -> Maybe Text+ mbAlias addr = Map.lookup (pretty addr) anas++ let aliases = ops <&> \case+ OpTransfer (TransactionData tx) -> withConstrained (tdReceiver tx) mbAlias+ OpTransferTicket TransferTicketData{..} -> withConstrained ttdDestination mbAlias+ OpOriginate _ -> Nothing+ OpReveal r -> mbAlias . mkKeyAddress $ rdPublicKey r+ OpDelegation d -> mbAlias . ImplicitAddress =<< ddDelegate d+ logInfo $ T.strip $ -- strip trailing newline- "Running " +| opName +| " by " +| sender' |+ ":\n" +|+ "Running " +| opName +| " by " +| sender |+ ":\n" +| blockListF' "-" buildOp (ops `NE.zip` aliases) -- | Perform sequence of operations.@@ -107,7 +110,7 @@ , HasTezosClient m , WithClientLog env m )- => ImplicitAddressOrAlias+ => ImplicitAddressWithAlias -> [OperationInfo ClientInput] -> m (Maybe OperationHash, [OperationInfo Result]) runOperations sender operations = case operations of@@ -130,7 +133,7 @@ , HasTezosClient m , WithClientLog env m )- => ImplicitAddressOrAlias+ => ImplicitAddressWithAlias -> NonEmpty (OperationInfo ClientInput) -> m (OperationHash, NonEmpty (OperationInfo Result)) runOperationsNonEmpty sender operations =@@ -172,7 +175,7 @@ , HasTezosClient m , WithClientLog env m )- => ImplicitAddressOrAlias+ => ImplicitAddressWithAlias -> NonEmpty (OperationInfo ClientInput) -> m (NonEmpty (AppliedResult, TezosMutez)) dryRunOperationsNonEmpty sender operations =@@ -189,11 +192,16 @@ , SingI runMode ) => Natural- -> ImplicitAddressOrAlias+ -> ImplicitAddressWithAlias -> NonEmpty (OperationInfo ClientInput) -> m (RunResult runMode)-runOperationsNonEmptyHelper retryCount sender operations = do- logOperations @runMode sender operations+runOperationsNonEmptyHelper retryCount sender@(AddressWithAlias senderAddress _) operations' = do+ operations <- fromMaybe operations' <$> runMaybeT do+ guard $ isRealRun @runMode && mayNeedSenderRevealing (toList operations')+ Nothing <- lift $ getManagerKey senderAddress+ pk <- lift $ getPublicKey sender+ pure $ OpReveal (RevealData pk Nothing) :| toList operations'+ logOperations sender operations -- If we intend to fail on duplicate aliases, we want to fail now, rather than -- after contract origination. forM_ operations $ \case@@ -201,11 +209,7 @@ resolved <- resolveAddressMaybe (AddressAlias odName) whenJust resolved $ const $ throwM $ DuplicateAlias (unAlias odName) _ -> pass- senderAddress <- resolveAddress sender- mbPassword <- getKeyPassword senderAddress- when (isRealRun @runMode && mayNeedSenderRevealing (toList operations)) $- revealKeyUnlessRevealed senderAddress mbPassword-+ mbPassword <- getKeyPassword sender pp <- getProtocolParameters OperationConstants{..} <- preProcessOperation senderAddress @@ -216,6 +220,16 @@ , toAmount = TezosMutez tdAmount , toParameters = toParametersInternals tdEpName tdParam }+ OpTransferTicket (TransferTicketData {..})+ | _ :: Value t <- ttdTicketContents ->+ OpTransferTicket TransferTicketOperation+ { ttoTicketContents = toExpression ttdTicketContents+ , ttoTicketTy = toExpression (demote @t)+ , ttoTicketTicketer = ttdTicketTicketer+ , ttoTicketAmount = StringEncode ttdTicketAmount+ , ttoDestination = ttdDestination+ , ttoEntrypoint = epNameToTezosEp ttdEntrypoint+ } OpOriginate OriginationData{..} -> OpOriginate OriginationOperation { ooBalance = TezosMutez odBalance@@ -239,6 +253,7 @@ let opsToRun = NE.zipWith convertOps (1 :| [(2 :: TezosInt64)..]) operations mbFees = operations <&> \case OpTransfer (TransactionData TD {..}) -> tdMbFee+ OpTransferTicket TransferTicketData{..} -> ttdMbFee OpOriginate OriginationData{..} -> odMbFee OpReveal RevealData{..} -> rdMbFee OpDelegation DelegationData {..} -> ddMbFee@@ -277,11 +292,12 @@ -- @gasSafetyGuard@ is added to origination operations and transfers to non-implicit -- accounts, see https://gitlab.com/tezos/tezos/-/blob/v13.0/src/proto_013_PtJakart/lib_client/injection.ml#L750 additionalGas = case internalOp of+ OpTransferTicket{} -> gasSafetyGuard OpOriginate _ -> gasSafetyGuard OpTransfer (TransactionOperation {..}) -> case toDestination of MkAddress ImplicitAddress{} -> 0 MkAddress ContractAddress{} -> gasSafetyGuard- MkAddress TxRollupAddress{} -> gasSafetyGuard+ MkAddress SmartRollupAddress{} -> gasSafetyGuard OpReveal _ -> 0 OpDelegation _ -> 0 let storageLimit = computeStorageLimit [ar] pp + 20@@ -356,13 +372,18 @@ operationHash <- waitForOperation $ injectOperation (HexJSONByteString signedOp) let contractAddrs = arOriginatedContracts <$> ars2 opsRes <- forM (NE.zip operations contractAddrs) $ \case- (OpTransfer _, []) ->- return $ OpTransfer $ mapMaybe iopsDataToEmitOp iopsData (OpTransfer _, addrs) -> do- logInfo . T.strip $- "The following contracts were originated during transactions: " +|- listF addrs |+ ""+ unless (null addrs) $+ logInfo . T.strip $+ "The following contracts were originated during transactions: " +|+ listF addrs |+ "" return $ OpTransfer $ mapMaybe iopsDataToEmitOp iopsData+ (OpTransferTicket _, addrs) -> do+ unless (null addrs) $+ logInfo . T.strip $+ "The following contracts were originated during transactions: " +|+ listF addrs |+ ""+ return $ OpTransferTicket $ mapMaybe iopsDataToEmitOp iopsData (OpOriginate _, []) -> throwM RpcOriginatedNoContracts (OpOriginate OriginationData{..}, [addr]) -> do@@ -393,6 +414,7 @@ mayNeedSenderRevealing :: [OperationInfo i] -> Bool mayNeedSenderRevealing = any \case OpTransfer{} -> True+ OpTransferTicket{} -> True OpOriginate{} -> True OpReveal{} -> False OpDelegation{} -> True
src/Morley/Client/Action/Origination.hs view
@@ -54,15 +54,16 @@ , HasTezosClient m , WithClientLog env m )- => ImplicitAddressOrAlias+ => ImplicitAddressWithAlias -> [OriginationData] -> m (Maybe OperationHash, [ContractAddress]) originateContracts sender originations = do (opHash, res) <- runOperations sender (OpOriginate <$> originations)- return (opHash, fromOrigination <$> res)+ return (opHash, getOriginations res) where- fromOrigination = \case- OpOriginate r -> r+ getOriginations = mapMaybe \case+ OpOriginate r -> Just r+ OpReveal{} -> Nothing _ -> error "Unexpectedly not origination" -- | Originate single contract@@ -76,7 +77,7 @@ ) => AliasBehavior -> ContractAlias- -> ImplicitAddressOrAlias+ -> ImplicitAddressWithAlias -> Mutez -> Contract cp st -> Value st@@ -96,7 +97,7 @@ ) => AliasBehavior -> ContractAlias- -> ImplicitAddressOrAlias+ -> ImplicitAddressWithAlias -> Mutez -> U.Contract -> U.Value@@ -116,7 +117,7 @@ , HasTezosClient m , WithClientLog env m )- => ImplicitAddressOrAlias+ => ImplicitAddressWithAlias -> [LOriginationData] -> m (Maybe OperationHash, [ContractAddress]) lOriginateContracts sender' originations =@@ -133,7 +134,7 @@ ) => AliasBehavior -> ContractAlias- -> ImplicitAddressOrAlias+ -> ImplicitAddressWithAlias -> Mutez -> L.Contract cp st vd -> st@@ -156,11 +157,10 @@ , HasTezosClient m , WithClientLog env m )- => ImplicitAddressOrAlias+ => ImplicitAddressWithAlias -> [OriginationData] -> m (Maybe OperationHash, [ContractAddress])-originateLargeContracts sender' largeOriginations = do- senderAddress <- resolveAddress sender'+originateLargeContracts sender'@(AddressWithAlias senderAddress _) largeOriginations = do -- calculate large contract originators let originators = map mkLargeOriginationData largeOriginations -- originate them. Note: we use the operation hash from here even tho the@@ -172,7 +172,7 @@ -- Note: it is not possible to run these all at once, because the node won't -- accept a transaction batch where the sum of the storage cost is over 16k, -- so here we need to run them one by one.- mapM_ (runTransactions senderAddress . (: [])) . concat $+ mapM_ (runTransactions sender' . (: [])) . concat $ zipWith mkLargeOriginatorTransactions originatorsAddr originators -- get the addresses of the originated large contracts back from the originators -- and remember their addresses with their aliases@@ -190,7 +190,7 @@ ) => AliasBehavior -> ContractAlias- -> ImplicitAddressOrAlias+ -> ImplicitAddressWithAlias -> Mutez -> Contract cp st -> Value st@@ -210,7 +210,7 @@ ) => AliasBehavior -> ContractAlias- -> ImplicitAddressOrAlias+ -> ImplicitAddressWithAlias -> Mutez -> U.Contract -> U.Value@@ -230,7 +230,7 @@ , HasTezosClient m , WithClientLog env m )- => ImplicitAddressOrAlias+ => ImplicitAddressWithAlias -> [LOriginationData] -> m (Maybe OperationHash, [ContractAddress]) lOriginateLargeContracts sender' originations =@@ -243,11 +243,11 @@ , HasTezosClient m , WithClientLog env m , NiceStorage st- , NiceParameterFull cp+ , NiceParameter cp ) => AliasBehavior -> ContractAlias- -> ImplicitAddressOrAlias+ -> ImplicitAddressWithAlias -> Mutez -> L.Contract cp st vd -> st@@ -263,7 +263,7 @@ -------------------------------------------------------------------------------- -- | Lorentz version of 'OriginationData'-data LOriginationData = forall cp st vd. (NiceParameterFull cp, NiceStorage st)+data LOriginationData = forall cp st vd. (NiceParameter cp, NiceStorage st) => LOriginationData { lodAliasBehavior :: AliasBehavior , lodName :: ContractAlias
src/Morley/Client/Action/Origination/Large.hs view
@@ -38,7 +38,7 @@ import Data.ByteString.Lazy qualified as LBS -import Lorentz+import Lorentz hiding (bytes) import Morley.Client.Action.Common import Morley.Client.RPC.Class import Morley.Client.RPC.Error
src/Morley/Client/Action/Reveal.hs view
@@ -5,32 +5,66 @@ module Morley.Client.Action.Reveal ( RevealData (..) , revealKey+ , revealKeyWithFee , revealKeyUnlessRevealed+ , revealKeyUnlessRevealedWithFee+ , revealKeyOp+ , revealKeyUnlessRevealedOp ) where import Fmt ((|+)) -import Morley.Client.Action.Common hiding (revealKeyUnlessRevealed)+import Morley.Client.Action.Common import Morley.Client.Action.Operation import Morley.Client.Logging import Morley.Client.RPC.Class import Morley.Client.RPC.Error import Morley.Client.RPC.Getters import Morley.Client.RPC.Types-import Morley.Client.TezosClient (HasTezosClient)+import Morley.Client.TezosClient.Class (HasTezosClient(getPublicKey))+import Morley.Client.TezosClient.Impl (getAlias) import Morley.Client.Types-import Morley.Tezos.Address (mkKeyAddress)+import Morley.Tezos.Address import Morley.Tezos.Address.Alias (AddressOrAlias(..)) import Morley.Tezos.Core (Mutez) import Morley.Tezos.Crypto (PublicKey) +-- | Resolve the public key of an implicit address and reveal it.+revealKey+ :: (HasTezosRpc m, HasTezosClient m, WithClientLog env m)+ => ImplicitAddressWithAlias -> m OperationHash+revealKey = (`revealKeyWithFee` Nothing)++-- | Version of 'revealKey' with explicit fee.+revealKeyWithFee+ :: (HasTezosRpc m, HasTezosClient m, WithClientLog env m)+ => ImplicitAddressWithAlias -> Maybe Mutez -> m OperationHash+revealKeyWithFee sender mbFee = do+ pk <- getPublicKey sender+ runRevealOperationRaw sender pk mbFee++-- | Resolve the public key of an implicit address and reveal it, unless already+-- revealed.+revealKeyUnlessRevealed+ :: (HasTezosRpc m, HasTezosClient m, WithClientLog env m)+ => ImplicitAddressWithAlias -> m ()+revealKeyUnlessRevealed = (`revealKeyUnlessRevealedWithFee` Nothing)++-- | Version of 'revealKeyUnlessRevealed' with explicit fee.+revealKeyUnlessRevealedWithFee+ :: (HasTezosRpc m, HasTezosClient m, WithClientLog env m)+ => ImplicitAddressWithAlias -> Maybe Mutez -> m ()+revealKeyUnlessRevealedWithFee sender mbFee = do+ pk <- getPublicKey sender+ handleAlreadyRevealed (flip (runRevealOperationRaw sender) mbFee) pk+ -- | Reveal given key. -- -- Note that sender is implicitly defined by the key being revealed, as you can -- only reveal your own key. -- -- This is a variation of key revealing method that tries to use solely RPC.-revealKey+revealKeyOp -- TODO [#873] remove HasTezosClient dependency :: forall m env. ( HasTezosRpc m@@ -40,16 +74,18 @@ => PublicKey -> Maybe Mutez -> m OperationHash-revealKey rdPublicKey rdMbFee =- fmap fst . runOperationsNonEmpty (AddressResolved sender) . one $ OpReveal RevealData{..}+revealKeyOp pk mbFee = do+ senderAlias <- getAlias $ AddressResolved senderAddress+ runRevealOperationRaw (AddressWithAlias senderAddress senderAlias) pk mbFee where- sender = mkKeyAddress rdPublicKey+ senderAddress = mkKeyAddress pk+{-# DEPRECATED revealKeyOp "Prefer using 'revealKeyWithFee', as it's a lot more efficient" #-} -- | Reveal given key. -- -- Note that sender is implicitly defined by the key being revealed, as you can -- only reveal your own key.-revealKeyUnlessRevealed+revealKeyUnlessRevealedOp -- TODO [#873] remove HasTezosClient dependency :: forall m env. ( HasTezosRpc m@@ -59,14 +95,31 @@ => PublicKey -> Maybe Mutez -> m ()-revealKeyUnlessRevealed key mbFee = do+revealKeyUnlessRevealedOp key mbFee = handleAlreadyRevealed (flip revealKeyOp mbFee) key+{-# DEPRECATED revealKeyUnlessRevealedOp+ "Prefer using 'revealKeyUnlessRevealedWithFee', as it's a lot more efficient" #-}++-- Internals++handleAlreadyRevealed+ :: (HasTezosRpc m, WithClientLog env m)+ => (PublicKey -> m a) -> PublicKey -> m ()+handleAlreadyRevealed doReveal key = do+ let sender = mkKeyAddress key -- An optimization for the average case, but we can't rely on it in -- distributed environment- let sender = mkKeyAddress key getManagerKey sender >>= \case Just _ -> logDebug $ sender |+ " address has already revealed key"- Nothing -> ignoreAlreadyRevealedError . void $ revealKey key mbFee+ Nothing -> ignoreAlreadyRevealedError . void $ doReveal key where ignoreAlreadyRevealedError = flip catch \case RunCodeErrors [PreviouslyRevealedKey _] -> pass e -> throwM e++-- | Note that sender and rdPublicKey must be consistent, otherwise network will+-- reject the operation+runRevealOperationRaw+ :: (HasTezosRpc m, HasTezosClient m, WithClientLog env m)+ => ImplicitAddressWithAlias -> PublicKey -> Maybe Mutez -> m OperationHash+runRevealOperationRaw sender rdPublicKey rdMbFee =+ fmap fst . runOperationsNonEmpty sender . one $ OpReveal RevealData{..}
src/Morley/Client/Action/Transaction.hs view
@@ -9,11 +9,13 @@ -- * Transfer , transfer , lTransfer+ , transferTicket -- Datatypes for batch transactions , TD (..) , LTransactionData (..) , TransactionData (..)+ , TransferTicketData (..) ) where import Lorentz.Constraints@@ -28,7 +30,6 @@ import Morley.Michelson.Typed.Scope import Morley.Michelson.Untyped.Entrypoints import Morley.Tezos.Address-import Morley.Tezos.Address.Alias (AddressOrAlias(..)) import Morley.Tezos.Core (Mutez) -- | Perform sequence of transactions to the contract. Returns operation hash@@ -39,7 +40,7 @@ , HasTezosClient m , WithClientLog env m )- => ImplicitAddress -> [TransactionData]+ => ImplicitAddressWithAlias -> [TransactionData] -> m (Maybe (OperationHash, [OperationInfo Result])) runTransactions sender transactions = runMaybeT do ts <- hoistMaybe $ nonEmpty transactions@@ -53,10 +54,10 @@ , HasTezosClient m , WithClientLog env m )- => ImplicitAddress -> NonEmpty TransactionData+ => ImplicitAddressWithAlias -> NonEmpty TransactionData -> m (OperationHash, NonEmpty (OperationInfo Result)) runTransactionsNonEmpty sender =- runOperationsNonEmpty (AddressResolved sender) . map OpTransfer+ runOperationsNonEmpty sender . map OpTransfer -- | Lorentz version of 'TransactionData'. data LTransactionData where@@ -71,7 +72,7 @@ , HasTezosClient m , WithClientLog env m )- => ImplicitAddress+ => ImplicitAddressWithAlias -> [LTransactionData] -> m (Maybe (OperationHash, [OperationInfo Result])) lRunTransactions sender transactions =@@ -89,7 +90,7 @@ , ParameterScope t , L1AddressKind kind )- => ImplicitAddress+ => ImplicitAddressWithAlias -> KindedAddress kind -> Mutez -> EpName@@ -103,6 +104,32 @@ OpTransfer i -> i _ -> [] +transferTicket+ :: forall m t env kind.+ ( HasTezosRpc m+ , HasTezosClient m+ , WithClientLog env m+ , ParameterScope t+ , Comparable t+ )+ => ImplicitAddressWithAlias -- ^ Sender+ -> KindedAddress kind -- ^ Destination+ -> ContractAddress -- ^ Ticketer+ -> T.Value t -- ^ Ticket value+ -> Natural -- ^ Ticket amount+ -> EpName -- ^ Destination entrypoint+ -> Maybe Mutez -- ^ Fee+ -> m (OperationHash, [IntOpEvent])+transferTicket from (Constrained -> ttdDestination)+ (Constrained -> ttdTicketTicketer) ttdTicketContents+ ttdTicketAmount ttdEntrypoint ttdMbFee =+ (fmap . second) (getEvents . toList) . runOperationsNonEmpty from . one . OpTransferTicket $+ TransferTicketData{..}+ where+ getEvents = concatMap \case+ OpTransferTicket i -> i+ _ -> []+ lTransfer :: forall m t env kind. ( HasTezosRpc m@@ -111,7 +138,7 @@ , NiceParameter t , L1AddressKind kind )- => ImplicitAddress+ => ImplicitAddressWithAlias -> KindedAddress kind -> Mutez -> EpName
src/Morley/Client/App.hs view
@@ -33,6 +33,8 @@ , getChainIdImpl , getDelegateImpl , waitForOperationImpl+ , getTicketBalanceAtBlockImpl+ , getAllTicketBalancesAtBlockImpl -- * Timeouts and retries , retryOnTimeout@@ -64,7 +66,7 @@ import Morley.Client.Logging (WithClientLog, logDebug) import Morley.Client.RPC import Morley.Client.RPC.API qualified as API-import Morley.Micheline (Expression, TezosInt64, TezosNat, unTezosMutez)+import Morley.Micheline (Expression, TezosInt64, TezosNat, unStringEncode, unTezosMutez) import Morley.Tezos.Address import Morley.Tezos.Core (ChainId, Mutez, parseChainId) import Morley.Tezos.Crypto (KeyHash, PublicKey)@@ -190,6 +192,17 @@ (RunClient m, MonadUnliftIO m, MonadCatch m) => BlockId -> Address -> m Mutez getBalanceImpl = retryOnceOnTimeout ... fmap unTezosMutez ... API.getBalance API.nodeMethods++getTicketBalanceAtBlockImpl ::+ (RunClient m, MonadUnliftIO m, MonadCatch m) => BlockId -> Address -> GetTicketBalance -> m Natural+getTicketBalanceAtBlockImpl =+ retryOnceOnTimeout ... fmap unStringEncode ... API.getTicketBalanceAtBlock API.nodeMethods++getAllTicketBalancesAtBlockImpl+ :: (RunClient m, MonadUnliftIO m, MonadCatch m)+ => BlockId -> ContractAddress -> m [GetAllTicketBalancesResponse]+getAllTicketBalancesAtBlockImpl =+ retryOnceOnTimeout ... API.getAllTicketBalancesAtBlock API.nodeMethods getDelegateImpl :: (RunClient m, MonadUnliftIO m, MonadCatch m) => BlockId -> L1Address -> m (Maybe KeyHash)
src/Morley/Client/Full.hs view
@@ -38,6 +38,7 @@ import Morley.Client.TezosClient.Impl (getTezosClientConfig) import Morley.Client.TezosClient.Impl qualified as TezosClient import Morley.Client.TezosClient.Types+import Morley.Client.Types import Morley.Tezos.Crypto (Signature(..)) import Morley.Tezos.Crypto.Ed25519 qualified as Ed25519 import Morley.Util.Lens (makeLensesWith, postfixLFields)@@ -78,19 +79,17 @@ setLogAction action mce = mce { mceLogAction = action } instance HasTezosClient MorleyClientM where- signBytes senderAlias mbPassword opHash = retryOnceOnTimeout $ do+ signBytes (AddressWithAlias _ senderAlias) mbPassword opHash = retryOnceOnTimeout $ do env <- ask case mceSecretKey env of Just sk -> pure . SignatureEd25519 $ Ed25519.sign sk opHash Nothing -> TezosClient.signBytes senderAlias mbPassword opHash rememberContract = failOnTimeout ... TezosClient.rememberContract getAliasesAndAddresses = retryOnceOnTimeout ... TezosClient.getAliasesAndAddresses- genFreshKey = retryOnceOnTimeout ... TezosClient.genFreshKey- genKey = failOnTimeout ... TezosClient.genKey- -- Key revealing cannot be safely retried, so we're not trying to recover it- -- from @ECONNRESET@.- revealKey = failOnTimeout ... TezosClient.revealKey- getKeyPassword = retryOnceOnTimeout . TezosClient.getKeyPassword+ genKey alias = flip AddressWithAlias alias <$> TezosClient.genKey alias+ genFreshKey alias = flip AddressWithAlias alias <$> TezosClient.genFreshKey alias+ getKeyPassword (AddressWithAlias _ alias) = retryOnceOnTimeout $ TezosClient.getKeyPassword alias+ getPublicKey (AddressWithAlias _ alias) = TezosClient.getPublicKey alias instance RunClient MorleyClientM where runRequestAcceptStatus :: Maybe [Status] -> Request -> MorleyClientM Response@@ -123,6 +122,8 @@ getChainId = getChainIdImpl getManagerKeyAtBlock = getManagerKeyImpl waitForOperation = (asks mceClientEnv >>=) . waitForOperationImpl+ getTicketBalanceAtBlock = getTicketBalanceAtBlockImpl+ getAllTicketBalancesAtBlock = getAllTicketBalancesAtBlockImpl -- | Construct 'MorleyClientEnv'.
src/Morley/Client/OnlyRPC.hs view
@@ -27,8 +27,8 @@ import Morley.Client.RPC.Class (HasTezosRpc(..)) import Morley.Client.RPC.HttpClient (newClientEnv) import Morley.Client.TezosClient.Class (HasTezosClient(..))+import Morley.Client.Types import Morley.Tezos.Address-import Morley.Tezos.Address.Alias import Morley.Tezos.Crypto (SecretKey, sign, toPublic) ----------------@@ -109,13 +109,11 @@ -- [#652] We may implement more methods here if the need arises. instance HasTezosClient MorleyOnlyRpcM where- signBytes sender _password opHash = case sender of- AddressAlias {} -> throwM $ UnsupportedByOnlyRPC "signBytes (AddressAlias _)"- AddressResolved address -> do- env <- ask- case moreSecretKeys env ^. at address of- Nothing -> throwM $ UnknownSecretKeyFor address- Just secretKey -> liftIO $ sign secretKey opHash+ signBytes (AddressWithAlias sender _) _password opHash = do+ env <- ask+ case moreSecretKeys env ^. at sender of+ Nothing -> throwM $ UnknownSecretKeyFor sender+ Just secretKey -> liftIO $ sign secretKey opHash -- In RPC-only mode we only use unencrypted in-memory passwords. getKeyPassword _ = pure Nothing@@ -135,7 +133,8 @@ -- Actions that are not supported and simply throw exceptions. genKey _ = throwM $ UnsupportedByOnlyRPC "genKey" genFreshKey _ = throwM $ UnsupportedByOnlyRPC "genFreshKey"- revealKey _ _ = throwM $ UnsupportedByOnlyRPC "revealKey"+ getPublicKey (AddressWithAlias addr _) = asks moreSecretKeys >>=+ maybe (throwM $ UnknownSecretKeyFor addr) (pure . toPublic) . view (at addr) instance RunClient MorleyOnlyRpcM where runRequestAcceptStatus statuses req = do@@ -167,3 +166,5 @@ getChainId = getChainIdImpl getManagerKeyAtBlock = getManagerKeyImpl waitForOperation = (asks moreClientEnv >>=) . waitForOperationImpl+ getTicketBalanceAtBlock = getTicketBalanceAtBlockImpl+ getAllTicketBalancesAtBlock = getAllTicketBalancesAtBlockImpl
src/Morley/Client/Parser.hs view
@@ -7,6 +7,8 @@ , OriginateArgs (..) , TransferArgs (..) , GetScriptSizeArgs (..)+ , TicketBalanceArgs (..)+ , TransferTicketArgs (..) , addressOrAliasOption , clientConfigParser , morleyClientInfo@@ -47,9 +49,12 @@ Originate :: OriginateArgs -> ClientArgsRaw GetScriptSize :: GetScriptSizeArgs -> ClientArgsRaw Transfer :: TransferArgs -> ClientArgsRaw+ TransferTicket :: TransferTicketArgs -> ClientArgsRaw GetBalance :: L1AddressKind kind => AddressOrAlias kind -> ClientArgsRaw GetBlockHeader :: BlockId -> ClientArgsRaw GetBlockOperations :: BlockId -> ClientArgsRaw+ TicketBalance :: SomeAddressOrAlias -> TicketBalanceArgs -> ClientArgsRaw+ AllTicketBalances :: ContractAddressOrAlias -> ClientArgsRaw data OriginateArgs = OriginateArgs { oaMbContractFile :: Maybe FilePath@@ -74,6 +79,16 @@ , taMbFee :: Maybe Mutez } +data TransferTicketArgs = TransferTicketArgs+ { ttaSender :: ImplicitAddressOrAlias+ , ttaTicketContents :: U.Value+ , ttaTicketType :: U.Ty+ , ttaTicketTicketer :: ContractAddressOrAlias+ , ttaTicketAmount :: Natural+ , ttaDestination :: SomeAddressOrAlias+ , ttaMbFee :: Maybe Mutez+ }+ morleyClientInfo :: Opt.ParserInfo ClientArgs morleyClientInfo = parserInfo@@ -131,6 +146,25 @@ \By default fee will be computed automatically." ) +data TicketBalanceArgs = TicketBalanceArgs+ { tbaTicketer :: ContractAddress+ , tbaContent :: U.Value+ , tbaContentType :: U.Ty+ }++getTicketBalanceOption :: Opt.Parser TicketBalanceArgs+getTicketBalanceOption = do+ tbaTicketer <- mkCLOptionParser Nothing+ (#name :! "ticketer")+ (#help :! "The contract that issued the ticket.")+ tbaContentType <- mkCLOptionParser Nothing+ (#name :! "content-type")+ (#help :! "Content type.")+ tbaContent <- valueOption Nothing+ (#name :! "content")+ (#help :! "Ticket content.")+ pure TicketBalanceArgs{..}+ -- | Generic parser to read an option of 'BlockId' type. blockIdOption :: Maybe BlockId@@ -143,12 +177,27 @@ argsRawParser = subparser $ mconcat [ originateCmd , transferCmd+ , transferTicketCmd , getBalanceCmd , getScriptSizeCmd , getBlockHeaderCmd , getBlockOperationsCmd+ , getTicketBalanceCmd+ , getAllTicketBalancesCmd ] where+ ownerOption f = f+ Nothing+ (#name :! "owner")+ (#help :! "Ticket owner")+ getTicketBalanceCmd =+ mkCommandParser "ticket-balance"+ (TicketBalance <$> ownerOption someAddressOrAliasOption <*> getTicketBalanceOption)+ "Get ticket balance for specific tickets"+ getAllTicketBalancesCmd =+ mkCommandParser "all-ticket-balances"+ (AllTicketBalances <$> ownerOption addressOrAliasOption)+ "Get all ticket balances" originateCmd = mkCommandParser "originate" (Originate <$> originateArgsOption)@@ -157,6 +206,10 @@ mkCommandParser "transfer" (Transfer <$> transferArgsOption) "Perform a transfer to the given contract with given amount and parameter."+ transferTicketCmd =+ mkCommandParser "transfer-ticket"+ (TransferTicket <$> transferTicketArgsOption)+ "Perform a ticket transfer to the given contract with given amount and parameter." getBalanceCmd = mkCommandParser "get-balance" ((GetBalance <$>@@ -266,6 +319,29 @@ (#help :! "Transfer parameter.") taMbFee <- feeOption pure $ TransferArgs {..}++transferTicketArgsOption :: Opt.Parser TransferTicketArgs+transferTicketArgsOption = do+ ttaSender <- addressOrAliasOption Nothing+ ! #name "from"+ ! #help "Address or alias from which transfer is performed."+ ttaTicketAmount <- mkCLOptionParser Nothing+ ! #name "amount"+ ! #help "Ticket amount."+ ttaTicketContents <- mkCLOptionParser Nothing+ ! #name "value"+ ! #help "Ticket value."+ ttaTicketType <- mkCLOptionParser Nothing+ ! #name "type"+ ! #help "Ticket type."+ ttaTicketTicketer <- mkCLOptionParser Nothing+ ! #name "ticketer"+ ! #help "Ticketer address or alias."+ ttaDestination <- someAddressOrAliasOption Nothing+ ! #name "to"+ ! #help "Address or alias of the transfer's destination."+ ttaMbFee <- feeOption+ pure $ TransferTicketArgs {..} usageDoc :: Doc usageDoc = mconcat
src/Morley/Client/RPC/API.hs view
@@ -8,6 +8,7 @@ , monitorHeads ) where +import Data.Coerce (coerce) import Network.HTTP.Types.Status (Status(..)) import Servant.API (Capture, Get, JSON, NewlineFraming, Post, QueryParam, ReqBody, SourceIO, StreamGet,@@ -17,7 +18,7 @@ import Morley.Client.RPC.QueryFixedParam import Morley.Client.RPC.Types-import Morley.Micheline (Expression, TezosInt64, TezosMutez)+import Morley.Micheline (Expression, TezosInt64, TezosMutez, TezosNat) import Morley.Tezos.Address import Morley.Tezos.Address.Kinds import Morley.Tezos.Crypto (KeyHash, PublicKey)@@ -39,6 +40,12 @@ Capture "block_id" BlockId :> "context" :> "contracts" :> Capture "contract" ContractAddress' :> "storage" :> Get '[JSON] Expression :<|> + Capture "block_id" BlockId :> "context" :> "contracts" :> Capture "contract" Address'+ :> "ticket_balance" :> ReqBody '[JSON] GetTicketBalance :> Post '[JSON] TezosNat :<|>++ Capture "block_id" BlockId :> "context" :> "contracts" :> Capture "contract" ContractAddress'+ :> "all_ticket_balances" :> Get '[JSON] [GetAllTicketBalancesResponse] :<|>+ Capture "block_id" BlockId :> Get '[JSON] BlockConstants :<|> Capture "block_id" BlockId :> "header" :> Get '[JSON] BlockHeader :<|>@@ -130,6 +137,8 @@ , getCounter :: BlockId -> ImplicitAddress -> m TezosInt64 , getScript :: BlockId -> ContractAddress -> m OriginationScript , getStorageAtBlock :: BlockId -> ContractAddress -> m Expression+ , getTicketBalanceAtBlock :: BlockId -> Address -> GetTicketBalance -> m TezosNat+ , getAllTicketBalancesAtBlock :: BlockId -> ContractAddress -> m [GetAllTicketBalancesResponse] , getBlockConstants :: BlockId -> m BlockConstants , getBlockHeader :: BlockId -> m BlockHeader , getProtocolParameters :: BlockId -> m ProtocolParameters@@ -156,39 +165,33 @@ nodeMethods :: forall m. (MonadCatch m, RunClient m) => NodeMethods m nodeMethods = NodeMethods- { getCounter = withKindedAddress' getCounter'- , getScript = withKindedAddress' getScript'- , getStorageAtBlock = withKindedAddress' getStorageAtBlock'- , getBigMap = withKindedAddress' getBigMap'- , getBalance = withAddress' getBalance'- , getDelegate = \block (Constrained addr) -> do+ { getDelegate = \block (Constrained addr) -> do result <- try $ getDelegate' block (Address' $ MkAddress addr) case result of Left (FailureResponse _ Response{responseStatusCode=Status{statusCode = 404}}) -> pure Nothing Left err -> throwM err Right res -> pure $ Just res- , getManagerKey = withKindedAddress' getManagerKey' , .. } where- withKindedAddress' f blockId = f blockId . KindedAddress'- withAddress' f blockId = f blockId . Address' (getBlockHash- :<|> getCounter'- :<|> getScript'- :<|> getStorageAtBlock'+ :<|> (coerce -> getCounter)+ :<|> (coerce -> getScript)+ :<|> (coerce -> getStorageAtBlock)+ :<|> (coerce -> getTicketBalanceAtBlock)+ :<|> (coerce -> getAllTicketBalancesAtBlock) :<|> getBlockConstants :<|> getBlockHeader :<|> getProtocolParameters :<|> getBlockOperations :<|> getBlockOperationHashes- :<|> getBigMap'+ :<|> (coerce -> getBigMap) :<|> getBigMapValueAtBlock :<|> getBigMapValuesAtBlock- :<|> getBalance'+ :<|> (coerce -> getBalance) :<|> getDelegate'- :<|> getManagerKey'+ :<|> (coerce -> getManagerKey) :<|> getScriptSizeAtBlock :<|> forgeOperation :<|> runOperation
src/Morley/Client/RPC/Class.hs view
@@ -83,3 +83,12 @@ -- ^ Blocks until an operation with the given hash is included into the chain. -- The first argument is the action that puts the operation on the chain. -- Returns the hash of the included operation.+ getTicketBalanceAtBlock :: BlockId -> Address -> GetTicketBalance -> m Natural+ -- ^ Access the contract's or implicit account's balance of ticket with+ -- specified ticketer, content type, and content.+ getAllTicketBalancesAtBlock+ :: BlockId+ -> ContractAddress+ -> m [GetAllTicketBalancesResponse]+ -- ^ Access the complete list of tickets owned by the given contract by+ -- scanning the contract's storage.
src/Morley/Client/RPC/Getters.hs view
@@ -31,6 +31,9 @@ , getDelegate , runCode , getManagerKey+ , contractStateResolver+ , getTicketBalance+ , getAllTicketBalances ) where import Data.Map as Map (fromList)@@ -42,6 +45,8 @@ import Lorentz (NicePackedValue, NiceUnpackedValue, valueToScriptExpr) import Lorentz.Value import Morley.Micheline+import Morley.Michelson.Runtime.GState (ContractState(..))+import Morley.Michelson.TypeCheck (typeCheckContract, typeCheckingWith) import Morley.Michelson.TypeCheck.TypeCheck (SomeParamType(..), TcOriginatedContracts, mkSomeParamType) import Morley.Michelson.Typed@@ -260,3 +265,29 @@ getManagerKey :: HasTezosRpc m => ImplicitAddress -> m (Maybe PublicKey) getManagerKey = getManagerKeyAtBlock HeadId++-- | Get 'ContractState' for a given t'ContractAddress' at a given 'BlockId'.+-- Can be used with the morley interpreter to add some network interoperability.+contractStateResolver :: HasTezosRpc m => BlockId -> ContractAddress -> m (Maybe ContractState)+contractStateResolver blkId addr = handleStatusCode 404 (pure Nothing) $ Just <$> do+ block <- BlockHashId <$> getBlockHash blkId+ uContract <- throwLeft $ fromExpression . osCode <$> getContractScriptAtBlock block addr+ csBalance <- getBalanceAtBlock block $ Constrained addr+ csDelegate <- getDelegateAtBlock block $ Constrained addr+ SomeContract csContract@Contract{} <-+ either throwM pure . typeCheckingWith def $ typeCheckContract uContract+ csStorage <- throwLeft $ fromExpression <$> getContractStorageAtBlock block addr+ pure ContractState{..}++getTicketBalance+ :: HasTezosRpc m+ => L1Address -- ^ Ticket owner+ -> GetTicketBalance -- ^ Ticket description+ -> m Natural+getTicketBalance = getTicketBalanceAtBlock HeadId . toAddress++getAllTicketBalances+ :: HasTezosRpc m+ => ContractAddress -- ^ Ticket owner+ -> m [GetAllTicketBalancesResponse]+getAllTicketBalances = getAllTicketBalancesAtBlock HeadId
src/Morley/Client/RPC/Types.hs view
@@ -52,8 +52,11 @@ , RunOperationResult (..) , RPCInput , TransactionOperation (..)+ , TransferTicketOperation (..) , WithCommonOperationData (..) , MonitorHeadsStep(..)+ , GetTicketBalance (..)+ , GetAllTicketBalancesResponse (..) , mkCommonOperationData -- * Errors@@ -122,6 +125,7 @@ data RPCInput instance OperationInfoDescriptor RPCInput where type TransferInfo RPCInput = TransactionOperation+ type TransferTicketInfo RPCInput = TransferTicketOperation type OriginationInfo RPCInput = OriginationOperation type RevealInfo RPCInput = RevealOperation type DelegationInfo RPCInput = DelegationOperation@@ -401,6 +405,7 @@ | IllTypedData Expression Expression | BadStack BadStackInformation | ForbiddenZeroAmountTicket+ | REEmptyImplicitContract ImplicitAddress deriving stock Show instance FromJSON RunError where@@ -441,6 +446,7 @@ , "unregistered_delegate" ~> UnregisteredDelegate <$> o .: "hash" , "no_deletion" ~> FailedUnDelegation <$> o .: "delegate" , "delegate.already_active" ~> pure DelegateAlreadyActive+ , "empty_implicit_contract" ~> REEmptyImplicitContract <$> o .: "implicit" , "ill_typed_contract" ~> IllTypedContract <$> o .: "ill_typed_code" , "ill_typed_data" ~> IllTypedData <$> o .: "expected_type" <*> o .: "ill_typed_expression" , "bad_stack" ~> BadStack <$> parseJSON (Object o)@@ -515,6 +521,8 @@ "Failed to withdraw delegation for: " +| addr |+ "" DelegateAlreadyActive -> "Delegate already active"+ REEmptyImplicitContract addr ->+ "Empty implicit contract (" +| addr |+ ")" IllTypedContract expr -> "Ill typed contract: " +| expr |+ "" IllTypedData expected ill_typed ->@@ -661,8 +669,8 @@ -- -- \[ -- \mathrm{min}\left(\mathbf{hard\_gas\_limit\_per\_operation},--- \left\lceil \frac{\mathbf{hard\_gas\_limit\_per\_block}}--- {num\_operations}\right\rceil\right)+-- \left\lfloor \frac{\mathbf{hard\_gas\_limit\_per\_block}}+-- {num\_operations}\right\rfloor\right) -- \] -- -- This works well enough for the case of many small operations, but will break@@ -694,7 +702,7 @@ | Just numOp <- argF #num_operations mNumOp , numOp > 0 = StringEncode $- min (unStringEncode ppHardGasLimitPerOperation) $ ceiling $+ min (unStringEncode ppHardGasLimitPerOperation) $ floor $ unStringEncode ppHardGasLimitPerBlock % numOp | otherwise = ppHardGasLimitPerOperation @@ -739,6 +747,15 @@ , toParameters :: ParametersInternal } +data TransferTicketOperation = TransferTicketOperation+ { ttoTicketContents :: Expression+ , ttoTicketTy :: Expression+ , ttoTicketTicketer :: Address+ , ttoTicketAmount :: TezosNat+ , ttoDestination :: Address+ , ttoEntrypoint :: Text+ }+ data OriginationScript = OriginationScript { osCode :: Expression , osStorage :: Expression@@ -824,6 +841,19 @@ , rcPayer :: Maybe ImplicitAddress } +data GetTicketBalance = GetTicketBalance+ { gtbTicketer :: ContractAddress+ , gtbContentType :: Expression+ , gtbContent :: Expression+ }++data GetAllTicketBalancesResponse = GetAllTicketBalancesResponse+ { gatbrTicketer :: ContractAddress+ , gatbrContentType :: Expression+ , gatbrContent :: Expression+ , gatbrAmount :: TezosNat+ }+ -- | Result storage of @run_code@ RPC endpoint call. -- -- Actual resulting JSON has more contents, but currently we're interested@@ -854,6 +884,18 @@ ] instance ToJSONObject TransactionOperation +instance ToJSON TransferTicketOperation where+ toJSON TransferTicketOperation{..} = object $+ [ "kind" .= String "transfer_ticket"+ , "ticket_contents" .= ttoTicketContents+ , "ticket_ty" .= ttoTicketTy+ , "ticket_ticketer" .= ttoTicketTicketer+ , "ticket_amount" .= ttoTicketAmount+ , "destination" .= ttoDestination+ , "entrypoint" .= ttoEntrypoint+ ]+instance ToJSONObject TransferTicketOperation+ instance FromJSON TransactionOperation where parseJSON = withObject "TransactionOperation" $ \obj -> do toAmount <- obj .: "amount"@@ -905,8 +947,10 @@ deriveToJSON morleyClientAesonOptions ''RunOperation deriveToJSON morleyClientAesonOptions ''GetBigMap+deriveToJSON morleyClientAesonOptions ''GetTicketBalance deriveToJSON morleyClientAesonOptions ''CalcSize deriveToJSON morleyClientAesonOptions{omitNothingFields = True} ''RunCode+deriveFromJSON morleyClientAesonOptions ''GetAllTicketBalancesResponse deriveFromJSON morleyClientAesonOptions ''BlockHeaderNoHash deriveFromJSON morleyClientAesonOptions ''ScriptSize deriveFromJSON morleyClientAesonOptions ''BlockConstants
src/Morley/Client/TezosClient.hs view
@@ -13,6 +13,8 @@ , ResolveError(..) , resolveAddress , resolveAddressMaybe+ , resolveAddressWithAlias+ , resolveAddressWithAliasMaybe , getAlias , getAliasMaybe ) where
src/Morley/Client/TezosClient/Class.hs view
@@ -11,6 +11,7 @@ import Data.ByteArray (ScrubbedBytes) +import Morley.Client.Types import Morley.Tezos.Address import Morley.Tezos.Address.Alias import Morley.Tezos.Crypto@@ -32,18 +33,20 @@ -- | Type class that provides interaction with @octez-client@ binary class (Monad m) => HasTezosClient m where- signBytes :: ImplicitAddressOrAlias -> Maybe ScrubbedBytes -> ByteString -> m Signature+ signBytes+ :: ImplicitAddressWithAlias+ -> Maybe ScrubbedBytes+ -> ByteString+ -> m Signature -- ^ Sign an operation with @octez-client@.- genKey :: ImplicitAlias -> m ImplicitAddress+ genKey :: ImplicitAlias -> m ImplicitAddressWithAlias -- ^ Generate a secret key and store it with given alias. -- If a key with this alias already exists, the corresponding address -- will be returned and no state will be changed.- genFreshKey :: ImplicitAlias -> m ImplicitAddress+ genFreshKey :: ImplicitAlias -> m ImplicitAddressWithAlias -- ^ Generate a secret key and store it with given alias. -- Unlike 'genKey' this function overwrites -- the existing key when given alias is already stored.- revealKey :: ImplicitAlias -> Maybe ScrubbedBytes -> m ()- -- ^ Reveal public key associated with given implicit account. rememberContract :: AliasBehavior -> ContractAddress -> ContractAlias -> m () -- ^ Associate the given contract with alias. -- The 'Bool' variable indicates whether or not we should replace already@@ -58,9 +61,11 @@ -- > ("key:abc", "tz1...") -- -- TODO [#910]: Cache this and turn it into a 'Morley.Util.Bimap'.- getKeyPassword :: ImplicitAddress -> m (Maybe ScrubbedBytes)+ getKeyPassword :: ImplicitAddressWithAlias -> m (Maybe ScrubbedBytes) -- ^ Get password for secret key associated with given address -- in case this key is password-protected. Obtained password is used -- in two places: -- * 1) In @signBytes@ call. -- * 2) in @revealKey@ call.+ getPublicKey :: ImplicitAddressWithAlias -> m PublicKey+ -- ^ Get a public key for an implicit address or alias.
src/Morley/Client/TezosClient/Impl.hs view
@@ -13,6 +13,7 @@ , genKey , genFreshKey , revealKey+ , revealKeyUnlessRevealed , ResolveError(..) , Resolve(..) , resolveAddress@@ -28,6 +29,8 @@ , getKeyPassword , registerDelegate , getAliasesAndAddresses+ , resolveAddressWithAlias+ , resolveAddressWithAliasMaybe -- * Internals , findAddress@@ -55,11 +58,14 @@ import Data.Singletons (demote) import Lorentz.Value import Morley.Client.Logging+import Morley.Client.RPC.Class (HasTezosRpc)+import Morley.Client.RPC.Getters (getManagerKey) import Morley.Client.RPC.Types import Morley.Client.TezosClient.Class (AliasBehavior(..)) import Morley.Client.TezosClient.Class qualified as Class (HasTezosClient(..)) import Morley.Client.TezosClient.Parser import Morley.Client.TezosClient.Types+import Morley.Client.Types import Morley.Client.Util (readScrubbedBytes, scrubbedBytesToString) import Morley.Micheline import Morley.Michelson.Typed.Scope@@ -67,6 +73,7 @@ import Morley.Tezos.Address.Alias import Morley.Tezos.Address.Kinds import Morley.Tezos.Crypto+import Morley.Util.Constrained import Morley.Util.Interpolate (itu) import Morley.Util.Peano import Morley.Util.Sing (castSing)@@ -132,10 +139,6 @@ | AmbiguousAlias Text ContractAddress ImplicitAddress -- ^ Expected an alias to be associated with either an implicit address or a -- contract address, but it was associated with both.- | AliasTxRollup Text (KindedAddress 'AddressKindTxRollup)- -- ^ Expected an alias to be associated with either- -- an implicit address or a contract address,- -- but it was associated with a transaction rollup address. | ResolveError ResolveError deriving stock instance Show TezosClientError@@ -190,11 +193,6 @@ * and an implicit address: #{implicitAddr} Use '#{contractPrefix}:#{aliasText}' or '#{implicitPrefix}:#{aliasText}' to disambiguate. |]- AliasTxRollup aliasText txRollupAddr ->- [itu|- Expected the alias '#{aliasText}' to be assigned to either a contract or an implicit account,- but it's assigned to a transaction rollup address: #{txRollupAddr}.- |] ResolveError err -> build err ----------------------------------------------------------------------------@@ -210,14 +208,13 @@ -- | Sign an arbtrary bytestring using @octez-client@. -- Secret key of the address corresponding to give 'AddressOrAlias' must be known. signBytes- :: (WithClientLog env m, HasTezosClientEnv env, MonadIO m, MonadCatch m, Class.HasTezosClient m)- => ImplicitAddressOrAlias+ :: (WithClientLog env m, HasTezosClientEnv env, MonadIO m, MonadCatch m)+ => ImplicitAlias -> Maybe ScrubbedBytes -> ByteString -> m Signature-signBytes signer mbPassword opHash = do- signerAlias <- getAlias signer- logDebug $ "Signing for " <> pretty signer+signBytes signerAlias mbPassword opHash = do+ logDebug $ "Signing for " <> pretty signerAlias output <- callTezosClientStrict ["sign", "bytes", toCmdArg opHash, "for", toCmdArg signerAlias] MockupMode mbPassword liftIO case T.stripPrefix "Signature: " output of@@ -300,6 +297,18 @@ logDebug $ "Successfully revealed key for " +| alias |+ "" +-- | Reveal key for implicit address if necessary.+revealKeyUnlessRevealed+ :: (WithClientLog env m, HasTezosRpc m, MonadIO m, HasTezosClientEnv env)+ => ImplicitAddressWithAlias+ -> Maybe ScrubbedBytes+ -> m ()+revealKeyUnlessRevealed (AddressWithAlias addr alias) mbPassword = do+ mbManagerKey <- getManagerKey addr+ case mbManagerKey of+ Nothing -> revealKey alias mbPassword+ Just _ -> logDebug $ alias |+ " alias has already revealed key"+ -- | Register alias as delegate registerDelegate :: (WithClientLog env m, HasTezosClientEnv env, MonadIO m, MonadCatch m)@@ -329,11 +338,10 @@ -- | Return 'PublicKey' corresponding to given 'AddressOrAlias'. getPublicKey- :: (WithClientLog env m, HasTezosClientEnv env, MonadIO m, MonadCatch m, Class.HasTezosClient m)- => ImplicitAddressOrAlias+ :: (WithClientLog env m, HasTezosClientEnv env, MonadIO m, MonadCatch m)+ => ImplicitAlias -> m PublicKey-getPublicKey addrOrAlias = do- alias <- getAlias addrOrAlias+getPublicKey alias = do logDebug $ "Getting " +| alias |+ " public key" output <- callTezosClientStrict ["show", "address", toCmdArg alias] MockupMode Nothing liftIO case lines output of@@ -347,11 +355,10 @@ -- | Return 'SecretKey' corresponding to given 'AddressOrAlias'. getSecretKey- :: (WithClientLog env m, HasTezosClientEnv env, MonadIO m, MonadCatch m, Class.HasTezosClient m)- => ImplicitAddressOrAlias+ :: (WithClientLog env m, HasTezosClientEnv env, MonadIO m, MonadCatch m)+ => ImplicitAlias -> m SecretKey-getSecretKey addrOrAlias = do- alias <- getAlias addrOrAlias+getSecretKey alias = do logDebug $ "Getting " +| alias |+ " secret key" output <- callTezosClientStrict ["show", "address", toCmdArg alias, "--show-secret"] MockupMode Nothing liftIO case lines output of@@ -393,7 +400,7 @@ => Bool -> ImplicitAlias -> SecretKey- -> m ImplicitAlias+ -> m ImplicitAddressWithAlias importKey replaceExisting name key = do let isAlreadyExistsError = T.isInfixOf "already exists"@@ -403,7 +410,7 @@ callTezosClient errHandler (if replaceExisting then args <> ["--force"] else args) MockupMode Nothing- pure name+ pure $ AddressWithAlias (mkKeyAddress (toPublic key)) name -- | Read @octez-client@ configuration. getTezosClientConfig :: FilePath -> Maybe FilePath -> IO TezosClientConfig@@ -488,25 +495,21 @@ -- | Get password for secret key associated with given address -- in case this key is password-protected getKeyPassword- :: (WithClientLog env m, HasTezosClientEnv env, MonadIO m, MonadMask m, Class.HasTezosClient m)- => ImplicitAddress -> m (Maybe ScrubbedBytes)-getKeyPassword key = (getAlias $ AddressResolved key) >>= getKeyPassword'- where- getKeyPassword'- :: (WithClientLog env m, HasTezosClientEnv env, MonadIO m, MonadCatch m, MonadMask m)- => ImplicitAlias -> m (Maybe ScrubbedBytes)- getKeyPassword' alias = do- output <- callTezosClientStrict [ "show", "address", pretty alias, "-S"] MockupMode Nothing- encryptionType <-- case parseSecretKeyEncryption output of- Right t -> return t- Left err -> throwM $ TezosClientParseEncryptionTypeError output $ pretty err- case encryptionType of- EncryptedKey -> do- putTextLn $ "Please enter password for '" <> pretty alias <> "':"- Just <$> withoutEcho readScrubbedBytes- _ -> pure Nothing+ :: (WithClientLog env m, HasTezosClientEnv env, MonadIO m, MonadMask m)+ => ImplicitAlias -> m (Maybe ScrubbedBytes)+getKeyPassword alias = do+ output <- callTezosClientStrict [ "show", "address", pretty alias, "-S"] MockupMode Nothing+ encryptionType <-+ case parseSecretKeyEncryption output of+ Right t -> return t+ Left err -> throwM $ TezosClientParseEncryptionTypeError output $ pretty err+ case encryptionType of+ EncryptedKey -> do+ putTextLn $ "Please enter password for '" <> pretty alias <> "':"+ Just <$> withoutEcho readScrubbedBytes+ _ -> pure Nothing + where -- Hide entered password withoutEcho :: (MonadIO m, MonadMask m) => m a -> m a withoutEcho action = do@@ -666,6 +669,7 @@ class Resolve addressOrAlias where type ResolvedAddress addressOrAlias :: Type type ResolvedAlias addressOrAlias :: Type+ type ResolvedAddressAndAlias addressOrAlias :: Type -- | Looks up the address associated with the given @addressOrAlias@. --@@ -698,9 +702,17 @@ => addressOrAlias -> m (Either ResolveError (ResolvedAlias addressOrAlias)) + -- | Resolve both address and alias at the same time+ resolveAddressWithAliasEither+ :: forall m env+ . (Class.HasTezosClient m, MonadThrow m, WithClientLog env m)+ => addressOrAlias+ -> m (Either ResolveError (ResolvedAddressAndAlias addressOrAlias))+ instance Resolve (AddressOrAlias kind) where type ResolvedAddress (AddressOrAlias kind) = KindedAddress kind type ResolvedAlias (AddressOrAlias kind) = Alias kind+ type ResolvedAddressAndAlias (AddressOrAlias kind) = AddressWithAlias kind resolveAddressEither :: (Class.HasTezosClient m, MonadThrow m, WithClientLog env m)@@ -738,9 +750,13 @@ let aliasTextWithoutPrefix = fromMaybe aliasText $ T.stripPrefix "key:" aliasText pure $ Right $ mkAlias @kind aliasTextWithoutPrefix \\ addressKindSanity addr + resolveAddressWithAliasEither addr =+ (liftA2 . liftA2) AddressWithAlias (resolveAddressEither addr) (getAliasEither addr)+ instance Resolve SomeAddressOrAlias where type ResolvedAddress SomeAddressOrAlias = L1Address type ResolvedAlias SomeAddressOrAlias = SomeAlias+ type ResolvedAddressAndAlias SomeAddressOrAlias = Constrained L1AddressKind AddressWithAlias resolveAddressEither :: (Class.HasTezosClient m, MonadThrow m, WithClientLog env m)@@ -761,12 +777,35 @@ SAOAKindSpecified aoa -> do fmap SomeAlias <$> getAliasEither aoa \\ addressOrAliasKindSanity aoa- aoa@(SAOAKindUnspecified aliasText) -> do+ aoa@SAOAKindUnspecified{} -> runExceptT do -- Find out whether this alias is associated with an implicit address or a contract, -- and return an @Alias kind@ of the correct kind.- resolveAddressEither aoa <&> fmap- \(Constrained (addr :: KindedAddress kind)) ->- SomeAlias $ mkAlias @kind aliasText \\ addressKindSanity addr+ ExceptT (resolveAddressWithAliasEither aoa) <&> foldConstrained (SomeAlias . awaAlias)++ resolveAddressWithAliasEither addr = runExceptT case addr of+ SAOAKindSpecified aoa -> do+ kaddr <- ExceptT $ resolveAddressEither aoa+ kalias <- ExceptT $ getAliasEither aoa+ pure $ Constrained (AddressWithAlias kaddr kalias) \\ addressOrAliasKindSanity aoa+ aoa@(SAOAKindUnspecified aliasText) -> do+ ExceptT (resolveAddressEither aoa) <&> foldConstrained+ \kaddr -> Constrained $ AddressWithAlias kaddr $ mkAlias aliasText \\ addressKindSanity kaddr++-- | Looks up the address and alias with the given @addressOrAlias@.+resolveAddressWithAlias+ :: forall addressOrAlias m env+ . (Class.HasTezosClient m, MonadThrow m, WithClientLog env m, Resolve addressOrAlias)+ => addressOrAlias+ -> m (ResolvedAddressAndAlias addressOrAlias)+resolveAddressWithAlias = resolveAddressWithAliasEither >=> either (throwM . ResolveError) pure++-- | Looks up the address and alias with the given @addressOrAlias@.+resolveAddressWithAliasMaybe+ :: forall addressOrAlias m env+ . (Class.HasTezosClient m, MonadThrow m, WithClientLog env m, Resolve addressOrAlias)+ => addressOrAlias+ -> m (Maybe (ResolvedAddressAndAlias addressOrAlias))+resolveAddressWithAliasMaybe = fmap rightToMaybe . resolveAddressWithAliasEither -- | Looks up the address associated with the given @addressOrAlias@. --
src/Morley/Client/TezosClient/Types.hs view
@@ -5,7 +5,6 @@ module Morley.Client.TezosClient.Types ( CmdArg (..)- -- , addressResolved , CalcOriginationFeeData (..) , CalcTransferFeeData (..) , TezosClientConfig (..)@@ -27,7 +26,6 @@ import Servant.Client (BaseUrl(..), showBaseUrl) import Text.Hex (encodeHex) --- import Lorentz (ToAddress, toAddress) import Morley.Client.RPC.Types (OperationHash) import Morley.Client.Util import Morley.Micheline
src/Morley/Client/Types.hs view
@@ -5,26 +5,38 @@ ( ToJSONObject , OperationInfoDescriptor (..) , OperationInfo (..)+ , AddressWithAlias(..)+ , ImplicitAddressWithAlias+ , ContractAddressWithAlias , _OpTransfer , _OpOriginate , _OpReveal , _OpDelegation+ , _OpTransferTicket ) where import Control.Lens (makePrisms) import Data.Aeson (ToJSON(..))+import Fmt (Buildable(..), (+|), (|+)) +import Lorentz (ToAddress(..), ToTAddress(..))+import Morley.Tezos.Address+import Morley.Tezos.Address.Alias+import Morley.Tezos.Address.Kinds+ -- | Designates types whose 'ToJSON' instance produces only 'Data.Aeson.Object's. class ToJSON a => ToJSONObject a class OperationInfoDescriptor (i :: Type) where type family TransferInfo i :: Type+ type family TransferTicketInfo i :: Type type family OriginationInfo i :: Type type family RevealInfo i :: Type type family DelegationInfo i :: Type data OperationInfo i = OpTransfer (TransferInfo i)+ | OpTransferTicket (TransferTicketInfo i) | OpOriginate (OriginationInfo i) | OpReveal (RevealInfo i) | OpDelegation (DelegationInfo i)@@ -32,13 +44,33 @@ -- Requiring 'ToJSONObject' in superclass as those different types of operation -- must be distinguishable and that is usually done by a special field instance- Each '[ToJSONObject] [TransferInfo i, OriginationInfo i, RevealInfo i, DelegationInfo i] =>+ Each '[ToJSONObject]+ [TransferInfo i, TransferTicketInfo i, OriginationInfo i, RevealInfo i, DelegationInfo i] => ToJSON (OperationInfo i) where toJSON = \case OpTransfer op -> toJSON op+ OpTransferTicket op -> toJSON op OpOriginate op -> toJSON op OpReveal op -> toJSON op OpDelegation op -> toJSON op instance ToJSON (OperationInfo i) => ToJSONObject (OperationInfo i) makePrisms ''OperationInfo++data AddressWithAlias kind = AddressWithAlias+ { awaAddress :: KindedAddress kind+ , awaAlias :: Alias kind+ }+ deriving stock (Show, Eq)++instance ToAddress (AddressWithAlias kind) where+ toAddress = toAddress . awaAddress++instance ToTAddress cp vd (KindedAddress kind) => ToTAddress cp vd (AddressWithAlias kind) where+ toTAddress = toTAddress . awaAddress++instance Buildable (AddressWithAlias kind) where+ build (AddressWithAlias addr alias) = addr |+ " (" +| alias |+ ")"++type ImplicitAddressWithAlias = AddressWithAlias 'AddressKindImplicit+type ContractAddressWithAlias = AddressWithAlias 'AddressKindContract
test/Test/BigMapGet.hs view
@@ -5,7 +5,7 @@ ( test_BigMapGetUnit ) where -import Data.Map (lookup)+import Control.Lens (at) import Test.HUnit (Assertion, assertFailure) import Test.Hspec.Expectations (shouldThrow) import Test.Tasty (TestTree, testGroup)@@ -28,15 +28,15 @@ bigMapGetHandlers = defaultHandlers { hGetContractBigMap = \blkId addr GetBigMap{..} -> do assertHeadBlockId blkId- st <- get- case lookup addr (fsContracts st) of+ use (fsContractsL . at addr) >>= \case Nothing -> throwM $ UnknownAccount $ Constrained addr Just AccountState{..} -> case asAccountData of ContractData _ mbBigMap -> case mbBigMap of Nothing -> throwM $ ContractDoesntHaveBigMap $ MkAddress addr- Just ContractStateBigMap{..} -> case lookup (encodeBase58Check $ expressionToScriptExpr bmKey) csbmMap of- Nothing -> pure GetBigMapNotFound- Just serializedValue -> pure $ GetBigMapResult $ decodeExpression serializedValue+ Just ContractStateBigMap{..} ->+ case csbmMap ^. at (encodeBase58Check $ expressionToScriptExpr bmKey) of+ Nothing -> pure GetBigMapNotFound+ Just serializedValue -> pure $ GetBigMapResult $ decodeExpression serializedValue } fakeStateWithBigMapContract
test/Test/Fees.hs view
@@ -14,9 +14,8 @@ import Morley.Client.Action.Origination import Morley.Client.Action.Transaction import Morley.Client.RPC.Types-import Morley.Michelson.Runtime.GState (genesisAddress1)+import Morley.Client.Types import Morley.Michelson.Untyped.Entrypoints-import Morley.Tezos.Address.Alias (AddressOrAlias(..)) import Morley.Tezos.Core (tz) import Test.Addresses import Test.Util@@ -26,7 +25,7 @@ :: FakeState fakeState = defaultFakeState { fsContracts = fromList $ one $ (contractAddress2, dumbContractState)- , fsImplicits = fromList $ one (genesisAddress1, dumbImplicitState)+ , fsImplicits = fromList $ one $ second revealKeyState $ genesisState @1 } countForgesHandlers :: Handlers $ TestT (State Word)@@ -48,7 +47,7 @@ { arConsumedMilliGas = 10100000 , arStorageSize = 250 , arPaidStorageDiff = 250- , arOriginatedContracts = originatedContracts+ , arOriginatedContracts = concatMap arOriginatedContracts originatedContracts , arAllocatedDestinationContracts = 0 } , rmInternalOperationResults = []@@ -82,7 +81,7 @@ [ testCase "One transaction" $ let forgeCalls = runForgesCountingTest $- lTransfer genesisAddress1 contractAddress2+ lTransfer addr1 contractAddress2 [tz|10u|] DefEpName () Nothing in forgeCalls @?= sum [ 2 -- for fees adjustment@@ -94,7 +93,7 @@ let forgeCalls = runForgesCountingTest $ lOriginateContract OverwriteDuplicateAlias "c"- (AddressResolved genesisAddress1) [tz|10u|]+ addr1 [tz|10u|] averageContract () Nothing Nothing in forgeCalls @?= sum [ 2 -- for fees adjustment@@ -103,3 +102,6 @@ ] ]++addr1 :: ImplicitAddressWithAlias+addr1 = addrAndAliasFromGenesisState @1
test/Test/KeyRevealing.hs view
@@ -13,17 +13,13 @@ import Morley.Client import Morley.Michelson.Runtime.GState (genesisAddress1) import Morley.Michelson.Typed-import Morley.Tezos.Address.Alias (AddressOrAlias(..)) import Morley.Tezos.Core (tz) import Test.Util import TestM fakeState :: FakeState fakeState = defaultFakeState- { fsImplicits = one ( genesisAddress1- , dumbImplicitState- { asAccountData = ImplicitData $ Just dumbManagerKey }- )+ { fsImplicits = one $ second revealKeyState $ genesisState @1 } test_keyRevealing :: TestTree@@ -31,14 +27,14 @@ [ testCase "Manager key for new address is revealed only once for transfer" $ handleSuccess $ runFakeTest chainOperationHandlers fakeState $ do senderAddress <- genKey "sender"- dummyTransfer genesisAddress1 senderAddress- mbManagerKey <- getManagerKey senderAddress+ dummyTransfer addr1 $ awaAddress senderAddress+ mbManagerKey <- getManagerKey $ awaAddress senderAddress when (isJust mbManagerKey) $ fail "Manager key was expected not to be revealed, but it's revealed." dummyTransfer senderAddress genesisAddress1- mbManagerKey' <- getManagerKey senderAddress+ mbManagerKey' <- getManagerKey $ awaAddress senderAddress when (isNothing mbManagerKey') $ fail "Manager key was expected to be revealed, but it's not revealed."@@ -50,16 +46,16 @@ , testCase "Manager key for new address is revealed only once for origination" $ handleSuccess $ runFakeTest chainOperationHandlers fakeState $ do originatorAddress <- genKey "originator"- dummyTransfer genesisAddress1 originatorAddress+ dummyTransfer addr1 $ awaAddress originatorAddress - mbManagerKey <- getManagerKey originatorAddress+ mbManagerKey <- getManagerKey $ awaAddress originatorAddress when (isJust mbManagerKey) $ fail "Manager key was expected not to be revealed, but it's revealed." originateDummy originatorAddress - mbManagerKey' <- getManagerKey originatorAddress+ mbManagerKey' <- getManagerKey $ awaAddress originatorAddress when (isNothing mbManagerKey') $ fail "Manager key was expected to be revealed, but it's not revealed." @@ -68,17 +64,18 @@ (originateDummy originatorAddress) ] where+ addr1 = addrAndAliasFromGenesisState @1 dummyTransfer from to = void $ transfer from to [tz|10u|] DefEpName (toVal ()) Nothing originateDummy addr =- lOriginateContract OverwriteDuplicateAlias "dummy" (AddressResolved addr) [tz|10u|]+ lOriginateContract OverwriteDuplicateAlias "dummy" addr [tz|10u|] dumbLorentzContract () Nothing Nothing -- | Handlers which don't allow to reveal key. noRevealHandlers :: (Monad m) => TestHandlers m noRevealHandlers = TestHandlers $ chainOperationHandlers- { hRevealKey = \_ _ -> throwM $ UnexpectedClientCall "revealKey" }+ { hGetPublicKey = \_ -> throwM $ UnexpectedClientCall "getPublicKey" } dumbLorentzContract :: L.Contract Integer () () dumbLorentzContract = L.defaultContract $
test/Test/Origination.hs view
@@ -5,15 +5,13 @@ ( test_lRunTransactionsUnit ) where -import Test.HUnit (Assertion, assertFailure) import Test.Hspec.Expectations (shouldThrow)+import Test.HUnit (Assertion, assertFailure) import Test.Tasty (TestTree, testGroup) import Test.Tasty.HUnit (testCase) import Lorentz qualified as L import Morley.Client-import Morley.Michelson.Runtime.GState (genesisAddress1, genesisAddress3)-import Morley.Tezos.Address.Alias (AddressOrAlias(..)) import Morley.Tezos.Core import Test.Addresses import Test.Util@@ -23,7 +21,7 @@ :: FakeState fakeState = defaultFakeState { fsContracts = fromList $ one $ (contractAddress2, dumbContractState)- , fsImplicits = fromList $ one $ (genesisAddress1, dumbImplicitState)+ , fsImplicits = fromList $ one $ genesisState @1 } dumbLorentzContract :: L.Contract Integer () ()@@ -34,14 +32,17 @@ test_lRunTransactionsUnit = testGroup "Mock test transaction sending" [ testCase "Successful origination" $ handleSuccess $ runFakeTest chainOperationHandlers fakeState $- lOriginateContract OverwriteDuplicateAlias "dummy" (AddressResolved genesisAddress1) [tz|100500u|]+ lOriginateContract OverwriteDuplicateAlias "dummy" addr1 [tz|100500u|] dumbLorentzContract () Nothing Nothing , testCase "Originator doesn't exist" $ handleUnknownContract $ runFakeTest chainOperationHandlers fakeState $- lOriginateContract OverwriteDuplicateAlias "dummy" (AddressResolved genesisAddress3) [tz|100500u|]+ lOriginateContract OverwriteDuplicateAlias "dummy" addr3 [tz|100500u|] dumbLorentzContract () Nothing Nothing ] where+ addr1 = addrAndAliasFromGenesisState @1+ addr3 = addrAndAliasFromGenesisState @3+ handleSuccess :: Either SomeException a -> Assertion handleSuccess (Right _) = pass handleSuccess (Left e) = assertFailure $ displayException e@@ -51,5 +52,5 @@ assertFailure "Origination unexpectedly didn't fail." handleUnknownContract (Left e) = shouldThrow (throwM e) $ \case- ResolveError REAddressNotFound{} -> True+ UnknownAccount{} -> True _ -> False
test/Test/ParameterTypeGet.hs view
@@ -5,7 +5,6 @@ ( test_parameterTypeGetUnit ) where -import Data.Map as Map (empty) import Test.HUnit (Assertion, assertEqual, assertFailure) import Test.Tasty (TestTree, testGroup) import Test.Tasty.HUnit (testCase)@@ -15,7 +14,6 @@ import Morley.Client.RPC.Getters import Morley.Client.RPC.Types import Morley.Micheline-import Morley.Michelson.Runtime.GState (genesisAddress1) import Morley.Michelson.TypeCheck.TypeCheck (SomeParamType, mkSomeParamType) import Morley.Michelson.Typed import Morley.Michelson.Untyped qualified as U@@ -56,7 +54,7 @@ [ (smartContractAddr1, buildSmartContractState "lol" (testContract @Natural)) , (smartContractAddr2, buildSmartContractState "kek" (testContract @Bool)) ]- , fsImplicits = fromList $ one (genesisAddress1, dumbImplicitState)+ , fsImplicits = fromList $ one $ genesisState @1 } test_parameterTypeGetUnit :: TestTree@@ -74,7 +72,7 @@ (runFakeTest chainOperationHandlers fakeStateWithSmartContracts $ getContractsParameterTypes [smartContractAddr3]- ) $ Map.empty+ ) mempty ] where expectContractMap
+ test/Test/Resolve.hs view
@@ -0,0 +1,117 @@+-- SPDX-FileCopyrightText: 2023 Oxhead Alpha+-- SPDX-License-Identifier: LicenseRef-MIT-OA++module Test.Resolve+ ( test_Resolve_calls+ ) where++import Test.HUnit ((@?=))+import Test.Tasty (TestTree)+import Test.Tasty.HUnit (testCase)++import Lorentz qualified as L+import Morley.Client (AliasBehavior(..))+import Morley.Client.Action.Batched+import Morley.Client.Action.Common+import Morley.Client.Action.Delegation+import Morley.Client.Action.Origination+import Morley.Client.Action.Reveal+import Morley.Client.Action.Transaction+import Morley.Client.Types+import Morley.Michelson.Untyped.Entrypoints+import Morley.Tezos.Address+import Morley.Tezos.Core (tz)+import Test.Addresses+import Test.Util+import TestM++fakeState :: Bool -> FakeState+fakeState initRevealed = defaultFakeState+ { fsContracts = fromList $ one $ (contractAddress2, dumbContractState)+ , fsImplicits = fromList $ one $ second revelation $ genesisState @1+ }+ where+ revelation | initRevealed = revealKeyState+ | otherwise = id++countAliasStoreCalls :: Handlers (TestT (State Word))+countAliasStoreCalls = chainOperationHandlers+ { hGetAliasesAndAddresses = do+ liftToFakeTest $ modify (+1)+ hGetAliasesAndAddresses chainOperationHandlers+ }++runAliasStoreCounterTest :: HasCallStack => Bool -> TestT (State Word) a -> Word+runAliasStoreCounterTest initRevealed action = do+ let (res, count) =+ usingState 0 $ runFakeTestT countAliasStoreCalls (fakeState initRevealed) action+ case res of+ Left e -> error . toText $ "Test action failed: " <> displayException e+ Right _ -> count++averageContract :: L.Contract () () ()+averageContract = L.defaultContract $ L.car L.# L.nil L.# L.pair++test_Resolve_calls :: [TestTree]+test_Resolve_calls =+ [ testCase "One transaction" $+ let storeCalls =+ runAliasStoreCounterTest True $+ lTransfer addr1 contractAddress2+ [tz|10u|] DefEpName () Nothing+ in storeCalls @?= 1 -- one call in operations log.++ , testCase "One origination"+ let storeCalls =+ runAliasStoreCounterTest True $+ lOriginateContract OverwriteDuplicateAlias "c"+ addr1 [tz|10u|]+ averageContract () Nothing Nothing+ in storeCalls @?= 0++ , testCase "One revelation"+ let storeCalls =+ runAliasStoreCounterTest False $ revealKey addr1+ in storeCalls @?= 1 -- one call in operations log.++ , testCase "One delegation"+ let storeCalls =+ runAliasStoreCounterTest True $ registerDelegateOp addr1+ in storeCalls @?= 1 -- one call in operations log.++ , testCase "Mix"+ let storeCalls = runAliasStoreCounterTest False do+ revealKeyUnlessRevealed addr1+ registerDelegateOp addr1+ lOriginateContract OverwriteDuplicateAlias "c" addr1 [tz|10u|] averageContract ()+ Nothing Nothing+ lTransfer addr1 contractAddress2 [tz|10u|] DefEpName () Nothing+ in storeCalls @?= 3 -- one per injection except origination++ , testCase "Batch"+ let storeCalls = runAliasStoreCounterTest False do+ void $ runOperationsBatch addr1 $ do+ delegateM $ DelegationData (Just $ unImplicitAddress $ awaAddress addr1) Nothing+ originateContractM OriginationData+ { odAliasBehavior = OverwriteDuplicateAlias+ , odName = "c"+ , odContract = L.toMichelsonContract averageContract+ , odStorage = L.toVal ()+ , odDelegate = Nothing+ , odMbFee = Nothing+ , odBalance = [tz|10u|] }+ runTransactionM $ TransactionData TD+ { tdParam = L.toVal ()+ , tdReceiver = Constrained contractAddress2+ , tdAmount = [tz|10u|]+ , tdEpName = DefEpName+ , tdMbFee = Nothing+ }+ pure ()+ in storeCalls @?= 1 -- one per batch+++ ]++addr1 :: ImplicitAddressWithAlias+addr1 = addrAndAliasFromGenesisState @1
test/Test/Transaction.hs view
@@ -5,14 +5,13 @@ ( test_lRunTransactionsUnit ) where -import Test.HUnit (Assertion, assertFailure) import Test.Hspec.Expectations (shouldThrow)+import Test.HUnit (Assertion, assertFailure) import Test.Tasty (TestTree, testGroup) import Test.Tasty.HUnit (testCase) -import Morley.Client (ResolveError(..), TezosClientError(..)) import Morley.Client.Action.Transaction-import Morley.Michelson.Runtime.GState (genesisAddress1, genesisAddress3)+import Morley.Michelson.Runtime.GState (genesisAddress3) import Morley.Michelson.Untyped.Entrypoints import Morley.Tezos.Core (tz) import Test.Addresses@@ -23,25 +22,27 @@ :: FakeState fakeState = defaultFakeState { fsContracts = fromList $ one (contractAddress2, dumbContractState)- , fsImplicits = fromList $ one (genesisAddress1, dumbImplicitState)+ , fsImplicits = fromList $ one $ genesisState @1 } test_lRunTransactionsUnit :: TestTree test_lRunTransactionsUnit = testGroup "Fake test transaction sending" [ testCase "Successful transaction" $ handleSuccess $ runFakeTest chainOperationHandlers fakeState $- lTransfer genesisAddress1 contractAddress2+ lTransfer addr1 contractAddress2 [tz|10u|] DefEpName () Nothing , testCase "Sender doesn't exist" $ handleUnknownContract $ runFakeTest chainOperationHandlers fakeState $- lTransfer genesisAddress3 contractAddress2+ lTransfer addr3 contractAddress2 [tz|10u|] DefEpName () Nothing , testCase "Destination doesn't exist" $ handleUnknownContract $ runFakeTest chainOperationHandlers fakeState $- lTransfer genesisAddress1 genesisAddress3+ lTransfer addr1 genesisAddress3 [tz|10u|] DefEpName () Nothing ] where+ addr1 = addrAndAliasFromGenesisState @1+ addr3 = addrAndAliasFromGenesisState @3 handleSuccess :: Either SomeException a -> Assertion handleSuccess (Right _) = pass handleSuccess (Left e) = assertFailure $ displayException e@@ -51,5 +52,5 @@ assertFailure "Transaction sending unexpectedly didn't fail." handleUnknownContract (Left e) = shouldThrow (throwM e) $ \case- ResolveError REAddressNotFound{} -> True+ UnknownAccount{} -> True _ -> False
test/Test/Util.hs view
@@ -5,10 +5,11 @@ module Test.Util ( chainOperationHandlers , dumbContractState- , dumbImplicitState- , dumbManagerKey , mapToContractStateBigMap , handleGetBigMapValue+ , genesisState+ , revealKeyState+ , addrAndAliasFromGenesisState -- * Internals , handleRunOperationInternal@@ -16,11 +17,9 @@ ) where import Control.Exception.Safe (throwString)-import Control.Lens (at, (?~))+import Control.Lens (at, (?=), (?~)) import Data.Aeson (encode)-import Data.ByteArray (ScrubbedBytes) import Data.ByteString.Lazy qualified as LBS (toStrict)-import Data.Map as Map (elems, insert, lookup, toList) import Data.Singletons (demote) import Fmt (pretty, (+|), (|+)) import Network.HTTP.Types.Status (status404)@@ -36,6 +35,7 @@ import Morley.Client.TezosClient (AliasBehavior(..), TezosClientError(DuplicateAlias)) import Morley.Client.Types import Morley.Micheline+import Morley.Michelson.Runtime.GState import Morley.Michelson.Typed import Morley.Tezos.Address import Morley.Tezos.Address.Alias@@ -43,6 +43,8 @@ import Morley.Tezos.Crypto import Morley.Tezos.Crypto.Ed25519 qualified as Ed25519 import Morley.Util.ByteString+import Morley.Util.Peano+import Morley.Util.SizedList qualified as Sized import TestM -- | Function to convert given map to big map representation@@ -54,8 +56,7 @@ { csbmKeyType = toExpression $ demote @(ToT k) , csbmValueType = toExpression $ demote @(ToT v) , csbmMap = fromList $- map (bimap (encodeBase58Check . valueToScriptExpr) lEncodeValue) $- Map.toList map'+ map (bimap (encodeBase58Check . valueToScriptExpr) lEncodeValue) $ toPairs map' , csbmId = bigMapId } @@ -72,12 +73,12 @@ Nothing } -dumbImplicitState :: AccountState 'AddressKindImplicit-dumbImplicitState = AccountState+dumbImplicitState :: PublicKey -> (ImplicitAddress, AccountState 'AddressKindImplicit)+dumbImplicitState pk = (mkKeyAddress pk, AccountState { asCounter = 100500 , asAlias = "genesis1"- , asAccountData = ImplicitData Nothing- }+ , asAccountData = ImplicitData pk Nothing+ }) -- | Fake handlers used for transaction sending and contract origination. chainOperationHandlers :: Monad m => Handlers (TestT m)@@ -99,22 +100,24 @@ , hGetKeyPassword = \_ -> pure Nothing , hGenKey = handleGenKey , hGetManagerKey = handleGetManagerKey- , hRevealKey = handleRevealKey+ , hGetPublicKey = handleGetPublicKey } where testSecretKey :: Ed25519.SecretKey testSecretKey = Ed25519.detSecretKey "\001\002\003\004" -mkRunOperationResult :: [ContractAddress] -> RunOperationResult-mkRunOperationResult originatedContracts = RunOperationResult- { rrOperationContents =- one $ OperationContent $ RunMetadata- { rmOperationResult = OperationApplied $- AppliedResult 100500 100500 100500 originatedContracts 0- , rmInternalOperationResults = []- }+mkRunOperationResult :: NonEmpty AppliedResult -> RunOperationResult+mkRunOperationResult results = RunOperationResult+ { rrOperationContents = results <&> \ar ->+ OperationContent $ RunMetadata+ { rmOperationResult = OperationApplied ar+ , rmInternalOperationResults = []+ } } +mkAppliedResult :: [ContractAddress] -> AppliedResult+mkAppliedResult originatedContracts = AppliedResult 100500 100500 100500 originatedContracts 0+ handleGetBlockHash :: Monad m => BlockId -> TestT m BlockHash handleGetBlockHash blkId = do unless (blkId == FinalHeadId) do@@ -130,8 +133,7 @@ => BlockId -> ImplicitAddress -> m TezosInt64 handleGetCounter blk addr = do assertHeadBlockId blk- FakeState{..} <- get- case lookup addr fsImplicits of+ use (fsImplicitsL . at addr) >>= \case Nothing -> throwM $ UnknownAccount $ Constrained addr Just AccountState{..} -> pure $ asCounter @@ -160,8 +162,7 @@ -- https://web.archive.org/web/20220305165609/https://tezos.gitlab.io/protocols/tenderbake.html unless (roiBranch roOperation == fsFinalHeadBlock) do throwM $ InvalidBranch $ roiBranch roOperation- originatedContracts <- handleRunOperationInternal roOperation- pure $ mkRunOperationResult originatedContracts+ mkRunOperationResult <$> handleRunOperationInternal roOperation handlePreApplyOperation :: Monad m => BlockId -> PreApplyOperation -> TestT m RunOperationResult handlePreApplyOperation blk PreApplyOperation{..} = do@@ -174,8 +175,8 @@ -- https://web.archive.org/web/20220305165609/https://tezos.gitlab.io/protocols/tenderbake.html unless (paoBranch == fsFinalHeadBlock) do throwM $ InvalidBranch paoBranch- originatedContracts <- concatMapM handleTransactionOrOrigination paoContents- pure $ mkRunOperationResult originatedContracts+ results <- handleOperationInput paoContents+ pure $ mkRunOperationResult results handleForgeOperation :: Monad m => BlockId -> ForgeOperation -> TestT m HexJSONByteString handleForgeOperation blkId op = do@@ -187,42 +188,40 @@ throwM $ InvalidBranch $ foBranch op pure . HexJSONByteString . LBS.toStrict . encode $ op -handleRunOperationInternal :: Monad m => RunOperationInternal -> TestT m [ContractAddress]-handleRunOperationInternal RunOperationInternal{..} = do- concatMapM handleTransactionOrOrigination roiContents+handleRunOperationInternal :: Monad m => RunOperationInternal -> TestT m (NonEmpty AppliedResult)+handleRunOperationInternal RunOperationInternal{roiContents} = handleOperationInput roiContents +handleOperationInput :: Monad m => NonEmpty OperationInput -> TestT m (NonEmpty AppliedResult)+handleOperationInput (c :| cs) =+ (:|) <$> go c 1 <*> zipWithM go cs [2, 3..]+ where go = fmap mkAppliedResult ... handleTransactionOrOrigination+ handleTransactionOrOrigination- :: (Monad m, HasCallStack) => OperationInput -> TestT m [ContractAddress]-handleTransactionOrOrigination op = do+ :: forall m. (Monad m, HasCallStack) => OperationInput -> TezosInt64 -> TestT m [ContractAddress]+handleTransactionOrOrigination op n = do FakeState{..} <- get+ AccountState{..} <-+ maybe (throwM $ UnknownAccount $ Constrained codSource) pure $ fsImplicits ^. at codSource+ unless ((asCounter + n) == codCounter) $ throwM CounterMismatch+ let checkContractExists :: Address -> TestT m ()+ checkContractExists dest'@(MkAddress dest) = case dest of+ ContractAddress{} -> when (isNothing $ fsContracts ^. at dest) $+ throwM $ UnknownAccount dest'+ ImplicitAddress{} -> when (isNothing $ fsImplicits ^. at dest) $+ throwM $ UnknownAccount dest'+ SmartRollupAddress{} -> error "smart rollup unsupported" case wcoCustom op of- -- Ensure that transaction sender exists- OpTransfer TransactionOperation{..} -> case lookup codSource fsImplicits of- Nothing -> throwM $ UnknownAccount $ Constrained codSource- Just AccountState{..} -> do- -- Ensure that sender counter matches- unless (asCounter + 1 == codCounter) (throwM CounterMismatch)- case toDestination of- MkAddress dest@ContractAddress{} ->- case lookup dest fsContracts of- Nothing -> throwM $ UnknownAccount $ Constrained dest- Just _ -> pure []- MkAddress dest@ImplicitAddress{} ->- case lookup dest fsImplicits of- Nothing -> throwM $ UnknownAccount $ Constrained dest- Just _ -> pure []- MkAddress TxRollupAddress{} -> error "tx rollup unsupported"- -- Ensure that originator exists- OpOriginate _ -> case lookup codSource fsImplicits of- Nothing -> throwM $ UnknownAccount $ Constrained codSource- Just AccountState{..} -> do- -- Ensure that originator counter matches- unless (asCounter + 1 == codCounter) (throwM CounterMismatch)- pure [dummyContractAddr]- where- dummyContractAddr = [ta|KT1LZwEZqbqtLYhwzaidBp6So9LgYDpkpEv7|]- OpReveal _ ->- -- We do not care about reveals at the moment+ OpTransfer TransactionOperation{toDestination} -> do+ checkContractExists toDestination+ pure []+ OpTransferTicket TransferTicketOperation{ttoDestination} -> do+ checkContractExists ttoDestination+ pure []+ OpOriginate{} ->+ pure [[ta|KT1LZwEZqbqtLYhwzaidBp6So9LgYDpkpEv7|]]+ OpReveal RevealOperation{..} -> do+ let addr = mkKeyAddress roPublicKey+ modify $ fsImplicitsL . at addr %~ fmap revealKeyState return [] OpDelegation _ -> -- We do not care about delegations at the moment@@ -244,8 +243,7 @@ -> m OriginationScript handleGetContractScript blockId addr = do assertHeadBlockId blockId- FakeState{..} <- get- case lookup addr fsContracts of+ use (fsContractsL . at addr) >>= \case Nothing -> throwM $ err404 path Just AccountState{..} -> case asAccountData of ContractData script _ -> pure script@@ -259,7 +257,7 @@ let allBigMaps :: [ContractStateBigMap] = catMaybes $- Map.elems (fsContracts st) <&> \cs -> case (asAccountData cs) of+ toList (fsContracts st) <&> \cs -> case (asAccountData cs) of ContractData _ bigMapMaybe -> bigMapMaybe -- Check if a big_map with the given ID exists and, if so, check@@ -267,7 +265,7 @@ case find (\bigMap -> csbmId bigMap == bigMapId) allBigMaps of Nothing -> throwM $ err404 path Just bigMap ->- case lookup scriptExpr (csbmMap bigMap ) of+ case csbmMap bigMap ^. at scriptExpr of Nothing -> throwM $ err404 path Just serializedValue -> pure $ decodeExpression serializedValue where@@ -278,25 +276,22 @@ handleRememberContract replaceExisting addr alias = do let cs = dumbContractState { asAlias = alias }- remember addr' cs' FakeState{..} =- modify $ \s -> s { fsContracts = insert addr' cs' fsContracts }+ remember addr' cs' = fsContractsL . at addr' ?= cs' - st@FakeState{..} <- get- case lookup addr fsContracts of- Nothing -> remember addr cs st+ use (fsContractsL . at addr) >>= \case+ Nothing -> remember addr cs _ -> case replaceExisting of KeepDuplicateAlias -> pass- OverwriteDuplicateAlias -> remember addr cs st+ OverwriteDuplicateAlias -> remember addr cs ForbidDuplicateAlias -> throwM $ DuplicateAlias $ unAlias alias -handleGenKey :: Monad m => ImplicitAlias -> TestT m ImplicitAddress+handleGenKey :: Monad m => ImplicitAlias -> TestT m ImplicitAddressWithAlias handleGenKey alias = do let- addr = detGenKeyAddress (encodeUtf8 $ unAlias alias)- newAccountState = dumbImplicitState { asAlias = alias }- modify $ \s ->- s & fsImplicitsL . at addr ?~ newAccountState- pure addr+ pk = toPublic . detSecretKey . encodeUtf8 $ unAlias alias+ (addr, newAccountState) = dumbImplicitState pk+ modify $ fsImplicitsL . at addr ?~ newAccountState{ asAlias = alias }+ pure $ AddressWithAlias addr alias handleGetAliasesAndAddresses :: forall m. Monad m@@ -307,7 +302,7 @@ where convert :: Map (KindedAddress kind) (AccountState kind) -> [(Text, Text)] convert m =- Map.toList m <&> \(addr, AccountState{asAlias}) -> (pretty asAlias, pretty addr)+ toPairs m <&> \(addr, AccountState{asAlias}) -> (pretty asAlias, pretty addr) handleGetManagerKey :: (Monad m) => BlockId -> ImplicitAddress -> TestT m (Maybe PublicKey) handleGetManagerKey blk addr = do@@ -315,8 +310,7 @@ s <- get let mbCs = s ^. fsImplicitsL . at addr case mbCs of- Just AccountState{..} -> case asAccountData of- ImplicitData mbManagerKey -> pure mbManagerKey+ Just AccountState{..} -> pure $ idManagerKey asAccountData Nothing -> throwM $ UnknownAccount $ Constrained addr -- In scenarios where the system under test checks for 404 errors, we@@ -339,25 +333,32 @@ , responseBody = "Contract with given address not found" } -handleRevealKey :: Monad m => ImplicitAlias -> Maybe ScrubbedBytes -> TestT m ()-handleRevealKey alias _ = do- accounts <- gets (Map.toList . fsImplicits)- let accounts' = filter (\(_, AccountState{..}) -> asAlias == alias) accounts+handleGetPublicKey :: Monad m => ImplicitAddressWithAlias -> TestT m PublicKey+handleGetPublicKey aaa@(AddressWithAlias addr alias) = do+ accounts <- gets (toPairs . fsImplicits)+ let accounts' = filter check accounts+ check (addr', AccountState{..}) = addr' == addr && asAlias == alias case accounts' of- [] -> throwM $ UnknownAlias alias- [(addr, cs@AccountState{..})] ->- case asAccountData of- ImplicitData (Just _) ->- throwM $ AlreadyRevealed $ MkAddress addr- ImplicitData Nothing ->- -- We don't care about the public key itself, but only its presence.- let newAccountState = cs { asAccountData = ImplicitData $ Just dumbManagerKey }- in modify $ \s -> s & fsImplicitsL . at addr ?~ newAccountState+ [] -> throwM $ UnknownAccount $ Constrained addr+ [(_, AccountState{..})] -> pure $ idPublicKey asAccountData _ ->- error $ "Multiple accounts have alias '" +| alias |++ error $ "Multiple accounts found for '" +| aaa |+ "'. This is most likely a bug in tests." --- | Dummy public key used in fake tests.-dumbManagerKey :: PublicKey-dumbManagerKey = fromRight (error "impossible") $ parsePublicKey- "edpkuwTWKgQNnhR5v17H2DYHbfcxYepARyrPGbf1tbMoGQAj8Ljr3V"+genesisPk :: forall n. (SingIPeano n, ToPeano 10 > ToPeano n ~ 'True) => PublicKey+genesisPk = toPublic $ Sized.index @n genesisSecrets++genesisState+ :: forall n. (SingIPeano n, ToPeano 10 > ToPeano n ~ 'True)+ => (ImplicitAddress, AccountState 'AddressKindImplicit)+genesisState = dumbImplicitState $ genesisPk @n++addrAndAliasFromGenesisState+ :: forall n. (SingIPeano n, ToPeano 10 > ToPeano n ~ 'True)+ => ImplicitAddressWithAlias+addrAndAliasFromGenesisState =+ let (addr, AccountState{asAlias}) = genesisState @n+ in AddressWithAlias addr asAlias++revealKeyState :: AccountState 'AddressKindImplicit -> AccountState 'AddressKindImplicit+revealKeyState = asAccountDataL %~ \x@ImplicitData{..} -> x{ idManagerKey = Just idPublicKey }
test/TestM.hs view
@@ -23,6 +23,8 @@ -- * Lens , fsImplicitsL+ , fsContractsL+ , asAccountDataL ) where import Colog.Core.Class (HasLog(..))@@ -78,16 +80,18 @@ , hGetChainId :: m ChainId , hGetManagerKey :: BlockId -> ImplicitAddress -> m (Maybe PublicKey) , hGetDelegateAtBlock :: BlockId -> L1Address -> m (Maybe KeyHash)+ , hGetTicketBalanceAtBlock :: BlockId -> Address -> GetTicketBalance -> m Natural+ , hGetAllTicketBalancesAtBlock :: BlockId -> ContractAddress -> m [GetAllTicketBalancesResponse] -- HasTezosClient- , hSignBytes :: ImplicitAddressOrAlias -> Maybe ScrubbedBytes -> ByteString -> m Signature- , hGenKey :: ImplicitAlias -> m ImplicitAddress- , hGenFreshKey :: ImplicitAlias -> m ImplicitAddress- , hRevealKey :: ImplicitAlias -> Maybe ScrubbedBytes -> m ()+ , hSignBytes :: ImplicitAddressWithAlias -> Maybe ScrubbedBytes -> ByteString -> m Signature+ , hGenKey :: ImplicitAlias -> m ImplicitAddressWithAlias+ , hGenFreshKey :: ImplicitAlias -> m ImplicitAddressWithAlias+ , hGetPublicKey :: ImplicitAddressWithAlias -> m PublicKey , hWaitForOperation :: m OperationHash -> m OperationHash , hRememberContract :: AliasBehavior -> ContractAddress -> ContractAlias -> m () , hGetAliasesAndAddresses :: m [(Text, Text)]- , hGetKeyPassword :: ImplicitAddress -> m (Maybe ScrubbedBytes)+ , hGetKeyPassword :: ImplicitAddressWithAlias -> m (Maybe ScrubbedBytes) -- HasLog , hLogAction :: ClientLogAction m@@ -120,12 +124,15 @@ , hSignBytes = \_ _ _ -> throwM $ UnexpectedClientCall "signBytes" , hGenKey = \_ -> throwM $ UnexpectedClientCall "genKey" , hGenFreshKey = \_ -> throwM $ UnexpectedRpcCall "genFreshKey"- , hRevealKey = \_ _ -> throwM $ UnexpectedClientCall "revealKey"+ , hGetPublicKey = \_ -> throwM $ UnexpectedClientCall "getPublicKey" , hWaitForOperation = \_ -> throwM $ UnexpectedRpcCall "waitForOperation"- , hRememberContract = \_ _ _ -> throwM $ UnexpectedClientCall "hRememberContract"+ , hRememberContract = \_ _ _ -> throwM $ UnexpectedClientCall "rememberContract" , hGetAliasesAndAddresses = throwM $ UnexpectedRpcCall "getAliasesAndAddresses" , hGetKeyPassword = \_ -> throwM $ UnexpectedClientCall "getKeyPassword" + , hGetTicketBalanceAtBlock = \_ _ _ -> throwM $ UnexpectedClientCall "getTicketBalanceAtBlock"+ , hGetAllTicketBalancesAtBlock = \_ _ -> throwM $ UnexpectedClientCall "getAllTicketBalancesAtBlock"+ , hLogAction = mempty } @@ -138,8 +145,14 @@ } data AccountData k where- ContractData :: OriginationScript -> Maybe ContractStateBigMap -> AccountData 'AddressKindContract- ImplicitData :: Maybe PublicKey -> AccountData 'AddressKindImplicit+ ContractData ::+ { cdScript :: OriginationScript+ , cdBigMap :: Maybe ContractStateBigMap+ } -> AccountData 'AddressKindContract+ ImplicitData ::+ { idPublicKey :: PublicKey+ , idManagerKey :: Maybe PublicKey+ } -> AccountData 'AddressKindImplicit -- | Type to represent big_map in @AccountState@. data ContractStateBigMap = ContractStateBigMap@@ -218,11 +231,9 @@ -- | Various fake test errors. data TestError- = AlreadyRevealed Address- | UnexpectedRpcCall Text+ = UnexpectedRpcCall Text | UnexpectedClientCall Text | UnknownAccount Address- | UnknownAlias ImplicitAlias | ContractDoesntHaveBigMap Address | InvalidChainId | InvalidProtocol@@ -247,9 +258,6 @@ genFreshKey alias = do h <- getHandler hGenFreshKey h alias- revealKey alias mbPassword = do- h <- getHandler hRevealKey- h alias mbPassword rememberContract replaceExisting addr alias = do h <- getHandler hRememberContract h replaceExisting addr alias@@ -258,6 +266,9 @@ getKeyPassword addr = do h <- getHandler hGetKeyPassword h addr+ getPublicKey addrOrAlias = do+ h <- getHandler hGetPublicKey+ h addrOrAlias instance Monad m => HasTezosRpc (TestT m) where getBlockHash block = do@@ -327,5 +338,12 @@ waitForOperation opHash = do h <- getHandler hWaitForOperation h opHash+ getTicketBalanceAtBlock block addr args = do+ h <- getHandler hGetTicketBalanceAtBlock+ h block addr args+ getAllTicketBalancesAtBlock block addr = do+ h <- getHandler hGetAllTicketBalancesAtBlock+ h block addr -makeLensesFor [("fsImplicits", "fsImplicitsL")] ''FakeState+makeLensesFor [("fsImplicits", "fsImplicitsL"), ("fsContracts", "fsContractsL")] ''FakeState+makeLensesFor [("asAccountData", "asAccountDataL")] ''AccountState
test/data/constants.json view
@@ -9,34 +9,35 @@ "max_allowed_global_constants_depth": 10000, "cache_layout_size": 3, "michelson_maximum_type_size": 2001,- "sc_max_wrapped_proof_binary_size": 30000,- "sc_rollup_message_size_limit": 4096,+ "smart_rollup_max_wrapped_proof_binary_size": 30000,+ "smart_rollup_message_size_limit": 4096,+ "smart_rollup_max_number_of_messages_per_level": "1000000", "preserved_cycles": 3,- "blocks_per_cycle": 4096,- "blocks_per_commitment": 32,- "nonce_revelation_threshold": 256,- "blocks_per_stake_snapshot": 256,+ "blocks_per_cycle": 8192,+ "blocks_per_commitment": 64,+ "nonce_revelation_threshold": 512,+ "blocks_per_stake_snapshot": 512, "cycles_per_voting_period": 1, "hard_gas_limit_per_operation": "1040000",- "hard_gas_limit_per_block": "5200000",+ "hard_gas_limit_per_block": "2600000", "proof_of_work_threshold": "-1", "minimal_stake": "6000000000",- "vdf_difficulty": "2000000000",+ "vdf_difficulty": "10000000000", "seed_nonce_revelation_tip": "125000", "origination_size": 257,- "baking_reward_fixed_portion": "10000000",- "baking_reward_bonus_per_slot": "4286",- "endorsing_reward_per_slot": "2857",+ "baking_reward_fixed_portion": "2666666",+ "baking_reward_bonus_per_slot": "1143",+ "endorsing_reward_per_slot": "761", "cost_per_byte": "250", "hard_storage_limit_per_operation": "60000", "quorum_min": 2000, "quorum_max": 7000, "min_proposal_quorum": 500,- "liquidity_baking_subsidy": "2500000",+ "liquidity_baking_subsidy": "666666", "liquidity_baking_toggle_ema_threshold": 1000000000,- "max_operations_time_to_live": 120,- "minimal_block_delay": "15",- "delay_increment_per_round": "5",+ "max_operations_time_to_live": 240,+ "minimal_block_delay": "8",+ "delay_increment_per_round": "3", "consensus_committee_size": 7000, "consensus_threshold": 4667, "minimal_participation_ratio": {@@ -54,7 +55,7 @@ "cache_script_size": 100000000, "cache_stake_distribution_cycles": 8, "cache_sampler_state_cycles": 8,- "tx_rollup_enable": true,+ "tx_rollup_enable": false, "tx_rollup_origination_size": 4000, "tx_rollup_hard_size_limit_per_inbox": 500000, "tx_rollup_hard_size_limit_per_message": 5000,@@ -72,25 +73,26 @@ "dal_parametric": { "feature_enable": false, "number_of_slots": 256,- "number_of_shards": 2048,- "endorsement_lag": 1,+ "attestation_lag": 1, "availability_threshold": 50,- "slot_size": 1048576, "redundancy_factor": 16,- "page_size": 4096+ "page_size": 4096,+ "slot_size": 1048576,+ "number_of_shards": 2048 },- "sc_rollup_enable": false,- "sc_rollup_origination_size": 6314,- "sc_rollup_challenge_window_in_blocks": 20160,- "sc_rollup_max_number_of_messages_per_commitment_period": 300000000,- "sc_rollup_stake_amount": "10000000000",- "sc_rollup_commitment_period_in_blocks": 30,- "sc_rollup_max_lookahead_in_blocks": 30000,- "sc_rollup_max_active_outbox_levels": 20160,- "sc_rollup_max_outbox_messages_per_level": 100,- "sc_rollup_number_of_sections_in_dissection": 32,- "sc_rollup_timeout_period_in_blocks": 20160,- "sc_rollup_max_number_of_cemented_commitments": 5,+ "smart_rollup_enable": true,+ "smart_rollup_arith_pvm_enable": false,+ "smart_rollup_origination_size": 6314,+ "smart_rollup_challenge_window_in_blocks": 40,+ "smart_rollup_stake_amount": "10000000000",+ "smart_rollup_commitment_period_in_blocks": 20,+ "smart_rollup_max_lookahead_in_blocks": 30000,+ "smart_rollup_max_active_outbox_levels": 20160,+ "smart_rollup_max_outbox_messages_per_level": 100,+ "smart_rollup_number_of_sections_in_dissection": 32,+ "smart_rollup_timeout_period_in_blocks": 500,+ "smart_rollup_max_number_of_cemented_commitments": 5,+ "smart_rollup_max_number_of_parallel_games": 32, "zk_rollup_enable": false, "zk_rollup_origination_size": 4000, "zk_rollup_min_pending_to_process": 10