Як створити карбувальник із Confidential Balances
Confidential Balances забезпечує приватні перекази токенів, додаючи додатковий стан до mint account. У цьому розділі пояснюється, як створити карбувальник токенів із увімкненим необхідним розширенням.
Наступна діаграма показує кроки, пов'язані зі створенням карбувальника з розширенням Confidential Balances:
Стан карбувальника Confidential Balances
Розширення додає стан ConfidentialTransferMint до mint account:
#[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,}
ConfidentialTransferMint містить три поля конфігурації:
-
authority: Обліковий запис, який має дозвіл на зміну налаштувань Confidential Balances для карбувальника та затвердження нових конфіденційних облікових записів, якщо автоматичне затвердження вимкнено.
-
auto_approve_new_accounts: Якщо встановлено значення true, користувачі можуть створювати token accounts із увімкненими Confidential Balances за замовчуванням. Якщо false, authority повинен затвердити кожен новий token account, перш ніж його можна буде використовувати для конфіденційних переказів.
-
auditor_elgamal_pubkey: Необов'язковий аудитор, який може розшифровувати суми переказів у конфіденційних транзакціях, забезпечуючи механізм відповідності вимогам при збереженні конфіденційності від широкої громадськості.
Необхідні інструкції
Для створення карбувальника з увімкненими Confidential Balances потрібні три інструкції в одній транзакції:
-
Створення Mint Account: Викличте інструкцію
CreateAccountSystem Program для створення mint account. -
Ініціалізація Confidential Balances: Викличте інструкцію Token Extensions Program ConfidentialTransferInstruction::InitializeMint для налаштування стану
ConfidentialTransferMintдля карбувальника. -
Ініціалізація Mint: Викличте інструкцію
Instruction::InitializeMintToken Extensions Program для ініціалізації стандартного стану mint.
Хоча ці інструкції можна написати вручну, крейт spl_token_client надає метод
create_mint, який будує та надсилає транзакцію з усіма трьома інструкціями в
одному виклику функції, як показано в прикладі нижче.
Приклад коду
Наступний код демонструє, як створити карбувальник із увімкненими Confidential Balances.
Confidential Balances залежить від програми ZK ElGamal Proof, яка увімкнена
на mainnet і devnet. Стандартний solana-test-validator не вмикає її, але
локальний validator із форком mainnet, наприклад Surfpool, підтримує це.
Запустіть приклад проти одного з них (у коді використовується devnet) із фінансованим платником
та замініть адреси-заповнювачі карбувальника й облікового запису на власні.
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 settingstrue, // auto-approve new accountsSome(auditor_pubkey),)?;let init_mint_ix = initialize_mint_base(&spl_token_2022::id(),&mint.pubkey(),&payer.pubkey(), // mint authorityNone, // freeze authoritydecimals,)?;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?