chia_sdk_bindings/puzzle/
option.rs

1use bindy::Result;
2use chia_protocol::{Bytes32, Coin};
3use chia_sdk_driver::{
4    OptionContract as SdkOptionContract, OptionInfo, OptionMetadata, OptionType, OptionUnderlying,
5    SingletonInfo,
6};
7use clvm_utils::{ToTreeHash, TreeHash};
8
9use crate::{Clvm, Program, Proof, Spend};
10
11use super::Puzzle;
12
13#[derive(Clone)]
14pub struct OptionContract {
15    pub coin: Coin,
16    pub proof: Proof,
17    pub info: OptionInfo,
18}
19
20pub trait OptionContractExt: Sized {
21    fn child_proof(&self) -> Result<Proof>;
22    fn child(&self, p2_puzzle_hash: Bytes32) -> Result<Self>;
23    fn child_with(&self, info: OptionInfo) -> Result<Self>;
24}
25
26impl OptionContractExt for OptionContract {
27    fn child_proof(&self) -> Result<Proof> {
28        Ok(SdkOptionContract::from(self.clone())
29            .child_lineage_proof()
30            .into())
31    }
32
33    fn child(&self, p2_puzzle_hash: Bytes32) -> Result<Self> {
34        Ok(SdkOptionContract::from(self.clone())
35            .child(p2_puzzle_hash, self.coin.amount)
36            .into())
37    }
38
39    fn child_with(&self, info: OptionInfo) -> Result<Self> {
40        Ok(SdkOptionContract::from(self.clone())
41            .child_with(info, self.coin.amount)
42            .into())
43    }
44}
45
46impl From<SdkOptionContract> for OptionContract {
47    fn from(value: SdkOptionContract) -> Self {
48        OptionContract {
49            coin: value.coin,
50            proof: value.proof.into(),
51            info: value.info,
52        }
53    }
54}
55
56impl From<OptionContract> for SdkOptionContract {
57    fn from(value: OptionContract) -> Self {
58        SdkOptionContract {
59            coin: value.coin,
60            proof: value.proof.into(),
61            info: value.info,
62        }
63    }
64}
65
66pub trait OptionInfoExt {
67    fn inner_puzzle_hash(&self) -> Result<TreeHash>;
68    fn puzzle_hash(&self) -> Result<TreeHash>;
69}
70
71impl OptionInfoExt for OptionInfo {
72    fn inner_puzzle_hash(&self) -> Result<TreeHash> {
73        Ok(SingletonInfo::inner_puzzle_hash(self))
74    }
75
76    fn puzzle_hash(&self) -> Result<TreeHash> {
77        Ok(SingletonInfo::puzzle_hash(self))
78    }
79}
80
81#[derive(Clone)]
82pub struct ParsedOptionInfo {
83    pub info: OptionInfo,
84    pub p2_puzzle: Puzzle,
85}
86
87#[derive(Clone)]
88pub struct ParsedOption {
89    pub option: OptionContract,
90    pub p2_puzzle: Puzzle,
91    pub p2_solution: Program,
92}
93
94pub trait OptionUnderlyingExt: Sized {
95    fn exercise_spend(
96        &self,
97        clvm: Clvm,
98        singleton_inner_puzzle_hash: Bytes32,
99        singleton_amount: u64,
100    ) -> Result<Spend>;
101    fn clawback_spend(&self, spend: Spend) -> Result<Spend>;
102    fn puzzle_hash(&self) -> Result<TreeHash>;
103    fn delegated_puzzle_hash(&self) -> Result<TreeHash>;
104}
105
106impl OptionUnderlyingExt for OptionUnderlying {
107    fn exercise_spend(
108        &self,
109        clvm: Clvm,
110        singleton_inner_puzzle_hash: Bytes32,
111        singleton_amount: u64,
112    ) -> Result<Spend> {
113        let mut ctx = clvm.0.lock().unwrap();
114        let spend = self.exercise_spend(&mut ctx, singleton_inner_puzzle_hash, singleton_amount)?;
115        Ok(Spend {
116            puzzle: Program(clvm.0.clone(), spend.puzzle),
117            solution: Program(clvm.0.clone(), spend.solution),
118        })
119    }
120
121    fn clawback_spend(&self, spend: Spend) -> Result<Spend> {
122        let ctx_clone = spend.puzzle.0.clone();
123        let mut ctx = ctx_clone.lock().unwrap();
124        let spend = self.clawback_spend(&mut ctx, spend.into())?;
125        Ok(Spend {
126            puzzle: Program(ctx_clone.clone(), spend.puzzle),
127            solution: Program(ctx_clone.clone(), spend.solution),
128        })
129    }
130
131    fn puzzle_hash(&self) -> Result<TreeHash> {
132        Ok(self.tree_hash())
133    }
134
135    fn delegated_puzzle_hash(&self) -> Result<TreeHash> {
136        Ok(self.delegated_puzzle().tree_hash())
137    }
138}
139
140pub trait OptionTypeExt: Sized {
141    fn xch(amount: u64) -> Result<Self>;
142    fn cat(asset_id: Bytes32, amount: u64) -> Result<Self>;
143    fn revocable_cat(asset_id: Bytes32, hidden_puzzle_hash: Bytes32, amount: u64) -> Result<Self>;
144    fn nft(launcher_id: Bytes32, settlement_puzzle_hash: Bytes32, amount: u64) -> Result<Self>;
145
146    fn to_xch(&self) -> Result<Option<OptionTypeXch>>;
147    fn to_cat(&self) -> Result<Option<OptionTypeCat>>;
148    fn to_revocable_cat(&self) -> Result<Option<OptionTypeRevocableCat>>;
149    fn to_nft(&self) -> Result<Option<OptionTypeNft>>;
150}
151
152impl OptionTypeExt for OptionType {
153    fn xch(amount: u64) -> Result<Self> {
154        Ok(Self::Xch { amount })
155    }
156
157    fn cat(asset_id: Bytes32, amount: u64) -> Result<Self> {
158        Ok(Self::Cat { asset_id, amount })
159    }
160
161    fn revocable_cat(asset_id: Bytes32, hidden_puzzle_hash: Bytes32, amount: u64) -> Result<Self> {
162        Ok(Self::RevocableCat {
163            asset_id,
164            hidden_puzzle_hash,
165            amount,
166        })
167    }
168
169    fn nft(launcher_id: Bytes32, settlement_puzzle_hash: Bytes32, amount: u64) -> Result<Self> {
170        Ok(Self::Nft {
171            launcher_id,
172            settlement_puzzle_hash,
173            amount,
174        })
175    }
176
177    fn to_xch(&self) -> Result<Option<OptionTypeXch>> {
178        match *self {
179            Self::Xch { amount } => Ok(Some(OptionTypeXch { amount })),
180            _ => Ok(None),
181        }
182    }
183
184    fn to_cat(&self) -> Result<Option<OptionTypeCat>> {
185        match *self {
186            Self::Cat { asset_id, amount } => Ok(Some(OptionTypeCat { asset_id, amount })),
187            _ => Ok(None),
188        }
189    }
190
191    fn to_revocable_cat(&self) -> Result<Option<OptionTypeRevocableCat>> {
192        match *self {
193            Self::RevocableCat {
194                asset_id,
195                hidden_puzzle_hash,
196                amount,
197            } => Ok(Some(OptionTypeRevocableCat {
198                asset_id,
199                hidden_puzzle_hash,
200                amount,
201            })),
202            _ => Ok(None),
203        }
204    }
205
206    fn to_nft(&self) -> Result<Option<OptionTypeNft>> {
207        match *self {
208            Self::Nft {
209                launcher_id,
210                settlement_puzzle_hash,
211                amount,
212            } => Ok(Some(OptionTypeNft {
213                launcher_id,
214                settlement_puzzle_hash,
215                amount,
216            })),
217            _ => Ok(None),
218        }
219    }
220}
221#[derive(Clone)]
222pub struct OptionTypeXch {
223    pub amount: u64,
224}
225
226#[derive(Clone)]
227pub struct OptionTypeCat {
228    pub asset_id: Bytes32,
229    pub amount: u64,
230}
231
232#[derive(Clone)]
233pub struct OptionTypeRevocableCat {
234    pub asset_id: Bytes32,
235    pub hidden_puzzle_hash: Bytes32,
236    pub amount: u64,
237}
238
239#[derive(Clone)]
240pub struct OptionTypeNft {
241    pub launcher_id: Bytes32,
242    pub settlement_puzzle_hash: Bytes32,
243    pub amount: u64,
244}
245
246pub trait OptionMetadataExt {}
247
248impl OptionMetadataExt for OptionMetadata {}