Build a Perps DEX
Ship a perpetuals trading UI on SYMMIO — connect a wallet, pick a market, open and close leveraged positions, manage TP/SL. There are two ways to build it, and they walk the same flows; pick the path by your stack, not by the feature set.
Three facts integrators get wrong most often
Read these before you write any integration code — they trip up humans and AI agents alike:
- Affiliate is optional for trading. The
affiliatesAddressconfig field must be present, but the zero address is a valid default — trading works; register an affiliate only to earn a fee share. - Instant trading spends the available balance. Fund with a plain deposit and trade — no allocate step.
allocate/depositAndAllocatebelong to the classic pool and reduce instant margin. See the Balance Model. - Two decimal scales. Deposit/withdraw amounts use the collateral token’s decimals; account balances and quote values are 18-decimal internal units.
Most teams should build with React. Reach for the Core path only when you cannot use React — a Node.js service, a bot, or a non-React framework. The two guides cover the same DEX; the Core guide additionally makes you rebuild the runtime machinery the React layer ships for free.
Choose your path
- With React — recommended. Build on
@symmio/trading-react: a provider, hooks, stores, cache-invalidation, and WebSocket wiring on top of the SDK. This is how our ownapps/webis built and how most integrators should start. - With Core — framework-agnostic. Build directly on
@symmio/trading-corewith plain viem clients — no React, no hooks. For Node.js/server code, bots, or another framework (Vue, Solid, Svelte). You own every runtime concern the React layer would handle.
Both start from the same gate ladder — wallet → subaccount → collateral → delegation → market data → open → close → TP/SL — and call into the same underlying SDK. The difference is entirely in who wires the runtime: the React layer, or you.
Why React is the default
@symmio/trading-react is a small layer on top of @symmio/trading-core, but it does a lot of work for you. A perps DEX has to track live state that is easy to get wrong: rows that go stale, a position that flickers out while it is still opening, a TP/SL box that never confirms, a balance that lags after a trade settles. The React layer handles all of it for you:
| Runtime concern | @symmio/trading-react handles it | On Core, you build it |
|---|---|---|
| State stores | Optimistic instant-opens, transactions, and the TP/SL identity store (temp-id ↔ on-chain-id) ship as ready hooks | Three framework-neutral stores with the same shapes and transition rules |
| Cache invalidation | Every mutation’s onSuccess invalidates the exact query set via a subset-match predicate | Reimplement the predicate and wire the per-mutation invalidation matrix by hand |
| WebSocket orchestration | useManagedQuotes / useQuoteTpSl hide two sockets: reconnect re-sync, debounced burst invalidation, temp-id ↔ quote-id linking | Subscribe to both streams and rebuild all of that orchestration yourself |
| Optimistic seeding | Write-time seeds from mutation variables so the UI shows the target before the wire confirms | Seed your own stores at write-time from the same inputs |
| Events-first polling | Accelerated on-chain reads for in-flight rows; no idle poll while the socket is open | Drive the same polling policy from row lifecycle + socket state |
| Error normalization | Every query/mutation failure is wrapped into a discriminated SymmError / SymmApiError | Wrap your own failures into the same request-error type |
If your app is a React app, use the React guide and let the layer do this work. Rebuilding it on Core is more code and more ways to introduce silent desync — worth it only when React is off the table.
When to choose Core
Pick the Core path when React is not an option:
- Node.js / server-side — a headless execution service, a market-making bot, or a backend that opens and closes positions without any UI.
- A different framework — Vue, Solid, Svelte, or anything else.
@symmio/trading-coreis framework-agnostic on purpose so a non-React layer can be built on it. - Full control — you want to own state, caching, and transport rather than adopt the React layer’s opinions.
Core gives you the same correct primitives — but every runtime concern in the table above becomes yours. Budget for the three stores, the full invalidation matrix, and the two WebSocket-authoritative flows. Skipping them produces stale rows and silent desync, not loud errors. The Core guide spells each one out, but if you are on React, do not take this path — use the React guide.
Next steps
- With React — the hooks-based build on
@symmio/trading-react. - With Core — the framework-agnostic build on
@symmio/trading-core.