chia_sdk_bindings/
conditions.rs

1use std::sync::{Arc, Mutex};
2
3use bindy::Result;
4use chia_bls::PublicKey;
5use chia_protocol::{Bytes, Bytes32};
6use chia_sdk_driver::SpendContext;
7use chia_sdk_types::conditions::{self, Memos, TradePrice};
8use clvm_traits::{FromClvm, ToClvm};
9use clvmr::NodePtr;
10use paste::paste;
11
12use crate::{Clvm, Program};
13
14trait Convert<T> {
15    fn convert(self, clvm: &Arc<Mutex<SpendContext>>) -> Result<T>;
16}
17
18impl Convert<Program> for NodePtr {
19    fn convert(self, clvm: &Arc<Mutex<SpendContext>>) -> Result<Program> {
20        Ok(Program(clvm.clone(), self))
21    }
22}
23
24impl Convert<NodePtr> for Program {
25    fn convert(self, _clvm: &Arc<Mutex<SpendContext>>) -> Result<NodePtr> {
26        Ok(self.1)
27    }
28}
29
30impl Convert<PublicKey> for PublicKey {
31    fn convert(self, _clvm: &Arc<Mutex<SpendContext>>) -> Result<PublicKey> {
32        Ok(self)
33    }
34}
35
36impl Convert<Bytes> for Bytes {
37    fn convert(self, _clvm: &Arc<Mutex<SpendContext>>) -> Result<Bytes> {
38        Ok(self)
39    }
40}
41
42impl Convert<Bytes32> for Bytes32 {
43    fn convert(self, _clvm: &Arc<Mutex<SpendContext>>) -> Result<Bytes32> {
44        Ok(self)
45    }
46}
47
48impl Convert<u64> for u64 {
49    fn convert(self, _clvm: &Arc<Mutex<SpendContext>>) -> Result<u64> {
50        Ok(self)
51    }
52}
53
54impl Convert<u32> for u32 {
55    fn convert(self, _clvm: &Arc<Mutex<SpendContext>>) -> Result<u32> {
56        Ok(self)
57    }
58}
59
60impl Convert<u8> for u8 {
61    fn convert(self, _clvm: &Arc<Mutex<SpendContext>>) -> Result<u8> {
62        Ok(self)
63    }
64}
65
66impl Convert<TradePrice> for TradePrice {
67    fn convert(self, _clvm: &Arc<Mutex<SpendContext>>) -> Result<TradePrice> {
68        Ok(self)
69    }
70}
71
72impl Convert<Memos<NodePtr>> for Option<Program> {
73    fn convert(self, _clvm: &Arc<Mutex<SpendContext>>) -> Result<Memos<NodePtr>> {
74        Ok(self.map_or(Memos::None, |program| Memos::Some(program.1)))
75    }
76}
77
78impl Convert<Option<Program>> for Memos<NodePtr> {
79    fn convert(self, clvm: &Arc<Mutex<SpendContext>>) -> Result<Option<Program>> {
80        Ok(match self {
81            Memos::None => None,
82            Memos::Some(value) => Some(Program(clvm.clone(), value)),
83        })
84    }
85}
86
87impl<T, U> Convert<Vec<U>> for Vec<T>
88where
89    T: Convert<U>,
90{
91    fn convert(self, clvm: &Arc<Mutex<SpendContext>>) -> Result<Vec<U>> {
92        self.into_iter()
93            .map(|value| T::convert(value, clvm))
94            .collect()
95    }
96}
97
98impl<T, U> Convert<Option<U>> for Option<T>
99where
100    T: Convert<U>,
101{
102    fn convert(self, clvm: &Arc<Mutex<SpendContext>>) -> Result<Option<U>> {
103        self.map(|value| T::convert(value, clvm)).transpose()
104    }
105}
106
107macro_rules! conditions {
108    ( $( $condition:ident $( < $( $generic:ty ),* > )? { $function:ident( $( $name:ident: $ty:ty ),* ) }, )* ) => {
109        $( #[derive(Clone)]
110        pub struct $condition {
111            $( pub $name: $ty, )*
112        } )*
113
114        $( paste! {
115            impl Clvm {
116                pub fn $function( &self, $( $name: $ty ),* ) -> Result<Program> {
117                    let mut ctx = self.0.lock().unwrap();
118                    $( let $name = Convert::convert($name, &self.0)?; )*
119                    let ptr = conditions::$condition $( ::< $( $generic ),* > )? ::new( $( $name ),* )
120                    .to_clvm(&mut **ctx)?;
121                    Ok(Program(self.0.clone(), ptr))
122                }
123            }
124
125            impl Program {
126                #[allow(unused)]
127                pub fn [< parse_ $function >]( &self ) -> Result<Option<$condition>> {
128                    let ctx = self.0.lock().unwrap();
129
130                    let Some(condition) = conditions::$condition $( ::< $( $generic ),* > )? ::from_clvm(&**ctx, self.1).ok() else {
131                        return Ok(None);
132                    };
133
134                    Ok(Some($condition {
135                        $( $name: Convert::convert(condition.$name, &self.0.clone())?, )*
136                    }))
137                }
138            }
139        } )*
140    };
141}
142
143conditions!(
144    Remark<NodePtr> {
145        remark(rest: Program)
146    },
147    AggSigParent {
148        agg_sig_parent(public_key: PublicKey, message: Bytes)
149    },
150    AggSigPuzzle {
151        agg_sig_puzzle(public_key: PublicKey, message: Bytes)
152    },
153    AggSigAmount {
154        agg_sig_amount(public_key: PublicKey, message: Bytes)
155    },
156    AggSigPuzzleAmount {
157        agg_sig_puzzle_amount(public_key: PublicKey, message: Bytes)
158    },
159    AggSigParentAmount {
160        agg_sig_parent_amount(public_key: PublicKey, message: Bytes)
161    },
162    AggSigParentPuzzle {
163        agg_sig_parent_puzzle(public_key: PublicKey, message: Bytes)
164    },
165    AggSigUnsafe {
166        agg_sig_unsafe(public_key: PublicKey, message: Bytes)
167    },
168    AggSigMe {
169        agg_sig_me(public_key: PublicKey, message: Bytes)
170    },
171    CreateCoin {
172        create_coin(puzzle_hash: Bytes32, amount: u64, memos: Option<Program>)
173    },
174    ReserveFee {
175        reserve_fee(amount: u64)
176    },
177    CreateCoinAnnouncement {
178        create_coin_announcement(message: Bytes)
179    },
180    CreatePuzzleAnnouncement {
181        create_puzzle_announcement(message: Bytes)
182    },
183    AssertCoinAnnouncement {
184        assert_coin_announcement(announcement_id: Bytes32)
185    },
186    AssertPuzzleAnnouncement {
187        assert_puzzle_announcement(announcement_id: Bytes32)
188    },
189    AssertConcurrentSpend {
190        assert_concurrent_spend(coin_id: Bytes32)
191    },
192    AssertConcurrentPuzzle {
193        assert_concurrent_puzzle(puzzle_hash: Bytes32)
194    },
195    AssertSecondsRelative {
196        assert_seconds_relative(seconds: u64)
197    },
198    AssertSecondsAbsolute {
199        assert_seconds_absolute(seconds: u64)
200    },
201    AssertHeightRelative {
202        assert_height_relative(height: u32)
203    },
204    AssertHeightAbsolute {
205        assert_height_absolute(height: u32)
206    },
207    AssertBeforeSecondsRelative {
208        assert_before_seconds_relative(seconds: u64)
209    },
210    AssertBeforeSecondsAbsolute {
211        assert_before_seconds_absolute(seconds: u64)
212    },
213    AssertBeforeHeightRelative {
214        assert_before_height_relative(height: u32)
215    },
216    AssertBeforeHeightAbsolute {
217        assert_before_height_absolute(height: u32)
218    },
219    AssertMyCoinId {
220        assert_my_coin_id(coin_id: Bytes32)
221    },
222    AssertMyParentId {
223        assert_my_parent_id(parent_id: Bytes32)
224    },
225    AssertMyPuzzleHash {
226        assert_my_puzzle_hash(puzzle_hash: Bytes32)
227    },
228    AssertMyAmount {
229        assert_my_amount(amount: u64)
230    },
231    AssertMyBirthSeconds {
232        assert_my_birth_seconds(seconds: u64)
233    },
234    AssertMyBirthHeight {
235        assert_my_birth_height(height: u32)
236    },
237    AssertEphemeral {
238        assert_ephemeral()
239    },
240    SendMessage<NodePtr> {
241        send_message(mode: u8, message: Bytes, data: Vec<Program>)
242    },
243    ReceiveMessage<NodePtr> {
244        receive_message(mode: u8, message: Bytes, data: Vec<Program>)
245    },
246    Softfork<NodePtr> {
247        softfork(cost: u64, rest: Program)
248    },
249    MeltSingleton {
250        melt_singleton()
251    },
252    TransferNft {
253        transfer_nft(launcher_id: Option<Bytes32>, trade_prices: Vec<TradePrice>, singleton_inner_puzzle_hash: Option<Bytes32>)
254    },
255    RunCatTail<NodePtr, NodePtr> {
256        run_cat_tail(program: Program, solution: Program)
257    },
258    UpdateNftMetadata<NodePtr, NodePtr> {
259        update_nft_metadata(updater_puzzle_reveal: Program, updater_solution: Program)
260    },
261    UpdateDataStoreMerkleRoot {
262        update_data_store_merkle_root(new_merkle_root: Bytes32, memos: Vec<Bytes>)
263    },
264);