Skip to main content
The SDK reports the access state of an account in one of two ways. A status read returns the state as a value. A data read throws the state as a PerpsError. An empty list from a data read means only one fact: the account exists and has no rows.

Status reads and data reads

A status read tells you what the user must do next:
  • Lighter getAccount returns a zero fee tier and apiKeyRegistered: false when the wallet has no locally stored API key that matches the registered key. Otherwise it reads the fee tier with the resolved token and throws Unauthorized if Lighter rejects the token. getAvailableToTrade reads through getAccount, so it throws the same Unauthorized.
  • Ondo getAccount returns an empty account without a session, and Ondo accountExists returns false.
  • Ondo getDepositFlow and getWithdrawFlow return kind: 'setupRequired' without a session.
  • Hyperliquid accountExists returns false before the wallet’s first deposit, while getDepositFlow remains available.
Lighter getAccount throws in two cases:
  • AccountNotFound for a wallet with no Lighter account. Call accountExists before getAccount.
  • Unauthorized when an auth token resolves for the registered API key and Lighter rejects the token on the fee-tier read.

Fact to code

Each data read throws one code per fact:

Before and after a read

checkSetup() tells you before a read what the read will throw. The thrown code tells you after the read. Both report the same fact, with the Lighter token-ordering exception that follows the table. A UI can use one or both. For a Lighter wallet with no account, checkSetup() returns an empty setup list and an empty checklist, so it has no registerApiKey step to offer. Treat the missing account as the first fact: offer onboarding, also when a Lighter read throws SetupRequired. checkSetup() cannot predict Unauthorized, because the venue decides it when it receives the credential. On Ondo, the provider removes the rejected session token, so the next checkSetup() shows siweLogin as unsatisfied. checkSetup() is not a pure read. Call it once after each setup step, not before each data read. See checkSetup.

Per provider

Lighter

  • getOrders, getOrder, getFills, getActivity and getPortfolioHistory need an auth token. They throw SetupRequired when no token resolves, Unauthorized when Lighter rejects the token, and AccountNotFound when the wallet has no Lighter account.
  • These reads check the token before the account. A wallet with no Lighter account and no token gets SetupRequired.
  • When Lighter reports an SDK-owned read-only token as revoked, the SDK replaces the token and retries the read once. If Lighter rejects the new token, the read throws Unauthorized.
  • getPositions and getWithdrawableBalances need no token. Their only access code is AccountNotFound.
  • getAvailableToTrade reads through getAccount on every Lighter market. It throws AccountNotFound for a wallet with no Lighter account, and Unauthorized when an auth token resolves for the registered API key and Lighter rejects the token.
  • getMarketSettings needs no token. It returns the venue default for a wallet with no Lighter account.
  • getOrders with statuses: [] returns an empty list without a token. It sends no request to Lighter.
  • The WebSocket orderUpdates and positions channels throw SetupRequired at subscribe time when no token resolves. When no auth-token resolver is wired, they throw SDKError — a wiring defect, not an account state, so no account setup fixes it. See Lighter WebSocket.
  • orderUpdates, fills, positions and accountSummary each resolve the Lighter account index before the channel opens, so every one throws AccountNotFound at subscribe time for a wallet with no Lighter account — including fills and accountSummary, which need no token. accountSummary degrades to the public account_all variant instead of throwing when no token resolves.
See Lighter / Authentication for the token resolution order.

Ondo

  • getPositions, getOrders, getOrder, getFills, getActivity, getPortfolioHistory, getWithdrawableBalances, getAvailableToTrade and getMarketSettings need a session. They throw SetupRequired when no session token is stored, and the provider sends no request to Ondo.
  • When Ondo rejects the stored session token, the provider removes the token and that read throws Unauthorized. The next read throws SetupRequired.
  • Ondo opens the account at the SIWE login, so an Ondo data read does not throw AccountNotFound.
  • getOrders with statuses: [] also throws SetupRequired without a session.
  • The WebSocket account channels throw SetupRequired at subscribe time when no session is stored.

Hyperliquid

  • Hyperliquid account reads need no credential, so they do not throw SetupRequired.
  • getAccount, getPositions, getOrders, getOrder, getFills, getActivity, getPortfolioHistory, getWithdrawableBalances, getAvailableToTrade and getMarketSettings first check preTransferCheck.userExists. They throw AccountNotFound before reading account data when it is false.
  • getOrders with statuses: [] still performs the account check before returning an empty list.
  • orderUpdates, fills, positions, spotBalances, accountSummary and availableToTrade WebSocket subscriptions throw AccountNotFound before opening a venue channel.
  • accountExists remains a boolean status read, and getDepositFlow remains available before account creation.
  • A Hyperliquid /info read that the venue rejects with HTTP 401 throws Unauthorized.
See Error Codes for every code.