Skip to main content

Market Data and Leaderboard

gSwap.market reads USD prices, price series and the platform volume totals, and gSwap.leaderboard reads the trading-competition seasons and rankings. They are public reads of the swap backend: no signer, no wallet.

Prices​

const [gala, bene] = await gSwap.market.getPrices([
'GALA$Unit$none$none',
{ collection: 'Token', category: 'Unit', type: 'BENE', additionalKey: 'client:5c806869e7fd0e2384461ce9' },
]);
console.log(gala?.price, gala?.change24h, gala?.listed);
const single = await gSwap.market.getPrice('GALA|Unit|none|none');

getPrices takes 1 to 500 tokens and sends them in as many GET /market/price requests as their length needs, one after another: the backend refuses a request line over 16 KB (HTTP 431; 300 launchpad keys are 17.7 KB), so each request carries at most MARKET_PRICE_QUERY_BYTES (8 000) of ids, about 135 launchpad keys. A failed request fails the call. Name a token by a symbol (GALA) or a class key: the $ form, the | form or the object (sent in its $ form). The answer is in the order you asked:

  • an entry is { token, price, change24h, listed }: token is the id that was asked for, price is USD (null when the backend knows the token but has no price), change24h is in percent;
  • undefined means the backend has no entry for that token. The backend keys each answer by the exact id it was asked for (and also by the symbol, which two keys can share), and the SDK reads only that id, so a token is never given another token's price.

A malformed entry is undefined too, and is reported to onInvalidEntry. A token string the backend would refuse (outside A-Z a-z 0-9 . _ $ + / : | -, or over 120 characters) is INVALID_MARKET_TOKEN before anything is sent; more than 500 tokens is INVALID_TOKEN_BATCH.

Price series​

const series = await gSwap.market.getPriceSeries('GALA$Unit$none$none', '1W');
for (const point of series.prices) console.log(new Date(point.time * 1000), point.price);
console.log(series.currentPrice, series.change24h);

The windows are 1D, 1W, 1M, 1Y and ALL (PRICE_SERIES_TIMEFRAMES); any other is INVALID_TIMEFRAME before anything is sent. The whole series comes in one answer, oldest first, with time in unix seconds. A token the backend has no prices for is an empty series with currentPrice: null.

Volume​

const volume = await gSwap.market.getVolumeSummary();
console.log(volume.tvl, volume.volume1d, volume.trades1d, volume.volume1dDelta);

TVL, 1-, 7- and 30-day volume (USD) and the 24-hour trade count across every current-contract pool. A delta is a fraction of the previous period: -0.11 is 11 % less, and it is 0 when the previous period had no volume.

New pools​

const stop = gSwap.pools.watchNewPools((pool) => console.log('new pool', pool.poolRef), {
intervalMs: 60_000,
minTvl: 1000,
tokens: ['GALA'],
onError: (error) => console.warn('poll failed', error),
});
// later
stop();

watchNewPools polls gSwap.pools.getPools() (the alternative to the realtime stream's gSwap.stream.subscribePoolCreated for a client that cannot hold a WebSocket open). The first answer is the baseline: a pool that existed then is never reported. Each later pool is judged once, when it first appears, against minTvl and tokens. A poll never overlaps the previous one, a failed poll or a throwing callback goes to onError (polling goes on), and nothing is reported after stop(). An intervalMs that is not a finite number of at least 1 is INVALID_POLL_INTERVAL.

Leaderboard​

const seasons = await gSwap.leaderboard.getSeasons();
const season = await gSwap.leaderboard.getCurrentSeason(); // null between seasons
const { entries } = await gSwap.leaderboard.getLeaderboard(seasons[0]!.id);
const current = await gSwap.leaderboard.getCurrentLeaderboard(); // null between seasons

A season is { id, name, start, end, rulesId } with Date bounds; getCurrentSeason picks the season running at options.now (default: now), and start and end both count as inside. An entry is { wallet, rank, totalXp, distributionPercent, liquidityXp, tradingXp, masteryTitles } with XP as decimal strings; totalXp is null for a ranked wallet the backend has no XP breakdown for yet. seasonId must be an integer of at least 1 (INVALID_SEASON_ID).

Failures​

Every failure of these reads is a read's (error.write === false), so classifyFailure judges a 5xx, a timeout or an unusable answer (INVALID_CHAIN_RESPONSE) as transient: Retry is safe.