MadeOnSolMade on Sol
RobinhoodBlogAdvertise
Sign in
MadeOnSolMade on Sol

Solana and Robinhood Chain intelligence — KOL wallet tracking, deployer intelligence, all-DEX trade streams, and a developer API. Discover, compare, and build.

Discover

  • All Tools
  • Stacks
  • KOL Tracker
  • Deployer Hunter
  • KOL Scout Leaderboard
  • Robinhood Chain
  • Robinhood Wallet Scanner
  • Robinhood API
  • Solana API
  • Datasets
  • API Pricing
  • Enterprise API
  • x402 for AI agents
  • Robinhood Chain x402
  • Yields
  • Blog
  • Blog Archive
  • Solana Glossary

Best Of

  • Best Trading Bots
  • Best DEXs
  • Best Wallets
  • Best Analytics
  • Best DeFi
  • Best Snipers

Compare

  • Wallets
  • DEXs
  • Snipers
  • TG Bots
  • Terminals
  • Analytics
  • Portfolio
  • Copy Trading
  • Security
  • Liquid Staking
  • RPC Providers
  • Bridges
  • Launchpads
  • NFT Marketplaces
  • Lending
  • Bot Calculator
  • Perps
  • Scanners
  • Data APIs

Resources

  • Submit a Tool
  • API Docs
  • Get an API Key
  • For Businesses
  • Affiliate Program
  • Changelog
  • API Status
  • Tool Uptime
  • Signal Scorecard
  • Compare KOLs
  • Leaderboard
  • Community
  • Site Stats
  • Advertise

Legal

  • About
  • Contact
  • Terms
  • Privacy
  • Security
  • DPA
  • Disclaimer

© 2026 MadeOnSol

MadeOnSol — eenmanszaak, Hulshout, Belgium · KBO/BTW BE 1039.535.538 (art. 56bis, no VAT charged)

Follow us on XPowered by:constant·k — Private Solana RPC Services
Changelog

Releases · public log

What shipped.
When and why.

Every meaningful change to the MadeOnSol API, the official SDKs, and the underlying infrastructure. The three most recent ship-notes render in full; older entries collapse into the archive below.

Read the docs Follow @MadeOnSolx

Velocity of this product

Live numbers — generated from this log on every revalidation.

97
Releases logged

Since Apr 7

5
Months of history

Full archive below

13
API ships

Endpoints + protocols

2.25.0
Latest Solana SDK

madeonsol — TS · Python · Rust

Recent

The latest three.

PlatformAugust 20, 2026#

Robinhood Chain: who bought first, and whether they stayed

GET /api/v1/rhc/tokens/{address}/early-buyers — the first 20 buyers of a token, in order, joined to what happened next: realized ETH, trade count, average entry market cap, and whether they still hold any.

The ranking itself is not new — rhc_early_buyers has covered 437,226 tokens for months and is recomputed daily. It was only ever read as a per-wallet count inside the wallet profile ("early buyer of N tokens"). The per-token list, which is the thing anyone actually asks for, was never exposed. Solana has had /kol/tokens/{mint}/entry-order; Robinhood Chain had nothing.

Three things are stated in the response rather than left for you to discover:

  • realized_eth is a profit only when position is closed. It is sold_eth - bought_eth, so an early buyer who is still holding shows a negative number — they have spent and not yet sold. Every row carries position (closed / open / unknown), because publishing the figure alone would systematically mislabel the winners as losers.
  • still_holding is only as exact as the fold behind it. It comes from the same ERC-20 Transfer replay as /holders, so the response carries holdings_verified — true only when that token reconciles against on-chain totalSupply().
  • Ranks are as of computed_at, not live. A token that began trading since the last sweep returns an empty list with a stated reason, never as an assertion that it had no early buyers.

Enrichment is additive: if the PnL or holdings join fails, those fields go null rather than taking down the ranking, which always exists. PRO+.

  • Also today, quietly faster: /tokens/search no longer computes match tiers whose rows cannot be returned (?q=pump 1,568 ms → 92 ms, ?q=bonk 507 ms → 17 ms) and now has a deterministic tie-break, so repeated searches return the same order. /rhc/tokens/{address}/risk dropped from a 504 ms median to 91 ms — and now finds a liquidity pool for ~49% more tokens, because it was matching only one side of the pair. RHC holder concentration and growth are single-pass (~3.8× and ~1.9× on the largest tokens). A full sweep of 117 route + filter combinations puts the API at an 18 ms median, 78 ms p90.
PlatformAugust 17, 2026#

SDKs: token locks, unlock calendar and pump.fun fee sharing in all 7 Solana packages; equities + liquidity removals in all 7 Robinhood Chain packages

The locks, unlock-calendar, fee-sharing and fee-claims endpoints — plus the two Robinhood Chain surfaces from the day before — now have typed bindings. Fourteen packages published today. (Still keyed-only, no SDK method yet: /tokens/search, POST /wallet/batch/trades, the token:prices channel and WS seq/replay — next SDK release.)

Solana — five methods + two stream channels. madeonsol 2.25.0 (npm — client.token.locks(mint), locksFeed(), unlocks(), feeShares(mint), feeClaims(), typed TokenLocksResponse / TokenUnlocksResponse / TokenFeeSharesResponse / TokenFeeClaimsResponse), madeonsol 0.26.0 (crates.io — client.token().locks(mint, &params), locks_feed, unlocks, fee_shares, fee_claims, ~30 new serde types), madeonsol-x402 1.27.0 (npm — keyed rest.tokenLocks(mint), tokenLocksFeed(), tokenUnlocks(), tokenFeeShares(mint), tokenFeeClaims()), madeonsol-x402 1.27.0 (PyPI — rest.token_locks(mint), token_locks_feed(), token_unlocks(), token_fee_shares(mint), token_fee_claims() + LangChain/CrewAI tools), mcp-server-madeonsol 1.24.0 (madeonsol_token_locks, madeonsol_token_locks_feed, madeonsol_token_unlocks, madeonsol_token_fee_shares, madeonsol_token_fee_claims), @madeonsol/plugin-madeonsol 1.23.0 and solana-agent-kit-plugin-madeonsol 1.23.0 (matching actions + tools). The token:locks and token:fee_claims WebSocket channels are in every stream client's channel union, and — one thing worth knowing — the frames on those channels are the compact writer rows the trackers emit (token:lock: lock account, program, mint, kind, sender, recipient, amount_raw, decimals, schedule; token:fee_claim: event type, mint, actor, recipient, amount_raw, social platform / user id, shareholders), not the enriched REST rows. The TypeScript and Rust SDKs type the frames as what is actually sent, so a client does not have to discover the difference in production. All five endpoints are PRO+ and keyed only (no x402 route); LP locks are not part of locks; fee-claim history starts today.

Robinhood Chain — two endpoints that shipped on 2026-08-16 without a binding. GET /rhc/equities (the beacon-verified tokenized stocks & ETFs — identity is the issuer beacon, never the name) and GET /rhc/lp-events (liquidity removals from our own node — the rug signal; adds are not persisted, and the response says so) are now in robinhood-chain-sdk 0.8.0 (equities(), lpEvents()), robinhood-chain 0.8.0 (crates.io, equities, lp_events), robinhood-chain 0.9.0 (PyPI, equities(), lp_events()), robinhood-chain-x402 0.9.0 (keyed client — neither endpoint is on the USDG rail), mcp-server-robinhood-chain 0.8.0 (rhc_equities, rhc_lp_events), @madeonsol/plugin-robinhood-chain 0.8.0 and solana-agent-kit-plugin-robinhood-chain 0.8.0.

  • Also today: GET /rhc/deployer-hunter/best-tokens had been answering 500 since 2026-08-14 — the elite+good deployer cohort grew to 178 addresses, the query rendered ~7.6 KB into the URL and the proxy answered 414. Chunked; the same ceiling is now respected on /rhc/deployer-hunter/alerts?tier=. Additive SDK release otherwise; nothing breaks if you do not upgrade.
PlatformAugust 17, 2026#

pump.fun fee sharing & claims: who the creator fees are redirected to, and every claim

pump.fun lets a coin's creator fees be split to other wallets (a SharingConfig of shareholders) and earmarked for social identities — an X account whose owner later claims. Two endpoints now read that straight from the programs' own events and account state.

GET /api/v1/tokens/{mint}/fee-shares — the split on a coin right now (each shareholder's share, whether it is the creator, whether it is a social-handle PDA), how much has actually been distributed to each of them, who used to be in the split, and every config change. A coin that never redirected returns is_default: true — a real answer, read live from chain.

GET /api/v1/tokens/fee-claims — the feed: distributions to shareholders (pro-rata per address), social-handle claims (platform + numeric user id, recipient wallet, amount), config changes and creator transfers, newest first with since= cursors — and pushed on the new token:fee_claims WebSocket channel.

  • Decoded from the on-chain Anchor events (DistributeCreatorFeesEvent, SocialFeePdaClaimed, CreateFeeSharingConfigEvent, …) of the pump and pump_fees programs; social-handle PDAs backfilled (10.9k identities, 53k SOL claimed lifetime on day one). Event history starts today.
  • Not stored on purpose: the default 100%-to-creator config pump creates for every coin, and the zero-amount distribution that comes with it — the feed is redirects and real claims only.

Archive

94 earlier ship notes.

Click any row to expand its full release notes inline. Grouped by month, newest first.

August 2026

8 ships
Aug 17Platform

Token locks & vesting: who locked, how much, until when — and what unlocks next

Three Solana endpoints that read the locker programs themselves instead of guessing from transfers.

Platform+

Three Solana endpoints that read the locker programs themselves instead of guessing from transfers.

GET /api/v1/tokens/{mint}/locks — every Streamflow stream, Jupiter Lock vesting escrow and Bonfida token-vesting contract on a mint, decoded from the programs' on-chain account state and derived live at request time: how much is still locked right now, what has unlocked, what is claimable, the next unlock event, and a 7d/30d forward schedule. The summary answers the questions that matter before you buy a "team-locked" token: how much of supply is actually locked, until when, by how many wallets — and how many of those locks the locker can still cancel (a cancelable lock is a promise to the recipient, not to you).

GET /api/v1/tokens/locks — the cross-token feed of new locks, newest first, with since= cursors — and pushed live on the new token:locks WebSocket channel the moment the contract lands.

GET /api/v1/tokens/unlocks — an unlock calendar: every active contract's next cliff / periodic / final unlock inside 1h–90d, with the amount, its % of supply and USD value, sortable by soonest or largest. "Which tokens have locked supply hitting the market this week."

  • Coverage today: Streamflow (66k contracts), Jupiter Lock (416k — mostly per-recipient airdrop vestings), Bonfida token-vesting. Adding a locker is a decoder + a program ID. LP locks (Raydium Burn & Earn, Meteora position locks) are a separate, not-yet-built feature — this is token/vesting locks.
  • Amounts are base-unit strings with ui / usd / % of supply alongside; decimals and supply are read off the SPL Mint account for every mint we see (most locked tokens are not memecoins in our trade universe), so the numbers do not depend on the token being "tracked".
  • Also today: the gRPC reconnect path in kol-tracker / dex-stream / deployer-listener could hang forever on a dead channel (a 6-hour single-region blind spot on 2026-08-17 that turned into 36 min of no feed when the other region failed). Connect/subscribe now time out, an orphaned region self-heals, and health monitoring reads region liveness directly.
Aug 17Platform

Who holds a token, exactly — on both chains — and, on Robinhood Chain, who arrived and who left

Two holder endpoints, one on each chain, that answer the question every other data API estimates.

Platform+

Two holder endpoints, one on each chain, that answer the question every other data API estimates.

Solana: GET /api/v1/tokens/{mint}/holders (shipped 2026-08-16, extended today). Not a top-20 list and not a trade-derived guess: a live census of every token account of the mint (mint-scoped getProgramAccounts at confirmed, Token-2022 aware — every pump.fun mint is), merged per owner. So holder_count is exact — distinct non-zero owners minus pools, bonding curves and burns — and top1/10/20/50/100_share are over a circulating denominator that excludes them. Each disclosed owner is labelled from our wallet intelligence (deployer / kol / early_buyer / bundle / bot / dump_cluster). Fresh memecoins scan in well under a second; a 500k-account token takes ~10 s upstream, so you get 503 holder_scan_in_progress with Retry-After 20 while the scan finishes into the cache. Mega-caps the provider refuses fall back to a top-20 view with holder_count: null and the reason stated — never estimated. Amounts are raw u64 strings.

  • Today: excluded owners are named. The #1 raw account of a fresh memecoin is its own pool. Before, everything off-curve was a generic program_account; now excluded[].reason is pool (with dex and pool_address — matched against our known pools for the mint or the shared Raydium v4 / Meteora DAMM v2 vault authorities), bonding_curve (pump.fun / LaunchLab), burn, or program_account only when we genuinely cannot attribute the PDA. concentration gains pool_pct / burned_pct / program_pct. Zero extra RPC.
  • PRO discloses ranks 1–10, ULTRA 1–50, BUSINESS 1–100; the maths is the same on every tier.

Robinhood Chain: GET /api/v1/rhc/tokens/{address}/holders now carries holder_growth. RHC holders were already exact — balances folded from ERC-20 Transfer logs on our own node and reconciled against totalSupply() to the wei — and that history is what makes today's field possible: {1h, 24h, 7d} × {entered, entered_still_holding, exited, net}. entered = addresses whose first Transfer of the token landed inside the window; exited = pre-existing holders whose last movement in the window left them at zero; net ≈ the change in holder_count. Pools and burns excluded. Sanity check from ship day: a token launched that morning showed 593 entered / 560 still holding over 24h — and holder_count was exactly 560. The Solana census is a point-in-time ledger read with no history, so this is an RHC-only capability by nature, and we say so rather than approximate it from trades.

  • Also fixed today: the RHC holder reads looked pools up with a lower() on an indexed column and were running a 988k-row parallel seq scan twice per request. Same numbers, ~2.4× less database time.
  • SDKs — published today, all 14 packages. Solana: the holders census had no SDK binding at all until now. madeonsol 2.24.0 (npm, client.alpha.holders(mint), typed TokenHoldersResponse), madeonsol 0.25.0 (crates.io, client.token().holders(mint)), madeonsol-x402 1.26.0 (npm, keyed rest.tokenHolders(mint)), madeonsol-x402 1.26.0 (PyPI, rest.token_holders(mint) + LangChain/CrewAI tools), mcp-server-madeonsol 1.23.0 (madeonsol_token_holders), @madeonsol/plugin-madeonsol 1.22.0 (GET_TOKEN_HOLDERS), solana-agent-kit-plugin-madeonsol 1.22.0 (tokenHolders). Robinhood Chain: holder_growth typed or documented in robinhood-chain-sdk 0.7.0, robinhood-chain 0.7.0 (crates.io), robinhood-chain 0.8.0 (PyPI), robinhood-chain-x402 0.8.0, mcp-server-robinhood-chain 0.7.0, @madeonsol/plugin-robinhood-chain 0.7.0, solana-agent-kit-plugin-robinhood-chain 0.7.0. The census is keyed-only (not on the x402 rail); RHC holder_growth rides the existing /rhc/tokens/{address}/holders route, so it is on the USDG keyless rail too.
  • One honest boundary: the Solana census is a point-in-time ledger read, so there is no holder_growth on Solana — we would rather leave the field absent than infer it from trades.
Aug 16Platform

The Robinhood Chain SDKs can now pay for themselves: keyless x402 in TypeScript and Python

The Robinhood Chain x402 rail has been live since July, but both SDKs were key-mode only — an agent that wanted to pay per call had to hand-roll the EIP-3009 signing from the 40…

Platform+

The Robinhood Chain x402 rail has been live since July, but both SDKs were key-mode only — an agent that wanted to pay per call had to hand-roll the EIP-3009 signing from the 402 challenge. robinhood-chain-x402 0.7.0 (npm) and robinhood-chain 0.7.0 (PyPI) close that: pass a privateKey / private_key of an EVM wallet holding USDG on Robinhood Chain instead of an API key, and the client does the 402 → sign transferWithAuthorization (EIP-712 domain {Global Dollar, 1, 4663}) → retry flow itself, one payment per call, from $0.04. The wallet needs USDG but no ETH — our facilitator relays gas. lastPayment / last_payment carries the on-chain settlement. Both were verified with real USDG settlements before publish.

  • Keyless rail is now 10 endpoints, not 6 — token risk (with live sell simulation), holder census, wallet PnL and tracked-deployer alerts joined the KOL feed / hot tokens / leaderboard / token snapshot / buyer quality / KOL consensus. The new four delegate to the keyed v1 handlers in-process, so the keyless bodies cannot drift from the keyed ones.
  • Honest boundary: any method that is not on the rail throws KeylessNotAvailableError on a keyless client and names the ten that are. Nothing silently downgrades.
  • TypeScript: createKeylessClient(process.env.RHC_PAYER_KEY), optional peer dependency viem; key mode still has zero runtime dependencies. New deployerAlerts() binding (52 methods).
  • Python: RobinhoodClient(private_key=…), extra pip install "robinhood-chain[x402]" (eth-account); sync and async.
  • Also on the API today: GET /rhc/equities (beacon-verified tokenized stocks/ETFs — 20 fake "GameStop • Robinhood Token" contracts existed on ship day and none are listed), /rhc/tokens?sort=newest&since= (+ /rhc/tokens/new), /rhc/lp-events, ?include= on the always-paired Solana calls, since= + stream pointers on the polled KOL feeds, sequence numbers + client-side replay on the WebSocket stream, and price/pool/reserve enrichment on the dex:trades firehose.

2026-08-16 — A trade row said it moved N tokens for M SOL, then quoted a price that was not M divided by N

An alert fired claiming our per-trade price was 71% wrong. It was not 71% wrong — that number came from a sampling flaw in our own monitor. But chasing it down surfaced something worse than the alert: for months, price_sol on a trade row was not the price of that trade.

What it actually was. Our market-cap tracker samples a canonical pool price per token, once per pool update. The ingest path stamped that value onto whatever trades landed near it. So a trade row told you it moved N tokens for M SOL, and then reported a price that was not M ÷ N. The gap ran to a 7.9% median and roughly 74% at the 90th percentile.

The mechanism is granularity, not a bug in the tracker. Every trade in the same slot gets one canonical price. On 2026-08-16, slot 439589939 held a dump: seven trades executing from 9.80e-6 down to 6.12e-6, all seven stamped 6.071174e-6. Their individual errors ran from −38% to −0.9%. On top of that sits a lag with a direction: a stale market price is low during a pump and high during a dump, so the error does not cancel when you average it — candles and VWAP built from that tape inherit the bias. Nothing regressed to cause this. The tape simply got faster, and a price sampled per-token stopped being a reasonable stand-in for a price paid per-trade.

What changed. On /tokens/{mint}/trades and /wallet/{address}/trades, price_sol and price_usd are now this trade's executed price, derived from the row's own amounts. They reconcile exactly with sol_amount / token_amount and with what the PnL endpoints sum. Because sol_amount is the wallet's net SOL movement, that price is the trader's all-in effective rate — it includes the swap fee and any account rent paid in the same transaction, and it is not the pool mid. We would rather tell you that plainly than quietly hand you a number you cannot reproduce from the chain.

The old number did not disappear. It moved to market_price_sol and market_price_usd on the same rows. A single per-token price series is genuinely useful, because executed prices bounce around with trade size and direction — it just should not have been wearing the label "the price of this trade". Use price_sol for cost basis, fills and PnL; use market_price_sol when you want a series independent of who traded and how much.

This is computed when you read, not when we write, so it is correct for every row we have ever captured — no backfill, no gap between old and new history. /wallet/{address}/trades gained all four fields; it previously returned amounts and no price at all, leaving every caller to divide by hand.

And we fixed the monitor that cried 71%. The check sampled the newest 1,000 trade rows, which at today's throughput is about twelve seconds of tape — usually one hot token. The mint that produced the 71% reading had 1,574 trades in three minutes and a 71% median all by itself, while the median across all mints in the same window was 12.4%. It now samples six slices across three hours and takes the median of per-mint medians, so no single token can page us. Two neighbouring monitor bugs went with it: a check that read "our node is one block ahead of the reference" as "DNS is dead on that box" (21 false alarms a day and climbing), and a self-healer that restarted services which were merely mid-restart.

Every SDK ships both prices. madeonsol 2.23.0 (TypeScript), madeonsol-x402 1.25.0 (npm and PyPI), mcp-server-madeonsol 1.22.0, @madeonsol/plugin-madeonsol 1.21.0, solana-agent-kit-plugin-madeonsol 1.21.0, and madeonsol 0.24.0 on crates.io. TokenTrade and WalletTrade carry all four fields, and the MCP tool descriptions spell out which price to use — an agent reading the schema should not have to guess which one belongs in a PnL calculation. The Rust fields are Option<f64>, so a client pinned to an older server still deserializes. Nothing breaks if you don't upgrade: price_sol still exists with the same type, it just finally means what its name says. The Robinhood Chain packages are untouched at 0.6.0 — that chain's trades have their own price columns.

Unrelated, but shipping the same day: the crypto checkout asks a harder question. A card payment comes with a counterparty — the issuer checks the billing address. A crypto payment has none, so an address is whatever someone types. One order arrived with a street, a city and a country belonging to three different jurisdictions, and it passed validation because the country it named has no postal codes, which waived the only checkable field. Now countries without a postal system must give a state or region instead, postal codes are checked against their country's format, and when the country you select disagrees with where you're connecting from, the checkout shows you the mismatch and asks you to confirm your country of residence. It isn't a block — VPNs are normal, and we'd rather ask than guess.

2026-08-15 — We audited our own SDKs and found fifteen endpoints you were paying for but could not call

This week's audit turned on our own packages rather than the API. Fourteen of them across npm, PyPI and crates.io. Registry hygiene was clean — every published version matched its manifest, the OpenAPI spec covers 134 of 135 routes, and every built package emits correct ESM. The problem was the gap between what the API sells and what the SDKs expose, plus a set of dependency ranges that described a version of the x402 ecosystem that stopped existing twenty majors ago.

The entire Robinhood Chain wallet surface had no SDK binding. Eight routes — the 90-day wallet profile, FIFO cost-basis PnL, open positions marked to market, the per-wallet trade tape, and all four watchlist routes — were live, documented in the spec, and reachable by curl, but a grep across all seven RHC packages returned nothing. If you wanted a wallet's PnL on Robinhood Chain you had to hand-roll the HTTP call while holding an SDK that covered forty other endpoints. All eight are now bound in every RHC package: the TypeScript, Python and Rust SDKs, the x402 client, the MCP server, and both agent plugins. The profile, PnL and positions calls share one 90-day snapshot cache server-side, so asking for all three on an address costs roughly one computation rather than three — cache_hit tells you which call paid for it.

Deployer Hunter was better covered on the newer chain than on the flagship one. Seven Solana routes — the reputation leaderboard, chain-wide stats, a single deployer's profile and full launch history, alert-volume stats, best recent tokens, and fresh graduations — were missing from all five Solana packages, while the Robinhood Chain packages covered the exact same seven on their side. The newer, smaller product line was more complete than the one we lead with. Fixed; all seven now ship in the Solana TypeScript, Python, MCP and both plugin packages. The bare madeonsol TypeScript and Rust SDKs already had them.

Our dependency ranges were fiction in both directions. Every x402-capable package declared its peers as unbounded >=0.0.1 or >=0.1.0. The x402 packages are at 2.22, and our code is written against 2.8–2.11. So a user pinned to @x402/[email protected] satisfied our range and got a package that could not possibly work, while a user installing fresh resolved a major we had never built against. The same held for @solana/kit (>=2.0.0 declared, 5.5.1 tested, 7.1.0 latest) and for the Python x402 extra (>=0.1 declared, against a 2.x module layout that does not exist on 0.x). Every range is now a caret bound on the version we actually test. Those peers are also lazily imported and only needed in keyless mode, so they are now marked optional — installing with an API key no longer drags in the entire Solana stack.

A Python bug that would have shipped with the new methods. The synchronous REST client passed query parameters straight to httpx, which encodes None as an empty value — ?tier=. Our routes use strict schemas that reject an empty enum with a 400 rather than reading it as "not supplied". Every method we were adding has optional parameters, so this would have bitten on the first call. Unset parameters are now dropped at the transport layer, matching what the Robinhood Chain Python client already did.

And we fixed the guard that should have caught all of this. Each SDK repo runs a route-parity check that fails CI when a package references an API path that does not exist. It was red on two of the four standalone repos — and every hit was a false positive, because the extractor was reading JSDoc and rustdoc prose as code and flagging backtick code spans like `/risk` as routes. A gate that cries wolf on every push is worse than no gate, because it trains you to ignore the day it is right. Both extractors now skip comments. The two Robinhood Chain checkers were failing differently: their route manifests were hand-maintained and forty entries stale, so the reverse direction — "is every documented route actually bound?" — had been silently passing on an incomplete list. Refreshed from the live spec, that check immediately flagged four unbound routes, all of which turned out to be server-side aliases of endpoints already covered; they are now allow-listed by name with the canonical target written next to each.

Versions. Robinhood Chain: TypeScript, Python, Rust, x402, MCP and both plugins all to 0.6.0. Solana: madeonsol-x402 1.24.0 (npm) and 1.24.0 (PyPI), mcp-server-madeonsol 1.21.0, the ElizaOS plugin 1.20.0, the Solana Agent Kit plugin 1.20.0. No API changes — the endpoints were already there. This release is entirely about being able to reach them.

Aug 12Platform

We audited our own API contract and fixed eight ways it could quietly mislead you

We ran a full product audit across both chains this week. Most of what it found was not broken code — it was working code whose output could mislead a paying customer without an…

Platform+

We ran a full product audit across both chains this week. Most of what it found was not broken code — it was working code whose output could mislead a paying customer without anyone noticing. Eight fixes shipped today. Three are outright bugs; five are disclosures we owed you.

The Robinhood Chain trade tape was silently dropping rows during pagination. /rhc/trades, /rhc/wallet/{address}/trades and /rhc/wallet-tracker/trades paged with a cursor on block_time alone — a second-grained value that dozens of trades can share on a chain producing multiple blocks per second. Whenever a page boundary fell mid-second, the rest of that second was skipped, undetectably. All three routes now use an opaque keyset cursor over (block_time, id) — the same scheme the Solana tape has used all along — with a has_more flag, and next_before is only emitted when there is genuinely more data. Old ISO-timestamp before values are still accepted forever, so existing integrations keep working and stop losing rows the moment they follow the new cursor. A nightly correctness case now walks five pages against a fixed reference window and fails on any missing or duplicated row.

A shipped WebSocket channel was invisible, and a published SDK constant didn't exist. The POST /stream/token discovery response advertised 14 channels; the server accepts 15. The missing one was token:graduations — live since day one, PRO+, and undiscoverable by any client that trusted the documented discovery flow. Separately, the 0.4.0 Robinhood Chain SDKs shipped a typed stream constant rhc:trades for a channel the server calls rhc:dex_trades — a subscribe with it was rejected with a warning frame the TypeScript SDK then silently discarded. Both lists now come from a single canonical registry the discovery route imports, so they structurally cannot drift again; the server accepts rhc:trades as a deprecated alias (inheriting the real channel's ULTRA gate); and a daily correctness case subscribes to every advertised channel and fails on any rejection. Corrected SDKs follow in the next release.

