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
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 bynanoid
.signature
: The private key used to sign the order (passed assigningKey
inprocessOrders
).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
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 ordersisBuy
: 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:
For each price change, it generates a unique order ID using
nanoid()
.The order ID is signed using the
handleOrderSignature
function.An order payload is created with information like the asset being traded, order size, leverage, and limit price.
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:
Current mark Price
Current Spot Price
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:
Open Orders
{{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:
token: Asset Eg: BTC
side: BUY/SELL
Output:
Paginated response of user open orders:
Datapoints include:
orderId: Unique Order id of the order.
openTime: order open time
account: user account
side: BUY/SELL
token: asset on which position is created
triggerPrice: price at which order will be triggered.
typeOfOrder:
Limit
Market
TakeProfit
StopLoss
size: Size of order in USDC.
orderValue: Number of tokens.
collateral: Used collateral for this open order.
decreaseOrder: true if order a decrease order
Note: Order can be of two types,
Normal orders to increase or create positon.
Orders to reduce position are categorized as decrease orders.
isTakeProfit -> true is order is a Take Profit order, otherwise false
isStopLoss -> true is order is a Stop Loss order, otherwise false
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 }
Closed Orders
{{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:
token: Asset Eg: BTC
side: BUY/SELL
Output:
Paginated response of user open orders:
Datapoints include:
orderId: Unique Order id of the order.
openTime: order open time
closedTime: Give last update on this order
account: user account
side: BUY/SELL
token: asset on which position is created
triggerPrice: price at which order will be triggered.
typeOfOrder:
Limit
Market
TakeProfit
StopLoss
size: Size of order in USDC.
orderValue: Number of tokens.
orderStatus:
OPEN
MATCHED
CANCELLED
FAILED
collateral: Used collateral for this order.
decreaseOrder: true if order a decrease order
Note: Order can be of two types,
Normal orders to increase or create positon.
Orders to reduce position are categorized as decrease orders.
isTakeProfit -> true is order is a Take Profit order, otherwise false
isStopLoss -> true is order is a Stop Loss order, otherwise false
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"
Order opened at time: 30/09/2024 - 11:56:47, for size: 400 USDC
It Matched for size $200, then an entry will be present with status matched and size $200.
Then if this order is cancelled, then another entry will be present of size $200 with status CANCELLED
Positons (Open Positions - Trades)
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:
openTime: Position open time
account: user account
side: BUY/SELL
token: asset on which position is created
entryPrice: average price of your position.
markPrice: current mark price, which is basically the best Ask.
size: Size of position in USDC, it keep on updating with market price movement.
quantity: Number of tokens (remains constant unless position is increased or decreased)
Collateral: Amount locked in USDC
Fees: Borrowing fees + Trading fees + Funding fees
realizedPnL: This is actually unrealized PnL value. which is calculated basd on formula.
BUY -> (markPrice - averagePrice) x quantity
SELL -> (averagePrice - markPrice) x quantity
takeProfit -> Return take profit price if set for position, otherwise null.
stopLoss -> Return stop loss price if set for position, otherwise null.
Liquidation Price -> Provides current liquidation price of user position, it keep on updating with moving market price.
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 }
Trade History
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:
tradeTime: Time when trade occurrred.
account: user account
side: BUY/SELL
token: asset on which position is created
price: price at which order was matched and trade was executed.
size: Size of position in USDC.
tradeValue: Number of tokens
Collateral: Amount locked in USDC
Fees: Borrowing fees + Trading fees + Funding fees charged
closedPnL: Realized PnL
orderType ->
OpenLong
OpenShort
CloseLong
CloseShort
LiquidationCloseLong
LiquidationCloseShort
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 }
Get trade history with associated Order Id.
URL: {{baseUrl}}/v1/positions/tradeHistory/paginated/:account?page=0&size=10&associatedOrderId=
Inputs:
account: Account address need to be passed in lower case.
associatedOrderId (Optional parameter): Order Id, for which necessary trades are required to be found.
Output:
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 }
Account Balance
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
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 } ]
Account PnL and Volume
Latest status on orders based on order Id
POST call on URL: {{baseUrl}}/v1/orders/latest-status
BODY: List of order ids 1.
[ "_9jsknvpe8hve3n-lyrsr", "ycrb3yuf8y0_kpabdb-v7", "6a3uss9jpoq2l5ipvs4w0" ]
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
API_BASE_URL
= https://orderbook.filament.finance/sei/
Order Book State:
To get Order Book State, we can use the following end points:
Get Index Token, from “Get All Traded Assets endpoint” for each traded asset. For eg: for BTC, indexToken = “0x152b9d0fdc40c096757f570a51e494bd4b943e50”
complete URL =
${API_BASE_URL}api/order-book/orderbook-websocket
;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); });
It will return following JSON
Live Feed On Assets:
To get live feed on state, we can use the following end points:
complete URL =
${API_BASE_URL}api/order-book/orderbook-websocket
;Get Index Token, from “Get All Traded Assets endpoint” for each traded asset. For eg: for BTC, indexToken = “0x152b9d0fdc40c096757f570a51e494bd4b943e50”
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; }
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
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
, andon_error
events.
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
).
Receive and Process Messages
Handle incoming messages via the
on_message
callback to process data in real-time.
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:
account
Optional Parameters:
token
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
Endpoint:
https://orderbook.filament.finance/sei/api/v1/positions/trades/paginated/{ACCOUNT}?page={page}&size={size}
Data Retrieved:
Each position includes fields like:
Side (
BUY
orSELL
)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 }
Use these fields:
quantity
: Total amount of the token to close.entryPrice
: Reference price to determine profit/loss.side
: Indicates whether the position isBUY
orSELL
.
Step 2: Place Close Order
Endpoint:
https://orderbook.filament.finance/sei/filament/api/v1/exchange
Payload Construction:
Construct the payload using the provided
quantity
,closePrice
(user-defined), andside
.reduceOnly
flag should be true for closed orders.size
=quantity
xentryPrice
isBuy
false: If position was short
true: If position was long
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>" } ] }
Parameters Explained:
isBuy
:false
for closing aSELL
position;true
for closing aBUY
position.size
: Equal to thequantity
from the position.reduceOnly
: Ensures the order reduces the position.limitPrice
: User-specified close price.
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
Fetch open positions using the trades endpoint.
Extract
quantity
,entryPrice
, andside
from the response.Define a close price → Which will decide whether position will be closed in profit or loss.
Construct a reduce-only order payload:
Use
isBuy
based on the position side (BUY
orSELL
).Set
reduceOnly
totrue
.Specify the
limitPrice
.
Place the close order via the orderbook endpoint.
Last updated