miraland_program/
feature.rs1use crate::{
15 account_info::AccountInfo, clock::Slot, instruction::Instruction, program_error::ProgramError,
16 pubkey::Pubkey, rent::Rent, system_instruction,
17};
18
19crate::declare_id!("Feature111111111111111111111111111111111111");
20
21#[derive(Default, Debug, Serialize, Deserialize, PartialEq, Eq)]
22pub struct Feature {
23 pub activated_at: Option<Slot>,
24}
25
26impl Feature {
27 pub const fn size_of() -> usize {
28 9 }
30
31 pub fn from_account_info(account_info: &AccountInfo) -> Result<Self, ProgramError> {
32 if *account_info.owner != id() {
33 return Err(ProgramError::InvalidAccountOwner);
34 }
35 bincode::deserialize(&account_info.data.borrow())
36 .map_err(|_| ProgramError::InvalidAccountData)
37 }
38}
39
40pub fn activate(feature_id: &Pubkey, funding_address: &Pubkey, rent: &Rent) -> Vec<Instruction> {
42 activate_with_lamports(
43 feature_id,
44 funding_address,
45 rent.minimum_balance(Feature::size_of()),
46 )
47}
48
49pub fn activate_with_lamports(
50 feature_id: &Pubkey,
51 funding_address: &Pubkey,
52 lamports: u64,
53) -> Vec<Instruction> {
54 vec![
55 system_instruction::transfer(funding_address, feature_id, lamports),
56 system_instruction::allocate(feature_id, Feature::size_of() as u64),
57 system_instruction::assign(feature_id, &id()),
58 ]
59}
60
61#[cfg(test)]
62mod test {
63 use {super::*, miraland_program::clock::Slot};
64
65 #[test]
66 fn test_feature_size_of() {
67 assert_eq!(Feature::size_of() as u64, {
68 let feature = Feature {
69 activated_at: Some(0),
70 };
71 bincode::serialized_size(&feature).unwrap()
72 });
73 assert!(
74 Feature::size_of() >= bincode::serialized_size(&Feature::default()).unwrap() as usize
75 );
76 assert_eq!(Feature::default(), Feature { activated_at: None });
77
78 let features = [
79 Feature {
80 activated_at: Some(0),
81 },
82 Feature {
83 activated_at: Some(Slot::MAX),
84 },
85 ];
86 for feature in &features {
87 assert_eq!(
88 Feature::size_of(),
89 bincode::serialized_size(feature).unwrap() as usize
90 );
91 }
92 }
93}