chia_sdk_driver/primitives/action_layer/
xchandles_registry_info.rs

1use chia_protocol::Bytes32;
2use chia_puzzle_types::singleton::SingletonArgs;
3use chia_sdk_types::{
4    MerkleTree, Mod,
5    puzzles::{
6        ActionLayerArgs, DefaultCatMakerArgs, DefaultFinalizer2ndCurryArgs,
7        XchandlesFactorPricingPuzzleArgs,
8    },
9};
10use clvm_traits::{FromClvm, ToClvm};
11use clvm_utils::{ToTreeHash, TreeHash};
12use clvmr::Allocator;
13
14use crate::{
15    ActionLayer, DelegatedStateAction, DriverError, Finalizer, Layer, Puzzle, SingletonAction,
16    SingletonLayer, XchandlesExpireAction, XchandlesExpirePricingPuzzle, XchandlesExtendAction,
17    XchandlesOracleAction, XchandlesRefundAction, XchandlesRegisterAction, XchandlesUpdateAction,
18};
19
20use super::XchandlesRegistry;
21
22pub type XchandlesRegistryLayers = SingletonLayer<ActionLayer<XchandlesRegistryState>>;
23
24#[must_use]
25#[derive(Debug, Clone, PartialEq, Eq, ToClvm, FromClvm, Copy)]
26#[clvm(list)]
27pub struct XchandlesRegistryState {
28    pub cat_maker_puzzle_hash: Bytes32,
29    pub pricing_puzzle_hash: Bytes32,
30    #[clvm(rest)]
31    pub expired_handle_pricing_puzzle_hash: Bytes32,
32}
33
34impl XchandlesRegistryState {
35    pub fn from(
36        payment_cat_tail_hash_hash: Bytes32,
37        base_price: u64,
38        registration_period: u64,
39    ) -> Self {
40        Self {
41            cat_maker_puzzle_hash: DefaultCatMakerArgs::new(payment_cat_tail_hash_hash)
42                .curry_tree_hash()
43                .into(),
44            pricing_puzzle_hash: XchandlesFactorPricingPuzzleArgs {
45                base_price,
46                registration_period,
47            }
48            .curry_tree_hash()
49            .into(),
50            expired_handle_pricing_puzzle_hash: XchandlesExpirePricingPuzzle::curry_tree_hash(
51                base_price,
52                registration_period,
53            )
54            .into(),
55        }
56    }
57}
58
59#[must_use]
60#[derive(Debug, Clone, PartialEq, Eq, Copy, ToClvm, FromClvm)]
61#[clvm(list)]
62pub struct XchandlesConstants {
63    pub launcher_id: Bytes32,
64    pub precommit_payout_puzzle_hash: Bytes32,
65    pub relative_block_height: u32,
66    pub price_singleton_launcher_id: Bytes32,
67}
68
69impl XchandlesConstants {
70    pub fn new(
71        launcher_id: Bytes32,
72        precommit_payout_puzzle_hash: Bytes32,
73        relative_block_height: u32,
74        price_singleton_launcher_id: Bytes32,
75    ) -> Self {
76        Self {
77            launcher_id,
78            precommit_payout_puzzle_hash,
79            relative_block_height,
80            price_singleton_launcher_id,
81        }
82    }
83
84    pub fn with_price_singleton(mut self, price_singleton_launcher_id: Bytes32) -> Self {
85        self.price_singleton_launcher_id = price_singleton_launcher_id;
86        self
87    }
88
89    pub fn with_launcher_id(mut self, launcher_id: Bytes32) -> Self {
90        self.launcher_id = launcher_id;
91        self
92    }
93}
94
95#[must_use]
96#[derive(Debug, Clone, PartialEq, Eq, Copy)]
97pub struct XchandlesRegistryInfo {
98    pub state: XchandlesRegistryState,
99
100    pub constants: XchandlesConstants,
101}
102
103impl XchandlesRegistryInfo {
104    pub fn new(state: XchandlesRegistryState, constants: XchandlesConstants) -> Self {
105        Self { state, constants }
106    }
107
108    pub fn with_state(mut self, state: XchandlesRegistryState) -> Self {
109        self.state = state;
110        self
111    }
112
113    pub fn action_puzzle_hashes(constants: &XchandlesConstants) -> [Bytes32; 7] {
114        [
115            XchandlesExpireAction::from_constants(constants)
116                .tree_hash()
117                .into(),
118            XchandlesExtendAction::from_constants(constants)
119                .tree_hash()
120                .into(),
121            XchandlesOracleAction::from_constants(constants)
122                .tree_hash()
123                .into(),
124            XchandlesRegisterAction::from_constants(constants)
125                .tree_hash()
126                .into(),
127            XchandlesUpdateAction::from_constants(constants)
128                .tree_hash()
129                .into(),
130            XchandlesRefundAction::from_constants(constants)
131                .tree_hash()
132                .into(),
133            <DelegatedStateAction as SingletonAction<XchandlesRegistry>>::from_constants(constants)
134                .tree_hash()
135                .into(),
136        ]
137    }
138
139    #[must_use]
140    pub fn into_layers(self) -> XchandlesRegistryLayers {
141        SingletonLayer::new(
142            self.constants.launcher_id,
143            ActionLayer::from_action_puzzle_hashes(
144                &Self::action_puzzle_hashes(&self.constants),
145                self.state,
146                Finalizer::Default {
147                    hint: self.constants.launcher_id,
148                },
149            ),
150        )
151    }
152
153    pub fn parse(
154        allocator: &mut Allocator,
155        puzzle: Puzzle,
156        constants: XchandlesConstants,
157    ) -> Result<Option<Self>, DriverError> {
158        let Some(layers) = XchandlesRegistryLayers::parse_puzzle(allocator, puzzle)? else {
159            return Ok(None);
160        };
161
162        let action_puzzle_hashes = Self::action_puzzle_hashes(&constants);
163        let merkle_root = MerkleTree::new(&action_puzzle_hashes).root();
164        if layers.inner_puzzle.merkle_root != merkle_root {
165            return Ok(None);
166        }
167
168        Ok(Some(Self::from_layers(&layers, constants)))
169    }
170
171    pub fn from_layers(layers: &XchandlesRegistryLayers, constants: XchandlesConstants) -> Self {
172        Self {
173            state: layers.inner_puzzle.state,
174            constants,
175        }
176    }
177
178    pub fn puzzle_hash(&self) -> TreeHash {
179        SingletonArgs::curry_tree_hash(self.constants.launcher_id, self.inner_puzzle_hash())
180    }
181
182    pub fn inner_puzzle_hash(&self) -> TreeHash {
183        ActionLayerArgs::curry_tree_hash(
184            DefaultFinalizer2ndCurryArgs::curry_tree_hash(self.constants.launcher_id),
185            MerkleTree::new(&Self::action_puzzle_hashes(&self.constants)).root(),
186            self.state.tree_hash(),
187        )
188    }
189}