madeonsol-x402 1.17.0 β†’ 1.18.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
@@ -1,414 +1,443 @@
1
- # madeonsol-x402
2
-
3
- [![npm version](https://img.shields.io/npm/v/madeonsol-x402?style=flat-square)](https://www.npmjs.com/package/madeonsol-x402)
4
- [![npm downloads](https://img.shields.io/npm/dm/madeonsol-x402?style=flat-square)](https://www.npmjs.com/package/madeonsol-x402)
5
- [![TypeScript](https://img.shields.io/badge/TypeScript-5.4+-blue?style=flat-square&logo=typescript&logoColor=white)](https://www.typescriptlang.org/)
6
- [![License: MIT](https://img.shields.io/badge/License-MIT-blue?style=flat-square)](LICENSE)
7
-
8
- > πŸ“‚ **[Examples](./examples/)** Β· πŸ“š **[API docs](https://madeonsol.com/api-docs)** Β· πŸ’° **[Get a free API key](https://madeonsol.com/pricing)**
9
-
10
- TypeScript SDK for the [MadeOnSol](https://madeonsol.com) Solana KOL intelligence API.
11
-
12
- > 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, score 1M+ early-buyer wallets (incl. dump-cluster detection), push every pump.fun graduation, and stream every DEX trade. Free tier: 200 requests/day at [madeonsol.com/pricing](https://madeonsol.com/pricing) β€” no credit card required.
13
-
14
- > **New in 1.17.0** β€” **Almost-bonded discovery + trending sorts.** `rest.almostBonded({ min_progress?, max_progress?, min_velocity_pct_per_min?, max_age_minutes?, deployer_tier?, authority_revoked?, min_liq?, sort?, limit? })` returns pre-bond pump.fun tokens near graduation, ranked by velocity (Ξ”progress/min) β€” "95% and accelerating" beats "92% stalled". Each token carries `progress_pct`, `velocity_pct_per_min`, `eta_minutes`, `stalled`, `real_sol_reserves`, `market_cap_usd`, `liquidity_usd`, `authorities_revoked`, `deployer_tier`, and `age_minutes` (typed `AlmostBondedResponse`). `sort` is `velocity_desc` (default) / `progress_desc` / `eta_asc`. **KEYED (v1) β€” requires an `msk_` API key; there is no x402 route.** PRO/ULTRA only. Plus `client.tokensList({ sort })` gains four momentum sorts β€” `mc_change_5m_desc`, `mc_change_1h_desc`, `volume_1h_desc`, and `trending` (composite recent-volume Γ— positive-momentum rank).
15
- >
16
- > **New in 1.16.0** β€” **Token trade flow.** `client.tokenFlow(mint, { window? })` returns a trade-flow aggregate over a `1h`/`24h` window β€” `unique_wallets` / `unique_buyers` / `unique_sellers`, `buy_count` / `sell_count` / `total_trades`, `buy_sol` / `sell_sol` / `net_sol`, and a `trades_per_wallet` wash-trading proxy (typed `TokenFlowResponse`). It's an **organic-vs-fake volume** read. **KEYED (v1) β€” requires an `msk_` API key; there is no x402 route**, so x402-only clients can't reach it. PRO/ULTRA only. Deployer alerts now carry `deployers.deployer_sol_balance` β€” the deployer wallet's SOL balance at alert time (null for historical rows).
17
- >
18
- > **New in 1.15.0** β€” **Live token snapshot + Signal Scorecard.** `rest.token(mint)` returns a live snapshot β€” price (USD/SOL), VWAP, market cap, FDV, liquidity, liquidity-to-MC ratio, primary DEX + pool, Token-2022 / transfer-fee flags, and a `top_buyers[]` array (typed `TokenSnapshotResponse`). `rest.signalPerformance(name, { history? })` returns the **Signal Scorecard** β€” out-of-sample reliability buckets (hit_rate, base_rate, lift, sample_n, window_days) for `dump_cluster_count`, `runner_rate`, `recycled_early_buyer_count`, or `coordination_count`, with a per-day `series` when `history: true` (typed `SignalPerformanceResponse`). `rest.signals()` is the free catalog of all scored signals (typed `SignalsCatalogResponse`). `rest.tokenRisk(mint)` and `rest.tokenBuyerQuality(mint)` are now fully live server-side.
19
- >
20
- > **New in 1.13.0** β€” **Token risk score.** `rest.tokenRisk(mint)` returns a transparent 0–100 rug-risk/safety score (higher = riskier) with a `band` (safe/caution/danger), an explainable `factors[]` array, and the raw `inputs` (mint/freeze authority, liquidity, liq-to-MC ratio, transfer fee, launch cohort, deployer bond rate, KOL signal, blacklist). Typed as `TokenRiskResponse`. PRO/ULTRA only.
21
- >
22
- > **New in 1.12.0** β€” `/token/{mint}` and `/token/batch` responses now include `liquidity_to_mc_ratio`, `launch_cohort_sol`, and `launch_cohort_size`. `/tokens` gains three new filter params: `min_liq_mc_ratio`, `max_liq_mc_ratio`, and `deployer_tier`. `/tokens` list items now include `liquidity_to_mc_ratio` and `deployer_tier`. `/kol/leaderboard` entries now include `median_hold_minutes_30d` and `percentile_early_entry_30d`.
23
- >
24
- > **New in 1.11.1** β€” Deployer profiles now carry `runner_rate` + `labeled_tokens` (fraction of a deployer's labeled tokens that ran vs dumped, gate on `labeled_tokens` β‰₯3) plus `avg_time_to_bond_minutes`, on `DeployerAlert.deployers` and the deployer-trajectory profile.
25
- >
26
- > **New in 1.11** β€” **Graduation events + dump-cluster detection.** Subscribe `token:graduations` for every pump.fun bond in real time (tracked deployer or not, typed `GraduationEvent`). Buyer-quality `breakdown` adds `dump_cluster_count` (out-of-sample: 3+ β†’ 94% dump vs 61% base) + `recycled_early_buyer_count`. DEX firehose: replay buffer deepened to ~5 min; mint-scoped subs get in-band `dex:graduations` frames.
27
-
28
- > **New in 1.10** β€” **Deshred Sniper.** `rest.sniper_recent()` β€” deshred deploy feed ~500ms before on-chain confirmation. PRO: elite/good. ULTRA: all tiers + watchlist. Use `sniper:deploys` WebSocket for push.
29
- >
30
- > **New in 1.9** β€” **Price alerts, scout leaderboard, coordination history.** `rest.priceAlertsCreate()` (PRO=5, ULTRA=25). `scoutLeaderboard()`, `kolConsensus()`, `peakHistory()`, `coordinationHistory()`. `walletStats()` now returns `derived`: win_rate, roi, verdict, biggest_miss.
31
- >
32
- > **New in 1.8** β€” **Universal Wallet API.** `rest.walletStats()`, `rest.walletPnl()`, `rest.walletPositions()`, `rest.walletTrades()` β€” FIFO cost-basis PnL for any Solana wallet. PRO+. Cache hits free.
33
- >
34
- > **New in 1.7.1** *(2026-05-13)* β€” Velocity field shape corrected to match the API: `mc_change_pct`, `volume_usd`, `mev_volume_pct` are top-level on the token response, each keyed by `5m`/`15m`/`1h`/`2h`/`4h`. The 1.7.0 README documented a `velocity[window]` shape that didn't match the wire format. Runtime is unchanged β€” fix is to typed shape + docs.
35
- >
36
- > **New in 1.7.0** *(2026-05-12)* β€” **Token directory + account inspection.** `client.tokensList({ min_liq, min_volume_1h_usd, max_mev_share_pct, mc_change_1h_min_pct, sort, min_liq_mc_ratio, max_liq_mc_ratio, deployer_tier, ... })` filters every active mint by MC band, liquidity floor, primary DEX, authority/safety flags, computed 1h volume, MEV-share ceiling, MC-change deltas, liq/MC ratio, and deployer tier. Response items now include `liquidity_to_mc_ratio` and `deployer_tier`. Default `min_liq=2000` skips phantom-MC dust; pass `min_liq=0` to opt out. `client.me()` β€” read your tier, daily/burst quota state, and per-feature usage in one call (no header parsing). Velocity / MEV-share fields added to every token response: `mc_change_pct`, `volume_usd`, `mev_volume_pct` (each keyed by `5m`/`15m`/`1h`/`2h`/`4h`) plus `history_age_seconds`. `/token/{mint}` 400s now ship structured `code`, `reason`, `received_length`, `example`, and `docs` β€” stop guessing why a mint failed. Deprecated `avg_entry_mc_usd` fully removed.
37
-
38
- ## Quick start (10 seconds)
39
-
40
- ```bash
41
- npm install madeonsol-x402
42
- ```
43
-
44
- ```ts
45
- import { createClient } from "madeonsol-x402";
46
- const client = createClient("msk_..."); // free tier at https://madeonsol.com/pricing
47
- const { trades } = await client.kolFeed({ limit: 5 });
48
- ```
49
-
50
- ## Authentication
51
-
52
- Two options:
53
-
54
- | Method | Option | Best for |
55
- |---|---|---|
56
- | **MadeOnSol API key** (recommended) | `apiKey` | Developers β€” [get a free key](https://madeonsol.com/pricing) |
57
- | x402 micropayments | `privateKey` | AI agents with Solana wallets |
58
-
59
- > **v1.0 breaking change:** RapidAPI auth has been removed. The MadeOnSol RapidAPI marketplace was retired on 2026-04-19. If you were using `rapidApiKey`, get a free `msk_` key at [madeonsol.com/pricing](https://madeonsol.com/pricing).
60
-
61
- ## Install
62
-
63
- ```bash
64
- npm install madeonsol-x402
65
- ```
66
-
67
- > x402 peer deps (`@x402/fetch @x402/svm @x402/core @solana/kit @scure/base`) are only needed when using `privateKey`.
68
-
69
- ## Quick Start
70
-
71
- ```ts
72
- import { createClient } from "madeonsol-x402";
73
-
74
- // Option 1: API key β€” get one free at madeonsol.com/pricing
75
- const client = createClient("msk_your_api_key_here");
76
-
77
- // Option 2: x402 micropayments (auto-detected when no msk_ prefix)
78
- // const client = createClient(process.env.SOLANA_PRIVATE_KEY!);
79
-
80
- const { trades } = await client.kolFeed({ limit: 10 });
81
- console.log(trades);
82
- ```
83
-
84
- ### Advanced initialization
85
-
86
- ```ts
87
- import { MadeOnSolX402 } from "madeonsol-x402";
88
-
89
- const client = new MadeOnSolX402({
90
- apiKey: "msk_...", // OR
91
- privateKey: "base58...", // x402 micropayments
92
- });
93
- ```
94
-
95
- ## x402 Endpoints (per-request micropayments)
96
-
97
- | Method | Description |
98
- |---|---|
99
- | `kolFeed(params?)` | Real-time KOL trade feed from 1,000+ tracked wallets |
100
- | `kolCoordination(params?)` | Tokens being accumulated by multiple KOLs simultaneously |
101
- | `kolLeaderboard(params?)` | KOL performance rankings by PnL and win rate (180 days of trade history) |
102
- | `kolPairs(params?)` | KOL affinity matrix β€” which KOLs frequently co-trade the same tokens |
103
- | `kolHotTokens(params?)` | KOL momentum tokens β€” accelerating KOL buy interest |
104
- | `kolTokenEntryOrder(mint, params?)` | Ranked KOL first-buyer order for a token |
105
- | `kolCompareWallets({ wallets })` | Side-by-side comparison of 2–5 KOL wallets |
106
- | `kolAlertsRecent(params?)` | Live KOL alert feed β€” clusters, fresh-token buys, heating-up wallets |
107
- | `deployerAlerts(params?)` | Pump.fun deployer alerts with KOL enrichment. PRO/ULTRA: filter by tier. |
108
- | `walletStats(address)` | **New 1.8** Β· Wallet stats + cross-product flags (is_kol / is_alpha_tracked + bot_confidence / is_deployer). 90-day window. **$0.005** |
109
- | `walletPnl(address)` | **New 1.8** Β· FIFO cost-basis PnL: realized + unrealized SOL, profit factor, drawdown, hold times, daily curve, closed + open positions. **$0.02** |
110
- | `walletPositions(address)` | **New 1.8** Β· Open positions only, live unrealized from market-cap tracker. Shares /pnl cache. **$0.01** |
111
- | `walletTrades(address, params?)` | **New 1.8** Β· Cursor-paginated raw trades with action / token / since-until filters. **$0.005** |
112
- | `tokenFlow(mint, params?)` | **New 1.16** Β· Trade-flow aggregate (organic-vs-fake volume) β€” unique wallets/buyers/sellers, buy/sell counts + SOL, net SOL, `trades_per_wallet` wash-trading proxy. `window` ("1h" \| "24h", default "1h"). **KEYED (v1) β€” needs an `msk_` API key, no x402 route.** PRO/ULTRA |
113
- | `discovery()` | Lists all endpoints, prices, and parameter docs (free) |
114
-
115
- ## REST API client
116
-
117
- The `MadeOnSolREST` class exposes the full v1 API (alpha intelligence, token quality, copy-trade rules, wallet tracker, webhooks, streaming). Most endpoints require a Pro or Ultra subscription.
118
-
119
- ```ts
120
- import { MadeOnSolREST } from "madeonsol-x402";
121
-
122
- const rest = new MadeOnSolREST({ apiKey: "msk_your_key" });
123
- const { leaderboard } = await rest.alphaLeaderboard({ period: "30d", sort: "win_rate" });
124
-
125
- // Rate-limit headers from the most recent response
126
- console.log(rest.lastRateLimit); // { limit, remaining, reset, requestId }
127
- ```
128
-
129
- ### Alpha wallet intelligence
130
-
131
- Scored from 1M+ early-buyer records (wallets seen in the first 20 buyers of Pump.fun tokens).
132
-
133
- | Method | Tier | Description |
134
- |---|---|---|
135
- | `rest.alphaLeaderboard(params?)` | All | Top profitable wallets. Up to 100 on Free/Pro; ULTRA unlocks 500 + bot signals |
136
- | `rest.alphaWallet(wallet)` | ULTRA | Full per-token breakdown + bot_signals array |
137
- | `rest.alphaLinked(wallet)` | ULTRA | Wallets behaviorally linked (co-bought 3+ tokens within 2s) |
138
-
139
- **alphaLeaderboard params** β€” `period` ("7d" \| "30d" \| "all"), `min_tokens` (1–20), `sort` ("win_rate" \| "pnl" \| "roi"), `exclude_bots` ("true" \| "false")
140
-
141
- ### Token quality
142
-
143
- | Method | Tier | Description |
144
- |---|---|---|
145
- | `rest.token(mint)` | All | **New 1.15** Β· Live token snapshot β€” price (USD/SOL), VWAP, market cap, FDV, liquidity, liq-to-MC ratio, primary DEX + pool, Token-2022 / transfer-fee flags, and `top_buyers[]`. Returns `{ token }` |
146
- | `rest.tokenCapTable(mint)` | PRO+ | First non-deployer early buyers, enriched with PnL/KOL/bot flags. PRO=10, ULTRA=20 |
147
- | `rest.tokenBuyerQuality(mint)` | All | 0–100 buyer-quality score + full breakdown (5-min cached). Live server-side |
148
- | `rest.tokenRisk(mint)` | PRO+ | Transparent 0–100 rug-risk/safety score with `band`, explainable `factors[]`, and raw `inputs`. Live server-side |
149
- | `rest.tokenCandles(mint, params?)` | PRO+ | OHLC candles. PRO = OHLCV, last 30 days; ULTRA = + net flow (buy/sell volume, `net_volume_usd`, counts, MEV vol), liquidity delta, full history |
150
-
151
- **tokenCandles params** β€” `tf` ("1m" \| "5m" \| "15m" \| "1h" \| "4h" \| "1d", default "1h"), `limit` (1–1000, default 200), `from` (ISO 8601), `to` (ISO 8601)
152
-
153
- ### Signal Scorecard *(new in 1.15)*
154
-
155
- Out-of-sample reliability for the scored early-buyer / coordination signals β€” every claim is backed by a hit-rate vs base-rate measurement so you can size positions on evidence, not vibes.
156
-
157
- | Method | Tier | Description |
158
- |---|---|---|
159
- | `rest.signals()` | All (free) | Catalog of scored signals β€” name, methodology, and each signal's `performance_endpoint`. No payment required |
160
- | `rest.signalPerformance(name, params?)` | All | Signal Scorecard for one signal β€” `buckets[]` (hit_rate, base_rate, lift, sample_n, window_days, test_from/test_to) + metric_type, outcome, methodology, as_of. Pass `{ history: true }` for a per-day `series[]` |
161
-
162
- Valid signal names: `dump_cluster_count`, `runner_rate`, `recycled_early_buyer_count`, `coordination_count`.
163
-
164
- ```ts
165
- const { signals } = await rest.signals();
166
- const scorecard = await rest.signalPerformance("dump_cluster_count", { history: true });
167
- console.log(scorecard.buckets); // [{ bucket, hit_rate, base_rate, lift, sample_n, ... }]
168
- ```
169
-
170
- ### KOL coordination alerts (v1.1 β€” push signals)
171
-
172
- Real-time push alerts when a cluster of KOLs co-buys the same token. Fires within ~1s of the triggering trade (pg_notify push, not polling). Delivered via WebSocket (`kol:coordination` channel, user-scoped) and/or HMAC-signed webhook. PRO=5 rules, ULTRA=20.
173
-
174
- ```ts
175
- // Create a rule
176
- const { rule, webhook_secret } = await rest.coordinationAlertsCreate({
177
- name: "fresh pump cluster",
178
- min_kols: 4, // minimum distinct KOLs in window
179
- window_minutes: 15, // peak-density window (1-60)
180
- min_score: 70, // 0-100 composite score cutoff
181
- include_majors: false, // filter WIF/BONK/POPCAT
182
- cooldown_min: 60, // one fire per (rule,token) per 60min...
183
- score_jump_break: 10, // ...unless score jumps +10 vs last fire
184
- delivery_mode: "both",
185
- webhook_url: "https://you.com/hooks/coord",
186
- });
187
- // β†’ store webhook_secret β€” shown ONCE
188
- ```
189
-
190
- `coordinationAlertsList`, `coordinationAlertsGet(id)`, `coordinationAlertsUpdate(id, params)`, `coordinationAlertsDelete(id)` round out the CRUD.
191
-
192
- **Webhook signature:** `X-MadeOnSol-Signature: sha256=<hmac>` where `hmac = HMAC-SHA256(webhook_secret, timestamp + "." + rawBody)`, and `X-MadeOnSol-Timestamp` carries the unix seconds used.
193
-
194
- **The `kolCoordination()` response** now includes v1.1 fields: `peak_window_start/end`, `peak_kols`, `peak_buys` (the busiest slice within the period), `exited_count` + per-KOL `exited` flag (net-flow-negative wallets), and `coordination_score` (0-100). Pass `min_score`, `window_minutes`, `include_majors` to filter.
195
-
196
- ### KOL first-touch signal *(new in 1.3)*
197
-
198
- Every "first KOL buy on a token mint" event β€” the moment a tracked KOL is the first of the cohort to touch a token. Filterable by **scout tier** (S/A/B/C from `mv_kol_scout_score`), KOL winrate, token age, mint suffix.
199
-
200
- **Backtest:** top scouts attract β‰₯3 follow-on KOLs within 4h ~50% of the time vs ~14% baseline (38d / 491k buys / 72,549 events). Live leaderboard at [madeonsol.com/kol/scouts](https://madeonsol.com/kol/scouts).
201
-
202
- ```ts
203
- import { MadeOnSolREST } from "madeonsol-x402";
204
- const rest = new MadeOnSolREST({ apiKey: process.env.MADEONSOL_API_KEY! });
205
-
206
- // S-tier scouts on tokens younger than 1h
207
- const { events } = await rest.firstTouches({ preset: "scout", min_scout_tier: "S" });
208
-
209
- for (const e of events) {
210
- console.log(e.first_kol.name, "scouted", e.token_symbol, `(scout_score=${e.first_kol.scout_score}%)`);
211
- }
212
- ```
213
-
214
- Filter knobs: `since`, `before`, `limit`, `kol`, `min_kol_winrate_7d`, `min_scout_tier` (`"S"|"A"|"B"|"C"`), `min_n_touches`, `strategy`, `token_age_max_min`, `min_first_buy_sol`, `mint_suffix` (`"pump"`, `"bonk"`, …), `preset` (`"scout"`/`"fresh_launch"`), `include` (`"followers_4h"`).
215
-
216
- > **Don't poll β€” push.** Median lead time before the second KOL is **12 seconds**. REST polling will miss the swarm. Subscribe to the `kol:first_touches` WebSocket channel (PRO+) or, on Ultra, create an HMAC-signed webhook subscription.
217
-
218
- **Webhook subscriptions (Ultra)** β€” up to 10 active per user, mirrors `coordinationAlerts`:
219
-
220
- ```ts
221
- const { subscription, webhook_secret } = await rest.firstTouchSubscriptionsCreate({
222
- name: "S-tier scouts on pump tokens",
223
- filters: { min_scout_tier: "S", mint_suffix: "pump" },
224
- delivery_mode: "webhook",
225
- webhook_url: "https://my.bot/hooks/scout",
226
- });
227
- // β†’ store webhook_secret β€” shown ONCE
228
- ```
229
-
230
- `firstTouchSubscriptionsList`, `firstTouchSubscriptionsGet(id)`, `firstTouchSubscriptionsUpdate(id, params)`, `firstTouchSubscriptionsDelete(id)` round out the CRUD.
231
-
232
- ### Price alerts *(new in 1.9)*
233
-
234
- CRUD for token dip/recovery price alerts. Fires via WebSocket (`price:alerts` channel) and/or HMAC-signed webhook when a token's market cap crosses your threshold. PRO=5 rules, ULTRA=25.
235
-
236
- ```ts
237
- const { alert, webhook_secret } = await rest.priceAlertsCreate({
238
- name: "SOL dip buy",
239
- token_mint: "So11111111111111111111111111111111111111112",
240
- condition: "below", // "below" | "above"
241
- threshold_mc_usd: 5_000_000_000,
242
- cooldown_min: 120,
243
- delivery_mode: "both",
244
- webhook_url: "https://you.com/hooks/price",
245
- });
246
- // β†’ store webhook_secret β€” shown ONCE
247
- ```
248
-
249
- `priceAlertsList`, `priceAlertsGet(id)`, `priceAlertsUpdate(id, params)`, `priceAlertsDelete(id)` round out the CRUD.
250
-
251
- ### Scout leaderboard & KOL consensus *(new in 1.9)*
252
-
253
- | Method | Tier | Description |
254
- |---|---|---|
255
- | `rest.scoutLeaderboard(params?)` | PRO+ | Top scout-tier KOLs ranked by first-touch follow-on rate, win rate, and ROI |
256
- | `rest.kolConsensus(params?)` | PRO+ | Tokens with the strongest KOL agreement signal β€” weighted by scout score and recent PnL |
257
- | `rest.peakHistory(mint)` | PRO+ | Historical peak-density windows for a token β€” every coordination spike with KOL breakdown |
258
- | `rest.coordinationHistory(params?)` | PRO+ | Global coordination event log with token, KOL count, score, and outcome |
259
-
260
- ```ts
261
- const { leaderboard } = await rest.scoutLeaderboard({ period: "30d", limit: 25 });
262
- const { tokens } = await rest.kolConsensus({ min_kols: 5, period: "24h" });
263
- ```
264
-
265
- ### Wallet derived stats *(new in 1.9)*
266
-
267
- `walletStats(address)` now includes a `stats` object with derived fields computed from the 90-day trade window:
268
-
269
- ```ts
270
- const { stats } = await rest.walletStats("WALLET_ADDRESS");
271
- // stats.win_rate β€” fraction 0-1, tokens sold above cost basis
272
- // stats.roi β€” aggregate return on invested SOL
273
- // stats.verdict β€” "strong" | "profitable" | "neutral" | "losing"
274
- // stats.biggest_miss β€” token with the highest post-exit gain the wallet missed
275
- ```
276
-
277
- ### Copy-trade rules
278
-
279
- Server-side rules that fire signals when one of your watched source wallets trades. Delivered via webhook (HMAC-signed) and/or WebSocket. PRO=3 rules Γ— 5 source wallets each; ULTRA=20 Γ— 50.
280
-
281
- | Method | Description |
282
- |---|---|
283
- | `rest.copyTradeList()` | List your rules |
284
- | `rest.copyTradeCreate(params)` | Create a rule. Returns `webhook_secret` **once** β€” store it |
285
- | `rest.copyTradeGet(id)` | Get one rule |
286
- | `rest.copyTradeUpdate(id, params)` | Update fields or toggle `is_active` |
287
- | `rest.copyTradeDelete(id)` | Delete permanently |
288
- | `rest.copyTradeSignals(params?)` | Recent fired signals (up to 7 days). Filter by `subscription_id`, `since`, `limit` (1–500) |
289
-
290
- ### Wallet tracker
291
-
292
- Per-account watchlist with historical swap/transfer history.
293
-
294
- | Method | Description |
295
- |---|---|
296
- | `rest.walletTrackerList()` | List tracked wallets + remaining capacity |
297
- | `rest.walletTrackerAdd(wallet, label?)` | Add a wallet |
298
- | `rest.walletTrackerRemove(wallet)` | Remove a wallet |
299
- | `rest.walletTrackerUpdateLabel(wallet, label)` | Update label (pass `null` to clear) |
300
- | `rest.walletTrackerTrades(params?)` | Historical events. Params: `wallet`, `action`, `event_type`, `limit` (1–200), `before` (cursor) |
301
- | `rest.walletTrackerSummary(params?)` | Per-wallet stats. Params: `period` ("24h" \| "7d" \| "30d"), `wallet` |
302
- | `rest.walletStats(address)` | **New 1.8** Β· Universal wallet stats (90d) + cross-product flags. PRO+. |
303
- | `rest.walletPnl(address)` | **New 1.8** Β· Full FIFO PnL + curve + closed/open positions. PRO+. |
304
- | `rest.walletPositions(address)` | **New 1.8** Β· Open positions only with live unrealized. PRO+. |
305
- | `rest.walletTrades(address, params?)` | **New 1.8** Β· Cursor-paginated raw trades. Params: `limit` (1-500), `cursor`, `action`, `token_mint`, `since`, `until`. PRO+. |
306
-
307
- ### Webhooks
308
-
309
- | Method | Description |
310
- |---|---|
311
- | `rest.createWebhook(params)` | Create webhook. Returns `secret` once β€” store it for HMAC verification |
312
- | `rest.listWebhooks()` | List your webhooks |
313
- | `rest.getWebhook(id)` | Get one + recent delivery log |
314
- | `rest.updateWebhook(id, params)` | Update URL, events, filters, or re-enable |
315
- | `rest.deleteWebhook(id)` | Delete |
316
- | `rest.testWebhook(id)` | Send test payload |
317
-
318
- ### KOL/deployer detail
319
-
320
- | Method | Description |
321
- |---|---|
322
- | `rest.kolTiming(wallet, params?)` | Entry/exit timing β€” hold duration, exit speed, hour distribution |
323
- | `rest.kolPnl(wallet, params?)` | Per-wallet PnL breakdown |
324
- | `rest.deployerTrajectory(wallet)` | Deployer skill curve β€” streaks, rolling bond rate, trend |
325
-
326
- ### Streaming token
327
-
328
- ```ts
329
- const token = await rest.getStreamToken();
330
- // token.ws_url β€” KOL/deployer streaming (Pro/Ultra)
331
- // token.dex_ws_url β€” all-DEX trade stream (Ultra only)
332
- ```
333
-
334
- ### Managed streaming client *(new in 1.10)*
335
-
336
- `rest.stream()` handles the token fetch + 24h refresh, auto-reconnect (backoff + jitter), heartbeat liveness, and typed events β€” just subscribe and listen.
337
-
338
- ```ts
339
- const stream = rest.stream();
340
- stream.on("kol:trade", (t) => console.log(t.token_symbol, t.action));
341
- stream.on("deployer:alert", (a) => console.log("new deploy", a.token_mint));
342
- stream.subscribe(["kol:trades", "deployer:alerts"]);
343
- // stream.unsubscribe([...]) / stream.close() when done
344
- ```
345
-
346
- 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`). Lifecycle events: `open`, `close`, `reconnect`, `heartbeat`, `error`. Uses the global `WebSocket` on Node 22+; on Node < 22 also `npm i ws`.
347
-
348
- ## DEX Firehose (Ultra)
349
-
350
- Connect to `dex_ws_url` and use the multi-subscription protocol β€” up to **10 named subs per connection**, each with its own `sub_id`, server-side filters, and optional replay (up to 500 most recent matching trades) from a server-side buffer holding ~5 minutes of firehose history β€” it backfills trades from before your connection existed. Replayed trades arrive newest-first flagged `"replay": true`, then a `replay_done` frame; sort by `block_time` client-side.
351
-
352
- ```ts
353
- import WebSocket from "ws";
354
-
355
- const { token, dex_ws_url } = await rest.getStreamToken();
356
- const ws = new WebSocket(`${dex_ws_url}?token=${token}`); // token MUST be in the query string
357
-
358
- ws.on("open", () => {
359
- ws.send(JSON.stringify({
360
- type: "subscribe",
361
- sub_id: "fresh-pumpfun",
362
- replay: 50, // up to 500 from ring buffer
363
- filters: {
364
- dex: "pumpfun", // pumpfun | pumpamm | pumpswap | raydium | jupiter | orca | meteora | launchlab
365
- token_age_max_seconds: 300,
366
- min_sol: 0.5,
367
- action: "buy",
368
- },
369
- }));
370
- });
371
-
372
- ws.on("message", (raw) => {
373
- const msg = JSON.parse(raw.toString());
374
- if (msg.channel === "dex:trades") {
375
- // { sub_id, data: { wallet, mint, action, sol_amount, dex, ... }, replay, ts }
376
- }
377
- });
378
- ```
379
-
380
- **Operations** (all carry `sub_id`): `subscribe`, `update` (replace filters in place), `unsubscribe`, `list`, `ping`. **Filters:** `token_mint(s)` (≀50), `wallet(s)` (≀50), `dex`, `program`, `deployer_tier`, `token_age_max_seconds`, `market_cap_min/max_sol`, `min_sol`, `max_sol`, `action`. At least one targeting filter is required. Inbound rate limit: 5 messages/sec.
381
-
382
- Full protocol reference: [madeonsol.com/api-docs#streaming](https://madeonsol.com/api-docs#streaming).
383
-
384
- ## Rate-limit headers
385
-
386
- Every successful REST response carries `X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset`, and `X-Request-Id`. The SDK exposes them via `rest.lastRateLimit`:
387
-
388
- ```ts
389
- await rest.alphaLeaderboard();
390
- const { limit, remaining, reset, requestId } = rest.lastRateLimit;
391
- if (remaining !== null && remaining < 5) {
392
- console.warn(`Throttle warning β€” ${remaining}/${limit} requests left until ${reset}`);
393
- }
394
- ```
395
-
396
- ## Discovery
397
-
398
- ```ts
399
- const info = await client.discovery();
400
- console.log(info.endpoints); // all endpoints with prices and params
401
- ```
402
-
403
- Docs: [madeonsol.com/solana-api](https://madeonsol.com/solana-api)
404
-
405
- ## Also Available
406
-
407
- | Platform | Package |
408
- |---|---|
409
- | TypeScript SDK | [`madeonsol`](https://www.npmjs.com/package/madeonsol) on npm |
410
- | Rust SDK | [`madeonsol`](https://crates.io/crates/madeonsol) on crates.io |
411
- | Python (LangChain, CrewAI) | [`madeonsol-x402`](https://pypi.org/project/madeonsol-x402/) on PyPI |
412
- | MCP Server (Claude, Cursor) | [`mcp-server-madeonsol`](https://www.npmjs.com/package/mcp-server-madeonsol) Β· [Smithery](https://smithery.ai/servers/madeonsol/solana-kol-intelligence) Β· [Glama](https://glama.ai/mcp/servers/LamboPoewert/mcp-server-madeonsol) |
413
- | ElizaOS | [`@madeonsol/plugin-madeonsol`](https://www.npmjs.com/package/@madeonsol/plugin-madeonsol) |
414
- | Solana Agent Kit | [`solana-agent-kit-plugin-madeonsol`](https://www.npmjs.com/package/solana-agent-kit-plugin-madeonsol) |
1
+ # madeonsol-x402
2
+
3
+ [![npm version](https://img.shields.io/npm/v/madeonsol-x402?style=flat-square)](https://www.npmjs.com/package/madeonsol-x402)
4
+ [![npm downloads](https://img.shields.io/npm/dm/madeonsol-x402?style=flat-square)](https://www.npmjs.com/package/madeonsol-x402)
5
+ [![TypeScript](https://img.shields.io/badge/TypeScript-5.4+-blue?style=flat-square&logo=typescript&logoColor=white)](https://www.typescriptlang.org/)
6
+ [![License: MIT](https://img.shields.io/badge/License-MIT-blue?style=flat-square)](LICENSE)
7
+
8
+ > πŸ“‚ **[Examples](./examples/)** Β· πŸ“š **[API docs](https://madeonsol.com/api-docs)** Β· πŸ’° **[Get a free API key](https://madeonsol.com/pricing)**
9
+
10
+ TypeScript SDK for the [MadeOnSol](https://madeonsol.com) Solana KOL intelligence API.
11
+
12
+ > 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, score 1M+ early-buyer wallets (incl. dump-cluster detection), push every pump.fun graduation, and stream every DEX trade. Free tier: 200 requests/day, every endpoint β€” no signup payment. Get a key at [madeonsol.com/pricing](https://madeonsol.com/pricing).
13
+
14
+ > **New in 1.18.0** β€” **Batch risk scoring + live stream-session control.** `rest.tokensBatchRisk(mints)` scores up to 50 mints in one call (counts as 1 request) β€” each entry in `tokens` is either a full risk result (same shape as `rest.tokenRisk(mint)`, plus `as_of`) or `{ mint, error: "not_tracked" }`; untracked mints don't fail the batch, and `tokens` preserves de-duplicated input order (typed `TokenBatchRiskResponse`). PRO/ULTRA only. Plus `rest.streamSessions()` lists your live WebSocket sessions across ws-streaming + dex-stream (typed `StreamSessionsResponse`), and `rest.streamSessionKill(id)` force-releases a slot by id (typed `StreamSessionEvictResponse`) β€” the self-serve fix for a 4002 lockout when a deploy overlap leaves a ghost socket holding your slot. PRO/ULTRA only.
15
+ >
16
+ > **New in 1.17.0** β€” **Almost-bonded discovery + trending sorts.** `rest.almostBonded({ min_progress?, max_progress?, min_velocity_pct_per_min?, max_age_minutes?, deployer_tier?, authority_revoked?, min_liq?, sort?, limit? })` returns pre-bond pump.fun tokens near graduation, ranked by velocity (Ξ”progress/min) β€” "95% and accelerating" beats "92% stalled". Each token carries `progress_pct`, `velocity_pct_per_min`, `eta_minutes`, `stalled`, `real_sol_reserves`, `market_cap_usd`, `liquidity_usd`, `authorities_revoked`, `deployer_tier`, and `age_minutes` (typed `AlmostBondedResponse`). `sort` is `velocity_desc` (default) / `progress_desc` / `eta_asc`. **KEYED (v1) β€” requires an `msk_` API key; there is no x402 route.** PRO/ULTRA only. Plus `client.tokensList({ sort })` gains four momentum sorts β€” `mc_change_5m_desc`, `mc_change_1h_desc`, `volume_1h_desc`, and `trending` (composite recent-volume Γ— positive-momentum rank).
17
+ >
18
+ > **New in 1.16.0** β€” **Token trade flow.** `client.tokenFlow(mint, { window? })` returns a trade-flow aggregate over a `1h`/`24h` window β€” `unique_wallets` / `unique_buyers` / `unique_sellers`, `buy_count` / `sell_count` / `total_trades`, `buy_sol` / `sell_sol` / `net_sol`, and a `trades_per_wallet` wash-trading proxy (typed `TokenFlowResponse`). It's an **organic-vs-fake volume** read. **KEYED (v1) β€” requires an `msk_` API key; there is no x402 route**, so x402-only clients can't reach it. PRO/ULTRA only. Deployer alerts now carry `deployers.deployer_sol_balance` β€” the deployer wallet's SOL balance at alert time (null for historical rows).
19
+ >
20
+ > **New in 1.15.0** β€” **Live token snapshot + Signal Scorecard.** `rest.token(mint)` returns a live snapshot β€” price (USD/SOL), VWAP, market cap, FDV, liquidity, liquidity-to-MC ratio, primary DEX + pool, Token-2022 / transfer-fee flags, and a `top_buyers[]` array (typed `TokenSnapshotResponse`). `rest.signalPerformance(name, { history? })` returns the **Signal Scorecard** β€” out-of-sample reliability buckets (hit_rate, base_rate, lift, sample_n, window_days) for `dump_cluster_count`, `runner_rate`, `recycled_early_buyer_count`, or `coordination_count`, with a per-day `series` when `history: true` (typed `SignalPerformanceResponse`). `rest.signals()` is the free catalog of all scored signals (typed `SignalsCatalogResponse`). `rest.tokenRisk(mint)` and `rest.tokenBuyerQuality(mint)` are now fully live server-side.
21
+ >
22
+ > **New in 1.13.0** β€” **Token risk score.** `rest.tokenRisk(mint)` returns a transparent 0–100 rug-risk/safety score (higher = riskier) with a `band` (safe/caution/danger), an explainable `factors[]` array, and the raw `inputs` (mint/freeze authority, liquidity, liq-to-MC ratio, transfer fee, launch cohort, deployer bond rate, KOL signal, blacklist). Typed as `TokenRiskResponse`. PRO/ULTRA only.
23
+ >
24
+ > **New in 1.12.0** β€” `/token/{mint}` and `/token/batch` responses now include `liquidity_to_mc_ratio`, `launch_cohort_sol`, and `launch_cohort_size`. `/tokens` gains three new filter params: `min_liq_mc_ratio`, `max_liq_mc_ratio`, and `deployer_tier`. `/tokens` list items now include `liquidity_to_mc_ratio` and `deployer_tier`. `/kol/leaderboard` entries now include `median_hold_minutes_30d` and `percentile_early_entry_30d`.
25
+ >
26
+ > **New in 1.11.1** β€” Deployer profiles now carry `runner_rate` + `labeled_tokens` (fraction of a deployer's labeled tokens that ran vs dumped, gate on `labeled_tokens` β‰₯3) plus `avg_time_to_bond_minutes`, on `DeployerAlert.deployers` and the deployer-trajectory profile.
27
+ >
28
+ > **New in 1.11** β€” **Graduation events + dump-cluster detection.** Subscribe `token:graduations` for every pump.fun bond in real time (tracked deployer or not, typed `GraduationEvent`). Buyer-quality `breakdown` adds `dump_cluster_count` (out-of-sample: 3+ β†’ 94% dump vs 61% base) + `recycled_early_buyer_count`. DEX firehose: replay buffer deepened to ~5 min; mint-scoped subs get in-band `dex:graduations` frames.
29
+
30
+ > **New in 1.10** β€” **Deshred Sniper.** `rest.sniper_recent()` β€” deshred deploy feed ~500ms before on-chain confirmation. PRO: elite/good. ULTRA: all tiers + watchlist. Use `sniper:deploys` WebSocket for push.
31
+ >
32
+ > **New in 1.9** β€” **Price alerts, scout leaderboard, coordination history.** `rest.priceAlertsCreate()` (PRO=5, ULTRA=25). `scoutLeaderboard()`, `kolConsensus()`, `peakHistory()`, `coordinationHistory()`. `walletStats()` now returns `derived`: win_rate, roi, verdict, biggest_miss.
33
+ >
34
+ > **New in 1.8** β€” **Universal Wallet API.** `rest.walletStats()`, `rest.walletPnl()`, `rest.walletPositions()`, `rest.walletTrades()` β€” FIFO cost-basis PnL for any Solana wallet. PRO+. Cache hits free.
35
+ >
36
+ > **New in 1.7.1** *(2026-05-13)* β€” Velocity field shape corrected to match the API: `mc_change_pct`, `volume_usd`, `mev_volume_pct` are top-level on the token response, each keyed by `5m`/`15m`/`1h`/`2h`/`4h`. The 1.7.0 README documented a `velocity[window]` shape that didn't match the wire format. Runtime is unchanged β€” fix is to typed shape + docs.
37
+ >
38
+ > **New in 1.7.0** *(2026-05-12)* β€” **Token directory + account inspection.** `client.tokensList({ min_liq, min_volume_1h_usd, max_mev_share_pct, mc_change_1h_min_pct, sort, min_liq_mc_ratio, max_liq_mc_ratio, deployer_tier, ... })` filters every active mint by MC band, liquidity floor, primary DEX, authority/safety flags, computed 1h volume, MEV-share ceiling, MC-change deltas, liq/MC ratio, and deployer tier. Response items now include `liquidity_to_mc_ratio` and `deployer_tier`. Default `min_liq=2000` skips phantom-MC dust; pass `min_liq=0` to opt out. `client.me()` β€” read your tier, daily/burst quota state, and per-feature usage in one call (no header parsing). Velocity / MEV-share fields added to every token response: `mc_change_pct`, `volume_usd`, `mev_volume_pct` (each keyed by `5m`/`15m`/`1h`/`2h`/`4h`) plus `history_age_seconds`. `/token/{mint}` 400s now ship structured `code`, `reason`, `received_length`, `example`, and `docs` β€” stop guessing why a mint failed. Deprecated `avg_entry_mc_usd` fully removed.
39
+
40
+ ## Quick start (10 seconds)
41
+
42
+ ```bash
43
+ npm install madeonsol-x402
44
+ ```
45
+
46
+ ```ts
47
+ import { createClient } from "madeonsol-x402";
48
+ const client = createClient("msk_..."); // free tier at https://madeonsol.com/pricing
49
+ const { trades } = await client.kolFeed({ limit: 5 });
50
+ ```
51
+
52
+ ## Authentication
53
+
54
+ Two options:
55
+
56
+ | Method | Option | Best for |
57
+ |---|---|---|
58
+ | **MadeOnSol API key** (recommended) | `apiKey` | Developers β€” [get a free key](https://madeonsol.com/pricing) |
59
+ | x402 micropayments | `privateKey` | AI agents with Solana wallets |
60
+
61
+ > **v1.0 breaking change:** RapidAPI auth has been removed. The MadeOnSol RapidAPI marketplace was retired on 2026-04-19. If you were using `rapidApiKey`, get a free `msk_` key at [madeonsol.com/pricing](https://madeonsol.com/pricing).
62
+
63
+ ## Install
64
+
65
+ ```bash
66
+ npm install madeonsol-x402
67
+ ```
68
+
69
+ > x402 peer deps (`@x402/fetch @x402/svm @x402/core @solana/kit @scure/base`) are only needed when using `privateKey`.
70
+
71
+ ## Quick Start
72
+
73
+ ```ts
74
+ import { createClient } from "madeonsol-x402";
75
+
76
+ // Option 1: API key β€” get one free at madeonsol.com/pricing
77
+ const client = createClient("msk_your_api_key_here");
78
+
79
+ // Option 2: x402 micropayments (auto-detected when no msk_ prefix)
80
+ // const client = createClient(process.env.SOLANA_PRIVATE_KEY!);
81
+
82
+ const { trades } = await client.kolFeed({ limit: 10 });
83
+ console.log(trades);
84
+ ```
85
+
86
+ ### Advanced initialization
87
+
88
+ ```ts
89
+ import { MadeOnSolX402 } from "madeonsol-x402";
90
+
91
+ const client = new MadeOnSolX402({
92
+ apiKey: "msk_...", // OR
93
+ privateKey: "base58...", // x402 micropayments
94
+ });
95
+ ```
96
+
97
+ ## x402 Endpoints (per-request micropayments)
98
+
99
+ | Method | Description |
100
+ |---|---|
101
+ | `kolFeed(params?)` | Real-time KOL trade feed from 1,000+ tracked wallets |
102
+ | `kolCoordination(params?)` | Tokens being accumulated by multiple KOLs simultaneously |
103
+ | `kolLeaderboard(params?)` | KOL performance rankings by PnL and win rate (180 days of trade history) |
104
+ | `kolPairs(params?)` | KOL affinity matrix β€” which KOLs frequently co-trade the same tokens |
105
+ | `kolHotTokens(params?)` | KOL momentum tokens β€” accelerating KOL buy interest |
106
+ | `kolTokenEntryOrder(mint, params?)` | Ranked KOL first-buyer order for a token |
107
+ | `kolCompareWallets({ wallets })` | Side-by-side comparison of 2–5 KOL wallets |
108
+ | `kolAlertsRecent(params?)` | Live KOL alert feed β€” clusters, fresh-token buys, heating-up wallets |
109
+ | `deployerAlerts(params?)` | Pump.fun deployer alerts with KOL enrichment. PRO/ULTRA: filter by tier. |
110
+ | `walletStats(address)` | **New 1.8** Β· Wallet stats + cross-product flags (is_kol / is_alpha_tracked + bot_confidence / is_deployer). 90-day window. **$0.005** |
111
+ | `walletPnl(address)` | **New 1.8** Β· FIFO cost-basis PnL: realized + unrealized SOL, profit factor, drawdown, hold times, daily curve, closed + open positions. **$0.02** |
112
+ | `walletPositions(address)` | **New 1.8** Β· Open positions only, live unrealized from market-cap tracker. Shares /pnl cache. **$0.01** |
113
+ | `walletTrades(address, params?)` | **New 1.8** Β· Cursor-paginated raw trades with action / token / since-until filters. **$0.005** |
114
+ | `tokenFlow(mint, params?)` | **New 1.16** Β· Trade-flow aggregate (organic-vs-fake volume) β€” unique wallets/buyers/sellers, buy/sell counts + SOL, net SOL, `trades_per_wallet` wash-trading proxy. `window` ("1h" \| "24h", default "1h"). **KEYED (v1) β€” needs an `msk_` API key, no x402 route.** PRO/ULTRA |
115
+ | `discovery()` | Lists all endpoints, prices, and parameter docs (free) |
116
+
117
+ ## REST API client
118
+
119
+ The `MadeOnSolREST` class exposes the full v1 API (alpha intelligence, token quality, copy-trade rules, wallet tracker, webhooks, streaming). Most endpoints require a Pro or Ultra subscription.
120
+
121
+ ```ts
122
+ import { MadeOnSolREST } from "madeonsol-x402";
123
+
124
+ const rest = new MadeOnSolREST({ apiKey: "msk_your_key" });
125
+ const { leaderboard } = await rest.alphaLeaderboard({ period: "30d", sort: "win_rate" });
126
+
127
+ // Rate-limit headers from the most recent response
128
+ console.log(rest.lastRateLimit); // { limit, remaining, reset, requestId }
129
+ ```
130
+
131
+ ### Alpha wallet intelligence
132
+
133
+ Scored from 1M+ early-buyer records (wallets seen in the first 20 buyers of Pump.fun tokens).
134
+
135
+ | Method | Tier | Description |
136
+ |---|---|---|
137
+ | `rest.alphaLeaderboard(params?)` | All | Top profitable wallets. Up to 100 on Free/Pro; ULTRA unlocks 500 + bot signals |
138
+ | `rest.alphaWallet(wallet)` | ULTRA | Full per-token breakdown + bot_signals array |
139
+ | `rest.alphaLinked(wallet)` | ULTRA | Wallets behaviorally linked (co-bought 3+ tokens within 2s) |
140
+
141
+ **alphaLeaderboard params** β€” `period` ("7d" \| "30d" \| "all"), `min_tokens` (1–20), `sort` ("win_rate" \| "pnl" \| "roi"), `exclude_bots` ("true" \| "false")
142
+
143
+ ### Token quality
144
+
145
+ | Method | Tier | Description |
146
+ |---|---|---|
147
+ | `rest.token(mint)` | All | **New 1.15** Β· Live token snapshot β€” price (USD/SOL), VWAP, market cap, FDV, liquidity, liq-to-MC ratio, primary DEX + pool, Token-2022 / transfer-fee flags, and `top_buyers[]`. Returns `{ token }` |
148
+ | `rest.tokenCapTable(mint)` | PRO+ | First non-deployer early buyers, enriched with PnL/KOL/bot flags. PRO=10, ULTRA=20 |
149
+ | `rest.tokenBuyerQuality(mint)` | All | 0–100 buyer-quality score + full breakdown (5-min cached). Live server-side |
150
+ | `rest.tokenRisk(mint)` | PRO+ | Transparent 0–100 rug-risk/safety score with `band`, explainable `factors[]`, and raw `inputs`. Live server-side |
151
+ | `rest.tokensBatchRisk(mints)` | PRO+ | **New 1.18** Β· Bulk risk scoring β€” up to 50 mints in one call (counts as 1 request). Each `tokens[]` entry is a full risk result or `{ mint, error: "not_tracked" }`; untracked mints don't fail the batch |
152
+ | `rest.tokenCandles(mint, params?)` | PRO+ | OHLC candles. PRO = OHLCV, last 30 days; ULTRA = + net flow (buy/sell volume, `net_volume_usd`, counts, MEV vol), liquidity delta, full history |
153
+
154
+ **tokenCandles params** β€” `tf` ("1m" \| "5m" \| "15m" \| "1h" \| "4h" \| "1d", default "1h"), `limit` (1–1000, default 200), `from` (ISO 8601), `to` (ISO 8601)
155
+
156
+ ```ts
157
+ // Score a basket in one request (counts as 1 against quota)
158
+ const { tokens, count } = await rest.tokensBatchRisk([mintA, mintB, mintC]);
159
+ for (const t of tokens) {
160
+ if ("error" in t) console.log(t.mint, t.error); // e.g. "not_tracked"
161
+ else console.log(t.mint, t.risk_score, t.band); // full risk result + as_of
162
+ }
163
+ ```
164
+
165
+ ### Signal Scorecard *(new in 1.15)*
166
+
167
+ Out-of-sample reliability for the scored early-buyer / coordination signals β€” every claim is backed by a hit-rate vs base-rate measurement so you can size positions on evidence, not vibes.
168
+
169
+ | Method | Tier | Description |
170
+ |---|---|---|
171
+ | `rest.signals()` | All (free) | Catalog of scored signals β€” name, methodology, and each signal's `performance_endpoint`. No payment required |
172
+ | `rest.signalPerformance(name, params?)` | All | Signal Scorecard for one signal β€” `buckets[]` (hit_rate, base_rate, lift, sample_n, window_days, test_from/test_to) + metric_type, outcome, methodology, as_of. Pass `{ history: true }` for a per-day `series[]` |
173
+
174
+ Valid signal names: `dump_cluster_count`, `runner_rate`, `recycled_early_buyer_count`, `coordination_count`.
175
+
176
+ ```ts
177
+ const { signals } = await rest.signals();
178
+ const scorecard = await rest.signalPerformance("dump_cluster_count", { history: true });
179
+ console.log(scorecard.buckets); // [{ bucket, hit_rate, base_rate, lift, sample_n, ... }]
180
+ ```
181
+
182
+ ### KOL coordination alerts (v1.1 β€” push signals)
183
+
184
+ Real-time push alerts when a cluster of KOLs co-buys the same token. Fires within ~1s of the triggering trade (pg_notify push, not polling). Delivered via WebSocket (`kol:coordination` channel, user-scoped) and/or HMAC-signed webhook. PRO=5 rules, ULTRA=20.
185
+
186
+ ```ts
187
+ // Create a rule
188
+ const { rule, webhook_secret } = await rest.coordinationAlertsCreate({
189
+ name: "fresh pump cluster",
190
+ min_kols: 4, // minimum distinct KOLs in window
191
+ window_minutes: 15, // peak-density window (1-60)
192
+ min_score: 70, // 0-100 composite score cutoff
193
+ include_majors: false, // filter WIF/BONK/POPCAT
194
+ cooldown_min: 60, // one fire per (rule,token) per 60min...
195
+ score_jump_break: 10, // ...unless score jumps +10 vs last fire
196
+ delivery_mode: "both",
197
+ webhook_url: "https://you.com/hooks/coord",
198
+ });
199
+ // β†’ store webhook_secret β€” shown ONCE
200
+ ```
201
+
202
+ `coordinationAlertsList`, `coordinationAlertsGet(id)`, `coordinationAlertsUpdate(id, params)`, `coordinationAlertsDelete(id)` round out the CRUD.
203
+
204
+ **Webhook signature:** `X-MadeOnSol-Signature: sha256=<hmac>` where `hmac = HMAC-SHA256(webhook_secret, timestamp + "." + rawBody)`, and `X-MadeOnSol-Timestamp` carries the unix seconds used.
205
+
206
+ **The `kolCoordination()` response** now includes v1.1 fields: `peak_window_start/end`, `peak_kols`, `peak_buys` (the busiest slice within the period), `exited_count` + per-KOL `exited` flag (net-flow-negative wallets), and `coordination_score` (0-100). Pass `min_score`, `window_minutes`, `include_majors` to filter.
207
+
208
+ ### KOL first-touch signal *(new in 1.3)*
209
+
210
+ Every "first KOL buy on a token mint" event β€” the moment a tracked KOL is the first of the cohort to touch a token. Filterable by **scout tier** (S/A/B/C from `mv_kol_scout_score`), KOL winrate, token age, mint suffix.
211
+
212
+ **Backtest:** top scouts attract β‰₯3 follow-on KOLs within 4h ~50% of the time vs ~14% baseline (38d / 491k buys / 72,549 events). Live leaderboard at [madeonsol.com/kol/scouts](https://madeonsol.com/kol/scouts).
213
+
214
+ ```ts
215
+ import { MadeOnSolREST } from "madeonsol-x402";
216
+ const rest = new MadeOnSolREST({ apiKey: process.env.MADEONSOL_API_KEY! });
217
+
218
+ // S-tier scouts on tokens younger than 1h
219
+ const { events } = await rest.firstTouches({ preset: "scout", min_scout_tier: "S" });
220
+
221
+ for (const e of events) {
222
+ console.log(e.first_kol.name, "scouted", e.token_symbol, `(scout_score=${e.first_kol.scout_score}%)`);
223
+ }
224
+ ```
225
+
226
+ Filter knobs: `since`, `before`, `limit`, `kol`, `min_kol_winrate_7d`, `min_scout_tier` (`"S"|"A"|"B"|"C"`), `min_n_touches`, `strategy`, `token_age_max_min`, `min_first_buy_sol`, `mint_suffix` (`"pump"`, `"bonk"`, …), `preset` (`"scout"`/`"fresh_launch"`), `include` (`"followers_4h"`).
227
+
228
+ > **Don't poll β€” push.** Median lead time before the second KOL is **12 seconds**. REST polling will miss the swarm. Subscribe to the `kol:first_touches` WebSocket channel (PRO+) or, on Ultra, create an HMAC-signed webhook subscription.
229
+
230
+ **Webhook subscriptions (Ultra)** β€” up to 10 active per user, mirrors `coordinationAlerts`:
231
+
232
+ ```ts
233
+ const { subscription, webhook_secret } = await rest.firstTouchSubscriptionsCreate({
234
+ name: "S-tier scouts on pump tokens",
235
+ filters: { min_scout_tier: "S", mint_suffix: "pump" },
236
+ delivery_mode: "webhook",
237
+ webhook_url: "https://my.bot/hooks/scout",
238
+ });
239
+ // β†’ store webhook_secret β€” shown ONCE
240
+ ```
241
+
242
+ `firstTouchSubscriptionsList`, `firstTouchSubscriptionsGet(id)`, `firstTouchSubscriptionsUpdate(id, params)`, `firstTouchSubscriptionsDelete(id)` round out the CRUD.
243
+
244
+ ### Price alerts *(new in 1.9)*
245
+
246
+ CRUD for token dip/recovery price alerts. Fires via WebSocket (`price:alerts` channel) and/or HMAC-signed webhook when a token's market cap crosses your threshold. PRO=5 rules, ULTRA=25.
247
+
248
+ ```ts
249
+ const { alert, webhook_secret } = await rest.priceAlertsCreate({
250
+ name: "SOL dip buy",
251
+ token_mint: "So11111111111111111111111111111111111111112",
252
+ condition: "below", // "below" | "above"
253
+ threshold_mc_usd: 5_000_000_000,
254
+ cooldown_min: 120,
255
+ delivery_mode: "both",
256
+ webhook_url: "https://you.com/hooks/price",
257
+ });
258
+ // β†’ store webhook_secret β€” shown ONCE
259
+ ```
260
+
261
+ `priceAlertsList`, `priceAlertsGet(id)`, `priceAlertsUpdate(id, params)`, `priceAlertsDelete(id)` round out the CRUD.
262
+
263
+ ### Scout leaderboard & KOL consensus *(new in 1.9)*
264
+
265
+ | Method | Tier | Description |
266
+ |---|---|---|
267
+ | `rest.scoutLeaderboard(params?)` | PRO+ | Top scout-tier KOLs ranked by first-touch follow-on rate, win rate, and ROI |
268
+ | `rest.kolConsensus(params?)` | PRO+ | Tokens with the strongest KOL agreement signal β€” weighted by scout score and recent PnL |
269
+ | `rest.peakHistory(mint)` | PRO+ | Historical peak-density windows for a token β€” every coordination spike with KOL breakdown |
270
+ | `rest.coordinationHistory(params?)` | PRO+ | Global coordination event log with token, KOL count, score, and outcome |
271
+
272
+ ```ts
273
+ const { leaderboard } = await rest.scoutLeaderboard({ period: "30d", limit: 25 });
274
+ const { tokens } = await rest.kolConsensus({ min_kols: 5, period: "24h" });
275
+ ```
276
+
277
+ ### Wallet derived stats *(new in 1.9)*
278
+
279
+ `walletStats(address)` now includes a `stats` object with derived fields computed from the 90-day trade window:
280
+
281
+ ```ts
282
+ const { stats } = await rest.walletStats("WALLET_ADDRESS");
283
+ // stats.win_rate β€” fraction 0-1, tokens sold above cost basis
284
+ // stats.roi β€” aggregate return on invested SOL
285
+ // stats.verdict β€” "strong" | "profitable" | "neutral" | "losing"
286
+ // stats.biggest_miss β€” token with the highest post-exit gain the wallet missed
287
+ ```
288
+
289
+ ### Copy-trade rules
290
+
291
+ Server-side rules that fire signals when one of your watched source wallets trades. Delivered via webhook (HMAC-signed) and/or WebSocket. PRO=3 rules Γ— 5 source wallets each; ULTRA=20 Γ— 50.
292
+
293
+ | Method | Description |
294
+ |---|---|
295
+ | `rest.copyTradeList()` | List your rules |
296
+ | `rest.copyTradeCreate(params)` | Create a rule. Returns `webhook_secret` **once** β€” store it |
297
+ | `rest.copyTradeGet(id)` | Get one rule |
298
+ | `rest.copyTradeUpdate(id, params)` | Update fields or toggle `is_active` |
299
+ | `rest.copyTradeDelete(id)` | Delete permanently |
300
+ | `rest.copyTradeSignals(params?)` | Recent fired signals (up to 7 days). Filter by `subscription_id`, `since`, `limit` (1–500) |
301
+
302
+ ### Wallet tracker
303
+
304
+ Per-account watchlist with historical swap/transfer history.
305
+
306
+ | Method | Description |
307
+ |---|---|
308
+ | `rest.walletTrackerList()` | List tracked wallets + remaining capacity |
309
+ | `rest.walletTrackerAdd(wallet, label?)` | Add a wallet |
310
+ | `rest.walletTrackerRemove(wallet)` | Remove a wallet |
311
+ | `rest.walletTrackerUpdateLabel(wallet, label)` | Update label (pass `null` to clear) |
312
+ | `rest.walletTrackerTrades(params?)` | Historical events. Params: `wallet`, `action`, `event_type`, `limit` (1–200), `before` (cursor) |
313
+ | `rest.walletTrackerSummary(params?)` | Per-wallet stats. Params: `period` ("24h" \| "7d" \| "30d"), `wallet` |
314
+ | `rest.walletStats(address)` | **New 1.8** Β· Universal wallet stats (90d) + cross-product flags. PRO+. |
315
+ | `rest.walletPnl(address)` | **New 1.8** Β· Full FIFO PnL + curve + closed/open positions. PRO+. |
316
+ | `rest.walletPositions(address)` | **New 1.8** Β· Open positions only with live unrealized. PRO+. |
317
+ | `rest.walletTrades(address, params?)` | **New 1.8** Β· Cursor-paginated raw trades. Params: `limit` (1-500), `cursor`, `action`, `token_mint`, `since`, `until`. PRO+. |
318
+
319
+ ### Webhooks
320
+
321
+ | Method | Description |
322
+ |---|---|
323
+ | `rest.createWebhook(params)` | Create webhook. Returns `secret` once β€” store it for HMAC verification |
324
+ | `rest.listWebhooks()` | List your webhooks |
325
+ | `rest.getWebhook(id)` | Get one + recent delivery log |
326
+ | `rest.updateWebhook(id, params)` | Update URL, events, filters, or re-enable |
327
+ | `rest.deleteWebhook(id)` | Delete |
328
+ | `rest.testWebhook(id)` | Send test payload |
329
+
330
+ ### KOL/deployer detail
331
+
332
+ | Method | Description |
333
+ |---|---|
334
+ | `rest.kolTiming(wallet, params?)` | Entry/exit timing β€” hold duration, exit speed, hour distribution |
335
+ | `rest.kolPnl(wallet, params?)` | Per-wallet PnL breakdown |
336
+ | `rest.deployerTrajectory(wallet)` | Deployer skill curve β€” streaks, rolling bond rate, trend |
337
+
338
+ ### Streaming token
339
+
340
+ ```ts
341
+ const token = await rest.getStreamToken();
342
+ // token.ws_url β€” KOL/deployer streaming (Pro/Ultra)
343
+ // token.dex_ws_url β€” all-DEX trade stream (Ultra only)
344
+ ```
345
+
346
+ ### Managed streaming client *(new in 1.10)*
347
+
348
+ `rest.stream()` handles the token fetch + 24h refresh, auto-reconnect (backoff + jitter), heartbeat liveness, and typed events β€” just subscribe and listen.
349
+
350
+ ```ts
351
+ const stream = rest.stream();
352
+ stream.on("kol:trade", (t) => console.log(t.token_symbol, t.action));
353
+ stream.on("deployer:alert", (a) => console.log("new deploy", a.token_mint));
354
+ stream.subscribe(["kol:trades", "deployer:alerts"]);
355
+ // stream.unsubscribe([...]) / stream.close() when done
356
+ ```
357
+
358
+ 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`). Lifecycle events: `open`, `close`, `reconnect`, `heartbeat`, `error`. Uses the global `WebSocket` on Node 22+; on Node < 22 also `npm i ws`.
359
+
360
+ ### Live stream sessions *(new in 1.18)*
361
+
362
+ List and force-release the connection slots your key currently holds across both stream services (ws-streaming + dex-stream). Reflects in-memory state, so every listed slot is evictable β€” the self-serve fix when a deploy overlap leaves a ghost socket holding your slot and reconnects hit the 4002 connection limit. PRO/ULTRA only.
363
+
364
+ | Method | Tier | Description |
365
+ |---|---|---|
366
+ | `rest.streamSessions()` | PRO+ | List your live sessions β€” each with `id`, `service`, `tier`, `channels[]`, `connected_at`, `remote_ip`, `messages_sent`. Typed `StreamSessionsResponse` |
367
+ | `rest.streamSessionKill(id)` | PRO+ | Terminate one of your sessions by `id` and free its slot. Throws on a bad id (400) or no matching live session (404). Typed `StreamSessionEvictResponse` |
368
+
369
+ ```ts
370
+ const { sessions } = await rest.streamSessions();
371
+ for (const s of sessions) console.log(s.id, s.service, s.channels, s.messages_sent);
372
+
373
+ // Free a stuck slot after a deploy overlap
374
+ if (sessions.length) await rest.streamSessionKill(sessions[0].id); // { evicted: true, id }
375
+ ```
376
+
377
+ ## DEX Firehose (Ultra)
378
+
379
+ Connect to `dex_ws_url` and use the multi-subscription protocol β€” up to **10 named subs per connection**, each with its own `sub_id`, server-side filters, and optional replay (up to 500 most recent matching trades) from a server-side buffer holding ~5 minutes of firehose history β€” it backfills trades from before your connection existed. Replayed trades arrive newest-first flagged `"replay": true`, then a `replay_done` frame; sort by `block_time` client-side.
380
+
381
+ ```ts
382
+ import WebSocket from "ws";
383
+
384
+ const { token, dex_ws_url } = await rest.getStreamToken();
385
+ const ws = new WebSocket(`${dex_ws_url}?token=${token}`); // token MUST be in the query string
386
+
387
+ ws.on("open", () => {
388
+ ws.send(JSON.stringify({
389
+ type: "subscribe",
390
+ sub_id: "fresh-pumpfun",
391
+ replay: 50, // up to 500 from ring buffer
392
+ filters: {
393
+ dex: "pumpfun", // pumpfun | pumpamm | pumpswap | raydium | jupiter | orca | meteora | launchlab
394
+ token_age_max_seconds: 300,
395
+ min_sol: 0.5,
396
+ action: "buy",
397
+ },
398
+ }));
399
+ });
400
+
401
+ ws.on("message", (raw) => {
402
+ const msg = JSON.parse(raw.toString());
403
+ if (msg.channel === "dex:trades") {
404
+ // { sub_id, data: { wallet, mint, action, sol_amount, dex, ... }, replay, ts }
405
+ }
406
+ });
407
+ ```
408
+
409
+ **Operations** (all carry `sub_id`): `subscribe`, `update` (replace filters in place), `unsubscribe`, `list`, `ping`. **Filters:** `token_mint(s)` (≀50), `wallet(s)` (≀50), `dex`, `program`, `deployer_tier`, `token_age_max_seconds`, `market_cap_min/max_sol`, `min_sol`, `max_sol`, `action`. At least one targeting filter is required. Inbound rate limit: 5 messages/sec.
410
+
411
+ Full protocol reference: [madeonsol.com/api-docs#streaming](https://madeonsol.com/api-docs#streaming).
412
+
413
+ ## Rate-limit headers
414
+
415
+ Every successful REST response carries `X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset`, and `X-Request-Id`. The SDK exposes them via `rest.lastRateLimit`:
416
+
417
+ ```ts
418
+ await rest.alphaLeaderboard();
419
+ const { limit, remaining, reset, requestId } = rest.lastRateLimit;
420
+ if (remaining !== null && remaining < 5) {
421
+ console.warn(`Throttle warning β€” ${remaining}/${limit} requests left until ${reset}`);
422
+ }
423
+ ```
424
+
425
+ ## Discovery
426
+
427
+ ```ts
428
+ const info = await client.discovery();
429
+ console.log(info.endpoints); // all endpoints with prices and params
430
+ ```
431
+
432
+ Docs: [madeonsol.com/solana-api](https://madeonsol.com/solana-api)
433
+
434
+ ## Also Available
435
+
436
+ | Platform | Package |
437
+ |---|---|
438
+ | TypeScript SDK | [`madeonsol`](https://www.npmjs.com/package/madeonsol) on npm |
439
+ | Rust SDK | [`madeonsol`](https://crates.io/crates/madeonsol) on crates.io |
440
+ | Python (LangChain, CrewAI) | [`madeonsol-x402`](https://pypi.org/project/madeonsol-x402/) on PyPI |
441
+ | MCP Server (Claude, Cursor) | [`mcp-server-madeonsol`](https://www.npmjs.com/package/mcp-server-madeonsol) Β· [Smithery](https://smithery.ai/servers/madeonsol/solana-kol-intelligence) Β· [Glama](https://glama.ai/mcp/servers/LamboPoewert/mcp-server-madeonsol) |
442
+ | ElizaOS | [`@madeonsol/plugin-madeonsol`](https://www.npmjs.com/package/@madeonsol/plugin-madeonsol) |
443
+ | Solana Agent Kit | [`solana-agent-kit-plugin-madeonsol`](https://www.npmjs.com/package/solana-agent-kit-plugin-madeonsol) |