penumbra_sdk_dex/component/position_manager/
price_index.rs

1use cnidarium::StateWrite;
2use penumbra_sdk_proto::StateWriteProto;
3
4use crate::{
5    lp::position::{self, Position},
6    state_key::engine,
7    DirectedTradingPair,
8};
9
10use anyhow::Result;
11use position::State::*;
12
13pub(crate) trait PositionByPriceIndex: StateWrite {
14    fn update_position_by_price_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 for 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_price(prev_lp, position_id);
24        }
25
26        if matches!(new_state.state, Opened) {
27            self.index_position_by_price(new_state, position_id);
28        }
29
30        Ok(())
31    }
32
33    fn deindex_position_by_price(&mut self, position: &Position, id: &position::Id) {
34        tracing::debug!("deindexing position");
35        let pair12 = DirectedTradingPair {
36            start: position.phi.pair.asset_1(),
37            end: position.phi.pair.asset_2(),
38        };
39        let phi12 = position.phi.component.clone();
40        let pair21 = DirectedTradingPair {
41            start: position.phi.pair.asset_2(),
42            end: position.phi.pair.asset_1(),
43        };
44        let phi21 = position.phi.component.flip();
45        self.nonverifiable_delete(engine::price_index::key(&pair12, &phi12, &id));
46        self.nonverifiable_delete(engine::price_index::key(&pair21, &phi21, &id));
47    }
48}
49impl<T: StateWrite + ?Sized> PositionByPriceIndex for T {}
50
51trait Inner: StateWrite {
52    fn index_position_by_price(&mut self, position: &position::Position, id: &position::Id) {
53        let (pair, phi) = (position.phi.pair, &position.phi);
54        if position.reserves.r2 != 0u64.into() {
55            // Index this position for trades FROM asset 1 TO asset 2, since the position has asset 2 to give out.
56            let pair12 = DirectedTradingPair {
57                start: pair.asset_1(),
58                end: pair.asset_2(),
59            };
60            let phi12 = phi.component.clone();
61            self.nonverifiable_put(
62                engine::price_index::key(&pair12, &phi12, &id),
63                position.clone(),
64            );
65            tracing::debug!("indexing position for 1=>2 trades");
66        }
67
68        if position.reserves.r1 != 0u64.into() {
69            // Index this position for trades FROM asset 2 TO asset 1, since the position has asset 1 to give out.
70            let pair21 = DirectedTradingPair {
71                start: pair.asset_2(),
72                end: pair.asset_1(),
73            };
74            let phi21 = phi.component.flip();
75            self.nonverifiable_put(
76                engine::price_index::key(&pair21, &phi21, &id),
77                position.clone(),
78            );
79            tracing::debug!("indexing position for 2=>1 trades");
80        }
81    }
82}
83
84impl<T: StateWrite + ?Sized> Inner for T {}