⭐ Star on GitHub · 📂 Examples · 📚 API docs
Python SDK for the MadeOnSol Solana KOL intelligence API.
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.
New in 1.19.0 — Batch risk scoring + stream-session control.
rest.tokens_batch_risk(["mint1", "mint2", ...])scores 1–50 base58 mints for rug-risk/safety in a single call (counts as 1 request against quota). Returns{ "tokens": [...], "count": N }where each entry mirrors the single-mintrest.token_risk()shape (risk_score,band,factors,inputs) plus anas_ofISO-8601 timestamp; untracked mints come back as{ "mint", "error": "not_tracked" }and don't fail the batch.tokenspreserves de-duplicated input order. PRO/ULTRA only. Plus WebSocket session control:rest.stream_sessions()lists your live sessions across both stream services (each withid,service,tier,channels,connected_at,remote_ip,messages_sent) andrest.kill_stream_session(id)force-terminates one and frees its connection slot — the self-serve fix for a 4002 connection-limit lockout after a deploy overlap leaves a ghost socket. Both PRO/ULTRA only, exposed as themadeonsol_stream_sessions/madeonsol_kill_stream_session(LangChain) and "MadeOnSol Stream Sessions" / "MadeOnSol Kill Stream Session" (CrewAI) tools.New in 1.18.0 — Almost-bonded discovery + trending sorts.
rest.almost_bonded(min_progress=90, min_velocity_pct_per_min=0.5, deployer_tier="elite", sort="eta_asc", limit=25)returns pre-bond pump.fun tokens near graduation, ranked by velocity (Δprogress/min) — "95% and accelerating" beats "92% stalled". Each token carriesprogress_pct,velocity_pct_per_min,eta_minutes,stalled,real_sol_reserves,market_cap_usd,liquidity_usd,authorities_revoked,deployer_tier, andage_minutes.sortis'velocity_desc'(default) /'progress_desc'/'eta_asc'. PRO/ULTRA only (keyed). Exposed as themadeonsol_almost_bonded(LangChain) / "MadeOnSol Almost Bonded" (CrewAI) tool. Plusrest.tokens_list(sort=...)gains four momentum sorts —'mc_change_5m_desc','mc_change_1h_desc','volume_1h_desc', and'trending'(composite recent-volume × positive-momentum rank).New in 1.17.0 — Token money-flow.
client.token_flow(mint, window="1h")(and the asyncawait client.token_flow_async(mint, window="1h")) aggregates buy/sell pressure for a token over a rolling'1h'or'24h'window. Returnsmint,window,from,unique_wallets,unique_buyers,unique_sellers,buy_count,sell_count,total_trades,buy_sol,sell_sol,net_sol, andtrades_per_wallet. PRO+ (keyed). Also:deployer_alerts()items now carrydeployer_sol_balance(float | None) — the deployer wallet's SOL balance at alert time (Nonefor historical rows).New in 1.16.0 — Live token snapshot + Signal Scorecard (keyless x402).
client.token(mint)returns a live{ "token": {...} }snapshot (price_usd/price_sol,market_cap,fdv_usd,liquidity_usd,liquidity_to_mc_ratio,primary_dex,is_token_2022,transfer_fee_bps,top_buyers=[{name, sol_amount}]).client.signal_performance(name, history=False)returns out-of-sample reliability for a named signal (hit_rate,base_rate,lift,sample_n,window_days,test_from/test_to, plusmetric_type,outcome,methodology,as_of; per-day series whenhistory=True) — valid names:dump_cluster_count,runner_rate,recycled_early_buyer_count,coordination_count.client.signals()(free) lists the signal catalog.New in 1.15.0 — Token OHLCV candles.
rest.token_candles(mint, tf="1h", limit=200, from_=None, to=None)returns 1-minute-derived OHLCV candles aggregated to a timeframe ('1m'|'5m'|'15m'|'1h'|'4h'|'1d'). Each candle hast,open,high,low,close,volume_usd,trades, andmarket_cap_usd. PRO returns OHLCV over the last 30 days; ULTRA adds per-candle net-flow fields (buy_volume_usd,sell_volume_usd,net_volume_usd,buy_count,sell_count,volume_mev_usd,open_liquidity_usd,close_liquidity_usd,high_mc_usd,low_mc_usd) and full history.New in 1.14.0 — Token risk score.
rest.token_risk(mint)returns a transparent 0–100 rug-risk/safety score (higher = riskier) with aband('safe'|'caution'|'danger'), an explainablefactorsarray, and the rawinputs(mint/freeze authority, liquidity, liq-to-MC ratio, transfer fee, launch cohort, deployer bond rate, KOL signal, blacklist). PRO/ULTRA only.New in 1.13.0 —
rest.tokens_list()gains three new filter params:min_liq_mc_ratio,max_liq_mc_ratio, anddeployer_tier('elite'|'good'|'moderate'|'rising'|'cold'|'unranked'). Response items now includeliquidity_to_mc_ratioanddeployer_tier. KOL leaderboard entries now includemedian_hold_minutes_30dandpercentile_early_entry_30d./token/{mint}and/token/batchresponses now includeliquidity_to_mc_ratio,launch_cohort_sol, andlaunch_cohort_size.New in 1.12.1 — Deployer alerts/profiles now carry
runner_rate+labeled_tokens(fraction of a deployer's labeled tokens that ran vs dumped, gate onlabeled_tokens>= 3) plusavg_time_to_bond_minutes.
New in 1.12 — Graduation events + dump-cluster detection. Subscribe
token:graduationsfor every pump.fun bond in real time (tracked deployer or not). Buyer-qualitybreakdownaddsdump_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-banddex:graduationsframes.
New in 1.10 — Deshred Sniper.
client.rest.sniper_recent()— deshred deploy feed ~500ms before on-chain confirmation. PRO: elite/good. ULTRA: all tiers +sniper_watchlist_add(). Usesniper:deploysWebSocket for push.New in 1.9 — Price alerts, scout leaderboard, coordination history.
client.rest.price_alerts_create()(PRO=5, ULTRA=25).scout_leaderboard(),kol_consensus(),peak_history(),coordination_history().wallet_stats()now returnsderived: win_rate, roi, verdict, biggest_miss.New in 1.8 — Universal Wallet API.
client.rest.wallet_stats(),wallet_pnl(),wallet_positions(),wallet_trades()— FIFO cost-basis PnL for any Solana wallet. PRO+. Cache hits free.New in 1.7.1 (2026-05-13) — Velocity field shape corrected to match the API:
mc_change_pct,volume_usd,mev_volume_pctare top-level on the token response, each keyed by'5m'/'15m'/'1h'/'2h'/'4h'. The 1.7.0 README documented avelocity[window]shape that didn't match the wire format.New in 1.7.0 (2026-05-12) — Token directory + account inspection.
client.rest.tokens_list(min_liq=10000, min_volume_1h_usd=5000, max_mev_share_pct=60, mc_change_1h_min_pct=20, sort="mc_desc", min_liq_mc_ratio=0.05, deployer_tier="elite")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 includeliquidity_to_mc_ratioanddeployer_tier. Defaultmin_liq=2000skips phantom-MC dust; passmin_liq=0to opt out.client.rest.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') plushistory_age_seconds./token/{mint}400s now ship structuredcode,reason,received_length,example, anddocs. Deprecatedavg_entry_mc_usdfully removed.
pip install madeonsol-x402from madeonsol_x402 import MadeOnSolClient
client = MadeOnSolClient(api_key="msk_...") # free tier at https://madeonsol.com/pricing
trades = client.kol_feed(limit=5, action="buy")Two options:
| Method | Parameter / Env var | Best for |
|---|---|---|
| MadeOnSol API key (recommended) | api_key / MADEONSOL_API_KEY |
Developers — get a free key |
| x402 micropayments | private_key / SVM_PRIVATE_KEY |
AI agents with Solana wallets |
v1.0 breaking change: RapidAPI auth has been removed. The MadeOnSol RapidAPI marketplace was retired on 2026-04-19. If you were using
rapidapi_key=orRAPIDAPI_KEY, get a freemsk_key at madeonsol.com/pricing.
pip install madeonsol-x402 # core SDK
pip install madeonsol-x402[langchain] # + LangChain tools
pip install madeonsol-x402[crewai] # + CrewAI toolsx402 dependencies are only needed when using
private_key/SVM_PRIVATE_KEY.
from madeonsol_x402 import MadeOnSolClient
client = MadeOnSolClient(api_key="msk_your_api_key_here")
# Real-time KOL trades — each trade now includes
# market_cap_usd_at_trade and price_usd_at_trade (real-time MC at the
# moment the swap fired, sourced from our in-memory price tracker).
trades = client.kol_feed(limit=10, action="buy")
for t in trades["trades"]:
print(f'{t["kol_name"]} bought {t["token_symbol"]} for {t["sol_amount"]:.2f} SOL @ MC ${t.get("market_cap_usd_at_trade") or "?"}')
# KOL convergence signals
signals = client.kol_coordination(period="24h", min_kols=3)
# KOL leaderboard — 180 days of history
leaders = client.kol_leaderboard(period="7d") # today | 7d | 30d | 90d | 180d
# Deployer alerts (all tiers can filter by tier)
# Each alert carries deployer_sol_balance (float | None) — deployer wallet
# SOL balance at alert time (None for historical rows).
alerts = client.deployer_alerts(limit=10)
elite_only = client.deployer_alerts(limit=10, tier="elite")
# Token money-flow over a rolling window (PRO+) — sync
flow = client.token_flow("So11111111111111111111111111111111111111112", window="1h")
print(flow["net_sol"], flow["unique_buyers"], flow["unique_sellers"])
# Alpha wallet leaderboard (REST)
top = client.rest.alpha_leaderboard(period="30d", sort="win_rate")
# Wallet Tracker (REST)
client.rest.wallet_tracker_add("WALLET_ADDRESS", label="whale")
events = client.rest.wallet_tracker_trades(limit=50)
# Inspect rate-limit headers from the most recent REST call
print(client.rest.last_rate_limit)
# {'limit': 100, 'remaining': 92, 'reset': 1714000000, 'request_id': 'rid_abc123'}token_flow(mint, window="1h") aggregates buy/sell pressure for a token over a rolling '1h' or '24h' window. PRO+ (keyed). Both sync and async variants are available:
import asyncio
from madeonsol_x402 import MadeOnSolClient
client = MadeOnSolClient(api_key="msk_...")
mint = "So11111111111111111111111111111111111111112"
# Sync
flow = client.token_flow(mint, window="1h")
print(flow["net_sol"], flow["buy_sol"], flow["sell_sol"])
# Async
async def main():
flow = await client.token_flow_async(mint, window="24h")
print(flow["unique_wallets"], flow["trades_per_wallet"])
asyncio.run(main())Response keys: mint, window, from, unique_wallets, unique_buyers, unique_sellers, buy_count, sell_count, total_trades, buy_sol, sell_sol, net_sol, trades_per_wallet.
Managed WebSocket stream — auto-reconnect, 24h-token refresh, and typed callbacks handled for you. Needs the stream extra: pip install "madeonsol-x402[stream]".
import asyncio
from madeonsol_x402 import MadeOnSolREST
client = MadeOnSolREST(api_key="msk_...")
async def main():
stream = client.stream()
@stream.on("kol:trade")
async def on_trade(data, evt):
print(data["token_symbol"], data["action"])
stream.subscribe(["kol:trades", "deployer:alerts"])
await stream.run() # blocks; manages connection + reconnects
asyncio.run(main())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). Lifecycle events: open, close, reconnect, heartbeat, error.
from madeonsol_x402.langchain_tools import ALL_TOOLS
# Set MADEONSOL_API_KEY or SVM_PRIVATE_KEY env var
agent = create_react_agent(llm, tools=ALL_TOOLS)from madeonsol_x402.crewai_tools import ALL_TOOLS
agent = Agent(role="Solana Analyst", tools=ALL_TOOLS)| Method | Description |
|---|---|
kol_feed() |
Real-time KOL trade feed (1,000+ wallets) |
kol_coordination() |
Multi-KOL convergence signals |
kol_leaderboard() |
PnL and win rate rankings — windows: today, 7d, 30d, 90d, 180d (180-day retention) |
kol_pairs() |
KOL affinity matrix — which KOLs co-trade the same tokens |
kol_hot_tokens() |
KOL momentum tokens — accelerating buy interest |
kol_trending_tokens() |
Tokens ranked by KOL buy volume |
kol_token_entry_order(mint) |
Ranked KOL first-buyer order for a token |
kol_compare_wallets(wallets) |
Side-by-side comparison of 2–5 KOL wallets |
kol_alerts_recent() |
Live KOL alert feed — clusters, fresh-token buys, heating-up |
deployer_alerts() |
Pump.fun deployer launches with KOL enrichment |
wallet_stats(address) |
New 1.8 · Universal wallet stats (90d) + cross-product flags. $0.005 |
wallet_pnl(address) |
New 1.8 · FIFO cost-basis PnL: realized + unrealized, profit factor, drawdown, daily curve, closed + open positions. $0.02 |
wallet_positions(address) |
New 1.8 · Open positions with live unrealized from market-cap tracker. Shares /pnl cache. $0.01 |
wallet_trades(address, ...) |
New 1.8 · Cursor-paginated raw trades with action / token / since-until filters. $0.005 |
token(mint) |
New 1.16 · Live token snapshot — price_usd/price_sol, market_cap, fdv_usd, liquidity_usd, liquidity_to_mc_ratio, primary_dex, is_token_2022, transfer_fee_bps, top_buyers |
signal_performance(name, history=False) |
New 1.16 · Signal Scorecard — out-of-sample hit_rate/base_rate/lift/sample_n per signal (dump_cluster_count, runner_rate, recycled_early_buyer_count, coordination_count) |
signals() |
New 1.16 · Free — signal catalog with per-signal methodology and performance_endpoint |
token_flow(mint, window="1h") |
New 1.17 · PRO+ · Token money-flow over a rolling 1h/24h window — unique wallets/buyers/sellers, buy/sell counts + SOL, net SOL flow, trades per wallet. Async: token_flow_async(mint, window="1h") |
discovery() |
Free — list all endpoints and prices |
| Method | Description |
|---|---|
rest.kol_pnl(wallet, period=) |
Deep per-wallet PnL: equity curve, risk metrics, closed positions. ULTRA adds open positions (tokens bought but not yet sold). |
rest.kol_timing(wallet, period=) |
KOL entry/exit timing profile — available on all tiers |
rest.deployer_trajectory(wallet) |
Deployer skill curve — streaks, rolling bond rate, trend — available on all tiers |
Scored from 1M+ early-buyer records (wallets seen in the first 20 buyers of Pump.fun tokens).
| Method | Tier | Description |
|---|---|---|
rest.alpha_leaderboard(period=, min_tokens=, sort=, exclude_bots=) |
All | Up to 100 results on Free/Pro; ULTRA unlocks 500 + bot signals |
rest.alpha_wallet(wallet) |
ULTRA | Full per-token breakdown + bot_signals array |
rest.alpha_linked(wallet) |
ULTRA | Wallets behaviorally linked (co-bought 3+ tokens within 2s) |
| Method | Tier | Description |
|---|---|---|
rest.token_cap_table(mint) |
PRO+ | First non-deployer early buyers, enriched with PnL/KOL/bot flags. PRO=10, ULTRA=20 |
rest.token_buyer_quality(mint) |
All | 0–100 buyer-quality score + full breakdown (5-min cached) |
rest.token_risk(mint) |
PRO+ | Transparent 0–100 rug-risk/safety score with band, explainable factors, and raw inputs |
rest.tokens_batch_risk(mints) |
New 1.19 · PRO+ | Bulk risk scoring for 1–50 mints in one call (1 request). Each entry mirrors token_risk + as_of; untracked mints → {mint, error: "not_tracked"} |
rest.token_candles(mint, tf, limit, from_, to) |
PRO+ | 1-minute-derived OHLCV candles by timeframe. PRO=OHLCV/30d, ULTRA=+net flow/full history |
The fastest path to a new pump.fun launch. Deploys are reconstructed from shred-level (deshred) data and surface ~500ms before the chain confirms them. PRO sees elite + good deployers; ULTRA sees every tier and can keep a custom deployer watchlist. For live push use the sniper:deploy webhook or the sniper:deploys WebSocket channel.
| Method | Tier | Description |
|---|---|---|
rest.sniper_recent(limit=, deployer_tier=, min_bond_rate=, since=, watchlist=) |
PRO+ | Deshred deploy feed, newest first. PRO=elite/good, ULTRA=all tiers. watchlist=True (ULTRA) narrows to your watchlist |
rest.sniper_by_deployer(wallet, limit=) |
ULTRA | Deshred deploys for one deployer |
rest.sniper_watchlist() |
ULTRA | List your custom deployer watchlist (max 50) |
rest.sniper_watchlist_add(wallet=/wallets=, label=) |
ULTRA | Add one or many deployers |
rest.sniper_watchlist_remove(wallet) |
ULTRA | Remove a deployer |
feed = client.rest.sniper_recent(limit=50, min_bond_rate=0.5)
client.rest.sniper_watchlist_add(wallets=["7dEx...4pQ8", "9aBc...2zZ1"], label="alpha devs")
tracked = client.rest.sniper_recent(watchlist=True) # ULTRA — only your tracked deployersReal-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.
res = client.rest.coordination_alerts_create(
name="fresh pump cluster",
min_kols=4,
window_minutes=15, # peak-density window (1-60)
min_score=70, # 0-100 composite score cutoff
include_majors=False, # filter WIF/BONK/POPCAT
cooldown_min=60, # one fire per (rule, token) per 60min...
score_jump_break=10, # ...unless score jumps +10 vs last fire
delivery_mode="both",
webhook_url="https://you.com/hooks/coord",
)
# store res["webhook_secret"] — shown ONCEcoordination_alerts_list(), coordination_alerts_get(id), coordination_alerts_update(id, **fields), coordination_alerts_delete(id).
Webhook signature: X-MadeOnSol-Signature: sha256=<hmac> where hmac = HMAC-SHA256(webhook_secret, timestamp + "." + rawBody), and X-MadeOnSol-Timestamp carries the unix seconds used.
The kol_coordination() 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 (net-flow-negative wallets), and coordination_score (0-100). Pass min_score=, window_minutes=, include_majors= to filter.
Every "first KOL buy on a token mint" event — when 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.
Backtest: S-tier scouts attract ≥3 follow-on KOLs within 4h ~50% of the time vs ~14% baseline (38d / 491k buys / 72,549 events). Public leaderboard at madeonsol.com/kol/scouts.
# REST query — S-tier scouts on tokens younger than 1h
events = client.rest.first_touches(preset="scout", min_scout_tier="S", limit=20)
for e in events["events"]:
fk = e["first_kol"]
print(fk["name"], "scouted", e["token_symbol"], f"(scout_score={fk['scout_score']}%)")
# Webhook subscription (Ultra) — HMAC-signed push
res = client.rest.first_touch_subscriptions_create(
name="S-tier scouts on pump tokens",
filters={"min_scout_tier": "S", "mint_suffix": "pump"},
delivery_mode="webhook",
webhook_url="https://you.com/hooks/scout",
)
# store res["webhook_secret"] — shown ONCECRUD: first_touch_subscriptions_list(), first_touch_subscriptions_get(id), first_touch_subscriptions_update(id, **fields), first_touch_subscriptions_delete(id). ULTRA only — up to 10 active.
Don't poll — push. Median lead time before the second KOL is 12 seconds. WebSocket channel:
kol:first_touches(PRO+).
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.
res = client.rest.price_alerts_create(
name="SOL dip buy",
token_mint="So11111111111111111111111111111111111111112",
condition="below", # "below" | "above"
threshold_mc_usd=5_000_000_000,
cooldown_min=120,
delivery_mode="both",
webhook_url="https://you.com/hooks/price",
)
# store res["webhook_secret"] — shown ONCEprice_alerts_list(), price_alerts_get(id), price_alerts_update(id, **fields), price_alerts_delete(id).
LangChain: MadeOnSolPriceAlertsListTool, MadeOnSolPriceAlertsCreateTool. CrewAI: same names via ALL_TOOLS.
| Method | Tier | Description |
|---|---|---|
rest.scout_leaderboard(period=, limit=) |
PRO+ | Top scout-tier KOLs ranked by first-touch follow-on rate, win rate, and ROI |
rest.kol_consensus(min_kols=, period=) |
PRO+ | Tokens with the strongest KOL agreement signal — weighted by scout score and recent PnL |
rest.peak_history(mint) |
PRO+ | Historical peak-density windows for a token — every coordination spike with KOL breakdown |
rest.almost_bonded(min_progress=, min_velocity_pct_per_min=, deployer_tier=, sort=, limit=) |
New 1.18 · PRO+ | Pre-bond pump.fun tokens near graduation, ranked by velocity (Δprogress/min) — progress_pct, velocity_pct_per_min, eta_minutes, stalled, deployer_tier |
rest.coordination_history(period=, limit=) |
PRO+ | Global coordination event log with token, KOL count, score, and outcome |
leaders = client.rest.scout_leaderboard(period="30d", limit=25)
consensus = client.rest.kol_consensus(min_kols=5, period="24h")wallet_stats(address) now includes a stats object with derived fields computed from the 90-day trade window:
data = client.rest.wallet_stats("WALLET_ADDRESS")
s = data["stats"]
# s["win_rate"] — fraction 0-1, tokens sold above cost basis
# s["roi"] — aggregate return on invested SOL
# s["verdict"] — "strong" | "profitable" | "neutral" | "losing"
# s["biggest_miss"] — token with the highest post-exit gain the wallet missedServer-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.
| Method | Description |
|---|---|
rest.copy_trade_list() |
List your rules |
rest.copy_trade_create(source_wallets, sizing_amount, ...) |
Create a rule. Returns webhook_secret once — store it |
rest.copy_trade_get(id) |
Get one rule |
rest.copy_trade_update(id, **fields) |
Update fields or toggle is_active |
rest.copy_trade_delete(id) |
Delete permanently |
rest.copy_trade_signals(subscription_id=, since=, limit=) |
Recent fired signals (up to 7 days, 1–500) |
| Method | Description |
|---|---|
rest.wallet_tracker_watchlist() |
List tracked wallets and remaining capacity (Free: 10, Pro: 50, Ultra: 100) |
rest.wallet_tracker_add(wallet_address, label=) |
Add wallet to watchlist |
rest.wallet_tracker_remove(wallet_address) |
Remove wallet from watchlist |
rest.wallet_tracker_update_label(wallet_address, label) |
Update wallet label |
rest.wallet_tracker_trades(wallet=, action=, event_type=, limit=, before=) |
Historical swap/transfer events (120-day retention) |
rest.wallet_tracker_summary(period=, wallet=) |
Per-wallet stats: swap counts, SOL bought/sold, last event |
Per-wallet endpoints that work on any Solana wallet, not just curated KOLs. FIFO cost-basis PnL over the last 90 days. PRO+ on every endpoint. Cache hits don't count against your daily quota.
| Method | Description |
|---|---|
rest.wallet_stats(address) |
Aggregate stats over 90d + cross-product flags (is_kol + kol_name, is_alpha_tracked + bot_confidence + win_rate, is_deployer + tokens_deployed) |
rest.wallet_pnl(address) |
Full FIFO cost-basis PnL: realized + unrealized SOL, profit factor, max drawdown, avg + median hold minutes, daily UTC PnL curve, closed positions sorted by pnl desc, open positions with live unrealized from mc-tracker |
rest.wallet_positions(address) |
Open lots only — shares /pnl cache, lighter response |
rest.wallet_trades(address, limit=, cursor=, action=, token_mint=, since=, until=) |
Cursor-paginated raw trades. Default window: last 90 days. limit 1-500 |
Cost-basis honesty: observable only inside the 90-day data window. Overflow sells (no matching buy in window) are silently discarded rather than fabricated. notes.cost_basis_observable_from makes the cutoff visible per call.
| Method | Description |
|---|---|
rest.create_webhook(url, events, filters=) |
Register webhook. Returns secret once — store it for HMAC verification |
rest.list_webhooks() |
List your webhooks |
rest.get_webhook(id) |
Get one + recent delivery log |
rest.update_webhook(id, **kwargs) |
Update URL, events, filters, or re-enable |
rest.delete_webhook(id) |
Delete permanently |
rest.test_webhook(id) |
Send test payload |
rest.get_stream_token() |
Issue a 24h WebSocket streaming token (returns ws_url + dex_ws_url) |
rest.stream_sessions() |
New 1.19 · PRO+ · List your live WebSocket sessions (id, service, tier, channels, connected_at, remote_ip, messages_sent) across both stream services |
rest.kill_stream_session(id) |
New 1.19 · PRO+ · Force-terminate one of your sessions by id and free its slot — self-serve fix for a 4002 connection-limit lockout |
Every successful REST response captures rate-limit headers in rest.last_rate_limit:
client.rest.alpha_leaderboard()
rl = client.rest.last_rate_limit
# {'limit': 100, 'remaining': 92, 'reset': 1714000000, 'request_id': 'rid_abc123'}
if rl['remaining'] is not None and rl['remaining'] < 5:
print(f"Throttle warning — {rl['remaining']}/{rl['limit']} requests left")rest.get_stream_token() returns dex_ws_url (Ultra only). Connect with any WebSocket client (websockets, websocket-client, etc.) 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.
import asyncio, json, websockets
from madeonsol_x402 import MadeOnSolClient
client = MadeOnSolClient(api_key="msk_...")
async def main():
token = client.rest.get_stream_token() # {"token", "ws_url", "dex_ws_url", ...}
# token MUST be appended as query param
async with websockets.connect(f"{token['dex_ws_url']}?token={token['token']}") as ws:
await ws.send(json.dumps({
"type": "subscribe",
"sub_id": "fresh-pumpfun",
"replay": 50, # up to 500 from ring buffer
"filters": {
"dex": "pumpfun",
"token_age_max_seconds": 300,
"min_sol": 0.5,
"action": "buy",
},
}))
async for raw in ws:
msg = json.loads(raw)
if msg.get("channel") == "dex:trades":
d = msg["data"]
print(msg["sub_id"], d["dex"], d["action"], d["sol_amount"])
asyncio.run(main())Operations (all carry sub_id): subscribe, update (replace filters in place), unsubscribe, list, ping. Filters: token_mint(s) (≤50), wallet(s) (≤50), dex (pumpfun | pumpamm | pumpswap | raydium | jupiter | orca | meteora | launchlab), 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.
Full protocol reference: madeonsol.com/api-docs#streaming.
| Tier | Price | Wallets tracked | Requests/day |
|---|---|---|---|
| BASIC (free) | $0 | 10 | 200 |
| PRO | €43/mo (€430/yr) ≈ $49 | 50 | 10,000 |
| ULTRA | €131/mo (€1310/yr) ≈ $149 | 100 + WS events | 100,000 |
Free tier returns the full REST response shape on every endpoint — real wallets, TX signatures, full precision. Paid tiers unlock webhooks, WebSockets, rule engines, and ULTRA-only data depth. Get a key at madeonsol.com/pricing.
| Platform | Package |
|---|---|
| TypeScript SDK | madeonsol on npm |
| Rust SDK | madeonsol on crates.io |
| MCP Server (Claude, Cursor) | mcp-server-madeonsol · Smithery · Glama |
| ElizaOS | @madeonsol/plugin-madeonsol |
| Solana Agent Kit | solana-agent-kit-plugin-madeonsol |
MIT