Filament Docs
  • About Filament Pro
  • Fundamentals
    • 📘Orderbook
    • 🌊COMB (Compartment-Based) Liquidity Pool
  • Guides
    • 🌉Bridging
    • 🤝Connecting to Sei
    • 🚰Depositing Funds
    • 📈Trading
    • 💧Providing Liquidity
  • Community
    • 💳Filament Credit System
  • Resources
    • ✏️Brand Kit
    • 📜Litepaper
    • 🔓Security Audits
  • Market Makers
    • Filament API
Powered by GitBook
On this page
  • Dependencies
  • Key Concepts and Workflow
  • 1. Price Change Orders
  • 2. Signature Generation: handleOrderSignature
  • Explanation:
  • Purpose of Signature:
  • 3. Function: processOrders
  • Explanation of Parameters:
  • Workflow:
  • 4. Sending the Order
  • Exchange URL
  • Limit Order Payload:
  • Market Order Payload
  • Cancel Order
  • Add Collateral
  • Remove Collateral
  • Update Take Profit On Position
  • Update Stop Loss on Position
  • Update Take Profit And Stop Loss on Position
  • GET Endpoints
  • Get All Traded Assets:
  • GET Calls for Orders, Positions And Market Stats
  • Web Socket Connections
  • Order Book State:
  • Live Feed On Assets:
  • Native WebSocket Connections
  • WebSocket Connection Workflow
  • OrderBook State:
  • Order Updates:
  • How to Place Close Orders for Open Positions
  • Step 1: Fetch Open Positions
  • Step 2: Place Close Order
  • Step 3: Confirmation
  • Summary
  1. Market Makers

Filament API

This is an in-depth guide to onboarding market makers, focusing on how orders are processed and signed.

We will explain how to use the provided code, break down key concepts such as signature generation, and guide you through the modules used (e.g., nanoid, ethers).

Our platform interacts with the order book API to facilitate trading using buy and sell orders based on price changes.

Dependencies

  • nanoid: Generates unique, secure IDs used for each order.

  • ethers.js (version 5.7.2): A library that provides utilities for interacting with Ethereum, particularly useful for signing messages (orders in our case).

Key Concepts and Workflow

1. Price Change Orders

Market makers often need to update their orders based on price changes. The processOrders function automates this by creating and sending orders to the platform with unique identifiers and signatures.

import { nanoid } from "nanoid";
import { handleOrderSignature } from "./utils";
export NEXT_API_URL=https://orderbook.filament.finance/sei;
  • nanoid: This package is used to create a unique identifier for each order. Each generated ID is lowercase to maintain consistency.

  • handleOrderSignature: This utility function is used to sign the order ID using the provided private key.

2. Signature Generation: handleOrderSignature

The function handleOrderSignature is critical for ensuring the authenticity of each order by creating a cryptographic signature.

export const handleOrderSignature = async (orderId: string, signature: string) => {
  const signer = new ethers.Wallet(signature); // Initialize a new ethers.js Wallet with the private key.
  const orderSignature = await signer.signMessage(orderId); // Sign the order ID to generate a signature.
  return orderSignature; // Return the signature for order validation.
};

Explanation:

  • orderId: The unique order ID generated by nanoid.

  • signature: The private key used to sign the order (passed as signingKey in processOrders).

  • The function uses ethers.js to sign the message, ensuring that only the owner of the private key can create valid orders.

Purpose of Signature:

  • Signatures verify the identity of the market maker submitting the order. When an order is signed with the private key, the platform can trust the authenticity of the request, making it difficult for malicious actors to forge orders.

3. Function: processOrders

The processOrders function handles the creation of orders and prepares them to be sent to the API.

export async function processOrders(
  price: any,
  isBuy: boolean,
  asset: string,
  account: string,
  signingKey: string
) {
    const id = nanoid().toLowerCase(); // Generating a unique order ID.
    const signature = await handleOrderSignature(id, signingKey); 
    const payload = {
      type: 'order',
      referralCode: null,
      orders: [
        {
          account: account.toLowerCase(), // Market maker's account address.
          indexToken: asset, // The asset to be traded.
          orderId: id, // The unique order ID.
          signature: signature, // Signature of the order for verification.
          isBuy, // Boolean indicating buy or sell.
          size: 15000, // Order size (e.g., 15,000 units).
          leverage: 30, // Leverage applied (e.g., 30x).
          reduceOnly: false, // Reduce-only flag (false in this example).
          orderType: {
            type: 'limit',
            limit: {
              tif: 'Gtc', // Time-in-force for the order ("Good 'til canceled").
              limitPrice: price, // The price associated with the order.
            },
          },
        },
      ],
    };
}

Explanation of Parameters:

  • price: Price to place orders

  • isBuy: A boolean value indicating whether the order is a buy (true) or a sell (false).

  • asset: The asset or token being traded (e.g., SOL, BTC).

  • account: The wallet address of the market maker, which will be used for the order.

  • signingKey: The private key used to sign the order for verification purposes.

Workflow:

  1. For each price change, it generates a unique order ID using nanoid().

  2. The order ID is signed using the handleOrderSignature function.

  3. An order payload is created with information like the asset being traded, order size, leverage, and limit price.

  4. The payload can be sent to the API for order execution.

4. Sending the Order

Once the payload is created, it can be sent to the platform’s API at the endpoint provided in the configuration. The API will process the order and execute it according to the details provided (e.g., size, limit price, etc.).

const response = await fetch(`${NEXT_API_URL}/filament/api/v1/exchange`, {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json',
        },
        body: JSON.stringify(payload),
      });
  • NEXT_API_URL: This is the base URL for the order book API, which will receive the payload containing the order details.

Exchange URL

URL: {{**NEXT_API_URL**}}/filament/api/v1/exchange

Limit Order Payload:

{
    "type": "order",
    "referralCode": null,
    "orders": [
        {
            "account": "<account>",
            "indexToken": "BTC",
            "isBuy": true,
            "size": 22,
            "leverage": 1.1,
            "reduceOnly": false,
            "orderId": "<orderId>",
            "signature": "<Signature>",
            "orderType": {
                "type": "limit",
                "limit": {
                    "tif": "Gtc",
                    "limitPrice": "57985"
                }
            }
        }
    ]
}

