代币是代表不同类别资产所有权的数字资产。代币化使财产权利的数字化成为可能。Solana 上的代币被称为 SPL(Solana Program Library)代币。
本节介绍了代币在 Solana 上的基本表示方式。代码示例请参考 SPL 代币基础 部分。
关键要点
-
Token Program 包含了在网络上与代币(包括同质化和非同质化)交互的全部指令逻辑。
-
Mint Account 代表某一特定代币,并存储该代币的全局元数据,如总发行量和铸造权限(有权创建新代币单位的地址)。
-
Token Account 用于跟踪特定所有者在特定 mint account 下的代币持有情况。
-
Associated Token Account 是通过所有者和 mint account 地址派生出的 Token Account。
Token Program
Solana 生态系统有两个主要的 Token Program。以下是这两个程序的源代码。
Token Program(原版)
- 基础代币功能(铸造、转账等)
- 不可变且被广泛使用
Token Extension Program(Token 2022)
- 包含原始 Token Program 的所有功能
- 通过“扩展”增加新特性
Token Program 包含了在网络上与代币(包括同质化和非同质化)交互的全部指令逻辑。Solana 上的所有代币本质上都是由 Token Program 拥有的 数据账户。
Token Program
Mint Account
Solana 上的代币由 Token Program 拥有的 Mint Account 地址唯一标识。该账户作为某一特定代币的全局计数器,并存储如下数据:
- Supply:该代币的总发行量
- Decimals:代币的小数精度
- Mint authority:有权铸造新代币、增加总供应量的账户
- Freeze authority:有权冻结 Token Account 中代币、阻止其转账或销毁的账户
Mint Account
每个 mint account 存储的完整信息包括:
pub struct Mint {/// Optional authority used to mint new tokens. The mint authority may only/// be provided during mint creation. If no mint authority is present/// then the mint has a fixed supply and no further tokens may be/// minted.pub mint_authority: COption<Pubkey>,/// Total supply of tokens.pub supply: u64,/// Number of base 10 digits to the right of the decimal place.pub decimals: u8,/// Is `true` if this structure has been initializedpub is_initialized: bool,/// Optional authority to freeze token accounts.pub freeze_authority: COption<Pubkey>,}
供参考,这里有一个 Solana Explorer 上的 USDC mint account 链接。
Token Account
Token Program 会创建 token account,用于追踪每个代币单位的个人持有情况。token account 会存储如下数据:
- Mint:该 token account 持有的代币
- Owner:有权从该 token account 转移代币的账户
- Amount:该 token account 当前持有的代币数量
Token Account
每个 token account 存储的完整信息包括:
pub struct Account {/// The mint associated with this accountpub mint: Pubkey,/// The owner of this account.pub owner: Pubkey,/// The amount of tokens this account holds.pub amount: u64,/// If `delegate` is `Some` then `delegated_amount` represents/// the amount authorized by the delegatepub delegate: COption<Pubkey>,/// The account's statepub state: AccountState,/// If is_native.is_some, this is a native token, and the value logs the/// rent-exempt reserve. An Account is required to be rent-exempt, so/// the value is used by the Processor to ensure that wrapped SOL/// accounts do not drop below this threshold.pub is_native: COption<u64>,/// The amount delegatedpub delegated_amount: u64,/// Optional authority to close the account.pub close_authority: COption<Pubkey>,}
每个钱包想要持有某个代币(mint)时,都需要一个对应的 token account,并将钱包地址设置为 token account 的 owner。每个钱包可以拥有多个相同代币(mint)的 token account,但每个 token account 只能有一个 owner,并且只能持有一种代币(mint)。
账户关系
请注意,每个 token account 的数据都包含一个 owner 字段,用于标识谁拥有该 token
account 的权限。这与基础 Account
类型中指定的程序 owner 不同,后者对于所有 token account 来说都是 Token Program。
关联代币账户
Associated Token Account 简化了查找特定 mint 和所有者的 token account 地址的流程。你可以将 Associated Token Account 理解为某个 mint 和所有者的“默认” token account。
Associated Token Account 是通过从所有者地址和 mint account 地址派生出的地址创建的。需要注意的是,Associated Token Account 其实就是一个具有特定地址的 token account。
这引入了 Solana 开发中的一个关键概念:Program Derived Address (PDA)。PDA 通过预定义的输入确定性地派生出一个地址,使得查找账户地址变得简单。
Associated Token Account
请注意,每个钱包都需要自己的 token account 来持有同一个 mint 的代币。
账户关系扩展
Token CLI 示例
spl-token CLI 可帮助你体验 SPL 代币。以下示例使用
Solana Playground
终端直接在浏览器中运行 CLI 命令,无需本地安装。
创建代币和账户时需要 SOL 用于账户 rent 押金和交易手续费。首次使用 Solana
Playground 时,请先创建 Playground 钱包,并在 Playground 终端运行
solana airdrop 命令。你也可以通过公共
web faucet 获取 devnet SOL。
$solana airdrop 2
运行 spl-token --help 查看所有可用命令。
$spl-token --help
如需在本地安装 spl-token CLI,请运行:
$cargo install spl-token-cli
在 spl-token 文档
中查看更多示例。
你在终端输出中看到的账户地址会与下方示例不同。操作时请使用你 Playground 终端中的地址。例如,create-token
命令会输出以你的 Playground 钱包为 mint authority 的 mint account 地址。
创建新代币
要创建一个新的代币(mint account),请运行:
$spl-token create-token
输出如下:
Creating token 99zqUzQGohamfYxyo8ykTEbi91iom3CLmwCA75FK5zTgAddress: 99zqUzQGohamfYxyo8ykTEbi91iom3CLmwCA75FK5zTgDecimals: 9Signature: 44fvKfT1ezBUwdzrCys3fvCdFxbLMnNvBstds76QZyE6cXag5NupBprSXwxPTzzjrC3cA6nvUZaLFTvmcKyzxrm1
新的 mint account 初始供应量为零。可通过以下命令检查当前供应量:
$spl-token supply <TOKEN_ADDRESS>
新代币的 supply 命令返回 0:
spl-token supply 99zqUzQGohamfYxyo8ykTEbi91iom3CLmwCA75FK5zTg
创建新的 Mint Account 需要包含两个指令的交易。以下是在 Solana Playground 上的 Javascript 示例。
-
System Program 创建一个新账户,为 Mint Account 数据分配空间,并将所有权转移给 Token Program。
-
Token Program 将新账户的数据初始化为 Mint Account。
创建 Token Account
要持有某个 mint 的代币,请创建一个 token account:
$spl-token create-account <TOKEN_ADDRESS>
示例命令:
spl-token create-account 99zqUzQGohamfYxyo8ykTEbi91iom3CLmwCA75FK5zTg
输出:
Creating account AfB7uwBEsGtrrBqPTVqEgzWed5XdYfM1psPNLmf7EeX9Signature: 2BtrynuCLX9CNofFiaw6Yzbx6hit66pup9Sk7aFjwU2NEbFz7NCHD9w9sWhrCfEd73XveAGK1DxFpJoQZPXU9tS1
create-account 命令会创建一个以你的钱包地址为所有者的 associated token
account。
如需为不同的所有者创建 token account:
$spl-token create-account --owner <OWNER_ADDRESS> <TOKEN_ADDRESS>
注意:<TOKEN_ADDRESS> 指定了 token account 所对应的 mint account。
示例命令:
spl-token create-account --owner 2i3KvjDCZWxBsqcxBHpdEaZYQwQSYE6LXUMx5VjY5XrR 99zqUzQGohamfYxyo8ykTEbi91iom3CLmwCA75FK5zTg
输出:
Creating account Hmyk3FSw4cfsuAes7sanp2oxSkE9ivaH6pMzDzbacqmtSignature: 44vqKdfzspT592REDPY4goaRJH3uJ3Ce13G4BCuUHg35dVUbHuGTHvqn4ZjYF9BGe9QrjMfe9GmuLkQhSZCBQuEt
创建 Associated Token Account 只需一个指令,该指令会调用 Associated Token Program。以下是在 Solana Playground 上的 Javascript 示例。
Associated Token Program 使用 跨程序调用 来:
- 调用 System Program 使用提供的 PDA 作为地址创建新账户
- 调用 Token Program 初始化 Token Account 数据
如果要用新的 keypair 创建一个新的 Token Account,而不是使用 Associated Token Account 地址,需要发送包含两个指令的交易。以下是在 Solana Playground 上的 Javascript 示例。
-
System Program 创建一个新账户,为 Token Account 数据分配空间,并将所有权转移给 Token Program。
-
Token Program 将数据初始化为 Token Account。
铸造代币
要创建新的代币单位,请将代币铸造到 Token Account:
$spl-token mint [OPTIONS] <TOKEN_ADDRESS> <TOKEN_AMOUNT> [--] [RECIPIENT_TOKEN_ACCOUNT_ADDRESS]
示例命令:
spl-token mint 99zqUzQGohamfYxyo8ykTEbi91iom3CLmwCA75FK5zTg 100
输出:
Minting 100 tokensToken: 99zqUzQGohamfYxyo8ykTEbi91iom3CLmwCA75FK5zTgRecipient: AfB7uwBEsGtrrBqPTVqEgzWed5XdYfM1psPNLmf7EeX9Signature: 2NJ1m7qCraPSBAVxbr2ssmWZmBU9Jc8pDtJAnyZsZJRcaYCYMqq1oRY1gqA4ddQno3g3xcnny5fzr1dvsnFKMEqG
要将代币铸造到其他 token account:
spl-token mint 99zqUzQGohamfYxyo8ykTEbi91iom3CLmwCA75FK5zTg 100 -- Hmyk3FSw4cfsuAes7sanp2oxSkE9ivaH6pMzDzbacqmt
输出:
Minting 100 tokensToken: 99zqUzQGohamfYxyo8ykTEbi91iom3CLmwCA75FK5zTgRecipient: Hmyk3FSw4cfsuAes7sanp2oxSkE9ivaH6pMzDzbacqmtSignature: 3SQvNM3o9DsTiLwcEkSPT1Edr14RgE2wC54TEjonEP2swyVCp2jPWYWdD6RwXUGpvDNUkKWzVBZVFShn5yntxVd7
Token Program 上的 MintTo 指令用于创建新代币。mint
authority 必须签署该交易。该指令会将代币铸造到 Token Account,并增加 Mint
Account 上的总供应量。以下是在
Solana Playground
上的 Javascript 示例。
转账代币
要在 token account 之间转账代币:
spl-token transfer [OPTIONS] <TOKEN_ADDRESS> <TOKEN_AMOUNT> <RECIPIENT_ADDRESS or RECIPIENT_TOKEN_ACCOUNT_ADDRESS>
示例命令:
spl-token transfer 99zqUzQGohamfYxyo8ykTEbi91iom3CLmwCA75FK5zTg 100 Hmyk3FSw4cfsuAes7sanp2oxSkE9ivaH6pMzDzbacqmt
输出:
Transfer 100 tokensSender: AfB7uwBEsGtrrBqPTVqEgzWed5XdYfM1psPNLmf7EeX9Recipient: Hmyk3FSw4cfsuAes7sanp2oxSkE9ivaH6pMzDzbacqmtSignature: 5y6HVwV8V2hHGLTVmTmdySRiEUCZnWmkasAvJ7J6m7JR46obbGKCBqUFgLpZu5zQGwM4Xy6GZ4M5LKd1h6Padx3o
Token Program 中的 Transfer 指令用于处理代币转账。发送方 Token
Account 的所有者必须签署该交易。此指令会在 Token
Account 之间转移代币。这里有一个 Javascript 示例,见
Solana Playground。
发送方和接收方都需要拥有该特定代币(mint)的 token account。发送方可以在同一笔交易中包含创建接收方 token account 的指令。
创建 Token 元数据
Token Extensions Program 允许你将元数据(名称、符号、图片链接)直接存储在 Mint Account 上。
要创建带有元数据扩展的代币:
spl-token create-token --program-id TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb --enable-metadata
输出:
Creating token BdhzpzhTD1MFqBiwNdrRy4jFo2FHFufw3n9e8sVjJczP under program TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEbTo initialize metadata inside the mint, please run `spl-token initialize-metadata BdhzpzhTD1MFqBiwNdrRy4jFo2FHFufw3n9e8sVjJczP <YOUR_TOKEN_NAME> <YOUR_TOKEN_SYMBOL> <YOUR_TOKEN_URI>`, and sign with the mint authority.Address: BdhzpzhTD1MFqBiwNdrRy4jFo2FHFufw3n9e8sVjJczPDecimals: 9Signature: 5iQofFeXdYhMi9uTzZghcq8stAaa6CY6saUwcdnELST13eNSifiuLbvR5DnRt311frkCTUh5oecj8YEvZSB3wfai
初始化元数据的方法:
spl-token initialize-metadata <TOKEN_MINT_ADDRESS> <YOUR_TOKEN_NAME> <YOUR_TOKEN_SYMBOL> <YOUR_TOKEN_URI>
token URI 指向链下元数据。示例 JSON 格式见 这里。
示例命令:
spl-token initialize-metadata BdhzpzhTD1MFqBiwNdrRy4jFo2FHFufw3n9e8sVjJczP "TokenName" "TokenSymbol" "https://raw.githubusercontent.com/solana-developers/opos-asset/main/assets/DeveloperPortal/metadata.json"
在 Solana Explorer 上查看元数据。
详细了解请参阅 Metadata Extension 指南。关于 Token Extensions 的更多信息,请参阅 Token Extensions 入门指南 以及 SPL 文档。
Is this page helpful?