Skip to Content
Symmio Trading-SDK — the SDK surface for builders on HyperEVM
CoreSolversOverview

Solvers

The solver APIs are off-chain REST endpoints configured per chain in createConfig. @symmio/trading-core exposes them as framework-agnostic actions plus TanStack Query option factories.

Use these APIs when you need solver metadata before building a trade flow: market lists, leverage limits, and locked percentages for a market/leverage pair.

Protocol model — intent-based, no orderbook

SYMMIO is intent-based. The current lowcap version has no orderbook. Positions are opened peer-to-peer between two roles:

  • partyA — the user. Sends an intent to open a position.
  • partyB — a solver. Watches partyA intents and takes the opposite side, becoming the direct counterparty.

Every lowcap position is one partyA ↔ one partyB agreement. There is no shared book, no matching engine, no other users on the other side. The solver is the counterparty.

Implications when building on the SDK:

  • No bid/ask depth to render. Prices come from off-chain feeds (see Price Service), not an on-chain book.
  • Trade lifecycle is intent → solver acceptance → on-chain settlement. Surface intent state, not order-fill progress.
  • partyA / partyB in ABIs, events, and notifications always mean user / solver respectively.

Markets

getMarkets

Fetch tradable markets from the chain solver’s /contract-symbols endpoint.

On Enigma, prefer getSymbols. It reads the same catalogue from the /symbols service but adds server-side filtering (name, asset, token, validity, per-side state) and pagination (limit / offset), so you fetch only the rows you need. Keep getMarkets when you want one call that also covers Rasa/symbols is Enigma-only.

import { getMarkets } from "@symmio/trading-core"; // Omit `solverId` → the `Market` union; narrow on `kind` for solver-specific fields. const markets = await getMarkets(config, {}); const btc = markets.find((market) => market.name === "BTCUSDT"); // Pass a literal solver kind → the exact per-solver market type. const rasa = await getMarkets(config, { solverId: "rasa" }); // RasaMarket[]

Parameters

NameTypeDefaultNotes
chainIdnumber?config defaultOptional chain override.
solverIdstring?default solverA literal solver kind ("enigma" / "rasa") narrows the returned market type.

ReturnsMarket[], the normalized SDK market shape. Market is a discriminated union EnigmaMarket | RasaMarket on kind; fields are camelCase and required (the SDK fills solver gaps), and maxLeverage is a number on every solver. Passing a literal solverId narrows the return to that kind (getMarkets(config, { solverId: "rasa" })RasaMarket[]); omitting it yields the union, which you narrow on kind to reach solver-specific fields.

Important market fields (all on Market):

FieldTypeNotes
kindstringDiscriminant: "enigma" or "rasa".
symbolIdnumberContract symbol id.
namestringSolver market name, often the value to pass as symbol.
symbolstringDisplay symbol.
maxLeveragenumberMaximum leverage accepted for this market.
state (Enigma)numberEnigma only — 0 disabled, 1 close only, 2 open only, 3 enabled. Narrow on kind === "enigma" to access.

getMarketsQueryOptions

Build TanStack Query options for getMarkets.

import { getMarketsQueryOptions } from "@symmio/trading-core"; import { useQuery } from "@tanstack/react-query"; const query = useQuery(getMarketsQueryOptions(config, { query: { staleTime: 30_000 } }));

Symbols (Enigma)

The /symbols service is the richer, preferred symbol catalogue on Enigma. Where getMarkets returns the whole /contract-symbols list in one shot, /symbols lets the solver do the work: filter by name, asset, token, validity, or per-side trading state, and page through the results — so a large catalogue costs one small request instead of a full download you filter yourself.

getSymbols

Fetch the tradable symbol catalogue from the Enigma solver’s /symbols endpoint. Enigma-only — calling it against a non-enigma solver throws UNSUPPORTED_BY_SOLVER.

import { getSymbols } from "@symmio/trading-core"; // First page, the solver's default of 100 rows. const symbols = await getSymbols(config, {}); // Server-side filtering + pagination: enabled "BTC" symbols, 20 per page. const page = await getSymbols(config, { search: "BTC", isValid: "true", stateLong: "enabled", limit: 20, offset: 0, });

Parameters

NameTypeDefaultNotes
chainIdnumber?config defaultOptional chain override.
solverId"enigma"?default solverMust resolve to an enigma solver.
limitnumber?100 (max 500)Page size.
offsetnumber?0Page offset for pagination.
symbolIdnumber?Restrict to a single symbol id.
searchstring?Case-insensitive substring match on the symbol name.
assetstring?Exact-match filter on the base asset.
tokenAddressstring?Exact-match filter on the collateral token address.
isValid"true" | "false" | "any"?"true"Validity filter; the solver defaults to valid-only.
stateLong"disabled" | "close_only" | "open_only" | "enabled"?Long-side trading-state filter.
stateShort"disabled" | "close_only" | "open_only" | "enabled"?Short-side trading-state filter.

