@teneo-protocol/sdk 1.0.0 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (211) hide show
  1. package/.github/workflows/publish-npm.yml +8 -6
  2. package/CHANGELOG.md +265 -0
  3. package/README.md +406 -53
  4. package/dist/core/websocket-client.d.ts +13 -0
  5. package/dist/core/websocket-client.d.ts.map +1 -1
  6. package/dist/core/websocket-client.js +34 -3
  7. package/dist/core/websocket-client.js.map +1 -1
  8. package/dist/handlers/message-handlers/agent-room-operation-response-handler.d.ts +76 -0
  9. package/dist/handlers/message-handlers/agent-room-operation-response-handler.d.ts.map +1 -0
  10. package/dist/handlers/message-handlers/agent-room-operation-response-handler.js +70 -0
  11. package/dist/handlers/message-handlers/agent-room-operation-response-handler.js.map +1 -0
  12. package/dist/handlers/message-handlers/agent-selected-handler.d.ts +92 -38
  13. package/dist/handlers/message-handlers/agent-selected-handler.d.ts.map +1 -1
  14. package/dist/handlers/message-handlers/agent-status-update-handler.d.ts +904 -0
  15. package/dist/handlers/message-handlers/agent-status-update-handler.d.ts.map +1 -0
  16. package/dist/handlers/message-handlers/agent-status-update-handler.js +51 -0
  17. package/dist/handlers/message-handlers/agent-status-update-handler.js.map +1 -0
  18. package/dist/handlers/message-handlers/auth-error-handler.d.ts +45 -31
  19. package/dist/handlers/message-handlers/auth-error-handler.d.ts.map +1 -1
  20. package/dist/handlers/message-handlers/auth-message-handler.d.ts +6 -0
  21. package/dist/handlers/message-handlers/auth-message-handler.d.ts.map +1 -1
  22. package/dist/handlers/message-handlers/auth-message-handler.js +65 -5
  23. package/dist/handlers/message-handlers/auth-message-handler.js.map +1 -1
  24. package/dist/handlers/message-handlers/auth-required-handler.d.ts +49 -31
  25. package/dist/handlers/message-handlers/auth-required-handler.d.ts.map +1 -1
  26. package/dist/handlers/message-handlers/auth-success-handler.d.ts +6 -0
  27. package/dist/handlers/message-handlers/auth-success-handler.d.ts.map +1 -1
  28. package/dist/handlers/message-handlers/auth-success-handler.js +46 -4
  29. package/dist/handlers/message-handlers/auth-success-handler.js.map +1 -1
  30. package/dist/handlers/message-handlers/challenge-handler.d.ts +45 -31
  31. package/dist/handlers/message-handlers/challenge-handler.d.ts.map +1 -1
  32. package/dist/handlers/message-handlers/error-message-handler.d.ts +49 -31
  33. package/dist/handlers/message-handlers/error-message-handler.d.ts.map +1 -1
  34. package/dist/handlers/message-handlers/index.d.ts +5 -0
  35. package/dist/handlers/message-handlers/index.d.ts.map +1 -1
  36. package/dist/handlers/message-handlers/index.js +23 -1
  37. package/dist/handlers/message-handlers/index.js.map +1 -1
  38. package/dist/handlers/message-handlers/list-available-agents-handler.d.ts +877 -0
  39. package/dist/handlers/message-handlers/list-available-agents-handler.d.ts.map +1 -0
  40. package/dist/handlers/message-handlers/list-available-agents-handler.js +38 -0
  41. package/dist/handlers/message-handlers/list-available-agents-handler.js.map +1 -0
  42. package/dist/handlers/message-handlers/list-room-agents-handler.d.ts +886 -0
  43. package/dist/handlers/message-handlers/list-room-agents-handler.d.ts.map +1 -0
  44. package/dist/handlers/message-handlers/list-room-agents-handler.js +51 -0
  45. package/dist/handlers/message-handlers/list-room-agents-handler.js.map +1 -0
  46. package/dist/handlers/message-handlers/list-rooms-response-handler.d.ts +178 -89
  47. package/dist/handlers/message-handlers/list-rooms-response-handler.d.ts.map +1 -1
  48. package/dist/handlers/message-handlers/ping-pong-handler.d.ts +62 -58
  49. package/dist/handlers/message-handlers/ping-pong-handler.d.ts.map +1 -1
  50. package/dist/handlers/message-handlers/regular-message-handler.d.ts +31 -29
  51. package/dist/handlers/message-handlers/regular-message-handler.d.ts.map +1 -1
  52. package/dist/handlers/message-handlers/regular-message-handler.js +1 -0
  53. package/dist/handlers/message-handlers/regular-message-handler.js.map +1 -1
  54. package/dist/handlers/message-handlers/room-operation-response-handler.d.ts +328 -0
  55. package/dist/handlers/message-handlers/room-operation-response-handler.d.ts.map +1 -0
  56. package/dist/handlers/message-handlers/room-operation-response-handler.js +92 -0
  57. package/dist/handlers/message-handlers/room-operation-response-handler.js.map +1 -0
  58. package/dist/handlers/message-handlers/subscribe-response-handler.d.ts +53 -31
  59. package/dist/handlers/message-handlers/subscribe-response-handler.d.ts.map +1 -1
  60. package/dist/handlers/message-handlers/types.d.ts +2 -0
  61. package/dist/handlers/message-handlers/types.d.ts.map +1 -1
  62. package/dist/handlers/message-handlers/unsubscribe-response-handler.d.ts +53 -31
  63. package/dist/handlers/message-handlers/unsubscribe-response-handler.d.ts.map +1 -1
  64. package/dist/managers/agent-room-manager.d.ts +222 -0
  65. package/dist/managers/agent-room-manager.d.ts.map +1 -0
  66. package/dist/managers/agent-room-manager.js +508 -0
  67. package/dist/managers/agent-room-manager.js.map +1 -0
  68. package/dist/managers/index.d.ts +2 -0
  69. package/dist/managers/index.d.ts.map +1 -1
  70. package/dist/managers/index.js +5 -1
  71. package/dist/managers/index.js.map +1 -1
  72. package/dist/managers/message-router.d.ts +1 -1
  73. package/dist/managers/message-router.d.ts.map +1 -1
  74. package/dist/managers/message-router.js +41 -4
  75. package/dist/managers/message-router.js.map +1 -1
  76. package/dist/managers/room-management-manager.d.ts +213 -0
  77. package/dist/managers/room-management-manager.d.ts.map +1 -0
  78. package/dist/managers/room-management-manager.js +440 -0
  79. package/dist/managers/room-management-manager.js.map +1 -0
  80. package/dist/managers/room-manager.d.ts +4 -4
  81. package/dist/managers/room-manager.d.ts.map +1 -1
  82. package/dist/managers/room-manager.js +1 -1
  83. package/dist/managers/room-manager.js.map +1 -1
  84. package/dist/teneo-sdk.d.ts +362 -14
  85. package/dist/teneo-sdk.d.ts.map +1 -1
  86. package/dist/teneo-sdk.js +497 -7
  87. package/dist/teneo-sdk.js.map +1 -1
  88. package/dist/types/config.d.ts +63 -54
  89. package/dist/types/config.d.ts.map +1 -1
  90. package/dist/types/config.js +9 -5
  91. package/dist/types/config.js.map +1 -1
  92. package/dist/types/error-codes.d.ts +2 -0
  93. package/dist/types/error-codes.d.ts.map +1 -1
  94. package/dist/types/error-codes.js +3 -0
  95. package/dist/types/error-codes.js.map +1 -1
  96. package/dist/types/events.d.ts +132 -68
  97. package/dist/types/events.d.ts.map +1 -1
  98. package/dist/types/events.js.map +1 -1
  99. package/dist/types/index.d.ts +1 -1
  100. package/dist/types/index.d.ts.map +1 -1
  101. package/dist/types/index.js +27 -2
  102. package/dist/types/index.js.map +1 -1
  103. package/dist/types/messages.d.ts +11396 -2559
  104. package/dist/types/messages.d.ts.map +1 -1
  105. package/dist/types/messages.js +294 -27
  106. package/dist/types/messages.js.map +1 -1
  107. package/dist/types/validation.d.ts.map +1 -1
  108. package/dist/types/validation.js +1 -1
  109. package/dist/types/validation.js.map +1 -1
  110. package/dist/utils/bounded-queue.d.ts +1 -1
  111. package/dist/utils/bounded-queue.js +6 -6
  112. package/dist/utils/circuit-breaker.d.ts.map +1 -1
  113. package/dist/utils/circuit-breaker.js.map +1 -1
  114. package/dist/utils/event-waiter.d.ts.map +1 -1
  115. package/dist/utils/event-waiter.js +2 -1
  116. package/dist/utils/event-waiter.js.map +1 -1
  117. package/dist/utils/rate-limiter.d.ts.map +1 -1
  118. package/dist/utils/rate-limiter.js +4 -6
  119. package/dist/utils/rate-limiter.js.map +1 -1
  120. package/dist/utils/secure-private-key.d.ts.map +1 -1
  121. package/dist/utils/secure-private-key.js +9 -15
  122. package/dist/utils/secure-private-key.js.map +1 -1
  123. package/dist/utils/signature-verifier.d.ts +2 -2
  124. package/dist/utils/signature-verifier.d.ts.map +1 -1
  125. package/dist/utils/signature-verifier.js +5 -5
  126. package/dist/utils/signature-verifier.js.map +1 -1
  127. package/examples/.env.example +1 -1
  128. package/examples/agent-room-management-example.ts +334 -0
  129. package/examples/claude-agent-x-follower/.env.example +117 -0
  130. package/examples/claude-agent-x-follower/QUICKSTART.md +243 -0
  131. package/examples/claude-agent-x-follower/README.md +540 -0
  132. package/examples/claude-agent-x-follower/index.ts +248 -0
  133. package/examples/claude-agent-x-follower/package.json +37 -0
  134. package/examples/claude-agent-x-follower/tsconfig.json +20 -0
  135. package/examples/n8n-teneo/.env.example +127 -0
  136. package/examples/n8n-teneo/Dockerfile +42 -0
  137. package/examples/n8n-teneo/README.md +564 -0
  138. package/examples/n8n-teneo/docker-compose.yml +71 -0
  139. package/examples/n8n-teneo/index.ts +177 -0
  140. package/examples/n8n-teneo/package.json +22 -0
  141. package/examples/n8n-teneo/tsconfig.json +12 -0
  142. package/examples/n8n-teneo/workflows/x-timeline.json +66 -0
  143. package/examples/openai-teneo/.env.example +130 -0
  144. package/examples/openai-teneo/README.md +635 -0
  145. package/examples/openai-teneo/index.ts +280 -0
  146. package/examples/openai-teneo/package.json +24 -0
  147. package/examples/openai-teneo/tsconfig.json +16 -0
  148. package/examples/production-dashboard/.env.example +5 -3
  149. package/examples/production-dashboard/README.md +839 -0
  150. package/examples/production-dashboard/pnpm-lock.yaml +92 -0
  151. package/examples/production-dashboard/public/dashboard.html +1150 -504
  152. package/examples/production-dashboard/server.ts +428 -12
  153. package/examples/room-management-example.ts +285 -0
  154. package/examples/usage/.env.example +17 -0
  155. package/examples/usage/01-connect.ts +116 -0
  156. package/examples/usage/02-list-agents.ts +153 -0
  157. package/examples/usage/03-pick-agent.ts +201 -0
  158. package/examples/usage/04-find-by-capability.ts +237 -0
  159. package/examples/usage/05-webhook-example.ts +319 -0
  160. package/examples/usage/06-simple-api-server.ts +396 -0
  161. package/examples/usage/07-event-listener.ts +402 -0
  162. package/examples/usage/README.md +383 -0
  163. package/examples/usage/package.json +42 -0
  164. package/package.json +13 -3
  165. package/src/core/websocket-client.ts +43 -9
  166. package/src/formatters/response-formatter.test.ts +8 -2
  167. package/src/handlers/message-handlers/agent-room-operation-response-handler.ts +83 -0
  168. package/src/handlers/message-handlers/agent-status-update-handler.ts +58 -0
  169. package/src/handlers/message-handlers/auth-message-handler.ts +73 -5
  170. package/src/handlers/message-handlers/auth-success-handler.ts +58 -6
  171. package/src/handlers/message-handlers/index.ts +19 -0
  172. package/src/handlers/message-handlers/list-available-agents-handler.ts +41 -0
  173. package/src/handlers/message-handlers/list-room-agents-handler.ts +61 -0
  174. package/src/handlers/message-handlers/regular-message-handler.ts +1 -0
  175. package/src/handlers/message-handlers/room-operation-response-handler.ts +105 -0
  176. package/src/handlers/message-handlers/types.ts +6 -0
  177. package/src/handlers/webhook-handler.test.ts +13 -10
  178. package/src/managers/agent-room-manager.ts +609 -0
  179. package/src/managers/index.ts +2 -0
  180. package/src/managers/message-router.ts +48 -6
  181. package/src/managers/room-management-manager.ts +523 -0
  182. package/src/managers/room-manager.ts +12 -6
  183. package/src/teneo-sdk.ts +543 -10
  184. package/src/types/config.ts +13 -6
  185. package/src/types/error-codes.ts +4 -0
  186. package/src/types/events.ts +24 -0
  187. package/src/types/index.ts +55 -0
  188. package/src/types/messages.ts +374 -41
  189. package/src/types/validation.ts +4 -1
  190. package/src/utils/bounded-queue.ts +9 -9
  191. package/src/utils/circuit-breaker.ts +4 -1
  192. package/src/utils/deduplication-cache.test.ts +2 -6
  193. package/src/utils/event-waiter.test.ts +4 -1
  194. package/src/utils/event-waiter.ts +5 -7
  195. package/src/utils/rate-limiter.test.ts +5 -17
  196. package/src/utils/rate-limiter.ts +6 -9
  197. package/src/utils/secure-private-key.test.ts +66 -59
  198. package/src/utils/secure-private-key.ts +10 -16
  199. package/src/utils/signature-verifier.test.ts +75 -70
  200. package/src/utils/signature-verifier.ts +7 -8
  201. package/src/utils/ssrf-validator.test.ts +3 -3
  202. package/tests/integration/room-management.test.ts +514 -0
  203. package/tests/integration/websocket.test.ts +1 -1
  204. package/tests/unit/handlers/agent-room-operation-response-handler.test.ts +394 -0
  205. package/tests/unit/handlers/agent-status-update-handler.test.ts +407 -0
  206. package/tests/unit/handlers/auth-success-handler-rooms.test.ts +699 -0
  207. package/tests/unit/handlers/list-available-agents-handler.test.ts +256 -0
  208. package/tests/unit/handlers/list-room-agents-handler.test.ts +294 -0
  209. package/tests/unit/handlers/room-operation-response-handler.test.ts +527 -0
  210. package/tests/unit/managers/agent-room-manager.test.ts +534 -0
  211. package/tests/unit/managers/room-management-manager.test.ts +438 -0
