# MEV Risk Scanner - DEX Sandwich + Fee Intel (`constructive_calm/mev-pair-scanner`) Actor

Per-pair MEV exposure, sandwich-attack rate, and fee-regime classification across 133 chains. Powered by Codex.io.

- **URL**: https://apify.com/constructive\_calm/mev-pair-scanner.md
- **Developed by:** [Omar Eldeeb](https://apify.com/constructive_calm) (community)
- **Categories:** Developer tools, Automation, Integrations
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 2 bookmarks
- **User rating**: 5.00 out of 5 stars

## Pricing

from $50.00 / 1,000 pair scanneds

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

Learn more: https://docs.apify.com/platform/actors/running/actors-in-store#pay-per-event

## What's an Apify Actor?

Actors are a software tools running on the Apify platform, for all kinds of web data extraction and automation use cases.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.
Actors are written with capital "A".

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.
The best way to integrate Actors is as follows.

In JavaScript/TypeScript projects, use official [JavaScript/TypeScript client](https://docs.apify.com/api/client/js.md):

```bash
npm install apify-client
```

In Python projects, use official [Python client library](https://docs.apify.com/api/client/python.md):

```bash
pip install apify-client
```

In shell scripts, use [Apify CLI](https://docs.apify.com/cli/docs.md):

````bash
# MacOS / Linux
curl -fsSL https://apify.com/install-cli.sh | bash
# Windows
irm https://apify.com/install-cli.ps1 | iex
```bash

In AI frameworks, you might use the [Apify MCP server](https://docs.apify.com/platform/integrations/mcp.md).

If your project is in a different language, use the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).


# README

## MEV Risk Scanner — DEX Sandwich + Fee Intel

**Per-pair MEV exposure, sandwich-attack rate, and fee-regime classification across 133 chains. Powered by Codex.io.**

The first Apify actor that surfaces MEV intelligence per DEX pair. While other crypto scrapers stop at price + volume, this one measures *what your trade actually costs* — gas vs builder tips vs LP fees, MEV-to-total-fees ratio, sandwich-attack frequency, and "safer trading windows" derived from hourly time series. Built on Codex.io, with optional AI verdicts via Gemini for non-technical traders.

### Why MEV intelligence matters

In 2025, sandwich attacks extracted **~$500M from Solana traders alone**, and individual high-profile losses on Ethereum reached six figures (the March 2025 stablecoin-swap loss of $215K on Uniswap V3 is one example). Yet no Apify actor exposes the underlying data — `mevRiskLevel`, sandwich rate per transaction, or fee decomposition — that would let traders avoid those pools or time their trades.

This actor closes that gap. For a given pair, you see:

- Whether it's **MEV-dominated, gas-dominated, or pool-fee-dominated**
- The **% of fees that go to MEV builders** (Ethereum) or Jito tips (Solana)
- The **sandwich-attack rate per transaction** and an estimated 24h sandwich count
- A **complete fee breakdown**: gas, priority fees, builder tips (MEV), pool/LP fees, L1 data fees (L2 rollups only)
- **24 hourly bars** of OHLCV + the same MEV/fee fields per bar — pinpoints which hours are safest to trade

### Why use this actor

- **Unique data on Apify** — no other actor exposes MEV/fee/sandwich fields. Codex's API is the only consumer-accessible source for these and this is the only Apify wrapper.
- **133 chains** — Ethereum, Solana, Base, BSC, Arbitrum, Optimism, Polygon, Avalanche, Sui, Aptos, HyperEVM, Monad, and 120+ more. Cross-chain comparisons in a single run.
- **Three modes in one actor** — scan specific pairs you care about, scan a token's top pools, or discover the most MEV-toxic pools chain-wide.
- **Per-row data quality flags** — every output row includes a `data_availability` map showing which fields populated for that pool. No false zeros.
- **Optional AI verdict** (Gemini Flash) — turns the raw numbers into one short trader-language sentence per pair: "Medium MEV, 24% of fees are MEV, avoid this pool unless using a private mempool."
- **Bulk CSV / JSON export** — works with everything Apify already supports: scheduled runs, webhooks, integrations.

### Modes

#### `scan-pair` — direct DEX pool scan
You provide a list of pair addresses; we return MEV intel + 24h hourly bars for each. Use when you already know which pool(s) to check (e.g. before a large trade).

#### `scan-token` — top pools for a token
You provide a token address; we discover its top-volume DEX pools (filtered by liquidity), and scan each. Use to compare MEV exposure across a token's pools — same token / different pools often have very different MEV profiles.

#### `discover-mev` — find the most MEV-toxic pools
We scan top-volume pools across the chains you specify and rank them by MEV risk (high → medium → low) then MEV-to-fees ratio. Use as a daily MEV-leaderboard or to flag emerging high-toxicity pools.

### How to use

1. Click **Try for free** and open the input form.
2. Pick a **mode**:
   - `Scan a token's top pools` (recommended starting mode) — paste any ERC-20 or SPL token address.
   - `Scan specific DEX pools` — paste one or more pool addresses.
   - `Discover the most MEV-toxic pools` — pick chains and a min-liquidity floor.
3. **Address format is forgiving** — you don't need to type a chain prefix:
   - Bare `0x...` addresses use the **Default chain for bare 0x addresses** dropdown (defaults to Ethereum). Switch it to `base`, `arbitrum`, `optimism`, etc. for a non-Ethereum EVM run.
   - Bare Solana base58 addresses (like `DezXAZ8z7PnrnRJjz3wXBoRgixCa6xjnB7YaB1pPB263`) auto-detect as Solana — no setting needed.
   - For mixed-chain runs, override per-row with `chain:address` (e.g. `base:0x4200...` next to `ethereum:0xc02aaa...`).
4. Optionally enable `Add AI trader verdict` for a 1-line trader summary per pool (charges an extra `ai-verdict` event).
5. Click **Start**. Most runs complete in 5–30 seconds.
6. Open the **Dataset** tab for results. Two views are configured: an **Overview** table with the MEV summary, and a **Fee breakdown** table with the full fee decomposition.

### Quick start recipes

Copy any of these directly into the input form (switch to JSON tab) for an instant working run.

#### 🟢 First-time test — minimum cost, instant feedback
```json
{ "mode": "scan-token", "tokens": ["0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2"], "max_pairs_per_token": 1, "max_results": 1 }
````

Scans the top WETH pool on Ethereum. ~1 pair-scanned event ≈ $0.05. Returns full MEV intel + 25 hourly bars.

#### 🟡 Memecoin MEV check (Solana)

```json
{ "mode": "scan-token", "tokens": ["DezXAZ8z7PnrnRJjz3wXBoRgixCa6xjnB7YaB1pPB263", "EKpQGSJtjMFqKZ9KQanSqYXRcF8fBopzLHYxdM65zcjm"], "max_pairs_per_token": 2, "max_results": 4, "enable_ai_verdict": true }
```

BONK + WIF top pools on Solana with AI verdicts. ~4 pair-scanned + 4 ai-verdict ≈ $0.28.

#### 🔵 Base ecosystem scan (use the default chain dropdown)

```json
{ "mode": "scan-token", "default_evm_chain": "base", "tokens": ["0x4200000000000000000000000000000000000006", "0x833589fcd6edb6e08f4c7c32d4f71b54bda02913"], "max_pairs_per_token": 2, "max_results": 4 }
```

WETH + USDC top pools on Base. Bare 0x addresses → resolved to Base via the dropdown.

#### 🔴 Daily MEV-toxic leaderboard

```json
{ "mode": "discover-mev", "discover_chains": ["ethereum", "solana", "base", "arbitrum"], "discover_min_liquidity_usd": 1000000, "max_results": 10, "enable_ai_verdict": true }
```

Top 10 most MEV-toxic pools across 4 chains, ranked high → low. ~10 pair-scanned + 10 ai-verdict ≈ $0.72. Schedule daily for a leaderboard.

#### 🟣 Pre-trade safety check on a known pool

```json
{ "mode": "scan-pair", "pairs": ["0xe0554a476a092703abdb3ef35c80e0d76d32939f"], "max_results": 1, "bar_resolution": "5", "enable_ai_verdict": true }
```

USDC/WETH Uniswap V3 0.05% pool, 5-minute bars (~289 bars), AI verdict. Run this before placing a large trade.

### Address format rules

| You paste | Actor uses |
|---|---|
| `0xc02aaa39...` (40-hex EVM) | The chain you picked in **Default chain for bare 0x addresses** (defaults to Ethereum) |
| `DezXAZ8z7Pnrn...` (Solana base58) | Auto-detected as Solana, regardless of the dropdown |
| `chain:address` (explicit) | The chain you typed — overrides the dropdown for that row |

Mix any of these in the same input — the actor logs which chain it picked for each address so you can verify before reading the output.

### Input reference

See the **Input** tab for the full form. Quick-start recipes are above; below is the full schema.

#### `mode` (required)

Which workflow to run: `scan-token`, `scan-pair`, or `discover-mev`. See the [Modes](#modes) section.

#### `default_evm_chain`

Default chain used when you paste a bare `0x...` EVM address (no `chain:` prefix). Defaults to `ethereum`. Switch to `base`, `arbitrum`, `optimism`, etc. for non-Ethereum scans without needing per-row prefixes. Solana base58 addresses always auto-detect regardless of this setting.

Available values: `ethereum`, `base`, `arbitrum`, `optimism`, `polygon`, `bsc`, `avalanche`, `linea`, `scroll`, `mantle`, `blast`, `zksync`, `metis`, `celo`, `fantom`, `cronos`, `moonbeam`, `moonriver`, `ronin`, `sei`, `monad`, `hyper-evm`.

#### `tokens` (used by `scan-token` mode)

List of token addresses, one per row. Bare addresses use `default_evm_chain` for EVM, auto-detect for Solana. `chain:address` overrides per row.

#### `max_pairs_per_token`

How many of each token's most-active pools to scan. Default 3, max 20.

#### `pairs` (used by `scan-pair` mode)

List of pool addresses, one per row. Same address rules as `tokens`.

#### `discover_chains` (used by `discover-mev` mode)

Canonical chain names — one per row. The actor scans each chain's top-volume pools (filtered by liquidity below) and ranks them by MEV risk. 133 chains supported; common picks: `ethereum`, `solana`, `base`, `bsc`, `arbitrum`, `optimism`, `polygon`, `avalanche`.

#### `discover_min_liquidity_usd`

Minimum pool liquidity for `discover-mev`. Default $1M. Lower for memecoin scans, higher for blue-chip-only.

#### `max_results`

Total pools returned per run, hard cap 20. Each pool fires one `pair-scanned` event ($0.05).

#### `bar_resolution`

`5` / `15` / `60` / `240` / `1D` — granularity of the 24h time-series bars. `60` (1h) is recommended and returns ~25 bars/24h. Tighter resolutions (`5`, `15`) surface intraday MEV spikes; `1D` collapses to a 1–2 bar overview.

#### `enable_ai_verdict`

When true, adds a 1-line trader-language verdict per pool via Gemini Flash (extra `ai-verdict` event @ $0.02 per pool).

#### Chain names accepted

Beyond the EVM chains in the dropdown above: `solana`, `sui`, `aptos`, plus any of the 133 supported networks via raw Codex slug (e.g. `tron`, `kaia`, `tac`). Network IDs are looked up dynamically at startup, so newly-added Codex chains work without an actor update. The full list prints in your run log.

### Output

Each dataset row is a `NormalizedPair`:

```jsonc
{
    "pair_address": "0xe0554a476a092703abdb3ef35c80e0d76d32939f",
    "chain": "ethereum",
    "network_id": 1,
    "exchange": "UniswapV3",
    "token0_symbol": "USDC",
    "token0_address": "0xa0b86991...",
    "token1_symbol": "WETH",
    "token1_address": "0xc02aaa39...",

    // 24h aggregates
    "volume_24h_usd": 76851555.5,
    "liquidity_usd": 2761557.8,
    "transactions_24h": 15589,

    // MEV intelligence (24h dominant)
    "mev_risk_level": "medium",                // low | medium | high | null
    "mev_to_total_fees_ratio_24h": 0.248,      // 24.8% of fees are MEV builder tips
    "fee_regime_24h": "mev-dominated",         // mev-dominated | gas-dominated | pool-fee-dominated
    "sandwich_rate_24h": 0.00179,              // 0.18% of transactions sandwiched
    "estimated_sandwich_attacks_24h": 28,

    "fees_24h": {
        "total_usd": 28820.5,
        "base_fees_usd": 4844.5,        // gas
        "priority_fees_usd": 8798.3,
        "builder_tips_usd": 7503.5,     // MEV bribes
        "pool_fees_usd": 7674.1,        // LP fees
        "l1_data_fees_usd": null        // populated on L2 rollups only
    },

    "cost_to_trade_24h": {
        "average_cost_per_trade_usd": 1.78,
        "fee_to_volume_ratio": 0.00038,
        "gas_per_volume": 0.000186
    },

    // Per-field coverage map. 1 = fully populated; <1 = partial; null = absent.
    "data_availability": {
        "totalFees": 1, "baseFees": 1, "priorityFees": 1, "builderTips": 1,
        "poolFees": 1, "l1DataFees": 0, "feeRegimeClassification": 1,
        "mevRiskLevel": 1, "mevToTotalFeesRatio": 1, "sandwichRate": 1,
        "gasPerVolume": 1, "feeToVolumeRatio": 1,
        "volume": 1, "liquidity": 1, "transactions": 1
    },

    "bars_hourly": [ /* 25 hourly bars with full MEV/fee/OHLCV columns */ ],
    "safer_trading_windows_utc": [ /* timestamps where MEV risk was 'low' */ ],
    "ai_verdict": "Medium MEV, 24% of fees are MEV, avoid this pool unless using a private mempool.",
    "fetched_at": "2026-04-30T13:00:07.235Z"
}
```

#### Reading `data_availability`

Codex doesn't index every chain or pool with the same depth. Field availability varies, especially on Solana where Jito-bundle data is per-pool. The map shows what populated *for this row*, so you can distinguish "no MEV detected" (zero) from "data unavailable" (null). Use this to filter or weight your analysis.

#### `safer_trading_windows_utc`

Hour-of-day timestamps (UTC) where the bar's `mev_risk_level` was `"low"` over the last 24h. Empty array on permanently-MEV-dominated pools.

### Pricing

This actor uses pay-per-event pricing.

| Event | Title | When it fires | Price |
|---|---|---|---|
| `apify-actor-start` | Actor start | Once per run (auto-fired by Apify, per GB memory) | $0.02 |
| `pair-scanned` | **Pair scanned (primary)** | Per DEX pair returned with full intel + 24h hourly bars | $0.05 |
| `ai-verdict` | AI verdict | Per Gemini-generated trader verdict (only when `enable_ai_verdict=true`) | $0.02 |

**Worked examples:**

- Scan one specific pair (no AI): $0.07
- Scan 5 pools of a token with AI: $0.02 + 5×$0.05 + 5×$0.02 = $0.37
- Discover top-20 MEV-toxic pools across 3 chains with AI: $0.02 + 20×$0.05 + 20×$0.02 = $1.42

### Limits and edge cases

- **Hard cap of 20 pairs per run** (`max_results` setting). Designed for fast, focused scans rather than bulk dumps. Use scheduling for higher volume.
- **Per-pool field availability varies on Solana** — some Raydium/Orca pools return only `sandwichRate`, others return everything. Codex's Jito-bundle indexing isn't uniform across all pools. The `data_availability` map flags this per row.
- **Builder tips are zero on Base / Arbitrum / Optimism / Polygon / other L2s** — these chains don't have an MEV-builder market like Ethereum mainnet, so `builderTips` is genuinely zero (not missing data). `mevToTotalFeesRatio` will then also be null because the math has no numerator.
- **`l1DataFees` populates only on L2 rollups** (Base, Arbitrum, Optimism, etc.). On L1 chains it's null by design.
- **Pair indexing churn** — DEX pools rotate and are sometimes deprecated. If you scan an inactive pool address, you'll get an empty result with a warning. Use `scan-token` mode if you want the actor to discover currently-active pools.
- **Free-tier safety on Solana addresses** — the actor preserves case for Solana base58 addresses. Lowercasing breaks them. Just paste the address as-is.

### Use cases

- **Defensive trading** — before placing a large swap, scan the pool and check `mev_to_total_fees_ratio_24h`. If high, route through a private mempool (Flashbots Protect, MEV Blocker).
- **DAO treasury management** — scheduled daily run on `discover-mev` for the chains your treasury is exposed to. Alert on new high-MEV pools where you have liquidity.
- **Market-maker pool selection** — when picking which DEX pool to LP into, prefer `pool-fee-dominated` regime over `mev-dominated`. The fee breakdown shows which pools genuinely return fees to LPs vs. leak them to MEV builders.
- **MEV research / academic** — bulk export hourly bars across many pools to study MEV intensity over time, validator dependence, etc.
- **Trader copy-bot defense** — before copying a trade signal, check if the source pool has historical sandwich activity.

### Powered by

[Codex.io](https://www.codex.io/) — the GraphQL data API for 133 blockchain networks. This actor is a thin orchestration layer on top: it handles input validation, multi-pair fan-out, output normalization, AI enrichment, and Apify-native dataset/scheduling integration. All on-chain data sourced via Codex.

### Limitations vs. our roadmap

What this v1 doesn't do (yet):

- **Wallet-level smart-money tracking** — Codex's wallet queries (`filterWallets`, `detailedWalletStats`) require their Growth plan. Roadmap item once we upgrade.
- **Real-time webhook alerts** — currently scheduled-poll-based via Apify cron. Native Codex webhooks are a v2 feature.
- **Pre-trade slippage simulation** — getting a quote for a hypothetical trade size and seeing how MEV/slippage scales is a v1.x candidate.
- **Cross-pair "safer hours" consensus** — when multiple pools are scanned, computing a chain-wide low-MEV window. v1.x.

### Changelog

- **0.1.11** — Added `default_evm_chain` dropdown to the input form. Bare `0x` addresses now resolve to the dropdown's chain (defaults to ethereum) instead of always defaulting to ethereum. Pick `base` once and paste bare Base addresses for the whole run.
- **0.1.10** — Auto-detect chain when address shape is unambiguous: bare `0x[40 hex]` → ethereum, bare Solana base58 → solana. Helpful warnings when format is unparseable.
- **0.1.9** — Cleaner section names ("Choose what to scan", "Tokens — for the 'Scan a token's top pools' mode", etc.) replacing mechanical "Step 2A/B/C". Added `items: { type: "string" }` for proper stringList rendering.
- **0.1.8** — Switched pair/token inputs from raw JSON-array editor to `stringList` with `chain:address` strings. Backward-compat parser still accepts legacy `{address, chain}` object format.
- **0.1.7** — Store-ready README.
- **0.1.6** — Removed redundant manual `actor-start` charge; Apify auto-fires `apify-actor-start` per GB memory.
- **0.1.5** — Solana base58 addresses now case-preserved (EVM hex still lowercased). Fixes empty-result bug on `scan-token` for Solana / Sui / Aptos tokens.
- **0.1.4** — Disabled Gemini's default thinking mode (`thinkingBudget: 0`) and raised output budget to 120 tokens. AI verdicts now consistently produce full trader-language sentences instead of two-word labels.
- **0.1.3** — Logo + dataset\_schema views (overview + fee breakdown).
- **0.1.2** — Initial public build.

# Actor input Schema

## `mode` (type: `string`):

Pick the workflow that matches your goal. Each mode uses a different input section below — only fill in the section labelled for the mode you chose.

## `default_evm_chain` (type: `string`):

When you paste a bare EVM address (no `chain:` prefix), use this chain. Defaults to ethereum — change to base / arbitrum / etc. if you're scanning a non-Ethereum EVM chain. Solana base58 addresses always auto-detect as solana regardless of this setting.

## `tokens` (type: `array`):

**Used by mode: Scan a token's top pools.**

One token per row. Just paste an address — no prefix needed.

Quick-start examples (copy + paste):
• `0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2` (WETH on whichever EVM chain you picked above)
• `DezXAZ8z7PnrnRJjz3wXBoRgixCa6xjnB7YaB1pPB263` (BONK on Solana — auto-detected)
• `EKpQGSJtjMFqKZ9KQanSqYXRcF8fBopzLHYxdM65zcjm` (WIF on Solana)

Mixing chains in one run: prefix with `chain:` to override the default — e.g. `base:0x4200000000000000000000000000000000000006`.

The actor discovers each token's top-volume DEX pools (filtered by liquidity) and scans them.

## `max_pairs_per_token` (type: `integer`):

How many of each token's most-active pools to scan. Higher = more coverage but more `pair-scanned` events charged.

## `pairs` (type: `array`):

**Used by mode: Scan specific DEX pools.**

One pool address per row. Same address rules as tokens — bare 0x uses the default EVM chain you picked above; Solana base58 auto-detects; explicit `chain:address` overrides.

Quick-start examples:
• `0xe0554a476a092703abdb3ef35c80e0d76d32939f` (USDC/WETH Uniswap V3 on Ethereum)
• `base:0xb2cc224c1c9fee385f8ad6a55b4d94e92359dc59` (WETH/USDC on Base)

Use this when you already know which pool to check (e.g. before placing a large trade).

## `discover_chains` (type: `array`):

**Used by mode: Discover the most MEV-toxic pools.**

Canonical chain names — one per row. The actor scans each chain's top-volume pools (filtered by liquidity below) and ranks them by MEV risk.

Most active chains for MEV: `ethereum`, `solana`, `base`, `bsc`, `arbitrum`, `optimism`, `polygon`, `avalanche`.

133 chains supported total. Run the actor once to see the full list in the log.

## `discover_min_liquidity_usd` (type: `integer`):

Skip pools below this liquidity. Default $1M filters out test pools and abandoned tokens. Lower this for memecoin-focused scans, raise for blue-chip-only.

## `max_results` (type: `integer`):

Total pools returned per run. Each pool fires one `pair-scanned` event ($0.05). Free-tier safety: capped at 20.

## `bar_resolution` (type: `string`):

How fine-grained the 24h time-series bars should be. Tighter resolutions surface intraday MEV spikes; coarser ones give a cleaner trend.

## `enable_ai_verdict` (type: `boolean`):

Adds a 1-line trader-language verdict per pool — e.g. "Medium MEV, 24% of fees are MEV, avoid this pool unless using a private mempool." Charges an extra `ai-verdict` event ($0.02) per pool returned. Off by default.

## Actor input object example

```json
{
  "mode": "scan-token",
  "default_evm_chain": "ethereum",
  "tokens": [
    "0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2"
  ],
  "max_pairs_per_token": 3,
  "pairs": [
    "0xe0554a476a092703abdb3ef35c80e0d76d32939f"
  ],
  "discover_chains": [
    "ethereum",
    "solana",
    "base"
  ],
  "discover_min_liquidity_usd": 1000000,
  "max_results": 5,
  "bar_resolution": "60",
  "enable_ai_verdict": false
}
```

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "tokens": [
        "0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2"
    ],
    "pairs": [
        "0xe0554a476a092703abdb3ef35c80e0d76d32939f"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("constructive_calm/mev-pair-scanner").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = {
    "tokens": ["0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2"],
    "pairs": ["0xe0554a476a092703abdb3ef35c80e0d76d32939f"],
}

# Run the Actor and wait for it to finish
run = client.actor("constructive_calm/mev-pair-scanner").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print("💾 Check your data here: https://console.apify.com/storage/datasets/" + run["defaultDatasetId"])
for item in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "tokens": [
    "0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2"
  ],
  "pairs": [
    "0xe0554a476a092703abdb3ef35c80e0d76d32939f"
  ]
}' |
apify call constructive_calm/mev-pair-scanner --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "command": "npx",
            "args": [
                "mcp-remote",
                "https://mcp.apify.com/?tools=constructive_calm/mev-pair-scanner",
                "--header",
                "Authorization: Bearer <YOUR_API_TOKEN>"
            ]
        }
    }
}

```

## OpenAPI specification

```json
{
    "openapi": "3.0.1",
    "info": {
        "title": "MEV Risk Scanner - DEX Sandwich + Fee Intel",
        "description": "Per-pair MEV exposure, sandwich-attack rate, and fee-regime classification across 133 chains. Powered by Codex.io.",
        "version": "0.1",
        "x-build-id": "Z5uYeEE4P4VpceY5Z"
    },
    "servers": [
        {
            "url": "https://api.apify.com/v2"
        }
    ],
    "paths": {
        "/acts/constructive_calm~mev-pair-scanner/run-sync-get-dataset-items": {
            "post": {
                "operationId": "run-sync-get-dataset-items-constructive_calm-mev-pair-scanner",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor, waits for its completion, and returns Actor's dataset items in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        },
        "/acts/constructive_calm~mev-pair-scanner/runs": {
            "post": {
                "operationId": "runs-sync-constructive_calm-mev-pair-scanner",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor and returns information about the initiated run in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/runsResponseSchema"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/acts/constructive_calm~mev-pair-scanner/run-sync": {
            "post": {
                "operationId": "run-sync-constructive_calm-mev-pair-scanner",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor, waits for completion, and returns the OUTPUT from Key-value store in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        }
    },
    "components": {
        "schemas": {
            "inputSchema": {
                "type": "object",
                "properties": {
                    "mode": {
                        "title": "What do you want to scan?",
                        "enum": [
                            "scan-token",
                            "scan-pair",
                            "discover-mev"
                        ],
                        "type": "string",
                        "description": "Pick the workflow that matches your goal. Each mode uses a different input section below — only fill in the section labelled for the mode you chose.",
                        "default": "scan-token"
                    },
                    "default_evm_chain": {
                        "title": "Default chain for bare 0x addresses",
                        "enum": [
                            "ethereum",
                            "base",
                            "arbitrum",
                            "optimism",
                            "polygon",
                            "bsc",
                            "avalanche",
                            "linea",
                            "scroll",
                            "mantle",
                            "blast",
                            "zksync",
                            "metis",
                            "celo",
                            "fantom",
                            "cronos",
                            "moonbeam",
                            "moonriver",
                            "ronin",
                            "sei",
                            "monad",
                            "hyper-evm"
                        ],
                        "type": "string",
                        "description": "When you paste a bare EVM address (no `chain:` prefix), use this chain. Defaults to ethereum — change to base / arbitrum / etc. if you're scanning a non-Ethereum EVM chain. Solana base58 addresses always auto-detect as solana regardless of this setting.",
                        "default": "ethereum"
                    },
                    "tokens": {
                        "title": "Tokens to analyze",
                        "type": "array",
                        "description": "**Used by mode: Scan a token's top pools.**\n\nOne token per row. Just paste an address — no prefix needed.\n\nQuick-start examples (copy + paste):\n• `0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2` (WETH on whichever EVM chain you picked above)\n• `DezXAZ8z7PnrnRJjz3wXBoRgixCa6xjnB7YaB1pPB263` (BONK on Solana — auto-detected)\n• `EKpQGSJtjMFqKZ9KQanSqYXRcF8fBopzLHYxdM65zcjm` (WIF on Solana)\n\nMixing chains in one run: prefix with `chain:` to override the default — e.g. `base:0x4200000000000000000000000000000000000006`.\n\nThe actor discovers each token's top-volume DEX pools (filtered by liquidity) and scans them.",
                        "items": {
                            "type": "string"
                        },
                        "default": []
                    },
                    "max_pairs_per_token": {
                        "title": "Top pools per token",
                        "minimum": 1,
                        "maximum": 20,
                        "type": "integer",
                        "description": "How many of each token's most-active pools to scan. Higher = more coverage but more `pair-scanned` events charged.",
                        "default": 3
                    },
                    "pairs": {
                        "title": "DEX pool addresses",
                        "type": "array",
                        "description": "**Used by mode: Scan specific DEX pools.**\n\nOne pool address per row. Same address rules as tokens — bare 0x uses the default EVM chain you picked above; Solana base58 auto-detects; explicit `chain:address` overrides.\n\nQuick-start examples:\n• `0xe0554a476a092703abdb3ef35c80e0d76d32939f` (USDC/WETH Uniswap V3 on Ethereum)\n• `base:0xb2cc224c1c9fee385f8ad6a55b4d94e92359dc59` (WETH/USDC on Base)\n\nUse this when you already know which pool to check (e.g. before placing a large trade).",
                        "items": {
                            "type": "string"
                        },
                        "default": []
                    },
                    "discover_chains": {
                        "title": "Chains to scan",
                        "type": "array",
                        "description": "**Used by mode: Discover the most MEV-toxic pools.**\n\nCanonical chain names — one per row. The actor scans each chain's top-volume pools (filtered by liquidity below) and ranks them by MEV risk.\n\nMost active chains for MEV: `ethereum`, `solana`, `base`, `bsc`, `arbitrum`, `optimism`, `polygon`, `avalanche`.\n\n133 chains supported total. Run the actor once to see the full list in the log.",
                        "items": {
                            "type": "string"
                        },
                        "default": [
                            "ethereum",
                            "solana",
                            "base"
                        ]
                    },
                    "discover_min_liquidity_usd": {
                        "title": "Minimum pool liquidity (USD)",
                        "minimum": 0,
                        "type": "integer",
                        "description": "Skip pools below this liquidity. Default $1M filters out test pools and abandoned tokens. Lower this for memecoin-focused scans, raise for blue-chip-only.",
                        "default": 1000000
                    },
                    "max_results": {
                        "title": "Maximum pools in output (hard cap 20)",
                        "minimum": 1,
                        "maximum": 20,
                        "type": "integer",
                        "description": "Total pools returned per run. Each pool fires one `pair-scanned` event ($0.05). Free-tier safety: capped at 20.",
                        "default": 5
                    },
                    "bar_resolution": {
                        "title": "Hourly bar granularity",
                        "enum": [
                            "5",
                            "15",
                            "60",
                            "240",
                            "1D"
                        ],
                        "type": "string",
                        "description": "How fine-grained the 24h time-series bars should be. Tighter resolutions surface intraday MEV spikes; coarser ones give a cleaner trend.",
                        "default": "60"
                    },
                    "enable_ai_verdict": {
                        "title": "Add AI trader verdict (Gemini Flash)",
                        "type": "boolean",
                        "description": "Adds a 1-line trader-language verdict per pool — e.g. \"Medium MEV, 24% of fees are MEV, avoid this pool unless using a private mempool.\" Charges an extra `ai-verdict` event ($0.02) per pool returned. Off by default.",
                        "default": false
                    }
                }
            },
            "runsResponseSchema": {
                "type": "object",
                "properties": {
                    "data": {
                        "type": "object",
                        "properties": {
                            "id": {
                                "type": "string"
                            },
                            "actId": {
                                "type": "string"
                            },
                            "userId": {
                                "type": "string"
                            },
                            "startedAt": {
                                "type": "string",
                                "format": "date-time",
                                "example": "2025-01-08T00:00:00.000Z"
                            },
                            "finishedAt": {
                                "type": "string",
                                "format": "date-time",
                                "example": "2025-01-08T00:00:00.000Z"
                            },
                            "status": {
                                "type": "string",
                                "example": "READY"
                            },
                            "meta": {
                                "type": "object",
                                "properties": {
                                    "origin": {
                                        "type": "string",
                                        "example": "API"
                                    },
                                    "userAgent": {
                                        "type": "string"
                                    }
                                }
                            },
                            "stats": {
                                "type": "object",
                                "properties": {
                                    "inputBodyLen": {
                                        "type": "integer",
                                        "example": 2000
                                    },
                                    "rebootCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "restartCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "resurrectCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "computeUnits": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            },
                            "options": {
                                "type": "object",
                                "properties": {
                                    "build": {
                                        "type": "string",
                                        "example": "latest"
                                    },
                                    "timeoutSecs": {
                                        "type": "integer",
                                        "example": 300
                                    },
                                    "memoryMbytes": {
                                        "type": "integer",
                                        "example": 1024
                                    },
                                    "diskMbytes": {
                                        "type": "integer",
                                        "example": 2048
                                    }
                                }
                            },
                            "buildId": {
                                "type": "string"
                            },
                            "defaultKeyValueStoreId": {
                                "type": "string"
                            },
                            "defaultDatasetId": {
                                "type": "string"
                            },
                            "defaultRequestQueueId": {
                                "type": "string"
                            },
                            "buildNumber": {
                                "type": "string",
                                "example": "1.0.0"
                            },
                            "containerUrl": {
                                "type": "string"
                            },
                            "usage": {
                                "type": "object",
                                "properties": {
                                    "ACTOR_COMPUTE_UNITS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_WRITES": {
                                        "type": "integer",
                                        "example": 1
                                    },
                                    "KEY_VALUE_STORE_LISTS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_INTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_EXTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_SERPS": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            },
                            "usageTotalUsd": {
                                "type": "number",
                                "example": 0.00005
                            },
                            "usageUsd": {
                                "type": "object",
                                "properties": {
                                    "ACTOR_COMPUTE_UNITS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_WRITES": {
                                        "type": "number",
                                        "example": 0.00005
                                    },
                                    "KEY_VALUE_STORE_LISTS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_INTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_EXTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_SERPS": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}
```
