module Tendermint.SDK.Application.App
  ( createIOApp
  ) where

import           Control.Exception
import           Control.Lens                         ((&), (.~))
import           Data.Default.Class                   (Default (..))
import           Data.String.Conversions              (cs)
import           Network.ABCI.Server.App              (App (..), MessageType,
                                                       Response (..),
                                                       transformApp)
import qualified Network.ABCI.Types.Messages.Response as Resp
import           Polysemy                             (Sem)
import           Tendermint.SDK.BaseApp.Errors        (AppError)

createIOApp
  :: forall r.
     (forall a. (Sem r) a -> IO a)
  -> App (Sem r)
  -> App IO
createIOApp :: (forall a. Sem r a -> IO a) -> App (Sem r) -> App IO
createIOApp nat :: forall a. Sem r a -> IO a
nat app :: App (Sem r)
app = (forall (t :: MessageType). Sem r (Response t) -> IO (Response t))
-> App (Sem r) -> App IO
forall (m :: * -> *) (g :: * -> *).
(forall (t :: MessageType). m (Response t) -> g (Response t))
-> App m -> App g
transformApp forall (t :: MessageType). Sem r (Response t) -> IO (Response t)
transformResponse App (Sem r)
app
  where
  transformResponse :: (forall (t :: MessageType). Sem r (Response t) -> IO (Response t))
  transformResponse :: Sem r (Response t) -> IO (Response t)
transformResponse (Sem r (Response t)
resp :: Sem r (Response t)) = do
    Either AppError (Response t)
eRes :: Either AppError (Response t) <- IO (Response t) -> IO (Either AppError (Response t))
forall e a. Exception e => IO a -> IO (Either e a)
try (IO (Response t) -> IO (Either AppError (Response t)))
-> IO (Response t) -> IO (Either AppError (Response t))
forall a b. (a -> b) -> a -> b
$ Sem r (Response t) -> IO (Response t)
forall a. Sem r a -> IO a
nat (Sem r (Response t) -> IO (Response t))
-> Sem r (Response t) -> IO (Response t)
forall a b. (a -> b) -> a -> b
$ Sem r (Response t)
resp
    case Either AppError (Response t)
eRes of
      Left e :: AppError
e -> Response t -> IO (Response t)
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Response t -> IO (Response t)) -> Response t -> IO (Response t)
forall a b. (a -> b) -> a -> b
$ Exception -> Response t
forall (m :: MessageType). Exception -> Response m
ResponseException (Exception -> Response t) -> Exception -> Response t
forall a b. (a -> b) -> a -> b
$
        Exception
forall a. Default a => a
def Exception -> (Exception -> Exception) -> Exception
forall a b. a -> (a -> b) -> b
& (Text -> Identity Text) -> Exception -> Identity Exception
Iso' Exception Text
Resp._exceptionError ((Text -> Identity Text) -> Exception -> Identity Exception)
-> Text -> Exception -> Exception
forall s t a b. ASetter s t a b -> b -> s -> t
.~ String -> Text
forall a b. ConvertibleStrings a b => a -> b
cs (AppError -> String
forall e. Exception e => e -> String
displayException AppError
e)
      Right a :: Response t
a -> Response t -> IO (Response t)
forall (f :: * -> *) a. Applicative f => a -> f a
pure Response t
a