All files parser-orca.ts

68.75% Statements 22/32
40% Branches 2/5
72.72% Functions 8/11
70.96% Lines 22/31

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64  1x   1x 1x   1x         2x 2x   2x 2x 2x                             2x 2x 2x                         2x 2x   2x 2x 2x 10x 10x         10x 8x   2x    
import { ParsedInstruction, ParsedTransactionWithMeta } from "@solana/web3.js";
import { DEX_PROGRAMS } from "./constants";
import { DexInfo, TokenInfo, TradeInfo, TransferData } from "./types";
import { TokenInfoExtractor } from "./token-extractor";
import { processSwapData, isTransfer, processTransfer } from "./transfer-utils";
 
export class OrcaParser {
  private readonly splTokenMap: Map<string, TokenInfo>;
  private readonly splDecimalsMap: Map<string, number>;
 
  constructor(
    private readonly txWithMeta: ParsedTransactionWithMeta,
    private readonly dexInfo: DexInfo
  ) {
    const tokenExtractor = new TokenInfoExtractor(txWithMeta);
    this.splTokenMap = tokenExtractor.extractSPLTokenInfo();
    this.splDecimalsMap = tokenExtractor.extractDecimals();
  }
 
  public processTrades(): TradeInfo[] {
    return this.txWithMeta.transaction.message.instructions
      .reduce((trades: TradeInfo[], instruction: any, index: number) => {
        Iif (this.isOrcaInstruction(instruction)) {
          const instructionTrades = this.processInstructionTrades(index);
          trades.push(...instructionTrades);
        }
        return trades;
      }, []);
  }
 
  public processInstructionTrades(instructionIndex: number): TradeInfo[] {
    try {
      const transfers = this.processOrcaSwaps(instructionIndex);
      return transfers.length ? [processSwapData(this.txWithMeta, transfers, this.dexInfo)] : [];
    } catch (error) {
      console.error('Error processing Orca trades:', error);
      return [];
    }
  }
 
  private isOrcaInstruction(instruction: any): boolean {
    const programId = instruction.programId.toBase58();
    return DEX_PROGRAMS.ORCA.id == programId;
  }
 
  private processOrcaSwaps(instructionIndex: number): TransferData[] {
    const innerInstructions = this.txWithMeta.meta?.innerInstructions;
    Iif (!innerInstructions) return [];
 
    return innerInstructions
      .filter(set => set.index === instructionIndex)
      .flatMap(set => set.instructions
        .map(instruction => this.processTransferInstruction(instruction as ParsedInstruction))
        .filter((transfer): transfer is TransferData => transfer !== null)
      );
  }
 
  private processTransferInstruction(instruction: ParsedInstruction): TransferData | null {
    if (isTransfer(instruction)) {
      return processTransfer(instruction, this.splTokenMap, this.splDecimalsMap);
    }
    return null;
  }
}