@keyringnetwork/keyring-connect-sdk 3.1.0 → 4.1.0-alpha.1

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 (69) hide show
  1. package/dist/core/VerificationSession.d.ts +62 -0
  2. package/dist/core/VerificationSession.js +404 -0
  3. package/dist/core/errors.d.ts +49 -0
  4. package/dist/core/errors.js +81 -0
  5. package/dist/core/htppClient.d.ts +17 -0
  6. package/dist/core/htppClient.js +160 -0
  7. package/dist/{main.d.ts → core/keyringConnectExtension.d.ts} +9 -7
  8. package/dist/{main.js → core/keyringConnectExtension.js} +53 -46
  9. package/dist/core/websocketClient.d.ts +23 -0
  10. package/dist/core/websocketClient.js +220 -0
  11. package/dist/index.d.ts +1 -1
  12. package/dist/index.js +3 -3
  13. package/dist/types/api.d.ts +24 -0
  14. package/dist/types/api.js +2 -0
  15. package/dist/types/core.d.ts +78 -0
  16. package/dist/types/core.js +2 -0
  17. package/dist/types/extension.d.ts +59 -0
  18. package/dist/types/index.d.ts +4 -0
  19. package/dist/types/index.js +20 -0
  20. package/dist/types/websocket.d.ts +68 -0
  21. package/dist/types/websocket.js +3 -0
  22. package/dist/ui/UIManager.d.ts +52 -0
  23. package/dist/ui/UIManager.js +257 -0
  24. package/dist/ui/components/keyring-button.d.ts +12 -0
  25. package/dist/ui/components/keyring-button.js +140 -0
  26. package/dist/ui/components/keyring-text.d.ts +12 -0
  27. package/dist/ui/components/keyring-text.js +169 -0
  28. package/dist/ui/composites/keyring-complete-modal.d.ts +19 -0
  29. package/dist/ui/composites/keyring-complete-modal.js +200 -0
  30. package/dist/ui/composites/keyring-mobile-modal.d.ts +25 -0
  31. package/dist/ui/composites/keyring-mobile-modal.js +308 -0
  32. package/dist/ui/composites/keyring-qr-modal.d.ts +32 -0
  33. package/dist/ui/composites/keyring-qr-modal.js +464 -0
  34. package/dist/ui/composites/keyring-selection-modal.d.ts +25 -0
  35. package/dist/ui/composites/keyring-selection-modal.js +342 -0
  36. package/dist/ui/composites/keyring-terminated-modal.d.ts +14 -0
  37. package/dist/ui/composites/keyring-terminated-modal.js +121 -0
  38. package/dist/ui/icons/apple-icon.d.ts +4 -0
  39. package/dist/ui/icons/apple-icon.js +47 -0
  40. package/dist/ui/icons/check-circle.d.ts +4 -0
  41. package/dist/ui/icons/check-circle.js +35 -0
  42. package/dist/ui/icons/checkmark.d.ts +4 -0
  43. package/dist/ui/icons/checkmark.js +37 -0
  44. package/dist/ui/icons/close-circle.d.ts +4 -0
  45. package/dist/ui/icons/close-circle.js +35 -0
  46. package/dist/ui/icons/error-circle.d.ts +4 -0
  47. package/dist/ui/icons/error-circle.js +48 -0
  48. package/dist/ui/icons/extension-grid.d.ts +4 -0
  49. package/dist/ui/icons/extension-grid.js +79 -0
  50. package/dist/ui/icons/google-icon.d.ts +4 -0
  51. package/dist/ui/icons/google-icon.js +55 -0
  52. package/dist/ui/icons/gradient-donut.d.ts +8 -0
  53. package/dist/ui/icons/gradient-donut.js +85 -0
  54. package/dist/ui/icons/keyring.d.ts +4 -0
  55. package/dist/ui/icons/keyring.js +71 -0
  56. package/dist/ui/icons/mobile-grid.d.ts +4 -0
  57. package/dist/ui/icons/mobile-grid.js +68 -0
  58. package/dist/ui/icons/success.d.ts +4 -0
  59. package/dist/ui/icons/success.js +54 -0
  60. package/dist/utils/environment.d.ts +34 -0
  61. package/dist/utils/environment.js +67 -0
  62. package/dist/utils/logger.d.ts +7 -0
  63. package/dist/utils/logger.js +40 -0
  64. package/dist/utils/platformUtils.d.ts +24 -0
  65. package/dist/utils/platformUtils.js +64 -0
  66. package/package.json +32 -9
  67. package/readme.md +57 -105
  68. package/dist/types.d.ts +0 -159
  69. /package/dist/{types.js → types/extension.js} +0 -0
