Coming Soon — This feature is under development and not yet available.
This tutorial will guide you through building a cross-DEX arbitrage scanner that discovers price differences between exchanges in real-time and identifies potential arbitrage opportunities.
Estimated Time : 45 minutes
Difficulty Level : ⭐⭐⭐ Intermediate
Objective
Discover cross-DEX price difference arbitrage opportunities:
Feature Checklist :
✅ Get multi-DEX trading pair prices
✅ Calculate spread percentage
✅ Evaluate feasibility (considering Gas, slippage, depth)
✅ Risk alerts (MEV, front-running)
Arbitrage Principles
Cross-DEX Arbitrage
The same token may have price differences across different DEXes:
Example: ETH/USDC trading pair
Uniswap: 1 ETH = $2,000
SushiSwap: 1 ETH = $2,010
Spread = ($2,010 - $2,000) / $2,000 = 0.5%
Arbitrage path:
Buy ETH on Uniswap → Sell ETH on SushiSwap → Profit from difference
Net Profit = Spread Revenue - Gas Fees - Slippage Loss
Practical considerations:
Gas fees for two transactions
Buy/sell slippage
Liquidity depth limits
MEV front-running risk
Step 1: Get Trading Pairs
1.1 Install Dependencies
npm install @chainstream-io/sdk dotenv
1.2 Configuration File
// config.js
import 'dotenv/config' ;
export const CHAINSTREAM_ACCESS_TOKEN = process . env . CHAINSTREAM_ACCESS_TOKEN ;
// DEXes to monitor
export const DEXES = [ 'uniswap_v3' , 'sushiswap' , 'curve' ];
// Trading pairs to monitor
export const TRADING_PAIRS = [
{ base: 'ETH' , quote: 'USDC' , chain: 'ethereum' },
{ base: 'ETH' , quote: 'USDT' , chain: 'ethereum' },
{ base: 'WBTC' , quote: 'ETH' , chain: 'ethereum' },
];
// Arbitrage thresholds
export const MIN_PROFIT_PERCENT = 0.3 ; // Minimum profit rate
export const MIN_LIQUIDITY_USD = 50000 ; // Minimum liquidity
1.3 Get Price Data
// scanner.js
import { ChainStreamClient } from '@chainstream-io/sdk' ;
import { CHAINSTREAM_ACCESS_TOKEN , DEXES } from './config.js' ;
export class PriceScanner {
constructor () {
this . client = new ChainStreamClient ( CHAINSTREAM_ACCESS_TOKEN );
}
async getDexPrices ( base , quote , chain ) {
// Get trading pair prices across DEXes
const prices = await this . client . dex . getPrices ({
base ,
quote ,
chain ,
dexes: DEXES
});
return prices ;
}
}
Step 2: Calculate Spread
// evaluator.js
import { MIN_PROFIT_PERCENT , MIN_LIQUIDITY_USD } from './config.js' ;
export class ArbitrageEvaluator {
findOpportunity ( prices , pair ) {
// Filter low liquidity
const validPrices = prices . filter (
p => ( p . liquidityUsd || 0 ) >= MIN_LIQUIDITY_USD
);
if ( validPrices . length < 2 ) {
return null ;
}
// Find lowest buy price and highest sell price
const sortedPrices = [ ... validPrices ]. sort (( a , b ) => a . price - b . price );
const buyFrom = sortedPrices [ 0 ]; // Lowest price - buy
const sellTo = sortedPrices [ sortedPrices . length - 1 ]; // Highest price - sell
// Calculate spread
const spread = ( sellTo . price - buyFrom . price ) / buyFrom . price * 100 ;
// Estimate costs
const gasCostPercent = 0.1 ; // ~0.1%
const slippagePercent = 0.2 ; // ~0.2%
const totalCost = gasCostPercent + slippagePercent ;
// Net profit
const netProfit = spread - totalCost ;
if ( netProfit < MIN_PROFIT_PERCENT ) {
return null ;
}
return {
pair: ` ${ pair . base } / ${ pair . quote } ` ,
buyDex: buyFrom . dex ,
buyPrice: buyFrom . price ,
sellDex: sellTo . dex ,
sellPrice: sellTo . price ,
spreadPercent: Number ( spread . toFixed ( 3 )),
netProfitPercent: Number ( netProfit . toFixed ( 3 )),
maxSizeUsd: Math . min ( buyFrom . liquidityUsd , sellTo . liquidityUsd ) * 0.02
};
}
}
Step 3: Evaluate Feasibility
Risk Assessment
// risk.js
export function assessRisk ( opportunity ) {
const risks = [];
// MEV risk
if ( opportunity . netProfitPercent > 1.0 ) {
risks . push ( '🔴 High profit easily front-run by MEV' );
}
// Liquidity risk
if ( opportunity . maxSizeUsd < 5000 ) {
risks . push ( '🟡 Executable size is small' );
}
// Timing risk
risks . push ( '⚠️ Price data has latency' );
return {
risks ,
executable: risks . filter ( r => r . includes ( '🔴' )). length === 0
};
}
Risk Warning
Important Risk Warnings :
MEV Front-running : Arbitrage trades are easily front-run by MEV bots
Price Latency : Prices may have changed by execution time
Gas Volatility : Costs can surge significantly during network congestion
Slippage : Actual slippage may be higher than estimated
This tool is only for discovering opportunities and does not constitute investment advice.
Complete Code
// index.js
import { PriceScanner } from './scanner.js' ;
import { ArbitrageEvaluator } from './evaluator.js' ;
import { TRADING_PAIRS } from './config.js' ;
async function main () {
const scanner = new PriceScanner ();
const evaluator = new ArbitrageEvaluator ();
console . log ( '🔍 Arbitrage scanner starting...' );
while ( true ) {
for ( const pair of TRADING_PAIRS ) {
const prices = await scanner . getDexPrices (
pair . base ,
pair . quote ,
pair . chain
);
const opp = evaluator . findOpportunity ( prices , pair );
if ( opp ) {
console . log ( `
🎯 Arbitrage opportunity found!
Pair: ${ opp . pair }
Buy: ${ opp . buyDex } @ $ ${ opp . buyPrice }
Sell: ${ opp . sellDex } @ $ ${ opp . sellPrice }
Spread: ${ opp . spreadPercent } %
Net Profit: ${ opp . netProfitPercent } %
Max Size: $ ${ opp . maxSizeUsd . toLocaleString () }
` );
}
}
// Scan every 10 seconds
await new Promise ( resolve => setTimeout ( resolve , 10000 ));
}
}
main ();
Extension Suggestions
Flash Loan Integration Use flash loans for zero-capital arbitrage
Multi-chain Scanning Extend to Arbitrum, Base, and other L2s
Auto Execution Integrate wallet for automatic trading (use caution)