ƒxyzƒxyz Network
The NetworkTechnologyExchanges

Exchanges

ECN trading infrastructure - order books, matching engine, and market data on fXYZ Network

Exchange Infrastructure

fXYZ Network includes a complete Electronic Communication Network (ECN) for peer-to-peer trading, built with a professional-grade matching engine.

Package: @fxyz/trading

The ECN is implemented in the packages/trading module with TypeScript types, order book, and matching engine.


ECN Architecture

The Electronic Communication Network provides:

ComponentDescription
Order BookPrice-time priority bid/ask aggregation
Matching EngineReal-time order matching with partial fills
Market DataOHLCV candles, ticker data, trade history
SettlementIntegration with Solana for on-chain settlement

Design Principles

  • Price-Time Priority: Orders matched at best price, then by arrival time
  • Partial Fills: Large orders can fill across multiple price levels
  • Time-in-Force: GTC, IOC, FOK, GTD order types
  • Fee Structure: Maker/taker fee model

Trading Pairs

Trading pairs define the relationship between base and quote assets:

interface TradingPair {
  id: string;           // e.g., "FLORIN-USDC"
  baseAsset: string;    // e.g., "FLORIN"
  quoteAsset: string;   // e.g., "USDC"
  baseMint: string;     // Solana mint address
  quoteMint: string;    // Solana mint address
  minOrderSize: number;
  maxOrderSize: number;
  tickSize: number;     // Price precision
  lotSize: number;      // Quantity precision
  makerFee: number;     // e.g., 0.001 = 0.1%
  takerFee: number;
  isActive: boolean;
}

Active Pairs

PairBaseQuoteStatus
FLORIN-USDCFlorinUSDCActive
FLORIN-SOLFlorinSOLActive
SOL-USDCSOLUSDCActive

Order Types

Order Sides

SideDescription
BUYBuying base asset with quote asset
SELLSelling base asset for quote asset

Order Types

TypeDescription
LIMITExecute at specified price or better
MARKETExecute immediately at best available price
STOP_LIMITLimit order triggered at stop price

Time-in-Force

TIFNameBehavior
GTCGood Till CancelledRemains open until filled or cancelled
IOCImmediate Or CancelFill immediately, cancel remainder
FOKFill Or KillFill completely or cancel entirely
GTDGood Till DateExpires at specified time

Order Book

The order book aggregates orders at each price level:

interface OrderBookLevel {
  price: number;
  quantity: number;     // Total quantity at this price
  orderCount: number;   // Number of orders
}

interface OrderBook {
  pairId: string;
  bids: OrderBookLevel[];  // Sorted descending (best bid first)
  asks: OrderBookLevel[];  // Sorted ascending (best ask first)
  lastTradePrice?: number;
  lastTradeQuantity?: number;
  spread?: number;         // Best ask - best bid
  midPrice?: number;       // (Best ask + best bid) / 2
  timestamp: Date;
}

Order Book Operations

import { OrderBookEngine } from '@fxyz/trading';

const book = new OrderBookEngine('FLORIN-USDC');

// Get current state
const snapshot = book.getSnapshot(50); // Top 50 levels

// Market data
const bestBid = book.getBestBidLevel();
const bestAsk = book.getBestAskLevel();
const spread = book.getSpread();

Matching Engine

The matching engine processes orders with price-time priority:

import { MatchingEngine, OrderSide, OrderType, TimeInForce } from '@fxyz/trading';

const engine = new MatchingEngine();

// Register trading pair
engine.registerPair({
  id: 'FLORIN-USDC',
  baseAsset: 'FLORIN',
  quoteAsset: 'USDC',
  baseMint: '...',
  quoteMint: '...',
  minOrderSize: 1,
  maxOrderSize: 100000,
  tickSize: 0.0001,
  lotSize: 1,
  makerFee: 0.001,
  takerFee: 0.002,
  isActive: true,
  createdAt: new Date(),
});

// Submit order
const result = engine.submitOrder({
  pairId: 'FLORIN-USDC',
  userId: 'user-123',
  walletAddress: 'ABC...XYZ',
  side: OrderSide.BUY,
  type: OrderType.LIMIT,
  price: 1.05,
  quantity: 100,
  timeInForce: TimeInForce.GTC,
});

if (result.status === 'ACCEPTED') {
  console.log('Order ID:', result.order.id);
  console.log('Trades:', result.trades.length);
}

