# Starkscan Voyager Migration

Use this skill when a client wants to replace a bounded Voyager workflow with Starkscan REST, SDK, CLI, MCP, or the Starkscan RPC provider beta.

## Contract

Given a Voyager call, map it to Starkscan only when the route is listed below or present in the published OpenAPI artifact at `/starkscan-openapi.yaml`.

If the requested Voyager surface is not listed, answer with one of these states:

- `certified`: production-safe Starkscan REST route exists.
- `beta`: usable with named clients and explicit limits.
- `rpc-beta`: use the Starkscan JSON-RPC provider beta, not REST.
- `unsupported`: no Starkscan replacement is published yet.

Do not hallucinate routes. Do not scrape Starkscan pages. Do not silently switch a REST request to RPC without telling the user.

## Environment

```bash
export STARKSCAN_BASE_URL="https://starkscan.co/api"
export STARKSCAN_CHAIN="SN_MAIN"
export STARKSCAN_API_KEY="mzk_live_key_redacted"
```

Hosted REST requests use:

```text
$STARKSCAN_BASE_URL/v1/$STARKSCAN_CHAIN/...
```

Send the key as:

```text
X-Starkscan-Api-Key: $STARKSCAN_API_KEY
```

## Migration Matrix

| Need | Starkscan replacement | State | Notes |
| --- | --- | --- | --- |
| Health / host reachability | `GET /v1/{chain}/status` | `certified` | Use first in smoke tests. |
| One block | `GET /v1/{chain}/block/{number_or_hash}` | `certified` | Use `tx_limit` when transaction list size matters. |
| Timestamp to block | `GET /v1/{chain}/block-at-timestamp?timestamp={time}&closest=before` | `beta` | Use for accounting close; response has `block.blockNumber`. |
| One transaction | `GET /v1/{chain}/tx/{tx_hash}` | `certified` | Includes token transfer context when available. |
| Exact token balance | `GET /v1/{chain}/token/{token}/balance-of/{address}?block_tag={block}` | `certified` | Use exact token contract and concrete block for replayable correctness. |
| Token total supply | `GET /v1/{chain}/token/{token}/total-supply?block_tag={block}` | `certified` | Use concrete block for deterministic checks. |
| Wallet transactions | `GET /v1/{chain}/address/{address}/transactions?limit={n}&cursor={nextCursor}` | `beta` | Cursor-based; pass `nextCursor` back unchanged. |
| Wallet transfer rows | `GET /v1/{chain}/transfers?address={address}&limit={n}&cursor={nextCursor}` | `beta` | Use for transfer-granular adapters. |
| Wallet holdings | `GET /v1/{chain}/address/{address}/token-holdings` | `beta` | Require complete/exact fields before unattended use. |
| Contract storage read | `POST /api/v1/{chain}/rpc` with `starknet_getStorageAt` | `rpc-beta` | REST standalone storage route is not certified. |
| Class reads / nonce / call / estimate fee / simulation | `POST /api/v1/{chain}/rpc` | `rpc-beta` | Preserve JSON-RPC id/result/error. |
| Writes / WebSockets | no first-beta replacement | `unsupported` | Do not suggest for current beta unless the provider track explicitly launches them. |
| Explorer transaction link | `https://starkscan.co/tx/{tx_hash}` | `certified` | UI link only; use for support/debug output. |
| Explorer contract/account link | `https://starkscan.co/contract/{address}` | `certified` | UI link only; use for accounts and contracts. |

## Accounting Point-In-Time Balance

For a user asking "what was this account's balance for this token at a date/time?", use the accounting skill:

```bash
curl -sS \
  -H "X-Starkscan-Api-Key: $STARKSCAN_API_KEY" \
  "$STARKSCAN_BASE_URL/v1/$STARKSCAN_CHAIN/block-at-timestamp?timestamp=2025-12-31T23%3A59%3A59Z&closest=before"
```

Then:

```bash
curl -sS \
  -H "X-Starkscan-Api-Key: $STARKSCAN_API_KEY" \
  "$STARKSCAN_BASE_URL/v1/$STARKSCAN_CHAIN/token/<token>/balance-of/<address>?block_tag=<block.blockNumber>"
```

For `2025-12-31T23:59:59Z`, Starkscan's correctness gate verified block `5007537` against RPC.

## Adapter Rules

- Preserve cursor values exactly. Do not build cursors client-side.
- Prefer a concrete block number or block hash over `latest` for correctness-sensitive migrations.
- Treat ticker symbols as display labels only; always use the token contract address.
- Log `X-Request-Id`, `X-Starkscan-Route-Class`, rate-limit headers, HTTP status, and latency.
- Honor `Retry-After` on `429` and `503`.
- For route status and schema, read `/starkscan-openapi.yaml` before generating client code.

## Smoke Test

```bash
curl -sS \
  -H "X-Starkscan-Api-Key: $STARKSCAN_API_KEY" \
  "$STARKSCAN_BASE_URL/v1/$STARKSCAN_CHAIN/status"

curl -sS \
  -H "X-Starkscan-Api-Key: $STARKSCAN_API_KEY" \
  "$STARKSCAN_BASE_URL/v1/$STARKSCAN_CHAIN/block-at-timestamp?timestamp=2025-12-31T23%3A59%3A59Z&closest=before"
```

If both return JSON, migrate one workflow at a time and write down the Starkscan route state next to each replaced Voyager call.
