AccountLayer
The AccountLayer contract is where SYMMIO subaccounts live. Each EOA can own multiple subaccounts; each subaccount can route trades into Virtual Accounts (VAs).
This slice also exposes SYMMIO core balance reads for accounts. The account input can be a subaccount or virtual account address depending on what the underlying SYMMIO method accepts.
Reads
getUserSubAccounts
List a user’s subaccounts.
import { getUserSubAccounts } from "@symmio/trading-core";
const subs = await getUserSubAccounts(config, {
user: "0xabc...",
offset: 0n,
limit: 200n,
});Parameters
| Name | Type | Default | Notes |
|---|---|---|---|
user | Address | — | EOA whose subaccounts to list. |
offset | bigint | 0n | Pagination offset. |
limit | bigint | 200n | Max number of subaccounts to return. Matches the Explorer Inspector page default. |
chainId | number? | config default | Optional chain override. |
Returns — readonly SubAccountDetail[].
interface SubAccountDetail {
accountAddress: Address; // proxy address on chain
owner: Address; // EOA that created this subaccount
name: string; // editable via editAccountName
isExists: boolean; // false if deleted
singleVAMode: boolean;
affiliate: Address;
symmioCore: Address;
metadata: Hex;
isolationType: SubAccountIsolationType;
}getAccountBalanceOf
Read the account’s available (deallocated) balance — collateral that lives on the account but is not currently allocated to any SubAccount for trading. This is the amount the user can transfer, withdraw, or allocate. Read via balanceOf(account) on the SYMMIO diamond.
import { getAccountBalanceOf } from "@symmio/trading-core";
const balance = await getAccountBalanceOf(config, {
account: "0xaccount...",
});Parameters
| Name | Type | Default | Notes |
|---|---|---|---|
account | Address | required | Account address passed to balanceOf. |
chainId | number? | config default | Optional chain override. |
Returns — bigint, in raw collateral token units. Use formatUnits(value, 18) / formatEther(value) or the utils package when displaying decimal values.
getAccountBalanceInfo
Read the account’s tradable (allocated) balance info — the collateral that has been allocated to this SubAccount and is available (or locked) for trading, together with the CVA / LF / margin locks currently held against it. Read via balanceInfoOfPartyA(account) on the SYMMIO diamond.
Pair with getAccountBalanceOf for the full picture: balanceOf is the free-to-move pot; balanceInfoOfPartyA is the allocated-and-in-play pot.
import { getAccountBalanceInfo } from "@symmio/trading-core";
const info = await getAccountBalanceInfo(config, {
account: "0xaccount...",
});
console.log(info.allocatedBalance);Parameters
| Name | Type | Default | Notes |
|---|---|---|---|
account | Address | required | Account address passed as PartyA to balanceInfoOfPartyA. |
chainId | number? | config default | Optional chain override. |
Returns — AccountBalanceInfo.
interface AccountBalanceInfo {
allocatedBalance: bigint;
lockedCVA: bigint;
lockedLF: bigint;
lockedPartyAMM: bigint;
lockedPartyBMM: bigint;
pendingLockedCVA: bigint;
pendingLockedLF: bigint;
pendingLockedPartyAMM: bigint;
pendingLockedPartyBMM: bigint;
}All fields are returned in raw collateral token units.
SubAccountIsolationType
enum SubAccountIsolationType {
POSITION = 0, // one VA per trade
MARKET = 1, // one VA per market
MARKET_DIRECTION = 2, // one VA per market + direction
CUSTOM = 3, // no automatic VA creation
}Writes
allocate
Move a subaccount’s available balance into its allocated (tradeable) balance — the
margin Party A trades against. The call is routed through the AccountLayer _call
proxy so the SYMMIO core attributes it to the subaccount; the connected wallet must
be the subaccount’s on-chain owner. The subaccount must not be suspended or in
liquidation as Party A.
import { allocate } from "@symmio/trading-core";
const hash = await allocate(config, {
account: "0xsub...",
amount: 1_000000000000000000n, // 18 decimals
});Parameters
| Name | Type | Notes |
|---|---|---|
account | Address | The subaccount to allocate into. The signer must equal its on-chain owner. |
amount | bigint | Amount moved into allocated balance, in 18 decimals (not collateral decimals). |
chainId | number? | Optional chain override. |
simulateBeforeWrite | boolean? | Dry-run via simulateContract first (defaults to the config’s setting, itself true by default). |
Returns — Hash (the broadcast tx hash).
Dry-run without sending via simulateAllocate(config, params).
deallocate
Move a subaccount’s allocated (tradeable) balance back into its available balance
— the reverse of allocate. Routed through the AccountLayer _call proxy; the
connected wallet must be the subaccount’s on-chain owner. Requires a fresh Muon
uPnL attestation so the contract can verify the subaccount stays solvent, and is
subject to the on-chain deallocate debounce.
import { deallocate, getDeallocateUpnlSig } from "@symmio/trading-core";
const upnlSig = await getDeallocateUpnlSig(config, { virtualAccount: "0xsub..." });
const hash = await deallocate(config, {
account: "0xsub...",
amount: 1_000000000000000000n, // 18 decimals
upnlSig,
});Parameters
| Name | Type | Notes |
|---|---|---|
account | Address | The subaccount to deallocate from. The signer must equal its on-chain owner. |
amount | bigint | Amount moved back into available balance, in 18 decimals (not collateral decimals). |
upnlSig | SingleUpnlSig | A fresh Muon uPnL attestation — fetch with getDeallocateUpnlSig right before submitting. |
chainId | number? | Optional chain override. |
simulateBeforeWrite | boolean? | Dry-run via simulateContract first (defaults to the config’s setting, itself true by default). |
Returns — Hash (the broadcast tx hash).
Dry-run without sending via simulateDeallocate(config, params).
editAccountName
Rename a subaccount.
import { editAccountName } from "@symmio/trading-core";
const hash = await editAccountName(config, {
account: "0xsub...",
name: "Trading bot",
});Parameters
| Name | Type | Notes |
|---|---|---|
account | Address | The subaccount being renamed. The signer must equal the subaccount’s owner on chain. |
name | string | New display name. |
chainId | number? | Optional chain override. |
Returns — Hash (the broadcast tx hash).
Query options
import {
getAccountBalanceInfoQueryOptions,
getAccountBalanceOfQueryOptions,
getUserSubAccountsQueryOptions,
} from "@symmio/trading-core";
useQuery(getAccountBalanceOfQueryOptions(config, { account }));
useQuery(getAccountBalanceInfoQueryOptions(config, { account }));
useQuery(getUserSubAccountsQueryOptions(config, { user }));Raw ABI
For consumers that want to call viem directly:
import { accountLayerAbi, symmioAbi } from "@symmio/trading-core";
await publicClient.readContract({
abi: accountLayerAbi,
address: accountLayerAddress,
functionName: "getUserSubAccounts",
args: ["0xabc...", 0n, 200n],
});
await publicClient.readContract({
abi: symmioAbi,
address: symmioAddress,
functionName: "balanceOf",
args: ["0xaccount..."],
});