{-# LANGUAGE ConstraintKinds #-}
{-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE TypeApplications #-}

module BtcLsp.Thread.Server
  ( apply,
  )
where

import BtcLsp.Grpc.Data
import qualified BtcLsp.Grpc.Server.HighLevel as Server
import BtcLsp.Grpc.Server.LowLevel
import qualified BtcLsp.Grpc.Sig as Sig
import BtcLsp.Import
import qualified BtcLsp.Storage.Model.User as User
import qualified Crypto.Secp256k1 as C
import qualified Data.ByteString as BS
import Data.ProtoLens.Field
import Lens.Micro
import Network.GRPC.HTTP2.ProtoLens (RPC (..))
import Network.GRPC.Server
import qualified Network.Wai.Internal as Wai
import Proto.BtcLsp (Service)
import qualified Proto.BtcLsp.Data.HighLevel as Proto
import qualified Proto.BtcLsp.Data.HighLevel_Fields as Proto
import qualified Proto.BtcLsp.Method.SwapFromLn as SwapFromLn
import qualified Proto.BtcLsp.Method.SwapIntoLn as SwapIntoLn
import qualified Universum

apply :: (Env m) => m ()
apply :: forall (m :: * -> *). Env m => m ()
apply = do
  GSEnv
env <- m GSEnv
forall (m :: * -> *). Env m => m GSEnv
getGsEnv
  (UnliftIO m -> IO ()) -> m ()
forall (m :: * -> *) a.
MonadUnliftIO m =>
(UnliftIO m -> IO a) -> m a
withUnliftIO ((UnliftIO m -> IO ()) -> m ()) -> (UnliftIO m -> IO ()) -> m ()
forall a b. (a -> b) -> a -> b
$ GSEnv -> (GSEnv -> RawRequestBytes -> [ServiceHandler]) -> IO ()
runServer GSEnv
env ((GSEnv -> RawRequestBytes -> [ServiceHandler]) -> IO ())
-> (UnliftIO m -> GSEnv -> RawRequestBytes -> [ServiceHandler])
-> UnliftIO m
-> IO ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. UnliftIO m -> GSEnv -> RawRequestBytes -> [ServiceHandler]
forall (m :: * -> *).
Env m =>
UnliftIO m -> GSEnv -> RawRequestBytes -> [ServiceHandler]
handlers

handlers ::
  forall m.
  ( Env m
  ) =>
  UnliftIO m ->
  GSEnv ->
  RawRequestBytes ->
  [ServiceHandler]
handlers :: forall (m :: * -> *).
Env m =>
UnliftIO m -> GSEnv -> RawRequestBytes -> [ServiceHandler]
handlers UnliftIO m
run GSEnv
gsEnv RawRequestBytes
body =
  [ RPC Service "swapIntoLn"
-> UnaryHandler IO Request Response -> ServiceHandler
forall r i o.
(GRPCInput r i, GRPCOutput r o) =>
r -> UnaryHandler IO i o -> ServiceHandler
unary (RPC Service "swapIntoLn"
forall s (m :: Symbol). RPC s m
RPC :: RPC Service "swapIntoLn") (UnaryHandler IO Request Response -> ServiceHandler)
-> UnaryHandler IO Request Response -> ServiceHandler
forall a b. (a -> b) -> a -> b
$
      (Entity User -> Request -> m Response)
-> UnaryHandler IO Request Response
forall req res failure specific.
(GrpcReq req, GrpcRes res failure specific, Out req, Out res) =>
(Entity User -> req -> m res) -> Request -> req -> IO res
runHandler Entity User -> Request -> m Response
forall (m :: * -> *). Env m => Entity User -> Request -> m Response
Server.swapIntoLn,
    RPC Service "swapFromLn"
-> UnaryHandler IO Request Response -> ServiceHandler
forall r i o.
(GRPCInput r i, GRPCOutput r o) =>
r -> UnaryHandler IO i o -> ServiceHandler
unary (RPC Service "swapFromLn"
forall s (m :: Symbol). RPC s m
RPC :: RPC Service "swapFromLn") (UnaryHandler IO Request Response -> ServiceHandler)
-> UnaryHandler IO Request Response -> ServiceHandler
forall a b. (a -> b) -> a -> b
$
      (Entity User -> Request -> m Response)
-> UnaryHandler IO Request Response
forall req res failure specific.
(GrpcReq req, GrpcRes res failure specific, Out req, Out res) =>
(Entity User -> req -> m res) -> Request -> req -> IO res
runHandler Entity User -> Request -> m Response
forall (m :: * -> *).
Monad m =>
Entity User -> Request -> m Response
swapFromLn,
    RPC Service "getCfg"
-> UnaryHandler IO Request Response -> ServiceHandler
forall r i o.
(GRPCInput r i, GRPCOutput r o) =>
r -> UnaryHandler IO i o -> ServiceHandler
unary (RPC Service "getCfg"
forall s (m :: Symbol). RPC s m
RPC :: RPC Service "getCfg") (UnaryHandler IO Request Response -> ServiceHandler)
-> UnaryHandler IO Request Response -> ServiceHandler
forall a b. (a -> b) -> a -> b
$
      (Entity User -> Request -> m Response)
-> UnaryHandler IO Request Response
forall req res failure specific.
(GrpcReq req, GrpcRes res failure specific, Out req, Out res) =>
(Entity User -> req -> m res) -> Request -> req -> IO res
runHandler Entity User -> Request -> m Response
forall (m :: * -> *). Env m => Entity User -> Request -> m Response
Server.getCfg
  ]
  where
    runHandler ::
      ( GrpcReq req,
        GrpcRes res failure specific,
        Out req,
        Out res
      ) =>
      (Entity User -> req -> m res) ->
      Wai.Request ->
      req ->
      IO res
    runHandler :: forall req res failure specific.
(GrpcReq req, GrpcRes res failure specific, Out req, Out res) =>
(Entity User -> req -> m res) -> Request -> req -> IO res
runHandler =
      UnliftIO m
-> GSEnv
-> RawRequestBytes
-> (Entity User -> req -> m res)
-> Request
-> req
-> IO res
forall req res failure specific (m :: * -> *).
(GrpcReq req, GrpcRes res failure specific, Env m, Out req,
 Out res) =>
UnliftIO m
-> GSEnv
-> RawRequestBytes
-> (Entity User -> req -> m res)
-> Request
-> req
-> IO res
withMiddleware UnliftIO m
run GSEnv
gsEnv RawRequestBytes
body

verifySigE ::
  GSEnv ->
  Wai.Request ->
  NodePubKey ->
  RawRequestBytes ->
  Either Failure ()
verifySigE :: GSEnv
-> Request -> NodePubKey -> RawRequestBytes -> Either Failure ()
verifySigE GSEnv
env Request
waiReq NodePubKey
pubNode (RawRequestBytes ByteString
payload) = do
  PubKey
pubDer <-
    Failure -> Maybe PubKey -> Either Failure PubKey
forall l r. l -> Maybe r -> Either l r
maybeToRight
      ( FailureInternal -> Failure
FailureInt (FailureInternal -> Failure)
-> (Text -> FailureInternal) -> Text -> Failure
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> FailureInternal
FailureGrpcServer (Text -> Failure) -> Text -> Failure
forall a b. (a -> b) -> a -> b
$
          Text
"NodePubKey DER import failed from "
            Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> NodePubKey -> Text
forall a. Out a => a -> Text
inspectPlain NodePubKey
pubNode
      )
      (Maybe PubKey -> Either Failure PubKey)
-> (ByteString -> Maybe PubKey)
-> ByteString
-> Either Failure PubKey
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ByteString -> Maybe PubKey
C.importPubKey
      (ByteString -> Either Failure PubKey)
-> ByteString -> Either Failure PubKey
forall a b. (a -> b) -> a -> b
$ NodePubKey -> ByteString
coerce NodePubKey
pubNode
  Sig
sig <-
    SigHeaderName -> Request -> Either Failure Sig
Sig.sigToVerify (GSEnv -> SigHeaderName
gsEnvSigHeaderName GSEnv
env) Request
waiReq
  Msg
msg <-
    Failure -> Maybe Msg -> Either Failure Msg
forall l r. l -> Maybe r -> Either l r
maybeToRight
      ( FailureInternal -> Failure
FailureInt (FailureInternal -> Failure)
-> (Text -> FailureInternal) -> Text -> Failure
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> FailureInternal
FailureGrpcServer (Text -> Failure) -> Text -> Failure
forall a b. (a -> b) -> a -> b
$
          Text
"Incorrect message from "
            Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> ByteString -> Text
forall a. Out a => a -> Text
inspectPlain ByteString
payload
      )
      (Maybe Msg -> Either Failure Msg)
-> Maybe Msg -> Either Failure Msg
forall a b. (a -> b) -> a -> b
$ ByteString -> Maybe Msg
Sig.msgToVerify ByteString
payload
  if PubKey -> Sig -> Msg -> Bool
C.verifySig PubKey
pubDer Sig
sig Msg
msg
    then () -> Either Failure ()
forall (f :: * -> *) a. Applicative f => a -> f a
pure ()
    else
      Failure -> Either Failure ()
forall a b. a -> Either a b
Left
        (Failure -> Either Failure ())
-> (Text -> Failure) -> Text -> Either Failure ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. FailureInternal -> Failure
FailureInt
        (FailureInternal -> Failure)
-> (Text -> FailureInternal) -> Text -> Failure
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> FailureInternal
FailureGrpcServer
        (Text -> Either Failure ()) -> Text -> Either Failure ()
forall a b. (a -> b) -> a -> b
$ Text
"Signature verification failed with key "
          Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> PubKey -> Text
forall a. Out a => a -> Text
inspectPlain PubKey
pubDer
          Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
" signature "
          Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Sig -> Text
forall a. Out a => a -> Text
inspectPlain Sig
sig
          Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
" message "
          Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> ByteString -> Text
forall a. Out a => a -> Text
inspectPlain ByteString
payload
          Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
" of "
          Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Int -> Text
forall a. Out a => a -> Text
inspectPlain (ByteString -> Int
BS.length ByteString
payload)
          Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
" bytes and message hash "
          Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> ByteString -> Text
forall a. Out a => a -> Text
inspectPlain (Msg -> ByteString
C.getMsg Msg
msg)

withMiddleware ::
  ( GrpcReq req,
    GrpcRes res failure specific,
    Env m,
    Out req,
    Out res
  ) =>
  UnliftIO m ->
  GSEnv ->
  RawRequestBytes ->
  (Entity User -> req -> m res) ->
  Wai.Request ->
  req ->
  IO res
withMiddleware :: forall req res failure specific (m :: * -> *).
(GrpcReq req, GrpcRes res failure specific, Env m, Out req,
 Out res) =>
UnliftIO m
-> GSEnv
-> RawRequestBytes
-> (Entity User -> req -> m res)
-> Request
-> req
-> IO res
withMiddleware (UnliftIO forall a. m a -> IO a
run) GSEnv
gsEnv RawRequestBytes
body Entity User -> req -> m res
handler Request
waiReq req
req =
  m res -> IO res
forall a. m a -> IO a
run (m res -> IO res) -> m res -> IO res
forall a b. (a -> b) -> a -> b
$ do
    Either res (Entity User)
userE <- ExceptT res m (Entity User) -> m (Either res (Entity User))
forall e (m :: * -> *) a. ExceptT e m a -> m (Either e a)
runExceptT (ExceptT res m (Entity User) -> m (Either res (Entity User)))
-> ExceptT res m (Entity User) -> m (Either res (Entity User))
forall a b. (a -> b) -> a -> b
$ do
      --
      -- NOTE : Here request type is hardcoded,
      -- because it's impossible to use generic "req"
      -- type with TH. Hardcoding request type is not ideal,
      -- because theoretically other requests could have
      -- other location of context stuff,
      -- but not really in this case.
      --
      Nonce
nonce <-
        ReversedFieldLocation -> Maybe Nonce -> ExceptT res m Nonce
forall a b res failure specific (m :: * -> *).
(From a b, 'False ~ (a == b), GrpcRes res failure specific,
 Monad m) =>
ReversedFieldLocation -> Maybe a -> ExceptT res m b
fromReqT
          $( mkFieldLocation
               @SwapIntoLn.Request
               [ "ctx",
                 "nonce"
               ]
           )
          (Maybe Nonce -> ExceptT res m Nonce)
-> Maybe Nonce -> ExceptT res m Nonce
forall a b. (a -> b) -> a -> b
$ req
req
            req -> Getting (First Nonce) req Nonce -> Maybe Nonce
forall s a. s -> Getting (First a) s a -> Maybe a
^? forall (x :: Symbol) s a (f :: * -> *).
(HasField s x a, Functor f) =>
(a -> f a) -> s -> f s
field @"maybe'ctx"
              ((Maybe Ctx -> Const (First Nonce) (Maybe Ctx))
 -> req -> Const (First Nonce) req)
-> ((Nonce -> Const (First Nonce) Nonce)
    -> Maybe Ctx -> Const (First Nonce) (Maybe Ctx))
-> Getting (First Nonce) req Nonce
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Ctx -> Const (First Nonce) Ctx)
-> Maybe Ctx -> Const (First Nonce) (Maybe Ctx)
forall a a'. Traversal (Maybe a) (Maybe a') a a'
_Just
              ((Ctx -> Const (First Nonce) Ctx)
 -> Maybe Ctx -> Const (First Nonce) (Maybe Ctx))
