{-# LANGUAGE DataKinds           #-}
{-# LANGUAGE GADTs               #-}
{-# LANGUAGE LambdaCase          #-}
{-# LANGUAGE RankNTypes          #-}
{-# LANGUAGE ScopedTypeVariables #-}


-- | A view of the transaction monitor protocol from the point of view of
-- the client.
--
-- This provides simple access to the local mempool snapshots, to allow building
-- more monitoring logic from the client side after submitting transactions.
--
-- For execution, 'localTxMonitorClientPeer' is provided for conversion
-- into the typed protocol.
--
module Ouroboros.Network.Protocol.LocalTxMonitor.Client
  ( -- * Protocol type for the client
    -- | The protocol states from the point of view of the client.
    LocalTxMonitorClient (..)
  , ClientStIdle (..)
  , ClientStAcquired (..)
    -- * Execution as a typed protocol
  , localTxMonitorClientPeer
  ) where

import           Network.TypedProtocol.Core

import           Ouroboros.Network.Protocol.LocalTxMonitor.Type

-- | A tx monitor client, on top of some effect 'm'.
--
newtype LocalTxMonitorClient txid tx slot m a = LocalTxMonitorClient {
      LocalTxMonitorClient txid tx slot m a
-> m (ClientStIdle txid tx slot m a)
runLocalTxMonitorClient :: m (ClientStIdle txid tx slot m a)
    }

-- | In the 'StIdle' protocol state, the client has agency and can proceed to
-- acquire a mempool snapshot, or end the protocol.
--
data ClientStIdle txid tx slot m a where

  -- | Send the 'MsgAcquire', with handlers for the replies.
  --
  -- This request cannot timeout and cannot fail, it'll acquire the latest
  -- mempool snapshot available on the server and hang on to it. This allows to
  -- run any subsequent queries against the same view of the mempool.
  --
  -- The snapshot is acquired for a particular slot number which materializes
  -- the 'virtual block' under construction.
  --
  SendMsgAcquire
    :: (slot -> m (ClientStAcquired txid tx slot m a))
    -> ClientStIdle txid tx slot m a

  -- | The client decided to end the protocol
  --
  SendMsgDone
    :: a
    -> ClientStIdle txid tx slot m a

-- | In the 'StAcquired' protocol state, the client has agency and can query the
-- server against the acquired snapshot. Alternatively, it can also (re)acquire
-- a more recent snapshot.
--
data ClientStAcquired txid tx slot m a where
  -- | The mempool is modeled as an ordered list of transactions and thus, can
  -- be traversed linearly. 'MsgNextTx' requests the next transaction from the
  -- current list. This must be a transaction that was not previously sent to
  -- the client for this particular snapshot.
  --
  SendMsgNextTx
    :: (Maybe tx -> m (ClientStAcquired txid tx slot m a))
    -> ClientStAcquired txid tx slot m a

  -- | For some cases where clients do not wish to traverse the entire mempool
  -- but look for a specific transaction, they can assess the presence of such
  -- transaction directly. Note that, the absence of a transaction does not
  -- imply anything about how the transaction was processed: it may have been
  -- dropped, or inserted in a block. 'False' simply means that it is no longer
  -- in the mempool.
  --
  SendMsgHasTx
    :: txid
    -> (Bool -> m (ClientStAcquired txid tx slot m a))
    -> ClientStAcquired txid tx slot m a

  -- | Ask the server about the current mempool's capacity and sizes. This is
  -- fixed in a given snapshot.
  SendMsgGetSizes
    :: (MempoolSizeAndCapacity -> m (ClientStAcquired txid tx slot m a))
    -> ClientStAcquired txid tx slot m a

  -- | Await for a new snapshot and acquire it.
  --
  SendMsgAwaitAcquire
    :: (slot ->  m (ClientStAcquired txid tx slot m a))
    -> ClientStAcquired txid tx slot m a

  -- | Release the acquired snapshot, in order to loop back to the idle state.
  --
  SendMsgRelease
    :: m (ClientStIdle txid tx slot m a)
    -> ClientStAcquired txid tx slot m a

-- | Interpret a 'LocalTxMonitorClient' action sequence as a 'Peer' on the
-- client-side of the 'LocalTxMonitor' protocol.
--
localTxMonitorClientPeer ::
     forall txid tx slot m a.
     ( Monad m
     )
  => LocalTxMonitorClient txid tx slot m a
  -> Peer (LocalTxMonitor txid tx slot) AsClient StIdle m a
localTxMonitorClientPeer :: LocalTxMonitorClient txid tx slot m a
-> Peer (LocalTxMonitor txid tx slot) 'AsClient 'StIdle m a
localTxMonitorClientPeer (LocalTxMonitorClient m (ClientStIdle txid tx slot m a)
mClient) =
    m (Peer (LocalTxMonitor txid tx slot) 'AsClient 'StIdle m a)
-> Peer (LocalTxMonitor txid tx slot) 'AsClient 'StIdle m a
forall (m :: * -> *) ps (pr :: PeerRole) (st :: ps) a.
m (Peer ps pr st m a) -> Peer ps pr st m a
Effect (m (Peer (LocalTxMonitor txid tx slot) 'AsClient 'StIdle m a)
 -> Peer (LocalTxMonitor txid tx slot) 'AsClient 'StIdle m a)
-> m (Peer (LocalTxMonitor txid tx slot) 'AsClient 'StIdle m a)
-> Peer (LocalTxMonitor txid tx slot) 'AsClient 'StIdle m a
forall a b. (a -> b) -> a -> b
$ ClientStIdle txid tx slot m a
-> Peer (LocalTxMonitor txid tx slot) 'AsClient 'StIdle m a
handleStIdle (ClientStIdle txid tx slot m a
 -> Peer (LocalTxMonitor txid tx slot) 'AsClient 'StIdle m a)
-> m (ClientStIdle txid tx slot m a)
-> m (Peer (LocalTxMonitor txid tx slot) 'AsClient 'StIdle m a)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> m (ClientStIdle txid tx slot m a)
mClient
  where
    handleStIdle ::
         ClientStIdle txid tx slot m a
      -> Peer (LocalTxMonitor txid tx slot) AsClient StIdle m a
    handleStIdle :: ClientStIdle txid tx slot m a
-> Peer (LocalTxMonitor txid tx slot) 'AsClient 'StIdle m a
handleStIdle = \case
      SendMsgAcquire slot -> m (ClientStAcquired txid tx slot m a)
stAcquired ->
        WeHaveAgency 'AsClient 'StIdle
-> Message (LocalTxMonitor txid tx slot) 'StIdle 'StAcquiring
-> Peer (LocalTxMonitor txid tx slot) 'AsClient 'StAcquiring m a
-> Peer (LocalTxMonitor txid tx slot) 'AsClient 'StIdle m a
forall (pr :: PeerRole) ps (st :: ps) (st' :: ps) (m :: * -> *) a.
WeHaveAgency pr st
-> Message ps st st' -> Peer ps pr st' m a -> Peer ps pr st m a
Yield (ClientHasAgency 'StIdle -> WeHaveAgency 'AsClient 'StIdle
forall ps (st :: ps).
ClientHasAgency st -> PeerHasAgency 'AsClient st
ClientAgency ClientHasAgency 'StIdle
forall k k k (txid :: k) (tx :: k) (slot :: k).
ClientHasAgency 'StIdle
TokIdle) Message (LocalTxMonitor txid tx slot) 'StIdle 'StAcquiring
forall k k k (txid :: k) (tx :: k) (slot :: k).
Message (LocalTxMonitor txid tx slot) 'StIdle 'StAcquiring
MsgAcquire (Peer (LocalTxMonitor txid tx slot) 'AsClient 'StAcquiring m a
 -> Peer (LocalTxMonitor txid tx slot) 'AsClient 'StIdle m a)
-> Peer (LocalTxMonitor txid tx slot) 'AsClient 'StAcquiring m a
-> Peer (LocalTxMonitor txid tx slot) 'AsClient 'StIdle m a
forall a b. (a -> b) -> a -> b
$
          TheyHaveAgency 'AsClient 'StAcquiring
-> (forall (st' :: LocalTxMonitor txid tx slot).
    Message (LocalTxMonitor txid tx slot) 'StAcquiring st'
    -> Peer (LocalTxMonitor txid tx slot) 'AsClient st' m a)
-> Peer (LocalTxMonitor txid tx slot) 'AsClient 'StAcquiring m a
forall (pr :: PeerRole) ps (st :: ps) (m :: * -> *) a.
TheyHaveAgency pr st
-> (forall (st' :: ps). Message ps st st' -> Peer ps pr st' m a)
-> Peer ps pr st m a
Await (ServerHasAgency 'StAcquiring
-> PeerHasAgency 'AsServer 'StAcquiring
forall ps (st :: ps).
ServerHasAgency st -> PeerHasAgency 'AsServer st
ServerAgency ServerHasAgency 'StAcquiring
forall k k k (txid :: k) (tx :: k) (slot :: k).
ServerHasAgency 'StAcquiring
TokAcquiring) ((forall (st' :: LocalTxMonitor txid tx slot).
  Message (LocalTxMonitor txid tx slot) 'StAcquiring st'
  -> Peer (LocalTxMonitor txid tx slot) 'AsClient st' m a)
 -> Peer (LocalTxMonitor txid tx slot) 'AsClient 'StAcquiring m a)
-> (forall (st' :: LocalTxMonitor txid tx slot).
    Message (LocalTxMonitor txid tx slot) 'StAcquiring st'
    -> Peer (LocalTxMonitor txid tx slot) 'AsClient st' m a)
-> Peer (LocalTxMonitor txid tx slot) 'AsClient 'StAcquiring m a
forall a b. (a -> b) -> a -> b
$ \case
            MsgAcquired slot -> m (Peer (LocalTxMonitor txid tx slot) 'AsClient 'StAcquired m a)
-> Peer (LocalTxMonitor txid tx slot) 'AsClient 'StAcquired m a
forall (m :: * -> *) ps (pr :: PeerRole) (st :: ps) a.
m (Peer ps pr st m a) -> Peer ps pr st m a
Effect (m (Peer (LocalTxMonitor txid tx slot) 'AsClient 'StAcquired m a)
 -> Peer (LocalTxMonitor txid tx slot) 'AsClient 'StAcquired m a)
-> m (Peer (LocalTxMonitor txid tx slot) 'AsClient 'StAcquired m a)
-> Peer (LocalTxMonitor txid tx slot) 'AsClient 'StAcquired m a
forall a b. (a -> b) -> a -> b
$ ClientStAcquired txid tx slot m a
-> Peer (LocalTxMonitor txid tx slot) 'AsClient 'StAcquired m a
handleStAcquired (ClientStAcquired txid tx slot m a
 -> Peer (LocalTxMonitor txid tx slot) 'AsClient 'StAcquired m a)
-> m (ClientStAcquired txid tx slot m a)
-> m (Peer (LocalTxMonitor txid tx slot) 'AsClient 'StAcquired m a)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> slot -> m (ClientStAcquired txid tx slot m a)
stAcquired slot
slot
slot
      SendMsgDone a
a ->
        WeHaveAgency 'AsClient 'StIdle
-> Message (LocalTxMonitor txid tx slot) 'StIdle 'StDone
-> Peer (LocalTxMonitor txid tx slot) 'AsClient 'StDone m a
-> Peer (LocalTxMonitor txid tx slot) 'AsClient 'StIdle m a
forall (pr :: PeerRole) ps (st :: ps) (st' :: ps) (m :: * -> *) a.
WeHaveAgency pr st
-> Message ps st st' -> Peer ps pr st' m a -> Peer ps pr st m a
Yield (ClientHasAgency 'StIdle -> WeHaveAgency 'AsClient 'StIdle
forall ps (st :: ps).
ClientHasAgency st -> PeerHasAgency 'AsClient st
ClientAgency ClientHasAgency 'StIdle
forall k k k (txid :: k) (tx :: k) (slot :: k).
ClientHasAgency 'StIdle
TokIdle) Message (LocalTxMonitor txid tx slot) 'StIdle 'StDone
forall k k k (txid :: k) (tx :: k) (slot :: k).
Message (LocalTxMonitor txid tx slot) 'StIdle 'StDone
MsgDone (NobodyHasAgency 'StDone
-> a -> Peer (LocalTxMonitor txid tx slot) 'AsClient 'StDone m a
forall ps (st :: ps) a (pr :: PeerRole) (m :: * -> *).
NobodyHasAgency st -> a -> Peer ps pr st m a
Done NobodyHasAgency 'StDone
forall k k k (txid :: k) (tx :: k) (slot :: k).
NobodyHasAgency 'StDone
TokDone a
a)

    handleStAcquired ::
         ClientStAcquired txid tx slot m a
      -> Peer (LocalTxMonitor txid tx slot) AsClient StAcquired m a
    handleStAcquired :: ClientStAcquired txid tx slot m a
-> Peer (LocalTxMonitor txid tx slot) 'AsClient 'StAcquired m a
handleStAcquired = \case
      SendMsgNextTx Maybe tx -> m (ClientStAcquired txid tx slot m a)
stAcquired ->
        WeHaveAgency 'AsClient 'StAcquired
-> Message
     (LocalTxMonitor txid tx slot) 'StAcquired ('StBusy 'NextTx)
-> Peer
     (LocalTxMonitor txid tx slot) 'AsClient ('StBusy 'NextTx) m a
-> Peer (LocalTxMonitor txid tx slot) 'AsClient 'StAcquired m a
forall (pr :: PeerRole) ps (st :: ps) (st' :: ps) (m :: * -> *) a.
WeHaveAgency pr st
-> Message ps st st' -> Peer ps pr st' m a -> Peer ps pr st m a
Yield (ClientHasAgency 'StAcquired -> WeHaveAgency 'AsClient 'StAcquired
forall ps (st :: ps).
ClientHasAgency st -> PeerHasAgency 'AsClient st
ClientAgency ClientHasAgency 'StAcquired
forall k k k (txid :: k) (tx :: k) (slot :: k).
ClientHasAgency 'StAcquired
TokAcquired) Message (LocalTxMonitor txid tx slot) 'StAcquired ('StBusy 'NextTx)
forall k k k (txid :: k) (tx :: k) (slot :: k).
Message (LocalTxMonitor txid tx slot) 'StAcquired ('StBusy 'NextTx)
MsgNextTx (Peer (LocalTxMonitor txid tx slot) 'AsClient ('StBusy 'NextTx) m a
 -> Peer (LocalTxMonitor txid tx slot) 'AsClient 'StAcquired m a)
-> Peer
     (LocalTxMonitor txid tx slot) 'AsClient ('StBusy 'NextTx) m a
-> Peer (LocalTxMonitor txid tx slot) 'AsClient 'StAcquired m a
forall a b. (a -> b) -> a -> b
$
          TheyHaveAgency 'AsClient ('StBusy 'NextTx)
-> (forall (st' :: LocalTxMonitor txid tx slot).
    Message (LocalTxMonitor txid tx slot) ('StBusy 'NextTx) st'
    -> Peer (LocalTxMonitor txid tx slot) 'AsClient st' m a)
-> Peer
     (LocalTxMonitor txid tx slot) 'AsClient ('StBusy 'NextTx) m a
forall (pr :: PeerRole) ps (st :: ps) (m :: * -> *) a.
TheyHaveAgency pr st
-> (forall (st' :: ps). Message ps st st' -> Peer ps pr st' m a)
-> Peer ps pr st m a
Await (ServerHasAgency ('StBusy 'NextTx)
-> PeerHasAgency 'AsServer ('StBusy 'NextTx)
forall ps (st :: ps).
ServerHasAgency st -> PeerHasAgency 'AsServer st
ServerAgency (TokBusyKind 'NextTx -> ServerHasAgency ('StBusy 'NextTx)
forall k k k (txid :: k) (tx :: k) (slot :: k) (k :: StBusyKind).
TokBusyKind k -> ServerHasAgency ('StBusy k)
TokBusy TokBusyKind 'NextTx
TokNextTx)) ((forall (st' :: LocalTxMonitor txid tx slot).
  Message (LocalTxMonitor txid tx slot) ('StBusy 'NextTx) st'
  -> Peer (LocalTxMonitor txid tx slot) 'AsClient st' m a)
 -> Peer
      (LocalTxMonitor txid tx slot) 'AsClient ('StBusy 'NextTx) m a)
-> (forall (st' :: LocalTxMonitor txid tx slot).
    Message (LocalTxMonitor txid tx slot) ('StBusy 'NextTx) st'
    -> Peer (LocalTxMonitor txid tx slot) 'AsClient st' m a)
-> Peer
     (LocalTxMonitor txid tx slot) 'AsClient ('StBusy 'NextTx) m a
forall a b. (a -> b) -> a -> b
$ \case
            MsgReplyNextTx tx ->
              m (Peer (LocalTxMonitor txid tx slot) 'AsClient 'StAcquired m a)
-> Peer (LocalTxMonitor txid tx slot) 'AsClient 'StAcquired m a
forall (m :: * -> *) ps (pr :: PeerRole) (st :: ps) a.
m (Peer ps pr st m a) -> Peer ps pr st m a
Effect (m (Peer (LocalTxMonitor txid tx slot) 'AsClient 'StAcquired m a)
 -> Peer (LocalTxMonitor txid tx slot) 'AsClient 'StAcquired m a)
-> m (Peer (LocalTxMonitor txid tx slot) 'AsClient 'StAcquired m a)
-> Peer (LocalTxMonitor txid tx slot) 'AsClient 'StAcquired m a
forall a b. (a -> b) -> a -> b
$ ClientStAcquired txid tx slot m a
-> Peer (LocalTxMonitor txid tx slot) 'AsClient 'StAcquired m a
handleStAcquired (ClientStAcquired txid tx slot m a
 -> Peer (LocalTxMonitor txid tx slot) 'AsClient 'StAcquired m a)
-> m (ClientStAcquired txid tx slot m a)
-> m (Peer (LocalTxMonitor txid tx slot) 'AsClient 'StAcquired m a)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Maybe tx -> m (ClientStAcquired txid tx slot m a)
stAcquired Maybe tx
Maybe tx
tx
      SendMsgHasTx txid
txid Bool -> m (ClientStAcquired txid tx slot m a)
stAcquired ->
        WeHaveAgency 'AsClient 'StAcquired
-> Message
     (LocalTxMonitor txid tx slot) 'StAcquired ('StBusy 'HasTx)
-> Peer
     (LocalTxMonitor txid tx slot) 'AsClient ('StBusy 'HasTx) m a
-> Peer (LocalTxMonitor txid tx slot) 'AsClient 'StAcquired m a
forall (pr :: PeerRole) ps (st :: ps) (st' :: ps) (m :: * -> *) a.
WeHaveAgency pr st
-> Message ps st st' -> Peer ps pr st' m a -> Peer ps pr st m a
Yield (ClientHasAgency 'StAcquired -> WeHaveAgency 'AsClient 'StAcquired
forall ps (st :: ps).
ClientHasAgency st -> PeerHasAgency 'AsClient st
ClientAgency ClientHasAgency 'StAcquired
forall k k k (txid :: k) (tx :: k) (slot :: k).
ClientHasAgency 'StAcquired
TokAcquired) (txid
-> Message
     (LocalTxMonitor txid tx slot) 'StAcquired ('StBusy 'HasTx)
forall k k txid (tx :: k) (slot :: k).
txid
-> Message
     (LocalTxMonitor txid tx slot) 'StAcquired ('StBusy 'HasTx)
MsgHasTx txid
txid) (Peer (LocalTxMonitor txid tx slot) 'AsClient ('StBusy 'HasTx) m a
 -> Peer (LocalTxMonitor txid tx slot) 'AsClient 'StAcquired m a)
-> Peer
     (LocalTxMonitor txid tx slot) 'AsClient ('StBusy 'HasTx) m a
-> Peer (LocalTxMonitor txid tx slot) 'AsClient 'StAcquired m a
forall a b. (a -> b) -> a -> b
$
          TheyHaveAgency 'AsClient ('StBusy 'HasTx)
-> (forall (st' :: LocalTxMonitor txid tx slot).
    Message (LocalTxMonitor txid tx slot) ('StBusy 'HasTx) st'
    -> Peer (LocalTxMonitor txid tx slot) 'AsClient st' m a)
-> Peer
     (LocalTxMonitor txid tx slot) 'AsClient ('StBusy 'HasTx) m a
forall (pr :: PeerRole) ps (st :: ps) (m :: * -> *) a.
TheyHaveAgency pr st
-> (forall (st' :: ps). Message ps st st' -> Peer ps pr st' m a)
-> Peer ps pr st m a
Await (ServerHasAgency ('StBusy 'HasTx)
-> PeerHasAgency 'AsServer ('StBusy 'HasTx)
forall ps (st :: ps).
ServerHasAgency st -> PeerHasAgency 'AsServer st
ServerAgency (TokBusyKind 'HasTx -> ServerHasAgency ('StBusy 'HasTx)
forall k k k (txid :: k) (tx :: k) (slot :: k) (k :: StBusyKind).
TokBusyKind k -> ServerHasAgency ('StBusy k)
TokBusy TokBusyKind 'HasTx
TokHasTx)) ((forall (st' :: LocalTxMonitor txid tx slot).
  Message (LocalTxMonitor txid tx slot) ('StBusy 'HasTx) st'
  -> Peer (LocalTxMonitor txid tx slot) 'AsClient st' m a)
 -> Peer
      (LocalTxMonitor txid tx slot) 'AsClient ('StBusy 'HasTx) m a)
-> (forall (st' :: LocalTxMonitor txid tx slot).
    Message (LocalTxMonitor txid tx slot) ('StBusy 'HasTx) st'
    -> Peer (LocalTxMonitor txid tx slot) 'AsClient st' m a)
-> Peer
     (LocalTxMonitor txid tx slot) 'AsClient ('StBusy 'HasTx) m a
forall a b. (a -> b) -> a -> b
$ \case
            MsgReplyHasTx res ->
              m (Peer (LocalTxMonitor txid tx slot) 'AsClient 'StAcquired m a)
-> Peer (LocalTxMonitor txid tx slot) 'AsClient 'StAcquired m a
forall (m :: * -> *) ps (pr :: PeerRole) (st :: ps) a.
m (Peer ps pr st m a) -> Peer ps pr st m a
Effect (m (Peer (LocalTxMonitor txid tx slot) 'AsClient 'StAcquired m a)
 -> Peer (LocalTxMonitor txid tx slot) 'AsClient 'StAcquired m a)
-> m (Peer (LocalTxMonitor txid tx slot) 'AsClient 'StAcquired m a)
-> Peer (LocalTxMonitor txid tx slot) 'AsClient 'StAcquired m a
forall a b. (a -> b) -> a -> b
$ ClientStAcquired txid tx slot m a
-> Peer (LocalTxMonitor txid tx slot) 'AsClient 'StAcquired m a
handleStAcquired (ClientStAcquired txid tx slot m a
 -> Peer (LocalTxMonitor txid tx slot) 'AsClient 'StAcquired m a)
-> m (ClientStAcquired txid tx slot m a)
-> m (Peer (LocalTxMonitor txid tx slot) 'AsClient 'StAcquired m a)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Bool -> m (ClientStAcquired txid tx slot m a)
stAcquired Bool
res
      SendMsgGetSizes MempoolSizeAndCapacity -> m (ClientStAcquired txid tx slot m a)
stAcquired ->
        WeHaveAgency 'AsClient 'StAcquired
-> Message
     (LocalTxMonitor txid tx slot) 'StAcquired ('StBusy 'GetSizes)
-> Peer
     (LocalTxMonitor txid tx slot) 'AsClient ('StBusy 'GetSizes) m a
-> Peer (LocalTxMonitor txid tx slot) 'AsClient 'StAcquired m a
forall (pr :: PeerRole) ps (st :: ps) (st' :: ps) (m :: * -> *) a.
WeHaveAgency pr st
-> Message ps st st' -> Peer ps pr st' m a -> Peer ps pr st m a
Yield (ClientHasAgency 'StAcquired -> WeHaveAgency 'AsClient 'StAcquired
forall ps (st :: ps).
ClientHasAgency st -> PeerHasAgency 'AsClient st
ClientAgency ClientHasAgency 'StAcquired
forall k k k (txid :: k) (tx :: k) (slot :: k).
ClientHasAgency 'StAcquired
TokAcquired) Message
  (LocalTxMonitor txid tx slot) 'StAcquired ('StBusy 'GetSizes)
forall k k k (txid :: k) (tx :: k) (slot :: k).
Message
  (LocalTxMonitor txid tx slot) 'StAcquired ('StBusy 'GetSizes)
MsgGetSizes (Peer
   (LocalTxMonitor txid tx slot) 'AsClient ('StBusy 'GetSizes) m a
 -> Peer (LocalTxMonitor txid tx slot) 'AsClient 'StAcquired m a)
-> Peer
     (LocalTxMonitor txid tx slot) 'AsClient ('StBusy 'GetSizes) m a
-> Peer (LocalTxMonitor txid tx slot) 'AsClient 'StAcquired m a
forall a b. (a -> b) -> a -> b
$
          TheyHaveAgency 'AsClient ('StBusy 'GetSizes)
-> (forall (st' :: LocalTxMonitor txid tx slot).
    Message (LocalTxMonitor txid tx slot) ('StBusy 'GetSizes) st'
    -> Peer (LocalTxMonitor txid tx slot) 'AsClient st' m a)
-> Peer
     (LocalTxMonitor txid tx slot) 'AsClient ('StBusy 'GetSizes) m a
forall (pr :: PeerRole) ps (st :: ps) (m :: * -> *) a.
TheyHaveAgency pr st
-> (forall (st' :: ps). Message ps st st' -> Peer ps pr st' m a)
-> Peer ps pr st m a
Await (ServerHasAgency ('StBusy 'GetSizes)
-> PeerHasAgency 'AsServer ('StBusy 'GetSizes)
forall ps (st :: ps).
ServerHasAgency st -> PeerHasAgency 'AsServer st
ServerAgency (TokBusyKind 'GetSizes -> ServerHasAgency ('StBusy 'GetSizes)
forall k k k (txid :: k) (tx :: k) (slot :: k) (k :: StBusyKind).
TokBusyKind k -> ServerHasAgency ('StBusy k)
TokBusy TokBusyKind 'GetSizes
TokGetSizes)) ((forall (st' :: LocalTxMonitor txid tx slot).
  Message (LocalTxMonitor txid tx slot) ('StBusy 'GetSizes) st'
  -> Peer (LocalTxMonitor txid tx slot) 'AsClient st' m a)
 -> Peer
      (LocalTxMonitor txid tx slot) 'AsClient ('StBusy 'GetSizes) m a)
-> (forall (st' :: LocalTxMonitor txid tx slot).
    Message (LocalTxMonitor txid tx slot) ('StBusy 'GetSizes) st'
    -> Peer (LocalTxMonitor txid tx slot) 'AsClient st' m a)
-> Peer
     (LocalTxMonitor txid tx slot) 'AsClient ('StBusy 'GetSizes) m a
forall a b. (a -> b) -> a -> b
$ \case
            MsgReplyGetSizes sizes ->
              m (Peer (LocalTxMonitor txid tx slot) 'AsClient 'StAcquired m a)
-> Peer (LocalTxMonitor txid tx slot) 'AsClient 'StAcquired m a
forall (m :: * -> *) ps (pr :: PeerRole) (st :: ps) a.
m (Peer ps pr st m a) -> Peer ps pr st m a
Effect (m (Peer (LocalTxMonitor txid tx slot) 'AsClient 'StAcquired m a)
 -> Peer (LocalTxMonitor txid tx slot) 'AsClient 'StAcquired m a)
-> m (Peer (LocalTxMonitor txid tx slot) 'AsClient 'StAcquired m a)
-> Peer (LocalTxMonitor txid tx slot) 'AsClient 'StAcquired m a
forall a b. (a -> b) -> a -> b
$ ClientStAcquired txid tx slot m a
-> Peer (LocalTxMonitor txid tx slot) 'AsClient 'StAcquired m a
handleStAcquired (ClientStAcquired txid tx slot m a
 -> Peer (LocalTxMonitor txid tx slot) 'AsClient 'StAcquired m a)
-> m (ClientStAcquired txid tx slot m a)
-> m (Peer (LocalTxMonitor txid tx slot) 'AsClient 'StAcquired m a)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> MempoolSizeAndCapacity -> m (ClientStAcquired txid tx slot m a)
stAcquired MempoolSizeAndCapacity
sizes
      SendMsgAwaitAcquire slot -> m (ClientStAcquired txid tx slot m a)
stAcquired ->
        WeHaveAgency 'AsClient 'StAcquired
-> Message (LocalTxMonitor txid tx slot) 'StAcquired 'StAcquiring
-> Peer (LocalTxMonitor txid tx slot) 'AsClient 'StAcquiring m a
-> Peer (LocalTxMonitor txid tx slot) 'AsClient 'StAcquired m a
forall (pr :: PeerRole) ps (st :: ps) (st' :: ps) (m :: * -> *) a.
WeHaveAgency pr st
-> Message ps st st' -> Peer ps pr st' m a -> Peer ps pr st m a
Yield (ClientHasAgency 'StAcquired -> WeHaveAgency 'AsClient 'StAcquired
forall ps (st :: ps).
ClientHasAgency st -> PeerHasAgency 'AsClient st
ClientAgency ClientHasAgency 'StAcquired
forall k k k (txid :: k) (tx :: k) (slot :: k).
ClientHasAgency 'StAcquired
TokAcquired) Message (LocalTxMonitor txid tx slot) 'StAcquired 'StAcquiring
forall k k k (txid :: k) (tx :: k) (slot :: k).
Message (LocalTxMonitor txid tx slot) 'StAcquired 'StAcquiring
MsgAwaitAcquire (Peer (LocalTxMonitor txid tx slot) 'AsClient 'StAcquiring m a
 -> Peer (LocalTxMonitor txid tx slot) 'AsClient 'StAcquired m a)
-> Peer (LocalTxMonitor txid tx slot) 'AsClient 'StAcquiring m a
-> Peer (LocalTxMonitor txid tx slot) 'AsClient 'StAcquired m a
forall a b. (a -> b) -> a -> b
$
          TheyHaveAgency 'AsClient 'StAcquiring
-> (forall (st' :: LocalTxMonitor txid tx slot).
    Message (LocalTxMonitor txid tx slot) 'StAcquiring st'
    -> Peer (LocalTxMonitor txid tx slot) 'AsClient st' m a)
-> Peer (LocalTxMonitor txid tx slot) 'AsClient 'StAcquiring m a
forall (pr :: PeerRole) ps (st :: ps) (m :: * -> *) a.
TheyHaveAgency pr st
-> (forall (st' :: ps). Message ps st st' -> Peer ps pr st' m a)
-> Peer ps pr st m a
Await (ServerHasAgency 'StAcquiring
-> PeerHasAgency 'AsServer 'StAcquiring
forall ps (st :: ps).
ServerHasAgency st -> PeerHasAgency 'AsServer st
ServerAgency ServerHasAgency 'StAcquiring
forall k k k (txid :: k) (tx :: k) (slot :: k).
ServerHasAgency 'StAcquiring
TokAcquiring) ((forall (st' :: LocalTxMonitor txid tx slot).
  Message (LocalTxMonitor txid tx slot) 'StAcquiring st'
  -> Peer (LocalTxMonitor txid tx slot) 'AsClient st' m a)
 -> Peer (LocalTxMonitor txid tx slot) 'AsClient 'StAcquiring m a)
-> (forall (st' :: LocalTxMonitor txid tx slot).
    Message (LocalTxMonitor txid tx slot) 'StAcquiring st'
    -> Peer (LocalTxMonitor txid tx slot) 'AsClient st' m a)
-> Peer (LocalTxMonitor txid tx slot) 'AsClient 'StAcquiring m a
forall a b. (a -> b) -> a -> b
$ \case
            MsgAcquired slot ->
              m (Peer (LocalTxMonitor txid tx slot) 'AsClient 'StAcquired m a)
-> Peer (LocalTxMonitor txid tx slot) 'AsClient 'StAcquired m a
forall (m :: * -> *) ps (pr :: PeerRole) (st :: ps) a.
m (Peer ps pr st m a) -> Peer ps pr st m a
Effect (m (Peer (LocalTxMonitor txid tx slot) 'AsClient 'StAcquired m a)
 -> Peer (LocalTxMonitor txid tx slot) 'AsClient 'StAcquired m a)
-> m (Peer (LocalTxMonitor txid tx slot) 'AsClient 'StAcquired m a)
-> Peer (LocalTxMonitor txid tx slot) 'AsClient 'StAcquired m a
forall a b. (a -> b) -> a -> b
$ ClientStAcquired txid tx slot m a
-> Peer (LocalTxMonitor txid tx slot) 'AsClient 'StAcquired m a
handleStAcquired (ClientStAcquired txid tx slot m a
 -> Peer (LocalTxMonitor txid tx slot) 'AsClient 'StAcquired m a)
-> m (ClientStAcquired txid tx slot m a)
-> m (Peer (LocalTxMonitor txid tx slot) 'AsClient 'StAcquired m a)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> slot -> m (ClientStAcquired txid tx slot m a)
stAcquired slot
slot
slot
      SendMsgRelease m (ClientStIdle txid tx slot m a)
stIdle ->
        WeHaveAgency 'AsClient 'StAcquired
-> Message (LocalTxMonitor txid tx slot) 'StAcquired 'StIdle
-> Peer (LocalTxMonitor txid tx slot) 'AsClient 'StIdle m a
-> Peer (LocalTxMonitor txid tx slot) 'AsClient 'StAcquired m a
forall (pr :: PeerRole) ps (st :: ps) (st' :: ps) (m :: * -> *) a.
WeHaveAgency pr st
-> Message ps st st' -> Peer ps pr st' m a -> Peer ps pr st m a
Yield (ClientHasAgency 'StAcquired -> WeHaveAgency 'AsClient 'StAcquired
forall ps (st :: ps).
ClientHasAgency st -> PeerHasAgency 'AsClient st
ClientAgency ClientHasAgency 'StAcquired
forall k k k (txid :: k) (tx :: k) (slot :: k).
ClientHasAgency 'StAcquired
TokAcquired) Message (LocalTxMonitor txid tx slot) 'StAcquired 'StIdle
forall k k k (txid :: k) (tx :: k) (slot :: k).
Message (LocalTxMonitor txid tx slot) 'StAcquired 'StIdle
MsgRelease (Peer (LocalTxMonitor txid tx slot) 'AsClient 'StIdle m a
 -> Peer (LocalTxMonitor txid tx slot) 'AsClient 'StAcquired m a)
-> Peer (LocalTxMonitor txid tx slot) 'AsClient 'StIdle m a
-> Peer (LocalTxMonitor txid tx slot) 'AsClient 'StAcquired m a
forall a b. (a -> b) -> a -> b
$
          m (Peer (LocalTxMonitor txid tx slot) 'AsClient 'StIdle m a)
-> Peer (LocalTxMonitor txid tx slot) 'AsClient 'StIdle m a
forall (m :: * -> *) ps (pr :: PeerRole) (st :: ps) a.
m (Peer ps pr st m a) -> Peer ps pr st m a
Effect (m (Peer (LocalTxMonitor txid tx slot) 'AsClient 'StIdle m a)
 -> Peer (LocalTxMonitor txid tx slot) 'AsClient 'StIdle m a)
-> m (Peer (LocalTxMonitor txid tx slot) 'AsClient 'StIdle m a)
-> Peer (LocalTxMonitor txid tx slot) 'AsClient 'StIdle m a
forall a b. (a -> b) -> a -> b
$ ClientStIdle txid tx slot m a
-> Peer (LocalTxMonitor txid tx slot) 'AsClient 'StIdle m a
handleStIdle (ClientStIdle txid tx slot m a
 -> Peer (LocalTxMonitor txid tx slot) 'AsClient 'StIdle m a)
-> m (ClientStIdle txid tx slot m a)
-> m (Peer (LocalTxMonitor txid tx slot) 'AsClient 'StIdle m a)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> m (ClientStIdle txid tx slot m a)
stIdle