# Configuration


This page lists every field a `SomniaMarkets` instance accepts, with its type, whether it is required, and its default. Engine fields form `ClientConfig`; signer fields and `rpcWebSocketConstructor` belong to the configured root. For the values to put in these fields on each network, see [Networks and endpoints](./networks-and-endpoints).

```ts
import { SomniaMarkets } from "@somnia-chain/markets-sdk";

const exchange = new SomniaMarkets(config); // config: SomniaMarketsConfig
```

## `SomniaMarketsConfig`

`SomniaMarketsConfig` accepts one chain configuration or a `chains` list, plus the signer fields `privateKey`, `account`, and `walletClient`, and the optional root RPC constructor.

| Field                     | Type                                | Required | Default                                        | Description                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    |
| ------------------------- | ----------------------------------- | -------- | ---------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `indexerUrl`              | `string`                            | no       | none                                           | Envio/Hasura GraphQL endpoint over HTTP. A same-origin relative path is accepted in a browser. Omit for a chain-only client (smart accounts, executors, on-chain reads): every indexer read and live watch then throws `NotConfiguredError` naming this field.                                                                                                                                                                                                                                 |
| `indexerWsUrl`            | `string`                            | no       | `indexerUrl` with `http` replaced by `ws`      | The indexer's GraphQL WebSocket endpoint, for live account views (`client.accountOrders.subscribe`). Set it when `indexerUrl` is a relative path, or when subscriptions are served from another address. Without it and without an absolute `indexerUrl`, `subscribe` throws `NotConfiguredError` naming this field.                                                                                                                                                                           |
| `chain`                   | `Chain` (viem)                      | yes      | none                                           | The chain the markets live on.                                                                                                                                                                                                                                                                                                                                                                                                                                                                 |
| `wsRpcUrl`                | `string`                            | no       | `chain.rpcUrls.default.webSocket[0]`           | The WebSocket RPC endpoint, the main chain transport: subscriptions, reads, and writes use it. There is no HTTP fallback. Required when `chain` carries no WebSocket URL. While it is unset or equals the chain's default WebSocket URL, the chain's `send` and `session` endpoints take their methods; see [send and session endpoints](./networks-and-endpoints#send-and-session-endpoints).                                                                                              |
| `rpcWebSocketConstructor` | `SomniaMarketsWebSocketConstructor` | no       | managed `ws` on Node; native/isows in browsers | Standard RPC constructor selected once per exchange, shared as a class across its chain engines. Each engine owns a separate created socket. Also opens price-feed sockets; indexer HTTP reads do not use it.                                                                                                                                                                                                                                                                                  |
| `indexerHeaders`          | `Record<string, string>`            | no       | none                                           | Extra headers on every indexer request, for example a Hasura admin secret. Server-side only.                                                                                                                                                                                                                                                                                                                                                                                                   |
| `simulateIndexerOutage`   | `"down" \| "slow"`                  | no       | none                                           | Makes the client act as if its indexer has an outage. Read once when the client is created. See [Simulating an indexer outage](#simulating-an-indexer-outage).                                                                                                                                                                                                                                                                                                                                 |
| `signal`                  | `AbortSignal`                       | no       | none                                           | Cancels in-flight indexer reads and receipt confirmations. Client-wide, not per read. An indexer abort rethrows the caller's reason, not an `IndexerError`. A local or wallet write canceled before broadcast rethrows that reason. After broadcast, canceled confirmation throws `TransactionOutcomeUnknownError` with the transaction hash and the reason in `cause`. Check that hash before retrying the write. Other chain reads have their own 4-second request timeout.                  |
| `fees`                    | `FixedFees`                         | no       | `DEFAULT_FEES`                                 | Fixed EIP-1559 fees for SDK-signed writes.                                                                                                                                                                                                                                                                                                                                                                                                                                                     |
| `addresses`               | `SomniaMarketsAddresses`            | no       | `{}`                                           | Protocol contract addresses. Every entry is optional. A method that needs a missing address throws `NotConfiguredError` when it is called.                                                                                                                                                                                                                                                                                                                                                     |
| `priceFeed`               | `PriceFeedConfig`                   | no       | none                                           | The realtime price-feed endpoint. Required only by the price methods that fetch or watch (`watchPrice`, `fetchPrice`, `fetchPriceOHLCV`, and the client's `fetchPrice*` and `listPriceFeeds`). Its `quote` is mandatory to watch: an unpinned feed rejects `watchPrice`/`watchPrices` with `NotConfiguredError` because the tick tape's cursor is unique only within one quote; the one-shot reads still work unpinned. The `getLivePrice*` reads return `null` or `[]` until a watch is open. |
| `debug`                   | `(event: DebugEvent) => void`       | no       | none                                           | Receives structured debug events. When unset the SDK emits nothing and does no debug-only work.                                                                                                                                                                                                                                                                                                                                                                                                |
| `privateKey`              | `` `0x${string}` ``                 | no       | none                                           | A local signing key. The SDK signs locally and confirms in one round-trip.                                                                                                                                                                                                                                                                                                                                                                                                                     |
| `account`                 | `Account \| Address`                | no       | none                                           | A viem account, or a plain address to trade as through `walletClient`.                                                                                                                                                                                                                                                                                                                                                                                                                         |
| `walletClient`            | `WalletClient`                      | no       | none                                           | An external signer, for example an injected browser wallet.                                                                                                                                                                                                                                                                                                                                                                                                                                    |

### Counts and `indexerHeaders`

This section describes how the count methods (`countMarkets`, `countOrders` and the others) pick a query. A count first asks Hasura for `<Table>_aggregate`. Only a privileged role, such as the one an admin secret in `indexerHeaders` selects, has that field. On the public role Hasura rejects the field, and the count scans at most 10,001 ids instead.

The client remembers that rejection for five minutes. The memory is per client, endpoint, header set and table. In that window a count of the same table sends only the scan. The first counts of a table that run at the same time share one probe. Only Hasura's exact `field '<Table>_aggregate' not found in type: 'query_root'` error is remembered. Any other failure still throws and is not remembered. `stopLive()` clears the memory. After a role gains or loses the field, counts use the new permission within five minutes, or at once after `stopLive()`.

### Simulating an indexer outage

This section tells you how to test your app against an indexer outage. Set `simulateIndexerOutage`, and the client acts as if its indexer has an outage:

- `"down"`: every indexer read fails at once, as for an HTTP 503.
- `"slow"`: every indexer read waits 10 s and then fails, as for a database statement timeout.

No indexer request reaches the network. The failures go through the SDK's real error handling, so your app gets the same errors as in a real outage. Reads throw `IndexerError`. After five failures (`indexerLimits.breakerThreshold`), reads fail at once with `IndexerUnavailableError` for 30 s (`indexerLimits.breakerCooldownMs`). Live watches cannot load their indexer snapshot, and live account views fail to connect. Chain reads, writes and the price feed keep working. [What still works when the main indexer is down](./read-tiers#what-still-works-when-the-main-indexer-is-down) lists what your app can still show.

`client.getVenueHealth()` reports the indexer as `"down"` during a simulated outage. See [Check venue health](../how-to/check-venue-health).

The client reads the option once, when it is created. To switch it, for example from a developer menu, create a new client. Leaving out `indexerUrl` is not the same test: that gives `NotConfiguredError`, a different error path from a real outage.

For a configuration with `chains`, set the option on each chain binding so every engine receives it. For a single-chain configuration, set it at the root:

```ts
// Set from a developer menu; the app creates a new exchange when it changes.
const outage = localStorage.getItem("indexer-outage");
const simulateIndexerOutage = outage === "down" || outage === "slow" ? outage : undefined;
let exchange: SomniaMarkets;
if ("chains" in config) {
  exchange = new SomniaMarkets({
    ...config,
    chains: config.chains.map((binding) => ({ ...binding, simulateIndexerOutage })),
  });
} else {
  exchange = new SomniaMarkets({ ...config, simulateIndexerOutage });
}
```

### RPC constructor selection

Node connections use the SDK-managed `ws` transport by default. Replacing
`globalThis.WebSocket` or isows on Node does not select an RPC constructor.
Price-feed sockets use the same selection and the same explicit constructor.
Browsers retain their native/global/isows selection, including replacements
installed before or after SDK import. An explicit `rpcWebSocketConstructor`
selects the constructor on either platform, independent of import order.

The selected constructor receives only standard WebSocket arguments. RPC
construction calls `new Constructor(url)`. Price-feed construction calls
`new Constructor(url, "graphql-transport-ws")`. A protocol is always the
standard second string or string-array argument. The SDK retains the exact
returned socket and does not mutate the caller's constructor or prototype.
Constructor selection is lazy. Closing the owner during dependency loading
prevents construction, and an indexer-only exchange makes no RPC dial.

A supplied constructor is trusted infrastructure. Every created socket belongs
to this exchange and must promptly dispose connecting and open work through
`close()`, stop replacement dials and safely observe errors during retirement.
Sharing a class between exchanges must not share its created sockets. A standard
interface proves the calling convention, not physical disposal. Node 22's native
WebSocket does not satisfy this custom disposal obligation; use the managed
Node default or a conforming implementation.

**Migrating a Node override**

Replace global assignment with a per-owner input. `AppWebSocket` below is your
application's conforming constructor; `config` is its existing exchange config.

```ts
// Before
globalThis.WebSocket = AppWebSocket;
const exchange = new SomniaMarkets(config);
```

```ts
// After
const exchange = new SomniaMarkets({
  ...config,
  rpcWebSocketConstructor: AppWebSocket,
});
```

A compile-checked factory can make that ownership explicit:

```ts
import {
  SomniaMarkets,
  type SomniaMarketsConfig,
  type SomniaMarketsWebSocketConstructor,
} from "@somnia-chain/markets-sdk";

function createExchange(config: SomniaMarketsConfig, AppWebSocket: SomniaMarketsWebSocketConstructor) {
  return new SomniaMarkets({ ...config, rpcWebSocketConstructor: AppWebSocket });
}
```

Modeled operations preserve concrete SDK constructor/member failures by identity;
other transport failures become `RpcError` with the original value as cause.
Price watches follow the same rule when a price-feed socket cannot be selected
or constructed: `watchPrice` and `watchPrices` reject with the constructor's SDK
error, or with `RpcError` for any other thrown value.
Root validation rejects a non-function input with `InvalidInputError`. Unexpected
configuration-access failures become `InvariantError` with their original cause.
`close()` and the engine's `stopLive()` finish remaining cleanup before reporting
the first disposal failure. A disposal failure following an already delivered
operation timeout does not replace that timeout; it is retained for owner cleanup.
A constructor that violates the disposal obligation cannot receive a physical
release guarantee from the SDK. Undecorated viem operations retain their platform
operational contract after access.

### Signer resolution

A method that writes, or reads data scoped to the caller, resolves the caller's address in this order: `walletClient.account.address`, then `account.address`, then `account` when it is a string, then the address derived from `privateKey`. When none is set, `walletAddress` is `undefined` and every authenticated method throws `SignerRequiredError`.

`setSigner(signer)` replaces the signer after construction. Passing `{}` removes it. Live watches and market data are unaffected.

### Signer paths

| Aspect       | `privateKey` or a signing `account`                                                                                                      | `walletClient`                                                                                                                       |
| ------------ | ---------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------ |
| Who signs    | The SDK, locally                                                                                                                         | The wallet, after a user prompt                                                                                                      |
| Fees and gas | The fixed values from `fees` and the gas ceiling                                                                                         | The same fixed values, passed to the wallet as `maxFeePerGas`, `maxPriorityFeePerGas`, and `gas`                                     |
| Send path    | `eth_sendRawTransactionSync`: send and receipt in one round-trip; falls back to `eth_sendRawTransaction` when the node does not serve it | `eth_sendTransaction` through the wallet; the receipt is read on heads and after 1 s idle, within a 60 s total confirmation deadline |
| Reverts      | Decoded by replaying the failed call at the receipt's block                                                                              | Surfaced by the wallet's simulation before the prompt, with revert data                                                              |
| Approvals    | One `approve(maxUint256)` per token and spender, on the first order that needs it, cached for the trader's lifetime                      | The same, as a second wallet prompt                                                                                                  |
| Nonce        | Tracked locally after one fetch; reset on a rejected send                                                                                | Managed by the wallet                                                                                                                |

### Lazy connections

The viem chain WebSocket opens on the first chain read, write, or watch. An instance that only performs indexer reads never opens one. On a chain whose `send` endpoint has a WebSocket URL, a second chain socket opens on the first transaction send. On a chain whose `session` endpoint has one, a session socket opens on each session's first call. An endpoint without a WebSocket URL is used over HTTP and opens no socket. The price-feed WebSocket opens on the first `watchPrice`. `close()` stops the watches and channels and closes every socket the instance opened, both the price-feed WebSockets and the viem chain transport, so a Node process exits on its own afterwards. It also ends session calls in flight. Each instance owns its own chain socket, even when several use the same `wsRpcUrl`, so closing one never affects another.

## `FixedFees`

| Field                  | Type     | Description                                                                         |
| ---------------------- | -------- | ----------------------------------------------------------------------------------- |
| `maxFeePerGas`         | `bigint` | Fee ceiling in wei per gas. The unspent margin above base fee plus tip is refunded. |
| `maxPriorityFeePerGas` | `bigint` | Tip in wei per gas.                                                                 |

`DEFAULT_FEES` is `{ maxFeePerGas: 60_000_000_000n, maxPriorityFeePerGas: 0n }`: a 60 gwei ceiling and no tip.

### Gas

Every SDK-signed write uses a fixed gas ceiling of 10,000,000 gas. Gas is never estimated. Unused gas is not charged. The mempool accepts a transaction only when the account holds `gas × maxFeePerGas` on top of the transaction value: 0.6 STT or SOMI at the defaults. A lower-level write accepts a per-call `gas` override only when its public parameter type declares one. Unified exchange methods such as `createOrder` and `cancelOrder` do not expose that override.

## `SomniaMarketsAddresses`

Every field is optional and typed `Address`, except `lend`.

| Field                                            | Used by                                                                                                                                                                                                                                                                                                                 |
| ------------------------------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `collateral`                                     | The venue's collateral ERC-20. `faucet()` mints it on test networks.                                                                                                                                                                                                                                                    |
| `testUsdc`                                       | Legacy alias for `collateral`. `collateral` takes precedence.                                                                                                                                                                                                                                                           |
| `binaryModule`                                   | Complete-set mint and redeem, market creation, hub-approval reads, system diagnostics.                                                                                                                                                                                                                                  |
| `marketCreator`                                  | The live tail watches `MarketCreated` on it to discover new binary markets.                                                                                                                                                                                                                                             |
| `clobFactory`                                    | System diagnostics fallback.                                                                                                                                                                                                                                                                                            |
| `binaryPoolImpl`, `binaryPoolBeacon`             | Surfaced to apps. Not read by the SDK.                                                                                                                                                                                                                                                                                  |
| `binarySettlement`                               | `redeemDirect`, `claimOwed`, `getSettlement`.                                                                                                                                                                                                                                                                           |
| `operatorPermissionsRegistry`                    | Operator approval of a stop-order registry. Discoverable at runtime with `getOperatorPermissionsRegistry(pool)`.                                                                                                                                                                                                        |
| `marketsCore`                                    | Operator and venue reads, `createOperatorAdmin`.                                                                                                                                                                                                                                                                        |
| `collateralRouter`                               | The native-token and Permit2 complete-set path (`mintSetNative`, `mintSetPermit2`, `redeemNative`).                                                                                                                                                                                                                     |
| `marketCreatorFactory`, `marketCreatorFactoryV2` | `createMarketCreatorAdmin`.                                                                                                                                                                                                                                                                                             |
| `oracleHub`                                      | OracleHub reads and `createOracleHubAdmin`.                                                                                                                                                                                                                                                                             |
| `perpPoolFactory`                                | Perp discovery when the indexer has no perp rows. `loadMarkets` otherwise resolves the factory from `MarginBank.getSystemConfig()` on an indexed perp row, so this is needed only when there is no such row. Without it, discovery is SKIPPED and reports through `perpDiscoverySkipped`. When set it takes precedence. |
| `priceFeedScheduler`                             | The Somnia price feed that the perp pools' oracles read. `accountPositions.subscribe` has the node push the account's state on its price writes. Without it, marks follow a read every 5 s. The Shannon and Hideki constants set it.                                                                                    |
| `lend`                                           | `LendAddresses` for the third-party SomniaLend deployment. Backs `client.lend`.                                                                                                                                                                                                                                         |
| `fakeOracle`                                     | `resolve` and `voidMarket` on demo stacks.                                                                                                                                                                                                                                                                              |
| `oracleAdapterFactory`, `sharedOracleAdapter`    | Deprecated. Kept so old configurations type-check. Not read.                                                                                                                                                                                                                                                            |

`SOMNIA_MAINNET_ADDRESSES`, `SOMNIA_TESTNET_ADDRESSES` and `SOMNIA_HIDEKI_TESTNET_ADDRESSES`, exported from the root entry, hold the current deployments. `SOMNIA_MAINNET_LEND` and `SOMNIA_TESTNET_LEND` hold the SomniaLend addresses and are already included in the mainnet and testnet constants. Hideki has no SomniaLend deployment, so its preset omits `lend`.

## `PriceFeedConfig`

| Field   | Type     | Required | Default                            | Description                                                                                                              |
| ------- | -------- | -------- | ---------------------------------- | ------------------------------------------------------------------------------------------------------------------------ |
| `url`   | `string` | yes      | none                               | HTTP GraphQL endpoint of the price-feed indexer. One endpoint serves every asset.                                        |
| `wsUrl` | `string` | no       | `url` with `http` replaced by `ws` | WebSocket GraphQL endpoint for live subscriptions.                                                                       |
| `quote` | `string` | no       | none                               | Quote asset to pin every read to, case-insensitive. When unset, a base that trades against two quotes is double-counted. |

`SOMNIA_TESTNET_PRICE_FEED` is `{ url: "https://price-feed.dev.oracle.somnia.host/v1/graphql", quote: "USDC" }`.
`SOMNIA_MAINNET_PRICE_FEED` is `{ url: "https://price-feed.prd.oracle.somnia.host/v1/graphql", quote: "USDC" }`.
`SOMNIA_TOKYO_PRICE_FEED` is `{ url: "https://price-feed.tokyo-prd.oracle.somnia.host/v1/graphql", quote: "USDC" }`.
They index different chains; see [networks and endpoints](./networks-and-endpoints).

## Transport constants

| Constant                        | Value                              | Where                                                                                                                                   |
| ------------------------------- | ---------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------- |
| Ordinary RPC operation          | 9,000 ms cold total                | 4 s handshake, 4 s response and 1 s liveness probe; zero retries.                                                                       |
| Heavy `eth_getLogs` operation   | 35,000 ms cold total               | 4 s handshake, 30 s response and 1 s probe.                                                                                             |
| HTTP send or session request    | 8,000 ms                           | A request to a chain's `send` or `session` endpoint when that entry has no WebSocket URL. Handshake included; zero retries.             |
| Session sockets                 | 16 per chain engine                | One for each session. To open another, the engine closes the least recently used socket with no call in flight.                         |
| Failed subscription observation | 30,000 ms lease; 64 IDs per socket | Separate from operation timeout; a late ID gets a bounded 4 s unsubscribe. Lease expiry, capacity or failed cleanup retires the socket. |
| Indexer request timeout         | 30,000 ms                          | Every indexer read.                                                                                                                     |
| Default gas ceiling             | 10,000,000                         | Every SDK-signed write. Not exported.                                                                                                   |
| `DEFAULT_FEES.maxFeePerGas`     | 60 gwei                            | Exported from the root entry.                                                                                                           |
| Reconnect backoff               | 500 ms, doubling to an 8 s cap     | Live watches after a socket error.                                                                                                      |
| Watch linger                    | about 30 s                         | Time a scope stays materialised after its last handle stops.                                                                            |

---

Every page is also Markdown: append `.md` to its URL, or ask for `text/markdown`. Found something wrong, missing or confusing in these docs? Tell us: `POST /api/feedback` on this site with JSON `{"message": "…", "context": "what you were doing and what happened", "page": "…"}`, or a plain-text body. `GET /api/feedback` gives the JSON Schema. The team reads every one.
