@metamask-previews/snap-networks-utils 3.0.0-preview-a589290 → 3.0.0-preview-de60dd1

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 (34) hide show
  1. package/CHANGELOG.md +9 -0
  2. package/dist/clients/security-alerts-api/SecurityAlertsApiClient.d.mts +50 -0
  3. package/dist/clients/security-alerts-api/SecurityAlertsApiClient.d.mts.map +1 -0
  4. package/dist/clients/security-alerts-api/SecurityAlertsApiClient.mjs +70 -0
  5. package/dist/clients/security-alerts-api/SecurityAlertsApiClient.mjs.map +1 -0
  6. package/dist/index.d.mts +9 -1
  7. package/dist/index.d.mts.map +1 -1
  8. package/dist/index.mjs +6 -1
  9. package/dist/index.mjs.map +1 -1
  10. package/dist/services/security-alerts/BaseTransactionScanService.d.mts +60 -0
  11. package/dist/services/security-alerts/BaseTransactionScanService.d.mts.map +1 -0
  12. package/dist/services/security-alerts/BaseTransactionScanService.mjs +87 -0
  13. package/dist/services/security-alerts/BaseTransactionScanService.mjs.map +1 -0
  14. package/dist/services/security-alerts/types.d.mts +65 -0
  15. package/dist/services/security-alerts/types.d.mts.map +1 -0
  16. package/dist/services/security-alerts/types.mjs +28 -0
  17. package/dist/services/security-alerts/types.mjs.map +1 -0
  18. package/dist/services/security-alerts/utils.d.mts +18 -0
  19. package/dist/services/security-alerts/utils.d.mts.map +1 -0
  20. package/dist/services/security-alerts/utils.mjs +50 -0
  21. package/dist/services/security-alerts/utils.mjs.map +1 -0
  22. package/dist/utils/errors/httpError.d.mts +20 -0
  23. package/dist/utils/errors/httpError.d.mts.map +1 -0
  24. package/dist/utils/errors/httpError.mjs +23 -0
  25. package/dist/utils/errors/httpError.mjs.map +1 -0
  26. package/dist/utils/errors/index.d.mts +1 -0
  27. package/dist/utils/errors/index.d.mts.map +1 -1
  28. package/dist/utils/errors/index.mjs +1 -0
  29. package/dist/utils/errors/index.mjs.map +1 -1
  30. package/dist/utils/fetchPolicy/executeWithFetchPolicy.d.mts +60 -0
  31. package/dist/utils/fetchPolicy/executeWithFetchPolicy.d.mts.map +1 -0
  32. package/dist/utils/fetchPolicy/executeWithFetchPolicy.mjs +182 -0
  33. package/dist/utils/fetchPolicy/executeWithFetchPolicy.mjs.map +1 -0
  34. package/package.json +1 -1
