即插即用 Token 扩展

  • Helius
  • 发布于 2024-02-09 14:43
  • 阅读 22

这篇文章介绍了Solana上的Token Extensions,详细讲解了如何使用TypeScript在Solana Playground中创建各种可编程代币,包括NFT、生息代币、灵魂绑定代币等,并提供了代码示例和操作步骤。

8分钟阅读 2024年2月7日

介绍

Token Extensions 使在 Solana 上创建可编程代币变得简单。开发人员可以使用新的 Token Extensions program 结合多达十几种 Mint 和 Account Extensions。通过完成本教程,你将创建并与可替代和不可替代代币、带息代币、冻结代币、你拥有绝对权限(包括将其移出不属于你的账户)的代币以及关闭 mint 账户以恢复资金进行交互。

即插即用的 Token Extensions 是一个与互动的 Solana Playground 例子,通过 TypeScript 帮助你学习 Token Extensions,以创建以下代币:

本教程所用的代码改编自 Solana Developer Guide。创建 Token Extensions 的脚本可以在 额外资源 部分找到。

Token Extensions 账户

引入新指令,Token Extensions 是建立在 Token Program 之上的。使用这两个程序创建的账户在初始长度上是相同的,直到 Token 程序指令结束和 Token Extensions 指令开始。对账户数据不熟悉的人可以在 Anchor 简介 中阅读关于账户空间的内容。简言之,Solana 上的账户必须创建时明确分配存储链上数据的空间。在这个空间中,我们可以计算出使账户免租所需的 lamports 数量。

这就是创建具有扩展的 mint 账户的样子。要为 Token Extensions 分配空间,使用 getMintLen 函数获取包含扩展的 mint 账户的大小。在 NonFungibleToken.ts 示例中,获取 MetadataPointerMintCloseAuthority 扩展类型的 mint 长度。

NonFungibleToken.ts 第 54 行:

代码

  // 带扩展的 Mint 账户的大小
  const mintLen = getMintLen([\
    ExtensionType.MetadataPointer,\
    ExtensionType.MintCloseAuthority,\
  ]);

Metadata 和 Metadata Pointer 扩展允许你存储并指向元数据,而无需依赖第三方协议。TokenMetadata 是来自 @solana/spl-token-metadata 的接口,包含字段如 updateAuthoritymintnamesymboluriadditionalMetadata。元数据长度通过对元数据对象使用 pack 函数来找到。

NonFungibleToken.ts 第 60 行:

代码

  // 存储在 Mint 账户中的元数据
  const metaData: TokenMetadata = {
    updateAuthority: updateAuthority,
    mint: mint,
    name: "Solana Soldier",
    symbol: "SOLD",
    uri: "https://shdw-drive.genesysgo.net/G1Tzt42SDqCV3x9vPY5X826foA8fEk8BR4bB5wARh75d/OIG2.jpg",
    additionalMetadata: [["armor", null]],
  };
  // 元数据大小
  const metadataLen = pack(metaData).length;
  // MetadataExtension 的大小 2 字节用于类型,2 字节用于长度
  const metadataExtension = TYPE_SIZE + LENGTH_SIZE;

将 mint 长度、元数据扩展和元数据长度相加,以找到 Mint 账户所需的最少 lamports。

NonFungibleToken.ts 第 75 行:

代码

  // Mint 账户所需的最少 lamports
  const lamports = await connection.getMinimumBalanceForRentExemption(
    mintLen + metadataExtension + metadataLen
  );

Token Extensions 指令

Solana 库如 @solana/spl-token@solana/spl-token-metadata 为 Token Extensions 程序添加了 TypeScript 支持。首先,使用来自 @solana/web3.jsSystemProgram 创建具有适当空间和免租 lamports 的账户。

NonFungibleToken.ts 第 80 行:

代码

  // 调用 System Program 创建新账户的指令
  const createAccountInstruction = SystemProgram.createAccount({
    fromPubkey: payer.publicKey, // 将 lamports 转移到创建账户的账户
    newAccountPubkey: mint, // 要创建的账户地址
    space: mintLen, // 分配给创建账户的字节数
    lamports, // 转移到创建账户的 lamports 数量
    programId: TOKEN_2022_PROGRAM_ID, // 被分配为创建账户所有者的程序
  });

接下来,我们可以创建指令来指定 mint。在调用 initializeMint 之前,必须先执行以下指令。即插即用 中使用的预 mint 指令有:

元数据账户可以独立于 initializeMint 初始化和更新。然而,元数据指针必须在 mint 之前初始化。交易中的指令顺序决定了它们的执行顺序。创建一个 mint 账户,初始化元数据指针,然后用 mint 的公钥初始化 mint close authority。接着,初始化 mint 和元数据账户并更新附加元数据。

NonFungibleToken.ts 第 135 行:

代码

  transaction = new Transaction().add(
    createAccountInstruction,
    initializeMetadataPointerInstruction,
    initializeMintCloseAuthorityInstruction,
    initializeMintInstruction,
    initializeMetadataInstruction,
    updateFieldInstruction
  );

