Solana转账故障求助:transfer方法无法创建指令
问题:Solana钱包转账失败,SystemProgram.transfer无法生成指令
问题描述
完全按照Solana官方JavaScript API文档编写钱包转账代码,但功能无法正常运行,核心问题是SystemProgram.transfer方法无法创建交易指令,尝试多种方法仍未解决,附上相关代码及报错位置。
我的代码
async function transfer() { const provider = await IsConnected(); console.log(provider.publicKey.toString()); const connection = new solanaWeb3.Connection( "https://api.devnet.solana.com", "confirmed" ); var recieverWallet = new solanaWeb3.PublicKey( "3uePV7kJcT3w5qMLPTHVAdLc72SF2iDRwNcxDE713EMf" ); // var airdropSignature = await connection.requestAirdrop( // provider.publicKey, // solanaWeb3.LAMPORTS_PER_SOL * 0.4 // ); // await connection // .confirmTransaction(airdropSignature) // .then(console.log("Airdropped")); var transaction = new solanaWeb3.Transaction(); transaction.feePayer = await provider.publicKey; let blockhashObj = await connection.getRecentBlockhash(); transaction.recentBlockhash = await blockhashObj.blockhash; transaction.add( await solanaWeb3.SystemProgram.transfer({ fromPubkey: provider.publicKey, toPubkey: recieverWallet, lamports: 10000, }) ); if (transaction) { console.log("Txn created successfully"); } let signed = await provider.signTransaction(transaction).serialize(); let signature = await connection.sendRawTransaction(signed); console.log(signature); let bConfirmed = await connection.confirmTransaction(signature); console.log(bConfirmed); }
报错位置代码
static transfer( params: TransferParams | TransferWithSeedParams, ): TransactionInstruction { let data; let keys; if ('basePubkey' in params) { const type = SYSTEM_INSTRUCTION_LAYOUTS.TransferWithSeed; data = encodeData(type, { lamports: BigInt(params.lamports), seed: params.seed, programId: toBuffer(params.programId.toBuffer()), }); keys = [ {pubkey: params.fromPubkey, isSigner: false, isWritable: true}, {pubkey: params.basePubkey, isSigner: true, isWritable: false}, {pubkey: params.toPubkey, isSigner: false, isWritable: true}, ]; } else { const type = SYSTEM_INSTRUCTION_LAYOUTS.Transfer; // ***报错位置 ->*** data = encodeData(type, {lamports: BigInt(params.lamports)}); keys = [ {pubkey: params.fromPubkey, isSigner: true, isWritable: true}, {pubkey: params.toPubkey, isSigner: false, isWritable: true}, ]; } return new TransactionInstruction({ keys, programId: this.programId, data, }); } export function encodeData<TInputData extends IInstructionInputData>( type: InstructionType<TInputData>, fields?: any, ): Buffer { const allocLength = type.layout.span >= 0 ? type.layout.span : Layout.getAlloc(type, fields); const data = Buffer.alloc(allocLength); const layoutFields = Object.assign({instruction: type.index}, fields); type.layout.encode(layoutFields, data); return data; } encode(src, b, offset = 0) { const firstOffset = offset; let lastOffset = 0; let lastWrote = 0; for (const fd of this.fields) { let span = fd.span; lastWrote = (0 < span) ? span : 0; if (undefined !== fd.property) { const fv = src[fd.property]; if (undefined !== fv) { lastWrote = fd.encode(fv, b, offset); if (0 > span) { /* Read the as-encoded span, which is not necessarily the * same as what we wrote. */ span = fd.getSpan(b, offset); } } } lastOffset = offset; offset += span; } const bigInt = (length: number) => (property?: string): Layout<bigint> => { const layout = blob(length, property); const {encode, decode} = encodeDecode(layout); const bigIntLayout = layout as Layout<unknown> as Layout<bigint>; bigIntLayout.decode = (buffer: Buffer, offset: number) => { const src = decode(buffer, offset); return toBigIntLE(Buffer.from(src)); }; bigIntLayout.encode = (bigInt: bigint, buffer: Buffer, offset: number) => { const src = toBufferLE(bigInt, length); return encode(src, buffer, offset); }; return bigIntLayout; }; function toBufferLE(num, width) { { const hex = num.toString(16); const buffer = Buffer.from(hex.padStart(width * 2, '0').slice(0, width * 2), 'hex'); buffer.reverse(); return buffer; } // Allocation is done here, since it is slower using napi in C return converter.fromBigInt(num, Buffer.allocUnsafe(width), false); } exports.toBufferLE = toBufferLE;
修复建议
移除不必要的await:
provider.publicKey、blockhashObj.blockhash、SystemProgram.transfer()都是同步操作,无需异步等待,修改后代码如下:transaction.feePayer = provider.publicKey; transaction.recentBlockhash = blockhashObj.blockhash; transaction.add( solanaWeb3.SystemProgram.transfer({ fromPubkey: provider.publicKey, toPubkey: recieverWallet, lamports: 10000, }) );修正签名步骤:
signTransaction返回Promise,需先await拿到签名后的交易再序列化:let signedTx = await provider.signTransaction(transaction); let signed = signedTx.serialize();更新依赖版本:确保
@solana/web3.js为最新稳定版,旧版本可能存在BigInt编码或指令布局的兼容性问题。添加错误捕获:在交易流程中加入try/catch,打印具体错误信息辅助定位:
try { // 交易创建、签名、发送逻辑 } catch (err) { console.error("交易失败详情:", err); }
内容的提问来源于stack exchange,提问作者pidor ads243
相关产品推荐
相关产品推荐

