All files / src/parsers parser-raydium-logs.ts

32.25% Statements 10/31
11.76% Branches 2/17
20% Functions 1/5
32.25% Lines 10/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 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199  1x 1x 1x 1x 1x 1x       1x                                                                                                                                                                                                                                                                                                                                                                       1x 1x 1x            
// Define log types for different operations
enum LogType {
  Init = 0,
  Deposit = 1,
  Withdraw = 2,
  SwapBaseIn = 3,
  SwapBaseOut = 4,
}
 
// Constants for swap direction
const SWAP_DIRECTION = {
  COIN_TO_PC: 0n, // Token A -> Token B (e.g., SOL -> USDC)
  PC_TO_COIN: 1n, // Token B -> Token A (e.g., USDC -> SOL)
} as const;
 
// Interface for Add Liquidity operation log
interface DepositLog {
  logType: LogType;
  // Input parameters
  maxCoin: bigint; // Maximum amount of token A to add
  maxPc: bigint; // Maximum amount of token B to add
  base: bigint; // Base value for calculation
  // Pool information
  poolCoin: bigint; // Current pool token A amount
  poolPc: bigint; // Current pool token B amount
  poolLp: bigint; // Current pool LP token amount
  calcPnlX: bigint; // PnL calculation X
  calcPnlY: bigint; // PnL calculation Y
  // Operation results
  deductCoin: bigint; // Actual token A amount added
  deductPc: bigint; // Actual token B amount added
  mintLp: bigint; // LP tokens minted
}
 
// Interface for Remove Liquidity operation log
interface WithdrawLog {
  logType: LogType;
  // Input parameters
  withdrawLp: bigint; // LP tokens to withdraw
  // User information
  userLp: bigint; // User's LP token balance
  // Pool information
  poolCoin: bigint; // Current pool token A amount
  poolPc: bigint; // Current pool token B amount
  poolLp: bigint; // Current pool LP token amount
  calcPnlX: bigint; // PnL calculation X
  calcPnlY: bigint; // PnL calculation Y
  // Operation results
  outCoin: bigint; // Token A amount received
  outPc: bigint; // Token B amount received
}
 
// Interface for Exact Input Swap operation log
interface SwapBaseInLog {
  logType: LogType;
  // Input parameters
  amountIn: bigint; // Exact amount to swap in
  minimumOut: bigint; // Minimum amount to receive
  direction: bigint; // Swap direction (0: A->B, 1: B->A)
  // User information
  userSource: bigint; // User's source token balance
  // Pool information
  poolCoin: bigint; // Current pool token A amount
  poolPc: bigint; // Current pool token B amount
  // Operation results
  outAmount: bigint; // Actual amount received
}
 
// Interface for Exact Output Swap operation log
interface SwapBaseOutLog {
  logType: LogType;
  // Input parameters
  maxIn: bigint; // Maximum amount to swap in
  amountOut: bigint; // Exact amount to receive
  direction: bigint; // Swap direction (0: A->B, 1: B->A)
  // User information
  userSource: bigint; // User's source token balance
  // Pool information
  poolCoin: bigint; // Current pool token A amount
  poolPc: bigint; // Current pool token B amount
  // Operation results
  deductIn: bigint; // Actual amount paid
}
 
// Main function to decode Raydium logs
function decodeRaydiumLog(base64Log: string): DepositLog | WithdrawLog | SwapBaseInLog | SwapBaseOutLog | null {
  // Remove "ray_log:" prefix and clean the string
  const cleanLog = base64Log.replace('ray_log:', '').trim();
 
  // Decode base64 string to buffer
  const data = Buffer.from(cleanLog, 'base64');
 
  // Read log type from first byte
  const logType = data[0];
  let offset = 1;
 
  // Helper function to read uint64 values
  function readU64(): bigint {
    const value = data.readBigUInt64LE(offset);
    offset += 8;
    return value;
  }
 
  // Helper function to read uint128 values
  function readU128(): bigint {
    const value = data.readBigUInt64LE(offset);
    const valueHigh = data.readBigUInt64LE(offset + 8);
    offset += 16;
    return valueHigh * BigInt(2 ** 64) + value;
  }
 
  // Parse log based on its type
  switch (logType) {
    case LogType.Deposit:
      return {
        logType: LogType.Deposit,
        maxCoin: readU64(),
        maxPc: readU64(),
        base: readU64(),
        poolCoin: readU64(),
        poolPc: readU64(),
        poolLp: readU64(),
        calcPnlX: readU128(),
        calcPnlY: readU128(),
        deductCoin: readU64(),
        deductPc: readU64(),
        mintLp: readU64(),
      };
 
    case LogType.Withdraw:
      return {
        logType: LogType.Withdraw,
        withdrawLp: readU64(),
        userLp: readU64(),
        poolCoin: readU64(),
        poolPc: readU64(),
        poolLp: readU64(),
        calcPnlX: readU128(),
        calcPnlY: readU128(),
        outCoin: readU64(),
        outPc: readU64(),
      };
 
    case LogType.SwapBaseIn:
      return {
        logType: LogType.SwapBaseIn,
        amountIn: readU64(),
        minimumOut: readU64(),
        direction: readU64(),
        userSource: readU64(),
        poolCoin: readU64(),
        poolPc: readU64(),
        outAmount: readU64(),
      };
 
    case LogType.SwapBaseOut:
      return {
        logType: LogType.SwapBaseOut,
        maxIn: readU64(),
        amountOut: readU64(),
        direction: readU64(),
        userSource: readU64(),
        poolCoin: readU64(),
        poolPc: readU64(),
        deductIn: readU64(),
      };
 
    default:
      return null; //Unsupported log type
  }
}
 
// Helper function to parse swap operation details
function parseRaydiumSwapLog(log: SwapBaseInLog | SwapBaseOutLog) {
  const isBaseIn = 'amountIn' in log;
  const isBuy = log.direction === SWAP_DIRECTION.PC_TO_COIN;
 
  const operation = {
    type: isBuy ? 'Buy' : 'Sell',
    mode: isBaseIn ? 'Exact Input' : 'Exact Output',
    inputAmount: isBaseIn ? log.amountIn : log.deductIn,
    outputAmount: isBaseIn ? log.outAmount : log.amountOut,
    slippageProtection: isBaseIn ? log.minimumOut : log.maxIn,
  };
 
  return operation;
}
 
export {
  LogType,
  SWAP_DIRECTION,
  decodeRaydiumLog,
  parseRaydiumSwapLog,
  type DepositLog,
  type WithdrawLog,
  type SwapBaseInLog,
  type SwapBaseOutLog,
};