{"content":{"title":"理解 Solana 的 Mint 账户和 Token 账户","body":"Solana dApp 开发带来了一些新的挑战，特别是对于那些像我一样有过类似以太坊开发经验的人来说，智能合约既包含代码又包含状态存储。在 Solana 的世界中，程序不包含任何数据，而是引用可以存储数据的账户。对于开发人员来说，这是一个巨大的范式转变，但这极大地帮助提高了性能，因为只要程序不访问相同的账户数据，它们就可以并发运行。\r\n\r\n另一个好处是，与通常使用 ERC-20 标准时不同，不需要为每个新代币部署新的程序。事实上，代币的功能总是相同的，不同的是与特定代币相关的数据。因此，Solana 开发者已经包含了一个标准的 [代币程序](https://spl.solana.com/token)，已经部署完毕，任何人都可以使用它来创建、铸币、交易甚至销毁代币。\r\n\r\n## 一张图说明一切\r\n\r\n下图说明了代币程序、它使用的账户以及相关角色之间的关系：\r\n\r\n![代币程序、账户和角色](https://img.learnblockchain.cn/2025/02/25/1V8Y6UwvVd3wJuPyK-ppnqg.png)\r\n\r\n图 1：代币程序、相关账户和角色（使用 [Sketchboard.io](https://sketchboard.io/) 制作）\r\n\r\n第一个元素是代币程序本身，它已经部署完毕并可以使用。\r\n\r\n### Mint 账户\r\n\r\n当有人想要创建一个新代币时，他会使用 `create-token` 函数来初始化一个新的 **Mint 账户**，该账户包含代币的基本信息：`mint-authority` 是一个被授权铸造该代币的公钥 (_pubkey_)，`freeze-authority` 可以冻结代币账户（将在下面描述），以及一些附加数据，如代币的总 `supply`，`decimals` 的数量，以及 `isInitialized` 标志。该账户存储了有关代币及其权限的通用信息。注意到这里没有关于特定个人代币持有量的数据。这些数据存储在 **代币账户** 中。\r\n\r\n### 代币账户\r\n\r\n**代币账户** 保存了由 _pubkey_ 拥有的代币信息。然而，所有权关系会有点混乱。代币账户本身由代币程序拥有，代币程序通过账户中的 `owner`、`close-authority` 和 `delegate` 字段控制对这些代币的访问。`owner` 是能够花费/转移代币的 _pubkey_，`close-authority` 可以关闭账户，`owner` 可以授权 `delegate` _pubkey_ 花费最多 `delegatedAmount` 的代币。除了这些字段外，还有一些标志：`isInitialized`、`isFrozen`、`isNative`。默认情况下，代币账户在创建时被初始化，不会被冻结，并且不是本地的。之前我们看到，mint 账户定义了一个 `freeze-authority`，它有权冻结用户账户中的代币。通常，`freeze-authority` 为 null（全零）。在这种情况下，没有人可以冻结代币账户中持有的相应代币。\r\n\r\n## 理论太多，让我们在实践中看看这些内容\r\n\r\n### Solana CLI\r\n\r\n我们将使用 Solana 工具套件与代币程序进行交互。你可以在这里获取它：\r\n\r\n[安装 Solana 工具套件 ](https://docs.solana.com/cli/install-solana-cli-tools?source=post_page-----546c0590e8e---------------------------------------)\r\n\r\n安装完成后，我们可以配置工具套件以连接到 devnet，如下所示：\r\n\r\n```bash\r\nsolana config set --url devnet\r\n```\r\n\r\n### 创建一个用户账户\r\n\r\n用户需要一个密钥对（_即_ 公钥及其对应的私钥）来持有 SOL 并与 Solana 区块链进行交易。他们还需要持有一些 SOL 以支付网络费用。幸运的是，开发网络会“空投”少量 SOL 给任何请求的人。\r\n\r\n让我们首先使用工具套件中的 `solana-keygen` 命令创建一个密钥对：\r\n\r\n```bash\r\nsolana-keygen new -o ~/.config/solana/kp_alice.json\r\nKP_ALICE=~/.config/solana/kp_alice.json\r\nPK_ALICE=`solana address -k $KP_ALICE`\r\necho $PK_ALICE\r\n```\r\n\r\n环境变量 KP_ALICE 和 PK_ALICE 分别指包含私钥的文件和公钥的值。\r\n\r\n然后，为这个账户请求空投，并使用以下命令检查余额：\r\n\r\n```bash\r\nsolana airdrop 1 $PK_ALICE\r\nsolana balance $PK_ALICE\r\n```\r\n\r\n![获取空投并检查余额](https://img.learnblockchain.cn/2025/02/25/1YLvOSTiydvwiUO7VgwMGzw.png)\r\n\r\n图 1：获取空投并检查余额\r\n\r\n### 创建 Mint 账户\r\n\r\n\r\n`spl-token` 程序中的 `create-token` 函数创建 *mint account*。默认情况下，初始供应量为零，冻结权限为 null。以下命令创建铸币账户，将其 *pubkey* 存储在 ALICE\\_TOKEN 变量中，并显示代币的供应量和 Alice 在支付费用后的 SOL 余额：\r\n```\r\nspl-token create-token \\  \r\n    --mint-authority $KP_ALICE \\  \r\n    --fee-payer $KP_ALICE  \r\nALICE_TOKEN=<token address>  \r\nspl-token supply $ALICE_TOKEN  \r\nsolana balance $PK_ALICE\r\n```\r\n\r\n![](https://img.learnblockchain.cn/attachments/migrate/1740448247386)\r\n\r\n图 2：创建铸币账户\r\n\r\nSolana 区块链的一个有趣之处在于，任何人都可以查看账户的原始十六进制内容。让我们使用以下命令检查 *mint account*：\r\n```\r\nsolana account $ALICE_TOKEN\r\n```\r\n以下图显示了示例输出：\r\n\r\n![](https://img.learnblockchain.cn/attachments/migrate/1740448247403)\r\n\r\n图 3：铸币账户的内容\r\n\r\n前六行是账户的元数据，显示其 pubkey、余额、所有者、是否可执行、租金Epoch和长度。如前所述，铸币账户的所有者是 Token 程序。公钥是在创建账户时生成的，并唯一标识给定的代币。一个小余额（从费用支付者转移）被分配给该账户以“支付租金”，在 Solana 世界中，这就是存储账户数据在区块链上的成本。该金额被计算为匹配“免租”最低值，因此只要账户保持此最低值，实际上就不需要支付租金。\r\n\r\n其余行显示账户包含的十六进制原始数据。`mint-authority` 的 *pubkey* 是前 32 个高亮字节。稍后的 `09` 是 `decimals` 字段。在这种情况下，`freeze-authority` 是 null（全为零）。\r\n\r\n以下节点一行代码显示 ALICE 的 base58 公钥的十六进制版本，以进行验证：\r\n```\r\nnode -e 'console.log(require(\"bs58\").decode(\"TULnhBExK6hwmrmGfzcMSeDH58qCttzugnWakbmERva\"))'\r\n```\r\n\r\n### 创建代币账户\r\n\r\n任何希望持有特定代币的用户，都需要为相应的代币创建一个 *token account*。代币账户使用 `spl-token` 的 `create-account` 子命令创建，如下所示：\r\n```\r\nspl-token create-account \\  \r\n    --owner $PK_ALICE \\  \r\n    --fee-payer $KP_ALICE $ALICE_TOKENALICE_ALICETOKENACCOUNT=<token account pubkey>\r\n```\r\n![](https://img.learnblockchain.cn/attachments/migrate/1740448247406)\r\n\r\n图 4：创建代币账户\r\n\r\n查看代币账户的原始内容也很有趣：\r\n\r\nsolana account $ALICE\\_ALICETOKENACCOUNT\r\n\r\n![](https://img.learnblockchain.cn/attachments/migrate/1740448247517)\r\n\r\n图 5：代币账户的原始内容\r\n\r\n图 5 中的元数据显示分配给该代币账户的公钥、免租存储的余额、所有者是 Token 程序等。红框中高亮的是铸币账户的 pubkey（使用 `node -e ‘console.log(require(“bs58”).decode(“3XspNCGyc2iD2jvwb7XMBCCqkSiztJEtv3Swv5nRa56Q”))’` 进行检查），绿色框是代币所有者，在这种情况下是 ALICE 的 *pubkey*，我们已经知道。\r\n\r\n幸运的是，为了满足未来的需求，`spl-token` 工具包括一个子命令来解码代币账户。该命令是：\r\n\r\n```\r\nspl-token account-info --address $ALICE_ALICETOKENACCOUNT\r\n```\r\n\r\n这将返回解码的信息，如下所示：\r\n\r\n![](https://img.learnblockchain.cn/attachments/migrate/1740448248361)\r\n\r\n图 6：解码的代币账户信息\r\n\r\n### 铸造代币\r\n\r\n铸币权限可以为任何用户铸造代币。此过程会更新用户的余额（在代币账户中）和供应量（在铸币账户中）。要铸造代币，我们使用 `spl-token` 的 `mint` 子命令，如下所示：\r\n\r\n```\r\nspl-token mint $ALICE_TOKEN 41394 $ALICE_ALICETOKENACCOUNT \\  \r\n    --fee-payer $KP_ALICE \\  \r\n    --mint-authority $KP_ALICE\r\n```\r\n\r\n这将产生如下输出：\r\n\r\n![](https://img.learnblockchain.cn/attachments/migrate/1740448248364)\r\n\r\n图 7：铸造代币\r\n\r\n如果我们查看代币账户，我们将看到更新后的金额，如下图所示：\r\n\r\n![](https://img.learnblockchain.cn/attachments/migrate/1740448248717)\r\n\r\n图 8：代币账户中的余额\r\n\r\n以下一行代码让我们验证十六进制值。请注意，9 个零对应于代币的小数位数。还要注意，数值在代币账户中以 [小端](https://en.wikipedia.org/wiki/Endianness) 顺序存储。\r\n\r\n```\r\nnode -e 'a=41394000000000; console.log(a.toString(16))'\r\n```\r\n\r\n铸币账户也会更新以反映总供应量：\r\n\r\n![](https://img.learnblockchain.cn/attachments/migrate/1740448248896)\r\n\r\n当然，`spl-token` 提供子命令来检查总供应量和某个 *pubkey* 的余额：\r\n\r\n```\r\nspl-token balance --address $ALICE_ALICETOKENACCOUNT  \r\nspl-token supply $ALICE_TOKEN\r\n```\r\n\r\n这将给出以下结果：\r\n\r\n![](https://img.learnblockchain.cn/attachments/migrate/1740448249088)\r\n\r\n图 10：用户代币余额和代币供应量\r\n\r\n### 销毁代币\r\n\r\n当代币经济政策要求时，可能需要销毁代币。Alice 可以使用 `spl-token` 的 `burn` 子命令销毁自己的代币，如下所示：\r\n\r\n```\r\nspl-token burn $ALICE_ALICETOKENACCOUNT 394 \\  \r\n    --fee-payer $KP_ALICE \\  \r\n    --owner $KP_ALICE\r\n```\r\n\r\n图 11 说明了销毁代币并检查余额和供应量的过程：\r\n\r\n![](https://img.learnblockchain.cn/attachments/migrate/1740448249472)\r\n\r\n图 11：销毁代币，检查余额和供应量\r\n\r\n### 关闭代币账户\r\n\r\n如果 Alice 不再使用这个特定的代币，她可以关闭代币账户并取回剩余的 SOL 余额。请注意，关闭账户之前余额必须为零。关闭代币账户的命令如下：\r\n\r\n```\r\nspl-token close \\  \r\n    --address $ALICE_ALICETOKENACCOUNT \\  \r\n    --fee-payer $KP_ALICE \\  \r\n    --owner $KP_ALICE\r\n```\r\n\r\n图 12 说明了关闭账户的过程，并显示 SOL 余额的增加，反映代币账户剩余余额被转回给 Alice。\r\n\r\n![](https://img.learnblockchain.cn/attachments/migrate/1740448249634)\r\n\r\n图 12：关闭代币账户并返回 SOL 余额\r\n\r\n之后，账户被删除，释放了区块链中的相应空间，如图 13 所示：\r\n\r\n![](https://img.learnblockchain.cn/attachments/migrate/1740448249668)\r\n\r\n图 13：关闭的账户被删除\r\n\r\n## 结束语\r\n\r\n我们讨论了 Solana 区块链中铸币账户和代币账户的概念元素，并通过命令行工具展示了它们的操作。这只是冰山一角，还有许多其他操作，如冻结铸币账户，这对于创建 NFT 至关重要，以及处理委托。也许，这为未来的内容提供了丰富的材料。\r\n\r\n>- 原文链接： [medium.com/@jorge_london...](https://medium.com/@jorge_londono_31005/understanding-solanas-mint-account-and-token-accounts-546c0590e8e)\r\n>- 登链社区 AI 助手，为大家转译优秀英文文章，如有翻译不通的地方，还请包涵～"},"author":{"user":"https://learnblockchain.cn/people/26231","address":null},"history":"bafkreihw37w4hvjb5ljyzbp65igremg2st3djlaaim4vturmqjbizals6i","timestamp":1740448546,"version":1}