chia_sdk_driver/layers/action_layer/actions/xchandles/
update.rs1use chia_protocol::{Bytes, Bytes32};
2use chia_puzzles::{SINGLETON_LAUNCHER_HASH, SINGLETON_TOP_LAYER_V1_1_HASH};
3use chia_sdk_types::{
4 Conditions, Mod,
5 puzzles::{
6 XchandlesDataValue, XchandlesSlotValue, XchandlesUpdateActionArgs,
7 XchandlesUpdateActionSolution,
8 },
9};
10use clvm_traits::clvm_tuple;
11use clvm_utils::{ToTreeHash, TreeHash};
12use clvmr::NodePtr;
13
14use crate::{
15 DriverError, SingletonAction, Slot, Spend, SpendContext, XchandlesConstants, XchandlesRegistry,
16};
17
18#[derive(Debug, Clone, Copy, PartialEq, Eq)]
19pub struct XchandlesUpdateAction {
20 pub launcher_id: Bytes32,
21}
22
23impl ToTreeHash for XchandlesUpdateAction {
24 fn tree_hash(&self) -> TreeHash {
25 Self::new_args(self.launcher_id).curry_tree_hash()
26 }
27}
28
29impl SingletonAction<XchandlesRegistry> for XchandlesUpdateAction {
30 fn from_constants(constants: &XchandlesConstants) -> Self {
31 Self {
32 launcher_id: constants.launcher_id,
33 }
34 }
35}
36
37impl XchandlesUpdateAction {
38 pub fn new_args(launcher_id: Bytes32) -> XchandlesUpdateActionArgs {
39 XchandlesUpdateActionArgs {
40 singleton_mod_hash: SINGLETON_TOP_LAYER_V1_1_HASH.into(),
41 singleton_launcher_mod_hash: SINGLETON_LAUNCHER_HASH.into(),
42 slot_1st_curry_hash: Slot::<()>::first_curry_hash(launcher_id, 0).into(),
43 }
44 }
45
46 fn construct_puzzle(&self, ctx: &mut SpendContext) -> Result<NodePtr, DriverError> {
47 ctx.curry(Self::new_args(self.launcher_id))
48 }
49
50 pub fn spent_slot_value(
51 ctx: &SpendContext,
52 solution: NodePtr,
53 ) -> Result<XchandlesSlotValue, DriverError> {
54 let solution = ctx.extract::<XchandlesUpdateActionSolution>(solution)?;
55
56 Ok(solution.current_slot_value)
57 }
58
59 pub fn created_slot_value(
60 ctx: &mut SpendContext,
61 solution: NodePtr,
62 ) -> Result<XchandlesSlotValue, DriverError> {
63 let solution = ctx.extract::<XchandlesUpdateActionSolution>(solution)?;
64
65 Ok(solution.current_slot_value.with_data(
66 solution.new_data.owner_launcher_id,
67 solution.new_data.resolved_data,
68 ))
69 }
70
71 pub fn spend(
72 self,
73 ctx: &mut SpendContext,
74 registry: &mut XchandlesRegistry,
75 slot: Slot<XchandlesSlotValue>,
76 new_owner_launcher_id: Bytes32,
77 new_resolved_data: &Bytes,
78 announcer_inner_puzzle_hash: Bytes32,
79 ) -> Result<Conditions, DriverError> {
80 let slot = registry.actual_slot(slot);
82 let action_solution = ctx.alloc(&XchandlesUpdateActionSolution {
83 current_slot_value: slot.info.value.clone(),
84 new_data: XchandlesDataValue {
85 owner_launcher_id: new_owner_launcher_id,
86 resolved_data: new_resolved_data.clone(),
87 },
88 announcer_inner_puzzle_hash,
89 })?;
90 let action_puzzle = self.construct_puzzle(ctx)?;
91
92 registry.insert_action_spend(ctx, Spend::new(action_puzzle, action_solution))?;
93
94 let my_inner_puzzle_hash = registry.info.inner_puzzle_hash().into();
96
97 let msg: Bytes32 = clvm_tuple!(
98 slot.info.value.handle_hash,
99 clvm_tuple!(new_owner_launcher_id, new_resolved_data.clone())
100 )
101 .tree_hash()
102 .into();
103
104 slot.spend(ctx, my_inner_puzzle_hash)?;
105
106 Ok(Conditions::new().send_message(
107 18,
108 msg.into(),
109 vec![ctx.alloc(®istry.coin.puzzle_hash)?],
110 ))
111 }
112}