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 }:tokenis the id that was asked for,priceis USD (nullwhen the backend knows the token but has no price),change24his in percent; undefinedmeans 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.