penumbra_sdk_auction/auction/dutch/actions/
schedule.rs

1use crate::auction::{dutch::DutchAuctionDescription, nft::AuctionNft};
2use anyhow::anyhow;
3use penumbra_sdk_asset::{Balance, Value};
4use penumbra_sdk_proto::{core::component::auction::v1 as pb, DomainType};
5use penumbra_sdk_txhash::{EffectHash, EffectingData};
6use serde::{Deserialize, Serialize};
7
8/// The maximum amount of input/output in a Dutch auction description.
9/// 52 bits gives us enough headroom to do infaillible price interpolation.
10pub const MAX_AUCTION_AMOUNT_RESERVES: u128 = (1 << 52) - 1;
11
12#[derive(Debug, Clone, Serialize, Deserialize)]
13#[serde(
14    try_from = "pb::ActionDutchAuctionSchedule",
15    into = "pb::ActionDutchAuctionSchedule"
16)]
17pub struct ActionDutchAuctionSchedule {
18    pub description: DutchAuctionDescription,
19}
20
21impl ActionDutchAuctionSchedule {
22    /// Compute the value balance corresponding to this action:
23    ///
24    /// # Diagram
25    ///
26    ///  ┌────────────────────┬──────────────────────┐
27    ///  │      Burn (-)      │       Mint (+)       │
28    ///  ├────────────────────┼──────────────────────┤
29    ///  │    input value     │  opened auction nft  │
30    ///  └────────────────────┴──────────────────────┘                  
31    pub fn balance(&self) -> Balance {
32        let opened_auction_nft = AuctionNft::new(self.description.id(), 0u64);
33        let opened_auction_nft_value = Value {
34            asset_id: opened_auction_nft.metadata.id(),
35            amount: 1u128.into(),
36        };
37
38        let output_nft_balance = Balance::from(opened_auction_nft_value);
39        let input_balance = Balance::from(self.description.input);
40
41        output_nft_balance - input_balance
42    }
43}
44
45/* Effect hash */
46impl EffectingData for ActionDutchAuctionSchedule {
47    fn effect_hash(&self) -> EffectHash {
48        EffectHash::from_proto_effecting_data(&self.to_proto())
49    }
50}
51
52/* Protobuf impls */
53impl DomainType for ActionDutchAuctionSchedule {
54    type Proto = pb::ActionDutchAuctionSchedule;
55}
56
57impl From<ActionDutchAuctionSchedule> for pb::ActionDutchAuctionSchedule {
58    fn from(domain: ActionDutchAuctionSchedule) -> Self {
59        pb::ActionDutchAuctionSchedule {
60            description: Some(domain.description.into()),
61        }
62    }
63}
64
65impl TryFrom<pb::ActionDutchAuctionSchedule> for ActionDutchAuctionSchedule {
66    type Error = anyhow::Error;
67
68    fn try_from(msg: pb::ActionDutchAuctionSchedule) -> Result<Self, Self::Error> {
69        Ok(ActionDutchAuctionSchedule {
70            description: msg
71                .description
72                .ok_or_else(|| {
73                    anyhow!("ActionDutchAuctionSchedule message is missing a description")
74                })?
75                .try_into()?,
76        })
77    }
78}