إنشاء حساب رمزي

ما هو الحساب الرمزي

يخزن الحساب الرمزي الرموز لعملة واحدة ومالك حساب رمزي واحد على سولانا.

Token Account Type
/// Account data.
#[repr(C)]
#[derive(Clone, Copy, Debug, Default, PartialEq)]
pub struct Account {
/// The mint associated with this account
pub mint: Pubkey,
/// The owner of this account.
pub owner: Pubkey,
/// The amount of tokens this account holds.
pub amount: u64,
/// If `delegate` is `Some` then `delegated_amount` represents
/// the amount authorized by the delegate
pub delegate: COption<Pubkey>,
/// The account's state
pub state: AccountState,
/// If `is_native.is_some`, this is a native token, and the value logs the
/// rent-exempt reserve. An Account is required to be rent-exempt, so
/// the value is used by the Processor to ensure that wrapped SOL
/// accounts do not drop below this threshold.
pub is_native: COption<u64>,
/// The amount delegated
pub delegated_amount: u64,
/// Optional authority to close the account.
pub close_authority: COption<Pubkey>,
}

هنا، تعني owner الصلاحية التي يمكنها نقل أو حرق أو تفويض الرموز من الحساب الرمزي. مالك برنامج الحساب لا يزال هو Token Program أو Token Extensions Program.

كل حساب رمزي مرتبط بعملة واحدة بالضبط، مما يعني أن الحساب الرمزي يمكنه الاحتفاظ بوحدات من رمز واحد فقط، وهو الرمز المحدد بحقل mint للحساب الرمزي.

ما هو الحساب الرمزي المرتبط

الحساب الرمزي المرتبط (ATA) هو الحساب الرمزي الافتراضي للمحفظة والعملة. يشتق Associated Token Program عنوان الحساب الرمزي المرتبط من عنوان المحفظة وعنوان برنامج الرمز وعنوان العملة.

فقط الحسابات الرمزية التي تم إنشاؤها بواسطة Associated Token Program تُسمى حسابات رمزية مرتبطة.

Associated Token Program هو طريقة لإنشاء حساب رمزي عند عنوان قياسي وحتمي. الحساب الناتج لا يزال حسابًا رمزيًا مملوكًا من قبل Token Program أو Token Extensions Program، وليس من قبل Associated Token Program.

يشتق Associated Token Program عنوان الحساب الرمزي المرتبط كما هو موضح في address.rs:

Associated Token Account Address Derivation
pub fn get_associated_token_address_and_bump_seed_internal(
wallet_address: &Pubkey,
token_mint_address: &Pubkey,
program_id: &Pubkey,
token_program_id: &Pubkey,
) -> (Pubkey, u8) {
Pubkey::find_program_address(
&[
&wallet_address.to_bytes(), // Owner's public key
&token_program_id.to_bytes(), // Token Program or Token Extension Program
&token_mint_address.to_bytes(), // Token mint address
],
program_id, // Associated Token Program ID
)
}

لأي مجموعة من المحفظة وبرنامج الرمز والعملة، يوجد عنوان حساب رمزي مرتبط واحد بالضبط. ينشئ Associated Token Program حسابًا رمزيًا قياسيًا عند ذلك العنوان، ولا يزال الحساب الناتج يستخدم نوع Account المحدد بواسطة Token Program أو Token Extensions Program.

كيفية إنشاء حساب رمز مرتبط

يستخدم إنشاء حساب رمز مرتبط تعليمة Create أو CreateIdempotent من برنامج الرموز المرتبطة. يقوم برنامج الرموز المرتبطة باشتقاق عنوان الحساب المرتبط، وإنشاء الحساب على هذا العنوان، وتهيئة الحساب كحساب رمز مملوك من قبل برنامج الرموز أو برنامج امتدادات الرموز.

موصى به

بالنسبة لمعظم التطبيقات، قم بإنشاء حسابات الرموز من خلال برنامج الرموز المرتبطة بدلاً من إنشائها مباشرة عن طريق استدعاء تعليمات برنامج النظام وبرنامج الرموز. يستخدم حساب الرمز المرتبط عنواناً قطعياً مشتقاً من المالك وبرنامج الرموز والنعناع، مما يجعل حساب الرموز الافتراضي لنعناع معين أسهل في العثور عليه من قبل المحافظ والتطبيقات.