ReturnsSolverSymbol[]. Same camelCase, gap-filled shape as an EnigmaMarket, except /symbols reports trading state per side (stateLong / stateShort) instead of the single state on getMarkets.

FieldTypeNotes
symbolIdnumberContract symbol id.
namestringSolver market name (e.g. "BTCUSDT").
symbolstringDisplay ticker.
maxLeveragenumberMaximum leverage (coerced to a number).
stateLongnumberLong-side state: 0 disabled, 1 close only, 2 open only, 3 enabled.
stateShortnumberShort-side state (same encoding).
isValidbooleanWhether the symbol is currently valid.

getSymbolsQueryOptions

Build TanStack Query options for getSymbols.

import { getSymbolsQueryOptions } from "@symmio/trading-core"; import { useQuery } from "@tanstack/react-query"; const query = useQuery(getSymbolsQueryOptions(config, { search: "ETH", limit: 50 }));

Trade volume & revenue (Enigma)

Three Enigma-only reads (each throws UNSUPPORTED_BY_SOLVER off Enigma, and each ships a matching …QueryOptions / …QueryKey factory).

getSolverRevenue

Revenue totals for a trailing window — protocol-wide by default, or one market’s share when symbolId is passed. Splits into a hedger-fee share and a funding share whose sum is totalRevenue, all as plain dollar numbers (no decimal scaling). Full reference: Revenue.

import { getSolverRevenue } from "@symmio/trading-core"; // Every market, since listing — the headline figure. const lifetime = await getSolverRevenue(config); // One market, trailing 24 hours. Always smaller than the protocol-wide total. const day = await getSolverRevenue(config, { symbolId: 1, timeRange: "24h" });

timeRange is a closed set — "1h" | "24h" | "7d" | "30d" | "lifetime" — and defaults to lifetime when omitted.

getTradeVolume

Daily trade-volume rows for one market from /trade-volume/{symbolId} — one { timestamp, volume } per day, ascending. timestamp is the solver’s ISO 8601 day bucket (e.g. "2026-07-09T00:00:00Z"); volume is a decimal string. symbolId is required. Full reference: Trade volume.

import { getTradeVolume } from "@symmio/trading-core"; const volume = await getTradeVolume(config, { symbolId: 1 }); const latest = volume.at(-1); // { timestamp: "2026-07-09T00:00:00Z", volume: "448.69…" }

getRevenueRecords

Incremental revenue records from /revenue/records, cursor-paginated on the record id. Returns { records, count }.

import { getRevenueRecords } from "@symmio/trading-core"; const { records, count } = await getRevenueRecords(config, { limit: 100 }); const nextCursor = records.at(-1)?.id; // pass back as `id` for the next page

Locked Params

getLockedParams

Fetch locked params from the chain solver’s /get_locked_params/{symbol} endpoint.

The symbol parameter is the solver path value. In trade UIs, use the selected market’s name when available, with symbol as a fallback.

import { getLockedParams } from "@symmio/trading-core"; const locked = await getLockedParams(config, { symbol: "BTCUSDT", leverage: 5, }); console.log(locked.cva, locked.lf, locked.partyAmm, locked.partyBmm);

Parameters

NameTypeDefaultNotes
symbolstringrequiredSolver market path value.
leveragenumberrequiredLeverage used to calculate locked params.
chainIdnumber?config defaultOptional chain override.

ReturnsSolverLockedParams.

interface SolverLockedParams { cva?: string; lf?: string; partyAmm?: string; partyBmm?: string; leverage?: string; }

getLockedParamsQueryOptions

Build TanStack Query options for getLockedParams.

import { getLockedParamsQueryOptions } from "@symmio/trading-core"; import { useQuery } from "@tanstack/react-query"; const options = getLockedParamsQueryOptions(config, { symbol: "BTCUSDT", leverage: 5, query: { staleTime: 10_000 }, }); const query = useQuery(options);

GetLockedParamsOptions requires symbol and leverage. The query factory does not make required action inputs optional and does not validate missing inputs inside queryFn.

For form UIs where values may be incomplete, gate the query outside the factory:

const ready = Boolean(symbol) && leverage > 0; const options = getLockedParamsQueryOptions(config, { symbol: symbol ?? "", leverage: leverage ?? 0, query: { enabled: ready }, });

