Crear un token mint

Cómo crear un mint con la extensión Confidential Transfer

La extensión Confidential Transfer permite transferencias privadas de tokens añadiendo estado adicional al mint account. Esta sección explica cómo crear un token mint con esta extensión habilitada.

El siguiente diagrama muestra los pasos necesarios para crear un mint con la extensión Confidential Transfer:

Create Mint with Confidential Transfer Extension

Estado del Mint con Confidential Transfer

La extensión añade el estado 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,
}

El ConfidentialTransferMint contiene tres campos de configuración:

  • authority: La cuenta que tiene permiso para cambiar la configuración de transferencias confidenciales del mint y aprobar nuevas cuentas confidenciales si la aprobación automática está deshabilitada.

  • auto_approve_new_accounts: Cuando se establece en true, los usuarios pueden crear token accounts con transferencias confidenciales habilitadas de forma predeterminada. Cuando es false, la authority debe aprobar cada nuevo token account antes de que pueda utilizarse para transferencias confidenciales.

  • auditor_elgamal_pubkey: Un auditor opcional que puede descifrar los montos de transferencia en transacciones confidenciales, proporcionando un mecanismo de cumplimiento normativo mientras se mantiene la privacidad frente al público en general.

Instrucciones Requeridas

Crear un mint con Confidential Transfer habilitado requiere tres instrucciones en una única transacción:

  1. Crear el Mint Account: Invocar la instrucción CreateAccount del System Program para crear el mint account.

  2. Inicializar la Extensión Confidential Transfer: Invocar la instrucción ConfidentialTransferInstruction::InitializeMint del Token Extensions Program para configurar el estado ConfidentialTransferMint del mint.

  3. Inicializar el Mint: Invocar la instrucción Instruction::InitializeMint del Token Extensions Program para inicializar el estado estándar del mint.

Si bien es posible escribir estas instrucciones manualmente, el crate spl_token_client proporciona un método create_mint que construye y envía una transacción con las tres instrucciones en una única llamada a función, como se muestra en el ejemplo a continuación.

Código de ejemplo

El siguiente código demuestra cómo crear un mint con la extensión Confidential Transfer.

Las transferencias confidenciales dependen del programa ZK ElGamal Proof, que está habilitado en mainnet y devnet. Un solana-test-validator estándar no lo habilita, pero un validator local con bifurcación de mainnet como Surfpool sí lo hace. Ejecuta el ejemplo en uno de ellos (el código usa devnet) con un pagador con fondos, y reemplaza las direcciones de mint y cuenta de marcador de posición con las tuyas propias.

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?

Tabla de Contenidos

Editar Página