{-# 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
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