-- SPDX-FileCopyrightText: 2021 Oxhead Alpha
-- SPDX-License-Identifier: LicenseRef-MIT-OA
-- | Functions to submit transactions via @tezos-client@ and node RPC.

module Morley.Client.Action.Transaction
  ( runTransactions
  , lRunTransactions

  -- * Transfer
  , transfer
  , lTransfer

  -- Datatypes for batch transactions
  , TD (..)
  , LTransactionData (..)
  , TransactionData (..)
  ) where

import Lorentz.Constraints
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.Types
import Morley.Client.TezosClient.Class
import Morley.Client.TezosClient.Types
import Morley.Client.Types
import Morley.Michelson.Typed qualified as T
import Morley.Michelson.Typed.Scope
import Morley.Michelson.Untyped.Entrypoints
import Morley.Tezos.Address
import Morley.Tezos.Core (Mutez)

-- | Perform sequence of transactions to the contract, each transactions should be
-- defined via @EntrypointParam t@. Returns operation hash and block in which
-- this operation appears or @Nothing@ in case empty list was provided.
runTransactions
  :: forall m env.
     ( HasTezosRpc m
     , HasTezosClient m
     , WithClientLog env m
     )
  => Address -> [TransactionData]
  -> m (Maybe OperationHash)
runTransactions :: Address -> [TransactionData] -> m (Maybe OperationHash)
runTransactions Address
sender [TransactionData]
transactions = do
  (Maybe OperationHash
opHash, [OperationInfo Result]
_) <- AddressOrAlias
-> [OperationInfo ClientInput]
-> m (Maybe OperationHash, [OperationInfo Result])
forall (m :: * -> *) env.
(HasTezosRpc m, HasTezosClient m, WithClientLog env m) =>
AddressOrAlias
-> [OperationInfo ClientInput]
-> m (Maybe OperationHash, [OperationInfo Result])
runOperations (Address -> AddressOrAlias
AddressResolved Address
sender) (TransactionData -> OperationInfo ClientInput
forall i. TransferInfo i -> OperationInfo i
OpTransfer (TransactionData -> OperationInfo ClientInput)
-> [TransactionData] -> [OperationInfo ClientInput]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [TransactionData]
transactions)
  Maybe OperationHash -> m (Maybe OperationHash)
forall (m :: * -> *) a. Monad m => a -> m a
return Maybe OperationHash
opHash

-- | Lorentz version of 'TransactionData'.
data LTransactionData where
  LTransactionData ::
    forall (t :: Type). NiceParameter t =>
    TD t -> LTransactionData

-- | Lorentz version of 'runTransactions'
lRunTransactions
  :: forall m env.
    ( HasTezosRpc m
    , HasTezosClient m
    , WithClientLog env m
    )
  => Address
  -> [LTransactionData]
  -> m (Maybe OperationHash)
lRunTransactions :: Address -> [LTransactionData] -> m (Maybe OperationHash)
lRunTransactions Address
sender [LTransactionData]
transactions =
  Address -> [TransactionData] -> m (Maybe OperationHash)
forall (m :: * -> *) env.
(HasTezosRpc m, HasTezosClient m, WithClientLog env m) =>
Address -> [TransactionData] -> m (Maybe OperationHash)
runTransactions Address
sender ([TransactionData] -> m (Maybe OperationHash))
-> [TransactionData] -> m (Maybe OperationHash)
forall a b. (a -> b) -> a -> b
$ (LTransactionData -> TransactionData)
-> [LTransactionData] -> [TransactionData]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
map LTransactionData -> TransactionData
convertLTransactionData [LTransactionData]
transactions
  where
    convertLTransactionData :: LTransactionData -> TransactionData
    convertLTransactionData :: LTransactionData -> TransactionData
convertLTransactionData (LTransactionData (TD {t
Maybe Mutez
Address
Mutez
EpName
tdMbFee :: forall t. TD t -> Maybe Mutez
tdParam :: forall t. TD t -> t
tdEpName :: forall t. TD t -> EpName
tdAmount :: forall t. TD t -> Mutez
tdReceiver :: forall t. TD t -> Address
tdMbFee :: Maybe Mutez
tdParam :: t
tdEpName :: EpName
tdAmount :: Mutez
tdReceiver :: Address
..} :: TD t))=
      (((SingI (ToT t), WellTyped (ToT t),
   FailOnOperationFound (ContainsOp (ToT t)),
   FailOnNestedBigMapsFound (ContainsNestedBigMaps (ToT t))),
  KnownValue t)
 :- ParameterScope (ToT t))
-> (ParameterScope (ToT t) => TransactionData) -> TransactionData
forall (c :: Constraint) e r. HasDict c e => e -> (c => r) -> r
withDict (((SingI (ToT t), WellTyped (ToT t),
  FailOnOperationFound (ContainsOp (ToT t)),
  FailOnNestedBigMapsFound (ContainsNestedBigMaps (ToT t))),
 KnownValue t)
:- ParameterScope (ToT t)
forall a. NiceParameter a :- ParameterScope (ToT a)
niceParameterEvi @t) ((ParameterScope (ToT t) => TransactionData) -> TransactionData)
-> (ParameterScope (ToT t) => TransactionData) -> TransactionData
forall a b. (a -> b) -> a -> b
$
      TD (Value (ToT t)) -> TransactionData
