penumbra_sdk_dex/component/action_handler/position/
open.rs

1use anyhow::{ensure, Result};
2use async_trait::async_trait;
3use cnidarium::StateWrite;
4use cnidarium_component::ActionHandler;
5
6use crate::{
7    component::{PositionManager, StateReadExt},
8    lp::{action::PositionOpen, position},
9};
10
11#[async_trait]
12/// Debits the initial reserves and credits an opened position NFT.
13impl ActionHandler for PositionOpen {
14    type CheckStatelessContext = ();
15    async fn check_stateless(&self, _context: ()) -> Result<()> {
16        // Check:
17        //  + reserves are at most 80 bits wide,
18        //  + the trading function coefficients are at most 80 bits wide.
19        //  + at least some assets are provisioned.
20        //  + the trading function coefficients are non-zero,
21        //  + the trading function doesn't specify a cyclic pair,
22        //  + the fee is <=50%.
23        self.position.check_stateless()?;
24        if self.position.state != position::State::Opened {
25            anyhow::bail!("attempted to open a position with a state besides `Opened`");
26        }
27        Ok(())
28    }
29
30    async fn check_and_execute<S: StateWrite>(&self, mut state: S) -> Result<()> {
31        // Only open the position if the dex is enabled in the dex params.
32        let dex_params = state.get_dex_params().await?;
33
34        ensure!(
35            dex_params.is_enabled,
36            "Dex MUST be enabled to open positions."
37        );
38
39        state.open_position(self.position.clone()).await?;
40        Ok(())
41    }
42}