@solana/web3.js、Durable Nonceを使ってSOLを送信したときに発生したエラー。
現象
ソースコードを実行すると以下のエラーが発生。
/Users/transaction-test/node_modules/@solana/web3.js/src/connection.ts:5920
throw new SendTransactionError(
^
SendTransactionError: failed to send transaction: Transaction simulation failed: Transaction results in an account (2) with insufficient funds for rent
at Connection.sendEncodedTransaction (/Users/transaction-test/node_modules/@solana/web3.js/src/connection.ts:5920:13)
at processTicksAndRejections (node:internal/process/task_queues:95:5)
at async Connection.sendRawTransaction (/Users/transaction-test/node_modules/@solana/web3.js/src/connection.ts:5879:20)
at async main (/Users/transaction-test/src/transferSolUsingMadMints.ts:105:39) {
logs: [
'Program 11111111111111111111111111111111 invoke [1]',
'Program 11111111111111111111111111111111 success',
'Program 11111111111111111111111111111111 invoke [1]',
'Program 11111111111111111111111111111111 success'
]
}
ソースコード:
// Lib
import * as dotenv from 'dotenv';
import * as bs58 from 'bs58';
// Solana
import {
Connection,
Keypair,
PublicKey,
SystemProgram,
Transaction,
LAMPORTS_PER_SOL,
} from '@solana/web3.js';
import { closeAccount } from '@solana/spl-token';
// Mad Mints
import { createNonceAccount } from 'mad-mints-packages';
import { getNonceAccount } from 'mad-mints-packages';
const main = async () => {
// ----------------------------------------------------
// Setup
// ----------------------------------------------------
dotenv.config();
const endpoint = process.env.ENDPOINT;
if (!endpoint) throw new Error('endpoint not found.');
const connection = new Connection(endpoint, 'confirmed');
const adminSecretKeyBase58 = process.env.PAYER_SECRET_KEY;
if (!adminSecretKeyBase58) throw new Error('adminSecretKeyBase58 not found.');
const payer = Keypair.fromSecretKey(bs58.decode(adminSecretKeyBase58));
// Taker
const takerPublicKey = new PublicKey(
'CJsPSQtV28CJiRt8XThuG5Ei1cX2fH5GcPoZYyM26gzm'
);
// ---------------------------------------------------
// Airdrop
// ---------------------------------------------------
let latestBlockhash = await connection.getLatestBlockhash();
const airdropSignature = await connection.requestAirdrop(
payer.publicKey,
LAMPORTS_PER_SOL
);
await connection.confirmTransaction({
blockhash: latestBlockhash.blockhash,
lastValidBlockHeight: latestBlockhash.lastValidBlockHeight,
signature: airdropSignature,
});
// ------------------------------------
// Create Nonce Account
// ------------------------------------
// Read None Account Auth Secret Key
const nonceAccountAuth = payer;
const nonceAccount = await createNonceAccount(
connection,
payer,
nonceAccountAuth.publicKey
);
if (!nonceAccount) throw Error('Nonce Account not found.');
console.log();
// ------------------------------------
// Get Nonce
// ------------------------------------
const nonceAccountInfo = await getNonceAccount(connection, nonceAccount);
if (!nonceAccountInfo) throw Error('Nonce Account not found.');
const nonce = nonceAccountInfo.nonce;
// ------------------------------------
// Create Instruction
// ------------------------------------
let tx = new Transaction();
// nonce advance must be the first insturction.
const nonceInstruction = SystemProgram.nonceAdvance({
noncePubkey: nonceAccount,
authorizedPubkey: nonceAccountAuth.publicKey,
});
tx.add(nonceInstruction);
const instructions = SystemProgram.transfer({
fromPubkey: payer.publicKey,
toPubkey: takerPublicKey,
lamports: LAMPORTS_PER_SOL * 0.00001,
});
tx.add(instructions);
// assign `nonce` as recentBlockhash.
tx.recentBlockhash = nonce;
tx.feePayer = payer.publicKey;
// ------------------------------------
// Sign and Send Transaction
// ------------------------------------
tx.sign(payer, nonceAccountAuth);
const signatureSendRawTransaction = await connection.sendRawTransaction(
tx.serialize()
);
console.log('signature =>', signatureSendRawTransaction);
};
main();
原因
SOLの受取先がSOL残高ゼロのため、Rent Feeがなくアカウント保持ができていないため。
対応
受取先にもSOL(Rent Fee分だけでよい)を残しておく。
(今回は、PayerしかAirdropしていなかったため、TakerのみAirdropすることで解決)
SolanaのRent Feeを計算することもできるが、面倒なのでだいたい 0.002 SOL をテストとして送信している。もしダメだったらもっと増やせばよい。