openbroker 1.3.1 → 1.3.2
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/SKILL.md +7 -4
- package/package.json +1 -1
- package/scripts/core/client.ts +13 -3
- package/scripts/info/all-markets.ts +18 -2
- package/scripts/info/search-markets.ts +18 -2
package/SKILL.md
CHANGED
|
@@ -4,7 +4,7 @@ description: Hyperliquid trading CLI skill for agents. Use when an agent needs t
|
|
|
4
4
|
license: MIT
|
|
5
5
|
compatibility: Requires Node.js 22+, network access to api.hyperliquid.xyz
|
|
6
6
|
homepage: https://www.npmjs.com/package/openbroker
|
|
7
|
-
metadata: {"author": "monemetrics", "version": "1.3.
|
|
7
|
+
metadata: {"author": "monemetrics", "version": "1.3.2"}
|
|
8
8
|
allowed-tools: Bash(openbroker:*)
|
|
9
9
|
---
|
|
10
10
|
|
|
@@ -52,12 +52,15 @@ Common globals:
|
|
|
52
52
|
openbroker search --query GOLD --json
|
|
53
53
|
openbroker search --query BTC --type perp --json
|
|
54
54
|
openbroker all-markets --type hip3 --json
|
|
55
|
+
openbroker all-markets --type outcome --json
|
|
55
56
|
openbroker outcomes --query BTC --json
|
|
56
57
|
```
|
|
57
58
|
|
|
58
59
|
- HIP-3 perps use `dex:COIN`, e.g. `xyz:CL`, not bare `CL`.
|
|
59
60
|
- `assetId` is the canonical identifier for comparisons and persisted agent state; order placement still uses `--coin`.
|
|
60
|
-
- HIP-4
|
|
61
|
+
- For HIP-4 discovery, use `outcomes --json` for grouped market metadata and `all-markets --type outcome --json` for flattened side rows.
|
|
62
|
+
- HIP-4 outcome orders use `--outcome <id|#encoding|+encoding>` plus `--outcome-side yes|no` when the reference is a plain ID. Encoded sides use `encoding = 10 * outcomeId + side`, where side `0` is the first side and side `1` is the second side.
|
|
63
|
+
- HIP-4 order books use `#<encoding>` coins; spot balances may show `+<encoding>` token names.
|
|
61
64
|
- On testnet, HIP-3 metadata may need an explicit prefixed coin such as `dex:COIN`.
|
|
62
65
|
|
|
63
66
|
## CLI command map
|
|
@@ -72,7 +75,7 @@ Most info commands accept `--json`. Use `--coin`, `--top`, and `--address` where
|
|
|
72
75
|
| `positions` | Open perp positions and liquidation distance | `--coin`, `--address` |
|
|
73
76
|
| `funding` | Funding rates | `--coin`, `--top`, `--sort annualized|hourly|oi`, `--all`, `--include-hip3` |
|
|
74
77
|
| `markets` | Perp market data | `--coin`, `--top`, `--sort volume|oi|change`, `--include-hip3` |
|
|
75
|
-
| `all-markets` | Browse every venue type | `--type perp|hip3|spot|outcome|all`, `--top` |
|
|
78
|
+
| `all-markets` | Browse every venue type | `--type perp|hip3|spot|outcome|all`, `--top`, `--json` |
|
|
76
79
|
| `search` | Find markets across providers | `--query`, `--type` |
|
|
77
80
|
| `spot` | Spot markets or balances | `--coin`, `--balances`, `--address`, `--top` |
|
|
78
81
|
| `fills` | Recent fills | `--coin`, `--side buy|sell`, `--top`, `--address` |
|
|
@@ -84,7 +87,7 @@ Most info commands accept `--json`. Use `--coin`, `--top`, and `--address` where
|
|
|
84
87
|
| `trades` | Recent tape | `--coin`, `--top` |
|
|
85
88
|
| `rate-limit` | API usage | — |
|
|
86
89
|
| `funding-scan` | Cross-dex scan | `--threshold`, `--main-only`, `--hip3-only`, `--pairs`, `--watch`, `--interval`, `--top` |
|
|
87
|
-
| `outcomes` | HIP-4 discovery/balances | `--query`, `--outcome`, `--side`, `--balances`, `--top` |
|
|
90
|
+
| `outcomes` | HIP-4 discovery/balances | `--query`, `--outcome`, `--side`, `--balances`, `--top`, `--json` |
|
|
88
91
|
|
|
89
92
|
### Perp trading
|
|
90
93
|
|
package/package.json
CHANGED
package/scripts/core/client.ts
CHANGED
|
@@ -668,9 +668,19 @@ export class HyperliquidClient {
|
|
|
668
668
|
private parseOutcomeDescription(description: string): Record<string, string> {
|
|
669
669
|
const parsed: Record<string, string> = {};
|
|
670
670
|
for (const part of description.split('|')) {
|
|
671
|
-
const
|
|
672
|
-
|
|
673
|
-
|
|
671
|
+
const rawSegment = part.trim();
|
|
672
|
+
const metadataIdx = rawSegment.indexOf('metadata=');
|
|
673
|
+
const segments = metadataIdx >= 0
|
|
674
|
+
? [rawSegment, rawSegment.slice(metadataIdx + 'metadata='.length)]
|
|
675
|
+
: [rawSegment];
|
|
676
|
+
|
|
677
|
+
for (const segment of segments) {
|
|
678
|
+
const idx = segment.indexOf(':');
|
|
679
|
+
if (idx <= 0) continue;
|
|
680
|
+
const key = segment.slice(0, idx).trim();
|
|
681
|
+
if (!/^[A-Za-z][A-Za-z0-9_]*$/.test(key)) continue;
|
|
682
|
+
parsed[key] = segment.slice(idx + 1).trim();
|
|
683
|
+
}
|
|
674
684
|
}
|
|
675
685
|
return parsed;
|
|
676
686
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env tsx
|
|
2
|
-
// All Markets - View all available markets across perps, spot, and HIP-
|
|
2
|
+
// All Markets - View all available markets across perps, HIP-3, spot, and HIP-4 outcomes
|
|
3
3
|
|
|
4
4
|
import { getClient } from '../core/client.js';
|
|
5
5
|
|
|
@@ -88,9 +88,22 @@ interface MarketRow {
|
|
|
88
88
|
maxLeverage?: number;
|
|
89
89
|
outcome?: number;
|
|
90
90
|
outcomeSide?: string;
|
|
91
|
+
outcomeName?: string;
|
|
92
|
+
tokenName?: string;
|
|
93
|
+
parsedDescription?: Record<string, string>;
|
|
91
94
|
description?: string;
|
|
92
95
|
}
|
|
93
96
|
|
|
97
|
+
function handleMarketFetchError(kind: NonNullable<Args['type']>, error: unknown, requestedType: Args['type'], verbose?: boolean): void {
|
|
98
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
99
|
+
if (requestedType === kind) {
|
|
100
|
+
throw new Error(`Failed to fetch ${kind} markets: ${message}`);
|
|
101
|
+
}
|
|
102
|
+
if (verbose) {
|
|
103
|
+
console.error(`Failed to fetch ${kind} markets:`, error);
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
|
|
94
107
|
async function main() {
|
|
95
108
|
const args = parseArgs();
|
|
96
109
|
const client = getClient();
|
|
@@ -202,12 +215,15 @@ async function main() {
|
|
|
202
215
|
volume24h: parseFloat(side.dayNtlVlm || '0'),
|
|
203
216
|
outcome: market.outcome,
|
|
204
217
|
outcomeSide: side.name,
|
|
218
|
+
outcomeName: market.name,
|
|
219
|
+
tokenName: side.tokenName,
|
|
220
|
+
parsedDescription: market.parsedDescription,
|
|
205
221
|
description: market.description,
|
|
206
222
|
});
|
|
207
223
|
}
|
|
208
224
|
}
|
|
209
225
|
} catch (e) {
|
|
210
|
-
|
|
226
|
+
handleMarketFetchError('outcome', e, args.type, args.verbose);
|
|
211
227
|
}
|
|
212
228
|
}
|
|
213
229
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env tsx
|
|
2
|
-
// Search Markets - Find specific assets across all providers (perps, HIP-3, spot)
|
|
2
|
+
// Search Markets - Find specific assets across all providers (perps, HIP-3, spot, HIP-4)
|
|
3
3
|
|
|
4
4
|
import { getClient } from '../core/client.js';
|
|
5
5
|
|
|
@@ -85,6 +85,16 @@ function formatFunding(rate: string): string {
|
|
|
85
85
|
return `${sign}${annualized.toFixed(2)}%`;
|
|
86
86
|
}
|
|
87
87
|
|
|
88
|
+
function handleMarketFetchError(kind: NonNullable<Args['type']>, error: unknown, requestedType: Args['type'], verbose?: boolean): void {
|
|
89
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
90
|
+
if (requestedType === kind) {
|
|
91
|
+
throw new Error(`Failed to fetch ${kind} markets: ${message}`);
|
|
92
|
+
}
|
|
93
|
+
if (verbose) {
|
|
94
|
+
console.error(`Failed to fetch ${kind} markets:`, error);
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
|
|
88
98
|
async function main() {
|
|
89
99
|
const args = parseArgs();
|
|
90
100
|
const client = getClient();
|
|
@@ -107,6 +117,9 @@ async function main() {
|
|
|
107
117
|
openInterest?: string;
|
|
108
118
|
outcome?: number;
|
|
109
119
|
outcomeSide?: string;
|
|
120
|
+
outcomeName?: string;
|
|
121
|
+
tokenName?: string;
|
|
122
|
+
parsedDescription?: Record<string, string>;
|
|
110
123
|
description?: string;
|
|
111
124
|
}
|
|
112
125
|
|
|
@@ -247,12 +260,15 @@ async function main() {
|
|
|
247
260
|
volume24h: parseFloat(side.dayNtlVlm || '0'),
|
|
248
261
|
outcome: market.outcome,
|
|
249
262
|
outcomeSide: side.name,
|
|
263
|
+
outcomeName: market.name,
|
|
264
|
+
tokenName: side.tokenName,
|
|
265
|
+
parsedDescription: market.parsedDescription,
|
|
250
266
|
description: market.description,
|
|
251
267
|
});
|
|
252
268
|
}
|
|
253
269
|
}
|
|
254
270
|
} catch (e) {
|
|
255
|
-
|
|
271
|
+
handleMarketFetchError('outcome', e, args.type, args.verbose);
|
|
256
272
|
}
|
|
257
273
|
}
|
|
258
274
|
|