WebSocket Integration is the alternative to the HTTPS Integration. In general, the overall flow remains the same, but Instead of native pulling the order book data from your server, websocket allows you to stream order book data to us.
WebSocket Endpoints
1. Server Url & Authentication
Native WebSocket URL is hosted on https://newapi.native.org/v1/pmm/ws .
In order for Native to authenticate all the requests coming, you need to pass the api_key in the headers. You can get api_key by requesting to the Native team because we need to manually whitelist the API key that has access to the websocket URL.
Note: You are required to connnect to our websoket via ws library, not socket.IO library. For further example, you can visit the
2. Orderbook/Price Levels
In order to indicate current pricing for Native APIs and aggregators, you have to send price levels for each supported pair on every network. The recommended frequency is every second for every pair on every supported network. The following is the message format expected by Native:
{
"messageType": "orderbook",
"message": {
"chainId": number, // e.g. 1 (mainnet), 137 (polygon)
"baseTokenAddress": string, // e.g. 0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2 (WETH)
"quoteTokenAddress": string, // e.g. 0xdac17f958d2ee523a2206206994597c13d831ec7 (USDT)
"side": "buy" | "sell",
"levels": [
{
// string representation of the quantity of current level e.g. (2.5 for 2.5 WETH)
quantity: string,
// string representation of the price per unit at that level
// (e.g. 3500 for "up to 2.5 WETH at 3500 USDT per WETH")
price: string
}
]
}
}
Note: Order quantity is ordered in a non-cumulative way, let's say we have a WETH-USDT order book with the current price level:
[
{ quantity: "0.001", price: "1600" }, //the first 0.001 ETH is priced at 1600 USDT / WETH
{ quantity: "1", price: "1610" }, //the next 1 ETH is priced at 1610 USDT / WETH
{ quantity: "2", price: "1612" } //the next 2 ETH is priced at 1612 USDT / WETH
]
For example, if someone wanted to trade 3 WETH for USDT, the price would be: 0.001 * 1600 + 1 * 1610 + 1.999 * 1612 = 4833.988
Note: Native will cache these price levels for a max of 5 seconds (or until new levels are published) and use them to route RFQs. Price will be considered expired and invalid if you do not post new price levels after 5 seconds
Note: The first level is always the minimum amount you're looking to buy. if you want to support arbitrarily small amount, you should pass the first level quantity as 0
3. Firm Quote
If our router decides to route to you, it will request a firm quote by passing a websocket message to your server in the following format
{
"messageType": "firmQuote",
"message": {
"quoteId": string, // This is a unique quote ID generated by Native
"chainId": number, // 1 for ETH L1
"baseTokenAddress": string, // Base token (the token the trader sells).
"quoteTokenAddress": string, // Quote token (the token the trader buys).
"baseTokenAmount": string, //in wei
"seller": string, //The address that will send seller token to market maker.
"pool": string, //Native pool contract address that will execute this order.
// How much, in basis points, will be charged to you in fees if this order goes through.
"feesBps": number
}
}
After receiving this Firm Quote message, you have to compute the quote you'd like to offer (based on market conditions, internal balances, etc) and return it in the following format:
{
"messageType": "quote",
"message": {
// Same as Firm Quote request
"quoteId": string;
"baseTokenAddress": string,
"quoteTokenAddress": string,
// Amounts are in wei
"baseTokenAmount": string,
"quoteTokenAmount": string,
// The unix timestamp when the quote expires, in seconds.
"deadlineTimestamp": number,
// an optional auth Id that we will pass back when we request for a sign quote
"authId": ?string;
}
}
4. Sign Quote
After our server has validated the firm quote, we will ask for you to sign the quote by requesting the following message
{
"messageType": "signQuote",
"message": {
"quoteData": {
// It is leveraged to mitigate quote replay.
"nonce": number,
"signer": string,
"baseTokenAddress": string,
"quoteTokenAddress": string,
"baseTokenAmount": string,
"quoteTokenAmount": string,
"deadlineTimestamp": string,
"chainId": number,
"caller": string,
"authId": ?string, //the same authId if it is sent in the firm quote
"quoteId": string,
}
}
}
You can refer to the previous page for the example of signing the order using the EIP712 specification.
After you validate the order and sign it, you can respond with the signature back to us:
{
"messageType": "signature",
"message": {
"quoteId": string, // This is the quote id previously sent.
"signature": string // 0x-prefix signature (65 bytes)
}
}