?primary_dex=launchpad filtering finally admits what the pricer already knew. Our own tracker stamps on-curve bonk tokens primary_dex=launchlab — and the /tokens filter enum rejected that exact value with a 400. Fixed, and the token surface gained an explicit launchpad field (pumpfun | launchlab | bags) on /tokens, /token/{mint}, /token/batch and /kol/feed, sourced from deploy records rather than inferred from the pool — because bags launches price through Meteora DBC and are indistinguishable by primary_dex alone. /tokens/almost-bonded accepts ?launchpad= too.

Leaderboards now paginate. /alpha/leaderboard scores tens of thousands of wallets and served exactly the top 100 (500 on ULTRA) with no way to see further — ever. It now takes offset with a deterministic tiebreaker so pages never overlap, as do /kol/leaderboard, /kol/tokens/trending, /kol/tokens/hot, /kol/pairs and /tokens/{mint}/top-traders (the latter sliced from cache, so deep pages cost nothing extra). We also deleted a comment on /deployer-hunter/alerts claiming pagination was ULTRA-only — it never was; the gate it described was dead code.

Every trade-derived endpoint now says what it covers. Persisted Solana trade history is scoped to the launchpad pipeline — that has always been documented, and five routes already carried a machine-readable coverage object saying so. Seven more now do: bundle, top-traders, cap-table, buyer-quality (single, batch and keyless), risk, the wallet profile and wallet holdings. The wallet profile also gained flags.coverage_note, stating plainly that is_sniper / is_bundler / is_dumper being false means not observed in covered trades — never verified clean. That sentence lived in a source comment; it belongs in the response.

Uniswap v4 liquidity now declares itself a ceiling. Last week we clamped v4's virtual-reserve arithmetic to the singleton's real holdings and wrote in this changelog that a clamped value is "a ceiling, not a measurement." Today the API says it too: every response carrying liquidity_usd for a v4-priced token now includes liquidity_basis: "v4_virtual_ceiling" ("measured" everywhere else), with a note on single-token routes. The $100 tradability gate on deployer alerts is unchanged — the clamp only ever lowers a number, so a v4 value can only false-pass a dust filter, and the response now tells you when a pass is a ceiling-pass.

Robinhood Chain aggregates disclose their attribution floor. Wallet-level analysis has carried attribution_complete_from: 2026-07-18 since July — but the four endpoints built on the same attributed-only data (/rhc/alpha-wallets, flow, top-traders, buyer-quality) disclosed nothing. They now carry the same attribution note, and buyer-quality's coverage block no longer claims "full parity with the Solana scorer": for launches before the floor, its "earliest 20 buyers" are the earliest 20 attributed buyers. The backfill that retires the floor entirely is scheduled; until it runs, the caveat travels with the data.

A dead monitor no longer reads as "All systems operational." The status endpoint computed overall from whichever health rows happened to be in the last 50 — so a monitor that stopped writing simply vanished from the calculation, and the page stayed green. Every core service is now fetched individually, a service whose last check is older than three cycles is marked stale, and stale, unknown or missing services degrade overall instead of disappearing from it. A monitoring failure now looks like what it is.

SDKs — all seven Robinhood Chain packages 0.5.0, four Solana packages patched. The RHC TypeScript, Rust and Python SDKs shipped a stream channel that never existed: rhc:trades, where the server says rhc:dex_trades — and the TypeScript event name rhc:trade was equally fictional, so a typed listener could never fire. In 0.5.0 the channel unions carry the six real channels (the four rule-engine channels were missing entirely), the TypeScript SDKs surface the server's channels_rejected warning frame as a typed warning event instead of silently discarding it, the phantom event literal is deliberately a compile error rather than a deprecation (a listener that can never fire should not compile), and the Python SDK gains a streaming client it simply never had — including stream_token(), which was missing even as a REST method. The Rust crate keeps RHC_TRADES for source compatibility, deprecated and re-pointed at the real channel. On the Solana side, madeonsol (TS 2.22.4, Rust 0.23.4), madeonsol-x402 (1.23.4) and the ElizaOS plugin (1.19.4) add the optional coverage object to their typed response models; we verified no published SDK rejects unknown fields, so older versions keep working — they just don't see the new field.

Aug 5Platform

We audited what our Robinhood Chain node actually tells us, and found four things we were getting wrong

We run our own Robinhood Chain node. It captures events well — 32.2 million logs decoded, 21.3 million trades written, KOL attribution resolved through ERC-4337 bundles. What it…

Platform+

We run our own Robinhood Chain node. It captures events well — 32.2 million logs decoded, 21.3 million trades written, KOL attribution resolved through ERC-4337 bundles. What it did badly was state: several values were read from the chain once, cached, and then trusted forever. Four fixes shipped today, three of which were live data errors on paid endpoints.

Market caps on the chain's largest tokens were wrong by up to 114%. Token supply was read exactly once — the first time a token ever traded — and never again. For the ~99% of Robinhood Chain tokens with fixed supply that is harmless. For the tokenized equities and stablecoins, which are beacon proxies whose implementation genuinely exposes mint(), it is not. Measured against our own node: USDe's supply had gone from 110,311,453 to 236,639,292 while we served a $110M market cap against a true ~$237M. The tokenized TSLA had gone from 2,324.297 to 5,043.288 (+117%), MSFT +34.5%. Supply is now re-read on a 10-minute TTL for any token that is still trading, and the correct figure — which our holder-reconciliation job had been reading from the chain every 10 minutes and discarding — is now propagated to the column the API serves. 605 tokens corrected on apply.

20,167 tokens were advertising liquidity that no longer existed. A pool's balances were only re-read when it traded. So a pool whose LP is pulled and then goes quiet kept its last-known liquidity indefinitely. We sampled 30 tokens claiming over $5,000 of liquidity with no trade in seven days and read their live balances on the node: 30 of 30 were fully drained, the largest still published at $92,820 against roughly zero. This is not cosmetic — liquidity_usd is a filter on /rhc/deployer-hunter/alerts and is served on the KOL feed, coordination and best-tokens. Pools now rotate through a balance re-read on a 6-hour TTL whether or not they trade.

And they now re-read within ~15 seconds of an actual LP withdrawal, because we subscribed to the removal events — Burn on Uniswap v2/v3 and negative ModifyLiquidity on v4. The node socket was already open, so this costs no extra RPC. Removals are also persisted, so a rug is now a queryable fact with a size and a timestamp; /rhc/tokens/{address}/risk gained liquidity.last_removed_at and an lp_removed_24h flag. One detail worth stating because it is the whole difficulty of v4: adds and removes are the same event, distinguished only by the sign of liquidityDelta. In our validation window 9,035 of 10,543 v4 liquidity events were adds. A decoder that ignored the sign would have reported every one of them as a rug.

Uniswap v4 liquidity was arithmetic, not money. v4's singleton makes per-pool balance reads impossible, so we derived virtual reserves from the last swap's price and in-range liquidity. Virtual reserves are not TVL, and at an extreme price the arithmetic runs away: 52 tokens each reported more liquidity than the entire v4 singleton holds, and the worst published $7.56 × 10²⁴. The whole PoolManager holds $19.4M across every pool on the chain. Each pool's derived reserve is now clamped to the singleton's real balance of that asset — a bound we can prove, since no single pool can be backed by more of an asset than all pools combined. Where a value is clamped it is a ceiling, not a measurement, and we would rather say so than publish a number we cannot defend.

Our honeypot detector was accusing innocent tokens — and we found it by trying to use it more. /rhc/tokens/{address}/risk simulates a sell through the router with state overrides; a revert is read as "bought but cannot be sold". We began precomputing that assessment for every liquid token so it could annotate the KOL feed and deployer alerts. The first 225 tokens produced 23 flagged as unsellable — and all 23 had completed a real sell on-chain within the previous hour. The simulation uses the Uniswap v3 router path, and 15 of the 23 had only a v2 or v4 route, so the revert meant "no route", not "trapped". Every simulated no is now cross-checked against observed sells and downgraded to unknown when reality disagrees. Across the first 550 tokens assessed, that check overturned 51 flags and zero false accusations remain. The honest consequence is that we currently report no confirmed honeypots on the chain rather than 51 fictional ones. sellable: "no" now means "trapped as far as we can tell", never merely "the call reverted".

/rhc/kol/feed and /rhc/deployer-hunter/alerts now carry a risk object (sellable, upgradeable, score, checked_at). It is null when a token has not been assessed yet — which means unknown, never clean — and it always travels with its own timestamp, because a cached "sellable" is the one thing that must never be mistaken for a live one. /rhc/tokens/{address}/risk is still computed live per request and does not read the cache.

Aug 4Platform

102 new Robinhood Chain KOL wallets, and 139k trades that were already ours

The Robinhood Chain KOL set grew by 102 wallets today, taking rhc_kol_trades from 185,005 rows to 324,788 — a 76% increase in tracked KOL activity. 412 KOLs have traded on the c…

Platform+

The Robinhood Chain KOL set grew by 102 wallets today, taking rhc_kol_trades from 185,005 rows to 324,788 — a 76% increase in tracked KOL activity. 412 KOLs have traded on the chain in the last seven days. Every endpoint that reads KOL data picks this up with no version change: /rhc/kol/feed, /rhc/kol/leaderboard, /rhc/kol/first-touches, consensus, and all four rule engines.

None of this is new ingestion. Every one of the 102 wallets was already trading through our pipeline and being written to rhc_trades — we simply had not labelled them as KOLs, so their activity never surfaced on a KOL endpoint. Retro-matching their history against the trades we already held produced 139,518 rows in under half a minute. The lesson we keep relearning on this chain is that the ingestion is rarely the constraint; the identity mapping is.

Where the coverage gap actually was. Two leaderboards went in. The first, sorted by 30-day smart-money ranking, was 92% new to us. The second, sorted by 1-day PnL, was 78% already covered. The difference is entirely explained by whether a wallet has a linked X account: our earlier imports scraped named KOLs, and every trader on the second list had a handle. The wallets we were missing are the anonymous ones — 73 of the 102 have no public identity at all and appear as a truncated address. They trade like KOLs and now score like them.

One wallet mattered more than the other 101. A trader we already tracked as a Solana KOL turned out to have a Robinhood Chain address we had never linked. That is not a new person — it is the same identity, now joined across both chains, which is the one thing a chain-specific leaderboard cannot tell you.

First-touch records were rebuilt rather than appended. Adding KOLs retroactively changes who touched a token first: 5,400 tokens gained a first-touch record they never had, and 2,575 existing records turned out to name the wrong wallet, because a newly-tracked KOL had bought the same token earlier. Those were repointed to the true earliest buy, keeping their row identity so nothing downstream broke. The correction is usually small and occasionally enormous: the median newly-correct first-toucher beat the previously-recorded one by 136 seconds, but the tail runs to 41 days. Had we skipped this, the next trade any of these KOLs made on a token they had already touched would have fired a "first touch" alert for a token that was first touched weeks ago.

No alerts were sent for any of it. A bulk insert of historical KOL trades will, by default, emit a first-touch event per token onto our internal bus — which is to say it would have pushed several thousand weeks-old tokens to live WebSocket subscribers and first-touch webhooks as if they had just happened. The backfill ran with trigger replication disabled so that history stayed history. If you have a first-touch subscription, you saw nothing today that was not genuinely first-touched today.

Aug 2SDK

Robinhood Chain had live WebSocket streams the whole time. Nobody could find them.

The RHC push surface has existed since the Robinhood Chain rollout. It was in no documentation, so as far as every customer and every SDK was concerned it did not exist.

SDK+

The RHC push surface has existed since the Robinhood Chain rollout. It was in no documentation, so as far as every customer and every SDK was concerned it did not exist.

Two WebSocket channels — rhc:kol_trades (PRO+) and rhc:dex_trades (ULTRA+) — plus the rhc:kol_trade webhook event have been running in production for weeks. They were registered in the streaming service and accepted by the webhooks API, and they appeared in neither our API reference nor the OpenAPI spec. Since our SDKs and MCP server are generated from that spec, they did not expose them either. We sold Robinhood Chain on being early to a new chain and then shipped something you could only poll.

That gap shows up in the numbers. Robinhood Chain currently carries roughly 3.3 million trades a day from ~160,000 distinct traders — on our own measurements about a fifth of Solana's real trading activity — while accounting for 1.6% of API traffic. The chain was never the problem.

All three are now documented, including the part people would otherwise get wrong: RHC channels ride the same socket and the same connection limit as the Solana channels, so you do not need a second connection. Amounts are native ETH, addresses are lowercase 0x, and identifiers are tx_hash/block_number — do not reuse a Solana deserializer unchanged. There is deliberately no rhc:dex_trade webhook; the firehose is WebSocket-only.

/rhc/kol/feed now supports ?min_kol_winrate and ?strategy. These were withheld on purpose — both read a Solana-only scoring table, and a filter that silently matches everything or nothing is worse than no filter. Robinhood Chain now has its own KOL scoring layer, so they work.

Two things about the semantics, because they differ from the Solana feed:

  • Winrate is measured on closed positions only — a position counts once at least 90% of what was bought has been sold. A KOL who has not sold has no winrate rather than a zero, and those wallets are dropped by the filter rather than scored as losers. "Not yet resolved" is not the same as "lost".
  • strategy is a hold-time bucket (scalper, day_trader, swing, inactive, unscored), not a port of the Solana strategy tag. Reusing that label would imply a parity that does not exist.

Endpoints backed by our trade history now tell you when they don't cover something. Persisted Solana trade history is scoped to the launchpad pipeline — pump.fun, LaunchLab/bonk and bags. For a token or wallet outside it, /tokens/{mint}/flow, /wallet/{address}/pnl, /positions and /trades returned zeros and empty arrays, which is indistinguishable from "this never traded". A wallet trading established memecoins got a PnL that was wrong rather than partial, and nothing in the response said so.

Every one of those responses now carries a coverage object with in_scope. When it is false, the zeros mean not captured, not no activity. The /wallet/{address}/pnl 404 keeps its exact status and message — SDKs match on that string — and carries the disclosure alongside it.

Corrections to things we had published that were not true:

  • /rhc/alpha-wallets said it refreshed every 15 minutes. It refreshes every 30, and that is the last stage of a pipeline whose worst case is several hours.
  • The Solana API page said leaderboard and PnL data refreshes every 5 minutes. That is true only for the today and 7-day leaderboards; 30-day is 15 minutes, and 90-day and 180-day are every 6 hours.
  • Our business page promised an "incident history" and an "incident log" on the status page. Neither existed.
  • The status page said six core services were monitored and named one that is not among them, while omitting two that are.
  • The 99.5% uptime figure is now labelled as what it is: an operating target, not a measured result or a guarantee. Our terms disclaim warranties, and publishing a number that reads like a promise next to that was a contradiction we should not have shipped. Measured availability stays public so you can check the real number instead of taking ours.

New: /security and /dpa. A security posture page covering infrastructure, key handling, access control, backups and recovery — including what we don't have (no SOC 2, no ISO 27001, no external penetration test, no disk-level encryption on the database volumes, and a single primary host). A signable GDPR Article 28 Data Processing Agreement with the sub-processor list. Vulnerability reports: /.well-known/security.txt.

Aug 1Platform

Overload is a 503 with `Retry-After` now, not a 500 — and the free tier always had 6× the burst we documented

On the morning of 2026-08-01 the API returned 940 server errors in two hours, and the way we reported them made it worse.

Platform+

On the morning of 2026-08-01 the API returned 940 server errors in two hours, and the way we reported them made it worse.

The trigger was our own nightly database dump. It has grown with the trade firehose to the point where a single pass saturates disk IO for long enough that queries start hitting Postgres' statement timeout. Three endpoints — /tokens/{mint}/bundle, /flow, and /tokens/{mint}/trades — caught that timeout and returned a bare 500.

That is the wrong answer, and not merely cosmetically. A 500 says "this is broken"; a timeout says "this is too heavy right now, try again". A 500 also carries no retry hint, so the client that hit it retried the same token five to nine times a minute and added load to the exact condition that caused the failure. Requests per token went from a baseline of 1.4 to 5.4, and every one of them failed.

What changed:

  • A query killed by the statement timeout now returns 503 with retry_after_seconds — on those three endpoints, matching what top-traders, /wallet and /holdings already did. There was one classifier for this behind three slightly different private copies and three endpoints with none at all; there is now exactly one.
  • Every 503 and 429 now sends a real Retry-After header. Until today not a single 503 in the API set it — the value existed only inside the JSON body, where no HTTP client and none of our seven SDKs look for it. If you have retry logic, it now works without special-casing us.
  • /tokens/{mint}/bundle is cached for 60 seconds. It was the only endpoint in its family without a cache, which is why the retry storm hit it hardest. Cache state is reported in an X-Cache header — deliberately not a new body field, which would break strictly-typed SDK models.

The free tier's burst limit has been 60/min for a while. Our docs said 10. We raised it so bot builders could sustain roughly one request per second, then never updated the pricing page, API docs, or comparison tables — so the limit was six times more generous than what we advertised, and anyone who throttled to our published number was leaving most of it unused. Corrected everywhere. Free is 200 calls/day, 60/min burst. Nothing about your key changed; only what we told you about it.

We also could not see this happening, which is the part worth admitting. The error rate reached 20.9% for two hours and nothing scheduled was reading the table that records what customers actually received. Our health probes reported green throughout, because they check a handful of synthetic endpoints on a path that bypasses normal auth — a different population from real traffic. Nginx could not see it either: an application-generated 500 is a perfectly successful upstream reply as far as the proxy is concerned.

There is now a check that reads the real request log every five minutes and alerts on the 5xx rate directly. While wiring it up we found the alerting had a wider hole: of 77 monitored services, only 10 had ever emitted a status capable of sending an alert at all. That is fixed too.

None of this is a feature. It is the difference between an incident you hear about from us and one you notice yourself.

July 2026

20 ships
Jul 30SDK

`trader_eoa` on Robinhood Chain now means the trader, not the bundler

We were crediting relayers with other people's trades, and we've fixed it — forward and backward.

SDK+

We were crediting relayers with other people's trades, and we've fixed it — forward and backward.

Robinhood Chain trades can be submitted as ERC-4337 user operations: you sign an intent, and a third-party bundler wraps it into a transaction and pays the gas. On those transactions tx.from is the bundler's address, not yours. trader_eoa was being written from tx.from, and documented across every SDK as "tx.from" — so on every bundled trade the relayer got the credit and the actual trader disappeared from the data.

It was not a rounding error. Roughly 46 bundler addresses had absorbed enough trades to occupy ranks 1–40 of the Robinhood Chain alpha-wallet leaderboard — the wallets we present as the sharpest money on the chain were gas relayers. After the fix there are zero in the top 100.

trader_eoa now holds the effective trading account: tx.from on an ordinary transaction, and the userOp sender when the trade was bundled — never the router, never the bundler. The bundler is preserved separately in tx_sender, populated only when the two differ, so nothing is thrown away. Attribution walks the UserOperationEvent log the EntryPoint emits after running each op, which is what makes multi-op bundles (about 11% of them) resolve correctly instead of collapsing to one wallet.

