기능
자산 소각
자산의 소유자는 Token Metadata 프로그램의 Burn 명령어를 사용하여 자산을 소각할 수 있습니다. 이는 자산과 연관된 모든 가능한 계정을 닫고 닫힌 계정에 이전에 보유된 다양한 임대료 면제 수수료를 소유자에게 이전합니다. 이 명령어는 다음 속성을 받습니다:
- Authority: 소각을 승인하는 서명자. 일반적으로 이는 자산의 소유자이지만 "위임된 권한" 페이지에서 논의된 바와 같이 특정 위임된 권한도 소유자를 대신하여 자산을 소각할 수 있다는 점에 주목하세요.
- Token Owner: 자산의 현재 소유자의 공개 키.
- Token Standard: 소각되는 자산의 표준. 이 명령어는 자산 소각을 위한 통합된 인터페이스를 제공하기 위해 모든 토큰 표준에서 작동합니다. 하지만 프로그래머블이 아닌 자산은 SPL Token 프로그램의 Burn 명령어를 직접 사용하여 소각할 수 있다는 점에 주목할 가치가 있습니다.
Burn 명령어에 의해 닫히는 정확한 계정들은 소각되는 자산의 토큰 표준에 따라 달라집니다. 다음은 각 토큰 표준에 대한 계정을 요약한 표입니다:
| Token Standard | Mint | Token | Metadata | Edition | Token Record | Edition Marker |
|---|---|---|---|---|---|---|
NonFungible | ❌ | ✅ | ✅ | ✅ | ❌ | ❌ |
NonFungibleEdition | ❌ | ✅ | ✅ | ✅ | ❌ | ✅ 모든 인쇄본이 소각된 경우 |
Fungible 및 FungibleAsset | ❌ | ✅ 모든 토큰이 소각된 경우 | ❌ | ❌ | ❌ | ❌ |
ProgrammableNonFungible | ❌ | ✅ | ✅ | ✅ | ✅ | ❌ |
SPL Token 프로그램이 이를 허용하지 않기 때문에 Mint 계정은 절대 닫히지 않는다는 점에 주목하세요.
다음은 Token Metadata에서 자산을 소각하기 위해 우리의 SDK를 사용하는 방법입니다.
NFT 소각
1import { publicKey } from '@metaplex-foundation/umi';
2import { burnV1, TokenStandard } from '@metaplex-foundation/mpl-token-metadata';
3
4// Assuming umi is set up with mplTokenMetadata plugin
5// See getting-started for full setup
6
7const mintAddress = publicKey('mintAddress...');
8
9// Burn the NFT (removes all accounts and closes token account)
10await burnV1(umi, {
11 mint: mintAddress,
12 authority: umi.identity,
13 tokenOwner: umi.identity.publicKey,
14 tokenStandard: TokenStandard.NonFungible,
15}).sendAndConfirm(umi);
16
17console.log('NFT burned:', mintAddress);
1import {
2 getBurnV1InstructionAsync,
3 TokenStandard,
4} from '@metaplex-foundation/mpl-token-metadata-kit';
5
6// Assuming rpc, rpcSubscriptions, sendAndConfirm, and authority are set up
7// See getting-started for full setup
8
9const mintAddress = 'mintAddress...'; // The NFT mint address
10
11// Burn the NFT (removes all accounts and closes token account)
12const burnIx = await getBurnV1InstructionAsync({
13 mint: mintAddress,
14 authority,
15 payer: authority,
16 tokenOwner: authority.address,
17 tokenStandard: TokenStandard.NonFungible,
18});
19
20await sendAndConfirm({
21 instructions: [burnIx],
22 payer: authority,
23});
24
25console.log('NFT burned:', mintAddress);
1use mpl_token_metadata::instructions::BurnNftCpiBuilder;
2
3BurnNftCpiBuilder::new(&metadata_program_id)
4 .metadata(&metadata)
5 // if your NFT is part of a collection you will need to pass in the collection metadata address.
6 .collection_metadata(collection_metadata.as_ref())
7 .owner(&owner)
8 .mint(&mint)
9 .token_account(&token)
10 .master_edition_account(&edition)
11 .spl_token_program(&spl_token)
12 .invoke()?;
1use anchor_lang::prelude::*;
2use anchor_spl::token::Mint;
3use mpl_token_metadata::instructions::BurnNftCpiBuilder;
4
5#[derive(Accounts)]
6pub struct NftBurnMpl<'info> {
7 #[account(mut)]
8 owner: Signer<'info>,
9 #[account(mut)]
10 mint: Account<'info, Mint>,
11 #[account(mut)]
12 metadata: AccountInfo<'info>,
13 #[account(mut)]
14 token: AccountInfo<'info>,
15 #[account(mut)]
16 edition: AccountInfo<'info>,
17 collection_metadata: Option<AccountInfo<'info>>,
18 spl_token: AccountInfo<'info>,
19 metadata_program_id: AccountInfo<'info>,
20}
21
22pub fn burn_nft_mpl_instruction<'info>(
23 ctx: Context<'_, '_, '_, 'info, NftBurnMpl<'info>>,
24) -> Result<()> {
25 let owner = ctx.accounts.owner.to_account_info();
26 let metadata = ctx.accounts.metadata.to_account_info();
27 let collection_metadata = ctx.accounts.collection_metadata.as_ref().map(|a| a.to_account_info());
28 let mint = ctx.accounts.mint.to_account_info();
29 let token = ctx.accounts.token.to_account_info();
30 let edition = ctx.accounts.edition.to_account_info();
31 let spl_token = ctx.accounts.spl_token.to_account_info();
32 let metadata_program_id = ctx.accounts.metadata_program_id.to_account_info();
33
34 BurnNftCpiBuilder::new(&metadata_program_id)
35 .metadata(&metadata)
36 // if your NFT is part of a collection you will also need to pass in the collection metadata address.
37 .collection_metadata(collection_metadata.as_ref())
38 .owner(&owner)
39 .mint(&mint)
40 .token_account(&token)
41 .master_edition_account(&edition)
42 .spl_token_program(&spl_token)
43 .invoke()?;
44
45 Ok(())
46}
pNFT 소각
pNFT는 명령어가 작동하기 위해 추가 계정들이 전달되어야 할 수 있습니다. 여기에는 다음이 포함될 수 있습니다:
- tokenAccount
- tokenRecord
- authorizationRules
- authorizationRulesProgram
1import { publicKey } from '@metaplex-foundation/umi';
2import { burnV1, TokenStandard } from '@metaplex-foundation/mpl-token-metadata';
3
4// Assuming umi is set up with mplTokenMetadata plugin
5
6const mintAddress = publicKey('mintAddress...');
7
8// Burn the Programmable NFT
9// Note: pNFTs have Token Record accounts that are also cleaned up
10await burnV1(umi, {
11 mint: mintAddress,
12 authority: umi.identity,
13 tokenOwner: umi.identity.publicKey,
14 tokenStandard: TokenStandard.ProgrammableNonFungible,
15}).sendAndConfirm(umi);
16
17console.log('pNFT burned:', mintAddress);
1import {
2 getBurnV1InstructionAsync,
3 TokenStandard,
4} from '@metaplex-foundation/mpl-token-metadata-kit';
5
6// Assuming rpc, rpcSubscriptions, sendAndConfirm, and authority are set up
7
8const mintAddress = 'mintAddress...'; // The pNFT mint address
9
10// Burn the Programmable NFT
11// Note: pNFTs have Token Record accounts that are also cleaned up
12const burnIx = await getBurnV1InstructionAsync({
13 mint: mintAddress,
14 authority,
15 payer: authority,
16 tokenOwner: authority.address,
17 tokenStandard: TokenStandard.ProgrammableNonFungible,
18});
19
20await sendAndConfirm({
21 instructions: [burnIx],
22 payer: authority,
23});
24
25console.log('pNFT burned:', mintAddress);
1use mpl_token_metadata::instructions::BurnNftCpiBuilder;
2
3BurnNftCpiBuilder::new(metadata_program_id.account_info())
4 .metadata(metadata.account_info())
5 .collection_metadata(Some(collection_metadata.account_info()))
6 .owner(owner.account_info())
7 .mint(mint.account_info())
8 .token_account(token.account_info())
9 .master_edition_account(edition.account_info())
10 .spl_token_program(spl_token.account_info())
11 .invoke()?;
1use anchor_lang::prelude::*;
2use anchor_spl::token::Mint;
3use mpl_token_metadata::instructions::BurnV1CpiBuilder;
4
5#[derive(Accounts)]
6pub struct PnftBurnMpl<'info> {
7 #[account(mut)]
8 owner: Signer<'info>,
9 #[account(mut)]
10 mint: Account<'info, Mint>,
11 #[account(mut)]
12 metadata: AccountInfo<'info>,
13 #[account(mut)]
14 token: AccountInfo<'info>,
15 #[account(mut)]
16 master_edition: AccountInfo<'info>,
17 #[account(mut)]
18 token_record: AccountInfo<'info>,
19 collection_metadata: Option<AccountInfo<'info>>,
20 spl_token: AccountInfo<'info>,
21 metadata_program_id: AccountInfo<'info>,
22}
23
24pub fn burn_pnft_mpl_instruction<'info>(
25 ctx: Context<'_, '_, '_, 'info, PnftBurnMpl<'info>>,
26) -> Result<()> {
27let owner = ctx.accounts.owner.to_account_info();
28let metadata = ctx.accounts.metadata.to_account_info();
29let mint = ctx.accounts.mint.to_account_info();
30let token = ctx.accounts.token.to_account_info();
31let master_edition = ctx.accounts.master_edition.to_account_info();
32let collection_metadata = ctx
33 .accounts
34 .collection_metadata
35 .as_ref()
36 .map(|a| a.to_account_info());
37let spl_token = ctx.accounts.spl_token.to_account_info();
38let token_record = ctx.accounts.token_record.to_account_info();
39let metadata_program_id = ctx.accounts.metadata_program_id.to_account_info();
40
41BurnV1CpiBuilder::new(&metadata_program_id)
42 .metadata(&metadata)
43 .collection_metadata(collection_metadata.as_ref())
44 .authority(&owner)
45 .mint(&mint)
46 .token(&token)
47 .spl_token_program(&spl_token)
48 .token_record(Some(&token_record))
49 .master_edition(Some(&master_edition))
50 .invoke()?;
51
52Ok(())
53}
