@nexstone/rift-cli 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (137) hide show
  1. package/LICENSE +201 -0
  2. package/bin/run.js +22 -0
  3. package/dist/commands/algo.d.ts +32 -0
  4. package/dist/commands/algo.js +719 -0
  5. package/dist/commands/audit.d.ts +13 -0
  6. package/dist/commands/audit.js +37 -0
  7. package/dist/commands/auth-status.d.ts +14 -0
  8. package/dist/commands/auth-status.js +118 -0
  9. package/dist/commands/auth.d.ts +14 -0
  10. package/dist/commands/auth.js +275 -0
  11. package/dist/commands/backtest.d.ts +26 -0
  12. package/dist/commands/backtest.js +283 -0
  13. package/dist/commands/collect/start.d.ts +11 -0
  14. package/dist/commands/collect/start.js +78 -0
  15. package/dist/commands/collect/status.d.ts +6 -0
  16. package/dist/commands/collect/status.js +60 -0
  17. package/dist/commands/compare.d.ts +16 -0
  18. package/dist/commands/compare.js +130 -0
  19. package/dist/commands/config.d.ts +16 -0
  20. package/dist/commands/config.js +143 -0
  21. package/dist/commands/cost.d.ts +20 -0
  22. package/dist/commands/cost.js +104 -0
  23. package/dist/commands/cross-asset.d.ts +14 -0
  24. package/dist/commands/cross-asset.js +39 -0
  25. package/dist/commands/data/fetch.d.ts +15 -0
  26. package/dist/commands/data/fetch.js +82 -0
  27. package/dist/commands/data/list.d.ts +6 -0
  28. package/dist/commands/data/list.js +28 -0
  29. package/dist/commands/data-inventory.d.ts +9 -0
  30. package/dist/commands/data-inventory.js +24 -0
  31. package/dist/commands/deposit.d.ts +10 -0
  32. package/dist/commands/deposit.js +222 -0
  33. package/dist/commands/doctor.d.ts +6 -0
  34. package/dist/commands/doctor.js +87 -0
  35. package/dist/commands/funding-browser.d.ts +12 -0
  36. package/dist/commands/funding-browser.js +33 -0
  37. package/dist/commands/guide.d.ts +6 -0
  38. package/dist/commands/guide.js +15 -0
  39. package/dist/commands/home.d.ts +23 -0
  40. package/dist/commands/home.js +210 -0
  41. package/dist/commands/init.d.ts +7 -0
  42. package/dist/commands/init.js +122 -0
  43. package/dist/commands/install.d.ts +9 -0
  44. package/dist/commands/install.js +89 -0
  45. package/dist/commands/interactive.d.ts +17 -0
  46. package/dist/commands/interactive.js +179 -0
  47. package/dist/commands/lessons.d.ts +12 -0
  48. package/dist/commands/lessons.js +33 -0
  49. package/dist/commands/montecarlo.d.ts +19 -0
  50. package/dist/commands/montecarlo.js +168 -0
  51. package/dist/commands/more.d.ts +11 -0
  52. package/dist/commands/more.js +227 -0
  53. package/dist/commands/new.d.ts +14 -0
  54. package/dist/commands/new.js +306 -0
  55. package/dist/commands/pairs.d.ts +22 -0
  56. package/dist/commands/pairs.js +147 -0
  57. package/dist/commands/perp/close.d.ts +12 -0
  58. package/dist/commands/perp/close.js +57 -0
  59. package/dist/commands/perp/long.d.ts +14 -0
  60. package/dist/commands/perp/long.js +38 -0
  61. package/dist/commands/perp/short.d.ts +14 -0
  62. package/dist/commands/perp/short.js +27 -0
  63. package/dist/commands/perp/status.d.ts +9 -0
  64. package/dist/commands/perp/status.js +26 -0
  65. package/dist/commands/portfolio/alerts.d.ts +6 -0
  66. package/dist/commands/portfolio/alerts.js +47 -0
  67. package/dist/commands/portfolio/backtest.d.ts +12 -0
  68. package/dist/commands/portfolio/backtest.js +178 -0
  69. package/dist/commands/portfolio/create.d.ts +7 -0
  70. package/dist/commands/portfolio/create.js +195 -0
  71. package/dist/commands/portfolio/start.d.ts +9 -0
  72. package/dist/commands/portfolio/start.js +64 -0
  73. package/dist/commands/portfolio/status.d.ts +6 -0
  74. package/dist/commands/portfolio/status.js +128 -0
  75. package/dist/commands/portfolio/stop.d.ts +6 -0
  76. package/dist/commands/portfolio/stop.js +81 -0
  77. package/dist/commands/portfolio-backtest.d.ts +13 -0
  78. package/dist/commands/portfolio-backtest.js +37 -0
  79. package/dist/commands/portfolio-matrix.d.ts +12 -0
  80. package/dist/commands/portfolio-matrix.js +30 -0
  81. package/dist/commands/quick-test.d.ts +17 -0
  82. package/dist/commands/quick-test.js +45 -0
  83. package/dist/commands/research.d.ts +57 -0
  84. package/dist/commands/research.js +1976 -0
  85. package/dist/commands/scout.d.ts +14 -0
  86. package/dist/commands/scout.js +184 -0
  87. package/dist/commands/serve.d.ts +9 -0
  88. package/dist/commands/serve.js +1176 -0
  89. package/dist/commands/setup/proxy.d.ts +10 -0
  90. package/dist/commands/setup/proxy.js +267 -0
  91. package/dist/commands/spot/buy.d.ts +14 -0
  92. package/dist/commands/spot/buy.js +38 -0
  93. package/dist/commands/spot/sell.d.ts +14 -0
  94. package/dist/commands/spot/sell.js +39 -0
  95. package/dist/commands/strategies/list.d.ts +6 -0
  96. package/dist/commands/strategies/list.js +34 -0
  97. package/dist/commands/sweep.d.ts +19 -0
  98. package/dist/commands/sweep.js +137 -0
  99. package/dist/commands/sync.d.ts +17 -0
  100. package/dist/commands/sync.js +54 -0
  101. package/dist/commands/test-trade.d.ts +6 -0
  102. package/dist/commands/test-trade.js +97 -0
  103. package/dist/commands/trade.d.ts +26 -0
  104. package/dist/commands/trade.js +274 -0
  105. package/dist/commands/transfer.d.ts +13 -0
  106. package/dist/commands/transfer.js +65 -0
  107. package/dist/commands/verify.d.ts +16 -0
  108. package/dist/commands/verify.js +38 -0
  109. package/dist/commands/walkforward.d.ts +20 -0
  110. package/dist/commands/walkforward.js +191 -0
  111. package/dist/commands/withdraw.d.ts +12 -0
  112. package/dist/commands/withdraw.js +55 -0
  113. package/dist/commands/workbench-create.d.ts +13 -0
  114. package/dist/commands/workbench-create.js +39 -0
  115. package/dist/lib/account-mode.d.ts +44 -0
  116. package/dist/lib/account-mode.js +96 -0
  117. package/dist/lib/analyzer.d.ts +4 -0
  118. package/dist/lib/analyzer.js +62 -0
  119. package/dist/lib/base-command.d.ts +35 -0
  120. package/dist/lib/base-command.js +49 -0
  121. package/dist/lib/credentials.d.ts +46 -0
  122. package/dist/lib/credentials.js +137 -0
  123. package/dist/lib/engine-passthrough.d.ts +28 -0
  124. package/dist/lib/engine-passthrough.js +60 -0
  125. package/dist/lib/fees.d.ts +52 -0
  126. package/dist/lib/fees.js +97 -0
  127. package/dist/lib/python-bridge.d.ts +24 -0
  128. package/dist/lib/python-bridge.js +182 -0
  129. package/dist/lib/setup-status.d.ts +32 -0
  130. package/dist/lib/setup-status.js +121 -0
  131. package/dist/lib/status-footer.d.ts +35 -0
  132. package/dist/lib/status-footer.js +101 -0
  133. package/dist/lib/tui.d.ts +130 -0
  134. package/dist/lib/tui.js +300 -0
  135. package/dist/lib/walletconnect.d.ts +70 -0
  136. package/dist/lib/walletconnect.js +407 -0
  137. package/package.json +49 -0
