Accounts and sessions
Wallets and accounts
A Solana wallet owns one or more Nord accounts. Accounts hold balances,
positions, and orders, and are addressed by a numeric accountId. A wallet's
accounts are resolved from its public key:
- REST:
GET /user/{pubkey}returns the account IDs for a wallet. - SDK:
await user.updateAccountId()populatesuser.accountIds.
Account-scoped state is then read with GET /account/{account_id} and the
related endpoints, or with await user.fetchInfo(). Accounts owned by the same
wallet are subaccounts — separate margin and
positions under one wallet. Every action that can target an account takes an
optional accountId, and the SDK defaults to the first account of the wallet.
Sessions
Signing every order with a wallet key would be slow and would keep the wallet key hot. Instead, a wallet authorizes a session key: an ephemeral keypair allowed to submit actions on its behalf until the session expires.
The flow:
- The wallet signs a session-creation request naming the session public key and an expiry.
- The session key signs subsequent actions — orders, cancels, withdrawals, transfers.
- Before expiry, the session is refreshed; otherwise it lapses and actions are rejected.
With the SDK:
const user = NordUser.fromPrivateKey(nord, process.env.PRIVATE_KEY!);
await user.updateAccountId();
await user.refreshSession(); // create or replace the session
await user.selfRefreshSession(); // extend the current session
await user.selfRevoke(); // end the current session
await user.revokeSession(sessionId); // revoke a session by id, from the wallet
refreshSession(expiryTimestamp?, refreshDeadline?) accepts an explicit expiry;
without arguments it uses the SDK's default session lifetime. Order-entry calls
throw if there is no valid session, so treat "refresh before expiry" as part of
your run loop rather than something to retry after a failure.
NordUser.fromPrivateKey generates the session keypair for you. Browser
integrations construct NordUser with signing callbacks from a wallet adapter,
so the wallet only ever signs session creation, not each order.
Two signature framings are supported for session creation: hex message signing and Solana transaction framing, for wallets that will only sign transactions.
Nonces and action IDs
Actions are ordered per account and carry a nonce, and each accepted action
returns an actionId. The SDK tracks nonces internally; direct integrations read
them from the API:
| Purpose | Endpoint |
|---|---|
| Current exchange timestamp | GET /timestamp |
| Last acknowledged nonce | GET /event/last-acked-nonce |
| Last executed action ID | GET /action/last-executed-id |
See Signed actions for how these are assembled into a submittable action.
Operational guidance
- Keep the wallet key offline where possible; ship only the session key to the process that trades.
- Give sessions the shortest lifetime that fits your refresh loop.
- Revoke sessions when a process is retired — a revoked session cannot submit actions even if its key leaks.
- Never commit keys or session material. Load them from your secret store.