使用@solana-labs/web3.js发送USDC时无法获取钱包签名器报错
Solana使用钱包适配器发送USDC报错解决
你遇到的报错信息如下:
Argument of type 'WalletAdapter' is not assignable to parameter of type 'Signer'. Property 'secretKey' is missing in type 'WalletAdapter' but required in type 'Signer'.
报错原因
旧版@solana/spl-token的Token类构造函数要求传入的签名器必须包含secretKey私钥属性,而浏览器钱包适配器(如Phantom、Solflare等)出于安全设计不会暴露用户私钥,因此不可能拿到符合要求的Signer实例,你原来的代码写法只适用于服务端持有私钥的签名场景,不适合前端接入用户钱包的场景。
修正方案
不用实例化Token类,直接构造转账交易,调用钱包提供的签名方法完成签名即可,参考代码如下:
import { Connection, PublicKey, Transaction, clusterApiUrl } from '@solana/web3.js'; import { getAssociatedTokenAddress, createTransferCheckedInstruction, createAssociatedTokenAccountInstruction, TOKEN_PROGRAM_ID } from '@solana/spl-token'; const connection = new Connection(clusterApiUrl("devnet")); // 注意:此处为Solana主网USDC铸币地址,devnet测试请替换为对应测试币地址 const USDC_MINT = new PublicKey("EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v"); const USDC_DECIMALS = 6; // USDC固定为6位小数 async function sendUSDC(toAddress, amount) { const toPubkey = new PublicKey(toAddress); // 1. 获取发送方USDC关联代币账户地址 const fromTokenAccount = await getAssociatedTokenAddress( USDC_MINT, wallet.publicKey ); // 2. 获取接收方USDC关联代币账户地址 const toTokenAccount = await getAssociatedTokenAddress( USDC_MINT, toPubkey ); const transaction = new Transaction(); // 3. 若接收方无对应USDC账户,先添加创建账户指令 const toAccountInfo = await connection.getAccountInfo(toTokenAccount); if (!toAccountInfo) { transaction.add( createAssociatedTokenAccountInstruction( wallet.publicKey, toTokenAccount, toPubkey, USDC_MINT ) ); } // 4. 添加USDC转账指令 transaction.add( createTransferCheckedInstruction( fromTokenAccount, USDC_MINT, toTokenAccount, wallet.publicKey, amount * Math.pow(10, USDC_DECIMALS), // 金额需换算为最小单位 USDC_DECIMALS ) ); // 5. 补充交易必填参数 const latestBlockhash = await connection.getLatestBlockhash(); transaction.recentBlockhash = latestBlockhash.blockhash; transaction.feePayer = wallet.publicKey; // 6. 调用钱包签名并发送交易 const signedTx = await wallet.signTransaction(transaction); const txId = await connection.sendRawTransaction(signedTx.serialize()); await connection.confirmTransaction(txId); return txId; }
注意事项
- 测试环境下请替换为devnet对应的USDC测试币铸币地址,使用主网地址在devnet环境会报错
- 转账金额需要乘以USDC的小数位(6位),比如转1枚USDC对应的数值为
1000000 - 确保钱包已授权连接,且
wallet实例已正常获取到用户公钥
内容的提问来源于stack exchange,提问作者Drey Sven
相关产品推荐
相关产品推荐

