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.
- package/CHANGELOG.md +12 -0
- package/dist/auto/audit.d.ts +57 -0
- package/dist/auto/audit.d.ts.map +1 -0
- package/dist/auto/audit.js +407 -0
- package/dist/auto/cli.d.ts +2 -0
- package/dist/auto/cli.d.ts.map +1 -0
- package/dist/auto/cli.js +423 -0
- package/dist/auto/events.d.ts +11 -0
- package/dist/auto/events.d.ts.map +1 -0
- package/dist/auto/events.js +36 -0
- package/dist/auto/examples/dca.d.ts +4 -0
- package/dist/auto/examples/dca.d.ts.map +1 -0
- package/dist/auto/examples/dca.js +60 -0
- package/dist/auto/examples/funding-arb.d.ts +4 -0
- package/dist/auto/examples/funding-arb.d.ts.map +1 -0
- package/dist/auto/examples/funding-arb.js +81 -0
- package/dist/auto/examples/grid.d.ts +4 -0
- package/dist/auto/examples/grid.d.ts.map +1 -0
- package/dist/auto/examples/grid.js +114 -0
- package/dist/auto/examples/mm-maker.d.ts +4 -0
- package/dist/auto/examples/mm-maker.d.ts.map +1 -0
- package/dist/auto/examples/mm-maker.js +131 -0
- package/dist/auto/examples/mm-spread.d.ts +4 -0
- package/dist/auto/examples/mm-spread.d.ts.map +1 -0
- package/dist/auto/examples/mm-spread.js +119 -0
- package/dist/auto/examples/price-alert.d.ts +4 -0
- package/dist/auto/examples/price-alert.d.ts.map +1 -0
- package/dist/auto/examples/price-alert.js +85 -0
- package/dist/auto/keep-awake.d.ts +11 -0
- package/dist/auto/keep-awake.d.ts.map +1 -0
- package/dist/auto/keep-awake.js +70 -0
- package/dist/auto/loader.d.ts +22 -0
- package/dist/auto/loader.d.ts.map +1 -0
- package/dist/auto/loader.js +127 -0
- package/dist/auto/prune.d.ts +40 -0
- package/dist/auto/prune.d.ts.map +1 -0
- package/dist/auto/prune.js +204 -0
- package/dist/auto/registry.d.ts +24 -0
- package/dist/auto/registry.d.ts.map +1 -0
- package/dist/auto/registry.js +93 -0
- package/dist/auto/report.d.ts +3 -0
- package/dist/auto/report.d.ts.map +1 -0
- package/dist/auto/report.js +385 -0
- package/dist/auto/runtime.d.ts +33 -0
- package/dist/auto/runtime.d.ts.map +1 -0
- package/dist/auto/runtime.js +844 -0
- package/dist/auto/types.d.ts +236 -0
- package/dist/auto/types.d.ts.map +1 -0
- package/dist/auto/types.js +3 -0
- package/dist/core/client.d.ts +684 -0
- package/dist/core/client.d.ts.map +1 -0
- package/dist/core/client.js +2040 -0
- package/dist/core/config.d.ts +22 -0
- package/dist/core/config.d.ts.map +1 -0
- package/dist/core/config.js +143 -0
- package/dist/core/types.d.ts +221 -0
- package/dist/core/types.d.ts.map +1 -0
- package/dist/core/types.js +2 -0
- package/dist/core/utils.d.ts +61 -0
- package/dist/core/utils.d.ts.map +1 -0
- package/dist/core/utils.js +142 -0
- package/dist/core/ws.d.ts +121 -0
- package/dist/core/ws.d.ts.map +1 -0
- package/dist/core/ws.js +222 -0
- package/dist/info/account.d.ts +3 -0
- package/dist/info/account.d.ts.map +1 -0
- package/dist/info/account.js +198 -0
- package/dist/info/all-markets.d.ts +3 -0
- package/dist/info/all-markets.d.ts.map +1 -0
- package/dist/info/all-markets.js +272 -0
- package/dist/info/candles.d.ts +3 -0
- package/dist/info/candles.d.ts.map +1 -0
- package/dist/info/candles.js +120 -0
- package/dist/info/fees.d.ts +3 -0
- package/dist/info/fees.d.ts.map +1 -0
- package/dist/info/fees.js +87 -0
- package/dist/info/fills.d.ts +3 -0
- package/dist/info/fills.d.ts.map +1 -0
- package/dist/info/fills.js +105 -0
- package/dist/info/funding-history.d.ts +3 -0
- package/dist/info/funding-history.d.ts.map +1 -0
- package/dist/info/funding-history.js +98 -0
- package/dist/info/funding-scan.d.ts +3 -0
- package/dist/info/funding-scan.d.ts.map +1 -0
- package/dist/info/funding-scan.js +178 -0
- package/dist/info/funding.d.ts +3 -0
- package/dist/info/funding.d.ts.map +1 -0
- package/dist/info/funding.js +158 -0
- package/dist/info/markets.d.ts +3 -0
- package/dist/info/markets.d.ts.map +1 -0
- package/dist/info/markets.js +178 -0
- package/dist/info/order-status.d.ts +3 -0
- package/dist/info/order-status.d.ts.map +1 -0
- package/dist/info/order-status.js +85 -0
- package/dist/info/orders.d.ts +3 -0
- package/dist/info/orders.d.ts.map +1 -0
- package/dist/info/orders.js +162 -0
- package/dist/info/outcomes.d.ts +3 -0
- package/dist/info/outcomes.d.ts.map +1 -0
- package/dist/info/outcomes.js +175 -0
- package/dist/info/positions.d.ts +3 -0
- package/dist/info/positions.d.ts.map +1 -0
- package/dist/info/positions.js +127 -0
- package/dist/info/rate-limit.d.ts +3 -0
- package/dist/info/rate-limit.d.ts.map +1 -0
- package/dist/info/rate-limit.js +58 -0
- package/dist/info/search-markets.d.ts +3 -0
- package/dist/info/search-markets.d.ts.map +1 -0
- package/dist/info/search-markets.js +296 -0
- package/dist/info/spot.d.ts +3 -0
- package/dist/info/spot.d.ts.map +1 -0
- package/dist/info/spot.js +192 -0
- package/dist/info/trades.d.ts +3 -0
- package/dist/info/trades.d.ts.map +1 -0
- package/dist/info/trades.js +97 -0
- package/dist/lib.d.ts +14 -0
- package/dist/lib.d.ts.map +1 -0
- package/dist/lib.js +17 -0
- package/dist/operations/bracket.d.ts +28 -0
- package/dist/operations/bracket.d.ts.map +1 -0
- package/dist/operations/bracket.js +266 -0
- package/dist/operations/cancel.d.ts +3 -0
- package/dist/operations/cancel.d.ts.map +1 -0
- package/dist/operations/cancel.js +107 -0
- package/dist/operations/chase.d.ts +25 -0
- package/dist/operations/chase.d.ts.map +1 -0
- package/dist/operations/chase.js +215 -0
- package/dist/operations/limit-order.d.ts +3 -0
- package/dist/operations/limit-order.d.ts.map +1 -0
- package/dist/operations/limit-order.js +144 -0
- package/dist/operations/market-order.d.ts +3 -0
- package/dist/operations/market-order.d.ts.map +1 -0
- package/dist/operations/market-order.js +153 -0
- package/dist/operations/outcome-order.d.ts +3 -0
- package/dist/operations/outcome-order.d.ts.map +1 -0
- package/dist/operations/outcome-order.js +171 -0
- package/dist/operations/scale.d.ts +3 -0
- package/dist/operations/scale.d.ts.map +1 -0
- package/dist/operations/scale.js +212 -0
- package/dist/operations/set-tpsl.d.ts +3 -0
- package/dist/operations/set-tpsl.d.ts.map +1 -0
- package/dist/operations/set-tpsl.js +277 -0
- package/dist/operations/spot-order.d.ts +3 -0
- package/dist/operations/spot-order.d.ts.map +1 -0
- package/dist/operations/spot-order.js +173 -0
- package/dist/operations/trigger-order.d.ts +3 -0
- package/dist/operations/trigger-order.d.ts.map +1 -0
- package/dist/operations/trigger-order.js +177 -0
- package/dist/operations/twap-cancel.d.ts +3 -0
- package/dist/operations/twap-cancel.d.ts.map +1 -0
- package/dist/operations/twap-cancel.js +57 -0
- package/dist/operations/twap-status.d.ts +3 -0
- package/dist/operations/twap-status.d.ts.map +1 -0
- package/dist/operations/twap-status.js +81 -0
- package/dist/operations/twap.d.ts +3 -0
- package/dist/operations/twap.d.ts.map +1 -0
- package/dist/operations/twap.js +124 -0
- package/dist/setup/approve-builder.d.ts +3 -0
- package/dist/setup/approve-builder.d.ts.map +1 -0
- package/dist/setup/approve-builder.js +155 -0
- package/dist/setup/env.d.ts +4 -0
- package/dist/setup/env.d.ts.map +1 -0
- package/dist/setup/env.js +8 -0
- package/dist/setup/onboard.d.ts +10 -0
- package/dist/setup/onboard.d.ts.map +1 -0
- package/dist/setup/onboard.js +462 -0
- package/package.json +10 -4
|
@@ -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 @@
|
|
|
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 @@
|
|
|
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 @@
|
|
|
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 @@
|
|
|
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 @@
|
|
|
1
|
+
{"version":3,"file":"search-markets.d.ts","sourceRoot":"","sources":["../../scripts/info/search-markets.ts"],"names":[],"mappings":""}
|