Solana[part4]_Token解析&创建

Solana[part4]_Token解析&创建

solana上的代币

代币是代表对各种资产所有权的数字资产。代币化使得财产权的数字化成为可能,是管理可替代和不可替代资产的基本组成部分

  • 可替代代币代表同类型和同价值的可互换和可分割资产(例如 USDC)
  • 不可替代代币(NFT)代表不可分隔资产的所有权(例如艺术品)

SPL(Solana Program Library)

SPL 是 Solana 生态的核心程序库,其中 Token Program 是创建和管理代币的基础协议,主要涉及以下核心概念:

  • Token Program:Solana 上的标准代币协议,定义了代币的创建、转账、铸币、销毁等核心逻辑
  • Mint Account:代币的"铸造源",存储代币的元数据(如总供应量、小数位数、是否可铸币/冻结等),每个代币类型对应唯一的 Mint 账户
  • Token Account:用户持有特定代币的账户,关联到一个 Mint 账户和一个所有者钱包,用于实际存储代币余额
  • Associated Token Account (ATA):与钱包地址绑定的标准代币账户,遵循固定地址推导规则(由钱包地址和 Mint 地址计算得出),方便用户管理不同代币

Token创建完整流程(基于spl-token-cli)

前置准备

  1. 安装工具

    # 安装Solana命令行工具
    sh -c "$(curl -sSfL https://release.solana.com/v1.18.4/install)"
    # 安装SPL Token命令行工具(锁定版本确保兼容性)
    cargo install spl-token-cli --version 2.0.0 --locked
  2. 初始化本地环境

    # 启动本地Solana测试节点(默认端口8899)
    solana-test-validator
    # 新建终端,配置集群为本地节点
    solana config set --url http://localhost:8899
  3. 创建测试钱包并获取空投(用于支付Gas费)

    # 创建新钱包(生成密钥对文件)
    solana-keygen new --outfile ~/my-wallet.json
    # 配置默认钱包
    solana config set --keypair ~/my-wallet.json
    # 获取测试网空投(本地节点无需真实代币)
    solana airdrop 10
    # 验证余额
    solana balance

核心步骤:创建并管理代币

1. 创建Mint账户(代币类型)

Mint账户是代币的"根",决定代币的基本属性:

 # 创建默认可替代代币(可铸币、可冻结,小数位6)
➜  ~ spl-token create-token
Creating token 3F14kaMXjdC1mFx5LRdD19amiMneKhgJsmMzGQUJjTt9 under program TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA

Address:  3F14kaMXjdC1mFx5LRdD19amiMneKhgJsmMzGQUJjTt9
Decimals:  9

Signature: 5RHsDWPbGkFs8Cuq5G8wRGwfKhgAYqAejLc5nGwLSoDSHxWNV3CmX6wpYy5yPjYWvPuZVqUwYXEMt9M3ByJTKzqM
---------------------------------------

 # 自定义参数示例:
 # 创建NFT(不可分割,小数位0,不可增发)
 spl-token create-token --decimals 0 --no-mint-authority --no-freeze-authority

 # 命令输出解析:
 # Creating token <MINT_ADDRESS>
 # Signature: <TRANSACTION_SIGNATURE>
 # 其中<MINT_ADDRESS>是新代币的唯一标识,需记录
 
 ---------------------------------
 ## 查看mint account info
 ➜  ~ spl-token account-info --address 3F14kaMXjdC1mFx5LRdD19amiMneKhgJsmMzGQUJjTt9

SPL Token Mint
  Address: 3F14kaMXjdC1mFx5LRdD19amiMneKhgJsmMzGQUJjTt9
  Program: TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA
  Supply: 0
  Decimals: 9
  Mint authority: FcKkQZRxD5P6JwGv58vGRAcX3CkjbX8oqFiygz6ohceU
  Freeze authority: (not set)

