Créer un mint de token

Comment créer un mint avec les Soldes Confidentiels

Les Soldes Confidentiels permettent des transferts de tokens privés en ajoutant un état supplémentaire au mint account. Cette section explique comment créer un mint de token avec l'extension requise activée.

Le diagramme suivant illustre les étapes de création d'un mint avec l'extension Soldes Confidentiels :

Create Mint with Confidential Balances

État du Mint avec Soldes Confidentiels

L'extension ajoute l'état ConfidentialTransferMint au 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,
}

Le ConfidentialTransferMint contient trois champs de configuration :

  • authority : Le compte qui dispose de l'autorisation de modifier les paramètres des Soldes Confidentiels pour le mint et d'approuver les nouveaux comptes confidentiels si l'approbation automatique est désactivée.

  • auto_approve_new_accounts : Lorsque défini sur true, les utilisateurs peuvent créer des token accounts avec les Soldes Confidentiels activés par défaut. Lorsque défini sur false, l'authority doit approuver chaque nouveau token account avant qu'il puisse être utilisé pour des transferts confidentiels.

  • auditor_elgamal_pubkey : Un auditeur optionnel pouvant déchiffrer les montants des transferts dans les transactions confidentielles, offrant ainsi un mécanisme de conformité tout en préservant la confidentialité vis-à-vis du grand public.

Instructions requises

La création d'un mint avec les Soldes Confidentiels activés nécessite trois instructions dans une seule transaction :

  1. Créer le Mint Account : Invoquer l'instruction CreateAccount du System Program pour créer le mint account.

  2. Initialiser les Soldes Confidentiels : Invoquez l'instruction ConfidentialTransferInstruction::InitializeMint du Token Extension Program pour configurer l'état ConfidentialTransferMint du mint.

  3. Initialiser le Mint : Invoquer l'instruction Instruction::InitializeMint du Token Extensions Program pour initialiser l'état standard du mint.

Bien que vous puissiez rédiger ces instructions manuellement, le crate spl_token_client fournit une méthode create_mint qui construit et envoie une transaction contenant les trois instructions en un seul appel de fonction, comme illustré dans l'exemple ci-dessous.

Exemple de code

Le code suivant montre comment créer un mint avec les Soldes Confidentiels activés.

Les Soldes Confidentiels dépendent du programme ZK ElGamal Proof, qui est activé sur le mainnet et le devnet. Un solana-test-validator standard ne l'active pas, mais un validator local avec fork du mainnet tel que Surfpool le fait. Exécutez l'exemple sur l'un d'eux (le code utilise le devnet) avec un payer approvisionné, et remplacez les adresses de mint et de compte fictives par les vôtres.

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?

Table des matières

Modifier la page
© 2026 Fondation Solana. Tous droits réservés.