chia_sdk_driver/layers/datalayer/
oracle_layer.rs1use chia_protocol::{Bytes, Bytes32};
2use chia_puzzle_types::Memos;
3use chia_sdk_types::Condition;
4use clvm_traits::{clvm_quote, match_quote, FromClvm, ToClvm};
5use clvmr::{Allocator, NodePtr};
6
7use crate::{DriverError, Layer, Puzzle, Spend, SpendContext};
8
9#[derive(Debug, Clone, Copy, PartialEq, Eq)]
12pub struct OracleLayer {
13 pub oracle_puzzle_hash: Bytes32,
15 pub oracle_fee: u64,
17}
18
19impl OracleLayer {
20 pub fn new(oracle_puzzle_hash: Bytes32, oracle_fee: u64) -> Option<Self> {
23 if oracle_fee % 2 != 0 {
24 return None;
25 }
26
27 Some(Self {
28 oracle_puzzle_hash,
29 oracle_fee,
30 })
31 }
32}
33
34impl Layer for OracleLayer {
35 type Solution = ();
36
37 fn parse_puzzle(allocator: &Allocator, puzzle: Puzzle) -> Result<Option<Self>, DriverError> {
38 let Some(puzzle) = puzzle.as_raw() else {
39 return Ok(None);
40 };
41
42 let (_q, conditions) =
43 <match_quote!(Vec<Condition<NodePtr>>)>::from_clvm(allocator, puzzle.ptr)?;
44 if conditions.len() != 2 {
45 return Ok(None);
46 }
47
48 if let Some(Condition::CreateCoin(create_coin)) = conditions.first() {
49 Ok(Self::new(create_coin.puzzle_hash, create_coin.amount))
50 } else {
51 Ok(None)
52 }
53 }
54
55 fn parse_solution(_: &Allocator, _: NodePtr) -> Result<Self::Solution, DriverError> {
56 Ok(())
57 }
58
59 fn construct_puzzle(&self, ctx: &mut SpendContext) -> Result<NodePtr, DriverError> {
60 if self.oracle_fee % 2 == 1 {
61 return Err(DriverError::Custom("oracle fee must be even".to_string()));
62 }
63
64 let conditions: Vec<Condition<NodePtr>> = vec![
65 Condition::create_coin(self.oracle_puzzle_hash, self.oracle_fee, Memos::None),
66 Condition::create_puzzle_announcement(Bytes::new("$".into())),
67 ];
68
69 Ok(clvm_quote!(conditions).to_clvm(ctx)?)
70 }
71
72 fn construct_solution(
73 &self,
74 _: &mut SpendContext,
75 (): Self::Solution,
76 ) -> Result<NodePtr, DriverError> {
77 Ok(NodePtr::NIL)
78 }
79}
80
81impl OracleLayer {
82 pub fn spend(self, ctx: &mut SpendContext) -> Result<Spend, DriverError> {
83 let puzzle = self.construct_puzzle(ctx)?;
84 let solution = self.construct_solution(ctx, ())?;
85
86 Ok(Spend { puzzle, solution })
87 }
88}