Creare un token mint

Come creare un mint con i Saldi Riservati

I Saldi Riservati consentono trasferimenti di token privati aggiungendo uno stato extra al mint account. Questa sezione spiega come creare un token mint con l'estensione richiesta abilitata.

Il seguente diagramma illustra i passaggi necessari per creare un mint con l'estensione Saldi Riservati:

Create Mint with Confidential Balances

Stato del Mint con Saldi Riservati

L'estensione aggiunge lo stato ConfidentialTransferMint al mint account:

Confidential Mint State
#[repr(C)]
#[derive(Clone, Copy, Debug, Default, PartialEq, Pod, Zeroable)]
pub struct ConfidentialTransferMint {
/// Authority to modify the `ConfidentialTransferMint` configuration and to
/// approve new accounts (if `auto_approve_new_accounts` is true)
///
/// The legacy Token Multisig account is not supported as the authority
pub authority: OptionalNonZeroPubkey,
/// Indicate if newly configured accounts must be approved by the
/// `authority` before they may be used by the user.
///
/// * If `true`, no approval is required and new accounts may be used
/// immediately
/// * If `false`, the authority must approve newly configured accounts (see
/// `ConfidentialTransferInstruction::ConfigureAccount`)
pub auto_approve_new_accounts: PodBool,
/// Authority to decode any transfer amount in a confidential transfer.
pub auditor_elgamal_pubkey: OptionalNonZeroElGamalPubkey,
}

Il ConfidentialTransferMint contiene tre campi di configurazione:

  • authority: L'account che ha il permesso di modificare le impostazioni dei Saldi Riservati per il mint e di approvare nuovi account riservati se l'approvazione automatica è disabilitata.

  • auto_approve_new_accounts: Se impostato su true, gli utenti possono creare token account con i Saldi Riservati abilitati per impostazione predefinita. Se impostato su false, l'authority deve approvare ogni nuovo token account prima che possa essere utilizzato per i trasferimenti riservati.

  • auditor_elgamal_pubkey: Un revisore opzionale che può decifrare gli importi dei trasferimenti nelle transazioni riservate, fornendo un meccanismo di conformità pur mantenendo la privacy rispetto al pubblico generale.

Istruzioni Necessarie

La creazione di un mint con i Saldi Riservati abilitati richiede tre istruzioni in un'unica transazione:

  1. Creare il Mint Account: Richiamare l'istruzione CreateAccount del System Program per creare il mint account.

  2. Inizializzazione dei Saldi Riservati: Invocare l'istruzione ConfidentialTransferInstruction::InitializeMint del Token Extension Program per configurare lo stato ConfidentialTransferMint per il mint.

  3. Inizializzare il Mint: Richiamare l'istruzione Instruction::InitializeMint del Token Extensions Program per inizializzare lo stato standard del mint.

Sebbene sia possibile scrivere queste istruzioni manualmente, il crate spl_token_client fornisce un metodo create_mint che costruisce e invia una transazione con tutte e tre le istruzioni in un'unica chiamata di funzione, come mostrato nell'esempio seguente.

Codice di Esempio

Il codice seguente dimostra come creare un mint con i Saldi Riservati abilitati.

I Saldi Riservati dipendono dal programma ZK ElGamal Proof, abilitato su mainnet e devnet. Un solana-test-validator standard non lo abilita, ma un validator locale con fork da mainnet come Surfpool sì. Esegui l'esempio su uno di questi (il codice utilizza devnet) con un payer finanziato, e sostituisci il mint e gli indirizzi account segnaposto con i tuoi.

Rust

fn main() -> Result<()> {
let rpc_client = RpcClient::new_with_commitment(
String::from("https://api.devnet.solana.com"),
CommitmentConfig::confirmed(),
);
let payer = load_keypair()?;
let mint = Keypair::new();
let decimals: u8 = 2;
// Allocate space for a mint that carries the ConfidentialTransferMint
// extension, then fund it for rent exemption.
let space =
ExtensionType::try_calculate_account_len::<Mint>(&[ExtensionType::ConfidentialTransferMint])?;
let rent = rpc_client.get_minimum_balance_for_rent_exemption(space)?;
// The auditor ElGamal key lets the issuer decrypt transfer amounts for
// compliance. Persist this key. Pass `None` to create a mint with no auditor.
let auditor = ElGamalKeypair::new_rand();
let auditor_pubkey: PodElGamalPubkey = (*auditor.pubkey()).into();
let create_account_ix = system_instruction::create_account(
&payer.pubkey(),
&mint.pubkey(),
rent,
space as u64,
&spl_token_2022::id(),
);
// The confidential-transfer extension must be initialized before the base
// mint and cannot be added later.
let init_confidential_ix = initialize_confidential_transfer_mint(
&spl_token_2022::id(),
&mint.pubkey(),
Some(payer.pubkey()), // authority that can update confidential settings
true, // auto-approve new accounts
Some(auditor_pubkey),
)?;
let init_mint_ix = initialize_mint_base(
&spl_token_2022::id(),
&mint.pubkey(),
&payer.pubkey(), // mint authority
None, // freeze authority
decimals,
)?;
let blockhash = rpc_client.get_latest_blockhash()?;
let transaction = Transaction::new_signed_with_payer(
&[create_account_ix, init_confidential_ix, init_mint_ix],
Some(&payer.pubkey()),
&[&payer, &mint],
blockhash,
);
let signature = rpc_client.send_and_confirm_transaction(&transaction)?;
println!("Created confidential mint {}: {signature}", mint.pubkey());
Ok(())
}
fn load_keypair() -> Result<Keypair> {
let keypair_path = dirs::home_dir()
.context("could not find home directory")?
.join(".config/solana/id.json");
let bytes: Vec<u8> = serde_json::from_reader(std::fs::File::open(keypair_path)?)?;
let mut secret = [0u8; 32];
secret.copy_from_slice(&bytes[0..32]);
Ok(Keypair::new_from_array(secret))
}

Typescript

const client = await createClient()
.use(signerFromFile(join(homedir(), ".config/solana/id.json")))
.use(
solanaRpc({
rpcUrl: "https://api.devnet.solana.com"
})
);
const payer = client.payer;
const mint = await generateKeyPairSigner();
// The auditor ElGamal key lets the issuer decrypt transfer amounts for
// compliance. Persist it; omit `auditorElgamalPubkey` to create a mint with no
// auditor.
const auditor = await deriveElGamalKeypairForOwnerMint({
signer: payer,
owner: payer.address,
mint: mint.address
});
const plan = getCreateMintInstructionPlan({
payer,
newMint: mint,
decimals: 2,
mintAuthority: payer,
extensions: [
{
__kind: "ConfidentialTransferMint",
authority: some(payer.address),
autoApproveNewAccounts: true,
auditorElgamalPubkey: some(auditor.elgamalPubkey)
}
]
});
const result = await client.sendTransaction(plan);
console.log(
`Created confidential mint ${mint.address}: ${result.context.signature}`
);

Is this page helpful?

Indice dei contenuti

Modifica pagina
© 2026 Solana Foundation. Tutti i diritti riservati.