mpl_candy_guard/guards/
mod.rs1use std::collections::BTreeMap;
2
3pub use anchor_lang::prelude::*;
4
5pub use crate::{errors::CandyGuardError, instructions::mint::*, state::GuardSet};
6use crate::{
7 instructions::{MintAccounts, Route, RouteContext},
8 state::CandyGuardData,
9};
10
11pub use address_gate::AddressGate;
12pub use allocation::Allocation;
13pub use allow_list::AllowList;
14pub use bot_tax::BotTax;
15pub use end_date::EndDate;
16pub use freeze_sol_payment::{FreezeEscrow, FreezeInstruction, FreezeSolPayment};
17pub use freeze_token_payment::FreezeTokenPayment;
18pub use gatekeeper::Gatekeeper;
19pub use mint_limit::{MintCounter, MintLimit};
20pub use nft_burn::NftBurn;
21pub use nft_gate::NftGate;
22pub use nft_payment::NftPayment;
23pub use program_gate::ProgramGate;
24pub use redeemed_amount::RedeemedAmount;
25pub use sol_payment::SolPayment;
26pub use start_date::StartDate;
27pub use third_party_signer::ThirdPartySigner;
28pub use token_burn::TokenBurn;
29pub use token_gate::TokenGate;
30pub use token_payment::TokenPayment;
31
32mod address_gate;
33mod allocation;
34mod allow_list;
35mod bot_tax;
36mod end_date;
37mod freeze_sol_payment;
38mod freeze_token_payment;
39mod gatekeeper;
40mod mint_limit;
41mod nft_burn;
42mod nft_gate;
43mod nft_payment;
44mod program_gate;
45mod redeemed_amount;
46mod sol_payment;
47mod start_date;
48mod third_party_signer;
49mod token_burn;
50mod token_gate;
51mod token_payment;
52
53pub trait Condition {
54 fn validate(
64 &self,
65 ctx: &mut EvaluationContext,
66 guard_set: &GuardSet,
67 mint_args: &[u8],
68 ) -> Result<()>;
69
70 fn pre_actions(
75 &self,
76 _ctx: &mut EvaluationContext,
77 _guard_set: &GuardSet,
78 _mint_args: &[u8],
79 ) -> Result<()> {
80 Ok(())
81 }
82
83 fn post_actions(
88 &self,
89 _ctx: &mut EvaluationContext,
90 _guard_set: &GuardSet,
91 _mint_args: &[u8],
92 ) -> Result<()> {
93 Ok(())
94 }
95}
96
97pub trait Guard: Condition + AnchorSerialize + AnchorDeserialize {
98 fn size() -> usize;
100
101 fn mask() -> u64;
103
104 fn instruction<'info>(
107 _ctx: &Context<'_, '_, '_, 'info, Route<'info>>,
108 _route_context: RouteContext<'info>,
109 _data: Vec<u8>,
110 ) -> Result<()> {
111 err!(CandyGuardError::InstructionNotFound)
112 }
113
114 fn is_enabled(features: u64) -> bool {
116 features & Self::mask() > 0
117 }
118
119 fn enable(features: u64) -> u64 {
121 features | Self::mask()
122 }
123
124 fn disable(features: u64) -> u64 {
126 features & !Self::mask()
127 }
128
129 fn save(&self, data: &mut [u8], offset: usize) -> Result<()> {
131 let mut result = Vec::with_capacity(Self::size());
132 self.serialize(&mut result)?;
133
134 data[offset..(result.len() + offset)].copy_from_slice(&result[..]);
135
136 Ok(())
137 }
138
139 fn load(data: &[u8], offset: usize) -> Result<Option<Self>> {
142 if offset <= data.len() {
143 let mut slice = &data[offset - Self::size()..offset];
144 let guard = Self::deserialize(&mut slice)?;
145 Ok(Some(guard))
146 } else {
147 Ok(None)
148 }
149 }
150
151 fn verify(_data: &CandyGuardData) -> Result<()> {
154 Ok(())
155 }
156}
157pub struct EvaluationContext<'b, 'c, 'info> {
158 pub(crate) accounts: MintAccounts<'b, 'c, 'info>,
160
161 pub account_cursor: usize,
164
165 pub args_cursor: usize,
168
169 pub indices: BTreeMap<&'info str, usize>,
171}
172
173pub fn try_get_account_info<T>(remaining_accounts: &[T], index: usize) -> Result<&T> {
176 if index < remaining_accounts.len() {
177 Ok(&remaining_accounts[index])
178 } else {
179 err!(CandyGuardError::MissingRemainingAccount)
180 }
181}
182
183pub fn get_account_info<T>(remaining_accounts: &[T], index: usize) -> Option<&T> {
186 if index < remaining_accounts.len() {
187 Some(&remaining_accounts[index])
188 } else {
189 None
190 }
191}