Trait penumbra_component::ActionHandler
source · pub trait ActionHandler {
fn check_stateless<'life0, 'async_trait>(
&'life0 self,
context: Arc<Transaction>
) -> Pin<Box<dyn Future<Output = Result<()>> + Send + 'async_trait>>
where
Self: 'async_trait,
'life0: 'async_trait;
fn check_stateful<'life0, 'async_trait>(
&'life0 self,
state: Arc<State>
) -> Pin<Box<dyn Future<Output = Result<()>> + Send + 'async_trait>>
where
Self: 'async_trait,
'life0: 'async_trait;
fn execute<'life0, 'life1, 'async_trait>(
&'life0 self,
state: &'life1 mut StateTransaction<'_>
) -> Pin<Box<dyn Future<Output = Result<()>> + Send + 'async_trait>>
where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait;
}
Expand description
Defines the interface for handling transaction actions.
Block-wide execution is performed using the Component
trait. Per-transaction execution is performed using the ActionHandler
trait.
The ActionHandler
trait has a top-level implementation on Transaction
,
which performs any transaction-wide checks and then calls the
ActionHandler
implementation for each Action
.
The validation logic in the ActionHandler
trait is split into three phases:
ActionHandler::check_stateless
, which has no access to state, only to the transaction the action is part of;ActionHandler::check_stateful
, which has read access to a snapshot of state prior to transaction execution;ActionHandler::execute
, which has write access to the state and read access to its own writes.
All of these methods are asynchronous and fallible; an error at any level fails the transaction and aborts any in-progress execution.
These methods are described in more detail below, but in general, as much
work as possible should be pushed up the stack, where greater parallelism is
available, with checks performed in execute
only as a last resort.
Required Methods§
sourcefn check_stateless<'life0, 'async_trait>(
&'life0 self,
context: Arc<Transaction>
) -> Pin<Box<dyn Future<Output = Result<()>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
fn check_stateless<'life0, 'async_trait>(
&'life0 self,
context: Arc<Transaction>
) -> Pin<Box<dyn Future<Output = Result<()>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
Performs all of this action’s stateless validity checks in the
context
of some Transaction
.
This method is async
to make it easy to perform stateless validity
checks in parallel, by allowing ActionHandler
implementations to
easily spawn tasks internally.
Supplying the context
means that stateless checks can use
transaction-wide data like the SCT anchor. Supplying it as an
Arc<Transaction>
makes it easy to share the context with internally
spawned tasks.
As much work as possible should be done in check_stateless
, as it can
be run in parallel across all transactions in a block.
sourcefn check_stateful<'life0, 'async_trait>(
&'life0 self,
state: Arc<State>
) -> Pin<Box<dyn Future<Output = Result<()>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
fn check_stateful<'life0, 'async_trait>(
&'life0 self,
state: Arc<State>
) -> Pin<Box<dyn Future<Output = Result<()>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
Performs all of this action’s stateful validity checks.
This method provides read access to a snapshot of the State
prior to
transaction execution. Because it does not give write access, it’s safe
to run the ActionHandler
implementations for all actions in a given
transaction in parallel.
As much work as possible should be done in check_stateful
, as it can
be run in parallel across all actions within a transaction.
Invariants
This method should only be called on data that has been checked
with ActionHandler::check_stateless
. This method can be called
before Component::begin_block
.
sourcefn execute<'life0, 'life1, 'async_trait>(
&'life0 self,
state: &'life1 mut StateTransaction<'_>
) -> Pin<Box<dyn Future<Output = Result<()>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
fn execute<'life0, 'life1, 'async_trait>(
&'life0 self,
state: &'life1 mut StateTransaction<'_>
) -> Pin<Box<dyn Future<Output = Result<()>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
Attempts to execute this action against the provided state
.
This method provides read and write access to the state
. It is
fallible, so it’s possible to perform checks within the execute
implementation and abort execution on error; the StateTransaction
mechanism ensures that all writes are correctly discarded.
Because execute
must run sequentially, whenever possible, checks
should be performed in ActionHandler::check_stateful
or
ActionHandler::check_stateless
. One example of where this is not
possible (in fact, the motivating example) is for IBC, where a
transaction may (1) submit a client update and then (2) relay messages
valid relative to the newly updated state. In this case, the checks for
(2) must be performed during execution, as they depend on the state
changes written while processing the client update.
However, this data flow pattern should be avoided whenever possible.
Invariants
This method should only be called immediately after an invocation of
ActionHandler::check_stateful
on the same transaction. This method
can be called before Component::begin_block
.
Implementations on Foreign Types§
source§impl ActionHandler for Delegate
impl ActionHandler for Delegate
fn check_stateless<'life0, 'async_trait>(
&'life0 self,
_context: Arc<Transaction>
) -> Pin<Box<dyn Future<Output = Result<()>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
fn check_stateful<'life0, 'async_trait>(
&'life0 self,
state: Arc<State>
) -> Pin<Box<dyn Future<Output = Result<()>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
fn execute<'life0, 'life1, 'async_trait>(
&'life0 self,
state: &'life1 mut StateTransaction<'_>
) -> Pin<Box<dyn Future<Output = Result<()>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
source§impl ActionHandler for MsgAcknowledgement
impl ActionHandler for MsgAcknowledgement
fn check_stateless<'life0, 'async_trait>(
&'life0 self,
_context: Arc<Transaction>
) -> Pin<Box<dyn Future<Output = Result<()>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
fn check_stateful<'life0, 'async_trait>(
&'life0 self,
state: Arc<State>
) -> Pin<Box<dyn Future<Output = Result<()>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
fn execute<'life0, 'life1, 'async_trait>(
&'life0 self,
state: &'life1 mut StateTransaction<'_>
) -> Pin<Box<dyn Future<Output = Result<()>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
source§impl ActionHandler for MsgChannelCloseConfirm
impl ActionHandler for MsgChannelCloseConfirm
fn check_stateless<'life0, 'async_trait>(
&'life0 self,
_context: Arc<Transaction>
) -> Pin<Box<dyn Future<Output = Result<()>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
fn check_stateful<'life0, 'async_trait>(
&'life0 self,
state: Arc<State>
) -> Pin<Box<dyn Future<Output = Result<()>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
fn execute<'life0, 'life1, 'async_trait>(
&'life0 self,
state: &'life1 mut StateTransaction<'_>
) -> Pin<Box<dyn Future<Output = Result<()>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
source§impl ActionHandler for MsgChannelCloseInit
impl ActionHandler for MsgChannelCloseInit
fn check_stateless<'life0, 'async_trait>(
&'life0 self,
_context: Arc<Transaction>
) -> Pin<Box<dyn Future<Output = Result<()>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
fn check_stateful<'life0, 'async_trait>(
&'life0 self,
state: Arc<State>
) -> Pin<Box<dyn Future<Output = Result<()>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
fn execute<'life0, 'life1, 'async_trait>(
&'life0 self,
state: &'life1 mut StateTransaction<'_>
) -> Pin<Box<dyn Future<Output = Result<()>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
source§impl ActionHandler for MsgChannelOpenAck
impl ActionHandler for MsgChannelOpenAck
fn check_stateless<'life0, 'async_trait>(
&'life0 self,
_context: Arc<Transaction>
) -> Pin<Box<dyn Future<Output = Result<()>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
fn check_stateful<'life0, 'async_trait>(
&'life0 self,
state: Arc<State>
) -> Pin<Box<dyn Future<Output = Result<()>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
fn execute<'life0, 'life1, 'async_trait>(
&'life0 self,
state: &'life1 mut StateTransaction<'_>
) -> Pin<Box<dyn Future<Output = Result<()>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
source§impl ActionHandler for MsgChannelOpenConfirm
impl ActionHandler for MsgChannelOpenConfirm
fn check_stateless<'life0, 'async_trait>(
&'life0 self,
_context: Arc<Transaction>
) -> Pin<Box<dyn Future<Output = Result<()>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
fn check_stateful<'life0, 'async_trait>(
&'life0 self,
state: Arc<State>
) -> Pin<Box<dyn Future<Output = Result<()>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
fn execute<'life0, 'life1, 'async_trait>(
&'life0 self,
state: &'life1 mut StateTransaction<'_>
) -> Pin<Box<dyn Future<Output = Result<()>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
source§impl ActionHandler for MsgChannelOpenInit
impl ActionHandler for MsgChannelOpenInit
fn check_stateless<'life0, 'async_trait>(
&'life0 self,
_context: Arc<Transaction>
) -> Pin<Box<dyn Future<Output = Result<()>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
fn check_stateful<'life0, 'async_trait>(
&'life0 self,
state: Arc<State>
) -> Pin<Box<dyn Future<Output = Result<()>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
fn execute<'life0, 'life1, 'async_trait>(
&'life0 self,
state: &'life1 mut StateTransaction<'_>
) -> Pin<Box<dyn Future<Output = Result<()>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
source§impl ActionHandler for MsgChannelOpenTry
impl ActionHandler for MsgChannelOpenTry
fn check_stateless<'life0, 'async_trait>(
&'life0 self,
_context: Arc<Transaction>
) -> Pin<Box<dyn Future<Output = Result<()>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
fn check_stateful<'life0, 'async_trait>(
&'life0 self,
state: Arc<State>
) -> Pin<Box<dyn Future<Output = Result<()>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
fn execute<'life0, 'life1, 'async_trait>(
&'life0 self,
state: &'life1 mut StateTransaction<'_>
) -> Pin<Box<dyn Future<Output = Result<()>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
source§impl ActionHandler for MsgConnectionOpenAck
impl ActionHandler for MsgConnectionOpenAck
fn check_stateless<'life0, 'async_trait>(
&'life0 self,
_context: Arc<Transaction>
) -> Pin<Box<dyn Future<Output = Result<()>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
fn check_stateful<'life0, 'async_trait>(
&'life0 self,
state: Arc<State>
) -> Pin<Box<dyn Future<Output = Result<()>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
fn execute<'life0, 'life1, 'async_trait>(
&'life0 self,
state: &'life1 mut StateTransaction<'_>
) -> Pin<Box<dyn Future<Output = Result<()>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
source§impl ActionHandler for MsgConnectionOpenConfirm
impl ActionHandler for MsgConnectionOpenConfirm
fn check_stateless<'life0, 'async_trait>(
&'life0 self,
_context: Arc<Transaction>
) -> Pin<Box<dyn Future<Output = Result<()>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
fn check_stateful<'life0, 'async_trait>(
&'life0 self,
state: Arc<State>
) -> Pin<Box<dyn Future<Output = Result<()>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
fn execute<'life0, 'life1, 'async_trait>(
&'life0 self,
state: &'life1 mut StateTransaction<'_>
) -> Pin<Box<dyn Future<Output = Result<()>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
source§impl ActionHandler for MsgConnectionOpenInit
impl ActionHandler for MsgConnectionOpenInit
fn check_stateless<'life0, 'async_trait>(
&'life0 self,
_context: Arc<Transaction>
) -> Pin<Box<dyn Future<Output = Result<()>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
fn check_stateful<'life0, 'async_trait>(
&'life0 self,
state: Arc<State>
) -> Pin<Box<dyn Future<Output = Result<()>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
fn execute<'life0, 'life1, 'async_trait>(
&'life0 self,
state: &'life1 mut StateTransaction<'_>
) -> Pin<Box<dyn Future<Output = Result<()>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
source§impl ActionHandler for MsgConnectionOpenTry
impl ActionHandler for MsgConnectionOpenTry
fn check_stateless<'life0, 'async_trait>(
&'life0 self,
_context: Arc<Transaction>
) -> Pin<Box<dyn Future<Output = Result<()>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
fn check_stateful<'life0, 'async_trait>(
&'life0 self,
state: Arc<State>
) -> Pin<Box<dyn Future<Output = Result<()>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
fn execute<'life0, 'life1, 'async_trait>(
&'life0 self,
state: &'life1 mut StateTransaction<'_>
) -> Pin<Box<dyn Future<Output = Result<()>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
source§impl ActionHandler for MsgCreateClient
impl ActionHandler for MsgCreateClient
fn check_stateless<'life0, 'async_trait>(
&'life0 self,
_context: Arc<Transaction>
) -> Pin<Box<dyn Future<Output = Result<()>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
fn check_stateful<'life0, 'async_trait>(
&'life0 self,
state: Arc<State>
) -> Pin<Box<dyn Future<Output = Result<()>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
fn execute<'life0, 'life1, 'async_trait>(
&'life0 self,
state: &'life1 mut StateTransaction<'_>
) -> Pin<Box<dyn Future<Output = Result<()>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
source§impl ActionHandler for MsgRecvPacket
impl ActionHandler for MsgRecvPacket
fn check_stateless<'life0, 'async_trait>(
&'life0 self,
_context: Arc<Transaction>
) -> Pin<Box<dyn Future<Output = Result<()>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
fn check_stateful<'life0, 'async_trait>(
&'life0 self,
state: Arc<State>
) -> Pin<Box<dyn Future<Output = Result<()>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
fn execute<'life0, 'life1, 'async_trait>(
&'life0 self,
state: &'life1 mut StateTransaction<'_>
) -> Pin<Box<dyn Future<Output = Result<()>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
source§impl ActionHandler for MsgTimeout
impl ActionHandler for MsgTimeout
fn check_stateless<'life0, 'async_trait>(
&'life0 self,
_context: Arc<Transaction>
) -> Pin<Box<dyn Future<Output = Result<()>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
fn check_stateful<'life0, 'async_trait>(
&'life0 self,
state: Arc<State>
) -> Pin<Box<dyn Future<Output = Result<()>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
fn execute<'life0, 'life1, 'async_trait>(
&'life0 self,
state: &'life1 mut StateTransaction<'_>
) -> Pin<Box<dyn Future<Output = Result<()>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
source§impl ActionHandler for MsgUpdateClient
impl ActionHandler for MsgUpdateClient
fn check_stateless<'life0, 'async_trait>(
&'life0 self,
_context: Arc<Transaction>
) -> Pin<Box<dyn Future<Output = Result<()>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
fn check_stateful<'life0, 'async_trait>(
&'life0 self,
state: Arc<State>
) -> Pin<Box<dyn Future<Output = Result<()>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
fn execute<'life0, 'life1, 'async_trait>(
&'life0 self,
state: &'life1 mut StateTransaction<'_>
) -> Pin<Box<dyn Future<Output = Result<()>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
source§impl ActionHandler for IbcAction
impl ActionHandler for IbcAction
fn check_stateless<'life0, 'async_trait>(
&'life0 self,
context: Arc<Transaction>
) -> Pin<Box<dyn Future<Output = Result<()>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
fn check_stateful<'life0, 'async_trait>(
&'life0 self,
state: Arc<State>
) -> Pin<Box<dyn Future<Output = Result<()>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
fn execute<'life0, 'life1, 'async_trait>(
&'life0 self,
state: &'life1 mut StateTransaction<'_>
) -> Pin<Box<dyn Future<Output = Result<()>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
source§impl ActionHandler for Ics20Withdrawal
impl ActionHandler for Ics20Withdrawal
fn check_stateless<'life0, 'async_trait>(
&'life0 self,
_context: Arc<Transaction>
) -> Pin<Box<dyn Future<Output = Result<()>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
fn check_stateful<'life0, 'async_trait>(
&'life0 self,
state: Arc<State>
) -> Pin<Box<dyn Future<Output = Result<()>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
fn execute<'life0, 'life1, 'async_trait>(
&'life0 self,
state: &'life1 mut StateTransaction<'_>
) -> Pin<Box<dyn Future<Output = Result<()>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
source§impl ActionHandler for Output
impl ActionHandler for Output
fn check_stateless<'life0, 'async_trait>(
&'life0 self,
_context: Arc<Transaction>
) -> Pin<Box<dyn Future<Output = Result<()>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
fn check_stateful<'life0, 'async_trait>(
&'life0 self,
_state: Arc<State>
) -> Pin<Box<dyn Future<Output = Result<()>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
fn execute<'life0, 'life1, 'async_trait>(
&'life0 self,
state: &'life1 mut StateTransaction<'_>
) -> Pin<Box<dyn Future<Output = Result<()>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
source§impl ActionHandler for PositionClose
impl ActionHandler for PositionClose
Debits an opened position NFT and credits a closed position NFT.
fn check_stateless<'life0, 'async_trait>(
&'life0 self,
_context: Arc<Transaction>
) -> Pin<Box<dyn Future<Output = Result<()>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
fn check_stateful<'life0, 'async_trait>(
&'life0 self,
_state: Arc<State>
) -> Pin<Box<dyn Future<Output = Result<()>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
fn execute<'life0, 'life1, 'async_trait>(
&'life0 self,
_state: &'life1 mut StateTransaction<'_>
) -> Pin<Box<dyn Future<Output = Result<()>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
source§impl ActionHandler for PositionOpen
impl ActionHandler for PositionOpen
Debits the initial reserves and credits an opened position NFT.
fn check_stateless<'life0, 'async_trait>(
&'life0 self,
_context: Arc<Transaction>
) -> Pin<Box<dyn Future<Output = Result<()>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
fn check_stateful<'life0, 'async_trait>(
&'life0 self,
_state: Arc<State>
) -> Pin<Box<dyn Future<Output = Result<()>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
fn execute<'life0, 'life1, 'async_trait>(
&'life0 self,
state: &'life1 mut StateTransaction<'_>
) -> Pin<Box<dyn Future<Output = Result<()>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
source§impl ActionHandler for PositionRewardClaim
impl ActionHandler for PositionRewardClaim
Debits a withdrawn position NFT and credits a claimed position NFT and any liquidity incentives.
fn check_stateless<'life0, 'async_trait>(
&'life0 self,
_context: Arc<Transaction>
) -> Pin<Box<dyn Future<Output = Result<()>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
fn check_stateful<'life0, 'async_trait>(
&'life0 self,
_state: Arc<State>
) -> Pin<Box<dyn Future<Output = Result<()>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
fn execute<'life0, 'life1, 'async_trait>(
&'life0 self,
_state: &'life1 mut StateTransaction<'_>
) -> Pin<Box<dyn Future<Output = Result<()>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
source§impl ActionHandler for PositionWithdraw
impl ActionHandler for PositionWithdraw
Debits a closed position NFT and credits a withdrawn position NFT and the final reserves.