Configuration
Tuning the MNMX routing engine for different use cases and environments.
Full Configuration Reference
Every configurable parameter with its type, default value, and description:
1const router = new MnmxRouter({2 // ─── Routing Strategy ────────────────────────────────3 strategy: 'minimax', // minimax | cheapest | fastest | safest4
5 // ─── Tolerance ────────────────────────────────────────6 slippageTolerance: 0.5, // Max acceptable slippage (%)7 timeout: 30_000, // Max quote computation time (ms)8 executionTimeout: 1_200_000, // Max total execution time (ms) — 20 min9 quoteRefreshInterval: 10_000, // Auto-refresh quotes every 10s10
11 // ─── Path Constraints ────────────────────────────────12 maxHops: 3, // Maximum bridge hops (swaps don't count)13 maxSwapsPerHop: 2, // Maximum swap steps per chain14 maxCandidatePaths: 50, // Cap on raw candidate paths15 maxEvaluatedPaths: 15, // Cap on paths after pruning16
17 // ─── Bridge Selection ────────────────────────────────18 bridges: ['wormhole', 'debridge', 'layerzero', 'allbridge'],19 excludeBridges: [], // Bridges to exclude20 customBridges: [], // Custom BridgeAdapter instances21
22 // ─── Scoring Weights (must sum to 1.0) ────────────────23 weights: {24 fees: 0.25, // Total fee weight25 slippage: 0.25, // Slippage impact weight26 speed: 0.15, // Transfer speed weight27 reliability: 0.20, // Bridge reliability weight28 mevExposure: 0.15, // MEV exposure weight29 },30
31 // ─── Adversarial Model ────────────────────────────────32 adversarialModel: {33 slippageMultiplier: 2.0, // Worst-case slippage = quoted * 2.034 gasMultiplier: 1.5, // Worst-case gas = current * 1.535 bridgeDelayMultiplier: 3.0, // Worst-case delay = median * 3.036 mevExtraction: 0.003, // 0.3% of value on unprotected swaps37 priceMovement: 0.005, // 0.5% adverse price change per bridge hop38 },39
40 // ─── Chain RPC Configuration ──────────────────────────41 chains: {42 ethereum: {43 rpc: 'https://eth-mainnet.g.alchemy.com/v2/YOUR_KEY',44 fallbackRpcs: [45 'https://mainnet.infura.io/v3/YOUR_KEY',46 'https://rpc.ankr.com/eth',47 ],48 blockConfirmations: 2,49 maxGasPrice: '100000000000', // 100 gwei max gas price50 },51 solana: {52 rpc: 'https://mainnet.helius-rpc.com/?api-key=YOUR_KEY',53 fallbackRpcs: [54 'https://api.mainnet-beta.solana.com',55 ],56 commitment: 'confirmed',57 maxComputeUnits: 400_000,58 },59 arbitrum: {60 rpc: 'https://arb-mainnet.g.alchemy.com/v2/YOUR_KEY',61 fallbackRpcs: [62 'https://arb1.arbitrum.io/rpc',63 ],64 blockConfirmations: 1,65 },66 base: {67 rpc: 'https://mainnet.base.org',68 fallbackRpcs: [],69 blockConfirmations: 1,70 },71 polygon: {72 rpc: 'https://polygon-mainnet.g.alchemy.com/v2/YOUR_KEY',73 fallbackRpcs: [74 'https://polygon-rpc.com',75 ],76 blockConfirmations: 30,77 },78 bsc: {79 rpc: 'https://bsc-dataseed1.binance.org',80 fallbackRpcs: [81 'https://bsc-dataseed2.binance.org',82 'https://bsc-dataseed3.binance.org',83 ],84 blockConfirmations: 15,85 },86 avalanche: {87 rpc: 'https://api.avax.network/ext/bc/C/rpc',88 fallbackRpcs: [],89 blockConfirmations: 1,90 },91 optimism: {92 rpc: 'https://mainnet.optimism.io',93 fallbackRpcs: [],94 blockConfirmations: 1,95 },96 },97
98 // ─── Cache Configuration ──────────────────────────────99 cache: {100 driver: 'memory', // 'memory' | 'redis'101 redis: {102 host: 'localhost',103 port: 6379,104 password: undefined,105 keyPrefix: 'mnmx:',106 db: 0,107 },108 ttl: {109 bridgeQuote: 10_000, // Bridge quotes: 10s110 dexQuote: 5_000, // DEX quotes: 5s111 gasEstimate: 15_000, // Gas estimates: 15s112 bridgeHealth: 60_000, // Health checks: 60s113 poolReserves: 30_000, // Pool reserves: 30s114 tokenPrice: 10_000, // Token prices: 10s115 chainGraph: 300_000, // Chain topology: 5 min116 tokenMetadata: 86_400_000, // Token metadata: 24h117 },118 maxMemoryMB: 256,119 evictionPolicy: 'lru',120 },121
122 // ─── Logging ───────────────────────────────────────────123 logLevel: 'info', // 'debug' | 'info' | 'warn' | 'error'124 logFormat: 'json', // 'json' | 'text'125 logDestination: 'stdout', // 'stdout' | 'file' | 'none'126 logFile: undefined, // Path to log file (when logDestination='file')127
128 // ─── Telemetry ─────────────────────────────────────────129 telemetry: {130 enabled: true,131 collectExecutionMetrics: true,132 collectQuoteMetrics: true,133 collectBridgeMetrics: true,134 metricsInterval: 60_000, // Aggregate metrics every 60s135 },136
137 // ─── Gas Management ────────────────────────────────────138 gas: {139 bufferMultiplier: 1.15, // Add 15% buffer to gas estimates140 maxPriorityFeeGwei: 3, // Max EIP-1559 priority fee141 useEIP1559: true, // Use EIP-1559 tx format when available142 speedUpAfter: 60_000, // Speed up stuck tx after 60s143 speedUpGasMultiplier: 1.3, // Increase gas by 30% on speed-up144 },145
146 // ─── Token Approvals ───────────────────────────────────147 approvals: {148 usePermit2: true, // Use Permit2 when available149 infiniteApproval: false, // Use infinite approval (less gas, less safe)150 revokeAfterExecution: false, // Revoke approval after execution151 },152});Strategy Profiles
Preset configurations for common use cases. Each strategy adjusts the scoring weights to prioritize different trade-offs:
| Strategy | Fees | Slippage | Speed | Reliability | MEV | Use Case |
|---|---|---|---|---|---|---|
| minimax | 0.25 | 0.25 | 0.15 | 0.20 | 0.15 | Best guaranteed outcome (default) |
| cheapest | 0.45 | 0.30 | 0.05 | 0.10 | 0.10 | Minimize total cost |
| fastest | 0.10 | 0.15 | 0.50 | 0.15 | 0.10 | Minimize transfer time |
| safest | 0.10 | 0.15 | 0.10 | 0.40 | 0.25 | Maximize security and reliability |
Custom Strategy
Define custom scoring weights for specialized use cases:
1// Whale strategy: prioritize low slippage and reliability for large transfers2const router = new MnmxRouter({3 strategy: 'minimax',4 weights: {5 fees: 0.10, // Fees are negligible relative to transfer size6 slippage: 0.35, // Slippage is the dominant cost for large amounts7 speed: 0.05, // Speed doesn't matter for large transfers8 reliability: 0.30, // Cannot afford a failed bridge on $500K+9 mevExposure: 0.20, // MEV extraction scales with transfer size10 },11});12
13// DeFi arbitrage strategy: speed is everything14const router = new MnmxRouter({15 strategy: 'fastest',16 weights: {17 fees: 0.15,18 slippage: 0.15,19 speed: 0.55, // Arbitrage windows close fast20 reliability: 0.10,21 mevExposure: 0.05,22 },23 maxHops: 2, // Fewer hops = faster24 timeout: 5_000, // Quick quote timeout25});26
27// Conservative treasury strategy: safety above all28const router = new MnmxRouter({29 strategy: 'safest',30 weights: {31 fees: 0.05,32 slippage: 0.15,33 speed: 0.05,34 reliability: 0.45, // Only use the most reliable bridges35 mevExposure: 0.30, // Minimize all extraction risk36 },37 bridges: ['wormhole'], // Only use the most established bridge38 adversarialModel: {39 slippageMultiplier: 3.0, // Very conservative40 gasMultiplier: 2.0,41 bridgeDelayMultiplier: 5.0,42 mevExtraction: 0.005,43 priceMovement: 0.01,44 },45});Adversarial Model Tuning
The adversarial model controls how the minimax engine estimates worst-case outcomes. Adjust based on your risk tolerance:
| Parameter | Type | Default | Conservative | Aggressive | Description |
|---|---|---|---|---|---|
slippageMultiplier | number | 2.0x | 3.0x | 1.5x | Multiplier applied to quoted slippage for worst-case estimate |
gasMultiplier | number | 1.5x | 2.0x | 1.2x | Multiplier applied to current gas price for surge modeling |
bridgeDelayMultiplier | number | 3.0x | 5.0x | 2.0x | Multiplier applied to median bridge confirmation time |
mevExtraction | number | 0.3% | 0.5% | 0.1% | Percentage of swap value assumed extracted by MEV bots |
priceMovement | number | 0.5% | 1.0% | 0.2% | Adverse price change assumed per bridge transit period |
When to Adjust the Adversarial Model
| Scenario | Recommended Adjustment |
|---|---|
| Large transfers (>$100K) | Increase slippageMultiplier to 3.0x, mevExtraction to 0.5% |
| Stablecoin-to-stablecoin | Decrease priceMovement to 0.1% (pegged assets have minimal price risk) |
| During high network congestion | Increase gasMultiplier to 2.5x, bridgeDelayMultiplier to 5.0x |
| Using MEV-protected RPCs (Flashbots) | Decrease mevExtraction to 0.05% |
| Small, frequent transfers (<$1K) | Decrease all multipliers by 30% for better average outcomes |
| Time-sensitive (arbitrage) | Decrease bridgeDelayMultiplier to 1.5x, increase speed weight |
Bridge Configuration
Include or exclude specific bridges, or configure bridge-specific parameters:
1// Only use specific bridges2const router = new MnmxRouter({3 bridges: ['wormhole', 'debridge'],4});5
6// Exclude specific bridges7const router = new MnmxRouter({8 excludeBridges: ['allbridge'],9});10
11// Per-route bridge exclusion12const route = await router.findRoute({13 from: { chain: 'ethereum', token: 'ETH', amount: '1.0' },14 to: { chain: 'solana', token: 'SOL' },15 options: { excludeBridges: ['layerzero'] },16});17
18// Bridge-specific configuration19const router = new MnmxRouter({20 bridgeConfig: {21 wormhole: {22 guardianRpc: 'https://wormhole-v2-mainnet-api.certus.one',23 consistencyLevel: 'finalized', // 'instant' | 'safe' | 'finalized'24 relayerEnabled: true,25 },26 debridge: {27 dlnApiUrl: 'https://dln.debridge.finance',28 minMakerLiquidity: '10000', // Minimum maker liquidity in USD29 preferDln: true, // Prefer DLN over native bridge30 },31 layerzero: {32 dvnConfig: {33 required: ['google-cloud', 'polyhedra'],34 optional: ['animoca', 'bware', 'horizen'],35 threshold: 2,36 },37 },38 allbridge: {39 minPoolUtilization: 20, // Skip pools below 20% utilization40 maxSlippageFromVirtualPrice: 2, // Max 2% virtual price deviation41 },42 },43});Chain Configuration
Configure RPC endpoints, confirmation requirements, and gas limits per chain:
1const router = new MnmxRouter({2 chains: {3 ethereum: {4 rpc: 'https://eth-mainnet.g.alchemy.com/v2/YOUR_KEY',5 fallbackRpcs: [6 'https://mainnet.infura.io/v3/YOUR_KEY',7 'https://rpc.ankr.com/eth',8 ],9 blockConfirmations: 2, // Wait for 2 block confirmations10 maxGasPrice: '100000000000', // 100 gwei — reject tx if gas exceeds this11 chainId: 1,12 },13 solana: {14 rpc: 'https://mainnet.helius-rpc.com/?api-key=YOUR_KEY',15 fallbackRpcs: [16 'https://api.mainnet-beta.solana.com',17 ],18 commitment: 'confirmed', // 'processed' | 'confirmed' | 'finalized'19 maxComputeUnits: 400_000, // Max compute units per transaction20 priorityFee: 10_000, // Priority fee in microlamports21 },22 arbitrum: {23 rpc: 'https://arb-mainnet.g.alchemy.com/v2/YOUR_KEY',24 fallbackRpcs: [25 'https://arb1.arbitrum.io/rpc',26 ],27 blockConfirmations: 1,28 maxGasPrice: '1000000000', // 1 gwei (Arbitrum gas is cheap)29 },30 },31});RPC Fallback Behavior
When the primary RPC endpoint fails, the system automatically tries fallback endpoints in order. Each endpoint is tracked for latency and error rate:
| Behavior | Threshold | Action |
|---|---|---|
| Primary endpoint timeout | 5 seconds | Try first fallback |
| Primary error rate > 10% | Rolling 100 requests | Demote to fallback, promote next |
| All endpoints fail | All return errors | Throw AllEndpointsFailedError |
| Latency > 3x median | Rolling 50 requests | Flag as degraded, prefer faster endpoints |
Cache Configuration
The state cache reduces RPC calls and improves quote latency. Two backends are supported:
1// In-memory cache (default) — suitable for single-instance deployments2const router = new MnmxRouter({3 cache: {4 driver: 'memory',5 maxMemoryMB: 256,6 evictionPolicy: 'lru',7 },8});9
10// Redis cache — required for multi-instance deployments11const router = new MnmxRouter({12 cache: {13 driver: 'redis',14 redis: {15 host: process.env.REDIS_HOST || 'localhost',16 port: 6379,17 password: process.env.REDIS_PASSWORD,18 keyPrefix: 'mnmx:state:',19 db: 0,20 tls: process.env.NODE_ENV === 'production',21 maxRetriesPerRequest: 3,22 connectTimeout: 5_000,23 },24 maxMemoryMB: 512,25 },26});Cache TTL Reference
| Data Type | Default TTL | Min Recommended | Max Recommended | Impact of Staleness |
|---|---|---|---|---|
| Bridge quotes | 10s | 5s | 30s | Stale quotes lead to slippage exceeded errors on execution |
| DEX quotes | 5s | 2s | 15s | Stale quotes produce inaccurate slippage estimates |
| Gas estimates | 15s | 5s | 60s | Stale estimates cause underpaid gas (tx stuck) or overpaid gas |
| Bridge health | 60s | 30s | 300s | Stale health data may route through degraded bridges |
| Pool reserves | 30s | 5s | 60s | Stale reserves cause incorrect slippage calculations |
| Token prices | 10s | 5s | 30s | Stale prices affect USD-normalized scoring |
| Chain graph | 5 min | 1 min | 15 min | New bridges/tokens not discovered until refresh |
| Token metadata | 24h | 1h | 7 days | Minimal — decimals and addresses rarely change |
Gas Management
Fine-tune gas estimation and submission behavior:
1const router = new MnmxRouter({2 gas: {3 // Gas estimation4 bufferMultiplier: 1.15, // 15% buffer on gas estimates5 maxPriorityFeeGwei: 3, // Max EIP-1559 priority fee6
7 // Transaction format8 useEIP1559: true, // Use EIP-1559 when available9
10 // Stuck transaction handling11 speedUpAfter: 60_000, // Speed up if not confirmed after 60s12 speedUpGasMultiplier: 1.3, // Increase gas by 30% on speed-up13 maxSpeedUpAttempts: 3, // Maximum speed-up attempts14
15 // Chain-specific gas limits16 perChain: {17 ethereum: {18 maxGasPriceGwei: 100, // Reject if gas > 100 gwei19 maxTransactionCostUSD: 50, // Reject if tx cost > $5020 },21 solana: {22 maxComputeUnits: 400_000,23 priorityFeeLamports: 10_000,24 },25 arbitrum: {26 maxGasPriceGwei: 5, // Arbitrum gas is cheap27 maxTransactionCostUSD: 2,28 },29 },30 },31});Token Approval Configuration
1const router = new MnmxRouter({2 approvals: {3 // Use Permit2 for gasless approvals when supported4 usePermit2: true,5
6 // Infinite approval: approve max uint256 once, skip future approvals7 // Saves ~21,000 gas per future transfer but grants permanent access8 infiniteApproval: false,9
10 // Revoke approval after execution completes11 // Costs extra gas but ensures no residual approvals12 revokeAfterExecution: false,13
14 // Approval amount when not using infinite approval15 // 'exact': approve exactly the transfer amount (safest)16 // 'padded': approve 1.1x the amount (handles slight quote changes)17 approvalMode: 'padded',18 },19});infiniteApprovalgrants permanent token access to bridge and DEX contracts. While this saves gas on repeated transfers, it increases exposure if a contract is compromised. For high-security deployments, keep this disabled and use revokeAfterExecution: true.Environment Variables
All configuration options can be set via environment variables. Environment variables override programmatic configuration:
| Variable | Type | Default | Description |
|---|---|---|---|
MNMX_STRATEGY | string | minimax | Default routing strategy |
MNMX_MAX_HOPS | number | 3 | Maximum intermediate bridge hops |
MNMX_TIMEOUT | number | 30000 | Quote computation timeout (ms) |
MNMX_EXEC_TIMEOUT | number | 1200000 | Execution timeout (ms) |
MNMX_SLIPPAGE | number | 0.5 | Default slippage tolerance (%) |
MNMX_LOG_LEVEL | string | info | Logging level (debug/info/warn/error) |
MNMX_LOG_FORMAT | string | json | Log format (json/text) |
MNMX_CACHE_DRIVER | string | memory | Cache backend (memory/redis) |
MNMX_CACHE_MAX_MB | number | 256 | Maximum cache memory (MB) |
MNMX_BRIDGES | string | all | Comma-separated bridge list |
MNMX_GAS_BUFFER | number | 1.15 | Gas estimate buffer multiplier |
MNMX_USE_EIP1559 | boolean | true | Use EIP-1559 transactions |
MNMX_TELEMETRY | boolean | true | Enable telemetry collection |
ETH_RPC_URL | string | - | Ethereum RPC endpoint |
SOL_RPC_URL | string | - | Solana RPC endpoint |
ARB_RPC_URL | string | - | Arbitrum RPC endpoint |
BASE_RPC_URL | string | - | Base RPC endpoint |
POLYGON_RPC_URL | string | - | Polygon RPC endpoint |
BSC_RPC_URL | string | - | BNB Chain RPC endpoint |
AVAX_RPC_URL | string | - | Avalanche RPC endpoint |
OP_RPC_URL | string | - | Optimism RPC endpoint |
REDIS_HOST | string | localhost | Redis host (when cache driver is redis) |
REDIS_PORT | number | 6379 | Redis port |
REDIS_PASSWORD | string | - | Redis password |
.mnmxrc Configuration File
Configuration can also be loaded from a .mnmxrc JSON file in the project root:
1{2 "strategy": "minimax",3 "slippageTolerance": 0.5,4 "maxHops": 3,5 "bridges": ["wormhole", "debridge", "layerzero", "allbridge"],6 "logLevel": "info",7 "chains": {8 "ethereum": {9 "rpc": "$ETH_RPC_URL"10 },11 "solana": {12 "rpc": "$SOL_RPC_URL"13 }14 },15 "adversarialModel": {16 "slippageMultiplier": 2.0,17 "gasMultiplier": 1.5,18 "bridgeDelayMultiplier": 3.0,19 "mevExtraction": 0.003,20 "priceMovement": 0.00521 }22}Configuration precedence (highest to lowest):
- Constructor arguments — Programmatic config in
new MnmxRouter({...}) - Environment variables —
MNMX_*prefixed variables - .mnmxrc file — JSON config file in project root
- Built-in defaults — Calibrated default values