@@ -31,7 +31,10 @@ export interface CircuitBreakerOptions {
31
31
  * Error thrown when circuit is open
32
32
  */
33
33
  export class CircuitBreakerError extends Error {
34
- constructor(message: string, public readonly state: CircuitState) {
34
+ constructor(
35
+ message: string,
36
+ public readonly state: CircuitState
37
+ ) {
35
38
  super(message);
36
39
  this.name = "CircuitBreakerError";
37
40
 
@@ -25,15 +25,11 @@ describe("DeduplicationCache", () => {
25
25
  });
26
26
 
27
27
  it("should throw error if TTL is less than 1000ms", () => {
28
- expect(() => new DeduplicationCache(999)).toThrow(
29
- "TTL must be at least 1000ms"
30
- );
28
+ expect(() => new DeduplicationCache(999)).toThrow("TTL must be at least 1000ms");
31
29
  });
32
30
 
33
31
  it("should throw error if maxSize is less than 1", () => {
34
- expect(() => new DeduplicationCache(5000, 0)).toThrow(
35
- "maxSize must be at least 1"
36
- );
32
+ expect(() => new DeduplicationCache(5000, 0)).toThrow("maxSize must be at least 1");
37
33
  });
38
34
  });
39
35
 
@@ -376,6 +376,9 @@ describe("waitForAllEvents", () => {
376
376
  emitter.emit("data", { id: 1, value: "first" });
377
377
 
378
378
  const results = await promise;
379
- expect(results).toEqual([{ id: 1, value: "first" }, { id: 2, value: "second" }]);
379
+ expect(results).toEqual([
380
+ { id: 1, value: "first" },
381
+ { id: 2, value: "second" }
382
+ ]);
380
383
  });
381
384
  });
