Docs
Docs/Quick Start

Quick Start

Start routing cross-chain transfers with MNMX in under 5 minutes.

Installation

bash
1git clone https://github.com/MNMX-labs/mnmx.git
2cd mnmx
3npm install
4npm run build

Setup

Configure your RPC endpoints. MNMX needs access to the chains you want to route through. At minimum, configure the source and destination chains:

bash
1# Create a .env file with your RPC endpoints
2cat > .env << 'EOF'
3ETH_RPC_URL=https://eth-mainnet.g.alchemy.com/v2/YOUR_KEY
4SOL_RPC_URL=https://mainnet.helius-rpc.com/?api-key=YOUR_KEY
5ARB_RPC_URL=https://arb-mainnet.g.alchemy.com/v2/YOUR_KEY
6BASE_RPC_URL=https://mainnet.base.org
7POLYGON_RPC_URL=https://polygon-mainnet.g.alchemy.com/v2/YOUR_KEY
8EOF
Free RPC endpoints: For testing, you can use public RPCs like https://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

typescript
1import { MnmxRouter } from '@mnmx/core';
2
3// Initialize the router
4const router = new MnmxRouter({
5 strategy: 'minimax',
6 slippageTolerance: 0.5,
7});
8
9// Find the optimal route
10const route = await router.findRoute({
11 from: { chain: 'ethereum', token: 'ETH', amount: '1.0' },
12 to: { chain: 'solana', token: 'SOL' },
13});
14
15// Inspect the result
16console.log(route.path); // Route hops
17console.log(route.expectedOutput); // Best-case output
18console.log(route.guaranteedMinimum); // Minimax (worst-case) output
19console.log(route.estimatedTime); // Expected transfer time
20console.log(route.totalFees); // Total fees across all hops
21
22// Execute the route
23const result = await router.execute(route, { signer });
24console.log(result.txHashes);
25console.log(result.actualOutput);

Strategy Options

typescript
1// Minimax (default) — best guaranteed minimum
2const router = new MnmxRouter({ strategy: 'minimax' });
3
4// Cheapest — lowest total fees
5const router = new MnmxRouter({ strategy: 'cheapest' });
6
7// Fastest — shortest transfer time
8const router = new MnmxRouter({ strategy: 'fastest' });
9
10// Safest — highest bridge reliability
11const 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:

typescript
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 USDC
9// Fees: ~$3.50 bridge + ~$12 gas = ~$15.50 total
10// Time: 90-180 seconds via deBridge DLN

Cross-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:

typescript
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 ETH
9// 2. Lower slippage on high-liquidity USDC pairs
10// 3. Better minimax score despite extra swap steps

L2 to L2 Transfer

Transfer between Layer 2 chains. These routes often go through a hub chain (Ethereum) or use direct L2-to-L2 bridges:

typescript
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:

typescript
1const router = new MnmxRouter({
2 strategy: 'minimax',
3 slippageTolerance: 0.3,
4 adversarialModel: {
5 slippageMultiplier: 3.0, // Very conservative on slippage
6 mevExtraction: 0.005, // Higher MEV assumption for large amounts
7 priceMovement: 0.01, // 1% price movement during bridge
8 },
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 bridges
18// Allbridge pool might only have $80K available → excluded
19// Wormhole + deBridge both have sufficient liquidity
20// deBridge DLN makers can handle this size in a single fill
21// Route: deBridge DLN direct (fastest, sufficient maker liquidity)

Swap to Different Token

Convert WBTC on Ethereum to AVAX on Avalanche:

typescript
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 Ethereum
8// Step 2: Wormhole(USDC) Ethereum → Avalanche
9// Step 3: TraderJoe(USDC → AVAX) on Avalanche
10//
11// The engine routes through USDC because:
12// 1. WBTC has no direct bridge to Avalanche with good liquidity
13// 2. USDC is the most liquid bridge asset
14// 3. USDC/AVAX has deep liquidity on TraderJoe

Compare Routes

View all candidate routes before choosing:

typescript
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 → jupiter
19// Expected: 14.32 SOL
20// Minimum: 13.85 SOL
21// Fees: $6.09
22// Time: 110s
23// Score: 0.8470
24//
25// Route: wormhole → jupiter
26// Expected: 14.28 SOL
27// Minimum: 13.52 SOL
28// Fees: $13.20
29// Time: 780s
30// Score: 0.7920
31//
32// Route: uniswap-v3 → allbridge → jupiter
33// Expected: 14.18 SOL
34// Minimum: 13.71 SOL
35// Fees: $8.50
36// Time: 300s
37// Score: 0.8210

Execution with Progress Monitoring

Track execution progress in real-time:

typescript
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 result
28if (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

typescript
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/tokens
19 console.error(`No route available: ${error.reason}`);
20 // Suggestion: try a different token pair or increase maxHops
21
22 } else if (error instanceof InsufficientLiquidityError) {
23 // Transfer amount exceeds bridge liquidity
24 console.error(`Liquidity too low. Available: ${error.available}`);
25 // Suggestion: reduce amount or wait for liquidity rebalance
26
27 } else if (error instanceof SlippageExceededError) {
28 // Slippage exceeded tolerance during execution
29 console.error(`Slippage ${error.actualSlippage}% > tolerance ${error.tolerance}%`);
30 // Suggestion: increase slippageTolerance or try later
31
32 } else if (error instanceof BridgeTimeoutError) {
33 // Bridge took too long
34 console.error(`Bridge ${error.bridge} timed out. TX: ${error.sourceTxHash}`);
35 // Note: funds may still arrive — check bridge explorer
36 }
37}

Integration with ethers.js

typescript
1import { MnmxRouter } from '@mnmx/core';
2import { ethers } from 'ethers';
3
4// Connect to wallet
5const provider = new ethers.BrowserProvider(window.ethereum);
6const signer = await provider.getSigner();
7
8// Initialize router with custom RPC
9const router = new MnmxRouter({
10 strategy: 'minimax',
11 chains: {
12 ethereum: { rpc: provider }, // Use existing provider
13 solana: { rpc: 'https://mainnet.helius-rpc.com/?api-key=YOUR_KEY' },
14 },
15});
16
17// Find and execute route
18const 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 progress
27 updateProgressBar(step.index / step.total);
28 updateStatusText(step.status);
29 },
30});

Integration with Solana web3.js

typescript
1import { MnmxRouter } from '@mnmx/core';
2import { Connection, Keypair } from '@solana/web3.js';
3
4// Load Solana wallet
5const keypair = Keypair.fromSecretKey(/* ... */);
6
7// Initialize router
8const 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 ETH
17const 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:

typescript
1const result = await router.execute(route, {
2 signer,
3 dryRun: true, // Simulate only, no on-chain transactions
4});
5
6// Result contains simulated outputs and gas estimates
7console.log(`Simulated output: ${result.actualOutput} SOL`);
8console.log(`Estimated gas: $${result.totalGasUsed}`);
9console.log(`All steps simulated successfully: ${result.status === 'completed'}`);

Supported Chains

ChainChain IDBridges AvailableType
Ethereum1Wormhole, deBridge, LayerZero, AllbridgeEVM
Solana-Wormhole, deBridge, AllbridgeSVM
Arbitrum42161Wormhole, deBridge, LayerZeroEVM (L2)
Base8453Wormhole, LayerZeroEVM (L2)
Polygon137Wormhole, LayerZero, AllbridgeEVM
BNB Chain56deBridge, LayerZero, AllbridgeEVM
Optimism10Wormhole, LayerZeroEVM (L2)
Avalanche43114Wormhole, LayerZero, AllbridgeEVM

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