Quick Start
Start routing cross-chain transfers with MNMX in under 5 minutes.
Installation
1git clone https://github.com/MNMX-labs/mnmx.git2cd mnmx3npm install4npm run buildSetup
Configure your RPC endpoints. MNMX needs access to the chains you want to route through. At minimum, configure the source and destination chains:
1# Create a .env file with your RPC endpoints2cat > .env << 'EOF'3ETH_RPC_URL=https://eth-mainnet.g.alchemy.com/v2/YOUR_KEY4SOL_RPC_URL=https://mainnet.helius-rpc.com/?api-key=YOUR_KEY5ARB_RPC_URL=https://arb-mainnet.g.alchemy.com/v2/YOUR_KEY6BASE_RPC_URL=https://mainnet.base.org7POLYGON_RPC_URL=https://polygon-mainnet.g.alchemy.com/v2/YOUR_KEY8EOFhttps://rpc.ankr.com/eth or https://api.mainnet-beta.solana.com. For production, use a provider like Alchemy, Infura, or Helius for reliability and rate limits.Basic Usage
1import { MnmxRouter } from '@mnmx/core';2
3// Initialize the router4const router = new MnmxRouter({5 strategy: 'minimax',6 slippageTolerance: 0.5,7});8
9// Find the optimal route10const route = await router.findRoute({11 from: { chain: 'ethereum', token: 'ETH', amount: '1.0' },12 to: { chain: 'solana', token: 'SOL' },13});14
15// Inspect the result16console.log(route.path); // Route hops17console.log(route.expectedOutput); // Best-case output18console.log(route.guaranteedMinimum); // Minimax (worst-case) output19console.log(route.estimatedTime); // Expected transfer time20console.log(route.totalFees); // Total fees across all hops21
22// Execute the route23const result = await router.execute(route, { signer });24console.log(result.txHashes);25console.log(result.actualOutput);Strategy Options
1// Minimax (default) — best guaranteed minimum2const router = new MnmxRouter({ strategy: 'minimax' });3
4// Cheapest — lowest total fees5const router = new MnmxRouter({ strategy: 'cheapest' });6
7// Fastest — shortest transfer time8const router = new MnmxRouter({ strategy: 'fastest' });9
10// Safest — highest bridge reliability11const router = new MnmxRouter({ strategy: 'safest' });Common Use Cases
Stablecoin Transfer
Transfer USDC between chains. Stablecoin-to-stablecoin transfers have minimal slippage and are typically the cheapest route type:
1const route = await router.findRoute({2 from: { chain: 'ethereum', token: 'USDC', amount: '5000' },3 to: { chain: 'solana', token: 'USDC' },4});5
6// Output for 5,000 USDC transfer:7// Expected: 4,996.50 USDC (bridge fee only, no swap slippage)8// Guaranteed minimum: 4,991.25 USDC9// Fees: ~$3.50 bridge + ~$12 gas = ~$15.50 total10// Time: 90-180 seconds via deBridge DLNCross-Chain Swap (Different Tokens)
Swap ETH on Ethereum for SOL on Solana. The engine will find the best combination of DEX swaps and bridge transfers:
1const route = await router.findRoute({2 from: { chain: 'ethereum', token: 'ETH', amount: '2.5' },3 to: { chain: 'solana', token: 'SOL' },4});5
6// Typical route: ETH → Uniswap(ETH→USDC) → deBridge(USDC) → Jupiter(USDC→SOL)7// The engine chose this over direct ETH bridge because:8// 1. USDC bridges have deeper liquidity than wrapped ETH9// 2. Lower slippage on high-liquidity USDC pairs10// 3. Better minimax score despite extra swap stepsL2 to L2 Transfer
Transfer between Layer 2 chains. These routes often go through a hub chain (Ethereum) or use direct L2-to-L2 bridges:
1const route = await router.findRoute({2 from: { chain: 'arbitrum', token: 'ETH', amount: '1.0' },3 to: { chain: 'base', token: 'ETH' },4});5
6// Possible routes:7// A: Arbitrum → LayerZero(ETH) → Base (direct, ~5 min)8// B: Arbitrum → Wormhole(ETH) → Base (direct, ~8 min)9// C: Arbitrum → deBridge → Ethereum → Base (via hub, slower)10//11// Engine typically picks A or B for L2-to-L2 (direct is faster and cheaper)Large Transfer ($100K+)
For large transfers, slippage and MEV exposure dominate the cost. Use conservative settings:
1const router = new MnmxRouter({2 strategy: 'minimax',3 slippageTolerance: 0.3,4 adversarialModel: {5 slippageMultiplier: 3.0, // Very conservative on slippage6 mevExtraction: 0.005, // Higher MEV assumption for large amounts7 priceMovement: 0.01, // 1% price movement during bridge8 },9});10
11const route = await router.findRoute({12 from: { chain: 'ethereum', token: 'USDC', amount: '150000' },13 to: { chain: 'solana', token: 'USDC' },14});15
16// For $150K USDC:17// Engine checks pool depths on all bridges18// Allbridge pool might only have $80K available → excluded19// Wormhole + deBridge both have sufficient liquidity20// deBridge DLN makers can handle this size in a single fill21// Route: deBridge DLN direct (fastest, sufficient maker liquidity)Swap to Different Token
Convert WBTC on Ethereum to AVAX on Avalanche:
1const route = await router.findRoute({2 from: { chain: 'ethereum', token: 'WBTC', amount: '0.5' },3 to: { chain: 'avalanche', token: 'AVAX' },4});5
6// Typical route:7// Step 1: Uniswap(WBTC → USDC) on Ethereum8// Step 2: Wormhole(USDC) Ethereum → Avalanche9// Step 3: TraderJoe(USDC → AVAX) on Avalanche10//11// The engine routes through USDC because:12// 1. WBTC has no direct bridge to Avalanche with good liquidity13// 2. USDC is the most liquid bridge asset14// 3. USDC/AVAX has deep liquidity on TraderJoeCompare Routes
View all candidate routes before choosing:
1const routes = await router.findAllRoutes({2 from: { chain: 'ethereum', token: 'ETH', amount: '1.0' },3 to: { chain: 'solana', token: 'SOL' },4});5
6for (const route of routes) {7 const hops = route.path.map(h => h.provider).join(' → ');8 console.log(`Route: ${hops}`);9 console.log(` Expected: ${route.expectedOutput} SOL`);10 console.log(` Minimum: ${route.guaranteedMinimum} SOL`);11 console.log(` Fees: $${route.totalFeesUSD}`);12 console.log(` Time: ${route.estimatedTime}s`);13 console.log(` Score: ${route.minimaxScore.toFixed(4)}`);14 console.log();15}16
17// Example output:18// Route: uniswap-v3 → debridge → jupiter19// Expected: 14.32 SOL20// Minimum: 13.85 SOL21// Fees: $6.0922// Time: 110s23// Score: 0.847024//25// Route: wormhole → jupiter26// Expected: 14.28 SOL27// Minimum: 13.52 SOL28// Fees: $13.2029// Time: 780s30// Score: 0.792031//32// Route: uniswap-v3 → allbridge → jupiter33// Expected: 14.18 SOL34// Minimum: 13.71 SOL35// Fees: $8.5036// Time: 300s37// Score: 0.8210Execution with Progress Monitoring
Track execution progress in real-time:
1const result = await router.execute(route, {2 signer: walletSigner,3 onProgress: (step) => {4 const prefix = `[${step.index + 1}/${step.total}]`;5
6 switch (step.status) {7 case 'simulated':8 console.log(`${prefix} Simulated ${step.hop.provider}: output looks good`);9 break;10 case 'submitted':11 console.log(`${prefix} Submitted to ${step.hop.from.chain}: ${step.txHash}`);12 break;13 case 'confirmed':14 console.log(`${prefix} Confirmed on ${step.hop.from.chain}`);15 break;16 case 'completed':17 console.log(`${prefix} Completed: received ${step.output} ${step.hop.to.token}`);18 break;19 case 'failed':20 console.error(`${prefix} Failed: ${step.error}`);21 break;22 }23 },24 autoRetry: true,25});26
27// Check final result28if (result.status === 'completed') {29 console.log(`Transfer complete! Received ${result.actualOutput} SOL`);30 console.log(`Total time: ${result.totalTime}s`);31 console.log(`Gas cost: $${result.totalGasUsed}`);32
33 if (result.meetsGuarantee) {34 console.log('Output met the guaranteed minimum.');35 } else {36 console.warn('Output fell below guaranteed minimum (rare edge case).');37 }38} else if (result.status === 'partial') {39 console.log(`Partial completion. Funds at: ${result.fundsLocation.chain}`);40 console.log(`Token: ${result.fundsLocation.token}`);41 console.log(`Amount: ${result.fundsLocation.amount}`);42}Error Handling
1import {2 NoRouteFoundError,3 InsufficientLiquidityError,4 SlippageExceededError,5 BridgeTimeoutError,6} from '@mnmx/core';7
8try {9 const route = await router.findRoute({10 from: { chain: 'ethereum', token: 'ETH', amount: '1.0' },11 to: { chain: 'solana', token: 'SOL' },12 });13
14 const result = await router.execute(route, { signer });15
16} catch (error) {17 if (error instanceof NoRouteFoundError) {18 // No path exists between these chains/tokens19 console.error(`No route available: ${error.reason}`);20 // Suggestion: try a different token pair or increase maxHops21
22 } else if (error instanceof InsufficientLiquidityError) {23 // Transfer amount exceeds bridge liquidity24 console.error(`Liquidity too low. Available: ${error.available}`);25 // Suggestion: reduce amount or wait for liquidity rebalance26
27 } else if (error instanceof SlippageExceededError) {28 // Slippage exceeded tolerance during execution29 console.error(`Slippage ${error.actualSlippage}% > tolerance ${error.tolerance}%`);30 // Suggestion: increase slippageTolerance or try later31
32 } else if (error instanceof BridgeTimeoutError) {33 // Bridge took too long34 console.error(`Bridge ${error.bridge} timed out. TX: ${error.sourceTxHash}`);35 // Note: funds may still arrive — check bridge explorer36 }37}Integration with ethers.js
1import { MnmxRouter } from '@mnmx/core';2import { ethers } from 'ethers';3
4// Connect to wallet5const provider = new ethers.BrowserProvider(window.ethereum);6const signer = await provider.getSigner();7
8// Initialize router with custom RPC9const router = new MnmxRouter({10 strategy: 'minimax',11 chains: {12 ethereum: { rpc: provider }, // Use existing provider13 solana: { rpc: 'https://mainnet.helius-rpc.com/?api-key=YOUR_KEY' },14 },15});16
17// Find and execute route18const route = await router.findRoute({19 from: { chain: 'ethereum', token: 'ETH', amount: '0.5' },20 to: { chain: 'arbitrum', token: 'ETH' },21});22
23const result = await router.execute(route, {24 signer,25 onProgress: (step) => {26 // Update UI with progress27 updateProgressBar(step.index / step.total);28 updateStatusText(step.status);29 },30});Integration with Solana web3.js
1import { MnmxRouter } from '@mnmx/core';2import { Connection, Keypair } from '@solana/web3.js';3
4// Load Solana wallet5const keypair = Keypair.fromSecretKey(/* ... */);6
7// Initialize router8const router = new MnmxRouter({9 strategy: 'minimax',10 chains: {11 solana: { rpc: 'https://mainnet.helius-rpc.com/?api-key=YOUR_KEY' },12 ethereum: { rpc: 'https://eth-mainnet.g.alchemy.com/v2/YOUR_KEY' },13 },14});15
16// Bridge SOL to ETH17const route = await router.findRoute({18 from: { chain: 'solana', token: 'SOL', amount: '10.0' },19 to: { chain: 'ethereum', token: 'ETH' },20});21
22console.log(`Will receive ~${route.expectedOutput} ETH`);23console.log(`Guaranteed minimum: ${route.guaranteedMinimum} ETH`);24
25const result = await router.execute(route, {26 signer: {27 publicKey: keypair.publicKey,28 signTransaction: (tx) => {29 tx.sign(keypair);30 return Promise.resolve(tx);31 },32 signAllTransactions: (txs) => {33 txs.forEach(tx => tx.sign(keypair));34 return Promise.resolve(txs);35 },36 },37});Dry Run (Simulation Only)
Simulate execution without submitting transactions:
1const result = await router.execute(route, {2 signer,3 dryRun: true, // Simulate only, no on-chain transactions4});5
6// Result contains simulated outputs and gas estimates7console.log(`Simulated output: ${result.actualOutput} SOL`);8console.log(`Estimated gas: $${result.totalGasUsed}`);9console.log(`All steps simulated successfully: ${result.status === 'completed'}`);Supported Chains
| Chain | Chain ID | Bridges Available | Type |
|---|---|---|---|
| Ethereum | 1 | Wormhole, deBridge, LayerZero, Allbridge | EVM |
| Solana | - | Wormhole, deBridge, Allbridge | SVM |
| Arbitrum | 42161 | Wormhole, deBridge, LayerZero | EVM (L2) |
| Base | 8453 | Wormhole, LayerZero | EVM (L2) |
| Polygon | 137 | Wormhole, LayerZero, Allbridge | EVM |
| BNB Chain | 56 | deBridge, LayerZero, Allbridge | EVM |
| Optimism | 10 | Wormhole, LayerZero | EVM (L2) |
| Avalanche | 43114 | Wormhole, LayerZero, Allbridge | EVM |
Next Steps
- Read the Architecture guide to understand the system design and data flow
- Explore the Routing Engine for the path discovery and execution deep dive
- Learn about the Minimax Algorithm and why it produces better outcomes than expected-value optimization
- Check Bridge Adapters for supported bridges, implementation details, and how to add new ones
- See Configuration for all tunable parameters and deployment options
- Use the Python SDK for route simulation and Monte Carlo analysis
- Reference the TypeScript SDK for complete type definitions and method signatures