@vike-io/cli 0.13.1 → 0.15.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/CHANGELOG.md +28 -0
- package/README.md +33 -19
- package/package.json +4 -4
- package/skills/vike/SKILL.md +144 -192
- package/skills/vike-alerts-setup/SKILL.md +37 -6
- package/skills/vike-alerts-webhook/SKILL.md +15 -8
- package/skills/vike-candles/SKILL.md +9 -2
- package/skills/vike-core/SKILL.md +16 -12
- package/skills/vike-hl-position-match/SKILL.md +8 -8
- package/skills/vike-hl-top-traders/SKILL.md +46 -11
- package/skills/vike-perp-funding/SKILL.md +82 -0
- package/skills/vike-perp-overview/SKILL.md +69 -0
- package/skills/vike-polymarket-market-detail/SKILL.md +2 -1
- package/skills/vike-polymarket-markets/SKILL.md +12 -7
- package/skills/vike-polymarket-smart-money/SKILL.md +38 -13
- package/skills/vike-polymarket-trader/SKILL.md +23 -20
- package/skills/vike-smart-money-discovery/SKILL.md +26 -32
- package/skills/vike-stream/SKILL.md +98 -0
- package/skills/vike-token-holders/SKILL.md +2 -1
- package/skills/vike-token-research/SKILL.md +22 -14
- package/skills/vike-token-screener/SKILL.md +35 -28
- package/skills/vike-token-transfers/SKILL.md +21 -11
- package/skills/vike-wallet-balances/SKILL.md +19 -13
- package/skills/vike-wallet-batch/SKILL.md +18 -14
- package/skills/vike-wallet-compare/SKILL.md +2 -0
- package/skills/vike-wallet-counterparties/SKILL.md +5 -1
- package/skills/vike-wallet-discover/SKILL.md +17 -10
- package/skills/vike-wallet-ens/SKILL.md +8 -4
- package/skills/vike-wallet-label-provenance/SKILL.md +25 -16
- package/skills/vike-wallet-pnl-history/SKILL.md +4 -1
- package/skills/vike-wallet-portfolio/SKILL.md +23 -21
- package/skills/vike-wallet-summary/SKILL.md +22 -9
- package/skills/vike-wallet-trace/SKILL.md +15 -11
- package/skills/vike-wallet-transactions/SKILL.md +3 -1
- package/skills.sh.json +17 -15
- package/src/auth.js +1 -1
- package/src/commands/alerts.js +85 -15
- package/src/commands/call.js +32 -0
- package/src/commands/candles.js +11 -15
- package/src/commands/doctor.js +4 -4
- package/src/commands/hl.js +274 -0
- package/src/commands/init.js +1 -1
- package/src/commands/labels.js +1 -1
- package/src/commands/perp.js +10 -9
- package/src/commands/polymarket.js +105 -5
- package/src/commands/search.js +10 -0
- package/src/commands/stream.js +308 -0
- package/src/commands/token.js +2 -0
- package/src/commands/tool-command.js +27 -0
- package/src/commands/wallet.js +24 -3
- package/src/index.js +10 -1
- package/src/mcp-client.js +37 -16
- package/skills/vike-cross-venue-perps/SKILL.md +0 -52
- package/skills/vike-hl-trader-profile/SKILL.md +0 -65
- package/skills/vike-perp-funding-arb/SKILL.md +0 -53
- package/skills/vike-perp-screener/SKILL.md +0 -48
- package/skills/vike-perp-spread-arb/SKILL.md +0 -38
- package/skills/vike-polymarket-screener/SKILL.md +0 -59
- package/skills/vike-router/SKILL.md +0 -54
package/src/auth.js
CHANGED
package/src/commands/alerts.js
CHANGED
|
@@ -1,11 +1,45 @@
|
|
|
1
1
|
import { callTool } from '../mcp-client.js';
|
|
2
2
|
import { emit, emitError } from '../format.js';
|
|
3
3
|
import { parseBool, parseInt10 } from '../util.js';
|
|
4
|
+
import { addTool } from './tool-command.js';
|
|
5
|
+
|
|
6
|
+
// What a rule watches beyond token and USD bounds: a transfer alert's address, and the Hyperliquid
|
|
7
|
+
// parameters. Which alert type takes which is the server's to check; it names the fix.
|
|
8
|
+
const TARGET_OPTIONS = [
|
|
9
|
+
['--address <a>', 'transfer: one wallet to watch (0x + 40 hex), sent or received'],
|
|
10
|
+
['--address-role <r>', 'transfer: any | from | to (default any; needs --address)'],
|
|
11
|
+
['--wallet <a>', 'Hyperliquid account (0x + 40 hex): required by hl_wallet and hl_liq_proximity, optional for hl_liquidation'],
|
|
12
|
+
['--actions <a...>', 'hl_wallet: open close flip increase reduce (default all but reduce)'],
|
|
13
|
+
['--pnl-cohorts <c...>', 'hl_cohort_fill, hl_liquidation: PnL cohorts, e.g. "3x smart" "2x smart"'],
|
|
14
|
+
['--size-cohorts <c...>', 'hl_cohort_fill, hl_liquidation: size cohorts, e.g. "4x whale" whale'],
|
|
15
|
+
['--index <i>', 'hl_cohort_bias (required): smi | wsi | smart_bias | whale_bias | smi_wsi_gap'],
|
|
16
|
+
['--threshold <n>', 'hl_cohort_bias: level to cross (default 0); hl_liq_proximity: share of the way to liquidation, 0-1 (default 0.8)'],
|
|
17
|
+
['--band <n>', 'hl_cohort_bias, hl_liq_proximity: hysteresis, > 0 (default 0.1)'],
|
|
18
|
+
['--direction <d>', 'hl_cohort_bias: up | down | both (default both)'],
|
|
19
|
+
];
|
|
20
|
+
|
|
21
|
+
// `--pnl-cohorts ''` clears the list: send [] (the server refuses ['']).
|
|
22
|
+
const list = (v) => (Array.isArray(v) && v.every((x) => x === '') ? [] : v);
|
|
23
|
+
|
|
24
|
+
function targetArgs(opts) {
|
|
25
|
+
return {
|
|
26
|
+
address: opts.address,
|
|
27
|
+
address_role: opts.addressRole,
|
|
28
|
+
wallet: opts.wallet,
|
|
29
|
+
actions: list(opts.actions),
|
|
30
|
+
pnl_cohorts: list(opts.pnlCohorts),
|
|
31
|
+
size_cohorts: list(opts.sizeCohorts),
|
|
32
|
+
index: opts.index,
|
|
33
|
+
threshold: opts.threshold,
|
|
34
|
+
band: opts.band,
|
|
35
|
+
direction: opts.direction,
|
|
36
|
+
};
|
|
37
|
+
}
|
|
4
38
|
|
|
5
39
|
export function registerAlerts(program) {
|
|
6
40
|
const cmd = program
|
|
7
41
|
.command('alerts')
|
|
8
|
-
.description('Manage on-chain
|
|
42
|
+
.description('Manage alerts: on-chain transfers and Hyperliquid fills, liquidations, cohort bias and liquidation proximity');
|
|
9
43
|
|
|
10
44
|
cmd
|
|
11
45
|
.command('list')
|
|
@@ -38,7 +72,7 @@ export function registerAlerts(program) {
|
|
|
38
72
|
|
|
39
73
|
cmd
|
|
40
74
|
.command('channels')
|
|
41
|
-
.description('List your enabled notification channels (email/
|
|
75
|
+
.description('List your enabled notification channels (email/webhook)')
|
|
42
76
|
.option('--json', 'Emit JSON')
|
|
43
77
|
.action(async (opts) => {
|
|
44
78
|
try {
|
|
@@ -47,25 +81,31 @@ export function registerAlerts(program) {
|
|
|
47
81
|
} catch (err) { emitError(err, opts); }
|
|
48
82
|
});
|
|
49
83
|
|
|
50
|
-
cmd
|
|
84
|
+
const create = cmd
|
|
51
85
|
.command('create')
|
|
52
|
-
.description('Create
|
|
86
|
+
.description('Create an alert: an on-chain transfer alert (default) or a Hyperliquid alert (--type)')
|
|
53
87
|
.requiredOption('--label <l>', 'Alert label (user-visible name)')
|
|
54
|
-
.option('--
|
|
55
|
-
.option('--
|
|
56
|
-
|
|
57
|
-
.option('--
|
|
58
|
-
.option('--
|
|
59
|
-
.option('--
|
|
88
|
+
.option('--type <t>', 'transfer | hl_wallet | hl_cohort_fill | hl_liquidation | hl_cohort_bias | hl_liq_proximity (default transfer)')
|
|
89
|
+
.option('--token <sym>', 'transfer: token ticker, UPPERCASE (e.g. USDC); Hyperliquid: the coin (BTC, kPEPE), required by hl_cohort_bias')
|
|
90
|
+
// No default chain: a Hyperliquid alert refuses one.
|
|
91
|
+
.option('--chain <c>', 'transfer only: eth | bsc | base | hyperevm (default eth)')
|
|
92
|
+
.option('--min-usd <n>', 'transfer: minimum USD value; Hyperliquid: fill or liquidation floor (hl_cohort_fill: required, >= 10000)')
|
|
93
|
+
.option('--max-usd <n>', 'transfer only: maximum USD value');
|
|
94
|
+
for (const [flags, text] of TARGET_OPTIONS) create.option(flags, text);
|
|
95
|
+
create
|
|
96
|
+
.option('--channel <c...>', 'Notification channel(s): email, webhook (Hyperliquid: webhook, or none and read them with `alerts events`)')
|
|
97
|
+
.option('--cooldown <min>', 'Token-wide transfer alerts: minimum gap between notifications (minutes)', '60')
|
|
60
98
|
.option('--json', 'Emit JSON')
|
|
61
99
|
.action(async (opts) => {
|
|
62
100
|
try {
|
|
63
101
|
const r = await callTool('alerts_create', {
|
|
64
102
|
label: opts.label,
|
|
103
|
+
alert_type: opts.type,
|
|
65
104
|
token_symbol: opts.token,
|
|
66
105
|
chain: opts.chain,
|
|
67
106
|
min_value_usd: opts.minUsd,
|
|
68
107
|
max_value_usd: opts.maxUsd,
|
|
108
|
+
...targetArgs(opts),
|
|
69
109
|
channels: opts.channel,
|
|
70
110
|
cooldown_minutes: parseInt10(opts.cooldown, 60),
|
|
71
111
|
});
|
|
@@ -73,27 +113,29 @@ export function registerAlerts(program) {
|
|
|
73
113
|
} catch (err) { emitError(err, opts); }
|
|
74
114
|
});
|
|
75
115
|
|
|
76
|
-
cmd
|
|
116
|
+
const edit = cmd
|
|
77
117
|
.command('edit <alert_id>')
|
|
78
|
-
.description('Update an alert (only fields you pass are modified)')
|
|
118
|
+
.description('Update an alert (only fields you pass are modified; \'\' clears an optional one)')
|
|
79
119
|
.option('--label <l>')
|
|
80
120
|
.option('--token <sym>')
|
|
81
121
|
.option('--chain <c>')
|
|
82
122
|
.option('--min-usd <n>')
|
|
83
|
-
.option('--max-usd <n>')
|
|
123
|
+
.option('--max-usd <n>');
|
|
124
|
+
for (const [flags, text] of TARGET_OPTIONS) edit.option(flags, text);
|
|
125
|
+
edit
|
|
84
126
|
.option('--channel <c...>')
|
|
85
127
|
.option('--cooldown <min>')
|
|
86
128
|
.option('--active <bool>', 'Pause/resume (true|false)')
|
|
87
129
|
.option('--json', 'Emit JSON')
|
|
88
130
|
.action(async (alertId, opts) => {
|
|
89
131
|
try {
|
|
90
|
-
const payload = { alert_id: alertId };
|
|
132
|
+
const payload = { alert_id: alertId, ...targetArgs(opts) };
|
|
91
133
|
if (opts.label !== undefined) payload.label = opts.label;
|
|
92
134
|
if (opts.token !== undefined) payload.token_symbol = opts.token;
|
|
93
135
|
if (opts.chain !== undefined) payload.chain = opts.chain;
|
|
94
136
|
if (opts.minUsd !== undefined) payload.min_value_usd = opts.minUsd;
|
|
95
137
|
if (opts.maxUsd !== undefined) payload.max_value_usd = opts.maxUsd;
|
|
96
|
-
if (opts.channel !== undefined) payload.channels = opts.channel;
|
|
138
|
+
if (opts.channel !== undefined) payload.channels = list(opts.channel);
|
|
97
139
|
if (opts.cooldown !== undefined) payload.cooldown_minutes = opts.cooldown;
|
|
98
140
|
if (opts.active !== undefined) payload.is_active = parseBool(opts.active, true);
|
|
99
141
|
const r = await callTool('alerts_edit', payload);
|
|
@@ -115,4 +157,32 @@ export function registerAlerts(program) {
|
|
|
115
157
|
emit(r, opts);
|
|
116
158
|
} catch (err) { emitError(err, opts); }
|
|
117
159
|
});
|
|
160
|
+
|
|
161
|
+
addTool(cmd, 'events', {
|
|
162
|
+
tool: 'alerts_events',
|
|
163
|
+
desc: 'Events your alerts produced, oldest first, with each delivery\'s status (kept 15 days)',
|
|
164
|
+
options: [
|
|
165
|
+
['--cursor <c>', 'next_cursor from the previous page (an empty page returns the same one)'],
|
|
166
|
+
['--limit <n>', 'Events per page, 1-500 (default 100)'],
|
|
167
|
+
['--rule-id <id>', 'Only the events of this alert'],
|
|
168
|
+
],
|
|
169
|
+
});
|
|
170
|
+
|
|
171
|
+
addTool(cmd, 'resend <delivery_id>', {
|
|
172
|
+
tool: 'alerts_resend_delivery',
|
|
173
|
+
args: ['delivery_id'],
|
|
174
|
+
desc: 'Send one delivery again (its id from an event\'s delivery list in `alerts events`)',
|
|
175
|
+
});
|
|
176
|
+
|
|
177
|
+
addTool(cmd, 'rotate-secret <channel_id>', {
|
|
178
|
+
tool: 'alerts_rotate_webhook_secret',
|
|
179
|
+
args: ['channel_id'],
|
|
180
|
+
desc: 'New signing secret for a webhook channel; the old one keeps signing for 24 hours',
|
|
181
|
+
});
|
|
182
|
+
|
|
183
|
+
addTool(cmd, 'test-webhook <channel_id>', {
|
|
184
|
+
tool: 'alerts_test_webhook',
|
|
185
|
+
args: ['channel_id'],
|
|
186
|
+
desc: 'Send the signed test event to a webhook channel again',
|
|
187
|
+
});
|
|
118
188
|
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { readFileSync } from 'node:fs';
|
|
2
|
+
import { callTool } from '../mcp-client.js';
|
|
3
|
+
import { emitError } from '../format.js';
|
|
4
|
+
|
|
5
|
+
export function registerCall(program) {
|
|
6
|
+
program
|
|
7
|
+
.command('call <tool>')
|
|
8
|
+
.description('Call any MCP tool by name and print its raw result (see `vike-data schema --pretty` for the tools and their arguments)')
|
|
9
|
+
.option('--args <json>', 'Tool arguments as a JSON object, e.g. \'{"symbol":"BTC"}\'')
|
|
10
|
+
.option('--args-file <path>', 'Read the arguments JSON from a file (- for stdin)')
|
|
11
|
+
.option('--timeout <s>', 'Seconds to wait for the answer', '60')
|
|
12
|
+
.option('--json', 'Errors as JSON on stdout (the result is JSON either way)')
|
|
13
|
+
.action(async (tool, opts) => {
|
|
14
|
+
try {
|
|
15
|
+
const text = (opts.argsFile !== undefined
|
|
16
|
+
? readFileSync(opts.argsFile === '-' ? 0 : opts.argsFile, 'utf8')
|
|
17
|
+
: (opts.args ?? '{}')).replace(/^/, '').trim(); // a file saved with a UTF-8 BOM
|
|
18
|
+
let args;
|
|
19
|
+
try { args = JSON.parse(text); } catch (err) {
|
|
20
|
+
throw new Error(`arguments are not valid JSON: ${err.message}`);
|
|
21
|
+
}
|
|
22
|
+
if (!args || typeof args !== 'object' || Array.isArray(args)) {
|
|
23
|
+
throw new Error('arguments must be a JSON object, e.g. {"address":"0x..."}');
|
|
24
|
+
}
|
|
25
|
+
const seconds = Number(opts.timeout);
|
|
26
|
+
if (!(seconds > 0)) throw new Error(`--timeout must be a positive number of seconds, got ${opts.timeout}`);
|
|
27
|
+
// Parsed only to check it; the text itself is sent, so numbers above 2^53 are not rounded.
|
|
28
|
+
const r = await callTool(tool, args, { raw: true, argsText: text, timeoutMs: seconds * 1000 });
|
|
29
|
+
process.stdout.write((typeof r === 'string' ? r : JSON.stringify(r)) + '\n');
|
|
30
|
+
} catch (err) { emitError(err, opts); }
|
|
31
|
+
});
|
|
32
|
+
}
|
package/src/commands/candles.js
CHANGED
|
@@ -8,26 +8,22 @@ export function registerCandles(program) {
|
|
|
8
8
|
.description('Historical OHLCV candles — Hyperliquid markets and Polymarket outcome tokens');
|
|
9
9
|
|
|
10
10
|
cmd
|
|
11
|
-
.command('hl
|
|
12
|
-
.description('Hyperliquid candles (perp or spot), aggregated from HL executed fills')
|
|
13
|
-
.option('--
|
|
14
|
-
.option('--
|
|
15
|
-
.option('--
|
|
11
|
+
.command('hl [symbol]')
|
|
12
|
+
.description('Hyperliquid candles (perp or spot), aggregated from HL executed fills; --view latest = the newest 1m bar of every symbol')
|
|
13
|
+
.option('--view <v>', 'candles (default; needs <symbol>) | export (the same, limit defaults to 5000) | latest (every symbol, no <symbol>)')
|
|
14
|
+
.option('--interval <i>', '1m | 5m | 15m | 30m | 1h | 4h | 1d (default 1h; latest: 1m only)')
|
|
15
|
+
.option('--market <m>', 'perp | spot (default perp)')
|
|
16
|
+
.option('--dex <d>', 'Perp DEX (default HL, the core venue; others are HIP-3 builder DEXs; latest: omit for every DEX)')
|
|
16
17
|
.option('--start <t>', 'ISO-8601 UTC or epoch ms (inclusive)')
|
|
17
18
|
.option('--end <t>', 'ISO-8601 UTC or epoch ms (exclusive)')
|
|
18
|
-
.option('--limit <n>', 'Max candles (default 500, max 5000)'
|
|
19
|
+
.option('--limit <n>', 'Max candles (default 500, export 5000; max 5000)')
|
|
19
20
|
.option('--json', 'Emit JSON')
|
|
20
21
|
.action(async (symbol, opts) => {
|
|
21
22
|
try {
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
limit: parseInt10(opts.limit, 500),
|
|
27
|
-
};
|
|
28
|
-
if (opts.dex !== undefined) args.dex = opts.dex;
|
|
29
|
-
if (opts.start !== undefined) args.start = opts.start;
|
|
30
|
-
if (opts.end !== undefined) args.end = opts.end;
|
|
23
|
+
// Only what was given: the server's defaults stay the defaults. `latest` takes only market, dex and
|
|
24
|
+
// interval, so a symbol, window or limit is not sent with it.
|
|
25
|
+
const args = { view: opts.view, interval: opts.interval, market: opts.market, dex: opts.dex };
|
|
26
|
+
if (opts.view !== 'latest') Object.assign(args, { symbol, start: opts.start, end: opts.end, limit: opts.limit });
|
|
31
27
|
const r = await callTool('hl_ohlcv', args);
|
|
32
28
|
emit(r, opts);
|
|
33
29
|
} catch (err) { emitError(err, opts); }
|
package/src/commands/doctor.js
CHANGED
|
@@ -8,13 +8,13 @@ export function registerDoctor(program) {
|
|
|
8
8
|
.action(async () => {
|
|
9
9
|
const checks = [];
|
|
10
10
|
|
|
11
|
-
// 1. Node version
|
|
11
|
+
// 1. Node version: package.json engines is >=22.12.0
|
|
12
12
|
const nodeVer = process.version;
|
|
13
|
-
const major =
|
|
13
|
+
const [major, minor] = process.versions.node.split('.').map(Number);
|
|
14
14
|
checks.push({
|
|
15
15
|
name: 'Node runtime',
|
|
16
|
-
ok: major >=
|
|
17
|
-
detail: `${nodeVer} (need >=
|
|
16
|
+
ok: major > 22 || (major === 22 && minor >= 12),
|
|
17
|
+
detail: `${nodeVer} (need >= 22.12.0)`,
|
|
18
18
|
});
|
|
19
19
|
|
|
20
20
|
// 2. API key
|
|
@@ -0,0 +1,274 @@
|
|
|
1
|
+
import { addTool } from './tool-command.js';
|
|
2
|
+
|
|
3
|
+
// One subcommand per Hyperliquid MCP tool; each takes `--view` (the first view is the default).
|
|
4
|
+
// `hl_perp_top_traders` and `hl_position_match` stay under `perp`, candles under `candles`.
|
|
5
|
+
// Flags carry the tool's own parameter names (--opened-within -> opened_within).
|
|
6
|
+
const view = (views) => ['--view <v>', `${views.join(' | ')} (default ${views[0]})`];
|
|
7
|
+
const SYMBOL = ['--symbol <s>', 'Instrument, e.g. BTC; a HIP-3 market is dex:TICKER (xyz:TSLA)'];
|
|
8
|
+
const START = ['--start <t>', 'ISO-8601 UTC lower bound, e.g. 2026-10-01T00:00:00Z'];
|
|
9
|
+
const END = ['--end <t>', 'ISO-8601 UTC upper bound'];
|
|
10
|
+
const CURSOR = ['--cursor <c>', 'nextCursor from the previous page, verbatim'];
|
|
11
|
+
const LIMIT = ['--limit <n>', 'Rows per page'];
|
|
12
|
+
const OPENED = ['--opened-within <w>', 'Only positions opened within: 24h | 7d | 30d | all'];
|
|
13
|
+
const AXIS = ['--axis <a>', 'Cohort ladder: size | pnl | pnl_abs'];
|
|
14
|
+
const COHORT = ['--cohort <c>', 'One cohort label on --axis, e.g. whale or "3x smart" (`hl segments --view cohorts` lists them)'];
|
|
15
|
+
const WINDOW = ['--window <w>', '1d | 7d | 30d | all'];
|
|
16
|
+
const VAULT_WINDOW = ['--window <w>', '7d | 30d | 90d | 365d | all'];
|
|
17
|
+
const ORDER = ['--order <o>', 'desc | asc'];
|
|
18
|
+
const SIDE = ['--side <s>', 'buy | sell'];
|
|
19
|
+
const WALLET = ['--wallet <a>', 'One wallet (0x + 40 hex)'];
|
|
20
|
+
|
|
21
|
+
export function registerHl(program) {
|
|
22
|
+
const hl = program
|
|
23
|
+
.command('hl')
|
|
24
|
+
.description('Hyperliquid: cohort positioning, wallets, leaderboards, liquidations, markets, builders, vaults');
|
|
25
|
+
|
|
26
|
+
addTool(hl, 'cohort-metrics <symbol>', {
|
|
27
|
+
tool: 'hl_cohort_metrics',
|
|
28
|
+
args: ['symbol'],
|
|
29
|
+
desc: 'Hourly long/short positioning of one perp split by cohort (are whales / smart money long or short)',
|
|
30
|
+
options: [
|
|
31
|
+
['--axis <a>', 'size | pnl | pnl_abs | tier | trade_size | pnl_unrealized (default size)'],
|
|
32
|
+
['--hours <n>', 'Hourly buckets, newest first, max 8760 (default 168; 1-24 for a current read)'],
|
|
33
|
+
START, END, OPENED,
|
|
34
|
+
['--label-basis <b>', 'current | point_in_time (point_in_time for any backtest)'],
|
|
35
|
+
['--grading <g>', 'realized | realized-pit | unrealized (pnl axes only)'],
|
|
36
|
+
['--include <list>', 'Comma list: volume, median_pnl (newest hour only)'],
|
|
37
|
+
CURSOR,
|
|
38
|
+
],
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
addTool(hl, 'segments', {
|
|
42
|
+
tool: 'hl_segments',
|
|
43
|
+
desc: 'Cohort vocabulary, one cohort now, the symbol x cohort board, or one cohort hour by hour',
|
|
44
|
+
options: [
|
|
45
|
+
view(['segments', 'cohorts', 'summary', 'heatmap', 'history']),
|
|
46
|
+
['--cohort <c>', 'One label (required by summary and history)'],
|
|
47
|
+
['--axis <a>', 'size | pnl | pnl_abs (history: size or pnl, required)'],
|
|
48
|
+
OPENED, START, END,
|
|
49
|
+
['--hours <n>', 'history: window length in hours (default 168)'],
|
|
50
|
+
['--limit <n>', 'history: max hourly rows (default 5000)'],
|
|
51
|
+
['--include <list>', 'history: leverage'],
|
|
52
|
+
],
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
addTool(hl, 'wallet <address>', {
|
|
56
|
+
tool: 'hl_wallet',
|
|
57
|
+
args: ['address'],
|
|
58
|
+
desc: 'One wallet: equity, open positions, cohort labels, risk metrics and lifetime flow (or closed-trade stats)',
|
|
59
|
+
options: [view(['summary', 'trades_summary']), WINDOW, OPENED],
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
addTool(hl, 'wallet-activity <address>', {
|
|
63
|
+
tool: 'hl_wallet_activity',
|
|
64
|
+
args: ['address'],
|
|
65
|
+
desc: 'One wallet\'s fills, funding, ledger (deposits, withdrawals, transfers, vault events) or builder routing',
|
|
66
|
+
options: [
|
|
67
|
+
view(['fills', 'funding', 'ledger', 'builders']),
|
|
68
|
+
SYMBOL, START, END, SIDE,
|
|
69
|
+
['--event-type <t>', 'ledger: one event type, e.g. deposit, withdraw, vaultDeposit'],
|
|
70
|
+
['--window <w>', 'builders: 1d | 7d | 30d | all'],
|
|
71
|
+
['--limit <n>', 'Rows per page (default 100, max 5000; builders 50, max 500)'],
|
|
72
|
+
CURSOR,
|
|
73
|
+
],
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
addTool(hl, 'leaderboard', {
|
|
77
|
+
tool: 'hl_leaderboard',
|
|
78
|
+
desc: 'Traders ranked on any of 20 metrics with the full risk set, or on fills-derived trading PnL',
|
|
79
|
+
options: [
|
|
80
|
+
view(['ranking', 'flow_adjusted']),
|
|
81
|
+
['--window <w>', '1d | 7d | 30d | all (default 30d)'],
|
|
82
|
+
['--sort <s>', 'pnl | realized_pnl | roi | volume | trades | win_rate | profit_factor | calmar | max_drawdown | ... (default pnl)'],
|
|
83
|
+
ORDER, COHORT, AXIS,
|
|
84
|
+
['--min-trades <n>', 'Minimum closed trades (default 3; 0 = no floor)'],
|
|
85
|
+
['--min-win-rate <f>', 'FRACTION 0-1 (0.6 = 60%), unlike `perp top-traders`'],
|
|
86
|
+
['--min-volume <usd>', 'Minimum total volume in USD'],
|
|
87
|
+
['--limit <n>', 'Rows per page (default 25, max 500)'],
|
|
88
|
+
CURSOR,
|
|
89
|
+
],
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
addTool(hl, 'liquidations', {
|
|
93
|
+
tool: 'hl_liquidations',
|
|
94
|
+
desc: 'Liquidation events, the share of open notional near liquidation per symbol, or one symbol\'s liquidation heatmap',
|
|
95
|
+
options: [
|
|
96
|
+
view(['fills', 'risk', 'heatmap']),
|
|
97
|
+
['--symbol <s>', 'One symbol (required by heatmap)'],
|
|
98
|
+
['--wallet <a>', 'fills: has this wallet been liquidated'],
|
|
99
|
+
START, END,
|
|
100
|
+
['--direction <d>', 'fills: long | short, the side that was closed'],
|
|
101
|
+
AXIS, COHORT,
|
|
102
|
+
['--min-value-usd <usd>', 'risk: smallest open notional a symbol needs to be ranked'],
|
|
103
|
+
['--bins <n>', 'heatmap: price bins, 5-500 (default 50)'],
|
|
104
|
+
['--limit <n>', 'Rows per page (fills max 5000, risk max 500)'],
|
|
105
|
+
CURSOR,
|
|
106
|
+
],
|
|
107
|
+
});
|
|
108
|
+
|
|
109
|
+
addTool(hl, 'market', {
|
|
110
|
+
tool: 'hl_market',
|
|
111
|
+
desc: 'Open interest per symbol, one symbol\'s hourly series, size breakdown, positions, indices or large fills',
|
|
112
|
+
options: [
|
|
113
|
+
view(['open_interest', 'symbol_metrics', 'size_breakdown', 'positions', 'indices', 'large_fills', 'hourly']),
|
|
114
|
+
['--symbol <s>', 'One symbol (required by every view but open_interest, positions and hourly)'],
|
|
115
|
+
['--symbols <list>', 'hourly: comma-separated perps, at most 64 (close, open interest, funding, premium)'],
|
|
116
|
+
['--days <n>', 'hourly: days back from --end, 1-400 (default 120)'],
|
|
117
|
+
WALLET, AXIS, COHORT, OPENED, START, END,
|
|
118
|
+
['--open-only <bool>', 'positions: true (default) = latest open; false needs --start'],
|
|
119
|
+
['--sort <s>', 'positions: size = biggest positions of one --symbol first'],
|
|
120
|
+
['--resolution <r>', 'positions history: 5m | 1h'],
|
|
121
|
+
['--label-basis <b>', 'symbol_metrics: current'],
|
|
122
|
+
['--hours <n>', 'indices: window in hours; large_fills: look-back, max 24'],
|
|
123
|
+
['--min-usd <usd>', 'large_fills: smallest fill, at least 50000'],
|
|
124
|
+
LIMIT, CURSOR,
|
|
125
|
+
],
|
|
126
|
+
});
|
|
127
|
+
|
|
128
|
+
addTool(hl, 'builders', {
|
|
129
|
+
tool: 'hl_builders',
|
|
130
|
+
desc: 'Builder codes: leaderboard, venue-wide stats, one builder\'s profile, users, fills or series',
|
|
131
|
+
options: [
|
|
132
|
+
view(['leaderboard', 'stats', 'profile', 'users', 'fills', 'series']),
|
|
133
|
+
['--builder <a>', 'Builder address (required by profile, users, fills, series)'],
|
|
134
|
+
['--window <w>', '1d | 7d | 30d | all (default 30d)'],
|
|
135
|
+
['--sort <s>', 'leaderboard: fee | volume | users | fills; users: volume | fees | pnl'],
|
|
136
|
+
ORDER, SYMBOL, SIDE, START, END,
|
|
137
|
+
['--bucket <b>', 'series: 1h | 1d'],
|
|
138
|
+
['--breakdown-limit <n>', 'profile: rows per breakdown, max 1000'],
|
|
139
|
+
LIMIT, CURSOR,
|
|
140
|
+
],
|
|
141
|
+
});
|
|
142
|
+
|
|
143
|
+
addTool(hl, 'vaults', {
|
|
144
|
+
tool: 'hl_vaults',
|
|
145
|
+
desc: 'Every vault with TVL, APR, PnL and flows, platform vault stats, or deposits and withdrawals across vaults',
|
|
146
|
+
options: [
|
|
147
|
+
view(['list', 'stats', 'flows']),
|
|
148
|
+
VAULT_WINDOW,
|
|
149
|
+
['--sort <s>', 'list: tvl | apr | pnl | return | net_flow | volume | age | leverage | top5_share'],
|
|
150
|
+
ORDER,
|
|
151
|
+
['--status <s>', 'list: open | closed | all'],
|
|
152
|
+
['--deposits <d>', 'list: any | open | closed'],
|
|
153
|
+
['--min-tvl <usd>', 'list: minimum TVL in USD'],
|
|
154
|
+
['--q <text>', 'list: part of a vault name, or an address prefix'],
|
|
155
|
+
['--min-usd <usd>', 'flows: smallest flow in USD (default 10000)'],
|
|
156
|
+
['--type <t>', 'flows: all | deposit | withdraw | distribution | commission'],
|
|
157
|
+
['--smart-only <bool>', 'flows: only top-1000 all-time PnL depositors'],
|
|
158
|
+
LIMIT, CURSOR,
|
|
159
|
+
],
|
|
160
|
+
});
|
|
161
|
+
|
|
162
|
+
addTool(hl, 'vault <vault>', {
|
|
163
|
+
tool: 'hl_vault',
|
|
164
|
+
args: ['vault'],
|
|
165
|
+
desc: 'One vault: profile, depositors, its own flows, or an equity / PnL series',
|
|
166
|
+
options: [
|
|
167
|
+
view(['profile', 'depositors', 'flows', 'series']),
|
|
168
|
+
['--sort <s>', 'depositors: share | pnl | all_time_pnl | entered'],
|
|
169
|
+
ORDER,
|
|
170
|
+
['--smart-only <bool>', 'depositors: only top-1000 all-time PnL wallets'],
|
|
171
|
+
['--min-equity-usd <usd>', 'depositors: smallest equity, at least 1'],
|
|
172
|
+
VAULT_WINDOW,
|
|
173
|
+
['--type <t>', 'flows: all | deposit | withdraw | distribution | commission'],
|
|
174
|
+
['--bucket <b>', 'series: 1h | 1d'],
|
|
175
|
+
START, END, LIMIT, CURSOR,
|
|
176
|
+
],
|
|
177
|
+
});
|
|
178
|
+
|
|
179
|
+
// The cross-wallet feeds (twaps, ledger, leverage-changes): `--order asc` follows a feed; resend the same
|
|
180
|
+
// filters with each nextCursor and stop on an empty page.
|
|
181
|
+
const FEED_ORDER = ['--order <o>', 'desc (default) | asc (to follow the feed)'];
|
|
182
|
+
const FEED_WINDOW = ['--start <t>', 'ISO-8601 UTC lower bound (default: 24 hours before --end, unless --wallet)'];
|
|
183
|
+
|
|
184
|
+
addTool(hl, 'orders', {
|
|
185
|
+
tool: 'hl_orders',
|
|
186
|
+
desc: 'Standing orders: resting at one instant, one wallet\'s orders over a window, or one symbol\'s order clusters',
|
|
187
|
+
options: [
|
|
188
|
+
view(['open', 'wallet', 'clusters']),
|
|
189
|
+
['--symbol <s>', 'open: symbol and/or --wallet required; clusters: required'],
|
|
190
|
+
['--wallet <a>', 'open: one wallet\'s resting orders'],
|
|
191
|
+
['--address <a>', 'wallet: the wallet (required)'],
|
|
192
|
+
['--at <t>', 'open, clusters: ISO-8601 UTC instant (default the newest snapshot)'],
|
|
193
|
+
['--oid <n>', 'open: one order id'],
|
|
194
|
+
['--order-type <t>', 'open: Limit | Stop Market | Stop Limit | Take Profit Market | Take Profit Limit | Trailing Stop Market'],
|
|
195
|
+
['--created-from <t>', 'open: placed at or after (ISO-8601 UTC)'],
|
|
196
|
+
['--created-to <t>', 'open: placed at or before (ISO-8601 UTC)'],
|
|
197
|
+
['--from <t>', 'wallet: window start (default 7 days before --to)'],
|
|
198
|
+
['--to <t>', 'wallet: window end (default the newest snapshot; at most 30 days)'],
|
|
199
|
+
['--status <s>', 'wallet: open | filled | partially_filled | canceled_or_expired'],
|
|
200
|
+
['--step-bps <n>', 'clusters: bucket width in basis points (default 10)'],
|
|
201
|
+
['--range-pct <n>', 'clusters: half-width around the mid in percent (default 10)'],
|
|
202
|
+
['--cohort-axis <a>', 'clusters: size | pnl | pnl_abs'],
|
|
203
|
+
['--cohort <c>', 'clusters: one cohort label (current labels; not with --at)'],
|
|
204
|
+
LIMIT, CURSOR,
|
|
205
|
+
],
|
|
206
|
+
});
|
|
207
|
+
|
|
208
|
+
addTool(hl, 'twaps', {
|
|
209
|
+
tool: 'hl_twaps',
|
|
210
|
+
desc: 'TWAP status lines across wallets, or one wallet\'s or one TWAP\'s',
|
|
211
|
+
options: [
|
|
212
|
+
WALLET,
|
|
213
|
+
['--twap-id <n>', 'One TWAP: every status line of it'],
|
|
214
|
+
SYMBOL,
|
|
215
|
+
['--status <s>', 'activated | waitingForTrigger | finished | terminated | stopped | error'],
|
|
216
|
+
FEED_WINDOW, END, FEED_ORDER, LIMIT, CURSOR,
|
|
217
|
+
],
|
|
218
|
+
});
|
|
219
|
+
|
|
220
|
+
addTool(hl, 'ledger', {
|
|
221
|
+
tool: 'hl_ledger',
|
|
222
|
+
desc: 'Deposits, withdrawals, transfers and vault events across wallets',
|
|
223
|
+
options: [
|
|
224
|
+
WALLET,
|
|
225
|
+
['--event-type <t>', 'One event type, e.g. deposit, withdraw, send, vaultDeposit'],
|
|
226
|
+
['--min-usd <usd>', 'Smallest absolute amount_usd'],
|
|
227
|
+
FEED_WINDOW, END, FEED_ORDER, LIMIT, CURSOR,
|
|
228
|
+
],
|
|
229
|
+
});
|
|
230
|
+
|
|
231
|
+
addTool(hl, 'leverage-changes', {
|
|
232
|
+
tool: 'hl_leverage_changes',
|
|
233
|
+
desc: 'Positions whose leverage or margin mode changed between two snapshots',
|
|
234
|
+
options: [
|
|
235
|
+
WALLET, SYMBOL,
|
|
236
|
+
['--change <c>', 'up | down | mode'],
|
|
237
|
+
['--min-leverage <x>', 'Smallest new leverage'],
|
|
238
|
+
FEED_WINDOW, END, FEED_ORDER, LIMIT, CURSOR,
|
|
239
|
+
],
|
|
240
|
+
});
|
|
241
|
+
|
|
242
|
+
addTool(hl, 'wallet-trades <address>', {
|
|
243
|
+
tool: 'hl_wallet_trades',
|
|
244
|
+
args: ['address'],
|
|
245
|
+
desc: 'One wallet\'s closed round-trip trades, newest close first',
|
|
246
|
+
options: [SYMBOL, START, END, LIMIT, CURSOR],
|
|
247
|
+
});
|
|
248
|
+
|
|
249
|
+
addTool(hl, 'stats', {
|
|
250
|
+
tool: 'hl_stats',
|
|
251
|
+
desc: 'Hourly venue-wide perp equity, open interest and positions, or hourly perp volume',
|
|
252
|
+
options: [
|
|
253
|
+
view(['ecosystem', 'volume']),
|
|
254
|
+
['--symbol <s>', 'volume: one symbol (omit for the whole venue)'],
|
|
255
|
+
START, END, LIMIT, CURSOR,
|
|
256
|
+
],
|
|
257
|
+
});
|
|
258
|
+
|
|
259
|
+
addTool(hl, 'hype-holders', {
|
|
260
|
+
tool: 'hl_hype_holders',
|
|
261
|
+
desc: 'HYPE holders ranked by spot balance plus staked',
|
|
262
|
+
options: [['--order <o>', 'desc (default) | asc'], LIMIT, CURSOR],
|
|
263
|
+
});
|
|
264
|
+
|
|
265
|
+
addTool(hl, 'archive', {
|
|
266
|
+
tool: 'hl_archive',
|
|
267
|
+
desc: 'Index of the Hyperliquid Parquet archive (fills, positions), or a 7-day download link for one file (--view url)',
|
|
268
|
+
options: [
|
|
269
|
+
view(['datasets', 'url']),
|
|
270
|
+
['--dataset <d>', 'url: fills | positions'],
|
|
271
|
+
['--date <d>', 'url: the UTC day, YYYY-MM-DD, or latest (positions only)'],
|
|
272
|
+
],
|
|
273
|
+
});
|
|
274
|
+
}
|
package/src/commands/init.js
CHANGED
|
@@ -31,7 +31,7 @@ export function registerInit(program) {
|
|
|
31
31
|
const path = saveApiKey(key);
|
|
32
32
|
console.log(`Saved to ${path}`);
|
|
33
33
|
|
|
34
|
-
console.log('Verifying connection to vike.io/mcp ...');
|
|
34
|
+
console.log('Verifying connection to data.vike.io/mcp ...');
|
|
35
35
|
const { status, body } = await ping({ apiKey: key });
|
|
36
36
|
if (status !== 200 || body?.error) {
|
|
37
37
|
console.error(`Endpoint returned HTTP ${status}: ${JSON.stringify(body)}`);
|
package/src/commands/labels.js
CHANGED
|
@@ -5,7 +5,7 @@ export function registerLabels(program) {
|
|
|
5
5
|
// `vike-data labels <address>` — multi-source label provenance for one wallet
|
|
6
6
|
program
|
|
7
7
|
.command('labels <address>')
|
|
8
|
-
.description('Multi-source label cascade for
|
|
8
|
+
.description('Multi-source label cascade for an Ethereum wallet (up to 6 label sources + in-house heuristic + consensus view)')
|
|
9
9
|
.option('--json', 'Emit JSON')
|
|
10
10
|
.action(async (address, opts) => {
|
|
11
11
|
try {
|
package/src/commands/perp.js
CHANGED
|
@@ -9,7 +9,7 @@ export function registerPerp(program) {
|
|
|
9
9
|
|
|
10
10
|
cmd
|
|
11
11
|
.command('funding')
|
|
12
|
-
.description('Funding rates per venue, or cross-venue funding-arb
|
|
12
|
+
.description('Funding rates per venue (raw per-interval rate + interval_h), or the top 5 cross-venue funding-arb rows')
|
|
13
13
|
.option('--symbol <s>', 'Specific symbol (e.g. BTC). Omit for top arb opportunities.')
|
|
14
14
|
.option('--json', 'Emit JSON')
|
|
15
15
|
.action(async (opts) => {
|
|
@@ -21,8 +21,8 @@ export function registerPerp(program) {
|
|
|
21
21
|
|
|
22
22
|
cmd
|
|
23
23
|
.command('spreads')
|
|
24
|
-
.description('Cross-venue
|
|
25
|
-
.option('--symbol <s>', '
|
|
24
|
+
.description('Cross-venue perp price gaps: the 10 widest (buy on one venue, sell on another)')
|
|
25
|
+
.option('--symbol <s>', 'Filter those 10 to one symbol (often empty). Omit for all.')
|
|
26
26
|
.option('--json', 'Emit JSON')
|
|
27
27
|
.action(async (opts) => {
|
|
28
28
|
try {
|
|
@@ -39,17 +39,18 @@ export function registerPerp(program) {
|
|
|
39
39
|
.requiredOption('--leverage <x>', 'Leverage from the share card (e.g. 25)')
|
|
40
40
|
.requiredOption('--entry <p>', 'Entry price from the share card')
|
|
41
41
|
.option('--mark <p>', 'Optional current mark price (sharpens tie-break)')
|
|
42
|
-
.option('--limit <n>', 'Max matches (default
|
|
42
|
+
.option('--limit <n>', 'Max matches (default 50, max 500)', '50')
|
|
43
43
|
.option('--json', 'Emit JSON')
|
|
44
44
|
.action(async (opts) => {
|
|
45
45
|
try {
|
|
46
|
+
// The tool renamed `coin` to `symbol` on 2026-10-19; `--coin` stays the flag users know.
|
|
46
47
|
const r = await callTool('hl_position_match', {
|
|
47
|
-
|
|
48
|
+
symbol: opts.coin,
|
|
48
49
|
side: opts.side,
|
|
49
50
|
leverage: Number(opts.leverage),
|
|
50
51
|
entry_price: Number(opts.entry),
|
|
51
52
|
mark_price: opts.mark != null ? Number(opts.mark) : undefined,
|
|
52
|
-
limit: parseInt10(opts.limit,
|
|
53
|
+
limit: parseInt10(opts.limit, 50),
|
|
53
54
|
});
|
|
54
55
|
emit(r, opts);
|
|
55
56
|
} catch (err) { emitError(err, opts); }
|
|
@@ -59,12 +60,12 @@ export function registerPerp(program) {
|
|
|
59
60
|
.command('top-traders')
|
|
60
61
|
.description('Top Hyperliquid perp wallets by PnL / ROI / win rate / volume')
|
|
61
62
|
.option('--window <w>', '1d | 7d | 30d | all', '30d')
|
|
62
|
-
.option('--sort <s>', 'pnl | roi | win_rate | volume | trade_count | drawdown', 'pnl')
|
|
63
|
+
.option('--sort <s>', 'pnl | roi | win_rate | volume | trade_count | drawdown | account_value | long_pnl | short_pnl', 'pnl')
|
|
63
64
|
.option('--order <o>', 'asc | desc', 'desc')
|
|
64
65
|
.option('--min-trades <n>', 'Minimum trade count', '3')
|
|
65
66
|
.option('--min-win-rate <p>', 'Minimum win rate percent (0-100)', '0')
|
|
66
67
|
.option('--min-volume <usd>', 'Minimum volume USD', '0')
|
|
67
|
-
.option('--size <n>', 'Page size (max
|
|
68
|
+
.option('--size <n>', 'Page size (default 20, max 100)', '20')
|
|
68
69
|
.option('--json', 'Emit JSON')
|
|
69
70
|
.action(async (opts) => {
|
|
70
71
|
try {
|
|
@@ -75,7 +76,7 @@ export function registerPerp(program) {
|
|
|
75
76
|
min_trades: parseInt10(opts.minTrades, 3),
|
|
76
77
|
min_win_rate: opts.minWinRate,
|
|
77
78
|
min_volume: opts.minVolume,
|
|
78
|
-
size: parseInt10(opts.size,
|
|
79
|
+
size: parseInt10(opts.size, 20),
|
|
79
80
|
});
|
|
80
81
|
emit(r, opts);
|
|
81
82
|
} catch (err) { emitError(err, opts); }
|