Solana Rust+Anchor框架代币转账测试报错:toString未定义
Solana Anchor代币转账测试报错
TypeError: Cannot read property 'toString' of undefined解决方法 问题场景
使用Solana Rust程序结合Anchor框架开发代币转账功能,完成程序编写后执行测试用例时触发以下错误:
Is transfer!: TypeError: Cannot read property 'toString' of undefined at Transaction.partialSign (node_modules/@solana/web3.js/src/transaction/legacy.ts:642:36) at /opt/projects/demo/rust-demo/second/node_modules/@project-serum/anchor/src/provider.ts:142:10 at Array.forEach (<anonymous>) at AnchorProvider.sendAndConfirm (node_modules/@project-serum/anchor/src/provider.ts:141:21) at processTicksAndRejections (internal/process/task_queues.js:95:5) at MethodsBuilder.rpc [as _rpcFn] (node_modules/@project-serum/anchor/src/program/namespace/rpc.ts:29:16)
涉及代码如下:
Rust程序代码
use anchor_lang::prelude::*; use anchor_spl::token::{ Token, TokenAccount, Transfer, Mint, self }; pub fn transfer_sol(ctx:Context<TransferInfo>) -> Result<()>{ let amt: u64 = 1000000; msg!("Lamport: {}",amt); msg!("Starting Tokens: {}",ctx.accounts.sender.amount); let cpi_ctx = CpiContext::new( ctx.accounts.token_program.to_account_info(), Transfer{ from:ctx.accounts.sender.to_account_info(), to:ctx.accounts.receiver.to_account_info(), authority:ctx.accounts.authority.to_account_info(), } ); token::transfer(cpi_ctx,amt)?; ctx.accounts.sender.reload()?; Ok(()) } #[derive(Accounts)] pub struct TransferInfo<'info>{ #[account(mut)] pub sender: Box<Account<'info, TokenAccount>>, #[account(mut)] pub receiver: Box<Account<'info, TokenAccount>>, pub authority: Signer<'info>, pub mint: Box<Account<'info, Mint>>, pub token_program: Program<'info, Token>, }
测试代码(原错误版本)
it("Is transfer!", async () =>{ //let amount = new anchor.BN(1000000); //let amount = new anchor.web3.BN(LAMPORTS_PER_SOL); await program.methods.transfera() .accounts({ sender:provider.wallet.publicKey, receiver:receiver_token.publicKey, authority:provider.wallet.publicKey, mint: mint.publicKey, tokenProgram:TOKEN_PROGRAM_ID }) .signers([sender_token.publicKey]) .rpc(); let tokenbal = await provider.connection.getTokenAccountBalance(sender_token.publicKey); console.log("tokenbal ",tokenbal); let tokenbalm = await provider.connection.getTokenAccountBalance(receiver_token.publicKey); console.log("tokenbalm ",tokenbalm); });
错误原因
- 方法名不匹配:Rust程序中定义的转账函数是
transfer_sol,但测试代码中调用的是transfera(),Anchor无法找到对应方法,导致指令生成异常。 - Signers参数错误:
signers需要传入签名者的Keypair对象(包含私钥),但代码中传入的是公钥sender_token.publicKey,公钥没有签名所需的私钥属性,触发toString读取undefined的错误。 - Accounts参数错误:Rust程序中
sender定义为TokenAccount类型,对应代币账户地址,但测试代码中传入的是钱包公钥provider.wallet.publicKey,类型不匹配导致后续流程异常。
修正方案
修正后的测试代码
it("Is transfer!", async () =>{ // 调用正确的方法名transferSol(Anchor会把snake_case转为camelCase) await program.methods.transferSol() .accounts({ // sender替换为代币账户地址 sender: sender_token.publicKey, receiver: receiver_token.publicKey, authority: provider.wallet.publicKey, mint: mint.publicKey, tokenProgram: TOKEN_PROGRAM_ID }) // signers传入钱包的Keypair(authority是钱包,所以用钱包签名) .signers([provider.wallet.payer]) .rpc(); let tokenbal = await provider.connection.getTokenAccountBalance(sender_token.publicKey); console.log("tokenbal ",tokenbal); let tokenbalm = await provider.connection.getTokenAccountBalance(receiver_token.publicKey); console.log("tokenbalm ",tokenbalm); });
额外检查点
- 确保执行
anchor build生成最新IDL,保证测试代码调用的方法名和IDL中的一致(Anchor会自动将Rust的snake_case函数名转为camelCase,比如transfer_sol对应transferSol)。 - 确认
sender_token是已初始化的代币账户,且余额足够支付转账金额+手续费。 - 确认
authority(这里是钱包)是sender代币账户的授权签名者。
内容的提问来源于stack exchange,提问作者Chris Dean
相关产品推荐
相关产品推荐