Market Order Payload

{
    "type": "order",
    "referralCode": null,
    "orders": [
        {
            "account": "<account>",
            "indexToken": "BTC",
            "isBuy": true,
            "size": 22,
            "leverage": 1.1,
            "reduceOnly": false,
            "orderId": "<orderId>",
            "signature": "<Signature>",
            "orderType": {
                "type": "trigger",
                "trigger": {
                    "isMarket": true,
                    "slippage": 5
                }
            }
        }
    ]
}

Cancel Order

{
    "type": "cancel",
    "cancels": [
        {
            "account": "<account>",
            "orderId": "<orderId>",
            "signature": "<Signature>"
        }
    ]
}

Add Collateral

{
    "type": "updateIsolatedMargin",
    "account": "<account>",
    "referralCode": null,
    "asset": "BTC",
    "collateral": 1,
    "isBuy": false,
    "isIncrement": true,
    "orderId": "<orderId>",
    "signature": "<Signature>",
    "tpsl": "na",
    "size": ""
}

Remove Collateral

{
    "type": "updateIsolatedMargin",
    "account": "<account>",
    "referralCode": null,
    "asset": "BTC",
    "collateral": 1,
    "isBuy": false,
    "isIncrement": false,
    "orderId": "<orderId>",
    "signature": "<Signature>",
    "tpsl": "na",
    "size": ""
}

Update Take Profit On Position

{
    "type": "updateIsolatedMargin",
    "account": "<account>",
    "referralCode": null,
    "asset": "BTC",
    "collateral": "",
    "isBuy": false,
    "isIncrement": true,
    "orderId": "<orderId>",
    "signature": "<Signature>",
    "takeProfit": "57990",
    "takeProfitOrderId": "<takeProfitOrderId>",
    "takeProfitSignature": "<takeProfitSignature>",
    "tpsl": "tp",
    "size": "0.000061"
}

Update Stop Loss on Position

{
    "type": "updateIsolatedMargin",
    "account": "<account>",
    "referralCode": null,
    "asset": "BTC",
    "collateral": "",
    "isBuy": false,
    "isIncrement": true,
    "orderId": "<orderId>",
    "signature": "<Signature>",
    "stopLoss": "58015",
    "stopLossOrderId": "<stopLossOrderId>",
    "stopLossSignature": "<stopLossSignature>",
    "tpsl": "sl",
    "size": "0.000061"
}

Update Take Profit And Stop Loss on Position

{
    "type": "updateIsolatedMargin",
    "account": "<account>",
    "referralCode": null,
    "asset": "BTC",
    "collateral": "",
    "isBuy": false,
    "isIncrement": true,
    "orderId": "<orderId>",
    "signature": "<Signature>",
    "takeProfit": "57990",
    "takeProfitOrderId": "<takeProfitOrderId>",
    "takeProfitSignature": "<takeProfitSignature>",
    "stopLoss": "58010",
    "stopLossOrderId": "<stopLossOrderId>",
    "stopLossSignature": "<stopLossSignature>",
    "tpsl": "both",
    "size": "0.000061"
}

GET Endpoints

Get All Traded Assets:

URL: https://orderbook.filament.finance/sei/filament/api/v1/assets

Relevant Info:

  1. Current mark Price

  2. Current Spot Price

  3. Index Token Address for Asset

Response:

[
  {
    "id": "667ee4b52c7c6773565ada80",
    "indexToken": "0x7dff46370e9ea5f0bad3c4e29711ad50062ea7a4",
    "assetName": "SOL",
    "indexPriceFetchAddress": "0xC663315f7aF904fbbB0F785c32046dFA03e85270",
    "interestRate": 0.00125,
    "markPrice": 138.1,
    "spotPrice": 138.1,
    "spotUpdateTime": "2024-10-03T11:02:18.696Z",
    "allowedDeviation": 0.05,
    "tradingEnabled": false,
    "assetImageUrl": "https://filamentimages.s3.ap-southeast-1.amazonaws.com/tokens/SOL.svg",
    "marginValue": 1000,
    "initialMarginRate": 0.033,
    "allowedPoolMatchRatio": 0.65,
    "fundingRate": -0.0421,
    "fundingRateDirection": "SHORT_TO_LONG",
    "nextFundingTimeStamp": "2024-10-03T12:00:00.138Z",
    "minimumCollateralRequirement": 20,
    "lastTradedPrice": 138.1,
    "tickSize": 0.01,
    "stepSize": 0.01,
    "minLeverage": 1.1,
    "maxLeverage": 3
  },
  {
    "id": "667ee4b52c7c6773565ad9f0",
    "indexToken": "0x152b9d0fdc40c096757f570a51e494bd4b943e50",
    "assetName": "BTC",
    "indexPriceFetchAddress": "0xD702DD976Fb76Fffc2D3963D037dfDae5b04E593",
    "interestRate": 0.00125,
    "markPrice": 60974,
    "spotPrice": 60992.7233333333,
    "spotUpdateTime": "2024-10-03T11:02:19.102Z",
    "allowedDeviation": 0.05,
    "tradingEnabled": true,
    "assetImageUrl": "https://filamentimages.s3.ap-southeast-1.amazonaws.com/tokens/BTC.svg",
    "marginValue": 1000,
    "initialMarginRate": 0.033,
    "allowedPoolMatchRatio": 0.65,
    "fundingRate": 0.00125,
    "fundingRateDirection": "LONG_TO_SHORT",
    "nextFundingTimeStamp": "2024-10-03T12:00:00.141Z",
    "minimumCollateralRequirement": 20,
    "lastTradedPrice": 60872,
    "tickSize": 1,
    "stepSize": 1,
    "minLeverage": 1.1,
    "maxLeverage": 3
  }
]

GET Calls for Orders, Positions And Market Stats