@@ -0,0 +1,62 @@
1
+ import { CredentialData, SDKEventData, SDKEventTypes, SessionConfig } from "../types";
2
+ /**
3
+ * Represents an active verification session with proper cleanup
4
+ */
5
+ export declare class VerificationSession {
6
+ private readonly sessionConfig;
7
+ private static activeSession;
8
+ private static staticLogger;
9
+ private logger;
10
+ private httpClient?;
11
+ private wsClient?;
12
+ private sessionResponse?;
13
+ private stopPolling?;
14
+ private uiManager?;
15
+ private eventListeners;
16
+ private isWebsocketActive;
17
+ private resultPromise?;
18
+ private resolveResult?;
19
+ private rejectResult?;
20
+ private constructor();
21
+ /**
22
+ * Launch verification flow with automatic platform detection and fallback
23
+ */
24
+ static launch(sessionConfig: SessionConfig): Promise<VerificationSession>;
25
+ /**
26
+ * Start the verification session
27
+ */
28
+ start(): Promise<CredentialData | null>;
29
+ get sessionId(): string | undefined;
30
+ get sessionToken(): string | undefined;
31
+ /**
32
+ * Add event listener for verification events
33
+ */
34
+ addEventListener<T extends SDKEventTypes>(eventType: T, listener: (data: SDKEventData[T]) => void): void;
35
+ /**
36
+ * Remove event listener
37
+ */
38
+ removeEventListener<T extends SDKEventTypes>(eventType: T, listener: (data: SDKEventData[T]) => void): void;
39
+ /**
40
+ * Clean up all resources
41
+ */
42
+ close(): Promise<void>;
43
+ private complete;
44
+ private fail;
45
+ /**
46
+ * Initialize mobile-specific resources (HTTP client, session, WebSocket)
47
+ */
48
+ private initializeMobileResources;
49
+ private setupWebSocket;
50
+ private setupUI;
51
+ private showQR;
52
+ private showMobileModal;
53
+ /**
54
+ * Start HTTP polling as fallback when WebSocket is disconnected
55
+ */
56
+ private startPollingFallback;
57
+ /**
58
+ * Handle session updates from HTTP polling
59
+ */
60
+ private handlePollingUpdate;
61
+ private emit;
62
+ }
@@ -0,0 +1,404 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.VerificationSession = void 0;
13
+ const UIManager_1 = require("../ui/UIManager");
14
+ const logger_1 = require("../utils/logger");
15
+ const platformUtils_1 = require("../utils/platformUtils");
16
+ const errors_1 = require("./errors");
17
+ const htppClient_1 = require("./htppClient");
18
+ const keyringConnectExtension_1 = require("./keyringConnectExtension");
19
+ const websocketClient_1 = require("./websocketClient");
20
+ /**
21
+ * Represents an active verification session with proper cleanup
22
+ */
23
+ class VerificationSession {
24
+ constructor(sessionConfig) {
25
+ this.sessionConfig = sessionConfig;
26
+ this.eventListeners = new Map();
27
+ this.isWebsocketActive = false;
28
+ // Initialize with basic logger, will be updated with sessionId after session is created
29
+ this.logger = logger_1.KeyringLogger.init("VerificationSession").child({
30
+ policyId: sessionConfig.policy_id,
31
+ name: sessionConfig.name,
32
+ });
33
+ this.logger.debug("Creating verification session");
34
+ }
35
+ /**
36
+ * Launch verification flow with automatic platform detection and fallback
37
+ */
38
+ static launch(sessionConfig) {
39
+ return __awaiter(this, void 0, void 0, function* () {
40
+ this.staticLogger.info({ sessionConfig }, "Launching verification flow");
41
+ try {
42
+ // Clean up any existing session
43
+ if (this.activeSession) {
44
+ this.staticLogger.debug("Cleaning up existing session");
45
+ this.activeSession.close();
46
+ this.activeSession = null;
47
+ }
48
+ // Ensure online connectivity
49
+ if (!(yield platformUtils_1.PlatformUtils.waitForOnline(5000))) {
50
+ throw new errors_1.KeyringError(errors_1.KeyringErrorCode.NETWORK_ERROR, "No internet connection available");
51
+ }
52
+ // Create and start verification session
53
+ this.activeSession = new VerificationSession(sessionConfig);
54
+ return this.activeSession;
55
+ }
56
+ catch (error) {
57
+ this.staticLogger.error(error, "Launch failed");
58
+ const keyringError = errors_1.KeyringError.fromUnknown(error);
59
+ throw keyringError;
60
+ }
61
+ });
62
+ }
63
+ /**
64
+ * Start the verification session
65
+ */
66
+ start() {
67
+ return __awaiter(this, void 0, void 0, function* () {
68
+ this.logger.debug("Starting verification session");
69
+ // Create result promise that will be resolved when verification completes
70
+ this.resultPromise = new Promise((resolve, reject) => {
71
+ this.resolveResult = resolve;
72
+ this.rejectResult = reject;
73
+ });
74
+ try {
75
+ // Setup UI - this will handle mobile/extension branching
76
+ yield this.setupUI();
77
+ // Return promise that resolves when verification completes
78
+ return this.resultPromise;
79
+ }
80
+ catch (error) {
81
+ this.close();
82
+ throw errors_1.KeyringError.fromUnknown(error, { sessionId: this.sessionId });
83
+ }
84
+ });
85
+ }
86
+ get sessionId() {
87
+ var _a;
88
+ return (_a = this.sessionResponse) === null || _a === void 0 ? void 0 : _a.session_id;
89
+ }
90
+ get sessionToken() {
91
+ var _a;
92
+ return (_a = this.sessionResponse) === null || _a === void 0 ? void 0 : _a.session_token;
93
+ }
94
+ /**
95
+ * Add event listener for verification events
96
+ */
97
+ addEventListener(eventType, listener) {
98
+ if (!this.eventListeners.has(eventType)) {
99
+ this.eventListeners.set(eventType, []);
100
+ }
101
+ this.eventListeners.get(eventType).push(listener);
102
+ }
103
+ /**
104
+ * Remove event listener
105
+ */
106
+ removeEventListener(eventType, listener) {
107
+ const listeners = this.eventListeners.get(eventType);
108
+ if (listeners) {
109
+ const index = listeners.indexOf(listener);
110
+ if (index > -1) {
111
+ listeners.splice(index, 1);
112
+ }
113
+ }
114
+ }
115
+ /**
116
+ * Clean up all resources
117
+ */
118
+ close() {
119
+ return __awaiter(this, void 0, void 0, function* () {
120
+ this.logger.debug("Cleaning up verification session");
121
+ // Stop polling if active
122
+ if (this.stopPolling) {
123
+ this.stopPolling();
124
+ this.stopPolling = undefined;
125
+ }
126
+ // Clean up WebSocket (mobile only)
127
+ if (this.wsClient) {
128
+ this.isWebsocketActive = false;
129
+ this.wsClient.disconnect();
130
+ this.wsClient = undefined;
131
+ }
132
+ // Clean up HTTP session (mobile only)
133
+ if (this.httpClient && this.sessionId && this.sessionToken) {
134
+ this.logger.debug({ sessionId: this.sessionId }, "Deleting session from backend");
135
+ yield this.httpClient.closeSession(this.sessionId, this.sessionToken);
136
+ }
137
+ // Clear event listeners
138
+ this.eventListeners.clear();
139
+ // Reject result promise if still pending
140
+ if (this.rejectResult) {
141
+ const error = new errors_1.KeyringError(errors_1.KeyringErrorCode.USER_CANCELLED, "Session was cleaned up");
142
+ this.rejectResult(error);
143
+ this.resolveResult = undefined;
144
+ this.rejectResult = undefined;
145
+ }
146
+ });
147
+ }
148
+ complete(result) {
149
+ var _a;
150
+ this.logger.debug("Session completed successfully");
151
+ (_a = this.resolveResult) === null || _a === void 0 ? void 0 : _a.call(this, result);
152
+ this.close();
153
+ }
154
+ fail(error) {
155
+ var _a;
156
+ this.logger.error(error, "Session failed");
157
+ (_a = this.rejectResult) === null || _a === void 0 ? void 0 : _a.call(this, error);
158
+ this.close();
159
+ }
160
+ /**
161
+ * Initialize mobile-specific resources (HTTP client, session, WebSocket)
162
+ */
163
+ initializeMobileResources() {
164
+ return __awaiter(this, void 0, void 0, function* () {
165
+ // Initialize HTTP client
166
+ this.httpClient = htppClient_1.HttpClient.initializeHttpClient(this.sessionConfig.api_key);
167
+ // Create backend session
168
+ this.sessionResponse = yield this.httpClient.createSession(this.sessionConfig);
169
+ // Update logger with sessionId now that we have it
170
+ this.logger = this.logger.child({
171
+ sessionId: this.sessionResponse.session_id,
172
+ });
173
+ this.logger.debug({
174
+ sessionId: this.sessionResponse.session_id,
175
+ status: this.sessionResponse.status,
176
+ }, "Mobile session created");
177
+ });
178
+ }
179
+ setupWebSocket() {
180
+ return __awaiter(this, void 0, void 0, function* () {
181
+ var _a;
182
+ if (!((_a = this.sessionResponse) === null || _a === void 0 ? void 0 : _a.session_id)) {
183
+ throw new errors_1.KeyringError(errors_1.KeyringErrorCode.SESSION_NOT_FOUND, "Session not initialized for mobile flow");
184
+ }
185
+ const wsCallbacks = {
186
+ onConnectionStatusChanged: (connected) => {
187
+ var _a;
188
+ this.emit("connectionStatusChanged", connected);
189
+ if (connected) {
190
+ (_a = this.uiManager) === null || _a === void 0 ? void 0 : _a.updateStatus("Connected to Keyring app", "connected");
191
+ // Stop polling if WebSocket reconnects
192
+ if (this.stopPolling) {
193
+ this.logger.debug("WebSocket reconnected, stopping polling");
194
+ this.stopPolling();
195
+ this.stopPolling = undefined;
196
+ }
197
+ }
198
+ else {
199
+ // Only start polling if session is still active (not intentionally closed)
200
+ if (this.isWebsocketActive) {
201
+ // WebSocket disconnected, start polling as fallback
202
+ this.startPollingFallback();
203
+ }
204
+ }
205
+ },
206
+ onMobileConnected: (data) => {
207
+ var _a;
208
+ this.emit("mobileConnected", data);
209
+ (_a = this.uiManager) === null || _a === void 0 ? void 0 : _a.updateStatus("Connected to mobile app", "connected");
210
+ },
211
+ onProcessingStarted: (data) => {
212
+ var _a;
213
+ this.logger.debug(data, "Processing started");
214
+ (_a = this.uiManager) === null || _a === void 0 ? void 0 : _a.updateStatus("Processing verification...", "processing");
215
+ this.emit("processingStarted", data);
216
+ },
217
+ onProcessingCompleted: (data) => {
218
+ var _a, _b;
219
+ this.logger.debug(data, "Processing completed");
220
+ if (!data.result.credential_data) {
221
+ (_a = this.uiManager) === null || _a === void 0 ? void 0 : _a.updateStatus("Verification failed", "failed");
222
+ this.fail(new errors_1.KeyringError(errors_1.KeyringErrorCode.PROCESSING_FAILED, "Processing failed"));
223
+ return;
224
+ }
225
+ else {
226
+ (_b = this.uiManager) === null || _b === void 0 ? void 0 : _b.showCompleteModal(data.result.entity_type, data.result.datasource);
227
+ this.emit("processingCompleted", data);
228
+ this.complete(data.result.credential_data);
229
+ }
230
+ },
231
+ onSessionExpired: (data) => {
232
+ var _a, _b;
233
+ (_a = this.uiManager) === null || _a === void 0 ? void 0 : _a.updateStatus("Session expired", "expired");
234
+ this.emit("sessionExpired", data);
235
+ (_b = this.uiManager) === null || _b === void 0 ? void 0 : _b.showTerminatedModal();
236
+ this.fail(new errors_1.KeyringError(errors_1.KeyringErrorCode.SESSION_EXPIRED, "Verification session has expired"));
237
+ },
238
+ onError: (data) => {
239
+ var _a;
240
+ this.logger.error(data, "WebSocket error");
241
+ this.emit("error", data);
242
+ const errorMessage = typeof data === "object" && "message" in data ? data.message : data;
243
+ (_a = this.uiManager) === null || _a === void 0 ? void 0 : _a.updateStatus("Verification failed", "failed");
244
+ this.fail(errors_1.KeyringError.fromUnknown(errorMessage, { sessionId: this.sessionId }));
245
+ },
246
+ };
247
+ this.wsClient = new websocketClient_1.KeyringWebSocketClient(this.sessionResponse.session_id, this.sessionResponse.session_token, wsCallbacks);
248
+ this.isWebsocketActive = true;
249
+ yield this.wsClient.connect();
250
+ });
251
+ }
252
+ setupUI() {
253
+ return __awaiter(this, void 0, void 0, function* () {
254
+ this.uiManager = new UIManager_1.UIManager();
255
+ this.uiManager.setCallbacks(
256
+ // onCancel
257
+ () => {
258
+ this.fail(new errors_1.KeyringError(errors_1.KeyringErrorCode.USER_CANCELLED, "User cancelled verification"));
259
+ },
260
+ // onExtensionSelected
261
+ () => __awaiter(this, void 0, void 0, function* () {
262
+ var _a;
263
+ try {
264
+ this.logger.debug("Extension selected");
265
+ const result = yield keyringConnectExtension_1.KeyringConnectExtension.launchExtension(this.sessionConfig);
266
+ this.complete(result);
267
+ }
268
+ catch (error) {
269
+ this.fail(new errors_1.KeyringError(errors_1.KeyringErrorCode.PROCESSING_FAILED, (_a = error.message) !== null && _a !== void 0 ? _a : "Extension launch failed"));
270
+ }
271
+ }),
272
+ // onMobileSelected
273
+ () => __awaiter(this, void 0, void 0, function* () {
274
+ var _a;
275
+ try {
276
+ this.logger.debug("Mobile selected");
277
+ // Initialize mobile resources when mobile is selected
278
+ yield this.initializeMobileResources();
279
+ // Setup WebSocket connection
280
+ yield this.setupWebSocket();
281
+ // Show QR code
282
+ this.showQR();
283
+ }
284
+ catch (error) {
285
+ this.logger.error({ error }, "Failed to initialize mobile flow");
286
+ this.fail(new errors_1.KeyringError(errors_1.KeyringErrorCode.SESSION_CREATION_FAILED, (_a = error.message) !== null && _a !== void 0 ? _a : "Failed to initialize mobile flow"));
287
+ }
288
+ }));
289
+ // Show appropriate UI based on platform
290
+ const platform = platformUtils_1.PlatformUtils.detectPlatform();
291
+ if (platform.isDesktop) {
292
+ this.uiManager.showSelectionModal();
293
+ }
294
+ else {
295
+ // For mobile platforms, initialize mobile resources immediately
296
+ yield this.initializeMobileResources();
297
+ yield this.setupWebSocket();
298
+ this.showMobileModal();
299
+ }
300
+ });
301
+ }
302
+ showQR() {
303
+ if (!this.uiManager || !this.sessionResponse)
304
+ return;
305
+ this.uiManager.showQRModal(this.sessionResponse.qr_code_data, this.sessionResponse.session_id, this.sessionResponse.expires_at);
306
+ }
307
+ showMobileModal() {
308
+ if (!this.uiManager || !this.sessionResponse)
309
+ return;
310
+ this.uiManager.showMobileModal(this.sessionResponse.qr_code_data, this.sessionResponse.expires_at);
311
+ }
312
+ /**
313
+ * Start HTTP polling as fallback when WebSocket is disconnected
314
+ */
315
+ startPollingFallback() {
316
+ var _a, _b;
317
+ if (!this.httpClient || !((_a = this.sessionResponse) === null || _a === void 0 ? void 0 : _a.session_id)) {
318
+ this.logger.warn("Cannot start polling: httpClient or sessionId not available");
319
+ return;
320
+ }
321
+ // Don't start polling if already active
322
+ if (this.stopPolling) {
323
+ return;
324
+ }
325
+ this.logger.info("Starting HTTP polling fallback");
326
+ (_b = this.uiManager) === null || _b === void 0 ? void 0 : _b.updateStatus("Connection lost, checking status...", "processing");
327
+ this.stopPolling = this.httpClient.startPolling(this.sessionResponse.session_id, this.sessionResponse.session_token, (session) => {
328
+ this.handlePollingUpdate(session);
329
+ }, (error) => {
330
+ this.logger.error({ error }, "Polling error");
331
+ this.fail(new errors_1.KeyringError(errors_1.KeyringErrorCode.NETWORK_ERROR, "Polling failed"));
332
+ }, 2000 // Poll every 2 seconds
333
+ );
334
+ }
335
+ /**
336
+ * Handle session updates from HTTP polling
337
+ */
338
+ handlePollingUpdate(session) {
339
+ var _a, _b, _c, _d, _e, _f, _g;
340
+ if (!this.isWebsocketActive) {
341
+ return;
342
+ }
343
+ this.logger.debug({ status: session.status, hasResult: !!session.result }, "Received polling update");
344
+ // Handle different session statuses
345
+ switch (session.status) {
346
+ case "processing_completed":
347
+ this.logger.debug("Session completed via polling");
348
+ const result = session.result;
349
+ const hasRequiredData = (result === null || result === void 0 ? void 0 : result.credential_data) && (result === null || result === void 0 ? void 0 : result.entity_type) && (result === null || result === void 0 ? void 0 : result.datasource);
350
+ if (hasRequiredData) {
351
+ (_a = this.uiManager) === null || _a === void 0 ? void 0 : _a.showCompleteModal(result.entity_type, result.datasource);
352
+ this.emit("processingCompleted", {
353
+ result: {
354
+ credential_data: result.credential_data,
355
+ entity_type: result.entity_type,
356
+ datasource: result.datasource,
357
+ },
358
+ status: "success",
359
+ });
360
+ this.complete(result.credential_data);
361
+ }
362
+ else {
363
+ (_b = this.uiManager) === null || _b === void 0 ? void 0 : _b.updateStatus("Verification failed", "failed");
364
+ this.fail(new errors_1.KeyringError(errors_1.KeyringErrorCode.PROCESSING_FAILED, "No credential data in result"));
365
+ }
366
+ break;
367
+ case "processing_failed":
368
+ this.logger.debug("Session failed via polling");
369
+ (_c = this.uiManager) === null || _c === void 0 ? void 0 : _c.updateStatus("Verification failed", "failed");
370
+ this.fail(new errors_1.KeyringError(errors_1.KeyringErrorCode.PROCESSING_FAILED, session.error || "Verification failed"));
371
+ break;
372
+ case "session_expired":
373
+ this.logger.debug("Session expired via polling");
374
+ (_d = this.uiManager) === null || _d === void 0 ? void 0 : _d.showTerminatedModal();
375
+ this.fail(new errors_1.KeyringError(errors_1.KeyringErrorCode.SESSION_EXPIRED, "Verification session has expired"));
376
+ break;
377
+ case "processing_started":
378
+ (_e = this.uiManager) === null || _e === void 0 ? void 0 : _e.updateStatus("Processing verification...", "processing");
379
+ break;
380
+ case "mobile_connected":
381
+ (_f = this.uiManager) === null || _f === void 0 ? void 0 : _f.updateStatus("Mobile app connected...", "connected");
382
+ break;
383
+ case "session_created":
384
+ (_g = this.uiManager) === null || _g === void 0 ? void 0 : _g.updateStatus("Waiting for mobile app...", "connected");
385
+ break;
386
+ }
387
+ }
388
+ emit(eventType, data) {
389
+ const listeners = this.eventListeners.get(eventType);
390
+ if (listeners) {
391
+ listeners.forEach((listener) => {
392
+ try {
393
+ listener(data);
394
+ }
395
+ catch (error) {
396
+ this.logger.error(error, `Error in event listener for ${eventType}`);
397
+ }
398
+ });
399
+ }
400
+ }
401
+ }
402
+ exports.VerificationSession = VerificationSession;
403
+ VerificationSession.activeSession = null;
404
+ VerificationSession.staticLogger = logger_1.KeyringLogger.init("VerificationSession");
@@ -0,0 +1,49 @@
1
+ /**
2
+ * Keyring SDK Error Codes
3
+ */
4
+ export declare enum KeyringErrorCode {
5
+ NETWORK_ERROR = "NETWORK_ERROR",
6
+ SESSION_CREATION_FAILED = "SESSION_CREATION_FAILED",
7
+ WEBSOCKET_CONNECTION_FAILED = "WEBSOCKET_CONNECTION_FAILED",
8
+ EXTENSION_NOT_FOUND = "EXTENSION_NOT_FOUND",
9
+ EXTENSION_TIMEOUT = "EXTENSION_TIMEOUT",
10
+ CHROME_RUNTIME_ERROR = "CHROME_RUNTIME_ERROR",
11
+ EXTENSION_LAUNCH_FAILED = "EXTENSION_LAUNCH_FAILED",
12
+ SESSION_EXPIRED = "SESSION_EXPIRED",
13
+ SESSION_NOT_FOUND = "SESSION_NOT_FOUND",
14
+ INVALID_SESSION_CONFIG = "INVALID_SESSION_CONFIG",
15
+ USER_CANCELLED = "USER_CANCELLED",
16
+ TIMEOUT_ERROR = "TIMEOUT_ERROR",
17
+ QR_DISPLAY_NOT_SUPPORTED = "QR_DISPLAY_NOT_SUPPORTED",
18
+ WEBSOCKET_NOT_SUPPORTED = "WEBSOCKET_NOT_SUPPORTED",
19
+ INVALID_CONFIG = "INVALID_CONFIG",
20
+ MISSING_REQUIRED_FIELD = "MISSING_REQUIRED_FIELD",
21
+ PROCESSING_FAILED = "PROCESSING_FAILED",
22
+ UNKNOWN_ERROR = "UNKNOWN_ERROR"
23
+ }
24
+ /**
25
+ * Keyring SDK Error class with structured error information
26
+ */
27
+ export declare class KeyringError extends Error {
28
+ readonly code: KeyringErrorCode;
29
+ readonly cause?: unknown | undefined;
30
+ readonly context?: Record<string, any> | undefined;
31
+ readonly name = "KeyringError";
32
+ readonly timestamp: string;
33
+ constructor(code: KeyringErrorCode, message: string, cause?: unknown | undefined, context?: Record<string, any> | undefined);
34
+ /**
35
+ * Create error from unknown source
36
+ */
37
+ static fromUnknown(error: unknown, context?: Record<string, any>): KeyringError;
38
+ /**
39
+ * Convert to JSON for logging/debugging
40
+ */
41
+ toJSON(): {
42
+ name: string;
43
+ code: KeyringErrorCode;
44
+ message: string;
45
+ timestamp: string;
46
+ context: Record<string, any> | undefined;
47
+ cause: unknown;
48
+ };
49
+ }
@@ -0,0 +1,81 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.KeyringError = exports.KeyringErrorCode = void 0;
4
+ /**
5
+ * Keyring SDK Error Codes
6
+ */
7
+ var KeyringErrorCode;
8
+ (function (KeyringErrorCode) {
9
+ // Network related errors
10
+ KeyringErrorCode["NETWORK_ERROR"] = "NETWORK_ERROR";
11
+ KeyringErrorCode["SESSION_CREATION_FAILED"] = "SESSION_CREATION_FAILED";
12
+ KeyringErrorCode["WEBSOCKET_CONNECTION_FAILED"] = "WEBSOCKET_CONNECTION_FAILED";
13
+ // Extension related errors
14
+ KeyringErrorCode["EXTENSION_NOT_FOUND"] = "EXTENSION_NOT_FOUND";
15
+ KeyringErrorCode["EXTENSION_TIMEOUT"] = "EXTENSION_TIMEOUT";
16
+ KeyringErrorCode["CHROME_RUNTIME_ERROR"] = "CHROME_RUNTIME_ERROR";
17
+ KeyringErrorCode["EXTENSION_LAUNCH_FAILED"] = "EXTENSION_LAUNCH_FAILED";
18
+ // Session related errors
19
+ KeyringErrorCode["SESSION_EXPIRED"] = "SESSION_EXPIRED";
20
+ KeyringErrorCode["SESSION_NOT_FOUND"] = "SESSION_NOT_FOUND";
21
+ KeyringErrorCode["INVALID_SESSION_CONFIG"] = "INVALID_SESSION_CONFIG";
22
+ // User interaction errors
23
+ KeyringErrorCode["USER_CANCELLED"] = "USER_CANCELLED";
24
+ KeyringErrorCode["TIMEOUT_ERROR"] = "TIMEOUT_ERROR";
25
+ // Platform support errors
26
+ KeyringErrorCode["QR_DISPLAY_NOT_SUPPORTED"] = "QR_DISPLAY_NOT_SUPPORTED";
27
+ KeyringErrorCode["WEBSOCKET_NOT_SUPPORTED"] = "WEBSOCKET_NOT_SUPPORTED";
28
+ // Validation errors
29
+ KeyringErrorCode["INVALID_CONFIG"] = "INVALID_CONFIG";
30
+ KeyringErrorCode["MISSING_REQUIRED_FIELD"] = "MISSING_REQUIRED_FIELD";
31
+ // Processing errors
32
+ KeyringErrorCode["PROCESSING_FAILED"] = "PROCESSING_FAILED";
33
+ KeyringErrorCode["UNKNOWN_ERROR"] = "UNKNOWN_ERROR";
34
+ })(KeyringErrorCode || (exports.KeyringErrorCode = KeyringErrorCode = {}));
35
+ /**
36
+ * Keyring SDK Error class with structured error information
37
+ */
38
+ class KeyringError extends Error {
39
+ constructor(code, message, cause, context) {
40
+ super(message);
41
+ this.code = code;
42
+ this.cause = cause;
43
+ this.context = context;
44
+ this.name = 'KeyringError';
45
+ this.timestamp = new Date().toISOString();
46
+ // Maintain proper stack trace for debugging
47
+ if (Error.captureStackTrace) {
48
+ Error.captureStackTrace(this, KeyringError);
49
+ }
50
+ }
51
+ /**
52
+ * Create error from unknown source
53
+ */
54
+ static fromUnknown(error, context) {
55
+ if (error instanceof KeyringError) {
56
+ return error;
57
+ }
58
+ if (error instanceof Error) {
59
+ return new KeyringError(KeyringErrorCode.UNKNOWN_ERROR, error.message, error, context);
60
+ }
61
+ return new KeyringError(KeyringErrorCode.UNKNOWN_ERROR, String(error), error, context);
62
+ }
63
+ /**
64
+ * Convert to JSON for logging/debugging
65
+ */
66
+ toJSON() {
67
+ return {
68
+ name: this.name,
69
+ code: this.code,
70
+ message: this.message,
71
+ timestamp: this.timestamp,
72
+ context: this.context,
73
+ cause: this.cause instanceof Error ? {
74
+ name: this.cause.name,
75
+ message: this.cause.message,
76
+ stack: this.cause.stack
77
+ } : this.cause
78
+ };
79
+ }
80
+ }
81
+ exports.KeyringError = KeyringError;
@@ -0,0 +1,17 @@
1
+ import { CrossDeviceSession, SessionConfig } from "../types/";
2
+ export declare class HttpClient {
3
+ private static instance;
4
+ private httpClient;
5
+ private logger;
6
+ private constructor();
7
+ private setupAxiosInterceptors;
8
+ static initializeHttpClient(apiKey: string): HttpClient;
9
+ createSession(sessionConfig: SessionConfig): Promise<CrossDeviceSession>;
10
+ closeSession(sessionId: string, sessionToken: string): Promise<void>;
11
+ getSession(sessionId: string, sessionToken: string): Promise<CrossDeviceSession | null>;
12
+ /**
13
+ * Start polling for session updates
14
+ * Returns a function to stop polling
15
+ */
16
+ startPolling(sessionId: string, sessionToken: string, onUpdate: (session: CrossDeviceSession) => void, onError: (error: any) => void, interval?: number): () => void;
17
+ }