@meshconnect/uwc-core 1.0.3 → 1.1.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 (121) hide show
  1. package/README.md +247 -76
  2. package/dist/events.d.ts +241 -5
  3. package/dist/events.d.ts.map +1 -1
  4. package/dist/events.js +77 -1
  5. package/dist/events.js.map +1 -1
  6. package/dist/index.d.ts +2 -0
  7. package/dist/index.d.ts.map +1 -1
  8. package/dist/index.js +2 -0
  9. package/dist/index.js.map +1 -1
  10. package/dist/logger/create-logger.d.ts +32 -0
  11. package/dist/logger/create-logger.d.ts.map +1 -0
  12. package/dist/logger/create-logger.js +79 -0
  13. package/dist/logger/create-logger.js.map +1 -0
  14. package/dist/managers/event-manager.d.ts.map +1 -1
  15. package/dist/managers/event-manager.js +5 -1
  16. package/dist/managers/event-manager.js.map +1 -1
  17. package/dist/observability/connect-observer.d.ts +33 -0
  18. package/dist/observability/connect-observer.d.ts.map +1 -0
  19. package/dist/observability/connect-observer.js +115 -0
  20. package/dist/observability/connect-observer.js.map +1 -0
  21. package/dist/observability/focus-tracker.d.ts +42 -0
  22. package/dist/observability/focus-tracker.d.ts.map +1 -0
  23. package/dist/observability/focus-tracker.js +57 -0
  24. package/dist/observability/focus-tracker.js.map +1 -0
  25. package/dist/observability/instrument-handoff.d.ts +54 -0
  26. package/dist/observability/instrument-handoff.d.ts.map +1 -0
  27. package/dist/observability/instrument-handoff.js +173 -0
  28. package/dist/observability/instrument-handoff.js.map +1 -0
  29. package/dist/observability/lifecycle-bridge.d.ts +69 -0
  30. package/dist/observability/lifecycle-bridge.d.ts.map +1 -0
  31. package/dist/observability/lifecycle-bridge.js +155 -0
  32. package/dist/observability/lifecycle-bridge.js.map +1 -0
  33. package/dist/observability/scrub.d.ts +31 -0
  34. package/dist/observability/scrub.d.ts.map +1 -0
  35. package/dist/observability/scrub.js +167 -0
  36. package/dist/observability/scrub.js.map +1 -0
  37. package/dist/observability/telemetry.d.ts +157 -0
  38. package/dist/observability/telemetry.d.ts.map +1 -0
  39. package/dist/observability/telemetry.js +373 -0
  40. package/dist/observability/telemetry.js.map +1 -0
  41. package/dist/services/connection-service.d.ts +23 -1
  42. package/dist/services/connection-service.d.ts.map +1 -1
  43. package/dist/services/connection-service.js +128 -19
  44. package/dist/services/connection-service.js.map +1 -1
  45. package/dist/services/network-switch-service.d.ts +2 -1
  46. package/dist/services/network-switch-service.d.ts.map +1 -1
  47. package/dist/services/network-switch-service.js +45 -16
  48. package/dist/services/network-switch-service.js.map +1 -1
  49. package/dist/services/signature-service.d.ts +14 -7
  50. package/dist/services/signature-service.d.ts.map +1 -1
  51. package/dist/services/signature-service.js +56 -58
  52. package/dist/services/signature-service.js.map +1 -1
  53. package/dist/services/transaction-service.d.ts +19 -5
  54. package/dist/services/transaction-service.d.ts.map +1 -1
  55. package/dist/services/transaction-service.js +55 -38
  56. package/dist/services/transaction-service.js.map +1 -1
  57. package/dist/universal-wallet-connector.d.ts +56 -1
  58. package/dist/universal-wallet-connector.d.ts.map +1 -1
  59. package/dist/universal-wallet-connector.js +207 -110
  60. package/dist/universal-wallet-connector.js.map +1 -1
  61. package/dist/utils/id.d.ts +2 -0
  62. package/dist/utils/id.d.ts.map +1 -0
  63. package/dist/utils/id.js +41 -0
  64. package/dist/utils/id.js.map +1 -0
  65. package/dist/utils/resolve-session-provider.d.ts +10 -0
  66. package/dist/utils/resolve-session-provider.d.ts.map +1 -0
  67. package/dist/utils/resolve-session-provider.js +21 -0
  68. package/dist/utils/resolve-session-provider.js.map +1 -0
  69. package/dist/utils/to-wallet-error.d.ts +35 -0
  70. package/dist/utils/to-wallet-error.d.ts.map +1 -0
  71. package/dist/utils/to-wallet-error.js +130 -0
  72. package/dist/utils/to-wallet-error.js.map +1 -0
  73. package/dist/utils/validate-wallet-session.d.ts +15 -0
  74. package/dist/utils/validate-wallet-session.d.ts.map +1 -0
  75. package/dist/utils/validate-wallet-session.js +29 -0
  76. package/dist/utils/validate-wallet-session.js.map +1 -0
  77. package/dist/version.d.ts +2 -0
  78. package/dist/version.d.ts.map +1 -0
  79. package/dist/version.js +3 -0
  80. package/dist/version.js.map +1 -0
  81. package/package.json +6 -6
  82. package/src/events.ts +326 -14
  83. package/src/index.ts +10 -0
  84. package/src/logger/create-logger.test.ts +126 -0
  85. package/src/logger/create-logger.ts +112 -0
  86. package/src/managers/event-manager.test.ts +55 -0
  87. package/src/managers/event-manager.ts +5 -1
  88. package/src/observability/connect-observer.test.ts +214 -0
  89. package/src/observability/connect-observer.ts +128 -0
  90. package/src/observability/focus-tracker.test.ts +191 -0
  91. package/src/observability/focus-tracker.ts +96 -0
  92. package/src/observability/instrument-handoff.test.ts +397 -0
  93. package/src/observability/instrument-handoff.ts +231 -0
  94. package/src/observability/lifecycle-bridge.test.ts +398 -0
  95. package/src/observability/lifecycle-bridge.ts +216 -0
  96. package/src/observability/scrub.test.ts +183 -0
  97. package/src/observability/scrub.ts +174 -0
  98. package/src/observability/telemetry.test.ts +549 -0
  99. package/src/observability/telemetry.ts +546 -0
  100. package/src/services/connection-service.test.ts +261 -1
  101. package/src/services/connection-service.ts +167 -38
  102. package/src/services/network-switch-service.test.ts +51 -1
  103. package/src/services/network-switch-service.ts +56 -24
  104. package/src/services/signature-service.test.ts +181 -76
  105. package/src/services/signature-service.ts +75 -85
  106. package/src/services/transaction-service.test.ts +270 -69
  107. package/src/services/transaction-service.ts +74 -51
  108. package/src/universal-wallet-connector.instrumentation-guard.test.ts +199 -0
  109. package/src/universal-wallet-connector.observability.test.ts +610 -0
  110. package/src/universal-wallet-connector.test.ts +27 -146
  111. package/src/universal-wallet-connector.ts +279 -142
  112. package/src/utils/id.test.ts +15 -0
  113. package/src/utils/id.ts +48 -0
  114. package/src/utils/resolve-session-provider.test.ts +54 -0
  115. package/src/utils/resolve-session-provider.ts +25 -0
  116. package/src/utils/to-wallet-error.test.ts +181 -0
  117. package/src/utils/to-wallet-error.ts +152 -0
  118. package/src/utils/validate-wallet-session.test.ts +77 -0
  119. package/src/utils/validate-wallet-session.ts +40 -0
  120. package/src/version.test.ts +11 -0
  121. package/src/version.ts +2 -0
