Установка
Убедитесь, что у вас есть все необходимые зависимости:
cargo add --dev litesvm litesvm-token solana-sdk spl-token spl-associated-token-account
Основы SPL-токенов
В 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 addresslet token_account = Keypair::new(); // Random addresslet create_ix = system_instruction::create_account(&payer.pubkey(),&token_account.pubkey(), // Any address you wantrent,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 + mintlet 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 Programlet (ata, bump) = Pubkey::find_program_address(&[owner.as_ref(),spl_token::id().as_ref(),mint.as_ref(),],&spl_associated_token_account::id(), // ATA program);
✓ Преимущества
- •Один канонический аккаунт на пару владелец/минт
- •Детерминированный — любой может вычислить адрес
- •Упрощает платежи — нужны только адрес кошелька и минт
- •Стандартное соглашение во всех приложениях Solana
✗ Недостатки
- •Можно иметь только ОДИН ATA на пару владелец/минт (по замыслу)
Рекомендуется в большинстве случаев: Кошельковые приложения, 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 itlet payer = Keypair::new();svm.airdrop(&payer.pubkey(), 10 * LAMPORTS_PER_SOL).unwrap();// Create a new SPL token mint with the payer as the mint authoritylet mint = CreateMint::new(&mut svm, &payer).authority(&payer.pubkey()).decimals(DECIMALS).send().unwrap();// Create a token account for the payerlet token_account = CreateAccount::new(&mut svm, &payer, &mint).owner(&payer.pubkey()).send().unwrap();// Mint tokens into the payer's token accountMintTo::new(&mut svm, &payer, &mint, &token_account, 1000).owner(&payer).send().unwrap();// Verify balancelet token_account: TokenAccount = get_spl_account(&svm, &token_account).unwrap();let account_balance = token_account.amount;assert_eq!(account_balance, 1000)}
Ключевые концепции
Десятичные знаки токена
Большинство токенов используют десятичные знаки для представления дробных количеств:
// SOL has 9 decimalslet one_sol = 10_u64.pow(9); // 1_000_000_000 lamports// USDC has 6 decimalslet one_usdc = 10_u64.pow(6); // 1_000_000 micro-USDC// Always account for decimals in calculationslet amount_tokens = 100;let amount_raw = amount_tokens * 10_u64.pow(decimals as u32);
Связи между аккаунтами
Понимание связей между аккаунтами имеет ключевое значение:
- Mint Account: Определяет токен (эмиссию, десятичные знаки, полномочия)
- Token Account: Хранит токены для конкретного владельца
- Associated Token Account: Детерминированный token account для пары владелец+минт
- Mint Authority: Может создавать новые токены
- Freeze Authority: Может замораживать token account (необязательно)
Устранение неполадок
Распространённые ошибки
| Ошибка | Причина | Решение |
|---|---|---|
AccountNotFound | Попытка использовать аккаунт, который не существует | Убедитесь, что аккаунт создан перед использованием |
AccountAlreadyInitialized | Попытка инициализировать уже инициализированный аккаунт | Проверьте, существует ли аккаунт перед созданием |
InsufficientFunds | Недостаточно lamport для rent или токенов для перевода | Обеспечьте достаточное финансирование/выпуск |
OwnerMismatch | Аккаунт принадлежит неверной программе | Проверьте правильность ID программы при создании |
Is this page helpful?