@meshconnect/uwc-core 2.5.16-snapshot.da6ba82 → 2.6.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 +2 -2
- package/dist/events.d.ts +10 -0
- package/dist/events.d.ts.map +1 -1
- package/dist/events.js.map +1 -1
- package/dist/observability/instrument-handoff.d.ts +2 -0
- package/dist/observability/instrument-handoff.d.ts.map +1 -1
- package/dist/observability/instrument-handoff.js +6 -0
- package/dist/observability/instrument-handoff.js.map +1 -1
- package/dist/observability/telemetry.d.ts +2 -0
- package/dist/observability/telemetry.d.ts.map +1 -1
- package/dist/observability/telemetry.js +15 -21
- package/dist/observability/telemetry.js.map +1 -1
- package/dist/services/connection-service.d.ts +5 -0
- package/dist/services/connection-service.d.ts.map +1 -1
- package/dist/services/connection-service.js +21 -4
- package/dist/services/connection-service.js.map +1 -1
- package/dist/universal-wallet-connector.d.ts +7 -0
- package/dist/universal-wallet-connector.d.ts.map +1 -1
- package/dist/universal-wallet-connector.js +3 -2
- package/dist/universal-wallet-connector.js.map +1 -1
- package/dist/utils/to-wallet-error.d.ts.map +1 -1
- package/dist/utils/to-wallet-error.js +7 -8
- package/dist/utils/to-wallet-error.js.map +1 -1
- package/dist/version.d.ts +1 -1
- package/dist/version.d.ts.map +1 -1
- package/dist/version.js +1 -1
- package/dist/version.js.map +1 -1
- package/package.json +5 -5
- package/src/events.ts +10 -0
- package/src/observability/instrument-handoff.ts +8 -0
- package/src/observability/telemetry.test.ts +0 -59
- package/src/observability/telemetry.ts +17 -22
- package/src/services/connection-service.test.ts +113 -1
- package/src/services/connection-service.ts +30 -4
- package/src/universal-wallet-connector.ts +10 -2
- package/src/utils/to-wallet-error.test.ts +11 -19
- package/src/utils/to-wallet-error.ts +6 -7
- package/src/version.ts +1 -1
|
@@ -26,6 +26,11 @@ export interface ServiceOptions {
|
|
|
26
26
|
* Forwarded verbatim to the connector; see `ConnectorConnectOptions`.
|
|
27
27
|
*/
|
|
28
28
|
requiredAddresses?: readonly string[]
|
|
29
|
+
/**
|
|
30
|
+
* Connect only if the wallet already trusts this origin (connect only).
|
|
31
|
+
* Injected mode only; see `ConnectorConnectOptions.silentOnly`.
|
|
32
|
+
*/
|
|
33
|
+
silentOnly?: boolean
|
|
29
34
|
}
|
|
30
35
|
|
|
31
36
|
/** Sibling-namespace live-account re-read poll: absorbs the lag while a wallet
|
|
@@ -101,6 +106,17 @@ export class ConnectionService {
|
|
|
101
106
|
const provider = this.getProviderForMode(wallet, connectionMode)
|
|
102
107
|
const network = this.validateAndDetermineNetwork(networkId, provider)
|
|
103
108
|
const connector = this.getConnector(connectionMode)
|
|
109
|
+
// A silent-only connect is a promise never to open wallet UI. Only the
|
|
110
|
+
// injected connector can keep it — WalletConnect / TON Connect always hand
|
|
111
|
+
// off to the wallet — so refuse the rest here, as a validation failure:
|
|
112
|
+
// before `connecting`, so the attempt never enters the hand-off funnel.
|
|
113
|
+
// A plain Error, not `WalletNotAuthorizedError`: that classifies as the
|
|
114
|
+
// expected `not_authorized` miss, which would hide this caller bug.
|
|
115
|
+
if (options?.silentOnly && connectionMode !== 'injected') {
|
|
116
|
+
throw new Error(
|
|
117
|
+
`silentOnly is not supported for connection mode '${connectionMode}'`
|
|
118
|
+
)
|
|
119
|
+
}
|
|
104
120
|
const connectAttemptId = generateId()
|
|
105
121
|
|
|
106
122
|
// Supersede any prior in-flight attempt: abort it so its URI poll and
|
|
@@ -157,7 +173,10 @@ export class ConnectionService {
|
|
|
157
173
|
walletId,
|
|
158
174
|
namespace: network.namespace,
|
|
159
175
|
chainId: network.id,
|
|
160
|
-
connectAttemptId
|
|
176
|
+
connectAttemptId,
|
|
177
|
+
// Lets telemetry tell a silent restore from a tapped connect: both
|
|
178
|
+
// succeed the same way, and only a miss carries a distinct failureKind.
|
|
179
|
+
silentOnly: options?.silentOnly === true
|
|
161
180
|
},
|
|
162
181
|
async handoffId => {
|
|
163
182
|
// Publish this attempt's routing for the connector's step sink.
|
|
@@ -170,7 +189,8 @@ export class ConnectionService {
|
|
|
170
189
|
provider,
|
|
171
190
|
signal,
|
|
172
191
|
connectAttemptId,
|
|
173
|
-
options?.requiredAddresses
|
|
192
|
+
options?.requiredAddresses,
|
|
193
|
+
options?.silentOnly
|
|
174
194
|
)
|
|
175
195
|
} finally {
|
|
176
196
|
// Retract ONLY if we are still the published attempt. An
|
|
@@ -261,7 +281,8 @@ export class ConnectionService {
|
|
|
261
281
|
provider: SupportedProvider,
|
|
262
282
|
signal: AbortSignal,
|
|
263
283
|
connectAttemptId: string,
|
|
264
|
-
requiredAddresses?: readonly string[]
|
|
284
|
+
requiredAddresses?: readonly string[],
|
|
285
|
+
silentOnly?: boolean
|
|
265
286
|
): Promise<ConnectorResult> {
|
|
266
287
|
// Race the connector call against the AbortSignal so a mid-flight abort
|
|
267
288
|
// (e.g. user cancels the WalletConnect QR while the prompt is open)
|
|
@@ -274,7 +295,12 @@ export class ConnectionService {
|
|
|
274
295
|
provider as
|
|
275
296
|
| ExtensionInjectedProvider
|
|
276
297
|
| IntegratedBrowserInjectedProvider,
|
|
277
|
-
requiredAddresses
|
|
298
|
+
requiredAddresses || silentOnly
|
|
299
|
+
? {
|
|
300
|
+
...(requiredAddresses ? { requiredAddresses } : {}),
|
|
301
|
+
...(silentOnly ? { silentOnly } : {})
|
|
302
|
+
}
|
|
303
|
+
: undefined
|
|
278
304
|
),
|
|
279
305
|
signal
|
|
280
306
|
)
|
|
@@ -130,6 +130,13 @@ export interface ConnectOptions extends OperationOptions {
|
|
|
130
130
|
* constraint.
|
|
131
131
|
*/
|
|
132
132
|
requiredAddresses?: readonly string[]
|
|
133
|
+
/**
|
|
134
|
+
* Connect only if the wallet already trusts this origin; never prompt.
|
|
135
|
+
* Forwarded to the connector as {@link ConnectorConnectOptions.silentOnly}
|
|
136
|
+
* — see there for the semantics. `'injected'` mode only: any other mode
|
|
137
|
+
* rejects with a plain `Error` before reaching the wallet.
|
|
138
|
+
*/
|
|
139
|
+
silentOnly?: boolean
|
|
133
140
|
}
|
|
134
141
|
|
|
135
142
|
export class UniversalWalletConnector {
|
|
@@ -473,8 +480,9 @@ export class UniversalWalletConnector {
|
|
|
473
480
|
UniversalWalletConnector.instance = this
|
|
474
481
|
}
|
|
475
482
|
|
|
476
|
-
// Initialize detected wallets after services are created
|
|
477
|
-
|
|
483
|
+
// Initialize detected wallets after services are created. Fire-and-forget on
|
|
484
|
+
// purpose (a constructor can't await); the method catches everything itself.
|
|
485
|
+
void this.initializeDetectedWallets()
|
|
478
486
|
}
|
|
479
487
|
|
|
480
488
|
/**
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { describe, it, expect } from 'vitest'
|
|
2
2
|
import {
|
|
3
3
|
WalletConnectorError,
|
|
4
|
-
NoCommonNetworkError
|
|
4
|
+
NoCommonNetworkError,
|
|
5
|
+
WalletNotAuthorizedError
|
|
5
6
|
} from '@meshconnect/uwc-types'
|
|
6
7
|
import {
|
|
7
8
|
classifyError,
|
|
@@ -38,6 +39,15 @@ describe('classifyError', () => {
|
|
|
38
39
|
})
|
|
39
40
|
})
|
|
40
41
|
|
|
42
|
+
it('classifies WalletNotAuthorizedError as not_authorized/connector (ONC-1975)', () => {
|
|
43
|
+
// A silent-only connect that found no authorization. Expected, not a
|
|
44
|
+
// fault, so it gets its own kind that failure rates can exclude.
|
|
45
|
+
expect(classifyError(new WalletNotAuthorizedError())).toEqual({
|
|
46
|
+
failureKind: 'not_authorized',
|
|
47
|
+
source: 'connector'
|
|
48
|
+
})
|
|
49
|
+
})
|
|
50
|
+
|
|
41
51
|
it('classifies -32002 (request already pending) as provider_error', () => {
|
|
42
52
|
// Delta B: the double-fire race. A provider-level error, not a user reject.
|
|
43
53
|
expect(classifyError({ code: -32002, message: 'already pending' })).toEqual(
|
|
@@ -203,24 +213,6 @@ describe('toWalletError', () => {
|
|
|
203
213
|
})
|
|
204
214
|
})
|
|
205
215
|
|
|
206
|
-
it('carries the provider reason of a connector error', () => {
|
|
207
|
-
const err = new WalletConnectorError({
|
|
208
|
-
type: 'unknown',
|
|
209
|
-
message: 'An unknown RPC error occurred.',
|
|
210
|
-
providerReason: 'cancelled'
|
|
211
|
-
})
|
|
212
|
-
expect(toWalletError(err)).toEqual({
|
|
213
|
-
type: 'unknown',
|
|
214
|
-
message: 'An unknown RPC error occurred.',
|
|
215
|
-
providerReason: 'cancelled'
|
|
216
|
-
})
|
|
217
|
-
})
|
|
218
|
-
|
|
219
|
-
it('omits providerReason when the connector error has none', () => {
|
|
220
|
-
const err = new WalletConnectorError({ type: 'unknown', message: 'x' })
|
|
221
|
-
expect(toWalletError(err)).not.toHaveProperty('providerReason')
|
|
222
|
-
})
|
|
223
|
-
|
|
224
216
|
it('bounds an over-long non-connector message (shared safeErrorMessage cap)', () => {
|
|
225
217
|
const err = new Error('x'.repeat(10_000))
|
|
226
218
|
expect(toWalletError(err).message).toHaveLength(500)
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
2
|
WalletConnectorError,
|
|
3
3
|
NoCommonNetworkError,
|
|
4
|
+
WalletNotAuthorizedError,
|
|
4
5
|
safeErrorMessage,
|
|
5
6
|
type WalletError,
|
|
6
7
|
type FailureKind,
|
|
@@ -26,13 +27,7 @@ const MAX_ERROR_CODE_LENGTH = 64
|
|
|
26
27
|
export function toWalletError(error: unknown): WalletError {
|
|
27
28
|
try {
|
|
28
29
|
if (error instanceof WalletConnectorError) {
|
|
29
|
-
return {
|
|
30
|
-
type: error.type,
|
|
31
|
-
message: error.message,
|
|
32
|
-
...(error.providerReason
|
|
33
|
-
? { providerReason: error.providerReason }
|
|
34
|
-
: {})
|
|
35
|
-
}
|
|
30
|
+
return { type: error.type, message: error.message }
|
|
36
31
|
}
|
|
37
32
|
return { type: 'unknown', message: safeErrorMessage(error) }
|
|
38
33
|
} catch {
|
|
@@ -107,6 +102,10 @@ function classifyErrorUnguarded(error: unknown): {
|
|
|
107
102
|
let failureKind: FailureKind = 'unknown'
|
|
108
103
|
if (isUserRejection(error)) {
|
|
109
104
|
failureKind = 'user_rejected'
|
|
105
|
+
} else if (error instanceof WalletNotAuthorizedError) {
|
|
106
|
+
// A silent-only connect stopped because the wallet hasn't authorized this
|
|
107
|
+
// origin. Nothing was shown to the user, so it is expected, not a fault.
|
|
108
|
+
failureKind = 'not_authorized'
|
|
110
109
|
} else if (error instanceof NoCommonNetworkError) {
|
|
111
110
|
// The wallet and configured networks don't overlap — the #1 prod connection
|
|
112
111
|
// failure. Carries its own CAIP-2 id lists; the caller forwards them.
|
package/src/version.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
// Generated from package.json by scripts/generate-version.mjs — do not edit.
|
|
2
|
-
export const UWC_CORE_VERSION = '2.
|
|
2
|
+
export const UWC_CORE_VERSION = '2.6.0'
|