-> ((Nonce -> Const (First Nonce) Nonce)
    -> Ctx -> Const (First Nonce) Ctx)
-> (Nonce -> Const (First Nonce) Nonce)
-> Maybe Ctx
-> Const (First Nonce) (Maybe Ctx)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. LensLike' (Const (First Nonce)) Ctx (Maybe Nonce)
forall (f :: * -> *) s a.
(Functor f, HasField s "maybe'nonce" a) =>
LensLike' f s a
Proto.maybe'nonce
              LensLike' (Const (First Nonce)) Ctx (Maybe Nonce)
-> ((Nonce -> Const (First Nonce) Nonce)
    -> Maybe Nonce -> Const (First Nonce) (Maybe Nonce))
-> (Nonce -> Const (First Nonce) Nonce)
-> Ctx
-> Const (First Nonce) Ctx
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Nonce -> Const (First Nonce) Nonce)
-> Maybe Nonce -> Const (First Nonce) (Maybe Nonce)
forall a a'. Traversal (Maybe a) (Maybe a') a a'
_Just
      NodePubKey
pub <-
        ReversedFieldLocation -> Maybe LnPubKey -> ExceptT res m NodePubKey
forall a b res failure specific (m :: * -> *).
(From a b, 'False ~ (a == b), GrpcRes res failure specific,
 Monad m) =>
