Skip to content

Trader dashboard

Goal: a “who is winning” board and a wallet profile page.

const board = await fetch(`${A}/smart-money/top?chain=5042&source=onchain&window=7d&limit=50`).then((r) => r.json());

wallets are ranked by Smart Score, with routers and bots already removed (botsRemoved says how many). Show pnlUsd (realized + open), realizedUsd, winRate, trades, topToken and archetype. totalWallets is how many qualified; indexedToBlock is the tape’s head when the board was built. 503 CHAIN_NOT_ENABLED means the board is not published for the chain yet.

Windows: 24h (rebuilt every 15 minutes), 7d and 30d (hourly), all (three-hourly). On Arc a live delta sits on top of the last rebuild, so polling every 30 s shows movement.

Four calls in parallel:

Panel Call
Holdings and PnL per token GET /portfolio/{wallet}/pnl?chain=5042
Trade history (chart markers, activity list) GET /portfolio/{wallet}/trades?chain=5042
Calendar (realized PnL by day) GET /portfolio/{wallet}/pnl-calendar?chain=5042
Liquidity positions GET /lp/positions?chain=5042&owner={wallet}&status=all
const [pnl, trades, cal, lp] = await Promise.all([
`${A}/portfolio/${w}/pnl?chain=5042`, `${A}/portfolio/${w}/trades?chain=5042`,
`${A}/portfolio/${w}/pnl-calendar?chain=5042`, `${A}/lp/positions?chain=5042&owner=${w}&status=all`,
].map((u) => fetch(u).then((r) => r.json())));
  • pnl.tokens[] gives realized, unrealized, average cost, current amount and value, ROI, and the untracked balance that arrived by transfer (no cost basis). Show untracked separately; it is not a loss or a gain.
  • pnl is cached stale-while-revalidate: updatedAt tells you how old the answer is; a first view of a busy wallet may take a few seconds.
  • cal.days[] (date, realizedUsd, trades) draws the calendar; realizedTotal reconciles with pnl.realized.
  • lp.summary (open, closed, wins, win rate, realized LP PnL, fees, open value) and lp.positions[] (each with live value, in-range, fees, jit / unreconciled flags) make the liquidity tab.

The board already removed bots. For a wallet you look up directly, the tells are in the data: hundreds of trades a day from the first trade, buy-then-sell inside a minute, dozens of launches sniped. The Ask agent can answer “is 0x… a bot” with its wallet profile tool if you would rather not implement the heuristics.

There is no server-side follow. Poll GET /portfolio/{wallet}/trades?chain=5042 every 30–60 s and diff by tx, or subscribe to the WebSocket trades channel for the tokens the wallet holds and match wallet on incoming items.