madeonsol 2.25.0 → 2.26.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -12,6 +12,10 @@
12
12
  Official TypeScript/JavaScript SDK for the **[MadeOnSol](https://madeonsol.com) Solana API** — zero dependencies, fully typed, works in Node.js ≥ 18 and edge runtimes.
13
13
  > Real-time Solana trading intelligence: track 1,069 KOL wallets with <3s latency, score 23,000+ Pump.fun deployers, surface deshred deploy signals **~500ms before on-chain confirmation**, detect multi-KOL coordination, score token rug-risk 0–100 with a transparent factor breakdown, expose the bundle cohort that bought a token together and how much of supply it still holds, verify any wallet's current on-chain holdings with airdrop/insider `transfer_delta` detection, push every pump.fun graduation the second it bonds, and stream every DEX trade across 9+ programs. Free tier: 200 requests/day, every endpoint — no signup payment. Get a key at [madeonsol.com/pricing](https://madeonsol.com/pricing).
14
14
 
15
+ > **New in 2.26.0 — token surges & revivals: momentum fires with the honest half attached — one endpoint + one live channel.** `client.token.surges(params?)` (typed `TokenSurgesResponse`) binds `GET /tokens/surges`: **`surge`** = a token < 30 min old whose MC runs hard vs its *launch* MC (tier `early` ≤ 10 min / ≥ $12k / ≥ 3×, `strong` ≤ 30 min / ≥ $30k / ≥ 6× and still climbing, `breakout` ≤ 2 min / ≥ $45k / ≥ 8× — each fires once per mint, and only when SUSTAINED across ≥ 10 s, never on a one-tick mark); **`revival`** = a token with no trade candle for ≥ 24 h that started trading again, confirmed by real buys + buy volume on the tape, never by the price move alone. Hard gates on both: liquidity ≥ $1.5k and ≥ 2 % of MC, and the MC gained must be *paid for* (buy volume ≥ 3 % of the move — a spoof-pool mark moves MC on ~$0). Every row carries `tape` (buys / sells / volume, `unique_buyers` only where wallet data exists — `wallet_data_available: false` otherwise, never inferred), `kol`, `early_buyers` (bundled / sold / sniper wallets), `deployer` reputation and **`risk_flags[]`** (`bundled_launch`, `few_buyers`, `wash_pattern`, `thin_liquidity`, `cold_deployer`, `sniper_heavy`, `early_buyers_exiting`, `sell_pressure`, `no_tape_trades`, `no_prior_price`, `mint_authority_active`, `transfer_fee`); rows ≥ 65 min old carry the +1 h `outcome` (`mc_1h_multiple`, `peak_1h_multiple`, `priced_after_1h`) and `stats: true` returns per-(kind, tier) hit-rates — out-of-sample by construction. Filters `kind`, `tier`, `mint`, `launchpad`, `deployer_tier`, `min_mc_usd` / `max_mc_usd`, `min_buys`, `exclude_flags`, `only_clean`; cursors `since` / `before`. Pushed live on the new **`token:surges`** WS channel (events `token:surge` / `token:revival`, typed `TokenSurgeStreamEvent`, server-side filters `TokenSurgesSubscribeFilters`: `kinds[]`, `tiers[]`, `launchpads[]`, `exclude_flags[]`, `min_mc_usd` / `max_mc_usd`, `deployer_tier[]`). Nearly every scalar is `| null` — null means unknown, never zero. **PRO+** (BASIC receives HTTP 403) on the keyed `msk_` API.
16
+
17
+ > **New in 2.25.1 — stream tokens never expire.** `client.stream.getToken()` (`POST /stream/token`) now returns the **same token on every call, forever**. It stops working only if your subscription lapses or you call `client.stream.getToken({ rotate: true })` to replace it (the previous value keeps working for 60 s). `StreamToken.expires_at` and `next_refresh_at` are always `null` (kept for wire compatibility — do not schedule refreshes on them); the response gains `rotated: boolean` and `lifetime: string`. The server never rotates on its own and never sends `token_refresh` unless you rotated; a `4001` close means "mint again" (lapsed or rotated), never a timer. Prefer `Authorization: Bearer <token>` on the WebSocket handshake — `?token=` still works and is masked in access logs. `client.stream.connect()` already does the right thing (it calls `getToken()` on every (re)connect); no code change needed on your side.
18
+
15
19
  > **New in 2.25.0 — token locks & vesting, upcoming unlocks, and pump.fun creator-fee sharing / fee claims — five endpoints + two live channels.** `client.token.locks(mint, params?)` (typed `TokenLocksResponse`) binds `GET /tokens/{mint}/locks`: every on-chain Streamflow / Jupiter Lock / Bonfida lock or vesting contract on a mint, decoded from the locker programs' account state, with a LIVE-derived view (`locked_raw` still locked, `unlocked`, `withdrawn`, `claimable`, `status`, `next_unlock`) and a `summary` (locked / deposited totals, the 7d / 30d forward unlock schedule, `active_cancelable_by_sender` — a lock the sender can cancel is a weaker promise). `client.token.locksFeed(params?)` (`GET /tokens/locks`) is the cross-token feed of NEW contracts, cursor-paginated (`pagination.next_since` / `next_before`) and pushed live on the new **`token:locks`** WS channel (event `token:lock`, typed `TokenLockStreamEvent`). `client.token.unlocks(params?)` (`GET /tokens/unlocks`) lists upcoming unlock EVENTS (cliff / period / final / tranche) inside `within=1h…90d` with `window_amount_*` per contract. `client.token.feeShares(mint)` (`GET /tokens/{mint}/fee-shares`) decodes a pump.fun coin's on-chain `SharingConfig` — who its creator fees are redirected to (`share_bps`, `is_admin`, `is_social_pda` for fees earmarked for an X account etc., `redirected_bps`, `social_bps`, `is_default` = 100% to the creator) plus the distribution rollup per recipient and the config change log; `client.token.feeClaims(params?)` (`GET /tokens/fee-claims`) is the fee-event feed (`distribution` with per-address `payouts[]`, `social_claim`, `shares_created` / `updated` / `reset`, `creator_transferred`, `creator_claim` on request), pushed live on the new **`token:fee_claims`** channel (event `token:fee_claim`, typed `TokenFeeClaimStreamEvent`). Honest limits: base-unit amounts are **strings** and ui / usd / pct are `null` when decimals or price are unknown; **LP locks are NOT included** (token / vesting locks only); **fee-event history starts 2026-08-17**; all five are **PRO+** (BASIC receives HTTP 403) on the keyed `msk_` API.
16
20
 
17
21
  > **New in 2.24.0 — live holder census: exact holder count, labelled holders, and pools that are named, not just excluded.** `client.alpha.holders(mint)` (typed `TokenHoldersResponse`) binds `GET /tokens/{mint}/holders` (PRO+): every token account of the mint read from the ledger at `confirmed` and merged per owner, so `concentration.holder_count` is EXACT (distinct non-zero owners minus pools / bonding curves / burns) — never a trade-derived estimate; it is `null` only when the provider refuses the census for a mega-cap, in which case you get the top-20 view and `source.census_fallback_reason` says so. Each disclosed owner carries our labels (`deployer` / `kol` / `early_buyer` / `bundle` / `bot` / `dump_cluster` — empty means unknown to us, not clean), and `excluded[]` NAMES what was taken out of the circulating denominator: `reason` = `pool` (with `dex` + `pool_address`), `bonding_curve` (pump.fun / LaunchLab), `burn`, or `program_account` only when we genuinely cannot attribute the PDA; `pool_pct` / `burned_pct` / `program_pct` split the exclusion. Amounts are raw u64 **strings**. Disclosure: PRO ranks 1–10, ULTRA 1–50, BUSINESS 1–100 — the maths is tier-independent. Big tokens take 5–30 s upstream: you get `503 holder_scan_in_progress` with `retry_after_seconds: 20` while the scan finishes into the cache, and the retry is instant.
@@ -1179,6 +1183,36 @@ Returns: `TokenFeeClaimsResponse` (`TokenFeeClaimEvent`, `TokenFeePayout`, `Toke
1179
1183
 
1180
1184
  ---
1181
1185
 
1186
+ #### `client.token.surges(params?)` *(new in 2.26 — PRO+)*
1187
+
1188
+ Token **momentum fires**, newest first (`GET /tokens/surges`). Two kinds. **`surge`** — a token < 30 min old whose market cap runs hard vs its *launch* MC: tier `early` (≤ 10 min, ≥ $12k, ≥ 3× launch MC), `strong` (≤ 30 min, ≥ $30k, ≥ 6× launch **and** ≥ 2× the lowest sample of the last 3 min — it is climbing *now*), `breakout` (≤ 2 min, ≥ $45k, ≥ 8×). Each tier fires at most once per mint; tiers are independent (a token can go straight to breakout). A tier must be **sustained** — floor + multiple hold on the current tick *and* on a sample ≥ 10 s older, and nothing fires before 20 s of age: a one-tick mark (same-slot bundle, routed dust) is a spike, not a surge. When the engine first saw the token late (`baseline_source: "late"`) the launch multiple is not applied — USD floor + velocity only. **`revival`** — a token with **no 1-minute trade candle for ≥ 24 h** that starts trading again, confirmed **only by the tape** (≥ 5 buys, ≥ $500 buy volume, MC ≥ 1.5× the pre-dormancy close — or ≥ 20 buys / ≥ $5k regardless), never by the price mark: a single dust buy into an empty pool marks MC up 300 % and is not a revival. One fire per dormancy episode (24 h re-fire guard). **Hard gates on both kinds** (not flags): liquidity ≥ $1.5k *and* ≥ 2 % of MC when known, MC ≤ $100B, and the MC gained must be **paid for** — buy volume on the tape ≥ 3 % × (MC − launch / pre-dormancy MC); a price mark in a spoof pool moves MC on ~$0 of volume. **PRO+** — BASIC receives HTTP 403.
1189
+
1190
+ Every row carries `tape` (buys / sells / volume since birth or revival; `tape.source` = `candles` or `wallet_trades`, `tape.available: false` with nulls while no tape covers the window yet; `unique_buyers` / `trades_per_wallet` only when the mint is in `token_trades` coverage — `wallet_data_available: false` otherwise, **never inferred zero**), `kol` (tracked-KOL buyers + names), `early_buyers` (first-20 cohort: bundled, cohort SOL, sold, sniper wallets), `deployer` (tier, bonding / runner rate, labeled tokens) and **`risk_flags[]`** — the honest half (thresholds echoed in `definitions.risk_flags`). Rows ≥ 65 min old carry `outcome` (`mc_usd_1h_after`, `peak_mc_usd_1h_after`, `low_mc_usd_1h_after`, `mc_1h_multiple`, `peak_1h_multiple`, `priced_after_1h` — `false` = no candle in the hour, not zero); `stats: true` adds per-(kind, tier) hit-rates over `days` (`up_1h_pct`, `median_peak_multiple`, `doubled_1h_pct`) — out-of-sample by construction, the fire is recorded before the outcome exists. The live thresholds are echoed in `definitions` (read from the engine, so they cannot drift from what fires). Poll with `since = pagination.next_since`, or subscribe to the **`token:surges`** WS channel (events `token:surge` / `token:revival` — the same object minus `outcome`).
1191
+
1192
+ - Nearly every scalar is `| null` — null means unknown, never zero. `tier` is null on revivals; `dormant_hours` / `prev_mc_usd` / `mc_vs_prev_multiple` are null on surges; `baseline_*` / `mc_multiple` / `mc_change_3m_pct` are null on revivals.
1193
+ - `launchpad` is the venue at *birth*, `primary_dex` where it trades at fire time — a pump token that graduated inside its first 10 min is `pumpfun` / `pumpswap`.
1194
+ - `tier` with `kind: "revival"` is a 400; an unknown flag in `exclude_flags` is a 400 with `known_flags[]`.
1195
+
1196
+ ```ts
1197
+ const { events, stats } = await client.token.surges({ kind: "surge", tier: "strong", exclude_flags: ["bundled_launch", "sniper_heavy"], stats: true });
1198
+ for (const e of events) {
1199
+ console.log(e.symbol, `$${e.market_cap_usd}`, `${e.mc_multiple}× launch`, e.tape.buys, "buys /", e.tape.unique_buyers ?? "n/a", "buyers", e.risk_flags, e.outcome ? `${e.outcome.peak_1h_multiple}× peak in 1h` : "outcome pending");
1200
+ }
1201
+ for (const r of stats?.rows ?? []) console.log(r.kind, r.tier, `${r.up_1h_pct}% up after 1h`, "median peak", r.median_peak_multiple, `(${r.with_outcome} fires)`);
1202
+
1203
+ // live
1204
+ const stream = await client.stream.connect();
1205
+ stream.subscribe(["token:surges"], { kinds: ["surge"], tiers: ["strong", "breakout"], exclude_flags: ["bundled_launch"], min_mc_usd: 30_000 } satisfies TokenSurgesSubscribeFilters);
1206
+ stream.on("token:surge", (d) => { const e = d as TokenSurgeStreamEvent; console.log(e.tier, e.symbol, e.market_cap_usd, e.risk_flags); });
1207
+ stream.on("token:revival", (d) => { const e = d as TokenSurgeStreamEvent; console.log("revived after", e.dormant_hours, "h", e.symbol, e.mc_vs_prev_multiple); });
1208
+ ```
1209
+
1210
+ Params: `kind` (surge | revival), `tier` (early | strong | breakout — surge only), `mint`, `since` / `before` (ISO date-time cursors), `min_mc_usd` / `max_mc_usd`, `min_buys`, `launchpad`, `deployer_tier` (elite | good | moderate | rising | cold | unranked), `exclude_flags` (array or comma list), `only_clean` (boolean), `stats` (boolean), `days` (1–30, default 7), `limit` (1–200, default 50).
1211
+
1212
+ Returns: `TokenSurgesResponse` (`TokenSurgeEvent`, `TokenSurgeStreamEvent`, `TokenSurgeTape`, `TokenSurgeKol`, `TokenSurgeEarlyBuyers`, `TokenSurgeDeployer`, `TokenSurgeOutcome`, `TokenSurgeStats`, `TokenSurgeStatsRow`, `TokenSurgesFilters`, `TokenSurgeDefinitions`, `TokenSurgeKind`, `TokenSurgeTier`, `TokenSurgeRiskFlag`, `TokenSurgeDeployerTier`, `TokenSurgesSubscribeFilters`, `TokenFeedPagination`, `TokenFeedStreamPointer`)
1213
+
1214
+ ---
1215
+
1182
1216
  ### Account — `client.me()` *(new in 2.6)*
1183
1217
 
1184
1218
  Inspect your tier, quota state, and feature usage in one call. Reads from the same in-memory counters that drive rate-limit enforcement, so `quota.daily.remaining` is authoritative — no header parsing needed. Works on every tier (BASIC/PRO/ULTRA).
@@ -1235,19 +1269,23 @@ Returns: `ToolsSearchResponse`
1235
1269
 
1236
1270
  #### `client.stream.getToken()`
1237
1271
 
1238
- Generate a 24-hour WebSocket streaming token. Pro/Ultra subscribers get `ws_url` for KOL/deployer event streaming. Ultra subscribers also get `dex_ws_url` for the all-DEX trade stream.
1272
+ Issue your WebSocket streaming token. Pro/Ultra subscribers get `ws_url` for KOL/deployer event streaming. Ultra subscribers also get `dex_ws_url` for the all-DEX trade stream.
1273
+
1274
+ Stream tokens **never expire** (since 2.25.1): the same token comes back on every call until your subscription lapses or you pass `{ rotate: true }` to replace it (the previous value keeps working for 60 s). Send it as `Authorization: Bearer <token>` on the WebSocket handshake (`?token=` still works). A `4001` close means "mint again", never a timer.
1239
1275
 
1240
1276
  ```ts
1241
1277
  const token = await client.stream.getToken();
1242
1278
  console.log(token.ws_url); // wss://madeonsol.com/ws/v1/stream
1243
1279
  console.log(token.dex_ws_url); // wss://madeonsol.com/ws/v1/dex-stream (Ultra only)
1280
+ console.log(token.expires_at); // null — never expires
1281
+ const fresh = await client.stream.getToken({ rotate: true }); // replace it
1244
1282
  ```
1245
1283
 
1246
- Returns: `StreamToken` — `{ token, expires_at, ws_url, dex_ws_url?, usage }`
1284
+ Returns: `StreamToken` — `{ token, expires_at: null, next_refresh_at: null, rotated, lifetime, ws_url, dex_ws_url?, usage }`
1247
1285
 
1248
1286
  #### `client.stream.connect()` *(new in 2.10)*
1249
1287
 
1250
- Open a **managed** stream — token fetch + 24h refresh, auto-reconnect (backoff + jitter), heartbeat liveness, and typed events are handled for you. No need to touch `getToken()` or `ws` directly.
1288
+ Open a **managed** stream — token fetch (the token never expires; `getToken()` is called on every (re)connect), auto-reconnect (backoff + jitter), heartbeat liveness, and typed events are handled for you. No need to touch `getToken()` or `ws` directly.
1251
1289
 
1252
1290
  ```ts
1253
1291
  const stream = client.stream.connect();
@@ -1257,7 +1295,7 @@ stream.subscribe(["kol:trades", "deployer:alerts"]);
1257
1295
  // stream.unsubscribe([...]) / stream.close() when done
1258
1296
  ```
1259
1297
 
1260
- Channels: `kol:trades`, `kol:coordination`, `kol:first_touches`, `deployer:alerts`, `wallet_tracker:events`, `copytrade:signals`, `price_alert:events`, `sniper:deploys`, `token:graduations` (every pump.fun graduation in real time, tracked deployer or not — typed `GraduationEvent`), `token:locks` (**new 2.25** — event `token:lock` for every NEW Streamflow / Jupiter Lock / Bonfida lock or vesting contract, typed `TokenLockStreamEvent`; PRO+; updates are not pushed — poll `client.token.locks()`), `token:fee_claims` (**new 2.25** — event `token:fee_claim` for every pump.fun fee event: distributions, social-handle claims, config changes, typed `TokenFeeClaimStreamEvent`; PRO+). Lifecycle: `open`, `close`, `reconnect`, `heartbeat`, `error`. Node 22+ uses the global `WebSocket`; on Node < 22 also `npm i ws`.
1298
+ Channels: `kol:trades`, `kol:coordination`, `kol:first_touches`, `deployer:alerts`, `wallet_tracker:events`, `copytrade:signals`, `price_alert:events`, `sniper:deploys`, `token:graduations` (every pump.fun graduation in real time, tracked deployer or not — typed `GraduationEvent`), `token:locks` (**new 2.25** — event `token:lock` for every NEW Streamflow / Jupiter Lock / Bonfida lock or vesting contract, typed `TokenLockStreamEvent`; PRO+; updates are not pushed — poll `client.token.locks()`), `token:fee_claims` (**new 2.25** — event `token:fee_claim` for every pump.fun fee event: distributions, social-handle claims, config changes, typed `TokenFeeClaimStreamEvent`; PRO+), `token:surges` (**new 2.26** — events `token:surge` / `token:revival` the moment a momentum fire is confirmed, typed `TokenSurgeStreamEvent` with `tape` / `kol` / `early_buyers` / `deployer` / `risk_flags[]`; server-side filters `kinds[]`, `tiers[]`, `launchpads[]`, `exclude_flags[]`, `min_mc_usd` / `max_mc_usd`, `deployer_tier[]` — typed `TokenSurgesSubscribeFilters`; PRO+; the +1 h `outcome` is REST-only — poll `client.token.surges()`). Lifecycle: `open`, `close`, `reconnect`, `heartbeat`, `error`. Node 22+ uses the global `WebSocket`; on Node < 22 also `npm i ws`.
1261
1299
 
1262
1300
  #### `client.stream.sessions()` / `client.stream.deleteSession(id)` *(new in 2.17 — PRO+)*
1263
1301
 
package/dist/index.d.ts CHANGED
@@ -2193,6 +2193,301 @@ export interface TokenFeeClaimStreamEvent {
2193
2193
  social_fee_pda: string | null;
2194
2194
  shareholders: TokenFeeShareEntry[] | null;
2195
2195
  }
2196
+ /** `surge` = a token < 30 min old running hard vs its launch MC; `revival` = a token dormant ≥ 24 h that started trading again (confirmed by real buys, never by a price mark). */
2197
+ export type TokenSurgeKind = "surge" | "revival";
2198
+ /** Surge tiers — each fires at most once per mint; tiers are independent. Revivals have no tier (`null`). */
2199
+ export type TokenSurgeTier = "early" | "strong" | "breakout";
2200
+ /** How the token's birth was established: pre-confirm pump.fun deploy (deshred), confirmed on-chain create, or the first trade the firehose observed. */
2201
+ export type TokenSurgeBirthSource = "sniper" | "deployer" | "first_seen";
2202
+ /** `launch` = the first MC sample after birth (≤ 90 s); `late` = the engine first saw the token later (restart mid-life) — the launch multiple is then NOT applied. */
2203
+ export type TokenSurgeBaselineSource = "launch" | "late";
2204
+ /** What the burst tape was measured on: 1-minute candles (every DEX we price) or live `token_trades` rows (pump-pipeline mints). */
2205
+ export type TokenSurgeTapeSource = "candles" | "wallet_trades";
2206
+ /** Deployer reputation tier as carried on the fire (`unranked` = no score yet). */
2207
+ export type TokenSurgeDeployerTier = "elite" | "good" | "moderate" | "rising" | "cold" | "unranked";
2208
+ /** Risk flags a fire can carry — the honest half. Thresholds are echoed in `definitions.risk_flags`. */
2209
+ export type TokenSurgeRiskFlag = "bundled_launch" | "few_buyers" | "wash_pattern" | "thin_liquidity" | "cold_deployer" | "sniper_heavy" | "early_buyers_exiting" | "sell_pressure" | "no_tape_trades" | "no_prior_price" | "mint_authority_active" | "transfer_fee";
2210
+ /**
2211
+ * The burst tape — trades since birth (surge) or since the revival minute.
2212
+ * `available: false` = no tape covers the window yet (candle lag; every count is
2213
+ * null). `unique_buyers` / `unique_wallets` / `trades_per_wallet` are null when
2214
+ * the mint is outside `token_trades` coverage (`wallet_data_available: false`) —
2215
+ * never inferred.
2216
+ */
2217
+ export interface TokenSurgeTape {
2218
+ since: string | null;
2219
+ available: boolean;
2220
+ source: TokenSurgeTapeSource | null;
2221
+ buys: number | null;
2222
+ sells: number | null;
2223
+ trades: number | null;
2224
+ buy_volume_usd: number | null;
2225
+ sell_volume_usd: number | null;
2226
+ volume_usd: number | null;
2227
+ mev_volume_usd: number | null;
2228
+ buy_sol: number | null;
2229
+ sell_sol: number | null;
2230
+ unique_buyers: number | null;
2231
+ unique_wallets: number | null;
2232
+ trades_per_wallet: number | null;
2233
+ wallet_data_available: boolean;
2234
+ }
2235
+ /** Tracked-KOL involvement on the tape (max 10 `names`). */
2236
+ export interface TokenSurgeKol {
2237
+ buyers: number;
2238
+ buys: number;
2239
+ sells: number;
2240
+ names: string[];
2241
+ }
2242
+ /** The first-20 early-buyer cohort at fire time. */
2243
+ export interface TokenSurgeEarlyBuyers {
2244
+ count: number;
2245
+ /** Bought in the same block as ≥ 2 other early buyers. */
2246
+ bundled: number;
2247
+ cohort_sol: number | null;
2248
+ /** Cohort wallets that have already sold. */
2249
+ sold: number;
2250
+ /** Early buyers that are known sniper wallets. */
2251
+ sniper_wallets: number;
2252
+ }
2253
+ /** Deployer reputation as carried on the fire (`null` on the event when the deployer is unknown). */
2254
+ export interface TokenSurgeDeployer {
2255
+ wallet: string | null;
2256
+ tier: TokenSurgeDeployerTier;
2257
+ bonding_rate: number | null;
2258
+ total_bonded: number | null;
2259
+ total_deployed: number | null;
2260
+ runner_rate: number | null;
2261
+ labeled_tokens: number | null;
2262
+ /** Last-10 outcome string, e.g. "BDDBBDDDBD" (B = bonded, D = dead). */
2263
+ recent: string | null;
2264
+ }
2265
+ /**
2266
+ * +1 h outcome, present on REST rows ≥ 65 min old (computed from candles every
2267
+ * 10 min). `priced_after_1h: false` = no candle in the hour — the token stopped
2268
+ * being priced, NOT zero. Never on the WS event.
2269
+ */
2270
+ export interface TokenSurgeOutcome {
2271
+ computed_at: string;
2272
+ mc_usd_1h_after: number | null;
2273
+ peak_mc_usd_1h_after: number | null;
2274
+ low_mc_usd_1h_after: number | null;
2275
+ /** `mc_usd_1h_after ÷ market_cap_usd` at the fire. */
2276
+ mc_1h_multiple: number | null;
2277
+ /** `peak_mc_usd_1h_after ÷ market_cap_usd` at the fire. */
2278
+ peak_1h_multiple: number | null;
2279
+ priced_after_1h: boolean;
2280
+ }
2281
+ /**
2282
+ * Payload of a `token:surge` / `token:revival` WS event (channel `token:surges`)
2283
+ * — pushed by the surge-tracker the moment a fire is confirmed. Both kinds share
2284
+ * one shape: `tier` is null on revivals; `dormant_hours` / `prev_mc_usd` /
2285
+ * `mc_vs_prev_multiple` are null on surges; `baseline_*` / `mc_multiple` /
2286
+ * `mc_change_3m_pct` are null on revivals. Nearly every scalar is nullable —
2287
+ * a null is "not known", never zero.
2288
+ */
2289
+ export interface TokenSurgeStreamEvent {
2290
+ id: number | null;
2291
+ kind: TokenSurgeKind;
2292
+ tier: TokenSurgeTier | null;
2293
+ mint: string;
2294
+ symbol: string | null;
2295
+ name: string | null;
2296
+ /** Venue at birth / classification (what the first_seen rule was judged on). */
2297
+ launchpad: string | null;
2298
+ /** Where it trades at fire time — a pump token that graduated is `pumpfun` / `pumpswap`. */
2299
+ primary_dex: string | null;
2300
+ fired_at: string;
2301
+ birth_at: string | null;
2302
+ birth_source: TokenSurgeBirthSource | null;
2303
+ age_seconds: number | null;
2304
+ market_cap_usd: number | null;
2305
+ liquidity_usd: number | null;
2306
+ liquidity_to_mc_ratio: number | null;
2307
+ price_usd: number | null;
2308
+ /** Surge only: launch MC (`baseline_source: "launch"`). */
2309
+ baseline_mc_usd: number | null;
2310
+ baseline_source: TokenSurgeBaselineSource | null;
2311
+ /** Surge only: `market_cap_usd ÷ baseline_mc_usd`; null when the baseline is `late`. */
2312
+ mc_multiple: number | null;
2313
+ /** Surge only: climb vs the lowest sample of the last 3 min. */
2314
+ mc_change_3m_pct: number | null;
2315
+ /** Revival only. */
2316
+ dormant_hours: number | null;
2317
+ /** Revival only: pre-dormancy candle close MC. */
2318
+ prev_mc_usd: number | null;
2319
+ /** Revival only: `market_cap_usd ÷ prev_mc_usd`. */
2320
+ mc_vs_prev_multiple: number | null;
2321
+ peak_mc_usd: number | null;
2322
+ pct_of_peak: number | null;
2323
+ bonding_progress_pct: number | null;
2324
+ is_bonded: boolean | null;
2325
+ tape: TokenSurgeTape;
2326
+ kol: TokenSurgeKol;
2327
+ early_buyers: TokenSurgeEarlyBuyers;
2328
+ deployer: TokenSurgeDeployer | null;
2329
+ /** Flat copies of `deployer.wallet` / `deployer.tier` (what the subscribe filter reads). */
2330
+ deployer_wallet: string | null;
2331
+ deployer_tier: TokenSurgeDeployerTier | null;
2332
+ mint_authority_revoked: boolean | null;
2333
+ freeze_authority_revoked: boolean | null;
2334
+ is_token_2022: boolean | null;
2335
+ risk_flags: TokenSurgeRiskFlag[];
2336
+ detail_url: string;
2337
+ /** false when the one-round-trip enrichment failed (tape / kol / early_buyers then carry zeros / nulls). */
2338
+ enrichment_available?: boolean;
2339
+ }
2340
+ /** A REST row on GET /tokens/surges — the WS payload plus the +1 h `outcome` (null until the fire is ≥ 65 min old). */
2341
+ export interface TokenSurgeEvent extends TokenSurgeStreamEvent {
2342
+ id: number;
2343
+ outcome: TokenSurgeOutcome | null;
2344
+ }
2345
+ /** Query params for GET /tokens/surges. */
2346
+ export interface TokenSurgesParams {
2347
+ kind?: TokenSurgeKind;
2348
+ /** Surge only — 400 with `kind: "revival"`. */
2349
+ tier?: TokenSurgeTier;
2350
+ mint?: string;
2351
+ /** ISO date-time — only fires after this instant (use `pagination.next_since`). */
2352
+ since?: string;
2353
+ /** ISO date-time — page back: only fires before this instant (`pagination.next_before`). */
2354
+ before?: string;
2355
+ min_mc_usd?: number;
2356
+ max_mc_usd?: number;
2357
+ /** Buys on the tape at fire time ≥. */
2358
+ min_buys?: number;
2359
+ /** Launchpad at birth, e.g. "pumpfun". */
2360
+ launchpad?: string;
2361
+ deployer_tier?: TokenSurgeDeployerTier;
2362
+ /** Drop rows carrying ANY of these flags (array or comma list; unknown flag → 400 with `known_flags[]`). */
2363
+ exclude_flags?: TokenSurgeRiskFlag[] | string;
2364
+ /** Only rows with no risk flags at all. */
2365
+ only_clean?: boolean;
2366
+ /** Also return per-(kind, tier) hit-rates over `days`. */
2367
+ stats?: boolean;
2368
+ /** Stats window, 1–30, default 7. */
2369
+ days?: number;
2370
+ /** 1–200, default 50. */
2371
+ limit?: number;
2372
+ }
2373
+ /** One per-(kind, tier) hit-rate row from `?stats=true`. Out-of-sample by construction. */
2374
+ export interface TokenSurgeStatsRow {
2375
+ kind: TokenSurgeKind;
2376
+ tier: TokenSurgeTier | null;
2377
+ fires: number;
2378
+ /** Fires ≥ 65 min old with a computed outcome — the denominator. */
2379
+ with_outcome: number;
2380
+ /** MC one hour after the fire ≥ MC at the fire. */
2381
+ up_1h: number;
2382
+ up_1h_pct: number | null;
2383
+ median_peak_multiple: number | null;
2384
+ p75_peak_multiple: number | null;
2385
+ median_mc_1h_multiple: number | null;
2386
+ doubled_1h: number;
2387
+ doubled_1h_pct: number | null;
2388
+ }
2389
+ export interface TokenSurgeStats {
2390
+ days: number;
2391
+ note: string;
2392
+ rows: TokenSurgeStatsRow[];
2393
+ }
2394
+ /** Echo of the filters the request was served with. */
2395
+ export interface TokenSurgesFilters {
2396
+ kind: TokenSurgeKind | null;
2397
+ tier: TokenSurgeTier | null;
2398
+ mint: string | null;
2399
+ launchpad: string | null;
2400
+ deployer_tier: TokenSurgeDeployerTier | null;
2401
+ min_mc_usd: number | null;
2402
+ max_mc_usd: number | null;
2403
+ min_buys: number | null;
2404
+ exclude_flags: string[];
2405
+ only_clean: boolean;
2406
+ }
2407
+ /** Per-tier surge thresholds as read from the live rule engine. */
2408
+ export interface TokenSurgeTierDefinition {
2409
+ max_age_seconds: number;
2410
+ min_market_cap_usd: number;
2411
+ min_launch_multiple: number;
2412
+ /** `strong` only. */
2413
+ min_3m_climb_multiple?: number;
2414
+ }
2415
+ /**
2416
+ * The live rule thresholds the response was produced under — read straight from
2417
+ * the engine, so they cannot drift from what fires.
2418
+ */
2419
+ export interface TokenSurgeDefinitions {
2420
+ surge: {
2421
+ early: TokenSurgeTierDefinition;
2422
+ strong: TokenSurgeTierDefinition;
2423
+ breakout: TokenSurgeTierDefinition;
2424
+ min_age_seconds: number;
2425
+ sustained_seconds: number;
2426
+ birth_sources: TokenSurgeBirthSource[];
2427
+ first_seen_launchpads: string[];
2428
+ birth_note: string;
2429
+ note: string;
2430
+ };
2431
+ revival: {
2432
+ min_dormant_hours: number;
2433
+ confirm_window_seconds: number;
2434
+ min_buys: number;
2435
+ min_buy_volume_usd: number;
2436
+ min_market_cap_usd: number;
2437
+ min_multiple_vs_prev_mc: number;
2438
+ unknown_prev_mc_min_buy_volume_usd: number;
2439
+ strong_confirm: {
2440
+ min_buys: number;
2441
+ min_buy_volume_usd: number;
2442
+ };
2443
+ refire_guard_hours: number;
2444
+ note: string;
2445
+ };
2446
+ shared: {
2447
+ min_liquidity_usd: number;
2448
+ min_liq_to_mc_ratio: number;
2449
+ volume_backing_ratio: number;
2450
+ unbacked_max_multiple: number;
2451
+ mc_sanity_max_usd: number;
2452
+ tape_lag_seconds: number;
2453
+ note: string;
2454
+ };
2455
+ /** Flag → human-readable threshold. */
2456
+ risk_flags: Record<string, string>;
2457
+ tiers: TokenSurgeTier[];
2458
+ }
2459
+ /**
2460
+ * GET /tokens/surges — token momentum fires (surges + revivals), newest first,
2461
+ * each with the burst tape, KOL involvement, early-buyer cohort, deployer
2462
+ * reputation, `risk_flags[]` and (≥ 65 min old) the +1 h `outcome`. PRO+, keyed only.
2463
+ */
2464
+ export interface TokenSurgesResponse {
2465
+ events: TokenSurgeEvent[];
2466
+ pagination: TokenFeedPagination;
2467
+ filters: TokenSurgesFilters;
2468
+ /** Only with `stats: true`. */
2469
+ stats?: TokenSurgeStats;
2470
+ /** Pointer to the `token:surges` WS channel (events `token:surge` / `token:revival`). */
2471
+ stream: TokenFeedStreamPointer;
2472
+ definitions: TokenSurgeDefinitions;
2473
+ note: string;
2474
+ meta?: Record<string, unknown>;
2475
+ }
2476
+ /**
2477
+ * Server-side subscribe filters for the `token:surges` WS channel — pass as the
2478
+ * `filters` argument of `stream.subscribe(["token:surges"], filters)`. `tiers`
2479
+ * applies to surges only (revivals always pass it); `exclude_flags` drops a fire
2480
+ * carrying ANY listed flag.
2481
+ */
2482
+ export interface TokenSurgesSubscribeFilters {
2483
+ kinds?: TokenSurgeKind[];
2484
+ tiers?: TokenSurgeTier[];
2485
+ launchpads?: string[];
2486
+ exclude_flags?: TokenSurgeRiskFlag[];
2487
+ min_mc_usd?: number;
2488
+ max_mc_usd?: number;
2489
+ deployer_tier?: TokenSurgeDeployerTier[];
2490
+ }
2196
2491
  export type CandleTimeframe = "1m" | "5m" | "15m" | "1h" | "4h" | "1d";
2197
2492
  export interface CandlesParams {
2198
2493
  /** Bar size. Default "1h". */
@@ -3187,8 +3482,14 @@ export interface ToolsSearchResponse {
3187
3482
  }
3188
3483
  export interface StreamToken {
3189
3484
  token: string;
3190
- expires_at: string;
3485
+ /** Always `null` since 2026-08-27 — stream tokens never expire. Kept for wire compatibility; do not schedule refreshes on it. */
3486
+ expires_at: string | null;
3487
+ /** Always `null` since 2026-08-27 — the server never rotates a token on its own. Kept for wire compatibility. */
3191
3488
  next_refresh_at?: string | null;
3489
+ /** `true` when this call replaced your previous token (`rotate: true`); the old value keeps working for 60 s. */
3490
+ rotated?: boolean;
3491
+ /** Human-readable lifetime statement ("This token does not expire. …"). */
3492
+ lifetime?: string;
3192
3493
  ws_url: string;
3193
3494
  /** DEX trade stream URL — only present for Ultra tier subscribers */
3194
3495
  dex_ws_url?: string | null;
@@ -3725,6 +4026,44 @@ declare class TokenClient {
3725
4026
  * ```
3726
4027
  */
3727
4028
  feeClaims(params?: TokenFeeClaimsParams): Promise<TokenFeeClaimsResponse>;
4029
+ /**
4030
+ * v2.26 — Token momentum fires, newest first (`GET /tokens/surges`). Two
4031
+ * kinds. **`surge`** — a token < 30 min old whose MC runs hard vs its LAUNCH
4032
+ * MC: tier `early` (≤ 10 min, ≥ $12k, ≥ 3× launch MC), `strong` (≤ 30 min,
4033
+ * ≥ $30k, ≥ 6× launch AND ≥ 2× the lowest sample of the last 3 min — it is
4034
+ * climbing NOW), `breakout` (≤ 2 min, ≥ $45k, ≥ 8×); each tier fires at
4035
+ * most once per mint and a tier must be SUSTAINED (floor + multiple hold on
4036
+ * the current tick and on a sample ≥ 10 s older; nothing fires before 20 s
4037
+ * of age — a one-tick mark is a spike, not a surge). **`revival`** — a token
4038
+ * with no 1-minute trade candle for ≥ 24 h that started trading again,
4039
+ * CONFIRMED by the tape (≥ 5 buys, ≥ $500 buy volume, MC ≥ 1.5× the
4040
+ * pre-dormancy close — or ≥ 20 buys / ≥ $5k regardless), never by the price
4041
+ * mark alone. Hard gates on both: liquidity ≥ $1.5k and ≥ 2% of MC when
4042
+ * known, MC ≤ $100B, and the MC gained must be PAID FOR (buy volume ≥ 3% of
4043
+ * the move — a price mark in a spoof pool moves MC on ~$0 of volume).
4044
+ *
4045
+ * Every row carries `tape` (buys / sells / volume since birth or revival —
4046
+ * `tape.source` says whether it was measured on candles or live wallet
4047
+ * trades; `unique_buyers` only when the mint is in `token_trades` coverage,
4048
+ * `wallet_data_available: false` otherwise, never inferred zero), `kol`,
4049
+ * `early_buyers` (first-20 cohort: bundled / sold / sniper wallets),
4050
+ * `deployer` and **`risk_flags[]`** — the honest half. Rows ≥ 65 min old
4051
+ * also carry `outcome` (MC / peak / low one hour after, `priced_after_1h:
4052
+ * false` = no candle in the hour, not zero) and `stats: true` prints
4053
+ * per-(kind, tier) hit-rates over `days` — out-of-sample by construction,
4054
+ * the fire is recorded before the outcome exists. The live thresholds are
4055
+ * echoed in `definitions`. Poll with `since = pagination.next_since` or
4056
+ * subscribe to the **`token:surges`** WS channel (events `token:surge` /
4057
+ * `token:revival`, typed `TokenSurgeStreamEvent`; server-side filters
4058
+ * `TokenSurgesSubscribeFilters`). **PRO+** — BASIC receives HTTP 403.
4059
+ * @example
4060
+ * ```ts
4061
+ * const { events, stats } = await client.token.surges({ kind: "surge", tier: "strong", only_clean: true, stats: true });
4062
+ * for (const e of events) console.log(e.symbol, e.market_cap_usd, `${e.mc_multiple}× launch`, e.tape.buys, "buys", e.outcome?.peak_1h_multiple ?? "pending");
4063
+ * for (const r of stats?.rows ?? []) console.log(r.kind, r.tier, `${r.up_1h_pct}% up after 1h`, "median peak", r.median_peak_multiple);
4064
+ * ```
4065
+ */
4066
+ surges(params?: TokenSurgesParams): Promise<TokenSurgesResponse>;
3728
4067
  }
3729
4068
  declare class DeployerClient {
3730
4069
  private readonly _fetch;
@@ -4252,13 +4591,22 @@ declare class StreamClient {
4252
4591
  private readonly _post;
4253
4592
  private readonly _delete;
4254
4593
  private readonly _baseUrl;
4255
- constructor(_get: <T>(url: string) => Promise<T>, _post: <T>(url: string) => Promise<T>, _delete: <T>(url: string) => Promise<T>, _baseUrl: string);
4594
+ constructor(_get: <T>(url: string) => Promise<T>, _post: <T>(url: string, body?: unknown) => Promise<T>, _delete: <T>(url: string) => Promise<T>, _baseUrl: string);
4256
4595
  /**
4257
- * Generate a 24-hour WebSocket streaming token.
4596
+ * Issue your WebSocket streaming token. Stream tokens never expire (since
4597
+ * 2026-08-27): every call returns the same token until your subscription
4598
+ * lapses or you pass `{ rotate: true }`, which replaces it (the previous
4599
+ * value keeps working for 60 s). `expires_at` / `next_refresh_at` are always
4600
+ * `null` — the server never rotates on its own and never sends
4601
+ * `token_refresh` unless you rotated. A `4001` close means "mint again"
4602
+ * (lapsed or rotated), never a timer. Authenticate the handshake with
4603
+ * `Authorization: Bearer <token>` (`?token=` still works, masked in logs).
4258
4604
  * Pro/Ultra: ws_url for KOL/deployer event streaming.
4259
4605
  * Ultra only: dex_ws_url for all-DEX trade streaming.
4260
4606
  */
4261
- getToken(): Promise<StreamToken>;
4607
+ getToken(opts?: {
4608
+ rotate?: boolean;
4609
+ }): Promise<StreamToken>;
4262
4610
  /**
4263
4611
  * List your live WebSocket sessions across the KOL/deployer (`ws-streaming`)
4264
4612
  * and all-DEX (`dex-stream`) services — id, tier, subscribed channels, connect