@glowlabs-org/events-sdk 1.0.3 → 1.0.4
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/README.md +101 -71
- package/dist/admin.d.ts +11 -4
- package/dist/admin.js +18 -24
- package/dist/base-event.d.ts +17 -17
- package/dist/base-event.js +3 -12
- package/dist/emitter.d.ts +5 -4
- package/dist/emitter.js +7 -8
- package/dist/event-registry.d.ts +1 -1
- package/dist/event-registry.js +11 -6
- package/dist/event-types.d.ts +7 -0
- package/dist/event-types.js +9 -0
- package/dist/listener.d.ts +4 -3
- package/dist/listener.js +7 -8
- package/dist/schemas/application-created.v1.js +2 -1
- package/dist/schemas/audit-pfees-paid.v1.js +5 -7
- package/dist/schemas/audit-pfees-paid.v2.js +5 -7
- package/dist/schemas/audit-pushed.v1.js +5 -6
- package/dist/schemas/audit-slashed.v1.js +4 -5
- package/dist/types.d.ts +13 -19
- package/dist/types.js +3 -0
- package/dist/utils.d.ts +11 -1
- package/dist/utils.js +22 -6
- package/dist/zones.d.ts +10 -3
- package/dist/zones.js +14 -4
- package/package.json +1 -1
package/README.md
CHANGED
@@ -26,6 +26,27 @@ The following zones are currently available:
|
|
26
26
|
|
27
27
|
- Use `zoneId: 0` (with `zoneName: "All Zones"`) to listen to all zones. **Emitters must be constructed with a specific zoneId (not 0).**
|
28
28
|
- The SDK types and runtime validation now officially support `zoneId: 0` and `zoneName: "All Zones"` everywhere for listeners, but not for emitters.
|
29
|
+
- **Use the `getZoneId` utility to get the correct zoneId for a given zone name:**
|
30
|
+
|
31
|
+
```ts
|
32
|
+
import { getZoneId } from "@glowlabs-org/events-sdk";
|
33
|
+
const zoneId = getZoneId("CleanGridProject");
|
34
|
+
```
|
35
|
+
|
36
|
+
---
|
37
|
+
|
38
|
+
## 🛠️ Options for Listeners & Emitters
|
39
|
+
|
40
|
+
Both `createGlowEventListener` and `createGlowEventEmitter` accept the following options:
|
41
|
+
|
42
|
+
| Option | Type | Required | Description |
|
43
|
+
| ---------------- | ------ | -------- | ------------------------------------------------------------------ |
|
44
|
+
| `username` | string | Yes | RabbitMQ username |
|
45
|
+
| `password` | string | Yes | RabbitMQ password |
|
46
|
+
| `zoneId` | number | Yes | Zone ID (use `getZoneId("ZoneName")`) |
|
47
|
+
| `queueName` | string | No | (Listener only) Pre-created queue name |
|
48
|
+
| `exchangePrefix` | string | No | Exchange prefix (default: `glow.zone-`) |
|
49
|
+
| `host` | string | No | **RabbitMQ host/port** (default: `turntable.proxy.rlwy.net:50784`) |
|
29
50
|
|
30
51
|
---
|
31
52
|
|
@@ -35,11 +56,29 @@ Currently supported event types and versions:
|
|
35
56
|
|
36
57
|
| Event Name | Version | Payload Type | Description |
|
37
58
|
| --------------------- | ------- | ----------------------------- | -------------------------------------- |
|
38
|
-
| `audit.pushed` |
|
39
|
-
| `audit.slashed` |
|
40
|
-
| `audit.pfees.paid` |
|
41
|
-
| `audit.pfees.paid` |
|
42
|
-
| `application.created` |
|
59
|
+
| `audit.pushed` | "v1" | `AuditPushedV1Payload` | Emitted when an audit is pushed |
|
60
|
+
| `audit.slashed` | "v1" | `AuditSlashedV1Payload` | Emitted when a farm is slashed |
|
61
|
+
| `audit.pfees.paid` | "v1" | `AuditPfeesPaidV1Payload` | Paid (by applicationId) |
|
62
|
+
| `audit.pfees.paid` | "v2" | `AuditPfeesPaidV2Payload` | Paid (by farmId) |
|
63
|
+
| `application.created` | "v1" | `ApplicationCreatedV1Payload` | Emitted when an application is created |
|
64
|
+
|
65
|
+
---
|
66
|
+
|
67
|
+
### Event Types Enum
|
68
|
+
|
69
|
+
The SDK provides a TypeScript constant for all supported event types to ensure type safety and avoid typos:
|
70
|
+
|
71
|
+
```ts
|
72
|
+
import { eventTypes, EventType } from "./src/event-types";
|
73
|
+
|
74
|
+
// Usage example:
|
75
|
+
const myEventType: EventType = eventTypes.auditPushed;
|
76
|
+
```
|
77
|
+
|
78
|
+
- `eventTypes` is a readonly object containing all event type strings.
|
79
|
+
- `EventType` is a TypeScript type representing any valid event type string.
|
80
|
+
|
81
|
+
Use these in your code to avoid hardcoding event names and to benefit from autocompletion and type checking.
|
43
82
|
|
44
83
|
---
|
45
84
|
|
@@ -141,50 +180,65 @@ export interface ApplicationCreatedV1Payload {
|
|
141
180
|
### Listen to Specific Event Types/Versions
|
142
181
|
|
143
182
|
```ts
|
144
|
-
import { createGlowEventListener } from "@glowlabs-org/events-sdk";
|
183
|
+
import { createGlowEventListener, getZoneId } from "@glowlabs-org/events-sdk";
|
145
184
|
|
146
185
|
const listener = createGlowEventListener({
|
147
186
|
username: "listener",
|
148
187
|
password: "your-password-here",
|
149
|
-
zoneId:
|
188
|
+
zoneId: getZoneId("CleanGridProject"),
|
150
189
|
queueName: "my.precreated.queue",
|
190
|
+
host: "my.rabbitmq.host:5672", // Optional: override the default host
|
151
191
|
});
|
152
192
|
|
153
|
-
listener.onEvent("audit.pushed",
|
154
|
-
|
193
|
+
listener.onEvent("audit.pushed", "v1", (event) => {
|
194
|
+
// event: GlowEvent<AuditPushedV1Payload>
|
195
|
+
console.log(
|
196
|
+
"Received audit.pushed v1:",
|
197
|
+
event.payload.farmId,
|
198
|
+
event.zoneId,
|
199
|
+
event.zoneName
|
200
|
+
);
|
155
201
|
});
|
156
202
|
|
157
|
-
listener.onEvent("audit.slashed",
|
158
|
-
|
203
|
+
listener.onEvent("audit.slashed", "v1", (event) => {
|
204
|
+
// event: GlowEvent<AuditSlashedV1Payload>
|
205
|
+
console.log(
|
206
|
+
"Received audit.slashed v1:",
|
207
|
+
event.payload.farmId,
|
208
|
+
event.payload.slasher
|
209
|
+
);
|
159
210
|
});
|
160
211
|
|
161
|
-
listener.onEvent("audit.pfees.paid",
|
212
|
+
listener.onEvent("audit.pfees.paid", "v1", (event) => {
|
213
|
+
// event: GlowEvent<AuditPfeesPaidV1Payload>
|
162
214
|
console.log(
|
163
215
|
"Received audit.pfees.paid v1:",
|
164
|
-
event.applicationId,
|
165
|
-
event.payer,
|
166
|
-
event.amount_12Decimals
|
216
|
+
event.payload.applicationId,
|
217
|
+
event.payload.payer,
|
218
|
+
event.payload.amount_12Decimals
|
167
219
|
);
|
168
220
|
});
|
169
221
|
|
170
|
-
listener.onEvent("audit.pfees.paid",
|
222
|
+
listener.onEvent("audit.pfees.paid", "v2", (event) => {
|
223
|
+
// event: GlowEvent<AuditPfeesPaidV2Payload>
|
171
224
|
console.log(
|
172
225
|
"Received audit.pfees.paid v2:",
|
173
|
-
event.farmId,
|
174
|
-
event.payer,
|
175
|
-
event.amount_12Decimals
|
226
|
+
event.payload.farmId,
|
227
|
+
event.payload.payer,
|
228
|
+
event.payload.amount_12Decimals
|
176
229
|
);
|
177
230
|
});
|
178
231
|
|
179
|
-
listener.onEvent("application.created",
|
232
|
+
listener.onEvent("application.created", "v1", (event) => {
|
233
|
+
// event: GlowEvent<ApplicationCreatedV1Payload>
|
180
234
|
console.log(
|
181
235
|
"Received application.created v1:",
|
182
|
-
event.gcaAddress,
|
183
|
-
event.lat,
|
184
|
-
event.lng,
|
185
|
-
event.estimatedCostOfPowerPerKWh,
|
186
|
-
event.estimatedKWhGeneratedPerYear,
|
187
|
-
event.installerCompanyName
|
236
|
+
event.payload.gcaAddress,
|
237
|
+
event.payload.lat,
|
238
|
+
event.payload.lng,
|
239
|
+
event.payload.estimatedCostOfPowerPerKWh,
|
240
|
+
event.payload.estimatedKWhGeneratedPerYear,
|
241
|
+
event.payload.installerCompanyName
|
188
242
|
);
|
189
243
|
});
|
190
244
|
|
@@ -196,57 +250,62 @@ await listener.start();
|
|
196
250
|
### Emit Events (Admin Only)
|
197
251
|
|
198
252
|
```ts
|
199
|
-
import { createGlowEventEmitter } from "@glowlabs-org/events-sdk";
|
253
|
+
import { createGlowEventEmitter, getZoneId } from "@glowlabs-org/events-sdk";
|
200
254
|
|
201
255
|
// You must construct the emitter with a specific zoneId (not 0)
|
202
256
|
const emitter = createGlowEventEmitter({
|
203
257
|
username: "admin",
|
204
258
|
password: "your-password-here",
|
205
|
-
zoneId:
|
259
|
+
zoneId: getZoneId("CleanGridProject"), // must be a specific zone
|
260
|
+
host: "my.rabbitmq.host:5672", // Optional: override the default host
|
206
261
|
});
|
207
262
|
|
208
263
|
await emitter.emit({
|
209
264
|
eventType: "audit.pushed",
|
210
|
-
schemaVersion:
|
265
|
+
schemaVersion: "v1",
|
211
266
|
payload: {
|
212
267
|
farmId: "0x...",
|
213
268
|
protocolFeeUSDPrice_12Decimals: "...",
|
214
269
|
expectedProduction_12Decimals: "...",
|
270
|
+
txHash: "0x...",
|
215
271
|
},
|
216
272
|
});
|
217
273
|
|
218
274
|
await emitter.emit({
|
219
275
|
eventType: "audit.slashed",
|
220
|
-
schemaVersion:
|
276
|
+
schemaVersion: "v1",
|
221
277
|
payload: {
|
222
278
|
farmId: "0x...",
|
223
279
|
slasher: "0x...",
|
280
|
+
txHash: "0x...",
|
224
281
|
},
|
225
282
|
});
|
226
283
|
|
227
284
|
await emitter.emit({
|
228
285
|
eventType: "audit.pfees.paid",
|
229
|
-
schemaVersion:
|
286
|
+
schemaVersion: "v1",
|
230
287
|
payload: {
|
231
288
|
applicationId: "0x...",
|
232
289
|
payer: "0x...",
|
233
290
|
amount_12Decimals: "1000000000000",
|
291
|
+
txHash: "0x...",
|
234
292
|
},
|
235
293
|
});
|
236
294
|
|
237
295
|
await emitter.emit({
|
238
296
|
eventType: "audit.pfees.paid",
|
239
|
-
schemaVersion:
|
297
|
+
schemaVersion: "v2",
|
240
298
|
payload: {
|
241
299
|
farmId: "0x...",
|
242
300
|
payer: "0x...",
|
243
301
|
amount_12Decimals: "1000000000000",
|
302
|
+
txHash: "0x...",
|
244
303
|
},
|
245
304
|
});
|
246
305
|
|
247
306
|
await emitter.emit({
|
248
307
|
eventType: "application.created",
|
249
|
-
schemaVersion:
|
308
|
+
schemaVersion: "v1",
|
250
309
|
payload: {
|
251
310
|
gcaAddress: "0x...",
|
252
311
|
lat: 45.5017,
|
@@ -264,10 +323,12 @@ await emitter.disconnect();
|
|
264
323
|
>
|
265
324
|
> - The emitter will automatically publish each event to both the global (zone 0) and the specific zone exchange.
|
266
325
|
> - You cannot construct an emitter for zoneId: 0, and you cannot specify zoneId per emit call.
|
326
|
+
> - `schemaVersion` is always a string (e.g., "v1", "v2").
|
327
|
+
> - **You can override the RabbitMQ host using the `host` option. Default is `turntable.proxy.rlwy.net:50784`.**
|
267
328
|
|
268
329
|
### 🌐 Listening to All Zones
|
269
330
|
|
270
|
-
You can listen to **all zones at once** by passing `zoneId: 0` to the listener. **Emitters must always use a specific zone.**
|
331
|
+
You can listen to **all zones at once** by passing `zoneId: 0` and `zoneName: "All Zones"` to the listener. **Emitters must always use a specific zone.**
|
271
332
|
|
272
333
|
#### Listen to All Zones
|
273
334
|
|
@@ -281,47 +342,16 @@ const listener = createGlowEventListener({
|
|
281
342
|
queueName: "my.precreated.queue",
|
282
343
|
});
|
283
344
|
|
284
|
-
listener.onEvent("audit.pushed",
|
285
|
-
console.log("Received audit.pushed v1 from any zone:", event.farmId);
|
286
|
-
});
|
287
|
-
|
288
|
-
listener.onEvent("audit.slashed", 1, (event) => {
|
345
|
+
listener.onEvent("audit.pushed", "v1", (event) => {
|
289
346
|
console.log(
|
290
|
-
"Received audit.
|
291
|
-
event.farmId,
|
292
|
-
event.
|
347
|
+
"Received audit.pushed v1 from any zone:",
|
348
|
+
event.payload.farmId,
|
349
|
+
event.zoneId,
|
350
|
+
event.zoneName
|
293
351
|
);
|
294
352
|
});
|
295
353
|
|
296
|
-
|
297
|
-
console.log(
|
298
|
-
"Received audit.pfees.paid v1 from any zone:",
|
299
|
-
event.applicationId,
|
300
|
-
event.payer,
|
301
|
-
event.amount_12Decimals
|
302
|
-
);
|
303
|
-
});
|
304
|
-
|
305
|
-
listener.onEvent("audit.pfees.paid", 2, (event) => {
|
306
|
-
console.log(
|
307
|
-
"Received audit.pfees.paid v2 from any zone:",
|
308
|
-
event.farmId,
|
309
|
-
event.payer,
|
310
|
-
event.amount_12Decimals
|
311
|
-
);
|
312
|
-
});
|
313
|
-
|
314
|
-
listener.onEvent("application.created", 1, (event) => {
|
315
|
-
console.log(
|
316
|
-
"Received application.created v1 from any zone:",
|
317
|
-
event.gcaAddress,
|
318
|
-
event.lat,
|
319
|
-
event.lng,
|
320
|
-
event.estimatedCostOfPowerPerKWh,
|
321
|
-
event.estimatedKWhGeneratedPerYear,
|
322
|
-
event.installerCompanyName
|
323
|
-
);
|
324
|
-
});
|
354
|
+
// ... other event handlers ...
|
325
355
|
|
326
356
|
await listener.start();
|
327
357
|
// To stop listening:
|
package/dist/admin.d.ts
CHANGED
@@ -8,6 +8,7 @@ export interface CreateAndBindQueueOptions {
|
|
8
8
|
queueOptions?: amqp.Options.AssertQueue;
|
9
9
|
exchangeOptions?: amqp.Options.AssertExchange;
|
10
10
|
routingKey?: string;
|
11
|
+
host?: string;
|
11
12
|
}
|
12
13
|
/**
|
13
14
|
* Create a RabbitMQ topic exchange (admin credentials required).
|
@@ -15,25 +16,31 @@ export interface CreateAndBindQueueOptions {
|
|
15
16
|
* @param options - Connection and exchange options
|
16
17
|
* @returns Promise<void>
|
17
18
|
*/
|
18
|
-
export declare function createExchange({ username, password, exchange, exchangeType, exchangeOptions, }: Omit<CreateAndBindQueueOptions, "queue" | "queueOptions" | "routingKey">
|
19
|
+
export declare function createExchange({ username, password, exchange, exchangeType, exchangeOptions, host, }: Omit<CreateAndBindQueueOptions, "queue" | "queueOptions" | "routingKey"> & {
|
20
|
+
host?: string;
|
21
|
+
}): Promise<void>;
|
19
22
|
/**
|
20
23
|
* Create a RabbitMQ queue and bind it to a topic exchange (admin credentials required).
|
21
24
|
*
|
22
25
|
* @param options - Connection, queue, and exchange options
|
23
26
|
* @returns Promise<void>
|
24
27
|
*/
|
25
|
-
export declare function bindQueueToExchange({ username, password, exchange, queue, exchangeType, queueOptions, exchangeOptions, routingKey, }: CreateAndBindQueueOptions): Promise<void>;
|
28
|
+
export declare function bindQueueToExchange({ username, password, exchange, queue, exchangeType, queueOptions, exchangeOptions, routingKey, host, }: CreateAndBindQueueOptions): Promise<void>;
|
26
29
|
/**
|
27
30
|
* Delete a RabbitMQ exchange (admin credentials required).
|
28
31
|
*
|
29
32
|
* @param options - Connection and exchange options
|
30
33
|
* @returns Promise<void>
|
31
34
|
*/
|
32
|
-
export declare function deleteExchange({ username, password, exchange, }: Omit<CreateAndBindQueueOptions, "queue" | "queueOptions" | "exchangeType" | "exchangeOptions" | "routingKey">
|
35
|
+
export declare function deleteExchange({ username, password, exchange, host, }: Omit<CreateAndBindQueueOptions, "queue" | "queueOptions" | "exchangeType" | "exchangeOptions" | "routingKey"> & {
|
36
|
+
host?: string;
|
37
|
+
}): Promise<void>;
|
33
38
|
/**
|
34
39
|
* Delete a RabbitMQ queue (admin credentials required).
|
35
40
|
*
|
36
41
|
* @param options - Connection and queue options
|
37
42
|
* @returns Promise<void>
|
38
43
|
*/
|
39
|
-
export declare function deleteQueue({ username, password, queue, }: Omit<CreateAndBindQueueOptions, "exchange" | "exchangeType" | "exchangeOptions" | "queueOptions" | "routingKey">
|
44
|
+
export declare function deleteQueue({ username, password, queue, host, }: Omit<CreateAndBindQueueOptions, "exchange" | "exchangeType" | "exchangeOptions" | "queueOptions" | "routingKey"> & {
|
45
|
+
host?: string;
|
46
|
+
}): Promise<void>;
|
package/dist/admin.js
CHANGED
@@ -8,23 +8,17 @@ exports.bindQueueToExchange = bindQueueToExchange;
|
|
8
8
|
exports.deleteExchange = deleteExchange;
|
9
9
|
exports.deleteQueue = deleteQueue;
|
10
10
|
const amqplib_1 = __importDefault(require("amqplib"));
|
11
|
-
|
12
|
-
// Require at least two segments separated by dots, only alphanumerics, dashes, underscores, and dots
|
13
|
-
const pattern = /^[a-zA-Z0-9_-]+(\.[a-zA-Z0-9_-]+)+$/;
|
14
|
-
if (!pattern.test(name)) {
|
15
|
-
throw new Error(`${type} name '${name}' is invalid. Must be dot-separated (e.g., 'glow.zone-1.events').`);
|
16
|
-
}
|
17
|
-
}
|
11
|
+
const utils_1 = require("./utils");
|
18
12
|
/**
|
19
13
|
* Create a RabbitMQ topic exchange (admin credentials required).
|
20
14
|
*
|
21
15
|
* @param options - Connection and exchange options
|
22
16
|
* @returns Promise<void>
|
23
17
|
*/
|
24
|
-
async function createExchange({ username, password, exchange, exchangeType = "topic", exchangeOptions = { durable: true }, }) {
|
25
|
-
validateName(exchange, "exchange");
|
26
|
-
const url =
|
27
|
-
const conn = await amqplib_1.default.connect(url
|
18
|
+
async function createExchange({ username, password, exchange, exchangeType = "topic", exchangeOptions = { durable: true }, host = "turntable.proxy.rlwy.net:50784", }) {
|
19
|
+
(0, utils_1.validateName)(exchange, "exchange");
|
20
|
+
const url = (0, utils_1.buildAmqpUrl)({ username, password, host });
|
21
|
+
const conn = await amqplib_1.default.connect(url);
|
28
22
|
const channel = await conn.createChannel();
|
29
23
|
await channel.assertExchange(exchange, exchangeType, exchangeOptions);
|
30
24
|
await channel.close();
|
@@ -36,11 +30,11 @@ async function createExchange({ username, password, exchange, exchangeType = "to
|
|
36
30
|
* @param options - Connection, queue, and exchange options
|
37
31
|
* @returns Promise<void>
|
38
32
|
*/
|
39
|
-
async function bindQueueToExchange({ username, password, exchange, queue, exchangeType = "topic", queueOptions = { durable: false }, exchangeOptions = { durable: true }, routingKey = "#", }) {
|
40
|
-
validateName(exchange, "exchange");
|
41
|
-
validateName(queue, "queue");
|
42
|
-
const url =
|
43
|
-
const conn = await amqplib_1.default.connect(url
|
33
|
+
async function bindQueueToExchange({ username, password, exchange, queue, exchangeType = "topic", queueOptions = { durable: false }, exchangeOptions = { durable: true }, routingKey = "#", host = "turntable.proxy.rlwy.net:50784", }) {
|
34
|
+
(0, utils_1.validateName)(exchange, "exchange");
|
35
|
+
(0, utils_1.validateName)(queue, "queue");
|
36
|
+
const url = (0, utils_1.buildAmqpUrl)({ username, password, host });
|
37
|
+
const conn = await amqplib_1.default.connect(url);
|
44
38
|
const channel = await conn.createChannel();
|
45
39
|
await channel.assertExchange(exchange, exchangeType, exchangeOptions);
|
46
40
|
await channel.assertQueue(queue, queueOptions);
|
@@ -54,10 +48,10 @@ async function bindQueueToExchange({ username, password, exchange, queue, exchan
|
|
54
48
|
* @param options - Connection and exchange options
|
55
49
|
* @returns Promise<void>
|
56
50
|
*/
|
57
|
-
async function deleteExchange({ username, password, exchange, }) {
|
58
|
-
validateName(exchange, "exchange");
|
59
|
-
const url =
|
60
|
-
const conn = await amqplib_1.default.connect(url
|
51
|
+
async function deleteExchange({ username, password, exchange, host = "turntable.proxy.rlwy.net:50784", }) {
|
52
|
+
(0, utils_1.validateName)(exchange, "exchange");
|
53
|
+
const url = (0, utils_1.buildAmqpUrl)({ username, password, host });
|
54
|
+
const conn = await amqplib_1.default.connect(url);
|
61
55
|
const channel = await conn.createChannel();
|
62
56
|
await channel.deleteExchange(exchange);
|
63
57
|
await channel.close();
|
@@ -69,10 +63,10 @@ async function deleteExchange({ username, password, exchange, }) {
|
|
69
63
|
* @param options - Connection and queue options
|
70
64
|
* @returns Promise<void>
|
71
65
|
*/
|
72
|
-
async function deleteQueue({ username, password, queue, }) {
|
73
|
-
validateName(queue, "queue");
|
74
|
-
const url =
|
75
|
-
const conn = await amqplib_1.default.connect(url
|
66
|
+
async function deleteQueue({ username, password, queue, host = "turntable.proxy.rlwy.net:50784", }) {
|
67
|
+
(0, utils_1.validateName)(queue, "queue");
|
68
|
+
const url = (0, utils_1.buildAmqpUrl)({ username, password, host });
|
69
|
+
const conn = await amqplib_1.default.connect(url);
|
76
70
|
const channel = await conn.createChannel();
|
77
71
|
await channel.deleteQueue(queue);
|
78
72
|
await channel.close();
|
package/dist/base-event.d.ts
CHANGED
@@ -1,64 +1,64 @@
|
|
1
1
|
import { z } from "zod";
|
2
|
-
import {
|
2
|
+
import { EventType } from "./event-types";
|
3
3
|
export declare const baseEventZ: z.ZodObject<{
|
4
4
|
id: z.ZodString;
|
5
5
|
zoneId: z.ZodEffects<z.ZodNumber, number, number>;
|
6
6
|
zoneName: z.ZodEnum<[string, ...string[]]>;
|
7
|
-
schemaVersion: z.
|
8
|
-
eventType: z.ZodEnum<[
|
7
|
+
schemaVersion: z.ZodEnum<["v1", "v2"]>;
|
8
|
+
eventType: z.ZodEnum<[EventType, ...EventType[]]>;
|
9
9
|
timeStamp: z.ZodNumber;
|
10
10
|
}, "strip", z.ZodTypeAny, {
|
11
11
|
id: string;
|
12
12
|
zoneId: number;
|
13
13
|
zoneName: string;
|
14
|
-
schemaVersion:
|
15
|
-
eventType:
|
14
|
+
schemaVersion: "v1" | "v2";
|
15
|
+
eventType: EventType;
|
16
16
|
timeStamp: number;
|
17
17
|
}, {
|
18
18
|
id: string;
|
19
19
|
zoneId: number;
|
20
20
|
zoneName: string;
|
21
|
-
schemaVersion:
|
22
|
-
eventType:
|
21
|
+
schemaVersion: "v1" | "v2";
|
22
|
+
eventType: EventType;
|
23
23
|
timeStamp: number;
|
24
24
|
}>;
|
25
25
|
export interface BaseEventAuditPushedV1 {
|
26
26
|
id: string;
|
27
27
|
zoneId: number;
|
28
|
-
zoneName:
|
29
|
-
schemaVersion:
|
28
|
+
zoneName: string;
|
29
|
+
schemaVersion: "v1";
|
30
30
|
eventType: "audit.pushed";
|
31
31
|
timeStamp: number;
|
32
32
|
}
|
33
33
|
export interface BaseEventAuditSlashedV1 {
|
34
34
|
id: string;
|
35
35
|
zoneId: number;
|
36
|
-
zoneName:
|
37
|
-
schemaVersion:
|
36
|
+
zoneName: string;
|
37
|
+
schemaVersion: "v1";
|
38
38
|
eventType: "audit.slashed";
|
39
39
|
timeStamp: number;
|
40
40
|
}
|
41
41
|
export interface BaseEventAuditPfeesPaidV1 {
|
42
42
|
id: string;
|
43
43
|
zoneId: number;
|
44
|
-
zoneName:
|
45
|
-
schemaVersion:
|
44
|
+
zoneName: string;
|
45
|
+
schemaVersion: "v1";
|
46
46
|
eventType: "audit.pfees.paid";
|
47
47
|
timeStamp: number;
|
48
48
|
}
|
49
49
|
export interface BaseEventAuditPfeesPaidV2 {
|
50
50
|
id: string;
|
51
51
|
zoneId: number;
|
52
|
-
zoneName:
|
53
|
-
schemaVersion:
|
52
|
+
zoneName: string;
|
53
|
+
schemaVersion: "v2";
|
54
54
|
eventType: "audit.pfees.paid";
|
55
55
|
timeStamp: number;
|
56
56
|
}
|
57
57
|
export interface BaseEventApplicationCreatedV1 {
|
58
58
|
id: string;
|
59
59
|
zoneId: number;
|
60
|
-
zoneName:
|
61
|
-
schemaVersion:
|
60
|
+
zoneName: string;
|
61
|
+
schemaVersion: "v1";
|
62
62
|
eventType: "application.created";
|
63
63
|
timeStamp: number;
|
64
64
|
}
|
package/dist/base-event.js
CHANGED
@@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.baseEventZ = void 0;
|
4
4
|
const zod_1 = require("zod");
|
5
5
|
const zones_1 = require("./zones");
|
6
|
+
const event_types_1 = require("./event-types");
|
6
7
|
const zoneIdNumbers = Object.keys(zones_1.zoneMap).map(Number);
|
7
8
|
const zoneNames = Object.values(zones_1.zoneMap);
|
8
9
|
exports.baseEventZ = zod_1.z.object({
|
@@ -11,17 +12,7 @@ exports.baseEventZ = zod_1.z.object({
|
|
11
12
|
message: "Invalid zoneId",
|
12
13
|
}),
|
13
14
|
zoneName: zod_1.z.enum(zoneNames),
|
14
|
-
schemaVersion: zod_1.z
|
15
|
-
|
16
|
-
.int()
|
17
|
-
.refine((v) => v === 1 || v === 2, {
|
18
|
-
message: "Invalid schemaVersion",
|
19
|
-
}),
|
20
|
-
eventType: zod_1.z.enum([
|
21
|
-
"audit.pushed",
|
22
|
-
"audit.slashed",
|
23
|
-
"audit.pfees.paid",
|
24
|
-
"application.created",
|
25
|
-
]),
|
15
|
+
schemaVersion: zod_1.z.enum(["v1", "v2"]),
|
16
|
+
eventType: zod_1.z.enum(Object.values(event_types_1.eventTypes)),
|
26
17
|
timeStamp: zod_1.z.number().int(),
|
27
18
|
});
|
package/dist/emitter.d.ts
CHANGED
@@ -1,17 +1,18 @@
|
|
1
|
-
import { EventPayload,
|
1
|
+
import type { EventPayload, EventPayloadMap, EventType } from "./types";
|
2
2
|
interface CreateGlowEventEmitterOptions {
|
3
3
|
username: string;
|
4
4
|
password: string;
|
5
5
|
zoneId: number;
|
6
6
|
exchangePrefix?: string;
|
7
|
+
host?: string;
|
7
8
|
}
|
8
|
-
interface EmitEventArgs<T extends EventType, V extends
|
9
|
+
interface EmitEventArgs<T extends EventType, V extends keyof EventPayloadMap[T]> {
|
9
10
|
eventType: T;
|
10
11
|
schemaVersion: V;
|
11
12
|
payload: EventPayload<T, V>;
|
12
13
|
}
|
13
|
-
export declare function createGlowEventEmitter({ username, password, zoneId, exchangePrefix, }: CreateGlowEventEmitterOptions): {
|
14
|
-
emit: <T extends EventType, V extends
|
14
|
+
export declare function createGlowEventEmitter({ username, password, zoneId, exchangePrefix, host, }: CreateGlowEventEmitterOptions): {
|
15
|
+
emit: <T extends EventType, V extends keyof import("./types").EventPayloadMap[T]>(args: EmitEventArgs<T, V>) => Promise<void>;
|
15
16
|
disconnect: () => Promise<void>;
|
16
17
|
};
|
17
18
|
export {};
|
package/dist/emitter.js
CHANGED
@@ -8,19 +8,18 @@ const amqplib_1 = __importDefault(require("amqplib"));
|
|
8
8
|
const utils_1 = require("./utils");
|
9
9
|
const uuid_1 = require("uuid");
|
10
10
|
const zones_1 = require("./zones");
|
11
|
-
function createGlowEventEmitter({ username, password, zoneId, exchangePrefix = "glow.zone-", }) {
|
11
|
+
function createGlowEventEmitter({ username, password, zoneId, exchangePrefix = "glow.zone-", host = "turntable.proxy.rlwy.net:50784", }) {
|
12
12
|
let amqpConnection = null;
|
13
13
|
let amqpChannel = null;
|
14
14
|
// Exchanges for global and specific zone
|
15
15
|
const globalExchangeName = `${exchangePrefix}0.events`;
|
16
16
|
const zoneExchangeName = `${exchangePrefix}${zoneId}.events`;
|
17
|
-
function
|
18
|
-
|
19
|
-
return url.toString();
|
17
|
+
function buildUrl() {
|
18
|
+
return (0, utils_1.buildAmqpUrl)({ username, password, host });
|
20
19
|
}
|
21
20
|
async function connectIfNeeded() {
|
22
21
|
if (!amqpConnection) {
|
23
|
-
amqpConnection = (await amqplib_1.default.connect(
|
22
|
+
amqpConnection = (await amqplib_1.default.connect(buildUrl()));
|
24
23
|
amqpChannel = (await amqpConnection.createChannel());
|
25
24
|
}
|
26
25
|
if (amqpChannel) {
|
@@ -34,7 +33,7 @@ function createGlowEventEmitter({ username, password, zoneId, exchangePrefix = "
|
|
34
33
|
}
|
35
34
|
async function emit(args) {
|
36
35
|
const { eventType, schemaVersion, payload } = args;
|
37
|
-
const zoneName = zones_1.zoneMap[
|
36
|
+
const zoneName = zones_1.zoneMap[zoneId];
|
38
37
|
if (!zoneName)
|
39
38
|
throw new Error(`Invalid zoneId: ${zoneId}`);
|
40
39
|
if (zoneId === 0)
|
@@ -49,8 +48,8 @@ function createGlowEventEmitter({ username, password, zoneId, exchangePrefix = "
|
|
49
48
|
payload,
|
50
49
|
};
|
51
50
|
(0, utils_1.validateZoneNameAndId)(event.zoneId, event.zoneName);
|
52
|
-
(0, utils_1.validateEventPayload)(event.eventType,
|
53
|
-
const routingKey = `${event.eventType}
|
51
|
+
(0, utils_1.validateEventPayload)(event.eventType, schemaVersion, event);
|
52
|
+
const routingKey = `${event.eventType}.${event.schemaVersion.toString()}`;
|
54
53
|
await connectIfNeeded();
|
55
54
|
// Emit to both the global and the specific zone exchange
|
56
55
|
amqpChannel.publish(globalExchangeName, routingKey, Buffer.from(JSON.stringify(event)), { persistent: true });
|
package/dist/event-registry.d.ts
CHANGED
@@ -1,2 +1,2 @@
|
|
1
1
|
import { z } from "zod";
|
2
|
-
export declare function getEventSchema(eventType: string, version:
|
2
|
+
export declare function getEventSchema(eventType: string, version: "v1" | "v2"): z.ZodTypeAny;
|
package/dist/event-registry.js
CHANGED
@@ -7,21 +7,26 @@ const audit_pfees_paid_v1_1 = require("./schemas/audit-pfees-paid.v1");
|
|
7
7
|
const audit_pfees_paid_v2_1 = require("./schemas/audit-pfees-paid.v2");
|
8
8
|
const base_event_1 = require("./base-event");
|
9
9
|
const application_created_v1_1 = require("./schemas/application-created.v1");
|
10
|
+
const event_types_1 = require("./event-types");
|
10
11
|
const eventTypeRegistry = {
|
11
|
-
|
12
|
-
|
13
|
-
|
12
|
+
[`${event_types_1.eventTypes.auditPushed}:v1`]: base_event_1.baseEventZ.extend({
|
13
|
+
payload: audit_pushed_v1_1.auditPushedV1PayloadZ,
|
14
|
+
}),
|
15
|
+
[`${event_types_1.eventTypes.auditSlashed}:v1`]: base_event_1.baseEventZ.extend({
|
16
|
+
payload: audit_slashed_v1_1.auditSlashedV1PayloadZ,
|
17
|
+
}),
|
18
|
+
[`${event_types_1.eventTypes.auditPfeesPaid}:v1`]: base_event_1.baseEventZ.extend({
|
14
19
|
payload: audit_pfees_paid_v1_1.auditPfeesPaidV1PayloadZ,
|
15
20
|
}),
|
16
|
-
|
21
|
+
[`${event_types_1.eventTypes.auditPfeesPaid}:v2`]: base_event_1.baseEventZ.extend({
|
17
22
|
payload: audit_pfees_paid_v2_1.auditPfeesPaidV2PayloadZ,
|
18
23
|
}),
|
19
|
-
|
24
|
+
[`${event_types_1.eventTypes.applicationCreated}:v1`]: base_event_1.baseEventZ.extend({
|
20
25
|
payload: application_created_v1_1.applicationCreatedV1PayloadZ,
|
21
26
|
}),
|
22
27
|
// Add more event types/versions here
|
23
28
|
};
|
24
29
|
function getEventSchema(eventType, version) {
|
25
|
-
const key = `${eventType}
|
30
|
+
const key = `${eventType}:${version}`;
|
26
31
|
return eventTypeRegistry[key];
|
27
32
|
}
|
@@ -0,0 +1,7 @@
|
|
1
|
+
export declare const eventTypes: {
|
2
|
+
readonly auditPushed: "audit.pushed";
|
3
|
+
readonly auditSlashed: "audit.slashed";
|
4
|
+
readonly auditPfeesPaid: "audit.pfees.paid";
|
5
|
+
readonly applicationCreated: "application.created";
|
6
|
+
};
|
7
|
+
export type EventType = (typeof eventTypes)[keyof typeof eventTypes];
|
@@ -0,0 +1,9 @@
|
|
1
|
+
"use strict";
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
3
|
+
exports.eventTypes = void 0;
|
4
|
+
exports.eventTypes = {
|
5
|
+
auditPushed: "audit.pushed",
|
6
|
+
auditSlashed: "audit.slashed",
|
7
|
+
auditPfeesPaid: "audit.pfees.paid",
|
8
|
+
applicationCreated: "application.created",
|
9
|
+
};
|
package/dist/listener.d.ts
CHANGED
@@ -1,13 +1,14 @@
|
|
1
|
-
import type { EventType,
|
1
|
+
import type { EventType, EventPayload, EventPayloadMap, GlowEvent } from "./types";
|
2
2
|
interface CreateGlowEventListenerOptions {
|
3
3
|
username: string;
|
4
4
|
password: string;
|
5
5
|
zoneId: number;
|
6
6
|
queueName?: string;
|
7
7
|
exchangePrefix?: string;
|
8
|
+
host?: string;
|
8
9
|
}
|
9
|
-
export declare function createGlowEventListener({ username, password, zoneId, queueName, exchangePrefix, }: CreateGlowEventListenerOptions): {
|
10
|
-
onEvent: <T extends EventType, V extends
|
10
|
+
export declare function createGlowEventListener({ username, password, zoneId, queueName, exchangePrefix, host, }: CreateGlowEventListenerOptions): {
|
11
|
+
onEvent: <T extends EventType, V extends keyof EventPayloadMap[T]>(eventType: T, schemaVersion: V, handler: (event: GlowEvent<EventPayload<T, V>>) => void) => void;
|
11
12
|
start: () => Promise<void>;
|
12
13
|
stop: () => Promise<void>;
|
13
14
|
};
|
package/dist/listener.js
CHANGED
@@ -7,7 +7,7 @@ exports.createGlowEventListener = createGlowEventListener;
|
|
7
7
|
const amqplib_1 = __importDefault(require("amqplib"));
|
8
8
|
const event_registry_1 = require("./event-registry");
|
9
9
|
const utils_1 = require("./utils");
|
10
|
-
function createGlowEventListener({ username, password, zoneId, queueName, exchangePrefix = "glow.zone-", }) {
|
10
|
+
function createGlowEventListener({ username, password, zoneId, queueName, exchangePrefix = "glow.zone-", host = "turntable.proxy.rlwy.net:50784", }) {
|
11
11
|
let amqpConnection = null;
|
12
12
|
let amqpChannel = null;
|
13
13
|
let internalQueueName;
|
@@ -15,13 +15,12 @@ function createGlowEventListener({ username, password, zoneId, queueName, exchan
|
|
15
15
|
// Use a special exchange for all zones if zoneId is 0
|
16
16
|
const exchangeName = `${exchangePrefix}${zoneId}.events`;
|
17
17
|
const eventHandlers = [];
|
18
|
-
function
|
19
|
-
|
20
|
-
return url.toString();
|
18
|
+
function buildUrl() {
|
19
|
+
return (0, utils_1.buildAmqpUrl)({ username, password, host });
|
21
20
|
}
|
22
21
|
async function connectIfNeeded(bindingPattern) {
|
23
22
|
if (!amqpConnection) {
|
24
|
-
amqpConnection = (await amqplib_1.default.connect(
|
23
|
+
amqpConnection = (await amqplib_1.default.connect(buildUrl()));
|
25
24
|
amqpChannel = (await amqpConnection.createChannel());
|
26
25
|
}
|
27
26
|
if (amqpChannel) {
|
@@ -39,7 +38,7 @@ function createGlowEventListener({ username, password, zoneId, queueName, exchan
|
|
39
38
|
}
|
40
39
|
}
|
41
40
|
function onEvent(eventType, schemaVersion, handler) {
|
42
|
-
const bindingPattern = `${String(eventType)}
|
41
|
+
const bindingPattern = `${String(eventType)}.${String(schemaVersion)}`;
|
43
42
|
eventHandlers.push({
|
44
43
|
bindingPattern,
|
45
44
|
handler: (event, meta) => handler(event),
|
@@ -56,11 +55,11 @@ function createGlowEventListener({ username, password, zoneId, queueName, exchan
|
|
56
55
|
try {
|
57
56
|
const decoded = JSON.parse(msg.content.toString());
|
58
57
|
const [eventType, versionStr] = msg.fields.routingKey.split(".v");
|
59
|
-
const schemaVersion =
|
58
|
+
const schemaVersion = `v${versionStr}`;
|
60
59
|
(0, utils_1.validateZoneNameAndId)(decoded.zoneId, decoded.zoneName);
|
61
60
|
(0, utils_1.validateEventPayload)(eventType, schemaVersion, decoded);
|
62
61
|
const event = (0, event_registry_1.getEventSchema)(eventType, schemaVersion).parse(decoded);
|
63
|
-
const handlerEntry = eventHandlers.find((h) => h.bindingPattern === `${eventType}
|
62
|
+
const handlerEntry = eventHandlers.find((h) => h.bindingPattern === `${eventType}.${schemaVersion}`);
|
64
63
|
if (handlerEntry)
|
65
64
|
handlerEntry.handler(event, { eventType, schemaVersion });
|
66
65
|
amqpChannel.ack(msg);
|
@@ -2,8 +2,9 @@
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
3
3
|
exports.applicationCreatedV1PayloadZ = void 0;
|
4
4
|
const zod_1 = require("zod");
|
5
|
+
const utils_1 = require("../utils");
|
5
6
|
exports.applicationCreatedV1PayloadZ = zod_1.z.object({
|
6
|
-
gcaAddress: zod_1.z.string().regex(
|
7
|
+
gcaAddress: zod_1.z.string().regex(utils_1.ethAddress), // eth address
|
7
8
|
lat: zod_1.z.number(),
|
8
9
|
lng: zod_1.z.number(),
|
9
10
|
estimatedCostOfPowerPerKWh: zod_1.z.number(),
|
@@ -2,14 +2,12 @@
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
3
3
|
exports.auditPfeesPaidV1PayloadZ = void 0;
|
4
4
|
const zod_1 = require("zod");
|
5
|
-
const
|
6
|
-
const ethAddress = /^0x[0-9a-fA-F]{40}$/;
|
7
|
-
const uint256 = /^[0-9]+$/;
|
5
|
+
const utils_1 = require("../utils");
|
8
6
|
exports.auditPfeesPaidV1PayloadZ = zod_1.z.object({
|
9
|
-
applicationId: zod_1.z.string().regex(hexBytes32, "bytes32 hex string"),
|
10
|
-
payer: zod_1.z.string().regex(ethAddress, "Ethereum address"),
|
7
|
+
applicationId: zod_1.z.string().regex(utils_1.hexBytes32, "bytes32 hex string"),
|
8
|
+
payer: zod_1.z.string().regex(utils_1.ethAddress, "Ethereum address"),
|
11
9
|
amount_12Decimals: zod_1.z
|
12
10
|
.string()
|
13
|
-
.regex(uint256, "uint256 (decimal) − 12 implied decimals"),
|
14
|
-
txHash: zod_1.z.string().regex(hexBytes32, "bytes32 hex string"),
|
11
|
+
.regex(utils_1.uint256, "uint256 (decimal) − 12 implied decimals"),
|
12
|
+
txHash: zod_1.z.string().regex(utils_1.hexBytes32, "bytes32 hex string"),
|
15
13
|
});
|
@@ -2,14 +2,12 @@
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
3
3
|
exports.auditPfeesPaidV2PayloadZ = void 0;
|
4
4
|
const zod_1 = require("zod");
|
5
|
-
const
|
6
|
-
const ethAddress = /^0x[0-9a-fA-F]{40}$/;
|
7
|
-
const uint256 = /^[0-9]+$/;
|
5
|
+
const utils_1 = require("../utils");
|
8
6
|
exports.auditPfeesPaidV2PayloadZ = zod_1.z.object({
|
9
|
-
farmId: zod_1.z.string().regex(hexBytes32, "bytes32 hex string"),
|
10
|
-
payer: zod_1.z.string().regex(ethAddress, "Ethereum address"),
|
7
|
+
farmId: zod_1.z.string().regex(utils_1.hexBytes32, "bytes32 hex string"),
|
8
|
+
payer: zod_1.z.string().regex(utils_1.ethAddress, "Ethereum address"),
|
11
9
|
amount_12Decimals: zod_1.z
|
12
10
|
.string()
|
13
|
-
.regex(uint256, "uint256 (decimal) − 12 implied decimals"),
|
14
|
-
txHash: zod_1.z.string().regex(hexBytes32, "bytes32 hex string"),
|
11
|
+
.regex(utils_1.uint256, "uint256 (decimal) − 12 implied decimals"),
|
12
|
+
txHash: zod_1.z.string().regex(utils_1.hexBytes32, "bytes32 hex string"),
|
15
13
|
});
|
@@ -2,13 +2,12 @@
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
3
3
|
exports.auditPushedV1PayloadZ = void 0;
|
4
4
|
const zod_1 = require("zod");
|
5
|
-
const
|
6
|
-
const uint256 = /^[0-9]+$/; // unsigned big‑int as decimal string
|
5
|
+
const utils_1 = require("../utils");
|
7
6
|
exports.auditPushedV1PayloadZ = zod_1.z.object({
|
8
|
-
farmId: zod_1.z.string().regex(hexBytes32, "bytes32 hex string"),
|
7
|
+
farmId: zod_1.z.string().regex(utils_1.hexBytes32, "bytes32 hex string"),
|
9
8
|
protocolFeeUSDPrice_12Decimals: zod_1.z
|
10
9
|
.string()
|
11
|
-
.regex(uint256, "uint256 (decimal) − 12 implied decimals"),
|
12
|
-
expectedProduction_12Decimals: zod_1.z.string().regex(uint256),
|
13
|
-
txHash: zod_1.z.string().regex(hexBytes32, "bytes32 hex string"),
|
10
|
+
.regex(utils_1.uint256, "uint256 (decimal) − 12 implied decimals"),
|
11
|
+
expectedProduction_12Decimals: zod_1.z.string().regex(utils_1.uint256),
|
12
|
+
txHash: zod_1.z.string().regex(utils_1.hexBytes32, "bytes32 hex string"),
|
14
13
|
});
|
@@ -2,10 +2,9 @@
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
3
3
|
exports.auditSlashedV1PayloadZ = void 0;
|
4
4
|
const zod_1 = require("zod");
|
5
|
-
const
|
6
|
-
const ethAddress = /^0x[0-9a-fA-F]{40}$/;
|
5
|
+
const utils_1 = require("../utils");
|
7
6
|
exports.auditSlashedV1PayloadZ = zod_1.z.object({
|
8
|
-
farmId: zod_1.z.string().regex(hexBytes32, "bytes32 hex string"),
|
9
|
-
slasher: zod_1.z.string().regex(ethAddress, "Ethereum address"),
|
10
|
-
txHash: zod_1.z.string().regex(hexBytes32, "bytes32 hex string"),
|
7
|
+
farmId: zod_1.z.string().regex(utils_1.hexBytes32, "bytes32 hex string"),
|
8
|
+
slasher: zod_1.z.string().regex(utils_1.ethAddress, "Ethereum address"),
|
9
|
+
txHash: zod_1.z.string().regex(utils_1.hexBytes32, "bytes32 hex string"),
|
11
10
|
});
|
package/dist/types.d.ts
CHANGED
@@ -4,31 +4,25 @@ import type { AuditSlashedV1Payload } from "./schemas/audit-slashed.v1";
|
|
4
4
|
import type { AuditPfeesPaidV1Payload } from "./schemas/audit-pfees-paid.v1";
|
5
5
|
import type { AuditPfeesPaidV2Payload } from "./schemas/audit-pfees-paid.v2";
|
6
6
|
import type { ApplicationCreatedV1Payload } from "./schemas/application-created.v1";
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
"audit.slashed": 1;
|
11
|
-
"audit.pfees.paid": 1 | 2;
|
12
|
-
"application.created": 1;
|
13
|
-
};
|
14
|
-
export type EventVersion<T extends EventType> = T extends keyof EventTypeToVersion ? EventTypeToVersion[T] : never;
|
7
|
+
import { eventTypes, EventType } from "./event-types";
|
8
|
+
export { EventType, eventTypes };
|
9
|
+
export type EventVersion = "v1" | "v2";
|
15
10
|
export interface EventPayloadMap {
|
16
|
-
|
17
|
-
|
11
|
+
[eventTypes.auditPushed]: {
|
12
|
+
v1: AuditPushedV1Payload;
|
18
13
|
};
|
19
|
-
|
20
|
-
|
14
|
+
[eventTypes.auditSlashed]: {
|
15
|
+
v1: AuditSlashedV1Payload;
|
21
16
|
};
|
22
|
-
|
23
|
-
|
24
|
-
|
17
|
+
[eventTypes.auditPfeesPaid]: {
|
18
|
+
v1: AuditPfeesPaidV1Payload;
|
19
|
+
v2: AuditPfeesPaidV2Payload;
|
25
20
|
};
|
26
|
-
|
27
|
-
|
21
|
+
[eventTypes.applicationCreated]: {
|
22
|
+
v1: ApplicationCreatedV1Payload;
|
28
23
|
};
|
29
24
|
}
|
30
|
-
export type EventPayload<T extends EventType, V extends
|
25
|
+
export type EventPayload<T extends EventType, V extends keyof EventPayloadMap[T]> = T extends keyof EventPayloadMap ? V extends keyof EventPayloadMap[T] ? EventPayloadMap[T][V] : never : never;
|
31
26
|
export interface GlowEvent<TPayload> extends Omit<BaseEvent, "payload"> {
|
32
27
|
payload: TPayload;
|
33
28
|
}
|
34
|
-
export {};
|
package/dist/types.js
CHANGED
@@ -1,2 +1,5 @@
|
|
1
1
|
"use strict";
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
3
|
+
exports.eventTypes = void 0;
|
4
|
+
const event_types_1 = require("./event-types");
|
5
|
+
Object.defineProperty(exports, "eventTypes", { enumerable: true, get: function () { return event_types_1.eventTypes; } });
|
package/dist/utils.d.ts
CHANGED
@@ -7,7 +7,7 @@ export declare function validateZoneNameAndId(zoneId: number, zoneName: string):
|
|
7
7
|
* Validates the event payload against the schema for the given eventType and schemaVersion.
|
8
8
|
* Throws an error if the schema does not exist or the payload is invalid.
|
9
9
|
*/
|
10
|
-
export declare function validateEventPayload(eventType: string, schemaVersion:
|
10
|
+
export declare function validateEventPayload(eventType: string, schemaVersion: "v1" | "v2", payload: any): void;
|
11
11
|
/**
|
12
12
|
* Processes a message object as the listener would, validating zone and schema.
|
13
13
|
* Throws if validation fails, returns the parsed event otherwise.
|
@@ -18,3 +18,13 @@ export declare function processEventMessage(msg: {
|
|
18
18
|
routingKey: string;
|
19
19
|
};
|
20
20
|
}): any;
|
21
|
+
export declare const hexBytes32: RegExp;
|
22
|
+
export declare const ethAddress: RegExp;
|
23
|
+
export declare const uint256: RegExp;
|
24
|
+
export declare const exchangeOrQueueNamePattern: RegExp;
|
25
|
+
export declare function validateName(name: string, type: "exchange" | "queue"): void;
|
26
|
+
export declare function buildAmqpUrl({ username, password, host, }: {
|
27
|
+
username: string;
|
28
|
+
password: string;
|
29
|
+
host: string;
|
30
|
+
}): string;
|
package/dist/utils.js
CHANGED
@@ -1,8 +1,11 @@
|
|
1
1
|
"use strict";
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
3
|
+
exports.exchangeOrQueueNamePattern = exports.uint256 = exports.ethAddress = exports.hexBytes32 = void 0;
|
3
4
|
exports.validateZoneNameAndId = validateZoneNameAndId;
|
4
5
|
exports.validateEventPayload = validateEventPayload;
|
5
6
|
exports.processEventMessage = processEventMessage;
|
7
|
+
exports.validateName = validateName;
|
8
|
+
exports.buildAmqpUrl = buildAmqpUrl;
|
6
9
|
const event_registry_1 = require("./event-registry");
|
7
10
|
const zones_1 = require("./zones");
|
8
11
|
/**
|
@@ -11,9 +14,9 @@ const zones_1 = require("./zones");
|
|
11
14
|
*/
|
12
15
|
function validateZoneNameAndId(zoneId, zoneName) {
|
13
16
|
if (typeof zoneId === "number" &&
|
14
|
-
|
15
|
-
zoneName !== zones_1.zoneMap[
|
16
|
-
throw new Error(`zoneName '${zoneName}' does not match zoneId '${zoneId}' (expected '${zones_1.zoneMap[
|
17
|
+
zoneId in zones_1.zoneMap &&
|
18
|
+
zoneName !== zones_1.zoneMap[zoneId]) {
|
19
|
+
throw new Error(`zoneName '${zoneName}' does not match zoneId '${zoneId}' (expected '${zones_1.zoneMap[zoneId]}')`);
|
17
20
|
}
|
18
21
|
}
|
19
22
|
/**
|
@@ -23,12 +26,12 @@ function validateZoneNameAndId(zoneId, zoneName) {
|
|
23
26
|
function validateEventPayload(eventType, schemaVersion, payload) {
|
24
27
|
const schema = (0, event_registry_1.getEventSchema)(eventType, schemaVersion);
|
25
28
|
if (!schema)
|
26
|
-
throw new Error(`No schema for event: ${eventType}
|
29
|
+
throw new Error(`No schema for event: ${eventType} ${schemaVersion}`);
|
27
30
|
try {
|
28
31
|
schema.parse(payload);
|
29
32
|
}
|
30
33
|
catch (err) {
|
31
|
-
throw new Error(`Payload does not match schema for event: ${eventType}
|
34
|
+
throw new Error(`Payload does not match schema for event: ${eventType} ${schemaVersion}: ${err.message}`);
|
32
35
|
}
|
33
36
|
}
|
34
37
|
/**
|
@@ -38,8 +41,21 @@ function validateEventPayload(eventType, schemaVersion, payload) {
|
|
38
41
|
function processEventMessage(msg) {
|
39
42
|
const decoded = JSON.parse(msg.content.toString());
|
40
43
|
const [eventType, versionStr] = msg.fields.routingKey.split(".v");
|
41
|
-
const schemaVersion =
|
44
|
+
const schemaVersion = `v${versionStr}`;
|
42
45
|
validateZoneNameAndId(decoded.zoneId, decoded.zoneName);
|
43
46
|
validateEventPayload(eventType, schemaVersion, decoded);
|
44
47
|
return (0, event_registry_1.getEventSchema)(eventType, schemaVersion).parse(decoded);
|
45
48
|
}
|
49
|
+
exports.hexBytes32 = /^0x[0-9a-fA-F]{64}$/;
|
50
|
+
exports.ethAddress = /^0x[0-9a-fA-F]{40}$/;
|
51
|
+
exports.uint256 = /^[0-9]+$/;
|
52
|
+
exports.exchangeOrQueueNamePattern = /^[a-zA-Z0-9_-]+(\.[a-zA-Z0-9_-]+)+$/;
|
53
|
+
function validateName(name, type) {
|
54
|
+
if (!exports.exchangeOrQueueNamePattern.test(name)) {
|
55
|
+
throw new Error(`${type} name '${name}' is invalid. Must be dot-separated (e.g., 'glow.zone-1.events').`);
|
56
|
+
}
|
57
|
+
}
|
58
|
+
function buildAmqpUrl({ username, password, host, }) {
|
59
|
+
const url = new URL(`amqp://${username}:${password}@${host}`);
|
60
|
+
return url.toString();
|
61
|
+
}
|
package/dist/zones.d.ts
CHANGED
@@ -1,7 +1,14 @@
|
|
1
1
|
export declare const zoneMap: {
|
2
|
-
readonly
|
3
|
-
readonly
|
4
|
-
readonly
|
2
|
+
readonly 0: "All Zones";
|
3
|
+
readonly 1: "Clean Grid Project";
|
4
|
+
readonly 2: "Coming Soon Zone ";
|
5
5
|
};
|
6
6
|
export type ZoneId = keyof typeof zoneMap;
|
7
7
|
export type ZoneName = (typeof zoneMap)[ZoneId];
|
8
|
+
export declare const zoneKeyToId: {
|
9
|
+
readonly AllZones: 0;
|
10
|
+
readonly CleanGridProject: 1;
|
11
|
+
readonly ComingSoonZone: 2;
|
12
|
+
};
|
13
|
+
export type ZoneKey = keyof typeof zoneKeyToId;
|
14
|
+
export declare function getZoneId(name: ZoneKey): number;
|
package/dist/zones.js
CHANGED
@@ -1,8 +1,18 @@
|
|
1
1
|
"use strict";
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
3
|
-
exports.zoneMap = void 0;
|
3
|
+
exports.zoneKeyToId = exports.zoneMap = void 0;
|
4
|
+
exports.getZoneId = getZoneId;
|
4
5
|
exports.zoneMap = {
|
5
|
-
|
6
|
-
|
7
|
-
|
6
|
+
0: "All Zones",
|
7
|
+
1: "Clean Grid Project",
|
8
|
+
2: "Coming Soon Zone ",
|
8
9
|
};
|
10
|
+
// Stable keys for zone lookup (do not change these keys, only the display names in zoneMap)
|
11
|
+
exports.zoneKeyToId = {
|
12
|
+
AllZones: 0,
|
13
|
+
CleanGridProject: 1,
|
14
|
+
ComingSoonZone: 2,
|
15
|
+
};
|
16
|
+
function getZoneId(name) {
|
17
|
+
return exports.zoneKeyToId[name];
|
18
|
+
}
|