openbroker 1.3.2 → 1.5.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 (169) hide show
  1. package/CHANGELOG.md +23 -0
  2. package/dist/auto/audit.d.ts +57 -0
  3. package/dist/auto/audit.d.ts.map +1 -0
  4. package/dist/auto/audit.js +407 -0
  5. package/dist/auto/cli.d.ts +2 -0
  6. package/dist/auto/cli.d.ts.map +1 -0
  7. package/dist/auto/cli.js +423 -0
  8. package/dist/auto/events.d.ts +11 -0
  9. package/dist/auto/events.d.ts.map +1 -0
  10. package/dist/auto/events.js +36 -0
  11. package/dist/auto/examples/dca.d.ts +4 -0
  12. package/dist/auto/examples/dca.d.ts.map +1 -0
  13. package/dist/auto/examples/dca.js +60 -0
  14. package/dist/auto/examples/funding-arb.d.ts +4 -0
  15. package/dist/auto/examples/funding-arb.d.ts.map +1 -0
  16. package/dist/auto/examples/funding-arb.js +81 -0
  17. package/dist/auto/examples/grid.d.ts +4 -0
  18. package/dist/auto/examples/grid.d.ts.map +1 -0
  19. package/dist/auto/examples/grid.js +114 -0
  20. package/dist/auto/examples/mm-maker.d.ts +4 -0
  21. package/dist/auto/examples/mm-maker.d.ts.map +1 -0
  22. package/dist/auto/examples/mm-maker.js +131 -0
  23. package/dist/auto/examples/mm-spread.d.ts +4 -0
  24. package/dist/auto/examples/mm-spread.d.ts.map +1 -0
  25. package/dist/auto/examples/mm-spread.js +119 -0
  26. package/dist/auto/examples/price-alert.d.ts +4 -0
  27. package/dist/auto/examples/price-alert.d.ts.map +1 -0
  28. package/dist/auto/examples/price-alert.js +85 -0
  29. package/dist/auto/keep-awake.d.ts +11 -0
  30. package/dist/auto/keep-awake.d.ts.map +1 -0
  31. package/dist/auto/keep-awake.js +70 -0
  32. package/dist/auto/loader.d.ts +22 -0
  33. package/dist/auto/loader.d.ts.map +1 -0
  34. package/dist/auto/loader.js +127 -0
  35. package/dist/auto/prune.d.ts +40 -0
  36. package/dist/auto/prune.d.ts.map +1 -0
  37. package/dist/auto/prune.js +204 -0
  38. package/dist/auto/registry.d.ts +24 -0
  39. package/dist/auto/registry.d.ts.map +1 -0
  40. package/dist/auto/registry.js +93 -0
  41. package/dist/auto/report.d.ts +3 -0
  42. package/dist/auto/report.d.ts.map +1 -0
  43. package/dist/auto/report.js +385 -0
  44. package/dist/auto/runtime.d.ts +33 -0
  45. package/dist/auto/runtime.d.ts.map +1 -0
  46. package/dist/auto/runtime.js +844 -0
  47. package/dist/auto/types.d.ts +236 -0
  48. package/dist/auto/types.d.ts.map +1 -0
  49. package/dist/auto/types.js +3 -0
  50. package/dist/core/client.d.ts +691 -0
  51. package/dist/core/client.d.ts.map +1 -0
  52. package/dist/core/client.js +2061 -0
  53. package/dist/core/config.d.ts +22 -0
  54. package/dist/core/config.d.ts.map +1 -0
  55. package/dist/core/config.js +143 -0
  56. package/dist/core/types.d.ts +228 -0
  57. package/dist/core/types.d.ts.map +1 -0
  58. package/dist/core/types.js +2 -0
  59. package/dist/core/utils.d.ts +61 -0
  60. package/dist/core/utils.d.ts.map +1 -0
  61. package/dist/core/utils.js +142 -0
  62. package/dist/core/ws.d.ts +121 -0
  63. package/dist/core/ws.d.ts.map +1 -0
  64. package/dist/core/ws.js +222 -0
  65. package/dist/info/account.d.ts +3 -0
  66. package/dist/info/account.d.ts.map +1 -0
  67. package/dist/info/account.js +198 -0
  68. package/dist/info/all-markets.d.ts +3 -0
  69. package/dist/info/all-markets.d.ts.map +1 -0
  70. package/dist/info/all-markets.js +272 -0
  71. package/dist/info/candles.d.ts +3 -0
  72. package/dist/info/candles.d.ts.map +1 -0
  73. package/dist/info/candles.js +120 -0
  74. package/dist/info/fees.d.ts +3 -0
  75. package/dist/info/fees.d.ts.map +1 -0
  76. package/dist/info/fees.js +87 -0
  77. package/dist/info/fills.d.ts +3 -0
  78. package/dist/info/fills.d.ts.map +1 -0
  79. package/dist/info/fills.js +105 -0
  80. package/dist/info/funding-history.d.ts +3 -0
  81. package/dist/info/funding-history.d.ts.map +1 -0
  82. package/dist/info/funding-history.js +98 -0
  83. package/dist/info/funding-scan.d.ts +3 -0
  84. package/dist/info/funding-scan.d.ts.map +1 -0
  85. package/dist/info/funding-scan.js +178 -0
  86. package/dist/info/funding.d.ts +3 -0
  87. package/dist/info/funding.d.ts.map +1 -0
  88. package/dist/info/funding.js +158 -0
  89. package/dist/info/markets.d.ts +3 -0
  90. package/dist/info/markets.d.ts.map +1 -0
  91. package/dist/info/markets.js +178 -0
  92. package/dist/info/order-status.d.ts +3 -0
  93. package/dist/info/order-status.d.ts.map +1 -0
  94. package/dist/info/order-status.js +85 -0
  95. package/dist/info/orders.d.ts +3 -0
  96. package/dist/info/orders.d.ts.map +1 -0
  97. package/dist/info/orders.js +162 -0
  98. package/dist/info/outcomes.d.ts +3 -0
  99. package/dist/info/outcomes.d.ts.map +1 -0
  100. package/dist/info/outcomes.js +175 -0
  101. package/dist/info/positions.d.ts +3 -0
  102. package/dist/info/positions.d.ts.map +1 -0
  103. package/dist/info/positions.js +127 -0
  104. package/dist/info/rate-limit.d.ts +3 -0
  105. package/dist/info/rate-limit.d.ts.map +1 -0
  106. package/dist/info/rate-limit.js +58 -0
  107. package/dist/info/search-markets.d.ts +3 -0
  108. package/dist/info/search-markets.d.ts.map +1 -0
  109. package/dist/info/search-markets.js +296 -0
  110. package/dist/info/spot.d.ts +3 -0
  111. package/dist/info/spot.d.ts.map +1 -0
  112. package/dist/info/spot.js +192 -0
  113. package/dist/info/trades.d.ts +3 -0
  114. package/dist/info/trades.d.ts.map +1 -0
  115. package/dist/info/trades.js +97 -0
  116. package/dist/lib.d.ts +14 -0
  117. package/dist/lib.d.ts.map +1 -0
  118. package/dist/lib.js +17 -0
  119. package/dist/operations/bracket.d.ts +28 -0
  120. package/dist/operations/bracket.d.ts.map +1 -0
  121. package/dist/operations/bracket.js +266 -0
  122. package/dist/operations/cancel.d.ts +3 -0
  123. package/dist/operations/cancel.d.ts.map +1 -0
  124. package/dist/operations/cancel.js +107 -0
  125. package/dist/operations/chase.d.ts +25 -0
  126. package/dist/operations/chase.d.ts.map +1 -0
  127. package/dist/operations/chase.js +215 -0
  128. package/dist/operations/limit-order.d.ts +3 -0
  129. package/dist/operations/limit-order.d.ts.map +1 -0
  130. package/dist/operations/limit-order.js +144 -0
  131. package/dist/operations/market-order.d.ts +3 -0
  132. package/dist/operations/market-order.d.ts.map +1 -0
  133. package/dist/operations/market-order.js +153 -0
  134. package/dist/operations/outcome-order.d.ts +3 -0
  135. package/dist/operations/outcome-order.d.ts.map +1 -0
  136. package/dist/operations/outcome-order.js +171 -0
  137. package/dist/operations/scale.d.ts +3 -0
  138. package/dist/operations/scale.d.ts.map +1 -0
  139. package/dist/operations/scale.js +212 -0
  140. package/dist/operations/set-tpsl.d.ts +3 -0
  141. package/dist/operations/set-tpsl.d.ts.map +1 -0
  142. package/dist/operations/set-tpsl.js +277 -0
  143. package/dist/operations/spot-order.d.ts +3 -0
  144. package/dist/operations/spot-order.d.ts.map +1 -0
  145. package/dist/operations/spot-order.js +173 -0
  146. package/dist/operations/trigger-order.d.ts +3 -0
  147. package/dist/operations/trigger-order.d.ts.map +1 -0
  148. package/dist/operations/trigger-order.js +177 -0
  149. package/dist/operations/twap-cancel.d.ts +3 -0
  150. package/dist/operations/twap-cancel.d.ts.map +1 -0
  151. package/dist/operations/twap-cancel.js +57 -0
  152. package/dist/operations/twap-status.d.ts +3 -0
  153. package/dist/operations/twap-status.d.ts.map +1 -0
  154. package/dist/operations/twap-status.js +81 -0
  155. package/dist/operations/twap.d.ts +3 -0
  156. package/dist/operations/twap.d.ts.map +1 -0
  157. package/dist/operations/twap.js +124 -0
  158. package/dist/setup/approve-builder.d.ts +3 -0
  159. package/dist/setup/approve-builder.d.ts.map +1 -0
  160. package/dist/setup/approve-builder.js +155 -0
  161. package/dist/setup/env.d.ts +4 -0
  162. package/dist/setup/env.d.ts.map +1 -0
  163. package/dist/setup/env.js +8 -0
  164. package/dist/setup/onboard.d.ts +10 -0
  165. package/dist/setup/onboard.d.ts.map +1 -0
  166. package/dist/setup/onboard.js +462 -0
  167. package/package.json +10 -4
  168. package/scripts/core/client.ts +19 -1
  169. package/scripts/core/types.ts +7 -0