المرجع المصدري

العنصرالوصفالمصدر
Createينشئ حساب رمز مرتبط على عنوان الحساب المرتبط المشتق.المصدر
CreateIdempotentينشئ حساب الرمز المرتبط، لكنه ينجح أيضاً إذا كان هذا الحساب المرتبط موجوداً بالفعل لنفس المالك والنعناع.المصدر
process_create_associated_token_accountيشتق عنوان الحساب المرتبط ويستخدم create_pda_account بالإضافة إلى استدعاءات البرامج المتقاطعة لبرنامج الرموز المحدد لتهيئة حساب الرمز. عندما يكون البرنامج المحدد هو برنامج امتدادات الرموز، يقوم معالج الحساب المرتبط أيضاً بتهيئة امتداد المالك الثابت.المصدر
create_pda_accountأداة مساعدة يستخدمها process_create_associated_token_account لإنشاء حساب العنوان المشتق بالبرنامج عن طريق استدعاء متقاطع لبرنامج النظام.المصدر

TypeScript

توضح أمثلة Kit أدناه النهج الموصى به باستخدام @solana/kit. تم تضمين أمثلة قديمة تستخدم @solana/web3.js للإشارة.

Kit

import { generateKeyPairSigner } from "@solana/kit";
import { createLocalClient } from "@solana/kit-client-rpc";
import {
associatedTokenProgram,
findAssociatedTokenPda,
tokenProgram,
TOKEN_PROGRAM_ADDRESS
} from "@solana-program/token";
const client = await createLocalClient()
.use(tokenProgram())
.use(associatedTokenProgram());
const result = await client.associatedToken.instructions
.createAssociatedToken({
payer: client.payer, // Account funding account creation.
mint: mint.address, // Mint for the token this account holds.
owner: client.payer.address // Account that owns the token account.
})
.sendTransaction();
const [associatedTokenAddress] = await findAssociatedTokenPda({
mint: mint.address,
owner: client.payer.address,
tokenProgram: TOKEN_PROGRAM_ADDRESS
});
const tokenAccountData = await client.token.accounts.token.fetch(
associatedTokenAddress
);
console.log("Mint Address:", mint.address);
console.log("\nAssociated Token Account Address:", associatedTokenAddress);
console.log("Associated Token Account:", tokenAccountData.data);
console.log("\nTransaction Signature:", result.context.signature);
Console
Click to execute the code.

Web3.js

import { Connection, Keypair, LAMPORTS_PER_SOL } from "@solana/web3.js";
import {
createAssociatedTokenAccount,
createMint,
getAccount,
TOKEN_PROGRAM_ID
} from "@solana/spl-token";
const associatedTokenAccount = await createAssociatedTokenAccount(
connection, // Connection to the local validator.
feePayer, // Account funding account creation.
mintPubkey, // Mint for the token this account holds.
feePayer.publicKey, // Account that owns the token account.
{
commitment: "confirmed" // Confirmation options for the transaction.
},
TOKEN_PROGRAM_ID // Token program to invoke.
);
const tokenAccountData = await getAccount(
connection,
associatedTokenAccount,
"confirmed",
TOKEN_PROGRAM_ID
);
console.log("Mint Address:", mintPubkey.toBase58());
console.log(
"\nAssociated Token Account Address:",
associatedTokenAccount.toBase58()
);
console.log("Associated Token Account:", tokenAccountData);
Console
Click to execute the code.

Rust

