O Que Faz a Transferência de Tokens?
A transferência de tokens move tokens de um token account para outro token account da mesma mint.
As transferências não alteram o fornecimento da mint. As transferências apenas atualizam os saldos entre token accounts.
Como Transferir Tokens
A transferência de tokens usa a instrução Transfer ou
TransferChecked do Token Program.
Os exemplos abaixo usam TransferChecked, que requer que o chamador forneça
a mint e os decimais para que a instrução possa verificar a mint esperada e a
precisão do token antes de mover tokens entre contas.
No Token Extensions Program, Transfer está descontinuado em favor de
TransferChecked ou TransferCheckedWithFee.
O proprietário do token account de origem ou um delegado aprovado assina a transferência. No Token Extensions Program, um delegado permanente da mint também pode autorizar a transferência se a mint tiver a extensão de delegado permanente habilitada.
Referência de Código-Fonte
| Item | Descrição | Token Program | Token Extensions Program |
|---|---|---|---|
Account | O estado do token account armazena os saldos atualizados por uma transferência. | Código-Fonte | Código-Fonte |
Transfer | Uma instrução de transferência que move tokens entre token accounts sem exigir que o chamador forneça a mint ou os decimais. No Token Extensions Program, use TransferChecked em vez disso. | Código-Fonte | Código-Fonte |
TransferChecked | Uma instrução de transferência que requer que o chamador forneça a mint e os decimais e verifica esses valores antes de mover tokens entre token accounts da mesma mint. | Código-Fonte | Código-Fonte |
process_transfer | Lógica compartilhada do processador para transferências de tokens. | Código-Fonte | Código-Fonte |
Typescript
Os exemplos Kit abaixo mostram a abordagem recomendada usando @solana/kit.
Exemplos legados usando @solana/web3.js estão incluídos para referência.
Kit
import { generateKeyPairSigner } from "@solana/kit";import { createLocalClient } from "@solana/kit-client-rpc";import {findAssociatedTokenPda,tokenProgram,TOKEN_PROGRAM_ADDRESS} from "@solana-program/token";const client = await createLocalClient().use(tokenProgram());const mint = await generateKeyPairSigner();const recipient = await generateKeyPairSigner();const result = await client.token.instructions.transferToATA({mint: mint.address, // Mint for the token being transferred.authority: client.payer, // Owner or delegate approving the transfer.recipient: recipient.address, // Account that owns the destination token account.amount: 25n, // Token amount in base units.decimals: 2 // Decimals defined on the mint account.}).sendTransaction();const [sourceTokenAccount] = await findAssociatedTokenPda({mint: mint.address,owner: client.payer.address,tokenProgram: TOKEN_PROGRAM_ADDRESS});const [destinationTokenAccount] = await findAssociatedTokenPda({mint: mint.address,owner: recipient.address,tokenProgram: TOKEN_PROGRAM_ADDRESS});const [sourceTokenAccountData, destinationTokenAccountData] =await client.token.accounts.token.fetchAll([sourceTokenAccount,destinationTokenAccount]);console.log("Mint Address:", mint.address);console.log("\nSource Token Account Address:", sourceTokenAccount);console.log("Source Token Account:", sourceTokenAccountData.data);console.log("\nDestination Token Account Address:", destinationTokenAccount);console.log("Destination Token Account:", destinationTokenAccountData.data);console.log("\nTransaction Signature:", result.context.signature);
Web3.js
import { Connection, Keypair, LAMPORTS_PER_SOL } from "@solana/web3.js";import {createAssociatedTokenAccount,createMint,getAccount,mintToChecked,TOKEN_PROGRAM_ID,transferChecked} from "@solana/spl-token";const result = await transferChecked(connection, // Connection to the local validator.feePayer, // Account paying transaction fees.feePayerATA, // Token account sending the tokens.mintPubkey, // Mint for the token being transferred.recipientATA, // Token account receiving the tokens.feePayer, // Owner or delegate approving the transfer.25, // Token amount in base units.2, // Decimals defined on the mint account.[], // Additional multisig signers.{commitment: "confirmed" // Confirmation options for the transaction.},TOKEN_PROGRAM_ID // Token program to invoke.);const senderTokenAccount = await getAccount(connection,feePayerATA,"confirmed",TOKEN_PROGRAM_ID);const recipientTokenAccount = await getAccount(connection,recipientATA,"confirmed",TOKEN_PROGRAM_ID);console.log("Mint Address:", mintPubkey.toBase58());console.log("\nSource Token Account Address:", feePayerATA.toBase58());console.log("Source Token Account:", senderTokenAccount);console.log("\nDestination Token Account Address:", recipientATA.toBase58());console.log("Destination Token Account:", recipientTokenAccount);console.log("\nTransaction Signature:", result);
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, mint_to_checked, transfer_checked},state::{Account, Mint},};#[tokio::main]async fn main() -> Result<()> {let client = RpcClient::new_with_commitment(String::from("http://localhost:8899"),CommitmentConfig::confirmed(),);let recipient = Keypair::new();let transfer_amount = 25;let transaction = Transaction::new_signed_with_payer(&[transfer_checked(&token_program_id(), // Token program to invoke.&source_token_address, // Token account sending the tokens.&mint.pubkey(), // Mint for the token being transferred.&destination_token_address, // Token account receiving the tokens.&fee_payer.pubkey(), // Owner or delegate approving the transfer.&[], // Additional multisig signers.transfer_amount, // Token amount in base units.decimals, // Decimals defined on the mint account.)?,],Some(&fee_payer.pubkey()),&[&fee_payer],latest_blockhash,);let transaction_signature = client.send_and_confirm_transaction(&transaction).await?;let source_token_account = client.get_account(&source_token_address).await?;let source_token_data = Account::unpack(&source_token_account.data)?;let destination_token_account = client.get_account(&destination_token_address).await?;let destination_token_data = Account::unpack(&destination_token_account.data)?;println!("Mint Address: {}", mint.pubkey());println!("\nSource Token Account Address: {}", source_token_address);println!("Source Token Account: {:#?}", source_token_data);println!("\nDestination Token Account Address: {}",destination_token_address);println!("Destination Token Account: {:#?}", destination_token_data);println!("\nTransaction Signature: {}", transaction_signature);Ok(())}
Python
#!/usr/bin/env python3import asyncioimport jsonfrom solana.rpc.async_api import AsyncClientfrom solders.keypair import Keypairfrom solders.message import Messagefrom solders.pubkey import Pubkeyfrom solders.system_program import create_account, CreateAccountParamsfrom solders.transaction import Transactionfrom spl.token.async_client import AsyncTokenfrom spl.token.instructions import (create_associated_token_account,get_associated_token_address,initialize_mint,InitializeMintParams,mint_to_checked,MintToCheckedParams,transfer_checked,TransferCheckedParams,)from spl.token.constants import MINT_LEN, TOKEN_PROGRAM_IDDECIMALS = 2AMOUNT_TO_MINT = 100AMOUNT_TO_TRANSFER = 25async def main():rpc = AsyncClient("http://localhost:8899")receiver = Keypair()async with rpc:transfer_tokens_instruction = transfer_checked(TransferCheckedParams(program_id=TOKEN_PROGRAM_ID, # Token program to invoke.source=source_token_account, # Token account sending the tokens.mint=mint.pubkey(), # Mint for the token being transferred.dest=destination_token_account, # Token account receiving the tokens.owner=fee_payer.pubkey(), # Account that owns the source token account.amount=AMOUNT_TO_TRANSFER, # Token amount in base units.decimals=DECIMALS, # Decimals defined on the mint account.))latest_blockhash = await rpc.get_latest_blockhash()transaction = Transaction([fee_payer],Message([transfer_tokens_instruction], fee_payer.pubkey()),latest_blockhash.value.blockhash,)result = await rpc.send_transaction(transaction)source_token_account_info = await token.get_account_info(source_token_account)destination_token_account_info = await token.get_account_info(destination_token_account)source_account = {key: str(value) if isinstance(value, Pubkey) else valuefor key, value in source_token_account_info._asdict().items()}destination_account = {key: str(value) if isinstance(value, Pubkey) else valuefor key, value in destination_token_account_info._asdict().items()}print("Mint Address:", mint.pubkey())print("\nSource Token Account Address:", source_token_account)print("Source Token Account:")print(json.dumps(source_account, indent=2))print("\nDestination Token Account Address:", destination_token_account)print("Destination Token Account:")print(json.dumps(destination_account, indent=2))print("\nTransaction Signature:", result.value)if __name__ == "__main__":asyncio.run(main())
Is this page helpful?