Skip to main content

findSwapPathsBetweenTokens

This module computes all valid intermediate-token sequences for swapping between any two tokens in a MarketsGraph. The result is a precomputed lookup table that swap routing uses to enumerate candidate routes.

Methods

This module exports a single function that builds a full swap-path lookup table from a markets graph.

findSwapPathsBetweenTokens

findSwapPathsBetweenTokens(graph: MarketsGraph): SwapPaths

Runs a breadth-first search from every token in graph to every other token and returns a SwapPaths map. Each entry in the map is an array of intermediate-token paths: the sequence of tokens the swap passes through between the source and destination. A direct swap with no intermediate hops is represented as an empty array [].

The search is bounded by MAX_EDGE_PATH_LENGTH = 3, which limits the total number of market edges (hops) in any path. An intermediate-token list therefore contains at most 2 addresses.

Tokens with no reachable targets are omitted from the result.

Path pruning rules

findSwapPathsBetweenTokens applies two pruning rules during the search to discard routes that would almost always produce a loss:

  1. Single-market A → B → A loop. If the path visits token X, then Y, then X again, and there is only one market between X and Y, the path is pruned. With a single market, the two legs incur price impact twice on the same pool, guaranteeing a net loss.
  2. Consecutive same-token visit. If the last two tokens in the path are identical, the path is pruned as a degenerate loop.

Same-token swaps (for example, ETH → ETH) are valid when multiple markets connect that token to itself and the path includes at least one intermediate token.

Return type

type SwapPaths = {
[fromToken: string]: {
[toToken: string]: string[][]; // array of intermediate-token sequences
};
};

Each string[] entry is one candidate route described by its intermediate tokens. For a direct single-hop swap, the entry is []. For a two-hop swap through USDC, the entry is ["0xUSDC"].

Example

import { findSwapPathsBetweenTokens } from "@gmx-io/sdk/utils/swap";
import { buildMarketsAdjacencyGraph } from "@gmx-io/sdk/utils/swap";
import { MARKETS } from "@gmx-io/sdk/configs/markets";

const graph = buildMarketsAdjacencyGraph(MARKETS[42161]);
const swapPaths = findSwapPathsBetweenTokens(graph);

// Direct swap ETH → USDC and indirect via BTC
// swapPaths[wethAddress][usdcAddress] might be:
// [[], ["0xBTC..."]]
// ^ ^
// | two-hop: ETH → BTC → USDC
// direct: ETH → USDC

const routes = swapPaths[wethAddress]?.[usdcAddress] ?? [];
for (const intermediates of routes) {
if (intermediates.length === 0) {
console.log("Direct swap");
} else {
console.log("Via:", intermediates.join(" → "));
}
}
note

findSwapPathsBetweenTokens returns the raw graph-level paths (intermediate tokens only). To evaluate which path gives the best output for a specific swap amount, pass these paths to getBestSwapPath from utils/swap/swapRouting, which applies live market data to score each route.

note

For most use cases, use the pre-computed constants from utils/swap/preparedSwapData instead: TOKEN_SWAP_PATHS, MARKETS_ADJACENCY_GRAPH, and REACHABLE_TOKENS are built from findSwapPathsBetweenTokens at module load time and are optimized for repeated lookups.