mpl_token_auth_rules/state/v2/constraint/
frequency.rs

1use solana_program::{
2    msg,
3    pubkey::{Pubkey, PUBKEY_BYTES},
4};
5
6use crate::{
7    error::RuleSetError,
8    state::{try_from_bytes, RuleResult},
9    state::{
10        v2::{Constraint, ConstraintType, HEADER_SECTION},
11        Header,
12    },
13};
14
15/// Constraint representing a comparison based on time between operations.
16///
17/// Currently not implemented. This constraint is planned check to ensure a certain
18/// amount of time has passed.  This rule will make use of the `rule_set_state_pda`
19/// optional account passed into `Validate`, and will require the optional
20/// `rule_authority` account to sign.
21pub struct Frequency<'a> {
22    /// The authority of the frequency account.
23    pub authority: &'a Pubkey,
24}
25
26impl<'a> Frequency<'a> {
27    /// Deserialize a constraint from a byte array.
28    pub fn from_bytes(bytes: &'a [u8]) -> Result<Self, RuleSetError> {
29        let authority = try_from_bytes::<Pubkey>(0, PUBKEY_BYTES, bytes)?;
30        Ok(Self { authority })
31    }
32
33    /// Serialize a constraint into a byte array.
34    pub fn serialize(authority: Pubkey) -> Result<Vec<u8>, RuleSetError> {
35        let length = PUBKEY_BYTES as u32;
36        let mut data = Vec::with_capacity(HEADER_SECTION + length as usize);
37
38        // Header
39        Header::serialize(ConstraintType::Frequency, length, &mut data);
40
41        // Constraint
42        // - pubkey
43        data.extend(authority.as_ref());
44
45        Ok(data)
46    }
47}
48
49impl<'a> Constraint<'a> for Frequency<'a> {
50    fn constraint_type(&self) -> ConstraintType {
51        ConstraintType::Frequency
52    }
53
54    fn validate(
55        &self,
56        _accounts: &std::collections::HashMap<
57            solana_program::pubkey::Pubkey,
58            &solana_program::account_info::AccountInfo,
59        >,
60        _payload: &crate::payload::Payload,
61        _update_rule_state: bool,
62        _rule_set_state_pda: &Option<&solana_program::account_info::AccountInfo>,
63        rule_authority: &Option<&solana_program::account_info::AccountInfo>,
64    ) -> RuleResult {
65        msg!("Validating Frequency");
66
67        if let Some(rule_authority) = rule_authority {
68            // TODO: If it's the wrong account (first condition) the `IsNotASigner`
69            // is misleading.  Should be improved, perhaps with a `Mismatch` error.
70            if self.authority != rule_authority.key || !rule_authority.is_signer {
71                return RuleResult::Error(RuleSetError::RuleAuthorityIsNotSigner.into());
72            }
73        } else {
74            return RuleResult::Error(RuleSetError::MissingAccount.into());
75        }
76
77        RuleResult::Error(RuleSetError::NotImplemented.into())
78    }
79}