@@ -102,7 +102,9 @@ export async function waitForEvent<T = any>(
102
102
  // Timeout handler - rejects after timeout
103
103
  timeoutHandle = setTimeout(() => {
104
104
  cleanup();
105
- const message = options.timeoutMessage || `Timeout waiting for event '${eventName}' after ${options.timeout}ms`;
105
+ const message =
106
+ options.timeoutMessage ||
107
+ `Timeout waiting for event '${eventName}' after ${options.timeout}ms`;
106
108
  reject(new Error(message));
107
109
  }, options.timeout);
108
110
 
@@ -135,9 +137,7 @@ export async function waitForAnyEvent<T = any>(
135
137
  }>
136
138
  ): Promise<T> {
137
139
  return Promise.race(
138
- waiters.map(({ emitter, eventName, options }) =>
139
- waitForEvent<T>(emitter, eventName, options)
140
- )
140
+ waiters.map(({ emitter, eventName, options }) => waitForEvent<T>(emitter, eventName, options))
141
141
  );
142
142
  }
143
143
 
@@ -165,8 +165,6 @@ export async function waitForAllEvents<T = any>(
165
165
  }>
166
166
  ): Promise<T[]> {
167
167
  return Promise.all(
168
- waiters.map(({ emitter, eventName, options }) =>
169
- waitForEvent<T>(emitter, eventName, options)
170
- )
168
+ waiters.map(({ emitter, eventName, options }) => waitForEvent<T>(emitter, eventName, options))
171
169
  );
172
170
  }