@@ -0,0 +1,143 @@
1
+ import { Args } from '@oclif/core';
2
+ import { GatedCommand } from '../lib/base-command.js';
3
+ import * as fs from 'node:fs';
4
+ import * as path from 'node:path';
5
+ const green = (s) => `\x1b[32m${s}\x1b[0m`;
6
+ const dim = (s) => `\x1b[2m${s}\x1b[0m`;
7
+ const bold = (s) => `\x1b[1m${s}\x1b[0m`;
8
+ const cyan = (s) => `\x1b[36m${s}\x1b[0m`;
9
+ function getConfigPath() {
10
+ const dir = path.join(process.env.HOME || '~', '.rift');
11
+ if (!fs.existsSync(dir))
12
+ fs.mkdirSync(dir, { recursive: true });
13
+ return path.join(dir, 'config.json');
14
+ }
15
+ function loadConfig() {
16
+ const p = getConfigPath();
17
+ if (!fs.existsSync(p))
18
+ return {};
19
+ return JSON.parse(fs.readFileSync(p, 'utf-8'));
20
+ }
21
+ function saveConfig(config) {
22
+ fs.writeFileSync(getConfigPath(), JSON.stringify(config, null, 2), { mode: 0o600 });
23
+ }
24
+ function getNestedValue(obj, keyPath) {
25
+ const parts = keyPath.split('.');
26
+ let current = obj;
27
+ for (const part of parts) {
28
+ if (current == null || typeof current !== 'object')
29
+ return undefined;
30
+ current = current[part];
31
+ }
32
+ return current;
33
+ }
34
+ function setNestedValue(obj, keyPath, value) {
35
+ const parts = keyPath.split('.');
36
+ let current = obj;
37
+ for (let i = 0; i < parts.length - 1; i++) {
38
+ if (!(parts[i] in current) || typeof current[parts[i]] !== 'object') {
39
+ current[parts[i]] = {};
40
+ }
41
+ current = current[parts[i]];
42
+ }
43
+ current[parts[parts.length - 1]] = value;
44
+ }
45
+ function maskSensitive(key, value) {
46
+ if (key.includes('key') || key.includes('secret') || key.includes('token') || key.includes('password')) {
47
+ if (value.length <= 10)
48
+ return '****';
49
+ return value.slice(0, 8) + '...' + value.slice(-4);
50
+ }
51
+ return value;
52
+ }
53
+ export default class Config extends GatedCommand {
54
+ static description = 'View and set RIFT configuration';
55
+ static examples = [
56
+ '$ rift config list',
57
+ '$ rift config set ai.api_key sk-ant-...',
58
+ '$ rift config get ai.api_key',
59
+ '$ rift config set ai.model claude-sonnet-4-20250514',
60
+ ];
61
+ static strict = false;
62
+ static args = {
63
+ action: Args.string({
64
+ description: 'Action: list, get, set',
65
+ required: false,
66
+ options: ['list', 'get', 'set'],
67
+ }),
68
+ key: Args.string({ description: 'Config key (dot-notation, e.g. ai.api_key)', required: false }),
69
+ value: Args.string({ description: 'Value to set', required: false }),
70
+ };
71
+ async run() {
72
+ const { args } = await this.parse(Config);
73
+ if (!args.action || args.action === 'list') {
74
+ return this.listConfig();
75
+ }
76
+ if (args.action === 'get') {
77
+ if (!args.key) {
78
+ this.log(` Usage: rift config get <key>`);
79
+ return;
80
+ }
81
+ return this.getConfig(args.key);
82
+ }
83
+ if (args.action === 'set') {
84
+ if (!args.key || args.value === undefined) {
85
+ this.log(` Usage: rift config set <key> <value>`);
86
+ this.log('');
87
+ this.log(` ${dim('Common keys:')}`);
88
+ this.log(` ${cyan('ai.api_key')} ${dim('Anthropic API key for --analyze')}`);
89
+ this.log(` ${cyan('ai.model')} ${dim('Model to use (default: claude-sonnet-4-20250514)')}`);
90
+ this.log(` ${cyan('network.proxy')} ${dim('Proxy URL for Hyperliquid API')}`);
91
+ return;
92
+ }
93
+ return this.setConfig(args.key, args.value);
94
+ }
95
+ }
96
+ listConfig() {
97
+ const config = loadConfig();
98
+ if (Object.keys(config).length === 0) {
99
+ this.log('');
100
+ this.log(` ${dim('No configuration set.')}`);
101
+ this.log('');
102
+ this.log(` ${dim('Get started:')}`);
103
+ this.log(` ${cyan('rift config set ai.api_key sk-ant-...')}`);
104
+ this.log('');
105
+ return;
106
+ }
107
+ this.log('');
108
+ this.log(` ${bold('RIFT Configuration')} ${dim('(~/.rift/config.json)')}`);
109
+ this.log('');
110
+ this.printObject(config, ' ');
111
+ this.log('');
112
+ }
113
+ printObject(obj, indent) {
114
+ for (const [key, value] of Object.entries(obj)) {
115
+ if (typeof value === 'object' && value !== null && !Array.isArray(value)) {
116
+ this.log(`${indent}${bold(key)}:`);
117
+ this.printObject(value, indent + ' ');
118
+ }
119
+ else {
120
+ const display = typeof value === 'string' ? maskSensitive(key, value) : String(value);
121
+ this.log(`${indent}${key}: ${dim(display)}`);
122
+ }
123
+ }
124
+ }
125
+ getConfig(key) {
126
+ const config = loadConfig();
127
+ const value = getNestedValue(config, key);
128
+ if (value === undefined) {
129
+ this.log(` ${dim('Not set:')} ${key}`);
130
+ }
131
+ else {
132
+ const display = typeof value === 'string' ? maskSensitive(key, value) : JSON.stringify(value, null, 2);
133
+ this.log(` ${key}: ${display}`);
134
+ }
135
+ }
136
+ setConfig(key, value) {
137
+ const config = loadConfig();
138
+ setNestedValue(config, key, value);
139
+ saveConfig(config);
140
+ const display = maskSensitive(key, value);
141
+ this.log(` ${green('✔')} ${key} = ${dim(display)}`);
142
+ }
143
+ }
@@ -0,0 +1,20 @@
1
+ import { GatedCommand } from '../lib/base-command.js';
2
+ export default class Cost extends GatedCommand {
3
+ static description: string;
4
+ static examples: string[];
5
+ static args: {
6
+ pair: import("@oclif/core/interfaces").Arg<string, Record<string, unknown>>;
7
+ notional: import("@oclif/core/interfaces").Arg<string, Record<string, unknown>>;
8
+ };
9
+ static flags: {
10
+ side: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
11
+ tf: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
12
+ hold: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
13
+ maker: import("@oclif/core/interfaces").BooleanFlag<boolean>;
14
+ spot: import("@oclif/core/interfaces").BooleanFlag<boolean>;
15
+ 'no-builder-fee': import("@oclif/core/interfaces").BooleanFlag<boolean>;
16
+ 'tier-vol-14d': import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
17
+ json: import("@oclif/core/interfaces").BooleanFlag<boolean>;
18
+ };
19
+ run(): Promise<void>;
20
+ }
@@ -0,0 +1,104 @@
1
+ import { Args, Flags } from '@oclif/core';
2
+ import { GatedCommand } from '../lib/base-command.js';
3
+ import { runEngine } from '../lib/python-bridge.js';
4
+ const bold = (s) => `\x1b[1m${s}\x1b[0m`;
5
+ const green = (s) => `\x1b[32m${s}\x1b[0m`;
6
+ const yellow = (s) => `\x1b[33m${s}\x1b[0m`;
7
+ const dim = (s) => `\x1b[2m${s}\x1b[0m`;
8
+ export default class Cost extends GatedCommand {
9
+ static description = 'Estimate pre-trade cost for a hypothetical trade: fees + funding + impact + slippage';
10
+ static examples = [
11
+ '$ rift cost BTC 50000',
12
+ '$ rift cost ETH 10000 --side sell --hold 24',
13
+ '$ rift cost BTC 100000 --maker --tier-vol-14d 5000000',
14
+ ];
15
+ static args = {
16
+ pair: Args.string({ description: 'Trading pair (e.g. BTC, ETH-PERP)', required: true }),
17
+ notional: Args.string({
18
+ description: 'Trade size in USD notional (e.g. 50000)',
19
+ required: true,
20
+ }),
21
+ };
22
+ static flags = {
23
+ side: Flags.string({ description: 'buy / sell / long / short', default: 'buy' }),
24
+ tf: Flags.string({ description: 'Candle interval for ADV / vol calc', default: '1h' }),
25
+ hold: Flags.string({ description: 'Holding period in hours (for funding accrual)', default: '0' }),
26
+ maker: Flags.boolean({ description: 'Treat as maker (post-only)', default: false }),
27
+ spot: Flags.boolean({ description: 'Treat as spot trade instead of perp', default: false }),
28
+ 'no-builder-fee': Flags.boolean({ description: 'Exclude RIFT builder fee', default: false }),
29
+ 'tier-vol-14d': Flags.string({
30
+ description: 'Your 14d HL volume USD (fee-tier lookup)',
31
+ default: '0',
32
+ }),
33
+ json: Flags.boolean({ description: 'Emit raw JSON instead of human format', default: false }),
34
+ };
35
+ async run() {
36
+ const { args, flags } = await this.parse(Cost);
37
+ const engineArgs = [args.pair, args.notional];
38
+ engineArgs.push('--side', flags.side);
39
+ engineArgs.push('--tf', flags.tf);
40
+ engineArgs.push('--hold', flags.hold);
41
+ if (flags.maker)
42
+ engineArgs.push('--maker');
43
+ if (flags.spot)
44
+ engineArgs.push('--spot');
45
+ if (flags['no-builder-fee'])
46
+ engineArgs.push('--no-builder-fee');
47
+ engineArgs.push('--tier-vol-14d', flags['tier-vol-14d']);
48
+ let result = null;
49
+ await runEngine('cost', engineArgs, (msg) => {
50
+ if (msg.type === 'result') {
51
+ result = msg;
52
+ }
53
+ else if (msg.type === 'error') {
54
+ this.error(msg.msg);
55
+ }
56
+ });
57
+ if (!result) {
58
+ this.error('No result returned from engine');
59
+ }
60
+ if (flags.json) {
61
+ this.log(JSON.stringify(result, null, 2));
62
+ return;
63
+ }
64
+ // Pretty render
65
+ const r = result;
66
+ const c = r.cost;
67
+ const pair = r.pair;
68
+ const side = r.side;
69
+ const notional = r.notional_usd;
70
+ const mid = r.mid_price;
71
+ const advPct = r.adv_pct;
72
+ this.log('');
73
+ this.log(` ${bold('Pre-trade cost estimate')} ${dim(`${pair} ${side}`)}`);
74
+ this.log(` ${dim('─'.repeat(56))}`);
75
+ this.log(` Notional $${notional.toLocaleString()}`);
76
+ if (mid > 0) {
77
+ this.log(` Mid price $${mid.toLocaleString()}`);
78
+ }
79
+ if (advPct !== null && advPct !== undefined) {
80
+ this.log(` % of ADV ${advPct.toFixed(3)}%`);
81
+ }
82
+ this.log('');
83
+ this.log(` Component bps USD`);
84
+ this.log(` ${dim('─'.repeat(40))}`);
85
+ this.log(` Fees ${c.fee_bps.toFixed(2).padStart(6)} $${c.fee_usd.toFixed(2).padStart(8)}`);
86
+ if (c.funding_bps !== 0) {
87
+ this.log(` Funding ${c.funding_bps.toFixed(2).padStart(6)} $${c.funding_usd.toFixed(2).padStart(8)}`);
88
+ }
89
+ this.log(` Impact ${c.impact_bps.toFixed(2).padStart(6)} $${c.impact_usd.toFixed(2).padStart(8)} ${dim('[' + (c.impact_model || '?') + ']')}`);
90
+ if (c.slippage_bps !== 0) {
91
+ this.log(` Slippage ${c.slippage_bps.toFixed(2).padStart(6)} $${c.slippage_usd.toFixed(2).padStart(8)}`);
92
+ }
93
+ this.log(` ${dim('─'.repeat(40))}`);
94
+ this.log(` ${bold('TOTAL')} ${c.total_bps.toFixed(2).padStart(6)} $${c.total_usd.toFixed(2).padStart(8)}`);
95
+ this.log('');
96
+ const warnings = r.warnings || [];
97
+ if (warnings.length > 0) {
98
+ for (const w of warnings) {
99
+ this.log(` ${yellow('!')} ${w}`);
100
+ }
101
+ this.log('');
102
+ }
103
+ }
104
+ }
@@ -0,0 +1,14 @@
1
+ import { GatedCommand } from '../lib/base-command.js';
2
+ export default class CrossAsset extends GatedCommand {
3
+ static description: string;
4
+ static examples: string[];
5
+ static flags: {
6
+ coins: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
7
+ tf: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
8
+ lookback: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
9
+ benchmark: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
10
+ 'max-lag': import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
11
+ json: import("@oclif/core/interfaces").BooleanFlag<boolean>;
12
+ };
13
+ run(): Promise<void>;
14
+ }
@@ -0,0 +1,39 @@
1
+ import { Flags } from '@oclif/core';
2
+ import { GatedCommand } from '../lib/base-command.js';
3
+ import { passthroughToEngine } from '../lib/engine-passthrough.js';
4
+ export default class CrossAsset extends GatedCommand {
5
+ static description = 'Cross-asset correlation matrix + lead-lag + beta-vs-benchmark';
6
+ static examples = [
7
+ '$ rift cross-asset',
8
+ '$ rift cross-asset --coins BTC,ETH,SOL --tf 4h --benchmark BTC',
9
+ ];
10
+ static flags = {
11
+ coins: Flags.string({
12
+ description: 'Comma-separated coin list',
13
+ default: 'BTC,ETH,SOL,SUI,AVAX,NEAR,LINK,DOGE',
14
+ }),
15
+ tf: Flags.string({ description: 'Timeframe', default: '1h' }),
16
+ lookback: Flags.string({ description: 'Candles to use (720 = 30d at 1h)', default: '720' }),
17
+ benchmark: Flags.string({ description: 'Beta-vs-benchmark coin', default: 'BTC' }),
18
+ 'max-lag': Flags.string({ description: 'Lead-lag search window (candles)', default: '6' }),
19
+ json: Flags.boolean({ description: 'Emit raw JSON only', default: false }),
20
+ };
21
+ async run() {
22
+ const { flags } = await this.parse(CrossAsset);
23
+ const args = [
24
+ '--coins', flags.coins,
25
+ '--tf', flags.tf,
26
+ '--lookback', flags.lookback,
27
+ '--benchmark', flags.benchmark,
28
+ '--max-lag', flags['max-lag'],
29
+ ];
30
+ await passthroughToEngine({
31
+ command: 'cross-asset',
32
+ args,
33
+ log: (m) => this.log(m),
34
+ error: (m) => this.error(m),
35
+ exit: (c) => this.exit(c),
36
+ jsonOnly: flags.json,
37
+ });
38
+ }
39
+ }
@@ -0,0 +1,15 @@
1
+ import { GatedCommand } from '../../lib/base-command.js';
2
+ export default class DataFetch extends GatedCommand {
3
+ static description: string;
4
+ static examples: string[];
5
+ static flags: {
6
+ pair: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
7
+ tf: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
8
+ start: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
9
+ all: import("@oclif/core/interfaces").BooleanFlag<boolean>;
10
+ top: import("@oclif/core/interfaces").OptionFlag<number | undefined, import("@oclif/core/interfaces").CustomOptions>;
11
+ };
12
+ run(): Promise<void>;
13
+ private fetchSingle;
14
+ private fetchMulti;
15
+ }
@@ -0,0 +1,82 @@
1
+ import { Flags } from '@oclif/core';
2
+ import { GatedCommand } from '../../lib/base-command.js';
3
+ import { runEngine } from '../../lib/python-bridge.js';
4
+ const green = (s) => `\x1b[32m${s}\x1b[0m`;
5
+ const red = (s) => `\x1b[31m${s}\x1b[0m`;
6
+ const bold = (s) => `\x1b[1m${s}\x1b[0m`;
7
+ const dim = (s) => `\x1b[2m${s}\x1b[0m`;
8
+ export default class DataFetch extends GatedCommand {
9
+ static description = 'Fetch and cache candle data from Hyperliquid';
10
+ static examples = [
11
+ '$ rift data fetch --pair BTC-PERP --tf 15m',
12
+ '$ rift data fetch --pair ETH-PERP --tf 1h --start 2025-01-01',
13
+ '$ rift data fetch --all --tf 1h',
14
+ '$ rift data fetch --top 10 --tf 4h',
15
+ ];
16
+ static flags = {
17
+ pair: Flags.string({ description: 'Trading pair (e.g. BTC-PERP)', default: 'BTC-PERP' }),
18
+ tf: Flags.string({ description: 'Timeframe / candle interval', default: '1h' }),
19
+ start: Flags.string({ description: 'Start date (YYYY-MM-DD)' }),
20
+ all: Flags.boolean({ description: 'Fetch top 20 pairs by volume', default: false }),
21
+ top: Flags.integer({ description: 'Fetch top N pairs by volume' }),
22
+ };
23
+ async run() {
24
+ const { flags } = await this.parse(DataFetch);
25
+ if (flags.all || flags.top) {
26
+ return this.fetchMulti(flags);
27
+ }
28
+ return this.fetchSingle(flags);
29
+ }
30
+ async fetchSingle(flags) {
31
+ const args = [flags.pair, '--tf', flags.tf];
32
+ if (flags.start)
33
+ args.push('--start', flags.start);
34
+ this.log(`\n Fetching ${bold(flags.pair)} ${flags.tf} candles...`);
35
+ await runEngine('fetch', args, (msg) => {
36
+ if (msg.type === 'progress' && msg.msg) {
37
+ process.stdout.write(`\r ${dim(String(msg.msg))}${''.padEnd(20)}`);
38
+ }
39
+ else if (msg.type === 'result') {
40
+ process.stdout.write('\r' + ' '.repeat(60) + '\r');
41
+ this.log(` ${green('✔')} ${bold(String(msg.pair))} — ${msg.candles} candles`);
42
+ }
43
+ else if (msg.type === 'error') {
44
+ this.error(msg.msg);
45
+ }
46
+ });
47
+ this.log('');
48
+ }
49
+ async fetchMulti(flags) {
50
+ const n = flags.top || 20;
51
+ const topArg = `top${n}`;
52
+ const args = [topArg, '--tf', flags.tf];
53
+ if (flags.start)
54
+ args.push('--start', flags.start);
55
+ args.push('--top', String(n));
56
+ this.log(`\n Fetching top ${bold(String(n))} pairs by volume (${flags.tf})...\n`);
57
+ await runEngine('fetch-multi', args, (msg) => {
58
+ if (msg.type === 'progress' && msg.msg) {
59
+ process.stdout.write(`\r ${dim(String(msg.msg))}${''.padEnd(30)}`);
60
+ }
61
+ else if (msg.type === 'result') {
62
+ process.stdout.write('\r' + ' '.repeat(60) + '\r');
63
+ const results = msg.results;
64
+ let succeeded = 0;
65
+ let failed = 0;
66
+ for (const r of results) {
67
+ if (r.status === 'ok') {
68
+ this.log(` ${green('✔')} ${bold(r.pair.padEnd(10))} ${dim(`${r.candles} candles`)}`);
69
+ succeeded++;
70
+ }
71
+ else {
72
+ this.log(` ${red('✘')} ${bold(r.pair.padEnd(10))} ${dim(r.error || 'failed')}`);
73
+ failed++;
74
+ }
75
+ }
76
+ this.log('');
77
+ this.log(` ${dim(`${succeeded} succeeded${failed > 0 ? `, ${failed} failed` : ''}`)}`);
78
+ }
79
+ });
80
+ this.log('');
81
+ }
82
+ }
@@ -0,0 +1,6 @@
1
+ import { GatedCommand } from '../../lib/base-command.js';
2
+ export default class DataList extends GatedCommand {
3
+ static description: string;
4
+ static examples: string[];
5
+ run(): Promise<void>;
6
+ }
@@ -0,0 +1,28 @@
1
+ import { GatedCommand } from '../../lib/base-command.js';
2
+ import { runEngine } from '../../lib/python-bridge.js';
3
+ export default class DataList extends GatedCommand {
4
+ static description = 'List cached candle data';
5
+ static examples = [
6
+ '$ rift data list',
7
+ ];
8
+ async run() {
9
+ await runEngine('list-data', [], (msg) => {
10
+ if (msg.type === 'result') {
11
+ const data = msg.data;
12
+ if (!data || data.length === 0) {
13
+ this.log('No cached data. Run: rift data fetch --pair BTC-PERP');
14
+ return;
15
+ }
16
+ this.log('');
17
+ this.log(' Pair Interval Candles Start End');
18
+ this.log(' ──────────────────────────────────────────────────────────────────');
19
+ for (const d of data) {
20
+ const start = new Date(d.start).toISOString().slice(0, 16);
21
+ const end = new Date(d.end).toISOString().slice(0, 16);
22
+ this.log(` ${d.pair.padEnd(14)} ${d.interval.padEnd(12)} ${String(d.rows).padEnd(12)} ${start} ${end}`);
23
+ }
24
+ this.log('');
25
+ }
26
+ });
27
+ }
28
+ }
@@ -0,0 +1,9 @@
1
+ import { GatedCommand } from '../lib/base-command.js';
2
+ export default class DataInventory extends GatedCommand {
3
+ static description: string;
4
+ static examples: string[];
5
+ static flags: {
6
+ json: import("@oclif/core/interfaces").BooleanFlag<boolean>;
7
+ };
8
+ run(): Promise<void>;
9
+ }
@@ -0,0 +1,24 @@
1
+ import { Flags } from '@oclif/core';
2
+ import { GatedCommand } from '../lib/base-command.js';
3
+ import { passthroughToEngine } from '../lib/engine-passthrough.js';
4
+ export default class DataInventory extends GatedCommand {
5
+ static description = 'Inventory of locally cached candles, funding, fills — counts + freshness';
6
+ static examples = [
7
+ '$ rift data-inventory',
8
+ '$ rift data-inventory --json',
9
+ ];
10
+ static flags = {
11
+ json: Flags.boolean({ description: 'Emit raw JSON only', default: false }),
12
+ };
13
+ async run() {
14
+ const { flags } = await this.parse(DataInventory);
15
+ await passthroughToEngine({
16
+ command: 'data-inventory',
17
+ args: [],
18
+ log: (m) => this.log(m),
19
+ error: (m) => this.error(m),
20
+ exit: (c) => this.exit(c),
21
+ jsonOnly: flags.json,
22
+ });
23
+ }
24
+ }
@@ -0,0 +1,10 @@
1
+ import { GatedCommand } from '../lib/base-command.js';
2
+ export default class Deposit extends GatedCommand {
3
+ static description: string;
4
+ static examples: string[];
5
+ static args: {
6
+ amount: import("@oclif/core/interfaces").Arg<string, Record<string, unknown>>;
7
+ };
8
+ static flags: {};
9
+ run(): Promise<void>;
10
+ }