openbroker 1.9.1 → 1.9.3
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 +10 -0
- package/README.md +11 -0
- package/SKILL.md +58 -1
- package/bin/cli.ts +3 -0
- package/dist/auto/cli.js +3 -0
- package/dist/auto/examples/dca.d.ts +2 -1
- package/dist/auto/examples/dca.d.ts.map +1 -1
- package/dist/auto/examples/dca.js +19 -1
- package/dist/auto/examples/funding-arb.d.ts +2 -1
- package/dist/auto/examples/funding-arb.d.ts.map +1 -1
- package/dist/auto/examples/funding-arb.js +19 -2
- package/dist/auto/examples/grid.d.ts +2 -1
- package/dist/auto/examples/grid.d.ts.map +1 -1
- package/dist/auto/examples/grid.js +18 -2
- package/dist/auto/examples/mm-maker.d.ts +2 -1
- package/dist/auto/examples/mm-maker.d.ts.map +1 -1
- package/dist/auto/examples/mm-maker.js +18 -2
- package/dist/auto/examples/mm-spread.d.ts +2 -1
- package/dist/auto/examples/mm-spread.d.ts.map +1 -1
- package/dist/auto/examples/mm-spread.js +18 -2
- package/dist/auto/examples/price-alert.d.ts +2 -1
- package/dist/auto/examples/price-alert.d.ts.map +1 -1
- package/dist/auto/examples/price-alert.js +1 -0
- package/dist/auto/guardrails.d.ts +19 -0
- package/dist/auto/guardrails.d.ts.map +1 -0
- package/dist/auto/guardrails.js +575 -0
- package/dist/auto/guardrails.test.d.ts +2 -0
- package/dist/auto/guardrails.test.d.ts.map +1 -0
- package/dist/auto/guardrails.test.js +173 -0
- package/dist/auto/loader.d.ts +3 -3
- package/dist/auto/loader.d.ts.map +1 -1
- package/dist/auto/loader.js +25 -3
- package/dist/auto/runtime.d.ts.map +1 -1
- package/dist/auto/runtime.js +38 -20
- package/dist/auto/types.d.ts +43 -0
- package/dist/auto/types.d.ts.map +1 -1
- package/dist/lib.d.ts +2 -0
- package/dist/lib.d.ts.map +1 -1
- package/dist/lib.js +1 -0
- package/dist/setup/install.d.ts +3 -0
- package/dist/setup/install.d.ts.map +1 -0
- package/dist/setup/install.js +113 -0
- package/package.json +4 -3
- package/scripts/auto/cli.ts +3 -0
- package/scripts/auto/examples/dca.ts +21 -2
- package/scripts/auto/examples/funding-arb.ts +21 -3
- package/scripts/auto/examples/grid.ts +20 -3
- package/scripts/auto/examples/mm-maker.ts +20 -3
- package/scripts/auto/examples/mm-spread.ts +20 -3
- package/scripts/auto/examples/price-alert.ts +3 -1
- package/scripts/auto/guardrails.test.ts +227 -0
- package/scripts/auto/guardrails.ts +700 -0
- package/scripts/auto/loader.ts +41 -4
- package/scripts/auto/runtime.ts +38 -22
- package/scripts/auto/types.ts +54 -0
- package/scripts/lib.ts +10 -0
- package/scripts/setup/install.ts +146 -0
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
import assert from 'node:assert/strict';
|
|
2
|
+
import test from 'node:test';
|
|
3
|
+
import { CLIENT_WRITE_METHODS, GuardrailViolation, createGuardrailedClient, validateAutomationGuardrails, } from './guardrails.js';
|
|
4
|
+
import { listExamples, loadAutomation } from './loader.js';
|
|
5
|
+
const logger = {
|
|
6
|
+
info() { },
|
|
7
|
+
warn() { },
|
|
8
|
+
error() { },
|
|
9
|
+
debug() { },
|
|
10
|
+
};
|
|
11
|
+
function tradingPolicy(overrides = {}) {
|
|
12
|
+
return {
|
|
13
|
+
mode: 'trading',
|
|
14
|
+
allowedMarkets: ['ETH'],
|
|
15
|
+
maxOrderUsd: 1_000,
|
|
16
|
+
maxPositionUsd: 2_000,
|
|
17
|
+
maxTotalExposureUsd: 5_000,
|
|
18
|
+
maxLeverage: 2,
|
|
19
|
+
maxMarginUsedPct: 50,
|
|
20
|
+
maxOpenOrders: 10,
|
|
21
|
+
maxOrdersPerMinute: 10,
|
|
22
|
+
maxSlippageBps: 40,
|
|
23
|
+
allowMarketOrders: true,
|
|
24
|
+
allowAccountWideCancel: false,
|
|
25
|
+
...overrides,
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
function mockClient(options = {}) {
|
|
29
|
+
const calls = [];
|
|
30
|
+
const client = {
|
|
31
|
+
address: '0x0000000000000000000000000000000000000001',
|
|
32
|
+
walletAddress: '0x0000000000000000000000000000000000000002',
|
|
33
|
+
isApiWallet: true,
|
|
34
|
+
async getUserStateAll() {
|
|
35
|
+
return {
|
|
36
|
+
assetPositions: (options.positions ?? []).map((position) => ({
|
|
37
|
+
position: {
|
|
38
|
+
coin: position.coin,
|
|
39
|
+
szi: String(position.size),
|
|
40
|
+
positionValue: String(Math.abs(position.size * position.price)),
|
|
41
|
+
leverage: { type: 'cross', value: position.leverage ?? 1 },
|
|
42
|
+
},
|
|
43
|
+
})),
|
|
44
|
+
marginSummary: { accountValue: '10000', totalMarginUsed: '0' },
|
|
45
|
+
};
|
|
46
|
+
},
|
|
47
|
+
async getAllMids() { return { ETH: '2000', BTC: '50000' }; },
|
|
48
|
+
async getOpenOrders() { return []; },
|
|
49
|
+
async getSpotBalances() { return { balances: options.spotBalances ?? [] }; },
|
|
50
|
+
async getSpotMetaAndAssetCtxs() {
|
|
51
|
+
return options.spotData ?? { meta: { tokens: [], universe: [] }, assetCtxs: [] };
|
|
52
|
+
},
|
|
53
|
+
resolveOutcomeRef() {
|
|
54
|
+
return { outcome: 1, side: 0, encoding: 10, coin: '#10', tokenName: '+10', assetId: 100000010 };
|
|
55
|
+
},
|
|
56
|
+
async marketOrder(...args) {
|
|
57
|
+
calls.push({ method: 'marketOrder', args });
|
|
58
|
+
return { status: 'ok' };
|
|
59
|
+
},
|
|
60
|
+
async limitOrder(...args) {
|
|
61
|
+
calls.push({ method: 'limitOrder', args });
|
|
62
|
+
return { status: 'ok' };
|
|
63
|
+
},
|
|
64
|
+
async bulkOrder(...args) {
|
|
65
|
+
calls.push({ method: 'bulkOrder', args });
|
|
66
|
+
return { status: 'ok' };
|
|
67
|
+
},
|
|
68
|
+
async spotLimitOrder(...args) {
|
|
69
|
+
calls.push({ method: 'spotLimitOrder', args });
|
|
70
|
+
return { status: 'ok' };
|
|
71
|
+
},
|
|
72
|
+
};
|
|
73
|
+
return { client, calls };
|
|
74
|
+
}
|
|
75
|
+
test('guardrail schema rejects missing and internally inconsistent limits', () => {
|
|
76
|
+
assert.throws(() => validateAutomationGuardrails({ mode: 'trading' }), /allowedMarkets/);
|
|
77
|
+
assert.throws(() => validateAutomationGuardrails(tradingPolicy({ maxOrderUsd: 3_000 })), /maxOrderUsd.*maxPositionUsd/);
|
|
78
|
+
assert.deepEqual(validateAutomationGuardrails({ mode: 'read-only' }), { mode: 'read-only' });
|
|
79
|
+
});
|
|
80
|
+
test('all client write families are included in the enforcement boundary', () => {
|
|
81
|
+
for (const method of [
|
|
82
|
+
'bulkOrder', 'bulkCancel', 'scheduleCancel',
|
|
83
|
+
'outcomeOrder', 'outcomeMarketOrder', 'outcomeLimitOrder',
|
|
84
|
+
]) {
|
|
85
|
+
assert.equal(CLIENT_WRITE_METHODS.has(method), true, `${method} must be guarded`);
|
|
86
|
+
}
|
|
87
|
+
});
|
|
88
|
+
test('every bundled example exports a valid guardrail policy', async () => {
|
|
89
|
+
for (const example of listExamples()) {
|
|
90
|
+
const loaded = await loadAutomation(example.path, { config: {} });
|
|
91
|
+
assert.ok(loaded.guardrails.mode === 'read-only' || loaded.guardrails.mode === 'trading');
|
|
92
|
+
}
|
|
93
|
+
});
|
|
94
|
+
test('read-only policy blocks every write before it reaches the client', async () => {
|
|
95
|
+
const { client, calls } = mockClient();
|
|
96
|
+
const guarded = createGuardrailedClient(client, {
|
|
97
|
+
policy: { mode: 'read-only' },
|
|
98
|
+
rawClient: client,
|
|
99
|
+
log: logger,
|
|
100
|
+
});
|
|
101
|
+
await assert.rejects(guarded.bulkOrder([{ coin: 'ETH', isBuy: true, size: 0.1, price: 2000 }]), (error) => error instanceof GuardrailViolation && error.code === 'read-only');
|
|
102
|
+
assert.equal(calls.length, 0);
|
|
103
|
+
});
|
|
104
|
+
test('trading policy blocks disallowed markets, missing leverage, and oversized orders', async () => {
|
|
105
|
+
const { client, calls } = mockClient();
|
|
106
|
+
const guarded = createGuardrailedClient(client, {
|
|
107
|
+
policy: tradingPolicy(),
|
|
108
|
+
rawClient: client,
|
|
109
|
+
log: logger,
|
|
110
|
+
});
|
|
111
|
+
await assert.rejects(guarded.limitOrder('BTC', true, 0.01, 50_000, 'Gtc', false, 1), (error) => error instanceof GuardrailViolation && error.code === 'market-not-allowed');
|
|
112
|
+
await assert.rejects(guarded.limitOrder('ETH', true, 0.1, 2_000), (error) => error instanceof GuardrailViolation && error.code === 'leverage-required');
|
|
113
|
+
await assert.rejects(guarded.limitOrder('ETH', true, 0.6, 2_000, 'Gtc', false, 1), (error) => error instanceof GuardrailViolation && error.code === 'order-notional');
|
|
114
|
+
assert.equal(calls.length, 0);
|
|
115
|
+
});
|
|
116
|
+
test('valid market orders execute with runtime-capped slippage', async () => {
|
|
117
|
+
const { client, calls } = mockClient();
|
|
118
|
+
const guarded = createGuardrailedClient(client, {
|
|
119
|
+
policy: tradingPolicy(),
|
|
120
|
+
rawClient: client,
|
|
121
|
+
log: logger,
|
|
122
|
+
});
|
|
123
|
+
await guarded.marketOrder('ETH', true, 0.1, undefined, 1);
|
|
124
|
+
assert.equal(calls.length, 1);
|
|
125
|
+
assert.deepEqual(calls[0], {
|
|
126
|
+
method: 'marketOrder',
|
|
127
|
+
args: ['ETH', true, 0.1, 40, 1],
|
|
128
|
+
});
|
|
129
|
+
});
|
|
130
|
+
test('account-wide exposure is checked while genuine reductions remain available above caps', async () => {
|
|
131
|
+
const exposed = mockClient({ positions: [{ coin: 'BTC', size: 0.1, price: 50_000 }] });
|
|
132
|
+
const exposureGuarded = createGuardrailedClient(exposed.client, {
|
|
133
|
+
policy: tradingPolicy({ maxTotalExposureUsd: 5_100 }),
|
|
134
|
+
rawClient: exposed.client,
|
|
135
|
+
log: logger,
|
|
136
|
+
});
|
|
137
|
+
await assert.rejects(exposureGuarded.limitOrder('ETH', true, 0.1, 2_000, 'Gtc', false, 1), (error) => error instanceof GuardrailViolation && error.code === 'total-exposure');
|
|
138
|
+
const reducing = mockClient({ positions: [{ coin: 'ETH', size: 1, price: 2_000 }] });
|
|
139
|
+
const reductionGuarded = createGuardrailedClient(reducing.client, {
|
|
140
|
+
policy: tradingPolicy({ maxPositionUsd: 1_000, maxTotalExposureUsd: 1_000 }),
|
|
141
|
+
rawClient: reducing.client,
|
|
142
|
+
log: logger,
|
|
143
|
+
});
|
|
144
|
+
await reductionGuarded.marketOrder('ETH', false, 0.1);
|
|
145
|
+
assert.equal(reducing.calls.length, 1);
|
|
146
|
+
});
|
|
147
|
+
test('spot exposure joins market contexts by pair identifier instead of array position', async () => {
|
|
148
|
+
const { client, calls } = mockClient({
|
|
149
|
+
spotBalances: [{ coin: 'HYPE', total: '3' }],
|
|
150
|
+
spotData: {
|
|
151
|
+
meta: {
|
|
152
|
+
tokens: [{ index: 0, name: 'USDC' }, { index: 1, name: 'HYPE' }],
|
|
153
|
+
universe: [{ name: '@107', tokens: [1, 0] }],
|
|
154
|
+
},
|
|
155
|
+
assetCtxs: [
|
|
156
|
+
{ coin: '@999', midPx: '99999', markPx: '99999' },
|
|
157
|
+
{ coin: '@107', midPx: '62.5', markPx: '62.5' },
|
|
158
|
+
],
|
|
159
|
+
},
|
|
160
|
+
});
|
|
161
|
+
const guarded = createGuardrailedClient(client, {
|
|
162
|
+
policy: tradingPolicy({
|
|
163
|
+
allowedMarkets: ['spot:HYPE'],
|
|
164
|
+
maxOrderUsd: 100,
|
|
165
|
+
maxPositionUsd: 500,
|
|
166
|
+
maxTotalExposureUsd: 500,
|
|
167
|
+
}),
|
|
168
|
+
rawClient: client,
|
|
169
|
+
log: logger,
|
|
170
|
+
});
|
|
171
|
+
await guarded.spotLimitOrder('HYPE', true, 0.1, 62.5, 'Gtc');
|
|
172
|
+
assert.equal(calls.length, 1);
|
|
173
|
+
});
|
package/dist/auto/loader.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { AutomationConfig, AutomationGuardrailContext, LoadedAutomation } from './types.js';
|
|
2
2
|
/** Resolve a script path from a name or path */
|
|
3
3
|
export declare function resolveScriptPath(nameOrPath: string): string;
|
|
4
4
|
/** Resolve a bundled example by name */
|
|
@@ -10,8 +10,8 @@ export declare function listExamples(): Array<{
|
|
|
10
10
|
}>;
|
|
11
11
|
/** Load config metadata from all bundled examples */
|
|
12
12
|
export declare function loadExampleConfigs(): Promise<Record<string, AutomationConfig>>;
|
|
13
|
-
/** Load an automation module and validate
|
|
14
|
-
export declare function loadAutomation(scriptPath: string): Promise<
|
|
13
|
+
/** Load an automation module and validate its factory plus required guardrails export. */
|
|
14
|
+
export declare function loadAutomation(scriptPath: string, context?: AutomationGuardrailContext): Promise<LoadedAutomation>;
|
|
15
15
|
/** List available automation scripts in ~/.openbroker/automations/ */
|
|
16
16
|
export declare function listAutomations(): Array<{
|
|
17
17
|
name: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"loader.d.ts","sourceRoot":"","sources":["../../scripts/auto/loader.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"loader.d.ts","sourceRoot":"","sources":["../../scripts/auto/loader.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAEV,gBAAgB,EAChB,0BAA0B,EAE1B,gBAAgB,EACjB,MAAM,YAAY,CAAC;AAQpB,gDAAgD;AAChD,wBAAgB,iBAAiB,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,CA2B5D;AAED,wCAAwC;AACxC,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAOvD;AAED,uCAAuC;AACvC,wBAAgB,YAAY,IAAI,KAAK,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC,CASpE;AAED,qDAAqD;AACrD,wBAAsB,kBAAkB,IAAI,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,gBAAgB,CAAC,CAAC,CAiBpF;AAmDD,0FAA0F;AAC1F,wBAAsB,cAAc,CAClC,UAAU,EAAE,MAAM,EAClB,OAAO,GAAE,0BAA2C,GACnD,OAAO,CAAC,gBAAgB,CAAC,CA0B3B;AAED,sEAAsE;AACtE,wBAAgB,eAAe,IAAI,KAAK,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC,CASvE;AAED,8CAA8C;AAC9C,wBAAgB,oBAAoB,IAAI,IAAI,CAE3C"}
|
package/dist/auto/loader.js
CHANGED
|
@@ -3,6 +3,7 @@ import { existsSync, readdirSync, mkdirSync } from 'fs';
|
|
|
3
3
|
import path from 'path';
|
|
4
4
|
import os from 'os';
|
|
5
5
|
import { fileURLToPath } from 'url';
|
|
6
|
+
import { resolveAutomationGuardrails } from './guardrails.js';
|
|
6
7
|
const __filename = fileURLToPath(import.meta.url);
|
|
7
8
|
const __dirname = path.dirname(__filename);
|
|
8
9
|
const AUTOMATIONS_DIR = path.join(os.homedir(), '.openbroker', 'automations');
|
|
@@ -98,8 +99,21 @@ function resolveAutomationConfig(mod) {
|
|
|
98
99
|
}
|
|
99
100
|
return null;
|
|
100
101
|
}
|
|
101
|
-
|
|
102
|
-
|
|
102
|
+
function resolveGuardrailsExport(mod) {
|
|
103
|
+
const candidates = [
|
|
104
|
+
mod.guardrails,
|
|
105
|
+
mod.default?.guardrails,
|
|
106
|
+
mod["module.exports"]?.guardrails,
|
|
107
|
+
];
|
|
108
|
+
for (const candidate of candidates) {
|
|
109
|
+
if (candidate && (typeof candidate === 'object' || typeof candidate === 'function')) {
|
|
110
|
+
return candidate;
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
return null;
|
|
114
|
+
}
|
|
115
|
+
/** Load an automation module and validate its factory plus required guardrails export. */
|
|
116
|
+
export async function loadAutomation(scriptPath, context = { config: {} }) {
|
|
103
117
|
const absolutePath = path.resolve(scriptPath);
|
|
104
118
|
// Dynamic import — tsx handles TypeScript transpilation
|
|
105
119
|
const mod = await import(absolutePath);
|
|
@@ -108,7 +122,15 @@ export async function loadAutomation(scriptPath) {
|
|
|
108
122
|
throw new Error(`Automation script must export a default function.\n` +
|
|
109
123
|
`Got: ${typeof factory} from ${scriptPath}`);
|
|
110
124
|
}
|
|
111
|
-
|
|
125
|
+
const guardrailsExport = resolveGuardrailsExport(mod);
|
|
126
|
+
if (!guardrailsExport) {
|
|
127
|
+
throw new Error(`Automation script must export "guardrails".\n` +
|
|
128
|
+
`Use { mode: "read-only" } for monitoring-only scripts or a validated trading policy.`);
|
|
129
|
+
}
|
|
130
|
+
return {
|
|
131
|
+
factory: factory,
|
|
132
|
+
guardrails: resolveAutomationGuardrails(guardrailsExport, context),
|
|
133
|
+
};
|
|
112
134
|
}
|
|
113
135
|
/** List available automation scripts in ~/.openbroker/automations/ */
|
|
114
136
|
export function listAutomations() {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"runtime.d.ts","sourceRoot":"","sources":["../../scripts/auto/runtime.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"runtime.d.ts","sourceRoot":"","sources":["../../scripts/auto/runtime.ts"],"names":[],"mappings":"AAgBA,OAAO,EAA4C,wBAAwB,IAAI,qBAAqB,EAAE,MAAM,eAAe,CAAC;AAG5H,OAAO,KAAK,EAYV,iBAAiB,EAElB,MAAM,YAAY,CAAC;AAqYpB,MAAM,WAAW,cAAc;IAC7B,UAAU,EAAE,MAAM,CAAC;IACnB,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,sFAAsF;IACtF,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,uEAAuE;IACvE,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,kFAAkF;IAClF,YAAY,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACvC;;;;;OAKG;IACH,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB;;;OAGG;IACH,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB;AAKD,wBAAgB,qBAAqB,IAAI,iBAAiB,EAAE,CAE3D;AAED,wBAAgB,aAAa,CAAC,EAAE,EAAE,MAAM,GAAG,iBAAiB,GAAG,SAAS,CAEvE;AAED,8EAA8E;AAC9E,OAAO,EAAE,qBAAqB,IAAI,wBAAwB,EAAE,CAAC;AAE7D,wBAAsB,eAAe,CAAC,OAAO,EAAE,cAAc,GAAG,OAAO,CAAC,iBAAiB,CAAC,CAijBzF"}
|
package/dist/auto/runtime.js
CHANGED
|
@@ -8,6 +8,7 @@ import { roundPrice, roundSize, sleep, normalizeCoin, formatUsd, formatPercent,
|
|
|
8
8
|
import { WebSocketManager } from '../core/ws.js';
|
|
9
9
|
import { AutomationEventBus } from './events.js';
|
|
10
10
|
import { loadAutomation } from './loader.js';
|
|
11
|
+
import { CLIENT_WRITE_METHODS, createGuardrailedClient } from './guardrails.js';
|
|
11
12
|
import { registerAutomation, unregisterAutomation, getRegisteredAutomations as getRegisteredFromFile } from './registry.js';
|
|
12
13
|
import { createAutomationAudit, toSerializable } from './audit.js';
|
|
13
14
|
import { startKeepAwake } from './keep-awake.js';
|
|
@@ -74,12 +75,6 @@ function fanOutAgentAction(observers, action, status, details, txHash) {
|
|
|
74
75
|
}
|
|
75
76
|
}
|
|
76
77
|
const STATE_DIR = path.join(os.homedir(), '.openbroker', 'state');
|
|
77
|
-
const AUDITED_WRITE_METHODS = new Set([
|
|
78
|
-
'order', 'marketOrder', 'limitOrder', 'triggerOrder',
|
|
79
|
-
'takeProfit', 'stopLoss', 'cancel', 'cancelAll',
|
|
80
|
-
'spotOrder', 'spotMarketOrder', 'spotLimitOrder', 'spotCancel',
|
|
81
|
-
'updateLeverage', 'approveBuilderFee', 'twapOrder', 'twapCancel',
|
|
82
|
-
]);
|
|
83
78
|
function createState(id) {
|
|
84
79
|
mkdirSync(STATE_DIR, { recursive: true });
|
|
85
80
|
const stateFile = path.join(STATE_DIR, `${id}.json`);
|
|
@@ -157,18 +152,11 @@ function createLogger(id, verbose, audit) {
|
|
|
157
152
|
};
|
|
158
153
|
}
|
|
159
154
|
// ── Dry-run client proxy ────────────────────────────────────────────
|
|
160
|
-
const WRITE_METHODS = new Set([
|
|
161
|
-
'order', 'marketOrder', 'limitOrder', 'triggerOrder',
|
|
162
|
-
'takeProfit', 'stopLoss', 'cancel', 'cancelAll',
|
|
163
|
-
'updateLeverage', 'approveBuilderFee',
|
|
164
|
-
'spotOrder', 'spotMarketOrder', 'spotLimitOrder', 'spotCancel',
|
|
165
|
-
'twapOrder', 'twapCancel',
|
|
166
|
-
]);
|
|
167
155
|
function createDryClient(client, log) {
|
|
168
156
|
return new Proxy(client, {
|
|
169
157
|
get(target, prop, receiver) {
|
|
170
158
|
const value = Reflect.get(target, prop, receiver);
|
|
171
|
-
if (typeof prop === 'string' &&
|
|
159
|
+
if (typeof prop === 'string' && CLIENT_WRITE_METHODS.has(prop) && typeof value === 'function') {
|
|
172
160
|
return (...args) => {
|
|
173
161
|
log.info(`[DRY] ${prop}(${args.map(a => JSON.stringify(a)).join(', ')})`);
|
|
174
162
|
return Promise.resolve({ status: 'ok', response: { type: 'dry_run' } });
|
|
@@ -182,7 +170,7 @@ function createAuditedClient(client, audit, dryRun, observers) {
|
|
|
182
170
|
return new Proxy(client, {
|
|
183
171
|
get(target, prop, receiver) {
|
|
184
172
|
const value = Reflect.get(target, prop, receiver);
|
|
185
|
-
if (typeof prop === 'string' &&
|
|
173
|
+
if (typeof prop === 'string' && CLIENT_WRITE_METHODS.has(prop) && typeof value === 'function') {
|
|
186
174
|
return async (...args) => {
|
|
187
175
|
const actionId = `${prop}:${Date.now()}:${Math.random().toString(16).slice(2)}`;
|
|
188
176
|
audit.recordAction({
|
|
@@ -396,8 +384,39 @@ export async function startAutomation(options) {
|
|
|
396
384
|
}
|
|
397
385
|
}
|
|
398
386
|
const observers = await loadConventionObservers(log);
|
|
387
|
+
let loaded;
|
|
388
|
+
try {
|
|
389
|
+
log.info(`Loading automation: ${scriptPath}`);
|
|
390
|
+
loaded = await loadAutomation(scriptPath, { config: stateController.snapshot() });
|
|
391
|
+
}
|
|
392
|
+
catch (err) {
|
|
393
|
+
const error = err instanceof Error ? err : new Error(String(err));
|
|
394
|
+
audit.recordError('guardrail_validation', error);
|
|
395
|
+
await audit.stop({
|
|
396
|
+
status: 'error',
|
|
397
|
+
stopReason: 'guardrail_validation_error',
|
|
398
|
+
pollCount: 0,
|
|
399
|
+
eventsEmitted: 0,
|
|
400
|
+
});
|
|
401
|
+
keepAwake?.stop();
|
|
402
|
+
throw error;
|
|
403
|
+
}
|
|
404
|
+
audit.recordNote('guardrails', loaded.guardrails);
|
|
399
405
|
const baseClient = dryRun ? createDryClient(rawClient, log) : rawClient;
|
|
400
|
-
const
|
|
406
|
+
const guardedClient = createGuardrailedClient(baseClient, {
|
|
407
|
+
policy: loaded.guardrails,
|
|
408
|
+
rawClient,
|
|
409
|
+
log,
|
|
410
|
+
onViolation: (error, method, args) => {
|
|
411
|
+
audit.recordNote('guardrail_block', {
|
|
412
|
+
code: error.code,
|
|
413
|
+
message: error.message,
|
|
414
|
+
method,
|
|
415
|
+
args: toSerializable(args),
|
|
416
|
+
});
|
|
417
|
+
},
|
|
418
|
+
});
|
|
419
|
+
const client = createAuditedClient(guardedClient, audit, dryRun, observers);
|
|
401
420
|
const startHooks = [];
|
|
402
421
|
const stopHooks = [];
|
|
403
422
|
const errorHooks = [];
|
|
@@ -428,12 +447,11 @@ export async function startAutomation(options) {
|
|
|
428
447
|
audit: auditApi,
|
|
429
448
|
id,
|
|
430
449
|
dryRun,
|
|
450
|
+
guardrails: loaded.guardrails,
|
|
431
451
|
};
|
|
432
452
|
try {
|
|
433
|
-
//
|
|
434
|
-
|
|
435
|
-
const factory = await loadAutomation(scriptPath);
|
|
436
|
-
await factory(api);
|
|
453
|
+
// Execute the already validated factory function (registers handlers).
|
|
454
|
+
await loaded.factory(api);
|
|
437
455
|
// Call onStart hooks
|
|
438
456
|
for (const hook of startHooks) {
|
|
439
457
|
try {
|
package/dist/auto/types.d.ts
CHANGED
|
@@ -1,6 +1,47 @@
|
|
|
1
1
|
import type { HyperliquidClient } from '../core/client.js';
|
|
2
2
|
/** What an automation .ts file exports */
|
|
3
3
|
export type AutomationFactory = (api: AutomationAPI) => void | Promise<void>;
|
|
4
|
+
/** Runtime-enforced policy exported by every automation module. */
|
|
5
|
+
export type AutomationGuardrails = ReadOnlyAutomationGuardrails | TradingAutomationGuardrails;
|
|
6
|
+
export interface ReadOnlyAutomationGuardrails {
|
|
7
|
+
/** Read-only automations cannot call any client write method. */
|
|
8
|
+
mode: 'read-only';
|
|
9
|
+
}
|
|
10
|
+
export interface TradingAutomationGuardrails {
|
|
11
|
+
mode: 'trading';
|
|
12
|
+
/** Canonical markets this automation may trade: `ETH`, `xyz:CL`, `spot:HYPE`, `#1230`. */
|
|
13
|
+
allowedMarkets: string[];
|
|
14
|
+
/** Maximum USD notional for one submitted order. */
|
|
15
|
+
maxOrderUsd: number;
|
|
16
|
+
/** Maximum absolute USD exposure in any one market after an order. */
|
|
17
|
+
maxPositionUsd: number;
|
|
18
|
+
/** Maximum absolute USD exposure across the account after an order. */
|
|
19
|
+
maxTotalExposureUsd: number;
|
|
20
|
+
/** Maximum leverage the automation may request or use when increasing perp exposure. */
|
|
21
|
+
maxLeverage: number;
|
|
22
|
+
/** Maximum account margin utilization allowed after a risk-increasing perp order. */
|
|
23
|
+
maxMarginUsedPct: number;
|
|
24
|
+
/** Maximum account-wide open orders after this automation submits an order. */
|
|
25
|
+
maxOpenOrders: number;
|
|
26
|
+
/** Maximum risk-increasing order submissions in a rolling 60-second window. */
|
|
27
|
+
maxOrdersPerMinute: number;
|
|
28
|
+
/** Maximum slippage passed to market-order helpers. */
|
|
29
|
+
maxSlippageBps: number;
|
|
30
|
+
/** Whether market-order helpers may be used. */
|
|
31
|
+
allowMarketOrders: boolean;
|
|
32
|
+
/** Whether `cancelAll()` without a market or an armed `scheduleCancel()` is allowed. */
|
|
33
|
+
allowAccountWideCancel: boolean;
|
|
34
|
+
}
|
|
35
|
+
export interface AutomationGuardrailContext {
|
|
36
|
+
/** Persisted automation state with current `--set` overrides applied. */
|
|
37
|
+
config: Readonly<Record<string, unknown>>;
|
|
38
|
+
}
|
|
39
|
+
/** Guardrails may be static or derived from startup config, but the result is always validated. */
|
|
40
|
+
export type AutomationGuardrailsExport = AutomationGuardrails | ((context: AutomationGuardrailContext) => AutomationGuardrails);
|
|
41
|
+
export interface LoadedAutomation {
|
|
42
|
+
factory: AutomationFactory;
|
|
43
|
+
guardrails: AutomationGuardrails;
|
|
44
|
+
}
|
|
4
45
|
/** Config field descriptor for example automations */
|
|
5
46
|
export interface AutomationConfigField {
|
|
6
47
|
type: 'string' | 'number' | 'boolean';
|
|
@@ -188,6 +229,8 @@ export interface AutomationAPI {
|
|
|
188
229
|
id: string;
|
|
189
230
|
/** True if running in --dry mode (write methods are intercepted) */
|
|
190
231
|
dryRun: boolean;
|
|
232
|
+
/** Validated policy currently enforced by the runtime client proxy. */
|
|
233
|
+
guardrails: Readonly<AutomationGuardrails>;
|
|
191
234
|
}
|
|
192
235
|
export interface AutomationSnapshot {
|
|
193
236
|
prices: Map<string, number>;
|
package/dist/auto/types.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../scripts/auto/types.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../scripts/auto/types.ts"],"names":[],"mappings":"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"}
|
package/dist/lib.d.ts
CHANGED
|
@@ -11,6 +11,8 @@ export type { ChaseOptions, ChaseResult } from './operations/chase.js';
|
|
|
11
11
|
export { startAutomation, getRunningAutomations, getAutomation, getRegisteredAutomations, } from './auto/runtime.js';
|
|
12
12
|
export type { RuntimeOptions } from './auto/runtime.js';
|
|
13
13
|
export { resolveScriptPath, resolveExamplePath, listAutomations, listExamples, loadExampleConfigs, ensureAutomationsDir, loadAutomation, } from './auto/loader.js';
|
|
14
|
+
export { GuardrailViolation, CLIENT_WRITE_METHODS, canonicalMarket, validateAutomationGuardrails, resolveAutomationGuardrails, createGuardrailedClient, } from './auto/guardrails.js';
|
|
15
|
+
export type { GuardrailedClientOptions } from './auto/guardrails.js';
|
|
14
16
|
export { registerAutomation, unregisterAutomation, cleanRegistry, getAutomationsToRestart, markAutomationError, } from './auto/registry.js';
|
|
15
17
|
export type * from './auto/types.js';
|
|
16
18
|
//# sourceMappingURL=lib.d.ts.map
|
package/dist/lib.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"lib.d.ts","sourceRoot":"","sources":["../scripts/lib.ts"],"names":[],"mappings":"AAQA,OAAO,EACL,iBAAiB,EACjB,SAAS,GACV,MAAM,kBAAkB,CAAC;AAK1B,OAAO,EACL,gBAAgB,EAChB,YAAY,EACZ,cAAc,GACf,MAAM,cAAc,CAAC;AACtB,YAAY,EAAE,UAAU,EAAE,WAAW,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAE5E,OAAO,EACL,UAAU,EACV,YAAY,EACZ,UAAU,EACV,SAAS,EACT,eAAe,EACf,aAAa,EACb,iBAAiB,EACjB,eAAe,EACf,2BAA2B,GAC5B,MAAM,kBAAkB,CAAC;AAE1B,OAAO,EACL,UAAU,EACV,SAAS,EACT,KAAK,EACL,aAAa,EACb,SAAS,EACT,aAAa,EACb,oBAAoB,EACpB,SAAS,EACT,gBAAgB,EAChB,cAAc,EACd,aAAa,EACb,WAAW,EACX,uBAAuB,GACxB,MAAM,iBAAiB,CAAC;AAEzB,mBAAmB,iBAAiB,CAAC;AAIrC,OAAO,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAC;AACrD,YAAY,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAC;AAE7E,OAAO,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AACjD,YAAY,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AAIvE,OAAO,EACL,eAAe,EACf,qBAAqB,EACrB,aAAa,EACb,wBAAwB,GACzB,MAAM,mBAAmB,CAAC;AAC3B,YAAY,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAExD,OAAO,EACL,iBAAiB,EACjB,kBAAkB,EAClB,eAAe,EACf,YAAY,EACZ,kBAAkB,EAClB,oBAAoB,EACpB,cAAc,GACf,MAAM,kBAAkB,CAAC;AAE1B,OAAO,EACL,kBAAkB,EAClB,oBAAoB,EACpB,aAAa,EACb,uBAAuB,EACvB,mBAAmB,GACpB,MAAM,oBAAoB,CAAC;AAE5B,mBAAmB,iBAAiB,CAAC"}
|
|
1
|
+
{"version":3,"file":"lib.d.ts","sourceRoot":"","sources":["../scripts/lib.ts"],"names":[],"mappings":"AAQA,OAAO,EACL,iBAAiB,EACjB,SAAS,GACV,MAAM,kBAAkB,CAAC;AAK1B,OAAO,EACL,gBAAgB,EAChB,YAAY,EACZ,cAAc,GACf,MAAM,cAAc,CAAC;AACtB,YAAY,EAAE,UAAU,EAAE,WAAW,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAE5E,OAAO,EACL,UAAU,EACV,YAAY,EACZ,UAAU,EACV,SAAS,EACT,eAAe,EACf,aAAa,EACb,iBAAiB,EACjB,eAAe,EACf,2BAA2B,GAC5B,MAAM,kBAAkB,CAAC;AAE1B,OAAO,EACL,UAAU,EACV,SAAS,EACT,KAAK,EACL,aAAa,EACb,SAAS,EACT,aAAa,EACb,oBAAoB,EACpB,SAAS,EACT,gBAAgB,EAChB,cAAc,EACd,aAAa,EACb,WAAW,EACX,uBAAuB,GACxB,MAAM,iBAAiB,CAAC;AAEzB,mBAAmB,iBAAiB,CAAC;AAIrC,OAAO,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAC;AACrD,YAAY,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAC;AAE7E,OAAO,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AACjD,YAAY,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AAIvE,OAAO,EACL,eAAe,EACf,qBAAqB,EACrB,aAAa,EACb,wBAAwB,GACzB,MAAM,mBAAmB,CAAC;AAC3B,YAAY,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAExD,OAAO,EACL,iBAAiB,EACjB,kBAAkB,EAClB,eAAe,EACf,YAAY,EACZ,kBAAkB,EAClB,oBAAoB,EACpB,cAAc,GACf,MAAM,kBAAkB,CAAC;AAE1B,OAAO,EACL,kBAAkB,EAClB,oBAAoB,EACpB,eAAe,EACf,4BAA4B,EAC5B,2BAA2B,EAC3B,uBAAuB,GACxB,MAAM,sBAAsB,CAAC;AAC9B,YAAY,EAAE,wBAAwB,EAAE,MAAM,sBAAsB,CAAC;AAErE,OAAO,EACL,kBAAkB,EAClB,oBAAoB,EACpB,aAAa,EACb,uBAAuB,EACvB,mBAAmB,GACpB,MAAM,oBAAoB,CAAC;AAE5B,mBAAmB,iBAAiB,CAAC"}
|
package/dist/lib.js
CHANGED
|
@@ -18,4 +18,5 @@ export { runChase } from './operations/chase.js';
|
|
|
18
18
|
// ── Automation runtime ──────────────────────────────────────────────
|
|
19
19
|
export { startAutomation, getRunningAutomations, getAutomation, getRegisteredAutomations, } from './auto/runtime.js';
|
|
20
20
|
export { resolveScriptPath, resolveExamplePath, listAutomations, listExamples, loadExampleConfigs, ensureAutomationsDir, loadAutomation, } from './auto/loader.js';
|
|
21
|
+
export { GuardrailViolation, CLIENT_WRITE_METHODS, canonicalMarket, validateAutomationGuardrails, resolveAutomationGuardrails, createGuardrailedClient, } from './auto/guardrails.js';
|
|
21
22
|
export { registerAutomation, unregisterAutomation, cleanRegistry, getAutomationsToRestart, markAutomationError, } from './auto/registry.js';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"install.d.ts","sourceRoot":"","sources":["../../scripts/setup/install.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
#!/usr/bin/env npx tsx
|
|
2
|
+
// Harness-aware OpenBroker installer.
|
|
3
|
+
import * as fs from 'fs';
|
|
4
|
+
import * as path from 'path';
|
|
5
|
+
import { homedir } from 'os';
|
|
6
|
+
import { fileURLToPath } from 'url';
|
|
7
|
+
import { spawnSync } from 'child_process';
|
|
8
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
9
|
+
const __dirname = path.dirname(__filename);
|
|
10
|
+
const packageRoot = path.resolve(__dirname, '../..');
|
|
11
|
+
const args = new Set(process.argv.slice(2));
|
|
12
|
+
function printUsage() {
|
|
13
|
+
console.log(`
|
|
14
|
+
OpenBroker Harness Installer
|
|
15
|
+
============================
|
|
16
|
+
|
|
17
|
+
Usage:
|
|
18
|
+
openbroker install --codex [options]
|
|
19
|
+
npx openbroker@latest install --codex [options]
|
|
20
|
+
|
|
21
|
+
Harnesses:
|
|
22
|
+
--codex Install the OpenBroker skill for Codex
|
|
23
|
+
|
|
24
|
+
Options:
|
|
25
|
+
--skip-cli Do not install the persistent global CLI
|
|
26
|
+
--skip-setup Install files without starting API-wallet onboarding
|
|
27
|
+
--help Show this help
|
|
28
|
+
|
|
29
|
+
The default Codex flow installs the global CLI, writes the skill under
|
|
30
|
+
$CODEX_HOME/skills/openbroker (default: ~/.codex/skills/openbroker), and starts
|
|
31
|
+
restricted API-wallet onboarding.
|
|
32
|
+
`);
|
|
33
|
+
}
|
|
34
|
+
function fail(message) {
|
|
35
|
+
console.error(`Error: ${message}`);
|
|
36
|
+
process.exit(1);
|
|
37
|
+
}
|
|
38
|
+
function assertOpenBrokerSkill(skillPath) {
|
|
39
|
+
if (!fs.existsSync(skillPath))
|
|
40
|
+
return;
|
|
41
|
+
const existing = fs.readFileSync(skillPath, 'utf8');
|
|
42
|
+
if (!/^name:\s*openbroker\s*$/m.test(existing)) {
|
|
43
|
+
fail(`refusing to overwrite unrelated skill at ${skillPath}`);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
function copyManagedFile(source, destination) {
|
|
47
|
+
if (!fs.existsSync(source)) {
|
|
48
|
+
fail(`packaged installer asset is missing: ${source}`);
|
|
49
|
+
}
|
|
50
|
+
fs.mkdirSync(path.dirname(destination), { recursive: true, mode: 0o755 });
|
|
51
|
+
fs.copyFileSync(source, destination);
|
|
52
|
+
fs.chmodSync(destination, 0o644);
|
|
53
|
+
}
|
|
54
|
+
function installCodexSkill() {
|
|
55
|
+
const codexHome = process.env.CODEX_HOME || path.join(homedir(), '.codex');
|
|
56
|
+
const destination = path.join(codexHome, 'skills', 'openbroker');
|
|
57
|
+
const skillPath = path.join(destination, 'SKILL.md');
|
|
58
|
+
assertOpenBrokerSkill(skillPath);
|
|
59
|
+
copyManagedFile(path.join(packageRoot, 'SKILL.md'), skillPath);
|
|
60
|
+
copyManagedFile(path.join(packageRoot, 'agents', 'openai.yaml'), path.join(destination, 'agents', 'openai.yaml'));
|
|
61
|
+
console.log(`✅ Codex skill installed: ${destination}`);
|
|
62
|
+
return destination;
|
|
63
|
+
}
|
|
64
|
+
function installGlobalCli() {
|
|
65
|
+
const npmCommand = process.platform === 'win32' ? 'npm.cmd' : 'npm';
|
|
66
|
+
console.log('\nInstalling the persistent OpenBroker CLI...');
|
|
67
|
+
const result = spawnSync(npmCommand, ['install', '-g', 'openbroker@latest'], {
|
|
68
|
+
stdio: 'inherit',
|
|
69
|
+
});
|
|
70
|
+
if (result.error) {
|
|
71
|
+
fail(`could not start npm: ${result.error.message}`);
|
|
72
|
+
}
|
|
73
|
+
if (result.status !== 0) {
|
|
74
|
+
fail('global CLI installation failed. Fix the npm permission error, then rerun with --skip-cli.');
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
function runApiWalletSetup() {
|
|
78
|
+
const onboardPath = path.join(packageRoot, 'scripts', 'setup', 'onboard.ts');
|
|
79
|
+
console.log('\nStarting restricted API-wallet onboarding...\n');
|
|
80
|
+
const result = spawnSync(process.execPath, ['--import', 'tsx', onboardPath, '--api-wallet'], {
|
|
81
|
+
stdio: 'inherit',
|
|
82
|
+
cwd: packageRoot,
|
|
83
|
+
env: process.env,
|
|
84
|
+
});
|
|
85
|
+
if (result.error) {
|
|
86
|
+
fail(`could not start onboarding: ${result.error.message}`);
|
|
87
|
+
}
|
|
88
|
+
if (result.status !== 0) {
|
|
89
|
+
fail('API-wallet onboarding did not complete. Rerun `openbroker setup --api-wallet`.');
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
function main() {
|
|
93
|
+
if (args.has('--help') || args.has('-h')) {
|
|
94
|
+
printUsage();
|
|
95
|
+
return;
|
|
96
|
+
}
|
|
97
|
+
if (!args.has('--codex')) {
|
|
98
|
+
printUsage();
|
|
99
|
+
fail('choose a supported harness flag such as --codex');
|
|
100
|
+
}
|
|
101
|
+
console.log('OpenBroker — Codex Installation');
|
|
102
|
+
console.log('================================\n');
|
|
103
|
+
installCodexSkill();
|
|
104
|
+
if (!args.has('--skip-cli')) {
|
|
105
|
+
installGlobalCli();
|
|
106
|
+
}
|
|
107
|
+
if (!args.has('--skip-setup')) {
|
|
108
|
+
runApiWalletSetup();
|
|
109
|
+
}
|
|
110
|
+
console.log('\n✅ OpenBroker installation complete.');
|
|
111
|
+
console.log('Restart Codex or start a new thread, then invoke $openbroker.');
|
|
112
|
+
}
|
|
113
|
+
main();
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "openbroker",
|
|
3
|
-
"version": "1.9.
|
|
3
|
+
"version": "1.9.3",
|
|
4
4
|
"description": "Hyperliquid trading CLI - execute orders, manage positions, and run trading strategies",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -51,8 +51,9 @@
|
|
|
51
51
|
"funding-scan": "tsx scripts/info/funding-scan.ts",
|
|
52
52
|
"outcomes": "tsx scripts/info/outcomes.ts",
|
|
53
53
|
"build": "tsc",
|
|
54
|
-
"prepublishOnly": "npm run build && npm run test:cli",
|
|
55
|
-
"test:cli": "node --import tsx bin/cli.ts --help"
|
|
54
|
+
"prepublishOnly": "npm run build && npm run test:guardrails && npm run test:cli",
|
|
55
|
+
"test:cli": "node --import tsx bin/cli.ts --help",
|
|
56
|
+
"test:guardrails": "node --import tsx --test scripts/auto/guardrails.test.ts"
|
|
56
57
|
},
|
|
57
58
|
"dependencies": {
|
|
58
59
|
"@nktkas/hyperliquid": "^0.30.3",
|
package/scripts/auto/cli.ts
CHANGED
|
@@ -50,6 +50,8 @@ Scripts are loaded from:
|
|
|
50
50
|
3. Bundled examples (via --example)
|
|
51
51
|
|
|
52
52
|
Writing an automation:
|
|
53
|
+
export const guardrails = { mode: 'read-only' };
|
|
54
|
+
|
|
53
55
|
export default function(api) {
|
|
54
56
|
api.on('price_change', async ({ coin, changePct }) => {
|
|
55
57
|
api.log.info(\`\${coin} moved \${changePct.toFixed(2)}%\`);
|
|
@@ -207,6 +209,7 @@ function listCommand() {
|
|
|
207
209
|
if (automations.length === 0 && examples.length === 0) {
|
|
208
210
|
console.log('No automations found in ~/.openbroker/automations/');
|
|
209
211
|
console.log('\nCreate a .ts file there with:');
|
|
212
|
+
console.log(" export const guardrails = { mode: 'read-only' };");
|
|
210
213
|
console.log(' export default function(api) { ... }');
|
|
211
214
|
console.log('\nOr run a bundled example: openbroker auto examples');
|
|
212
215
|
return;
|