penumbra_sdk_dex/
swap_execution.rs

1use anyhow::Result;
2use penumbra_sdk_asset::Value;
3use penumbra_sdk_num::fixpoint::U128x128;
4use penumbra_sdk_proto::{penumbra::core::component::dex::v1 as pb, DomainType};
5use serde::{Deserialize, Serialize};
6
7/// Contains the summary data of a trade, for client consumption.
8#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
9#[serde(try_from = "pb::SwapExecution", into = "pb::SwapExecution")]
10pub struct SwapExecution {
11    pub traces: Vec<Vec<Value>>,
12    /// The input value that was consumed.
13    pub input: Value,
14    /// The output value that was produced.
15    pub output: Value,
16}
17
18impl SwapExecution {
19    /// Returns the price of the latest execution trace.
20    pub fn max_price(&self) -> Option<U128x128> {
21        let Some((input, output)) = self.traces.last().and_then(|trace| {
22            let input = trace.first()?;
23            let output = trace.last()?;
24            Some((input, output))
25        }) else {
26            return None;
27        };
28
29        let price = U128x128::ratio(input.amount, output.amount).ok()?;
30        Some(price)
31    }
32}
33
34impl DomainType for SwapExecution {
35    type Proto = pb::SwapExecution;
36}
37
38impl TryFrom<pb::SwapExecution> for SwapExecution {
39    type Error = anyhow::Error;
40    fn try_from(se: pb::SwapExecution) -> Result<Self> {
41        Ok(Self {
42            traces: se
43                .traces
44                .into_iter()
45                .map(|vt| {
46                    vt.value
47                        .into_iter()
48                        .map(TryInto::try_into)
49                        .collect::<Result<Vec<_>>>()
50                })
51                .collect::<Result<Vec<_>>>()?,
52            input: se
53                .input
54                .ok_or_else(|| anyhow::anyhow!("missing input"))?
55                .try_into()?,
56            output: se
57                .output
58                .ok_or_else(|| anyhow::anyhow!("missing output"))?
59                .try_into()?,
60        })
61    }
62}
63
64impl From<SwapExecution> for pb::SwapExecution {
65    fn from(se: SwapExecution) -> Self {
66        pb::SwapExecution {
67            traces: se
68                .traces
69                .into_iter()
70                .map(|vt| pb::swap_execution::Trace {
71                    value: vt.into_iter().map(Into::into).collect(),
72                })
73                .collect(),
74            input: Some(se.input.into()),
75            output: Some(se.output.into()),
76        }
77    }
78}