使用 Solana Web3.js 2.0 创建可替代代币

  • QuickNode
  • 发布于 2024-03-15 12:39
  • 阅读 29

本文介绍了如何使用 Solana Web3.js 2.0 库在 Solana 区块链上创建可替代代币(Fungible Token),包括设置连接、生成密钥对、创建铸币账户、初始化铸币、创建关联代币账户(ATA)以及铸造代币等步骤。

概述

Solana 的 Web3.js 2.0 库引入了一种与 Solana 区块链交互的新方式,强调可组合性和模块化。在本指南中,我们将探讨如何使用这个更新的库创建一个同质化代币。

让我们开始吧!

你将做什么

使用 Solana Web3.js 2.0 库编写一个脚本,在 Solana 区块链上创建一个同质化代币:

  • 建立与 Solana 集群的连接
  • 生成必要的密钥对
  • 创建铸币账户
  • 初始化铸币
  • 创建关联代币账户 (ATA)
  • 将代币铸造到 ATA

你将需要什么

本指南中使用的依赖项

依赖项 版本
@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 上的同质化代币是一种数字资产,其中每个单位可以与同一代币的另一个单位互换。这些代币是使用 Solana 的代币程序创建和管理的,该程序提供了铸造、转移和销毁代币的功能。同质化代币可以用于存储和交换价值(例如,USDC 或其他资产)、作为实用工具(例如,用于即将推出的 NFT 铸造的白名单代币)、代表协议中的权益(例如,治理代币),或者任何你能想到的其他用途。

Solana 上同质化代币的关键组件包括:

  1. 铸币账户:存储有关代币的信息,例如总供应量和小数位数。
  2. 代币账户:持有特定所有者的代币余额。
  3. 关联代币账户 (ATA):从所有者的地址和铸币地址派生的确定性代币账户。

现在,让我们探索如何使用 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();

建立与 Solana 集群的连接

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} 的连接`);

我们使用 createSolanaRpccreateSolanaRpcSubscriptions 函数来创建我们的 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

在创建代币之前,我们需要用 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 的几个关键特性:

  1. 我们使用 getCreateAccountInstructiongetInitializeMintInstruction 来创建用于创建和初始化我们的铸币账户的指令。
  2. 我们使用 pipe 函数在创建和发送交易时将多个操作链接在一起。
  3. 我们使用 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 代币
  • 使用 getFreezeAccountInstructiongetThawAccountInstruction 冻结和解冻 SPL 代币

我们 ❤️ 反馈!

告诉我们 如果你有任何反馈或新主题的请求。我们非常乐意听取你的意见。

资源

  • 原文链接: quicknode.com/guides/sol...
  • 登链社区 AI 助手,为大家转译优秀英文文章,如有翻译不通的地方,还请包涵~
点赞 0
收藏 0
分享
本文参与登链社区写作激励计划 ,好文好收益,欢迎正在阅读的你也加入。

0 条评论

请先 登录 后评论
QuickNode
QuickNode
江湖只有他的大名,没有他的介绍。