1

I just got started with Solana so please be gentle :)

I'm trying to extract information from a transaction in order to perform subsequent processing. I'm using @solana/web3.js with connection.getBlock to query a block and I can extract the information I need.

However the problem is that I want to extract this information as soon as the transaction has been finalized. I was under the impression that I could just listen for changes to a certain account using connection.onAccountChange and then using information from the callback to query the transaction. However the event provides me with a slot which seems to be 1 or 2 integer values lower than the block in which the transaction is finalized.

I thought that changing the commitment level to finalized on the connection and in the getBlock call would do the job, but this just gives me a wrong block.

The code I just is:

const connection = new web3.Connection(web3.clusterApiUrl('mainnet-beta'), 'finalized');
const sub = createSubscription = connection.onAccountChange(
    pubkey,
    async (accountInfo, context) => {
        const blockConfig = {
            maxSupportedTransactionVersion: 1, 
            transactionDetails: 'full', 
            rewards: false,
            commitment: 'finalized'
        };
        const block = await connection.getBlock(context.slot, blockConfig);
        // block is not null, it just doesn't contain my transaction. If I look on-chain
        // the transaction is actually in block# -> context.slot+1 or context.slot+2 
    }, 
    {
        'commitment': 'finalized'
    }
);

Is there some built-in way to do what I'm trying to achieve? Basically get the block that contains the finalized transaction that triggered onAccountChange?

1 Answer 1

3

You can try this. I just modified your code

const connection = new web3.Connection(web3.clusterApiUrl('mainnet-beta'), 'finalized');

const sub = connection.onAccountChange( pubkey, async (accountInfo, context) => { let block = null; const blockConfig = { maxSupportedTransactionVersion: 1, transactionDetails: 'full', rewards: false, commitment: 'finalized' };

    // Try getting the block in the current slot, and if not found, check the next two slots
    for (let i = 0; i < 3; i++) {
        block = await connection.getBlock(context.slot + i, blockConfig);
        if (block && block.transactions && block.transactions.length > 0) {
            // Check if the block contains your transaction
            const transactionFound = block.transactions.find(tx => {
                // Add your logic to find the specific transaction
                // For example, by checking tx.transaction.signatures or other criteria
                return tx.transaction.signatures.includes("your-transaction-signature");
            });

            if (transactionFound) {
                console.log("Transaction found in block:", context.slot + i);
                break;
            }
        }
    }

    if (!block) {
        console.error("Transaction not found in expected slots");
    }
}, 
{ commitment: 'finalized' }

);

Using getConfirmedSignaturesForAddress2 allows you to get the signatures of confirmed transactions affecting a specific account and then retrieve the transaction details using those signatures.

You can read more about this here => https://solana-labs.github.io/solana-web3.js/

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.