Solana web3.js交互脚本未返回transactionSignature问题求助
问题分析与解决
核心问题1:异步函数未等待导致日志丢失
你的main函数中调用pingProgram时没有添加await,主线程会直接跳过异步操作执行后续的then块并退出程序,导致pingProgram里的交易签名日志根本没机会打印。
核心问题2:交易Blockhash的时机问题
Web3.Transaction实例创建时不会自动包含blockhash,sendAndConfirmTransaction方法内部会自动获取最新blockhash并填充到交易中。所以在调用该方法前打印transaction,自然看不到blockhash信息。如果需要在发送前查看,可以显式获取并赋值。
修改后的代码
/* What this program will do? Our client will ping a counter program, which will increment a counter. I'm going to tell everyone on the network that I'm a builder */ // I'm adding these import * as Web3 from '@solana/web3.js'; import * as fs from 'fs'; // for file handling import dotenv from 'dotenv'; dotenv.config(); // WE NEED TO KNOW WHAT ACCOUNTS THESE INSTRUCTIONS ARE DEALING WITH, THESE ARE 2 DUMMY ACCOUNTS const PROGRAM_ID = new Web3.PublicKey("ChT1B39WKLS8qUrkLvFDXMhEJ4F1XZzwUNHUt4AU9aVa") const PROGRAM_DATA_PUBLIC_KEY = new Web3.PublicKey("Ah9K7dQ8EHaZqcAsgBW8w37yN2eAy3koFmUn4x3CJtod") async function initializeKeypair(connection : Web3.Connection): Promise<Web3.Keypair> { if(!process.env.PRIVATE_KEY) { console.log("Generating secret key...🗝️"); const signer = Web3.Keypair.generate(); console.log("Creating .env file..."); fs.writeFileSync('.env', `PRIVATE_KEY=[${signer.secretKey.toString()}]`); return signer; } const secret = JSON.parse(process.env.PRIVATE_KEY ?? '') as number[]; const secretKey = Uint8Array.from(secret); const keypairFromSecret = Web3.Keypair.fromSecretKey(secretKey); // When creating it from the secret key await airdropSolIfNeeded(keypairFromSecret, connection); return keypairFromSecret; } async function airdropSolIfNeeded(signer : Web3.Keypair, connection : Web3.Connection) { const balance = await connection.getBalance(signer.publicKey); console.log('Current balance is ', balance / Web3.LAMPORTS_PER_SOL, 'SOL'); //1 SOL is enough for anything we do if(balance / Web3.LAMPORTS_PER_SOL < 1) { // We can only get up to 2 SOL per request console.log("Airdropping 1 SOL..."); const airdropSignature = await connection.requestAirdrop(signer.publicKey, Web3.LAMPORTS_PER_SOL); const latestBlockhash = await connection.getLatestBlockhash(); await connection.confirmTransaction({ blockhash : latestBlockhash.blockhash, lastValidBlockHeight : latestBlockhash.lastValidBlockHeight, signature : airdropSignature, }); const newBalance = await connection.getBalance(signer.publicKey); console.log('The new balance is ', newBalance / Web3.LAMPORTS_PER_SOL, 'SOL'); } } async function pingProgram(connection : Web3.Connection, payer : Web3.Keypair) { const transaction = new Web3.Transaction(); // 1. WE MAKE A TRANSACTION const instruction = new Web3.TransactionInstruction({ // 2. WE MAKE AN INSTRUCTION // Instructions need 3 things // (i) The public keys of all the accounts the instruction will read/write keys : [ { pubkey : PROGRAM_DATA_PUBLIC_KEY, isSigner : false, isWritable : true } ], // (ii) The ID of the program this instruction will be sent to programId : PROGRAM_ID // (iii) Data - in this case, there's none! }); transaction.add(instruction); // 3. WE ADD THIS INSTRUCTION TO THE TRANSACTION // 可选:手动获取并设置blockhash,打印时即可看到 const latestBlockhash = await connection.getLatestBlockhash(); transaction.recentBlockhash = latestBlockhash.blockhash; transaction.lastValidBlockHeight = latestBlockhash.lastValidBlockHeight; transaction.feePayer = payer.publicKey; console.log(transaction) const transactionSignature = await Web3.sendAndConfirmTransaction(connection, transaction, [payer]); // 4. WE SEND THE TRANSACTION TO THE NETWORK console.log(transactionSignature) console.log(`Transaction https://explore.solana.com/tx/${transactionSignature}?cluster=devnet`); } async function main() { const connection = new Web3.Connection(Web3.clusterApiUrl('devnet')); const signer = await initializeKeypair(connection); console.log('Public Key : ', signer.publicKey.toBase58()); // Solana Public keys are Base58 alphanumeric characters // 添加await,等待pingProgram执行完成 await pingProgram(connection, signer); } main() .then(() => { console.log("Finished successfully") process.exit(0) }) .catch((error) => { console.log(error) process.exit(1) })
关键修改点
- 在
main函数中调用pingProgram时添加await,确保程序等待交易流程完成再退出。 - (可选)在
pingProgram中手动设置交易的recentBlockhash、lastValidBlockHeight和feePayer,提前打印transaction就能看到blockhash信息。
内容的提问来源于stack exchange,提问作者m1k3_0xm0L
相关产品推荐
相关产品推荐

