npm package: @lendliq/router
Description: DEX routing and path finding for LendLiq protocol
Author: LendLiq Team
Latest version: 1.0.0

# @lendliq/router

DEX routing and path finding for LendLiq protocol. Works with [@lendliq/sdk](https://www.npmjs.com/package/@lendliq/sdk) for core entities.

## Installation

```bash
npm install @lendliq/router @lendliq/sdk viem
# or
yarn add @lendliq/router @lendliq/sdk viem
# or
pnpm add @lendliq/router @lendliq/sdk viem
```

## Quick Start

```typescript
import { PathFinder } from "@lendliq/router";
import { Token, Trade, Route } from "@lendliq/sdk";
import { createPublicClient, http } from "viem";
import { bsc } from "viem/chains";
import { BigNumber } from "bignumber.js";

// 1. Define your tokens
const WBNB = new Token(56, "0xbb4CdB9CBd36B01bD1cBaEBF2De08d9173bc095c", 18, "WBNB");
const USDT = new Token(56, "0x55d398326f99059fF775485246999027B3197955", 18, "USDT");
const ETH = new Token(56, "0x2170Ed0880ac9A755fd29B2688956BD959F933F8", 18, "ETH");

// 2. Create viem client
const client = createPublicClient({
  chain: bsc,
  transport: http()
});

// 3. Initialize PathFinder (once at app startup)
const pathFinder = await PathFinder.create({
  chainId: 56,
  client,
  v3Factory: "0xdB1d10011AD0Ff90774D0C6Bb92e5C5c8b4461F7",
  tokens: [WBNB, USDT, ETH],
  feeTiers: [500, 2500, 10000],
});

// 4. Find best route (no need to pass config again!)
const result = await pathFinder.findBestRoute(
  USDT.address,
  ETH.address,
  new BigNumber("100000000000000000000") // 100 USDT
);

if (result) {
  console.log(`Output: ${result.amountOut.toString()}`);
  console.log(`Price Impact: ${result.priceImpact}%`);
  console.log(`Routes: ${result.routes.length}`);

  // Create Trade object for execution
  const routes = result.routes.map(r =>
    new Route(r.steps, r.expectedOutput, r.priceImpact, r.percentage)
  );
  const trade = new Trade(USDT, ETH, amountIn, result.amountOut, routes, result.priceImpact);

  // Get params for smart contract
  const params = trade.toAggregatorParams(userAddress, 50); // 0.5% slippage
}
```

## Setup Configuration

| Option | Type | Required | Default | Description |
|--------|------|----------|---------|-------------|
| `chainId` | `number` | Yes | - | Chain ID (e.g., 56 for BSC) |
| `client` | `PublicClient` | Yes | - | Viem public client |
| `v3Factory` | `string` | Yes | - | V3 factory contract address |
| `tokens` | `Token[]` | Yes | - | Token list for pool discovery |
| `quoter` | `string` | No | - | Optional Quoter contract address |
| `feeTiers` | `number[]` | No | `[500, 2500, 10000]` | Fee tiers to search (basis points) |
| `maxHops` | `number` | No | `3` | Maximum hops in a route |
| `maxRoutes` | `number` | No | `5` | Maximum routes to consider |
| `enableSplitRouting` | `boolean` | No | `true` | Enable split routing |
| `maxSplitRoutes` | `number` | No | `3` | Maximum routes to split across |
| `minSplitPercentage` | `number` | No | `500` | Minimum percentage per split (5%) |
| `multicallBatchSize` | `number` | No | `100` | Batch size for multicall requests |

## API

### PathFinder.create(config)

Create and initialize a new PathFinder instance. Discovers all pools between provided tokens.

```typescript
const pathFinder = await PathFinder.create({
  chainId: 56,
  client,
  v3Factory: "0x...",
  tokens: [WBNB, USDT, ETH, BUSD],
  feeTiers: [500, 2500, 10000],
});
```

### pathFinder.findBestRoute(tokenIn, tokenOut, amountIn, options?)

Find the best route for a swap. Configuration from setup is used automatically.

```typescript
const result = await pathFinder.findBestRoute(
  USDT.address,
  ETH.address,
  new BigNumber("100000000000000000000"),
  {
    // Optional overrides for this query
    maxHops: 2,
    disableSplitRouting: true,
  }
);
```

### pathFinder.addTokens(tokens)

Add new tokens and discover their pools with existing tokens.

```typescript
const CAKE = new Token(56, "0x0E09FaBB73Bd3Ade0a17ECC321fD13a19e81cE82", 18, "CAKE");
await pathFinder.addTokens([CAKE]);
```

### pathFinder.refreshPools()

Refresh all pool data (prices, liquidity).

```typescript
await pathFinder.refreshPools();
```

### pathFinder.setFeeTiers(feeTiers)

Update fee tiers and clear pool cache.

```typescript
pathFinder.setFeeTiers([100, 500, 3000, 10000]);
```

### pathFinder.getDiscoveredPools()

Get all discovered pools.

```typescript
const pools = pathFinder.getDiscoveredPools();
console.log(`Found ${pools.length} pools`);
```

### pathFinder.getCacheStats()

Get cache statistics.

```typescript
const stats = pathFinder.getCacheStats();
console.log(`Pools: ${stats.pools}, Tokens: ${stats.tokens}`);
```

## Performance (Multicall)

PathFinder uses **multicall** for efficient batch RPC requests, significantly reducing initialization time:

```typescript
// Without multicall: 10 tokens × 3 fee tiers = 135 pool queries = 135+ RPC calls
// With multicall: Same queries batched into ~3-4 RPC calls

// Example: 10 tokens with 3 fee tiers
// - Pool address queries: 1 multicall (45 calls batched)
// - Pool data queries: 1-2 multicalls (225 calls batched)
// - Token decimals: 1 multicall (if needed)
```

Configure batch size based on your RPC provider limits:

```typescript
const pathFinder = await PathFinder.create({
  // ... other config
  multicallBatchSize: 100, // Default: 100, adjust based on RPC limits
});
```

## Split Routing

For large trades, PathFinder automatically splits the trade across multiple routes to minimize price impact:

```typescript
const result = await pathFinder.findBestRoute(tokenIn, tokenOut, largeAmount);

// result.routes might contain multiple routes:
// [
//   { percentage: 6000, expectedOutput: "...", steps: [...] },  // 60%
//   { percentage: 4000, expectedOutput: "...", steps: [...] },  // 40%
// ]
```

## Multi-Chain Support

Use the same API for different chains:

```typescript
// BSC Mainnet
const bscPathFinder = await PathFinder.create({
  chainId: 56,
  client: bscClient,
  v3Factory: "0x...",
  tokens: bscTokens,
});

// BSC Testnet
const testnetPathFinder = await PathFinder.create({
  chainId: 97,
  client: testnetClient,
  v3Factory: "0x...",
  tokens: testnetTokens,
});

// Ethereum
const ethPathFinder = await PathFinder.create({
  chainId: 1,
  client: ethClient,
  v3Factory: "0x1F98431c8aD98523631AE4a59f267346ea31F984", // Uniswap V3
  tokens: ethTokens,
  feeTiers: [100, 500, 3000, 10000], // Uniswap fee tiers
});
```

## License

MIT