> ## Documentation Index
> Fetch the complete documentation index at: https://docs.mobula.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Wallet Backfill Status (Internal)

> Real-time status of the per-wallet backfill pipeline (slot extraction + position rebuild) with unified progress and ETA.

### 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-backfilling` → `qa-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

| State         | Meaning                                                                                                                                       |
| ------------- | --------------------------------------------------------------------------------------------------------------------------------------------- |
| `not_started` | No backfill has ever been requested for this wallet.                                                                                          |
| `processing`  | Phase 1 in progress (fetching transactions and ingesting slots).                                                                              |
| `rebuilding`  | Phase 2 in progress (re-aggregating swaps into positions).                                                                                    |
| `completed`   | Both phases finished — `wallet_positions` is up to date.                                                                                      |
| `stuck`       | Phase 1 started (`transferStatus="1"`) but the provider call died before publishing any batches. A retry of the backfill trigger clears this. |

### 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

```json theme={null}
{
  "wallet": "A92oggkrdzUTd4NGpd2jDYR1rpeeo5LUHayGgjwPLnd4",
  "state": "rebuilding",
  "progressPercent": 82.4,
  "etaSeconds": 6,
  "estimatedCompletionAt": "2026-04-20T13:31:35.000Z",
  "transferStatus": "2",
  "swapStatus": "2",
  "phase1": {
    "expectedBatches": 58,
    "doneBatches": 58,
    "seenBatches": 58,
    "remainingBatches": 0,
    "progressPercent": 100,
    "startedAt": "2026-04-20T13:30:56.193Z",
    "elapsedSeconds": 47,
    "etaSeconds": null
  },
  "phase2": {
    "swapCount": 12430,
    "startedAt": "2026-04-20T13:31:23.101Z",
    "completedAt": null,
    "elapsedSeconds": 6,
    "predictedDurationSeconds": 18,
    "progressPercent": 33.3,
    "etaSeconds": 12,
    "avgMsPerSwap": 1.462
  },
  "rebuildPublished": true,
  "positionRebuildLocked": true,
  "backfillVersion": "1"
}
```

### 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.

### Related

* 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)
