solana-dex-parser
Version:
Solana Dex Transaction Parser
158 lines • 8.03 kB
JavaScript
;
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