penumbra_sdk_dex/component/position_manager/
inventory_index.rs

1use cnidarium::StateWrite;
2use tracing::instrument;
3
4use crate::{
5    lp::position::{self, Position},
6    state_key::eviction_queue,
7    DirectedTradingPair,
8};
9
10use anyhow::Result;
11use position::State::*;
12
13pub(super) trait PositionByInventoryIndex: StateWrite {
14    fn update_position_by_inventory_index(
15        &mut self,
16        position_id: &position::Id,
17        prev_state: &Option<Position>,
18        new_state: &Position,
19    ) -> Result<()> {
20        // Clear an existing record of the position, since changes to the
21        // reserves or the position state might have invalidated it.
22        if let Some(prev_lp) = prev_state {
23            self.deindex_position_by_inventory(prev_lp, position_id);
24        }
25
26        if matches!(new_state.state, Opened) {
27            self.index_position_by_inventory(new_state, position_id);
28        }
29
30        Ok(())
31    }
32}
33
34impl<T: StateWrite + ?Sized> PositionByInventoryIndex for T {}
35
36trait Inner: StateWrite {
37    #[instrument(skip(self, position))]
38    fn index_position_by_inventory(&mut self, position: &position::Position, id: &position::Id) {
39        tracing::trace!("indexing position by inventory");
40        let canonical_pair = position.phi.pair;
41        // A position is bound to an unordered trading pair: A <> B.
42        // We want to index the position by inventory for each direction:
43        // A -> B
44        let pair_ab = DirectedTradingPair::new(canonical_pair.asset_1(), canonical_pair.asset_2());
45        let inventory_a = position
46            .reserves_for(pair_ab.start)
47            .expect("the directed trading pair is correct");
48        let key_ab = eviction_queue::inventory_index::key(&pair_ab, inventory_a, id).to_vec();
49        self.nonverifiable_put_raw(key_ab, vec![]);
50
51        // B -> A
52        let pair_ba = pair_ab.flip();
53        let inventory_b = position
54            .reserves_for(pair_ba.start)
55            .expect("the directed trading pair is correct");
56        let key_ba = eviction_queue::inventory_index::key(&pair_ba, inventory_b, id).to_vec();
57        self.nonverifiable_put_raw(key_ba, vec![]);
58    }
59
60    fn deindex_position_by_inventory(
61        &mut self,
62        prev_position: &position::Position,
63        id: &position::Id,
64    ) {
65        let canonical_pair = prev_position.phi.pair;
66
67        // To deindex the position, we need to reconstruct the tuple of keys
68        // that correspond to each direction of the trading pair:
69        // A -> B
70        let pair_ab = DirectedTradingPair::new(canonical_pair.asset_1(), canonical_pair.asset_2());
71        let inventory_a = prev_position
72            .reserves_for(pair_ab.start)
73            .expect("the directed trading pair is correct");
74        let key_ab = eviction_queue::inventory_index::key(&pair_ab, inventory_a, id).to_vec();
75        self.nonverifiable_delete(key_ab);
76
77        // B -> A
78        let pair_ba = pair_ab.flip();
79        let inventory_b = prev_position
80            .reserves_for(pair_ba.start)
81            .expect("the directed trading pair is correct");
82        let key_ba = eviction_queue::inventory_index::key(&pair_ba, inventory_b, id).to_vec();
83        self.nonverifiable_delete(key_ba);
84    }
85}
86impl<T: StateWrite + ?Sized> Inner for T {}