Please find the below Postman Documentation of GET endpoints, to get following info:

  1. Open Orders

    1. {{baseUrl}}/v1/orders/open-orders/paginated/account/:account?token=&side=&page=0&size=10

      This end-point provides details on all open orders placed by the user.

      It is paginated endpoint.

      Inputs:

      account: Account address need to be passed in lower case (Mandatory)

      Optional arguments to filter out futher:

      1. token: Asset Eg: BTC

      2. side: BUY/SELL

      Output:

      Paginated response of user open orders:

      Datapoints include:

      1. orderId: Unique Order id of the order.

      2. openTime: order open time

      3. account: user account

      4. side: BUY/SELL

      5. token: asset on which position is created

      6. triggerPrice: price at which order will be triggered.

      7. typeOfOrder:

        1. Limit

        2. Market

        3. TakeProfit

        4. StopLoss

      8. size: Size of order in USDC.

      9. orderValue: Number of tokens.

      10. collateral: Used collateral for this open order.

      11. decreaseOrder: true if order a decrease order

        1. Note: Order can be of two types,

          1. Normal orders to increase or create positon.

          2. Orders to reduce position are categorized as decrease orders.

      12. isTakeProfit -> true is order is a Take Profit order, otherwise false

      13. isStopLoss -> true is order is a Stop Loss order, otherwise false

      14. decreaseOrder -> Provides current liquidation price of user position, it keep on updating with moving market price.

      Eg:

      {
          "content": [
              {
                  "orderId": "65ng1numbemfertp3tn8m",
                  "account": "0xa4abeaf78144a834e22b49ee4310f23d3ebf4d10",
                  "token": "BTC",
                  "size": 343.917502,
                  "collateral": 34.391750,
                  "side": "BUY",
                  "typeOfOrder": "Limit",
                  "triggerPrice": 63782.000000,
                  "orderStatus": "OPEN",
                  "orderValue": 0.005392,
                  "openTime": "30/09/2024 - 11:56:48",
                  "decreaseOrder": false,
                  "isStopLoss": false,
                  "isTakeProfit": false
              },
              {
                  "orderId": "pgr3tfmto7z8i8avhrovl",
                  "account": "0xa4abeaf78144a834e22b49ee4310f23d3ebf4d10",
                  "token": "BTC",
                  "size": 343.917502,
                  "collateral": 34.391750,
                  "side": "BUY",
                  "typeOfOrder": "Limit",
                  "triggerPrice": 63781.000000,
                  "orderStatus": "OPEN",
                  "orderValue": 0.005392,
                  "openTime": "30/09/2024 - 11:56:48",
                  "decreaseOrder": false,
                  "isStopLoss": false,
                  "isTakeProfit": false
              },
              {
                  "orderId": "k81bwvngqeccrqbjjgf86",
                  "account": "0xa4abeaf78144a834e22b49ee4310f23d3ebf4d10",
                  "token": "BTC",
                  "size": 343.917502,
                  "collateral": 34.391750,
                  "side": "BUY",
                  "typeOfOrder": "Limit",
                  "triggerPrice": 63780.000000,
                  "orderStatus": "OPEN",
                  "orderValue": 0.005392,
                  "openTime": "30/09/2024 - 11:56:48",
                  "decreaseOrder": false,
                  "isStopLoss": false,
                  "isTakeProfit": false
              },
              {
                  "orderId": "edfd8saq8b8ajwzlakdza",
                  "account": "0xa4abeaf78144a834e22b49ee4310f23d3ebf4d10",
                  "token": "BTC",
                  "size": 343.917502,
                  "collateral": 34.391750,
                  "side": "BUY",
                  "typeOfOrder": "Limit",
                  "triggerPrice": 63779.000000,
                  "orderStatus": "OPEN",
                  "orderValue": 0.005392,
                  "openTime": "30/09/2024 - 11:56:47",
                  "decreaseOrder": false,
                  "isStopLoss": false,
                  "isTakeProfit": false
              }
          ],
          "pageable": {
              "pageNumber": 0,
              "pageSize": 4,
              "sort": {
                  "empty": false,
                  "sorted": true,
                  "unsorted": false
              },
              "offset": 0,
              "paged": true,
              "unpaged": false
          },
          "last": false,
          "totalElements": 199,
          "totalPages": 50,
          "first": true,
          "size": 4,
          "number": 0,
          "sort": {
              "empty": false,
              "sorted": true,
              "unsorted": false
          },
          "numberOfElements": 4,
          "empty": false
      }
      
  2. Closed Orders

    1. {{baseUrl}}/v1/orders/closed-orders/paginated/account/:account?token=&side=&page=0&size=10

      This end-point provides details on all closed orders by the user.

      It is paginated endpoint.

      Inputs:

      account: Account address need to be passed in lower case (Mandatory)

      Optional arguments to filter out futher:

      1. token: Asset Eg: BTC

      2. side: BUY/SELL

      Output:

      Paginated response of user open orders:

      Datapoints include:

      1. orderId: Unique Order id of the order.

      2. openTime: order open time

      3. closedTime: Give last update on this order

      4. account: user account

      5. side: BUY/SELL

      6. token: asset on which position is created

      7. triggerPrice: price at which order will be triggered.

      8. typeOfOrder:

        1. Limit

        2. Market

        3. TakeProfit

        4. StopLoss

      9. size: Size of order in USDC.

      10. orderValue: Number of tokens.

      11. orderStatus:

        1. OPEN

        2. MATCHED

        3. CANCELLED

        4. FAILED

      12. collateral: Used collateral for this order.

      13. decreaseOrder: true if order a decrease order

        1. Note: Order can be of two types,

          1. Normal orders to increase or create positon.

          2. Orders to reduce position are categorized as decrease orders.

      14. isTakeProfit -> true is order is a Take Profit order, otherwise false

      15. isStopLoss -> true is order is a Stop Loss order, otherwise false

      16. decreaseOrder -> Provides current liquidation price of user position, it keep on updating with moving market price.

      Eg:

      JSON

      {
          "content": [
              {
                  "orderId": "65ng1numbemfertp3tn8m",
                  "account": "0xa4abeaf78144a834e22b49ee4310f23d3ebf4d10",
                  "token": "BTC",
                  "size": 343.917502,
                  "collateral": 34.391750,
                  "side": "BUY",
                  "typeOfOrder": "Limit",
                  "triggerPrice": 63782.000000,
                  "orderStatus": "OPEN",
                  "orderValue": 0.005392,
                  "openTime": "30/09/2024 - 11:56:48",
                  "closedTime": "30/09/2024 - 11:56:49",
                  "decreaseOrder": false,
                  "isStopLoss": false,
                  "isTakeProfit": false
              },
              {
                  "orderId": "pgr3tfmto7z8i8avhrovl",
                  "account": "0xa4abeaf78144a834e22b49ee4310f23d3ebf4d10",
                  "token": "BTC",
                  "size": 343.917502,
                  "collateral": 34.391750,
                  "side": "BUY",
                  "typeOfOrder": "Limit",
                  "triggerPrice": 63781.000000,
                  "orderStatus": "OPEN",
                  "orderValue": 0.005392,
                  "openTime": "30/09/2024 - 11:56:48",
                  "closedTime": "30/09/2024 - 11:56:49",
                  "decreaseOrder": false,
                  "isStopLoss": false,
                  "isTakeProfit": false
              },
              {
                  "orderId": "marjfhzh6a7rbffqogwrv",
                  "account": "0xa4abeaf78144a834e22b49ee4310f23d3ebf4d10",
                  "token": "BTC",
                  "size": 343.917502,
                  "collateral": 34.391750,
                  "side": "BUY",
                  "typeOfOrder": "Limit",
                  "triggerPrice": 63778.000000,
                  "orderStatus": "OPEN",
                  "orderValue": 0.005392,
                  "openTime": "30/09/2024 - 11:56:47",
                  "closedTime": "30/09/2024 - 11:56:48",
                  "decreaseOrder": false,
                  "isStopLoss": false,
                  "isTakeProfit": false
              },
              {
                  "orderId": "edfd8saq8b8ajwzlakdza",
                  "account": "0xa4abeaf78144a834e22b49ee4310f23d3ebf4d10",
                  "token": "BTC",
                  "size": 343.917502,
                  "collateral": 34.391750,
                  "side": "BUY",
                  "typeOfOrder": "Limit",
                  "triggerPrice": 63779.000000,
                  "orderStatus": "OPEN",
                  "orderValue": 0.005392,
                  "openTime": "30/09/2024 - 11:56:47",
                  "closedTime": "30/09/2024 - 11:56:48",
                  "decreaseOrder": false,
                  "isStopLoss": false,
                  "isTakeProfit": false
              }
          ],
          "pageable": {
              "pageNumber": 0,
              "pageSize": 4,
              "sort": {
                  "empty": false,
                  "sorted": true,
                  "unsorted": false
              },
              "offset": 0,
              "paged": true,
              "unpaged": false
          },
          "last": false,
          "totalElements": 8127,
          "totalPages": 2032,
          "first": true,
          "size": 4,
          "number": 0,
          "sort": {
              "empty": false,
              "sorted": true,
              "unsorted": false
          },
          "numberOfElements": 4,
          "empty": false
      }
      

      Note: There can be multiple enteries for an orderId.

      Eg: Lets say for orderId: "edfd8saq8b8ajwzlakdza"

      1. Order opened at time: 30/09/2024 - 11:56:47, for size: 400 USDC

      2. It Matched for size $200, then an entry will be present with status matched and size $200.

      3. Then if this order is cancelled, then another entry will be present of size $200 with status CANCELLED

  3. Positons (Open Positions - Trades)

    1. URL: {{baseUrl}}/v1/positions/trades/paginated/:account?page=0&size=10

      This end-point provides details on all open positions of the user.

      Inputs:

      account: Account address need to be passed in lower case.

      Output:

      Paginated response of user positions:

      Datapoints include:

      1. openTime: Position open time

      2. account: user account

      3. side: BUY/SELL

      4. token: asset on which position is created

      5. entryPrice: average price of your position.

      6. markPrice: current mark price, which is basically the best Ask.

      7. size: Size of position in USDC, it keep on updating with market price movement.

      8. quantity: Number of tokens (remains constant unless position is increased or decreased)

      9. Collateral: Amount locked in USDC

      10. Fees: Borrowing fees + Trading fees + Funding fees

      11. realizedPnL: This is actually unrealized PnL value. which is calculated basd on formula.

        1. BUY -> (markPrice - averagePrice) x quantity

        2. SELL -> (averagePrice - markPrice) x quantity

      12. takeProfit -> Return take profit price if set for position, otherwise null.

      13. stopLoss -> Return stop loss price if set for position, otherwise null.

      14. Liquidation Price -> Provides current liquidation price of user position, it keep on updating with moving market price.

      15. leverage → size / collateral

      Eg:

      {
      "content": [
      {
      "openTime": "20/09/2024 - 13:44:29",
      "account": "0xa4abeaf78144a834e22b49ee4310f23d3ebf4d10",
      "token": "BTC",
      "side": "SELL",
      "entryPrice": 64360.982200,
      "markPrice": 63594.000000,
      "size": 8506.689213,
      "quantity": 0.130615,
      "collateral": 1464.555463,
      "fees": 0.483904,
      "realizedPnL": 100.179380,
      "takeProfit": null,
      "stopLoss": null,
      "liquidationPrice": 73964.723700,
      "leverage": 5.808376
      },
      {
      "openTime": "20/09/2024 - 13:28:27",
      "account": "0xa4abeaf78144a834e22b49ee4310f23d3ebf4d10",
      "token": "BTC",
      "side": "BUY",
      "entryPrice": 64588.422113,
      "markPrice": 63594.000000,
      "size": 11479.070974,
      "quantity": 0.180506,
      "collateral": 1881.701965,
      "fees": 21.725320,
      "realizedPnL": -179.499158,
      "takeProfit": null,
      "stopLoss": null,
      "liquidationPrice": 55778.512885,
      "leverage": 6.100366
      }
      ],
      "pageable": {
      "pageNumber": 0,
      "pageSize": 4,
      "sort": {
      "empty": false,
      "sorted": true,
      "unsorted": false
      },
      "offset": 0,
      "paged": true,
      "unpaged": false
      },
      "last": true,
      "totalElements": 2,
      "totalPages": 1,
      "first": true,
      "size": 4,
      "number": 0,
      "sort": {
      "empty": false,
      "sorted": true,
      "unsorted": false
      },
      "numberOfElements": 2,
      "empty": false
      }
      
  4. Trade History

    1. URL: {{baseUrl}}/v1/positions/tradeHistory/paginated/:account?page=0&size=10

      This end-point provides all matched trades, it gives insight on every order match.

      Inputs:

      account: Account address need to be passed in lower case.

      Output:

      Paginated response of user positions:

      Datapoints include:

      1. tradeTime: Time when trade occurrred.

      2. account: user account

      3. side: BUY/SELL

      4. token: asset on which position is created

      5. price: price at which order was matched and trade was executed.

      6. size: Size of position in USDC.

      7. tradeValue: Number of tokens

      8. Collateral: Amount locked in USDC

      9. Fees: Borrowing fees + Trading fees + Funding fees charged

      10. closedPnL: Realized PnL

      11. orderType ->

        1. OpenLong

        2. OpenShort

        3. CloseLong

        4. CloseShort

        5. LiquidationCloseLong

        6. LiquidationCloseShort

      12. associatedOrderId: Order Id associated with this trade.

      Eg:

      {
          "content": [
              {
                  "id": "6703c621fcabec1ae0daafc7",
                  "tradeTime": "07/10/2024 - 11:29:37",
                  "tradeTimeForSorting": "2024-10-07T11:29:37.621Z",
                  "account": "0xa4abeaf78144a834e22b49ee4310f23d3ebf4d10",
                  "token": "BTC",
                  "side": "BUY",
                  "price": 62910.000000,
                  "size": 59.99999999999998239,
                  "tradeValue": 0.000953,
                  "fee": 0.000008,
                  "closedPnL": 0.000000,
                  "orderType": "OpenLong",
                  "associatedOrderId": "n8thz2qvffol-kfwrorj0"
              },
              {
                  "id": "6703c262fcabec1ae0daaf9d",
                  "tradeTime": "07/10/2024 - 11:13:38",
                  "tradeTimeForSorting": "2024-10-07T11:13:38.857Z",
                  "account": "0xa4abeaf78144a834e22b49ee4310f23d3ebf4d10",
                  "token": "BTC",
                  "side": "BUY",
                  "price": 62825.000000,
                  "size": 27.724234454589275575,
                  "tradeValue": 0.000441,
                  "fee": 0.000000,
                  "closedPnL": 0.000000,
                  "orderType": "OpenLong",
                  "associatedOrderId": "qcn0a1hcwhlm8flt-z42i"
              },
              {
                  "id": "6703c25cfcabec1ae0daaf92",
                  "tradeTime": "07/10/2024 - 11:13:32",
                  "tradeTimeForSorting": "2024-10-07T11:13:32.321Z",
                  "account": "0xa4abeaf78144a834e22b49ee4310f23d3ebf4d10",
                  "token": "BTC",
                  "side": "BUY",
                  "price": 62900.000000,
                  "size": 99.9999999999999407,
                  "tradeValue": 0.001589,
                  "fee": 0.000000,
                  "closedPnL": 0.000000,
                  "orderType": "OpenLong",
                  "associatedOrderId": "qcn0a1hcwhlm8flt-z42i"
              },
              {
                  "id": "6703c25bfcabec1ae0daaf8a",
                  "tradeTime": "07/10/2024 - 11:13:31",
                  "tradeTimeForSorting": "2024-10-07T11:13:31.529Z",
                  "account": "0xa4abeaf78144a834e22b49ee4310f23d3ebf4d10",
                  "token": "BTC",
                  "side": "BUY",
                  "price": 62750.000000,
                  "size": 99.999999999999992,
                  "tradeValue": 0.001593,
                  "fee": 0.000000,
                  "closedPnL": 0.000000,
                  "orderType": "OpenLong",
                  "associatedOrderId": "qcn0a1hcwhlm8flt-z42i"
              }
          ],
          "pageable": {
              "pageNumber": 0,
              "pageSize": 4,
              "sort": {
                  "empty": false,
                  "sorted": true,
                  "unsorted": false
              },
              "offset": 0,
              "paged": true,
              "unpaged": false
          },
          "last": false,
          "totalElements": 1148,
          "totalPages": 287,
          "first": true,
          "size": 4,
          "number": 0,
          "sort": {
              "empty": false,
              "sorted": true,
              "unsorted": false
          },
          "numberOfElements": 4,
          "empty": false
      }
    2. Get trade history with associated Order Id.

      1. URL: {{baseUrl}}/v1/positions/tradeHistory/paginated/:account?page=0&size=10&associatedOrderId=

      2. Inputs:

        1. account: Account address need to be passed in lower case.

        2. associatedOrderId (Optional parameter): Order Id, for which necessary trades are required to be found.

      3. Output:

        1. Example

        {
            "content": [
                {
                    "id": "67064206fcabec1ae0dac8a4",
                    "tradeTime": "09/10/2024 - 08:42:46",
                    "tradeTimeForSorting": "2024-10-09T08:42:46.441Z",
                    "account": "0xa4abeaf78144a834e22b49ee4310f23d3ebf4d10",
                    "token": "BTC",
                    "side": "SELL",
                    "price": 62154.000000,
                    "size": 49.999999999999946328,
                    "tradeValue": 0.000804,
                    "fee": 0.000002,
                    "closedPnL": 0.000000,
                    "orderType": "OpenShort",
                    "associatedOrderId": "s5yj8etnxmvo2sxjyczyf"
                },
                {
                    "id": "670641ebfcabec1ae0dac883",
                    "tradeTime": "09/10/2024 - 08:42:19",
                    "tradeTimeForSorting": "2024-10-09T08:42:19.051Z",
                    "account": "0xa4abeaf78144a834e22b49ee4310f23d3ebf4d10",
                    "token": "BTC",
                    "side": "SELL",
                    "price": 62154.000000,
                    "size": 49.999999999999946328,
                    "tradeValue": 0.000804,
                    "fee": 0.000145,
                    "closedPnL": 0.000000,
                    "orderType": "OpenShort",
                    "associatedOrderId": "s5yj8etnxmvo2sxjyczyf"
                },
                {
                    "id": "67063a45fcabec1ae0dac836",
                    "tradeTime": "09/10/2024 - 08:09:41",
                    "tradeTimeForSorting": "2024-10-09T08:09:41.049Z",
                    "account": "0xa4abeaf78144a834e22b49ee4310f23d3ebf4d10",
                    "token": "BTC",
                    "side": "SELL",
                    "price": 62200.000000,
                    "size": 63.3631450542137632,
                    "tradeValue": 0.001018,
                    "fee": 0.000000,
                    "closedPnL": 0.000000,
                    "orderType": "OpenShort",
                    "associatedOrderId": "s5yj8etnxmvo2sxjyczyf"
                }
            ],
            "pageable": {
                "pageNumber": 0,
                "pageSize": 10,
                "sort": {
                    "empty": false,
                    "sorted": true,
                    "unsorted": false
                },
                "offset": 0,
                "paged": true,
                "unpaged": false
            },
            "last": true,
            "totalElements": 3,
            "totalPages": 1,
            "first": true,
            "size": 10,
            "number": 0,
            "sort": {
                "empty": false,
                "sorted": true,
                "unsorted": false
            },
            "numberOfElements": 3,
            "empty": false
        }
  5. Account Balance

    1. URL: {{baseUrl}}/v1/accountData/balance/:account

      This endpoint give insight on available deposited balance in USDC. Basically amount of collateral free to use. Input: account: User address Output: USDC value Eg: 343.917502459535209000

    2. URL: {{baseUrl}}/v1/positions/balance/:account

      It gives insight on USDC locked with the position, adding or subtracting unrealized PnL and subtracting fees.

      Input:

      account: user account

      Output:

      Gives you list of objects, each object corresponds to position of every asset.

      token -> Asset info

      amount -> collateral locked in position + open orders for this asset + unrealized PnL (can be positive or negative)

      value → Number of BTC tokens (locked in position + tokens that will be obtained on fulfilling open orders)

      Eg:

      [
          {
              "token": "BTC-PERP",
              "amount": 10703.573838,
              "value": 1.404813686625569662278803881985814801
          }
      ]
      
  6. Account PnL and Volume

  7. Latest status on orders based on order Id

    1. POST call on URL: {{baseUrl}}/v1/orders/latest-status

    2. BODY: List of order ids 1.

      [
          "_9jsknvpe8hve3n-lyrsr",
          "ycrb3yuf8y0_kpabdb-v7",
          "6a3uss9jpoq2l5ipvs4w0"
      ]
    3. Response: 1.

      [
          {
              "orderId": "_9jsknvpe8hve3n-lyrsr",
              "account": "0xa4abeaf78144a834e22b49ee4310f23d3ebf4d10",
              "token": "BTC",
              "size": 221.979417,
              "collateral": 22.197942,
              "side": "BUY",
              "typeOfOrder": "Limit",
              "triggerPrice": 60950.000000,
              "orderStatus": "OPEN",
              "orderValue": 0.003642,
              "openTime": "03/10/2024 - 10:51:52",
              "decreaseOrder": false,
              "isStopLoss": false,
              "isTakeProfit": false
          },
          {
              "orderId": "ycrb3yuf8y0_kpabdb-v7",
              "account": "0xa4abeaf78144a834e22b49ee4310f23d3ebf4d10",
              "token": "BTC",
              "size": 267.160545,
              "collateral": 26.716055,
              "side": "SELL",
              "typeOfOrder": "Limit",
              "triggerPrice": 63143.000000,
              "orderStatus": "CANCELLED",
              "orderValue": 0.004231,
              "openTime": "30/09/2024 - 23:45:58",
              "closedTime": "30/09/2024 - 23:54:54",
              "orderValueType": "Maker",
              "decreaseOrder": false,
              "isStopLoss": false,
              "isTakeProfit": false
          },
          {
              "orderId": "6a3uss9jpoq2l5ipvs4w0",
              "account": "0x5260fcd99dce754c278b5ceff17405ca4b4ac4d7",
              "token": "BTC",
              "size": 22.000000,
              "collateral": 0.000000,
              "side": "BUY",
              "typeOfOrder": "Limit",
              "triggerPrice": 54288.630000,
              "orderStatus": "MATCHED",
              "orderValue": 0.000405,
              "openTime": "07/09/2024 - 20:38:47",
              "closedTime": "07/09/2024 - 20:39:44",
              "orderValueType": "Maker",
              "decreaseOrder": false,
              "isStopLoss": false,
              "isTakeProfit": false
          }
      ]

