Enhance transaction detail extraction to identify sender, receiver, and transaction types (transfer, swap, nft_mint)

This commit is contained in:
void-57 2026-01-14 01:40:01 +05:30
parent a5ebc25567
commit 774abf7bd6

View File

@ -2578,11 +2578,111 @@
status === "confirmed" ? `Included in Slot #${tx.slot}` : "";
}
// Fill in transaction details
// Extract sender and receiver from transaction
let sender = "Unknown";
let receiver = "Unknown";
let transactionType = "transfer"; // transfer, swap, nft_mint, other
const accountKeys = tx.transaction?.message?.accountKeys || [];
const instructions = tx.transaction?.message?.instructions || [];
const logMessages = tx.meta?.logMessages || [];
// Check if this is an NFT mint by looking at log messages
const isNFTMint = logMessages.some(log =>
log.includes("MintToCollectionV1") ||
log.includes("MintV1") ||
log.includes("Bubblegum") ||
(log.includes("Instruction: Mint") && !log.includes("MintTo") && !log.includes("JUP"))
);
if (isNFTMint) {
transactionType = "nft_mint";
sender = "NFT Mint";
receiver = accountKeys[0]?.toString() || "Unknown";
}
// Check if this is a token swap by looking at token balance changes
else if (tx.meta?.preTokenBalances && tx.meta?.postTokenBalances) {
const preTokens = tx.meta.preTokenBalances;
const postTokens = tx.meta.postTokenBalances;
// Find tokens that decreased (sent)
let tokenSent = null;
let tokenReceived = null;
for (const preTok of preTokens) {
const postTok = postTokens.find(p => p.accountIndex === preTok.accountIndex);
if (postTok) {
const preAmount = parseFloat(preTok.uiTokenAmount.amount);
const postAmount = parseFloat(postTok.uiTokenAmount.amount);
// Token amount decreased significantly (sent/swapped)
if (preAmount > postAmount && (preAmount - postAmount) > 0.000001) {
tokenSent = {
mint: preTok.mint,
amount: preTok.uiTokenAmount.uiAmountString,
symbol: preTok.mint === "So11111111111111111111111111111111111111112" ? "SOL" : preTok.mint
};
}
// Token amount increased significantly (received)
if (postAmount > preAmount && (postAmount - preAmount) > 0.000001) {
tokenReceived = {
mint: postTok.mint,
amount: postTok.uiTokenAmount.uiAmountString,
symbol: postTok.mint === "So11111111111111111111111111111111111111112" ? "SOL" : postTok.mint
};
}
}
}
// If we found a token swap, use that instead of FROM/TO
if (tokenSent && tokenReceived) {
transactionType = "swap";
sender = `${tokenSent.symbol}`;
receiver = `${tokenReceived.symbol}`;
}
}
// If not a swap or NFT mint, try to find the transfer instruction
if (transactionType === "transfer") {
for (const ix of instructions) {
if (ix.accounts && ix.accounts.length >= 2) {
if (ix.data) {
try {
const dataBytes = bs58.decode(ix.data);
if (dataBytes[0] === 2) {
sender = accountKeys[ix.accounts[0]]?.toString() || "Unknown";
receiver = accountKeys[ix.accounts[1]]?.toString() || "Unknown";
break;
}
} catch (e) {
// If decode fails, continue
}
}
}
}
// Fallback: use balance changes to determine sender/receiver
if (sender === "Unknown" && tx.meta?.preBalances && tx.meta?.postBalances) {
for (let i = 0; i < accountKeys.length; i++) {
const balanceChange = tx.meta.postBalances[i] - tx.meta.preBalances[i];
if (balanceChange < -100000 && sender === "Unknown") {
sender = accountKeys[i]?.toString() || "Unknown";
}
if (balanceChange > 100000 && receiver === "Unknown") {
receiver = accountKeys[i]?.toString() || "Unknown";
}
}
}
// Final fallback: use first account as sender
if (sender === "Unknown" && accountKeys[0]) {
sender = accountKeys[0]?.toString() || "Unknown";
}
}
if (getRef("tx_from")) {
const sender =
tx.transaction?.message?.accountKeys?.[0]?.toString() ||
"Unknown";
getRef("tx_from").value = sender;
getRef("tx_from").addEventListener("click", function (e) {
if (
@ -2601,9 +2701,6 @@
}
if (getRef("tx_to")) {
const receiver =
tx.transaction?.message?.accountKeys?.[1]?.toString() ||
"Unknown";
getRef("tx_to").value = receiver;
getRef("tx_to").addEventListener("click", function (e) {
if (
@ -2682,49 +2779,6 @@
if (currentCurrency !== "sol" && !isHistoricApiAvailable) {
testHistoricalAPIAndRenderToggle();
}
let sender = "Unknown";
let receiver = "Unknown";
const message = tx.transaction?.message;
const accountKeys =
message?.staticAccountKeys || message?.accountKeys || [];
const instructions =
message?.compiledInstructions || message?.instructions || [];
// Try to extract from parsed instructions (for parsed transactions)
if (instructions && instructions.length > 0) {
// Try to find a transfer instruction (SPL or System)
for (const ix of instructions) {
// For parsed transactions (if available)
if (ix.parsed && ix.parsed.info) {
if (ix.parsed.info.source && ix.parsed.info.destination) {
sender = ix.parsed.info.source;
receiver = ix.parsed.info.destination;
break;
}
if (ix.parsed.info.authority && ix.parsed.info.destination) {
sender = ix.parsed.info.authority;
receiver = ix.parsed.info.destination;
break;
}
}
// For raw instructions (like in your prompt)
if (ix.accountKeyIndexes && ix.accountKeyIndexes.length >= 2) {
sender = accountKeys[ix.accountKeyIndexes[0]] || "Unknown";
receiver = accountKeys[ix.accountKeyIndexes[1]] || "Unknown";
break;
}
}
}
// Fallback: just use first two account keys
if (sender === "Unknown" && accountKeys[0]) sender = accountKeys[0];
if (receiver === "Unknown" && accountKeys[1])
receiver = accountKeys[1];
if (getRef("tx_from")) getRef("tx_from").value = sender;
if (getRef("tx_to")) getRef("tx_to").value = receiver;
})
.catch((error) => {
console.error("Error:", error);
@ -2766,7 +2820,6 @@
);
}
}
async function fetchSolanaTransactionDetails(signature) {
try {
// Check for valid signature format