1use crate::PROGRAM_ID;
2
3use super::TokenMetadataDecoder;
4pub mod _use;
5pub mod approve_collection_authority;
6pub mod approve_use_authority;
7pub mod bubblegum_set_collection_size;
8pub mod burn;
9pub mod burn_edition_nft;
10pub mod burn_nft;
11pub mod close_accounts;
12pub mod close_escrow_account;
13pub mod collect;
14pub mod convert_master_edition_v1_to_v2;
15pub mod create;
16pub mod create_escrow_account;
17pub mod create_master_edition;
18pub mod create_master_edition_v3;
19pub mod create_metadata_account;
20pub mod create_metadata_account_v2;
21pub mod create_metadata_account_v3;
22pub mod delegate;
23pub mod deprecated_create_master_edition;
24pub mod deprecated_create_reservation_list;
25pub mod deprecated_mint_new_edition_from_master_edition_via_printing_token;
26pub mod deprecated_mint_printing_tokens;
27pub mod deprecated_mint_printing_tokens_via_token;
28pub mod deprecated_set_reservation_list;
29pub mod freeze_delegated_account;
30pub mod lock;
31pub mod migrate;
32pub mod mint;
33pub mod mint_new_edition_from_master_edition_via_token;
34pub mod mint_new_edition_from_master_edition_via_vault_proxy;
35pub mod print;
36pub mod puff_metadata;
37pub mod remove_creator_verification;
38pub mod resize;
39pub mod revoke;
40pub mod revoke_collection_authority;
41pub mod revoke_use_authority;
42pub mod set_and_verify_collection;
43pub mod set_and_verify_sized_collection_item;
44pub mod set_collection_size;
45pub mod set_token_standard;
46pub mod sign_metadata;
47pub mod thaw_delegated_account;
48pub mod transfer;
49pub mod transfer_out_of_escrow;
50pub mod unlock;
51pub mod unverify;
52pub mod unverify_collection;
53pub mod unverify_sized_collection_item;
54pub mod update;
55pub mod update_metadata_account;
56pub mod update_metadata_account_v2;
57pub mod update_primary_sale_happened_via_token;
58pub mod utilize;
59pub mod verify;
60pub mod verify_collection;
61pub mod verify_sized_collection_item;
62
63#[derive(
64 carbon_core::InstructionType,
65 serde::Serialize,
66 serde::Deserialize,
67 PartialEq,
68 Eq,
69 Debug,
70 Clone,
71 Hash,
72)]
73pub enum TokenMetadataInstruction {
74 CreateMetadataAccount(create_metadata_account::CreateMetadataAccount),
75 UpdateMetadataAccount(update_metadata_account::UpdateMetadataAccount),
76 DeprecatedCreateMasterEdition(deprecated_create_master_edition::DeprecatedCreateMasterEdition),
77 DeprecatedMintNewEditionFromMasterEditionViaPrintingToken(deprecated_mint_new_edition_from_master_edition_via_printing_token::DeprecatedMintNewEditionFromMasterEditionViaPrintingToken),
78 UpdatePrimarySaleHappenedViaToken(update_primary_sale_happened_via_token::UpdatePrimarySaleHappenedViaToken),
79 DeprecatedSetReservationList(deprecated_set_reservation_list::DeprecatedSetReservationList),
80 DeprecatedCreateReservationList(deprecated_create_reservation_list::DeprecatedCreateReservationList),
81 SignMetadata(sign_metadata::SignMetadata),
82 DeprecatedMintPrintingTokensViaToken(deprecated_mint_printing_tokens_via_token::DeprecatedMintPrintingTokensViaToken),
83 DeprecatedMintPrintingTokens(deprecated_mint_printing_tokens::DeprecatedMintPrintingTokens),
84 CreateMasterEdition(create_master_edition::CreateMasterEdition),
85 MintNewEditionFromMasterEditionViaToken(mint_new_edition_from_master_edition_via_token::MintNewEditionFromMasterEditionViaToken),
86 ConvertMasterEditionV1ToV2(convert_master_edition_v1_to_v2::ConvertMasterEditionV1ToV2),
87 MintNewEditionFromMasterEditionViaVaultProxy(mint_new_edition_from_master_edition_via_vault_proxy::MintNewEditionFromMasterEditionViaVaultProxy),
88 PuffMetadata(puff_metadata::PuffMetadata),
89 UpdateMetadataAccountV2(update_metadata_account_v2::UpdateMetadataAccountV2),
90 CreateMetadataAccountV2(create_metadata_account_v2::CreateMetadataAccountV2),
91 CreateMasterEditionV3(create_master_edition_v3::CreateMasterEditionV3),
92 VerifyCollection(verify_collection::VerifyCollection),
93 Utilize(utilize::Utilize),
94 ApproveUseAuthority(approve_use_authority::ApproveUseAuthority),
95 RevokeUseAuthority(revoke_use_authority::RevokeUseAuthority),
96 UnverifyCollection(unverify_collection::UnverifyCollection),
97 ApproveCollectionAuthority(approve_collection_authority::ApproveCollectionAuthority),
98 RevokeCollectionAuthority(revoke_collection_authority::RevokeCollectionAuthority),
99 SetAndVerifyCollection(set_and_verify_collection::SetAndVerifyCollection),
100 FreezeDelegatedAccount(freeze_delegated_account::FreezeDelegatedAccount),
101 ThawDelegatedAccount(thaw_delegated_account::ThawDelegatedAccount),
102 RemoveCreatorVerification(remove_creator_verification::RemoveCreatorVerification),
103 BurnNft(burn_nft::BurnNft),
104 VerifySizedCollectionItem(verify_sized_collection_item::VerifySizedCollectionItem),
105 UnverifySizedCollectionItem(unverify_sized_collection_item::UnverifySizedCollectionItem),
106 SetAndVerifySizedCollectionItem(set_and_verify_sized_collection_item::SetAndVerifySizedCollectionItem),
107 CreateMetadataAccountV3(create_metadata_account_v3::CreateMetadataAccountV3),
108 SetCollectionSize(set_collection_size::SetCollectionSize),
109 SetTokenStandard(set_token_standard::SetTokenStandard),
110 BubblegumSetCollectionSize(bubblegum_set_collection_size::BubblegumSetCollectionSize),
111 BurnEditionNft(burn_edition_nft::BurnEditionNft),
112 CreateEscrowAccount(create_escrow_account::CreateEscrowAccount),
113 CloseEscrowAccount(close_escrow_account::CloseEscrowAccount),
114 TransferOutOfEscrow(transfer_out_of_escrow::TransferOutOfEscrow),
115 Burn(burn::Burn),
116 Create(create::Create),
117 Mint(mint::Mint),
118 Delegate(delegate::Delegate),
119 Revoke(revoke::Revoke),
120 Lock(lock::Lock),
121 Unlock(unlock::Unlock),
122 Migrate(migrate::Migrate),
123 Transfer(transfer::Transfer),
124 Update(update::Update),
125 Use(_use::Use),
126 Verify(verify::Verify),
127 Unverify(unverify::Unverify),
128 Collect(collect::Collect),
129 Print(print::Print),
130 Resize(resize::Resize),
131 CloseAccounts(close_accounts::CloseAccounts),
132}
133
134impl carbon_core::instruction::InstructionDecoder<'_> for TokenMetadataDecoder {
135 type InstructionType = TokenMetadataInstruction;
136
137 fn decode_instruction(
138 &self,
139 instruction: &solana_instruction::Instruction,
140 ) -> Option<carbon_core::instruction::DecodedInstruction<Self::InstructionType>> {
141 if !instruction.program_id.eq(&PROGRAM_ID) {
142 return None;
143 }
144
145 carbon_core::try_decode_instructions!(instruction,
146 TokenMetadataInstruction::CreateMetadataAccount => create_metadata_account::CreateMetadataAccount,
147 TokenMetadataInstruction::UpdateMetadataAccount => update_metadata_account::UpdateMetadataAccount,
148 TokenMetadataInstruction::DeprecatedCreateMasterEdition => deprecated_create_master_edition::DeprecatedCreateMasterEdition,
149 TokenMetadataInstruction::DeprecatedMintNewEditionFromMasterEditionViaPrintingToken => deprecated_mint_new_edition_from_master_edition_via_printing_token::DeprecatedMintNewEditionFromMasterEditionViaPrintingToken,
150 TokenMetadataInstruction::UpdatePrimarySaleHappenedViaToken => update_primary_sale_happened_via_token::UpdatePrimarySaleHappenedViaToken,
151 TokenMetadataInstruction::DeprecatedSetReservationList => deprecated_set_reservation_list::DeprecatedSetReservationList,
152 TokenMetadataInstruction::DeprecatedCreateReservationList => deprecated_create_reservation_list::DeprecatedCreateReservationList,
153 TokenMetadataInstruction::SignMetadata => sign_metadata::SignMetadata,
154 TokenMetadataInstruction::DeprecatedMintPrintingTokensViaToken => deprecated_mint_printing_tokens_via_token::DeprecatedMintPrintingTokensViaToken,
155 TokenMetadataInstruction::DeprecatedMintPrintingTokens => deprecated_mint_printing_tokens::DeprecatedMintPrintingTokens,
156 TokenMetadataInstruction::CreateMasterEdition => create_master_edition::CreateMasterEdition,
157 TokenMetadataInstruction::MintNewEditionFromMasterEditionViaToken => mint_new_edition_from_master_edition_via_token::MintNewEditionFromMasterEditionViaToken,
158 TokenMetadataInstruction::ConvertMasterEditionV1ToV2 => convert_master_edition_v1_to_v2::ConvertMasterEditionV1ToV2,
159 TokenMetadataInstruction::MintNewEditionFromMasterEditionViaVaultProxy => mint_new_edition_from_master_edition_via_vault_proxy::MintNewEditionFromMasterEditionViaVaultProxy,
160 TokenMetadataInstruction::PuffMetadata => puff_metadata::PuffMetadata,
161 TokenMetadataInstruction::UpdateMetadataAccountV2 => update_metadata_account_v2::UpdateMetadataAccountV2,
162 TokenMetadataInstruction::CreateMetadataAccountV2 => create_metadata_account_v2::CreateMetadataAccountV2,
163 TokenMetadataInstruction::CreateMasterEditionV3 => create_master_edition_v3::CreateMasterEditionV3,
164 TokenMetadataInstruction::VerifyCollection => verify_collection::VerifyCollection,
165 TokenMetadataInstruction::Utilize => utilize::Utilize,
166 TokenMetadataInstruction::ApproveUseAuthority => approve_use_authority::ApproveUseAuthority,
167 TokenMetadataInstruction::RevokeUseAuthority => revoke_use_authority::RevokeUseAuthority,
168 TokenMetadataInstruction::UnverifyCollection => unverify_collection::UnverifyCollection,
169 TokenMetadataInstruction::ApproveCollectionAuthority => approve_collection_authority::ApproveCollectionAuthority,
170 TokenMetadataInstruction::RevokeCollectionAuthority => revoke_collection_authority::RevokeCollectionAuthority,
171 TokenMetadataInstruction::SetAndVerifyCollection => set_and_verify_collection::SetAndVerifyCollection,
172 TokenMetadataInstruction::FreezeDelegatedAccount => freeze_delegated_account::FreezeDelegatedAccount,
173 TokenMetadataInstruction::ThawDelegatedAccount => thaw_delegated_account::ThawDelegatedAccount,
174 TokenMetadataInstruction::RemoveCreatorVerification => remove_creator_verification::RemoveCreatorVerification,
175 TokenMetadataInstruction::BurnNft => burn_nft::BurnNft,
176 TokenMetadataInstruction::VerifySizedCollectionItem => verify_sized_collection_item::VerifySizedCollectionItem,
177 TokenMetadataInstruction::UnverifySizedCollectionItem => unverify_sized_collection_item::UnverifySizedCollectionItem,
178 TokenMetadataInstruction::SetAndVerifySizedCollectionItem => set_and_verify_sized_collection_item::SetAndVerifySizedCollectionItem,
179 TokenMetadataInstruction::CreateMetadataAccountV3 => create_metadata_account_v3::CreateMetadataAccountV3,
180 TokenMetadataInstruction::SetCollectionSize => set_collection_size::SetCollectionSize,
181 TokenMetadataInstruction::SetTokenStandard => set_token_standard::SetTokenStandard,
182 TokenMetadataInstruction::BubblegumSetCollectionSize => bubblegum_set_collection_size::BubblegumSetCollectionSize,
183 TokenMetadataInstruction::BurnEditionNft => burn_edition_nft::BurnEditionNft,
184 TokenMetadataInstruction::CreateEscrowAccount => create_escrow_account::CreateEscrowAccount,
185 TokenMetadataInstruction::CloseEscrowAccount => close_escrow_account::CloseEscrowAccount,
186 TokenMetadataInstruction::TransferOutOfEscrow => transfer_out_of_escrow::TransferOutOfEscrow,
187 TokenMetadataInstruction::Burn => burn::Burn,
188 TokenMetadataInstruction::Create => create::Create,
189 TokenMetadataInstruction::Mint => mint::Mint,
190 TokenMetadataInstruction::Delegate => delegate::Delegate,
191 TokenMetadataInstruction::Revoke => revoke::Revoke,
192 TokenMetadataInstruction::Lock => lock::Lock,
193 TokenMetadataInstruction::Unlock => unlock::Unlock,
194 TokenMetadataInstruction::Migrate => migrate::Migrate,
195 TokenMetadataInstruction::Transfer => transfer::Transfer,
196 TokenMetadataInstruction::Update => update::Update,
197 TokenMetadataInstruction::Use => _use::Use,
198 TokenMetadataInstruction::Verify => verify::Verify,
199 TokenMetadataInstruction::Unverify => unverify::Unverify,
200 TokenMetadataInstruction::Collect => collect::Collect,
201 TokenMetadataInstruction::Print => print::Print,
202 TokenMetadataInstruction::Resize => resize::Resize,
203 TokenMetadataInstruction::CloseAccounts => close_accounts::CloseAccounts,
204 )
205 }
206}
207
208#[cfg(test)]
209mod tests {
210 use super::*;
211 use crate::{
212 instructions::{
213 create_metadata_account_v3::{
214 CreateMetadataAccountV3, CreateMetadataAccountV3InstructionAccounts,
215 },
216 TokenMetadataInstruction,
217 },
218 types::{CreateMetadataAccountArgsV3, Creator, DataV2},
219 TokenMetadataDecoder,
220 };
221 use carbon_core::{deserialize::ArrangeAccounts, instruction::InstructionDecoder};
222 use carbon_test_utils::read_instruction;
223 use solana_instruction::AccountMeta;
224 use solana_pubkey::pubkey;
225
226 #[test]
227 fn test_decode_create_metadata_v3_without_rent() {
228 let expected_ix = TokenMetadataInstruction::CreateMetadataAccountV3(CreateMetadataAccountV3 {
229 create_metadata_account_args_v3: CreateMetadataAccountArgsV3 {
230 data: DataV2 {
231 name: "スキズー".to_owned(),
232 symbol: "SKZOO".to_owned(),
233 uri: "https://ipfs.io/ipfs/bafkreigwusbaqy7cgbh3mvij5gu4c2m4msaceoutpw5fyisypych7glzjm".to_owned(),
234 seller_fee_basis_points: 0,
235 creators: Some(
236 vec![
237 Creator {
238 address: pubkey!("WLHv2UAZm6z4KyaaELi5pjdbJh6RESMva1Rnn8pJVVh"),
239 verified: true,
240 share: 100,
241 }
242 ]
243 ),
244 collection: None,
245 uses: None,
246 },
247 is_mutable: false,
248 collection_details: None,
249 }
250 });
251
252 let expected_accounts = vec![
253 AccountMeta::new(
254 pubkey!("FURfzvnjVPdjrfMBRzeSgahzS1xietCqiv8SG9pCS8ke"),
255 false,
256 ),
257 AccountMeta::new(
258 pubkey!("A3p836DWHzDA3DY73QfJSLCqekkhGohNXVAHAa1Qbonk"),
259 true,
260 ),
261 AccountMeta::new_readonly(
262 pubkey!("WLHv2UAZm6z4KyaaELi5pjdbJh6RESMva1Rnn8pJVVh"),
263 false,
264 ),
265 AccountMeta::new(
266 pubkey!("5f5BPCCNeMkekfjFZi18kAYU95rRdM2jToGaNZZwYZX6"),
267 true,
268 ),
269 AccountMeta::new_readonly(
270 pubkey!("WLHv2UAZm6z4KyaaELi5pjdbJh6RESMva1Rnn8pJVVh"),
271 false,
272 ),
273 AccountMeta::new_readonly(pubkey!("11111111111111111111111111111111"), false),
274 ];
275
276 let expected_arranged_accounts = CreateMetadataAccountV3InstructionAccounts {
277 metadata: pubkey!("FURfzvnjVPdjrfMBRzeSgahzS1xietCqiv8SG9pCS8ke"),
278 mint: pubkey!("A3p836DWHzDA3DY73QfJSLCqekkhGohNXVAHAa1Qbonk"),
279 mint_authority: pubkey!("WLHv2UAZm6z4KyaaELi5pjdbJh6RESMva1Rnn8pJVVh"),
280 payer: pubkey!("5f5BPCCNeMkekfjFZi18kAYU95rRdM2jToGaNZZwYZX6"),
281 update_authority: pubkey!("WLHv2UAZm6z4KyaaELi5pjdbJh6RESMva1Rnn8pJVVh"),
282 system_program: pubkey!("11111111111111111111111111111111"),
283 rent: None,
284 };
285
286 let decoder = TokenMetadataDecoder;
287
288 const FIXTURE_PATH: &str = "tests/fixtures/create_metadata_v3_ix.json";
289 let instruction = read_instruction(FIXTURE_PATH).expect("read fixture");
290
291 let decoded_instruction = decoder
292 .decode_instruction(&instruction)
293 .expect("decode instruction");
294
295 let decoded_arranged_accounts =
296 CreateMetadataAccountV3::arrange_accounts(&instruction.accounts)
297 .expect("arrange accounts");
298
299 assert_eq!(decoded_instruction.data, expected_ix);
300 assert_eq!(decoded_instruction.accounts, expected_accounts);
301 assert_eq!(decoded_instruction.program_id, PROGRAM_ID);
302 assert!(decoded_arranged_accounts.rent.is_none());
303 assert_eq!(decoded_arranged_accounts, expected_arranged_accounts);
304 }
305}