@aztec/validator-ha-signer 4.0.0-nightly.20260114 → 4.0.0-nightly.20260116

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.
@@ -1,14 +1,22 @@
1
1
  import { EthAddress } from '@aztec/foundation/eth-address';
2
- import type { Pool } from 'pg';
2
+ import type { QueryResult, QueryResultRow } from 'pg';
3
3
  import type { SlashingProtectionDatabase, TryInsertOrGetResult } from '../types.js';
4
4
  import type { CheckAndRecordParams, DutyType } from './types.js';
5
+ /**
6
+ * Minimal pool interface for database operations.
7
+ * Both pg.Pool and test adapters (e.g., PGlite) satisfy this interface.
8
+ */
9
+ export interface QueryablePool {
10
+ query<R extends QueryResultRow = any>(text: string, values?: any[]): Promise<QueryResult<R>>;
11
+ end(): Promise<void>;
12
+ }
5
13
  /**
6
14
  * PostgreSQL implementation of the slashing protection database
7
15
  */
8
16
  export declare class PostgresSlashingProtectionDatabase implements SlashingProtectionDatabase {
9
17
  private readonly pool;
10
18
  private readonly log;
11
- constructor(pool: Pool);
19
+ constructor(pool: QueryablePool);
12
20
  /**
13
21
  * Verify that database migrations have been run and schema version matches.
14
22
  * Should be called once at startup.
@@ -52,4 +60,4 @@ export declare class PostgresSlashingProtectionDatabase implements SlashingProte
52
60
  */
53
61
  cleanupOwnStuckDuties(nodeId: string, maxAgeMs: number): Promise<number>;
54
62
  }
