Skip to content

Latest commit

 

History

35 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 

Repository files navigation

madeonsol-x402

PyPI Python Downloads GitHub stars License: MIT

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, expose bundle-cohort supply retention (held % of supply), verify any wallet's current on-chain holdings, 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.27.0 — token locks & vesting, upcoming unlocks, and pump.fun creator-fee sharing. Five keyed (PRO+) REST bindings + two WebSocket channels. rest.token_locks(mint, status=, program=, limit=) — every on-chain Streamflow / Jupiter Lock / Bonfida vesting contract on a mint with the schedule (start / cliff / period / end), the terms (cancelable_by_sender — a cancelable lock is a weaker promise — cancelable_by_recipient, transferable, can_topup) and a live-derived view (locked_raw now, unlocked, withdrawn, claimable, status, next_unlock), plus a summary (exact lock_count, distinct_lockers, locked / deposited totals as raw + ui + usd + % of supply, unlocking_7d_* / unlocking_30d_*, nearest next_unlock, active_cancelable_by_sender). rest.token_locks_feed(since=, before=, mint=, sender=, recipient=, program=, kind=, status=, min_usd=, min_pct_of_supply=, include_estimated=, limit=) — cross-token feed of NEW contracts, newest first, cursor pagination.next_since / next_before. rest.token_unlocks(within=, mint=, program=, kind=, min_usd=, min_pct_of_supply=, sort=, limit=) — upcoming unlock EVENTS (cliff / period / final / tranche) inside 1h90d with amount_* and window_amount_*. LP locks are NOT included in any of the three. rest.token_fee_shares(mint) — the pump.fun SharingConfig: who receives what share (bps) of a coin's creator fees, is_admin / is_social_pda (fees earmarked for an X account etc. — social.platform 2 = X, user_id = the platform-native numeric id), redirected_bps, social_bps, is_default: true = 100% to the creator, plus the distributions rollup and config history. rest.token_fee_claims(type=, mint=, recipient=, actor=, social_platform=, social_user_id=, min_sol=, since=, before=, limit=) — the fee-event feed (distribution with payouts[], social_claim, shares_created / shares_updated / shares_reset, creator_transferred, creator_claim only when asked via type=). Fee history starts 2026-08-17. All base-unit amounts (*_raw) are strings; ui / usd / pct are None when decimals or price are unknown. Streams: token:locks (event token:lock, one frame per new contract) and token:fee_claims (event token:fee_claim) — added to CHANNELS / EVENT_NAMES. LangChain / CrewAI tools: MadeOnSolTokenLocks, MadeOnSolTokenLocksFeed, MadeOnSolTokenUnlocks, MadeOnSolTokenFeeShares, MadeOnSolTokenFeeClaims. Keyed (msk_) API only — none of these are on the x402 rail; BASIC gets HTTP 403.

New in 1.26.0 — live holder census: exact holder count, labelled holders, and pools that are named, not just excluded. rest.token_holders(mint) (plus MadeOnSolTokenHolders LangChain / CrewAI tools) 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) only — the census is not on the x402 rail.

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.token_trades(mint) and rest.wallet_trades(address) carry all four fields — wallet_trades returned amounts and no price at all before.

