openbroker 1.10.0 → 1.12.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 (52) hide show
  1. package/CHANGELOG.md +16 -0
  2. package/README.md +52 -0
  3. package/SKILL.md +45 -2
  4. package/bin/cli.ts +11 -0
  5. package/dist/auto/examples/grid.js +1 -1
  6. package/dist/auto/examples/mm-maker.js +4 -4
  7. package/dist/auto/examples/mm-spread.js +4 -4
  8. package/dist/core/client.d.ts +23 -26
  9. package/dist/core/client.d.ts.map +1 -1
  10. package/dist/core/client.js +24 -3
  11. package/dist/core/types.d.ts +22 -0
  12. package/dist/core/types.d.ts.map +1 -1
  13. package/dist/core/ws.d.ts +5 -0
  14. package/dist/core/ws.d.ts.map +1 -1
  15. package/dist/core/ws.js +9 -7
  16. package/dist/guardian/cli.d.ts +2 -0
  17. package/dist/guardian/cli.d.ts.map +1 -0
  18. package/dist/guardian/cli.js +288 -0
  19. package/dist/guardian/engine.d.ts +107 -0
  20. package/dist/guardian/engine.d.ts.map +1 -0
  21. package/dist/guardian/engine.js +526 -0
  22. package/dist/guardian/rules.d.ts +35 -0
  23. package/dist/guardian/rules.d.ts.map +1 -0
  24. package/dist/guardian/rules.js +237 -0
  25. package/dist/guardian/telegram.d.ts +24 -0
  26. package/dist/guardian/telegram.d.ts.map +1 -0
  27. package/dist/guardian/telegram.js +125 -0
  28. package/dist/guardian/types.d.ts +90 -0
  29. package/dist/guardian/types.d.ts.map +1 -0
  30. package/dist/guardian/types.js +45 -0
  31. package/dist/lib.d.ts +8 -0
  32. package/dist/lib.d.ts.map +1 -1
  33. package/dist/lib.js +5 -0
  34. package/dist/operations/cancel.js +4 -1
  35. package/dist/operations/chase.d.ts +3 -1
  36. package/dist/operations/chase.d.ts.map +1 -1
  37. package/dist/operations/chase.js +4 -2
  38. package/package.json +2 -2
  39. package/scripts/auto/examples/grid.ts +1 -1
  40. package/scripts/auto/examples/mm-maker.ts +4 -4
  41. package/scripts/auto/examples/mm-spread.ts +4 -4
  42. package/scripts/core/client.ts +29 -3
  43. package/scripts/core/types.ts +23 -0
  44. package/scripts/core/ws.ts +9 -6
  45. package/scripts/guardian/cli.ts +322 -0
  46. package/scripts/guardian/engine.ts +614 -0
  47. package/scripts/guardian/rules.ts +265 -0
  48. package/scripts/guardian/telegram.ts +147 -0
  49. package/scripts/guardian/types.ts +160 -0
  50. package/scripts/lib.ts +33 -0
  51. package/scripts/operations/cancel.ts +4 -1
  52. package/scripts/operations/chase.ts +5 -3
