Real-time token discovery
` lowercased) and pass it explicitly — same advice as for Gains. * **Gains `marketId` shape differs per chain.** Mainnet uses `gains--usd` (e.g. `gains-btc-usd`); Arbitrum Sepolia carries the collateral suffix (e.g. `gains-hype-usd-usdc`). Read the canonical `marketId` straight from the `/pairs` response row instead of constructing it client-side. * **Response envelope shape.** Most endpoints return `{ data: { ... } }` (no `success` flag) on 2xx. The execute-v2 success body adds `success: true` inside `data`. Parse defensively: read `body.data`, then check for the action-specific fields you actually need. * **Reading state via the wallet provider.** See the prerequisites — embedded-wallet providers (Privy etc.) can return stale `nonce` / `feeData`. Always read via a chain RPC. ## Common errors Errors you will hit while wiring the flow, with the typical cause and the fix: | Error (verbatim from `execute-v2` / RPC) | Cause | Fix | | - | - | - | | `ERC20: transfer amount exceeds allowance` (Gains 400) | USDC `approve(spender, …)` never executed for this wallet | Run the `ensureGainsAllowance` helper from the Prerequisites section before the first Gains order. | | `INTRINSIC_GAS_TOO_LOW` | `gasLimit` left at 0 or below the chain's minimum | Set `gasLimit: 1_500_000n` for Gains, or take `max(estimate * 2, 1_500_000n)`. | | `NONCE_TOO_LOW` | Stale nonce — typically reading from an embedded-wallet provider that defaults to 0 | Fetch `eth_getTransactionCount(addr, "pending")` from a real chain RPC. | | `TRANSACTION_UNDERPRICED` | `maxFeePerGas` not high enough to survive base-fee drift between build and execute | Use `feeData.maxFeePerGas * 3n` (Arbitrum / Base). | | `Cannot POST /api/2/perp/...` (404) | Hit the production gateway | Switch to `https://api.mobula.io` (perp routes are on the demo gateway today). | | `payloadStr metadata does not match request metadata` | Mutated `action`/`dex`/`chainId`/`transport`/`marketId` between build and execute | Forward the envelope metadata fields verbatim from the build response. | | `signature signer does not match payload.from` | Execute-v2 signed by a different EOA than `payload.data.from` | Sign execute-v2 with the same wallet that the envelope was built for. | | `signature already used` | Replay of a 30s-window signature | Re-sign with a fresh `timestamp` — every build and execute call needs its own signature. | | `timestamp expired` | Build or execute timestamp >30s from server clock | Re-sign immediately before the request — do not pre-compute. | | `could not build create-order payload` + `"No market matching base/quote"` | `quote: 'USDC'` sent to a Gains route | Use `quote: 'USD'` on Gains, or omit `quote` and pass `marketId: 'gains- -usd'`. | | `Failed to broadcast signed transaction on ` | RPC rejected `signedTx` (often a fee/nonce/gas issue) | Inspect the `errors[]` list in the response body — it carries the upstream RPC reason. | *** ## Related # Retrieve All Perp Markets Source: https://docs.mobula.io/cookbooks/retrieve-perp-markets Fetch the full catalog of tradable perpetual markets indexed by Mobula (Gains Network + Lighter) with a single GET request to /api/2/perp/pairs. Mobula indexes perp markets from **Gains Network** and **Lighter**. To enumerate them, call the **Perp Pairs** endpoint. It returns every **tradable** market in one request — no pagination, no per-DEX normalization needed. Preview fills and pick a DEX before building the payload. Full execute-v2 reference including signature and error table. Poll status of async deposits. List all tradable perp markets via the Perp Pairs endpoint. Live state — open positions + pending orders. Live lifecycle — fills, liquidations, TP/SL, cancels. Confirm Lighter / Gains upstreams are healthy before routing. Fee breakdown per DEX with worked examples. Only **tradable** markets are returned. Disabled, closed, or delisted markets are filtered out server-side, so anything absent from the response is not tradable. There is no separate "disabled" flag to check. *** ## Endpoint shape | | | | - | - | | **URL** | `GET https://api.mobula.io/api/2/perp/pairs` | | **Auth header** | `Authorization:` (raw key, no `Bearer`) | | **Query** | `chain` (optional) — filter to a single chain/venue | | **Response** | `{ "data": [ ...pairs ] }` | ### Query parameter | Parameter | Type | Required | Description | | - | - | - | - | | `chain` | enum | No | Restrict the result to one chain/venue. Omit it to get **every** chain and DEX in one list. | **Accepted `chain` values** | Value | Meaning | DEX | | - | - | - | | `arbitrum` | Gains markets on Arbitrum | gains | | `base` | Gains markets on Base | gains | | `arbitrum-sepolia` | Gains markets on Arbitrum Sepolia (test) | gains | | `lighter` | Lighter markets | lighter | *** ## Quick start — curl ```bash theme={null} # All markets (every chain + DEX) curl "https://api.mobula.io/api/2/perp/pairs" \ -H "Authorization: YOUR_API_KEY" # Single chain — Arbitrum (Gains) curl "https://api.mobula.io/api/2/perp/pairs?chain=arbitrum" \ -H "Authorization: YOUR_API_KEY" # Lighter only curl "https://api.mobula.io/api/2/perp/pairs?chain=lighter" \ -H "Authorization: YOUR_API_KEY" ``` *** ## Response ```json theme={null} { "data": [ { "name": "BTC/USD", "baseToken": "BTC", "quoteToken": "USD", "minLeverage": 1.1, "maxLeverage": 200, "dex": "gains", "chain": "arbitrum", "assetClass": "crypto", "dexMarketId": 0, "socialUrl": "", "pairFullName": "BTC", "percentageChange24h": -2.98, "price": 71571.74, "logo": "https://metadata.mobula.io/assets/logos/100001656.webp" } ] } ``` `data` is the full list of tradable markets — there is no pagination. ### Market model | Field | Type | Description | | - | - | - | | `name` | string | Human-readable `base/quote` label, e.g. `"BTC/USD"`. | | `baseToken` | string | Base asset symbol, e.g. `"BTC"`. | | `quoteToken` | string | Quote asset symbol, e.g. `"USD"`. | | `minLeverage` | number | Minimum allowed leverage. | | `maxLeverage` | number | Maximum allowed leverage. Always `> 0` (disabled markets are excluded). | | `dex` | enum | `"gains"` or `"lighter"`. | | `chain` | enum | `"arbitrum"`, `"base"`, `"arbitrum-sepolia"`, or `"lighter"`. | | `assetClass` | enum | `"crypto"`, `"forex"`, `"stocks"`, `"indices"`, `"commodities"`, `"degen"`, or `"new"`. | | `dexMarketId` | integer (≥ 0) | The DEX's internal market id — Gains `pairIndex` / Lighter `market_id`. Use it when referencing the market in quote/execution calls. | | `socialUrl` | string | Reserved for a social/info URL. Currently empty. | | `pairFullName` | string | Full name of the market as reported by the DEX. | | `percentageChange24h` | number | 24h price change, in percent. | | `price` | number | Latest/mark price in USD (`0` if no price is currently available). | | `logo` | string \| null | Base-asset logo URL, or `null` when unknown. | *** ## TypeScript ```typescript theme={null} import axios from 'axios'; const PAIRS_URL = 'https://api.mobula.io/api/2/perp/pairs'; const API_KEY = process.env.MOBULA_API_KEY!; type PerpPair = { name: string; baseToken: string; quoteToken: string; minLeverage: number; maxLeverage: number; dex: 'gains' | 'lighter'; chain: 'arbitrum' | 'base' | 'arbitrum-sepolia' | 'lighter'; assetClass: 'crypto' | 'forex' | 'stocks' | 'indices' | 'commodities' | 'degen' | 'new'; dexMarketId: number; socialUrl: string; pairFullName: string; percentageChange24h: number; price: number; logo: string | null; }; async function fetchPerpPairs(chain?: PerpPair['chain']): Promise { const res = await axios.get<{ data: PerpPair[] }>(PAIRS_URL, { headers: { Authorization: API_KEY }, params: chain ? { chain } : undefined, }); return res.data.data; } // Every tradable market across all chains and DEXes const all = await fetchPerpPairs(); // Gains markets on Arbitrum only const arbitrum = await fetchPerpPairs('arbitrum'); console.log(`Total markets: ${all.length}`); ``` *** ## Common pitfalls * **`Bearer` prefix in the Authorization header.** Don't add it — pass the raw API key. * **Expecting disabled markets.** They are filtered out. If a market isn't in the response, it isn't tradable. * **Using `dexMarketId` across DEXes.** It is only unique within a `(dex, chain)`. Pair it with `dex`/`chain` when keying markets. *** ## Related *** ## Need help? Quote a perp position once you've picked a market. Submit signed payloads via `/2/perp/execute-v2`. Lighter / Gains uptime, probe results and maintenance windows. Indexed event shapes for perps. # Setup Trading View Charting Library JS for Crypto Source: https://docs.mobula.io/cookbooks/setup-trading-view-chart Learn how to setup a Trading View candle chart with crypto real time price updates, and historical candle chart. Mobula pair data API allows you to fetch real-time and historical price data for any on-chain pair. You can use this data to feed Trading View charting library. Fast support Community Enterprise Contact us **Live Demo**: See charts in action on [mtt.gg](https://mtt.gg) - try any token or pair page! **Full Source Code**: The complete TradingView implementation is open-source at [github.com/MobulaFi/MTT](https://github.com/MobulaFi/MTT) ### What you'll need 1. Access to trading view codebase repo (need manual approval from Trading View) 2. An API key from the [Dashboard](https://admin.mobula.io) (only for production use, you can use the API without an API key in development mode) 3. A react app (or any other framework) to display the chart *** ## Open Source Reference Implementation Before diving into the code, check out the production-ready implementation in the MTT (Mobula Trader Terminal) codebase: | File | Description | | - | - | | [`datafeed.tsx`](https://github.com/MobulaFi/MTT/blob/main/src/components/charts/datafeed.tsx) | Complete datafeed with REST + WebSocket OHLCV streaming | | [`index.tsx`](https://github.com/MobulaFi/MTT/blob/main/src/components/charts/index.tsx) | TradingView chart component with theme support | | [`token/page.tsx`](https://github.com/MobulaFi/MTT/blob/main/src/app/token/%5Bblockchain%5D/%5Baddress%5D/page.tsx) | Token page with chart integration | | [`pair/page.tsx`](https://github.com/MobulaFi/MTT/blob/main/src/app/pair/%5Bblockchain%5D/%5Baddress%5D/page.tsx) | Pair page with chart integration | **Live Examples**: * Token page: [mtt.gg/token/solana:solana/So11111111111111111111111111111111111111112](https://mtt.gg/token/solana:solana/So11111111111111111111111111111111111111112) * Pair page: [mtt.gg/pair/solana:solana/YOUR\_PAIR\_ADDRESS](https://mtt.gg/pair/solana:solana/YOUR_PAIR_ADDRESS) *** ### Walkthrough*** ## Token Page vs Pair Page The MTT terminal has two types of pages that use charts differently: ### Token Page (`/token/[blockchain]/[address]`) Uses the **asset mode** which automatically routes to the highest liquidity pool: ```typescript theme={null} // Token page passes isPair: false Pick your asset symbol, name or address. If it is a symbol/name, make sure to check case sensitivity and to respect the asset name as listed on Mobula curated token list (explorable [here](https://mobula.io)). If it is an address, make sure to check the blockchain supported (check [here](/rest-api-reference/endpoint/blockchains) for the full list) and to respect the blockchain ID format. You can also use pair address directly (if using asset, we will route to the largest liquidity pool for this asset). Let's first setup the main chart component - you must host the trading view lib files inside the public folder of your app, in our example, we host them at static/charting\_library. Here's a simplified version. For the full production implementation with theme support, loading states, and tool persistence, see the [MTT chart component](https://github.com/MobulaFi/MTT/blob/main/src/components/charts/index.tsx). ```typescript theme={null} const ChartBox = ({ baseAsset, mobile = false, custom_css_url = "../themed.css", isPair = false, isUsd = true, }: ChartBoxProps) => { const ref = useRef (null); const { resolvedTheme } = useTheme(); const isWhiteMode = resolvedTheme === "light"; useEffect(() => { if (!baseAsset) return () => {}; let freshWidget: IChartingLibraryWidget | null = null; import("../../../../../../../../public/static/charting_library").then( ({ widget: Widget }) => { if (!ref.current) return; // Build symbol for display const symbol = isPair ? `${baseAsset.base?.symbol ?? baseAsset.symbol}/USD` : `${baseAsset.symbol}/USD`; freshWidget = new Widget({ // Datafeed with pair/token mode support datafeed: Datafeed(baseAsset, isUsd), symbol, interval: "60" as ResolutionString, // Settings container: ref.current, container_id: ref.current.id, library_path: "/static/charting_library/", // UI & Behavior locale: "en", fullscreen: false, disabled_features: [ "header_saveload", "header_symbol_search", ...(mobile ? ["left_toolbar"] : []), ], timezone: Intl.DateTimeFormat().resolvedOptions() .timeZone as Timezone, autosize: true, // Theme theme: isWhiteMode ? "Light" : "Dark", overrides: overrides(isWhiteMode), custom_css_url, }); } ); return () => { freshWidget?.remove(); }; }, [baseAsset, custom_css_url, mobile, isPair, isUsd]); return ; }; ``` The datafeed handles both **token-based** and **pair-based** charts. This is the key difference in the MTT implementation: * **Token mode** (`isPair: false`): Uses `asset` parameter to route to the highest liquidity pool * **Pair mode** (`isPair: true`): Uses `address` parameter for a specific pool ```typescript theme={null} export const supportedResolutions = ['1s', '5s', '15s', '30s', '1', '5', '15', '30', '60', '240', '1D', '1W', '1M']; const lastBarsCache = new Map(); const activeSubscriptions = new Map (); type BaseAsset = { asset?: string; // Token address (for token mode) address?: string; // Pair/pool address (for pair mode) chainId: string; symbol?: string; priceUSD?: number; isPair?: boolean; }; export const Datafeed = (initialBaseAsset: BaseAsset, isUsd = false) => { let baseAsset = initialBaseAsset; return { // Allow updating the asset without recreating the datafeed updateBaseAsset: (newAsset: BaseAsset) => { baseAsset = newAsset; }, onReady: (callback: Function) => { setTimeout(() => { callback({ supported_resolutions: supportedResolutions, supports_time: true, supports_marks: false, }); }, 0); }, resolveSymbol: (symbolName: string, onResolve: Function) => { setTimeout(() => { const price = baseAsset.priceUSD ?? 1; onResolve({ name: symbolName, type: 'crypto', session: '24x7', timezone: 'Etc/UTC', minmov: 1, pricescale: Math.min(10 ** String(Math.round(10000 / price)).length, 1e16), has_intraday: true, has_seconds: true, supported_resolution: supportedResolutions, data_status: 'streaming', }); }, 0); }, // ... getBars and subscribeBars below }; }; ``` The `getBars` function fetches historical OHLCV data. The key is handling both token and pair modes: ```typescript theme={null} getBars: async ( _info: any, resolution: string, params: any, onResult: (bars: any[], meta: { noData: boolean }) => void ) => { const assetId = baseAsset.isPair ? baseAsset.address : baseAsset.asset; const normalizedResolution = normalizeResolution(resolution); const cacheKey = `${assetId}-${normalizedResolution}`; // TradingView provides timestamps in seconds, convert to ms const fromMs = params.from * 1000; const toMs = params.to * 1000; try { const client = getMobulaClient(); // Build request params based on mode (token vs pair) const requestParams: any = { from: fromMs, to: toMs, amount: params.countBack, usd: `${isUsd}`, period: normalizedResolution, blockchain: baseAsset.chainId }; if (baseAsset.isPair) { // Pair mode: use pool address directly requestParams.address = baseAsset.address; requestParams.mode = 'pool'; } else { // Token mode: use asset address, routes to highest liquidity pool requestParams.asset = baseAsset.asset; requestParams.mode = 'asset'; } const response = await client.fetchMarketHistoricalPairData(requestParams); const bars = response.data || []; onResult(bars, { noData: !bars.length }); // Cache last bar for real-time updates if (bars.length > 0) { lastBarsCache.set(cacheKey, bars[bars.length - 1]); } } catch (err) { console.error('Error fetching bars:', err); onResult([], { noData: true }); } } ``` The MTT implementation uses Mobula's WebSocket `ohlcv` stream for real-time candle updates: ```typescript theme={null} subscribeBars: async ( _info: any, resolution: string, onRealtime: (bar: any) => void, subscriberUID: string ) => { const client = getMobulaClient(); if (!client) return; const assetId = baseAsset.isPair ? baseAsset.address : baseAsset.asset; const key = `${assetId}-${subscriberUID}`; const normalizedResolution = normalizeResolution(resolution); const cacheKey = `${assetId}-${normalizedResolution}`; // Unsubscribe from existing subscription if any if (activeSubscriptions.has(key)) { try { await client.streams.unsubscribe('ohlcv', activeSubscriptions.get(key)!); } catch {} activeSubscriptions.delete(key); } try { // Build subscription params based on mode const subscribeParams: any = { period: normalizedResolution, chainId: baseAsset.chainId, }; if (baseAsset.isPair) { subscribeParams.address = baseAsset.address; } else { subscribeParams.asset = baseAsset.asset; } // Subscribe to OHLCV stream const subId = client.streams.subscribe( 'ohlcv', subscribeParams, (candle: any) => { if (!candle?.time) return; // Handle candle timestamp format const normalizedCandle = { ...candle, time: candle.time > 10000000000 ? candle.time / 1000 : candle.time }; onRealtime(normalizedCandle); lastBarsCache.set(cacheKey, normalizedCandle); } ); activeSubscriptions.set(key, subId); } catch (err) { console.error('Error subscribing to OHLCV stream', err); } }, unsubscribeBars: async (subscriberUID: string) => { const client = getMobulaClient(); const assetId = baseAsset.isPair ? baseAsset.address : baseAsset.asset; const key = `${assetId}-${subscriberUID}`; const subId = activeSubscriptions.get(key); if (subId && client) { try { await client.streams.unsubscribe('ohlcv', subId); } catch (err) { console.error('Unsubscribe error:', err); } activeSubscriptions.delete(key); } } ``` The MTT datafeed supports sub-second resolutions. Here's the normalization function: ```typescript theme={null} const normalizeResolution = (resolution: string): string => { switch (resolution) { case '1S': case '1s': return '1s'; case '5S': case '5s': return '5s'; case '15S': case '15s': return '15s'; case '30S': case '30s': return '30s'; case '1': case '1m': return '1m'; case '5': case '5m': return '5m'; case '15': case '15m': return '15m'; case '60': case '1h': return '1h'; case '240': case '4h': return '4h'; case '1D': case '1d': return '1d'; case '1W': case '1w': return '1w'; case '1M': case '1month': return '1M'; default: return resolution; } }; ``` ``` ### Pair Page (`/pair/[blockchain]/[address]`) Uses the **pair mode** for a specific pool/pair: ```typescript theme={null} // Pair page passes isPair: true ``` *** ## Supported Resolutions The MTT implementation supports these resolutions: | Resolution | Period | Description | | - | - | - | | `1s` | 1 second | Sub-second precision | | `5s` | 5 seconds | | | `15s` | 15 seconds | | | `30s` | 30 seconds | | | `1` / `1m` | 1 minute | | | `5` / `5m` | 5 minutes | | | `15` / `15m` | 15 minutes | | | `60` / `1h` | 1 hour | | | `1D` / `1d` | 1 day | | | `1W` / `1w` | 1 week | | | `1M` | 1 month | | *** ## Full Example: Complete Datafeed For the complete production-ready datafeed with all edge cases handled, see: **[src/components/charts/datafeed.tsx](https://github.com/MobulaFi/MTT/blob/main/src/components/charts/datafeed.tsx)** Key features in the production implementation: * Request deduplication with `pendingRequests` map * Last bar caching for smooth real-time updates * First candle gap handling (fills gaps between last historical bar and first streaming candle) * Proper subscription cleanup * Support for both token and pair modes *** ### Need help? Can't find what you're looking for? Reach out to us, response times \< 1h. # Analyze LP Locking & Rug Pull Risk Source: https://docs.mobula.io/cookbooks/token-security-liquidity-analysis Use the Token Security endpoint to check if a token's liquidity is burned, locked, or at risk of being pulled. ## What You'll Build A script that checks whether a token's liquidity pool is safe by analyzing LP holder distribution — burned, locked in known protocols (Unicrypt, PinkLock, Team Finance, Mudra), held by contracts, or sitting unlocked in regular wallets. ## Why It Matters The #1 rug pull vector is unlocked liquidity. A developer who holds LP tokens can remove all liquidity at any time, crashing the token price to zero. The `liquidityAnalysis` field gives you a per-pool breakdown of exactly who holds the LP tokens and whether they're safe. ## Quick Start ```bash theme={null} curl -s "https://api.mobula.io/api/2/token/security?blockchain=ethereum&address=0x6982508145454ce325ddbe47a25d4ec3d2311933" \ -H "Authorization: YOUR_API_KEY" | jq '.data.liquidityAnalysis' ``` ## Understanding the Response The `liquidityAnalysis` array returns the top 3 pools by 24h volume. Each pool includes a full holder breakdown: ```json theme={null} { "liquidityAnalysis": [ { "poolAddress": "0xa43fe16908251ee70ef74718545e4fe6c5ccec8f", "poolType": "uniswap-v2", "burnedPercentage": 36.4, "lockedPercentage": 0, "contractPercentage": 0.8, "unlockedPercentage": 62.8, "topHolders": [ { "address": "0x371d...", "percentage": 31.8, "type": "unlocked", "protocol": null }, { "address": "0x0000...0000", "percentage": 20.6, "type": "burned", "protocol": null }, { "address": "0x663a...", "percentage": 16.2, "type": "locked", "protocol": "Unicrypt" } ] } ] } ``` ### Holder Types | Type | What It Means | Risk Level | | - | - | - | | `burned` | LP tokens sent to a dead address. Liquidity is **permanently** locked. | Safe | | `locked` | LP tokens held by a locker protocol (Unicrypt, PinkLock, etc.). Locked for a defined period. | Safe (while lock active) | | `contract` | LP tokens in an unrecognized contract. Could be a custom lock, a multisig, or something else. | Investigate | | `unlocked` | LP tokens in a regular wallet. Can be removed at any time. | Risk | ## Cookbook: Rug Pull Risk Scorer This TypeScript function takes a token address and returns a risk assessment: ```typescript theme={null} const API_KEY = "YOUR_API_KEY"; interface LiquidityRisk { riskLevel: "safe" | "moderate" | "high" | "critical"; burnedPct: number; lockedPct: number; unlockedPct: number; topUnlockedHolder: { address: string; percentage: number } | null; pools: number; details: string; } async function assessLiquidityRisk( address: string, blockchain: string ): Promise Telegram Slack Discord { const res = await fetch( `https://api.mobula.io/api/2/token/security?address=${address}&blockchain=${blockchain}`, { headers: { Authorization: API_KEY } } ); const { data } = await res.json(); const pools = data.liquidityAnalysis; if (!pools || pools.length === 0) { return { riskLevel: "critical", burnedPct: 0, lockedPct: 0, unlockedPct: 100, topUnlockedHolder: null, pools: 0, details: "No liquidity analysis available", }; } // Aggregate across all pools (weighted by position in array = volume rank) let totalBurned = 0, totalLocked = 0, totalUnlocked = 0; let topUnlocked: { address: string; percentage: number } | null = null; for (const pool of pools) { totalBurned += pool.burnedPercentage; totalLocked += pool.lockedPercentage; totalUnlocked += pool.unlockedPercentage; for (const holder of pool.topHolders) { if (holder.type === "unlocked") { if (!topUnlocked || holder.percentage > topUnlocked.percentage) { topUnlocked = { address: holder.address, percentage: holder.percentage }; } } } } // Average across pools const n = pools.length; const burned = totalBurned / n; const locked = totalLocked / n; const unlocked = totalUnlocked / n; const safePct = burned + locked; let riskLevel: LiquidityRisk["riskLevel"]; let details: string; if (safePct >= 90) { riskLevel = "safe"; details = `${burned.toFixed(1)}% burned + ${locked.toFixed(1)}% locked across ${n} pool(s)`; } else if (safePct >= 60) { riskLevel = "moderate"; details = `${unlocked.toFixed(1)}% unlocked — some rug pull risk remains`; } else if (safePct >= 30) { riskLevel = "high"; details = `Only ${safePct.toFixed(1)}% of LP is burned/locked — significant rug risk`; } else { riskLevel = "critical"; details = `${unlocked.toFixed(1)}% of LP is unlocked — high probability of rug pull`; } return { riskLevel, burnedPct: burned, lockedPct: locked, unlockedPct: unlocked, topUnlockedHolder: topUnlocked, pools: n, details }; } // Usage const risk = await assessLiquidityRisk("0x6982508145454ce325ddbe47a25d4ec3d2311933", "ethereum"); console.log(`Risk: ${risk.riskLevel} — ${risk.details}`); ``` ## Supported Protocols ### LP Locker Detection When LP tokens are held by a recognized locker contract, the `protocol` field identifies it: | Protocol | Chains | Description | | - | - | - | | **Unicrypt** | Ethereum, BSC, Arbitrum, Base | Largest LP locker, time-locked vaults | | **Team Finance** | Ethereum, BSC | Team token and LP locking | | **PinkLock** | Ethereum, BSC, Arbitrum, Base | PinkSale ecosystem locker | | **Mudra Locker** | BSC | BSC-focused LP locker | ### Supported DEX Pools Liquidity analysis works across all major DEX types: **EVM:** * Uniswap V2/V3/V4, PancakeSwap, Camelot, Balancer, Curve, Solidly/Aerodrome, Fluid **Solana:** * PumpSwap, Raydium (AMM V4, CPMM), Meteora (Dynamic AMM, DBC, DLMM), Orca Whirlpool ## Combining with Other Security Signals For a complete security assessment, combine `liquidityAnalysis` with other fields from the same endpoint: ```typescript theme={null} const { data } = await res.json(); const redFlags = []; // Liquidity risk if (!data.liquidityAnalysis || data.liquidityAnalysis.length === 0) { redFlags.push("No LP analysis available"); } else if (data.liquidityAnalysis[0].unlockedPercentage > 80) { redFlags.push(`${data.liquidityAnalysis[0].unlockedPercentage}% LP unlocked`); } // Contract risks if (data.isHoneypot) redFlags.push("Honeypot detected"); if (data.balanceMutable) redFlags.push("Balance can be manipulated"); if (data.isMintable) redFlags.push("Supply can be minted"); if (!data.renounced) redFlags.push("Ownership not renounced"); if (data.sellFeePercentage > 10) redFlags.push(`High sell fee: ${data.sellFeePercentage}%`); if (data.transferFeePercentage > 10) redFlags.push(`High transfer tax: ${data.transferFeePercentage}%`); // Holder concentration if (data.top10HoldingsPercentage > 50) { redFlags.push(`Top 10 holders control ${data.top10HoldingsPercentage}%`); } console.log(redFlags.length === 0 ? "No red flags" : `Red flags: ${redFlags.join(", ")}`); ``` # Data APIs Source: https://docs.mobula.io/data-introduction Access comprehensive on-chain market data, token analytics, wallet portfolios, and more. ## Overview Mobula's Data APIs provide real-time and historical access to on-chain data across 40+ blockchains: ## Authentication All endpoints require an API key. Get one for free at [admin.mobula.io](https://admin.mobula.io). ```bash theme={null} curl "https://api.mobula.io/api/2/token/price?address=So11111111111111111111111111111111111111112" \ -H "Authorization: YOUR_API_KEY" ``` ## Base URL | Environment | URL | | - | - | | Production | `https://api.mobula.io/api/2` | | Demo (rate-limited) | `https://demo-api.mobula.io/api/2` (no key required for some endpoints) | # Benchmarks Source: https://docs.mobula.io/data/benchmarks Real-time latency benchmarks comparing Mobula against other crypto data aggregators. See how Mobula delivers the fastest on-chain data. Mobula is built for speed. We continuously benchmark our infrastructure against other crypto data aggregators to ensure we deliver the fastest, most reliable data. Token prices, market caps, liquidity, and detailed token analytics across all supported chains. Historical prices, OHLCV candles, and real-time trade feeds with enriched metadata. Portfolio balances, trade history, DeFi positions, PnL tracking, and wallet labels. **Live Results**: View real-time benchmarks at [openchainbench.com](https://openchainbench.com) **Open Source**: The benchmark suite is fully open source at [github.com/ChainBench/OpenChainBench](https://github.com/ChainBench/OpenChainBench) *** ## What We Measure We track multiple metrics to provide a comprehensive view of aggregator performance: | Benchmark | Description | | - | - | | **Transaction Coverage** | Unique transaction hashes captured per token (the ground truth) | | **Pool Discovery** | Time between on-chain token deployment and aggregator detection | | **Head Lag** | Delay between latest blockchain block and aggregator sync | | **REST API Latency** | Response time for REST API endpoints | | **Quote API Latency** | Response time for swap quote endpoints (vs DEX aggregators) | | **Metadata Coverage** | Percentage of tokens with logo, description, social links |Latency and coverage metrics are published in real time on [OpenChainBench](https://openchainbench.com), the open benchmark suite we built and open-sourced. *** ## Transaction Coverage — Competitive Analysis Solana is the critical chain. The fragmentation is structural: traders route through aggregators like Jupiter that bundle swaps across multiple DEXs simultaneously. On EVM chains, most volume flows through Uniswap or PancakeSwap directly — every provider indexes those reliably. Beyond coverage, each provider has a structural limitation that matters in production: | Provider | Solana coverage | EVM coverage | Critical limitation | | - | - | - | - | | **Mobula** | Reference | Complete | None | | **Bitquery** | -11% to -13% | Perfect | 10k trades hard cap, no pagination | | **Codex** | -22% to -25% | Perfect | 10 trades/page (60s for 296 TX) | | **Moralis** | -48% to -57% | Good | Not viable on Solana | Bitquery is fastest but truncates silently above 10,000 trades. Codex pagination at 10 results per page makes it unusable at volume. Mobula has no artificial cap. ### Transaction Hashes — 10 min Windows We tested Mobula, Moralis, Bitquery, and Codex on 8 tokens across Solana, Ethereum, BSC, and Base using 10-minute windows. The metric: **unique transaction hashes** — not total trade count, which varies depending on how each provider handles multi-leg swaps. | Chain | Token | Mobula | Bitquery | Codex | Moralis | | - | - | - | - | - | - | | **Solana** | Nana | **166 TX** | 144 TX (-13%) | 125 TX (-25%) | 72 TX (-57%) | | **Solana** | Oilinu | **107 TX** | 95 TX (-11%) | 83 TX (-22%) | 51 TX (-52%) | | **Ethereum** | OIL | **26 TX** | 26 TX (0%) | 26 TX (0%) | 26 TX (0%) | | **Ethereum** | Kimchi | **7 TX** | 7 TX (0%) | 7 TX (0%) | 6 TX (-14%) | | **BSC** | MILADY | **27 TX** | 27 TX (0%) | 26 TX (-4%) | 25 TX (-7%) | | **BSC** | ARK | **296 TX** | 296 TX (0%) | 296 TX (0%) | 205 TX (-31%) | | **Base** | Broke | **41 TX** | 41 TX (0%) | 41 TX (0%) | 39 TX (-5%) | | **Base** | LANCER | **166 TX** | 166 TX (0%) | 167 TX (+0.6%) | 164 TX (-1%) |Full benchmark code (independently testable): [github.com/Flotapponnier/token-trade-benchmark-](https://github.com/Flotapponnier/token-trade-benchmark-) *** ## Live Metrics — Latency & Coverage These are measured continuously on [OpenChainBench](https://openchainbench.com), the open benchmark suite we built and open-sourced. Every badge below is live and links to the leaderboard, methodology and source. [](https://openchainbench.com/benchmarks/aggregator-head-lag) Head lag is the delay between the latest chain block and aggregator sync. Mobula ranks first among the measured aggregators, with a p50 head lag of 0.8 s. [](https://openchainbench.com/benchmarks/bridge-quote-latency) Bridge quote latency is the response time for cross-chain quote requests. Mobula ranks first of five providers, at around 210 ms p50. [](https://openchainbench.com/benchmarks/metadata-coverage) Metadata coverage is the share of tokens with logo, description and social links. Mobula ranks first among the measured aggregators. *** ## Methodology * **Transaction coverage**: unique TX hashes in 10-minute windows, same tokens queried simultaneously across all providers * **Latency**: real-time monitoring via WebSocket + REST polling, Prometheus metrics, Grafana visualization * **Same events** compared across all aggregators at the same time * **Multiple chains** tested: Solana, Ethereum, BSC, Base, Arbitrum *** ## Tracked Aggregators | Aggregator | TX Coverage | Pool Discovery | Head Lag | REST API | Quote API | Metadata | | - | - | - | - | - | - | - | | **Mobula** | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | | **Codex** | ✅ | ✅ | ✅ | ✅ | - | ✅ | | **GeckoTerminal** | - | ✅ | ✅ | ✅ | - | ✅ | | **Bitquery** | ✅ | - | - | - | - | - | | **Moralis** | ✅ | - | - | - | - | - | | **Jupiter** | - | - | - | - | ✅ (Solana) | ✅ (Solana) | | **OpenOcean** | - | - | - | - | ✅ (EVM) | - | | **ParaSwap** | - | - | - | - | ✅ (EVM) | - | | **Li.Fi** | - | - | - | - | ✅ (EVM) | - | | **KyberSwap** | - | - | - | - | ✅ (EVM) | - | *** ## Run Your Own Benchmark Want to verify the results yourself? Both benchmark tools are fully open-source. ### Latency Benchmark The benchmark suite is open source. The harness code lives in the [OpenChainBench repository](https://github.com/ChainBench/OpenChainBench), under [harnesses/aggregator-latency-benchmark](https://github.com/ChainBench/OpenChainBench/tree/main/harnesses/aggregator-latency-benchmark). Live results and methodology are published at [openchainbench.com](https://openchainbench.com). ### Transaction Coverage Benchmark ```bash theme={null} git clone https://github.com/Flotapponnier/token-trade-benchmark-.git cd token-trade-benchmark- # Follow README for setup ``` *** ## Why These Metrics Matter*** ## Get Started with Mobula Experience the fastest crypto data API yourself: Missing trades = wrong PnL, wrong volume, wrong analytics. On Solana, the gap between providers is 25-57%. Faster detection of new tokens = first-mover advantage on new launches. Critical for trading bots and snipers. Lower head lag = more accurate real-time data. Essential for live price feeds and position monitoring. Faster API responses = better UX. Important for dashboards, portfolio trackers, and trading interfaces. # Get Funding Rate Source: https://docs.mobula.io/data/perps/market-cefi-funding-rate get /1/market/cefi/funding-rate Fetches the latest CeFi funding rate for a given symbol on a specified exchange. This can be queried via REST or WebSocket. # Get Perp Chart Source: https://docs.mobula.io/data/perps/perp-chart GET /2/perp/ohlcv-history Fetch OHLC candles for a perpetual market from a supported DEX (Gains Network, Lighter), normalized to a single shape regardless of upstream. ### Query Details Returns OHLC candles for the requested market and period. Same param/response shape as `GET /2/market/ohlcv-history` and `GET /2/token/ohlcv-history`, so a single client can render both spot and perp charts. * Market identifier is `dex` + `market` (perp has no pool address). * Market mappings are cached server-side for 5 minutes. * Candles are sorted ascending by `t`. Duplicate timestamps and rows with `h < l` or non-finite values are dropped. * Empty result sets are not errors — `data: []` with HTTP 200 is returned when the upstream has no data for the range. Create your account and get instant access Explore the REST API documentation Connect to real-time data streams Build with production-ready examples Timestamps accept **seconds, milliseconds, or ISO date strings** — milliseconds are auto-detected for numeric values above `1e12`. > **Note on Lighter:** > Only USD-quoted perps are supported (e.g., `BTC/USD`, `SOL/USD`, `HYPE/USD`). > **Note on Gains:** > Crypto, forex, stocks, and commodities are supported. Quote can be non-USD (e.g., `USD/JPY`, `EUR/CHF`). ### Query Parameters | Parameter | Type | Required | Description | | - | - | - | - | | dex | string | Yes | Upstream DEX to query. One of `gains`, `lighter`. | | market | string | Yes | Pair in `BASE/QUOTE` format (e.g., `BTC/USD`, `USD/JPY`). Case-insensitive. | | period | string | No | Candle width. One of `1m`, `5m`, `15m`, `30m`, `1h`, `4h`, `1d`, `1w`. Default `5m`. | | from | number \| string | No | Range start (inclusive). UNIX seconds, UNIX milliseconds, or ISO date string. | | to | number \| string | No | Range end (inclusive). Same unit handling as `from`. Must be greater than `from`. | | amount | number | No | Max candles to return (capped at `2000`). When range yields more than `amount`, the most recent are kept. | ### Response Each entry in `data` is a candle: | Field | Type | Description | | - | - | - | | t | number | UNIX seconds. | | o | number | Opening price. | | h | number | Highest price in the interval. | | l | number | Lowest price in the interval. | | c | number | Closing price. | Note: candle shape matches spot OHLCV endpoints (`{t, o, h, l, c}`). Perp has no `v` field — volume is not reported by the upstream DEXes. ### Usage Examples * Lighter `BTC/USD`, 1-minute candles for the last hour: ```bash theme={null} curl -X GET "https://api.mobula.io/api/2/perp/ohlcv-history?dex=lighter&market=BTC/USD&period=1m&from=1777035900&to=1777039500" ``` * Gains `USD/JPY`, 5-minute candles, last 200 candles only: ```bash theme={null} curl -X GET "https://api.mobula.io/api/2/perp/ohlcv-history?dex=gains&market=USD/JPY&period=5m&from=1777000000&to=1777039500&amount=200" ``` Response: ```json theme={null} { "data": [ { "t": 1777035900, "o": 78328.9, "h": 78370.8, "l": 78328.9, "c": 78367.1 }, { "t": 1777035960, "o": 78367.1, "h": 78388.6, "l": 78340.2, "c": 78380.0 } ] } ``` ### Errors | Status | When | `message` | | - | - | - | | 400 | Zod validation failed (invalid `dex`, malformed `market`) | `zod validation failed` | | 400 | `from >= to` | `from must be < to` | | 400 | `period` not in supported set | `unsupported period ""` | | 404 | Market not found for the selected DEX (`errors[0]` lists example pairs) | `unknown market " " for dex " "` | | 502 | Upstream DEX returned an error (timeout, non-200, or `code !== 200` for Lighter) | `upstream error` | | 500 | Unexpected internal error | `internal server error` | ### Notes * Market mappings (Gains pairs, Lighter `orderBookDetails`) are fetched lazily on first request per process and cached for 5 minutes. * Upstream requests have a 10s timeout. * Each request is traced server-side with a short `traceId` included in every log line for that request. # Generate Perp Chart Image Source: https://docs.mobula.io/data/perps/perp-chart-image POST /2/perp/chart Render a candlestick chart image for a perpetual market from OHLC candles plus header/footer metadata and optional overlay lines (stop-loss, take-profit, liquidation). The candle shape is identical to the /2/perp/ohlcv-history response, so its output can be passed straight in. ### Query Details Send OHLC candles together with the header and footer blocks shown around the chart, and the rendered chart is returned in `data`. This is a synchronous proxy: one request in, one rendered chart out — nothing is stored. * Candles use the same `t / o / h / l / c` shape as `GET /2/perp/ohlcv-history` — feed that endpoint's output directly. * `t` is UNIX **milliseconds**. * `priceChange` is a percentage (e.g. `-6.31` means `-6.31%`), not a ratio. * Send candles ordered oldest → newest. * All top-level fields except `lines` are required. Within `lines`, each of `stopLoss` / `takeProfit` / `liquidation` is independently optional — send only the levels you have. ### Request Body | Field | Type | Required | Description | | - | - | - | - | | candles | array | Yes | OHLC series (`{t, o, h, l, c}`), oldest-to-newest. Min 1 candle. | | width | integer | Yes | Output image width in pixels. Positive integer. | | height | integer | Yes | Output image height in pixels. Positive integer. | | name | string | Yes | Chart title / pair label shown on the chart (e.g. `FLUID/USD`). | | lines | object | No | Overlay lines: `stopLoss`, `takeProfit`, `liquidation` (all optional). | | headerData | object | Yes | Header block (see below). | | footerData | object | Yes | Footer block (see below). | `headerData`: | Field | Type | Description | | - | - | - | | pair | string | Trading pair label (e.g. `FLUID/USD`). | | leverage | number | Position leverage multiplier. | | currentPrice | number | Current mark/last price. | | priceChange | number | Price change for the window, as a percentage (may be negative). | | openInterestL | object | Long-side open interest: `{ value, total }`. | | openInterestS | object | Short-side open interest: `{ value, total }`. | | holdingL | number | Long holding amount. | | holdingS | number | Short holding amount. | `footerData`: | Field | Type | Description | | - | - | - | | high24h | number | 24-hour high price. | | low24h | number | 24-hour low price. | | volume24h | number | 24-hour traded volume. | ### Response | Field | Type | Description | | - | - | - | | data | string | The rendered chart, passed through verbatim. Treat as an opaque string payload. | Example of the rendered chart returned for the request below: ### Usage Example ```bash theme={null} curl -X POST "https://api.mobula.io/api/2/perp/chart" \ -H "Content-Type: application/json" \ -d '{ "candles": [ { "t": 1780860000000, "o": 1.0615964, "h": 1.0656162, "l": 1.0506006, "c": 1.0605862 }, { "t": 1780861800000, "o": 1.0605862, "h": 1.0655736, "l": 1.0525683, "c": 1.0630746 } ], "width": 1024, "height": 850, "name": "FLUID/USD", "lines": { "stopLoss": 1.28768, "takeProfit": 0.73582, "liquidation": 1.42315 }, "headerData": { "pair": "FLUID/USD", "leverage": 3, "currentPrice": 1.103729, "priceChange": -6.305772495755514, "openInterestL": { "value": 0, "total": 250000 }, "openInterestS": { "value": 30.000026, "total": 249969.999974 }, "holdingL": 0.00251711712, "holdingS": 0.00251711712 }, "footerData": { "high24h": 1.2151002, "low24h": 1.0799406, "volume24h": 2001.2866550754236 } }' ``` ### Errors | Status | When | `message` | | - | - | - | | 400 | Body failed validation (missing/invalid fields, empty candles, wrong keys) | `zod validation failed` | | 502 | Upstream chart generator failed or was unreachable | `upstream chart generator error` | | 500 | Unexpected internal error | `failed to generate chart` | # Get Perp DEX Status Source: https://docs.mobula.io/data/perps/perp-dex-status GET /2/perp/dex-status Health and status snapshot for supported perp DEXes (Lighter, Gains). Probes upstream HTTP and WebSocket endpoints, surfaces scheduled-maintenance windows, and rolls per-check results into an overall status. ### Query Details Returns one entry per probed DEX with a rolled-up `status`, the individual probe results powering that rollup, and any active or upcoming maintenance windows. * Probes both **HTTP** and **WebSocket** upstreams. WS probes connect, wait for the first message, and disconnect. * Results are cached server-side per check to avoid hammering upstreams. Concurrent cold-cache calls are deduped — `N` parallel requests fire a single upstream probe. * Probes never throw — failures surface as `ok: false` on the corresponding check. * Auxiliary checks are informational and never affect the rollup; only `critical` checks do. ### Endpoint ``` GET /api/2/perp/dex-status ``` ### Query Parameters | Parameter | Type | Required | Description | | - | - | - | - | | dex | `'lighter' \| 'gains'` | No | Filter to a single DEX. If omitted, both DEXes are probed in parallel and returned together. | ### Usage Examples * Both DEXes: ```bash theme={null} curl 'https://api.mobula.io/api/2/perp/dex-status' ``` * Lighter only: ```bash theme={null} curl 'https://api.mobula.io/api/2/perp/dex-status?dex=lighter' ``` * Gains only: ```bash theme={null} curl 'https://api.mobula.io/api/2/perp/dex-status?dex=gains' ``` ### Response Top-level shape: ```ts theme={null} { data: PerpDexHealth[]; meta?: { generatedAt: number; // unix ms — server-side response build time totalMs: number; // controller-measured request duration in ms }; } ``` #### `PerpDexHealth` One entry per probed DEX. | Field | Type | Description | | - | - | - | | dex | `'lighter' \| 'gains'` | DEX identifier. | | status | `'operational' \| 'degraded' \| 'maintenance' \| 'down'` | Roll-up status derived from `checks` and any active maintenance window. See [Status rollup](#status-rollup). | | checkedAt | `number` | Unix ms — when the snapshot for this DEX was assembled. | | checks | `PerpDexCheckResult[]` | Individual probe results powering the rollup. | | maintenance | `{ active: boolean; windows: PerpDexMaintenanceWindow[] }` | Active flag and parsed maintenance windows. Currently populated for `lighter` only (Gains: empty). | | meta | `Record
` (optional) | DEX-specific extras. For Gains: `{ chains: [{ chainId, isTestnet, pairsCount }, ...] }`. | #### `PerpDexCheckResult` One per upstream probe. | Field | Type | Description | | - | - | - | | name | `string` | Check identifier. See [Checks reference](#checks-reference). | | description | `string` | Human-readable summary of what this check probes and why it matters. | | weight | `'critical' \| 'auxiliary'` | Only `critical` checks contribute to the rollup. `auxiliary` is informational. | | transport | `'http' \| 'ws'` | Probe transport. | | ok | `boolean` | True if the probe succeeded (and, where applicable, body validation passed — e.g. `pairs.length > 0` for `trading-variables`). | | slow | `boolean` | True only when `ok === true` and latency exceeds the transport's slow threshold (HTTP: 2000 ms, WS: 3000 ms). | | latencyMs | `number \| null` | Round-trip latency for the probe. | | cached | `boolean` | True if the value was served from the in-memory cache rather than freshly fetched. | | fetchedAt | `number` | Unix ms — timestamp of the underlying probe (cache-fill time when `cached === true`). | | error | `string` (optional) | Present when `ok === false`; short error label. | | meta | `Record ` (optional) | Check-specific extras (e.g. `pairsCount`, `networkId`, `firstMessageBytes`, `chainId`, `isTestnet`). | #### `PerpDexMaintenanceWindow` | Field | Type | Description | | - | - | - | | title | `string` | Source announcement title. | | content | `string` | Source announcement body. | | createdAt | `number` | Source announcement `created_at`, unix seconds. | | expiredAt | `number \| null` | Source announcement `expired_at`, unix seconds (null when none). | | isMaintenance | `boolean` | True when title/content match maintenance keywords (`upgrade`, `maintenance`, `downtime`). | | scheduledAt | `number \| null` | Parsed window start in unix seconds (null when not extractable). | | scheduledEndAt | `number \| null` | Parsed window end in unix seconds (null when not extractable). | | active | `boolean` | True when `now` falls inside the parsed window (or inside the `expiredAt` fallback). | ### Status Rollup Ranking best → worst: 1. `maintenance` — any maintenance window with `active === true`. 2. `operational` — every critical check is `ok && !slow`. 3. `down` — zero critical checks `ok`. 4. `degraded` — anything else (some critical OK and some not, or one critical is `slow`). Auxiliary checks never affect the rollup. ### Checks Reference #### Lighter | name | weight | transport | Probes | | - | - | - | - | | http-root | critical | http | `https://mainnet.zklighter.elliot.ai/` — sequencer reachability; returns network id + timestamp. | | announcements | auxiliary | http | Public announcements API. Source of `maintenance.windows`. | | ws-stream | critical | ws | `wss://mainnet.zklighter.elliot.ai/stream` — live order/transaction confirmations. | #### Gains One `trading-variables` and one `ws-trading` per supported chain, plus a single shared `ws-pricing`. | name | weight | transport | Probes | | - | - | - | - | | trading-variables | critical (Arbitrum, Base) / auxiliary (Polygon, Arbitrum Sepolia) | http | ` /trading-variables/all` — pair list and per-pair trading parameters. | | ws-trading | critical (Arbitrum, Base) / auxiliary (Polygon, Arbitrum Sepolia) | ws | Gains backend event WS — order, position and chain events. | | ws-pricing | critical | ws | `wss://backend-pricing.eu.gains.trade` — shared price feed for every Gains chain. | Per-chain weights: | chainId | network | weight | isTestnet | | - | - | - | - | | evm:42161 | Arbitrum | critical | false | | evm:8453 | Base | critical | false | | evm:137 | Polygon | auxiliary | false | | evm:421614 | Arbitrum Sepolia | auxiliary | true | ### Caching & Timeouts In-memory per-check TTLs: | Check | TTL | | - | - | | lighter `http-root` | 10000 ms | | lighter `announcements` | 30000 ms | | lighter `ws-stream` | 15000 ms | | gains `trading-variables/*` | 15000 ms | | gains `ws-trading/*` | 15000 ms | | gains `ws-pricing` | 15000 ms | Probe budgets: * HTTP — timeout: 5000 ms · slow threshold: 2000 ms. * WS — timeout: 4000 ms · slow threshold: 3000 ms. ### Example Response Truncated for readability. ```json theme={null} { "data": [ { "dex": "lighter", "status": "operational", "checkedAt": 1714200000000, "checks": [ { "name": "http-root", "description": "Lighter HTTP root endpoint. Returns the current network id and chain timestamp; failure means the L2 sequencer is unreachable.", "weight": "critical", "transport": "http", "ok": true, "slow": false, "latencyMs": 142, "cached": false, "fetchedAt": 1714199999850, "meta": { "status": 200, "networkId": 1, "serverTimestamp": 1714199999 } }, { "name": "announcements", "description": "Lighter public announcements API. Source of scheduled maintenance and network-upgrade notices surfaced under `maintenance.windows`.", "weight": "auxiliary", "transport": "http", "ok": true, "slow": false, "latencyMs": 198, "cached": true, "fetchedAt": 1714199985000, "meta": { "totalAnnouncements": 42, "maintenanceWindowsTotal": 1, "maintenanceWindowsRelevant": 1 } }, { "name": "ws-stream", "description": "Lighter WebSocket stream (`/stream`). Used for live order-status and transaction confirmations; failure breaks order tracking.", "weight": "critical", "transport": "ws", "ok": true, "slow": false, "latencyMs": 612, "cached": false, "fetchedAt": 1714199999800, "meta": { "firstMessageBytes": 184 } } ], "maintenance": { "active": false, "windows": [ { "title": "Network Upgrade May 1", "content": "...", "createdAt": 1713000000, "expiredAt": null, "isMaintenance": true, "scheduledAt": 1714572000, "scheduledEndAt": 1714575600, "active": false } ] } }, { "dex": "gains", "status": "operational", "checkedAt": 1714200000000, "checks": [ { "name": "trading-variables", "description": "Gains backend `trading-variables/all` HTTP endpoint. Returns the pair list and per-pair trading parameters used to build orders.", "weight": "critical", "transport": "http", "ok": true, "slow": false, "latencyMs": 311, "cached": false, "fetchedAt": 1714199999700, "meta": { "chainId": "evm:42161", "isTestnet": false, "pairsCount": 168 } }, { "name": "ws-trading", "description": "Gains backend WebSocket event stream. Pushes order, position and chain events; failure breaks live order tracking.", "weight": "critical", "transport": "ws", "ok": true, "slow": false, "latencyMs": 510, "cached": false, "fetchedAt": 1714199999700, "meta": { "chainId": "evm:42161", "isTestnet": false, "firstMessageBytes": 12 } }, { "name": "ws-pricing", "description": "Gains pricing WebSocket (`backend-pricing.eu.gains.trade`). Provides the price feed used across every Gains chain.", "weight": "critical", "transport": "ws", "ok": true, "slow": false, "latencyMs": 240, "cached": false, "fetchedAt": 1714199999700, "meta": { "firstMessageBytes": 96 } } ], "maintenance": { "active": false, "windows": [] }, "meta": { "chains": [ { "chainId": "evm:42161", "isTestnet": false, "pairsCount": 168 }, { "chainId": "evm:8453", "isTestnet": false, "pairsCount": 168 }, { "chainId": "evm:137", "isTestnet": false, "pairsCount": 168 }, { "chainId": "evm:421614","isTestnet": true, "pairsCount": 168 } ] } } ], "meta": { "generatedAt": 1714200000000, "totalMs": 740 } } ``` ### Errors | Status | When | `message` | | - | - | - | | 400 | Zod validation failed on `dex` (only `lighter` or `gains` accepted). | `zod validation failed` | | 500 | Unexpected internal error. | `internal server error` | Probes themselves never throw — upstream failures are reflected as `ok: false` on the per-check result, not as HTTP errors. ### Related # Get Perp Pairs Source: https://docs.mobula.io/data/perps/perp-pairs GET /2/perp/pairs List all tradable perpetual markets (Gains Network + Lighter). Supported exchanges and capability map. Fee structure for each integrated DEX. Preview fees, fills and venue routing before executing. Build → execute flow against Lighter and Gains. Only **tradable** markets are returned. Disabled, closed, or delisted markets are filtered out server-side, so anything absent from the response is not tradable — there is no separate "disabled" flag to check. For a full walkthrough with code samples, see the [Retrieve All Perp Markets](/cookbooks/retrieve-perp-markets) cookbook. ### Query ParametersRestrict the result to one chain/venue. Omit to return every chain and DEX in one list. One of: `arbitrum`, `base`, `arbitrum-sepolia`, `lighter`. ### ResponseArray of tradable perpetual markets. # Get Perp Unfilled Orders Source: https://docs.mobula.io/data/perps/wallet-perp-orders GET /2/wallet/positions/perp/unfilled Retrieve all open (unfilled) limit or stop orders for a specific wallet. # Get Perp Positions Source: https://docs.mobula.io/data/perps/wallet-perp-positions GET /2/wallet/positions/perp/open Retrieve all active perpetual positions for a specific wallet. # Check Perp Process Source: https://docs.mobula.io/exec/perps/perp-check-process GET /2/perp/check-process Poll the status of a long-running perpetual action (typically a deposit) started by /2/perp/execute-v2. Some actions submitted to `/2/perp/execute-v2` are asynchronous — the most common case is `deposit` on Lighter, which must observe the underlying bridge/settlement before the user's margin is usable. When the execute-v2 response includes a `processId`, poll this endpoint until the process reports a terminal status. ### Query ParametersHuman-readable `base/quote` label, e.g. `BTC/USD`. Base asset symbol, e.g. `BTC`. Quote asset symbol, e.g. `USD`. Minimum allowed leverage. Maximum allowed leverage (always greater than 0). DEX the market belongs to: `gains` or `lighter`. Chain/venue: `arbitrum`, `base`, `arbitrum-sepolia`, or `lighter`. Asset class: `crypto`, `forex`, `stocks`, `indices`, `commodities`, `degen`, or `new`. DEX internal market id — Gains `pairIndex` / Lighter `market_id`. Only unique within a `(dex, chain)`. Reserved for a social/info URL. Currently empty. Full name of the market as reported by the DEX. 24h price change, in percent. Latest/mark price in USD (`0` if no price is currently available). Base-asset logo URL, or `null` when unknown. UUID returned by `/2/perp/execute-v2` in `data.processId`. ### Response**Unwrapped body.** Unlike every other perp route (`{ data: { ... } }`), this endpoint returns the fields below at the top level — there is no `data` envelope. Parse defensively if your client assumes the wrapped shape. ```json theme={null} { "processId": "0c1f6f24-…", "status": "settled", "message": "deposit settled on L2" } ``` UUID of the tracked process. Process status reported by the execution engine (e.g., `pending`, `settled`, `failed`). Terminal values depend on the action; clients should treat any non-`pending` value as final. Human-readable status message. Error detail, present only when the process failed. ### Errors | Status | `message` | | - | - | | 404 | `Process not found or tracking disabled` — unknown `processId`, or the instance has process tracking disabled | # Execute Perp Action Source: https://docs.mobula.io/exec/perps/perp-execute POST /2/perp/execute-v2 Submit a canonical perpetual action (order, close, cancel, deposit, withdraw, …) previously built by /2/perp/payloads/. Handles both off-chain DEX APIs and signed EVM transaction broadcast. Single unified execution endpoint for every perp action. You forward the exact envelope returned by the matching `/2/perp/payloads/ ` call plus a signature that proves the caller approved this specific payload at this specific timestamp. The `/2/perp/execute` (v1) endpoint is deprecated. All new integrations must use `/2/perp/execute-v2`. ## Flow 1. Call `POST /2/perp/payloads/` (see left-hand nav) → receive `{ action, dex, chainId, marketId?, transport, payloadStr }`. 2. For Gains `transport: "evm-tx"` only: parse `payloadStr`, extract `payload.data`, sign the EVM transaction locally → obtain `signedTx`. 3. Sign the execute-v2 authentication message (see Authentication below). 4. `POST /2/perp/execute-v2` with the envelope fields, signature, timestamp, and (when required) `signedTx`. ### Request Body Canonical action name. One of `withdraw`, `create-account`, `deposit`, `create-order`, `close-position`, `cancel-order`, `update-margin`, `edit-order`. Must match the `action` inside `payloadStr`. `gains` or `lighter`. Must match `payloadStr`. Chain of the action. Must match `payloadStr`. Mobula market identifier. If provided, must match `payloadStr.marketId`. `offchain-api` — server submits to the DEX off-chain API using the user's signature.
`evm-tx` — server broadcasts the user-signed EVM transaction supplied in `signedTx`. Must match `payloadStr`.JSON-stringified canonical envelope returned by `/2/perp/payloads/ `. **Envelope metadata** (`action`, `dex`, `chainId`, `transport`, `marketId`) must be forwarded unchanged — it is cross-checked against the request fields. **`payload` sub-fields are action-specific and some flows require mutating them** before signing execute-v2: * `deposit` (Lighter route with EVM bridge steps) — sign every tx in `payload.steps[].items[].data` and write the hex results into `payload.signedTxs` as an array of strings. * `withdraw` on Lighter — sign `payload.MessageToSign`, set the hex result on `payload.L1Sig`, then delete `payload.MessageToSign`. In those cases you re-stringify the envelope and use the **new** string everywhere: as this field, and in the execute-v2 signed message below. Unix timestamp in milliseconds, within 30 seconds of server time. Hex signature of the message `api/2/perp/execute-v2-{timestamp}-{payloadStr}`. The recovered signer address must match the `payload.data.from` address for actions that carry a `from` (e.g., `create-order`, `close-position`). Single-use: a second call with the same signature is rejected. Hex-encoded **single** signed EVM transaction. Used for Gains single-tx actions (`create-order`, `close-position`, `cancel-order`, `edit-order`, `update-margin`) whose response has `transport: "evm-tx"`. The server broadcasts it via `eth_sendRawTransaction` on `chainId`. Do **not** use this field for multi-tx flows (Lighter `deposit` bridge route) — those inject signed txs **into** `payloadStr` under `payload.signedTxs` instead. ### Response### Errors | Status | `message` | Cause | | - | - | - | | 400 | `payloadStr is not valid JSON` | `payloadStr` is not parseable | | 400 | `invalid payloadStr` | envelope fails schema validation (see `errors`) | | 400 | `payloadStr metadata does not match request metadata` | `action`/`dex`/`transport`/`chainId` mismatch between envelope and request | | 400 | `payloadStr marketId does not match request marketId` | `marketId` mismatch | | 400 | `signedTx execution requires an EVM chainId, received " Always `true` on success. Per-leg execution details. Transaction hash (EVM) or DEX-side identifier. Execution kind (e.g., `evm-tx`, `lighter-order`). DEX-reported status (e.g., `submitted`, `filled`). DEX-reported order-level statuses, when applicable. Order id (numeric string). Order status. Order type (`order`, `tp`, `sl`, …). UUID of the async tracking process. Present for long-running actions (typically `deposit`). Poll `/2/perp/check-process?processId= ` until it reports terminal status. "` | `transport: "evm-tx"` with a non-EVM chain | | 403 | `timestamp expired` | `timestamp` more than 30s from server clock | | 403 | `signature already used` | Replay of an earlier request | | 403 | `signature signer does not match payload.from` | Signer address ≠ `payload.data.from` for actions that carry a `from` | | 500 | `Failed to broadcast signed transaction on ` | RPC rejected `signedTx` (see `errors` list for details) | | 500 | *DEX-specific reason* | Adapter-level failure returned by the DEX | ### Authentication The execute-v2 signature binds **the exact payloadStr** to **the exact timestamp**: ```javascript theme={null} const timestamp = Date.now(); const message = `api/2/perp/execute-v2-${timestamp}-${payloadStr}`; const signature = await wallet.signMessage(message); ``` Rules: * `payloadStr` in the signed message is the **same string** you put in the request body. If the flow requires injecting fields (deposit `signedTxs`, Lighter withdraw `L1Sig`), do the injection + re-stringify **before** signing — sign the final string, not the original. * For actions whose envelope carries `payload.data.from` (Gains EVM txs, Lighter orders), the signer must equal `from`. Deposit/withdraw envelopes that don't expose a `from` skip this check. * Signatures are single-use for 30 seconds after the timestamp. ### Transport & signing matrix The `transport` returned by `/2/perp/payloads/ ` is authoritative — forward it as-is. What the client must sign depends on both the DEX and the action: | DEX | Action | Transport | Client signing | | - | - | - | - | | Lighter | `create-order`, `close-position`, `cancel-order`, `edit-order`, `update-margin` | `offchain-api` | execute-v2 signature only — forward `payloadStr` byte-for-byte | | Lighter | `create-account` | `offchain-api` | If the response carries `payload.MessageToSign`: sign it, set `payload.L1Sig`, delete `payload.MessageToSign`, re-stringify. Otherwise no mutation. | | Lighter | `deposit` | `evm-tx` | Sign **each** tx in `payload.steps[].items[].data` (each item's `data` is a tx object: `to`, `data`, `value`, `chainId`, `gas?`, fee fields). Inject results into `payload.signedTxs: string[]`, re-stringify, then sign execute-v2 over the new string. Do **not** send top-level `signedTx`. | | Lighter | `withdraw` | `offchain-api` | Sign `payload.MessageToSign`, set `payload.L1Sig`, delete `payload.MessageToSign`, re-stringify, then sign execute-v2 over the new string. | | Gains | `create-order`, `close-position`, `cancel-order`, `edit-order`, `update-margin` | `evm-tx` | Read the tx object at `payload.data` (fields: `to`, **`callData`** *(not `data`)*, `value`, `chainId`, `nonce?`, `gas?`, fee fields). Sign as a type-2 EVM tx → submit as top-level `signedTx`. `payloadStr` is forwarded unchanged. | # Build Cancel-Order Payload Source: https://docs.mobula.io/exec/perps/perp-payload-cancel-order POST /2/perp/payloads/cancel-order Build a signed canonical payload to cancel an unfilled limit order (or TP/SL attached to a position) on Gains Network or Lighter. **Lighter requires the wallet to be a registered account before any trade/withdraw action.** If the EOA has never deposited on Lighter, this endpoint will fail. First-time setup is a two-step prerequisite: 1. **Deposit ≥ 5 USDC** via [`/2/perp/payloads/deposit`](/rest-api-reference/endpoint/perp-payload-deposit) → Lighter creates an `accountIndex` on-chain once the bridge settles. (5 USDC is a Lighter requirement, not a Mobula limit.) 2. **Provision API key + auth token** via [`/2/perp/payloads/create-account`](/rest-api-reference/endpoint/perp-payload-create-account) using that `accountIndex`. Read the [Build Create-Account Payload](/rest-api-reference/endpoint/perp-payload-create-account) page for the full setup flow including how to discover the `accountIndex` after a deposit. Builds the payload to cancel an unfilled order. For Gains, `orderType` distinguishes pending limit orders (`order`) from TP/SL legs (`tp`, `sl`) attached to an open trade. ### Request Body`gains` or `lighter`. Chain of the order. Order index as a positive integer string (regex `^\d+$`). Obtainable from `/2/wallet/perp/orders`. Mobula market identifier. Required by Lighter. Gains only. One of `order`, `tp`, `sl`. Omit for Lighter. ### Authentication Every `/2/perp/payloads/` endpoint verifies the caller by requiring two extra fields in the request body alongside the action parameters: Unix timestamp in milliseconds. Must be within 30 seconds of server time. Older timestamps are rejected to prevent replay. Hex signature (EIP-191 `personal_sign`) of the message `` `${endpoint}-${timestamp}` ``, where `endpoint` is the path **of this endpoint** without the leading slash (e.g., for this page: `api/2/perp/payloads/ ```javascript theme={null} // Replace ``). The recovered signer address becomes the `user` for the request. Single-use — replay returns `403 signature already used`. ` with the action of THIS page (e.g. create-account, deposit, …) const endpoint = 'api/2/perp/payloads/ '; const timestamp = Date.now(); const signature = await wallet.signMessage(`${endpoint}-${timestamp}`); await fetch(`https://api.mobula.io/${endpoint}`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ timestamp, signature, // ...action-specific fields below }), }); ``` ### Authentication errors | Status | `message` | | - | - | | 403 | `timestamp expired` — timestamp older than 30s | | 403 | `signature already used` — replay attempt | | 400 | `zod validation failed` — `timestamp`/`signature` shape invalid | ### Response envelope Every `/2/perp/payloads/ ` endpoint returns the same envelope shape. You pass these fields verbatim into `POST /2/perp/execute-v2` to execute the action. **Top-level shape.** Successful (2xx) responses return `{ data: { ... } }`. A `success: true` flag is only present inside the body of `execute-v2`'s response, not on the payload-build endpoints. Parse defensively: read `body.data`, then check for the action-specific fields you need (e.g. `data.payloadStr`). ### Endpoint-specific errors | Status | `message` | | - | - | | 400 | `cancel-order payload generation failed` — order not found or DEX refusal | ### Full flow — cancel an order end-to-end Single example covering both DEXes (Lighter offchain-api, Gains evm-tx). The flow branches on `data.transport`. ```javascript theme={null} import { ethers } from 'ethers'; // 1. Auth-sign + fetch the cancel-order payload const endpoint = 'api/2/perp/payloads/cancel-order'; const ts = Date.now(); const authSig = await wallet.signMessage(`${endpoint}-${ts}`); const { data } = await fetch(`https://api.mobula.io/${endpoint}`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ timestamp: ts, signature: authSig, dex: 'lighter', // or 'gains' chainId: 'lighter:301', // or 'evm:42161' marketId: 'lighter-btc-usd', // Lighter requires marketId orderIndex: '42', // orderType: 'order', // Gains only: 'order' | 'tp' | 'sl' }), }).then(r => r.json()); // 2. Branch on transport let signedTx; const finalPayloadStr = data.payloadStr; if (data.transport === 'evm-tx') { // Gains const txData = JSON.parse(data.payloadStr).payload.data; const provider = new ethers.JsonRpcProvider(rpcUrlFor(txData.chainId)); const feeData = await provider.getFeeData(); const baseTx = { to: txData.to, data: txData.callData, value: txData.value ? BigInt(txData.value) : 0n, from: wallet.address, chainId: txData.chainId, nonce: txData.nonce ?? await provider.getTransactionCount(wallet.address), }; const gasLimit = txData.gas ? BigInt(txData.gas) : await provider.estimateGas(baseTx); signedTx = await wallet.signTransaction({ ...baseTx, gasLimit, maxFeePerGas: txData.maxFeePerGas ? BigInt(txData.maxFeePerGas) : feeData.maxFeePerGas, maxPriorityFeePerGas: txData.maxPriorityFeePerGas ? BigInt(txData.maxPriorityFeePerGas) : feeData.maxPriorityFeePerGas, type: 2, }); } // 3. Sign + submit execute-v2 const execTs = Date.now(); const execSig = await wallet.signMessage( `api/2/perp/execute-v2-${execTs}-${finalPayloadStr}`, ); const execRes = await fetch('https://api.mobula.io/api/2/perp/execute-v2', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ action: data.action, dex: data.dex, chainId: data.chainId, transport: data.transport, payloadStr: finalPayloadStr, timestamp: execTs, signature: execSig, ...(signedTx && { signedTx }), }), }).then(r => r.json()); ``` # Build Close-Position Payload Source: https://docs.mobula.io/exec/perps/perp-payload-close-position POST /2/perp/payloads/close-position Build a signed canonical payload to close (fully or partially) an open perpetual position on Gains Network or Lighter. Canonical action name — one of `withdraw`, `create-account`, `deposit`, `create-order`, `close-position`, `cancel-order`, `update-margin`, `edit-order`. `gains` or `lighter`. Chain where the action lands (e.g., `evm:42161`, `lighter:301`). Mobula market identifier. Present when the action targets a specific market. `offchain-api` — server submits to the DEX off-chain API on the user's behalf (Lighter trades, Lighter `withdraw`, Lighter `create-account`).
`evm-tx` — server broadcasts a user-signed EVM transaction (Lighter `deposit` bridge route, Gains trade actions). The Gains case requires a top-level `signedTx` on execute-v2; the Lighter `deposit` case injects signed txs **inside** `payloadStr`.JSON-stringified canonical envelope. For most actions you forward this byte-for-byte into `/2/perp/execute-v2`. Mutations are required for: Lighter `deposit` (inject `payload.signedTxs`), Lighter `withdraw` (sign `payload.MessageToSign` → `payload.L1Sig`, delete `MessageToSign`), Lighter `create-account` (same as `withdraw` only if `payload.MessageToSign` is present). After mutation, re-stringify and sign execute-v2 over the **new** string. Never alter the envelope metadata (`action`, `dex`, `chainId`, `transport`, `marketId`) — execute-v2 cross-checks it. **Lighter requires the wallet to be a registered account before any trade/withdraw action.** If the EOA has never deposited on Lighter, this endpoint will fail. First-time setup is a two-step prerequisite: 1. **Deposit ≥ 5 USDC** via [`/2/perp/payloads/deposit`](/rest-api-reference/endpoint/perp-payload-deposit) → Lighter creates an `accountIndex` on-chain once the bridge settles. (5 USDC is a Lighter requirement, not a Mobula limit.) 2. **Provision API key + auth token** via [`/2/perp/payloads/create-account`](/rest-api-reference/endpoint/perp-payload-create-account) using that `accountIndex`. Read the [Build Create-Account Payload](/rest-api-reference/endpoint/perp-payload-create-account) page for the full setup flow including how to discover the `accountIndex` after a deposit. Builds the payload for closing an existing position. Close size is either explicit (`amountRaw`) or percentage-based (`closePercentage`). ### Request Body`gains` or `lighter`. Chain of the position (e.g., `evm:42161`, `lighter:301`). Mobula market identifier (e.g., `lighter-btc-usd`). **Gains only — required.** The Gains *trade index*, sent as a **string that parses as a non-negative integer** (e.g. `"0"`, `"919"`). The Gains positions endpoints (`GET /2/wallet/positions/perp/open`, `perp-positions-open` WSS channel) expose a **composite** position id of the form: ``` pos-gains- Not used for Lighter.- -- - ``` e.g. `pos-gains-inj-usd-usdc-0xaa0055ef84ef93138c7c11be1d19dac5dcd08741-0`. `payloads/close-position` does **not** accept this composite id — passing it returns `400 close-position payload generation failed: gains - positionId must be a non-negative integer, got " "`. **Extract the trailing trade index segment** (the final `- `) and send it as a string: ```typescript theme={null} // composite → trade index const tradeIndex = compositeId.split('-').pop(); // e.g. "0" // Send as string. A JS number is rejected by the zod layer // ("expected string, received number"); a string with leading zeros // or decimals fails the non-negative-integer business check. ``` Portion of the position to close, in percent (`0` \< value ≤ `100`). Use `100` for a full close. Mutually exclusive with `amountRaw`. Raw base-token amount to close. Mutually exclusive with `closePercentage`. Additional DEX-specific parameters. For Gains partial closes, the API transparently injects `currentCollateralRaw` from the position cache when available, so you do not need to supply it. ### Authentication Every `/2/perp/payloads/` endpoint verifies the caller by requiring two extra fields in the request body alongside the action parameters: Unix timestamp in milliseconds. Must be within 30 seconds of server time. Older timestamps are rejected to prevent replay. Hex signature (EIP-191 `personal_sign`) of the message `` `${endpoint}-${timestamp}` ``, where `endpoint` is the path **of this endpoint** without the leading slash (e.g., for this page: `api/2/perp/payloads/ ```javascript theme={null} // Replace ``). The recovered signer address becomes the `user` for the request. Single-use — replay returns `403 signature already used`. ` with the action of THIS page (e.g. create-account, deposit, …) const endpoint = 'api/2/perp/payloads/ '; const timestamp = Date.now(); const signature = await wallet.signMessage(`${endpoint}-${timestamp}`); await fetch(`https://api.mobula.io/${endpoint}`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ timestamp, signature, // ...action-specific fields below }), }); ``` ### Authentication errors | Status | `message` | | - | - | | 403 | `timestamp expired` — timestamp older than 30s | | 403 | `signature already used` — replay attempt | | 400 | `zod validation failed` — `timestamp`/`signature` shape invalid | ### Response envelope Every `/2/perp/payloads/ ` endpoint returns the same envelope shape. You pass these fields verbatim into `POST /2/perp/execute-v2` to execute the action. **Top-level shape.** Successful (2xx) responses return `{ data: { ... } }`. A `success: true` flag is only present inside the body of `execute-v2`'s response, not on the payload-build endpoints. Parse defensively: read `body.data`, then check for the action-specific fields you need (e.g. `data.payloadStr`). ### Endpoint-specific errors | Status | `message` | | - | - | | 400 | `close-position payload generation failed` — position not found, invalid close size, or DEX refusal | ### Full flow — close a position end-to-end Single example covering both DEXes (Lighter offchain-api, Gains evm-tx). The flow branches on `data.transport`. ```javascript theme={null} import { ethers } from 'ethers'; // 1. Auth-sign + fetch the close-position payload const endpoint = 'api/2/perp/payloads/close-position'; const ts = Date.now(); const authSig = await wallet.signMessage(`${endpoint}-${ts}`); const { data } = await fetch(`https://api.mobula.io/${endpoint}`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ timestamp: ts, signature: authSig, dex: 'gains', // or 'lighter' chainId: 'evm:42161', // or 'lighter:301' marketId: 'gains-btc-usd', positionId: '12345', // Gains only — Gains trade index closePercentage: 50, // close 50%; or use amountRaw }), }).then(r => r.json()); // 2. Branch on transport let signedTx; const finalPayloadStr = data.payloadStr; // close-position never mutates the envelope if (data.transport === 'evm-tx') { // Gains: sign the single EVM tx and pass as top-level signedTx. // Read nonce / feeData from a real chain RPC — NOT an embedded-wallet // provider, which can return stale or default-to-0 nonce. const txData = JSON.parse(data.payloadStr).payload.data; const provider = new ethers.JsonRpcProvider(rpcUrlFor(txData.chainId)); const [nonce, feeData] = await Promise.all([ provider.getTransactionCount(wallet.address, 'pending'), provider.getFeeData(), ]); signedTx = await wallet.signTransaction({ to: txData.to, data: txData.callData, // calldata field is `callData`, not `data` value: txData.value ? BigInt(txData.value) : 0n, from: wallet.address, chainId: txData.chainId, nonce: txData.nonce ?? nonce, gasLimit: txData.gas ? BigInt(txData.gas) : 1_500_000n, // Diamond proxy under-reports; floor at 1.5 M maxFeePerGas: txData.maxFeePerGas ? BigInt(txData.maxFeePerGas) : (feeData.maxFeePerGas ?? 0n) * 3n, // headroom across the roundtrip maxPriorityFeePerGas: txData.maxPriorityFeePerGas ? BigInt(txData.maxPriorityFeePerGas) : (feeData.maxPriorityFeePerGas ?? 0n), type: 2, }); } // Lighter offchain-api: nothing to sign here // 3. Sign + submit execute-v2 const execTs = Date.now(); const execSig = await wallet.signMessage( `api/2/perp/execute-v2-${execTs}-${finalPayloadStr}`, ); const execRes = await fetch('https://api.mobula.io/api/2/perp/execute-v2', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ action: data.action, dex: data.dex, chainId: data.chainId, marketId: data.marketId, transport: data.transport, payloadStr: finalPayloadStr, timestamp: execTs, signature: execSig, ...(signedTx && { signedTx }), }), }).then(r => r.json()); ``` # Build Create-Account Payload Source: https://docs.mobula.io/exec/perps/perp-payload-create-account POST /2/perp/payloads/create-account Build a signed canonical payload to create/provision the user's account on a perpetual DEX (e.g., register a Lighter sub-account or API key). Canonical action name — one of `withdraw`, `create-account`, `deposit`, `create-order`, `close-position`, `cancel-order`, `update-margin`, `edit-order`. `gains` or `lighter`. Chain where the action lands (e.g., `evm:42161`, `lighter:301`). Mobula market identifier. Present when the action targets a specific market. `offchain-api` — server submits to the DEX off-chain API on the user's behalf (Lighter trades, Lighter `withdraw`, Lighter `create-account`).
`evm-tx` — server broadcasts a user-signed EVM transaction (Lighter `deposit` bridge route, Gains trade actions). The Gains case requires a top-level `signedTx` on execute-v2; the Lighter `deposit` case injects signed txs **inside** `payloadStr`.JSON-stringified canonical envelope. For most actions you forward this byte-for-byte into `/2/perp/execute-v2`. Mutations are required for: Lighter `deposit` (inject `payload.signedTxs`), Lighter `withdraw` (sign `payload.MessageToSign` → `payload.L1Sig`, delete `MessageToSign`), Lighter `create-account` (same as `withdraw` only if `payload.MessageToSign` is present). After mutation, re-stringify and sign execute-v2 over the **new** string. Never alter the envelope metadata (`action`, `dex`, `chainId`, `transport`, `marketId`) — execute-v2 cross-checks it. **Lighter-only.** Gains has no provisioning step — accounts are implicit. Skip this endpoint for Gains. Provisions the signer's Lighter sub-account API key + auth token. Run once per `(L1 address, accountIndex)` after the user's first deposit so subsequent trades, withdrawals, etc. can authenticate against Lighter. ## Account lifecycle on Lighter A wallet (EOA) is **not** a Lighter account by default. Lighter only registers an account on-chain after the L1 address makes its first USDC deposit (≥ **5 USDC**, a Lighter-side requirement). Once the deposit settles, Lighter assigns an `accountIndex` to that L1 address. The integrator must then call this endpoint with the discovered `accountIndex` to provision an API key + auth token — without it, every other Lighter perp endpoint (`create-order`, `close-position`, `withdraw`, …) will fail. End-to-end first-time setup: 1. **Deposit** ≥ 5 USDC via [`/2/perp/payloads/deposit`](/rest-api-reference/endpoint/perp-payload-deposit) → submit via `/2/perp/execute-v2` → poll [`/2/perp/check-process`](/rest-api-reference/endpoint/perp-check-process) until success. 2. **Discover the `accountIndex`** by polling Lighter's account-lookup endpoint (the bridge takes a few seconds to settle on L2): ```http theme={null} GET https://mainnet.zklighter.elliot.ai/api/v1/account?by=l1_address&value=Accept: application/json ``` Response shape (success): `{ "code": 200, "accounts": [{ "account_index": , ... }] }`. Poll every \~1s until `accounts[0].account_index` is present. **Coming soon.** Mobula will expose a proxy endpoint so integrators don't need to call Lighter directly. For now, hit Lighter's URL above. 3. **Provision the API key** by calling this endpoint with the discovered `accountIndex` and submitting via `/2/perp/execute-v2`. The response payload may carry `payload.MessageToSign` — sign it, set `payload.L1Sig`, delete `payload.MessageToSign`, re-stringify, and sign execute-v2 over the new string. 4. The user's wallet can now call all Lighter trade/withdraw endpoints. ### Request BodyMust be `lighter`. Must be `lighter:304` (the only chain that accepts Lighter `create-account` today). Lighter sub-account index (non-negative integer). Discovered via the Lighter `/api/v1/account?by=l1_address&value= ` lookup after the first deposit settles. Lighter API key slot to provision (≥ 0). Pick any unused slot. Defaults server-side if omitted. ### Authentication Every `/2/perp/payloads/` endpoint verifies the caller by requiring two extra fields in the request body alongside the action parameters: Unix timestamp in milliseconds. Must be within 30 seconds of server time. Older timestamps are rejected to prevent replay. Hex signature (EIP-191 `personal_sign`) of the message `` `${endpoint}-${timestamp}` ``, where `endpoint` is the path **of this endpoint** without the leading slash (e.g., for this page: `api/2/perp/payloads/ ```javascript theme={null} // Replace ``). The recovered signer address becomes the `user` for the request. Single-use — replay returns `403 signature already used`. ` with the action of THIS page (e.g. create-account, deposit, …) const endpoint = 'api/2/perp/payloads/ '; const timestamp = Date.now(); const signature = await wallet.signMessage(`${endpoint}-${timestamp}`); await fetch(`https://api.mobula.io/${endpoint}`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ timestamp, signature, // ...action-specific fields below }), }); ``` ### Authentication errors | Status | `message` | | - | - | | 403 | `timestamp expired` — timestamp older than 30s | | 403 | `signature already used` — replay attempt | | 400 | `zod validation failed` — `timestamp`/`signature` shape invalid | ### Response envelope Every `/2/perp/payloads/ ` endpoint returns the same envelope shape. You pass these fields verbatim into `POST /2/perp/execute-v2` to execute the action. **Top-level shape.** Successful (2xx) responses return `{ data: { ... } }`. A `success: true` flag is only present inside the body of `execute-v2`'s response, not on the payload-build endpoints. Parse defensively: read `body.data`, then check for the action-specific fields you need (e.g. `data.payloadStr`). ### Endpoint-specific errors | Status | `message` | | - | - | | 400 | `accountIndex must be a non-negative integer for lighter create-account` — missing or invalid `accountIndex` | | 400 | `Invalid chainId " Canonical action name — one of `withdraw`, `create-account`, `deposit`, `create-order`, `close-position`, `cancel-order`, `update-margin`, `edit-order`. `gains` or `lighter`. Chain where the action lands (e.g., `evm:42161`, `lighter:301`). Mobula market identifier. Present when the action targets a specific market. `offchain-api` — server submits to the DEX off-chain API on the user's behalf (Lighter trades, Lighter `withdraw`, Lighter `create-account`).
`evm-tx` — server broadcasts a user-signed EVM transaction (Lighter `deposit` bridge route, Gains trade actions). The Gains case requires a top-level `signedTx` on execute-v2; the Lighter `deposit` case injects signed txs **inside** `payloadStr`.JSON-stringified canonical envelope. For most actions you forward this byte-for-byte into `/2/perp/execute-v2`. Mutations are required for: Lighter `deposit` (inject `payload.signedTxs`), Lighter `withdraw` (sign `payload.MessageToSign` → `payload.L1Sig`, delete `MessageToSign`), Lighter `create-account` (same as `withdraw` only if `payload.MessageToSign` is present). After mutation, re-stringify and sign execute-v2 over the **new** string. Never alter the envelope metadata (`action`, `dex`, `chainId`, `transport`, `marketId`) — execute-v2 cross-checks it. " for lighter create-account` — chainId other than `lighter:304` | | 400 | `create-account payload generation failed` — Lighter rejected provisioning (e.g., slot already in use) | | 501 | `payload action "create-account" not implemented yet` — `dex` other than `lighter` | ### Full flow — provision a Lighter sub-account end-to-end Assumes the wallet has already deposited ≥ 5 USDC and you have polled Lighter to discover its `accountIndex`. Snippet shows step 3 of the lifecycle above. ```javascript theme={null} // 1. Auth-sign + fetch the create-account payload const endpoint = 'api/2/perp/payloads/create-account'; const ts = Date.now(); const authSig = await wallet.signMessage(`${endpoint}-${ts}`); const { data } = await fetch(`https://api.mobula.io/${endpoint}`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ timestamp: ts, signature: authSig, dex: 'lighter', chainId: 'lighter:304', accountIndex, // discovered from Lighter's /api/v1/account lookup apiKeyIndex: 100, // any unused slot }), }).then(r => r.json()); // 2. Mutate the envelope only if Lighter returns an L1 challenge const parsed = JSON.parse(data.payloadStr); let finalPayloadStr = data.payloadStr; if (parsed.payload.MessageToSign) { parsed.payload.L1Sig = await wallet.signMessage(parsed.payload.MessageToSign); delete parsed.payload.MessageToSign; finalPayloadStr = JSON.stringify(parsed); } // 3. Sign + submit execute-v2 const execTs = Date.now(); const execSig = await wallet.signMessage( `api/2/perp/execute-v2-${execTs}-${finalPayloadStr}`, ); const execRes = await fetch('https://api.mobula.io/api/2/perp/execute-v2', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ action: data.action, dex: data.dex, chainId: data.chainId, transport: data.transport, payloadStr: finalPayloadStr, timestamp: execTs, signature: execSig, }), }).then(r => r.json()); ``` ### Helper — discover `accountIndex` after a deposit ```javascript theme={null} async function pollLighterAccountIndex(eoaAddress, { intervalMs = 1000, maxRetries = 200 } = {}) { for (let i = 0; i < maxRetries; i++) { const res = await fetch( `https://mainnet.zklighter.elliot.ai/api/v1/account?by=l1_address&value=${eoaAddress}`, { headers: { Accept: 'application/json' } }, ).then(r => r.json()).catch(() => null); if (res?.code === 200 && res.accounts?.[0]?.account_index != null) { return res.accounts[0].account_index; } await new Promise(r => setTimeout(r, intervalMs)); } throw new Error(`Lighter accountIndex not found for ${eoaAddress} after ${maxRetries} polls`); } ``` # Build Create-Order Payload Source: https://docs.mobula.io/exec/perps/perp-payload-create-order POST /2/perp/payloads/create-order Build a signed canonical payload to open a new perpetual position on Gains Network or Lighter. The response is submitted as-is to /2/perp/execute-v2. **Lighter requires the wallet to be a registered account before any trade/withdraw action.** If the EOA has never deposited on Lighter, this endpoint will fail. First-time setup is a two-step prerequisite: 1. **Deposit ≥ 5 USDC** via [`/2/perp/payloads/deposit`](/rest-api-reference/endpoint/perp-payload-deposit) → Lighter creates an `accountIndex` on-chain once the bridge settles. (5 USDC is a Lighter requirement, not a Mobula limit.) 2. **Provision API key + auth token** via [`/2/perp/payloads/create-account`](/rest-api-reference/endpoint/perp-payload-create-account) using that `accountIndex`. Read the [Build Create-Account Payload](/rest-api-reference/endpoint/perp-payload-create-account) page for the full setup flow including how to discover the `accountIndex` after a deposit. **Gains requires a one-time USDC approval per wallet.** Gains' Diamond proxy executes `USDC.transferFrom(user, gainsVault, collateral)` mid-trade. Without an `approve(spender, …)` granting it allowance, `/2/perp/execute-v2` returns `400` with the on-chain revert: ``` ERC20: transfer amount exceeds allowance ``` Before the first Gains order on a wallet, send `USDC.approve(payload.data.to, MaxUint256)` (the `spender` is the `to` field from the build response). See [Approval prerequisite](/cookbooks/perp-execution-flow#gains-usdc-allowance-on-the-trading-proxy) in the cookbook for a copy-paste helper. Native USDC per chain — Arbitrum `0xaf88d065e77c8cC2239327C5EDb3A432268e5831`, Base `0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913`. Builds the canonical order payload used by `/2/perp/execute-v2`. The signer recovered from the `signature` field becomes the order's `user`. ### Request BodyBase token address, symbol, or Mobula asset id. Quote token of the market. Semantics differ per DEX: * **Lighter** — pass the ERC-20 collateral symbol (`USDC`). * **Gains** — pass the synthetic quote (`USD`). Sending `USDC` returns `"No market matching base/quote"`. When unsure, pass `marketId` (e.g. `gains-btc-usd`, `lighter-btc-usd`) and the field is derived server-side. Leverage multiplier (e.g., `10`). `true` for long, `false` for short. `true` if the order must only reduce an existing position. Collateral in `quote` units (e.g., USDC). One of `market`, `limit`, `stop_limit`. Default `market`. Trigger/limit price. Required for `limit` and `stop_limit`. Take-profit price. Stop-loss price. Raw position size in base-token units. If omitted, derived from `collateralAmount * leverage`. Max slippage in percent. Routing **hint**, not a strict filter. The router prefers the requested chains but may fall back to another supported chain if the requested market is not deployed on any of them. Example: passing `chainIds: ['evm:42161']` for a market that only exists on Base will silently return `chainId: 'evm:8453'`. **Always trust the response `chainId`** when broadcasting. Pass an explicit `marketId` (or rely on the response) for unambiguous routing. Restrict routing to `gains` and/or `lighter`. `0` = cross, `1` = isolated (DEX-specific). Referrer wallet address for fee sharing. Force a specific Mobula market instead of routing. ### Authentication Every `/2/perp/payloads/` endpoint verifies the caller by requiring two extra fields in the request body alongside the action parameters: Unix timestamp in milliseconds. Must be within 30 seconds of server time. Older timestamps are rejected to prevent replay. Hex signature (EIP-191 `personal_sign`) of the message `` `${endpoint}-${timestamp}` ``, where `endpoint` is the path **of this endpoint** without the leading slash (e.g., for this page: `api/2/perp/payloads/ ```javascript theme={null} // Replace ``). The recovered signer address becomes the `user` for the request. Single-use — replay returns `403 signature already used`. ` with the action of THIS page (e.g. create-account, deposit, …) const endpoint = 'api/2/perp/payloads/ '; const timestamp = Date.now(); const signature = await wallet.signMessage(`${endpoint}-${timestamp}`); await fetch(`https://api.mobula.io/${endpoint}`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ timestamp, signature, // ...action-specific fields below }), }); ``` ### Authentication errors | Status | `message` | | - | - | | 403 | `timestamp expired` — timestamp older than 30s | | 403 | `signature already used` — replay attempt | | 400 | `zod validation failed` — `timestamp`/`signature` shape invalid | ### Response envelope Every `/2/perp/payloads/ ` endpoint returns the same envelope shape. You pass these fields verbatim into `POST /2/perp/execute-v2` to execute the action. **Top-level shape.** Successful (2xx) responses return `{ data: { ... } }`. A `success: true` flag is only present inside the body of `execute-v2`'s response, not on the payload-build endpoints. Parse defensively: read `body.data`, then check for the action-specific fields you need (e.g. `data.payloadStr`). ### Endpoint-specific errors | Status | `message` | | - | - | | 500 | `could not build create-order payload` — no DEX could build a payload for the given parameters | ### Full flow — open a position end-to-end Single example covering both DEXes (Lighter offchain-api, Gains evm-tx). The flow branches on `data.transport`. ```javascript theme={null} import { ethers } from 'ethers'; // 1. Auth-sign + fetch the create-order payload const endpoint = 'api/2/perp/payloads/create-order'; const ts = Date.now(); const authSig = await wallet.signMessage(`${endpoint}-${ts}`); const { data } = await fetch(`https://api.mobula.io/${endpoint}`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ timestamp: ts, signature: authSig, baseToken: 'BTC', quote: 'USDC', // Lighter quote. For Gains: 'USD' (synthetic) — or omit and pass `marketId`. long: true, reduceOnly: false, leverage: 10, collateralAmount: 100, // 100 USDC of collateral orderType: 'market', maxSlippageP: 0.5, dexes: ['lighter'], // or ['gains'], or omit to let routing pick }), }).then(r => r.json()); // 2. Branch on transport let signedTx; const finalPayloadStr = data.payloadStr; if (data.transport === 'evm-tx') { // Gains: sign the single EVM tx and pass as top-level signedTx. // Read nonce / feeData from a real chain RPC — NOT an embedded-wallet // provider, which can return stale or default-to-0 nonce. const txData = JSON.parse(data.payloadStr).payload.data; const provider = new ethers.JsonRpcProvider(rpcUrlFor(txData.chainId)); const [nonce, feeData] = await Promise.all([ provider.getTransactionCount(wallet.address, 'pending'), provider.getFeeData(), ]); signedTx = await wallet.signTransaction({ to: txData.to, data: txData.callData, // calldata field is `callData`, not `data` value: txData.value ? BigInt(txData.value) : 0n, from: wallet.address, chainId: txData.chainId, nonce: txData.nonce ?? nonce, // Gains Diamond proxy under-reports estimateGas (~28 k vs ~270 k real burn); // use a floor of 1.5 M or take max(estimate * 2, 1_500_000n). gasLimit: txData.gas ? BigInt(txData.gas) : 1_500_000n, // Bump 3x to absorb base-fee drift across the build → execute roundtrip. maxFeePerGas: txData.maxFeePerGas ? BigInt(txData.maxFeePerGas) : (feeData.maxFeePerGas ?? 0n) * 3n, maxPriorityFeePerGas: txData.maxPriorityFeePerGas ? BigInt(txData.maxPriorityFeePerGas) : (feeData.maxPriorityFeePerGas ?? 0n), type: 2, }); } // Lighter offchain-api: nothing to sign here // 3. Sign + submit execute-v2 const execTs = Date.now(); const execSig = await wallet.signMessage( `api/2/perp/execute-v2-${execTs}-${finalPayloadStr}`, ); const execRes = await fetch('https://api.mobula.io/api/2/perp/execute-v2', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ action: data.action, dex: data.dex, chainId: data.chainId, marketId: data.marketId, transport: data.transport, payloadStr: finalPayloadStr, timestamp: execTs, signature: execSig, ...(signedTx && { signedTx }), }), }).then(r => r.json()); ``` # Build Deposit Payload Source: https://docs.mobula.io/exec/perps/perp-payload-deposit POST /2/perp/payloads/deposit Build a signed canonical payload to deposit USDC collateral into a perpetual DEX account (Lighter) or bridge USDC into a Gains account. Canonical action name — one of `withdraw`, `create-account`, `deposit`, `create-order`, `close-position`, `cancel-order`, `update-margin`, `edit-order`. `gains` or `lighter`. Chain where the action lands (e.g., `evm:42161`, `lighter:301`). Mobula market identifier. Present when the action targets a specific market. `offchain-api` — server submits to the DEX off-chain API on the user's behalf (Lighter trades, Lighter `withdraw`, Lighter `create-account`).
`evm-tx` — server broadcasts a user-signed EVM transaction (Lighter `deposit` bridge route, Gains trade actions). The Gains case requires a top-level `signedTx` on execute-v2; the Lighter `deposit` case injects signed txs **inside** `payloadStr`.JSON-stringified canonical envelope. For most actions you forward this byte-for-byte into `/2/perp/execute-v2`. Mutations are required for: Lighter `deposit` (inject `payload.signedTxs`), Lighter `withdraw` (sign `payload.MessageToSign` → `payload.L1Sig`, delete `MessageToSign`), Lighter `create-account` (same as `withdraw` only if `payload.MessageToSign` is present). After mutation, re-stringify and sign execute-v2 over the **new** string. Never alter the envelope metadata (`action`, `dex`, `chainId`, `transport`, `marketId`) — execute-v2 cross-checks it. **Lighter-only.** Gains has no deposit endpoint — collateral on Gains is sent directly with each `create-order`. Skip this for Gains. Bridges USDC from `originChainId` to the Lighter L2 account via a multi-step bridge route. Deposits are eventually consistent and tracked asynchronously — the `execute-v2` response carries a `processId` you poll via `/2/perp/check-process`.**First-time deposits register the account on Lighter.** If the EOA has never deposited on Lighter, this call must transfer **≥ 5 USDC** (a Lighter-side requirement). Once the bridge settles, Lighter assigns an `accountIndex` to the L1 address — needed by [`/2/perp/payloads/create-account`](/rest-api-reference/endpoint/perp-payload-create-account) and every subsequent trade/withdraw call. See the create-account page for how to discover the `accountIndex` afterwards. ### Lighter deposit payload shape The response's `payloadStr` is a canonical envelope whose `payload` carries a bridge route with one or more transaction steps: ```jsonc theme={null} { "action": "deposit", "dex": "lighter", "chainId": "lighter:304", "transport": "evm-tx", "payload": { "route": "...", "steps": [ { "id": "...", "kind": "transaction", "items": [ { "status": "incomplete", "data": { "to": "0x..", "data": "0x..", "value": "0", "chainId": 42161, "gas": "...", "maxFeePerGas": "...", "maxPriorityFeePerGas": "..." } } ] } // additional steps (approvals, bridge, …) ] } } ``` **Client workflow (Lighter):** 1. Parse `payloadStr`. 2. For every step with `kind === "transaction"` and every `item` whose `status !== "complete"`, sign the tx with the user's key on `item.data.chainId`. 3. Push each signed hex string (in order) into a new array `payload.signedTxs`. 4. Re-stringify the envelope → `finalPayloadStr`. 5. Sign `` `api/2/perp/execute-v2-${timestamp}-${finalPayloadStr}` `` and call `/2/perp/execute-v2` with **that** `payloadStr` and **no** top-level `signedTx`. ### Request BodyMust be `lighter`. Destination Lighter chain. Must be `lighter:304` — only id the router accepts for deposit today. EVM chain holding the user's USDC. Confirmed working: `evm:42161` (Arbitrum), `evm:8453` (Base). Other EVM chains may resolve — open an issue if you need one that isn't listed. USDC amount as a decimal string (e.g., `"250"` or `"100.5"`). Must be positive. ### Authentication Every `/2/perp/payloads/` endpoint verifies the caller by requiring two extra fields in the request body alongside the action parameters: Unix timestamp in milliseconds. Must be within 30 seconds of server time. Older timestamps are rejected to prevent replay. Hex signature (EIP-191 `personal_sign`) of the message `` `${endpoint}-${timestamp}` ``, where `endpoint` is the path **of this endpoint** without the leading slash (e.g., for this page: `api/2/perp/payloads/ ```javascript theme={null} // Replace ``). The recovered signer address becomes the `user` for the request. Single-use — replay returns `403 signature already used`. ` with the action of THIS page (e.g. create-account, deposit, …) const endpoint = 'api/2/perp/payloads/ '; const timestamp = Date.now(); const signature = await wallet.signMessage(`${endpoint}-${timestamp}`); await fetch(`https://api.mobula.io/${endpoint}`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ timestamp, signature, // ...action-specific fields below }), }); ``` ### Authentication errors | Status | `message` | | - | - | | 403 | `timestamp expired` — timestamp older than 30s | | 403 | `signature already used` — replay attempt | | 400 | `zod validation failed` — `timestamp`/`signature` shape invalid | ### Response envelope Every `/2/perp/payloads/ ` endpoint returns the same envelope shape. You pass these fields verbatim into `POST /2/perp/execute-v2` to execute the action. **Top-level shape.** Successful (2xx) responses return `{ data: { ... } }`. A `success: true` flag is only present inside the body of `execute-v2`'s response, not on the payload-build endpoints. Parse defensively: read `body.data`, then check for the action-specific fields you need (e.g. `data.payloadStr`). ### Endpoint-specific errors | Status | `message` | | - | - | | 400 | `deposit payload generation failed` — bridge unavailable, insufficient USDC, or DEX refusal | ### Example — Lighter bridge from Arbitrum ```javascript theme={null} import { ethers } from 'ethers'; const endpoint = 'api/2/perp/payloads/deposit'; const timestamp = Date.now(); const signature = await wallet.signMessage(`${endpoint}-${timestamp}`); const payloadRes = await fetch(`https://api.mobula.io/${endpoint}`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ timestamp, signature, dex: 'lighter', chainId: 'lighter:304', originChainId: 'evm:42161', amountUsdc: '250', }), }).then(r => r.json()); const { data } = payloadRes; const parsed = JSON.parse(data.payloadStr); // 1. sign each bridge tx in order const provider = new ethers.JsonRpcProvider(arbitrumRpcUrl); let nonce = await provider.getTransactionCount(wallet.address); const feeData = await provider.getFeeData(); const signedTxs = []; for (const step of parsed.payload.steps) { if (step.kind !== 'transaction') continue; for (const item of step.items) { if (item.status === 'complete') continue; const tx = item.data; const signed = await wallet.signTransaction({ to: tx.to, data: tx.data, value: tx.value ? BigInt(tx.value) : 0n, chainId: tx.chainId, nonce: nonce++, gasLimit: tx.gas ? BigInt(tx.gas) : 1_500_000n, maxFeePerGas: tx.maxFeePerGas ? BigInt(tx.maxFeePerGas) : feeData.maxFeePerGas, maxPriorityFeePerGas: tx.maxPriorityFeePerGas ? BigInt(tx.maxPriorityFeePerGas) : feeData.maxPriorityFeePerGas, type: 2, }); signedTxs.push(signed); } } // 2. inject + re-stringify parsed.payload.signedTxs = signedTxs; const finalPayloadStr = JSON.stringify(parsed); // 3. sign execute-v2 over the UPDATED string const execTs = Date.now(); const execSig = await wallet.signMessage(`api/2/perp/execute-v2-${execTs}-${finalPayloadStr}`); const execRes = await fetch('https://api.mobula.io/api/2/perp/execute-v2', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ action: data.action, dex: data.dex, chainId: data.chainId, transport: data.transport, payloadStr: finalPayloadStr, timestamp: execTs, signature: execSig, }), }).then(r => r.json()); // poll execRes.data.processId via /2/perp/check-process ``` # Build Edit-Order Payload Source: https://docs.mobula.io/exec/perps/perp-payload-edit-order POST /2/perp/payloads/edit-order Build a signed canonical payload to change the TP/SL of an existing perpetual position or pending order. Canonical action name — one of `withdraw`, `create-account`, `deposit`, `create-order`, `close-position`, `cancel-order`, `update-margin`, `edit-order`. `gains` or `lighter`. Chain where the action lands (e.g., `evm:42161`, `lighter:301`). Mobula market identifier. Present when the action targets a specific market. `offchain-api` — server submits to the DEX off-chain API on the user's behalf (Lighter trades, Lighter `withdraw`, Lighter `create-account`).
`evm-tx` — server broadcasts a user-signed EVM transaction (Lighter `deposit` bridge route, Gains trade actions). The Gains case requires a top-level `signedTx` on execute-v2; the Lighter `deposit` case injects signed txs **inside** `payloadStr`.JSON-stringified canonical envelope. For most actions you forward this byte-for-byte into `/2/perp/execute-v2`. Mutations are required for: Lighter `deposit` (inject `payload.signedTxs`), Lighter `withdraw` (sign `payload.MessageToSign` → `payload.L1Sig`, delete `MessageToSign`), Lighter `create-account` (same as `withdraw` only if `payload.MessageToSign` is present). After mutation, re-stringify and sign execute-v2 over the **new** string. Never alter the envelope metadata (`action`, `dex`, `chainId`, `transport`, `marketId`) — execute-v2 cross-checks it. **Lighter requires the wallet to be a registered account before any trade/withdraw action.** If the EOA has never deposited on Lighter, this endpoint will fail. First-time setup is a two-step prerequisite: 1. **Deposit ≥ 5 USDC** via [`/2/perp/payloads/deposit`](/rest-api-reference/endpoint/perp-payload-deposit) → Lighter creates an `accountIndex` on-chain once the bridge settles. (5 USDC is a Lighter requirement, not a Mobula limit.) 2. **Provision API key + auth token** via [`/2/perp/payloads/create-account`](/rest-api-reference/endpoint/perp-payload-create-account) using that `accountIndex`. Read the [Build Create-Account Payload](/rest-api-reference/endpoint/perp-payload-create-account) page for the full setup flow including how to discover the `accountIndex` after a deposit. Edits the take-profit and/or stop-loss attached to a position or pending order. Pass `0` on Gains to remove a leg. ### Request Body`gains` or `lighter`. Chain of the position/order. Mobula market identifier. Gains trade index (regex `^\d+$`). Required for Gains. New take-profit price (≥ 0). On Gains, pass `0` to clear the TP. New stop-loss price (≥ 0). On Gains, pass `0` to clear the SL. ### Authentication Every `/2/perp/payloads/` endpoint verifies the caller by requiring two extra fields in the request body alongside the action parameters: Unix timestamp in milliseconds. Must be within 30 seconds of server time. Older timestamps are rejected to prevent replay. Hex signature (EIP-191 `personal_sign`) of the message `` `${endpoint}-${timestamp}` ``, where `endpoint` is the path **of this endpoint** without the leading slash (e.g., for this page: `api/2/perp/payloads/ ```javascript theme={null} // Replace ``). The recovered signer address becomes the `user` for the request. Single-use — replay returns `403 signature already used`. ` with the action of THIS page (e.g. create-account, deposit, …) const endpoint = 'api/2/perp/payloads/ '; const timestamp = Date.now(); const signature = await wallet.signMessage(`${endpoint}-${timestamp}`); await fetch(`https://api.mobula.io/${endpoint}`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ timestamp, signature, // ...action-specific fields below }), }); ``` ### Authentication errors | Status | `message` | | - | - | | 403 | `timestamp expired` — timestamp older than 30s | | 403 | `signature already used` — replay attempt | | 400 | `zod validation failed` — `timestamp`/`signature` shape invalid | ### Response envelope Every `/2/perp/payloads/ ` endpoint returns the same envelope shape. You pass these fields verbatim into `POST /2/perp/execute-v2` to execute the action. **Top-level shape.** Successful (2xx) responses return `{ data: { ... } }`. A `success: true` flag is only present inside the body of `execute-v2`'s response, not on the payload-build endpoints. Parse defensively: read `body.data`, then check for the action-specific fields you need (e.g. `data.payloadStr`). ### Endpoint-specific errors | Status | `message` | | - | - | | 400 | `edit-order payload action failed` — invalid TP/SL direction, missing position, or DEX refusal | ### Full flow — edit TP/SL end-to-end Single example covering both DEXes (Lighter offchain-api, Gains evm-tx). The flow branches on `data.transport`. ```javascript theme={null} import { ethers } from 'ethers'; // 1. Auth-sign + fetch the edit-order payload const endpoint = 'api/2/perp/payloads/edit-order'; const ts = Date.now(); const authSig = await wallet.signMessage(`${endpoint}-${ts}`); const { data } = await fetch(`https://api.mobula.io/${endpoint}`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ timestamp: ts, signature: authSig, dex: 'gains', // or 'lighter' chainId: 'evm:42161', // or 'lighter:301' marketId: 'gains-btc-usd', positionId: '12345', // Gains trade index — required for Gains newTp: 75000, // pass 0 on Gains to clear the TP newSl: 0, // pass 0 on Gains to clear the SL }), }).then(r => r.json()); // 2. Branch on transport let signedTx; const finalPayloadStr = data.payloadStr; if (data.transport === 'evm-tx') { // Gains const txData = JSON.parse(data.payloadStr).payload.data; const provider = new ethers.JsonRpcProvider(rpcUrlFor(txData.chainId)); const feeData = await provider.getFeeData(); const baseTx = { to: txData.to, data: txData.callData, value: txData.value ? BigInt(txData.value) : 0n, from: wallet.address, chainId: txData.chainId, nonce: txData.nonce ?? await provider.getTransactionCount(wallet.address), }; const gasLimit = txData.gas ? BigInt(txData.gas) : await provider.estimateGas(baseTx); signedTx = await wallet.signTransaction({ ...baseTx, gasLimit, maxFeePerGas: txData.maxFeePerGas ? BigInt(txData.maxFeePerGas) : feeData.maxFeePerGas, maxPriorityFeePerGas: txData.maxPriorityFeePerGas ? BigInt(txData.maxPriorityFeePerGas) : feeData.maxPriorityFeePerGas, type: 2, }); } // 3. Sign + submit execute-v2 const execTs = Date.now(); const execSig = await wallet.signMessage( `api/2/perp/execute-v2-${execTs}-${finalPayloadStr}`, ); const execRes = await fetch('https://api.mobula.io/api/2/perp/execute-v2', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ action: data.action, dex: data.dex, chainId: data.chainId, marketId: data.marketId, transport: data.transport, payloadStr: finalPayloadStr, timestamp: execTs, signature: execSig, ...(signedTx && { signedTx }), }), }).then(r => r.json()); ``` # Build Update-Margin Payload Source: https://docs.mobula.io/exec/perps/perp-payload-update-margin POST /2/perp/payloads/update-margin Build a signed canonical payload to add or remove collateral from an open perpetual position (Lighter) or change its per-trade leverage (Gains). Canonical action name — one of `withdraw`, `create-account`, `deposit`, `create-order`, `close-position`, `cancel-order`, `update-margin`, `edit-order`. `gains` or `lighter`. Chain where the action lands (e.g., `evm:42161`, `lighter:301`). Mobula market identifier. Present when the action targets a specific market. `offchain-api` — server submits to the DEX off-chain API on the user's behalf (Lighter trades, Lighter `withdraw`, Lighter `create-account`).
`evm-tx` — server broadcasts a user-signed EVM transaction (Lighter `deposit` bridge route, Gains trade actions). The Gains case requires a top-level `signedTx` on execute-v2; the Lighter `deposit` case injects signed txs **inside** `payloadStr`.JSON-stringified canonical envelope. For most actions you forward this byte-for-byte into `/2/perp/execute-v2`. Mutations are required for: Lighter `deposit` (inject `payload.signedTxs`), Lighter `withdraw` (sign `payload.MessageToSign` → `payload.L1Sig`, delete `MessageToSign`), Lighter `create-account` (same as `withdraw` only if `payload.MessageToSign` is present). After mutation, re-stringify and sign execute-v2 over the **new** string. Never alter the envelope metadata (`action`, `dex`, `chainId`, `transport`, `marketId`) — execute-v2 cross-checks it. **Lighter requires the wallet to be a registered account before any trade/withdraw action.** If the EOA has never deposited on Lighter, this endpoint will fail. First-time setup is a two-step prerequisite: 1. **Deposit ≥ 5 USDC** via [`/2/perp/payloads/deposit`](/rest-api-reference/endpoint/perp-payload-deposit) → Lighter creates an `accountIndex` on-chain once the bridge settles. (5 USDC is a Lighter requirement, not a Mobula limit.) 2. **Provision API key + auth token** via [`/2/perp/payloads/create-account`](/rest-api-reference/endpoint/perp-payload-create-account) using that `accountIndex`. Read the [Build Create-Account Payload](/rest-api-reference/endpoint/perp-payload-create-account) page for the full setup flow including how to discover the `accountIndex` after a deposit. Adjusts margin on an open position. The exact semantics depend on the DEX: * **Lighter** — supply `usdcAmount` and `increase` to add or remove USDC collateral on the market's position. * **Gains** — supply `newLeverage` to change the trade's leverage, which effectively adjusts its collateral. ### Request Body`gains` or `lighter`. Chain of the position. Mobula market identifier. Gains trade index. Required for Gains. **Lighter only.** USDC amount to add or remove (> 0). **Lighter only.** `true` to add margin, `false` to remove it. **Gains only.** New per-trade leverage (> 0). ### Authentication Every `/2/perp/payloads/` endpoint verifies the caller by requiring two extra fields in the request body alongside the action parameters: Unix timestamp in milliseconds. Must be within 30 seconds of server time. Older timestamps are rejected to prevent replay. Hex signature (EIP-191 `personal_sign`) of the message `` `${endpoint}-${timestamp}` ``, where `endpoint` is the path **of this endpoint** without the leading slash (e.g., for this page: `api/2/perp/payloads/ ```javascript theme={null} // Replace ``). The recovered signer address becomes the `user` for the request. Single-use — replay returns `403 signature already used`. ` with the action of THIS page (e.g. create-account, deposit, …) const endpoint = 'api/2/perp/payloads/ '; const timestamp = Date.now(); const signature = await wallet.signMessage(`${endpoint}-${timestamp}`); await fetch(`https://api.mobula.io/${endpoint}`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ timestamp, signature, // ...action-specific fields below }), }); ``` ### Authentication errors | Status | `message` | | - | - | | 403 | `timestamp expired` — timestamp older than 30s | | 403 | `signature already used` — replay attempt | | 400 | `zod validation failed` — `timestamp`/`signature` shape invalid | ### Response envelope Every `/2/perp/payloads/ ` endpoint returns the same envelope shape. You pass these fields verbatim into `POST /2/perp/execute-v2` to execute the action. **Top-level shape.** Successful (2xx) responses return `{ data: { ... } }`. A `success: true` flag is only present inside the body of `execute-v2`'s response, not on the payload-build endpoints. Parse defensively: read `body.data`, then check for the action-specific fields you need (e.g. `data.payloadStr`). ### Endpoint-specific errors | Status | `message` | | - | - | | 400 | `update-margin payload action failed` — missing position, wrong leg supplied for the DEX, or DEX refusal | ### Full flow — update margin end-to-end Single example covering both DEXes (Lighter offchain-api with `usdcAmount`+`increase`, Gains evm-tx with `newLeverage`). The flow branches on `data.transport`. ```javascript theme={null} import { ethers } from 'ethers'; // 1. Auth-sign + fetch the update-margin payload const endpoint = 'api/2/perp/payloads/update-margin'; const ts = Date.now(); const authSig = await wallet.signMessage(`${endpoint}-${ts}`); // Lighter: add 50 USDC of margin to BTC-USD const lighterBody = { timestamp: ts, signature: authSig, dex: 'lighter', chainId: 'lighter:301', marketId: 'lighter-btc-usd', usdcAmount: 50, increase: true, }; // Gains alternative: lower leverage to 5x on Gains trade #12345 // const gainsBody = { // timestamp: ts, signature: authSig, // dex: 'gains', chainId: 'evm:42161', // marketId: 'gains-btc-usd', // positionId: '12345', newLeverage: 5, // }; const { data } = await fetch(`https://api.mobula.io/${endpoint}`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(lighterBody), }).then(r => r.json()); // 2. Branch on transport let signedTx; const finalPayloadStr = data.payloadStr; if (data.transport === 'evm-tx') { // Gains const txData = JSON.parse(data.payloadStr).payload.data; const provider = new ethers.JsonRpcProvider(rpcUrlFor(txData.chainId)); const feeData = await provider.getFeeData(); const baseTx = { to: txData.to, data: txData.callData, value: txData.value ? BigInt(txData.value) : 0n, from: wallet.address, chainId: txData.chainId, nonce: txData.nonce ?? await provider.getTransactionCount(wallet.address), }; const gasLimit = txData.gas ? BigInt(txData.gas) : await provider.estimateGas(baseTx); signedTx = await wallet.signTransaction({ ...baseTx, gasLimit, maxFeePerGas: txData.maxFeePerGas ? BigInt(txData.maxFeePerGas) : feeData.maxFeePerGas, maxPriorityFeePerGas: txData.maxPriorityFeePerGas ? BigInt(txData.maxPriorityFeePerGas) : feeData.maxPriorityFeePerGas, type: 2, }); } // 3. Sign + submit execute-v2 const execTs = Date.now(); const execSig = await wallet.signMessage( `api/2/perp/execute-v2-${execTs}-${finalPayloadStr}`, ); const execRes = await fetch('https://api.mobula.io/api/2/perp/execute-v2', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ action: data.action, dex: data.dex, chainId: data.chainId, marketId: data.marketId, transport: data.transport, payloadStr: finalPayloadStr, timestamp: execTs, signature: execSig, ...(signedTx && { signedTx }), }), }).then(r => r.json()); ``` # Build Withdraw Payload Source: https://docs.mobula.io/exec/perps/perp-payload-withdraw POST /2/perp/payloads/withdraw Build a signed canonical payload to withdraw USDC collateral from a perpetual DEX account back to the user's wallet. Canonical action name — one of `withdraw`, `create-account`, `deposit`, `create-order`, `close-position`, `cancel-order`, `update-margin`, `edit-order`. `gains` or `lighter`. Chain where the action lands (e.g., `evm:42161`, `lighter:301`). Mobula market identifier. Present when the action targets a specific market. `offchain-api` — server submits to the DEX off-chain API on the user's behalf (Lighter trades, Lighter `withdraw`, Lighter `create-account`).
`evm-tx` — server broadcasts a user-signed EVM transaction (Lighter `deposit` bridge route, Gains trade actions). The Gains case requires a top-level `signedTx` on execute-v2; the Lighter `deposit` case injects signed txs **inside** `payloadStr`.JSON-stringified canonical envelope. For most actions you forward this byte-for-byte into `/2/perp/execute-v2`. Mutations are required for: Lighter `deposit` (inject `payload.signedTxs`), Lighter `withdraw` (sign `payload.MessageToSign` → `payload.L1Sig`, delete `MessageToSign`), Lighter `create-account` (same as `withdraw` only if `payload.MessageToSign` is present). After mutation, re-stringify and sign execute-v2 over the **new** string. Never alter the envelope metadata (`action`, `dex`, `chainId`, `transport`, `marketId`) — execute-v2 cross-checks it. **Lighter requires the wallet to be a registered account before any trade/withdraw action.** If the EOA has never deposited on Lighter, this endpoint will fail. First-time setup is a two-step prerequisite: 1. **Deposit ≥ 5 USDC** via [`/2/perp/payloads/deposit`](/rest-api-reference/endpoint/perp-payload-deposit) → Lighter creates an `accountIndex` on-chain once the bridge settles. (5 USDC is a Lighter requirement, not a Mobula limit.) 2. **Provision API key + auth token** via [`/2/perp/payloads/create-account`](/rest-api-reference/endpoint/perp-payload-create-account) using that `accountIndex`. Read the [Build Create-Account Payload](/rest-api-reference/endpoint/perp-payload-create-account) page for the full setup flow including how to discover the `accountIndex` after a deposit. **Lighter-only.** Gains withdraws collateral by closing positions — there is no separate withdraw endpoint. Skip this for Gains. Moves free USDC from the user's Lighter account back to their wallet. Only free margin (not locked by open positions/orders) can be withdrawn. ### Lighter withdraw payload shape The response's `payloadStr` is an envelope whose `payload` includes an L1 authorization challenge: ```jsonc theme={null} { "action": "withdraw", "dex": "lighter", "chainId": "lighter:301", "transport": "offchain-api", "payload": { "MessageToSign": "Lighter withdraw ...", // other Lighter-native fields } } ``` **Client workflow (Lighter):** 1. Parse `payloadStr`. 2. Sign `payload.MessageToSign` with the user's wallet (standard EIP-191 `personal_sign`). 3. Set the resulting hex on `payload.L1Sig` and **delete** `payload.MessageToSign`. 4. Re-stringify the envelope → `finalPayloadStr`. 5. Sign `` `api/2/perp/execute-v2-${timestamp}-${finalPayloadStr}` `` and call `/2/perp/execute-v2` with **that** `payloadStr` (no top-level `signedTx`). ### Request Body Must be `lighter`. Lighter chain (e.g., `lighter:301`). USDC amount as a decimal string (e.g., `"100"`). Must be positive. ### Authentication Every `/2/perp/payloads/` endpoint verifies the caller by requiring two extra fields in the request body alongside the action parameters: Unix timestamp in milliseconds. Must be within 30 seconds of server time. Older timestamps are rejected to prevent replay. Hex signature (EIP-191 `personal_sign`) of the message `` `${endpoint}-${timestamp}` ``, where `endpoint` is the path **of this endpoint** without the leading slash (e.g., for this page: `api/2/perp/payloads/ ```javascript theme={null} // Replace ``). The recovered signer address becomes the `user` for the request. Single-use — replay returns `403 signature already used`. ` with the action of THIS page (e.g. create-account, deposit, …) const endpoint = 'api/2/perp/payloads/ '; const timestamp = Date.now(); const signature = await wallet.signMessage(`${endpoint}-${timestamp}`); await fetch(`https://api.mobula.io/${endpoint}`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ timestamp, signature, // ...action-specific fields below }), }); ``` ### Authentication errors | Status | `message` | | - | - | | 403 | `timestamp expired` — timestamp older than 30s | | 403 | `signature already used` — replay attempt | | 400 | `zod validation failed` — `timestamp`/`signature` shape invalid | ### Response envelope Every `/2/perp/payloads/ ` endpoint returns the same envelope shape. You pass these fields verbatim into `POST /2/perp/execute-v2` to execute the action. **Top-level shape.** Successful (2xx) responses return `{ data: { ... } }`. A `success: true` flag is only present inside the body of `execute-v2`'s response, not on the payload-build endpoints. Parse defensively: read `body.data`, then check for the action-specific fields you need (e.g. `data.payloadStr`). ### Endpoint-specific errors | Status | `message` | | - | - | | 400 | `withdraw payload generation failed` — insufficient free margin or DEX refusal | ### Example — Lighter withdraw 100 USDC ```javascript theme={null} const endpoint = 'api/2/perp/payloads/withdraw'; const timestamp = Date.now(); const signature = await wallet.signMessage(`${endpoint}-${timestamp}`); const payloadRes = await fetch(`https://api.mobula.io/${endpoint}`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ timestamp, signature, dex: 'lighter', chainId: 'lighter:301', amountUsdc: '100', }), }).then(r => r.json()); const { data } = payloadRes; const envelope = JSON.parse(data.payloadStr); // Lighter L1 sig dance const l1Sig = await wallet.signMessage(envelope.payload.MessageToSign); envelope.payload.L1Sig = l1Sig; delete envelope.payload.MessageToSign; const finalPayloadStr = JSON.stringify(envelope); const execTs = Date.now(); const execSig = await wallet.signMessage(`api/2/perp/execute-v2-${execTs}-${finalPayloadStr}`); await fetch('https://api.mobula.io/api/2/perp/execute-v2', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ action: data.action, dex: data.dex, chainId: data.chainId, transport: data.transport, payloadStr: finalPayloadStr, timestamp: execTs, signature: execSig, }), }); ``` # Get Perp Quote Source: https://docs.mobula.io/exec/perps/perp-quote POST /2/perp/quote Get a non-binding quote for opening a perpetual position on a supported DEX (Gains Network, Lighter). Quotes do not authenticate the caller and are not used by the execution flow; they are purely informational and exposed to help clients pick a DEX, price, or slippage before building a real payload. Canonical action name — one of `withdraw`, `create-account`, `deposit`, `create-order`, `close-position`, `cancel-order`, `update-margin`, `edit-order`. `gains` or `lighter`. Chain where the action lands (e.g., `evm:42161`, `lighter:301`). Mobula market identifier. Present when the action targets a specific market. `offchain-api` — server submits to the DEX off-chain API on the user's behalf (Lighter trades, Lighter `withdraw`, Lighter `create-account`).
`evm-tx` — server broadcasts a user-signed EVM transaction (Lighter `deposit` bridge route, Gains trade actions). The Gains case requires a top-level `signedTx` on execute-v2; the Lighter `deposit` case injects signed txs **inside** `payloadStr`.JSON-stringified canonical envelope. For most actions you forward this byte-for-byte into `/2/perp/execute-v2`. Mutations are required for: Lighter `deposit` (inject `payload.signedTxs`), Lighter `withdraw` (sign `payload.MessageToSign` → `payload.L1Sig`, delete `MessageToSign`), Lighter `create-account` (same as `withdraw` only if `payload.MessageToSign` is present). After mutation, re-stringify and sign execute-v2 over the **new** string. Never alter the envelope metadata (`action`, `dex`, `chainId`, `transport`, `marketId`) — execute-v2 cross-checks it. **Quotes are informational only.** Execution uses the `/2/perp/payloads/ ### Request Body` → `/2/perp/execute-v2` flow. Use the quote endpoint to preview fills, fees, and which DEX would route best; then call `/2/perp/payloads/create-order` to build the actual signed payload you submit. Wallet address of the trader. Used to scope the quote (e.g., Lighter account lookup). **Quote is unauthenticated.** Unlike the payload endpoints, `/2/perp/quote` does **not** take a `signature` field — only `user` is required. The quote endpoint is purely informational; nothing is signed or executed. Base token address, symbol, or Mobula asset id (e.g., `ETH`, `0x...`). Quote token of the market. Semantics differ per DEX: * **Lighter** — pass the ERC-20 collateral symbol (`USDC`). * **Gains** — pass the synthetic quote (`USD`). When unsure, pass `marketId` (e.g. `gains-btc-usd`, `lighter-btc-usd`) — the field is derived server-side from the market. Leverage multiplier (e.g., `10` for 10x). `true` for long, `false` for short. String form (`"true"`/`"false"`) is also accepted. `true` if the order should only reduce an existing position (never increase exposure). Collateral to commit, denominated in the `quote` token units (e.g., `100` USDC). One of `market`, `limit`, `stop_limit`. Default `market`. Trigger/limit price. Required for `limit` and `stop_limit`. Take-profit price. Must be directionally valid (above open for long, below for short). Stop-loss price. Must be directionally valid (below open for long, above for short). Raw position size in base-token units. If omitted, derived from `collateralAmount * leverage`. Max slippage in percent (e.g., `0.5` = 0.5%). Routing **hint**, not a strict filter. If the matching market is not deployed on any of the requested chains, the router falls back to a chain that hosts it (e.g. `chainIds: ['evm:42161']` for a Base-only market silently returns `chainId: 'evm:8453'`). Always trust the response `chainId`. Omit to search all supported chains. Restrict routing to specific DEXs. Values: `gains`, `lighter`. Omit to consider all. `0` = cross, `1` = isolated. DEX-specific; ignored when not applicable. Referrer wallet address for fee sharing. ### Response### Errors | Status | When | `message` | | - | - | - | | 400 | Zod validation failed | `zod validation failed` | | 500 | No DEX returned a quote | `could not find quote` | The `errors` field lists per-DEX failures, formatted as `" `gains` or `lighter`. Mobula market identifier (e.g., `lighter-btc-usd`). Chain where the order would be executed (e.g., `evm:42161`, `lighter:301`). Informational payload structure for the matched DEX. **Not** the payload used for execution — to execute, call `/2/perp/payloads/create-order` with the same parameters. `lighter` `market` | `limit` | `stop_limit` Take-profit price, if set. Stop-loss price, if set. Lighter order parameters (`marketIndex`, `clientOrderIndex`, `baseAmount`, `maxSlippage`, `isAsk`, `reduceOnly`, `nonce`, `apiKeyIndex`, `idealPrice`, `leverage`, optional `marginMode`). `evm` `market` | `limit` | `stop_limit` Take-profit price, if set. Stop-loss price, if set. EVM transaction fields: `to`, `callData`, optional `from`, `value`, `chainId`, `nonce`, `gas`, `gasPrice`, `maxFeePerGas`, `maxPriorityFeePerGas`. JSON-stringified `payload` — provided for parity with payload endpoints but not used by `/2/perp/execute-v2`. - "`. # API Key vs API Token Source: https://docs.mobula.io/guides/api-key-vs-api-token Understand the difference between your static API key and short-lived API tokens, when to use each, and how to send them in requests. Mobula supports two ways to authenticate: a **static API key** (from the dashboard) and **short-lived API tokens** (JWTs you create from that key). This guide explains the difference and shows examples for both. *** ## Comparison | | **API Key** | **API Token (short-lived)** | | - | - | - | | **What it is** | Long-lived credential from [admin.mobula.io](https://admin.mobula.io). Same value until you rotate or delete it. | JWT created via `POST /api/2/auth/tokens`. Expires after a set time and has an optional request limit. | | **How to send** | `Authorization: YOUR_API_KEY` or `x-api-key: YOUR_API_KEY` | **Only** `Authorization: Bearer ` (do not use `x-api-key`) | | **Use case** | Backend services, scripts, your own servers. Full control over the key. | Temporary access for a client (e.g. frontend, worker, partner). Limited lifetime and optional request cap. | | **Can create tokens?** | Yes. Use the API key to call `/api/2/auth/tokens` and create tokens. | No. Short-lived tokens cannot create or manage other tokens. | | **Plans** | All plans (free and paid). | Startup, Growth, Enterprise only. | *** ## When to use an API key Use your **API key** when: * You call the API from a backend you control (server, cron job, script). * You want one credential that does not expire (until you rotate it). * You need to create or revoke short-lived tokens (token management requires the API key). ### Example: request with API key You can send the key in the `Authorization` header or in `x-api-key`: ```bash theme={null} # Option 1: Authorization header curl -X GET "https://api.mobula.io/api/1/market/data?asset=bitcoin" \ -H "Authorization: YOUR_API_KEY" # Option 2: x-api-key header curl -X GET "https://api.mobula.io/api/1/market/data?asset=bitcoin" \ -H "x-api-key: YOUR_API_KEY" ``` *** ## When to use an API token (short-lived) Use a **short-lived API token** when: * You need to give a client (e.g. frontend, mobile app, partner service) access without sharing your main API key. * You want a credential that expires and optionally has a request limit. * You issue tokens from your backend and the client only holds the token. **Always use Bearer.** Send the short-lived token only as `Authorization: Bearer ### Example: create a token, then call the API with it **Step 1 — Create a token** (with your API key): ```bash theme={null} curl -X POST "https://api.mobula.io/api/2/auth/tokens" \ -H "Authorization: YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{"expiresIn": 3600000, "requestLimit": "1000"}' ``` Response includes a `token` (JWT). Store it securely; it is returned only once. **Step 2 — Call any endpoint with the token** (Bearer only): ```bash theme={null} curl -X GET "https://api.mobula.io/api/1/market/data?asset=bitcoin" \ -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..." ``` *** ## Summary * **API key**: Long-lived, from the dashboard. Use `Authorization: YOUR_API_KEY` or `x-api-key: YOUR_API_KEY`. Use it on the server and for creating tokens. * **API token**: Short-lived JWT from `/api/2/auth/tokens`. Use **only** `Authorization: Bearer`. Do **not** send it in `x-api-key`. `. Use it for clients that should not see your API key. # How to Build a Crypto AI Agent Source: https://docs.mobula.io/guides/build-crypto-ai-agent In an ever-changing ecosystem like cryptocurrencies, having the right tools to analyze, monitor, and respond to market movements is crucial. Crypto AI agents, combining data from advanced APIs with AI-powered analytical capabilities, offer a robust solution to these challenges by enabling smarter decision-making and streamlined portfolio management. Mobula API enables the development of efficient and reliable Crypto AI agents by providing seamless access to real-time and historical cryptocurrency data. These agents harness the power of data aggregation and machine learning to automate portfolio monitoring, analyze token trends, and predict market movements. This guide is tailored for developers and crypto enthusiasts with basic Python knowledge, providing step-by-step instructions to build and deploy your own AI-powered crypto agent. ### What you’ll need * Basic Python knowledge. * Python environment configured with `requests` and `pandas`. * An API key from the [Dashboard](https://admin.mobula.io) (only for production use, you can use the API without an API key in development mode) ### Walkthrough Get your static API key from the dashboard Create, list, and revoke short-lived tokens To take it further, connect it to a Telegram bot to receive real-time notifications, enhancing your responsiveness to market changes and increasing automation. ### Need Assistance? Having issue integrating your API key? Reach out to us, response times \< 1h. **Install Dependencies**: ```bash theme={null} pip install requests pandas ``` **Mobula API Configuration**: Obtain your free API key from [Dashboard](https://docs.mobula.io/). **Connecting to Mobula APIs**: Use Mobula’s endpoints for market and wallet data: **Market Data** ```python theme={null} import requests headers = { 'Authorization': 'Bearer YOUR_MOBULA_API_KEY', } response = requests.get('https://api.mobula.io/api/1/market/data?asset=bitcoin', headers=headers) data = response.json() print(data) ``` Retrieve prices, volumes, and market caps using the `/market/data` endpoint. Refer to the [Market Data Documentation](https://docs.mobula.io/rest-api-reference/endpoint/market-data) for more information. **Wallet Data** Access balances and transactions via wallet endpoints: ```python theme={null} response = requests.get('https://api.mobula.io/api/1/wallet/portfolio?wallet=WALLET_ADDRESS', headers=headers) wallet_data = response.json() print(wallet_data) ``` Relevant guides: * [How to query Any Crypto Balance](https://docs.mobula.io/guides/query-any-crypto-balance-from-a-wallet) * [How to query Crypto Transactions](https://docs.mobula.io/guides/query-any-crypto-transactions-from-a-wallet) * [How to query Wallet USD Balance](https://docs.mobula.io/guides/query-usd-balance-of-a-wallet) Add an AI layer to analyze and interpret collected data and turn it into actionable insights. **Choosing a Model**: Use GPT (e.g., OpenAI’s API) or a local ML model to analyze data retrieved from Mobula APIs. **Example Analysis**: ```python theme={null} import openai openai.api_key = 'YOUR_OPENAI_API_KEY' prompt = f"Analyze the following data and give a recommendation: {data}" response = openai.Completion.create( engine="text-davinci-003", prompt=prompt, max_tokens=150) print(response.choices[0].text.strip()) ``` To enhance automation and flexibility, provide the LLM with Mobula's API context. This will allow the AI to understand the API's functions and generate requests or interpret responses dynamically. **Defining the API Context**: Provide detailed documentation of Mobula's API endpoints, parameters, and expected responses to the LLM. For example: ```python theme={null} api_context = """ Mobula API allows you to retrieve market and wallet data for cryptocurrencies. Endpoints: - Market Data (`/market/data`): Retrieve information about asset prices, volumes, and market caps. Parameters: - asset (string): The symbol of the asset (e.g., "bitcoin"). Response Example: { "asset": "bitcoin", "price": 98381.92, "volume": 7988374, "market_cap": 589321034.32 } - Wallet Portfolio (`/wallet/portfolio`): Retrieve the portfolio of a given wallet. Parameters: - wallet (string): The wallet address. Response Example: { "wallet": "WALLET_ADDRESS", "assets": [ {"asset": "ethereum", "balance": 11.05}, {"asset": "bitcoin", "balance": 0.61} ] } """ ``` **Prompting the LLM**: Use the API context and an instruction to generate a query or analyze data dynamically. ```python theme={null} import openai openai.api_key = 'YOUR_OPENAI_API_KEY' user_request = "Get the current price of Ethereum." prompt = f""" Using the following API context, determine how to retrieve the requested data: API Context: {api_context} User Request: {user_request} Generate an appropriate API request and interpret the response. """ response = openai.Completion.create( engine="text-davinci-003", prompt=prompt, max_tokens=300) print(response.choices[0].text.strip()) ``` Automate trend detection and set up real-time alerts for significant changes, ensuring quick market response. **Trend Detection**: Write scripts to detect significant price or volume changes. **Sending Alerts**: Configure email or Slack notifications based on specific conditions: ```python theme={null} def send_alert(message): msg = MIMEText(message) msg['Subject'] = 'Crypto Alert' msg['From'] = 'your_email@example.com' msg['To'] = 'recipient@example.com' try: with smtplib.SMTP('smtp.example.com', 587) as server: server.starttls() server.login('your_email@example.com', 'your_password') server.send_message(msg) print("Alert sent successfully.") except smtplib.SMTPException as e: print(f"Failed to send alert: {e}") ``` Use frameworks like Flask or Streamlit to create a basic interface for displaying real-time insights. # How to build your Telegram Buy Bot Source: https://docs.mobula.io/guides/build-telegram-buy-bot Buy Bot bots on Telegram are essential for keeping communities informed about project token transactions in real time. These bots enhance users' ability to react quickly to market changes, making them a valuable asset for any cryptocurrency-focused Telegram group. Mobula API enables the development of efficient and reliable Buy Bots on Telegram, focusing on the integration of transaction data. This guide will take you through the essential steps to build such a bot. ### What you’ll need 1. Knowledge in Python or Node.js programming languages. 2. Knowledge of the [Telegram API](https://core.telegram.org/). 3. A database like MySQL, PostgreSQL, or MongoDB to store user data and transaction histories. 4. A web cloud server to host the bot, ensuring its availability and responsiveness. 5. An API key from the [Dashboard](https://admin.mobula.io) (required for production; optional in development mode). ### Walkthrough Telegram Slack Discord ### Need Assistance? Having issue integrating your API key? Reach out to us, response times \< 1h. * **Start a chat with BotFather**: Launch [BotFather](https://telegram.me/BotFather), start a conversation, and type /newbot. * **Follow instructions**: BotFather will ask for a name for your bot and then a username. The username must end in *bot* (e.g., buy\_alert\_bot). * **Receive API token**: After setup, BotFather will give you a token. This is crucial as it will allow your software to communicate with Telegram API. * **Choose a programming environment**: Python is recommended due to its simplicity and powerful libraries. Install Python and then set up a virtual environment. * **Install necessary libraries**: Use pip to install [python-telegram-bot](https://python-telegram-bot.org/) and any other needed libraries. * **Write basic bot code**: Initialize the bot with the token you received and write basic functions to respond to messages. * Subscribe to [Mobula WSS trades API](https://docs.mobula.io/rest-api-reference/endpoint/wss-market-trades) * Install the websocket-client package and python-telegram-bot if it's not already installed: ```bash theme={null} pip install websocket-client pip install python-telegram-bot ``` * Fetch recent transactions and filter them by token address, amount, or sending/receiving addresses. ```python theme={null} import websocket import json import threading from telegram import Bot # Initialize your Telegram Bot TOKEN = 'YOUR_TELEGRAM_BOT_TOKEN' CHAT_ID = 'YOUR_CHAT_ID' bot = Bot(TOKEN) def send_telegram_message(message): bot.send_message(chat_id=CHAT_ID, text=message) def on_message(ws, message): data = json.loads(message) if data.get("type") == "trade_update": trades = data.get("data", []) for trade in trades: if trade['token_amount_usd'] >= 1 and trade.get('contract_address') == 'THE-TOKEN_CONTRACT_ADDRESS': alert_message = f"Trade Alert - Blockchain: {trade['blockchain']}, Hash: {trade['hash']}, " \ f"Token: {trade.get('token_name', 'Unknown Token')}, " \ f"Amount: {trade['token_amount']}, Value in USD: {trade['token_amount_usd']}" send_telegram_message(alert_message) def on_error(ws, error): print("Error:", error) def on_close(ws, close_status_code, close_msg): print("### closed ###") def on_open(ws): def run(*args): message = { "type": "pair", "authorization": "YOUR-API-KEY", "payload": { "blockchain": "1", "filters": { "amount_usd": { "operator": ">=", "value": 1 }, "contract_address": "THE-TOKEN_CONTRACT_ADDRESS" # Ensure this key is supported by your API } } } ws.send(json.dumps(message)) print("Message sent, listening for The-Token trades...") thread = threading.Thread(target=run) thread.start() if __name__ == "__main__": websocket.enableTrace(True) ws = websocket.WebSocketApp("wss://api.mobula.io", on_open=on_open, on_message=on_message, on_error=on_error, on_close=on_close) ws.run_forever() ``` * Replace *your\_api\_key* with your actual API key. * Replace *your\_telegram\_bot\_toekn* with your actual bot token. * Replace *your\_chat\_id* with the chat ID where you want alerts to be sent. * Determine the contract address of *The-Token* on the blockchain you are monitoring. Replace 'the\_token\_contract\_address\_' with the actual contract address of *The-Token*. This script will continuously run and print updates about relevant trades as they occur, based on your provided criteria and connection setup. * **Choose a hosting service**: Deploy your bot on a cloud platform like AWS, Heroku, or a dedicated VPS to ensure it runs 24/7. * **Set environment variables**: Store sensitive information like your API keys and bot token in environment variables to keep them secure. * **Perform functional testing**: Test all components of your bot in a controlled environment to ensure they work as expected. * **Monitor and optimize**: After deployment, monitor the bot’s performance and optimize the code, API usage, or server configuration if necessary. * **User instructions**: Provide clear instructions for users on how to interact with your bot. * **Continuous monitoring**: Regularly check the bot's operation, update its functionalities as needed, and ensure it remains compliant with any changes in the Telegram or Mobula APIs. # Build a Telegram Liquidations Alert Bot Source: https://docs.mobula.io/guides/build-telegram-liquidations-bot Learn how to build a real-time Telegram bot that alerts you when perpetual positions get liquidated on Lighter and other perps DEXs ## Overview In this guide, you'll learn how to build a **Telegram bot that sends real-time liquidation alerts** for perpetual trading positions. This is useful for: * **Traders** who want to monitor market liquidations for trading signals * **Risk managers** tracking leverage exposure in the market * **Analysts** studying liquidation patterns and market dynamics Telegram Slack Discord ## Prerequisites * A Mobula API key ([Get one here](https://admin.mobula.io)) * A Telegram Bot Token (create via [@BotFather](https://t.me/botfather)) * Node.js 18+ or Bun runtime * Basic TypeScript knowledge ## Step 1: Create Your Telegram Bot 1. Open Telegram and search for **@BotFather** 2. Send `/newbot` and follow the prompts 3. Save your **Bot Token** (looks like `123456789:ABCdefGHIjklMNOpqrsTUVwxyz`) 4. Create a channel or group for alerts and add your bot as admin 5. Get the **Channel ID** (you can use [@userinfobot](https://t.me/userinfobot) or check the URL)
For public channels, the ID is usually `-100` followed by numbers. For private channels, you can get the ID by forwarding a message to [@userinfobot](https://t.me/userinfobot). ## Step 2: Set Up Your Project ```bash theme={null} mkdir liquidation-bot cd liquidation-bot npm init -y npm install ws typescript @types/ws tsx ``` Create a `tsconfig.json`: ```json theme={null} { "compilerOptions": { "target": "ES2022", "module": "ESNext", "moduleResolution": "node", "esModuleInterop": true, "strict": true, "outDir": "./dist" } } ``` ## Step 3: Build the Liquidation Bot Create `src/index.ts`: ```typescript theme={null} import WebSocket from 'ws'; // Configuration const MOBULA_API_KEY = 'YOUR_MOBULA_API_KEY'; const TELEGRAM_BOT_TOKEN = 'YOUR_TELEGRAM_BOT_TOKEN'; const TELEGRAM_CHANNEL_ID = '-100XXXXXXXXXX'; // Your channel ID // WebSocket endpoint for perps const WS_ENDPOINT = 'wss://stream-perps-prod.mobula.io/'; // Supported chains for Lighter const LIGHTER_CHAINS = ['lighter:301', 'lighter:304']; interface PerpOrder { market: string; exchange: string; chainId: string; type: string; priceQuote: number; priceUSD: number; collateralAmountRaw: string; traderAddress: string; transactionHash: string; leverage: number | null; extra?: { trade?: { long?: boolean; }; }; } interface WebSocketMessage { data: PerpOrder; chainId: string; subscriptionId: string; } // Format USD values function formatUsd(value: number): string { if (value >= 1_000_000) return `$${(value / 1_000_000).toFixed(1)}M`; if (value >= 1_000) return `$${(value / 1_000).toFixed(1)}K`; return `$${value.toFixed(2)}`; } // Format price function formatPrice(price: number): string { if (price >= 1000) return `$${price.toFixed(2)}`; if (price >= 1) return `$${price.toFixed(4)}`; return `$${price.toFixed(6)}`; } // Extract symbol from market (e.g., "lighter-eth-usd" -> "ETH") function getSymbol(market: string): string { const parts = market.split('-'); return parts.length >= 2 ? parts[1].toUpperCase() : market.toUpperCase(); } // Calculate position value function calculateValueUsd(order: PerpOrder): number { const collateralUsd = Number(order.collateralAmountRaw) / 1e18; const leverage = order.leverage || 1; return collateralUsd * leverage; } // Get Lighter explorer URL function getExplorerUrl(txHash: string): string { return `https://app.lighter.xyz/explorer/logs/${txHash}/`; } // Send Telegram message async function sendTelegramMessage(text: string): Promise{ try { const url = `https://api.telegram.org/bot${TELEGRAM_BOT_TOKEN}/sendMessage`; const response = await fetch(url, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ chat_id: TELEGRAM_CHANNEL_ID, text, parse_mode: 'HTML', disable_web_page_preview: true, }), }); if (!response.ok) { const error = await response.text(); console.error('Telegram error:', error); } } catch (error) { console.error('Failed to send Telegram message:', error); } } // Handle liquidation event async function handleLiquidation(order: PerpOrder): Promise { const symbol = getSymbol(order.market); const valueUsd = calculateValueUsd(order); const price = order.priceQuote || order.priceUSD || 0; const explorerUrl = getExplorerUrl(order.transactionHash); // Determine position direction const isLong = order.extra?.trade?.long ?? true; const direction = isLong ? 'LONG' : 'SHORT'; const message = `🔴 #${symbol} Liquidated ${direction} - ${formatUsd(valueUsd)} at ${formatPrice(price)} | tx`; console.log(`[LIQUIDATION] ${message}`); await sendTelegramMessage(message); } // Connect to WebSocket function connect(): void { const ws = new WebSocket(WS_ENDPOINT); ws.on('open', () => { console.log('✅ Connected to Mobula Perps Stream'); // Subscribe to liquidations const subscription = { event: 'stream', authorization: MOBULA_API_KEY, data: { chainIds: LIGHTER_CHAINS, events: ['order'], filters: { eq: ['type', 'LIQUIDATION'] }, }, }; ws.send(JSON.stringify(subscription)); console.log('📡 Subscribed to liquidation events'); }); ws.on('message', async (data: WebSocket.Data) => { try { const message: WebSocketMessage = JSON.parse(data.toString()); // Skip non-data messages (like subscription confirmations) if (!message.data || !message.data.type) return; if (message.data.type === 'LIQUIDATION') { await handleLiquidation(message.data); } } catch (error) { console.error('Error processing message:', error); } }); ws.on('error', (error) => { console.error('WebSocket error:', error); }); ws.on('close', () => { console.log('❌ Disconnected, reconnecting in 5s...'); setTimeout(connect, 5000); }); // Keep connection alive with ping setInterval(() => { if (ws.readyState === WebSocket.OPEN) { ws.send(JSON.stringify({ event: 'ping' })); } }, 30000); } // Start the bot console.log('🚀 Starting Liquidation Alert Bot...'); connect(); ``` ## Step 4: Run Your Bot ```bash theme={null} npx tsx src/index.ts ``` Or with Bun: ```bash theme={null} bun run src/index.ts ``` You should see: ``` 🚀 Starting Liquidation Alert Bot... ✅ Connected to Mobula Perps Stream 📡 Subscribed to liquidation events ``` ## Step 5: Customize Your Alerts ### Add Market Order Alerts Extend your bot to also alert on large market orders: ```typescript theme={null} // Minimum USD value to alert (e.g., $10,000) const MIN_MARKET_ORDER_USD = 10_000; async function handleMarketOrder(order: PerpOrder): Promise { const valueUsd = calculateValueUsd(order); // Only alert for large orders if (valueUsd < MIN_MARKET_ORDER_USD) return; const symbol = getSymbol(order.market); const price = order.priceQuote || order.priceUSD || 0; const explorerUrl = getExplorerUrl(order.transactionHash); const isBuy = order.type === 'MARKET_BUY'; const emoji = isBuy ? '🟢' : '🔴'; const action = isBuy ? 'BUY' : 'SELL'; const message = `${emoji} #${symbol} Market ${action} - ${formatUsd(valueUsd)} at ${formatPrice(price)} | tx`; console.log(`[MARKET] ${message}`); await sendTelegramMessage(message); } // Update the message handler ws.on('message', async (data: WebSocket.Data) => { const message = JSON.parse(data.toString()); if (!message.data?.type) return; switch (message.data.type) { case 'LIQUIDATION': await handleLiquidation(message.data); break; case 'MARKET_BUY': case 'MARKET_SELL': await handleMarketOrder(message.data); break; } }); ``` ### Filter by Specific Markets ```typescript theme={null} // Only track BTC and ETH liquidations const TRACKED_MARKETS = ['lighter-btc-usd', 'lighter-eth-usd']; if (!TRACKED_MARKETS.includes(order.market)) return; ``` ### Add Rate Limiting To avoid Telegram rate limits (30 messages/second): ```typescript theme={null} const messageQueue: string[] = []; let isProcessing = false; async function queueTelegramMessage(text: string): Promise { messageQueue.push(text); if (!isProcessing) processQueue(); } async function processQueue(): Promise { isProcessing = true; while (messageQueue.length > 0) { const message = messageQueue.shift()!; await sendTelegramMessage(message); await new Promise(resolve => setTimeout(resolve, 100)); // 10 msg/sec max } isProcessing = false; } ``` ## Order Data Model Here's the full data structure you receive for perp orders: ```typescript theme={null} interface PerpOrder { market: string; // e.g., "lighter-eth-usd" exchange: string; // e.g., "lighter", "gains" chainId: string; // e.g., "lighter:301" type: string; // MARKET_BUY, MARKET_SELL, LIQUIDATION, etc. priceQuote: number; // Price in quote currency priceUSD: number; // Price in USD baseAmountRaw: string; // Base asset amount (wei) collateralAmountRaw: string; // Collateral amount (wei) traderAddress: string; // Trader's wallet address transactionHash: string; // Transaction hash tradeId: string; // Unique trade identifier leverage: number | null; // Position leverage takeProfitUSD: number | null; stopLossUSD: number | null; collateralAsset: string | null; date: string; // ISO timestamp extra?: { trade?: { long?: boolean; // Position direction index?: number; openPrice?: bigint; }; }; } ``` ## Deployment ### Using PM2 ```bash theme={null} npm install -g pm2 pm2 start "npx tsx src/index.ts" --name liquidation-bot pm2 save ``` ### Using Docker ```dockerfile theme={null} FROM oven/bun:1 WORKDIR /app COPY package*.json ./ RUN bun install COPY . . CMD ["bun", "run", "src/index.ts"] ``` ## Support Need help? Reach out to our team: # Complete Swap Guide: From Quote to Execution Source: https://docs.mobula.io/guides/complete-swap-guide Learn how to execute token swaps on any blockchain using Mobula Swap API with comprehensive TypeScript examples ## Overview Telegram Slack **Solana Swap Execution - Alpha Mode** Swap execution on Solana is currently in **alpha mode**. The feature is functional but may have limitations. EVM chains are fully stable and production-ready. Please report any Solana-related issues to the Mobula team. This guide walks you through the complete process of executing a token swap using Mobula's Swap API. You'll learn how to: 1. Get an optimized swap quote 2. Sign the transaction with your wallet 3. Broadcast the transaction to the blockchain 4. Monitor the transaction status The Mobula Swap API provides optimal routing across multiple DEXs and supports both EVM chains and Solana. ### Supported EVM Chains All EVM swaps are executed through **MobulaRouter**, a smart contract deployed on: | Chain | Chain ID | Native Token | | - | - | - | | Ethereum | `evm:1` | ETH | | Optimism | `evm:10` | ETH | | BNB Chain | `evm:56` | BNB | | Polygon | `evm:137` | MATIC | | Base | `evm:8453` | ETH | | Arbitrum | `evm:42161` | ETH | | Avalanche | `evm:43114` | AVAX | | Robinhood Chain | `evm:4663` | ETH | | Stable | `evm:988` | USDT0 | MobulaRouter automatically routes to the best available aggregator for optimal pricing across all DEX liquidity on each chain. ## Prerequisites * Node.js 18+ installed * A Mobula API key (get one at [admin.mobula.io](https://admin.mobula.io)) * Basic knowledge of TypeScript/JavaScript * A wallet with funds on the blockchain you want to swap on ## Installation First, install the required dependencies: ```bash theme={null} npm install @solana/web3.js @solana/wallet-adapter-base ethers ``` ## Complete Swap Flow ### Step 1: Get a Swap Quote The first step is to request a swap quote. The API will return the estimated output amount and a serialized transaction ready to be signed. ```typescript theme={null} interface SwapQuoteParams { chainId: string; tokenIn: string; tokenOut: string; amount: string; walletAddress: string; slippage?: string; onlyProtocols?: string; excludedProtocols?: string; } interface SwapQuoteResponse { data: { transaction?: { serialized: string; type: 'legacy' | 'versioned'; }; estimatedAmountOut?: string; estimatedSlippage?: number; requestId: string; }; error?: string; } async function getSwapQuote(params: SwapQuoteParams): Promise{ const queryParams = new URLSearchParams({ chainId: params.chainId, tokenIn: params.tokenIn, tokenOut: params.tokenOut, amount: params.amount, walletAddress: params.walletAddress, slippage: params.slippage || '1', }); if (params.onlyProtocols) { queryParams.append('onlyProtocols', params.onlyProtocols); } if (params.excludedProtocols) { queryParams.append('excludedProtocols', params.excludedProtocols); } const response = await fetch( `https://api.mobula.io/api/2/swap/quoting?${queryParams}`, { headers: { 'Authorization': `Bearer ${process.env.MOBULA_API_KEY}`, }, } ); if (!response.ok) { throw new Error(`HTTP error! status: ${response.status}`); } return await response.json(); } ``` ### Step 2: Sign the Transaction Once you have the quote, you need to sign the transaction with your wallet. The process differs between Solana and EVM chains. #### Solana Transaction Signing ```typescript theme={null} import { VersionedTransaction, Transaction } from '@solana/web3.js'; import type { WalletAdapter } from '@solana/wallet-adapter-base'; async function signSolanaTransaction( serializedTransaction: string, transactionType: 'legacy' | 'versioned', wallet: WalletAdapter ): Promise { // Decode the base64 transaction const transactionBuffer = Buffer.from(serializedTransaction, 'base64'); if (transactionType === 'versioned') { // Handle versioned transaction (most common for Solana) const transaction = VersionedTransaction.deserialize(transactionBuffer); // Sign the transaction with the wallet const signedTx = await wallet.signTransaction(transaction); // Serialize the signed transaction back to base64 return Buffer.from(signedTx.serialize()).toString('base64'); } else { // Handle legacy transaction const transaction = Transaction.from(transactionBuffer); // Sign the transaction const signedTx = await wallet.signTransaction(transaction); // Serialize and encode return Buffer.from( signedTx.serialize({ requireAllSignatures: false }) ).toString('base64'); } } ``` #### EVM Transaction Signing ```typescript theme={null} import { ethers } from 'ethers'; async function signEvmTransaction( serializedTransaction: string, wallet: ethers.Wallet ): Promise { // Decode the transaction const transactionBuffer = Buffer.from(serializedTransaction, 'base64'); // Parse the transaction const transaction = ethers.utils.parseTransaction(transactionBuffer); // Sign the transaction const signedTx = await wallet.signTransaction({ to: transaction.to, data: transaction.data, value: transaction.value, gasLimit: transaction.gasLimit, gasPrice: transaction.gasPrice, nonce: transaction.nonce, chainId: transaction.chainId, }); // Return as base64 return Buffer.from(ethers.utils.arrayify(signedTx)).toString('base64'); } ``` ### Step 3: Send the Signed Transaction After signing, broadcast the transaction to the blockchain. ```typescript theme={null} interface SwapSendParams { chainId: string; signedTransaction: string; } interface SwapSendResponse { data: { success: boolean; transactionHash?: string; requestId: string; }; error?: string; } async function sendSwapTransaction(params: SwapSendParams): Promise { const response = await fetch('https://api.mobula.io/api/2/swap/send', { method: 'POST', headers: { 'Content-Type': 'application/json', 'Authorization': `Bearer ${process.env.MOBULA_API_KEY}`, }, body: JSON.stringify(params), }); if (!response.ok) { throw new Error(`HTTP error! status: ${response.status}`); } return await response.json(); } ``` ### Step 4: Monitor Transaction Status After broadcasting, monitor the transaction on the blockchain. ```typescript theme={null} import { Connection, PublicKey } from '@solana/web3.js'; import { ethers } from 'ethers'; // For Solana async function waitForSolanaConfirmation( signature: string, connection: Connection, maxAttempts: number = 30 ): Promise { for (let i = 0; i < maxAttempts; i++) { const status = await connection.getSignatureStatus(signature); if (status.value?.confirmationStatus === 'confirmed' || status.value?.confirmationStatus === 'finalized') { console.log(`✅ Transaction confirmed: ${signature}`); return true; } if (status.value?.err) { console.error(`❌ Transaction failed:`, status.value.err); return false; } // Wait 2 seconds before checking again await new Promise(resolve => setTimeout(resolve, 2000)); } console.warn(`⚠️ Transaction not confirmed after ${maxAttempts} attempts`); return false; } // For EVM async function waitForEvmConfirmation( txHash: string, provider: ethers.providers.Provider, confirmations: number = 1 ): Promise { try { const receipt = await provider.waitForTransaction(txHash, confirmations); if (receipt.status === 1) { console.log(`✅ Transaction confirmed: ${txHash}`); return true; } else { console.error(`❌ Transaction failed: ${txHash}`); return false; } } catch (error) { console.error(`❌ Error waiting for transaction:`, error); return false; } } ``` ## Complete Examples ### Example 1: Swap SOL to USDC on Solana ```typescript theme={null} import { Connection, PublicKey } from '@solana/web3.js'; import { WalletAdapter } from '@solana/wallet-adapter-base'; async function swapSolToUsdc( wallet: WalletAdapter, amountInSol: number, slippagePercent: number = 1 ) { const connection = new Connection('https://api.mainnet-beta.solana.com'); console.log(`🔄 Starting swap: ${amountInSol} SOL → USDC`); try { // Step 1: Get quote console.log('📊 Fetching quote...'); const quote = await getSwapQuote({ chainId: 'solana', tokenIn: 'So11111111111111111111111111111111111111112', // SOL tokenOut: 'EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v', // USDC amount: (amountInSol * 1e9).toString(), // Convert to lamports walletAddress: wallet.publicKey!.toString(), slippage: slippagePercent.toString(), }); if (quote.error || !quote.data.transaction) { throw new Error(quote.error || 'No transaction returned'); } console.log(`💰 Estimated output: ${quote.data.estimatedAmountOut} USDC`); console.log(`📉 Estimated slippage: ${quote.data.estimatedSlippage}%`); // Step 2: Sign transaction console.log('✍️ Signing transaction...'); const signedTx = await signSolanaTransaction( quote.data.transaction.serialized, quote.data.transaction.type, wallet ); // Step 3: Send transaction console.log('📤 Broadcasting transaction...'); const result = await sendSwapTransaction({ chainId: 'solana', signedTransaction: signedTx, }); if (!result.data.success || !result.data.transactionHash) { throw new Error(result.error || 'Transaction failed'); } console.log(`🔗 Transaction hash: ${result.data.transactionHash}`); // Step 4: Wait for confirmation console.log('⏳ Waiting for confirmation...'); const confirmed = await waitForSolanaConfirmation( result.data.transactionHash, connection ); if (confirmed) { console.log('🎉 Swap completed successfully!'); return result.data.transactionHash; } else { throw new Error('Transaction not confirmed'); } } catch (error) { console.error('❌ Swap failed:', error); throw error; } } // Usage const amountToSwap = 0.1; // 0.1 SOL const maxSlippage = 1; // 1% swapSolToUsdc(wallet, amountToSwap, maxSlippage) .then(txHash => console.log(`Success! TX: ${txHash}`)) .catch(error => console.error('Failed:', error)); ``` ### Example 2: Swap ETH to USDC on Ethereum ```typescript theme={null} import { ethers } from 'ethers'; async function swapEthToUsdc( wallet: ethers.Wallet, amountInEth: number, slippagePercent: number = 1 ) { const provider = wallet.provider; console.log(`🔄 Starting swap: ${amountInEth} ETH → USDC`); try { // Step 1: Get quote console.log('📊 Fetching quote...'); const quote = await getSwapQuote({ chainId: 'ethereum', tokenIn: '0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE', // ETH tokenOut: '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48', // USDC amount: ethers.utils.parseEther(amountInEth.toString()).toString(), walletAddress: wallet.address, slippage: slippagePercent.toString(), }); if (quote.error || !quote.data.transaction) { throw new Error(quote.error || 'No transaction returned'); } const estimatedUsdc = parseFloat(quote.data.estimatedAmountOut || '0') / 1e6; console.log(`💰 Estimated output: ${estimatedUsdc.toFixed(2)} USDC`); console.log(`📉 Estimated slippage: ${quote.data.estimatedSlippage}%`); // Step 2: Sign transaction console.log('✍️ Signing transaction...'); const signedTx = await signEvmTransaction( quote.data.transaction.serialized, wallet ); // Step 3: Send transaction console.log('📤 Broadcasting transaction...'); const result = await sendSwapTransaction({ chainId: 'ethereum', signedTransaction: signedTx, }); if (!result.data.success || !result.data.transactionHash) { throw new Error(result.error || 'Transaction failed'); } console.log(`🔗 Transaction hash: ${result.data.transactionHash}`); // Step 4: Wait for confirmation console.log('⏳ Waiting for confirmation...'); const confirmed = await waitForEvmConfirmation( result.data.transactionHash, provider!, 1 ); if (confirmed) { console.log('🎉 Swap completed successfully!'); return result.data.transactionHash; } else { throw new Error('Transaction not confirmed'); } } catch (error) { console.error('❌ Swap failed:', error); throw error; } } // Usage with ethers wallet const provider = new ethers.providers.JsonRpcProvider('https://eth.llamarpc.com'); const wallet = new ethers.Wallet('YOUR_PRIVATE_KEY', provider); const amountToSwap = 0.1; // 0.1 ETH const maxSlippage = 1; // 1% swapEthToUsdc(wallet, amountToSwap, maxSlippage) .then(txHash => console.log(`Success! TX: ${txHash}`)) .catch(error => console.error('Failed:', error)); ``` ### Example 3: Advanced Swap with Protocol Restrictions ```typescript theme={null} async function advancedSwap( wallet: WalletAdapter, tokenIn: string, tokenOut: string, amount: string, options: { slippage?: number; onlyProtocols?: string[]; excludedProtocols?: string[]; } = {} ) { try { // Get quote with advanced options const quote = await getSwapQuote({ chainId: 'solana', tokenIn, tokenOut, amount, walletAddress: wallet.publicKey!.toString(), slippage: options.slippage?.toString() || '1', onlyProtocols: options.onlyProtocols?.join(','), excludedProtocols: options.excludedProtocols?.join(','), }); if (quote.error) { throw new Error(quote.error); } console.log('Quote received:', { estimatedOut: quote.data.estimatedAmountOut, slippage: quote.data.estimatedSlippage, requestId: quote.data.requestId, }); // ... continue with signing and sending } catch (error) { console.error('Swap error:', error); throw error; } } // Usage: Only use Raydium and Orca advancedSwap( wallet, 'So11111111111111111111111111111111111111112', // SOL 'EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v', // USDC '100000000', // 0.1 SOL { slippage: 2, onlyProtocols: ['raydium-amm', 'orca-whirlpool'], } ); // Usage: Exclude specific protocol advancedSwap( wallet, 'So11111111111111111111111111111111111111112', 'EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v', '100000000', { excludedProtocols: ['0xSomeFactoryAddress'], } ); ``` ## Error Handling Best Practices ```typescript theme={null} enum SwapErrorType { QUOTE_FAILED = 'QUOTE_FAILED', SIGNING_FAILED = 'SIGNING_FAILED', BROADCAST_FAILED = 'BROADCAST_FAILED', CONFIRMATION_TIMEOUT = 'CONFIRMATION_TIMEOUT', INSUFFICIENT_BALANCE = 'INSUFFICIENT_BALANCE', SLIPPAGE_EXCEEDED = 'SLIPPAGE_EXCEEDED', } class SwapError extends Error { constructor( public type: SwapErrorType, message: string, public originalError?: unknown ) { super(message); this.name = 'SwapError'; } } async function executeSwapWithErrorHandling( params: SwapQuoteParams, wallet: WalletAdapter ) { try { // Get quote const quote = await getSwapQuote(params); if (quote.error) { if (quote.error.includes('slippage')) { throw new SwapError( SwapErrorType.SLIPPAGE_EXCEEDED, 'Slippage tolerance exceeded. Try increasing slippage or reducing amount.', quote.error ); } if (quote.error.includes('liquidity')) { throw new SwapError( SwapErrorType.QUOTE_FAILED, 'Insufficient liquidity for this swap.', quote.error ); } throw new SwapError( SwapErrorType.QUOTE_FAILED, `Failed to get quote: ${quote.error}`, quote.error ); } if (!quote.data.transaction) { throw new SwapError( SwapErrorType.QUOTE_FAILED, 'No transaction returned from quote' ); } // Sign transaction let signedTx: string; try { signedTx = await signSolanaTransaction( quote.data.transaction.serialized, quote.data.transaction.type, wallet ); } catch (error) { throw new SwapError( SwapErrorType.SIGNING_FAILED, 'Failed to sign transaction. User may have rejected.', error ); } // Send transaction const result = await sendSwapTransaction({ chainId: params.chainId, signedTransaction: signedTx, }); if (!result.data.success) { throw new SwapError( SwapErrorType.BROADCAST_FAILED, result.error || 'Failed to broadcast transaction', result.error ); } return { success: true, transactionHash: result.data.transactionHash, estimatedAmountOut: quote.data.estimatedAmountOut, }; } catch (error) { if (error instanceof SwapError) { // Handle specific swap errors switch (error.type) { case SwapErrorType.SLIPPAGE_EXCEEDED: console.error('💥 Slippage too high. Consider:'); console.error(' - Increasing slippage tolerance'); console.error(' - Reducing swap amount'); console.error(' - Trying again in a few moments'); break; case SwapErrorType.SIGNING_FAILED: console.error('✍️ Transaction signing failed'); console.error(' - User may have rejected the transaction'); console.error(' - Check wallet connection'); break; case SwapErrorType.BROADCAST_FAILED: console.error('📡 Failed to broadcast transaction'); console.error(' - Check network connection'); console.error(' - Verify wallet has sufficient balance for fees'); break; default: console.error('❌ Swap error:', error.message); } throw error; } // Unknown error console.error('❌ Unexpected error:', error); throw new SwapError( SwapErrorType.QUOTE_FAILED, 'An unexpected error occurred', error ); } } ``` ## Important Notes ### Token Addresses * **EVM native tokens**: Use `0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE` for native tokens on any EVM chain (ETH, BNB, MATIC, AVAX) * **Solana native**: Use `So11111111111111111111111111111111111111112` for SOL * **Token amounts**: Always use the smallest unit (wei for EVM, lamports for Solana) ### EVM Chains All EVM swap transactions go through MobulaRouter. The response provides a ready-to-sign transaction in the `evm.transaction` field: ```typescript theme={null} const { evm, requestId } = response.data; // Sign and send using ethers.js v6 const tx = await signer.sendTransaction({ to: evm.transaction.to, // MobulaRouter address data: evm.transaction.data, // Encoded executeAggregatorSwap calldata value: evm.transaction.value, // Native token amount (0 for ERC-20 input) chainId: evm.transaction.chainId, }); await tx.wait(); console.log('Swap confirmed:', tx.hash); ``` For **native token swaps** (ETH, BNB, MATIC, AVAX), use `0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE` as `tokenIn`. The API will set the correct `value` field in the transaction. For **ERC-20 token swaps**, you must first approve the MobulaRouter contract to spend your tokens. The router address is returned in `evm.transaction.to`. ### Amount Conversion ```typescript theme={null} // EVM chains (18 decimals for most tokens) const ethAmount = '1.5'; // 1.5 ETH const amountInWei = ethers.utils.parseEther(ethAmount).toString(); // For tokens with different decimals const usdcAmount = '100'; // 100 USDC const amountInSmallestUnit = (parseFloat(usdcAmount) * 1e6).toString(); // USDC has 6 decimals // Solana (9 decimals for most tokens) const solAmount = 0.5; // 0.5 SOL const amountInLamports = (solAmount * 1e9).toString(); ``` ### Protocol Filtering * **`onlyProtocols`**: Restricts routing to specific tradable protocols. Only valid tradable pool types will be considered. ```typescript theme={null} onlyProtocols: 'uniswap-v3,sushiswap-v2' ``` * **`excludedProtocols`**: Excludes specific factory addresses from routing. ```typescript theme={null} excludedProtocols: '0xfactoryAddress1,0xfactoryAddress2' ``` ### Slippage Recommendations * **Stablecoins**: 0.1% - 0.5% * **Major tokens**: 0.5% - 1% * **Low liquidity tokens**: 2% - 5% * **Memecoins**: 5% - 10% Higher slippage increases success rate but may result in worse execution prices. ## Troubleshooting ### Common Issues 1. **"Slippage too high"** * Increase slippage tolerance * Reduce swap amount * Wait for better market conditions 2. **"No route found"** * Check token addresses are correct * Verify tokens have liquidity on the chain * Try without protocol restrictions 3. **"Transaction simulation failed"** * Insufficient balance (including gas fees) * Token approval may be needed (for non-native tokens) * Slippage tolerance too low 4. **Transaction not confirming** * Network congestion (especially on Ethereum) * Gas price too low (EVM chains) * Check blockchain explorer with transaction hash ## Next Steps * [Swap Quoting API Reference](/rest-api-reference/endpoint/swap-quoting) * [Swap Send API Reference](/rest-api-reference/endpoint/swap-send) * [Supported Blockchains](/blockchains/intro-blockchains) ## Support Need help? Join our community: * [Discord](https://discord.gg/JVT7xKm3AD) * [Telegram](https://t.me/mobuladevelopers) * Email: [contact@mobulalabs.org](mailto:contact@mobulalabs.org) # Detect a Token's Chain from Contract Address Source: https://docs.mobula.io/guides/detect-token-chain-from-address Learn how to automatically identify which blockchain a token is deployed on using just the contract address - no RPC calls needed. ## Overview When building crypto applications, you often need to identify which blockchain a token contract belongs to. Traditional approaches require expensive RPC calls to multiple chains, which is slow and resource-intensive. Mobula's **Universal Search** (`/api/2/fast-search`) automatically detects the chain for any contract address in **under 30ms** - no RPC calls, no chain guessing. ## Quick Start Simply pass the contract address to the search endpoint: ```bash theme={null} curl "https://api.mobula.io/api/2/fast-search?input=0xdAC17F958D2ee523a2206206994597C13D831ec7" ``` The response includes the `chainId` field that tells you exactly which chain the token is on: ```json theme={null} { "data": [ { "address": "0xdAC17F958D2ee523a2206206994597C13D831ec7", "chainId": "evm:1", "symbol": "USDT", "name": "Tether USD", "priceUSD": 0.9999, ... } ] } ``` ## How It Works When you provide a contract address to the search endpoint: 1. **Cross-chain lookup**: Mobula searches across all supported blockchains simultaneously 2. **Instant matching**: Uses indexed data instead of live RPC calls 3. **Returns chain info**: The response includes `chainId` identifying the exact blockchain This is significantly faster than the traditional approach of making sequential RPC calls to each chain. ## Code Examples ### TypeScript / JavaScript ```typescript theme={null} interface TokenResult { address: string; chainId: string; symbol: string | null; name: string | null; priceUSD: number; // ... many more fields } interface SearchResponse { data: TokenResult[]; } async function detectChain(contractAddress: string): Promise { const response = await fetch( `https://api.mobula.io/api/2/fast-search?input=${contractAddress}`, { headers: { 'Authorization': `Bearer ${process.env.MOBULA_API_KEY}`, }, } ); const result: SearchResponse = await response.json(); if (result.data.length === 0) { return null; // Token not found } return result.data[0].chainId; } // Usage const chainId = await detectChain('0xdAC17F958D2ee523a2206206994597C13D831ec7'); console.log(`Token is on chain: ${chainId}`); // Output: "evm:1" ``` ### Python ```python theme={null} import requests from typing import Optional def detect_chain(contract_address: str, api_key: str = None) -> Optional[str]: """Detect which blockchain a contract address belongs to.""" headers = {} if api_key: headers["Authorization"] = f"Bearer {api_key}" response = requests.get( f"https://api.mobula.io/api/2/fast-search?input={contract_address}", headers=headers ) data = response.json() if not data.get("data"): return None return data["data"][0]["chainId"] # Usage chain_id = detect_chain("0xdAC17F958D2ee523a2206206994597C13D831ec7") print(f"Token is on chain: {chain_id}") # Output: "evm:1" # Solana example chain_id = detect_chain("EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v") print(f"Token is on chain: {chain_id}") # Output: "solana:solana" ``` ## Get Full Token Data Once you have the chain ID, you can fetch complete token details: ```typescript theme={null} async function getTokenWithChainDetection(contractAddress: string) { // Step 1: Detect chain from address const searchResponse = await fetch( `https://api.mobula.io/api/2/fast-search?input=${contractAddress}&limit=1` ); const searchResult = await searchResponse.json(); if (searchResult.data.length === 0) { throw new Error('Token not found'); } const { chainId, address } = searchResult.data[0]; // Step 2: Fetch full token details const detailsResponse = await fetch( `https://api.mobula.io/api/2/token/details?blockchain=${chainId}&address=${address}` ); return detailsResponse.json(); } // Usage const tokenData = await getTokenWithChainDetection('0xdAC17F958D2ee523a2206206994597C13D831ec7'); console.log(tokenData); ``` The search endpoint already returns comprehensive token data including price, volume, liquidity, and trading metrics. In most cases, you won't need to make a second API call. ## Multi-Chain Tokens Some tokens exist on multiple chains (like USDT or USDC). The search returns all instances sorted by trading activity: ```typescript theme={null} async function findTokenAcrossChains(contractAddress: string) { const response = await fetch( `https://api.mobula.io/api/2/fast-search?input=${contractAddress}&limit=20` ); const result = await response.json(); // Group by chain const byChain = new Map(); for (const token of result.data) { if (!byChain.has(token.chainId)) { byChain.set(token.chainId, token); } } return byChain; } ``` ## Chain ID Format Mobula uses standardized chain identifiers: | Chain | Chain ID | | - | - | | Ethereum | `evm:1` | | BSC | `evm:56` | | Base | `evm:8453` | | Arbitrum | `evm:42161` | | Polygon | `evm:137` | | Optimism | `evm:10` | | Solana | `solana:solana` | | Sui | `sui:sui` | See the [Blockchains endpoint](/rest-api-reference/endpoint/blockchains) for the complete list of supported chains and their identifiers. ## Performance Comparison | Method | Latency | RPC Calls | | - | - | - | | Sequential RPC checks (10 chains) | 2-5 seconds | 10+ | | Parallel RPC checks (10 chains) | 500ms-1s | 10+ | | **Mobula Universal Search** | **\<30ms** | **0** | ## Best Practices ### 1. Handle Multiple Results When a token exists on multiple chains, the API returns all matches. Always check if your expected chain is in the results: ```typescript theme={null} async function findTokenOnSpecificChains( address: string, preferredChains: string[] ): Promise{ const response = await fetch( `https://api.mobula.io/api/2/fast-search?input=${address}&limit=10` ); const result = await response.json(); // Find token on preferred chain first for (const chain of preferredChains) { const match = result.data.find((t: TokenResult) => t.chainId === chain); if (match) return match; } // Fallback to most active (first result) return result.data[0] || null; } ``` ### 2. Cache Results Chain IDs for contracts don't change. Cache the results to avoid repeated lookups: ```typescript theme={null} const chainCache = new Map (); async function detectChainCached(address: string): Promise { const normalizedAddress = address.toLowerCase(); if (chainCache.has(normalizedAddress)) { return chainCache.get(normalizedAddress)!; } const chainId = await detectChain(address); if (chainId) { chainCache.set(normalizedAddress, chainId); } return chainId; } ``` ### 3. Filter by Specific Chains If you only support certain chains, filter the results: ```typescript theme={null} const response = await fetch( `https://api.mobula.io/api/2/fast-search?input=${address}&filters={"blockchains":"1,8453,solana"}` ); ``` ## Response Fields Each token in the response includes: | Field | Type | Description | | - | - | - | | `address` | string | Token contract address | | `chainId` | string | Blockchain identifier | | `symbol` | string | Token symbol | | `name` | string | Token name | | `priceUSD` | number | Current price in USD | | `volume24hUSD` | number | 24h trading volume | | `liquidityUSD` | number | Total liquidity | | `marketCapUSD` | number | Market capitalization | The full response includes 100+ fields. See the [Universal Search API Reference](/rest-api-reference/endpoint/fast-search) for complete documentation. ## Use Cases * **Trading bots**: Quickly identify token chains for cross-chain arbitrage * **Portfolio trackers**: Auto-detect chains for user-provided addresses * **Token analytics**: Build chain-agnostic token dashboards * **Wallet integrations**: Display correct chain info without RPC overhead ## Next Steps * [Universal Search API Reference](/rest-api-reference/endpoint/fast-search) - Full API documentation * [Token Details](/rest-api-reference/endpoint/token-details) - Get comprehensive token data * [Supported Blockchains](/blockchains/intro-blockchains) - See all supported chains ## Support Need help? Join our community: * [Discord](https://discord.gg/JVT7xKm3AD) * [Telegram](https://t.me/mobuladevelopers) * Email: [contact@mobulalabs.org](mailto:contact@mobulalabs.org) # DEX Screener APIs Source: https://docs.mobula.io/guides/dex-screener-apis This guide provides a comprehensive overview of how to access and utilize DEXScreener-like data through Mobula's APIs. ## **Dexscreener APIs vs. Mobula APIs: What’s the Difference?** Dexscreener provides free APIs that allow access to real-time price, volume, and liquidity data for DEX trading pairs. However, these APIs are **focused on trading** and limited to token pairs.\ **Mobula**, on the other hand, provides **a more comprehensive API**, aggregating both **on-chain and off-chain** token data, with **multi-blockchain support** and advanced query customization. | **Features** | **Dexscreener APIs** | **Mobula APIs** | | - | - | - | | **Real-time price data** | ✅ Yes | ✅ Yes | | **DEX trading data** | ✅ Yes | ✅ Yes | | **Multi-blockchain support** | ❌ No (DEX-focused) | ✅ Yes | | **On-chain + off-chain data** | ❌ No | ✅ Yes | | **Customizable queries** | ❌ Limited | ✅ Advanced | | **Vesting/unlock data** | ❌ No | ✅ Yes | | **New token tracking** | ❌ Limited | ✅ Yes | | **Global market data** | ❌ No | ✅ Yes | If you only need basic DEX trading pair data, Dexscreener API is a solid free option.\ But if you require **a broader, multi-blockchain,** and **customizable data solution**, **Mobula API** is clearly superior. **Mobula APIs** provide comprehensive access to decentralized exchange (DEX) data, offering the same level of detail as platforms like **Dexscreener**, but with more flexibility and integration options.\ Whether you need token prices, liquidity, or trade volumes, **Mobula** allows you to easily fetch this data in real-time from multiple blockchain networks, integrating seamlessly into your applications. ## **General Prerequisites** Before diving into Mobula's APIs, ensure you have the following: * Basic understanding of **RESTful APIs** and **JavaScript**. * An API key from the [**Mobula Dashboard**](https://admin.mobula.io) (required for production; optional in development mode). ## **Retrieving Real-Time Trade Transactions for a Specific Pair** With **Mobula APIs**, you can easily access recent trade history for a specific pair or pool, just like Dexscreener. This feature allows you to track buys, sells, prices, and USD volume in real-time. ### Using cURL ```bash theme={null} curl --request GET \ --url 'https://api.mobula.io/api/1/market/trades/pair?blockchain=ethereum&address=0xc4ce8e63921b8b6cbdb8fcb6bd64cc701fb926f2&mode=pair&sortOrder=desc' ``` ### Using JavaScript ```jsx theme={null} fetch('https://api.mobula.io/api/1/market/trades/pair?blockchain=ethereum&address=0xc4ce8e63921b8b6cbdb8fcb6bd64cc701fb926f2&mode=pair&sortOrder=desc') .then(response => response.json()) .then(response => console.log(response.data)) .catch(error => console.error(error)); ``` ## **Retrieving Comprehensive Token Metrics** Using **Mobula APIs** you can fetch key metrics such as buy volume, sell volume, total trade volume, and more for specific tokens. ### Using cURL ```bash theme={null} curl --request GET \ --url 'https://api.mobula.io/api/1/market/data?asset=bitcoin' ``` ### Using JavaScript ```jsx theme={null} fetch('https://api.mobula.io/api/1/market/data?asset=bitcoin').then(response => response.json()) .then(response => console.log(response.data)) .catch(error => console.error(error)); ``` ## **Accessing Top Trading Pairs** **Mobula** also allows you to retrieve all markets for a token, ranked by trading volume and liquidity, just like Dexscreener. This enables you to surface the most active pairs for any token across various blockchains, allowing you to spot trends in real-time. ### Using cURL ```bash theme={null} curl --request GET \ --url 'https://api.mobula.io/api/2/token/markets?blockchain=evm:1&address=0xdac17f958d2ee523a2206206994597c13d831ec7&limit=10' ``` ### Using JavaScript ```jsx theme={null} fetch('https://api.mobula.io/api/2/token/markets?blockchain=evm:1&address=0xdac17f958d2ee523a2206206994597c13d831ec7&limit=10').then(response => response.json()) .then(response => console.log(response.data)) .catch(error => console.error(error)); ``` ## **Discovering Newly Listed Tokens** **Mobula** enables you to stay ahead of emerging trends by tracking `newly listed`, `bonding`, and `bonded` tokens across multiple blockchains through the **Pulse** endpoint. ### Using cURL ```bash theme={null} curl --request POST \ --url 'https://api.mobula.io/api/2/pulse' \ --header 'Content-Type: application/json' \ --data '{"chainId":["solana:solana"],"model":"default","limit":10}' ``` ### Using JavaScript ```jsx theme={null} fetch('https://api.mobula.io/api/2/pulse', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ chainId: ['solana:solana'], model: 'default', limit: 10 }), }) .then(response => response.json()) .then(response => console.log(response)) .catch(error => console.error(error)); ``` ## **Why Choose Mobula APIs Over Dexscreener?** * **Real-Time Data**: Always up-to-date, integrated directly into your platform. * **Customizable Queries**: Filter and customize the data you retrieve. * **Multi-Blockchain Support**: Fetch data across multiple networks. By leveraging **Mobula's APIs**, you can access the same crucial DEX data available on platforms like Dexscreener, but with added benefits of customization, multi-blockchain support, and seamless integration into your applications. ### Need Assistance? Having issue integrating your API key? Reach out to us, response times \< 1h.# DEXTools V2 APIs Source: https://docs.mobula.io/guides/dextools-v2-apis This guide provides a comprehensive overview of how to access and utilize DEXScreener-like data through Mobula's APIs. In the rapidly evolving DeFi space, accessing reliable, multi-chain data is crucial. Both **Mobula APIs** and **DEXTools V2 APIs** offer valuable features, but Mobula stands out as the more comprehensive, flexible solution for developers building applications beyond Ethereum. Below, we’ll compare key features and provide code examples to highlight why Mobula APIs offer more for DeFi developers. ## **Feature Comparison: Mobula vs. DEXTools V2 APIs** | **Feature** | **Mobula APIs** | **DEXTools V2 APIs** | | - | - | - | | **Real-Time Trading Data** | ✅ Yes – Extensive real-time data covering prices, volumes, liquidity across 50+ blockchains. | ✅ Yes – Primarily Ethereum-based trading pairs. | | **Vesting Data** | ✅ Detailed vesting schedules for tokens. | ❌ Not Available. | | **New Pairs Detection** | ✅ Real-time new pair alerts across multiple blockchains. | ❌ Not Available. | | **Historical Data** | 🌟 Full historical price and volume data for advanced analytics. | 👎 Limited to Ethereum pairs. | | **Token Metadata** | 🌟 Includes logos, social links, and more for tokens across chains. | 👎 Available for Ethereum tokens. | | **Customization & Query Flexibility** | 🌟 Advanced queries for market data, token vesting, historical trends, and more. | 👎 Basic, predefined endpoints. | | **On-Chain + Off-Chain Data** | 🌟 Combines on-chain metrics with off-chain data (e.g., social sentiment). | 👎 On-chain data only. | | **Developer Tools & SDK** | 🌟 Robust documentation, SDKs, and integration guides. | 👎 Limited documentation. | | **API Rate Limits** | 🌟 Generous, scalable for enterprise needs. | 👎 More restrictive. | ### **Analysis** * **Mobula**: Provides extensive support for multi-blockchain data, including Ethereum, Binance Smart Chain, Solana, and more. It delivers deeper market insights by combining on-chain and off-chain data, which is critical for advanced analytics and building next-gen DeFi applications. * **DEXTools V2**: Great for Ethereum-based DEX data but lacks broader blockchain support, historical data depth, and off-chain metrics. ## Code Examples ### **1. Fetching Token Data Across Multiple Blockchains** Mobula's APIs allow developers to easily query token data from multiple blockchains in one request. **Using cURL:** ```bash theme={null} # Mobula: Fetch token data on Ethereum and BSC curl -X 'GET' \ 'https://api.mobula.io/api/1/market/data?blockchain=ethereum&blockchain=bsc&token=0xYourTokenAddress' \ -H 'accept: application/json' ``` **Using Axios:** ```jsx theme={null} fetch('https://api.mobula.io/api/1/market/data?blockchain=ethereum&blockchain=bsc&token=0xYourTokenAddress') .then(response => response.json()).then(response => console.log(response.data)); ``` ### **2. Retrieving Real-Time Market Data** Both Mobula and DEXTools provide real-time market data, but Mobula covers more blockchains and has greater flexibility. **Using cURL (Mobula):** ```bash theme={null} curl --request GET \ --url 'https://api.mobula.io/api/1/market/blockchain/pairs?blockchain=ethereum&sortBy=createdAt' ``` **Using Axios (Mobula):** ```jsx theme={null} fetch('https://api.mobula.io/api/1/market/blockchain/pairs?blockchain=ethereum&sortBy=createdAt') .then(response => response.json()) .then(response => console.log(response.data)) .catch(error => console.error(error)); ``` ### **3. Vesting and Unlock Data (Exclusive to Mobula)** Mobula provides detailed token vesting and unlock schedules, crucial for understanding tokenomics and potential market impacts. **Using cURL (Mobula):** ```bash theme={null} curl --request GET \ --url 'https://api.mobula.io/api/1/token/vesting?token=0xYourTokenAddress' \ -H 'accept: application/json' ``` **Using Axios (Mobula):** ```jsx theme={null} fetch('https://api.mobula.io/api/1/token/vesting?token=0xYourTokenAddress') .then(response => response.json()).then(response => console.log(response.data)); ``` ### **4. Detecting New Trading Pairs in Real-Time** Mobula’s real-time new pair detection gives developers a competitive edge in identifying emerging trends. **Using cURL (Mobula):** ```bash theme={null} curl --request GET \ --url 'https://api.mobula.io/api/1/market/new-pairs' \ -H 'accept: application/json' ``` **Using Axios (Mobula):** ```jsx theme={null} fetch('https://api.mobula.io/api/1/market/new-pairs').then(response => response.json()) .then(response => console.log(response.data)); ``` ### **5. Comprehensive Historical Data** Mobula offers complete historical data for price and volume trends, ideal for backtesting and advanced analytics. **Using cURL (Mobula):** ```bash theme={null} curl -X 'GET' \ 'https://api.mobula.io/api/1/market/history?token=0xYourTokenAddress&from=2023-01-01&to=2023-10-01' \ -H 'accept: application/json' ``` **Using Axios (Mobula):** ```jsx theme={null} fetch('https://api.mobula.io/api/1/market/history?token=0xYourTokenAddress&from=2023-01-01&to=2023-10-01') .then(response => response.json()).then(response => console.log(response.data)); ``` ## **Why Mobula APIs Stand Out** 1. **Multi-Chain Support**: Mobula offers unified endpoints for 50+ blockchains, including EVM and non-EVM networks like Solana, making it versatile for DeFi development. 2. **Comprehensive Data**: Combines on-chain data with off-chain metrics (social sentiment, news), offering a 360° view of tokens, which is critical for advanced analytics. 3. **Advanced Customization**: Mobula enables highly customizable queries for market data, historical trends, vesting schedules, and more. 4. **Developer-Friendly**: Extensive documentation, SDKs, and guides ensure smooth integration and fast development cycles. 5. **Exclusive Features**: Real-time new pair detection, token vesting schedules, and more give Mobula a competitive edge in the DeFi space. ## ## For developers building the next generation of DeFi applications, Mobula’s APIs provide a more robust, flexible, and future-proof solution compared to DEXTools V2.\ With multi-chain support, richer data, and unique features like vesting schedules and new pair detection, Mobula empowers you to build smarter and faster. Ready to get started? Check out Mobula’s [API documentation](https://docs.mobula.io/) and [OpenAPI spec](https://github.com/MobulaFi/mobula-api-docs/blob/main/rest-api-reference/openapi.yaml) to see the full potential of what you can build. ## ## ### Need Assistance? Having issue integrating your API key? Reach out to us, response times \< 1h. Telegram Slack Discord # 4 GMGN API Alternatives Source: https://docs.mobula.io/guides/gmgn-alternatives Building Next-Gen Apps with Open, Scalable APIs GMGN has become a go-to tool for Solana trading, offering features like anti-MEV execution and Telegram bot automation. However, its **closed API** limits developers’ ability to innovate. Fortunately, several alternatives exist, each with unique strengths. Let's explore 4 GMGN API alternatives. ## GMGN API Alternatives ### Feature Comparison | **Feature** | **GMGN** | **Mobula** | **Jupiter** | **Birdeye** | **Raydium** | | - | - | - | - | - | - | | **API Accessibility** | ❌ Closed | ✅ Open – Fully accessible with extensive documentation | ✅ Open | ✅ Open | ✅ Open | | **Multi-Chain Support** | ❌ Solana-only | 🌎 Extensive – 100+ chains, including non-EVM networks | ❌ Solana-only | ❌ Solana-only | ❌ Solana-only | | **Data Coverage** | 📉 Solana-only | 📊 1M+ assets, DEX + CEX data | 🔄 Solana DEXs | 🔄 Solana DEXs + NFTs | 🔄 Raydium DEX only | | **Data Depth** | ⚠️ Solana DEXs | 🔥 Comprehensive – Real-time, historical, on-chain/off-chain, vesting, unlocks | ⚠️ Solana DEXs | ⚠️ Solana DEXs + NFTs | ⚠️ Raydium DEX only | | **Customization & Flexibility** | ❌ Proprietary | 🚀 High – Custom queries, robust SDK | ❌ Fixed execution | ❌ Limited filtering | ❌ No customization | | **Developer Tools & Documentation** | ❌ Proprietary | 📚 Extensive – SDKs, open-source docs | 📄 Basic | 📑 Limited | 📄 Basic | | **Anti-MEV Execution** | ✅ Proprietary | ❌ (Uses Solana tools) | ✅ Built-in | ❌ No protection | ❌ No protection | | **Wallet Intelligence** | 🔍 Solana wallets | 🔍 Cross-chain wallet tracking | ❌ No tracking | 🔍 Solana wallets | ❌ No tracking | | **AI/ML Integration** | 🤖 Basic Telegram bots | 🤖 Built-in LLM compatibility | ❌ No AI features | ❌ No AI features | ❌ No AI features | | **Cost** | 💰 Subscription-based | 🆓 Free tier (10k req/day) | 🆓 Free | 💰 Freemium | 🆓 Free | ### Alternatives Details ### 1. Jupiter * **Strengths**: Anti-MEV execution, Solana DEX aggregation. * **Weaknesses**: Limited to Solana, no cross-chain support. * **Best For**: Solana-focused trading bots. ### 2. Birdeye * **Strengths**: Solana DEX + NFT data, user-friendly API. * **Weaknesses**: No cross-chain support, limited AI/ML integration. * **Best For**: NFT traders and Solana analytics. ### 3. Raydium * **Strengths**: Direct access to Raydium DEX liquidity. * **Weaknesses**: Limited to Raydium, no advanced analytics. * **Best For**: Raydium-specific trading strategies. ## Why Choose Mobula API? ### 1. Open and Robust Access Mobula APIs are open to developers, complete with extensive documentation and SDK support. This openness contrasts sharply with GMGN.ai’s closed system, allowing you to build, test, and scale your applications without restrictions. ### 2. Comprehensive Multi-Chain Data Unlike alternatives that focus narrowly on one or two blockchains, Mobula supports over 50 chains. Whether you’re targeting Solana, Ethereum, Binance Smart Chain, or non-EVM networks, Mobula delivers a unified and scalable solution. ### 3. Rich Data Sets and Customization Mobula doesn’t stop at real-time market data. It offers historical data, detailed token vesting and unlock schedules, and both on-chain and off-chain analytics. This level of granularity and flexibility lets you design custom dashboards, perform in-depth market analysis, and build advanced automated trading strategies. ### 4. Better Developer Experience With robust documentation, live API references (e.g., [Mobula OpenAPI](https://github.com/MobulaFi/mobula-api-docs/blob/main/rest-api-reference/openapi.yaml)), and active community support, Mobula is built with the developer in mind. The comprehensive tools available streamline integration, ensuring that your trading portal remains agile and feature-rich. ### Need Assistance? Having issue integrating your API key? Reach out to us, response times \< 1h. Telegram Slack Discord # GMGN APIs Source: https://docs.mobula.io/guides/gmgn-apis GMGN specializes in MEME trading and signal execution on Solana/ETH/Base, but **its APIs are not publicly available.** In contrast, Mobula provides an open, multi-chain API with real-time data, historical insights, and advanced customization, making it the go-to choice for developers. In today’s fast-paced DeFi landscape, access to reliable data is crucial. Unlike GMGN’s private APIs, which are restricted to their ecosystem and not publicly accessible, **Mobula** offers a publicly available, multi-chain API with advanced customization and comprehensive market data, including **deep support for Solana**. ## Feature Table | **Feature** | **GMGN APIs** | **Mobula APIs** | | - | - | - | | **Real-Time Trading Data** | ✅ Yes – Focused on rapid token trades and copy trading | ✅ Yes – Extensive real-time data covering prices, volumes, liquidity, and more | | **Multi-Blockchain Support** | 👎 Limited – Primarily Solana and ETH/Base | 🌟 Extensive – Supports 50+ chains including non-EVM networks | | **On-Chain & Off-Chain Data** | 👎 Primarily on-chain; focused on trading signals | 🌟 Both on-chain and off-chain data for deeper market insights | | **Customization & Query Flexibility** | 👎 Basic – Pre-defined endpoints for trading routes and simulation | 🌟 Advanced – Customizable queries across market data, historical trends, vesting, etc. | | **Additional Metrics** | 👎 Trading routes, slippage, anti-MEV features | 🌟 Comprehensive metrics including historical token data, vesting/unlock details, wallet transactions, and more | | **Developer Tools & SDK** | 👎 Limited documentation focused on trading automation | 🌟 Robust documentation, SDKs, and integration guides for various use cases | *** ## Examples of Mobula API Usage ### 1. Retrieving Real-Time Market Data **Using cURL:** ```bash theme={null} curl --request GET \ --url 'https://api.mobula.io/api/1/market/blockchain/pairs?blockchain=solana&sortBy=createdAt' ``` **Using Axios:** ```jsx theme={null} fetch('https://api.mobula.io/api/1/market/blockchain/pairs?blockchain=solana&sortBy=createdAt') .then(response => response.json()) .then(response => console.log(response.data)) .catch(error => console.error(error)); ``` ### 2. Accessing Historical Token Data (Mobula Exclusive) **Using cURL:** ```bash theme={null} curl --request GET \ --url 'https://api.mobula.io/api/1/market/history?asset=solana&blockchain=solana' ``` **Using Axios:** ```jsx theme={null} fetch('https://api.mobula.io/api/1/market/history?asset=solana&blockchain=solana') .then(response => response.json()) .then(response => console.log(response.data)) .catch(error => console.error(error)); ``` ### 3. Retrieving Token Vesting and Unlock Details (Mobula Exclusive) **Using cURL:** ```bash theme={null} curl --request GET \ --url 'https://api.mobula.io/api/1/market/vesting?asset=tokenName&blockchain=ethereum' ``` **Using Axios:** ```jsx theme={null} fetch('https://api.mobula.io/api/1/market/vesting?asset=tokenName&blockchain=solana') .then(response => response.json()) .then(response => console.log(response.data)) .catch(error => console.error(error)); ``` ### ### ### While GMGN’s private APIs specialize in rapid trading signals and execution within a restricted ecosystem, Mobula’s public APIs provide a comprehensive suite of data tools that empower developers to: * **Integrate Multi-Chain Data:** Access a wide array of blockchain networks, including Solana, ensuring your application isn’t limited to just one ecosystem. * **Perform Deep Market Analysis:** Retrieve not only real-time trading data but also historical trends, token vesting details, and comprehensive wallet transactions. * **Customize Data Queries:** Leverage advanced query capabilities to tailor the data to your specific needs—ideal for building detailed dashboards, analytical tools, and automated trading strategies. * **Ensure Seamless Integration:** With extensive documentation, robust SDK support, and flexible endpoints, Mobula’s APIs are designed to integrate effortlessly into any development workflow. If you need a powerful, all-encompassing solution for real-time market data, historical analysis, and multi-blockchain support, including comprehensive Solana data, **Mobula’s APIs** are your go-to choice. Ready to get started? Check out Mobula’s [API documentation](https://docs.mobula.io/) and [OpenAPI spec](https://github.com/MobulaFi/mobula-api-docs/blob/main/rest-api-reference/openapi.yaml) to see the full potential of what you can build. ### Need Assistance? Having issue integrating your API key? Reach out to us, response times \< 1h. Telegram Slack Discord # Why is GMGN API Not Open to the Public? Source: https://docs.mobula.io/guides/gmgn-closed-apis Decoding the Closed Ecosystem of Solana’s Leading Trading Tool Despite its impressive features, **GMGN’s API remains inaccessible to the public**, limiting opportunities for developers and enterprises.\ Why? Let’s break it down. GMGN has opted to keep its data API private. Instead, they provide access to their data crawling IP whitelist, but only for users with GMGN transaction records. To apply, users must submit their GMGN transaction address, invitation code, and IP address for whitelist approval. The API is heavily restricted, with a rate limit of just 2 requests per second, and frequent modifications or removals of API fields. Additionally, GMGN lacks the infrastructure to support a high-availability and high-throughput API for enterprise use. ## GMGN’s Core Features vs. Public Accessibility | **Feature** | **GMGN Capability** | **Public API Availability** | | - | - | - | | **Anti-MEV Execution** | Jito-style bundles for MEV protection | ❌ Closed | | **Telegram Bot Automation** | Stop-loss, take-profit, and DCA strategies via bots | ❌ Closed | | **DEX Aggregation** | Real-time price feeds from Raydium, Orca, and other Solana DEXs | ❌ Closed | | **Transaction Simulation** | Pre-trade simulation to avoid failed transactions | ❌ Closed | | **Wallet Tracking** | Monitor wallet activity for “smart money” insights | ❌ Closed | ## Why GMGN Keeps Its API Closed ### 1. Protecting Intellectual Property GMGN’s **anti-MEV execution engine** is a key differentiator. By restricting API access, they prevent competitors from reverse-engineering their proprietary algorithms. **Example**: * GMGN’s `/router/quote` endpoint minimizes slippage and mitigates sandwich attacks. * A public API could enable forks or clones, eroding GMGN’s competitive advantage. ### 2. Ensuring Platform Stability Public APIs are vulnerable to abuse, leading to performance degradation. GMGN’s closed system guarantees: * **Low Latency**: Sub-500ms trade execution. * **High Uptime**: Protection from unauthorized overloads. **Developer Impact**: * Without strict rate limits, API access could compromise reliability for paying users. * GMGN prioritizes stability over accessibility. ### 3. Monetization Strategy GMGN profits from **subscription-based Telegram bots** and **partner integrations**. Opening its API could: * Undermine its revenue streams. * Enable third parties to develop competing platforms. **Example**: * GMGN charges users for premium bot features (e.g., stop-loss, DCA). * Public API access could facilitate free alternatives. ### 4. Regulatory and Security Concerns Handling sensitive transaction data requires stringent security measures. A closed API: * Limits exposure to hacks. * Simplifies compliance with financial regulations (AML, KYC). **Developer Perspective**: * Secure API infrastructure demands significant resources. * GMGN circumvents these challenges by restricting access. ## What Developers Are Missing Out On ### 1. Anti-MEV Trade Execution GMGN’s `/router/quote` and `/submit-tx` endpoints provide advanced MEV protection. Developers must rely on: * Solana’s `@solana/web3.js` for transaction bundling. * Standalone DEX APIs (Raydium, Orca) for liquidity data. ### 2. Telegram Bot Automation GMGN automates trading strategies (stop-loss, DCA). Without API access, developers must: * Build bots using Solana RPC nodes. * Handle rate limits and transaction failures manually. **Example**: ```python theme={null} # Simulate GMGN’s stop-loss bot if token_price < stop_loss: execute_sell_via_solana_rpc() ``` ### 3. Real-Time DEX Analytics GMGN aggregates data from multiple DEXs. Developers need to: * Manually integrate each DEX API. * Deal with inconsistent data formats. **Alternative**: Use **Mobula’s `/market/data` endpoint** for unified DEX data. ## The Future of GMGN’s API While GMGN’s API remains closed, developers have options: 1. **Partner Programs**: GMGN may grant API access to select partners. 2. **Open-Source Alternatives**: Solutions like **Jupiter and Mobula** offer similar features. 3. **Community Pressure**: Increased demand may push GMGN towards openness. ## The Trade-Offs of a Closed Ecosystem GMGN’s restricted API has pros and cons: * **Pros**: Protects IP, ensures stability, and supports monetization. * **Cons**: Stifles innovation and developer participation. For developers seeking **scalable and accessible** API solutions, **Mobula offers a superior alternative**. ## Comparing Mobula API vs. GMGN API | Feature | Mobula API | GMGN API | | - | - | - | | **Access** | ✨ Open to all developers (API key required for production) | 👎 Restricted; requires GMGN transaction records and IP whitelist | | **Rate Limiting** | ✨ Flexible limits based on subscription tier | 👎 Strict 2 requests per second cap | | **Field Stability** | ✨ Regular updates with clear documentation | 👎 Frequent changes/removals | | **Enterprise Support** | ✨ High availability, scalable for large applications | 👎 Not optimized for enterprise use | ## Why Mobula Stands Out * **Multi-Chain Coverage**: Supports **50+ blockchains** (Ethereum, BNB, Avalanche, Polygon, etc.). * **Comprehensive Data Access**: Fetch **market data, wallet transactions, holdings, and metadata** via **REST, GraphQL, and SQL**. * **Advanced Indexing Solutions**: Offers **The Graph, Ponder, and Octoflow** frameworks as cloud services. * **Real-Time Streaming**: Webhooks & WebSockets for **instant data updates**. * **Token Vesting Insights**: Detailed vesting schedules and unlock events. By leveraging Mobula’s cutting-edge APIs, developers can build scalable, data-rich applications without the limitations imposed by GMGN. ### Need Assistance? Having issue integrating your API key? Reach out to us, response times \< 1h. Telegram Slack Discord # How to Check Token Security Across Ethereum, Solana, BNB, Base & More Source: https://docs.mobula.io/guides/how-to-check-token-security Use the Token Security endpoint to retrieve security and restriction information for a token by contract address. The [**Token Security**](https://docs.mobula.io/rest-api-reference/endpoint/token-security-get) endpoint lets you retrieve security and restriction information for a token by contract address. This helps you identify potential red flags like honeypots, restrictive transfer mechanics, high fees, and risky contract capabilities across chains like [Solana](https://docs.mobula.io/blockchains/solana), [Ethereum](https://docs.mobula.io/blockchains/ethereum), [BNB Chain](https://docs.mobula.io/blockchains/bsc), [Base](https://docs.mobula.io/blockchains/base), and more. It also provides holder distribution signals and additional risk indicators for faster due diligence. *** Telegram Slack Discord *** ## What this endpoint does With this API, you can: * Retrieve comprehensive token security information for a token on EVM and Solana chains * Return data about contract and burned holdings where supported * Return buy and sell fee percentages * Return transfer restrictions like max wallet, max buy, max sell, and max transfer where supported * Return holder concentration signals like top 10 and top 50 holdings percentages * Return contract risk indicators such as honeypot, blacklist, pausability, minting, and balance manipulation flags * Return static code analysis status for verified EVM contracts when available *** ## What you’ll need * Basic knowledge of REST APIs * A token address * A Mobula API key Note: All Mobula endpoints require an API key.\ Get a free API key: [Here](https://admin.mobula.io/) Optional: * DexScreener (to find token addresses to test) *** ## When to use Token Security Use this endpoint when you want to: * Run due diligence checks before trading or integrating a token * Detect restrictive mechanics like honeypots, blacklists, or transfer pauses * Evaluate fee structures that can make trading expensive * Assess holder concentration risk using top holder distribution fields * Check whether a token can be minted or frozen by an authority * Display safety badges or warnings in community tools and dashboards If you want wallet-level swaps and transfers to pair with security checks, use: [**Wallet Activity**](https://docs.mobula.io/rest-api-reference/endpoint/wallet-activity) If you want all wallet swaps/trades over time, use: [**Wallet Trades**](https://docs.mobula.io/rest-api-reference/endpoint/wallet-trades-v2) If you want market-level stats (price, liquidity, volume) for the pools a token trades on, use: [**Market Details**](https://docs.mobula.io/rest-api-reference/endpoint/market-details) *** ## Walkthrough to Get Token Security ### 1. Prepare your query The Token Security endpoint requires two parameters: | Parameter | Description | | - | - | | `blockchain` | Blockchain name or chain ID (example: `evm:1`, `solana:solana`, `ethereum`, `bsc`, `base`) | | `address` | Token contract address (EVM) or token mint address (Solana) | Tip: Make sure you select the correct chain, such as [Solana](https://docs.mobula.io/blockchains/solana) or [Ethereum](https://docs.mobula.io/blockchains/ethereum). ### 2. Find a token address to test with DexScreener To get a real token address: * Open DexScreener * Pick a token * Open its token page (or open a pair page for the token) * Copy the token contract address (or Solana mint address) This address is used as the `address` parameter. ### 3. Fill the API form Enter the blockchain and paste the token address into `address`, then click **Send**. *** ## Reviewing the response Here are the key fields to interpret in the token security response: **Core identifiers** * `address` / `chainId`: Token contract address and chain identifier **Holdings and supply signals** * `contractHoldingsPercentage`: Percentage of total supply held by the contract itself when available * `burnedHoldingsPercentage`: Percentage of supply burned when available * `burnRate`: Burn ratio as a decimal string when provided **Holder distribution risk** * `top10HoldingsPercentage` / `top50HoldingsPercentage` / `top100HoldingsPercentage` / `top200HoldingsPercentage`: Holder concentration signals. Higher concentration can indicate control risk. **Fees** * `buyFeePercentage` / `sellFeePercentage` / `transferFeePercentage`: Fee percentages applied on buy, sell, or plain user-to-user transfer transactions **Transfer restrictions and limits (chain dependent)** * `maxWalletAmountRaw`: Maximum wallet balance limit when present * `maxBuyAmountRaw` / `maxSellAmountRaw`: Max buy or sell size when present * `maxTransferAmountRaw`: Max transfer amount when present **Contract risk indicators** * `isHoneypot`: Honeypot detection signal when available * `transferPausable`: Whether transfers can be paused * `isBlacklisted` / `isWhitelisted`: Whether the contract includes blacklist or whitelist mechanics * `balanceMutable`: Whether balances can be arbitrarily modified * `modifyableTax`: Whether fees can be changed after deployment * `selfDestruct`: Whether the contract can self-destruct **Token capabilities** * `isMintable`: Whether supply can be minted * `isFreezable`: Whether accounts can be frozen on chains that support it **Static analysis** * `staticAnalysisStatus`: Status of AI-powered static analysis for eligible EVM contracts * `staticAnalysisDate`: When analysis was last performed if completed **Other useful fields** * `renounced`: Ownership renounced signal when available * `locked`: LP lock ratio when provided * `lowLiquidity`: Low liquidity warning field when present * `liquidityBurnPercentage`: Percent of LP tokens burned when available * `isLaunchpadToken`: Whether the token originated from a bonding curve or launchpad mechanism * `proTraderVolume24hPercentage`: Estimated share of 24h volume from terminal UI flows *** ## Try It Live with Mobula Token Security Demo (UI) You can also test this endpoint using our demo UI: [Demo UI Homepage](https://mobula-demo-endpoint-production.up.railway.app/) [Token Security Demo UI](https://mobula-demo-endpoint-production.up.railway.app/token-security) [Docs](https://docs.mobula.io/rest-api-reference/endpoint/token-security-get) *** ## Summary The [**Token Security**](https://docs.mobula.io/rest-api-reference/endpoint/token-security-get) endpoint helps you: * Retrieve security signals for a token by blockchain and contract address * Detect red flags like honeypots, blacklists, transfer pauses, minting, and balance manipulation * Evaluate fees, holder concentration, and optional static analysis results when available * Visualize security data instantly in the Token Security Demo UI *** ## Try Mobula for Free Try our free API today and start building in minutes.\ Get your free API key: [Here](https://admin.mobula.io/) # How to Fetch Asset Metadata Across Ethereum, Solana, BNB, Base & More Source: https://docs.mobula.io/guides/how-to-fetch-asset-metadata Use the Metadata endpoint to retrieve detailed metadata for an asset by name, symbol, Mobula ID, or contract address plus blockchain. The [**Metadata**](https://docs.mobula.io/rest-api-reference/endpoint/metadata) endpoint lets you retrieve detailed metadata for an asset by name, symbol, Mobula ID, or contract address plus blockchain. This is useful for enriching token pages with descriptive and informational fields beyond just market data, across chains like [Solana](https://docs.mobula.io/blockchains/solana), [Ethereum](https://docs.mobula.io/blockchains/ethereum), [BNB Chain](https://docs.mobula.io/blockchains/bsc), [Base](https://docs.mobula.io/blockchains/base), and more. Some assets may not have an `id` if they are not listed on Mobula. ****** ## What this endpoint does With this API, you can: * Retrieve detailed metadata for an asset, including enriched information when available * Query by asset name, symbol, Mobula `id`, or contract address (with `blockchain`) * Optionally force fresh fetching and return a more enriched metadata payload using `force` and `full` *** ## What you’ll need * Basic knowledge of REST APIs * An asset name, symbol, ID, or contract address (depending on how you query) * A Mobula API key Note: All Mobula endpoints require an API key.\ Get a free API key: [Here](https://admin.mobula.io/) Optional: * DexScreener (to find token contract addresses to test) *** ## When to use Metadata Use this endpoint when you want to: * Enrich an asset or token page with metadata like description, image, ranks, tags, and contracts * Retrieve fundraising, tokenomics, investors, and other enriched categories for supported assets * Resolve a Mobula internal asset ID from a symbol or asset query * Query metadata by contract address when you only have on-chain identifiers If you want a full asset snapshot with market data and supply stats, use: [**Asset Details**](https://docs.mobula.io/rest-api-reference/endpoint/asset-details) If you want enriched contract-level market stats for a token, use: [**Token Details**](https://docs.mobula.io/rest-api-reference/endpoint/token-details) If you want token security signals like honeypot flags, taxes, and restrictions, use: [**Token Security**](https://docs.mobula.io/rest-api-reference/endpoint/token-security-get) If you want pool-level stats like liquidity and volume for markets where a token trades, use: [**Market Details**](https://docs.mobula.io/rest-api-reference/endpoint/market-details) *** ## Walkthrough to Get Metadata ### 1. Prepare your query The Metadata endpoint requires one parameter: | Parameter | Description | | - | - | | `asset` | Asset name or contract address. If using a contract address, `blockchain` is required. | Optional parameters you can use: * `blockchain`: Blockchain identifier, required if `asset` is a contract address * `symbol`: Symbol of the asset (alternative way to query) * `id`: Mobula internal asset ID (alternative way to query) * `force`: If `true`, forces fresh data fetching * `full`: If `true`, returns full enriched metadata when available Tip: If you query by contract address, pass it in `asset` and also provide `blockchain` (example: `ethereum`, `evm:1`, or `solana`). ### 2. Find a token address to test with DexScreener To get a real contract address: * Open DexScreener * Pick a token * Open its token page (or open a pair page for the token) * Copy the token contract address (or Solana mint address) * Note the chain the token is on (you will use this for `blockchain`) This address is used as the `asset` parameter. ### 3. Fill the API form Either: * Enter an asset name, or * Enter a `symbol`, or * Paste an `id`, or * Paste a contract address into `asset` and also set `blockchain` (Optional) set `full=true` for enriched metadata when available, and `force=true` to trigger a fresh fetch, then click **Send**. *** ## Reviewing the response The response returns a `metadata` object for the asset. Depending on the asset, you may see: * `id`: Mobula internal asset ID when available * `name` / `symbol`: Asset identity fields * `image` / `logo`: Asset image when available * `description`: Asset description field when available * `rank`: Ranking fields when provided * `tags` / `categories`: Classification tags when available * `contracts`: Contract information and chain mapping when provided * `centralization` / `distribution`: Distribution signals when available * `fundraising` / `investors` / `tokenomics`: Enriched metadata categories when `full=true` is supported Notes: * Some assets may not have an `id` if they are not listed on Mobula. * Use `full=true` to request more enriched metadata when available. * Use `force=true` if you want to trigger a fresh fetch. *** ## Try It Live with Mobula Asset Metadata Demo (UI) You can also test this endpoint using our demo UI: [Demo UI Homepage](https://mobula-demo-endpoint-production.up.railway.app/) [Asset Metadata Demo UI](https://mobula-demo-endpoint-production.up.railway.app/asset-metadata) [Docs](https://docs.mobula.io/rest-api-reference/endpoint/metadata) *** ## Summary The [**Metadata**](https://docs.mobula.io/rest-api-reference/endpoint/metadata) endpoint helps you: * Retrieve asset metadata by name, symbol, ID, or contract address plus blockchain * Use `full=true` for enriched categories when available and `force=true` to fetch fresh data * Enrich asset pages with description, images, ranks, tags, and contract mapping * Visualize metadata instantly in the Asset Metadata Demo UI *** ## Try Mobula for Free Try our free API today and start building in minutes.\ Get your free API key: [Here](https://admin.mobula.io/) # How to Fetch CeFi Funding Rates Across Binance, Bybit, OKX, Deribit, Bitget, MEXC, Kraken, Coinbase & More Source: https://docs.mobula.io/guides/how-to-fetch-cefi-funding-rates Use the CeFi Funding Rate endpoint to fetch the latest funding rate for a given symbol across supported centralized exchanges. The [**CeFi Funding Rate**](https://docs.mobula.io/rest-api-reference/endpoint/market-cefi-funding-rate) endpoint lets you fetch the latest funding rate for a given symbol across supported exchanges. By default, it returns results from multiple CeFi venues so you can compare rates quickly. You can also specify one or more exchanges to narrow the response. ****** ## What this endpoint does With this API, you can: * Fetch the latest CeFi funding rate for a given symbol * Return rates from all supported exchanges by default if `exchange` is not provided * Filter to one or multiple exchanges using a comma-separated list * Use an optional quote currency to refine the contract symbol format on some venues * Query via REST, and also use the WebSocket version when needed *** ## What you’ll need * Basic knowledge of REST APIs * A trading symbol (example: `ETH`, `BTC`) * A Mobula API key Note: All Mobula endpoints require an API key.\ Get a free API key: [Here](https://admin.mobula.io/) *** ## When to use CeFi Funding Rate Use this endpoint when you want to: * Compare funding rates across multiple centralized exchanges * Monitor long vs short funding pressure for a symbol * Track venue differences for arbitrage and risk monitoring * Build funding rate widgets for dashboards * Pull rates from a specific venue like `deribit` or `okx` when needed If you want spot market pricing and change metrics for a token, use: [**Get Market Details**](https://docs.mobula.io/rest-api-reference/endpoint/market-details) If you want onchain market trade history (DEX trades), use: [**Market Trades Pair**](https://docs.mobula.io/rest-api-reference/endpoint/market-trades-pair) If you want a specific onchain trade by transaction hash, use: [**Token Trade by Transaction**](https://docs.mobula.io/rest-api-reference/endpoint/token-trade) *** ## Walkthrough to Get CeFi Funding Rate ### 1. Prepare your query The CeFi Funding Rate endpoint requires one parameter: | Parameter | Description | | - | - | | `symbol` | The trading symbol (example: `BTC`, `ETH`) | Optional parameters you can use: * `quote`: Optional quote currency (example: `USDT`, `USDC`) * `exchange`: Optional exchanges, comma-separated (example: `deribit,binance,okx,lighter`) Tip: If you do not provide `exchange`, the endpoint returns rates across all supported exchanges by default. ### 2. Find a symbol to test To test quickly, you can use a major symbol: * Use `BTC` or `ETH` as your `symbol` If you want a venue-specific contract format: * Add `quote=USDT` (common for many perp venues) * Add `exchange=binance` (or any supported venue) to narrow results This symbol is used as the `symbol` parameter. ### 3. Fill the API form Enter the symbol, set `exchange` and `quote` if needed, then click **Send**. *** ## Reviewing the response The response returns a `queryDetails` object plus one object per exchange: * `queryDetails`: Echoes what you queried, like symbol, quote, and exchange selection * `binanceFundingRate` / `bybitFundingRate` / `okxFundingRate` / `deribitFundingRate`: Exchange-specific funding rate objects when available * `hyperliquidFundingRate` / `gateFundingRate` / `lighterFundingRate` / `kucoinFundingRate`: Additional venue objects when available depending on your query * `bitgetFundingRate` / `mexcFundingRate` / `krakenFundingRate` / `coinbaseFundingRate`: Additional venues when available Every venue object shares the same shape: | Field | Type | Description | | - | - | - | | `symbol` | string | The venue's own contract symbol (e.g. `ETHUSDT`, `ETHPERP`, `PF_BTCUSD`, `BTC-PERP`) | | `fundingTime` | number | Settlement timestamp of the last closed funding epoch, **in milliseconds** (UNIX epoch ms) | | `fundingRate` | number | Unitless funding rate for that epoch (e.g. `0.0001` = `0.01%`); positive = longs pay shorts | | `epochDurationMs` | number | Funding interval **in milliseconds** (e.g. `28800000` for 8h, `3600000` for 1h) | | `marketPrice` | string \| number | Mark/index price, on venues that provide it (`binance`, `deribit`, `coinbase`, `hyperliquid`) | `fundingTime` and `epochDurationMs` are normalized to **milliseconds for every venue**, so you can treat them uniformly (e.g. `new Date(fundingTime)`) regardless of the source exchange. Important interpretation notes: * If you do not provide `exchange`, the endpoint returns rates across all supported exchanges by default. * For Gate.io, contracts use a USDT settle format like `SYMBOL_USDT`. * For Lighter, a positive rate means longs pay shorts, and a negative rate means shorts pay longs. * For Hyperliquid DEX (HIP3) funding, you must prefix the symbol with `dex:` (example: `dex:BTC`). ### Quote handling per venue The optional `quote` parameter only affects venues that list the same base under multiple quote currencies: * **Bitget** — `quote=USDT` → `usdt-futures` (ticker `ETHUSDT`), `quote=USDC` → `usdc-futures` (ticker `ETHPERP`), `quote=USD` → coin-margined `coin-futures`. Defaults to `USDT`. * **MEXC** — `quote=USDT` → contract `ETH_USDT`, `quote=USDC` → `ETH_USDC`. Defaults to `USDT`. * **Coinbase** — `quote` is ignored. Coinbase International perpetuals are all USDC-quoted and listed as `SYM-PERP` (e.g. `BTC-PERP`). * **Kraken** — `quote` is ignored. Kraken multi-collateral perpetuals are all USD-quoted and listed as `PF_SYMUSD` (e.g. `PF_BTCUSD`); `BTC` is internally mapped to Kraken's `XBT`. For all other venues (`binance`, `bybit`, `okx`, `deribit`, `gate`, `kucoin`), `quote` defaults to `USDT` where applicable. *** ## Try It Live with Mobula CeFi Funding Rate Demo (UI) You can also test this endpoint using our demo UI: [Demo UI Homepage](https://mobula-demo-endpoint-production.up.railway.app/) [CeFi Funding Rate Demo UI](https://mobula-demo-endpoint-production.up.railway.app/cefi-funding-rate) [Docs](https://docs.mobula.io/rest-api-reference/endpoint/market-cefi-funding-rate) *** ## Summary The [**CeFi Funding Rate**](https://docs.mobula.io/rest-api-reference/endpoint/market-cefi-funding-rate) endpoint helps you: * Fetch the latest CeFi funding rate for a symbol like `BTC` or `ETH` * Compare rates across multiple exchanges by default or specify exchanges to filter * Optionally use `quote` to refine contract formats for certain venues * Visualize results instantly in the CeFi Funding Rate Demo UI *** ## Try Mobula for Free Try our free API today and start building in minutes.\ Get your free API key: [Here](https://admin.mobula.io/) # How to Fetch Multi Asset Metadata Across Ethereum, Solana, BNB, Base & More Source: https://docs.mobula.io/guides/how-to-fetch-multi-asset-metadata Use the Multi Metadata endpoint to retrieve metadata for multiple assets in a single request using ids, symbols, or contract addresses with matching blockchains. The [**Multi Metadata**](https://docs.mobula.io/rest-api-reference/endpoint/multi-metadata) endpoint lets you retrieve metadata for multiple assets in a single request. You can query by Mobula asset IDs, asset names, symbols, or contract addresses with matching blockchains across chains like [Solana](https://docs.mobula.io/blockchains/solana), [Ethereum](https://docs.mobula.io/blockchains/ethereum), [BNB Chain](https://docs.mobula.io/blockchains/bsc), [Base](https://docs.mobula.io/blockchains/base), and more. This is useful for bulk enrichment when building token lists and dashboards. ****** ## What this endpoint does With this API, you can: * Retrieve metadata for multiple assets at the same time * Query using `ids` (Mobula asset IDs), `assets` (asset names or contract addresses), or `symbols` (token symbols) * Use `blockchains` to match contract addresses passed in `assets` * Map the first blockchain with the first contract address, and so on * When `symbols` are used, return the asset with the highest market cap for that symbol *** ## What you’ll need * Basic knowledge of REST APIs * A list of asset IDs, symbols, or contract addresses (depending on how you query) * A Mobula API key Note: All Mobula endpoints require an API key.\ Get a free API key: [Here](https://admin.mobula.io/) Optional: * DexScreener (to find contract addresses to test) *** ## When to use Multi Metadata Use this endpoint when you want to: * Enrich a token list with metadata in one request instead of calling `/metadata` repeatedly * Map CEX symbols to asset metadata using the `symbols` parameter * Fetch metadata for many contract addresses across Solana and EVM chains * Build dashboards that need logos, websites, Twitter links, and metadata fields in bulk * Retrieve enriched metadata for supported assets when available If you want metadata for a single asset, use: [**Metadata**](https://docs.mobula.io/rest-api-reference/endpoint/metadata) If you want a full asset snapshot with market data and supply stats, use: [**Asset Details**](https://docs.mobula.io/rest-api-reference/endpoint/asset-details) If you want to find assets first by typing a symbol or name, use: [**Fast Search**](https://docs.mobula.io/rest-api-reference/endpoint/fast-search) *** ## Walkthrough to Get Multi Metadata ### 1. Prepare your query The Multi Metadata endpoint requires two parameters: | Parameter | Description | | - | - | | `assets` | Comma-separated list of asset names or contract addresses | | `blockchains` | Comma-separated blockchain name(s) used to match contract addresses in `assets` | Optional parameters you can use: * `ids`: Comma-separated list of Mobula asset IDs * `symbols`: Comma-separated list of token symbols Tip: If you pass contract addresses in `assets`, you must also pass `blockchains` with the same number of entries in the same order. ### 2. Find token addresses to test with DexScreener To get real contract addresses: * Open DexScreener * Pick a token * Open its token page (or open a pair page for the token) * Copy the token contract address (or Solana mint address) * Note the chain the token is on (you will use this for `blockchains`) * Repeat for a second token if you want to test multiple entries These addresses are used as the `assets` parameter. ### 3. Fill the API form Either: * Enter a comma-separated `assets` list and a comma-separated `blockchains` list (same number of entries, same order), or * Enter `ids` (comma-separated), or * Enter `symbols` (comma-separated) Then click **Send**. *** ## Reviewing the response The response returns an array of metadata objects, one per matched asset. Depending on the asset, you may see: * **Asset identity fields**: name, symbol, and `id` when available * **Logo and visuals**: image or logo fields when provided * **Social links**: Twitter and website fields when available * **Descriptions and tags**: some assets include descriptions, ranks, and classification tags * **Contracts**: contract mapping fields when returned Important behavior notes: * When using `assets` + `blockchains` with contract addresses, the endpoint maps the first blockchain to the first address, and so on. * When using `symbols`, Mobula returns the asset with the highest market cap for that symbol. * Some assets may not have an `id` if they are not listed on Mobula. *** ## Try It Live with Mobula Multi Metadata Demo (UI) You can also test this endpoint using our demo UI: [Demo UI Homepage](https://mobula-demo-endpoint-production.up.railway.app/) [Multi Metadata Demo UI](https://mobula-demo-endpoint-production.up.railway.app/multi-metadata) [Docs](https://docs.mobula.io/rest-api-reference/endpoint/multi-metadata) *** ## Summary The [**Multi Metadata**](https://docs.mobula.io/rest-api-reference/endpoint/multi-metadata) endpoint helps you: * Retrieve metadata for multiple assets in one request * Query using `ids`, `assets` with `blockchains`, or `symbols` for fast mapping * Bulk enrich token lists with socials, logos, and descriptive metadata * Visualize results instantly in the Multi Metadata Demo UI *** ## Try Mobula for Free Try our free API today and start building in minutes.\ Get your free API key: [Here](https://admin.mobula.io/) # How to Get All Asset Categories and Market Cap Changes Source: https://docs.mobula.io/guides/how-to-get-all-asset-categories-and-market-cap-changes Use the Metadata Categories endpoint to retrieve a list of all asset categories with market cap and percentage changes over 24h and 7d. The [**Metadata Categories**](https://docs.mobula.io/rest-api-reference/endpoint/metadata-categories) endpoint lets you retrieve a list of all asset categories available in Mobula metadata. It returns each category’s market cap plus percentage changes over the last 24 hours and 7 days. This is useful for building category dashboards and market overviews. ****** ## What this endpoint does With this API, you can: * Retrieve all asset categories available in Mobula metadata * Return category-level market cap * Return category market cap percentage change over `24h` and `7d` *** ## What you’ll need * Basic knowledge of REST APIs * No parameters required for this endpoint * A Mobula API key Note: All Mobula endpoints require an API key.\ Get a free API key: [Here](https://admin.mobula.io/) *** ## When to use Metadata Categories Use this endpoint when you want to: * Build a category overview page with market cap and trends * Compare category performance across 24h and 7d windows * Rank categories by market cap * Track which sectors are gaining or losing market share If you want metadata for a single asset (description, links, tags), use: [**Metadata**](https://docs.mobula.io/rest-api-reference/endpoint/metadata) If you want metadata for many assets in one call, use: [**Multi Metadata**](https://docs.mobula.io/rest-api-reference/endpoint/multi-metadata) If you want asset-level market data and supply stats across chains, use: [**Asset Details**](https://docs.mobula.io/rest-api-reference/endpoint/asset-details) *** ## Walkthrough to Get Metadata Categories ### 1. Click the API form This endpoint does not have a required parameter, you may just click **Send**. *** ## Reviewing the response Each item in the response represents one category: * `name`: Category name * `market_cap`: Total market cap for the category * `market_cap_change_24h`: Market cap percentage change over the last 24 hours * `market_cap_change_7d`: Market cap percentage change over the last 7 days *** ## Try It Live with Mobula Metadata Categories Demo (UI) You can also test this endpoint using our demo UI: [Demo UI Homepage](https://mobula-demo-endpoint-production.up.railway.app/) [Metadata Categories Demo UI](https://mobula-demo-endpoint-production.up.railway.app/metadata-categories) [Docs](https://docs.mobula.io/rest-api-reference/endpoint/metadata-categories) *** ## Summary The [**Metadata Categories**](https://docs.mobula.io/rest-api-reference/endpoint/metadata-categories) endpoint helps you: * Retrieve all asset categories with market cap and 24h and 7d changes * Call the endpoint with no parameters required * Build category dashboards and sector performance tracking views * Visualize results instantly in the Metadata Categories Demo UI *** ## Try Mobula for Free Try our free API today and start building in minutes.\ Get your free API key: [Here](https://admin.mobula.io/) # How to Get All Cryptocurrencies Available on Mobula Source: https://docs.mobula.io/guides/how-to-get-all-cryptocurrencies-available-on-mobula Use the All Cryptocurrencies endpoint to retrieve the full list of cryptocurrencies available in Mobula, with an optional fields parameter to reduce payload size. The [**All Cryptocurrencies**](https://docs.mobula.io/rest-api-reference/endpoint/all) endpoint lets you retrieve the full list of cryptocurrencies available in Mobula. Because this endpoint can return a lot of data, you can use the `fields` parameter to only return what you need. This is useful for building token lists, dropdowns, and bulk lookups. ****** ## What this endpoint does With this API, you can: * Retrieve a list of all cryptocurrencies available in Mobula * Use the optional `fields` parameter to select which fields are returned * Reduce payload size by returning only specific columns like `price`, `logo`, `name`, or `symbol` *** ## What you’ll need * Basic knowledge of REST APIs * No required parameters for this endpoint * A Mobula API key Note: All Mobula endpoints require an API key.\ Get a free API key: [Here](https://admin.mobula.io/) *** ## When to use All Cryptocurrencies Use this endpoint when you want to: * Retrieve the full list of cryptocurrencies available in Mobula * Fetch specific columns like price, logo, or symbol in bulk using `fields` * Reduce response size by limiting output fields for your use case If you want to search by a query string instead of downloading the entire list, use: [**Fast Search**](https://docs.mobula.io/rest-api-reference/endpoint/fast-search) If you want real-time market data for a specific token or market, use: [**Market Details**](https://docs.mobula.io/rest-api-reference/endpoint/market-details) If you want enriched metadata (description, socials, tags) for a specific asset, use: [**Metadata**](https://docs.mobula.io/rest-api-reference/endpoint/metadata) *** ## Walkthrough to Get All Cryptocurrencies ### 1. Prepare your query This endpoint has no required parameters. You can optionally use `fields` to reduce payload size. | Parameter | Description | | - | - | | `fields` | Comma-separated list of fields to return (example: `logo,price,symbol,name`) | Tip: This endpoint can return a large payload. For dashboards and token lists, using `fields` is usually the fastest option. ### 2. Fill the API form Either: * Call the endpoint without `fields` to retrieve the default payload, or * Add `fields` to return only specific columns Then click **Send**. *** ## Reviewing the response The response contains a list of cryptocurrencies Mobula tracks. * If you do not set `fields`, you receive the default fields for each cryptocurrency * If you set `fields`, the response returns only the selected columns for each item *** ## Summary The [**All Cryptocurrencies**](https://docs.mobula.io/rest-api-reference/endpoint/all) endpoint helps you: * Retrieve all cryptocurrencies available in Mobula with one request * Use `fields` to reduce payload size and return only what you need * Build token lists, dropdowns, and bulk mapping tables * Create your own search or indexing layer on top of the dataset *** ## Try Mobula for Free Try our free API today and start building in minutes.\ Get your free API key: [Here](https://admin.mobula.io/) # How to Get Asset Details Across Ethereum, Solana, BNB, Base & More Source: https://docs.mobula.io/guides/how-to-get-asset-details Use the Asset Details endpoint to retrieve asset-level information across chains in one request, including metadata, market data, supply stats, and associated token contracts. The [**Asset Details**](https://docs.mobula.io/rest-api-reference/endpoint/asset-details) endpoint lets you retrieve asset-level information across chains in one request. This includes metadata, market data, supply statistics, and detailed token information for each contract linked to the asset across chains like [Solana](https://docs.mobula.io/blockchains/solana), [Ethereum](https://docs.mobula.io/blockchains/ethereum), [BNB Chain](https://docs.mobula.io/blockchains/bsc), [Base](https://docs.mobula.io/blockchains/base), and more. You can query by Mobula asset ID, or by token address and blockchain. ****** ## What this endpoint does With this API, you can: * Retrieve comprehensive asset-level data including metadata, market statistics, and supply stats * Aggregate data at the asset level and return token details for associated contracts across chains * Query by `id` (Mobula asset ID), or `address` + `blockchain` (resolve the asset from a token contract) * Control how many token contracts return enriched details using `tokensLimit` * Batch query multiple assets in a single request using POST *** ## What you’ll need * Basic knowledge of REST APIs * An asset ID or token address (depending on how you query) * A Mobula API key Note: All Mobula endpoints require an API key.\ Get a free API key: [Here](https://admin.mobula.io/) Optional: * DexScreener (to find token addresses to test) *** ## When to use Asset Details Use this endpoint when you want to: * Retrieve a complete asset snapshot across chains, not just one token contract * Display asset metadata like name, symbol, logo, description, rank, and socials * Pull supply and valuation fields like total supply, circulating supply, and market cap * List token contracts linked to the same asset and show token-level market stats * Build multi-chain dashboards that need asset-level aggregation If you want contract-level enriched data for a single token, use: [**Token Details**](https://docs.mobula.io/rest-api-reference/endpoint/token-details) If you want token security signals like honeypot flags, taxes, and restrictions, use: [**Token Security**](https://docs.mobula.io/rest-api-reference/endpoint/token-security-get) If you want market-level pool stats like liquidity, volume, and price changes, use: [**Market Details**](https://docs.mobula.io/rest-api-reference/endpoint/market-details) If you want all markets (pairs) for a token across DEXes, use: [**Token Markets**](https://docs.mobula.io/rest-api-reference/endpoint/token-markets) *** ## Walkthrough to Get Asset Details ### 1. Prepare your query The Asset Details endpoint supports two query modes: | Parameter | Description | | - | - | | `id` | Mobula asset ID. Use this to query the asset directly. Required if `address` is not provided. | | `address` | Token contract address (EVM) or token mint address (Solana). Required if `id` is not provided and must be used with `blockchain`. | | `blockchain` | Blockchain identifier (example: `evm:1`, `solana`, `ethereum`). Required when using `address`. | Optional parameters you can use: * `tokensLimit`: Maximum number of tokens to return enriched detailed data for (default: `10`, max: `50`) Tip: Provide either `id`, or `address` + `blockchain`. You do not need both. ### 2. Find a token address to test with DexScreener To get a real token address: * Open DexScreener * Pick a token * Open its token page (or open a pair page for the token) * Copy the token contract address (or Solana mint address) * Note the chain the token is on (you will use this for `blockchain`) This address is used as the `address` parameter. ### 3. Fill the API form Either: * Paste an `id`, or * Paste `address` and `blockchain` (Optional) set `tokensLimit` if needed, then click **Send**. *** ## Reviewing the response The response contains one main object with asset-level info and token-level info. **Asset object** * `asset.id`: Unique asset identifier in Mobula * `asset.name` / `asset.symbol`: Asset name and ticker * `asset.logo` / `asset.description`: Display metadata for UIs * `asset.rank`: Market cap rank when available * `asset.nativeChainId`: Native chain if this is a native coin * `asset.priceUSD`: Current price in USD * `asset.totalSupply` / `asset.circulatingSupply`: Supply statistics * `asset.marketCapUSD` / `asset.marketCapDilutedUSD`: Market cap and fully diluted market cap * `asset.athPriceUSD` / `asset.athPriceDate`: All-time high price and date when available * `asset.atlPriceUSD` / `asset.atlPriceDate`: All-time low price and date when available * `asset.socials`: Links like website, Twitter, GitHub, Discord when available **Tokens array** * `tokens[]`: Token contracts associated with this asset * Token objects in `tokens[]` include the same type of enriched fields you get from [**Token Details**](https://docs.mobula.io/rest-api-reference/endpoint/token-details), such as price, liquidity, volume, and more * `tokensCount`: Total number of tokens associated with the asset (may be higher than the number returned if `tokensLimit` is smaller) **tokensLimit tip** * Use a lower `tokensLimit` for faster responses when you only need the top token contracts * Increase `tokensLimit` when you need more detailed contract coverage for the asset *** ## Try It Live with Mobula Asset Details Demo (UI) You can also test this endpoint using our demo UI: [Demo UI Homepage](https://mobula-demo-endpoint-production.up.railway.app/) [Asset Details Demo UI](https://mobula-demo-endpoint-production.up.railway.app/asset-details) [Docs](https://docs.mobula.io/rest-api-reference/endpoint/asset-details) *** ## Summary The [**Asset Details**](https://docs.mobula.io/rest-api-reference/endpoint/asset-details) endpoint helps you: * Retrieve asset-level metadata, market data, and supply stats across chains * Query by Mobula asset ID or by token address plus blockchain * Use `tokensLimit` to control how many associated token contracts return enriched details * Visualize results instantly in the Asset Details Demo UI *** ## Try Mobula for Free Try our free API today and start building in minutes.\ Get your free API key: [Here](https://admin.mobula.io/) # How to Get In-depth Token Details Across Ethereum, Solana, BNB, Base & More Source: https://docs.mobula.io/guides/how-to-get-in-depth-token-details Use the Token Details endpoint to retrieve in-depth information for a token by contract address. The [**Get Token Details**](https://docs.mobula.io/rest-api-reference/endpoint/token-details) endpoint lets you retrieve in-depth token information using a contract address. This includes token metadata, supply details, market data, and volume statistics across chains like [Solana](https://docs.mobula.io/blockchains/solana), [Ethereum](https://docs.mobula.io/blockchains/ethereum), [BNB Chain](https://docs.mobula.io/blockchains/bsc), [Base](https://docs.mobula.io/blockchains/base), and more. ****** ## What this endpoint does With this API, you can: * Retrieve detailed token information for a specific token by address * Return metadata like name, symbol, decimals, and logo * Include supply and market fields like total supply, circulating supply, market cap, and liquidity * Return volume, trades, and price change data across multiple timeframes * Support optional multi-currency price conversion using the `currencies` parameter *** ## What you’ll need * Basic knowledge of REST APIs * A token contract address * A Mobula API key Note: All Mobula endpoints require an API key.\ Get a free API key: [Here](https://admin.mobula.io/) Optional: * DexScreener (to quickly find token contract addresses) *** ## When to use Token Details Use this endpoint when you want to: * Display token metadata and market stats for a contract address * Check supply and market cap details, including diluted market cap * Track price changes and volume across multiple timeframes * Analyze liquidity and reserve data for a token * Pull token info for dashboards, watchlists, and token research pages If you need live trades for a token or pool, use: [**Get Token Trades**](https://docs.mobula.io/rest-api-reference/endpoint/token-trades) If you need top holders and holder tags, use: [**Get Token Holders**](https://docs.mobula.io/rest-api-reference/endpoint/market-token-holders) If you need historical prices for charting, use: [**Get Asset Price History**](https://docs.mobula.io/rest-api-reference/endpoint/asset-price-history) *** ## Walkthrough to Get Token Details ### 1. Prepare your query The `token/details` endpoint requires two parameters: | Parameter | Description | | - | - | | `blockchain` | Blockchain identifier (example: `ethereum`, `solana`, `evm:1`) | | `address` | Token contract address | Optional parameters you can use: * `currencies`: Comma-separated fiat currencies for conversion (example: `EUR,USD`)\ Default is USD. *** ### 2. Find a token address to test To retrieve real token data: * Open DexScreener * Pick any token * Copy the token contract address from the token page This address is used as the `address` parameter. *** ### 3. Fill the API form Once your token address is ready: * Enter the blockchain value (example: `solana`) * Paste the token contract into the `address` field * (Optional) add currencies like `currencies=EUR,USD` * Click **Send** to retrieve the token details snapshot *** ## Reviewing the response Key fields you will typically use: * `address` / `chainId`: Token contract address and chain identifier * `symbol` / `name` / `decimals`: Core metadata for display and formatting * `logo` / `originLogoUrl`: Token image URLs when available * `priceUSD`: Current token price in USD * `liquidityUSD` / `liquidityMaxUSD`: Liquidity depth metrics * `totalSupply` / `circulatingSupply`: Supply figures for valuation * `marketCapUSD` / `marketCapDilutedUSD`: Market cap values derived from supply and price * `priceChange*`: Price change percentages across multiple timeframes * `volume*`: Volume metrics across windows like 1h, 4h, 24h * `trades*` / `buys*` / `sells*`: Trade counts split by timeframe * `holdersCount`: Estimated number of holders when available * `socials`: Website, Twitter, Telegram links when available * `security`: Basic security flags such as honeypot or malicious signals * `organic*` fields: Cleaner metrics with bot activity filtered out Multi-currency note: If you set `currencies=EUR,USD`, the response adds converted fields like: * `priceEUR` * `marketCapEUR` * `volume24hEUR` *** ## Try It Live with Mobula Token Details Demo (UI) [Demo UI Homepage](https://mobula-demo-endpoint-production.up.railway.app/) [Token Details Demo UI](https://mobula-demo-endpoint-production.up.railway.app/token-details) [Docs](https://docs.mobula.io/rest-api-reference/endpoint/token-details) *** ## Summary The [**Get Token Details**](https://docs.mobula.io/rest-api-reference/endpoint/token-details) endpoint helps you: * Retrieve metadata, supply, market cap, liquidity, and volume stats * Add multi-currency output using the `currencies` parameter * Use organic metrics for deeper token research * Visualize token snapshots instantly in the demo UI *** ## Try Mobula for Free Try our free API today and start building in minutes.\ Get your free API key: [Here](https://admin.mobula.io/) # How to Get a Token Trade by Transaction Hash Across Ethereum, Solana, BNB, Base & More Source: https://docs.mobula.io/guides/how-to-get-token-trade-by-transaction-hash Use the Token Trade by Transaction endpoint to retrieve a specific trade using a transaction hash on supported blockchains. The [**Token Trade by Transaction**](https://docs.mobula.io/rest-api-reference/endpoint/token-trade) endpoint lets you retrieve a specific trade using a transaction hash. This is helpful when you already have a tx hash and want the trade details without knowing the pool or token address, across chains like [Solana](https://docs.mobula.io/blockchains/solana), [Ethereum](https://docs.mobula.io/blockchains/ethereum), [BNB Chain](https://docs.mobula.io/blockchains/bsc), [Base](https://docs.mobula.io/blockchains/base), and more. The endpoint returns the first trade found in that transaction. ****** ## What this endpoint does With this API, you can: * Retrieve a single trade by transaction hash on a specific blockchain * Return detailed swap information like amounts, USD value, execution prices, and fees * Include market context such as `marketAddress` and `marketAddresses` for multi-hop swaps * Include `swapRecipient` when available, which helps with accurate attribution in Account Abstraction flows * If a transaction contains multiple swaps, only the most recent one is returned *** ## What you’ll need * Basic knowledge of REST APIs * A transaction hash * A Mobula API key Note: All Mobula endpoints require an API key.\ Get a free API key: [Here](https://admin.mobula.io/) Optional: * DexScreener (to find transactions to test) *** ## When to use Token Trade by Transaction Use this endpoint when you want to: * Fetch the exact details of a trade when you only have a transaction hash * Monitor or audit specific trades after detecting an on-chain transaction * Show trade details when a user clicks a transaction inside a wallet activity view * Retrieve execution prices and fee breakdown for one specific swap * Handle Account Abstraction flows using `swapRecipient` when `transactionSenderAddress` is not the actual user If you want the full normalized activity feed for a wallet, use: [**Wallet Activity**](https://docs.mobula.io/rest-api-reference/endpoint/wallet-activity) If you want all swaps/trades for a wallet over time, use: [**Wallet Trades**](https://docs.mobula.io/rest-api-reference/endpoint/wallet-trades-v2) If you want pool-level context (price, liquidity, volume) for the market a trade happened on, use: [**Market Details**](https://docs.mobula.io/rest-api-reference/endpoint/market-details) *** ## Walkthrough to Get Token Trade by Transaction ### 1. Prepare your query The Token Trade by Transaction endpoint requires two parameters: | Parameter | Description | | - | - | | `blockchain` | Blockchain identifier (example: `base`, `ethereum`, `bsc`, `solana`) | | `transactionHash` | Transaction hash of the trade | Tip: Make sure you select the correct chain, such as [Base](https://docs.mobula.io/blockchains/base) or [Ethereum](https://docs.mobula.io/blockchains/ethereum). ### 2. Find a transaction hash to test with DexScreener To get a real transaction hash: * Open DexScreener * Pick a token * Open its pair page * Click **Trades** (or Recent Trades) * Click a trade entry to open the explorer * Copy the transaction hash This hash is used as the `transactionHash` parameter. ### 3. Fill the API form Enter the blockchain and paste the transaction hash into `transactionHash`, then click **Send**. *** ## Reviewing the response The response contains a single trade object, including: * `id`: Unique swap identifier * `operation`: Swap operation type like `regular`, `deposit`, or `withdrawal` * `type`: Trade type like `buy`, `sell`, `deposit`, or `withdrawal` * `baseTokenAmount` / `quoteTokenAmount`: Token amounts traded in formatted units * `baseTokenAmountUSD` / `quoteTokenAmountUSD`: USD value for each side of the trade * `date`: Trade timestamp in milliseconds * `transactionHash`: The transaction hash you queried * `marketAddress`: Main pool or market address where the trade occurred * `marketAddresses`: All market addresses involved for multi-hop swaps * `swapSenderAddress`: Address that executed the swap * `transactionSenderAddress`: Transaction originator address * `swapRecipient`: Wallet that receives the output tokens, useful for accurate attribution in AA flows * `baseTokenPriceUSD` / `quoteTokenPriceUSD`: Execution prices in USD at the time of the trade * `labels`: Wallet labels when available * `walletMetadata`: Enriched wallet metadata when available * `platform`: Trading platform or aggregator object when available * `totalFeesUSD`: Total fees paid in USD * `gasFeesUSD` / `platformFeesUSD` / `mevFeesUSD`: Fee breakdown fields *** ## Try It Live with Mobula Token Trade by Transaction Demo (UI) You can also test this endpoint using our demo UI: [Demo UI Homepage](https://mobula-demo-endpoint-production.up.railway.app/) [Token Trade by Transaction Demo UI](https://mobula-demo-endpoint-production.up.railway.app/token-trade-detail) [Docs](https://docs.mobula.io/rest-api-reference/endpoint/token-trade) *** ## Summary The [**Token Trade by Transaction**](https://docs.mobula.io/rest-api-reference/endpoint/token-trade) endpoint helps you: * Retrieve a specific trade by blockchain and transaction hash * Get full swap context including amounts, USD values, execution prices, and fees * Use `swapRecipient` when available for accurate user attribution in Account Abstraction flows * Visualize the trade details instantly in the demo UI *** ## Try Mobula for Free Try our free API today and start building in minutes.\ Get your free API key: [Here](https://admin.mobula.io/) # How to Get Wallet Balance of a Single Token Across All Chains Source: https://docs.mobula.io/guides/how-to-get-wallet-balance-of-a-single-token-across-all-chains Learn how to query the balance and position of a specific token (native, USDC, USDT, or any contract) for any wallet using the Mobula API /wallet/position endpoint. Want to know how much SOL, ETH, USDC, or any token a wallet holds — along with full PnL data? The **Wallet Position** endpoint (`/api/2/wallet/position`) returns the balance, USD value, and complete trading history for a single token in one call.**Quick Start**: Get your free API key at [admin.mobula.io](https://admin.mobula.io) to start querying immediately. ## Overview The `/api/2/wallet/position` endpoint returns everything you need about a wallet's holding of a specific token on a specific blockchain: * **Balance** (token amount + USD value) * **PnL** (realized, unrealized, total) * **Trading stats** (buys, sells, volume, avg prices) * **Full token metadata** (price, market cap, liquidity, logo, etc.) ## Parameters | Parameter | Type | Required | Description | | - | - | - | - | | `wallet` | string | Yes | The wallet address to query | | `asset` | string | Yes | The token contract address. Use `0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee` for native tokens (ETH, BNB, SOL, etc.) | | `blockchain` | string | Yes | The blockchain to query (e.g. `Solana`, `1` for Ethereum, `8453` for Base, etc.) | ## Examples ### 1. Get Native Token Balance (SOL on Solana) Use `0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee` as the asset address to query any chain's native token. **cURL** ```bash theme={null} curl -X GET "https://api.mobula.io/api/2/wallet/position?wallet=3GKvD6Fbj19HKnKdJJboMSZM1Mt9MZeehPGcq1DHBAGS&asset=0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee&blockchain=Solana" \ -H "Authorization: YOUR_API_KEY" ``` **TypeScript** ```typescript theme={null} const response = await fetch( "https://api.mobula.io/api/2/wallet/position?" + new URLSearchParams({ wallet: "3GKvD6Fbj19HKnKdJJboMSZM1Mt9MZeehPGcq1DHBAGS", asset: "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee", blockchain: "Solana", }), { headers: { Authorization: "YOUR_API_KEY" } } ); const { data } = await response.json(); console.log(`${data.token.symbol} balance: ${data.balance}`); console.log(`USD value: $${data.amountUSD.toFixed(2)}`); console.log(`Realized PnL: $${data.realizedPnlUSD.toFixed(2)}`); console.log(`Unrealized PnL: $${data.unrealizedPnlUSD.toFixed(2)}`); ``` **Python** ```python theme={null} import requests response = requests.get( "https://api.mobula.io/api/2/wallet/position", params={ "wallet": "3GKvD6Fbj19HKnKdJJboMSZM1Mt9MZeehPGcq1DHBAGS", "asset": "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee", "blockchain": "Solana", }, headers={"Authorization": "YOUR_API_KEY"}, ) data = response.json()["data"] print(f"{data['token']['symbol']} balance: {data['balance']}") print(f"USD value: ${data['amountUSD']:.2f}") ``` **Response** ```json theme={null} { "data": { "token": { "address": "So11111111111111111111111111111111111111112", "chainId": "solana:solana", "symbol": "SOL", "name": "Solana", "priceUSD": 181.20, "marketCapUSD": 46111177215, "logo": "https://metadata.mobula.io/assets/logos/solana_solana_So11111111111111111111111111111111111111112.webp" }, "balance": 12.5, "rawBalance": "12500000000", "amountUSD": 2265.0, "buys": 5, "sells": 2, "volumeBuy": 1800.0, "volumeSell": 500.0, "avgBuyPriceUSD": 160.0, "avgSellPriceUSD": 175.0, "realizedPnlUSD": 30.0, "unrealizedPnlUSD": 265.0, "totalPnlUSD": 295.0 } } ``` ### 2. Get ETH Balance on Ethereum ```bash theme={null} curl -X GET "https://api.mobula.io/api/2/wallet/position?wallet=0x77A89C51f106D6cD547542a3A83FE73cB4459135&asset=0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee&blockchain=1" \ -H "Authorization: YOUR_API_KEY" ``` ### 3. Get USDC Balance on Ethereum Pass the USDC contract address as the `asset` parameter: ```bash theme={null} curl -X GET "https://api.mobula.io/api/2/wallet/position?wallet=0x77A89C51f106D6cD547542a3A83FE73cB4459135&asset=0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48&blockchain=1" \ -H "Authorization: YOUR_API_KEY" ``` ### 4. Get USDT Balance on Arbitrum ```bash theme={null} curl -X GET "https://api.mobula.io/api/2/wallet/position?wallet=0x77A89C51f106D6cD547542a3A83FE73cB4459135&asset=0xFd086bC7CD5C481DCC9C85ebE478A1C0b69FCbb9&blockchain=42161" \ -H "Authorization: YOUR_API_KEY" ``` ### 5. Query Multiple Chains at Once (Batch) Need the same token balance on multiple chains? Use the **POST** batch endpoint to send multiple queries in a single request: ```typescript theme={null} const response = await fetch("https://api.mobula.io/api/2/wallet/position", { method: "POST", headers: { Authorization: "YOUR_API_KEY", "Content-Type": "application/json", }, body: JSON.stringify({ items: [ { wallet: "0x77A89C51f106D6cD547542a3A83FE73cB4459135", asset: "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee", blockchain: "1", }, { wallet: "0x77A89C51f106D6cD547542a3A83FE73cB4459135", asset: "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee", blockchain: "42161", }, { wallet: "0x77A89C51f106D6cD547542a3A83FE73cB4459135", asset: "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee", blockchain: "8453", }, ], }), }); const { payload } = await response.json(); for (const position of payload) { if ("error" in position) continue; console.log(`${position.token.symbol} on chain ${position.token.chainId}: ${position.balance} ($${position.amountUSD.toFixed(2)})`); } ``` ### 6. Using the Mobula SDK ```typescript theme={null} import { Mobula } from "@mobula/sdk"; const mobula = new Mobula({ apiKey: "YOUR_API_KEY" }); // Single position const position = await mobula.fetchWalletPosition({ wallet: "3GKvD6Fbj19HKnKdJJboMSZM1Mt9MZeehPGcq1DHBAGS", asset: "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee", blockchain: "Solana", }); console.log(`SOL balance: ${position.data.balance}`); console.log(`PnL: $${position.data.totalPnlUSD.toFixed(2)}`); ``` ## Common Contract Addresses Here are some commonly queried token addresses: | Token | Chain | Address | | - | - | - | | Native (ETH/SOL/BNB/...) | Any | `0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee` | | USDC | Ethereum (1) | `0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48` | | USDT | Ethereum (1) | `0xdAC17F958D2ee523a2206206994597C13D831ec7` | | USDC | Arbitrum (42161) | `0xaf88d065e77c8cC2239327C5EDb3A432268e5831` | | USDT | Arbitrum (42161) | `0xFd086bC7CD5C481DCC9C85ebE478A1C0b69FCbb9` | | USDC | Base (8453) | `0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913` | | USDC | Solana | `EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v` | ## Tips * **Native token shortcut**: `0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee` works for native tokens on every chain — the API automatically resolves it to the actual native address (WETH, WSOL, WBNB, etc.). * **Zero position**: If the wallet has never traded this token, the endpoint still returns the current balance and token metadata — PnL fields will be zero. * **Batch for multi-chain**: Use the POST batch endpoint when you need the same token across several chains — it's faster than individual calls. ## Need Assistance? Our support team is ready to help you with any questions or integration challenges.# How to Track Market Details Across Ethereum, Solana, BNB, Base & More Source: https://docs.mobula.io/guides/how-to-track-market-details Use the Market Details endpoint to retrieve market information for a specific pool or token address. The [**Get Market Details**](https://docs.mobula.io/rest-api-reference/endpoint/market-details) endpoint lets you retrieve market information for a specific pool or token address. This includes liquidity, volume, price changes, and trading activity across chains like [Solana](https://docs.mobula.io/blockchains/solana), [Ethereum](https://docs.mobula.io/blockchains/ethereum), [BNB Chain](https://docs.mobula.io/blockchains/bsc), [Base](https://docs.mobula.io/blockchains/base), and more. *** Telegram Slack Discord *** ## What this endpoint does With this API, you can: * Retrieve detailed market information for a specific pool or token address * Return base and quote token metadata plus market-level metrics * Include liquidity, volume, price changes, and trade activity across multiple timeframes * Support multi-currency output using the `currencies` parameter * Support batch queries via POST for fetching multiple markets in one request *** ## What you’ll need * Basic knowledge of REST APIs * A pool address * A Mobula API key Note: All Mobula endpoints require an API key.\ Get a free API key: [Here](https://admin.mobula.io/) Optional: * DexScreener (to find pool addresses to test) *** ## When to use Market Details Use this endpoint when you want to: * Display detailed pool or pair metrics for a DEX market page * Monitor liquidity and volume changes for a token pair over time * Track price change metrics across multiple timeframes like 1h and 24h * Retrieve both base and quote token metadata in the same response * Convert pricing and market metrics into other fiat currencies when needed If you want to list all markets where a token trades, use: [**Get Token Markets**](https://docs.mobula.io/rest-api-reference/endpoint/token-markets) If you want trade-level activity instead, use: [**Get Token Trades**](https://docs.mobula.io/rest-api-reference/endpoint/token-trades) *** ## Walkthrough to Get Market Details ### 1. Prepare your query The `market/details` endpoint requires two parameters: | Parameter | Description | | - | - | | `blockchain` | Blockchain identifier (example: `evm:1`, `solana`, `ethereum`) | | `address` | Direct pool or token address | Optional parameters you can use: * `currencies`: Comma-separated fiat currencies for conversion (example: `EUR,USD`). Default is USD. Tip: Make sure you select the correct chain, such as [Solana](https://docs.mobula.io/blockchains/solana) or [Ethereum](https://docs.mobula.io/blockchains/ethereum). ### 2. Find a pool address to test To retrieve real market data: * Open DexScreener * Pick a token * Open one of its trading pools * Copy the pool contract address This address is used as the `address` parameter. ### 3. Fill the API form Once your pool address is ready: * Enter the blockchain value into `blockchain` * Paste the pool contract into `address` * (Optional) add `currencies` if you want multi-currency output * Click **Send** to retrieve market details *** ## Reviewing the response The response returns detailed market metrics for the queried pool. Key fields include: * `data.base` / `data.quote`: Base and quote token objects including address, symbol, name, decimals, and pricing fields * `liquidityUSD`: Liquidity available in the market in USD * `latestTradeDate`: Timestamp of the most recent trade for the market * `address`: The pool or market address queried * `exchange`: Exchange metadata including name and logo when available * `priceUSD` / `priceToken`: Market price fields for the pair * `priceChange*`: Price change percentages across timeframes like 1h, 4h, 12h, and 24h * `volume*`: Volume metrics across multiple windows like 1h, 4h, 12h, and 24h * `trades*` / `buys*` / `sells*`: Trade counts split by timeframe and direction * `buyers*` / `sellers*` / `traders*`: Unique participant counts across time windows * `feesPaid*` and `totalFeesPaidUSD`: Aggregated fee metrics when available * `socials`: Social links when available * `security`: Basic security-related fields when available Multi-currency note:\ If you set `currencies=EUR,USD`, the response adds corresponding fields like `priceEUR`, `liquidityEUR`, and other converted values for USD-based metrics. *** ## Try It Live with Mobula Market Details Demo (UI) You can also test this endpoint using our demo UI: [Demo UI Homepage](https://mobula-demo-endpoint-production.up.railway.app/) [Market Details Demo UI](https://mobula-demo-endpoint-production.up.railway.app/market-details) [Docs](https://docs.mobula.io/rest-api-reference/endpoint/market-details) *** ## Summary The [**Get Market Details**](https://docs.mobula.io/rest-api-reference/endpoint/market-details) endpoint helps you: * Retrieve market details for a pool or token address using blockchain and address * Get liquidity, volume, price changes, and trading activity across multiple timeframes * Add multi-currency output using `currencies` when needed * Visualize results instantly in the demo UI *** ## Try Mobula for Free Try our free API today and start building in minutes.\ Get your free API key: [Here](https://admin.mobula.io/) # How to Track Market OHLCV History Across Ethereum, Solana, BNB, Base & More Source: https://docs.mobula.io/guides/how-to-track-market-ohlcv-history Use the Market OHLCV History endpoint to retrieve OHLCV candlestick data for a specific pool or market by address. The [**Get Market OHLCV History**](https://docs.mobula.io/rest-api-reference/endpoint/market-ohlcv-history) endpoint lets you retrieve OHLCV candlestick data for a specific pool or market by address. This returns open, high, low, close, and volume values across a selected candle period across chains like [Solana](https://docs.mobula.io/blockchains/solana), [Ethereum](https://docs.mobula.io/blockchains/ethereum), [BNB Chain](https://docs.mobula.io/blockchains/bsc), [Base](https://docs.mobula.io/blockchains/base), and more. It also supports batch queries when you need OHLCV history for multiple pools. ****** ## What this endpoint does With this API, you can: * Retrieve OHLCV (Open, High, Low, Close, Volume) candlestick data for a specific pool or market * Support GET for a single market and POST batch queries for up to 10 markets * Choose the candle resolution using the `period` parameter * Set a time range using `from` and `to` timestamps in milliseconds * Return USD prices (`usd=true` by default) *** ## What you’ll need * Basic knowledge of REST APIs * A pool address * A Mobula API key Note: All Mobula endpoints require an API key.\ Get a free API key: [Here](https://admin.mobula.io/) Optional: * DexScreener (to find pool addresses to test) *** ## When to use Market OHLCV History Use this endpoint when you want to: * Build candlestick charts for a specific pool or market when you already know the pool address * Analyze price action and volume at the pool level across consistent candle periods * Fetch historical OHLCV data for multiple pools using batch queries * Use pool-based OHLCV instead of token-based OHLCV when you want data from a specific market If you want token-level OHLCV history instead, use: [**Get Token OHLCV History**](https://docs.mobula.io/rest-api-reference/endpoint/token-ohlcv-history) If you want market-level stats instead of candles, use: [**Get Market Details**](https://docs.mobula.io/rest-api-reference/endpoint/market-details) *** ## Walkthrough to Get Market OHLCV History ### 1. Prepare your query The `market/ohlcv-history` endpoint requires two parameters: | Parameter | Description | | - | - | | `address` | Pool or market contract address | | `chainId` | Chain identifier (example: `ethereum`, `base`, `solana`) | Optional parameters you can use: * `period`: Candle resolution. Examples include `1m`, `5m`, `1h`, `4h`, `1d`, `1w`. Default is `5m`. * `from`: Start timestamp in milliseconds. Default is `0`. * `to`: End timestamp in milliseconds. Default is current time. * `amount`: Maximum number of candles to return. * `usd`: Return USD prices. Default is `true`. * `fill`: Forward-fill empty candles between trades so the series has no gaps. Default is `false`. Tip: Make sure you select the correct chain, such as [Solana](https://docs.mobula.io/blockchains/solana) or [Ethereum](https://docs.mobula.io/blockchains/ethereum). ### 2. Find a pool address to test To retrieve real market data: * Open DexScreener * Pick a token * Open one of its trading pools * Copy the pool contract address This address is used as the `address` parameter. ### 3. Fill the API form Once your pool address is ready: * Paste it into the `address` field * Enter the chain into `chainId` * (Optional) add `period` or `from` / `to` filters if needed * Click **Send** to retrieve OHLCV history *** ## Reviewing the response Each item in the response represents a candlestick: * `t`: Candle timestamp in milliseconds * `o`: Opening price for the candle * `h`: Highest price during the candle window * `l`: Lowest price during the candle window * `c`: Closing price for the candle * `v`: Volume during the candle window Batch query note:\ For POST batch requests, the response returns one entry per requested market with an `ohlcv` array and includes `address` and `chainId` for each market.\ If the market is not found, the entry can return an `error` field. *** ## Try It Live with Mobula Market OHLCV History Demo (UI) You can also test this endpoint using our demo UI: [Demo UI Homepage](https://mobula-demo-endpoint-production.up.railway.app/) [Market OHLCV History Demo UI](https://mobula-demo-endpoint-production.up.railway.app/market-ohlcv-history) [Docs](https://docs.mobula.io/rest-api-reference/endpoint/market-ohlcv-history) *** ## Summary The [**Get Market OHLCV History**](https://docs.mobula.io/rest-api-reference/endpoint/market-ohlcv-history) endpoint helps you: * Retrieve OHLCV candlestick history for a market using address and chainId * Choose candle resolution with period and narrow the time range with from and to * Batch query up to 10 markets with POST for dashboards and research tools * Visualize OHLCV history instantly in the demo UI *** ## Try Mobula for Free Try our free API today and start building in minutes.\ Get your free API key: [Here](https://admin.mobula.io/) # How to Track Pair Trades Across Ethereum, Solana, BNB, Base & More Source: https://docs.mobula.io/guides/how-to-track-pair-trades-market-trades-pair Use the Market Trades Pair endpoint to retrieve recent trade history for a specific trading pair or pool, with filtering, sorting, and pagination. The [**Market Trades Pair**](https://docs.mobula.io/rest-api-reference/endpoint/market-trades-pair) endpoint lets you retrieve recent trade history for a specific trading pair or pool. You can query directly by pair address, or resolve the most active pair linked to a token. This is useful for building market activity views with normalized pricing and volume metrics across chains like [Solana](https://docs.mobula.io/blockchains/solana), [Ethereum](https://docs.mobula.io/blockchains/ethereum), [BNB Chain](https://docs.mobula.io/blockchains/bsc), [Base](https://docs.mobula.io/blockchains/base), and more. ****** ## What this endpoint does With this API, you can: * Retrieve recent trade history for a specific trading pair or pool * Resolve the most active pair linked to a token when querying by `asset` mode * Return normalized pricing and volume metrics per trade record * Support pagination and sorting, plus optional filtering by minimum amount and sender *** ## What you’ll need * Basic knowledge of REST APIs * A pair or pool address * A Mobula API key Note: All Mobula endpoints require an API key.\ Get a free API key: [Here](https://admin.mobula.io/) Optional: * DexScreener (to find pair addresses to test) *** ## When to use Market Trades Pair Use this endpoint when you want to: * Display recent trades for a specific pair or pool * Build a live feed of buys and sells for a market * Filter trades by minimum USD size using `amount` * Sort trades by date or amount and paginate results * Investigate trades from a specific initiator address using `transactionSenderAddress` If you want token-level trades (not pair-specific), use: [**Get Token Trades**](https://docs.mobula.io/rest-api-reference/endpoint/token-trades) If you want one specific trade by transaction hash, use: [**Get Token Trade by Transaction**](https://docs.mobula.io/rest-api-reference/endpoint/token-trade) If you want market-level stats like price, liquidity, and volume for the pair, use: [**Get Market Details**](https://docs.mobula.io/rest-api-reference/endpoint/market-details) *** ## Walkthrough to Get Market Trades Pair ### 1. Prepare your query The Market Trades Pair endpoint requires two parameters: | Parameter | Description | | - | - | | `blockchain` | Blockchain name or ID (example: `evm:1`, `evm:56`, `ethereum`, `bsc`, `base`, `solana`) | | `address` | Specific pair or pool contract address to query trades for | Optional parameters you can use: * `mode`: Query mode. Common values include `pair` or `asset` (default is `pair`) * `asset`: Asset name or token contract address to resolve the most active pair automatically (used with `mode=asset`) * `symbol`: Token ticker symbol as an alternative to `asset` * `limit`: Maximum number of trade records to return * `offset`: Pagination offset (default: `0`) * `amount`: Minimum trade amount filter * `sortBy`: Field to sort by (example: `amount_usd`, `date`) * `sortOrder`: Sort order `asc` or `desc` (default: `desc`) * `transactionSenderAddress`: Filter trades initiated by a specific transaction sender address Tip: If you use `mode=asset`, you can provide `asset` (or `symbol`) and the endpoint will resolve it to the most active pair automatically. ### 2. Find a pair address to test with DexScreener To get a real pair address: * Open DexScreener * Pick a token * Open one of its pairs * Copy the pair or pool contract address This address is used as the `address` parameter. ### 3. Fill the API form Once your pair address is ready: * Enter `blockchain` * Paste the pair address into `address` * (Optional) set `limit`, `offset`, `amount`, `sortBy`, `sortOrder`, or `transactionSenderAddress` * Click **Send**… *** ## Reviewing the response Each item in `data[]` represents a trade record and typically includes: * `blockchain`: Chain where the trade happened * `hash`: On-chain transaction hash * `pair`: Pair or pool address * `date`: Trade timestamp * `type` / `operation`: Trade direction and operation type (buy, sell, swap, etc.) * Token prices: price fields for the quoted token and USD pricing when available * Amounts: amounts in raw units, token units, and USD equivalent * Sender fields: swap sender and transaction initiator address fields * `platform`: Platform or aggregator used (example: axiom, gmgn, padre, trojan, universalX) when available * Fee breakdown: `totalFeesUSD`, `gasFeesUSD`, `platformFeesUSD`, `mevFeesUSD` when available *** ## Try It Live with Mobula Market Trades Pair Demo (UI) You can also test this endpoint using our demo UI: [Demo UI Homepage](https://mobula-demo-endpoint-production.up.railway.app/) [Market Trades Pair Demo UI](https://mobula-demo-endpoint-production.up.railway.app/market-trades-pair) [Docs](https://docs.mobula.io/rest-api-reference/endpoint/market-trades-pair) *** ## Summary The [**Market Trades Pair**](https://docs.mobula.io/rest-api-reference/endpoint/market-trades-pair) endpoint helps you: * Retrieve recent trade history for a specific pair or pool using `blockchain` and `address` * Optionally resolve the most active pair linked to a token using `mode=asset` * Filter, sort, and paginate trade records for market activity dashboards * Visualize results instantly in the Market Trades Pair Demo UI *** ## Try Mobula for Free Try our free API today and start building in minutes.\ Get your free API key: [Here](https://admin.mobula.io/) # How to Track a Token Developer's On-Chain Activity Source: https://docs.mobula.io/guides/how-to-track-token-dev-history Use the Token Dev History endpoint to get a single merged feed of a token deployer's fee claims, swaps, and transfers — across PumpFun, PumpSwap, Meteora DBC (Bags, Moonshot, Believe) and more.**Alpha** — This endpoint is in early access. Response shape, field names, and filter semantics may change without notice. `swap` and `transfer` rows are chain-agnostic — they work on any chain Mobula indexes (Solana and every supported EVM chain). `feeClaim` coverage is launchpad-specific: all major Solana launchpads (PumpFun, PumpSwap, Meteora DBC) plus **Clanker** on EVM, with other EVM launchpads (e.g. Bankr) still rolling out. The [**Token Dev History**](https://docs.mobula.io/rest-api-reference/endpoint/token-dev-history) endpoint returns a single, chronological feed of a token deployer's on-chain activity for a specific coin — so you can see **what the dev is doing** in one place instead of stitching together fee-claim events, DEX swaps, and wallet transfers across three different datasets. It's the same feed you'd build to power a "dev activity" panel, a rug-detection alert, or a trust score. *** ## What this endpoint does One call returns a merged, paginated stream of three polymorphic event types, all attributable to the token's deployer: * **`feeClaim`** — the deployer drained their accumulated trading fees from a protocol vault. * Solana: **PumpFun** bonding curve, **PumpSwap** AMM, and **Meteora DBC** — which is the underlying program for **Bags**, **Moonshot**, **Believe**, **Subs.fun**, **Cults.fun**, **Time.fun**, and most Solana launchpads. You don't have to query each launchpad separately. * EVM: **Clanker** creator-fee claims (primarily Base). Other EVM launchpads (e.g. Bankr) are still rolling out. * **`swap`** — the deployer executed a swap on a pool that contains the queried token. The `side` field tells you if they bought or sold from their perspective. * **`transfer`** — a direct token transfer to or from the deployer, with `direction: "in"` or `"out"`. Each row has a `type` discriminator — client code switches on that to render each variant. *** ## What you'll need Note: all Mobula endpoints require an API key. Get a free API key: [Here](https://admin.mobula.io/) You'll provide two things: * `blockchain` — e.g. `solana`, `base`, `ethereum`. * `token` — the token's mint / contract address. The endpoint reads the deployer from Mobula's token registry automatically; you don't need to know it yourself. *** ## When to use Token Dev History * **Rug & dump detection** — detect fresh `transfer` out-rows from the deployer while their coin is trading. * **Fee extraction scoring** — sum `feeClaim.amountRaw` to quantify how aggressively a dev is cashing out. * **Cross-launchpad dev views** — a Bags token graduates to PumpSwap? The same endpoint keeps following the deployer. * **Pre-trade due diligence** — show "last 10 dev actions" before a buy. If you want the **deployer's other tokens**, use the [Wallet Deployer endpoint](https://docs.mobula.io/rest-api-reference/endpoint/wallet-deployer). If you want wallet-level trade history for any address (not just the deployer), use [Wallet Trades](https://docs.mobula.io/rest-api-reference/endpoint/wallet-trades). *** ## Walkthrough ### 1. Prepare your query | Parameter | Required | Description | | - | - | - | | `blockchain` | Yes | Blockchain identifier (`solana`, `base`, `ethereum`, …). | | `token` | Yes | Token mint / contract address. | | `type` | No | Filter to one variant: `feeClaim`, `swap`, or `transfer`. | | `limit` | No | 1–200, default `50`. | | `offset` | No | Pagination offset, default `0`. | ### 2. Call the endpoint Full feed (all three types interleaved by date DESC): ```bash theme={null} curl -X GET "https://api.mobula.io/api/2/token/dev-history?blockchain=solana&token=Fv8HhSVUquGC8WHqmMJLp7QEZMN4cZqcZjeYUPqvbrrr&limit=50" \ -H "Authorization: Bearer" ``` Only fee claims (useful for a "dev earnings" card): ```bash theme={null} curl -X GET "https://api.mobula.io/api/2/token/dev-history?blockchain=solana&token=Fv8HhSVUquGC8WHqmMJLp7QEZMN4cZqcZjeYUPqvbrrr&type=feeClaim" ``` Next page: ```bash theme={null} curl -X GET "https://api.mobula.io/api/2/token/dev-history?blockchain=solana&token=Fv8HhSVUquGC8WHqmMJLp7QEZMN4cZqcZjeYUPqvbrrr&limit=50&offset=50" ``` ### 3. Discriminate on `type` in your client ```typescript theme={null} import { MobulaClient } from '@mobula_labs/sdk'; const mobula = new MobulaClient({ apiKey: process.env.MOBULA_API_KEY! }); const { data, deployer } = await mobula.fetchTokenDevHistory({ blockchain: 'solana', address: 'Fv8HhSVUquGC8WHqmMJLp7QEZMN4cZqcZjeYUPqvbrrr', limit: 50, }); for (const entry of data) { switch (entry.type) { case 'feeClaim': console.log( `🎁 ${deployer} claimed ${entry.amountRaw} of ${entry.quoteAddress} on ${entry.protocol}`, ); break; case 'swap': console.log( `🔁 dev ${entry.side === 'buy' ? 'bought' : 'sold'} — tx ${entry.transactionHash}`, ); break; case 'transfer': console.log( `📤 dev ${entry.direction === 'out' ? 'sent to' : 'received from'} ${entry.counterpartyAddress}`, ); break; } } ``` *** ## Attribution caveats For PumpFun bonding curve and PumpSwap AMM, the creator fee vault is derived from the creator's address alone and is **shared across all their coins**. A `feeClaim` row under those protocols reflects one real on-chain claim, but the amount may include fees accumulated from other coins by the same deployer. If you need exact per-coin attribution, rely on `meteoradbc` rows, which carry `tokenAddress` and `poolAddress` precisely (per-pool vaults). *** ## Related endpoints * [Token Trades](https://docs.mobula.io/rest-api-reference/endpoint/token-trades) — all trades on a token, not just the deployer's. * [Wallet Trades](https://docs.mobula.io/rest-api-reference/endpoint/wallet-trades) — trades for an arbitrary wallet. * [Wallet Deployer](https://docs.mobula.io/rest-api-reference/endpoint/wallet-deployer) — all tokens the deployer created. # How to Track Token First Buyers Across Solana, Ethereum, BNB, Base & More Source: https://docs.mobula.io/guides/how-to-track-token-first-buyers Easily retrieve the earliest buyers of any token using the Mobula API. The [**Get Token First Buyers**](https://docs.mobula.io/rest-api-reference/endpoint/wallet-first-buyers) endpoint returns the first buyer wallets for a given asset on a specific blockchain. It is ideal for developers building **token launch analytics**, **early buyer tracking tools**, **holder discovery views**, and **on-chain research dashboards**. *** *** ## What this endpoint does With this API, you can: * Retrieve the **first buyers** of a token (early wallets) * Query by `asset` (token contract address) + `blockchain` * Control how many first buyers you return using `limit` * Use early buyer data for launch tracking, distribution analysis, and wallet research Unlike holders ranking endpoints, this endpoint focuses specifically on the **earliest buyers**, not the largest holders today. *** ## What you’ll need * Basic knowledge of REST APIs * A token contract address (asset address) * A blockchain value (Solana, Ethereum, Base, BNB Chain, etc.) * A Mobula API key Note: All Mobula endpoints require an API key.\ Get a free API key: [Here](https://admin.mobula.io/) Optional: * DexScreener (to quickly find token addresses) *** ## When to use Get Token First Buyers Use this endpoint when you want to: * Track the earliest buyers right after a token launch * Build a “First Buyers” section in a token dashboard * Analyze early wallet participation and distribution * Discover early wallets to investigate further (labels, trades, PnL, etc.) If you want the current top holders, use the [**Token Holder Positions**](https://docs.mobula.io/rest-api-reference/endpoint/token-holder-positions) endpoint. *** ## Walkthrough to Get Token First Buyers ### 1. Prepare your query The token first buyers endpoint uses: | Parameter | Description | | - | - | | `asset` | Token contract address to analyze | | `blockchain` | Chain name or ID | Optional parameters you can use: * `limit`: number of first buyers to return * `offset`: pagination offset (when applicable) Tip: Use the blockchain field for chains like [Solana](https://docs.mobula.io/blockchains/solana), [Ethereum](https://docs.mobula.io/blockchains/ethereum), [Base](https://docs.mobula.io/blockchains/base), and more. ### 2. Find a token address to test To retrieve real token data: * Open DexScreener * Search for any token you want * Copy the token contract address from the token page This address is used as the `asset` parameter. ### 3. Identify the blockchain On DexScreener, check which chain the token is on (Solana, Ethereum, Base, etc.). Use that value as the `blockchain` parameter. ### 4. Fill the API form Once everything is filled: * Paste the token address into `asset` * Fill in the correct `blockchain` value * (Optional) set `limit` if you want fewer or more buyers * Click **Send** *** ## Reviewing the token first buyers response This endpoint helps you build token launch analytics like: * A list of earliest buyer wallet addresses * A configurable “first buyers” range (based on `limit`) * Fast early wallet discovery for follow-up analysis (labels, trades, activity, etc.) *** ## Try It Live with Mobula Token First Buyers Demo (UI) You can also test this endpoint using our demo UI: [Demo UI Homepage](https://mobula-demo-endpoint-production.up.railway.app/) [Token First Buyers Demo UI](https://mobula-demo-endpoint-production.up.railway.app/token-first-buyers) [Docs](https://docs.mobula.io/rest-api-reference/endpoint/wallet-first-buyers) *** ## Summary The [Get Token First Buyers](https://docs.mobula.io/rest-api-reference/endpoint/wallet-first-buyers) endpoint gives you early buyer discovery for a token across supported chains, using: * Token contract address + blockchain * A clean list of earliest buyers * Optional limits for how many first buyers you want to retrieve If you’re building token launch analytics, early holder tracking, or wallet research tools, this endpoint is a strong foundation. *** ## Try Mobula for Free Try our free API today and start building in minutes.\ Get your free API key: [Here](https://admin.mobula.io/) # How to Track Token Holders Across Ethereum, Solana, BNB, Base & More Source: https://docs.mobula.io/guides/how-to-track-token-holders-across-ethereum-solana-bnb-base Retrieve the top holders of any token, including holder tags, balances, supply share, and USD value, using the Mobula API. The [**Get Token Holders**](https://docs.mobula.io/rest-api-reference/endpoint/token-holder-positions) endpoint returns a ranked list of **token holders** for a specific asset, including enriched metadata like **wallet tags** (dev, LP, holder), token amounts, **total supply share**, and estimated **USD value**. It is ideal for developers building **holder dashboards**, **token analytics tools**, **risk monitoring**, and **on-chain research apps**. ****** ## What this endpoint does With this API, you can: * Fetch the top **token holders** for a specific asset * Retrieve holder balances in raw units and formatted token amounts * Get each holder’s share of **total supply (percentage)** * Estimate holder balance value in **USD** * Receive enriched holder tags (**dev**, **LP pairs**, **holder**, etc.) * Paginate through holders with `limit` and `offset` * Optionally include historical holders with zero balance Unlike a basic “holders list,” this endpoint returns enriched holder metadata that’s ready to display in a UI. *** ## What you’ll need * Basic knowledge of REST APIs * A token contract address (recommended) or token name * A blockchain identifier (required when using contract address) * A Mobula API key Note: All Mobula endpoints require an API key.\ Get a free API key: [Here](https://admin.mobula.io/) Optional: * DexScreener or a block explorer to find token contract addresses quickly *** ## When to use Get Token Holders Use this endpoint when you want to: * Build a “Top Holders” table for a token page * Track whales and concentration risk (top supply holders) * Identify dev wallets or LP-related addresses via tags * Monitor token distribution changes with pagination and offsets * Include historical holders who sold out (`includeZeroBalance=true`) If you need wallet-level analytics, use wallet endpoints like [**wallet/activity**](https://docs.mobula.io/rest-api-reference/endpoint/wallet-activity) or [**wallet/positions**](https://docs.mobula.io/rest-api-reference/endpoint/wallet-positions). *** ## Walkthrough — Get Token Holders for a Token ### 1. Prepare your query The `market/token/holders` endpoint supports two common query modes. Recommended: Contract address mode (most accurate) | Parameter | Description | | - | - | | `asset` | Token contract address | | `blockchain` | Chain identifier (example: `1` for [Ethereum](https://docs.mobula.io/blockchains/ethereum), `solana` for [Solana](https://docs.mobula.io/blockchains/solana)) | Optional parameters you can use to control output: * `limit` (max 100): number of holders returned (default 20) * `offset`: pagination offset (default 0) * `includeZeroBalance`: include historical holders who now have 0 balance (default false) Alternative: Name mode You can also set `asset=Bitcoin` or `asset=Ethereum`, but contract address + blockchain is the safest for exact matches. Note: `backfill` exists as a feature, but you do not need it for the typical “top holders” use case. ### 2. Find a token contract address To get a valid token address quickly: * Open DexScreener (or a block explorer) * Search for the token you want to analyze * On the token page, copy the contract address * Confirm the chain (Solana, Ethereum, Base, etc.) so you can fill the blockchain parameter correctly ### 3. Fill the API form Back in the endpoint “Try it” form: * Paste the contract address into the `asset` field * Fill in `blockchain` for the chain the token is deployed on * Set `limit` and `offset` if you want pagination * Click **Send** *** ## Reviewing the token holders response The response returns a ranked list of holders plus a total count. What you typically get per holder: * `address`: the holder wallet address * `amountRaw`: raw token balance (before decimals) * `amount`: formatted token balance * `chainId`: chain identifier (example: ethereum:1, solana:solana) * `totalSupplyShare`: % of total supply held by the wallet * `amountUSD`: estimated USD value of the holdings * `tag`: enriched label (dev, LP pair label, holder, etc.) This makes it easy to build a top holders table with supply concentration and wallet tagging. *** ## Try It Live with Mobula Token Holders Demo (UI) You can also test this endpoint using our demo UI: [Demo UI Homepage](https://mobula-demo-endpoint-production.up.railway.app/) [Token Holders Demo UI](https://mobula-demo-endpoint-production.up.railway.app/token-holders) [Docs](https://docs.mobula.io/rest-api-reference/endpoint/token-holder-positions) *** ## Summary The [Get Token Holders](https://docs.mobula.io/rest-api-reference/endpoint/token-holder-positions) endpoint helps you retrieve and display token distribution data, including: * Top holders ranked by **balance** * Token balance amounts (raw and formatted) * USD value estimates * Total supply share per holder * Enriched holder tags * Pagination with `limit` and `offset` * Optional inclusion of zero-balance historical holders If you’re building token pages, holder dashboards, or monitoring tools, this endpoint is a strong foundation for token distribution analytics. *** ## Try Mobula for Free Try our free API today and start building in minutes.\ Get your free API key: [Here](https://admin.mobula.io/) # How to Track Token Markets Across Ethereum, Solana, BNB, Base & More Source: https://docs.mobula.io/guides/how-to-track-token-markets Use the Token Markets endpoint to retrieve market data for a token using its contract address. The [**Get Token Markets**](https://docs.mobula.io/rest-api-reference/endpoint/token-markets) endpoint lets you retrieve market data for a token using its contract address. This returns market-level details like liquidity, volume, price changes, and trading activity across chains like [Solana](https://docs.mobula.io/blockchains/solana), [Ethereum](https://docs.mobula.io/blockchains/ethereum), [BNB Chain](https://docs.mobula.io/blockchains/bsc), [Base](https://docs.mobula.io/blockchains/base), and more. ****** ## What this endpoint does With this API, you can: * Retrieve market information matching a token on a specific blockchain * Return market-level data such as liquidity, volume, price changes, and trade activity * Include base and quote token metadata for each market * Support limiting results to control how many markets are returned *** ## What you’ll need * Basic knowledge of REST APIs * A token address * A Mobula API key Note: All Mobula endpoints require an API key.\ Get a free API key: [Here](https://admin.mobula.io/) Optional: * DexScreener (to find token addresses to test) *** ## When to use Token Markets Use this endpoint when you want to: * List the markets or pools where a token is trading * Compare liquidity across different markets for the same token * Track volume, trades, and price change metrics at the market level * Build token market pages for dashboards and analytics tools * Limit results to show only the top markets you care about If you need in-depth token metadata instead, use: [**Get Token Details**](https://docs.mobula.io/rest-api-reference/endpoint/token-details) If you need trade-level activity instead, use: [**Get Token Trades**](https://docs.mobula.io/rest-api-reference/endpoint/token-trades) *** ## Walkthrough to Get Token Markets ### 1. Prepare your query The `token/markets` endpoint requires two parameters: | Parameter | Description | | - | - | | `blockchain` | Blockchain identifier (example: `evm:1`, `solana`, `ethereum`) | | `address` | Direct token address | Optional parameters you can use: * `limit`: Number of markets to return (default: `10`, max: `25`) Tip: Make sure you select the correct chain, such as [Solana](https://docs.mobula.io/blockchains/solana) or [Ethereum](https://docs.mobula.io/blockchains/ethereum). ### 2. Find a token address to test To retrieve real token market data: * Open DexScreener * Pick a token * Copy the token contract address from the token page This address is used as the `address` parameter. ### 3. Fill the API form Once your token address is ready: * Enter the blockchain value into `blockchain` * Paste the token contract into `address` * (Optional) set `limit` to control how many markets are returned * Click **Send** to retrieve token market data *** ## Reviewing the response Each item in `data[]` represents a market for the token. Key fields include: * `base` / `quote`: Base and quote token objects with metadata like symbol, name, decimals, and price * `liquidityUSD`: Liquidity available in the market in USD * `latestTradeDate`: Timestamp of the most recent trade observed * `blockchain`: Blockchain name for the market * `address`: Market or pool address * `type`: DEX or market type (example: Uniswap v3 style markets) * `exchange`: Exchange object with name and logo * `priceUSD` / `priceToken`: Market pricing fields * `priceChange*`: Price change percentages across timeframes like 1h and 24h * `volume*`: Volume metrics across timeframes like 1h, 4h, and 24h * `trades*` / `buys*` / `sells*`: Trade counts across multiple time windows * `buyers*` / `sellers*` / `traders*`: Unique participant counts * `security`: Basic security-related fields when available * `socials`: Token social links when available *** ## Try It Live with Mobula Token Markets Demo (UI) You can also test this endpoint using our demo UI: [Demo UI Homepage](https://mobula-demo-endpoint-production.up.railway.app/) [Token Markets Demo UI](https://mobula-demo-endpoint-production.up.railway.app/token-markets) [Docs](https://docs.mobula.io/rest-api-reference/endpoint/token-markets) *** ## Summary The Get Token Markets endpoint helps you: * Retrieve token market data by providing blockchain and token address * Use `limit` to control how many markets are returned * Compare liquidity, volume, and price change stats across markets * Visualize results instantly in the demo UI *** ## Try Mobula for Free Try our free API today and start building in minutes.\ Get your free API key: [Here](https://admin.mobula.io/) # How to Track Token OHLCV History Across Ethereum, Solana, BNB, Base & More Source: https://docs.mobula.io/guides/how-to-track-token-ohlcv-history Use the Token OHLCV History endpoint to retrieve OHLCV candlestick data for a token by contract address. The [**Get Token OHLCV History**](https://docs.mobula.io/rest-api-reference/endpoint/token-ohlcv-history) endpoint lets you retrieve OHLCV candlestick data for a token by contract address. This returns open, high, low, close, and volume values across a selected candle period, across chains like [Solana](https://docs.mobula.io/blockchains/solana), [Ethereum](https://docs.mobula.io/blockchains/ethereum), [BNB Chain](https://docs.mobula.io/blockchains/bsc), [Base](https://docs.mobula.io/blockchains/base), and more. It also supports batch queries when you need OHLCV history for multiple tokens. ****** ## What this endpoint does With this API, you can: * Retrieve OHLCV (Open, High, Low, Close, Volume) candlestick data for a token * Use GET for a single token and POST batch queries for up to 10 tokens * Choose candle resolution using the `period` parameter * Set a time range using `from` and `to` timestamps in milliseconds * Return USD prices (`usd=true` by default) *** ## What you’ll need * Basic knowledge of REST APIs * A token contract address * A Mobula API key Note: All Mobula endpoints require an API key.\ Get a free API key: [Here](https://admin.mobula.io/) Optional: * DexScreener (to quickly find token addresses) *** ## When to use Token OHLCV History Use this endpoint when you want to: * Build price charts using OHLCV candles for a token * Backtest or analyze price action with consistent time-based candles * Pull historical volume and price movement for dashboards * Fetch OHLCV history for multiple tokens using batch queries If you only need the current token snapshot (metadata + price + liquidity + volume), use: [**Get Token Details**](https://docs.mobula.io/rest-api-reference/endpoint/token-details) If you need token price history without OHLCV candlesticks, use: [**Get Asset Price History**](https://docs.mobula.io/rest-api-reference/endpoint/asset-price-history) *** ## Walkthrough to Get Token OHLCV History ### 1. Prepare your query The `token/ohlcv-history` endpoint requires: | Parameter | Description | | - | - | | `address` | Token contract address | | `chainId` | Chain identifier (example: `ethereum`, `base`, `solana`) | Optional parameters you can use: * `period`: Candle resolution. Examples include `1m`, `5m`, `1h`, `4h`, `1d`, `1w`. Default is `5m`. * `from`: Start timestamp in milliseconds. Default is `0`. * `to`: End timestamp in milliseconds. Default is current time. * `amount`: Maximum number of candles to return. * `usd`: Return USD prices. Default is `true`. * `fill`: Forward-fill empty candles between trades so the series has no gaps. Default is `false`. ### 2. Find a token address to test To retrieve real token data: * Open DexScreener * Pick a token * Copy the token contract address from the token page This address is used as the `address` parameter. ### 3. Fill the API form Once your token address is ready: * Paste the token contract into the `address` field * Enter the chain in `chainId` (example: `solana`) * (Optional) set `period` or add `from` / `to` timestamps * Click **Send** to retrieve the OHLCV history *** ## Reviewing the response Each item in the response represents a candlestick: * `t`: Candle timestamp in milliseconds * `o`: Opening price for the candle * `h`: Highest price during the candle window * `l`: Lowest price during the candle window * `c`: Closing price for the candle * `v`: Volume during the candle window Batch query note: For POST batch requests, the response returns one entry per requested token with an `ohlcv` array and includes `address` and `chainId` for each token. If no pool is found, the entry can return an `error` field. *** ## Try It Live with Mobula Token OHLCV History Demo (UI) [Demo UI Homepage](https://mobula-demo-endpoint-production.up.railway.app/) [Token OHLCV History Demo UI](https://mobula-demo-endpoint-production.up.railway.app/token-ohlcv-history) [Docs](https://docs.mobula.io/rest-api-reference/endpoint/token-ohlcv-history) *** ## Summary The [**Get Token OHLCV History**](https://docs.mobula.io/rest-api-reference/endpoint/token-ohlcv-history) endpoint helps you: * Retrieve OHLCV candlestick history using `address` and `chainId` * Choose candle resolution with `period` and narrow time range with `from` and `to` * Batch query up to 10 tokens with POST for dashboards and research tools * Visualize OHLCV history instantly in the demo UI *** ## Try Mobula for Free Try our free API today and start building in minutes.\ Get your free API key: [Here](https://admin.mobula.io/) # How to Track Token Trades Across Ethereum, Solana, BNB, Base & More Source: https://docs.mobula.io/guides/how-to-track-token-trades Use the Token Trades endpoint to retrieve recent trades for a specific token or pool. The [**Token Trades**](https://docs.mobula.io/rest-api-reference/endpoint/token-trades) endpoint lets you retrieve recent trades for a specific token or pool. This makes it easy to monitor live trading activity across chains like [Solana](https://docs.mobula.io/blockchains/solana), [Ethereum](https://docs.mobula.io/blockchains/ethereum), [BNB Chain](https://docs.mobula.io/blockchains/bsc), [Base](https://docs.mobula.io/blockchains/base), and more. ****** ## What this endpoint does With this API, you can: * Retrieve trades for a specific token or pool with pagination * Query trades using two modes: * **pair**: query trades for a specific pool or pair address * **asset**: query trades across top pools for a token asset * Filter results by swap types, wallet labels, sender addresses, date range, and USD amount * Return detailed trade fields, including the market address, token amounts, prices, and fees *** ## What you’ll need Note: All Mobula endpoints require an API key.\ Get a free API key: [Here](https://admin.mobula.io/) Optional: * DexScreener (to find token addresses and active traders) *** ## When to use Token Trades Use Token Trades when you want to: * Track recent buys and sells for a token or a specific pool * Filter trades by swap type like regular, deposit, or withdrawal * Investigate activity from specific wallets using sender address filters * Monitor large trades using minimum and maximum USD amount filters * Paginate through trade history for analytics or dashboards If you need wallet-level swap history, use: [**Get Wallet Trades**](https://docs.mobula.io/rest-api-reference/endpoint/wallet-trades) If you need full wallet activity feeds, use: [**Get Wallet Activity**](https://docs.mobula.io/rest-api-reference/endpoint/wallet-activity) *** ## Walkthrough to Get Token Trades ### 1. Prepare your query | Parameter | Description | | - | - | | `blockchain` | Blockchain identifier (example: base, ethereum, bsc) | | `address` | Token or pool address depending on mode | Optional parameters you can use: * `mode`: pair (default) to query a specific pool, or asset to query trades across top pools for a token * `limit`: Number of results per page (default: 10, max: 1000) * `offset`: Offset for pagination (default: 0) * `sortOrder`: asc or desc (default: desc) * `swapTypes`: Filter by swap types (example: REGULAR, DEPOSIT, WITHDRAWAL) * `transactionSenderAddresses`: Filter by transaction sender addresses (max: 25) * `label`: Filter by wallet label (example: PRO\_TRADER, SMART\_TRADER, FRESH\_TRADER, DEV) * `minAmountUSD`: Minimum trade amount in USD * `maxAmountUSD`: Maximum trade amount in USD * `fromDate`: Start date filter (ISO 8601 or Unix timestamp) * `toDate`: End date filter (ISO 8601 or Unix timestamp) ### 2. Find a wallet address to test To retrieve real token trade activity: * Open DexScreener * Pick a token * Click **Top Traders** * Select an active wallet * Open it in the blockchain explorer * Copy the wallet address This address is useful when filtering by sender addresses. ### 3. Fill the API form Once your blockchain and token or pool address are ready: * Enter the blockchain value (example: solana, ethereum, base) * Paste the token or pool address into the `address` field * (Optional) set swapTypes, labels, or USD size filters * Click **Send** to retrieve the token trades *** ## Reviewing the response Each item in data\[] represents a single trade: * `id`: Unique swap identifier for the trade * `operation`: Swap operation type such as regular, deposit, or withdrawal * `type`: Trade direction like buy or sell * `baseTokenAmount` / `quoteTokenAmount`: Token amounts traded in formatted units * `baseTokenAmountUSD` / `quoteTokenAmountUSD`: USD value for each side of the trade * `date`: Trade timestamp in milliseconds * `transactionHash`: On-chain transaction hash * `marketAddress`: Pool or market address where the trade occurred * `swapSenderAddress`: Address that executed the swap * `transactionSenderAddress`: Transaction originator address (tx.from) * `swapRecipient`: Wallet that receives the output tokens * `baseTokenPriceUSD` / `quoteTokenPriceUSD`: Token prices at execution time * `labels`: Wallet labels attached to the swap participant * `totalFeesUSD`: Total fees paid in USD, including gas, platform, and MEV fees *** ## Try It Live with Mobula Token Trades Demo (UI) [Demo UI Homepage](https://mobula-demo-endpoint-production.up.railway.app/) [Token Trades Demo UI](https://mobula-demo-endpoint-production.up.railway.app/token-trades) [Docs](https://docs.mobula.io/rest-api-reference/endpoint/token-trades) *** ## Summary The [**Token Trades**](https://docs.mobula.io/rest-api-reference/endpoint/token-trades) endpoint helps you: * Retrieve recent token or pool trades with pagination * Filter trades by swap type, wallet labels, sender addresses, date range, and USD amount * Use swapRecipient when available for accurate wallet attribution * Visualize trades instantly in the demo UI *** ## Try Mobula for Free Try our free API today and start building in minutes.\ Get your free API key: [Here](https://admin.mobula.io/) # How to Track Tokens Deployed by a Wallet Across Solana, Ethereum, Base & More Source: https://docs.mobula.io/guides/how-to-track-tokens-deployed-by-a-wallet Easily fetch all tokens deployed by a creator wallet, including enriched token metrics like liquidity, market performance, trading activity, and organic volume using the Mobula API. The [**Get Wallet Deployer Tokens**](https://docs.mobula.io/rest-api-reference/endpoint/wallet-deployer) endpoint returns every token created by a deployer wallet, enriched with **token metadata**, **liquidity and bonding data**, **price performance**, **organic volume**, and **wallet-level activity insights**. It is ideal for developers building **token discovery tools**, **deployer dashboards**, **on-chain research apps**, and **trader analytics**. ****** ## What this endpoint does With this API, you can: * Retrieve all tokens deployed by a specific wallet (**creator address**) * Get enriched token metadata (**symbol, name, supply, price, market cap**) * Access liquidity, bonding status, and pool details (when available) * Track token performance (**ATH/ATL, price changes, volume across timeframes**) * Analyze wallet-level activity (**buys, sells, volume, average prices, PnL**) * Review organic trading metrics (**organic volume, organic trades, buyers/sellers**) * Surface deployer and token context such as **source, exchange, and socials** Unlike token-only market endpoints, this endpoint is built for **deployer-first analysis**, so you can map a creator wallet to all tokens it launched. *** ## What you’ll need * Basic knowledge of REST APIs * A creator (**deployer**) wallet address * A Mobula API key Note: All Mobula endpoints require an API key.\ Get a free API key: [Here](https://admin.mobula.io/) Optional: * DexScreener (to find a token and copy its deployer wallet) *** ## When to use Get Wallet Deployer Tokens Use this endpoint when you want to: * List every token deployed by a creator wallet * Build a **deployer profile page** with token performance metrics * Analyze deployer activity and token outcomes over time * Detect token launches tied to a wallet * Power token research dashboards and on-chain due diligence tools If you want deeper token analytics after discovering deployed tokens, you can also use: * [**Get Token Details**](https://docs.mobula.io/rest-api-reference/endpoint/token-details) * [**Get Token Trades**](https://docs.mobula.io/rest-api-reference/endpoint/token-trades) * [**Get Token Holder Positions**](https://docs.mobula.io/rest-api-reference/endpoint/token-holder-positions) If you want full wallet-level activity tracking for the deployer, use: [**Get Wallet Activity**](https://docs.mobula.io/rest-api-reference/endpoint/wallet-activity) *** ## Walkthrough to Get Wallet Deployer Tokens ### 1. Prepare your query The `wallet/deployer` endpoint uses: | Parameter | Description | | - | - | | `wallet` | Creator wallet address to analyze | Optional parameters you can use: * `blockchain`: analyze a specific chain analyze a specific chain like [Solana](https://docs.mobula.io/blockchains/solana), [Ethereum](https://docs.mobula.io/blockchains/ethereum), and more (otherwise defaults to all supported chains) * `page`: paginate through the deployer’s token list * `limit`: control how many deployed tokens are returned per page ### 2. Find a deployer wallet address to test To retrieve real wallet data: 1. Open DexScreener 2. Search for any token 3. Open the token page 4. Copy the developer / creator / deployer address Use that address as the `wallet` parameter. ### 3. Fill the API form Back in the endpoint “Try it” form: * Paste the deployer address into `wallet` * (Optional) set `blockchain` if you want a single chain * Adjust `page` and `limit` if you want pagination * Click **Send** to retrieve deployed tokens *** ## Reviewing the deployer tokens response For each deployed token, the API can return: * Token metadata: **name, symbol, decimals, supply, logo, contract address** * Market data: **price, liquidity, volume, market cap, price change windows** * Liquidity and bonding context: **pool address, bonding status, reserves** * Wallet activity stats: **buys, sells, volume, average prices** * PnL signals: **realized and unrealized PnL metrics** (when available) * Organic metrics: **organic volume, trades, traders, buyers/sellers** * Source and socials: **exchange/source and socials** (when available) This makes it easy to build a deployer token list UI with meaningful performance and activity signals, not just token addresses. *** ## Try It Live with Mobula Wallet Deployer Demo (UI) You can also test this endpoint using our demo UI: [Demo UI Homepage](https://mobula-demo-endpoint-production.up.railway.app/) [Wallet Deployer Demo UI](https://mobula-demo-endpoint-production.up.railway.app/wallet-deployer) [Docs](https://docs.mobula.io/rest-api-reference/endpoint/wallet-deployer) *** ## Summary The [**Get Wallet Deployer Tokens**](https://docs.mobula.io/rest-api-reference/endpoint/wallet-deployer) endpoint helps you fetch all tokens deployed by a wallet and analyze each token with enriched market and activity metrics, including: * Deployer token discovery across chains * Liquidity, volume, market performance, and wallet activity * Organic trading metrics and deployer-linked signals If you’re building deployer dashboards, token discovery tools, or research workflows, this endpoint is a strong foundation. *** ## Try Mobula for Free Try our free API today and start building in minutes.\ Get your free API key: [Here](https://admin.mobula.io/) # How to Track Top Token Trader Positions Across Ethereum, Solana, BNB, Base & More Source: https://docs.mobula.io/guides/how-to-track-top-token-trader-positions Use the Token Trader Positions endpoint to retrieve the top trader positions for a token on a specific blockchain. The [**Get Token Trader Positions**](https://docs.mobula.io/rest-api-reference/endpoint/token-trader-positions) endpoint lets you retrieve the top trader positions for a token on a specific blockchain. This helps you understand who holds the token, how they traded it, and how their PnL evolves across chains like [Solana](https://docs.mobula.io/blockchains/solana), [Ethereum](https://docs.mobula.io/blockchains/ethereum), [BNB Chain](https://docs.mobula.io/blockchains/bsc), [Base](https://docs.mobula.io/blockchains/base), and more. ****** ## What this endpoint does With this API, you can: * Retrieve trader positions for a token on a specific blockchain * Return holdings, trading activity, and PnL fields per trader wallet * Filter results by trader label categories and specific wallet addresses * Control response size with a `limit` parameter * Optionally bypass cache with `force=true` *** ## What you’ll need * Basic knowledge of REST APIs * A token contract address * A Mobula API key Note: All Mobula endpoints require an API key. Get a free API key: [Here](https://admin.mobula.io/) Optional: * DexScreener (to quickly find token addresses) *** ## When to use Token Trader Positions Use this endpoint when you want to: * Identify the top wallets holding a token and their share of total supply * Analyze trader activity like buys, sells, and buy or sell volumes * Track realized and unrealized PnL per wallet for the token * Filter results by trader categories like sniper, insider, bundler, smartTrader, or dev * Pull positions for specific wallets using `walletAddresses` If you need top holders without PnL breakdown, use: [**Get Token Holders**](https://docs.mobula.io/rest-api-reference/endpoint/market-token-holders) If you need recent token swap trades, use: [**Get Token Trades**](https://docs.mobula.io/rest-api-reference/endpoint/token-trades) *** ## Walkthrough to Get Token Trader Positions ### 1. Prepare your query The `token-trader-positions` endpoint requires: | Parameter | Description | | - | - | | `blockchain` | Blockchain identifier (example: `ethereum`, `evm:1`, `solana`) | | `address` | Token contract address or mint address | Optional parameters you can use: * `label`: Filter by trader type (`sniper`, `insider`, `bundler`, `proTrader`, `smartTrader`, `freshTrader`, `dev`) * `walletAddresses`: One or multiple wallet addresses (comma-separated or array) * `limit`: Maximum number of positions returned (default: `100`, max: `1000`) ### 2. Find a token address to test To retrieve real token data: * Open DexScreener * Pick any token * Copy the token contract address from the token page This address is used as the `address` parameter. ### 3. Fill the API form Once your token address is ready: * Enter the blockchain (example: `solana`) * Paste the token contract into the `address` field * (Optional) add trader filters like `label=smartTrader` * Click **Send** to retrieve the top trader positions *** ## Reviewing the response Each item represents a trader position for the token: * `chainId`: Chain identifier for the position (example: `solana:solana`, `evm:1`) * `walletAddress`: Trader wallet address * `tokenAddress`: Token contract or mint address * `tokenAmount` / `tokenAmountRaw`: Token balance in human-readable form and raw integer units * `tokenAmountUSD`: Estimated USD value of the wallet’s token balance * `percentageOfTotalSupply`: Share of the token’s total supply held by this wallet * `realizedPnlUSD`: Realized PnL from sold tokens * `unrealizedPnlUSD`: Unrealized PnL based on current value minus cost basis * `totalPnlUSD`: Total PnL combining realized and unrealized * `buys` / `sells`: Total trade counts for the wallet * `volumeBuyToken` / `volumeSellToken`: Token-denominated buy and sell volumes * `volumeBuyUSD` / `volumeSellUSD`: USD-denominated buy and sell volumes * `avgBuyPriceUSD` / `avgSellPriceUSD`: Average buy and sell prices in USD * `walletFundAt`: Timestamp when the wallet was first funded * `firstTradeAt` / `lastTradeAt`: Timestamps for first and most recent recorded trades * `lastActivityAt`: Timestamp of the most recent activity * `labels`: Array of trader labels associated with the wallet *** ## Try It Live with Mobula Token Trader Positions Demo (UI) [Demo UI Homepage](https://mobula-demo-endpoint-production.up.railway.app/) [Token Trader Positions Demo UI](https://mobula-demo-endpoint-production.up.railway.app/token-trader-positions) [Docs](https://docs.mobula.io/rest-api-reference/endpoint/token-trader-positions) *** ## Summary The Get Token Trader Positions endpoint helps you: * Retrieve top trader positions for a token on a specific blockchain * Analyze holdings, trade counts, volumes, and realized/unrealized PnL per wallet * Filter by trader labels or specific wallets * Visualize results instantly in the demo UI *** ## Try Mobula for Free Try our free API today and start building in minutes. Get your free API key: [Here](https://admin.mobula.io/) # How to Track Wallet Activity Across Ethereum, Solana, BNB, Base & More Source: https://docs.mobula.io/guides/how-to-track-wallet-activity-with-mobula-api Easily fetch detailed wallet activity, including transfers, swaps, and vault operations, using the Mobula API. Easily fetch detailed wallet activity, including transfers, swaps, and vault operations, using the Mobula API. The [**Get Wallet Activity**](https://docs.mobula.io/rest-api-reference/endpoint/wallet-activity) endpoint returns a unified activity feed for a wallet, with **smart swap detection** that automatically groups related transfers into swap transactions. It is ideal for developers building **wallet explorers, transaction feeds, portfolio dashboards, trading analytics**, and **on-chain monitoring tools**. ****** ## What this endpoint does With this API, you can: * Fetch a unified wallet activity feed across supported blockchains like [Solana](https://docs.mobula.io/blockchains/solana), [Ethereum](https://docs.mobula.io/blockchains/ethereum) and more * Retrieve **transfers**, **swaps**, and **vault operations** in one response * Automatically group IN/OUT transfers into **swap objects** when they happen in the same transaction * Filter spam tokens and optionally include unlisted/unverified assets * Exclude specific addresses using a blacklist * Paginate results using page, offset, or cursor-based navigation Unlike raw transaction lists, this endpoint returns activity in a cleaner format optimized for UI feeds. *** ## What you’ll need * Basic knowledge of REST APIs * A wallet address * A Mobula API key Note: All Mobula endpoints require an API key.\ Get a free API key: [Here](https://admin.mobula.io/) Optional: * A block explorer or DexScreener to find example wallets to test *** ## When to use Get Wallet Activity Use this endpoint when you want to: * Build a wallet activity timeline (transfers + swaps + vault actions) * Detect swaps without manually reconstructing transfers * Monitor wallets across chains for analytics, alerts, or dashboards * Filter spam tokens and unlisted assets in wallet feeds * Paginate through large activity histories efficiently If you need token balances and PnL, use [wallet/positions](https://docs.mobula.io/rest-api-reference/endpoint/wallet-positions) or [wallet/position](https://docs.mobula.io/rest-api-reference/endpoint/wallet-position). *** ## Walkthrough to Get Wallet Activity for a Wallet ### 1. Prepare your query The `wallet`/`activity` endpoint requires one parameter to work: | Parameter | Description | | - | - | | `wallet` | Wallet address to analyze | Optional parameters you can use to control output: * `limit` (max 1000): number of items returned * `page` / `offset`: pagination controls (offset is an alternative to page) * `order`: `asc` or `desc` by timestamp * `blacklist`: exclude activity involving specific addresses * `filterSpam`: filter out spam tokens * `unlistedAssets`: include unlisted/unverified tokens * `cursor_hash` + `cursor_direction`: cursor pagination for precise navigation * `pagination`: include pagination metadata * `backfillTransfers`: backfill feature available * `withTokens`: include token list in response * `backfillStatus`: response status for backfill processing ### 2. Find a wallet address to test To get a real wallet example: 1. Open a block explorer (Etherscan, Solscan, etc.) or DexScreener 2. Pick an active wallet (top traders, top holders, or known accounts) 3. Copy the wallet address Use that address as the `wallet` parameter. ### 3. Fill the API form Once the wallet address is filled (and optional filters are set), click **Send** to retrieve the wallet’s activity data. *** ## Reviewing the wallet activity response The response returns a unified feed: * `data[]`: the activity items * `pagination`: page/offset info when enabled * `backfillStatus`: `processed`, `processing`, or `pending` * `tokens[]` (optional): enriched token objects when `withTokens=true` *** ## Activity types you’ll see ### Transfer (model: "transfer") * ERC20 token transfers (IN/OUT) * Native transfers (IN/OUT) * Vault operations (DEPOSIT/WITHDRAW) ### Swap (model: "swap") * Automatically detected from combined transfers * Includes token pair, base/quote identification, pricing, and amount in USD *** ## Try It Live with Mobula Wallet Activity Demo (UI) You can also test this endpoint using our demo UI: [Demo UI Homepage](https://mobula-demo-endpoint-production.up.railway.app/) [Wallet Activity Demo UI](https://mobula-demo-endpoint-production.up.railway.app/wallet-activity) [Docs](https://docs.mobula.io/rest-api-reference/endpoint/wallet-activity) *** ## Summary The [**Get Wallet Activity**](https://docs.mobula.io/rest-api-reference/endpoint/wallet-activity) endpoint provides a clean, unified wallet activity feed, including: * Transfers, swaps, and vault operations * Smart swap detection with grouped transfers * Spam filtering and optional unlisted asset support * Flexible pagination options (page, offset, cursor navigation) If you’re building wallet explorers, timelines, dashboards, or monitoring tools, this endpoint is a strong foundation for real-time and historical activity tracking. *** ## Try Mobula for Free Try our free API today and start building in minutes.\ Get your free API key: [Here](https://admin.mobula.io/) # How to Track Wallet Balance and Wallet Position with PnL Across Ethereum, Solana, BNB, Base & More Source: https://docs.mobula.io/guides/how-to-track-wallet-balance-and-wallet-position-with-pnl Easily retrieve wallet data, token balances, and profit & loss (PnL) for any blockchain wallet using the Mobula API. This endpoint allows you to **get wallet balance for a specific token**, analyze trading activity, and track realized and unrealized PnL across supported blockchains. The [**Get Wallet Position**](https://docs.mobula.io/rest-api-reference/endpoint/wallet-position) endpoint is ideal for developers building wallet analytics, trader dashboards, or on-chain performance tools. ****** ## What this endpoint does With this API, you can: * Get a **crypto wallet balance** for a specific token * Retrieve detailed **wallet position data** * Analyze **buy and sell history** for a wallet * Calculate **realized and unrealized PnL** * Access enriched **token market data** Unlike portfolio-level endpoints, this endpoint focuses on **one wallet + one token**, making it perfect for **deep wallet analysis**. *** ## What you’ll need * Basic knowledge of REST APIs * A **wallet address** (EVM or Solana) * A **token (asset) address** * The **blockchain** where the token exists (Ethereum, Solana, Base, etc.) Optional: * DexScreener (to discover tokens and active wallets) *** ## When to use Get Wallet Position Use this endpoint when you want to: * Get wallet balance for a **specific token** * Analyze **wallet trading performance** * Track **wallet PnL** over time * Build **wallet analytics** or trader profiling tools * Display **token-level wallet data** in dashboards *** ## Walkthrough — Get Wallet Balance for a Token ### 1. Prepare your query The wallet/position endpoint requires three parameters: | Parameter | Description | | - | - | | `asset` | Token contract address | | `blockchain` | Blockchain name or ID | | `wallet` | Wallet address to analyze | ### 2. Find a token (asset address) To get a valid token address: 1. Open DexScreener 2. Search for the token you want to analyze 3. Copy the token contract address shown on the token page This address is used as the `asset` parameter. ### 3. Identify the blockchain Still on DexScreener: * Check which blockchain the token is deployed on (e.g. [Solana](https://docs.mobula.io/blockchains/solana), [Ethereum](https://docs.mobula.io/blockchains/ethereum), [Base](https://docs.mobula.io/blockchains/base)) This value is used as the `blockchain` parameter. ### 4. Find a wallet address To retrieve real wallet data: 1. Open the Top Traders section on DexScreener 2. Select an active wallet 3. Open it in the blockchain explorer 4. Copy the wallet address This address is used as the `wallet` parameter. *** ## Execute the API Call ### Using cURL ```bash theme={null} curl -X GET \ "https://demo-api.mobula.io/api/2/wallet/position?wallet=YOUR_WALLET&asset=TOKEN_ADDRESS&blockchain=solana" ``` This request fetches **wallet balance, wallet position, and wallet PnL** for the selected token. ### Using the Mobula SDK ```ts theme={null} import { Mobula } from '@mobula/sdk'; const mobula = new Mobula({ apiKey: 'your-key' }); const position = await mobula.fetchWalletPosition({ wallet: 'YOUR_WALLET', blockchain: 'Solana', asset: 'TOKEN_ADDRESS', }); ``` *** ## Review the wallet data response The response returns **detailed wallet data**, including: * Token metadata and pricing * Token balance (raw and formatted) * Wallet value in USD * Buy and sell counts * Trading volumes * Average buy and sell prices * Realized PnL * Unrealized PnL * Total wallet profit and loss * First and last interaction timestamps This allows you to fully analyze **wallet balance, trading behavior, and profitability** for a specific asset. *** ## Try It Live with Mobula Wallet Position Demo (UI) You can also test the Get Wallet Position endpoint using our open-source Wallet Position UI demo. This lightweight application uses Mobula cURL requests under the hood to fetch wallet balance, wallet data, and PnL for a specific token and blockchain, allowing you to validate parameters before integrating the API into your own application. [Try it Here](https://mobula-demo-endpoint-production.up.railway.app/wallet-position) *** ## Summary The [**Get Wallet Position**](https://docs.mobula.io/rest-api-reference/endpoint/wallet-position) endpoint lets you go beyond basic wallet balances by providing **token-level wallet data, trading history, and PnL**. If you’re building tools that require: * Accurate **wallet balance tracking** * Token-specific **wallet analytics** * Advanced **on-chain wallet insights** This endpoint is the right choice. # How to Track Wallet Balance and Wallet Positions with PnL Across Ethereum, Solana, Base & More Source: https://docs.mobula.io/guides/how-to-track-wallet-balance-and-wallet-positions-with-pnl Easily retrieve a wallet’s full token portfolio, enriched token metrics, and profit & loss (PnL) data using the Mobula API. The [**Get Wallet Positions**](https://docs.mobula.io/rest-api-reference/endpoint/wallet-positions) **with PnL** endpoint returns all enriched token positions for a wallet on a specific blockchain, including token metadata, liquidity, trade stats, and wallet-level PnL per token. It is ideal for developers building **wallet analytics, portfolio dashboards, trader tooling,** and **on-chain performance apps**. ****** ## What this endpoint does With this API, you can: * Retrieve **all token positions** in a wallet on a specific blockchain * Get **wallet balances and USD values** per token * Access **enriched token metrics** like liquidity, volume, trades, and holders * Track **realized, unrealized, and total PnL** per token * Analyze wallet trading stats per token (buys, sells, volume, average prices) Unlike token-specific endpoints, this one gives you a **portfolio-wide view** of a wallet’s tokens (for one chain per request). *** ## What you’ll need * Basic knowledge of REST APIs * A wallet address * A Mobula API key Note: All Mobula endpoints require an API key.\ Get a free API key: [Here](https://admin.mobula.io/) Optional: * DexScreener (to find active wallets to test) *** ## When to use Get Wallet Positions with PnL Use this endpoint when you want to: * Build a wallet portfolio view (token list, balances, USD value) * Track token-level wallet profitability with PnL * Analyze wallet trading behavior across all holdings * Power dashboards, wallet explorers, or trader profiling tools If you only want one token position for a wallet, use [**wallet/position**](https://docs.mobula.io/rest-api-reference/endpoint/wallet-position).\ If you want all token positions for a wallet, use [**wallet/positions**](https://docs.mobula.io/rest-api-reference/endpoint/wallet-positions). *** ## Walkthrough to Get Wallet Positions for a Wallet ### 1. Prepare your query The `wallet`/`positions` endpoint requires two parameters: | Parameter | Description | | - | - | | `wallet` | Wallet address to analyze | | `blockchain` | Blockchain name or ID | ### 2. Find a wallet address to test To get a real wallet example: 1. Open DexScreener 2. Search for any token on the chain you want ([Solana](https://docs.mobula.io/blockchains/solana) or [Ethereum](https://docs.mobula.io/blockchains/ethereum)) 3. Open the **Top Traders** or **Holders** section 4. Click a wallet and copy the wallet address You will use this address as the `wallet` parameter. ### 3. Identify the blockchain On DexScreener, check the chain for the token you used to find wallets. This value is used as the `blockchain` parameter. ### 4. Fill the API form Once the wallet address is filled (and optional filters are set), click **Send** to retrieve the wallet’s positions data. *** ## Reviewing the wallet positions response ### What you get per token position * **Token metadata**: name, symbol, decimals, logo, contract address * **Token market metrics**: price, liquidity, volume, trades, holders, market cap * **Security and socials**: buy/sell tax, blacklist flags, top holders, and social links * **Wallet position data**: balance, rawBalance, USD value * **Trading stats**: buys, sells, buy/sell volumes, average buy/sell prices * **PnL breakdown**: realized, unrealized, total PnL * **Time bounds**: first and last interaction timestamps This makes it easy to build a **wallet portfolio table** with profitability insights. *** ## Try It Live with Mobula Wallet Positions Demo (UI) You can also test this endpoint using our demo UI: [Demo UI Homepage](https://mobula-demo-endpoint-production.up.railway.app/) [Wallet Positions Demo UI](https://mobula-demo-endpoint-production.up.railway.app/wallet-positions) [Docs](https://docs.mobula.io/rest-api-reference/endpoint/wallet-positions) *** ## Summary The [**Get Wallet Positions**](https://docs.mobula.io/rest-api-reference/endpoint/wallet-positions) **with PnL** endpoint provides a full portfolio view of a wallet on a specific chain, including: * Token balances and USD value * Enriched token metrics (liquidity, trades, holders, security) * Trading stats per token * Realized and unrealized PnL per token If you’re building wallet analytics that require **token-level profitability** and **enriched portfolio data**, this endpoint is the right choice. *** ## Try Mobula for Free Try our free API today and start building in minutes.\ Get your free API key: [Here](https://admin.mobula.io/) *** # How to Track Wallet DeFi Positions Across Solana, Ethereum, BNB, Base & More Source: https://docs.mobula.io/guides/how-to-track-wallet-defi-positions Easily retrieve a wallet’s DeFi positions across multiple protocols using the Mobula API. The [**Get Wallet DeFi Positions**](https://docs.mobula.io/rest-api-reference/endpoint/wallet-defi-positions) endpoint returns a unified view of DeFi positions for a wallet, including **lending, LP positions, liquid staking, native staking,** and **perps** across supported chains and protocols. This is ideal for developers building **DeFi portfolio dashboards**, **wallet analytics**, **yield tracking**, and **on-chain risk monitoring tools**. ****** ## What this endpoint does With this API, you can: * Fetch DeFi positions for a wallet across multiple supported protocols * Get a portfolio-level overview: total value, total deposited, total borrowed, and rewards (USD) * Group positions by protocol (ex: Orca, Raydium, Kamino, Drift, Aave V3, Lido, EigenLayer) * Retrieve position-level details, including: * underlying tokens and balances * position value in USD * rewards (fees, incentives, staking rewards) * category-specific metadata (LP range, staking APY, lending health factor, perps leverage) Unlike basic wallet token balance endpoints, this endpoint focuses specifically on **DeFi protocol positions**. *** ## What you’ll need * Basic knowledge of REST APIs * A wallet address * A blockchain value * A Mobula API key Note: All Mobula endpoints require an API key.\ Get a free API key: [Here](https://admin.mobula.io/) Optional: * Solscan or a block explorer to find wallets that are active in DeFi protocols *** ## When to use Get Wallet DeFi Positions Use this endpoint when you want to: * Build a DeFi portfolio view (positions grouped by protocol) * Track wallet exposure across lending, LPs, staking, restaking, and perps * Show protocol-level totals and position breakdowns in a dashboard * Monitor risk signals and leverage details (especially for lending and perps) * Power yield tracking or DeFi analytics tooling If you need wallet token balances and PnL per token, use **[wallet/positions](https://docs.mobula.io/rest-api-reference/endpoint/wallet-positions)**.\ If you need swaps and transfers activity, use **[wallet/activity](https://docs.mobula.io/rest-api-reference/endpoint/wallet-activity)**. *** ## Walkthrough to Get Wallet DeFi Positions for a Wallet ### 1. Prepare your query The `wallet`/`defi-positions` endpoint requires two parameters: | Parameter | Description | | - | - | | `wallet` | Wallet address (EVM 0x… or Solana base58) | | `blockchains` | Blockchain name or ID (example: `solana`, `ethereum`) | ### 2. Find a wallet address to test (Solana example) To retrieve real wallet data: 1. Open Solscan 2. Search for a supported DeFi protocol (example: Kamino) 3. Open a wallet that interacts with that protocol 4. Copy the wallet address This address is used as the `wallet` parameter. ### 3. Fill the API form * Paste the wallet address into `wallet` * Set `blockchains` to the chain you want (example: [solana](https://docs.mobula.io/blockchains/solana)) * Click **Send** The API will return the wallet’s DeFi positions across supported protocols on that chain. *** ## Reviewing the wallet DeFi positions response The response is structured for dashboards: ### Portfolio * Total value in USD * Total deposited and borrowed * Total rewards in USD ### Protocols Each protocol includes: * protocol metadata (name, category, logo, URL) * total value per protocol * positions list ### Positions Each position includes: * position name/type (stake, lending, liquidity, perp, etc.) * position USD value * underlying tokens (amounts and USD values) * optional rewards * category-specific metadata This makes it easy to build a DeFi portfolio UI with protocol grouping. *** ## Try It Live with Mobula Wallet DeFi Positions Demo (UI) You can also test this endpoint using our demo UI: [Demo UI Homepage](https://mobula-demo-endpoint-production.up.railway.app/) [Wallet DeFi Positions Demo UI](https://mobula-demo-endpoint-production.up.railway.app/wallet-defi-positions) [Docs](https://docs.mobula.io/rest-api-reference/endpoint/wallet-defi-positions) *** ## Summary The [Get Wallet DeFi Positions](https://docs.mobula.io/rest-api-reference/endpoint/wallet-defi-positions) endpoint provides a DeFi-native portfolio view, including: * Protocol-level grouping of positions * Lending, LP, staking, restaking, and perps coverage (depending on chain) * USD totals for wallet value, deposits, borrows, and rewards * Position-level breakdown with tokens and DeFi metadata If you’re building DeFi dashboards, yield trackers, or wallet analytics, this endpoint gives you a clean DeFi portfolio layer without manual protocol integrations. *** ## Try Mobula for Free Try our free API today and start building in minutes.\ Get your free API key: [Here](https://admin.mobula.io/) # How to Track Wallet Historical Net Worth Across Ethereum, Solana, BNB, Base & More Source: https://docs.mobula.io/guides/how-to-track-wallet-historical-net-worth Easily retrieve historical wallet net worth over time across chains using the Mobula API. The [**Get Historical Net Worth**](https://docs.mobula.io/rest-api-reference/endpoint/wallet-history) endpoint returns historical **net worth (USD)** for one wallet or multiple wallets combined, with flexible filters for time range, chains, liquidity thresholds, spam filtering, and aggregation period. It is ideal for developers building **portfolio history charts**, **wallet analytics dashboards**, **performance tracking**, and **multi-wallet reporting tools**. ****** ## What this endpoint does With this API, you can: * Retrieve historical **wallet net worth** over a specified time range * Query **one wallet** or **multiple wallets aggregated** into a single history * Filter results by **blockchains** (or fetch across many chains) * Set time windows using `from` and `to` (Unix ms timestamps) * Choose the chart granularity using `period` (5min → 7d) * Filter low-liquidity assets using `minliq` * Optionally include unlisted assets, filter spam, and fetch untracked history * Trigger transfer backfilling and read `backfill_status` in the response Unlike portfolio snapshot endpoints, this one is designed for **time-series net worth history**. *** ## What you’ll need * Basic knowledge of REST APIs * A wallet address (or multiple wallet addresses) * A Mobula API key Note: All Mobula endpoints require an API key.\ Get a free API key: [Here](https://admin.mobula.io/) Optional: * DexScreener or a block explorer to find example wallets to test *** ## When to use Get Historical Net Worth Use this endpoint when you want to: * Build a **wallet net worth chart** over time * Track portfolio performance historically for a wallet * Combine multiple wallets into a single “group net worth” timeline * Filter out spam tokens or low-liquidity assets from historical calculations * Generate performance history for dashboards, reports, or user profiles If you need wallet activity events (transfers/swaps), use [**wallet/activity**](https://docs.mobula.io/rest-api-reference/endpoint/wallet-activity).\ If you need current token positions with PnL, use [**wallet/positions**](https://docs.mobula.io/rest-api-reference/endpoint/wallet-positions). *** ## Walkthrough — Get Wallet Historical Net Worth ### 1. Prepare your query Either `wallet` or `wallets` must be provided. | Parameter | Description | | - | - | | `wallet` | Single wallet address to query | | `wallets` | Comma-separated wallet addresses to query in aggregate | Optional parameters you can use to control output: * `blockchains`: comma-separated chains (e.g.,[`solana`](https://docs.mobula.io/blockchains/solana),[`ethereum`](https://docs.mobula.io/blockchains/ethereum),[`base`](https://docs.mobula.io/blockchains/base)) * `from`: start time (Unix ms timestamp) * `to`: end time (Unix ms timestamp) * `period`: aggregation granularity (`5min`, `15min`, `1h`, `6h`, `1d`, `7d`) * `unlistedAssets`: `"true"` to include unlisted assets * `accuracy`: set to `"maximum"` to analyze all assets (otherwise small assets may be skipped) * `minliq`: minimum liquidity threshold in USD (assets below excluded) * `filterSpam`: `"true"` to remove spam/low-quality assets * `fetchUntrackedHistory`: `"true"` to fetch historical prices for untracked assets * `fetchAllChains`: `"true"` to query all supported chains * `shouldFetchPriceChange`: set to `"24h"` to include 24-hour price change data * `backfillTransfers`: `"true"` to trigger transfer backfilling (returns backfill\_status) * `testnet`: `"true"` to include testnet data Note: Boolean parameters are passed as strings: `"true"` or `"false"`. ### 2. Choose your time range and granularity This endpoint uses Unix timestamps in milliseconds. * Use `from` and `to` to define the window * Use `period` to define how detailed the baseline history grid is Examples: * `period=1h` for hourly points * `period=1d` for daily net worth * `period=5min` for high-frequency charts (when needed)`period` sets the **minimum** spacing of the baseline grid, not a hard cap on the number of points. The response also includes one point at the exact timestamp of every balance-changing transfer, so the total is roughly `(to − from) / period + number of transfers`. A 30-day query with `period=1d` therefore returns \~30 grid points **plus** one point per transfer, which can exceed 100 points for an active wallet. To get exactly one point per interval, bucket `balance_history` client-side and keep the last value per bucket. ### 3. Decide if you want single-wallet or multi-wallet history * Use `wallet=` for one wallet * Use `wallets=` for multiple wallets combined (comma-separated) This is useful for: * tracking a user’s wallet + cold wallet together * combining treasury wallets * aggregating multiple addresses into one net worth chart ### 4. Fill the API form Once the wallet address is filled (and optional filters are set), click **Send** to retrieve the wallet’s historical data. *** ## Reviewing the wallet historical net worth response The response returns a historical net worth object inside data: * `wallets`: list of queried wallets (or aggregated wallet list) * `balance_usd`: current balance in USD (summary) * `balance_history`: historical net worth time series * `backfill_status`: status for transfer backfill (when enabled) *** ## Try It Live with Mobula Wallet History Demo (UI) You can also test this endpoint using our demo UI: [Demo UI Homepage](https://mobula-demo-endpoint-production.up.railway.app/) [Wallet History Demo UI](https://mobula-demo-endpoint-production.up.railway.app/wallet-history) [Docs](https://docs.mobula.io/rest-api-reference/endpoint/wallet-history) *** ## Summary The [Get Historical Net Worth](https://docs.mobula.io/rest-api-reference/endpoint/wallet-history) endpoint lets you build accurate wallet net worth history charts, with support for: * Single wallet or multi-wallet aggregation * Flexible time windows (`from`, `to`) * Multiple chains via `blockchains` * Chart granularity using `period` * Cleaner results via `minliq` and `filterSpam` * Optional backfill status reporting If you’re building portfolio performance analytics or historical dashboards, this endpoint is the right choice. *** ## Try Mobula for Free Try our free API today and start building in minutes.\ Get your free API key: [Here](https://admin.mobula.io/) # How to Track Wallet Labels Across Solana, Ethereum & More Source: https://docs.mobula.io/guides/how-to-track-wallet-labels Easily label wallets as pro traders, smart traders, fresh traders, snipers, insiders, bundlers, and more using the Mobula API. The [**Get Wallet Labels**](https://docs.mobula.io/rest-api-reference/endpoint/wallet-labels) endpoint returns wallet labels for one or more wallet addresses across blockchains like [Solana](https://docs.mobula.io/blockchains/solana), [Ethereum](https://docs.mobula.io/blockchains/ethereum) and more, and can optionally return labels in the context of a specific token. It is ideal for developers building **wallet scoring**, **trader discovery**, **copy-trading tools**, **alpha dashboards**, and **on-chain profiling systems**. ****** ## What this endpoint does With this API, you can: * Retrieve wallet labels for one or multiple wallets * Detect trading-style labels like **proTrader**, **smartTrader**, **freshTrader**, **sniper**, **insider**, **bundler**, and more * Optionally provide a **token address** to get labels in the context of that token * Use the output to power wallet profiling, filtering, and ranking in your product Unlike raw wallet stats, this endpoint gives you a high-level “wallet classification” that’s easier to use in UIs and scoring logic. *** ## What you’ll need * Basic knowledge of REST APIs * A wallet address * A Mobula API key Note: All Mobula endpoints require an API key.\ Get a free API key: [Here](https://admin.mobula.io/) Optional: * DexScreener + a block explorer to find active wallets and token contract addresses *** ## When to use Get Wallet Labels Use this endpoint when you want to: * Identify “smart money” style wallets and trading behavior * Label wallets for discovery (leaderboards, filtering, tagging systems) * Build trader profiles (pro trader vs fresh trader vs sniper) * Add wallet classification to dashboards or wallet analytics products * Run wallet screening before copying trades or tracking addresses If you want **wallet swaps only**, use [wallet/trades](https://docs.mobula.io/rest-api-reference/endpoint/wallet-trades).\ If you want **wallet activity feeds**, use [wallet/activity](https://docs.mobula.io/rest-api-reference/endpoint/wallet-activity). *** ## Walkthrough — Get Wallet Labels for a Wallet ### 1. Prepare your query The `wallet/labels` endpoint requires one parameter to work: | Parameter | Description | | - | - | | `walletAddresses` | Required. A string or array of wallet addresses | | `tokenAddress` | Optional. If set, returns labels in the context of that token | ### 2. Find a wallet address to test To retrieve real wallet data: 1. Open DexScreener 2. Open any token page 3. Go to the **Transactions** (or traders activity) section 4. Pick a recent transaction and copy the **signer wallet address** This address is used in `walletAddresses`. ### 3. (Optional) Find a token address to label by token context If you want token-specific label context: * On the same DexScreener token page, copy the **token contract address** This address is used as `tokenAddress`. ### 4. Fill the API form In the Mobula docs “Try it” form: * Paste your wallet(s) into `walletAddresses` * (Optional) paste the token contract into `tokenAddress` * Click **Send** *** ## Reviewing the wallet labels response The response returns labels for the wallet(s) you submitted. What you should expect: * A list of label outputs per wallet * Labels can include classifications like: **proTrader**, **smartTrader**, **freshTrader**, **sniper**, **insider**, **bundler**, etc. * If you provided `tokenAddress`, labels are returned with token context * **`fundingInfo`** — the wallet's initial funding source, including the funder address, chain, amount, currency, and funder identity if known. This removes the need to call `/wallet/positions` just to get funding data. *** ## Try It Live with Mobula Wallet Labels Demo (UI) You can also test this endpoint using our demo UI: [Demo UI Homepage](https://mobula-demo-endpoint-production.up.railway.app/) [Wallet Labels Demo UI](https://mobula-demo-endpoint-production.up.railway.app/wallet-labels) [Docs](https://docs.mobula.io/rest-api-reference/endpoint/wallet-labels) *** ## Summary The [**Get Wallet Labels**](https://docs.mobula.io/rest-api-reference/endpoint/wallet-labels) endpoint helps you classify wallets with trader-style labels, including: * Wallet labels like **proTrader**, **smartTrader**, **freshTrader**, **sniper**, **insider**, **bundler** * Optional token-context labeling with `tokenAddress` * Support for multiple wallet inputs via `walletAddresses` * **Funding info** (funder address, chain, amount, currency) included in the response — no extra API call needed If you’re building wallet discovery, trader scoring, or profiling tools, this endpoint is a clean way to enrich wallets with actionable labels. *** ## Try Mobula for Free Try our free API today and start building in minutes.\ Get your free API key: [Here](https://admin.mobula.io/) # How to Track Wallet NFT Holdings Across Ethereum, Solana, Base & More Source: https://docs.mobula.io/guides/how-to-track-wallet-nft-holdings-using-mobula-api Easily retrieve all NFTs owned by a wallet across supported blockchains using the Mobula API. The [**Get NFTs Holdings**](https://docs.mobula.io/rest-api-reference/endpoint/wallet-nfts) endpoint returns a wallet’s NFT inventory, including token metadata, ownership details, and optional pagination. It is ideal for developers building **NFT portfolio dashboards**, **wallet explorers**, **NFT gating tools**, and **on-chain identity or collector analytics**. ****** ## What this endpoint does With this API, you can: * Retrieve all NFTs owned by a wallet across supported blockchains like [Solana](https://docs.mobula.io/blockchains/solana), [Ethereum](https://docs.mobula.io/blockchains/ethereum) and more * Filter results by specific chains using `blockchains` * Paginate through large NFT inventories using `page` or `offset` * Control response size using `limit` * Optionally include pagination metadata using `pagination=true` Unlike collection-specific tools, this endpoint focuses on **wallet-level NFT ownership**. *** ## What you’ll need * Basic knowledge of REST APIs * A wallet address * A Mobula API key Note: All Mobula endpoints require an API key.\ Get a free API key: [Here](https://admin.mobula.io/) Optional: * NFTScan (to find wallets that hold NFTs) *** ## When to use Get NFTs Holdings Use this endpoint when you want to: * Display a wallet’s NFT holdings in an NFT portfolio page * Build NFT ownership lookups for wallet-based user profiles * Add NFT-based features to dashboards (collector insights, inventory, gating) * Paginate large NFT collections in a wallet efficiently * Filter by chain to speed up queries and reduce noise If you want historical wallet net worth, use [**wallet/history**](https://docs.mobula.io/rest-api-reference/endpoint/wallet-history). If you want wallet activity events (transfers/swaps), use [**wallet/activity**](https://docs.mobula.io/rest-api-reference/endpoint/wallet-activity). *** ## Walkthrough to Get NFTs Holdings for a Wallet ### 1. Prepare your query The `wallet`/`nfts` endpoint requires one parameter to work: | Parameter | Description | | - | - | | `wallet` | Wallet address to analyze | Optional parameters you can use to control output: * `blockchains`: comma-separated list of chains (defaults to all supported chains) * `limit`: maximum number of NFTs returned per response * `page`: page number for pagination * `offset`: number of records to skip (alternative to page) * `pagination`: set to `true` to include pagination metadata (default is false) Note: either `page` or `offset` can be used for pagination. ### 2. Find a wallet address to test To retrieve real wallet data: * Open NFTScan * Search for any NFT collection you want * Open the holders list for that collection * Select an active holder wallet * Copy the wallet address This address is used as the `wallet` parameter. ### 3. Configure pagination (optional) If the wallet holds many NFTs: * Use `limit` to control how many NFTs are returned per request * Use `page` or `offset` to move through the full NFT inventory * Set `pagination=true` to include pagination metadata in the response ### 4. Fill the API form Once the wallet address is filled (and optional filters are set), click **Send** to retrieve the wallet’s NFT holdings. *** ## Reviewing the wallet NFTs response The response returns: * `data[]`: the list of NFTs owned by the wallet * `pagination`: pagination metadata (only when enabled) * `NFT metadata` What you can build with this data: * A wallet NFT inventory list (collection name, token IDs, contract address) * Wallet-level NFT ownership views for dashboards * Paginated NFT galleries for wallets with large holdings *** ## Try It Live with Mobula Wallet NFTs Demo (UI) You can also test this endpoint using our demo UI: [Demo UI Homepage](https://mobula-demo-endpoint-production.up.railway.app/) [Wallet NFTs Demo UI](https://mobula-demo-endpoint-production.up.railway.app/wallet-nfts) [Docs](https://docs.mobula.io/rest-api-reference/endpoint/wallet-nfts) *** ## Summary The [**Get NFTs Holdings**](https://docs.mobula.io/rest-api-reference/endpoint/wallet-nfts) endpoint makes it easy to fetch wallet NFT ownership across chains, with support for: * Multi-chain NFT holdings via `blockchains` * Pagination with `limit`, `page`, and `offset` * Optional pagination metadata using `pagination=true` * A clean response format suitable for NFT dashboards and wallet explorers If you’re building NFT portfolio tools or wallet-based NFT experiences, this endpoint is the right choice. *** ## Try Mobula for Free Try our free API today and start building in minutes.\ Get your free API key: [Here](https://admin.mobula.io/) # How to Track Wallet Swap Trades Across Ethereum, Solana, BNB, Base & More Source: https://docs.mobula.io/guides/how-to-track-wallet-swap-trades-using-mobula-api Easily retrieve swap trades executed by a wallet using the Mobula API. The [**Get Wallet Trades**](https://docs.mobula.io/rest-api-reference/endpoint/wallet-trades) endpoint returns a clean list of swap trades for one wallet or multiple wallets across chains like [Solana](https://docs.mobula.io/blockchains/solana), [Ethereum](https://docs.mobula.io/blockchains/ethereum), [Base](https://docs.mobula.io/blockchains/base), and more, with time range filtering, ordering, and pagination. It is ideal for developers building trading history views, wallet analytics dashboards, copy trading tools, and on-chain trader profiling. ****** ## What this endpoint does With this API, you can: * Fetch swap trades for a **single wallet** or **multiple wallets combined** * Filter trades by a specific time window using `from` and `to` * Paginate results using `page` or `offset` * Control result size with `limit` * Sort trades using `order=asc` or `order=desc` * Get enriched trade context including: * pool and token addresses * buy/sell side * USD notional (best effort) * trade ratio and execution pricing (best effort) * enriched base token data (market and liquidity stats) * wallet labels and platform identifier when available Unlike wallet activity feeds, this endpoint is focused specifically on **swap trades**. *** ## What you’ll need * Basic knowledge of REST APIs * A wallet address (or multiple wallet addresses) * A Mobula API key Note: All Mobula endpoints require an API key.\ Get a free API key: [Here](https://admin.mobula.io/) Optional: * DexScreener (to find active wallets that are actively trading) *** ## When to use Get Wallet Trades Use this endpoint when you want to: * Build a wallet’s swap trade history (buy and sell activity) * Analyze trade frequency, trade sizes, and token rotation * Power trading analytics dashboards (volume, count, average sizing) * Support copy trading and trader profiling workflows * Pull wallet swap trades in a specific time range for research or alerts If you need transfers, vault actions, and swap detection in one feed, use [**wallet/activity**](https://docs.mobula.io/rest-api-reference/endpoint/wallet-activity).\ If you need wallet token balances and PnL, use [**wallet/positions**](https://docs.mobula.io/rest-api-reference/endpoint/wallet-positions). *** ## Walkthrough — Get Wallet Trades for a Wallet ### 1. Prepare your query You can provide either single or multiple wallets to analyse one or more wallets. | Parameter | Description | | - | - | | `wallet` | Single wallet address to query trades for | | `wallets` | Comma-separated list of wallet addresses to query trades for | Optional parameters you can use to control output: * `from`: start timestamp (Unix ms or ISO 8601) * `to`: end timestamp (Unix ms or ISO 8601) * `limit`: number of results per page * `page`: page number for pagination * `offset`: offset for pagination * `order`: `asc` or `desc` (default is `desc`) Tip: use `from` and `to` when you want trades for a specific period instead of the wallet’s full history. ### 2. Find a wallet address to test To retrieve real wallet data: 1. Open DexScreener 2. Search for any token 3. Open the **Top Traders** section 4. Select an active wallet 5. Open it in a block explorer 6. Copy the wallet address This address is used as the `wallet` parameter. ### 3. Set your time range (optional) If you want to restrict results: * Fill `from` and `to` with Unix ms timestamps or ISO 8601 dates This is useful for: * “last 24 hours” trade history * weekly performance checks * event-based analysis ### 4. Fill the API form Once the wallet field is filled (and optional time range / pagination is set), click **Send** to retrieve the wallet’s swap trades data. *** ## Reviewing the wallet trades response Each item in `data[]` represents a single swap trade involving the queried wallet. Key fields you will typically use: * Trade identity: `transaction_hash`, `date`, `chain_id`, `pool_address` * Pair details: `token0_address`, `token1_address`, `base`, `quote` * Direction: `side` is `buy` or `sell` relative to the `base` token * Sizing: `amount_base`, `amount_quote` (returned as absolute positive values) * USD value: `amount_usd` (best effort, can be 0 for illiquid tokens) * Execution context: `ratio`, `price_usd_token0`, `price_usd_token1` (best effort) * Enrichment: `base_token` includes token stats (price, liquidity, volume, market cap, and more) * Context: `labels` (if available), `platform` (if available) Note: amounts are returned as absolute values for easier consumption. Use `side` to interpret direction. *** ## Try It Live with Mobula Wallet Trades Demo (UI) You can also test this endpoint using our demo UI: [Demo UI Homepage](https://mobula-demo-endpoint-production.up.railway.app/) [Wallet Trades Demo UI](https://mobula-demo-endpoint-production.up.railway.app/wallet-trades) [Docs](https://docs.mobula.io/rest-api-reference/endpoint/wallet-trades) *** ## Summary The [**Get Wallet Trades**](https://docs.mobula.io/rest-api-reference/endpoint/wallet-trades) endpoint helps you build swap-focused trading history and analytics with: * Single wallet or multi-wallet support * Time range filtering (`from`, `to`) * Pagination controls (`page`, `offset`, `limit`) * Buy/sell direction via `side` * Enriched token context via `base_token` * Optional wallet labels and platform tags If you’re building trading dashboards, trader profiling, or copy trading tooling, this endpoint is a strong foundation. *** ## Try Mobula for Free Try our free API today and start building in minutes.\ Get your free API key: [Here](https://admin.mobula.io/) # How to Track Wallet Trading Performance with PnL, Win Rate & Market Cap Distributions Source: https://docs.mobula.io/guides/how-to-track-wallet-trading-performance-with-pnl-winrate Easily analyze a wallet’s trading performance across Ethereum, Solana, Base & more using the Mobula API. The [**Get Wallet Trading Analysis**](https://docs.mobula.io/rest-api-reference/endpoint/wallet-analysis) endpoint returns comprehensive wallet trading analytics across chains like [Solana](https://docs.mobula.io/blockchains/solana), [Ethereum](https://docs.mobula.io/blockchains/ethereum), and more, including **PnL**, **win rate distributions**, **market cap distributions**, and detailed trading statistics over a selected time period. It is ideal for developers building **smart money detection**, **wallet scoring**, **trader dashboards**, and **on-chain due diligence tools**. ****** ## What this endpoint does With this API, you can: * Analyze wallet trading performance over a selected period (1d, 7d, 30d, 90d) * Retrieve total performance metrics including realized and unrealized PnL * Get a **win rate distribution** across profit/loss ranges * Get a **market cap distribution** of traded tokens * Review detailed trading statistics (buys, sells, volumes, win rate, holding behavior) * Retrieve the wallet’s most profitable token (if available) * Retrieve labels associated with the wallet (Smart Money, Early Adopter, etc.) Unlike raw activity feeds, this endpoint is optimized for **performance analytics and wallet scoring**. *** ## What you’ll need * Basic knowledge of REST APIs * A wallet address * A Mobula API key Note: All Mobula endpoints require an API key.\ Get a free API key: [Here](https://admin.mobula.io/) Optional: * DexScreener (to find active wallets to test) *** ## When to use Get Wallet Trading Analysis Use this endpoint when you want to: * Track wallet PnL and trading performance over time * Score wallets based on win rate and trading behavior * Identify smart wallets using distribution metrics and labels * Analyze risk profile through market cap exposure * Research a wallet before following or copying trades If you need wallet activity events like swaps and transfers, use [**wallet/activity**](https://docs.mobula.io/rest-api-reference/endpoint/wallet-activity).\ If you need all token positions in a wallet, use [**wallet/positions**](https://docs.mobula.io/rest-api-reference/endpoint/wallet-defi-positions). *** ## Walkthrough to Get Wallet Trading Analysis for a Wallet ### 1. Prepare your query The `wallet`/`analysis` endpoint requires one parameter to work: | Parameter | Description | | - | - | | `wallet` | Wallet address to analyze | Optional parameters you can use to control output: * `blockchain`: analyze a specific blockchain (if not provided, analysis runs across all supported chains) * `period`: analysis period (`1d`, `7d`, `30d`, `90d`), default is `7d` ### 2. Find a wallet address to test To retrieve real wallet data: 1. Open DexScreener 2. Search for any token you want 3. Open the **Top Traders** section 4. Select an active wallet 5. Open it in the blockchain explorer 6. Copy the wallet address This address is used as the `wallet` parameter. ### 3. Select your period (optional) If you want a different window than the default: * Use `period=1d` for short-term performance * Use `period=30d` or `period=90d` for longer-term analysis ### 4. Fill the API form Once the wallet address is filled (and optional filters are set), click **Send** to retrieve the wallet trading analysis data. *** ## Reviewing the wallet trading analysis response The response returns a single analytics object inside `data`, including: ### Win Rate Distribution This summarizes how many trades fall into profit/loss ranges: * `>500%` * `200%-500%` * `50%-200%` * `0%-50%` * `-50%-0%` * `<-50%` This is useful for quickly understanding if the wallet tends to make small consistent wins, large winners, or frequent losses. ### Market Cap Distribution This shows what size of tokens the wallet trades most: * `>1000M` (over \$1B) * `>100M` ($100M to $1B) * `10M-100M` * `1M-10M` * `100k-1M` * `<100k` This is useful for profiling wallet risk and strategy (large caps vs micro caps). ### Trading Statistics (`stat` object) Key trading metrics you can use for scoring and analytics, including: * `totalValue` (current portfolio value in USD) * `periodTotalPnlUSD` (realized + unrealized PnL for the period) * `periodRealizedPnlUSD` and `periodRealizedRate` * Buy/sell activity: `periodBuys`, `periodSells`, `periodVolumeBuy`, `periodVolumeSell` * Token coverage: `periodTradingTokens`, `periodBuyTokens`, `periodSellTokens` * Holding behavior: `holdingTokensCount`, `holdingDuration` * Win performance: `winRealizedPnl`, `winRealizedPnlRate` * `winToken` (most profitable token, if available) * `fundingInfo` (initial wallet funding context, when available) * `nativeBalance` (native token balance details) ### Period Timeframes A time series of realized PnL points: * `date` * `realized` This is useful for charts showing performance over time within the selected period. ### Labels An array of labels tied to the wallet (examples: Smart Money, Early Adopter, etc.). This can be used directly in UI badges or wallet ranking systems. *** ## Try It Live with Mobula Wallet Analysis Demo (UI) You can also test this endpoint using our demo UI: [Demo UI Homepage](https://mobula-demo-endpoint-production.up.railway.app/) [Wallet Analysis Demo UI](https://mobula-demo-endpoint-production.up.railway.app/wallet-analysis) [Docs](https://docs.mobula.io/rest-api-reference/endpoint/wallet-analysis) *** ## Summary The [Get Wallet Trading Analysis](https://docs.mobula.io/rest-api-reference/endpoint/wallet-analysis) endpoint provides advanced wallet performance analytics, including: * PnL tracking over a selected period * Win rate distribution across profit/loss ranges * Market cap distribution of traded tokens * Detailed trading statistics for wallet scoring * Timeframe-based realized PnL series * Wallet labels for classification (when available) If you’re building smart money detection, trader dashboards, or wallet scoring systems, this endpoint is the right choice. *** ## Try Mobula for Free Try our free API today and start building in minutes.\ Get your free API key: [Here](https://admin.mobula.io/) # How to Use Stellar Data Source: https://docs.mobula.io/guides/how-to-use-stellar-data A developer tutorial for accessing Stellar data with the Mobula API — historical transaction lookups, token liquidity insights, contract interaction data, and real-time WebSocket streams — with live requests, responses, use cases, and guidance on what to use for what. This tutorial shows how to access Stellar data through the Mobula API — REST endpoints, real-time WebSocket streams, and the TypeScript SDK — across four common needs: **historical transaction lookups**, **token liquidity insights**, **contract interaction data**, and **live market streams**. Every example is a live Stellar request, and [MTT](https://mtt.gg) (open source) renders it all live. ### What you can build * **Trading bots & terminals** — stream live trades and market depth, then execute off your own signals. * **Portfolio & tax tools** — reconstruct an account's full history and current holdings. * **Analytics dashboards** — track liquidity, volume, and holder distribution per market. * **Price & liquidity alerts** — subscribe to streams and react to moves as ledgers close. * **New-launch monitors** — surface newly created Stellar pairs the moment they're indexed and move first. * **Telegram & Discord bots** — forward live trades, price moves, and new pairs straight to a channel. * **Compliance & reconciliation** — resolve any transfer or swap by transaction hash. ### What you'll need 1. A Stellar asset (`CODE:ISSUER`), a transaction hash, or a `G…` account. 2. The chain identifier `stellar:stellar` (mainnet) or `stellar:testnet`. 3. An API key from the [Dashboard](https://admin.mobula.io).**Base URLs & keys.** The REST examples below use `https://api.mobula.io` and also run **without a key** on `https://demo-api.mobula.io` for quick evaluation. WebSocket streams always require an API key in the `authorization` field. ### What Stellar supports Mobula indexes Stellar on **mainnet** (`stellar:stellar`) and **testnet** (`stellar:testnet`), covering tokens, transfers, DEX markets (Aquarius, Soroswap, and the classic AMM), and wallet portfolios. Swap quote/execution routing and NFT holdings are not covered. Full per-network reference — chain identifiers, address formats, and every supported endpoint: * **[Stellar (mainnet)](/blockchains/stellar)** * **[Stellar Testnet](/blockchains/stellar-testnet)** ### What to use for what | I want to… | Endpoint | | - | - | | Look up one swap/transaction by hash | `GET /api/2/token/trade` | | Get a token's trade history | `GET /api/2/token/trades` | | Get an account's full transaction ledger | `GET /api/1/wallet/transactions` | | See per-market liquidity, reserves & volume | `GET /api/2/token/markets` | | Get a token's liquidity & market cap | `GET /api/1/metadata` | | Get decoded account activity (transfers, swaps, vault) | `GET /api/2/wallet/activity` | | Stream live trades as ledgers close | `WSS fast-trade` | | Stream live pool price, volume & liquidity | `WSS market-details` | | Stream live token price & stats | `WSS token-details` | | Stream real-time OHLCV candles | `WSS ohlcv` | | Discover newly launched Stellar pairs | `WSS pulse-v2` | *** ## 1. Historical transaction lookups Use these when you need to resolve a specific transaction, reconstruct a token's trade timeline, or pull an account's full history. Add `limit` (and `offset`) to page through large result sets. **Look up a single swap by transaction hash** — for support, compliance or reconciliation: ```bash theme={null} curl -X GET "https://api.mobula.io/api/2/token/trade?blockchain=stellar:stellar&transactionHash=84ce022d070cf38a1a4921cdbde9195206ea12c6fd6d2b2b673e74256f78ea3d" ``` ```json theme={null} { "data": { "type": "buy", "baseTokenAmount": 964.8612501, "baseTokenAmountUSD": 166.02, "quoteTokenAmount": 167.2260013, "date": 1785302032000, "swapSenderAddress": "GCLN4HAD2UPYTQ5WR4RMCHCG5F5XZV77HX7BA7PDPZ7NFEBM4KR56KVR", "blockchain": "Stellar", "transactionHash": "84ce022d070cf38a1a4921cdbde9195206ea12c6fd6d2b2b673e74256f78ea3d", "marketAddress": "CBRUQ7I6C6OGHMDYWD6XQUZFB6KJ3LLPNE34EPKSPFZ2YMBJ2GIWYYZ7" } } ``` **Page a token's trade history** — newest first: ```bash theme={null} curl -X GET "https://api.mobula.io/api/2/token/trades?chainId=stellar:stellar&address=AQUA:GBNZILSTVQZ4R7IKQDGHYGY2QXL5QOFJYQMXPKWRRM5PAV7Y4M67AQUA" ``` **Pull an account's transaction ledger** — the full history for a `G…` account: ```bash theme={null} curl -X GET "https://api.mobula.io/api/1/wallet/transactions?wallet=GDHF3HIKWM5KJAVLZBSZWUFDOEOT7IBMY22UXG4QBE326O354INLPAND&blockchains=stellar:stellar" ``` ```json theme={null} { "data": { "transactions": [ { "hash": "3f166266f158e1973cff265b891bba28bf4975a4b3e3a9d03c5c4274757a03a3", "from": "GDHF3HIKWM5KJAVLZBSZWUFDOEOT7IBMY22UXG4QBE326O354INLPAND", "to": "GAA23STAFIH3D24GT3AKKL4TPK44WEUBH3JF4OPMLN777XQ4EHTHCHIS", "type": "native", "amount": 9224.76107, "block_number": 63698663, "timestamp": 1785305171000, "blockchain": "Stellar" } ] } } ``` *** ## 2. Token liquidity insights Use these to rank venues by depth, monitor liquidity migrations across DEXes, or screen out thin pools. **List an asset's markets** — reserves, 24h volume and price per venue (Aquarius, Soroswap, classic AMM): ```bash theme={null} curl -X GET "https://api.mobula.io/api/2/token/markets?blockchain=stellar:stellar&address=AQUA:GBNZILSTVQZ4R7IKQDGHYGY2QXL5QOFJYQMXPKWRRM5PAV7Y4M67AQUA" ``` ```json theme={null} { "data": [ { "exchange": { "name": "Aquarius" }, "type": "aquarius-concentrated", "address": "CBRUQ7I6C6OGHMDYWD6XQUZFB6KJ3LLPNE34EPKSPFZ2YMBJ2GIWYYZ7", "blockchain": "Stellar", "liquidityUSD": 89861.27, "volume24hUSD": 9743.39, "trades24h": 50, "priceUSD": 0.0003414966853920328, "latestTradeDate": "2026-07-29T06:08:37.000Z" } ] } ``` Each market entry also carries bucketed volume, trade and trader counts (`1min`…`24h`), price-change percentages, fees paid and holder-distribution metrics. **Get token-level liquidity & market cap** — a single aggregated figure: ```bash theme={null} curl -X GET "https://api.mobula.io/api/1/metadata?asset=AQUA:GBNZILSTVQZ4R7IKQDGHYGY2QXL5QOFJYQMXPKWRRM5PAV7Y4M67AQUA&blockchain=stellar:stellar" ``` ```json theme={null} { "data": { "name": "Aquarius", "symbol": "AQUA", "price": 0.000338, "liquidity": 1086674.84, "market_cap": 12147718.70 } } ``` *** ## 3. Contract interaction data Use this to build an account activity timeline mixing classic payments and Soroban contract calls, or to attribute value flows to specific contracts and counterparties. **Fetch decoded account activity** — transfers, swaps and vault operations per transaction: ```bash theme={null} curl -X GET "https://api.mobula.io/api/2/wallet/activity?wallet=GDHF3HIKWM5KJAVLZBSZWUFDOEOT7IBMY22UXG4QBE326O354INLPAND&blockchains=stellar:stellar" ``` ```json theme={null} { "data": [ { "chainId": "stellar:stellar", "txHash": "3f166266f158e1973cff265b891bba28bf4975a4b3e3a9d03c5c4274757a03a3", "txDateIso": "2026-07-29T06:06:11.000Z", "txBlockNumber": 63698663, "txIndex": 111, "actions": [ { "model": "transfer", "transferType": "NATIVE_OUT", "transferAmount": 9224.76107, "transferFromAddress": "GDHF3HIKWM5KJAVLZBSZWUFDOEOT7IBMY22UXG4QBE326O354INLPAND", "transferToAddress": "GAA23STAFIH3D24GT3AKKL4TPK44WEUBH3JF4OPMLN777XQ4EHTHCHIS", "transferAsset": { "symbol": "XLM", "decimals": 7 } } ] } ] } ``` Each transaction's `actions` array is a decoded view of the interaction: `transfer` (value movements), swap (DEX trades) and vault (deposit/withdraw) models. Transaction-level fields (`txBlockNumber` = ledger sequence, `txIndex` = application order) let you order and reconcile activity exactly as it appears on-chain. *** ## 4. Live market streams Use these to power live charts, trading terminals, and price or liquidity alerts — updates are pushed as ledgers close, so you never poll. All Stellar markets and tokens stream over `wss://api.mobula.io`; pass `blockchain: "stellar:stellar"` in the subscribe payload. Every subscribe payload must include your API key in the `authorization` field — streams reject unauthenticated connections. **Connect and subscribe:** ```javascript theme={null} const ws = new WebSocket('wss://api.mobula.io'); ws.onopen = () => ws.send(JSON.stringify(subscribe)); // any payload below ws.onmessage = (e) => console.log(JSON.parse(e.data)); ``` | Stream | `type` | Delivers | Docs | | - | - | - | - | | Fast Trades | `fast-trade` | Each swap, pushed as its ledger closes | [Reference](/indexing-stream/stream/websocket/wss-fast-trades) | | Market Details | `market-details` | Live pool price, volume and liquidity | [Reference](/indexing-stream/stream/websocket/wss-market-details) | | Token Details | `token-details` | Live token price and market stats | [Reference](/indexing-stream/stream/websocket/wss-token-details) | | OHLCV | `ohlcv` | Real-time candles | [Reference](/indexing-stream/stream/websocket/ohlcv-stream) | | Pulse | `pulse-v2` | Newly created and trending Stellar pairs | [Reference](/indexing-stream/stream/websocket/pulse-stream-v2-pool-based) | **Subscribe to live trades on a Stellar market:** ```json theme={null} { "type": "fast-trade", "authorization": "YOUR-API-KEY", "payload": { "assetMode": false, "items": [ { "blockchain": "stellar:stellar", "address": "CBRUQ7I6C6OGHMDYWD6XQUZFB6KJ3LLPNE34EPKSPFZ2YMBJ2GIWYYZ7" } ] } } ``` **Subscribe to live market details for a Stellar pool:** ```json theme={null} { "type": "market-details", "authorization": "YOUR-API-KEY", "payload": { "pools": [ { "blockchain": "stellar:stellar", "address": "CBRUQ7I6C6OGHMDYWD6XQUZFB6KJ3LLPNE34EPKSPFZ2YMBJ2GIWYYZ7" } ] } } ``` Token Details and OHLCV follow the same connection pattern — set `blockchain` to `stellar:stellar` and see each stream's reference for its payload fields. **Be a first mover — stream newly launched Stellar pairs:** Scope Pulse to `stellar:stellar` and sort by `created_at` to receive new pairs the moment they're indexed. ```json theme={null} { "type": "pulse-v2", "authorization": "YOUR-API-KEY", "payload": { "views": [ { "name": "new-stellar-pairs", "chainId": ["stellar:stellar"], "sortBy": "created_at", "sortOrder": "desc", "limit": 50 } ] } } ``` *** ## 5. Build with the SDK The [`@mobula_labs/sdk`](https://www.npmjs.com/package/@mobula_labs/sdk) wraps every endpoint above with typed methods and defaults to `demo-api.mobula.io`, so it works without a key for evaluation. ```bash theme={null} npm install @mobula_labs/sdk ``` ```typescript theme={null} import { MobulaClient } from '@mobula_labs/sdk'; const client = new MobulaClient({ apiKey: 'YOUR-API-KEY' }); // Stellar token markets — liquidity, volume and price per venue const markets = await client.fetchTokenMarkets({ blockchain: 'stellar:stellar', address: 'CAUP7NFABXE5TJRL3FKTPMWRLC7IAXYDCTHQRFSCLR5TMGKHOOQO772J', // XSOLVBTC }); // → [{ exchange: { name: 'Aquarius' }, liquidityUSD: 10472431.6, priceUSD: 63338.23, ... }] ``` The same typed methods power **[MTT](https://mtt.gg)** — Mobula's open-source trading terminal and a full reference implementation that renders Stellar tokens live:mtt.gg/token/stellar:stellar/CAUP7NFA…772J — live chart, trades, liquidity and holders, all served by the endpoints on this page. Source: [github.com/MobulaFi/MTT](https://github.com/MobulaFi/MTT). *** ## Use cases in practice Each use case is just a few of the calls above combined. A few worked examples: **Portfolio tracker** — an account's current holdings plus its decoded activity feed: ```bash theme={null} # 1) Balances curl "https://api.mobula.io/api/2/wallet/holdings?wallet=GDHF3HIK…PAND&blockchains=stellar:stellar" # 2) Decoded activity (transfers, swaps, vault) curl "https://api.mobula.io/api/2/wallet/activity?wallet=GDHF3HIK…PAND&blockchains=stellar:stellar" ``` **Token dashboard** — valuation, per-venue liquidity, and recent trades for one token: ```bash theme={null} # 1) Market cap + aggregate liquidity curl "https://api.mobula.io/api/1/metadata?asset=AQUA:GBNZ…AQUA&blockchain=stellar:stellar" # 2) Liquidity per venue (Aquarius, Soroswap, classic AMM) curl "https://api.mobula.io/api/2/token/markets?blockchain=stellar:stellar&address=AQUA:GBNZ…AQUA" # 3) Recent trades curl "https://api.mobula.io/api/2/token/trades?chainId=stellar:stellar&address=AQUA:GBNZ…AQUA" ``` **New-launch monitor (first mover)** — stream freshly created pairs, then pull each one's liquidity to filter: ```text theme={null} 1) Subscribe to pulse-v2 scoped to stellar:stellar, sorted by created_at desc (see §4) 2) For each new market address it pushes: GET /api/2/token/markets?blockchain=stellar:stellar&address=3) Act on the pairs that clear your liquidity / volume threshold ``` **Live trading terminal** — snapshot with REST, then keep it live over a stream: ```text theme={null} 1) GET /api/2/token/markets → initial price, liquidity, trades 2) Subscribe to fast-trade + market-details for the pool (see §4) 3) Apply each pushed update to your local state as ledgers close ``` **Telegram bot** — push new-pair or price alerts to a channel: ```text theme={null} 1) Subscribe to pulse-v2 (new pairs) or fast-trade (price/trades) over WSS (see §4) 2) On each pushed update, call the Telegram Bot API sendMessage to post it ``` See the full build in **[Build a Telegram Buy Bot](/guides/build-telegram-buy-bot)** — the same pattern, pointed at `stellar:stellar`. ### Need Help? Our support team is available to assist with your queries or integration issues. # How to Use Universal Fast Search Across Ethereum, Solana, BNB, Base & More Source: https://docs.mobula.io/guides/how-to-use-universal-fast-search Use the Fast Search endpoint to search tokens by typing an input string like a symbol or name, with optional filtering and sorting across chains. The [**Fast Search**](https://docs.mobula.io/rest-api-reference/endpoint/fast-search) endpoint lets you search tokens by typing an input string like a symbol or name. It helps you quickly find token information and relevant results across chains like [Solana](https://docs.mobula.io/blockchains/solana), [Ethereum](https://docs.mobula.io/blockchains/ethereum), [BNB Chain](https://docs.mobula.io/blockchains/bsc), [Base](https://docs.mobula.io/blockchains/base), and more. You can also filter and sort results using optional parameters. *** Telegram Slack Discord *** ## What this endpoint does With this API, you can: * Perform a universal search using an input string * Return results such as token pricing information, holders data, and metadata depending on the result type * Filter results to specific chains using `filters` (JSON) * Sort results using `sortBy` and control output size with `limit` * Use exact symbol match by wrapping the input in double quotes (example: `"W"`) * Search by EVM address prefix for autocomplete flows (example: `0x0e09`) *** ## What you’ll need * Basic knowledge of REST APIs * A token symbol or name to search (example: `eth`, `parti`) * A Mobula API key Note: All Mobula endpoints require an API key.\ Get a free API key: [Here](https://admin.mobula.io/) Optional: * DexScreener (to pick real token symbols to test) *** ## When to use Fast Search Use this endpoint when you want to: * Search tokens quickly by symbol or name * Build a search bar for tokens, assets, or pairs * Restrict results to specific chains like Ethereum, Base, Arbitrum, or Solana * Sort results by metrics like `volume24h` or `marketCap` * Use exact match search for short symbols to reduce noisy results If you want a full asset snapshot after selecting a result, use: [**Asset Details**](https://docs.mobula.io/rest-api-reference/endpoint/asset-details) If you want enriched details for a specific token contract, use: [**Token Details**](https://docs.mobula.io/rest-api-reference/endpoint/token-details) If you want to list pools and markets for a token across DEXes, use: [**Token Markets**](https://docs.mobula.io/rest-api-reference/endpoint/token-markets) If you want market-level pool stats like liquidity, volume, and price changes, use: [**Market Details**](https://docs.mobula.io/rest-api-reference/endpoint/market-details) *** ## Walkthrough to Get Fast Search ### 1. Prepare your query The Fast Search endpoint requires one parameter: | Parameter | Description | | - | - | | `input` | Search query string (example: `eth`, `parti`, `"W"`, `0x0e09`) | Optional parameters you can use: * `type`: Type of results to return: `tokens`, `assets`, or `pairs` * `filters`: JSON string with filter options like `blockchains` (example: `filters={"blockchains":"8453,1,42161,10,solana"}`) * `sortBy`: Sort field (example: `volume24h`, `marketCap`, `searchScore`) * `limit`: Maximum number of results (1 to 20, default: 5) * `excludeBonded`: Exclude bonded tokens from results Tip: Wrap your input in double quotes to perform an exact symbol match. Example: `"W"` returns only tokens with symbol `W`, not `WETH` or `WBTC`. Tip: If the input starts with an EVM address prefix like `0x0e09`, Fast Search matches token contract addresses, pool addresses, and deployer addresses that start with that prefix. ### 2. Find a token to test with DexScreener To get a real search term: * Open DexScreener * Pick a token * Copy the token symbol or name This symbol is used as the `input` parameter. ### 3. Fill the API form Either: * Enter an `input` string only, or * Enter `input` and set `type`, `filters`, `sortBy`, `limit`, or `excludeBonded` Then click **Send**. *** ## Reviewing the response * **Search results list**: The endpoint returns the top matches for your input query in `data[]`. * **Result type**: Use `type` to control whether you get `tokens`, `assets`, or `pairs`. * **Ranking**: Results are ranked using `searchScore` by default. You can change ranking using `sortBy` (example: `volume24h`, `marketCap`). * **Filters**: Use `filters` to restrict results to specific chains by passing a JSON object or JSON string for `blockchains`. * **Exact match**: Wrap your input in double quotes to search for an exact symbol match, useful for short symbols. * **Address prefix match**: Start the input with an EVM prefix such as `0x0e09` to find matching token, pool, or deployer addresses. * **Output size**: Use `limit` to control how many results are returned (up to 20). *** ## Summary The [**Fast Search**](https://docs.mobula.io/rest-api-reference/endpoint/fast-search) endpoint helps you: * Search tokens using an input string like a symbol or name * Search by EVM address prefix for contract autocomplete * Filter results by chain using `filters` and sort by key metrics using `sortBy` * Use double quotes for exact symbol matches when needed * Control output size with `limit` *** ## Try Mobula for Free Try our free API today and start building in minutes.\ Get your free API key: [Here](https://admin.mobula.io/) # How to View Wallet Portfolio Holdings Across Ethereum, Solana, BNB, Base & More Source: https://docs.mobula.io/guides/how-to-view-wallet-portfolio-holdings Use the Wallet Portfolio endpoint to retrieve a wallet’s holdings and see all assets inside it. The [**Get Crypto Holdings**](https://docs.mobula.io/rest-api-reference/endpoint/wallet-portfolio) endpoint lets you retrieve a wallet’s holdings and view all assets inside it in a single request. This is one of the simplest ways to inspect wallet portfolios across chains like [Solana](https://docs.mobula.io/blockchains/solana), [Ethereum](https://docs.mobula.io/blockchains/ethereum), [BNB Chain](https://docs.mobula.io/blockchains/bsc), [Base](https://docs.mobula.io/blockchains/base), and more. You can also query multiple wallets in the same query. ****** ## What this endpoint does With this API, you can: * Retrieve all holdings and assets for a wallet portfolio * Query a single wallet or multiple wallets in one request * Return per-asset balances, estimated USD value, and allocation breakdown * Optionally filter spam assets and exclude low-liquidity tokens * Include 24h price change data for monitoring *** ## What you’ll need * A wallet address (or multiple wallets) * A Mobula API key Note: All Mobula endpoints require an API key.\ Get a free API key: [Here](https://admin.mobula.io/) Optional: * DexScreener (to find active wallets to test) *** ## When to use Wallet Portfolio Use this endpoint when you want to: * Display a wallet’s current holdings and portfolio composition * Combine multiple wallets into one aggregated portfolio view * Filter results by chain for faster responses * Remove spam assets and exclude low-liquidity tokens * Add optional 24-hour price change data for monitoring This endpoint returns holdings only. For realized/unrealized gains, use: * [`/wallet/positions`](https://docs.mobula.io/rest-api-reference/endpoint/wallet-positions) * [`/wallet/position`](https://docs.mobula.io/rest-api-reference/endpoint/wallet-position) *** ## Walkthrough to Get Wallet Portfolio ### 1. Prepare your query The `wallet/portfolio` endpoint supports one or multiple wallets: | Parameter | Description | | - | - | | `wallet` | Single wallet address to query (can also accept comma-separated addresses). Required if `wallets` is not provided. | | `wallets` | Comma-separated wallet addresses to query in aggregate. Required if `wallet` is not provided. | Optional parameters you can use: * `blockchains`: Comma-separated list of chains (example: `ethereum,base`)\ Tip: For fastest responses, specify only the chains you need, such as [Solana](https://docs.mobula.io/blockchains/solana) or [Ethereum](https://docs.mobula.io/blockchains/ethereum). * `fetchAllChains`: `"true"` to query all supported chains * `cache`: `"true"` to allow cached results (faster responses) * `stale`: Number of seconds to allow cached data before refreshing (example: `3600`) * `unlistedAssets`: `"true"` to include unlisted or non-indexed assets in the calculation. * `accuracy`: Set to `"maximum"` to analyze all assets (may increase response time) * `minliq`: Minimum liquidity threshold in USD (example: `10000`) * `filterSpam`: `"true"` to remove spam or low-quality assets * `shouldFetchPriceChange`: Set to `"24h"` to include 24-hour price change data * `fetchEmptyBalances`: `"true"` to include tokens with zero balance * `testnet`: `"true"` to include testnet data * `backfillTransfers`: `"true"` to trigger transfer backfilling (returns `backfill_status`) ### 2. Find a wallet address to test To retrieve real wallet data: * Open DexScreener * Pick any token * Click **Top Traders** * Select an active wallet * Open it in the blockchain explorer * Copy the wallet address This address is used as the `wallet` parameter. ### 3. Fill the API form Once your wallet address is ready: * Paste it into the `wallet` field * (Optional) add chain filters like `blockchains=solana` * Set spam filtering or liquidity thresholds if needed * Click **Send** to retrieve the wallet portfolio holdings *** ## Reviewing the response Each asset returned represents a holding found in the wallet portfolio. Key fields include: * `price`: Current price in USD * `token_balance`: Total token amount held * `estimated_balance`: Estimated USD value (`token_balance × price`) * `allocation`: Percentage share of total portfolio value * `liquidity`: Total liquidity across DEX pools * `price_change_24h`: Returned when `shouldFetchPriceChange=24h` is enabled * `contracts_balances`: Detailed breakdown per chain and contract * `cross_chain_balances`: Aggregated balances per blockchain * `wallets`: Wallet addresses holding the asset (useful for multi-wallet queries) *** ## Try It Live with Mobula Wallet Portfolio Demo (UI) [Demo UI Homepage](https://mobula-demo-endpoint-production.up.railway.app/) [Wallet Portfolio Demo UI](https://mobula-demo-endpoint-production.up.railway.app/wallet-portfolio) [Docs](https://docs.mobula.io/rest-api-reference/endpoint/wallet-portfolio) *** ## Summary The [**Get Crypto Holdings**](https://docs.mobula.io/rest-api-reference/endpoint/wallet-portfolio) endpoint helps you: * Retrieve wallet holdings and assets in one request * Query single or multiple wallets in the same call * Filter by chain, remove spam assets, and set liquidity thresholds * Visualize results instantly in the demo UI *** ## Try Mobula for Free Try our free API today and start building in minutes.\ Get your free API key: [Here](https://admin.mobula.io/) # Migrate from the Launchpad GraphQL Stream to Pulse Source: https://docs.mobula.io/guides/migrate-launchpad-stream-to-pulse Step-by-step guide to migrate from the Codex-compatible onLaunchpadTokenEvent GraphQL subscription to the native Mobula Pulse V2 stream — endpoint mapping, protocol and network ID translation, field mapping, and message handling. Mobula's [GraphQL API](/api-reference/graphql/overview) is Codex-compatible: the `onLaunchpadTokenEvent` and `onLaunchpadTokenEventBatch` subscriptions accept the same operations a Codex client already sends, which makes it the fastest first step off Codex. The native **Pulse V2 stream** is the recommended production target: instead of a flat event firehose you subscribe to *views* (new / bonding / bonded, or fully custom), each maintained server-side with sorting, limits, and a Prisma-style filter tree over 100+ token statistics. This guide maps the launchpad subscription to Pulse V2, concept by concept.Already on the GraphQL layer? Both APIs run on the same indexing pipeline, so you can migrate view by view and compare outputs side by side with the same API key. ## Endpoint mapping | | Launchpad GraphQL stream | Pulse V2 | | - | - | - | | Real-time | `wss://graphql.mobula.io/graphql` (`graphql-transport-ws`) | `wss://api.mobula.io` — message `type: "pulse-v2"` | | HTTP snapshot | `filterTokens` query | `POST /api/2/pulse` ([documentation](/rest-api-reference/endpoint/pulse-post)) | | Counts only | — | `POST /api/2/pulse/pagination` | | Auth | `Authorization: YOUR_API_KEY` header | `authorization` field in the subscribe message |Pulse V2 over WebSocket requires a Growth or Enterprise plan. ## The mental model shift The launchpad subscription is **event-based**: every push is one lifecycle event (`Deployed`, `Updated`, `Completed`, `Migrated`, …) for one token, and your client assembles the current state. Pulse V2 is **view-based**: the server maintains the state — each view is a sorted, filtered, limited set of tokens — and streams membership changes: | Launchpad stream | Pulse V2 equivalent | | | - | - | - | | `eventType: Deployed` / `Created` push | `new-token` message on a view filtering `bonded: false` (the default `new` view) | | | `eventType: Updated` push | `update-token` message on any view containing the token | | | `eventType: Completed` / `Migrated` push | `new-token` message on a view filtering `bonded: true` (the default `bonded` view) | | | `removeToken` payload | `remove-token` message (`tokenKey` = \`chainId | tokenAddress\`) | | `onLaunchpadTokenEventBatch` | Views batch naturally — the `init` message delivers the full snapshot per view | | | `updatePeriod` input | Server-managed update cadence; use `compressed: true` to cut bandwidth | | So the three lifecycle stages you modeled with `eventType` filters become three concurrent views on **one** WebSocket connection. The default model creates them for you: ```json theme={null} { "type": "pulse-v2", "authorization": "YOUR_API_KEY", "payload": { "model": "default", "assetMode": true, "chainId": ["solana:solana"], "poolTypes": ["pumpfun"], "compressed": false } } ``` This yields the views `new` (not yet bonded, sorted by `created_at`), `bonding` (`bonding_percentage < 100`, sorted by graduation progress), and `bonded` (`bonded: true`, sorted by `bonded_at`). ## Step 1 — Translate network IDs The GraphQL layer uses Codex-style numeric `networkId`; Pulse uses string chain IDs. * **EVM chains** map directly: numeric `networkId` `N` → `evm:N` (e.g. `8453` → `evm:8453`). [`getNetworks`](/api-reference/graphql/queries/getNetworks) lists them. * **Non-EVM chains** use fixed string IDs: `solana:solana`, `sui:sui`, `starknet:starknet`. They are covered by [`getNetworkConfigs`](/api-reference/graphql/queries/getNetworkConfigs). * Token identity changes from Codex's `address:networkId` to Mobula's `chainId|address` (this is the `tokenKey` format in `remove-token` messages). ## Step 2 — Translate protocols to pool types `protocol` / `protocols` enum values map to Pulse `poolTypes` / factory ids. The authoritative list lives at `GET https://api.mobula.io/api/1/system-metadata` (`data.factories[].name`); the common ones: | `LaunchpadTokenProtocol` | Pulse `poolTypes` / factory id | | - | - | | `Pump` | `pumpfun` | | `FourMeme` | `fourmeme` | | `RaydiumLaunchpad` | `raydium-launchlab` | | `BoopFun` | `boop` | | `MeteoraDBC` | `meteora-dbc` | | `ZoraV4` | `zora` | | `Virtuals` | `virtuals` | | `Clanker` / `ClankerV4` | `clanker` | | `HeavenAMM` | `heaven` | | `Printr` | `printr` | | `NadFun` | `nadfun` | | `Flaunch` | `flaunch-v4` | | `Liquid` | `liquidlaunch` | See [LaunchpadTokenProtocol](/api-reference/graphql/types/LaunchpadTokenProtocol) for the full factory-id table. ## Step 3 — Translate the subscription into views Before — one subscription per protocol and event type: ```graphql theme={null} subscription { onLaunchpadTokenEvent(input: { protocol: Pump, eventType: Deployed }) { update { address networkId eventType price marketCap holders volume1 token { symbol name } } removeToken { address networkId reason } } } ``` After — a custom view (or use the default model above): ```json theme={null} { "type": "pulse-v2", "authorization": "YOUR_API_KEY", "payload": { "assetMode": true, "views": [ { "name": "pump-new", "chainId": ["solana:solana"], "poolTypes": ["pumpfun"], "sortBy": "created_at", "sortOrder": "desc", "limit": 50, "filters": { "bonded": { "equals": false } } } ] } } ``` Anything you expressed with the subscription input's `filters` / `rankings` carries over to the view's `filters` / `sortBy` — Pulse filters support the full `AND` / `OR` / `NOT` tree with `equals`, `not`, `gte`, `gt`, `lte`, `lt`, `in`, `notIn`, `contains`, `startsWith`, `endsWith`. See the [Filter Details](/indexing-stream/stream/websocket/filters-details) reference. ## Step 4 — Translate fieldsPulse **filters** use snake\_case (`market_cap`, `holders_count`); the **response** token object uses camelCase (`token.holdersCount`, `token.top10HoldingsPercentage`). | Launchpad output field | Pulse filter field | Notes | | - | - | - | | `price` | `latest_price` | | | `marketCap` | `market_cap` | String in GraphQL, number in Pulse | | `holders` | `holders_count` | | | `buyCount1` / `sellCount1` | `buys_1h` / `sells_1h` | All timeframes available: `1min`, `5min`, `15min`, `1h`, `4h`, `6h`, `12h`, `24h` | | `volume1` | `volume_1h` | Plus `volume_buy_*` / `volume_sell_*` splits | | `transactions1` | `trades_1h` | | | `totalFees1`, `poolFees1`, … | `fees_paid_1h` | | | `sniperCount` / `sniperHeldPercentage` | `snipers_count` / snipers holdings percentage | | | `bundlerCount` / `bundlerHeldPercentage` | `bundlers_count` / bundlers holdings percentage | | | `insiderCount` / `insiderHeldPercentage` | `insiders_count` / insiders holdings percentage | | | `devHeldPercentage` | dev holdings percentage | Response: `token.devHoldingsPercentage` | | `top10HoldersPercent` | `top_10_holdings_percentage` | Response: `token.top10HoldingsPercentage` | | `launchpadGraduationPercent` | `bonding_percentage` | | | `launchpadCompleted` / `launchpadMigrated` | `bonded` | | | `launchpadCompletedAt` / `launchpadMigratedAt` | `bonded_at` | | Pulse additionally exposes fields the launchpad stream never had — organic (bot-excluded) volume/trade series, fresh/pro/smart trader counts, ATH/ATL, security data — see the [Token Data Model](/indexing-stream/stream/websocket/pulse-stream-v2#token-data-model). ## Step 5 — Handle the message loop Replace your `graphql-transport-ws` `next`-message handler with five message types: 1. **`init`** — full snapshot per view. Replaces your initial `filterTokens` backfill query; render it as-is. 2. **`new-token`** — a token entered a view (deploy in `new`, graduation in `bonded`, …). 3. **`update-token`** — stats changed for a token already in a view. 4. **`remove-token`** — token left a view; delete by `tokenKey` (`chainId|tokenAddress`). 5. **`sync`** — the server resets the view. **You must discard local view state and replace it with the sync payload** — do not merge. Operational bits: * **Keepalive**: send `{"event":"ping"}` every 30–60 s. * **Pause instead of resubscribe**: `{"type": "pulse-pause", "payload": {"action": "pause", "views": ["pump-new"]}}` (and `"unpause"`) — no reconnect, no snapshot replay. * **Compression**: `compressed: true` enables gzip payloads. ## Step 6 — Validate the migration * Run both streams side by side for a few days before cutting over; compare **token membership per view**, not raw event counts — an event-based and a view-based stream will never emit the same number of messages for the same reality. * When counts differ on trades/volume, compare on unique transaction hashes: providers count multi-leg swaps differently (see [benchmarks](/streams-benchmarks)). * Test with the launchpads you actually track — validate `poolTypes` values against `/api/1/system-metadata` rather than hardcoding. ## Related documentation# Pool Targeting: Route Swaps Through Specific Pools Source: https://docs.mobula.io/guides/pool-targeting Learn how to target specific liquidity pools or DEX protocols when executing swaps via the Mobula Swap API ## Overview By default, the Mobula Swap API automatically finds the best route across all available liquidity sources. However, you may want to **target a specific pool** or **restrict routing to certain protocols** — for example, to: * Execute a swap directly through a specific Aerodrome CL pool on Base * Restrict routing to only Uniswap V3 pools * Avoid certain factory contracts * Force routing through a specific DEX for compliance or analytics The Swap API provides three parameters for pool targeting: | Parameter | Routing | Description | | - | - | - | | `poolAddress` | **Direct on-chain** | Target a specific pool by address — bypasses aggregators, executes directly via MobulaRouter | | `onlyProtocols` | Via aggregator | Restrict to specific pool types (e.g., `uniswap-v3`) — routed through KyberSwap/Jupiter | | `excludedProtocols` | Via aggregator | Exclude specific factory addresses from routing | Full WebSocket reference — views, filters, message formats. Integrate with `@mobula/sdk`, with open-source examples from MTT. The GraphQL subscription this guide migrates from. End-to-end cookbook for a token discovery feed. **Key difference**: `poolAddress` routes the swap **directly on-chain** through MobulaRouter's `executeRoute` function. `onlyProtocols` passes the restriction to an external aggregator (KyberSwap, Jupiter) which handles the routing. ## Direct Pool Access (`poolAddress`) Use `poolAddress` when you know the exact pool contract address and want to swap **directly through it**, without going through an external aggregator. The swap is executed on-chain via MobulaRouter's internal routing engine. ### Basic Example Route a USDC → WETH swap directly through a specific Aerodrome CL pool on Base: ```bash theme={null} curl -X GET "https://api.mobula.io/api/2/swap/quoting?\ chainId=evm:8453\ &tokenIn=0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913\ &tokenOut=0x4200000000000000000000000000000000000006\ &amount=100\ &walletAddress=0xYourWallet\ &slippage=1\ &poolAddress=0xb4cb800910b228ed3d0834cf79d697127bbb00e5" ``` ### Concrete Example — USDC to TKFG on Aerodrome CL (Base) This example swaps \~300 USDC (raw units) to TKFG on Base, routed directly through the Aerodrome CL pool: ```bash theme={null} curl -X GET "https://api.mobula.io/api/2/swap/quoting?\ chainId=evm%3A8453\ &tokenIn=0x833589fcd6edb6e08f4c7c32d4f71b54bda02913\ &tokenOut=0xe9d139df6212fde346ec650e83039f322018f60d\ &amountRaw=300539874\ &walletAddress=0xYourWallet\ &slippage=1\ &poolAddress=0x66fbdb0b14a889b3735da163843289a55d28bb97" ``` The response transaction will use MobulaRouter's `executeRoute` selector (`0x1688b026` as of v2.19.0; `0xa564dfa4` on routers still running v2.17.0), executing the swap directly on-chain without any aggregator intermediary.You can discover pool addresses using the [Token Markets](/rest-api-reference/endpoint/token-markets) endpoint, which returns all pools for a given token pair along with their addresses, types, and liquidity. ### When to Use `poolAddress` * You want **zero aggregator fees** — the swap goes directly through the pool * You need **deterministic routing** — always the exact same pool, no fallback * You're building a **pool-specific UI** (e.g., showing swap for a specific market) * Multiple pools exist for the same pair (e.g., different fee tiers) and you want a specific one ## Filtering by Protocol (`onlyProtocols`) Use `onlyProtocols` to restrict the swap to pools of a specific type. The swap is routed through an external aggregator (KyberSwap on EVM, Jupiter on Solana) which applies the filter. ### Single Protocol Route a swap exclusively through Uniswap V3 pools: ```bash theme={null} curl -X GET "https://api.mobula.io/api/2/swap/quoting?\ chainId=evm:1\ &tokenIn=0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE\ &tokenOut=0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48\ &amount=0.5\ &walletAddress=0xYourWallet\ &slippage=1\ &onlyProtocols=uniswap-v3" ``` ### Multiple Protocols Route through either Aerodrome CL or Uniswap V3 pools on Base: ```bash theme={null} curl -X GET "https://api.mobula.io/api/2/swap/quoting?\ chainId=evm:8453\ &tokenIn=0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913\ &tokenOut=0x4200000000000000000000000000000000000006\ &amount=100\ &walletAddress=0xYourWallet\ &slippage=1\ &onlyProtocols=aerodrome-cl-2,uniswap-v3" ``` ## Excluding Protocols (`excludedProtocols`) Use `excludedProtocols` to exclude specific factory addresses from routing. Unlike `onlyProtocols` which takes pool type names, this parameter takes **factory contract addresses**: ```bash theme={null} curl -X GET "https://api.mobula.io/api/2/swap/quoting?\ chainId=evm:1\ &tokenIn=0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE\ &tokenOut=0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48\ &amount=1\ &walletAddress=0xYourWallet\ &slippage=1\ &excludedProtocols=0x1F98431c8aD98523631AE4a59f267346ea31F984" ``` ## Common Pool Types ### EVM Chains | Pool Type | Description | | - | - | | `uniswap-v2` | Uniswap V2 and forks (SushiSwap, PancakeSwap V2, etc.) | | `uniswap-v3` | Uniswap V3 concentrated liquidity pools | | `uniswap-v4` | Uniswap V4 pools with hooks | | `aerodrome` | Aerodrome V2 pools (Base) | | `aerodrome-cl-2` | Aerodrome CL (concentrated liquidity) pools (Base) | | `pancakeswap-v3` | PancakeSwap V3 pools | | `solidly-v2` | Solidly V2 pools and forks | | `solidly-v3` | Solidly V3 pools (CL) | | `trader-joe-v2.1` | Trader Joe Liquidity Book pools | | `maverick-v2` | Maverick V2 pools | ### Solana | Pool Type | Description | | - | - | | `raydium-amm` | Raydium AMM pools | | `raydium-clmm` | Raydium concentrated liquidity pools | | `raydium-cpmm` | Raydium constant product pools | | `orca-whirlpool` | Orca Whirlpool concentrated liquidity pools | | `meteora-dlmm` | Meteora DLMM pools | | `pumpfun` | PumpFun bonding curve pools | | `pumpswap` | PumpSwap pools |Only **tradable** pool types are accepted by `onlyProtocols`. Non-tradable types are automatically filtered out. If no valid pool types remain after filtering, the API returns a "No route found" error. ## Choosing a Router (`onlyRouters`) You can also restrict which **aggregator/router** handles the swap, independently from pool targeting: | Router | Chains | Description | | - | - | - | | `kyberswap` | EVM | KyberSwap aggregator (no extra fees) | | `lifi` | EVM | LI.FI cross-chain aggregator | | `jupiter` | Solana | Jupiter aggregator | ```bash theme={null} curl -X GET "https://api.mobula.io/api/2/swap/quoting?\ chainId=evm:8453\ &tokenIn=0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE\ &tokenOut=0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913\ &amount=0.01\ &walletAddress=0xYourWallet\ &slippage=1\ &onlyRouters=kyberswap" ``` ## TypeScript Example ```typescript theme={null} // Direct pool access — swap through a specific pool on-chain async function swapViaSpecificPool() { const params = new URLSearchParams({ chainId: 'evm:8453', tokenIn: '0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913', // USDC tokenOut: '0x4200000000000000000000000000000000000006', // WETH amount: '100', // 100 USDC walletAddress: '0xYourWallet', slippage: '1', poolAddress: '0xb4cb800910b228ed3d0834cf79d697127bbb00e5', // Specific pool }); const response = await fetch( `https://api.mobula.io/api/2/swap/quoting?${params}`, { headers: { Authorization: 'YOUR_API_KEY' } } ); const { data } = await response.json(); // Transaction uses MobulaRouter's executeRoute (direct on-chain) console.log('Route:', data.route); console.log('Estimated output:', data.estimatedAmountOut); console.log('Transaction:', data.evm?.transaction); } // Protocol-filtered — restrict aggregator to specific pool types async function swapWithProtocolFilter() { const params = new URLSearchParams({ chainId: 'evm:8453', tokenIn: '0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913', tokenOut: '0x4200000000000000000000000000000000000006', amount: '100', walletAddress: '0xYourWallet', slippage: '1', onlyProtocols: 'aerodrome-cl-2', // Only Aerodrome CL pools }); const response = await fetch( `https://api.mobula.io/api/2/swap/quoting?${params}`, { headers: { Authorization: 'YOUR_API_KEY' } } ); const { data } = await response.json(); // Transaction uses aggregator (KyberSwap) with protocol filter console.log('Route:', data.route); console.log('Estimated output:', data.estimatedAmountOut); console.log('Transaction:', data.evm?.transaction); } ``` ## Troubleshooting | Issue | Cause | Solution | | - | - | - | | `"No route found"` | No pool of the requested type exists for this pair | Check the pool type name is correct, or try without `onlyProtocols` | | `"Pool not found"` | The `poolAddress` doesn't exist in Mobula's index | Verify the pool address on a block explorer | | Swap uses aggregator instead of direct access | Used `onlyProtocols` instead of `poolAddress` | Use `poolAddress` for direct on-chain routing | | `"Invalid protocol"` | Typo in the pool type name | Check the [Common Pool Types](#common-pool-types) table above | # Pulse WebSocket Integration with the Mobula SDK Source: https://docs.mobula.io/guides/pulse-wss-sdk-integration Learn how to connect to Mobula's Pulse V2 WebSocket stream using the @mobula/sdk. This guide covers real-time token discovery, subscription management, filtering, pause/resume, and performance patterns — with open-source examples from the MTT codebase. Mobula's Pulse V2 WebSocket stream delivers real-time token data — new pairs, bonding curve progress, and migrations — directly to your application. This guide shows you how to integrate the Pulse WSS using the `@mobula/sdk`, with practical patterns taken from the open-source [MTT (Mobula Trader Terminal)](https://github.com/MobulaFi/MTT) codebase.**Live Demo**: See Pulse in action at [mtt.gg](https://mtt.gg) **Source Code**: Full implementation at [github.com/MobulaFi/MTT](https://github.com/MobulaFi/MTT) *** ## Prerequisites * Node.js 18+ or Bun * A Mobula API key (Growth or Enterprise plan) — get one at [admin.mobula.io](https://admin.mobula.io) * `@mobula/sdk` installed in your project ```bash theme={null} npm install @mobula/sdk # or bun add @mobula/sdk ``` *** ## Quick Start Connect to Pulse V2 and start receiving real-time token data in under 10 lines: ```typescript theme={null} import { MobulaClient } from '@mobula/sdk'; const client = new MobulaClient({ restUrl: 'https://pulse-v2-api.mobula.io', apiKey: 'YOUR_API_KEY', }); // Subscribe to the pulse-v2 stream const subscriptionId = client.streams.subscribe( 'pulse-v2', { assetMode: true, views: [ { name: 'new', model: 'new', chainId: ['solana:solana'], limit: 30 }, { name: 'bonding', model: 'bonding', chainId: ['solana:solana'], limit: 30 }, { name: 'bonded', model: 'bonded', chainId: ['solana:solana'], limit: 30 }, ], }, (data) => { console.log('Received:', data); } ); ``` That's it — you're now receiving live token updates. *** ## How the SDK StreamClient Works The `MobulaClient` exposes a `streams` property — an instance of `StreamClient` that manages WebSocket connections. Key behaviors: | Feature | Detail | | - | - | | **Auto-reconnect** | Exponential backoff up to 30 seconds | | **Heartbeat** | Pings every 30s to keep connections alive | | **Deduplication** | Subscriptions are hashed to prevent duplicates | | **Compression** | Per-message deflate supported | | **Queue** | Messages queued until the WebSocket is ready | ### Core Methods ```typescript theme={null} // Subscribe — returns a subscription ID const id = client.streams.subscribe('pulse-v2', payload, callback); // Unsubscribe by ID await client.streams.unsubscribe('pulse-v2', id); // Close the WebSocket connection entirely client.streams.close('pulse-v2'); ``` *** ## Understanding the Payload The subscription payload controls what data you receive. Here's the full shape: ```typescript theme={null} interface PulsePayload { assetMode?: boolean; // true = token mode, false = pool mode compressed?: boolean; // gzip-compressed responses views: Array<{ name: string; // Your label for this view model: 'new' | 'bonding' | 'bonded'; // Token lifecycle stage chainId?: string[]; // e.g. ['solana:solana', 'evm:56'] poolTypes?: string[]; // Filter by pool type sortBy?: string; // Sort field sortOrder?: 'asc' | 'desc'; limit?: number; // Max tokens per view (max 100, default 30) offset?: number; // Pagination offset filters?: Record; // Advanced filters (see below) min_socials?: number; // 1-3, require social links }>; } ``` ### View Models | Model | Description | | - | - | | `new` | Freshly created tokens still in their bonding phase | | `bonding` | Tokens nearing the end of their bonding curve (final stretch) | | `bonded` | Tokens that have migrated to a DEX (graduated) | *** ## Message Types The stream sends three message types: ### `init` — Initial Data Snapshot Sent immediately after subscribing. Contains the current state for all views: ```typescript theme={null} { type: 'init', payload: { new: { data: PulseToken[] }, bonding: { data: PulseToken[] }, bonded: { data: PulseToken[] }, } } ``` ### `update-token` — Token Data Changed Sent when a token's metrics update (price, holders, market cap, etc.): ```typescript theme={null} { type: 'update-token', payload: { viewName: 'new' | 'bonding' | 'bonded', token: PulseToken, } } ``` ### `new-token` — New Token Appeared Sent when a token enters a view for the first time: ```typescript theme={null} { type: 'new-token', payload: { viewName: 'new' | 'bonding' | 'bonded', token: PulseToken, } } ``` *** ## REST + WebSocket Pattern MTT uses a **REST-first, WebSocket-second** pattern for the best user experience: load data instantly via REST, then switch to WebSocket for live updates. Here's a simplified version of how MTT does it (`apps/mtt/src/features/pulse/hooks/usePulseV2.ts`): ```typescript theme={null} import { MobulaClient } from '@mobula/sdk'; const client = new MobulaClient({ restUrl: 'https://pulse-v2-api.mobula.io', apiKey: 'YOUR_API_KEY', }); // 1. Load initial data via REST (fast first paint) const initialData = await client.fetchPulseV2({ assetMode: true, compressed: false, views: [ { name: 'new', model: 'new', chainId: ['solana:solana'], limit: 50 }, { name: 'bonding', model: 'bonding', chainId: ['solana:solana'], limit: 50 }, { name: 'bonded', model: 'bonded', chainId: ['solana:solana'], limit: 50 }, ], }); // Render initialData immediately... // 2. Then subscribe to WebSocket for live updates const subscriptionId = client.streams.subscribe( 'pulse-v2', { assetMode: true, views: [ { name: 'new', model: 'new', chainId: ['solana:solana'], limit: 50 }, { name: 'bonding', model: 'bonding', chainId: ['solana:solana'], limit: 50 }, { name: 'bonded', model: 'bonded', chainId: ['solana:solana'], limit: 50 }, ], }, (msg) => { if (msg.type === 'init') { // Replace all view data } if (msg.type === 'update-token' || msg.type === 'new-token') { // Merge single token into the right view } } ); ``` The REST and WebSocket APIs accept the same payload shape, so you can reuse your view configuration for both. *** ## How MTT Implements Pulse WSS MTT is Mobula's open-source trading terminal. Its Pulse implementation is a production reference you can study and adapt. Here are the key architectural pieces: ### Architecture ``` ┌──────────────────────────────────────────────────────┐ │ PulseStreamProvider │ │ React Context — shares stream state with all children│ ├──────────────────────────────────────────────────────┤ │ usePulseV2 Hook │ │ REST initial load → WebSocket subscription │ │ Message batching → Pause/Resume → Filter resubscribe │ ├─────────────────────┬────────────────────────────────┤ │ usePulseDataStore │ usePulseFilterStore │ │ Zustand store: │ Zustand + localStorage: │ │ tokens per view │ chain, protocol, metric │ │ merge / sort / cap │ and audit filters │ ├─────────────────────┴────────────────────────────────┤ │ UI Components │ │ TokenSection → TokenCard → FilterModal │ └──────────────────────────────────────────────────────┘ ``` ### Key Files in the MTT Codebase | File | Purpose | | - | - | | `src/lib/sdkClient.ts` | SDK wrapper with server/client mode routing | | `src/features/pulse/hooks/usePulseV2.ts` | Core hook — REST load, WSS subscribe, message handling | | `src/features/pulse/store/usePulseDataStore.ts` | Token state management per view | | `src/features/pulse/store/usePulseModalFilterStore.ts` | Filter state with localStorage persistence | | `src/features/pulse/context/PulseStreamContext.tsx` | React context provider for stream state | | `src/features/pulse/components/FilterModal.tsx` | Filter UI that triggers resubscription | | `src/config/endpoints.ts` | WSS and REST URL configuration | ### SDK Client Wrapper MTT wraps the SDK to support both server-side (SSR) and client-side modes. Here's the stream subscription pattern from `sdkClient.ts`: ```typescript theme={null} import { MobulaClient } from '@mobula/sdk'; import type { PulsePayloadParams } from '@mobula/types'; type StreamSubscription = { unsubscribe: () => void }; function subscribePulseV2( params: PulsePayloadParams, callback: (data: unknown) => void ): StreamSubscription { const client = getMobulaClient(); // your singleton const subscriptionId = client.streams.subscribe('pulse-v2', params, callback); return { unsubscribe: () => { client.streams.unsubscribe('pulse-v2', subscriptionId); }, }; } ``` ### Update Batching for 60fps MTT batches incoming WebSocket messages using `requestAnimationFrame` to avoid render storms: ```typescript theme={null} class UpdateBatcher{ private updates: T[] = []; private scheduled = false; constructor(private callback: (updates: T[]) => void) {} add(update: T) { this.updates.push(update); if (!this.scheduled) { this.scheduled = true; requestAnimationFrame(() => { this.callback(this.updates); this.updates = []; this.scheduled = false; }); } } } // Usage in the pulse hook const batcher = new UpdateBatcher<{ view: string; token: PulseToken }>((updates) => { updates.forEach(({ view, token }) => { dataStore.mergeToken(view, token); }); }); // In the WebSocket callback: client.streams.subscribe('pulse-v2', payload, (msg) => { if (msg.type === 'update-token' || msg.type === 'new-token') { batcher.add({ view: msg.payload.viewName, token: msg.payload.token }); } }); ``` Without batching, high-frequency token updates can cause hundreds of React re-renders per second. The `UpdateBatcher` coalesces them into a single render per animation frame. *** ## Pause and Resume The SDK supports pausing specific views without disconnecting: ```typescript theme={null} // Pause views (stop receiving updates for these views) client.streams.subscribe('pulse-v2-pause', { action: 'pause', views: ['new', 'bonding'], }); // Resume views client.streams.subscribe('pulse-v2-pause', { action: 'unpause', views: ['new', 'bonding'], }); ``` MTT uses this when the user scrolls away from a section or when applying filters (to prevent flickering during resubscription): ```typescript theme={null} // From usePulseV2.ts — pause during filter changes const applyFilters = () => { setIsPaused(true); // Unsubscribe old → resubscribe with new filters // Resume after a short delay setTimeout(() => setIsPaused(false), 500); }; ``` *** ## Filtering Pass filters inside each view to narrow down the token stream. Filters use `{ gte, lte }` range syntax: ```typescript theme={null} client.streams.subscribe('pulse-v2', { assetMode: true, views: [ { name: 'new', model: 'new', chainId: ['solana:solana'], limit: 50, filters: { market_cap: { gte: 10000, lte: 1000000 }, holders_count: { gte: 50 }, volume_24h: { gte: 5000 }, dev_holdings_percentage: { lte: 10 }, top10_holders_percent: { lte: 50 }, }, }, ], }); ``` ### Available Filter Fields | Filter | Type | Description | | - | - | - | | `market_cap` | `{ gte?, lte? }` | Market capitalization in USD | | `volume_24h` | `{ gte?, lte? }` | 24-hour trading volume | | `liquidity` | `{ gte?, lte? }` | Available liquidity | | `holders_count` | `{ gte?, lte? }` | Number of token holders | | `top10_holders_percent` | `{ gte?, lte? }` | Top 10 holders concentration | | `dev_holdings_percentage` | `{ gte?, lte? }` | Developer holdings % | | `snipers_holdings_percentage` | `{ gte?, lte? }` | Sniper wallet holdings % | | `insiders_holdings_percentage` | `{ gte?, lte? }` | Insider holdings % | | `bundlers_holdings_percentage` | `{ gte?, lte? }` | Bundler holdings % | | `bonding_percentage` | `{ gte?, lte? }` | Bonding curve progress % | | `pro_traders_count` | `{ gte?, lte? }` | Number of pro traders | | `trades_24h` | `{ gte?, lte? }` | 24h transaction count | | `buys_24h` | `{ gte?, lte? }` | 24h buy count | | `sells_24h` | `{ gte?, lte? }` | 24h sell count | | `fees_paid_24h` | `{ gte?, lte? }` | Fees paid in 24h | | `created_at_offset` | `{ gte?, lte? }` | Token age in seconds | | `deployer_migrations_count` | `{ gte?, lte? }` | Deployer's migration count | | `dexscreener_ad_paid` | `{ equals: true }` | Has DEX Screener ad | | `twitter` | `{ not: null }` | Has Twitter link | | `website` | `{ not: null }` | Has website | | `telegram` | `{ not: null }` | Has Telegram link | | `min_socials` | `number` | Min social links (1-3) | | `includeKeywords` | `string[]` | Token name must contain one of these | | `excludeKeywords` | `string[]` | Token name must not contain these |For the complete filter reference with examples, see [Filter Details](/indexing-stream/stream/websocket/filters-details). *** ## Multi-Chain Support Subscribe to multiple chains in a single view: ```typescript theme={null} client.streams.subscribe('pulse-v2', { assetMode: true, views: [ { name: 'new-multichain', model: 'new', chainId: ['solana:solana', 'evm:56', 'evm:8453', 'evm:1'], limit: 50, }, ], }); ``` Or use separate views per chain for independent control: ```typescript theme={null} client.streams.subscribe('pulse-v2', { assetMode: true, views: [ { name: 'new-sol', model: 'new', chainId: ['solana:solana'], limit: 30 }, { name: 'new-bsc', model: 'new', chainId: ['evm:56'], limit: 30 }, { name: 'new-base', model: 'new', chainId: ['evm:8453'], limit: 30 }, ], }); ``` *** ## Custom WSS URLs The SDK lets you override WebSocket endpoints per stream type: ```typescript theme={null} const client = new MobulaClient({ restUrl: 'https://pulse-v2-api.mobula.io', apiKey: 'YOUR_API_KEY', wsUrlMap: { 'pulse-v2': 'wss://pulse-v2-api.mobula.io', 'pulse-v2-pause': 'wss://pulse-v2-api.mobula.io', }, }); ``` MTT uses this to allow users to configure custom endpoints from the UI (stored in localStorage). *** ## Unsubscribing and Cleanup Always clean up subscriptions when your component unmounts or when you no longer need the data: ```typescript theme={null} // Store the subscription ID const subscriptionId = client.streams.subscribe('pulse-v2', payload, callback); // Later — unsubscribe cleanly await client.streams.unsubscribe('pulse-v2', subscriptionId); // Or close the entire WebSocket connection for this stream type client.streams.close('pulse-v2'); ``` In React, handle this in a cleanup function: ```typescript theme={null} useEffect(() => { const id = client.streams.subscribe('pulse-v2', payload, handleMessage); return () => { client.streams.unsubscribe('pulse-v2', id); }; }, [payload]); ``` *** ## Full React Example Here's a minimal but complete React hook for Pulse V2, inspired by MTT's implementation: ```typescript theme={null} import { useEffect, useRef, useState, useMemo, useCallback } from 'react'; import { MobulaClient } from '@mobula/sdk'; interface PulseToken { address?: string; chainId?: string; name?: string; symbol?: string; logo?: string; marketCap?: number; holders_count?: number; price_change_24h?: number; created_at?: string; [key: string]: unknown; } type ViewName = 'new' | 'bonding' | 'bonded'; export function usePulseStream(apiKey: string, chainIds: string[] = ['solana:solana']) { const clientRef = useRef(null); const subIdRef = useRef (null); const [tokens, setTokens] = useState >({ new: [], bonding: [], bonded: [], }); const [loading, setLoading] = useState(true); const getClient = useCallback(() => { if (!clientRef.current) { clientRef.current = new MobulaClient({ restUrl: 'https://pulse-v2-api.mobula.io', apiKey, }); } return clientRef.current; }, [apiKey]); const payload = useMemo(() => ({ assetMode: true, compressed: false, views: [ { name: 'new', model: 'new' as const, chainId: chainIds, limit: 50 }, { name: 'bonding', model: 'bonding' as const, chainId: chainIds, limit: 50 }, { name: 'bonded', model: 'bonded' as const, chainId: chainIds, limit: 50 }, ], }), [chainIds]); useEffect(() => { const client = getClient(); // 1. REST for fast initial load client.fetchPulseV2(payload).then((data) => { setTokens({ new: Array.isArray(data.new?.data) ? data.new.data : [], bonding: Array.isArray(data.bonding?.data) ? data.bonding.data : [], bonded: Array.isArray(data.bonded?.data) ? data.bonded.data : [], }); setLoading(false); }); // 2. WebSocket for live updates subIdRef.current = client.streams.subscribe('pulse-v2', payload, (msg: any) => { if (msg.type === 'init') { setTokens({ new: Array.isArray(msg.payload.new?.data) ? msg.payload.new.data : [], bonding: Array.isArray(msg.payload.bonding?.data) ? msg.payload.bonding.data : [], bonded: Array.isArray(msg.payload.bonded?.data) ? msg.payload.bonded.data : [], }); setLoading(false); } if (msg.type === 'update-token' || msg.type === 'new-token') { const { viewName, token } = msg.payload; setTokens((prev) => { const view = prev[viewName as ViewName] || []; const idx = view.findIndex((t) => t.address === token.address); const updated = idx >= 0 ? view.map((t, i) => (i === idx ? { ...t, ...token } : t)) : [token, ...view].slice(0, 50); return { ...prev, [viewName]: updated }; }); } }); return () => { if (subIdRef.current) { client.streams.unsubscribe('pulse-v2', subIdRef.current); subIdRef.current = null; } }; }, [getClient, payload]); return { tokens, loading }; } ``` *** ## Next Steps # Get all Historical Transactions of a Crypto Wallet Source: https://docs.mobula.io/guides/query-all-historical-transactions-of-a-crypto-wallet Learn how to retrieve a complete history of transactions for any EVM-compatible wallet using the Mobula API. This guide covers methods for obtaining detailed transaction data, including filtering by date, type, and blockchain. The Mobula API allows for an in-depth exploration of all historical transactions associated with EVM-compatible wallets. This comprehensive guide will show you how to effectively use the API to access this data. ### What you'll need 1. An EVM-compatible wallet address. 2. An idea of what you want to build 3. An API key from the [Dashboard](https://admin.mobula.io) (only for production use, you can use the API without an API key in development mode) ### Walkthrough Full API reference with all parameters and response schemas Complete filter reference with operators and examples Step-by-step guide to building a complete Pulse UI with Next.js Explore the full open-source trading terminal ### Leveraging Transaction Data With this data, you can: * **Track Wallet Activity**: Observe the frequency and types of transactions over time. * **Analyze Spending Patterns**: Gain insights into how the wallet interacts with various tokens and blockchains. * **Build Financial Histories**: Compile comprehensive financial records for wallets, useful for audits or portfolio analysis. ### Need Help? Our support team is available to assist with your queries or integration issues. Identify the wallet address for your query. Optionally, specify filters like transaction types, blockchains, and date ranges. Execute the API call using cURL, Axios, or the Mobula SDK (Beta): **Using cURL**: ```bash theme={null} curl --location --request GET 'https://api.mobula.io/api/1/wallet/transactions?wallet=0x77A89C51f106D6cD547542a3A83FE73cB4459135' ``` **Using Axios**: ```javascript theme={null} fetch('https://api.mobula.io/api/1/wallet/transactions?wallet=0x77A89C51f106D6cD547542a3A83FE73cB4459135').then(response => response.json()) .then(response => console.log(response.data)) .catch(error => console.log(error)); ``` The API response will include detailed transaction records, such as timestamps, transaction types, amounts, and blockchain specifics. ```json theme={null} { "data": { "transactions": [ { "timestamp": 1650788305000, "asset": { "name": "StaySAFU", "symbol": "SAFU", "id": 3, "contract": "0x890cc7d14948478c98a6cd7f511e1f7f7f99f397", "logo": "https://metacore.mobula.io/4ed4daf3f124fae650cfab146ae7348cdb62920bc25bf6408698654835192a1b.png" }, "type": "buy", "method_id": null, "hash": "0x0768d341245f70010d2a326062b6d46f76c794fc46ef0f6a75802cf66493cc54", "blockchain": "BNB Smart Chain (BEP20)", "amount": 4.95, "amount_usd": 41.255, "to": "0x77a89c51f106d6cd547542a3a83fe73cb4459135", "from": "0xbb663a119193ca68512c351b0fdfdeb9c22dc416" }, { "timestamp": 1651854030000, "asset": { "name": "Polygon", "symbol": "MATIC", "id": 100007238, "contract": "0x0d500b1d8e8ef31e21c99d1db9a6444d3adf1270", "logo": "https://metacore.mobula.io/22884f2d889a75fd9715538bf8c4ffedfd91766e8b3a886128dd9495521deca7.png" }, "type": "buy", "method_id": "0x", "hash": "0xa09eb4063df609101f94cdaff14ee936e10304501f88ba7bee58b290f86db3b9", "blockchain": "Polygon", "amount": 11, "amount_usd": 11.485, "to": "0x77a89c51f106d6cd547542a3a83fe73cb4459135", "from": "0x0490d25a95befdde088c8a3d741b5afba29cb8d9" }, { "timestamp": 1652261163000, "asset": { "name": "Mobula", "symbol": "MOBL", "id": 222, "contract": "0x5fef39b578deeefa4485a7e5944c7691677d5dd4", "logo": "https://mobula.mypinata.cloud/ipfs/QmTn6CLSsURsMfEwQA4o5SwBJKjrHJrtuYcNKd14kdJ77o?pinataGatewayToken=WQn5Yv-xwpvoa6O4Kc6yMwL4kG-UCFSmo0FL2pcIRAdN-V8XYVaL7udtsC7R3_Nm" }, "type": "buy", "method_id": null, "hash": "0xa52485281b07659f91b63d9e1924871cb6f90b666255d24dd03bd0febed0cdaf", "blockchain": "Polygon", "amount": 1, "amount_usd": 0, "to": "0x77a89c51f106d6cd547542a3a83fe73cb4459135", "from": "0x0490d25a95befdde088c8a3d741b5afba29cb8d9" } // ... more transactions ... ] } } ``` # Get any Crypto Balance for a Wallet Source: https://docs.mobula.io/guides/query-any-crypto-balance-from-a-wallet Easily access the balance and holdings of any EVM-compatible or Solana wallet using the Mobula API, with flexible options for blockchain filtering, caching, and handling stale data Mobula API provides a convenient way to access wallet balances and asset distributions for EVM-compatible and Solana wallets. This guide details the steps to query wallet holdings. ### What you'll need 1. Basic knowledge of RESTful APIs and JavaScript. 2. An EVM-compatible or Solana wallet address. 3. Optional: Preferences for specific blockchains, cache settings, and stale data handling. ### Walkthrough Telegram Slack Discord ### Extending Your Insights With the retrieved data, you can: * **Analyze Asset Allocation**: Gain insights into how assets are distributed across different blockchains. * **Monitor Portfolio Performance**: Track the total wallet balance and individual asset trends. * **Develop Financial Applications**: Integrate this data into financial management tools or investment analysis platforms. ### Need Assistance? Our support team is ready to help you with any questions or integration challenges. Decide on the wallet address to query. You can also specify blockchains, cache options, and staleness parameters according to your needs. Make the API call using cURL, Axios, or the Mobula SDK (Beta): **Using cURL**: ```bash theme={null} curl --location --request GET 'https://api.mobula.io/api/1/wallet/portfolio?wallet=0x77A89C51f106D6cD547542a3A83FE73cB4459135' ``` **Using Axios**: ```javascript theme={null} fetch('https://api.mobula.io/api/1/wallet/portfolio?wallet=0x77A89C51f106D6cD547542a3A83FE73cB4459135').then(response => response.json()) .then(response => console.log(response.data)) .catch(error => console.log(error)); ``` The API will return a comprehensive response including the wallet balance, individual asset details, and blockchain information. ```json theme={null} { "data": { "total_wallet_balance": 241.03441553241606, "wallet": "0x77A89C51f106D6cD547542a3A83FE73cB4459135", "assets": [ { "asset": { "name": "StaySAFU", "symbol": "SAFU", "id": 3, "contracts": ["0x890cc7d14948478c98a6cd7f511e1f7f7f99f397"], "logo": "https://metacore.mobula.io/4ed4daf3f124fae650cfab146ae7348cdb62920bc25bf6408698654835192a1b.png" }, "price": 2.5182506506214875, "estimated_balance": 0.19400291001132328, "token_balance": 0.077038761, "cross_chain_balances": { "BNB Smart Chain (BEP20)": { "address": "0x890cc7d14948478c98a6cd7f511e1f7f7f99f397", "balance": 0.077038761, "balanceRaw": "77038761", "chainId": 56 } } }, { "asset": { "name": "Mobula", "symbol": "MOBL", "id": 222, "contracts": [ "0x33b3a50c766dd3e61b1e90b251390e7c28aefb7c", "0xae85d5aa526b1ecc5e90e466cbd2bdec22c606ff", "0x5fef39b578deeefa4485a7e5944c7691677d5dd4" ], "logo": "https://mobula.mypinata.cloud/ipfs/QmTn6CLSsURsMfEwQA4o5SwBJKjrHJrtuYcNKd14kdJ77o?pinataGatewayToken=WQn5Yv-xwpvoa6O4Kc6yMwL4kG-UCFSmo0FL2pcIRAdN-V8XYVaL7udtsC7R3_Nm" }, "price": 0, "estimated_balance": 0, "token_balance": 7254.324894349606, "cross_chain_balances": { "BNB Smart Chain (BEP20)": { "address": "0x33b3a50c766dd3e61b1e90b251390e7c28aefb7c", "balance": 193, "balanceRaw": "193000000000000000000", "chainId": 56 }, "Polygon": { "address": "0x5fef39b578deeefa4485a7e5944c7691677d5dd4", "balance": 7061.324894349606, "balanceRaw": "7.061324894349606e+21", "chainId": 137 } } } // ... other assets ... ] } } ``` # Get any Crypto Price Source: https://docs.mobula.io/guides/query-any-crypto-price Fetch from symbol, address, name aggregated price, volume, price change of any crypto - from Monero to the latest shitcoin on your favorite L2. Mobula API allows you to query market data from any kind of assets in a unified way. You can query any crypto price, volume, price change, and more from any blockchain supported (check [here](/rest-api-reference/endpoint/blockchains) for the full list) or asset listed on Mobula curated token list (explorable [here](https://mobula.io)). ### What you'll need 1. An idea of what you want to build 2. An API key from the [Dashboard](https://admin.mobula.io) (only for production use, you can use the API without an API key in development mode) ### Walkthrough Telegram Slack Discord ### Go further Cool! We're done with the basics. Here's a few more things you can do with Mobula API: * Fetch up to 500 assets at once with `market/multi-data` endpoint (check [here](/rest-api-reference/endpoint/market-multi-data) for more details) * Subscribe to real-time price updates with WebSockets (contact us on [Telegram](https://t.me/mobuladevelopers?start=WSS_Guide) for more details) * Fetch historical price data with `market/history` endpoint (check [here](/rest-api-reference/endpoint/market-history) for more details) ### Need help? Can’t find what you’re looking for? Reach out to us, response times \< 1h. Pick your asset symbol, name or address. If it is a symbol/name, make sure to check case sensitivity and to respect the asset name as listed on Mobula curated token list (explorable [here](https://mobula.io)). If it is an address, make sure to check the blockchain supported (check [here](/rest-api-reference/endpoint/blockchains) for the full list) and to respect the blockchain ID format. You can call Mobula API directly from your terminal using cURL or any HTTP client. ```bash theme={null} curl --location --request GET 'https://api.mobula.io/api/1/market/data?asset=Bitcoin' \ --header 'Content-Type: application/json' \ --header 'Authorization: YOUR_API_KEY_HERE' ``` or a basic HTTP client: ```typescript theme={null} fetch('https://api.mobula.io/api/1/market/data?asset=Bitcoin').then(response => response.json()) .then(function (response) { console.log(response); }) .catch(function (error) { console.log(error); }) ``` You will get a response with the following format: ```json theme={null} { "data": { "market_cap": 843024041586, "market_cap_diluted": 903697702893, "liquidity": 158895577, "liquidity_change_24h": 26.329614639282227, "price": 43033.22394727512, "off_chain_volume": 18370240881, "volume": 184557344, "volume_change_24h": 41.50541687011719, "volume_7d": 191757056, "is_listed": true, "price_change_24h": -0.5605395, "price_change_1h": 0.21656898, "price_change_7d": 1.4587651, "price_change_1m": 21.078182, "price_change_1y": 141.66528, "ath": 67617.0155448617, "atl": 67.809 } } ``` ``` ``` # Get any Transactions of a Crypto Wallet Source: https://docs.mobula.io/guides/query-any-crypto-transactions-from-a-wallet Discover how to access any transaction of a crypto wallet using the Mobula API. This guide provides insights on fetching real-time and historical transaction data for any EVM-compatible wallet, with options for filtering and detailed analysis. Mobula API offers powerful tools to fetch real-time and historical transaction data from EVM-compatible wallets. Follow this guide to master the process of retrieving any transaction, filtered by your specific criteria. ### What you'll need 1. An EVM-compatible wallet address. 2. An understanding of your project's requirements. 3. An API key from the [Mobula Dashboard](https://admin.mobula.io) (required for production; optional in development mode). ### Walkthrough Telegram Slack Discord ### Utilizing Transaction Data With the retrieved information, you can: * **Monitor Wallet Transactions**: Keep an eye on incoming and outgoing transactions in real-time or historically. * **Understand Wallet Interactions**: Learn how the wallet engages with different cryptocurrencies and blockchains. * **Create Detailed Transaction Reports**: Develop comprehensive transaction histories for wallets, crucial for financial tracking or analysis. ### Support and Assistance Our expert support team is on hand to help with any inquiries or issues with API integration. Select the wallet address you wish to investigate. You have the option to filter by transaction type, specific assets, blockchain networks, and timeframes. Make the API call using your preferred method - cURL, Axios, or the Mobula SDK (Beta): **Using cURL**: ```bash theme={null} curl --location --request GET 'https://api.mobula.io/api/1/wallet/transactions?wallet=0x77A89C51f106D6cD547542a3A83FE73cB4459135' ``` **Using Axios**: ```javascript theme={null} fetch('https://api.mobula.io/api/1/wallet/transactions?wallet=0x77A89C51f106D6cD547542a3A83FE73cB4459135').then(response => response.json()) .then(response => console.log(response.data)) .catch(error => console.log(error)); ``` The API's response will include a wealth of information, including transaction timestamps, types, amounts, and specific blockchain data. ```json theme={null} { "data": { "transactions": [ { "timestamp": 1650788305000, "asset": { "name": "StaySAFU", "symbol": "SAFU", "id": 3, "contract": "0x890cc7d14948478c98a6cd7f511e1f7f7f99f397", "logo": "https://metacore.mobula.io/4ed4daf3f124fae650cfab146ae7348cdb62920bc25bf6408698654835192a1b.png" }, "type": "buy", "method_id": null, "hash": "0x0768d341245f70010d2a326062b6d46f76c794fc46ef0f6a75802cf66493cc54", "blockchain": "BNB Smart Chain (BEP20)", "amount": 4.95, "amount_usd": 41.255, "to": "0x77a89c51f106d6cd547542a3a83fe73cb4459135", "from": "0xbb663a119193ca68512c351b0fdfdeb9c22dc416" }, { "timestamp": 1651854030000, "asset": { "name": "Polygon", "symbol": "MATIC", "id": 100007238, "contract": "0x0d500b1d8e8ef31e21c99d1db9a6444d3adf1270", "logo": "https://metacore.mobula.io/22884f2d889a75fd9715538bf8c4ffedfd91766e8b3a886128dd9495521deca7.png" }, "type": "buy", "method_id": "0x", "hash": "0xa09eb4063df609101f94cdaff14ee936e10304501f88ba7bee58b290f86db3b9", "blockchain": "Polygon", "amount": 11, "amount_usd": 11.485, "to": "0x77a89c51f106d6cd547542a3a83fe73cb4459135", "from": "0x0490d25a95befdde088c8a3d741b5afba29cb8d9" }, { "timestamp": 1652261163000, "asset": { "name": "Mobula", "symbol": "MOBL", "id": 222, "contract": "0x5fef39b578deeefa4485a7e5944c7691677d5dd4", "logo": "https://mobula.mypinata.cloud/ipfs/QmTn6CLSsURsMfEwQA4o5SwBJKjrHJrtuYcNKd14kdJ77o?pinataGatewayToken=WQn5Yv-xwpvoa6O4Kc6yMwL4kG-UCFSmo0FL2pcIRAdN-V8XYVaL7udtsC7R3_Nm" }, "type": "buy", "method_id": null, "hash": "0xa52485281b07659f91b63d9e1924871cb6f90b666255d24dd03bd0febed0cdaf", "blockchain": "Polygon", "amount": 1, "amount_usd": 0, "to": "0x77a89c51f106d6cd547542a3a83fe73cb4459135", "from": "0x0490d25a95befdde088c8a3d741b5afba29cb8d9" } // ... more transactions ... ] } } ``` # Get the Blockchain Logo Source: https://docs.mobula.io/guides/query-blockchain-logos It is crucial for applications and websites displaying information on blockchains to show the most accurate information possible. Mobula API simplifies blockchain logo retrieval, helping developers and content creators save time. ### What you'll need Basic knowledge of RESTful APIs and JavaScript. ### Walkthrough Telegram Slack Discord ### Extending Your Insights With the retrieved data, you can: * **Branding and User Interface Design**: Use blockchain and token logos in your app's interface. * **Marketing Materials**: Use logos in marketing materials to visually represent supported blockchains and tokens. * **Comparison and Analytics Tools**: Display logos with financial data in analytics tools for clear visual references. ### Need Help? Our support team is available to assist you with any questions or challenges in using the API. Retrieve logos directly using cURL or any HTTP client: **Using cURL**: ```bash theme={null} curl --request GET \ --url https://api.mobula.io/api/1/blockchains ``` **Using Axios**: ```javascript theme={null} fetch('https://api.mobula.io/api/1/blockchains').then(response => response.json()) .then(function (response) { console.log(response); }) .catch(function (error) { console.log(error); }) ``` To access the blockchain logo, use the URL specified under the *logo* key in the data. For additional details such as RPC endpoints, explorer links, and information on specific tokens, refer to the corresponding keys. ```json theme={null} { "data": [ { "name": "Base", "chainId": "8453", "evmChainId": 8453, "rpcs": ["https://developer-access-mainnet.base.org"], "explorer": "https://basescan.org", "logo": "https://dd.dexscreener.com/ds-data/chains/base.png", "eth": { "name": "Ethereum", "symbol": "ETH", "decimals": 18, "address": "0x4200000000000000000000000000000000000006", "type": "eth", "logo": "https://metacore.mobula.io/d90e937d915ab0c865ff6e335361386c56524d4d33fb66f2f04defe1500082eb.png", "id": 100004304 }, "stable": { "symbol": "AXLUSDC", "name": "axlUSDC", "logo": "https://s2.coinmarketcap.com/static/img/coins/64x64/3408.png", "contracts": [ "0x1b6382dbdea11d97f24495c9a90b7c88469134a4", "0xfab550568c688d5d8a52c7d794cb93edc26ec0ec", "0x750e4c4984a9e0f12978ea6742bc1c5d248f40ed", "0xca01a1d0993565291051daff390892518acfad3a", "0xeb466342c4d449bc9f53a865d5cb90586f405215" ], "blockchains": ["Fantom", "Avalanche C-Chain", "Polygon", "Moonbeam", "Base"], "blockchain": "Base", "address": "0xeb466342c4d449bc9f53a865d5cb90586f405215", "decimals": 6, "type": "stable" }, "routers": [ { "name": "RocketSwap", "address": "0x4cf76043b3f97ba06917cbd90f9e3a2aac1b306e", "factory": "0x1b8128c3a1b7d20053d10763ff02466ca7ff99fc", "fee": 9970 } ], "tokens": [ { "name": "Ethereum", "symbol": "ETH", "address": "0x4200000000000000000000000000000000000006", "decimals": 18, "type": "eth" }, { "name": "axlUSDC", "symbol": "AXLUSDC", "address": "0xeb466342c4d449bc9f53a865d5cb90586f405215", "decimals": 6, "type": "stable" } ], "supportedProtocols": ["forkV2"], "color": "#0052FE", "dexscreenerChain": "base", "coingeckoChain": "base", "isLayer2": true, "coverage": ["metadata", "market", "explorer"] } ] } ``` To access the blockchain logo, refer to the URL specified in the 'logo' key. # Get Historical Balance of any Crypto Wallet Source: https://docs.mobula.io/guides/query-historical-balance-of-a-crypto-wallet Learn how to retrieve the historical balance data of any EVM-compatible crypto wallet using the Mobula API. This guide provides a comprehensive walkthrough for accessing past balance records, offering insights into wallet value fluctuations over time. Mobula API enables the retrieval of historical balance data from EVM-compatible crypto wallets. This tutorial will guide you through the process of fetching and analyzing the historical balance of a wallet. ### What you'll need 1. An EVM-compatible wallet address for querying. 2. An API key from the [Dashboard](https://admin.mobula.io) (only for production use, you can use the API without an API key in development mode). ### Walkthrough Telegram Slack Discord ### Extending Your Insights With the historical balance data, you can: * **Track Value Fluctuations**: Observe how the wallet's value has changed over specified periods. * **Identify Trends**: Spot patterns or significant events in the wallet's history. * **Incorporate Data into Applications**: Use this historical data for financial analysis, trading strategies, or portfolio management tools. ### Need Assistance? Our support team is ready to help you with any queries or integration challenges. Select the wallet address for which you want to query historical balance data. Optionally, decide if you want to filter the data by blockchain or specific time intervals. Utilize cURL, Axios, or the Mobula SDK (Beta) to make the API request: **Using cURL**: ```bash theme={null} curl --request GET \ --url 'https://api.mobula.io/api/1/wallet/history?wallet=0x77A89C51f106D6cD547542a3A83FE73cB4459135&from=1650788304000&to=1651940430000' ``` **Using Axios**: ```javascript theme={null} fetch('https://api.mobula.io/api/1/wallet/history?wallet=0x77A89C51f106D6cD547542a3A83FE73cB4459135&from=1650788304000&to=1651940430000').then(response => response.json()) .then(response => console.log(response.data)) .catch(error => console.log(error)); ``` The API response will include detailed historical balance data, showing how the wallet's value has changed over time: ```json theme={null} { "data": { "wallet": [ "0x77a89c51f106d6cd547542a3a83fe73cb4459135" ], "balance_usd": 241.16725574204617, "balance_history": [ [1650788304000, 0], [1650788305000, 0], [1650874705000, 40.94737444508439], // ... other data points ... [1651940430000, 47.36438419453997] ] } } ``` # Get Price History of an Asset Source: https://docs.mobula.io/guides/query-historical-price-of-any-crypto Discover how to retrieve the historical price data of any cryptocurrency using the Mobula API. This guide offers a step-by-step walkthrough for accessing past price records, providing valuable insights into cryptocurrency market trends. ### What You'll Need: 1. An idea of what you want to build. 2. An API key from the [Dashboard](https://admin.mobula.io) (only for production use, you can use the API without an API key in development mode). 3. The name of the cryptocurrency asset or its smart-contract address for querying. *** ### Walkthrough: Telegram Slack Discord ### Extending Your Insights With the historical price data, you can: * **Analyze Market Trends**: Track the asset's price fluctuations over time. * **Assess Investment Opportunities**: Gain insights into potential investment decisions based on past price movements. * **Enhance Financial Models**: Integrate this data into financial models for more comprehensive analysis. ### Need Assistance? Our support team is ready to assist with any queries or integration challenges. Choose the cryptocurrency asset for your query. If using a smart-contract address, also specify the blockchain. Perform the API request using cURL, Axios, or the Mobula SDK (Beta): **Using cURL**: ```bash theme={null} curl --request GET \ --url 'https://api.mobula.io/api/1/market/history?asset=Floki&from=1697648158' ``` **Using Axios**: ```javascript theme={null} fetch('https://api.mobula.io/api/1/market/history?asset=Floki&from=1697648158').then(response => response.json()) .then(response => console.log(response.data)) .catch(error => console.log(error)); ``` The API will return a detailed history of the asset's price, including timestamps and price values: ```json theme={null} { "data": { "price_history": [ [1624623325000, 1.113340820039224e-9], [1624626986000, 2.2957561345049817e-10], // Additional data points... [1683309600000, 1.7181969777003686e-7] ] } } ``` # Get Latest Created Pairs Source: https://docs.mobula.io/guides/query-latest-created-pairs Staying updated with the latest created pairs on various exchanges can provide a critical edge in market analysis and trading strategies. Mobula API delivers precise and immediate data on newly created trading pairs, enabling traders and developers to tap into new market opportunities as they emerge. This guide details the steps to query data for newly created pairs. ### What you’ll need 1. Basic knowledge of RESTful APIs and JavaScript. 2. Optional: Preferences for specific blockchains, cache settings, and stale data handling. 3. An API key from the [Dashboard](https://admin.mobula.io) (required for production; optional in development mode). ### Walkthrough Telegram Slack Discord ### Extending Your Insights With this information, you can: * **Develop Financial Applications**: Integrate this data into financial management tools or investment analysis platforms. * **Assess Investment Opportunities**: Gain insights into potential investment decisions based on most traded pairs. ### Need Assistance? Our support team is ready to assist with any queries or integration challenges. You can call Mobula API directly from your terminal using cURL or any HTTP client. **Using cURL**: ```bash theme={null} curl --request GET \ --url 'https://api.mobula.io/api/1/market/query/token?sortBy=listed_at&sortOrder=desc&blockchain=Base' ``` **Using Axios**: ```javascript theme={null} fetch('https://api.mobula.io/api/1/market/query/token?sortBy=listed_at&sortOrder=desc&blockchain=Base').then(response => response.json()) .then(function (response) { console.log(response); }) .catch(function (error) { console.log(error); }) ``` The API will return a comprehensive response that includes details on trading pairs, featuring each token's address and detailed price token statistics. ```json theme={null} { "data": [ { "name": "USDe", "symbol": "USDe", "address": "0xf290be4044bfbe8150eff82c2d33b9cdfd342b35", "blockchain": "Base", "decimals": 18, "volume_24h": 0, "listed_at": "2024-05-28T14:47:19+00:00", "pairs": [ { "token0": { "address": "0x4200000000000000000000000000000000000006", "price": 3847.361963243166, "priceToken": 367771.4257120958, "priceTokenString": "367771.42571209580637514591217041015625", "logo": "https://metacore.mobula.io/d90e937d915ab0c865ff6e335361386c56524d4d33fb66f2f04defe1500082eb.png", "approximateReserveUSD": 10108.570360463622, "approximateReserveTokenRaw": "2627402999000000000", "approximateReserveToken": 2.6274, "symbol": "ETH", "name": "Ethereum", "id": 100004304, "decimals": 18, "totalSupply": 120129946, "circulatingSupply": 120364095 }, "token1": { "address": "0xf290be4044bfbe8150eff82c2d33b9cdfd342b35", "price": 0.010461285717871442, "priceToken": 0.0000027190801951613134, "priceTokenString": "0.00000271908019516131338716002225", "approximateReserveUSD": 0, "approximateReserveTokenRaw": "966283746862466389448279", "approximateReserveToken": 966283.7468, "decimals": 18, "symbol": "USDe", "name": "USDe", "totalSupply": 1000000, "circulatingSupply": 1000000 }, "volume24h": 0, "liquidity": 10108.570360463622, "blockchain": "Base", "address": "0x8662e57fc31dab9e256187728ab085a4fa3917b6", "createdAt": "2024-05-28T14:47:19.000Z", "type": "univ2", "baseToken": "token1", "factory": "0x8909dc15e40173ff4699343b6eb8132c65e18ec6", "quoteToken": "token0", "price_change_5min": 0, "price_change_1h": 0, "price_change_4h": 0, "price_change_12h": 0, "price_change_24h": 0, "trades_5min": 0, "buys_5min": 0, "sells_5min": 0, "volume_5min": 0, "buy_volume_5min": 0, "sell_volume_5min": 0, "trades_1h": 0, "buys_1h": 0, "sells_1h": 0, "volume_1h": 0, "buy_volume_1h": 0, "sell_volume_1h": 0, "trades_4h": 0, "buys_4h": 0, "sells_4h": 0, "volume_4h": 0, "buy_volume_4h": 0, "sell_volume_4h": 0, "trades_12h": 0, "buys_12h": 0, "sells_12h": 0, "volume_12h": 0, "buy_volume_12h": 0, "sell_volume_12h": 0, "trades_24h": 0, "buys_24h": 0, "sells_24h": 0, "volume_24h": 0, "buy_volume_24h": 0, "sell_volume_24h": 0 } ] } ] } ``` # Get Newly Listed Tokens Onchain Source: https://docs.mobula.io/guides/query-newly-listed-tokens-onchain The rapidly changing cryptocurrency market makes monitoring newly listed tokens crucial. Mobula’s Pulse API provides real-time visibility into `newly listed`, `bonded`, and `bonding` tokens across **multiple blockchains**. This guide explains how to retrieve and analyze these on-chain events efficiently using the Pulse API endpoint. ### What you’ll need 1. Basic knowledge of RESTful APIs and JavaScript. 2. Optional: Preferences for specific blockchains, cache settings, and stale data handling. 3. An API key from the [Dashboard](https://admin.mobula.io) (required for production; optional in development mode). ### Walkthrough The Best THinf fot rhits is Pulse uou can use pulse endpoint to list out all new listed endpoint BaseEndpoint: [https://api.mobula.io](https://api.mobula.io) Telegram Slack Discord ### Extending Your Insights With this information, you can: * **Reverse Discovery**: Monitor blockchains in real time to identify newly listed tokens. Use query parameters to filter by pools and token states (`bonded`, `bonding`, or `new`), then perform your due diligence before investing. * **Pulse Documentation** :Access all newly listed and recently migrated tokens directly through the [Pulse POST endpoint](/rest-api-reference/endpoint/pulse-post) * **Analytic Integration**: Use blockchain activity data to power a tool that delivers statistical insights on blockchain performance. ### Need Help? Our support team is available to assist you with any questions or challenges in using the API. You can call Mobula API directly from your terminal using cURL or any HTTP client. **Using cURL**: ```bash theme={null} curl --request POST \ --url 'https://api.mobula.io/api/2/pulse' \ --header 'Content-Type: application/json' \ --data '{"assetMode":false,"chainId":["solana:solana"],"model":"default"}' ``` **Using Axios**: ```javascript theme={null} fetch('https://api.mobula.io/api/2/pulse', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ assetMode: false, chainId: ['solana:solana'], model: 'default' }), }).then(response => response.json()) .then(function (response) { console.log(response); }) .catch(function (error) { console.log(error); }) ``` The API will return a comprehensive response including the token's blockchain, address, creation date, pair type, transaction statistics, and details of the tokens forming trading pairs. ```json theme={null} { "new": { "data": [ { "address": "HqmRhb2nm5f3hEBHojpcVhuceecQkpGhC1ru5Vo5Qw3E", "chainId": "solana:solana", "symbol": "ON.✨", "name": "Orochi.✨", "decimals": 6, "id": 0, "price": 0.0018887643721193443, "priceToken": 0.000009801167227562427, "priceTokenString": "0.00000980116722756242657744584629", "approximateReserveUSD": 1507176.1759337373, "approximateReserveTokenRaw": "797969401679557", "approximateReserveToken": 797969401.679557, "totalSupply": 1000000000, "circulatingSupply": 1000000000, "marketCap": 1888764.3721193443, "marketCapDiluted": 1888764.3721193443, "logo": "https://pbs.twimg.com/profile_images/1877208842834161666/DosXGKCB_400x400.jpg", "exchange": { "name": "Meteora DBC", "logo": "https://metadata.mobula.io/assets/logos/dbcij3LWUppWqq96dh6gJWwBifmcGfLSB5D4DuSMaqN.webp" }, "factory": "dbcij3LWUppWqq96dh6gJWwBifmcGfLSB5D4DuSMaqN", "source": "meteora-dbc", "liquidity": 38547.78819747422, "liquidityMax": 1545723.9641312116, "bonded": false, "bondingPercentage": 0, "preBondingFactory": "dbcij3LWUppWqq96dh6gJWwBifmcGfLSB5D4DuSMaqN", "poolAddress": "A25oVn9UyZeoSBTJXgL8uEes2Ezp5f8eAktHayZ7KayC", "blockchain": "Solana", "type": "meteora-dbc", "deployer": "7sDgzzETS1y2BgMAy2678i29aJDJvd2FkAyEPX7SA66A", "createdAt": "2025-10-24T07:19:10.000Z", "ath": 0.001888412099352294, "atl": 0.0018881406009524455, "athDate": "2025-10-24T07:19:11.100Z", "atlDate": "2025-10-24T07:19:11.100Z", "bonded_at": null, "holdersCount": 5, "smartTradersHoldingsPercentage": 0, "insidersCount": 0, "bundlersCount": 0, "snipersCount": 0, "freshTradersCount": 0, "proTradersCount": 1, "smartTradersCount": 0, "freshTradersBuys": 0, "proTradersBuys": 1, "smartTradersBuys": 0, "top10Holdings": 20.2031332829597, "top50Holdings": 20.2031332829597, "top100Holdings": 20.2031332829597, "top200Holdings": 20.2031332829597, "devHoldings": 0, "insidersHoldings": 0, "bundlersHoldings": 0, "snipersHoldings": 0, "proTradersHoldings": 0, "freshTradersHoldings": 0, "token": { "address": "HqmRhb2nm5f3hEBHojpcVhuceecQkpGhC1ru5Vo5Qw3E", "chainId": "solana:solana", "symbol": "ON.✨", "name": "Orochi.✨", "decimals": 6, "id": 0, "price": 0.0018887643721193443, "priceToken": 0.000009801167227562427, "priceTokenString": "0.00000980116722756242657744584629", "approximateReserveUSD": 1507176.1759337373, "approximateReserveTokenRaw": "797969401679557", "approximateReserveToken": 797969401.679557, "totalSupply": 1000000000, "circulatingSupply": 1000000000, "marketCap": 1888764.3721193443, "marketCapDiluted": 1888764.3721193443, "logo": "https://pbs.twimg.com/profile_images/1877208842834161666/DosXGKCB_400x400.jpg", "exchange": { "name": "Meteora DBC", "logo": "https://metadata.mobula.io/assets/logos/dbcij3LWUppWqq96dh6gJWwBifmcGfLSB5D4DuSMaqN.webp" }, "factory": "dbcij3LWUppWqq96dh6gJWwBifmcGfLSB5D4DuSMaqN", "source": "meteora-dbc", "liquidity": 38547.78819747422, "liquidityMax": 1545723.9641312116, "bonded": false, "bondingPercentage": 0, "preBondingFactory": "dbcij3LWUppWqq96dh6gJWwBifmcGfLSB5D4DuSMaqN", "poolAddress": "A25oVn9UyZeoSBTJXgL8uEes2Ezp5f8eAktHayZ7KayC", "blockchain": "Solana", "type": "meteora-dbc", "deployer": "7sDgzzETS1y2BgMAy2678i29aJDJvd2FkAyEPX7SA66A", "createdAt": "2025-10-24T07:19:10.000Z", "ath": 0.001888412099352294, "atl": 0.0018881406009524455, "athDate": "2025-10-24T07:19:11.100Z", "atlDate": "2025-10-24T07:19:11.100Z", "bonded_at": null, "holdersCount": 5, "top10HoldingsPercentage": 20.2031332829597, "top50HoldingsPercentage": 20.2031332829597, "top100HoldingsPercentage": 20.2031332829597, "top200HoldingsPercentage": 20.2031332829597, "devHoldingsPercentage": 0, "insidersHoldingsPercentage": 0, "bundlersHoldingsPercentage": 0, "snipersHoldingsPercentage": 0, "proTradersHoldingsPercentage": 0, "freshTradersHoldingsPercentage": 0, "smartTradersHoldingsPercentage": 0, "insidersCount": 0, "bundlersCount": 0, "snipersCount": 0, "freshTradersCount": 0, "proTradersCount": 1, "smartTradersCount": 0, "freshTradersBuys": 0, "proTradersBuys": 1, "smartTradersBuys": 0 }, "dexscreenerHeader": null, "dexscreenerAdPaid": false, "latest_trade_date": null, "latest_price": 0.0018887643721193443, "price_change_1min": 0.028770969417868185, "price_change_5min": 0.028770969417868185, "price_change_1h": 0.028770969417868185, "price_change_4h": 0.028770969417868185, "price_change_6h": 0.028770969417868185, "price_change_12h": 0.028770969417868185, "price_change_24h": 0.028770969417868185, "price_1min_ago": 0, "price_5min_ago": 0, "price_1h_ago": 0, "price_4h_ago": 0, "price_6h_ago": 0, "price_12h_ago": 0, "price_24h_ago": 0, "volume_1min": 38541.59599480834, "volume_5min": 38541.59599480834, "volume_15min": 38541.59599480834, "volume_1h": 38541.59599480834, "volume_4h": 38541.59599480834, "volume_6h": 38541.59599480834, "volume_12h": 38541.59599480834, "volume_24h": 38541.59599480834, "volume_buy_1min": 38541.59599480834, "volume_buy_5min": 38541.59599480834, "volume_buy_15min": 38541.59599480834, "volume_buy_1h": 38541.59599480834, "volume_buy_4h": 38541.59599480834, "volume_buy_6h": 38541.59599480834, "volume_buy_12h": 38541.59599480834, "volume_buy_24h": 38541.59599480834, "volume_sell_1min": 0, "volume_sell_5min": 0, "volume_sell_15min": 0, "volume_sell_1h": 0, "volume_sell_4h": 0, "volume_sell_6h": 0, "volume_sell_12h": 0, "volume_sell_24h": 0, "buys_1min": 5, "buys_5min": 5, "buys_15min": 5, "buys_1h": 5, "buys_4h": 5, "buys_6h": 5, "buys_12h": 5, "buys_24h": 5, "sells_1min": 0, "sells_5min": 0, "sells_15min": 0, "sells_1h": 0, "sells_4h": 0, "sells_6h": 0, "sells_12h": 0, "sells_24h": 0, "trades_1min": 5, "trades_5min": 5, "trades_15min": 5, "trades_1h": 5, "trades_4h": 5, "trades_6h": 5, "trades_12h": 5, "trades_24h": 5, "buyers_1min": 5, "buyers_5min": 5, "buyers_15min": 5, "buyers_1h": 5, "buyers_4h": 5, "buyers_6h": 5, "buyers_12h": 5, "buyers_24h": 5, "sellers_1min": 0, "sellers_5min": 0, "sellers_15min": 0, "sellers_1h": 0, "sellers_4h": 0, "sellers_6h": 0, "sellers_12h": 0, "sellers_24h": 0, "traders_1min": 5, "traders_5min": 5, "traders_15min": 5, "traders_1h": 5, "traders_4h": 5, "traders_6h": 5, "traders_12h": 5, "traders_24h": 5, "fees_paid_1min": 0, "fees_paid_5min": 0, "fees_paid_15min": 0, "fees_paid_1h": 0, "fees_paid_4h": 0, "fees_paid_6h": 0, "fees_paid_12h": 0, "fees_paid_24h": 0, "totalFeesPaidUSD": 0, "description": null, "socials": { "twitter": "https://x.com/OrochiNetwork", "website": "https://onprover.orochi.network/", "telegram": null, "others": { "properties.category": "image", "properties.files": "{\"uri\":\"https://pbs.twimg.com/profile_images/1877208842834161666/DosXGKCB_400x400.jpg\",\"type\":\"image/*\"}", "properties.creators": "{\"address\":\"7sDgzzETS1y2BgMAy2678i29aJDJvd2FkAyEPX7SA66A\",\"share\":100}", "extensions.website": "https://onprover.orochi.network/", "extensions.homepage": "https://onprover.orochi.network/" }, "uri": "https://ipfs.io/ipfs/bafkreih53fpn45f2u6s36yjcpqailpl7izjdrhpy7dmyhl24zitoxrt43a" }, "security": null, "twitterReusesCount": 0, "twitterRenameCount": 0, "twitterRenameHistory": [], "deployerMigrationsCount": 0, "dexscreenerListed": false, "holders_list": [], "organic_trades_1min": 4, "organic_trades_5min": 4, "organic_trades_15min": 4, "organic_trades_1h": 4, "organic_trades_4h": 4, "organic_trades_6h": 4, "organic_trades_12h": 4, "organic_trades_24h": 4, "organic_volume_1min": 38541.59599480834, "organic_volume_5min": 38541.59599480834, "organic_volume_15min": 38541.59599480834, "organic_volume_1h": 38541.59599480834, "organic_volume_4h": 38541.59599480834, "organic_volume_6h": 38541.59599480834, "organic_volume_12h": 38541.59599480834, "organic_volume_24h": 38541.59599480834, "organic_buys_1min": 4, "organic_buys_5min": 4, "organic_buys_15min": 4, "organic_buys_1h": 4, "organic_buys_4h": 4, "organic_buys_6h": 4, "organic_buys_12h": 4, "organic_buys_24h": 4, "organic_sells_1min": 0, "organic_sells_5min": 0, "organic_sells_15min": 0, "organic_sells_1h": 0, "organic_sells_4h": 0, "organic_sells_6h": 0, "organic_sells_12h": 0, "organic_sells_24h": 0, "organic_buyers_1min": 4, "organic_buyers_5min": 4, "organic_buyers_15min": 4, "organic_buyers_1h": 4, "organic_buyers_4h": 4, "organic_buyers_6h": 4, "organic_buyers_12h": 4, "organic_buyers_24h": 4, "organic_sellers_1min": 0, "organic_sellers_5min": 0, "organic_sellers_15min": 0, "organic_sellers_1h": 0, "organic_sellers_4h": 0, "organic_sellers_6h": 0, "organic_sellers_12h": 0, "organic_sellers_24h": 0, "organic_traders_1min": 4, "organic_traders_5min": 4, "organic_traders_15min": 4, "organic_traders_1h": 4, "organic_traders_4h": 4, "organic_traders_6h": 4, "organic_traders_12h": 4, "organic_traders_24h": 4, "organic_volume_buy_1min": 38541.59599480834, "organic_volume_buy_5min": 38541.59599480834, "organic_volume_buy_15min": 38541.59599480834, "organic_volume_buy_1h": 38541.59599480834, "organic_volume_buy_4h": 38541.59599480834, "organic_volume_buy_6h": 38541.59599480834, "organic_volume_buy_12h": 38541.59599480834, "organic_volume_buy_24h": 38541.59599480834, "organic_volume_sell_1min": 0, "organic_volume_sell_5min": 0, "organic_volume_sell_15min": 0, "organic_volume_sell_1h": 0, "organic_volume_sell_4h": 0, "organic_volume_sell_6h": 0, "organic_volume_sell_12h": 0, "organic_volume_sell_24h": 0, "created_at": "2025-10-24T07:19:10.000Z", "market_cap": 0, "latest_market_cap": 1888764.3721193443 }, ] }, "bonding": { "data": [ { "address": "8DcDpXBXBkNwe9kU6HqyJ8xVLiahzcLxvcYuTBL24fto", "chainId": "solana:solana", "symbol": "DOOM", "name": "Doomer", "decimals": 6, "id": 0, "price": 0.20041643014519284, "priceToken": 0.0010400000000000001, "priceTokenString": "0.00104000000000000012573275753880", "approximateReserveUSD": 0, "approximateReserveTokenRaw": "0", "approximateReserveToken": 0, "totalSupply": 999999312, "circulatingSupply": 999999312, "marketCap": 200416292.2586889, "marketCapDiluted": 200416292.2586889, "logo": null, "exchange": { "name": "Meteora", "logo": "https://metadata.mobula.io/assets/logos/LBUZKhRxPF3XUpBCjp4YzTKgLccjZhTSDM9YuVaPwxo.webp" }, "factory": "LBUZKhRxPF3XUpBCjp4YzTKgLccjZhTSDM9YuVaPwxo", "source": null, "sourceFactory": "6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P", "liquidity": 19782.47773361801, "liquidityMax": 39635.79022826627, "bonded": false, "bondingPercentage": 96.85954466754092, "preBondingFactory": "6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P", "poolAddress": "6DaQpcBxmQfPUxKTznfXaxj5E3nK8moQbrgorSX9LGpE", "blockchain": "Solana", "type": "meteora", "deployer": null, "createdAt": "2025-06-25T02:07:06.000Z", "ath": 0, "atl": 0, "athDate": "1970-01-01T00:00:00.000Z", "atlDate": "1970-01-01T00:00:00.000Z", "bonded_at": null, "holdersCount": 211, "smartTradersHoldingsPercentage": 0, "insidersCount": 0, "bundlersCount": 0, "snipersCount": 0, "freshTradersCount": 4, "proTradersCount": 81, "smartTradersCount": 1, "freshTradersBuys": 4, "proTradersBuys": 81, "smartTradersBuys": 1, "top10Holdings": 23.978690575940828, "top50Holdings": 63.927972469096616, "top100Holdings": 78.26123335558654, "top200Holdings": 82.63143146870384, "devHoldings": 0, "insidersHoldings": 0, "bundlersHoldings": 0, "snipersHoldings": 0, "proTradersHoldings": 0, "freshTradersHoldings": 0, "token": { "address": "8DcDpXBXBkNwe9kU6HqyJ8xVLiahzcLxvcYuTBL24fto", "chainId": "solana:solana", "symbol": "DOOM", "name": "Doomer", "decimals": 6, "id": 0, "price": 0.20041643014519284, "priceToken": 0.0010400000000000001, "priceTokenString": "0.00104000000000000012573275753880", "approximateReserveUSD": 0, "approximateReserveTokenRaw": "0", "approximateReserveToken": 0, "totalSupply": 999999312, "circulatingSupply": 999999312, "marketCap": 200416292.2586889, "marketCapDiluted": 200416292.2586889, "logo": null, "exchange": { "name": "Meteora", "logo": "https://metadata.mobula.io/assets/logos/LBUZKhRxPF3XUpBCjp4YzTKgLccjZhTSDM9YuVaPwxo.webp" }, "factory": "LBUZKhRxPF3XUpBCjp4YzTKgLccjZhTSDM9YuVaPwxo", "source": null, "sourceFactory": "6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P", "liquidity": 19782.47773361801, "liquidityMax": 39635.79022826627, "bonded": false, "bondingPercentage": 96.85954466754092, "preBondingFactory": "6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P", "poolAddress": "6DaQpcBxmQfPUxKTznfXaxj5E3nK8moQbrgorSX9LGpE", "blockchain": "Solana", "type": "meteora", "deployer": null, "createdAt": "2025-06-25T02:07:06.000Z", "ath": 0, "atl": 0, "athDate": "1970-01-01T00:00:00.000Z", "atlDate": "1970-01-01T00:00:00.000Z", "bonded_at": null, "holdersCount": 211, "top10HoldingsPercentage": 23.978690575940828, "top50HoldingsPercentage": 63.927972469096616, "top100HoldingsPercentage": 78.26123335558654, "top200HoldingsPercentage": 82.63143146870384, "devHoldingsPercentage": 0, "insidersHoldingsPercentage": 0, "bundlersHoldingsPercentage": 0, "snipersHoldingsPercentage": 0, "proTradersHoldingsPercentage": 0, "freshTradersHoldingsPercentage": 0, "smartTradersHoldingsPercentage": 0, "insidersCount": 0, "bundlersCount": 0, "snipersCount": 0, "freshTradersCount": 4, "proTradersCount": 81, "smartTradersCount": 1, "freshTradersBuys": 4, "proTradersBuys": 81, "smartTradersBuys": 1 }, "dexscreenerHeader": "https://cdn.dexscreener.com/cms/images/be3826494f8e5387a44a5f57ac7d049ddf04915fbcc994aaa5730a51b671fb2c?width=600&height=200&fit=crop&quality=95&format=auto", "dexscreenerAdPaid": false, "latest_trade_date": "2025-10-24T07:15:00.000Z", "latest_price": 0.20041643014519284, "price_change_1min": 0, "price_change_5min": -1.255297952631489, "price_change_1h": 1.005909794285214, "price_change_4h": -11.27931134678725, "price_change_6h": -15.29164893708496, "price_change_12h": 6.831272844322694, "price_change_24h": 64.34761472826176, "price_1min_ago": 0.00006514613827933418, "price_5min_ago": 0.00006597431247307135, "price_1h_ago": 0.00006449735308757158, "price_4h_ago": 0.00007342835055527391, "price_6h_ago": 0.00007690639407081421, "price_12h_ago": 0.00006098040072429618, "price_24h_ago": 0.00003963923564515928, "volume_1min": 0, "volume_5min": 70.8479339320045, "volume_15min": 645.9593838529815, "volume_1h": 1600.6194638230786, "volume_4h": 18215.421126196525, "volume_6h": 30172.00336230662, "volume_12h": 60432.42576605377, "volume_24h": 98803.59415807517, "volume_buy_1min": 0, "volume_buy_5min": 0, "volume_buy_15min": 0, "volume_buy_1h": 831.1008068346143, "volume_buy_4h": 8437.393788469839, "volume_buy_6h": 14191.97141984561, "volume_buy_12h": 30446.5646871764, "volume_buy_24h": 51200.49820915133, "volume_sell_1min": 0, "volume_sell_5min": 70.8479339320045, "volume_sell_15min": 645.9593838529815, "volume_sell_1h": 769.5186569884643, "volume_sell_4h": 9778.027337726686, "volume_sell_6h": 15980.03194246101, "volume_sell_12h": 29985.86107887737, "volume_sell_24h": 47603.09594892383, "buys_1min": 0, "buys_5min": 0, "buys_15min": 0, "buys_1h": 9, "buys_4h": 92, "buys_6h": 179, "buys_12h": 328, "buys_24h": 529, "sells_1min": 0, "sells_5min": 1, "sells_15min": 4, "sells_1h": 9, "sells_4h": 63, "sells_6h": 129, "sells_12h": 233, "sells_24h": 348, "trades_1min": 0, "trades_5min": 1, "trades_15min": 4, "trades_1h": 18, "trades_4h": 155, "trades_6h": 308, "trades_12h": 561, "trades_24h": 877, "buyers_1min": 0, "buyers_5min": 0, "buyers_15min": 0, "buyers_1h": 9, "buyers_4h": 72, "buyers_6h": 128, "buyers_12h": 265, "buyers_24h": 452, "sellers_1min": 0, "sellers_5min": 1, "sellers_15min": 4, "sellers_1h": 9, "sellers_4h": 59, "sellers_6h": 112, "sellers_12h": 213, "sellers_24h": 325, "traders_1min": 0, "traders_5min": 1, "traders_15min": 4, "traders_1h": 18, "traders_4h": 128, "traders_6h": 235, "traders_12h": 462, "traders_24h": 746, "fees_paid_1min": 0, "fees_paid_5min": 0, "fees_paid_15min": 0, "fees_paid_1h": 3.06561021360767, "fees_paid_4h": 108.8642145630536, "fees_paid_6h": 170.5319430169373, "fees_paid_12h": 395.3060391512968, "fees_paid_24h": 629.3590573363641, "totalFeesPaidUSD": 629.3590573363641, "description": null, "socials": { "twitter": "https://x.com/i/communities/1981090942502511053", "website": "https://knowyourmeme.com/memes/doomer", "telegram": null, "others": {} }, "security": { "buyTax": "0.0000", "sellTax": "0.0000", "top10Holders": "1.0001", "isBlacklisted": false, "balanceMutable": false, "noMintAuthority": true, "transferPausable": false }, "twitterReusesCount": 0, "twitterRenameCount": 0, "twitterRenameHistory": [], "deployerMigrationsCount": 3, "dexscreenerListed": true, "holders_list": [], "organic_trades_1min": 0, "organic_trades_5min": 1, "organic_trades_15min": 4, "organic_trades_1h": 18, "organic_trades_4h": 155, "organic_trades_6h": 308, "organic_trades_12h": 561, "organic_trades_24h": 877, "organic_volume_1min": 0, "organic_volume_5min": 70.8479339320045, "organic_volume_15min": 645.9593838529815, "organic_volume_1h": 1600.619463823079, "organic_volume_4h": 18215.42112619652, "organic_volume_6h": 30172.00336230662, "organic_volume_12h": 60432.42576605377, "organic_volume_24h": 98803.59415807517, "organic_buys_1min": 0, "organic_buys_5min": 0, "organic_buys_15min": 0, "organic_buys_1h": 9, "organic_buys_4h": 92, "organic_buys_6h": 179, "organic_buys_12h": 328, "organic_buys_24h": 529, "organic_sells_1min": 0, "organic_sells_5min": 1, "organic_sells_15min": 4, "organic_sells_1h": 9, "organic_sells_4h": 63, "organic_sells_6h": 129, "organic_sells_12h": 233, "organic_sells_24h": 348, "organic_buyers_1min": 0, "organic_buyers_5min": 0, "organic_buyers_15min": 0, "organic_buyers_1h": 9, "organic_buyers_4h": 72, "organic_buyers_6h": 128, "organic_buyers_12h": 265, "organic_buyers_24h": 452, "organic_sellers_1min": 0, "organic_sellers_5min": 1, "organic_sellers_15min": 4, "organic_sellers_1h": 9, "organic_sellers_4h": 59, "organic_sellers_6h": 112, "organic_sellers_12h": 213, "organic_sellers_24h": 325, "organic_traders_1min": 0, "organic_traders_5min": 1, "organic_traders_15min": 4, "organic_traders_1h": 18, "organic_traders_4h": 128, "organic_traders_6h": 235, "organic_traders_12h": 462, "organic_traders_24h": 746, "organic_volume_buy_1min": 0, "organic_volume_buy_5min": 0, "organic_volume_buy_15min": 0, "organic_volume_buy_1h": 831.1008068346143, "organic_volume_buy_4h": 8437.393788469839, "organic_volume_buy_6h": 14191.97141984561, "organic_volume_buy_12h": 30446.5646871764, "organic_volume_buy_24h": 51200.49820915133, "organic_volume_sell_1min": 0, "organic_volume_sell_5min": 70.8479339320045, "organic_volume_sell_15min": 645.9593838529815, "organic_volume_sell_1h": 769.5186569884643, "organic_volume_sell_4h": 9778.027337726686, "organic_volume_sell_6h": 15980.03194246101, "organic_volume_sell_12h": 29985.86107887737, "organic_volume_sell_24h": 47603.09594892383, "created_at": "2025-06-25T02:07:06.000Z", "market_cap": 200397268.998502, "latest_market_cap": 200416292.2586889 }, ] }, "bonded": { "data": [ { "address": "5xF3SeL6ntMcbQCuVFDUM2dHv4RHgAGjfqM7Nj67pump", "chainId": "solana:solana", "symbol": "STEVE", "name": "Gork's Real Name", "decimals": 6, "id": 0, "price": 0.000005032034746071594, "priceToken": 2.611221112023177e-8, "priceTokenString": "0.00000002611221112023177100283149", "approximateReserveUSD": 4687.250728080079, "approximateReserveTokenRaw": "931482186552730", "approximateReserveToken": 931482186.55273, "totalSupply": 999224201, "circulatingSupply": 999224201, "marketCap": 5028.130898547626, "marketCapDiluted": 5028.130898547626, "logo": null, "exchange": { "name": "PumpSwap", "logo": "https://metadata.mobula.io/assets/logos/pAMMBay6oceH9fJKBRHGP5D4bD4sWpmSwMn52FMfXEA.webp" }, "factory": "pAMMBay6oceH9fJKBRHGP5D4bD4sWpmSwMn52FMfXEA", "source": "pumpfun", "sourceFactory": "6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P", "liquidity": 4687.250728080079, "liquidityMax": 9374.501456160158, "bonded": true, "bondingPercentage": 0, "preBondingFactory": "6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P", "poolAddress": "J1kqDar5VfpqSgbgegvb5NY9VUfPavY4vLLY2DJqLTpc", "blockchain": "Solana", "type": "pumpswap", "deployer": "GZVSEAajExLJEvACHHQcujBw7nJq98GWUEZtood9LM9b", "createdAt": "2025-04-30T20:34:28.000Z", "ath": 0.000005031748118232972, "atl": 0.000005031748118232972, "athDate": "2025-10-24T07:19:14.100Z", "atlDate": "2025-10-24T07:19:14.100Z", "bonded_at": "2025-10-24T07:19:14.000Z", "holdersCount": 8, "smartTradersHoldingsPercentage": 0, "insidersCount": 3, "bundlersCount": 0, "snipersCount": 0, "freshTradersCount": 0, "proTradersCount": 3, "smartTradersCount": 0, "freshTradersBuys": 0, "proTradersBuys": 3, "smartTradersBuys": 0, "top10Holdings": 0.06256788883091102, "top50Holdings": 0.06256788883091102, "top100Holdings": 0.06256788883091102, "top200Holdings": 0.06256788883091102, "devHoldings": 0, "insidersHoldings": 0.03989948191498797, "bundlersHoldings": 0, "snipersHoldings": 0, "proTradersHoldings": 0.020878152974934543, "freshTradersHoldings": 0, "token": { "address": "5xF3SeL6ntMcbQCuVFDUM2dHv4RHgAGjfqM7Nj67pump", "chainId": "solana:solana", "symbol": "STEVE", "name": "Gork's Real Name", "decimals": 6, "id": 0, "price": 0.000005032034746071594, "priceToken": 2.611221112023177e-8, "priceTokenString": "0.00000002611221112023177100283149", "approximateReserveUSD": 4687.250728080079, "approximateReserveTokenRaw": "931482186552730", "approximateReserveToken": 931482186.55273, "totalSupply": 999224201, "circulatingSupply": 999224201, "marketCap": 5028.130898547626, "marketCapDiluted": 5028.130898547626, "logo": null, "exchange": { "name": "PumpSwap", "logo": "https://metadata.mobula.io/assets/logos/pAMMBay6oceH9fJKBRHGP5D4bD4sWpmSwMn52FMfXEA.webp" }, "factory": "pAMMBay6oceH9fJKBRHGP5D4bD4sWpmSwMn52FMfXEA", "source": "pumpfun", "sourceFactory": "6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P", "liquidity": 4687.250728080079, "liquidityMax": 9374.501456160158, "bonded": true, "bondingPercentage": 0, "preBondingFactory": "6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P", "poolAddress": "J1kqDar5VfpqSgbgegvb5NY9VUfPavY4vLLY2DJqLTpc", "blockchain": "Solana", "type": "pumpswap", "deployer": "GZVSEAajExLJEvACHHQcujBw7nJq98GWUEZtood9LM9b", "createdAt": "2025-04-30T20:34:28.000Z", "ath": 0.000005031748118232972, "atl": 0.000005031748118232972, "athDate": "2025-10-24T07:19:14.100Z", "atlDate": "2025-10-24T07:19:14.100Z", "bonded_at": "2025-10-24T07:19:14.000Z", "holdersCount": 8, "top10HoldingsPercentage": 0.06256788883091102, "top50HoldingsPercentage": 0.06256788883091102, "top100HoldingsPercentage": 0.06256788883091102, "top200HoldingsPercentage": 0.06256788883091102, "devHoldingsPercentage": 0, "insidersHoldingsPercentage": 0.03989948191498797, "bundlersHoldingsPercentage": 0, "snipersHoldingsPercentage": 0, "proTradersHoldingsPercentage": 0.020878152974934543, "freshTradersHoldingsPercentage": 0, "smartTradersHoldingsPercentage": 0, "insidersCount": 3, "bundlersCount": 0, "snipersCount": 0, "freshTradersCount": 0, "proTradersCount": 3, "smartTradersCount": 0, "freshTradersBuys": 0, "proTradersBuys": 3, "smartTradersBuys": 0 }, "dexscreenerHeader": null, "dexscreenerAdPaid": false, "latest_trade_date": null, "latest_price": 0.000005032034746071594, "price_change_1min": 0, "price_change_5min": 0, "price_change_1h": 0, "price_change_4h": 0, "price_change_6h": 0, "price_change_12h": 0, "price_change_24h": 0, "price_1min_ago": 0, "price_5min_ago": 0, "price_1h_ago": 0, "price_4h_ago": 0, "price_6h_ago": 0, "price_12h_ago": 0, "price_24h_ago": 0, "volume_1min": 0, "volume_5min": 0, "volume_15min": 0, "volume_1h": 0, "volume_4h": 0, "volume_6h": 0, "volume_12h": 0, "volume_24h": 0, "volume_buy_1min": 0, "volume_buy_5min": 0, "volume_buy_15min": 0, "volume_buy_1h": 0, "volume_buy_4h": 0, "volume_buy_6h": 0, "volume_buy_12h": 0, "volume_buy_24h": 0, "volume_sell_1min": 0, "volume_sell_5min": 0, "volume_sell_15min": 0, "volume_sell_1h": 0, "volume_sell_4h": 0, "volume_sell_6h": 0, "volume_sell_12h": 0, "volume_sell_24h": 0, "buys_1min": 0, "buys_5min": 0, "buys_15min": 0, "buys_1h": 0, "buys_4h": 0, "buys_6h": 0, "buys_12h": 0, "buys_24h": 0, "sells_1min": 0, "sells_5min": 0, "sells_15min": 0, "sells_1h": 0, "sells_4h": 0, "sells_6h": 0, "sells_12h": 0, "sells_24h": 0, "trades_1min": 0, "trades_5min": 0, "trades_15min": 0, "trades_1h": 0, "trades_4h": 0, "trades_6h": 0, "trades_12h": 0, "trades_24h": 0, "buyers_1min": 0, "buyers_5min": 0, "buyers_15min": 0, "buyers_1h": 0, "buyers_4h": 0, "buyers_6h": 0, "buyers_12h": 0, "buyers_24h": 0, "sellers_1min": 0, "sellers_5min": 0, "sellers_15min": 0, "sellers_1h": 0, "sellers_4h": 0, "sellers_6h": 0, "sellers_12h": 0, "sellers_24h": 0, "traders_1min": 0, "traders_5min": 0, "traders_15min": 0, "traders_1h": 0, "traders_4h": 0, "traders_6h": 0, "traders_12h": 0, "traders_24h": 0, "fees_paid_1min": 0, "fees_paid_5min": 0, "fees_paid_15min": 0, "fees_paid_1h": 0, "fees_paid_4h": 0, "fees_paid_6h": 0, "fees_paid_12h": 0, "fees_paid_24h": 0, "totalFeesPaidUSD": 0, "description": null, "socials": { "twitter": null, "website": null, "telegram": null, "others": null }, "security": null, "twitterReusesCount": 0, "twitterRenameCount": 0, "twitterRenameHistory": [], "deployerMigrationsCount": 0, "dexscreenerListed": false, "holders_list": [], "organic_trades_1min": 0, "organic_trades_5min": 0, "organic_trades_15min": 0, "organic_trades_1h": 0, "organic_trades_4h": 0, "organic_trades_6h": 0, "organic_trades_12h": 0, "organic_trades_24h": 0, "organic_volume_1min": 0, "organic_volume_5min": 0, "organic_volume_15min": 0, "organic_volume_1h": 0, "organic_volume_4h": 0, "organic_volume_6h": 0, "organic_volume_12h": 0, "organic_volume_24h": 0, "organic_buys_1min": 0, "organic_buys_5min": 0, "organic_buys_15min": 0, "organic_buys_1h": 0, "organic_buys_4h": 0, "organic_buys_6h": 0, "organic_buys_12h": 0, "organic_buys_24h": 0, "organic_sells_1min": 0, "organic_sells_5min": 0, "organic_sells_15min": 0, "organic_sells_1h": 0, "organic_sells_4h": 0, "organic_sells_6h": 0, "organic_sells_12h": 0, "organic_sells_24h": 0, "organic_buyers_1min": 0, "organic_buyers_5min": 0, "organic_buyers_15min": 0, "organic_buyers_1h": 0, "organic_buyers_4h": 0, "organic_buyers_6h": 0, "organic_buyers_12h": 0, "organic_buyers_24h": 0, "organic_sellers_1min": 0, "organic_sellers_5min": 0, "organic_sellers_15min": 0, "organic_sellers_1h": 0, "organic_sellers_4h": 0, "organic_sellers_6h": 0, "organic_sellers_12h": 0, "organic_sellers_24h": 0, "organic_traders_1min": 0, "organic_traders_5min": 0, "organic_traders_15min": 0, "organic_traders_1h": 0, "organic_traders_4h": 0, "organic_traders_6h": 0, "organic_traders_12h": 0, "organic_traders_24h": 0, "organic_volume_buy_1min": 0, "organic_volume_buy_5min": 0, "organic_volume_buy_15min": 0, "organic_volume_buy_1h": 0, "organic_volume_buy_4h": 0, "organic_volume_buy_6h": 0, "organic_volume_buy_12h": 0, "organic_volume_buy_24h": 0, "organic_volume_sell_1min": 0, "organic_volume_sell_5min": 0, "organic_volume_sell_15min": 0, "organic_volume_sell_1h": 0, "organic_volume_sell_4h": 0, "organic_volume_sell_6h": 0, "organic_volume_sell_12h": 0, "organic_volume_sell_24h": 0, "created_at": "2025-04-30T20:34:28.000Z", "market_cap": 0, "latest_market_cap": 5028.130898547626 }, ] } } ``` # Get Trading Pairs per Blockchain Source: https://docs.mobula.io/guides/query-pairs-per-blockchain Get detailed trading pair information for a specific blockchain. Perfect for developers and investors seeking real-time insights. Mobula API provides precise and real-time data on trading pairs for specific blockchains, enabling developers and investors to gain actionable insights into market liquidity, trading volumes, and pair creation trends. This guide will walk you through retrieving detailed trading pair information via the API, showcasing its practical applications in portfolio tracking, market research, and DEX integrations. ### **What You’ll Need** 1. Basic knowledge of RESTful APIs and JavaScript. 2. Preferences for specific blockchains, cache settings, and stale data handling (optional). 3. An API key from the [**Dashboard**](https://admin.mobula.io) (required for production; optional in development mode). ### **Walkthrough** #### **Execute the API Call** You can call the Mobula API directly from your terminal using cURL or any HTTP client. **Using cURL**: ```bash theme={null} curl --request GET \ --url 'https://api.mobula.io/api/1/market/blockchain/pairs?blockchain=Base&sortBy=createdAt' ``` **Using Axios**: ```javascript theme={null} fetch('https://api.mobula.io/api/1/market/blockchain/pairs?blockchain=Base&sortBy=createdAt') .then(response => response.json()) .then(response => console.log(response.data)) .catch(error => console.error(error)); ``` #### **Get Your Data** The API provides detailed data on trading pairs for a specific blockchain, including pair creation trends, market liquidity, and trading volumes. Available filters and sorting fields are listed [here](https://docs.mobula.io/rest-api-reference/endpoint/market-blockchain-pairs). ### **Insights You Can Extract** * **Liquidity Monitoring**: Assess market liquidity for specific pairs to identify trading opportunities. * **Volume Analysis**: Track 24-hour trading volumes to determine market trends and pair popularity. * **New Pair Tracking**: Monitor recently created trading pairs with the `sortBy=createdAt` parameter. ### **Use Cases** * **Portfolio Tracking**: Enhance portfolio tools with real-time pair data for a specific blockchain. * **Market Research**: Evaluate trading pair performance to plan trading strategies. * **DEX Integrations**: Build applications that rely on specific blockchain trading pair data. ### **Need Help?** Our support team is available to assist you with any questions or challenges in using the API. Telegram Slack Discord ``` ``` # Query Token by Ticker (Symbol) Source: https://docs.mobula.io/guides/query-token-by-ticker Learn how to search and retrieve token data using a ticker symbol like USDC, ETH, or SOL instead of contract addresses ## Overview While most APIs require contract addresses to retrieve token data, Mobula's **Universal Search** (`/api/2/fast-search`) allows you to query tokens directly by their ticker symbol (like `USDC`, `ETH`, `SOL`). This is perfect for: * Building search interfaces for users * Quick token lookups without knowing the address * Supporting multiple chains with a single query The API responds in **under 30ms** and returns detailed token information matching your query. ## Quick Start ### Basic Ticker Search ```bash theme={null} curl "https://api.mobula.io/api/2/fast-search?input=usdc" ``` This returns all tokens with the symbol or name starting with "usdc", sorted by trading activity. ### Exact Symbol Match Wrap your ticker in double quotes for exact matching (useful for short tickers): ```bash theme={null} curl "https://api.mobula.io/api/2/fast-search?input=\"W\"" ``` This returns only tokens with the exact symbol "W" (like Wormhole), not "WETH", "WBTC", etc. ## Code Examples ### TypeScript / JavaScript ```typescript theme={null} interface TokenResult { name: string | null; symbol: string | null; address: string; chainId: string; decimals: number; priceUSD: number; priceChange24hPercentage: number; volume24hUSD: number; marketCapUSD: number; liquidityUSD?: number; logo: string | null; createdAt: string | null; holdersCount: number; // ... many more fields available } interface SearchResponse { data: TokenResult[]; } async function searchByTicker( ticker: string, options?: { exact?: boolean; chains?: string[]; limit?: number; sortBy?: string; } ): Promise Telegram Slack Discord { const params = new URLSearchParams(); // Use exact match syntax if specified const input = options?.exact ? `"${ticker}"` : ticker; params.set('input', input); // Optional: filter by blockchains if (options?.chains?.length) { params.set('filters', JSON.stringify({ blockchains: options.chains.join(',') })); } // Optional: limit results (1-20, default: 5) if (options?.limit) { params.set('limit', options.limit.toString()); } // Optional: sort by metric if (options?.sortBy) { params.set('sortBy', options.sortBy); } const response = await fetch( `https://api.mobula.io/api/2/fast-search?${params}`, { headers: { 'Authorization': `Bearer ${process.env.MOBULA_API_KEY}`, }, } ); const data: SearchResponse = await response.json(); return data.data; } // Usage examples const usdcTokens = await searchByTicker('usdc'); console.log(usdcTokens[0]); // Most traded USDC const exactW = await searchByTicker('W', { exact: true }); console.log(exactW[0]); // Wormhole token const solanaUsdc = await searchByTicker('usdc', { chains: ['solana'], limit: 1 }); console.log(solanaUsdc[0]); // USDC on Solana only ``` ### Python ```python theme={null} import requests import json from typing import Optional def search_by_ticker( ticker: str, exact: bool = False, chains: Optional[list[str]] = None, limit: int = 5, sort_by: str = "searchScore" ) -> list[dict]: """Search for tokens by ticker symbol.""" # Use exact match syntax if specified input_query = f'"{ticker}"' if exact else ticker params = { "input": input_query, "limit": limit, "sortBy": sort_by } # Optional chain filter if chains: params["filters"] = json.dumps({"blockchains": ",".join(chains)}) response = requests.get( "https://api.mobula.io/api/2/fast-search", params=params, headers={"Authorization": f"Bearer {API_KEY}"} ) return response.json()["data"] # Usage examples usdc_tokens = search_by_ticker("usdc") print(f"Top USDC: {usdc_tokens[0]['name']} at ${usdc_tokens[0]['priceUSD']}") # Exact match for short symbols w_token = search_by_ticker("W", exact=True) print(f"W token: {w_token[0]['name']}") # Filter by chain sol_pepe = search_by_ticker("pepe", chains=["solana"], limit=3) for token in sol_pepe: print(f"{token['symbol']}: {token['address']}") ``` ## Parameters | Parameter | Type | Description | | - | - | - | | `input` | string | The ticker/symbol to search for. Wrap in `"` for exact match. | | `limit` | number | Number of results (1-20, default: 5) | | `sortBy` | string | Sort metric: `volume24h`, `marketCap`, `feesPaid24h`, etc. (default: `searchScore`) | | `filters` | JSON | Filter options including `blockchains` | ### Available Sort Options * `searchScore` - Composite ranking (fees × liquidity) **(default)** * `volume24h` - 24h trading volume * `marketCap` - Market capitalization * `volume5min` / `volume1h` - Short-term volume * `feesPaid5min` / `feesPaid1h` / `feesPaid24h` - Trading fees * `holdersCount` - Number of holders * `organicVolume1h` - Organic 1h volume * `totalFeesPaidUsd` - Total fees paid in USD * `createdAt` - Token creation date ## Response Format Each token in the response follows the full [Token Details](/rest-api-reference/endpoint/token-details) data model. Here's an example with key fields: ```json theme={null} { "data": [ { "address": "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v", "chainId": "solana:solana", "symbol": "USDC", "name": "USD Coin", "decimals": 6, "logo": "https://...", "priceUSD": 0.9999, "priceToken": 1.0001, "priceTokenString": "1000100000000000000", "marketCapUSD": 25000000000, "marketCapDilutedUSD": 30000000000, "totalSupply": 30000000000, "circulatingSupply": 25000000000, "liquidityUSD": 500000000, "approximateReserveUSD": 250000000, "approximateReserveToken": 250000000, "priceChange5minPercentage": 0.01, "priceChange1hPercentage": 0.02, "priceChange24hPercentage": 0.05, "volume5minUSD": 1000000, "volume1hUSD": 50000000, "volume24hUSD": 1234567890, "trades5min": 500, "trades1h": 5000, "trades24h": 50000, "buys24h": 28000, "sells24h": 22000, "buyers24h": 15000, "sellers24h": 12000, "traders24h": 20000, "feesPaid24hUSD": 123456, "totalFeesPaidUSD": 9876543, "holdersCount": 1500000, "createdAt": "2020-10-15T00:00:00.000Z", "latestTradeDate": "2026-01-27T15:30:00.000Z", "deployer": "...", "poolAddress": "...", "factory": "...", "exchange": { "name": "Raydium", "logo": "https://..." }, "socials": { "twitter": "https://twitter.com/...", "website": "https://...", "telegram": "https://t.me/..." }, "security": { "mintable": false, "freezable": false, "lpBurned": true } } ] } ``` The response includes 100+ fields per token including organic metrics, DEXScreener data, and more. See the [Token Details endpoint](/rest-api-reference/endpoint/token-details) for the complete schema. ```` ## Best Practices ### 1. Use Exact Match for Short Symbols Short symbols (1-3 characters) can return noisy results. Use double quotes: ```bash # Returns many results: "W", "WETH", "WBTC", "WRAPPED"... curl "https://api.mobula.io/api/2/fast-search?input=w" # Returns only exact "W" symbol curl "https://api.mobula.io/api/2/fast-search?input=\"w\"" ```` ### 2. Filter by Chain for Precision If you know the target chain, filter to avoid cross-chain duplicates: ```bash theme={null} curl "https://api.mobula.io/api/2/fast-search?input=usdc&filters={\"blockchains\":\"solana\"}" ``` ### 3. Use Search Score for Discovery The `searchScore` metric combines fees and liquidity - perfect for finding actively traded tokens: ```bash theme={null} curl "https://api.mobula.io/api/2/fast-search?input=pepe&sortBy=searchScore&limit=10" ``` ## Common Use Cases ### Token Autocomplete Build a search bar with live suggestions: ```typescript theme={null} async function getAutocomplete(query: string): Promise{ if (query.length < 2) return []; return searchByTicker(query, { limit: 5, sortBy: 'searchScore' }); } ``` ### Multi-chain Token Resolver Get the same token across multiple chains: ```typescript theme={null} async function getTokenAcrossChains(ticker: string): Promise