TypeScript SDK
Official @anaxer/sdk client for Node.js — typed WebSocket streams and REST reads over the public /v1 API. Handles auth, heartbeat, and auto-reconnect so you don't hand-roll the lifecycle.
Install
Requires Node.js ≥ 20. ESM and CommonJS builds ship together.
npm install @anaxer/sdkA Python SDK is coming soon.
Quickstart
import { connect } from "@anaxer/sdk";
const client = connect({ apiKey: process.env.ANAXER_API_KEY! });
client.stream("creations", { excludeMayhem: true }).on("data", (token) => {
console.log("new launch:", token.symbol, token.mint);
});
const price = await client.tokens.price(
"3PFaeFMXiRVYueDCnHHSKndKDDpKZhbhFjQ13JXYpump"
);connect() returns immediately. The WebSocket opens on the first stream() call (or await client.ready()). Auth is Authorization: Bearer for both WS and REST.
What it handles
- Auth — attaches your API key for WebSocket and REST.
- Typed events — channel payloads match the public WebSocket and REST v1 shapes.
- Heartbeat — client pings; the socket is treated as dead if no inbound traffic arrives within 2× the interval.
- Reconnection — exponential backoff with jitter; re-sends every active subscription after reconnect.
Streaming
Subscribe with client.stream(channel, filters?). Each call returns a subscription you can listen on and close independently.
| Channel | Payload | Common filters |
|---|---|---|
| trades | SwapV1 | sources, mints, wallets, minVolumeUsd, maxVolumeUsd |
| creations | CreatedV1 | sources, enriched, excludeMayhem |
| graduations | GraduatedV1 | sources, excludeMayhem, minLiquiditySol |
| prices | PriceUpdateV1 | sources, mints |
const sub = client.stream("trades", {
sources: ["pump_fun"],
minVolumeUsd: 10,
});
sub.on("subscribed", (filters) => console.log("live", filters));
sub.on("data", (swap) => console.log(swap.signature, swap.volumeUsd));
sub.on("error", (err) => console.error(err.code, err.message));
// later
sub.close(); // unsubscribe; not resurrected after reconnectThe transfers channel is not exposed on stream() yet (server ingestion pending). The TransferV1 type is still exported for typing.
Connection events
client.on("connected", ({ maxSubscriptions }) => {
console.log("plan cap", maxSubscriptions);
});
client.on("reconnect", (attempt) => console.log("retry", attempt));
client.on("error", (err) => console.error(err.code, err.message));
await client.ready(); // resolves on first connected frame
await client.close(); // graceful shutdown; disables reconnect- Heartbeat default
heartbeatMs: 15_000; set0to disable. - Reconnect is on by default;
reconnect: falsedisables it.unauthorizedis terminal (bad key — no retry loop).
REST
All calls are authenticated GETs. Transient 429 / 5xx retry up to restMaxRetries (default 2), honoring Retry-After. Other 4xx throw immediately.
| Method | Returns |
|---|---|
| client.tokens.get(mint) | TokenMetadataV1 |
| client.tokens.batch(mints) | TokenMetadataV1[] (max 50) |
| client.tokens.price(mint) | PriceUpdateV1 |
| client.tokens.batchPrice(mints) | PriceUpdateV1[] |
| client.tokens.trades(mint, opts?) | Page<SwapV1> |
| client.creations(opts?) | Page<CreatedV1> |
| client.graduations(opts?) | Page<GraduatedV1> |
| client.launchpads.stats(opts?) | LaunchpadStatsV1 |
List endpoints return a Page<T> with .data, .next, and .window. It is also an async iterable that walks next on the same endpoint until null:
const page = await client.creations({ excludeMayhem: true, limit: 50 });
console.log(page.data.length, page.window);
for await (const created of page) {
console.log(created.mint);
}Config
connect({
apiKey: process.env.ANAXER_API_KEY!, // required
baseUrl: "https://api.anaxer.com", // optional
// wsUrl derived from baseUrl → wss://…/v1/stream
reconnect: true, // or false | { baseDelayMs, maxDelayMs, maxRetries }
heartbeatMs: 15_000, // 0 disables
restMaxRetries: 2, // 0 disables REST retries
});Errors
REST non-2xx throws AnaxerError (code, message, status). WebSocket error frames emit on the matching subscription (when an id is present) or on the client.
import { AnaxerError, connect } from "@anaxer/sdk";
const client = connect({ apiKey: process.env.ANAXER_API_KEY! });
try {
await client.tokens.get(mint);
} catch (e) {
if (e instanceof AnaxerError && e.code === "not_found") {
// mint never observed
}
}See the full error codes reference.
Types
Payload and filter types are exported from the package (SwapV1, CreatedV1, TradesFilters, SubscriptionFiltersV1, …). WIRE_VERSION is 1 (envelope v, independent of the npm package version).