Starkscan

Wallets

The calls a consumer wallet, paymaster, or portfolio client needs, mapped to the screens that use them.

Wallets

Use the Wallets lane when you are building a consumer wallet, a paymaster, or any client that renders one user's balances, activity, and transactions.

A wallet asks the chain a narrow, repetitive set of questions: what does this account hold, what happened to it, what will this transaction cost, and did it land. This page maps those questions to exact Starkscan calls, and tells you which surface to use for each.

Choose a surface

A wallet normally uses both surfaces:

  • JSON-RPCPOST https://api.starkscan.co/v1/SN_MAIN/rpc with X-Starkscan-Api-Key, or the node URL at https://starkscan.co/rpc/v0_10/SN_MAIN/<starkscan_api_key> when your library only accepts a URL. Use it for anything a Starknet node answers: reads at a block, fee estimation, simulation, and submitting transactions.
  • RESThttps://api.starkscan.co/v1/SN_MAIN/... with the same key. Use it for bounded wallet-state composition and indexed context a node cannot produce in one call: discovered asset candidates, a block-pinned wallet screen, an activity feed, a decoded transaction, address labels.

The rule of thumb: RPC for individual live reads and sending, wallet-state REST for a bounded home screen, and indexed REST for history and context.

First working setup

export STARKSCAN_API_KEY="YOUR_STARKSCAN_API_KEY"
export STARKSCAN_CHAIN="SN_MAIN"

Before wiring anything else, read your own limits:

curl -s https://api.starkscan.co/v1/meta/capabilities \
  -H "X-Starkscan-Api-Key: $STARKSCAN_API_KEY"

The caller block returns your scopes and live remaining budget, and rpcProvider.quotaClasses maps every RPC method to the class that governs it. Read it at startup and size your limiter from it instead of discovering ceilings through 429 responses.

Portfolio

JobCall
Discover candidate token contractsGET /v1/{chain}/address/{address}/assets/discovery
Verify a bounded wallet screenPOST /v1/{chain}/query/wallet-state
One token balanceGET /v1/{chain}/token/{token}/balance-of/{address}
Live balance at a block tagRPC starknet_call with a balanceOf selector

Discovery returns candidate contracts and evidence, not balances. Its coverage.completeWithinScope applies only to the declared standard-fungible evidence scope; it does not prove a globally complete asset universe.

wallet-state resolves one immutable block hash and verifies a bounded set of balances plus optional nonce/class hash at that same block. The current public contract accepts at most 25 candidates. The 26-50 band remains unavailable until dedicated-pool and clean-window capacity certification plus a coordinated schema and client release. Use mode=require_complete for a wallet home screen. Any failed value produces 503 instead of a partial success. verified_partial is for diagnostics and always exposes typed failures. Starkscan never substitutes an indexed balance and never interprets an error as zero.

Treat a holding as priced only when its price status is priced. When pricing is unavailable, priceUsd and valueUsd are null, the non-zero holding remains visible, and it is excluded from totalUsd; the holding is not zero dollars. Require walletSafe=true for the bounded selected page, then inspect coverage separately.

balance-of takes the token first and the owner second, and returns balanceRaw as a string.

Prefer wallet-state over client-side balanceOf fan-out when painting a bounded home screen. The partner spends one wallet-screen operation while Starkscan bounds and accounts for the underlying RPC work. See Migrate to wallet state.

Activity

JobCall
Account activity feedGET /v1/{chain}/address/{address}/transactions
Token movements for an accountGET /v1/{chain}/address/{address}/transfers
One transaction, decodedGET /v1/{chain}/tx/{hash}

address/{address}/transactions returns cursor-paginated list-view rows with txHash, timestampIso, kinds, counterparty, transferCount, and inline topTransfer* and operation* summaries, so a feed row does not need a second call to render.

address/{address}/transfers accepts direction=in, out, or any. Rows are newest-first by (blockNumber, txIndex, logIndex, transferIndex); preserve the exclusive cursor unchanged. Each item carries tokenAddress, fromAddress, toAddress, amount, rawValue, plus standard and tokenId, so fungible and NFT movements arrive in the same shape. List-row historicalUsd is intentionally null; use a separately documented historical pricing workflow if you need it.

