// Developers
TypeScript SDK
@routerx.exchange/sdk is a typed client for quotes and swaps, Cross via rx.cross, plus limit order and DCA. Swap quotes load GET /v1/:chain/quotePlan and run the calls on your RPC. Swaps settle on RXRouter. Cross history uses the Cross API.
Installation#
npm install @routerx.exchange/sdkTargets Node 18+. Reads (quotes, allowances, nonces) go over HTTPS JSON-RPC. Pass a wallet EIP-1193 provider only when you need to sign or send.
Creating a client#
Instantiate RouterX with a chainId. Quotes and other reads use rpcUrls when you set them, otherwise the built-in public HTTPS list. The wallet is a fallback only when the chain has no RPC, or every RPC is down and the wallet is already on that chain. Approve, swap, and Cross execute still need the wallet to sign and send.
import { RouterX } from '@routerx.exchange/sdk'
const rx = new RouterX({
chainId: 8453,
// provider: window.ethereum, // signs and sends; not used for quotes
// rpcUrls: ['https://…'], // optional; replaces built-in RPCs for this chain
// crossApiUrl: 'https://cross-api.routerx.exchange',
})swap.quote()#
Loads GET /v1/:chain/quotePlan from https://api.routerx.exchange (override with quoteApiUrl; pass apiKey when the server requires x-api-key), then eth_calls the Multicall3 batches on your RPC. A chunk that reverts is split and retried. If every candidate misses, quote throws NO_ROUTE without a full-search fallback. quote.router is still the swap proxy. Amounts are decimal strings in base units. quote.quotedAt is milliseconds since epoch. Pass this object into swap or buildSwapTx to reuse it; a quote older than 30 seconds (maxQuoteAgeMs) is read again.
The plan's split probes run in the same round. When splitting across pools beats the single path (same impact tiers as /quote), quote.legs is set, amountOut is the sum of the legs, and swap encodes every leg. Orders under 10 bps of price impact stay on one path.
const quote = await rx.swap.quote({
tokenIn: '0x4200000000000000000000000000000000000006', // WETH on Base
tokenOut: '0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913', // USDC
amountIn: '1000000000000000000',
// maxSteps?: number
// gasPrice?: string // wei
// split?: 'auto' | 'force' | 'off'
})
console.log(quote.amountOut)
console.log(quote.offer.path)
console.log(quote.legs?.map((leg) => leg.split)) // e.g. [7000, 3000] when split
console.log(quote.router)| Option | Type | Description |
|---|---|---|
tokenIn | string | Input token. Required. Native: NATIVE_PLACEHOLDER. |
tokenOut | string | Output token. Required. |
amountIn | string | Input amount in base units. Required. |
maxSteps | number | Max hops. Optional. On-chain query accepts 1–4; the SDK clamps to the chain default. |
gasPrice | string | Wei for gas-aware scoring. Optional. |
split | 'auto' | 'force' | 'off' | Split routing. Optional; default auto. force skips the small-order gate, off stays on one path. |
swap.swap()#
Quotes, optionally approves the router, and sends the swap transaction. Pass the quote the user saw so the signed price matches it. Returns the built result plus hash.
const result = await rx.swap.swap({
tokenIn: quote.tokenIn,
tokenOut: quote.tokenOut,
amountIn: quote.amountIn,
to: account, // recipient
slippage: 0.5, // percent; default 0.5
quote, // reused while quotedAt is within 30s
autoApprove: true, // default true for ERC-20
// approvalMode: 'exact' | 'infinite'
})
console.log(result.hash)
console.log(result.minAmountOut)
console.log(result.tx)Provider required
swap, approve, and Cross execute need a wallet provider on the client.swap.buildSwapTx()#
Same as swap without sending — returns minAmountOut, feeBps, and tx: { to, data, value } for your own broadcaster or simulator. minAmountOut is amountOut × (1 − feeBps / 10000) × (1 − slippage / 100), floored, with feeBps = max(fee, 10): the router takes its fee from amountIn and charges 10 bps to senders outside its fee whitelist.
const built = await rx.swap.buildSwapTx({
tokenIn: quote.tokenIn,
tokenOut: quote.tokenOut,
amountIn: quote.amountIn,
to: account,
slippage: 0.5,
quote, // same reuse rule as swap()
})
// eth_call / Tenderly / your bot against built.txcross#
rx.cross.quote composes source/dest swap legs with the same quotePlan path as swap.quote, plus Circle Iris Fast+Forwarder fees. Transfer history uses https://cross-api.routerx.exchange (routerx-cross). HTTP POST /v1/quote on that host is disabled.
import { RouterX, NATIVE_PLACEHOLDER } from '@routerx.exchange/sdk'
const rx = new RouterX({
chainId: 8453,
provider: window.ethereum,
crossApiUrl: 'https://cross-api.routerx.exchange',
})
const quote = await rx.cross.quote({
srcChainId: 8453,
dstChainId: 42161,
tokenIn: NATIVE_PLACEHOLDER,
tokenOut: '0xaf88d065e77c8cC2239327C5EDb3A432268e5831',
amountIn: '1000000000000000000',
slippageBps: 50,
})
const { burnTxHash } = await rx.cross.execute({
quote,
from: account,
provider: window.ethereum,
srcChainId: 8453,
dstChainId: 42161,
tokenInDecimals: 18,
tokenOutDecimals: 6,
slippage: 0.5,
onStatus: (status) => console.log(status),
})Types#
Core shapes from the SDK:
interface QuoteResult {
chainId: number
tokenIn: string
tokenOut: string
amountIn: string
amountOut: string // sum of legs when split
offer: FormattedOffer
router: string
cached: boolean
legs?: QuoteSplitLeg[] // only when splitting beats the single path
quotedAt?: number // ms since epoch; swap reuses the quote while this is fresh
}
interface FormattedOffer {
amounts: string[]
adapters: { address: string; name: string }[]
path: string[]
gasEstimate: string
extras: string[] // aligned with adapters; pass to hops[i].extra
}
interface QuoteSplitLeg {
split: number // bps of post-fee amount; last leg takes remainder
hops: Array<{ adapter: string; name?: string; tokenOut: string; extra: string }>
amountIn?: string // floor(amountIn × split / 10000) as quoted
amountOut: string
gasEstimate?: string
}
interface SwapResult extends QuoteResult {
minAmountOut: string // after feeBps, then slippage
feeBps: number // max(fee, 10); 0 for wrap/unwrap
tx: { to: string; data: string; value: string }
}- Also:
rx.limitOrderandrx.dcaon LO-capable chains. - See the Integration guide for contract addresses and the API reference for HTTP quote, quotePlan, and swap.
swap.quoteuses quotePlan; it does not callGET /quoteorPOST /swap.