@metamask/connect-multichain 0.13.0 → 0.14.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/CHANGELOG.md +17 -1
- package/dist/browser/es/connect-multichain.d.mts +46 -2
- package/dist/browser/es/connect-multichain.mjs +144 -19
- package/dist/browser/es/connect-multichain.mjs.map +1 -1
- package/dist/browser/es/metafile-esm.json +1 -1
- package/dist/browser/iife/connect-multichain.d.ts +46 -2
- package/dist/browser/iife/connect-multichain.js +144 -19
- package/dist/browser/iife/connect-multichain.js.map +1 -1
- package/dist/browser/iife/metafile-iife.json +1 -1
- package/dist/browser/umd/connect-multichain.d.ts +46 -2
- package/dist/browser/umd/connect-multichain.js +144 -19
- package/dist/browser/umd/connect-multichain.js.map +1 -1
- package/dist/browser/umd/metafile-cjs.json +1 -1
- package/dist/node/cjs/connect-multichain.d.ts +46 -2
- package/dist/node/cjs/connect-multichain.js +145 -19
- package/dist/node/cjs/connect-multichain.js.map +1 -1
- package/dist/node/cjs/metafile-cjs.json +1 -1
- package/dist/node/es/connect-multichain.d.mts +46 -2
- package/dist/node/es/connect-multichain.mjs +144 -19
- package/dist/node/es/connect-multichain.mjs.map +1 -1
- package/dist/node/es/metafile-esm.json +1 -1
- package/dist/react-native/es/connect-multichain.d.mts +46 -2
- package/dist/react-native/es/connect-multichain.mjs +144 -19
- package/dist/react-native/es/connect-multichain.mjs.map +1 -1
- package/dist/react-native/es/metafile-esm.json +1 -1
- package/dist/src/domain/utils/index.d.ts +2 -1
- package/dist/src/domain/utils/index.d.ts.map +1 -1
- package/dist/src/domain/utils/index.js +1 -1
- package/dist/src/domain/utils/index.js.map +1 -1
- package/dist/src/multichain/index.d.ts.map +1 -1
- package/dist/src/multichain/index.js +2 -2
- package/dist/src/multichain/index.js.map +1 -1
- package/dist/src/multichain/rpc/requestRouter.d.ts.map +1 -1
- package/dist/src/multichain/rpc/requestRouter.js +4 -4
- package/dist/src/multichain/rpc/requestRouter.js.map +1 -1
- package/dist/src/multichain/transports/mwp/index.d.ts.map +1 -1
- package/dist/src/multichain/transports/mwp/index.js +17 -5
- package/dist/src/multichain/transports/mwp/index.js.map +1 -1
- package/dist/src/multichain/utils/analytics.d.ts +82 -1
- package/dist/src/multichain/utils/analytics.d.ts.map +1 -1
- package/dist/src/multichain/utils/analytics.js +252 -17
- package/dist/src/multichain/utils/analytics.js.map +1 -1
- package/dist/types/connect-multichain.d.ts +46 -2
- package/package.json +2 -2
|
@@ -1,11 +1,77 @@
|
|
|
1
1
|
import type { InvokeMethodOptions, MultichainOptions, PlatformType, StoreClient, TransportType } from '../../domain';
|
|
2
|
+
/**
|
|
3
|
+
* Tag describing the cause of a failed wallet action / connection. Surfaced
|
|
4
|
+
* as the `failure_reason` property on `mmconnect_wallet_action_failed` and
|
|
5
|
+
* `mmconnect_connection_failed` events so we can distinguish e.g. a transport
|
|
6
|
+
* timeout from a wallet-side internal error in Mixpanel.
|
|
7
|
+
*
|
|
8
|
+
* Intentionally a string union (not a const enum) so callers stay free to
|
|
9
|
+
* pass through a new bucket; the schema-side property is an open string for
|
|
10
|
+
* the same reason.
|
|
11
|
+
*/
|
|
12
|
+
export type FailureReason = 'transport_timeout' | 'transport_disconnect' | 'wallet_method_unsupported' | 'wallet_invalid_params' | 'wallet_internal_error' | 'wallet_unauthorized' | 'unrecognized_chain' | 'unknown';
|
|
13
|
+
/**
|
|
14
|
+
* Sanitises an error message for inclusion in analytics. Strips wallet
|
|
15
|
+
* addresses (EVM hex, Solana / Bitcoin Base58, Bech32), long hex blobs,
|
|
16
|
+
* URLs, and large decimal numbers, then truncates to
|
|
17
|
+
* {@link ERROR_MESSAGE_SAMPLE_MAX_LENGTH} characters. Returns `undefined`
|
|
18
|
+
* if there's no message to sample.
|
|
19
|
+
*
|
|
20
|
+
* @param message - Raw error message
|
|
21
|
+
* @returns A safe-to-emit short string, or `undefined`
|
|
22
|
+
*/
|
|
23
|
+
export declare function sanitiseErrorMessage(message: string | undefined): string | undefined;
|
|
2
24
|
/**
|
|
3
25
|
* Checks if an error represents a user rejection.
|
|
4
26
|
*
|
|
27
|
+
* Unwraps `RPCInvokeMethodErr` so the wallet's `code: 4001` survives the
|
|
28
|
+
* SDK's transport-boundary wrapping (the outer error otherwise reports
|
|
29
|
+
* `code: 53`, which would never match the heuristics here).
|
|
30
|
+
*
|
|
5
31
|
* @param error - The error object to check
|
|
6
32
|
* @returns True if the error indicates a user rejection, false otherwise
|
|
7
33
|
*/
|
|
8
34
|
export declare function isRejectionError(error: unknown): boolean;
|
|
35
|
+
/**
|
|
36
|
+
* Classifies a failed wallet action / connection error into a short tag for
|
|
37
|
+
* the `failure_reason` analytics property. Caller is expected to have already
|
|
38
|
+
* established that the error is *not* a user rejection (use `isRejectionError`
|
|
39
|
+
* for that branching).
|
|
40
|
+
*
|
|
41
|
+
* The taxonomy is deliberately producer-side-only — the schema accepts any
|
|
42
|
+
* string — so we can add buckets here without an API migration. Once the
|
|
43
|
+
* distribution stabilises we may convert the schema field to a closed enum.
|
|
44
|
+
*
|
|
45
|
+
* @param error - The error to classify
|
|
46
|
+
* @returns A short, snake_case tag describing why the operation failed
|
|
47
|
+
*/
|
|
48
|
+
export declare function classifyFailureReason(error: unknown): FailureReason;
|
|
49
|
+
/**
|
|
50
|
+
* Bundle of diagnostic properties attached to `mmconnect_*_failed` events:
|
|
51
|
+
* the bucketed {@link FailureReason}, the raw wallet-side error code if
|
|
52
|
+
* present, and a sanitised sample of the original message. All three are
|
|
53
|
+
* derived from a single error so producers only need to call this once.
|
|
54
|
+
*
|
|
55
|
+
* `error_code` and `error_message_sample` are intentionally optional —
|
|
56
|
+
* many SDK-internal errors (e.g. `'Transport not initialized'`) have
|
|
57
|
+
* neither a numeric code nor a useful message; in that case the caller
|
|
58
|
+
* should attach only `failure_reason`.
|
|
59
|
+
*/
|
|
60
|
+
export type ErrorDiagnostics = {
|
|
61
|
+
failure_reason: FailureReason;
|
|
62
|
+
error_code?: number;
|
|
63
|
+
error_message_sample?: string;
|
|
64
|
+
};
|
|
65
|
+
/**
|
|
66
|
+
* Computes the full set of diagnostic properties to attach to a
|
|
67
|
+
* `mmconnect_*_failed` event from a single error. Combines
|
|
68
|
+
* {@link classifyFailureReason}, the unwrapped wallet code, and a
|
|
69
|
+
* sanitised message sample so producer call sites stay a single line.
|
|
70
|
+
*
|
|
71
|
+
* @param error - The error to inspect
|
|
72
|
+
* @returns Diagnostics ready to spread into the event properties
|
|
73
|
+
*/
|
|
74
|
+
export declare function extractErrorDiagnostics(error: unknown): ErrorDiagnostics;
|
|
9
75
|
/**
|
|
10
76
|
* Gets base analytics properties that are common across all events.
|
|
11
77
|
*
|
|
@@ -26,14 +92,29 @@ export declare function getBaseAnalyticsProperties(options: MultichainOptions, s
|
|
|
26
92
|
* @param storage - Storage client for getting anonymous ID
|
|
27
93
|
* @param invokeOptions - The invoke method options containing method and scope
|
|
28
94
|
* @param transportType - The transport type to use for the analytics event
|
|
95
|
+
* @param extra - Optional event-specific diagnostic properties. Used by
|
|
96
|
+
* `mmconnect_wallet_action_failed` to attach the {@link ErrorDiagnostics}
|
|
97
|
+
* bundle (`failure_reason`, `error_code`, `error_message_sample`).
|
|
98
|
+
* @param extra.failure_reason - A short tag describing why the operation
|
|
99
|
+
* failed; see `classifyFailureReason` and the `FailureReason` union.
|
|
100
|
+
* @param extra.error_code - The raw wallet-side error code, if present.
|
|
101
|
+
* @param extra.error_message_sample - A sanitised, truncated sample of the
|
|
102
|
+
* original error message.
|
|
29
103
|
* @returns Wallet action analytics properties
|
|
30
104
|
*/
|
|
31
|
-
export declare function getWalletActionAnalyticsProperties(options: MultichainOptions, storage: StoreClient, invokeOptions: InvokeMethodOptions, transportType: TransportType
|
|
105
|
+
export declare function getWalletActionAnalyticsProperties(options: MultichainOptions, storage: StoreClient, invokeOptions: InvokeMethodOptions, transportType: TransportType, extra?: {
|
|
106
|
+
failure_reason?: FailureReason;
|
|
107
|
+
error_code?: number;
|
|
108
|
+
error_message_sample?: string;
|
|
109
|
+
}): Promise<{
|
|
32
110
|
mmconnect_versions: Record<string, string>;
|
|
33
111
|
dapp_id: string;
|
|
34
112
|
method: string;
|
|
35
113
|
caip_chain_id: string;
|
|
36
114
|
anon_id: string;
|
|
37
115
|
transport_type: TransportType;
|
|
116
|
+
failure_reason?: FailureReason;
|
|
117
|
+
error_code?: number;
|
|
118
|
+
error_message_sample?: string;
|
|
38
119
|
}>;
|
|
39
120
|
//# sourceMappingURL=analytics.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"analytics.d.ts","sourceRoot":"","sources":["../../../../src/multichain/utils/analytics.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EACV,mBAAmB,EACnB,iBAAiB,EACjB,YAAY,EAEZ,WAAW,EACX,aAAa,EACd,MAAM,cAAc,CAAC;AAGtB
|
|
1
|
+
{"version":3,"file":"analytics.d.ts","sourceRoot":"","sources":["../../../../src/multichain/utils/analytics.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EACV,mBAAmB,EACnB,iBAAiB,EACjB,YAAY,EAEZ,WAAW,EACX,aAAa,EACd,MAAM,cAAc,CAAC;AAGtB;;;;;;;;;GASG;AACH,MAAM,MAAM,aAAa,GACrB,mBAAmB,GACnB,sBAAsB,GACtB,2BAA2B,GAC3B,uBAAuB,GACvB,uBAAuB,GACvB,qBAAqB,GACrB,oBAAoB,GACpB,SAAS,CAAC;AA2Dd;;;;;;;;;GASG;AACH,wBAAgB,oBAAoB,CAClC,OAAO,EAAE,MAAM,GAAG,SAAS,GAC1B,MAAM,GAAG,SAAS,CAcpB;AAiCD;;;;;;;;;GASG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CA2BxD;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,OAAO,GAAG,aAAa,CAyFnE;AAED;;;;;;;;;;GAUG;AACH,MAAM,MAAM,gBAAgB,GAAG;IAC7B,cAAc,EAAE,aAAa,CAAC;IAC9B,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,oBAAoB,CAAC,EAAE,MAAM,CAAC;CAC/B,CAAC;AAEF;;;;;;;;GAQG;AACH,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,OAAO,GAAG,gBAAgB,CASxE;AAED;;;;;;GAMG;AACH,wBAAsB,0BAA0B,CAC9C,OAAO,EAAE,iBAAiB,EAC1B,OAAO,EAAE,WAAW,GACnB,OAAO,CAAC;IACT,kBAAkB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC3C,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,YAAY,CAAC;IACvB,OAAO,EAAE,MAAM,CAAC;CACjB,CAAC,CAWD;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAsB,kCAAkC,CACtD,OAAO,EAAE,iBAAiB,EAC1B,OAAO,EAAE,WAAW,EACpB,aAAa,EAAE,mBAAmB,EAClC,aAAa,EAAE,aAAa,EAC5B,KAAK,CAAC,EAAE;IACN,cAAc,CAAC,EAAE,aAAa,CAAC;IAC/B,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,oBAAoB,CAAC,EAAE,MAAM,CAAC;CAC/B,GACA,OAAO,CAAC;IACT,kBAAkB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC3C,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,aAAa,EAAE,MAAM,CAAC;IACtB,OAAO,EAAE,MAAM,CAAC;IAChB,cAAc,EAAE,aAAa,CAAC;IAC9B,cAAc,CAAC,EAAE,aAAa,CAAC;IAC/B,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,oBAAoB,CAAC,EAAE,MAAM,CAAC;CAC/B,CAAC,CAmBD"}
|
|
@@ -10,27 +10,257 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
10
10
|
/* eslint-disable @typescript-eslint/naming-convention */
|
|
11
11
|
/* eslint-disable @typescript-eslint/no-unused-vars -- Scope type used in JSDoc */
|
|
12
12
|
import { getDappId } from '.';
|
|
13
|
-
import { getPlatformType } from '../../domain';
|
|
13
|
+
import { getPlatformType, RPCInvokeMethodErr } from '../../domain';
|
|
14
|
+
/**
|
|
15
|
+
* Maximum length of `error_message_sample` after sanitisation. Mirrors the
|
|
16
|
+
* `maxLength: 200` constraint declared in the analytics-api `api.spec.yml`.
|
|
17
|
+
*/
|
|
18
|
+
const ERROR_MESSAGE_SAMPLE_MAX_LENGTH = 200;
|
|
19
|
+
/**
|
|
20
|
+
* Patterns scrubbed from `error_message_sample` before it leaves the SDK.
|
|
21
|
+
* The goal is to surface enough error context for triage in Mixpanel
|
|
22
|
+
* without leaking PII / wallet addresses / RPC endpoints / large numeric
|
|
23
|
+
* quantities, across any chain the SDK might route to.
|
|
24
|
+
*
|
|
25
|
+
* Order matters. URLs are stripped early so address-shaped path segments
|
|
26
|
+
* inside URLs aren't re-mangled by later passes. Specific patterns run
|
|
27
|
+
* before broad ones (e.g. EVM `0x{40}` before the generic long-hex pass)
|
|
28
|
+
* so the longer / more specific match wins. Bech32 runs before generic
|
|
29
|
+
* Base58 because the two alphabets partially overlap — Bech32 includes
|
|
30
|
+
* `0` (which Base58 excludes) and Base58 includes `o`/`i`/`b`/`l` (which
|
|
31
|
+
* Bech32 excludes) — so running Base58 first can chop off the tail of an
|
|
32
|
+
* HRP-prefixed Bech32 address at the first `l`/`i`/`o`/`b` and leave the
|
|
33
|
+
* suffix unscrubbed. Decimal-number scrubbing runs last so it doesn't
|
|
34
|
+
* fragment hex / Base58 tokens that contain digit runs.
|
|
35
|
+
*/
|
|
36
|
+
const SANITISE_PATTERNS = [
|
|
37
|
+
// EVM-style 20-byte hex addresses (e.g. `0x` + 40 hex chars).
|
|
38
|
+
{ pattern: /0x[a-fA-F0-9]{40}/gu, replacement: '<addr>' },
|
|
39
|
+
// Other long hex blobs: tx hashes, signatures, raw byte strings, large
|
|
40
|
+
// hex amounts. 16+ hex chars catches 32-byte hashes/signatures without
|
|
41
|
+
// snagging EVM method selectors (8 chars) or short hex codes.
|
|
42
|
+
{ pattern: /(?:0x)?[a-fA-F0-9]{16,}/gu, replacement: '<hex>' },
|
|
43
|
+
// URLs of any scheme up to the first whitespace / quote / closing paren.
|
|
44
|
+
// Catches RPC endpoints, dapp deeplinks, query strings with secrets.
|
|
45
|
+
{ pattern: /https?:\/\/[^\s"')]+/gu, replacement: '<url>' },
|
|
46
|
+
// Bech32 addresses: short HRP (1-10 lowercase chars) + `1` separator +
|
|
47
|
+
// ≥38 chars of Bech32 data alphabet `[ac-hj-np-z02-9]` (excludes the
|
|
48
|
+
// look-alike chars `b`, `i`, `o`, `1`). Covers Bitcoin SegWit
|
|
49
|
+
// (`bc1…`/`tb1…`) and Cosmos-SDK chains (`cosmos1…`, `osmo1…`,
|
|
50
|
+
// `juno1…`, `inj1…`, etc.) without enumerating every HRP. Runs before
|
|
51
|
+
// the Base58 pattern below — see header comment for why.
|
|
52
|
+
{
|
|
53
|
+
pattern: /\b[a-z]{1,10}1[ac-hj-np-z02-9]{38,}\b/gu,
|
|
54
|
+
replacement: '<addr>',
|
|
55
|
+
},
|
|
56
|
+
// Base58 tokens (32+ chars, Base58 alphabet `[1-9A-HJ-NP-Za-km-z]`).
|
|
57
|
+
// Covers Solana pubkeys (32-44 chars), Solana tx signatures (~88 chars),
|
|
58
|
+
// and Bitcoin Base58 addresses ≥32 chars. The 32-char floor and `\b`
|
|
59
|
+
// word boundary keep English words and shorter alphanumerics safe.
|
|
60
|
+
{
|
|
61
|
+
pattern: /\b[1-9A-HJ-NP-Za-km-z]{32,}\b/gu,
|
|
62
|
+
replacement: '<addr>',
|
|
63
|
+
},
|
|
64
|
+
// Long decimal numbers — token amounts, gas units, timestamps, lamports.
|
|
65
|
+
// 10+ digits catches typical chain quantities without affecting JSON-RPC
|
|
66
|
+
// codes (-32601, 4001, etc.) or short numeric IDs.
|
|
67
|
+
{ pattern: /\d{10,}/gu, replacement: '<num>' },
|
|
68
|
+
];
|
|
69
|
+
/**
|
|
70
|
+
* Sanitises an error message for inclusion in analytics. Strips wallet
|
|
71
|
+
* addresses (EVM hex, Solana / Bitcoin Base58, Bech32), long hex blobs,
|
|
72
|
+
* URLs, and large decimal numbers, then truncates to
|
|
73
|
+
* {@link ERROR_MESSAGE_SAMPLE_MAX_LENGTH} characters. Returns `undefined`
|
|
74
|
+
* if there's no message to sample.
|
|
75
|
+
*
|
|
76
|
+
* @param message - Raw error message
|
|
77
|
+
* @returns A safe-to-emit short string, or `undefined`
|
|
78
|
+
*/
|
|
79
|
+
export function sanitiseErrorMessage(message) {
|
|
80
|
+
if (!message) {
|
|
81
|
+
return undefined;
|
|
82
|
+
}
|
|
83
|
+
let sanitised = message;
|
|
84
|
+
for (const { pattern, replacement } of SANITISE_PATTERNS) {
|
|
85
|
+
sanitised = sanitised.replace(pattern, replacement);
|
|
86
|
+
}
|
|
87
|
+
if (sanitised.length > ERROR_MESSAGE_SAMPLE_MAX_LENGTH) {
|
|
88
|
+
// Trim and mark as truncated so consumers can tell vs. naturally short
|
|
89
|
+
// messages. The trailing ellipsis fits inside the maxLength budget.
|
|
90
|
+
sanitised = `${sanitised.slice(0, ERROR_MESSAGE_SAMPLE_MAX_LENGTH - 1)}…`;
|
|
91
|
+
}
|
|
92
|
+
return sanitised;
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* Pulls the most informative `code` / `message` pair out of an error,
|
|
96
|
+
* unwrapping `RPCInvokeMethodErr` so the wallet-side code (e.g. 4001) is
|
|
97
|
+
* visible to classifiers instead of being hidden behind the SDK's static
|
|
98
|
+
* `code: 53`. Falls back to the outer error if there is no inner wallet code.
|
|
99
|
+
*
|
|
100
|
+
* @param error - The error object to inspect
|
|
101
|
+
* @returns The most relevant `{ code, message }` pair we can extract
|
|
102
|
+
*/
|
|
103
|
+
function getUnwrappedErrorDetails(error) {
|
|
104
|
+
var _a, _b, _c, _d;
|
|
105
|
+
if (typeof error !== 'object' || error === null) {
|
|
106
|
+
return { code: undefined, message: '' };
|
|
107
|
+
}
|
|
108
|
+
if (error instanceof RPCInvokeMethodErr) {
|
|
109
|
+
return {
|
|
110
|
+
code: (_a = error.rpcCode) !== null && _a !== void 0 ? _a : error.code,
|
|
111
|
+
message: (_c = (_b = error.rpcMessage) !== null && _b !== void 0 ? _b : error.message) !== null && _c !== void 0 ? _c : '',
|
|
112
|
+
};
|
|
113
|
+
}
|
|
114
|
+
const errorObj = error;
|
|
115
|
+
return {
|
|
116
|
+
code: errorObj.code,
|
|
117
|
+
message: (_d = errorObj.message) !== null && _d !== void 0 ? _d : '',
|
|
118
|
+
};
|
|
119
|
+
}
|
|
14
120
|
/**
|
|
15
121
|
* Checks if an error represents a user rejection.
|
|
16
122
|
*
|
|
123
|
+
* Unwraps `RPCInvokeMethodErr` so the wallet's `code: 4001` survives the
|
|
124
|
+
* SDK's transport-boundary wrapping (the outer error otherwise reports
|
|
125
|
+
* `code: 53`, which would never match the heuristics here).
|
|
126
|
+
*
|
|
17
127
|
* @param error - The error object to check
|
|
18
128
|
* @returns True if the error indicates a user rejection, false otherwise
|
|
19
129
|
*/
|
|
20
130
|
export function isRejectionError(error) {
|
|
21
|
-
var _a, _b;
|
|
22
131
|
if (typeof error !== 'object' || error === null) {
|
|
23
132
|
return false;
|
|
24
133
|
}
|
|
25
|
-
const
|
|
26
|
-
const
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
134
|
+
const { code, message } = getUnwrappedErrorDetails(error);
|
|
135
|
+
const errorMessage = message.toLowerCase();
|
|
136
|
+
// EIP-1193 4001 "User Rejected Request" is the canonical rejection code.
|
|
137
|
+
// Note: 4100 "Unauthorized" is deliberately NOT matched here. On multichain
|
|
138
|
+
// sessions it's what the CAIP-25 permission layer returns when a method
|
|
139
|
+
// isn't in the granted scope (the layer rejects it before the method
|
|
140
|
+
// handler runs). That's a permission/support signal, not a user-driven
|
|
141
|
+
// rejection — misclassifying it as `_rejected` hides genuine permission
|
|
142
|
+
// issues from `_failed`.
|
|
143
|
+
return (code === 4001 ||
|
|
30
144
|
errorMessage.includes('reject') ||
|
|
31
145
|
errorMessage.includes('denied') ||
|
|
32
146
|
errorMessage.includes('cancel') ||
|
|
33
|
-
|
|
147
|
+
// Narrow "user …" matches — bare "user" is too greedy (catches Account
|
|
148
|
+
// Abstraction errors like "user operation reverted").
|
|
149
|
+
errorMessage.includes('user rejected') ||
|
|
150
|
+
errorMessage.includes('user denied') ||
|
|
151
|
+
errorMessage.includes('user cancelled') ||
|
|
152
|
+
errorMessage.includes('user canceled'));
|
|
153
|
+
}
|
|
154
|
+
/**
|
|
155
|
+
* Classifies a failed wallet action / connection error into a short tag for
|
|
156
|
+
* the `failure_reason` analytics property. Caller is expected to have already
|
|
157
|
+
* established that the error is *not* a user rejection (use `isRejectionError`
|
|
158
|
+
* for that branching).
|
|
159
|
+
*
|
|
160
|
+
* The taxonomy is deliberately producer-side-only — the schema accepts any
|
|
161
|
+
* string — so we can add buckets here without an API migration. Once the
|
|
162
|
+
* distribution stabilises we may convert the schema field to a closed enum.
|
|
163
|
+
*
|
|
164
|
+
* @param error - The error to classify
|
|
165
|
+
* @returns A short, snake_case tag describing why the operation failed
|
|
166
|
+
*/
|
|
167
|
+
export function classifyFailureReason(error) {
|
|
168
|
+
var _a, _b;
|
|
169
|
+
if (typeof error !== 'object' || error === null) {
|
|
170
|
+
return 'unknown';
|
|
171
|
+
}
|
|
172
|
+
const errorObj = error;
|
|
173
|
+
const errorName = (_a = errorObj.name) !== null && _a !== void 0 ? _a : '';
|
|
174
|
+
const errorMessageRaw = (_b = errorObj.message) !== null && _b !== void 0 ? _b : '';
|
|
175
|
+
const errorMessage = errorMessageRaw.toLowerCase();
|
|
176
|
+
// Wallet-side JSON-RPC / EIP-1193 code is the strongest signal we have —
|
|
177
|
+
// check it before any message-substring heuristics so a wallet error like
|
|
178
|
+
// `{ code: 4900, message: 'Disconnected' }` doesn't get caught by the
|
|
179
|
+
// transport-disconnect text match below. Unwraps `RPCInvokeMethodErr` so
|
|
180
|
+
// the wallet's actual error code is visible.
|
|
181
|
+
const { code } = getUnwrappedErrorDetails(error);
|
|
182
|
+
if (typeof code === 'number') {
|
|
183
|
+
// JSON-RPC 2.0 + EIP-1474 standard codes.
|
|
184
|
+
if (code === -32601) {
|
|
185
|
+
return 'wallet_method_unsupported';
|
|
186
|
+
}
|
|
187
|
+
if (code === -32602) {
|
|
188
|
+
return 'wallet_invalid_params';
|
|
189
|
+
}
|
|
190
|
+
if (code === -32603) {
|
|
191
|
+
return 'wallet_internal_error';
|
|
192
|
+
}
|
|
193
|
+
// Standard JSON-RPC server error range.
|
|
194
|
+
if (code <= -32000 && code >= -32099) {
|
|
195
|
+
return 'wallet_internal_error';
|
|
196
|
+
}
|
|
197
|
+
// EIP-1193 named provider codes — handled individually. Codes in the
|
|
198
|
+
// 1000–4999 range that aren't matched here fall through to `unknown`.
|
|
199
|
+
if (code === 4100) {
|
|
200
|
+
// Unauthorized — most commonly fires when a method isn't in the
|
|
201
|
+
// CAIP-25 scope's granted methods list (the multichain permission
|
|
202
|
+
// layer rejects it before the method handler runs). Distinct from
|
|
203
|
+
// a user rejection (4001) and worth tracking separately.
|
|
204
|
+
return 'wallet_unauthorized';
|
|
205
|
+
}
|
|
206
|
+
if (code === 4200) {
|
|
207
|
+
// Unsupported method — wallet handler exists but explicitly refuses.
|
|
208
|
+
return 'wallet_method_unsupported';
|
|
209
|
+
}
|
|
210
|
+
if (code === 4902) {
|
|
211
|
+
// Unrecognized chain ID — `wallet_switchEthereumChain` to a chain the
|
|
212
|
+
// wallet hasn't been told about. MetaMask (extension + mobile) always
|
|
213
|
+
// sets code 4902 on this error, so we don't need a message-substring
|
|
214
|
+
// fallback below.
|
|
215
|
+
return 'unrecognized_chain';
|
|
216
|
+
}
|
|
217
|
+
// Anything else in the EIP-1193 / EIP-1474 provider-defined range
|
|
218
|
+
// (1000–4999) falls through to `unknown` — we can promote specific codes
|
|
219
|
+
// into their own buckets later as the distribution stabilises, without a
|
|
220
|
+
// schema migration. Two buckets for "we don't know what this is" adds
|
|
221
|
+
// noise without insight.
|
|
222
|
+
}
|
|
223
|
+
// Transport-layer errors. Two shapes exist:
|
|
224
|
+
// - `TransportTimeoutError` from `@metamask/multichain-api-client` (used by
|
|
225
|
+
// MWP and the warmup paths of the default extension transport). It's a
|
|
226
|
+
// subclass of `TransportError` so we match on the name field rather than
|
|
227
|
+
// importing the symbol (the type lives in a runtime dependency that the
|
|
228
|
+
// analytics utils shouldn't pull in directly).
|
|
229
|
+
// - A plain `new Error('Request timeout')` thrown by `DefaultTransport`'s
|
|
230
|
+
// own setTimeout. Indistinguishable from other errors without the message.
|
|
231
|
+
if (errorName === 'TransportTimeoutError' ||
|
|
232
|
+
errorMessageRaw === 'Request timeout' ||
|
|
233
|
+
errorMessage.includes('timed out') ||
|
|
234
|
+
errorMessage.includes('timeout')) {
|
|
235
|
+
return 'transport_timeout';
|
|
236
|
+
}
|
|
237
|
+
// Transport disconnect. Narrowed substring set so we don't snag wallet
|
|
238
|
+
// error messages that happen to contain "disconnect" (e.g. EIP-1193
|
|
239
|
+
// `4900 Disconnected`, which the wallet-code branch above already routed
|
|
240
|
+
// to `unknown` per policy).
|
|
241
|
+
if (errorName === 'TransportError' ||
|
|
242
|
+
errorMessage.includes('not connected') ||
|
|
243
|
+
errorMessage.includes('transport disconnect') ||
|
|
244
|
+
errorMessage.includes('connection lost') ||
|
|
245
|
+
errorMessage.includes('socket closed')) {
|
|
246
|
+
return 'transport_disconnect';
|
|
247
|
+
}
|
|
248
|
+
return 'unknown';
|
|
249
|
+
}
|
|
250
|
+
/**
|
|
251
|
+
* Computes the full set of diagnostic properties to attach to a
|
|
252
|
+
* `mmconnect_*_failed` event from a single error. Combines
|
|
253
|
+
* {@link classifyFailureReason}, the unwrapped wallet code, and a
|
|
254
|
+
* sanitised message sample so producer call sites stay a single line.
|
|
255
|
+
*
|
|
256
|
+
* @param error - The error to inspect
|
|
257
|
+
* @returns Diagnostics ready to spread into the event properties
|
|
258
|
+
*/
|
|
259
|
+
export function extractErrorDiagnostics(error) {
|
|
260
|
+
const failureReason = classifyFailureReason(error);
|
|
261
|
+
const { code, message } = getUnwrappedErrorDetails(error);
|
|
262
|
+
const messageSample = sanitiseErrorMessage(message);
|
|
263
|
+
return Object.assign(Object.assign({ failure_reason: failureReason }, (typeof code === 'number' ? { error_code: code } : {})), (messageSample ? { error_message_sample: messageSample } : {}));
|
|
34
264
|
}
|
|
35
265
|
/**
|
|
36
266
|
* Gets base analytics properties that are common across all events.
|
|
@@ -60,21 +290,26 @@ export function getBaseAnalyticsProperties(options, storage) {
|
|
|
60
290
|
* @param storage - Storage client for getting anonymous ID
|
|
61
291
|
* @param invokeOptions - The invoke method options containing method and scope
|
|
62
292
|
* @param transportType - The transport type to use for the analytics event
|
|
293
|
+
* @param extra - Optional event-specific diagnostic properties. Used by
|
|
294
|
+
* `mmconnect_wallet_action_failed` to attach the {@link ErrorDiagnostics}
|
|
295
|
+
* bundle (`failure_reason`, `error_code`, `error_message_sample`).
|
|
296
|
+
* @param extra.failure_reason - A short tag describing why the operation
|
|
297
|
+
* failed; see `classifyFailureReason` and the `FailureReason` union.
|
|
298
|
+
* @param extra.error_code - The raw wallet-side error code, if present.
|
|
299
|
+
* @param extra.error_message_sample - A sanitised, truncated sample of the
|
|
300
|
+
* original error message.
|
|
63
301
|
* @returns Wallet action analytics properties
|
|
64
302
|
*/
|
|
65
|
-
export function getWalletActionAnalyticsProperties(options, storage, invokeOptions, transportType) {
|
|
303
|
+
export function getWalletActionAnalyticsProperties(options, storage, invokeOptions, transportType, extra) {
|
|
66
304
|
return __awaiter(this, void 0, void 0, function* () {
|
|
67
305
|
var _a;
|
|
68
306
|
const dappId = getDappId(options.dapp);
|
|
69
307
|
const anonId = yield storage.getAnonId();
|
|
70
|
-
return {
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
anon_id: anonId,
|
|
76
|
-
transport_type: transportType,
|
|
77
|
-
};
|
|
308
|
+
return Object.assign(Object.assign(Object.assign({ mmconnect_versions: (_a = options.versions) !== null && _a !== void 0 ? _a : {}, dapp_id: dappId, method: invokeOptions.request.method, caip_chain_id: invokeOptions.scope, anon_id: anonId, transport_type: transportType }, ((extra === null || extra === void 0 ? void 0 : extra.failure_reason) ? { failure_reason: extra.failure_reason } : {})), (typeof (extra === null || extra === void 0 ? void 0 : extra.error_code) === 'number'
|
|
309
|
+
? { error_code: extra.error_code }
|
|
310
|
+
: {})), ((extra === null || extra === void 0 ? void 0 : extra.error_message_sample)
|
|
311
|
+
? { error_message_sample: extra.error_message_sample }
|
|
312
|
+
: {}));
|
|
78
313
|
});
|
|
79
314
|
}
|
|
80
315
|
//# sourceMappingURL=analytics.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"analytics.js","sourceRoot":"","sources":["../../../../src/multichain/utils/analytics.ts"],"names":[],"mappings":";;;;;;;;;AAAA,yDAAyD;AACzD,kFAAkF;AAClF,OAAO,EAAE,SAAS,EAAE,MAAM,GAAG,CAAC;AAS9B,OAAO,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;
|
|
1
|
+
{"version":3,"file":"analytics.js","sourceRoot":"","sources":["../../../../src/multichain/utils/analytics.ts"],"names":[],"mappings":";;;;;;;;;AAAA,yDAAyD;AACzD,kFAAkF;AAClF,OAAO,EAAE,SAAS,EAAE,MAAM,GAAG,CAAC;AAS9B,OAAO,EAAE,eAAe,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC;AAsBnE;;;GAGG;AACH,MAAM,+BAA+B,GAAG,GAAG,CAAC;AAE5C;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,iBAAiB,GAA+C;IACpE,8DAA8D;IAC9D,EAAE,OAAO,EAAE,qBAAqB,EAAE,WAAW,EAAE,QAAQ,EAAE;IACzD,uEAAuE;IACvE,uEAAuE;IACvE,8DAA8D;IAC9D,EAAE,OAAO,EAAE,2BAA2B,EAAE,WAAW,EAAE,OAAO,EAAE;IAC9D,yEAAyE;IACzE,qEAAqE;IACrE,EAAE,OAAO,EAAE,wBAAwB,EAAE,WAAW,EAAE,OAAO,EAAE;IAC3D,uEAAuE;IACvE,qEAAqE;IACrE,8DAA8D;IAC9D,+DAA+D;IAC/D,sEAAsE;IACtE,yDAAyD;IACzD;QACE,OAAO,EAAE,yCAAyC;QAClD,WAAW,EAAE,QAAQ;KACtB;IACD,qEAAqE;IACrE,yEAAyE;IACzE,qEAAqE;IACrE,mEAAmE;IACnE;QACE,OAAO,EAAE,iCAAiC;QAC1C,WAAW,EAAE,QAAQ;KACtB;IACD,yEAAyE;IACzE,yEAAyE;IACzE,mDAAmD;IACnD,EAAE,OAAO,EAAE,WAAW,EAAE,WAAW,EAAE,OAAO,EAAE;CAC/C,CAAC;AAEF;;;;;;;;;GASG;AACH,MAAM,UAAU,oBAAoB,CAClC,OAA2B;IAE3B,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,OAAO,SAAS,CAAC;IACnB,CAAC;IACD,IAAI,SAAS,GAAG,OAAO,CAAC;IACxB,KAAK,MAAM,EAAE,OAAO,EAAE,WAAW,EAAE,IAAI,iBAAiB,EAAE,CAAC;QACzD,SAAS,GAAG,SAAS,CAAC,OAAO,CAAC,OAAO,EAAE,WAAW,CAAC,CAAC;IACtD,CAAC;IACD,IAAI,SAAS,CAAC,MAAM,GAAG,+BAA+B,EAAE,CAAC;QACvD,uEAAuE;QACvE,oEAAoE;QACpE,SAAS,GAAG,GAAG,SAAS,CAAC,KAAK,CAAC,CAAC,EAAE,+BAA+B,GAAG,CAAC,CAAC,GAAG,CAAC;IAC5E,CAAC;IACD,OAAO,SAAS,CAAC;AACnB,CAAC;AAED;;;;;;;;GAQG;AACH,SAAS,wBAAwB,CAAC,KAAc;;IAI9C,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,EAAE,CAAC;QAChD,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,EAAE,EAAE,CAAC;IAC1C,CAAC;IAED,IAAI,KAAK,YAAY,kBAAkB,EAAE,CAAC;QACxC,OAAO;YACL,IAAI,EAAE,MAAA,KAAK,CAAC,OAAO,mCAAI,KAAK,CAAC,IAAI;YACjC,OAAO,EAAE,MAAA,MAAA,KAAK,CAAC,UAAU,mCAAI,KAAK,CAAC,OAAO,mCAAI,EAAE;SACjD,CAAC;IACJ,CAAC;IAED,MAAM,QAAQ,GAAG,KAA4C,CAAC;IAC9D,OAAO;QACL,IAAI,EAAE,QAAQ,CAAC,IAAI;QACnB,OAAO,EAAE,MAAA,QAAQ,CAAC,OAAO,mCAAI,EAAE;KAChC,CAAC;AACJ,CAAC;AAED;;;;;;;;;GASG;AACH,MAAM,UAAU,gBAAgB,CAAC,KAAc;IAC7C,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,EAAE,CAAC;QAChD,OAAO,KAAK,CAAC;IACf,CAAC;IAED,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,GAAG,wBAAwB,CAAC,KAAK,CAAC,CAAC;IAC1D,MAAM,YAAY,GAAG,OAAO,CAAC,WAAW,EAAE,CAAC;IAE3C,yEAAyE;IACzE,4EAA4E;IAC5E,wEAAwE;IACxE,qEAAqE;IACrE,uEAAuE;IACvE,wEAAwE;IACxE,yBAAyB;IACzB,OAAO,CACL,IAAI,KAAK,IAAI;QACb,YAAY,CAAC,QAAQ,CAAC,QAAQ,CAAC;QAC/B,YAAY,CAAC,QAAQ,CAAC,QAAQ,CAAC;QAC/B,YAAY,CAAC,QAAQ,CAAC,QAAQ,CAAC;QAC/B,uEAAuE;QACvE,sDAAsD;QACtD,YAAY,CAAC,QAAQ,CAAC,eAAe,CAAC;QACtC,YAAY,CAAC,QAAQ,CAAC,aAAa,CAAC;QACpC,YAAY,CAAC,QAAQ,CAAC,gBAAgB,CAAC;QACvC,YAAY,CAAC,QAAQ,CAAC,eAAe,CAAC,CACvC,CAAC;AACJ,CAAC;AAED;;;;;;;;;;;;GAYG;AACH,MAAM,UAAU,qBAAqB,CAAC,KAAc;;IAClD,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,EAAE,CAAC;QAChD,OAAO,SAAS,CAAC;IACnB,CAAC;IAED,MAAM,QAAQ,GAAG,KAA4C,CAAC;IAC9D,MAAM,SAAS,GAAG,MAAA,QAAQ,CAAC,IAAI,mCAAI,EAAE,CAAC;IACtC,MAAM,eAAe,GAAG,MAAA,QAAQ,CAAC,OAAO,mCAAI,EAAE,CAAC;IAC/C,MAAM,YAAY,GAAG,eAAe,CAAC,WAAW,EAAE,CAAC;IAEnD,yEAAyE;IACzE,0EAA0E;IAC1E,sEAAsE;IACtE,yEAAyE;IACzE,6CAA6C;IAC7C,MAAM,EAAE,IAAI,EAAE,GAAG,wBAAwB,CAAC,KAAK,CAAC,CAAC;IACjD,IAAI,OAAO,IAAI,KAAK,QAAQ,EAAE,CAAC;QAC7B,0CAA0C;QAC1C,IAAI,IAAI,KAAK,CAAC,KAAK,EAAE,CAAC;YACpB,OAAO,2BAA2B,CAAC;QACrC,CAAC;QACD,IAAI,IAAI,KAAK,CAAC,KAAK,EAAE,CAAC;YACpB,OAAO,uBAAuB,CAAC;QACjC,CAAC;QACD,IAAI,IAAI,KAAK,CAAC,KAAK,EAAE,CAAC;YACpB,OAAO,uBAAuB,CAAC;QACjC,CAAC;QACD,wCAAwC;QACxC,IAAI,IAAI,IAAI,CAAC,KAAK,IAAI,IAAI,IAAI,CAAC,KAAK,EAAE,CAAC;YACrC,OAAO,uBAAuB,CAAC;QACjC,CAAC;QACD,qEAAqE;QACrE,sEAAsE;QACtE,IAAI,IAAI,KAAK,IAAI,EAAE,CAAC;YAClB,gEAAgE;YAChE,kEAAkE;YAClE,kEAAkE;YAClE,yDAAyD;YACzD,OAAO,qBAAqB,CAAC;QAC/B,CAAC;QACD,IAAI,IAAI,KAAK,IAAI,EAAE,CAAC;YAClB,qEAAqE;YACrE,OAAO,2BAA2B,CAAC;QACrC,CAAC;QACD,IAAI,IAAI,KAAK,IAAI,EAAE,CAAC;YAClB,sEAAsE;YACtE,sEAAsE;YACtE,qEAAqE;YACrE,kBAAkB;YAClB,OAAO,oBAAoB,CAAC;QAC9B,CAAC;QACD,kEAAkE;QAClE,yEAAyE;QACzE,yEAAyE;QACzE,sEAAsE;QACtE,yBAAyB;IAC3B,CAAC;IAED,4CAA4C;IAC5C,4EAA4E;IAC5E,yEAAyE;IACzE,2EAA2E;IAC3E,0EAA0E;IAC1E,iDAAiD;IACjD,0EAA0E;IAC1E,6EAA6E;IAC7E,IACE,SAAS,KAAK,uBAAuB;QACrC,eAAe,KAAK,iBAAiB;QACrC,YAAY,CAAC,QAAQ,CAAC,WAAW,CAAC;QAClC,YAAY,CAAC,QAAQ,CAAC,SAAS,CAAC,EAChC,CAAC;QACD,OAAO,mBAAmB,CAAC;IAC7B,CAAC;IACD,uEAAuE;IACvE,oEAAoE;IACpE,yEAAyE;IACzE,4BAA4B;IAC5B,IACE,SAAS,KAAK,gBAAgB;QAC9B,YAAY,CAAC,QAAQ,CAAC,eAAe,CAAC;QACtC,YAAY,CAAC,QAAQ,CAAC,sBAAsB,CAAC;QAC7C,YAAY,CAAC,QAAQ,CAAC,iBAAiB,CAAC;QACxC,YAAY,CAAC,QAAQ,CAAC,eAAe,CAAC,EACtC,CAAC;QACD,OAAO,sBAAsB,CAAC;IAChC,CAAC;IAED,OAAO,SAAS,CAAC;AACnB,CAAC;AAmBD;;;;;;;;GAQG;AACH,MAAM,UAAU,uBAAuB,CAAC,KAAc;IACpD,MAAM,aAAa,GAAG,qBAAqB,CAAC,KAAK,CAAC,CAAC;IACnD,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,GAAG,wBAAwB,CAAC,KAAK,CAAC,CAAC;IAC1D,MAAM,aAAa,GAAG,oBAAoB,CAAC,OAAO,CAAC,CAAC;IACpD,qCACE,cAAc,EAAE,aAAa,IAC1B,CAAC,OAAO,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,EAAE,UAAU,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,GACtD,CAAC,aAAa,CAAC,CAAC,CAAC,EAAE,oBAAoB,EAAE,aAAa,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,EACjE;AACJ,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAgB,0BAA0B,CAC9C,OAA0B,EAC1B,OAAoB;;;QAOpB,MAAM,MAAM,GAAG,SAAS,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;QACvC,MAAM,QAAQ,GAAG,eAAe,EAAE,CAAC;QACnC,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,SAAS,EAAE,CAAC;QAEzC,OAAO;YACL,kBAAkB,EAAE,MAAA,OAAO,CAAC,QAAQ,mCAAI,EAAE;YAC1C,OAAO,EAAE,MAAM;YACf,QAAQ;YACR,OAAO,EAAE,MAAM;SAChB,CAAC;IACJ,CAAC;CAAA;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,UAAgB,kCAAkC,CACtD,OAA0B,EAC1B,OAAoB,EACpB,aAAkC,EAClC,aAA4B,EAC5B,KAIC;;;QAYD,MAAM,MAAM,GAAG,SAAS,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;QACvC,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,SAAS,EAAE,CAAC;QAEzC,mDACE,kBAAkB,EAAE,MAAA,OAAO,CAAC,QAAQ,mCAAI,EAAE,EAC1C,OAAO,EAAE,MAAM,EACf,MAAM,EAAE,aAAa,CAAC,OAAO,CAAC,MAAM,EACpC,aAAa,EAAE,aAAa,CAAC,KAAK,EAClC,OAAO,EAAE,MAAM,EACf,cAAc,EAAE,aAAa,IAC1B,CAAC,CAAA,KAAK,aAAL,KAAK,uBAAL,KAAK,CAAE,cAAc,EAAC,CAAC,CAAC,EAAE,cAAc,EAAE,KAAK,CAAC,cAAc,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,GACvE,CAAC,OAAO,CAAA,KAAK,aAAL,KAAK,uBAAL,KAAK,CAAE,UAAU,CAAA,KAAK,QAAQ;YACvC,CAAC,CAAC,EAAE,UAAU,EAAE,KAAK,CAAC,UAAU,EAAE;YAClC,CAAC,CAAC,EAAE,CAAC,GACJ,CAAC,CAAA,KAAK,aAAL,KAAK,uBAAL,KAAK,CAAE,oBAAoB;YAC7B,CAAC,CAAC,EAAE,oBAAoB,EAAE,KAAK,CAAC,oBAAoB,EAAE;YACtD,CAAC,CAAC,EAAE,CAAC,EACP;IACJ,CAAC;CAAA"}
|
|
@@ -679,13 +679,42 @@ declare abstract class Modal<Options, Data extends DataType = DataType> {
|
|
|
679
679
|
set data(data: Data);
|
|
680
680
|
}
|
|
681
681
|
|
|
682
|
+
/**
|
|
683
|
+
* Tag describing the cause of a failed wallet action / connection. Surfaced
|
|
684
|
+
* as the `failure_reason` property on `mmconnect_wallet_action_failed` and
|
|
685
|
+
* `mmconnect_connection_failed` events so we can distinguish e.g. a transport
|
|
686
|
+
* timeout from a wallet-side internal error in Mixpanel.
|
|
687
|
+
*
|
|
688
|
+
* Intentionally a string union (not a const enum) so callers stay free to
|
|
689
|
+
* pass through a new bucket; the schema-side property is an open string for
|
|
690
|
+
* the same reason.
|
|
691
|
+
*/
|
|
692
|
+
type FailureReason = 'transport_timeout' | 'transport_disconnect' | 'wallet_method_unsupported' | 'wallet_invalid_params' | 'wallet_internal_error' | 'wallet_unauthorized' | 'unrecognized_chain' | 'unknown';
|
|
682
693
|
/**
|
|
683
694
|
* Checks if an error represents a user rejection.
|
|
684
695
|
*
|
|
696
|
+
* Unwraps `RPCInvokeMethodErr` so the wallet's `code: 4001` survives the
|
|
697
|
+
* SDK's transport-boundary wrapping (the outer error otherwise reports
|
|
698
|
+
* `code: 53`, which would never match the heuristics here).
|
|
699
|
+
*
|
|
685
700
|
* @param error - The error object to check
|
|
686
701
|
* @returns True if the error indicates a user rejection, false otherwise
|
|
687
702
|
*/
|
|
688
703
|
declare function isRejectionError(error: unknown): boolean;
|
|
704
|
+
/**
|
|
705
|
+
* Classifies a failed wallet action / connection error into a short tag for
|
|
706
|
+
* the `failure_reason` analytics property. Caller is expected to have already
|
|
707
|
+
* established that the error is *not* a user rejection (use `isRejectionError`
|
|
708
|
+
* for that branching).
|
|
709
|
+
*
|
|
710
|
+
* The taxonomy is deliberately producer-side-only — the schema accepts any
|
|
711
|
+
* string — so we can add buckets here without an API migration. Once the
|
|
712
|
+
* distribution stabilises we may convert the schema field to a closed enum.
|
|
713
|
+
*
|
|
714
|
+
* @param error - The error to classify
|
|
715
|
+
* @returns A short, snake_case tag describing why the operation failed
|
|
716
|
+
*/
|
|
717
|
+
declare function classifyFailureReason(error: unknown): FailureReason;
|
|
689
718
|
/**
|
|
690
719
|
* Gets analytics properties specific to wallet action events.
|
|
691
720
|
*
|
|
@@ -693,15 +722,30 @@ declare function isRejectionError(error: unknown): boolean;
|
|
|
693
722
|
* @param storage - Storage client for getting anonymous ID
|
|
694
723
|
* @param invokeOptions - The invoke method options containing method and scope
|
|
695
724
|
* @param transportType - The transport type to use for the analytics event
|
|
725
|
+
* @param extra - Optional event-specific diagnostic properties. Used by
|
|
726
|
+
* `mmconnect_wallet_action_failed` to attach the {@link ErrorDiagnostics}
|
|
727
|
+
* bundle (`failure_reason`, `error_code`, `error_message_sample`).
|
|
728
|
+
* @param extra.failure_reason - A short tag describing why the operation
|
|
729
|
+
* failed; see `classifyFailureReason` and the `FailureReason` union.
|
|
730
|
+
* @param extra.error_code - The raw wallet-side error code, if present.
|
|
731
|
+
* @param extra.error_message_sample - A sanitised, truncated sample of the
|
|
732
|
+
* original error message.
|
|
696
733
|
* @returns Wallet action analytics properties
|
|
697
734
|
*/
|
|
698
|
-
declare function getWalletActionAnalyticsProperties(options: MultichainOptions, storage: StoreClient, invokeOptions: InvokeMethodOptions, transportType: TransportType
|
|
735
|
+
declare function getWalletActionAnalyticsProperties(options: MultichainOptions, storage: StoreClient, invokeOptions: InvokeMethodOptions, transportType: TransportType, extra?: {
|
|
736
|
+
failure_reason?: FailureReason;
|
|
737
|
+
error_code?: number;
|
|
738
|
+
error_message_sample?: string;
|
|
739
|
+
}): Promise<{
|
|
699
740
|
mmconnect_versions: Record<string, string>;
|
|
700
741
|
dapp_id: string;
|
|
701
742
|
method: string;
|
|
702
743
|
caip_chain_id: string;
|
|
703
744
|
anon_id: string;
|
|
704
745
|
transport_type: TransportType;
|
|
746
|
+
failure_reason?: FailureReason;
|
|
747
|
+
error_code?: number;
|
|
748
|
+
error_message_sample?: string;
|
|
705
749
|
}>;
|
|
706
750
|
|
|
707
751
|
/**
|
|
@@ -713,4 +757,4 @@ declare function getVersion(): string;
|
|
|
713
757
|
|
|
714
758
|
declare const createMultichainClient: CreateMultichainFN;
|
|
715
759
|
|
|
716
|
-
export { type ConnectVersions, type ConnectionRequest, type ConnectionStatus, type CreateMultichainFN, type DappSettings, type DataType, type DomainErrorCodes, type Enumerate, type ErrorCodeRange, type ErrorCodes, EventEmitter, type EventTypes, type ExtendedTransport, type InstallWidgetProps, type InvokeMethodOptions, type LoggerNameSpaces, type MergeableMultichainOptions, Modal, type ModalFactoryConnectOptions, type ModalFactoryOptions, MultichainCore, type MultichainOptions, type NotificationCallback, type OTPCode, type OTPCodeWidgetProps, PlatformType, type QRLink, type RPCAPI, type RPCErrorCodes, RPCHttpErr, RPCInvokeMethodErr, RPCReadonlyRequestErr, RPCReadonlyResponseErr, type RPCResponse, RPC_HANDLED_METHODS, type RpcMethod, type RpcUrlsMap, type SDKEvents, SDK_HANDLED_METHODS, type Scope, type StorageErrorCodes, StoreAdapter, StoreClient, type StoreOptions, TransportType, createLogger, createMultichainClient, enableDebug, getInfuraRpcUrls, getPlatformType, getTransportType, getVersion, getWalletActionAnalyticsProperties, hasExtension, infuraRpcUrls, isEnabled, isMetamaskExtensionInstalled, isRejectionError, isSecure };
|
|
760
|
+
export { type ConnectVersions, type ConnectionRequest, type ConnectionStatus, type CreateMultichainFN, type DappSettings, type DataType, type DomainErrorCodes, type Enumerate, type ErrorCodeRange, type ErrorCodes, EventEmitter, type EventTypes, type ExtendedTransport, type FailureReason, type InstallWidgetProps, type InvokeMethodOptions, type LoggerNameSpaces, type MergeableMultichainOptions, Modal, type ModalFactoryConnectOptions, type ModalFactoryOptions, MultichainCore, type MultichainOptions, type NotificationCallback, type OTPCode, type OTPCodeWidgetProps, PlatformType, type QRLink, type RPCAPI, type RPCErrorCodes, RPCHttpErr, RPCInvokeMethodErr, RPCReadonlyRequestErr, RPCReadonlyResponseErr, type RPCResponse, RPC_HANDLED_METHODS, type RpcMethod, type RpcUrlsMap, type SDKEvents, SDK_HANDLED_METHODS, type Scope, type StorageErrorCodes, StoreAdapter, StoreClient, type StoreOptions, TransportType, classifyFailureReason, createLogger, createMultichainClient, enableDebug, getInfuraRpcUrls, getPlatformType, getTransportType, getVersion, getWalletActionAnalyticsProperties, hasExtension, infuraRpcUrls, isEnabled, isMetamaskExtensionInstalled, isRejectionError, isSecure };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@metamask/connect-multichain",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.14.0",
|
|
4
4
|
"description": "Multichain package for MetaMask Connect",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"MetaMask",
|
|
@@ -68,7 +68,7 @@
|
|
|
68
68
|
"test:watch": "vitest watch"
|
|
69
69
|
},
|
|
70
70
|
"dependencies": {
|
|
71
|
-
"@metamask/analytics": "^0.
|
|
71
|
+
"@metamask/analytics": "^0.5.0",
|
|
72
72
|
"@metamask/mobile-wallet-protocol-core": "^0.4.0",
|
|
73
73
|
"@metamask/mobile-wallet-protocol-dapp-client": "^0.3.0",
|
|
74
74
|
"@metamask/multichain-api-client": "^0.10.1",
|