- The user’s L1 wallet — any EVM-compatible signer that owns the funds.
- An SDK-managed API key — a Lighter-native (Schnorr-style) keypair the SDK creates and registers on-chain once.
REGISTER_API_KEY step). This page explains what the two signatures are and what the API key can and cannot do — Setup covers the step-by-step API.
The L1 (user) wallet signature
The user’s EVM-compatible signer — provided to the SDK viauserWallet (createPerpsClient) or setUserWallet() — is used only when a provider descriptor includes the public USER signer:
DEPOSIT— the on-chain EVM transaction(s) that fund the account (and create it on first deposit).REGISTER_API_KEY— the native key signsChangePubKeyand the L1 wallet countersigns its EIP-191 authorization.APPROVE_INTEGRATOR— the native key signs the approval blob and the L1 owner supplies the protocol-required EIP-191 signature.
SDK signer.
The API key
The API key is a Lighter-native keypair (Schnorr-style — not an EVM key). The SDK generates it, and its public key is registered on-chain in one of the account’s key slots viaREGISTER_API_KEY. Lighter verifies every trade against that registered public key. Signing happens inside a Go WASM signer that produces opaque { txType, txInfo, txHash } blobs.
What the API key does:
- Signs every trading and operational action —
placeOrder,placeTriggerOrder,cancelOrders,modifyOrders,updateLeverage,updatePositionMargin, andWITHDRAWAL.
- It is not the L1 wallet — it cannot sign the
DEPOSITtransaction or the EIP-191 countersignature for its own registration. Those require the account owner’s EVM wallet. - It cannot redirect funds — withdrawals are constrained to the account owner’s address by the backend, so a leaked API key cannot drain funds elsewhere.
- It is not an EVM key — it’s a Lighter-native (Schnorr-style) keypair that means nothing to an EVM chain; don’t reuse it as a wallet key.
How the API key is created
The SDK generates a fresh Lighter-native keypair client-side (LighterSigner.generateAPIKey()), then registers its public key on-chain at a key slot — slot 42 by default (DEFAULT_API_KEY_INDEX) — through the dual-signed REGISTER_API_KEY step. Re-registering the same slot overwrites the previous key.
How the API key is stored
EachlighterProvider() / lighterRhProvider() instance creates its own LighterKeyStore over the provider’s storage option. The default is encrypted browser localStorage; pass a custom adapter only for SSR, tests, or another persistence backend. Consumers do not construct or inject a key store separately. Each record holds { accountIndex, apiKeyIndex, apiKeyPrivateKey, apiKeyPublicKey }.
- Namespace: mainnet preserves
lifi-perps-lighter-key:<l1-address>; additional deployments include the provider key, for examplelifi-perps-lighter-key:lighter-rh:<l1-address>. - Scope: client-side only. The private key is never transmitted to the LI.FI backend.
checkSetup() re-surfaces REGISTER_API_KEY and the user registers a fresh keypair at the same slot.