> ## Documentation Index
> Fetch the complete documentation index at: https://docs.0xmonaco.com/llms.txt
> Use this file to discover all available pages before exploring further.

# V1.0.55

# Monaco Protocol SDK v1.0.55

This release covers the consumer-facing changes since v1.0.54. Nothing in it changes a request or response field, and nothing changes for a client that upgrades and does nothing else. REST session authentication now accepts a second, opt-in signing protocol — RFC 9421 HTTP message signatures over the same Ed25519 session keys — alongside the legacy `X-Monaco-*` headers, which remain supported with no retirement date. The TypeScript and Rust SDKs can produce the new signatures, but both default to legacy, so opting in is a deliberate per-application step and one you should only take against a gateway that already verifies it. Alongside that, the OpenAPI specification now declares an authentication requirement on 24 endpoints that previously declared none — a specification correction, not a change in what the gateway enforces.

## Added

### Opt-in RFC 9421 request signing

REST session authentication accepts RFC 9421 HTTP message signatures as an alternative to the legacy `X-Monaco-PublicKey` / `X-Monaco-Timestamp` / `X-Monaco-Signature` headers. Both protocols use the same wallet-authorized Ed25519 session keys and run the same session expiry, revocation, delegated-agent permission, and account-restriction checks. WebSocket and gRPC signing are unchanged.

A signed request carries three headers:

```http theme={null}
Content-Digest: sha-256=:BASE64_SHA256_OF_BODY:
Signature-Input: monaco=("@method" "@path" "@query" "content-digest");created=1788868800;keyid="SESSION_PUBLIC_KEY_HEX";alg="ed25519"
Signature: monaco=:BASE64_ED25519_SIGNATURE:
```

Monaco verifies a bounded application profile rather than arbitrary RFC 9421 input. The signature label is `monaco` and exactly one dictionary member is accepted; the four covered components appear in the order shown; `created`, `keyid`, and `alg` are required; and extra components, extra labels, extra parameters, or another digest algorithm are rejected. `created` is an integer Unix timestamp in **seconds** within 30 seconds of server time — legacy timestamps are milliseconds. `keyid` is the registered session public key as 64 lowercase hexadecimal characters. `@query` begins with `?`, keeps raw ordering, duplicates and percent encoding, and is `?` when the query is absent. `Content-Digest` is RFC 9530 SHA-256 over the exact body bytes, including the empty body on a `GET`.

Presence of `Signature` or `Signature-Input` selects RFC verification, and failure never falls back to legacy: there is no automatic protocol downgrade. Sending `Signature` or `Signature-Input` alongside any `X-Monaco-*` header is rejected as `401 Unauthorized`. `Content-Digest` on its own is ordinary HTTP integrity metadata — it neither selects RFC verification nor overrides the body hash legacy verification computes independently.

The 30-second window bounds how long a captured signature stays usable; it does not stop an identical signed request from being accepted again inside that window, and Monaco keeps no nonce or replay cache. Use the endpoint's idempotency mechanism for exactly-once behavior, and when re-signing an aged-out retry, keep the original `idempotencyKey` and payload. See [HTTP message signatures](/reference/http-message-signatures) for the full profile, signature base, and migration sequence.

### `SDKConfig.requestSigning` selects the protocol in TypeScript

`createMonacoSDK` (and `new MonacoSDK`) accepts `requestSigning: "legacy" | "rfc9421"`, defaulting to `"legacy"`. The `RequestSigning` type is exported from `@0xmonaco/types`.

```typescript theme={null}
const sdk = createMonacoSDK({
  network: "staging",
  seiRpcUrl: "https://your-sei-rpc.example",
  requestSigning: "rfc9421",
});
```

