npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@madeonsol/plugin-madeonsol

v1.30.1

Published

ElizaOS plugin for MadeOnSol — Solana KOL intelligence and deployer analytics via x402 micropayments

Readme

@madeonsol/plugin-madeonsol

npm version npm downloads ElizaOS License: MIT

📚 API docs · 💰 Free API key · 🤖 ElizaOS

ElizaOS plugin for MadeOnSol — Solana KOL trading intelligence, deployer analytics, and wallet tracking.

Real-time Solana trading intelligence: track 2,000+ KOL wallets with <3s latency on paid keys and x402 pay-per-call (free-tier live feeds are 5-min delayed), score 85K+ Pump.fun deployers, expose bundle-cohort held-% of supply (the rug/insider signal), verify any wallet's CURRENT on-chain holdings straight from its token accounts, surface deshred deploy signals ~500ms before on-chain confirmation, detect multi-KOL coordination, and stream every DEX trade. Free tier: 200 requests/day across 40+ endpoints (live feeds 5-min delayed) — no signup payment. Get a key at madeonsol.com/pricing.

New in 1.29.0: token lock provenance. Typed + action description: Token lock rows carry provider (identity verified | compatible | unverified; lock_url always null on Solana, never constructed), explorer (Solana Explorer links), price_usd, seconds_until_end, seconds_until_next_unlock and, for Bonfida, the tranche schedule (server 2026-10-02). Additive only.

New in 1.30.0: TradeCoverage.size_floor is typed, and the holder census action names every fallback reason (provider refusal, timeout, or a census refused because its balances exceeded the supply).

New in 1.28.1: descriptions match the API. Token risk is described as risk evidence for your own policy, not a verdict (no "safety score" wording). The deployer-profile description names the fields the API returns: is_deployer and the nested deployer object (total_tokens_deployed, ...); an untracked wallet returns is_deployer: false and deployer: null.

New in 1.28.0 — per-rule copy-trade signals really filter now. client.copyTradeSignals({ subscription_id }) sends subscription_id, the parameter the API reads. Before, it sent rule_id, which the API ignores, so a per-rule request silently returned the signals of every rule. rule_id still works as a deprecated alias. copyTradeSignals also gains min_mc_usd / max_mc_usd. client.getWalletTrackerTrades() gains order (slot | block_time) and the before_slot cursor, and its action type is "buy" | "sell" (transfers have action: null; select them with event_type: "transfer"). The WALLET_TRACKER_TRADES action no longer prints "null" for transfers. Copy-trade docs: per-rule wallet limits are PRO 5, ULTRA 50, BUSINESS 250 (Enterprise follows Business), enforced by the server, and signals fire only for trades by tracked KOL wallets (GET /api/v1/kol/wallets).

New in 1.26.0 — top traders, sniper detection, and two update actions. Found by an internal agentic-infra coverage audit. GET_TOKEN_TOP_TRADERS (client.getTokenTopTraders(mint, params?)) ranks a token's wallets by realized PnL or ROI with KOL/alpha-wallet identity — existed on the REST API but had no action. GET_SNIPER_RECENT / GET_SNIPER_BY_DEPLOYER and the new sniper-watchlist actions (SNIPER_WATCHLIST_LIST / _ADD / _REMOVE) bring the deshred pre-confirm deploy feed to this plugin for the first time. client.updateWebhook(id, params) (PATCH) and client.relabelWatchlist(address, label) (PATCH) round out the CRUD surface that previously only supported create/list/delete.

New in 1.25.0 — deployer reputation as-of a date, and creator-fee rewards. Two new actions + typed client methods (PRO+, keyed msk_ API only — no x402 route). GET_DEPLOYER_AS_OF (client.getDeployerAsOf(wallet, date?), typed DeployerAsOf) binds GET /deployer-hunter/{wallet}/as-of: the deployer's reputation exactly as it stood on date (default today, UTC) — the latest write-on-change snapshot at or before it, so a backtest sees only what was knowable then. snapshot.snapshot_date can predate date (write-on-change); snapshot.carried: true marks that. No snapshot at or before date → as_of: false, snapshot: null — nothing is ever synthesized. date must be ≥ 2026-04-07 and not in the future. GET_DEPLOYER_REWARDS (client.getDeployerRewards(wallet), typed DeployerRewards) binds GET /deployer-hunter/{wallet}/rewards: pump.fun creator-fee rewards, answered two ways that are never merged — collected (what actually reached the wallet: direct vault claims kept 90 days, social-handle claims, shareholder payouts on any token) and attributed (every payout on the tokens it deployed, split to_self/to_others + redirected_pct). Every money field is {sol, usdc, usd}; usd is null (never a silent 0) when a SOL amount exists and no SOL price was available. top_tokens/top_recipients (≤10, USD-sorted) show where attributed fees went. Works for non-deployers too (is_deployer: false, attributed empty).