55
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicG9zdGdyZXMuZC50cyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9kYi9wb3N0Z3Jlcy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFJQSxPQUFPLEVBQUUsVUFBVSxFQUFFLE1BQU0sK0JBQStCLENBQUM7QUFHM0QsT0FBTyxLQUFLLEVBQUUsSUFBSSxFQUFlLE1BQU0sSUFBSSxDQUFDO0FBRTVDLE9BQU8sS0FBSyxFQUFFLDBCQUEwQixFQUFFLG9CQUFvQixFQUFFLE1BQU0sYUFBYSxDQUFDO0FBUXBGLE9BQU8sS0FBSyxFQUFFLG9CQUFvQixFQUFXLFFBQVEsRUFBdUMsTUFBTSxZQUFZLENBQUM7QUFFL0c7O0dBRUc7QUFDSCxxQkFBYSxrQ0FBbUMsWUFBVywwQkFBMEI7SUFHdkUsT0FBTyxDQUFDLFFBQVEsQ0FBQyxJQUFJO0lBRmpDLE9BQU8sQ0FBQyxRQUFRLENBQUMsR0FBRyxDQUFTO0lBRTdCLFlBQTZCLElBQUksRUFBRSxJQUFJLEVBRXRDO0lBRUQ7Ozs7O09BS0c7SUFDRyxVQUFVLElBQUksT0FBTyxDQUFDLElBQUksQ0FBQyxDQWdDaEM7SUFFRDs7Ozs7T0FLRztJQUNHLHNCQUFzQixDQUFDLE1BQU0sRUFBRSxvQkFBb0IsR0FBRyxPQUFPLENBQUMsb0JBQW9CLENBQUMsQ0F3QnhGO0lBRUQ7Ozs7O09BS0c7SUFDRyxnQkFBZ0IsQ0FDcEIsZ0JBQWdCLEVBQUUsVUFBVSxFQUM1QixJQUFJLEVBQUUsTUFBTSxFQUNaLFFBQVEsRUFBRSxRQUFRLEVBQ2xCLFNBQVMsRUFBRSxNQUFNLEVBQ2pCLFNBQVMsRUFBRSxNQUFNLEdBQ2hCLE9BQU8sQ0FBQyxPQUFPLENBQUMsQ0FrQmxCO0lBRUQ7Ozs7OztPQU1HO0lBQ0csVUFBVSxDQUNkLGdCQUFnQixFQUFFLFVBQVUsRUFDNUIsSUFBSSxFQUFFLE1BQU0sRUFDWixRQUFRLEVBQUUsUUFBUSxFQUNsQixTQUFTLEVBQUUsTUFBTSxHQUNoQixPQUFPLENBQUMsT0FBTyxDQUFDLENBaUJsQjtJQUVEOztPQUVHO0lBQ0gsT0FBTyxDQUFDLFdBQVc7SUFpQm5COztPQUVHO0lBQ0csS0FBSyxJQUFJLE9BQU8sQ0FBQyxJQUFJLENBQUMsQ0FHM0I7SUFFRDs7O09BR0c7SUFDRyxxQkFBcUIsQ0FBQyxNQUFNLEVBQUUsTUFBTSxFQUFFLFFBQVEsRUFBRSxNQUFNLEdBQUcsT0FBTyxDQUFDLE1BQU0sQ0FBQyxDQUk3RTtDQUNGIn0=
63
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicG9zdGdyZXMuZC50cyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9kYi9wb3N0Z3Jlcy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFJQSxPQUFPLEVBQUUsVUFBVSxFQUFFLE1BQU0sK0JBQStCLENBQUM7QUFHM0QsT0FBTyxLQUFLLEVBQUUsV0FBVyxFQUFFLGNBQWMsRUFBRSxNQUFNLElBQUksQ0FBQztBQUV0RCxPQUFPLEtBQUssRUFBRSwwQkFBMEIsRUFBRSxvQkFBb0IsRUFBRSxNQUFNLGFBQWEsQ0FBQztBQVFwRixPQUFPLEtBQUssRUFBRSxvQkFBb0IsRUFBVyxRQUFRLEVBQXVDLE1BQU0sWUFBWSxDQUFDO0FBRS9HOzs7R0FHRztBQUNILE1BQU0sV0FBVyxhQUFhO0lBQzVCLEtBQUssQ0FBQyxDQUFDLFNBQVMsY0FBYyxHQUFHLEdBQUcsRUFBRSxJQUFJLEVBQUUsTUFBTSxFQUFFLE1BQU0sQ0FBQyxFQUFFLEdBQUcsRUFBRSxHQUFHLE9BQU8sQ0FBQyxXQUFXLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUM3RixHQUFHLElBQUksT0FBTyxDQUFDLElBQUksQ0FBQyxDQUFDO0NBQ3RCO0FBRUQ7O0dBRUc7QUFDSCxxQkFBYSxrQ0FBbUMsWUFBVywwQkFBMEI7SUFHdkUsT0FBTyxDQUFDLFFBQVEsQ0FBQyxJQUFJO0lBRmpDLE9BQU8sQ0FBQyxRQUFRLENBQUMsR0FBRyxDQUFTO0lBRTdCLFlBQTZCLElBQUksRUFBRSxhQUFhLEVBRS9DO0lBRUQ7Ozs7O09BS0c7SUFDRyxVQUFVLElBQUksT0FBTyxDQUFDLElBQUksQ0FBQyxDQWdDaEM7SUFFRDs7Ozs7T0FLRztJQUNHLHNCQUFzQixDQUFDLE1BQU0sRUFBRSxvQkFBb0IsR0FBRyxPQUFPLENBQUMsb0JBQW9CLENBQUMsQ0F3QnhGO0lBRUQ7Ozs7O09BS0c7SUFDRyxnQkFBZ0IsQ0FDcEIsZ0JBQWdCLEVBQUUsVUFBVSxFQUM1QixJQUFJLEVBQUUsTUFBTSxFQUNaLFFBQVEsRUFBRSxRQUFRLEVBQ2xCLFNBQVMsRUFBRSxNQUFNLEVBQ2pCLFNBQVMsRUFBRSxNQUFNLEdBQ2hCLE9BQU8sQ0FBQyxPQUFPLENBQUMsQ0FrQmxCO0lBRUQ7Ozs7OztPQU1HO0lBQ0csVUFBVSxDQUNkLGdCQUFnQixFQUFFLFVBQVUsRUFDNUIsSUFBSSxFQUFFLE1BQU0sRUFDWixRQUFRLEVBQUUsUUFBUSxFQUNsQixTQUFTLEVBQUUsTUFBTSxHQUNoQixPQUFPLENBQUMsT0FBTyxDQUFDLENBaUJsQjtJQUVEOztPQUVHO0lBQ0gsT0FBTyxDQUFDLFdBQVc7SUFpQm5COztPQUVHO0lBQ0csS0FBSyxJQUFJLE9BQU8sQ0FBQyxJQUFJLENBQUMsQ0FHM0I7SUFFRDs7O09BR0c7SUFDRyxxQkFBcUIsQ0FBQyxNQUFNLEVBQUUsTUFBTSxFQUFFLFFBQVEsRUFBRSxNQUFNLEdBQUcsT0FBTyxDQUFDLE1BQU0sQ0FBQyxDQUk3RTtDQUNGIn0=
@@ -1 +1 @@
1
- {"version":3,"file":"postgres.d.ts","sourceRoot":"","sources":["../../src/db/postgres.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,UAAU,EAAE,MAAM,+BAA+B,CAAC;AAG3D,OAAO,KAAK,EAAE,IAAI,EAAe,MAAM,IAAI,CAAC;AAE5C,OAAO,KAAK,EAAE,0BAA0B,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC;AAQpF,OAAO,KAAK,EAAE,oBAAoB,EAAW,QAAQ,EAAuC,MAAM,YAAY,CAAC;AAE/G;;GAEG;AACH,qBAAa,kCAAmC,YAAW,0BAA0B;IAGvE,OAAO,CAAC,QAAQ,CAAC,IAAI;IAFjC,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAS;IAE7B,YAA6B,IAAI,EAAE,IAAI,EAEtC;IAED;;;;;OAKG;IACG,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC,CAgChC;IAED;;;;;OAKG;IACG,sBAAsB,CAAC,MAAM,EAAE,oBAAoB,GAAG,OAAO,CAAC,oBAAoB,CAAC,CAwBxF;IAED;;;;;OAKG;IACG,gBAAgB,CACpB,gBAAgB,EAAE,UAAU,EAC5B,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,QAAQ,EAClB,SAAS,EAAE,MAAM,EACjB,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,OAAO,CAAC,CAkBlB;IAED;;;;;;OAMG;IACG,UAAU,CACd,gBAAgB,EAAE,UAAU,EAC5B,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,QAAQ,EAClB,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,OAAO,CAAC,CAiBlB;IAED;;OAEG;IACH,OAAO,CAAC,WAAW;IAiBnB;;OAEG;IACG,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAG3B;IAED;;;OAGG;IACG,qBAAqB,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAI7E;CACF"}
1
+ {"version":3,"file":"postgres.d.ts","sourceRoot":"","sources":["../../src/db/postgres.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,UAAU,EAAE,MAAM,+BAA+B,CAAC;AAG3D,OAAO,KAAK,EAAE,WAAW,EAAE,cAAc,EAAE,MAAM,IAAI,CAAC;AAEtD,OAAO,KAAK,EAAE,0BAA0B,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC;AAQpF,OAAO,KAAK,EAAE,oBAAoB,EAAW,QAAQ,EAAuC,MAAM,YAAY,CAAC;AAE/G;;;GAGG;AACH,MAAM,WAAW,aAAa;IAC5B,KAAK,CAAC,CAAC,SAAS,cAAc,GAAG,GAAG,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,GAAG,EAAE,GAAG,OAAO,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC;IAC7F,GAAG,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CACtB;AAED;;GAEG;AACH,qBAAa,kCAAmC,YAAW,0BAA0B;IAGvE,OAAO,CAAC,QAAQ,CAAC,IAAI;IAFjC,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAS;IAE7B,YAA6B,IAAI,EAAE,aAAa,EAE/C;IAED;;;;;OAKG;IACG,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC,CAgChC;IAED;;;;;OAKG;IACG,sBAAsB,CAAC,MAAM,EAAE,oBAAoB,GAAG,OAAO,CAAC,oBAAoB,CAAC,CAwBxF;IAED;;;;;OAKG;IACG,gBAAgB,CACpB,gBAAgB,EAAE,UAAU,EAC5B,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,QAAQ,EAClB,SAAS,EAAE,MAAM,EACjB,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,OAAO,CAAC,CAkBlB;IAED;;;;;;OAMG;IACG,UAAU,CACd,gBAAgB,EAAE,UAAU,EAC5B,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,QAAQ,EAClB,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,OAAO,CAAC,CAiBlB;IAED;;OAEG;IACH,OAAO,CAAC,WAAW;IAiBnB;;OAEG;IACG,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAG3B;IAED;;;OAGG;IACG,qBAAqB,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAI7E;CACF"}
@@ -0,0 +1,92 @@
1
+ /**
2
+ * Vendored pg-compatible Pool/Client wrapper for PGlite.
3
+ *
4
+ * Copied from @middle-management/pglite-pg-adapter v0.0.3
5
+ * https://www.npmjs.com/package/@middle-management/pglite-pg-adapter
6
+ *
7
+ * Modifications:
8
+ * - Converted to ESM and TypeScript
9
+ * - Uses PGliteInterface instead of PGlite class to avoid TypeScript
10
+ * type mismatches from ESM/CJS dual package resolution with private fields
11
+ * - Simplified rowCount calculation to handle CTEs properly
12
+ */
13
+ import type { PGliteInterface } from '@electric-sql/pglite';
14
+ import { EventEmitter } from 'events';
15
+ import type { QueryResult, QueryResultRow } from 'pg';
16
+ import { Readable, Writable } from 'stream';
17
+ export interface PoolConfig {
18
+ pglite: PGliteInterface;
19
+ max?: number;
20
+ min?: number;
21
+ }
22
+ interface ClientConfig {
23
+ pglite: PGliteInterface;
24
+ host?: string;
25
+ port?: number;
26
+ ssl?: boolean;
27
+ }
28
+ export declare class Client extends EventEmitter {
29
+ protected pglite: PGliteInterface;
30
+ protected _connected: boolean;
31
+ readonly host: string;
32
+ readonly port: number;
33
+ readonly ssl: boolean;
34
+ readonly connection: object;
35
+ readonly copyFrom: () => Writable;
36
+ readonly copyTo: () => Readable;
37
+ readonly pauseDrain: () => void;
38
+ readonly resumeDrain: () => void;
39
+ readonly escapeLiteral: (str: string) => string;
40
+ readonly escapeIdentifier: (str: string) => string;
41
+ readonly setTypeParser: () => void;
42
+ readonly getTypeParser: () => (value: string) => unknown;
43
+ constructor(config: ClientConfig);
44
+ connect(): Promise<void>;
45
+ end(): Promise<void>;
46
+ query<R extends QueryResultRow = any>(text: string, values?: any[]): Promise<QueryResult<R>>;
47
+ protected convertPGliteResult<R extends QueryResultRow>(result: {
48
+ rows: R[];
49
+ fields: Array<{
50
+ name: string;
51
+ dataTypeID: number;
52
+ }>;
53
+ affectedRows?: number;
54
+ }): QueryResult<R>;
55
+ get connected(): boolean;
56
+ }
57
+ export declare class Pool extends EventEmitter {
58
+ private clients;
59
+ private availableClients;
60
+ private waitingQueue;
61
+ private _ended;
62
+ private pglite;
63
+ private _config;
64
+ readonly expiredCount = 0;
65
+ readonly options: PoolConfig;
66
+ constructor(config: PoolConfig);
67
+ get totalCount(): number;
68
+ get idleCount(): number;
69
+ get waitingCount(): number;
70
+ get ending(): boolean;
71
+ get ended(): boolean;
72
+ connect(): Promise<PoolClient>;
73
+ query<R extends QueryResultRow = any>(text: string, values?: any[]): Promise<QueryResult<R>>;
74
+ releaseClient(client: PoolClient): void;
75
+ end(): Promise<void>;
76
+ }
77
+ export declare class PoolClient extends Client {
78
+ private pool;
79
+ private _released;
80
+ private _inUse;
81
+ private _userReleased;
82
+ constructor(pglite: PGliteInterface, pool: Pool);
83
+ query<R extends QueryResultRow = any>(text: string, values?: any[]): Promise<QueryResult<R>>;
84
+ release(): void;
85
+ end(): Promise<void>;
86
+ _markInUse(): void;
87
+ _markAvailable(): void;
88
+ _markReleased(): void;
89
+ get connected(): boolean;
90
+ }
91
+ export {};
92
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicGdsaXRlX3Bvb2wuZC50cyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy90ZXN0L3BnbGl0ZV9wb29sLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOzs7Ozs7Ozs7OztHQVdHO0FBQ0gsT0FBTyxLQUFLLEVBQUUsZUFBZSxFQUFFLE1BQU0sc0JBQXNCLENBQUM7QUFDNUQsT0FBTyxFQUFFLFlBQVksRUFBRSxNQUFNLFFBQVEsQ0FBQztBQUN0QyxPQUFPLEtBQUssRUFBRSxXQUFXLEVBQUUsY0FBYyxFQUFFLE1BQU0sSUFBSSxDQUFDO0FBQ3RELE9BQU8sRUFBRSxRQUFRLEVBQUUsUUFBUSxFQUFFLE1BQU0sUUFBUSxDQUFDO0FBRTVDLE1BQU0sV0FBVyxVQUFVO0lBQ3pCLE1BQU0sRUFBRSxlQUFlLENBQUM7SUFDeEIsR0FBRyxDQUFDLEVBQUUsTUFBTSxDQUFDO0lBQ2IsR0FBRyxDQUFDLEVBQUUsTUFBTSxDQUFDO0NBQ2Q7QUFFRCxVQUFVLFlBQVk7SUFDcEIsTUFBTSxFQUFFLGVBQWUsQ0FBQztJQUN4QixJQUFJLENBQUMsRUFBRSxNQUFNLENBQUM7SUFDZCxJQUFJLENBQUMsRUFBRSxNQUFNLENBQUM7SUFDZCxHQUFHLENBQUMsRUFBRSxPQUFPLENBQUM7Q0FDZjtBQUVELHFCQUFhLE1BQU8sU0FBUSxZQUFZO0lBQ3RDLFNBQVMsQ0FBQyxNQUFNLEVBQUUsZUFBZSxDQUFDO0lBQ2xDLFNBQVMsQ0FBQyxVQUFVLFVBQVM7SUFDN0IsUUFBUSxDQUFDLElBQUksRUFBRSxNQUFNLENBQUM7SUFDdEIsUUFBUSxDQUFDLElBQUksRUFBRSxNQUFNLENBQUM7SUFDdEIsUUFBUSxDQUFDLEdBQUcsRUFBRSxPQUFPLENBQUM7SUFDdEIsUUFBUSxDQUFDLFVBQVUsRUFBRSxNQUFNLENBQUM7SUFHNUIsUUFBUSxDQUFDLFFBQVEsaUJBQWtDO0lBQ25ELFFBQVEsQ0FBQyxNQUFNLGlCQUFrQztJQUNqRCxRQUFRLENBQUMsVUFBVSxhQUFr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
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pglite_pool.d.ts","sourceRoot":"","sources":["../../src/test/pglite_pool.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,210 @@
1
+ /**
2
+ * Vendored pg-compatible Pool/Client wrapper for PGlite.
3
+ *
4
+ * Copied from @middle-management/pglite-pg-adapter v0.0.3
5
+ * https://www.npmjs.com/package/@middle-management/pglite-pg-adapter
6
+ *
7
+ * Modifications:
8
+ * - Converted to ESM and TypeScript
9
+ * - Uses PGliteInterface instead of PGlite class to avoid TypeScript
10
+ * type mismatches from ESM/CJS dual package resolution with private fields
11
+ * - Simplified rowCount calculation to handle CTEs properly
12
+ */ import { EventEmitter } from 'events';
13
+ import { Readable, Writable } from 'stream';
14
+ export class Client extends EventEmitter {
15
+ pglite;
16
+ _connected = false;
17
+ host;
18
+ port;
19
+ ssl;
20
+ connection;
21
+ // Stub implementations for pg compatibility
22
+ copyFrom = ()=>new Writable();
23
+ copyTo = ()=>new Readable();
24
+ pauseDrain = ()=>{};
25
+ resumeDrain = ()=>{};
26
+ escapeLiteral = (str)=>`'${str.replace(/'/g, "''")}'`;
27
+ escapeIdentifier = (str)=>`"${str.replace(/"/g, '""')}"`;
28
+ setTypeParser = ()=>{};
29
+ getTypeParser = ()=>(value)=>value;
30
+ constructor(config){
31
+ super();
32
+ this.pglite = config.pglite;
33
+ this.host = config.host || 'localhost';
34
+ this.port = config.port || 5432;
35
+ this.ssl = typeof config.ssl === 'boolean' ? config.ssl : !!config.ssl;
36
+ this.connection = {};
37
+ }
38
+ connect() {
39
+ if (this._connected) {
40
+ return Promise.resolve();
41
+ }
42
+ this._connected = true;
43
+ this.emit('connect');
44
+ return Promise.resolve();
45
+ }
46
+ end() {
47
+ if (!this._connected) {
48
+ return Promise.resolve();
49
+ }
50
+ this._connected = false;
51
+ this.emit('end');
52
+ return Promise.resolve();
53
+ }
54
+ async query(text, values) {
55
+ if (!this._connected) {
56
+ throw new Error('Client is not connected');
57
+ }
58
+ const result = await this.pglite.query(text, values);
59
+ return this.convertPGliteResult(result);
60
+ }
61
+ convertPGliteResult(result) {
62
+ return {
63
+ command: '',
64
+ rowCount: 'affectedRows' in result ? result.affectedRows ?? 0 : result.rows.length,
65
+ oid: 0,
66
+ fields: result.fields.map((field)=>({
67
+ name: field.name,
68
+ tableID: 0,
69
+ columnID: 0,
70
+ dataTypeID: field.dataTypeID,
71
+ dataTypeSize: -1,
72
+ dataTypeModifier: -1,
73
+ format: 'text'
74
+ })),
75
+ rows: result.rows
76
+ };
77
+ }
78
+ get connected() {
79
+ return this._connected;
80
+ }
81
+ }
82
+ export class Pool extends EventEmitter {
83
+ clients = [];
84
+ availableClients = [];
85
+ waitingQueue = [];
86
+ _ended = false;
87
+ pglite;
88
+ _config;
89
+ expiredCount = 0;
90
+ options;
91
+ constructor(config){
92
+ super();
93
+ this._config = {
94
+ max: 10,
95
+ min: 0,
96
+ ...config
97
+ };
98
+ this.pglite = config.pglite;
99
+ this.options = config;
100
+ }
101
+ get totalCount() {
102
+ return this.clients.length;
103
+ }
104
+ get idleCount() {
105
+ return this.availableClients.length;
106
+ }
107
+ get waitingCount() {
108
+ return this.waitingQueue.length;
109
+ }
110
+ get ending() {
111
+ return this._ended;
112
+ }
113
+ get ended() {
114
+ return this._ended;
115
+ }
116
+ connect() {
117
+ if (this._ended) {
118
+ return Promise.reject(new Error('Pool is ended'));
119
+ }
120
+ if (this.availableClients.length > 0) {
121
+ const client = this.availableClients.pop();
122
+ client._markInUse();
123
+ return Promise.resolve(client);
124
+ }
125
+ if (this.clients.length < (this._config.max || 10)) {
126
+ const client = new PoolClient(this.pglite, this);
127
+ this.clients.push(client);
128
+ return Promise.resolve(client);
129
+ }
130
+ return new Promise((resolve)=>{
131
+ this.waitingQueue.push(resolve);
132
+ });
133
+ }
134
+ async query(text, values) {
135
+ const client = await this.connect();
136
+ try {
137
+ return await client.query(text, values);
138
+ } finally{
139
+ client.release();
140
+ }
141
+ }
142
+ releaseClient(client) {
143
+ const index = this.clients.indexOf(client);
144
+ if (index !== -1) {
145
+ client._markAvailable();
146
+ if (this.waitingQueue.length > 0) {
147
+ const resolve = this.waitingQueue.shift();
148
+ client._markInUse();
149
+ resolve(client);
150
+ } else {
151
+ this.availableClients.push(client);
152
+ }
153
+ }
154
+ }
155
+ end() {
156
+ this._ended = true;
157
+ this.clients.forEach((client)=>client._markReleased());
158
+ this.clients = [];
159
+ this.availableClients = [];
160
+ this.emit('end');
161
+ return Promise.resolve();
162
+ }
163
+ }
164
+ export class PoolClient extends Client {
165
+ pool;
166
+ _released = false;
167
+ _inUse = true;
168
+ _userReleased = false;
169
+ constructor(pglite, pool){
170
+ super({
171
+ pglite
172
+ });
173
+ this.pool = pool;
174
+ this._connected = true;
175
+ }
176
+ async query(text, values) {
177
+ if (this._userReleased && !this._inUse) {
178
+ throw new Error('Client has been released back to the pool');
179
+ }
180
+ const result = await this.pglite.query(text, values);
181
+ return this.convertPGliteResult(result);
182
+ }
183
+ release() {
184
+ if (this._released || this._userReleased) {
185
+ return;
186
+ }
187
+ this._userReleased = true;
188
+ this.pool.releaseClient(this);
189
+ }
190
+ end() {
191
+ this.release();
192
+ return Promise.resolve();
193
+ }
194
+ _markInUse() {
195
+ this._inUse = true;
196
+ this._userReleased = false;
197
+ }
198
+ _markAvailable() {
199
+ this._inUse = false;
200
+ this._userReleased = false;
201
+ }
202
+ _markReleased() {
203
+ this._released = true;
204
+ this._inUse = false;
205
+ this._userReleased = true;
206
+ }
207
+ get connected() {
208
+ return this._connected && !this._released;
209
+ }
210
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aztec/validator-ha-signer",
3
- "version": "4.0.0-nightly.20260114",
3
+ "version": "4.0.0-nightly.20260116",
4
4
  "type": "module",
5
5
  "exports": {
6
6
  "./config": "./dest/config.js",
@@ -73,21 +73,20 @@
73
73
  ]
74
74
  },
75
75
  "dependencies": {
76
- "@aztec/foundation": "4.0.0-nightly.20260114",
77
- "@aztec/node-keystore": "4.0.0-nightly.20260114",
76
+ "@aztec/foundation": "4.0.0-nightly.20260116",
77
+ "@aztec/node-keystore": "4.0.0-nightly.20260116",
78
78
  "node-pg-migrate": "^8.0.4",
79
79
  "pg": "^8.11.3",
80
80
  "tslib": "^2.4.0"
81
81
  },
82
82
  "devDependencies": {
83
- "@electric-sql/pglite": "^0.2.17",
83
+ "@electric-sql/pglite": "^0.3.14",
84
84
  "@jest/globals": "^30.0.0",
85
- "@middle-management/pglite-pg-adapter": "^0.0.3",
86
85
  "@types/jest": "^30.0.0",
87
86
  "@types/node": "^22.15.17",
88
87
  "@types/node-pg-migrate": "^2.3.1",
89
88
  "@types/pg": "^8.10.9",
90
- "@typescript/native-preview": "7.0.0-dev.20251126.1",
89
+ "@typescript/native-preview": "7.0.0-dev.20260113.1",
91
90
  "jest": "^30.0.0",
92
91
  "jest-mock-extended": "^4.0.0",
93
92
  "ts-node": "^10.9.1",
@@ -5,7 +5,7 @@ import { randomBytes } from '@aztec/foundation/crypto/random';
5
5
  import { EthAddress } from '@aztec/foundation/eth-address';
6
6
  import { type Logger, createLogger } from '@aztec/foundation/log';
7
7
 
8
- import type { Pool, QueryResult } from 'pg';
8
+ import type { QueryResult, QueryResultRow } from 'pg';
9
9
 
10
10
  import type { SlashingProtectionDatabase, TryInsertOrGetResult } from '../types.js';
11
11
  import {
@@ -17,13 +17,22 @@ import {
17
17
  } from './schema.js';
18
18
  import type { CheckAndRecordParams, DutyRow, DutyType, InsertOrGetRow, ValidatorDutyRecord } from './types.js';
19
19
 
20
+ /**
21
+ * Minimal pool interface for database operations.
22
+ * Both pg.Pool and test adapters (e.g., PGlite) satisfy this interface.
23
+ */
24
+ export interface QueryablePool {
25
+ query<R extends QueryResultRow = any>(text: string, values?: any[]): Promise<QueryResult<R>>;
26
+ end(): Promise<void>;
27
+ }
28
+
20
29
  /**
21
30
  * PostgreSQL implementation of the slashing protection database
22
31
  */
23
32
  export class PostgresSlashingProtectionDatabase implements SlashingProtectionDatabase {
24
33
  private readonly log: Logger;
25
34
 
26
- constructor(private readonly pool: Pool) {
35
+ constructor(private readonly pool: QueryablePool) {
27
36
  this.log = createLogger('slashing-protection:postgres');
28
37
  }
29
38
 
@@ -0,0 +1,256 @@
1
+ /**
2
+ * Vendored pg-compatible Pool/Client wrapper for PGlite.
3
+ *
4
+ * Copied from @middle-management/pglite-pg-adapter v0.0.3
5
+ * https://www.npmjs.com/package/@middle-management/pglite-pg-adapter
6
+ *
7
+ * Modifications:
8
+ * - Converted to ESM and TypeScript
9
+ * - Uses PGliteInterface instead of PGlite class to avoid TypeScript
10
+ * type mismatches from ESM/CJS dual package resolution with private fields
11
+ * - Simplified rowCount calculation to handle CTEs properly
12
+ */
13
+ import type { PGliteInterface } from '@electric-sql/pglite';
14
+ import { EventEmitter } from 'events';
15
+ import type { QueryResult, QueryResultRow } from 'pg';
16
+ import { Readable, Writable } from 'stream';
17
+
18
+ export interface PoolConfig {
19
+ pglite: PGliteInterface;
20
+ max?: number;
21
+ min?: number;
22
+ }
23
+
24
+ interface ClientConfig {
25
+ pglite: PGliteInterface;
26
+ host?: string;
27
+ port?: number;
28
+ ssl?: boolean;
29
+ }
30
+
31
+ export class Client extends EventEmitter {
32
+ protected pglite: PGliteInterface;
33
+ protected _connected = false;
34
+ readonly host: string;
35
+ readonly port: number;
36
+ readonly ssl: boolean;
37
+ readonly connection: object;
38
+
39
+ // Stub implementations for pg compatibility
40
+ readonly copyFrom = (): Writable => new Writable();
41
+ readonly copyTo = (): Readable => new Readable();
42
+ readonly pauseDrain = (): void => {};
43
+ readonly resumeDrain = (): void => {};
44
+ readonly escapeLiteral = (str: string): string => `'${str.replace(/'/g, "''")}'`;
45
+ readonly escapeIdentifier = (str: string): string => `"${str.replace(/"/g, '""')}"`;
46
+ readonly setTypeParser = (): void => {};
47
+ readonly getTypeParser = (): ((value: string) => unknown) => (value: string) => value;
48
+
49
+ constructor(config: ClientConfig) {
50
+ super();
51
+ this.pglite = config.pglite;
52
+ this.host = config.host || 'localhost';
53
+ this.port = config.port || 5432;
54
+ this.ssl = typeof config.ssl === 'boolean' ? config.ssl : !!config.ssl;
55
+ this.connection = {};
56
+ }
57
+
58
+ connect(): Promise<void> {
59
+ if (this._connected) {
60
+ return Promise.resolve();
61
+ }
62
+ this._connected = true;
63
+ this.emit('connect');
64
+ return Promise.resolve();
65
+ }
66
+
67
+ end(): Promise<void> {
68
+ if (!this._connected) {
69
+ return Promise.resolve();
70
+ }
71
+ this._connected = false;
72
+ this.emit('end');
73
+ return Promise.resolve();
74
+ }
75
+
76
+ async query<R extends QueryResultRow = any>(text: string, values?: any[]): Promise<QueryResult<R>> {
77
+ if (!this._connected) {
78
+ throw new Error('Client is not connected');
79
+ }
80
+ const result = await this.pglite.query<R>(text, values);
81
+ return this.convertPGliteResult(result);
82
+ }
83
+
84
+ protected convertPGliteResult<R extends QueryResultRow>(result: {
85
+ rows: R[];
86
+ fields: Array<{ name: string; dataTypeID: number }>;
87
+ affectedRows?: number;
88
+ }): QueryResult<R> {
89
+ return {
90
+ command: '',
91
+ rowCount: 'affectedRows' in result ? (result.affectedRows ?? 0) : result.rows.length,
92
+ oid: 0,
93
+ fields: result.fields.map(field => ({
94
+ name: field.name,
95
+ tableID: 0,
96
+ columnID: 0,
97
+ dataTypeID: field.dataTypeID,
98
+ dataTypeSize: -1,
99
+ dataTypeModifier: -1,
100
+ format: 'text',
101
+ })),
102
+ rows: result.rows,
103
+ };
104
+ }
105
+
106
+ get connected(): boolean {
107
+ return this._connected;
108
+ }
109
+ }
110
+
111
+ export class Pool extends EventEmitter {
112
+ private clients: PoolClient[] = [];
113
+ private availableClients: PoolClient[] = [];
114
+ private waitingQueue: Array<(client: PoolClient) => void> = [];
115
+ private _ended = false;
116
+ private pglite: PGliteInterface;
117
+ private _config: PoolConfig;
118
+
119
+ readonly expiredCount = 0;
120
+ readonly options: PoolConfig;
121
+
122
+ constructor(config: PoolConfig) {
123
+ super();
124
+ this._config = { max: 10, min: 0, ...config };
125
+ this.pglite = config.pglite;
126
+ this.options = config;
127
+ }
128
+
129
+ get totalCount(): number {
130
+ return this.clients.length;
131
+ }
132
+
133
+ get idleCount(): number {
134
+ return this.availableClients.length;
135
+ }
136
+
137
+ get waitingCount(): number {
138
+ return this.waitingQueue.length;
139
+ }
140
+
141
+ get ending(): boolean {
142
+ return this._ended;
143
+ }
144
+
145
+ get ended(): boolean {
146
+ return this._ended;
147
+ }
148
+
149
+ connect(): Promise<PoolClient> {
150
+ if (this._ended) {
151
+ return Promise.reject(new Error('Pool is ended'));
152
+ }
153
+
154
+ if (this.availableClients.length > 0) {
155
+ const client = this.availableClients.pop()!;
156
+ client._markInUse();
157
+ return Promise.resolve(client);
158
+ }
159
+
160
+ if (this.clients.length < (this._config.max || 10)) {
161
+ const client = new PoolClient(this.pglite, this);
162
+ this.clients.push(client);
163
+ return Promise.resolve(client);
164
+ }
165
+
166
+ return new Promise(resolve => {
167
+ this.waitingQueue.push(resolve);
168
+ });
169
+ }
170
+
171
+ async query<R extends QueryResultRow = any>(text: string, values?: any[]): Promise<QueryResult<R>> {
172
+ const client = await this.connect();
173
+ try {
174
+ return await client.query<R>(text, values);
175
+ } finally {
176
+ client.release();
177
+ }
178
+ }
179
+
180
+ releaseClient(client: PoolClient): void {
181
+ const index = this.clients.indexOf(client);
182
+ if (index !== -1) {
183
+ client._markAvailable();
184
+ if (this.waitingQueue.length > 0) {
185
+ const resolve = this.waitingQueue.shift()!;
186
+ client._markInUse();
187
+ resolve(client);
188
+ } else {
189
+ this.availableClients.push(client);
190
+ }
191
+ }
192
+ }
193
+
194
+ end(): Promise<void> {
195
+ this._ended = true;
196
+ this.clients.forEach(client => client._markReleased());
197
+ this.clients = [];
198
+ this.availableClients = [];
199
+ this.emit('end');
200
+ return Promise.resolve();
201
+ }
202
+ }
203
+
204
+ export class PoolClient extends Client {
205
+ private pool: Pool;
206
+ private _released = false;
207
+ private _inUse = true;
208
+ private _userReleased = false;
209
+
210
+ constructor(pglite: PGliteInterface, pool: Pool) {
211
+ super({ pglite });
212
+ this.pool = pool;
213
+ this._connected = true;
214
+ }
215
+
216
+ override async query<R extends QueryResultRow = any>(text: string, values?: any[]): Promise<QueryResult<R>> {
217
+ if (this._userReleased && !this._inUse) {
218
+ throw new Error('Client has been released back to the pool');
219
+ }
220
+ const result = await this.pglite.query<R>(text, values);
221
+ return this.convertPGliteResult(result);
222
+ }
223
+
224
+ release(): void {
225
+ if (this._released || this._userReleased) {
226
+ return;
227
+ }
228
+ this._userReleased = true;
229
+ this.pool.releaseClient(this);
230
+ }
231
+
232
+ override end(): Promise<void> {
233
+ this.release();
234
+ return Promise.resolve();
235
+ }
236
+
237
+ _markInUse(): void {
238
+ this._inUse = true;
239
+ this._userReleased = false;
240
+ }
241
+
242
+ _markAvailable(): void {
243
+ this._inUse = false;
244
+ this._userReleased = false;
245
+ }
246
+
247
+ _markReleased(): void {
248
+ this._released = true;
249
+ this._inUse = false;
250
+ this._userReleased = true;
251
+ }
252
+
253
+ override get connected(): boolean {
254
+ return this._connected && !this._released;
255
+ }
256
+ }