@@ -1,5 +1,6 @@
1
- import type { UniversalWalletConnectorState, Network, WalletMetadata, NetworkId, ConnectionMode, WalletConnectConfig, TonConnectConfig, TransactionRequest, TransactionResult, EVMCapabilities, SignatureType, EIP712TypedData } from '@meshconnect/uwc-types';
1
+ import type { UniversalWalletConnectorState, Network, WalletMetadata, NetworkId, ConnectionMode, WalletConnectConfig, TonConnectConfig, TransactionRequest, TransactionResult, EVMCapabilities, SignatureType, EIP712TypedData, LogLevel, Logger } from '@meshconnect/uwc-types';
2
2
  import type { TronConnectorConfig } from '@meshconnect/uwc-tron-connector';
3
+ import type { UWCObserver } from './observability/telemetry';
3
4
  import type { UWCEventName, UWCEventListener } from './events';
4
5
  /**
5
6
  * Configuration object form of the UniversalWalletConnector constructor.
@@ -12,6 +13,37 @@ export interface UWCConfig {
12
13
  walletConnectConfig?: WalletConnectConfig;
13
14
  tonConnectConfig?: TonConnectConfig;
14
15
  tronConnectorConfig?: TronConnectorConfig;
16
+ /**
17
+ * Vendor-agnostic telemetry sink. When omitted, UWC emits NOTHING externally —
18
+ * zero egress is the security-first default for a sign-only wallet layer. The
19
+ * consumer implements the sink and wires it to their backend (Datadog/…).
20
+ */
21
+ observer?: UWCObserver;
22
+ /**
23
+ * Redirect UWC's internal logging into your own logger. Receives raw
24
+ * `(message, ...args)` at/above `logLevel`. When omitted, a console-backed
25
+ * logger is used. LOCAL SINK by contract: args are NOT scrubbed here — do not
26
+ * wire this to a remote transport; use `observer.onLog` (scrubbed) for egress.
27
+ */
28
+ logger?: Logger;
29
+ /** Console threshold for the default logger. Default `'warn'`. */
30
+ logLevel?: LogLevel;
31
+ /**
32
+ * Consumer correlation id, surfaced as its OWN `correlationId` field on every
33
+ * telemetry record — never aliased onto the generated `sdkSessionId`, so
34
+ * "no id supplied" and "id == session" stay distinguishable. Supply your own
35
+ * (e.g. the consumer's `link_sess_id`) so UWC events join your existing
36
+ * telemetry in Datadog/RUM without a separate mapping. Pass a getter if the
37
+ * id isn't known at construction or can change; resolved per-event, and a
38
+ * throwing/empty getter OMITS the field for that record.
39
+ */
40
+ correlationId?: string | (() => string);
41
+ /**
42
+ * Observational wallet-response deadline (ms) for the `walletTimedOut` marker.
43
+ * `0` disables it. TON is always exempt (it bounds its own response). Default
44
+ * 60_000.
45
+ */
46
+ walletResponseTimeoutMs?: number;
15
47
  }
16
48
  /** Common options for user-initiated async operations. */