ReversedFieldLocation -> Maybe a -> ExceptT res m b
fromReqT
          $( mkFieldLocation
               @SwapIntoLn.Request
               [ "ctx",
                 "ln_pub_key"
               ]
           )
          (Maybe LnPubKey -> ExceptT res m NodePubKey)
-> Maybe LnPubKey -> ExceptT res m NodePubKey
forall a b. (a -> b) -> a -> b
$ req
req
            req -> Getting (First LnPubKey) req LnPubKey -> Maybe LnPubKey
forall s a. s -> Getting (First a) s a -> Maybe a
^? forall (x :: Symbol) s a (f :: * -> *).
(HasField s x a, Functor f) =>
(a -> f a) -> s -> f s
field @"maybe'ctx"
              ((Maybe Ctx -> Const (First LnPubKey) (Maybe Ctx))
 -> req -> Const (First LnPubKey) req)
-> ((LnPubKey -> Const (First LnPubKey) LnPubKey)
    -> Maybe Ctx -> Const (First LnPubKey) (Maybe Ctx))
-> Getting (First LnPubKey) req LnPubKey
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Ctx -> Const (First LnPubKey) Ctx)
-> Maybe Ctx -> Const (First LnPubKey) (Maybe Ctx)
forall a a'. Traversal (Maybe a) (Maybe a') a a'
_Just
              ((Ctx -> Const (First LnPubKey) Ctx)
 -> Maybe Ctx -> Const (First LnPubKey) (Maybe Ctx))
