module Tendermint.SDK.Modules.Bank.Router
  ( MessageApi
  , messageHandlers
  ) where

import           Polysemy                             (Members, Sem)
import           Servant.API                          ((:<|>) (..))
import           Tendermint.SDK.BaseApp               ((:~>), Return, RouteTx,
                                                       RoutingTx (..),
                                                       TypedMessage)
import           Tendermint.SDK.Modules.Auth          (Coin (..))
import           Tendermint.SDK.Modules.Bank.Keeper   (BankEffs, burn, transfer)
import           Tendermint.SDK.Modules.Bank.Messages
import           Tendermint.SDK.Types.Message         (Msg (..))
import           Tendermint.SDK.Types.Transaction     (Tx (..))

type MessageApi =
       TypedMessage BurnMsg :~> Return ()
  :<|> TypedMessage TransferMsg :~> Return ()

messageHandlers
  ::Members BankEffs r
  => RouteTx MessageApi r
messageHandlers :: RouteTx MessageApi r
messageHandlers = RoutingTx BurnMsg -> Sem r ()
forall (r :: [(* -> *) -> * -> *]).
Members BankEffs r =>
RoutingTx BurnMsg -> Sem r ()
burnH (RoutingTx BurnMsg -> Sem r ())
-> (RoutingTx TransferMsg -> Sem r ())
-> (RoutingTx BurnMsg -> Sem r ())
   :<|> (RoutingTx TransferMsg -> Sem r ())
forall a b. a -> b -> a :<|> b
:<|> RoutingTx TransferMsg -> Sem r ()
forall (r :: [(* -> *) -> * -> *]).
Members BankEffs r =>
RoutingTx TransferMsg -> Sem r ()
transferH

transferH
  :: Members BankEffs r
  => RoutingTx TransferMsg
  -> Sem r ()
transferH :: RoutingTx TransferMsg -> Sem r ()
transferH (RoutingTx Tx{txMsg :: forall k (alg :: k) msg. Tx alg msg -> Msg msg
txMsg=Msg{TransferMsg
msgData :: forall msg. Msg msg -> msg
msgData :: TransferMsg
msgData}}) =
  let TransferMsg{..} = TransferMsg
msgData
      coin :: Coin
coin = CoinId -> Amount -> Coin
Coin CoinId
transferCoinId Amount
transferAmount
  in Address -> Coin -> Address -> Sem r ()
forall (r :: [(* -> *) -> * -> *]).
MemberWithError BankKeeper r =>
Address -> Coin -> Address -> Sem r ()
transfer Address
transferFrom Coin
coin Address
transferTo

burnH
  :: Members BankEffs r
  => RoutingTx BurnMsg
  -> Sem r ()
burnH :: RoutingTx BurnMsg -> Sem r ()
burnH (RoutingTx Tx{txMsg :: forall k (alg :: k) msg. Tx alg msg -> Msg msg
txMsg=Msg{BurnMsg
msgData :: BurnMsg
msgData :: forall msg. Msg msg -> msg
msgData}}) =
  let BurnMsg{..} = BurnMsg
msgData
      coin :: Coin
coin = CoinId -> Amount -> Coin
Coin CoinId
burnCoinId Amount
burnAmount
  in Address -> Coin -> Sem r ()
forall (r :: [(* -> *) -> * -> *]).
MemberWithError BankKeeper r =>
Address -> Coin -> Sem r ()
burn Address
burnAddress Coin
coin