Solana/SPL Token/铸造代币和查询代币余额
铸造代币和查询代币余额
您可以通过简单的代码为任意用户增发指定数量的代币余额. 注意: 只有代币的创建者有权限增发代币!
使用 spl_mint()
方法增发的代币数量需考虑小数位, 例如, 若 decimals=9, 则 1000000000 表示 1 个代币.
类似的, 使用 spl_balance()
方法查询您的代币余额时, 函数将返回一个数组: 数组第 0 位表示您拥有的代币数量, 第 1 位表示该代币的小数位.
import pxsol
ada = pxsol.wallet.Wallet(pxsol.core.PriKey.int_decode(1))
spl = pxsol.core.PubKey.base58_decode('2CMXJX8arHRsiiZadVheRLTd6uhP7DpbaJ9hRiRMSGcF')
ada.spl_mint(spl, ada.pubkey, 100000000 * 10 ** 9)
print(ada.spl_balance(spl)) # [100000000000000000, 9]
关联代币账户
与我们之前写的泰铢币程序一样, 您的代币实质上存储于一个 pda 账户里. 我们习惯称呼该账户为关联代币账户(associated token account, ata), 它是用于存储和管理用户持有 spl token 的特殊账户.
- 每个 ata 唯一对应于一个普通钱包账户和一个代币的地址.
- 由程序自动生成, 遵循确定性地址规则, 确保同一个钱包和代币组合始终生成相同的 ata 地址.
- 存储用户的代币余额, 并记录与该代币相关的操作(如转账, 增发, 销毁).
当您使用 pxsol 的 spl_mint()
方法增发代币时, 如果目标用户还没有 ata 账户, pxsol 会自动为其生成 ata 账户. 我们可以使用 rpc 查询 ata 账户数据, 获得返回数据如下.
import base64
import pxsol
ada = pxsol.wallet.Wallet(pxsol.core.PriKey.int_decode(1))
spl = pxsol.core.PubKey.base58_decode('2CMXJX8arHRsiiZadVheRLTd6uhP7DpbaJ9hRiRMSGcF')
ata = ada.spl_account(spl)
info = pxsol.rpc.get_account_info(ata.base58(), {})
data = base64.b64decode(info['data'][0])
print(data.hex())
返回数据总共长 170 个字节, 我们对其进行详细分析.
11c447d79a76ef38a896d72fe54b373bab14dcba868425645a1670180e656780 代币的地址
4cb5abf6ad79fbf5abbccafcc269d85cd2651ed4b885b5869f241aedf0a5ba29 用户的普通钱包地址
00008a5d78456301 余额, 小端序表示, 为 100000000 * 10 ** 9
00000000 是否设置代理地址 (delegate), 0=未设置
0000000000000000000000000000000000000000000000000000000000000000 代理地址
01 账户状态(0=未初始化, 1=已初始化, 2=冻结)
00000000 是否为原生代币, 0=非原生代币, 符合预期
0000000000000000 若为原生代币时, 记录其租赁豁免阈值
0000000000000000 委托金额
00000000 是否允许关闭帐户
0000000000000000000000000000000000000000000000000000000000000000 关闭帐户的权限拥有者地址
02 账户类型(0=未初始化, 1=铸造账户, 2=持仓账户)
0700 代币扩展(7=不可改变账户所有权)
0000 代币扩展(填充, 无实际意义)
您可以参考以下两个源代码链接, 这有助于您加深对 ata 账户的理解.
在多数情况下, 我们只会关注前三个字段, 也就是代币的地址, 用户的普通钱包地址以及余额.
习题
例: Bob 是否被允许铸造新代币? 请编写代码尝试.
答:
import pxsol
bob = pxsol.wallet.Wallet(pxsol.core.PriKey.int_decode(2))
spl = pxsol.core.PubKey.base58_decode('2CMXJX8arHRsiiZadVheRLTd6uhP7DpbaJ9hRiRMSGcF')
bob.spl_mint(spl, bob.pubkey, 100000000 * 10 ** 9)
# Exception: {
# 'code': -32002,
# 'message': 'Transaction simulation failed: Attempt to debit an account but found no record of a prior credit.',
# 'data': {
# 'accounts': None,
# 'err': 'AccountNotFound',
# 'innerInstructions': None,
# 'logs': [],
# 'replacementBlockhash': None,
# 'returnData': None,
# 'unitsConsumed': 0
# }
# }