Criar um token mint

Como criar um mint com Saldos Confidenciais

Os Saldos Confidenciais permitem transferências privadas de tokens adicionando estado extra ao mint account. Esta seção explica como criar um token mint com a extensão necessária habilitada.

O diagrama a seguir mostra as etapas envolvidas na criação de um mint com a extensão de Saldos Confidenciais:

Create Mint with Confidential Balances

Estado do Mint de Saldos Confidenciais

A extensão adiciona o estado ConfidentialTransferMint ao 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,
}

O ConfidentialTransferMint contém três campos de configuração:

  • authority: A conta que tem permissão para alterar as configurações de Saldos Confidenciais do mint e aprovar novas contas confidenciais caso a aprovação automática esteja desabilitada.

  • auto_approve_new_accounts: Quando definido como true, os usuários podem criar token accounts com Saldos Confidenciais habilitado por padrão. Quando false, a authority deve aprovar cada novo token account antes que ele possa ser usado para transferências confidenciais.

  • auditor_elgamal_pubkey: Um auditor opcional que pode desencriptar os valores das transferências em transacções confidenciais, fornecendo um mecanismo de conformidade enquanto mantém a privacidade perante o público em geral.

Instruções Necessárias

Criar um mint com Saldos Confidenciais habilitado requer três instruções em uma única transação:

  1. Criar o Mint Account: Invocar a instrução CreateAccount do System Program para criar o mint account.

  2. Inicializar Saldos Confidenciais: Invoque a instrução ConfidentialTransferInstruction::InitializeMint do Token Extension Program para configurar o estado ConfidentialTransferMint do mint.

  3. Inicializar o Mint: Invocar a instrução Instruction::InitializeMint do Token Extensions Program para inicializar o estado padrão do mint.

Embora seja possível escrever estas instruções manualmente, o crate spl_token_client fornece um método create_mint que constrói e envia uma transacção com as três instruções numa única chamada de função, conforme demonstrado no exemplo abaixo.

Exemplo de Código

O código a seguir demonstra como criar um mint com Saldos Confidenciais habilitado.

Os Saldos Confidenciais dependem do programa ZK ElGamal Proof, que está habilitado na mainnet e na devnet. Um solana-test-validator padrão não o habilita, mas um validator local com fork da mainnet, como o Surfpool, o faz. Execute o exemplo em um desses ambientes (o código usa a devnet) com um pagador com saldo suficiente, e substitua os endereços de mint e conta de exemplo pelos seus próprios.

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?

Índice

Editar Página
© 2026 Fundação Solana. Todos os direitos reservados.