New in 1.24.0 — token surges & revivals: momentum fires with the honest half attached. The new GET_TOKEN_SURGES action (client.getTokenSurges(params?), typed TokenSurges / TokenSurgeEvent) binds GET /tokens/surges (PRO+, keyed msk_ API only — no x402 route): every token momentum fire, newest first. Two kinds, one row shape. surge — a token < 30 min old whose market cap runs hard against its launch MC, in three tiers that each fire at most once per mint: early (≤10 min, ≥$12k, ≥3× launch), strong (≤30 min, ≥$30k, ≥6× launch and ≥2× the lowest sample of the last 3 min — it is climbing now), breakout (≤2 min, ≥$45k, ≥8×). A tier must be sustained (current tick and a sample ≥10 s older; nothing fires before 20 s of age) — a same-slot bundle marked to $475k at age 1 s is a spike, not a surge. revival — a token with no 1-minute trade candle for ≥24 h that starts trading again, confirmed only by the tape (≥5 buys, ≥$500 buy volume, MC ≥1.5× the pre-dormancy close), never by the price mark; tier is null. Hard gates on both: liquidity ≥$1.5k and ≥2 % of MC, and the MC gained must be paid for by buy volume (a price mark in a spoof pool moves MC on ~$0). Every row carries the burst tape (source candles / wallet_trades; unique_buyers only where the mint is in trade coverage — wallet_data_available:false otherwise, never an inferred zero), kol buyers, the first-20 early_buyers cohort (bundled / sold / sniper wallets), deployer reputation and risk_flags[] (bundled_launch, few_buyers, wash_pattern, thin_liquidity, cold_deployer, sniper_heavy, early_buyers_exiting, sell_pressure, no_tape_trades, no_prior_price, mint_authority_active, transfer_fee — empty means no flag raised, not verified clean). Rows ≥65 min old carry the +1 h outcome; stats: "1" prints per-(kind, tier) hit-rates (up_1h_pct, median_peak_multiple, doubled_1h_pct) — out-of-sample by construction. Filters kind, tier, mint, launchpad, deployer_tier, min_mc_usd / max_mc_usd, min_buys, exclude_flags, only_clean; cursors since / before. Pushed live on the new token:surges WS channel (events token:surge / token:revival; subscribe filters kinds[], tiers[], launchpads[], exclude_flags[], min_mc_usd / max_mc_usd, deployer_tier[]) and accepted by the webhook registry as events token:surge / token:revival with the same filters.

New in 1.23.1 — stream tokens never expire. client.getStreamToken() (POST /stream/token) now returns the same token on every call, forever. It stops working only if your subscription lapses or you call client.getStreamToken({ rotate: true }) to replace it (the previous value keeps working for 60 s). expires_at and the new next_refresh_at are always null (kept for wire compatibility — do not schedule refreshes on them); the response gains rotated (boolean) and lifetime (string). The server never rotates on its own and never sends token_refresh unless you rotated; a 4001 close means "mint again" (lapsed or rotated), never a timer. Prefer Authorization: Bearer <token> on the WebSocket handshake — ?token= still works and is masked in access logs.

New in 1.23.0 — token locks & vesting, upcoming unlocks, and pump.fun creator-fee sharing / claims. Five new actions + typed client methods (all PRO+, keyed msk_ API only — no x402 route). GET_TOKEN_LOCKS (client.getTokenLocks(mint, { status?, program?, limit? }), typed TokenLocks) binds GET /tokens/{mint}/locks: every on-chain lock / vesting contract on a mint (Streamflow, Jupiter Lock, Bonfida vesting) with the schedule, the terms (cancelable_by_sender = the locker can pull it — funds are locked against the recipient, not the locker) and a live-derived view (locked_*, claimable_*, next_unlock) plus a summary with 7d / 30d forward unlock totals. GET_TOKEN_LOCKS_FEED (client.getTokenLocksFeed(params), TokenLocksFeed) is the cross-token feed of NEW contracts (cursor pagination.next_since, or push on WS channel token:locks, event token:lock); GET_TOKEN_UNLOCKS (client.getTokenUnlocks(params), TokenUnlocks) lists upcoming unlock EVENTS (cliff / period / final / tranche) inside a 1h–90d window sorted by soonest / largest_usd / largest_pct. LP locks are not included — token/vesting locks only. GET_TOKEN_FEE_SHARES (client.getTokenFeeShares(mint), TokenFeeShares) decodes a pump.fun coin's on-chain SharingConfig — shareholders with share_bps, is_admin, is_social_pda (fees earmarked for an X identity: social.platform 2 = X, user_id = the numeric platform id, not the handle), redirected_bps, is_default: true = 100% to the creator — plus a distributions rollup and config history; GET_TOKEN_FEE_CLAIMS (client.getTokenFeeClaims(params), TokenFeeClaims) is the fee-event feed (distribution with per-address payouts[], social_claim, shares_created/updated/reset, creator_transferred, creator_claim only when asked via type), pushed on WS channel token:fee_claims (event token:fee_claim). Fee-event history starts 2026-08-17. All base-unit amounts are digit strings; ui / usd / pct are null when decimals or price are unknown.

New in 1.22.0 — live holder census: exact holder count, labelled holders, and pools that are named, not just excluded. The new GET_TOKEN_HOLDERS action (client.getTokenHolders(mint), typed TokenHolders) 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.

New in 1.21.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. GET_TOKEN_TRADES now prints the executed price on each line, and TokenTradeEntry types all four fields.

