UNPKG

solana-dex-parser

Version:

Solana Dex Transaction Parser

158 lines 8.03 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.DexParser = void 0; const constants_1 = require("./constants"); const instruction_classifier_1 = require("./instruction-classifier"); const parsers_1 = require("./parsers"); const transaction_adapter_1 = require("./transaction-adapter"); const transaction_utils_1 = require("./transaction-utils"); const utils_1 = require("./utils"); /** * Main parser class for Solana DEX transactions */ class DexParser { constructor() { // Trade parser mapping this.parserMap = { [constants_1.DEX_PROGRAMS.JUPITER.id]: parsers_1.JupiterParser, [constants_1.DEX_PROGRAMS.JUPITER_DCA.id]: parsers_1.JupiterParser, [constants_1.DEX_PROGRAMS.MOONSHOT.id]: parsers_1.MoonshotParser, [constants_1.DEX_PROGRAMS.METEORA.id]: parsers_1.MeteoraParser, [constants_1.DEX_PROGRAMS.METEORA_POOLS.id]: parsers_1.MeteoraParser, [constants_1.DEX_PROGRAMS.PUMP_FUN.id]: parsers_1.PumpfunParser, [constants_1.DEX_PROGRAMS.PUMP_SWAP.id]: parsers_1.PumpswapParser, [constants_1.DEX_PROGRAMS.RAYDIUM_ROUTE.id]: parsers_1.RaydiumParser, [constants_1.DEX_PROGRAMS.RAYDIUM_CL.id]: parsers_1.RaydiumParser, [constants_1.DEX_PROGRAMS.RAYDIUM_CPMM.id]: parsers_1.RaydiumParser, [constants_1.DEX_PROGRAMS.RAYDIUM_V4.id]: parsers_1.RaydiumParser, [constants_1.DEX_PROGRAMS.RAYDIUM_LCP.id]: parsers_1.RaydiumLaunchpadParser, [constants_1.DEX_PROGRAMS.ORCA.id]: parsers_1.OrcaParser, }; // Liquidity parser mapping this.parseLiquidityMap = { [constants_1.DEX_PROGRAMS.METEORA.id]: parsers_1.MeteoraDLMMPoolParser, [constants_1.DEX_PROGRAMS.METEORA_POOLS.id]: parsers_1.MeteoraPoolsParser, [constants_1.DEX_PROGRAMS.RAYDIUM_V4.id]: parsers_1.RaydiumV4PoolParser, [constants_1.DEX_PROGRAMS.RAYDIUM_CPMM.id]: parsers_1.RaydiumCPMMPoolParser, [constants_1.DEX_PROGRAMS.RAYDIUM_CL.id]: parsers_1.RaydiumCLPoolParser, [constants_1.DEX_PROGRAMS.ORCA.id]: parsers_1.OrcaLiquidityParser, [constants_1.DEX_PROGRAMS.PUMP_FUN.id]: parsers_1.PumpswapLiquidityParser, [constants_1.DEX_PROGRAMS.PUMP_SWAP.id]: parsers_1.PumpswapLiquidityParser, }; } /** * Parse transaction with specific type */ parseWithClassifier(tx, config = { tryUnknowDEX: true }, parseType) { const result = { state: true, trades: [], liquidities: [], transfers: [], }; try { const adapter = new transaction_adapter_1.TransactionAdapter(tx, config); const utils = new transaction_utils_1.TransactionUtils(adapter); const classifier = new instruction_classifier_1.InstructionClassifier(adapter); // Get DEX information and validate const dexInfo = utils.getDexInfo(classifier); const allProgramIds = classifier.getAllProgramIds(); const transferActions = utils.getTransferActions(['mintTo', 'burn', 'mintToChecked', 'burnChecked']); // Try specific parser first if (dexInfo.programId && [constants_1.DEX_PROGRAMS.JUPITER.id, constants_1.DEX_PROGRAMS.JUPITER_DCA.id].includes(dexInfo.programId)) { if (parseType === 'trades' || parseType === 'all') { const jupiterInstructions = classifier.getInstructions(dexInfo.programId); const parser = new parsers_1.JupiterParser(adapter, dexInfo, transferActions, jupiterInstructions); result.trades.push(...parser.processTrades()); } return result; } // Process instructions for each program for (const programId of allProgramIds) { const classifiedInstructions = classifier.getInstructions(programId); // Process trades if needed if (parseType === 'trades' || parseType === 'all') { if (config?.programIds && !config.programIds.some((id) => id == programId)) continue; if (config?.ignoreProgramIds && config.ignoreProgramIds.some((id) => id == programId)) continue; const TradeParserClass = this.parserMap[programId]; if (TradeParserClass) { const parser = new TradeParserClass(adapter, { ...dexInfo, programId: programId, amm: (0, utils_1.getProgramName)(programId) }, transferActions, classifiedInstructions); result.trades.push(...parser.processTrades()); } else if (config?.tryUnknowDEX) { // Handle unknown DEX programs const transfers = Object.entries(transferActions).find(([key]) => key.startsWith(programId))?.[1]; if (transfers && transfers.length >= 2) { const trade = utils.processSwapData(transfers, { ...dexInfo, programId: programId, amm: (0, utils_1.getProgramName)(programId), }); if (trade) result.trades.push(trade); } } } // Process liquidity if needed if (parseType === 'liquidity' || parseType === 'all') { if (config?.programIds && !config.programIds.some((id) => id == programId)) continue; if (config?.ignoreProgramIds && config.ignoreProgramIds.some((id) => id == programId)) continue; const LiquidityParserClass = this.parseLiquidityMap[programId]; if (LiquidityParserClass) { const parser = new LiquidityParserClass(adapter, transferActions, classifiedInstructions); result.liquidities.push(...parser.processLiquidity()); } } } // Deduplicate trades if (result.trades.length > 0) { result.trades = [...new Map(result.trades.map((item) => [`${item.idx}-${item.signature}`, item])).values()]; } // Process transfer if needed (if no trades and no liquidity) if (result.trades.length == 0 && result.liquidities.length == 0) { if (parseType === 'transfer' || parseType === 'all') { if (!allProgramIds.some((id) => constants_1.DEX_PROGRAM_IDS.includes(id))) { result.transfers.push(...Object.values(transferActions).flat()); } } } } catch (error) { const msg = `Parse error: ${tx?.transaction?.signatures?.[0]} ${error}`; console.error(error); result.state = false; result.msg = msg; } return result; } /** * Parse trades from transaction */ parseTrades(tx, config) { return this.parseWithClassifier(tx, config, 'trades').trades; } /** * Parse liquidity events from transaction */ parseLiquidity(tx, config) { return this.parseWithClassifier(tx, config, 'liquidity').liquidities; } /** * Parse transfers from transaction (if no trades and no liquidity) */ parseTransfers(tx, config) { return this.parseWithClassifier(tx, config, 'transfer').transfers; } /** * Parse both trades and liquidity events from transaction */ parseAll(tx, config) { return this.parseWithClassifier(tx, config, 'all'); } } exports.DexParser = DexParser; //# sourceMappingURL=dex-parser.js.map