tx/{hash} returns executionStatus, finalityStatus, calldata, receipt, logs, messages, and tokenTransfers inline — enough to render "sent 5 USDC to 0x…" without a second call or a trace.

Send and gas

JobMethodQuota class
Account noncestarknet_getNoncerpc_read_state
Estimate a feestarknet_estimateFeerpc_simulation
Simulate a transactionstarknet_simulateTransactionsrpc_simulation
Submit a transactionstarknet_addInvokeTransactionrpc_write
Deploy an accountstarknet_addDeployAccountTransactionrpc_write

starknet_simulateTransactions forwards supported Starknet SIMULATION_FLAGS, including SKIP_VALIDATE and SKIP_FEE_CHARGE, to the upstream method. If you sponsor gas, size against rpc_simulation: it is the tightest class, and every sponsored transaction costs at least one estimate.

Confirmation and settlement

JobCall
Poll to finalityRPC starknet_getTransactionStatus, then starknet_getTransactionReceipt
Read at L1 settlementany read with block_id set to l1_accepted

Four block tags are accepted: latest, pending, pre_confirmed, and l1_accepted. l1_accepted resolves to the real L1 watermark rather than an alias of latest. When a product decision depends on irreversibility — withdrawals, off-ramps, credit — read at that tag instead of reimplementing settlement tracking.

Identity and labels

JobCall
Classify many addresses at oncePOST /v1/{chain}/address/intelligence
One contract's factsGET /v1/{chain}/contract/{address}
Deployment and wallet classRPC starknet_getClassHashAt

address/intelligence takes { "addresses": [...] } with up to 128 addresses per request and returns label, typeLabel, classHash, isAccount, isDeployed, deployedByAddress, hasReceivedFunds, and latestActivityBlock for each. It is the call that turns a feed of hex strings into a feed of names: resolve every counterparty on a screen in one round trip instead of 128.

Use starknet_getClassHashAt for the pre-first-transaction deployment check and for upgrade detection.

Positions and protocol activity

JobCall
Events from one contract, filteredGET /v1/{chain}/contract/{address}/events
Events across the chainGET /v1/{chain}/events

The contract route accepts positional key filters: pass topic0 together with any of topic1 through topic15, plus numeric from_block and to_block. That lets you request only the events of a protocol that concern one user's position, instead of downloading a contract's whole event stream and filtering client-side.

Two rules to design against:

  • Filters apply to values a contract places in event keys. Events that pack their parameters into data cannot be filtered this way, which is the same constraint the underlying node has.
  • Filtered queries run over a bounded block window. Scan recent history in chunks rather than requesting all of history in one call.

Sizing your rate limits

Quota classes are per minute, and each JSON-RPC child request is classified and counted independently. A batch therefore buys round trips, not headroom: a batch of 10 decrements your budget by 10.

The practical consequence: if a home screen issues N per-token starknet_call reads, your ceiling is the rpc_read_state budget divided by N screen loads per minute across the whole tenant. A bounded wallet-state request is billed as one partner operation, while internal capacity accounting still tracks actual calls and enforces the certified 25- or 50-candidate band, concurrency, timeout, and response-size ceilings.

Read the real numbers for your key from caller.rateLimit and rpcProvider.quotaClasses rather than hard-coding them.

Conventions

  • Auth header is X-Starkscan-Api-Key on both surfaces; the chain string is SN_MAIN.
  • Pagination is limit plus an opaque cursor; responses carry nextCursor. Page until nextCursor is absent.
  • Every response carries x-request-id. Budgeted responses also carry x-ratelimit-limit, x-ratelimit-remaining, x-ratelimit-policy, and x-starkscan-route-class; quote the request id when reporting a problem.
  • REST errors use { code, message, docSlug, requestId }. JSON-RPC errors are typed JSON-RPC error objects, including authentication failures, so a standard client throws instead of silently resolving undefined.
  • Amounts are raw integer strings alongside decimals. Do not parse them as floating-point numbers.

When not to start here

  • Use Quickstart when you only need a first successful request.
  • Use Starkscan RPC when your client needs a node URL and standard JSON-RPC method names.
  • Use Agents when a coding agent or tool-calling client is the consumer.
  • Use the API reference when you need every path and parameter with live try-it execution.

On this page