销毁的作用是什么?
销毁代币会永久减少代币账户余额,并将铸币的总供应量减少相同数量。
如何销毁代币
销毁代币使用 Token Program 的 Burn 或 BurnChecked 指令。
以下示例使用
BurnChecked,该指令要求调用者提供铸币的小数位数,以便指令在销毁前验证预期的代币精度。
原生铸币 不支持销毁。请改用
CloseAccount。
代币账户所有者或经批准的委托人对交易进行签名。在 Token Extensions Program 中,如果铸币启用了永久委托扩展,铸币永久委托人也可以授权销毁操作。
源代码参考
| 项目 | 描述 | Token Program | Token Extensions Program |
|---|---|---|---|
Mint | 铸币状态存储代币总供应量。 | 源代码 | 源代码 |
Account | 代币账户状态存储因销毁而减少的代币余额。 | 源代码 | 源代码 |
Burn | 一个销毁指令,减少代币账户余额和铸币供应量,无需调用者提供铸币的小数位数。 | 源代码 | 源代码 |
BurnChecked | 一个销毁指令,要求调用者提供铸币的小数位数,并在减少代币账户余额和铸币供应量之前检查该值。 | 源代码 | 源代码 |
process_burn | 代币销毁的共享处理器逻辑。 | 源代码 | 源代码 |
Typescript
下面的 Kit 示例展示了使用 @solana/kit 的推荐方法。为了方便参考,还包含了使用
@solana/web3.js 的旧版示例。
Kit
import { generateKeyPairSigner } from "@solana/kit";import { createLocalClient } from "@solana/kit-client-rpc";import {findAssociatedTokenPda,tokenProgram,TOKEN_PROGRAM_ADDRESS} from "@solana-program/token";const client = await createLocalClient().use(tokenProgram());const mint = await generateKeyPairSigner();const [tokenAccount] = await findAssociatedTokenPda({mint: mint.address,owner: client.payer.address,tokenProgram: TOKEN_PROGRAM_ADDRESS});const result = await client.token.instructions.burnChecked({account: tokenAccount, // Token account holding the tokens to burn.mint: mint.address, // Mint for the token being burned.authority: client.payer, // Owner or delegate approving the burn.amount: 25n, // Token amount in base units.decimals: 2 // Decimals defined on the mint account.}).sendTransaction();const mintAccount = await client.token.accounts.mint.fetch(mint.address);const tokenAccountData = await client.token.accounts.token.fetch(tokenAccount);console.log("Mint Address:", mint.address);console.log("Mint Account:", mintAccount.data);console.log("\nToken Account Address:", tokenAccount);console.log("Token Account:", tokenAccountData.data);console.log("\nTransaction Signature:", result.context.signature);
Console
Click to execute the code.
Web3.js
import { Connection, Keypair, LAMPORTS_PER_SOL } from "@solana/web3.js";import {createAssociatedTokenAccount,burnChecked,createMint,getAccount,getMint,mintToChecked,TOKEN_PROGRAM_ID} from "@solana/spl-token";const result = await burnChecked(connection, // Connection to the local validator.feePayer, // Account paying transaction fees.associatedTokenAccount, // Token account holding the tokens to burn.mintPubkey, // Mint for the token being burned.feePayer, // Owner or delegate approving the burn.25, // Token amount in base units.2, // Decimals defined on the mint account.[], // Additional multisig signers.{commitment: "confirmed" // Confirmation options for the transaction.},TOKEN_PROGRAM_ID // Token program to invoke.);const mintAccount = await getMint(connection,mintPubkey,"confirmed",TOKEN_PROGRAM_ID);const tokenAccountData = await getAccount(connection,associatedTokenAccount,"confirmed",TOKEN_PROGRAM_ID);console.log("Mint Address:", mintPubkey.toBase58());console.log("Mint Account:", mintAccount);console.log("\nAssociated Token Account Address:",associatedTokenAccount.toBase58());console.log("Associated Token Account:", tokenAccountData);console.log("\nTransaction Signature:", result);
Console
Click to execute the code.
Rust
Rust
use anyhow::Result;use solana_client::nonblocking::rpc_client::RpcClient;use solana_commitment_config::CommitmentConfig;use solana_sdk::{program_pack::Pack,signature::{Keypair, Signer},transaction::Transaction,};use solana_system_interface::instruction::create_account;use spl_associated_token_account_interface::{address::get_associated_token_address, instruction::create_associated_token_account,};use spl_token_interface::{id as token_program_id,instruction::{burn_checked, initialize_mint, mint_to_checked},state::{Account, Mint},};#[tokio::main]async fn main() -> Result<()> {let client = RpcClient::new_with_commitment(String::from("http://localhost:8899"),CommitmentConfig::confirmed(),);let burn_amount = 25;let transaction = Transaction::new_signed_with_payer(&[burn_checked(&token_program_id(), // Token program to invoke.&associated_token_address, // Token account holding the tokens to burn.&mint.pubkey(), // Mint for the token being burned.&fee_payer.pubkey(), // Owner or delegate approving the burn.&[], // Additional multisig signers.burn_amount, // Token amount in base units.decimals, // Decimals defined on the mint account.)?,],Some(&fee_payer.pubkey()),&[&fee_payer],latest_blockhash,);let transaction_signature = client.send_and_confirm_transaction(&transaction).await?;let mint_account = client.get_account(&mint.pubkey()).await?;let mint_data = Mint::unpack(&mint_account.data)?;let token_account = client.get_account(&associated_token_address).await?;let token_data = Account::unpack(&token_account.data)?;println!("Mint Address: {}", mint.pubkey());println!("Mint Account: {:#?}", mint_data);println!("\nAssociated Token Account Address: {}",associated_token_address);println!("Associated Token Account: {:#?}", token_data);println!("\nTransaction Signature: {}", transaction_signature);Ok(())}
Console
Click to execute the code.
Python
Python
#!/usr/bin/env python3import asyncioimport jsonfrom solana.rpc.async_api import AsyncClientfrom solders.keypair import Keypairfrom solders.message import Messagefrom solders.pubkey import Pubkeyfrom solders.system_program import create_account, CreateAccountParamsfrom solders.transaction import Transactionfrom spl.token.async_client import AsyncTokenfrom spl.token.instructions import (burn_checked,BurnCheckedParams,create_associated_token_account,get_associated_token_address,initialize_mint,InitializeMintParams,mint_to_checked,MintToCheckedParams,)from spl.token.constants import MINT_LEN, TOKEN_PROGRAM_IDDECIMALS = 2AMOUNT_TO_MINT = 100AMOUNT_TO_BURN = 25async def main():rpc = AsyncClient("http://localhost:8899")async with rpc:burn_tokens_instruction = burn_checked(BurnCheckedParams(program_id=TOKEN_PROGRAM_ID, # Token program to invoke.mint=mint.pubkey(), # Mint for the token being burned.account=token_account_address, # Token account whose balance decreases.owner=fee_payer.pubkey(), # Account that owns the token account and signs the transaction.amount=AMOUNT_TO_BURN, # Token amount in base units.decimals=DECIMALS, # Decimals defined on the mint account.))latest_blockhash = await rpc.get_latest_blockhash()transaction = Transaction([fee_payer],Message([burn_tokens_instruction], fee_payer.pubkey()),latest_blockhash.value.blockhash,)result = await rpc.send_transaction(transaction)mint_info = await token.get_mint_info()token_account_info = await token.get_account_info(token_account_address)mint_account = {key: str(value) if isinstance(value, Pubkey) else valuefor key, value in mint_info._asdict().items()}token_account = {key: str(value) if isinstance(value, Pubkey) else valuefor key, value in token_account_info._asdict().items()}print("Mint Address:", mint.pubkey())print("Mint Account:")print(json.dumps(mint_account, indent=2))print("\nToken Account Address:", token_account_address)print("Token Account:")print(json.dumps(token_account, indent=2))print("\nTransaction Signature:", result.value)if __name__ == "__main__":asyncio.run(main())
Console
Click to execute the code.
Is this page helpful?