Δημιουργία Token Account

Τι Είναι ένας Token Account

Ένας token account αποθηκεύει tokens για ένα mint και έναν κάτοχο token account στο Solana.

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 σημαίνει την αρχή που μπορεί να μεταφέρει, να καταστρέψει ή να αναθέσει tokens από τον token account. Ο κάτοχος του προγράμματος του λογαριασμού εξακολουθεί να είναι το Token Program ή το Token Extensions Program.

Κάθε token account συνδέεται ακριβώς με ένα mint, που σημαίνει ότι ο token account μπορεί να κατέχει μονάδες μόνο ενός token, του token που προσδιορίζεται από το πεδίο mint του token account.

Τι Είναι ένας Associated Token Account

Ένας associated token account (ATA) είναι ο προεπιλεγμένος token account για ένα πορτοφόλι και mint. Το Associated Token Program παράγει τη διεύθυνση ATA από τη διεύθυνση του πορτοφολιού, τη διεύθυνση του token program και τη διεύθυνση mint.

Μόνο οι token accounts που δημιουργούνται από το Associated Token Program ονομάζονται associated token accounts.

Το Associated Token Program είναι ένας τρόπος δημιουργίας ενός token account σε μια τυπική, ντετερμινιστική διεύθυνση. Ο προκύπτων λογαριασμός παραμένει ένας token account που ανήκει στο Token Program ή Token Extensions Program, όχι στο Associated Token Program.

Το Associated Token Program παράγει τη διεύθυνση ATA όπως φαίνεται στο 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
)
}

Για οποιονδήποτε συνδυασμό πορτοφολιού, token program και mint, υπάρχει ακριβώς μία διεύθυνση ATA. Το Associated Token Program δημιουργεί έναν τυπικό token account σε αυτήν τη διεύθυνση, και ο προκύπτων λογαριασμός εξακολουθεί να χρησιμοποιεί τον τύπο Account που ορίζεται από το Token Program ή Token Extensions Program.

Πώς να Δημιουργήσετε έναν Συσχετισμένο Λογαριασμό Token

Η δημιουργία ενός συσχετισμένου λογαριασμού token χρησιμοποιεί την εντολή Create ή CreateIdempotent του Associated Token Program. Το Associated Token Program παράγει τη διεύθυνση ATA, δημιουργεί τον λογαριασμό στη διεύθυνση ATA και αρχικοποιεί τον λογαριασμό ως λογαριασμό token που ανήκει στο Token Program ή το Token Extension Program.

Συνιστάται

Για τις περισσότερες εφαρμογές, δημιουργήστε λογαριασμούς token μέσω του Associated Token Program αντί να τους δημιουργείτε καλώντας απευθείας τις εντολές του System Program και του Token Program. Ένας συσχετισμένος λογαριασμός token χρησιμοποιεί μια ντετερμινιστική διεύθυνση που προκύπτει από τον κάτοχο, το πρόγραμμα token και το mint, κάτι που καθιστά τον προεπιλεγμένο λογαριασμό token για ένα συγκεκριμένο mint ευκολότερο στην εύρεση από πορτοφόλια και εφαρμογές.

Αναφορά Πηγής

ΣτοιχείοΠεριγραφήΠηγή
CreateΔημιουργεί έναν συσχετισμένο λογαριασμό token στην παραγόμενη διεύθυνση ATA.Πηγή
CreateIdempotentΔημιουργεί τον συσχετισμένο λογαριασμό token, αλλά εξακολουθεί να επιτυγχάνει ακόμα και αν αυτό το ATA υπάρχει ήδη για τον ίδιο κάτοχο και mint.Πηγή
process_create_associated_token_accountΠαράγει τη διεύθυνση ATA και χρησιμοποιεί το create_pda_account συν CPIs στο επιλεγμένο πρόγραμμα token για να αρχικοποιήσει τον λογαριασμό token. Όταν το επιλεγμένο πρόγραμμα είναι το Token Extension Program, ο επεξεργαστής ATA αρχικοποιεί επίσης την επέκταση αμετάβλητου κατόχου.Πηγή
create_pda_accountΒοηθητική λειτουργία που χρησιμοποιείται από το process_create_associated_token_account για τη δημιουργία του λογαριασμού PDA μέσω CPI στο System Program.Πηγή

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.

Πώς να Δημιουργήσετε έναν Λογαριασμό Token

Η δημιουργία ενός token account απαιτεί δύο εντολές:

  1. Η εντολή CreateAccount του System Program δημιουργεί έναν νέο λογαριασμό απαλλαγμένο από rent και αναθέτει το Token Program ως κάτοχο προγράμματος του νέου λογαριασμού.
  2. Η εντολή InitializeAccount, InitializeAccount2, ή InitializeAccount3 του Token Program αρχικοποιεί τον νέο λογαριασμό για ένα mint και έναν κάτοχο.

Συμπεριλάβετε την εντολή CreateAccount και την εντολή αρχικοποίησης token account στην ίδια συναλλαγή.

Κατά την αρχικοποίηση του token account, το Token Program ελέγχει ότι ο λογαριασμός δεν έχει ήδη αρχικοποιηθεί και είναι απαλλαγμένος από rent.

Η παρακάτω ενότητα δείχνει πώς να δημιουργήσετε έναν token account καλώντας απευθείας τις εντολές του System Program και του Token Program. Για τις περισσότερες εφαρμογές, χρησιμοποιήστε το Associated Token Program αντί αυτού. Χρησιμοποιήστε απευθείας κλήσεις στο System Program και Token Program όταν έχετε έναν συγκεκριμένο λόγο να μη χρησιμοποιήσετε ένα associated token account ή όταν χρειάζεται να δημιουργήσετε προσαρμοσμένους token accounts PDA κάνοντας CPIs στο System Program και τις εντολές του Token Program από το δικό σας πρόγραμμα Solana.

Αναφορά Πηγής

ΣτοιχείοΠεριγραφήToken ProgramToken Extensions Program
AccountΤα βασικά πεδία token account που αποθηκεύονται σε κάθε token account.ΠηγήΠηγή
InitializeAccountΜια εντολή αρχικοποίησης token account που αναμένει τον κάτοχο και τον λογαριασμό rent sysvar στη λίστα λογαριασμών της.ΠηγήΠηγή
InitializeAccount2Μια εντολή αρχικοποίησης token account που περνάει τον κάτοχο στα instruction data αντί για τη λίστα λογαριασμών.ΠηγήΠηγή
InitializeAccount3Μια εντολή αρχικοποίησης token account που περνάει τον κάτοχο στα instruction data και δεν απαιτεί τον λογαριασμό rent sysvar.ΠηγήΠηγή
_process_initialize_accountΚοινή λογική επεξεργαστή για την αρχικοποίηση token 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 Ίδρυμα Solana.
Με επιφύλαξη παντός δικαιώματος.
Συνδεθείτε