@@ -0,0 +1,288 @@
1
+ // CLI entry point for `openbroker guardian` — read-only position risk
2
+ // monitoring with Telegram / agent-hook delivery. The CLI counterpart of the
3
+ // hosted guardian at /markets/guardian.
4
+ import { parseArgs } from '../core/utils.js';
5
+ import { getClient } from '../core/client.js';
6
+ import { getConfigPath } from '../core/config.js';
7
+ import { startGuardian } from './engine.js';
8
+ import { generateLinkCode, getTelegramBotInfo, loadTelegramSettings, saveEnvVar, sendTelegramMessage, waitForTelegramLink, } from './telegram.js';
9
+ import { GUARDIAN_RULE_IDS, GUARDIAN_RULE_LABELS, } from './types.js';
10
+ function printUsage() {
11
+ console.log(`
12
+ OpenBroker Guardian — read-only position risk monitoring
13
+
14
+ Watches Hyperliquid addresses for liquidation risk, missing TP/SL, funding
15
+ bleed and more. Never touches your keys or places orders. Alerts go to the
16
+ console and (once connected) Telegram; if an OpenClaw agent gateway is
17
+ configured, alerts also wake the agent.
18
+
19
+ Usage:
20
+ openbroker guardian run [options] Start watching (long-running)
21
+ openbroker guardian connect Link a Telegram chat for alerts
22
+ openbroker guardian test Send a test Telegram message
23
+ openbroker guardian status Show guardian configuration
24
+ openbroker guardian rules List alert rules
25
+
26
+ Options (for run):
27
+ --address <0x..[,0x..]> Address(es) to watch (default: configured account)
28
+ --min-severity <level> info | warning | critical (default: info)
29
+ --disable <rules> CSV of rules to turn off (see: guardian rules)
30
+ --only <rules> CSV of rules to run exclusively
31
+ --poll <ms> Position poll interval (default: 30000; 15000 near liquidation)
32
+ --orders-poll <ms> Open-orders poll interval (default: 120000)
33
+ --liq-warn <pct> Liq-distance warning threshold (default: 10)
34
+ --liq-critical <pct> Liq-distance critical threshold (default: 5)
35
+ --margin-pct <pct> Margin-usage warning threshold (default: 80)
36
+ --funding-apr <pct> Funding-bleed APR threshold (default: 15)
37
+ --tpsl-minutes <min> Minutes unprotected before no-TP/SL alert (default: 15)
38
+ --stale-hours <h> Hours resting before stale-order alert (default: 12)
39
+ --no-telegram Don't deliver to Telegram even if linked
40
+ --no-ws Disable the WebSocket liquidation fast lane
41
+ --json Print alerts as JSON lines (agent-friendly)
42
+ --verbose Show debug output
43
+
44
+ Telegram setup (one-time):
45
+ 1. Message @BotFather on Telegram, send /newbot, and copy the bot token
46
+ 2. Put it in your config: TELEGRAM_BOT_TOKEN=123456:ABC-...
47
+ 3. Run: openbroker guardian connect (then tap the printed link)
48
+
49
+ Examples:
50
+ openbroker guardian run
51
+ openbroker guardian run --address 0xabc...,0xdef... --min-severity warning
52
+ openbroker guardian run --disable position_lifecycle,stale_order
53
+ openbroker guardian run --json --no-telegram
54
+ `);
55
+ }
56
+ const SEVERITIES = ['info', 'warning', 'critical'];
57
+ function parseRuleCsv(raw, flag) {
58
+ const rules = raw.split(',').map((r) => r.trim()).filter(Boolean);
59
+ for (const rule of rules) {
60
+ if (!GUARDIAN_RULE_IDS.includes(rule)) {
61
+ console.error(`Error: unknown rule '${rule}' in ${flag}. Valid rules: ${GUARDIAN_RULE_IDS.join(', ')}`);
62
+ process.exit(1);
63
+ }
64
+ }
65
+ return rules;
66
+ }
67
+ function parseNum(args, key) {
68
+ const raw = args[key];
69
+ if (raw === undefined || raw === true)
70
+ return undefined;
71
+ const n = Number(raw);
72
+ if (!Number.isFinite(n) || n <= 0) {
73
+ console.error(`Error: --${key} must be a positive number`);
74
+ process.exit(1);
75
+ }
76
+ return n;
77
+ }
78
+ async function runCommand(args) {
79
+ const addresses = typeof args.address === 'string'
80
+ ? args.address.split(',').map((a) => a.trim()).filter(Boolean)
81
+ : undefined;
82
+ const prefs = {};
83
+ if (typeof args['min-severity'] === 'string') {
84
+ const sev = args['min-severity'];
85
+ if (!SEVERITIES.includes(sev)) {
86
+ console.error(`Error: --min-severity must be one of: ${SEVERITIES.join(', ')}`);
87
+ process.exit(1);
88
+ }
89
+ prefs.minSeverity = sev;
90
+ }
91
+ if (typeof args.disable === 'string') {
92
+ prefs.rules = Object.fromEntries(parseRuleCsv(args.disable, '--disable').map((r) => [r, false]));
93
+ }
94
+ if (typeof args.only === 'string') {
95
+ const only = new Set(parseRuleCsv(args.only, '--only'));
96
+ prefs.rules = Object.fromEntries(GUARDIAN_RULE_IDS.map((r) => [r, only.has(r)]));
97
+ }
98
+ const thresholds = {};
99
+ const liqWarn = parseNum(args, 'liq-warn');
100
+ const liqCritical = parseNum(args, 'liq-critical');
101
+ if (liqWarn !== undefined || liqCritical !== undefined) {
102
+ const warn = (liqWarn ?? 10) / 100;
103
+ const crit = (liqCritical ?? 5) / 100;
104
+ thresholds.liqThresholds = [
105
+ { pct: warn, severity: 'warning' },
106
+ { pct: crit, severity: 'critical' },
107
+ { pct: crit / 2.5, severity: 'critical' },
108
+ ];
109
+ }
110
+ const marginPct = parseNum(args, 'margin-pct');
111
+ if (marginPct !== undefined) {
112
+ thresholds.marginThresholdPct = marginPct;
113
+ thresholds.marginRearmPct = marginPct * 0.9;
114
+ }
115
+ const fundingApr = parseNum(args, 'funding-apr');
116
+ if (fundingApr !== undefined)
117
+ thresholds.fundingBleedAprPct = fundingApr;
118
+ const tpslMinutes = parseNum(args, 'tpsl-minutes');
119
+ if (tpslMinutes !== undefined)
120
+ thresholds.noTpslAfterMs = tpslMinutes * 60_000;
121
+ const staleHours = parseNum(args, 'stale-hours');
122
+ if (staleHours !== undefined)
123
+ thresholds.staleOrderAgeMs = staleHours * 3600_000;
124
+ const options = {
125
+ addresses,
126
+ prefs,
127
+ thresholds,
128
+ pollIntervalMs: parseNum(args, 'poll'),
129
+ ordersIntervalMs: parseNum(args, 'orders-poll'),
130
+ useWebSocket: args['no-ws'] !== true,
131
+ telegram: args['no-telegram'] === true ? false : undefined,
132
+ json: args.json === true,
133
+ verbose: args.verbose === true,
134
+ };
135
+ const guardian = await startGuardian(options);
136
+ const stats = guardian.getStats();
137
+ const disabled = GUARDIAN_RULE_IDS.filter((r) => prefs.rules?.[r] === false);
138
+ if (!options.json) {
139
+ console.log('OpenBroker Guardian — watching (read-only, Ctrl+C to stop)');
140
+ console.log(` Addresses: ${stats.addresses.join(', ')}`);
141
+ console.log(` Min severity: ${prefs.minSeverity ?? 'info'}`);
142
+ console.log(` Rules off: ${disabled.length > 0 ? disabled.join(', ') : 'none'}`);
143
+ console.log(` Channels: ${stats.channels.join(', ')}`);
144
+ if (!stats.channels.includes('telegram')) {
145
+ console.log(' Tip: run `openbroker guardian connect` to get alerts in Telegram.');
146
+ }
147
+ console.log('');
148
+ for (const target of guardian.getTargets()) {
149
+ const positions = [...target.positions.values()];
150
+ if (positions.length === 0) {
151
+ console.log(` ${target.address}: no open positions`);
152
+ continue;
153
+ }
154
+ console.log(` ${target.address}: equity $${target.equity.toFixed(2)}, margin ${target.marginUsedPct.toFixed(1)}%`);
155
+ for (const pos of positions) {
156
+ const liq = pos.liquidationPx !== null ? `liq $${pos.liquidationPx}` : 'no liq px';
157
+ console.log(` ${pos.side} ${Math.abs(pos.szi)} ${pos.coin} @ $${pos.entryPx ?? '?'} (${pos.leverage}x, ${liq}, uPnL $${pos.unrealizedPnl.toFixed(2)})`);
158
+ }
159
+ }
160
+ console.log('');
161
+ }
162
+ const shutdown = async () => {
163
+ if (!options.json)
164
+ console.log('\nStopping guardian...');
165
+ await guardian.stop();
166
+ process.exit(0);
167
+ };
168
+ process.on('SIGINT', shutdown);
169
+ process.on('SIGTERM', shutdown);
170
+ await new Promise(() => { });
171
+ }
172
+ async function connectCommand(args) {
173
+ const settings = loadTelegramSettings();
174
+ const token = typeof args.token === 'string' ? args.token : settings.token;
175
+ if (!token) {
176
+ console.log('No Telegram bot token configured.\n');
177
+ console.log('One-time setup:');
178
+ console.log(' 1. Open Telegram and message @BotFather');
179
+ console.log(' 2. Send /newbot and follow the prompts (any name, e.g. "my-guardian-bot")');
180
+ console.log(' 3. Copy the bot token BotFather gives you');
181
+ console.log(` 4. Add it to your config (${getConfigPath()}):`);
182
+ console.log(' TELEGRAM_BOT_TOKEN=123456789:AAF...');
183
+ console.log(' 5. Re-run: openbroker guardian connect');
184
+ process.exit(1);
185
+ }
186
+ let bot;
187
+ try {
188
+ bot = await getTelegramBotInfo(token);
189
+ }
190
+ catch (err) {
191
+ console.error(`Could not reach the Telegram bot: ${err instanceof Error ? err.message : String(err)}`);
192
+ console.error('Check TELEGRAM_BOT_TOKEN.');
193
+ process.exit(1);
194
+ }
195
+ const code = generateLinkCode();
196
+ console.log(`Bot: @${bot.username}`);
197
+ console.log('\nOpen this link in Telegram and tap START (or send the code to the bot):\n');
198
+ console.log(` https://t.me/${bot.username}?start=${code}`);
199
+ console.log(`\n code: ${code}`);
200
+ console.log('\nWaiting for the link (10 min timeout, Ctrl+C to abort)...');
201
+ const chatId = await waitForTelegramLink(token, code);
202
+ if (chatId === null) {
203
+ console.error('\nTimed out waiting for the Telegram link. Re-run: openbroker guardian connect');
204
+ process.exit(1);
205
+ }
206
+ const savedTo = saveEnvVar('TELEGRAM_CHAT_ID', String(chatId));
207
+ if (typeof args.token === 'string')
208
+ saveEnvVar('TELEGRAM_BOT_TOKEN', args.token);
209
+ console.log(`\nLinked chat ${chatId} — saved TELEGRAM_CHAT_ID to ${savedTo}`);
210
+ console.log('Guardian alerts will now be delivered to Telegram. Try: openbroker guardian test');
211
+ }
212
+ async function testCommand() {
213
+ const { token, chatId } = loadTelegramSettings();
214
+ if (!token || !chatId) {
215
+ console.error('Telegram not connected. Run: openbroker guardian connect');
216
+ process.exit(1);
217
+ }
218
+ await sendTelegramMessage(token, chatId, '<b>[TEST]</b> OpenBroker guardian is connected. Risk alerts will arrive here.');
219
+ console.log('Test message sent.');
220
+ }
221
+ async function statusCommand() {
222
+ const { token, chatId } = loadTelegramSettings();
223
+ let address = 'not configured';
224
+ try {
225
+ address = getClient().address;
226
+ }
227
+ catch { /* read-only mode without an address */ }
228
+ console.log('OpenBroker Guardian — status\n');
229
+ console.log(` Default address: ${address}`);
230
+ console.log(` Config file: ${getConfigPath()}`);
231
+ console.log(` Telegram token: ${token ? 'set' : 'NOT SET (see: openbroker guardian connect)'}`);
232
+ console.log(` Telegram chat: ${chatId ? `linked (${chatId})` : 'not linked'}`);
233
+ console.log(` Agent hook: ${process.env.OPENCLAW_HOOKS_TOKEN ? 'configured' : 'not configured'}`);
234
+ console.log('\nRules (all on by default):');
235
+ for (const rule of GUARDIAN_RULE_IDS) {
236
+ console.log(` ${rule.padEnd(20)} ${GUARDIAN_RULE_LABELS[rule]}`);
237
+ }
238
+ }
239
+ function rulesCommand() {
240
+ console.log('Guardian alert rules:\n');
241
+ const details = {
242
+ liq_proximity: 'warning at 10% from liquidation price, critical at 5% and 2% (--liq-warn/--liq-critical)',
243
+ no_tpsl: 'info when a position is open 15+ min with no reduce-only trigger orders (--tpsl-minutes)',
244
+ stale_order: 'info for limit orders resting 12h+ and 3%+ from mid (--stale-hours)',
245
+ margin_usage: 'warning when margin used exceeds 80% of equity (--margin-pct)',
246
+ funding_bleed: 'warning when paying 15%+ APR funding for 60+ min (--funding-apr)',
247
+ position_lifecycle: 'info on position open / close / resize',
248
+ };
249
+ for (const rule of GUARDIAN_RULE_IDS) {
250
+ console.log(` ${rule.padEnd(20)} ${GUARDIAN_RULE_LABELS[rule]}`);
251
+ console.log(` ${''.padEnd(20)} ${details[rule]}\n`);
252
+ }
253
+ console.log('Disable rules with --disable <csv>, or run a subset with --only <csv>.');
254
+ }
255
+ async function main() {
256
+ const rawArgs = process.argv.slice(2);
257
+ if (rawArgs.length === 0 || rawArgs[0] === '--help' || rawArgs[0] === '-h') {
258
+ printUsage();
259
+ process.exit(0);
260
+ }
261
+ const subcommand = rawArgs[0];
262
+ const args = parseArgs(rawArgs.slice(1));
263
+ switch (subcommand) {
264
+ case 'run':
265
+ await runCommand(args);
266
+ break;
267
+ case 'connect':
268
+ await connectCommand(args);
269
+ break;
270
+ case 'test':
271
+ await testCommand();
272
+ break;
273
+ case 'status':
274
+ await statusCommand();
275
+ break;
276
+ case 'rules':
277
+ rulesCommand();
278
+ break;
279
+ default:
280
+ console.error(`Unknown subcommand: ${subcommand}`);
281
+ console.log('Run "openbroker guardian --help" for usage');
282
+ process.exit(1);
283
+ }
284
+ }
285
+ main().catch((err) => {
286
+ console.error(err instanceof Error ? err.message : err);
287
+ process.exit(1);
288
+ });
@@ -0,0 +1,107 @@
1
+ import { type HyperliquidClient } from '../core/client.js';
2
+ import type { GuardianAlert, GuardianPrefs, GuardianTargetState, GuardianThresholds } from './types.js';
3
+ export interface GuardianTelegramChannel {
4
+ token: string;
5
+ chatId: string;
6
+ }
7
+ export interface GuardianAgentHookChannel {
8
+ hooksToken: string;
9
+ gatewayPort?: number;
10
+ }
11
+ export interface GuardianOptions {
12
+ /** Addresses to watch. Default: the configured account address. */
13
+ addresses?: string[];
14
+ /** Min severity + per-rule opt-out (same contract as the hosted guardian). */
15
+ prefs?: GuardianPrefs;
16
+ /** Rule threshold overrides. */
17
+ thresholds?: Partial<GuardianThresholds>;
18
+ /** clearinghouseState cadence (ms). Default 30s; drops to 15s near liquidation. */
19
+ pollIntervalMs?: number;
20
+ /** frontendOpenOrders cadence (ms). Default 120s. */
21
+ ordersIntervalMs?: number;
22
+ /** Price (mids + main-dex ctxs) cadence (ms). Default 30s. */
23
+ pricesIntervalMs?: number;
24
+ /** HIP-3 mark/funding cadence (ms), fetched only while HIP-3 positions exist. Default 5m. */
25
+ hip3PricesIntervalMs?: number;
26
+ /** Rule-engine tick (ms), pure in-memory. Default 5s. */
27
+ riskIntervalMs?: number;
28
+ /**
29
+ * Subscribe WS userEvents for instant liquidation alerts and fill-triggered
30
+ * re-polls. Only active when exactly one address is watched (the feed is not
31
+ * tagged per user). Default true.
32
+ */
33
+ useWebSocket?: boolean;
34
+ /** Telegram channel. Default: from TELEGRAM_BOT_TOKEN/TELEGRAM_CHAT_ID env. Pass false to disable. */
35
+ telegram?: GuardianTelegramChannel | false;
36
+ /** OpenClaw agent hook channel. Default: from OPENCLAW_HOOKS_TOKEN/OPENCLAW_GATEWAY_PORT env. Pass false to disable. */
37
+ agentHook?: GuardianAgentHookChannel | false;
38
+ /** Print alerts as JSON lines instead of human-readable text. */
39
+ json?: boolean;
40
+ /** Suppress console alert output entirely (library consumers). */
41
+ quiet?: boolean;
42
+ verbose?: boolean;
43
+ /** Callback fired for every alert that passes prefs. */
44
+ onAlert?: (alert: GuardianAlert) => void;
45
+ /** Injectable client (tests / plugin). Default getClient(). */
46
+ client?: HyperliquidClient;
47
+ }
48
+ export interface GuardianStats {
49
+ addresses: string[];
50
+ statePolls: number;
51
+ orderPolls: number;
52
+ alertsFired: number;
53
+ alertsDelivered: number;
54
+ deliveryErrors: number;
55
+ evaluations: number;
56
+ pricesAt: number | null;
57
+ channels: string[];
58
+ }
59
+ export interface GuardianHandle {
60
+ stop(): Promise<void>;
61
+ getStats(): GuardianStats;
62
+ getTargets(): GuardianTargetState[];
63
+ }
64
+ export declare class Guardian {
65
+ private readonly client;
66
+ private readonly targets;
67
+ private readonly prices;
68
+ private readonly risk;
69
+ private readonly prefs;
70
+ private readonly telegram;
71
+ private readonly agentHook;
72
+ private readonly opts;
73
+ private timers;
74
+ private wsSubs;
75
+ private wsUsed;
76
+ private stopped;
77
+ private polling;
78
+ private statePolls;
79
+ private orderPolls;
80
+ private alertsFired;
81
+ private alertsDelivered;
82
+ private deliveryErrors;
83
+ private lastPricesAt;
84
+ constructor(addresses: string[], opts?: GuardianOptions);
85
+ channels(): string[];
86
+ start(): Promise<void>;
87
+ stop(): Promise<void>;
88
+ getStats(): GuardianStats;
89
+ getTargets(): GuardianTargetState[];
90
+ private startWebSocket;
91
+ private hasHip3Positions;
92
+ private refreshPrices;
93
+ /** HIP-3 mark/funding — heavier (per-dex metaAndAssetCtxs), only while HIP-3 positions exist. */
94
+ private refreshHip3Prices;
95
+ private pollAllStates;
96
+ private pollAllOrders;
97
+ private pollState;
98
+ private pollOrders;
99
+ /** Snapshot diff → position lifecycle alerts (mirrors the hosted poller). */
100
+ private diff;
101
+ private passesPrefs;
102
+ private dispatch;
103
+ private log;
104
+ }
105
+ /** Start watching. Resolves once the first snapshot is seeded. */
106
+ export declare function startGuardian(opts?: GuardianOptions): Promise<GuardianHandle>;
107
+ //# sourceMappingURL=engine.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"engine.d.ts","sourceRoot":"","sources":["../../scripts/guardian/engine.ts"],"names":[],"mappings":"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"}