package/CHANGELOG.md CHANGED
@@ -7,6 +7,15 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ### Added
11
+
12
+ - Add `executeWithFetchPolicy` for wrapping transport-only operations in a policy created by `createFetchPolicy`, passing `SyntaxError` and abort errors through unchanged, passing errors already in the policy shape through unchanged, and mapping any other error with an optional mapper (defaulting to a network failure) ([#478](https://github.com/MetaMask/internal-snaps/pull/478))
13
+ - Add `fetchWithPolicy` for the common policy-wrapped HTTP call: a fetch with a 10 second timeout, a status check that throws a `FetchPolicyError` for non-2xx responses (honouring `Retry-After`), and a body read inside the policy ([#478](https://github.com/MetaMask/internal-snaps/pull/478))
14
+ - Add `parseRetryAfter` for parsing a `Retry-After` header value as milliseconds ([#478](https://github.com/MetaMask/internal-snaps/pull/478))
15
+ - Add the `FetchPolicy` type, the minimal policy surface `executeWithFetchPolicy` and `fetchWithPolicy` accept ([#478](https://github.com/MetaMask/internal-snaps/pull/478))
16
+ - Add the shared `BaseTransactionScanService` base class for network snap transaction scan services, owning the shared scan dependencies (Security Alerts API client, analytics, logger, error reporting) and the scan analytics orchestration ([#397](https://github.com/MetaMask/internal-snaps/pull/397))
17
+ - Add the shared Security Alerts API HTTP client for `BaseTransactionScanService`.
18
+
10
19
  ## [3.0.0]
11
20
 
12
21
  ### Added
@@ -0,0 +1,50 @@
1
+ /**
2
+ * Headers sent with every Security Alerts API request.
3
+ */
4
+ export declare const SECURITY_ALERTS_REQUEST_HEADERS: Record<string, string>;
5
+ /**
6
+ * Options for a `SecurityAlertsApiClient` constructor.
7
+ */
8
+ export type SecurityAlertsApiClientOptions = {
9
+ /**
10
+ * The full scan endpoint URL, e.g. `https://security-alerts.api.cx.metamask.io/tron/transaction/scan`.
11
+ */
12
+ scanUrl: string;
13
+ /** The fetch implementation to use. Defaults to `globalThis.fetch`. */
14
+ fetch?: typeof globalThis.fetch;
15
+ };
16
+ /**
17
+ * HTTP client for a Security Alerts API scan endpoint.
18
+ *
19
+ * Owns the request envelope shared by every chain — POSTing the JSON body,
20
+ * wrapping request failures, non-2xx responses, and malformed JSON bodies as
21
+ * {@link HttpError}, and parsing the JSON response — and nothing
22
+ * else.
23
+ *
24
+ * The request body is a chain-specific Blockaid contract: the caller
25
+ * supplies a typed body (e.g. checked with `satisfies` against a per-snap
26
+ * body type) and is responsible for validating the parsed response payload.
27
+ */
28
+ export declare class SecurityAlertsApiClient {
29
+ #private;
30
+ /**
31
+ * Creates a new SecurityAlertsApiClient.
32
+ *
33
+ * @param options - The client options.
34
+ * @param options.scanUrl - The full scan endpoint URL. Validated once, so
35
+ * an invalid URL fails fast at construction.
36
+ * @param options.fetch - Optional fetch implementation; defaults to
37
+ * `globalThis.fetch`.
38
+ */
39
+ constructor({ scanUrl, fetch: fetchFn, }: SecurityAlertsApiClientOptions);
40
+ /**
41
+ * Scans a transaction by posting the request body to the scan endpoint.
42
+ *
43
+ * @param body - The chain-specific scan request body.
44
+ * @returns The parsed scan response.
45
+ * @throws HttpError if the request fails, the API responds
46
+ * with a non-2xx status, or the response body cannot be parsed as JSON.
47
+ */
48
+ scanTransaction(body: unknown): Promise<unknown>;
49
+ }
50
+ //# sourceMappingURL=SecurityAlertsApiClient.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SecurityAlertsApiClient.d.mts","sourceRoot":"","sources":["../../../src/clients/security-alerts-api/SecurityAlertsApiClient.ts"],"names":[],"mappings":"AAKA;;GAEG;AACH,eAAO,MAAM,+BAA+B,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAGlE,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,8BAA8B,GAAG;IAC3C;;OAEG;IACH,OAAO,EAAE,MAAM,CAAC;IAChB,uEAAuE;IACvE,KAAK,CAAC,EAAE,OAAO,UAAU,CAAC,KAAK,CAAC;CACjC,CAAC;AAEF;;;;;;;;;;;GAWG;AACH,qBAAa,uBAAuB;;IAKlC;;;;;;;;OAQG;gBACS,EACV,OAAO,EACP,KAAK,EAAE,OAA0B,GAClC,EAAE,8BAA8B;IAOjC;;;;;;;OAOG;IACG,eAAe,CAAC,IAAI,EAAE,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC;CAuBvD"}
@@ -0,0 +1,70 @@
1
+ import { assert } from "@metamask/superstruct";
2
+ import { HttpError } from "../../utils/errors/index.mjs";
3
+ import { UrlStruct } from "../../utils/urlStruct/urlStruct.mjs";
4
+ /**
5
+ * Headers sent with every Security Alerts API request.
6
+ */
7
+ export const SECURITY_ALERTS_REQUEST_HEADERS = {
8
+ 'Content-Type': 'application/json',
9
+ accept: 'application/json',
10
+ };
11
+ /**
12
+ * HTTP client for a Security Alerts API scan endpoint.
13
+ *
14
+ * Owns the request envelope shared by every chain — POSTing the JSON body,
15
+ * wrapping request failures, non-2xx responses, and malformed JSON bodies as
16
+ * {@link HttpError}, and parsing the JSON response — and nothing
17
+ * else.
18
+ *
19
+ * The request body is a chain-specific Blockaid contract: the caller
20
+ * supplies a typed body (e.g. checked with `satisfies` against a per-snap
21
+ * body type) and is responsible for validating the parsed response payload.
22
+ */
23
+ export class SecurityAlertsApiClient {
24
+ #fetch;
25
+ #scanUrl;
26
+ /**
27
+ * Creates a new SecurityAlertsApiClient.
28
+ *
29
+ * @param options - The client options.
30
+ * @param options.scanUrl - The full scan endpoint URL. Validated once, so
31
+ * an invalid URL fails fast at construction.
32
+ * @param options.fetch - Optional fetch implementation; defaults to
33
+ * `globalThis.fetch`.
34
+ */
35
+ constructor({ scanUrl, fetch: fetchFn = globalThis.fetch, }) {
36
+ assert(scanUrl, UrlStruct);
37
+ this.#fetch = fetchFn;
38
+ this.#scanUrl = scanUrl;
39
+ }
40
+ /**
41
+ * Scans a transaction by posting the request body to the scan endpoint.
42
+ *
43
+ * @param body - The chain-specific scan request body.
44
+ * @returns The parsed scan response.
45
+ * @throws HttpError if the request fails, the API responds
46
+ * with a non-2xx status, or the response body cannot be parsed as JSON.
47
+ */
48
+ async scanTransaction(body) {
49
+ try {
50
+ const response = await this.#fetch(this.#scanUrl, {
51
+ headers: { ...SECURITY_ALERTS_REQUEST_HEADERS },
52
+ method: 'POST',
53
+ body: JSON.stringify(body),
54
+ });
55
+ if (!response.ok) {
56
+ throw new HttpError(`HTTP error! status: ${response.status}`);
57
+ }
58
+ return await response.json();
59
+ }
60
+ catch (error) {
61
+ if (error instanceof HttpError) {
62
+ throw error;
63
+ }
64
+ throw new HttpError('Security Alerts API error', {
65
+ cause: error,
66
+ });
67
+ }
68
+ }
69
+ }
70
+ //# sourceMappingURL=SecurityAlertsApiClient.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SecurityAlertsApiClient.mjs","sourceRoot":"","sources":["../../../src/clients/security-alerts-api/SecurityAlertsApiClient.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,8BAA8B;AAE/C,OAAO,EAAE,SAAS,EAAE,qCAA2B;AAC/C,OAAO,EAAE,SAAS,EAAE,4CAAwC;AAE5D;;GAEG;AACH,MAAM,CAAC,MAAM,+BAA+B,GAA2B;IACrE,cAAc,EAAE,kBAAkB;IAClC,MAAM,EAAE,kBAAkB;CAC3B,CAAC;AAcF;;;;;;;;;;;GAWG;AACH,MAAM,OAAO,uBAAuB;IACzB,MAAM,CAA0B;IAEhC,QAAQ,CAAS;IAE1B;;;;;;;;OAQG;IACH,YAAY,EACV,OAAO,EACP,KAAK,EAAE,OAAO,GAAG,UAAU,CAAC,KAAK,GACF;QAC/B,MAAM,CAAC,OAAO,EAAE,SAAS,CAAC,CAAC;QAE3B,IAAI,CAAC,MAAM,GAAG,OAAO,CAAC;QACtB,IAAI,CAAC,QAAQ,GAAG,OAAO,CAAC;IAC1B,CAAC;IAED;;;;;;;OAOG;IACH,KAAK,CAAC,eAAe,CAAC,IAAa;QACjC,IAAI,CAAC;YACH,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,QAAQ,EAAE;gBAChD,OAAO,EAAE,EAAE,GAAG,+BAA+B,EAAE;gBAC/C,MAAM,EAAE,MAAM;gBACd,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC;aAC3B,CAAC,CAAC;YAEH,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;gBACjB,MAAM,IAAI,SAAS,CAAC,uBAAuB,QAAQ,CAAC,MAAM,EAAE,CAAC,CAAC;YAChE,CAAC;YAED,OAAO,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC;QAC/B,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,IAAI,KAAK,YAAY,SAAS,EAAE,CAAC;gBAC/B,MAAM,KAAK,CAAC;YACd,CAAC;YAED,MAAM,IAAI,SAAS,CAAC,2BAA2B,EAAE;gBAC/C,KAAK,EAAE,KAAK;aACb,CAAC,CAAC;QACL,CAAC;IACH,CAAC;CACF","sourcesContent":["import { assert } from '@metamask/superstruct';\n\nimport { HttpError } from '../../utils/errors';\nimport { UrlStruct } from '../../utils/urlStruct/urlStruct';\n\n/**\n * Headers sent with every Security Alerts API request.\n */\nexport const SECURITY_ALERTS_REQUEST_HEADERS: Record<string, string> = {\n 'Content-Type': 'application/json',\n accept: 'application/json',\n};\n\n/**\n * Options for a `SecurityAlertsApiClient` constructor.\n */\nexport type SecurityAlertsApiClientOptions = {\n /**\n * The full scan endpoint URL, e.g. `https://security-alerts.api.cx.metamask.io/tron/transaction/scan`.\n */\n scanUrl: string;\n /** The fetch implementation to use. Defaults to `globalThis.fetch`. */\n fetch?: typeof globalThis.fetch;\n};\n\n/**\n * HTTP client for a Security Alerts API scan endpoint.\n *\n * Owns the request envelope shared by every chain — POSTing the JSON body,\n * wrapping request failures, non-2xx responses, and malformed JSON bodies as\n * {@link HttpError}, and parsing the JSON response — and nothing\n * else.\n *\n * The request body is a chain-specific Blockaid contract: the caller\n * supplies a typed body (e.g. checked with `satisfies` against a per-snap\n * body type) and is responsible for validating the parsed response payload.\n */\nexport class SecurityAlertsApiClient {\n readonly #fetch: typeof globalThis.fetch;\n\n readonly #scanUrl: string;\n\n /**\n * Creates a new SecurityAlertsApiClient.\n *\n * @param options - The client options.\n * @param options.scanUrl - The full scan endpoint URL. Validated once, so\n * an invalid URL fails fast at construction.\n * @param options.fetch - Optional fetch implementation; defaults to\n * `globalThis.fetch`.\n */\n constructor({\n scanUrl,\n fetch: fetchFn = globalThis.fetch,\n }: SecurityAlertsApiClientOptions) {\n assert(scanUrl, UrlStruct);\n\n this.#fetch = fetchFn;\n this.#scanUrl = scanUrl;\n }\n\n /**\n * Scans a transaction by posting the request body to the scan endpoint.\n *\n * @param body - The chain-specific scan request body.\n * @returns The parsed scan response.\n * @throws HttpError if the request fails, the API responds\n * with a non-2xx status, or the response body cannot be parsed as JSON.\n */\n async scanTransaction(body: unknown): Promise<unknown> {\n try {\n const response = await this.#fetch(this.#scanUrl, {\n headers: { ...SECURITY_ALERTS_REQUEST_HEADERS },\n method: 'POST',\n body: JSON.stringify(body),\n });\n\n if (!response.ok) {\n throw new HttpError(`HTTP error! status: ${response.status}`);\n }\n\n return await response.json();\n } catch (error) {\n if (error instanceof HttpError) {\n throw error;\n }\n\n throw new HttpError('Security Alerts API error', {\n cause: error,\n });\n }\n }\n}\n"]}
package/dist/index.d.mts CHANGED
@@ -2,6 +2,12 @@ export { ASSETS_PROVIDER_NAME, AssetsProvider, type AssetsProviderMessenger, } f
2
2
  export { REMOTE_FEATURE_FLAGS_PROVIDER_NAME, RemoteFeatureFlagsProvider, type RemoteFeatureFlagsProviderMessenger, } from "./providers/remote-feature-flags/RemoteFeatureFlagsProvider.mjs";
3
3
  export { AnalyticsService, SecurityEventType, TransactionEventType, } from "./services/analytics/AnalyticsService.mjs";
4
4
  export type { AnalyticsServiceOptions, SecurityAlertDetectedEventProperties, SecurityScanCompletedEventProperties, SnapTrackEventRequest, TrackEventCapableProvider, TransactionEventProperties, TransactionFinalizedEventProperties, WebSocketConnectionClosedEventProperties, } from "./services/analytics/AnalyticsService.mjs";
5
+ export { SecurityAlertsApiClient, SECURITY_ALERTS_REQUEST_HEADERS, } from "./clients/security-alerts-api/SecurityAlertsApiClient.mjs";
6
+ export type { SecurityAlertsApiClientOptions } from "./clients/security-alerts-api/SecurityAlertsApiClient.mjs";
7
+ export { SECURITY_ALERTS_SCAN_OPTIONS, SecurityAlertResponse, SecurityAlertsScanStatus, } from "./services/security-alerts/types.mjs";
8
+ export type { BaseScanParams, BaseTransactionScanServiceOptions, SecurityAlertsScanOption, SecurityScanOutcome, } from "./services/security-alerts/types.mjs";
9
+ export { BaseTransactionScanService } from "./services/security-alerts/BaseTransactionScanService.mjs";
10
+ export { deriveSecurityAlert, getSecurityAlertDescription, } from "./services/security-alerts/utils.mjs";
5
11
  export { safeMerge } from "./utils/safeMerge/safeMerge.mjs";
6
12
  export { resolveFlowTransactionType, resolveUnifiedSwapTransactionType, } from "./utils/transactionType/transactionType.mjs";
7
13
  export { buildUrl } from "./utils/buildUrl/buildUrl.mjs";
@@ -30,10 +36,12 @@ export { State } from "./utils/state/State.mjs";
30
36
  export type { StateConfig } from "./utils/state/State.mjs";
31
37
  export { InMemoryState } from "./utils/state/InMemoryState.mjs";
32
38
  export type { IStateManager } from "./utils/state/IStateManager.mjs";
33
- export { createSnapErrorHandling, createTrackError, createWithCatchAndThrowSnapError, formatAccountSyncFailures, getSyncFailuresFromSettledResult, isSnapRpcError, normalizeError, stringifyReason, SynchronizationError, } from "./utils/errors/index.mjs";
39
+ export { createSnapErrorHandling, createTrackError, createWithCatchAndThrowSnapError, formatAccountSyncFailures, getSyncFailuresFromSettledResult, HttpError, isSnapRpcError, normalizeError, stringifyReason, SynchronizationError, } from "./utils/errors/index.mjs";
34
40
  export { InFlightCoalescer } from "./utils/dedupe/InFlightCoalescer.mjs";
35
41
  export { BrokenCircuitError, createFetchPolicy, createFetchPolicyError, FetchPolicyErrorName, isTransientError, MAX_RETRY_AFTER_MS, } from "./utils/fetchPolicy/createFetchPolicy.mjs";
36
42
  export type { CreateFetchPolicyOptions, FetchPolicyError, } from "./utils/fetchPolicy/createFetchPolicy.mjs";
43
+ export { executeWithFetchPolicy, fetchWithPolicy, parseRetryAfter, } from "./utils/fetchPolicy/executeWithFetchPolicy.mjs";
44
+ export type { FetchPolicy } from "./utils/fetchPolicy/executeWithFetchPolicy.mjs";
37
45
  export { ActionHeader } from "./ui/ActionHeader/ActionHeader.mjs";
38
46
  export type { ActionHeaderProps } from "./ui/ActionHeader/ActionHeader.mjs";
39
47
  export { Asset, AssetIcon } from "./ui/Asset/Asset.mjs";
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.mts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.d.mts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
package/dist/index.mjs CHANGED
@@ -1,6 +1,10 @@
1
1
  export { ASSETS_PROVIDER_NAME, AssetsProvider } from "./providers/assets/AssetsProvider.mjs";
2
2
  export { REMOTE_FEATURE_FLAGS_PROVIDER_NAME, RemoteFeatureFlagsProvider } from "./providers/remote-feature-flags/RemoteFeatureFlagsProvider.mjs";
3
3
  export { AnalyticsService, SecurityEventType, TransactionEventType } from "./services/analytics/AnalyticsService.mjs";
4
+ export { SecurityAlertsApiClient, SECURITY_ALERTS_REQUEST_HEADERS } from "./clients/security-alerts-api/SecurityAlertsApiClient.mjs";
5
+ export { SECURITY_ALERTS_SCAN_OPTIONS, SecurityAlertResponse, SecurityAlertsScanStatus } from "./services/security-alerts/types.mjs";
6
+ export { BaseTransactionScanService } from "./services/security-alerts/BaseTransactionScanService.mjs";
7
+ export { deriveSecurityAlert, getSecurityAlertDescription } from "./services/security-alerts/utils.mjs";
4
8
  export { safeMerge } from "./utils/safeMerge/safeMerge.mjs";
5
9
  export { resolveFlowTransactionType, resolveUnifiedSwapTransactionType } from "./utils/transactionType/transactionType.mjs";
6
10
  export { buildUrl } from "./utils/buildUrl/buildUrl.mjs";
@@ -21,9 +25,10 @@ export { createOriginPermissions, DEFAULT_PROD_ORIGINS, DEFAULT_DEV_ORIGINS, DEF
21
25
  export { validateOrigin } from "./utils/originPermissions/validateOrigin.mjs";
22
26
  export { State } from "./utils/state/State.mjs";
23
27
  export { InMemoryState } from "./utils/state/InMemoryState.mjs";
24
- export { createSnapErrorHandling, createTrackError, createWithCatchAndThrowSnapError, formatAccountSyncFailures, getSyncFailuresFromSettledResult, isSnapRpcError, normalizeError, stringifyReason, SynchronizationError } from "./utils/errors/index.mjs";
28
+ export { createSnapErrorHandling, createTrackError, createWithCatchAndThrowSnapError, formatAccountSyncFailures, getSyncFailuresFromSettledResult, HttpError, isSnapRpcError, normalizeError, stringifyReason, SynchronizationError } from "./utils/errors/index.mjs";
25
29
  export { InFlightCoalescer } from "./utils/dedupe/InFlightCoalescer.mjs";
26
30
  export { BrokenCircuitError, createFetchPolicy, createFetchPolicyError, FetchPolicyErrorName, isTransientError, MAX_RETRY_AFTER_MS } from "./utils/fetchPolicy/createFetchPolicy.mjs";
31
+ export { executeWithFetchPolicy, fetchWithPolicy, parseRetryAfter } from "./utils/fetchPolicy/executeWithFetchPolicy.mjs";
27
32
  export { ActionHeader } from "./ui/ActionHeader/ActionHeader.mjs";
28
33
  export { Asset, AssetIcon } from "./ui/Asset/Asset.mjs";
29
34
  export { EstimatedChanges } from "./ui/EstimatedChanges/EstimatedChanges.mjs";
@@ -1 +1 @@
1
- {"version":3,"file":"index.mjs","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,oBAAoB,EACpB,cAAc,EAEf,8CAA0C;AAC3C,OAAO,EACL,kCAAkC,EAClC,0BAA0B,EAE3B,wEAAoE;AACrE,OAAO,EACL,gBAAgB,EAChB,iBAAiB,EACjB,oBAAoB,EACrB,kDAA8C;AAW/C,OAAO,EAAE,SAAS,EAAE,wCAAoC;AACxD,OAAO,EACL,0BAA0B,EAC1B,iCAAiC,EAClC,oDAAgD;AACjD,OAAO,EAAE,QAAQ,EAAE,sCAAkC;AAErD,OAAO,EACL,yBAAyB,EACzB,WAAW,EACZ,sCAAkC;AACnC,OAAO,EAAE,SAAS,EAAE,wCAAoC;AACxD,OAAO,EAAE,UAAU,EAAE,0CAAsC;AAC3D,OAAO,EAAE,sBAAsB,EAAE,kDAA8C;AAK/E,OAAO,EAAE,QAAQ,EAAE,oCAAgC;AACnD,OAAO,EAAE,kBAAkB,EAAE,8CAA0C;AACvE,OAAO,EACL,oBAAoB,EACpB,kBAAkB,EAClB,gBAAgB,EAChB,kBAAkB,EAClB,gBAAgB,EACjB,sCAAkC;AACnC,OAAO,EAAE,cAAc,EAAE,0CAAsC;AAC/D,OAAO,EACL,WAAW,EACX,iBAAiB,EAClB,6CAAyC;AAC1C,OAAO,EACL,UAAU,EACV,iBAAiB,EACjB,2BAA2B,EAC3B,oBAAoB,EACpB,MAAM,EACP,gCAA4B;AAC7B,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,kCAA8B;AAQzD,OAAO,EAAE,SAAS,EAAE,WAAW,EAAE,gDAA4C;AAE7E,OAAO,EACL,4BAA4B,EAC5B,gCAAgC,EAChC,uCAAuC,EACvC,sCAAsC,EACtC,wCAAwC,EACxC,mCAAmC,EACnC,kCAAkC,EAClC,6BAA6B,EAC7B,iCAAiC,EAClC,sDAAkD;AAUnD,OAAO,EACL,uBAAuB,EACvB,oBAAoB,EACpB,mBAAmB,EACnB,uBAAuB,EACxB,8DAA0D;AAE3D,OAAO,EAAE,cAAc,EAAE,qDAAiD;AAC1E,OAAO,EAAE,KAAK,EAAE,gCAA4B;AAE5C,OAAO,EAAE,aAAa,EAAE,wCAAoC;AAE5D,OAAO,EACL,uBAAuB,EACvB,gBAAgB,EAChB,gCAAgC,EAChC,yBAAyB,EACzB,gCAAgC,EAChC,cAAc,EACd,cAAc,EACd,eAAe,EACf,oBAAoB,EACrB,iCAAuB;AACxB,OAAO,EAAE,iBAAiB,EAAE,6CAAyC;AACrE,OAAO,EACL,kBAAkB,EAClB,iBAAiB,EACjB,sBAAsB,EACtB,oBAAoB,EACpB,gBAAgB,EAChB,kBAAkB,EACnB,kDAA8C;AAK/C,OAAO,EAAE,YAAY,EAAE,2CAAuC;AAE9D,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,6BAAyB;AAEpD,OAAO,EAAE,gBAAgB,EAAE,mDAA+C;AAM1E,OAAO,EAAE,gBAAgB,EAAE,mDAA+C;AAO1E,OAAO,EAAE,aAAa,EAAE,wCAAoC;AAC5D,OAAO,EAAE,UAAU,EAAE,qCAAiC;AACtD,OAAO,EAAE,QAAQ,EAAE,mCAA+B;AAClD,OAAO,EAAE,aAAa,EAAE,wCAAoC;AAiB5D,OAAO,EACL,iBAAiB,EACjB,gBAAgB,EACjB,8CAA0C","sourcesContent":["export {\n ASSETS_PROVIDER_NAME,\n AssetsProvider,\n type AssetsProviderMessenger,\n} from './providers/assets/AssetsProvider';\nexport {\n REMOTE_FEATURE_FLAGS_PROVIDER_NAME,\n RemoteFeatureFlagsProvider,\n type RemoteFeatureFlagsProviderMessenger,\n} from './providers/remote-feature-flags/RemoteFeatureFlagsProvider';\nexport {\n AnalyticsService,\n SecurityEventType,\n TransactionEventType,\n} from './services/analytics/AnalyticsService';\nexport type {\n AnalyticsServiceOptions,\n SecurityAlertDetectedEventProperties,\n SecurityScanCompletedEventProperties,\n SnapTrackEventRequest,\n TrackEventCapableProvider,\n TransactionEventProperties,\n TransactionFinalizedEventProperties,\n WebSocketConnectionClosedEventProperties,\n} from './services/analytics/AnalyticsService';\nexport { safeMerge } from './utils/safeMerge/safeMerge';\nexport {\n resolveFlowTransactionType,\n resolveUnifiedSwapTransactionType,\n} from './utils/transactionType/transactionType';\nexport { buildUrl } from './utils/buildUrl/buildUrl';\nexport type { BuildUrlParams } from './utils/buildUrl/buildUrl';\nexport {\n sanitizeControlCharacters,\n sanitizeUri,\n} from './utils/sanitize/sanitize';\nexport { UrlStruct } from './utils/urlStruct/urlStruct';\nexport { UuidStruct } from './utils/uuidStruct/uuidStruct';\nexport { asStrictKeyringAccount } from './utils/keyringAccount/keyringAccount';\nexport type {\n ExtendedKeyringAccount,\n KeyringAccountExtension,\n} from './utils/keyringAccount/keyringAccount';\nexport { parseEnv } from './utils/config/parseEnv';\nexport { BaseConfigProvider } from './utils/config/BaseConfigProvider';\nexport {\n commaSeparatedListOf,\n defaultedUrlStruct,\n emptyToUndefined,\n parseIntegerStruct,\n parseFloatStruct,\n} from './utils/config/envStructs';\nexport { LogLevelStruct } from './utils/config/logLevelStruct';\nexport {\n Environment,\n EnvironmentStruct,\n} from './utils/config/environmentStruct';\nexport {\n batchesAll,\n batchesAllSettled,\n batchesAllSettledWithChunks,\n batchesAllWithChunks,\n chunks,\n} from './utils/async/async';\nexport { Logger, LogLevel } from './utils/logger/Logger';\nexport type {\n LoggerOptions,\n LoggerMethod,\n LogMethod,\n LogMethodDecorator,\n LoggerDecorators,\n} from './utils/logger/Logger';\nexport { serialize, deserialize } from './utils/serialization/serialization';\nexport type { Serializable } from './utils/serialization/types';\nexport {\n parseProofOfOwnershipMessage,\n ProofOfOwnershipBatchErrorStruct,\n ProofOfOwnershipBatchItemResponseStruct,\n ProofOfOwnershipBatchRequestItemStruct,\n ProofOfOwnershipBatchRequestParamsStruct,\n ProofOfOwnershipBatchResponseStruct,\n ProofOfOwnershipBatchSuccessStruct,\n ProofOfOwnershipMessageStruct,\n PROOF_OF_OWNERSHIP_MESSAGE_PREFIX,\n} from './utils/proofOfOwnership/proofOfOwnership';\nexport type {\n ProofOfOwnershipBatchError,\n ProofOfOwnershipBatchItemResponse,\n ProofOfOwnershipBatchRequestItem,\n ProofOfOwnershipBatchRequestParams,\n ProofOfOwnershipBatchResponse,\n ProofOfOwnershipBatchSuccess,\n ProofOfOwnershipMessage,\n} from './utils/proofOfOwnership/proofOfOwnership';\nexport {\n createOriginPermissions,\n DEFAULT_PROD_ORIGINS,\n DEFAULT_DEV_ORIGINS,\n DEFAULT_METAMASK_ORIGIN,\n} from './utils/originPermissions/createOriginPermissions';\nexport type { CreateOriginPermissionsParams } from './utils/originPermissions/createOriginPermissions';\nexport { validateOrigin } from './utils/originPermissions/validateOrigin';\nexport { State } from './utils/state/State';\nexport type { StateConfig } from './utils/state/State';\nexport { InMemoryState } from './utils/state/InMemoryState';\nexport type { IStateManager } from './utils/state/IStateManager';\nexport {\n createSnapErrorHandling,\n createTrackError,\n createWithCatchAndThrowSnapError,\n formatAccountSyncFailures,\n getSyncFailuresFromSettledResult,\n isSnapRpcError,\n normalizeError,\n stringifyReason,\n SynchronizationError,\n} from './utils/errors';\nexport { InFlightCoalescer } from './utils/dedupe/InFlightCoalescer';\nexport {\n BrokenCircuitError,\n createFetchPolicy,\n createFetchPolicyError,\n FetchPolicyErrorName,\n isTransientError,\n MAX_RETRY_AFTER_MS,\n} from './utils/fetchPolicy/createFetchPolicy';\nexport type {\n CreateFetchPolicyOptions,\n FetchPolicyError,\n} from './utils/fetchPolicy/createFetchPolicy';\nexport { ActionHeader } from './ui/ActionHeader/ActionHeader';\nexport type { ActionHeaderProps } from './ui/ActionHeader/ActionHeader';\nexport { Asset, AssetIcon } from './ui/Asset/Asset';\nexport type { AssetIconProps, AssetProps } from './ui/Asset/Asset';\nexport { EstimatedChanges } from './ui/EstimatedChanges/EstimatedChanges';\nexport type {\n EstimatedChangesAsset,\n EstimatedChangesLabels,\n EstimatedChangesProps,\n} from './ui/EstimatedChanges/EstimatedChanges';\nexport { TransactionAlert } from './ui/TransactionAlert/TransactionAlert';\nexport type {\n TransactionAlertError,\n TransactionAlertLabels,\n TransactionAlertProps,\n TransactionAlertValidation,\n} from './ui/TransactionAlert/TransactionAlert';\nexport { InMemoryCache } from './utils/cache/InMemoryCache';\nexport { StateCache } from './utils/cache/StateCache';\nexport { useCache } from './utils/cache/useCache';\nexport { useCacheUntil } from './utils/cache/useCacheUntil';\nexport type { CacheOptions } from './utils/cache/useCache';\nexport type {\n CacheUntilOptions,\n ResultWithExpiry,\n} from './utils/cache/useCacheUntil';\nexport type {\n ICache,\n CacheEntry,\n TimestampMilliseconds,\n} from './utils/cache/types';\nexport type {\n CacheStateManager,\n CacheStore,\n CachePrefix,\n StateValue,\n} from './utils/cache/StateCache';\nexport {\n noopAssetHandlers,\n wrapSnapHandlers,\n} from './utils/handlers/wrapSnapHandlers';\nexport type {\n SnapHandlers,\n WithCatchAndThrowSnapError,\n} from './utils/handlers/wrapSnapHandlers';\nexport type {\n AccountSyncFailure,\n CreateSnapErrorHandlingOptions,\n CreateTrackErrorOptions,\n CreateWithCatchAndThrowSnapErrorOptions,\n LogErrorFn,\n NormalizeErrorFn,\n PrepareErrorForTrackingFn,\n ShouldTrackErrorFn,\n SnapRpcError,\n SnapTrackErrorRequest,\n TrackErrorCapableProvider,\n TrackErrorFn,\n} from './utils/errors';\n"]}
1
+ {"version":3,"file":"index.mjs","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,oBAAoB,EACpB,cAAc,EAEf,8CAA0C;AAC3C,OAAO,EACL,kCAAkC,EAClC,0BAA0B,EAE3B,wEAAoE;AACrE,OAAO,EACL,gBAAgB,EAChB,iBAAiB,EACjB,oBAAoB,EACrB,kDAA8C;AAW/C,OAAO,EACL,uBAAuB,EACvB,+BAA+B,EAChC,kEAA8D;AAE/D,OAAO,EACL,4BAA4B,EAC5B,qBAAqB,EACrB,wBAAwB,EACzB,6CAAyC;AAO1C,OAAO,EAAE,0BAA0B,EAAE,kEAA8D;AACnG,OAAO,EACL,mBAAmB,EACnB,2BAA2B,EAC5B,6CAAyC;AAC1C,OAAO,EAAE,SAAS,EAAE,wCAAoC;AACxD,OAAO,EACL,0BAA0B,EAC1B,iCAAiC,EAClC,oDAAgD;AACjD,OAAO,EAAE,QAAQ,EAAE,sCAAkC;AAErD,OAAO,EACL,yBAAyB,EACzB,WAAW,EACZ,sCAAkC;AACnC,OAAO,EAAE,SAAS,EAAE,wCAAoC;AACxD,OAAO,EAAE,UAAU,EAAE,0CAAsC;AAC3D,OAAO,EAAE,sBAAsB,EAAE,kDAA8C;AAK/E,OAAO,EAAE,QAAQ,EAAE,oCAAgC;AACnD,OAAO,EAAE,kBAAkB,EAAE,8CAA0C;AACvE,OAAO,EACL,oBAAoB,EACpB,kBAAkB,EAClB,gBAAgB,EAChB,kBAAkB,EAClB,gBAAgB,EACjB,sCAAkC;AACnC,OAAO,EAAE,cAAc,EAAE,0CAAsC;AAC/D,OAAO,EACL,WAAW,EACX,iBAAiB,EAClB,6CAAyC;AAC1C,OAAO,EACL,UAAU,EACV,iBAAiB,EACjB,2BAA2B,EAC3B,oBAAoB,EACpB,MAAM,EACP,gCAA4B;AAC7B,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,kCAA8B;AAQzD,OAAO,EAAE,SAAS,EAAE,WAAW,EAAE,gDAA4C;AAE7E,OAAO,EACL,4BAA4B,EAC5B,gCAAgC,EAChC,uCAAuC,EACvC,sCAAsC,EACtC,wCAAwC,EACxC,mCAAmC,EACnC,kCAAkC,EAClC,6BAA6B,EAC7B,iCAAiC,EAClC,sDAAkD;AAUnD,OAAO,EACL,uBAAuB,EACvB,oBAAoB,EACpB,mBAAmB,EACnB,uBAAuB,EACxB,8DAA0D;AAE3D,OAAO,EAAE,cAAc,EAAE,qDAAiD;AAC1E,OAAO,EAAE,KAAK,EAAE,gCAA4B;AAE5C,OAAO,EAAE,aAAa,EAAE,wCAAoC;AAE5D,OAAO,EACL,uBAAuB,EACvB,gBAAgB,EAChB,gCAAgC,EAChC,yBAAyB,EACzB,gCAAgC,EAChC,SAAS,EACT,cAAc,EACd,cAAc,EACd,eAAe,EACf,oBAAoB,EACrB,iCAAuB;AACxB,OAAO,EAAE,iBAAiB,EAAE,6CAAyC;AACrE,OAAO,EACL,kBAAkB,EAClB,iBAAiB,EACjB,sBAAsB,EACtB,oBAAoB,EACpB,gBAAgB,EAChB,kBAAkB,EACnB,kDAA8C;AAK/C,OAAO,EACL,sBAAsB,EACtB,eAAe,EACf,eAAe,EAChB,uDAAmD;AAEpD,OAAO,EAAE,YAAY,EAAE,2CAAuC;AAE9D,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,6BAAyB;AAEpD,OAAO,EAAE,gBAAgB,EAAE,mDAA+C;AAM1E,OAAO,EAAE,gBAAgB,EAAE,mDAA+C;AAO1E,OAAO,EAAE,aAAa,EAAE,wCAAoC;AAC5D,OAAO,EAAE,UAAU,EAAE,qCAAiC;AACtD,OAAO,EAAE,QAAQ,EAAE,mCAA+B;AAClD,OAAO,EAAE,aAAa,EAAE,wCAAoC;AAiB5D,OAAO,EACL,iBAAiB,EACjB,gBAAgB,EACjB,8CAA0C","sourcesContent":["export {\n ASSETS_PROVIDER_NAME,\n AssetsProvider,\n type AssetsProviderMessenger,\n} from './providers/assets/AssetsProvider';\nexport {\n REMOTE_FEATURE_FLAGS_PROVIDER_NAME,\n RemoteFeatureFlagsProvider,\n type RemoteFeatureFlagsProviderMessenger,\n} from './providers/remote-feature-flags/RemoteFeatureFlagsProvider';\nexport {\n AnalyticsService,\n SecurityEventType,\n TransactionEventType,\n} from './services/analytics/AnalyticsService';\nexport type {\n AnalyticsServiceOptions,\n SecurityAlertDetectedEventProperties,\n SecurityScanCompletedEventProperties,\n SnapTrackEventRequest,\n TrackEventCapableProvider,\n TransactionEventProperties,\n TransactionFinalizedEventProperties,\n WebSocketConnectionClosedEventProperties,\n} from './services/analytics/AnalyticsService';\nexport {\n SecurityAlertsApiClient,\n SECURITY_ALERTS_REQUEST_HEADERS,\n} from './clients/security-alerts-api/SecurityAlertsApiClient';\nexport type { SecurityAlertsApiClientOptions } from './clients/security-alerts-api/SecurityAlertsApiClient';\nexport {\n SECURITY_ALERTS_SCAN_OPTIONS,\n SecurityAlertResponse,\n SecurityAlertsScanStatus,\n} from './services/security-alerts/types';\nexport type {\n BaseScanParams,\n BaseTransactionScanServiceOptions,\n SecurityAlertsScanOption,\n SecurityScanOutcome,\n} from './services/security-alerts/types';\nexport { BaseTransactionScanService } from './services/security-alerts/BaseTransactionScanService';\nexport {\n deriveSecurityAlert,\n getSecurityAlertDescription,\n} from './services/security-alerts/utils';\nexport { safeMerge } from './utils/safeMerge/safeMerge';\nexport {\n resolveFlowTransactionType,\n resolveUnifiedSwapTransactionType,\n} from './utils/transactionType/transactionType';\nexport { buildUrl } from './utils/buildUrl/buildUrl';\nexport type { BuildUrlParams } from './utils/buildUrl/buildUrl';\nexport {\n sanitizeControlCharacters,\n sanitizeUri,\n} from './utils/sanitize/sanitize';\nexport { UrlStruct } from './utils/urlStruct/urlStruct';\nexport { UuidStruct } from './utils/uuidStruct/uuidStruct';\nexport { asStrictKeyringAccount } from './utils/keyringAccount/keyringAccount';\nexport type {\n ExtendedKeyringAccount,\n KeyringAccountExtension,\n} from './utils/keyringAccount/keyringAccount';\nexport { parseEnv } from './utils/config/parseEnv';\nexport { BaseConfigProvider } from './utils/config/BaseConfigProvider';\nexport {\n commaSeparatedListOf,\n defaultedUrlStruct,\n emptyToUndefined,\n parseIntegerStruct,\n parseFloatStruct,\n} from './utils/config/envStructs';\nexport { LogLevelStruct } from './utils/config/logLevelStruct';\nexport {\n Environment,\n EnvironmentStruct,\n} from './utils/config/environmentStruct';\nexport {\n batchesAll,\n batchesAllSettled,\n batchesAllSettledWithChunks,\n batchesAllWithChunks,\n chunks,\n} from './utils/async/async';\nexport { Logger, LogLevel } from './utils/logger/Logger';\nexport type {\n LoggerOptions,\n LoggerMethod,\n LogMethod,\n LogMethodDecorator,\n LoggerDecorators,\n} from './utils/logger/Logger';\nexport { serialize, deserialize } from './utils/serialization/serialization';\nexport type { Serializable } from './utils/serialization/types';\nexport {\n parseProofOfOwnershipMessage,\n ProofOfOwnershipBatchErrorStruct,\n ProofOfOwnershipBatchItemResponseStruct,\n ProofOfOwnershipBatchRequestItemStruct,\n ProofOfOwnershipBatchRequestParamsStruct,\n ProofOfOwnershipBatchResponseStruct,\n ProofOfOwnershipBatchSuccessStruct,\n ProofOfOwnershipMessageStruct,\n PROOF_OF_OWNERSHIP_MESSAGE_PREFIX,\n} from './utils/proofOfOwnership/proofOfOwnership';\nexport type {\n ProofOfOwnershipBatchError,\n ProofOfOwnershipBatchItemResponse,\n ProofOfOwnershipBatchRequestItem,\n ProofOfOwnershipBatchRequestParams,\n ProofOfOwnershipBatchResponse,\n ProofOfOwnershipBatchSuccess,\n ProofOfOwnershipMessage,\n} from './utils/proofOfOwnership/proofOfOwnership';\nexport {\n createOriginPermissions,\n DEFAULT_PROD_ORIGINS,\n DEFAULT_DEV_ORIGINS,\n DEFAULT_METAMASK_ORIGIN,\n} from './utils/originPermissions/createOriginPermissions';\nexport type { CreateOriginPermissionsParams } from './utils/originPermissions/createOriginPermissions';\nexport { validateOrigin } from './utils/originPermissions/validateOrigin';\nexport { State } from './utils/state/State';\nexport type { StateConfig } from './utils/state/State';\nexport { InMemoryState } from './utils/state/InMemoryState';\nexport type { IStateManager } from './utils/state/IStateManager';\nexport {\n createSnapErrorHandling,\n createTrackError,\n createWithCatchAndThrowSnapError,\n formatAccountSyncFailures,\n getSyncFailuresFromSettledResult,\n HttpError,\n isSnapRpcError,\n normalizeError,\n stringifyReason,\n SynchronizationError,\n} from './utils/errors';\nexport { InFlightCoalescer } from './utils/dedupe/InFlightCoalescer';\nexport {\n BrokenCircuitError,\n createFetchPolicy,\n createFetchPolicyError,\n FetchPolicyErrorName,\n isTransientError,\n MAX_RETRY_AFTER_MS,\n} from './utils/fetchPolicy/createFetchPolicy';\nexport type {\n CreateFetchPolicyOptions,\n FetchPolicyError,\n} from './utils/fetchPolicy/createFetchPolicy';\nexport {\n executeWithFetchPolicy,\n fetchWithPolicy,\n parseRetryAfter,\n} from './utils/fetchPolicy/executeWithFetchPolicy';\nexport type { FetchPolicy } from './utils/fetchPolicy/executeWithFetchPolicy';\nexport { ActionHeader } from './ui/ActionHeader/ActionHeader';\nexport type { ActionHeaderProps } from './ui/ActionHeader/ActionHeader';\nexport { Asset, AssetIcon } from './ui/Asset/Asset';\nexport type { AssetIconProps, AssetProps } from './ui/Asset/Asset';\nexport { EstimatedChanges } from './ui/EstimatedChanges/EstimatedChanges';\nexport type {\n EstimatedChangesAsset,\n EstimatedChangesLabels,\n EstimatedChangesProps,\n} from './ui/EstimatedChanges/EstimatedChanges';\nexport { TransactionAlert } from './ui/TransactionAlert/TransactionAlert';\nexport type {\n TransactionAlertError,\n TransactionAlertLabels,\n TransactionAlertProps,\n TransactionAlertValidation,\n} from './ui/TransactionAlert/TransactionAlert';\nexport { InMemoryCache } from './utils/cache/InMemoryCache';\nexport { StateCache } from './utils/cache/StateCache';\nexport { useCache } from './utils/cache/useCache';\nexport { useCacheUntil } from './utils/cache/useCacheUntil';\nexport type { CacheOptions } from './utils/cache/useCache';\nexport type {\n CacheUntilOptions,\n ResultWithExpiry,\n} from './utils/cache/useCacheUntil';\nexport type {\n ICache,\n CacheEntry,\n TimestampMilliseconds,\n} from './utils/cache/types';\nexport type {\n CacheStateManager,\n CacheStore,\n CachePrefix,\n StateValue,\n} from './utils/cache/StateCache';\nexport {\n noopAssetHandlers,\n wrapSnapHandlers,\n} from './utils/handlers/wrapSnapHandlers';\nexport type {\n SnapHandlers,\n WithCatchAndThrowSnapError,\n} from './utils/handlers/wrapSnapHandlers';\nexport type {\n AccountSyncFailure,\n CreateSnapErrorHandlingOptions,\n CreateTrackErrorOptions,\n CreateWithCatchAndThrowSnapErrorOptions,\n LogErrorFn,\n NormalizeErrorFn,\n PrepareErrorForTrackingFn,\n ShouldTrackErrorFn,\n SnapRpcError,\n SnapTrackErrorRequest,\n TrackErrorCapableProvider,\n TrackErrorFn,\n} from './utils/errors';\n"]}
@@ -0,0 +1,60 @@
1
+ import type { SecurityAlertsApiClient } from "../../clients/security-alerts-api/SecurityAlertsApiClient.mjs";
2
+ import type { TrackErrorFn } from "../../utils/errors/index.mjs";
3
+ import type { Logger } from "../../utils/logger/Logger.mjs";
4
+ import type { AnalyticsService } from "../analytics/AnalyticsService.mjs";
5
+ import type { BaseScanParams, BaseTransactionScanServiceOptions, SecurityScanOutcome } from "./types.mjs";
6
+ /**
7
+ * Base for the network snaps' transaction scan services.
8
+ *
9
+ * Owns the shared scan dependencies (Security Alerts API client, analytics,
10
+ * logger, error reporting) and the scan analytics orchestration. Each snap
11
+ * implements its own {@link scanTransaction} flow — request body, schema
12
+ * assertions, and response mapping are chain-specific — and calls the
13
+ * protected analytics methods as the scan completes or fails.
14
+ */
15
+ export declare abstract class BaseTransactionScanService {
16
+ protected readonly securityAlertsApiClient: SecurityAlertsApiClient;
17
+ protected readonly analyticsService: AnalyticsService;
18
+ protected readonly logger: Logger;
19
+ protected readonly trackError: TrackErrorFn;
20
+ /**
21
+ * Creates a new base transaction scan service.
22
+ *
23
+ * @param options - The service options.
24
+ * @param options.securityAlertsApiClient - The shared scan API client.
25
+ * @param options.analyticsService - The shared analytics service.
26
+ * @param options.logger - The logger to use.
27
+ * @param options.trackError - Reports scan failures to Sentry.
28
+ */
29
+ constructor({ securityAlertsApiClient, analyticsService, logger, trackError, }: BaseTransactionScanServiceOptions);
30
+ /**
31
+ * The single scan entry point every network snap implements.
32
+ *
33
+ * Parameters are chain-specific and intentionally unconstrained here;
34
+ * implementations resolve to the mapped scan result, or `null` when the
35
+ * scan could not be performed. Analytics reporting is the implementation's
36
+ * responsibility, via {@link trackScanCompleted} / {@link trackScanFailed}.
37
+ *
38
+ * @param params - The chain-specific scan parameters.
39
+ * @returns The mapped scan result, or `null` when the scan failed.
40
+ */
41
+ abstract scanTransaction(params: unknown): Promise<SecurityScanOutcome | null>;
42
+ /**
43
+ * Tracks the analytics events of a completed scan: always a completed scan
44
+ * event, plus an alert-detected event when the verdict is reportable.
45
+ *
46
+ * Analytics are only tracked when the scan params carry an account type.
47
+ *
48
+ * @param params - The origin and account the scan belongs to.
49
+ * @param scan - The mapped scan result.
50
+ */
51
+ protected trackScanCompleted(params: BaseScanParams, scan: SecurityScanOutcome): Promise<void>;
52
+ /**
53
+ * Tracks the analytics events of a failed scan: a completed scan event with
54
+ * an error status, when the scan is tied to an account.
55
+ *
56
+ * @param params - The origin and account the scan belongs to.
57
+ */
58
+ protected trackScanFailed(params: BaseScanParams): Promise<void>;
59
+ }
60
+ //# sourceMappingURL=BaseTransactionScanService.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"BaseTransactionScanService.d.mts","sourceRoot":"","sources":["../../../src/services/security-alerts/BaseTransactionScanService.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,uBAAuB,EAAE,sEAAkE;AACzG,OAAO,KAAK,EAAE,YAAY,EAAE,qCAA2B;AACvD,OAAO,KAAK,EAAE,MAAM,EAAE,sCAAkC;AACxD,OAAO,KAAK,EAAE,gBAAgB,EAAE,0CAAsC;AACtE,OAAO,KAAK,EACV,cAAc,EACd,iCAAiC,EACjC,mBAAmB,EACpB,oBAAgB;AAIjB;;;;;;;;GAQG;AACH,8BAAsB,0BAA0B;IAC9C,SAAS,CAAC,QAAQ,CAAC,uBAAuB,EAAE,uBAAuB,CAAC;IAEpE,SAAS,CAAC,QAAQ,CAAC,gBAAgB,EAAE,gBAAgB,CAAC;IAEtD,SAAS,CAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IAElC,SAAS,CAAC,QAAQ,CAAC,UAAU,EAAE,YAAY,CAAC;IAE5C;;;;;;;;OAQG;gBACS,EACV,uBAAuB,EACvB,gBAAgB,EAChB,MAAM,EACN,UAAU,GACX,EAAE,iCAAiC;IAOpC;;;;;;;;;;OAUG;IACH,QAAQ,CAAC,eAAe,CACtB,MAAM,EAAE,OAAO,GACd,OAAO,CAAC,mBAAmB,GAAG,IAAI,CAAC;IAEtC;;;;;;;;OAQG;cACa,kBAAkB,CAChC,MAAM,EAAE,cAAc,EACtB,IAAI,EAAE,mBAAmB,GACxB,OAAO,CAAC,IAAI,CAAC;IAiChB;;;;;OAKG;cACa,eAAe,CAAC,MAAM,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC;CAevE"}
@@ -0,0 +1,87 @@
1
+ import { SecurityAlertsScanStatus } from "./types.mjs";
2
+ import { deriveSecurityAlert, getSecurityAlertDescription } from "./utils.mjs";
3
+ /**
4
+ * Base for the network snaps' transaction scan services.
5
+ *
6
+ * Owns the shared scan dependencies (Security Alerts API client, analytics,
7
+ * logger, error reporting) and the scan analytics orchestration. Each snap
8
+ * implements its own {@link scanTransaction} flow — request body, schema
9
+ * assertions, and response mapping are chain-specific — and calls the
10
+ * protected analytics methods as the scan completes or fails.
11
+ */
12
+ export class BaseTransactionScanService {
13
+ securityAlertsApiClient;
14
+ analyticsService;
15
+ logger;
16
+ trackError;
17
+ /**
18
+ * Creates a new base transaction scan service.
19
+ *
20
+ * @param options - The service options.
21
+ * @param options.securityAlertsApiClient - The shared scan API client.
22
+ * @param options.analyticsService - The shared analytics service.
23
+ * @param options.logger - The logger to use.
24
+ * @param options.trackError - Reports scan failures to Sentry.
25
+ */
26
+ constructor({ securityAlertsApiClient, analyticsService, logger, trackError, }) {
27
+ this.securityAlertsApiClient = securityAlertsApiClient;
28
+ this.analyticsService = analyticsService;
29
+ this.logger = logger;
30
+ this.trackError = trackError;
31
+ }
32
+ /**
33
+ * Tracks the analytics events of a completed scan: always a completed scan
34
+ * event, plus an alert-detected event when the verdict is reportable.
35
+ *
36
+ * Analytics are only tracked when the scan params carry an account type.
37
+ *
38
+ * @param params - The origin and account the scan belongs to.
39
+ * @param scan - The mapped scan result.
40
+ */
41
+ async trackScanCompleted(params, scan) {
42
+ const { origin, accountType, scope } = params;
43
+ if (!accountType) {
44
+ return;
45
+ }
46
+ const securityAlert = deriveSecurityAlert(scan.validation?.type);
47
+ await this.analyticsService.trackSecurityScanCompleted({
48
+ origin,
49
+ accountType,
50
+ chainIdCaip: scope,
51
+ scanStatus: scan.status,
52
+ hasSecurityAlerts: Boolean(securityAlert),
53
+ });
54
+ if (!securityAlert) {
55
+ return;
56
+ }
57
+ const reason = scan.validation?.reason ?? null;
58
+ await this.analyticsService.trackSecurityAlertDetected({
59
+ origin,
60
+ accountType,
61
+ chainIdCaip: scope,
62
+ securityAlertResponse: securityAlert,
63
+ securityAlertReason: reason,
64
+ securityAlertDescription: getSecurityAlertDescription(reason),
65
+ });
66
+ }
67
+ /**
68
+ * Tracks the analytics events of a failed scan: a completed scan event with
69
+ * an error status, when the scan is tied to an account.
70
+ *
71
+ * @param params - The origin and account the scan belongs to.
72
+ */
73
+ async trackScanFailed(params) {
74
+ const { origin, accountType, scope } = params;
75
+ if (!accountType) {
76
+ return;
77
+ }
78
+ await this.analyticsService.trackSecurityScanCompleted({
79
+ origin,
80
+ accountType,
81
+ chainIdCaip: scope,
82
+ scanStatus: SecurityAlertsScanStatus.ERROR,
83
+ hasSecurityAlerts: false,
84
+ });
85
+ }
86
+ }
87
+ //# sourceMappingURL=BaseTransactionScanService.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"BaseTransactionScanService.mjs","sourceRoot":"","sources":["../../../src/services/security-alerts/BaseTransactionScanService.ts"],"names":[],"mappings":"AASA,OAAO,EAAE,wBAAwB,EAAE,oBAAgB;AACnD,OAAO,EAAE,mBAAmB,EAAE,2BAA2B,EAAE,oBAAgB;AAE3E;;;;;;;;GAQG;AACH,MAAM,OAAgB,0BAA0B;IAC3B,uBAAuB,CAA0B;IAEjD,gBAAgB,CAAmB;IAEnC,MAAM,CAAS;IAEf,UAAU,CAAe;IAE5C;;;;;;;;OAQG;IACH,YAAY,EACV,uBAAuB,EACvB,gBAAgB,EAChB,MAAM,EACN,UAAU,GACwB;QAClC,IAAI,CAAC,uBAAuB,GAAG,uBAAuB,CAAC;QACvD,IAAI,CAAC,gBAAgB,GAAG,gBAAgB,CAAC;QACzC,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;QACrB,IAAI,CAAC,UAAU,GAAG,UAAU,CAAC;IAC/B,CAAC;IAiBD;;;;;;;;OAQG;IACO,KAAK,CAAC,kBAAkB,CAChC,MAAsB,EACtB,IAAyB;QAEzB,MAAM,EAAE,MAAM,EAAE,WAAW,EAAE,KAAK,EAAE,GAAG,MAAM,CAAC;QAE9C,IAAI,CAAC,WAAW,EAAE,CAAC;YACjB,OAAO;QACT,CAAC;QAED,MAAM,aAAa,GAAG,mBAAmB,CAAC,IAAI,CAAC,UAAU,EAAE,IAAI,CAAC,CAAC;QAEjE,MAAM,IAAI,CAAC,gBAAgB,CAAC,0BAA0B,CAAC;YACrD,MAAM;YACN,WAAW;YACX,WAAW,EAAE,KAAK;YAClB,UAAU,EAAE,IAAI,CAAC,MAAM;YACvB,iBAAiB,EAAE,OAAO,CAAC,aAAa,CAAC;SAC1C,CAAC,CAAC;QAEH,IAAI,CAAC,aAAa,EAAE,CAAC;YACnB,OAAO;QACT,CAAC;QAED,MAAM,MAAM,GAAG,IAAI,CAAC,UAAU,EAAE,MAAM,IAAI,IAAI,CAAC;QAE/C,MAAM,IAAI,CAAC,gBAAgB,CAAC,0BAA0B,CAAC;YACrD,MAAM;YACN,WAAW;YACX,WAAW,EAAE,KAAK;YAClB,qBAAqB,EAAE,aAAa;YACpC,mBAAmB,EAAE,MAAM;YAC3B,wBAAwB,EAAE,2BAA2B,CAAC,MAAM,CAAC;SAC9D,CAAC,CAAC;IACL,CAAC;IAED;;;;;OAKG;IACO,KAAK,CAAC,eAAe,CAAC,MAAsB;QACpD,MAAM,EAAE,MAAM,EAAE,WAAW,EAAE,KAAK,EAAE,GAAG,MAAM,CAAC;QAE9C,IAAI,CAAC,WAAW,EAAE,CAAC;YACjB,OAAO;QACT,CAAC;QAED,MAAM,IAAI,CAAC,gBAAgB,CAAC,0BAA0B,CAAC;YACrD,MAAM;YACN,WAAW;YACX,WAAW,EAAE,KAAK;YAClB,UAAU,EAAE,wBAAwB,CAAC,KAAK;YAC1C,iBAAiB,EAAE,KAAK;SACzB,CAAC,CAAC;IACL,CAAC;CACF","sourcesContent":["import type { SecurityAlertsApiClient } from '../../clients/security-alerts-api/SecurityAlertsApiClient';\nimport type { TrackErrorFn } from '../../utils/errors';\nimport type { Logger } from '../../utils/logger/Logger';\nimport type { AnalyticsService } from '../analytics/AnalyticsService';\nimport type {\n BaseScanParams,\n BaseTransactionScanServiceOptions,\n SecurityScanOutcome,\n} from './types';\nimport { SecurityAlertsScanStatus } from './types';\nimport { deriveSecurityAlert, getSecurityAlertDescription } from './utils';\n\n/**\n * Base for the network snaps' transaction scan services.\n *\n * Owns the shared scan dependencies (Security Alerts API client, analytics,\n * logger, error reporting) and the scan analytics orchestration. Each snap\n * implements its own {@link scanTransaction} flow — request body, schema\n * assertions, and response mapping are chain-specific — and calls the\n * protected analytics methods as the scan completes or fails.\n */\nexport abstract class BaseTransactionScanService {\n protected readonly securityAlertsApiClient: SecurityAlertsApiClient;\n\n protected readonly analyticsService: AnalyticsService;\n\n protected readonly logger: Logger;\n\n protected readonly trackError: TrackErrorFn;\n\n /**\n * Creates a new base transaction scan service.\n *\n * @param options - The service options.\n * @param options.securityAlertsApiClient - The shared scan API client.\n * @param options.analyticsService - The shared analytics service.\n * @param options.logger - The logger to use.\n * @param options.trackError - Reports scan failures to Sentry.\n */\n constructor({\n securityAlertsApiClient,\n analyticsService,\n logger,\n trackError,\n }: BaseTransactionScanServiceOptions) {\n this.securityAlertsApiClient = securityAlertsApiClient;\n this.analyticsService = analyticsService;\n this.logger = logger;\n this.trackError = trackError;\n }\n\n /**\n * The single scan entry point every network snap implements.\n *\n * Parameters are chain-specific and intentionally unconstrained here;\n * implementations resolve to the mapped scan result, or `null` when the\n * scan could not be performed. Analytics reporting is the implementation's\n * responsibility, via {@link trackScanCompleted} / {@link trackScanFailed}.\n *\n * @param params - The chain-specific scan parameters.\n * @returns The mapped scan result, or `null` when the scan failed.\n */\n abstract scanTransaction(\n params: unknown,\n ): Promise<SecurityScanOutcome | null>;\n\n /**\n * Tracks the analytics events of a completed scan: always a completed scan\n * event, plus an alert-detected event when the verdict is reportable.\n *\n * Analytics are only tracked when the scan params carry an account type.\n *\n * @param params - The origin and account the scan belongs to.\n * @param scan - The mapped scan result.\n */\n protected async trackScanCompleted(\n params: BaseScanParams,\n scan: SecurityScanOutcome,\n ): Promise<void> {\n const { origin, accountType, scope } = params;\n\n if (!accountType) {\n return;\n }\n\n const securityAlert = deriveSecurityAlert(scan.validation?.type);\n\n await this.analyticsService.trackSecurityScanCompleted({\n origin,\n accountType,\n chainIdCaip: scope,\n scanStatus: scan.status,\n hasSecurityAlerts: Boolean(securityAlert),\n });\n\n if (!securityAlert) {\n return;\n }\n\n const reason = scan.validation?.reason ?? null;\n\n await this.analyticsService.trackSecurityAlertDetected({\n origin,\n accountType,\n chainIdCaip: scope,\n securityAlertResponse: securityAlert,\n securityAlertReason: reason,\n securityAlertDescription: getSecurityAlertDescription(reason),\n });\n }\n\n /**\n * Tracks the analytics events of a failed scan: a completed scan event with\n * an error status, when the scan is tied to an account.\n *\n * @param params - The origin and account the scan belongs to.\n */\n protected async trackScanFailed(params: BaseScanParams): Promise<void> {\n const { origin, accountType, scope } = params;\n\n if (!accountType) {\n return;\n }\n\n await this.analyticsService.trackSecurityScanCompleted({\n origin,\n accountType,\n chainIdCaip: scope,\n scanStatus: SecurityAlertsScanStatus.ERROR,\n hasSecurityAlerts: false,\n });\n }\n}\n"]}
@@ -0,0 +1,65 @@
1
+ import type { SecurityAlertsApiClient } from "../../clients/security-alerts-api/SecurityAlertsApiClient.mjs";
2
+ import type { TrackErrorFn } from "../../utils/errors/index.mjs";
3
+ import type { Logger } from "../../utils/logger/Logger.mjs";
4
+ import type { AnalyticsService } from "../analytics/AnalyticsService.mjs";
5
+ /**
6
+ * Scan options recognized by the Security Alerts API scan endpoints.
7
+ *
8
+ * `simulation` requests an on-chain simulation of the transaction (asset
9
+ * diffs); `validation` requests a security verdict.
10
+ */
11
+ export declare const SECURITY_ALERTS_SCAN_OPTIONS: readonly ["simulation", "validation"];
12
+ export type SecurityAlertsScanOption = (typeof SECURITY_ALERTS_SCAN_OPTIONS)[number];
13
+ /** Status of a completed security scan. */
14
+ export declare const SecurityAlertsScanStatus: {
15
+ readonly SUCCESS: "SUCCESS";
16
+ readonly ERROR: "ERROR";
17
+ };
18
+ export type SecurityAlertsScanStatus = (typeof SecurityAlertsScanStatus)[keyof typeof SecurityAlertsScanStatus];
19
+ /**
20
+ * Verdicts emitted by the Security Alerts API validation.
21
+ *
22
+ * Shared by all network snaps so scan results and analytics agree on the
23
+ * verdict vocabulary.
24
+ */
25
+ export declare const SecurityAlertResponse: {
26
+ readonly Benign: "Benign";
27
+ readonly Warning: "Warning";
28
+ readonly Malicious: "Malicious";
29
+ readonly Error: "Error";
30
+ };
31
+ export type SecurityAlertResponse = (typeof SecurityAlertResponse)[keyof typeof SecurityAlertResponse];
32
+ /**
33
+ * Parameters identifying the origin and account a scan belongs to, resolved
34
+ * by the calling snap for scan analytics.
35
+ */
36
+ export type BaseScanParams = {
37
+ /** The origin of the scan request. */
38
+ origin: string;
39
+ /** The CAIP-2 chain id of the scanned transaction. */
40
+ scope: string;
41
+ /** Type of the keyring account the scanned transaction belongs to. */
42
+ accountType?: string;
43
+ };
44
+ /**
45
+ * Minimal shape the analytics methods read from a completed scan result.
46
+ * Chain-specific scan result types must structurally satisfy it.
47
+ */
48
+ export type SecurityScanOutcome = {
49
+ status: string;
50
+ validation?: {
51
+ type?: string | null;
52
+ reason?: string | null;
53
+ } | null;
54
+ };
55
+ /**
56
+ * Options for a {@link BaseTransactionScanService} constructor.
57
+ */
58
+ export type BaseTransactionScanServiceOptions = {
59
+ securityAlertsApiClient: SecurityAlertsApiClient;
60
+ analyticsService: AnalyticsService;
61
+ logger: Logger;
62
+ /** Reports unexpected scan failures to Sentry. */
63
+ trackError: TrackErrorFn;
64
+ };
65
+ //# sourceMappingURL=types.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.mts","sourceRoot":"","sources":["../../../src/services/security-alerts/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,uBAAuB,EAAE,sEAAkE;AACzG,OAAO,KAAK,EAAE,YAAY,EAAE,qCAA2B;AACvD,OAAO,KAAK,EAAE,MAAM,EAAE,sCAAkC;AACxD,OAAO,KAAK,EAAE,gBAAgB,EAAE,0CAAsC;AAEtE;;;;;GAKG;AACH,eAAO,MAAM,4BAA4B,uCAG/B,CAAC;AAEX,MAAM,MAAM,wBAAwB,GAClC,CAAC,OAAO,4BAA4B,CAAC,CAAC,MAAM,CAAC,CAAC;AAEhD,2CAA2C;AAC3C,eAAO,MAAM,wBAAwB;;;CAG3B,CAAC;AAEX,MAAM,MAAM,wBAAwB,GAClC,CAAC,OAAO,wBAAwB,CAAC,CAAC,MAAM,OAAO,wBAAwB,CAAC,CAAC;AAE3E;;;;;GAKG;AACH,eAAO,MAAM,qBAAqB;;;;;CAKxB,CAAC;AAEX,MAAM,MAAM,qBAAqB,GAC/B,CAAC,OAAO,qBAAqB,CAAC,CAAC,MAAM,OAAO,qBAAqB,CAAC,CAAC;AAErE;;;GAGG;AACH,MAAM,MAAM,cAAc,GAAG;IAC3B,sCAAsC;IACtC,MAAM,EAAE,MAAM,CAAC;IACf,sDAAsD;IACtD,KAAK,EAAE,MAAM,CAAC;IACd,sEAAsE;IACtE,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB,CAAC;AAEF;;;GAGG;AACH,MAAM,MAAM,mBAAmB,GAAG;IAChC,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,CAAC,EAAE;QACX,IAAI,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;QACrB,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;KACxB,GAAG,IAAI,CAAC;CACV,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,iCAAiC,GAAG;IAC9C,uBAAuB,EAAE,uBAAuB,CAAC;IACjD,gBAAgB,EAAE,gBAAgB,CAAC;IACnC,MAAM,EAAE,MAAM,CAAC;IACf,kDAAkD;IAClD,UAAU,EAAE,YAAY,CAAC;CAC1B,CAAC"}
@@ -0,0 +1,28 @@
1
+ /**
2
+ * Scan options recognized by the Security Alerts API scan endpoints.
3
+ *
4
+ * `simulation` requests an on-chain simulation of the transaction (asset
5
+ * diffs); `validation` requests a security verdict.
6
+ */
7
+ export const SECURITY_ALERTS_SCAN_OPTIONS = [
8
+ 'simulation',
9
+ 'validation',
10
+ ];
11
+ /** Status of a completed security scan. */
12
+ export const SecurityAlertsScanStatus = {
13
+ SUCCESS: 'SUCCESS',
14
+ ERROR: 'ERROR',
15
+ };
16
+ /**
17
+ * Verdicts emitted by the Security Alerts API validation.
18
+ *
19
+ * Shared by all network snaps so scan results and analytics agree on the
20
+ * verdict vocabulary.
21
+ */
22
+ export const SecurityAlertResponse = {
23
+ Benign: 'Benign',
24
+ Warning: 'Warning',
25
+ Malicious: 'Malicious',
26
+ Error: 'Error',
27
+ };
28
+ //# sourceMappingURL=types.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.mjs","sourceRoot":"","sources":["../../../src/services/security-alerts/types.ts"],"names":[],"mappings":"AAKA;;;;;GAKG;AACH,MAAM,CAAC,MAAM,4BAA4B,GAAG;IAC1C,YAAY;IACZ,YAAY;CACJ,CAAC;AAKX,2CAA2C;AAC3C,MAAM,CAAC,MAAM,wBAAwB,GAAG;IACtC,OAAO,EAAE,SAAS;IAClB,KAAK,EAAE,OAAO;CACN,CAAC;AAKX;;;;;GAKG;AACH,MAAM,CAAC,MAAM,qBAAqB,GAAG;IACnC,MAAM,EAAE,QAAQ;IAChB,OAAO,EAAE,SAAS;IAClB,SAAS,EAAE,WAAW;IACtB,KAAK,EAAE,OAAO;CACN,CAAC","sourcesContent":["import type { SecurityAlertsApiClient } from '../../clients/security-alerts-api/SecurityAlertsApiClient';\nimport type { TrackErrorFn } from '../../utils/errors';\nimport type { Logger } from '../../utils/logger/Logger';\nimport type { AnalyticsService } from '../analytics/AnalyticsService';\n\n/**\n * Scan options recognized by the Security Alerts API scan endpoints.\n *\n * `simulation` requests an on-chain simulation of the transaction (asset\n * diffs); `validation` requests a security verdict.\n */\nexport const SECURITY_ALERTS_SCAN_OPTIONS = [\n 'simulation',\n 'validation',\n] as const;\n\nexport type SecurityAlertsScanOption =\n (typeof SECURITY_ALERTS_SCAN_OPTIONS)[number];\n\n/** Status of a completed security scan. */\nexport const SecurityAlertsScanStatus = {\n SUCCESS: 'SUCCESS',\n ERROR: 'ERROR',\n} as const;\n\nexport type SecurityAlertsScanStatus =\n (typeof SecurityAlertsScanStatus)[keyof typeof SecurityAlertsScanStatus];\n\n/**\n * Verdicts emitted by the Security Alerts API validation.\n *\n * Shared by all network snaps so scan results and analytics agree on the\n * verdict vocabulary.\n */\nexport const SecurityAlertResponse = {\n Benign: 'Benign',\n Warning: 'Warning',\n Malicious: 'Malicious',\n Error: 'Error',\n} as const;\n\nexport type SecurityAlertResponse =\n (typeof SecurityAlertResponse)[keyof typeof SecurityAlertResponse];\n\n/**\n * Parameters identifying the origin and account a scan belongs to, resolved\n * by the calling snap for scan analytics.\n */\nexport type BaseScanParams = {\n /** The origin of the scan request. */\n origin: string;\n /** The CAIP-2 chain id of the scanned transaction. */\n scope: string;\n /** Type of the keyring account the scanned transaction belongs to. */\n accountType?: string;\n};\n\n/**\n * Minimal shape the analytics methods read from a completed scan result.\n * Chain-specific scan result types must structurally satisfy it.\n */\nexport type SecurityScanOutcome = {\n status: string;\n validation?: {\n type?: string | null;\n reason?: string | null;\n } | null;\n};\n\n/**\n * Options for a {@link BaseTransactionScanService} constructor.\n */\nexport type BaseTransactionScanServiceOptions = {\n securityAlertsApiClient: SecurityAlertsApiClient;\n analyticsService: AnalyticsService;\n logger: Logger;\n /** Reports unexpected scan failures to Sentry. */\n trackError: TrackErrorFn;\n};\n"]}
@@ -0,0 +1,18 @@
1
+ /**
2
+ * Resolves the human-readable description of a security alert reason.
3
+ *
4
+ * @param reason - The Blockaid validation reason, if any.
5
+ * @returns A human-readable description of the alert.
6
+ */
7
+ export declare function getSecurityAlertDescription(reason?: string | null): string;
8
+ /**
9
+ * Resolves the analytics-reportable alert for a validation verdict.
10
+ *
11
+ * A verdict is reportable when the validation produced a real classification:
12
+ * not missing, not benign, and not an error (which means no verdict).
13
+ *
14
+ * @param type - The validation verdict, if any.
15
+ * @returns The reportable alert type, or null when there is nothing to report.
16
+ */
17
+ export declare function deriveSecurityAlert(type?: string | null): string | null;
18
+ //# sourceMappingURL=utils.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.d.mts","sourceRoot":"","sources":["../../../src/services/security-alerts/utils.ts"],"names":[],"mappings":"AAgCA;;;;;GAKG;AACH,wBAAgB,2BAA2B,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,GAAG,MAAM,CAO1E;AAED;;;;;;;;GAQG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,CAAC,EAAE,MAAM,GAAG,IAAI,GAAG,MAAM,GAAG,IAAI,CAMvE"}
@@ -0,0 +1,50 @@
1
+ import { SecurityAlertResponse } from "./types.mjs";
2
+ /**
3
+ * Human-readable description suffixes for Blockaid validation reasons, shared
4
+ * by all network snaps so analytics descriptions agree across chains.
5
+ *
6
+ * Reasons missing from this table fall back to the raw reason.
7
+ *
8
+ * Reference: https://docs.blockaid.io/reference/response-reference
9
+ */
10
+ const SECURITY_ALERT_REASON_DESCRIPTIONS = {
11
+ unfair_trade: "Unfair trade of assets, without adequate compensation to the owner's account",
12
+ transfer_farming: "Substantial transfer of the account's assets to untrusted entities",
13
+ writable_accounts_farming: 'Transaction exposes unused writable account, can be utilized in BIT-FLIP attacks patterns',
14
+ native_ownership_change: 'The account transferred ownership of its native SOL to untrusted entities',
15
+ spl_token_ownership_change: 'The account transferred ownership of its SPL tokens to untrusted entities',
16
+ exposure_farming: 'The account delegates ownership, thereby exposing its assets to untrusted spenders',
17
+ known_attacker: "A known attacker's account is involved in the transaction",
18
+ invalid_signature: 'One of the transactions provided contains non valid signatures, that can lead misleading simulation results',
19
+ honeypot: 'The account invests funds in a token that is part of an orchestrated honeypot scheme',
20
+ other: 'The transaction was marked as malicious for other reason, further details would be described in features field',
21
+ };
22
+ /**
23
+ * Resolves the human-readable description of a security alert reason.
24
+ *
25
+ * @param reason - The Blockaid validation reason, if any.
26
+ * @returns A human-readable description of the alert.
27
+ */
28
+ export function getSecurityAlertDescription(reason) {
29
+ const suffix = SECURITY_ALERT_REASON_DESCRIPTIONS[reason ?? ''] ??
30
+ reason ??
31
+ 'Unknown reason';
32
+ return `Security alert: ${suffix}`;
33
+ }
34
+ /**
35
+ * Resolves the analytics-reportable alert for a validation verdict.
36
+ *
37
+ * A verdict is reportable when the validation produced a real classification:
38
+ * not missing, not benign, and not an error (which means no verdict).
39
+ *
40
+ * @param type - The validation verdict, if any.
41
+ * @returns The reportable alert type, or null when there is nothing to report.
42
+ */
43
+ export function deriveSecurityAlert(type) {
44
+ return type &&
45
+ type !== SecurityAlertResponse.Benign &&
46
+ type !== SecurityAlertResponse.Error
47
+ ? type
48
+ : null;
49
+ }
50
+ //# sourceMappingURL=utils.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.mjs","sourceRoot":"","sources":["../../../src/services/security-alerts/utils.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,qBAAqB,EAAE,oBAAgB;AAEhD;;;;;;;GAOG;AACH,MAAM,kCAAkC,GAA2B;IACjE,YAAY,EACV,8EAA8E;IAChF,gBAAgB,EACd,oEAAoE;IACtE,yBAAyB,EACvB,2FAA2F;IAC7F,uBAAuB,EACrB,2EAA2E;IAC7E,0BAA0B,EACxB,2EAA2E;IAC7E,gBAAgB,EACd,oFAAoF;IACtF,cAAc,EAAE,2DAA2D;IAC3E,iBAAiB,EACf,6GAA6G;IAC/G,QAAQ,EACN,sFAAsF;IACxF,KAAK,EACH,gHAAgH;CACnH,CAAC;AAEF;;;;;GAKG;AACH,MAAM,UAAU,2BAA2B,CAAC,MAAsB;IAChE,MAAM,MAAM,GACV,kCAAkC,CAAC,MAAM,IAAI,EAAE,CAAC;QAChD,MAAM;QACN,gBAAgB,CAAC;IAEnB,OAAO,mBAAmB,MAAM,EAAE,CAAC;AACrC,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,mBAAmB,CAAC,IAAoB;IACtD,OAAO,IAAI;QACT,IAAI,KAAK,qBAAqB,CAAC,MAAM;QACrC,IAAI,KAAK,qBAAqB,CAAC,KAAK;QACpC,CAAC,CAAC,IAAI;QACN,CAAC,CAAC,IAAI,CAAC;AACX,CAAC","sourcesContent":["import { SecurityAlertResponse } from './types';\n\n/**\n * Human-readable description suffixes for Blockaid validation reasons, shared\n * by all network snaps so analytics descriptions agree across chains.\n *\n * Reasons missing from this table fall back to the raw reason.\n *\n * Reference: https://docs.blockaid.io/reference/response-reference\n */\nconst SECURITY_ALERT_REASON_DESCRIPTIONS: Record<string, string> = {\n unfair_trade:\n \"Unfair trade of assets, without adequate compensation to the owner's account\",\n transfer_farming:\n \"Substantial transfer of the account's assets to untrusted entities\",\n writable_accounts_farming:\n 'Transaction exposes unused writable account, can be utilized in BIT-FLIP attacks patterns',\n native_ownership_change:\n 'The account transferred ownership of its native SOL to untrusted entities',\n spl_token_ownership_change:\n 'The account transferred ownership of its SPL tokens to untrusted entities',\n exposure_farming:\n 'The account delegates ownership, thereby exposing its assets to untrusted spenders',\n known_attacker: \"A known attacker's account is involved in the transaction\",\n invalid_signature:\n 'One of the transactions provided contains non valid signatures, that can lead misleading simulation results',\n honeypot:\n 'The account invests funds in a token that is part of an orchestrated honeypot scheme',\n other:\n 'The transaction was marked as malicious for other reason, further details would be described in features field',\n};\n\n/**\n * Resolves the human-readable description of a security alert reason.\n *\n * @param reason - The Blockaid validation reason, if any.\n * @returns A human-readable description of the alert.\n */\nexport function getSecurityAlertDescription(reason?: string | null): string {\n const suffix =\n SECURITY_ALERT_REASON_DESCRIPTIONS[reason ?? ''] ??\n reason ??\n 'Unknown reason';\n\n return `Security alert: ${suffix}`;\n}\n\n/**\n * Resolves the analytics-reportable alert for a validation verdict.\n *\n * A verdict is reportable when the validation produced a real classification:\n * not missing, not benign, and not an error (which means no verdict).\n *\n * @param type - The validation verdict, if any.\n * @returns The reportable alert type, or null when there is nothing to report.\n */\nexport function deriveSecurityAlert(type?: string | null): string | null {\n return type &&\n type !== SecurityAlertResponse.Benign &&\n type !== SecurityAlertResponse.Error\n ? type\n : null;\n}\n"]}
@@ -0,0 +1,20 @@
1
+ /**
2
+ * Error thrown when an HTTP request to an API fails: the request could not
3
+ * be completed, the API responded with a non-2xx status, or a 2xx response
4
+ * body could not be parsed as JSON.
5
+ *
6
+ * The original error, when there is one, is available as `cause` (e.g. a
7
+ * `TypeError` for a network failure or a `SyntaxError` for an unparseable
8
+ * response body).
9
+ */
10
+ export declare class HttpError extends Error {
11
+ /**
12
+ * Construct a new HTTP error.
13
+ *
14
+ * @param message - The error message, e.g. `'HTTP error! status: 503'`.
15
+ * @param options - Additional error options.
16
+ * @param options.cause - The underlying error that caused the failure, if any.
17
+ */
18
+ constructor(message: string, options?: ErrorOptions);
19
+ }
20
+ //# sourceMappingURL=httpError.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"httpError.d.mts","sourceRoot":"","sources":["../../../src/utils/errors/httpError.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,qBAAa,SAAU,SAAQ,KAAK;IAClC;;;;;;OAMG;gBACS,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,YAAY;CAIpD"}
@@ -0,0 +1,23 @@
1
+ /**
2
+ * Error thrown when an HTTP request to an API fails: the request could not
3
+ * be completed, the API responded with a non-2xx status, or a 2xx response
4
+ * body could not be parsed as JSON.
5
+ *
6
+ * The original error, when there is one, is available as `cause` (e.g. a
7
+ * `TypeError` for a network failure or a `SyntaxError` for an unparseable
8
+ * response body).
9
+ */
10
+ export class HttpError extends Error {
11
+ /**
12
+ * Construct a new HTTP error.
13
+ *
14
+ * @param message - The error message, e.g. `'HTTP error! status: 503'`.
15
+ * @param options - Additional error options.
16
+ * @param options.cause - The underlying error that caused the failure, if any.
17
+ */
18
+ constructor(message, options) {
19
+ super(message, options);
20
+ this.name = 'HttpError';
21
+ }
22
+ }
23
+ //# sourceMappingURL=httpError.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"httpError.mjs","sourceRoot":"","sources":["../../../src/utils/errors/httpError.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,MAAM,OAAO,SAAU,SAAQ,KAAK;IAClC;;;;;;OAMG;IACH,YAAY,OAAe,EAAE,OAAsB;QACjD,KAAK,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;QACxB,IAAI,CAAC,IAAI,GAAG,WAAW,CAAC;IAC1B,CAAC;CACF","sourcesContent":["/**\n * Error thrown when an HTTP request to an API fails: the request could not\n * be completed, the API responded with a non-2xx status, or a 2xx response\n * body could not be parsed as JSON.\n *\n * The original error, when there is one, is available as `cause` (e.g. a\n * `TypeError` for a network failure or a `SyntaxError` for an unparseable\n * response body).\n */\nexport class HttpError extends Error {\n /**\n * Construct a new HTTP error.\n *\n * @param message - The error message, e.g. `'HTTP error! status: 503'`.\n * @param options - Additional error options.\n * @param options.cause - The underlying error that caused the failure, if any.\n */\n constructor(message: string, options?: ErrorOptions) {\n super(message, options);\n this.name = 'HttpError';\n }\n}\n"]}
@@ -1,4 +1,5 @@
1
1
  export { createSnapErrorHandling, createTrackError } from "./trackError.mjs";
2
+ export { HttpError } from "./httpError.mjs";
2
3
  export { SynchronizationError, formatAccountSyncFailures, getSyncFailuresFromSettledResult, } from "./syncError.mjs";
3
4
  export type { AccountSyncFailure } from "./syncError.mjs";
4
5
  export { createWithCatchAndThrowSnapError, normalizeError } from "./errors.mjs";
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.mts","sourceRoot":"","sources":["../../../src/utils/errors/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,uBAAuB,EAAE,gBAAgB,EAAE,yBAAqB;AACzE,OAAO,EACL,oBAAoB,EACpB,yBAAyB,EACzB,gCAAgC,GACjC,wBAAoB;AACrB,YAAY,EAAE,kBAAkB,EAAE,wBAAoB;AACtD,OAAO,EAAE,gCAAgC,EAAE,cAAc,EAAE,qBAAiB;AAC5E,OAAO,EAAE,eAAe,EAAE,8BAA0B;AACpD,OAAO,EAAE,cAAc,EAAE,2BAAuB;AAChD,YAAY,EACV,8BAA8B,EAC9B,uBAAuB,EACvB,yBAAyB,EACzB,kBAAkB,EAClB,qBAAqB,EACrB,yBAAyB,GAC1B,yBAAqB;AACtB,YAAY,EACV,uCAAuC,EACvC,UAAU,EACV,gBAAgB,EAChB,YAAY,GACb,qBAAiB;AAClB,YAAY,EAAE,YAAY,EAAE,2BAAuB"}
1
+ {"version":3,"file":"index.d.mts","sourceRoot":"","sources":["../../../src/utils/errors/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,uBAAuB,EAAE,gBAAgB,EAAE,yBAAqB;AACzE,OAAO,EAAE,SAAS,EAAE,wBAAoB;AACxC,OAAO,EACL,oBAAoB,EACpB,yBAAyB,EACzB,gCAAgC,GACjC,wBAAoB;AACrB,YAAY,EAAE,kBAAkB,EAAE,wBAAoB;AACtD,OAAO,EAAE,gCAAgC,EAAE,cAAc,EAAE,qBAAiB;AAC5E,OAAO,EAAE,eAAe,EAAE,8BAA0B;AACpD,OAAO,EAAE,cAAc,EAAE,2BAAuB;AAChD,YAAY,EACV,8BAA8B,EAC9B,uBAAuB,EACvB,yBAAyB,EACzB,kBAAkB,EAClB,qBAAqB,EACrB,yBAAyB,GAC1B,yBAAqB;AACtB,YAAY,EACV,uCAAuC,EACvC,UAAU,EACV,gBAAgB,EAChB,YAAY,GACb,qBAAiB;AAClB,YAAY,EAAE,YAAY,EAAE,2BAAuB"}
@@ -1,4 +1,5 @@
1
1
  export { createSnapErrorHandling, createTrackError } from "./trackError.mjs";
2
+ export { HttpError } from "./httpError.mjs";
2
3
  export { SynchronizationError, formatAccountSyncFailures, getSyncFailuresFromSettledResult } from "./syncError.mjs";
3
4
  export { createWithCatchAndThrowSnapError, normalizeError } from "./errors.mjs";
4
5
  export { stringifyReason } from "./stringifyReason.mjs";
@@ -1 +1 @@
1
- {"version":3,"file":"index.mjs","sourceRoot":"","sources":["../../../src/utils/errors/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,uBAAuB,EAAE,gBAAgB,EAAE,yBAAqB;AACzE,OAAO,EACL,oBAAoB,EACpB,yBAAyB,EACzB,gCAAgC,EACjC,wBAAoB;AAErB,OAAO,EAAE,gCAAgC,EAAE,cAAc,EAAE,qBAAiB;AAC5E,OAAO,EAAE,eAAe,EAAE,8BAA0B;AACpD,OAAO,EAAE,cAAc,EAAE,2BAAuB","sourcesContent":["export { createSnapErrorHandling, createTrackError } from './trackError';\nexport {\n SynchronizationError,\n formatAccountSyncFailures,\n getSyncFailuresFromSettledResult,\n} from './syncError';\nexport type { AccountSyncFailure } from './syncError';\nexport { createWithCatchAndThrowSnapError, normalizeError } from './errors';\nexport { stringifyReason } from './stringifyReason';\nexport { isSnapRpcError } from './snapRpcError';\nexport type {\n CreateSnapErrorHandlingOptions,\n CreateTrackErrorOptions,\n PrepareErrorForTrackingFn,\n ShouldTrackErrorFn,\n SnapTrackErrorRequest,\n TrackErrorCapableProvider,\n} from './trackError';\nexport type {\n CreateWithCatchAndThrowSnapErrorOptions,\n LogErrorFn,\n NormalizeErrorFn,\n TrackErrorFn,\n} from './errors';\nexport type { SnapRpcError } from './snapRpcError';\n"]}
1
+ {"version":3,"file":"index.mjs","sourceRoot":"","sources":["../../../src/utils/errors/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,uBAAuB,EAAE,gBAAgB,EAAE,yBAAqB;AACzE,OAAO,EAAE,SAAS,EAAE,wBAAoB;AACxC,OAAO,EACL,oBAAoB,EACpB,yBAAyB,EACzB,gCAAgC,EACjC,wBAAoB;AAErB,OAAO,EAAE,gCAAgC,EAAE,cAAc,EAAE,qBAAiB;AAC5E,OAAO,EAAE,eAAe,EAAE,8BAA0B;AACpD,OAAO,EAAE,cAAc,EAAE,2BAAuB","sourcesContent":["export { createSnapErrorHandling, createTrackError } from './trackError';\nexport { HttpError } from './httpError';\nexport {\n SynchronizationError,\n formatAccountSyncFailures,\n getSyncFailuresFromSettledResult,\n} from './syncError';\nexport type { AccountSyncFailure } from './syncError';\nexport { createWithCatchAndThrowSnapError, normalizeError } from './errors';\nexport { stringifyReason } from './stringifyReason';\nexport { isSnapRpcError } from './snapRpcError';\nexport type {\n CreateSnapErrorHandlingOptions,\n CreateTrackErrorOptions,\n PrepareErrorForTrackingFn,\n ShouldTrackErrorFn,\n SnapTrackErrorRequest,\n TrackErrorCapableProvider,\n} from './trackError';\nexport type {\n CreateWithCatchAndThrowSnapErrorOptions,\n LogErrorFn,\n NormalizeErrorFn,\n TrackErrorFn,\n} from './errors';\nexport type { SnapRpcError } from './snapRpcError';\n"]}
@@ -0,0 +1,60 @@
1
+ import type { ServicePolicy } from "@metamask/base-data-service";
2
+ import type { FetchPolicyError } from "./createFetchPolicy.mjs";
3
+ /**
4
+ * The minimal policy surface `executeWithFetchPolicy` and `fetchWithPolicy`
5
+ * accept: the `execute` method of a policy created by
6
+ * {@link createFetchPolicy}.
7
+ */
8
+ export type FetchPolicy = Pick<ServicePolicy, 'execute'>;
9
+ /**
10
+ * Parse a `Retry-After` header value as milliseconds.
11
+ *
12
+ * @param value - The header value: a delay in seconds or an HTTP date.
13
+ * @returns The delay in milliseconds, or `undefined` if the value is invalid.
14
+ */
15
+ export declare function parseRetryAfter(value: unknown): number | undefined;
16
+ /**
17
+ * Execute a transport-only operation through a fetch policy, mapping errors to
18
+ * the shape the policy decides on.
19
+ *
20
+ * The operation must contain only transport work: a fetch, a status check and
21
+ * a body read. Parsing and validation belong outside it, so their errors
22
+ * propagate unchanged instead of being counted as failures.
23
+ *
24
+ * - `SyntaxError` and abort errors pass through unchanged: the policy must not
25
+ * retry or count them.
26
+ * - Errors already in the policy shape (with an `httpStatus`, or a network or
27
+ * timeout name) pass through unchanged.
28
+ * - Any other error is mapped with `mapError`, which defaults to treating it
29
+ * as a network failure. The catch-all is intentional: real `fetch` network
30
+ * failures are not recognisable by name or code across runtimes, so they can
31
+ * only be identified by being the residual case.
32
+ *
33
+ * @param policy - The shared fetch policy.
34
+ * @param operation - The transport operation.
35
+ * @param mapError - An optional mapper for unrecognized errors. Use it to
36
+ * extract statuses from protocol-specific error shapes (e.g. axios responses
37
+ * or Solana transport errors).
38
+ * @param signal - Optional caller abort signal. When aborted, skips or
39
+ * interrupts retry backoff immediately without another transport invocation.
40
+ * @returns The operation result.
41
+ */
42
+ export declare function executeWithFetchPolicy<Result>(policy: FetchPolicy, operation: () => Promise<Result>, mapError?: (error: unknown) => FetchPolicyError, signal?: AbortSignal | null): Promise<Result>;
43
+ /**
44
+ * Fetch a URL through a fetch policy, throwing a {@link FetchPolicyError} on a
45
+ * non-2xx response and returning the body as text.
46
+ *
47
+ * This is the common shape of every policy-wrapped HTTP call in the snaps: a
48
+ * fetch with a timeout, a status check that turns a non-2xx response into a
49
+ * policy error (honouring `Retry-After`), and a body read inside the policy so
50
+ * a truncated response is retried too.
51
+ *
52
+ * @param policy - The shared fetch policy.
53
+ * @param url - The URL to fetch.
54
+ * @param init - Optional fetch options. A caller-provided `signal` replaces
55
+ * the default timeout signal.
56
+ * @param fetchImpl - The fetch implementation, defaulting to `globalThis.fetch`.
57
+ * @returns The response body as text.
58
+ */
59
+ export declare function fetchWithPolicy(policy: FetchPolicy, url: string, init?: RequestInit, fetchImpl?: typeof globalThis.fetch): Promise<string>;
60
+ //# sourceMappingURL=executeWithFetchPolicy.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"executeWithFetchPolicy.d.mts","sourceRoot":"","sources":["../../../src/utils/fetchPolicy/executeWithFetchPolicy.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,oCAAoC;AAEjE,OAAO,KAAK,EAAE,gBAAgB,EAAE,gCAA4B;AAM5D;;;;GAIG;AACH,MAAM,MAAM,WAAW,GAAG,IAAI,CAAC,aAAa,EAAE,SAAS,CAAC,CAAC;AAOzD;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,GAAG,SAAS,CAYlE;AAgED;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,wBAAsB,sBAAsB,CAAC,MAAM,EACjD,MAAM,EAAE,WAAW,EACnB,SAAS,EAAE,MAAM,OAAO,CAAC,MAAM,CAAC,EAChC,QAAQ,GAAE,CAAC,KAAK,EAAE,OAAO,KAAK,gBAAiC,EAC/D,MAAM,CAAC,EAAE,WAAW,GAAG,IAAI,GAC1B,OAAO,CAAC,MAAM,CAAC,CAuDjB;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAsB,eAAe,CACnC,MAAM,EAAE,WAAW,EACnB,GAAG,EAAE,MAAM,EACX,IAAI,CAAC,EAAE,WAAW,EAClB,SAAS,GAAE,OAAO,UAAU,CAAC,KAAwB,GACpD,OAAO,CAAC,MAAM,CAAC,CAoBjB"}
@@ -0,0 +1,182 @@
1
+ import { createFetchPolicyError, FetchPolicyErrorName } from "./createFetchPolicy.mjs";
2
+ /**
3
+ * The default timeout for a `fetchWithPolicy` request, in milliseconds.
4
+ */
5
+ const DEFAULT_TIMEOUT_MS = 10_000;
6
+ /**
7
+ * Parse a `Retry-After` header value as milliseconds.
8
+ *
9
+ * @param value - The header value: a delay in seconds or an HTTP date.
10
+ * @returns The delay in milliseconds, or `undefined` if the value is invalid.
11
+ */
12
+ export function parseRetryAfter(value) {
13
+ if (typeof value !== 'string') {
14
+ return undefined;
15
+ }
16
+ const seconds = Number(value);
17
+ if (Number.isFinite(seconds) && seconds >= 0) {
18
+ return seconds * 1000;
19
+ }
20
+ const date = Date.parse(value);
21
+ return Number.isNaN(date) ? undefined : Math.max(0, date - Date.now());
22
+ }
23
+ /**
24
+ * Convert an unrecognized error to a network failure.
25
+ *
26
+ * @param error - The upstream error.
27
+ * @returns The error in the policy shape.
28
+ */
29
+ function toNetworkError(error) {
30
+ return error instanceof Error
31
+ ? createFetchPolicyError(error.message, {
32
+ name: FetchPolicyErrorName.Network,
33
+ cause: error,
34
+ })
35
+ : createFetchPolicyError('Network request failed', {
36
+ name: FetchPolicyErrorName.Network,
37
+ cause: error,
38
+ });
39
+ }
40
+ function createAbortError() {
41
+ return Object.assign(new Error('The operation was aborted.'), {
42
+ name: 'AbortError',
43
+ });
44
+ }
45
+ function noop() {
46
+ // Intentionally empty.
47
+ }
48
+ /**
49
+ * Race a promise against an abort signal so caller cancellation interrupts
50
+ * retry backoff waits without waiting for the timer to expire.
51
+ *
52
+ * @param promise - The operation promise.
53
+ * @param signal - Optional abort signal from the caller.
54
+ * @returns The operation result, or rejects with the abort reason.
55
+ */
56
+ async function raceWithSignal(promise, signal) {
57
+ if (!signal) {
58
+ return promise;
59
+ }
60
+ let onAbort;
61
+ const abortPromise = new Promise((_resolve, reject) => {
62
+ onAbort = () => {
63
+ reject(createAbortError());
64
+ };
65
+ signal.addEventListener('abort', onAbort, { once: true });
66
+ if (signal.aborted) {
67
+ onAbort();
68
+ }
69
+ });
70
+ // Suppress unhandled rejection if `promise` settles after `abortPromise` wins.
71
+ promise.catch(noop);
72
+ try {
73
+ return await Promise.race([promise, abortPromise]);
74
+ }
75
+ finally {
76
+ signal.removeEventListener('abort', onAbort);
77
+ }
78
+ }
79
+ /**
80
+ * Execute a transport-only operation through a fetch policy, mapping errors to
81
+ * the shape the policy decides on.
82
+ *
83
+ * The operation must contain only transport work: a fetch, a status check and
84
+ * a body read. Parsing and validation belong outside it, so their errors
85
+ * propagate unchanged instead of being counted as failures.
86
+ *
87
+ * - `SyntaxError` and abort errors pass through unchanged: the policy must not
88
+ * retry or count them.
89
+ * - Errors already in the policy shape (with an `httpStatus`, or a network or
90
+ * timeout name) pass through unchanged.
91
+ * - Any other error is mapped with `mapError`, which defaults to treating it
92
+ * as a network failure. The catch-all is intentional: real `fetch` network
93
+ * failures are not recognisable by name or code across runtimes, so they can
94
+ * only be identified by being the residual case.
95
+ *
96
+ * @param policy - The shared fetch policy.
97
+ * @param operation - The transport operation.
98
+ * @param mapError - An optional mapper for unrecognized errors. Use it to
99
+ * extract statuses from protocol-specific error shapes (e.g. axios responses
100
+ * or Solana transport errors).
101
+ * @param signal - Optional caller abort signal. When aborted, skips or
102
+ * interrupts retry backoff immediately without another transport invocation.
103
+ * @returns The operation result.
104
+ */
105
+ export async function executeWithFetchPolicy(policy, operation, mapError = toNetworkError, signal) {
106
+ // Skip policy execution entirely if the caller already aborted before entry.
107
+ if (signal?.aborted) {
108
+ throw signal.reason ?? createAbortError();
109
+ }
110
+ try {
111
+ return await raceWithSignal(policy.execute(async () => {
112
+ // Guard against Cockatiel waking from a backoff timer after caller abort.
113
+ if (signal?.aborted) {
114
+ throw createAbortError();
115
+ }
116
+ try {
117
+ return await operation();
118
+ }
119
+ catch (error) {
120
+ // Normalize caller cancellation to an AbortError so the policy does
121
+ // not retry or count it toward the circuit breaker.
122
+ if (signal?.aborted) {
123
+ throw createAbortError();
124
+ }
125
+ // Parsing failures and explicit aborts are non-transient; pass through.
126
+ if (error instanceof SyntaxError ||
127
+ error?.name === 'AbortError') {
128
+ throw error;
129
+ }
130
+ // Errors already in the policy shape pass through unchanged.
131
+ if (error instanceof Error &&
132
+ (error.httpStatus !== undefined ||
133
+ error.name === FetchPolicyErrorName.Network ||
134
+ error.name === FetchPolicyErrorName.Timeout)) {
135
+ throw error;
136
+ }
137
+ // Map remaining protocol/transport errors into the policy shape.
138
+ throw mapError(error);
139
+ }
140
+ }, signal ?? undefined), signal ?? undefined);
141
+ }
142
+ catch (error) {
143
+ // Restore the caller's original abort reason if one was provided.
144
+ if (signal?.aborted) {
145
+ throw signal.reason ?? error;
146
+ }
147
+ throw error;
148
+ }
149
+ }
150
+ /**
151
+ * Fetch a URL through a fetch policy, throwing a {@link FetchPolicyError} on a
152
+ * non-2xx response and returning the body as text.
153
+ *
154
+ * This is the common shape of every policy-wrapped HTTP call in the snaps: a
155
+ * fetch with a timeout, a status check that turns a non-2xx response into a
156
+ * policy error (honouring `Retry-After`), and a body read inside the policy so
157
+ * a truncated response is retried too.
158
+ *
159
+ * @param policy - The shared fetch policy.
160
+ * @param url - The URL to fetch.
161
+ * @param init - Optional fetch options. A caller-provided `signal` replaces
162
+ * the default timeout signal.
163
+ * @param fetchImpl - The fetch implementation, defaulting to `globalThis.fetch`.
164
+ * @returns The response body as text.
165
+ */
166
+ export async function fetchWithPolicy(policy, url, init, fetchImpl = globalThis.fetch) {
167
+ const callerSignal = init?.signal;
168
+ return executeWithFetchPolicy(policy, async () => {
169
+ const response = await fetchImpl(url, {
170
+ ...init,
171
+ signal: callerSignal ?? AbortSignal.timeout(DEFAULT_TIMEOUT_MS),
172
+ });
173
+ if (!response.ok) {
174
+ throw createFetchPolicyError(`HTTP error! status: ${response.status}`, {
175
+ httpStatus: response.status,
176
+ retryAfterMs: parseRetryAfter(response.headers?.get('Retry-After')),
177
+ });
178
+ }
179
+ return response.text();
180
+ }, toNetworkError, callerSignal);
181
+ }
182
+ //# sourceMappingURL=executeWithFetchPolicy.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"executeWithFetchPolicy.mjs","sourceRoot":"","sources":["../../../src/utils/fetchPolicy/executeWithFetchPolicy.ts"],"names":[],"mappings":"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","sourcesContent":["import type { ServicePolicy } from '@metamask/base-data-service';\n\nimport type { FetchPolicyError } from './createFetchPolicy';\nimport {\n createFetchPolicyError,\n FetchPolicyErrorName,\n} from './createFetchPolicy';\n\n/**\n * The minimal policy surface `executeWithFetchPolicy` and `fetchWithPolicy`\n * accept: the `execute` method of a policy created by\n * {@link createFetchPolicy}.\n */\nexport type FetchPolicy = Pick<ServicePolicy, 'execute'>;\n\n/**\n * The default timeout for a `fetchWithPolicy` request, in milliseconds.\n */\nconst DEFAULT_TIMEOUT_MS = 10_000;\n\n/**\n * Parse a `Retry-After` header value as milliseconds.\n *\n * @param value - The header value: a delay in seconds or an HTTP date.\n * @returns The delay in milliseconds, or `undefined` if the value is invalid.\n */\nexport function parseRetryAfter(value: unknown): number | undefined {\n if (typeof value !== 'string') {\n return undefined;\n }\n\n const seconds = Number(value);\n if (Number.isFinite(seconds) && seconds >= 0) {\n return seconds * 1000;\n }\n\n const date = Date.parse(value);\n return Number.isNaN(date) ? undefined : Math.max(0, date - Date.now());\n}\n\n/**\n * Convert an unrecognized error to a network failure.\n *\n * @param error - The upstream error.\n * @returns The error in the policy shape.\n */\nfunction toNetworkError(error: unknown): FetchPolicyError {\n return error instanceof Error\n ? createFetchPolicyError(error.message, {\n name: FetchPolicyErrorName.Network,\n cause: error,\n })\n : createFetchPolicyError('Network request failed', {\n name: FetchPolicyErrorName.Network,\n cause: error,\n });\n}\n\nfunction createAbortError(): Error {\n return Object.assign(new Error('The operation was aborted.'), {\n name: 'AbortError',\n });\n}\n\nfunction noop(): void {\n // Intentionally empty.\n}\n\n/**\n * Race a promise against an abort signal so caller cancellation interrupts\n * retry backoff waits without waiting for the timer to expire.\n *\n * @param promise - The operation promise.\n * @param signal - Optional abort signal from the caller.\n * @returns The operation result, or rejects with the abort reason.\n */\nasync function raceWithSignal<Result>(\n promise: Promise<Result>,\n signal: AbortSignal | undefined,\n): Promise<Result> {\n if (!signal) {\n return promise;\n }\n let onAbort!: () => void;\n const abortPromise = new Promise<never>((_resolve, reject) => {\n onAbort = (): void => {\n reject(createAbortError());\n };\n signal.addEventListener('abort', onAbort, { once: true });\n if (signal.aborted) {\n onAbort();\n }\n });\n // Suppress unhandled rejection if `promise` settles after `abortPromise` wins.\n promise.catch(noop);\n try {\n return await Promise.race([promise, abortPromise]);\n } finally {\n signal.removeEventListener('abort', onAbort);\n }\n}\n\n/**\n * Execute a transport-only operation through a fetch policy, mapping errors to\n * the shape the policy decides on.\n *\n * The operation must contain only transport work: a fetch, a status check and\n * a body read. Parsing and validation belong outside it, so their errors\n * propagate unchanged instead of being counted as failures.\n *\n * - `SyntaxError` and abort errors pass through unchanged: the policy must not\n * retry or count them.\n * - Errors already in the policy shape (with an `httpStatus`, or a network or\n * timeout name) pass through unchanged.\n * - Any other error is mapped with `mapError`, which defaults to treating it\n * as a network failure. The catch-all is intentional: real `fetch` network\n * failures are not recognisable by name or code across runtimes, so they can\n * only be identified by being the residual case.\n *\n * @param policy - The shared fetch policy.\n * @param operation - The transport operation.\n * @param mapError - An optional mapper for unrecognized errors. Use it to\n * extract statuses from protocol-specific error shapes (e.g. axios responses\n * or Solana transport errors).\n * @param signal - Optional caller abort signal. When aborted, skips or\n * interrupts retry backoff immediately without another transport invocation.\n * @returns The operation result.\n */\nexport async function executeWithFetchPolicy<Result>(\n policy: FetchPolicy,\n operation: () => Promise<Result>,\n mapError: (error: unknown) => FetchPolicyError = toNetworkError,\n signal?: AbortSignal | null,\n): Promise<Result> {\n // Skip policy execution entirely if the caller already aborted before entry.\n if (signal?.aborted) {\n throw signal.reason ?? createAbortError();\n }\n\n try {\n return await raceWithSignal(\n policy.execute(async () => {\n // Guard against Cockatiel waking from a backoff timer after caller abort.\n if (signal?.aborted) {\n throw createAbortError();\n }\n\n try {\n return await operation();\n } catch (error) {\n // Normalize caller cancellation to an AbortError so the policy does\n // not retry or count it toward the circuit breaker.\n if (signal?.aborted) {\n throw createAbortError();\n }\n\n // Parsing failures and explicit aborts are non-transient; pass through.\n if (\n error instanceof SyntaxError ||\n (error as { name?: unknown } | undefined)?.name === 'AbortError'\n ) {\n throw error;\n }\n\n // Errors already in the policy shape pass through unchanged.\n if (\n error instanceof Error &&\n ((error as FetchPolicyError).httpStatus !== undefined ||\n error.name === FetchPolicyErrorName.Network ||\n error.name === FetchPolicyErrorName.Timeout)\n ) {\n throw error;\n }\n\n // Map remaining protocol/transport errors into the policy shape.\n throw mapError(error);\n }\n }, signal ?? undefined),\n signal ?? undefined,\n );\n } catch (error) {\n // Restore the caller's original abort reason if one was provided.\n if (signal?.aborted) {\n throw signal.reason ?? error;\n }\n\n throw error;\n }\n}\n\n/**\n * Fetch a URL through a fetch policy, throwing a {@link FetchPolicyError} on a\n * non-2xx response and returning the body as text.\n *\n * This is the common shape of every policy-wrapped HTTP call in the snaps: a\n * fetch with a timeout, a status check that turns a non-2xx response into a\n * policy error (honouring `Retry-After`), and a body read inside the policy so\n * a truncated response is retried too.\n *\n * @param policy - The shared fetch policy.\n * @param url - The URL to fetch.\n * @param init - Optional fetch options. A caller-provided `signal` replaces\n * the default timeout signal.\n * @param fetchImpl - The fetch implementation, defaulting to `globalThis.fetch`.\n * @returns The response body as text.\n */\nexport async function fetchWithPolicy(\n policy: FetchPolicy,\n url: string,\n init?: RequestInit,\n fetchImpl: typeof globalThis.fetch = globalThis.fetch,\n): Promise<string> {\n const callerSignal = init?.signal;\n return executeWithFetchPolicy(\n policy,\n async () => {\n const response = await fetchImpl(url, {\n ...init,\n signal: callerSignal ?? AbortSignal.timeout(DEFAULT_TIMEOUT_MS),\n });\n if (!response.ok) {\n throw createFetchPolicyError(`HTTP error! status: ${response.status}`, {\n httpStatus: response.status,\n retryAfterMs: parseRetryAfter(response.headers?.get('Retry-After')),\n });\n }\n return response.text();\n },\n toNetworkError,\n callerSignal,\n );\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@metamask-previews/snap-networks-utils",
3
- "version": "3.0.0-preview-a589290",
3
+ "version": "3.0.0-preview-de60dd1",
4
4
  "description": "Shared utilities for MetaMask network snaps",
5
5
  "keywords": [
6
6
  "Ethereum",