如何用Python的solana.py实现自定义Solana代币转账?
Solana自定义代币转账(Python实现)及关键参数说明
一、代币转账核心流程
使用Python的solana.py和spl-token库完成自定义代币转账,核心是构造TransferChecked指令并签名发送交易,步骤如下:
- 准备转账所需的所有关键参数(下文详细说明含义与获取方式)
- 导入对应库与工具类
- 构造转账交易(如需自动创建接收方代币账户可补充对应指令)
- 连接Solana节点并发送签名后的交易
二、关键参数含义与获取方式
以下是你提到的核心参数的定义及获取途径:
1. Mint地址(mint_public_id)
- 含义:每个Solana代币的唯一标识,相当于代币的"身份证"。所有同类型代币绑定同一个Mint地址,它定义了代币的总供应量、小数位数等核心属性。
- 获取方式:
- 从代币项目官网、Dapp或钱包(如Phantom)的代币详情页复制
- 通过Solana区块浏览器搜索代币名称,找到对应的Mint地址
2. 代币账户地址(from_token_account / to_token_account)
- 含义:Solana上的代币并非直接存于钱包地址,而是存于代币账户中——每个钱包地址针对某一Mint代币,会有专属的代币账户(也可存在多个),用于存储该代币的余额。
- 获取方式:
- 转出方代币账户:调用Solana RPC的
get_token_accounts_by_owner方法,传入你的钱包地址和目标代币Mint地址,即可获取对应代币账户地址 - 转入方代币账户:
- 若接收方已持有过该代币,同样用
get_token_accounts_by_owner查询 - 若接收方从未持有该代币,可通过
spl.token库的create_associated_token_account指令自动创建(建议提前创建,避免因无对应账户导致转账失败)
- 若接收方已持有过该代币,同样用
- 转出方代币账户:调用Solana RPC的
3. 钱包地址(from_wallet_address)
- 含义:你的Solana钱包公钥,是对应代币账户的所有者,只有持有该钱包私钥的用户才能操作对应的代币账户。
- 获取方式:从钱包(如Phantom)导出公钥,或从本地
id.json文件中提取公钥字段
4. 钱包私钥(SECRET_KEY)
- 含义:对应钱包地址的私钥,用于签署交易,证明你有权限操作该钱包下的代币账户。
- 获取方式:从钱包导出私钥(务必严格保密,绝不泄露),或从本地
id.json文件中读取私钥数组
三、代码解析与可运行示例
你提供的代码已具备基础框架,以下是补充完善后的带注释版本:
from spl.token.constants import TOKEN_PROGRAM_ID from spl.token.instructions import transfer_checked, TransferCheckedParams, create_associated_token_account, CreateAssociatedTokenAccountParams from spl.token.core import get_associated_token_address from solana.rpc.commitment import Confirmed from solana.rpc.api import Client from solana.rpc.types import TxOpts from solana.keypair import Keypair from solana.publickey import PublicKey from solana.transaction import Transaction # -------------------------- 替换为你的实际参数 -------------------------- # 转出方钱包私钥(从id.json或钱包导出) SECRET_KEY = bytes([43,124,...,3,226,229,189]) # 转出方钱包公钥 from_wallet_address = PublicKey("rjPKeL...wedQp") # 目标代币的Mint地址 mint_public_id = PublicKey("4qYnL....Pt4taGk") # 转入方钱包公钥 to_wallet_address = PublicKey("xxx...xxx") # 转账数量(需乘以代币小数位数,如9位小数则1个代币填10**9) transfer_amount = 1 * 10**9 # 代币小数位数(从Mint地址元数据获取,多数代币为9位) decimals = 9 # Solana节点地址(主网用"https://api.mainnet-beta.solana.com") endpoint = "https://api.devnet.solana.com" # --------------------------------------------------------------------- # 初始化Solana客户端 client = Client(endpoint=endpoint, commitment=Confirmed) # 转出方Keypair(用于签名交易) owner = Keypair.from_secret_key(SECRET_KEY) # 获取转出方的关联代币账户地址 from_token_account = get_associated_token_address(from_wallet_address, mint_public_id) # 获取转入方的关联代币账户地址 to_token_account = get_associated_token_address(to_wallet_address, mint_public_id) transaction = Transaction() # 检查转入方是否存在对应代币账户,不存在则创建 to_token_account_info = client.get_account_info(to_token_account) if not to_token_account_info['result']['value']: transaction.add( create_associated_token_account( CreateAssociatedTokenAccountParams( payer=from_wallet_address, owner=to_wallet_address, mint=mint_public_id, program_id=TOKEN_PROGRAM_ID ) ) ) # 添加转账指令 transaction.add( transfer_checked( TransferCheckedParams( program_id=TOKEN_PROGRAM_ID, source=from_token_account, # 转出代币账户地址 mint=mint_public_id, # 代币Mint地址 dest=to_token_account, # 转入代币账户地址 owner=from_wallet_address, # 转出方钱包地址(代币账户所有者) amount=transfer_amount, # 转账数量(已处理小数位数) decimals=decimals, # 代币小数位数 signers=[] # 额外签名者(一般留空) ) ) ) # 发送交易并等待确认 response = client.send_transaction( transaction, owner, opts=TxOpts(skip_confirmation=False, preflight_commitment=Confirmed) ) print(f"交易已发送,签名:{response['result']}")
代码关键注意点:
- 小数位数处理:转账数量必须乘以代币的小数位数,否则实际转出金额会远小于预期(如9位小数代币,输入1则实际转出0.000000001个代币)
- 手续费保障:转出方钱包必须持有足够的SOL,用于支付交易手续费
- 网络切换:测试使用devnet节点,主网需替换为正式节点地址
内容的提问来源于stack exchange,提问作者Rudra Lakhani
相关产品推荐
相关产品推荐