New in 1.20.0 — the Deployer Hunter surface completed. Seven new operations that existed on the API but had no SDK binding: a single GET_DEPLOYER_HUNTER action that routes by intent across the leaderboard, chain stats, one deployer's profile and launches, alert-volume stats, best recent tokens and fresh graduations. 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.19.0 — Token depth / price impact + deployer self-activity on risk. New action GET_TOKEN_DEPTH + client.getTokenDepth(mint, { sizes? }) (GET /tokens/{mint}/depth) — per-pool price-impact / slippage: "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]); every computable pool returns spot_price_sol, fee_pct, a quotes[] entry per size (size_sol, 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 bonding curves from a live read of the curve's virtual reserves (source: "live_rpc"). Pools that can't be priced 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) instead of a wrong number; primary_pool names the deepest computable pool, found: false means no pool with sufficient authoritative data for depth (see unsupported_pools[].reason; tracked pools may still be listed there) (typed TokenDepth). PRO/ULTRA only. And client.getTokenRisk(mint) (GET_TOKEN_RISK) now returns a top-level dev block (typed TokenRiskDev | null; null = no deployer-pipeline row): 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 — wallet_empty: is the dev wallet empty NOW), and transferred_out (tokens left without a sell; null = unknown, never a guess), plus as_of. deployer:alert webhook/WS payloads gain dev_buy_sol + dev_buy_supply_pct.

New in 1.18.0 — Wallet batch classify + token trade tape. New action GET_TOKEN_TRADES + client.getTokenTrades(mint, { limit, cursor, action, wallet, since, until }) (GET /tokens/{mint}/trades) — the mint-scoped trade tape: every captured trade, cursor-paginated newest first, each with tx_signature, wallet_address, action, sol_amount, token_amount, price_sol/price_usd, early_buyer_rank, slot, block_time. Default window is the full history (tape starts 2026-04-12; the response coverage block carries history_start + scope — capture is pump.fun-pipeline scoped). New client method client.classifyWallets(wallets) (POST /wallet/batch/classify, 1–100 addresses) — bulk reputation flags per wallet: is_sniper, is_bundler (lifetime), is_dumper (rolling 42d), is_kol + kol_name, bot_confidence, dump_cluster cohort stats. Flags are pump.fun-pipeline scoped: false = not observed, NOT verified clean. Wallet-profile flags (WALLET_STATS) gain the same is_sniper/is_bundler/is_dumper + dump_cluster fields, and bot_confidence is a type fix: it's a string enum "none" | "low" | "medium" | "high" | null (the old number | null typing never matched a real value — the API returned null unconditionally due to a bug, now fixed). Both PRO+.

New in 1.17.0 — Verified on-chain wallet holdings. New action WALLET_HOLDINGS + client.getWalletHoldings(address, { limit, min_value_usd }) (GET /wallet/{address}/holdings) — the wallet's CURRENT holdings read straight from chain: its actual SPL + Token-2022 token accounts and SOL balance, each enriched with price_usd / value_usd / market_cap_usd / name / symbol / is_bonded, plus transfer_delta (on-chain amount − trade-derived net position — exposes non-swap flows like airdrops, insider funding, wallet-hopping). Distinct from WALLET_POSITIONS (trade-derived FIFO): this is what the wallet actually holds right now. limit 1–500 (default 200), min_value_usd ≥0 (default 0). Returns { address, sol_balance, holdings[], summary, verified_at, trade_window_days, cache_hit, ttl_seconds }. ULTRA only.

New in 1.16.2 — Per-venue pools + deployer reputation history. Two new actions + client methods. GET_TOKEN_POOLS + client.getTokenPools(mint) (GET /tokens/{mint}/pools) — the per-venue liquidity map: every DEX pool a token trades in, live vs parked, with fragmentation and top-pool concentration. Each pool carries pool_address, dex, quote_mint, liquidity_usd, last_price_sol, last_swap_at, amm_id, is_active; summary rolls up pool_count, active_pool_count, dex_count, dexes, total_liquidity_usd, primary_pool, primary_dex, top_pool_share_pct. And GET_DEPLOYER_HISTORY + client.getDeployerHistory(wallet, limit?) (GET /deployer-hunter/{wallet}/history?limit=N) — a deployer's daily reputation time-series so you can backtest "was this deployer elite when it launched token X?" without look-ahead bias. Returns is_deployer, wallet, and snapshots[] (date, tier, is_tracked, total_deployed, total_bonded, bonding_rate, recent_bond_rate, avg_peak_mc, best_token_peak_mc); limit is days (1–365, default 90). PRO+.

New in 1.16.0 — Bundle-cohort holdings. New action GET_TOKEN_BUNDLE + client.getTokenBundle(mint) (GET /tokens/{mint}/bundle) — which same-slot "bundle" wallets (≥3 buying in one slot) bought a token and how much of supply they STILL hold, straight from confirmed on-chain data. The bundle block carries wallet_count, bundle_kind (atomic_tx/same_slot/none), held_ratio, held_pct_of_supply (the headline rug/insider signal, 0–1 or null), fully_exited, buy_volume, and tokens_held. Tier-gated: BASIC get the bundle block only (wallets: []); PRO adds a top-10 flags-only wallets[] (rank, held_ratio, has_sold, atomic, is_kol); ULTRA adds identity (kol_name, win_rate, bot_confidence, tokens_held).

