datalayer_driver/
dig_coin.rs1use crate::error::WalletError;
2use crate::wallet::DIG_ASSET_ID;
3use crate::{Bytes32, Coin, Peer};
4use chia::protocol::CoinState;
5use chia::puzzles::cat::CatArgs;
6use chia_wallet_sdk::driver::{Asset, Cat, Puzzle, SpendContext};
7use chia_wallet_sdk::prelude::{TreeHash, MAINNET_CONSTANTS};
8
9pub struct DigCoin {
10 cat: Cat,
11}
12
13impl DigCoin {
14 #[inline]
15 pub fn cat(&self) -> Cat {
16 self.cat
17 }
18
19 pub fn puzzle_hash(wallet_puzzle_hash: Bytes32) -> Bytes32 {
20 let ph_bytes =
21 CatArgs::curry_tree_hash(DIG_ASSET_ID, TreeHash::from(wallet_puzzle_hash)).to_bytes();
22 Bytes32::from(ph_bytes)
23 }
24
25 pub async fn from_coin_state(peer: &Peer, coin_state: &CoinState) -> Result<Self, WalletError> {
26 let coin_created_height = coin_state.created_height.ok_or(WalletError::Parse(
27 "Cannot determine coin creation height".to_string(),
28 ))?;
29 Self::from_coin(peer, &coin_state.coin, coin_created_height).await
30 }
31
32 pub async fn from_coin(
35 peer: &Peer,
36 coin: &Coin,
37 coin_created_height: u32,
38 ) -> Result<Self, WalletError> {
39 let mut ctx = SpendContext::new();
40
41 let parent_state_response = peer
43 .request_coin_state(
44 vec![coin.parent_coin_info],
45 None,
46 MAINNET_CONSTANTS.genesis_challenge,
47 false,
48 )
49 .await?;
50
51 let parent_state = parent_state_response.map_err(|_| WalletError::RejectCoinState)?;
52
53 let parent_puzzle_and_solution_response = peer
55 .request_puzzle_and_solution(parent_state.coin_ids[0], coin_created_height)
56 .await?;
57
58 let parent_puzzle_and_solution =
59 parent_puzzle_and_solution_response.map_err(|_| WalletError::RejectPuzzleSolution)?;
60
61 let parent_puzzle_ptr = ctx.alloc(&parent_puzzle_and_solution.puzzle)?;
63 let parent_puzzle = Puzzle::parse(&ctx, parent_puzzle_ptr);
64
65 let parent_solution = ctx.alloc(&parent_puzzle_and_solution.solution)?;
67
68 let parsed_children = Cat::parse_children(
70 &mut ctx,
71 parent_state.coin_states[0].coin,
72 parent_puzzle,
73 parent_solution,
74 )?
75 .ok_or(WalletError::UnknownCoin)?;
76
77 let proved_cat = parsed_children
78 .into_iter()
79 .find(|parsed_child| {
80 parsed_child.coin_id() == coin.coin_id()
81 && parsed_child.lineage_proof.is_some()
82 && parsed_child.info.asset_id == DIG_ASSET_ID
83 })
84 .ok_or_else(|| WalletError::UnknownCoin)?;
85
86 Ok(Self { cat: proved_cat })
87 }
88}