17
49
  export interface OperationOptions {
@@ -35,6 +67,12 @@ export declare class UniversalWalletConnector {
35
67
  private usingIntegratedBrowser;
36
68
  private detectionComplete;
37
69
  private networkRpcMap;
70
+ private logger;
71
+ /** Per-instance correlation id stamped on every telemetry record. */
72
+ private readonly sdkSessionId;
73
+ private walletResponseTimeoutMs;
74
+ /** Tears down the observer subscriptions; set only when an observer is wired. */
75
+ private observerTeardown;
38
76
  /**
39
77
  * Recommended entry point: returns the shared instance, creating it on the
40
78
  * first call. Subsequent calls ignore the `config` argument — use
@@ -55,6 +93,13 @@ export declare class UniversalWalletConnector {
55
93
  * in parallel without racing on the merge logic.
56
94
  */
57
95
  private applyDetectedWallet;
96
+ /**
97
+ * Per-namespace requested-vs-matched counts after detection. `requested` =
98
+ * configured wallets that declared the namespace; `matched` = those now marked
99
+ * installed. Counts only — never a wallet id or address. Feeds `walletsDetected`
100
+ * so a dashboard can answer "asked for N, matched 0?".
101
+ */
102
+ private summarizeDiscovery;
58
103
  getSession(): import("@meshconnect/uwc-types").Session;
59
104
  isReady(): boolean;
60
105
  /** Subscribe to a typed event. Returns an unsubscribe function. */
@@ -123,6 +168,16 @@ export declare class UniversalWalletConnector {
123
168
  */
124
169
  isConnectionModeAvailable(connectionMode: ConnectionMode, walletId: string): boolean;
125
170
  getActiveWalletCapabilities(): Record<string, EVMCapabilities> | null;
171
+ /**
172
+ * Set the console log threshold at runtime (e.g. from a support toggle). The
173
+ * global `window.UWC_DEBUG` override still takes precedence for ad-hoc triage.
174
+ */
175
+ setLogLevel(level: LogLevel): void;
176
+ /**
177
+ * Release observer subscriptions and clear all event listeners. Call on full
178
+ * teardown / logout to avoid leaking listeners across connector lifecycles.
179
+ */
180
+ dispose(): void;
126
181
  private emitError;
127
182
  }
128
183
  //# sourceMappingURL=universal-wallet-connector.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"universal-wallet-connector.d.ts","sourceRoot":"","sources":["../src/universal-wallet-connector.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,6BAA6B,EAC7B,OAAO,EACP,cAAc,EACd,SAAS,EACT,cAAc,EACd,mBAAmB,EACnB,gBAAgB,EAOhB,kBAAkB,EAClB,iBAAiB,EAEjB,eAAe,EACf,aAAa,EACb,eAAe,EAEhB,MAAM,wBAAwB,CAAA;AAK/B,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,iCAAiC,CAAA;AAS1E,OAAO,KAAK,EAAE,YAAY,EAAE,gBAAgB,EAAgB,MAAM,UAAU,CAAA;AAE5E;;;GAGG;AACH,MAAM,WAAW,SAAS;IACxB,QAAQ,EAAE,OAAO,EAAE,CAAA;IAInB,OAAO,EAAE,cAAc,EAAE,CAAA;IACzB,sBAAsB,CAAC,EAAE,OAAO,CAAA;IAChC,mBAAmB,CAAC,EAAE,mBAAmB,CAAA;IACzC,gBAAgB,CAAC,EAAE,gBAAgB,CAAA;IACnC,mBAAmB,CAAC,EAAE,mBAAmB,CAAA;CAC1C;AAED,0DAA0D;AAC1D,MAAM,WAAW,gBAAgB;IAC/B,wFAAwF;IACxF,MAAM,CAAC,EAAE,WAAW,CAAA;CACrB;AAED,qBAAa,wBAAwB;IACnC,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAwC;IAC/D,OAAO,CAAC,MAAM,CAAC,aAAa,CAAI;IAChC,OAAO,CAAC,MAAM,CAAC,+BAA+B,CAAQ;IAEtD,OAAO,CAAC,cAAc,CAAgB;IACtC,OAAO,CAAC,YAAY,CAAc;IAClC,OAAO,CAAC,iBAAiB,CAAmB;IAC5C,OAAO,CAAC,oBAAoB,CAAsB;IAClD,OAAO,CAAC,gBAAgB,CAAkB;IAC1C,OAAO,CAAC,kBAAkB,CAAoB;IAC9C,OAAO,CAAC,yBAAyB,CAA2B;IAC5D,OAAO,CAAC,UAAU,CAAgC;IAClD,OAAO,CAAC,iBAAiB,CAAmB;IAC5C,OAAO,CAAC,OAAO,CAAkB;IACjC,OAAO,CAAC,sBAAsB,CAAS;IACvC,OAAO,CAAC,iBAAiB,CAAQ;IACjC,OAAO,CAAC,aAAa,CAAe;IAEpC;;;;OAIG;IACH,MAAM,CAAC,WAAW,CAAC,MAAM,CAAC,EAAE,SAAS,GAAG,wBAAwB;IAYhE,sFAAsF;IACtF,MAAM,CAAC,aAAa,IAAI,IAAI;gBAMhB,MAAM,EAAE,SAAS;gBAE3B,QAAQ,EAAE,OAAO,EAAE,EACnB,OAAO,EAAE,cAAc,EAAE,EACzB,sBAAsB,CAAC,EAAE,OAAO,EAChC,mBAAmB,CAAC,EAAE,mBAAmB,EACzC,gBAAgB,CAAC,EAAE,gBAAgB,EACnC,mBAAmB,CAAC,EAAE,mBAAmB;IA0J3C;;OAEG;YACW,yBAAyB;IA8DvC;;;;OAIG;IACH,OAAO,CAAC,mBAAmB;IAgI3B,UAAU;IAIV,OAAO;IAMP,mEAAmE;IACnE,EAAE,CAAC,CAAC,SAAS,YAAY,EACvB,KAAK,EAAE,CAAC,EACR,QAAQ,EAAE,gBAAgB,CAAC,CAAC,CAAC,GAC5B,MAAM,IAAI;IAIb,wEAAwE;IACxE,IAAI,CAAC,CAAC,SAAS,YAAY,EACzB,KAAK,EAAE,CAAC,EACR,QAAQ,EAAE,gBAAgB,CAAC,CAAC,CAAC,GAC5B,MAAM,IAAI;IAIb,GAAG,CAAC,CAAC,SAAS,YAAY,EAAE,KAAK,EAAE,CAAC,EAAE,QAAQ,EAAE,gBAAgB,CAAC,CAAC,CAAC,GAAG,IAAI;IAI1E;;;OAGG;IACH,SAAS,CAAC,QAAQ,EAAE,MAAM,IAAI,GAAG,MAAM,IAAI;IAI3C,QAAQ,IAAI,6BAA6B;IAMzC,UAAU,IAAI,cAAc,EAAE;IAI9B,WAAW,IAAI,OAAO,EAAE;IAIlB,OAAO,CACX,cAAc,EAAE,cAAc,EAC9B,QAAQ,EAAE,MAAM,EAChB,SAAS,CAAC,EAAE,SAAS,EACrB,OAAO,CAAC,EAAE,gBAAgB,GACzB,OAAO,CAAC,IAAI,CAAC;IAchB,gBAAgB,IAAI,MAAM,GAAG,SAAS;IAIhC,UAAU,CAAC,OAAO,CAAC,EAAE,gBAAgB,GAAG,OAAO,CAAC,IAAI,CAAC;IASrD,aAAa,CACjB,SAAS,EAAE,SAAS,EACpB,OAAO,CAAC,EAAE,gBAAgB,GACzB,OAAO,CAAC,IAAI,CAAC;IAShB,4BAA4B;;;;IAI5B;;;;;OAKG;IACG,WAAW,CACf,OAAO,EAAE,MAAM,EACf,OAAO,CAAC,EAAE,gBAAgB,GACzB,OAAO,CAAC,aAAa,CAAC;IAuCzB;;;;;;;OAOG;IACG,aAAa,CAAC,SAAS,EAAE,eAAe,GAAG,OAAO,CAAC,MAAM,CAAC;IA+BhE;;;;;OAKG;IACG,eAAe,CACnB,OAAO,EAAE,kBAAkB,EAC3B,OAAO,CAAC,EAAE,gBAAgB,GACzB,OAAO,CAAC,iBAAiB,CAAC;IA2C7B;;;;OAIG;IACG,qBAAqB,CAAC,YAAY,EAAE,UAAU,GAAG,OAAO,CAAC,UAAU,CAAC;IAsB1E;;;;;;OAMG;IACG,qBAAqB,CACzB,OAAO,EAAE,MAAM,EACf,aAAa,CAAC,EAAE,OAAO,EACvB,OAAO,CAAC,EAAE,gBAAgB,GACzB,OAAO,CAAC,IAAI,CAAC;IAahB;;;;;OAKG;IACH,yBAAyB,CACvB,cAAc,EAAE,cAAc,EAC9B,QAAQ,EAAE,MAAM,GACf,OAAO;IA8CV,2BAA2B,IAAI,MAAM,CAAC,MAAM,EAAE,eAAe,CAAC,GAAG,IAAI;IAOrE,OAAO,CAAC,SAAS;CAgBlB"}
1
+ {"version":3,"file":"universal-wallet-connector.d.ts","sourceRoot":"","sources":["../src/universal-wallet-connector.ts"],"names":[],"mappings":"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"}
@@ -1,4 +1,3 @@
1
- import { WalletConnectorError } from '@meshconnect/uwc-types';
2
1
  import { InjectedConnector } from '@meshconnect/uwc-injected-connector';
3
2
  import { WalletConnectConnector } from '@meshconnect/uwc-wallet-connect-connector';
4
3
  import { TonConnectConnector } from '@meshconnect/uwc-ton-connector';
@@ -10,6 +9,14 @@ import { SignatureService } from './services/signature-service';
10
9
  import { TransactionService } from './services/transaction-service';
11
10
  import { WalletCapabilitiesService } from './services/wallet-capabilities-service';
12
11
  import { createNetworkRpcMap } from './utils/network-rpc-utils';
12
+ import { generateId } from './utils/id';
13
+ import { toWalletError, isAbortError, classifyError } from './utils/to-wallet-error';
14
+ import { NoCommonNetworkError } from '@meshconnect/uwc-types';
15
+ import { createLogger } from './logger/create-logger';
16
+ import { connectObserver } from './observability/connect-observer';
17
+ import { hasHandoffTerminal } from './observability/instrument-handoff';
18
+ /** Default observational wallet-response deadline (ms). Matches TON's 60s. */
19
+ const DEFAULT_WALLET_RESPONSE_TIMEOUT_MS = 60_000;
13
20
  export class UniversalWalletConnector {
14
21
  static instance = null;
15
22
  static instanceCount = 0;
@@ -27,6 +34,12 @@ export class UniversalWalletConnector {
27
34
  usingIntegratedBrowser;
28
35
  detectionComplete = false;
29
36
  networkRpcMap;
37
+ logger;
38
+ /** Per-instance correlation id stamped on every telemetry record. */
39
+ sdkSessionId = generateId();
40
+ walletResponseTimeoutMs;
41
+ /** Tears down the observer subscriptions; set only when an observer is wired. */
42
+ observerTeardown;
30
43
  /**
31
44
  * Recommended entry point: returns the shared instance, creating it on the
32
45
  * first call. Subsequent calls ignore the `config` argument — use
@@ -72,12 +85,43 @@ export class UniversalWalletConnector {
72
85
  config = networksOrConfig;
73
86
  }
74
87
  const { networks, wallets: configuredWallets = [], usingIntegratedBrowser: configuredUsingIntegratedBrowser = false, walletConnectConfig: configuredWalletConnectConfig, tonConnectConfig: configuredTonConnectConfig, tronConnectorConfig: configuredTronConnectorConfig } = config;
88
+ // Observability seam — wire the event bus, logger, and (optional) observer
89
+ // FIRST so even construction-time logs/events are captured. `sdkSessionId` is
90
+ // already assigned as a field initializer.
91
+ this.eventManager = new EventManager();
92
+ this.walletResponseTimeoutMs =
93
+ config.walletResponseTimeoutMs ?? DEFAULT_WALLET_RESPONSE_TIMEOUT_MS;
94
+ this.logger = createLogger({
95
+ level: config.logLevel ?? 'warn',
96
+ sink: config.logger,
97
+ // Pre-gate tap → typed `log` event → observer.onLog. Fires for all levels
98
+ // regardless of the console threshold.
99
+ onLog: (level, message, args) => this.eventManager.emit('log', { level, message, args })
100
+ });
101
+ if (config.observer) {
102
+ // Resolve the OPTIONAL consumer correlation id per-event so a consumer can
103
+ // align it to their own session key (e.g. link_sess_id). It is kept
104
+ // separate from the always-present generated `sdkSessionId` — never aliased
105
+ // — so a record can distinguish "no consumer id" from "id == session". A
106
+ // missing/empty value or a throwing getter yields `undefined` (no fallback).
107
+ const cid = config.correlationId;
108
+ const getCorrelationId = typeof cid === 'function'
109
+ ? () => {
110
+ try {
111
+ return cid() || undefined;
112
+ }
113
+ catch {
114
+ return undefined;
115
+ }
116
+ }
117
+ : () => cid;
118
+ this.observerTeardown = connectObserver(this.eventManager, config.observer, this.sdkSessionId, getCorrelationId, Date.now, this.logger);
119
+ }
75
120
  // Track instance creation and warn on duplicates
76
121
  UniversalWalletConnector.instanceCount++;
77
122
  if (UniversalWalletConnector.instanceCount > 1 &&
78
123
  !UniversalWalletConnector.hasWarnedAboutMultipleInstances) {
79
- // eslint-disable-next-line no-console
80
- console.error(`⚠️ WARNING: Multiple instances of UniversalWalletConnector detected (${UniversalWalletConnector.instanceCount} instances). ` +
124
+ this.logger.error(`⚠️ WARNING: Multiple instances of UniversalWalletConnector detected (${UniversalWalletConnector.instanceCount} instances). ` +
81
125
  'This can lead to state inconsistencies and unexpected behavior. ' +
82
126
  'Please ensure you create only one instance and reuse it throughout your application. ' +
83
127
  'Use UniversalWalletConnector.getInstance(config) instead of `new` to guarantee a single instance. ' +
@@ -100,21 +144,34 @@ export class UniversalWalletConnector {
100
144
  this.networkRpcMap = createNetworkRpcMap(networks);
101
145
  // Initialize connectors with RPC map
102
146
  this.connectors = new Map();
103
- this.injectedConnector = new InjectedConnector(this.networkRpcMap, this.wallets, configuredTonConnectConfig, configuredTronConnectorConfig, networks);
147
+ this.injectedConnector = new InjectedConnector(this.networkRpcMap, this.wallets, configuredTonConnectConfig, configuredTronConnectorConfig, networks,
148
+ // Surface BridgeChild discovery failures (the Bitstarz "wallet never
149
+ // appeared via the bridge" class) as a telemetry event.
150
+ info => this.eventManager.emit('bridgeError', {
151
+ namespace: info.namespace,
152
+ error: { type: 'unknown', message: info.message }
153
+ }));
104
154
  this.connectors.set('injected', this.injectedConnector);
105
155
  if (configuredTonConnectConfig) {
106
156
  this.connectors.set('tonConnect', new TonConnectConnector(configuredTonConnectConfig));
107
157
  }
108
158
  // Only add WalletConnect connector if config is provided
109
159
  if (configuredWalletConnectConfig) {
110
- this.connectors.set('walletConnect', new WalletConnectConnector(configuredWalletConnectConfig, this.networkRpcMap));
160
+ this.connectors.set('walletConnect', new WalletConnectConnector(configuredWalletConnectConfig, this.networkRpcMap,
161
+ // Surface relay-socket failures (e.g. code 3000 JWT clock skew) that are
162
+ // detached from the connect handoff, as a telemetry event.
163
+ (error) => this.eventManager.emit('relayError', {
164
+ error: {
165
+ type: 'unknown',
166
+ message: error instanceof Error ? error.message : String(error)
167
+ }
168
+ })));
111
169
  }
112
170
  this.sessionManager = new SessionManager();
113
- this.eventManager = new EventManager();
114
- this.connectionService = new ConnectionService(networks, this.wallets, this.sessionManager, this.connectors, configuredUsingIntegratedBrowser, this.eventManager);
115
- this.networkSwitchService = new NetworkSwitchService(networks, this.sessionManager, this.connectors, configuredUsingIntegratedBrowser, this.eventManager);
116
- this.signatureService = new SignatureService(this.sessionManager, this.connectors);
117
- this.transactionService = new TransactionService(this.sessionManager, this.connectors);
171
+ this.connectionService = new ConnectionService(networks, this.wallets, this.sessionManager, this.connectors, configuredUsingIntegratedBrowser, this.eventManager, this.walletResponseTimeoutMs);
172
+ this.networkSwitchService = new NetworkSwitchService(networks, this.sessionManager, this.connectors, configuredUsingIntegratedBrowser, this.eventManager, this.walletResponseTimeoutMs);
173
+ this.signatureService = new SignatureService(this.sessionManager, this.connectors, configuredUsingIntegratedBrowser, this.eventManager, this.walletResponseTimeoutMs);
174
+ this.transactionService = new TransactionService(this.sessionManager, this.connectors, configuredUsingIntegratedBrowser, this.eventManager, this.walletResponseTimeoutMs);
118
175
  this.walletCapabilitiesService = new WalletCapabilitiesService(networks, this.connectors, this.sessionManager, this.eventManager);
119
176
  // Register as the shared instance so getInstance() works
120
177
  // (only set if no instance exists, to avoid overwriting an earlier one)
@@ -148,7 +205,7 @@ export class UniversalWalletConnector {
148
205
  // call, not the sum.
149
206
  const detectionTasks = [];
150
207
  for (const namespace of namespaces) {
151
- for (const [, connector] of this.connectors) {
208
+ for (const [connectionMode, connector] of this.connectors) {
152
209
  if (typeof connector.getAvailableWallets !== 'function')
153
210
  continue;
154
211
  detectionTasks.push(Promise.resolve()
@@ -158,8 +215,17 @@ export class UniversalWalletConnector {
158
215
  this.applyDetectedWallet(namespace, d);
159
216
  }
160
217
  })
161
- .catch(() => {
162
- // Silently handle errors for individual connector/namespace combinations
218
+ .catch(error => {
219
+ // Was a silent catch now a telemetry signal so a discovery
220
+ // failure (the "why didn't wallet X appear?" class) is observable
221
+ // rather than vanishing. STILL swallowed for control flow: one
222
+ // namespace × connector failing must not abort the others or
223
+ // reject detection.
224
+ this.eventManager.emit('walletDiscoveryFailed', {
225
+ namespace: namespace,
226
+ connectionMode,
227
+ error: toWalletError(error)
228
+ });
163
229
  }));
164
230
  }
165
231
  }
@@ -168,7 +234,13 @@ export class UniversalWalletConnector {
168
234
  this.connectionService.updateWallets(this.wallets);
169
235
  // Mark detection as complete
170
236
  this.detectionComplete = true;
171
- this.eventManager.emit('walletsDetected', { wallets: this.wallets });
237
+ // Per-namespace requested-vs-matched summary (counts only, non-PII) so a
238
+ // dashboard can tell "asked for N solana wallets, matched 0" (a metadata /
239
+ // config problem) from "asked for none".
240
+ this.eventManager.emit('walletsDetected', {
241
+ wallets: this.wallets,
242
+ discovery: this.summarizeDiscovery(namespaces)
243
+ });
172
244
  this.eventManager.emit('ready', undefined);
173
245
  }
174
246
  catch (error) {
@@ -273,6 +345,32 @@ export class UniversalWalletConnector {
273
345
  };
274
346
  }
275
347
  }
348
+ /**
349
+ * Per-namespace requested-vs-matched counts after detection. `requested` =
350
+ * configured wallets that declared the namespace; `matched` = those now marked
351
+ * installed. Counts only — never a wallet id or address. Feeds `walletsDetected`
352
+ * so a dashboard can answer "asked for N, matched 0?".
353
+ */
354
+ summarizeDiscovery(namespaces) {
355
+ const pickProvider = (w) => this.usingIntegratedBrowser
356
+ ? w.integratedBrowserInjectedProvider
357
+ : w.extensionInjectedProvider;
358
+ const summary = {};
359
+ for (const namespace of namespaces) {
360
+ let requested = 0;
361
+ let matched = 0;
362
+ for (const wallet of this.wallets) {
363
+ const nsMeta = pickProvider(wallet)?.namespaceMetaData?.[namespace];
364
+ if (!nsMeta)
365
+ continue;
366
+ requested++;
367
+ if (nsMeta.installed)
368
+ matched++;
369
+ }
370
+ summary[namespace] = { requested, matched };
371
+ }
372
+ return summary;
373
+ }
276
374
  getSession() {
277
375
  return this.sessionManager.getSession();
278
376
  }
@@ -311,10 +409,13 @@ export class UniversalWalletConnector {
311
409
  }
312
410
  async connect(connectionMode, walletId, networkId, options) {
313
411
  try {
412
+ // Hand-off instrumentation lives in ConnectionService.connect (emitted
413
+ // after validation, at the real wallet boundary) — not here, so pre-wallet
414
+ // validation failures don't pollute the funnel.
314
415
  await this.connectionService.connect(connectionMode, walletId, networkId, options);
315
416
  }
316
417
  catch (error) {
317
- this.emitError(error, 'connect');
418
+ this.emitError(error, 'connect', options?.signal);
318
419
  throw error;
319
420
  }
320
421
  }
@@ -326,16 +427,27 @@ export class UniversalWalletConnector {
326
427
  await this.connectionService.disconnect(options);
327
428
  }
328
429
  catch (error) {
329
- this.emitError(error, 'disconnect');
430
+ this.emitError(error, 'disconnect', options?.signal);
330
431
  throw error;
331
432
  }
332
433
  }
333
434
  async switchNetwork(networkId, options) {
435
+ // Captured before the switch so a cross-namespace move is detectable after.
436
+ const previousNamespace = this.sessionManager.getSession().activeNetwork?.namespace;
334
437
  try {
438
+ // Hand-off instrumentation lives in NetworkSwitchService.switchNetwork
439
+ // (emitted after validation, at the real wallet boundary).
335
440
  await this.networkSwitchService.switchNetwork(networkId, options);
441
+ // A cross-namespace switch changes the live provider, so the connect-time
442
+ // lifecycle subscription would keep observing the OLD namespace's provider
443
+ // and label its events with the new session's routing. Re-evaluate it.
444
+ const nextNamespace = this.sessionManager.getSession().activeNetwork?.namespace;
445
+ if (nextNamespace !== undefined && nextNamespace !== previousNamespace) {
446
+ this.connectionService.reattachLifecycle();
447
+ }
336
448
  }
337
449
  catch (error) {
338
- this.emitError(error, 'switchNetwork');
450
+ this.emitError(error, 'switchNetwork', options?.signal);
339
451
  throw error;
340
452
  }
341
453
  }
@@ -349,34 +461,13 @@ export class UniversalWalletConnector {
349
461
  * @returns A promise that resolves to the signature
350
462
  */
351
463
  async signMessage(message, options) {
352
- const session = this.sessionManager.getSession();
353
- if (!session.activeWallet) {
354
- throw new Error('No active wallet');
355
- }
356
- if (!session.connectionMode) {
357
- throw new Error('No active connection');
358
- }
359
464
  try {
360
- // Get the provider from the active wallet based on connection mode
361
- let provider;
362
- if (session.connectionMode === 'injected') {
363
- provider = this.usingIntegratedBrowser
364
- ? session.activeWallet.integratedBrowserInjectedProvider
365
- : session.activeWallet.extensionInjectedProvider;
366
- }
367
- else if (session.connectionMode === 'walletConnect') {
368
- provider = session.activeWallet.walletConnectProvider;
369
- }
370
- else if (session.connectionMode === 'tonConnect') {
371
- return await this.signatureService.signMessage(message, undefined, options);
372
- }
373
- if (!provider) {
374
- throw new Error('No provider available for the active wallet');
375
- }
376
- return await this.signatureService.signMessage(message, provider, options);
465
+ // Validation + funnel instrumentation live in SignatureService (after
466
+ // validation, at the real wallet boundary) — same layering as connect.
467
+ return await this.signatureService.signMessage(message, options);
377
468
  }
378
469
  catch (error) {
379
- this.emitError(error, 'signMessage');
470
+ this.emitError(error, 'signMessage', options?.signal);
380
471
  throw error;
381
472
  }
382
473
  }
@@ -389,28 +480,14 @@ export class UniversalWalletConnector {
389
480
  * @returns A promise that resolves to the 65-byte hex signature (0x-prefixed)
390
481
  */
391
482
  async signTypedData(typedData) {
392
- const session = this.sessionManager.getSession();
393
- if (!session.activeWallet) {
394
- throw new Error('No active wallet');
395
- }
396
- if (!session.connectionMode) {
397
- throw new Error('No active connection');
398
- }
399
- if (session.connectionMode === 'tonConnect') {
400
- throw new Error('signTypedData is not supported for TON wallets');
401
- }
402
- // Resolve the injected provider from the active wallet. WalletConnect
403
- // resolves its own provider inside the connector, so it stays undefined here.
404
- let provider;
405
- if (session.connectionMode === 'injected') {
406
- provider = this.usingIntegratedBrowser
407
- ? session.activeWallet.integratedBrowserInjectedProvider
408
- : session.activeWallet.extensionInjectedProvider;
409
- if (!provider) {
410
- throw new Error('No provider available for the active wallet');
411
- }
483
+ try {
484
+ // Validation + funnel instrumentation live in SignatureService.
485
+ return await this.signatureService.signTypedData(typedData);
486
+ }
487
+ catch (error) {
488
+ this.emitError(error, 'signTypedData');
489
+ throw error;
412
490
  }
413
- return await this.signatureService.signTypedData(typedData, provider);
414
491
  }
415
492
  /**
416
493
  * Send a transaction with the connected wallet
@@ -419,34 +496,13 @@ export class UniversalWalletConnector {
419
496
  * @returns A promise that resolves to the transaction result
420
497
  */
421
498
  async sendTransaction(request, options) {
422
- const session = this.sessionManager.getSession();
423
- if (!session.activeWallet) {
424
- throw new Error('No active wallet');
425
- }
426
- if (!session.connectionMode) {
427
- throw new Error('No active connection');
428
- }
429
499
  try {
430
- // Get the provider from the active wallet based on connection mode
431
- let provider;
432
- if (session.connectionMode === 'injected') {
433
- provider = this.usingIntegratedBrowser
434
- ? session.activeWallet.integratedBrowserInjectedProvider
435
- : session.activeWallet.extensionInjectedProvider;
436
- }
437
- else if (session.connectionMode === 'walletConnect') {
438
- provider = session.activeWallet.walletConnectProvider;
439
- }
440
- else if (session.connectionMode === 'tonConnect') {
441
- return await this.transactionService.sendTransaction(request, undefined, options);
442
- }
443
- if (!provider) {
444
- throw new Error('No provider available for the active wallet');
445
- }
446
- return await this.transactionService.sendTransaction(request, provider, options);
500
+ // Validation + funnel instrumentation live in TransactionService (after
501
+ // validation, at the real wallet boundary) — same layering as connect.
502
+ return await this.transactionService.sendTransaction(request, options);
447
503
  }
448
504
  catch (error) {
449
- this.emitError(error, 'sendTransaction');
505
+ this.emitError(error, 'sendTransaction', options?.signal);
450
506
  throw error;
451
507
  }
452
508
  }
@@ -456,19 +512,14 @@ export class UniversalWalletConnector {
456
512
  * tonConnect doesn't implement it.
457
513
  */
458
514
  async signSolanaTransaction(serializedTx) {
459
- const session = this.sessionManager.getSession();
460
- if (!session.activeWallet) {
461
- throw new Error('No active wallet');
462
- }
463
- if (!session.connectionMode) {
464
- throw new Error('No active connection');
515
+ try {
516
+ // Validation + funnel instrumentation live in TransactionService.
517
+ return await this.transactionService.signSolanaTransactionBytes(serializedTx);
465
518
  }
466
- // The active connector must implement the optional signSolanaTransactionBytes.
467
- const connector = this.connectors.get(session.connectionMode);
468
- if (!connector?.signSolanaTransactionBytes) {
469
- throw new Error(`signSolanaTransaction is not supported for connection mode "${session.connectionMode}"`);
519
+ catch (error) {
520
+ this.emitError(error, 'signSolanaTransaction');
521
+ throw error;
470
522
  }
471
- return await connector.signSolanaTransactionBytes(serializedTx);
472
523
  }
473
524
  /**
474
525
  * Fetch wallet capabilities for the connected wallet
@@ -482,7 +533,7 @@ export class UniversalWalletConnector {
482
533
  return await this.walletCapabilitiesService.getWalletCapabilities(address, activeNetwork, options);
483
534
  }
484
535
  catch (error) {
485
- this.emitError(error, 'getWalletCapabilities');
536
+ this.emitError(error, 'getWalletCapabilities', options?.signal);
486
537
  throw error;
487
538
  }
488
539
  }
@@ -528,21 +579,67 @@ export class UniversalWalletConnector {
528
579
  const session = this.sessionManager.getSession();
529
580
  return session.activeWalletCapabilities;
530
581
  }
582
+ /**
583
+ * Set the console log threshold at runtime (e.g. from a support toggle). The
584
+ * global `window.UWC_DEBUG` override still takes precedence for ad-hoc triage.
585
+ */
586
+ setLogLevel(level) {
587
+ this.logger.setLevel(level);
588
+ }
589
+ /**
590
+ * Release observer subscriptions and clear all event listeners. Call on full
591
+ * teardown / logout to avoid leaking listeners across connector lifecycles.
592
+ */
593
+ dispose() {
594
+ this.observerTeardown?.();
595
+ this.observerTeardown = undefined;
596
+ // Release any live provider-lifecycle listeners on a connected session —
597
+ // `dispose()` can be called without a prior `disconnect()`, and leaving the
598
+ // EIP-1193/adapter `.on` handlers attached is the zombie-listener leak this
599
+ // method's contract promises to prevent.
600
+ this.connectionService.teardownLifecycle();
601
+ this.eventManager.clearAllListeners();
602
+ // Full teardown: if this was the shared singleton, clear the static refs too
603
+ // so a later getInstance()/new starts clean — otherwise getInstance() would
604
+ // hand back this now-listener-less instance, and the instance-count warning
605
+ // would mis-fire on the next construction.
606
+ if (UniversalWalletConnector.instance === this) {
607
+ UniversalWalletConnector.resetInstance();
608
+ }
609
+ }
531
610
  // ---- private helpers ----
532
- emitError(error, operation) {
611
+ emitError(error, operation, signal) {
533
612
  // Intentional cancellations (AbortSignal.throwIfAborted, fetch abort,
534
613
  // DOMException) should NOT surface as wallet errors — the caller already
535
- // knows it asked to abort. Skip emission so error telemetry stays clean.
536
- if (error instanceof Error && error.name === 'AbortError') {
614
+ // knows it asked to abort. Uses the same name+signal check as
615
+ // `instrumentHandoff`, so both a DOMException abort (not an `Error`
616
+ // subclass in every runtime) AND a custom `abort(reason)` — whose rejection
617
+ // value carries the caller's own name — are skipped consistently.
618
+ if (isAbortError(error) || signal?.aborted) {
537
619
  return;
538
620
  }
539
- const walletError = error instanceof WalletConnectorError
540
- ? { type: error.type, message: error.message }
541
- : {
542
- type: 'unknown',
543
- message: error instanceof Error ? error.message : String(error)
544
- };
545
- this.eventManager.emit('error', { error: walletError, operation });
621
+ // Classify here too so a PRE-wallet validation failure — which never enters
622
+ // the handoff funnel (no awaitingWallet/terminal) — still carries
623
+ // failureKind/source/errorCode in telemetry. The #1 prod connection error,
624
+ // `no_common_network`, lands here; forward its two CAIP-2 id lists.
625
+ const { errorCode, failureKind, source } = classifyError(error);
626
+ this.eventManager.emit('error', {
627
+ error: toWalletError(error),
628
+ operation,
629
+ errorCode,
630
+ failureKind,
631
+ source,
632
+ // A handoff terminal already reported this failure — mark this record as
633
+ // the back-compat duplicate so metrics can count terminals + uncovered
634
+ // errors without double-counting.
635
+ ...(hasHandoffTerminal(error) && { handoffCovered: true }),
636
+ ...(error instanceof NoCommonNetworkError && {
637
+ networkMismatch: {
638
+ walletNetworkIds: error.walletNetworkIds,
639
+ configuredNetworkIds: error.configuredNetworkIds
640
+ }
641
+ })
642
+ });
546
643
  }
547
644
  }
548
645
  //# sourceMappingURL=universal-wallet-connector.js.map