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

AccountLayer hooks

React-query wrappers over @symmio/trading-core’s AccountLayer slice.

The page is split into two groups:

  • Reads — TanStack useQuery-shaped hooks. Same call = same cached result. Refetch on invalidation.
  • Writes — TanStack useMutation-shaped hooks. Trigger mutate / mutateAsync, watch isPending / data / error, and let the hook invalidate the affected reads for you.

Every write also has a paired useSimulateXyz — see Simulate then write.

Reads

useUserSubAccounts

Read a user’s subaccounts. Returns react-query’s full UseQueryResult shape.

import { useUserSubAccounts, useWalletAccount } from "@symmio/trading-react"; const { address } = useWalletAccount(); const { data, isLoading, error, refetch } = useUserSubAccounts({ user: address }); if (!address) return <p>Connect a wallet.</p>; if (isLoading) return <Spinner />; if (error) return <ErrorView kind={error.kind} message={error.message} />; return ( <ul> {data?.map((sub) => ( <li key={sub.accountAddress}>{sub.name}</li> ))} </ul> );

Parameters

NameTypeDefaultNotes
userAddress?undefinedEOA whose subaccounts to fetch. The query is disabled while this is undefined, so you can pass the connected address without a manual enabled guard.
offsetbigint?0nPagination offset.
limitbigint?200nPagination cap.
chainIdnumber?config defaultOptional chain override.
queryobject?undefinedTanStack Query overrides, including enabled.

Return type

UseQueryResult<readonly SubAccountDetail[], SymmioRequestError> — every field react-query exposes, with the SDK error type.

useAccountBalanceOf

Read the account’s available balance — deposited collateral idle on the account. For the instant (lowcap) flow this is the trading balance: deposits credit it, instant opens spend it, and withdrawals draw from it. Under the hood: balanceOf(account) on the SYMMIO diamond. See Balance Model.

import { formatEther } from "viem"; import { useAccountBalanceOf } from "@symmio/trading-react"; const { data, isLoading, error } = useAccountBalanceOf({ account }); if (isLoading) return <Spinner />; if (error) return <ErrorView kind={error.kind} message={error.message} />; return <span>{data === undefined ? "-" : formatEther(data)}</span>;

Parameters

NameTypeDefaultNotes
accountAddress?undefinedAccount address passed to balanceOf. The query is disabled while undefined.
chainIdnumber?config defaultOptional chain override.
queryobject?undefinedTanStack Query overrides.
configConfig?provider valueOptional config override.
liveboolean?falseSubscribe to the account’s on-chain settle notifications and refetch on each open/close settle (a shared WebSocket; requires the provider tree).

Return type

UseQueryResult<bigint, SymmioRequestError>.

The value is in the protocol’s 18-decimal internal units (not the collateral token’s decimals) — use formatEther / formatUnits(value, 18) to display.

useAccountBalanceInfo

Read the account’s classic-pool (allocated) balance info — collateral allocated to this account, plus the CVA / LF / margin locks currently held against it. Instant opens do not spend this pool — the instant flow trades from the available balance (useAccountBalanceOf); see Balance Model. Under the hood: balanceInfoOfPartyA(account) on the SYMMIO diamond.

import { formatEther } from "viem"; import { useAccountBalanceInfo } from "@symmio/trading-react"; const { data } = useAccountBalanceInfo({ account }); return <span>{data ? formatEther(data.allocatedBalance) : "-"}</span>;

Parameters

NameTypeDefaultNotes
accountAddress?undefinedAccount address passed as PartyA to balanceInfoOfPartyA. The query is disabled while undefined.
chainIdnumber?config defaultOptional chain override.
queryobject?undefinedTanStack Query overrides.
configConfig?provider valueOptional config override.
liveboolean?falseSame as useAccountBalanceOf, and it also refetches on any frame whose vaAddress equals account (the account’s Virtual Account just settled).

Return type

UseQueryResult<AccountBalanceInfo, SymmioRequestError>.

interface AccountBalanceInfo { allocatedBalance: bigint; lockedCVA: bigint; lockedLF: bigint; lockedPartyAMM: bigint; lockedPartyBMM: bigint; pendingLockedCVA: bigint; pendingLockedLF: bigint; pendingLockedPartyAMM: bigint; pendingLockedPartyBMM: bigint; }

All fields are in the protocol’s 18-decimal internal units (not the collateral token’s decimals).

usePredictedNextVirtualAccount

Predict the deterministic address of the Virtual Account (VA) a SubAccount will create for its next (isolationType, symbolId) position — before the trade lands on-chain and the VA exists. In lowcap, an instant open isolates each position into its own VA; the AccountLayer derives that address up front, so you can sign against it early. The main use: attaching TP/SL in the same flow as an instant open (the TP/SL order must be signed against the VA, not the SubAccount). Pair the side with isolationTypeForSide(positionType) to pick the isolation type.

