Skip to main content
Mobula’s GraphQL API is Codex-compatible: the onLaunchpadTokenEvent and onLaunchpadTokenEventBatch subscriptions accept the same operations a Codex client already sends, which makes it the fastest first step off Codex. The native Pulse V2 stream is the recommended production target: instead of a flat event firehose you subscribe to views (new / bonding / bonded, or fully custom), each maintained server-side with sorting, limits, and a Prisma-style filter tree over 100+ token statistics. This guide maps the launchpad subscription to Pulse V2, concept by concept.
Already on the GraphQL layer? Both APIs run on the same indexing pipeline, so you can migrate view by view and compare outputs side by side with the same API key.

Endpoint mapping

Pulse V2 over WebSocket requires a Growth or Enterprise plan.

The mental model shift

The launchpad subscription is event-based: every push is one lifecycle event (Deployed, Updated, Completed, Migrated, …) for one token, and your client assembles the current state. Pulse V2 is view-based: the server maintains the state — each view is a sorted, filtered, limited set of tokens — and streams membership changes: So the three lifecycle stages you modeled with eventType filters become three concurrent views on one WebSocket connection. The default model creates them for you:
This yields the views new (not yet bonded, sorted by created_at), bonding (bonding_percentage < 100, sorted by graduation progress), and bonded (bonded: true, sorted by bonded_at).

Step 1 — Translate network IDs

The GraphQL layer uses Codex-style numeric networkId; Pulse uses string chain IDs.
  • EVM chains map directly: numeric networkId Nevm:N (e.g. 8453evm:8453). getNetworks lists them.
  • Non-EVM chains use fixed string IDs: solana:solana, sui:sui, starknet:starknet. They are covered by getNetworkConfigs.
  • Token identity changes from Codex’s address:networkId to Mobula’s chainId|address (this is the tokenKey format in remove-token messages).

Step 2 — Translate protocols to pool types

protocol / protocols enum values map to Pulse poolTypes / factory ids. The authoritative list lives at GET https://api.mobula.io/api/1/system-metadata (data.factories[].name); the common ones: See LaunchpadTokenProtocol for the full factory-id table.

Step 3 — Translate the subscription into views

Before — one subscription per protocol and event type:
After — a custom view (or use the default model above):
Anything you expressed with the subscription input’s filters / rankings carries over to the view’s filters / sortBy — Pulse filters support the full AND / OR / NOT tree with equals, not, gte, gt, lte, lt, in, notIn, contains, startsWith, endsWith. See the Filter Details reference.

Step 4 — Translate fields

Pulse filters use snake_case (market_cap, holders_count); the response token object uses camelCase (token.holdersCount, token.top10HoldingsPercentage).
Pulse additionally exposes fields the launchpad stream never had — organic (bot-excluded) volume/trade series, fresh/pro/smart trader counts, ATH/ATL, security data — see the Token Data Model.

Step 5 — Handle the message loop

Replace your graphql-transport-ws next-message handler with five message types:
  1. init — full snapshot per view. Replaces your initial filterTokens backfill query; render it as-is.
  2. new-token — a token entered a view (deploy in new, graduation in bonded, …).
  3. update-token — stats changed for a token already in a view.
  4. remove-token — token left a view; delete by tokenKey (chainId|tokenAddress).
  5. sync — the server resets the view. You must discard local view state and replace it with the sync payload — do not merge.
Operational bits:
  • Keepalive: send {"event":"ping"} every 30–60 s.
  • Pause instead of resubscribe: {"type": "pulse-pause", "payload": {"action": "pause", "views": ["pump-new"]}} (and "unpause") — no reconnect, no snapshot replay.
  • Compression: compressed: true enables gzip payloads.

Step 6 — Validate the migration

  • Run both streams side by side for a few days before cutting over; compare token membership per view, not raw event counts — an event-based and a view-based stream will never emit the same number of messages for the same reality.
  • When counts differ on trades/volume, compare on unique transaction hashes: providers count multi-leg swaps differently (see benchmarks).
  • Test with the launchpads you actually track — validate poolTypes values against /api/1/system-metadata rather than hardcoding.

Pulse Stream V2

Full WebSocket reference — views, filters, message formats.

Pulse WSS SDK Integration

Integrate with @mobula/sdk, with open-source examples from MTT.

onLaunchpadTokenEvent

The GraphQL subscription this guide migrates from.

Build an Axiom-style Pulse

End-to-end cookbook for a token discovery feed.