11use crate :: dig_coin:: DigCoin ;
22use crate :: error:: WalletError ;
33use crate :: wallet:: DIG_ASSET_ID ;
4- use crate :: { Bytes , Bytes32 , Coin , CoinSpend , CoinState , P2ParentCoin , Peer , PublicKey } ;
4+ use crate :: {
5+ Bytes , Bytes32 , Coin , CoinSpend , CoinState , LineageProof , P2ParentCoin , Peer , PublicKey ,
6+ } ;
57use chia:: puzzles:: Memos ;
68use chia:: traits:: Streamable ;
79use chia_wallet_sdk:: driver:: {
@@ -13,6 +15,7 @@ use clvmr::Allocator;
1315use indexmap:: indexmap;
1416use num_bigint:: BigInt ;
1517
18+ #[ derive( Debug , Clone ) ]
1619pub struct DigCollateralCoin {
1720 inner : P2ParentCoin ,
1821 #[ allow( dead_code) ]
@@ -22,8 +25,16 @@ pub struct DigCollateralCoin {
2225}
2326
2427impl DigCollateralCoin {
28+ pub fn coin ( & self ) -> Coin {
29+ self . inner . coin
30+ }
31+
32+ pub fn proof ( & self ) -> LineageProof {
33+ self . inner . proof
34+ }
35+
2536 /// Morphs a DIG store launcher ID into the DIG store collateral coin namespace.
26- pub fn morph_store_launcher_if_for_collateral ( store_launcher_id : Bytes32 ) -> Bytes32 {
37+ pub fn morph_store_launcher_id_for_collateral ( store_launcher_id : Bytes32 ) -> Bytes32 {
2738 ( store_launcher_id, "DIG_STORE_COLLATERAL" )
2839 . tree_hash ( )
2940 . into ( )
@@ -139,67 +150,62 @@ impl DigCollateralCoin {
139150
140151 /// Uses the specified $DIG to create a collateral coin for the provided DIG store ID (launcher ID)
141152 #[ allow( clippy:: result_large_err) ]
142- pub fn create (
153+ pub fn create_collateral (
143154 dig_coins : Vec < DigCoin > ,
144- collateral_amount : u64 ,
155+ amount : u64 ,
145156 store_id : Bytes32 ,
146- mirror_urls : Option < Vec < String > > ,
147157 synthetic_key : PublicKey ,
148158 fee_coins : Vec < Coin > ,
149159 fee : u64 ,
150160 ) -> Result < Vec < CoinSpend > , WalletError > {
151- let p2_parent_inner_hash = P2ParentCoin :: inner_puzzle_hash ( Some ( DIG_ASSET_ID ) ) ;
152-
153161 let mut ctx = SpendContext :: new ( ) ;
154162
155- let morphed_store_id = Self :: morph_store_launcher_if_for_collateral ( store_id) ;
156-
157- let memos = match mirror_urls {
158- Some ( urls) => {
159- let mut memos_vec = Vec :: with_capacity ( urls. len ( ) + 1 ) ;
160- memos_vec. push ( morphed_store_id. to_vec ( ) ) ;
161-
162- for url in & urls {
163- memos_vec. push ( url. as_bytes ( ) . to_vec ( ) ) ;
164- }
165-
166- let memos_node_ptr = ctx. alloc ( & memos_vec) ?;
167- Memos :: Some ( memos_node_ptr)
168- }
169- None => ctx. hint ( morphed_store_id) ?,
170- } ;
171-
172- let actions = [
173- Action :: fee ( fee) ,
174- Action :: send (
175- Id :: Existing ( DIG_ASSET_ID ) ,
176- p2_parent_inner_hash. into ( ) ,
177- collateral_amount,
178- memos,
179- ) ,
180- ] ;
163+ let morphed_store_id = Self :: morph_store_launcher_id_for_collateral ( store_id) ;
164+ let hint = ctx. hint ( morphed_store_id) ?;
181165
182- let p2_layer = StandardLayer :: new ( synthetic_key) ;
183- let p2_puzzle_hash: Bytes32 = p2_layer. tree_hash ( ) . into ( ) ;
184- let mut spends = Spends :: new ( p2_puzzle_hash) ;
166+ Self :: build_coin_spends (
167+ & mut ctx,
168+ hint,
169+ dig_coins,
170+ amount,
171+ synthetic_key,
172+ fee_coins,
173+ fee,
174+ )
175+ }
185176
186- // add collateral coins to spends
187- for dig_coin in dig_coins {
188- spends. add ( dig_coin. cat ( ) ) ;
189- }
177+ #[ allow( clippy:: result_large_err, clippy:: too_many_arguments) ]
178+ pub fn create_mirror (
179+ dig_coins : Vec < DigCoin > ,
180+ amount : u64 ,
181+ store_id : Bytes32 ,
182+ mirror_urls : Vec < String > ,
183+ epoch : BigInt ,
184+ synthetic_key : PublicKey ,
185+ fee_coins : Vec < Coin > ,
186+ fee : u64 ,
187+ ) -> Result < Vec < CoinSpend > , WalletError > {
188+ let mut ctx = SpendContext :: new ( ) ;
189+ let morphed_store_id = Self :: morph_store_launcher_id_for_mirror ( store_id, & epoch) ;
190+ let mut memos_vec = Vec :: with_capacity ( mirror_urls. len ( ) + 1 ) ;
191+ memos_vec. push ( morphed_store_id. to_vec ( ) ) ;
190192
191- // add fee coins to spends
192- for fee_xch_coin in fee_coins {
193- spends. add ( fee_xch_coin) ;
193+ for url in & mirror_urls {
194+ memos_vec. push ( url. as_bytes ( ) . to_vec ( ) ) ;
194195 }
195196
196- let deltas = spends . apply ( & mut ctx , & actions ) ?;
197- let index_map = indexmap ! { p2_puzzle_hash => synthetic_key } ;
197+ let memos_node_ptr = ctx . alloc ( & memos_vec ) ?;
198+ let memos = Memos :: Some ( memos_node_ptr ) ;
198199
199- let _outputs =
200- spends. finish_with_keys ( & mut ctx, & deltas, Relation :: AssertConcurrent , & index_map) ?;
201-
202- Ok ( ctx. take ( ) )
200+ Self :: build_coin_spends (
201+ & mut ctx,
202+ memos,
203+ dig_coins,
204+ amount,
205+ synthetic_key,
206+ fee_coins,
207+ fee,
208+ )
203209 }
204210
205211 /// Builds the spend bundle for spending the $DIG collateral coin to de-collateralize
@@ -216,7 +222,7 @@ impl DigCollateralCoin {
216222
217223 if p2_puzzle_hash != self . inner . proof . parent_inner_puzzle_hash {
218224 return Err ( WalletError :: PuzzleHashMismatch (
219- "This coin is not owned by this wallet" . to_string ( ) ,
225+ "Collateral coin controlled by another wallet" . to_string ( ) ,
220226 ) ) ;
221227 }
222228
@@ -256,4 +262,49 @@ impl DigCollateralCoin {
256262
257263 Ok ( ctx. take ( ) )
258264 }
265+
266+ #[ allow( clippy:: result_large_err) ]
267+ fn build_coin_spends (
268+ ctx : & mut SpendContext ,
269+ memos : Memos ,
270+ dig_coins : Vec < DigCoin > ,
271+ amount : u64 ,
272+ synthetic_key : PublicKey ,
273+ fee_coins : Vec < Coin > ,
274+ fee : u64 ,
275+ ) -> Result < Vec < CoinSpend > , WalletError > {
276+ let p2_parent_inner_hash = P2ParentCoin :: inner_puzzle_hash ( Some ( DIG_ASSET_ID ) ) ;
277+
278+ let actions = [
279+ Action :: fee ( fee) ,
280+ Action :: send (
281+ Id :: Existing ( DIG_ASSET_ID ) ,
282+ p2_parent_inner_hash. into ( ) ,
283+ amount,
284+ memos,
285+ ) ,
286+ ] ;
287+
288+ let p2_layer = StandardLayer :: new ( synthetic_key) ;
289+ let p2_puzzle_hash: Bytes32 = p2_layer. tree_hash ( ) . into ( ) ;
290+ let mut spends = Spends :: new ( p2_puzzle_hash) ;
291+
292+ // add collateral coins to spends
293+ for dig_coin in dig_coins {
294+ spends. add ( dig_coin. cat ( ) ) ;
295+ }
296+
297+ // add fee coins to spends
298+ for fee_xch_coin in fee_coins {
299+ spends. add ( fee_xch_coin) ;
300+ }
301+
302+ let deltas = spends. apply ( ctx, & actions) ?;
303+ let index_map = indexmap ! { p2_puzzle_hash => synthetic_key} ;
304+
305+ let _outputs =
306+ spends. finish_with_keys ( ctx, & deltas, Relation :: AssertConcurrent , & index_map) ?;
307+
308+ Ok ( ctx. take ( ) )
309+ }
259310}
0 commit comments