The arbitrage scanner compares spot prices across all 6 supported DEXes and surfaces pairs where the spread exceeds 0.5%. On Monad’s ~400 ms block time, profitable windows can be extremely short - this scanner is designed for low-latency polling or WebSocket-driven triggering.
How It Works
getArbitrageAlerts queries all DEX pairs and returns alerts where spreadPct > 0.5%
getAllSwapQuotes gives a full breakdown of what each DEX would pay for a specific trade
detectDexArbitrage checks a single token pair and returns the best buy/sell combination
Full Example
import { getArbitrageAlerts, getAllSwapQuotes, detectDexArbitrage } from 'rampart-monad'
const USDC = '0xf817257fed379853cDe0fa4F97AB987181B1E5Ea'
const MON = '0x0000000000000000000000000000000000000000'
async function scanArbitrage() {
const alerts = await getArbitrageAlerts()
for (const alert of alerts) {
if (alert.spreadPct > 0.5 && alert.profitable) {
console.log(`ARBITRAGE: Buy on ${alert.buyDex} @ $${alert.buyPrice}`)
console.log(` Sell on ${alert.sellDex} @ $${alert.sellPrice}`)
console.log(` Spread: ${alert.spreadPct.toFixed(2)}%`)
}
}
// Drill into a specific pair
const quotes = await getAllSwapQuotes(MON, USDC, '10000000000000000000') // 10 MON
console.log('\nQuotes for 10 MON → USDC:')
for (const q of quotes) {
console.log(` ${q.dex}: ${(Number(q.amountOut) / 1e6).toFixed(4)} USDC`)
}
}
await scanArbitrage()
Example Output
ARBITRAGE: Buy on kuru @ $0.3540
Sell on uniswap-v3 @ $0.3571
Spread: 0.88%
Quotes for 10 MON → USDC:
kuru: 3.5400 USDC
uniswap-v3: 3.5710 USDC
pancake-v3: 3.5380 USDC
uniswap-v2: 3.5200 USDC
pancake-v2: 3.5150 USDC
openocean: 3.5690 USDC
Checking a Specific Pair
import { detectDexArbitrage } from 'rampart-monad'
const MON = '0x0000000000000000000000000000000000000000'
const USDC = '0xf817257fed379853cDe0fa4F97AB987181B1E5Ea'
const alert = await detectDexArbitrage(MON, USDC)
if (alert === null) {
console.log('No arbitrage opportunity - prices are in sync')
} else {
console.log(`Spread: ${alert.spreadPct.toFixed(2)}%`)
console.log(`Profitable: ${alert.profitable}`)
console.log(`Action: buy on ${alert.buyDex} @ $${alert.buyPrice}, sell on ${alert.sellDex} @ $${alert.sellPrice}`)
}
Continuous Scanner with Alerting
import { getArbitrageAlerts } from 'rampart-monad'
const MIN_SPREAD = 0.8 // percent
const POLL_MS = 2000 // 2 s (5 Monad blocks)
async function runScanner() {
console.log(`Scanning every ${POLL_MS}ms, threshold: ${MIN_SPREAD}%`)
let lastAlert = ''
while (true) {
try {
const alerts = await getArbitrageAlerts()
const profitable = alerts.filter(a => a.spreadPct >= MIN_SPREAD && a.profitable)
for (const alert of profitable) {
const key = `${alert.buyDex}-${alert.sellDex}`
if (key !== lastAlert) {
lastAlert = key
console.log(
`[${new Date().toISOString()}] ${alert.spreadPct.toFixed(2)}% spread - ` +
`buy ${alert.buyDex} / sell ${alert.sellDex}`
)
}
}
} catch (err) {
console.error('Scan error:', err)
}
await new Promise(r => setTimeout(r, POLL_MS))
}
}
await runScanner()
Cross-Oracle Price Discrepancy
For a deeper check, combine DEX arbitrage scanning with oracle discrepancy detection:
import { detectDexArbitrage, detectOracleDiscrepancy } from 'rampart-monad'
const MON = '0x0000000000000000000000000000000000000000'
const [dexAlert, oracleAlert] = await Promise.all([
detectDexArbitrage(MON, '0xf817257fed379853cDe0fa4F97AB987181B1E5Ea'),
detectOracleDiscrepancy('MON'),
])
if (dexAlert?.profitable) {
console.log('DEX arbitrage available:', dexAlert)
}
if (oracleAlert?.significant) {
console.log('Oracle price divergence detected:', oracleAlert)
}
Notes
- Monad’s ~400 ms block time means arbitrage windows close faster than on Ethereum. Target spreads above 0.8% to account for gas costs and execution latency.
getAllSwapQuotes returns routes sorted by amountOut descending - the first element is always the best available quote.
- OpenOcean is included in the scan but may introduce latency from the REST API call. If speed is critical, filter it out:
quotes.filter(q => q.dex !== 'openocean').
amountOut values are returned as strings in wei (token decimals vary - USDC uses 6 decimals, most ERC20s use 18).