New in 1.24.0 — the Deployer Hunter surface completed. Seven new operations that existed on the API but had no SDK binding: deployer_leaderboard(), deployer_stats(), deployer_profile(), deployer_tokens(), deployer_alert_stats(), deployer_best_tokens() and deployer_recent_bonds() (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.

New in 1.23.0Pool depth / price-impact + dev self-activity on the risk score. rest.token_depth(mint, sizes=None) (GET /tokens/{mint}/depth, PRO+) answers "how much SOL does it take to move the price N%" per pool: each depth-computable pool returns spot_price_sol, fee_pct, source ('stream' for constant-product AMMs served zero-RPC from stream reserves, 'live_rpc' for pump.fun/bonk curves priced from a live read of the curve's VIRTUAL reserves), reserves_age_ms, per-size quotes (size_sol, tokens_out, avg_price_sol, price_impact_pct), and to_move_price (SOL to move price '1pct'/'5pct'/'10pct'). sizes is a CSV string or list of floats (max 8, each >0 and ≤10000; default 0.5,1,5,10); the response carries sol_usd, sizes_sol, primary_pool, and honesty-first unsupported_pools — concentrated pools (CLMM/Orca/DLMM), Meteora-DBC curves, and unclassified pools come back with a reason instead of a wrong number. Exposed as the madeonsol_token_depth (LangChain) / "MadeOnSol Token Depth" (CrewAI) tool. Plus rest.token_risk(mint) responses gain a top-level dev object — deployer self-activity for the mint: wallet, launchpad, deployed_at, create-tx buy_sol/buy_tokens/buy_supply_pct, post-create bought_tokens_after/sold_tokens/sold_sol with first_sell_at/last_sell_at, live on-chain holdings_tokens/holdings_supply_pct, wallet_empty (bool | None), and transferred_out (bool | None — chain balance well below the trade-derived expectation, i.e. tokens moved without a swap) — plus as_of. dev is None when the mint has no tracked deploy row.

New in 1.22.0Batch wallet classification, token trade tape + 7 endpoints go keyless. rest.wallet_batch_classify(["addr1", ...]) returns reputation flags for 1–100 wallets in one call (counts as 1 request): per wallet is_sniper / is_bundler / is_dumper / is_kol (+ kol_name), bot_confidence (string enum 'none'/'low'/'medium'/'high', None when not alpha-tracked), and a dump_cluster block (dump_cohorts, runner_cohorts, total_cohorts, as_of). Flags are pump.fun-pipeline scoped — False = not observed, NOT verified clean; is_bundler is lifetime, is_dumper is a rolling 42d window. rest.token_trades(mint, limit=100, cursor=None, action=None, wallet=None, since=None, until=None) is the mint-scoped trade tape — cursor-paginated raw trades (default FULL history; capture starts 2026-04-12) with a coverage honesty block. Both PRO+. wallet_stats() flags gain the same reputation flags + dump_cluster, and bot_confidence is now correctly a string enum (a server bug made it always None before — real values now). token_risk() inputs and sniper_recent() deploys gain the slot-window sniper_footprint/footprint rollup. The keyless x402 catalog grows 18 → 25: new MadeOnSolClient (keyless-capable) methods token_candles ($0.01), almost_bonded ($0.01), token_top_traders ($0.02), token_cap_table ($0.02), sniper_recent ($0.01), deployer_trajectory ($0.01) — joining token_flow ($0.01).

New in 1.21.0Verified wallet holdings. rest.wallet_holdings(address, limit=200, min_value_usd=0) reads the wallet's actual SPL + Token-2022 token accounts and SOL balance directly from chain, enriches each with our price/MC/name/symbol data, and computes transfer_delta (on-chain amount minus trade-derived net position) to expose non-swap flows — airdrops, insider funding, wallet-hopping. Distinct from wallet_positions (trade-derived FIFO): holdings is "what they actually hold right now". Returns address, sol_balance, holdings (each with mint, symbol, name, amount, amount_raw, decimals, token_program ('spl' | 'token2022'), price_usd, value_usd, market_cap_usd, is_bonded, trade_derived_amount, transfer_delta), a summary (token_accounts, non_zero, returned, priced, total_value_usd, truncated), verified_at, trade_window_days, cache_hit, and ttl_seconds. limit 1–500 (default 200), min_value_usd ≥ 0 (default 0). ULTRA only.

New in 1.20.0Bundle-cohort holdings. rest.token_bundle(mint) reveals how much of a token's supply its launch bundle still holds. The bundle summary carries wallet_count, bundle_kind ('atomic_tx' | 'same_slot' | 'none'), held_pct_of_supply (net-held / circulating supply — the HEADLINE signal, null when supply is unknown), held_ratio (net-held / buy-volume — churn-sensitive, secondary), fully_exited, buy_volume (cumulative buy volume — NOT distinct tokens, can exceed supply), and tokens_held (swap-derived net position). All tiers reach the endpoint, field-gated by tier: BASIC get the bundle summary only (wallets: []), PRO adds the top-10 wallets with flags only (rank, wallet, held_ratio, has_sold, atomic, is_kol), and ULTRA adds per-wallet identity (kol_name, win_rate, bot_confidence, tokens_held).

New in 1.19.0Batch 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-mint rest.token_risk() shape (risk_score, band, factors, inputs) plus an as_of ISO-8601 timestamp; untracked mints come back as { "mint", "error": "not_tracked" } and don't fail the batch. tokens preserves de-duplicated input order. PRO/ULTRA only. Plus WebSocket session control: rest.stream_sessions() lists your live sessions across both stream services (each with id, service, tier, channels, connected_at, remote_ip, messages_sent) and rest.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 the madeonsol_stream_sessions / madeonsol_kill_stream_session (LangChain) and "MadeOnSol Stream Sessions" / "MadeOnSol Kill Stream Session" (CrewAI) tools.

New in 1.18.0Almost-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 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. sort is 'velocity_desc' (default) / 'progress_desc' / 'eta_asc'. PRO/ULTRA only (keyed). Exposed as the madeonsol_almost_bonded (LangChain) / "MadeOnSol Almost Bonded" (CrewAI) tool. Plus rest.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.0Token money-flow. client.token_flow(mint, window="1h") (and the async await client.token_flow_async(mint, window="1h")) aggregates buy/sell pressure for a token over a rolling '1h' or '24h' window. Returns mint, window, from, unique_wallets, unique_buyers, unique_sellers, buy_count, sell_count, total_trades, buy_sol, sell_sol, net_sol, and trades_per_wallet. PRO+ (keyed). Also: deployer_alerts() items now carry deployer_sol_balance (float | None) — the deployer wallet's SOL balance at alert time (None for historical rows).

New in 1.16.0Live 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, plus metric_type, outcome, methodology, as_of; per-day series when history=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.0Token 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 has t, open, high, low, close, volume_usd, trades, and market_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.0Token risk score. rest.token_risk(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). PRO/ULTRA only.

New in 1.13.0rest.tokens_list() gains three new filter params: min_liq_mc_ratio, max_liq_mc_ratio, and deployer_tier ('elite' | 'good' | 'moderate' | 'rising' | 'cold' | 'unranked'). Response items now include liquidity_to_mc_ratio and deployer_tier. KOL leaderboard entries now include median_hold_minutes_30d and percentile_early_entry_30d. /token/{mint} and /token/batch responses now include liquidity_to_mc_ratio, launch_cohort_sol, and launch_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 on labeled_tokens >= 3) plus avg_time_to_bond_minutes.

New in 1.12Graduation events + dump-cluster detection. Subscribe token:graduations for every pump.fun bond in real time (tracked deployer or not). 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.

New in 1.10Deshred Sniper. client.rest.sniper_recent() — deshred deploy feed ~500ms before on-chain confirmation. PRO: elite/good. ULTRA: all tiers + sniper_watchlist_add(). Use sniper:deploys WebSocket for push.

New in 1.9Price 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 returns derived: win_rate, roi, verdict, biggest_miss.

New in 1.8Universal 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_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.

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 include liquidity_to_mc_ratio and deployer_tier. Default min_liq=2000 skips phantom-MC dust; pass min_liq=0 to 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') plus history_age_seconds. /token/{mint} 400s now ship structured code, reason, received_length, example, and docs. Deprecated avg_entry_mc_usd fully removed.

Quick start (10 seconds)

pip install madeonsol-x402
from madeonsol_x402 import MadeOnSolClient
client = MadeOnSolClient(api_key="msk_...")  # free tier at https://madeonsol.com/pricing
trades = client.kol_feed(limit=5, action="buy")

Authentication

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= or RAPIDAPI_KEY, get a free msk_ key at madeonsol.com/pricing.

Install

pip install madeonsol-x402                    # core SDK
pip install madeonsol-x402[langchain]         # + LangChain tools
pip install madeonsol-x402[crewai]            # + CrewAI tools

x402 dependencies are only needed when using private_key / SVM_PRIVATE_KEY.

Quick Start

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 money-flow (new in 1.17)

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.

Real-time streaming (new in 1.11)

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), token:locks (event token:lock — every NEW Streamflow / Jupiter Lock / Bonfida lock or vesting contract, PRO+; LP locks not included), token:fee_claims (event token:fee_claim — every pump.fun fee event: distributions, social-handle claims, SharingConfig changes, PRO+; history starts 2026-08-17). Lifecycle events: open, close, reconnect, heartbeat, error.