参数说明:

  • --decimals:代币小数位数(默认6,如USDC),NFT需设为0
  • --mint-authority:指定铸币权限账户(默认当前钱包),--no-mint-authority表示永久不可铸币
  • --freeze-authority:指定冻结权限账户(默认当前钱包),--no-freeze-authority表示永久不可冻结

2. 创建Token Account(代币持有账户)

用户需要关联Mint账户的Token Account才能接收代币,推荐使用ATA(自动关联钱包):

 # 创建与当前钱包关联的ATA(自动推导地址)
 spl-token create-account <MINT_ADDRESS>
 --------------------
 ➜  ~ spl-token create-account 3F14kaMXjdC1mFx5LRdD19amiMneKhgJsmMzGQUJjTt9
Creating account 7i8smGYKco3hicJThL8WYrMaGKpceeKkZRekqR4aWKFJ

Signature: 5AiPVz8Kjc9RYEtMGQAgx8Mdgy8cNiAwnprAHK14JYyciNJr1ufmPu3AQAwXbr5w1hRV1tTbiDDfEQz66yKkvxVy
----------------------

 # 手动指定所有者创建Token Account(非ATA)
 spl-token create-account <MINT_ADDRESS> <OWNER_WALLET_ADDRESS>
 
 ---------------------
➜  ~ spl-token create-account 3F14kaMXjdC1mFx5LRdD19amiMneKhgJsmMzGQUJjTt9 /Users/tinachan/.config/solana/t2.json
Creating account 2tQibfGH1UX4PEA1dNWJ8zvnpSbKRBr5a5eVhaRxF6EX

Signature: 4dvu4YNxgfbEAyGiBxYxDqGHdsEgamZ8MMEE8uNBdoGJWZg3UM4eGk3v4BsEMQADut7VeYx32Ng7p4r4zWL6CMaK
 ---------------------

 # 命令输出解析:
 # Creating account <TOKEN_ACCOUNT_ADDRESS>
 # Signature: <TRANSACTION_SIGNATURE>
 # <TOKEN_ACCOUNT_ADDRESS>为新创建的代币持有账户地址

代码中第一个创建的就是ATA,默认关联的token account; 第二个用私钥创建的是非ATA的token account ,两者区别:

  1. 地址生成方式不同
  • ATA(自动关联代币账户)
    地址是通过固定算法推导出来的,公式为:
    ATA地址 = 基于钱包地址 + Mint地址 + 代币程序ID 推导的唯一地址
    这种推导规则是 Solana 的官方标准,确保一个钱包(所有者)对一个 Mint 只能有唯一对应的 ATA
    例如:你的钱包地址为A,Mint 地址为M,那么对应的 ATA 地址是唯一确定的,任何人用AM推导都会得到同一个地址。
  • 非 ATA Token Account(手动指定所有者)
    地址是随机生成的,不遵循上述推导规则。每次执行create-account <MINT> <OWNER>命令,都会生成一个全新的随机地址,即使所有者和 Mint 相同,也会得到不同的地址。
  1. 与所有者的关联性不同
  • ATA
    强制与「创建时的钱包地址」绑定,即 ATA 的所有者(owner)就是该钱包地址,且无法修改
    一个钱包对一个 Mint 只能有1 个 ATA(因为地址唯一),这是钱包管理代币的「默认账户」。
  • 非 ATA Token Account
    所有者可以是任意地址(可以是你的钱包、其他用户的钱包,甚至是智能合约地址),且允许一个所有者对一个 Mint 创建多个非 ATA 账户(因为地址随机)。
    例如:你可以用自己的钱包作为所有者,为同一个 Mint 创建 10 个不同的非 ATA 账户,分别持有不同数量的代币。
  1. 钱包与 DApp 兼容性不同
  • ATA
    遵循 Solana 官方标准,所有主流钱包(如 Phantom、Solflare)和 DApp 都会自动识别并显示 ATA 中的代币,无需手动添加地址。
    例如:你在 Phantom 钱包中看到的某代币余额,实际就是你钱包对应的 ATA 中的余额。
  • 非 ATA Token Account
    不被钱包自动识别,需要用户手动添加账户地址才能在钱包中显示余额。
    大多数 DApp 也不会默认与非 ATA 交互,需要手动指定账户地址才能进行转账、交易等操作。
  1. 使用场景不同
  • ATA
    适合普通用户日常使用,用于接收、存储和管理代币,因为兼容性好、管理简单(一个 Mint 对应一个账户,不易混乱)。
    例如:别人向你转账某代币时,只需提供你的钱包地址,对方会自动向你的 ATA 转账(因为 ATA 地址可推导)。
  • 非 ATA Token Account
    适合特殊场景,例如:
    • 智能合约需要控制代币(将所有者设为合约地址);
    • 需将同一 Mint 的代币拆分到多个账户管理(如分账、隔离资金);
    • 临时账户(用完即弃)等。

