トークンミントの作成
Confidential Transfer拡張機能を持つミントの作成方法
Confidential Transfer拡張機能は、ミントアカウントに追加の状態を加えることで、プライベートなトークン転送を可能にします。このセクションでは、この拡張機能を有効にしたトークンミントの作成方法について説明します。
以下の図は、Confidential Transfer拡張機能を持つミントを作成するための手順を示しています:
Confidential Transferミントの状態
この拡張機能は、ミントアカウントにConfidentialTransferMint状態を追加します:
#[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 authoritypub 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,}
*rsConfidentialTransferMint
*には3つの設定フィールドが含まれています:
-
authority: ミントの機密転送設定を変更する権限を持ち、自動承認が無効になっている場合に新しい機密アカウントを承認するアカウント。
-
auto_approve_new_accounts: trueに設定すると、ユーザーはデフォルトで機密転送が有効なトークンアカウントを作成できます。falseの場合、各新規トークンアカウントが機密転送に使用される前に、authorityによる承認が必要です。
-
auditor_elgamal_pubkey: 機密取引の転送金額を復号化できるオプションの監査者で、一般公開からのプライバシーを維持しながらコンプライアンスメカニズムを提供します。
必要なインストラクション
Confidential Transferを有効にしたミントの作成には、単一のトランザクションで3つのインストラクションが必要です:
-
ミントアカウントの作成: System Programの*rs
CreateAccount
*インストラクションを呼び出してミントアカウントを作成します。 -
Confidential Transfer拡張機能の初期化: Token Extensions ProgramのConfidentialTransferInstruction::InitializeMintインストラクションを呼び出して、ミントの*rs
ConfidentialTransferMint
*状態を設定します。 -
ミントの初期化: Token Extensions Programの*rs
Instruction::InitializeMint
*インストラクションを呼び出して、標準のミント状態を初期化します。
これらのインストラクションを手動で記述することもできますが、spl_token_client
クレートはcreate_mint
メソッドを提供しており、以下の例で示すように、3つのインストラクションをすべて含むトランザクションを1回の関数呼び出しで構築して送信します。
サンプルコード
以下のコードは、Confidential Transfer拡張機能を持つミントを作成する方法を示しています。
このサンプルを実行するには、以下のコマンドを使用してメインネットからクローンしたToken Extension Programを使用してローカルvalidatorを起動してください。ローカルvalidatorを起動するにはSolana CLIがインストールされている必要があります。
$solana-test-validator --clone-upgradeable-program TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb --url https://api.mainnet-beta.solana.com -r
執筆時点では、Confidential Transfersはデフォルトのローカルvalidatorで有効になっていません。サンプルコードを実行するには、メインネットのToken Extension Programをクローンする必要があります。
use anyhow::{Context, Result};use solana_client::nonblocking::rpc_client::RpcClient;use solana_sdk::{commitment_config::CommitmentConfig,signature::{Keypair, Signer},};use spl_token_client::{client::{ProgramRpcClient, ProgramRpcClientSendTransaction},spl_token_2022::id as token_2022_program_id,token::{ExtensionInitializationParams, Token},};use std::sync::Arc;#[tokio::main]async fn main() -> Result<()> {// Create connection to local test validatorlet rpc_client = RpcClient::new_with_commitment(String::from("http://localhost:8899"),CommitmentConfig::confirmed(),);// Load the default Solana CLI keypair to use as the fee payer// This will be the wallet paying for the transaction fees// Use Arc to prevent multiple clones of the keypairlet payer = Arc::new(load_keypair()?);println!("Using payer: {}", payer.pubkey());// Generate a new keypair to use as the address of the token mintlet mint = Keypair::new();println!("Mint keypair generated: {}", mint.pubkey());// Set up program client for Token clientlet program_client =ProgramRpcClient::new(Arc::new(rpc_client), ProgramRpcClientSendTransaction);// Number of decimals for the mintlet decimals = 9;// Create a token client for the Token-2022 program// This provides high-level methods for token operationslet token = Token::new(Arc::new(program_client),&token_2022_program_id(), // Use the Token-2022 program (newer version with extensions)&mint.pubkey(), // Address of the new token mintSome(decimals), // Number of decimal placespayer.clone(), // Fee payer for transactions (cloning Arc, not keypair));// Create extension initialization parameters// The ConfidentialTransferMint extension enables confidential (private) transfers of tokenslet extension_initialization_params =vec![ExtensionInitializationParams::ConfidentialTransferMint {authority: Some(payer.pubkey()), // Authority that can modify confidential transfer settingsauto_approve_new_accounts: true, // Automatically approve new confidential accountsauditor_elgamal_pubkey: None, // Optional auditor ElGamal public key}];// Create and initialize the mint with the ConfidentialTransferMint extension// This sends a transaction to create the new token mintlet transaction_signature = token.create_mint(&payer.pubkey(), // Mint authority - can mint new tokensSome(&payer.pubkey()), // Freeze authority - can freeze token accountsextension_initialization_params, // Add the ConfidentialTransferMint extension&[&mint], // Mint keypair needed as signer).await?;// Print results for user verificationprintln!("Mint Address: {}", mint.pubkey());println!("Transaction Signature: {}", transaction_signature);Ok(())}// Load the keypair from the default Solana CLI keypair path (~/.config/solana/id.json)// This enables using the same wallet as the Solana CLI toolsfn load_keypair() -> Result<Keypair> {// Get the default keypair pathlet keypair_path = dirs::home_dir().context("Could not find home directory")?.join(".config/solana/id.json");// Read the keypair file directly into bytes using serde_json// The keypair file is a JSON array of byteslet file = std::fs::File::open(&keypair_path)?;let keypair_bytes: Vec<u8> = serde_json::from_reader(file)?;// Create keypair from the loaded bytes// This converts the byte array into a keypairlet keypair = Keypair::from_bytes(&keypair_bytes)?;Ok(keypair)}
Is this page helpful?