The MadeOnSol API gives you programmatic access to datasets that are hard to build yourself: Solana KOL trades from 1,100+ active tracked wallets, reputation profiles for 85K+ Pump.fun deployers (1.2M+ deployer wallets indexed), token/wallet intelligence, and the wider MadeOnSol tool directory. The madeonsol TypeScript SDK wraps all of it in a typed client you can install from npm.
This tutorial covers three practical use cases: a KOL trade alert bot, a deployer reputation checker, and a multi-KOL convergence scanner. Each one is a standalone script you can run today.
Prerequisites
- Node.js 18+ and TypeScript
- A MadeOnSol API key (the Free plan gives you 200 calls/day, no payment required; Use Case 3 needs Pro)
- Basic familiarity with async/await
Installation and Setup
Install the SDK:
npm install madeonsol
Create a .env file:
MADEONSOL_API_KEY=msk_your_api_key_here
Initialize the client:
import { MadeOnSol } from "madeonsol";
const client = new MadeOnSol({
apiKey: process.env.MADEONSOL_API_KEY!,
});
See pricing at madeonsol.com/pricing, generate a free msk_ key, and copy it into your .env. You get 200 requests per day at no cost, enough to prototype the first two examples below. The convergence scanner in Use Case 3 calls the KOL coordination endpoint, which needs a Pro plan or higher. The SDK auto-detects the msk_ prefix and authenticates directly with MadeOnSol's REST API using a Bearer token. Prefer to generate your own client instead of using the SDK? Our walkthrough on scaffolding a typed TypeScript client from any Solana API's OpenAPI spec shows the codegen route.
Use Case 1: KOL Trade Alert Bot
The Solana KOL Tracker monitors 1,100+ active wallets. Paid API keys receive the live feed; the Free/BASIC feed is intentionally delayed by 5 minutes. You can poll the feed endpoint to get the latest buys and sells, then filter for the trades that matter to you.
Here is a complete script that polls for large KOL buys every 30 seconds and logs them:
import { MadeOnSol } from "madeonsol";
const client = new MadeOnSol({ apiKey: process.env.MADEONSOL_API_KEY! });
async function pollKolBuys() {
const { trades } = await client.kol.feed({ limit: 10, action: "buy" });
for (const trade of trades) {
if (trade.sol_amount > 5) {
console.log(
`${trade.kol_name} bought $${trade.token_symbol} for ${trade.sol_amount} SOL`
);
// Send to Telegram, Discord, etc.
}
}
}
// Poll every 30 seconds
setInterval(pollKolBuys, 30_000);
// Run immediately on start
pollKolBuys();
What You Can Do With This
- Telegram alerts: Pipe the output to a Telegram bot using
node-telegram-bot-api. Filter by SOL amount, specific KOL names, or token age.
- Discord webhooks: POST formatted embeds to a Discord channel whenever a trade matches your criteria.
- CSV logging: Append trades to a file for later analysis — track which KOLs have the best hit rate over time.
Rate Limit Considerations
At 30-second intervals, this script uses about 2,880 calls per day. The Free plan caps at 200 requests/day, so you will need a paid plan for continuous polling. On Free the KOL feed is also delayed 5 minutes, so alerts arrive at least 5 minutes after the trade; Pro and up are real-time. For testing, increase the interval to 5 minutes (300,000ms) to stay within the Free plan's daily limit.
Use Case 2: Deployer Reputation Checker
Before buying a newly launched Pump.fun token, you want to know whether the deployer has a track record of creating tokens that actually bond and migrate to PumpSwap — or whether they are a serial rugger. The Deployer Hunter endpoint gives you exactly that.
import { MadeOnSol } from "madeonsol";
const client = new MadeOnSol({ apiKey: process.env.MADEONSOL_API_KEY! });
async function checkDeployer(wallet: string) {
const { deployer } = await client.deployer.profile(wallet);
console.log(`Tier: ${deployer.tier}`);
console.log(`Bond rate: ${(deployer.bonding_rate * 100).toFixed(1)}%`);
console.log(`Total deployed: ${deployer.total_tokens_deployed}`);
console.log(`Total bonded: ${deployer.total_bonded}`);
if (deployer.tier === "elite" || deployer.tier === "good") {
console.log("This deployer has a solid track record");
} else {
console.log("Proceed with caution");
}
}
// Example: check a deployer wallet
checkDeployer("7xKXtg2CW87d97TXJSDpbD5jBkheTqA83TZRuJosgAsU");
Understanding the Tiers
The API categorizes deployers into tiers based on their bonding rate (percentage of tokens that successfully bond and graduate to PumpSwap) and total deployment count:
- Elite: 5+ launches, 5+ bonds, at least 40% lifetime bonding rate and at least 50% recent rate.
- Good: 3+ launches, 3+ bonds, at least 25% lifetime rate and at least 30% recent rate.
- Moderate: 3+ launches, at least 1 bond, and at least 15% lifetime and recent rate.
- Rising / cold / unranked: additional states capture short positive histories, recent zero-bond streaks, or insufficient history. Treat the tier as evidence, not a guarantee.
Building a Screening Pipeline
You can combine this with on-chain monitoring to build an automated screening pipeline:
async function screenNewToken(deployerWallet: string, tokenMint: string) {
const { deployer } = await client.deployer.profile(deployerWallet);
const score = {
tier: deployer.tier,
bondRate: deployer.bonding_rate,
totalDeployed: deployer.total_tokens_deployed,
pass: deployer.tier === "elite" || deployer.tier === "good",
};
if (score.pass) {
console.log(`Token ${tokenMint} passed deployer check — consider buying`);
} else {
console.log(`Token ${tokenMint} failed deployer check — skipping`);
}
return score;
}
This is one API call per token. At 200 free calls per day, you can screen 200 new launches — more than enough for manual review workflows.
Use Case 3: Multi-KOL Convergence Scanner
When multiple KOLs buy the same token within a short window, it can signal genuine interest rather than a single influencer pumping their bags. The coordination endpoint surfaces exactly these patterns. It needs a Pro plan or higher: a Free key gets 403 tier_required.
import { MadeOnSol } from "madeonsol";
const client = new MadeOnSol({ apiKey: process.env.MADEONSOL_API_KEY! });
async function findConvergence() {
const { tokens } = await client.kol.coordination({
period: "24h",
min_kols: 3,
});
for (const token of tokens) {
const direction = token.net_flow > 0 ? "accumulating" : "distributing";
console.log(
`${token.token_symbol}: ${token.kol_count} KOLs, net flow: ${direction}`
);
}
}
findConvergence();
Interpreting the Results
- kol_count: How many distinct KOL wallets traded this token in the period.
- net_flow: Positive means more SOL flowed in (buys outweigh sells). Negative means KOLs are exiting.
- period: Use
"1h", "6h", "24h", or "7d".
A denser cluster over a shorter window can be more informative than the same count spread across a day, but the coordination score and underlying wallets matter more than a universal threshold. Combine this with deployer checks and your own on-chain analysis before making any trading decisions.
Filtering for Actionable Signals
async function getTopConvergence() {
const { tokens } = await client.kol.coordination({
period: "6h",
min_kols: 3,
});
// Only show tokens where KOLs are net buying
const accumulating = tokens.filter((t) => t.net_flow > 0);
// Sort by number of KOLs
accumulating.sort((a, b) => b.kol_count - a.kol_count);
console.log("Top convergence signals (last 4h):");
for (const token of accumulating.slice(0, 5)) {
console.log(
` ${token.token_symbol} — ${token.kol_count} KOLs accumulating`
);
}
}
Combining All Three
The real power comes from chaining these endpoints together. Here is a workflow that finds convergence signals, checks deployer reputation for each token, and outputs a ranked list:
async function fullScan() {
// Step 1: Find tokens multiple KOLs are buying
const { tokens } = await client.kol.coordination({
period: "6h",
min_kols: 3,
});
const results = [];
for (const token of tokens.filter((t) => t.net_flow > 0)) {
// Step 2: Check deployer reputation (if available)
if (token.deployer_wallet) {
const { deployer } = await client.deployer.profile(token.deployer_wallet);
results.push({
symbol: token.token_symbol,
kolCount: token.kol_count,
deployerTier: deployer.tier,
bondRate: deployer.bonding_rate,
});
}
}
// Step 3: Rank by deployer quality + KOL count
results.sort((a, b) => {
const tierOrder = { elite: 5, good: 4, moderate: 3, rising: 2, cold: 1 };
const tierDiff =
(tierOrder[b.deployerTier] || 0) - (tierOrder[a.deployerTier] || 0);
return tierDiff !== 0 ? tierDiff : b.kolCount - a.kolCount;
});
console.log("Ranked signals:");
for (const r of results) {
console.log(
` ${r.symbol} — ${r.kolCount} KOLs, deployer: ${r.deployerTier} (${(r.bondRate * 100).toFixed(1)}% bond rate)`
);
}
}
fullScan();