React
@symmio/trading-react is the React layer on top of @symmio/trading-core. Every hook wraps a core action or query-options factory and threads it through useQuery / useMutation, plus a small set of Zustand stores for state that has no natural home in TanStack Query cache (optimistic quotes, TP/SL folded records, pending transactions).
Two rules govern the layer:
coreowns the logic. Contract calls, REST clients, subgraph queries, WebSocket parsing, math — all incore. Hooks are ~10 lines of glue: read config, resolve chain id, call the core factory, feed into TanStack.- State lives in stores. Reactive state that spans components (open trade queue, folded TP/SL rows, tx receipts) sits in module-level Zustand stores exposed as
useXxxStore()hooks. The stores are documented next to the hook that populates them.
What the wrapper gives you
When a hook wraps a core action, it doesn’t just forward — it takes care of the things every consumer would otherwise wire by hand:
- Cache invalidation done at the right places. Every write hook’s
onSuccessinvalidates the read queries the write actually mutated. FireuseAllocate(), and the allocated balance / collateral balance / party-scoped quote reads automatically refetch. You don’t chase down which queries went stale. See Cache invalidation. - Sensible refetch intervals baked in. Data hooks that need polling (
useManagedQuotes, price service reads, notional cap gates) ship with defaults calibrated to the underlying service — 5 s idle, ~1.5 s accelerated when a row is mid-transition, WS reports piggybacked to invalidate the next poll. You get “live” without picking numbers. - Full override access on every knob. Every hook accepts a
queryoverride (any TanStack option —staleTime,refetchInterval,enabled,select, …), an optionalconfigoverride, and an optionalchainIdoverride. Defaults are what most consumers want; overrides are one prop away when they aren’t.
Result: mount the provider, call the hook, render the data. Refetch, invalidation, and interval choices are already handled.
Install
pnpm add @symmio/trading-react viem wagmi @tanstack/react-queryPeer deps: react, react-dom, viem, wagmi. Transitive: @symmio/trading-core, @symmio/utils, zustand.
Mount the providers
The host owns the wagmi config and the QueryClient. SymmioProvider sits inside them, builds the core Config, and supplies it via context:
<WagmiProvider config={wagmiConfig}>
<QueryClientProvider client={queryClient}>
<SymmioProvider>{children}</SymmioProvider>
</QueryClientProvider>
</WagmiProvider>SymmioProvider reads wagmi’s connection state and bridges getPublicClient / getWalletClient into the core config. See SymmioProvider.
The hook pattern
Every read hook is the same three-line shape — this is intentional, so behavior is predictable across the whole library:
export function useMarkets(parameters = {}) {
const config = useSymmioConfig(parameters);
const chainId = useSymmioChainId();
return useQuery(getMarketsQueryOptions(config, { ...parameters, chainId }));
}useSymmioConfig(parameters)=parameters.config ?? contextConfig(mirrors wagmi’suseConfig).useSymmioChainId()reads the connected chain from wagmi.- The core factory owns the
queryKey,queryFn, and anyenabledguard.
Mutations follow the same shape via useMutation(xyzMutationOptions(config)). See Concepts › Hook pattern.
Concepts
- Hook pattern — the shape every read / write hook follows.
- Error normalization — how
SymmioRequestErrorclassifies transport / user-rejection / config failures. - Cache invalidation —
predicateMatchand the mutation invalidation pattern. - Simulate then write — the
useSimulateXyz→useXyzpattern for writes. - Stores — the three module-level Zustand stores and when they update.
Reference
Every domain slice, one page. Each mirrors its core counterpart plus the React-specific glue (invalidation on mutation success, provider access, store updates).
Provider + Wallet
- SymmioProvider — mount, chain overrides, WebSocket ctor override,
useSymmioConfig,useSymmioChainId. - Wallet —
useWalletAccount,useConnectWallet,useDisconnectWallet,useSwitchToSymmioChain.
Contract hooks
- AccountLayer — sub-account / virtual-account reads + writes.
- InstantLayer — delegation reads +
useGrantDelegation. - SYMMIO Contract — quote reads, party positions, collateral, allocate / deallocate, on-chain markets.
- Withdraw — request / cancel / finalize + polling helpers.
Trading
- Unified Quotes —
useManagedQuotes(polling + WS + reconciliation),useGroupedQuotes,useOptimisticQuotesStore. - Solvers —
useMarkets,useLockedParams,useNotionalCap*. Nested: - TP/SL —
useQuoteTpSl, mutations,useTpSlStore. - Markets — solver + on-chain market catalog hooks.
- Fees —
useFeeForUser,useQuotePlatformFee.
Data
- Price Service — REST + WS Enigma hooks, per-market helpers.
- Notifications —
useNotifications,useSearchNotifications. - Subgraph —
useSubgraphQueryescape hatch + history hooks. - Muon — oracle signature helpers.
- Notional Cap —
useNotionalCapAll,useNotionalCapBySymbolId,useOpenInterestBySymbolId. - Locked Params —
useLockedParams. - Error codes — solver error code + message lookup hooks.
Stores + utilities
- Transactions store —
useTransactionsStorefor pending write receipts. - Errors —
SymmioRequestErrordiscriminant,normalizeSymmError.
Convenience re-exports
@symmio/trading-react re-exports the most-used formatters from @symmio/utils so apps don’t have to add a second dependency for basic amount / address rendering:
formatTokenAmount,parseTokenAmount,rawToDecimal,decimalToRaw(from@symmio/utils/amounts)shortenAddress(from@symmio/utils/address)
For the full Decimal / currency toolkit, depend on @symmio/utils directly. See Utils.
Types like SubAccountDetail, SubAccountIsolationType, EditAccountNameParams, SymmError, and TpSlRecord are re-exported from core so app code doesn’t need to depend on @symmio/trading-core unless it wants to call standalone actions outside the React tree.