@@ -17,21 +17,15 @@ describe("TokenBucketRateLimiter", () => {
17
17
  });
18
18
 
19
19
  it("should throw error if tokensPerSecond is less than 1", () => {
20
- expect(() => new TokenBucketRateLimiter(0, 10)).toThrow(
21
- "tokensPerSecond must be at least 1"
22
- );
20
+ expect(() => new TokenBucketRateLimiter(0, 10)).toThrow("tokensPerSecond must be at least 1");
23
21
  expect(() => new TokenBucketRateLimiter(-1, 10)).toThrow(
24
22
  "tokensPerSecond must be at least 1"
25
23
  );
26
24
  });
27
25
 
28
26
  it("should throw error if maxBurst is less than 1", () => {
29
- expect(() => new TokenBucketRateLimiter(10, 0)).toThrow(
30
- "maxBurst must be at least 1"
31
- );
32
- expect(() => new TokenBucketRateLimiter(10, -1)).toThrow(
33
- "maxBurst must be at least 1"
34
- );
27
+ expect(() => new TokenBucketRateLimiter(10, 0)).toThrow("maxBurst must be at least 1");
28
+ expect(() => new TokenBucketRateLimiter(10, -1)).toThrow("maxBurst must be at least 1");
35
29
  });
36
30
  });
37
31
 
@@ -159,9 +153,7 @@ describe("TokenBucketRateLimiter", () => {
159
153
  // Reset and try again to verify error message
160
154
  limiter.reset();
161
155
  limiter.tryConsume();
162
- await expect(limiter.consume(10)).rejects.toThrow(
163
- /Rate limit timeout/
164
- );
156
+ await expect(limiter.consume(10)).rejects.toThrow(/Rate limit timeout/);
165
157
  });
166
158
 