getLockedParamsQueryKey

Build a cache key for a locked-params query.

import { getLockedParamsQueryKey } from "@symmio/trading-core"; const key = getLockedParamsQueryKey({ symbol: "BTCUSDT", leverage: 5, });

symbol and leverage are part of the key, so each market/leverage pair caches independently.

Notional Cap (available liquidity)

Per-market caps on how much notional the solver still permits — the frontline “can I open this size?” gate.

getNotionalCapBySymbolId

Cap for one market.

import { getNotionalCapBySymbolId } from "@symmio/trading-core"; const cap = await getNotionalCapBySymbolId(config, { symbolId: 1n }); // { used: bigint, cap: bigint, availability: bigint }

getNotionalCapAll

Batch — every market’s cap in one call. Cheaper than looping getNotionalCapBySymbolId.

import { getNotionalCapAll } from "@symmio/trading-core"; const caps = await getNotionalCapAll(config, {});

getOpenInterestBySymbolId

Used vs capped notional per market.

import { getOpenInterestBySymbolId } from "@symmio/trading-core"; const oi = await getOpenInterestBySymbolId(config, { symbolId: 1n });

Estimated price

getEstimatedPrice

Ask the solver what price an open or close would actually fill at — a read-only simulation of the trade (GET /estimated-price; nothing is submitted) → { estimatedPrice }. Pass the order quantity, the side, whether it’s an "open" or "close", and the slippage-adjusted request price the caller computed (calculateTradeParams().requestedOpenPrice for an open, calculateClosePrice() for a close) — not the raw mark. position_type is sent as "long" / "short".

import { getEstimatedPrice, PositionType } from "@symmio/trading-core"; const { estimatedPrice } = await getEstimatedPrice(config, { symbolId: 1, quantity: "1000", positionType: PositionType.LONG, entry: "open", price: requestPrice, });

getEstimatedPriceQueryOptions / getEstimatedPriceQueryKey ship alongside for TanStack; the React layer wraps them as useEstimatedPrice.

calculatePriceImpact

Pure helper — signed price-impact percent of an estimated fill vs a reference price: (estimated − reference) / reference × 100. Returns 0 for a zero / non-finite reference. The UI colors it by side.

import { calculatePriceImpact } from "@symmio/trading-core"; const impact = calculatePriceImpact({ estimatedPrice, referencePrice: markPrice }); // e.g. 0.42 → +0.42%

Rasa-only solver endpoints

The rasa solver (majors, on Base) exposes reads the enigma solver does not. Each is a normal getX action with a …QueryOptions / …QueryKey factory; calling one against a non-rasa solver throws UNSUPPORTED_BY_SOLVER. In React these are the Rasa Solver hooks. See Solvers & Chains for the kind model.

ActionPurpose
getSolverReadinessWhether the solver is up and accepting trades.
addSolverWhitelistAdd a partyA to the solver whitelist (a write, with addSolverWhitelistMutationOptions).
getSolverBalanceInfoSolver-side balance for an account.
getPartyAUpnlPartyA uPnL as computed by the solver.
getSolverOpenInterestGlobal open interest.
getSolverPriceRangeAccepted price range for a symbol.

Notification history search is not listed here: it is the unified searchNotifications, which dispatches to the rasa solver’s position-state endpoint (POST /position-state/{start}/{size}) for a rasa solver and returns the rasa result variant. See Notifications.

supportsEstimatedPrice

Pure predicate — whether the resolved solver kind supports the /estimated-price simulation. Gate the estimated-price read with it so a majors UI doesn’t call an endpoint its solver doesn’t serve.

import { supportsEstimatedPrice } from "@symmio/trading-core"; if (supportsEstimatedPrice(config, { solverId })) { // safe to call getEstimatedPrice for this solver }

getErrorMessage

Resolve a solver error code to a human message (getErrorMessageQueryOptions / …QueryKey alongside). The React wrapper is useErrorMessage.

Instant Open / Instant Close

The lowcap trading flows live on their own pages:

  • Instant OpeninstantOpen, instantOpenAuto, prepareInstantOpenParams, getInstantOpens, getInstantOpenQuoteId.
  • Instant CloseinstantClose, instantCloseAuto, instantCloseBulk, prepareInstantCloseParams, getInstantCloses.
  • SYMMIO Contract — on-chain reads. getOnchainContractMarkets is the contract-side analog to getMarkets.
  • Unified QuotesPendingInstantOpen / PendingInstantClose from getInstantOpens / getInstantCloses feed reconcileQuotes.
  • Errors — solver failures surface as SymmApiError.
Last updated on