إنشاء mint للرمز المميز

كيفية إنشاء mint مع امتداد النقل السري

يُتيح امتداد النقل السري إجراء عمليات نقل رمزية خاصة عن طريق إضافة حالة إضافية إلى mint account. يشرح هذا القسم كيفية إنشاء mint رمزي مع تفعيل هذا الامتداد.

يوضح الرسم البياني التالي الخطوات المتبعة في إنشاء mint مع امتداد النقل السري:

Create Mint with Confidential Transfer Extension

حالة Mint للنقل السري

يُضيف الامتداد حالة ConfidentialTransferMint إلى 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,
}

يحتوي ConfidentialTransferMint على ثلاثة حقول تهيئة:

  • authority: الحساب الذي يملك صلاحية تغيير إعدادات النقل السري للـ mint والموافقة على الحسابات السرية الجديدة في حال كانت الموافقة التلقائية معطّلة.

  • auto_approve_new_accounts: عند التعيين على true، يمكن للمستخدمين إنشاء token account مع تفعيل النقل السري بشكل افتراضي. وعند التعيين على false، يجب على الجهة المُخوَّلة الموافقة على كل token account جديد قبل استخدامه للنقل السري.

  • auditor_elgamal_pubkey: مدقق اختياري يمكنه فك تشفير مبالغ النقل في المعاملات السرية، مما يوفر آلية امتثال مع الحفاظ على الخصوصية من العامة.

التعليمات المطلوبة

يتطلب إنشاء mint مع تفعيل النقل السري ثلاث تعليمات في معاملة واحدة:

  1. إنشاء mint account: استدعاء تعليمة CreateAccount الخاصة بـ System Program لإنشاء mint account.

  2. تهيئة امتداد النقل السري: استدعاء تعليمة ConfidentialTransferInstruction::InitializeMint الخاصة بـ Token Extensions Program لتهيئة حالة ConfidentialTransferMint للـ mint.

  3. تهيئة Mint: استدعاء تعليمة Instruction::InitializeMint الخاصة بـ Token Extensions Program لتهيئة حالة mint القياسية.

بينما يمكنك كتابة هذه التعليمات يدويًا، توفر حزمة spl_token_client طريقة create_mint التي تبني معاملة وترسلها بجميع التعليمات الثلاث في استدعاء دالة واحد، كما هو موضح في المثال أدناه.

مثال على الكود

يوضح الكود التالي كيفية إنشاء mint مع امتداد النقل السري (Confidential Transfer).

تعتمد عمليات النقل السري على برنامج ZK ElGamal Proof، الذي يكون مُفعَّلاً على الشبكة الرئيسية (mainnet) وشبكة المطورين (devnet). إن solana-test-validator الافتراضي لا يُفعِّله، أما validator المحلي الذي يعمل بنسخة مفرَّعة من الشبكة الرئيسية مثل Surfpool فيدعمه. شغِّل المثال على إحداها (يستخدم الكود شبكة devnet) مع حساب ممول، واستبدل عناوين mint والحسابات الوهمية بعناوينك الخاصة.

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?

جدول المحتويات

تعديل الصفحة