Skip to content

Keeping every token

A backend that keeps every token doesn’t need to download all of them each time. Poll tokens.get (or GET /tokens) with since set to the height of the result before, and get only what changed:

  1. Fetch every token once, and remember the result’s height.
  2. Every few seconds, fetch again with since set to that height.
  3. If the result has "resumed": true, rows are only the tokens that changed, each with every field you asked for. Replace them, drop the tokens in left, which stopped matching where, and remember the new height.
  4. If it has "resumed": false, the server couldn’t work out what changed (it restarted since), and rows has every token. Start over with them.
/**
* Turns a table into `{ <key>: { <column>: value } }`, keyed by its first column
*/
function tableToObjects({ columns, rows }) {
const objects = {};
for (const row of rows) {
const object = {};
columns.slice(1).forEach((column, i) => (object[column] = row[i + 1]));
objects[String(row[0])] = object;
}
return objects;
}
const params = new URLSearchParams({ fields: 'symbol,decimals,price_usd' });
if (since !== undefined) params.set('since', String(since));
const response = await fetch(`https://api.intea.rs/tokens?${params}`);
const result = await response.json();
if (!response.ok) throw new Error(result.error.message);
if (!result.resumed) tokens.clear(); // every token is in rows
for (const [token, fields] of Object.entries(tableToObjects(result))) tokens.set(token, fields);
for (const token of result.left ?? []) tokens.delete(token);
// Poll again with `since: result.height`

since can’t be combined with sort, limit or offset, and the other params have to be the same as in the earlier request.

With min_change, the values are the ones subscribers with the same thresholds were sent. A threshold is kept for 10 minutes after it was last used, so polling more often than that with since only gets what crossed it.