@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.
- package/README.md +247 -76
- package/dist/events.d.ts +241 -5
- package/dist/events.d.ts.map +1 -1
- package/dist/events.js +77 -1
- package/dist/events.js.map +1 -1
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -1
- package/dist/logger/create-logger.d.ts +32 -0
- package/dist/logger/create-logger.d.ts.map +1 -0
- package/dist/logger/create-logger.js +79 -0
- package/dist/logger/create-logger.js.map +1 -0
- package/dist/managers/event-manager.d.ts.map +1 -1
- package/dist/managers/event-manager.js +5 -1
- package/dist/managers/event-manager.js.map +1 -1
- package/dist/observability/connect-observer.d.ts +33 -0
- package/dist/observability/connect-observer.d.ts.map +1 -0
- package/dist/observability/connect-observer.js +115 -0
- package/dist/observability/connect-observer.js.map +1 -0
- package/dist/observability/focus-tracker.d.ts +42 -0
- package/dist/observability/focus-tracker.d.ts.map +1 -0
- package/dist/observability/focus-tracker.js +57 -0
- package/dist/observability/focus-tracker.js.map +1 -0
- package/dist/observability/instrument-handoff.d.ts +54 -0
- package/dist/observability/instrument-handoff.d.ts.map +1 -0
- package/dist/observability/instrument-handoff.js +173 -0
- package/dist/observability/instrument-handoff.js.map +1 -0
- package/dist/observability/lifecycle-bridge.d.ts +69 -0
- package/dist/observability/lifecycle-bridge.d.ts.map +1 -0
- package/dist/observability/lifecycle-bridge.js +155 -0
- package/dist/observability/lifecycle-bridge.js.map +1 -0
- package/dist/observability/scrub.d.ts +31 -0
- package/dist/observability/scrub.d.ts.map +1 -0
- package/dist/observability/scrub.js +167 -0
- package/dist/observability/scrub.js.map +1 -0
- package/dist/observability/telemetry.d.ts +157 -0
- package/dist/observability/telemetry.d.ts.map +1 -0
- package/dist/observability/telemetry.js +373 -0
- package/dist/observability/telemetry.js.map +1 -0
- package/dist/services/connection-service.d.ts +23 -1
- package/dist/services/connection-service.d.ts.map +1 -1
- package/dist/services/connection-service.js +128 -19
- package/dist/services/connection-service.js.map +1 -1
- package/dist/services/network-switch-service.d.ts +2 -1
- package/dist/services/network-switch-service.d.ts.map +1 -1
- package/dist/services/network-switch-service.js +45 -16
- package/dist/services/network-switch-service.js.map +1 -1
- package/dist/services/signature-service.d.ts +14 -7
- package/dist/services/signature-service.d.ts.map +1 -1
- package/dist/services/signature-service.js +56 -58
- package/dist/services/signature-service.js.map +1 -1
- package/dist/services/transaction-service.d.ts +19 -5
- package/dist/services/transaction-service.d.ts.map +1 -1
- package/dist/services/transaction-service.js +55 -38
- package/dist/services/transaction-service.js.map +1 -1
- package/dist/universal-wallet-connector.d.ts +56 -1
- package/dist/universal-wallet-connector.d.ts.map +1 -1
- package/dist/universal-wallet-connector.js +207 -110
- package/dist/universal-wallet-connector.js.map +1 -1
- package/dist/utils/id.d.ts +2 -0
- package/dist/utils/id.d.ts.map +1 -0
- package/dist/utils/id.js +41 -0
- package/dist/utils/id.js.map +1 -0
- package/dist/utils/resolve-session-provider.d.ts +10 -0
- package/dist/utils/resolve-session-provider.d.ts.map +1 -0
- package/dist/utils/resolve-session-provider.js +21 -0
- package/dist/utils/resolve-session-provider.js.map +1 -0
- package/dist/utils/to-wallet-error.d.ts +35 -0
- package/dist/utils/to-wallet-error.d.ts.map +1 -0
- package/dist/utils/to-wallet-error.js +130 -0
- package/dist/utils/to-wallet-error.js.map +1 -0
- package/dist/utils/validate-wallet-session.d.ts +15 -0
- package/dist/utils/validate-wallet-session.d.ts.map +1 -0
- package/dist/utils/validate-wallet-session.js +29 -0
- package/dist/utils/validate-wallet-session.js.map +1 -0
- package/dist/version.d.ts +2 -0
- package/dist/version.d.ts.map +1 -0
- package/dist/version.js +3 -0
- package/dist/version.js.map +1 -0
- package/package.json +6 -6
- package/src/events.ts +326 -14
- package/src/index.ts +10 -0
- package/src/logger/create-logger.test.ts +126 -0
- package/src/logger/create-logger.ts +112 -0
- package/src/managers/event-manager.test.ts +55 -0
- package/src/managers/event-manager.ts +5 -1
- package/src/observability/connect-observer.test.ts +214 -0
- package/src/observability/connect-observer.ts +128 -0
- package/src/observability/focus-tracker.test.ts +191 -0
- package/src/observability/focus-tracker.ts +96 -0
- package/src/observability/instrument-handoff.test.ts +397 -0
- package/src/observability/instrument-handoff.ts +231 -0
- package/src/observability/lifecycle-bridge.test.ts +398 -0
- package/src/observability/lifecycle-bridge.ts +216 -0
- package/src/observability/scrub.test.ts +183 -0
- package/src/observability/scrub.ts +174 -0
- package/src/observability/telemetry.test.ts +549 -0
- package/src/observability/telemetry.ts +546 -0
- package/src/services/connection-service.test.ts +261 -1
- package/src/services/connection-service.ts +167 -38
- package/src/services/network-switch-service.test.ts +51 -1
- package/src/services/network-switch-service.ts +56 -24
- package/src/services/signature-service.test.ts +181 -76
- package/src/services/signature-service.ts +75 -85
- package/src/services/transaction-service.test.ts +270 -69
- package/src/services/transaction-service.ts +74 -51
- package/src/universal-wallet-connector.instrumentation-guard.test.ts +199 -0
- package/src/universal-wallet-connector.observability.test.ts +610 -0
- package/src/universal-wallet-connector.test.ts +27 -146
- package/src/universal-wallet-connector.ts +279 -142
- package/src/utils/id.test.ts +15 -0
- package/src/utils/id.ts +48 -0
- package/src/utils/resolve-session-provider.test.ts +54 -0
- package/src/utils/resolve-session-provider.ts +25 -0
- package/src/utils/to-wallet-error.test.ts +181 -0
- package/src/utils/to-wallet-error.ts +152 -0
- package/src/utils/validate-wallet-session.test.ts +77 -0
- package/src/utils/validate-wallet-session.ts +40 -0
- package/src/version.test.ts +11 -0
- package/src/version.ts +2 -0
|
@@ -0,0 +1,373 @@
|
|
|
1
|
+
import { UWC_CORE_VERSION } from '../version';
|
|
2
|
+
import { scrubMessage } from './scrub';
|
|
3
|
+
/**
|
|
4
|
+
* Telemetry record schema version. Bump on any breaking change to the
|
|
5
|
+
* `UWCTelemetryEvent` shape so a downstream consumer can branch on it.
|
|
6
|
+
*/
|
|
7
|
+
export const TELEMETRY_SCHEMA_VERSION = 1;
|
|
8
|
+
/**
|
|
9
|
+
* Egress bounds for `networkMismatch`. `walletNetworkIds` comes from catalog
|
|
10
|
+
* wallet metadata (`provider.supportedNetworkIds`), not live wallet input — but
|
|
11
|
+
* it is unbounded upstream, so cap cardinality and element length here as
|
|
12
|
+
* defense-in-depth. Elements are NOT scrubbed: a legitimate
|
|
13
|
+
* `solana:<32-char-base58-ref>` CAIP-2 id would be eaten by the base58 rule.
|
|
14
|
+
*/
|
|
15
|
+
const MAX_NETWORK_MISMATCH_IDS = 20;
|
|
16
|
+
const MAX_NETWORK_ID_LENGTH = 64;
|
|
17
|
+
function capNetworkMismatch(mismatch) {
|
|
18
|
+
if (!mismatch)
|
|
19
|
+
return undefined;
|
|
20
|
+
const cap = (ids) => ids
|
|
21
|
+
.slice(0, MAX_NETWORK_MISMATCH_IDS)
|
|
22
|
+
.map(id => id.slice(0, MAX_NETWORK_ID_LENGTH));
|
|
23
|
+
return {
|
|
24
|
+
walletNetworkIds: cap(mismatch.walletNetworkIds),
|
|
25
|
+
configuredNetworkIds: cap(mismatch.configuredNetworkIds)
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Best-effort coarse runtime surface. HEURISTIC — user agents lie and in-app
|
|
30
|
+
* browsers are hard to detect; treat `webview` as a hint, not a guarantee.
|
|
31
|
+
* Never returns the raw UA (PII / high-cardinality).
|
|
32
|
+
*/
|
|
33
|
+
export function derivePlatform() {
|
|
34
|
+
if (typeof navigator === 'undefined' || !navigator.userAgent)
|
|
35
|
+
return 'unknown';
|
|
36
|
+
const ua = navigator.userAgent;
|
|
37
|
+
const isIOS = /iPhone|iPad|iPod/i.test(ua);
|
|
38
|
+
const isAndroid = /Android/i.test(ua);
|
|
39
|
+
// Android in-app browsers tag the UA with `; wv`; iOS WKWebViews lack `Safari`.
|
|
40
|
+
const isWebview = (isAndroid && /; wv\)/i.test(ua)) || (isIOS && !/Safari/i.test(ua));
|
|
41
|
+
if (isWebview)
|
|
42
|
+
return 'webview';
|
|
43
|
+
if (isIOS || isAndroid)
|
|
44
|
+
return 'mobile';
|
|
45
|
+
return 'desktop';
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Derive the flow taxonomy from connection mode + surface. HEURISTIC — UWC does
|
|
49
|
+
* not always know whether a WalletConnect handoff used a deeplink vs a QR scan;
|
|
50
|
+
* we infer from the platform (mobile ⇒ deeplink, desktop ⇒ QR), matching link-v2's
|
|
51
|
+
* historical intent. Consumers with better context may override downstream.
|
|
52
|
+
*/
|
|
53
|
+
export function deriveWalletFlowType(connectionMode, platform) {
|
|
54
|
+
const isDesktop = platform === 'desktop';
|
|
55
|
+
switch (connectionMode) {
|
|
56
|
+
case 'injected':
|
|
57
|
+
// Injected on a phone almost always means we're inside a wallet's browser.
|
|
58
|
+
return isDesktop ? 'browser_extension_flow' : 'in_wallet_browser_flow';
|
|
59
|
+
case 'walletConnect':
|
|
60
|
+
return isDesktop
|
|
61
|
+
? 'wallet_connect_qr_flow'
|
|
62
|
+
: 'wallet_connect_deep_link_flow';
|
|
63
|
+
case 'tonConnect':
|
|
64
|
+
return isDesktop ? 'ton_connect_qr_flow' : 'ton_connect_deep_link_flow';
|
|
65
|
+
default:
|
|
66
|
+
return 'unknown';
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Per-namespace address coverage for a session — telemetry-only, non-PII
|
|
71
|
+
* (namespace names + counts, never an address). Derived purely from the session:
|
|
72
|
+
* `availableNetworks` is the connected wallet's supported networks already
|
|
73
|
+
* filtered to the session's configured set, and `availableAddresses` is what the
|
|
74
|
+
* connect actually gathered, so `missing` is precise per-connect (no cross-wallet
|
|
75
|
+
* discovery join that could false-positive on a different installed wallet).
|
|
76
|
+
*
|
|
77
|
+
* `missing` is the observable symptom of a dropped secondary-namespace gather:
|
|
78
|
+
* the wallet supports the namespace for a configured network, but no address for
|
|
79
|
+
* it came back.
|
|
80
|
+
*/
|
|
81
|
+
function summarizeAddressCoverage(session) {
|
|
82
|
+
// Defensive `?? []`: this runs on the wallet path, so a partial/malformed
|
|
83
|
+
// session must never throw here (a real session always has both arrays).
|
|
84
|
+
const addressNamespaces = {};
|
|
85
|
+
const present = new Set();
|
|
86
|
+
for (const { networkId } of session.availableAddresses ?? []) {
|
|
87
|
+
const namespace = networkId.split(':')[0];
|
|
88
|
+
if (!namespace)
|
|
89
|
+
continue;
|
|
90
|
+
present.add(namespace);
|
|
91
|
+
addressNamespaces[namespace] = (addressNamespaces[namespace] ?? 0) + 1;
|
|
92
|
+
}
|
|
93
|
+
const supported = new Set((session.availableNetworks ?? []).map(n => n.namespace));
|
|
94
|
+
const missing = [...supported].filter(namespace => !present.has(namespace));
|
|
95
|
+
return { addressNamespaces, missing };
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* Map a raw `UWCEventMap` event to its PII-safe `UWCTelemetryEvent`.
|
|
99
|
+
*
|
|
100
|
+
* Per-event allow-listing: only known-safe fields are copied. Payloads carrying a
|
|
101
|
+
* `Session`/`Network` (which include the wallet address) are reduced to
|
|
102
|
+
* `namespace` + `chainId` + `walletId`. Unknown/noisy payloads collapse to just
|
|
103
|
+
* the name. `error.message` is scrubbed.
|
|
104
|
+
*/
|
|
105
|
+
function buildTelemetryEvent(name, data, sdkSessionId, now, correlationId) {
|
|
106
|
+
// `correlationId` is added to the key only when supplied — never aliased to
|
|
107
|
+
// `sdkSessionId`, so a consumer can tell "I gave no id" from "id == session".
|
|
108
|
+
const base = {
|
|
109
|
+
schemaVersion: TELEMETRY_SCHEMA_VERSION,
|
|
110
|
+
uwcVersion: UWC_CORE_VERSION,
|
|
111
|
+
name,
|
|
112
|
+
sdkSessionId,
|
|
113
|
+
timestamp: now,
|
|
114
|
+
...(correlationId !== undefined ? { correlationId } : {})
|
|
115
|
+
};
|
|
116
|
+
switch (name) {
|
|
117
|
+
case 'connecting': {
|
|
118
|
+
const d = data;
|
|
119
|
+
return {
|
|
120
|
+
...base,
|
|
121
|
+
operation: 'connect',
|
|
122
|
+
connectionMode: d.connectionMode,
|
|
123
|
+
walletId: d.walletId
|
|
124
|
+
};
|
|
125
|
+
}
|
|
126
|
+
case 'connected':
|
|
127
|
+
case 'sessionChanged': {
|
|
128
|
+
const d = data;
|
|
129
|
+
const session = d.session;
|
|
130
|
+
const { addressNamespaces, missing } = summarizeAddressCoverage(session);
|
|
131
|
+
return {
|
|
132
|
+
...base,
|
|
133
|
+
connectionMode: session.connectionMode ?? undefined,
|
|
134
|
+
namespace: session.activeNetwork?.namespace,
|
|
135
|
+
chainId: session.activeNetwork?.id,
|
|
136
|
+
walletId: session.activeWallet?.id,
|
|
137
|
+
addressNamespaces,
|
|
138
|
+
...(missing.length > 0 && { missingNamespaces: missing })
|
|
139
|
+
};
|
|
140
|
+
}
|
|
141
|
+
case 'networkSwitched': {
|
|
142
|
+
const d = data;
|
|
143
|
+
return {
|
|
144
|
+
...base,
|
|
145
|
+
operation: 'switchNetwork',
|
|
146
|
+
namespace: d.network.namespace,
|
|
147
|
+
chainId: d.network.id
|
|
148
|
+
};
|
|
149
|
+
}
|
|
150
|
+
case 'connectionUri': {
|
|
151
|
+
// Carry the mode but NEVER the URI itself (a relay/pairing string).
|
|
152
|
+
const d = data;
|
|
153
|
+
return { ...base, connectionMode: d.connectionMode };
|
|
154
|
+
}
|
|
155
|
+
case 'error': {
|
|
156
|
+
const d = data;
|
|
157
|
+
return {
|
|
158
|
+
...base,
|
|
159
|
+
operation: d.operation,
|
|
160
|
+
error: { type: d.error.type, message: scrubMessage(d.error.message) },
|
|
161
|
+
// Telemetry-only classification — undefined for ordinary errors, set for
|
|
162
|
+
// pre-wallet validation failures (e.g. no_common_network) that never
|
|
163
|
+
// reach the handoff funnel.
|
|
164
|
+
errorCode: d.errorCode,
|
|
165
|
+
failureKind: d.failureKind,
|
|
166
|
+
source: d.source,
|
|
167
|
+
networkMismatch: capNetworkMismatch(d.networkMismatch),
|
|
168
|
+
handoffCovered: d.handoffCovered
|
|
169
|
+
};
|
|
170
|
+
}
|
|
171
|
+
case 'awaitingWallet': {
|
|
172
|
+
const d = data;
|
|
173
|
+
return {
|
|
174
|
+
...base,
|
|
175
|
+
operation: d.operation,
|
|
176
|
+
connectionMode: d.connectionMode,
|
|
177
|
+
walletId: d.walletId,
|
|
178
|
+
namespace: d.namespace,
|
|
179
|
+
chainId: d.chainId,
|
|
180
|
+
handoffId: d.handoffId,
|
|
181
|
+
walletFlowType: d.walletFlowType,
|
|
182
|
+
platform: d.platform,
|
|
183
|
+
targetAlreadyActive: d.targetAlreadyActive
|
|
184
|
+
};
|
|
185
|
+
}
|
|
186
|
+
case 'walletSucceeded': {
|
|
187
|
+
const d = data;
|
|
188
|
+
return {
|
|
189
|
+
...base,
|
|
190
|
+
operation: d.operation,
|
|
191
|
+
connectionMode: d.connectionMode,
|
|
192
|
+
walletId: d.walletId,
|
|
193
|
+
namespace: d.namespace,
|
|
194
|
+
chainId: d.chainId,
|
|
195
|
+
handoffId: d.handoffId,
|
|
196
|
+
durationMs: d.durationMs,
|
|
197
|
+
timedOut: d.timedOut,
|
|
198
|
+
timeoutMs: d.timeoutMs,
|
|
199
|
+
targetAlreadyActive: d.targetAlreadyActive
|
|
200
|
+
};
|
|
201
|
+
}
|
|
202
|
+
case 'walletRejected': {
|
|
203
|
+
const d = data;
|
|
204
|
+
return {
|
|
205
|
+
...base,
|
|
206
|
+
operation: d.operation,
|
|
207
|
+
connectionMode: d.connectionMode,
|
|
208
|
+
walletId: d.walletId,
|
|
209
|
+
namespace: d.namespace,
|
|
210
|
+
chainId: d.chainId,
|
|
211
|
+
handoffId: d.handoffId,
|
|
212
|
+
durationMs: d.durationMs,
|
|
213
|
+
timedOut: d.timedOut,
|
|
214
|
+
timeoutMs: d.timeoutMs,
|
|
215
|
+
targetAlreadyActive: d.targetAlreadyActive,
|
|
216
|
+
errorCode: d.errorCode,
|
|
217
|
+
failureKind: d.failureKind,
|
|
218
|
+
source: d.source
|
|
219
|
+
};
|
|
220
|
+
}
|
|
221
|
+
case 'walletTimedOut': {
|
|
222
|
+
const d = data;
|
|
223
|
+
return {
|
|
224
|
+
...base,
|
|
225
|
+
operation: d.operation,
|
|
226
|
+
connectionMode: d.connectionMode,
|
|
227
|
+
walletId: d.walletId,
|
|
228
|
+
namespace: d.namespace,
|
|
229
|
+
chainId: d.chainId,
|
|
230
|
+
handoffId: d.handoffId,
|
|
231
|
+
durationMs: d.durationMs,
|
|
232
|
+
timeoutMs: d.timeoutMs,
|
|
233
|
+
targetAlreadyActive: d.targetAlreadyActive
|
|
234
|
+
};
|
|
235
|
+
}
|
|
236
|
+
case 'walletFailed': {
|
|
237
|
+
const d = data;
|
|
238
|
+
return {
|
|
239
|
+
...base,
|
|
240
|
+
operation: d.operation,
|
|
241
|
+
connectionMode: d.connectionMode,
|
|
242
|
+
walletId: d.walletId,
|
|
243
|
+
namespace: d.namespace,
|
|
244
|
+
chainId: d.chainId,
|
|
245
|
+
handoffId: d.handoffId,
|
|
246
|
+
durationMs: d.durationMs,
|
|
247
|
+
timedOut: d.timedOut,
|
|
248
|
+
timeoutMs: d.timeoutMs,
|
|
249
|
+
targetAlreadyActive: d.targetAlreadyActive,
|
|
250
|
+
errorCode: d.errorCode,
|
|
251
|
+
failureKind: d.failureKind,
|
|
252
|
+
source: d.source,
|
|
253
|
+
error: { type: d.error.type, message: scrubMessage(d.error.message) }
|
|
254
|
+
};
|
|
255
|
+
}
|
|
256
|
+
case 'capabilitiesUpdated': {
|
|
257
|
+
const d = data;
|
|
258
|
+
// Summarize to per-chain lists of the capability names that are not
|
|
259
|
+
// 'unsupported'. Compact + non-PII (chain ids + bounded feature names).
|
|
260
|
+
const capabilities = {};
|
|
261
|
+
for (const [chainId, caps] of Object.entries(d.capabilities)) {
|
|
262
|
+
const enabled = Object.entries(caps)
|
|
263
|
+
.filter(([, cap]) => cap && cap.status !== 'unsupported')
|
|
264
|
+
.map(([feature]) => feature);
|
|
265
|
+
if (enabled.length > 0)
|
|
266
|
+
capabilities[chainId] = enabled;
|
|
267
|
+
}
|
|
268
|
+
return { ...base, capabilities };
|
|
269
|
+
}
|
|
270
|
+
case 'walletsDetected': {
|
|
271
|
+
const d = data;
|
|
272
|
+
// Carry only the compact requested-vs-matched summary; never the wallet list.
|
|
273
|
+
return { ...base, ...(d.discovery ? { discovery: d.discovery } : {}) };
|
|
274
|
+
}
|
|
275
|
+
case 'walletDiscoveryFailed': {
|
|
276
|
+
const d = data;
|
|
277
|
+
return {
|
|
278
|
+
...base,
|
|
279
|
+
connectionMode: d.connectionMode,
|
|
280
|
+
namespace: d.namespace,
|
|
281
|
+
error: { type: d.error.type, message: scrubMessage(d.error.message) }
|
|
282
|
+
};
|
|
283
|
+
}
|
|
284
|
+
case 'pageHiddenDuringHandoff':
|
|
285
|
+
case 'pageVisibleDuringHandoff': {
|
|
286
|
+
const d = data;
|
|
287
|
+
return { ...base, handoffId: d.handoffId, platform: d.platform };
|
|
288
|
+
}
|
|
289
|
+
case 'bridgeError': {
|
|
290
|
+
const d = data;
|
|
291
|
+
return {
|
|
292
|
+
...base,
|
|
293
|
+
namespace: d.namespace,
|
|
294
|
+
source: 'bridge',
|
|
295
|
+
failureKind: 'bridge_error',
|
|
296
|
+
error: { type: d.error.type, message: scrubMessage(d.error.message) }
|
|
297
|
+
};
|
|
298
|
+
}
|
|
299
|
+
case 'relayError': {
|
|
300
|
+
const d = data;
|
|
301
|
+
// A relay-socket transport failure (WalletConnect only). The scrubbed message
|
|
302
|
+
// carries the diagnostic detail (e.g. "code: 3000 (JWT ... not yet valid)").
|
|
303
|
+
return {
|
|
304
|
+
...base,
|
|
305
|
+
connectionMode: 'walletConnect',
|
|
306
|
+
source: 'provider',
|
|
307
|
+
failureKind: 'network_error',
|
|
308
|
+
error: { type: d.error.type, message: scrubMessage(d.error.message) }
|
|
309
|
+
};
|
|
310
|
+
}
|
|
311
|
+
case 'walletAccountChanged':
|
|
312
|
+
case 'walletDisconnected':
|
|
313
|
+
case 'walletSessionExpired': {
|
|
314
|
+
const d = data;
|
|
315
|
+
return {
|
|
316
|
+
...base,
|
|
317
|
+
connectionMode: d.connectionMode,
|
|
318
|
+
walletId: d.walletId,
|
|
319
|
+
namespace: d.namespace
|
|
320
|
+
};
|
|
321
|
+
}
|
|
322
|
+
case 'walletChainChanged': {
|
|
323
|
+
const d = data;
|
|
324
|
+
return {
|
|
325
|
+
...base,
|
|
326
|
+
connectionMode: d.connectionMode,
|
|
327
|
+
walletId: d.walletId,
|
|
328
|
+
namespace: d.namespace,
|
|
329
|
+
chainId: d.chainId
|
|
330
|
+
};
|
|
331
|
+
}
|
|
332
|
+
case 'lifecycleTelemetryUnavailable': {
|
|
333
|
+
const d = data;
|
|
334
|
+
return {
|
|
335
|
+
...base,
|
|
336
|
+
connectionMode: d.connectionMode,
|
|
337
|
+
walletId: d.walletId,
|
|
338
|
+
namespace: d.namespace,
|
|
339
|
+
reason: d.reason,
|
|
340
|
+
runtime: d.runtime
|
|
341
|
+
};
|
|
342
|
+
}
|
|
343
|
+
default:
|
|
344
|
+
// ready / disconnected / networkSwitching / change / log — name only
|
|
345
|
+
// (log goes via onLog).
|
|
346
|
+
return base;
|
|
347
|
+
}
|
|
348
|
+
}
|
|
349
|
+
/**
|
|
350
|
+
* Drop keys whose value is `undefined` so a record never carries a
|
|
351
|
+
* present-but-undefined optional (e.g. `errorCode: undefined` on a non-error
|
|
352
|
+
* event), which would make `'errorCode' in event` misleading. Shallow by design:
|
|
353
|
+
* nested objects (`error`, `networkMismatch`, `discovery`, `capabilities`,
|
|
354
|
+
* `addressNamespaces`) are only ever built with defined values.
|
|
355
|
+
*/
|
|
356
|
+
function compactUndefined(event) {
|
|
357
|
+
const record = event;
|
|
358
|
+
const out = {};
|
|
359
|
+
for (const key of Object.keys(record)) {
|
|
360
|
+
const value = record[key];
|
|
361
|
+
if (value !== undefined)
|
|
362
|
+
out[key] = value;
|
|
363
|
+
}
|
|
364
|
+
return out;
|
|
365
|
+
}
|
|
366
|
+
/**
|
|
367
|
+
* Normalize a bus event into a PII-safe `UWCTelemetryEvent`, dropping undefined
|
|
368
|
+
* optionals so the emitted shape is consistent across event kinds.
|
|
369
|
+
*/
|
|
370
|
+
export function normalizeEvent(name, data, sdkSessionId, now, correlationId) {
|
|
371
|
+
return compactUndefined(buildTelemetryEvent(name, data, sdkSessionId, now, correlationId));
|
|
372
|
+
}
|
|
373
|
+
//# sourceMappingURL=telemetry.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"telemetry.js","sourceRoot":"","sources":["../../src/observability/telemetry.ts"],"names":[],"mappings":"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"}
|
|
@@ -11,9 +11,31 @@ export declare class ConnectionService {
|
|
|
11
11
|
private connectors;
|
|
12
12
|
private usingIntegratedBrowser;
|
|
13
13
|
private eventManager;
|
|
14
|
+
private walletResponseTimeoutMs;
|
|
14
15
|
private activeConnector;
|
|
15
|
-
|
|
16
|
+
/** Tears down the post-connect lifecycle subscription; set while connected. */
|
|
17
|
+
private lifecycleTeardown;
|
|
18
|
+
constructor(networks: Network[], wallets: WalletMetadata[], sessionManager: SessionManager, connectors: Map<ConnectionMode, Connector>, usingIntegratedBrowser: boolean, eventManager: EventManager, walletResponseTimeoutMs: number);
|
|
16
19
|
connect(connectionMode: ConnectionMode, walletId: string, networkId?: NetworkId, options?: ServiceOptions): Promise<void>;
|
|
20
|
+
/** Wire the active connector's lifecycle stream onto the bus (or signal absence). */
|
|
21
|
+
private attachLifecycle;
|
|
22
|
+
/**
|
|
23
|
+
* Remove the active provider-lifecycle subscription (EIP-1193 `.on` / wallet-
|
|
24
|
+
* adapter / SignClient listeners) WITHOUT disconnecting the wallet. Idempotent.
|
|
25
|
+
* Exposed so a full `dispose()` that bypasses `disconnect()` still releases these
|
|
26
|
+
* listeners — leaving them attached is the zombie-listener class this layer
|
|
27
|
+
* exists to prevent.
|
|
28
|
+
*/
|
|
29
|
+
teardownLifecycle(): void;
|
|
30
|
+
/**
|
|
31
|
+
* Re-evaluate the lifecycle source for the CURRENT session. Used after a
|
|
32
|
+
* cross-namespace switchNetwork: the live provider changes with the namespace,
|
|
33
|
+
* so the connect-time subscription would keep observing the old namespace's
|
|
34
|
+
* provider and label its events with the new session's routing. Tears the old
|
|
35
|
+
* subscription down and re-attaches against the active session's facets.
|
|
36
|
+
* Safe no-op when nothing is connected.
|
|
37
|
+
*/
|
|
38
|
+
reattachLifecycle(): void;
|
|
17
39
|
private connectWithURIPoll;
|
|
18
40
|
private getConnector;
|
|
19
41
|
private findWallet;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"connection-service.d.ts","sourceRoot":"","sources":["../../src/services/connection-service.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,OAAO,EACP,SAAS,
|
|
1
|
+
{"version":3,"file":"connection-service.d.ts","sourceRoot":"","sources":["../../src/services/connection-service.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,OAAO,EACP,SAAS,EAET,cAAc,EACd,cAAc,EACd,SAAS,EAMV,MAAM,wBAAwB,CAAA;AAE/B,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,6BAA6B,CAAA;AACjE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAA;AAK7D,MAAM,WAAW,cAAc;IAC7B,MAAM,CAAC,EAAE,WAAW,CAAA;CACrB;AAED,qBAAa,iBAAiB;IAM1B,OAAO,CAAC,QAAQ;IAChB,OAAO,CAAC,OAAO;IACf,OAAO,CAAC,cAAc;IACtB,OAAO,CAAC,UAAU;IAClB,OAAO,CAAC,sBAAsB;IAC9B,OAAO,CAAC,YAAY;IAEpB,OAAO,CAAC,uBAAuB;IAZjC,OAAO,CAAC,eAAe,CAAyB;IAChD,+EAA+E;IAC/E,OAAO,CAAC,iBAAiB,CAA0B;gBAGzC,QAAQ,EAAE,OAAO,EAAE,EACnB,OAAO,EAAE,cAAc,EAAE,EACzB,cAAc,EAAE,cAAc,EAC9B,UAAU,EAAE,GAAG,CAAC,cAAc,EAAE,SAAS,CAAC,EAC1C,sBAAsB,EAAE,OAAO,EAC/B,YAAY,EAAE,YAAY,EAE1B,uBAAuB,EAAE,MAAM;IAGnC,OAAO,CACX,cAAc,EAAE,cAAc,EAC9B,QAAQ,EAAE,MAAM,EAChB,SAAS,CAAC,EAAE,SAAS,EACrB,OAAO,CAAC,EAAE,cAAc,GACvB,OAAO,CAAC,IAAI,CAAC;IAiHhB,qFAAqF;IACrF,OAAO,CAAC,eAAe;IA8CvB;;;;;;OAMG;IACH,iBAAiB,IAAI,IAAI;IAKzB;;;;;;;OAOG;IACH,iBAAiB,IAAI,IAAI;YAqBX,kBAAkB;IAqDhC,OAAO,CAAC,YAAY;IAUpB,OAAO,CAAC,UAAU;IAQlB,OAAO,CAAC,kBAAkB;IA2C1B,OAAO,CAAC,2BAA2B;IAiD7B,UAAU,CAAC,OAAO,CAAC,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC;IAqBzD,gBAAgB,IAAI,MAAM,GAAG,SAAS;IAiBtC,UAAU,IAAI,cAAc,EAAE;IAI9B,aAAa,CAAC,OAAO,EAAE,cAAc,EAAE,GAAG,IAAI;IAI9C,WAAW,IAAI,OAAO,EAAE;IAIxB;;;;;;;;;;;;OAYG;IACH,OAAO,CAAC,wBAAwB;CAiBjC"}
|
|
@@ -1,4 +1,7 @@
|
|
|
1
|
+
import { NoCommonNetworkError } from '@meshconnect/uwc-types';
|
|
1
2
|
import { raceAbort } from '../utils/abort';
|
|
3
|
+
import { instrumentHandoff } from '../observability/instrument-handoff';
|
|
4
|
+
import { attachLifecycle } from '../observability/lifecycle-bridge';
|
|
2
5
|
export class ConnectionService {
|
|
3
6
|
networks;
|
|
4
7
|
wallets;
|
|
@@ -6,14 +9,20 @@ export class ConnectionService {
|
|
|
6
9
|
connectors;
|
|
7
10
|
usingIntegratedBrowser;
|
|
8
11
|
eventManager;
|
|
12
|
+
walletResponseTimeoutMs;
|
|
9
13
|
activeConnector = null;
|
|
10
|
-
|
|
14
|
+
/** Tears down the post-connect lifecycle subscription; set while connected. */
|
|
15
|
+
lifecycleTeardown;
|
|
16
|
+
constructor(networks, wallets, sessionManager, connectors, usingIntegratedBrowser, eventManager,
|
|
17
|
+
// Observational wallet-response deadline for the handoff timeout marker.
|
|
18
|
+
walletResponseTimeoutMs) {
|
|
11
19
|
this.networks = networks;
|
|
12
20
|
this.wallets = wallets;
|
|
13
21
|
this.sessionManager = sessionManager;
|
|
14
22
|
this.connectors = connectors;
|
|
15
23
|
this.usingIntegratedBrowser = usingIntegratedBrowser;
|
|
16
24
|
this.eventManager = eventManager;
|
|
25
|
+
this.walletResponseTimeoutMs = walletResponseTimeoutMs;
|
|
17
26
|
}
|
|
18
27
|
async connect(connectionMode, walletId, networkId, options) {
|
|
19
28
|
options?.signal?.throwIfAborted();
|
|
@@ -33,28 +42,46 @@ export class ConnectionService {
|
|
|
33
42
|
this.activeConnector = connector;
|
|
34
43
|
let result;
|
|
35
44
|
try {
|
|
36
|
-
//
|
|
37
|
-
//
|
|
38
|
-
//
|
|
39
|
-
//
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
45
|
+
// Instrument the wallet hand-off HERE — after validation + the `connecting`
|
|
46
|
+
// emit — so `awaitingWallet` marks the real wallet boundary. A pre-wallet
|
|
47
|
+
// lookup/validation failure throws above and never enters the funnel. The
|
|
48
|
+
// resolved `network` gives accurate namespace/chainId facets.
|
|
49
|
+
result = await instrumentHandoff({
|
|
50
|
+
eventManager: this.eventManager,
|
|
51
|
+
timeoutMs: this.walletResponseTimeoutMs,
|
|
52
|
+
signal: options?.signal
|
|
53
|
+
}, {
|
|
54
|
+
operation: 'connect',
|
|
55
|
+
connectionMode,
|
|
56
|
+
walletId,
|
|
57
|
+
namespace: network.namespace,
|
|
58
|
+
chainId: network.id
|
|
59
|
+
}, async () => {
|
|
60
|
+
// Race the connector call against the AbortSignal so a mid-flight abort
|
|
61
|
+
// (e.g. user cancels the WalletConnect QR while the prompt is open)
|
|
62
|
+
// rejects the caller's await promptly. The underlying wallet prompt
|
|
63
|
+
// itself can't be cancelled, but the dapp UI is no longer blocked on it.
|
|
64
|
+
if (connectionMode === 'injected') {
|
|
65
|
+
return await raceAbort(connector.connect(network, provider), options?.signal);
|
|
66
|
+
}
|
|
67
|
+
else if (connectionMode === 'tonConnect' ||
|
|
68
|
+
connectionMode === 'walletConnect') {
|
|
69
|
+
return await raceAbort(this.connectWithURIPoll(connector, network, provider, connectionMode, options?.signal), options?.signal);
|
|
70
|
+
}
|
|
71
|
+
else {
|
|
72
|
+
throw new Error(`Unsupported connection mode: ${connectionMode}`);
|
|
73
|
+
}
|
|
74
|
+
});
|
|
75
|
+
// Belt-and-suspenders: if the signal fired between raceAbort resolving
|
|
76
|
+
// and this point, still bail before mutating session. Inside the try so
|
|
77
|
+
// the half-attached connector is released on this late abort too — a
|
|
78
|
+
// stale activeConnector would keep serving the aborted attempt's URI.
|
|
79
|
+
options?.signal?.throwIfAborted();
|
|
50
80
|
}
|
|
51
81
|
catch (error) {
|
|
52
82
|
this.activeConnector = null;
|
|
53
83
|
throw error;
|
|
54
84
|
}
|
|
55
|
-
// Belt-and-suspenders: if the signal fired between raceAbort resolving
|
|
56
|
-
// and this point, still bail before mutating session.
|
|
57
|
-
options?.signal?.throwIfAborted();
|
|
58
85
|
// Filter available addresses to only include those for configured networks
|
|
59
86
|
const filteredAvailableAddresses = result.availableAddresses.filter(addr => this.networks.some(n => n.id === addr.networkId));
|
|
60
87
|
this.sessionManager.updateSession({
|
|
@@ -69,6 +96,82 @@ export class ConnectionService {
|
|
|
69
96
|
const session = this.sessionManager.getSession();
|
|
70
97
|
this.eventManager.emit('connected', { session });
|
|
71
98
|
this.eventManager.emit('sessionChanged', { session });
|
|
99
|
+
// Observe post-connect wallet lifecycle (account/chain switch in the wallet,
|
|
100
|
+
// disconnect, expiry) from the live provider — telemetry only, never changes
|
|
101
|
+
// connection behaviour. Torn down on disconnect.
|
|
102
|
+
this.attachLifecycle(connectionMode, wallet.id, network.namespace);
|
|
103
|
+
}
|
|
104
|
+
/** Wire the active connector's lifecycle stream onto the bus (or signal absence). */
|
|
105
|
+
attachLifecycle(connectionMode, walletId, namespace, initialSwitch) {
|
|
106
|
+
this.teardownLifecycle();
|
|
107
|
+
const connector = this.activeConnector;
|
|
108
|
+
this.lifecycleTeardown = attachLifecycle({
|
|
109
|
+
eventManager: this.eventManager,
|
|
110
|
+
// Reattach-after-switch only: seed echo suppression, because the fresh
|
|
111
|
+
// subscription never saw the completed switch's bus events.
|
|
112
|
+
...(initialSwitch && { initialSwitch }),
|
|
113
|
+
// The context names the session being attached FOR — the connector routes
|
|
114
|
+
// by it (never by its own ambient state, which is ambiguous when the
|
|
115
|
+
// secondary-namespace gather left several live surfaces).
|
|
116
|
+
subscribe: connector?.onLifecycleEvent
|
|
117
|
+
? listener => connector.onLifecycleEvent(listener, {
|
|
118
|
+
connectionMode,
|
|
119
|
+
namespace,
|
|
120
|
+
walletId
|
|
121
|
+
})
|
|
122
|
+
: undefined,
|
|
123
|
+
getRouting: () => {
|
|
124
|
+
const s = this.sessionManager.getSession();
|
|
125
|
+
return {
|
|
126
|
+
connectionMode: s.connectionMode ?? connectionMode,
|
|
127
|
+
walletId: s.activeWallet?.id ?? walletId,
|
|
128
|
+
namespace: s.activeNetwork?.namespace ?? namespace
|
|
129
|
+
};
|
|
130
|
+
},
|
|
131
|
+
connectionMode,
|
|
132
|
+
walletId,
|
|
133
|
+
namespace,
|
|
134
|
+
// The bridge child sets this when UWC runs inside the Link iframe; it tells
|
|
135
|
+
// a `lifecycleTelemetryUnavailable` consumer whether lifecycle was silent on
|
|
136
|
+
// the direct page or (expected, pending P3) over the production bridge.
|
|
137
|
+
runtime: globalThis
|
|
138
|
+
.UWCBridgeChildInitialized === true
|
|
139
|
+
? 'iframe'
|
|
140
|
+
: 'direct'
|
|
141
|
+
});
|
|
142
|
+
}
|
|
143
|
+
/**
|
|
144
|
+
* Remove the active provider-lifecycle subscription (EIP-1193 `.on` / wallet-
|
|
145
|
+
* adapter / SignClient listeners) WITHOUT disconnecting the wallet. Idempotent.
|
|
146
|
+
* Exposed so a full `dispose()` that bypasses `disconnect()` still releases these
|
|
147
|
+
* listeners — leaving them attached is the zombie-listener class this layer
|
|
148
|
+
* exists to prevent.
|
|
149
|
+
*/
|
|
150
|
+
teardownLifecycle() {
|
|
151
|
+
this.lifecycleTeardown?.();
|
|
152
|
+
this.lifecycleTeardown = undefined;
|
|
153
|
+
}
|
|
154
|
+
/**
|
|
155
|
+
* Re-evaluate the lifecycle source for the CURRENT session. Used after a
|
|
156
|
+
* cross-namespace switchNetwork: the live provider changes with the namespace,
|
|
157
|
+
* so the connect-time subscription would keep observing the old namespace's
|
|
158
|
+
* provider and label its events with the new session's routing. Tears the old
|
|
159
|
+
* subscription down and re-attaches against the active session's facets.
|
|
160
|
+
* Safe no-op when nothing is connected.
|
|
161
|
+
*/
|
|
162
|
+
reattachLifecycle() {
|
|
163
|
+
const session = this.sessionManager.getSession();
|
|
164
|
+
if (!this.activeConnector ||
|
|
165
|
+
!session.connectionMode ||
|
|
166
|
+
!session.activeWallet ||
|
|
167
|
+
!session.activeNetwork) {
|
|
168
|
+
return;
|
|
169
|
+
}
|
|
170
|
+
this.attachLifecycle(session.connectionMode, session.activeWallet.id, session.activeNetwork.namespace,
|
|
171
|
+
// The reattach follows a JUST-completed switch to the now-active chain —
|
|
172
|
+
// arm echo suppression for it so the new provider's echo isn't mistaken
|
|
173
|
+
// for a wallet-initiated change (one-shot, same as bus-armed switches).
|
|
174
|
+
{ chainId: session.activeNetwork.id, at: Date.now() });
|
|
72
175
|
}
|
|
73
176
|
async connectWithURIPoll(connector, network, provider, connectionMode, signal) {
|
|
74
177
|
const connectPromise = connector.connect(network, provider);
|
|
@@ -170,7 +273,10 @@ export class ConnectionService {
|
|
|
170
273
|
// Use the first supported network that exists in both wallet and configured networks
|
|
171
274
|
const supportedNetwork = provider.supportedNetworkIds.find(id => this.networks.some(n => n.id === id));
|
|
172
275
|
if (!supportedNetwork) {
|
|
173
|
-
|
|
276
|
+
// The #1 production connection failure. Throw a typed, self-describing
|
|
277
|
+
// error carrying both CAIP-2 id lists (non-PII) so telemetry can tell a
|
|
278
|
+
// metadata gap from a client-config mistake — see NoCommonNetworkError.
|
|
279
|
+
throw new NoCommonNetworkError(provider.supportedNetworkIds, this.networks.map(n => n.id));
|
|
174
280
|
}
|
|
175
281
|
targetNetworkId = supportedNetwork;
|
|
176
282
|
}
|
|
@@ -183,6 +289,9 @@ export class ConnectionService {
|
|
|
183
289
|
}
|
|
184
290
|
async disconnect(options) {
|
|
185
291
|
options?.signal?.throwIfAborted();
|
|
292
|
+
// Remove the lifecycle listeners first so a provider 'disconnect' fired during
|
|
293
|
+
// teardown doesn't re-enter as a wallet-initiated `walletDisconnected`.
|
|
294
|
+
this.teardownLifecycle();
|
|
186
295
|
try {
|
|
187
296
|
if (this.activeConnector &&
|
|
188
297
|
typeof this.activeConnector.disconnect === 'function') {
|