Pre-requisite

Bearer Token need to be passed as the method of authentication to fetch data from the following endpoints.

How to fetch bearer token is explained above.


Web Socket Connections

Order Book State:

  1. To get Order Book State, we can use the following end points:

    1. Get Index Token, from “Get All Traded Assets endpoint” for each traded asset. For eg: for BTC, indexToken = “0x152b9d0fdc40c096757f570a51e494bd4b943e50”

    2. complete URL = ${API_BASE_URL}api/order-book/orderbook-websocket;

    3. To connect with websockets, we need to create a initial connection, then connect to /topic/orderBookState:

      const socket = new SockJS(URL, {}, {});
      stompClient = Stomp.over(socket);
      
      // Subscribe to a single topic that broadcasts all necessary data
      
      stompClient.send("/app/init", {}, indexToken);
      
      stompClient.subscribe("/topic/orderBookState", (message) => {
        const data: MarketStateDataWS = JSON.parse(message.body);
      });
  2. It will return following JSON

Live Feed On Assets:

  1. To get live feed on state, we can use the following end points:

    1. complete URL = ${API_BASE_URL}api/order-book/orderbook-websocket;

    2. Get Index Token, from “Get All Traded Assets endpoint” for each traded asset. For eg: for BTC, indexToken = “0x152b9d0fdc40c096757f570a51e494bd4b943e50”

    3. To connect with web sockets, we need to create a initial connection, then connect to /topic/livefeed:

    stompClient.send("/app/init", {}, indexToken);
    
    stompClient.subscribe("/topic/livefeed", (message: any) => {
    const data = JSON.parse(message.body);
    console.log("Received data from WebSocket", data);
    if (!data || data.symbol !== tokenCurrency) {
      console.log("Invalid data", data);
      return;
    }
    
  2. It will return following JSON

    {
      "symbol": "BTC",
      "currentPrice": 59994,
      "oraclePrice": 62063.293333333335,
      "epochTimestamp": 1726733269
    }


Native WebSocket Connections

Native WebSocket connections provide a more granular approach to interacting with WebSocket servers without relying on higher-level libraries like SockJS or STOMP clients. Below is an example of connecting to the Filament Finance Order Book WebSocket server using Python.

WebSocket Connection Workflow

  1. Establish a WebSocket Connection

    • Connect to the WebSocket endpoint using the websocket.WebSocketApp library.

    • Define callback functions to handle on_open, on_message, on_close, and on_error events.

  2. Send STOMP Frames

    • Connect Frame: Establishes the STOMP connection by sending necessary headers.

    • Subscribe Frame: Subscribes to the desired topic, such as /topic/orderBookState.

    • Send Frame: Sends initialization messages with the required payload (e.g., indexToken).

  3. Receive and Process Messages

    • Handle incoming messages via the on_message callback to process data in real-time.

  4. Threaded Connection

    • Run the WebSocket client in a separate thread to maintain a persistent connection while allowing other processes to run concurrently.

OrderBook State:

BASE_URL = wss://orderbook.filament.finance/sei/api/order-book/book-websocket

Example Code

import websocket
import threading
import time

# STOMP frame for connecting
def create_connect_frame():
    return (
        "CONNECT\n"
        "accept-version:1.1,1.2\n"
        "host:orderbook.filament.finance\n"
        "\n"
        "\x00"
    )

# STOMP frame for subscribing to a topic
def create_subscribe_frame():
    return (
        "SUBSCRIBE\n"
        "id:sub-0\n"
        "destination:/topic/orderBookState\n"
        "\n"
        "\x00"
    )

# STOMP frame for sending a message
def create_send_frame(index_token):
    return (
        f"SEND\ndestination:/app/init\n\n{index_token}\x00"
    )

# Define the WebSocket connection URL
ws_url = "wss://orderbook.filament.finance/sei/api/order-book/book-websocket"

# Function to handle messages from the WebSocket
def on_message(ws, message):
    print(f"Received message: {message}")

# Function to handle WebSocket connection opening
def on_open(ws):
    print("WebSocket connection opened")

    # Send the STOMP CONNECT frame
    ws.send(create_connect_frame())
    time.sleep(1)  # Small delay to ensure the server processes the connect

    # Subscribe to the topic
    ws.send(create_subscribe_frame())
    print("Subscribed to /topic/orderBookState")

    # Send the initialization message
    index_token = "0x152b9d0fdc40c096757f570a51e494bd4b943e50"
    ws.send(create_send_frame(index_token))
    print(f"Sent initialization message with token: {index_token}")

# Function to handle WebSocket closing
def on_close(ws):
    print("WebSocket connection closed")

# Function to handle WebSocket errors
def on_error(ws, error):
    print(f"WebSocket error: {error}")

# Create the WebSocket app and assign event handlers
ws = websocket.WebSocketApp(ws_url,
                            on_message=on_message,
                            on_open=on_open,
                            on_close=on_close,
                            on_error=on_error)

# Run the WebSocket in a separate thread
ws_thread = threading.Thread(target=ws.run_forever)
ws_thread.start()

# Keep the main thread alive to maintain the WebSocket connection
try:
    while True:
        time.sleep(1)
except KeyboardInterrupt:
    print("Closing connection")
    ws.close()
    ws_thread.join()

Order Updates:

BASE_URL = wss://orderbook.filament.finance/sei/api/order-websocket

account → Wallet address need to passed in lower case Eg: 0xb02a810c5bb22b093ed52e3d6adb45c8519d68e7

Mandatory Parameters:

  1. account

Optional Parameters:

  1. token

  2. side

Payload required to be passed:

{
  "account": "0xb02a810c5bb22b093ed52e3d6adb45c8519d68e7", // required
  "token": "BTC", // optional
  "side": "BUY" // optional
}

Example Code

import websocket
import threading
import time
import json

# STOMP frame for connecting
def create_connect_frame():
    return (
        "CONNECT\n"
        "accept-version:1.1,1.2\n"
        "host:orderbook.filament.finance\n"
        "\n"
        "\x00"
    )

# STOMP frame for subscribing to a specific topic
def create_subscribe_frame(account):
    return (
        f"SUBSCRIBE\n"
        f"id:sub-0\n"
        f"destination:/topic/order-updates/{account}\n"
        "\n"
        "\x00"
    )

# STOMP frame for sending an initialization message
def create_send_frame(account):
    payload = json.dumps({"account": account})
    return (
        f"SEND\n"
        f"destination:/app/init/order-updates\n"
        f"content-type:text/plain\n"
        f"\n"
        f"{payload}\x00"
    )

# Define the WebSocket connection URL
ws_url = "wss://orderbook.filament.finance/sei/api/order-websocket"

# Function to handle messages from the WebSocket
def on_message(ws, message):
    print(f"Received raw message:\n{message}")
    try:
        # Extract and parse the JSON body from the STOMP message
        if "\n\n" in message:
            body = message.split("\n\n", 1)[1].strip("\x00")  # Extract message body
            data = json.loads(body)  # Parse JSON
        else:
            body = message.strip("\x00")
            data = json.loads(body)

        # Distinguish between list and single object
        if isinstance(data, list):
            print("Received initial list of orders:")
            for order in data:
                print(order)
        elif isinstance(data, dict):
            print("Received individual order update:")
            print(data)
        else:
            print("Unexpected message format")
    except json.JSONDecodeError as e:
        print(f"Error parsing JSON message: {e}")
    except Exception as e:
        print(f"Unexpected error in on_message: {e}")

# Function to handle WebSocket connection opening
def on_open(ws):
    print("WebSocket connection opened")

    # Send the STOMP CONNECT frame
    ws.send(create_connect_frame())
    time.sleep(1)  # Allow server to process the connection

    # Account to subscribe to and initialize
    account = "0xb02a810c5bb22b093ed52e3d6adb45c8519d68e7"

    # Subscribe to the topic
    ws.send(create_subscribe_frame(account))
    print(f"Subscribed to /topic/order-updates/{account}")

    # Send the initialization message
    ws.send(create_send_frame(account))
    print(f"Sent initialization message for account: {account}")

# Function to handle WebSocket closing
def on_close(ws):
    print("WebSocket connection closed")

# Function to handle WebSocket errors
def on_error(ws, error):
    print(f"WebSocket error: {error}")

# Function to handle WebSocket ping messages
def on_ping(ws, message):
    print(f"Received ping: {message}")

# Function to handle WebSocket pong messages
def on_pong(ws, message):
    print(f"Received pong: {message}")

# Create the WebSocket app and assign event handlers
ws = websocket.WebSocketApp(
    ws_url,
    on_message=on_message,
    on_open=on_open,
    on_close=on_close,
    on_error=on_error,
    on_ping=on_ping,
    on_pong=on_pong,
)

# Run the WebSocket in a separate thread
ws_thread = threading.Thread(target=ws.run_forever)
ws_thread.daemon = True  # Set as a daemon thread to exit with the main program
ws_thread.start()

# Keep the main thread alive to maintain the WebSocket connection
try:
    while True:
        time.sleep(1)
except KeyboardInterrupt:
    print("Closing connection")
    ws.close()
    ws_thread.join()

Sample Response, on order updates:

{
  "orderId": "nvqyvjbmyvepgfxykinbq",
  "account": "0xb02a810c5bb22b093ed52e3d6adb45c8519d68e7",
  "token": "BTC",
  "size": 1556.2,
  "collateral": 77.81,
  "side": "SELL",
  "typeOfOrder": "Limit",
  "triggerPrice": 89952.0,
  "orderStatus": "OPEN",
  "orderValue": 0.0173,
  "openTime": "18/11/2024 - 13:47:24",
  "decreaseOrder": false,
  "isStopLoss": false,
  "isTakeProfit": false
}

How to Place Close Orders for Open Positions

Using the response from the trades endpoint, you can determine the necessary details (quantity, entryPrice, and side) for each position and decide the price at which they want to close the position, either for profit or loss. Below is a step-by-step guide:


Step 1: Fetch Open Positions

  1. Endpoint:

    https://orderbook.filament.finance/sei/api/v1/positions/trades/paginated/{ACCOUNT}?page={page}&size={size}

  2. Data Retrieved:

    Each position includes fields like:

    • Side (BUY or SELL)

    • Quantity (e.g., 0.000139)

    • Entry Price (e.g., 98269.916666)

    • Collateral and other metrics.

    Example, for account:

    {
        "content": [
            {
                "openTime": "27/11/2024 - 12:00:52",
                "account": "0x216d86bfb23544ad5c14ac728620465cb6a9d5f4",
                "token": "BTC",
                "side": "SELL",
                "entryPrice": 98269.916666,
                "markPrice": 98900.000000,
                "size": 13.572581,
                "quantity": 0.000139,
                "collateral": 37.236174,
                "fees": 0.006854,
                "realizedPnL": -0.087582,
                "takeProfit": null,
                "stopLoss": null,
                "liquidationPrice": 363686.674029,
                "leverage": 0.364500
            }
        ],
        "pageable": {
            "pageNumber": 0,
            "pageSize": 4,
            "sort": {
                "empty": false,
                "unsorted": false,
                "sorted": true
            },
            "offset": 0,
            "paged": true,
            "unpaged": false
        },
        "last": true,
        "totalElements": 1,
        "totalPages": 1,
        "first": true,
        "size": 4,
        "number": 0,
        "sort": {
            "empty": false,
            "unsorted": false,
            "sorted": true
        },
        "numberOfElements": 1,
        "empty": false
    }
    
  3. Use these fields:

    • quantity: Total amount of the token to close.

    • entryPrice: Reference price to determine profit/loss.

    • side: Indicates whether the position is BUY or SELL.


Step 2: Place Close Order

  1. Endpoint:

    https://orderbook.filament.finance/sei/filament/api/v1/exchange

  2. Payload Construction:

    • Construct the payload using the provided quantity, closePrice (user-defined), and side.

    • reduceOnly flag should be true for closed orders.

    • size = quantity x entryPrice

    • isBuy

      • false: If position was short

      • true: If position was long

  3. Payload Example: For a SELL position:

    {
      "type": "order",
      "referralCode": null,
      "orders": [
        {
          "account": "0x216D86BfB23544AD5c14ac728620465Cb6a9D5F4",
          "indexToken": "BTC",
          "isBuy": false,
          "size": 13.659518,
          "leverage": -1,
          "reduceOnly": true,
          "orderType": {
            "type": "limit",
            "limit": {
              "tif": "Gtc",
              "limitPrice": "98269"
            }
          },
          "orderId": "<generated_order_id>",
          "signature": "<generated_signature>"
        }
      ]
    }
    
  4. Parameters Explained:

    • isBuy: false for closing a SELL position; true for closing a BUY position.

    • size: Equal to the quantity from the position.

    • reduceOnly: Ensures the order reduces the position.

    • limitPrice: User-specified close price.

  5. Send the Request:

    • Use POST to send the constructed payload to the endpoint.


Step 3: Confirmation

  • The response from the order placement endpoint will indicate whether the close order was successfully placed.


Summary

  1. Fetch open positions using the trades endpoint.

  2. Extract quantity, entryPrice, and side from the response.

  3. Define a close price → Which will decide whether position will be closed in profit or loss.

  4. Construct a reduce-only order payload:

    • Use isBuy based on the position side (BUY or SELL).

    • Set reduceOnly to true.

    • Specify thelimitPrice.

  5. Place the close order via the orderbook endpoint.

PreviousSecurity Audits

Last updated 2 months ago

API_BASE_URL =

PostMan Collection
https://orderbook.filament.finance/sei/
PAYLOAD