module Tendermint.SDK.BaseApp.Transaction
  ( serveTxApplication
    -- * Re-Exports
  , module Tendermint.SDK.BaseApp.Transaction.Types
  , HasTxRouter(..)
  , emptyTxServer
  , DefaultCheckTx(..)
  , VoidReturn
  , TxEffs
  , evalReadOnly
  , AnteHandler
  ) where

import           Control.Lens                                   ((&), (.~))
import           Data.ByteString                                (ByteString)
import           Data.Default.Class                             (def)
import           Data.Proxy
import           Polysemy                                       (Sem)
import           Tendermint.SDK.BaseApp.Errors                  (makeAppError, txResultAppError)
import           Tendermint.SDK.BaseApp.Router                  (Application, RouteResult (..),
                                                                 emptyDelayed,
                                                                 runRouter)
import           Tendermint.SDK.BaseApp.Transaction.AnteHandler
import           Tendermint.SDK.BaseApp.Transaction.Cache       (Cache)
import           Tendermint.SDK.BaseApp.Transaction.Checker
import           Tendermint.SDK.BaseApp.Transaction.Effect
import           Tendermint.SDK.BaseApp.Transaction.Router
import           Tendermint.SDK.BaseApp.Transaction.Types
import           Tendermint.SDK.Types.Effects                   ((:&))
import           Tendermint.SDK.Types.TxResult                  (TxResult)

serveTxApplication
  :: HasTxRouter layout r scope
  => Proxy layout
  -> Proxy r
  -> Proxy scope
  -> RouteTx layout (TxEffs :& r)
  -> TransactionApplication (Sem r)
serveTxApplication :: Proxy layout
-> Proxy r
-> Proxy scope
-> RouteTx layout (TxEffs :& r)
-> TransactionApplication (Sem r)
serveTxApplication pl :: Proxy layout
pl pr :: Proxy r
pr ps :: Proxy scope
ps server :: RouteTx layout (TxEffs :& r)
server =
  Application (Sem r) (RoutingTx ByteString) (TxResult, Maybe Cache)
-> TransactionApplication (Sem r)
forall (r :: EffectRow).
Application (Sem r) (RoutingTx ByteString) (TxResult, Maybe Cache)
-> TransactionApplication (Sem r)
toTxApplication (Router () r (RoutingTx ByteString) (TxResult, Maybe Cache)
-> ()
-> Application
     (Sem r) (RoutingTx ByteString) (TxResult, Maybe Cache)
forall req env (r :: EffectRow) res.
HasPath req =>
Router env r req res -> env -> Application (Sem r) req res
runRouter (Proxy layout
-> Proxy r
-> Proxy scope
-> Delayed
     (Sem r) () (RoutingTx ByteString) (RouteTx layout (TxEffs :& r))
-> Router () r (RoutingTx ByteString) (TxResult, Maybe Cache)
forall k (layout :: k) (r :: EffectRow) (scope :: Scope) env.
HasTxRouter layout r scope =>
Proxy layout
-> Proxy r
-> Proxy scope
-> Delayed
     (Sem r) env (RoutingTx ByteString) (RouteTx layout (TxEffs :& r))
-> Router env r (RoutingTx ByteString) (TxResult, Maybe Cache)
routeTx Proxy layout
pl Proxy r
pr Proxy scope
ps (RouteResult
  (RouteTx
     layout
     (Output Event
        : GasMeter : WriteStore : ReadStore : Error AppError : r))
-> Delayed
     (Sem r)
     ()
     (RoutingTx ByteString)
     (RouteTx
        layout
        (Output Event
           : GasMeter : WriteStore : ReadStore : Error AppError : r))
forall (m :: * -> *) a b req.
Monad m =>
RouteResult a -> Delayed m b req a
emptyDelayed (RouteTx
  layout
  (Output Event
     : GasMeter : WriteStore : ReadStore : Error AppError : r)
-> RouteResult
     (RouteTx
        layout
        (Output Event
           : GasMeter : WriteStore : ReadStore : Error AppError : r))
forall a. a -> RouteResult a
Route RouteTx
  layout
  (Output Event
     : GasMeter : WriteStore : ReadStore : Error AppError : r)
RouteTx layout (TxEffs :& r)
server))) ())

toTxApplication
  :: Application (Sem r) (RoutingTx ByteString) (TxResult, Maybe Cache)
  -> TransactionApplication (Sem r)
toTxApplication :: Application (Sem r) (RoutingTx ByteString) (TxResult, Maybe Cache)
-> TransactionApplication (Sem r)
toTxApplication ra :: Application (Sem r) (RoutingTx ByteString) (TxResult, Maybe Cache)
ra tx :: RoutingTx ByteString
tx = do
  RouteResult (TxResult, Maybe Cache)
res <- Application (Sem r) (RoutingTx ByteString) (TxResult, Maybe Cache)
ra RoutingTx ByteString
tx
  case RouteResult (TxResult, Maybe Cache)
res of
    Fail e :: RouterError
e      -> (TxResult, Maybe Cache) -> Sem r (TxResult, Maybe Cache)
forall (f :: * -> *) a. Applicative f => a -> f a
pure (TxResult
forall a. Default a => a
def TxResult -> (TxResult -> TxResult) -> TxResult
forall a b. a -> (a -> b) -> b
& (AppError -> Identity AppError) -> TxResult -> Identity TxResult
Lens' TxResult AppError
txResultAppError ((AppError -> Identity AppError) -> TxResult -> Identity TxResult)
-> AppError -> TxResult -> TxResult
forall s t a b. ASetter s t a b -> b -> s -> t
.~ RouterError -> AppError
forall e. IsAppError e => e -> AppError
makeAppError RouterError
e, Maybe Cache
forall a. Maybe a
Nothing)
    FailFatal e :: RouterError
e -> (TxResult, Maybe Cache) -> Sem r (TxResult, Maybe Cache)
forall (f :: * -> *) a. Applicative f => a -> f a
pure (TxResult
forall a. Default a => a
def TxResult -> (TxResult -> TxResult) -> TxResult
forall a b. a -> (a -> b) -> b
& (AppError -> Identity AppError) -> TxResult -> Identity TxResult
Lens' TxResult AppError
txResultAppError ((AppError -> Identity AppError) -> TxResult -> Identity TxResult)
-> AppError -> TxResult -> TxResult
forall s t a b. ASetter s t a b -> b -> s -> t
.~ RouterError -> AppError
forall e. IsAppError e => e -> AppError
makeAppError RouterError
e, Maybe Cache
forall a. Maybe a
Nothing)
    Route a :: (TxResult, Maybe Cache)
a     -> (TxResult, Maybe Cache) -> Sem r (TxResult, Maybe Cache)
forall (f :: * -> *) a. Applicative f => a -> f a
pure (TxResult, Maybe Cache)
a