Live quotes
When a user is looking at a swap form, the quote gets old fast. Instead of polling /route, open a WebSocket to /route/subscribe. The server sends a new set of quotes every time the pools change in a way that changes the result.
wss://router.intear.tech/route/subscribeHow it works
Section titled “How it works”-
Open the socket.
-
Send a request.
queryis the same query string/routetakes, andidis any number you choose:{"id": 1,"query": "token_in=near&token_out=usdt.tether-token.near&amount_in=1000000000000000000000000&max_wait_ms=2000&slippage_type=Fixed&slippage=0.01&trader_account_id=alice.near"} -
Receive quotes. The first update comes as soon as routes are found, then a new one whenever they change:
{ "id": 1, "routes": [ ... ] }routesis the same array of quotes/routereturns. -
When the user changes the form, send a new request with a new
id. It replaces the previous one: the server stops updating the old request. Updates of the old request that were already on their way may still arrive, so ignore any update whoseidisn’t the latest one you sent. -
To stop updates without closing the socket, send a message with only an
id:{ "id": 2 }
Example
Section titled “Example”const socket = new WebSocket('wss://router.intear.tech/route/subscribe');let latestId = 0;
function requestQuotes(params) { latestId += 1; socket.send(JSON.stringify({ id: latestId, query: new URLSearchParams(params).toString() }));}
socket.addEventListener('message', (event) => { const update = JSON.parse(event.data); if (update.id !== latestId) return; // an update of an older request if ('error' in update) { showError(update.error); } else { showQuotes(update.routes); }});
socket.addEventListener('open', () => { requestQuotes({ token_in: 'near', token_out: 'usdt.tether-token.near', amount_in: '1000000000000000000000000', max_wait_ms: '2000', slippage_type: 'Fixed', slippage: '0.01', trader_account_id: 'alice.near', });});With tokio-tungstenite, using the Quote type from the Quickstart:
futures-util = "0.3"serde_json = "1"tokio-tungstenite = { version = "0.30", features = ["native-tls"] }use futures_util::{SinkExt, StreamExt};use tokio_tungstenite::{connect_async, tungstenite::Message};
#[derive(Deserialize)]#[serde(untagged)]enum Update { Routes { id: u64, routes: Vec<Quote> }, Error { id: u64, error: String },}
let (mut socket, _) = connect_async("wss://router.intear.tech/route/subscribe").await?;
let latest_id = 1;let query = "token_in=near&token_out=usdt.tether-token.near&amount_in=1000000000000000000000000\ &max_wait_ms=2000&slippage_type=Fixed&slippage=0.01&trader_account_id=alice.near";let request = serde_json::json!({ "id": latest_id, "query": query });socket.send(Message::text(request.to_string())).await?;
while let Some(message) = socket.next().await { let Message::Text(text) = message? else { continue; }; match serde_json::from_str::<Update>(&text)? { Update::Routes { id, routes } if id == latest_id => show_quotes(routes), Update::Error { id, error } if id == latest_id => show_error(error), _ => {} // an update of an older request }}Things to know
Section titled “Things to know”- Errors don’t close the socket. An invalid query returns
{ "id": 1, "error": "..." }and the socket stays open. - Invalid JSON closes the socket. A message that isn’t
{ "id": ..., "query": ... }ends the connection. - Updates are only sent on changes. If the pools change but the quotes stay the same, nothing is sent.
- Updates are throttled. After each update, the server waits about 10× the time routing took (at most 3 seconds) before routing again.