name_tokenizer/processor/
edit_data.rs1use {
4 bonfida_utils::{
5 checks::{check_account_key, check_account_owner, check_signer},
6 BorshSize, InstructionsAccount,
7 },
8 borsh::{BorshDeserialize, BorshSerialize},
9 solana_program::{
10 account_info::{next_account_info, AccountInfo},
11 entrypoint::ProgramResult,
12 program::invoke_signed,
13 program_error::ProgramError,
14 pubkey::Pubkey,
15 },
16};
17
18use solana_program::{msg, program_pack::Pack};
19use spl_name_service::instruction::update;
20use spl_token::state::Account;
21
22use crate::state::{NftRecord, Tag};
23
24#[derive(BorshDeserialize, BorshSerialize, BorshSize)]
25pub struct Params {
26 pub offset: u32,
28 pub data: Vec<u8>,
30}
31
32#[derive(InstructionsAccount, Debug)]
33pub struct Accounts<'a, T> {
34 #[cons(signer)]
36 pub nft_owner: &'a T,
37
38 pub nft_account: &'a T,
40
41 pub nft_record: &'a T,
43
44 #[cons(writable)]
46 pub name_account: &'a T,
47
48 pub spl_token_program: &'a T,
50
51 pub spl_name_service_program: &'a T,
53}
54
55impl<'a, 'b: 'a> Accounts<'a, AccountInfo<'b>> {
56 pub fn parse(
57 accounts: &'a [AccountInfo<'b>],
58 program_id: &Pubkey,
59 ) -> Result<Self, ProgramError> {
60 let accounts_iter = &mut accounts.iter();
61 let accounts = Accounts {
62 nft_owner: next_account_info(accounts_iter)?,
63 nft_account: next_account_info(accounts_iter)?,
64 nft_record: next_account_info(accounts_iter)?,
65 name_account: next_account_info(accounts_iter)?,
66 spl_token_program: next_account_info(accounts_iter)?,
67 spl_name_service_program: next_account_info(accounts_iter)?,
68 };
69
70 check_account_key(accounts.spl_token_program, &spl_token::ID)?;
72 check_account_key(accounts.spl_name_service_program, &spl_name_service::ID)?;
73
74 check_account_owner(accounts.nft_account, &spl_token::ID)?;
76 check_account_owner(accounts.nft_record, program_id)?;
77 check_account_owner(accounts.name_account, &spl_name_service::ID)?;
78
79 check_signer(accounts.nft_owner)?;
81
82 Ok(accounts)
83 }
84}
85
86pub fn process(program_id: &Pubkey, accounts: &[AccountInfo], params: Params) -> ProgramResult {
87 let accounts = Accounts::parse(accounts, program_id)?;
88
89 let (nft_record_key, _) = NftRecord::find_key(accounts.name_account.key, program_id);
90 check_account_key(accounts.nft_record, &nft_record_key)?;
91
92 let nft_record = NftRecord::from_account_info(accounts.nft_record, Tag::ActiveRecord)?;
93 let nft = Account::unpack(&accounts.nft_account.data.borrow())?;
94
95 if nft.mint != nft_record.nft_mint {
96 msg!("+ NFT mint mismatch");
97 return Err(ProgramError::InvalidArgument);
98 }
99 if nft.amount != 1 {
100 msg!("+ Invalid NFT amount, received {}", nft.amount);
101 return Err(ProgramError::InvalidArgument);
102 }
103 check_account_key(accounts.nft_owner, &nft.owner)?;
104
105 let ix = update(
106 spl_name_service::ID,
107 params.offset,
108 params.data,
109 *accounts.name_account.key,
110 *accounts.nft_record.key,
111 None,
112 )?;
113 let seeds: &[&[u8]] = &[
114 NftRecord::SEED,
115 &accounts.name_account.key.to_bytes(),
116 &[nft_record.nonce],
117 ];
118 invoke_signed(
119 &ix,
120 &[
121 accounts.spl_name_service_program.clone(),
122 accounts.nft_record.clone(),
123 accounts.name_account.clone(),
124 ],
125 &[seeds],
126 )?;
127
128 Ok(())
129}