### Install All Dependencies (Post Integration) Source: https://docs.o2.app/trading-agent/project-setup.html Installs all project dependencies, including those added from the o2 API example code. This command should be run after integrating external code or making changes to the dependency list. ```bash pnpm install ``` -------------------------------- ### Execute Trading Workflow Source: https://docs.o2.app/developer-quick-start-python.html A complete example demonstrating account setup, session management, order placement, and order cancellation using the O2Client. ```python import asyncio from o2_sdk import Network, O2Client, OrderSide, OrderType PRIVATE_KEY = "0xYOUR_PRIVATE_KEY" async def main(): client = O2Client(network=Network.TESTNET) wallet = client.load_wallet(PRIVATE_KEY) account = await client.setup_account(wallet) await asyncio.sleep(5) markets = await client.get_markets() pair = markets[0].pair session = await client.create_session(owner=wallet, markets=[pair], expiry_days=30) result = await client.create_order( market=pair, side=OrderSide.BUY, price="1", quantity="5", order_type=OrderType.SPOT ) if result.success: open_orders = await client.get_orders(account.trade_account_id, pair, is_open=True) if open_orders: await client.cancel_order(order_id=open_orders[0].order_id, market=pair) await client.close() if __name__ == "__main__": asyncio.run(main()) ``` -------------------------------- ### Initialize Project Environment Source: https://docs.o2.app/developer-quick-start-python.html Commands to set up a virtual environment, install the o2-sdk dependency, and create the main entry point script. ```bash mkdir o2-quickstart && cd o2-quickstart python -m venv venv source venv/bin/activate pip install o2-sdk touch main.py ``` -------------------------------- ### Integrate o2 API Example Code Source: https://docs.o2.app/trading-agent/project-setup.html Clones the trading-agent-bot repository, copies the `lib/` directory containing o2 API example code into the project, and cleans up the temporary clone. This provides interfaces for interacting with the o2 Exchange API. ```bash # Clone the trading-agent-bot repository git clone https://github.com/FuelLabs/trading-agent-bot.git temp-trading-bot # Copy the lib folder to your project cp -r temp-trading-bot/lib ./lib # Clean up temporary clone rm -rf temp-trading-bot ``` -------------------------------- ### Execute Trading Flow Source: https://docs.o2.app/developer-quick-start.html A complete example demonstrating how to initialize a client, set up a trading account, fetch markets, manage sessions, and execute/cancel orders. ```typescript import { Network, O2Client } from "@o2exchange/sdk"; const PRIVATE_KEY = "0xYOUR_PRIVATE_KEY"; async function main() { const client = new O2Client({ network: Network.TESTNET }); const wallet = O2Client.loadWallet(PRIVATE_KEY); const { tradeAccountId } = await client.setupAccount(wallet); const markets = await client.getMarkets(); const market = markets[0]; const pair = `${market.base.symbol}/${market.quote.symbol}`; await client.createSession(wallet, [pair], 30); const orderRes = await client.createOrder(pair, "buy", "1", "5"); console.log("Order tx:", orderRes.txId); client.close(); } main().catch(console.error); ``` -------------------------------- ### Initialize o2 Project Source: https://docs.o2.app/developer-quick-start.html Commands to create a new project directory and install the required o2 SDK dependencies using either Bun or NPM. ```bash mkdir o2-quickstart && cd o2-quickstart bun init -y && bun install @o2exchange/sdk ``` ```bash mkdir o2-quickstart && cd o2-quickstart npm init -y && npm install @o2exchange/sdk ``` -------------------------------- ### Install Project Dependencies Source: https://docs.o2.app/trading-agent/project-setup.html Installs both runtime and development dependencies required for the trading agent. This includes libraries for blockchain interaction, data fetching, and development tooling. ```bash # Install runtime dependencies pnpm install fuels@0.102.0 axios ccxt decimal.js pino pino-pretty yaml ethers # Install dev dependencies pnpm install -D typescript @types/node prettier ts-node ``` -------------------------------- ### Create Order Example (JavaScript) Source: https://docs.o2.app/parameters-reference.html Example of how to structure the 'actions' array for creating a spot buy order. This demonstrates the format for market_id and the nested actions object. ```javascript [ { "market_id": "0x...", "actions": [ { "CreateOrder": { "side": "Buy", "price": "1000000000", "quantity": "100000000", "order_type": "Spot" } } ] } ] ``` -------------------------------- ### Submit Batch Orders with O2 SDK Source: https://docs.o2.app/developer-quick-start.html Submits up to 5 actions per request using `batchActions` with type-safe action factories. This example demonstrates creating a new session, refreshing the nonce, and then submitting multiple order actions within a batch. ```typescript 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}`); } } ``` -------------------------------- ### Configure package.json Scripts Source: https://docs.o2.app/trading-agent/project-setup.html Defines essential scripts in package.json for building, running, formatting, and installing dependencies for the trading agent. These scripts automate common development tasks. ```json { "name": "trading-agent", "version": "1.0.0", "main": "dist/index.js", "scripts": { "build": "tsc", // Compile TypeScript to JavaScript "start": "tsc && node dist/src/index.js", // Build and run the agent "format": "prettier --write . --ignore-path .prettierignore", // Auto-format code "install:all": "pnpm install" // Install all dependencies } } ``` -------------------------------- ### Setup AI Rules Directory for Claude Code Source: https://docs.o2.app/skills.html Commands to create the required directory structure and move the o2 integration files into the project's rules folder for Claude Code. ```bash mkdir -p .claude/rules cp o2-skills.md o2-reference.md .claude/rules/ ``` -------------------------------- ### CreateOrder with BoundedMarket Example Source: https://docs.o2.app/api-endpoints/session-management.html An example of a JSON request body demonstrating the creation of an order using the BoundedMarket order type. This showcases how to specify the side, price, quantity, and the bounded market parameters. ```json { "CreateOrder": { "side": "Buy", "price": "1000000000", "quantity": "5000000000", "order_type": { "BoundedMarket": { "max_price": "1100000000", "min_price": "900000000" } } } } ``` -------------------------------- ### Run Trading Script Source: https://docs.o2.app/developer-quick-start-python.html Command to execute the completed Python trading script. ```bash python main.py ``` -------------------------------- ### Configure Network and Trading Client Source: https://docs.o2.app/developer-quick-start-python.html Demonstrates how to import the SDK components and configure the client to connect to a specific network environment. ```python from o2_sdk import Network network = Network.TESTNET ``` -------------------------------- ### Run Trading Script Source: https://docs.o2.app/developer-quick-start.html Commands to execute the TypeScript trading script using Bun or tsx. ```bash bun index.ts ``` ```bash npx tsx index.ts ``` -------------------------------- ### Example: Scaling Price for Blockchain Source: https://docs.o2.app/trading-agent/math-utilities.html Demonstrates the step-by-step process of converting a human-readable price into a blockchain-compatible integer representation. ```typescript const price = new Decimal(2500.50); const decimals = 9; const maxPrecision = 4; const scaled = price.mul(new Decimal(10).pow(decimals)); const truncateFactor = new Decimal(10).pow(decimals - maxPrecision); const truncated = scaled.div(truncateFactor).floor().mul(truncateFactor); ``` -------------------------------- ### GET /v1/markets Source: https://docs.o2.app/o2-skills.md Retrieves available markets and their configuration details. ```APIDOC ## GET /v1/markets ### Description Fetches a list of all active markets, including contract IDs, asset IDs, and decimal configurations required for order placement. ### Method GET ### Endpoint /v1/markets ### Response #### Success Response (200) - **markets** (array) - List of market objects containing market_id, contract_id, and asset details. #### Response Example { "markets": [ { "market_id": "0x...", "contract_id": "0x...", "base_asset": "0x...", "quote_asset": "0x..." } ] } ``` -------------------------------- ### Configure o2 Network Source: https://docs.o2.app/developer-quick-start.html Sets the network environment for the o2 client, specifically targeting the Mainnet endpoint. ```typescript import { Network } from '@o2exchange/sdk'; const network = Network.MAINNET; // https://api.o2.app ``` -------------------------------- ### Initialize Project Directory and pnpm Source: https://docs.o2.app/trading-agent/project-setup.html Creates a new directory for the trading agent and initializes it using pnpm. This is the first step in setting up the project environment. ```bash # Create project directory mkdir trading-agent && cd trading-agent # Initialize with pnpm pnpm init ``` -------------------------------- ### GET /v1/aggregated/summary Source: https://docs.o2.app/api-endpoints/aggregator-endpoints.html Get 24-hour market statistics and summary data for all trading pairs. ```APIDOC ## GET /v1/aggregated/summary ### Description Get 24-hour market statistics and summary data for all trading pairs. ### Method GET ### Endpoint /v1/aggregated/summary ### Request Example curl -X GET "https://api.o2.app/v1/aggregated/summary" -H "Accept: application/json" ### Response #### Success Response (200) - **summaries** (array) - An array of market summaries for all available pairs. ``` -------------------------------- ### Submit Batch Orders with o2 SDK Source: https://docs.o2.app/developer-quick-start-python.html Demonstrates how to create a session, refresh the nonce, and use the fluent builder to submit a batch of up to 5 trading actions. Note that the total action count, including auto-prepended settle balance calls, must not exceed the limit of 5. ```python from o2_sdk import OrderSide, OrderType await client.create_session(owner=wallet, markets=["fFUEL/fUSDC"], expiry_days=30) await client.refresh_nonce() 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}") if result.orders: for order in result.orders: print(f"{order.side} order: {order.order_id}") ``` -------------------------------- ### GET /v1/aggregated/ticker Source: https://docs.o2.app/api-endpoints/aggregator-endpoints.html Get real-time ticker data for all trading pairs, including last price and volume. ```APIDOC ## GET /v1/aggregated/ticker ### Description Get real-time ticker data for all trading pairs, including last price and volume. ### Method GET ### Endpoint /v1/aggregated/ticker ### Request Example curl -X GET "https://api.o2.app/v1/aggregated/ticker" -H "Accept: application/json" ### Response #### Success Response (200) - **tickers** (object) - A map of market pairs to ticker data. ``` -------------------------------- ### Create Source Directories Source: https://docs.o2.app/trading-agent/project-setup.html Creates the necessary source directories (`src/types` and `src/utils`) for organizing the trading agent's code. This is a standard practice for structuring Node.js projects. ```bash mkdir -p src/types src/utils ``` -------------------------------- ### Get Historical Price Bars (OHLCV) Source: https://docs.o2.app/api-endpoints/trading-data.html Get historical candlestick/bar data for charts. This endpoint is useful for technical analysis and visualizing price action over time. ```APIDOC ## GET /v1/bars ### Description Get historical candlestick/bar data for charts. ### Method GET ### Endpoint /v1/bars ### Parameters #### Query Parameters - **market_id** (string) - Required - The ID of the market. - **from** (number) - Required - The starting timestamp for the bar data (Unix timestamp). - **to** (number) - Required - The ending timestamp for the bar data (Unix timestamp). - **resolution** (string) - Required - The resolution of the bars (e.g., '1m', '5m', '1h', '1d'). - **count_back** (number) - Optional - The number of bars to retrieve counting back from the `to` timestamp. ### Request Example ```curl curl -X GET \ "https://api.o2.app/v1/bars?market_id=some_market_id&from=1678886400&to=1678972800&resolution=1h" \ -H "Accept: application/json" ``` ### Response #### Success Response (200) - **bars** (array) - An array of candlestick bar objects. - **timestamp** (number) - The timestamp of the bar (start of the interval). - **open** (string) - The opening price for the interval. - **high** (string) - The highest price during the interval. - **low** (string) - The lowest price during the interval. - **close** (string) - The closing price for the interval. - **volume** (string) - The total volume traded during the interval. #### Response Example ```json { "bars": [ { "timestamp": 1678886400, "open": "1.2345", "high": "1.2350", "low": "1.2340", "close": "1.2348", "volume": "500.0" } ] } ``` ### Limits Maximum 5000 bars per request. ``` -------------------------------- ### Ed25519 Signature Example (JSON) Source: https://docs.o2.app/api-endpoints/session-keys.html Example JSON structure for an Ed25519 signature, designed for high-performance applications requiring fast signing and verification. This scheme uses Curve25519. ```json { "signature": { "Ed25519": "0x..." } } ``` -------------------------------- ### Submit Batch Orders with Fluent Builder Source: https://docs.o2.app/developer-quick-start-rust.html Demonstrates how to create a session, refresh the nonce, and execute multiple trading actions in a single batch request. The total number of actions per request is limited to 5. ```rust use o2_sdk::{OrderType, Side}; let mut session = client .create_session( &wallet, &["fFUEL/fUSDC"], std::time::Duration::from_secs(30 * 24 * 3600), ) .await?; client.refresh_nonce(&mut session).await?; 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("?")); if let Some(orders) = &result.orders { for order in orders { println!("{} order: {}", order.side, order.order_id); } } ``` -------------------------------- ### Market Maker Cycle Example (Pseudocode) Source: https://docs.o2.app/o2-skills.md Illustrates the core logic of a market maker bot. This pseudocode outlines a typical cycle involving fetching external prices, managing existing orders, settling balances, and placing new orders. All actions are grouped within a single `session/actions` request for atomic execution. ```pseudocode // Fetch external reference price // Cancel stale orders // Settle balance // Place symmetric buy/sell orders around the spread // Sleep // Repeat ``` -------------------------------- ### Secp256r1 Signature Example (JSON) Source: https://docs.o2.app/api-endpoints/session-keys.html Example JSON structure for a Secp256r1 signature, suitable for browser applications using passkeys or hardware security modules. This signature type is part of the NIST standard. ```json { "signature": { "Secp256r1": "0x..." } } ``` -------------------------------- ### Secp256k1 Signature Example (JSON) Source: https://docs.o2.app/api-endpoints/session-keys.html Example JSON structure for a Secp256k1 signature, commonly used with Fuel wallets and the fuels TypeScript SDK. This format is used in API requests to specify the signature type and its value. ```json { "signature": { "Secp256k1": "0x..." } } ``` -------------------------------- ### Example O2 Bot Configuration File (YAML) Source: https://docs.o2.app/trading-agent/configuration.html Provides a sample `config.yaml` file for the O2 Trading Agent Bot, configured for the testnet. It includes settings for general parameters, market details, order sizing, timing, price feeds, strategy adjustments, and account credentials. ```yaml # Example configuration file for the Trading Agent Bot # General Settings general: # The logging level (e.g., DEBUG, INFO, WARNING, ERROR) log_level: INFO # The URL of the Fuel network network_url: https://testnet.fuel.network/v1/graphql # o2 Trading Agent Bot Settings o2: # The base URL for the O2 API base_url: https://api.testnet.o2.app # o2 Market configuration # Adjust these settings to specify which market to trade on # As of now, only one market configuration is supported market: # Market identifiers market_id: '0x09c17f779eb0a7658424e48935b2bef24013766f8b3da757becb2264406f9e96' contract_id: '0x2a78ab167c28f474d2ad62daabe7a42ce03f066dd8aa7cf57b984d14e4bd907b' # Trading pair symbols base_symbol: ETH quote_symbol: USDC # Order sizing # Value of each buy/sell order in terms of USDC order_usdc_value: 10 # Timing configuration # Interval between a single buy and sell order, in seconds order_interval_seconds: 1 # Interval between multiple buy & sell order pairs, in seconds order_pairs_interval_seconds: 2.5 # Price feed configuration # Corresponding Bitget trading symbol (format: BASE/QUOTE) # This is used to determine the price of orders on O2 bitget_symbol: ETH/USDC # If true, use the inverse price (1/price) instead of the regular price # Useful for inverse pairs e.g. USDC/USDT -> USDT/USDC reciprocal_rate: false # Whether to convert the Bitget price quotation to USDC # Useful for O2 assets that do not have a USDC pair on Bitget # Example: To get FUEL/USDC price, fetch FUEL/USDT and USDT/USDC from Bitget convert_to_usdc: false # Strategy configuration # A factor to adjust the price fetched from Bitget # Example: 0.05 increases buy price by 5% and decreases sell price by 5% price_adjustment_factor: 0.1 # Order type for trading # Available options: Spot, FillOrKill order_type: Spot # Account credentials account: # Private key of a wallet with funds on O2 private_key: '' ``` -------------------------------- ### GET /v1/orders Source: https://docs.o2.app/o2-reference.md Query order history and status for an account. ```APIDOC ## GET /v1/orders ### Description Retrieves a list of orders based on market and account filters. ### Method GET ### Endpoint /v1/orders ### Parameters #### Query Parameters - **market_id** (string) - Required - **contract** (string) - Required - **direction** (string) - Required - **count** (number) - Required - Max 200 - **is_open** (boolean) - Optional ### Response #### Success Response (200) - **orders** (array) - List of order objects. ``` -------------------------------- ### Decimal Scaling Example Source: https://docs.o2.app/o2-skills.md Explains the process of decimal scaling for prices and quantities, which are represented as u64 integers. Multiply by `10^decimals` and truncate to `max_precision` digits, obtaining these values from market info responses. ```pseudocode // Decimal scaling: // Prices and quantities are u64 integers. // Multiply by 10^decimals and truncate to max_precision digits. // Get decimals and max_precision from market info response. ``` -------------------------------- ### Import Rules via Markdown Reference Source: https://docs.o2.app/skills.html Syntax for importing the o2 integration rules into an existing CLAUDE.md file using the @ reference pattern. ```markdown @.claude/rules/o2-skills.md @.claude/rules/o2-reference.md ``` -------------------------------- ### Execute Order Placement Flow in TypeScript Source: https://docs.o2.app/trading-agent/o2-client.html This workflow demonstrates the end-to-end process of placing an order, including fetching market metadata, scaling price and quantity values using math utilities, and submitting the order via the o2Client. ```typescript // 1. Get market metadata const market = await o2Client.getMarket(config); // 2. Calculate scaled price (see Math Utilities section) const price = scaleUpAndTruncateToInt( new Decimal(2500.50), market.quote.decimals, // 9 market.quote.max_precision // 4 ); // 3. Calculate scaled quantity const quantity = calculateBaseQuantity( new Decimal(10), // $10 order size new Decimal(2500), // Current price market.base.decimals, // 9 market.base.max_precision // 5 ); // 4. Place order await o2Client.placeOrder(market, price, quantity, OrderSide.Buy); ``` -------------------------------- ### GET /v1/depth Source: https://docs.o2.app/o2-reference.md Retrieve the order book depth for a specific market. ```APIDOC ## GET /v1/depth ### Description Fetches order book depth updates keyed by market_id and precision. ### Method GET ### Endpoint /v1/depth ### Parameters #### Query Parameters - **market_id** (string) - Required - The unique identifier for the market. - **precision** (number) - Required - Powers of ten from 10 up to 1000000000. ### Response #### Success Response (200) - **data** (object) - Order book depth information. ``` -------------------------------- ### GET /v1/markets Source: https://docs.o2.app/o2-reference.md Retrieves metadata for all available markets on the O2 exchange. ```APIDOC ## GET /v1/markets ### Description Fetches market metadata including market IDs, contract addresses, asset details, and decimal precision. ### Method GET ### Endpoint /v1/markets ### Response #### Success Response (200) - **markets** (array) - List of available trading markets. #### Response Example { "markets": [ { "market_id": "0x...", "base_asset": "0x...", "decimals": 9 } ] } ``` -------------------------------- ### GET /trades Source: https://docs.o2.app/parameters-reference.html Retrieves trade data. Supports filtering by timestamp. ```APIDOC ## GET /trades ### Description Retrieves historical trade data. You can specify an end timestamp to filter the results. ### Method GET ### Endpoint /trades ### Parameters #### Query Parameters - **to** (number) - Optional - End timestamp in milliseconds (Unix epoch time) for historical data range. ### Response #### Success Response (200) - **response** (object) - Contains trade data. #### Response Example ```json { "trades": [ { "trade_id": "0x...", "timestamp": 1699200000000, "price": "1000000000", "quantity": "100000000" } ] } ``` ``` -------------------------------- ### Initialize Trading Agent and Clients Source: https://docs.o2.app/trading-agent/core-logic.html This TypeScript code initializes the main trading agent. It loads configuration, sets up logging, and initializes clients for Bitget (price fetching) and O2 (order execution). It uses top-level await for asynchronous operations. ```typescript import { loadConfig } from './config'; import { BitgetClient } from './bitget'; import { O2Client } from './o2'; import { createLogger } from './utils/logger'; import { BotConfig, MarketConfig } from './types/config'; import Decimal from 'decimal.js'; import { OrderSide } from '../lib/index'; import { scaleUpAndTruncateToInt, calculateBaseQuantity } from './utils/numbers'; import { shortenAxiosError } from '../lib/rest-api/utils/httpRequest'; // Constants // Symbol for USDC/USDT pair on Bitget - used when converting prices to USDC const USDC_USDT_SYMBOL = 'USDC/USDT'; // Load configuration from YAML file const configPath = process.env.CONFIG_PATH || 'config.yaml'; const config: BotConfig = loadConfig(configPath); // Main logic - wrapped in async IIFE for top-level await (async () => { // Create logger with configured log level (defaults to 'info') const logger = createLogger(config.general?.log_level?.toLowerCase() || 'info'); // Initialize Bitget client for fetching external price data const bitgetClient = new BitgetClient(); // Initialize O2 client for placing orders on the exchange const o2Client = new O2Client(config.o2.base_url, config.general.network_url, logger); // Initialize the O2 client with session key and market contract await o2Client.init(config.o2.account.private_key, config.o2.market.contract_id); // Worker function - executes a single trading cycle (buy + sell) async function marketWorker(marketConfig: MarketConfig, isRunningRef: { value: boolean }) { // Prevent overlapping cycles - skip if previous cycle still running if (isRunningRef.value) { logger.warn( `Previous job still running for market ${marketConfig.base_symbol}/${marketConfig.quote_symbol}, skipping this cycle.` ); return; } isRunningRef.value = true; logger.debug(`Starting worker for market ${marketConfig.base_symbol}/${marketConfig.quote_symbol}`); try { // Fetch market metadata from O2 (decimals, precision, etc.) const market = await o2Client.getMarket(marketConfig); if (!market) { logger.error(`Market not found on O2: ${marketConfig.base_symbol}/${marketConfig.quote_symbol}`); throw new Error('Market not found'); } // Fetch reference price from Bitget let price: Decimal; try { // Get base price from Bitget (e.g., ETH/USDC) price = new Decimal(await bitgetClient.fetchPrice(marketConfig.bitget_symbol)); // Convert to USDC if needed (e.g., FUEL/USDT -> FUEL/USDC) if (marketConfig.convert_to_usdc) { logger.debug('Converting price to USDC using USDC/USDT pair'); const usdc_usdt_price = await bitgetClient.fetchPrice(USDC_USDT_SYMBOL); // Convert: (FUEL/USDT) / (USDC/USDT) = FUEL/USDC price = price.div(usdc_usdt_price); } // Apply reciprocal rate if needed (e.g., USDC/USDT -> USDT/USDC) if (marketConfig.reciprocal_rate) { logger.debug(`Applying reciprocal rate: 1/${price} = ${new Decimal(1).div(price)}`); price = new Decimal(1).div(price); } logger.info(`Fetched Bitget price for ${marketConfig.base_symbol}/${marketConfig.quote_symbol}: ${price}`); } catch (err) { logger.error( { err }, `Failed to fetch Bitget price for ${marketConfig.base_symbol}/${marketConfig.quote_symbol}. Skipping this cycle.` ); return; } // Calculate adjusted buy price (increase by adjustment factor to ensure fill) const buyPrice = scaleUpAndTruncateToInt( price.mul(1 + marketConfig.price_adjustment_factor), market.quote.decimals, market.quote.max_precision ).toString(); // Calculate adjusted sell price (decrease by adjustment factor to ensure fill) const sellPrice = scaleUpAndTruncateToInt( price.mul(1 - marketConfig.price_adjustment_factor), market.quote.decimals, market.quote.max_precision ).toString(); logger.info( `Final buy/sell prices: ${new Decimal(buyPrice).toString()}/${new Decimal(sellPrice).toString()} with adjustment ${marketConfig.price_adjustment_factor}` ); // Calculate order quantity based on USDC value and current price const usdcValue = new Decimal(marketConfig.order_usdc_value); const quantityDecimal = calculateBaseQuantity(usdcValue, price, market.base.decimals, market.base.max_precision); const quantity = quantityDecimal.toString(); // Place buy order on O2 let buyOrderSuccess = false; try { const start = Date.now(); ``` -------------------------------- ### GET /bars Source: https://docs.o2.app/parameters-reference.html Retrieves historical OHLCV bar data for charting. ```APIDOC ## GET /bars ### Description Fetches historical candlestick data for a specific market. ### Method GET ### Endpoint /bars ### Parameters #### Query Parameters - **market_id** (string) - Required - Unique identifier for a trading market - **resolution** (string) - Required - Time resolution (e.g., 1m, 5m, 1h, 1d) - **from** (number) - Optional - Start timestamp in ms - **count_back** (number) - Optional - Number of historical bars to return (Max 5000) ### Request Example GET /bars?market_id=0xc0c5c48315d8cfff9f00777f81fdf04e9b4ef69e802a1a068549a8d6a06ee19f&resolution=5m&count_back=100 ### Response #### Success Response (200) - **bars** (array) - List of OHLCV data points #### Response Example { "bars": [ {"time": 1699100000000, "open": 100, "high": 105, "low": 99, "close": 102, "volume": 1000} ] } ``` -------------------------------- ### Place Buy and Sell Orders on O2 Source: https://docs.o2.app/trading-agent/core-logic.html This snippet demonstrates the process of placing buy and sell orders using the O2 client. It includes error handling for both buy and sell operations and logs the latency of each order. The sell order is attempted even if the buy order fails. Dependencies include an 'o2Client', 'marketConfig', 'OrderSide', 'logger', and a 'shortenAxiosError' function. ```typescript buyOrderSuccess = await o2Client.placeOrder(market, buyPrice, quantity, OrderSide.Buy, marketConfig.order_type); logger.info( `Buy order placed for ${marketConfig.base_symbol}/${marketConfig.quote_symbol}; price ${buyPrice}, quantity ${quantity} with latency ${Date.now() - start} ms` ); } catch (err) { logger.error( { err: shortenAxiosError(err) }, `Buy order failed for ${marketConfig.base_symbol}/${marketConfig.quote_symbol}. Trying the sell anyways.` ); } if (!buyOrderSuccess) { logger.error( `Buy order unsuccessful for ${marketConfig.base_symbol}/${marketConfig.quote_symbol}. Trying the sell anyways.` ); } // Wait between buy and sell orders (order_interval_seconds) await sleep(marketConfig.order_interval_seconds * 1000); // Place sell order on O2 (continues even if buy failed) let sellOrderSuccess = false; try { const start = Date.now(); sellOrderSuccess = await o2Client.placeOrder( market, sellPrice, quantity, OrderSide.Sell, marketConfig.order_type ); logger.info( `Sell order placed for ${marketConfig.base_symbol}/${marketConfig.quote_symbol}; price ${sellPrice}, quantity ${quantity} with latency ${Date.now() - start} ms` ); } catch (err) { logger.error( { err: shortenAxiosError(err) }, `Sell order failed for ${marketConfig.base_symbol}/${marketConfig.quote_symbol}` ); } if (!sellOrderSuccess) { logger.error(`Sell order unsuccessful for ${marketConfig.base_symbol}/${marketConfig.quote_symbol}`); } ``` -------------------------------- ### Example with Multiple Order Types Including BoundedMarket Source: https://docs.o2.app/api-endpoints/session-management.html Demonstrates an API request body that includes multiple order creations across different markets, specifically showcasing the BoundedMarket order type alongside FillOrKill. ```json { "actions": [ { "market_id": "0x1234567890abcdef...", "actions": [ { "CreateOrder": { "side": "Buy", "price": "1000000000", "quantity": "5000000000", "order_type": { "BoundedMarket": { "max_price": "1100000000", "min_price": "900000000" } } } } ] }, { "market_id": "0xfedcba9876543210...", "actions": [ { "CreateOrder": { "side": "Sell", "price": "2000000000", "quantity": "10000000000", "order_type": "FillOrKill" } } ] } ], "signature": { "Secp256k1": "0x789..." }, "nonce": "3", "trade_account_id": "0xdef456...", "session_id": { "Address": "0xabc123..." }, "collect_orders": true } ``` -------------------------------- ### GET /v1/aggregated/ticker Source: https://docs.o2.app/api-endpoints-reference.html Retrieves real-time ticker data for market pairs. ```APIDOC ## GET /v1/aggregated/ticker ### Description Fetches the latest market ticker data including price, volume, and change for trading pairs. ### Method GET ### Endpoint /v1/aggregated/ticker ### Parameters #### Query Parameters - **market_id** (string) - Optional - Filter by specific market. ### Request Example GET /v1/aggregated/ticker?market_id=ETH_USDC ### Response #### Success Response (200) - **price** (string) - Current market price. - **volume** (string) - 24h trading volume. #### Response Example { "price": "2500.50", "volume": "150.25" } ``` -------------------------------- ### GET /balance Source: https://docs.o2.app/parameters-reference.html Retrieves the balance for a specific user wallet address and asset. ```APIDOC ## GET /balance ### Description Fetches the balance of a specific asset for a given user wallet address. ### Method GET ### Endpoint /balance ### Parameters #### Query Parameters - **address** (string) - Required - User wallet address (B256 hex string) - **asset_id** (string) - Required - Asset contract identifier (B256 hex string) - **contract** (string) - Optional - Trading account contract ID ### Request Example GET /balance?address=0x91F0E90eff49ee08c0d42E617F5ec4e7A52F5b3A9D9E3Bbd0Aa995567fe98df5&asset_id=0x286c479da40dc953bddc3bb4c453b608bba2e0ac483b077bd475174115395e6b ### Response #### Success Response (200) - **balance** (number) - The current balance of the asset #### Response Example { "balance": 150.5 } ``` -------------------------------- ### GET /o2_markets_list Source: https://docs.o2.app/mcp-server.html Retrieves a comprehensive list of all trading markets available on the platform. ```APIDOC ## GET /o2_markets_list ### Description Returns a list of all available trading markets. ### Method GET ### Endpoint /o2_markets_list ### Response #### Success Response (200) - **markets** (array) - List of available market symbols and configurations. #### Response Example { "markets": ["BTC/USDC", "ETH/USDC"] } ``` -------------------------------- ### GET /bars Source: https://docs.o2.app/parameters-reference.html Retrieves historical bar data. Requires an end timestamp for filtering. ```APIDOC ## GET /bars ### Description Retrieves historical OHLC (Open, High, Low, Close) bar data. You can specify an end timestamp to filter the results. ### Method GET ### Endpoint /bars ### Parameters #### Query Parameters - **to** (number) - Optional - End timestamp in milliseconds (Unix epoch time) for historical data range. ### Response #### Success Response (200) - **response** (object) - Contains bar data. #### Response Example ```json { "bars": [ { "timestamp": 1699200000000, "open": "1000000000", "high": "1010000000", "low": "990000000", "close": "1005000000", "volume": "100000000" } ] } ``` ``` -------------------------------- ### Example Request Body with Multiple Actions Source: https://docs.o2.app/api-endpoints/session-management.html Illustrates a comprehensive API request body for session actions. It includes creating different types of orders (Spot, PostOnly) and canceling an order, demonstrating a typical workflow. ```json { "actions": [ { "market_id": "0x1234567890abcdef...", "actions": [ { "CreateOrder": { "side": "Buy", "price": "1000000000", "quantity": "100000000", "order_type": "Spot" } }, { "CreateOrder": { "side": "Sell", "price": "1050000000", "quantity": "50000000", "order_type": "PostOnly" } }, { "CancelOrder": { "order_id": "0xabcdef..." } } ] } ], "signature": { "Secp256k1": "0x789..." }, "nonce": "2", "trade_account_id": "0xdef456...", "session_id": { "Address": "0xabc123..." }, "collect_orders": true } ``` -------------------------------- ### GET /orders Source: https://docs.o2.app/parameters-reference.html Retrieves a list of orders based on account, market, and status filters. ```APIDOC ## GET /orders ### Description Retrieves order history or active orders for a specific account or market. ### Method GET ### Endpoint /orders ### Parameters #### Query Parameters - **account** (string) - Optional - User wallet address - **contract** (string) - Optional - Trading account contract ID - **market_id** (string) - Optional - Unique identifier for a trading market - **is_open** (boolean) - Optional - Filter to show only open/active orders - **count** (number) - Optional - Number of items to return (Max 50) - **direction** (string) - Optional - Sort order (asc/desc) ### Request Example GET /orders?market_id=0xc0c5c48315d8cfff9f00777f81fdf04e9b4ef69e802a1a068549a8d6a06ee19f&is_open=true ### Response #### Success Response (200) - **orders** (array) - List of order objects #### Response Example { "orders": [ { "order_id": "0x7f8e9d6c5b4a3f2e1d0c9b8a7f6e5d4c3b2a1f0e9d8c7b6a5f4e3d2c1b0a9f8e", "status": "open" } ] } ``` -------------------------------- ### Create o2 Client File (Bash) Source: https://docs.o2.app/trading-agent/o2-client.html Creates the TypeScript file for the o2 client. This is a foundational step before adding the client's implementation. ```bash touch src/o2.ts ``` -------------------------------- ### Get Trading Account Information API Request (Shell, Node.js, Rust) Source: https://docs.o2.app/api-endpoints/account-balance.html This snippet shows how to retrieve trading account information using the O2 App API. It requires a GET request to the /v1/accounts endpoint and necessitates providing exactly one of 'owner', 'owner_contract', or 'trade_account_id' as a query parameter. ```Shell curl -X GET \ "https://api.o2.app/v1/accounts?owner=some_owner_address" \ -H "Accept: application/json" ``` ```Node.js const fetch = require('node-fetch'); async function getAccountInfo(ownerAddress) { const response = await fetch(`https://api.o2.app/v1/accounts?owner=${ownerAddress}`, { method: 'GET', headers: { 'Accept': 'application/json' } }); return response.json(); } ``` ```Rust use reqwest::blocking::Client; fn get_account_info(owner_address: &str) { let client = Client::new(); let response = client.get(&format!("https://api.o2.app/v1/accounts?owner={}", owner_address)) .header("Accept", "application/json") .send(); match response { Ok(res) => println!("Response: {:?}", res.text().unwrap()), Err(err) => println!("Error: {}", err) } } ``` -------------------------------- ### Initialize Math Utilities File Source: https://docs.o2.app/trading-agent/math-utilities.html Creates the necessary TypeScript file for storing math utility functions using bash. ```bash touch src/utils/numbers.ts ``` -------------------------------- ### GET /v1/balance Source: https://docs.o2.app/network-identifiers.html Query the account balance for a specific asset, owner address, and owner trading account ID. ```APIDOC ## GET /v1/balance ### Description Queries the account balance for a specific asset, owner address, and owner trading account ID. This endpoint is useful for retrieving the balance of a particular asset held by an owner. ### Method GET ### Endpoint `/v1/balance` ### Parameters #### Query Parameters - **asset_id** (string) - Required - The unique identifier for the asset. - **address** (string) - Required - The owner's wallet address. - **contract** (string) - Required - The owner's trading account ID. ### Request Example ```javascript const USDC_ASSETID = '0x6c91bc65f585da1a238f8ec5e410e62616d2b2c8f2cb4701e225deb51240add6'; const OWNER_ADDRESS = '0x6c49291704aDc561074d887603c0C5E98B162b8662b746A1c945Bb1C71E40f79'; const OWNER_TRADING_ID = '0x5adea7826b1e4c39d2003a37f24453e4312cc97296408502c7f50b633704c67b'; const response = await fetch( `https://api.o2.app/v1/balance?asset_id=${USDC_ASSETID}&address=${OWNER_ADDRESS}&contract=${OWNER_TRADING_ID}`, { method: 'GET', headers: { 'Accept': 'application/json' } } ); const balance = await response.json(); console.log(balance); ``` ### Response #### Success Response (200) - **balance** (object) - An object containing the asset balance details. - **amount** (string) - The amount of the asset. - **asset_id** (string) - The asset identifier. - **decimals** (integer) - The number of decimal places for the asset. #### Response Example ```json { "balance": { "amount": "1000000000000000000", "asset_id": "0x6c91bc65f585da1a238f8ec5e410e62616d2b2c8f2cb4701e225deb51240add6", "decimals": 18 } } ``` ``` -------------------------------- ### Initialize Trade Account Manager (TypeScript) Source: https://docs.o2.app/trading-agent/o2-client.html Demonstrates the initialization of the trade account manager within the o2 client. This call establishes a trading session by providing the bot's wallet, a signer for transactions, and a list of whitelisted contract IDs. ```typescript await this.client.initTradeAccountManager({ account: sessionWallet, // Temporary bot wallet signer: this.signer, // Signs transactions contractIds: [contractId], // Whitelisted contracts }); ```