0

Can someone please help me understand why I'm getting this error? I'm trying to perform this automatic transaction through websocket the moment the account receives any funds. I'm pretty sure the feeInLamports is correct, because when I try manually and check the transaction in Solscan, 21000 lamports (0.000021 SOL) is showing as FEE. I event tried to increase the fee amount, but still showing the same error.

import WebSocket = require("ws");
import { Keypair, PublicKey, SystemProgram } from '@solana/web3.js';

const web3 = require('@solana/web3.js');
const ws = new WebSocket("wss://api.mainnet-beta.solana.com");

const WALLET_1_PRIVATE_KEY = Uint8Array.from([...]);
const receiverAccount = new PublicKey("...");
const privateKeyBuffer = Buffer.from(WALLET_1_PRIVATE_KEY);
const senderAccountKeyPair = Keypair.fromSecretKey(privateKeyBuffer);
const connection = new web3.Connection(web3.clusterApiUrl('mainnet-beta'));

async function commitTransaction() {
    await connection.getBalance(senderAccountKeyPair.publicKey).then((balance: any) => {
        let feeInLamports = 21000;
        let amountToSend = balance - feeInLamports;
        if (balance >= amountToSend && amountToSend > feeInLamports) {
            let transaction = new web3.Transaction().add(
                web3.SystemProgram.transfer({
                    fromPubkey: senderAccountKeyPair.publicKey,
                    toPubkey: receiverAccount,
                    lamports: amountToSend,
                    programId: SystemProgram.programId,
                })
            );
            console.log("[transaction] balance =", balance);
            console.log("[transaction] amountToSend =", amountToSend);

            async function sendTransactionWithRetry(transaction: any, signers: any, maxRetries = 5, delayMs = 1000) {
                let retries = 0;
                while (retries < maxRetries) {
                    try {
                        await web3.sendAndConfirmTransaction(
                            connection,
                            transaction,
                            signers
                        );
                        console.log("Transaction sent successfully.");
                    } catch (error) {
                        console.error(`Error sending transaction: ${error}`);
            
                        if (retries < maxRetries - 1) {
                            console.log(`Retrying transaction in ${delayMs} ms...`);
                            new Promise(resolve => setTimeout(resolve, delayMs));
                        }
                    }
                    retries++;
                }
                console.error("Max retries reached. Transaction failed.");
            }
            sendTransactionWithRetry(transaction, [senderAccountKeyPair]);


            
        } else {
            console.log('Insufficient balance for the transaction.')
        }
    })
}


function subscribeToAccount(ws: WebSocket, account: string){
    const requestData = {
        "jsonrpc": "2.0",
        "id": 135791,
        "method": "accountSubscribe",
        "params": [
            account.toString(),
            {
                "encoding": "jsonParsed",
                "commitment": "finalized"
            }
        ]
    };
    ws.send(JSON.stringify(requestData))
    console.log("Subcribed to account")
}

ws.addEventListener("open", () => {
    console.log("new connection!")
    subscribeToAccount(ws, senderAccountKeyPair.publicKey.toString());
    setInterval(() => {
        if (ws.readyState === WebSocket.OPEN) {
            subscribeToAccount(ws, senderAccountKeyPair.publicKey.toString())
        }
    }, 45000);
});

ws.onmessage = async (event) => {
    try {
        const data = JSON.parse(Buffer.from(event.data).toString('utf-8'));
        console.log('On message event data:', data);
        if (data && data.params && data.params.result && data.params.result.value && data.params.result.value.lamports) {
            // let balance = data.params.result.value.lamports;
            await commitTransaction()
        } else {
            console.log('Invalid or missing data in the WebSocket message.');
        }
    } catch (error) {
        console.error('Error parsing event data:', error);
    };
};

let reconnectInterval = 1000; // Initial reconnect interval in milliseconds
let maxReconnectAttempts = 5;
ws.onclose = () => {
    console.log('WebSocket connection closed.');
    if (maxReconnectAttempts > 0) {
        setTimeout(() => {
            subscribeToAccount(ws, senderAccountKeyPair.publicKey.toString());
            maxReconnectAttempts--;
            reconnectInterval *= 2; // Exponential backoff
        }, reconnectInterval);
    } else {
        console.log('Maximum reconnection attempts reached.');
    }
};

ws.onerror = (error) => {
    console.error('WebSocket error:', error);
};

1 Answer 1

2

So what's happening here is that one of your accounts ends up with a balance that is below 0.00089088 SOL and NOT zero. Then it doesn't have enough lamports for rent and you get this error.

I have a very detailed explanation of this issue here: https://youtu.be/kPQEm46uLuM?si=y5WIWHPrHxePIlnv&t=1611

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.