使用Python及solana.py、anchor.py发起Solana交易时如何打开钱包签名
Solana Python开发链上交易钱包签名实现方案
核心实现分三类场景,对应不同的签名逻辑,基于solana.py v0.30+、anchorpy v0.19+版本验证可用:
- 本地脚本/后端服务热钱包签名:适合自动化交易、链上脚本、服务端托管交易场景
- Anchor框架合约调用签名:基于anchor.py封装的Provider自动完成签名
- 对接用户端浏览器钱包签名:适合dApp场景,用户自主授权签名,服务端不接触私钥
1. solana.py原生本地钱包签名
这个场景不需要唤起任何钱包UI,直接从本地存储的私钥加载密钥对,本地完成签名后直接广播交易。
from solana.rpc.api import Client from solana.keypair import Keypair from solana.transaction import Transaction from solana.system_program import transfer, TransferParams from base58 import b58decode # 初始化RPC连接,主网用https://api.mainnet-beta.solana.com,测试网换devnet地址 client = Client("https://api.devnet.solana.com") # 加载钱包两种方式二选一即可 # 方式1:从数字数组格式私钥加载(Phantom等钱包导出的私钥默认是该格式) secret_key_arr = [21,43,55,...] # 替换为自己的私钥数组 sender = Keypair.from_secret_key(bytes(secret_key_arr)) # 方式2:从base58编码的私钥字符串加载 b58_secret = "你的base58格式私钥字符串" sender = Keypair.from_secret_key(b58decode(b58_secret)) # 构建测试交易:0.001 SOL转账 tx = Transaction() tx.add(transfer(TransferParams( from_pubkey=sender.pubkey(), to_pubkey="接收方钱包公钥", lamports=1_000_000 # 1 SOL = 10^9 lamports ))) # 传入签名者钱包,本地自动完成签名+广播 send_resp = client.send_transaction(tx, sender) print(f"交易哈希:{send_resp.value}")
2. anchor.py合约调用签名
anchor.py对签名流程做了封装,初始化Provider时绑定钱包实例,后续所有合约调用、交易发送都会自动完成签名,不需要手动调用签名方法。
import asyncio from solana.rpc.async_api import AsyncClient from solana.keypair import Keypair from base58 import b58decode from anchorpy import Provider, Wallet async def anchor_contract_call(): # 初始化异步RPC客户端 rpc_client = AsyncClient("https://api.devnet.solana.com") # 加载签名钱包,加载逻辑和solana.py完全一致 signer_wallet = Wallet(Keypair.from_secret_key(b58decode("你的私钥"))) # 初始化Provider,后续所有合约交互都通过该实例完成,自动签名 provider = Provider(rpc_client, signer_wallet) # 加载Anchor程序示例,后续调用合约方法时会自动签名发送 # program = await Program.at("你的合约ID", provider) # await program.rpc["合约方法名"](参数列表) asyncio.run(anchor_contract_call())
3. 对接Phantom/Solflare等用户端钱包签名
如果是开发面向普通用户的dApp,绝对不要收集用户私钥,签名流程必须在用户本地钱包侧完成,服务端只负责组装未签名交易:
def build_unsigned_tx(sender_pubkey: str, receiver_pubkey: str, amount_lamports: int): tx = Transaction() tx.add(transfer(TransferParams( from_pubkey=sender_pubkey, to_pubkey=receiver_pubkey, lamports=amount_lamports ))) # 补全交易必要的区块哈希、手续费支付人信息 blockhash_resp = client.get_latest_blockhash() tx.recent_blockhash = blockhash_resp.value.blockhash tx.fee_payer = sender_pubkey # 序列化未签名交易为十六进制字符串,返回给前端唤起钱包签名 return tx.serialize(None).hex()
前端拿到未签名交易后,通过钱包适配器唤起用户钱包弹窗,用户确认签名后,前端可以直接广播交易,也可以把签名后的交易传回服务端广播。
安全提示:私钥是钱包资产的唯一凭证,生产环境不要把私钥硬编码在代码中,建议存放在环境变量、加密密钥管理服务中,避免私钥泄露造成资产损失。
内容的提问来源于stack exchange,提问作者Kashif Manzoor
相关产品推荐
相关产品推荐

