Skip to content
🌐Network: Mainnet

Orders

Guide for placing and cancelling orders through o2 SDKs.

Use the SDK when one is available for your language. The SDK handles session signing, nonce handling, market lookup, precision scaling, and request submission. Use the raw API examples only when you are building your own client or need lower-level control.

For endpoint-only reference, see POST /v1/session/actions. For the full session model, see Session Keys and Authentication & Signing.

Create Order

Create an order with the SDK first. Prices and quantities are human-readable strings in the SDK examples; the SDK scales them to the integer values expected by the API.

typescript
// Requires an active session for the market.
const result = await client.createOrder("fFUEL/fUSDC", "buy", "1", "5");

console.log("Order tx:", result.txId);
if (result.orders?.length) {
  console.log("Order ID:", result.orders[0].order_id);
}
python
# Requires an active session for the market.
from o2_sdk import OrderSide, OrderType

result = await client.create_order(
    market="fFUEL/fUSDC",
    side=OrderSide.BUY,
    price="1",
    quantity="5",
    order_type=OrderType.SPOT,
)

print(f"Order tx: {result.tx_id}")
if result.orders:
    print(f"Order ID: {result.orders[0].order_id}")
rust
// Requires an active session for the market.
use o2_sdk::{OrderType, Side};

let result = client
    .create_order(
        &mut session,
        "fFUEL/fUSDC",
        Side::Buy,
        "1",
        "5",
        OrderType::Spot,
        true,
        true,
    )
    .await?;

println!("Order tx: {}", result.tx_id.as_deref().unwrap_or("?"));
if let Some(orders) = &result.orders {
    println!("Order ID: {}", orders[0].order_id);
}

createOrder / create_order automatically prepends SettleBalance by default. The total action count, including settle, must not exceed 5.

Raw API

Raw order creation uses a CreateOrder action inside POST /v1/session/actions:

json
{
  "CreateOrder": {
    "side": "Buy",
    "price": "1000000000",
    "quantity": "5000000000",
    "order_type": "Spot"
  }
}

Use Precision & Decimals to convert human prices and quantities into raw integer values.

Order Types

The SDK examples above use a standard spot order. For common order-type variants, pass the corresponding SDK order type when your SDK exposes it. If your SDK version does not expose a helper for a specific advanced order type, use the raw API shape or the lower-level session action builder.

Order TypeUse When
SpotYou want a normal order that can fill immediately and rest on the book if not fully filled
MarketYou want immediate execution against available liquidity
LimitYou need execution at a specified price or better
PostOnlyYou only want to add liquidity as a maker
FillOrKillThe full order must execute immediately or fail
BoundedMarketYou want market-style execution with price protection

SDK Examples

typescript
import { createOrderAction } from "@o2exchange/sdk";

const postOnly = createOrderAction("sell", "2", "5", "PostOnly");
python
from o2_sdk import OrderSide, OrderType

batch = (
    client.actions_for("fFUEL/fUSDC")
    .create_order(OrderSide.SELL, "2", "5", OrderType.POST_ONLY)
    .build()
)
rust
use o2_sdk::{OrderType, Side};

let actions = client
    .actions_for("fFUEL/fUSDC")
    .await?
    .create_order(Side::Sell, "2", "5", OrderType::PostOnly)
    .build()?;

Raw API

Set CreateOrder.order_type to one of these values:

Order TypeRaw order_type Value
Spot"Spot"
Market"Market"
Limit{ "Limit": ["1000000000", "1734876543210"] }
Post Only"PostOnly"
Fill Or Kill"FillOrKill"
Bounded Market{ "BoundedMarket": { "max_price": "1100000000", "min_price": "900000000" } }

Notes:

  • Buy limit orders execute at the limit price or lower.
  • Sell limit orders execute at the limit price or higher.
  • PostOnly reverts if any quantity would execute immediately as a taker.
  • FillOrKill fails unless the full order can execute immediately.
  • BoundedMarket requires max_price greater than or equal to min_price.

Cancel Order

Cancel an open order by order ID.

typescript
await client.cancelOrder("0xORDER_ID", "fFUEL/fUSDC");
console.log("Order cancelled");
python
await client.cancel_order(
    order_id="0xORDER_ID",
    market="fFUEL/fUSDC",
)
print("Order cancelled")
rust
client
    .cancel_order(
        &mut session,
        "0xORDER_ID",
        "fFUEL/fUSDC",
    )
    .await?;

println!("Order cancelled");

Raw API

Raw cancellation uses a CancelOrder action inside POST /v1/session/actions:

json
{
  "CancelOrder": {
    "order_id": "0x..."
  }
}

For low-level signing details specific to cancellation, see Cancelling an Order.

Batch Order Actions

Batch actions let you submit multiple order actions in one request. Use them when you need atomic order placement, cancellation, and settlement behavior.

typescript
import {
  createOrderAction,
  settleBalanceAction,
} from "@o2exchange/sdk";

const response = await client.batchActions([
  {
    market: "fFUEL/fUSDC",
    actions: [
      settleBalanceAction(),
      createOrderAction("buy", "0.1", "50"),
      createOrderAction("buy", "1", "5"),
      createOrderAction("sell", "2", "5", "PostOnly"),
    ],
  },
], true);

console.log("Batch tx:", response.txId);
python
from o2_sdk import OrderSide, OrderType

batch = (
    client.actions_for("fFUEL/fUSDC")
    .settle_balance()
    .create_order(OrderSide.BUY, "0.1", "50")
    .create_order(OrderSide.BUY, "1", "5")
    .create_order(OrderSide.SELL, "2", "5", OrderType.POST_ONLY)
    .build()
)

result = await client.batch_actions([batch], collect_orders=True)
print(f"Batch tx: {result.tx_id}")
rust
use o2_sdk::{OrderType, Side};

let actions = client
    .actions_for("fFUEL/fUSDC")
    .await?
    .settle_balance()
    .create_order(Side::Buy, "0.1", "50", OrderType::Spot)
    .create_order(Side::Buy, "1", "5", OrderType::Spot)
    .create_order(Side::Sell, "2", "5", OrderType::PostOnly)
    .build()?;

let result = client
    .batch_actions(&mut session, "fFUEL/fUSDC", actions, true)
    .await?;

println!("Batch tx: {}", result.tx_id.as_deref().unwrap_or("?"));

Raw API

json
{
  "actions": [
    {
      "market_id": "0x1234567890abcdef...",
      "actions": [
        {
          "CreateOrder": {
            "side": "Buy",
            "price": "1000000000",
            "quantity": "100000000",
            "order_type": "Spot"
          }
        },
        {
          "CancelOrder": {
            "order_id": "0xabcdef..."
          }
        }
      ]
    }
  ]
}

The total action count, including SettleBalance, must not exceed 5.

  • Create or update a session before submitting session actions.
  • Session keys can place and cancel orders, but cannot withdraw funds.
  • Use the owner key for withdrawals and privileged account operations.
  • Use Nonces when coordinating retries or concurrent requests.