LangChain

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)

CrewAI

from madeonsol_x402.crewai_tools import ALL_TOOLS

agent = Agent(role="Solana Analyst", tools=ALL_TOOLS)

Endpoints

KOL Intelligence (x402-priced — also reachable via msk_ API key)

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")
token_candles(mint, tf=, limit=, from_=, to=) New 1.22 · OHLCV candles, keyless (PRO slice: 30d). $0.01
almost_bonded(**filters) New 1.22 · Pre-bond pump.fun tokens near graduation, ranked by velocity. $0.01
token_top_traders(mint, limit=, sort=, window_days=, min_bought_sol=) New 1.22 · Wallets ranked by realized PnL/ROI on a token, enriched with KOL/alpha identity. $0.02
token_cap_table(mint) New 1.22 · Early-buyer cap table with PnL/exit/bundle/KOL flags. $0.02
sniper_recent(since=, deployer_tier=, min_bond_rate=, limit=) New 1.22 · Deshred pre-confirm deploy feed (keyless: elite/good scope) with per-deploy footprint snipe rollup. $0.01
deployer_trajectory(wallet) New 1.22 · Deployer skill curve — streaks, rolling bond rate, trend. $0.01
discovery() Free — list all endpoints and prices (25 keyless x402 endpoints)

REST API — KOL/deployer detail

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
rest.deployer_history(wallet, limit=90) New 1.20

