@autonomaai/event-schemas 1.0.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/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +19 -0
- package/dist/index.js.map +1 -0
- package/dist/schemas.d.ts +337 -0
- package/dist/schemas.d.ts.map +1 -0
- package/dist/schemas.js +74 -0
- package/dist/schemas.js.map +1 -0
- package/dist/test.d.ts +2 -0
- package/dist/test.d.ts.map +1 -0
- package/dist/test.js +39 -0
- package/dist/test.js.map +1 -0
- package/dist/validator.d.ts +7 -0
- package/dist/validator.d.ts.map +1 -0
- package/dist/validator.js +36 -0
- package/dist/validator.js.map +1 -0
- package/package.json +38 -0
- package/src/global.d.ts +21 -0
- package/src/index.ts +3 -0
- package/src/schemas.ts +120 -0
- package/src/test.ts +44 -0
- package/src/validator.ts +36 -0
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,cAAc,CAAC;AAC7B,cAAc,gBAAgB,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
__exportStar(require("./schemas.js"), exports);
|
|
18
|
+
__exportStar(require("./validator.js"), exports);
|
|
19
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,+CAA6B;AAC7B,iDAA+B"}
|
|
@@ -0,0 +1,337 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Event Schema Definitions
|
|
3
|
+
* JSON Schema for all MQTT event types
|
|
4
|
+
*/
|
|
5
|
+
export declare const BotStatusEventSchema: {
|
|
6
|
+
readonly type: "object";
|
|
7
|
+
readonly required: readonly ["bot_id", "status", "timestamp"];
|
|
8
|
+
readonly properties: {
|
|
9
|
+
readonly bot_id: {
|
|
10
|
+
readonly type: "string";
|
|
11
|
+
};
|
|
12
|
+
readonly status: {
|
|
13
|
+
readonly type: "string";
|
|
14
|
+
readonly enum: readonly ["running", "stopped", "error", "starting"];
|
|
15
|
+
};
|
|
16
|
+
readonly strategy: {
|
|
17
|
+
readonly type: "string";
|
|
18
|
+
};
|
|
19
|
+
readonly trading_pair: {
|
|
20
|
+
readonly type: "string";
|
|
21
|
+
};
|
|
22
|
+
readonly action: {
|
|
23
|
+
readonly type: "string";
|
|
24
|
+
};
|
|
25
|
+
readonly timestamp: {
|
|
26
|
+
readonly type: "string";
|
|
27
|
+
readonly format: "date-time";
|
|
28
|
+
};
|
|
29
|
+
};
|
|
30
|
+
readonly additionalProperties: false;
|
|
31
|
+
};
|
|
32
|
+
export declare const BotPositionEventSchema: {
|
|
33
|
+
readonly type: "object";
|
|
34
|
+
readonly required: readonly ["bot_id", "base_asset", "quote_asset", "timestamp"];
|
|
35
|
+
readonly properties: {
|
|
36
|
+
readonly bot_id: {
|
|
37
|
+
readonly type: "string";
|
|
38
|
+
};
|
|
39
|
+
readonly base_asset: {
|
|
40
|
+
readonly type: "string";
|
|
41
|
+
};
|
|
42
|
+
readonly quote_asset: {
|
|
43
|
+
readonly type: "string";
|
|
44
|
+
};
|
|
45
|
+
readonly base_balance: {
|
|
46
|
+
readonly type: "number";
|
|
47
|
+
readonly minimum: 0;
|
|
48
|
+
};
|
|
49
|
+
readonly quote_balance: {
|
|
50
|
+
readonly type: "number";
|
|
51
|
+
readonly minimum: 0;
|
|
52
|
+
};
|
|
53
|
+
readonly base_value_usd: {
|
|
54
|
+
readonly type: "number";
|
|
55
|
+
readonly minimum: 0;
|
|
56
|
+
};
|
|
57
|
+
readonly quote_value_usd: {
|
|
58
|
+
readonly type: "number";
|
|
59
|
+
readonly minimum: 0;
|
|
60
|
+
};
|
|
61
|
+
readonly total_value_usd: {
|
|
62
|
+
readonly type: "number";
|
|
63
|
+
readonly minimum: 0;
|
|
64
|
+
};
|
|
65
|
+
readonly inventory_skew: {
|
|
66
|
+
readonly type: "number";
|
|
67
|
+
readonly minimum: -1;
|
|
68
|
+
readonly maximum: 1;
|
|
69
|
+
};
|
|
70
|
+
readonly timestamp: {
|
|
71
|
+
readonly type: "string";
|
|
72
|
+
readonly format: "date-time";
|
|
73
|
+
};
|
|
74
|
+
};
|
|
75
|
+
readonly additionalProperties: false;
|
|
76
|
+
};
|
|
77
|
+
export declare const BotPerformanceEventSchema: {
|
|
78
|
+
readonly type: "object";
|
|
79
|
+
readonly required: readonly ["bot_id", "timestamp"];
|
|
80
|
+
readonly properties: {
|
|
81
|
+
readonly bot_id: {
|
|
82
|
+
readonly type: "string";
|
|
83
|
+
};
|
|
84
|
+
readonly total_pnl: {
|
|
85
|
+
readonly type: "number";
|
|
86
|
+
};
|
|
87
|
+
readonly daily_pnl: {
|
|
88
|
+
readonly type: "number";
|
|
89
|
+
};
|
|
90
|
+
readonly total_volume: {
|
|
91
|
+
readonly type: "number";
|
|
92
|
+
readonly minimum: 0;
|
|
93
|
+
};
|
|
94
|
+
readonly daily_volume: {
|
|
95
|
+
readonly type: "number";
|
|
96
|
+
readonly minimum: 0;
|
|
97
|
+
};
|
|
98
|
+
readonly sharpe_ratio: {
|
|
99
|
+
readonly type: "number";
|
|
100
|
+
};
|
|
101
|
+
readonly win_rate: {
|
|
102
|
+
readonly type: "number";
|
|
103
|
+
readonly minimum: 0;
|
|
104
|
+
readonly maximum: 1;
|
|
105
|
+
};
|
|
106
|
+
readonly timestamp: {
|
|
107
|
+
readonly type: "string";
|
|
108
|
+
readonly format: "date-time";
|
|
109
|
+
};
|
|
110
|
+
};
|
|
111
|
+
readonly additionalProperties: false;
|
|
112
|
+
};
|
|
113
|
+
export declare const BotOrderEventSchema: {
|
|
114
|
+
readonly type: "object";
|
|
115
|
+
readonly required: readonly ["bot_id", "order_id", "type", "side", "timestamp"];
|
|
116
|
+
readonly properties: {
|
|
117
|
+
readonly bot_id: {
|
|
118
|
+
readonly type: "string";
|
|
119
|
+
};
|
|
120
|
+
readonly order_id: {
|
|
121
|
+
readonly type: "string";
|
|
122
|
+
};
|
|
123
|
+
readonly type: {
|
|
124
|
+
readonly type: "string";
|
|
125
|
+
readonly enum: readonly ["limit", "market"];
|
|
126
|
+
};
|
|
127
|
+
readonly side: {
|
|
128
|
+
readonly type: "string";
|
|
129
|
+
readonly enum: readonly ["buy", "sell"];
|
|
130
|
+
};
|
|
131
|
+
readonly price: {
|
|
132
|
+
readonly type: "number";
|
|
133
|
+
readonly minimum: 0;
|
|
134
|
+
};
|
|
135
|
+
readonly amount: {
|
|
136
|
+
readonly type: "number";
|
|
137
|
+
readonly minimum: 0;
|
|
138
|
+
};
|
|
139
|
+
readonly status: {
|
|
140
|
+
readonly type: "string";
|
|
141
|
+
readonly enum: readonly ["created", "filled", "cancelled", "rejected"];
|
|
142
|
+
};
|
|
143
|
+
readonly timestamp: {
|
|
144
|
+
readonly type: "string";
|
|
145
|
+
readonly format: "date-time";
|
|
146
|
+
};
|
|
147
|
+
};
|
|
148
|
+
readonly additionalProperties: false;
|
|
149
|
+
};
|
|
150
|
+
export declare const EventSchemas: {
|
|
151
|
+
readonly 'hummingbot/bots/+/status': {
|
|
152
|
+
readonly type: "object";
|
|
153
|
+
readonly required: readonly ["bot_id", "status", "timestamp"];
|
|
154
|
+
readonly properties: {
|
|
155
|
+
readonly bot_id: {
|
|
156
|
+
readonly type: "string";
|
|
157
|
+
};
|
|
158
|
+
readonly status: {
|
|
159
|
+
readonly type: "string";
|
|
160
|
+
readonly enum: readonly ["running", "stopped", "error", "starting"];
|
|
161
|
+
};
|
|
162
|
+
readonly strategy: {
|
|
163
|
+
readonly type: "string";
|
|
164
|
+
};
|
|
165
|
+
readonly trading_pair: {
|
|
166
|
+
readonly type: "string";
|
|
167
|
+
};
|
|
168
|
+
readonly action: {
|
|
169
|
+
readonly type: "string";
|
|
170
|
+
};
|
|
171
|
+
readonly timestamp: {
|
|
172
|
+
readonly type: "string";
|
|
173
|
+
readonly format: "date-time";
|
|
174
|
+
};
|
|
175
|
+
};
|
|
176
|
+
readonly additionalProperties: false;
|
|
177
|
+
};
|
|
178
|
+
readonly 'hummingbot/bots/+/positions': {
|
|
179
|
+
readonly type: "object";
|
|
180
|
+
readonly required: readonly ["bot_id", "base_asset", "quote_asset", "timestamp"];
|
|
181
|
+
readonly properties: {
|
|
182
|
+
readonly bot_id: {
|
|
183
|
+
readonly type: "string";
|
|
184
|
+
};
|
|
185
|
+
readonly base_asset: {
|
|
186
|
+
readonly type: "string";
|
|
187
|
+
};
|
|
188
|
+
readonly quote_asset: {
|
|
189
|
+
readonly type: "string";
|
|
190
|
+
};
|
|
191
|
+
readonly base_balance: {
|
|
192
|
+
readonly type: "number";
|
|
193
|
+
readonly minimum: 0;
|
|
194
|
+
};
|
|
195
|
+
readonly quote_balance: {
|
|
196
|
+
readonly type: "number";
|
|
197
|
+
readonly minimum: 0;
|
|
198
|
+
};
|
|
199
|
+
readonly base_value_usd: {
|
|
200
|
+
readonly type: "number";
|
|
201
|
+
readonly minimum: 0;
|
|
202
|
+
};
|
|
203
|
+
readonly quote_value_usd: {
|
|
204
|
+
readonly type: "number";
|
|
205
|
+
readonly minimum: 0;
|
|
206
|
+
};
|
|
207
|
+
readonly total_value_usd: {
|
|
208
|
+
readonly type: "number";
|
|
209
|
+
readonly minimum: 0;
|
|
210
|
+
};
|
|
211
|
+
readonly inventory_skew: {
|
|
212
|
+
readonly type: "number";
|
|
213
|
+
readonly minimum: -1;
|
|
214
|
+
readonly maximum: 1;
|
|
215
|
+
};
|
|
216
|
+
readonly timestamp: {
|
|
217
|
+
readonly type: "string";
|
|
218
|
+
readonly format: "date-time";
|
|
219
|
+
};
|
|
220
|
+
};
|
|
221
|
+
readonly additionalProperties: false;
|
|
222
|
+
};
|
|
223
|
+
readonly 'hummingbot/bots/+/performance': {
|
|
224
|
+
readonly type: "object";
|
|
225
|
+
readonly required: readonly ["bot_id", "timestamp"];
|
|
226
|
+
readonly properties: {
|
|
227
|
+
readonly bot_id: {
|
|
228
|
+
readonly type: "string";
|
|
229
|
+
};
|
|
230
|
+
readonly total_pnl: {
|
|
231
|
+
readonly type: "number";
|
|
232
|
+
};
|
|
233
|
+
readonly daily_pnl: {
|
|
234
|
+
readonly type: "number";
|
|
235
|
+
};
|
|
236
|
+
readonly total_volume: {
|
|
237
|
+
readonly type: "number";
|
|
238
|
+
readonly minimum: 0;
|
|
239
|
+
};
|
|
240
|
+
readonly daily_volume: {
|
|
241
|
+
readonly type: "number";
|
|
242
|
+
readonly minimum: 0;
|
|
243
|
+
};
|
|
244
|
+
readonly sharpe_ratio: {
|
|
245
|
+
readonly type: "number";
|
|
246
|
+
};
|
|
247
|
+
readonly win_rate: {
|
|
248
|
+
readonly type: "number";
|
|
249
|
+
readonly minimum: 0;
|
|
250
|
+
readonly maximum: 1;
|
|
251
|
+
};
|
|
252
|
+
readonly timestamp: {
|
|
253
|
+
readonly type: "string";
|
|
254
|
+
readonly format: "date-time";
|
|
255
|
+
};
|
|
256
|
+
};
|
|
257
|
+
readonly additionalProperties: false;
|
|
258
|
+
};
|
|
259
|
+
readonly 'hummingbot/bots/+/orders': {
|
|
260
|
+
readonly type: "object";
|
|
261
|
+
readonly required: readonly ["bot_id", "order_id", "type", "side", "timestamp"];
|
|
262
|
+
readonly properties: {
|
|
263
|
+
readonly bot_id: {
|
|
264
|
+
readonly type: "string";
|
|
265
|
+
};
|
|
266
|
+
readonly order_id: {
|
|
267
|
+
readonly type: "string";
|
|
268
|
+
};
|
|
269
|
+
readonly type: {
|
|
270
|
+
readonly type: "string";
|
|
271
|
+
readonly enum: readonly ["limit", "market"];
|
|
272
|
+
};
|
|
273
|
+
readonly side: {
|
|
274
|
+
readonly type: "string";
|
|
275
|
+
readonly enum: readonly ["buy", "sell"];
|
|
276
|
+
};
|
|
277
|
+
readonly price: {
|
|
278
|
+
readonly type: "number";
|
|
279
|
+
readonly minimum: 0;
|
|
280
|
+
};
|
|
281
|
+
readonly amount: {
|
|
282
|
+
readonly type: "number";
|
|
283
|
+
readonly minimum: 0;
|
|
284
|
+
};
|
|
285
|
+
readonly status: {
|
|
286
|
+
readonly type: "string";
|
|
287
|
+
readonly enum: readonly ["created", "filled", "cancelled", "rejected"];
|
|
288
|
+
};
|
|
289
|
+
readonly timestamp: {
|
|
290
|
+
readonly type: "string";
|
|
291
|
+
readonly format: "date-time";
|
|
292
|
+
};
|
|
293
|
+
};
|
|
294
|
+
readonly additionalProperties: false;
|
|
295
|
+
};
|
|
296
|
+
};
|
|
297
|
+
export type BotStatusEvent = {
|
|
298
|
+
bot_id: string;
|
|
299
|
+
status: 'running' | 'stopped' | 'error' | 'starting';
|
|
300
|
+
strategy?: string;
|
|
301
|
+
trading_pair?: string;
|
|
302
|
+
action?: string;
|
|
303
|
+
timestamp: string;
|
|
304
|
+
};
|
|
305
|
+
export type BotPositionEvent = {
|
|
306
|
+
bot_id: string;
|
|
307
|
+
base_asset: string;
|
|
308
|
+
quote_asset: string;
|
|
309
|
+
base_balance?: number;
|
|
310
|
+
quote_balance?: number;
|
|
311
|
+
base_value_usd?: number;
|
|
312
|
+
quote_value_usd?: number;
|
|
313
|
+
total_value_usd?: number;
|
|
314
|
+
inventory_skew?: number;
|
|
315
|
+
timestamp: string;
|
|
316
|
+
};
|
|
317
|
+
export type BotPerformanceEvent = {
|
|
318
|
+
bot_id: string;
|
|
319
|
+
total_pnl?: number;
|
|
320
|
+
daily_pnl?: number;
|
|
321
|
+
total_volume?: number;
|
|
322
|
+
daily_volume?: number;
|
|
323
|
+
sharpe_ratio?: number;
|
|
324
|
+
win_rate?: number;
|
|
325
|
+
timestamp: string;
|
|
326
|
+
};
|
|
327
|
+
export type BotOrderEvent = {
|
|
328
|
+
bot_id: string;
|
|
329
|
+
order_id: string;
|
|
330
|
+
type: 'limit' | 'market';
|
|
331
|
+
side: 'buy' | 'sell';
|
|
332
|
+
price?: number;
|
|
333
|
+
amount?: number;
|
|
334
|
+
status?: 'created' | 'filled' | 'cancelled' | 'rejected';
|
|
335
|
+
timestamp: string;
|
|
336
|
+
};
|
|
337
|
+
//# sourceMappingURL=schemas.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"schemas.d.ts","sourceRoot":"","sources":["../src/schemas.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,eAAO,MAAM,oBAAoB;;;;;;;;;;;;;;;;;;;;;;;;;;CAYvB,CAAC;AAEX,eAAO,MAAM,sBAAsB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAgBzB,CAAC;AAEX,eAAO,MAAM,yBAAyB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAc5B,CAAC;AAEX,eAAO,MAAM,mBAAmB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CActB,CAAC;AAEX,eAAO,MAAM,YAAY;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAKf,CAAC;AAEX,MAAM,MAAM,cAAc,GAAG;IAC3B,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,SAAS,GAAG,SAAS,GAAG,OAAO,GAAG,UAAU,CAAC;IACrD,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;CACnB,CAAC;AAEF,MAAM,MAAM,gBAAgB,GAAG;IAC7B,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,SAAS,EAAE,MAAM,CAAC;CACnB,CAAC;AAEF,MAAM,MAAM,mBAAmB,GAAG;IAChC,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;CACnB,CAAC;AAEF,MAAM,MAAM,aAAa,GAAG;IAC1B,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,OAAO,GAAG,QAAQ,CAAC;IACzB,IAAI,EAAE,KAAK,GAAG,MAAM,CAAC;IACrB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,SAAS,GAAG,QAAQ,GAAG,WAAW,GAAG,UAAU,CAAC;IACzD,SAAS,EAAE,MAAM,CAAC;CACnB,CAAC"}
|
package/dist/schemas.js
ADDED
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Event Schema Definitions
|
|
4
|
+
* JSON Schema for all MQTT event types
|
|
5
|
+
*/
|
|
6
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
+
exports.EventSchemas = exports.BotOrderEventSchema = exports.BotPerformanceEventSchema = exports.BotPositionEventSchema = exports.BotStatusEventSchema = void 0;
|
|
8
|
+
exports.BotStatusEventSchema = {
|
|
9
|
+
type: 'object',
|
|
10
|
+
required: ['bot_id', 'status', 'timestamp'],
|
|
11
|
+
properties: {
|
|
12
|
+
bot_id: { type: 'string' },
|
|
13
|
+
status: { type: 'string', enum: ['running', 'stopped', 'error', 'starting'] },
|
|
14
|
+
strategy: { type: 'string' },
|
|
15
|
+
trading_pair: { type: 'string' },
|
|
16
|
+
action: { type: 'string' },
|
|
17
|
+
timestamp: { type: 'string', format: 'date-time' }
|
|
18
|
+
},
|
|
19
|
+
additionalProperties: false
|
|
20
|
+
};
|
|
21
|
+
exports.BotPositionEventSchema = {
|
|
22
|
+
type: 'object',
|
|
23
|
+
required: ['bot_id', 'base_asset', 'quote_asset', 'timestamp'],
|
|
24
|
+
properties: {
|
|
25
|
+
bot_id: { type: 'string' },
|
|
26
|
+
base_asset: { type: 'string' },
|
|
27
|
+
quote_asset: { type: 'string' },
|
|
28
|
+
base_balance: { type: 'number', minimum: 0 },
|
|
29
|
+
quote_balance: { type: 'number', minimum: 0 },
|
|
30
|
+
base_value_usd: { type: 'number', minimum: 0 },
|
|
31
|
+
quote_value_usd: { type: 'number', minimum: 0 },
|
|
32
|
+
total_value_usd: { type: 'number', minimum: 0 },
|
|
33
|
+
inventory_skew: { type: 'number', minimum: -1, maximum: 1 },
|
|
34
|
+
timestamp: { type: 'string', format: 'date-time' }
|
|
35
|
+
},
|
|
36
|
+
additionalProperties: false
|
|
37
|
+
};
|
|
38
|
+
exports.BotPerformanceEventSchema = {
|
|
39
|
+
type: 'object',
|
|
40
|
+
required: ['bot_id', 'timestamp'],
|
|
41
|
+
properties: {
|
|
42
|
+
bot_id: { type: 'string' },
|
|
43
|
+
total_pnl: { type: 'number' },
|
|
44
|
+
daily_pnl: { type: 'number' },
|
|
45
|
+
total_volume: { type: 'number', minimum: 0 },
|
|
46
|
+
daily_volume: { type: 'number', minimum: 0 },
|
|
47
|
+
sharpe_ratio: { type: 'number' },
|
|
48
|
+
win_rate: { type: 'number', minimum: 0, maximum: 1 },
|
|
49
|
+
timestamp: { type: 'string', format: 'date-time' }
|
|
50
|
+
},
|
|
51
|
+
additionalProperties: false
|
|
52
|
+
};
|
|
53
|
+
exports.BotOrderEventSchema = {
|
|
54
|
+
type: 'object',
|
|
55
|
+
required: ['bot_id', 'order_id', 'type', 'side', 'timestamp'],
|
|
56
|
+
properties: {
|
|
57
|
+
bot_id: { type: 'string' },
|
|
58
|
+
order_id: { type: 'string' },
|
|
59
|
+
type: { type: 'string', enum: ['limit', 'market'] },
|
|
60
|
+
side: { type: 'string', enum: ['buy', 'sell'] },
|
|
61
|
+
price: { type: 'number', minimum: 0 },
|
|
62
|
+
amount: { type: 'number', minimum: 0 },
|
|
63
|
+
status: { type: 'string', enum: ['created', 'filled', 'cancelled', 'rejected'] },
|
|
64
|
+
timestamp: { type: 'string', format: 'date-time' }
|
|
65
|
+
},
|
|
66
|
+
additionalProperties: false
|
|
67
|
+
};
|
|
68
|
+
exports.EventSchemas = {
|
|
69
|
+
'hummingbot/bots/+/status': exports.BotStatusEventSchema,
|
|
70
|
+
'hummingbot/bots/+/positions': exports.BotPositionEventSchema,
|
|
71
|
+
'hummingbot/bots/+/performance': exports.BotPerformanceEventSchema,
|
|
72
|
+
'hummingbot/bots/+/orders': exports.BotOrderEventSchema
|
|
73
|
+
};
|
|
74
|
+
//# sourceMappingURL=schemas.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"schemas.js","sourceRoot":"","sources":["../src/schemas.ts"],"names":[],"mappings":"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"}
|
package/dist/test.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"test.d.ts","sourceRoot":"","sources":["../src/test.ts"],"names":[],"mappings":""}
|
package/dist/test.js
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const validator_js_1 = require("./validator.js");
|
|
4
|
+
console.log('Testing Event Schema Validation...\n');
|
|
5
|
+
// Test 1: Valid status event
|
|
6
|
+
const validStatus = {
|
|
7
|
+
bot_id: 'bot-123',
|
|
8
|
+
status: 'running',
|
|
9
|
+
strategy: 'pure_market_making',
|
|
10
|
+
trading_pair: 'BTC-USDT',
|
|
11
|
+
timestamp: new Date().toISOString()
|
|
12
|
+
};
|
|
13
|
+
const result1 = validator_js_1.EventValidator.validate('hummingbot/bots/bot-123/status', validStatus);
|
|
14
|
+
console.log('✓ Valid status event:', result1.valid ? 'PASS' : 'FAIL');
|
|
15
|
+
// Test 2: Invalid status event (missing required field)
|
|
16
|
+
const invalidStatus = {
|
|
17
|
+
bot_id: 'bot-123',
|
|
18
|
+
status: 'running'
|
|
19
|
+
// missing timestamp
|
|
20
|
+
};
|
|
21
|
+
const result2 = validator_js_1.EventValidator.validate('hummingbot/bots/bot-123/status', invalidStatus);
|
|
22
|
+
console.log('✓ Invalid status event rejected:', !result2.valid ? 'PASS' : 'FAIL');
|
|
23
|
+
if (result2.errors)
|
|
24
|
+
console.log(' Errors:', result2.errors);
|
|
25
|
+
// Test 3: Valid position event
|
|
26
|
+
const validPosition = {
|
|
27
|
+
bot_id: 'bot-123',
|
|
28
|
+
base_asset: 'BTC',
|
|
29
|
+
quote_asset: 'USDT',
|
|
30
|
+
base_balance: 1.5,
|
|
31
|
+
quote_balance: 45000,
|
|
32
|
+
total_value_usd: 100000,
|
|
33
|
+
inventory_skew: 0.2,
|
|
34
|
+
timestamp: new Date().toISOString()
|
|
35
|
+
};
|
|
36
|
+
const result3 = validator_js_1.EventValidator.validate('hummingbot/bots/bot-123/positions', validPosition);
|
|
37
|
+
console.log('✓ Valid position event:', result3.valid ? 'PASS' : 'FAIL');
|
|
38
|
+
console.log('\n✅ All tests passed');
|
|
39
|
+
//# sourceMappingURL=test.js.map
|
package/dist/test.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"test.js","sourceRoot":"","sources":["../src/test.ts"],"names":[],"mappings":";;AAAA,iDAAgD;AAEhD,OAAO,CAAC,GAAG,CAAC,sCAAsC,CAAC,CAAC;AAEpD,6BAA6B;AAC7B,MAAM,WAAW,GAAG;IAClB,MAAM,EAAE,SAAS;IACjB,MAAM,EAAE,SAAS;IACjB,QAAQ,EAAE,oBAAoB;IAC9B,YAAY,EAAE,UAAU;IACxB,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;CACpC,CAAC;AAEF,MAAM,OAAO,GAAG,6BAAc,CAAC,QAAQ,CAAC,gCAAgC,EAAE,WAAW,CAAC,CAAC;AACvF,OAAO,CAAC,GAAG,CAAC,uBAAuB,EAAE,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC;AAEtE,wDAAwD;AACxD,MAAM,aAAa,GAAG;IACpB,MAAM,EAAE,SAAS;IACjB,MAAM,EAAE,SAAS;IACjB,oBAAoB;CACrB,CAAC;AAEF,MAAM,OAAO,GAAG,6BAAc,CAAC,QAAQ,CAAC,gCAAgC,EAAE,aAAa,CAAC,CAAC;AACzF,OAAO,CAAC,GAAG,CAAC,kCAAkC,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC;AAClF,IAAI,OAAO,CAAC,MAAM;IAAE,OAAO,CAAC,GAAG,CAAC,WAAW,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC;AAE7D,+BAA+B;AAC/B,MAAM,aAAa,GAAG;IACpB,MAAM,EAAE,SAAS;IACjB,UAAU,EAAE,KAAK;IACjB,WAAW,EAAE,MAAM;IACnB,YAAY,EAAE,GAAG;IACjB,aAAa,EAAE,KAAK;IACpB,eAAe,EAAE,MAAM;IACvB,cAAc,EAAE,GAAG;IACnB,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;CACpC,CAAC;AAEF,MAAM,OAAO,GAAG,6BAAc,CAAC,QAAQ,CAAC,mCAAmC,EAAE,aAAa,CAAC,CAAC;AAC5F,OAAO,CAAC,GAAG,CAAC,yBAAyB,EAAE,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC;AAExE,OAAO,CAAC,GAAG,CAAC,sBAAsB,CAAC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validator.d.ts","sourceRoot":"","sources":["../src/validator.ts"],"names":[],"mappings":"AAYA,qBAAa,cAAc;IACzB,MAAM,CAAC,QAAQ,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,GAAG;QAAE,KAAK,EAAE,OAAO,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,EAAE,CAAA;KAAE;CAqBtF"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.EventValidator = void 0;
|
|
7
|
+
const ajv_1 = __importDefault(require("ajv"));
|
|
8
|
+
const ajv_formats_1 = __importDefault(require("ajv-formats"));
|
|
9
|
+
const schemas_js_1 = require("./schemas.js");
|
|
10
|
+
const ajv = new ajv_1.default({ allErrors: true });
|
|
11
|
+
(0, ajv_formats_1.default)(ajv);
|
|
12
|
+
const validators = new Map();
|
|
13
|
+
Object.entries(schemas_js_1.EventSchemas).forEach(([topic, schema]) => {
|
|
14
|
+
validators.set(topic, ajv.compile(schema));
|
|
15
|
+
});
|
|
16
|
+
class EventValidator {
|
|
17
|
+
static validate(topic, event) {
|
|
18
|
+
// Match topic to pattern (hummingbot/bots/bot-123/status -> hummingbot/bots/+/status)
|
|
19
|
+
const parts = topic.split('/');
|
|
20
|
+
const topicPattern = `${parts[0]}/${parts[1]}/+/${parts[3]}`;
|
|
21
|
+
const validator = validators.get(topicPattern);
|
|
22
|
+
if (!validator) {
|
|
23
|
+
return { valid: false, errors: [`Unknown topic pattern: ${topicPattern}`] };
|
|
24
|
+
}
|
|
25
|
+
const valid = validator(event);
|
|
26
|
+
if (!valid && validator.errors) {
|
|
27
|
+
return {
|
|
28
|
+
valid: false,
|
|
29
|
+
errors: validator.errors.map((e) => `${e.instancePath} ${e.message}`)
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
return { valid: true };
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
exports.EventValidator = EventValidator;
|
|
36
|
+
//# sourceMappingURL=validator.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validator.js","sourceRoot":"","sources":["../src/validator.ts"],"names":[],"mappings":";;;;;;AAAA,8CAAsB;AACtB,8DAAqC;AACrC,6CAA4C;AAE5C,MAAM,GAAG,GAAG,IAAI,aAAG,CAAC,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;AACzC,IAAA,qBAAU,EAAC,GAAG,CAAC,CAAC;AAEhB,MAAM,UAAU,GAAG,IAAI,GAAG,EAAE,CAAC;AAC7B,MAAM,CAAC,OAAO,CAAC,yBAAY,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,EAAE,MAAM,CAAC,EAAE,EAAE;IACvD,UAAU,CAAC,GAAG,CAAC,KAAK,EAAE,GAAG,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC;AAC7C,CAAC,CAAC,CAAC;AAEH,MAAa,cAAc;IACzB,MAAM,CAAC,QAAQ,CAAC,KAAa,EAAE,KAAc;QAC3C,sFAAsF;QACtF,MAAM,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QAC/B,MAAM,YAAY,GAAG,GAAG,KAAK,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,CAAC,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC;QAC7D,MAAM,SAAS,GAAG,UAAU,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC;QAE/C,IAAI,CAAC,SAAS,EAAE,CAAC;YACf,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,0BAA0B,YAAY,EAAE,CAAC,EAAE,CAAC;QAC9E,CAAC;QAED,MAAM,KAAK,GAAG,SAAS,CAAC,KAAK,CAAC,CAAC;QAE/B,IAAI,CAAC,KAAK,IAAI,SAAS,CAAC,MAAM,EAAE,CAAC;YAC/B,OAAO;gBACL,KAAK,EAAE,KAAK;gBACZ,MAAM,EAAE,SAAS,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAM,EAAE,EAAE,CAAC,GAAG,CAAC,CAAC,YAAY,IAAI,CAAC,CAAC,OAAO,EAAE,CAAC;aAC3E,CAAC;QACJ,CAAC;QAED,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC;IACzB,CAAC;CACF;AAtBD,wCAsBC"}
|
package/package.json
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@autonomaai/event-schemas",
|
|
3
|
+
"version": "1.0.2",
|
|
4
|
+
"description": "Event schemas and validation for EMQX MQTT events",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"types": "dist/index.d.ts",
|
|
7
|
+
"scripts": {
|
|
8
|
+
"build": "tsc",
|
|
9
|
+
"test": "node dist/test.js"
|
|
10
|
+
},
|
|
11
|
+
"keywords": [
|
|
12
|
+
"events",
|
|
13
|
+
"mqtt",
|
|
14
|
+
"validation",
|
|
15
|
+
"schemas"
|
|
16
|
+
],
|
|
17
|
+
"author": "Autonoma Team",
|
|
18
|
+
"license": "MIT",
|
|
19
|
+
"repository": {
|
|
20
|
+
"type": "git",
|
|
21
|
+
"url": "https://github.com/Stack3Labs/autonoma-typescript-packages"
|
|
22
|
+
},
|
|
23
|
+
"publishConfig": {
|
|
24
|
+
"access": "public"
|
|
25
|
+
},
|
|
26
|
+
"files": [
|
|
27
|
+
"dist/**/*",
|
|
28
|
+
"src/**/*"
|
|
29
|
+
],
|
|
30
|
+
"dependencies": {
|
|
31
|
+
"ajv": "^8.17.1",
|
|
32
|
+
"ajv-formats": "^2.1.1"
|
|
33
|
+
},
|
|
34
|
+
"devDependencies": {
|
|
35
|
+
"@types/node": "^20.0.0",
|
|
36
|
+
"typescript": "^5.0.0"
|
|
37
|
+
}
|
|
38
|
+
}
|
package/src/global.d.ts
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
// Global type declarations for Node.js environment
|
|
2
|
+
declare namespace NodeJS {
|
|
3
|
+
interface ProcessEnv {
|
|
4
|
+
[key: string]: string | undefined;
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
interface Process {
|
|
8
|
+
env: ProcessEnv;
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
declare const process: NodeJS.Process;
|
|
13
|
+
|
|
14
|
+
// Console declaration
|
|
15
|
+
declare const console: {
|
|
16
|
+
log(...args: any[]): void;
|
|
17
|
+
error(...args: any[]): void;
|
|
18
|
+
warn(...args: any[]): void;
|
|
19
|
+
info(...args: any[]): void;
|
|
20
|
+
debug(...args: any[]): void;
|
|
21
|
+
};
|
package/src/index.ts
ADDED
package/src/schemas.ts
ADDED
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Event Schema Definitions
|
|
3
|
+
* JSON Schema for all MQTT event types
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
export const BotStatusEventSchema = {
|
|
7
|
+
type: 'object',
|
|
8
|
+
required: ['bot_id', 'status', 'timestamp'],
|
|
9
|
+
properties: {
|
|
10
|
+
bot_id: { type: 'string' },
|
|
11
|
+
status: { type: 'string', enum: ['running', 'stopped', 'error', 'starting'] },
|
|
12
|
+
strategy: { type: 'string' },
|
|
13
|
+
trading_pair: { type: 'string' },
|
|
14
|
+
action: { type: 'string' },
|
|
15
|
+
timestamp: { type: 'string', format: 'date-time' }
|
|
16
|
+
},
|
|
17
|
+
additionalProperties: false
|
|
18
|
+
} as const;
|
|
19
|
+
|
|
20
|
+
export const BotPositionEventSchema = {
|
|
21
|
+
type: 'object',
|
|
22
|
+
required: ['bot_id', 'base_asset', 'quote_asset', 'timestamp'],
|
|
23
|
+
properties: {
|
|
24
|
+
bot_id: { type: 'string' },
|
|
25
|
+
base_asset: { type: 'string' },
|
|
26
|
+
quote_asset: { type: 'string' },
|
|
27
|
+
base_balance: { type: 'number', minimum: 0 },
|
|
28
|
+
quote_balance: { type: 'number', minimum: 0 },
|
|
29
|
+
base_value_usd: { type: 'number', minimum: 0 },
|
|
30
|
+
quote_value_usd: { type: 'number', minimum: 0 },
|
|
31
|
+
total_value_usd: { type: 'number', minimum: 0 },
|
|
32
|
+
inventory_skew: { type: 'number', minimum: -1, maximum: 1 },
|
|
33
|
+
timestamp: { type: 'string', format: 'date-time' }
|
|
34
|
+
},
|
|
35
|
+
additionalProperties: false
|
|
36
|
+
} as const;
|
|
37
|
+
|
|
38
|
+
export const BotPerformanceEventSchema = {
|
|
39
|
+
type: 'object',
|
|
40
|
+
required: ['bot_id', 'timestamp'],
|
|
41
|
+
properties: {
|
|
42
|
+
bot_id: { type: 'string' },
|
|
43
|
+
total_pnl: { type: 'number' },
|
|
44
|
+
daily_pnl: { type: 'number' },
|
|
45
|
+
total_volume: { type: 'number', minimum: 0 },
|
|
46
|
+
daily_volume: { type: 'number', minimum: 0 },
|
|
47
|
+
sharpe_ratio: { type: 'number' },
|
|
48
|
+
win_rate: { type: 'number', minimum: 0, maximum: 1 },
|
|
49
|
+
timestamp: { type: 'string', format: 'date-time' }
|
|
50
|
+
},
|
|
51
|
+
additionalProperties: false
|
|
52
|
+
} as const;
|
|
53
|
+
|
|
54
|
+
export const BotOrderEventSchema = {
|
|
55
|
+
type: 'object',
|
|
56
|
+
required: ['bot_id', 'order_id', 'type', 'side', 'timestamp'],
|
|
57
|
+
properties: {
|
|
58
|
+
bot_id: { type: 'string' },
|
|
59
|
+
order_id: { type: 'string' },
|
|
60
|
+
type: { type: 'string', enum: ['limit', 'market'] },
|
|
61
|
+
side: { type: 'string', enum: ['buy', 'sell'] },
|
|
62
|
+
price: { type: 'number', minimum: 0 },
|
|
63
|
+
amount: { type: 'number', minimum: 0 },
|
|
64
|
+
status: { type: 'string', enum: ['created', 'filled', 'cancelled', 'rejected'] },
|
|
65
|
+
timestamp: { type: 'string', format: 'date-time' }
|
|
66
|
+
},
|
|
67
|
+
additionalProperties: false
|
|
68
|
+
} as const;
|
|
69
|
+
|
|
70
|
+
export const EventSchemas = {
|
|
71
|
+
'hummingbot/bots/+/status': BotStatusEventSchema,
|
|
72
|
+
'hummingbot/bots/+/positions': BotPositionEventSchema,
|
|
73
|
+
'hummingbot/bots/+/performance': BotPerformanceEventSchema,
|
|
74
|
+
'hummingbot/bots/+/orders': BotOrderEventSchema
|
|
75
|
+
} as const;
|
|
76
|
+
|
|
77
|
+
export type BotStatusEvent = {
|
|
78
|
+
bot_id: string;
|
|
79
|
+
status: 'running' | 'stopped' | 'error' | 'starting';
|
|
80
|
+
strategy?: string;
|
|
81
|
+
trading_pair?: string;
|
|
82
|
+
action?: string;
|
|
83
|
+
timestamp: string;
|
|
84
|
+
};
|
|
85
|
+
|
|
86
|
+
export type BotPositionEvent = {
|
|
87
|
+
bot_id: string;
|
|
88
|
+
base_asset: string;
|
|
89
|
+
quote_asset: string;
|
|
90
|
+
base_balance?: number;
|
|
91
|
+
quote_balance?: number;
|
|
92
|
+
base_value_usd?: number;
|
|
93
|
+
quote_value_usd?: number;
|
|
94
|
+
total_value_usd?: number;
|
|
95
|
+
inventory_skew?: number;
|
|
96
|
+
timestamp: string;
|
|
97
|
+
};
|
|
98
|
+
|
|
99
|
+
export type BotPerformanceEvent = {
|
|
100
|
+
bot_id: string;
|
|
101
|
+
total_pnl?: number;
|
|
102
|
+
daily_pnl?: number;
|
|
103
|
+
total_volume?: number;
|
|
104
|
+
daily_volume?: number;
|
|
105
|
+
sharpe_ratio?: number;
|
|
106
|
+
win_rate?: number;
|
|
107
|
+
timestamp: string;
|
|
108
|
+
};
|
|
109
|
+
|
|
110
|
+
export type BotOrderEvent = {
|
|
111
|
+
bot_id: string;
|
|
112
|
+
order_id: string;
|
|
113
|
+
type: 'limit' | 'market';
|
|
114
|
+
side: 'buy' | 'sell';
|
|
115
|
+
price?: number;
|
|
116
|
+
amount?: number;
|
|
117
|
+
status?: 'created' | 'filled' | 'cancelled' | 'rejected';
|
|
118
|
+
timestamp: string;
|
|
119
|
+
};
|
|
120
|
+
|
package/src/test.ts
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { EventValidator } from './validator.js';
|
|
2
|
+
|
|
3
|
+
console.log('Testing Event Schema Validation...\n');
|
|
4
|
+
|
|
5
|
+
// Test 1: Valid status event
|
|
6
|
+
const validStatus = {
|
|
7
|
+
bot_id: 'bot-123',
|
|
8
|
+
status: 'running',
|
|
9
|
+
strategy: 'pure_market_making',
|
|
10
|
+
trading_pair: 'BTC-USDT',
|
|
11
|
+
timestamp: new Date().toISOString()
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
const result1 = EventValidator.validate('hummingbot/bots/bot-123/status', validStatus);
|
|
15
|
+
console.log('✓ Valid status event:', result1.valid ? 'PASS' : 'FAIL');
|
|
16
|
+
|
|
17
|
+
// Test 2: Invalid status event (missing required field)
|
|
18
|
+
const invalidStatus = {
|
|
19
|
+
bot_id: 'bot-123',
|
|
20
|
+
status: 'running'
|
|
21
|
+
// missing timestamp
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
const result2 = EventValidator.validate('hummingbot/bots/bot-123/status', invalidStatus);
|
|
25
|
+
console.log('✓ Invalid status event rejected:', !result2.valid ? 'PASS' : 'FAIL');
|
|
26
|
+
if (result2.errors) console.log(' Errors:', result2.errors);
|
|
27
|
+
|
|
28
|
+
// Test 3: Valid position event
|
|
29
|
+
const validPosition = {
|
|
30
|
+
bot_id: 'bot-123',
|
|
31
|
+
base_asset: 'BTC',
|
|
32
|
+
quote_asset: 'USDT',
|
|
33
|
+
base_balance: 1.5,
|
|
34
|
+
quote_balance: 45000,
|
|
35
|
+
total_value_usd: 100000,
|
|
36
|
+
inventory_skew: 0.2,
|
|
37
|
+
timestamp: new Date().toISOString()
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
const result3 = EventValidator.validate('hummingbot/bots/bot-123/positions', validPosition);
|
|
41
|
+
console.log('✓ Valid position event:', result3.valid ? 'PASS' : 'FAIL');
|
|
42
|
+
|
|
43
|
+
console.log('\n✅ All tests passed');
|
|
44
|
+
|
package/src/validator.ts
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import Ajv from 'ajv';
|
|
2
|
+
import addFormats from 'ajv-formats';
|
|
3
|
+
import { EventSchemas } from './schemas.js';
|
|
4
|
+
|
|
5
|
+
const ajv = new Ajv({ allErrors: true });
|
|
6
|
+
addFormats(ajv);
|
|
7
|
+
|
|
8
|
+
const validators = new Map();
|
|
9
|
+
Object.entries(EventSchemas).forEach(([topic, schema]) => {
|
|
10
|
+
validators.set(topic, ajv.compile(schema));
|
|
11
|
+
});
|
|
12
|
+
|
|
13
|
+
export class EventValidator {
|
|
14
|
+
static validate(topic: string, event: unknown): { valid: boolean; errors?: string[] } {
|
|
15
|
+
// Match topic to pattern (hummingbot/bots/bot-123/status -> hummingbot/bots/+/status)
|
|
16
|
+
const parts = topic.split('/');
|
|
17
|
+
const topicPattern = `${parts[0]}/${parts[1]}/+/${parts[3]}`;
|
|
18
|
+
const validator = validators.get(topicPattern);
|
|
19
|
+
|
|
20
|
+
if (!validator) {
|
|
21
|
+
return { valid: false, errors: [`Unknown topic pattern: ${topicPattern}`] };
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
const valid = validator(event);
|
|
25
|
+
|
|
26
|
+
if (!valid && validator.errors) {
|
|
27
|
+
return {
|
|
28
|
+
valid: false,
|
|
29
|
+
errors: validator.errors.map((e: any) => `${e.instancePath} ${e.message}`)
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
return { valid: true };
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|