# Slippage Mapping This document describes how `SlippageBps` is derived for each supported swap protocol in this repository. ## Unified Fields Each parsed `Swap` may include these normalized fields: - `SwapMode` - `FixedAmount` - `FixedAmountSide` - `FixedMint` - `LimitAmountType` - `LimitAmount` - `LimitAmountSide` - `LimitMint` - `ActualLimitAmount` - `ActualLimitAmountSide` - `SlippageBps` ## Internal Enum Mapping These fields are stored internally as `uint8` enums and serialized as strings in JSON / debug output. ### `SwapMode` | Raw Value | Name | Serialized Value | | --- | --- | --- | | `0` | `SwapModeUnknown` | `""` | | `1` | `SwapModeExactIn` | `"exact_in"` | | `2` | `SwapModeExactOut` | `"exact_out"` | ### `SwapAmountSide` Used by: - `FixedAmountSide` - `LimitAmountSide` - `ActualLimitAmountSide` | Raw Value | Name | Serialized Value | | --- | --- | --- | | `0` | `SwapAmountSideUnknown` | `""` | | `1` | `SwapAmountSideBase` | `"base"` | | `2` | `SwapAmountSideQuote` | `"quote"` | ### `SwapLimitType` Used by: - `LimitAmountType` | Raw Value | Name | Serialized Value | | --- | --- | --- | | `0` | `SwapLimitTypeUnknown` | `""` | | `1` | `SwapLimitTypeMinOut` | `"min_out"` | | `2` | `SwapLimitTypeMaxIn` | `"max_in"` | ## Calculation Rules - `exact_in` - `SlippageBps = (actual_out - min_out) / actual_out * 10000` - `exact_out` - `SlippageBps = (max_in - actual_in) / max_in * 10000` Interpretation: - Positive: execution is better than the user limit - Zero: execution lands exactly on the user limit - `10000`: user limit is effectively unbounded on the constrained side (for example `min_out = 0`) - Negative raw headroom is clamped to `0` because successful-swap storage uses a non-negative bounded metric This definition makes `SlippageBps` a bounded "remaining headroom to the user's limit" metric for successful swaps: - `exact_in`: how much output headroom remained, measured against the realized output - `exact_out`: how much input headroom remained, measured against the allowed max input ## Protocol Mapping | Protocol | Method Semantics | `SwapMode` | `FixedAmount` | `LimitAmountType` | `LimitAmount` | `ActualLimitAmount` | | --- | --- | --- | --- | --- | --- | --- | | `Pump` | `buy` | `exact_out` | target token amount | `max_in` | max SOL in | actual SOL in | | `Pump` | `buy_exact_sol_in` | `exact_in` | SOL in | `min_out` | min token out | actual token out | | `Pump` | `sell` | `exact_in` | token in | `min_out` | min SOL out | actual SOL out | | `PumpAMM` | `buy` | `exact_out` | target base out | `max_in` | max quote in | actual quote in | | `PumpAMM` | `buy_exact_quote_in` | `exact_in` | quote in | `min_out` | min base out | actual base out | | `PumpAMM` | `sell` | `exact_in` | base in | `min_out` | min quote out | actual quote out | | `MeteoraDLMM` | `swap` / `swap2` / `swap_with_price_impact` | `exact_in` | `AmountIn` | `min_out` | instruction min out | event output | | `MeteoraDLMM` | `swap_exact_out` / `swap_exact_out2` | `exact_out` | `OutAmount` | `max_in` | `MaxInAmount` | event input | | `MeteoraPools` | `swap` | `exact_in` | `InAmount` | `min_out` | `MinimumOutAmount` | actual output side | | `MeteoraBondingCurve` | `swap` / `swap2` | `exact_in` | `AmountIn` | `min_out` | `MinimumAmountOut` | actual output side | | `MeteoraAmmV2` | `swap` / `swap2` exact-in or partial | `exact_in` | params input side | `min_out` | params output threshold | actual output side | | `MeteoraAmmV2` | `swap` / `swap2` exact-out | `exact_out` | params target output | `max_in` | params max input | actual input side | | `RaydiumLaunchLab` | `*_ExactIn` | `exact_in` | `Amount` | `min_out` | `OtherAmountThreshold` | actual output side | | `RaydiumLaunchLab` | `*_ExactOut` | `exact_out` | `Amount` | `max_in` | `OtherAmountThreshold` | actual input side | | `RaydiumCPMM` | `swap_base_input` | `exact_in` | `AmountIn` | `min_out` | `MinimumAmountOut` | actual output side | | `RaydiumCPMM` | `swap_base_output` | `exact_out` | `AmountOut` | `max_in` | `MaxAmountIn` | actual input side | | `RaydiumCLMM` | `swap` / `swap_v2` | `exact_in` or `exact_out` | `amount` | `min_out` or `max_in` | `other_amount_threshold` | opposite-side actual amount | | `RaydiumV4` | `swap_base_in` / `swap_base_in_v2` | `exact_in` | `amount_in` | `min_out` | `minimum_amount_out` | actual output side | | `RaydiumV4` | `swap_base_out` / `swap_base_out_v2` | `exact_out` | `amount_out` | `max_in` | `max_amount_in` | actual input side | | `OrcaWhirlpool` | `swap` / `swap_v2` | `exact_in` or `exact_out` | `amount` | `min_out` or `max_in` | `other_amount_threshold` | opposite-side actual amount | | `OrcaWhirlpool` | `two_hop_swap` / `two_hop_swap_v2` | route-level | route specified amount | `min_out` or `max_in` | route threshold | route final output or total input | ## Notes - `Pump` quote side is normalized to `wSOL` in the slippage fields, even when legacy `Swap.QuoteMint` is not populated. - `OrcaWhirlpool` two-hop instructions use route-level slippage. The normalized slippage fields are attached to the first returned swap entry. - `MeteoraAmmV2` uses `SwapMode.ExactIn`, `SwapMode.PartialFill`, and `SwapMode.ExactOut`. `PartialFill` is treated like exact-in for slippage purposes because it still uses a minimum-output threshold. ## DAMM v2 Verification The `MeteoraAmmV2` mapping has been checked against the program IDL for `cpamdpZCGKUy5JxQXB4dcpGPiikHawvSWAd6mEn1sGG`. - `swap` - instruction arg type: `SwapParameters` - fields: `amountIn`, `minimumAmountOut` - semantics: exact-in - `swap2`: - instruction / event arg type: `SwapParameters2` - `amount0`: "When it's exact in, partial fill, this will be amount_in. When it's exact out, this will be amount_out" - `amount1`: "When it's exact in, partial fill, this will be minimum_amount_out. When it's exact out, this will be maximum_amount_in" - `swapMode`: `ExactIn`, `PartialFill`, `ExactOut` The downloaded JSON IDL references `SwapMode` in the field docs but does not inline the enum body itself. In this repository, the raw `swapMode` values are interpreted consistently as: - `0 = ExactIn` - `1 = PartialFill` - `2 = ExactOut` That means the parser mapping is: - `swap2` + `ExactIn` / `PartialFill` - `FixedAmount = amount0` - `LimitAmount = amount1` - `LimitAmountType = min_out` - `swap2` + `ExactOut` - `FixedAmount = amount0` - `LimitAmount = amount1` - `LimitAmountType = max_in` ## Source Files - `Swap` normalized fields: `tx.go` - Shared slippage mapping helpers: `swap_amounts.go` - Protocol parsers: - `pump.go` - `pumpamm.go` - `metaoradlmm.go` - `metaorapool.go` - `meteora_bonding_curve.go` - `meteoradamm.go` - `raydiumlaunchlab.go` - `raydiumcpmm.go` - `raydiumclmm.go` - `raydiumv4.go` - `orcawhirpool.go`