penumbra_dex/component/action_handler/position/close.rs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37
use anyhow::Result;
use async_trait::async_trait;
use cnidarium::StateWrite;
use cnidarium_component::ActionHandler;
use penumbra_proto::{DomainType as _, StateWriteProto as _};
use crate::{component::PositionManager, event, lp::action::PositionClose};
#[async_trait]
/// Debits an opened position NFT and credits a closed position NFT.
impl ActionHandler for PositionClose {
type CheckStatelessContext = ();
async fn check_stateless(&self, _context: ()) -> Result<()> {
// Nothing to do: the only validation is of the state change,
// and that's done by the value balance mechanism.
Ok(())
}
async fn check_and_execute<S: StateWrite>(&self, mut state: S) -> Result<()> {
// We don't want to actually close the position here, because otherwise
// the economic effects could depend on intra-block ordering, and we'd
// lose the ability to do block-scoped JIT liquidity, where a single
// transaction opens and closes a position, keeping liquidity live only
// during that block's batch swap execution.
state.queue_close_position(self.position_id);
// queue position close you will...
state.record_proto(
event::EventQueuePositionClose {
position_id: self.position_id,
}
.to_proto(),
);
Ok(())
}
}