forall (t :: T).
ParameterScope t =>
TD (Value t) -> TransactionData
TransactionData TD :: forall t. Address -> Mutez -> EpName -> t -> Maybe Mutez -> TD t
TD
      { tdReceiver :: Address
tdReceiver = Address
tdReceiver
      , tdEpName :: EpName
tdEpName = EpName
tdEpName
      , tdAmount :: Mutez
tdAmount = Mutez
tdAmount
      , tdParam :: Value (ToT t)
tdParam = t -> Value (ToT t)
forall a. IsoValue a => a -> Value (ToT a)
T.toVal t
tdParam
      , tdMbFee :: Maybe Mutez
tdMbFee = Maybe Mutez
tdMbFee
      }

transfer
  :: forall m t env.
    ( HasTezosRpc m
    , HasTezosClient m
    , WithClientLog env m
    , ParameterScope t
    )
  => Address
  -> Address
  -> Mutez
  -> EpName
  -> T.Value t
  -> Maybe Mutez
  -> m OperationHash
transfer :: Address
-> Address
-> Mutez
-> EpName
-> Value t
-> Maybe Mutez
-> m OperationHash
transfer Address
from Address
to Mutez
amount EpName
epName Value t
param Maybe Mutez
mbFee = do
  Maybe OperationHash
res <- Address -> [TransactionData] -> m (Maybe OperationHash)
forall (m :: * -> *) env.
(HasTezosRpc m, HasTezosClient m, WithClientLog env m) =>
Address -> [TransactionData] -> m (Maybe OperationHash)
runTransactions Address
from ([TransactionData] -> m (Maybe OperationHash))
-> [TransactionData] -> m (Maybe OperationHash)
forall a b. (a -> b) -> a -> b
$
    [TD (Value t) -> TransactionData
forall (t :: T).
ParameterScope t =>
TD (Value t) -> TransactionData
TransactionData TD :: forall t. Address -> Mutez -> EpName -> t -> Maybe Mutez -> TD t
TD
      { tdReceiver :: Address
tdReceiver = Address
to
      , tdAmount :: Mutez
tdAmount = Mutez
amount
      , tdEpName :: EpName
tdEpName = EpName
epName
      , tdParam :: Value t
tdParam = Value t
param
      , tdMbFee :: Maybe Mutez
tdMbFee = Maybe Mutez
mbFee
      }
    ]
  case Maybe OperationHash
res of
    Just OperationHash
hash -> OperationHash -> m OperationHash
forall (m :: * -> *) a. Monad m => a -> m a
return OperationHash
hash
    Maybe OperationHash
_ -> IncorrectRpcResponse -> m OperationHash
forall (m :: * -> *) e a. (MonadThrow m, Exception e) => e -> m a
throwM IncorrectRpcResponse
RpcNoOperationsRun

lTransfer
  :: forall m t env.
    ( HasTezosRpc m
    , HasTezosClient m
    , WithClientLog env m
    , NiceParameter t
    )
  => Address
  -> Address
  -> Mutez
  -> EpName
  -> t
  -> Maybe Mutez
  -> m OperationHash
lTransfer :: Address
-> Address
-> Mutez
-> EpName
-> t
-> Maybe Mutez
-> m OperationHash
lTransfer Address
from Address
to Mutez
amount EpName
epName t
param Maybe Mutez
mbFee =
  (((SingI (ToT t), WellTyped (ToT t),
   FailOnOperationFound (ContainsOp (ToT t)),
   FailOnNestedBigMapsFound (ContainsNestedBigMaps (ToT t))),
  KnownValue t)
 :- ParameterScope (ToT t))
-> (ParameterScope (ToT t) => m OperationHash) -> m OperationHash
forall (c :: Constraint) e r. HasDict c e => e -> (c => r) -> r
withDict (((SingI (ToT t), WellTyped (ToT t),
  FailOnOperationFound (ContainsOp (ToT t)),
  FailOnNestedBigMapsFound (ContainsNestedBigMaps (ToT t))),
 KnownValue t)
:- ParameterScope (ToT t)
forall a. NiceParameter a :- ParameterScope (ToT a)
niceParameterEvi @t) ((ParameterScope (ToT t) => m OperationHash) -> m OperationHash)
-> (ParameterScope (ToT t) => m OperationHash) -> m OperationHash
forall a b. (a -> b) -> a -> b
$
    Address
-> Address
-> Mutez
-> EpName
-> Value (ToT t)
-> Maybe Mutez
-> m OperationHash
forall (m :: * -> *) (t :: T) env.
(HasTezosRpc m, HasTezosClient m, WithClientLog env m,
 ParameterScope t) =>
Address
-> Address
-> Mutez
-> EpName
-> Value t
-> Maybe Mutez
-> m OperationHash
transfer Address
from Address
to Mutez
amount EpName
epName (t -> Value (ToT t)
forall a. IsoValue a => a -> Value (ToT a)
T.toVal t
param) Maybe Mutez
mbFee