@sharpe-terminal/mcp-server 1.2.0 → 1.4.0
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 +58 -158
- package/dist/api-client.d.ts +17 -0
- package/dist/api-client.d.ts.map +1 -1
- package/dist/api-client.js +144 -9
- package/dist/api-client.js.map +1 -1
- package/dist/composite-tools.d.ts +64 -0
- package/dist/composite-tools.d.ts.map +1 -1
- package/dist/composite-tools.js +479 -230
- package/dist/composite-tools.js.map +1 -1
- package/dist/index.js +9 -226
- package/dist/index.js.map +1 -1
- package/dist/resources.d.ts +44 -5
- package/dist/resources.d.ts.map +1 -1
- package/dist/resources.js +61 -5
- package/dist/resources.js.map +1 -1
- package/dist/server.d.ts +15 -0
- package/dist/server.d.ts.map +1 -0
- package/dist/server.js +264 -0
- package/dist/server.js.map +1 -0
- package/dist/tool-runtime.d.ts +46 -0
- package/dist/tool-runtime.d.ts.map +1 -1
- package/dist/tool-runtime.js +265 -52
- package/dist/tool-runtime.js.map +1 -1
- package/dist/tools.d.ts +139 -75
- package/dist/tools.d.ts.map +1 -1
- package/dist/tools.js +412 -107
- package/dist/tools.js.map +1 -1
- package/package.json +1 -1
package/dist/tools.js
CHANGED
|
@@ -1,7 +1,55 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
2
|
import { FUTURES_CHARTS } from "./resources.js";
|
|
3
|
+
import { MAX_ITEMS, paginateRows, paginateSnapshotPayload, rowTimeMs, } from "./tool-runtime.js";
|
|
3
4
|
// -- Tool schemas (Zod shapes for McpServer.tool()) --
|
|
4
5
|
const FUTURES_CHART_IDS = FUTURES_CHARTS.map((chart) => chart.id);
|
|
6
|
+
const pageCursorSchema = z
|
|
7
|
+
.string()
|
|
8
|
+
.optional()
|
|
9
|
+
.describe("Pagination cursor returned by the previous page. Only meaningful alongside limit.");
|
|
10
|
+
export const globalOverviewSchema = {
|
|
11
|
+
tab: z
|
|
12
|
+
.enum(["crypto", "equity", "preipo", "etf", "index", "commodity", "fx"])
|
|
13
|
+
.default("crypto")
|
|
14
|
+
.describe("Universe to return rows for. 'crypto' = crypto perps; the rest are RWA perp classes. The market-wide metric block is identical on every tab. The 'basket' asset class has no tab and is rejected."),
|
|
15
|
+
limit: z
|
|
16
|
+
.number()
|
|
17
|
+
.int()
|
|
18
|
+
.min(1)
|
|
19
|
+
.max(1000)
|
|
20
|
+
.optional()
|
|
21
|
+
.describe("Rows per page (1-1000). A paged response is { data, pagination } holding only the ranked rows; the market-wide metric block comes back on unpaged calls. Responses are additionally capped at 200 items, so pass limit together with cursor to page through every row."),
|
|
22
|
+
cursor: pageCursorSchema,
|
|
23
|
+
};
|
|
24
|
+
export const rwaPerpRatesSchema = {
|
|
25
|
+
type: z
|
|
26
|
+
.enum(["current", "history", "stats"])
|
|
27
|
+
.default("current")
|
|
28
|
+
.describe("Type of rwa-perp data. 'current' = latest funding/rollover snapshot per venue market, 'history' = session-tagged settlement time-series for one symbol (Hyperliquid + Kraken), 'stats' = best carry, top cross-venue spread, weekend premium, and tracked open interest."),
|
|
29
|
+
symbol: z
|
|
30
|
+
.string()
|
|
31
|
+
.optional()
|
|
32
|
+
.describe("Underlying equity ticker (e.g. TSLA, NVDA, MSTR). Required for type=history. GOOG (Ostium) and GOOGL (Hyperliquid/Kraken) are distinct share classes."),
|
|
33
|
+
venue: z
|
|
34
|
+
.string()
|
|
35
|
+
.optional()
|
|
36
|
+
.describe("Filter results to a single venue, e.g. Binance, Bybit, OKX, Bitget, Gate, Kraken, Coinbase, Aster, Lighter, Extended, GRVT, ApeX, Pacifica, Orderly, Ostium, Avantis, or a Hyperliquid HIP-3 builder market (Hyperliquid, Felix, Kinetiq, dreamcash, Paragon, Ventuals). Free-form because the venue list is registry-driven and grows."),
|
|
37
|
+
days: z
|
|
38
|
+
.number()
|
|
39
|
+
.min(1)
|
|
40
|
+
.max(90)
|
|
41
|
+
.default(7)
|
|
42
|
+
.optional()
|
|
43
|
+
.describe("Days of settlement history to retrieve (type=history only). Range: 1-90."),
|
|
44
|
+
limit: z
|
|
45
|
+
.number()
|
|
46
|
+
.int()
|
|
47
|
+
.min(1)
|
|
48
|
+
.max(5000)
|
|
49
|
+
.optional()
|
|
50
|
+
.describe("Rows per page for type=current and type=history (1-5000); a paged response is { data, pagination }. Responses are additionally capped at 200 items, so pass limit together with cursor to page through every row."),
|
|
51
|
+
cursor: pageCursorSchema,
|
|
52
|
+
};
|
|
5
53
|
export const fundingRatesSchema = {
|
|
6
54
|
type: z
|
|
7
55
|
.enum(["current", "accumulated", "history"])
|
|
@@ -10,7 +58,19 @@ export const fundingRatesSchema = {
|
|
|
10
58
|
coin: z
|
|
11
59
|
.string()
|
|
12
60
|
.optional()
|
|
13
|
-
.describe("
|
|
61
|
+
.describe("Coin ticker, lot spelling or full name (e.g. BTC, PEPE, 1000PEPE, kPEPE, bitcoin). Returns every contract of that asset across all exchanges, whatever its base_coin spelling: PEPE also returns the 1000PEPE and KPEPE lot contracts (read lot_multiplier). Required for type=history; optional for current/accumulated."),
|
|
62
|
+
exchange: z
|
|
63
|
+
.string()
|
|
64
|
+
.optional()
|
|
65
|
+
.describe("Filter to a single venue. Values are title case exactly as returned in the `exchange` field (e.g. Binance, Bybit, OKX, Gate.io, Hyperliquid, Kraken, Aster, Lighter, dYdX, Crypto.com, edgeX, tradeXYZ); lowercase slugs such as 'gate-io' also resolve. Free-form because the venue list is registry-driven and grows. Read sharpe://exchanges for the current list."),
|
|
66
|
+
margin: z
|
|
67
|
+
.enum(["linear", "inverse"])
|
|
68
|
+
.optional()
|
|
69
|
+
.describe("Collateral convention: 'linear' = quote-margined (USDT/USDC), 'inverse' = coin-margined. Unfiltered by default."),
|
|
70
|
+
asset_class: z
|
|
71
|
+
.enum(["crypto", "equity", "commodity", "fx", "index"])
|
|
72
|
+
.optional()
|
|
73
|
+
.describe("Underlying category of the perpetual. Unfiltered by default, so tokenized-equity, commodity, index and FX perps are returned alongside crypto; pass 'crypto' to rank crypto only."),
|
|
14
74
|
days: z
|
|
15
75
|
.number()
|
|
16
76
|
.min(1)
|
|
@@ -18,6 +78,42 @@ export const fundingRatesSchema = {
|
|
|
18
78
|
.default(30)
|
|
19
79
|
.optional()
|
|
20
80
|
.describe("Number of days of history to retrieve (type=history only). Range: 1-1095."),
|
|
81
|
+
limit: z
|
|
82
|
+
.number()
|
|
83
|
+
.int()
|
|
84
|
+
.min(1)
|
|
85
|
+
.max(5000)
|
|
86
|
+
.optional()
|
|
87
|
+
.describe("Maximum rows to return. Responses are additionally capped at 200 items to protect the agent context window, so pass limit together with cursor to page through the whole book."),
|
|
88
|
+
cursor: z
|
|
89
|
+
.string()
|
|
90
|
+
.optional()
|
|
91
|
+
.describe("Pagination cursor returned by the previous page. Only meaningful alongside limit."),
|
|
92
|
+
};
|
|
93
|
+
export const fundingSettlementSchema = {
|
|
94
|
+
window: z
|
|
95
|
+
.enum(["current", "1d", "3d", "7d"])
|
|
96
|
+
.default("current")
|
|
97
|
+
.describe("Settlement window. 'current' is the next settlement, priced live off open interest and the forward-looking rate (predicted_rate when a venue publishes one, else the in-progress rate) -- always estimated, never realised yet. '1d'/'3d'/'7d' are realised windows; one whose coverage is below 90% carries partial: true in its window value because its history is still accruing, not a completed total."),
|
|
98
|
+
class: z
|
|
99
|
+
.enum(["all", "crypto", "rwa"])
|
|
100
|
+
.default("all")
|
|
101
|
+
.describe("Asset universe. 'rwa' = tokenized equity, commodity, FX and index perps. crypto + rwa always equal the all totals."),
|
|
102
|
+
coin: z
|
|
103
|
+
.string()
|
|
104
|
+
.optional()
|
|
105
|
+
.describe("Comma-separated base coin tickers (e.g. 'BTC' or 'BTC,ETH,SOL') to filter rows to. `totals` stays scoped to the selected class regardless of this filter -- read a filtered coin's own row for its number, not totals."),
|
|
106
|
+
exchange: z
|
|
107
|
+
.string()
|
|
108
|
+
.optional()
|
|
109
|
+
.describe("Keep only coins that have a contract on this venue. Each row's windows and open interest stay all-venue totals, not this venue's own figures. Free-form because the venue list is registry-driven and grows; an unresolvable value is rejected rather than silently returning an empty book."),
|
|
110
|
+
limit: z
|
|
111
|
+
.number()
|
|
112
|
+
.int()
|
|
113
|
+
.min(1)
|
|
114
|
+
.max(1000)
|
|
115
|
+
.optional()
|
|
116
|
+
.describe("Maximum rows to return, in market-cap rank order (unranked coins follow alphabetically). Defaults to 100."),
|
|
21
117
|
};
|
|
22
118
|
export const futuresDataSchema = {
|
|
23
119
|
chart: z
|
|
@@ -37,6 +133,14 @@ export const futuresDataSchema = {
|
|
|
37
133
|
.string()
|
|
38
134
|
.optional()
|
|
39
135
|
.describe("Comma-separated list of exchanges to include (e.g. Binance,Bybit,OKX,Deribit,Hyperliquid)."),
|
|
136
|
+
limit: z
|
|
137
|
+
.number()
|
|
138
|
+
.int()
|
|
139
|
+
.min(1)
|
|
140
|
+
.max(10000)
|
|
141
|
+
.optional()
|
|
142
|
+
.describe("Rows per page (1-10000), oldest first, returned with a pagination cursor. Paged rows are raw chart rows, oi-snapshot included. Responses are additionally capped at 200 items, so pass limit together with cursor to page through the full window."),
|
|
143
|
+
cursor: pageCursorSchema,
|
|
40
144
|
};
|
|
41
145
|
export const futuresCoinsSchema = {};
|
|
42
146
|
export const correlationMatrixSchema = {
|
|
@@ -48,7 +152,7 @@ export const correlationMatrixSchema = {
|
|
|
48
152
|
ids: z
|
|
49
153
|
.string()
|
|
50
154
|
.optional()
|
|
51
|
-
.describe("Comma-separated
|
|
155
|
+
.describe("Comma-separated asset IDs. Use CoinGecko IDs for crypto (e.g. bitcoin,ethereum) and Sharpe IDs for TradFi (e.g. sp500,gold,nvda). If omitted, returns the default mixed set."),
|
|
52
156
|
};
|
|
53
157
|
export const arbitrageSpotPerpSchema = {
|
|
54
158
|
exchange: z
|
|
@@ -60,13 +164,27 @@ export const arbitrageSpotPerpSchema = {
|
|
|
60
164
|
.enum(["all", "long", "short"])
|
|
61
165
|
.default("all")
|
|
62
166
|
.optional()
|
|
63
|
-
.describe("Filter by
|
|
167
|
+
.describe("Filter by perpetual-leg direction: short for positive funding capture, long for negative funding capture."),
|
|
64
168
|
};
|
|
65
169
|
export const arbitrageCrossExchangeSchema = {
|
|
66
170
|
exchanges: z
|
|
67
171
|
.string()
|
|
68
172
|
.optional()
|
|
69
|
-
.describe("Comma-separated list of
|
|
173
|
+
.describe("Comma-separated list of venues to compare (e.g. Binance,Bybit,Hyperliquid). Omit for all 32 funding venues."),
|
|
174
|
+
minOiUsd: z
|
|
175
|
+
.number()
|
|
176
|
+
.min(0)
|
|
177
|
+
.optional()
|
|
178
|
+
.describe("Minimum open interest in USD on the smaller leg. Legs with unknown OI fail the floor. Default 0 (no floor)."),
|
|
179
|
+
minVolUsd: z
|
|
180
|
+
.number()
|
|
181
|
+
.min(0)
|
|
182
|
+
.optional()
|
|
183
|
+
.describe("Minimum 24h volume in USD on the smaller leg. Legs with unknown volume fail the floor. Default 0 (no floor)."),
|
|
184
|
+
assetClass: z
|
|
185
|
+
.enum(["all", "crypto", "rwa"])
|
|
186
|
+
.optional()
|
|
187
|
+
.describe('Underlying filter: "all" (default), "crypto", or "rwa" (equity, commodity, FX and index perps). Pairs never cross asset classes.'),
|
|
70
188
|
};
|
|
71
189
|
export const arbitrageScannerSchema = {
|
|
72
190
|
coin: z
|
|
@@ -80,17 +198,26 @@ export const arbitrageScannerSchema = {
|
|
|
80
198
|
minApr: z
|
|
81
199
|
.number()
|
|
82
200
|
.optional()
|
|
83
|
-
.describe("Minimum
|
|
201
|
+
.describe("Minimum product-specific fee-adjusted net APR in percentage points."),
|
|
84
202
|
minOiUsd: z
|
|
85
203
|
.number()
|
|
86
204
|
.min(0)
|
|
87
205
|
.optional()
|
|
88
206
|
.describe("Minimum open interest in USD."),
|
|
207
|
+
minVolumeUsd: z
|
|
208
|
+
.number()
|
|
209
|
+
.min(0)
|
|
210
|
+
.optional()
|
|
211
|
+
.describe("Minimum 24-hour volume in USD."),
|
|
89
212
|
minDepthUsd: z
|
|
90
213
|
.number()
|
|
91
214
|
.min(0)
|
|
92
215
|
.optional()
|
|
93
216
|
.describe("Minimum executable depth in USD when available."),
|
|
217
|
+
marginType: z
|
|
218
|
+
.enum(["linear", "inverse", "both"])
|
|
219
|
+
.optional()
|
|
220
|
+
.describe("Futures margin type filter."),
|
|
94
221
|
notional: z
|
|
95
222
|
.number()
|
|
96
223
|
.positive()
|
|
@@ -112,7 +239,10 @@ export const arbitrageScannerSchema = {
|
|
|
112
239
|
export const cexSpotTransferScannerSchema = {
|
|
113
240
|
coin: arbitrageScannerSchema.coin,
|
|
114
241
|
exchanges: arbitrageScannerSchema.exchanges,
|
|
115
|
-
minApr:
|
|
242
|
+
minApr: z
|
|
243
|
+
.number()
|
|
244
|
+
.optional()
|
|
245
|
+
.describe("Minimum fee-adjusted transfer profit in percentage points (legacy parameter name)."),
|
|
116
246
|
minDepthUsd: arbitrageScannerSchema.minDepthUsd,
|
|
117
247
|
notional: arbitrageScannerSchema.notional,
|
|
118
248
|
limit: arbitrageScannerSchema.limit,
|
|
@@ -128,21 +258,7 @@ export const heatmapSchema = {
|
|
|
128
258
|
.string()
|
|
129
259
|
.default("top-100")
|
|
130
260
|
.optional()
|
|
131
|
-
.describe("
|
|
132
|
-
};
|
|
133
|
-
export const dexScreenerDataSchema = {
|
|
134
|
-
category: z
|
|
135
|
-
.enum(["volume", "trending", "gainers", "losers", "new_pairs"])
|
|
136
|
-
.default("trending")
|
|
137
|
-
.optional()
|
|
138
|
-
.describe("DEX Screener category."),
|
|
139
|
-
network: z.string().optional().describe("Optional chain/network slug."),
|
|
140
|
-
phrase: z.string().optional().describe("Optional search phrase."),
|
|
141
|
-
limit: z.number().min(1).max(100).default(50).optional(),
|
|
142
|
-
};
|
|
143
|
-
export const dexScreenerSecuritySchema = {
|
|
144
|
-
address: z.string().describe("Token contract address."),
|
|
145
|
-
chainId: z.number().int().positive().describe("Codex network ID."),
|
|
261
|
+
.describe("One of 34 category slugs (e.g. top-100, defi, layer-1, memes). The legacy top-100 slug returns the Top 50 universe."),
|
|
146
262
|
};
|
|
147
263
|
export const tokenScannerSchema = {
|
|
148
264
|
mode: z
|
|
@@ -156,18 +272,30 @@ export const tokenScannerSchema = {
|
|
|
156
272
|
.describe("Comma-separated Dexscreener chain IDs."),
|
|
157
273
|
chain: z.string().optional().describe("Single chain for top-new mode."),
|
|
158
274
|
profile: z
|
|
159
|
-
.enum(["discovery", "balanced", "strict"
|
|
275
|
+
.enum(["discovery", "balanced", "strict"])
|
|
160
276
|
.optional()
|
|
161
277
|
.describe("Scanner profile."),
|
|
162
|
-
|
|
278
|
+
days: z.number().min(1).optional().describe("Top-new lookback in days."),
|
|
279
|
+
limit: z.number().min(1).max(72).default(50).optional(),
|
|
163
280
|
minLiquidityUsd: z.number().min(0).optional(),
|
|
164
281
|
minVolumeH24: z.number().min(0).optional(),
|
|
165
282
|
minTxnsH1: z.number().min(0).optional(),
|
|
283
|
+
minTxnsH24: z.number().min(0).optional(),
|
|
166
284
|
maxAgeHours: z.number().min(0).optional(),
|
|
285
|
+
includeUnknownAge: z.boolean().optional(),
|
|
286
|
+
sortBy: z.enum(["score", "readiness", "rs", "volume", "momentum"]).optional(),
|
|
287
|
+
minBreakoutReadiness: z.number().min(0).optional(),
|
|
288
|
+
minRelativeStrength: z.number().optional(),
|
|
289
|
+
maxVolLiqRatio: z.number().min(0).optional(),
|
|
290
|
+
minPriceChangeH1: z.number().optional(),
|
|
167
291
|
};
|
|
168
292
|
export const rugCheckSecuritySchema = {
|
|
169
293
|
address: z.string().describe("Token contract address."),
|
|
170
|
-
chainId: z
|
|
294
|
+
chainId: z
|
|
295
|
+
.number()
|
|
296
|
+
.int()
|
|
297
|
+
.positive()
|
|
298
|
+
.describe("EVM chain ID (1 Ethereum, 56 BNB Smart Chain, 8453 Base, 42161 Arbitrum, 137 Polygon, 10 Optimism, 43114 Avalanche, 146 Sonic, 80094 Berachain, and 29 more), or 1399811149 for Solana and 728126428 for Tron. An unsupported chain returns 400."),
|
|
171
299
|
};
|
|
172
300
|
export const rugCheckTrendingSchema = {
|
|
173
301
|
limit: z.number().min(1).max(100).default(50).optional(),
|
|
@@ -205,7 +333,7 @@ export const webTrafficSchema = {
|
|
|
205
333
|
.optional()
|
|
206
334
|
.describe("Entity type."),
|
|
207
335
|
mode: z
|
|
208
|
-
.enum(["rankings", "
|
|
336
|
+
.enum(["rankings", "snapshots", "market"])
|
|
209
337
|
.optional()
|
|
210
338
|
.describe("Payload mode."),
|
|
211
339
|
tf: z
|
|
@@ -218,12 +346,11 @@ export const webTrafficSchema = {
|
|
|
218
346
|
.optional()
|
|
219
347
|
.describe("Market sub-mode when mode=market."),
|
|
220
348
|
};
|
|
221
|
-
export const katanaSchema = {};
|
|
222
349
|
export const narrativesSchema = {
|
|
223
350
|
narrative: z
|
|
224
351
|
.string()
|
|
225
352
|
.optional()
|
|
226
|
-
.describe("Narrative
|
|
353
|
+
.describe("Narrative to filter by, as the id the API matches (layer-1, layer-2, defi, ai-agents, defai, depin, desci, gaming, dex, cex, lending, memes, nfts, oracles, privacy, rwa, stablecoins, restaking, liquid-staking, modular, socialfi, intent, prediction-markets, perps, bridges, account-abstraction, tap-to-earn, telegram-apps, zk, yield-farming). Page slugs such as dex-tokens or cex-tokens return no coins; use dex or cex. Omit for all narratives."),
|
|
227
354
|
correlation: z
|
|
228
355
|
.string()
|
|
229
356
|
.optional()
|
|
@@ -234,7 +361,7 @@ export const ecosystemsSchema = {
|
|
|
234
361
|
ecosystem: z
|
|
235
362
|
.string()
|
|
236
363
|
.optional()
|
|
237
|
-
.describe("Ecosystem
|
|
364
|
+
.describe("Ecosystem to filter by, as the id the API matches (e.g. ethereum, solana, bnb, arbitrum, base, bitcoin, avalanche, optimism, cosmos, polkadot, sui, aptos, ton, tron); read sharpe://ecosystems for all of them. Page slugs such as bnb-chain or toncoin return no coins; use bnb or ton. Omit for all ecosystems."),
|
|
238
365
|
excludeNative: z
|
|
239
366
|
.string()
|
|
240
367
|
.optional()
|
|
@@ -291,6 +418,13 @@ export const newsSchema = {
|
|
|
291
418
|
.string()
|
|
292
419
|
.optional()
|
|
293
420
|
.describe("ISO 8601 timestamp. Only return articles published after this time."),
|
|
421
|
+
q: z
|
|
422
|
+
.string()
|
|
423
|
+
.trim()
|
|
424
|
+
.min(1)
|
|
425
|
+
.max(200)
|
|
426
|
+
.optional()
|
|
427
|
+
.describe("Search article titles across the stored news corpus."),
|
|
294
428
|
offset: z
|
|
295
429
|
.number()
|
|
296
430
|
.int()
|
|
@@ -298,36 +432,19 @@ export const newsSchema = {
|
|
|
298
432
|
.optional()
|
|
299
433
|
.describe("Offset for pagination; skip this many articles before returning results."),
|
|
300
434
|
};
|
|
301
|
-
export const curatedNewsSchema = {
|
|
302
|
-
limit: z
|
|
303
|
-
.number()
|
|
304
|
-
.min(1)
|
|
305
|
-
.max(100)
|
|
306
|
-
.default(20)
|
|
307
|
-
.optional()
|
|
308
|
-
.describe("Maximum number of curated stories to return (1-100)."),
|
|
309
|
-
category: z
|
|
310
|
-
.enum(["all", "crypto", "ai", "markets", "geopolitics"])
|
|
311
|
-
.optional()
|
|
312
|
-
.describe("Filter by category: all, crypto, ai, markets, geopolitics."),
|
|
313
|
-
cursor: z
|
|
314
|
-
.string()
|
|
315
|
-
.optional()
|
|
316
|
-
.describe("Pagination cursor (ISO date or 'date|id') from a previous response."),
|
|
317
|
-
};
|
|
318
435
|
export const marketOverviewSchema = {};
|
|
319
436
|
export const pricePredictionSchema = {
|
|
320
437
|
coin: z
|
|
321
438
|
.string()
|
|
322
439
|
.optional()
|
|
323
|
-
.describe("
|
|
440
|
+
.describe("Ticker or canonical coin slug (e.g. BTC, bitcoin, solana). Omit for all coins."),
|
|
324
441
|
};
|
|
325
442
|
export const searchMarketCapSchema = {
|
|
326
443
|
q: z
|
|
327
444
|
.string()
|
|
328
445
|
.min(2)
|
|
329
446
|
.max(100)
|
|
330
|
-
.describe("
|
|
447
|
+
.describe("Crypto or supported TradFi asset name/symbol (2-100 characters)."),
|
|
331
448
|
};
|
|
332
449
|
export const gemFinderSchema = {
|
|
333
450
|
limit: z
|
|
@@ -337,6 +454,10 @@ export const gemFinderSchema = {
|
|
|
337
454
|
.default(100)
|
|
338
455
|
.optional()
|
|
339
456
|
.describe("Maximum number of tokens to return (1-1000)."),
|
|
457
|
+
cursor: z
|
|
458
|
+
.string()
|
|
459
|
+
.optional()
|
|
460
|
+
.describe("Snapshot-bound pagination cursor returned by the previous Gem Finder page."),
|
|
340
461
|
};
|
|
341
462
|
export const derivativesOverviewSchema = {};
|
|
342
463
|
export const apiCoverageSchema = {};
|
|
@@ -375,15 +496,25 @@ const listingExchangeIds = [
|
|
|
375
496
|
"dydx",
|
|
376
497
|
"aevo",
|
|
377
498
|
];
|
|
499
|
+
// /listings/data validates only the legacy compatibility venues
|
|
500
|
+
// (legacyListingExchangeIds in src/lib/api/schemas.ts) and 400s the rest;
|
|
501
|
+
// the recent/events feeds accept every id in listingExchangeIds.
|
|
502
|
+
const legacyListingExchangeIds = [
|
|
503
|
+
"binance",
|
|
504
|
+
"okx",
|
|
505
|
+
"bybit",
|
|
506
|
+
"gateio",
|
|
507
|
+
"mexc",
|
|
508
|
+
];
|
|
378
509
|
export const listingsDataSchema = {
|
|
379
510
|
narrative: z
|
|
380
511
|
.string()
|
|
381
512
|
.optional()
|
|
382
513
|
.describe("Filter to a single narrative slug (e.g. 'ai-agents', 'memes', 'layer-1', 'rwa', 'defi'). Uses the Sharpe narrative taxonomy."),
|
|
383
514
|
exchange: z
|
|
384
|
-
.enum(
|
|
515
|
+
.enum(legacyListingExchangeIds)
|
|
385
516
|
.optional()
|
|
386
|
-
.describe("Filter to a single exchange."),
|
|
517
|
+
.describe("Filter to a single exchange. The aggregate hub covers the compatibility venues only; use get_recent_listings or get_listing_events for the other venues."),
|
|
387
518
|
};
|
|
388
519
|
export const listingsRecentSchema = {
|
|
389
520
|
narrative: z
|
|
@@ -573,16 +704,158 @@ export const pumpDumpSchema = {
|
|
|
573
704
|
.optional()
|
|
574
705
|
.describe("Filter to one manipulation lifecycle phase."),
|
|
575
706
|
};
|
|
707
|
+
// -- Keyless-path post-processing helpers --
|
|
708
|
+
function isRecord(value) {
|
|
709
|
+
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
710
|
+
}
|
|
711
|
+
function cursorArg(args) {
|
|
712
|
+
return typeof args.cursor === "string" && args.cursor
|
|
713
|
+
? args.cursor
|
|
714
|
+
: undefined;
|
|
715
|
+
}
|
|
716
|
+
/**
|
|
717
|
+
* The stored `manipulation_phase` values a public phase param selects.
|
|
718
|
+
* Mirrors resolvePhaseFilter in src/app/api/v1/pump-dump/data/route.ts.
|
|
719
|
+
*/
|
|
720
|
+
function resolvePhaseFilter(phase) {
|
|
721
|
+
if (!phase)
|
|
722
|
+
return null;
|
|
723
|
+
if (phase === "dumping")
|
|
724
|
+
return ["distribution", "dump-risk"];
|
|
725
|
+
if (phase === "dump")
|
|
726
|
+
return ["dump-risk"];
|
|
727
|
+
return [phase];
|
|
728
|
+
}
|
|
729
|
+
/**
|
|
730
|
+
* The free pump-dump and insider-selling routes are statically cached and
|
|
731
|
+
* read no query params, so limit, min_score and phase only ever reached v1
|
|
732
|
+
* (2026-09-24 audit). Re-apply them to the keyless `{ scores, meta }` payload
|
|
733
|
+
* the way the v1 routes do: score floor, phase mapping, then limit over the
|
|
734
|
+
* score-ordered rows. The v1 payload (`{ coins, ... }`) is already filtered.
|
|
735
|
+
*/
|
|
736
|
+
export function filterSignalScores(data, args) {
|
|
737
|
+
if (!isRecord(data) || !Array.isArray(data.scores))
|
|
738
|
+
return data;
|
|
739
|
+
const minScore = typeof args.min_score === "number" ? args.min_score : 0;
|
|
740
|
+
const limit = typeof args.limit === "number" ? args.limit : 100;
|
|
741
|
+
const phases = resolvePhaseFilter(typeof args.phase === "string" ? args.phase : undefined);
|
|
742
|
+
const scores = data.scores
|
|
743
|
+
.filter((row) => {
|
|
744
|
+
if (!isRecord(row) || typeof row.score !== "number")
|
|
745
|
+
return false;
|
|
746
|
+
if (row.score < minScore)
|
|
747
|
+
return false;
|
|
748
|
+
return phases === null || phases.includes(String(row.manipulation_phase));
|
|
749
|
+
})
|
|
750
|
+
.slice(0, limit);
|
|
751
|
+
return { ...data, scores };
|
|
752
|
+
}
|
|
753
|
+
/**
|
|
754
|
+
* oi-snapshot is documented as current open interest by exchange, but both
|
|
755
|
+
* routes return the whole ascending window (up to 5,000 raw rows). Keep each
|
|
756
|
+
* exchange's newest reading, largest first, so "current" means current.
|
|
757
|
+
*/
|
|
758
|
+
export function latestRowPerExchange(rows) {
|
|
759
|
+
const latest = new Map();
|
|
760
|
+
for (const row of rows) {
|
|
761
|
+
const at = rowTimeMs(row);
|
|
762
|
+
if (!isRecord(row) || at == null)
|
|
763
|
+
continue;
|
|
764
|
+
const exchange = String(row.exchange ?? "");
|
|
765
|
+
const prev = latest.get(exchange);
|
|
766
|
+
if (!prev || at >= prev.at)
|
|
767
|
+
latest.set(exchange, { row, at });
|
|
768
|
+
}
|
|
769
|
+
const oiOf = (row) => {
|
|
770
|
+
const value = Number(row.open_interest_value);
|
|
771
|
+
return Number.isFinite(value) ? value : Number.NEGATIVE_INFINITY;
|
|
772
|
+
};
|
|
773
|
+
return [...latest.values()]
|
|
774
|
+
.map((entry) => entry.row)
|
|
775
|
+
.sort((a, b) => oiOf(b) - oiOf(a));
|
|
776
|
+
}
|
|
777
|
+
/**
|
|
778
|
+
* The rows of a funding response that belong to `coin`. The funding API
|
|
779
|
+
* resolves `coin` to an asset and returns every contract of it, so `PEPE`
|
|
780
|
+
* also returns the 1000PEPE and KPEPE lot contracts, whose base_coin differs.
|
|
781
|
+
* A row is kept when its base_coin, asset_symbol or asset_id names the coin,
|
|
782
|
+
* or when it is a contract of the same asset as a row that does
|
|
783
|
+
* (`coin=1000PEPE` keeps the PEPE-spelled contracts too). Rows from an API
|
|
784
|
+
* without the asset fields, or with them null (no instrument master to read),
|
|
785
|
+
* match on base_coin exactly as before.
|
|
786
|
+
*/
|
|
787
|
+
export function rowsForFundingCoin(rows, coin) {
|
|
788
|
+
const needle = coin.trim().toUpperCase();
|
|
789
|
+
const text = (row, key) => {
|
|
790
|
+
const value = row !== null && typeof row === "object"
|
|
791
|
+
? row[key]
|
|
792
|
+
: undefined;
|
|
793
|
+
return typeof value === "string" ? value : null;
|
|
794
|
+
};
|
|
795
|
+
const names = (row) => [
|
|
796
|
+
text(row, "base_coin") ?? text(row, "coin"),
|
|
797
|
+
text(row, "asset_symbol"),
|
|
798
|
+
text(row, "asset_id"),
|
|
799
|
+
].some((value) => value?.toUpperCase() === needle);
|
|
800
|
+
const assets = new Set(rows
|
|
801
|
+
.filter(names)
|
|
802
|
+
.map((row) => text(row, "asset_id"))
|
|
803
|
+
.filter((assetId) => assetId !== null));
|
|
804
|
+
return rows.filter((row) => {
|
|
805
|
+
const assetId = text(row, "asset_id");
|
|
806
|
+
return names(row) || (assetId !== null && assets.has(assetId));
|
|
807
|
+
});
|
|
808
|
+
}
|
|
576
809
|
export const TOOL_DEFS = [
|
|
810
|
+
{
|
|
811
|
+
name: "get_global_overview",
|
|
812
|
+
description: "Get the whole-market derivatives board in one call: total open interest with its crypto-versus-RWA split, 24h liquidations, average Wilder RSI(14) across the top 100 crypto perps by market cap, the Altcoin Season Index (share of the top 50 by market cap beating BTC over 90 days, excluding stablecoins and wrapped/staked derivatives), open interest broken down by asset class, and a ranked per-asset row table. The tab parameter selects the universe: crypto, equity, preipo, etf, index, commodity or fx. Rows carry price, 24h price change, funding rate (interval-true, never assumed 8h), 24h volume, market cap, open interest with 1h and 24h changes, plus liquidations on crypto or a venue count on RWA tabs. Ranks are by open interest descending. Liquidations are crypto-only because no RWA venue publishes a liquidation feed. Use this for 'what is the market doing' questions; use get_funding_rates for per-venue crypto funding detail and get_rwa_perp_funding for RWA carry and cross-venue spreads.",
|
|
813
|
+
schema: globalOverviewSchema,
|
|
814
|
+
apiPath: "/api/v1/global/overview",
|
|
815
|
+
fallbackPath: "/api/global/overview",
|
|
816
|
+
// The free route ignores limit/cursor and always returns every row with
|
|
817
|
+
// the metric block. Page its rows into the v1 paged shape ({ data,
|
|
818
|
+
// pagination }, rows only) so a keyless caller can reach all of them.
|
|
819
|
+
postProcess: (data, args, context) => {
|
|
820
|
+
if (context?.paginated || typeof args.limit !== "number")
|
|
821
|
+
return data;
|
|
822
|
+
if (!isRecord(data) || !Array.isArray(data.rows))
|
|
823
|
+
return data;
|
|
824
|
+
return paginateRows(data.rows, args.limit, cursorArg(args));
|
|
825
|
+
},
|
|
826
|
+
},
|
|
827
|
+
{
|
|
828
|
+
name: "get_rwa_perp_funding",
|
|
829
|
+
description: "Get funding and carry for real-world-asset perpetuals (RWA perps: stocks, pre-IPO, ETFs, indices, commodities, FX) across 19 venues: CEXs (Binance, Bybit, OKX, Bitget, Gate, Kraken xStocks, Coinbase INTX), perp DEXs (Aster, Lighter, Extended, GRVT, ApeX, Pacifica, Orderly), Hyperliquid HIP-3 builder markets, and the rollover venues Ostium and Avantis. Rates are interval-true and mechanism-true: funding_apr annualizes each venue's own settlement interval (never an assumed 8h), and a both-sides rollover is reported separately as borrow_apr_annual (a cost, never mixed into funding spreads). Marks more than 2% off the cross-venue median are flagged is_price_suspect and excluded from stats and spreads. type=history returns session-tagged settlements (market/after_hours/weekend/holiday); type=stats returns best carry, top cross-venue spread, weekend premium, and open interest.",
|
|
830
|
+
schema: rwaPerpRatesSchema,
|
|
831
|
+
apiPath: "/api/v1/rwa-perps/rates",
|
|
832
|
+
fallbackPath: "/api/rwa-perps/rates",
|
|
833
|
+
// The free route returns current/history rows as a bare array and
|
|
834
|
+
// ignores limit/cursor; page it the way v1 does. type=stats is an object
|
|
835
|
+
// and passes through.
|
|
836
|
+
postProcess: (data, args, context) => {
|
|
837
|
+
if (context?.paginated || typeof args.limit !== "number")
|
|
838
|
+
return data;
|
|
839
|
+
if (!Array.isArray(data))
|
|
840
|
+
return data;
|
|
841
|
+
return paginateRows(data, args.limit, cursorArg(args));
|
|
842
|
+
},
|
|
843
|
+
},
|
|
577
844
|
{
|
|
578
845
|
name: "get_funding_rates",
|
|
579
|
-
description: "Get perpetual funding rates across
|
|
846
|
+
description: "Get perpetual funding rates across every supported venue (see sharpe://exchanges for the current list). Returns current snapshots, accumulated rates over multiple windows, or per-coin historical rates. Units: `rate` is a decimal fraction settled over that row's own `interval_hours` (1h, 2h, 4h, 8h or 24h depending on venue and market). It is not a percent and never implicitly 8h, so annualize with rate * (8760 / interval_hours) before comparing or ranking venues. Accumulated rows carry realized sums (acc_1d/acc_7d/acc_30d/acc_90d/acc_1y) instead of a per-interval rate. Filter with coin, exchange, margin (linear/inverse) and asset_class; asset_class is unfiltered by default, so tokenized-equity, commodity, index and FX perps are included alongside crypto. `coin` names an asset: PEPE returns every PEPE contract, the 1000PEPE and KPEPE lot contracts included. Current and accumulated rows carry asset_id, asset_symbol, lot_multiplier (asset units per contract unit, e.g. 1000 on 1000PEPEUSDT), instrument_status (the venue's own status) and is_live (null = unknown). Page the full book with limit and cursor.",
|
|
580
847
|
schema: fundingRatesSchema,
|
|
581
848
|
apiPath: "/api/v1/funding/rates",
|
|
582
849
|
fallbackPath: "/api/funding/rates",
|
|
583
|
-
// The
|
|
584
|
-
//
|
|
585
|
-
//
|
|
850
|
+
// The unpaged book is ~13,000 rows (6MB) of which MAX_ITEMS survive
|
|
851
|
+
// truncation: page it server-side instead, so the rows come with a cursor
|
|
852
|
+
// (0.3s instead of 1.8s, 2026-09-26). A coin filter or history is small.
|
|
853
|
+
prepareArgs: (args) => args.limit == null && args.coin == null && args.type !== "history"
|
|
854
|
+
? { ...args, limit: MAX_ITEMS }
|
|
855
|
+
: args,
|
|
856
|
+
// Both funding endpoints narrow by `coin` server-side. This client-side
|
|
857
|
+
// pass is a belt-and-braces guard so a coin-scoped request can never be
|
|
858
|
+
// reduced to an arbitrary alphabetical prefix by MAX_ITEMS truncation.
|
|
586
859
|
postProcess: (data, args) => {
|
|
587
860
|
const coin = args.coin;
|
|
588
861
|
const type = args.type;
|
|
@@ -592,43 +865,85 @@ export const TOOL_DEFS = [
|
|
|
592
865
|
if (!Array.isArray(data)) {
|
|
593
866
|
return data;
|
|
594
867
|
}
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
868
|
+
return rowsForFundingCoin(data, coin);
|
|
869
|
+
},
|
|
870
|
+
},
|
|
871
|
+
{
|
|
872
|
+
name: "get_funding_settlement",
|
|
873
|
+
description: "Get the dollar value of funding actually paid at each settlement -- not just the rate -- and which side, longs or shorts, paid it. Every response carries both the per-coin row breakdown and a totals block (net/long_paid/short_paid) for the requested window and class, so 'who paid funding today' is read directly from totals rather than summed from a page of rows; totals always reflects the full requested class regardless of any coin/exchange filter on the rows. window=current (the default) is the next settlement, priced live off open interest and the forward-looking rate -- always estimated, never realised. 1d/3d/7d are realised windows; one whose coverage is below 90% carries partial: true because its history is still accruing, not a completed total. Sign convention: a window's net = long_paid - short_paid; positive means longs paid more than they received (a cost to longs), negative means shorts paid more. Both long_paid and short_paid are always non-negative magnitudes. Missing is null, never 0. class splits crypto perps from RWA perps (tokenized equity, commodity, FX, index); crypto + rwa totals always equal the all totals.",
|
|
874
|
+
schema: fundingSettlementSchema,
|
|
875
|
+
apiPath: "/api/v1/funding/settlement",
|
|
876
|
+
fallbackPath: "/api/funding/settlement",
|
|
877
|
+
// The v1 payload nests rows/totals/settlementMeta inside the envelope's
|
|
878
|
+
// `data` field; the free fallback puts the row array directly under
|
|
879
|
+
// `data` with `totals` riding alongside it (api-client.ts preserves that
|
|
880
|
+
// sibling instead of discarding it). Normalize both shapes into one
|
|
881
|
+
// `{ rows, totals, meta }` result so callers never branch on which tier
|
|
882
|
+
// answered, and `totals` is always the API's own aggregate -- never
|
|
883
|
+
// recomputed from a possibly-truncated page of rows.
|
|
884
|
+
postProcess: (data) => {
|
|
885
|
+
if (!data || typeof data !== "object" || Array.isArray(data)) {
|
|
886
|
+
return data;
|
|
887
|
+
}
|
|
888
|
+
const obj = data;
|
|
889
|
+
const result = {
|
|
890
|
+
rows: obj.rows ?? obj.data,
|
|
891
|
+
totals: obj.totals,
|
|
892
|
+
};
|
|
893
|
+
const meta = obj.settlementMeta ?? obj.meta;
|
|
894
|
+
if (meta !== undefined)
|
|
895
|
+
result.meta = meta;
|
|
896
|
+
return result;
|
|
599
897
|
},
|
|
600
898
|
},
|
|
601
899
|
{
|
|
602
900
|
name: "get_futures_data",
|
|
603
|
-
description: "Get futures chart data including open interest, volume, funding rate history, liquidations, long/short ratios, basis, term structure, and OHLCV.",
|
|
901
|
+
description: "Get futures chart data including open interest, volume, funding rate history, liquidations, long/short ratios, basis, term structure, and OHLCV. Time series are oldest-first; when one exceeds the response cap its newest rows are kept (truncated_fields marks kept: latest). Without limit, oi-snapshot returns each exchange's latest reading; pass limit/cursor to page raw rows oldest-first.",
|
|
604
902
|
schema: futuresDataSchema,
|
|
605
903
|
apiPath: "/api/v1/futures/data",
|
|
606
904
|
fallbackPath: "/api/futures/data",
|
|
905
|
+
postProcess: (data, args, context) => {
|
|
906
|
+
if (context?.paginated || !isRecord(data) || !Array.isArray(data.data)) {
|
|
907
|
+
return data;
|
|
908
|
+
}
|
|
909
|
+
if (typeof args.limit === "number") {
|
|
910
|
+
// The free route ignores limit/cursor: page the same oldest-first
|
|
911
|
+
// rows v1 pages.
|
|
912
|
+
return {
|
|
913
|
+
...data,
|
|
914
|
+
...paginateRows(data.data, args.limit, cursorArg(args)),
|
|
915
|
+
};
|
|
916
|
+
}
|
|
917
|
+
if (args.chart === "oi-snapshot") {
|
|
918
|
+
return { ...data, data: latestRowPerExchange(data.data) };
|
|
919
|
+
}
|
|
920
|
+
return data;
|
|
921
|
+
},
|
|
607
922
|
},
|
|
608
923
|
{
|
|
609
924
|
name: "get_futures_coins",
|
|
610
|
-
description: "Get
|
|
925
|
+
description: "Get up to 1,000 coins with futures data, including funding, open-interest, liquidation, long/short, CVD, and dated-basis capability flags plus observed venue coverage and market-cap rank.",
|
|
611
926
|
schema: futuresCoinsSchema,
|
|
612
927
|
apiPath: "/api/v1/futures/coins",
|
|
613
928
|
fallbackPath: "/api/futures/coins",
|
|
614
929
|
},
|
|
615
930
|
{
|
|
616
931
|
name: "get_correlation_matrix",
|
|
617
|
-
description: "Get a price correlation matrix for crypto assets over a specified period. Useful for portfolio analysis and diversification.",
|
|
932
|
+
description: "Get a price correlation matrix for crypto and supported TradFi assets over a specified calendar period. Useful for portfolio analysis and diversification.",
|
|
618
933
|
schema: correlationMatrixSchema,
|
|
619
934
|
apiPath: "/api/v1/correlation/matrix",
|
|
620
935
|
fallbackPath: "/api/correlation/matrix",
|
|
621
936
|
},
|
|
622
937
|
{
|
|
623
938
|
name: "get_arbitrage_spot_perp",
|
|
624
|
-
description: "Get
|
|
939
|
+
description: "Get structurally executable spot-perpetual funding-capture rows with live funding, verified spot or margin availability, diagnostic basis, gross APR, and fee-adjusted net APR.",
|
|
625
940
|
schema: arbitrageSpotPerpSchema,
|
|
626
941
|
apiPath: "/api/v1/arbitrage/spot-perp",
|
|
627
942
|
fallbackPath: "/api/arbitrage/spot-perp",
|
|
628
943
|
},
|
|
629
944
|
{
|
|
630
945
|
name: "get_arbitrage_cross_exchange",
|
|
631
|
-
description: "Get cross-exchange
|
|
946
|
+
description: "Get cross-exchange funding arbitrage across every funding venue and asset class (crypto plus RWA perps: equity, commodity, FX, index — pairs never cross classes), ranked with executable rows (book-priced netApr) first by netApr, then indicative rows by gross annualized funding differential (apr); pairs whose two legs' prices differ by more than 20% are indicative (likely different instruments). Spread uses real books where available (spreadSource: book) or reference prices (reference); netApr is present only on book-priced rows; unknown spread/OI/volume are null, never zero.",
|
|
632
947
|
schema: arbitrageCrossExchangeSchema,
|
|
633
948
|
apiPath: "/api/v1/arbitrage/cross-exchange",
|
|
634
949
|
fallbackPath: "/api/arbitrage/cross-exchange",
|
|
@@ -656,35 +971,21 @@ export const TOOL_DEFS = [
|
|
|
656
971
|
},
|
|
657
972
|
{
|
|
658
973
|
name: "get_arbitrage_cex_spot_transfer",
|
|
659
|
-
description: "Get live CEX spot-transfer arbitrage rows after common network, fee, status, depth, slippage, and spread-lifetime checks.",
|
|
974
|
+
description: "Get live CEX spot-transfer arbitrage rows after common network and token-contract matching, fee, status, depth, slippage, and spread-lifetime checks.",
|
|
660
975
|
schema: cexSpotTransferScannerSchema,
|
|
661
976
|
apiPath: "/api/v1/arbitrage/cex-spot-transfer",
|
|
662
977
|
fallbackPath: "/api/arbitrage/cex-spot-transfer",
|
|
663
978
|
},
|
|
664
979
|
{
|
|
665
980
|
name: "get_heatmap",
|
|
666
|
-
description: "Get market heatmap data for coins, narratives, or ecosystems.
|
|
981
|
+
description: "Get market heatmap data for coins, narratives, or ecosystems. The legacy top-100 slug returns the Top 50 universe; aggregate modes expose complete or partial category coverage.",
|
|
667
982
|
schema: heatmapSchema,
|
|
668
983
|
apiPath: "/api/v1/heatmap/data",
|
|
669
984
|
fallbackPath: "/api/heatmap/data",
|
|
670
985
|
},
|
|
671
|
-
{
|
|
672
|
-
name: "get_dexscreener_data",
|
|
673
|
-
description: "Get live DEX Screener rows by category, network, or search phrase. Use this for pair-level discovery across DEX markets. Requires API key (SHARPE_API_KEY) — not available on the free tier.",
|
|
674
|
-
schema: dexScreenerDataSchema,
|
|
675
|
-
apiPath: "/api/v1/dexscreener/data",
|
|
676
|
-
fallbackPath: "/api/v1/dexscreener/data",
|
|
677
|
-
},
|
|
678
|
-
{
|
|
679
|
-
name: "get_dexscreener_security",
|
|
680
|
-
description: "Get token contract security signals for a DEX Screener token by address and chain ID.",
|
|
681
|
-
schema: dexScreenerSecuritySchema,
|
|
682
|
-
apiPath: "/api/v1/dexscreener/security",
|
|
683
|
-
fallbackPath: "/api/dexscreener/security",
|
|
684
|
-
},
|
|
685
986
|
{
|
|
686
987
|
name: "get_token_scanner",
|
|
687
|
-
description: "Run read-only token scanner modes
|
|
988
|
+
description: "Run read-only token scanner modes for hot tokens, new runners, alpha drops, AI tokens, and top-new pairs. Responses expose source coverage; valuation and risk fields stay null when unavailable. Requires an API key (SHARPE_API_KEY; the free tier works). No keyless fallback.",
|
|
688
989
|
schema: tokenScannerSchema,
|
|
689
990
|
apiPath: "/api/v1/token-scanner/scan",
|
|
690
991
|
fallbackPath: "/api/v1/token-scanner/scan",
|
|
@@ -726,14 +1027,14 @@ export const TOOL_DEFS = [
|
|
|
726
1027
|
},
|
|
727
1028
|
{
|
|
728
1029
|
name: "get_memecoin_launches",
|
|
729
|
-
description: "Get recently launched memecoin
|
|
1030
|
+
description: "Get recently launched tokens from recognized memecoin launchpads, screened by age, liquidity, volume, and transactions. Generic new DEX pairs are excluded; response includes complete/partial chain coverage.",
|
|
730
1031
|
schema: memecoinLaunchesSchema,
|
|
731
1032
|
apiPath: "/api/v1/memecoins/launches",
|
|
732
1033
|
fallbackPath: "/api/memecoins/launches",
|
|
733
1034
|
},
|
|
734
1035
|
{
|
|
735
1036
|
name: "get_stablecoins",
|
|
736
|
-
description: "Get stablecoin overview, detail, or yield data including
|
|
1037
|
+
description: "Get stablecoin overview, detail, or yield data including nominal supply at peg, marked value, nullable peg metrics, mechanism mix, chain supply, velocity coverage, freshness, and APY risk flags. Requires an API key (SHARPE_API_KEY; the free tier works). No keyless fallback.",
|
|
737
1038
|
schema: stablecoinsSchema,
|
|
738
1039
|
apiPath: "/api/v1/stablecoins/data",
|
|
739
1040
|
fallbackPath: "/api/v1/stablecoins/data",
|
|
@@ -747,63 +1048,65 @@ export const TOOL_DEFS = [
|
|
|
747
1048
|
},
|
|
748
1049
|
{
|
|
749
1050
|
name: "get_web_traffic",
|
|
750
|
-
description: "Get attention rankings,
|
|
1051
|
+
description: "Get attention rankings, social snapshots, or market-level signals for coins and narratives, plus CoinGecko trust-score rankings for exchanges.",
|
|
751
1052
|
schema: webTrafficSchema,
|
|
752
1053
|
apiPath: "/api/v1/web-traffic/data",
|
|
753
1054
|
fallbackPath: "/api/web-traffic/data",
|
|
754
1055
|
},
|
|
755
|
-
{
|
|
756
|
-
name: "get_katana",
|
|
757
|
-
description: "Get Katana Network TVL, token, holder, sentiment, pool, mover, and ecosystem analytics.",
|
|
758
|
-
schema: katanaSchema,
|
|
759
|
-
apiPath: "/api/v1/katana/data",
|
|
760
|
-
fallbackPath: "/api/products/katana/data",
|
|
761
|
-
},
|
|
762
1056
|
{
|
|
763
1057
|
name: "get_news",
|
|
764
|
-
description: "Get aggregated crypto news articles from multiple sources, with optional filtering by category or coin. Articles are deduplicated so only the best source per story is shown.",
|
|
1058
|
+
description: "Get aggregated crypto news articles from multiple sources, with optional title search and filtering by category or coin. Articles are deduplicated so only the best source per story is shown.",
|
|
765
1059
|
schema: newsSchema,
|
|
766
1060
|
apiPath: "/api/v1/news/feed",
|
|
767
1061
|
fallbackPath: "/api/news/feed",
|
|
768
1062
|
},
|
|
769
|
-
{
|
|
770
|
-
name: "get_curated_news",
|
|
771
|
-
description: "Get AI-curated crypto news highlights across crypto, AI, markets, and geopolitics. Updated every 15 minutes.",
|
|
772
|
-
schema: curatedNewsSchema,
|
|
773
|
-
apiPath: "/api/v1/news/curated",
|
|
774
|
-
fallbackPath: "/api/news/curated",
|
|
775
|
-
},
|
|
776
1063
|
{
|
|
777
1064
|
name: "get_market_overview",
|
|
778
|
-
description: "Get
|
|
1065
|
+
description: "Get BTC and ETH price/change, total crypto market cap and 24h volume, BTC dominance, market-cap change, and the Fear & Greed Index. Auxiliary source fields may be null when unavailable.",
|
|
779
1066
|
schema: marketOverviewSchema,
|
|
780
1067
|
apiPath: "/api/v1/tracker/market-overview",
|
|
781
1068
|
fallbackPath: "/api/tracker/market-overview",
|
|
782
1069
|
},
|
|
783
1070
|
{
|
|
784
1071
|
name: "get_price_prediction",
|
|
785
|
-
description: "Get
|
|
1072
|
+
description: "Get deterministic directional scores and sub-signal breakdowns for a coin. Optional 7D/30D values are volatility-scaled heuristic scenarios, not calibrated targets or probabilities.",
|
|
786
1073
|
schema: pricePredictionSchema,
|
|
787
1074
|
apiPath: "/api/v1/price-prediction/data",
|
|
788
1075
|
fallbackPath: "/api/price-prediction/data",
|
|
789
1076
|
},
|
|
790
1077
|
{
|
|
791
1078
|
name: "search_market_cap",
|
|
792
|
-
description: "Search
|
|
1079
|
+
description: "Search crypto and supported TradFi assets by name or ticker. Returns matching assets with asset class, market cap, and nullable price, 24h change, FDV, ATH, and estimated ATH market cap fields.",
|
|
793
1080
|
schema: searchMarketCapSchema,
|
|
794
1081
|
apiPath: "/api/v1/market-cap/search",
|
|
795
1082
|
fallbackPath: "/api/market-cap/search",
|
|
796
1083
|
},
|
|
797
1084
|
{
|
|
798
1085
|
name: "get_gem_finder",
|
|
799
|
-
description: "Get
|
|
1086
|
+
description: "Get market-ranked token rows with market cap, volume, price and market-cap change, circulating supply, ATH and ATL history, nullable FDV/MCap, the preferred chain plus every supported chain the asset is deployed on (chainSlugs), observed exchange availability, quote freshness, and enrichment coverage. Delisted or halted markets whose upstream quote is over 24 hours old are excluded rather than reporting a weeks-old price change as current. Ambiguous same-ticker assets do not receive symbol-only exchange attribution. No wallet signal or proprietary score is returned.",
|
|
800
1087
|
schema: gemFinderSchema,
|
|
801
1088
|
apiPath: "/api/v1/gem-finder/data",
|
|
802
1089
|
fallbackPath: "/api/gem-finder/data",
|
|
1090
|
+
postProcess: (data, args) => {
|
|
1091
|
+
// Authenticated v1 calls are already an array with pagination reattached
|
|
1092
|
+
// by the runtime. The free fallback returns the complete cache payload,
|
|
1093
|
+
// so apply the same snapshot-bound paging semantics client-side.
|
|
1094
|
+
if (!data ||
|
|
1095
|
+
typeof data !== "object" ||
|
|
1096
|
+
Array.isArray(data) ||
|
|
1097
|
+
!Array.isArray(data.coins)) {
|
|
1098
|
+
return data;
|
|
1099
|
+
}
|
|
1100
|
+
const limit = typeof args.limit === "number" && Number.isInteger(args.limit)
|
|
1101
|
+
? args.limit
|
|
1102
|
+
: 100;
|
|
1103
|
+
const cursor = typeof args.cursor === "string" ? args.cursor : undefined;
|
|
1104
|
+
return paginateSnapshotPayload(data, limit, cursor);
|
|
1105
|
+
},
|
|
803
1106
|
},
|
|
804
1107
|
{
|
|
805
1108
|
name: "get_derivatives_overview",
|
|
806
|
-
description: "Get a derivatives market overview including aggregated open interest, funding rates,
|
|
1109
|
+
description: "Get a derivatives market overview including aggregated open interest, 8-hour-equivalent funding rates, top coins by open interest, and exchange/coin counts. Requires an API key (SHARPE_API_KEY; the free tier works). No keyless fallback.",
|
|
807
1110
|
schema: derivativesOverviewSchema,
|
|
808
1111
|
apiPath: "/api/v1/market/derivatives-overview",
|
|
809
1112
|
fallbackPath: "/api/v1/market/derivatives-overview",
|
|
@@ -817,21 +1120,21 @@ export const TOOL_DEFS = [
|
|
|
817
1120
|
},
|
|
818
1121
|
{
|
|
819
1122
|
name: "get_exchange_listings",
|
|
820
|
-
description: "Get the New Listings hub payload
|
|
1123
|
+
description: "Get the New Listings hub payload: weekly + monthly aggregated counts by narrative and exchange, plus the last-90-day recent listings. Optionally filter by narrative slug or single exchange. Useful for tracking where venues are adding listing slots.",
|
|
821
1124
|
schema: listingsDataSchema,
|
|
822
1125
|
apiPath: "/api/v1/listings/data",
|
|
823
1126
|
fallbackPath: "/api/listings/data",
|
|
824
1127
|
},
|
|
825
1128
|
{
|
|
826
1129
|
name: "get_recent_listings",
|
|
827
|
-
description: "Get a flat feed of recent token listings. Defaults remain backward-compatible with the legacy spot listing feed
|
|
1130
|
+
description: "Get a flat feed of recent token listings. Defaults remain backward-compatible with the legacy spot listing feed. Event filters add source-observation freshness, partial status, and provider coverage so agents can reject incomplete opportunity scans.",
|
|
828
1131
|
schema: listingsRecentSchema,
|
|
829
1132
|
apiPath: "/api/v1/listings/recent",
|
|
830
1133
|
fallbackPath: "/api/listings/recent",
|
|
831
1134
|
},
|
|
832
1135
|
{
|
|
833
1136
|
name: "get_listing_events",
|
|
834
|
-
description: "Get canonical listing lifecycle events across CEXs and Perp DEXs, including
|
|
1137
|
+
description: "Get canonical listing lifecycle events across CEXs and Perp DEXs, including source URLs, confidence, real source-observation freshness, partial status, and per-provider coverage. Pass the opaque cursor through unchanged.",
|
|
835
1138
|
schema: listingsEventsSchema,
|
|
836
1139
|
apiPath: "/api/v1/listings/events",
|
|
837
1140
|
fallbackPath: "/api/listings/events",
|
|
@@ -845,17 +1148,19 @@ export const TOOL_DEFS = [
|
|
|
845
1148
|
},
|
|
846
1149
|
{
|
|
847
1150
|
name: "get_insider_selling",
|
|
848
|
-
description: "Get insider selling pressure signals across crypto assets. Scores require cross-venue negative funding and combine OI, basis, CVD, sell-side flow, and supporting wallet/supply context.",
|
|
1151
|
+
description: "Get insider selling pressure signals across crypto assets. Scores require cross-venue negative funding and combine OI, basis, CVD, sell-side flow, and supporting wallet/supply context; read signal_coverage_pct because partial-input scores are conservative lower bounds.",
|
|
849
1152
|
schema: signalScoreSchema,
|
|
850
1153
|
apiPath: "/api/v1/insider-selling/data",
|
|
851
1154
|
fallbackPath: "/api/insider-selling/data",
|
|
1155
|
+
postProcess: filterSignalScores,
|
|
852
1156
|
},
|
|
853
1157
|
{
|
|
854
1158
|
name: "get_pump_dump",
|
|
855
|
-
description: "Get pump-and-dump manipulation risk signals across crypto assets. Scores combine derivatives pressure, holder concentration, liquidity quality, DEX flow, and price behavior.",
|
|
1159
|
+
description: "Get pump-and-dump manipulation risk signals across crypto assets. Scores combine derivatives pressure, holder concentration, liquidity quality, DEX flow, and price behavior; read signal_coverage_pct because partial-input scores are conservative lower bounds.",
|
|
856
1160
|
schema: pumpDumpSchema,
|
|
857
1161
|
apiPath: "/api/v1/pump-dump/data",
|
|
858
1162
|
fallbackPath: "/api/pump-dump/data",
|
|
1163
|
+
postProcess: filterSignalScores,
|
|
859
1164
|
},
|
|
860
1165
|
];
|
|
861
1166
|
//# sourceMappingURL=tools.js.map
|