History was reattributed, not just fixed going forward. 4,081,928 past trades were rewritten from a chain-wide sweep of every UserOperationEvent — including ops routed through all three EntryPoint contracts that are live on the chain, since filtering on the Robinhood Chain one alone misses 23% of them. If you pulled a leaderboard, a wallet profile or a top-traders list before today, pull it again: the answers changed.

Our own truth check had been certifying the bug. The oracle that samples recent trades against the chain every two hours was asserting trader_eoa == receipt.from — which is exactly what the bug produced, so bundled rows passed vacuously and the check reported clean. It now resolves the owning user operation from the receipt logs instead. We'd rather publish that than quietly fix it.

All 7 Robinhood Chain SDKs go to 0.3.1 — TypeScript, Python, x402, MCP server, ElizaOS plugin, Solana-Agent-Kit plugin and the Rust crate. Documentation only: no method, parameter or response-shape changes, so it's a drop-in bump. What changes is that they no longer tell you trader_eoa is tx.from.

Jul 30Platform

Five new Robinhood Chain endpoints: who made money, who's dumping, and can you actually sell it

Five new token-intelligence endpoints on Robinhood Chain, all PRO+, all in the SDKs:

Platform+

Five new token-intelligence endpoints on Robinhood Chain, all PRO+, all in the SDKs:

  • GET /api/v1/rhc/tokens/{address}/top-traders — who actually made money on a token, with win-rate, bot heuristic, KOL identity, dump-cluster membership and early-buyer rank. One caveat we'd rather state than bury: net_eth is realized flow (sell − buy), not PnL. It doesn't value a trader's remaining bag, so a wallet that bought and still holds ranks last, not first.
  • GET /api/v1/rhc/tokens/{address}/flow — which cohort is accumulating and which is distributing, split into KOL / bot / dump-cluster / early-buyer / unprofiled / smart-money / retail. Positive net_eth means that cohort sold into you.
  • GET /api/v1/rhc/tokens/{address}/peak-history — peak market cap, drawdown, and a running high-water curve.
  • GET /api/v1/rhc/tokens/{address}/risk — the one we'd actually use before buying.
  • GET /api/v1/rhc/tokens/{address}/early-buyers — the first 20 buyers, joined to realized PnL and whether they still hold.
  • GET /api/v1/rhc/tokens/{address}/holders — exact holder set and concentration.

Risk is EVM-native, not a Solana port — and that distinction is the whole point. EVM has no mint or freeze authority. We scanned 300 random Robinhood Chain tokens: only 2.3% even expose an owner function and 0% expose mint in their own bytecode. A Solana-shaped risk model would answer "all clear" for ~98% of the chain and tell you nothing. So this one reports what actually discriminates: proxy upgradeability, LP custody, and above all sellability — we simulate a sell at the chain head to catch a token you can buy but not sell. That check is never cached, because whether a token is sellable can change the moment an owner flips a setting. Resolving proxies first matters too: 14% of tokens are minimal proxies with no code of their own, and the tokenized equities are beacon proxies whose implementation is what carries mint/pause/upgradeTo — scan the wrapper and you'd report "no owner, no mint" for the only tokens on the chain that genuinely are mintable.

Holders are exact, not estimated — and we tell you when they aren't. Balances are folded from ERC-20 Transfer logs rather than inferred from trades, which is why this exists on Robinhood Chain when the Solana equivalent was withdrawn: trade-derived balances decay to mostly-wrong within days. Before shipping we replayed a token's entire life and the reconstructed supply matched on-chain totalSupply() to the wei, with 15 of 15 top holders matching a live balance read. Every token carries that reconciliation, and one that fails it comes back verified: false with a reason rather than pretending. Concentration deliberately excludes liquidity pools and burn addresses — the biggest "holder" of a token is normally its own pool, which would make top1_share meaningless.

All 7 Robinhood Chain SDKs are at 0.3.0 — TypeScript, Python, x402, MCP server, ElizaOS plugin, Solana-Agent-Kit plugin and the Rust crate — each going from 25 to 30 endpoints.

Jul 29Platform

Checkout that prices upgrades correctly, and Robinhood Chain data that proves itself against the chain

Upgrades are now priced properly, and signed-out payers aren't lost. If you were already on a paid plan and moved up a tier, checkout could quote you the full price of the new p…

Platform+

Upgrades are now priced properly, and signed-out payers aren't lost. If you were already on a paid plan and moved up a tier, checkout could quote you the full price of the new plan instead of the difference. It now prices the upgrade. Separately, anyone who started a purchase while signed out could reach the end of the flow and lose it — that path now carries you through. There's also a dedicated /checkout route rather than a step buried in the dashboard.

The card-required free trial is gone. It converted nobody, and asking for a card up front to access data you can evaluate in a single call was friction with no payoff. Start on a plan when the data is worth it.

Robinhood Chain trade data is now checked against the chain itself. A new oracle samples recent rhc_trades rows every two hours and re-verifies them directly against our own Robinhood Chain node — amount, direction, token and counterparty. It's been running clean at 40/40 on every sample. Nobody else publishing Robinhood Chain data verifies it against the chain in public, and we'd rather find a decoder drift ourselves than have you find it.

Robinhood Chain alpha-wallet data got much faster and materially fresher. The wallet reputation behind /rhc/alpha-wallets, buyer-quality scoring and the wallet endpoints is now maintained incrementally instead of being recomputed wholesale. The refresh that feeds it went from 168 seconds to 22, and the underlying rollup updates in milliseconds rather than minutes — so the rankings you read track the chain closely instead of drifting between rebuilds. A full rebuild runs every six hours and reconciles itself against ground truth, and the difference is measured and alerted on rather than assumed.

Reads no longer stall behind maintenance. Partition-securing DDL could briefly block API reads while it ran. It doesn't anymore.

All 14 SDK packages picked up a documentation pass and a patch release across npm, PyPI and crates.io.

Jul 25Platform

Robinhood Chain deployer intelligence: 9 new endpoints, and a tier model that resists farming

Nine new Robinhood Chain endpoints, closing the biggest gaps against the Solana surface:

Platform+

Nine new Robinhood Chain endpoints, closing the biggest gaps against the Solana surface:

  • GET /api/v1/rhc/deployer-hunter/{address}/trajectory — is this deployer improving or coasting? Streaks, a 10-launch rolling hit rate, and a trend verdict.
  • GET /api/v1/rhc/deployer-hunter/{address}/tokens — the full paginated launch history, enriched with live MC, peak MC and liquidity.
  • GET /api/v1/rhc/deployer-hunter/best-tokens — the highest-peaking launches from reputable deployers only.
  • GET /api/v1/rhc/deployer-hunter/stats — chain-wide reputation census, including the active tier thresholds so you never have to guess what "elite" means.
  • POST /api/v1/rhc/token/batch — up to 50 tokens in one call.
  • POST /api/v1/rhc/tokens/batch/buyer-quality — up to 20 tokens' early-buyer cohorts scored at once.
  • Four path aliases so a Solana integration ported to Robinhood Chain stops 404-ing on capabilities we already ship: /rhc/token/{address}, /rhc/tokens/{address}/trades, /rhc/kol/tokens/hot, /rhc/alpha/leaderboard.

Deployer tiers now resist farming. A $40K peak market cap turned out to be cheap enough to manufacture — roughly 7,400 tokens clear it in a week, and we found operations mass-relaunching a single ticker across rotating wallets (one used 149 wallets and 341 contracts in a month) to farm a high graduation rate. Two of those wallets had earned our top tier.

Tiers are now earned on the $100K runner rate and require 24 hours of deployer history, so a wallet minutes old can no longer qualify, fire alerts and decay. graduation_rate still means the $40K bar and is still returned — it just no longer sets the tier.

The alert feed tells the truth about now, not about then. tier and its explanation are resolved at read time instead of being frozen when the alert fired, so a demoted deployer can't keep being advertised as good-tier (tier_at_alert and tier_is_stale preserve the original). A tradability filter is now on by default — the feed had been serving alerts on tokens that pumped and drained, one at $45K market cap against $68 of liquidity. Pass include_untradeable=true for the raw tape.

All 7 Robinhood Chain SDKs are at 0.2.0 — Python, x402, MCP server, ElizaOS plugin, Solana-Agent-Kit plugin, the bare TypeScript SDK and the Rust crate — each going from 14 to 25 endpoints.

Jul 22Platform

Robinhood Chain x402: pay-per-call in USDG or USDC

Six Robinhood Chain intelligence endpoints are now keyless and pay-per-call for AI agents via the x402 protocol — the first KOL & deployer intelligence API on Robinhood Chain pa…

Platform+

Six Robinhood Chain intelligence endpoints are now keyless and pay-per-call for AI agents via the x402 protocol — the first KOL & deployer intelligence API on Robinhood Chain payable per-call in USDG. Your agent's wallet is the key: no signup, no subscription.

Every endpoint is dual-accept — the agent pays with whichever stablecoin it holds:

  • USDG on Robinhood Chain (native, chain id 4663, via EIP-3009 transferWithAuthorization) — flat $0.04 minimum per call.
  • USDC on Solana — the standard $0.005–$0.02 per call.

