Developer Quick Start - TypeScript â
Build your first o2 trade in minutes using the official SDK.
Prerequisites â
- Node.js v18+ (or Bun)
- A private key (we'll generate one below, or use an existing Fuel wallet key)
AI Tools â
Use AI assistants to help build and run your trading bot. See the Skills (gives AI agents the o2 integration workflow and patterns) and the MCP Server (trade via natural language).
1. Set Up Your Project â
mkdir o2-quickstart && cd o2-quickstart
bun init -y && bun install @o2exchange/sdkmkdir o2-quickstart && cd o2-quickstart
npm init -y && npm install @o2exchange/sdkCreate your trading script:
touch index.ts2. Get Test Funds â
Faucet is not available on mainnet. Deposit funds from your Fuel wallet to your trade account contract via the web-interface or via the Deposit flow.
3. Complete Trading Flow â
Create index.ts. The SDK handles network configuration, signing, encoding, and nonce management automatically.
Select your network (the SDK has built-in endpoints for each):
import { Network } from '@o2exchange/sdk';
const network = Network.MAINNET; // https://api.o2.appimport { Network, O2Client } from "@o2exchange/sdk";
// Configuration
const PRIVATE_KEY = "0xYOUR_PRIVATE_KEY"; // Use env vars in production!
async function main() {
// 1. Initialize client (use Network.MAINNET for production)
const client = new O2Client({ network: Network.TESTNET });
// 2. Load wallet
// Use loadWallet() for an existing key, or generateWallet() for a new one
const wallet = O2Client.loadWallet(PRIVATE_KEY);
console.log("Owner address:", wallet.b256Address);
// 3. Set up trading account
// Idempotent: creates account, mints test tokens (testnet/devnet),
// and whitelists â safe to call on every startup
const { tradeAccountId } = await client.setupAccount(wallet);
console.log("Trade account:", tradeAccountId);
// Wait for faucet funds to settle
await new Promise((r) => setTimeout(r, 5000));
// 4. Fetch markets
const markets = await client.getMarkets();
const market = markets[0];
const pair = `${market.base.symbol}/${market.quote.symbol}`;
console.log("Trading on:", pair);
// 5. Check balances
const balances = await client.getBalances(tradeAccountId);
for (const [symbol, bal] of Object.entries(balances)) {
console.log(`${symbol}: ${bal.trading_account_balance}`);
}
// 6. Create session
// Delegates trading authority to an ephemeral keypair.
// The session is stored on the client and used implicitly by trading methods.
// o2 sponsors gas for all session-based actions.
await client.createSession(wallet, [pair], 30);
console.log("Session created:", client.session!.sessionAddress);
// 7. Place an order
// Prices and quantities are human-readable strings â the SDK auto-scales them.
// SettleBalance is auto-prepended by default.
// Use a low price to avoid immediate fill; notional must be >= ~5 USDC.
const orderRes = await client.createOrder(pair, "buy", "1", "5");
console.log("Order tx:", orderRes.txId);
if (orderRes.success && orderRes.orders?.length) {
const order = orderRes.orders[0];
console.log("Order ID:", order.order_id);
// 8. Check open orders
await new Promise((r) => setTimeout(r, 3000));
const openOrders = await client.getOrders(tradeAccountId, pair, true);
console.log("Open orders:", openOrders.length);
// 9. Cancel order
if (openOrders.length > 0) {
await client.cancelOrder(openOrders[0].order_id, pair);
console.log("Order cancelled");
}
}
// 10. Check final balance
const finalBalances = await client.getBalances(tradeAccountId);
for (const [symbol, bal] of Object.entries(finalBalances)) {
console.log(`${symbol}: ${bal.trading_account_balance}`);
}
client.close();
}
main().catch(console.error);Run the script:
bun index.tsnpx tsx index.ts4. Batch Orders â
You can submit up to 5 actions per request using batchActions with type-safe action factories.
Create a new session scoped to the batch market, refresh the nonce, then submit:
import {
createOrderAction,
settleBalanceAction,
} from "@o2exchange/sdk";
await client.createSession(wallet, ["fFUEL/fUSDC"], 30);
await client.refreshNonce();
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);
if (response.orders) {
for (const order of response.orders) {
console.log(`${order.side} order: ${order.order_id}`);
}
}WARNING
createOrder automatically prepends a SettleBalance call (controlled by settleFirst, default true). When using batchActions, add settleBalanceAction() explicitly if needed. The total action count (including settle) must not exceed 5.
5. Deposit & Withdraw â
The easiest way to deposit and withdraw funds is through the o2 trading UI. The UI supports deposits from and withdrawals to EVM chains (Base, Ethereum) and Fuel wallets, and handles all bridging, wrapping, and unwrapping automatically.
Programmatic deposits & withdrawals coming soon
Fully integrated deposit and withdrawal support via the @o2exchange/sdk is currently in development.
In the meanwhile, if you want to go ahead, you can refer to the Fast Bridge docs and implement the deposit and withdrawal flow directly. For contract addresses and asset IDs, see the Network Identifiers page.
Key Concepts â
| Concept | Description |
|---|---|
| Trading Account | On-chain contract holding your balances and order state |
| Session | Ephemeral keypair authorized to trade. Enables fast trading without wallet popups |
| Nonce | Counter for replay protection. Auto-managed by the SDK |
| Gas Sponsorship | o2 pays gas fees for all session-based actions |
| setupAccount() | Idempotent â creates account, funds via faucet, whitelists. Safe on every startup |
| SettleBalance | Moves filled order proceeds into your available balance. Auto-prepended by createOrder |
Nonce management
The SDK auto-manages nonces. If you encounter errors after a failed transaction, call refreshNonce() to re-sync:
await client.refreshNonce();SDK Reference â
For the full API reference, advanced patterns (market making, WebSocket streams, external signers), and more examples, see the SDK documentation on GitHub.