文件 nonFungibleToken.tssoulboundToken.tsinterestBearingToken.tsdelegateToken.ts 采用相同的结构创建代币,不同之处在于使用的扩展和指令。

该过程从导入所需的 Solana 库中的所有必要函数开始,定义支付者,并生成 mint 地址。然后,找到所需代币扩展的 mint 地址所需的空间和 lamports。使用 @solana/spl-token@solana/spl-token-metadata 库创建指令,将它们添加到一个交易中,发送交易到网络,并验证结果。

诸如转移和烧毁等代币操作可以在不同的代币扩展上使用。带有元数据扩展的代币可以使用 createUpdateFieldInstructioncreateRemoveKeyInstruction 指令分别更新或删除元数据。

即插即用

Solana Playground 中,客户端包含与 Token Extensions 交互所需的功能。例如,灵魂绑定代币使用不可转移和元数据扩展创建灵魂绑定 NFT。创建和与代币交互的函数在同一个文件中可用(在 Solana Playground 的情况下,你必须复制并粘贴代码,而不是导入它)。

quest.ts 文件允许你扮演 Solana Soldier。或者,运行每个包含代币扩展的文件,以查看其特定功能。Playground Wallet 需要 Devnet SOL 来运行任务。官方 Solana Faucet 也可用于空投 Devnet SOL。

任务从创建一个 Solana Soldier 开始,这是一个 NFT,支付者 (pg.wallet.keypair) 将拥有 mint close authority ——允许支付者关闭并从 mint 账户中回收 SOL。这种机制对应用程序有用,可以从不再活跃的账户中返回 SOL。

image.png

创建 Solana Soldier 后,使用他们的 mint 地址更新 NFT 的元数据。让我们将士兵的护甲更新为 iron。可以在 NonFungibleToken.ts 文件中从第 167 行找到 getMetadataupdateMetadataremoveMetadata 函数。可以对使用 Metadata Extension 的 mint 账户调用这些函数。为了简便起见,元数据函数仅在 NonFungibleToken.ts 文件中包含。

接下来,是时候开始升级了。一个 带息代币 将表示 Solana Soldier 的等级。从 InterestBearingToken.ts 导入 createInterestBearingToken,并使用该指令创建代币。账户上的利息将根据在 InterestBearingToken.ts 第 43 行设置的利率增长。可以使用 amountToUiAmount 函数来确定带有累积利息的代币数量。利息随着时间的推移而积累,我们可以调用 amountToUiAmount 来检查 Solana Soldier 的等级。

一旦士兵开始升级,他们就需要接受任务。该任务由一个 灵魂绑定代币 表示 —— 士兵不能转移它(尝试通过调用转移函数捕获错误),也只能通过烧毁它来摆脱任务。与其放弃任务,不如检查一下。提示,查看元数据!

Solana soldier soulbound tokenmage.png

一旦你阅读了任务,即插即用 的教程将在 token 地址上部署一支军队。Solana Soldier 必须能够在代币部署后召回军队到支付者。Token Extensions 通过引入代理权限使这成为可能。代理权限可以转移和烧毁代币,而不论是谁拥有代币。将永久代理设置为你可以访问的密钥对,该密钥对需要签名以便烧毁和转移代币。

代理代币 将代表 Solana Army。通过 DelegateToken.ts 第 33 行的 createDelegateTokens 创建代理代币,转移到敌人的代币账户。当代币铸造时,Solana Army 和敌人在理论上进行战斗。战斗结束后,使用在 DelegateTokens.ts 第 176 行找到的 transferDelegateTokens 函数从敌人账户召回士兵。

Solana army delegate tokens

请注意,并非所有士兵都被从敌人的地址召回。假设他们已经阵亡。使用来自 @solana/spl-tokenburn 函数来烧毁敌人代币账户中剩余的代币 (sourceTokenAccount)。

随着战斗的成功,Solana Soldier 的任务结束。使用 @solana/spl-tokencloseAccount 函数关闭账户并返还租金。本文未讨论的 Token Extensions 包括机密转账、转账费用和转账钩子。几乎所有的代币扩展都可以混合搭配,除了像转账钩子和不可转移代币这样的少数例外。与本教程中涉及的 Token Extensions 相关的参考 Solana Playgrounds 链接于 额外资源 中。

结论

受到 CryptoZombies 的启发,本 即插即用 教程涵盖了使用扩展组合创建流行 Token Extensions 的基础知识。该教程通过动手游戏体验展示了 Token Extensions 的组装性。这些示例可以直接使用,也可以作为开发人员编写自己代币的指南。从计算账户大小到指令排序,这些示例提供了创建带 Token Extensions 的账户的简化过程。如果你发现这种游戏化学习体验具有教育意义,请在我们的 Discord 上分享反馈或在 X 上标记 @heliuslabs

额外资源

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

0 条评论

请先 登录 后评论
Helius
Helius
https://www.helius.dev/