use chia_protocol::Bytes32;
use chia_puzzle_types::Memos;
use chia_sdk_types::{Condition, conditions::CreateCoin};
use clvm_traits::{FromClvm, clvm_quote};
use clvm_utils::{ToTreeHash, tree_hash};
use clvmr::{Allocator, NodePtr};
use crate::{ClawbackV2, P2ConditionsOrSingleton, RevealedP2Puzzle, Reveals};
#[derive(Debug, Clone)]
pub struct ParsedMemos {
pub p2_puzzle_hash: Bytes32,
pub clawback: Option<ClawbackV2>,
pub human_readable_memos: Vec<String>,
pub fixed_conditions: Option<Vec<Condition>>,
}
pub fn parse_memos(
reveals: &Reveals,
allocator: &Allocator,
p2_create_coin: CreateCoin<NodePtr>,
requires_hint: bool,
) -> ParsedMemos {
let Memos::Some(memos) = p2_create_coin.memos else {
return ParsedMemos {
p2_puzzle_hash: p2_create_coin.puzzle_hash,
clawback: None,
human_readable_memos: Vec::new(),
fixed_conditions: None,
};
};
if let Ok((hint, (clawback_memo, rest))) =
<(Bytes32, (NodePtr, NodePtr))>::from_clvm(allocator, memos)
&& let Some(clawback) = ClawbackV2::from_memo(
allocator,
clawback_memo,
hint,
p2_create_coin.amount,
requires_hint,
p2_create_coin.puzzle_hash,
)
{
return ParsedMemos {
p2_puzzle_hash: clawback.receiver_puzzle_hash,
clawback: Some(clawback),
human_readable_memos: parse_memo_list(allocator, rest),
fixed_conditions: None,
};
}
if let Some(RevealedP2Puzzle::P2ConditionsOrSingleton(p2_conditions_or_singleton)) =
reveals.p2_puzzle(p2_create_coin.puzzle_hash.into())
&& let Ok((_hint, (memo, rest))) =
<(Bytes32, (NodePtr, NodePtr))>::from_clvm(allocator, memos)
&& let Ok(conditions) = Vec::<Condition>::from_clvm(allocator, memo)
&& P2ConditionsOrSingleton::fixed_conditions_hash(
clvm_quote!(tree_hash(allocator, memo)).tree_hash().into(),
) == p2_conditions_or_singleton.fixed_conditions_hash
{
return ParsedMemos {
p2_puzzle_hash: p2_create_coin.puzzle_hash,
clawback: None,
human_readable_memos: parse_memo_list(allocator, rest),
fixed_conditions: Some(conditions),
};
}
if requires_hint && let Ok((_hint, rest)) = <(Bytes32, NodePtr)>::from_clvm(allocator, memos) {
return ParsedMemos {
p2_puzzle_hash: p2_create_coin.puzzle_hash,
clawback: None,
human_readable_memos: parse_memo_list(allocator, rest),
fixed_conditions: None,
};
}
ParsedMemos {
p2_puzzle_hash: p2_create_coin.puzzle_hash,
clawback: None,
human_readable_memos: parse_memo_list(allocator, memos),
fixed_conditions: None,
}
}
fn parse_memo_list(allocator: &Allocator, memos: NodePtr) -> Vec<String> {
let memos = Vec::<NodePtr>::from_clvm(allocator, memos).unwrap_or_default();
let mut result = Vec::new();
for memo in memos {
let Ok(memo) = String::from_clvm(allocator, memo) else {
continue;
};
result.push(memo);
}
result
}