Endpoints: GET /api/x402/rhc/kol/feed, /kol/hot-tokens, /kol/leaderboard, /tokens/{address}, /tokens/{address}/buyer-quality, /tokens/{address}/kol-consensus — responses match the equivalent keyed /api/v1/rhc/* endpoints exactly. Settlement runs through our own Robinhood Chain node and a self-hosted, non-custodial facilitator (the payment moves wallet→wallet directly — we never take custody).

Free discovery endpoint for agent self-configuration: GET /api/x402/rhc. Full details at /robinhood/x402. Prefer a flat monthly plan (Robinhood Chain bundled at no extra cost)? See madeonsol.com/pricing.

Jul 21SDK

Dedicated Robinhood Chain SDKs

Robinhood Chain now has its own SDKs — seven standalone packages, separate from the Solana ones so it's unmistakable you're building on a different chain. Each is fully typed wi…

SDK+

Robinhood Chain now has its own SDKs — seven standalone packages, separate from the Solana ones so it's unmistakable you're building on a different chain. Each is fully typed with EVM-native fields (0x addresses, eth_amount, tx_hash, block_number) and covers the full RHC surface: KOL feed / leaderboard / hot-tokens / profile, the DEX trade tape, token discovery + candles + KOL-consensus + buyer-quality + launch-bundle detection, Deployer Hunter, and smart-money alpha wallets.

New packages:

  • TypeScript — npm i robinhood-chain-sdk
  • Python — pip install robinhood-chain
  • Rust — cargo add robinhood-chain
  • x402 (robinhood-chain-x402), MCP server (mcp-server-robinhood-chain), ElizaOS (@madeonsol/plugin-robinhood-chain), and Solana Agent Kit (solana-agent-kit-plugin-robinhood-chain) plugins — for AI agents.

Same msk_ key, same base URL — and Robinhood Chain is bundled into every tier at no extra cost. The free tier is 200 requests/day across every endpoint. Start at madeonsol.com/pricing; full reference at /robinhood and /api-docs.

Jul 20Platform

Robinhood Chain: launch-bundle detection

Spot coordinated launch bundles on Robinhood Chain — the same signal we run on Solana, now on RHC.

Platform+

Spot coordinated launch bundles on Robinhood Chain — the same signal we run on Solana, now on RHC.

New API endpoint (/api/v1/rhc/*):

  • GET /rhc/tokens/{address}/bundle (BASIC gets the scalar signal; PRO adds the top-10 wallets; ULTRA the full cohort with alpha-wallet identity) — detects when a token's earliest buyers are a coordinated bundle: we rank the first 20 distinct buyers by on-chain order and flag a bundle when 3+ of them buy in the same block, then report how much of what they bought they still hold (held_ratio, held_pct_of_supply) and whether they've fully exited (bought the launch, then dumped). Robinhood Chain is an Arbitrum Orbit L2 with no atomic multi-wallet transaction, so a detected bundle is same_block — there's no atomic_tx sleight-of-hand to hide behind.

Buyer-quality now has full Solana parity. GET /rhc/tokens/{address}/buyer-quality previously declared bundle and dump-cluster detection unavailable — both are now live. A bundled buyer in the top 10 costs the quality score −5, and a heavily bundled cohort (>10 of the first 20) costs −15, so bundled launches land in the negative band. And a new dump_cluster_count flags early buyers that repeatedly show up in launches that crashed off their own peak (a rolling 42-day ensemble) — informational, so it surfaces the pattern without moving the score. We out-of-sample validated it on Robinhood Chain first: a wallet cluster of 3+ in a token's first 20 buyers predicts a crash ~98% of the time vs a 50% base. The coverage field now reports both signals available.

Forward-looking by design: bundles clip right after launch, so detection runs on new launches going forward — straight from our own Robinhood Chain node, same accuracy standard as Solana.

Jul 20SDK

SDK streaming: clean shutdown

A lifecycle fix for the two TypeScript SDKs' managed WebSocket streaming client. Calling close() now fully tears down the underlying socket, so short-lived scripts (a one-off st…

SDK+

A lifecycle fix for the two TypeScript SDKs' managed WebSocket streaming client. Calling close() now fully tears down the underlying socket, so short-lived scripts (a one-off stream read, a cron task) exit promptly instead of hanging until the process is killed.

  • [email protected] and [email protected] — on Node the stream client now prefers the ws package (which exposes terminate()) and hard-terminates the socket on close(); browsers still use the native WebSocket. On Node ≥22 the global WebSocket kept its TLS socket open after close(), holding the event loop.

No API changes — purely a client-side lifecycle fix. If you're on Node ≥22 and want the fast exit, make sure ws is installed (npm i ws); it's already a dependency in most setups.

Jul 19Platform

Robinhood Chain token intelligence: KOL consensus + buyer quality

Two new per-token intel endpoints on Robinhood Chain, plus a correctness fix under the hood.

Platform+

Two new per-token intel endpoints on Robinhood Chain, plus a correctness fix under the hood.

New API endpoints (/api/v1/rhc/*):

  • GET /rhc/tokens/{address}/kol-consensus (PRO; ULTRA adds the buyer/exited wallet lists) — how the tracked-KOL cohort is positioned on any RHC token: distinct buyers vs sellers, exit rate, net ETH flow, total buy/sell volume, first-touch wallet, and median entry market cap. It also returns entry_mc_samples so you can see how many buys the median is based on. Aggregated server-side across every KOL trade on the token — no result-size cap.
  • GET /rhc/tokens/{address}/buyer-quality (free tier) — a 0–100 quality score on a token's earliest buyer cohort, built from wallet win-rate, KOL presence, and bot-domination. We're upfront about coverage: the bundle-buyer and dump-cluster signals we run on Solana need launchpad-level decoding we don't have on RHC yet, so those are declared unavailable in a coverage field rather than reported as a misleading zero.

Reliability: the bulk POST /tokens/batch/buyer-quality (Solana) now runs its wallet lookups in parallel, removing the intermittent timeout that could affect very large batches on busy days.

As always, straight from our own nodes — same accuracy standard across both chains.

Jul 17Platform

Robinhood Chain deployer reputation, KOL launchpads, and consensus signals

Robinhood Chain Deployer Hunter is live. Check any RHC token deployer's reputation and get live signals when proven ones launch — /robinhood/deployer-hunter.

Platform+

Robinhood Chain Deployer Hunter is live. Check any RHC token deployer's reputation and get live signals when proven ones launch — /robinhood/deployer-hunter.

  • Market-cap graduation model. Most RHC launchpads are direct-to-DEX (no bonding curve), so a deployer's graduation rate = the share of their tokens that reached a $40K+ peak market cap, and runner rate = $100K+. Every deployer from chain genesis is scored and tiered (elite / good / neutral / spam factory).
  • Peak market caps reconstructed to genesis. We backfilled each token's all-time-high market cap from on-chain DEX trades back to the chain's first block, so reputation reflects a token's full history — not just what we've seen since we started tracking.
  • Live deployer signal feed + free deployer checker on the site, with the full ranked leaderboard available via the API.

API changes (/api/v1/rhc/*):

  • /rhc/deployer-hunter/leaderboard and /{address} now return graduation_rate, graduated, runners, and runner_rate. This replaces the old bonding_rate / curve_tokens fields — RHC graduation is a market-cap milestone, not a bonding-curve event.
  • launchpad added to RHC KOL trades and trade endpoints, so you can filter by where each token launched.
  • New GET /api/v1/rhc/kol/hot-tokens (free tier) — tokens multiple tracked RHC KOLs are buying right now (consensus signal), with current market cap and buyer counts.
  • Richer RHC KOL data — feed and per-wallet endpoints now include current market cap, the multiple since the KOL traded (did the call run), deployer tier, and graduation status.

All of it comes straight from our own Robinhood Chain node — same accuracy standard as our Solana feeds, no third-party data API in the middle.

Jul 15Platform

Robinhood Chain support is coming: MadeOnSol goes multichain

MadeOnSol is expanding beyond Solana. Over the coming week we're rolling out coverage for Robinhood Chain — Robinhood's new EVM Layer-2 (Arbitrum Orbit, chain ID 4663) — bringin…

Platform+

MadeOnSol is expanding beyond Solana. Over the coming week we're rolling out coverage for Robinhood Chain — Robinhood's new EVM Layer-2 (Arbitrum Orbit, chain ID 4663) — bringing the same on-chain intelligence you use for Solana to a second chain, on the back of one of the busiest memecoin scenes in crypto right now.

Live today:

  • Chain switcher in the header — Solana now, with Robinhood Chain — Soon alongside it. The site is multichain-aware end to end.
  • A research cluster on Robinhood Chain on the blog: what the chain is, how to bridge to it, the memecoin landscape, and the hood.fun launchpad.

Rolling out over the next few days:

  • KOL, deployer, and sniper intelligence for Robinhood Chain, served through the same /api/v1 endpoints (chain-parameterized) and gated by the same tiers as their Solana equivalents — no per-chain upsell, it's coverage included in the plan you already have.
  • We're running our own Robinhood Chain node, so the data comes straight from the chain — the same accuracy standard as our Solana feeds, with no third-party data API in the middle.

New here? The free tier is 200 requests/day across every endpoint. See plans.

Jul 13SDK

Token depth / price impact + SDK release across all 7 packages

API:

SDK+

API:

  • New GET /api/v1/tokens/{mint}/depth (PRO+) — per-pool price-impact / slippage: "how much SOL does it take to move the price 1% / 5% / 10%" (to_move_price) plus the impact, average fill price, and tokens received for each buy size you ask about (?sizes= up to 8 SOL amounts, default 0.5,1,5,10). Exact for constant-product AMMs (PumpSwap, Raydium v4/CPMM, Meteora DAMM — computed from our streamed reserves, zero RPC, validated against Jupiter) and correct for pump.fun / bonk bonding curves via a live read of the curve's virtual reserves. Honesty built in: impact is per-pool (not router-optimal), and concentrated-liquidity pools (Raydium CLMM, Orca, Meteora DLMM) return under unsupported_pools[] with a reason instead of a wrong number. The sizing data a bot actually needs — raw liquidity_usd can't tell a deep pool from a thin one-sided one.

SDKs — all 7 packages updated:

  • Every SDK gains a token depth method and documents the risk endpoint's dev self-activity block (dev-buy at create, dev sells, live wallet_empty / transferred_out): TypeScript madeonsol 2.21.0, Rust madeonsol 0.23.0, Python madeonsol-x402 1.23.0, TypeScript madeonsol-x402 1.22.0, MCP server 1.20.0, ElizaOS plugin 1.19.0, Solana Agent Kit plugin 1.19.0.
Jul 11Platform

Dev-activity intelligence: did the dev buy, did the dev dump, is the dev wallet empty

API:

Platform+

API:

  • New dev block on GET /api/v1/tokens/{mint}/risk — the full deployer self-activity story for a launch, three layers deep:
    • Dev-buy at create: buy_sol, buy_tokens, buy_supply_pct — the deployer's self-buy extracted exactly from the create transaction's balance meta ("dev bought 2.5 SOL = 8.2% of supply at launch"). Captured on effectively all new pump.fun creates going forward.
    • Dev sells: sold_tokens, sold_sol, first_sell_at, last_sell_at — the deployer's post-create trades on their own token, rolled up every 2 minutes.
    • Live truth: holdings_tokens, holdings_supply_pct, and wallet_empty — the dev wallet's current on-chain balance for the mint, read live (60s cache). This answers the question that actually gates most buys — "is the dev wallet empty right now?" — regardless of trade-capture coverage.
    • Plus transferred_out: when the on-chain balance sits well below what the dev's trades say they should still hold, the tokens left by transfer, not sale — the classic pre-dump wallet-hop. Only asserted when we have the coverage to prove it; reads null (unknown), never a guess.
  • deployer:alert webhook/WS payloads now carry dev_buy_sol + dev_buy_supply_pct — filter tracked-deployer launch alerts by dev skin-in-the-game the moment they fire.
  • GET /api/v1/wallet/{address} is faster at the tail — the enrichment layer's external lookups are now cached, tighter-bounded, and parallelized; worst-case latency dropped from ~6s to well under 1.5s, typical repeat lookups ~100ms.
Jul 11Security

x402 never-charged-for-errors, gap-free deployer history, security & data hardening

x402:

Security+

x402:

  • Invalid requests are now rejected before payment. Every keyless x402 endpoint validates your query params — enums, numeric ranges, address/timestamp formats, and from/to ordering — before settlement, returning a clean 400 with the offending param named. A malformed call like ?tf=99m or ?period=99d is no longer settled-then-errored, honoring the "pay → get data, never pay for an error" contract across the whole catalog (previously enforced on only two endpoints).

API:

  • GET /api/v1/deployer-hunter/{wallet}/history returns a continuous daily series. Snapshots are now stored write-on-change (a row only when a deployer's reputation actually changes), and the endpoint forward-fills the gaps on read — so you still get one entry per day, with a new carried flag marking days synthesized from the most recent real snapshot. Same shape, far less storage, no behavior change for consumers beyond the new field.

Reliability & security:

  • Account deletion is now all-or-nothing. Every erasure step is checked and the irreversible account delete is aborted if any step fails — no more orphaned rows on a partial failure — and the statutory invoice snapshot is guaranteed to persist before payment records are removed.
  • Changing your password now signs out your other sessions.
  • Hardened webhook signature enforcement, tightened a handful of error responses (duplicate actions now return 409, malformed input 400 instead of 500), and added dead-cron / retention-job monitoring across the platform.
Jul 10Platform

Wallet reputation flags + batch classify, token trade tape, sniper footprint, x402 catalog 18 → 25

API:

Platform+

API:

  • New POST /api/v1/wallet/batch/classify (PRO+) — bulk wallet reputation flags for up to 100 addresses in one call. Body { wallets: string[] } (or a comma-separated string). Per wallet: is_sniper, is_bundler, is_dumper + the raw dump_cluster cohort counts, is_kol + kol_name, and bot_confidence — values identical to the single-wallet flags block. Pure index lookups: ~10ms per 100-address batch, counts as 1 request. Screen an entire early-buyer list or copy-trade candidate set in a single call.
  • GET /api/v1/wallet/{address} — reputation flags in the flags block. New: is_sniper (≥5 tokens early-bought with ≥80% flipped in under 5 minutes; behavior-updated ~every 12 min), is_bundler (bought >1 token in the same block, ever — lifetime flag), is_dumper (≥5 dump cohorts and 0 runner cohorts in a rolling 42-day window) plus the dump_cluster cohort counts. Also fixed: bot_confidence was always null due to a coercion bug — it now returns the real string enum (none/low/medium/high). Honesty note: flags are pump.fun-pipeline scoped — false means not observed, not verified clean.
  • New GET /api/v1/tokens/{mint}/trades (PRO+) — the mint-scoped trade tape: every captured trade for one token, newest first, cursor-paginated. Filters: limit (1–500), action (buy/sell), wallet, since/until (default full history). Each trade carries tx_signature, wallet_address, action, sol_amount, token_amount, price_sol/price_usd, early_buyer_rank, slot, and block_time. The response's coverage block states the capture window plainly (history starts 2026-04-12, pump.fun-pipeline scoped). The backfill complement to the live firehose — seed your history, then stay current via the stream.
  • Sniper footprint — how hard a launch was sniped. GET /api/v1/tokens/{mint}/risk gains inputs.sniper_footprint and every deploy on GET /api/v1/sniper/recent gains a footprint block: the rollup of buys landing in slots deploy−1 through deploy+3 — buys, buyers, sol, supply_pct (% of supply bought in-window), and sniper_wallet_buys (window buyers already on the sniper registry). Informational — it doesn't move the risk score — and data_available: false means the mint is outside our capture window, not zero snipes. Null on sniper/recent for deploys younger than the rollup's 10-minute settle window.

x402:

  • Keyless catalog grew 18 → 25 endpoints. Seven more endpoints are now payable per-call in USDC with no API key: tokens/{mint}/candles ($0.01), tokens/almost-bonded ($0.01), tokens/{mint}/top-traders ($0.02), tokens/{mint}/cap-table ($0.02), sniper/recent ($0.01), tokens/{mint}/flow ($0.01), and deployer-hunter/{wallet}/trajectory ($0.01). Full list on the free discovery endpoint at /api/x402.

Data quality:

  • Phantom counterparty rows eliminated. Bonding-curve PDAs had been recorded as wallet-side traders on ~32% of token_trades rows — those phantom rows are now filtered at ingest and cleaned up historically, and early-buyer ranks were recomputed accordingly. Cap-table, buyer-quality, trade tapes, and wallet PnL all read cleaner for it.

SDKs:

  • The batch-classify and token-trades methods ship across all 7 SDKs — madeonsol-x402 1.21.0 (npm), the bare TypeScript madeonsol 2.20.0, madeonsol 1.22.0 (PyPI), the Rust crate madeonsol 0.22.0, the MCP server mcp-server-madeonsol 1.19.0, the Eliza plugin @madeonsol/plugin-madeonsol 1.18.0, and solana-agent-kit-plugin-madeonsol 1.18.0. Additive only, no breaking changes.
Jul 8Platform

Business tier — self-serve embedding at 500k requests/day

Pricing:

Platform+

Pricing:

  • New BUSINESS tier — €400/mo or €4,000/yr. The self-serve tier between Ultra and contact-sales Enterprise, built for embedders and high-volume builders. Everything in Ultra at roughly 5× the limits: 500,000 requests/day, 3,000/min burst, 10 WebSocket connections + 5 DEX-firehose connections, 30 webhooks, copy-trade 250 wallets across 100 rules, 100 coordination rules, 50 first-touch subscriptions, 125 price alerts, and a 500-slot wallet tracker.
  • The embed license. Business is the first tier licensed to display MadeOnSol data inside your own product to your end users (one product). The terms now spell out the data license per tier: below Business, usage is internal-only. Raw resale, redistribution, and white-label stay on Enterprise.
  • Available on every payment rail — one-off SOL/USDC, card (Stripe), and on-chain USDC auto-renew. Upgrade from /pricing or straight from the upgrade link in an Ultra 429 body.
Jul 7SDK

Verified wallet holdings in every SDK

API:

SDK+

API:

  • GET /api/v1/wallet/{address}/holdings (ULTRA) is now documented in the OpenAPI spec and shipped across all SDKs. It returns a wallet's chain-verified current holdings — its actual SPL + Token-2022 token accounts and SOL balance read live from chain, enriched with price, market cap, and name/symbol from our own data. Unlike /wallet/{address}/positions (trade-derived FIFO, transfer-blind), this is a true holdings census, and each holding carries transfer_delta = on-chain amount minus the trade-derived net position — a large positive delta flags tokens that arrived without a swap (airdrops, insider funding, wallet-hopping). 90s cache; cache hits are free.

SDKs:

  • The new holdings method ships across all 7 SDKs — madeonsol-x402 1.20.0 (npm), the bare TypeScript madeonsol 2.19.0, madeonsol 1.21.0 (PyPI), the Rust crate madeonsol 0.21.0, the MCP server mcp-server-madeonsol 1.18.0 (tool madeonsol_wallet_holdings), the Eliza plugin @madeonsol/plugin-madeonsol 1.17.0, and solana-agent-kit-plugin-madeonsol 1.17.0. Call walletHoldings(wallet) (TS) / wallet_holdings(wallet) (Python/Rust). Additive only, no breaking changes.
Jul 5Platform

Four new endpoints: pool map, early-buyer PnL, deployer history, supply-inflation risk

API:

Platform+

API:

  • New GET /api/v1/tokens/{mint}/pools (PRO+) — the per-venue liquidity map for a token. Every pool it trades in across pump.fun / PumpSwap / Raydium / Meteora / Orca, with each pool's liquidity_usd, last_price_sol, DEX and quote mint, whether it's live vs parked (is_active), plus a summary: total liquidity, pool/DEX counts, the primary (deepest) pool, and top_pool_share_pct (how concentrated liquidity is in one pool). GET /token/{mint} returns a single aggregate liquidity number — this shows where that liquidity actually sits and how fragmented it is.
  • GET /api/v1/tokens/{mint}/cap-table — enriched with exit/PnL. Each early buyer now carries realized_pnl_sol, total_sol_bought / total_sol_sold, first_sell_at, and still_holding. Turns the early-buyer list into a smart-money exhaustion read: did the early money profit, and has it already cashed out? Computed from confirmed on-chain trades.
  • New GET /api/v1/deployer-hunter/{wallet}/history (PRO+) — a deployer's daily reputation time-series: bonding_rate, recent_bond_rate, tier, avg_peak_mc and totals per day. Lets you answer "was this deployer elite at the time it launched token X?" — i.e. backtest deployer alerts without look-ahead bias, which the point-in-time GET /deployer-hunter/{wallet} can't.
  • Token risk: new supply_inflation factor. GET /api/v1/tokens/{mint}/risk now flags on-chain supply that has grown above its expected/launch supply (stealth mint / post-launch dilution), normalized by supply so it's decimals-agnostic and noise-filtered. A rug vector distinct from mint-authority — the authority can be revoked yet supply already have been inflated before.

All new/changed endpoints are PRO+ (cap-table stays field-gated across tiers). Full reference on the API docs.

Jul 4Platform

Bundle intelligence: how much of supply the bundle still holds

API:

Platform+

API:

  • New GET /api/v1/tokens/{mint}/bundle — bundle intelligence for a token. It resolves the token's bundle cohort — the same-slot "bundle" wallets that bought together (≥3 wallets buying in one slot = is_bundle) — and, the headline, how much of supply that cohort still holds. The bundle block returns wallet_count, bundle_kind (atomic_tx | same_slot | none), held_ratio, held_pct_of_supply (net tokens held ÷ supply, clamped 0–1 — the rug/insider read), fully_exited, buy_volume, and tokens_held. Crucially this is computed from confirmed on-chain trades (token_trades), not a pre-execution shred feed — it's the incumbents' headline "current held %" signal done the correct confirmed-data way, with bundle_kind atomicity added on top. Honest about its inputs: held_pct_of_supply is a swap-derived net proxy (clamped), tokens_held is that same net proxy rather than a holder census, and buy_volume is cumulative buy volume — not distinct tokens, so it can exceed supply. Field-gated across all tiers (funnel-hook, same as buyer-quality / cap-table): BASIC/TRADER get the scalar bundle block only, PRO adds the top-10 wallets (flags only), and ULTRA returns the full cohort enriched with KOL/alpha identity (kol_name, win_rate, bot_confidence). Full reference on the API docs.

SDKs:

  • A new bundle-holdings method ships across all 7 SDKs — madeonsol-x402 1.19.0 (npm), the MCP server mcp-server-madeonsol 1.17.0 (tool madeonsol_token_bundle), the Eliza plugin @madeonsol/plugin-madeonsol 1.16.0, solana-agent-kit-plugin-madeonsol 1.16.0, madeonsol 1.20.0 (PyPI), the bare TypeScript madeonsol 2.18.0, and the Rust crate madeonsol 0.20.0. Additive only, no breaking changes.

Site:

  • The API docs now list and let you try /tokens/{mint}/bundle alongside cap-table and buyer-quality.
Jul 1Platform

Accurate PnL (cost-basis + unrealized) + bonk/bags coverage

API — PnL accuracy:

Platform+

API — PnL accuracy:

  • KOL leaderboard & wallet PnL are now cost-basis realized PnL, not net SOL flow. Before, a trader mid-accumulation — bought a lot, sold a little — showed a large "loss" because the full cost was charged against partial proceeds. Now only the cost of the sold portion counts, so /api/v1/kol/leaderboard, /api/v1/kol/{wallet}/pnl, and the wallet endpoints report realized PnL that reflects actual round-trips. Accumulators no longer read as losers, and the leaderboard ranks on true realized PnL.

  • Unrealized PnL on still-held positions. /api/v1/kol/{wallet}/pnl and the wallet endpoints now include unrealized_pnl_sol + total_pnl_sol — the mark-to-market value of tokens a wallet is still holding, priced from our own data, alongside realized. Held inventory is valued, not counted as a loss.

  • USDC/USDT-quoted trades are now captured. Swaps priced in USDC/USDT rather than SOL — a growing share on pump.fun & PumpSwap stable pairs — are now recorded and counted in PnL, volume, and firehose data instead of being dropped.

API — beyond pump.fun:

  • Wallet PnL, token flow, and cap-table now cover bonk (LetsBonk) & bags launchpad tokens, not just pump.fun — a wallet's bonk/bags trades now show up in /api/v1/wallet/{address}/pnl, /api/v1/tokens/{mint}/flow, and the cap-table.

  • Deployer-hunter now surfaces bonk deploys. GET /api/v1/deployer-hunter/{wallet} gains a launchpad_tokens field listing a deployer's bonk (Raydium LaunchLab) tokens from our own on-chain index, alongside the existing pump.fun pump_tokens.

  • Almost-bonded now covers bonk (LetsBonk). GET /api/v1/tokens/almost-bonded widened past pump.fun to include bonk/LetsBonk (Raydium LaunchLab) tokens approaching graduation, with live bonding-curve progress_pct computed from the LaunchLab curve. Each token now carries a launchpad field (pumpfun or launchlab) so you can tell the venue apart. Read straight from our firehose — no external API.

June 2026

23 ships
Jun 30Platform

Pay by card (Stripe) + EUR-canonical pricing

Payments:

Platform+

Payments:

  • Card payments are live. You can now subscribe to PRO or ULTRA with a credit or debit card via Stripe Checkout, right alongside the existing crypto rails — one-off USDC/SOL, or on-chain USDC auto-renew. Card is the default at checkout, renewals are automatic, and you can upgrade, downgrade, update your card, or cancel anytime from the Stripe billing portal (linked in the developer dashboard). Non-EU buyers are shown their local currency at checkout via Stripe Adaptive Pricing.

  • EUR is now the canonical price. Plans are billed in euro — PRO €43/mo (€430/yr), ULTRA €131/mo (€1,310/yr) — with the dollar figure shown as a live "≈ $49 / ≈ $149" reference that floats with the daily rate. The crypto rails price off the same fixed euro amount, converted to USDC/SOL at the day's rate, so every method quotes the same price. The checkout pay button shows what you'll actually send per rail (e.g. "~0.67 SOL (€43/mo)").

Site:

  • Pricing, checkout, the developer dashboard, blog, and SDK docs now show "€X (≈ $Y)" with card, USDC, and SOL all offered (card first). Product structured data and page metadata were updated to the euro prices.
Jun 29Platform

Self-serve WebSocket session management

API:

Platform+

API:

  • New GET /api/v1/stream/sessions (PRO/ULTRA) — list your live WebSocket sessions across both the event stream and the DEX firehose. Each entry carries its id, service, tier, subscribed channels, connected_at, remote_ip, and messages_sent. It reflects in-memory connection state, not historical logs, so every id it returns is one you can act on.

  • New DELETE /api/v1/stream/sessions/{id} (PRO/ULTRA) — force-close one of your own live sessions and release its connection slot immediately. This is the self-serve fix for a 4002 Connection limit reached lockout when a redeploy on your side (e.g. an old and new instance briefly running at once) leaves a half-open socket holding your slot — no need to email support or wait for the server-side reaper. The socket is closed with code 4002; you can only terminate sessions belonging to your own key.

Jun 27Platform

Almost-bonded discovery + trending/momentum sorts

API:

Platform+

API:

  • New GET /api/v1/tokens/almost-bonded (PRO/ULTRA) — pre-bond pump.fun tokens approaching graduation, so you can catch them before they bond. Each token carries its live bonding-curve progress_pct (from on-chain real_token_reserves depletion) and, uniquely, its velocity (velocity_pct_per_min = Δprogress/min) plus a linear eta_minutes projection — "95% and accelerating" ranks above "92% stalled". Enriched with deployer reputation (deployer_tier) so you can filter to elite/good deployers only. Filters: min_progress/max_progress (default 80–99.99% band), min_velocity_pct_per_min, max_age_minutes, deployer_tier, authority_revoked, min_liq. Sort by velocity_desc (default), progress_desc, or eta_asc. Self-hosted from our firehose — no external API.

  • Trending / momentum sorts on GET /api/v1/tokens (PRO/ULTRA). The token directory now accepts four new sort values — mc_change_5m_desc, mc_change_1h_desc, volume_1h_desc, and trending (recent volume × momentum) — turning it into a reputation-aware momentum board. Combine with deployer_tier and max_mev_share_pct to surface clean-volume movers from trusted deployers and screen out bot-driven wash-pump volume.

Jun 26Platform

Data-services hub for builders + in-article embed CTA

Content:

Platform+

Content:

  • New builder's hub: Solana Memecoin Data API for Builders. A pillar guide for teams embedding our data in a product — what the KOL-flow, deployer-reputation, coordination, and DEX-firehose layer actually is, the build-vs-buy math, the four ways to pull it in (REST, WebSocket, webhooks, MCP/SDKs), and when to white-label it on Enterprise. It anchors a B2B-embedder content cluster, interlinked with the gRPC streaming, Geyser-plugin, and self-hosting cost guides.

Site:

  • In-article "embed our data" CTA. Data-service blog posts now surface a compact data-services call-to-action partway through the article, not only in the footer band — so readers building on Solana data hit the Enterprise / white-label path before they finish reading, instead of scrolling past it at the end.
Jun 21API

Token trade-flow endpoint + deployer SOL balance on alerts

API:

API+

API:

  • New GET /api/v1/tokens/{mint}/flow?window=1h|24h (PRO/ULTRA) — a per-token trade-flow aggregate computed straight from the trade firehose, the "organic vs fake volume" read for a single mint. Returns unique_wallets, unique_buyers, unique_sellers, buy_count, sell_count, total_trades, buy_sol, sell_sol, net_sol, and trades_per_wallet. trades_per_wallet is a wash-trading proxy: a high trade count concentrated across very few wallets is the classic synthetic-volume tell, while a low ratio across many wallets reads as organic demand. Counts and flows only — no holder data. Self-hosted from our firehose, no external API.

  • deployer_sol_balance on deployer-hunter alerts. GET /api/v1/deployer-hunter/alerts items now carry deployer_sol_balance (number | null) — the deployer wallet's SOL balance captured at alert time. null for rows alerted before 2026-06-21. The field was already on the deployer:alert webhook payload; it's now on the REST feed too.

SDKs:

  • A new tokenFlow method ships across all 7 SDKs — madeonsol 2.15.0 (TypeScript), madeonsol-x402 1.16.0 (TS) and 1.17.0 (Python), the MCP server 1.14.0, the Eliza and Solana Agent Kit plugins 1.13.0, and the Rust crate madeonsol-rs 0.17.0 — and the deployer-alert types gain the deployer_sol_balance field. Additive only, no breaking changes.
Jun 21Platform

Call the API from the browser (CORS) + Enterprise tier

API:

Platform+

API:

  • CORS is now enabled on every /api/v1 endpoint. Browser and frontend apps — dashboards, widgets, in-app panels — can call the keyed API directly with their Authorization: Bearer token, no server-side proxy required. Preflight OPTIONS requests return immediately, and the Access-Control-Allow-* headers ride every response. Auth is Bearer-token (not cookies), so direct browser calls are safe.

Platform:

  • Enterprise tier. For tools, funds, and platforms embedding our data in production: an uptime SLA, dedicated rate limits beyond Ultra's 100k/day, white-label and redistribution rights, custom endpoints, and a priority support channel. See Pricing or email [email protected].

SDK (1.12.1):

  • Fixed copy-trade & alpha methods in the Eliza and Solana Agent Kit plugins. They were calling retired paths (/copy-trade/rules, /alpha/wallet/{w}) and 404ing; they now hit the live routes (/copytrade/subscriptions, /alpha/{w}). copyTradeCreate also takes the correct body — source_wallets[] + sizing_amount — instead of the old single-source_wallet shape.
Jun 20Platform

Canonical pricing across the API

Every token price we serve — on the /tokens endpoints, wallet PnL, positions, and the KOL feed — now comes straight from on-chain pool and bonding-curve reserves, the same sourc…

Platform+

Every token price we serve — on the /tokens endpoints, wallet PnL, positions, and the KOL feed — now comes straight from on-chain pool and bonding-curve reserves, the same source our market-cap engine trusts.

We retired the older trade-derived estimate, which could be thrown off by network fees, Jito tips, and rent on small trades, and we revived pricing for pre-graduation pump.fun tokens so brand-new launches get a real price instead of a gap. The result: roughly 98% of trade prices now land inside the minute's actual traded range, and the rare order-of-magnitude bad-price tail is gone.

Jun 19Security

x402 security hardening on keyless pay-per-call

A focused security pass on the keyless x402 surface — the path where agents and scripts pay per request with no API key.

Security+

A focused security pass on the keyless x402 surface — the path where agents and scripts pay per request with no API key.

  • Method precheck. Unsupported HTTP methods are rejected before any payment is requested, so you're never charged for a request that was never going to succeed.
  • Per-IP rate limiting. The keyless surface now enforces the same in-memory per-IP limits as the keyed API — a single caller can't hammer it.
  • Strictly read-only. The x402 path exposes data endpoints only; no state-changing route is reachable without a key.
  • Consistent validation. Every x402 endpoint validates mint and wallet inputs identically to the keyed /api/v1 routes, and the OpenAPI spec now matches actual behavior — including string-or-array batch mints and Solana path-param examples.
Jun 17Platform

Upgrade-aware 403s + one-click first call

Two onboarding upgrades: the API now tells you exactly how to unlock a gated endpoint, and the dashboard runs your first call for you.

Platform+

Two onboarding upgrades: the API now tells you exactly how to unlock a gated endpoint, and the dashboard runs your first call for you.

API:

  • Tier-gated endpoints now return an actionable 403. When a free or under-tier key calls a PRO/ULTRA endpoint, the response is no longer a bare error string — it carries an upgrade block with the required_tier, monthly price, the new daily/burst limits, a one-line note of what unlocks, and a direct upgrade_url. SDK clients (and humans curling) see the path out inline instead of bouncing to the docs. Applied across every tier-gated route — token risk, cap tables, wallet PnL/positions, sniper feeds, copy-trade, KOL coordination, and more.

Site:

  • "Run your first call" on the /developer dashboard — generate a key and fire a real request against live data in one click, no code or curl needed. Returning key-holders get the same one-click sample call.
  • The Quick Start snippet now pre-fills your actual key, so it's copy-paste-run.
  • API pricing CTAs added across the Intelligence pages (KOL Tracker, Deployer Hunter, Wallet Scanner, Token Lookup, Scout Leaderboard, Daily Alpha) — a reminder that the free tier is 200 calls/day, no card.
Jun 15Platform

Token Risk Score: a rug-risk number you can audit

A single, transparent safety score for any token — with the per-factor breakdown that produced it, not just an opaque number.

Platform+

A single, transparent safety score for any token — with the per-factor breakdown that produced it, not just an opaque number.

API:

  • New GET /api/v1/tokens/{mint}/risk (PRO/ULTRA) — a 0–100 rug-risk / safety score with a band (safe / caution / danger) and an auditable factors[] array. Each factor carries its own status, points, and detail — mint/freeze authority, liquidity depth & thinness, Token-2022 transfer fee, LP burn, bundled/sniped open, deployer track record, KOL distribution, and blacklist. Unlike a black-box score, you can see exactly why a token landed where it did. The response also returns the raw inputs and a score_version. Composed from the same data layer as GET /token/{mint}, so there's no extra latency. Full reference on /api-docs#tools.

SDKs:

  • madeonsol-x402 1.13.0 · madeonsol (PyPI) 1.14.0 · mcp-server-madeonsol 1.12.0 · @madeonsol/plugin-madeonsol 1.11.0 · solana-agent-kit-plugin 1.11.0 — all gain a token-risk method/tool. Additive only, no breaking changes.
  • Bare TypeScript SDK madeonsol 2.13.0 and the Rust SDK madeonsol 0.14.0 — also updated with the token-risk method.

Site:

  • Token Risk Score added to the pricing/feature cards, the /developer page, and the API docs.
Jun 14Platform

Liquidity depth, launch cohort, and deployer-tier filters on /tokens

Four new enrichment fields and three new filters — all computed from data we already hold, no new pipeline.

Platform+

Four new enrichment fields and three new filters — all computed from data we already hold, no new pipeline.

New fields on /token/{mint} and /token/batch:

  • liquidity_to_mc_ratio — liquidity_usd ÷ market_cap. A structural depth gauge: low ratios flag thin pools where a single exit can crater price. Useful as a risk screen before sizing a position.
  • launch_cohort_sol — total SOL committed by the token's first-20 buyers. A proxy for early conviction: high cohort SOL on a no-name deployer is a signal worth watching; high SOL with a dump-factory deployer is a counter-signal.
  • launch_cohort_size — how many of the first-20 buyer slots are filled (0–20). Low size on an older token typically means it was abandoned early.

New fields on /tokens list response: liquidity_to_mc_ratio and deployer_tier are now returned per token — screen the whole list without a /token/{mint} roundtrip.

New filters on /tokens:

  • min_liq_mc_ratio / max_liq_mc_ratio — keep only tokens within a liquidity-depth band.
  • deployer_tier — filter to tokens from a specific deployer reputation tier (elite | good | moderate | rising | cold | unranked). Combine with min_liq_mc_ratio=0.05 to find elite-deployer tokens that still have meaningful liquidity.

New fields on /kol/leaderboard: median_hold_minutes_30d and percentile_early_entry_30d are now returned per KOL, surfacing hold-duration and timing discipline without a separate profile call.

All fields are additive — no breaking changes.

Jun 14SDK

SDK v1.12.0: enrichment fields + new filters

All seven SDKs updated with today's API additions. Additive only, no breaking changes.

SDK+

All seven SDKs updated with today's API additions. Additive only, no breaking changes.

madeonsol 2.12.0 · madeonsol-x402 1.12.0 · madeonsol-python 1.13.0 · madeonsol-rs 0.13.0 · mcp-server-madeonsol 1.11.0 · @madeonsol/plugin-madeonsol 1.10.0 · solana-agent-kit-plugin 1.10.1

  • TypeScript / x402 — TokenResponseBody gains liquidity_to_mc_ratio, launch_cohort_sol, launch_cohort_size; TokenListParams gains min_liq_mc_ratio, max_liq_mc_ratio, deployer_tier; KolLeaderboardEntry gains median_hold_minutes_30d, percentile_early_entry_30d; new getSignalPerformance(name) method.
  • Python — tokens_list() now accepts min_liq_mc_ratio, max_liq_mc_ratio, and deployer_tier keyword args.
  • Rust — all three structs (TokenResponseBody, TokensListParams, KolLeaderboardEntry) updated with typed fields.
  • MCP — madeonsol_tokens_list tool gains the three new filter params; new madeonsol_signal_performance tool added.
  • Plugins — getTokensList() / tokensList() extended with the three new filter params.
Jun 11Platform

Data quality you can see

We don't just claim the data's clean — we continuously verify it and show you the result. /api-status now reports live data-quality SLOs alongside service uptime:

Platform+

We don't just claim the data's clean — we continuously verify it and show you the result. /api-status now reports live data-quality SLOs alongside service uptime:

  • On-chain accuracy — a rolling sample of served tokens is re-checked against on-chain supply (FDV ≡ price × supply). A stale-supply or phantom-price market cap is caught within minutes, not on your bug report.
  • Field correctness — every served field on the core data endpoints is validated against its contract (never-null where it shouldn't be, values in range) on a fast cadence.
  • Quality drift — per-field null-rates are tracked against a trailing baseline, so a slow degradation surfaces before it crosses a hard line.
  • Serve-time integrity — the exact bytes we send you are audited the instant they leave the API.

Each is shown as adherence over a trailing window with its sample count — honest, on-chain-grounded (no external aggregators), and self-correcting as history accrues. The same checks page us internally the moment something slips.

Also for developers: subscribing to an unknown or tier-gated WebSocket channel now returns a channels_rejected warning naming what was dropped and why — instead of silently delivering nothing. (Tried dex:trades and got silence? The DEX firehose is a separate ULTRA endpoint — the warning now points you there.)

Jun 9Platform

Signal Scorecard: every signal, backtested live

You shouldn't have to trust a signal on faith. Every signal we serve now self-reports how well it actually works — measured out-of-sample, refreshed daily, and shown openly.

Platform+

You shouldn't have to trust a signal on faith. Every signal we serve now self-reports how well it actually works — measured out-of-sample, refreshed daily, and shown openly.

  • Public Signal Scorecard — per-signal hit rate by bucket, lift over base, and sample size. Starts with dump-cluster detection and deployer runner-rate; more to come.
  • Inline on tokens/{mint}/buyer-quality — responses now include a signal_stats block so a raw value explains itself: dump_cluster_count=17 comes back as "98% of such tokens dumped vs 75% base (1.3× lift), n=190, 14d out-of-sample."
  • New GET /api/v1/signals/{name}/performance — the full backtest as JSON (dump_cluster_count | runner_rate), so bots can weight signals programmatically instead of guessing. ?history=true returns the per-day series for drift.

How it stays honest: rolling train/test split (signals graded only on data they weren't built from — no lookahead), a ≥15 early-buyer filter so sparse tokens can't inflate the numbers, and peak-timing labels (dump <15 min, runner ≥60 min). The numbers will move with the market — that's the point.

Also shipped:

  • WS deployer:bond now carries runner_rate, labeled_tokens, and recent_bond_rate (previously only on deployer:alert) — read deployer quality straight off a graduation event, no REST round-trip.
  • Token market caps — fixed a class of stale-supply phantom MCs (idle tokens whose on-chain supply had drifted after we stopped tracking them). /tokens and /token/{mint} now reconcile supply against the live chain daily, so a dead token can't report an impossible market cap.
Jun 8Platform

Deployer runner-rate on alerts, sniper deploys & streams

Every deployer signal now carries the deployer's runner-rate — the fraction of their tokens (with a real first-20 buyer cohort) that ran (peak ≥60 min after deploy) vs dumped (p…

Platform+

Every deployer signal now carries the deployer's runner-rate — the fraction of their tokens (with a real first-20 buyer cohort) that ran (peak ≥60 min after deploy) vs dumped (peak under 15 min). It's a validated as-of read on the next launch: out-of-sample across 8,635 auto-labeled tokens it moved P(runner) monotonically from 10.5% (deployers who never produce runners) to 75.5% (deployers who consistently do), against a 27.6% base — and it adds signal within tier, separating a 0%-runner "elite" pump-and-dump factory from a genuine builder the tier alone scores the same.

New fields (additive, no breaking changes):

  • deployer-hunter/alerts + deployer-hunter/{wallet} — runner_rate, labeled_tokens (the confidence denominator — gate on ≥3), and avg_time_to_bond_minutes.
  • sniper/recent + WS sniper:deploys — deployer_runner_rate, deployer_labeled_tokens, snapshotted onto the pre-confirmation deploy.
  • WS deployer:alert / deployer:bond — runner_rate, labeled_tokens.

Refreshed every 6 hours. One counter-intuitive note from the validation: fast bonders skew dump, not runner — a deployer who bonds in under 30 min runs 12% of the time vs 40% for those taking 6 h+. Slow bond = organic demand.

Also fixed: WS min_mc_usd / max_mc_usd band filtering now works on deployer:alert, deployer:bond and token:graduations. It previously matched the field on none of those channels and silently dropped every event when a band was set.

Jun 7SDK

SDK v1.11.0: graduation events + dump-cluster types

All seven SDKs updated for today's API additions — additive only, no breaking changes:

SDK+

All seven SDKs updated for today's API additions — additive only, no breaking changes:

  • TypeScript madeonsol-x402 1.11.0 and bare madeonsol 2.11.0 — token:graduations added to the typed channel union (no more casting to subscribe), new GraduationEvent payload interface, buyer-quality breakdown typed with dump_cluster_count + recycled_early_buyer_count.
  • Rust madeonsol 0.12.0 — same two breakdown fields on AlphaBuyerQualityBreakdown (previously serde dropped them silently) + GraduationEvent struct.
  • Python madeonsol-x402 1.12.0 — channel/event registries updated; string subscribe already worked, docs now match.
  • mcp-server-madeonsol 1.10.3 — buyer-quality tool description corrected (full breakdown is returned on all tiers, not PRO+) and now mentions the dump-cluster fields.
  • @madeonsol/plugin-madeonsol and solana-agent-kit-plugin-madeonsol 1.9.2 — README documentation for both features (payloads pass through unchanged).
Jun 7Platform

Real-time graduation events

Pump.fun graduations (bonding curve complete → PumpSwap migration) are now pushed in real time, two ways:

Platform+

Pump.fun graduations (bonding curve complete → PumpSwap migration) are now pushed in real time, two ways:

token:graduations channel on the WebSocket stream (PRO + ULTRA) — every graduation, whether or not the deployer is tracked. This closes the gap left by deployer:bond, which only covers tracked deployers. Payload carries token_mint, name/symbol, time_to_bond_minutes, deployer_wallet, deployer_tier (unranked when unknown), market_cap_usd at bond, and bonded_at. The deployer_tier array filter applies if you only want graded deployers.

In-band dex:graduations frames on the DEX firehose (ULTRA) — subscriptions that scope mints via token_mint(s) receive the graduation for those mints on the same connection and sub_id as the trade flow. If you're watching an open position, the bond arrives in the stream you're already reading — no separate connection, no polling recent-bonds.

Detection rides the hardened three-layer bond pipeline (instruction parser on dual-region gRPC, pool-state confirmation, curve-confirm reconciler) — the same source of truth as deployer-hunter stats. Events fire from the real-time paths only, so a graduation frame is always seconds-fresh, never a stale backfill.

Jun 7Platform

Buyer-quality: dump-cluster wallet detection

Two new fields in the buyer-quality breakdown (single + batch endpoints, all tiers, no score impact):

Platform+

Two new fields in the buyer-quality breakdown (single + batch endpoints, all tiers, no score impact):

dump_cluster_count — how many of the token's first-20 buyers are on a rolling dump-cluster list: wallets whose recent first-20 appearances (5+) are exclusively on tokens that peaked within 15 minutes of deploy. This shipped only after surviving out-of-sample validation on 8,300+ auto-labeled launches with a strict temporal split: 3+ such wallets in a cohort predicted a sub-15-minute peak 94% of the time (vs 61% base rate), rising to 99% at 5+. Controls confirmed it's the composition that matters — raw sniper-wallet activity in a cohort predicts nothing (61%, exactly base).

recycled_early_buyer_count — first-20 buyers with 5+ recent first-20 appearances of any kind. On its own it's noise, but the combination is informative in both directions: a heavily recycled cohort with dump_cluster_count 0 historically leaned runner (39% dump — 22 points below base).

The list is rebuilt daily over a trailing 42-day window — validation showed wallet churn kills any static list within ~2 weeks, so the ensemble rolls. Individual wallets are never exposed.

Jun 7API

DEX firehose: replay buffer deepened 12×

replay: N on a firehose subscription backfills the N most recent trades matching your filters from a server-side buffer — it is not connection-scoped, so it covers trades from b…

API+

replay: N on a firehose subscription backfills the N most recent trades matching your filters from a server-side buffer — it is not connection-scoped, so it covers trades from before your connection existed. Until today that buffer held only ~30 seconds of firehose history (it was sized for reconnect gaps); it now holds roughly 5–6 minutes at typical volume (2–3 minutes at peak). Subscribing to a mint at alert time with replay: 500 now recovers the in-flight trade history, not just the last half-minute.

Semantics worth knowing (now also in the API docs): replayed trades arrive newest-first flagged "replay": true, followed by a replay_done frame — sort by block_time client-side. The per-subscription cap stays at 500 trades; async filters (token age, market cap, deployer tier) are skipped on replay since they evaluate against live state. No client or SDK changes required.

Jun 6Platform

WebSocket streaming overhaul: no more silent connections

A delivery audit found that most streaming customers were getting stuck in the same invisible traps — connected but never receiving events. All of them are now dismantled:

Platform+

A delivery audit found that most streaming customers were getting stuck in the same invisible traps — connected but never receiving events. All of them are now dismantled:

The server tells you when you're not subscribed. A WebSocket connection delivers nothing until you send {"type":"subscribe","channels":[...]} — previously, getting that wrong meant silence with no feedback. Now the connected frame includes a subscribe example and the full channel list, and if no channels are active after 10 seconds the server sends a hint frame with exactly what to send. Same on the DEX firehose.

Token lifecycle is no longer hostile to long-running clients.

  • POST /v1/stream/token is idempotent while your current token has more than 6 hours left — the same token is returned, so multi-process clients no longer invalidate each other's tokens on every mint.
  • When a token does rotate, the previous token stays valid for 60 seconds — in-flight reconnects survive the swap.
  • Expiring tokens are now rotated server-side and pushed in-band as a {"type":"token_refresh"} frame. Healthy connections are never hard-closed at the 24-hour mark anymore.
  • The mint endpoint got its own rate bucket (10/min), exempt from the shared REST quota — heavy REST usage can no longer lock you out of minting a streaming token.

Webhook owners are notified when their endpoint breaks. Ten consecutive failed deliveries still auto-pause a webhook, but now the owner gets an email explaining what failed and how to resume — previously the pause was silent.

Coordination alert latency, measured: in a live end-to-end test today, a coordination signal reached the subscriber's WebSocket 570ms after the triggering on-chain trade (rule create → KOL convergence → push).

Subscription housekeeping: when a paid plan lapses, copy-trade and coordination rules are now deactivated alongside webhooks and streaming tokens (previously they kept firing into the void), and they re-enable from the dashboard after renewal.

Jun 5SDK

SDK metadata patch release

Housekeeping release across four packages — no API surface changes:

SDK+

Housekeeping release across four packages — no API surface changes:

  • Pricing tables corrected in the package READMEs (they showed retired tiers; the real lineup is BASIC free / PRO $49/mo / ULTRA $149/mo, annual two-months-free): @madeonsol/plugin-madeonsol 1.9.1, solana-agent-kit-plugin-madeonsol 1.9.1, mcp-server-madeonsol 1.10.2, madeonsol-x402 (PyPI) 1.11.1.
  • The ElizaOS plugin's npm page now links to its GitHub repository (missing repository field added).
  • GitHub mirror repos synced + re-topiced for discoverability.
Jun 1SDK

SDKs: managed real-time streaming client

One-line WebSocket streaming across all SDKs. Until now every SDK handed you a token and left you to hand-roll the connection — open the socket, refresh the 24h token, reconnect…

SDK+

One-line WebSocket streaming across all SDKs. Until now every SDK handed you a token and left you to hand-roll the connection — open the socket, refresh the 24h token, reconnect on drop, parse heartbeats, type the events. The new managed client does all of it: client.stream() (TypeScript madeonsol-x402 1.10.0 / Python madeonsol-x402 1.11.0) and client.stream.connect() (bare madeonsol 2.10.0) return a stream you just subscribe-and-listen on, with auto-reconnect (backoff + jitter), token auto-refresh, heartbeat liveness, and typed events for all eight channels (KOL trades, coordination, first-touches, deployer alerts, wallet-tracker, copy-trade, price alerts, sniper deploys).

const stream = client.stream();               // x402
stream.on("kol:trade", (t) => console.log(t.token_symbol, t.action));
stream.subscribe(["kol:trades", "deployer:alerts"]);

The TypeScript clients use the native WebSocket on Node 22+ (with a lazy ws fallback) and zero required dependencies; the Python client is asyncio-based behind the optional madeonsol-x402[stream] extra.

Bare madeonsol SDK reaches full parity. Added the copy-trade namespace (client.copytrade — rules CRUD + signal history) that was the last gap versus madeonsol-x402.

Jun 1Platform

Public token pages, on-chain naming, reliability fixes

New: public token pages at /token/[mint]. Every token now has a shareable, AI-citable page — live price, market cap, liquidity, rug-safety checks (mint/freeze authority, LP burn…

Platform+

New: public token pages at /token/[mint]. Every token now has a shareable, AI-citable page — live price, market cap, liquidity, rug-safety checks (mint/freeze authority, LP burn, Token-2022 transfer fees), deployer reputation, and which tracked KOL wallets are buying or selling. Reachable from a new Token Lookup entry in the Intelligence menu (paste any mint). Pages carry FAQ + breadcrumb structured data; only tokens with real substance (named, liquid, or with KOL activity) are indexed — the long tail stays noindex to protect crawl budget.

On-chain token naming. Names/symbols for non-pump tokens (Raydium/Meteora/established SPL) are now resolved on-chain — Metaplex metadata accounts and the Token-2022 metadata extension — and cached. mc-tracker resolves each new token at first sighting (off the price hot path), so the highest-search-demand tokens get named and indexed automatically.

Deployer Hunter: false "Unknown" deploy alerts fixed. A parser bug was mis-reading ordinary swaps (which log Instruction: CreateTokenAccount/CreateIdempotent) as brand-new deploys, surfacing already-bonded tokens — some over a year old — as fresh "Unknown" launches. Create detection is now anchored to genuine pump-program token creates (with InitializeMint2 proof), and the auto-discovery that had widened the listener to the whole DEX firehose was reset to the real pump programs. Existing false alerts were cleaned up and affected deployer tiers reconciled.

Universal Wallet API resilience. /v1/wallet/{address} no longer returns a 500 on very high-trade-count wallets — when the 90-day aggregation exceeds the query timeout it degrades gracefully (core flags returned with an enrichment_unavailable flag) and the response is briefly cached, so repeat polls on the same heavy wallet are instant instead of timing out.

May 2026

23 ships
May 31Security

Content clusters, sitemap fix, security hardening

15 new blog posts across three content clusters. Trading-bot comparisons (Bloom vs BullX, Bloom vs Trojan, Photon vs Axiom, Banana Gun vs Trojan) and tool reviews (Bullpen, MevX…

Security+

15 new blog posts across three content clusters. Trading-bot comparisons (Bloom vs BullX, Bloom vs Trojan, Photon vs Axiom, Banana Gun vs Trojan) and tool reviews (Bullpen, MevX, TradeWiz, Cypherock X1, SafePal), plus a KOL/pump.fun guide set: filtering bot wallets from a KOL list, finding pump.fun tokens before KOLs tweet, why most pump.fun tokens die in the first hour, scoring a new token in 60 seconds, free vs paid KOL trackers, and Cielo vs Birdeye vs Solscan. All wired into hub/spoke internal links.

Sitemap fix — every blog post now indexable. The sitemap was only emitting the blog index page, not the ~360 individual posts (a stale-build artifact). Added hourly revalidation so all published posts now surface to search engines and AI crawlers. IndexNow notified on each new post.

Security: referral-earnings function locked down. The increment_referral_earnings Postgres function was callable by the anon/authenticated roles via PostgREST. Execute is now revoked from everything except the server-side service role (migration 158). No abuse observed — closed proactively after a health check flagged it.

Affiliate click attribution. Blog affiliate links now route through tracked /go/[slug]?source=blog/... redirects for per-post attribution, and admin clicks are excluded from affiliate stats to prevent self-click inflation.

Product structured-data fixes. Resolved Google Search Console warnings on tool pages (missing image and availability fields in the Product/Offer JSON-LD).

May 30Platform

Deployer Hunter: reliable bond detection (MigrateV2 fix)

Fixed: ~75% of pump.fun graduations were being missed. pump.fun renamed its on-chain graduation instruction (Migrate → MigrateV2), and our parser's exact-match guard silently dr…

Platform+

Fixed: ~75% of pump.fun graduations were being missed. pump.fun renamed its on-chain graduation instruction (Migrate → MigrateV2), and our parser's exact-match guard silently dropped every V2 migration — so most "bonded" events never fired. Detection now recognizes Migrate, MigrateV2, and future variants, restoring real-time bonded alerts across webhook, WebSocket, and Telegram. Verified live (a graduation recorded ~1 minute after it landed on-chain).

Authoritative catch-up reconciler. A new 5-minute backstop reconciles recently-deployed tokens against the bonding-curve complete flag on-chain — the single source of truth — recovering any graduation the live gRPC stream missed during reconnects, with zero false positives. Idempotent and silent (no duplicate or stale alerts).

Every graduation now counts, including unknown deployers. Detection is keyed on the graduation itself, not on whether we already track the deployer, so bonds from previously-unseen wallets are now recorded. This corrected lifetime bond stats network-wide and promoted ~390 deployers into tracked tiers (12,207 → 12,596).

May 29Platform

Sniper Alerts now on Pro (curated)

Sniper Alerts come to PRO. The pre-confirm pump.fun deploy feed — previously ULTRA-exclusive — is now available on PRO, curated to elite + good-tier deployers (the high-signal l…

Platform+

Sniper Alerts come to PRO. The pre-confirm pump.fun deploy feed — previously ULTRA-exclusive — is now available on PRO, curated to elite + good-tier deployers (the high-signal launches). ULTRA keeps the full firehose: every deployer tier, the all scope, custom watchlists, and the /v1/sniper/by-deployer/{wallet} audit feed.

The curation runs at delivery time across all three channels (webhook, WebSocket, Telegram), so it applies consistently whether you consume sniper:deploy webhooks, the sniper:deploys WS channel, /alert sniper in Telegram, or the GET /v1/sniper/recent read API. Same ~500-800ms pre-confirm head start on both tiers.

Custom deployer watchlist (ULTRA). New GET/POST /v1/sniper/watchlist + DELETE /v1/sniper/watchlist/{wallet} (up to 50 deployers). Turn on "watchlist" scope to receive deploys from only the deployers you track, regardless of tier — works across the read API (?watchlist=true), webhook + WebSocket (sniper_scope: "watchlist"), and Telegram (/alert sniper watchlist). One source of truth across every channel.

Head-start instrumentation. We now reconcile each deshred detection against the confirmed stream and record confirmed_at on sniper_deploys, giving a measured per-deploy head start (currently ~415ms median / ~518ms p90 in production).

May 28Platform

Sniper Alerts (Ultra): pre-confirm pump.fun deploys

New ULTRA feature. Pre-confirmation pump.fun deploy alerts. New token launches surface in the feed ~500-800ms before they confirm on-chain — measured head start in production ag…

Platform+

New ULTRA feature. Pre-confirmation pump.fun deploy alerts. New token launches surface in the feed ~500-800ms before they confirm on-chain — measured head start in production against our existing CONFIRMED-stream deployer alerts. Delivery on every channel: webhook (sniper:deploy event), WebSocket (sniper:deploys), and Telegram (/alert sniper elite,good). ULTRA-tier exclusive.

Payload. Each alert includes mint, deployer wallet, signature, slot, plus a snapshot of the deployer's reputation (tier, lifetime bond rate, last-10 outcome bitmap). Pre-execution detection — no balances, logs, or compute info in the payload. Honest caveat: ~1-3% of detected deploys can abandon before chain settlement; payloads include confidence: "deshred" so consumers can treat the alert as "buy intent observed", not a guaranteed deploy.

Read API (Ultra). Two new endpoints for backtesting and post-hoc auditing:

  • GET /v1/sniper/recent — paginated deploy feed with filters: since, deployer_tier, min_bond_rate
  • GET /v1/sniper/by-deployer/{wallet} — deploys filtered to a specific deployer wallet

Telegram. New /alert sniper command in @MadeOnSolAlphaBot. Scope options: elite, elite,good, all, or off. ULTRA-tier check enforced at the command level.

Operator playbook. Full sniper guide added to /developer (under the Sniper spotlight card): pre-built tx templates, priority fees + Jito tip sizing, low-latency infra placement, deployer reputation filtering, buy params, exit triggers, and realistic latency budgets. The head start only converts to fills if your stack is set up to execute inside it.

May 26Platform

Bond sweep, hot-token auto-poster, deploy validation, 5 blog posts

Bond detection sweep. mc-tracker now runs a 2-minute periodic sweep that catches PumpSwap graduations the gRPC stream missed. Previously, missed bonds were only detected on mc-t…

Platform+

Bond detection sweep. mc-tracker now runs a 2-minute periodic sweep that catches PumpSwap graduations the gRPC stream missed. Previously, missed bonds were only detected on mc-tracker restart — now max detection delay is 2 minutes. Deployer-listener also enriches missing token metadata from pump.fun API before creating bond alerts.

Hot-token auto-poster. New X post type: every 4 hours, finds the token with the most KOL buyers in the last 30 minutes and posts with full enrichments — live MC, net SOL flow, token age, deployer tier + bond rate, buy/sell sentiment signal, and up to 5 KOL handles tagged. Repeat KOL detection highlights wallets that appeared in the previous hot pick.

Sentiment signals on X posts. Hot-token posts include a plain-language sentiment label based on KOL buy/sell ratio: "Strong accumulation", "Accumulating", "Leaning bullish", "Mixed signals", or "KOLs exiting".

Deploy validation hardened. Zero-downtime deploy script now runs deep checks before swapping nginx: API ping, status endpoint, static assets, and blog content. Failed validation aborts the swap and keeps the old slot running.

Resend webhook improvements. Bounce handler now correctly tracks all bounced addresses. Click tracking enabled for outbound emails.

5 new blog posts. What Is a Solana API, Light Terminal review, gRPC pipeline deep dive, deployer intelligence scoring, signal caller evaluation guide.

New tool. Light Terminal added to directory — social trading terminal with strategy marketplace, creator leaderboard, and automated limit orders on Solana.

May 25Platform

v1.9.0: Price alerts, wallet scanner enrichments, 5 new endpoints

Price Alert System — Sub-second token MC dip/recovery alerts. Set a drop % threshold on any tracked token; get notified via webhook or WebSocket when MC drops below baseline. Op…

Platform+

Price Alert System — Sub-second token MC dip/recovery alerts. Set a drop % threshold on any tracked token; get notified via webhook or WebSocket when MC drops below baseline. Optional recovery tracking fires when MC bounces back. One-shot lifecycle (watching → dipped → recovered), 30-day auto-expiry. PRO: 5 alerts, ULTRA: 25. New API: 6 CRUD + events endpoints. New WS channel: price_alert:events. New TG command: /pricealert.

5 New API Endpoints:

  • GET /kol/scouts/leaderboard — Scout leaderboard: top KOLs ranked by scout score and swarm attraction (ULTRA)
  • GET /tokens/{mint}/kol-consensus — KOL buy/sell consensus on a token with exit rate and median entry MC (PRO+)
  • GET /tokens/{mint}/peak-history — ATH market cap history with MC at bond and post-bond snapshots (PRO+)
  • GET /kol/coordination/history — Historical coordination alert fires (ULTRA)
  • GET /deployer-hunter/{wallet}/trajectory?include=daily_snapshots — Daily tier/bonding snapshots (extended)

Wallet Scanner Enrichments:

  • Win rate, ROI, best/worst trade, AI-classified verdict ("Degen flipper", "Smart money", etc.)
  • Biggest miss: scans all round-trip tokens, calculates missed SOL profit using pump.fun ATH
  • Ticker symbols resolved via pump.fun API (was showing contract addresses)
  • ATH market cap per token from pump.fun (was showing misleading current MC)
  • All enrichments available via REST API (derived block on /wallet/{address}) and Telegram /wallet

SDK v1.9.0 — All 7 packages updated: TypeScript 2.8.0, Rust 0.10.0, x402-TS/Python/MCP/ElizaOS/SAK all 1.9.0.

May 23Platform

Bond detection fix, 7 blog posts, 11 MCP servers, ad placements, new tools

Deployer Hunter bond detection rebuilt. 96%+ of bonds were being missed. New pipeline: mc-tracker emits pg_notify('pumpswap_bond') on graduation → deployer-listener resolves in …

Platform+

Deployer Hunter bond detection rebuilt. 96%+ of bonds were being missed. New pipeline: mc-tracker emits pg_notify('pumpswap_bond') on graduation → deployer-listener resolves in near real-time. Zero extra gRPC bandwidth. 436 historical bonds backfilled.

7 new blog posts. CoinTracking vs CoinLedger vs Blockpit, How to Buy SOL on Binance/MEXC, Bitsgap review, CoinStats review, Chainstack RPC review, Sol Trading Bot review, MEXC vs Binance vs Bybit comparison.

11 new MCP servers added to directory (21 total): Phantom, Vybe Network, Flipside, Jupiter, Crossmint, DexScreener, OpenSVM, Memecoin Observatory, Rug Check, PumpSwap, Magic Eden.

Banner advertising system. 5 ad placements across the site (homepage, /tools, /best/[category], KOL Tracker, Deployer Hunter) with "Your project here" placeholders linking to /advertise. Pricing from $75-$150/mo, manually approved via email.

New tools. Monkey Tools, CoinStats API, NordVPN, Surfshark, ProtonVPN, Cryptohopper added to directory.

Other. Promo banner system (CoinStats 10% off). Wallet scan counter on /wallet. Telegram page redesigned. Re-engagement emails sent to 4 silent PRO subscribers.

May 21Platform

v1.8.1 patch: Wallet Scanner web page + 4 API enrichments + TG `/wallet`

Three additive surfaces shipped on top of yesterday's v1.8.0 wallet endpoints:

Platform+

Three additive surfaces shipped on top of yesterday's v1.8.0 wallet endpoints:

1. Wallet Scanner web page. New /wallet search page under Intelligence in the navbar — paste any Solana address, get the same KOL/Deployer/Alpha flag check plus the new enrichment block in one render. Free, no signup, unlimited scans. The results page (/wallet/{address}) is non-indexed but freely linkable, so the page works as a shareable lookup for tippers, scouts, and the curious.

2. Four API enrichments on /api/v1/wallet/{address}. Additive fields, zero breaking changes:

  • top_tokens[] — most-traded tokens in the 90d window with realized PnL per token, plus current MC and peak MC (cross-joined with deployer_tokens for pump.fun launches).
  • trading_style — average trade size (SOL), sniper rate (% trades placed in the first 10 buyers of a token), round-trip rate (% tokens with both buys and sells), median hold minutes, dominant action.
  • deployer_breakdown — tier distribution of pump.fun deployers this wallet has bought from (ELITE / GOOD / RISING / MODERATE / COLD / unranked). Useful for spotting alpha-buyers vs random degens.
  • recent_trades[] — last 10 trades regardless of window with token symbols joined in.

All four are nullable so old SDK consumers ignoring them keep working. Backed by 4 new STABLE SECURITY DEFINER SQL helpers (migration 150).

3. Telegram /wallet command in @MadeOnSolAlphaBot. Same flag-set, light 7-day stats, deeplink to the web profile. Free 3 scans/day per chat, paid tiers unlimited. Rate-limited via the existing rate_limit_buckets (key tg-wallet:{chat_id}).

SDK propagation: all 7 packages bumped to v1.8.1 with the new response fields in the type definitions. No method-signature changes.

madeonsol                          2.7.0  →  2.7.1   (bare TypeScript)
madeonsol-x402                     1.8.0  →  1.8.1   (npm)
madeonsol-x402                     1.8.0  →  1.8.1   (PyPI)
mcp-server-madeonsol               1.8.0  →  1.8.1
@madeonsol/plugin-madeonsol        1.8.0  →  1.8.1   (Eliza)
solana-agent-kit-plugin-madeonsol  1.8.0  →  1.8.1
madeonsol (crates.io)              0.9.0  →  0.9.1   (Rust)

Bonus: stale middleware redirect /wallet → /best/wallets removed (was from a pre-scanner time when the path didn't exist — 113 GSC impressions that previously went to the listicle now land on the real scanner).

May 20SDK

SDK v1.8.0 release: wallet endpoints in all 7 packages

All 7 official SDKs ship the new Universal Wallet API surface — same shape across TypeScript, Python, Rust, MCP server, ElizaOS plugin, and Solana Agent Kit plugin.

SDK+

All 7 official SDKs ship the new Universal Wallet API surface — same shape across TypeScript, Python, Rust, MCP server, ElizaOS plugin, and Solana Agent Kit plugin.

madeonsol                          2.6.3  →  2.7.0   (bare TypeScript)
madeonsol-x402                     1.7.3  →  1.8.0   (npm)
madeonsol-x402                     1.7.3  →  1.8.0   (PyPI — pip install madeonsol-x402)
mcp-server-madeonsol               1.7.4  →  1.8.0
@madeonsol/plugin-madeonsol        1.7.3  →  1.8.0   (Eliza)
solana-agent-kit-plugin-madeonsol  1.7.3  →  1.8.0
madeonsol (crates.io)              0.8.2  →  0.9.0   (Rust)

Each SDK now exposes 4 new typed methods: wallet.stats(address), wallet.pnl(address), wallet.positions(address), wallet.trades(address, params?) (naming varies slightly per language convention). Full type definitions for every response shape — WalletStats, WalletPnl, WalletOpenPosition, WalletClosedPosition, WalletTrade, etc. — exported from each package so SDK consumers get autocomplete and compile-time validation.

The endpoints themselves shipped separately (see the entry below) — this release is the SDK propagation pass. /api/x402/wallet/* mirrors are wired into the x402 SDKs at the same prices ($0.005 / $0.02 / $0.01 / $0.005). OpenAPI spec bumped to v1.3.0 with full schemas for every wallet endpoint, so downstream code generators stay in sync.

Test status: 221 cases passed / 0 failed across REST matrix (200), WS events (5+6), SDK smoke tests (10), velocity-shape regression guard (7), and the new wallet-endpoint regression suite (17/17 — all filter combinations).

May 20Security

RLS gap closure on 5 internal tables (security)

Audit triggered by an end-of-day "is the DB secured?" check found five tables with row-level security disabled and the Supabase anon role (the public key shipped to every browse…

Security+

Audit triggered by an end-of-day "is the DB secured?" check found five tables with row-level security disabled and the Supabase anon role (the public key shipped to every browser) granted full CRUD via PostgREST: mv_early_buyer_pnl, sniper_wallets_cache, bundler_wallets_cache, token_blacklist, and early_buyer_pnl_refresh_state. Per-wallet realized PnL and the internal moderation blacklist were readable; cache tables and refresh-state were also DELETE/TRUNCATE-able.

Migration 148 enables RLS on all five tables (deny-by-default) and revokes privilege grants as defense in depth. No code changes needed — all endpoints continued working. Regression guard added for future RLS changes.

May 20Platform

Universal wallet endpoints: stats, PnL, positions, paginated trades

Four new Pro/Ultra endpoints under /api/v1/wallet/{address} let you pull profile data for any Solana wallet — not just the 1,058 we curate as KOLs. Same FIFO cost-basis math, sa…

Platform+

Four new Pro/Ultra endpoints under /api/v1/wallet/{address} let you pull profile data for any Solana wallet — not just the 1,058 we curate as KOLs. Same FIFO cost-basis math, same response shape, but the address space is everyone we've seen trade through our DEX firehose (90-day window, ~38 days of historical data right now).

GET /api/v1/wallet/{address} — cheap stats lookup. Returns total_trades, buys/sells split, SOL in/out, unique tokens, first/last seen, plus cross-product flags (is_kol, is_alpha_tracked with bot_confidence + win rate + net PnL, is_deployer with tokens deployed). Backed by a get_wallet_stats() SQL function that reads the existing idx_token_trades_wallet_time — sub-100ms on a wallet with 1,123 trades across 324 tokens. No materialised view, no new ingestion pipeline.

GET /api/v1/wallet/{address}/pnl — full PnL with the same shape as /api/v1/kol/{wallet}/pnl: realized + unrealized SOL, profit factor, avg + median hold minutes, max drawdown, daily PnL curve (UTC), closed positions (sorted by pnl desc) with ROI %, open positions with current price fetched live from our market-cap tracker. Cached in wallet_analyses with dynamic TTL — 5 min for wallets active in the last 24h, 1 hour for 1–7d old, 24 hours for dormant. Cache hits are free against your daily quota.

GET /api/v1/wallet/{address}/positions — open lots only, leaner response for client UIs that don't need the full PnL summary. Shares the /pnl cache so if you've recently called /pnl for this wallet the /positions call is a cache hit immediately.

GET /api/v1/wallet/{address}/trades — paginated raw trades. Cursor-based on (block_time, id) for stable DESC ordering. Filters: action (buy/sell), token_mint, since/until Unix timestamps, limit (1–500, default 100). Response includes next_cursor + has_more.

Honest about the data window. Cost basis is only observable inside the 38-day data window (we started capturing every DEX swap on 2026-04-12). A wallet that bought a token 60 days ago and sells it today gets the sell counted but no matching cost basis — overflow sells are silently discarded rather than inventing a realized PnL number. notes.cost_basis_observable_from in the response surfaces the cutoff so clients can warn users when relevant.

Why this matters for SDK users. Pre-1.8 you could only get rich PnL data for hand-curated KOL wallets. Now any wallet works — feed an address from a Twitter pump screenshot, a deployer's wallet, a trader who DM'd you, and get the same shape back. The four endpoints will land in the next SDK release across all 7 packages.

Suite addition: a new scripts/test-wallet-endpoints.mjs runs as part of /testapi covering every filter combo (action, token_mint, since/until, cursor pagination, limit clamp, invalid inputs, unknown wallets, cache hits). 17/17 green on first prod run.

Heads up if you build on top: open-position counts are bounded by mc-tracker's price coverage — mints without a current price in our cache return unrealized_sol: null rather than a fabricated zero. Same with the new MC clamp shipped earlier today on kol_trades (see below): if mc-tracker's quoted price is 5× the swap-implied rate, the MC and price fields land as null on that trade rather than letting a momentary phantom-pool number poison history.

May 20Platform

KOL trade MC sanity-clamp (no more $57M phantom market caps)

When a KOL trade lands, kol-tracker fetches the current market cap from mc-tracker and writes it into kol_trades.market_cap_usd_at_trade. That value is now sanity-clamped: if mc…

Platform+

When a KOL trade lands, kol-tracker fetches the current market cap from mc-tracker and writes it into kol_trades.market_cap_usd_at_trade. That value is now sanity-clamped: if mc-tracker's quoted per-token price is more than 5× higher than the swap-implied rate (sol_amount / token_amount × sol_usd), the MC and price fields are nulled before writing to the row.

This was triggered by a 2026-05-19 autopost that announced $MC: $72.4K → $57.9M MC — the high-MC number came from two trades where mc-tracker quoted a price 16× and 182× the actual swap rate, briefly during a graduation-moment when a phantom routing wallet became the primary pool. The two bad rows poisoned the 6-hour band-crosser query downstream.

The clamp is inflation-only. Creator-fee PumpSwap tokens where the trader receives ~0.15% of bought tokens have implied price way higher than headline — those are not clamped because the headline is correct, the implied is the distorted one.

Downstream protection: webhook deliveries, WebSocket kol:trade events, the Telegram bot's "@ MC $X" line, copy-trade signal payloads, charts, and the X autopost all read the same market_cap_usd_at_trade column. One clamp at the write boundary protects every consumer.

In the first 5 minutes of running, the clamp fired exactly once on a HENRY token (different mint than the headline-named one) where mc-tracker briefly quoted $0.0087/tok vs implied $0.001/tok (8.4×). The good first-delivery from the redundant multi-region gRPC streams had already inserted the correct row; the clamp on the second delivery was a correct no-op.

May 19Bot

Free Telegram alerts: KOL trades + elite deployer launches

The MadeOnSol Alpha Bot moves from broadcast-only to interactive for the free tier. Previously, free users got the /digest once per day plus on-demand lookups (/token, /wallet, …

Bot+

The MadeOnSol Alpha Bot moves from broadcast-only to interactive for the free tier. Previously, free users got the /digest once per day plus on-demand lookups (/token, /wallet, /deployer) and nothing else — real-time fan-out was paid-only. That made the bot feel like a newsletter and drove a 37% pause rate among linked free users.

/alert kol and /alert deployer are now open to the free tier, with two server-side caps and full user-set filters:

  • /alert kol — up to 30 KOL trades per day matching your own rule. Set your own min_sol threshold (e.g. /alert kol 5 for buys ≥ 5 SOL), scope to a specific KOL (/alert kol "Casino"), token mint, or wallet. Same filter grammar as the paid tiers.
  • /alert deployer elite,good — up to 3 deployer launches per day matching the tiers you picked. All five deployer tiers (elite, good, moderate, rising, cold) are selectable.

Both caps reset at 00:00 UTC. Hit one and the bot silently stops fanning out that rule type for the day — no scary "rate limit" message, just quiet — and resumes after midnight. The user-set filters (min SOL, KOL name, token mint, deployer tier) decide which trades make the cut; the bot doesn't second-guess your taste.

Paid features stay paid. Coordination alerts (/alert coord), copy-trade signals (/alert copytrade), and the wallet tracker (/watch) remain Pro/Ultra. Free users see those submenus but the toggle buttons are gated with a "requires Pro/Ultra" message. The 30/day kol_trade cap is also the main reason to upgrade — Pro removes it entirely.

If you're already linked, /menu → 🚨 Configure alerts → 📊 KOL trades to start. If you don't have a MadeOnSol account yet, madeonsol.com/developer takes about 30 seconds.

May 14Platform

Public `/pricing` page, demo key on `/api-docs`, smarter 429s, lineup trimmed

Five user-facing changes ship together — most of them long-overdue housekeeping around the API funnel.

Platform+

Five user-facing changes ship together — most of them long-overdue housekeeping around the API funnel.

New public /pricing route. Plans, limits, and feature matrix now live on a dedicated marketing page at madeonsol.com/pricing. The /developer page stays focused on its job — signing in, generating + managing keys, managing your subscription. All "see plans / free tier / starts free at…" CTAs across the site, the LLM docs, the Telegram bot, and changelog point at /pricing; action CTAs ("Generate your key", "Manage your subscription") keep pointing at /developer.

Public demo key on /api-docs. The try-it widget on /api-docs is now wired to a public demo key — no signup needed. Capped at 20 req/hr per IP across 3 endpoints (/kol/feed, /deployer-hunter/alerts, /token/{mint}). Validate the response shape in 10 seconds before signing up.

429 responses now carry upgrade info inline. Hitting the daily or burst cap used to return a bare 429 { error: "rate_limit_exceeded" } plus the standard Retry-After header. The body now includes the caller's current tier, the violated limit, the absolute resets_at ISO timestamp, and an upgrade_url pointing at /pricing. SDKs can surface "you're on Free, upgrade to Pro for 50× headroom" without a second /me round-trip. Retry-After is still set on every 429 (seconds-until-reset for daily, seconds-until-burst-window-rolls for burst).

Pro headline sharpened. The Pro tier was previously sold as "Telegram + full v1 API", which understated what it actually unlocks. The new headline across the pricing page, the bot's /upgrade message, the LLM docs, and the SDK READMEs is "Production webhooks + copy-trade signals" — HMAC-signed webhooks, per-rule copy-trade delivery, coordination alerts with custom thresholds, wallet tracker, and the WS streaming surface. The 10k req/day + 120 burst/min limits are still the same — only the framing changes.

Trader tier retired from sale. The $25/mo Trader tier (Telegram-only alerts) is no longer purchasable. Existing Trader subscribers keep their access through the end of their billing period — no forced migration. The lineup is now Free / Pro / Ultra everywhere. References to Trader in marketing surfaces (pricing page, bot upsells, LLM docs, this changelog going forward) are gone; the underlying database tier code and existing Trader subscriber flows are unchanged.

SDK surface sync — docs/marketing-URL patch (no API changes):

madeonsol                          2.6.1  →  2.6.2   (bare TypeScript)
madeonsol-x402                     1.7.1  →  1.7.2   (npm)
madeonsol-x402                     1.7.1  →  1.7.2   (PyPI — pip install madeonsol-x402)
mcp-server-madeonsol               1.7.0  →  1.7.2
@madeonsol/plugin-madeonsol        1.7.0  →  1.7.2   (Eliza)
solana-agent-kit-plugin-madeonsol  1.7.0  →  1.7.2
madeonsol (crates.io)              0.8.0  →  0.8.1   (Rust)

Every README, JSDoc, docstring, tool-description, error message, code-comment, and CLI hint across 30+ files now sends prospects to /pricing (public, free-tier card visible without auth) instead of /developer (login-gated). Action-tone refs ("sign in", "manage your key") still point at /developer. Trader tier dropped from package README tier lists. Rust SDK README ULTRA annual price corrected ($1990 → $1490). No runtime behaviour changes; SDK types unchanged; ApiTier::Trader / "TRADER" union variant retained for grandfathered subscriber rows.

May 13API

Velocity on `/kol/coordination` + SDK velocity-shape patch (1.7.1 / 2.6.1)

Two related changes shipped today.

API+

Two related changes shipped today.

/api/v1/kol/coordination now returns velocity fields alongside every cluster: mc_change_pct, volume_usd, mev_volume_pct (each keyed by 5m/15m/1h/2h/4h) and history_age_seconds. Same shape as /token/{mint} and /copytrade/signals. Lets coordination consumers tell whether a cluster is firing into a moving token or before the move, in one call instead of N follow-up /token/{mint} lookups. Sparse — only windows with enough mc-tracker history are populated.

SDK velocity-shape patch (1.7.1 / 2.6.1): the 1.7.0 / 2.6.0 release shipped TypeScript types and README examples for velocity in a velocity[window].mc_change_pct shape that didn't match the API's actual mc_change_pct[window] shape. Anyone reading client.token.get(...).velocity?.["1h"]?.mc_change_pct was getting undefined. Patched packages:

madeonsol         2.6.0  →  2.6.1   (bare TypeScript)
madeonsol-x402    1.7.0  →  1.7.1   (npm + PyPI)

mcp-server-madeonsol, plugin-madeonsol, solana-agent-kit-plugin (1.7.0) had only generic mentions and stay at 1.7.0. Rust SDK (madeonsol crate, 0.8.0) doesn't surface velocity yet — no patch needed. The fix is type-only; runtime API contract is unchanged.

May 12SDK

Token directory, account self-inspection, smarter 400s (SDK 1.7.0)

Three new API surfaces, two long-deferred cleanups, and a defensive throttle for endpoint probers.

SDK+

Three new API surfaces, two long-deferred cleanups, and a defensive throttle for endpoint probers.

New endpoints:

GET /api/v1/me        → all tiers
GET /api/v1/tokens    → PRO+

GET /api/v1/me reads from the same in-memory counters that drive rate-limit enforcement — quota.daily.remaining is authoritative, no header parsing required. Returns tier, subscription block (status, billing_cycle, current_period_end, started_at), quota.daily (limit/used/remaining/resets_at), quota.burst (limit/used/remaining/window_seconds), and per-feature usage across webhooks, copy-trade wallets/rules, coordination rules, first-touch subscriptions, ws/dex connections, and wallet-tracker watchlist. Useful for self-throttling clients and quota-aware retry logic.

GET /api/v1/tokens is a filtered, sortable directory across every active mint we track — complements the single-mint /token/{mint} and the KOL-scoped /kol/tokens/{hot,trending}. Server-side filters: min_mc, max_mc, min_liq (default 2000 USD — set 0 to disable phantom-MC dust floor), active_h, primary_dex (pumpfun/pumpswap/raydium/meteora/orca/raydium_clmm), authority_revoked, exclude_token2022, min_lp_burnt_pct. Computed post-filters (over-fetches 3× and filters in app): min_volume_1h_usd, max_mev_share_pct, mc_change_1h_min_pct, mc_change_1h_max_pct. Sort: mc_desc / mc_asc / last_trade_desc / liquidity_desc / cumulative_volume_desc. Pagination response includes post_filtered: true so clients can detect when computed filters trim a page below limit.

// Momentum scanner: liquid mints up >20% in 1h, low bot share
const { tokens } = await client.token.list({
  min_liq: 10000,
  min_volume_1h_usd: 5000,
  max_mev_share_pct: 60,
  mc_change_1h_min_pct: 20,
  sort: "mc_desc",
});

Structured 400 on /token/{mint}: invalid mints now ship code: "invalid_mint", reason (specific diagnosis — "too short — got 8 chars, need 32-44", "contains '0' which isn't valid base58", etc.), received, received_length, expected_length, example, and a docs URL. No more trial-and-error.

Velocity / MEV-share fields added to every TokenResponseBody (catching the SDK up to the 2026-05-07 server-side ship): mc_change_pct, volume_usd, mev_volume_pct (each keyed by 5m/15m/1h/2h/4h) plus history_age_seconds on the parent. mev_volume_pct is unique to MadeOnSol — flag wash-pump patterns where headline volume is bot-driven (sandwich/Jito-bundle MEV) rather than organic demand. Note: the 1.7.0 typed shape was wrong (velocity[window] instead of field-keyed) — patched in 1.7.1 / 2.6.1, see entry above.

Per-IP 401 throttle: repeated authentication failures from the same IP now hit a 30-failure/min cap that short-circuits to a 429 with a tiny body — stops endpoint-fishing without DB lookups. Legitimate clients with a typo get 30 retries before the cap fires.

TRADER tier (Telegram) unlocks coordination + copy-trade alerts: the $25/mo Trader tier now includes 1 copy-trade wallet + 1 coordination alert rule, delivered exclusively over Telegram (/alert copytrade <wallet>, /alert coord on). REST/WS/webhook access for those endpoints stays PRO+ — the underlying rules are auto-created on direct DB write when a Trader user opts in via the bot. Default coord thresholds locked at min_kols=5, window=15min, cooldown=30min for Trader; PRO+ keep custom thresholds.

TG bot /start UX: new unlinked users now see one real sample alert appended to the welcome message (no rate-limit hit), the $25/mo price line moved out of the cold open into /upgrade, a "Just /pause anytime to silence" reassurance line was added, and the post-link flow renders a one-tap "🚨 Configure my alerts" keyboard instead of plain text.

Removed: the deprecated avg_entry_mc_usd / entry_mc_samples fields are now fully gone from leaderboard endpoints, SDK types, READMEs, openapi-spec, llms.txt, and MCP tool descriptions. If you were reading them, switch to per-trade market_cap_usd_at_trade (via the v1.6 MC enrichment).

SDK versions published:

madeonsol                          2.5.0  →  2.6.0   (bare TypeScript)
madeonsol-x402                     1.6.0  →  1.7.0   (npm)
madeonsol-x402                     1.6.1  →  1.7.0   (PyPI — pip install madeonsol-x402)
@madeonsol/mcp-server              1.6.0  →  1.7.0
@madeonsol/plugin                  1.6.0  →  1.7.0   (Eliza)
@madeonsol/solana-agent-kit-plugin 1.6.0  →  1.7.0
madeonsol (crates.io)              0.7.0  →  0.8.0   (Rust)

All packages add a me() method (or client.rest.me() in Python) and a tokensList() / token.list() / tokens_list() method, plus expose the velocity/MEV-share fields on token responses. The MCP server gains two new tools: madeonsol_me and madeonsol_tokens_list. The Eliza and Solana-Agent-Kit plugins gain matching meAction and tokensListAction.

May 9SDK

Market-cap filtering everywhere (SDK 1.6.0)

The MC enrichment from the last release now becomes a first-class filter. Every signal surface — REST, WebSocket, per-rule alerts, the Telegram bot — accepts min_mc_usd and max_…

SDK+

The MC enrichment from the last release now becomes a first-class filter. Every signal surface — REST, WebSocket, per-rule alerts, the Telegram bot — accepts min_mc_usd and max_mc_usd so callers can scope every request or every alert rule to a specific market-cap band. "Show me only sub-$50K KOL trades". "Skip every coordination signal on tokens above $5M". "Auto-fire the copy-trade only when the source bought between $100K and $1M MC".

REST API — four endpoints accept the band:

/api/v1/kol/feed?max_mc_usd=50000           → only sub-$50K KOL trades
/api/v1/kol/coordination?min_mc_usd=100000  → skip micro-cap coordination
/api/v1/kol/first-touches?max_mc_usd=200000 → S-tier scout entries below $200K
/api/v1/copytrade/signals?max_mc_usd=500000 → drop signals above $500K

/kol/feed filters at the database layer (uses the existing idx_kol_trades_mc_at_trade partial index). The other three filter post-aggregate on whichever MC concept matches the endpoint — /coordination filters on the cluster's MC at the chronologically-first KOL buy, /first-touches on the at-touch MC, /copytrade/signals on the source trade's MC. Trades with unknown MC drop out when the band is set — the caller asked for a specific range, we don't pretend "unknown" matches.

WebSocket — subscribe-time bands on kol:trades, kol:first_touch, and kol:coordination. The server-side filter drops events that miss the band before pushing — saves bandwidth and lets your bot wake on relevant alpha only.

ws.send(JSON.stringify({
  type: "subscribe",
  channels: ["kol:trades"],
  filters: { min_mc_usd: 10000, max_mc_usd: 250000 },
}));

Per-rule alert tables now carry the band. Three user-rule tables — coordination_alert_rules, copytrade_subscriptions, kol_first_touch_subscriptions — gain min_mc_usd / max_mc_usd columns. The signal-evaluator reads them on every trade and drops triggers that fall outside the rule's band before the alert ever fires. Lets you persist "alert me on KOL coordination, but only on tokens under $50K MC" as the rule itself instead of post-filtering downstream.

Telegram bot — global per-user MC band. New /mc command sets a band that overlays on top of every alert the bot delivers to you, regardless of which underlying rule fired:

/mc 50k-1m   → only alerts on tokens between $50K and $1M MC
/mc -500k    → only alerts on tokens at or below $500K
/mc 200k-    → only alerts on tokens at or above $200K
/mc          → show current band
/mc clear    → remove the band

The outbox poller filters at delivery time using the user's pref. Daily digests (no per-token MC) are unaffected; alerts whose extracted MC is unknown still deliver (we don't penalise missing data on the noise-filter side).

SDKs — bumped:

  • madeonsol (npm, bare) → 2.5.0
  • madeonsol-x402 (npm + PyPI) → 1.6.0
  • mcp-server-madeonsol → 1.6.0
  • @madeonsol/plugin-madeonsol → 1.6.0
  • solana-agent-kit-plugin-madeonsol → 1.6.0
  • madeonsol (Rust crate) → 0.7.0

All min_mc_usd / max_mc_usd params are optional — the SDK call signatures stay backwards-compatible. Param fields also live on the coordinationAlerts.create/update and firstTouchSubscriptions.create/update methods so persistent rules carry the band end-to-end.

Cleanup — avg_entry_mc_usd removed. The deprecated avg_entry_mc_usd and entry_mc_samples fields on /kol/leaderboard and /alpha/leaderboard are gone. They were a 2026-05-06 experiment that the new MC band on requests subsumes — instead of asking for "the avg entry MC for this KOL", filter the trade feed by max_mc_usd and you get the actual sub-set you cared about.

Coverage breadth (since 1.5.0): Moonshot bonding curve indexed in kol-tracker + dex-stream. Meteora CPAMM (DAMM v2) pool state subscription. USD1 added to the recognised quote-mint set. Phantom-pool rejection and a /price/{mint} trades_24h ReferenceError fix on the side.

Ops note: Backup format upgraded for improved restore reliability. No customer-visible change.

May 7API

Velocity deltas + organic/MEV volume on `/api/v1/token/{mint}`

The big one. Every call to /api/v1/token/{mint} now returns a per-window breakdown of how the market cap moved and what kind of volume drove it.

API+

The big one. Every call to /api/v1/token/{mint} now returns a per-window breakdown of how the market cap moved and what kind of volume drove it.

{
  "token": {
    "mint": "...",
    "market_cap": 423000,
    "mc_change_pct": { "5m": 8.2, "15m": 31.4, "1h": 62.1, "2h": 75.0, "4h": 87.0 },
    "volume_usd":     { "5m": 42000, "15m": 118000, "1h": 340000, "2h": 500000, "4h": 920000 },
    "mev_volume_pct": { "5m": 18.4, "15m": 22.1, "1h": 27.3, "2h": 31.8, "4h": 34.2 },
    "history_age_seconds": 14400
  }
}

Window choice. 5m / 15m / 1h / 2h / 4h matches memecoin lifecycle: 5m and 15m for entry timing, the 1h-2h-4h gradient is where pumps separate from fades. We deliberately skipped 6h and 24h because most memecoins don't survive that long — the survivors are a different product surface.

Volume is split into organic and MEV. volume_usd excludes sandwich and Jito-bundle bot churn (mc-tracker tags these per-trade via the existing MEV detector). mev_volume_pct surfaces the MEV share as a separate field so traders can flag wash-pump patterns. A token with volume_usd.4h: 920k and mev_volume_pct.4h: 35% is materially different from the same headline volume at 5%. Nobody else surfaces this.

Reorg-safe. mc-tracker consumes from dex-stream's CONFIRMED-commitment Yellowstone subscription (~1-3s lag from chain head, vs shred's sub-150ms). Cumulative volume counters are stable across reorgs at this commitment depth.

Coverage. Window keys are only present when the token has been tracked long enough — a 1-hour-old token only returns 5m, 15m, and 1h (not 2h or 4h). history_age_seconds reports our in-memory ring's coverage so SDKs can branch cleanly without probing for missing keys.

Heads-up after first deploy. mc-tracker's history ring rebuilds in memory; expect roughly a 4-hour warmup before all windows are populated for tokens that existed before deploy. Subsequent restarts hydrate cumulative counters from the persisted columns and warm up faster (the ring itself is rebuilt from scratch but counters carry).

Backed by migration 129 (18 new columns on token_prices), mc-tracker's new in-memory velocity ring (24-byte tuples per token, sparse, 60s append rate-limit, 4h trim), and a projectMcDeltas helper in mc-enrichment.ts.

Also enriched with the same shape (REST):

  • POST /api/v1/token/batch — same per-mint deltas as the single-mint endpoint, batched up to 50 mints/call.
  • GET /api/v1/copytrade/signals — every signal now carries the source token's current mc_change_pct, volume_usd, mev_volume_pct alongside the existing market_cap_usd_at_trade. Lets copy-trade clients see at a glance whether the signal token is still pumping or already faded.

WebSocket + webhook payloads — every event with a token_mint now carries velocity:

  • mc:update broadcast (consumed by ws-streaming WS subscribers + webhook-worker push customers) now includes mc_change_pct, volume_usd, mev_volume_pct, history_age_seconds. ~300B → ~500B per payload, well under the 7,500B budget.
  • kol:trade — token's velocity context attached at emit time (the trader bought into a token already up 62% in 1h with 18% MEV share, or into a flat token).
  • kol:coordination — cluster trigger token's velocity context.
  • deployer:alert + deployer:bond — the launching token's velocity right at alert time.
  • wallet_tracker:event — tracked-wallet trade target token's velocity context.
  • copytrade:signal — same velocity fields as the REST endpoint, on every fire.

Telegram alerts now render velocity: Every paid TG alert template (KOL trades, deployer launches, deployer bonds, KOL coordination clusters, wallet activity, copy-trade signals) carries one extra line:

📈 +62.1% / 1h · vol $340K · 🤖 18% MEV

The MEV badge only fires when ≥10% of the window's volume is sandwich/bundle activity — that's the signal that a headline pump may be wash-traded rather than organic. Window picked automatically from the most informative one available (1h preferred, falls back to 15m → 5m → 2h → 4h).

May 7Platform

Friendlier 400s on token endpoints, `is_deployer` flag

Two ergonomics fixes driven by 7-day audit-log review.

Platform+

Two ergonomics fixes driven by 7-day audit-log review.

Token endpoints — clearer error on tickers. /api/v1/token/{mint}, /api/v1/tokens/{mint}/buyer-quality, and /api/v1/tokens/{mint}/cap-table now return a richer 400 when the path isn't a base58 mint:

{
  "error": "Invalid token mint address",
  "hint": "Pass a Solana base58 mint address (32-44 chars). Tickers like 'BTC', 'ETH', or 'XRP' aren't supported because they aren't Solana-native assets. For SOL, use the wrapped SOL mint: So11111111111111111111111111111111111111112.",
  "received": "BTC"
}

The audit log showed users hitting /token/SOL, /token/BTC, /token/AAPL, /token/CRO, /token/XRP and burning rate-limit on cryptic 400s. The hint text points them at the wrapped SOL mint and explains why the rest don't have Solana-native equivalents.

/api/v1/deployer-hunter/{wallet} — 404 → 200 with is_deployer: false. Untracked wallets used to return 404 with { "error": "Deployer not found" }. They now return 200 with:

{
  "is_deployer": false,
  "wallet": "<echoed>",
  "deployer": null,
  "pump_stats": null,
  "pump_tokens": [],
  "pump_error": null
}

Backwards compatible — clients checking if (response.deployer) still see falsy. Branch on is_deployer going forward. The change matches user intent: "is this wallet a deployer?" is a feature, not an error.

May 6Platform

Market cap enrichment everywhere

The MC-at-trade-time work that landed yesterday now flows through every signal surface — every paid endpoint, every WebSocket event, every webhook, every Telegram alert, and the…

Platform+

The MC-at-trade-time work that landed yesterday now flows through every signal surface — every paid endpoint, every WebSocket event, every webhook, every Telegram alert, and the leaderboards.

REST endpoints — new fields:

  • GET /api/v1/copytrade/signals — market_cap_usd_at_trade, price_usd_at_trade (joined from the source kol_trades row by tx_signature), plus current market_cap_usd/last_price_usd from token_prices. No more separate /token round-trip after every signal.
  • GET /api/v1/kol/coordination — market_cap_usd_at_first_buy (cap at the cluster's chronologically-first KOL buy) + current market_cap_usd/last_price_usd per token. Distinguishes coordinated accumulation at micro-cap from late-stage chasing.
  • GET /api/v1/kol/alerts/recent — consensus_cluster alerts now match fresh_token_kol_buy's shape: market_cap_usd_at_first_buy + current MC fields.
  • GET /api/v1/kol/first-touches — market_cap_usd_at_first_buy, price_usd_at_first_buy (joined via tx_signature), plus current market_cap_usd/last_price_usd. Lets the scout-tier filter combine with cap band ("S-tier scouts entering at <$50K MC").
  • GET /api/v1/kol/leaderboard — avg_entry_mc_usd + entry_mc_samples per KOL, computed live from buys in the period. Surfaces who's playing micro-cap vs mid-cap.
  • GET /api/v1/alpha/leaderboard — same avg_entry_mc_usd + entry_mc_samples per wallet (null + 0 for non-KOL wallets).
  • GET /api/v1/deployer-hunter/stats — avg_mc_at_alert_usd_30d per tier (elite/good/rising) + sample count. Shows whether elite deployers launch at micro-cap or already-pumped.

WebSocket + webhook payloads — three event types newly carry MC:

  • kol:first_touch (live + replay) — market_cap_usd_at_trade + price_usd_at_trade flow through via the updated record_kol_first_touch Postgres trigger.
  • kol:coordination — triggering_trade.market_cap_usd_at_trade + price_usd_at_trade.
  • copytrade:signal — market_cap_usd_at_trade + price_usd_at_trade on every signal.

Telegram bot — five surfaces newly enriched:

  • copytrade:signal alerts: bought 5 SOL of $TOKEN at $50K MC
  • kol:coordination alerts: Latest in: X (5 SOL at $50K MC) on the triggering trade line
  • /token <mint> adds a current-MC line: 📈 MC $50K · liq $10K · on pumpswap
  • /wallet <addr> shows @ $50K MC on each recent trade
  • /digest top-tokens-by-KOL-interest now includes avg $50K MC per token

Website:

  • KOL leaderboard table: new Avg Entry MC column with sample-count tooltip (micro-cap vs mid-cap trader signal).
  • KOL profile token-PnL table: new Avg Buy MC column.

Pipeline reliability fixes shipped alongside (root causes that dropped accuracy):

  • mc-tracker flushDirty now chunks at 500 rows per tx — eliminated the ~9% flush-failure rate from statement_timeout on large UPSERTs.
  • Eager-fetch hint from kol-tracker: when /mc/<mint> misses for a KOL trade, mc-tracker preemptively fetches mint supply + (if tx_signature provided) synthesizes a swap event from the tx, eliminating the bootstrap-lag window.
  • Bags.app pool support: activity-based authority bypass (liquidity_usd ≥ $5K AND swap_count ≥ 3) admits real Bags pools whose Meteora-wrapped non-PDA authorities previously failed phantom-pool detection.
  • PumpSwap canonical pool-state subscription: Pool state account (245B, owner pAMMBay…) decoded via the official IDL → token.pumpswap_canonical[quote_mint] registry. Pool entries whose pool_address doesn't match the canonical token-vault get flagged is_canonical=false and excluded from primary selection / VWAP / last_price propagation. Closes the creator-fee redirect-treasury contamination class.
  • Multi-hop Jupiter routes (≥2 underlying DEXes in one tx) are now tagged dex=jupiter so mc-tracker's existing jupiter filter rejects them at handleSwap entry — no more phantom router-as-pool entries (the Apple $46M-MC bug class).
  • Stablecoin filter: KOL trades where token_mint ∈ {SOL, USDC, USDT} are dropped before insert — no more "$KOL bought 100 SOL of USDC" noise on the feed.

Tools: SDK packages already at 1.4.0 from yesterday's bump pick up the new fields automatically (untyped-access). A 1.5.0 release with full TS type extensions across all 5 SDKs ships next session.

May 5Bot

Market cap at trade time (KOL feed + WS + TG bot)

Every KOL trade now ships with the token's market cap at the exact moment the swap fired. Sourced live from our in-memory price tracker (the same one that powers /api/v1/token/{…

Bot+

Every KOL trade now ships with the token's market cap at the exact moment the swap fired. Sourced live from our in-memory price tracker (the same one that powers /api/v1/token/{mint}), not from a Dexscreener round-trip — so the number reflects the real cap during a fast-moving wave, not whatever the chart settled at later.

REST: GET /api/v1/kol/feed, GET /api/v1/kol/alerts/recent, GET /api/v1/kol/{wallet} — each trade gains market_cap_usd_at_trade and price_usd_at_trade (USD; nullable for tokens we don't track yet).

WebSocket: the kol:trade event payload includes both fields automatically — ULTRA WS subscribers see them with no client change.

SDKs: bumped — npm madeonsol 2.3.0, madeonsol-x402 1.4.0, @madeonsol/plugin-madeonsol 1.4.0, solana-agent-kit-plugin-madeonsol 1.4.0, mcp-server-madeonsol 1.4.0, PyPI madeonsol-x402 1.4.0, crates.io madeonsol 0.5.0. TypeScript and Rust SDKs surface the new fields as typed optionals; Python passes them through in the response dict.

TG alerts: KOL ALERT messages now read e.g. Goyim bought 5.05 SOL of $WURK at $18K MC, with sells correctly labeled sold.

Storage: persisted on kol_trades (migration 126) so historical "show KOL trades that hit MC < $X" queries work end-to-end. Backfilled trades skip the enrichment to avoid stamping current state on old block_times.

May 3Bot

Telegram bot: 1-tap signup, /menu hub, and 3 free lookup commands

Two days after launch, the bot got a UX pass driven by the friction we watched in production. Fifteen slash commands collapse into a single button hub; the deep-link signup is r…

Bot+

Two days after launch, the bot got a UX pass driven by the friction we watched in production. Fifteen slash commands collapse into a single button hub; the deep-link signup is replaced by a 1-tap Mini App; three new free lookup commands work without an account.

/menu hub (new) — five buttons replace the wall of slash commands: 📊 Discover (lookups + digest), 🚨 Configure alerts (tap-to-toggle, no grammar), 👁 Wallet tracker, 👤 Account (tier, usage, pause/resume), ❓ Help. Power-user CLI commands all still work — they're just hidden from the slash autocomplete.

Free lookup commands (new, no signup) — /token <mint> returns unique KOL buyer count, still-in vs exited split, momentum (buyers in 1h / 15m / 5m), total SOL bought vs sold, deployer tier, and the latest 5 KOL buyers. /wallet <addr> returns KOL identity (name, strategy, X followers) if tracked, plus 7-day buys/sells/unique-tokens, SOL in vs out, and the latest 5 trades. /deployer <addr> returns tier, bond rate, last-10 streak, avg time-to-bond, peak MC of best token, and recent launches with bond status.

1-tap Mini App signup (new) — old flow: visit /developer in a browser → click Connect Telegram → follow the deep link back into the bot → confirm. Three context switches, two browser tabs. New flow: open the bot → tap "Create free account (1 tap)" → sign in via Google or email inside the Telegram Mini App → done. TG chat binds via a signed HMAC token; webview auto-closes via WebApp.close(); works on iOS / Android / desktop. Existing accounts are detected and re-bound on the same screen.

Tap-to-toggle coordination presets — /menu → Configure alerts → 🧬 Coordination now offers 🟢 Strict (5 KOLs / 15 min) · 🟡 Moderate (4 / 10) · 🔴 Aggressive (3 / 5) · 🔇 Off. Persists into coordination_alert_rules under name='tg-bot' so the same rule shows up in the WebSocket subscription.

📤 Share as image — every /token output now ships with a Share-as-image button that posts a 1200×630 PNG (rendered server-side via next/og) with our brand baked in. Drop straight into X, Discord, or your group chat.

Inline confirms for destructive actions — /menu → Account → 🔌 Unlink now morphs into a Yes / Cancel inline keyboard instead of asking the user to type /unlink. One tap to ask, one tap to confirm.

Slim slash-menu — BOT_COMMANDS registered with Telegram trimmed to 6: start, menu, digest, sample, upgrade, help. Everything else still works when typed manually.

Alpha-wallet bot detection improved (migration 124) — mv_alpha_wallets.bot_confidence now flags as high when tokens-per-active-hour > 5, when win rate ≥ 1.0 over ≥10 samples, or when the burner pattern (>10 tokens in under 6 active hours) is met. Filters out the obvious bot 100%-winrate wallets from the homepage scout list.

Landing page refresh: the Telegram landing page (since removed) led with the free commands and the 1-tap onboarding. Pricing on /solana-api updated to reflect the free lookups in the BASIC tier and the tap-to-toggle config in the TRADER tier.

May 2Bot

MadeOnSol Alpha Bot: real-time alerts in Telegram

Five live alert streams pushed to your Telegram DM in under 2 seconds end-to-end: KOL trades, Pump.fun deployer launches and bonds, KOL coordination clusters, copy-trade signals…

Bot+

Five live alert streams pushed to your Telegram DM in under 2 seconds end-to-end: KOL trades, Pump.fun deployer launches and bonds, KOL coordination clusters, copy-trade signals, and wallet-tracker events. Same pg_notify pipeline our WebSocket customers already use — Telegram is just another delivery target.

@MadeOnSolAlphaBot (new) — open the bot, run /digest for top tokens & scouts (last 24h), or /sample for one delayed real alert. Both work free, no signup. Connect your account at /developer → "Connect Telegram" to enable real-time delivery.

/alert grammar — /alert kol N (catch-all min SOL), /alert kol "Casino" 1 (per-KOL), /alert kol mint <mint> 1 (per-token), /alert kol wallet <addr> 1 (per-wallet), /alert deployer elite,good, /alert tracker on, /alert copytrade on, /alert coord on. Append off to disable any rule. /rules lists everything active, /delete <id> removes one.

Alert enrichment — every KOL alert ships with the trader's 7-day win rate; deployer alerts ship with the full track record (lifetime bond rate, last-10 outcome streaks, avg time-to-bond, peak market cap of the deployer's best token); coordination alerts ship with score 0-100, cluster avg win rate, exited count, and top 5 names.

Group mode (Ultra) — add the bot to a Telegram group, link from an Ultra account (/start link_<token> in the group), alerts broadcast to everyone in the chat. Per-chat rate gate auto-throttles to Telegram's 20 msg/min group cap.

Pricing: free /digest + 1 daily /sample for everyone; Trader $25/mo unlocks real-time KOL + deployer alerts; Pro / Ultra add copy-trade, coordination, wallet tracker, group-mode broadcasting.

Three bot tokens already provisioned (@MadeOnSolAlphaBot, @MadeOnSolAlpha2Bot, @MadeOnSolAlpha3Bot) — single bot today, sharded fan-out kicks in at 3k+ users. Outbox delivery uses FOR UPDATE SKIP LOCKED row claiming, per-chat 1msg/sec gate, global 25/sec token bucket. Daily /digest cron + 7d tg_outbox retention sweep run via pg_cron.

Landing page: /telegram (since removed). Docs: /help inside the bot.

April 2026

20 ships
Apr 26Platform

Scout signal: first-KOL-touch as a queryable + pushable feed

New product surface for tracking the moment a tracked KOL first buys a token — backtested as a meaningful leading indicator of multi-KOL coordination. 38d / 491k buys / 72,549 e…

Platform+

New product surface for tracking the moment a tracked KOL first buys a token — backtested as a meaningful leading indicator of multi-KOL coordination. 38d / 491k buys / 72,549 events analyzed; conditioning on top scouts (S-tier) lifts ≥3-follower hit rate from ~14% baseline to ~50%.

GET /api/v1/kol/first-touches (new) — every first KOL buy, filterable by min_scout_tier (S/A/B/C), min_kol_winrate_7d, min_n_touches, strategy, token_age_max_min, min_first_buy_sol, mint_suffix, plus since / before cursors. preset=scout and preset=fresh_launch shortcuts apply curated filter sets. include=followers_4h attaches retrospective follower counts for events ≥4h old. ULTRA gets the KOL wallet field; PRO/BASIC get name + scout context.

WebSocket kol:first_touches (new) — sub-second push on the same channel infrastructure as kol:coordination. Filterable at subscribe time on min_scout_tier, mint_suffix, min_first_buy_sol, kol, min_n_touches. PRO + ULTRA. Median lead time before the second KOL is 12 seconds, so the WS surface is the only one fast enough for automated trading.

POST /api/v1/kol/first-touches/subscriptions (new, ULTRA) — webhook delivery with HMAC-SHA256 signing. Up to 10 per-rule subscriptions with independent filter sets. Mirrors coordination/alerts.

mv_kol_scout_score materialized view — per-KOL aggregate over a rolling 30d window: n_first_touches_30d, avg_followers_4h, swarm_3plus_pct, swarm_5plus_pct, scout_tier. Refreshes hourly via pg_cron with advisory-lock guard. Stable across non-overlapping halves at n≥30 (Pearson r=0.78).

Public scout leaderboard at /kol/scouts — sortable table of top scouts with per-scout detail at /kol/scouts/[wallet] showing recent first-touches and follower outcomes.

SDKs: madeonsol-x402 (npm) → 1.3.1, madeonsol-x402 (PyPI) → 1.3.1, @madeonsol/plugin-madeonsol → 1.3.1, mcp-server-madeonsol → 1.3.1, and solana-agent-kit-plugin-madeonsol → 1.3.1 all expose firstTouches() plus firstTouchSubscriptions{List,Create,Get,Update,Delete} (Ultra). Bare madeonsol (npm) and the Rust SDK on crates.io ship in a follow-up release.

Apr 25Platform

Push-delivery observability: WS sessions + admin dashboards

Resolved a silent-failure mode that turned up on 2026-04-23: a PRO user (1ff470bd…) had 2,310 copy-trade signals fire over a week with 0 delivered — their WebSocket had been dis…

Platform+

Resolved a silent-failure mode that turned up on 2026-04-23: a PRO user (1ff470bd…) had 2,310 copy-trade signals fire over a week with 0 delivered — their WebSocket had been disconnected for days and no surface flagged it. Customers can't tell the difference between "no alpha to deliver" and "delivery is broken", so we built one.

  • ws_sessions table (migration 110) — every WS connect/disconnect on ws-streaming and dex-stream writes a row with user_id, tier, channels[], connected_at / disconnected_at, close_code, close_reason, messages_sent, remote_ip. 60-day retention.
  • coordination_alert_signals table (migration 111) — per-fire history for kol:coordination, parallel to copytrade_signals. Tracks delivered, delivered_at, delivery_error per dispatch (was previously fire-and-forget).
  • Admin push-delivery breakdowns (migration 112 + /admin/api) — three new SECURITY DEFINER functions (admin_copytrade_delivery_breakdown, admin_coord_delivery_breakdown, admin_first_touch_delivery_breakdown) bucket fires by failure mode (ws_not_connected / ws_not_subscribed / webhook_err / no_status / delivered). The /admin/api page now shows per-customer delivery health with at-a-glance churn vs. broken-pipe distinction.

No customer-visible API changes — purely operational visibility.

Apr 24Infra

Cron perf: incremental bundler/sniper cache refresh

refresh_bundler_sniper_caches() (introduced in migration 105) was full-scanning token_early_buyers on every run. Once that table crossed ~1M rows, the cron job started timing ou…

Infra+

refresh_bundler_sniper_caches() (introduced in migration 105) was full-scanning token_early_buyers on every run. Once that table crossed ~1M rows, the cron job started timing out at 60s — both the 2026-04-20 and 2026-04-21 runs failed silently.

Migration 109 rewrites the function to be incremental:

  • Watermark column on early_buyer_pnl_refresh_state tracks the max block_time covered by the last refresh.
  • Bundler cache — append-only by definition (a wallet that did a same-block multi-token buy stays flagged), so we only scan buys in new blocks.
  • Sniper cache — must handle additions and removals (a fresh slow-sell can drop a wallet's quick-flip ratio below 0.8). Builds a candidate set of wallets with new early-buy rows or new sells, recomputes qualification across each candidate's full history, then upserts/deletes against the cache.
  • First-run path preserved as a one-time bootstrap with elevated statement_timeout and work_mem.

Post-fix: cron runs in 2–4s instead of timing out. New index idx_early_buyers_first_buy_at supports the candidate-discovery query.

Apr 23API

Top-6 endpoint improvements + batch lookups

Audit of 30d api_audit_log surfaced concrete gaps on the most-used paid routes — missing filters, silent response bugs, no batch support. High-priority fixes shipped together:

API+

Audit of 30d api_audit_log surfaced concrete gaps on the most-used paid routes — missing filters, silent response bugs, no batch support. High-priority fixes shipped together:

/kol/feed — token_image_url now returned (was selected in the query but dropped from the mapped response — silent bug; UI consumers were missing token icons). Added ?before=<ISO> cursor pagination with next_before so polling clients stop re-fetching the same top rows.

/token/{mint} — enriched with first_seen_at, age_seconds, is_blacklisted, and blacklist_category (stablecoin / wrapped_sol / lst / rug). Joins against token_first_seen + token_blacklist, saving consumers a follow-up call.

POST /token/batch (new) — bulk lookup of up to 50 mints in one request. Same per-mint shape as GET /token/{mint}. Cuts request volume 10–20× for sniper workflows that previously polled per-mint.

POST /tokens/batch/buyer-quality (new) — bulk buyer-quality scoring for up to 50 mints. Shares the LRU cache with the single-mint endpoint — repeat calls return cache_hits=N at near-zero cost.

/deployer-hunter/alerts — new filters: ?min_kol_buys=N, ?alert_type=, ?priority=high|medium|low. ?before=<ISO> cursor pagination (was only offset-paginated). Joined deployer payload now includes best_token_peak_mc.

/deployer-hunter/recent-bonds — ?since=<ISO> for incremental polling + next_since cursor (without it, every poll re-returned the same rows). Added ?tier=, ?peak_mc_min=, and token_image_url in the response.

All additions backward-compatible. /api-docs, /solana-api, openapi-spec, and llms.txt updated to match. Filter matrix verified 30/30 on the green slot before deploy.

Apr 23SDK

SDK refresh: filters + batch routes across all 7 SDKs

Mirrored the new endpoint surface into every official SDK so consumers can call the new filters and batch routes through typed methods.

SDK+

Mirrored the new endpoint surface into every official SDK so consumers can call the new filters and batch routes through typed methods.

  • madeonsol (TypeScript) → 2.1.0 (npm) — kol.feed() before cursor + next_before, KolTrade.token_image_url. deployer.alerts() before / alert_type / priority / min_kol_buys. deployer.recentBonds() since / tier / peak_mc_min + next_since. New client.token namespace: get(), batch(), batchBuyerQuality().
  • madeonsol (Rust) → 0.3.0 (crates.io) — same additions on types.rs + api/{kol,deployer}.rs; new api/token.rs with Token::{get, batch, batch_buyer_quality} registered as client.token.
  • mcp-server-madeonsol → 1.2.1 — three new MCP tools (madeonsol_token_get, madeonsol_token_batch, madeonsol_tokens_batch_buyer_quality) + new filter params on madeonsol_kol_feed and madeonsol_deployer_alerts. Strategy enum corrected to scalper / day_trader / swing_trader / hodler / mixed (matches the live mv_kol_scores classifier).
  • @madeonsol/plugin-madeonsol → 1.2.0 — getToken, getTokenBatch, getTokenBuyerQualityBatch + new filter args. Bug fixes: getAlphaLinked now hits /alpha/{w}/linked (was 404'ing on /alpha/wallet/{w}/linked); getTokenCapTable + getTokenBuyerQuality now use plural /tokens/ paths.
  • solana-agent-kit-plugin-madeonsol → 1.2.0 — same additions + same path-bug fixes on alphaWallet, alphaLinked, tokenCapTable, tokenBuyerQuality. New tokenGet, tokenBatch, tokenBuyerQualityBatch functions.
  • madeonsol-x402 (npm) → 1.2.0 — KolFeedParams.before, DeployerAlertsParams.{before, alert_type, priority, min_kol_buys}, next_before in response, strategy enum corrected.
  • madeonsol-x402 (PyPI) → 1.2.0 — kol_feed(before=...) and deployer_alerts(before=, alert_type=, priority=, min_kol_buys=).

All changes backward-compatible — new params are optional, new fields are additive, new methods don't change existing signatures. Existing consumers continue to work without modification.

Apr 23Infra

gRPC stream teardown fix + dex-stream always-on

@triton-one/yellowstone-grpc moved to a native N-API client where ClientDuplexStream extends stream.Duplex and has no .cancel() method, so every reconnect path was silently no-o…

Infra+

@triton-one/yellowstone-grpc moved to a native N-API client where ClientDuplexStream extends stream.Duplex and has no .cancel() method, so every reconnect path was silently no-op'ing on teardown, leaving the subscription + TCP socket dangling. wallet-tracker (which reconnects on every wallet_watchlist_changes pg_notify) had accumulated 97 sockets to Kaldera, saturating the per-account limit and causing dex-stream subscribe attempts to be rejected with GenericFailure.

  • Replaced state.stream.cancel() → state.stream.destroy() across all 15 call sites in wallet-tracker, kol-tracker, dex-stream, and deployer-listener.
  • dex-stream no longer auto-shuts when no client is subscribed — rapid subscribe/unsubscribe churn was tripping Kaldera anti-abuse for extended windows. Now matches kol-tracker's always-on pattern, so the all-DEX firehose is ready the moment a ULTRA client connects.
  • Tightened pg pool idleTimeoutMillis (30s → 10s) and tagged application_name across the three gRPC services for cleaner DB-side observability.

Post-fix, wallet-tracker dropped from 97 → 4 sockets and dex-stream subscribes cleanly to both gRPC regions (~15k tx per 30s heartbeat).

Apr 23Infra

Dependency refresh (`@supabase/ssr` 0.9 → 0.10.2)

Routine semver-patch sweep: 17 npm packages updated (Next 16.2.4, React 19.2.5, @supabase/supabase-js 2.104.1, Tailwind 4.2.4, @x402/* 2.10.0, Resend 6.12.2, Vitest 4.1.5, other…

Infra+

Routine semver-patch sweep: 17 npm packages updated (Next 16.2.4, React 19.2.5, @supabase/supabase-js 2.104.1, Tailwind 4.2.4, @x402/* 2.10.0, Resend 6.12.2, Vitest 4.1.5, others). Plus one one-major bump worth flagging:

@supabase/ssr 0.9.0 → 0.10.2 — v0.10 propagates cache headers to setAll to prevent CDN caching of auth responses, and now respects user-provided auth options in createBrowserClient. No API signature changes — middleware.ts, supabase/client.ts, supabase/server.ts compile unchanged.

@solana/kit 5.5 → 6.8 deferred: would dedupe-invalidate against @x402/svm → @solana-program/[email protected] which peer-requires @solana/kit@^5. Risk of runtime break in the x402 subscription payment path; waiting for upstream compute-budget v6 support.

Apr 22SDK

Broken-link redirect + SDK error-message cleanup

Site

SDK+

Site

  • Added middleware rule that strips trailing ), )., ,, ;, ] from paths and 301-redirects. Rescues clicks from auto-linkified URLs in emails, terminals, and IDE tooltips that over-greedy grabbed trailing punctuation (affected /developer), /developer). among others).

SDKs — all x402 / ElizaOS variants

  • @madeonsol/plugin-madeonsol → 1.1.2 (npm)
  • madeonsol-x402 (npm) → 1.1.2 (npm)
  • madeonsol-x402 (PyPI) → 1.1.3 (PyPI)

Reworded every (free at madeonsol.com/developer) pattern in error messages, JSDoc, and docstrings to an em-dashed form — — free at https://madeonsol.com/developer — — so no terminal or email auto-linkifier grabs a trailing paren. No behaviour or API changes.

Apr 21SDK

Rust SDK launch + TypeScript SDK correctness fix

New: Official Rust SDK (crates.io)

SDK+

New: Official Rust SDK (crates.io)

cargo add madeonsol

Full-surface async client built on tokio + reqwest with rustls — no OpenSSL dependency, cross-compiles cleanly. Covers the same endpoint set as the TypeScript SDK: KOL feed/leaderboard/coordination/pairs/hot/trending/entry-order/timing/pnl, deployer alerts and leaderboards, wallet tracker, alpha wallet intelligence, and x402 discovery. Typed response structs, structured error surfacing, and the same msk_ Bearer auth as every other SDK.

TypeScript SDK v2.0.0 (npm) — correctness release

The major bump is a breaking response-type realignment:

  • KolTrade.signature → tx_signature (and sibling fields on DeployerAlert, WalletEvent, coordination wallet rows) — now matches the actual REST payload. Previous versions had drifted from the live API shape.
  • MadeOnSolError.message now surfaces the server's error field from the response body instead of the generic HTTP status text — real diagnostics in catch blocks.
  • Response types across KOL, deployer, wallet, and alpha endpoints audited against the live API and corrected.

Upgrade: npm install madeonsol@latest. If you were reading signature off trade objects, rename to tx_signature. No other call-site changes.

Apr 20API

Coordination v1.1: peak-density, exits, push alerts

The /kol/coordination endpoint got three upgrades and a new companion API for real-time push alerts.

API+

The /kol/coordination endpoint got three upgrades and a new companion API for real-time push alerts.

Richer response (backward-compatible)

  • Peak-density window: response now includes peak_window_start, peak_window_end, peak_kols, peak_buys — the densest window_minutes slice inside the full period. A cluster where 8 KOLs bought across 4 hours is very different from one where 8 KOLs bought in a 15-minute window. Now you can tell.
  • Exits: exited_count flags KOLs that net-sold the token after buying — a quiet but strong de-weight signal for copy-trading.
  • Coordination score: coordination_score (0-100) is a composite over peak density, freshness, exits, avg winrate, and strategy diversity. Use ?min_score=70 to filter for only high-conviction clusters.
  • New filters: ?window_minutes=1-60 (default 15), ?min_score=0-100 (default 60), ?include_majors=true|false (filter WIF/BONK/POPCAT noise, default false).
  • Majors are blacklisted via the coordination_excluded_mints table — contact us if you want a specific mint added.

New: Coordination Alerts API (PRO/ULTRA — 5 endpoints)

Push alerts fire within ~1s of a qualifying trade (pg_notify, not cron-poll). Delivered via WebSocket (kol:coordination, user-scoped) and/or per-rule HMAC-signed webhook.

POST   /api/v1/kol/coordination/alerts
GET    /api/v1/kol/coordination/alerts
GET    /api/v1/kol/coordination/alerts/{id}
PATCH  /api/v1/kol/coordination/alerts/{id}
DELETE /api/v1/kol/coordination/alerts/{id}

Rule fields: name, min_kols (2-50), window_minutes, min_score, include_majors, cooldown_min (60 default — de-dupe per (rule, token)), score_jump_break (10 default — re-fire inside cooldown if score jumps by N), delivery_mode (webhook / websocket / both), webhook_url. Webhook secret returned once on create — store it securely.

Limits: PRO 5 rules. ULTRA 20 rules.

SDKs

All six SDKs (TypeScript 1.11.0, Python 1.1.0, MCP 1.1.0, ElizaOS 1.1.0, Solana Agent Kit 1.1.0, madeonsol-x402 TS 1.1.0) expose the new fields on kolCoordination() and add coordinationAlerts{List,Create,Get,Update,Delete}.

Full surface on /api-docs#kol.

Apr 18API

Rate limit headers, live stats, SDK refresh

API

API+

API

  • Every response now returns X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset, and X-Request-Id. Useful for client-side backoff and for support — paste the X-Request-Id in any bug report and we can trace it end-to-end.
  • Error envelopes now include a _rid watermark for the same reason.

SDKs

  • All six SDKs (TypeScript, Python, MCP, ElizaOS, Solana Agent Kit, LangChain) now support KOL entry-order queries, wallet compare, and alerts/recent.

Site

  • Live platform stats on the homepage, /developer, and /solana-api — pulled from the public stats endpoint and cached for 5 minutes.
Apr 18API

KOL API v2

New mv_kol_scores materialized view backs the entire KOL surface. Three net-new endpoints, five enriched.

API+

New mv_kol_scores materialized view backs the entire KOL surface. Three net-new endpoints, five enriched.

  • GET /kol/coordination — multi-KOL convergence signals with cluster avg winrate + distinct-strategy filters (PRO+).
  • GET /kol/hot — trending KOLs by recent momentum.
  • GET /kol/compare — side-by-side stats for up to 10 wallets.
  • GET /kol/leaderboard now supports sort=pnl|winrate|profit_factor|roi|early_entry (PRO+) and a strategy filter.
  • GET /kol/{wallet} adds include=pnl_by_token (PRO/ULTRA).

Trade retention extended to 180 days across all KOL endpoints. Full surface on /api-docs#kol.

Apr 16API

DEX Firehose v2

wss://ws.madeonsol.com/dex (ULTRA-only) now supports:

API+

wss://ws.madeonsol.com/dex (ULTRA-only) now supports:

  • Multi-subscription: subscribe to multiple filter sets over a single connection.
  • Replay: request the last N seconds on reconnect to bridge any gap.
  • Server-side filters: min_sol, token_age_max_min, min_market_cap, min_kol_tier.
  • Alt gRPC endpoint: redundant stream on a second provider for failover.

Catches roughly every swap on every major Solana DEX with sub-second latency. See DEX stream docs.

Apr 16API

Webhook signatures v2

Webhook deliveries now sign <timestamp>.<body> with HMAC-SHA256 under the X-MadeOnSol-Signature header, and include X-MadeOnSol-Timestamp. Reject any delivery older than ~5 minu…

API+

Webhook deliveries now sign <timestamp>.<body> with HMAC-SHA256 under the X-MadeOnSol-Signature header, and include X-MadeOnSol-Timestamp. Reject any delivery older than ~5 minutes to defeat replay. v1 signatures keep working during the transition. Verify examples in the webhooks docs.

Apr 16Security

Security audit pass

Security+
  • XSS + SSRF hardening across all user-supplied URL inputs.
  • Scheme whitelist (http: / https: only) on every outbound fetch.
  • Input size caps + NaN guards on all numeric query params.
  • RLS enabled on all sensitive tables.
  • Tightened access on public-facing routes.
Apr 15Platform

Navbar refresh

Platform+
  • API dropdown got bordered cards for scannability.
  • The "API" section is now labelled Solana API end-to-end — the product covers the entire Solana data stack, not just MadeOnSol-specific data.
Apr 15API

v0.7.0: Wallet Tracker API

Powers the new /developer dashboard wallet panel. Full reference on /api-docs#wallet-tracker.

API+
  • POST /wallet-tracker/watch — add any Solana wallet to your watchlist.
  • GET /wallet-tracker/summary — aggregate stats for your tracked wallets.
  • GET /wallet-tracker/trades — unified recent swaps + transfers feed.
  • BASIC: 10 wallets. PRO: 50. ULTRA: 100 + live WS events.

Powers the new /developer dashboard wallet panel. Full reference on /api-docs#wallet-tracker.

Apr 14API

v0.6.0: Alpha wallet intelligence

API+
  • New human_wallets signal separates organic traders from bundle/sniper bots using our mv_alpha_wallets bot-confidence classifier.
  • Buyer quality scoring revamped: base score = avg 7d winrate of non-bot buyers with ≥3 tokens, + KOL bonuses, − bundle/bot penalties.
  • GET /tokens/{mint}/buyer-quality and GET /tokens/{mint}/cap-table now return richer breakdowns (PRO+).
  • Homepage refreshed to lead with real numbers instead of copy.
Apr 10API

v0.5.0: KOL PnL + trending tokens

API+
  • GET /kol/{wallet} — full KOL wallet profile with PnL stats and trade history.
  • GET /tokens/trending — tokens gaining KOL attention right now.
  • First version of /api-docs, llms.txt, and an OpenAPI spec for AI agents.
Apr 7Infra

Nginx buffer autofix

Production 502 outage traced to proxy_buffer_size too small for large PostgREST responses on mv_kol_scores. Fix: the health-monitor cron now automatically bumps proxy_buffer_siz…

Infra+

Production 502 outage traced to proxy_buffer_size too small for large PostgREST responses on mv_kol_scores. Fix: the health-monitor cron now automatically bumps proxy_buffer_size (capped at 128k) when it detects "upstream sent too big header" in nginx error logs, reloads nginx, and posts to system_health_checks.

Keep exploring

Read the docs. Get a key. Ship the bot.

API reference Get free API keyPricingStatus