openbroker 1.3.1 → 1.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (171) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/SKILL.md +7 -4
  3. package/dist/auto/audit.d.ts +57 -0
  4. package/dist/auto/audit.d.ts.map +1 -0
  5. package/dist/auto/audit.js +407 -0
  6. package/dist/auto/cli.d.ts +2 -0
  7. package/dist/auto/cli.d.ts.map +1 -0
  8. package/dist/auto/cli.js +423 -0
  9. package/dist/auto/events.d.ts +11 -0
  10. package/dist/auto/events.d.ts.map +1 -0
  11. package/dist/auto/events.js +36 -0
  12. package/dist/auto/examples/dca.d.ts +4 -0
  13. package/dist/auto/examples/dca.d.ts.map +1 -0
  14. package/dist/auto/examples/dca.js +60 -0
  15. package/dist/auto/examples/funding-arb.d.ts +4 -0
  16. package/dist/auto/examples/funding-arb.d.ts.map +1 -0
  17. package/dist/auto/examples/funding-arb.js +81 -0
  18. package/dist/auto/examples/grid.d.ts +4 -0
  19. package/dist/auto/examples/grid.d.ts.map +1 -0
  20. package/dist/auto/examples/grid.js +114 -0
  21. package/dist/auto/examples/mm-maker.d.ts +4 -0
  22. package/dist/auto/examples/mm-maker.d.ts.map +1 -0
  23. package/dist/auto/examples/mm-maker.js +131 -0
  24. package/dist/auto/examples/mm-spread.d.ts +4 -0
  25. package/dist/auto/examples/mm-spread.d.ts.map +1 -0
  26. package/dist/auto/examples/mm-spread.js +119 -0
  27. package/dist/auto/examples/price-alert.d.ts +4 -0
  28. package/dist/auto/examples/price-alert.d.ts.map +1 -0
  29. package/dist/auto/examples/price-alert.js +85 -0
  30. package/dist/auto/keep-awake.d.ts +11 -0
  31. package/dist/auto/keep-awake.d.ts.map +1 -0
  32. package/dist/auto/keep-awake.js +70 -0
  33. package/dist/auto/loader.d.ts +22 -0
  34. package/dist/auto/loader.d.ts.map +1 -0
  35. package/dist/auto/loader.js +127 -0
  36. package/dist/auto/prune.d.ts +40 -0
  37. package/dist/auto/prune.d.ts.map +1 -0
  38. package/dist/auto/prune.js +204 -0
  39. package/dist/auto/registry.d.ts +24 -0
  40. package/dist/auto/registry.d.ts.map +1 -0
  41. package/dist/auto/registry.js +93 -0
  42. package/dist/auto/report.d.ts +3 -0
  43. package/dist/auto/report.d.ts.map +1 -0
  44. package/dist/auto/report.js +385 -0
  45. package/dist/auto/runtime.d.ts +33 -0
  46. package/dist/auto/runtime.d.ts.map +1 -0
  47. package/dist/auto/runtime.js +844 -0
  48. package/dist/auto/types.d.ts +236 -0
  49. package/dist/auto/types.d.ts.map +1 -0
  50. package/dist/auto/types.js +3 -0
  51. package/dist/core/client.d.ts +684 -0
  52. package/dist/core/client.d.ts.map +1 -0
  53. package/dist/core/client.js +2040 -0
  54. package/dist/core/config.d.ts +22 -0
  55. package/dist/core/config.d.ts.map +1 -0
  56. package/dist/core/config.js +143 -0
  57. package/dist/core/types.d.ts +221 -0
  58. package/dist/core/types.d.ts.map +1 -0
  59. package/dist/core/types.js +2 -0
  60. package/dist/core/utils.d.ts +61 -0
  61. package/dist/core/utils.d.ts.map +1 -0
  62. package/dist/core/utils.js +142 -0
  63. package/dist/core/ws.d.ts +121 -0
  64. package/dist/core/ws.d.ts.map +1 -0
  65. package/dist/core/ws.js +222 -0
  66. package/dist/info/account.d.ts +3 -0
  67. package/dist/info/account.d.ts.map +1 -0
  68. package/dist/info/account.js +198 -0
  69. package/dist/info/all-markets.d.ts +3 -0
  70. package/dist/info/all-markets.d.ts.map +1 -0
  71. package/dist/info/all-markets.js +272 -0
  72. package/dist/info/candles.d.ts +3 -0
  73. package/dist/info/candles.d.ts.map +1 -0
  74. package/dist/info/candles.js +120 -0
  75. package/dist/info/fees.d.ts +3 -0
  76. package/dist/info/fees.d.ts.map +1 -0
  77. package/dist/info/fees.js +87 -0
  78. package/dist/info/fills.d.ts +3 -0
  79. package/dist/info/fills.d.ts.map +1 -0
  80. package/dist/info/fills.js +105 -0
  81. package/dist/info/funding-history.d.ts +3 -0
  82. package/dist/info/funding-history.d.ts.map +1 -0
  83. package/dist/info/funding-history.js +98 -0
  84. package/dist/info/funding-scan.d.ts +3 -0
  85. package/dist/info/funding-scan.d.ts.map +1 -0
  86. package/dist/info/funding-scan.js +178 -0
  87. package/dist/info/funding.d.ts +3 -0
  88. package/dist/info/funding.d.ts.map +1 -0
  89. package/dist/info/funding.js +158 -0
  90. package/dist/info/markets.d.ts +3 -0
  91. package/dist/info/markets.d.ts.map +1 -0
  92. package/dist/info/markets.js +178 -0
  93. package/dist/info/order-status.d.ts +3 -0
  94. package/dist/info/order-status.d.ts.map +1 -0
  95. package/dist/info/order-status.js +85 -0
  96. package/dist/info/orders.d.ts +3 -0
  97. package/dist/info/orders.d.ts.map +1 -0
  98. package/dist/info/orders.js +162 -0
  99. package/dist/info/outcomes.d.ts +3 -0
  100. package/dist/info/outcomes.d.ts.map +1 -0
  101. package/dist/info/outcomes.js +175 -0
  102. package/dist/info/positions.d.ts +3 -0
  103. package/dist/info/positions.d.ts.map +1 -0
  104. package/dist/info/positions.js +127 -0
  105. package/dist/info/rate-limit.d.ts +3 -0
  106. package/dist/info/rate-limit.d.ts.map +1 -0
  107. package/dist/info/rate-limit.js +58 -0
  108. package/dist/info/search-markets.d.ts +3 -0
  109. package/dist/info/search-markets.d.ts.map +1 -0
  110. package/dist/info/search-markets.js +296 -0
  111. package/dist/info/spot.d.ts +3 -0
  112. package/dist/info/spot.d.ts.map +1 -0
  113. package/dist/info/spot.js +192 -0
  114. package/dist/info/trades.d.ts +3 -0
  115. package/dist/info/trades.d.ts.map +1 -0
  116. package/dist/info/trades.js +97 -0
  117. package/dist/lib.d.ts +14 -0
  118. package/dist/lib.d.ts.map +1 -0
  119. package/dist/lib.js +17 -0
  120. package/dist/operations/bracket.d.ts +28 -0
  121. package/dist/operations/bracket.d.ts.map +1 -0
  122. package/dist/operations/bracket.js +266 -0
  123. package/dist/operations/cancel.d.ts +3 -0
  124. package/dist/operations/cancel.d.ts.map +1 -0
  125. package/dist/operations/cancel.js +107 -0
  126. package/dist/operations/chase.d.ts +25 -0
  127. package/dist/operations/chase.d.ts.map +1 -0
  128. package/dist/operations/chase.js +215 -0
  129. package/dist/operations/limit-order.d.ts +3 -0
  130. package/dist/operations/limit-order.d.ts.map +1 -0
  131. package/dist/operations/limit-order.js +144 -0
  132. package/dist/operations/market-order.d.ts +3 -0
  133. package/dist/operations/market-order.d.ts.map +1 -0
  134. package/dist/operations/market-order.js +153 -0
  135. package/dist/operations/outcome-order.d.ts +3 -0
  136. package/dist/operations/outcome-order.d.ts.map +1 -0
  137. package/dist/operations/outcome-order.js +171 -0
  138. package/dist/operations/scale.d.ts +3 -0
  139. package/dist/operations/scale.d.ts.map +1 -0
  140. package/dist/operations/scale.js +212 -0
  141. package/dist/operations/set-tpsl.d.ts +3 -0
  142. package/dist/operations/set-tpsl.d.ts.map +1 -0
  143. package/dist/operations/set-tpsl.js +277 -0
  144. package/dist/operations/spot-order.d.ts +3 -0
  145. package/dist/operations/spot-order.d.ts.map +1 -0
  146. package/dist/operations/spot-order.js +173 -0
  147. package/dist/operations/trigger-order.d.ts +3 -0
  148. package/dist/operations/trigger-order.d.ts.map +1 -0
  149. package/dist/operations/trigger-order.js +177 -0
  150. package/dist/operations/twap-cancel.d.ts +3 -0
  151. package/dist/operations/twap-cancel.d.ts.map +1 -0
  152. package/dist/operations/twap-cancel.js +57 -0
  153. package/dist/operations/twap-status.d.ts +3 -0
  154. package/dist/operations/twap-status.d.ts.map +1 -0
  155. package/dist/operations/twap-status.js +81 -0
  156. package/dist/operations/twap.d.ts +3 -0
  157. package/dist/operations/twap.d.ts.map +1 -0
  158. package/dist/operations/twap.js +124 -0
  159. package/dist/setup/approve-builder.d.ts +3 -0
  160. package/dist/setup/approve-builder.d.ts.map +1 -0
  161. package/dist/setup/approve-builder.js +155 -0
  162. package/dist/setup/env.d.ts +4 -0
  163. package/dist/setup/env.d.ts.map +1 -0
  164. package/dist/setup/env.js +8 -0
  165. package/dist/setup/onboard.d.ts +10 -0
  166. package/dist/setup/onboard.d.ts.map +1 -0
  167. package/dist/setup/onboard.js +462 -0
  168. package/package.json +10 -4
  169. package/scripts/core/client.ts +13 -3
  170. package/scripts/info/all-markets.ts +18 -2
  171. package/scripts/info/search-markets.ts +18 -2