@@ -0,0 +1,85 @@
1
+ #!/usr/bin/env npx tsx
2
+ // Check status of a specific order on Hyperliquid
3
+ import { getClient } from '../core/client.js';
4
+ import { formatUsd, parseArgs } from '../core/utils.js';
5
+ function printUsage() {
6
+ console.log(`
7
+ Usage: openbroker order-status --oid <order-id>
8
+
9
+ Options:
10
+ --oid <id> Order ID (number) or client order ID (hex string) — required
11
+ --address <0x...> Look up order on another account
12
+ --json Output as JSON (machine-readable)
13
+ --help, -h Show this help
14
+
15
+ Examples:
16
+ openbroker order-status --oid 123456789
17
+ openbroker order-status --oid 0x1234abcd...
18
+ openbroker order-status --oid 123456789 --address 0xabc...
19
+ `);
20
+ }
21
+ async function main() {
22
+ const args = parseArgs(process.argv.slice(2));
23
+ if (args.help || args.h) {
24
+ printUsage();
25
+ process.exit(0);
26
+ }
27
+ const oidArg = args.oid;
28
+ if (!oidArg) {
29
+ console.error('Error: --oid is required');
30
+ printUsage();
31
+ process.exit(1);
32
+ }
33
+ const oid = oidArg.startsWith('0x') ? oidArg : parseInt(oidArg);
34
+ const targetAddress = args.address;
35
+ const jsonOutput = args.json;
36
+ const client = getClient();
37
+ const lookupAddress = targetAddress?.toLowerCase();
38
+ if (!jsonOutput) {
39
+ console.log('Open Broker - Order Status');
40
+ console.log('=========================\n');
41
+ }
42
+ try {
43
+ const result = await client.getOrderStatus(oid, lookupAddress);
44
+ if (jsonOutput) {
45
+ console.log(JSON.stringify(result, null, 2));
46
+ return;
47
+ }
48
+ if (result.status === 'unknownOid') {
49
+ console.log(`Order ${oidArg} not found`);
50
+ return;
51
+ }
52
+ if (result.order) {
53
+ const o = result.order.order;
54
+ const time = new Date(o.timestamp).toLocaleString();
55
+ const statusTime = new Date(result.order.statusTimestamp).toLocaleString();
56
+ const side = o.side === 'B' ? 'BUY' : 'SELL';
57
+ console.log(`${o.coin} - ${o.orderType}`);
58
+ console.log('─'.repeat(40));
59
+ console.log(`Order ID: ${o.oid}`);
60
+ if (o.cloid)
61
+ console.log(`Client OID: ${o.cloid}`);
62
+ console.log(`Side: ${side}`);
63
+ console.log(`Size: ${o.sz} (orig: ${o.origSz})`);
64
+ console.log(`Limit Price: ${formatUsd(parseFloat(o.limitPx))}`);
65
+ console.log(`Type: ${o.orderType}`);
66
+ if (o.tif)
67
+ console.log(`Time in Force: ${o.tif}`);
68
+ console.log(`Reduce Only: ${o.reduceOnly ? 'Yes' : 'No'}`);
69
+ if (o.isTrigger) {
70
+ console.log(`Trigger Price: ${formatUsd(parseFloat(o.triggerPx))}`);
71
+ console.log(`Trigger Cond: ${o.triggerCondition}`);
72
+ }
73
+ if (o.isPositionTpsl)
74
+ console.log(`Position TP/SL: Yes`);
75
+ console.log(`Status: ${result.order.status}`);
76
+ console.log(`Created: ${time}`);
77
+ console.log(`Status Updated: ${statusTime}`);
78
+ }
79
+ }
80
+ catch (error) {
81
+ console.error('Error fetching order status:', error);
82
+ process.exit(1);
83
+ }
84
+ }
85
+ main();
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env npx tsx
2
+ export {};
3
+ //# sourceMappingURL=orders.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"orders.d.ts","sourceRoot":"","sources":["../../scripts/info/orders.ts"],"names":[],"mappings":""}
@@ -0,0 +1,162 @@
1
+ #!/usr/bin/env npx tsx
2
+ // View historical orders 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 orders [options]
8
+
9
+ Options:
10
+ --coin <symbol> Filter by coin (e.g. ETH, BTC)
11
+ --status <status> Filter by status (filled, canceled, open, triggered, rejected, etc.)
12
+ --open Show only currently open orders
13
+ --top <n> Show last N orders (default: 20)
14
+ --address <0x...> Look up another account's orders
15
+ --help, -h Show this help
16
+
17
+ Examples:
18
+ openbroker orders
19
+ openbroker orders --open
20
+ openbroker orders --open --coin ETH
21
+ openbroker orders --coin ETH --status filled
22
+ openbroker orders --top 50
23
+ openbroker orders --address 0xabc... --open
24
+ `);
25
+ }
26
+ async function main() {
27
+ const args = parseArgs(process.argv.slice(2));
28
+ if (args.help || args.h) {
29
+ printUsage();
30
+ process.exit(0);
31
+ }
32
+ const filterCoin = args.coin;
33
+ const filterStatus = args.status;
34
+ const openOnly = args.open;
35
+ const top = parseInt(args.top) || 20;
36
+ const jsonOutput = args.json;
37
+ const targetAddress = args.address;
38
+ const client = getClient();
39
+ const lookupAddress = targetAddress?.toLowerCase();
40
+ try {
41
+ // On testnet, load specific HIP-3 dex on demand if filtering by dex:COIN
42
+ if (client.isTestnet && filterCoin?.includes(':')) {
43
+ await client.loadSingleHip3Dex(filterCoin.split(':')[0]);
44
+ }
45
+ if (openOnly) {
46
+ // Use the dedicated open orders endpoint
47
+ let openOrders = await client.getOpenOrders(lookupAddress);
48
+ if (filterCoin) {
49
+ openOrders = openOrders.filter(o => o.coin === normalizeCoin(filterCoin));
50
+ }
51
+ openOrders.sort((a, b) => b.timestamp - a.timestamp);
52
+ openOrders = openOrders.slice(0, top);
53
+ if (jsonOutput) {
54
+ console.log(JSON.stringify(openOrders.map(o => ({
55
+ time: new Date(o.timestamp).toISOString(),
56
+ coin: o.coin,
57
+ side: o.side === 'B' ? 'buy' : 'sell',
58
+ orderType: o.orderType,
59
+ size: o.sz,
60
+ origSize: o.origSz,
61
+ price: o.limitPx,
62
+ status: 'open',
63
+ oid: o.oid,
64
+ })), null, 2));
65
+ return;
66
+ }
67
+ console.log('Open Broker - Open Orders');
68
+ console.log('=========================\n');
69
+ if (targetAddress) {
70
+ console.log(`Lookup: ${lookupAddress}\n`);
71
+ }
72
+ if (openOrders.length === 0) {
73
+ console.log('No open orders found');
74
+ return;
75
+ }
76
+ // Table header
77
+ console.log('Time'.padEnd(20) +
78
+ 'Coin'.padEnd(10) +
79
+ 'Side'.padEnd(6) +
80
+ 'Type'.padEnd(14) +
81
+ 'Size'.padEnd(12) +
82
+ 'Price'.padEnd(14) +
83
+ 'OID');
84
+ console.log('─'.repeat(90));
85
+ for (const o of openOrders) {
86
+ const time = new Date(o.timestamp).toLocaleString();
87
+ const side = o.side === 'B' ? 'BUY' : 'SELL';
88
+ console.log(time.padEnd(20) +
89
+ o.coin.padEnd(10) +
90
+ side.padEnd(6) +
91
+ o.orderType.padEnd(14) +
92
+ o.sz.padEnd(12) +
93
+ formatUsd(parseFloat(o.limitPx)).padEnd(14) +
94
+ String(o.oid));
95
+ }
96
+ console.log('─'.repeat(90));
97
+ console.log(`Showing ${openOrders.length} open orders`);
98
+ return;
99
+ }
100
+ let orders = await client.getHistoricalOrders(lookupAddress);
101
+ if (filterCoin) {
102
+ orders = orders.filter(o => o.order.coin === normalizeCoin(filterCoin));
103
+ }
104
+ if (filterStatus) {
105
+ const s = filterStatus.toLowerCase();
106
+ orders = orders.filter(o => o.status.toLowerCase().includes(s));
107
+ }
108
+ // Most recent first
109
+ orders.sort((a, b) => b.order.timestamp - a.order.timestamp);
110
+ orders = orders.slice(0, top);
111
+ if (jsonOutput) {
112
+ console.log(JSON.stringify(orders.map(entry => ({
113
+ time: new Date(entry.order.timestamp).toISOString(),
114
+ coin: entry.order.coin,
115
+ side: entry.order.side === 'B' ? 'buy' : 'sell',
116
+ orderType: entry.order.orderType,
117
+ size: entry.order.sz,
118
+ price: entry.order.limitPx,
119
+ status: entry.status,
120
+ oid: entry.order.oid,
121
+ })), null, 2));
122
+ return;
123
+ }
124
+ console.log('Open Broker - Order History');
125
+ console.log('==========================\n');
126
+ if (targetAddress) {
127
+ console.log(`Lookup: ${lookupAddress}\n`);
128
+ }
129
+ if (orders.length === 0) {
130
+ console.log('No orders found');
131
+ return;
132
+ }
133
+ // Table header
134
+ console.log('Time'.padEnd(20) +
135
+ 'Coin'.padEnd(10) +
136
+ 'Side'.padEnd(6) +
137
+ 'Type'.padEnd(14) +
138
+ 'Size'.padEnd(12) +
139
+ 'Price'.padEnd(14) +
140
+ 'Status');
141
+ console.log('─'.repeat(90));
142
+ for (const entry of orders) {
143
+ const o = entry.order;
144
+ const time = new Date(o.timestamp).toLocaleString();
145
+ const side = o.side === 'B' ? 'BUY' : 'SELL';
146
+ console.log(time.padEnd(20) +
147
+ o.coin.padEnd(10) +
148
+ side.padEnd(6) +
149
+ o.orderType.padEnd(14) +
150
+ o.sz.padEnd(12) +
151
+ formatUsd(parseFloat(o.limitPx)).padEnd(14) +
152
+ entry.status);
153
+ }
154
+ console.log('─'.repeat(90));
155
+ console.log(`Showing ${orders.length} orders`);
156
+ }
157
+ catch (error) {
158
+ console.error('Error fetching orders:', error);
159
+ process.exit(1);
160
+ }
161
+ }
162
+ main();
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env tsx
2
+ export {};
3
+ //# sourceMappingURL=outcomes.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"outcomes.d.ts","sourceRoot":"","sources":["../../scripts/info/outcomes.ts"],"names":[],"mappings":""}
@@ -0,0 +1,175 @@
1
+ #!/usr/bin/env tsx
2
+ // HIP-4 Outcomes - search and inspect prediction markets
3
+ import { getClient } from '../core/client.js';
4
+ function parseArgs() {
5
+ const args = {};
6
+ for (let i = 2; i < process.argv.length; i++) {
7
+ const arg = process.argv[i];
8
+ if ((arg === '--query' || arg === '-q') && process.argv[i + 1]) {
9
+ args.query = process.argv[++i];
10
+ }
11
+ else if ((arg === '--outcome' || arg === '--id') && process.argv[i + 1]) {
12
+ args.outcome = process.argv[++i];
13
+ }
14
+ else if (arg === '--side' && process.argv[i + 1]) {
15
+ args.side = process.argv[++i];
16
+ }
17
+ else if (arg === '--balances') {
18
+ args.balances = true;
19
+ }
20
+ else if (arg === '--top' && process.argv[i + 1]) {
21
+ args.top = parseInt(process.argv[++i], 10);
22
+ }
23
+ else if (arg === '--verbose') {
24
+ args.verbose = true;
25
+ }
26
+ else if (arg === '--json') {
27
+ args.json = true;
28
+ }
29
+ else if (arg === '--help' || arg === '-h') {
30
+ printUsage();
31
+ process.exit(0);
32
+ }
33
+ else if (!args.query && !arg.startsWith('-')) {
34
+ args.query = arg;
35
+ }
36
+ }
37
+ return args;
38
+ }
39
+ function printUsage() {
40
+ console.log(`
41
+ Open Broker - HIP-4 Outcomes
42
+ ============================
43
+
44
+ Search and inspect Hyperliquid outcome markets.
45
+
46
+ Usage:
47
+ openbroker outcomes [--query <text>] [--outcome <id|#encoding|+encoding>] [options]
48
+
49
+ Options:
50
+ --query, -q <text> Search market name, description, underlying, expiry, target
51
+ --outcome, --id <ref> Show one outcome by id or encoded coin (#1230 / +1230)
52
+ --side <yes|no|0|1> Select a side when using a plain outcome id
53
+ --balances Show outcome token balances for the configured account
54
+ --top <n> Show only top N matches
55
+ --json Output as JSON
56
+ --verbose Include raw descriptions and question metadata
57
+
58
+ Examples:
59
+ openbroker outcomes --query BTC
60
+ openbroker outcomes --outcome 123
61
+ openbroker outcomes --outcome 123 --side yes --json
62
+ openbroker outcomes --balances
63
+ `);
64
+ }
65
+ function formatPrice(value) {
66
+ if (!value)
67
+ return '-';
68
+ const n = parseFloat(value);
69
+ if (!Number.isFinite(n))
70
+ return value;
71
+ return n.toFixed(4);
72
+ }
73
+ function formatVolume(value) {
74
+ if (!value)
75
+ return '-';
76
+ const n = parseFloat(value);
77
+ if (!Number.isFinite(n))
78
+ return value;
79
+ if (n >= 1_000_000)
80
+ return `$${(n / 1_000_000).toFixed(2)}M`;
81
+ if (n >= 1_000)
82
+ return `$${(n / 1_000).toFixed(2)}K`;
83
+ return `$${n.toFixed(2)}`;
84
+ }
85
+ async function main() {
86
+ const args = parseArgs();
87
+ const client = getClient();
88
+ client.verbose = args.verbose ?? false;
89
+ if (!args.json) {
90
+ console.log('Open Broker - HIP-4 Outcomes');
91
+ console.log('============================\n');
92
+ }
93
+ try {
94
+ if (args.balances) {
95
+ const balances = await client.getSpotBalances();
96
+ const outcomeBalances = (balances.balances ?? []).filter((b) => b.coin.startsWith('+') || b.coin.startsWith('#'));
97
+ if (args.json) {
98
+ console.log(JSON.stringify(outcomeBalances, null, 2));
99
+ return;
100
+ }
101
+ if (outcomeBalances.length === 0) {
102
+ console.log('No outcome token balances found.');
103
+ return;
104
+ }
105
+ console.log('Outcome Balances');
106
+ console.log('----------------');
107
+ console.log('Token Total Hold Entry Value');
108
+ console.log('-'.repeat(70));
109
+ for (const b of outcomeBalances) {
110
+ console.log(`${b.coin.padEnd(12)} ${parseFloat(b.total).toFixed(6).padStart(18)} ` +
111
+ `${parseFloat(b.hold).toFixed(6).padStart(18)} ${formatVolume(b.entryNtl).padStart(15)}`);
112
+ }
113
+ return;
114
+ }
115
+ let markets = await client.getOutcomeMarkets();
116
+ if (args.outcome) {
117
+ const resolved = client.resolveOutcomeRef(args.outcome, args.side);
118
+ markets = markets.filter((market) => market.outcome === resolved.outcome);
119
+ for (const market of markets) {
120
+ market.sides = market.sides.filter((side) => side.side === resolved.side);
121
+ }
122
+ }
123
+ if (args.query) {
124
+ const query = args.query.toUpperCase();
125
+ markets = markets.filter((market) => {
126
+ const parsed = Object.values(market.parsedDescription).join(' ');
127
+ const searchable = `${market.name} ${market.description} ${parsed}`.toUpperCase();
128
+ return searchable.includes(query);
129
+ });
130
+ }
131
+ markets.sort((a, b) => {
132
+ const aVol = Math.max(...a.sides.map((s) => parseFloat(s.dayNtlVlm ?? '0')));
133
+ const bVol = Math.max(...b.sides.map((s) => parseFloat(s.dayNtlVlm ?? '0')));
134
+ return bVol - aVol;
135
+ });
136
+ const displayMarkets = args.top ? markets.slice(0, args.top) : markets;
137
+ if (args.json) {
138
+ console.log(JSON.stringify(displayMarkets, null, 2));
139
+ return;
140
+ }
141
+ if (displayMarkets.length === 0) {
142
+ console.log('No outcome markets found.');
143
+ return;
144
+ }
145
+ console.log(`Found ${displayMarkets.length} outcome market(s)\n`);
146
+ console.log('Outcome Side Coin AssetID Price 24h Volume Market');
147
+ console.log('-'.repeat(98));
148
+ for (const market of displayMarkets) {
149
+ const spec = market.parsedDescription;
150
+ const labelParts = [
151
+ spec.underlying,
152
+ spec.expiry ? `exp ${spec.expiry}` : undefined,
153
+ spec.targetPrice ? `target ${spec.targetPrice}` : undefined,
154
+ ].filter(Boolean);
155
+ const label = labelParts.length > 0 ? labelParts.join(' | ') : market.description;
156
+ for (const side of market.sides) {
157
+ console.log(`${String(market.outcome).padStart(7)} ${side.name.padEnd(4)} ${side.coin.padEnd(9)} ` +
158
+ `${String(side.assetId).padStart(10)} ${formatPrice(side.midPx ?? side.markPx).padStart(7)} ` +
159
+ `${formatVolume(side.dayNtlVlm).padStart(13)} ${label}`);
160
+ }
161
+ if (args.verbose) {
162
+ console.log(` Description: ${market.description}`);
163
+ if (market.question)
164
+ console.log(` Question: ${market.question.name}`);
165
+ }
166
+ }
167
+ }
168
+ catch (error) {
169
+ const message = error instanceof Error ? error.message : String(error);
170
+ console.error(`Error: ${message}`);
171
+ console.error('Note: Hyperliquid currently documents outcomeMeta as testnet-only.');
172
+ process.exit(1);
173
+ }
174
+ }
175
+ main();
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env npx tsx
2
+ export {};
3
+ //# sourceMappingURL=positions.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"positions.d.ts","sourceRoot":"","sources":["../../scripts/info/positions.ts"],"names":[],"mappings":""}
@@ -0,0 +1,127 @@
1
+ #!/usr/bin/env npx tsx
2
+ // Get detailed position info from Hyperliquid
3
+ import { getClient } from '../core/client.js';
4
+ import { formatUsd, formatPercent, parseArgs } from '../core/utils.js';
5
+ async function main() {
6
+ const args = parseArgs(process.argv.slice(2));
7
+ const filterCoin = args.coin;
8
+ const jsonOutput = args.json;
9
+ const targetAddress = args.address;
10
+ const client = getClient();
11
+ if (args.verbose) {
12
+ client.verbose = true;
13
+ }
14
+ const lookupAddress = targetAddress?.toLowerCase();
15
+ const isOtherAccount = !!targetAddress;
16
+ try {
17
+ const [state, mids, fundingHistory] = await Promise.all([
18
+ client.getUserStateAll(lookupAddress),
19
+ client.getAllMids(),
20
+ client.getUserFunding(lookupAddress),
21
+ ]);
22
+ const positions = state.assetPositions.filter(ap => {
23
+ const size = parseFloat(ap.position.szi);
24
+ if (Math.abs(size) < 0.0001)
25
+ return false;
26
+ if (filterCoin && ap.position.coin !== filterCoin)
27
+ return false;
28
+ return true;
29
+ });
30
+ // Sum cumulative funding per coin
31
+ const fundingByCoin = new Map();
32
+ for (const entry of fundingHistory) {
33
+ const coin = entry.delta.coin;
34
+ const usdc = parseFloat(entry.delta.usdc);
35
+ fundingByCoin.set(coin, (fundingByCoin.get(coin) ?? 0) + usdc);
36
+ }
37
+ // JSON output
38
+ if (jsonOutput) {
39
+ const result = positions.map(ap => {
40
+ const pos = ap.position;
41
+ const size = parseFloat(pos.szi);
42
+ const markPx = parseFloat(mids[pos.coin] || '0');
43
+ const liqPx = pos.liquidationPx ? parseFloat(pos.liquidationPx) : null;
44
+ return {
45
+ coin: pos.coin,
46
+ side: size > 0 ? 'long' : 'short',
47
+ size: pos.szi,
48
+ entryPrice: pos.entryPx,
49
+ markPrice: markPx,
50
+ notional: Math.abs(parseFloat(pos.positionValue)),
51
+ unrealizedPnl: parseFloat(pos.unrealizedPnl),
52
+ returnOnEquity: parseFloat(pos.returnOnEquity),
53
+ cumulativeFunding: fundingByCoin.get(pos.coin) ?? 0,
54
+ marginUsed: parseFloat(pos.marginUsed),
55
+ leverage: `${pos.leverage.value}x`,
56
+ leverageType: pos.leverage.type,
57
+ liquidationPrice: liqPx,
58
+ liquidationDistance: liqPx && markPx ? Math.abs((markPx - liqPx) / markPx) : null,
59
+ maxLeverage: pos.maxLeverage,
60
+ };
61
+ });
62
+ console.log(JSON.stringify(result, null, 2));
63
+ return;
64
+ }
65
+ // Human-readable output
66
+ console.log('Open Broker - Positions');
67
+ console.log('=======================\n');
68
+ if (isOtherAccount) {
69
+ console.log(`Lookup: ${lookupAddress}\n`);
70
+ }
71
+ if (positions.length === 0) {
72
+ console.log(filterCoin ? `No position in ${filterCoin}` : 'No open positions');
73
+ if (!filterCoin && !isOtherAccount && !client.isApiWallet) {
74
+ console.log('\n⚠️ If this account is traded via an API wallet, set HYPERLIQUID_ACCOUNT_ADDRESS');
75
+ console.log(' in ~/.openbroker/.env to the master account address.');
76
+ }
77
+ return;
78
+ }
79
+ for (const ap of positions) {
80
+ const pos = ap.position;
81
+ const size = parseFloat(pos.szi);
82
+ const entryPx = parseFloat(pos.entryPx);
83
+ const notional = parseFloat(pos.positionValue);
84
+ const pnl = parseFloat(pos.unrealizedPnl);
85
+ const marginUsed = parseFloat(pos.marginUsed);
86
+ const roe = parseFloat(pos.returnOnEquity);
87
+ const markPx = parseFloat(mids[pos.coin] || '0');
88
+ const side = size > 0 ? 'LONG' : 'SHORT';
89
+ const sideEmoji = size > 0 ? '+' : '-';
90
+ const cumulativeFunding = fundingByCoin.get(pos.coin) ?? 0;
91
+ console.log(`${pos.coin} - ${side}`);
92
+ console.log('─'.repeat(40));
93
+ console.log(`Size: ${sideEmoji}${Math.abs(size).toFixed(6)}`);
94
+ console.log(`Entry Price: ${formatUsd(entryPx)}`);
95
+ console.log(`Mark Price: ${formatUsd(markPx)}`);
96
+ console.log(`Notional: ${formatUsd(Math.abs(notional))}`);
97
+ console.log(`Unrealized PnL: ${formatUsd(pnl)} (${formatPercent(roe)})`);
98
+ console.log(`Cum. Funding: ${formatUsd(cumulativeFunding)}${cumulativeFunding >= 0 ? ' (received)' : ' (paid)'}`);
99
+ console.log(`Margin Used: ${formatUsd(marginUsed)}`);
100
+ console.log(`Leverage: ${pos.leverage.value}x (${pos.leverage.type})`);
101
+ if (pos.liquidationPx) {
102
+ const liqPx = parseFloat(pos.liquidationPx);
103
+ const liqDistance = Math.abs((markPx - liqPx) / markPx);
104
+ console.log(`Liquidation: ${formatUsd(liqPx)} (${formatPercent(liqDistance)} away)`);
105
+ }
106
+ console.log(`Max Leverage: ${pos.maxLeverage}x`);
107
+ console.log('');
108
+ }
109
+ // Summary
110
+ const totalFunding = Array.from(fundingByCoin.values()).reduce((sum, v) => sum + v, 0);
111
+ if (positions.length > 1) {
112
+ const totalPnl = positions.reduce((sum, ap) => sum + parseFloat(ap.position.unrealizedPnl), 0);
113
+ const totalNotional = positions.reduce((sum, ap) => sum + Math.abs(parseFloat(ap.position.positionValue)), 0);
114
+ console.log('Summary');
115
+ console.log('─'.repeat(40));
116
+ console.log(`Total Positions: ${positions.length}`);
117
+ console.log(`Total Notional: ${formatUsd(totalNotional)}`);
118
+ console.log(`Total PnL: ${formatUsd(totalPnl)}`);
119
+ console.log(`Total Funding: ${formatUsd(totalFunding)}${totalFunding >= 0 ? ' (received)' : ' (paid)'}`);
120
+ }
121
+ }
122
+ catch (error) {
123
+ console.error('Error fetching positions:', error);
124
+ process.exit(1);
125
+ }
126
+ }
127
+ main();
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env npx tsx
2
+ export {};
3
+ //# sourceMappingURL=rate-limit.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rate-limit.d.ts","sourceRoot":"","sources":["../../scripts/info/rate-limit.ts"],"names":[],"mappings":""}
@@ -0,0 +1,58 @@
1
+ #!/usr/bin/env npx tsx
2
+ // View API rate limit status on Hyperliquid
3
+ import { getClient } from '../core/client.js';
4
+ import { formatUsd, parseArgs } from '../core/utils.js';
5
+ function printUsage() {
6
+ console.log(`
7
+ Usage: openbroker rate-limit [options]
8
+
9
+ Options:
10
+ --json Output as JSON (machine-readable)
11
+ --help, -h Show this help
12
+
13
+ Examples:
14
+ openbroker rate-limit
15
+ `);
16
+ }
17
+ async function main() {
18
+ const args = parseArgs(process.argv.slice(2));
19
+ if (args.help || args.h) {
20
+ printUsage();
21
+ process.exit(0);
22
+ }
23
+ const jsonOutput = args.json;
24
+ const client = getClient();
25
+ if (!jsonOutput) {
26
+ console.log('Open Broker - API Rate Limit');
27
+ console.log('===========================\n');
28
+ }
29
+ try {
30
+ const rl = await client.getUserRateLimit();
31
+ if (jsonOutput) {
32
+ console.log(JSON.stringify(rl, null, 2));
33
+ return;
34
+ }
35
+ const used = rl.nRequestsUsed;
36
+ const cap = rl.nRequestsCap;
37
+ const surplus = rl.nRequestsSurplus;
38
+ const pct = cap > 0 ? (used / cap * 100) : 0;
39
+ // Progress bar
40
+ const barWidth = 30;
41
+ const filled = Math.round(barWidth * Math.min(pct, 100) / 100);
42
+ const bar = '\u2588'.repeat(filled) + '\u2591'.repeat(barWidth - filled);
43
+ console.log('Rate Limit Status');
44
+ console.log('─'.repeat(40));
45
+ console.log(`Requests Used: ${used.toLocaleString()} / ${cap.toLocaleString()}`);
46
+ console.log(`Usage: [${bar}] ${pct.toFixed(1)}%`);
47
+ console.log(`Surplus: ${surplus.toLocaleString()}`);
48
+ console.log(`Cum. Volume: ${formatUsd(parseFloat(rl.cumVlm))}`);
49
+ if (pct > 80) {
50
+ console.log('\nWarning: API usage above 80% of capacity');
51
+ }
52
+ }
53
+ catch (error) {
54
+ console.error('Error fetching rate limit:', error);
55
+ process.exit(1);
56
+ }
57
+ }
58
+ main();
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env tsx
2
+ export {};
3
+ //# sourceMappingURL=search-markets.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"search-markets.d.ts","sourceRoot":"","sources":["../../scripts/info/search-markets.ts"],"names":[],"mappings":""}