Skip to content

Perpetuals API (Orderly)

All under /api/defi/orderly. Controller: bz-backend/controllers/defi/orderlyController.js.

Blazpay is an Orderly Network client. It manages the account lifecycle and the ed25519 request key; Orderly provides the order book, matching, settlement and liquidation.

Product page: perpetuals.

Account lifecycle

MethodPathPurpose
GET/defi/orderly/account-exits/:walletAddressDoes an Orderly account exist for this wallet? (typo for "exists" is in the route)
GET/defi/orderly/getNonce/:walletAddressRegistration nonce from Orderly
POST/defi/orderly/register/accountRegister the account after the user signs
POST/defi/orderly/add-orderly-keyGenerate and store the ed25519 request key

The ed25519 key

Orderly requires a separate keypair for signing API requests, distinct from the wallet key.

@noble/ed25519 generates the pair
bs58 encodes it
utils/kms.js encrypts the private half   →  models/orderlyAccount.js
getOrderlyKey(walletAddress) decrypts on demand
utils/orderlySigner.js → signAndSendRequest(accountId, privateKey, url, …)

This is the one place Blazpay custodies a signing key

It is an API key scoped to Orderly — it cannot move funds out of the user's wallet, and Orderly's withdrawal flow requires a fresh wallet signature. But it is a key the platform holds, encrypted at rest via AWS_KEY_ID_KMS. Treat models/orderlyAccount.js as sensitive data.

Orders

MethodPathPurpose
POST/defi/orderly/limit-orderCreate a limit order
POST/defi/orderly/tp-sl-orderCreate a take-profit / stop-loss order
PUT/defi/orderly/limit-orderEdit an order
POST/defi/orderly/limit-order/deleteCancel an order
GET/defi/orderly/ordersThe user's limit orders (getUsersLimitOrders)
GET/defi/orderly/getOrdersOrders (getOrders)

POST /defi/orderly/limit-order

FieldRequiredNotes
priceyesRejected with 400 if missing
quantityyesRejected with 400 if missing
symbolyese.g. PERP_ETH_USDC
leverageApplied to the account before the order
walletAddressyesResolves the Orderly account
sideDefaults to "BUY"

Before submitting, the controller:

  1. Loads the account (getExitingAccount) and decrypts the Orderly key.
  2. Fetches https://api-evm.orderly.org/v1/public/info/{symbol} and derives decimal places from base_tick.
  3. Calls setLeverageAccount(leverage, account, orderlyPrivateKey).
  4. Signs and posts to ${Orderly.publicUrl}order.

Tick-size rounding is not optional

Orderly rejects orders that violate tick size. getDecimalPlaces(filterSize.base_tick) is why quantity has to be rounded before submission — skipping it produces an opaque upstream rejection.

Leverage is account-level, not per-order

Orderly's model applies leverage to the account. setLeverageAccount is therefore called on every order, which means placing an order at a different leverage changes it for the whole account.

Positions

MethodPathPurpose
GET/defi/orderly/getPositions/:walletAddressOpen positions
POST/defi/orderly/close-positionClose a position
POST/defi/orderly/set-leverageSet account leverage

Withdrawal

MethodPathPurpose
GET/defi/orderly/get-available-withdraw/:walletAddressWithdrawable balance (getOrderlyHodlings)
POST/defi/orderly/request-withdrawSubmit a withdrawal request

Data model

CollectionContents
models/orderlyAccount.jsaccount_id, the KMS-encrypted ed25519 key, wallet mapping
models/limitOrder.jsOrder records

models/limitOrder.js is shared

It backs both perp orders and the unshipped spot limit-order product. Any query that does not filter by source mixes the two. See limit orders.

Configuration

Orderly in bz-backend/utils/constants.js holds publicUrl and related endpoints. The public info endpoint is https://api-evm.orderly.org/v1/public/info/{symbol}.

Helpers in utils/helpers.js: getDecimalPlaces, getExitingAccount, getOrderlyKey, setLeverageAccount, tInverse, sendResponse.

Frontend

SurfaceFile
Trading pagedefi-dex/src/pages/defi/perpetual.tsx (~710 lines)
Order historydefi-dex/src/pages/defi/PerpetualTransactions.tsx/defi/perpetual-transaction
SEO landing page/perpetuals via src/data/featureSeo.mjs

Failure modes

SymptomCause
400 "verify you are providing all the required details"price or quantity missing
Opaque upstream rejectionTick-size violation, or a symbol Orderly does not list
Leverage changed unexpectedlyIt is account-level; another order set it
Account not foundNo registration, or add-orderly-key never ran
Cannot decrypt the Orderly keyKMS misconfiguration (AWS_KEY_ID_KMS)
Everything fails at onceOrderly outage — Blazpay has no fallback venue for perps

Not covered

  • No BlazAI intent. The agent cannot open or manage a perp position; this is a deliberate scope decision.
  • Perp collateral does not appear in portfolio totals — it sits inside Orderly, and the portfolio is Zerion-backed wallet data.
  • Deposits happen through Orderly's own contract flow rather than a Blazpay endpoint.

Internal + developer documentation. Usage figures are point-in-time snapshots — re-verify before publishing them.