chia_sdk_driver/action_system/
spend_kind.rs

1use chia_protocol::Bytes32;
2use chia_puzzle_types::offer::{NotarizedPayment, Payment};
3use chia_sdk_types::{
4    conditions::{AssertPuzzleAnnouncement, CreateCoin},
5    payment_assertion, tree_hash_notarized_payment, Conditions,
6};
7use clvmr::{Allocator, NodePtr};
8
9use crate::{Output, OutputConstraints, OutputSet};
10
11mod conditions_spend;
12mod settlement_spend;
13
14pub use conditions_spend::*;
15pub use settlement_spend::*;
16
17#[derive(Debug, Clone)]
18pub enum SpendKind {
19    Conditions(ConditionsSpend),
20    Settlement(SettlementSpend),
21}
22
23impl SpendKind {
24    pub fn conditions() -> Self {
25        Self::Conditions(ConditionsSpend::new())
26    }
27
28    pub fn settlement() -> Self {
29        Self::Settlement(SettlementSpend::new())
30    }
31
32    pub fn is_conditions(&self) -> bool {
33        matches!(self, Self::Conditions(_))
34    }
35
36    pub fn is_settlement(&self) -> bool {
37        matches!(self, Self::Settlement(_))
38    }
39
40    pub fn create_coin_with_assertion(
41        &mut self,
42        allocator: &Allocator,
43        parent_puzzle_hash: Bytes32,
44        payment_assertions: &mut Vec<AssertPuzzleAnnouncement>,
45        create_coin: CreateCoin<NodePtr>,
46    ) {
47        match self {
48            SpendKind::Conditions(spend) => {
49                spend.add_conditions(Conditions::new().with(create_coin));
50            }
51            SpendKind::Settlement(spend) => {
52                // TODO: Use nil for the nonce from the payment
53                let notarized_payment = NotarizedPayment::new(
54                    Bytes32::default(),
55                    vec![Payment::new(
56                        create_coin.puzzle_hash,
57                        create_coin.amount,
58                        create_coin.memos,
59                    )],
60                );
61                payment_assertions.push(payment_assertion(
62                    parent_puzzle_hash,
63                    tree_hash_notarized_payment(allocator, &notarized_payment),
64                ));
65                spend.add_notarized_payment(notarized_payment);
66            }
67        }
68    }
69
70    pub fn create_intermediate_coin(&mut self, create_coin: CreateCoin<NodePtr>) {
71        match self {
72            Self::Conditions(spend) => {
73                spend.add_conditions(Conditions::new().with(create_coin));
74            }
75            Self::Settlement(spend) => {
76                // TODO: Use nil for the nonce from the payment
77                spend.add_notarized_payment(NotarizedPayment {
78                    nonce: Bytes32::default(),
79                    payments: vec![Payment::new(
80                        create_coin.puzzle_hash,
81                        create_coin.amount,
82                        create_coin.memos,
83                    )],
84                });
85            }
86        }
87    }
88
89    #[must_use]
90    pub fn empty_copy(&self) -> Self {
91        match self {
92            Self::Conditions(_) => Self::conditions(),
93            Self::Settlement(_) => Self::settlement(),
94        }
95    }
96}
97
98impl OutputSet for SpendKind {
99    fn has_output(&self, output: &Output) -> bool {
100        match self {
101            Self::Conditions(spend) => spend.has_output(output),
102            Self::Settlement(spend) => spend.has_output(output),
103        }
104    }
105
106    fn can_run_cat_tail(&self) -> bool {
107        match self {
108            Self::Conditions(spend) => spend.can_run_cat_tail(),
109            Self::Settlement(spend) => spend.can_run_cat_tail(),
110        }
111    }
112
113    fn missing_singleton_output(&self) -> bool {
114        match self {
115            Self::Conditions(spend) => spend.missing_singleton_output(),
116            Self::Settlement(spend) => spend.missing_singleton_output(),
117        }
118    }
119
120    fn is_allowed(&self, output: &Output, output_constraints: &OutputConstraints) -> bool {
121        match self {
122            Self::Conditions(spend) => spend.is_allowed(output, output_constraints),
123            Self::Settlement(spend) => spend.is_allowed(output, output_constraints),
124        }
125    }
126}