@madeonsol/plugin-madeonsol 0.7.0 → 1.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +14 -2
- package/dist/actions/deployer-alerts.js +1 -1
- package/dist/actions/kol-alerts-recent.js +1 -1
- package/dist/actions/kol-compare.js +1 -1
- package/dist/actions/kol-coordination.js +1 -1
- package/dist/actions/kol-feed.js +1 -1
- package/dist/actions/kol-leaderboard.js +1 -1
- package/dist/actions/kol-token-entry-order.js +1 -1
- package/dist/client.d.ts +83 -3
- package/dist/client.js +75 -12
- package/dist/index.js +10 -9
- package/package.json +7 -2
- package/src/actions/deployer-alerts.ts +0 -72
- package/src/actions/kol-alerts-recent.ts +0 -67
- package/src/actions/kol-compare.ts +0 -79
- package/src/actions/kol-coordination.ts +0 -64
- package/src/actions/kol-feed.ts +0 -65
- package/src/actions/kol-leaderboard.ts +0 -64
- package/src/actions/kol-token-entry-order.ts +0 -71
- package/src/actions/wallet-tracker.ts +0 -119
- package/src/client.ts +0 -204
- package/src/index.ts +0 -78
- package/tsconfig.json +0 -14
package/README.md
CHANGED
|
@@ -4,6 +4,18 @@ ElizaOS plugin for [MadeOnSol](https://madeonsol.com) — Solana KOL trading int
|
|
|
4
4
|
|
|
5
5
|
> Real-time Solana trading intelligence: track 1,000+ KOL wallets with <3s latency, score 6,700+ Pump.fun deployers by reputation, detect multi-KOL coordination signals, monitor any Solana wallet for swaps and transfers, and stream every DEX trade. Free tier: 200 requests/day at [madeonsol.com/developer](https://madeonsol.com/developer) — no credit card required.
|
|
6
6
|
|
|
7
|
+
## Quick start (10 seconds)
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
npm install @madeonsol/plugin-madeonsol
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
```ts
|
|
14
|
+
import { madeOnSolPlugin } from "@madeonsol/plugin-madeonsol";
|
|
15
|
+
const agent = { plugins: [madeOnSolPlugin], settings: { MADEONSOL_API_KEY: "msk_..." } }; // free key: https://madeonsol.com/developer
|
|
16
|
+
// Then ask the agent: "What are KOLs buying right now?"
|
|
17
|
+
```
|
|
18
|
+
|
|
7
19
|
## Authentication
|
|
8
20
|
|
|
9
21
|
Three options (in priority order):
|
|
@@ -42,7 +54,7 @@ import { madeOnSolPlugin } from "@madeonsol/plugin-madeonsol";
|
|
|
42
54
|
const agent = {
|
|
43
55
|
plugins: [madeOnSolPlugin],
|
|
44
56
|
settings: {
|
|
45
|
-
// Option 1: API key
|
|
57
|
+
// Option 1: API key — get one free at madeonsol.com/developer
|
|
46
58
|
MADEONSOL_API_KEY: "msk_your_api_key_here",
|
|
47
59
|
|
|
48
60
|
// Option 2: x402 micropayments (AI agents)
|
|
@@ -65,7 +77,7 @@ Your agent can then respond to queries like:
|
|
|
65
77
|
|------|-------|-----------------|--------------|
|
|
66
78
|
| BASIC | Free | 10 | 200 |
|
|
67
79
|
| PRO | $49/mo | 50 | 10,000 |
|
|
68
|
-
| ULTRA | $
|
|
80
|
+
| ULTRA | $149/mo | 100 + WS events | 100,000 |
|
|
69
81
|
|
|
70
82
|
Get a key at [madeonsol.com/developer](https://madeonsol.com/developer).
|
|
71
83
|
|
|
@@ -29,7 +29,7 @@ export const deployerAlertsAction = {
|
|
|
29
29
|
const result = await client.getDeployerAlerts(tier ? { limit, tier } : { limit });
|
|
30
30
|
if (result.error) {
|
|
31
31
|
callback?.({ text: result.status === 402
|
|
32
|
-
? "Authentication required. Set MADEONSOL_API_KEY (free at madeonsol.com/developer)
|
|
32
|
+
? "Authentication required. Set MADEONSOL_API_KEY (free at madeonsol.com/developer) or SVM_PRIVATE_KEY."
|
|
33
33
|
: `Error: ${result.error}` });
|
|
34
34
|
return undefined;
|
|
35
35
|
}
|
|
@@ -24,7 +24,7 @@ export const kolAlertsRecentAction = {
|
|
|
24
24
|
const result = await client.getKolAlertsRecent({ window, limit: "20" });
|
|
25
25
|
if (result.error) {
|
|
26
26
|
callback?.({ text: result.status === 402
|
|
27
|
-
? "Authentication required. Set MADEONSOL_API_KEY (free at madeonsol.com/developer)
|
|
27
|
+
? "Authentication required. Set MADEONSOL_API_KEY (free at madeonsol.com/developer) or SVM_PRIVATE_KEY."
|
|
28
28
|
: `Error: ${result.error}` });
|
|
29
29
|
return undefined;
|
|
30
30
|
}
|
|
@@ -29,7 +29,7 @@ export const kolCompareAction = {
|
|
|
29
29
|
const result = await client.getKolCompare(wallets);
|
|
30
30
|
if (result.error) {
|
|
31
31
|
callback?.({ text: result.status === 402
|
|
32
|
-
? "Authentication required. Set MADEONSOL_API_KEY (free at madeonsol.com/developer)
|
|
32
|
+
? "Authentication required. Set MADEONSOL_API_KEY (free at madeonsol.com/developer) or SVM_PRIVATE_KEY."
|
|
33
33
|
: `Error: ${result.error}` });
|
|
34
34
|
return undefined;
|
|
35
35
|
}
|
|
@@ -24,7 +24,7 @@ export const kolCoordinationAction = {
|
|
|
24
24
|
const result = await client.getKolCoordination({ period, limit: "10" });
|
|
25
25
|
if (result.error) {
|
|
26
26
|
callback?.({ text: result.status === 402
|
|
27
|
-
? "Authentication required. Set MADEONSOL_API_KEY (free at madeonsol.com/developer)
|
|
27
|
+
? "Authentication required. Set MADEONSOL_API_KEY (free at madeonsol.com/developer) or SVM_PRIVATE_KEY."
|
|
28
28
|
: `Error: ${result.error}` });
|
|
29
29
|
return undefined;
|
|
30
30
|
}
|
package/dist/actions/kol-feed.js
CHANGED
|
@@ -25,7 +25,7 @@ export const kolFeedAction = {
|
|
|
25
25
|
const result = await client.getKolFeed({ limit: "10", ...(action ? { action } : {}) });
|
|
26
26
|
if (result.error) {
|
|
27
27
|
callback?.({ text: result.status === 402
|
|
28
|
-
? "Authentication required. Set MADEONSOL_API_KEY (free at madeonsol.com/developer)
|
|
28
|
+
? "Authentication required. Set MADEONSOL_API_KEY (free at madeonsol.com/developer) or SVM_PRIVATE_KEY."
|
|
29
29
|
: `Error: ${result.error}` });
|
|
30
30
|
return undefined;
|
|
31
31
|
}
|
|
@@ -24,7 +24,7 @@ export const kolLeaderboardAction = {
|
|
|
24
24
|
const result = await client.getKolLeaderboard({ period, limit: "10" });
|
|
25
25
|
if (result.error) {
|
|
26
26
|
callback?.({ text: result.status === 402
|
|
27
|
-
? "Authentication required. Set MADEONSOL_API_KEY (free at madeonsol.com/developer)
|
|
27
|
+
? "Authentication required. Set MADEONSOL_API_KEY (free at madeonsol.com/developer) or SVM_PRIVATE_KEY."
|
|
28
28
|
: `Error: ${result.error}` });
|
|
29
29
|
return undefined;
|
|
30
30
|
}
|
|
@@ -28,7 +28,7 @@ export const kolTokenEntryOrderAction = {
|
|
|
28
28
|
const result = await client.getKolTokenEntryOrder(mint, { limit: "20" });
|
|
29
29
|
if (result.error) {
|
|
30
30
|
callback?.({ text: result.status === 402
|
|
31
|
-
? "Authentication required. Set MADEONSOL_API_KEY (free at madeonsol.com/developer)
|
|
31
|
+
? "Authentication required. Set MADEONSOL_API_KEY (free at madeonsol.com/developer) or SVM_PRIVATE_KEY."
|
|
32
32
|
: `Error: ${result.error}` });
|
|
33
33
|
return undefined;
|
|
34
34
|
}
|
package/dist/client.d.ts
CHANGED
|
@@ -1,22 +1,32 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* MadeOnSol API client.
|
|
3
|
-
*
|
|
3
|
+
* Two auth modes: MadeOnSol API key (`msk_`, recommended) or x402 micropayments.
|
|
4
|
+
*
|
|
5
|
+
* v1.0 breaking change: RapidAPI auth has been removed (marketplace retired 2026-04-19).
|
|
6
|
+
* Get a free `msk_` key at https://madeonsol.com/developer.
|
|
4
7
|
*/
|
|
5
8
|
export interface MadeOnSolClientOptions {
|
|
6
9
|
baseUrl?: string;
|
|
7
10
|
/** MadeOnSol API key (get one free at madeonsol.com/developer). Preferred. */
|
|
8
11
|
apiKey?: string;
|
|
9
|
-
/** RapidAPI subscription key. */
|
|
10
|
-
rapidApiKey?: string;
|
|
11
12
|
/** x402 payment-enabled fetch (for AI agents with SVM_PRIVATE_KEY). */
|
|
12
13
|
fetchFn?: typeof fetch;
|
|
13
14
|
}
|
|
15
|
+
export interface RateLimitInfo {
|
|
16
|
+
limit?: string;
|
|
17
|
+
remaining?: string;
|
|
18
|
+
reset?: string;
|
|
19
|
+
requestId?: string;
|
|
20
|
+
}
|
|
14
21
|
export declare class MadeOnSolClient {
|
|
15
22
|
private baseUrl;
|
|
16
23
|
private fetchFn;
|
|
17
24
|
private authMode;
|
|
18
25
|
private authHeaders;
|
|
26
|
+
/** Most recent rate-limit headers, populated by every request. */
|
|
27
|
+
lastRateLimit: RateLimitInfo;
|
|
19
28
|
constructor(options?: MadeOnSolClientOptions);
|
|
29
|
+
private captureRateLimit;
|
|
20
30
|
query<T = unknown>(path: string, params?: Record<string, string | undefined>): Promise<{
|
|
21
31
|
data?: T;
|
|
22
32
|
error?: string;
|
|
@@ -194,4 +204,74 @@ export declare class MadeOnSolClient {
|
|
|
194
204
|
error?: string;
|
|
195
205
|
status: number;
|
|
196
206
|
}>;
|
|
207
|
+
getAlphaLeaderboard(params?: {
|
|
208
|
+
limit?: string;
|
|
209
|
+
min_tokens?: string;
|
|
210
|
+
min_pnl?: string;
|
|
211
|
+
}): Promise<{
|
|
212
|
+
data?: unknown;
|
|
213
|
+
error?: string;
|
|
214
|
+
status: number;
|
|
215
|
+
}>;
|
|
216
|
+
getAlphaWallet(wallet: string): Promise<{
|
|
217
|
+
data?: unknown;
|
|
218
|
+
error?: string;
|
|
219
|
+
status: number;
|
|
220
|
+
}>;
|
|
221
|
+
getAlphaLinked(wallet: string): Promise<{
|
|
222
|
+
data?: unknown;
|
|
223
|
+
error?: string;
|
|
224
|
+
status: number;
|
|
225
|
+
}>;
|
|
226
|
+
getTokenCapTable(mint: string): Promise<{
|
|
227
|
+
data?: unknown;
|
|
228
|
+
error?: string;
|
|
229
|
+
status: number;
|
|
230
|
+
}>;
|
|
231
|
+
getTokenBuyerQuality(mint: string): Promise<{
|
|
232
|
+
data?: unknown;
|
|
233
|
+
error?: string;
|
|
234
|
+
status: number;
|
|
235
|
+
}>;
|
|
236
|
+
copyTradeList(): Promise<{
|
|
237
|
+
data?: unknown;
|
|
238
|
+
error?: string;
|
|
239
|
+
status: number;
|
|
240
|
+
}>;
|
|
241
|
+
copyTradeCreate(params: {
|
|
242
|
+
name: string;
|
|
243
|
+
source_wallet: string;
|
|
244
|
+
is_active?: boolean;
|
|
245
|
+
webhook_url?: string;
|
|
246
|
+
delivery?: "webhook" | "websocket" | "both";
|
|
247
|
+
filters?: Record<string, unknown>;
|
|
248
|
+
}): Promise<{
|
|
249
|
+
data?: unknown;
|
|
250
|
+
error?: string;
|
|
251
|
+
status: number;
|
|
252
|
+
}>;
|
|
253
|
+
copyTradeGet(ruleId: string): Promise<{
|
|
254
|
+
data?: unknown;
|
|
255
|
+
error?: string;
|
|
256
|
+
status: number;
|
|
257
|
+
}>;
|
|
258
|
+
copyTradeUpdate(ruleId: string, updates: Record<string, unknown>): Promise<{
|
|
259
|
+
data?: unknown;
|
|
260
|
+
error?: string;
|
|
261
|
+
status: number;
|
|
262
|
+
}>;
|
|
263
|
+
copyTradeDelete(ruleId: string): Promise<{
|
|
264
|
+
data?: unknown;
|
|
265
|
+
error?: string;
|
|
266
|
+
status: number;
|
|
267
|
+
}>;
|
|
268
|
+
copyTradeSignals(params?: {
|
|
269
|
+
rule_id?: string;
|
|
270
|
+
limit?: string;
|
|
271
|
+
since?: string;
|
|
272
|
+
}): Promise<{
|
|
273
|
+
data?: unknown;
|
|
274
|
+
error?: string;
|
|
275
|
+
status: number;
|
|
276
|
+
}>;
|
|
197
277
|
}
|
package/dist/client.js
CHANGED
|
@@ -1,14 +1,18 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* MadeOnSol API client.
|
|
3
|
-
*
|
|
3
|
+
* Two auth modes: MadeOnSol API key (`msk_`, recommended) or x402 micropayments.
|
|
4
|
+
*
|
|
5
|
+
* v1.0 breaking change: RapidAPI auth has been removed (marketplace retired 2026-04-19).
|
|
6
|
+
* Get a free `msk_` key at https://madeonsol.com/developer.
|
|
4
7
|
*/
|
|
5
8
|
const DEFAULT_BASE = "https://madeonsol.com";
|
|
6
|
-
const RAPIDAPI_HOST = "madeonsol-solana-kol-tracker-tools-api.p.rapidapi.com";
|
|
7
9
|
export class MadeOnSolClient {
|
|
8
10
|
baseUrl;
|
|
9
11
|
fetchFn;
|
|
10
12
|
authMode;
|
|
11
13
|
authHeaders;
|
|
14
|
+
/** Most recent rate-limit headers, populated by every request. */
|
|
15
|
+
lastRateLimit = {};
|
|
12
16
|
constructor(options = {}) {
|
|
13
17
|
this.baseUrl = options.baseUrl || DEFAULT_BASE;
|
|
14
18
|
this.fetchFn = options.fetchFn || globalThis.fetch;
|
|
@@ -17,17 +21,24 @@ export class MadeOnSolClient {
|
|
|
17
21
|
this.authMode = "madeonsol";
|
|
18
22
|
this.authHeaders = { Authorization: `Bearer ${options.apiKey}` };
|
|
19
23
|
}
|
|
20
|
-
else if (options.rapidApiKey) {
|
|
21
|
-
this.authMode = "rapidapi";
|
|
22
|
-
this.authHeaders = { "x-rapidapi-key": options.rapidApiKey, "x-rapidapi-host": RAPIDAPI_HOST };
|
|
23
|
-
}
|
|
24
24
|
else if (options.fetchFn) {
|
|
25
25
|
this.authMode = "x402";
|
|
26
26
|
}
|
|
27
27
|
else {
|
|
28
28
|
this.authMode = "none";
|
|
29
|
+
console.warn("\n[madeonsol] MadeOnSolClient constructed without apiKey or fetchFn — every request will fail.\n" +
|
|
30
|
+
" → Get a free key (200 req/day, no card) at https://madeonsol.com/developer\n" +
|
|
31
|
+
" → Then: new MadeOnSolClient({ apiKey: process.env.MADEONSOL_API_KEY })\n");
|
|
29
32
|
}
|
|
30
33
|
}
|
|
34
|
+
captureRateLimit(res) {
|
|
35
|
+
this.lastRateLimit = {
|
|
36
|
+
limit: res.headers.get("X-RateLimit-Limit") ?? undefined,
|
|
37
|
+
remaining: res.headers.get("X-RateLimit-Remaining") ?? undefined,
|
|
38
|
+
reset: res.headers.get("X-RateLimit-Reset") ?? undefined,
|
|
39
|
+
requestId: res.headers.get("X-Request-Id") ?? undefined,
|
|
40
|
+
};
|
|
41
|
+
}
|
|
31
42
|
async query(path, params) {
|
|
32
43
|
const apiPath = this.authMode === "x402" || this.authMode === "none"
|
|
33
44
|
? path
|
|
@@ -42,6 +53,7 @@ export class MadeOnSolClient {
|
|
|
42
53
|
const res = this.authMode === "x402"
|
|
43
54
|
? await this.fetchFn(url.toString(), { method: "GET" })
|
|
44
55
|
: await this.fetchFn(url.toString(), { method: "GET", headers: this.authHeaders });
|
|
56
|
+
this.captureRateLimit(res);
|
|
45
57
|
if (res.status === 402) {
|
|
46
58
|
const body = await res.json();
|
|
47
59
|
return { error: `Payment required: ${JSON.stringify(body.accepts?.[0] || body)}`, status: 402 };
|
|
@@ -98,10 +110,10 @@ export class MadeOnSolClient {
|
|
|
98
110
|
getDeployerTrajectory(wallet) {
|
|
99
111
|
return this.restRequest("GET", `/deployer-hunter/${wallet}/trajectory`);
|
|
100
112
|
}
|
|
101
|
-
// ──
|
|
113
|
+
// ── REST helper (used by webhooks, streaming, alpha, copy-trade, wallet-tracker) ──
|
|
102
114
|
async restRequest(method, path, body) {
|
|
103
|
-
if (this.authMode !== "madeonsol"
|
|
104
|
-
return { error: "API key
|
|
115
|
+
if (this.authMode !== "madeonsol") {
|
|
116
|
+
return { error: "MadeOnSol API key required for this endpoint. Get a free `msk_` key at https://madeonsol.com/developer", status: 401 };
|
|
105
117
|
}
|
|
106
118
|
const res = await this.fetchFn(`${this.baseUrl}/api/v1${path}`, {
|
|
107
119
|
method,
|
|
@@ -111,12 +123,14 @@ export class MadeOnSolClient {
|
|
|
111
123
|
},
|
|
112
124
|
...(body ? { body: JSON.stringify(body) } : {}),
|
|
113
125
|
});
|
|
126
|
+
this.captureRateLimit(res);
|
|
114
127
|
if (!res.ok) {
|
|
115
128
|
const text = await res.text().catch(() => "Unknown error");
|
|
116
129
|
return { error: text, status: res.status };
|
|
117
130
|
}
|
|
118
131
|
return { data: await res.json(), status: res.status };
|
|
119
132
|
}
|
|
133
|
+
// ── Webhook management (PRO/ULTRA) ──
|
|
120
134
|
createWebhook(params) {
|
|
121
135
|
return this.restRequest("POST", "/webhooks", params);
|
|
122
136
|
}
|
|
@@ -143,14 +157,15 @@ export class MadeOnSolClient {
|
|
|
143
157
|
return this.restRequest("DELETE", `/wallet-tracker/watchlist/${encodeURIComponent(walletAddress)}`);
|
|
144
158
|
}
|
|
145
159
|
getWalletTrackerTrades(params) {
|
|
146
|
-
const
|
|
160
|
+
const qs = new URLSearchParams();
|
|
147
161
|
if (params) {
|
|
148
162
|
for (const [k, v] of Object.entries(params)) {
|
|
149
163
|
if (v !== undefined)
|
|
150
|
-
|
|
164
|
+
qs.set(k, v);
|
|
151
165
|
}
|
|
152
166
|
}
|
|
153
|
-
|
|
167
|
+
const query = qs.toString() ? `?${qs.toString()}` : "";
|
|
168
|
+
return this.restRequest("GET", `/wallet-tracker/trades${query}`);
|
|
154
169
|
}
|
|
155
170
|
getWalletTrackerSummary(params) {
|
|
156
171
|
const qs = new URLSearchParams();
|
|
@@ -161,4 +176,52 @@ export class MadeOnSolClient {
|
|
|
161
176
|
const query = qs.toString() ? `?${qs.toString()}` : "";
|
|
162
177
|
return this.restRequest("GET", `/wallet-tracker/summary${query}`);
|
|
163
178
|
}
|
|
179
|
+
// ── Alpha Wallet Intelligence ──
|
|
180
|
+
getAlphaLeaderboard(params) {
|
|
181
|
+
const qs = new URLSearchParams();
|
|
182
|
+
if (params)
|
|
183
|
+
for (const [k, v] of Object.entries(params))
|
|
184
|
+
if (v !== undefined)
|
|
185
|
+
qs.set(k, v);
|
|
186
|
+
const query = qs.toString() ? `?${qs.toString()}` : "";
|
|
187
|
+
return this.restRequest("GET", `/alpha/leaderboard${query}`);
|
|
188
|
+
}
|
|
189
|
+
getAlphaWallet(wallet) {
|
|
190
|
+
return this.restRequest("GET", `/alpha/wallet/${encodeURIComponent(wallet)}`);
|
|
191
|
+
}
|
|
192
|
+
getAlphaLinked(wallet) {
|
|
193
|
+
return this.restRequest("GET", `/alpha/wallet/${encodeURIComponent(wallet)}/linked`);
|
|
194
|
+
}
|
|
195
|
+
// ── Token Quality ──
|
|
196
|
+
getTokenCapTable(mint) {
|
|
197
|
+
return this.restRequest("GET", `/token/${encodeURIComponent(mint)}/cap-table`);
|
|
198
|
+
}
|
|
199
|
+
getTokenBuyerQuality(mint) {
|
|
200
|
+
return this.restRequest("GET", `/token/${encodeURIComponent(mint)}/buyer-quality`);
|
|
201
|
+
}
|
|
202
|
+
// ── Copy-Trade Rules (PRO/ULTRA) ──
|
|
203
|
+
copyTradeList() {
|
|
204
|
+
return this.restRequest("GET", "/copy-trade/rules");
|
|
205
|
+
}
|
|
206
|
+
copyTradeCreate(params) {
|
|
207
|
+
return this.restRequest("POST", "/copy-trade/rules", params);
|
|
208
|
+
}
|
|
209
|
+
copyTradeGet(ruleId) {
|
|
210
|
+
return this.restRequest("GET", `/copy-trade/rules/${encodeURIComponent(ruleId)}`);
|
|
211
|
+
}
|
|
212
|
+
copyTradeUpdate(ruleId, updates) {
|
|
213
|
+
return this.restRequest("PATCH", `/copy-trade/rules/${encodeURIComponent(ruleId)}`, updates);
|
|
214
|
+
}
|
|
215
|
+
copyTradeDelete(ruleId) {
|
|
216
|
+
return this.restRequest("DELETE", `/copy-trade/rules/${encodeURIComponent(ruleId)}`);
|
|
217
|
+
}
|
|
218
|
+
copyTradeSignals(params) {
|
|
219
|
+
const qs = new URLSearchParams();
|
|
220
|
+
if (params)
|
|
221
|
+
for (const [k, v] of Object.entries(params))
|
|
222
|
+
if (v !== undefined)
|
|
223
|
+
qs.set(k, v);
|
|
224
|
+
const query = qs.toString() ? `?${qs.toString()}` : "";
|
|
225
|
+
return this.restRequest("GET", `/copy-trade/signals${query}`);
|
|
226
|
+
}
|
|
164
227
|
}
|
package/dist/index.js
CHANGED
|
@@ -11,7 +11,7 @@ import { MadeOnSolClient } from "./client.js";
|
|
|
11
11
|
export const MADEONSOL_CLIENT_KEY = "madeonsol:client";
|
|
12
12
|
export const madeOnSolPlugin = {
|
|
13
13
|
name: "madeonsol",
|
|
14
|
-
description: "Query Solana KOL trading intelligence and deployer analytics from MadeOnSol. Tracks 1,000+ KOL wallets and
|
|
14
|
+
description: "Query Solana KOL trading intelligence and deployer analytics from MadeOnSol. Tracks 1,000+ KOL wallets and 6,700+ Pump.fun deployers.",
|
|
15
15
|
actions: [
|
|
16
16
|
kolFeedAction,
|
|
17
17
|
kolCoordinationAction,
|
|
@@ -25,21 +25,20 @@ export const madeOnSolPlugin = {
|
|
|
25
25
|
],
|
|
26
26
|
/**
|
|
27
27
|
* Initialize the MadeOnSol client.
|
|
28
|
-
* Auth priority: MADEONSOL_API_KEY >
|
|
29
|
-
* Get a free API key at madeonsol.com/developer — no wallet needed.
|
|
28
|
+
* Auth priority: MADEONSOL_API_KEY > SVM_PRIVATE_KEY (x402).
|
|
29
|
+
* Get a free `msk_` API key at madeonsol.com/developer — no wallet needed.
|
|
30
|
+
*
|
|
31
|
+
* v1.0 breaking change: RAPIDAPI_KEY support has been removed
|
|
32
|
+
* (MadeOnSol RapidAPI marketplace was retired 2026-04-19).
|
|
30
33
|
*/
|
|
31
34
|
init: async (_config, runtime) => {
|
|
32
35
|
const baseUrl = String(runtime.getSetting?.("MADEONSOL_API_URL") || "https://madeonsol.com");
|
|
33
36
|
const apiKey = runtime.getSetting?.("MADEONSOL_API_KEY");
|
|
34
|
-
const rapidApiKey = runtime.getSetting?.("RAPIDAPI_KEY");
|
|
35
37
|
const privateKey = runtime.getSetting?.("SVM_PRIVATE_KEY");
|
|
36
38
|
let fetchFn;
|
|
37
39
|
if (apiKey) {
|
|
38
40
|
console.log("[madeonsol] Using MadeOnSol API key (Bearer auth)");
|
|
39
41
|
}
|
|
40
|
-
else if (rapidApiKey) {
|
|
41
|
-
console.log("[madeonsol] Using RapidAPI key");
|
|
42
|
-
}
|
|
43
42
|
else if (privateKey) {
|
|
44
43
|
try {
|
|
45
44
|
const { wrapFetchWithPayment } = await import("@x402/fetch");
|
|
@@ -58,9 +57,11 @@ export const madeOnSolPlugin = {
|
|
|
58
57
|
}
|
|
59
58
|
}
|
|
60
59
|
else {
|
|
61
|
-
console.
|
|
60
|
+
console.warn("[madeonsol] No auth configured — every API call will fail.\n" +
|
|
61
|
+
" → Get a free MADEONSOL_API_KEY (200 req/day, no card) at https://madeonsol.com/developer\n" +
|
|
62
|
+
" → Or set SVM_PRIVATE_KEY for x402 micropayments.");
|
|
62
63
|
}
|
|
63
|
-
const madeOnSolClient = new MadeOnSolClient({ baseUrl, apiKey,
|
|
64
|
+
const madeOnSolClient = new MadeOnSolClient({ baseUrl, apiKey, fetchFn });
|
|
64
65
|
runtime[MADEONSOL_CLIENT_KEY] = madeOnSolClient;
|
|
65
66
|
},
|
|
66
67
|
};
|
package/package.json
CHANGED
|
@@ -1,10 +1,15 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@madeonsol/plugin-madeonsol",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "1.0.1",
|
|
4
4
|
"description": "ElizaOS plugin for MadeOnSol — Solana KOL intelligence and deployer analytics via x402 micropayments",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
7
7
|
"types": "dist/index.d.ts",
|
|
8
|
+
"files": [
|
|
9
|
+
"dist",
|
|
10
|
+
"README.md",
|
|
11
|
+
"LICENSE"
|
|
12
|
+
],
|
|
8
13
|
"scripts": {
|
|
9
14
|
"build": "tsc",
|
|
10
15
|
"dev": "tsc --watch"
|
|
@@ -46,4 +51,4 @@
|
|
|
46
51
|
"devDependencies": {
|
|
47
52
|
"@elizaos/core": "^2.0.0-alpha.77"
|
|
48
53
|
}
|
|
49
|
-
}
|
|
54
|
+
}
|
|
@@ -1,72 +0,0 @@
|
|
|
1
|
-
import type { Action, IAgentRuntime, Memory, State, HandlerCallback } from "@elizaos/core";
|
|
2
|
-
import { MadeOnSolClient } from "../client.js";
|
|
3
|
-
import { MADEONSOL_CLIENT_KEY } from "../index.js";
|
|
4
|
-
|
|
5
|
-
function getClient(runtime: IAgentRuntime): MadeOnSolClient {
|
|
6
|
-
return ((runtime as unknown as Record<string, unknown>)[MADEONSOL_CLIENT_KEY] as MadeOnSolClient) ?? new MadeOnSolClient();
|
|
7
|
-
}
|
|
8
|
-
|
|
9
|
-
export const deployerAlertsAction: Action = {
|
|
10
|
-
name: "GET_DEPLOYER_ALERTS",
|
|
11
|
-
description:
|
|
12
|
-
"Get real-time Pump.fun deployer alerts from MadeOnSol. Shows new token launches from tracked elite/good deployers with stats, market cap, and KOL buy enrichment.",
|
|
13
|
-
similes: [
|
|
14
|
-
"deployer alerts",
|
|
15
|
-
"pump fun launches",
|
|
16
|
-
"new token alerts",
|
|
17
|
-
"deployer tracker",
|
|
18
|
-
"elite deployer tokens",
|
|
19
|
-
],
|
|
20
|
-
|
|
21
|
-
validate: async (_runtime: IAgentRuntime, message: Memory): Promise<boolean> => {
|
|
22
|
-
const text = (message.content?.text || "").toLowerCase();
|
|
23
|
-
return /\b(deployer|pump\.?fun|launch|new token)/i.test(text) && /\b(alert|track|monitor|latest|recent)/i.test(text);
|
|
24
|
-
},
|
|
25
|
-
|
|
26
|
-
handler: async (
|
|
27
|
-
runtime: IAgentRuntime,
|
|
28
|
-
message: Memory,
|
|
29
|
-
_state?: State,
|
|
30
|
-
_options?: unknown,
|
|
31
|
-
callback?: HandlerCallback,
|
|
32
|
-
) => {
|
|
33
|
-
const client = getClient(runtime);
|
|
34
|
-
const text = (message.content?.text || "").toLowerCase();
|
|
35
|
-
const limit = text.match(/\b(\d+)\s*(alert|token|launch)/)?.[1] || "10";
|
|
36
|
-
// Best-effort tier inference from the user's prompt — only sent to the API
|
|
37
|
-
// when the user explicitly mentioned a tier. The tier filter requires
|
|
38
|
-
// PRO/ULTRA on the caller's API key.
|
|
39
|
-
const tierMatch = text.match(/\b(elite|good|moderate|rising|cold)\b/);
|
|
40
|
-
const tier = tierMatch?.[1];
|
|
41
|
-
|
|
42
|
-
const result = await client.getDeployerAlerts(tier ? { limit, tier } : { limit });
|
|
43
|
-
|
|
44
|
-
if (result.error) {
|
|
45
|
-
callback?.({ text: result.status === 402
|
|
46
|
-
? "Authentication required. Set MADEONSOL_API_KEY (free at madeonsol.com/developer), RAPIDAPI_KEY, or SVM_PRIVATE_KEY."
|
|
47
|
-
: `Error: ${result.error}` });
|
|
48
|
-
return undefined;
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
const data = result.data as { alerts: Array<{ title: string; token_symbol: string; priority: string; market_cap_at_alert: number | null; deployers: { tier: string; bonding_rate: number | null }; kol_buys: { count: number; kols: string[] } | null }> };
|
|
52
|
-
const lines = (data.alerts || []).slice(0, 10).map((a) => {
|
|
53
|
-
const deployer = a.deployers as unknown as { tier: string; bonding_rate: number | null };
|
|
54
|
-
const mc = a.market_cap_at_alert ? `$${(a.market_cap_at_alert / 1000).toFixed(1)}k` : "?";
|
|
55
|
-
const kols = a.kol_buys ? `${a.kol_buys.count} KOLs buying` : "";
|
|
56
|
-
return `[${deployer?.tier}] ${a.token_symbol || "?"} — MC: ${mc}${kols ? ` | ${kols}` : ""}`;
|
|
57
|
-
});
|
|
58
|
-
|
|
59
|
-
callback?.({
|
|
60
|
-
text: `Deployer Alerts:\n${lines.join("\n") || "No recent alerts."}`,
|
|
61
|
-
content: data,
|
|
62
|
-
});
|
|
63
|
-
return undefined;
|
|
64
|
-
},
|
|
65
|
-
|
|
66
|
-
examples: [
|
|
67
|
-
[
|
|
68
|
-
{ name: "user1", content: { text: "Show me the latest deployer alerts from Pump.fun" } },
|
|
69
|
-
{ name: "assistant", content: { text: "Here are the latest deployer alerts..." } },
|
|
70
|
-
],
|
|
71
|
-
] as Action["examples"],
|
|
72
|
-
};
|
|
@@ -1,67 +0,0 @@
|
|
|
1
|
-
import type { Action, IAgentRuntime, Memory, State, HandlerCallback } from "@elizaos/core";
|
|
2
|
-
import { MadeOnSolClient } from "../client.js";
|
|
3
|
-
import { MADEONSOL_CLIENT_KEY } from "../index.js";
|
|
4
|
-
|
|
5
|
-
function getClient(runtime: IAgentRuntime): MadeOnSolClient {
|
|
6
|
-
return ((runtime as unknown as Record<string, unknown>)[MADEONSOL_CLIENT_KEY] as MadeOnSolClient) ?? new MadeOnSolClient();
|
|
7
|
-
}
|
|
8
|
-
|
|
9
|
-
export const kolAlertsRecentAction: Action = {
|
|
10
|
-
name: "GET_KOL_ALERTS_RECENT",
|
|
11
|
-
description:
|
|
12
|
-
"Get live KOL alerts from MadeOnSol — consensus clusters, fresh-token KOL buys, and heating-up wallets in one unified stream.",
|
|
13
|
-
similes: [
|
|
14
|
-
"kol alerts",
|
|
15
|
-
"recent alerts",
|
|
16
|
-
"kol signals",
|
|
17
|
-
"whats happening now",
|
|
18
|
-
"live kol feed",
|
|
19
|
-
],
|
|
20
|
-
|
|
21
|
-
validate: async (_runtime: IAgentRuntime, message: Memory): Promise<boolean> => {
|
|
22
|
-
const text = (message.content?.text || "").toLowerCase();
|
|
23
|
-
return /\b(kol|smart money)\b/.test(text) && /\b(alert|signal|recent|live|now)\b/.test(text);
|
|
24
|
-
},
|
|
25
|
-
|
|
26
|
-
handler: async (
|
|
27
|
-
runtime: IAgentRuntime,
|
|
28
|
-
message: Memory,
|
|
29
|
-
_state?: State,
|
|
30
|
-
_options?: unknown,
|
|
31
|
-
callback?: HandlerCallback,
|
|
32
|
-
) => {
|
|
33
|
-
const client = getClient(runtime);
|
|
34
|
-
const text = (message.content?.text || "").toLowerCase();
|
|
35
|
-
const window = text.includes("1h") ? "1h" : text.includes("6h") ? "6h" : text.includes("24h") ? "24h" : text.includes("5m") ? "5m" : "15m";
|
|
36
|
-
|
|
37
|
-
const result = await client.getKolAlertsRecent({ window, limit: "20" });
|
|
38
|
-
|
|
39
|
-
if (result.error) {
|
|
40
|
-
callback?.({ text: result.status === 402
|
|
41
|
-
? "Authentication required. Set MADEONSOL_API_KEY (free at madeonsol.com/developer), RAPIDAPI_KEY, or SVM_PRIVATE_KEY."
|
|
42
|
-
: `Error: ${result.error}` });
|
|
43
|
-
return undefined;
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
const data = result.data as {
|
|
47
|
-
alerts: Array<{ type: string; severity: string; token_symbol: string | null; kol_name: string | null; detected_at: string }>;
|
|
48
|
-
};
|
|
49
|
-
const lines = (data.alerts || []).slice(0, 10).map((a) => {
|
|
50
|
-
const subject = a.token_symbol || a.kol_name || "—";
|
|
51
|
-
return `[${a.severity}] ${a.type}: ${subject}`;
|
|
52
|
-
});
|
|
53
|
-
|
|
54
|
-
callback?.({
|
|
55
|
-
text: `KOL alerts (${window}):\n${lines.join("\n") || "No alerts in window."}`,
|
|
56
|
-
content: data,
|
|
57
|
-
});
|
|
58
|
-
return undefined;
|
|
59
|
-
},
|
|
60
|
-
|
|
61
|
-
examples: [
|
|
62
|
-
[
|
|
63
|
-
{ name: "user1", content: { text: "What are the recent KOL alerts?" } },
|
|
64
|
-
{ name: "assistant", content: { text: "Here are the live KOL alerts..." } },
|
|
65
|
-
],
|
|
66
|
-
] as Action["examples"],
|
|
67
|
-
};
|
|
@@ -1,79 +0,0 @@
|
|
|
1
|
-
import type { Action, IAgentRuntime, Memory, State, HandlerCallback } from "@elizaos/core";
|
|
2
|
-
import { MadeOnSolClient } from "../client.js";
|
|
3
|
-
import { MADEONSOL_CLIENT_KEY } from "../index.js";
|
|
4
|
-
|
|
5
|
-
function getClient(runtime: IAgentRuntime): MadeOnSolClient {
|
|
6
|
-
return ((runtime as unknown as Record<string, unknown>)[MADEONSOL_CLIENT_KEY] as MadeOnSolClient) ?? new MadeOnSolClient();
|
|
7
|
-
}
|
|
8
|
-
|
|
9
|
-
const ADDR_RE = /\b[1-9A-HJ-NP-Za-km-z]{32,44}\b/g;
|
|
10
|
-
|
|
11
|
-
export const kolCompareAction: Action = {
|
|
12
|
-
name: "GET_KOL_COMPARE",
|
|
13
|
-
description:
|
|
14
|
-
"Compare 2-5 Solana KOL wallets side-by-side on MadeOnSol — strategy, winrates, ROI, percentile. PRO+ adds overlap tokens (bought by 2+ in last 30d).",
|
|
15
|
-
similes: [
|
|
16
|
-
"compare kols",
|
|
17
|
-
"compare wallets",
|
|
18
|
-
"kol comparison",
|
|
19
|
-
"side by side kols",
|
|
20
|
-
"who is better kol",
|
|
21
|
-
],
|
|
22
|
-
|
|
23
|
-
validate: async (_runtime: IAgentRuntime, message: Memory): Promise<boolean> => {
|
|
24
|
-
const text = message.content?.text || "";
|
|
25
|
-
const matches = text.match(ADDR_RE) ?? [];
|
|
26
|
-
return /\bcompare\b/i.test(text) && matches.length >= 2;
|
|
27
|
-
},
|
|
28
|
-
|
|
29
|
-
handler: async (
|
|
30
|
-
runtime: IAgentRuntime,
|
|
31
|
-
message: Memory,
|
|
32
|
-
_state?: State,
|
|
33
|
-
_options?: unknown,
|
|
34
|
-
callback?: HandlerCallback,
|
|
35
|
-
) => {
|
|
36
|
-
const client = getClient(runtime);
|
|
37
|
-
const wallets = ((message.content?.text || "").match(ADDR_RE) ?? []).slice(0, 5);
|
|
38
|
-
if (wallets.length < 2) {
|
|
39
|
-
callback?.({ text: "Please include at least 2 wallet addresses to compare." });
|
|
40
|
-
return undefined;
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
const result = await client.getKolCompare(wallets);
|
|
44
|
-
|
|
45
|
-
if (result.error) {
|
|
46
|
-
callback?.({ text: result.status === 402
|
|
47
|
-
? "Authentication required. Set MADEONSOL_API_KEY (free at madeonsol.com/developer), RAPIDAPI_KEY, or SVM_PRIVATE_KEY."
|
|
48
|
-
: `Error: ${result.error}` });
|
|
49
|
-
return undefined;
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
const data = result.data as {
|
|
53
|
-
profiles: Array<{ wallet_address: string; name: string | null; strategy_tag: string | null; winrate_7d: number | null; pnl_30d: number | null }>;
|
|
54
|
-
overlap?: Array<{ token_symbol: string | null; wallets: string[] }>;
|
|
55
|
-
};
|
|
56
|
-
const lines = (data.profiles || []).map((p) => {
|
|
57
|
-
const who = p.name || `${p.wallet_address.slice(0, 4)}…${p.wallet_address.slice(-4)}`;
|
|
58
|
-
const wr = p.winrate_7d != null ? `${p.winrate_7d.toFixed(1)}%` : "—";
|
|
59
|
-
const pnl = p.pnl_30d != null ? `${p.pnl_30d > 0 ? "+" : ""}${p.pnl_30d.toFixed(1)} SOL` : "—";
|
|
60
|
-
return `${who} [${p.strategy_tag || "mixed"}] winrate 7d: ${wr}, PnL 30d: ${pnl}`;
|
|
61
|
-
});
|
|
62
|
-
const overlap = (data.overlap || []).slice(0, 5).map((o) => `${o.token_symbol || "?"} (${o.wallets.length} wallets)`);
|
|
63
|
-
|
|
64
|
-
callback?.({
|
|
65
|
-
text:
|
|
66
|
-
`KOL comparison:\n${lines.join("\n")}` +
|
|
67
|
-
(overlap.length ? `\n\nOverlap (30d): ${overlap.join(", ")}` : ""),
|
|
68
|
-
content: data,
|
|
69
|
-
});
|
|
70
|
-
return undefined;
|
|
71
|
-
},
|
|
72
|
-
|
|
73
|
-
examples: [
|
|
74
|
-
[
|
|
75
|
-
{ name: "user1", content: { text: "Compare these two KOLs: ABC...123 and DEF...456" } },
|
|
76
|
-
{ name: "assistant", content: { text: "Here's the side-by-side comparison..." } },
|
|
77
|
-
],
|
|
78
|
-
] as Action["examples"],
|
|
79
|
-
};
|