import { isolationTypeForSide, PositionType, usePredictedNextVirtualAccount } from "@symmio/trading-react"; const positionType = side === "long" ? PositionType.LONG : PositionType.SHORT; const { data: predictedVa } = usePredictedNextVirtualAccount({ subAccount, isolationType: isolationTypeForSide(positionType), // MARKET_LONG / MARKET_SHORT symbolId: BigInt(market.symbol_id), }); // predictedVa → pass as `virtualAccount` to a TP/SL attached at open.

Parameters

NameTypeDefaultNotes
subAccountAddress?undefinedThe SubAccount that will open the position.
isolationTypeVirtualAccountIsolationType?undefinedIsolation bucket for the VA — use isolationTypeForSide(positionType).
symbolIdbigint?undefinedSolver market id of the position.
chainIdnumber?config defaultOptional chain override.
queryobject?undefinedTanStack Query overrides.
configConfig?provider valueOptional config override.

The query is disabled until subAccount, isolationType, and symbolId are all set. The prediction is stable per (subAccount, isolationType, symbolId) only until the SubAccount’s virtual nonce advances (i.e. it opens that isolation), so a short staleTime applies — override via query.staleTime.

Return type

UseQueryResult<Address, SymmioRequestError> — the predicted VA address.

Writes

Every hook below returns react-query’s UseMutationResult — call mutate(inputs) (or mutateAsync), watch isPending / data / error, and the hook invalidates the reads it affected on your behalf.

Building the instant (lowcap) flow? You need neither useAllocate nor useDeallocate. Instant trading spends the available balance; allocating moves funds into the classic pool and reduces what an instant open can use. Fund with useDeposit, exit with the withdraw hooks. See Balance Model.

useAllocate

Allocate a subaccount’s available balance into its allocated (tradeable) balance. The call inputs (account, amount) are passed to mutate; amount is in 18 decimals.

import { useAllocate } from "@symmio/trading-react"; const { mutate, isPending, isSuccess, data, error } = useAllocate(); <button onClick={() => mutate({ account: "0xsub...", amount: 1_000000000000000000n })} disabled={isPending}> {isPending ? "Sending…" : "Allocate"} </button>; { isSuccess && <p>tx: {data.hash}</p>; }

Options

interface UseAllocateParameters { waitForReceipt?: boolean; // default true — mutation resolves only after the receipt is mined confirmations?: number; // default 1 }

Cache invalidation

On success, the hook invalidates the subaccount’s useAccountBalanceInfo and useAccountBalanceOf queries in the active QueryClient, so allocated and available balances rerender automatically.

Dry run

useSimulateAllocate() runs the same call through simulateContract without sending — useful to surface a would-be revert before prompting the wallet.

useDeallocate

Deallocate a subaccount’s allocated (tradeable) balance back into its available balance — the reverse of useAllocate. The hook fetches a fresh Muon uPnL signature automatically before submitting (the contract requires it to prove the subaccount stays solvent), unless you pass one as upnlSig. amount is in 18 decimals.

import { useDeallocate } from "@symmio/trading-react"; const { mutate, isPending, isSuccess, data, error } = useDeallocate(); <button onClick={() => mutate({ account: "0xsub...", amount: 1_000000000000000000n })} disabled={isPending}> {isPending ? "Sending…" : "Deallocate"} </button>; { isSuccess && <p>tx: {data.hash}</p>; }

Options

interface UseDeallocateParameters { waitForReceipt?: boolean; // default true — mutation resolves only after the receipt is mined confirmations?: number; // default 1 }

Cache invalidation

On success, the hook invalidates the subaccount’s useAccountBalanceInfo and useAccountBalanceOf queries in the active QueryClient, so allocated and available balances rerender automatically.

Muon signature & cooldown

The hook calls getDeallocateUpnlSig for you unless you pass a upnlSig variable. Deallocate is subject to the on-chain debounce — submitting too soon after a prior deallocate reverts — and the result must keep the subaccount solvent; both surface as a normalized SymmioRequestError. useSimulateDeallocate() dry-runs the call (supply a upnlSig there — it does not auto-fetch).

useEditAccountName

Submit a rename transaction.

import { useEditAccountName } from "@symmio/trading-react"; const { mutate, isPending, isSuccess, data, error } = useEditAccountName(); <button onClick={() => mutate({ account: "0xsub...", name: "Trading bot" })} disabled={isPending}> {isPending ? "Sending…" : "Rename"} </button>; { isSuccess && <p>tx: {data.hash}</p>; } { error?.kind === "user-rejected" ? null : error && <p>{error.message}</p>; }

Options

interface UseEditAccountNameOptions { waitForReceipt?: boolean; // default true — mutation resolves only after the receipt is mined confirmations?: number; // default 1 }

Cache invalidation

On success, the hook invalidates every cached useUserSubAccounts query in the active QueryClient, so mounted lists rerender with the new name automatically. No manual invalidation needed.

Why this hook needs a connected wallet

The hook reads useSymmioWalletClient() under the hood. If the user is disconnected or on the wrong chain, calling mutate throws a SymmioRequestError with kind: "sdk" before any contract call is made. UIs typically gate the button on useWalletAccount().isOnExpectedChain to avoid the error path entirely.

Last updated on