openbroker 1.3.2 → 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 (167) hide show
  1. package/CHANGELOG.md +12 -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 +684 -0
  51. package/dist/core/client.d.ts.map +1 -0
  52. package/dist/core/client.js +2040 -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 +221 -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
@@ -0,0 +1,144 @@
1
+ #!/usr/bin/env npx tsx
2
+ // Execute a limit 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
+ Open Broker - Limit Order
8
+ =========================
9
+
10
+ Place a limit order with specified price.
11
+
12
+ Usage:
13
+ npx tsx scripts/operations/limit-order.ts --coin <COIN> --side <buy|sell> --size <SIZE> --price <PRICE>
14
+
15
+ Options:
16
+ --coin Asset to trade (e.g., ETH, BTC)
17
+ --side Order side: buy or sell
18
+ --size Order size in base asset
19
+ --price Limit price
20
+ --tif Time in force: GTC, IOC, or ALO (default: GTC)
21
+ GTC = Good Till Cancel (rests on book)
22
+ IOC = Immediate Or Cancel (fills or cancels)
23
+ ALO = Add Liquidity Only (post-only, maker only)
24
+ --leverage Set leverage (e.g., 10 for 10x). Cross for main perps, isolated for HIP-3
25
+ --reduce Reduce-only order (default: false)
26
+ --dry Dry run - show order details without executing
27
+
28
+ Examples:
29
+ npx tsx scripts/operations/limit-order.ts --coin ETH --side buy --size 1 --price 3000
30
+ npx tsx scripts/operations/limit-order.ts --coin BTC --side sell --size 0.1 --price 100000 --tif ALO
31
+ npx tsx scripts/operations/limit-order.ts --coin SOL --side buy --size 10 --price 150 --reduce
32
+ `);
33
+ }
34
+ async function main() {
35
+ const args = parseArgs(process.argv.slice(2));
36
+ // Parse and validate arguments
37
+ const coin = args.coin;
38
+ const side = args.side;
39
+ const size = parseFloat(args.size);
40
+ const price = parseFloat(args.price);
41
+ const tifArg = args.tif?.toUpperCase() || 'GTC';
42
+ const leverage = args.leverage ? parseInt(args.leverage) : undefined;
43
+ const reduceOnly = args.reduce;
44
+ const dryRun = args.dry;
45
+ if (!coin || !side || isNaN(size) || isNaN(price)) {
46
+ printUsage();
47
+ process.exit(1);
48
+ }
49
+ if (side !== 'buy' && side !== 'sell') {
50
+ console.error('Error: --side must be "buy" or "sell"');
51
+ process.exit(1);
52
+ }
53
+ if (size <= 0) {
54
+ console.error('Error: --size must be positive');
55
+ process.exit(1);
56
+ }
57
+ if (price <= 0) {
58
+ console.error('Error: --price must be positive');
59
+ process.exit(1);
60
+ }
61
+ // Map uppercase CLI input to Pascal case for SDK
62
+ const tifMap = {
63
+ 'GTC': 'Gtc',
64
+ 'IOC': 'Ioc',
65
+ 'ALO': 'Alo'
66
+ };
67
+ const tif = tifMap[tifArg];
68
+ if (!tif) {
69
+ console.error(`Error: --tif must be one of: GTC, IOC, ALO`);
70
+ process.exit(1);
71
+ }
72
+ const isBuy = side === 'buy';
73
+ const client = getClient();
74
+ console.log('Open Broker - Limit Order');
75
+ console.log('=========================\n');
76
+ try {
77
+ // Get current price for reference
78
+ const mids = await client.getAllMids();
79
+ const midPrice = parseFloat(mids[coin]);
80
+ if (!midPrice) {
81
+ console.error(`Error: No market data for ${coin}`);
82
+ process.exit(1);
83
+ }
84
+ const notional = price * size;
85
+ const distanceFromMid = ((price - midPrice) / midPrice) * 100;
86
+ console.log('Order Details');
87
+ console.log('-------------');
88
+ console.log(`Coin: ${coin}`);
89
+ console.log(`Side: ${isBuy ? 'BUY' : 'SELL'}`);
90
+ console.log(`Size: ${size}`);
91
+ console.log(`Limit Price: ${formatUsd(price)}`);
92
+ console.log(`Current Mid: ${formatUsd(midPrice)}`);
93
+ console.log(`Distance: ${distanceFromMid >= 0 ? '+' : ''}${distanceFromMid.toFixed(2)}% from mid`);
94
+ console.log(`Notional: ${formatUsd(notional)}`);
95
+ console.log(`Time in Force: ${tif}`);
96
+ console.log(`Reduce Only: ${reduceOnly ? 'Yes' : 'No'}`);
97
+ if (leverage)
98
+ console.log(`Leverage: ${leverage}x`);
99
+ console.log(`Builder Fee: ${client.builderInfo.f / 10} bps`);
100
+ // Warning if order would be aggressively priced
101
+ if ((isBuy && price > midPrice) || (!isBuy && price < midPrice)) {
102
+ console.log(`\n⚠️ Order is priced aggressively - may fill immediately as taker`);
103
+ }
104
+ if (dryRun) {
105
+ console.log('\n🔍 Dry run - order not submitted');
106
+ return;
107
+ }
108
+ console.log('\nSubmitting...');
109
+ const response = await client.limitOrder(coin, isBuy, size, price, tif, reduceOnly, leverage);
110
+ console.log('\nResult');
111
+ console.log('------');
112
+ if (response.status === 'ok' && response.response && typeof response.response !== 'string') {
113
+ const statuses = response.response.data.statuses;
114
+ for (const status of statuses) {
115
+ if (status.filled) {
116
+ const fillSz = parseFloat(status.filled.totalSz);
117
+ const avgPx = parseFloat(status.filled.avgPx);
118
+ const fillNotional = fillSz * avgPx;
119
+ console.log(`✅ Filled`);
120
+ console.log(` Order ID: ${status.filled.oid}`);
121
+ console.log(` Size: ${fillSz}`);
122
+ console.log(` Avg Price: ${formatUsd(avgPx)}`);
123
+ console.log(` Notional: ${formatUsd(fillNotional)}`);
124
+ }
125
+ else if (status.resting) {
126
+ console.log(`✅ Order placed`);
127
+ console.log(` Order ID: ${status.resting.oid}`);
128
+ console.log(` Status: Resting on book`);
129
+ }
130
+ else if (status.error) {
131
+ console.log(`❌ Error: ${status.error}`);
132
+ }
133
+ }
134
+ }
135
+ else {
136
+ console.log(`❌ Error: ${response.error || 'Unknown error'}`);
137
+ }
138
+ }
139
+ catch (error) {
140
+ console.error('Error submitting order:', error);
141
+ process.exit(1);
142
+ }
143
+ }
144
+ main();
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env npx tsx
2
+ export {};
3
+ //# sourceMappingURL=market-order.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"market-order.d.ts","sourceRoot":"","sources":["../../scripts/operations/market-order.ts"],"names":[],"mappings":""}
@@ -0,0 +1,153 @@
1
+ #!/usr/bin/env npx tsx
2
+ // Execute a market order on Hyperliquid
3
+ import { getClient } from '../core/client.js';
4
+ import { formatUsd, parseArgs, checkBuilderFeeApproval } from '../core/utils.js';
5
+ function printUsage() {
6
+ console.log(`
7
+ Open Broker - Market Order
8
+ ==========================
9
+
10
+ Execute a market order with slippage protection.
11
+
12
+ Usage:
13
+ npx tsx scripts/operations/market-order.ts --coin <COIN> --side <buy|sell> --size <SIZE>
14
+
15
+ Options:
16
+ --coin Asset to trade (e.g., ETH, BTC)
17
+ --side Order side: buy or sell
18
+ --size Order size in base asset
19
+ --slippage Slippage tolerance in bps (default: from config, usually 50 = 0.5%)
20
+ --leverage Set leverage (e.g., 10 for 10x). Cross for main perps, isolated for HIP-3
21
+ --reduce Reduce-only order (default: false)
22
+ --dry Dry run - show order details without executing
23
+ --verbose Show full API request/response for debugging
24
+
25
+ Environment:
26
+ HYPERLIQUID_PRIVATE_KEY Your wallet private key (0x...)
27
+ HYPERLIQUID_NETWORK "mainnet" or "testnet" (default: mainnet)
28
+ VERBOSE=1 Enable verbose logging
29
+
30
+ Examples:
31
+ npx tsx scripts/operations/market-order.ts --coin ETH --side buy --size 0.1
32
+ npx tsx scripts/operations/market-order.ts --coin BTC --side sell --size 0.01 --slippage 100
33
+ npx tsx scripts/operations/market-order.ts --coin SOL --side buy --size 10 --dry
34
+ npx tsx scripts/operations/market-order.ts --coin ETH --side buy --size 0.1 --verbose
35
+ `);
36
+ }
37
+ async function main() {
38
+ const args = parseArgs(process.argv.slice(2));
39
+ // Parse and validate arguments
40
+ const coin = args.coin;
41
+ const side = args.side;
42
+ const size = parseFloat(args.size);
43
+ const slippage = args.slippage ? parseInt(args.slippage) : undefined;
44
+ const leverage = args.leverage ? parseInt(args.leverage) : undefined;
45
+ const reduceOnly = args.reduce;
46
+ const dryRun = args.dry;
47
+ if (!coin || !side || isNaN(size)) {
48
+ printUsage();
49
+ process.exit(1);
50
+ }
51
+ if (side !== 'buy' && side !== 'sell') {
52
+ console.error('Error: --side must be "buy" or "sell"');
53
+ process.exit(1);
54
+ }
55
+ if (size <= 0) {
56
+ console.error('Error: --size must be positive');
57
+ process.exit(1);
58
+ }
59
+ const isBuy = side === 'buy';
60
+ const client = getClient();
61
+ // Enable verbose mode if requested
62
+ if (args.verbose) {
63
+ client.verbose = true;
64
+ }
65
+ console.log('Open Broker - Market Order');
66
+ console.log('==========================\n');
67
+ // Check builder fee approval (warning only, don't block)
68
+ await checkBuilderFeeApproval(client);
69
+ try {
70
+ // Get current price
71
+ const mids = await client.getAllMids();
72
+ const midPrice = parseFloat(mids[coin]);
73
+ if (!midPrice) {
74
+ console.error(`Error: No market data for ${coin}`);
75
+ process.exit(1);
76
+ }
77
+ // Calculate order details
78
+ const slippageBps = slippage ?? 50;
79
+ const slippageMultiplier = slippageBps / 10000;
80
+ const limitPrice = isBuy
81
+ ? midPrice * (1 + slippageMultiplier)
82
+ : midPrice * (1 - slippageMultiplier);
83
+ const notional = midPrice * size;
84
+ console.log('Order Details');
85
+ console.log('-------------');
86
+ console.log(`Coin: ${coin}`);
87
+ console.log(`Side: ${isBuy ? 'BUY' : 'SELL'}`);
88
+ console.log(`Size: ${size}`);
89
+ console.log(`Mid Price: ${formatUsd(midPrice)}`);
90
+ console.log(`Limit Price: ${formatUsd(limitPrice)} (${slippageBps} bps slippage)`);
91
+ console.log(`Notional: ~${formatUsd(notional)}`);
92
+ console.log(`Reduce Only: ${reduceOnly ? 'Yes' : 'No'}`);
93
+ if (leverage)
94
+ console.log(`Leverage: ${leverage}x`);
95
+ console.log(`Builder Fee: ${client.builderInfo.f / 10} bps`);
96
+ if (dryRun) {
97
+ console.log('\n🔍 Dry run - order not submitted');
98
+ return;
99
+ }
100
+ console.log('\nExecuting...');
101
+ const response = await client.marketOrder(coin, isBuy, size, slippage, leverage);
102
+ console.log('\nResult');
103
+ console.log('------');
104
+ // Log full response for debugging
105
+ if (args.verbose || process.env.VERBOSE) {
106
+ console.log('\nFull Response:');
107
+ console.log(JSON.stringify(response, null, 2));
108
+ }
109
+ if (response.status === 'ok' && response.response && typeof response.response === 'object') {
110
+ const statuses = response.response.data.statuses;
111
+ for (const status of statuses) {
112
+ if (status.filled) {
113
+ const fillSz = parseFloat(status.filled.totalSz);
114
+ const avgPx = parseFloat(status.filled.avgPx);
115
+ const fillNotional = fillSz * avgPx;
116
+ const slippageActual = isBuy
117
+ ? (avgPx - midPrice) / midPrice
118
+ : (midPrice - avgPx) / midPrice;
119
+ console.log(`✅ Filled`);
120
+ console.log(` Order ID: ${status.filled.oid}`);
121
+ console.log(` Size: ${fillSz}`);
122
+ console.log(` Avg Price: ${formatUsd(avgPx)}`);
123
+ console.log(` Notional: ${formatUsd(fillNotional)}`);
124
+ console.log(` Slippage: ${(slippageActual * 10000).toFixed(1)} bps`);
125
+ }
126
+ else if (status.resting) {
127
+ console.log(`⏳ Resting (partial fill)`);
128
+ console.log(` Order ID: ${status.resting.oid}`);
129
+ }
130
+ else if (status.error) {
131
+ console.log(`❌ Error: ${status.error}`);
132
+ }
133
+ else {
134
+ // Unknown status - show the whole thing
135
+ console.log(`⚠️ Unknown status:`);
136
+ console.log(JSON.stringify(status, null, 2));
137
+ }
138
+ }
139
+ }
140
+ else if (response.status === 'err') {
141
+ console.log(`❌ API Error: ${response.response || JSON.stringify(response)}`);
142
+ }
143
+ else {
144
+ console.log(`❌ Unexpected response:`);
145
+ console.log(JSON.stringify(response, null, 2));
146
+ }
147
+ }
148
+ catch (error) {
149
+ console.error('Error executing order:', error);
150
+ process.exit(1);
151
+ }
152
+ }
153
+ main();
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env npx tsx
2
+ export {};
3
+ //# sourceMappingURL=outcome-order.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"outcome-order.d.ts","sourceRoot":"","sources":["../../scripts/operations/outcome-order.ts"],"names":[],"mappings":""}
@@ -0,0 +1,171 @@
1
+ #!/usr/bin/env npx tsx
2
+ // Execute a HIP-4 outcome order on Hyperliquid
3
+ import { getClient } from '../core/client.js';
4
+ import { checkBuilderFeeApproval, formatUsd, parseArgs } from '../core/utils.js';
5
+ function printUsage() {
6
+ console.log(`
7
+ Open Broker - HIP-4 Outcome Order
8
+ =================================
9
+
10
+ Buy or sell a YES/NO outcome token.
11
+
12
+ Usage:
13
+ openbroker outcome-order --outcome <id|#encoding|+encoding> --outcome-side <yes|no> --side <buy|sell> --size <SIZE>
14
+
15
+ Options:
16
+ --outcome Outcome id, outcome spot coin (#1230), or token name (+1230)
17
+ --outcome-side Outcome side when --outcome is a plain id: yes/no or 0/1 (default: yes)
18
+ --side Trade side: buy or sell
19
+ --size Order size in outcome token units
20
+ --price Limit price between 0.001 and 0.999 (omit for market IOC)
21
+ --tif Time-in-force for limit orders: Gtc, Ioc, Alo (default: Gtc)
22
+ --slippage Slippage tolerance in bps for market orders (default: config, usually 50)
23
+ --sz-decimals Override size decimals if outcome metadata omits token decimals
24
+ --dry Dry run - show order details without executing
25
+ --verbose Show full API request/response for debugging
26
+
27
+ Examples:
28
+ openbroker outcomes --query BTC
29
+ openbroker outcome-order --outcome 123 --outcome-side yes --side buy --size 10 --dry
30
+ openbroker outcome-buy --outcome 123 --outcome-side no --size 5 --price 0.42
31
+ openbroker outcome-sell --outcome #1230 --size 10
32
+ `);
33
+ }
34
+ function formatOutcomePrice(price) {
35
+ return price.toFixed(4);
36
+ }
37
+ async function main() {
38
+ const args = parseArgs(process.argv.slice(2));
39
+ if (args.help || args.h) {
40
+ printUsage();
41
+ process.exit(0);
42
+ }
43
+ const outcomeRef = args.outcome;
44
+ const outcomeSide = args['outcome-side'];
45
+ const side = args.side;
46
+ const size = parseFloat(args.size);
47
+ const price = args.price ? parseFloat(args.price) : undefined;
48
+ const tif = args.tif ?? 'Gtc';
49
+ const slippage = args.slippage ? parseInt(args.slippage) : undefined;
50
+ const szDecimals = args['sz-decimals'] ? parseInt(args['sz-decimals'], 10) : undefined;
51
+ const dryRun = args.dry;
52
+ if (!outcomeRef || !side || isNaN(size)) {
53
+ printUsage();
54
+ process.exit(1);
55
+ }
56
+ if (side !== 'buy' && side !== 'sell') {
57
+ console.error('Error: --side must be "buy" or "sell"');
58
+ process.exit(1);
59
+ }
60
+ if (size <= 0) {
61
+ console.error('Error: --size must be positive');
62
+ process.exit(1);
63
+ }
64
+ if (price !== undefined && (price <= 0 || price >= 1)) {
65
+ console.error('Error: --price must be between 0 and 1 for outcome tokens');
66
+ process.exit(1);
67
+ }
68
+ if (szDecimals !== undefined && (szDecimals < 0 || szDecimals > 8)) {
69
+ console.error('Error: --sz-decimals must be between 0 and 8');
70
+ process.exit(1);
71
+ }
72
+ const client = getClient();
73
+ if (args.verbose)
74
+ client.verbose = true;
75
+ const isBuy = side === 'buy';
76
+ const isMarket = price === undefined;
77
+ console.log('Open Broker - HIP-4 Outcome Order');
78
+ console.log('=================================\n');
79
+ await checkBuilderFeeApproval(client);
80
+ try {
81
+ const resolved = client.resolveOutcomeRef(outcomeRef, outcomeSide);
82
+ const market = await client.getOutcomeMarket(resolved.outcome);
83
+ const marketSide = market?.sides.find((s) => s.side === resolved.side);
84
+ const sideName = marketSide?.name ?? (resolved.side === 0 ? 'Yes' : 'No');
85
+ const midPrice = await client.getOutcomeMidPrice(resolved.outcome, resolved.side);
86
+ const slippageBps = slippage ?? 50;
87
+ const limitPrice = isMarket
88
+ ? (isBuy ? midPrice * (1 + slippageBps / 10000) : midPrice * (1 - slippageBps / 10000))
89
+ : price;
90
+ const notional = midPrice * size;
91
+ console.log('Order Details');
92
+ console.log('-------------');
93
+ console.log(`Outcome: ${resolved.outcome}`);
94
+ console.log(`Market: ${market?.name ?? 'Unknown'}${market?.parsedDescription.underlying ? ` (${market.parsedDescription.underlying})` : ''}`);
95
+ if (market?.parsedDescription.expiry)
96
+ console.log(`Expiry: ${market.parsedDescription.expiry}`);
97
+ if (market?.parsedDescription.targetPrice)
98
+ console.log(`Target: ${market.parsedDescription.targetPrice}`);
99
+ console.log(`Outcome Side: ${sideName.toUpperCase()} (${resolved.side})`);
100
+ console.log(`Coin: ${resolved.coin}`);
101
+ console.log(`Asset ID: ${resolved.assetId}`);
102
+ console.log(`Trade Side: ${isBuy ? 'BUY' : 'SELL'}`);
103
+ console.log(`Size: ${size}`);
104
+ console.log(`Mid Price: ${formatOutcomePrice(midPrice)}`);
105
+ if (isMarket) {
106
+ console.log(`Type: Market (IOC)`);
107
+ console.log(`Limit Price: ${formatOutcomePrice(limitPrice)} (${slippageBps} bps slippage)`);
108
+ }
109
+ else {
110
+ console.log(`Type: Limit (${tif})`);
111
+ console.log(`Limit Price: ${formatOutcomePrice(price)}`);
112
+ }
113
+ console.log(`Notional: ~${formatUsd(notional)}`);
114
+ if (marketSide?.szDecimals !== undefined || szDecimals !== undefined) {
115
+ console.log(`Sz Decimals: ${szDecimals ?? marketSide?.szDecimals}`);
116
+ }
117
+ console.log(`Builder Fee: ${client.builderInfo.f / 10} bps`);
118
+ if (dryRun) {
119
+ console.log('\nDry run - order not submitted');
120
+ return;
121
+ }
122
+ console.log('\nExecuting...');
123
+ const response = isMarket
124
+ ? await client.outcomeMarketOrder(outcomeRef, outcomeSide, isBuy, size, slippage, szDecimals)
125
+ : await client.outcomeLimitOrder(outcomeRef, outcomeSide, isBuy, size, price, tif, szDecimals);
126
+ console.log('\nResult');
127
+ console.log('------');
128
+ if (args.verbose || process.env.VERBOSE) {
129
+ console.log('\nFull Response:');
130
+ console.log(JSON.stringify(response, null, 2));
131
+ }
132
+ if (response.status === 'ok' && response.response && typeof response.response === 'object') {
133
+ const statuses = response.response.data.statuses;
134
+ for (const status of statuses) {
135
+ if (status.filled) {
136
+ const fillSz = parseFloat(status.filled.totalSz);
137
+ const avgPx = parseFloat(status.filled.avgPx);
138
+ console.log('Filled');
139
+ console.log(` Order ID: ${status.filled.oid}`);
140
+ console.log(` Size: ${fillSz}`);
141
+ console.log(` Avg Price: ${formatOutcomePrice(avgPx)}`);
142
+ console.log(` Notional: ${formatUsd(fillSz * avgPx)}`);
143
+ }
144
+ else if (status.resting) {
145
+ console.log('Resting');
146
+ console.log(` Order ID: ${status.resting.oid}`);
147
+ }
148
+ else if (status.error) {
149
+ console.log(`Error: ${status.error}`);
150
+ }
151
+ else {
152
+ console.log('Unknown status:');
153
+ console.log(JSON.stringify(status, null, 2));
154
+ }
155
+ }
156
+ }
157
+ else if (response.status === 'err') {
158
+ console.log(`API Error: ${response.response || JSON.stringify(response)}`);
159
+ }
160
+ else {
161
+ console.log('Unexpected response:');
162
+ console.log(JSON.stringify(response, null, 2));
163
+ }
164
+ }
165
+ catch (error) {
166
+ console.error('Error executing outcome order:', error);
167
+ console.error('Note: Hyperliquid currently documents outcomeMeta as testnet-only.');
168
+ process.exit(1);
169
+ }
170
+ }
171
+ main();
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env npx tsx
2
+ export {};
3
+ //# sourceMappingURL=scale.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scale.d.ts","sourceRoot":"","sources":["../../scripts/operations/scale.ts"],"names":[],"mappings":""}