Rust
use anyhow::Result;
use solana_client::nonblocking::rpc_client::RpcClient;
use solana_commitment_config::CommitmentConfig;
use solana_sdk::{
program_pack::Pack,
signature::{Keypair, Signer},
transaction::Transaction,
};
use solana_system_interface::instruction::create_account;
use spl_associated_token_account_interface::{
address::get_associated_token_address, instruction::create_associated_token_account,
};
use spl_token_interface::{
id as token_program_id,
instruction::initialize_mint,
state::{Account, Mint},
};
#[tokio::main]
async fn main() -> Result<()> {
let client = RpcClient::new_with_commitment(
String::from("http://localhost:8899"),
CommitmentConfig::confirmed(),
);
let transaction = Transaction::new_signed_with_payer(
&[
create_associated_token_account(
&fee_payer.pubkey(), // Account funding account creation.
&fee_payer.pubkey(), // Account that owns the token account.
&mint.pubkey(), // Mint for the token this account holds.
&token_program_id(), // Token program that owns the account.
),
],
Some(&fee_payer.pubkey()),
&[&fee_payer],
latest_blockhash,
);
let transaction_signature = client.send_and_confirm_transaction(&transaction).await?;
let associated_token_account = get_associated_token_address(&fee_payer.pubkey(), &mint.pubkey());
let token_account = client.get_account(&associated_token_account).await?;
let token_data = Account::unpack(&token_account.data)?;
println!("Mint Address: {}", mint.pubkey());
println!(
"\nAssociated Token Account Address: {}",
associated_token_account
);
println!("Associated Token Account: {:#?}", token_data);
println!("\nTransaction Signature: {}", transaction_signature);
Ok(())
}
Console
Click to execute the code.

Python

Python
#!/usr/bin/env python3
import asyncio
import json
from solana.rpc.async_api import AsyncClient
from solders.keypair import Keypair
from solders.message import Message
from solders.pubkey import Pubkey
from solders.system_program import create_account, CreateAccountParams
from solders.transaction import Transaction
from spl.token.async_client import AsyncToken
from spl.token.instructions import (
create_associated_token_account,
get_associated_token_address,
initialize_mint,
InitializeMintParams,
)
from spl.token.constants import MINT_LEN, TOKEN_PROGRAM_ID
async def main():
rpc = AsyncClient("http://localhost:8899")
fee_payer = Keypair()
owner = Keypair()
async with rpc:
create_associated_token_account_instruction = create_associated_token_account(
payer=fee_payer.pubkey(), # Account funding account creation.
owner=owner.pubkey(), # Account that owns the token account.
mint=mint.pubkey(), # Mint for the token this account holds.
token_program_id=TOKEN_PROGRAM_ID, # Token program that owns the new token account.
)
latest_blockhash = await rpc.get_latest_blockhash()
transaction = Transaction(
[fee_payer],
Message([create_associated_token_account_instruction], fee_payer.pubkey()),
latest_blockhash.value.blockhash,
)
result = await rpc.send_transaction(transaction)
token_account_info = await token.get_account_info(associated_token_account)
token_account = {
key: str(value) if isinstance(value, Pubkey) else value
for key, value in token_account_info._asdict().items()
}
print("Mint Address:", mint.pubkey())
print("\nToken Account Address:", associated_token_account)
print("Token Account:")
print(json.dumps(token_account, indent=2))
print("\nTransaction Signature:", result.value)
if __name__ == "__main__":
asyncio.run(main())
Console
Click to execute the code.

كيفية إنشاء حساب رمز

إنشاء حساب رمز يتطلب تعليمتين:

  1. تعليمة CreateAccount الخاصة بـ System Program تُنشئ حسابًا جديدًا معفيًا من rent وتُعيّن Token Program كمالك البرنامج للحساب الجديد.
  2. تعليمة InitializeAccount أو InitializeAccount2 أو InitializeAccount3 الخاصة بـ Token Program تُهيّئ الحساب الجديد لعملة ومالك.

قم بتضمين تعليمة CreateAccount وتعليمة تهيئة حساب الرمز في نفس المعاملة.

أثناء تهيئة حساب الرمز، يتحقق Token Program من أن الحساب غير مُهيّأ بالفعل وأنه معفي من rent.

