本文介绍了如何使用 Solana Web3.js 2.0 库在 Solana 区块链上创建可替代代币(Fungible Token),包括设置连接、生成密钥对、创建铸币账户、初始化铸币、创建关联代币账户(ATA)以及铸造代币等步骤。
Solana 的 Web3.js 2.0 库引入了一种与 Solana 区块链交互的新方式,强调可组合性和模块化。在本指南中,我们将探讨如何使用这个更新的库创建一个同质化代币。
让我们开始吧!
使用 Solana Web3.js 2.0 库编写一个脚本,在 Solana 区块链上创建一个同质化代币:
依赖项 | 版本 |
---|---|
@solana/web3.js | ^2.0.0 |
@solana-program/system | ^0.5.0 |
@solana-program/token | ^0.4.1 |
solana cli | 1.18.8 |
让我们开始吧!
Solana 上的同质化代币是一种数字资产,其中每个单位可以与同一代币的另一个单位互换。这些代币是使用 Solana 的代币程序创建和管理的,该程序提供了铸造、转移和销毁代币的功能。同质化代币可以用于存储和交换价值(例如,USDC 或其他资产)、作为实用工具(例如,用于即将推出的 NFT 铸造的白名单代币)、代表协议中的权益(例如,治理代币),或者任何你能想到的其他用途。
Solana 上同质化代币的关键组件包括:
现在,让我们探索如何使用 Solana Web3.js 2.0 创建这些组件。
首先,让我们设置我们的项目:
mkdir solana-fungible-token && cd solana-fungible-token
将你的项目初始化为 Node.js 项目:
npm init -y
安装依赖项:
npm install @solana/web3.js@2 @solana-program/system @solana-program/token && npm install --save-dev @types/node typescript ts-node
注意:你可能需要使用
--legacy-peer-deps
标志来安装@solana-program/system
和@solana-program/token
包。
在项目中添加一个 tsconfig.json
文件:
tsc --init --resolveJsonModule true
在项目目录中创建一个名为 create-token.ts
的新文件:
echo > create-token.ts
很好!现在,我们准备好开始编码了。
在你的 create-token.ts
文件中,让我们首先导入必要的依赖项:
import { getCreateAccountInstruction } from "@solana-program/system";
import {
findAssociatedTokenPda,
getCreateAssociatedTokenIdempotentInstructionAsync,
getInitializeMintInstruction,
getMintSize,
getMintToInstruction,
TOKEN_PROGRAM_ADDRESS
} from "@solana-program/token";
import {
airdropFactory,
createSolanaRpc,
createSolanaRpcSubscriptions,
generateKeyPairSigner,
lamports,
sendAndConfirmTransactionFactory,
pipe,
createTransactionMessage,
setTransactionMessageLifetimeUsingBlockhash,
signTransactionMessageWithSigners,
getSignatureFromTransaction,
setTransactionMessageFeePayerSigner,
appendTransactionMessageInstructions,
CompilableTransactionMessage,
TransactionMessageWithBlockhashLifetime,
Commitment,
} from "@solana/web3.js";
const LAMPORTS_PER_SOL = BigInt(1_000_000_000);
const DECIMALS = 9;
const DROP_AMOUNT = 100;
在这里,我们从 Solana Web3.js 2.0 库和 Solana 程序库中导入了各种函数。
接下来,让我们创建我们的 main
函数,该函数将包含我们脚本的逻辑:
async function main() {
// 1 - 建立与 Solana 集群的连接
// 2 - 生成密钥对
// 3 - 向支付者账户空投 SOL
// 4 - 创建铸币账户并初始化铸币
// 5 - 创建关联代币账户并铸造代币
}
main();
在 main
函数内部,让我们建立与本地 Solana 集群的连接:
// 1 - 建立与 Solana 集群的连接
const httpEndpoint = 'http://127.0.0.1:8899';
const wsEndpoint = 'ws://127.0.0.1:8900';
const rpc = createSolanaRpc(httpEndpoint);
const rpcSubscriptions = createSolanaRpcSubscriptions(wsEndpoint);
console.log(`✅ - 已建立与 ${httpEndpoint} 的连接`);
我们使用 createSolanaRpc
和 createSolanaRpcSubscriptions
函数来创建我们的 RPC 连接。在本指南中,我们使用 localhost,但如果你准备连接到远程 Solana 集群,你可以使用你的 QuickNode HTTP Provider 和 WSS Provider 端点,这些端点可以从你的 QuickNode 仪表板 获取。
让我们为代币创建过程生成必要的密钥对。在步骤 2 中的 main
函数中添加以下代码:
// 2 - 生成密钥对
const mintAuthority = await generateKeyPairSigner();
const payer = await generateKeyPairSigner();
const owner = await generateKeyPairSigner();
const mint = await generateKeyPairSigner();
const [ata] = await findAssociatedTokenPda({
mint: mint.address,
owner: owner.address,
tokenProgram: TOKEN_PROGRAM_ADDRESS,
});
console.log(`✅ - 已生成密钥对`);
console.log(` 铸币权限:${mintAuthority.address}`);
console.log(` 支付者:${payer.address}`);
console.log(` 所有者:${owner.address}`);
console.log(` 铸币账户:${mint.address}`);
console.log(` 关联代币账户:${ata}`);
在这里,我们为铸币权限、支付者、所有者和铸币账户本身生成了密钥对。我们还使用 findAssociatedTokenPda
函数派生了关联代币账户 (ATA) 地址。作为示例,我们将地址记录到控制台以供参考。
在创建代币之前,我们需要用 SOL 为我们的支付者账户提供资金。让我们使用 airdropFactory
函数来完成此操作。在步骤 3 中的 main
函数中添加以下代码:
// 3 - 向支付者账户空投 SOL
const airdrop = airdropFactory({ rpc, rpcSubscriptions });
const airdropTx = await airdrop({
commitment: 'processed',
lamports: lamports(LAMPORTS_PER_SOL),
recipientAddress: payer.address
});
console.log(`✅ - 已向支付者空投 1 SOL:${airdropTx}`);
在这里,我们使用 airdropFactory
函数创建一个 airdrop
函数,然后我们使用该函数向我们的支付者账户空投 1 SOL。
现在我们的 payer
账户有了 SOL,让我们创建并初始化我们的铸币账户。在步骤 4 中的 main
函数中添加以下代码:
// 4 - 创建铸币账户并初始化铸币
const mintSpace = BigInt(getMintSize());
const mintRent = await rpc.getMinimumBalanceForRentExemption(mintSpace).send();
const instructions = [\
// 创建铸币账户\
getCreateAccountInstruction({\
payer,\
newAccount: mint,\
lamports: mintRent,\
space: mintSpace,\
programAddress: TOKEN_PROGRAM_ADDRESS,\
}),\
// 初始化铸币\
getInitializeMintInstruction({\
mint: mint.address,\
decimals: DECIMALS,\
mintAuthority: mintAuthority.address\
}),\
];
const { value: latestBlockhash } = await rpc.getLatestBlockhash().send();
const sendAndConfirmTransaction = sendAndConfirmTransactionFactory({ rpc, rpcSubscriptions });
const signAndSendTransaction = createSignAndSendTransaction(sendAndConfirmTransaction);
const createMintTxid = await pipe(
createTransactionMessage({ version: 0 }),
(tx) => setTransactionMessageFeePayerSigner(payer, tx),
(tx) => setTransactionMessageLifetimeUsingBlockhash(latestBlockhash, tx),
(tx) => appendTransactionMessageInstructions(instructions, tx),
(tx) => signAndSendTransaction(tx)
);
console.log(`✅ - 铸币账户已创建并初始化:${createMintTxid}`);
此部分展示了 Web3.js 2.0 的几个关键特性:
getCreateAccountInstruction
和 getInitializeMintInstruction
来创建用于创建和初始化我们的铸币账户的指令。pipe
函数在创建和发送交易时将多个操作链接在一起。createSignAndSendTransaction
,这是我们稍后将定义的自定义辅助函数,以允许我们签名和发送我们的交易。最后,让我们创建另一个交易,为我们的所有者创建一个关联代币账户 (ATA) 并向其铸造一些代币。在步骤 5 中的 main
函数中添加以下代码:
// 5 - 创建关联代币账户并铸造代币
const mintInstructions = [\
// 创建目标关联代币账户\
await getCreateAssociatedTokenIdempotentInstructionAsync({\
mint: mint.address,\
payer,\
owner: owner.address,\
}),\
// 向目标关联代币账户铸造代币\
getMintToInstruction({\
mint: mint.address,\
token: ata,\
amount: BigInt(DROP_AMOUNT * 10 ** DECIMALS),\
mintAuthority, // 通过包含签名者而不是公钥来签名\
})\
];
const mintTxid = await pipe(
createTransactionMessage({ version: 0 }),
(tx) => setTransactionMessageFeePayerSigner(payer, tx),
(tx) => setTransactionMessageLifetimeUsingBlockhash(latestBlockhash, tx),
(tx) => appendTransactionMessageInstructions(mintInstructions, tx),
(tx) => signAndSendTransaction(tx)
);
console.log(`✅ - 代币已铸造到 ATA:${mintTxid}`);
在这里,我们为我们的所有者创建了一个 ATA 并向其铸造代币。我们使用 getCreateAssociatedTokenIdempotentInstructionAsync
函数来创建 ATA,并使用 getMintToInstruction
向其铸造代币。我们使用与步骤 4 中类似的 pipe
函数来创建和发送我们的交易。
让我们在文件末尾添加一个辅助函数来处理签名和发送交易。在你的 create-token.ts
文件末尾添加以下代码:
const createSignAndSendTransaction = (sendAndConfirmTransaction: ReturnType<typeof sendAndConfirmTransactionFactory>) => {
return async (
transactionMessage: CompilableTransactionMessage & TransactionMessageWithBlockhashLifetime,
commitment: Commitment = 'processed',
skipPreflight: boolean = true
) => {
const signedTransaction = await signTransactionMessageWithSigners(transactionMessage);
try {
await sendAndConfirmTransaction(signedTransaction, { commitment, skipPreflight });
return getSignatureFromTransaction(signedTransaction);
} catch (e) {
console.error('交易失败:', e);
throw e;
}
};
};
这个辅助函数封装了签名和发送交易的过程,使我们的主代码更加简洁和易读。
在本指南中,我们将使用本地 Solana 验证器。打开一个新的终端窗口并启动验证器:
solana-test-validator -r
当你准备好将你的代币投入生产时,你需要将其部署到 Solana 集群。无论是部署到主网还是开发网,你都可以通过注册 QuickNode 账户 来获得免费的 QuickNode 端点。
要运行我们的脚本,请使用以下命令:
ts-node create-token.ts
你应该会看到输出,指示成功连接、密钥对生成、空投、铸币创建和代币铸造:
✅ - 已建立与 http://127.0.0.1:8899 的连接
✅ - 已生成密钥对
铸币权限:7JBobKzJt8BgGwbPwGGGD2HyLMf6nGW1FXvHvd2xUKZ8
支付者:3eVn4tAFGGP5tW3Rc1Lqq7hEDUFJz8uxFpNa3SJsDtba
所有者:8nM1gKXDygKUWDCy8PJvAJvQUd11m5coQWUo7v5Zitm1
铸币账户:9vgOWh6vhd9s33S1JTzS3Hk1mPEp2kPMPNK1sY6lEYvZ
关联代币账户:6Z9Q5KyFbUZ2hYU2HfxUVPD6XpQUy1rHgLGLwR6sPGNj
✅ - 已向支付者空投 1 SOL:2gkQL7h7hHRWNfNwf2WyuPRmbhVd8oP7Ehfs54Pspqxx7KkYGF3wxjeoiVwLUHMgr9UYKY4PiMymmsGsQqKVWYoC
✅ - 铸币账户已创建并初始化:5JcnmFrYhPcZnmfUPecuBUJw9RVAoHwUQ2xGtcJ8XkHNwZHMWLR13eJcuqfkdbBnfRm1ajFTaF3E7WzQFyCpgCc3
✅ - 代币已铸造到 ATA:3nLePg18vjuVDM5m3z1jFSTPBYNWUHx4eaUprWXKqCu6ZNCYSBUgezp3xKnPeKQAjBRJmtVqc4ij3KvZUakqPa8y
干得好!你已经成功地使用 Solana Web3.js 2.0 创建了一个同质化代币。你应该能够在 本地 Solana 浏览器 中看到你的交易和铸币。
本指南通过创建一个脚本来使用 SPL 代币程序和新的 @solana-program/token
库执行一些基本操作,探索了新的 Solana Web3.js 2.0 库。希望在本指南之后,你开始看到新库的一些强大功能,以及它如何帮助你构建更复杂的应用程序。随着你继续探索 Web3.js 2.0,你会发现更多强大的功能和改进。继续努力!
如果你想继续练习,尝试扩展脚本以执行一些新操作:
getTransferCheckedInstruction
将 SPL 代币转移到另一个账户getBurnCheckedInstruction
销毁 SPL 代币getFreezeAccountInstruction
和 getThawAccountInstruction
冻结和解冻 SPL 代币告诉我们 如果你有任何反馈或新主题的请求。我们非常乐意听取你的意见。
- 原文链接: quicknode.com/guides/sol...
- 登链社区 AI 助手,为大家转译优秀英文文章,如有翻译不通的地方,还请包涵~
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!