Orders

Place order via RISExUniversalRouter. Client signs the permit (server holds no signer keys), the server builds the byte-packed payload and submits it via the Router.

Two auth flows: with a JWT (Authorization: Bearer) the order is executed against the account's OperatorHub allowance and no per-order signature is needed — omit permit. Without a JWT, sign the permit as described below. Everything from here on applies to the permit flow only.

Prerequisites:

  1. The account must already be registered on-chain; its first collateral deposit registers it. Until then every order fails FailedPrecondition: account <addr> is not registered (userId 0). The userId registry is fed by chain events, so for a few seconds after that deposit lands the error can still surface intermittently; retry instead of treating it as a signing problem.
  2. GET /v1/auth/eip712-domain — EIP-712 domain (name, version, chainId, verifyingContract = Authorization contract)
  3. GET /v1/nonce-state/{account} — nonce_anchor and current_bitmap_index (pass it as permit.nonce_bitmap_index; if 208 the anchor is full — use nonce_anchor+1 with bitmap index 0)
  4. GET /v1/system/config — router address (RISExUniversalRouter), used as the target field below

Order data — pack the order fields into a uint88, MSB to LSB:

[87:70] marketId    (16 bits)
[69:38] sizeSteps   (32 bits)
[37:14] priceTicks  (24 bits)
[13:6]  orderFlags  (8 bits)
[5:1]   version     (5 bits, must be 1)
[0]     reserved    (1 bit)

orderFlags bits: 0 side (1=Sell), 1 postOnly, 2 reduceOnly, 4:3 stpMode, 5 orderType (0=Market, 1=Limit), 7:6 timeInForce.

Header flags — a separate byte covering which optional fields are present: 0x01 permit (always set), 0x02 builderId != 0, 0x04 clientOrderId != 0, 0x10 ttlUnits != 0.

Action hash:

actionHash = keccak256(abi.encode(
  keccak256("RISE_PERPS_PLACE_ORDER_V1"),  // bytes32 action selector
  uint8(headerFlags),
  uint88(orderData),
  uint16(builderId),
  uint16(builderFeeBps),   // ONLY when builder_fee_bps > 0 — omit this slot otherwise
  uint64(clientOrderId),
  uint16(ttlUnits)))

Permit digest (EIP-712):

VerifyWitness(address account,address target,bytes32 hash,uint48 nonceAnchor,uint8 nonceBitmap,uint32 deadline)

Sign as standard EIP-712 typed data (e.g. ethers signTypedData) with hash = actionHash, target = RISExUniversalRouter address (NOT the OrdersManager, NOT the account, NOT the domain verifyingContract), nonceBitmap = permit.nonce_bitmap_index. Signing against the wrong target recovers a different address on every attempt and fails with SignerNotAuthorized.

Signature: 64-byte EIP-2098 compact (r + yParityAndS) or 65-byte (r+s+v, auto-converted). permit.signature is a protobuf bytes field — send it base64 over REST, not 0x hex.

post/v1/orders/place

Request

Request body

market_idinteger

Market ID (uint16)

size_stepsinteger

Order size in steps (uint32)

price_ticksinteger

Order price in ticks (uint24, max 16777215)

sideinteger

Order side: 0=Buy, 1=Sell

post_onlyboolean
reduce_onlyboolean
stp_modeinteger

Self-trade prevention: 0=ExpireMaker, 1=ExpireTaker, 2=ExpireBoth

order_typeinteger

Order type: 0=Market, 1=Limit

time_in_forceinteger

Time-in-force: 0=GTC, 1=GTT, 2=FOK, 3=IOC

builder_idinteger

Optional builder ID (uint16, 0 = none)

client_order_idstring uint64

Optional client order ID (uint64, 0 = none)

ttl_unitsinteger

Optional TTL units for GTT orders (uint16, 0 = none)

no_retryboolean
builder_fee_bpsinteger

Per-order builder fee in parts per million, denominator 1e6 (uint16, 0 = none). 100 = 1 bps = 0.01%. 10 = 0.1 bps. Must not exceed the user-signed max for this builder (see ApproveBuilderFee). Setting this non-zero changes the signed action hash: builder_fee_bps must be encoded as an extra uint16 word right after builder_id (which is always part of the hash) and before client_order_id/ttl_units. Leave at 0 to use the hash layout without that word.

Example request

{
  "client_order_id": "0",
  "permit": {
    "account": "0x742d35Cc6634C0532925a3b844Bc454e4438f44e",
    "signer": "0x1234567890123456789012345678901234567890",
    "nonce_anchor": "0"
  }
}

Response

A successful response.

order_idstring

Composite order ID: scOrderId-blockNumber-logIndex

tx_hashstring
block_numberstring uint64
sc_order_idstring uint64

Raw smart contract order ID for client reference

filled_quantitystring

Total filled size in WAD (1e18). Empty string for non-IOC orders; for IOC orders, "0" if unfilled.

messagestring

Human-readable fill status message. Only set for IOC orders.

filled_percentstring

Fill percentage (0-100, two decimal places). Only set for IOC orders.

Example response

{
  "order_id": "12345-100-0"
}

Changes