module Tendermint.SDK.Application.AnteHandler
( module Tendermint.SDK.Application.AnteHandler
, AnteHandler
) where
import Control.Monad (unless, void)
import Data.Foldable (fold)
import Data.Monoid (Endo (..))
import Polysemy
import Polysemy.Error (Error)
import Tendermint.SDK.BaseApp.Errors (AppError, SDKError (..),
throwSDKError)
import Tendermint.SDK.BaseApp.Transaction (AnteHandler,
RoutingTx (..))
import qualified Tendermint.SDK.Modules.Auth as A
import Tendermint.SDK.Types.Message (Msg (..))
import Tendermint.SDK.Types.Transaction (Tx (..))
createAccountAnteHandler
:: Members A.AuthEffs r
=> AnteHandler r
createAccountAnteHandler :: AnteHandler r
createAccountAnteHandler = ((RoutingTx msg -> Sem r a) -> RoutingTx msg -> Sem r a)
-> Endo (RoutingTx msg -> Sem r a)
forall a. (a -> a) -> Endo a
Endo (((RoutingTx msg -> Sem r a) -> RoutingTx msg -> Sem r a)
-> Endo (RoutingTx msg -> Sem r a))
-> ((RoutingTx msg -> Sem r a) -> RoutingTx msg -> Sem r a)
-> Endo (RoutingTx msg -> Sem r a)
forall a b. (a -> b) -> a -> b
$
\txApplication :: RoutingTx msg -> Sem r a
txApplication tx :: RoutingTx msg
tx@(RoutingTx Tx{..}) -> do
let Msg{Address
msgAuthor :: forall msg. Msg msg -> Address
msgAuthor :: Address
msgAuthor} = Msg msg
txMsg
Maybe Account
mAcnt <- Address -> Sem r (Maybe Account)
forall (r :: [Effect]).
MemberWithError Accounts r =>
Address -> Sem r (Maybe Account)
A.getAccount Address
msgAuthor
case Maybe Account
mAcnt of
Nothing -> Sem r Account -> Sem r ()
forall (f :: * -> *) a. Functor f => f a -> f ()
void (Sem r Account -> Sem r ()) -> Sem r Account -> Sem r ()
forall a b. (a -> b) -> a -> b
$ Address -> Sem r Account
forall (r :: [Effect]).
MemberWithError Accounts r =>
Address -> Sem r Account
A.createAccount Address
msgAuthor
_ -> () -> Sem r ()
forall (f :: * -> *) a. Applicative f => a -> f a
pure ()
RoutingTx msg -> Sem r a
txApplication RoutingTx msg
tx Sem r a -> (a -> Sem r a) -> Sem r a
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= a -> Sem r a
forall (f :: * -> *) a. Applicative f => a -> f a
pure
nonceAnteHandler
:: Members A.AuthEffs r
=> Member (Error AppError) r
=> AnteHandler r
nonceAnteHandler :: AnteHandler r
nonceAnteHandler = ((RoutingTx msg -> Sem r a) -> RoutingTx msg -> Sem r a)
-> Endo (RoutingTx msg -> Sem r a)
forall a. (a -> a) -> Endo a
Endo (((RoutingTx msg -> Sem r a) -> RoutingTx msg -> Sem r a)
-> Endo (RoutingTx msg -> Sem r a))
-> ((RoutingTx msg -> Sem r a) -> RoutingTx msg -> Sem r a)
-> Endo (RoutingTx msg -> Sem r a)
forall a b. (a -> b) -> a -> b
$
\txApplication :: RoutingTx msg -> Sem r a
txApplication tx :: RoutingTx msg
tx@(RoutingTx Tx{..}) -> do
let Msg{Address
msgAuthor :: Address
msgAuthor :: forall msg. Msg msg -> Address
msgAuthor} = Msg msg
txMsg
Maybe Account
preMAcnt <- Address -> Sem r (Maybe Account)
forall (r :: [Effect]).
MemberWithError Accounts r =>
Address -> Sem r (Maybe Account)
A.getAccount Address
msgAuthor
case Maybe Account
preMAcnt of
Just A.Account{Word64
accountNonce :: Account -> Word64
accountNonce :: Word64
accountNonce} -> do
let expectedNonce :: Word64
expectedNonce = Word64
accountNonce Word64 -> Word64 -> Word64
forall a. Num a => a -> a -> a
+ 1
Bool -> Sem r () -> Sem r ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
unless (Word64
txNonce Word64 -> Word64 -> Bool
forall a. Eq a => a -> a -> Bool
== Word64
expectedNonce) (Sem r () -> Sem r ()) -> Sem r () -> Sem r ()
forall a b. (a -> b) -> a -> b
$
SDKError -> Sem r ()
forall (r :: [Effect]) a.
Member (Error AppError) r =>
SDKError -> Sem r a
throwSDKError (Word64 -> Word64 -> SDKError
NonceException Word64
expectedNonce Word64
txNonce)
Nothing -> SDKError -> Sem r ()
forall (r :: [Effect]) a.
Member (Error AppError) r =>
SDKError -> Sem r a
throwSDKError (Address -> SDKError
UnknownAccountError Address
msgAuthor)
a
result <- RoutingTx msg -> Sem r a
txApplication RoutingTx msg
tx
Maybe Account
postMAcnt <- Address -> Sem r (Maybe Account)
forall (r :: [Effect]).
MemberWithError Accounts r =>
Address -> Sem r (Maybe Account)
A.getAccount Address
msgAuthor
case Maybe Account
postMAcnt of
Just A.Account{Word64
accountNonce :: Word64
accountNonce :: Account -> Word64
accountNonce} -> do
Address -> (Account -> Account) -> Sem r ()
forall (r :: [Effect]).
MemberWithError Accounts r =>
Address -> (Account -> Account) -> Sem r ()
A.updateAccount Address
msgAuthor ((Account -> Account) -> Sem r ())
-> (Account -> Account) -> Sem r ()
forall a b. (a -> b) -> a -> b
$ \a :: Account
a ->
Account
a { accountNonce :: Word64
A.accountNonce = Word64
accountNonce Word64 -> Word64 -> Word64
forall a. Num a => a -> a -> a
+ 1}
Nothing -> () -> Sem r ()
forall (f :: * -> *) a. Applicative f => a -> f a
pure ()
a -> Sem r a
forall (f :: * -> *) a. Applicative f => a -> f a
pure a
result
baseAppAnteHandler
:: Members A.AuthEffs r
=> Member (Error AppError) r
=> AnteHandler r
baseAppAnteHandler :: AnteHandler r
baseAppAnteHandler = [Endo (RoutingTx msg -> Sem r a)]
-> Endo (RoutingTx msg -> Sem r a)
forall (t :: * -> *) m. (Foldable t, Monoid m) => t m -> m
fold ([Endo (RoutingTx msg -> Sem r a)]
-> Endo (RoutingTx msg -> Sem r a))
-> [Endo (RoutingTx msg -> Sem r a)]
-> Endo (RoutingTx msg -> Sem r a)
forall a b. (a -> b) -> a -> b
$
[ Endo (RoutingTx msg -> Sem r a)
forall (r :: [Effect]). Members AuthEffs r => AnteHandler r
createAccountAnteHandler
, Endo (RoutingTx msg -> Sem r a)
forall (r :: [Effect]).
(Members AuthEffs r, Member (Error AppError) r) =>
AnteHandler r
nonceAnteHandler
]