يوضح القسم أدناه كيفية إنشاء حساب رمز من خلال استدعاء تعليمات System Program و Token Program مباشرة. بالنسبة لمعظم التطبيقات، استخدم Associated Token Program بدلاً من ذلك. استخدم استدعاءات System Program و Token Program المباشرة عندما يكون لديك سبب محدد لعدم استخدام associated token account أو عندما تحتاج إلى إنشاء حسابات رمز PDA مخصصة عن طريق إجراء CPIs لتعليمات System Program و Token Program من برنامج سولانا الخاص بك.

المرجع المصدري

العنصرالوصفToken ProgramToken Extensions Program
Accountحقول حساب الرمز الأساسية المخزنة في كل token account.المصدرالمصدر
InitializeAccountتعليمة تهيئة حساب رمز تتوقع حساب المالك و rent sysvar في قائمة حساباتها.المصدرالمصدر
InitializeAccount2تعليمة تهيئة حساب رمز تمرر المالك في instruction data بدلاً من قائمة الحسابات.المصدرالمصدر
InitializeAccount3تعليمة تهيئة حساب رمز تمرر المالك في instruction data ولا تتطلب حساب rent sysvar.المصدرالمصدر
_process_initialize_accountمنطق المعالج المشترك لتهيئة حساب الرمز.المصدرالمصدر
process_initialize_accountالمعالج العام لـ InitializeAccount.المصدرالمصدر
process_initialize_account2المعالج العام لـ InitializeAccount2.المصدرالمصدر
process_initialize_account3المعالج العام لـ InitializeAccount3.المصدرالمصدر

Typescript

توضح الأمثلة في Kit أدناه النهج الموصى به باستخدام @solana/kit. تم تضمين أمثلة قديمة باستخدام @solana/web3.js للرجوع إليها.

Kit

import { generateKeyPairSigner } from "@solana/kit";
import { createLocalClient } from "@solana/kit-client-rpc";
import { systemProgram } from "@solana-program/system";
import {
getTokenSize,
tokenProgram,
TOKEN_PROGRAM_ADDRESS
} from "@solana-program/token";
const client = await createLocalClient()
.use(systemProgram())
.use(tokenProgram());
const result = await client.sendTransaction([
client.system.instructions.createAccount({
newAccount: tokenAccount, // New token account to create.
lamports: rent, // Lamports funding the new account rent.
space, // Account size in bytes.
programAddress: TOKEN_PROGRAM_ADDRESS // Program that owns the new account.
}),
client.token.instructions.initializeAccount({
account: tokenAccount.address, // Token account to initialize.
mint: mint.address, // Mint for the token this account holds.
owner: client.payer.address // Account that owns the token account.
})
]);
const tokenAccountData = await client.token.accounts.token.fetch(
tokenAccount.address
);
console.log("Mint Address:", mint.address);
console.log("\nToken Account Address:", tokenAccount.address);
console.log("Token Account:", tokenAccountData.data);
console.log("\nTransaction Signature:", result.context.signature);
Console
Click to execute the code.

Web3.js

import { Connection, Keypair, LAMPORTS_PER_SOL } from "@solana/web3.js";
import {
createAccount,
createMint,
getAccount,
TOKEN_PROGRAM_ID
} from "@solana/spl-token";
const tokenAccount = await createAccount(
connection, // Connection to the local validator.
feePayer, // Account paying transaction fees.
mintPubkey, // Mint for the token this account holds.
feePayer.publicKey, // Account that owns the token account.
Keypair.generate(), // New token account to create.
{
commitment: "confirmed" // Confirmation options for the transaction.
},
TOKEN_PROGRAM_ID // Token program to invoke.
);
const tokenAccountData = await getAccount(
connection,
tokenAccount,
"confirmed",
TOKEN_PROGRAM_ID
);
console.log("Mint Address:", mintPubkey.toBase58());
console.log("\nToken Account Address:", tokenAccount.toBase58());
console.log("Token Account:", tokenAccountData);
Console
Click to execute the code.

Rust

