如何使用Node.js实现Solana密钥对保存及代币发送功能
Solana开发问题解决方案
1 公钥无法请求空投的修复
问题原因
connection.requestAirdrop方法要求第一个入参为solanaWeb3.PublicKey类型实例,你传入公钥字符串会触发类型校验错误。另外你代码里写的stringPK是控制台打印PublicKey对象时输出的内部结构内容,不是正确的公钥字符串:对PublicKey实例调用.toString()会返回标准base58编码的公钥字符串,格式为纯字母数字组合,没有_bn:这类前缀。
修复方法
如果要使用公钥字符串请求空投,先将字符串转为PublicKey实例:
// 正确获取公钥字符串 const correctPubKeyStr = wallet.publicKey.toString(); // 转为PublicKey实例后再调用空投接口 const airdropSignature = await connection.requestAirdrop( new solanaWeb3.PublicKey(correctPubKeyStr), solanaWeb3.LAMPORTS_PER_SOL );
2 密钥对安全保存方案
Keypair生成的secretKey为Uint8Array类型,直接调用toString()会得到逗号分隔的数字串,不适合存储,推荐两种存储方式:
- 方案1:存储私钥原始数组(适合服务端离线存储)
// 存储:转成JSON字符串存到文件/安全数据库 const secretKeyStr = JSON.stringify(Array.from(wallet.secretKey)); // 恢复:读取字符串转Uint8Array,生成Keypair实例 const restoredWallet = solanaWeb3.Keypair.fromSecretKey( new Uint8Array(JSON.parse(secretKeyStr)) );
- 方案2:存储助记词(适合面向用户的钱包场景)
配合bip39包生成12/24位助记词,用户可通过助记词恢复钱包,安全性更高:
import * as bip39 from 'bip39'; import { HDKey } from 'ed25519-hd-key'; // 生成助记词 const mnemonic = bip39.generateMnemonic(); // 从助记词生成密钥对 const seed = await bip39.mnemonicToSeed(mnemonic); const derivedSeed = HDKey.derivePath("m/44'/501'/0'/0'", seed.toString('hex')).key; const wallet = solanaWeb3.Keypair.fromSeed(derivedSeed);
注意:私钥/助记词属于敏感信息,禁止明文存储在前端、公开代码仓库,服务端存储需要做加密处理
3 SPL代币发送实现示例
使用@solana/spl-token包实现转账的核心代码如下:
const transferSignature = await splToken.transfer( connection, // 链连接实例 wallet, // 付款方密钥对 sourceTokenAccount, // 付款方代币账户地址 destTokenAccount, // 收款方代币账户地址 wallet.publicKey, // 代币账户所有者 1000000, // 转账数量,注意要乘上代币的小数位 ); // 确认交易 await connection.confirmTransaction(transferSignature);
修复后的完整可运行代码
const solanaWeb3 = require("@solana/web3.js"); const splToken = require("@solana/spl-token"); (async () => { // 连接到devnet集群 const connection = new solanaWeb3.Connection( solanaWeb3.clusterApiUrl("devnet"), "confirmed" ); // 生成密钥对 const wallet = solanaWeb3.Keypair.generate(); console.log("公钥:", wallet.publicKey.toString()); // 存储私钥 const saveSecretKey = JSON.stringify(Array.from(wallet.secretKey)); console.log("私钥可保存此值:", saveSecretKey); // 申请空投 const airdropSignature = await connection.requestAirdrop( wallet.publicKey, solanaWeb3.LAMPORTS_PER_SOL ); await connection.confirmTransaction(airdropSignature); // 查询账户信息 const accountInfo = await connection.getAccountInfo(wallet.publicKey); console.log("账户SOL余额:", accountInfo.lamports / solanaWeb3.LAMPORTS_PER_SOL); })();
内容的提问来源于stack exchange,提问作者graysonmcm
相关产品推荐
相关产品推荐

