Was ist Mint Close Authority?
Die MintCloseAuthority-Mint-Erweiterung des Token Extensions Program
ermöglicht es einer bezeichneten Autorität, ein mint account zu schließen und
dessen rent zurückzufordern, sobald der Gesamtvorrat des Mints Null erreicht.
Ohne diese Erweiterung kann ein mint account nicht geschlossen werden.
- Der Gesamtvorrat muss Null sein, daher müssen alle Token in allen token account verbrannt werden, bevor ein Mint geschlossen werden kann
- Nur die konfigurierte Close Authority kann das Mint schließen
So erstellen und schließen Sie ein Mint
Um ein Mint zu erstellen und zu schließen:
- Berechnen Sie die mint account-Größe und die benötigte rent für das Mint und
die
MintCloseAuthority-Erweiterung. - Erstellen Sie das mint account mit
CreateAccount, initialisieren SieMintCloseAuthorityund initialisieren Sie das Mint mitInitializeMint. - Wenn der Gesamtvorrat Null ist, kann das mint account mit
CloseAccountgeschlossen werden, signiert von der Close Authority.
Kontengröße berechnen
Berechnen Sie die mint account-Größe für das Basis-Mint plus die
MintCloseAuthority-Erweiterung. Dies ist die Größe, die in
CreateAccount verwendet wird.
Rent berechnen
Berechnen Sie die rent unter Verwendung der für das Mint benötigten Größe plus
die MintCloseAuthority-Erweiterung.
Mint account erstellen
Erstellen Sie das mint account mit dem berechneten Speicherplatz und lamport.
MintCloseAuthority initialisieren
Initialisieren Sie die MintCloseAuthority-Erweiterung für das Mint.
Mint initialisieren
Initialisieren Sie das Mint mit InitializeMint in derselben Transaktion.
Reihenfolge der Anweisungen
InitializeMintCloseAuthority muss vor InitializeMint kommen.
CreateAccount, InitializeMintCloseAuthority und
InitializeMint müssen in derselben Transaktion enthalten sein.
Quellreferenz
| Element | Beschreibung | Quelle |
|---|---|---|
MintCloseAuthority | Mint-Erweiterung, die die Berechtigung speichert, ein Mint zu schließen, sobald dessen Versorgung null erreicht. | Quelle |
InitializeMintCloseAuthority | Anweisungen, die die Mint-Close-Authority vor InitializeMint initialisiert. | Quelle |
CloseAccount | Basis-Token- Anweisungen, die das Mint- Konten schließt, nachdem die Gesamtversorgung null erreicht hat. | Quelle |
process_initialize_mint_close_authority | Prozessorlogik, die die MintCloseAuthority-Erweiterung auf ein nicht initialisiertes Mint schreibt. | Quelle |
process_close_account | Gemeinsamer Close- Konten-Handler, der die Null-Versorgungsregel für Mints mit Close-Authority durchsetzt. | Quelle |
Typescript
Das folgende Kit-Beispiel verwendet die generierten Anweisungen direkt.
Legacy-Beispiele mit @solana/web3.js und @solana/spl-token sind als Referenz
enthalten.
Kit
import { lamports, createClient, generateKeyPairSigner } from "@solana/kit";import { solanaRpc, rpcAirdrop } from "@solana/kit-plugin-rpc";import { generatedPayer, airdropPayer } from "@solana/kit-plugin-signer";import { getCreateAccountInstruction } from "@solana-program/system";import {extension,findAssociatedTokenPda,getBurnCheckedInstruction,getCloseAccountInstruction,getCreateAssociatedTokenInstructionAsync,getInitializeMintCloseAuthorityInstruction,getInitializeMintInstruction,getMintSize,getMintToCheckedInstruction,TOKEN_2022_PROGRAM_ADDRESS} from "@solana-program/token-2022";const client = await createClient().use(generatedPayer()).use(solanaRpc({rpcUrl: "http://localhost:8899",rpcSubscriptionsUrl: "ws://localhost:8900"})).use(rpcAirdrop()).use(airdropPayer(lamports(1_000_000_000n)));const mint = await generateKeyPairSigner();const destination = await generateKeyPairSigner();const mintCloseAuthorityExtension = extension("MintCloseAuthority", {closeAuthority: client.payer.address});const mintSpace = BigInt(getMintSize([mintCloseAuthorityExtension]));const mintRent = await client.rpc.getMinimumBalanceForRentExemption(mintSpace).send();await client.sendTransaction([getCreateAccountInstruction({payer: client.payer,newAccount: mint,lamports: mintRent,space: mintSpace,programAddress: TOKEN_2022_PROGRAM_ADDRESS}),getInitializeMintCloseAuthorityInstruction({mint: mint.address, // Mint account that stores the MintCloseAuthority extension.closeAuthority: client.payer.address // Authority allowed to close the mint.}),getInitializeMintInstruction({mint: mint.address,decimals: 0,mintAuthority: client.payer.address,freezeAuthority: client.payer.address})]);const [token] = await findAssociatedTokenPda({mint: mint.address,owner: client.payer.address,tokenProgram: TOKEN_2022_PROGRAM_ADDRESS});await client.sendTransaction([await getCreateAssociatedTokenInstructionAsync({payer: client.payer,mint: mint.address,owner: client.payer.address}),getMintToCheckedInstruction({mint: mint.address,token,mintAuthority: client.payer,amount: 1n,decimals: 0})]);await client.sendTransaction([getBurnCheckedInstruction({mint: mint.address,account: token,authority: client.payer,amount: 1n,decimals: 0}),getCloseAccountInstruction({account: mint.address, // Mint account to close.destination: destination.address, // Account receiving the reclaimed lamports.owner: client.payer // Close authority signing the instruction.})]);const mintInfo = await client.rpc.getAccountInfo(mint.address).send();console.log("Mint Address:", mint.address);console.log("Destination Address:", destination.address);console.log("Mint Closed:", mintInfo.value === null);
Web3.js
import {Connection,Keypair,sendAndConfirmTransaction,SystemProgram,Transaction,LAMPORTS_PER_SOL} from "@solana/web3.js";import {createInitializeMintInstruction,ExtensionType,getMintLen,createInitializeMintCloseAuthorityInstruction,TOKEN_2022_PROGRAM_ID,createCloseAccountInstruction} from "@solana/spl-token";const connection = new Connection("http://localhost:8899", "confirmed");const latestBlockhash = await connection.getLatestBlockhash();const feePayer = Keypair.generate();const destination = Keypair.generate();const airdropSignature = await connection.requestAirdrop(feePayer.publicKey,5 * LAMPORTS_PER_SOL);await connection.confirmTransaction({blockhash: latestBlockhash.blockhash,lastValidBlockHeight: latestBlockhash.lastValidBlockHeight,signature: airdropSignature});const mint = Keypair.generate();const extensions = [ExtensionType.MintCloseAuthority];const mintLength = getMintLen(extensions);const mintRent = await connection.getMinimumBalanceForRentExemption(mintLength);const createAccountInstruction = SystemProgram.createAccount({fromPubkey: feePayer.publicKey,newAccountPubkey: mint.publicKey,space: mintLength,lamports: mintRent,programId: TOKEN_2022_PROGRAM_ID});const initializeMintCloseAuthorityInstruction =createInitializeMintCloseAuthorityInstruction(mint.publicKey, // Mint account that stores the MintCloseAuthority extension.feePayer.publicKey, // Authority allowed to close the mint.TOKEN_2022_PROGRAM_ID // Token program that owns the mint.);const initializeMintInstruction = createInitializeMintInstruction(mint.publicKey, // mint pubkey9, // decimalsfeePayer.publicKey, // mint authorityfeePayer.publicKey, // freeze authorityTOKEN_2022_PROGRAM_ID);const transaction = new Transaction({feePayer: feePayer.publicKey,blockhash: latestBlockhash.blockhash,lastValidBlockHeight: latestBlockhash.lastValidBlockHeight}).add(createAccountInstruction,initializeMintCloseAuthorityInstruction,initializeMintInstruction);const transactionSignature = await sendAndConfirmTransaction(connection,transaction,[feePayer, mint]);console.log("Mint Address:", mint.publicKey.toBase58());console.log("Transaction Signature:", transactionSignature);const latestBlockhash2 = await connection.getLatestBlockhash();const closeMintInstruction = createCloseAccountInstruction(mint.publicKey, // Mint account to close.destination.publicKey, // Account receiving the reclaimed lamports.feePayer.publicKey, // Close authority signing the instruction.[], // Additional multisig signers.TOKEN_2022_PROGRAM_ID // Token program that owns the mint.);const closeMintTransaction = new Transaction({feePayer: feePayer.publicKey,blockhash: latestBlockhash2.blockhash,lastValidBlockHeight: latestBlockhash2.lastValidBlockHeight}).add(closeMintInstruction);const transactionSignature3 = await sendAndConfirmTransaction(connection,closeMintTransaction,[feePayer]);console.log("\nDestination Address:", destination.publicKey.toBase58());console.log("Transaction Signature:", transactionSignature3);
Rust
use anyhow::Result;use solana_client::nonblocking::rpc_client::RpcClient;use solana_commitment_config::CommitmentConfig;use solana_sdk::{signature::{Keypair, Signer},transaction::Transaction,};use solana_system_interface::instruction::create_account;use spl_token_2022_interface::{extension::{mint_close_authority::MintCloseAuthority, BaseStateWithExtensions, ExtensionType,StateWithExtensions,},instruction::{close_account, initialize_mint, initialize_mint_close_authority},state::Mint,ID as TOKEN_2022_PROGRAM_ID,};#[tokio::main]async fn main() -> Result<()> {let client = RpcClient::new_with_commitment(String::from("http://localhost:8899"),CommitmentConfig::confirmed(),);let fee_payer = Keypair::new();let destination = Keypair::new();let airdrop_signature = client.request_airdrop(&fee_payer.pubkey(), 5_000_000_000).await?;loop {let confirmed = client.confirm_transaction(&airdrop_signature).await?;if confirmed {break;}}let mint = Keypair::new();let mint_space =ExtensionType::try_calculate_account_len::<Mint>(&[ExtensionType::MintCloseAuthority])?;let mint_rent = client.get_minimum_balance_for_rent_exemption(mint_space).await?;let create_account_instruction = create_account(&fee_payer.pubkey(), // payer&mint.pubkey(), // new account (mint)mint_rent, // lamportsmint_space as u64, // space&TOKEN_2022_PROGRAM_ID, // program id);let initialize_close_mint_instruction = initialize_mint_close_authority(&TOKEN_2022_PROGRAM_ID, // token program&mint.pubkey(), // mintSome(&fee_payer.pubkey()), // close authority)?;let initialize_mint_instruction = initialize_mint(&TOKEN_2022_PROGRAM_ID, // token program&mint.pubkey(), // mint&fee_payer.pubkey(), // mint authoritySome(&fee_payer.pubkey()), // freeze authority9, // decimals)?;let transaction = Transaction::new_signed_with_payer(&[create_account_instruction,initialize_close_mint_instruction,initialize_mint_instruction,],Some(&fee_payer.pubkey()),&[&fee_payer, &mint],client.get_latest_blockhash().await?,);client.send_and_confirm_transaction(&transaction).await?;println!("Mint Address: {}", mint.pubkey());let mint_account = client.get_account(&mint.pubkey()).await?;let mint_state = StateWithExtensions::<Mint>::unpack(&mint_account.data)?;let mint_extension_types = mint_state.get_extension_types()?;println!("\nMint extensions enabled: {:?}", mint_extension_types);let mint_close_authority = mint_state.get_extension::<MintCloseAuthority>()?;println!("\n{:#?}", mint_close_authority);let close_mint_instruction = close_account(&TOKEN_2022_PROGRAM_ID, // Token program that owns the mint.&mint.pubkey(), // Mint account to close.&destination.pubkey(), // Account receiving the reclaimed lamports.&fee_payer.pubkey(), // Close authority signing the instruction.&[&fee_payer.pubkey()], // Additional multisig signers.)?;let transaction = Transaction::new_signed_with_payer(&[close_mint_instruction],Some(&fee_payer.pubkey()),&[&fee_payer],client.get_latest_blockhash().await?,);client.send_and_confirm_transaction(&transaction).await?;match client.get_account(&mint.pubkey()).await {Ok(_) => println!("\nMint account still exists (unexpected)"),Err(e) => println!("\nMint account successfully closed: {:#?}", e),}Ok(())}
Is this page helpful?