Skip to main content

EVM Chains & Accounts

Sparky settles on EVM chains. This page explains how identity works, how you log in, and what "one deployment per chain" means for integrators.

1. Supported networks​

NetworkChain IDDeploymentNotes
Avalanche C-Chain43114MainnetPrimary settlement chain
Arbitrum One42161Mainnet
BNB Chain56Mainnet
Avalanche Fuji43113TestnetTest USDT, no real value
Arbitrum Sepolia421614TestnetTest USDT, no real value

Each network is served by a separate backend process with its own base URL (see Base URLs). The chain a deployment settles on is fixed by its CHAIN_ID / RPC_URL configuration and is echoed in the EIP-712 domain returned by GET /api/v1/auth/nonce/{address}.

2. Account identity = EOA address​

Your account on Sparky is your wallet address. There is no separate user id:

  • The backend keys balances, positions, orders, API keys and referral data by the lowercase EOA address.
  • accountAlias on /fapi/v2/balance is always "default" — one wallet address maps to exactly one account.

Per-chain isolation​

Because every chain is a separate deployment:

  • Balances are per chain. Depositing into the Avalanche Vault credits only your Avalanche account.
  • Positions and orders are per chain. There is no cross-chain margin.
  • API keys are per chain. Create keys on each deployment you trade on (max 30 per account per deployment).
  • Referral codes are per chain.

Use the same private key on every chain if you want a single identity; the backend never links deployments together.

3. Login (EIP-712 → JWT)​

The native /api/v1/* surface uses a JWT obtained by signing an EIP-712 typed message. The /fapi/* surface does not use JWTs — it uses API keys created with a JWT (see API Keys).

Client ──① GET /api/v1/auth/nonce/{address} ──▶ nonce + typed_data
──② sign typed_data with the wallet (off-chain)
──③ POST /api/v1/auth/login {address, signature, timestamp} ──▶ { token, expires_at }

3.1 Get nonce and typed data​

GET /api/v1/auth/nonce/{address}
{
"nonce": 1,
"typed_data": {
"types": {
"EIP712Domain": [
{ "name": "name", "type": "string" },
{ "name": "version", "type": "string" },
{ "name": "chainId", "type": "uint256" },
{ "name": "verifyingContract", "type": "address" }
],
"Login": [
{ "name": "wallet", "type": "address" },
{ "name": "nonce", "type": "uint256" },
{ "name": "timestamp", "type": "uint256" }
]
},
"domain": {
"name": "AXBlade",
"version": "1",
"chainId": 43114,
"verifyingContract": "0x0000000000000000000000000000000000000000"
},
"primaryType": "Login",
"message": {
"wallet": "0xYourWalletAddress",
"nonce": 1,
"timestamp": 1700000000
}
}
}

The domain.name is a legacy identifier kept for signature compatibility; always take the domain from this response rather than hard-coding it. chainId is the deployment's chain.

3.2 Sign​

// ethers.js v6
const { types, domain, message } = typed_data;
const { EIP712Domain, ...signTypes } = types; // ethers adds the domain type itself
const signature = await signer.signTypedData(domain, signTypes, message);

3.3 Exchange for a JWT​

POST /api/v1/auth/login
Content-Type: application/json
FieldTypeRequiredNotes
addressstringyesWallet address
signaturestringyes0x-prefixed EIP-712 signature
timestampnumberyesMust equal typed_data.message.timestamp (Unix seconds); rejected with TIMESTAMP_EXPIRED if more than 300 s from server time
{ "token": "eyJhbGciOiJIUzI1NiIs...", "expires_at": 1700086400 }

Send it as Authorization: Bearer <token> on every /api/v1/* call. Re-login when expires_at passes.

3.4 Privy embedded wallets​

The Sparky web app uses a Privy-based product model: users sign in with email, Google or an external wallet, Privy provisions an embedded EOA, and the front end exchanges the Privy access token for a Sparky JWT via POST /api/v1/auth/privy-login. For those sessions, order placement, cancellation, TP/SL and position close are authorised by the JWT alone — the signature field on those request bodies is a legacy/API-compatibility field that Privy sessions no longer rely on.

Programmatic integrators normally skip Privy and use the EIP-712 flow above, then create API keys for /fapi.

4. Which surface to use​

You are…UseAuth
A bot / market maker / SDK user/fapi/v1/*, /fapi/v2/*, /futures/data/*X-MBX-APIKEY + HMAC-SHA256
A front end or script that needs deposits/withdrawals or referral/api/v1/*Authorization: Bearer <JWT>
Reading public market dataeither /fapi/v1/* or /api/v1/markets/*none

API keys cannot withdraw. Withdrawals and referral actions always require a wallet-derived JWT.