#![allow(clippy::missing_const_for_fn)]
use chia_protocol::{Bytes32, Coin, CoinSpend};
use chia_puzzles::{nft::NftIntermediateLauncherArgs, singleton::SINGLETON_LAUNCHER_PUZZLE_HASH};
use chia_sdk_types::{announcement_id, Conditions};
use clvm_utils::CurriedProgram;
use clvmr::{sha2::Sha256, Allocator};
use crate::{DriverError, SpendContext};
use super::Launcher;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[must_use]
pub struct IntermediateLauncher {
mint_number: usize,
mint_total: usize,
intermediate_coin: Coin,
launcher_coin: Coin,
}
impl IntermediateLauncher {
pub fn new(parent_coin_id: Bytes32, mint_number: usize, mint_total: usize) -> Self {
let intermediate_puzzle_hash =
NftIntermediateLauncherArgs::curry_tree_hash(mint_number, mint_total).into();
let intermediate_coin = Coin::new(parent_coin_id, intermediate_puzzle_hash, 0);
let launcher_coin = Coin::new(
intermediate_coin.coin_id(),
SINGLETON_LAUNCHER_PUZZLE_HASH.into(),
1,
);
Self {
mint_number,
mint_total,
intermediate_coin,
launcher_coin,
}
}
pub fn intermediate_coin(&self) -> Coin {
self.intermediate_coin
}
pub fn launcher_coin(&self) -> Coin {
self.launcher_coin
}
pub fn create(self, ctx: &mut SpendContext) -> Result<Launcher, DriverError> {
let mut parent = Conditions::new();
let intermediate_puzzle = ctx.nft_intermediate_launcher()?;
let puzzle = ctx.alloc(&CurriedProgram {
program: intermediate_puzzle,
args: NftIntermediateLauncherArgs::new(self.mint_number, self.mint_total),
})?;
parent = parent.create_coin(self.intermediate_coin.puzzle_hash, 0, Vec::new());
let puzzle_reveal = ctx.serialize(&puzzle)?;
let solution = ctx.serialize(&())?;
ctx.insert(CoinSpend::new(
self.intermediate_coin,
puzzle_reveal,
solution,
));
let mut index_message = Sha256::new();
index_message.update(usize_to_bytes(self.mint_number));
index_message.update(usize_to_bytes(self.mint_total));
Ok(Launcher::from_coin(
self.launcher_coin,
parent.assert_coin_announcement(announcement_id(
self.intermediate_coin.coin_id(),
index_message.finalize(),
)),
))
}
}
fn usize_to_bytes(value: usize) -> Vec<u8> {
let mut allocator = Allocator::new();
let atom = allocator.new_number(value.into()).unwrap();
allocator.atom(atom).as_ref().to_vec()
}