如何在Solana单元测试中创建代币/NFT并解决requestAirdrop失败问题
问题分析与修复方案
你的代码逻辑本身没问题,但依赖公共Devnet节点进行Anchor单元测试的方式不合理,这是导致requestAirdrop偶发失败的核心原因——公共测试网存在节点速率限制、网络拥堵等不可控因素,无法保证单元测试的稳定性。
修复方案
1. 改用Anchor本地测试网(推荐)
Anchor测试框架默认会启动本地Solana私有节点,完全避免公共网络的不稳定问题,同时本地节点无速率限制、交易确认更快,是单元测试的最优选择。
修改后的测试代码示例:
import * as anchor from "@coral-xyz/anchor"; import * as splToken from "@solana/spl-token"; describe("TokenTransferTest", () => { // 初始化Anchor Provider,自动使用本地测试网连接 anchor.setProvider(anchor.AnchorProvider.env()); const connection = anchor.getProvider().connection; const myKeypair = anchor.web3.Keypair.generate(); // 测试前给测试账户打SOL before(async () => { const airdropSig = await connection.requestAirdrop( myKeypair.publicKey, 2 * anchor.web3.LAMPORTS_PER_SOL ); // 使用finalized确认级别,确保交易完全上链 await connection.confirmTransaction(airdropSig, "finalized"); }); it("Creates mint and tests transfer", async () => { // 创建代币Mint,无需手动生成Mint Keypair,createMint会自动处理 const mint = await splToken.createMint( connection, myKeypair, myKeypair.publicKey, null, 1, undefined, null, splToken.TOKEN_PROGRAM_ID ); // 后续添加转账测试逻辑... }); });
2. 若必须使用Devnet,优化Airdrop重试逻辑
如果因特殊需求必须依赖Devnet,需要增加重试机制和严格的交易确认逻辑,以应对公共节点的不稳定:
// 带重试的Airdrop工具函数 async function requestAirdropWithRetry( connection: anchor.web3.Connection, pubkey: anchor.web3.PublicKey, amount: number, maxRetries: number = 3 ): Promise<string> { for (let i = 0; i < maxRetries; i++) { try { const signature = await connection.requestAirdrop(pubkey, amount); // 等待交易最终确认 await connection.confirmTransaction(signature, "finalized"); return signature; } catch (err) { console.log(`Airdrop失败,重试中(${i+1}/${maxRetries})`, err); await new Promise(resolve => setTimeout(resolve, 1000)); // 重试前等待1秒 } } throw new Error("多次重试后仍无法完成Airdrop"); } // 使用方式 const fromAirdropSignature = await requestAirdropWithRetry( connection, myKeypair.publicKey, 2 * anchor.web3.LAMPORTS_PER_SOL );
额外优化点
createMint方法无需手动传入web3.Keypair.generate()作为Mint的密钥对,传undefined即可让方法自动生成,简化代码。
内容的提问来源于stack exchange,提问作者marethyu
相关产品推荐
相关产品推荐

