Key Concepts¶
This page covers the core concepts you need to understand when integrating with the O2 Exchange via the Python SDK.
See also
For a comprehensive overview of the O2 Exchange architecture, see the O2 Exchange documentation.
On-chain order book¶
O2 is a central limit order book (CLOB) implemented entirely on-chain using Sway smart contracts on the Fuel Network. Unlike AMM-based DEXs, O2 matches orders in a traditional price-time priority order book.
All order matching, settlement, and balance management happens on-chain. The SDK communicates with an off-chain executor layer that sponsors gas and forwards signed transactions to the Fuel blockchain.
Wallets and identities¶
The SDK supports two types of wallets:
Type |
Address format |
Use case |
|---|---|---|
Fuel B256 ( |
Fuel-native accounts |
|
EVM address zero-padded to 32 bytes |
Ethereum/EVM accounts bridged to Fuel |
Both wallet types implement the Signer protocol and
can be used interchangeably throughout the SDK.
Trading accounts¶
A trading account is an on-chain contract that holds your balances and
tracks your nonce (action counter). It is identified by a trade_account_id
(a 0x-prefixed hex contract ID).
Use setup_account() to create or verify a
trading account. This method is idempotent and safe to call on every startup.
Sessions¶
The O2 Exchange uses a session-based signing model to avoid requiring the owner’s private key for every trade. When you create a session:
A temporary session keypair is generated.
The owner wallet signs a delegation that authorizes the session key to act on specific markets for a set duration.
Subsequent trade actions are signed with the lightweight session key.
Important
Session creation uses
personalSign(message prefix + hash).Session actions (orders, cancels, settlements) use
rawSign(plain SHA-256 hash).The SDK handles this distinction automatically.
Sessions are scoped to specific market contracts and expire after a configurable number of days (default: 30).
Nonce management¶
Every action on-chain increments the account’s nonce. The SDK caches and auto-increments the nonce, but there is an important caveat:
Warning
The nonce increments on-chain even when a transaction reverts. If an
action fails, the SDK automatically calls
refresh_nonce() to resynchronize.
You can also manually refresh the nonce:
nonce = await client.refresh_nonce(session)
Markets¶
A market represents a trading pair on the O2 Exchange (e.g.,
FUEL/USDC). Each market has:
A
contract_id— the on-chain contract managing the order book.A
market_id— a unique identifier within the contract.baseandquoteassets, each with their owndecimalsandmax_precision.Fee rates (
maker_fee,taker_fee),min_ordersize, anddustthreshold.
The SDK automatically resolves human-readable pair names (like
"fFUEL/fUSDC") to their on-chain identifiers.
Price and quantity scaling¶
On-chain, prices and quantities are represented as unsigned 64-bit integers scaled by the asset’s decimal places. The SDK converts between human-readable floats and on-chain integers automatically:
market = await client.get_market("fFUEL/fUSDC")
# Human → on-chain
chain_price = market.scale_price(0.025) # e.g. 25000
chain_qty = market.scale_quantity(100.0) # e.g. 100000000000
# On-chain → human
human_price = market.format_price(25000) # 0.025
human_qty = market.format_quantity(100000000000) # 100.0
Order types¶
The order_type parameter accepts OrderType enum
values for simple types, or typed dataclasses for Limit and
BoundedMarket:
Type |
Description |
|---|---|
|
Standard limit order. Rests on the book if not immediately matched. |
|
Executes immediately at the best available price. Fails if the book is empty. |
|
Guaranteed to be a maker order. Rejected if it would cross the spread and match immediately. |
|
Must be filled entirely or not at all. |
|
Like Spot but includes a limit price and a timestamp for time-in-force semantics. |
|
Market order with price bounds. |
Batch actions¶
The O2 Exchange supports submitting up to 5 actions in a single
transaction via batch_actions(). Actions are
strongly typed using dataclasses and grouped by market using
MarketActions:
CreateOrderAction— Place a new order.CancelOrderAction— Cancel an existing order.SettleBalanceAction— Settle filled order proceeds back to your trading account.RegisterRefererAction— Register a referer.
A common pattern is to settle + cancel + place in one batch:
from o2_sdk import OrderSide, OrderType
result = await client.batch_actions([
client.actions_for("fFUEL/fUSDC")
.settle_balance()
.cancel_order(old_order_id)
.create_order(OrderSide.BUY, "0.02", "100", OrderType.SPOT)
.build()
])
Signing model¶
Operation |
Signing method |
Details |
|---|---|---|
Session creation |
|
Fuel: |
Session actions |
|
Plain |
Withdrawals |
|
Same as session creation, signed with the owner key. |
The session wallet always uses Fuel-style signing, even when the owner is an EVM wallet.