Event Callbacks

// Trade executed
engine.onTrade = (trade) => {
  console.log(`Trade: ${trade.quantity} @ ${trade.price}`);
  // Trigger settlement
};

// Order status changed
engine.onOrderUpdate = (order) => {
  console.log(`Order ${order.id}: ${order.status}`);
};

Trades

When orders match, trades are generated:

interface Trade {
  id: string;
  pairId: string;
  makerOrderId: string;
  takerOrderId: string;
  makerId: string;
  takerId: string;
  makerWallet: string;
  takerWallet: string;
  side: OrderSide;       // Taker's side
  price: number;
  quantity: number;
  makerFee: number;
  takerFee: number;
  settlementStatus: SettlementStatus;
  settlementTxId?: string;
  createdAt: Date;
  settledAt?: Date;
}

Settlement Status

StatusDescription
PENDINGAwaiting settlement
ESCROWFunds in escrow account
SETTLINGSettlement in progress
SETTLEDSuccessfully settled on-chain
FAILEDSettlement failed
REFUNDEDFunds returned to parties

Market Data

OHLCV Candles

interface OHLCV {
  pairId: string;
  interval: string;    // "1m", "5m", "1h", "1d"
  open: number;
  high: number;
  low: number;
  close: number;
  volume: number;
  quoteVolume: number;
  tradeCount: number;
  timestamp: Date;
}

Ticker

interface Ticker {
  pairId: string;
  lastPrice: number;
  bidPrice: number;
  askPrice: number;
  highPrice24h: number;
  lowPrice24h: number;
  volume24h: number;
  priceChange24h: number;
  priceChangePercent24h: number;
  tradeCount24h: number;
  timestamp: Date;
}

GraphQL API

Trading operations are exposed via GraphQL:

# Queries
query GetOrderBook($pairId: String!, $depth: Int) {
  orderBook(pairId: $pairId, depth: $depth) {
    bids { price quantity orderCount }
    asks { price quantity orderCount }
    spread
    midPrice
  }
}

query GetMyOrders($status: [OrderStatus]) {
  myOrders(status: $status) {
    id
    side
    type
    price
    quantity
    filledQuantity
    status
  }
}

# Mutations
mutation SubmitOrder($input: OrderInput!) {
  submitOrder(input: $input) {
    order { id status }
    trades { id price quantity }
    status
    message
  }
}

mutation CancelOrder($orderId: String!) {
  cancelOrder(orderId: $orderId) {
    id
    status
  }
}

WebSocket Events

Real-time market data via WebSocket:

type WSEventType =
  | 'ORDER_BOOK_SNAPSHOT'
  | 'ORDER_BOOK_UPDATE'
  | 'TRADE'
  | 'TICKER'
  | 'ORDER_UPDATE'
  | 'BALANCE_UPDATE';

interface WSMessage<T> {
  type: WSEventType;
  pairId?: string;
  data: T;
  timestamp: Date;
  sequence?: number;
}

Subscribing to Updates

// Connect to WebSocket
const ws = new WebSocket('wss://api.fxyz.network/ws');

// Subscribe to order book
ws.send(JSON.stringify({
  action: 'subscribe',
  channel: 'orderbook',
  pairId: 'FLORIN-USDC',
}));

// Handle updates
ws.onmessage = (event) => {
  const msg = JSON.parse(event.data);
  if (msg.type === 'ORDER_BOOK_UPDATE') {
    updateLocalOrderBook(msg.data);
  }
};

External Data Sources

The network integrates with external data providers:

Price Feeds

SourceDataEndpoint
CoinGeckoDigital asset prices/api/prices
BISFX rates, turnover/api/fx/bis
RWA.xyzTokenized assets/api/rwa/*

Data Cron Jobs

JobSchedulePurpose
asset-pricesEvery 5 minUpdate digital asset prices
fx-ratesHourlyUpdate FX rates
bis-dataDailyBIS market data
rwa-syncDailyRWA.xyz data

UI Components

The trading UI is available at app.fxyz.network/markets/trade:

Order Form

  • Buy/Sell tabs
  • Limit/Market order types
  • Price and quantity inputs
  • Order preview with fees

Order Book Display

  • Real-time bid/ask levels
  • Depth visualization
  • Spread indicator
  • Mid-price display

Trade History

  • Recent trades for pair
  • User's trade history
  • Settlement status tracking