chia_sdk_parser/puzzles/
singleton.rs

1use chia_protocol::{Bytes32, Coin};
2use chia_puzzles::{
3    singleton::{SingletonArgs, SINGLETON_LAUNCHER_PUZZLE_HASH, SINGLETON_TOP_LAYER_PUZZLE_HASH},
4    LineageProof,
5};
6use clvm_traits::FromClvm;
7use clvmr::{Allocator, NodePtr};
8
9use crate::{ParseError, Puzzle};
10
11#[derive(Debug, Clone, Copy)]
12pub struct SingletonPuzzle {
13    pub launcher_id: Bytes32,
14    pub inner_puzzle: Puzzle,
15}
16
17impl SingletonPuzzle {
18    pub fn parse(
19        allocator: &Allocator,
20        puzzle: &Puzzle,
21    ) -> Result<Option<SingletonPuzzle>, ParseError> {
22        let Some(puzzle) = puzzle.as_curried() else {
23            return Ok(None);
24        };
25
26        if puzzle.mod_hash != SINGLETON_TOP_LAYER_PUZZLE_HASH {
27            return Ok(None);
28        }
29
30        let args = SingletonArgs::<NodePtr>::from_clvm(allocator, puzzle.args)?;
31
32        if args.singleton_struct.mod_hash != SINGLETON_TOP_LAYER_PUZZLE_HASH.into()
33            || args.singleton_struct.launcher_puzzle_hash != SINGLETON_LAUNCHER_PUZZLE_HASH.into()
34        {
35            return Err(ParseError::InvalidSingletonStruct);
36        }
37
38        Ok(Some(SingletonPuzzle {
39            launcher_id: args.singleton_struct.launcher_id,
40            inner_puzzle: Puzzle::parse(allocator, args.inner_puzzle),
41        }))
42    }
43
44    pub fn lineage_proof(&self, parent_coin: Coin) -> LineageProof {
45        LineageProof {
46            parent_parent_coin_id: parent_coin.parent_coin_info,
47            parent_inner_puzzle_hash: self.inner_puzzle.curried_puzzle_hash().into(),
48            parent_amount: parent_coin.amount,
49        }
50    }
51}