167
159
  it("should succeed within timeout if token becomes available", async () => {
@@ -309,11 +301,7 @@ describe("TokenBucketRateLimiter", () => {
309
301
  limiter.tryConsume();
310
302
 
311
303
  // Start multiple blocking consume calls
312
- const promises = [
313
- limiter.consume(1000),
314
- limiter.consume(1000),
315
- limiter.consume(1000)
316
- ];
304
+ const promises = [limiter.consume(1000), limiter.consume(1000), limiter.consume(1000)];
317
305
 
318
306
  // All should eventually succeed as tokens refill
319
307
  await expect(Promise.all(promises)).resolves.toBeDefined();
@@ -13,7 +13,7 @@
13
13
  export class RateLimitError extends Error {
14
14
  constructor(message: string) {
15
15
  super(message);
16
- this.name = 'RateLimitError';
16
+ this.name = "RateLimitError";
17
17
 
18
18
  if (Error.captureStackTrace) {
19
19
  Error.captureStackTrace(this, RateLimitError);
@@ -64,10 +64,10 @@ export class TokenBucketRateLimiter {
64
64
  private readonly maxBurst: number
65
65
  ) {
66
66
  if (tokensPerSecond < 1) {
67
- throw new Error('TokenBucketRateLimiter tokensPerSecond must be at least 1');
67
+ throw new Error("TokenBucketRateLimiter tokensPerSecond must be at least 1");
68
68
  }
69
69
  if (maxBurst < 1) {
70
- throw new Error('TokenBucketRateLimiter maxBurst must be at least 1');
70
+ throw new Error("TokenBucketRateLimiter maxBurst must be at least 1");
71
71
  }
72
72
 
73
73
  this.tokens = maxBurst; // Start with full bucket
@@ -131,17 +131,14 @@ export class TokenBucketRateLimiter {
131
131
  // Check timeout
132
132
  const elapsed = Date.now() - startTime;
133
133
  if (timeout !== undefined && elapsed >= timeout) {
134
- throw new RateLimitError(
135
- `Rate limit timeout: no token available after ${timeout}ms`
136
- );
134
+ throw new RateLimitError(`Rate limit timeout: no token available after ${timeout}ms`);
137
135
  }
138
136
 
139
137
  // Calculate wait time until next token
140
138
  // If timeout is specified, don't wait longer than remaining timeout
141
139
  const baseWaitTime = Math.min(this.refillInterval, 100);
142
- const waitTime = timeout !== undefined
143
- ? Math.min(baseWaitTime, timeout - elapsed)
144
- : baseWaitTime;
140
+ const waitTime =
141
+ timeout !== undefined ? Math.min(baseWaitTime, timeout - elapsed) : baseWaitTime;
145
142
 
146
143
  // If waitTime is very small or negative, check timeout immediately
147
144
  if (waitTime <= 0) {
@@ -3,65 +3,72 @@
3
3
  * Verifies secure encryption, decryption, memory cleanup, and integration with viem
4
4
  */
5
5
 
6
- import { SecurePrivateKey } from './secure-private-key';
7
- import { privateKeyToAccount } from 'viem/accounts';
6
+ import { SecurePrivateKey } from "./secure-private-key";
7
+ import { privateKeyToAccount } from "viem/accounts";
8
8
 
9
- describe('SecurePrivateKey', () => {
9
+ describe("SecurePrivateKey", () => {
10
10
  // Test private key (do NOT use in production)
11
- const testPrivateKey = '0x1234567890123456789012345678901234567890123456789012345678901234';
11
+ const testPrivateKey = "0x1234567890123456789012345678901234567890123456789012345678901234";
12
12
 
13
- describe('constructor', () => {
14
- it('should create instance with valid private key', () => {
13
+ describe("constructor", () => {
14
+ it("should create instance with valid private key", () => {
15
15
  const secureKey = new SecurePrivateKey(testPrivateKey);
16
16
  expect(secureKey).toBeInstanceOf(SecurePrivateKey);
17
17
  expect(secureKey.isDestroyed()).toBe(false);
18
18
  secureKey.destroy();
19
19
  });
20
20
 
21
- it('should throw error with empty private key', () => {
22
- expect(() => new SecurePrivateKey('')).toThrow('Private key must be a non-empty string');
21
+ it("should throw error with empty private key", () => {
22
+ expect(() => new SecurePrivateKey("")).toThrow("Private key must be a non-empty string");
23
23
  });
24
24
 
25
- it('should throw error with null private key', () => {
26
- expect(() => new SecurePrivateKey(null as any)).toThrow('Private key must be a non-empty string');
25
+ it("should throw error with null private key", () => {
26
+ expect(() => new SecurePrivateKey(null as any)).toThrow(
27
+ "Private key must be a non-empty string"
28
+ );
27
29
  });
28
30
 
29
- it('should throw error with undefined private key', () => {
31
+ it("should throw error with undefined private key", () => {
30
32
  expect(() => new SecurePrivateKey(undefined as any)).toThrow(
31
- 'Private key must be a non-empty string'
33
+ "Private key must be a non-empty string"
32
34
  );
33
35
  });
34
36
 
35
- it('should throw error with non-string private key', () => {
36
- expect(() => new SecurePrivateKey(123 as any)).toThrow('Private key must be a non-empty string');
37
+ it("should throw error with non-string private key", () => {
38
+ expect(() => new SecurePrivateKey(123 as any)).toThrow(
39
+ "Private key must be a non-empty string"
40
+ );
37
41
  });
38
42
  });
39
43
 
40
- describe('use()', () => {
41
- it('should decrypt and pass key to callback', () => {
44
+ describe("use()", () => {
45
+ it("should decrypt and pass key to callback", () => {
42
46
  const secureKey = new SecurePrivateKey(testPrivateKey);
43
47
 
44
48
  const result = secureKey.use((key) => {
45
49
  expect(key).toBe(testPrivateKey);
46
- return 'success';
50
+ return "success";
47
51
  });
48
52
 
49
- expect(result).toBe('success');
53
+ expect(result).toBe("success");
50
54
  secureKey.destroy();
51
55
  });
52
56
 
53
- it('should return callback result', () => {
57
+ it("should return callback result", () => {
54
58
  const secureKey = new SecurePrivateKey(testPrivateKey);
55
59
 
56
60
  const result = secureKey.use((key) => {
57
61
  return { key: key.substring(0, 10), length: key.length };
58
62
  });
59
63
 
60
- expect(result).toEqual({ key: testPrivateKey.substring(0, 10), length: testPrivateKey.length });
64
+ expect(result).toEqual({
65
+ key: testPrivateKey.substring(0, 10),
66
+ length: testPrivateKey.length
67
+ });
61
68
  secureKey.destroy();
62
69
  });
63
70
 
64
- it('should work with async callbacks', async () => {
71
+ it("should work with async callbacks", async () => {
65
72
  const secureKey = new SecurePrivateKey(testPrivateKey);
66
73
 
67
74
  const result = await secureKey.use(async (key) => {
@@ -73,7 +80,7 @@ describe('SecurePrivateKey', () => {
73
80
  secureKey.destroy();
74
81
  });
75
82
 
76
- it('should allow multiple uses', () => {
83
+ it("should allow multiple uses", () => {
77
84
  const secureKey = new SecurePrivateKey(testPrivateKey);
78
85
 
79
86
  const result1 = secureKey.use((key) => key.length);
@@ -87,33 +94,33 @@ describe('SecurePrivateKey', () => {
87
94
  secureKey.destroy();
88
95
  });
89
96
 
90
- it('should throw if key has been destroyed', () => {
97
+ it("should throw if key has been destroyed", () => {
91
98
  const secureKey = new SecurePrivateKey(testPrivateKey);
92
99
  secureKey.destroy();
93
100
 
94
101
  expect(() => {
95
102
  secureKey.use((key) => key);
96
- }).toThrow('SecurePrivateKey has been destroyed and can no longer be used');
103
+ }).toThrow("SecurePrivateKey has been destroyed and can no longer be used");
97
104
  });
98
105
 
99
- it('should propagate errors from callback', () => {
106
+ it("should propagate errors from callback", () => {
100
107
  const secureKey = new SecurePrivateKey(testPrivateKey);
101
108
 
102
109
  expect(() => {
103
110
  secureKey.use((key) => {
104
- throw new Error('Test error');
111
+ throw new Error("Test error");
105
112
  });
106
- }).toThrow('Test error');
113
+ }).toThrow("Test error");
107
114
 
108
115
  secureKey.destroy();
109
116
  });
110
117
 
111
- it('should clean up even if callback throws', () => {
118
+ it("should clean up even if callback throws", () => {
112
119
  const secureKey = new SecurePrivateKey(testPrivateKey);
113
120
 
114
121
  try {
115
122
  secureKey.use((key) => {
116
- throw new Error('Test error');
123
+ throw new Error("Test error");
117
124
  });
118
125
  } catch (error) {
119
126
  // Expected
@@ -127,8 +134,8 @@ describe('SecurePrivateKey', () => {
127
134
  });
128
135
  });
129
136
 
130
- describe('destroy()', () => {
131
- it('should mark instance as destroyed', () => {
137
+ describe("destroy()", () => {
138
+ it("should mark instance as destroyed", () => {
132
139
  const secureKey = new SecurePrivateKey(testPrivateKey);
133
140
  expect(secureKey.isDestroyed()).toBe(false);
134
141
 
@@ -136,7 +143,7 @@ describe('SecurePrivateKey', () => {
136
143
  expect(secureKey.isDestroyed()).toBe(true);
137
144
  });
138
145
 
139
- it('should be idempotent (safe to call multiple times)', () => {
146
+ it("should be idempotent (safe to call multiple times)", () => {
140
147
  const secureKey = new SecurePrivateKey(testPrivateKey);
141
148
 
142
149
  secureKey.destroy();
@@ -146,32 +153,32 @@ describe('SecurePrivateKey', () => {
146
153
  expect(secureKey.isDestroyed()).toBe(true);
147
154
  });
148
155
 
149
- it('should prevent further use after destruction', () => {
156
+ it("should prevent further use after destruction", () => {
150
157
  const secureKey = new SecurePrivateKey(testPrivateKey);
151
158
  secureKey.destroy();
152
159
 
153
160
  expect(() => {
154
161
  secureKey.use((key) => key);
155
- }).toThrow('SecurePrivateKey has been destroyed');
162
+ }).toThrow("SecurePrivateKey has been destroyed");
156
163
  });
157
164
  });
158
165
 
159
- describe('isDestroyed()', () => {
160
- it('should return false for new instance', () => {
166
+ describe("isDestroyed()", () => {
167
+ it("should return false for new instance", () => {
161
168
  const secureKey = new SecurePrivateKey(testPrivateKey);
162
169
  expect(secureKey.isDestroyed()).toBe(false);
163
170
  secureKey.destroy();
164
171
  });
165
172
 
166
- it('should return true after destruction', () => {
173
+ it("should return true after destruction", () => {
167
174
  const secureKey = new SecurePrivateKey(testPrivateKey);
168
175
  secureKey.destroy();
169
176
  expect(secureKey.isDestroyed()).toBe(true);
170
177
  });
171
178
  });
172
179
 
173
- describe('encryption/decryption', () => {
174
- it('should correctly encrypt and decrypt private key', () => {
180
+ describe("encryption/decryption", () => {
181
+ it("should correctly encrypt and decrypt private key", () => {
175
182
  const secureKey = new SecurePrivateKey(testPrivateKey);
176
183
 
177
184
  const decrypted = secureKey.use((key) => key);
@@ -180,8 +187,8 @@ describe('SecurePrivateKey', () => {
180
187
  secureKey.destroy();
181
188
  });
182
189
 
183
- it('should handle keys with special characters', () => {
184
- const specialKey = '0xABCDEF123456!@#$%^&*()_+-=[]{}|;:,.<>?';
190
+ it("should handle keys with special characters", () => {
191
+ const specialKey = "0xABCDEF123456!@#$%^&*()_+-=[]{}|;:,.<>?";
185
192
  const secureKey = new SecurePrivateKey(specialKey);
186
193
 
187
194
  const decrypted = secureKey.use((key) => key);
@@ -190,8 +197,8 @@ describe('SecurePrivateKey', () => {
190
197
  secureKey.destroy();
191
198
  });
192
199
 
193
- it('should handle very long keys', () => {
194
- const longKey = '0x' + 'a'.repeat(1000);
200
+ it("should handle very long keys", () => {
201
+ const longKey = "0x" + "a".repeat(1000);
195
202
  const secureKey = new SecurePrivateKey(longKey);
196
203
 
197
204
  const decrypted = secureKey.use((key) => key);
@@ -200,7 +207,7 @@ describe('SecurePrivateKey', () => {
200
207
  secureKey.destroy();
201
208
  });
202
209
 
203
- it('should produce different encrypted data for same key (random IV)', () => {
210
+ it("should produce different encrypted data for same key (random IV)", () => {
204
211
  const secureKey1 = new SecurePrivateKey(testPrivateKey);
205
212
  const secureKey2 = new SecurePrivateKey(testPrivateKey);
206
213
 
@@ -223,8 +230,8 @@ describe('SecurePrivateKey', () => {
223
230
  });
224
231
  });
225
232
 
226
- describe('integration with viem', () => {
227
- it('should work with privateKeyToAccount', () => {
233
+ describe("integration with viem", () => {
234
+ it("should work with privateKeyToAccount", () => {
228
235
  const secureKey = new SecurePrivateKey(testPrivateKey);
229
236
 
230
237
  const account = secureKey.use((key) => {
@@ -238,14 +245,14 @@ describe('SecurePrivateKey', () => {
238
245
  secureKey.destroy();
239
246
  });
240
247
 
241
- it('should allow signing messages with account created from secure key', async () => {
248
+ it("should allow signing messages with account created from secure key", async () => {
242
249
  const secureKey = new SecurePrivateKey(testPrivateKey);
243
250
 
244
251
  const account = secureKey.use((key) => {
245
252
  return privateKeyToAccount(key as `0x${string}`);
246
253
  });
247
254
 
248
- const message = 'Hello, Teneo!';
255
+ const message = "Hello, Teneo!";
249
256
  const signature = await account.signMessage({ message });
250
257
 
251
258
  expect(signature).toBeDefined();
@@ -255,7 +262,7 @@ describe('SecurePrivateKey', () => {
255
262
  secureKey.destroy();
256
263
  });
257
264
 
258
- it('should create consistent account address across multiple uses', () => {
265
+ it("should create consistent account address across multiple uses", () => {
259
266
  const secureKey = new SecurePrivateKey(testPrivateKey);
260
267
 
261
268
  const address1 = secureKey.use((key) => {
@@ -272,8 +279,8 @@ describe('SecurePrivateKey', () => {
272
279
  });
273
280
  });
274
281
 
275
- describe('security properties', () => {
276
- it('should not expose private key in toString()', () => {
282
+ describe("security properties", () => {
283
+ it("should not expose private key in toString()", () => {
277
284
  const secureKey = new SecurePrivateKey(testPrivateKey);
278
285
 
279
286
  const stringified = String(secureKey);
@@ -283,7 +290,7 @@ describe('SecurePrivateKey', () => {
283
290
  secureKey.destroy();
284
291
  });
285
292
 
286
- it('should not expose private key in JSON.stringify()', () => {
293
+ it("should not expose private key in JSON.stringify()", () => {
287
294
  const secureKey = new SecurePrivateKey(testPrivateKey);
288
295
 
289
296
  const jsonString = JSON.stringify(secureKey);
@@ -293,7 +300,7 @@ describe('SecurePrivateKey', () => {
293
300
  secureKey.destroy();
294
301
  });
295
302
 
296
- it('should not expose private key when inspecting object', () => {
303
+ it("should not expose private key when inspecting object", () => {
297
304
  const secureKey = new SecurePrivateKey(testPrivateKey);
298
305
 
299
306
  // Try to access private properties (they're still accessible via 'any' but not exposed)
@@ -307,23 +314,23 @@ describe('SecurePrivateKey', () => {
307
314
  secureKey.destroy();
308
315
  });
309
316
 
310
- it('should store key encrypted in memory', () => {
317
+ it("should store key encrypted in memory", () => {
311
318
  const secureKey = new SecurePrivateKey(testPrivateKey);
312
319
 
313
320
  // Access encrypted buffer via any
314
321
  const encrypted = (secureKey as any).encrypted as Buffer;
315
322
 
316
323
  // Encrypted data should not contain the plaintext key
317
- const encryptedString = encrypted.toString('utf8');
324
+ const encryptedString = encrypted.toString("utf8");
318
325
  expect(encryptedString).not.toContain(testPrivateKey);
319
- expect(encryptedString).not.toContain('1234567890');
326
+ expect(encryptedString).not.toContain("1234567890");
320
327
 
321
328
  secureKey.destroy();
322
329
  });
323
330
  });
324
331
 
325
- describe('memory cleanup', () => {
326
- it('should zero out encryption key on destroy', () => {
332
+ describe("memory cleanup", () => {
333
+ it("should zero out encryption key on destroy", () => {
327
334
  const secureKey = new SecurePrivateKey(testPrivateKey);
328
335
 
329
336
  // Get reference to encryption key before destroy
@@ -338,7 +345,7 @@ describe('SecurePrivateKey', () => {
338
345
  expect(encryptionKey.every((byte) => byte === 0)).toBe(true);
339
346
  });
340
347
 
341
- it('should zero out encrypted buffer on destroy', () => {
348
+ it("should zero out encrypted buffer on destroy", () => {
342
349
  const secureKey = new SecurePrivateKey(testPrivateKey);
343
350
 
344
351
  // Get reference to encrypted buffer before destroy
@@ -19,7 +19,7 @@
19
19
  * ```
20
20
  */
21
21
 
22
- import crypto from 'crypto';
22
+ import crypto from "crypto";
23
23
 
24
24
  /**
25
25
  * Securely stores and manages an encrypted private key in memory.
@@ -42,8 +42,8 @@ export class SecurePrivateKey {
42
42
  * @throws {Error} If private key is empty or invalid
43
43
  */
44
44
  constructor(privateKey: string) {
45
- if (!privateKey || typeof privateKey !== 'string') {
46
- throw new Error('Private key must be a non-empty string');
45
+ if (!privateKey || typeof privateKey !== "string") {
46
+ throw new Error("Private key must be a non-empty string");
47
47
  }
48
48
 
49
49
  // Generate a random encryption key for AES-256
@@ -136,13 +136,10 @@ export class SecurePrivateKey {
136
136
  const iv = crypto.randomBytes(16);
137
137
 
138
138
  // Create cipher
139
- const cipher = crypto.createCipheriv('aes-256-gcm', this.encryptionKey, iv);
139
+ const cipher = crypto.createCipheriv("aes-256-gcm", this.encryptionKey, iv);
140
140
 
141
141
  // Encrypt the data
142
- const encrypted = Buffer.concat([
143
- cipher.update(data, 'utf8'),
144
- cipher.final()
145
- ]);
142
+ const encrypted = Buffer.concat([cipher.update(data, "utf8"), cipher.final()]);
146
143
 
147
144
  // Get authentication tag for integrity verification
148
145
  const authTag = cipher.getAuthTag();
@@ -164,16 +161,13 @@ export class SecurePrivateKey {
164
161
  const ciphertext = this.encrypted.subarray(32);
165
162
 
166
163
  // Create decipher
167
- const decipher = crypto.createDecipheriv('aes-256-gcm', this.encryptionKey, iv);
164
+ const decipher = crypto.createDecipheriv("aes-256-gcm", this.encryptionKey, iv);
168
165
  decipher.setAuthTag(authTag);
169
166
 
170
167
  // Decrypt the data
171
- const decrypted = Buffer.concat([
172
- decipher.update(ciphertext),
173
- decipher.final()
174
- ]);
168
+ const decrypted = Buffer.concat([decipher.update(ciphertext), decipher.final()]);
175
169
 
176
- return decrypted.toString('utf8');
170
+ return decrypted.toString("utf8");
177
171
  }
178
172
 
179
173
  /**
@@ -185,7 +179,7 @@ export class SecurePrivateKey {
185
179
  */
186
180
  private zeroOutString(str: string): void {
187
181
  // Convert to buffer and zero it out
188
- const buffer = Buffer.from(str, 'utf8');
182
+ const buffer = Buffer.from(str, "utf8");
189
183
  buffer.fill(0);
190
184
 
191
185
  // Note: The original string object may still exist in memory
@@ -199,7 +193,7 @@ export class SecurePrivateKey {
199
193
  */
200
194
  private checkNotDestroyed(): void {
201
195
  if (this.destroyed) {
202
- throw new Error('SecurePrivateKey has been destroyed and can no longer be used');
196
+ throw new Error("SecurePrivateKey has been destroyed and can no longer be used");
203
197
  }
204
198
  }
205
199
  }