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

Subgraph hooks

React hooks over the two per-chain GraphQL subgraphs (analytics + events). See Core Subgraph for the full data model, endpoint layout, and how to add missing queries.

Read only. Subgraphs are historical indexes — writing happens on-chain, then indexed here.

Import

import { useSubgraphQuery, useBalanceHistory, useTransferHistory, useQuoteHistory, useQuoteEventsByType, useQuoteFunding, useQuotesFunding, useQuoteGroupFunding, useQuoteGroupFundingHistory, useDepositHistory, useWithdrawHistory, } from "@symmio/trading-react";

Escape hatch — useSubgraphQuery

Send any raw GraphQL query against either subgraph. Use when the SDK doesn’t ship a pre-baked hook for what you need.

const history = useSubgraphQuery({ subgraph: "analytics", query: gql` query MyCustomQuery($account: String!) { myEntities(where: { account: $account }) { id value } } `, variables: { account: subAccount }, });

Returns UseQueryResult<T, SymmioRequestError> — same shape as every SDK hook. The response is parsed as-is; consumers own the type.

If you find yourself writing the same raw query across two components, that’s the signal to open a PR adding a typed hook — see Core Subgraph.

Pre-baked history reads

useBalanceHistory

Deposit / withdraw / allocate / deallocate events over time.

const history = useBalanceHistory({ account, first: 50, skip: 0 });

useTransferHistory

Every collateral in / out for an account.

const transfers = useTransferHistory({ account, first: 50, skip: 0 });

useDepositHistory / useWithdrawHistory

Filtered projections of the balance history for the two most common UI needs.

Per-quote history

useQuoteHistory

Terminal (close / liquidation) events for a set of accounts, newest first. Keyed on subAccounts — not on a quote id — because the subgraph filters history by the quote’s owning account. Pass the parent SubAccount and, when the positions are isolated, its Virtual Accounts.

const { data } = useQuoteHistory({ subAccounts: [subAccount], first: 100 }); const rows = data?.rows ?? [];

useQuoteEventsByType

Non-terminal events for one quote, filtered to the QuoteEventTypes you ask for → { rows, hasMore }. The indexed types are SettleUpnl (open-price recompute), ChargeFundingRate, and ChargeAccumulatedFundingFee; two presets ship with the SDK — PRICE_HISTORY_EVENT_TYPES (all three, the open-price timeline) and FUNDING_HISTORY_EVENT_TYPES (the two funding charges only).

import { FUNDING_HISTORY_EVENT_TYPES } from "@symmio/trading-core"; const { data } = useQuoteEventsByType({ quoteId: 42n, types: FUNDING_HISTORY_EVENT_TYPES, first: 20, });

useQuoteFunding

Funding totals — paid, received, netReceived — for one quote across its lifetime. Disabled while quoteId is undefined (an off-chain row).

const { data, isLoading } = useQuoteFunding({ quoteId: 42n }); /** `data` is `QuoteFundingData | null`: { quoteId, paid, received, netReceived }, all wei. */ const netReceived = data?.netReceived ?? 0n;

useQuotesFunding

Batch variant — funding for many quotes in one request, plus the running sums. Feeds “sum of funding across open positions” UI.

It takes quote-shaped rows, not bare ids: anything with an optional quoteId (a UnifiedQuote works as-is). Off-chain rows (quoteId === undefined) are skipped silently and duplicate ids are fetched — and summed — exactly once.

const { rows, netReceived, missingQuoteIds, isLoading } = useQuotesFunding({ quotes: group.quotes });

rows is aligned 1:1 with the input quotes (null for an off-chain or not-yet-indexed row). missingQuoteIds is every requested id while the query is in flight or failed, and the not-yet-indexed subset once it settles.

Group funding

Both hooks take a QuoteGroup and derive the child quote ids themselves: optimistic children (no quoteId) are dropped and duplicates collapsed, so one grouped position costs one subgraph round-trip.

Sign convention — shared with useQuoteFunding and useQuotesFunding above: netReceived = received − paid, the P&L perspective, so a positive value means the position earned funding. This matches QuoteFundingData.netReceived and the uPnL folds, and is the inverse of the cost-positive on-chain int256. A UI that colors “money in” green renders it as-is — no negation anywhere.

Settled to date only. These are funding charges the protocol has already applied and the analytics subgraph has indexed. Funding accrued since a quote’s last charge is not indexed anywhere and is therefore not included.

useQuoteGroupFunding

Aggregated settled funding for a whole group — the group-level counterpart of useQuoteFunding. Reads every child in one round-trip via useQuotesFunding, then folds with core’s pure aggregateGroupFunding. The result is memoized, so it is referentially stable while the group and its rows are unchanged.

function GroupedPositionFunding({ group }: { group: QuoteGroup }) { const { funding, isLoading } = useQuoteGroupFunding({ group }); /** `funding.netReceived` is a LOWER BOUND until `isComplete` is true — never render it as final before checking. */ if (isLoading || !funding.isComplete) return <FundingSkeleton />; /** Already income-positive: `netReceived > 0n` means the group EARNED funding. */ return <Money amount={funding.netReceived} label="Funding" />; }

funding is a QuoteGroupFunding: paid / received / netReceived (wei), resolvedCount, expectedCount, missingQuoteIds, and isComplete. Treat isComplete: false as “funding unknown”, not “no funding” — an all-optimistic or empty group reports false with netReceived: 0n. rows is the per-child QuoteFundingData | null, aligned 1:1 with group.quotes.

useQuoteGroupFundingHistory

The per-tick timeline behind that total: every child’s funding events as one merged, time-sorted stream. types is locked to FUNDING_HISTORY_EVENT_TYPES, so the hook takes only the group plus paging / sort.

const { data, isLoading } = useQuoteGroupFundingHistory({ group, first: 100 }); for (const row of data?.rows ?? []) { /** Rows arrive interleaved across quotes — `row.quoteId` says which leg this tick belongs to. */ const netReceived = (row.fundingReceived ?? 0n) - (row.fundingPaid ?? 0n); /** netReceived > 0n → the position earned funding on this tick. `row.rate` is the signed rate applied (wei). */ }

Returns a TanStack UseQueryResult<{ rows: QuoteEventRow[]; hasMore: boolean }, SymmioRequestError>. Paging is over the merged stream, not per quote id: pass first / skip and keep going while data.hasMore is true. Omitting first asks for the 1000-row ceiling the subgraph enforces, so an un-paged call loads the whole timeline unless the group has more ticks than one request can return. Pass orderDirection: "asc" for an oldest-first timeline. The query stays disabled while the group has no on-chain children.

On current deployments effectively every row is CHARGE_FUNDING_RATE; CHARGE_ACCUMULATED_FUNDING_FEE is part of the preset for completeness but is not yet emitted, so do not rely on seeing it.

Last updated on