@aicoin/opendata-mcp 1.0.28 → 2.0.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 +153 -165
- package/build/index.js +978 -2249
- package/package.json +1 -1
package/build/index.js
CHANGED
|
@@ -44,7 +44,7 @@ Endpoint: ${path}`;
|
|
|
44
44
|
}
|
|
45
45
|
throw new Error(msg);
|
|
46
46
|
}
|
|
47
|
-
var BIZ_AUTH_CODES = /* @__PURE__ */ new Set([
|
|
47
|
+
var BIZ_AUTH_CODES = /* @__PURE__ */ new Set([403, 401, 304]);
|
|
48
48
|
function checkBizError(data, path) {
|
|
49
49
|
if (!data || typeof data !== "object") return;
|
|
50
50
|
const obj = data;
|
|
@@ -329,2410 +329,1225 @@ function err(e) {
|
|
|
329
329
|
// src/tools/coins.ts
|
|
330
330
|
function registerCoinTools(server2) {
|
|
331
331
|
server2.tool(
|
|
332
|
-
"
|
|
333
|
-
"
|
|
334
|
-
{ ...maxItemsParam },
|
|
335
|
-
async ({ _max_items }) => {
|
|
336
|
-
try {
|
|
337
|
-
return okList(
|
|
338
|
-
await apiGet("/api/v2/coin"),
|
|
339
|
-
parseMax(_max_items, 100)
|
|
340
|
-
);
|
|
341
|
-
} catch (e) {
|
|
342
|
-
return err(e);
|
|
343
|
-
}
|
|
344
|
-
}
|
|
345
|
-
);
|
|
346
|
-
server2.tool(
|
|
347
|
-
"get_coin_ticker",
|
|
348
|
-
"Get real-time ticker data for coins (price, change, volume)",
|
|
349
|
-
{
|
|
350
|
-
coin_list: z2.string().describe("Coin keys, comma-separated, e.g. bitcoin,ethereum")
|
|
351
|
-
},
|
|
352
|
-
async ({ coin_list }) => {
|
|
353
|
-
try {
|
|
354
|
-
return ok(
|
|
355
|
-
await apiGet("/api/v2/coin/ticker", { coin_list })
|
|
356
|
-
);
|
|
357
|
-
} catch (e) {
|
|
358
|
-
return err(e);
|
|
359
|
-
}
|
|
360
|
-
}
|
|
361
|
-
);
|
|
362
|
-
server2.tool(
|
|
363
|
-
"get_coin_config",
|
|
364
|
-
"Get coin profile/description data",
|
|
365
|
-
{
|
|
366
|
-
coin_list: z2.string().describe(
|
|
367
|
-
"Coin keys, comma-separated, max 100, e.g. bitcoin,ethereum"
|
|
368
|
-
)
|
|
369
|
-
},
|
|
370
|
-
async ({ coin_list }) => {
|
|
371
|
-
try {
|
|
372
|
-
return ok(
|
|
373
|
-
await apiGet("/api/v2/coin/config", { coin_list })
|
|
374
|
-
);
|
|
375
|
-
} catch (e) {
|
|
376
|
-
return err(e);
|
|
377
|
-
}
|
|
378
|
-
}
|
|
379
|
-
);
|
|
380
|
-
server2.tool(
|
|
381
|
-
"get_ai_coin_analysis",
|
|
382
|
-
"Get AI interpretation and prediction for coins",
|
|
383
|
-
{
|
|
384
|
-
coin_keys: z2.string().describe('Coin keys JSON array, e.g. ["bitcoin","ethereum"]'),
|
|
385
|
-
language: z2.enum(["CN", "EN", "TC"]).optional().describe("Language: CN/EN/TC, default CN")
|
|
386
|
-
},
|
|
387
|
-
async ({ coin_keys, language }) => {
|
|
388
|
-
try {
|
|
389
|
-
const body = {
|
|
390
|
-
coinKeys: JSON.parse(coin_keys)
|
|
391
|
-
};
|
|
392
|
-
if (language) body.language = language;
|
|
393
|
-
return ok(
|
|
394
|
-
await apiPost("/api/v2/content/ai-coins", body)
|
|
395
|
-
);
|
|
396
|
-
} catch (e) {
|
|
397
|
-
return err(e);
|
|
398
|
-
}
|
|
399
|
-
}
|
|
400
|
-
);
|
|
401
|
-
server2.tool(
|
|
402
|
-
"get_funding_rate_history",
|
|
403
|
-
"Get funding rate history",
|
|
404
|
-
{
|
|
405
|
-
symbol: z2.string().describe(
|
|
406
|
-
"Trading pair, e.g. btcswapusdt:okcoinfutures"
|
|
407
|
-
),
|
|
408
|
-
interval: z2.string().describe(
|
|
409
|
-
"Interval: 5m,15m,30m,8h (recommended). 1h,4h,1d may return empty data"
|
|
410
|
-
),
|
|
411
|
-
limit: z2.string().optional().describe("Number of records, default 100"),
|
|
412
|
-
start_time: z2.string().optional().describe("Start time in ms"),
|
|
413
|
-
end_time: z2.string().optional().describe("End time in ms")
|
|
414
|
-
},
|
|
415
|
-
async ({ symbol, interval, limit, start_time, end_time }) => {
|
|
416
|
-
try {
|
|
417
|
-
const params = {
|
|
418
|
-
symbol,
|
|
419
|
-
interval
|
|
420
|
-
};
|
|
421
|
-
params.limit = limit ?? "100";
|
|
422
|
-
if (start_time) params.start_time = start_time;
|
|
423
|
-
if (end_time) params.end_time = end_time;
|
|
424
|
-
return ok(
|
|
425
|
-
await apiGet(
|
|
426
|
-
"/api/upgrade/v2/futures/funding-rate/history",
|
|
427
|
-
params
|
|
428
|
-
)
|
|
429
|
-
);
|
|
430
|
-
} catch (e) {
|
|
431
|
-
return err(e);
|
|
432
|
-
}
|
|
433
|
-
}
|
|
434
|
-
);
|
|
435
|
-
server2.tool(
|
|
436
|
-
"get_liquidation_map",
|
|
437
|
-
"Get liquidation heatmap data",
|
|
332
|
+
"coin_info",
|
|
333
|
+
"Coin data.\n\u2022 list \u2014 all coins, no params needed\n\u2022 ticker \u2014 real-time prices. Requires: coin_list\n\u2022 config \u2014 coin profiles. Requires: coin_list\n\u2022 ai_analysis \u2014 AI predictions. Requires: coin_keys (JSON array string)",
|
|
438
334
|
{
|
|
439
|
-
|
|
440
|
-
"
|
|
441
|
-
),
|
|
442
|
-
cycle: z2.string().describe("Cycle: 24h or 7d"),
|
|
443
|
-
leverage: z2.string().optional().describe(
|
|
444
|
-
"Leverage filter: 10,25,50,100 (empty=all)"
|
|
335
|
+
action: z2.enum(["list", "ticker", "config", "ai_analysis"]).describe(
|
|
336
|
+
"list: top coins; ticker: real-time prices; config: coin profiles; ai_analysis: AI predictions"
|
|
445
337
|
),
|
|
338
|
+
coin_list: z2.string().optional().describe('REQUIRED for ticker, config. Comma-separated coin keys, e.g. "bitcoin,ethereum". NOT used by ai_analysis'),
|
|
339
|
+
coin_keys: z2.string().optional().describe(`REQUIRED for ai_analysis. JSON array string, e.g. '["bitcoin","ethereum"]'. NOT used by ticker/config`),
|
|
340
|
+
language: z2.enum(["CN", "EN", "TC"]).optional().describe("Optional for ai_analysis: response language, default CN"),
|
|
446
341
|
...maxItemsParam
|
|
447
342
|
},
|
|
448
|
-
async ({
|
|
449
|
-
try {
|
|
450
|
-
const params = {
|
|
451
|
-
dbkey,
|
|
452
|
-
cycle
|
|
453
|
-
};
|
|
454
|
-
if (leverage) params.leverage = leverage;
|
|
455
|
-
return okList(
|
|
456
|
-
await apiGet(
|
|
457
|
-
"/api/upgrade/v2/futures/liquidation/map",
|
|
458
|
-
params
|
|
459
|
-
),
|
|
460
|
-
parseMax(_max_items, 50)
|
|
461
|
-
);
|
|
462
|
-
} catch (e) {
|
|
463
|
-
return err(e);
|
|
464
|
-
}
|
|
465
|
-
}
|
|
466
|
-
);
|
|
467
|
-
server2.tool(
|
|
468
|
-
"get_weighted_funding_rate_history",
|
|
469
|
-
"Get volume-weighted funding rate history",
|
|
470
|
-
{
|
|
471
|
-
symbol: z2.string().describe("Symbol, e.g. btcswapusdt"),
|
|
472
|
-
interval: z2.string().describe(
|
|
473
|
-
"Interval: 5m,15m,30m,8h (recommended). 1h,4h,1d may return empty data"
|
|
474
|
-
),
|
|
475
|
-
limit: z2.string().optional().describe("Number of records, default 100"),
|
|
476
|
-
start_time: z2.string().optional().describe("Start time in ms"),
|
|
477
|
-
end_time: z2.string().optional().describe("End time in ms")
|
|
478
|
-
},
|
|
479
|
-
async ({ symbol, interval, limit, start_time, end_time }) => {
|
|
480
|
-
try {
|
|
481
|
-
const params = {
|
|
482
|
-
symbol,
|
|
483
|
-
interval
|
|
484
|
-
};
|
|
485
|
-
params.limit = limit ?? "100";
|
|
486
|
-
if (start_time) params.start_time = start_time;
|
|
487
|
-
if (end_time) params.end_time = end_time;
|
|
488
|
-
return ok(
|
|
489
|
-
await apiGet(
|
|
490
|
-
"/api/upgrade/v2/futures/funding-rate/vol-weight-history",
|
|
491
|
-
params
|
|
492
|
-
)
|
|
493
|
-
);
|
|
494
|
-
} catch (e) {
|
|
495
|
-
return err(e);
|
|
496
|
-
}
|
|
497
|
-
}
|
|
498
|
-
);
|
|
499
|
-
server2.tool(
|
|
500
|
-
"get_aggregated_stablecoin_oi_history",
|
|
501
|
-
"Get aggregated stablecoin-margined open interest history",
|
|
502
|
-
{
|
|
503
|
-
symbol: z2.string().describe("Coin symbol, e.g. BTC"),
|
|
504
|
-
interval: z2.string().describe("Interval: 1m,2m,15m,30m"),
|
|
505
|
-
limit: z2.string().optional().describe("Number of records, default 100"),
|
|
506
|
-
start_time: z2.string().optional().describe("Start time in ms"),
|
|
507
|
-
end_time: z2.string().optional().describe("End time in ms")
|
|
508
|
-
},
|
|
509
|
-
async ({ symbol, interval, limit, start_time, end_time }) => {
|
|
343
|
+
async ({ action, coin_list, coin_keys, language, _max_items }) => {
|
|
510
344
|
try {
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
"/api/
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
345
|
+
switch (action) {
|
|
346
|
+
case "list":
|
|
347
|
+
return okList(await apiGet("/api/v2/coin"), parseMax(_max_items, 100));
|
|
348
|
+
case "ticker": {
|
|
349
|
+
if (!coin_list) return err("coin_list is required for ticker action");
|
|
350
|
+
return ok(await apiGet("/api/v2/coin/ticker", { coin_list }));
|
|
351
|
+
}
|
|
352
|
+
case "config": {
|
|
353
|
+
if (!coin_list) return err("coin_list is required for config action");
|
|
354
|
+
return ok(await apiGet("/api/v2/coin/config", { coin_list }));
|
|
355
|
+
}
|
|
356
|
+
case "ai_analysis": {
|
|
357
|
+
if (!coin_keys) return err("coin_keys is required for ai_analysis action");
|
|
358
|
+
const body = { coinKeys: JSON.parse(coin_keys) };
|
|
359
|
+
if (language) body.language = language;
|
|
360
|
+
return ok(await apiPost("/api/v2/content/ai-coins", body));
|
|
361
|
+
}
|
|
362
|
+
}
|
|
524
363
|
} catch (e) {
|
|
525
364
|
return err(e);
|
|
526
365
|
}
|
|
527
366
|
}
|
|
528
367
|
);
|
|
529
368
|
server2.tool(
|
|
530
|
-
"
|
|
531
|
-
"
|
|
369
|
+
"coin_funding_rate",
|
|
370
|
+
"Funding rate history.\n\u2022 Default: per-exchange rate. Requires symbol with exchange suffix, e.g. btcswapusdt:binance\n\u2022 weighted=true: volume-weighted rate across exchanges. Symbol WITHOUT exchange suffix, e.g. btcswapusdt",
|
|
532
371
|
{
|
|
533
|
-
symbol: z2.string().describe("
|
|
534
|
-
interval: z2.string().describe("
|
|
372
|
+
symbol: z2.string().describe("REQUIRED. Trading pair. With exchange suffix for normal (e.g. btcswapusdt:binance), WITHOUT suffix for weighted (e.g. btcswapusdt)"),
|
|
373
|
+
interval: z2.string().describe("REQUIRED. Candle interval: 5m, 15m, 30m, 8h (recommended). 1h, 4h, 1d may return empty"),
|
|
374
|
+
weighted: z2.boolean().optional().default(false).describe("Use volume-weighted funding rate"),
|
|
535
375
|
limit: z2.string().optional().describe("Number of records, default 100"),
|
|
536
376
|
start_time: z2.string().optional().describe("Start time in ms"),
|
|
537
377
|
end_time: z2.string().optional().describe("End time in ms")
|
|
538
378
|
},
|
|
539
|
-
async ({ symbol, interval, limit, start_time, end_time }) => {
|
|
540
|
-
try {
|
|
541
|
-
const params = {
|
|
542
|
-
symbol,
|
|
543
|
-
interval
|
|
544
|
-
};
|
|
545
|
-
params.limit = limit ?? "100";
|
|
546
|
-
if (start_time) params.start_time = start_time;
|
|
547
|
-
if (end_time) params.end_time = end_time;
|
|
548
|
-
return ok(
|
|
549
|
-
await apiGet(
|
|
550
|
-
"/api/upgrade/v2/futures/open-interest/aggregated-coin-margin-history",
|
|
551
|
-
params
|
|
552
|
-
)
|
|
553
|
-
);
|
|
554
|
-
} catch (e) {
|
|
555
|
-
return err(e);
|
|
556
|
-
}
|
|
557
|
-
}
|
|
558
|
-
);
|
|
559
|
-
server2.tool(
|
|
560
|
-
"get_liquidation_history",
|
|
561
|
-
"Get liquidation order history",
|
|
562
|
-
{
|
|
563
|
-
symbol: z2.string().describe(
|
|
564
|
-
"Trading pair, e.g. btcswapusdt:binance"
|
|
565
|
-
),
|
|
566
|
-
interval: z2.string().describe("Interval: 1m,2m,15m,30m"),
|
|
567
|
-
limit: z2.string().optional().describe("Number of records, default 10"),
|
|
568
|
-
start_time: z2.string().optional().describe("Start time in ms"),
|
|
569
|
-
end_time: z2.string().optional().describe("End time in ms")
|
|
570
|
-
},
|
|
571
|
-
async ({ symbol, interval, limit, start_time, end_time }) => {
|
|
379
|
+
async ({ symbol, interval, weighted, limit, start_time, end_time }) => {
|
|
572
380
|
try {
|
|
573
|
-
const params = {
|
|
574
|
-
symbol,
|
|
575
|
-
interval
|
|
576
|
-
};
|
|
381
|
+
const params = { symbol, interval };
|
|
577
382
|
params.limit = limit ?? "100";
|
|
578
383
|
if (start_time) params.start_time = start_time;
|
|
579
384
|
if (end_time) params.end_time = end_time;
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
"/api/upgrade/v2/futures/liquidation/history",
|
|
583
|
-
params
|
|
584
|
-
)
|
|
585
|
-
);
|
|
385
|
+
const path = weighted ? "/api/upgrade/v2/futures/funding-rate/vol-weight-history" : "/api/upgrade/v2/futures/funding-rate/history";
|
|
386
|
+
return ok(await apiGet(path, params));
|
|
586
387
|
} catch (e) {
|
|
587
388
|
return err(e);
|
|
588
389
|
}
|
|
589
390
|
}
|
|
590
391
|
);
|
|
591
392
|
server2.tool(
|
|
592
|
-
"
|
|
593
|
-
"
|
|
393
|
+
"coin_liquidation",
|
|
394
|
+
"Liquidation data.\n\u2022 history \u2014 liquidation orders. Requires: symbol + interval\n\u2022 map \u2014 liquidation heatmap. Requires: dbkey + cycle\n\u2022 estimated \u2014 estimated liquidation chart. Requires: dbkey + cycle",
|
|
594
395
|
{
|
|
595
|
-
|
|
596
|
-
"
|
|
597
|
-
),
|
|
598
|
-
cycle: z2.string().describe("Cycle: 24h or 7d"),
|
|
599
|
-
leverage: z2.string().optional().describe(
|
|
600
|
-
"Leverage filter: 10,25,50,100 (empty=all)"
|
|
396
|
+
action: z2.enum(["map", "history", "estimated"]).describe(
|
|
397
|
+
"map: liquidation heatmap; history: liquidation orders; estimated: estimated liquidation chart"
|
|
601
398
|
),
|
|
602
|
-
|
|
399
|
+
symbol: z2.string().optional().describe("REQUIRED for history. Trading pair with exchange, e.g. btcswapusdt:binance. NOT used by map/estimated"),
|
|
400
|
+
dbkey: z2.string().optional().describe("REQUIRED for map, estimated. Trading pair key, e.g. btcswapusdt:binance. NOT used by history"),
|
|
401
|
+
cycle: z2.string().optional().describe('REQUIRED for map, estimated. Time cycle: "24h" or "7d"'),
|
|
402
|
+
leverage: z2.string().optional().describe("Optional for map, estimated. Leverage filter: 10, 25, 50, 100"),
|
|
403
|
+
interval: z2.string().optional().describe("REQUIRED for history. Candle interval: 1m, 2m, 15m, 30m"),
|
|
404
|
+
limit: z2.string().optional().describe("Number of records"),
|
|
603
405
|
start_time: z2.string().optional().describe("Start time in ms"),
|
|
604
406
|
end_time: z2.string().optional().describe("End time in ms"),
|
|
605
407
|
...maxItemsParam
|
|
606
408
|
},
|
|
607
|
-
async ({ dbkey, cycle, leverage, limit, start_time, end_time, _max_items }) => {
|
|
608
|
-
try {
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
async ({ key, limit, start_time, end_time }) => {
|
|
642
|
-
try {
|
|
643
|
-
const params = { key };
|
|
644
|
-
params.limit = limit ?? "100";
|
|
645
|
-
if (start_time) params.start_time = start_time;
|
|
646
|
-
if (end_time) params.end_time = end_time;
|
|
647
|
-
return ok(
|
|
648
|
-
await apiGet(
|
|
649
|
-
"/api/upgrade/v2/futures/historical-depth",
|
|
650
|
-
params
|
|
651
|
-
)
|
|
652
|
-
);
|
|
653
|
-
} catch (e) {
|
|
654
|
-
return err(e);
|
|
655
|
-
}
|
|
656
|
-
}
|
|
657
|
-
);
|
|
658
|
-
server2.tool(
|
|
659
|
-
"get_super_depth_history",
|
|
660
|
-
"Get large order depth history",
|
|
661
|
-
{
|
|
662
|
-
key: z2.string().describe(
|
|
663
|
-
"Trading pair key, e.g. btcswapusdt:okcoinfutures"
|
|
664
|
-
),
|
|
665
|
-
amount: z2.string().optional().describe("USD threshold, default 10000"),
|
|
666
|
-
limit: z2.string().optional().describe("Number of records, max 1000"),
|
|
667
|
-
start_time: z2.string().optional().describe("Start time in ms"),
|
|
668
|
-
end_time: z2.string().optional().describe("End time in ms")
|
|
669
|
-
},
|
|
670
|
-
async ({ key, amount, limit, start_time, end_time }) => {
|
|
671
|
-
try {
|
|
672
|
-
const params = { key };
|
|
673
|
-
params.amount = amount ?? "10000";
|
|
674
|
-
params.limit = limit ?? "100";
|
|
675
|
-
if (start_time) params.start_time = start_time;
|
|
676
|
-
if (end_time) params.end_time = end_time;
|
|
677
|
-
return ok(
|
|
678
|
-
await apiGet(
|
|
679
|
-
"/api/upgrade/v2/futures/super-depth/history",
|
|
680
|
-
params
|
|
681
|
-
)
|
|
682
|
-
);
|
|
683
|
-
} catch (e) {
|
|
684
|
-
return err(e);
|
|
685
|
-
}
|
|
686
|
-
}
|
|
687
|
-
);
|
|
688
|
-
server2.tool(
|
|
689
|
-
"get_trade_data",
|
|
690
|
-
"Get latest trade data for futures",
|
|
691
|
-
{
|
|
692
|
-
dbkey: z2.string().describe(
|
|
693
|
-
"Trading pair key, e.g. btcswapusdt:okcoinfutures"
|
|
694
|
-
),
|
|
695
|
-
limit: z2.string().optional().describe("Number of records, max 1000"),
|
|
696
|
-
start_time: z2.string().optional().describe("Start time in ms"),
|
|
697
|
-
end_time: z2.string().optional().describe("End time in ms")
|
|
698
|
-
},
|
|
699
|
-
async ({ dbkey, limit, start_time, end_time }) => {
|
|
700
|
-
try {
|
|
701
|
-
const params = { dbkey };
|
|
702
|
-
params.limit = limit ?? "100";
|
|
703
|
-
if (start_time) params.start_time = start_time;
|
|
704
|
-
if (end_time) params.end_time = end_time;
|
|
705
|
-
return ok(
|
|
706
|
-
await apiGet(
|
|
707
|
-
"/api/upgrade/v2/futures/trade-data",
|
|
708
|
-
params
|
|
709
|
-
)
|
|
710
|
-
);
|
|
711
|
-
} catch (e) {
|
|
712
|
-
return err(e);
|
|
713
|
-
}
|
|
714
|
-
}
|
|
715
|
-
);
|
|
716
|
-
}
|
|
717
|
-
|
|
718
|
-
// src/tools/contents.ts
|
|
719
|
-
import { z as z3 } from "zod";
|
|
720
|
-
function registerContentTools(server2) {
|
|
721
|
-
server2.tool(
|
|
722
|
-
"get_newsflash",
|
|
723
|
-
"Get latest crypto flash news by AiCoin only",
|
|
724
|
-
{
|
|
725
|
-
language: z3.string().optional().describe("Language: cn, tc, en")
|
|
726
|
-
},
|
|
727
|
-
async ({ language }) => {
|
|
728
|
-
try {
|
|
729
|
-
const params = {};
|
|
730
|
-
if (language) params.language = language;
|
|
731
|
-
return ok(
|
|
732
|
-
await apiGet("/api/v2/content/newsflash", params)
|
|
733
|
-
);
|
|
734
|
-
} catch (e) {
|
|
735
|
-
return err(e);
|
|
736
|
-
}
|
|
737
|
-
}
|
|
738
|
-
);
|
|
739
|
-
server2.tool(
|
|
740
|
-
"get_news_list",
|
|
741
|
-
"Get news article list",
|
|
742
|
-
{
|
|
743
|
-
page: z3.string().optional().describe("Page number, default 1"),
|
|
744
|
-
pageSize: z3.string().optional().describe("Page size, max 20")
|
|
745
|
-
},
|
|
746
|
-
async ({ page, pageSize }) => {
|
|
747
|
-
try {
|
|
748
|
-
const params = {};
|
|
749
|
-
if (page) params.page = page;
|
|
750
|
-
params.pageSize = pageSize ?? "20";
|
|
751
|
-
return ok(
|
|
752
|
-
await apiGet("/api/v2/content/news-list", params)
|
|
753
|
-
);
|
|
754
|
-
} catch (e) {
|
|
755
|
-
return err(e);
|
|
756
|
-
}
|
|
757
|
-
}
|
|
758
|
-
);
|
|
759
|
-
server2.tool(
|
|
760
|
-
"get_news_detail",
|
|
761
|
-
"Get full content of a news article",
|
|
762
|
-
{
|
|
763
|
-
id: z3.string().describe("News article ID")
|
|
764
|
-
},
|
|
765
|
-
async ({ id }) => {
|
|
766
|
-
try {
|
|
767
|
-
return ok(
|
|
768
|
-
await apiGet("/api/v2/content/news-detail", { id })
|
|
769
|
-
);
|
|
770
|
-
} catch (e) {
|
|
771
|
-
return err(e);
|
|
772
|
-
}
|
|
773
|
-
}
|
|
774
|
-
);
|
|
775
|
-
server2.tool(
|
|
776
|
-
"get_rss_news_list",
|
|
777
|
-
"Get RSS news list (dedicated RSS feed)",
|
|
778
|
-
{
|
|
779
|
-
page: z3.string().optional().describe("Page number"),
|
|
780
|
-
pageSize: z3.string().optional().describe("Page size, max 20")
|
|
781
|
-
},
|
|
782
|
-
async ({ page, pageSize }) => {
|
|
783
|
-
try {
|
|
784
|
-
const params = {};
|
|
785
|
-
if (page) params.page = page;
|
|
786
|
-
params.pageSize = pageSize ?? "20";
|
|
787
|
-
return ok(
|
|
788
|
-
await apiGet(
|
|
789
|
-
"/api/v2/content/square/market/news-list",
|
|
790
|
-
params
|
|
791
|
-
)
|
|
792
|
-
);
|
|
793
|
-
} catch (e) {
|
|
794
|
-
return err(e);
|
|
795
|
-
}
|
|
796
|
-
}
|
|
797
|
-
);
|
|
798
|
-
server2.tool(
|
|
799
|
-
"get_flash_list",
|
|
800
|
-
"Get industry flash news (with flash type classification)",
|
|
801
|
-
{
|
|
802
|
-
language: z3.string().optional().describe("Language: cn, tc, en"),
|
|
803
|
-
createtime: z3.string().optional().describe("Filter by create time"),
|
|
804
|
-
...maxItemsParam
|
|
805
|
-
},
|
|
806
|
-
async ({ language, createtime, _max_items }) => {
|
|
807
|
-
try {
|
|
808
|
-
const params = {};
|
|
809
|
-
if (language) params.language = language;
|
|
810
|
-
if (createtime) params.createtime = createtime;
|
|
811
|
-
return okList(
|
|
812
|
-
await apiGet(
|
|
813
|
-
"/api/v2/content/flashList",
|
|
814
|
-
params
|
|
815
|
-
),
|
|
816
|
-
parseMax(_max_items, 30)
|
|
817
|
-
);
|
|
818
|
-
} catch (e) {
|
|
819
|
-
return err(e);
|
|
820
|
-
}
|
|
821
|
-
}
|
|
822
|
-
);
|
|
823
|
-
server2.tool(
|
|
824
|
-
"get_exchange_listing_flash",
|
|
825
|
-
"Get exchange coin listing/delisting news",
|
|
826
|
-
{
|
|
827
|
-
language: z3.string().optional().describe("Language: cn, tc, en"),
|
|
828
|
-
memberIds: z3.string().optional().describe(
|
|
829
|
-
"Exchange member IDs, comma-separated. 477=Binance, 1509=Bitget. Default: 477,1509"
|
|
830
|
-
),
|
|
831
|
-
pageSize: z3.string().optional().describe("Page size, default 20")
|
|
832
|
-
},
|
|
833
|
-
async ({ language, memberIds, pageSize }) => {
|
|
834
|
-
try {
|
|
835
|
-
const params = {};
|
|
836
|
-
if (language) params.language = language;
|
|
837
|
-
if (memberIds) params.memberIds = memberIds;
|
|
838
|
-
if (pageSize) params.pageSize = pageSize;
|
|
839
|
-
return ok(
|
|
840
|
-
await apiGet(
|
|
841
|
-
"/api/v2/content/exchange-listing-flash",
|
|
842
|
-
params
|
|
843
|
-
)
|
|
844
|
-
);
|
|
409
|
+
async ({ action, symbol, dbkey, cycle, leverage, interval, limit, start_time, end_time, _max_items }) => {
|
|
410
|
+
try {
|
|
411
|
+
switch (action) {
|
|
412
|
+
case "map": {
|
|
413
|
+
if (!dbkey || !cycle) return err("dbkey and cycle are required for map action");
|
|
414
|
+
const params = { dbkey, cycle };
|
|
415
|
+
if (leverage) params.leverage = leverage;
|
|
416
|
+
return okList(
|
|
417
|
+
await apiGet("/api/upgrade/v2/futures/liquidation/map", params),
|
|
418
|
+
parseMax(_max_items, 50)
|
|
419
|
+
);
|
|
420
|
+
}
|
|
421
|
+
case "history": {
|
|
422
|
+
if (!symbol || !interval) return err("symbol and interval are required for history action");
|
|
423
|
+
const params = { symbol, interval };
|
|
424
|
+
params.limit = limit ?? "100";
|
|
425
|
+
if (start_time) params.start_time = start_time;
|
|
426
|
+
if (end_time) params.end_time = end_time;
|
|
427
|
+
return ok(await apiGet("/api/upgrade/v2/futures/liquidation/history", params));
|
|
428
|
+
}
|
|
429
|
+
case "estimated": {
|
|
430
|
+
if (!dbkey || !cycle) return err("dbkey and cycle are required for estimated action");
|
|
431
|
+
const params = { dbkey, cycle };
|
|
432
|
+
if (leverage) params.leverage = leverage;
|
|
433
|
+
params.limit = limit ?? "5";
|
|
434
|
+
if (start_time) params.start_time = start_time;
|
|
435
|
+
if (end_time) params.end_time = end_time;
|
|
436
|
+
return okListDeep(
|
|
437
|
+
await apiGet("/api/upgrade/v2/futures/estimated-liquidation/history", params),
|
|
438
|
+
parseMax(_max_items, 5),
|
|
439
|
+
20
|
|
440
|
+
);
|
|
441
|
+
}
|
|
442
|
+
}
|
|
845
443
|
} catch (e) {
|
|
846
444
|
return err(e);
|
|
847
445
|
}
|
|
848
446
|
}
|
|
849
447
|
);
|
|
850
|
-
}
|
|
851
|
-
|
|
852
|
-
// src/tools/markets.ts
|
|
853
|
-
import { z as z4 } from "zod";
|
|
854
|
-
function registerMarketTools(server2) {
|
|
855
448
|
server2.tool(
|
|
856
|
-
"
|
|
857
|
-
"
|
|
449
|
+
"coin_open_interest",
|
|
450
|
+
"Aggregated open interest history. Requires: symbol + interval.\n\u2022 margin_type=stablecoin: stablecoin-margined OI (default)\n\u2022 margin_type=coin: coin-margined OI",
|
|
858
451
|
{
|
|
859
|
-
symbol:
|
|
860
|
-
|
|
861
|
-
)
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
),
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
open_time: z4.string().optional().describe("Open time offset: 0 or 8")
|
|
868
|
-
},
|
|
869
|
-
async ({ symbol, period, size, since, open_time }) => {
|
|
870
|
-
try {
|
|
871
|
-
const params = {
|
|
872
|
-
symbol
|
|
873
|
-
};
|
|
874
|
-
if (period) params.period = period;
|
|
875
|
-
params.size = size ?? "100";
|
|
876
|
-
if (since) params.since = since;
|
|
877
|
-
if (open_time) params.open_time = open_time;
|
|
878
|
-
return ok(
|
|
879
|
-
await apiGet(
|
|
880
|
-
"/api/v2/commonKline/dataRecords",
|
|
881
|
-
params
|
|
882
|
-
)
|
|
883
|
-
);
|
|
884
|
-
} catch (e) {
|
|
885
|
-
return err(e);
|
|
886
|
-
}
|
|
887
|
-
}
|
|
888
|
-
);
|
|
889
|
-
server2.tool(
|
|
890
|
-
"get_market_ticker",
|
|
891
|
-
"Get ticker data for exchange platforms",
|
|
892
|
-
{
|
|
893
|
-
market_list: z4.string().describe(
|
|
894
|
-
"Comma-separated exchange keys, max 100, e.g. okex,binance"
|
|
895
|
-
)
|
|
896
|
-
},
|
|
897
|
-
async ({ market_list }) => {
|
|
898
|
-
try {
|
|
899
|
-
return ok(
|
|
900
|
-
await apiGet("/api/v2/market/ticker", {
|
|
901
|
-
market_list
|
|
902
|
-
})
|
|
903
|
-
);
|
|
904
|
-
} catch (e) {
|
|
905
|
-
return err(e);
|
|
906
|
-
}
|
|
907
|
-
}
|
|
908
|
-
);
|
|
909
|
-
server2.tool(
|
|
910
|
-
"get_markets",
|
|
911
|
-
"Get list of all supported exchange platforms",
|
|
912
|
-
{},
|
|
913
|
-
async () => {
|
|
914
|
-
try {
|
|
915
|
-
return ok(await apiGet("/api/v2/market"));
|
|
916
|
-
} catch (e) {
|
|
917
|
-
return err(e);
|
|
918
|
-
}
|
|
919
|
-
}
|
|
920
|
-
);
|
|
921
|
-
server2.tool(
|
|
922
|
-
"get_futures_interest",
|
|
923
|
-
"Get futures open interest data",
|
|
924
|
-
{
|
|
925
|
-
lan: z4.string().optional().describe("Language: cn or en"),
|
|
926
|
-
page: z4.string().optional().describe("Page number"),
|
|
927
|
-
pageSize: z4.string().optional().describe("Page size, max 20"),
|
|
928
|
-
currency: z4.string().optional().describe("Currency: cny or usd")
|
|
929
|
-
},
|
|
930
|
-
async ({ lan, page, pageSize, currency }) => {
|
|
931
|
-
try {
|
|
932
|
-
const params = {};
|
|
933
|
-
if (lan) params.lan = lan;
|
|
934
|
-
if (page) params.page = page;
|
|
935
|
-
if (pageSize) params.pageSize = pageSize;
|
|
936
|
-
if (currency) params.currency = currency;
|
|
937
|
-
return ok(
|
|
938
|
-
await apiGet(
|
|
939
|
-
"/api/v2/futures/interest",
|
|
940
|
-
params
|
|
941
|
-
)
|
|
942
|
-
);
|
|
943
|
-
} catch (e) {
|
|
944
|
-
return err(e);
|
|
945
|
-
}
|
|
946
|
-
}
|
|
947
|
-
);
|
|
948
|
-
server2.tool(
|
|
949
|
-
"get_crypto_stock_quotes",
|
|
950
|
-
"Get crypto-related stock quotes (MSTR, COIN, etc.)",
|
|
951
|
-
{
|
|
952
|
-
tickers: z4.string().optional().describe(
|
|
953
|
-
"Stock tickers, e.g. i:mstr:nasdaq,i:coin:nasdaq"
|
|
954
|
-
)
|
|
955
|
-
},
|
|
956
|
-
async ({ tickers }) => {
|
|
957
|
-
try {
|
|
958
|
-
const params = {};
|
|
959
|
-
if (tickers) params.tickers = tickers;
|
|
960
|
-
return ok(
|
|
961
|
-
await apiGet(
|
|
962
|
-
"/api/upgrade/v2/crypto_stock/quotes",
|
|
963
|
-
params
|
|
964
|
-
)
|
|
965
|
-
);
|
|
966
|
-
} catch (e) {
|
|
967
|
-
return err(e);
|
|
968
|
-
}
|
|
969
|
-
}
|
|
970
|
-
);
|
|
971
|
-
server2.tool(
|
|
972
|
-
"get_crypto_stock_top_gainer",
|
|
973
|
-
"Get top gaining crypto-related stocks (US and/or HK market)",
|
|
974
|
-
{
|
|
975
|
-
us_stock: z4.boolean().optional().describe("Include US stocks (default false)"),
|
|
976
|
-
hk_stock: z4.boolean().optional().describe("Include HK stocks (default false)"),
|
|
977
|
-
limit: z4.number().optional().describe("Number of results (default 50)")
|
|
978
|
-
},
|
|
979
|
-
async ({ us_stock, hk_stock, limit }) => {
|
|
980
|
-
try {
|
|
981
|
-
const params = {};
|
|
982
|
-
if (us_stock != null)
|
|
983
|
-
params.us_stock = String(us_stock);
|
|
984
|
-
if (hk_stock != null)
|
|
985
|
-
params.hk_stock = String(hk_stock);
|
|
986
|
-
params.limit = String(limit ?? 30);
|
|
987
|
-
return ok(
|
|
988
|
-
await apiGet(
|
|
989
|
-
"/api/upgrade/v2/crypto_stock/top-gainer",
|
|
990
|
-
params
|
|
991
|
-
)
|
|
992
|
-
);
|
|
993
|
-
} catch (e) {
|
|
994
|
-
return err(e);
|
|
995
|
-
}
|
|
996
|
-
}
|
|
997
|
-
);
|
|
998
|
-
server2.tool(
|
|
999
|
-
"get_index_price",
|
|
1000
|
-
"Get index price data",
|
|
1001
|
-
{
|
|
1002
|
-
key: z4.string().describe("Index key, e.g. i:diniw:ice"),
|
|
1003
|
-
currency: z4.string().optional().describe("Currency: cny or usd")
|
|
1004
|
-
},
|
|
1005
|
-
async ({ key, currency }) => {
|
|
1006
|
-
try {
|
|
1007
|
-
const params = { key };
|
|
1008
|
-
if (currency) params.currency = currency;
|
|
1009
|
-
return ok(
|
|
1010
|
-
await apiGet("/api/v2/index/indexPrice", params)
|
|
1011
|
-
);
|
|
1012
|
-
} catch (e) {
|
|
1013
|
-
return err(e);
|
|
1014
|
-
}
|
|
1015
|
-
}
|
|
1016
|
-
);
|
|
1017
|
-
server2.tool(
|
|
1018
|
-
"get_hot_tab_coins",
|
|
1019
|
-
"Get trending/hot coins list by category",
|
|
1020
|
-
{
|
|
1021
|
-
key: z4.string().describe(
|
|
1022
|
-
"Category key: gamefi,anonymous,market,web,newcoin,stable,defi"
|
|
1023
|
-
),
|
|
1024
|
-
currency: z4.string().optional().describe("Currency: cny or usd"),
|
|
1025
|
-
...maxItemsParam
|
|
1026
|
-
},
|
|
1027
|
-
async ({ key, currency, _max_items }) => {
|
|
1028
|
-
try {
|
|
1029
|
-
const params = { key };
|
|
1030
|
-
if (currency) params.currency = currency;
|
|
1031
|
-
return okList(
|
|
1032
|
-
await apiGet(
|
|
1033
|
-
"/api/v2/market/hotTabCoins",
|
|
1034
|
-
params
|
|
1035
|
-
),
|
|
1036
|
-
parseMax(_max_items, 20)
|
|
1037
|
-
);
|
|
1038
|
-
} catch (e) {
|
|
1039
|
-
return err(e);
|
|
1040
|
-
}
|
|
1041
|
-
}
|
|
1042
|
-
);
|
|
1043
|
-
server2.tool(
|
|
1044
|
-
"get_crypto_company_info",
|
|
1045
|
-
"Get crypto-related company details by stock symbol",
|
|
1046
|
-
{
|
|
1047
|
-
symbol: z4.string().describe(
|
|
1048
|
-
"Symbol in i:ticker:market format, e.g. i:mstr:nasdaq"
|
|
1049
|
-
)
|
|
1050
|
-
},
|
|
1051
|
-
async ({ symbol }) => {
|
|
1052
|
-
try {
|
|
1053
|
-
return ok(
|
|
1054
|
-
await apiGet(
|
|
1055
|
-
`/api/upgrade/v2/crypto_stock/company/${symbol}`
|
|
1056
|
-
)
|
|
1057
|
-
);
|
|
1058
|
-
} catch (e) {
|
|
1059
|
-
return err(e);
|
|
1060
|
-
}
|
|
1061
|
-
}
|
|
1062
|
-
);
|
|
1063
|
-
server2.tool(
|
|
1064
|
-
"get_index_info",
|
|
1065
|
-
"Get index detail information",
|
|
1066
|
-
{
|
|
1067
|
-
key: z4.string().describe("Index key, e.g. i:diniw:ice"),
|
|
1068
|
-
lan: z4.string().optional().describe("Language: en or cn")
|
|
1069
|
-
},
|
|
1070
|
-
async ({ key, lan }) => {
|
|
1071
|
-
try {
|
|
1072
|
-
const params = { key };
|
|
1073
|
-
if (lan) params.lan = lan;
|
|
1074
|
-
return ok(
|
|
1075
|
-
await apiGet("/api/v2/index/indexInfo", params)
|
|
1076
|
-
);
|
|
1077
|
-
} catch (e) {
|
|
1078
|
-
return err(e);
|
|
1079
|
-
}
|
|
1080
|
-
}
|
|
1081
|
-
);
|
|
1082
|
-
server2.tool(
|
|
1083
|
-
"get_index_list",
|
|
1084
|
-
"Get list of all available indexes",
|
|
1085
|
-
{ ...maxItemsParam },
|
|
1086
|
-
async ({ _max_items }) => {
|
|
1087
|
-
try {
|
|
1088
|
-
return okList(
|
|
1089
|
-
await apiGet("/api/v2/index/getIndex"),
|
|
1090
|
-
parseMax(_max_items, 20)
|
|
1091
|
-
);
|
|
1092
|
-
} catch (e) {
|
|
1093
|
-
return err(e);
|
|
1094
|
-
}
|
|
1095
|
-
}
|
|
1096
|
-
);
|
|
1097
|
-
server2.tool(
|
|
1098
|
-
"get_indicator_kline_trading_pair",
|
|
1099
|
-
"Get trading pairs for indicator K-line",
|
|
1100
|
-
{
|
|
1101
|
-
coinType: z4.string().optional().describe("Coin type, e.g. bitcoin"),
|
|
1102
|
-
indicator_key: z4.string().optional().describe(
|
|
1103
|
-
"Indicator key: fundflow,aiaggtrade,fr,etc."
|
|
1104
|
-
)
|
|
1105
|
-
},
|
|
1106
|
-
async ({ coinType, indicator_key }) => {
|
|
1107
|
-
try {
|
|
1108
|
-
const params = {};
|
|
1109
|
-
if (coinType) params.coinType = coinType;
|
|
1110
|
-
if (indicator_key)
|
|
1111
|
-
params.indicator_key = indicator_key;
|
|
1112
|
-
return ok(
|
|
1113
|
-
await apiGet(
|
|
1114
|
-
"/api/v2/indicatorKline/getTradingPair",
|
|
1115
|
-
params
|
|
1116
|
-
)
|
|
1117
|
-
);
|
|
1118
|
-
} catch (e) {
|
|
1119
|
-
return err(e);
|
|
1120
|
-
}
|
|
1121
|
-
}
|
|
1122
|
-
);
|
|
1123
|
-
server2.tool(
|
|
1124
|
-
"get_indicator_kline_data",
|
|
1125
|
-
"Get indicator K-line data records",
|
|
1126
|
-
{
|
|
1127
|
-
symbol: z4.string().describe(
|
|
1128
|
-
"Trading pair, e.g. btcswapusdt:binance"
|
|
1129
|
-
),
|
|
1130
|
-
indicator_key: z4.string().describe(
|
|
1131
|
-
"Indicator key: fundflow, aiaggtrade, fr, etc."
|
|
1132
|
-
),
|
|
1133
|
-
period: z4.string().optional().describe(
|
|
1134
|
-
"Period in seconds: 900=15min, 3600=1h, 14400=4h, 86400=1d"
|
|
1135
|
-
),
|
|
1136
|
-
size: z4.string().optional().describe("Number of records, 1-500"),
|
|
1137
|
-
since: z4.string().optional().describe("Start timestamp"),
|
|
1138
|
-
open_time: z4.string().optional().describe("Open time offset: 0 or 8")
|
|
1139
|
-
},
|
|
1140
|
-
async ({
|
|
1141
|
-
symbol,
|
|
1142
|
-
indicator_key,
|
|
1143
|
-
period,
|
|
1144
|
-
size,
|
|
1145
|
-
since,
|
|
1146
|
-
open_time
|
|
1147
|
-
}) => {
|
|
1148
|
-
try {
|
|
1149
|
-
const params = {
|
|
1150
|
-
symbol,
|
|
1151
|
-
indicator_key
|
|
1152
|
-
};
|
|
1153
|
-
if (period) params.period = period;
|
|
1154
|
-
params.size = size ?? "100";
|
|
1155
|
-
if (since) params.since = since;
|
|
1156
|
-
if (open_time) params.open_time = open_time;
|
|
1157
|
-
return ok(
|
|
1158
|
-
await apiGet(
|
|
1159
|
-
"/api/v2/indicatorKline/dataRecords",
|
|
1160
|
-
params
|
|
1161
|
-
)
|
|
1162
|
-
);
|
|
1163
|
-
} catch (e) {
|
|
1164
|
-
return err(e);
|
|
1165
|
-
}
|
|
1166
|
-
}
|
|
1167
|
-
);
|
|
1168
|
-
server2.tool(
|
|
1169
|
-
"get_coin_treasury_entities",
|
|
1170
|
-
"Get coin treasury entity data (e.g. MicroStrategy BTC holdings)",
|
|
1171
|
-
{
|
|
1172
|
-
coin: z4.string().describe("Coin ticker, e.g. BTC, ETH"),
|
|
1173
|
-
entity_type: z4.string().optional().describe(
|
|
1174
|
-
"Entity type: public-companies, eth-treasuries, etc."
|
|
1175
|
-
),
|
|
1176
|
-
name: z4.string().optional().describe("Entity name fuzzy search"),
|
|
1177
|
-
ticker: z4.string().optional().describe("Stock ticker filter"),
|
|
1178
|
-
start_date: z4.string().optional().describe("Start date, ISO 8601"),
|
|
1179
|
-
end_date: z4.string().optional().describe("End date, ISO 8601"),
|
|
1180
|
-
page: z4.string().optional().describe("Page number, default 1"),
|
|
1181
|
-
page_size: z4.string().optional().describe("Page size, default 20, max 100"),
|
|
1182
|
-
sort_order: z4.string().optional().describe("Sort: asc or desc, default desc")
|
|
1183
|
-
},
|
|
1184
|
-
async ({
|
|
1185
|
-
coin,
|
|
1186
|
-
entity_type,
|
|
1187
|
-
name,
|
|
1188
|
-
ticker,
|
|
1189
|
-
start_date,
|
|
1190
|
-
end_date,
|
|
1191
|
-
page,
|
|
1192
|
-
page_size,
|
|
1193
|
-
sort_order
|
|
1194
|
-
}) => {
|
|
1195
|
-
try {
|
|
1196
|
-
const body = { coin };
|
|
1197
|
-
if (entity_type) body.entity_type = entity_type;
|
|
1198
|
-
if (name) body.name = name;
|
|
1199
|
-
if (ticker) body.ticker = ticker;
|
|
1200
|
-
if (start_date) body.start_date = start_date;
|
|
1201
|
-
if (end_date) body.end_date = end_date;
|
|
1202
|
-
if (page) body.page = Number(page);
|
|
1203
|
-
if (page_size)
|
|
1204
|
-
body.page_size = Number(page_size);
|
|
1205
|
-
if (sort_order) body.sort_order = sort_order;
|
|
1206
|
-
return ok(
|
|
1207
|
-
await apiPost(
|
|
1208
|
-
"/api/upgrade/v2/coin-treasuries/entities",
|
|
1209
|
-
body
|
|
1210
|
-
)
|
|
1211
|
-
);
|
|
1212
|
-
} catch (e) {
|
|
1213
|
-
return err(e);
|
|
1214
|
-
}
|
|
1215
|
-
}
|
|
1216
|
-
);
|
|
1217
|
-
server2.tool(
|
|
1218
|
-
"get_coin_treasury_history",
|
|
1219
|
-
"Get coin treasury historical data",
|
|
1220
|
-
{
|
|
1221
|
-
coin: z4.string().describe("Coin ticker, e.g. BTC, ETH"),
|
|
1222
|
-
name: z4.string().optional().describe("Entity name filter"),
|
|
1223
|
-
type: z4.string().optional().describe("Trade type: Buy or Sell"),
|
|
1224
|
-
start_date: z4.string().optional().describe("Start date, ISO 8601"),
|
|
1225
|
-
end_date: z4.string().optional().describe("End date, ISO 8601"),
|
|
1226
|
-
page: z4.string().optional().describe("Page number, default 1"),
|
|
1227
|
-
page_size: z4.string().optional().describe("Page size, default 20"),
|
|
1228
|
-
sort_by: z4.string().optional().describe("Sort field, default date"),
|
|
1229
|
-
sort_order: z4.string().optional().describe("Sort: asc or desc, default desc")
|
|
1230
|
-
},
|
|
1231
|
-
async ({
|
|
1232
|
-
coin,
|
|
1233
|
-
name,
|
|
1234
|
-
type,
|
|
1235
|
-
start_date,
|
|
1236
|
-
end_date,
|
|
1237
|
-
page,
|
|
1238
|
-
page_size,
|
|
1239
|
-
sort_by,
|
|
1240
|
-
sort_order
|
|
1241
|
-
}) => {
|
|
1242
|
-
try {
|
|
1243
|
-
const body = { coin };
|
|
1244
|
-
if (name) body.name = name;
|
|
1245
|
-
if (type) body.type = type;
|
|
1246
|
-
if (start_date) body.start_date = start_date;
|
|
1247
|
-
if (end_date) body.end_date = end_date;
|
|
1248
|
-
if (page) body.page = Number(page);
|
|
1249
|
-
if (page_size)
|
|
1250
|
-
body.page_size = Number(page_size);
|
|
1251
|
-
if (sort_by) body.sort_by = sort_by;
|
|
1252
|
-
if (sort_order) body.sort_order = sort_order;
|
|
1253
|
-
return ok(
|
|
1254
|
-
await apiPost(
|
|
1255
|
-
"/api/upgrade/v2/coin-treasuries/history",
|
|
1256
|
-
body
|
|
1257
|
-
)
|
|
1258
|
-
);
|
|
1259
|
-
} catch (e) {
|
|
1260
|
-
return err(e);
|
|
1261
|
-
}
|
|
1262
|
-
}
|
|
1263
|
-
);
|
|
1264
|
-
server2.tool(
|
|
1265
|
-
"get_coin_treasury_accumulated",
|
|
1266
|
-
"Get accumulated coin treasury historical data",
|
|
1267
|
-
{
|
|
1268
|
-
coin: z4.string().describe("Coin ticker, e.g. BTC, ETH"),
|
|
1269
|
-
entity_type: z4.string().optional().describe("Entity type filter"),
|
|
1270
|
-
start_date: z4.string().optional().describe("Start date, ISO 8601"),
|
|
1271
|
-
end_date: z4.string().optional().describe("End date, ISO 8601"),
|
|
1272
|
-
interval: z4.string().optional().describe(
|
|
1273
|
-
"Interval: daily, weekly, or monthly"
|
|
1274
|
-
)
|
|
1275
|
-
},
|
|
1276
|
-
async ({
|
|
1277
|
-
coin,
|
|
1278
|
-
entity_type,
|
|
1279
|
-
start_date,
|
|
1280
|
-
end_date,
|
|
1281
|
-
interval
|
|
1282
|
-
}) => {
|
|
1283
|
-
try {
|
|
1284
|
-
const body = { coin };
|
|
1285
|
-
if (entity_type)
|
|
1286
|
-
body.entity_type = entity_type;
|
|
1287
|
-
if (start_date)
|
|
1288
|
-
body.start_date = start_date;
|
|
1289
|
-
if (end_date) body.end_date = end_date;
|
|
1290
|
-
if (interval) body.interval = interval;
|
|
1291
|
-
return ok(
|
|
1292
|
-
await apiPost(
|
|
1293
|
-
"/api/upgrade/v2/coin-treasuries/history/accumulated",
|
|
1294
|
-
body
|
|
1295
|
-
)
|
|
1296
|
-
);
|
|
1297
|
-
} catch (e) {
|
|
1298
|
-
return err(e);
|
|
1299
|
-
}
|
|
1300
|
-
}
|
|
1301
|
-
);
|
|
1302
|
-
server2.tool(
|
|
1303
|
-
"get_latest_coin_treasury_entities",
|
|
1304
|
-
"Get latest coin treasury entity data",
|
|
1305
|
-
{
|
|
1306
|
-
coin: z4.string().describe("Coin ticker, e.g. BTC, ETH"),
|
|
1307
|
-
...maxItemsParam
|
|
1308
|
-
},
|
|
1309
|
-
async ({ coin, _max_items }) => {
|
|
1310
|
-
try {
|
|
1311
|
-
return okList(
|
|
1312
|
-
await apiGet(
|
|
1313
|
-
"/api/upgrade/v2/coin-treasuries/latest/entities",
|
|
1314
|
-
{ coin }
|
|
1315
|
-
),
|
|
1316
|
-
parseMax(_max_items, 20)
|
|
1317
|
-
);
|
|
1318
|
-
} catch (e) {
|
|
1319
|
-
return err(e);
|
|
1320
|
-
}
|
|
1321
|
-
}
|
|
1322
|
-
);
|
|
1323
|
-
server2.tool(
|
|
1324
|
-
"get_latest_coin_treasury_history",
|
|
1325
|
-
"Get latest coin treasury history data",
|
|
1326
|
-
{
|
|
1327
|
-
coin: z4.string().describe("Coin ticker, e.g. BTC, ETH"),
|
|
1328
|
-
...maxItemsParam
|
|
1329
|
-
},
|
|
1330
|
-
async ({ coin, _max_items }) => {
|
|
1331
|
-
try {
|
|
1332
|
-
return okList(
|
|
1333
|
-
await apiGet(
|
|
1334
|
-
"/api/upgrade/v2/coin-treasuries/latest/history",
|
|
1335
|
-
{ coin }
|
|
1336
|
-
),
|
|
1337
|
-
parseMax(_max_items, 20)
|
|
1338
|
-
);
|
|
1339
|
-
} catch (e) {
|
|
1340
|
-
return err(e);
|
|
1341
|
-
}
|
|
1342
|
-
}
|
|
1343
|
-
);
|
|
1344
|
-
server2.tool(
|
|
1345
|
-
"get_coin_treasury_summary",
|
|
1346
|
-
"Get coin treasury data summary",
|
|
1347
|
-
{
|
|
1348
|
-
coin: z4.string().describe("Coin ticker, e.g. BTC, ETH")
|
|
1349
|
-
},
|
|
1350
|
-
async ({ coin }) => {
|
|
1351
|
-
try {
|
|
1352
|
-
return ok(
|
|
1353
|
-
await apiGet(
|
|
1354
|
-
"/api/upgrade/v2/coin-treasuries/summary",
|
|
1355
|
-
{ coin }
|
|
1356
|
-
)
|
|
1357
|
-
);
|
|
1358
|
-
} catch (e) {
|
|
1359
|
-
return err(e);
|
|
1360
|
-
}
|
|
1361
|
-
}
|
|
1362
|
-
);
|
|
1363
|
-
server2.tool(
|
|
1364
|
-
"get_latest_depth",
|
|
1365
|
-
"Get latest order book depth snapshot from Redis",
|
|
1366
|
-
{
|
|
1367
|
-
dbKey: z4.string().describe(
|
|
1368
|
-
"Trading pair key, e.g. btcusdt:binance, ethusdt:okex"
|
|
1369
|
-
),
|
|
1370
|
-
size: z4.string().optional().describe(
|
|
1371
|
-
"Number of depth levels, 1-500, default 50"
|
|
1372
|
-
)
|
|
1373
|
-
},
|
|
1374
|
-
async ({ dbKey, size }) => {
|
|
1375
|
-
try {
|
|
1376
|
-
const params = {
|
|
1377
|
-
dbKey
|
|
1378
|
-
};
|
|
1379
|
-
if (size) params.size = size;
|
|
1380
|
-
return ok(
|
|
1381
|
-
await apiGet(
|
|
1382
|
-
"/api/upgrade/v2/futures/latest-depth",
|
|
1383
|
-
params
|
|
1384
|
-
)
|
|
1385
|
-
);
|
|
1386
|
-
} catch (e) {
|
|
1387
|
-
return err(e);
|
|
1388
|
-
}
|
|
1389
|
-
}
|
|
1390
|
-
);
|
|
1391
|
-
server2.tool(
|
|
1392
|
-
"get_full_depth",
|
|
1393
|
-
"Get full order book depth data for futures",
|
|
1394
|
-
{
|
|
1395
|
-
dbKey: z4.string().describe(
|
|
1396
|
-
"Trading pair key, e.g. btcswapusd:hbdm, btcswapusdt:binance"
|
|
1397
|
-
),
|
|
1398
|
-
...maxItemsParam
|
|
1399
|
-
},
|
|
1400
|
-
async ({ dbKey, _max_items }) => {
|
|
1401
|
-
try {
|
|
1402
|
-
return okDepth(
|
|
1403
|
-
await apiGet(
|
|
1404
|
-
"/api/upgrade/v2/futures/full-depth",
|
|
1405
|
-
{ dbKey }
|
|
1406
|
-
),
|
|
1407
|
-
parseMax(_max_items, 50)
|
|
1408
|
-
);
|
|
1409
|
-
} catch (e) {
|
|
1410
|
-
return err(e);
|
|
1411
|
-
}
|
|
1412
|
-
}
|
|
1413
|
-
);
|
|
1414
|
-
server2.tool(
|
|
1415
|
-
"get_full_depth_grouped",
|
|
1416
|
-
"Get full depth data grouped by price interval",
|
|
1417
|
-
{
|
|
1418
|
-
dbKey: z4.string().describe(
|
|
1419
|
-
"Trading pair key, e.g. btcswapusd:hbdm, btcswapusdt:binance"
|
|
1420
|
-
),
|
|
1421
|
-
groupSize: z4.string().describe(
|
|
1422
|
-
"Price grouping interval, e.g. 100, 500, 1000"
|
|
1423
|
-
),
|
|
1424
|
-
...maxItemsParam
|
|
1425
|
-
},
|
|
1426
|
-
async ({ dbKey, groupSize, _max_items }) => {
|
|
1427
|
-
try {
|
|
1428
|
-
return okDepth(
|
|
1429
|
-
await apiGet(
|
|
1430
|
-
"/api/upgrade/v2/futures/full-depth/grouped",
|
|
1431
|
-
{ dbKey, groupSize }
|
|
1432
|
-
),
|
|
1433
|
-
parseMax(_max_items, 50)
|
|
1434
|
-
);
|
|
1435
|
-
} catch (e) {
|
|
1436
|
-
return err(e);
|
|
1437
|
-
}
|
|
1438
|
-
}
|
|
1439
|
-
);
|
|
1440
|
-
}
|
|
1441
|
-
|
|
1442
|
-
// src/tools/features.ts
|
|
1443
|
-
import { z as z5 } from "zod";
|
|
1444
|
-
function registerFeatureTools(server2) {
|
|
1445
|
-
server2.tool(
|
|
1446
|
-
"get_ls_ratio",
|
|
1447
|
-
"Get long/short ratio data",
|
|
1448
|
-
{},
|
|
1449
|
-
async () => {
|
|
1450
|
-
try {
|
|
1451
|
-
return ok(
|
|
1452
|
-
await apiGet("/api/v2/mix/ls-ratio")
|
|
1453
|
-
);
|
|
1454
|
-
} catch (e) {
|
|
1455
|
-
return err(e);
|
|
1456
|
-
}
|
|
1457
|
-
}
|
|
1458
|
-
);
|
|
1459
|
-
server2.tool(
|
|
1460
|
-
"get_liquidation_data",
|
|
1461
|
-
"Get liquidation/forced-close data",
|
|
1462
|
-
{
|
|
1463
|
-
currency: z5.string().optional().describe("Currency: cny or usd, default cny"),
|
|
1464
|
-
type: z5.string().optional().describe(
|
|
1465
|
-
"Query type: 1=by coin, 2=by platform"
|
|
1466
|
-
),
|
|
1467
|
-
coinKey: z5.string().optional().describe("Coin key, used when type=1"),
|
|
1468
|
-
marketKey: z5.string().optional().describe("Market key, used when type=2")
|
|
1469
|
-
},
|
|
1470
|
-
async ({ currency, type, coinKey, marketKey }) => {
|
|
1471
|
-
try {
|
|
1472
|
-
const params = {};
|
|
1473
|
-
if (currency) params.currency = currency;
|
|
1474
|
-
if (type) params.type = type;
|
|
1475
|
-
if (coinKey) params.coinKey = coinKey;
|
|
1476
|
-
if (marketKey) params.marketKey = marketKey;
|
|
1477
|
-
return ok(
|
|
1478
|
-
await apiGet("/api/v2/mix/liq", params)
|
|
1479
|
-
);
|
|
1480
|
-
} catch (e) {
|
|
1481
|
-
return err(e);
|
|
1482
|
-
}
|
|
1483
|
-
}
|
|
1484
|
-
);
|
|
1485
|
-
server2.tool(
|
|
1486
|
-
"get_big_orders",
|
|
1487
|
-
"Get whale/large order tracking data",
|
|
1488
|
-
{
|
|
1489
|
-
symbol: z5.string().describe(
|
|
1490
|
-
"Trading pair, e.g. btcusdt:okex"
|
|
1491
|
-
),
|
|
1492
|
-
...maxItemsParam
|
|
1493
|
-
},
|
|
1494
|
-
async ({ symbol, _max_items }) => {
|
|
1495
|
-
try {
|
|
1496
|
-
return okList(
|
|
1497
|
-
await apiGet("/api/v2/order/bigOrder", {
|
|
1498
|
-
symbol
|
|
1499
|
-
}),
|
|
1500
|
-
parseMax(_max_items, 20)
|
|
1501
|
-
);
|
|
1502
|
-
} catch (e) {
|
|
1503
|
-
return err(e);
|
|
1504
|
-
}
|
|
1505
|
-
}
|
|
1506
|
-
);
|
|
1507
|
-
server2.tool(
|
|
1508
|
-
"get_agg_trades",
|
|
1509
|
-
"Get aggregated large trades data",
|
|
1510
|
-
{
|
|
1511
|
-
symbol: z5.string().describe(
|
|
1512
|
-
"Trading pair, e.g. btcusdt:okex"
|
|
1513
|
-
),
|
|
1514
|
-
...maxItemsParam
|
|
1515
|
-
},
|
|
1516
|
-
async ({ symbol, _max_items }) => {
|
|
1517
|
-
try {
|
|
1518
|
-
return okList(
|
|
1519
|
-
await apiGet("/api/v2/order/aggTrade", {
|
|
1520
|
-
symbol
|
|
1521
|
-
}),
|
|
1522
|
-
parseMax(_max_items, 30)
|
|
1523
|
-
);
|
|
1524
|
-
} catch (e) {
|
|
1525
|
-
return err(e);
|
|
1526
|
-
}
|
|
1527
|
-
}
|
|
1528
|
-
);
|
|
1529
|
-
server2.tool(
|
|
1530
|
-
"get_trading_pair_ticker",
|
|
1531
|
-
"Get ticker data for specific trading pairs",
|
|
1532
|
-
{
|
|
1533
|
-
key_list: z5.string().describe(
|
|
1534
|
-
"Trading pair keys, comma-separated, max 100, e.g. btcusdt:okex,btcusdt:huobipro"
|
|
1535
|
-
)
|
|
1536
|
-
},
|
|
1537
|
-
async ({ key_list }) => {
|
|
1538
|
-
try {
|
|
1539
|
-
return ok(
|
|
1540
|
-
await apiGet("/api/v2/trading-pair/ticker", {
|
|
1541
|
-
key_list
|
|
1542
|
-
})
|
|
1543
|
-
);
|
|
1544
|
-
} catch (e) {
|
|
1545
|
-
return err(e);
|
|
1546
|
-
}
|
|
1547
|
-
}
|
|
1548
|
-
);
|
|
1549
|
-
server2.tool(
|
|
1550
|
-
"get_strategy_signal",
|
|
1551
|
-
"Get indicator win-rate signal data",
|
|
1552
|
-
{
|
|
1553
|
-
coin_type: z5.string().optional().describe("Coin type, e.g. bitcoin"),
|
|
1554
|
-
signal_key: z5.string().optional().describe(
|
|
1555
|
-
"Signal key: depth_win_one,depth_win_two,depth_buy_one,order_buy_one,td_buy_one,lsur_one"
|
|
1556
|
-
),
|
|
1557
|
-
latest_time: z5.string().optional().describe("Latest time in ms timestamp"),
|
|
1558
|
-
...maxItemsParam
|
|
1559
|
-
},
|
|
1560
|
-
async ({ coin_type, signal_key, latest_time, _max_items }) => {
|
|
1561
|
-
try {
|
|
1562
|
-
const params = {};
|
|
1563
|
-
if (coin_type) params.coin_type = coin_type;
|
|
1564
|
-
if (signal_key) params.signal_key = signal_key;
|
|
1565
|
-
if (latest_time)
|
|
1566
|
-
params.latest_time = latest_time;
|
|
1567
|
-
return okList(
|
|
1568
|
-
await apiGet(
|
|
1569
|
-
"/api/v2/signal/strategySignal",
|
|
1570
|
-
params
|
|
1571
|
-
),
|
|
1572
|
-
parseMax(_max_items, 20)
|
|
1573
|
-
);
|
|
1574
|
-
} catch (e) {
|
|
1575
|
-
return err(e);
|
|
1576
|
-
}
|
|
1577
|
-
}
|
|
1578
|
-
);
|
|
1579
|
-
server2.tool(
|
|
1580
|
-
"get_nav",
|
|
1581
|
-
"Get navigation bar data (market overview)",
|
|
1582
|
-
{
|
|
1583
|
-
lan: z5.string().optional().describe("Language: cn or en")
|
|
1584
|
-
},
|
|
1585
|
-
async ({ lan }) => {
|
|
1586
|
-
try {
|
|
1587
|
-
const params = {};
|
|
1588
|
-
if (lan) params.lan = lan;
|
|
1589
|
-
return ok(
|
|
1590
|
-
await apiGet("/api/v2/mix/nav", params)
|
|
1591
|
-
);
|
|
1592
|
-
} catch (e) {
|
|
1593
|
-
return err(e);
|
|
1594
|
-
}
|
|
1595
|
-
}
|
|
1596
|
-
);
|
|
1597
|
-
server2.tool(
|
|
1598
|
-
"get_grayscale_trust",
|
|
1599
|
-
"Get Grayscale trust fund data",
|
|
1600
|
-
{},
|
|
1601
|
-
async () => {
|
|
1602
|
-
try {
|
|
1603
|
-
return ok(
|
|
1604
|
-
await apiGet("/api/v2/mix/grayscale-trust")
|
|
1605
|
-
);
|
|
1606
|
-
} catch (e) {
|
|
1607
|
-
return err(e);
|
|
1608
|
-
}
|
|
1609
|
-
}
|
|
1610
|
-
);
|
|
1611
|
-
server2.tool(
|
|
1612
|
-
"get_gray_scale",
|
|
1613
|
-
"Get Grayscale holdings data",
|
|
1614
|
-
{
|
|
1615
|
-
coins: z5.string().describe(
|
|
1616
|
-
"Coin list, comma-separated: btc,ltc,eth,bch,xrp,xlm,zec,zen,etc"
|
|
1617
|
-
)
|
|
1618
|
-
},
|
|
1619
|
-
async ({ coins }) => {
|
|
1620
|
-
try {
|
|
1621
|
-
return ok(
|
|
1622
|
-
await apiGet("/api/v2/mix/gray-scale", {
|
|
1623
|
-
coins
|
|
1624
|
-
})
|
|
1625
|
-
);
|
|
1626
|
-
} catch (e) {
|
|
1627
|
-
return err(e);
|
|
1628
|
-
}
|
|
1629
|
-
}
|
|
1630
|
-
);
|
|
1631
|
-
server2.tool(
|
|
1632
|
-
"get_stock_market",
|
|
1633
|
-
"Get stock market data (crypto-related)",
|
|
1634
|
-
{ ...maxItemsParam },
|
|
1635
|
-
async ({ _max_items }) => {
|
|
1636
|
-
try {
|
|
1637
|
-
return okList(
|
|
1638
|
-
await apiGet("/api/v2/mix/stock-market"),
|
|
1639
|
-
parseMax(_max_items, 50)
|
|
1640
|
-
);
|
|
1641
|
-
} catch (e) {
|
|
1642
|
-
return err(e);
|
|
1643
|
-
}
|
|
1644
|
-
}
|
|
1645
|
-
);
|
|
1646
|
-
server2.tool(
|
|
1647
|
-
"get_signal_alert",
|
|
1648
|
-
"Get signal alert data",
|
|
1649
|
-
{ ...maxItemsParam },
|
|
1650
|
-
async ({ _max_items }) => {
|
|
1651
|
-
try {
|
|
1652
|
-
return okList(
|
|
1653
|
-
await apiGet(
|
|
1654
|
-
"/api/v2/signal/signalAlert"
|
|
1655
|
-
),
|
|
1656
|
-
parseMax(_max_items, 20)
|
|
1657
|
-
);
|
|
1658
|
-
} catch (e) {
|
|
1659
|
-
return err(e);
|
|
1660
|
-
}
|
|
1661
|
-
}
|
|
1662
|
-
);
|
|
1663
|
-
server2.tool(
|
|
1664
|
-
"get_signal_alert_config",
|
|
1665
|
-
"Get signal alert configuration options",
|
|
1666
|
-
{
|
|
1667
|
-
lan: z5.string().optional().describe("Language: cn or en"),
|
|
1668
|
-
...maxItemsParam
|
|
1669
|
-
},
|
|
1670
|
-
async ({ lan, _max_items }) => {
|
|
1671
|
-
try {
|
|
1672
|
-
const params = {};
|
|
1673
|
-
if (lan) params.lan = lan;
|
|
1674
|
-
return okList(
|
|
1675
|
-
await apiGet(
|
|
1676
|
-
"/api/v2/signal/signalAlertConf",
|
|
1677
|
-
params
|
|
1678
|
-
),
|
|
1679
|
-
parseMax(_max_items, 20)
|
|
1680
|
-
);
|
|
1681
|
-
} catch (e) {
|
|
1682
|
-
return err(e);
|
|
1683
|
-
}
|
|
1684
|
-
}
|
|
1685
|
-
);
|
|
1686
|
-
server2.tool(
|
|
1687
|
-
"delete_signal_alert",
|
|
1688
|
-
"Delete a signal alert by ID",
|
|
1689
|
-
{
|
|
1690
|
-
id: z5.string().describe("Signal alert ID")
|
|
1691
|
-
},
|
|
1692
|
-
async ({ id }) => {
|
|
1693
|
-
try {
|
|
1694
|
-
return ok(
|
|
1695
|
-
await apiGet(
|
|
1696
|
-
"/api/v2/signal/delSignalAlert",
|
|
1697
|
-
{ id }
|
|
1698
|
-
)
|
|
1699
|
-
);
|
|
1700
|
-
} catch (e) {
|
|
1701
|
-
return err(e);
|
|
1702
|
-
}
|
|
1703
|
-
}
|
|
1704
|
-
);
|
|
1705
|
-
server2.tool(
|
|
1706
|
-
"add_signal_alert",
|
|
1707
|
-
"Add a new signal alert",
|
|
1708
|
-
{
|
|
1709
|
-
subType: z5.string().describe("Alert sub type"),
|
|
1710
|
-
symbol: z5.string().describe("Trading pair symbol"),
|
|
1711
|
-
remark: z5.string().optional().describe("Alert remark/note")
|
|
1712
|
-
},
|
|
1713
|
-
async ({ subType, symbol, remark }) => {
|
|
1714
|
-
try {
|
|
1715
|
-
const params = {
|
|
1716
|
-
subType,
|
|
1717
|
-
symbol
|
|
1718
|
-
};
|
|
1719
|
-
if (remark) params.remark = remark;
|
|
1720
|
-
return ok(
|
|
1721
|
-
await apiGet(
|
|
1722
|
-
"/api/v2/signal/addSignalAlert",
|
|
1723
|
-
params
|
|
1724
|
-
)
|
|
1725
|
-
);
|
|
1726
|
-
} catch (e) {
|
|
1727
|
-
return err(e);
|
|
1728
|
-
}
|
|
1729
|
-
}
|
|
1730
|
-
);
|
|
1731
|
-
server2.tool(
|
|
1732
|
-
"get_signal_alert_list",
|
|
1733
|
-
"Get signal alert settings list",
|
|
1734
|
-
{},
|
|
1735
|
-
async () => {
|
|
1736
|
-
try {
|
|
1737
|
-
return ok(
|
|
1738
|
-
await apiGet(
|
|
1739
|
-
"/api/v2/signal/getSignalAlertSetList"
|
|
1740
|
-
)
|
|
1741
|
-
);
|
|
1742
|
-
} catch (e) {
|
|
1743
|
-
return err(e);
|
|
1744
|
-
}
|
|
1745
|
-
}
|
|
1746
|
-
);
|
|
1747
|
-
server2.tool(
|
|
1748
|
-
"get_change_signal",
|
|
1749
|
-
"Get abnormal movement signal data",
|
|
1750
|
-
{
|
|
1751
|
-
type: z5.string().optional().describe(
|
|
1752
|
-
"Signal type: 1-12, 17, 18, 23, 24"
|
|
1753
|
-
),
|
|
1754
|
-
currency: z5.string().optional().describe("Currency: usd (default) or cny"),
|
|
1755
|
-
...maxItemsParam
|
|
1756
|
-
},
|
|
1757
|
-
async ({ type, currency, _max_items }) => {
|
|
1758
|
-
try {
|
|
1759
|
-
const params = {};
|
|
1760
|
-
if (type) params.type = type;
|
|
1761
|
-
if (currency) params.currency = currency;
|
|
1762
|
-
return okList(
|
|
1763
|
-
await apiGet(
|
|
1764
|
-
"/api/v2/signal/changeSignal",
|
|
1765
|
-
params
|
|
1766
|
-
),
|
|
1767
|
-
parseMax(_max_items, 50)
|
|
1768
|
-
);
|
|
1769
|
-
} catch (e) {
|
|
1770
|
-
return err(e);
|
|
1771
|
-
}
|
|
1772
|
-
}
|
|
1773
|
-
);
|
|
1774
|
-
server2.tool(
|
|
1775
|
-
"get_trading_pair",
|
|
1776
|
-
"Get trading pair info for a platform",
|
|
1777
|
-
{
|
|
1778
|
-
market: z5.string().describe(
|
|
1779
|
-
"Platform key (from get_markets), e.g. okex, binance"
|
|
1780
|
-
),
|
|
1781
|
-
...maxItemsParam
|
|
1782
|
-
},
|
|
1783
|
-
async ({ market, _max_items }) => {
|
|
1784
|
-
try {
|
|
1785
|
-
return okList(
|
|
1786
|
-
await apiGet(
|
|
1787
|
-
"/api/v2/trading-pair/getTradingPair",
|
|
1788
|
-
{ market }
|
|
1789
|
-
),
|
|
1790
|
-
parseMax(_max_items, 50)
|
|
1791
|
-
);
|
|
1792
|
-
} catch (e) {
|
|
1793
|
-
return err(e);
|
|
1794
|
-
}
|
|
1795
|
-
}
|
|
1796
|
-
);
|
|
1797
|
-
server2.tool(
|
|
1798
|
-
"get_trading_pairs",
|
|
1799
|
-
"Get trading pair list for a platform",
|
|
1800
|
-
{
|
|
1801
|
-
market: z5.string().describe(
|
|
1802
|
-
"Platform key (from /v2/market), e.g. okex, binance"
|
|
1803
|
-
),
|
|
1804
|
-
currency: z5.string().optional().describe("Quote currency filter"),
|
|
1805
|
-
show: z5.string().optional().describe("Coin symbol filter"),
|
|
1806
|
-
...maxItemsParam
|
|
1807
|
-
},
|
|
1808
|
-
async ({ market, currency, show, _max_items }) => {
|
|
1809
|
-
try {
|
|
1810
|
-
const params = {
|
|
1811
|
-
market
|
|
1812
|
-
};
|
|
1813
|
-
if (currency) params.currency = currency;
|
|
1814
|
-
if (show) params.show = show;
|
|
1815
|
-
return okList(
|
|
1816
|
-
await apiGet("/api/v2/trading-pair", params),
|
|
1817
|
-
parseMax(_max_items, 100)
|
|
1818
|
-
);
|
|
1819
|
-
} catch (e) {
|
|
1820
|
-
return err(e);
|
|
1821
|
-
}
|
|
1822
|
-
}
|
|
1823
|
-
);
|
|
1824
|
-
}
|
|
1825
|
-
|
|
1826
|
-
// src/tools/hyperliquid.ts
|
|
1827
|
-
import { z as z6 } from "zod";
|
|
1828
|
-
function registerHyperliquidTools(server2) {
|
|
1829
|
-
server2.tool(
|
|
1830
|
-
"hl_get_tickers",
|
|
1831
|
-
"Get Hyperliquid ticker data (truncated to top 50, use hl_get_ticker_by_coin for specific coin)",
|
|
1832
|
-
{ ...maxItemsParam },
|
|
1833
|
-
async ({ _max_items }) => {
|
|
1834
|
-
try {
|
|
1835
|
-
return okList(
|
|
1836
|
-
await apiGet("/api/upgrade/v2/hl/tickers"),
|
|
1837
|
-
parseMax(_max_items, 50)
|
|
1838
|
-
);
|
|
1839
|
-
} catch (e) {
|
|
1840
|
-
return err(e);
|
|
1841
|
-
}
|
|
1842
|
-
}
|
|
1843
|
-
);
|
|
1844
|
-
server2.tool(
|
|
1845
|
-
"hl_get_ticker_by_coin",
|
|
1846
|
-
"Get Hyperliquid ticker for a specific coin",
|
|
1847
|
-
{
|
|
1848
|
-
coin: z6.string().describe("Coin symbol, e.g. BTC, ETH")
|
|
1849
|
-
},
|
|
1850
|
-
async ({ coin }) => {
|
|
1851
|
-
try {
|
|
1852
|
-
return ok(
|
|
1853
|
-
await apiGet(`/api/upgrade/v2/hl/tickers/coin/${coin}`)
|
|
1854
|
-
);
|
|
1855
|
-
} catch (e) {
|
|
1856
|
-
return err(e);
|
|
1857
|
-
}
|
|
1858
|
-
}
|
|
1859
|
-
);
|
|
1860
|
-
server2.tool(
|
|
1861
|
-
"hl_get_whale_positions",
|
|
1862
|
-
"Get Hyperliquid whale open positions",
|
|
1863
|
-
{
|
|
1864
|
-
coin: z6.string().optional().describe("Coin filter, e.g. BTC"),
|
|
1865
|
-
min_usd: z6.string().optional().describe("Min position size in USD"),
|
|
1866
|
-
...maxItemsParam
|
|
1867
|
-
},
|
|
1868
|
-
async ({ coin, min_usd, _max_items }) => {
|
|
1869
|
-
try {
|
|
1870
|
-
const params = {};
|
|
1871
|
-
if (coin) params.coin = coin;
|
|
1872
|
-
if (min_usd) params.min_usd = min_usd;
|
|
1873
|
-
return okList(
|
|
1874
|
-
await apiGet(
|
|
1875
|
-
"/api/upgrade/v2/hl/whales/open-positions",
|
|
1876
|
-
params
|
|
1877
|
-
),
|
|
1878
|
-
parseMax(_max_items, 50)
|
|
1879
|
-
);
|
|
1880
|
-
} catch (e) {
|
|
1881
|
-
return err(e);
|
|
1882
|
-
}
|
|
1883
|
-
}
|
|
1884
|
-
);
|
|
1885
|
-
server2.tool(
|
|
1886
|
-
"hl_get_liquidations",
|
|
1887
|
-
"Get Hyperliquid liquidation history",
|
|
1888
|
-
{
|
|
1889
|
-
coin: z6.string().optional().describe("Coin filter"),
|
|
1890
|
-
...maxItemsParam
|
|
1891
|
-
},
|
|
1892
|
-
async ({ coin, _max_items }) => {
|
|
1893
|
-
try {
|
|
1894
|
-
const params = {};
|
|
1895
|
-
if (coin) params.coin = coin;
|
|
1896
|
-
return okList(
|
|
1897
|
-
await apiGet(
|
|
1898
|
-
"/api/upgrade/v2/hl/liquidations/history",
|
|
1899
|
-
params
|
|
1900
|
-
),
|
|
1901
|
-
parseMax(_max_items, 50)
|
|
1902
|
-
);
|
|
1903
|
-
} catch (e) {
|
|
1904
|
-
return err(e);
|
|
1905
|
-
}
|
|
1906
|
-
}
|
|
1907
|
-
);
|
|
1908
|
-
server2.tool(
|
|
1909
|
-
"hl_get_trader_stats",
|
|
1910
|
-
"Get Hyperliquid trader statistics by address",
|
|
1911
|
-
{
|
|
1912
|
-
address: z6.string().describe("Wallet address, e.g. 0x..."),
|
|
1913
|
-
period: z6.string().optional().describe("Period in days, e.g. 7, 30")
|
|
1914
|
-
},
|
|
1915
|
-
async ({ address, period }) => {
|
|
1916
|
-
try {
|
|
1917
|
-
const params = {};
|
|
1918
|
-
if (period) params.period = period;
|
|
1919
|
-
return ok(
|
|
1920
|
-
await apiGet(
|
|
1921
|
-
`/api/upgrade/v2/hl/traders/${address}/addr-stat`,
|
|
1922
|
-
params
|
|
1923
|
-
)
|
|
1924
|
-
);
|
|
1925
|
-
} catch (e) {
|
|
1926
|
-
return err(e);
|
|
1927
|
-
}
|
|
1928
|
-
}
|
|
1929
|
-
);
|
|
1930
|
-
server2.tool(
|
|
1931
|
-
"hl_info",
|
|
1932
|
-
"Generic Hyperliquid Info API (supports all info types)",
|
|
1933
|
-
{
|
|
1934
|
-
type: z6.string().describe(
|
|
1935
|
-
"Info type, e.g. metaAndAssetCtxs, clearinghouseState, spotMeta, allMids, l2Book, openOrders, userFills, candleSnapshot"
|
|
1936
|
-
),
|
|
1937
|
-
user: z6.string().optional().describe("User wallet address (for user-specific queries)"),
|
|
1938
|
-
extra_params: z6.string().optional().describe('Extra params as JSON string, e.g. {"coin":"BTC"}'),
|
|
1939
|
-
...maxItemsParam
|
|
1940
|
-
},
|
|
1941
|
-
async ({ type, user, extra_params, _max_items }) => {
|
|
1942
|
-
try {
|
|
1943
|
-
const body = { type };
|
|
1944
|
-
if (user) body.user = user;
|
|
1945
|
-
if (extra_params) {
|
|
1946
|
-
Object.assign(body, JSON.parse(extra_params));
|
|
1947
|
-
}
|
|
1948
|
-
return okList(
|
|
1949
|
-
await apiPost("/api/upgrade/v2/hl/info", body),
|
|
1950
|
-
parseMax(_max_items, 20)
|
|
1951
|
-
);
|
|
1952
|
-
} catch (e) {
|
|
1953
|
-
return err(e);
|
|
1954
|
-
}
|
|
1955
|
-
}
|
|
1956
|
-
);
|
|
1957
|
-
server2.tool(
|
|
1958
|
-
"hl_get_fills_by_address",
|
|
1959
|
-
"Get Hyperliquid user trade fills by wallet address",
|
|
1960
|
-
{
|
|
1961
|
-
address: z6.string().describe("Wallet address, e.g. 0x..."),
|
|
1962
|
-
coin: z6.string().optional().describe("Coin filter, e.g. BTC"),
|
|
1963
|
-
limit: z6.string().optional().describe("Max results"),
|
|
1964
|
-
...maxItemsParam
|
|
1965
|
-
},
|
|
1966
|
-
async ({ address, coin, limit, _max_items }) => {
|
|
1967
|
-
try {
|
|
1968
|
-
const params = {};
|
|
1969
|
-
if (coin) params.coin = coin;
|
|
1970
|
-
if (limit) params.limit = limit;
|
|
1971
|
-
return okList(
|
|
1972
|
-
await apiGet(
|
|
1973
|
-
`/api/upgrade/v2/hl/fills/${address}`,
|
|
1974
|
-
params
|
|
1975
|
-
),
|
|
1976
|
-
parseMax(_max_items, 50)
|
|
1977
|
-
);
|
|
1978
|
-
} catch (e) {
|
|
1979
|
-
return err(e);
|
|
1980
|
-
}
|
|
1981
|
-
}
|
|
1982
|
-
);
|
|
1983
|
-
server2.tool(
|
|
1984
|
-
"hl_get_fills_by_oid",
|
|
1985
|
-
"Get Hyperliquid trade fills by order ID",
|
|
1986
|
-
{
|
|
1987
|
-
oid: z6.string().describe("Order ID")
|
|
1988
|
-
},
|
|
1989
|
-
async ({ oid }) => {
|
|
1990
|
-
try {
|
|
1991
|
-
return ok(
|
|
1992
|
-
await apiGet(`/api/upgrade/v2/hl/fills/oid/${oid}`)
|
|
1993
|
-
);
|
|
1994
|
-
} catch (e) {
|
|
1995
|
-
return err(e);
|
|
1996
|
-
}
|
|
1997
|
-
}
|
|
1998
|
-
);
|
|
1999
|
-
server2.tool(
|
|
2000
|
-
"hl_get_fills_by_twapid",
|
|
2001
|
-
"Get Hyperliquid trade fills by TWAP ID",
|
|
2002
|
-
{
|
|
2003
|
-
twapid: z6.string().describe("TWAP ID")
|
|
2004
|
-
},
|
|
2005
|
-
async ({ twapid }) => {
|
|
2006
|
-
try {
|
|
2007
|
-
return ok(
|
|
2008
|
-
await apiGet(
|
|
2009
|
-
`/api/upgrade/v2/hl/fills/twapid/${twapid}`
|
|
2010
|
-
)
|
|
2011
|
-
);
|
|
2012
|
-
} catch (e) {
|
|
2013
|
-
return err(e);
|
|
2014
|
-
}
|
|
2015
|
-
}
|
|
2016
|
-
);
|
|
2017
|
-
server2.tool(
|
|
2018
|
-
"hl_get_top_trades",
|
|
2019
|
-
"Get Hyperliquid top trades",
|
|
2020
|
-
{
|
|
2021
|
-
coin: z6.string().optional().describe("Coin filter, e.g. BTC"),
|
|
2022
|
-
interval: z6.string().optional().describe("Interval, e.g. 4h, 1d"),
|
|
2023
|
-
limit: z6.string().optional().describe("Max results"),
|
|
2024
|
-
...maxItemsParam
|
|
2025
|
-
},
|
|
2026
|
-
async ({ coin, interval, limit, _max_items }) => {
|
|
2027
|
-
try {
|
|
2028
|
-
const params = {};
|
|
2029
|
-
if (coin) params.coin = coin;
|
|
2030
|
-
if (interval) params.interval = interval;
|
|
2031
|
-
if (limit) params.limit = limit;
|
|
2032
|
-
return okList(
|
|
2033
|
-
await apiGet(
|
|
2034
|
-
"/api/upgrade/v2/hl/fills/top-trades",
|
|
2035
|
-
params
|
|
2036
|
-
),
|
|
2037
|
-
parseMax(_max_items, 50)
|
|
2038
|
-
);
|
|
2039
|
-
} catch (e) {
|
|
2040
|
-
return err(e);
|
|
2041
|
-
}
|
|
2042
|
-
}
|
|
2043
|
-
);
|
|
2044
|
-
server2.tool(
|
|
2045
|
-
"hl_get_filled_orders",
|
|
2046
|
-
"Get filled orders by wallet address",
|
|
2047
|
-
{
|
|
2048
|
-
address: z6.string().describe("Wallet address"),
|
|
2049
|
-
coin: z6.string().optional().describe("Coin filter, e.g. BTC"),
|
|
2050
|
-
limit: z6.string().optional().describe("Max results, default 1000"),
|
|
2051
|
-
...maxItemsParam
|
|
2052
|
-
},
|
|
2053
|
-
async ({ address, coin, limit, _max_items }) => {
|
|
2054
|
-
try {
|
|
2055
|
-
const params = {};
|
|
2056
|
-
if (coin) params.coin = coin;
|
|
2057
|
-
if (limit) params.limit = limit;
|
|
2058
|
-
return okList(
|
|
2059
|
-
await apiGet(
|
|
2060
|
-
`/api/upgrade/v2/hl/filled-orders/${address}/latest`,
|
|
2061
|
-
params
|
|
2062
|
-
),
|
|
2063
|
-
parseMax(_max_items, 50)
|
|
2064
|
-
);
|
|
2065
|
-
} catch (e) {
|
|
2066
|
-
return err(e);
|
|
2067
|
-
}
|
|
2068
|
-
}
|
|
2069
|
-
);
|
|
2070
|
-
server2.tool(
|
|
2071
|
-
"hl_get_filled_order_by_oid",
|
|
2072
|
-
"Get filled order by order ID",
|
|
2073
|
-
{
|
|
2074
|
-
oid: z6.string().describe("Order ID")
|
|
2075
|
-
},
|
|
2076
|
-
async ({ oid }) => {
|
|
2077
|
-
try {
|
|
2078
|
-
return ok(
|
|
2079
|
-
await apiGet(
|
|
2080
|
-
`/api/upgrade/v2/hl/filled-orders/oid/${oid}`
|
|
2081
|
-
)
|
|
2082
|
-
);
|
|
2083
|
-
} catch (e) {
|
|
2084
|
-
return err(e);
|
|
2085
|
-
}
|
|
2086
|
-
}
|
|
2087
|
-
);
|
|
2088
|
-
server2.tool(
|
|
2089
|
-
"hl_get_orders",
|
|
2090
|
-
"Get latest orders by wallet address",
|
|
2091
|
-
{
|
|
2092
|
-
address: z6.string().describe("Wallet address"),
|
|
2093
|
-
coin: z6.string().optional().describe("Coin filter, e.g. BTC"),
|
|
2094
|
-
limit: z6.string().optional().describe("Max results, default 2000"),
|
|
2095
|
-
...maxItemsParam
|
|
2096
|
-
},
|
|
2097
|
-
async ({ address, coin, limit, _max_items }) => {
|
|
2098
|
-
try {
|
|
2099
|
-
const params = {};
|
|
2100
|
-
if (coin) params.coin = coin;
|
|
2101
|
-
if (limit) params.limit = limit;
|
|
2102
|
-
return okList(
|
|
2103
|
-
await apiGet(
|
|
2104
|
-
`/api/upgrade/v2/hl/orders/${address}/latest`,
|
|
2105
|
-
params
|
|
2106
|
-
),
|
|
2107
|
-
parseMax(_max_items, 50)
|
|
2108
|
-
);
|
|
2109
|
-
} catch (e) {
|
|
2110
|
-
return err(e);
|
|
2111
|
-
}
|
|
2112
|
-
}
|
|
2113
|
-
);
|
|
2114
|
-
server2.tool(
|
|
2115
|
-
"hl_get_order_by_oid",
|
|
2116
|
-
"Get order by order ID",
|
|
2117
|
-
{
|
|
2118
|
-
oid: z6.string().describe("Order ID")
|
|
2119
|
-
},
|
|
2120
|
-
async ({ oid }) => {
|
|
2121
|
-
try {
|
|
2122
|
-
return ok(
|
|
2123
|
-
await apiGet(`/api/upgrade/v2/hl/orders/oid/${oid}`)
|
|
2124
|
-
);
|
|
2125
|
-
} catch (e) {
|
|
2126
|
-
return err(e);
|
|
2127
|
-
}
|
|
2128
|
-
}
|
|
2129
|
-
);
|
|
2130
|
-
server2.tool(
|
|
2131
|
-
"hl_get_top_open_orders",
|
|
2132
|
-
"Get top open orders on Hyperliquid",
|
|
2133
|
-
{
|
|
2134
|
-
coin: z6.string().optional().describe("Coin filter"),
|
|
2135
|
-
min_val: z6.string().optional().describe("Min order value filter"),
|
|
2136
|
-
limit: z6.string().optional().describe("Max results"),
|
|
2137
|
-
...maxItemsParam
|
|
452
|
+
symbol: z2.string().describe("REQUIRED. Coin symbol in uppercase, e.g. BTC, ETH"),
|
|
453
|
+
interval: z2.string().describe("REQUIRED. Candle interval: 1m, 2m, 15m, 30m"),
|
|
454
|
+
margin_type: z2.enum(["stablecoin", "coin"]).default("stablecoin").describe(
|
|
455
|
+
"stablecoin: stablecoin-margined OI; coin: coin-margined OI"
|
|
456
|
+
),
|
|
457
|
+
limit: z2.string().optional().describe("Number of records, default 100"),
|
|
458
|
+
start_time: z2.string().optional().describe("Start time in ms"),
|
|
459
|
+
end_time: z2.string().optional().describe("End time in ms")
|
|
2138
460
|
},
|
|
2139
|
-
async ({
|
|
461
|
+
async ({ symbol, interval, margin_type, limit, start_time, end_time }) => {
|
|
2140
462
|
try {
|
|
2141
|
-
const params = {};
|
|
2142
|
-
|
|
2143
|
-
if (
|
|
2144
|
-
if (
|
|
2145
|
-
|
|
2146
|
-
|
|
2147
|
-
"/api/upgrade/v2/hl/orders/top-open-orders",
|
|
2148
|
-
params
|
|
2149
|
-
),
|
|
2150
|
-
parseMax(_max_items, 50)
|
|
2151
|
-
);
|
|
463
|
+
const params = { symbol, interval };
|
|
464
|
+
params.limit = limit ?? "100";
|
|
465
|
+
if (start_time) params.start_time = start_time;
|
|
466
|
+
if (end_time) params.end_time = end_time;
|
|
467
|
+
const path = margin_type === "coin" ? "/api/upgrade/v2/futures/open-interest/aggregated-coin-margin-history" : "/api/upgrade/v2/futures/open-interest/aggregated-stablecoin-history";
|
|
468
|
+
return ok(await apiGet(path, params));
|
|
2152
469
|
} catch (e) {
|
|
2153
470
|
return err(e);
|
|
2154
471
|
}
|
|
2155
472
|
}
|
|
2156
473
|
);
|
|
2157
474
|
server2.tool(
|
|
2158
|
-
"
|
|
2159
|
-
"
|
|
475
|
+
"coin_futures_data",
|
|
476
|
+
"Futures depth & trade data.\n\u2022 historical_depth \u2014 order book history. Requires: key\n\u2022 super_depth \u2014 large orders >$10k. Requires: key\n\u2022 trade_data \u2014 latest trades. Requires: dbkey (NOT key)",
|
|
2160
477
|
{
|
|
2161
|
-
|
|
2162
|
-
|
|
2163
|
-
|
|
2164
|
-
)
|
|
478
|
+
action: z2.enum(["historical_depth", "super_depth", "trade_data"]).describe(
|
|
479
|
+
"historical_depth: order book history; super_depth: large order depth; trade_data: latest trade data"
|
|
480
|
+
),
|
|
481
|
+
key: z2.string().optional().describe("REQUIRED for historical_depth, super_depth. Trading pair key, e.g. btcswapusdt:okcoinfutures. NOT used by trade_data"),
|
|
482
|
+
dbkey: z2.string().optional().describe("REQUIRED for trade_data. Trading pair key, e.g. btcswapusdt:okcoinfutures. NOT used by historical_depth/super_depth"),
|
|
483
|
+
amount: z2.string().optional().describe("For super_depth: USD threshold, default 10000"),
|
|
484
|
+
limit: z2.string().optional().describe("Number of records, max 1000"),
|
|
485
|
+
start_time: z2.string().optional().describe("Start time in ms"),
|
|
486
|
+
end_time: z2.string().optional().describe("End time in ms")
|
|
2165
487
|
},
|
|
2166
|
-
async ({
|
|
488
|
+
async ({ action, key, dbkey, amount, limit, start_time, end_time }) => {
|
|
2167
489
|
try {
|
|
2168
|
-
|
|
2169
|
-
|
|
2170
|
-
|
|
2171
|
-
|
|
2172
|
-
|
|
2173
|
-
|
|
2174
|
-
|
|
2175
|
-
params
|
|
2176
|
-
|
|
2177
|
-
|
|
490
|
+
switch (action) {
|
|
491
|
+
case "historical_depth": {
|
|
492
|
+
if (!key) return err("key is required for historical_depth action");
|
|
493
|
+
const params = { key };
|
|
494
|
+
params.limit = limit ?? "100";
|
|
495
|
+
if (start_time) params.start_time = start_time;
|
|
496
|
+
if (end_time) params.end_time = end_time;
|
|
497
|
+
return ok(await apiGet("/api/upgrade/v2/futures/historical-depth", params));
|
|
498
|
+
}
|
|
499
|
+
case "super_depth": {
|
|
500
|
+
if (!key) return err("key is required for super_depth action");
|
|
501
|
+
const params = { key };
|
|
502
|
+
params.amount = amount ?? "10000";
|
|
503
|
+
params.limit = limit ?? "100";
|
|
504
|
+
if (start_time) params.start_time = start_time;
|
|
505
|
+
if (end_time) params.end_time = end_time;
|
|
506
|
+
return ok(await apiGet("/api/upgrade/v2/futures/super-depth/history", params));
|
|
507
|
+
}
|
|
508
|
+
case "trade_data": {
|
|
509
|
+
if (!dbkey) return err("dbkey is required for trade_data action");
|
|
510
|
+
const params = { dbkey };
|
|
511
|
+
params.limit = limit ?? "100";
|
|
512
|
+
if (start_time) params.start_time = start_time;
|
|
513
|
+
if (end_time) params.end_time = end_time;
|
|
514
|
+
return ok(await apiGet("/api/upgrade/v2/futures/trade-data", params));
|
|
515
|
+
}
|
|
516
|
+
}
|
|
2178
517
|
} catch (e) {
|
|
2179
518
|
return err(e);
|
|
2180
519
|
}
|
|
2181
520
|
}
|
|
2182
521
|
);
|
|
522
|
+
}
|
|
523
|
+
|
|
524
|
+
// src/tools/contents.ts
|
|
525
|
+
import { z as z3 } from "zod";
|
|
526
|
+
function registerContentTools(server2) {
|
|
2183
527
|
server2.tool(
|
|
2184
|
-
"
|
|
2185
|
-
"
|
|
528
|
+
"news",
|
|
529
|
+
"News articles.\n\u2022 list \u2014 paginated news articles\n\u2022 detail \u2014 full article content. Requires: id\n\u2022 rss \u2014 RSS news feed",
|
|
2186
530
|
{
|
|
2187
|
-
|
|
2188
|
-
|
|
2189
|
-
"Time window: day, week, month, allTime"
|
|
531
|
+
action: z3.enum(["list", "detail", "rss"]).describe(
|
|
532
|
+
"list: paginated news articles; detail: full article content; rss: RSS news feed"
|
|
2190
533
|
),
|
|
2191
|
-
|
|
2192
|
-
|
|
2193
|
-
|
|
2194
|
-
|
|
2195
|
-
|
|
2196
|
-
|
|
2197
|
-
|
|
2198
|
-
|
|
2199
|
-
|
|
2200
|
-
|
|
534
|
+
id: z3.string().optional().describe("REQUIRED for detail. News article ID"),
|
|
535
|
+
page: z3.string().optional().describe("For list/rss: page number, default 1"),
|
|
536
|
+
pageSize: z3.string().optional().describe("For list/rss: page size, max 20")
|
|
537
|
+
},
|
|
538
|
+
async ({ action, id, page, pageSize }) => {
|
|
539
|
+
try {
|
|
540
|
+
switch (action) {
|
|
541
|
+
case "list": {
|
|
542
|
+
const params = {};
|
|
543
|
+
if (page) params.page = page;
|
|
544
|
+
params.pageSize = pageSize ?? "20";
|
|
545
|
+
return ok(await apiGet("/api/v2/content/news-list", params));
|
|
546
|
+
}
|
|
547
|
+
case "detail": {
|
|
548
|
+
if (!id) return err("id is required for detail action");
|
|
549
|
+
return ok(await apiGet("/api/v2/content/news-detail", { id }));
|
|
550
|
+
}
|
|
551
|
+
case "rss": {
|
|
552
|
+
const params = {};
|
|
553
|
+
if (page) params.page = page;
|
|
554
|
+
params.pageSize = pageSize ?? "20";
|
|
555
|
+
return ok(await apiGet("/api/v2/content/square/market/news-list", params));
|
|
556
|
+
}
|
|
557
|
+
}
|
|
2201
558
|
} catch (e) {
|
|
2202
559
|
return err(e);
|
|
2203
560
|
}
|
|
2204
561
|
}
|
|
2205
562
|
);
|
|
2206
563
|
server2.tool(
|
|
2207
|
-
"
|
|
2208
|
-
"
|
|
564
|
+
"flash",
|
|
565
|
+
"Flash news.\n\u2022 newsflash \u2014 AiCoin flash news\n\u2022 list \u2014 industry flash with classification\n\u2022 exchange_listing \u2014 coin listing/delisting announcements",
|
|
2209
566
|
{
|
|
2210
|
-
|
|
2211
|
-
|
|
2212
|
-
|
|
567
|
+
action: z3.enum(["newsflash", "list", "exchange_listing"]).describe(
|
|
568
|
+
"newsflash: AiCoin flash news; list: industry flash with types; exchange_listing: coin listing/delisting"
|
|
569
|
+
),
|
|
570
|
+
language: z3.string().optional().describe("Language: cn, tc, en"),
|
|
571
|
+
createtime: z3.string().optional().describe("For list: filter by create time"),
|
|
572
|
+
memberIds: z3.string().optional().describe(
|
|
573
|
+
"For exchange_listing: exchange member IDs, comma-separated. 477=Binance, 1509=Bitget. Default: 477,1509"
|
|
2213
574
|
),
|
|
575
|
+
pageSize: z3.string().optional().describe("For exchange_listing: page size, default 20"),
|
|
2214
576
|
...maxItemsParam
|
|
2215
577
|
},
|
|
2216
|
-
async ({
|
|
578
|
+
async ({ action, language, createtime, memberIds, pageSize, _max_items }) => {
|
|
2217
579
|
try {
|
|
2218
|
-
|
|
2219
|
-
|
|
2220
|
-
|
|
2221
|
-
|
|
2222
|
-
|
|
2223
|
-
|
|
2224
|
-
|
|
2225
|
-
|
|
2226
|
-
|
|
580
|
+
switch (action) {
|
|
581
|
+
case "newsflash": {
|
|
582
|
+
const params = {};
|
|
583
|
+
if (language) params.language = language;
|
|
584
|
+
return ok(await apiGet("/api/v2/content/newsflash", params));
|
|
585
|
+
}
|
|
586
|
+
case "list": {
|
|
587
|
+
const params = {};
|
|
588
|
+
if (language) params.language = language;
|
|
589
|
+
if (createtime) params.createtime = createtime;
|
|
590
|
+
return okList(
|
|
591
|
+
await apiGet("/api/v2/content/flashList", params),
|
|
592
|
+
parseMax(_max_items, 30)
|
|
593
|
+
);
|
|
594
|
+
}
|
|
595
|
+
case "exchange_listing": {
|
|
596
|
+
const params = {};
|
|
597
|
+
if (language) params.language = language;
|
|
598
|
+
if (memberIds) params.memberIds = memberIds;
|
|
599
|
+
if (pageSize) params.pageSize = pageSize;
|
|
600
|
+
return ok(await apiGet("/api/v2/content/exchange-listing-flash", params));
|
|
601
|
+
}
|
|
602
|
+
}
|
|
2227
603
|
} catch (e) {
|
|
2228
604
|
return err(e);
|
|
2229
605
|
}
|
|
2230
606
|
}
|
|
2231
607
|
);
|
|
608
|
+
}
|
|
609
|
+
|
|
610
|
+
// src/tools/markets.ts
|
|
611
|
+
import { z as z4 } from "zod";
|
|
612
|
+
function registerMarketTools(server2) {
|
|
2232
613
|
server2.tool(
|
|
2233
|
-
"
|
|
2234
|
-
"
|
|
614
|
+
"market_info",
|
|
615
|
+
"Exchange/market data.\n\u2022 exchanges \u2014 all platforms, no params needed\n\u2022 ticker \u2014 platform tickers. Requires: market_list (NOT key)\n\u2022 hot_coins \u2014 trending by category. Requires: key (category key, NOT exchange name)\n\u2022 futures_interest \u2014 futures OI rankings, no required params",
|
|
2235
616
|
{
|
|
2236
|
-
|
|
2237
|
-
|
|
2238
|
-
|
|
617
|
+
action: z4.enum(["exchanges", "ticker", "hot_coins", "futures_interest"]).describe(
|
|
618
|
+
"exchanges: all supported platforms; ticker: platform ticker data; hot_coins: trending coins; futures_interest: futures open interest"
|
|
619
|
+
),
|
|
620
|
+
market_list: z4.string().optional().describe('REQUIRED for ticker. Comma-separated exchange keys, e.g. "okex,binance". NOT used by hot_coins'),
|
|
621
|
+
key: z4.string().optional().describe("REQUIRED for hot_coins. Category key: gamefi, anonymous, market, web, newcoin, stable, defi. This is a category key, NOT an exchange name"),
|
|
622
|
+
currency: z4.string().optional().describe("Currency: cny or usd"),
|
|
623
|
+
lan: z4.string().optional().describe("For futures_interest: language cn or en"),
|
|
624
|
+
page: z4.string().optional().describe("For futures_interest: page number"),
|
|
625
|
+
pageSize: z4.string().optional().describe("For futures_interest: page size, max 20"),
|
|
626
|
+
...maxItemsParam
|
|
2239
627
|
},
|
|
2240
|
-
async ({
|
|
628
|
+
async ({ action, market_list, key, currency, lan, page, pageSize, _max_items }) => {
|
|
2241
629
|
try {
|
|
2242
|
-
|
|
2243
|
-
|
|
2244
|
-
|
|
2245
|
-
|
|
2246
|
-
|
|
2247
|
-
|
|
2248
|
-
|
|
2249
|
-
|
|
2250
|
-
|
|
2251
|
-
|
|
630
|
+
switch (action) {
|
|
631
|
+
case "exchanges":
|
|
632
|
+
return ok(await apiGet("/api/v2/market"));
|
|
633
|
+
case "ticker": {
|
|
634
|
+
if (!market_list) return err("market_list is required for ticker action");
|
|
635
|
+
return ok(await apiGet("/api/v2/market/ticker", { market_list }));
|
|
636
|
+
}
|
|
637
|
+
case "hot_coins": {
|
|
638
|
+
if (!key) return err("key is required for hot_coins action");
|
|
639
|
+
const params = { key };
|
|
640
|
+
if (currency) params.currency = currency;
|
|
641
|
+
return okList(await apiGet("/api/v2/market/hotTabCoins", params), parseMax(_max_items, 20));
|
|
642
|
+
}
|
|
643
|
+
case "futures_interest": {
|
|
644
|
+
const params = {};
|
|
645
|
+
if (lan) params.lan = lan;
|
|
646
|
+
if (page) params.page = page;
|
|
647
|
+
if (pageSize) params.pageSize = pageSize;
|
|
648
|
+
if (currency) params.currency = currency;
|
|
649
|
+
return ok(await apiGet("/api/v2/futures/interest", params));
|
|
650
|
+
}
|
|
651
|
+
}
|
|
2252
652
|
} catch (e) {
|
|
2253
653
|
return err(e);
|
|
2254
654
|
}
|
|
2255
655
|
}
|
|
2256
656
|
);
|
|
2257
657
|
server2.tool(
|
|
2258
|
-
"
|
|
2259
|
-
"
|
|
658
|
+
"kline",
|
|
659
|
+
"K-line (candlestick) data.\n\u2022 data \u2014 standard K-line. Requires: symbol\n\u2022 indicator \u2014 indicator K-line. Requires: symbol + indicator_key\n\u2022 trading_pair \u2014 available pairs for indicator. Optional: coinType, indicator_key",
|
|
2260
660
|
{
|
|
2261
|
-
|
|
2262
|
-
|
|
2263
|
-
|
|
661
|
+
action: z4.enum(["data", "indicator", "trading_pair"]).describe(
|
|
662
|
+
"data: standard K-line data; indicator: indicator K-line data; trading_pair: available pairs for indicator K-line"
|
|
663
|
+
),
|
|
664
|
+
symbol: z4.string().optional().describe("REQUIRED for data, indicator. Trading pair with exchange, e.g. btcusdt:okex or btcswapusdt:binance"),
|
|
665
|
+
indicator_key: z4.string().optional().describe("REQUIRED for indicator. Optional for trading_pair. Indicator key: fundflow, aiaggtrade, fr, etc."),
|
|
666
|
+
coinType: z4.string().optional().describe("Optional for trading_pair. Coin type, e.g. bitcoin"),
|
|
667
|
+
period: z4.string().optional().describe("Period in seconds: 900=15min, 3600=1h, 14400=4h, 86400=1d"),
|
|
668
|
+
size: z4.string().optional().describe("Number of candles, 1-500"),
|
|
669
|
+
since: z4.string().optional().describe("Start timestamp"),
|
|
670
|
+
open_time: z4.string().optional().describe("Open time offset: 0 or 8")
|
|
2264
671
|
},
|
|
2265
|
-
async ({
|
|
2266
|
-
try {
|
|
2267
|
-
|
|
2268
|
-
|
|
2269
|
-
|
|
2270
|
-
|
|
2271
|
-
|
|
2272
|
-
|
|
2273
|
-
|
|
2274
|
-
params
|
|
2275
|
-
|
|
2276
|
-
|
|
672
|
+
async ({ action, symbol, indicator_key, coinType, period, size, since, open_time }) => {
|
|
673
|
+
try {
|
|
674
|
+
switch (action) {
|
|
675
|
+
case "data": {
|
|
676
|
+
if (!symbol) return err("symbol is required for data action");
|
|
677
|
+
const params = { symbol };
|
|
678
|
+
if (period) params.period = period;
|
|
679
|
+
params.size = size ?? "100";
|
|
680
|
+
if (since) params.since = since;
|
|
681
|
+
if (open_time) params.open_time = open_time;
|
|
682
|
+
return ok(await apiGet("/api/v2/commonKline/dataRecords", params));
|
|
683
|
+
}
|
|
684
|
+
case "indicator": {
|
|
685
|
+
if (!symbol || !indicator_key) return err("symbol and indicator_key are required for indicator action");
|
|
686
|
+
const params = { symbol, indicator_key };
|
|
687
|
+
if (period) params.period = period;
|
|
688
|
+
params.size = size ?? "100";
|
|
689
|
+
if (since) params.since = since;
|
|
690
|
+
if (open_time) params.open_time = open_time;
|
|
691
|
+
return ok(await apiGet("/api/v2/indicatorKline/dataRecords", params));
|
|
692
|
+
}
|
|
693
|
+
case "trading_pair": {
|
|
694
|
+
const params = {};
|
|
695
|
+
if (coinType) params.coinType = coinType;
|
|
696
|
+
if (indicator_key) params.indicator_key = indicator_key;
|
|
697
|
+
return ok(await apiGet("/api/v2/indicatorKline/getTradingPair", params));
|
|
698
|
+
}
|
|
699
|
+
}
|
|
2277
700
|
} catch (e) {
|
|
2278
701
|
return err(e);
|
|
2279
702
|
}
|
|
2280
703
|
}
|
|
2281
704
|
);
|
|
2282
705
|
server2.tool(
|
|
2283
|
-
"
|
|
2284
|
-
"
|
|
706
|
+
"index_data",
|
|
707
|
+
"Index data.\n\u2022 price \u2014 index price. Requires: key\n\u2022 info \u2014 index detail. Requires: key\n\u2022 list \u2014 all available indexes, no params needed",
|
|
2285
708
|
{
|
|
2286
|
-
|
|
2287
|
-
|
|
2288
|
-
|
|
709
|
+
action: z4.enum(["price", "info", "list"]).describe(
|
|
710
|
+
"price: index price data; info: index detail; list: all available indexes"
|
|
711
|
+
),
|
|
712
|
+
key: z4.string().optional().describe('REQUIRED for price, info. Index key in "i:symbol:exchange" format, e.g. "i:diniw:ice". Use list action to discover available keys'),
|
|
713
|
+
currency: z4.string().optional().describe("For price: currency cny or usd"),
|
|
714
|
+
lan: z4.string().optional().describe("For info: language en or cn"),
|
|
2289
715
|
...maxItemsParam
|
|
2290
716
|
},
|
|
2291
|
-
async ({
|
|
717
|
+
async ({ action, key, currency, lan, _max_items }) => {
|
|
2292
718
|
try {
|
|
2293
|
-
|
|
2294
|
-
|
|
2295
|
-
|
|
2296
|
-
|
|
2297
|
-
|
|
2298
|
-
|
|
2299
|
-
|
|
2300
|
-
|
|
2301
|
-
|
|
2302
|
-
|
|
719
|
+
switch (action) {
|
|
720
|
+
case "price": {
|
|
721
|
+
if (!key) return err("key is required for price action");
|
|
722
|
+
const params = { key };
|
|
723
|
+
if (currency) params.currency = currency;
|
|
724
|
+
return ok(await apiGet("/api/v2/index/indexPrice", params));
|
|
725
|
+
}
|
|
726
|
+
case "info": {
|
|
727
|
+
if (!key) return err("key is required for info action");
|
|
728
|
+
const params = { key };
|
|
729
|
+
if (lan) params.lan = lan;
|
|
730
|
+
return ok(await apiGet("/api/v2/index/indexInfo", params));
|
|
731
|
+
}
|
|
732
|
+
case "list":
|
|
733
|
+
return okList(await apiGet("/api/v2/index/getIndex"), parseMax(_max_items, 20));
|
|
734
|
+
}
|
|
2303
735
|
} catch (e) {
|
|
2304
736
|
return err(e);
|
|
2305
737
|
}
|
|
2306
738
|
}
|
|
2307
739
|
);
|
|
2308
740
|
server2.tool(
|
|
2309
|
-
"
|
|
2310
|
-
|
|
741
|
+
"crypto_stock",
|
|
742
|
+
'Crypto-related stocks.\n\u2022 quotes \u2014 stock prices. Optional: tickers\n\u2022 top_gainer \u2014 top gainers. Optional: us_stock, hk_stock\n\u2022 company \u2014 company details. Requires: symbol (in "i:ticker:market" format)',
|
|
2311
743
|
{
|
|
2312
|
-
|
|
2313
|
-
|
|
2314
|
-
|
|
2315
|
-
|
|
2316
|
-
|
|
2317
|
-
|
|
2318
|
-
|
|
2319
|
-
|
|
2320
|
-
|
|
2321
|
-
|
|
744
|
+
action: z4.enum(["quotes", "top_gainer", "company"]).describe(
|
|
745
|
+
"quotes: stock quotes (MSTR,COIN); top_gainer: top gaining stocks; company: company details"
|
|
746
|
+
),
|
|
747
|
+
tickers: z4.string().optional().describe('Optional for quotes. Comma-separated stock tickers in "i:ticker:market" format, e.g. "i:mstr:nasdaq,i:coin:nasdaq"'),
|
|
748
|
+
symbol: z4.string().optional().describe('REQUIRED for company. Stock symbol in "i:ticker:market" format, e.g. "i:mstr:nasdaq"'),
|
|
749
|
+
us_stock: z4.boolean().optional().describe("For top_gainer: include US stocks"),
|
|
750
|
+
hk_stock: z4.boolean().optional().describe("For top_gainer: include HK stocks"),
|
|
751
|
+
limit: z4.number().optional().describe("For top_gainer: number of results, default 30")
|
|
752
|
+
},
|
|
753
|
+
async ({ action, tickers, symbol, us_stock, hk_stock, limit }) => {
|
|
754
|
+
try {
|
|
755
|
+
switch (action) {
|
|
756
|
+
case "quotes": {
|
|
757
|
+
const params = {};
|
|
758
|
+
if (tickers) params.tickers = tickers;
|
|
759
|
+
return ok(await apiGet("/api/upgrade/v2/crypto_stock/quotes", params));
|
|
760
|
+
}
|
|
761
|
+
case "top_gainer": {
|
|
762
|
+
const params = {};
|
|
763
|
+
if (us_stock != null) params.us_stock = String(us_stock);
|
|
764
|
+
if (hk_stock != null) params.hk_stock = String(hk_stock);
|
|
765
|
+
params.limit = String(limit ?? 30);
|
|
766
|
+
return ok(await apiGet("/api/upgrade/v2/crypto_stock/top-gainer", params));
|
|
767
|
+
}
|
|
768
|
+
case "company": {
|
|
769
|
+
if (!symbol) return err("symbol is required for company action");
|
|
770
|
+
return ok(await apiGet(`/api/upgrade/v2/crypto_stock/company/${symbol}`));
|
|
771
|
+
}
|
|
772
|
+
}
|
|
2322
773
|
} catch (e) {
|
|
2323
774
|
return err(e);
|
|
2324
775
|
}
|
|
2325
776
|
}
|
|
2326
777
|
);
|
|
2327
778
|
server2.tool(
|
|
2328
|
-
"
|
|
2329
|
-
"
|
|
779
|
+
"coin_treasury",
|
|
780
|
+
"Coin treasury data (corporate holdings). Requires: coin for all actions.\n\u2022 entities \u2014 treasury entities\n\u2022 history \u2014 trade history\n\u2022 accumulated \u2014 accumulated holdings over time\n\u2022 latest_entities / latest_history \u2014 latest data\n\u2022 summary \u2014 overview stats",
|
|
2330
781
|
{
|
|
2331
|
-
|
|
2332
|
-
|
|
2333
|
-
startTime: z6.string().optional().describe(
|
|
2334
|
-
"Start time in ms, at least one of startTime/endTime required"
|
|
782
|
+
action: z4.enum(["entities", "history", "accumulated", "latest_entities", "latest_history", "summary"]).describe(
|
|
783
|
+
"entities: treasury entity data; history: trade history; accumulated: accumulated data; latest_entities/latest_history: latest data; summary: overview"
|
|
2335
784
|
),
|
|
2336
|
-
|
|
2337
|
-
|
|
2338
|
-
)
|
|
785
|
+
coin: z4.string().describe("REQUIRED for all actions. Coin ticker in uppercase, e.g. BTC, ETH"),
|
|
786
|
+
entity_type: z4.string().optional().describe("Entity type filter"),
|
|
787
|
+
name: z4.string().optional().describe("Entity name filter"),
|
|
788
|
+
ticker: z4.string().optional().describe("For entities: stock ticker filter"),
|
|
789
|
+
type: z4.string().optional().describe("For history: trade type Buy or Sell"),
|
|
790
|
+
start_date: z4.string().optional().describe("Start date, ISO 8601"),
|
|
791
|
+
end_date: z4.string().optional().describe("End date, ISO 8601"),
|
|
792
|
+
interval: z4.string().optional().describe("For accumulated: daily, weekly, or monthly"),
|
|
793
|
+
page: z4.string().optional().describe("Page number, default 1"),
|
|
794
|
+
page_size: z4.string().optional().describe("Page size, default 20"),
|
|
795
|
+
sort_by: z4.string().optional().describe("For history: sort field, default date"),
|
|
796
|
+
sort_order: z4.string().optional().describe("Sort: asc or desc, default desc"),
|
|
797
|
+
...maxItemsParam
|
|
2339
798
|
},
|
|
2340
|
-
async ({
|
|
2341
|
-
try {
|
|
2342
|
-
|
|
2343
|
-
|
|
2344
|
-
|
|
2345
|
-
|
|
2346
|
-
|
|
2347
|
-
|
|
2348
|
-
|
|
2349
|
-
|
|
2350
|
-
|
|
799
|
+
async ({ action, coin, entity_type, name, ticker, type, start_date, end_date, interval, page, page_size, sort_by, sort_order, _max_items }) => {
|
|
800
|
+
try {
|
|
801
|
+
switch (action) {
|
|
802
|
+
case "entities": {
|
|
803
|
+
const body = { coin };
|
|
804
|
+
if (entity_type) body.entity_type = entity_type;
|
|
805
|
+
if (name) body.name = name;
|
|
806
|
+
if (ticker) body.ticker = ticker;
|
|
807
|
+
if (start_date) body.start_date = start_date;
|
|
808
|
+
if (end_date) body.end_date = end_date;
|
|
809
|
+
if (page) body.page = Number(page);
|
|
810
|
+
if (page_size) body.page_size = Number(page_size);
|
|
811
|
+
if (sort_order) body.sort_order = sort_order;
|
|
812
|
+
return ok(await apiPost("/api/upgrade/v2/coin-treasuries/entities", body));
|
|
813
|
+
}
|
|
814
|
+
case "history": {
|
|
815
|
+
const body = { coin };
|
|
816
|
+
if (name) body.name = name;
|
|
817
|
+
if (type) body.type = type;
|
|
818
|
+
if (start_date) body.start_date = start_date;
|
|
819
|
+
if (end_date) body.end_date = end_date;
|
|
820
|
+
if (page) body.page = Number(page);
|
|
821
|
+
if (page_size) body.page_size = Number(page_size);
|
|
822
|
+
if (sort_by) body.sort_by = sort_by;
|
|
823
|
+
if (sort_order) body.sort_order = sort_order;
|
|
824
|
+
return ok(await apiPost("/api/upgrade/v2/coin-treasuries/history", body));
|
|
825
|
+
}
|
|
826
|
+
case "accumulated": {
|
|
827
|
+
const body = { coin };
|
|
828
|
+
if (entity_type) body.entity_type = entity_type;
|
|
829
|
+
if (start_date) body.start_date = start_date;
|
|
830
|
+
if (end_date) body.end_date = end_date;
|
|
831
|
+
if (interval) body.interval = interval;
|
|
832
|
+
return ok(await apiPost("/api/upgrade/v2/coin-treasuries/history/accumulated", body));
|
|
833
|
+
}
|
|
834
|
+
case "latest_entities":
|
|
835
|
+
return okList(
|
|
836
|
+
await apiGet("/api/upgrade/v2/coin-treasuries/latest/entities", { coin }),
|
|
837
|
+
parseMax(_max_items, 20)
|
|
838
|
+
);
|
|
839
|
+
case "latest_history":
|
|
840
|
+
return okList(
|
|
841
|
+
await apiGet("/api/upgrade/v2/coin-treasuries/latest/history", { coin }),
|
|
842
|
+
parseMax(_max_items, 20)
|
|
843
|
+
);
|
|
844
|
+
case "summary":
|
|
845
|
+
return ok(await apiGet("/api/upgrade/v2/coin-treasuries/summary", { coin }));
|
|
846
|
+
}
|
|
2351
847
|
} catch (e) {
|
|
2352
848
|
return err(e);
|
|
2353
849
|
}
|
|
2354
850
|
}
|
|
2355
851
|
);
|
|
2356
852
|
server2.tool(
|
|
2357
|
-
"
|
|
2358
|
-
"
|
|
853
|
+
"depth",
|
|
854
|
+
"Order book depth. Requires: dbKey for all actions.\n\u2022 latest \u2014 real-time snapshot\n\u2022 full \u2014 complete order book\n\u2022 grouped \u2014 grouped by price interval. Requires: groupSize",
|
|
2359
855
|
{
|
|
2360
|
-
|
|
2361
|
-
|
|
2362
|
-
|
|
856
|
+
action: z4.enum(["latest", "full", "grouped"]).describe(
|
|
857
|
+
"latest: real-time snapshot; full: complete order book; grouped: grouped by price interval"
|
|
858
|
+
),
|
|
859
|
+
dbKey: z4.string().describe("REQUIRED for all actions. Trading pair key, e.g. btcswapusdt:binance"),
|
|
860
|
+
size: z4.string().optional().describe("Optional for latest. Depth levels 1-500, default 50"),
|
|
861
|
+
groupSize: z4.string().optional().describe('REQUIRED for grouped. Price grouping interval, e.g. "100", "500", "1000"'),
|
|
862
|
+
...maxItemsParam
|
|
2363
863
|
},
|
|
2364
|
-
async ({
|
|
864
|
+
async ({ action, dbKey, size, groupSize, _max_items }) => {
|
|
2365
865
|
try {
|
|
2366
|
-
|
|
2367
|
-
|
|
2368
|
-
|
|
2369
|
-
|
|
2370
|
-
|
|
2371
|
-
|
|
866
|
+
switch (action) {
|
|
867
|
+
case "latest": {
|
|
868
|
+
const params = { dbKey };
|
|
869
|
+
if (size) params.size = size;
|
|
870
|
+
return ok(await apiGet("/api/upgrade/v2/futures/latest-depth", params));
|
|
871
|
+
}
|
|
872
|
+
case "full":
|
|
873
|
+
return okDepth(
|
|
874
|
+
await apiGet("/api/upgrade/v2/futures/full-depth", { dbKey }),
|
|
875
|
+
parseMax(_max_items, 50)
|
|
876
|
+
);
|
|
877
|
+
case "grouped": {
|
|
878
|
+
if (!groupSize) return err("groupSize is required for grouped action");
|
|
879
|
+
return okDepth(
|
|
880
|
+
await apiGet("/api/upgrade/v2/futures/full-depth/grouped", { dbKey, groupSize }),
|
|
881
|
+
parseMax(_max_items, 50)
|
|
882
|
+
);
|
|
883
|
+
}
|
|
884
|
+
}
|
|
2372
885
|
} catch (e) {
|
|
2373
886
|
return err(e);
|
|
2374
887
|
}
|
|
2375
888
|
}
|
|
2376
889
|
);
|
|
890
|
+
}
|
|
891
|
+
|
|
892
|
+
// src/tools/features.ts
|
|
893
|
+
import { z as z5 } from "zod";
|
|
894
|
+
function registerFeatureTools(server2) {
|
|
2377
895
|
server2.tool(
|
|
2378
|
-
"
|
|
2379
|
-
"
|
|
896
|
+
"market_overview",
|
|
897
|
+
"Market overview data.\n\u2022 nav \u2014 market overview/navigation\n\u2022 ls_ratio \u2014 long/short ratio, no params needed\n\u2022 liquidation \u2014 forced-close data\n\u2022 grayscale_trust \u2014 trust fund, no params needed\n\u2022 gray_scale \u2014 grayscale holdings. Requires: coins\n\u2022 stock_market \u2014 crypto stocks, no params needed",
|
|
2380
898
|
{
|
|
2381
|
-
|
|
2382
|
-
|
|
2383
|
-
interval: z6.string().describe("Interval, e.g. 1h, 4h, 1d"),
|
|
2384
|
-
startTime: z6.string().optional().describe(
|
|
2385
|
-
"Start time in ms, at least one of startTime/endTime required"
|
|
899
|
+
action: z5.enum(["nav", "ls_ratio", "liquidation", "grayscale_trust", "gray_scale", "stock_market"]).describe(
|
|
900
|
+
"nav: market overview; ls_ratio: long/short ratio; liquidation: forced-close data; grayscale_trust: trust fund; gray_scale: holdings; stock_market: crypto stocks"
|
|
2386
901
|
),
|
|
2387
|
-
|
|
2388
|
-
|
|
2389
|
-
)
|
|
902
|
+
lan: z5.string().optional().describe('Optional for nav. Language: "cn" or "en"'),
|
|
903
|
+
currency: z5.string().optional().describe('Optional for liquidation. Currency: "cny" or "usd"'),
|
|
904
|
+
type: z5.string().optional().describe('Optional for liquidation. Group by: "1"=by coin, "2"=by platform'),
|
|
905
|
+
coinKey: z5.string().optional().describe('Optional for liquidation. Coin key filter (when type="1")'),
|
|
906
|
+
marketKey: z5.string().optional().describe('Optional for liquidation. Market key filter (when type="2")'),
|
|
907
|
+
coins: z5.string().optional().describe('REQUIRED for gray_scale. Comma-separated coin symbols in lowercase, e.g. "btc,eth"'),
|
|
908
|
+
...maxItemsParam
|
|
2390
909
|
},
|
|
2391
|
-
async ({
|
|
910
|
+
async ({ action, lan, currency, type, coinKey, marketKey, coins, _max_items }) => {
|
|
2392
911
|
try {
|
|
2393
|
-
|
|
2394
|
-
|
|
2395
|
-
|
|
2396
|
-
|
|
2397
|
-
|
|
2398
|
-
|
|
2399
|
-
|
|
2400
|
-
|
|
2401
|
-
|
|
912
|
+
switch (action) {
|
|
913
|
+
case "nav": {
|
|
914
|
+
const params = {};
|
|
915
|
+
if (lan) params.lan = lan;
|
|
916
|
+
return ok(await apiGet("/api/v2/mix/nav", params));
|
|
917
|
+
}
|
|
918
|
+
case "ls_ratio":
|
|
919
|
+
return ok(await apiGet("/api/v2/mix/ls-ratio"));
|
|
920
|
+
case "liquidation": {
|
|
921
|
+
const params = {};
|
|
922
|
+
if (currency) params.currency = currency;
|
|
923
|
+
if (type) params.type = type;
|
|
924
|
+
if (coinKey) params.coinKey = coinKey;
|
|
925
|
+
if (marketKey) params.marketKey = marketKey;
|
|
926
|
+
return ok(await apiGet("/api/v2/mix/liq", params));
|
|
927
|
+
}
|
|
928
|
+
case "grayscale_trust":
|
|
929
|
+
return ok(await apiGet("/api/v2/mix/grayscale-trust"));
|
|
930
|
+
case "gray_scale": {
|
|
931
|
+
if (!coins) return err("coins is required for gray_scale action");
|
|
932
|
+
return ok(await apiGet("/api/v2/mix/gray-scale", { coins }));
|
|
933
|
+
}
|
|
934
|
+
case "stock_market":
|
|
935
|
+
return okList(await apiGet("/api/v2/mix/stock-market"), parseMax(_max_items, 50));
|
|
936
|
+
}
|
|
2402
937
|
} catch (e) {
|
|
2403
938
|
return err(e);
|
|
2404
939
|
}
|
|
2405
940
|
}
|
|
2406
941
|
);
|
|
2407
942
|
server2.tool(
|
|
2408
|
-
"
|
|
2409
|
-
"
|
|
943
|
+
"order_flow",
|
|
944
|
+
"Order flow data. Requires: symbol for all actions.\n\u2022 big_orders \u2014 whale/large order tracking\n\u2022 agg_trades \u2014 aggregated large trades",
|
|
2410
945
|
{
|
|
2411
|
-
|
|
2412
|
-
|
|
2413
|
-
|
|
946
|
+
action: z5.enum(["big_orders", "agg_trades"]).describe(
|
|
947
|
+
"big_orders: whale/large order tracking; agg_trades: aggregated large trades"
|
|
948
|
+
),
|
|
949
|
+
symbol: z5.string().describe("REQUIRED. Trading pair with exchange, e.g. btcswapusdt:binance"),
|
|
950
|
+
...maxItemsParam
|
|
2414
951
|
},
|
|
2415
|
-
async ({
|
|
952
|
+
async ({ action, symbol, _max_items }) => {
|
|
2416
953
|
try {
|
|
2417
|
-
|
|
2418
|
-
|
|
2419
|
-
|
|
2420
|
-
|
|
2421
|
-
|
|
2422
|
-
|
|
954
|
+
switch (action) {
|
|
955
|
+
case "big_orders":
|
|
956
|
+
return okList(await apiGet("/api/v2/order/bigOrder", { symbol }), parseMax(_max_items, 20));
|
|
957
|
+
case "agg_trades":
|
|
958
|
+
return okList(await apiGet("/api/v2/order/aggTrade", { symbol }), parseMax(_max_items, 30));
|
|
959
|
+
}
|
|
2423
960
|
} catch (e) {
|
|
2424
961
|
return err(e);
|
|
2425
962
|
}
|
|
2426
963
|
}
|
|
2427
964
|
);
|
|
2428
965
|
server2.tool(
|
|
2429
|
-
"
|
|
2430
|
-
"
|
|
966
|
+
"trading_pair",
|
|
967
|
+
"Trading pair data.\n\u2022 ticker \u2014 specific pair tickers. Requires: key_list\n\u2022 by_market \u2014 all pairs for a platform. Requires: market\n\u2022 list \u2014 pairs with filters. Requires: market",
|
|
2431
968
|
{
|
|
2432
|
-
|
|
2433
|
-
|
|
2434
|
-
interval: z6.string().describe("Interval, e.g. 1h, 4h, 1d"),
|
|
2435
|
-
startTime: z6.string().optional().describe(
|
|
2436
|
-
"Start time in ms, at least one of startTime/endTime required"
|
|
969
|
+
action: z5.enum(["ticker", "by_market", "list"]).describe(
|
|
970
|
+
"ticker: specific pair tickers; by_market: pairs for a platform; list: pairs with filters"
|
|
2437
971
|
),
|
|
2438
|
-
|
|
2439
|
-
|
|
2440
|
-
)
|
|
972
|
+
key_list: z5.string().optional().describe('REQUIRED for ticker. Comma-separated pair keys, e.g. "btcusdt:okex,btcusdt:huobipro"'),
|
|
973
|
+
market: z5.string().optional().describe("REQUIRED for by_market, list. Platform/exchange key, e.g. okex, binance"),
|
|
974
|
+
currency: z5.string().optional().describe("For list: quote currency filter"),
|
|
975
|
+
show: z5.string().optional().describe("For list: coin symbol filter"),
|
|
976
|
+
...maxItemsParam
|
|
2441
977
|
},
|
|
2442
|
-
async ({
|
|
978
|
+
async ({ action, key_list, market, currency, show, _max_items }) => {
|
|
2443
979
|
try {
|
|
2444
|
-
|
|
2445
|
-
|
|
2446
|
-
|
|
2447
|
-
|
|
2448
|
-
|
|
2449
|
-
|
|
2450
|
-
|
|
2451
|
-
|
|
2452
|
-
|
|
980
|
+
switch (action) {
|
|
981
|
+
case "ticker": {
|
|
982
|
+
if (!key_list) return err("key_list is required for ticker action");
|
|
983
|
+
return ok(await apiGet("/api/v2/trading-pair/ticker", { key_list }));
|
|
984
|
+
}
|
|
985
|
+
case "by_market": {
|
|
986
|
+
if (!market) return err("market is required for by_market action");
|
|
987
|
+
return okList(
|
|
988
|
+
await apiGet("/api/v2/trading-pair/getTradingPair", { market }),
|
|
989
|
+
parseMax(_max_items, 50)
|
|
990
|
+
);
|
|
991
|
+
}
|
|
992
|
+
case "list": {
|
|
993
|
+
if (!market) return err("market is required for list action");
|
|
994
|
+
const params = { market };
|
|
995
|
+
if (currency) params.currency = currency;
|
|
996
|
+
if (show) params.show = show;
|
|
997
|
+
return okList(await apiGet("/api/v2/trading-pair", params), parseMax(_max_items, 100));
|
|
998
|
+
}
|
|
999
|
+
}
|
|
2453
1000
|
} catch (e) {
|
|
2454
1001
|
return err(e);
|
|
2455
1002
|
}
|
|
2456
1003
|
}
|
|
2457
1004
|
);
|
|
2458
1005
|
server2.tool(
|
|
2459
|
-
"
|
|
2460
|
-
"
|
|
1006
|
+
"signal_data",
|
|
1007
|
+
"Signal data.\n\u2022 strategy \u2014 indicator win-rate signals\n\u2022 alert \u2014 current signal alerts\n\u2022 config \u2014 alert configurations\n\u2022 alert_list \u2014 user alert settings\n\u2022 change \u2014 abnormal price movements",
|
|
2461
1008
|
{
|
|
2462
|
-
|
|
1009
|
+
action: z5.enum(["strategy", "alert", "config", "alert_list", "change"]).describe(
|
|
1010
|
+
"strategy: indicator win-rate signals; alert: signal alert data; config: alert configurations; alert_list: alert settings; change: abnormal movement"
|
|
1011
|
+
),
|
|
1012
|
+
coin_type: z5.string().optional().describe("Optional for strategy. Coin type, e.g. bitcoin"),
|
|
1013
|
+
signal_key: z5.string().optional().describe("Optional for strategy. Signal key: depth_win_one, td_buy_one, etc."),
|
|
1014
|
+
latest_time: z5.string().optional().describe("Optional for strategy. Latest time filter in ms"),
|
|
1015
|
+
lan: z5.string().optional().describe('Optional for config. Language: "cn" or "en"'),
|
|
1016
|
+
type: z5.string().optional().describe("Optional for change. Signal type: 1-12, 17, 18, 23, 24"),
|
|
1017
|
+
currency: z5.string().optional().describe('Optional for change. Currency: "usd" or "cny"'),
|
|
1018
|
+
...maxItemsParam
|
|
2463
1019
|
},
|
|
2464
|
-
async ({
|
|
1020
|
+
async ({ action, coin_type, signal_key, latest_time, lan, type, currency, _max_items }) => {
|
|
2465
1021
|
try {
|
|
2466
|
-
|
|
2467
|
-
|
|
2468
|
-
|
|
2469
|
-
|
|
2470
|
-
|
|
1022
|
+
switch (action) {
|
|
1023
|
+
case "strategy": {
|
|
1024
|
+
const params = {};
|
|
1025
|
+
if (coin_type) params.coin_type = coin_type;
|
|
1026
|
+
if (signal_key) params.signal_key = signal_key;
|
|
1027
|
+
if (latest_time) params.latest_time = latest_time;
|
|
1028
|
+
return okList(await apiGet("/api/v2/signal/strategySignal", params), parseMax(_max_items, 20));
|
|
1029
|
+
}
|
|
1030
|
+
case "alert":
|
|
1031
|
+
return okList(await apiGet("/api/v2/signal/signalAlert"), parseMax(_max_items, 20));
|
|
1032
|
+
case "config": {
|
|
1033
|
+
const params = {};
|
|
1034
|
+
if (lan) params.lan = lan;
|
|
1035
|
+
return okList(await apiGet("/api/v2/signal/signalAlertConf", params), parseMax(_max_items, 20));
|
|
1036
|
+
}
|
|
1037
|
+
case "alert_list":
|
|
1038
|
+
return ok(await apiGet("/api/v2/signal/getSignalAlertSetList"));
|
|
1039
|
+
case "change": {
|
|
1040
|
+
const params = {};
|
|
1041
|
+
if (type) params.type = type;
|
|
1042
|
+
if (currency) params.currency = currency;
|
|
1043
|
+
return okList(await apiGet("/api/v2/signal/changeSignal", params), parseMax(_max_items, 50));
|
|
1044
|
+
}
|
|
1045
|
+
}
|
|
2471
1046
|
} catch (e) {
|
|
2472
1047
|
return err(e);
|
|
2473
1048
|
}
|
|
2474
1049
|
}
|
|
2475
1050
|
);
|
|
2476
1051
|
server2.tool(
|
|
2477
|
-
"
|
|
2478
|
-
"
|
|
1052
|
+
"signal_manage",
|
|
1053
|
+
"Delete a signal alert. Requires: id",
|
|
2479
1054
|
{
|
|
2480
|
-
|
|
1055
|
+
id: z5.string().describe("REQUIRED. Signal alert ID to delete")
|
|
2481
1056
|
},
|
|
2482
|
-
async ({
|
|
1057
|
+
async ({ id }) => {
|
|
2483
1058
|
try {
|
|
2484
|
-
return ok(
|
|
2485
|
-
await apiPost(
|
|
2486
|
-
"/api/upgrade/v2/hl/traders/statistics",
|
|
2487
|
-
{ addresses: JSON.parse(addresses) }
|
|
2488
|
-
)
|
|
2489
|
-
);
|
|
1059
|
+
return ok(await apiGet("/api/v2/signal/delSignalAlert", { id }));
|
|
2490
1060
|
} catch (e) {
|
|
2491
1061
|
return err(e);
|
|
2492
1062
|
}
|
|
2493
1063
|
}
|
|
2494
1064
|
);
|
|
1065
|
+
}
|
|
1066
|
+
|
|
1067
|
+
// src/tools/hyperliquid.ts
|
|
1068
|
+
import { z as z6 } from "zod";
|
|
1069
|
+
function registerHyperliquidTools(server2) {
|
|
2495
1070
|
server2.tool(
|
|
2496
|
-
"
|
|
2497
|
-
"
|
|
1071
|
+
"hl_ticker",
|
|
1072
|
+
"Hyperliquid tickers. If coin provided, returns single ticker; otherwise returns all tickers.",
|
|
2498
1073
|
{
|
|
2499
|
-
coin: z6.string().optional().describe("Coin
|
|
1074
|
+
coin: z6.string().optional().describe("Optional. Coin symbol in uppercase, e.g. BTC, ETH. Omit to get all tickers"),
|
|
2500
1075
|
...maxItemsParam
|
|
2501
1076
|
},
|
|
2502
1077
|
async ({ coin, _max_items }) => {
|
|
2503
1078
|
try {
|
|
2504
|
-
|
|
2505
|
-
|
|
2506
|
-
|
|
2507
|
-
|
|
2508
|
-
"/api/upgrade/v2/hl/whales/latest-events",
|
|
2509
|
-
params
|
|
2510
|
-
),
|
|
2511
|
-
parseMax(_max_items, 50)
|
|
2512
|
-
);
|
|
1079
|
+
if (coin) {
|
|
1080
|
+
return ok(await apiGet(`/api/upgrade/v2/hl/tickers/coin/${coin}`));
|
|
1081
|
+
}
|
|
1082
|
+
return okList(await apiGet("/api/upgrade/v2/hl/tickers"), parseMax(_max_items, 50));
|
|
2513
1083
|
} catch (e) {
|
|
2514
1084
|
return err(e);
|
|
2515
1085
|
}
|
|
2516
1086
|
}
|
|
2517
1087
|
);
|
|
2518
1088
|
server2.tool(
|
|
2519
|
-
"
|
|
2520
|
-
"
|
|
1089
|
+
"hl_whale",
|
|
1090
|
+
"Hyperliquid whale data. All actions support optional coin filter.\n\u2022 positions \u2014 whale open positions\n\u2022 events \u2014 latest whale events\n\u2022 directions \u2014 long/short counts\n\u2022 history_ratio \u2014 historical long ratio",
|
|
2521
1091
|
{
|
|
2522
|
-
|
|
1092
|
+
action: z6.enum(["positions", "events", "directions", "history_ratio"]).describe(
|
|
1093
|
+
"positions: whale open positions; events: latest whale events; directions: long/short counts; history_ratio: historical long ratio"
|
|
1094
|
+
),
|
|
1095
|
+
coin: z6.string().optional().describe("Optional. Coin filter in uppercase, e.g. BTC"),
|
|
1096
|
+
min_usd: z6.string().optional().describe("Optional for positions. Min position size in USD"),
|
|
1097
|
+
...maxItemsParam
|
|
2523
1098
|
},
|
|
2524
|
-
async ({ coin }) => {
|
|
1099
|
+
async ({ action, coin, min_usd, _max_items }) => {
|
|
2525
1100
|
try {
|
|
2526
1101
|
const params = {};
|
|
2527
1102
|
if (coin) params.coin = coin;
|
|
2528
|
-
|
|
2529
|
-
|
|
2530
|
-
|
|
2531
|
-
|
|
2532
|
-
|
|
2533
|
-
|
|
1103
|
+
switch (action) {
|
|
1104
|
+
case "positions": {
|
|
1105
|
+
if (min_usd) params.min_usd = min_usd;
|
|
1106
|
+
return okList(
|
|
1107
|
+
await apiGet("/api/upgrade/v2/hl/whales/open-positions", params),
|
|
1108
|
+
parseMax(_max_items, 50)
|
|
1109
|
+
);
|
|
1110
|
+
}
|
|
1111
|
+
case "events":
|
|
1112
|
+
return okList(
|
|
1113
|
+
await apiGet("/api/upgrade/v2/hl/whales/latest-events", params),
|
|
1114
|
+
parseMax(_max_items, 50)
|
|
1115
|
+
);
|
|
1116
|
+
case "directions":
|
|
1117
|
+
return ok(await apiGet("/api/upgrade/v2/hl/whales/directions", params));
|
|
1118
|
+
case "history_ratio":
|
|
1119
|
+
return okList(
|
|
1120
|
+
await apiGet("/api/upgrade/v2/hl/whales/history-long-ratio", params),
|
|
1121
|
+
parseMax(_max_items, 30)
|
|
1122
|
+
);
|
|
1123
|
+
}
|
|
2534
1124
|
} catch (e) {
|
|
2535
1125
|
return err(e);
|
|
2536
1126
|
}
|
|
2537
1127
|
}
|
|
2538
1128
|
);
|
|
2539
1129
|
server2.tool(
|
|
2540
|
-
"
|
|
2541
|
-
"
|
|
1130
|
+
"hl_liquidation",
|
|
1131
|
+
"Hyperliquid liquidation data. All actions support optional coin filter.\n\u2022 history \u2014 liquidation history\n\u2022 stats \u2014 aggregate stats\n\u2022 stats_by_coin \u2014 per-coin stats\n\u2022 top_positions \u2014 top liquidated positions",
|
|
2542
1132
|
{
|
|
2543
|
-
|
|
1133
|
+
action: z6.enum(["history", "stats", "stats_by_coin", "top_positions"]).describe(
|
|
1134
|
+
"history: liquidation history; stats: aggregate stats; stats_by_coin: per-coin stats; top_positions: top liquidated"
|
|
1135
|
+
),
|
|
1136
|
+
coin: z6.string().optional().describe("Optional. Coin filter in uppercase, e.g. BTC"),
|
|
2544
1137
|
...maxItemsParam
|
|
2545
1138
|
},
|
|
2546
|
-
async ({ coin, _max_items }) => {
|
|
1139
|
+
async ({ action, coin, _max_items }) => {
|
|
2547
1140
|
try {
|
|
2548
1141
|
const params = {};
|
|
2549
1142
|
if (coin) params.coin = coin;
|
|
2550
|
-
|
|
2551
|
-
|
|
2552
|
-
|
|
2553
|
-
|
|
2554
|
-
|
|
2555
|
-
|
|
2556
|
-
|
|
2557
|
-
|
|
2558
|
-
|
|
2559
|
-
|
|
2560
|
-
|
|
2561
|
-
|
|
2562
|
-
|
|
2563
|
-
|
|
2564
|
-
|
|
2565
|
-
|
|
2566
|
-
async () => {
|
|
2567
|
-
try {
|
|
2568
|
-
return ok(
|
|
2569
|
-
await apiGet("/api/upgrade/v2/hl/liquidations/stat")
|
|
2570
|
-
);
|
|
1143
|
+
switch (action) {
|
|
1144
|
+
case "history":
|
|
1145
|
+
return okList(
|
|
1146
|
+
await apiGet("/api/upgrade/v2/hl/liquidations/history", params),
|
|
1147
|
+
parseMax(_max_items, 50)
|
|
1148
|
+
);
|
|
1149
|
+
case "stats":
|
|
1150
|
+
return ok(await apiGet("/api/upgrade/v2/hl/liquidations/stat"));
|
|
1151
|
+
case "stats_by_coin":
|
|
1152
|
+
return ok(await apiGet("/api/upgrade/v2/hl/liquidations/stat-by-coin", params));
|
|
1153
|
+
case "top_positions":
|
|
1154
|
+
return okList(
|
|
1155
|
+
await apiGet("/api/upgrade/v2/hl/liquidations/top-positions", params),
|
|
1156
|
+
parseMax(_max_items, 50)
|
|
1157
|
+
);
|
|
1158
|
+
}
|
|
2571
1159
|
} catch (e) {
|
|
2572
1160
|
return err(e);
|
|
2573
1161
|
}
|
|
2574
1162
|
}
|
|
2575
1163
|
);
|
|
2576
1164
|
server2.tool(
|
|
2577
|
-
"
|
|
2578
|
-
"
|
|
1165
|
+
"hl_open_interest",
|
|
1166
|
+
"Hyperliquid open interest.\n\u2022 summary \u2014 overall OI summary, no params needed\n\u2022 top_coins \u2014 top coins ranked by OI\n\u2022 history \u2014 per-coin OI history. Requires: coin",
|
|
2579
1167
|
{
|
|
2580
|
-
|
|
1168
|
+
action: z6.enum(["summary", "top_coins", "history"]).describe(
|
|
1169
|
+
"summary: overall OI summary; top_coins: top coins by OI; history: per-coin OI history"
|
|
1170
|
+
),
|
|
1171
|
+
coin: z6.string().optional().describe("REQUIRED for history. Coin in uppercase, e.g. BTC"),
|
|
1172
|
+
interval: z6.string().optional().describe("Optional for history. Time window: 4h, 1d, etc."),
|
|
1173
|
+
limit: z6.string().optional().describe("Optional for top_coins. Number of coins to return"),
|
|
1174
|
+
...maxItemsParam
|
|
2581
1175
|
},
|
|
2582
|
-
async ({ coin }) => {
|
|
2583
|
-
try {
|
|
2584
|
-
|
|
2585
|
-
|
|
2586
|
-
|
|
2587
|
-
|
|
2588
|
-
|
|
2589
|
-
params
|
|
2590
|
-
|
|
2591
|
-
|
|
1176
|
+
async ({ action, coin, interval, limit, _max_items }) => {
|
|
1177
|
+
try {
|
|
1178
|
+
switch (action) {
|
|
1179
|
+
case "summary":
|
|
1180
|
+
return ok(await apiGet("/api/upgrade/v2/hl/open-interest/summary"));
|
|
1181
|
+
case "top_coins": {
|
|
1182
|
+
const params = {};
|
|
1183
|
+
if (limit) params.limit = limit;
|
|
1184
|
+
return okList(
|
|
1185
|
+
await apiGet("/api/upgrade/v2/hl/open-interest/top-coins", params),
|
|
1186
|
+
parseMax(_max_items, 50)
|
|
1187
|
+
);
|
|
1188
|
+
}
|
|
1189
|
+
case "history": {
|
|
1190
|
+
if (!coin) return err("coin is required for history action");
|
|
1191
|
+
const params = {};
|
|
1192
|
+
if (interval) params.interval = interval;
|
|
1193
|
+
return okList(
|
|
1194
|
+
await apiGet(`/api/upgrade/v2/hl/open-interest/history/${coin}`, params),
|
|
1195
|
+
parseMax(_max_items, 50)
|
|
1196
|
+
);
|
|
1197
|
+
}
|
|
1198
|
+
}
|
|
2592
1199
|
} catch (e) {
|
|
2593
1200
|
return err(e);
|
|
2594
1201
|
}
|
|
2595
1202
|
}
|
|
2596
1203
|
);
|
|
2597
1204
|
server2.tool(
|
|
2598
|
-
"
|
|
2599
|
-
"
|
|
1205
|
+
"hl_taker",
|
|
1206
|
+
"Hyperliquid taker data. Requires: coin for all actions.\n\u2022 delta \u2014 accumulated taker buy/sell delta\n\u2022 klines \u2014 K-lines with taker volume",
|
|
2600
1207
|
{
|
|
2601
|
-
|
|
1208
|
+
action: z6.enum(["delta", "klines"]).describe(
|
|
1209
|
+
"delta: accumulated taker buy/sell delta; klines: K-lines with taker volume"
|
|
1210
|
+
),
|
|
1211
|
+
coin: z6.string().describe("REQUIRED. Coin in uppercase, e.g. BTC, ETH"),
|
|
1212
|
+
interval: z6.string().optional().describe("Optional. Time window: 15m, 4h, 1d. Default 4h for klines"),
|
|
2602
1213
|
...maxItemsParam
|
|
2603
1214
|
},
|
|
2604
|
-
async ({ coin, _max_items }) => {
|
|
1215
|
+
async ({ action, coin, interval, _max_items }) => {
|
|
2605
1216
|
try {
|
|
2606
1217
|
const params = {};
|
|
2607
|
-
if (
|
|
2608
|
-
|
|
2609
|
-
|
|
2610
|
-
|
|
2611
|
-
|
|
2612
|
-
|
|
2613
|
-
|
|
2614
|
-
|
|
1218
|
+
if (interval) params.interval = interval;
|
|
1219
|
+
switch (action) {
|
|
1220
|
+
case "delta":
|
|
1221
|
+
return ok(await apiGet(`/api/upgrade/v2/hl/accumulated-taker-delta/${coin}`, params));
|
|
1222
|
+
case "klines":
|
|
1223
|
+
return okList(
|
|
1224
|
+
await apiGet(`/api/upgrade/v2/hl/klines-with-taker-vol/${coin}/${interval || "4h"}`),
|
|
1225
|
+
parseMax(_max_items, 30)
|
|
1226
|
+
);
|
|
1227
|
+
}
|
|
2615
1228
|
} catch (e) {
|
|
2616
1229
|
return err(e);
|
|
2617
1230
|
}
|
|
2618
1231
|
}
|
|
2619
1232
|
);
|
|
2620
1233
|
server2.tool(
|
|
2621
|
-
"
|
|
2622
|
-
"
|
|
1234
|
+
"hl_trader",
|
|
1235
|
+
"Hyperliquid trader analytics.\n\u2022 stats \u2014 trader stats. Requires: address\n\u2022 best_trades \u2014 most profitable trades. Requires: address + period\n\u2022 performance \u2014 per-coin performance. Requires: address + period\n\u2022 completed_trades \u2014 completed trade list. Requires: address\n\u2022 accounts \u2014 batch account info. Requires: addresses (JSON array string)\n\u2022 statistics \u2014 batch stats. Requires: addresses (JSON array string)",
|
|
2623
1236
|
{
|
|
2624
|
-
|
|
1237
|
+
action: z6.enum(["stats", "best_trades", "performance", "completed_trades", "accounts", "statistics"]).describe(
|
|
1238
|
+
"stats: trader stats; best_trades: most profitable; performance: per-coin performance; completed_trades: completed list; accounts: batch account info; statistics: batch stats"
|
|
1239
|
+
),
|
|
1240
|
+
address: z6.string().optional().describe("REQUIRED for stats, best_trades, performance, completed_trades. Single wallet address (0x...)"),
|
|
1241
|
+
addresses: z6.string().optional().describe(`REQUIRED for accounts, statistics. Must be a JSON array string, e.g. '["0xabc...","0xdef..."]'. NOT comma-separated`),
|
|
1242
|
+
period: z6.string().optional().describe("REQUIRED for best_trades, performance. Optional for stats. Period in days: 7, 30, 90"),
|
|
1243
|
+
coin: z6.string().optional().describe("Optional for completed_trades. Coin filter in uppercase, e.g. BTC"),
|
|
1244
|
+
limit: z6.string().optional().describe("Max results"),
|
|
2625
1245
|
...maxItemsParam
|
|
2626
1246
|
},
|
|
2627
|
-
async ({
|
|
1247
|
+
async ({ action, address, addresses, period, coin, limit, _max_items }) => {
|
|
2628
1248
|
try {
|
|
2629
|
-
|
|
2630
|
-
|
|
2631
|
-
"
|
|
2632
|
-
|
|
2633
|
-
|
|
2634
|
-
|
|
2635
|
-
|
|
1249
|
+
switch (action) {
|
|
1250
|
+
case "stats": {
|
|
1251
|
+
if (!address) return err("address is required for stats action");
|
|
1252
|
+
const params = {};
|
|
1253
|
+
if (period) params.period = period;
|
|
1254
|
+
return ok(await apiGet(`/api/upgrade/v2/hl/traders/${address}/addr-stat`, params));
|
|
1255
|
+
}
|
|
1256
|
+
case "best_trades": {
|
|
1257
|
+
if (!address || !period) return err("address and period are required for best_trades action");
|
|
1258
|
+
const params = { period };
|
|
1259
|
+
if (limit) params.limit = limit;
|
|
1260
|
+
return ok(await apiGet(`/api/upgrade/v2/hl/traders/${address}/best-trades`, params));
|
|
1261
|
+
}
|
|
1262
|
+
case "performance": {
|
|
1263
|
+
if (!address || !period) return err("address and period are required for performance action");
|
|
1264
|
+
const params = { period };
|
|
1265
|
+
if (limit) params.limit = limit;
|
|
1266
|
+
return ok(await apiGet(`/api/upgrade/v2/hl/traders/${address}/performance-by-coin`, params));
|
|
1267
|
+
}
|
|
1268
|
+
case "completed_trades": {
|
|
1269
|
+
if (!address) return err("address is required for completed_trades action");
|
|
1270
|
+
const params = {};
|
|
1271
|
+
if (coin) params.coin = coin;
|
|
1272
|
+
if (limit) params.limit = limit;
|
|
1273
|
+
return okList(
|
|
1274
|
+
await apiGet(`/api/upgrade/v2/hl/traders/${address}/completed-trades`, params),
|
|
1275
|
+
parseMax(_max_items, 50)
|
|
1276
|
+
);
|
|
1277
|
+
}
|
|
1278
|
+
case "accounts": {
|
|
1279
|
+
if (!addresses) return err("addresses is required for accounts action");
|
|
1280
|
+
return ok(await apiPost("/api/upgrade/v2/hl/traders/accounts", {
|
|
1281
|
+
addresses: JSON.parse(addresses)
|
|
1282
|
+
}));
|
|
1283
|
+
}
|
|
1284
|
+
case "statistics": {
|
|
1285
|
+
if (!addresses) return err("addresses is required for statistics action");
|
|
1286
|
+
return ok(await apiPost("/api/upgrade/v2/hl/traders/statistics", {
|
|
1287
|
+
addresses: JSON.parse(addresses)
|
|
1288
|
+
}));
|
|
1289
|
+
}
|
|
1290
|
+
}
|
|
2636
1291
|
} catch (e) {
|
|
2637
1292
|
return err(e);
|
|
2638
1293
|
}
|
|
2639
1294
|
}
|
|
2640
1295
|
);
|
|
2641
1296
|
server2.tool(
|
|
2642
|
-
"
|
|
2643
|
-
"
|
|
1297
|
+
"hl_fills",
|
|
1298
|
+
"Hyperliquid trade fills.\n\u2022 by_address \u2014 fills by wallet. Requires: address\n\u2022 by_oid \u2014 fills by order ID. Requires: oid\n\u2022 by_twapid \u2014 fills by TWAP ID. Requires: twapid\n\u2022 top_trades \u2014 top trades, no required params",
|
|
2644
1299
|
{
|
|
2645
|
-
|
|
1300
|
+
action: z6.enum(["by_address", "by_oid", "by_twapid", "top_trades"]).describe(
|
|
1301
|
+
"by_address: fills by wallet; by_oid: fills by order ID; by_twapid: fills by TWAP ID; top_trades: top trades"
|
|
1302
|
+
),
|
|
1303
|
+
address: z6.string().optional().describe("REQUIRED for by_address. Wallet address (0x...)"),
|
|
1304
|
+
oid: z6.string().optional().describe("REQUIRED for by_oid. Order ID"),
|
|
1305
|
+
twapid: z6.string().optional().describe("REQUIRED for by_twapid. TWAP ID"),
|
|
1306
|
+
coin: z6.string().optional().describe("Optional. Coin filter in uppercase, e.g. BTC"),
|
|
1307
|
+
interval: z6.string().optional().describe("Optional for top_trades. Interval: 4h, 1d"),
|
|
1308
|
+
limit: z6.string().optional().describe("Max results"),
|
|
2646
1309
|
...maxItemsParam
|
|
2647
1310
|
},
|
|
2648
|
-
async ({
|
|
2649
|
-
try {
|
|
2650
|
-
|
|
2651
|
-
|
|
2652
|
-
"
|
|
2653
|
-
|
|
2654
|
-
|
|
2655
|
-
|
|
2656
|
-
|
|
1311
|
+
async ({ action, address, oid, twapid, coin, interval, limit, _max_items }) => {
|
|
1312
|
+
try {
|
|
1313
|
+
switch (action) {
|
|
1314
|
+
case "by_address": {
|
|
1315
|
+
if (!address) return err("address is required for by_address action");
|
|
1316
|
+
const params = {};
|
|
1317
|
+
if (coin) params.coin = coin;
|
|
1318
|
+
if (limit) params.limit = limit;
|
|
1319
|
+
return okList(
|
|
1320
|
+
await apiGet(`/api/upgrade/v2/hl/fills/${address}`, params),
|
|
1321
|
+
parseMax(_max_items, 50)
|
|
1322
|
+
);
|
|
1323
|
+
}
|
|
1324
|
+
case "by_oid": {
|
|
1325
|
+
if (!oid) return err("oid is required for by_oid action");
|
|
1326
|
+
return ok(await apiGet(`/api/upgrade/v2/hl/fills/oid/${oid}`));
|
|
1327
|
+
}
|
|
1328
|
+
case "by_twapid": {
|
|
1329
|
+
if (!twapid) return err("twapid is required for by_twapid action");
|
|
1330
|
+
return ok(await apiGet(`/api/upgrade/v2/hl/fills/twapid/${twapid}`));
|
|
1331
|
+
}
|
|
1332
|
+
case "top_trades": {
|
|
1333
|
+
const params = {};
|
|
1334
|
+
if (coin) params.coin = coin;
|
|
1335
|
+
if (interval) params.interval = interval;
|
|
1336
|
+
if (limit) params.limit = limit;
|
|
1337
|
+
return okList(
|
|
1338
|
+
await apiGet("/api/upgrade/v2/hl/fills/top-trades", params),
|
|
1339
|
+
parseMax(_max_items, 50)
|
|
1340
|
+
);
|
|
1341
|
+
}
|
|
1342
|
+
}
|
|
2657
1343
|
} catch (e) {
|
|
2658
1344
|
return err(e);
|
|
2659
1345
|
}
|
|
2660
1346
|
}
|
|
2661
1347
|
);
|
|
2662
1348
|
server2.tool(
|
|
2663
|
-
"
|
|
2664
|
-
"
|
|
1349
|
+
"hl_orders",
|
|
1350
|
+
"Hyperliquid orders.\n\u2022 latest \u2014 latest orders. Requires: address\n\u2022 by_oid \u2014 single order. Requires: oid\n\u2022 filled \u2014 filled orders. Requires: address\n\u2022 filled_by_oid \u2014 filled order. Requires: oid\n\u2022 top_open \u2014 top open orders\n\u2022 active_stats \u2014 active order stats\n\u2022 twap_states \u2014 TWAP states. Requires: address",
|
|
2665
1351
|
{
|
|
2666
|
-
|
|
1352
|
+
action: z6.enum(["latest", "by_oid", "filled", "filled_by_oid", "top_open", "active_stats", "twap_states"]).describe(
|
|
1353
|
+
"latest: latest orders by address; by_oid: order by ID; filled: filled orders; filled_by_oid: filled order by ID; top_open: top open orders; active_stats: active order stats; twap_states: TWAP states"
|
|
1354
|
+
),
|
|
1355
|
+
address: z6.string().optional().describe("REQUIRED for latest, filled, twap_states. Wallet address (0x...)"),
|
|
1356
|
+
oid: z6.string().optional().describe("REQUIRED for by_oid, filled_by_oid. Order ID"),
|
|
1357
|
+
coin: z6.string().optional().describe("Optional. Coin filter in uppercase"),
|
|
1358
|
+
min_val: z6.string().optional().describe("Optional for top_open. Min order value in USD"),
|
|
1359
|
+
whale_threshold: z6.string().optional().describe("Optional for active_stats. Whale threshold in USD"),
|
|
1360
|
+
limit: z6.string().optional().describe("Max results"),
|
|
1361
|
+
...maxItemsParam
|
|
2667
1362
|
},
|
|
2668
|
-
async ({ address }) => {
|
|
2669
|
-
try {
|
|
2670
|
-
|
|
2671
|
-
|
|
2672
|
-
|
|
2673
|
-
|
|
2674
|
-
|
|
1363
|
+
async ({ action, address, oid, coin, min_val, whale_threshold, limit, _max_items }) => {
|
|
1364
|
+
try {
|
|
1365
|
+
switch (action) {
|
|
1366
|
+
case "latest": {
|
|
1367
|
+
if (!address) return err("address is required for latest action");
|
|
1368
|
+
const params = {};
|
|
1369
|
+
if (coin) params.coin = coin;
|
|
1370
|
+
if (limit) params.limit = limit;
|
|
1371
|
+
return okList(
|
|
1372
|
+
await apiGet(`/api/upgrade/v2/hl/orders/${address}/latest`, params),
|
|
1373
|
+
parseMax(_max_items, 50)
|
|
1374
|
+
);
|
|
1375
|
+
}
|
|
1376
|
+
case "by_oid": {
|
|
1377
|
+
if (!oid) return err("oid is required for by_oid action");
|
|
1378
|
+
return ok(await apiGet(`/api/upgrade/v2/hl/orders/oid/${oid}`));
|
|
1379
|
+
}
|
|
1380
|
+
case "filled": {
|
|
1381
|
+
if (!address) return err("address is required for filled action");
|
|
1382
|
+
const params = {};
|
|
1383
|
+
if (coin) params.coin = coin;
|
|
1384
|
+
if (limit) params.limit = limit;
|
|
1385
|
+
return okList(
|
|
1386
|
+
await apiGet(`/api/upgrade/v2/hl/filled-orders/${address}/latest`, params),
|
|
1387
|
+
parseMax(_max_items, 50)
|
|
1388
|
+
);
|
|
1389
|
+
}
|
|
1390
|
+
case "filled_by_oid": {
|
|
1391
|
+
if (!oid) return err("oid is required for filled_by_oid action");
|
|
1392
|
+
return ok(await apiGet(`/api/upgrade/v2/hl/filled-orders/oid/${oid}`));
|
|
1393
|
+
}
|
|
1394
|
+
case "top_open": {
|
|
1395
|
+
const params = {};
|
|
1396
|
+
if (coin) params.coin = coin;
|
|
1397
|
+
if (min_val) params.min_val = min_val;
|
|
1398
|
+
if (limit) params.limit = limit;
|
|
1399
|
+
return okList(
|
|
1400
|
+
await apiGet("/api/upgrade/v2/hl/orders/top-open-orders", params),
|
|
1401
|
+
parseMax(_max_items, 50)
|
|
1402
|
+
);
|
|
1403
|
+
}
|
|
1404
|
+
case "active_stats": {
|
|
1405
|
+
const params = {};
|
|
1406
|
+
if (coin) params.coin = coin;
|
|
1407
|
+
if (whale_threshold) params.whale_threshold = whale_threshold;
|
|
1408
|
+
return ok(await apiGet("/api/upgrade/v2/hl/orders/active-stats", params));
|
|
1409
|
+
}
|
|
1410
|
+
case "twap_states": {
|
|
1411
|
+
if (!address) return err("address is required for twap_states action");
|
|
1412
|
+
return ok(await apiGet(`/api/upgrade/v2/hl/twap-states/${address}/latest`));
|
|
1413
|
+
}
|
|
1414
|
+
}
|
|
2675
1415
|
} catch (e) {
|
|
2676
1416
|
return err(e);
|
|
2677
1417
|
}
|
|
2678
1418
|
}
|
|
2679
1419
|
);
|
|
2680
1420
|
server2.tool(
|
|
2681
|
-
"
|
|
2682
|
-
"
|
|
1421
|
+
"hl_position",
|
|
1422
|
+
"Hyperliquid position data. Requires: address + coin for all actions.\n\u2022 current_history \u2014 current position history\n\u2022 completed_history \u2014 closed position history. Optional: startTime, endTime\n\u2022 current_pnl \u2014 current PnL. Requires: interval\n\u2022 completed_pnl \u2014 closed PnL. Requires: interval. Optional: startTime, endTime\n\u2022 current_executions \u2014 current execution trace. Requires: interval\n\u2022 completed_executions \u2014 closed execution trace. Requires: interval. Optional: startTime, endTime",
|
|
2683
1423
|
{
|
|
2684
|
-
|
|
2685
|
-
|
|
2686
|
-
|
|
2687
|
-
|
|
2688
|
-
|
|
2689
|
-
|
|
2690
|
-
|
|
2691
|
-
|
|
2692
|
-
|
|
2693
|
-
|
|
2694
|
-
|
|
1424
|
+
action: z6.enum(["current_history", "completed_history", "current_pnl", "completed_pnl", "current_executions", "completed_executions"]).describe(
|
|
1425
|
+
"current_history: current position history; completed_history: closed position history; current_pnl/completed_pnl: PnL data; current_executions/completed_executions: execution trace"
|
|
1426
|
+
),
|
|
1427
|
+
address: z6.string().describe("REQUIRED. Wallet address (0x...)"),
|
|
1428
|
+
coin: z6.string().describe("REQUIRED. Coin in uppercase, e.g. BTC"),
|
|
1429
|
+
interval: z6.string().optional().describe("REQUIRED for current_pnl, completed_pnl, current_executions, completed_executions. Interval: 1h, 4h, 1d"),
|
|
1430
|
+
startTime: z6.string().optional().describe("Optional for completed_* actions. Start time in ms"),
|
|
1431
|
+
endTime: z6.string().optional().describe("Optional for completed_* actions. End time in ms")
|
|
1432
|
+
},
|
|
1433
|
+
async ({ action, address, coin, interval, startTime, endTime }) => {
|
|
1434
|
+
try {
|
|
1435
|
+
switch (action) {
|
|
1436
|
+
case "current_history":
|
|
1437
|
+
return ok(await apiGet(`/api/upgrade/v2/hl/traders/${address}/current-position-history/${coin}`));
|
|
1438
|
+
case "completed_history": {
|
|
1439
|
+
const params = {};
|
|
1440
|
+
if (startTime) params.startTime = startTime;
|
|
1441
|
+
if (endTime) params.endTime = endTime;
|
|
1442
|
+
return ok(await apiGet(`/api/upgrade/v2/hl/traders/${address}/completed-position-history/${coin}`, params));
|
|
1443
|
+
}
|
|
1444
|
+
case "current_pnl": {
|
|
1445
|
+
if (!interval) return err("interval is required for current_pnl action");
|
|
1446
|
+
return ok(await apiGet(`/api/upgrade/v2/hl/traders/${address}/current-position-pnl/${coin}`, { interval }));
|
|
1447
|
+
}
|
|
1448
|
+
case "completed_pnl": {
|
|
1449
|
+
if (!interval) return err("interval is required for completed_pnl action");
|
|
1450
|
+
const params = { interval };
|
|
1451
|
+
if (startTime) params.startTime = startTime;
|
|
1452
|
+
if (endTime) params.endTime = endTime;
|
|
1453
|
+
return ok(await apiGet(`/api/upgrade/v2/hl/traders/${address}/completed-position-pnl/${coin}`, params));
|
|
1454
|
+
}
|
|
1455
|
+
case "current_executions": {
|
|
1456
|
+
if (!interval) return err("interval is required for current_executions action");
|
|
1457
|
+
return ok(await apiGet(`/api/upgrade/v2/hl/traders/${address}/current-position-executions/${coin}`, { interval }));
|
|
1458
|
+
}
|
|
1459
|
+
case "completed_executions": {
|
|
1460
|
+
if (!interval) return err("interval is required for completed_executions action");
|
|
1461
|
+
const params = { interval };
|
|
1462
|
+
if (startTime) params.startTime = startTime;
|
|
1463
|
+
if (endTime) params.endTime = endTime;
|
|
1464
|
+
return ok(await apiGet(`/api/upgrade/v2/hl/traders/${address}/completed-position-executions/${coin}`, params));
|
|
1465
|
+
}
|
|
1466
|
+
}
|
|
2695
1467
|
} catch (e) {
|
|
2696
1468
|
return err(e);
|
|
2697
1469
|
}
|
|
2698
1470
|
}
|
|
2699
1471
|
);
|
|
2700
1472
|
server2.tool(
|
|
2701
|
-
"
|
|
2702
|
-
"
|
|
1473
|
+
"hl_portfolio",
|
|
1474
|
+
"Hyperliquid portfolio data. Requires: address for all actions.\n\u2022 portfolio \u2014 account value curve. Requires: window (NOT days)\n\u2022 pnls \u2014 PNL curve. Optional: period\n\u2022 max_drawdown \u2014 max drawdown. Requires: days (NOT window)\n\u2022 net_flow \u2014 ledger net flow. Requires: days (NOT window)",
|
|
2703
1475
|
{
|
|
2704
|
-
|
|
2705
|
-
|
|
1476
|
+
action: z6.enum(["portfolio", "pnls", "max_drawdown", "net_flow"]).describe(
|
|
1477
|
+
"portfolio: account value curve; pnls: PNL curve; max_drawdown: max drawdown; net_flow: ledger net flow"
|
|
1478
|
+
),
|
|
1479
|
+
address: z6.string().describe("REQUIRED. Wallet address (0x...)"),
|
|
1480
|
+
window: z6.string().optional().describe('REQUIRED for portfolio ONLY. Time window: "day", "week", "month", "allTime". NOT used by max_drawdown/net_flow'),
|
|
1481
|
+
period: z6.string().optional().describe("Optional for pnls. Period in days: 0=allTime, 1, 7, 30"),
|
|
1482
|
+
days: z6.string().optional().describe("REQUIRED for max_drawdown, net_flow. Number of days: 7, 30, 90. NOT used by portfolio"),
|
|
1483
|
+
...maxItemsParam
|
|
2706
1484
|
},
|
|
2707
|
-
async ({ address, days }) => {
|
|
1485
|
+
async ({ action, address, window: win, period, days, _max_items }) => {
|
|
2708
1486
|
try {
|
|
2709
|
-
|
|
2710
|
-
|
|
2711
|
-
|
|
2712
|
-
|
|
2713
|
-
|
|
2714
|
-
|
|
1487
|
+
switch (action) {
|
|
1488
|
+
case "portfolio": {
|
|
1489
|
+
if (!win) return err("window is required for portfolio action");
|
|
1490
|
+
return okList(
|
|
1491
|
+
await apiGet(`/api/upgrade/v2/hl/portfolio/${address}/${win}`),
|
|
1492
|
+
parseMax(_max_items, 30)
|
|
1493
|
+
);
|
|
1494
|
+
}
|
|
1495
|
+
case "pnls": {
|
|
1496
|
+
const params = {};
|
|
1497
|
+
if (period) params.period = period;
|
|
1498
|
+
return okList(
|
|
1499
|
+
await apiGet(`/api/upgrade/v2/hl/pnls/${address}`, params),
|
|
1500
|
+
parseMax(_max_items, 100)
|
|
1501
|
+
);
|
|
1502
|
+
}
|
|
1503
|
+
case "max_drawdown": {
|
|
1504
|
+
if (!days) return err("days is required for max_drawdown action");
|
|
1505
|
+
return ok(await apiGet(`/api/upgrade/v2/hl/max-drawdown/${address}`, { days }));
|
|
1506
|
+
}
|
|
1507
|
+
case "net_flow": {
|
|
1508
|
+
if (!days) return err("days is required for net_flow action");
|
|
1509
|
+
return ok(await apiGet(`/api/upgrade/v2/hl/ledger-updates/net-flow/${address}`, { days }));
|
|
1510
|
+
}
|
|
1511
|
+
}
|
|
2715
1512
|
} catch (e) {
|
|
2716
1513
|
return err(e);
|
|
2717
1514
|
}
|
|
2718
1515
|
}
|
|
2719
1516
|
);
|
|
2720
1517
|
server2.tool(
|
|
2721
|
-
"
|
|
2722
|
-
"
|
|
1518
|
+
"hl_advanced",
|
|
1519
|
+
"Hyperliquid advanced.\n\u2022 info \u2014 generic Hyperliquid Info API. Requires: type\n\u2022 smart_find \u2014 smart money discovery. Optional: params_json\n\u2022 discover \u2014 trader discovery. Optional: params_json",
|
|
2723
1520
|
{
|
|
2724
|
-
|
|
2725
|
-
|
|
1521
|
+
action: z6.enum(["info", "smart_find", "discover"]).describe(
|
|
1522
|
+
"info: generic Hyperliquid Info API; smart_find: smart money addresses; discover: trader discovery"
|
|
1523
|
+
),
|
|
1524
|
+
type: z6.string().optional().describe("REQUIRED for info. Info type: metaAndAssetCtxs, clearinghouseState, allMids, etc."),
|
|
1525
|
+
user: z6.string().optional().describe("Optional for info. User wallet address (0x...)"),
|
|
1526
|
+
extra_params: z6.string().optional().describe("Optional for info. Extra params as JSON string"),
|
|
1527
|
+
params_json: z6.string().optional().describe("Optional for smart_find, discover. Search params as JSON string"),
|
|
2726
1528
|
...maxItemsParam
|
|
2727
1529
|
},
|
|
2728
|
-
async ({
|
|
1530
|
+
async ({ action, type, user, extra_params, params_json, _max_items }) => {
|
|
2729
1531
|
try {
|
|
2730
|
-
|
|
2731
|
-
|
|
2732
|
-
|
|
2733
|
-
|
|
2734
|
-
|
|
2735
|
-
|
|
1532
|
+
switch (action) {
|
|
1533
|
+
case "info": {
|
|
1534
|
+
if (!type) return err("type is required for info action");
|
|
1535
|
+
const body = { type };
|
|
1536
|
+
if (user) body.user = user;
|
|
1537
|
+
if (extra_params) Object.assign(body, JSON.parse(extra_params));
|
|
1538
|
+
return okList(await apiPost("/api/upgrade/v2/hl/info", body), parseMax(_max_items, 20));
|
|
1539
|
+
}
|
|
1540
|
+
case "smart_find":
|
|
1541
|
+
return okList(
|
|
1542
|
+
await apiPost("/api/upgrade/v2/hl/smart/find", JSON.parse(params_json || "{}")),
|
|
1543
|
+
parseMax(_max_items, 20)
|
|
1544
|
+
);
|
|
1545
|
+
case "discover":
|
|
1546
|
+
return okList(
|
|
1547
|
+
await apiPost("/api/upgrade/v2/hl/traders/discover", JSON.parse(params_json || "{}")),
|
|
1548
|
+
parseMax(_max_items, 20)
|
|
1549
|
+
);
|
|
1550
|
+
}
|
|
2736
1551
|
} catch (e) {
|
|
2737
1552
|
return err(e);
|
|
2738
1553
|
}
|
|
@@ -2744,11 +1559,27 @@ function registerHyperliquidTools(server2) {
|
|
|
2744
1559
|
import { z as z7 } from "zod";
|
|
2745
1560
|
function registerGuideTools(server2) {
|
|
2746
1561
|
server2.tool(
|
|
2747
|
-
"
|
|
2748
|
-
"
|
|
2749
|
-
{
|
|
2750
|
-
|
|
2751
|
-
|
|
1562
|
+
"guide",
|
|
1563
|
+
"Setup guides. Actions: api_key (get AiCoin API key), upgrade (tier comparison)",
|
|
1564
|
+
{
|
|
1565
|
+
action: z7.enum(["api_key", "upgrade"]).describe(
|
|
1566
|
+
"api_key: register & get API key; upgrade: tier comparison & upgrade"
|
|
1567
|
+
),
|
|
1568
|
+
current_error: z7.string().optional().describe("For upgrade: the error message received"),
|
|
1569
|
+
endpoint: z7.string().optional().describe("For upgrade: the endpoint that returned 403")
|
|
1570
|
+
},
|
|
1571
|
+
async ({ action, current_error, endpoint }) => {
|
|
1572
|
+
switch (action) {
|
|
1573
|
+
case "api_key":
|
|
1574
|
+
return { content: [{ type: "text", text: getApiKeyGuide() }] };
|
|
1575
|
+
case "upgrade":
|
|
1576
|
+
return { content: [{ type: "text", text: getUpgradeGuide(current_error, endpoint) }] };
|
|
1577
|
+
}
|
|
1578
|
+
}
|
|
1579
|
+
);
|
|
1580
|
+
}
|
|
1581
|
+
function getApiKeyGuide() {
|
|
1582
|
+
return `# AiCoin OpenAPI Key Setup Guide
|
|
2752
1583
|
|
|
2753
1584
|
## Step 1: Register / Login
|
|
2754
1585
|
Visit https://www.aicoin.com and create an account (or log in).
|
|
@@ -2788,24 +1619,19 @@ Add them to your MCP client config:
|
|
|
2788
1619
|
}
|
|
2789
1620
|
\`\`\`
|
|
2790
1621
|
|
|
2791
|
-
After updating the config, restart your MCP client to apply
|
|
2792
|
-
|
|
2793
|
-
|
|
2794
|
-
|
|
2795
|
-
|
|
2796
|
-
|
|
2797
|
-
|
|
2798
|
-
|
|
2799
|
-
|
|
2800
|
-
|
|
2801
|
-
current_error: z7.string().optional().describe("The error message received"),
|
|
2802
|
-
endpoint: z7.string().optional().describe("The endpoint that returned 403")
|
|
2803
|
-
},
|
|
2804
|
-
async ({ current_error, endpoint }) => {
|
|
2805
|
-
const guide = `# AiCoin API Tier Upgrade Guide
|
|
1622
|
+
After updating the config, restart your MCP client to apply.
|
|
1623
|
+
|
|
1624
|
+
## Want Trading Features?
|
|
1625
|
+
For exchange trading (place orders, check balances), use the full AiCoin MCP:
|
|
1626
|
+
\`\`\`
|
|
1627
|
+
npx -y @aicoin/aicoin-mcp
|
|
1628
|
+
\`\`\``;
|
|
1629
|
+
}
|
|
1630
|
+
function getUpgradeGuide(currentError, endpoint) {
|
|
1631
|
+
return `# AiCoin API Tier Upgrade Guide
|
|
2806
1632
|
|
|
2807
1633
|
## Current Issue
|
|
2808
|
-
${
|
|
1634
|
+
${currentError ? `Error: ${currentError}` : "Your current API tier does not have permission for this endpoint."}
|
|
2809
1635
|
${endpoint ? `Endpoint: ${endpoint}` : ""}
|
|
2810
1636
|
|
|
2811
1637
|
## API Tier Comparison
|
|
@@ -2831,103 +1657,6 @@ ${endpoint ? `Endpoint: ${endpoint}` : ""}
|
|
|
2831
1657
|
5. Complete payment
|
|
2832
1658
|
|
|
2833
1659
|
After upgrading, your existing key will be automatically upgraded. No config changes needed.`;
|
|
2834
|
-
return {
|
|
2835
|
-
content: [{ type: "text", text: guide }]
|
|
2836
|
-
};
|
|
2837
|
-
}
|
|
2838
|
-
);
|
|
2839
|
-
server2.tool(
|
|
2840
|
-
"guide_setup_ccxt_trade",
|
|
2841
|
-
"Guide user to set up the AiCoin Trade MCP server (CCXT-based) for executing trades. Includes exchange API key setup and local proxy configuration.",
|
|
2842
|
-
{
|
|
2843
|
-
exchange: z7.string().optional().describe(
|
|
2844
|
-
"Target exchange: binance, okx, bybit, bitget, gate, huobi, pionex, hyperliquid"
|
|
2845
|
-
)
|
|
2846
|
-
},
|
|
2847
|
-
async ({ exchange }) => {
|
|
2848
|
-
const ex = exchange?.toLowerCase() || "binance";
|
|
2849
|
-
const needsPass = ex === "okx" || ex === "bitget";
|
|
2850
|
-
const EX = ex.toUpperCase();
|
|
2851
|
-
let keyBlock = `${EX}_API_KEY=your_api_key
|
|
2852
|
-
${EX}_SECRET=your_secret`;
|
|
2853
|
-
if (needsPass) keyBlock += `
|
|
2854
|
-
${EX}_PASSPHRASE=your_passphrase`;
|
|
2855
|
-
let envJson = ` "${EX}_API_KEY": "<your_api_key>",
|
|
2856
|
-
"${EX}_SECRET": "<your_secret>"`;
|
|
2857
|
-
if (needsPass) {
|
|
2858
|
-
envJson += `,
|
|
2859
|
-
"${EX}_PASSPHRASE": "<your_passphrase>"`;
|
|
2860
|
-
}
|
|
2861
|
-
const guide = getTradeGuide(ex, EX, keyBlock, envJson);
|
|
2862
|
-
return {
|
|
2863
|
-
content: [{ type: "text", text: guide }]
|
|
2864
|
-
};
|
|
2865
|
-
}
|
|
2866
|
-
);
|
|
2867
|
-
}
|
|
2868
|
-
function getExchangeGuide(ex) {
|
|
2869
|
-
const guides = {
|
|
2870
|
-
binance: '1. Log in to https://www.binance.com\n2. Go to Account \u2192 API Management\n3. Create API key, enable "Spot Trading" permission\n4. Recommended: set IP whitelist',
|
|
2871
|
-
okx: '1. Log in to https://www.okx.com\n2. Go to Account \u2192 API \u2192 Create API Key\n3. Set passphrase, enable "Trade" permission\n4. Note: OKX requires a passphrase in addition to key/secret',
|
|
2872
|
-
bybit: '1. Log in to https://www.bybit.com\n2. Go to Account \u2192 API Management\n3. Create API key with "Trade" permission',
|
|
2873
|
-
bitget: '1. Log in to https://www.bitget.com\n2. Go to Account \u2192 API Management\n3. Create API key with passphrase, enable "Trade"\n4. Note: Bitget requires a passphrase',
|
|
2874
|
-
gate: '1. Log in to https://www.gate.io\n2. Go to Account \u2192 API Management\n3. Create API key with "Spot Trade" permission',
|
|
2875
|
-
huobi: '1. Log in to https://www.huobi.com\n2. Go to Account \u2192 API Management\n3. Create API key with "Trade" permission',
|
|
2876
|
-
pionex: "1. Log in to https://www.pionex.com\n2. Go to Account \u2192 API Management\n3. Create API key",
|
|
2877
|
-
hyperliquid: "1. Visit https://app.hyperliquid.xyz\n2. Connect your wallet\n3. Go to API \u2192 Generate API Key"
|
|
2878
|
-
};
|
|
2879
|
-
return guides[ex] || guides.binance;
|
|
2880
|
-
}
|
|
2881
|
-
function getTradeGuide(ex, EX, keyBlock, envJson) {
|
|
2882
|
-
return `# AiCoin Trade MCP Setup Guide (CCXT)
|
|
2883
|
-
|
|
2884
|
-
> All API keys are stored locally only. They are never sent to AiCoin servers.
|
|
2885
|
-
|
|
2886
|
-
## Step 1: Get Exchange API Key
|
|
2887
|
-
|
|
2888
|
-
${getExchangeGuide(ex)}
|
|
2889
|
-
|
|
2890
|
-
\`\`\`
|
|
2891
|
-
${keyBlock}
|
|
2892
|
-
\`\`\`
|
|
2893
|
-
|
|
2894
|
-
## Step 2: Proxy Configuration
|
|
2895
|
-
|
|
2896
|
-
Many exchanges require proxy access in certain regions.
|
|
2897
|
-
If you are in mainland China or behind a firewall, you likely need a local proxy.
|
|
2898
|
-
|
|
2899
|
-
- If YES: set \`USE_PROXY=true\` and \`PROXY_URL\` (default: \`http://127.0.0.1:7890\`)
|
|
2900
|
-
- If NO: set \`USE_PROXY=false\` or leave it unset
|
|
2901
|
-
|
|
2902
|
-
Common proxy ports:
|
|
2903
|
-
- Clash: 7890
|
|
2904
|
-
- V2Ray: 10808
|
|
2905
|
-
- Shadowsocks: 1080
|
|
2906
|
-
|
|
2907
|
-
## Step 3: Configure MCP Client
|
|
2908
|
-
|
|
2909
|
-
\`\`\`json
|
|
2910
|
-
{
|
|
2911
|
-
"mcpServers": {
|
|
2912
|
-
"aicoin-trade": {
|
|
2913
|
-
"command": "npx",
|
|
2914
|
-
"args": ["-y", "@aicoin/trade-mcp"],
|
|
2915
|
-
"env": {
|
|
2916
|
-
"DEFAULT_EXCHANGE": "${ex}",
|
|
2917
|
-
${envJson},
|
|
2918
|
-
"USE_PROXY": "true",
|
|
2919
|
-
"PROXY_URL": "http://127.0.0.1:7890"
|
|
2920
|
-
}
|
|
2921
|
-
}
|
|
2922
|
-
}
|
|
2923
|
-
}
|
|
2924
|
-
\`\`\`
|
|
2925
|
-
|
|
2926
|
-
## Security Notes
|
|
2927
|
-
- API keys are stored in your local MCP config only
|
|
2928
|
-
- Never share your secret key with anyone
|
|
2929
|
-
- Enable IP whitelist on the exchange if possible
|
|
2930
|
-
- For trading, enable "Trade" permission; disable "Withdraw"`;
|
|
2931
1660
|
}
|
|
2932
1661
|
|
|
2933
1662
|
// src/tools/index.ts
|