Here is an article on the issue you’re experiencing with parsing transactions on the Solana blockchain using web3.js:
Title: Solana Web3.js: ParsedTransaction Returning Null despite Logs Being Available
Introduction
As a developer building applications on the Solana blockchain, parsing transaction details is crucial for understanding program conditions and triggering custom logic. However, in this article, we’ll investigate an issue that arises when trying to access parsed transactions using web3.js on a certain account.
The Issue: ParsedTransaction Returning Null
We’ve written a script that listens to Solana logs on a specific public key. The code is designed to parse the transaction details whenever a program condition is met:
const solana = require("solana-web3");
const connection = new solana.Connection();
connection.onLogs(publicKey, (result) => {
const parsedTransaction = result.parsedTransactions;
console.log(parsedTransaction);
});
After setting up the script and connecting to the Solana network, we’re expecting to see the transaction details in the parsedTransactions
array. However, when we log the output of this code, we notice that it’s returning an empty object:
{
"error": null,
"info": null,
"status": null,
"result": {
"transactions": []
}
}
What Went Wrong?
In Solana, when you fetch transactions using connection.getEntry
, the result is a Web3Transaction
object. However, in this case, we’re not explicitly fetching these transactions. Instead, we’re relying on the parsedTransactions
array provided by web3.js.
The issue arises because the getEntry
method doesn’t guarantee that all transaction entries will be returned when using result.parsedTransactions
. In fact, if the program condition is met and there are no matching transactions, result.parsedTransactions
will return an empty array ([]
). The code we wrote assumes that this array is always non-empty.
Solving the Issue
To fix this issue, you can use a different approach to parse transaction details. One way to do this is by fetching all transactions and then filtering out those that don’t match your condition:
const solana = require("solana-web3");
const connection = new solana.Connection();
connection.onLogs(publicKey, (result) => {
const parsedTransactions = result.parsedTransactions;
if (!parsedTransactions.length) return; // Ignore empty arrays
const matchingTransactions = parsedTransactions.filter((transaction) => {
// Implement your program condition here
if (/ your condition /) {
return true;
}
return false;
});
console.log(matchingTransactions);
});
Alternatively, you can use the getEntries
method to fetch all transaction entries and then create a mapping of entry IDs to their corresponding Web3Transaction objects:
const solana = require("solana-web3");
const connection = new solana.Connection();
connection.onLogs(publicKey, (result) => {
const transactions = result.parsedTransactions;
const entryToTransactionMap = {};
for (const transaction of transactions) {
const entryId = transaction.entryId.toString();
if (!entryToTransactionMap[entryId]) {
entryToTransactionMap[entryId] = {};
}
entryToTransactionMap[entryId][transaction.id.toString()] = transaction;
}
console.log(entryToTransactionMap);
});
By using one of these approaches, you should be able to parse transaction details even when the program condition is not met.