The Token Program
在 Solana 上,所有与代币相关的操作都由 SPL Token Program 和 Token2022 Program 处理:这是 Solana 的原生代币框架,定义了所有代币的创建、管理和转移方式。
这是一个统一的程序,处理网络中的所有代币操作,确保一致性和互操作性。
让我们从使用 Web3.js 安装所需的包以与 SPL Token Program 一起工作开始:
npm i @solana/spl-token
Mint and Token Accounts
在底层,创建一个 Mint
和 Token
账户是相当“复杂”的。需要不同的指令、不同的输入和账户;在实际初始化之前,账户需要达到免租金状态,等等。
Mint Account
如果没有任何抽象,创建一个 Mint
账户看起来会是这样的:
import {
Keypair,
sendAndConfirmTransaction,
SystemProgram,
Transaction,
} from "@solana/web3.js";
import {
createInitializeMint2Instruction,
MINT_SIZE,
getMinimumBalanceForRentExemptMint,
TOKEN_PROGRAM_ID,
} from "@solana/spl-token";
const mint = Keypair.generate();
const mintRent = await getMinimumBalanceForRentExemptMint(connection);
const createAccountInstruction = SystemProgram.createAccount({
fromPubkey: feePayer.publicKey,
newAccountPubkey: mint.publicKey,
space: MINT_SIZE,
lamports: mintRent,
programId: TOKEN_PROGRAM_ID
});
const initializeMintInstruction = createInitializeMint2Instruction(
mint.publicKey, // mint pubkey
6, // decimals
feePayer.publicKey, // mint authority
null, // freeze authority
TOKEN_PROGRAM_ID
);
const transaction = new Transaction().add(
createAccountInstruction,
initializeMintInstruction,
);
const signature = await sendAndConfirmTransaction(connection, transaction, [keypair, mint]);
console.log(`Mint created! Check out your TX here: https://explorer.solana.com/tx/${signature}?cluster=devnet`);
幸运的是,@solana/spl-token
包提供了一些抽象。因此,我们可以通过一个简单的 createMint()
函数来创建一个 Mint
账户,如下所示:
const mint = await createMint(
connection, // connection
keypair, // payer
keypair.publicKey, // mint authority
null, // freeze authority
6 // decimals
);
Token Account
同样地,创建 Token
账户如果没有任何抽象会是这样的:
import {
Keypair,
sendAndConfirmTransaction,
SystemProgram,
Transaction,
} from "@solana/web3.js";
import {
createInitializeAccount3Instruction,
ACCOUNT_SIZE,
getMinimumBalanceForRentExemptAccount,
TOKEN_PROGRAM_ID,
} from "@solana/spl-token";
const token = Keypair.generate();
const tokenRent = await getMinimumBalanceForRentExemptAccount(connection);
const createAccountInstruction = SystemProgram.createAccount({
fromPubkey: feePayer.publicKey,
newAccountPubkey: token.publicKey,
space: ACCOUNT_SIZE,
lamports: tokenRent,
programId: TOKEN_PROGRAM_ID
});
const initializeTokenInstruction = createInitializeAccount3Instruction(
token.publicKey, // token pubkey
mint.publicKey, // mint pubkey
feePayer.publicKey, // owner pubkey
TOKEN_PROGRAM_ID
);
const transaction = new Transaction().add(
createAccountInstruction,
initializeTokenInstruction,
);
const signature = await sendAndConfirmTransaction(connection, transaction, [keypair, token]);
console.log(`Token created! Check out your TX here: https://explorer.solana.com/tx/${signature}?cluster=devnet`);
但与 Mint
账户一样,@solana/spl-token
包提供了一些抽象来创建 Token
账户。我们可以使用 createAccount()
函数,如下所示:
const token = await createAccount(
connection, // connection
keypair, // payer
mint.publicKey, // mint pubkey
keypair.publicKey, // owner pubkey
);
Associated Token Account
对于 Associated Token
账户也是如此,但抽象与账户的创建无关,而主要与地址的派生有关,就像 Mint
和 Token
账户一样。
以下是如何在没有任何抽象的情况下创建一个 Associated Token
账户:
import {
sendAndConfirmTransaction,
Transaction,
} from "@solana/web3.js";
import {
TOKEN_PROGRAM_ID
createAssociatedTokenAccountIdempotentInstruction,
getAssociatedTokenAddress,
} from "@solana/spl-token";
const associatedTokenAccount = await getAssociatedTokenAddress(
mint.publicKey, // mint pubkey
keypair.publicKey, // owner pubkey
false, // allow owner off-curve
TOKEN_PROGRAM_ID
);
// Create ATA creation instructions for all accounts
const createAtaInstruction = createAssociatedTokenAccountIdempotentInstruction(
keypair.publicKey, // payer
associatedTokenAccount, // associated token account address
keypair.publicKey, // owner
mint.publicKey, // mint
TOKEN_PROGRAM_ID
);
const transaction = new Transaction().add(
createAtaInstruction,
);
const signature = await sendAndConfirmTransaction(connection, transaction, [keypair]);
console.log(`Associated Token created! Check out your TX here: https://explorer.solana.com/tx/${signature}?cluster=devnet`);
以下是带有抽象的实现方式:
const ata = await getOrCreateAssociatedTokenAccount(
connection, // connection
keypair, // payer
mint, // mint pubkey
keypair.publicKey // owner pubkey
);