> ## Documentation Index
> Fetch the complete documentation index at: https://public-perps-docs.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Signing Model

> The two-part signing scheme on Lighter: the user's L1 wallet and the SDK-managed API key

Lighter uses a **two-part signing scheme** — the user approves a signer once, then trades execute without a per-trade wallet popup. Two keys sign two classes of action:

* 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.

Registering the API key is part of the one-time [Setup](/providers/lighter/setup) flow (the dual-signed `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 via `userWallet` (`createPerpsClient`) or [`setUserWallet()`](/sdk/trading/methods#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 signs `ChangePubKey` and 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.

Other trading and operational actions are handled by the plugin's public `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 via `REGISTER_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`, and `WITHDRAWAL`.

**What the API key does not do:**

* It is **not the L1 wallet** — it cannot sign the `DEPOSIT` transaction 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

Each `lighterProvider()` / `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 example `lifi-perps-lighter-key:lighter-rh:<l1-address>`.
* **Scope:** client-side only. The private key is never transmitted to the LI.FI backend.

If the local store is cleared (or the user is on a new device), the SDK has no signing key — [`checkSetup()`](/providers/lighter/setup) re-surfaces `REGISTER_API_KEY` and the user registers a fresh keypair at the same slot.

## Who signs what

| Action                                                                                                                    | Signer                                                                                         |
| ------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------- |
| `placeOrder`, `placeTriggerOrder`, `cancelOrders`, `modifyOrders`, `updateLeverage`, `updatePositionMargin`, `WITHDRAWAL` | SDK-managed API key (WASM signer, no popup)                                                    |
| `DEPOSIT`                                                                                                                 | User's L1 wallet (EVM transaction)                                                             |
| `REGISTER_API_KEY`                                                                                                        | **Both** — the new API key signs the `ChangePubKey` blob, the L1 wallet countersigns (EIP-191) |

## WASM signer dispatch

The provider instance owns the Go WASM signer and loads it once per process. Each action maps to a specific WASM call; applications do not load the module or dispatch methods themselves.

| Action                              | WASM call                                                                |
| ----------------------------------- | ------------------------------------------------------------------------ |
| `PLACE_ORDER`                       | `SignCreateOrder`                                                        |
| `CANCEL_ORDER`                      | `SignCancelOrder`                                                        |
| `CANCEL_ALL_ORDERS`                 | `SignCancelAllOrders`                                                    |
| `MODIFY_ORDER`                      | `SignModifyOrder`                                                        |
| `UPDATE_LEVERAGE`                   | `SignUpdateLeverage`                                                     |
| `UPDATE_POSITION_MARGIN`            | `SignUpdateMargin`                                                       |
| `WITHDRAWAL`                        | `SignWithdraw`                                                           |
| `TRANSFER` (internal, fastwithdraw) | `SignTransfer`                                                           |
| `REGISTER_API_KEY`                  | `SignChangePubKey` (dual-signed — see [Setup](/providers/lighter/setup)) |
