Alpha feature: Token Filters access is gated. Ask the Mobula team to enable it for your account. Until then, use Pulse; it works the same way for the same view/filter workflow.
Migrating from Pulse V2? Check out the Migration Guide for step-by-step instructions.
This endpoint is only available to Growth and Enterprise plans.
What’s New in Token Filters
Token Filters Stream introduces significant improvements over Pulse V2:
- Clean Data Models: Output follows exactly
TokenDetailsOutput and MarketDetailsOutput schemas with consistent camelCase naming
- Partial Updates: Only changed fields are sent, reducing bandwidth and JSON parsing overhead
- Real-time View Updates: Views are updated in real-time based on incoming swaps - no more periodic sync messages
- REST API Initialization: Initialize views via REST API before connecting to WebSocket for better control
- WebSocket-only Subscriptions: Send the complete
mode + views payload directly over WebSocket when you do not need a REST init response first
- OHLCV Attachments: Add historical candles to initial view results and receive live candle updates per swap
- Improved Delete Messages: Delete messages now use structured objects instead of pipe-separated selectors
- Consistent camelCase: All input parameters use camelCase matching the output format
Architecture Overview
Connection Flow
You can connect to Token Filters in two ways:
- WebSocket Only (recommended): Send the full payload directly via WebSocket
- REST + WebSocket: Initialize via REST API first, then connect to WebSocket
┌─────────────────────────────────────────────────────────────────┐
│ Option 1: WebSocket Only │
├─────────────────────────────────────────────────────────────────┤
│ WebSocket Connect ──▶ Send Full Payload ──▶ Real-time │
│ (wss://api.mobula.io) (views + filters) Updates │
└─────────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────────┐
│ Option 2: REST + WebSocket │
├─────────────────────────────────────────────────────────────────┤
│ REST API ──▶ Get Initial Data ──▶ WebSocket ──▶ Updates │
│ (POST) + subscriptionId (subscribe) │
└─────────────────────────────────────────────────────────────────┘
Important: Even when using WebSocket, you must send the complete payload with mode and views - not just a subscriptionId. The REST API is optional and only useful if you need the initial data before connecting.
Token Filters WebSocket accepts the same GraphQL/Codex-style aliases as the REST token filters, including marketCap, sellCount4, sniperCount, and bundlerCount. See the Token Filters Reference for the full alias table.
Modes
Token Filters supports two modes:
| Mode | Description | Output Schema |
|---|
token | Token-based analytics and statistics | TokenDetailsOutput |
market | Pool/market-based data with pair information | MarketDetailsOutput |
Step 1: Initialize Views via REST API
Endpoint
POST /api/2/token/filters
Request Body
{
"mode": "token",
"views": {
"new-tokens": {
"sortBy": "createdAt",
"sortOrder": "desc",
"limit": 50,
"filters": {
"chainId": { "in": ["solana:solana"] },
"source": { "in": ["pumpfun"] },
"bonded": { "equals": false }
}
},
"trending": {
"sortBy": "trendingScore5min",
"sortOrder": "desc",
"limit": 30,
"filters": {
"chainId": { "in": ["solana:solana", "evm:8453"] },
"source": { "in": ["pumpfun", "moonshot-evm"] }
}
}
}
}
Response
{
"subscriptionId": "sub_abc123xyz",
"views": {
"new-tokens": {
"data": [
{
"address": "DPQxrrxJfTrLEjyknrUBcMDsAMYbAQJMnKTuJh4kbonk",
"chainId": "solana:solana",
"symbol": "EXAMPLE",
"name": "Example Token",
"priceUSD": 0.000123,
"marketCapUSD": 123000,
"volumeUSD24h": 50000,
...
}
]
},
"trending": {
"data": [...]
}
}
}
Step 2: Connect to WebSocket
Connection
Subscribe Message
Send the complete payload with your views configuration:
{
"type": "token-filters",
"authorization": "YOUR_API_KEY",
"payload": {
"mode": "token",
"delta": true,
"maxUpdatesPerMinute": 120,
"views": {
"new-tokens": {
"sortBy": "createdAt",
"sortOrder": "desc",
"limit": 50,
"filters": {
"chainId": { "in": ["solana:solana"] },
"source": { "in": ["pumpfun"] },
"bonded": { "equals": false }
}
},
"trending": {
"sortBy": "trendingScore5min",
"sortOrder": "desc",
"limit": 30,
"filters": {
"chainId": { "in": ["solana:solana", "evm:8453"] }
}
}
}
}
}
| Payload field | Type | Default | Description |
|---|
mode | "token" | "market" | Required | Selects token output or market/pool output |
views | object | Required | Object keyed by view name. Each value is a view definition |
delta | boolean | true | When true, update-token / update-market messages contain only changed fields plus identifiers |
maxUpdatesPerMinute | number | No throttle | Per-entity update throttle for the subscription |
Do NOT send just a subscriptionId. You must always send the full mode and views configuration, even if you previously called the REST API. The WebSocket subscription is stateless.
Preset Models
Use preset models for common use cases without defining full custom views:
{
"mode": "token",
"views": {
"new-tokens": {
"model": "new",
"filters": {
"chainId": { "in": ["solana:solana"] },
"source": { "in": ["pumpfun"] }
}
}
}
}
Available Presets
| Model | Description | Sort By | Default Filters |
|---|
new | Newly created launchpad tokens | createdAt desc | bonded: false, source: { in: launchpad pools } |
bonding | Tokens in bonding phase | bondingPercentage desc | bondingPercentage: { gt: 0, lt: 100 }, volume1hUSD: { gte: 10 }, bonded: false, bondedAt: null, launchpad pools |
bonded | Recently bonded tokens | bondedAt desc | bonded: true, bondedAt: { not: null }, launchpad pools |
trending | Fee-weighted trending tokens | feesPaid15minUSD desc | Liquidity, fee, volume, holder-concentration, transfer-tax and chain-specific thresholds |
explorer | Explorer view by trending | trendingScore1h desc | - |
topGainers | Top price gainers | priceChange6hPercentage desc | volume1hUSD: { gte: 500 } |
surge | Small-cap surge tokens | surgeScore desc | liquidityUSD: { gte: 3000, lte: 50000 }, surgeScore: { gt: 0 } |
OHLCV Mode
Enable OHLCV candlestick data for each token in a view by setting ohlcv: true in the view definition.
Parameters:
| Parameter | Type | Default | Description |
|---|
ohlcv | boolean | false | Enable OHLCV candle data |
ohlcvTimeframe | string | "5m" | Candle timeframe: 1s, 5s, 15s, 1m, 5m, 15m, 30m, 1h, 4h, 1d |
Constraints:
- When
ohlcv: true, the max limit is 15 tokens (automatically clamped)
- Up to 200 candles per token are returned on init when history is available
- Candle format:
{ o, h, l, c, v, t } (open, high, low, close, volume, timestamp ms)
Example (surge + OHLCV):
{
"mode": "token",
"views": {
"surge-ohlcv": {
"model": "surge",
"ohlcv": true,
"ohlcvTimeframe": "5m",
"limit": 10
}
}
}
Init response includes ohlcv array per token:
{
"subscriptionId": "sub_abc123",
"views": {
"surge-ohlcv": {
"data": [
{
"address": "TokenAddress...",
"chainId": "solana:solana",
"priceUSD": 0.001,
"ohlcv": [
{ "o": 0.0009, "h": 0.0012, "l": 0.0008, "c": 0.001, "v": 5000, "t": 1709300000000 },
{ "o": 0.001, "h": 0.0013, "l": 0.0009, "c": 0.0012, "v": 3200, "t": 1709300300000 }
]
}
]
}
}
}
Real-time candle updates are sent via update-token-ohlcv messages when new swaps occur:
{
"type": "update-token-ohlcv",
"payload": {
"viewName": "surge-ohlcv",
"token": { "address": "TokenAddress...", "chainId": "solana:solana" },
"candle": { "o": 0.001, "h": 0.0015, "l": 0.001, "c": 0.0014, "v": 8500, "t": 1709300600000 }
}
}
When a new candle period starts, the previous candle’s close is used as the new candle’s open. Volume resets to 0 for each new period.
Message Types
Update Message (Partial)
When token/market data changes, only the modified fields are sent:
{
"type": "update-token",
"payload": {
"viewName": "trending",
"token": {
"address": "DPQxrrxJfTrLEjyknrUBcMDsAMYbAQJMnKTuJh4kbonk",
"chainId": "solana:solana",
"priceUSD": 0.000135,
"priceChange1hPercentage": 15.2,
"volume1hUSD": 55000
}
}
}
Partial Updates: Only changed fields are included. Apply these as patches to your local state. The address and chainId are always included for identification.
New Token/Market Message
When a new token enters a view:
{
"type": "new-token",
"payload": {
"viewName": "new-tokens",
"token": {
"address": "NewTokenAddress123",
"chainId": "solana:solana",
"symbol": "NEW",
"name": "New Token",
"decimals": 6,
"priceUSD": 0.0001,
"priceToken": 0.00000005,
"priceTokenString": "0.00000005",
"marketCapUSD": 100000,
"volume1hUSD": 5000,
"volume24hUSD": 25000,
"trades1h": 150,
"trades24h": 800,
"holdersCount": 250,
"liquidityUSD": 15000,
"bonded": false,
"bondingPercentage": 45.5,
"createdAt": "2025-01-23T10:30:00.000Z",
"socials": {
"twitter": "https://twitter.com/newtoken",
"website": "https://newtoken.com",
"telegram": null,
"others": null
},
...
}
}
}
Remove Token/Market Message
When a token exits a view:
{
"type": "remove-token",
"payload": {
"viewName": "trending",
"token": {
"chainId": "solana:solana",
"address": "DPQxrrxJfTrLEjyknrUBcMDsAMYbAQJMnKTuJh4kbonk"
}
}
}
Improved Format: Token Filters uses a structured object { chainId, address } instead of the V2 pipe-separated format chainId|address.
OHLCV Update Message
When OHLCV mode is enabled, candle updates are sent on each swap:
{
"type": "update-token-ohlcv",
"payload": {
"viewName": "surge-view",
"token": {
"chainId": "solana:solana",
"address": "DPQxrrxJfTrLEjyknrUBcMDsAMYbAQJMnKTuJh4kbonk"
},
"candle": {
"o": 0.001,
"h": 0.0013,
"l": 0.0009,
"c": 0.0012,
"v": 6500,
"t": 1709300000000
}
}
}
OHLCV Mode
Enable OHLCV mode to receive historical candlestick data on init and real-time candle updates on each swap.
View Definition with OHLCV
Add ohlcv: true and optionally ohlcvTimeframe to a view definition:
{
"mode": "token",
"views": {
"surge-candles": {
"model": "surge",
"ohlcv": true,
"ohlcvTimeframe": "5m"
}
}
}
Parameters
| Parameter | Type | Default | Description |
|---|
ohlcv | boolean | false | Enable OHLCV candlestick data |
ohlcvTimeframe | string | "5m" | Candle timeframe. Allowed: 1s, 5s, 15s, 1m, 5m, 15m, 30m, 1h, 4h, 1d |
Constraints
- When
ohlcv: true, the view limit is clamped to 15 (max 15 tokens per view)
- Each token receives up to 200 historical candles on init when history is available
- Real-time candle updates are sent via
update-token-ohlcv messages
Init Response with OHLCV
When OHLCV is enabled, each token in the response includes an ohlcv array:
{
"subscriptionId": "sub_abc123",
"views": {
"surge-candles": {
"data": [
{
"address": "DPQxrrxJfTrLEjyknrUBcMDsAMYbAQJMnKTuJh4kbonk",
"chainId": "solana:solana",
"priceUSD": 0.001,
"ohlcv": [
{ "o": 0.001, "h": 0.0012, "l": 0.0009, "c": 0.0011, "v": 5000, "t": 1709300000000 },
{ "o": 0.0011, "h": 0.0015, "l": 0.001, "c": 0.0013, "v": 3200, "t": 1709300300000 }
]
}
]
}
}
}
Candle Fields
| Field | Description |
|---|
o | Open price |
h | High price |
l | Low price |
c | Close price |
v | Volume (USD) |
t | Candle timestamp (ms, aligned to timeframe) |
Token Data Model (mode: “token”)
The token mode returns data following the TokenDetailsOutput schema:
interface TokenDetailsOutput {
// Identification
address: string;
chainId: string;
symbol: string | null;
name: string | null;
decimals: number;
id: number | null;
// Pricing
priceUSD: number;
priceToken: number;
priceTokenString: string;
// Market Data
marketCapUSD: number;
marketCapDilutedUSD: number;
totalSupply: number;
circulatingSupply: number;
approximateReserveUSD: number;
approximateReserveToken: number;
approximateReserveTokenRaw: string;
// Liquidity
liquidityUSD: number;
liquidityMaxUSD: number;
// Bonding
bonded: boolean;
bondingPercentage: number;
bondingCurveAddress: string | null;
preBondingFactory: string;
bondedAt: Date | null;
// Price Changes
priceChange1minPercentage: number;
priceChange5minPercentage: number;
priceChange1hPercentage: number;
priceChange4hPercentage: number;
priceChange6hPercentage: number;
priceChange12hPercentage: number;
priceChange24hPercentage: number;
// Volume (USD)
volume1minUSD: number;
volume5minUSD: number;
volume15minUSD: number;
volume1hUSD: number;
volume4hUSD: number;
volume6hUSD: number;
volume12hUSD: number;
volume24hUSD: number;
// Volume Buy/Sell
volumeBuy1minUSD: number;
volumeBuy1hUSD: number;
volumeBuy24hUSD: number;
volumeSell1minUSD: number;
volumeSell1hUSD: number;
volumeSell24hUSD: number;
// ... all timeframes
// Trades
trades1min: number;
trades5min: number;
trades1h: number;
trades24h: number;
// ... all timeframes
// Buys/Sells
buys1min: number;
buys1h: number;
buys24h: number;
sells1min: number;
sells1h: number;
sells24h: number;
// ... all timeframes
// Unique Participants
buyers1h: number;
buyers24h: number;
sellers1h: number;
sellers24h: number;
traders1h: number;
traders24h: number;
// ... all timeframes
// Organic Metrics (excluding bot activity)
organicTrades1h: number;
organicVolume1hUSD: number;
organicBuyers1h: number;
// ... all organic fields
// Trending Scores
trendingScore1min: number;
trendingScore5min: number;
trendingScore15min: number;
trendingScore1h: number;
trendingScore4h: number;
trendingScore6h: number;
trendingScore12h: number;
trendingScore24h: number;
// Holdings Analysis
holdersCount: number;
top10HoldingsPercentage: number;
top50HoldingsPercentage: number;
top100HoldingsPercentage: number;
top200HoldingsPercentage: number;
devHoldingsPercentage: number;
insidersHoldingsPercentage: number;
bundlersHoldingsPercentage: number;
snipersHoldingsPercentage: number;
proTradersHoldingsPercentage: number;
freshTradersHoldingsPercentage: number;
smartTradersHoldingsPercentage: number;
// Trader Categories
insidersCount: number;
bundlersCount: number;
snipersCount: number;
freshTradersCount: number;
proTradersCount: number;
smartTradersCount: number;
smartTradersBuys: number;
freshTradersBuys: number;
proTradersBuys: number;
// Fees
feesPaid1hUSD: number;
feesPaid24hUSD: number;
totalFeesPaidUSD: number;
totalFeesPaidNativeRaw: string;
// ... all timeframes
// ATH/ATL
athUSD: number;
atlUSD: number;
athDate: Date;
atlDate: Date;
// Metadata
logo: string | null;
originLogoUrl: string | null;
description: string | null;
deployer: string | null;
deployerMigrationsCount: number;
deployerTokensCount: number;
rank: number | null;
cexs: string[];
// Social
socials: {
twitter: string | null;
website: string | null;
telegram: string | null;
others: Record<string, unknown> | undefined;
uri: string | undefined;
};
// Security
security: SecurityFlags | null;
// Twitter Analysis
twitterReusesCount: number;
twitterRenameCount: number;
twitterRenameHistory: Array<{
username: string;
lastChecked: string;
}>;
// DexScreener
dexscreenerListed: boolean;
dexscreenerHeader: string | null;
dexscreenerAdPaid: boolean;
dexscreenerAdPaidDate: Date | null;
dexscreenerSocialPaid: boolean;
dexscreenerSocialPaidDate: Date | null;
dexscreenerBoosted: boolean;
dexscreenerBoostedDate: Date | null;
dexscreenerBoostedAmount: number;
// Livestream
liveStatus: string | null;
liveThumbnail: string | null;
livestreamTitle: string | null;
liveReplyCount: number | null;
// Exchange & Factory
exchange: { name: string; logo: string } | undefined;
factory: string | null;
source: string | null;
sourceFactory: string | null;
poolAddress: string;
blockchain: string;
tokenType: string;
// Timestamps
createdAt: Date | null;
latestTradeDate: Date | null;
// Internationalization
i18n: Record<string, unknown> | null;
}
Market Data Model (mode: “market”)
The market mode returns data following the MarketDetailsOutput schema with pair information:
interface MarketDetailsOutput {
// Pool Information
address: string;
blockchain: string;
type: string;
factory: string | null;
createdAt: Date | null;
latestTradeDate: Date | null;
// Pair Tokens
base: TokenData;
quote: TokenData;
baseToken: "token0" | "token1";
quoteToken: "token0" | "token1";
// Pricing
priceUSD: number;
priceToken: number;
priceTokenString: string;
liquidityUSD: number;
// Bonding
bonded: boolean;
bondingPercentage: number;
preBondingPoolAddress: string | null;
sourceFactory: string | null;
// Price Changes
priceChange1minPercentage: number;
priceChange5minPercentage: number;
priceChange1hPercentage: number;
// ... all timeframes
// Volume, Trades, Participants
// Same structure as TokenDetailsOutput
// Holdings, Security, Socials
// Inherited from base token
// Exchange
exchange: { name: string; logo: string };
}
View Configuration
View Parameters
| Parameter | Type | Required | Description |
|---|
| view key | string | Yes | Unique identifier for the view, e.g. "new-tokens" in views |
model | string | No | Preset model: new, bonding, bonded, trending, explorer, topGainers, surge |
sortBy | string | No | Field to sort by (camelCase) |
sortOrder | ”asc” | “desc” | No | Sort direction |
limit | number | No | Max results (default: 50, max: 100) |
offset | number | No | Pagination offset |
filters | object | No | Filter configuration |
selectors | array | No | Explicit token or market selectors: { "chainId": "...", "address": "..." } |
ohlcv | boolean | No | Include OHLCV history and live candle updates for token views |
ohlcvTimeframe | string | No | OHLCV timeframe when ohlcv is true |
Use filters.chainId for chains and filters.source for token launchpads/factories. In market mode, use filters.pool.type or filters.type for pool type filtering.
Filter Operators
| Operator | Description | Example |
|---|
equals | Exact match | { "bonded": { "equals": true } } |
gte | Greater than or equal | { "marketCapUSD": { "gte": 10000 } } |
lte | Less than or equal | { "volume1hUSD": { "lte": 100000 } } |
gt | Greater than | { "holdersCount": { "gt": 100 } } |
lt | Less than | { "bondingPercentage": { "lt": 100 } } |
not | Not equal | { "source": { "not": null } } |
in | In array | { "chainId": { "in": ["solana:solana"] } } |
contains | String contains | { "symbol": { "contains": "DOGE" } } |
startsWith | String prefix | { "chainId": { "startsWith": "ton" } } |
endsWith | String suffix | { "symbol": { "endsWith": "INU" } } |
Custom Views Example
{
"mode": "token",
"views": {
"high-volume-pumpfun": {
"sortBy": "volume1hUSD",
"sortOrder": "desc",
"limit": 50,
"filters": {
"chainId": { "in": ["solana:solana"] },
"source": { "in": ["pumpfun"] },
"volume1hUSD": { "gte": 5000 },
"marketCapUSD": { "gte": 10000 },
"bonded": { "equals": false }
}
},
"whale-accumulation": {
"sortBy": "volumeBuy1hUSD",
"sortOrder": "desc",
"limit": 30,
"filters": {
"chainId": { "in": ["solana:solana", "evm:8453"] },
"volumeBuy1hUSD": { "gte": 10000 },
"top10HoldingsPercentage": { "lte": 30 },
"holdersCount": { "gte": 100 }
}
},
"safe-tokens": {
"sortBy": "trendingScore1h",
"sortOrder": "desc",
"limit": 25,
"filters": {
"chainId": { "in": ["solana:solana"] },
"security": {
"noMintAuthority": { "equals": true },
"isBlacklisted": { "equals": false }
},
"devHoldingsPercentage": { "lte": 5 }
}
}
}
}
View Management
Pause Views
Temporarily stop receiving updates for specific views:
{
"type": "token-filters-pause",
"payload": {
"action": "pause",
"views": ["high-volume-pumpfun", "whale-accumulation"]
}
}
Unpause Views
Resume updates:
{
"type": "token-filters-pause",
"payload": {
"action": "unpause",
"views": ["high-volume-pumpfun"]
}
}
Unsubscribe
Unsubscribe from All
{
"type": "unsubscribe",
"authorization": "YOUR_API_KEY",
"payload": {
"type": "token-filters"
}
}
Unsubscribe from Specific View
{
"type": "unsubscribe",
"authorization": "YOUR_API_KEY",
"payload": {
"type": "token-filters",
"viewName": "high-volume-pumpfun"
}
}
Unsubscribe by Subscription ID
{
"type": "unsubscribe",
"authorization": "YOUR_API_KEY",
"payload": {
"type": "token-filters",
"subscriptionId": "sub_abc123xyz"
}
}
Connection Keepalive
Send periodic ping messages to maintain the connection:
The server responds with a pong message.
Send ping messages every 30-60 seconds for long-lived connections.
Complete TypeScript Example
import WebSocket from 'ws';
interface TokenFiltersConfig {
apiKey: string;
mode: 'token' | 'market';
views: Record<string, ViewConfig>;
delta?: boolean;
maxUpdatesPerMinute?: number;
}
interface ViewConfig {
model?: 'new' | 'bonding' | 'bonded' | 'trending' | 'explorer' | 'topGainers' | 'surge';
sortBy?: string;
sortOrder?: 'asc' | 'desc';
limit?: number;
offset?: number;
filters?: Record<string, unknown>;
ohlcv?: boolean;
ohlcvTimeframe?: string;
}
class TokenFiltersClient {
private ws: WebSocket | null = null;
private state: Map<string, Map<string, unknown>> = new Map();
constructor(private config: TokenFiltersConfig) {}
async initialize(): Promise<void> {
// Initialize view state maps
for (const viewName of Object.keys(this.config.views)) {
this.state.set(viewName, new Map());
}
// Connect to WebSocket directly
await this.connect();
}
private async connect(): Promise<void> {
this.ws = new WebSocket('wss://api.mobula.io');
this.ws.on('open', () => {
// Send FULL payload with mode and views (not just subscriptionId)
this.ws!.send(JSON.stringify({
type: 'token-filters',
authorization: this.config.apiKey,
payload: {
mode: this.config.mode,
delta: this.config.delta ?? true,
maxUpdatesPerMinute: this.config.maxUpdatesPerMinute,
views: this.config.views
}
}));
});
this.ws.on('message', (data) => {
const message = JSON.parse(data.toString());
this.handleMessage(message);
});
// Keepalive
setInterval(() => {
if (this.ws?.readyState === WebSocket.OPEN) {
this.ws.send(JSON.stringify({ event: 'ping' }));
}
}, 30000);
}
private handleMessage(message: {
type: string;
payload: {
viewName: string;
token: { address: string; chainId: string; [key: string]: unknown };
};
}): void {
const { type, payload } = message;
switch (type) {
case 'new-token':
case 'new-market': {
const viewState = this.state.get(payload.viewName);
if (viewState) {
const key = `${payload.token.chainId}|${payload.token.address}`;
viewState.set(key, payload.token);
console.log(`[NEW] ${payload.viewName}: ${payload.token.symbol}`);
}
break;
}
case 'update-token':
case 'update-market': {
const viewState = this.state.get(payload.viewName);
if (viewState) {
const key = `${payload.token.chainId}|${payload.token.address}`;
const existing = viewState.get(key) as Record<string, unknown> | undefined;
if (existing) {
// Apply partial update
const updated = { ...existing, ...payload.token };
viewState.set(key, updated);
console.log(`[UPDATE] ${payload.viewName}: ${(existing as { symbol?: string }).symbol}`);
}
}
break;
}
case 'remove-token':
case 'remove-market': {
const viewState = this.state.get(payload.viewName);
if (viewState) {
const key = `${payload.token.chainId}|${payload.token.address}`;
viewState.delete(key);
console.log(`[REMOVE] ${payload.viewName}: ${payload.token.address}`);
}
break;
}
}
}
getViewData(viewName: string): unknown[] {
const viewState = this.state.get(viewName);
return viewState ? Array.from(viewState.values()) : [];
}
}
// Usage
const client = new TokenFiltersClient({
apiKey: 'YOUR_API_KEY',
mode: 'token',
views: {
trending: {
sortBy: 'feesPaid15minUSD',
sortOrder: 'desc',
limit: 50,
filters: {
chainId: { in: ['solana:solana'] },
source: { in: ['pumpfun'] }
}
}
}
});
await client.initialize();
View Limits
- Maximum 10 views per connection
- Maximum 100 items per view
- Maximum 1000 total items across all views
Bandwidth Optimization
- Partial updates significantly reduce bandwidth
- Use
pause for inactive views
- Filter aggressively to reduce data volume
- Use appropriate
limit values
Best Practices
- Initialize via REST API to get initial state
- Apply partial updates to local state
- Use ping/pong for connection health
- Implement reconnection logic
- Handle all message types gracefully
Support
Need help? Our response times are < 1h.