use chia_protocol::Bytes32;
use chia_sdk_types::{
Conditions, Mod, announcement_id,
puzzles::{
RewardDistributorAddIncentivesActionArgs, RewardDistributorAddIncentivesActionSolution,
},
};
use clvm_utils::{ToTreeHash, TreeHash};
use clvmr::NodePtr;
use crate::{
DriverError, RewardDistributor, RewardDistributorAddIncentivesActionLog,
RewardDistributorConstants, RewardDistributorCreatedAnnouncementPrefix,
RewardDistributorStateTransition, SingletonAction, Spend, SpendContext,
};
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct RewardDistributorAddIncentivesAction {
pub fee_payout_puzzle_hash: Bytes32,
pub fee_bps: u64,
pub precision: u64,
}
impl ToTreeHash for RewardDistributorAddIncentivesAction {
fn tree_hash(&self) -> TreeHash {
RewardDistributorAddIncentivesActionArgs {
fee_payout_puzzle_hash: self.fee_payout_puzzle_hash,
fee_bps: self.fee_bps,
precision: self.precision,
}
.curry_tree_hash()
}
}
impl SingletonAction<RewardDistributor> for RewardDistributorAddIncentivesAction {
fn from_constants(constants: &RewardDistributorConstants) -> Self {
Self {
fee_payout_puzzle_hash: constants.fee_payout_puzzle_hash,
fee_bps: constants.fee_bps,
precision: constants.precision,
}
}
}
impl RewardDistributorAddIncentivesAction {
fn construct_puzzle(&self, ctx: &mut SpendContext) -> Result<NodePtr, DriverError> {
ctx.curry(RewardDistributorAddIncentivesActionArgs {
fee_payout_puzzle_hash: self.fee_payout_puzzle_hash,
fee_bps: self.fee_bps,
precision: self.precision,
})
}
pub fn get_log(
ctx: &SpendContext,
solution: NodePtr,
changes: RewardDistributorStateTransition,
) -> Result<RewardDistributorAddIncentivesActionLog, DriverError> {
let solution = ctx.extract::<RewardDistributorAddIncentivesActionSolution>(solution)?;
Ok(RewardDistributorAddIncentivesActionLog {
amount: solution.amount,
manager_fee: solution.manager_fee,
changes,
})
}
pub fn spend(
self,
ctx: &mut SpendContext,
distributor: &mut RewardDistributor,
amount: u64,
) -> Result<Conditions, DriverError> {
let my_state = distributor.pending_spend.latest_state.1;
let add_incentives_announcement =
Conditions::new().assert_puzzle_announcement(announcement_id(
distributor.coin.puzzle_hash,
RewardDistributorCreatedAnnouncementPrefix::add_incentives(
amount,
my_state.round_time_info.last_update,
),
));
let action_solution = ctx.alloc(&RewardDistributorAddIncentivesActionSolution {
amount,
manager_fee: amount * distributor.info.constants.fee_bps / 10000,
})?;
let action_puzzle = self.construct_puzzle(ctx)?;
distributor.insert_action_spend(ctx, Spend::new(action_puzzle, action_solution))?;
Ok(add_incentives_announcement)
}
}