总结来说,ATA 是「标准化、自动关联、易管理」的代币账户,适合大多数日常场景;非 ATA 是「灵活、自定义、需手动管理」的账户,适合特殊需求。实际开发或使用中,优先推荐使用 ATA,除非有明确的特殊场景需要非 ATA。

3. 铸币(增加代币供应量)

只有Mint账户的mint-authority有权限铸币:

 # 向指定Token Account铸币100单位(注意小数位,实际金额=数量*10^decimals)
 spl-token mint <MINT_ADDRESS> 100 <TOKEN_ACCOUNT_ADDRESS>

 # 示例:向当前钱包的ATA铸币1000(假设decimals=6,实际为1000 * 10^6 最小单位)
 spl-token mint <MINT_ADDRESS> 1000
 
 --------
 ➜  ~ spl-token mint 3F14kaMXjdC1mFx5LRdD19amiMneKhgJsmMzGQUJjTt9 100
Minting 100 tokens
  Token: 3F14kaMXjdC1mFx5LRdD19amiMneKhgJsmMzGQUJjTt9
  Recipient: 7i8smGYKco3hicJThL8WYrMaGKpceeKkZRekqR4aWKFJ

Signature: USQP7cDcCip1ePdgKDxEXobBm8ohtaVwDRmGFt2BmDyi3tRQMrxtbvMkXbrUcdkoSNuQ2X9k6u1NNbztHeYY97Y

 --------

 # 验证铸币结果
 spl-token balance <MINT_ADDRESS>
  --------
 ➜  ~ spl-token balance 3F14kaMXjdC1mFx5LRdD19amiMneKhgJsmMzGQUJjTt9
100
 --------

4. 代币转账

# 从当前钱包的ATA向目标钱包的ATA转账50单位
spl-token transfer <MINT_ADDRESS> 50 <RECIPIENT_WALLET_ADDRESS> --fund-recipient

# 参数说明:
# --fund-recipient:自动为接收者创建ATA(若不存在)并支付创建费用

5. 销毁代币(减少供应量)

代币持有者可销毁自己持有的代币:

# 销毁当前钱包ATA中的20单位代币
spl-token burn <TOKEN_ACCOUNT_ADDRESS> 20

6. 查看代币信息

# 查看Mint账户详情(总供应量、权限等)
spl-token mint-info <MINT_ADDRESS>

# 查看Token Account详情(余额、所有者等)
spl-token account-info <TOKEN_ACCOUNT_ADDRESS>

关键注意事项

  1. 权限管理:Mint账户的铸币/冻结权限默认归创建者,可通过spl-token authorize转移或撤销
  2. NFT特殊处理:必须设置--decimals 0,且通常只铸币1个单位(spl-token mint <MINT> 1
  3. 主网操作:切换集群为https://api.mainnet-beta.solana.com时,需使用真实SOL支付Gas费
  4. 地址记录:Mint地址是代币的唯一标识,需妥善保存(可通过solana address -k <MINT_KEYPAIR_FILE>查询)

通过以上步骤,即可完成从代币创建到转账销毁的全流程操作。实际开发中,可通过Solana Rust SDK或Web3.js调用Token Program的指令实现相同功能。