@liq/onchain
Onchain helpers for the Liq perpetuals exchange — deposits, collateral, accounts, positions, and settlement via viem.
Overview
@liq/onchain provides the LiqOnchain façade and individual service classes for all onchain interactions: depositing USDC collateral, managing SNX accounts, reading open positions, and submitting settlement transactions to the Synthetix V3 PerpsMarketProxy. It also exports the canonical contract ABIs. signOrder (EIP-712) is exported too, but only as an @internal transit for @liq/react. The only runtime dependencies are @liq/core and viem.
Key Exports
LiqOnchain (façade)
Instantiated with OnchainConfig ({ chainId, walletClient, publicClient }). Exposes:
| Property | Description |
|---|---|
.accounts | Create SNX account NFTs, set book mode |
.collateral | Read available + locked margins |
.deposit | USDC → sUSDC → modifyCollateral flow |
.positions | Read open positions from PerpsMarketProxy |
.delegate | Gasless relay reads: delegate address, state(user) |
.settlement | Call settleBookOrders() |
Builders (standalone, no wallet required)
DepositBuilder/WithdrawBuilder—build(): TxPlanreturns the deposit / withdraw steps; each step'sforwarderSafeflag says whether it can ride a wallet-sender batchexecuteTypedData(chainId, user, { calls, nonce, deadline })— thesignTypedDataarguments of a relayed batchclaimFaucetCall(faucetAddress, token)— the faucet claim as onePlanStep(forwarderSafe: false); sent by whichever sender the plan uses, wallet includedonchain.deposit.repay(debtWei)— the repay legs of a withdraw as a builder whosebuild()returns aTxPlan(WithdrawBuilder.afterRepay)tokenTransferPlan(token, amount, recipients)— aTxPlanof one direct ERC-20transferper recipient (forwarderSafe: false:transferreadsmsg.sender);tokenis the{ token, decimals }pair agetCollateralresult already is, so the address and its decimals cannot drift apart
Sending a plan
A builder only returns a TxPlan (readonly PlanStep[]); turning it into transactions is the sender's job, picked at the call site:
executePlan(plan, { sender, publicClient })— sends the plan group by group, waits for each receipt, stops at the first that doesn't landwalletSender(config)— batches a contiguousforwarderSaferun of steps into oneTrustedMulticallForwarder.aggregate3call; a step markedforwarderSafe: false(a bare ERC-20approve) goes as its own transactionrelaySender(config)— sends the whole plan as oneDelegate7702.executebatch through the gasless relay (ADR-0063)landedOrThrow(outcome, what)— the outcome as a throw: returnsLandedTx[]when the plan landed, throwsPlanRevertedError(or the sender/transport's own error) otherwise
Signing
signOrder is exported only as an @internal transit for @liq/react's useOrderSubmission; it is not a stable API (ADR-0012, 0.62.0 update).
ABIs
perpsMarketProxyAbi,perpsAccountProxyAbi,bookOrderModuleAbispotMarketProxyAbi,trustedMulticallForwarderAbi,isolatedMarginManagerAbi,erc20Abi- Legacy aliases:
PERPS_MARKET_PROXY_ABI,ERC20_ABI
Oracle helpers
OnchainMarketsService.getChainlinkFeedAddress(nodeId)— resolves a price node's Chainlink-type (RedStone) feed address, ornullwhen that node isn't type 3
Chain helpers
getViemChain(chainId)— returns viemChainobject for a given chain ID
Install
pnpm add @liq/onchain
Dependencies
@liq/core— chain config, contract addresses, shared typesviem— onchain interaction (read/write contracts, wallet client)
Build
moon run liq-onchain:build # tsup → dist/