-> ((LnPubKey -> Const (First LnPubKey) LnPubKey)
    -> Ctx -> Const (First LnPubKey) Ctx)
-> (LnPubKey -> Const (First LnPubKey) LnPubKey)
-> Maybe Ctx
-> Const (First LnPubKey) (Maybe Ctx)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. LensLike' (Const (First LnPubKey)) Ctx (Maybe LnPubKey)
forall (f :: * -> *) s a.
(Functor f, HasField s "maybe'lnPubKey" a) =>
LensLike' f s a
Proto.maybe'lnPubKey
              LensLike' (Const (First LnPubKey)) Ctx (Maybe LnPubKey)
-> ((LnPubKey -> Const (First LnPubKey) LnPubKey)
    -> Maybe LnPubKey -> Const (First LnPubKey) (Maybe LnPubKey))
-> (LnPubKey -> Const (First LnPubKey) LnPubKey)
-> Ctx
-> Const (First LnPubKey) Ctx
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (LnPubKey -> Const (First LnPubKey) LnPubKey)
-> Maybe LnPubKey -> Const (First LnPubKey) (Maybe LnPubKey)
forall a a'. Traversal (Maybe a) (Maybe a') a a'
_Just
      if GSEnv -> Bool
gsEnvSigVerify GSEnv
gsEnv
        then
          Either res () -> ExceptT res m ()
