Migration skills
Download source-backed SKILL.md artifacts for Voyager migration and accounting point-in-time balances.
Download source-backed SKILL.md artifacts for Voyager migration and accounting point-in-time balances.
Use this page when a client wants an agent to migrate from Voyager-style calls to Starkscan without guessing routes.
The artifacts below are intentionally narrow. They read like executable migration contracts, not generic prompts. Each skill tells the agent which Starkscan routes are certified, beta, RPC-beta, or unsupported, and points back to the published starkscan-openapi.yaml before any code generation.
| Skill | Best for | Artifact |
|---|---|---|
| Accounting point-in-time balances | Accountants that need one token balance for one account at a calendar close. | /skills/accounting-point-in-time-balances/SKILL.md |
| Voyager migration | Adapters that need to replace a bounded Voyager workflow with Starkscan REST or RPC-beta routes. | /skills/voyager-migration/SKILL.md |
Install the artifact by giving the SKILL.md file to Claude, Codex, Cursor, or any agent runtime that supports portable task instructions. If the runtime does not support skills directly, paste only the relevant sections into the migration task and keep the OpenAPI link attached.
The current ComptaCrypto-style workflow is already possible with two Starkscan calls:
export STARKSCAN_BASE_URL="https://starkscan.co/api"
export STARKSCAN_CHAIN="SN_MAIN"
export STARKSCAN_API_KEY="<api_key>"
export STARKSCAN_TIMESTAMP="2025-12-31T23:59:59Z"
export STARKSCAN_TIMESTAMP_QUERY="2025-12-31T23%3A59%3A59Z"
export STARKSCAN_TOKEN="<token_contract_address>"
export STARKSCAN_ACCOUNT="<account_address>"
curl -sS \
-H "X-Starkscan-Api-Key: $STARKSCAN_API_KEY" \
"$STARKSCAN_BASE_URL/v1/$STARKSCAN_CHAIN/block-at-timestamp?timestamp=$STARKSCAN_TIMESTAMP_QUERY&closest=before"
Use the returned block.blockNumber as the block_tag:
curl -sS \
-H "X-Starkscan-Api-Key: $STARKSCAN_API_KEY" \
"$STARKSCAN_BASE_URL/v1/$STARKSCAN_CHAIN/token/$STARKSCAN_TOKEN/balance-of/$STARKSCAN_ACCOUNT?block_tag=<block.blockNumber>"
For 2025-12-31T23:59:59Z, Starkscan's correctness gate verified block 5007537 against RPC. The helper response also includes previousBlock, nextBlock, and source=indexed_blocks so an accountant can keep the bracket evidence with the report.
Use this matrix before generating migration code. The state must stay attached to every replaced call so clients know whether they are using a certified REST route, a beta REST route, the RPC provider beta, or no Starkscan replacement yet.
| Voyager-style need | Starkscan replacement | State | Migration note |
|---|---|---|---|
| Health / host reachability | GET /v1/{chain}/status | certified | Use this as the first smoke for every integration. |
| Exact token balance | GET /v1/{chain}/token/{token}/balance-of/{address}?block_tag={block} | certified | Use exact token and account addresses; pass a concrete block for accounting. |
| Timestamp to block | GET /v1/{chain}/block-at-timestamp?timestamp={time}&closest=before | beta | Use as the helper before historical balance checks. |
| One transaction | GET /v1/{chain}/tx/{tx_hash} | certified | Use for transaction detail and support links. |
| Wallet transactions | GET /v1/{chain}/address/{address}/transactions?limit={n}&cursor={nextCursor} | beta | Cursor-based; preserve nextCursor exactly. |
| Wallet transfer rows | GET /v1/{chain}/transfers?address={address}&limit={n}&cursor={nextCursor} | beta | Use for transfer-granular adapters, not total portfolio valuation. |
| Storage reads, class reads, nonce, calls, fee, simulation | POST /api/v1/{chain}/rpc | rpc-beta | Preserve JSON-RPC id, result, and error; bill/rate-limit per method. |
| Writes, WebSocket subscriptions, broad Voyager parity | No first-beta replacement | unsupported | Keep the existing provider path until Starkscan RPC formally launches that surface. |
| Task | Route | State |
|---|---|---|
| Health check | GET /v1/{chain}/status | certified |
| Timestamp to block | GET /v1/{chain}/block-at-timestamp?timestamp={time}&closest=before | beta |
| Exact token balance | GET /v1/{chain}/token/{token}/balance-of/{address}?block_tag={block} | certified |
| One transaction | GET /v1/{chain}/tx/{tx_hash} | certified |
| Wallet transactions | GET /v1/{chain}/address/{address}/transactions?limit={n}&cursor={nextCursor} | beta |
| Wallet transfer rows | GET /v1/{chain}/transfers?address={address}&limit={n}&cursor={nextCursor} | beta |
| Storage reads / class reads / nonce / simulation | POST /api/v1/{chain}/rpc | rpc-beta |
Current gaps must stay visible in migration plans. A standalone REST storage route and broad Voyager parity are not certified launch surfaces. If an agent asks for a route that is not listed here or in the OpenAPI artifact, it should answer unsupported instead of inventing an endpoint.
X-Starkscan-Api-Key; do not paste the full key into chats, screenshots, tickets, or generated reports.closest=before for "as of this instant" accounting semantics.USDC when correctness matters.latest for historical accounting close.X-Request-Id, X-Starkscan-Route-Class, rate-limit headers, HTTP status, and latency for support./starkscan-openapi.yaml before generating SDK code or adding a route to a migration matrix.curl -sS \
-H "X-Starkscan-Api-Key: $STARKSCAN_API_KEY" \
"$STARKSCAN_BASE_URL/v1/$STARKSCAN_CHAIN/status"
BLOCK_RESPONSE="$(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")"
printf '%s\n' "$BLOCK_RESPONSE"
BLOCK_NUMBER="$(printf '%s' "$BLOCK_RESPONSE" | python3 -c 'import json, sys; print(json.load(sys.stdin)["block"]["blockNumber"])')"
curl -sS \
-H "X-Starkscan-Api-Key: $STARKSCAN_API_KEY" \
"$STARKSCAN_BASE_URL/v1/$STARKSCAN_CHAIN/token/$STARKSCAN_TOKEN/balance-of/$STARKSCAN_ACCOUNT?block_tag=$BLOCK_NUMBER"
If the client is using the Starkscan repo checkout, also run the acceptance bench for the existing Voyager replacement slice:
STARKSCAN_BASE_URL="https://starkscan.co/api" \
STARKSCAN_API_KEY="$STARKSCAN_API_KEY" \
python3 rust-exp/scripts/chipi-migration-acceptance-bench.py \
--wallets-file rust-exp/scripts/fixtures/chipi-balance-of-wallets-strkbtc.json \
--count 100 \
--report-dir .artifacts/chipi-migration
Use the TypeScript SDK for the certified balance route after the timestamp helper resolves the block:
import { createStarkscanClient } from "@starkscan/sdk";
const baseUrl = process.env.STARKSCAN_BASE_URL ?? "https://starkscan.co/api";
const chainId = process.env.STARKSCAN_CHAIN ?? "SN_MAIN";
const apiKey = process.env.STARKSCAN_API_KEY;
const token = process.env.STARKSCAN_TOKEN;
const account = process.env.STARKSCAN_ACCOUNT;
const timestamp = "2025-12-31T23:59:59Z";
if (!apiKey || !token || !account) {
throw new Error("STARKSCAN_API_KEY, STARKSCAN_TOKEN, and STARKSCAN_ACCOUNT are required");
}
const blockResponse = await fetch(
`${baseUrl}/v1/${chainId}/block-at-timestamp?timestamp=${encodeURIComponent(timestamp)}&closest=before`,
{ headers: { "X-Starkscan-Api-Key": apiKey } },
);
const { block } = (await blockResponse.json()) as { block: { blockNumber: number } };
const starkscan = createStarkscanClient({ apiKey, baseUrl, chainId });
const balance = await starkscan.tokenBalanceOf(token, account, String(block.blockNumber));
console.log({ blockNumber: block.blockNumber, balance });
Use the CLI for a package-level smoke after the block number is known:
npx -y @starkscan/cli@alpha \
--base-url "$STARKSCAN_BASE_URL" \
--chain "$STARKSCAN_CHAIN" \
--api-key "$STARKSCAN_API_KEY" \
doctor
npx -y @starkscan/cli@alpha \
--base-url "$STARKSCAN_BASE_URL" \
--chain "$STARKSCAN_CHAIN" \
--api-key "$STARKSCAN_API_KEY" \
--output-format json \
token-balance-of "$STARKSCAN_ACCOUNT" "$STARKSCAN_TOKEN" \
--block-tag "$BLOCK_NUMBER"
The safe builder behavior is constrained:
SKILL.md, curl commands, TypeScript SDK notes, Python smoke, and a route-state table only for matched routes.unsupported, beta, or rpc-beta with the reason.This prevents a migration agent from converting "missing docs" into fake Starkscan routes.