> ## 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

> Ondo's signing scheme: the SIWE session credential, the client-held API key, and the HMAC-signed trading relay

Ondo uses a **session-plus-API-key** scheme. The user signs in once with their wallet, and from then on trading executes without a per-trade wallet popup. Three signing methods appear across Ondo's actions:

* **`siwe`** — the one-time Sign-In-With-Ethereum login. The wallet `personal_sign`s a backend-issued ERC-4361 challenge.
* **`session`** — client-only setup steps the SDK runs directly against the venue with the session credential. No signed step returns to the backend.
* **`hmac`** — every trading action. The SDK signs each venue request with the API key and the backend relays the signed request to the venue.

## The SIWE session

The user's EVM-compatible signer — provided to the SDK via `userWallet` (`createPerpsClient`) or [`setUserWallet()`](/sdk/trading/methods#setuserwallet) — signs **one** thing on Ondo: the SIWE login challenge.

`createAction` for `siweLogin` returns a `SiweActionStep` carrying the challenge (`{ challengeId, message }`). The wallet `personal_sign`s the `message`, and the resulting `SiweSignedActionStep` (`{ action, siwe, signature }`) is submitted via `executeAction`. In exchange the venue issues a **session credential** the SDK holds client-side — it is never shared with LI.FI.

## The API key

The API key is a venue trading key the SDK creates during setup (the `registerApiKey` step) using the session credential. It is stored client-side and is used to sign every trading request thereafter.

**What the API key does:**

* Signs every trading action — `placeOrder`, `placeTriggerOrder`, `cancelOrder`, `cancelAllOrders`, and `updateLeverage`.

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

* It does not sign the SIWE login — that requires the user's wallet.
* It is not transmitted to the LI.FI backend. Only the per-request HMAC material (`{ keyId, timestampMs, signature }`) crosses the wire; the backend builds the venue's transport headers from it at relay time.

## The HMAC-signed trading relay

Trading actions are **HMAC-relayed**. `createAction` returns one or more `HmacActionStep`s, each an unsigned venue request:

```json theme={null}
{
  "action": "placeOrder",
  "request": {
    "method": "POST",
    "path": "/v1/perps/orders",
    "body": "{\"market\":\"BTC-USD.P\",\"side\":\"buy\",\"type\":\"limit\",\"size\":\"0.01\",\"price\":\"65000\",\"timeInForce\":\"GTC\"}"
  }
}
```

The SDK computes a per-request HMAC signature over the step from the API key and attaches it as a structured `hmac` field, yielding a `HmacSignedActionStep`:

```json theme={null}
{
  "action": "placeOrder",
  "request": { "method": "POST", "path": "/v1/perps/orders", "body": "..." },
  "hmac": { "keyId": "...", "timestampMs": 1736899200000, "signature": "..." }
}
```

`request.body` is a **pre-serialized string** that transits verbatim — it is the exact byte string the HMAC signature covers, and it is never re-serialized downstream. The backend relays the signed request to the venue and returns the venue's result.

## Client-only session steps

`createDepositAddress`, `acceptProviderTerms`, `registerApiKey`, and `setReferrer` are **`session`** steps. The SDK performs the venue call itself with the client-held session credential and skips `executeAction`. Most carry an empty session marker; `createDepositAddress` carries only the fixed public `{ network: 'ethereum', symbol: 'USDC', depositDestination: { wallet: 'margin' } }` policy. No venue path, headers, or credentials cross the marker.

## Who signs what

| Action                                                                                | Signing method | Signer                                                 |
| ------------------------------------------------------------------------------------- | -------------- | ------------------------------------------------------ |
| `siweLogin`                                                                           | `siwe`         | User's wallet (`USER`)                                 |
| `createDepositAddress`, `acceptProviderTerms`, `registerApiKey`                       | `session`      | Client-only venue call initiated for a user setup step |
| `setReferrer`                                                                         | `session`      | Provider plugin (`SDK`), completed internally          |
| `placeOrder`, `placeTriggerOrder`, `cancelOrder`, `cancelAllOrders`, `updateLeverage` | `hmac`         | Provider plugin (`SDK`) using the client-held API key  |