forall (m :: * -> *) e a. Monad m => Either e a -> ExceptT e m a
except
            (Either res () -> ExceptT res m ())
-> (Either Failure () -> Either res ())
-> Either Failure ()
-> ExceptT res m ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Failure -> res) -> Either Failure () -> Either res ()
forall (p :: * -> * -> *) a b c.
Bifunctor p =>
(a -> b) -> p a c -> p b c
first
              ( res -> Failure -> res
forall a b. a -> b -> a
const (res -> Failure -> res) -> res -> Failure -> res
forall a b. (a -> b) -> a -> b
$
                  InputFailureKind -> ReversedFieldLocation -> res
forall res failure specific.
GrpcRes res failure specific =>
InputFailureKind -> ReversedFieldLocation -> res
newGenFailure
                    InputFailureKind
Proto.VERIFICATION_FAILED
                    ReversedFieldLocation
forall a. Monoid a => a
mempty
              )
            (Either Failure () -> ExceptT res m ())
-> Either Failure () -> ExceptT res m ()
forall a b. (a -> b) -> a -> b
$ GSEnv
-> Request -> NodePubKey -> RawRequestBytes -> Either Failure ()
verifySigE GSEnv
gsEnv Request
waiReq NodePubKey
pub RawRequestBytes
body
        else
          $(logTM)
            Severity
ErrorS
            LogStr
"WARNING!!! SIGNATURE VERIFICATION DISABLED!!!"
      (Failure -> res)