New in 1.15.0 — Batch risk scoring + live WebSocket session control. Two client methods: client.getTokenRiskBatch(mints) scores up to 50 mints in one call (POST /tokens/batch/risk) — each entry is the single-mint risk shape plus an as_of timestamp, or { mint, error: "not_tracked" } for untracked mints (which don't fail the batch); returns { tokens, count } in de-duplicated input order and counts as one request. And client.getStreamSessions() lists your live WebSocket sessions ({ id, service, tier, channels, connected_at, remote_ip, messages_sent }) while client.deleteStreamSession(id) force-evicts one by id to free a connection slot. Both PRO/ULTRA only.

New in 1.14.0 — Almost-bonded discovery + trending sorts. New action MADEONSOL_ALMOST_BONDED + client.getAlmostBonded(params) — 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. Params: min_progress, max_progress, min_velocity_pct_per_min, max_age_minutes, deployer_tier, authority_revoked, min_liq, sort (velocity_desc / progress_desc / eta_asc), limit. PRO/ULTRA only. Plus client.getTokensList({ 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.13.0 — Token net flow. New action GET_TOKEN_FLOW + client.getTokenFlow(mint, { window }) — net buy/sell flow over a rolling window (1h default, or 24h): unique_wallets, unique_buyers, unique_sellers, buy_count, sell_count, total_trades, buy_sol, sell_sol, net_sol, trades_per_wallet. PRO+. Deployer alerts now also surface deployer_sol_balance — the deployer wallet's SOL balance at alert time (null for historical rows).

New in 1.12.0 — Token OHLCV candles. New action GET_TOKEN_CANDLES + client.getTokenCandles(mint, { tf, limit, from, to }) — historical price candles (1m/5m/15m/1h/4h/1d) aggregated from the on-chain trade firehose. Each candle has t/open/high/low/close/volume_usd/trades/market_cap_usd. PRO returns OHLCV for the last 30 days; ULTRA adds buy/sell volume + count splits, net flow, MEV volume, open/close liquidity, high/low MC, and full history. PRO/ULTRA only.

New in 1.11.0 — Token risk score. New action GET_TOKEN_RISK + client.getTokenRisk(mint) — 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.10.0 — client.getTokensList() gains three new filter params: min_liq_mc_ratio, max_liq_mc_ratio, and deployer_tier. 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 endpoints now return liquidity_to_mc_ratio, launch_cohort_sol, and launch_cohort_size.

New in 1.9.3 — Deployer alerts now surface runner_rate + labeled_tokens (fraction of a deployer's labeled tokens that ran vs dumped, gate on labeled_tokens ≥3) and avg_time_to_bond_minutes.

New in 1.9.2 — Dump-cluster detection. Buyer-quality breakdown now includes dump_cluster_count (3+ dump-cluster wallets in the first-20 → 94% historical dump rate vs 61% base) and recycled_early_buyer_count, on all tiers. The API also pushes every pump.fun graduation in real time (token:graduations WS channel).

New in 1.9 — Price alerts, scout leaderboard, coordination history, wallet derived stats. PRICE_ALERTS_* actions (PRO=5, ULTRA=25 rules). SCOUT_LEADERBOARD, KOL_CONSENSUS, PEAK_HISTORY, COORDINATION_HISTORY. WALLET_STATS now returns derived: win_rate, roi, verdict, biggest_miss.

New in 1.8 — Universal Wallet API. WALLET_STATS, WALLET_PNL, WALLET_POSITIONS, WALLET_TRADES — FIFO cost-basis PnL and raw trades for any Solana wallet. PRO+. Cache hits free.

New in 1.7.0 (2026-05-12) — Account introspection + token scanner actions. Two new actions: meAction (GET_MADEONSOL_ACCOUNT) reports the caller's tier, daily/burst quota, and webhook / copy-trade / coord-rule slot counts; tokensListAction (LIST_MADEONSOL_TOKENS) scans the Solana token universe by MC, liquidity, 1h momentum, and primary DEX. New client methods: client.getMe() and client.getTokensList(params). Token responses now expose velocity / MEV-share enrichment fields. The /tokens scanner applies a default min_liq=2000 so the agent isn't drowned in dust pools by default. /token/{mint} HTTP 400s now return structured code / reason / example / docs so the agent can self-correct bad mints. Deprecated avg_entry_mc_usd has been removed from all leaderboard payloads.

Quick start (10 seconds)

npm install @madeonsol/plugin-madeonsol
import { madeOnSolPlugin } from "@madeonsol/plugin-madeonsol";
const agent = { plugins: [madeOnSolPlugin], settings: { MADEONSOL_API_KEY: "msk_..." } }; // free tier at https://madeonsol.com/pricing
// Then ask the agent: "What are KOLs buying right now?"

Authentication

Three options (in priority order):

| Method | Setting | Best for | |---|---|---| | MadeOnSol API key (recommended) | MADEONSOL_API_KEY | Developers — get a free key | | x402 micropayments | SVM_PRIVATE_KEY | AI agents with Solana wallets |

x402 paid-result recovery (PAY-05): NOT supported by this plugin. The SVM_PRIVATE_KEY mode pays through the upstream @x402/fetch wrapper. It has no payment policy (SDK-01), no PAYMENT-RECOVERY signer and no bounded recovery of a paid call whose answer was lost or is still pending. It does not provide PAY-05-compatible automatic recovery, and a failed paid call can end in a second payment if you call again. Until this plugin moves to the SDK-01 payment policy, use a MADEONSOL_API_KEY, or pay keyless through madeonsol-x402 / mcp-server-madeonsol / solana-agent-kit-plugin-madeonsol, which do implement PAY-05 recovery.

What it does

Gives your ElizaOS agent access to MadeOnSol's Solana intelligence API.

| Action | Description | |--------|-------------| | GET_KOL_FEED | Real-time KOL trade feed (1,000+ wallets) | | GET_KOL_COORDINATION | Multi-KOL convergence (v1.1 — peak-density, exits, 0-100 score) | | GET_KOL_LEADERBOARD | KOL PnL/win-rate rankings (180 days of history) | | GET_DEPLOYER_ALERTS | Pump.fun deployer alerts with KOL enrichment | | WALLET_TRACKER_WATCHLIST | List your tracked wallets and remaining capacity | | WALLET_TRACKER_TRADES | Recent swaps and transfers from your watchlist | | GET_MADEONSOL_ACCOUNT | Your tier, daily quota, burst limit, and slot usage (new in 1.7.0) | | LIST_MADEONSOL_TOKENS | Scan tokens by MC, liquidity, 1h momentum, primary DEX, plus momentum sorts (mc_change_5m_desc/mc_change_1h_desc/volume_1h_desc/trending) (new in 1.7.0) | | MADEONSOL_ALMOST_BONDED | New 1.14 · Pre-bond pump.fun tokens near graduation, ranked by velocity — progress_pct, velocity_pct_per_min, eta_minutes, stalled, deployer_tier (PRO+) | | WALLET_STATS | New 1.8 · Stats + cross-product flags (is_kol, is_alpha_tracked + bot_confidence, is_deployer; 1.18 adds is_sniper/is_bundler/is_dumper + dump_cluster) for any wallet (PRO+) | | WALLET_PNL | New 1.8 · Full FIFO PnL — realized + unrealized, profit factor, drawdown, hold times, top winners (PRO+) | | WALLET_POSITIONS | New 1.8 · Open positions with live unrealized SOL from market-cap tracker (PRO+) | | WALLET_HOLDINGS | New 1.17 · Verified CURRENT on-chain holdings (real SPL + Token-2022 accounts + SOL) enriched with price/MC/name, plus transfer_delta vs trade-derived position (ULTRA only) | | WALLET_TRADES | New 1.8 · Recent trades for any wallet, filtered by action (PRO+) | | GET_TOKEN_RISK | New 1.11 · Transparent 0–100 risk score (evidence, not a verdict) with band + explainable factors; 1.19 adds the dev block — deployer self-buy at create, sells rollup, live on-chain holdings, wallet_empty, transferred_out (PRO+) | | GET_TOKEN_CANDLES | New 1.12 · Historical OHLCV candles (1m–1d). PRO=OHLCV 30d; ULTRA=+net flow, liquidity delta, full history (PRO+) | | GET_TOKEN_FLOW | New 1.13 · Net buy/sell flow over a 1h/24h window — unique wallets/buyers/sellers, buy/sell counts, buy/sell/net SOL, trades-per-wallet (PRO+) | | GET_TOKEN_TRADES | New 1.18 · Mint-scoped trade tape — cursor-paginated raw trades with price + early-buyer rank, full history (starts 2026-04-12, pump.fun-pipeline scoped) (PRO+) | | GET_TOKEN_BUNDLE | New 1.16 · Bundle-cohort holdings — same-slot "bundle" wallets and their held_pct_of_supply (rug/insider signal). BASIC=summary; PRO=top-10 flags; ULTRA=+KOL identity | | GET_TOKEN_POOLS | New 1.16.2 · Per-venue liquidity map — every DEX pool a token trades in, live vs parked, plus fragmentation + top-pool share (PRO+) | | GET_TOKEN_DEPTH | New 1.19 · Per-pool price impact / slippage — quotes per SOL buy size + SOL to move price 1%/5%/10%; unsupported pools flagged with a reason (PRO+) | | GET_TOKEN_HOLDERS | New · Live holder census + concentration — who holds NOW (client.getTokenHolders(mint)). concentration.holder_count is EXACT (mint-scoped getProgramAccounts census; null only when the provider refuses a mega-cap → top-20 fallback with source.census_fallback_reason, never trade-estimated). Owners labelled deployer / kol / early_buyer / bundle / bot / dump_cluster (empty = unknown, not clean); pools / bonding curves / burns EXCLUDED from circulating and NAMED in excluded[] (pool + dex + pool_address, bonding_curve, burn, program_account); amount_raw is a raw u64 STRING. Disclosure PRO 10 / ULTRA 50 / BUSINESS 100. Big tokens: first call may be HTTP 503 holder_scan_in_progress (retry in 20 s — scan continues + cached) (PRO+) | | GET_TOKEN_LOCKS | New 1.23 · Token locks & vesting on a mint (client.getTokenLocks(mint, params?)) — every Streamflow / Jupiter Lock / Bonfida contract: program, kind (lock / vesting), derived status, sender / recipient, schedule, terms (cancelable_by_sender — the locker can pull it), live locked_* / claimable_* / next_unlock, plus summary (unlocking_7d_* / unlocking_30d_*, nearest next_unlock, active_cancelable_by_sender). Base-unit amounts are STRINGS; ui/usd/pct null when unknown. LP locks not included (PRO+, keyed only) | | GET_TOKEN_LOCKS_FEED | New 1.23 · Cross-token feed of NEW lock / vesting contracts, newest first (client.getTokenLocksFeed(params?)) — filters mint, sender, recipient, program, kind, status, min_usd, min_pct_of_supply, include_estimated; cursors since / before. Push: WS channel token:locks (event token:lock) (PRO+, keyed only) | | GET_TOKEN_UNLOCKS | New 1.23 · Upcoming unlock EVENTS across all active contracts inside within = 1h–90d (client.getTokenUnlocks(params?)) — one entry per contract = its next event (cliff / period / final / tranche) with amount_* + window_amount_*, token, lock; sort soonest / largest_usd / largest_pct (PRO+, keyed only) | | GET_TOKEN_FEE_SHARES | New 1.23 · pump.fun creator-fee SharingConfig on a coin (client.getTokenFeeShares(mint)) — shareholders[] (share_bps, is_admin, is_social_pda + social {platform (2 = X), user_id, lifetime_claimed}, received_*), redirected_bps, is_default, source stream / chain; distributions rollup, history[], recent_distributions[]. Event history starts 2026-08-17 (PRO+, keyed only) | | GET_TOKEN_FEE_CLAIMS | New 1.23 · pump.fun fee-event feed, newest first (client.getTokenFeeClaims(params?)) — type distribution (with payouts[]) / social_claim / shares_created / shares_updated / shares_reset / creator_transferred / creator_claim (excluded unless type asks); filters mint, recipient, actor, social_platform, social_user_id, min_sol, since / before. Push: WS channel token:fee_claims (event token:fee_claim). History starts 2026-08-17 (PRO+, keyed only) | | GET_TOKEN_SURGES | New 1.24 · Token surges & revivals — momentum fires, newest first (client.getTokenSurges(params?)). kind surge (token < 30 min old vs its LAUNCH MC; tier early ≤10 min ≥$12k ≥3× · strong ≤30 min ≥$30k ≥6× and ≥2× the 3-min low · breakout ≤2 min ≥$45k ≥8×; each once per mint, sustained ≥10 s) or revival (no trade candle ≥24 h, then ≥5 buys / ≥$500 buy volume / ≥1.5× the pre-dormancy MC on the tape — never a price mark; tier null). Each row: burst tape (unique_buyers null outside trade coverage), kol, early_buyers (bundled / sold / sniper), deployer, risk_flags[] (empty = no flag raised, not verified clean), outcome (+1 h) once ≥65 min old; stats: "1" = per-(kind, tier) hit-rates. Filters kind, tier, mint, launchpad, deployer_tier, min_mc_usd / max_mc_usd, min_buys, exclude_flags, only_clean; cursors since / before. Push: WS channel token:surges (events token:surge / token:revival) (PRO+, keyed only) | | GET_DEPLOYER_HISTORY | New 1.16.2 · A deployer's daily reputation time-series (tier, bonding_rate, avg_peak_mc…) — backtest "was this deployer elite when it launched?" without look-ahead bias (PRO+) |

Install

npm install @madeonsol/plugin-madeonsol

x402 peer deps (@x402/fetch @x402/svm @x402/core @solana/kit @scure/base) are only needed when using SVM_PRIVATE_KEY.

Usage

import { madeOnSolPlugin } from "@madeonsol/plugin-madeonsol";

const agent = {
  plugins: [madeOnSolPlugin],
  settings: {
    // Option 1: API key — get one free at madeonsol.com/pricing
    MADEONSOL_API_KEY: "msk_your_api_key_here",

    // Option 2: x402 micropayments (AI agents)
    // SVM_PRIVATE_KEY: "your_base58_solana_private_key",
  },
};

v1.1 Coordination alerts (programmatic)

The GET_KOL_COORDINATION action surfaces the v1.1 coordination_score, peak_kols, and exited_count fields. For push alerts (fires within ~1s of a qualifying trade via WS kol:coordination channel + HMAC-signed webhook), use the client directly from a custom action:

import { MadeOnSolClient } from "@madeonsol/plugin-madeonsol";

const client = new MadeOnSolClient({ apiKey: process.env.MADEONSOL_API_KEY });
const res = await client.coordinationAlertsCreate({
  name: "fresh pump cluster",
  min_kols: 4,
  window_minutes: 15,
  min_score: 70,
  include_majors: false,
  cooldown_min: 60,
  score_jump_break: 10,
  delivery_mode: "both",
  webhook_url: "https://you.com/hooks/coord",
});
// store res.data.webhook_secret — shown ONCE

PRO=5 rules, ULTRA=20. Also available: coordinationAlertsList(), coordinationAlertsGet(id), coordinationAlertsUpdate(id, updates), coordinationAlertsDelete(id).

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

import { MadeOnSolClient } from "@madeonsol/plugin-madeonsol";
const client = new MadeOnSolClient({ apiKey: process.env.MADEONSOL_API_KEY });

// REST query
const { events } = await client.firstTouches({ preset: "scout", min_scout_tier: "S", limit: 20 });

// Webhook subscription (Ultra) — push delivery, HMAC-signed
const { subscription, webhook_secret } = await client.firstTouchSubscriptionsCreate({
  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 webhook_secret — shown ONCE

ULTRA only for subscriptions — up to 10 active. CRUD: firstTouchSubscriptionsList(), firstTouchSubscriptionsGet(id), firstTouchSubscriptionsUpdate(id, updates), firstTouchSubscriptionsDelete(id).

Don't poll — push. Median lead time before the second KOL is 12 seconds. WebSocket channel: kol:first_touches.

Price alerts (new in 1.9)

CRUD for token dip/recovery price alerts. Fires when a token's market cap crosses your threshold. PRO=5 rules, ULTRA=25.

| Action | Description | |---|---| | PRICE_ALERTS_LIST | List your price alert rules | | PRICE_ALERTS_CREATE | Create a dip/recovery alert rule | | PRICE_ALERTS_DELETE | Delete a price alert rule |

import { MadeOnSolClient } from "@madeonsol/plugin-madeonsol";
const client = new MadeOnSolClient({ apiKey: process.env.MADEONSOL_API_KEY });

const { alert, webhook_secret } = await client.priceAlertsCreate({
  name: "SOL dip buy",
  token_mint: "So11111111111111111111111111111111111111112",
  condition: "below",
  threshold_mc_usd: 5_000_000_000,
  cooldown_min: 120,
  delivery_mode: "both",
  webhook_url: "https://you.com/hooks/price",
});
// store webhook_secret — shown ONCE

Also available: priceAlertsList(), priceAlertsGet(id), priceAlertsUpdate(id, updates), priceAlertsDelete(id).

Scout leaderboard & KOL consensus (new in 1.9)

| Action | Description | |---|---| | SCOUT_LEADERBOARD | Top scout-tier KOLs ranked by first-touch follow-on rate, win rate, and ROI (PRO+) | | KOL_CONSENSUS | Tokens with the strongest KOL agreement signal (PRO+) | | PEAK_HISTORY | Historical peak-density windows for a token (PRO+) | | COORDINATION_HISTORY | Global coordination event log (PRO+) |

Token net flow (new in 1.13)

GET_TOKEN_FLOW (or client.getTokenFlow(mint, { window })) returns net buy/sell flow over a rolling 1h (default) or 24h window. PRO+.

import { MadeOnSolClient } from "@madeonsol/plugin-madeonsol";
const client = new MadeOnSolClient({ apiKey: process.env.MADEONSOL_API_KEY });

const { data } = await client.getTokenFlow("7xKXtg2CW87d97TXJSDpbD5jBkheTqA83TZRuJosgAsU", { window: "24h" });
// { mint, window, from, unique_wallets, unique_buyers, unique_sellers,
//   buy_count, sell_count, total_trades, buy_sol, sell_sol, net_sol, trades_per_wallet }
console.log(`Net ${data.net_sol} SOL across ${data.unique_wallets} wallets`);

Deployer alerts (GET_DEPLOYER_ALERTS / client.getDeployerAlerts()) now include deployer_sol_balance — the deployer wallet's SOL balance at alert time (null for historical rows).

Token locks, unlocks & pump.fun fee sharing (new in 1.23)

All five are PRO+ and keyed-API only (no x402 route). Base-unit amounts are digit strings; ui / usd / pct fields are null when decimals or price are unknown. LP locks are not included (token/vesting locks only); fee-event history starts 2026-08-17.

import { MadeOnSolClient } from "@madeonsol/plugin-madeonsol";
const client = new MadeOnSolClient({ apiKey: process.env.MADEONSOL_API_KEY });

// Did the team lock, how much, until when, and can they pull it?
const { data: locks } = await client.getTokenLocks("NUGye8S6CV82ZNrauf5YfXL2xJxvSvfiMAvy2U1sAVk", { status: "active" });
// { mint, token, summary: { lock_count, active_count, locked_raw, locked_pct_of_supply, unlocking_7d_*, unlocking_30d_*,
//   next_unlock, active_cancelable_by_sender, ... }, locks: [ { lock_account, program, kind, status, sender, recipient,
//   amount_raw, locked_raw, claimable_raw, start_at, cliff_at, end_at, cancelable_by_sender, next_unlock, ... } ] }

// Newest lock / vesting contracts across all mints (poll with next_since, or WS channel token:locks)
const { data: feed } = await client.getTokenLocksFeed({ min_usd: 10_000, limit: 50 });
// { locks: [ { ...lock, token: { symbol, price_usd, market_cap_usd } } ], pagination: { next_since, next_before, has_more }, stream: { channel: "token:locks" } }

// What locked supply hits the market this week?
const { data: unlocks } = await client.getTokenUnlocks({ within: "7d", sort: "largest_usd" });
// { window: { within, from, to }, unlocks: [ { unlock_at, in_seconds, event, amount_raw, amount_usd, amount_pct_of_supply,
//   window_amount_*, mint, token, lock: { lock_account, program, sender, cancelable_by_sender, ... } } ], pagination: { total_in_window } }

// pump.fun creator-fee sharing: who receives what share of a coin's creator fees
const { data: shares } = await client.getTokenFeeShares("E2rQLGJxb1pq4u4AoXSAmqTbspupMXfgfbJsXU5npump");
// { config: { is_default, redirected_bps, social_bps, shareholders: [ { address, share_bps, is_admin, is_social_pda, social: { platform, user_id }, received_raw } ], source },
//   distributions: { count, total_raw, recipients, past_recipients }, history, recent_distributions }

// Fee-event feed: distributions to shareholders, social (X) claims, config changes (WS channel token:fee_claims)
const { data: claims } = await client.getTokenFeeClaims({ type: "distribution,social_claim", min_sol: 0.5 });
// { events: [ { id, type, at, tx_signature, mint, actor, recipient, amount_raw, amount_usd, social, payouts, ... } ], pagination: { next_since }, stream: { channel: "token:fee_claims" } }

Token surges & revivals (new in 1.24)

Token momentum fires with the honest half attached — PRO+, keyed-API only (no x402 route). Empty risk_flags means no flag raised, not verified clean; tape.unique_buyers is null (never an inferred zero) when the mint is outside trade coverage.

import { MadeOnSolClient } from "@madeonsol/plugin-madeonsol";
const client = new MadeOnSolClient({ apiKey: process.env.MADEONSOL_API_KEY });

// Newest surges with no risk flags — strong tier = ≥ 6× launch MC and still climbing
const { data: surges } = await client.getTokenSurges({ kind: "surge", tier: "strong", only_clean: "1", limit: 20 });
// { events: [ { kind: "surge", tier: "strong", mint, symbol, launchpad, market_cap_usd, mc_multiple, age_seconds,
//   tape: { buys, sells, buy_volume_usd, unique_buyers, wallet_data_available, source }, kol: { buyers, names },
//   early_buyers: { bundled, sold, sniper_wallets }, deployer: { tier, bonding_rate }, risk_flags: [], outcome: null | { mc_1h_multiple, peak_1h_multiple } } ],
//   pagination: { next_since, next_before, has_more }, definitions: { surge, revival, shared, risk_flags }, stream: { channel: "token:surges" } }

// Dormant tokens that woke up (confirmed by tape buys, never by a price mark) — drop bundled / sniper-heavy ones
const { data: revivals } = await client.getTokenSurges({ kind: "revival", exclude_flags: "bundled_launch,sniper_heavy", min_mc_usd: 20_000 });

// How good are the tiers, really? Out-of-sample hit-rates for the last 7 days
const { data: scored } = await client.getTokenSurges({ stats: "1", days: 7, limit: 1 });
// scored.stats.rows → [ { kind: "surge", tier: "breakout", fires, with_outcome, up_1h_pct, median_peak_multiple, doubled_1h_pct }, ... ]

Batch risk scoring & WebSocket session control (new in 1.15)

Score up to 50 mints in one request, and list/kill your live WebSocket sessions — both client-only, PRO/ULTRA.

import { MadeOnSolClient } from "@madeonsol/plugin-madeonsol";
const client = new MadeOnSolClient({ apiKey: process.env.MADEONSOL_API_KEY });

// Bulk rug-risk — one request, up to 50 mints
const { data } = await client.getTokenRiskBatch([mintA, mintB, mintC]);
// { tokens: [ { mint, risk_score, band, factors, inputs, as_of } | { mint, error: "not_tracked" } ], count }

// Live WebSocket sessions
const { data: s } = await client.getStreamSessions();
// { sessions: [ { id, service, tier, channels, connected_at, remote_ip, messages_sent } ], count }
await client.deleteStreamSession(s.sessions[0].id); // → { evicted: true, id }

Wallet batch classify (new in 1.18)

Bulk reputation flags for 1–100 wallets in one request — client-only (like batch risk), PRO+.

import { MadeOnSolClient } from "@madeonsol/plugin-madeonsol";
const client = new MadeOnSolClient({ apiKey: process.env.MADEONSOL_API_KEY });

const { data } = await client.classifyWallets([buyerA, buyerB, buyerC]);
// { wallets: [ { address, is_sniper, is_bundler, is_dumper, is_kol, kol_name,
//                bot_confidence: "none"|"low"|"medium"|"high"|null,
//                dump_cluster: { dump_cohorts, runner_cohorts, total_cohorts, as_of } | null } ],
//   count, as_of }

Semantics — flags are pump.fun-pipeline scoped: false means "not observed by our pipeline", NOT verified clean. is_bundler is a lifetime flag; is_dumper is a rolling 42-day window.

Wallet derived stats (new in 1.9)

WALLET_STATS now returns a stats object with derived fields: win_rate (0-1), roi, verdict ("strong" | "profitable" | "neutral" | "losing"), and biggest_miss (token with the highest post-exit gain the wallet missed).

Your agent can then respond to queries like:

  • "What are KOLs buying right now?"
  • "Show me the KOL leaderboard this week"
  • "What tokens are multiple KOLs accumulating?"
  • "Any new deployer alerts from Pump.fun?"
  • "Show my wallet tracker watchlist"
  • "What did my tracked wallets trade recently?"

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 40+ endpoints — real wallets, TX signatures, full precision — with live feeds delayed 5 minutes (delayed responses carry delay/as_of and an X-Data-Delay header). Paid tiers are real-time and unlock webhooks, WebSockets, rule engines, and ULTRA-only data depth; x402 pay-per-call is always real-time. Get a key at madeonsol.com/pricing.

Also Available

| Platform | Package | |---|---| | TypeScript SDK | madeonsol on npm | | Rust SDK | madeonsol on crates.io | | Python (LangChain, CrewAI) | madeonsol-x402 on PyPI | | MCP Server (Claude, Cursor) | mcp-server-madeonsol · Smithery · Glama | | Solana Agent Kit | solana-agent-kit-plugin-madeonsol |

License

MIT