Документація SolanaLiteSVMRustДодаткові контейнериlitesvm-token

Швидкий старт

Встановлення

Переконайтеся, що у вас є всі необхідні залежності:

cargo add --dev litesvm litesvm-token solana-sdk spl-token spl-associated-token-account

Основи SPL Token

У Solana створення token account є двоетапним процесом.

Створіть Mint Account

  • Не має балансу токенів
  • Зберігає всю глобальну інформацію про токен, наприклад загальну пропозицію, десяткові знаки, авторитет тощо
  • Існує один mint account на токен
  • Власником є Token Program (TokenKeg або Token 2022)

Створіть Token Account

  • Зберігає баланс для конкретного токена SPL
  • Містить mint account для визначення того, який токен SPL знаходиться на цьому рахунку
  • Для одного mint account може бути кілька token accounts
  • Власник — це той, хто має контроль над токенами всередині цього рахунку

Типи Token Accounts

Звичайний Token Account

Token account зберігає ваш баланс для конкретного токена SPL:

// Can create token accounts at ANY address
let token_account = Keypair::new(); // Random address
let create_ix = system_instruction::create_account(
&payer.pubkey(),
&token_account.pubkey(), // Any address you want
rent,
165, // Token account size
&spl_token::id(),
);
let init_ix = spl_token::instruction::initialize_account(
&spl_token::id(),
&token_account.pubkey(),
&mint,
&owner.pubkey(),
)?;

Переваги

  • Можна створювати кілька рахунків для одного mint/власника
  • Гнучкість — можна використовувати будь-яку адресу

Недоліки

  • Недетермінований — потрібно відстежувати адреси вручну
  • Одержувач повинен повідомити вам, на який рахунок надсилати
  • Створює плутанину за наявності кількох рахунків

Коли використовувати: Тимчасові/ескроу-рахунки, рахунки, що належать програмі з нестандартною логікою, коли потрібно кілька рахунків для одного токена, складні DeFi-стратегії.

Associated Token Account (ATA)

ATA — це token account за детермінованою PDA-адресою:

// ATA address is ALWAYS the same for owner + mint
let ata = get_associated_token_address(&owner.pubkey(), &mint);
// Address derived from: [owner_pubkey, token_program_id, mint]

Як виводиться ATA-адреса:

// ATA is a PDA owned by the Associated Token Program
let (ata, bump) = Pubkey::find_program_address(
&[
owner.as_ref(),
spl_token::id().as_ref(),
mint.as_ref(),
],
&spl_associated_token_account::id(), // ATA program
);

Переваги

  • Один канонічний рахунок на пару власник/mint
  • Детермінований — будь-хто може обчислити адресу
  • Спрощує платежі — потрібна лише адреса гаманця + mint
  • Стандартний підхід у всіх додатках Solana

Недоліки

  • Можна мати лише ОДИН ATA на пару власник/mint (за задумом)

Рекомендовано для більшості випадків: Гаманці, DeFi-протоколи, NFT-активи, платіжні системи та будь-які користувацькі перекази токенів.

Швидкий приклад

Ось повний приклад створення карбування токена та випуску токенів:

use litesvm::LiteSVM;
use litesvm_token::{
get_spl_account,
spl_token::{native_mint::DECIMALS, state::Account as TokenAccount},
CreateAccount, CreateMint, MintTo, Transfer,
};
use solana_sdk::{
native_token::LAMPORTS_PER_SOL,
signature::{Keypair, Signer},
};
#[test]
fn test_create_and_mint_tokens() {
let mut svm = LiteSVM::new();
// Create payer account and fund it
let payer = Keypair::new();
svm.airdrop(&payer.pubkey(), 10 * LAMPORTS_PER_SOL).unwrap();
// Create a new SPL token mint with the payer as the mint authority
let mint = CreateMint::new(&mut svm, &payer)
.authority(&payer.pubkey())
.decimals(DECIMALS)
.send()
.unwrap();
// Create a token account for the payer
let token_account = CreateAccount::new(&mut svm, &payer, &mint)
.owner(&payer.pubkey())
.send()
.unwrap();
// Mint tokens into the payer's token account
MintTo::new(&mut svm, &payer, &mint, &token_account, 1000)
.owner(&payer)
.send()
.unwrap();
// Verify balance
let token_account: TokenAccount = get_spl_account(&svm, &token_account).unwrap();
let account_balance = token_account.amount;
assert_eq!(account_balance, 1000)
}

Ключові концепції

Десяткові знаки токена

Більшість токенів використовують десяткові знаки для представлення дробових значень:

// SOL has 9 decimals
let one_sol = 10_u64.pow(9); // 1_000_000_000 lamports
// USDC has 6 decimals
let one_usdc = 10_u64.pow(6); // 1_000_000 micro-USDC
// Always account for decimals in calculations
let amount_tokens = 100;
let amount_raw = amount_tokens * 10_u64.pow(decimals as u32);

Зв'язки між акаунтами

Розуміння зв'язків між акаунтами є критично важливим:

  • Акаунт карбування: Визначає токен (пропозиція, десяткові знаки, повноваження)
  • Token account: Зберігає токени для конкретного власника
  • Associated token account: Детермінований token account для пари власник+карбування
  • Повноваження карбування: Може створювати нові токени
  • Повноваження заморожування: Може заморожувати token account (необов'язково)

Усунення несправностей

Поширені помилки

ПомилкаПричинаРішення
AccountNotFoundСпроба використати акаунт, який не існуєПереконайтеся, що акаунт створено перед використанням
AccountAlreadyInitializedСпроба ініціалізувати вже ініціалізований акаунтПеревірте наявність акаунта перед створенням
InsufficientFundsНедостатньо lamport для rent або токенів для переказуЗабезпечте достатнє фінансування/карбування
OwnerMismatchАкаунт належить неправильній програміПеревірте правильний ідентифікатор програми під час створення

Is this page helpful?