For the complete documentation index, see llms.txt. This page is also available as Markdown.

Submit a batch order

This guide shows how to send several intents in a single signed transaction using the orderbook's submitBatch envelope. A common use is to place an entry order together with its take-profit and stop-loss triggers atomically, so they all target the same auction tick.

For the envelope's rules and constraints, see Batch envelope in the Orderbook precompile reference. See the Orderbook precompile reference for the timestamp unit, deadline-alignment, and TTL rules that apply to every call below.

Each entry in inner is the full ABI-encoded calldata of a single-intent call (submitOrder, submitTrigger, etc.), and every sub-intent must carry the same deadline so the whole envelope lands in one tick.

Steps

  1. ABI-encode each single-intent call (entry order, take-profit trigger, stop-loss trigger).

  2. Pass them as the inner array to submitBatch.

The example opens a 5 NVDA long at $140 and arms two asset-grouped (position-bound), reduce-only triggers — a take-profit that sells at $160 and a stop-loss that sells at $120.

import { ethers } from "ethers";

const provider = new ethers.JsonRpcProvider("https://rpc.podtestnet.dev");
const wallet = new ethers.Wallet(PRIVATE_KEY, provider);

const ORDERBOOK = "0x50d0000000000000000000000000000000000002";
const abi = [
  "function submitOrder(bytes32 orderbookId, int256 size, uint256 price, uint8 orderType, uint128 deadline, uint128 ttl, bool reduceOnly, bool ioc)",
  "function submitTrigger(bytes32 orderbookId, int256 size, uint256 limitPrice, uint256 triggerPrice, uint8 triggerType, uint8 grouping, uint128 deadline, uint128 ttl, bool reduceOnly, bool ioc)",
  "function submitBatch(bytes[] inner)",
];
const orderbook = new ethers.Contract(ORDERBOOK, abi, wallet);

const nvdaPerpId = "0x0000000000000000000000000000000000000000000000000000000000000007"; // NVDA-USD perp
const now = BigInt(Date.now()) * 1000n; // microseconds

// One shared deadline for the whole envelope — required by submitBatch.
const deadline = now + 10_000_000n;
const ttl = 60n * 1_000_000n;
const size = ethers.parseEther("5"); // +5 NVDA long

// 1. Entry: 5 NVDA long at $140 limit
const entry = orderbook.interface.encodeFunctionData("submitOrder", [
  nvdaPerpId, size, ethers.parseEther("140"), 0 /* Limit */, deadline, ttl, false, false,
]);

// 2. Take-profit: sell 5 NVDA when price reaches $160 (reduceOnly, tied to the position)
const takeProfit = orderbook.interface.encodeFunctionData("submitTrigger", [
  nvdaPerpId, -size, ethers.parseEther("160"), ethers.parseEther("160"),
  0 /* TakeProfit */, 1 /* Asset */, deadline, ttl, true, false,
]);

// 3. Stop-loss: sell 5 NVDA when price drops to $120 (reduceOnly, tied to the position)
const stopLoss = orderbook.interface.encodeFunctionData("submitTrigger", [
  nvdaPerpId, -size, ethers.parseEther("120"), ethers.parseEther("120"),
  1 /* StopLoss */, 1 /* Asset */, deadline, ttl, true, false,
]);

// Submit all three as one atomic envelope
const tx = await orderbook.submitBatch([entry, takeProfit, stopLoss]);
console.log("Batch tx:", tx.hash);

Last updated