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