-> ExceptT Failure m (Entity User) -> ExceptT res m (Entity User)
forall (m :: * -> *) e e' a.
Functor m =>
(e -> e') -> ExceptT e m a -> ExceptT e' m a
withExceptT
        ( res -> Failure -> res
forall a b. a -> b -> a
const (res -> Failure -> res) -> res -> Failure -> res
forall a b. (a -> b) -> a -> b
$
            InputFailureKind -> ReversedFieldLocation -> res
forall res failure specific.
GrpcRes res failure specific =>
InputFailureKind -> ReversedFieldLocation -> res
newGenFailure
              InputFailureKind
Proto.VERIFICATION_FAILED
              $( mkFieldLocation
                   @SwapIntoLn.Request
                   [ "ctx",
                     "nonce"
                   ]
               )
        )
        (ExceptT Failure m (Entity User) -> ExceptT res m (Entity User))
-> (ReaderT SqlBackend m (Either Failure (Entity User))
    -> ExceptT Failure m (Entity User))
-> ReaderT SqlBackend m (Either Failure (Entity User))
-> ExceptT res m (Entity User)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. m (Either Failure (Entity User)) -> ExceptT Failure m (Entity User)
forall e (m :: * -> *) a. m (Either e a) -> ExceptT e m a
ExceptT
        (m (Either Failure (Entity User))
 -> ExceptT Failure m (Entity User))
-> (ReaderT SqlBackend m (Either Failure (Entity User))
    -> m (Either Failure (Entity User)))
-> ReaderT SqlBackend m (Either Failure (Entity User))
-> ExceptT Failure m (Entity User)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ReaderT SqlBackend m (Either Failure (Entity User))
-> m (Either Failure (Entity User))
forall (m :: * -> *) a. Storage m => ReaderT SqlBackend m a -> m a
runSql
        (ReaderT SqlBackend m (Either Failure (Entity User))
 -> ExceptT res m (Entity User))
-> ReaderT SqlBackend m (Either Failure (Entity User))
-> ExceptT res m (Entity User)
forall a b. (a -> b) -> a -> b
$ NodePubKey
-> Nonce -> ReaderT SqlBackend m (Either Failure (Entity User))
forall (m :: * -> *).
MonadIO m =>
NodePubKey
-> Nonce -> ReaderT SqlBackend m (Either Failure (Entity User))
User.createVerifySql NodePubKey
pub Nonce
nonce
    case Either res (Entity User)
userE of
      Right Entity User
user -> do
        res
res <- res -> m res
forall (m :: * -> *) msg.
(Env m, HasField msg "ctx" Ctx) =>
msg -> m msg
setGrpcCtx (res -> m res) -> m res -> m res
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< Entity User -> req -> m res
handler Entity User
user req
req
        $(logTM) Severity
DebugS (LogStr -> m ()) -> (Text -> LogStr) -> Text -> m ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> LogStr
forall a. StringConv a Text => a -> LogStr
logStr (Text -> m ()) -> Text -> m ()
forall a b. (a -> b) -> a -> b
$ res -> Text
forall a. Out a => a -> Text
debugMsg res
res
        res -> m res
forall (f :: * -> *) a. Applicative f => a -> f a
pure res
res
      Left res
e -> do
        $(logTM) Severity
DebugS (LogStr -> m ()) -> (Text -> LogStr) -> Text -> m ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> LogStr
forall a. StringConv a Text => a -> LogStr
logStr (Text -> m ()) -> Text -> m ()
forall a b. (a -> b) -> a -> b
$ res -> Text
forall a. Out a => a -> Text
debugMsg res
e
        res -> m res
forall (f :: * -> *) a. Applicative f => a -> f a
pure res
e
  where
    debugMsg :: (Out a) => a -> Text
    debugMsg :: forall a. Out a => a -> Text
debugMsg a
x =
      Text
"Got input "
        Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> RawRequestBytes -> Text
forall a. Out a => a -> Text
inspect RawRequestBytes
body
        Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
" with Wai request "
        Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Request -> Text
forall b a. (Show a, IsString b) => a -> b
Universum.show Request
waiReq
        Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
" and decoded "
        Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> req -> Text
forall a. Out a => a -> Text
inspect req
req
        Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
" producing result "
        Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> a -> Text
forall a. Out a => a -> Text
inspect a
x

swapFromLn ::
  ( Monad m
  ) =>
  Entity User ->
  SwapFromLn.Request ->
  m SwapFromLn.Response
swapFromLn :: forall (m :: * -> *).
Monad m =>
Entity User -> Request -> m Response
swapFromLn Entity User
_ Request
_ =
  Response -> m Response
forall (f :: * -> *) a. Applicative f => a -> f a
pure Response
forall msg. Message msg => msg
defMessage