在尝试使用 Solana 区块链上的 Jupiter API 执行交换时,我遇到持续的“资金不足”错误,即使我已确认钱包有足够的余额。下面是我正在使用的脚本,它与 Jupiter 交换 API 集成以将 SOL 转换为 USDT。即使调整了余额阈值并确保有足够的资金来支付交易费用和租金豁免后,也会发生错误。钱包余额:0,09 SOL。交易规模:0,0001 SOL
环境:
Node.js
@solana/web3.js
@solana/spl-token
我将 SOL 余额增加到交易费用和租金豁免所需的阈值以上。 在Phantom钱包中手动确认可以用较小的余额完成兑换,不会出现错误。 检查并重新检查脚本中的帐户创建和余额验证逻辑。 尽管进行了这些调整,脚本仍无法执行交换而不会遇到“资金不足”错误。通过钱包手动交易不会遇到此问题。
程序错误:“指令 #4 失败 - 资金不足”程序 返回错误:自定义程序错误:0x1
quire('dotenv').config();
const fetch = require('cross-fetch');
const bs58 = require('bs58');
const {
Connection,
Keypair,
PublicKey,
VersionedTransaction,
LAMPORTS_PER_SOL,
sendAndConfirmTransaction
} = require('@solana/web3.js');
const RPC_ENDPOINT = 'https://api.mainnet-beta.solana.com';
const connection = new Connection(RPC_ENDPOINT, 'confirmed');
const payer = Keypair.fromSecretKey(bs58.decode(process.env.PRIVATE_KEY));
const { Token, TOKEN_PROGRAM_ID } = require('@solana/spl-token');
async function ensureTokenAccountExists(connection, payer, mintAddress) {
const mintPublicKey = new PublicKey(mintAddress);
const payerPublicKey = payer.publicKey;
// Check if the token account already exists
const tokenAccount = await Token.getAssociatedTokenAddress(
Token.ASSOCIATED_TOKEN_PROGRAM_ID,
TOKEN_PROGRAM_ID,
mintPublicKey,
payerPublicKey
);
let tokenAccountInfo = await connection.getAccountInfo(tokenAccount);
if (!tokenAccountInfo) {
console.log("Token account does not exist, creating one...");
const transaction = new Transaction().add(
Token.createAssociatedTokenAccountInstruction(
Token.ASSOCIATED_TOKEN_PROGRAM_ID,
TOKEN_PROGRAM_ID,
mintPublicKey,
tokenAccount,
payerPublicKey,
payerPublicKey
)
);
// Sign and send the transaction to create the token account
await sendAndConfirmTransaction(connection, transaction, [payer]);
} else {
console.log("Token account already exists.");
}
// Re-check the balance to ensure it covers rent exemption
const solBalance = await connection.getBalance(payerPublicKey);
const minimumRequiredBalance = LAMPORTS_PER_SOL * 0.1; // Increased threshold to 0.1 SOL
if (solBalance < minimumRequiredBalance) {
console.log("Insufficient SOL to cover transaction fees and rent. Please fund your account.");
throw new Error("Insufficient funds to proceed.");
}
}
async function getSwapQuote(inputMint, outputMint, amount, slippageBps = 50) {
const url = `https://quote-api.jup.ag/v6/quote?inputMint=${inputMint}&outputMint=${outputMint}&amount=${amount}&slippageBps=${slippageBps}`;
const response = await fetch(url);
if (!response.ok) throw new Error(`HTTP error! status: ${response.status}`);
return await response.json();
}
async function executeSwap(quoteResponse) {
console.log("Starting swap execution...");
const swapResponse = await fetch('https://quote-api.jup.ag/v6/swap', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
quoteResponse,
userPublicKey: payer.publicKey.toString(),
wrapAndUnwrapSol: false,
})
});
if (!swapResponse.ok) {
const responseBody = await swapResponse.text();
console.error(`HTTP error during swap! status: ${swapResponse.status}`);
console.error("Response body:", responseBody);
throw new Error(`HTTP error! status: ${swapResponse.status}`);
}
const responseData = await swapResponse.json();
if (responseData.error || !responseData.swapTransaction) {
throw new Error(`Failed to obtain swap transaction: ${responseData.error}`);
}
const transactionBuffer = Buffer.from(responseData.swapTransaction, 'base64');
const transaction = VersionedTransaction.deserialize(transactionBuffer);
transaction.recentBlockhash = (await connection.getRecentBlockhash()).blockhash;
transaction.sign([payer]);
console.log("Transaction details before sending:", JSON.stringify(transaction));
const txid = await connection.sendRawTransaction(transaction.serialize(), {
skipPreflight: true,
preflightCommitment: 'confirmed'
});
console.log(`Swap executed, transaction ID: ${txid}`);
}
(async () => {
try {
const inputMint = 'So11111111111111111111111111111111111111112'; // SOL
const outputMint = 'Es9vMFrzaCERmJfrF4H2FYD4KCoNkY11McCe8BenwNYB'; // USDT
const amount = 0.0001 * LAMPORTS_PER_SOL;
console.log(`Attempting to swap ${amount / LAMPORTS_PER_SOL} SOL to USDT...`);
const quoteResponse = await getSwapQuote(inputMint, outputMint, amount);
console.log("Quote response:", JSON.stringify(quoteResponse, null, 2));
if (!quoteResponse.error) {
await executeSwap(quoteResponse);
} else {
console.error('Failed to get a swap quote:', quoteResponse.error);
}
} catch (error) {
console.error('An error occurred:', error);
}
})();
当我运行脚本时,这是我收到的输出:
Attempting to swap 0.0001 SOL to USDT...
Quote response: {
"inputMint": "So11111111111111111111111111111111111111112",
"inAmount": "100000",
"outputMint": "Es9vMFrzaCERmJfrF4H2FYD4KCoNkY11McCe8BenwNYB",
"outAmount": "14644",
"otherAmountThreshold": "14571",
"swapMode": "ExactIn",
"slippageBps": 50,
"platformFee": null,
"priceImpactPct": "0",
"routePlan": [
{
"swapInfo": {
"ammKey": "Bev3s1WZtmvfSspWmkpfvaBz2vCB3ckqm5SLVtVJiDPF",
"label": "Raydium CLMM",
"inputMint": "So11111111111111111111111111111111111111112",
"outputMint": "7dHbWXmci3dT8UFYWYZweBLXgycu7Y3iL6trKn1Y7ARj",
"inAmount": "100000",
"outAmount": "84914",
"feeAmount": "9",
"feeMint": "So11111111111111111111111111111111111111112"
},
...
}
],
"contextSlot": 261029705,
"timeTaken": 0.006935252
}
Starting swap execution...
Transaction details before sending: {"signatures": [{"0":243,"1":85,...},{"message": {"header":...
Swap executed, transaction ID:
我遇到过类似的问题,我发现问题是在转换为字符串时有时该值不准确。
body: JSON.stringify({quoteResponse, userPublicKey: payer.publicKey.toString(), wrapAndUnwrapSol: false})
您使用的这一行可能会在转换 quoteResponse 的值时引起问题。
您还将wrapAndUnwrapSol 设置为false。这意味着对于交换,它需要 wSOL(Wrapped SOL)已存在于您的钱包中。钱包还需要定期 SOL 来支付交易费用。 您确定钱包里有 wSOL 吗?如果不是,只需将wrapAndUnwrapSol 条件更改为true。