open_creator_protocol/
state.rs1use crate::{action::ActionCtx, errors::OCPErrorCode, royalty::DynamicRoyalty};
2use anchor_lang::prelude::*;
3use anchor_lang::solana_program::pubkey::Pubkey;
4use json_rules_engine_fork::{Rule, Status};
5use serde::{Deserialize, Serialize};
6use serde_json::Value;
7
8#[account]
9#[derive(Default, Serialize, Deserialize)]
10pub struct MintState {
11 pub version: u8,
12 pub bump: [u8; 1],
13 pub mint: Pubkey,
14 pub policy: Pubkey,
15 pub locked_by: Option<Pubkey>,
16 pub last_approved_at: i64,
17 pub last_transferred_at: i64,
18 pub transferred_count: u32,
19}
20
21impl MintState {
22 pub const LEN: usize = 200;
23 pub const SEED: &'static str = "mint_state";
24
25 pub fn record_transfer(&mut self) {
26 self.last_transferred_at = Clock::get().unwrap().unix_timestamp;
27 self.transferred_count = self.transferred_count.checked_add(1).unwrap_or(u32::MAX);
28 }
29 pub fn record_approve(&mut self) {
30 self.last_approved_at = Clock::get().unwrap().unix_timestamp;
31 }
32}
33
34#[account]
35#[derive(Default, Serialize, Deserialize)]
36pub struct Policy {
37 pub version: u8,
38 pub bump: [u8; 1],
39 pub uuid: Pubkey,
40 pub authority: Pubkey,
41 pub dynamic_royalty: Option<DynamicRoyalty>,
42 pub json_rule: Option<String>,
43}
44
45impl Policy {
46 pub const LEN: usize = Policy::JSON_RULE_MAX_LEN + 400 ;
47 pub const SEED: &'static str = "policy";
48 pub const MANAGED_AUTHORITY: &'static str = "RULERZZDGsXqd9TeJu5ikLfbXzBFpoDPT8N3FHRhq1T";
49 pub const JSON_RULE_MAX_LEN: usize = 1000;
50
51 pub fn valid(&self) -> Result<()> {
52 match &self.json_rule {
53 Some(json_rule) => {
54 if json_rule.len() > Policy::JSON_RULE_MAX_LEN {
55 return Err(OCPErrorCode::InvalidPolicyCreation.into());
56 }
57 serde_json::from_str::<Rule>(json_rule).expect("json_rule should be valid");
58 }
59 None => {}
60 }
61 match &self.dynamic_royalty {
62 Some(dynamic_royalty) => {
63 dynamic_royalty.valid()?;
64 }
65 None => {}
66 }
67 Ok(())
68 }
69
70 pub fn is_managed(&self) -> bool {
71 self.authority.to_string() == Policy::MANAGED_AUTHORITY
72 }
73
74 pub fn matches(&self, ctx: &ActionCtx) -> Result<()> {
75 match &self.json_rule {
76 Some(json_rule) => {
77 if json_rule.is_empty() {
78 return Ok(());
79 }
80 let rule: Rule = serde_json::from_str::<Rule>(json_rule).expect("json_rule should be valid");
81 let fact: &Value = &serde_json::to_value::<&ActionCtx>(ctx).expect("action_ctx should be serializable");
82 let result = rule.check_value(fact);
83 if result.condition_result.status != Status::Met {
84 msg!("Policy does not match: {}", result.condition_result.name);
85 msg!("fact: {}", fact);
86 return Err(OCPErrorCode::InvalidPolicyEvaluation.into());
87 }
88 }
89 None => {}
90 }
91
92 Ok(())
93 }
94
95 pub fn signer_seeds(&self) -> [&[u8]; 3] {
96 [Policy::SEED.as_bytes(), self.uuid.as_ref(), &self.bump]
97 }
98
99 pub fn get_freeze_authority(&self, upstream_authority: Pubkey) -> Pubkey {
100 let (freeze_authority, _) = Pubkey::find_program_address(&[upstream_authority.as_ref()], &community_managed_token::id());
101 freeze_authority
102 }
103}