use chia_protocol::Coin;
use chia_puzzle_types::Memos;
use chia_wallet_sdk::driver::{
OptionLauncher, OptionLauncherInfo, OptionType, SpendContext, SpendWithConditions,
};
use crate::error::{Error, Result};
use crate::types::{CreatedOption, OptionSpend, OptionTerms, Owner};
pub fn create(
ctx: &mut SpendContext,
creator: &Owner,
funding_coin: Coin,
terms: &OptionTerms,
) -> Result<OptionSpend> {
if terms.underlying_amount == 0 {
return Err(Error::invalid(
"option underlying amount must be greater than zero",
));
}
if !matches!(terms.strike_type, OptionType::Xch { .. }) {
return Err(Error::invalid(
"CAT/NFT strike exercise not yet supported — see dig-options CAT/NFT follow-up",
));
}
let needed = terms.underlying_amount.checked_add(1).ok_or_else(|| {
Error::invalid("underlying amount overflows the 1-mojo singleton addition")
})?;
if funding_coin.amount < needed {
return Err(Error::invalid(format!(
"funding coin amount {} is too small: need {needed} (underlying {} + 1 mojo singleton)",
funding_coin.amount, terms.underlying_amount
)));
}
let launcher = OptionLauncher::new(
ctx,
funding_coin.coin_id(),
OptionLauncherInfo::new(
terms.creator_puzzle_hash,
terms.owner_puzzle_hash,
terms.expiry_seconds,
terms.underlying_amount,
terms.strike_type,
),
1,
)?;
let underlying = launcher.underlying();
let p2_option = launcher.p2_puzzle_hash();
let underlying_coin = Coin::new(funding_coin.coin_id(), p2_option, terms.underlying_amount);
let launcher = launcher.with_underlying(underlying_coin.coin_id());
let (mint_conditions, option) = launcher.mint(ctx)?;
let conditions = mint_conditions.create_coin(p2_option, terms.underlying_amount, Memos::None);
let inner_spend = creator.spend_with_conditions(ctx, conditions)?;
ctx.spend(funding_coin, inner_spend)?;
Ok(OptionSpend {
coin_spends: ctx.take(),
created: Some(CreatedOption {
option,
underlying,
underlying_coin,
}),
})
}