Alpha Wallet Intelligence

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)

Token Quality

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.token_bundle(mint) New 1.20 · All Bundle-cohort holdings — bundle summary with held_pct_of_supply (headline), bundle_kind, fully_exited. BASIC=summary only, PRO=+top-10 wallet flags, ULTRA=+identity
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
rest.token_trades(mint, limit=, cursor=, action=, wallet=, since=, until=) New 1.22 · PRO+ Mint-scoped trade tape — cursor-paginated raw trades, default FULL history (capture starts 2026-04-12, pump.fun-pipeline scoped; see the coverage block)
rest.token_pools(mint) New 1.20 · PRO+ Per-venue liquidity map — every DEX pool a token trades in, live vs parked. pools array + summary with total_liquidity_usd, primary_dex, top_pool_share_pct
rest.token_holders(mint) New · PRO+ Live holder census + concentration — who holds NOW. concentration.holder_count is EXACT (mint-scoped getProgramAccounts census; None only when the provider refuses a mega-cap → top-20 fallback with source.census_fallback_reason, never trade-estimated). Each disclosed owner labelled deployer/kol/early_buyer/bundle/bot/dump_cluster; pools / bonding curves / burns EXCLUDED from the circulating denominator and NAMED in excluded[] (pool+dex+pool_address | bonding_curve | burn | program_account). Amounts are raw u64 STRINGS. Disclosure PRO=10, ULTRA=50, BUSINESS=100. Big tokens: first call may be HTTP 503 holder_scan_in_progress (retry_after_seconds: 20) — scan continues + cached, retry is instant. Exposed as madeonsol_token_holders (LangChain) / "MadeOnSol Token Holders" (CrewAI). Key-mode only (not on the x402 rail)
rest.token_locks(mint, status=, program=, limit=) New 1.27 · PRO+ Token locks & vesting on a mint — every Streamflow / Jupiter Lock / Bonfida vesting contract: schedule (start / cliff / period / end), terms (cancelable_by_sender / _recipient, transferable, can_topup), live-derived locked_raw / unlocked / withdrawn / claimable / status / next_unlock, and a summary (exact lock_count, distinct_lockers, locked / deposited raw + ui + usd + % of supply, unlocking_7d_* / unlocking_30d_*, active_cancelable_by_sender). Base-unit amounts are STRINGS; ui/usd/pct None when unknown. LP locks NOT included. Key-mode only
rest.token_locks_feed(since=, before=, mint=, sender=, recipient=, program=, kind=, status=, min_usd=, min_pct_of_supply=, include_estimated=, limit=) New 1.27 · PRO+ Cross-token feed of NEW lock / vesting contracts, newest first (+ per-row token block). Cursors pagination.next_since / next_before; pushed live on WS token:locks. Backfilled Jupiter rows excluded unless include_estimated=True. Key-mode only
rest.token_unlocks(within=, mint=, program=, kind=, min_usd=, min_pct_of_supply=, sort=, limit=) New 1.27 · PRO+ Upcoming unlock EVENTS (cliff / period / final / tranche) across all active contracts inside within=1h…90d (default 7d): unlock_at, in_seconds, amount_*, window_amount_* (total release over the window), token, lock. `sort=soonest
rest.token_fee_shares(mint) New 1.27 · PRO+ pump.fun creator-fee SharingConfig on a mint: shareholders[] with share_bps, is_admin, is_social_pda (+ social.platform 2 = X, social.user_id numeric id, lifetime claimed), redirected_bps, social_bps, is_default (True = 100% to creator), config.source stream|chain; distributions rollup (per-recipient received, past_recipients), history, recent_distributions. Quote base-unit amounts are STRINGS. Fee history starts 2026-08-17. Key-mode only
rest.token_fee_claims(type=, mint=, recipient=, actor=, social_platform=, social_user_id=, min_sol=, since=, before=, limit=) New 1.27 · PRO+ pump.fun fee-event feed, newest first: distribution (+ payouts[]), social_claim, shares_created / shares_updated / shares_reset, creator_transferred; creator_claim only when requested via type=. Cursor pagination.next_since; pushed live on WS token:fee_claims. History starts 2026-08-17. Key-mode only

Deshred Sniper Alerts (new in 1.10)

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 deployers

KOL Coordination Alerts (v1.1 — push signals)

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.

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 ONCE

coordination_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.

KOL First-Touch Signal (new in 1.3)

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 ONCE

CRUD: 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+).

Price Alerts (new in 1.9)

CRUD for token dip/recovery price alerts. Fires via WebSocket (price_alert:events 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 ONCE

price_alerts_list(), price_alerts_get(id), price_alerts_update(id, **fields), price_alerts_delete(id).

LangChain: MadeOnSolPriceAlertsListTool, MadeOnSolPriceAlertsCreateTool. CrewAI: same names via ALL_TOOLS.

Scout Leaderboard & KOL Consensus (new in 1.9)

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 Derived Stats (new in 1.9)

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 missed

Copy-Trade Rules (PRO/ULTRA)

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.

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)

Wallet Tracker

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

Universal Wallet API (new in 1.8)

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 'none'/'low'/'medium'/'high', is_deployer + tokens_deployed; new 1.22: is_sniper / is_bundler / is_dumper + dump_cluster)
rest.wallet_batch_classify(wallets) New 1.22 · Bulk reputation flags for 1–100 wallets in one call — is_sniper/is_bundler/is_dumper/is_kol, bot_confidence, dump_cluster. Pump.fun-pipeline scoped: False = not observed, not verified clean
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.

Webhooks + Streaming

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

Rate-limit headers

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")

DEX Firehose (Ultra) — WebSocket

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.

Tiers

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
BUSINESS €400/mo (€4000/yr) ≈ $449 500 + WS events 500,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.

Also Available

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

License

MIT

About

Python SDK for MadeOnSol x402 API — LangChain & CrewAI tools included

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages