Skip to main content

What it reports

When a client calls GET /api/2/wallet/positions?wallet=…&_backfillSwapsAndPositions=true, the platform runs a two-phase pipeline:
  1. Slot extraction (wallet-backfillingqa-blocks-processor) — fetches the wallet’s historical transactions from the active provider (Moralis / Dune / Solscan), splits the slots into batches, and ingests transfers + swaps into public.swaps.
  2. Position rebuild (update-wallet-positions) — once slot extraction is done, the job acquires a per-wallet lock, wipes existing rows in wallet_positions / wallet_positions_recipients, and re-aggregates swaps into positions.
This endpoint surfaces the state of both phases in a single response, plus a unified progressPercent and etaSeconds so callers can drive a progress bar or notify the user when the wallet is ready.

state values

Progress & ETA semantics

  • progressPercent is weighted: phase 1 spans 0 → 70%, phase 2 spans 70 → 100%. It caps at 99.9 until phase 2 observably completes, and only then flips to 100.
  • etaSeconds during phase 1 is a linear extrapolation (elapsed / done) × remaining. During phase 2 it is swapCount × globalAvgMsPerSwap − elapsedRebuild, where the global average is an EWMA (alpha 0.1) updated after every successful rebuild.
  • Both fields are null before the first batch lands (no data yet to extrapolate from).

Example

Bulk variant

GET /internal/wallet-backfill/status?wallets=w1,w2,w3 returns { statuses: [...] } with one entry per wallet, in the same order. Useful for dashboards polling many wallets at once.
  • Trigger a backfill: GET /api/2/wallet/positions?wallet=…&_backfillSwapsAndPositions=true
  • Tune phase 1 retention: BACKFILL_VERSION env var (bump to invalidate all cached states)