# API Reference

This document provides a detailed reference for integrating with the FermiHybrid Sequencer API, which enables interaction with a decentralized order book for Solana token markets.

#### Base URL <a href="#base-url" id="base-url"></a>

You can ping the following URLs (at the `/health`endpoint), for figuring out which is your closest local sequencer for order placement/cancellation. Note that market related read ops can only be performed against the global sequencer.

#### Authentication <a href="#authentication" id="authentication"></a>

All endpoints that modify state (place/cancel orders) require cryptographic signatures to ensure the request originates from the owner of the key. See [Signing Requirements](https://github.com/Fermi-DEX/fermihybrid-sequencer/commits/exp_virtual/#signing-requirements) section for details.

#### Market Operations <a href="#market-operations" id="market-operations"></a>

**Create Market**

Creates a new trading market for a pair of tokens.

**Endpoint:** `POST /markets`

**Request Body:**

```
{
  "base_mint": "Base58EncodedPublicKey",
  "quote_mint": "Base58EncodedPublicKey",
  "name": "MARKET_NAME"
}
```

**Response:**

```
{
  "code": 201,
  "message": "Market created successfully",
  "data": {
    "uuid": "market-uuid",
    "base_mint": "Base58EncodedPublicKey",
    "quote_mint": "Base58EncodedPublicKey",
    "name": "MARKET_NAME",
    "created_at": 1679489282
  }
}
```

**List Markets**

Retrieves all available markets.

**Endpoint:** `GET /markets`

**Response:**

```
{
  "code": 200,
  "message": "Markets retrieved successfully",
  "data": [
    {
      "uuid": "market-uuid-1",
      "base_mint": "Base58EncodedPublicKey",
      "quote_mint": "Base58EncodedPublicKey",
      "name": "SOL/USDC",
      "created_at": 1679489282
    },
    {
      "uuid": "market-uuid-2",
      "base_mint": "Base58EncodedPublicKey",
      "quote_mint": "Base58EncodedPublicKey",
      "name": "BONK/USDC",
      "created_at": 1679489282
    }
  ]
}
```

**Get Orderbook**

Retrieves the current orderbook for a specific market.

**Endpoint:** `GET /markets/:market_id/orderbook`

**Parameters:**

* `market_id` (UUID) - The unique identifier of the market

**Response:**

```
{
  "code": 200,
  "message": "Orderbook retrieved successfully",
  "data": {
    "buys": [
      {
        "order_id": 123,
        "owner": "Base58EncodedPublicKey",
        "price": 50000000,
        "quantity": 2000000000,
        "side": "Buy",
        "expiry": 1679489282,
        "base_mint": "Base58EncodedPublicKey",
        "quote_mint": "Base58EncodedPublicKey",
        "market_id": "market-uuid"
      }
    ],
    "sells": [
      {
        "order_id": 124,
        "owner": "Base58EncodedPublicKey",
        "price": 51000000,
        "quantity": 1000000000,
        "side": "Sell",
        "expiry": 1679489282,
        "base_mint": "Base58EncodedPublicKey",
        "quote_mint": "Base58EncodedPublicKey",
        "market_id": "market-uuid"
      }
    ]
  }
}
```

**Get Trades**

Retrieves recent trade history for a specific market.

**Endpoint:** `GET /markets/:market_id/trades`

**Parameters:**

* `market_id` (UUID) - The unique identifier of the market

**Response:**

```
{
  "code": 200,
  "message": "Trade history retrieved successfully",
  "data": [
    {
      "buyer_order_id": 123,
      "seller_order_id": 456,
      "buyer": "Base58EncodedPublicKey",
      "seller": "Base58EncodedPublicKey",
      "price": 50500000,
      "quantity": 1000000000,
      "timestamp": 1679489282
    }
  ]
}
```

#### Order Operations <a href="#order-operations" id="order-operations"></a>

**Place Order**

Places a new order in a market.

**Endpoint:** `POST /orders`

**Request Body:**

```
{
  "intent": {
    "order_id": 123,
    "owner": "Base58EncodedPublicKey",
    "side": "Buy",
    "price": 50000000,
    "quantity": 1000000000,
    "expiry": 1679489282,
    "market_id": "market-uuid"
  },
  "signature": [signature_bytes]
}
```

The `signature` field must contain a valid ed25519 signature over the message derived from the order intent. See [Order Placement Signing](https://github.com/Fermi-DEX/fermihybrid-sequencer/commits/exp_virtual/#order-placement-signing)for details.

**Response:**

```
{
  "code": 200,
  "message": "Order placed successfully",
  "data": {
    "order_id": 123,
    "market_id": "market-uuid",
    "status": "placed"
  }
}
```

**Cancel Order**

Cancels an existing order.

**Endpoint:** `POST /orders/cancel`

**Request Body:**

```
{
  "order_id": 123,
  "owner": "Base58EncodedPublicKey",
  "market_id": "market-uuid",
  "signature": "HexEncodedSignature"
}
```

The `signature` field must contain a hex-encoded ed25519 signature over the message derived from the cancellation data. See [Order Cancellation Signing](https://github.com/Fermi-DEX/fermihybrid-sequencer/commits/exp_virtual/#order-cancellation-signing) for details.

**Response:**

```
{
  "code": 200,
  "message": "Order cancelled successfully",
  "data": {
    "order_id": 123,
    "market_id": "market-uuid",
    "status": "cancelled"
  }
}
```

#### Signing Requirements <a href="#signing-requirements" id="signing-requirements"></a>

**Order Placement Signing**

To place an order, you must create and sign a message using the following steps:

1. Create an `OrderIntent` with all order details
2. Serialize the `OrderIntent` using Borsh serialization (not JSON)
3. Create the signing message by:
   * Prepending the domain prefix `FRM_DEX_ORDER:`
   * Appending the Borsh-serialized order intent
   * Computing the SHA-256 hash of this combined data
   * Converting the hash to a hex string
   * Converting the hex string to UTF-8 bytes
4. Sign these UTF-8 bytes with an ed25519 private key
5. Include the signature in the request

**Order Cancellation Signing**

To cancel an order, you must create and sign a message using the following steps:

1. Create a `CancelOrderData` with order ID, owner public key, and market ID
2. Serialize using Borsh serialization
3. Create the signing message by:
   * Prepending the domain prefix `FRM_DEX_CANCEL:`
   * Appending the Borsh-serialized cancel data
   * Computing the SHA-256 hash of this combined data
   * Converting the hash to a hex string
   * Converting the hex string to UTF-8 bytes
4. Sign these UTF-8 bytes with an ed25519 private key
5. Convert the signature to a hex string
6. Include the hex-encoded signature in the request

#### Error Handling <a href="#error-handling" id="error-handling"></a>

All API responses follow a standard format:

```
{
  "code": 400,
  "message": "Error message",
  "error": "Detailed error description"
}
```

Common error codes:

* 400: Bad Request (invalid parameters, parsing errors)
* 401: Unauthorized (invalid signature)
* 404: Not Found (market or resource not found)
* 500: Internal Server Error

#### Receipt System <a href="#receipt-system" id="receipt-system"></a>

The sequencer provides cryptographic receipts for each processed order. These receipts can be used to verify that an order was received and processed by the sequencer.

**OrderReceipt Structure**

Copy

```
struct OrderReceipt {
    order_id: u64,
    owner: Pubkey,
    timestamp_ms: u128,
    sequencer_id: String,
    merkle_root: [u8; 32],
    sequencer_signature: [u8; 64],
}
```

The receipt contains:

* `order_id`: The unique identifier of the order
* `owner`: The public key of the order owner
* `timestamp_ms`: The precise millisecond timestamp when the order was processed
* `sequencer_id`: The identifier of the processing sequencer
* `merkle_root`: A cryptographic commitment to the state of the orderbook at the time of processing
* `sequencer_signature`: The sequencer's signature over the receipt data

**Receipt Signing Format**

The sequencer signs the receipt with the following message format:

Copy

```
ORDER_RECEIPT:{order_id}:{owner}:{timestamp_ms}:{sequencer_id}:{merkle_root_hex}
```

**Verifying a Receipt**

To verify a receipt, reconstruct the signing message and verify the signature against the sequencer's public key:

Copy

```
use ed25519_dalek::{PublicKey, Signature, Verifier};
use hex;

// Reconstruct the message that was signed
let message = format!(
    "ORDER_RECEIPT:{}:{}:{}:{}:{}",
    receipt.order_id,
    receipt.owner,
    receipt.timestamp_ms,
    receipt.sequencer_id,
    hex::encode(receipt.merkle_root)
);

// Convert to bytes
let message_bytes = message.as_bytes();

// Parse the signature and sequencer's public key
let signature = Signature::from_bytes(&receipt.sequencer_signature).unwrap();
let sequencer_pubkey = PublicKey::from_bytes(&sequencer_public_bytes).unwrap();

// Verify the signature
let is_valid = sequencer_pubkey.verify(message_bytes, &signature).is_ok();
```
