madeonsol-x402 1.25.0 β 1.27.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 +481 -471
- package/dist/index.d.ts +121 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +139 -0
- package/dist/index.js.map +1 -1
- package/dist/stream.d.ts +2 -2
- package/dist/stream.d.ts.map +1 -1
- package/dist/stream.js.map +1 -1
- package/dist/types.d.ts +609 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +76 -76
package/README.md
CHANGED
|
@@ -1,471 +1,481 @@
|
|
|
1
|
-
# madeonsol-x402
|
|
2
|
-
|
|
3
|
-
[](https://www.npmjs.com/package/madeonsol-x402)
|
|
4
|
-
[](https://www.npmjs.com/package/madeonsol-x402)
|
|
5
|
-
[](https://www.typescriptlang.org/)
|
|
6
|
-
[](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), read bundle-cohort holdings (`held_pct_of_supply` β are the bundlers still holding?), verify any wallet's current on-chain holdings (with airdrop/insider `transfer_delta` 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.
|
|
15
|
-
|
|
16
|
-
> **New in 1.
|
|
17
|
-
|
|
18
|
-
> **New in 1.
|
|
19
|
-
|
|
20
|
-
> **New in 1.
|
|
21
|
-
|
|
22
|
-
> **New in 1.
|
|
23
|
-
>
|
|
24
|
-
> **New in 1.
|
|
25
|
-
>
|
|
26
|
-
> **New in 1.
|
|
27
|
-
>
|
|
28
|
-
> **New in 1.
|
|
29
|
-
>
|
|
30
|
-
> **New in 1.
|
|
31
|
-
>
|
|
32
|
-
> **New in 1.
|
|
33
|
-
>
|
|
34
|
-
> **New in 1.
|
|
35
|
-
>
|
|
36
|
-
> **New in 1.
|
|
37
|
-
>
|
|
38
|
-
> **New in 1.
|
|
39
|
-
>
|
|
40
|
-
> **New in 1.
|
|
41
|
-
>
|
|
42
|
-
> **New in 1.
|
|
43
|
-
|
|
44
|
-
> **New in 1.
|
|
45
|
-
>
|
|
46
|
-
> **New in 1.
|
|
47
|
-
|
|
48
|
-
> **New in 1.
|
|
49
|
-
>
|
|
50
|
-
> **New in 1.
|
|
51
|
-
>
|
|
52
|
-
> **New in 1.
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
```
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
```
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
//
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
```
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
|
118
|
-
|
|
119
|
-
| `
|
|
120
|
-
| `
|
|
121
|
-
| `
|
|
122
|
-
| `
|
|
123
|
-
| `
|
|
124
|
-
| `
|
|
125
|
-
| `
|
|
126
|
-
| `
|
|
127
|
-
| `
|
|
128
|
-
| `
|
|
129
|
-
| `
|
|
130
|
-
| `
|
|
131
|
-
| `
|
|
132
|
-
| `
|
|
133
|
-
| `
|
|
134
|
-
| `
|
|
135
|
-
| `
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
|
170
|
-
|
|
171
|
-
| `rest.
|
|
172
|
-
| `rest.
|
|
173
|
-
| `rest.
|
|
174
|
-
| `rest.
|
|
175
|
-
| `rest.
|
|
176
|
-
| `rest.
|
|
177
|
-
| `rest.
|
|
178
|
-
| `rest.
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
```ts
|
|
213
|
-
|
|
214
|
-
const
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
}
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
```
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
`
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
|
333
|
-
|
|
334
|
-
| `rest.
|
|
335
|
-
| `rest.
|
|
336
|
-
| `rest.
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
|
343
|
-
|
|
344
|
-
| `rest.
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
|
349
|
-
|
|
350
|
-
| `rest.
|
|
351
|
-
| `rest.
|
|
352
|
-
| `rest.
|
|
353
|
-
| `rest.
|
|
354
|
-
| `rest.
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
| `rest.
|
|
362
|
-
| `rest.
|
|
363
|
-
| `rest.
|
|
364
|
-
| `rest.
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
```ts
|
|
379
|
-
const
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
```
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
```ts
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
1
|
+
# madeonsol-x402
|
|
2
|
+
|
|
3
|
+
[](https://www.npmjs.com/package/madeonsol-x402)
|
|
4
|
+
[](https://www.npmjs.com/package/madeonsol-x402)
|
|
5
|
+
[](https://www.typescriptlang.org/)
|
|
6
|
+
[](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), read bundle-cohort holdings (`held_pct_of_supply` β are the bundlers still holding?), verify any wallet's current on-chain holdings (with airdrop/insider `transfer_delta` 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.27.0 β token locks & vesting, upcoming unlocks, and pump.fun creator-fee sharing / fee claims β five endpoints + two live channels.** `rest.tokenLocks(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). `rest.tokenLocksFeed(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`). `rest.tokenUnlocks(params?)` (`GET /tokens/unlocks`) lists upcoming unlock EVENTS (cliff / period / final / tranche) inside `within=1hβ¦90d` with `window_amount_*` per contract. `rest.tokenFeeShares(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; `rest.tokenFeeClaims(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+** and **KEYED (v1) only β `msk_` API key, no x402 route.**
|
|
15
|
+
|
|
16
|
+
> **New in 1.26.0 β live holder census: exact holder count, labelled holders, and pools that are named, not just excluded.** `rest.tokenHolders(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. **KEYED (v1) β requires an `msk_` API key; the census is not on the x402 rail.**
|
|
17
|
+
|
|
18
|
+
> **New in 1.25.0 β two prices on the trade tape, and the right one is now the default.** The trade tape now tells you what a trade actually cost. `price_sol`/`price_usd` on each trade are THIS trade's executed price β `sol_amount / token_amount`, reconciling exactly with the amounts on the same row and with the PnL endpoints. Because `sol_amount` is the wallet's net SOL movement, that is the trader's all-in effective rate: swap fee and any account rent included, not the pool mid. The market-cap tracker's canonical pool price moved to the new **`market_price_sol`/`market_price_usd`** fields β it is sampled once per token per pool update, so every trade in the same slot shares it. Until now `price_sol` carried that canonical value and disagreed with the row's own amounts by a **7.9% median** (p90 ~74%): a stale market price reads low in a pump and high in a dump, so anything you averaged out of the tape inherited the bias instead of cancelling it. Use `price_sol` for cost basis, fills and PnL; `market_price_sol` for a per-token series independent of trade size and direction. Both `rest.tokenTrades(mint)` and `rest.walletTrades(address)` carry all four fields (typed on `TokenTrade` / `WalletTrade`) β `walletTrades` returned amounts and no price at all before.
|
|
19
|
+
|
|
20
|
+
> **New in 1.24.0 β the Deployer Hunter surface completed.** Seven new operations that existed on the API but had no SDK binding: `deployerLeaderboard()`, `deployerStats()`, `deployerProfile()`, `deployerTokens()`, `deployerAlertStats()`, `deployerBestTokens()` and `deployerRecentBonds()` (poll it incrementally with `next_since`). Read `bonding_rate` (lifetime) against `recent_bond_rate` (rolling) β the gap between them is the signal, not either number alone. `runner_rate` only means something once `labeled_tokens >= 3`, and an **untracked wallet returns a profile with zeroed counters, not a 404**, so check `total_deployed` before reading a 0% bond rate as a track record. Dependency ranges are now bounded to the versions actually tested (`@x402/*` `^2.x`, `@solana/kit` `^5.5.1`) instead of open-ended `>=0.0.1`, and the lazily-imported x402 peers are marked optional β a keyed install no longer pulls the whole Solana stack.
|
|
21
|
+
|
|
22
|
+
> **New in 1.23.0** β **Clean stream shutdown.** `rest.stream().close()` now fully tears down the underlying WebSocket so short-lived scripts exit promptly instead of hanging on a lingering socket. In Node the client now prefers the `ws` package (which exposes `terminate()`) and hard-terminates on close; the browser still uses the native WebSocket. No API changes β purely a lifecycle fix. (If you don't already depend on `ws` and want the fast exit on Node β₯22, `npm i ws`.)
|
|
23
|
+
>
|
|
24
|
+
> **New in 1.22.0** β **Token depth / price impact + deployer self-activity on risk.** `rest.tokenDepth(mint, { sizes? })` (`GET /tokens/{mint}/depth`, PRO+) answers "how much SOL moves this token's price N%" β per pool, not router-optimal. Pass up to 8 SOL buy `sizes` (each >0 and β€10000; default `[0.5, 1, 5, 10]`, sent as a CSV `sizes` param); every computable pool returns `spot_price_sol`, `fee_pct`, a `quotes[]` entry per size (`tokens_out`, `avg_price_sol`, `price_impact_pct`), and `to_move_price` β the SOL required to move price **1% / 5% / 10%**. Constant-product AMMs are served from stream reserves (`source: "stream"` with `reserves_age_ms`); pump.fun/bonk curves from a **live** read of the curve's virtual reserves (`source: "live_rpc"`). Pools we can't price honestly β concentrated CLMM/Orca/DLMM, Meteora-DBC curves, unclassified models β come back in `unsupported_pools[]` with a `reason` (e.g. `concentrated_liquidity_depth_not_supported`, `curve_graduated_use_amm_pool`) rather than a wrong number; `primary_pool` names the deepest computable pool and `found: false` means no pools are tracked at all. Typed `TokenDepthResponse` (+ `TokenDepthParams`, `TokenDepthPool`, `TokenDepthQuote`, `TokenDepthToMovePrice`, `TokenDepthUnsupportedPool`). **KEYED (v1) β requires an `msk_` API key; there is no x402 route.** And `rest.tokenRisk(mint)` now returns a top-level **`dev` block** (typed `TokenRiskDev | null`) β the deployer's self-activity on its own mint: the create-tx self-buy snapshot (`buy_sol`, `buy_tokens`, `buy_supply_pct`), the post-create rollup (`bought_tokens_after` β catches the same-second-separate-tx dev buy the create snapshot reads as 0 β `sold_tokens`, `sold_sol`, `first_sell_at`/`last_sell_at`), **live on-chain holdings** (`holdings_tokens`, `holdings_supply_pct` β pump.fun 1B denominator, null elsewhere β and `wallet_empty`: is the dev wallet empty NOW), and `transferred_out` (tokens left without a sell; `null` = unknown when trade coverage or rollup freshness can't prove it β never a guess). `dev` is `null` when the mint has no pending_deploys row; the response also carries `as_of`. `deployer:alert` webhook/WS payloads gain `dev_buy_sol` + `dev_buy_supply_pct` β the dev's self-buy visible at alert time.
|
|
25
|
+
>
|
|
26
|
+
> **New in 1.21.0** β **Wallet batch classify, token trade tape, sniper footprint, and 7 new x402-payable endpoints.** `rest.walletClassify(wallets)` (`POST /wallet/batch/classify`, 1β100 addresses, PRO+) returns bulk reputation flags per wallet: `is_sniper`, `is_bundler` (lifetime), `is_dumper` (rolling 42d), `is_kol` + `kol_name`, `bot_confidence`, and `dump_cluster` cohort stats (typed `WalletBatchClassifyResponse`) β flags are pump.fun-pipeline scoped (`false` = not observed, NOT verified clean). `rest.tokenTrades(mint, params?)` (`GET /tokens/{mint}/trades`, PRO+) is the mint-scoped trade tape β cursor-paginated raw trades with `price_sol`/`price_usd`/`early_buyer_rank`/`slot`, filterable by `action`/`wallet`/`since`/`until`, defaulting to the **full history** (starts 2026-04-12; the `coverage` block carries `history_start` + `scope`). `rest.tokenTopTraders(mint, params?)` and `rest.sniperRecent(params?)` are new keyed methods too. The wallet profile `flags` block gains the same `is_sniper`/`is_bundler`/`is_dumper` + `dump_cluster` fields, and **`bot_confidence` is a type fix**: previously typed `number | null` but the API always returned `null` due to a bug β it now returns the real value as a string enum `"none" | "low" | "medium" | "high" | null`. `TokenRiskInputs` gains `sniper_footprint` (slot-window snipe rollup, `SniperFootprint | null`) and sniper deploys each carry the same `footprint` block. **x402 catalog grew 18 β 25**: `tokenCandles` ($0.01), `almostBonded` ($0.01), `tokenTopTraders` ($0.02), `tokenCapTable` ($0.02), `sniperRecent` ($0.01), `tokenFlow` ($0.01 β the 1.16 keyed-only guard is gone), and `deployerTrajectory` ($0.01) are now callable on the `MadeOnSolX402` client with per-request USDC micropayments. New types: `WalletClassification`, `WalletBatchClassifyResponse`, `TokenTradesParams`, `TokenTrade`, `TokenTradesResponse`, `TokenTopTradersParams`, `TokenTopTrader`, `TokenTopTradersResponse`, `SniperRecentParams`, `SniperDeploy`, `SniperRecentResponse`, `SniperFootprint`, `DumpClusterStats`.
|
|
27
|
+
>
|
|
28
|
+
> **New in 1.20.0** β **Verified wallet holdings.** `rest.walletHoldings(wallet, { limit?, min_value_usd? })` reads the wallet's actual current SPL + Token-2022 token accounts and SOL balance straight from chain, enriches each with our price/MC/name/symbol, and computes a `transfer_delta` (on-chain amount β trade-derived net position) β exposing tokens that arrived or left **without a swap** (airdrops, insider funding, wallet-hopping). Distinct from `walletPositions` (trade-derived FIFO): holdings is "what they actually hold right now". Returns typed `WalletHoldingsResponse` with a `summary` (token_accounts / non_zero / returned / priced / total_value_usd / truncated) and `verified_at`. **KEYED (v1) β requires an `msk_` API key; there is no x402 route.** ULTRA only.
|
|
29
|
+
>
|
|
30
|
+
> **New in 1.19.0** β **Bundle-cohort holdings.** `rest.tokenBundle(mint)` returns the bundle wallets' current position for a token β the "are the bundlers still holding, or did they dump on you?" read. The `bundle` block carries `wallet_count`, `bundle_kind` (`atomic_tx` / `same_slot` / `none`), `held_ratio` (net held / buy volume β churn-sensitive secondary), **`held_pct_of_supply`** (net held / circulating supply β the headline signal; null when supply is unknown), `fully_exited`, `buy_volume`, and `tokens_held` (typed `TokenBundleResponse`). Field-gated by tier: BASIC get the `bundle` block only (`wallets: []`); PRO adds the top-10 `wallets` with flags (`has_sold`, `atomic`, `is_kol`); ULTRA returns the full cohort plus per-wallet identity (`kol_name`, `win_rate`, `bot_confidence`, `tokens_held`). All tiers reach it.
|
|
31
|
+
>
|
|
32
|
+
> **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.
|
|
33
|
+
>
|
|
34
|
+
> **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).
|
|
35
|
+
>
|
|
36
|
+
> **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).
|
|
37
|
+
>
|
|
38
|
+
> **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.
|
|
39
|
+
>
|
|
40
|
+
> **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.
|
|
41
|
+
>
|
|
42
|
+
> **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`.
|
|
43
|
+
>
|
|
44
|
+
> **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.
|
|
45
|
+
>
|
|
46
|
+
> **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.
|
|
47
|
+
|
|
48
|
+
> **New in 1.10** β **Deshred Sniper.** Deshred deploy feed ~500ms before on-chain confirmation (SDK method `rest.sniperRecent()` shipped in 1.21). PRO: elite/good. ULTRA: all tiers + watchlist. Use `sniper:deploys` WebSocket for push.
|
|
49
|
+
>
|
|
50
|
+
> **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.
|
|
51
|
+
>
|
|
52
|
+
> **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.
|
|
53
|
+
>
|
|
54
|
+
> **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.
|
|
55
|
+
>
|
|
56
|
+
> **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.
|
|
57
|
+
|
|
58
|
+
## Quick start (10 seconds)
|
|
59
|
+
|
|
60
|
+
```bash
|
|
61
|
+
npm install madeonsol-x402
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
```ts
|
|
65
|
+
import { createClient } from "madeonsol-x402";
|
|
66
|
+
const client = createClient("msk_..."); // free tier at https://madeonsol.com/pricing
|
|
67
|
+
const { trades } = await client.kolFeed({ limit: 5 });
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
## Authentication
|
|
71
|
+
|
|
72
|
+
Two options:
|
|
73
|
+
|
|
74
|
+
| Method | Option | Best for |
|
|
75
|
+
|---|---|---|
|
|
76
|
+
| **MadeOnSol API key** (recommended) | `apiKey` | Developers β [get a free key](https://madeonsol.com/pricing) |
|
|
77
|
+
| x402 micropayments | `privateKey` | AI agents with Solana wallets |
|
|
78
|
+
|
|
79
|
+
> **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).
|
|
80
|
+
|
|
81
|
+
## Install
|
|
82
|
+
|
|
83
|
+
```bash
|
|
84
|
+
npm install madeonsol-x402
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
> x402 peer deps (`@x402/fetch @x402/svm @x402/core @solana/kit @scure/base`) are only needed when using `privateKey`.
|
|
88
|
+
|
|
89
|
+
## Quick Start
|
|
90
|
+
|
|
91
|
+
```ts
|
|
92
|
+
import { createClient } from "madeonsol-x402";
|
|
93
|
+
|
|
94
|
+
// Option 1: API key β get one free at madeonsol.com/pricing
|
|
95
|
+
const client = createClient("msk_your_api_key_here");
|
|
96
|
+
|
|
97
|
+
// Option 2: x402 micropayments (auto-detected when no msk_ prefix)
|
|
98
|
+
// const client = createClient(process.env.SOLANA_PRIVATE_KEY!);
|
|
99
|
+
|
|
100
|
+
const { trades } = await client.kolFeed({ limit: 10 });
|
|
101
|
+
console.log(trades);
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
### Advanced initialization
|
|
105
|
+
|
|
106
|
+
```ts
|
|
107
|
+
import { MadeOnSolX402 } from "madeonsol-x402";
|
|
108
|
+
|
|
109
|
+
const client = new MadeOnSolX402({
|
|
110
|
+
apiKey: "msk_...", // OR
|
|
111
|
+
privateKey: "base58...", // x402 micropayments
|
|
112
|
+
});
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
## x402 Endpoints (per-request micropayments)
|
|
116
|
+
|
|
117
|
+
| Method | Description |
|
|
118
|
+
|---|---|
|
|
119
|
+
| `kolFeed(params?)` | Real-time KOL trade feed from 1,000+ tracked wallets |
|
|
120
|
+
| `kolCoordination(params?)` | Tokens being accumulated by multiple KOLs simultaneously |
|
|
121
|
+
| `kolLeaderboard(params?)` | KOL performance rankings by PnL and win rate (180 days of trade history) |
|
|
122
|
+
| `kolPairs(params?)` | KOL affinity matrix β which KOLs frequently co-trade the same tokens |
|
|
123
|
+
| `kolHotTokens(params?)` | KOL momentum tokens β accelerating KOL buy interest |
|
|
124
|
+
| `kolTokenEntryOrder(mint, params?)` | Ranked KOL first-buyer order for a token |
|
|
125
|
+
| `kolCompareWallets({ wallets })` | Side-by-side comparison of 2β5 KOL wallets |
|
|
126
|
+
| `kolAlertsRecent(params?)` | Live KOL alert feed β clusters, fresh-token buys, heating-up wallets |
|
|
127
|
+
| `deployerAlerts(params?)` | Pump.fun deployer alerts with KOL enrichment. PRO/ULTRA: filter by tier. |
|
|
128
|
+
| `walletStats(address)` | **New 1.8** Β· Wallet stats + cross-product flags (is_kol / is_alpha_tracked + bot_confidence / is_deployer). 90-day window. **$0.005** |
|
|
129
|
+
| `walletPnl(address)` | **New 1.8** Β· FIFO cost-basis PnL: realized + unrealized SOL, profit factor, drawdown, hold times, daily curve, closed + open positions. **$0.02** |
|
|
130
|
+
| `walletPositions(address)` | **New 1.8** Β· Open positions only, live unrealized from market-cap tracker. Shares /pnl cache. **$0.01** |
|
|
131
|
+
| `walletTrades(address, params?)` | **New 1.8** Β· Cursor-paginated raw trades with action / token / since-until filters. **$0.005** |
|
|
132
|
+
| `tokenFlow(mint, params?)` | 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"). **Now x402-payable (1.21).** **$0.01** |
|
|
133
|
+
| `tokenCandles(mint, params?)` | **New 1.21** Β· OHLCV candles (1mβ1d timeframes, 30d history) with per-candle volume, trade count, and market cap. **$0.01** |
|
|
134
|
+
| `almostBonded(params?)` | **New 1.21** Β· Launchpad tokens approaching graduation (pump.fun + LetsBonk LaunchLab) β bonding progress, velocity (Ξprogress/min), ETA, deployer tier. **$0.01** |
|
|
135
|
+
| `tokenTopTraders(mint, params?)` | **New 1.21** Β· Wallets ranked by realized PnL (or ROI) on a token, enriched with KOL identity + alpha reputation. **$0.02** |
|
|
136
|
+
| `tokenCapTable(mint)` | **New 1.21** Β· Early-buyer cap table β first 10 non-deployer buyers with PnL, exit status, bundle/KOL/alpha flags + buyer-quality score. **$0.02** |
|
|
137
|
+
| `sniperRecent(params?)` | **New 1.21** Β· Deshred sniper deploy feed (elite/good deployers) with per-deploy snipe `footprint`. **$0.01** |
|
|
138
|
+
| `deployerTrajectory(wallet, params?)` | **New 1.21** Β· Deployer bond-rate trajectory β streaks, rolling bond rates, trend, cadence. `include: "daily_snapshots"` adds 90 days. **$0.01** |
|
|
139
|
+
| `discovery()` | Lists all 25 endpoints, prices, and parameter docs (free) |
|
|
140
|
+
|
|
141
|
+
## REST API client
|
|
142
|
+
|
|
143
|
+
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.
|
|
144
|
+
|
|
145
|
+
```ts
|
|
146
|
+
import { MadeOnSolREST } from "madeonsol-x402";
|
|
147
|
+
|
|
148
|
+
const rest = new MadeOnSolREST({ apiKey: "msk_your_key" });
|
|
149
|
+
const { leaderboard } = await rest.alphaLeaderboard({ period: "30d", sort: "win_rate" });
|
|
150
|
+
|
|
151
|
+
// Rate-limit headers from the most recent response
|
|
152
|
+
console.log(rest.lastRateLimit); // { limit, remaining, reset, requestId }
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
### Alpha wallet intelligence
|
|
156
|
+
|
|
157
|
+
Scored from 1M+ early-buyer records (wallets seen in the first 20 buyers of Pump.fun tokens).
|
|
158
|
+
|
|
159
|
+
| Method | Tier | Description |
|
|
160
|
+
|---|---|---|
|
|
161
|
+
| `rest.alphaLeaderboard(params?)` | All | Top profitable wallets. Up to 100 on Free/Pro; ULTRA unlocks 500 + bot signals |
|
|
162
|
+
| `rest.alphaWallet(wallet)` | ULTRA | Full per-token breakdown + bot_signals array |
|
|
163
|
+
| `rest.alphaLinked(wallet)` | ULTRA | Wallets behaviorally linked (co-bought 3+ tokens within 2s) |
|
|
164
|
+
|
|
165
|
+
**alphaLeaderboard params** β `period` ("7d" \| "30d" \| "all"), `min_tokens` (1β20), `sort` ("win_rate" \| "pnl" \| "roi"), `exclude_bots` ("true" \| "false")
|
|
166
|
+
|
|
167
|
+
### Token quality
|
|
168
|
+
|
|
169
|
+
| Method | Tier | Description |
|
|
170
|
+
|---|---|---|
|
|
171
|
+
| `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 }` |
|
|
172
|
+
| `rest.tokenCapTable(mint)` | PRO+ | First non-deployer early buyers, enriched with PnL/KOL/bot flags. PRO=10, ULTRA=20 |
|
|
173
|
+
| `rest.tokenBuyerQuality(mint)` | All | 0β100 buyer-quality score + full breakdown (5-min cached). Live server-side |
|
|
174
|
+
| `rest.tokenRisk(mint)` | PRO+ | Transparent 0β100 rug-risk/safety score with `band`, explainable `factors[]`, and raw `inputs`. **1.22:** adds a top-level `dev` block (`TokenRiskDev \| null`) β deployer self-buy at create, sells rollup, live on-chain holdings, `wallet_empty`, `transferred_out`. Live server-side |
|
|
175
|
+
| `rest.tokenBundle(mint)` | All | **New 1.19** Β· Bundle-cohort holdings β `bundle` block (`wallet_count`, `bundle_kind`, `held_ratio`, headline `held_pct_of_supply`, `fully_exited`, `buy_volume`, `tokens_held`). BASIC = block only; PRO = top-10 `wallets` + flags; ULTRA = full cohort + identity fields |
|
|
176
|
+
| `rest.tokenPools(mint)` | PRO+ | **New 1.19.2** Β· Per-venue liquidity map β every DEX pool a token trades in (`pool_address`, `dex`, `liquidity_usd`, `last_price_sol`, `is_active`), plus a `summary` rollup (`pool_count`, `active_pool_count`, `dex_count`, `total_liquidity_usd`, `primary_pool`/`primary_dex`, `top_pool_share_pct`) |
|
|
177
|
+
| `rest.tokenDepth(mint, params?)` | PRO+ | **New 1.22** Β· Per-pool price impact / slippage β `quotes[]` per SOL buy size (`tokens_out`, `avg_price_sol`, `price_impact_pct`), `to_move_price` (SOL to move price 1%/5%/10%), `spot_price_sol`, `fee_pct`. Pools we can't price honestly land in `unsupported_pools[]` with a `reason`. `sizes` max 8, default `[0.5, 1, 5, 10]` |
|
|
178
|
+
| `rest.tokenHolders(mint)` | PRO+ | **New** Β· Live holder census + concentration β who holds NOW (vs `tokenCapTable` = who bought first). `concentration.holder_count` is EXACT (mint-scoped `getProgramAccounts` census, merged per owner; `null` only when the provider refuses a mega-cap β top-20 `getTokenLargestAccounts` fallback with `source.census_fallback_reason` β never trade-estimated). Each disclosed owner labelled `deployer` / `kol` / `early_buyer` / `bundle` / `bot` / `dump_cluster` (empty = unknown, not clean). Pools / bonding curves / burns EXCLUDED from the circulating denominator and NAMED in `excluded[]` (`reason`: `pool` + `dex` + `pool_address`, `bonding_curve`, `burn`, `program_account`). `amount_raw` / `supply_raw` / `circulating_raw` are raw u64 STRINGS. Disclosure PRO 10 / ULTRA 50 / BUSINESS 100; maths tier-independent. Big tokens: first call may be HTTP 503 `holder_scan_in_progress` (`retry_after_seconds: 20`) β the scan continues and is cached, the retry is instant. Keyed only (no x402 route) |
|
|
179
|
+
| `rest.tokenLocks(mint, params?)` | PRO+ | **New 1.27** Β· Token locks & vesting on a mint β every Streamflow / Jupiter Lock / Bonfida vesting contract with a live-derived view (`locked_raw` still locked, `unlocked`, `withdrawn`, `claimable`, `status`, `next_unlock`, `cancelable_by_sender`) + `summary` (locked / deposited raw + ui + usd + % of supply, `unlocking_7d` / `unlocking_30d`, nearest `next_unlock`, `active_cancelable_by_sender`). Params `status`, `program`, `limit` (β€500). Base-unit amounts are STRINGS; ui/usd/pct null when unknown. **LP locks NOT included.** Keyed only (no x402 route) |
|
|
180
|
+
| `rest.tokenLocksFeed(params?)` | PRO+ | **New 1.27** Β· Cross-token feed of NEW lock / vesting contracts, newest first (same row + `token` facts). Cursor `since` = `pagination.next_since`, `before` = `next_before`; filters `mint`, `sender`, `recipient`, `program`, `kind`, `status`, `min_usd`, `min_pct_of_supply`, `include_estimated` (backfilled Jupiter rows). Pushed live on WS `token:locks`. Keyed only |
|
|
181
|
+
| `rest.tokenUnlocks(params?)` | PRO+ | **New 1.27** Β· Upcoming unlock EVENTS across all active contracts inside `within` (1h Β· 6h Β· 24h Β· 3d Β· 7d Β· 14d Β· 30d Β· 90d) β each contract's NEXT cliff / period / final / tranche with `amount_*` + `window_amount_*` (total over the window). `sort` soonest Β· largest_usd Β· largest_pct; filters `mint`, `program`, `kind`, `min_usd`, `min_pct_of_supply`. Keyed only |
|
|
182
|
+
| `rest.tokenFeeShares(mint)` | PRO+ | **New 1.27** Β· pump.fun creator-fee sharing on a coin β the on-chain `SharingConfig` (`admin`, `shareholders[]` with `share_bps` / `is_admin` / `is_social_pda` + `social` identity (platform 2 = X, `user_id` = numeric id, lifetime claimed), `redirected_bps`, `social_bps`, `is_default` = 100% to creator, `source` stream/chain) + `distributions` rollup per recipient, `past_recipients`, `history` (config changes / creator transfers), `recent_distributions`. Quote base units as STRINGS. **History starts 2026-08-17.** Keyed only |
|
|
183
|
+
| `rest.tokenFeeClaims(params?)` | PRO+ | **New 1.27** Β· pump.fun fee-event feed, newest first β `distribution` (with pro-rata `payouts[]`), `social_claim`, `shares_created` / `shares_updated` / `shares_reset`, `creator_transferred`, `creator_claim` (only when asked via `type`). Filters `type` (comma list), `mint`, `recipient`, `actor`, `social_platform`, `social_user_id`, `min_sol`; cursor `since` = `pagination.next_since`. Pushed live on WS `token:fee_claims`. **History starts 2026-08-17.** Keyed only |
|
|
184
|
+
| `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 |
|
|
185
|
+
| `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 |
|
|
186
|
+
| `rest.tokenTrades(mint, params?)` | PRO+ | **New 1.21** Β· Mint-scoped trade tape β cursor-paginated raw trades (`price_sol`/`price_usd`, `early_buyer_rank`, `slot`), filter by `action`/`wallet`/`since`/`until`. Default window = **full history**; `coverage` block carries `history_start` (2026-04-12) + `scope` (pump.fun pipeline) |
|
|
187
|
+
| `rest.tokenTopTraders(mint, params?)` | PRO+ | **New 1.21** Β· Wallets ranked by realized PnL (or ROI) on a token β `sort` ("pnl" \| "roi"), `window_days` (1β180), `min_bought_sol`; enriched with KOL identity + alpha reputation (`bot_confidence`, historical win rate/PnL) |
|
|
188
|
+
| `rest.sniperRecent(params?)` | PRO+ | **New 1.21** Β· Deshred sniper deploy feed β PRO sees elite/good deployers, ULTRA all tiers. Each deploy carries a slot-window snipe `footprint` (`buys`/`buyers`/`sol`/`supply_pct`/`sniper_wallet_buys`; null until the ~10-min settle window) |
|
|
189
|
+
|
|
190
|
+
**tokenCandles params** β `tf` ("1m" \| "5m" \| "15m" \| "1h" \| "4h" \| "1d", default "1h"), `limit` (1β1000, default 200), `from` (ISO 8601), `to` (ISO 8601)
|
|
191
|
+
|
|
192
|
+
```ts
|
|
193
|
+
// Score a basket in one request (counts as 1 against quota)
|
|
194
|
+
const { tokens, count } = await rest.tokensBatchRisk([mintA, mintB, mintC]);
|
|
195
|
+
for (const t of tokens) {
|
|
196
|
+
if ("error" in t) console.log(t.mint, t.error); // e.g. "not_tracked"
|
|
197
|
+
else console.log(t.mint, t.risk_score, t.band); // full risk result + as_of
|
|
198
|
+
}
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
### Signal Scorecard *(new in 1.15)*
|
|
202
|
+
|
|
203
|
+
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.
|
|
204
|
+
|
|
205
|
+
| Method | Tier | Description |
|
|
206
|
+
|---|---|---|
|
|
207
|
+
| `rest.signals()` | All (free) | Catalog of scored signals β name, methodology, and each signal's `performance_endpoint`. No payment required |
|
|
208
|
+
| `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[]` |
|
|
209
|
+
|
|
210
|
+
Valid signal names: `dump_cluster_count`, `runner_rate`, `recycled_early_buyer_count`, `coordination_count`.
|
|
211
|
+
|
|
212
|
+
```ts
|
|
213
|
+
const { signals } = await rest.signals();
|
|
214
|
+
const scorecard = await rest.signalPerformance("dump_cluster_count", { history: true });
|
|
215
|
+
console.log(scorecard.buckets); // [{ bucket, hit_rate, base_rate, lift, sample_n, ... }]
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
### KOL coordination alerts (v1.1 β push signals)
|
|
219
|
+
|
|
220
|
+
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.
|
|
221
|
+
|
|
222
|
+
```ts
|
|
223
|
+
// Create a rule
|
|
224
|
+
const { rule, webhook_secret } = await rest.coordinationAlertsCreate({
|
|
225
|
+
name: "fresh pump cluster",
|
|
226
|
+
min_kols: 4, // minimum distinct KOLs in window
|
|
227
|
+
window_minutes: 15, // peak-density window (1-60)
|
|
228
|
+
min_score: 70, // 0-100 composite score cutoff
|
|
229
|
+
include_majors: false, // filter WIF/BONK/POPCAT
|
|
230
|
+
cooldown_min: 60, // one fire per (rule,token) per 60min...
|
|
231
|
+
score_jump_break: 10, // ...unless score jumps +10 vs last fire
|
|
232
|
+
delivery_mode: "both",
|
|
233
|
+
webhook_url: "https://you.com/hooks/coord",
|
|
234
|
+
});
|
|
235
|
+
// β store webhook_secret β shown ONCE
|
|
236
|
+
```
|
|
237
|
+
|
|
238
|
+
`coordinationAlertsList`, `coordinationAlertsGet(id)`, `coordinationAlertsUpdate(id, params)`, `coordinationAlertsDelete(id)` round out the CRUD.
|
|
239
|
+
|
|
240
|
+
**Webhook signature:** `X-MadeOnSol-Signature: sha256=<hmac>` where `hmac = HMAC-SHA256(webhook_secret, timestamp + "." + rawBody)`, and `X-MadeOnSol-Timestamp` carries the unix seconds used.
|
|
241
|
+
|
|
242
|
+
**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.
|
|
243
|
+
|
|
244
|
+
### KOL first-touch signal *(new in 1.3)*
|
|
245
|
+
|
|
246
|
+
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.
|
|
247
|
+
|
|
248
|
+
**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).
|
|
249
|
+
|
|
250
|
+
```ts
|
|
251
|
+
import { MadeOnSolREST } from "madeonsol-x402";
|
|
252
|
+
const rest = new MadeOnSolREST({ apiKey: process.env.MADEONSOL_API_KEY! });
|
|
253
|
+
|
|
254
|
+
// S-tier scouts on tokens younger than 1h
|
|
255
|
+
const { events } = await rest.firstTouches({ preset: "scout", min_scout_tier: "S" });
|
|
256
|
+
|
|
257
|
+
for (const e of events) {
|
|
258
|
+
console.log(e.first_kol.name, "scouted", e.token_symbol, `(scout_score=${e.first_kol.scout_score}%)`);
|
|
259
|
+
}
|
|
260
|
+
```
|
|
261
|
+
|
|
262
|
+
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"`).
|
|
263
|
+
|
|
264
|
+
> **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.
|
|
265
|
+
|
|
266
|
+
**Webhook subscriptions (Ultra)** β up to 10 active per user, mirrors `coordinationAlerts`:
|
|
267
|
+
|
|
268
|
+
```ts
|
|
269
|
+
const { subscription, webhook_secret } = await rest.firstTouchSubscriptionsCreate({
|
|
270
|
+
name: "S-tier scouts on pump tokens",
|
|
271
|
+
filters: { min_scout_tier: "S", mint_suffix: "pump" },
|
|
272
|
+
delivery_mode: "webhook",
|
|
273
|
+
webhook_url: "https://my.bot/hooks/scout",
|
|
274
|
+
});
|
|
275
|
+
// β store webhook_secret β shown ONCE
|
|
276
|
+
```
|
|
277
|
+
|
|
278
|
+
`firstTouchSubscriptionsList`, `firstTouchSubscriptionsGet(id)`, `firstTouchSubscriptionsUpdate(id, params)`, `firstTouchSubscriptionsDelete(id)` round out the CRUD.
|
|
279
|
+
|
|
280
|
+
### Price alerts *(new in 1.9)*
|
|
281
|
+
|
|
282
|
+
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.
|
|
283
|
+
|
|
284
|
+
```ts
|
|
285
|
+
const { alert, webhook_secret } = await rest.priceAlertsCreate({
|
|
286
|
+
name: "SOL dip buy",
|
|
287
|
+
token_mint: "So11111111111111111111111111111111111111112",
|
|
288
|
+
condition: "below", // "below" | "above"
|
|
289
|
+
threshold_mc_usd: 5_000_000_000,
|
|
290
|
+
cooldown_min: 120,
|
|
291
|
+
delivery_mode: "both",
|
|
292
|
+
webhook_url: "https://you.com/hooks/price",
|
|
293
|
+
});
|
|
294
|
+
// β store webhook_secret β shown ONCE
|
|
295
|
+
```
|
|
296
|
+
|
|
297
|
+
`priceAlertsList`, `priceAlertsGet(id)`, `priceAlertsUpdate(id, params)`, `priceAlertsDelete(id)` round out the CRUD.
|
|
298
|
+
|
|
299
|
+
### Scout leaderboard & KOL consensus *(new in 1.9)*
|
|
300
|
+
|
|
301
|
+
| Method | Tier | Description |
|
|
302
|
+
|---|---|---|
|
|
303
|
+
| `rest.scoutLeaderboard(params?)` | PRO+ | Top scout-tier KOLs ranked by first-touch follow-on rate, win rate, and ROI |
|
|
304
|
+
| `rest.kolConsensus(params?)` | PRO+ | Tokens with the strongest KOL agreement signal β weighted by scout score and recent PnL |
|
|
305
|
+
| `rest.peakHistory(mint)` | PRO+ | Historical peak-density windows for a token β every coordination spike with KOL breakdown |
|
|
306
|
+
| `rest.coordinationHistory(params?)` | PRO+ | Global coordination event log with token, KOL count, score, and outcome |
|
|
307
|
+
|
|
308
|
+
```ts
|
|
309
|
+
const { leaderboard } = await rest.scoutLeaderboard({ period: "30d", limit: 25 });
|
|
310
|
+
const { tokens } = await rest.kolConsensus({ min_kols: 5, period: "24h" });
|
|
311
|
+
```
|
|
312
|
+
|
|
313
|
+
### Wallet derived stats *(new in 1.9)*
|
|
314
|
+
|
|
315
|
+
`walletStats(address)` now includes a `stats` object with derived fields computed from the 90-day trade window:
|
|
316
|
+
|
|
317
|
+
```ts
|
|
318
|
+
const { stats } = await rest.walletStats("WALLET_ADDRESS");
|
|
319
|
+
// stats.win_rate β fraction 0-1, tokens sold above cost basis
|
|
320
|
+
// stats.roi β aggregate return on invested SOL
|
|
321
|
+
// stats.verdict β "strong" | "profitable" | "neutral" | "losing"
|
|
322
|
+
// stats.biggest_miss β token with the highest post-exit gain the wallet missed
|
|
323
|
+
```
|
|
324
|
+
|
|
325
|
+
### Copy-trade rules
|
|
326
|
+
|
|
327
|
+
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.
|
|
328
|
+
|
|
329
|
+
| Method | Description |
|
|
330
|
+
|---|---|
|
|
331
|
+
| `rest.copyTradeList()` | List your rules |
|
|
332
|
+
| `rest.copyTradeCreate(params)` | Create a rule. Returns `webhook_secret` **once** β store it |
|
|
333
|
+
| `rest.copyTradeGet(id)` | Get one rule |
|
|
334
|
+
| `rest.copyTradeUpdate(id, params)` | Update fields or toggle `is_active` |
|
|
335
|
+
| `rest.copyTradeDelete(id)` | Delete permanently |
|
|
336
|
+
| `rest.copyTradeSignals(params?)` | Recent fired signals (up to 7 days). Filter by `subscription_id`, `since`, `limit` (1β500) |
|
|
337
|
+
|
|
338
|
+
### Wallet tracker
|
|
339
|
+
|
|
340
|
+
Per-account watchlist with historical swap/transfer history.
|
|
341
|
+
|
|
342
|
+
| Method | Description |
|
|
343
|
+
|---|---|
|
|
344
|
+
| `rest.walletTrackerList()` | List tracked wallets + remaining capacity |
|
|
345
|
+
| `rest.walletTrackerAdd(wallet, label?)` | Add a wallet |
|
|
346
|
+
| `rest.walletTrackerRemove(wallet)` | Remove a wallet |
|
|
347
|
+
| `rest.walletTrackerUpdateLabel(wallet, label)` | Update label (pass `null` to clear) |
|
|
348
|
+
| `rest.walletTrackerTrades(params?)` | Historical events. Params: `wallet`, `action`, `event_type`, `limit` (1β200), `before` (cursor) |
|
|
349
|
+
| `rest.walletTrackerSummary(params?)` | Per-wallet stats. Params: `period` ("24h" \| "7d" \| "30d"), `wallet` |
|
|
350
|
+
| `rest.walletStats(address)` | **New 1.8** Β· Universal wallet stats (90d) + cross-product flags. PRO+. |
|
|
351
|
+
| `rest.walletPnl(address)` | **New 1.8** Β· Full FIFO PnL + curve + closed/open positions. PRO+. |
|
|
352
|
+
| `rest.walletPositions(address)` | **New 1.8** Β· Open positions only with live unrealized. PRO+. |
|
|
353
|
+
| `rest.walletTrades(address, params?)` | **New 1.8** Β· Cursor-paginated raw trades. Params: `limit` (1-500), `cursor`, `action`, `token_mint`, `since`, `until`. PRO+. |
|
|
354
|
+
| `rest.walletClassify(wallets)` | **New 1.21** Β· Bulk reputation flags for 1β100 wallets in one request β `is_sniper` / `is_bundler` (lifetime) / `is_dumper` (rolling 42d) / `is_kol` + `kol_name` / `bot_confidence` / `dump_cluster`. Pump.fun-pipeline scoped: `false` = not observed, NOT verified clean. PRO+. |
|
|
355
|
+
|
|
356
|
+
### Webhooks
|
|
357
|
+
|
|
358
|
+
| Method | Description |
|
|
359
|
+
|---|---|
|
|
360
|
+
| `rest.createWebhook(params)` | Create webhook. Returns `secret` once β store it for HMAC verification |
|
|
361
|
+
| `rest.listWebhooks()` | List your webhooks |
|
|
362
|
+
| `rest.getWebhook(id)` | Get one + recent delivery log |
|
|
363
|
+
| `rest.updateWebhook(id, params)` | Update URL, events, filters, or re-enable |
|
|
364
|
+
| `rest.deleteWebhook(id)` | Delete |
|
|
365
|
+
| `rest.testWebhook(id)` | Send test payload |
|
|
366
|
+
|
|
367
|
+
### KOL/deployer detail
|
|
368
|
+
|
|
369
|
+
| Method | Description |
|
|
370
|
+
|---|---|
|
|
371
|
+
| `rest.kolTiming(wallet, params?)` | Entry/exit timing β hold duration, exit speed, hour distribution |
|
|
372
|
+
| `rest.kolPnl(wallet, params?)` | Per-wallet PnL breakdown |
|
|
373
|
+
| `rest.deployerTrajectory(wallet)` | Deployer skill curve β streaks, rolling bond rate, trend |
|
|
374
|
+
| `rest.deployerHistory(wallet, opts?)` | **New 1.19.2** Β· PRO+ Β· Daily reputation time-series β backtest "was this deployer elite when it launched token X?" without look-ahead. `snapshots[]` carry per-day `tier`, `is_tracked`, `total_deployed`/`total_bonded`, `bonding_rate`, `recent_bond_rate`, `avg_peak_mc`, `best_token_peak_mc`. `opts.limit` (1β365, default 90) |
|
|
375
|
+
|
|
376
|
+
### Streaming token
|
|
377
|
+
|
|
378
|
+
```ts
|
|
379
|
+
const token = await rest.getStreamToken();
|
|
380
|
+
// token.ws_url β KOL/deployer streaming (Pro/Ultra)
|
|
381
|
+
// token.dex_ws_url β all-DEX trade stream (Ultra only)
|
|
382
|
+
```
|
|
383
|
+
|
|
384
|
+
### Managed streaming client *(new in 1.10)*
|
|
385
|
+
|
|
386
|
+
`rest.stream()` handles the token fetch + 24h refresh, auto-reconnect (backoff + jitter), heartbeat liveness, and typed events β just subscribe and listen.
|
|
387
|
+
|
|
388
|
+
```ts
|
|
389
|
+
const stream = rest.stream();
|
|
390
|
+
stream.on("kol:trade", (t) => console.log(t.token_symbol, t.action));
|
|
391
|
+
stream.on("deployer:alert", (a) => console.log("new deploy", a.token_mint));
|
|
392
|
+
stream.subscribe(["kol:trades", "deployer:alerts"]);
|
|
393
|
+
// stream.unsubscribe([...]) / stream.close() when done
|
|
394
|
+
```
|
|
395
|
+
|
|
396
|
+
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 1.27** β event `token:lock` for every NEW Streamflow / Jupiter Lock / Bonfida lock or vesting contract, typed `TokenLockStreamEvent`; PRO+; updates are not pushed β poll `rest.tokenLocks()`), `token:fee_claims` (**new 1.27** β event `token:fee_claim` for every pump.fun fee event: distributions, social-handle claims, config changes, typed `TokenFeeClaimStreamEvent`; PRO+). Lifecycle events: `open`, `close`, `reconnect`, `heartbeat`, `error`. Uses the global `WebSocket` on Node 22+; on Node < 22 also `npm i ws`.
|
|
397
|
+
|
|
398
|
+
### Live stream sessions *(new in 1.18)*
|
|
399
|
+
|
|
400
|
+
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.
|
|
401
|
+
|
|
402
|
+
| Method | Tier | Description |
|
|
403
|
+
|---|---|---|
|
|
404
|
+
| `rest.streamSessions()` | PRO+ | List your live sessions β each with `id`, `service`, `tier`, `channels[]`, `connected_at`, `remote_ip`, `messages_sent`. Typed `StreamSessionsResponse` |
|
|
405
|
+
| `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` |
|
|
406
|
+
|
|
407
|
+
```ts
|
|
408
|
+
const { sessions } = await rest.streamSessions();
|
|
409
|
+
for (const s of sessions) console.log(s.id, s.service, s.channels, s.messages_sent);
|
|
410
|
+
|
|
411
|
+
// Free a stuck slot after a deploy overlap
|
|
412
|
+
if (sessions.length) await rest.streamSessionKill(sessions[0].id); // { evicted: true, id }
|
|
413
|
+
```
|
|
414
|
+
|
|
415
|
+
## DEX Firehose (Ultra)
|
|
416
|
+
|
|
417
|
+
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.
|
|
418
|
+
|
|
419
|
+
```ts
|
|
420
|
+
import WebSocket from "ws";
|
|
421
|
+
|
|
422
|
+
const { token, dex_ws_url } = await rest.getStreamToken();
|
|
423
|
+
const ws = new WebSocket(`${dex_ws_url}?token=${token}`); // token MUST be in the query string
|
|
424
|
+
|
|
425
|
+
ws.on("open", () => {
|
|
426
|
+
ws.send(JSON.stringify({
|
|
427
|
+
type: "subscribe",
|
|
428
|
+
sub_id: "fresh-pumpfun",
|
|
429
|
+
replay: 50, // up to 500 from ring buffer
|
|
430
|
+
filters: {
|
|
431
|
+
dex: "pumpfun", // pumpfun | pumpamm | pumpswap | raydium | jupiter | orca | meteora | launchlab
|
|
432
|
+
token_age_max_seconds: 300,
|
|
433
|
+
min_sol: 0.5,
|
|
434
|
+
action: "buy",
|
|
435
|
+
},
|
|
436
|
+
}));
|
|
437
|
+
});
|
|
438
|
+
|
|
439
|
+
ws.on("message", (raw) => {
|
|
440
|
+
const msg = JSON.parse(raw.toString());
|
|
441
|
+
if (msg.channel === "dex:trades") {
|
|
442
|
+
// { sub_id, data: { wallet, mint, action, sol_amount, dex, ... }, replay, ts }
|
|
443
|
+
}
|
|
444
|
+
});
|
|
445
|
+
```
|
|
446
|
+
|
|
447
|
+
**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.
|
|
448
|
+
|
|
449
|
+
Full protocol reference: [madeonsol.com/api-docs#streaming](https://madeonsol.com/api-docs#streaming).
|
|
450
|
+
|
|
451
|
+
## Rate-limit headers
|
|
452
|
+
|
|
453
|
+
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`:
|
|
454
|
+
|
|
455
|
+
```ts
|
|
456
|
+
await rest.alphaLeaderboard();
|
|
457
|
+
const { limit, remaining, reset, requestId } = rest.lastRateLimit;
|
|
458
|
+
if (remaining !== null && remaining < 5) {
|
|
459
|
+
console.warn(`Throttle warning β ${remaining}/${limit} requests left until ${reset}`);
|
|
460
|
+
}
|
|
461
|
+
```
|
|
462
|
+
|
|
463
|
+
## Discovery
|
|
464
|
+
|
|
465
|
+
```ts
|
|
466
|
+
const info = await client.discovery();
|
|
467
|
+
console.log(info.endpoints); // all endpoints with prices and params
|
|
468
|
+
```
|
|
469
|
+
|
|
470
|
+
Docs: [madeonsol.com/solana-api](https://madeonsol.com/solana-api)
|
|
471
|
+
|
|
472
|
+
## Also Available
|
|
473
|
+
|
|
474
|
+
| Platform | Package |
|
|
475
|
+
|---|---|
|
|
476
|
+
| TypeScript SDK | [`madeonsol`](https://www.npmjs.com/package/madeonsol) on npm |
|
|
477
|
+
| Rust SDK | [`madeonsol`](https://crates.io/crates/madeonsol) on crates.io |
|
|
478
|
+
| Python (LangChain, CrewAI) | [`madeonsol-x402`](https://pypi.org/project/madeonsol-x402/) on PyPI |
|
|
479
|
+
| 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/madeonsol/mcp-server-madeonsol) |
|
|
480
|
+
| ElizaOS | [`@madeonsol/plugin-madeonsol`](https://www.npmjs.com/package/@madeonsol/plugin-madeonsol) |
|
|
481
|
+
| Solana Agent Kit | [`solana-agent-kit-plugin-madeonsol`](https://www.npmjs.com/package/solana-agent-kit-plugin-madeonsol) |
|