mango-transaction-scraper-v3/src/parseTransactions.ts

129 lines
3.9 KiB
TypeScript

const bs58 = require('bs58');
import {
MangoInstructionLayout,
} from '@blockworks-foundation/mango-client';
import { jsonParser } from './jsonParsers';
import { anchorParser } from './anchorParsers';
export function parseTransactions(transactionsResult, mangoProgramId) {
let transactionSummaries: any = [];
let parsedTransactions: any = {
deposits_withdraws: [],
cache_prices: [],
cache_indexes: [],
settle_pnl: [],
settle_fees: [],
force_settle_quote_positions: [], // Deprecated
liquidate_token_and_token: [],
liquidate_token_and_perp: [],
liquidate_perp_market: [],
token_bankruptcy: [],
perp_bankruptcy: [],
fill_events: [],
net_balances: [],
redeem_mngo: [],
funding: [],
open_orders_balances: [],
mango_accrual: [],
cancel_all_perp_orders: [],
// Mango: PlacePerpOrder
// Mango: CancelPerpOrderByClientI
// Mango: CancelPerpOrder
};
for (let transactionResult of transactionsResult) {
let [signature, transaction] = transactionResult;
try {
let result = transaction.result;
let logMessages = result!.meta!.logMessages!.join('\n');
try {
if (result.meta.err !== null) {
transactionSummaries.push({
signature: signature,
process_state: 'transaction error',
log_messages: logMessages
});
} else {
let slot = result.slot;
let blockTime = result.blockTime;
let blockDatetime = new Date(blockTime * 1000).toISOString();
// only look at cases where instruction is for mango program id
// Skip attempting to parse serum instructions, etc
let instructions = result.transaction.message.instructions;
let innerInstructions = result.meta.innerInstructions.map(e => e.instructions).flat();
instructions.push(...innerInstructions)
instructions = instructions.filter(
(ix) =>
ix.programId === mangoProgramId &&
!(
// Old mango group - not in ids.json so have to hardcode here to ignore
(
ix.accounts &&
ix.accounts[0] ===
'2WNLfEMzhgwBPn6QptT43SdZy9cXTUbVJCMdCfimg4oi'
)
),
);
// Anchor logging was deployed at slot 100936906 - use different parsing code before and after this slot
const ancorDeploymentSlot = 100936906
if (slot < ancorDeploymentSlot) {
// Populate instruction num and name for each instruction
let ixNum = 1;
for (const ix of instructions) {
let decodedData = bs58.decode(ix.data);
let decodedInstruction = MangoInstructionLayout.decode(decodedData, 0);
let instructionName = Object.keys(decodedInstruction)[0];
ix.instructionNum = ixNum;
ix.instructionName = instructionName;
ixNum++;
}
jsonParser(parsedTransactions, result, instructions, signature, blockTime, slot, blockDatetime)
} else {
anchorParser(parsedTransactions, result, signature, blockTime, slot, blockDatetime)
}
transactionSummaries.push({
signature: signature,
process_state: 'processed',
log_messages: logMessages
});
}
} catch (e: any) {
console.log(e.stack);
transactionSummaries.push({
signature: signature,
process_state: 'parsing error',
log_messages: logMessages
});
}
} catch {
transactionSummaries.push({
signature: signature,
process_state: 'transaction download error',
log_messages: null
});
}
}
return [transactionSummaries, parsedTransactions];
}