@@ -0,0 +1,272 @@
1
+ #!/usr/bin/env tsx
2
+ // All Markets - View all available markets across perps, HIP-3, spot, and HIP-4 outcomes
3
+ import { getClient } from '../core/client.js';
4
+ function parseArgs() {
5
+ const args = { type: 'all' };
6
+ for (let i = 2; i < process.argv.length; i++) {
7
+ const arg = process.argv[i];
8
+ if (arg === '--type' && process.argv[i + 1]) {
9
+ const val = process.argv[++i].toLowerCase();
10
+ if (['perp', 'spot', 'hip3', 'outcome', 'all'].includes(val)) {
11
+ args.type = val;
12
+ }
13
+ }
14
+ else if (arg === '--top' && process.argv[i + 1]) {
15
+ args.top = parseInt(process.argv[++i], 10);
16
+ }
17
+ else if (arg === '--verbose') {
18
+ args.verbose = true;
19
+ }
20
+ else if (arg === '--json') {
21
+ args.json = true;
22
+ }
23
+ else if (arg === '--help' || arg === '-h') {
24
+ console.log(`
25
+ All Markets - View all available markets on Hyperliquid
26
+
27
+ Usage: npx tsx scripts/info/all-markets.ts [options]
28
+
29
+ Options:
30
+ --type <type> Market type: perp, spot, hip3, outcome, or all (default: all)
31
+ --top <n> Show only top N markets by volume
32
+ --json Output as JSON (machine-readable)
33
+ --verbose Show detailed output
34
+ --help Show this help
35
+
36
+ Examples:
37
+ npx tsx scripts/info/all-markets.ts # Show all markets
38
+ npx tsx scripts/info/all-markets.ts --type perp # Show only main perps
39
+ npx tsx scripts/info/all-markets.ts --type hip3 # Show only HIP-3 perps
40
+ npx tsx scripts/info/all-markets.ts --type spot # Show only spot markets
41
+ npx tsx scripts/info/all-markets.ts --type outcome # Show only HIP-4 outcomes
42
+ npx tsx scripts/info/all-markets.ts --top 20 # Show top 20 by volume
43
+ npx tsx scripts/info/all-markets.ts --json # JSON output
44
+ `);
45
+ process.exit(0);
46
+ }
47
+ }
48
+ return args;
49
+ }
50
+ function formatVolume(vol) {
51
+ if (vol >= 1_000_000_000)
52
+ return `$${(vol / 1_000_000_000).toFixed(2)}B`;
53
+ if (vol >= 1_000_000)
54
+ return `$${(vol / 1_000_000).toFixed(2)}M`;
55
+ if (vol >= 1_000)
56
+ return `$${(vol / 1_000).toFixed(2)}K`;
57
+ return `$${vol.toFixed(2)}`;
58
+ }
59
+ function formatPrice(price) {
60
+ const p = typeof price === 'string' ? parseFloat(price) : price;
61
+ if (p >= 1000)
62
+ return p.toFixed(2);
63
+ if (p >= 1)
64
+ return p.toFixed(4);
65
+ if (p >= 0.01)
66
+ return p.toFixed(6);
67
+ return p.toFixed(8);
68
+ }
69
+ function formatFunding(rate) {
70
+ const r = parseFloat(rate);
71
+ const annualized = r * 24 * 365 * 100;
72
+ const sign = annualized >= 0 ? '+' : '';
73
+ return `${sign}${annualized.toFixed(2)}%`;
74
+ }
75
+ function handleMarketFetchError(kind, error, requestedType, verbose) {
76
+ const message = error instanceof Error ? error.message : String(error);
77
+ if (requestedType === kind) {
78
+ throw new Error(`Failed to fetch ${kind} markets: ${message}`);
79
+ }
80
+ if (verbose) {
81
+ console.error(`Failed to fetch ${kind} markets:`, error);
82
+ }
83
+ }
84
+ async function main() {
85
+ const args = parseArgs();
86
+ const client = getClient();
87
+ client.verbose = args.verbose ?? false;
88
+ if (!args.json) {
89
+ console.log('Fetching market data...\n');
90
+ }
91
+ const allMarkets = [];
92
+ // Fetch main perps
93
+ if (args.type === 'all' || args.type === 'perp') {
94
+ const meta = await client.getMetaAndAssetCtxs();
95
+ for (let i = 0; i < meta.meta.universe.length; i++) {
96
+ const asset = meta.meta.universe[i];
97
+ const ctx = meta.assetCtxs[i];
98
+ allMarkets.push({
99
+ type: 'perp',
100
+ provider: 'Hyperliquid',
101
+ coin: asset.name,
102
+ assetId: i,
103
+ price: ctx.markPx,
104
+ volume24h: parseFloat(ctx.dayNtlVlm),
105
+ funding: ctx.funding,
106
+ maxLeverage: asset.maxLeverage,
107
+ });
108
+ }
109
+ }
110
+ // Fetch HIP-3 perps
111
+ if (args.type === 'all' || args.type === 'hip3') {
112
+ if (client.isTestnet && !args.json) {
113
+ console.log('Note: Testnet — HIP-3 dexes not auto-loaded. Use "dexName:COIN" syntax to load a specific dex.\n');
114
+ }
115
+ try {
116
+ const allPerpMetas = await client.getAllPerpMetas();
117
+ // Skip index 0 (main dex), process HIP-3 dexs
118
+ for (let dexIdx = 1; dexIdx < allPerpMetas.length; dexIdx++) {
119
+ const dexData = allPerpMetas[dexIdx];
120
+ if (!dexData || !dexData.meta?.universe)
121
+ continue;
122
+ for (let i = 0; i < dexData.meta.universe.length; i++) {
123
+ const asset = dexData.meta.universe[i];
124
+ const ctx = dexData.assetCtxs[i];
125
+ if (!asset || !ctx)
126
+ continue;
127
+ let assetId = -1;
128
+ try {
129
+ assetId = client.getAssetIndex(asset.name);
130
+ }
131
+ catch { /* not registered */ }
132
+ allMarkets.push({
133
+ type: 'hip3',
134
+ provider: dexData.dexName || `HIP-3 DEX ${dexIdx}`,
135
+ coin: asset.name,
136
+ assetId,
137
+ price: ctx.markPx,
138
+ volume24h: parseFloat(ctx.dayNtlVlm || '0'),
139
+ funding: ctx.funding,
140
+ maxLeverage: asset.maxLeverage,
141
+ });
142
+ }
143
+ }
144
+ }
145
+ catch (e) {
146
+ console.error('Failed to fetch HIP-3 markets:', e);
147
+ }
148
+ }
149
+ // Fetch spot markets
150
+ if (args.type === 'all' || args.type === 'spot') {
151
+ try {
152
+ const spotData = await client.getSpotMetaAndAssetCtxs();
153
+ // contexts carry coin field that matches pair.name; not necessarily aligned by index
154
+ const ctxMap = new Map();
155
+ for (const ctx of spotData.assetCtxs) {
156
+ if (ctx.coin) {
157
+ ctxMap.set(ctx.coin, ctx);
158
+ }
159
+ }
160
+ for (const pair of spotData.meta.universe) {
161
+ if (!pair)
162
+ continue;
163
+ const ctx = ctxMap.get(pair.name);
164
+ if (!ctx)
165
+ continue;
166
+ allMarkets.push({
167
+ type: 'spot',
168
+ provider: 'Spot',
169
+ coin: pair.name,
170
+ assetId: 10000 + pair.index,
171
+ price: ctx.markPx,
172
+ volume24h: parseFloat(ctx.dayNtlVlm || '0'),
173
+ });
174
+ }
175
+ }
176
+ catch (e) {
177
+ console.error('Failed to fetch spot markets:', e);
178
+ }
179
+ }
180
+ // Fetch HIP-4 outcomes
181
+ if (args.type === 'all' || args.type === 'outcome') {
182
+ try {
183
+ const outcomes = await client.getOutcomeMarkets();
184
+ for (const market of outcomes) {
185
+ for (const side of market.sides) {
186
+ allMarkets.push({
187
+ type: 'outcome',
188
+ provider: 'HIP-4',
189
+ coin: side.coin,
190
+ assetId: side.assetId,
191
+ price: side.midPx ?? side.markPx ?? '0',
192
+ volume24h: parseFloat(side.dayNtlVlm || '0'),
193
+ outcome: market.outcome,
194
+ outcomeSide: side.name,
195
+ outcomeName: market.name,
196
+ tokenName: side.tokenName,
197
+ parsedDescription: market.parsedDescription,
198
+ description: market.description,
199
+ });
200
+ }
201
+ }
202
+ }
203
+ catch (e) {
204
+ handleMarketFetchError('outcome', e, args.type, args.verbose);
205
+ }
206
+ }
207
+ // Sort by volume
208
+ allMarkets.sort((a, b) => b.volume24h - a.volume24h);
209
+ // Apply top filter
210
+ const markets = args.top ? allMarkets.slice(0, args.top) : allMarkets;
211
+ if (args.json) {
212
+ console.log(JSON.stringify(markets, null, 2));
213
+ return;
214
+ }
215
+ // Group by type for display
216
+ const perps = markets.filter((m) => m.type === 'perp');
217
+ const hip3 = markets.filter((m) => m.type === 'hip3');
218
+ const spots = markets.filter((m) => m.type === 'spot');
219
+ const outcomes = markets.filter((m) => m.type === 'outcome');
220
+ // Print summary
221
+ console.log('=== Market Summary ===\n');
222
+ console.log(`Total Markets: ${allMarkets.length}`);
223
+ console.log(` - Main Perps: ${perps.length}`);
224
+ console.log(` - HIP-3 Perps: ${hip3.length}`);
225
+ console.log(` - Spot Markets: ${spots.length}`);
226
+ console.log(` - HIP-4 Outcomes: ${outcomes.length}`);
227
+ console.log();
228
+ // Print perps
229
+ if (perps.length > 0) {
230
+ console.log('=== Main Perpetuals ===\n');
231
+ console.log('Coin AssetID Price 24h Volume Funding (Ann.) Leverage');
232
+ console.log('-'.repeat(87));
233
+ for (const m of perps) {
234
+ console.log(`${m.coin.padEnd(14)} ${String(m.assetId).padStart(7)} ${formatPrice(m.price).padStart(16)} ${formatVolume(m.volume24h).padStart(13)} ${(m.funding ? formatFunding(m.funding) : '-').padStart(14)} ${(m.maxLeverage ? `${m.maxLeverage}x` : '-').padStart(9)}`);
235
+ }
236
+ console.log();
237
+ }
238
+ // Print HIP-3 markets
239
+ if (hip3.length > 0) {
240
+ console.log('=== HIP-3 Perpetuals ===\n');
241
+ console.log('Coin Provider AssetID Price 24h Volume Funding (Ann.)');
242
+ console.log('-'.repeat(92));
243
+ for (const m of hip3) {
244
+ console.log(`${m.coin.padEnd(14)} ${m.provider.padEnd(16)} ${String(m.assetId).padStart(7)} ${formatPrice(m.price).padStart(16)} ${formatVolume(m.volume24h).padStart(13)} ${(m.funding ? formatFunding(m.funding) : '-').padStart(14)}`);
245
+ }
246
+ console.log();
247
+ }
248
+ // Print spot markets
249
+ if (spots.length > 0) {
250
+ console.log('=== Spot Markets ===\n');
251
+ console.log('Pair AssetID Price 24h Volume');
252
+ console.log('-'.repeat(62));
253
+ for (const m of spots) {
254
+ console.log(`${m.coin.padEnd(14)} ${String(m.assetId).padStart(7)} ${formatPrice(m.price).padStart(16)} ${formatVolume(m.volume24h).padStart(13)}`);
255
+ }
256
+ console.log();
257
+ }
258
+ // Print HIP-4 outcome markets
259
+ if (outcomes.length > 0) {
260
+ console.log('=== HIP-4 Outcomes ===\n');
261
+ console.log('Coin Outcome Side AssetID Price 24h Volume');
262
+ console.log('-'.repeat(78));
263
+ for (const m of outcomes) {
264
+ console.log(`${m.coin.padEnd(14)} ${String(m.outcome ?? '-').padStart(7)} ${(m.outcomeSide ?? '-').padEnd(8)} ${String(m.assetId).padStart(9)} ${formatPrice(m.price).padStart(7)} ${formatVolume(m.volume24h).padStart(13)}`);
265
+ }
266
+ console.log();
267
+ }
268
+ }
269
+ main().catch((e) => {
270
+ console.error('Error:', e.message);
271
+ process.exit(1);
272
+ });
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env npx tsx
2
+ export {};
3
+ //# sourceMappingURL=candles.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"candles.d.ts","sourceRoot":"","sources":["../../scripts/info/candles.ts"],"names":[],"mappings":""}
@@ -0,0 +1,120 @@
1
+ #!/usr/bin/env npx tsx
2
+ // View OHLCV candle data from Hyperliquid
3
+ import { getClient } from '../core/client.js';
4
+ import { formatUsd, parseArgs, normalizeCoin } from '../core/utils.js';
5
+ const VALID_INTERVALS = ['1m', '3m', '5m', '15m', '30m', '1h', '2h', '4h', '8h', '12h', '1d', '3d', '1w', '1M'];
6
+ const INTERVAL_MS = {
7
+ '1m': 60_000, '3m': 180_000, '5m': 300_000, '15m': 900_000, '30m': 1_800_000,
8
+ '1h': 3_600_000, '2h': 7_200_000, '4h': 14_400_000, '8h': 28_800_000, '12h': 43_200_000,
9
+ '1d': 86_400_000, '3d': 259_200_000, '1w': 604_800_000, '1M': 2_592_000_000,
10
+ };
11
+ function printUsage() {
12
+ console.log(`
13
+ Usage: openbroker candles --coin <symbol> [options]
14
+
15
+ Options:
16
+ --coin <symbol> Asset symbol (required, e.g. ETH, BTC)
17
+ --interval <interval> Candle interval (default: 1h)
18
+ Valid: ${VALID_INTERVALS.join(', ')}
19
+ --bars <n> Number of bars to fetch (default: 24)
20
+ --json Output as JSON (machine-readable)
21
+ --help, -h Show this help
22
+
23
+ Examples:
24
+ openbroker candles --coin ETH
25
+ openbroker candles --coin BTC --interval 4h --bars 48
26
+ openbroker candles --coin SOL --interval 1d --bars 30
27
+ `);
28
+ }
29
+ function formatVolume(v) {
30
+ if (v >= 1_000_000_000)
31
+ return `$${(v / 1_000_000_000).toFixed(2)}B`;
32
+ if (v >= 1_000_000)
33
+ return `$${(v / 1_000_000).toFixed(2)}M`;
34
+ if (v >= 1_000)
35
+ return `$${(v / 1_000).toFixed(2)}K`;
36
+ return formatUsd(v);
37
+ }
38
+ async function main() {
39
+ const args = parseArgs(process.argv.slice(2));
40
+ if (args.help || args.h) {
41
+ printUsage();
42
+ process.exit(0);
43
+ }
44
+ const coin = args.coin;
45
+ if (!coin) {
46
+ console.error('Error: --coin is required');
47
+ printUsage();
48
+ process.exit(1);
49
+ }
50
+ const interval = args.interval || '1h';
51
+ if (!VALID_INTERVALS.includes(interval)) {
52
+ console.error(`Error: invalid interval "${interval}". Valid: ${VALID_INTERVALS.join(', ')}`);
53
+ process.exit(1);
54
+ }
55
+ const bars = parseInt(args.bars) || 24;
56
+ const jsonOutput = args.json;
57
+ const client = getClient();
58
+ if (!jsonOutput) {
59
+ console.log(`Open Broker - ${normalizeCoin(coin)} Candles (${interval})`);
60
+ console.log('='.repeat(40) + '\n');
61
+ }
62
+ try {
63
+ // Load metadata (needed for HIP-3 coin resolution)
64
+ await client.getMetaAndAssetCtxs();
65
+ if (client.isTestnet && coin.includes(':')) {
66
+ await client.loadSingleHip3Dex(coin.split(':')[0]);
67
+ }
68
+ const now = Date.now();
69
+ const startTime = now - (bars * (INTERVAL_MS[interval] || 3_600_000));
70
+ const candles = await client.getCandleSnapshot(normalizeCoin(coin), interval, startTime);
71
+ if (jsonOutput) {
72
+ let assetId = -1;
73
+ try {
74
+ assetId = client.getAssetIndex(normalizeCoin(coin));
75
+ }
76
+ catch { /* noop */ }
77
+ console.log(JSON.stringify({ coin: normalizeCoin(coin), assetId, interval, candles }, null, 2));
78
+ return;
79
+ }
80
+ if (candles.length === 0) {
81
+ console.log('No candle data found');
82
+ return;
83
+ }
84
+ // Table header
85
+ console.log('Time'.padEnd(20) +
86
+ 'Open'.padEnd(14) +
87
+ 'High'.padEnd(14) +
88
+ 'Low'.padEnd(14) +
89
+ 'Close'.padEnd(14) +
90
+ 'Volume'.padEnd(12) +
91
+ 'Trades');
92
+ console.log('─'.repeat(95));
93
+ for (const c of candles) {
94
+ const time = new Date(c.t).toLocaleString();
95
+ const vol = parseFloat(c.v);
96
+ console.log(time.padEnd(20) +
97
+ formatUsd(parseFloat(c.o)).padEnd(14) +
98
+ formatUsd(parseFloat(c.h)).padEnd(14) +
99
+ formatUsd(parseFloat(c.l)).padEnd(14) +
100
+ formatUsd(parseFloat(c.c)).padEnd(14) +
101
+ formatVolume(vol).padEnd(12) +
102
+ String(c.n));
103
+ }
104
+ // Summary
105
+ const opens = candles.map(c => parseFloat(c.o));
106
+ const highs = candles.map(c => parseFloat(c.h));
107
+ const lows = candles.map(c => parseFloat(c.l));
108
+ const closes = candles.map(c => parseFloat(c.c));
109
+ const totalVol = candles.reduce((s, c) => s + parseFloat(c.v), 0);
110
+ const totalTrades = candles.reduce((s, c) => s + c.n, 0);
111
+ console.log('─'.repeat(95));
112
+ console.log(`Bars: ${candles.length} | High: ${formatUsd(Math.max(...highs))} | Low: ${formatUsd(Math.min(...lows))} | Volume: ${formatVolume(totalVol)} | Trades: ${totalTrades}`);
113
+ console.log(`Change: ${formatUsd(closes[closes.length - 1] - opens[0])} (${((closes[closes.length - 1] - opens[0]) / opens[0] * 100).toFixed(2)}%)`);
114
+ }
115
+ catch (error) {
116
+ console.error('Error fetching candles:', error);
117
+ process.exit(1);
118
+ }
119
+ }
120
+ main();
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env npx tsx
2
+ export {};
3
+ //# sourceMappingURL=fees.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fees.d.ts","sourceRoot":"","sources":["../../scripts/info/fees.ts"],"names":[],"mappings":""}
@@ -0,0 +1,87 @@
1
+ #!/usr/bin/env npx tsx
2
+ // View fee schedule and trading volume from Hyperliquid
3
+ import { getClient } from '../core/client.js';
4
+ import { formatUsd, formatPercent, parseArgs } from '../core/utils.js';
5
+ function printUsage() {
6
+ console.log(`
7
+ Usage: openbroker fees [options]
8
+
9
+ Options:
10
+ --address <0x...> Look up another account's fees
11
+ --json Output as JSON (machine-readable)
12
+ --help, -h Show this help
13
+
14
+ Examples:
15
+ openbroker fees
16
+ openbroker fees --json
17
+ `);
18
+ }
19
+ async function main() {
20
+ const args = parseArgs(process.argv.slice(2));
21
+ if (args.help || args.h) {
22
+ printUsage();
23
+ process.exit(0);
24
+ }
25
+ const targetAddress = args.address;
26
+ const jsonOutput = args.json;
27
+ const client = getClient();
28
+ const lookupAddress = targetAddress?.toLowerCase();
29
+ if (!jsonOutput) {
30
+ console.log('Open Broker - Fee Schedule');
31
+ console.log('=========================\n');
32
+ if (targetAddress) {
33
+ console.log(`Lookup: ${lookupAddress}\n`);
34
+ }
35
+ }
36
+ try {
37
+ const fees = await client.getUserFees(lookupAddress);
38
+ if (jsonOutput) {
39
+ console.log(JSON.stringify(fees, null, 2));
40
+ return;
41
+ }
42
+ // Fee rates
43
+ console.log('Fee Rates');
44
+ console.log('─'.repeat(40));
45
+ console.log(`Perp Taker (Cross): ${formatPercent(parseFloat(fees.userCrossRate))}`);
46
+ console.log(`Perp Maker (Add): ${formatPercent(parseFloat(fees.userAddRate))}`);
47
+ console.log(`Spot Taker (Cross): ${formatPercent(parseFloat(fees.userSpotCrossRate))}`);
48
+ console.log(`Spot Maker (Add): ${formatPercent(parseFloat(fees.userSpotAddRate))}`);
49
+ console.log('');
50
+ // Discounts
51
+ const refDiscount = parseFloat(fees.activeReferralDiscount);
52
+ if (refDiscount > 0) {
53
+ console.log(`Referral Discount: ${formatPercent(refDiscount)}`);
54
+ }
55
+ if (fees.activeStakingDiscount) {
56
+ console.log(`Staking Discount: ${fees.activeStakingDiscount.basisPoints} bps (${formatPercent(parseFloat(fees.activeStakingDiscount.discountRate))})`);
57
+ }
58
+ if (fees.stakingLink) {
59
+ console.log(`Staking Link: ${fees.stakingLink.stakingUser} (${fees.stakingLink.status})`);
60
+ }
61
+ // Daily volumes
62
+ if (fees.dailyUserVlm && fees.dailyUserVlm.length > 0) {
63
+ console.log('\nRecent Daily Volume');
64
+ console.log('─'.repeat(60));
65
+ console.log('Date'.padEnd(14) +
66
+ 'Cross Vol'.padEnd(18) +
67
+ 'Add Vol'.padEnd(18) +
68
+ 'Total');
69
+ console.log('─'.repeat(60));
70
+ // Show last 7 days
71
+ const recent = fees.dailyUserVlm.slice(-7);
72
+ for (const day of recent) {
73
+ const cross = parseFloat(day.userCross || '0');
74
+ const add = parseFloat(day.userAdd || '0');
75
+ console.log(day.date.padEnd(14) +
76
+ formatUsd(cross).padEnd(18) +
77
+ formatUsd(add).padEnd(18) +
78
+ formatUsd(cross + add));
79
+ }
80
+ }
81
+ }
82
+ catch (error) {
83
+ console.error('Error fetching fees:', error);
84
+ process.exit(1);
85
+ }
86
+ }
87
+ main();
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env npx tsx
2
+ export {};
3
+ //# sourceMappingURL=fills.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fills.d.ts","sourceRoot":"","sources":["../../scripts/info/fills.ts"],"names":[],"mappings":""}
@@ -0,0 +1,105 @@
1
+ #!/usr/bin/env npx tsx
2
+ // View trade fill history from Hyperliquid
3
+ import { getClient } from '../core/client.js';
4
+ import { formatUsd, parseArgs, normalizeCoin } from '../core/utils.js';
5
+ function printUsage() {
6
+ console.log(`
7
+ Usage: openbroker fills [options]
8
+
9
+ Options:
10
+ --coin <symbol> Filter by coin (e.g. ETH, BTC)
11
+ --side <buy|sell> Filter by side
12
+ --top <n> Show last N fills (default: 20)
13
+ --address <0x...> Look up another account's fills
14
+ --help, -h Show this help
15
+
16
+ Examples:
17
+ openbroker fills
18
+ openbroker fills --coin ETH
19
+ openbroker fills --coin BTC --side buy --top 50
20
+ openbroker fills --address 0xabc... --coin ETH
21
+ `);
22
+ }
23
+ async function main() {
24
+ const args = parseArgs(process.argv.slice(2));
25
+ if (args.help || args.h) {
26
+ printUsage();
27
+ process.exit(0);
28
+ }
29
+ const filterCoin = args.coin;
30
+ const filterSide = args.side;
31
+ const top = parseInt(args.top) || 20;
32
+ const jsonOutput = args.json;
33
+ const targetAddress = args.address;
34
+ const client = getClient();
35
+ const lookupAddress = targetAddress?.toLowerCase();
36
+ try {
37
+ let fills = await client.getUserFills(lookupAddress);
38
+ if (filterCoin) {
39
+ fills = fills.filter(f => f.coin === normalizeCoin(filterCoin));
40
+ }
41
+ if (filterSide) {
42
+ const sideCode = filterSide.toLowerCase() === 'buy' ? 'B' : 'A';
43
+ fills = fills.filter(f => f.side === sideCode);
44
+ }
45
+ // Most recent first
46
+ fills.sort((a, b) => b.time - a.time);
47
+ fills = fills.slice(0, top);
48
+ if (jsonOutput) {
49
+ console.log(JSON.stringify(fills.map(f => ({
50
+ time: new Date(f.time).toISOString(),
51
+ coin: f.coin,
52
+ side: f.side === 'B' ? 'buy' : 'sell',
53
+ size: f.sz,
54
+ price: f.px,
55
+ fee: f.fee,
56
+ closedPnl: f.closedPnl,
57
+ })), null, 2));
58
+ return;
59
+ }
60
+ console.log('Open Broker - Trade Fills');
61
+ console.log('========================\n');
62
+ if (targetAddress) {
63
+ console.log(`Lookup: ${lookupAddress}\n`);
64
+ }
65
+ if (fills.length === 0) {
66
+ console.log('No fills found');
67
+ return;
68
+ }
69
+ // Table header
70
+ console.log('Time'.padEnd(20) +
71
+ 'Coin'.padEnd(10) +
72
+ 'Side'.padEnd(6) +
73
+ 'Size'.padEnd(14) +
74
+ 'Price'.padEnd(14) +
75
+ 'Fee'.padEnd(12) +
76
+ 'Closed PnL');
77
+ console.log('─'.repeat(90));
78
+ let totalFees = 0;
79
+ let totalPnl = 0;
80
+ for (const fill of fills) {
81
+ const time = new Date(fill.time).toLocaleString();
82
+ const side = fill.side === 'B' ? 'BUY' : 'SELL';
83
+ const fee = parseFloat(fill.fee);
84
+ const pnl = parseFloat(fill.closedPnl);
85
+ totalFees += fee;
86
+ totalPnl += pnl;
87
+ console.log(time.padEnd(20) +
88
+ fill.coin.padEnd(10) +
89
+ side.padEnd(6) +
90
+ fill.sz.padEnd(14) +
91
+ formatUsd(parseFloat(fill.px)).padEnd(14) +
92
+ formatUsd(fee).padEnd(12) +
93
+ formatUsd(pnl));
94
+ }
95
+ console.log('─'.repeat(90));
96
+ console.log(`Showing ${fills.length} fills`);
97
+ console.log(`Total Fees: ${formatUsd(totalFees)}`);
98
+ console.log(`Total Closed PnL: ${formatUsd(totalPnl)}`);
99
+ }
100
+ catch (error) {
101
+ console.error('Error fetching fills:', error);
102
+ process.exit(1);
103
+ }
104
+ }
105
+ main();
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env npx tsx
2
+ export {};
3
+ //# sourceMappingURL=funding-history.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"funding-history.d.ts","sourceRoot":"","sources":["../../scripts/info/funding-history.ts"],"names":[],"mappings":""}