chia_sdk_driver/layers/action_layer/actions/xchandles/
oracle.rs

1use chia_protocol::Bytes32;
2use chia_sdk_types::{
3    Conditions, Mod, announcement_id,
4    puzzles::{XchandlesOracleActionArgs, XchandlesSlotValue},
5};
6use clvm_utils::{ToTreeHash, TreeHash};
7use clvmr::NodePtr;
8
9use crate::{
10    DriverError, SingletonAction, Slot, Spend, SpendContext, XchandlesConstants, XchandlesRegistry,
11};
12
13#[derive(Debug, Clone, Copy, PartialEq, Eq)]
14pub struct XchandlesOracleAction {
15    pub launcher_id: Bytes32,
16}
17
18impl ToTreeHash for XchandlesOracleAction {
19    fn tree_hash(&self) -> TreeHash {
20        Self::new_args(self.launcher_id).curry_tree_hash()
21    }
22}
23
24impl SingletonAction<XchandlesRegistry> for XchandlesOracleAction {
25    fn from_constants(constants: &XchandlesConstants) -> Self {
26        Self {
27            launcher_id: constants.launcher_id,
28        }
29    }
30}
31
32impl XchandlesOracleAction {
33    pub fn new_args(launcher_id: Bytes32) -> XchandlesOracleActionArgs {
34        XchandlesOracleActionArgs {
35            slot_1st_curry_hash: Slot::<()>::first_curry_hash(launcher_id, 0).into(),
36        }
37    }
38
39    fn construct_puzzle(&self, ctx: &mut SpendContext) -> Result<NodePtr, DriverError> {
40        ctx.curry(Self::new_args(self.launcher_id))
41    }
42
43    pub fn spent_slot_value(
44        ctx: &SpendContext,
45        solution: NodePtr,
46    ) -> Result<XchandlesSlotValue, DriverError> {
47        let slot_value = ctx.extract::<XchandlesSlotValue>(solution)?;
48
49        Ok(slot_value)
50    }
51
52    pub fn created_slot_value(spent_slot_value: XchandlesSlotValue) -> XchandlesSlotValue {
53        spent_slot_value
54    }
55
56    pub fn spend(
57        self,
58        ctx: &mut SpendContext,
59        registry: &mut XchandlesRegistry,
60        slot: Slot<XchandlesSlotValue>,
61    ) -> Result<Conditions, DriverError> {
62        // spend self
63        let slot = registry.actual_slot(slot);
64        let action_solution = ctx.alloc(&slot.info.value)?;
65        let action_puzzle = self.construct_puzzle(ctx)?;
66
67        registry.insert_action_spend(ctx, Spend::new(action_puzzle, action_solution))?;
68
69        let new_slot = Self::created_slot_value(slot.info.value.clone());
70
71        // spend slot
72        slot.spend(ctx, registry.info.inner_puzzle_hash().into())?;
73
74        let mut oracle_ann = new_slot.tree_hash().to_vec();
75        oracle_ann.insert(0, b'o');
76        Ok(Conditions::new()
77            .assert_puzzle_announcement(announcement_id(registry.coin.puzzle_hash, oracle_ann)))
78    }
79}