Rust
use anyhow::Result;
use solana_client::nonblocking::rpc_client::RpcClient;
use solana_commitment_config::CommitmentConfig;
use solana_sdk::{
program_pack::Pack,
signature::{Keypair, Signer},
transaction::Transaction,
};
use solana_system_interface::instruction::create_account;
use spl_token_interface::{
id as token_program_id,
instruction::{initialize_account, initialize_mint},
state::{Account, Mint},
};
#[tokio::main]
async fn main() -> Result<()> {
let client = RpcClient::new_with_commitment(
String::from("http://localhost:8899"),
CommitmentConfig::confirmed(),
);
let token_account = Keypair::new();
let token_account_rent = client
.get_minimum_balance_for_rent_exemption(Account::LEN)
.await?;
let transaction = Transaction::new_signed_with_payer(
&[
create_account(
&fee_payer.pubkey(), // Account funding account creation.
&token_account.pubkey(), // New token account to create.
token_account_rent, // Lamports funding the new account rent.
Account::LEN as u64, // Account size in bytes.
&token_program_id(), // Program that owns the new account.
),
initialize_account(
&token_program_id(),
&token_account.pubkey(), // Token account to initialize.
&mint.pubkey(), // Mint for the token this account holds.
&fee_payer.pubkey(), // Account that owns the token account.
)?,
],
Some(&fee_payer.pubkey()),
&[&fee_payer, &token_account],
latest_blockhash,
);
let transaction_signature = client.send_and_confirm_transaction(&transaction).await?;
let token_account_data = client.get_account(&token_account.pubkey()).await?;
let token_data = Account::unpack(&token_account_data.data)?;
println!("Mint Address: {}", mint.pubkey());
println!("\nToken Account Address: {}", token_account.pubkey());
println!("Token Account: {:#?}", token_data);
println!("\nTransaction Signature: {}", transaction_signature);
Ok(())
}
Console
Click to execute the code.

Python

Python
#!/usr/bin/env python3
import asyncio
import json
from solana.rpc.async_api import AsyncClient
from solders.keypair import Keypair
from solders.message import Message
from solders.pubkey import Pubkey
from solders.system_program import create_account, CreateAccountParams
from solders.transaction import Transaction
from spl.token.async_client import AsyncToken
from spl.token.instructions import (
initialize_account,
InitializeAccountParams,
initialize_mint,
InitializeMintParams,
)
from spl.token.constants import ACCOUNT_LEN, MINT_LEN, TOKEN_PROGRAM_ID
async def main():
rpc = AsyncClient("http://localhost:8899")
async with rpc:
token_account = Keypair()
token_account_rent = (await rpc.get_minimum_balance_for_rent_exemption(ACCOUNT_LEN)).value
create_token_account_instructions = [
create_account(
CreateAccountParams(
from_pubkey=fee_payer.pubkey(), # Account funding account creation.
to_pubkey=token_account.pubkey(), # New token account to create.
lamports=token_account_rent, # Lamports funding the new account rent.
space=ACCOUNT_LEN, # Account size in bytes.
owner=TOKEN_PROGRAM_ID, # Program that owns the new token account.
)
),
initialize_account(
InitializeAccountParams(
program_id=TOKEN_PROGRAM_ID, # Token program to invoke.
account=token_account.pubkey(), # Token account to initialize.
mint=mint.pubkey(), # Mint for the token this account holds.
owner=fee_payer.pubkey(), # Account that owns the token account.
)
),
]
latest_blockhash = await rpc.get_latest_blockhash()
transaction = Transaction(
[fee_payer, token_account],
Message(create_token_account_instructions, fee_payer.pubkey()),
latest_blockhash.value.blockhash,
)
result = await rpc.send_transaction(transaction)
token_account_info = await token.get_account_info(token_account.pubkey())
token_account_data = {
key: str(value) if isinstance(value, Pubkey) else value
for key, value in token_account_info._asdict().items()
}
print("Mint Address:", mint.pubkey())
print("\nToken Account Address:", token_account.pubkey())
print("Token Account:")
print(json.dumps(token_account_data, indent=2))
print("\nTransaction Signature:", result.value)
if __name__ == "__main__":
asyncio.run(main())
Console
Click to execute the code.

Is this page helpful?

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

تعديل الصفحة

تدار بواسطة

© 2026 مؤسسة سولانا.
جميع الحقوق محفوظة.
تواصل معنا