In `rfc9421` mode the SDK signs the final URL path and query plus the serialized body, requires the body to be a string, sets `redirect: "error"` on authenticated requests so a signed request is never forwarded unchanged, and throws if the caller supplies any signature header itself. Public and backend-key requests keep their existing authentication either way. See [TypeScript migration](/reference/http-message-signatures#typescript-migration).

### `Client::new_authenticated` in the Rust REST SDK

The Rust REST SDK gains a signing client constructor:

```rust theme={null}
use monaco_sdk::{Client, RequestSigning, SessionSigner};

let signer = SessionSigner::new(session_private_seed, RequestSigning::Rfc9421);
let client = Client::new_authenticated("https://staging.apimonaco.xyz", signer);
```

It signs the session-authenticated operations the OpenAPI contract classifies and leaves public and backend-key operations unsigned. Authenticated clients disable HTTP redirects, which is why the constructor is available on native targets only — redirect policy is not enforceable on `wasm32`. Existing unsigned constructors are unchanged. `RequestSigning::Legacy` selects the legacy headers for a gateway that has not migrated, and the lower-level `SessionSigner::sign_at` helper signs a reusable `reqwest` request, with the caller responsible for preserving the signed bytes and disabling redirects. Streaming bodies are rejected rather than signed as empty. See [Rust migration](/reference/http-message-signatures#rust-migration) and [Sign Authenticated Requests](/sdk/rust-rest#sign-authenticated-requests).

## Fixed

### The specification declares authentication on 24 previously undeclared endpoints

The OpenAPI specification gains a `monacoHttpSignature` security scheme next to the existing `monacoSignature`, and every session-authenticated operation now lists both. While making that change, 24 operations were found to declare **no** security requirement at all, so the generated API reference and any client generated from the specification presented them as public:

* seven endpoints under `/api/v1/positions` — `GET /api/v1/positions`, `GET /api/v1/positions/history`, `GET /api/v1/positions/{positionId}`, `GET /api/v1/positions/{positionId}/risk`, `POST /api/v1/positions/batch-close-all`, `POST /api/v1/positions/{positionId}/close`, and `POST /api/v1/positions/{positionId}/tp-sl`. `GET /api/v1/positions/{positionId}/pnl/history` already declared its requirement and is unaffected
* all fourteen endpoints under `/api/v1/margin` — the margin account and parent margin account reads and their movements, `GET /api/v1/margin/collateral/available`, the collateral transfer-in and transfer-out endpoints, and the three `simulate-order-risk` endpoints
* the three conditional order endpoints, `GET /api/v1/orders/conditional`, `GET /api/v1/orders/conditional/{conditionalOrderId}`, and `DELETE /api/v1/orders/conditional/{conditionalOrderId}`

**The gateway always required a session signature on all of them** — this corrects the published contract, not the enforced one, so a client that was already signing these calls needs no change. A generated client that relied on the specification to decide what to sign was not signing them, and now will. A test asserts the specification's declared authentication against the gateway's registered route table, so an endpoint can no longer ship with the wrong contract.

### Request-body buffering is scoped to session-authenticated routes

The gateway buffered and hashed every request body globally so that signature verification could cover it. That buffer is now mounted only on session-authenticated resources. Signed routes still read and hash their bodies under the same 2 MiB bound; public and backend-key routes use their normal extractor limits instead. No request or response shape changes, and body hashing is not removed from any signed route.

## Upgrade

```bash theme={null}
npm install @0xmonaco/core@1.0.55 @0xmonaco/types@1.0.55 @0xmonaco/react@1.0.55 @0xmonaco/contracts@1.0.55
# or bun
bun add @0xmonaco/core@1.0.55 @0xmonaco/types@1.0.55 @0xmonaco/react@1.0.55 @0xmonaco/contracts@1.0.55
```

Upgrading changes nothing on its own: `requestSigning` defaults to `"legacy"` and the Rust SDK's existing constructors are untouched. Before selecting `rfc9421`, confirm the gateway you target verifies it, because there is no automatic downgrade — a client that opts in early fails closed. Never mix the two credential sets on one request. If you sign requests with your own client rather than an SDK, read the profile end to end before implementing it: the covered-component list, their order, the seconds-based `created`, and the exact digest encoding are all verified strictly. If you generate a client from the OpenAPI specification, regenerate it so the 24 corrected endpoints are signed, and audit any client generated before v1.0.55 to confirm it was not calling them unsigned.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.