@metamask/shield-controller 4.0.0 → 4.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -7,11 +7,28 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [4.1.0]
11
+
12
+ ### Uncategorized
13
+
14
+ - Chore/w3a controllers linting ([#7455](https://github.com/MetaMask/core/pull/7455))
15
+ - Remove breaking designation from version bumps in changelog ([#7419](https://github.com/MetaMask/core/pull/7419))
16
+
17
+ ### Added
18
+
19
+ - Add optional constructor param, `captureException` to capture any errors during coverage API calls. ([#7555](https://github.com/MetaMask/core/pull/7555))
20
+
21
+ ### Changed
22
+
23
+ - Upgrade `@metamask/utils` from `^11.8.1` to `^11.9.0` ([#7511](https://github.com/MetaMask/core/pull/7511))
24
+ - Bump `@metamask/transaction-controller` from `^62.5.0` to `^62.7.0` ([#7430](https://github.com/MetaMask/core/pull/7430), [#7494](https://github.com/MetaMask/core/pull/7494))
25
+ - Bump `@metamask/controller-utils` from `^11.16.0` to `^11.17.0` ([#7534](https://github.com/MetaMask/core/pull/7534))
26
+
10
27
  ## [4.0.0]
11
28
 
12
29
  ### Changed
13
30
 
14
- - **BREAKING:** Bump `@metamask/signature-controller` from `^37.0.0` to `^38.0.0` ([#7330](https://github.com/MetaMask/core/pull/7330))
31
+ - Bump `@metamask/signature-controller` from `^37.0.0` to `^38.0.0` ([#7330](https://github.com/MetaMask/core/pull/7330))
15
32
  - Bump `@metamask/transaction-controller` from `^62.3.0` to `^62.5.0` ([#7257](https://github.com/MetaMask/core/pull/7257), [#7289](https://github.com/MetaMask/core/pull/7289), [#7325](https://github.com/MetaMask/core/pull/7325))
16
33
 
17
34
  ## [3.1.0]
@@ -169,7 +186,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
169
186
 
170
187
  - Initial release of the shield-controller package ([#6137](https://github.com/MetaMask/core/pull/6137)
171
188
 
172
- [Unreleased]: https://github.com/MetaMask/core/compare/@metamask/shield-controller@4.0.0...HEAD
189
+ [Unreleased]: https://github.com/MetaMask/core/compare/@metamask/shield-controller@4.1.0...HEAD
190
+ [4.1.0]: https://github.com/MetaMask/core/compare/@metamask/shield-controller@4.0.0...@metamask/shield-controller@4.1.0
173
191
  [4.0.0]: https://github.com/MetaMask/core/compare/@metamask/shield-controller@3.1.0...@metamask/shield-controller@4.0.0
174
192
  [3.1.0]: https://github.com/MetaMask/core/compare/@metamask/shield-controller@3.0.0...@metamask/shield-controller@3.1.0
175
193
  [3.0.0]: https://github.com/MetaMask/core/compare/@metamask/shield-controller@2.1.1...@metamask/shield-controller@3.0.0
@@ -10,7 +10,7 @@ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (
10
10
  if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
11
11
  return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
12
12
  };
13
- var _ShieldController_instances, _ShieldController_backend, _ShieldController_coverageHistoryLimit, _ShieldController_transactionHistoryLimit, _ShieldController_normalizeSignatureRequest, _ShieldController_transactionControllerStateChangeHandler, _ShieldController_signatureControllerStateChangeHandler, _ShieldController_started, _ShieldController_handleSignatureControllerStateChange, _ShieldController_handleTransactionControllerStateChange, _ShieldController_addCoverageResult, _ShieldController_logSignature, _ShieldController_logTransaction, _ShieldController_getCoverageStatus, _ShieldController_getLatestCoverageId;
13
+ var _ShieldController_instances, _ShieldController_backend, _ShieldController_coverageHistoryLimit, _ShieldController_transactionHistoryLimit, _ShieldController_normalizeSignatureRequest, _ShieldController_transactionControllerStateChangeHandler, _ShieldController_signatureControllerStateChangeHandler, _ShieldController_started, _ShieldController_handleSignatureControllerStateChange, _ShieldController_handleTransactionControllerStateChange, _ShieldController_addCoverageResult, _ShieldController_logSignature, _ShieldController_logTransaction, _ShieldController_getCoverageShownStatus, _ShieldController_getLatestCoverageId;
14
14
  Object.defineProperty(exports, "__esModule", { value: true });
15
15
  exports.ShieldController = exports.getDefaultShieldControllerState = void 0;
16
16
  const base_controller_1 = require("@metamask/base-controller");
@@ -78,6 +78,9 @@ class ShieldController extends base_controller_1.BaseController {
78
78
  __classPrivateFieldSet(this, _ShieldController_started, false, "f");
79
79
  __classPrivateFieldSet(this, _ShieldController_normalizeSignatureRequest, normalizeSignatureRequest, "f");
80
80
  }
81
+ /**
82
+ * Start the ShieldController and subscribe to the transaction and signature controller state changes.
83
+ */
81
84
  start() {
82
85
  if (__classPrivateFieldGet(this, _ShieldController_started, "f")) {
83
86
  return;
@@ -86,6 +89,9 @@ class ShieldController extends base_controller_1.BaseController {
86
89
  this.messenger.subscribe('TransactionController:stateChange', __classPrivateFieldGet(this, _ShieldController_transactionControllerStateChangeHandler, "f"), (state) => state.transactions);
87
90
  this.messenger.subscribe('SignatureController:stateChange', __classPrivateFieldGet(this, _ShieldController_signatureControllerStateChangeHandler, "f"), (state) => state.signatureRequests);
88
91
  }
92
+ /**
93
+ * Stop the ShieldController and unsubscribe from the transaction and signature controller state changes.
94
+ */
89
95
  stop() {
90
96
  if (!__classPrivateFieldGet(this, _ShieldController_started, "f")) {
91
97
  return;
@@ -235,7 +241,7 @@ _ShieldController_backend = new WeakMap(), _ShieldController_coverageHistoryLimi
235
241
  if (!signature) {
236
242
  throw new Error('Signature not found');
237
243
  }
238
- const { status } = __classPrivateFieldGet(this, _ShieldController_instances, "m", _ShieldController_getCoverageStatus).call(this, signatureRequest.id);
244
+ const { status } = __classPrivateFieldGet(this, _ShieldController_instances, "m", _ShieldController_getCoverageShownStatus).call(this, signatureRequest.id);
239
245
  await __classPrivateFieldGet(this, _ShieldController_backend, "f").logSignature({
240
246
  signatureRequest,
241
247
  signature,
@@ -250,14 +256,14 @@ _ShieldController_backend = new WeakMap(), _ShieldController_coverageHistoryLimi
250
256
  if (!rawTransactionHex) {
251
257
  throw new Error('Raw transaction hex not found');
252
258
  }
253
- const { status } = __classPrivateFieldGet(this, _ShieldController_instances, "m", _ShieldController_getCoverageStatus).call(this, txMeta.id);
259
+ const { status } = __classPrivateFieldGet(this, _ShieldController_instances, "m", _ShieldController_getCoverageShownStatus).call(this, txMeta.id);
254
260
  await __classPrivateFieldGet(this, _ShieldController_backend, "f").logTransaction({
255
261
  txMeta,
256
262
  transactionHash,
257
263
  rawTransactionHex,
258
264
  status,
259
265
  });
260
- }, _ShieldController_getCoverageStatus = function _ShieldController_getCoverageStatus(itemId) {
266
+ }, _ShieldController_getCoverageShownStatus = function _ShieldController_getCoverageShownStatus(itemId) {
261
267
  // The status is assigned as follows:
262
268
  // - 'shown' if we have a result
263
269
  // - 'not_shown' if we don't have a result
@@ -1 +1 @@
1
- {"version":3,"file":"ShieldController.cjs","sourceRoot":"","sources":["../src/ShieldController.ts"],"names":[],"mappings":"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","sourcesContent":["import { BaseController } from '@metamask/base-controller';\nimport type {\n ControllerGetStateAction,\n ControllerStateChangeEvent,\n} from '@metamask/base-controller';\nimport type { Messenger } from '@metamask/messenger';\nimport { SignatureRequestStatus } from '@metamask/signature-controller';\nimport type {\n SignatureRequest,\n SignatureStateChange,\n} from '@metamask/signature-controller';\nimport { TransactionStatus } from '@metamask/transaction-controller';\nimport type {\n TransactionControllerStateChangeEvent,\n TransactionMeta,\n} from '@metamask/transaction-controller';\nimport { cloneDeep, isEqual } from 'lodash';\n\nimport { controllerName } from './constants';\nimport { projectLogger, createModuleLogger } from './logger';\nimport type {\n CoverageResult,\n NormalizeSignatureRequestFn,\n ShieldBackend,\n} from './types';\n\nconst log = createModuleLogger(projectLogger, 'ShieldController');\n\nexport type CoverageResultRecordEntry = {\n /**\n * History of coverage results, latest first.\n */\n results: CoverageResult[];\n};\n\nexport type ShieldControllerState = {\n /**\n * Coverage results by transaction ID.\n */\n coverageResults: Record<\n string, // txId\n CoverageResultRecordEntry\n >;\n /**\n * List of txIds ordered by time, latest first.\n */\n orderedTransactionHistory: string[];\n};\n\n/**\n * Get the default state for the ShieldController.\n *\n * @returns The default state for the ShieldController.\n */\nexport function getDefaultShieldControllerState(): ShieldControllerState {\n return {\n coverageResults: {},\n orderedTransactionHistory: [],\n };\n}\n\nexport type ShieldControllerGetStateAction = ControllerGetStateAction<\n typeof controllerName,\n ShieldControllerState\n>;\n\nexport type ShieldControllerCheckCoverageAction = {\n type: `${typeof controllerName}:checkCoverage`;\n handler: ShieldController['checkCoverage'];\n};\n\n/**\n * The internal actions available to the ShieldController.\n */\nexport type ShieldControllerActions =\n | ShieldControllerGetStateAction\n | ShieldControllerCheckCoverageAction;\n\nexport type ShieldControllerCoverageResultReceivedEvent = {\n type: `${typeof controllerName}:coverageResultReceived`;\n payload: [coverageResult: CoverageResult];\n};\n\nexport type ShieldControllerStateChangeEvent = ControllerStateChangeEvent<\n typeof controllerName,\n ShieldControllerState\n>;\n\n/**\n * The internal events available to the ShieldController.\n */\nexport type ShieldControllerEvents =\n | ShieldControllerCoverageResultReceivedEvent\n | ShieldControllerStateChangeEvent;\n\n/**\n * The external events available to the ShieldController.\n */\ntype AllowedEvents =\n | SignatureStateChange\n | TransactionControllerStateChangeEvent;\n\n/**\n * The messenger of the {@link ShieldController}.\n */\nexport type ShieldControllerMessenger = Messenger<\n typeof controllerName,\n ShieldControllerActions,\n ShieldControllerEvents | AllowedEvents\n>;\n\n/**\n * Metadata for the ShieldController state, describing how to \"anonymize\"\n * the state and which parts should be persisted.\n */\nconst metadata = {\n coverageResults: {\n includeInStateLogs: true,\n persist: true,\n includeInDebugSnapshot: false,\n usedInUi: true,\n },\n orderedTransactionHistory: {\n includeInStateLogs: true,\n persist: true,\n includeInDebugSnapshot: false,\n usedInUi: false,\n },\n};\n\nexport type ShieldControllerOptions = {\n messenger: ShieldControllerMessenger;\n state?: Partial<ShieldControllerState>;\n backend: ShieldBackend;\n transactionHistoryLimit?: number;\n coverageHistoryLimit?: number;\n /**\n * Normalize the signature request before sending it to the backend.\n * Please note that the reason this is not being done internally is to\n * align the request body (data & params) with the security-alerts API.\n * The same normalization function which is used to normalize security-alerts request should be used here.\n *\n * @param signatureRequest - The signature request to normalize.\n * @returns The normalized signature request.\n */\n normalizeSignatureRequest?: NormalizeSignatureRequestFn;\n};\n\nexport class ShieldController extends BaseController<\n typeof controllerName,\n ShieldControllerState,\n ShieldControllerMessenger\n> {\n readonly #backend: ShieldBackend;\n\n readonly #coverageHistoryLimit: number;\n\n readonly #transactionHistoryLimit: number;\n\n readonly #normalizeSignatureRequest?: NormalizeSignatureRequestFn;\n\n readonly #transactionControllerStateChangeHandler: (\n transactions: TransactionMeta[],\n previousTransactions: TransactionMeta[] | undefined,\n ) => void;\n\n readonly #signatureControllerStateChangeHandler: (\n signatureRequests: Record<string, SignatureRequest>,\n previousSignatureRequests: Record<string, SignatureRequest> | undefined,\n ) => void;\n\n #started: boolean;\n\n constructor(options: ShieldControllerOptions) {\n const {\n messenger,\n state,\n backend,\n transactionHistoryLimit = 100,\n coverageHistoryLimit = 10,\n normalizeSignatureRequest,\n } = options;\n super({\n name: controllerName,\n metadata,\n messenger,\n state: {\n ...getDefaultShieldControllerState(),\n ...state,\n },\n });\n\n this.#backend = backend;\n this.#coverageHistoryLimit = coverageHistoryLimit;\n this.#transactionHistoryLimit = transactionHistoryLimit;\n this.#transactionControllerStateChangeHandler =\n this.#handleTransactionControllerStateChange.bind(this);\n this.#signatureControllerStateChangeHandler =\n this.#handleSignatureControllerStateChange.bind(this);\n this.#started = false;\n this.#normalizeSignatureRequest = normalizeSignatureRequest;\n }\n\n start() {\n if (this.#started) {\n return;\n }\n this.#started = true;\n\n this.messenger.subscribe(\n 'TransactionController:stateChange',\n this.#transactionControllerStateChangeHandler,\n (state) => state.transactions,\n );\n\n this.messenger.subscribe(\n 'SignatureController:stateChange',\n this.#signatureControllerStateChangeHandler,\n (state) => state.signatureRequests,\n );\n }\n\n stop() {\n if (!this.#started) {\n return;\n }\n this.#started = false;\n\n this.messenger.unsubscribe(\n 'TransactionController:stateChange',\n this.#transactionControllerStateChangeHandler,\n );\n\n this.messenger.unsubscribe(\n 'SignatureController:stateChange',\n this.#signatureControllerStateChangeHandler,\n );\n }\n\n #handleSignatureControllerStateChange(\n signatureRequests: Record<string, SignatureRequest>,\n previousSignatureRequests: Record<string, SignatureRequest> | undefined,\n ) {\n const signatureRequestsArray = Object.values(signatureRequests);\n const previousSignatureRequestsArray = Object.values(\n previousSignatureRequests ?? {},\n );\n const previousSignatureRequestsById = new Map<string, SignatureRequest>(\n previousSignatureRequestsArray.map((request) => [request.id, request]),\n );\n for (const signatureRequest of signatureRequestsArray) {\n const previousSignatureRequest = previousSignatureRequestsById.get(\n signatureRequest.id,\n );\n\n // Check coverage if the signature request is new.\n if (!previousSignatureRequest) {\n this.checkSignatureCoverage(signatureRequest).catch(\n // istanbul ignore next\n (error) => log('Error checking coverage:', error),\n );\n }\n\n // Log signature once the signature request has been fulfilled.\n if (\n signatureRequest.status === SignatureRequestStatus.Signed &&\n signatureRequest.status !== previousSignatureRequest?.status\n ) {\n this.#logSignature(signatureRequest).catch(\n // istanbul ignore next\n (error) => log('Error logging signature:', error),\n );\n }\n }\n }\n\n #handleTransactionControllerStateChange(\n transactions: TransactionMeta[],\n previousTransactions: TransactionMeta[] | undefined,\n ) {\n const previousTransactionsById = new Map<string, TransactionMeta>(\n previousTransactions?.map((tx) => [tx.id, tx]) ?? [],\n );\n for (const transaction of transactions) {\n const previousTransaction = previousTransactionsById.get(transaction.id);\n\n if (\n // We don't need to check coverage for submitted or confirmed transactions.\n transaction.status !== TransactionStatus.submitted &&\n transaction.status !== TransactionStatus.confirmed\n ) {\n // Check if the simulation data has changed.\n const simulationDataChanged =\n // only check if the previous transaction has simulation data and if it has changed\n // this is to avoid checking coverage for the `TWICE` (once when it's added to the state and once when it's simulated for the first time).\n // we only need to update the coverage result when the simulation data has changed.\n previousTransaction?.simulationData &&\n !isEqual(\n transaction.simulationData,\n previousTransaction.simulationData,\n );\n\n // Check coverage if the transaction is new or if the simulation data has\n // changed.\n if (!previousTransaction || simulationDataChanged) {\n this.checkCoverage(transaction).catch(\n // istanbul ignore next\n (error) => log('Error checking coverage:', error),\n );\n }\n }\n\n // Log transaction once it has been submitted.\n if (\n transaction.status === TransactionStatus.submitted &&\n transaction.status !== previousTransaction?.status\n ) {\n this.#logTransaction(transaction).catch(\n // istanbul ignore next\n (error) => log('Error logging transaction:', error),\n );\n }\n }\n }\n\n /**\n * Checks the coverage of a transaction.\n *\n * @param txMeta - The transaction to check coverage for.\n * @returns The coverage result.\n */\n async checkCoverage(txMeta: TransactionMeta): Promise<CoverageResult> {\n // Check coverage\n const coverageId = this.#getLatestCoverageId(txMeta.id);\n const coverageResult = await this.#backend.checkCoverage({\n txMeta,\n coverageId,\n });\n\n // Publish coverage result\n this.messenger.publish(\n `${controllerName}:coverageResultReceived`,\n coverageResult,\n );\n\n // Update state\n this.#addCoverageResult(txMeta.id, coverageResult);\n\n return coverageResult;\n }\n\n /**\n * Checks the coverage of a signature request.\n *\n * @param signatureRequest - The signature request to check coverage for.\n * @returns The coverage result.\n */\n async checkSignatureCoverage(\n signatureRequest: SignatureRequest,\n ): Promise<CoverageResult> {\n // Check coverage\n const coverageId = this.#getLatestCoverageId(signatureRequest.id);\n\n // Normalize the signature request before sending it to the backend.\n // This is to ensure that the signature data is normalized and consistent as the security alerts api calls.\n const clonedSignatureRequest = cloneDeep(signatureRequest);\n const normalizedSignatureRequest =\n this.#normalizeSignatureRequest?.(clonedSignatureRequest) ??\n clonedSignatureRequest;\n const coverageResult = await this.#backend.checkSignatureCoverage({\n signatureRequest: normalizedSignatureRequest,\n coverageId,\n });\n\n // Publish coverage result\n this.messenger.publish(\n `${controllerName}:coverageResultReceived`,\n coverageResult,\n );\n\n // Update state\n this.#addCoverageResult(signatureRequest.id, coverageResult);\n\n return coverageResult;\n }\n\n #addCoverageResult(txId: string, coverageResult: CoverageResult) {\n // Assert the coverageId hasn't changed.\n const latestCoverageId = this.#getLatestCoverageId(txId);\n if (latestCoverageId && coverageResult.coverageId !== latestCoverageId) {\n throw new Error('Coverage ID has changed');\n }\n\n this.update((draft) => {\n // Fetch coverage result entry.\n let newEntry = false;\n let coverageResultEntry = draft.coverageResults[txId];\n\n // Create new entry if necessary.\n if (!coverageResultEntry) {\n newEntry = true;\n coverageResultEntry = {\n results: [],\n };\n draft.coverageResults[txId] = coverageResultEntry;\n }\n\n // Trim coverage history if necessary.\n if (coverageResultEntry.results.length >= this.#coverageHistoryLimit) {\n coverageResultEntry.results.pop();\n }\n\n // Add new result.\n coverageResultEntry.results.unshift(coverageResult);\n\n // Add to history if new entry.\n const { orderedTransactionHistory } = draft;\n let removedTxId: string | undefined;\n if (newEntry) {\n // Trim transaction history if necessary.\n if (orderedTransactionHistory.length >= this.#transactionHistoryLimit) {\n removedTxId = orderedTransactionHistory.pop();\n // Delete corresponding coverage result entry.\n if (removedTxId) {\n delete draft.coverageResults[removedTxId];\n }\n }\n // Add to history.\n orderedTransactionHistory.unshift(txId);\n }\n });\n }\n\n async #logSignature(signatureRequest: SignatureRequest) {\n const signature = signatureRequest.rawSig;\n if (!signature) {\n throw new Error('Signature not found');\n }\n\n const { status } = this.#getCoverageStatus(signatureRequest.id);\n\n await this.#backend.logSignature({\n signatureRequest,\n signature,\n status,\n });\n }\n\n async #logTransaction(txMeta: TransactionMeta) {\n const transactionHash = txMeta.hash;\n if (!transactionHash) {\n throw new Error('Transaction hash not found');\n }\n\n const rawTransactionHex = txMeta.rawTx;\n if (!rawTransactionHex) {\n throw new Error('Raw transaction hex not found');\n }\n\n const { status } = this.#getCoverageStatus(txMeta.id);\n\n await this.#backend.logTransaction({\n txMeta,\n transactionHash,\n rawTransactionHex,\n status,\n });\n }\n\n #getCoverageStatus(itemId: string) {\n // The status is assigned as follows:\n // - 'shown' if we have a result\n // - 'not_shown' if we don't have a result\n const coverageId = this.#getLatestCoverageId(itemId);\n let status = 'shown';\n if (!coverageId) {\n log('Coverage ID not found for', itemId);\n status = 'not_shown';\n }\n return { status };\n }\n\n #getLatestCoverageId(itemId: string): string | undefined {\n return this.state.coverageResults[itemId]?.results[0]?.coverageId;\n }\n}\n"]}
1
+ {"version":3,"file":"ShieldController.cjs","sourceRoot":"","sources":["../src/ShieldController.ts"],"names":[],"mappings":"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","sourcesContent":["import { BaseController } from '@metamask/base-controller';\nimport type {\n ControllerGetStateAction,\n ControllerStateChangeEvent,\n} from '@metamask/base-controller';\nimport type { Messenger } from '@metamask/messenger';\nimport { SignatureRequestStatus } from '@metamask/signature-controller';\nimport type {\n SignatureRequest,\n SignatureStateChange,\n} from '@metamask/signature-controller';\nimport { TransactionStatus } from '@metamask/transaction-controller';\nimport type {\n TransactionControllerStateChangeEvent,\n TransactionMeta,\n} from '@metamask/transaction-controller';\nimport { cloneDeep, isEqual } from 'lodash';\n\nimport { controllerName } from './constants';\nimport { projectLogger, createModuleLogger } from './logger';\nimport type {\n CoverageResult,\n NormalizeSignatureRequestFn,\n ShieldBackend,\n} from './types';\n\nconst log = createModuleLogger(projectLogger, 'ShieldController');\n\nexport type CoverageResultRecordEntry = {\n /**\n * History of coverage results, latest first.\n */\n results: CoverageResult[];\n};\n\nexport type ShieldControllerState = {\n /**\n * Coverage results by transaction ID.\n */\n coverageResults: Record<\n string, // txId\n CoverageResultRecordEntry\n >;\n /**\n * List of txIds ordered by time, latest first.\n */\n orderedTransactionHistory: string[];\n};\n\n/**\n * Get the default state for the ShieldController.\n *\n * @returns The default state for the ShieldController.\n */\nexport function getDefaultShieldControllerState(): ShieldControllerState {\n return {\n coverageResults: {},\n orderedTransactionHistory: [],\n };\n}\n\nexport type ShieldControllerGetStateAction = ControllerGetStateAction<\n typeof controllerName,\n ShieldControllerState\n>;\n\nexport type ShieldControllerCheckCoverageAction = {\n type: `${typeof controllerName}:checkCoverage`;\n handler: ShieldController['checkCoverage'];\n};\n\n/**\n * The internal actions available to the ShieldController.\n */\nexport type ShieldControllerActions =\n | ShieldControllerGetStateAction\n | ShieldControllerCheckCoverageAction;\n\nexport type ShieldControllerCoverageResultReceivedEvent = {\n type: `${typeof controllerName}:coverageResultReceived`;\n payload: [coverageResult: CoverageResult];\n};\n\nexport type ShieldControllerStateChangeEvent = ControllerStateChangeEvent<\n typeof controllerName,\n ShieldControllerState\n>;\n\n/**\n * The internal events available to the ShieldController.\n */\nexport type ShieldControllerEvents =\n | ShieldControllerCoverageResultReceivedEvent\n | ShieldControllerStateChangeEvent;\n\n/**\n * The external events available to the ShieldController.\n */\ntype AllowedEvents =\n | SignatureStateChange\n | TransactionControllerStateChangeEvent;\n\n/**\n * The messenger of the {@link ShieldController}.\n */\nexport type ShieldControllerMessenger = Messenger<\n typeof controllerName,\n ShieldControllerActions,\n ShieldControllerEvents | AllowedEvents\n>;\n\n/**\n * Metadata for the ShieldController state, describing how to \"anonymize\"\n * the state and which parts should be persisted.\n */\nconst metadata = {\n coverageResults: {\n includeInStateLogs: true,\n persist: true,\n includeInDebugSnapshot: false,\n usedInUi: true,\n },\n orderedTransactionHistory: {\n includeInStateLogs: true,\n persist: true,\n includeInDebugSnapshot: false,\n usedInUi: false,\n },\n};\n\nexport type ShieldControllerOptions = {\n messenger: ShieldControllerMessenger;\n state?: Partial<ShieldControllerState>;\n backend: ShieldBackend;\n transactionHistoryLimit?: number;\n coverageHistoryLimit?: number;\n /**\n * Normalize the signature request before sending it to the backend.\n * Please note that the reason this is not being done internally is to\n * align the request body (data & params) with the security-alerts API.\n * The same normalization function which is used to normalize security-alerts request should be used here.\n *\n * @param signatureRequest - The signature request to normalize.\n * @returns The normalized signature request.\n */\n normalizeSignatureRequest?: NormalizeSignatureRequestFn;\n};\n\nexport class ShieldController extends BaseController<\n typeof controllerName,\n ShieldControllerState,\n ShieldControllerMessenger\n> {\n readonly #backend: ShieldBackend;\n\n readonly #coverageHistoryLimit: number;\n\n readonly #transactionHistoryLimit: number;\n\n readonly #normalizeSignatureRequest?: NormalizeSignatureRequestFn;\n\n readonly #transactionControllerStateChangeHandler: (\n transactions: TransactionMeta[],\n previousTransactions: TransactionMeta[] | undefined,\n ) => void;\n\n readonly #signatureControllerStateChangeHandler: (\n signatureRequests: Record<string, SignatureRequest>,\n previousSignatureRequests: Record<string, SignatureRequest> | undefined,\n ) => void;\n\n #started: boolean;\n\n constructor(options: ShieldControllerOptions) {\n const {\n messenger,\n state,\n backend,\n transactionHistoryLimit = 100,\n coverageHistoryLimit = 10,\n normalizeSignatureRequest,\n } = options;\n super({\n name: controllerName,\n metadata,\n messenger,\n state: {\n ...getDefaultShieldControllerState(),\n ...state,\n },\n });\n\n this.#backend = backend;\n this.#coverageHistoryLimit = coverageHistoryLimit;\n this.#transactionHistoryLimit = transactionHistoryLimit;\n this.#transactionControllerStateChangeHandler =\n this.#handleTransactionControllerStateChange.bind(this);\n this.#signatureControllerStateChangeHandler =\n this.#handleSignatureControllerStateChange.bind(this);\n this.#started = false;\n this.#normalizeSignatureRequest = normalizeSignatureRequest;\n }\n\n /**\n * Start the ShieldController and subscribe to the transaction and signature controller state changes.\n */\n start(): void {\n if (this.#started) {\n return;\n }\n this.#started = true;\n\n this.messenger.subscribe(\n 'TransactionController:stateChange',\n this.#transactionControllerStateChangeHandler,\n (state) => state.transactions,\n );\n\n this.messenger.subscribe(\n 'SignatureController:stateChange',\n this.#signatureControllerStateChangeHandler,\n (state) => state.signatureRequests,\n );\n }\n\n /**\n * Stop the ShieldController and unsubscribe from the transaction and signature controller state changes.\n */\n stop(): void {\n if (!this.#started) {\n return;\n }\n this.#started = false;\n\n this.messenger.unsubscribe(\n 'TransactionController:stateChange',\n this.#transactionControllerStateChangeHandler,\n );\n\n this.messenger.unsubscribe(\n 'SignatureController:stateChange',\n this.#signatureControllerStateChangeHandler,\n );\n }\n\n #handleSignatureControllerStateChange(\n signatureRequests: Record<string, SignatureRequest>,\n previousSignatureRequests: Record<string, SignatureRequest> | undefined,\n ): void {\n const signatureRequestsArray = Object.values(signatureRequests);\n const previousSignatureRequestsArray = Object.values(\n previousSignatureRequests ?? {},\n );\n const previousSignatureRequestsById = new Map<string, SignatureRequest>(\n previousSignatureRequestsArray.map((request) => [request.id, request]),\n );\n for (const signatureRequest of signatureRequestsArray) {\n const previousSignatureRequest = previousSignatureRequestsById.get(\n signatureRequest.id,\n );\n\n // Check coverage if the signature request is new.\n if (!previousSignatureRequest) {\n this.checkSignatureCoverage(signatureRequest).catch(\n // istanbul ignore next\n (error) => log('Error checking coverage:', error),\n );\n }\n\n // Log signature once the signature request has been fulfilled.\n if (\n signatureRequest.status === SignatureRequestStatus.Signed &&\n signatureRequest.status !== previousSignatureRequest?.status\n ) {\n this.#logSignature(signatureRequest).catch(\n // istanbul ignore next\n (error) => log('Error logging signature:', error),\n );\n }\n }\n }\n\n #handleTransactionControllerStateChange(\n transactions: TransactionMeta[],\n previousTransactions: TransactionMeta[] | undefined,\n ): void {\n const previousTransactionsById = new Map<string, TransactionMeta>(\n previousTransactions?.map((tx) => [tx.id, tx]) ?? [],\n );\n for (const transaction of transactions) {\n const previousTransaction = previousTransactionsById.get(transaction.id);\n\n if (\n // We don't need to check coverage for submitted or confirmed transactions.\n transaction.status !== TransactionStatus.submitted &&\n transaction.status !== TransactionStatus.confirmed\n ) {\n // Check if the simulation data has changed.\n const simulationDataChanged =\n // only check if the previous transaction has simulation data and if it has changed\n // this is to avoid checking coverage for the `TWICE` (once when it's added to the state and once when it's simulated for the first time).\n // we only need to update the coverage result when the simulation data has changed.\n previousTransaction?.simulationData &&\n !isEqual(\n transaction.simulationData,\n previousTransaction.simulationData,\n );\n\n // Check coverage if the transaction is new or if the simulation data has\n // changed.\n if (!previousTransaction || simulationDataChanged) {\n this.checkCoverage(transaction).catch(\n // istanbul ignore next\n (error) => log('Error checking coverage:', error),\n );\n }\n }\n\n // Log transaction once it has been submitted.\n if (\n transaction.status === TransactionStatus.submitted &&\n transaction.status !== previousTransaction?.status\n ) {\n this.#logTransaction(transaction).catch(\n // istanbul ignore next\n (error) => log('Error logging transaction:', error),\n );\n }\n }\n }\n\n /**\n * Checks the coverage of a transaction.\n *\n * @param txMeta - The transaction to check coverage for.\n * @returns The coverage result.\n */\n async checkCoverage(txMeta: TransactionMeta): Promise<CoverageResult> {\n // Check coverage\n const coverageId = this.#getLatestCoverageId(txMeta.id);\n const coverageResult = await this.#backend.checkCoverage({\n txMeta,\n coverageId,\n });\n\n // Publish coverage result\n this.messenger.publish(\n `${controllerName}:coverageResultReceived`,\n coverageResult,\n );\n\n // Update state\n this.#addCoverageResult(txMeta.id, coverageResult);\n\n return coverageResult;\n }\n\n /**\n * Checks the coverage of a signature request.\n *\n * @param signatureRequest - The signature request to check coverage for.\n * @returns The coverage result.\n */\n async checkSignatureCoverage(\n signatureRequest: SignatureRequest,\n ): Promise<CoverageResult> {\n // Check coverage\n const coverageId = this.#getLatestCoverageId(signatureRequest.id);\n\n // Normalize the signature request before sending it to the backend.\n // This is to ensure that the signature data is normalized and consistent as the security alerts api calls.\n const clonedSignatureRequest = cloneDeep(signatureRequest);\n const normalizedSignatureRequest =\n this.#normalizeSignatureRequest?.(clonedSignatureRequest) ??\n clonedSignatureRequest;\n const coverageResult = await this.#backend.checkSignatureCoverage({\n signatureRequest: normalizedSignatureRequest,\n coverageId,\n });\n\n // Publish coverage result\n this.messenger.publish(\n `${controllerName}:coverageResultReceived`,\n coverageResult,\n );\n\n // Update state\n this.#addCoverageResult(signatureRequest.id, coverageResult);\n\n return coverageResult;\n }\n\n #addCoverageResult(txId: string, coverageResult: CoverageResult): void {\n // Assert the coverageId hasn't changed.\n const latestCoverageId = this.#getLatestCoverageId(txId);\n if (latestCoverageId && coverageResult.coverageId !== latestCoverageId) {\n throw new Error('Coverage ID has changed');\n }\n\n this.update((draft) => {\n // Fetch coverage result entry.\n let newEntry = false;\n let coverageResultEntry = draft.coverageResults[txId];\n\n // Create new entry if necessary.\n if (!coverageResultEntry) {\n newEntry = true;\n coverageResultEntry = {\n results: [],\n };\n draft.coverageResults[txId] = coverageResultEntry;\n }\n\n // Trim coverage history if necessary.\n if (coverageResultEntry.results.length >= this.#coverageHistoryLimit) {\n coverageResultEntry.results.pop();\n }\n\n // Add new result.\n coverageResultEntry.results.unshift(coverageResult);\n\n // Add to history if new entry.\n const { orderedTransactionHistory } = draft;\n let removedTxId: string | undefined;\n if (newEntry) {\n // Trim transaction history if necessary.\n if (orderedTransactionHistory.length >= this.#transactionHistoryLimit) {\n removedTxId = orderedTransactionHistory.pop();\n // Delete corresponding coverage result entry.\n if (removedTxId) {\n delete draft.coverageResults[removedTxId];\n }\n }\n // Add to history.\n orderedTransactionHistory.unshift(txId);\n }\n });\n }\n\n async #logSignature(signatureRequest: SignatureRequest): Promise<void> {\n const signature = signatureRequest.rawSig;\n if (!signature) {\n throw new Error('Signature not found');\n }\n\n const { status } = this.#getCoverageShownStatus(signatureRequest.id);\n\n await this.#backend.logSignature({\n signatureRequest,\n signature,\n status,\n });\n }\n\n async #logTransaction(txMeta: TransactionMeta): Promise<void> {\n const transactionHash = txMeta.hash;\n if (!transactionHash) {\n throw new Error('Transaction hash not found');\n }\n\n const rawTransactionHex = txMeta.rawTx;\n if (!rawTransactionHex) {\n throw new Error('Raw transaction hex not found');\n }\n\n const { status } = this.#getCoverageShownStatus(txMeta.id);\n\n await this.#backend.logTransaction({\n txMeta,\n transactionHash,\n rawTransactionHex,\n status,\n });\n }\n\n /**\n * Get the coverage shown status for a given item ID.\n *\n * @param itemId - The item ID to get the coverage status for.\n * @returns The coverage status.\n */\n #getCoverageShownStatus(itemId: string): { status: string } {\n // The status is assigned as follows:\n // - 'shown' if we have a result\n // - 'not_shown' if we don't have a result\n const coverageId = this.#getLatestCoverageId(itemId);\n let status = 'shown';\n if (!coverageId) {\n log('Coverage ID not found for', itemId);\n status = 'not_shown';\n }\n return { status };\n }\n\n #getLatestCoverageId(itemId: string): string | undefined {\n return this.state.coverageResults[itemId]?.results[0]?.coverageId;\n }\n}\n"]}
@@ -74,7 +74,13 @@ export type ShieldControllerOptions = {
74
74
  export declare class ShieldController extends BaseController<typeof controllerName, ShieldControllerState, ShieldControllerMessenger> {
75
75
  #private;
76
76
  constructor(options: ShieldControllerOptions);
77
+ /**
78
+ * Start the ShieldController and subscribe to the transaction and signature controller state changes.
79
+ */
77
80
  start(): void;
81
+ /**
82
+ * Stop the ShieldController and unsubscribe from the transaction and signature controller state changes.
83
+ */
78
84
  stop(): void;
79
85
  /**
80
86
  * Checks the coverage of a transaction.
@@ -1 +1 @@
1
- {"version":3,"file":"ShieldController.d.cts","sourceRoot":"","sources":["../src/ShieldController.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,kCAAkC;AAC3D,OAAO,KAAK,EACV,wBAAwB,EACxB,0BAA0B,EAC3B,kCAAkC;AACnC,OAAO,KAAK,EAAE,SAAS,EAAE,4BAA4B;AAErD,OAAO,KAAK,EACV,gBAAgB,EAChB,oBAAoB,EACrB,uCAAuC;AAExC,OAAO,KAAK,EACV,qCAAqC,EACrC,eAAe,EAChB,yCAAyC;AAG1C,OAAO,EAAE,cAAc,EAAE,wBAAoB;AAE7C,OAAO,KAAK,EACV,cAAc,EACd,2BAA2B,EAC3B,aAAa,EACd,oBAAgB;AAIjB,MAAM,MAAM,yBAAyB,GAAG;IACtC;;OAEG;IACH,OAAO,EAAE,cAAc,EAAE,CAAC;CAC3B,CAAC;AAEF,MAAM,MAAM,qBAAqB,GAAG;IAClC;;OAEG;IACH,eAAe,EAAE,MAAM,CACrB,MAAM,EAAE,OAAO;IACf,yBAAyB,CAC1B,CAAC;IACF;;OAEG;IACH,yBAAyB,EAAE,MAAM,EAAE,CAAC;CACrC,CAAC;AAEF;;;;GAIG;AACH,wBAAgB,+BAA+B,IAAI,qBAAqB,CAKvE;AAED,MAAM,MAAM,8BAA8B,GAAG,wBAAwB,CACnE,OAAO,cAAc,EACrB,qBAAqB,CACtB,CAAC;AAEF,MAAM,MAAM,mCAAmC,GAAG;IAChD,IAAI,EAAE,GAAG,OAAO,cAAc,gBAAgB,CAAC;IAC/C,OAAO,EAAE,gBAAgB,CAAC,eAAe,CAAC,CAAC;CAC5C,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,uBAAuB,GAC/B,8BAA8B,GAC9B,mCAAmC,CAAC;AAExC,MAAM,MAAM,2CAA2C,GAAG;IACxD,IAAI,EAAE,GAAG,OAAO,cAAc,yBAAyB,CAAC;IACxD,OAAO,EAAE,CAAC,cAAc,EAAE,cAAc,CAAC,CAAC;CAC3C,CAAC;AAEF,MAAM,MAAM,gCAAgC,GAAG,0BAA0B,CACvE,OAAO,cAAc,EACrB,qBAAqB,CACtB,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,sBAAsB,GAC9B,2CAA2C,GAC3C,gCAAgC,CAAC;AAErC;;GAEG;AACH,KAAK,aAAa,GACd,oBAAoB,GACpB,qCAAqC,CAAC;AAE1C;;GAEG;AACH,MAAM,MAAM,yBAAyB,GAAG,SAAS,CAC/C,OAAO,cAAc,EACrB,uBAAuB,EACvB,sBAAsB,GAAG,aAAa,CACvC,CAAC;AAqBF,MAAM,MAAM,uBAAuB,GAAG;IACpC,SAAS,EAAE,yBAAyB,CAAC;IACrC,KAAK,CAAC,EAAE,OAAO,CAAC,qBAAqB,CAAC,CAAC;IACvC,OAAO,EAAE,aAAa,CAAC;IACvB,uBAAuB,CAAC,EAAE,MAAM,CAAC;IACjC,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B;;;;;;;;OAQG;IACH,yBAAyB,CAAC,EAAE,2BAA2B,CAAC;CACzD,CAAC;AAEF,qBAAa,gBAAiB,SAAQ,cAAc,CAClD,OAAO,cAAc,EACrB,qBAAqB,EACrB,yBAAyB,CAC1B;;gBAqBa,OAAO,EAAE,uBAAuB;IA8B5C,KAAK;IAmBL,IAAI;IAuGJ;;;;;OAKG;IACG,aAAa,CAAC,MAAM,EAAE,eAAe,GAAG,OAAO,CAAC,cAAc,CAAC;IAoBrE;;;;;OAKG;IACG,sBAAsB,CAC1B,gBAAgB,EAAE,gBAAgB,GACjC,OAAO,CAAC,cAAc,CAAC;CA8H3B"}
1
+ {"version":3,"file":"ShieldController.d.cts","sourceRoot":"","sources":["../src/ShieldController.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,kCAAkC;AAC3D,OAAO,KAAK,EACV,wBAAwB,EACxB,0BAA0B,EAC3B,kCAAkC;AACnC,OAAO,KAAK,EAAE,SAAS,EAAE,4BAA4B;AAErD,OAAO,KAAK,EACV,gBAAgB,EAChB,oBAAoB,EACrB,uCAAuC;AAExC,OAAO,KAAK,EACV,qCAAqC,EACrC,eAAe,EAChB,yCAAyC;AAG1C,OAAO,EAAE,cAAc,EAAE,wBAAoB;AAE7C,OAAO,KAAK,EACV,cAAc,EACd,2BAA2B,EAC3B,aAAa,EACd,oBAAgB;AAIjB,MAAM,MAAM,yBAAyB,GAAG;IACtC;;OAEG;IACH,OAAO,EAAE,cAAc,EAAE,CAAC;CAC3B,CAAC;AAEF,MAAM,MAAM,qBAAqB,GAAG;IAClC;;OAEG;IACH,eAAe,EAAE,MAAM,CACrB,MAAM,EAAE,OAAO;IACf,yBAAyB,CAC1B,CAAC;IACF;;OAEG;IACH,yBAAyB,EAAE,MAAM,EAAE,CAAC;CACrC,CAAC;AAEF;;;;GAIG;AACH,wBAAgB,+BAA+B,IAAI,qBAAqB,CAKvE;AAED,MAAM,MAAM,8BAA8B,GAAG,wBAAwB,CACnE,OAAO,cAAc,EACrB,qBAAqB,CACtB,CAAC;AAEF,MAAM,MAAM,mCAAmC,GAAG;IAChD,IAAI,EAAE,GAAG,OAAO,cAAc,gBAAgB,CAAC;IAC/C,OAAO,EAAE,gBAAgB,CAAC,eAAe,CAAC,CAAC;CAC5C,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,uBAAuB,GAC/B,8BAA8B,GAC9B,mCAAmC,CAAC;AAExC,MAAM,MAAM,2CAA2C,GAAG;IACxD,IAAI,EAAE,GAAG,OAAO,cAAc,yBAAyB,CAAC;IACxD,OAAO,EAAE,CAAC,cAAc,EAAE,cAAc,CAAC,CAAC;CAC3C,CAAC;AAEF,MAAM,MAAM,gCAAgC,GAAG,0BAA0B,CACvE,OAAO,cAAc,EACrB,qBAAqB,CACtB,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,sBAAsB,GAC9B,2CAA2C,GAC3C,gCAAgC,CAAC;AAErC;;GAEG;AACH,KAAK,aAAa,GACd,oBAAoB,GACpB,qCAAqC,CAAC;AAE1C;;GAEG;AACH,MAAM,MAAM,yBAAyB,GAAG,SAAS,CAC/C,OAAO,cAAc,EACrB,uBAAuB,EACvB,sBAAsB,GAAG,aAAa,CACvC,CAAC;AAqBF,MAAM,MAAM,uBAAuB,GAAG;IACpC,SAAS,EAAE,yBAAyB,CAAC;IACrC,KAAK,CAAC,EAAE,OAAO,CAAC,qBAAqB,CAAC,CAAC;IACvC,OAAO,EAAE,aAAa,CAAC;IACvB,uBAAuB,CAAC,EAAE,MAAM,CAAC;IACjC,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B;;;;;;;;OAQG;IACH,yBAAyB,CAAC,EAAE,2BAA2B,CAAC;CACzD,CAAC;AAEF,qBAAa,gBAAiB,SAAQ,cAAc,CAClD,OAAO,cAAc,EACrB,qBAAqB,EACrB,yBAAyB,CAC1B;;gBAqBa,OAAO,EAAE,uBAAuB;IA8B5C;;OAEG;IACH,KAAK,IAAI,IAAI;IAmBb;;OAEG;IACH,IAAI,IAAI,IAAI;IAuGZ;;;;;OAKG;IACG,aAAa,CAAC,MAAM,EAAE,eAAe,GAAG,OAAO,CAAC,cAAc,CAAC;IAoBrE;;;;;OAKG;IACG,sBAAsB,CAC1B,gBAAgB,EAAE,gBAAgB,GACjC,OAAO,CAAC,cAAc,CAAC;CAoI3B"}
@@ -74,7 +74,13 @@ export type ShieldControllerOptions = {
74
74
  export declare class ShieldController extends BaseController<typeof controllerName, ShieldControllerState, ShieldControllerMessenger> {
75
75
  #private;
76
76
  constructor(options: ShieldControllerOptions);
77
+ /**
78
+ * Start the ShieldController and subscribe to the transaction and signature controller state changes.
79
+ */
77
80
  start(): void;
81
+ /**
82
+ * Stop the ShieldController and unsubscribe from the transaction and signature controller state changes.
83
+ */
78
84
  stop(): void;
79
85
  /**
80
86
  * Checks the coverage of a transaction.
@@ -1 +1 @@
1
- {"version":3,"file":"ShieldController.d.mts","sourceRoot":"","sources":["../src/ShieldController.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,kCAAkC;AAC3D,OAAO,KAAK,EACV,wBAAwB,EACxB,0BAA0B,EAC3B,kCAAkC;AACnC,OAAO,KAAK,EAAE,SAAS,EAAE,4BAA4B;AAErD,OAAO,KAAK,EACV,gBAAgB,EAChB,oBAAoB,EACrB,uCAAuC;AAExC,OAAO,KAAK,EACV,qCAAqC,EACrC,eAAe,EAChB,yCAAyC;AAG1C,OAAO,EAAE,cAAc,EAAE,wBAAoB;AAE7C,OAAO,KAAK,EACV,cAAc,EACd,2BAA2B,EAC3B,aAAa,EACd,oBAAgB;AAIjB,MAAM,MAAM,yBAAyB,GAAG;IACtC;;OAEG;IACH,OAAO,EAAE,cAAc,EAAE,CAAC;CAC3B,CAAC;AAEF,MAAM,MAAM,qBAAqB,GAAG;IAClC;;OAEG;IACH,eAAe,EAAE,MAAM,CACrB,MAAM,EAAE,OAAO;IACf,yBAAyB,CAC1B,CAAC;IACF;;OAEG;IACH,yBAAyB,EAAE,MAAM,EAAE,CAAC;CACrC,CAAC;AAEF;;;;GAIG;AACH,wBAAgB,+BAA+B,IAAI,qBAAqB,CAKvE;AAED,MAAM,MAAM,8BAA8B,GAAG,wBAAwB,CACnE,OAAO,cAAc,EACrB,qBAAqB,CACtB,CAAC;AAEF,MAAM,MAAM,mCAAmC,GAAG;IAChD,IAAI,EAAE,GAAG,OAAO,cAAc,gBAAgB,CAAC;IAC/C,OAAO,EAAE,gBAAgB,CAAC,eAAe,CAAC,CAAC;CAC5C,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,uBAAuB,GAC/B,8BAA8B,GAC9B,mCAAmC,CAAC;AAExC,MAAM,MAAM,2CAA2C,GAAG;IACxD,IAAI,EAAE,GAAG,OAAO,cAAc,yBAAyB,CAAC;IACxD,OAAO,EAAE,CAAC,cAAc,EAAE,cAAc,CAAC,CAAC;CAC3C,CAAC;AAEF,MAAM,MAAM,gCAAgC,GAAG,0BAA0B,CACvE,OAAO,cAAc,EACrB,qBAAqB,CACtB,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,sBAAsB,GAC9B,2CAA2C,GAC3C,gCAAgC,CAAC;AAErC;;GAEG;AACH,KAAK,aAAa,GACd,oBAAoB,GACpB,qCAAqC,CAAC;AAE1C;;GAEG;AACH,MAAM,MAAM,yBAAyB,GAAG,SAAS,CAC/C,OAAO,cAAc,EACrB,uBAAuB,EACvB,sBAAsB,GAAG,aAAa,CACvC,CAAC;AAqBF,MAAM,MAAM,uBAAuB,GAAG;IACpC,SAAS,EAAE,yBAAyB,CAAC;IACrC,KAAK,CAAC,EAAE,OAAO,CAAC,qBAAqB,CAAC,CAAC;IACvC,OAAO,EAAE,aAAa,CAAC;IACvB,uBAAuB,CAAC,EAAE,MAAM,CAAC;IACjC,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B;;;;;;;;OAQG;IACH,yBAAyB,CAAC,EAAE,2BAA2B,CAAC;CACzD,CAAC;AAEF,qBAAa,gBAAiB,SAAQ,cAAc,CAClD,OAAO,cAAc,EACrB,qBAAqB,EACrB,yBAAyB,CAC1B;;gBAqBa,OAAO,EAAE,uBAAuB;IA8B5C,KAAK;IAmBL,IAAI;IAuGJ;;;;;OAKG;IACG,aAAa,CAAC,MAAM,EAAE,eAAe,GAAG,OAAO,CAAC,cAAc,CAAC;IAoBrE;;;;;OAKG;IACG,sBAAsB,CAC1B,gBAAgB,EAAE,gBAAgB,GACjC,OAAO,CAAC,cAAc,CAAC;CA8H3B"}
1
+ {"version":3,"file":"ShieldController.d.mts","sourceRoot":"","sources":["../src/ShieldController.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,kCAAkC;AAC3D,OAAO,KAAK,EACV,wBAAwB,EACxB,0BAA0B,EAC3B,kCAAkC;AACnC,OAAO,KAAK,EAAE,SAAS,EAAE,4BAA4B;AAErD,OAAO,KAAK,EACV,gBAAgB,EAChB,oBAAoB,EACrB,uCAAuC;AAExC,OAAO,KAAK,EACV,qCAAqC,EACrC,eAAe,EAChB,yCAAyC;AAG1C,OAAO,EAAE,cAAc,EAAE,wBAAoB;AAE7C,OAAO,KAAK,EACV,cAAc,EACd,2BAA2B,EAC3B,aAAa,EACd,oBAAgB;AAIjB,MAAM,MAAM,yBAAyB,GAAG;IACtC;;OAEG;IACH,OAAO,EAAE,cAAc,EAAE,CAAC;CAC3B,CAAC;AAEF,MAAM,MAAM,qBAAqB,GAAG;IAClC;;OAEG;IACH,eAAe,EAAE,MAAM,CACrB,MAAM,EAAE,OAAO;IACf,yBAAyB,CAC1B,CAAC;IACF;;OAEG;IACH,yBAAyB,EAAE,MAAM,EAAE,CAAC;CACrC,CAAC;AAEF;;;;GAIG;AACH,wBAAgB,+BAA+B,IAAI,qBAAqB,CAKvE;AAED,MAAM,MAAM,8BAA8B,GAAG,wBAAwB,CACnE,OAAO,cAAc,EACrB,qBAAqB,CACtB,CAAC;AAEF,MAAM,MAAM,mCAAmC,GAAG;IAChD,IAAI,EAAE,GAAG,OAAO,cAAc,gBAAgB,CAAC;IAC/C,OAAO,EAAE,gBAAgB,CAAC,eAAe,CAAC,CAAC;CAC5C,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,uBAAuB,GAC/B,8BAA8B,GAC9B,mCAAmC,CAAC;AAExC,MAAM,MAAM,2CAA2C,GAAG;IACxD,IAAI,EAAE,GAAG,OAAO,cAAc,yBAAyB,CAAC;IACxD,OAAO,EAAE,CAAC,cAAc,EAAE,cAAc,CAAC,CAAC;CAC3C,CAAC;AAEF,MAAM,MAAM,gCAAgC,GAAG,0BAA0B,CACvE,OAAO,cAAc,EACrB,qBAAqB,CACtB,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,sBAAsB,GAC9B,2CAA2C,GAC3C,gCAAgC,CAAC;AAErC;;GAEG;AACH,KAAK,aAAa,GACd,oBAAoB,GACpB,qCAAqC,CAAC;AAE1C;;GAEG;AACH,MAAM,MAAM,yBAAyB,GAAG,SAAS,CAC/C,OAAO,cAAc,EACrB,uBAAuB,EACvB,sBAAsB,GAAG,aAAa,CACvC,CAAC;AAqBF,MAAM,MAAM,uBAAuB,GAAG;IACpC,SAAS,EAAE,yBAAyB,CAAC;IACrC,KAAK,CAAC,EAAE,OAAO,CAAC,qBAAqB,CAAC,CAAC;IACvC,OAAO,EAAE,aAAa,CAAC;IACvB,uBAAuB,CAAC,EAAE,MAAM,CAAC;IACjC,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B;;;;;;;;OAQG;IACH,yBAAyB,CAAC,EAAE,2BAA2B,CAAC;CACzD,CAAC;AAEF,qBAAa,gBAAiB,SAAQ,cAAc,CAClD,OAAO,cAAc,EACrB,qBAAqB,EACrB,yBAAyB,CAC1B;;gBAqBa,OAAO,EAAE,uBAAuB;IA8B5C;;OAEG;IACH,KAAK,IAAI,IAAI;IAmBb;;OAEG;IACH,IAAI,IAAI,IAAI;IAuGZ;;;;;OAKG;IACG,aAAa,CAAC,MAAM,EAAE,eAAe,GAAG,OAAO,CAAC,cAAc,CAAC;IAoBrE;;;;;OAKG;IACG,sBAAsB,CAC1B,gBAAgB,EAAE,gBAAgB,GACjC,OAAO,CAAC,cAAc,CAAC;CAoI3B"}
@@ -9,7 +9,7 @@ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (
9
9
  if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
10
10
  return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
11
11
  };
12
- var _ShieldController_instances, _ShieldController_backend, _ShieldController_coverageHistoryLimit, _ShieldController_transactionHistoryLimit, _ShieldController_normalizeSignatureRequest, _ShieldController_transactionControllerStateChangeHandler, _ShieldController_signatureControllerStateChangeHandler, _ShieldController_started, _ShieldController_handleSignatureControllerStateChange, _ShieldController_handleTransactionControllerStateChange, _ShieldController_addCoverageResult, _ShieldController_logSignature, _ShieldController_logTransaction, _ShieldController_getCoverageStatus, _ShieldController_getLatestCoverageId;
12
+ var _ShieldController_instances, _ShieldController_backend, _ShieldController_coverageHistoryLimit, _ShieldController_transactionHistoryLimit, _ShieldController_normalizeSignatureRequest, _ShieldController_transactionControllerStateChangeHandler, _ShieldController_signatureControllerStateChangeHandler, _ShieldController_started, _ShieldController_handleSignatureControllerStateChange, _ShieldController_handleTransactionControllerStateChange, _ShieldController_addCoverageResult, _ShieldController_logSignature, _ShieldController_logTransaction, _ShieldController_getCoverageShownStatus, _ShieldController_getLatestCoverageId;
13
13
  import { BaseController } from "@metamask/base-controller";
14
14
  import { SignatureRequestStatus } from "@metamask/signature-controller";
15
15
  import { TransactionStatus } from "@metamask/transaction-controller";
@@ -75,6 +75,9 @@ export class ShieldController extends BaseController {
75
75
  __classPrivateFieldSet(this, _ShieldController_started, false, "f");
76
76
  __classPrivateFieldSet(this, _ShieldController_normalizeSignatureRequest, normalizeSignatureRequest, "f");
77
77
  }
78
+ /**
79
+ * Start the ShieldController and subscribe to the transaction and signature controller state changes.
80
+ */
78
81
  start() {
79
82
  if (__classPrivateFieldGet(this, _ShieldController_started, "f")) {
80
83
  return;
@@ -83,6 +86,9 @@ export class ShieldController extends BaseController {
83
86
  this.messenger.subscribe('TransactionController:stateChange', __classPrivateFieldGet(this, _ShieldController_transactionControllerStateChangeHandler, "f"), (state) => state.transactions);
84
87
  this.messenger.subscribe('SignatureController:stateChange', __classPrivateFieldGet(this, _ShieldController_signatureControllerStateChangeHandler, "f"), (state) => state.signatureRequests);
85
88
  }
89
+ /**
90
+ * Stop the ShieldController and unsubscribe from the transaction and signature controller state changes.
91
+ */
86
92
  stop() {
87
93
  if (!__classPrivateFieldGet(this, _ShieldController_started, "f")) {
88
94
  return;
@@ -231,7 +237,7 @@ _ShieldController_backend = new WeakMap(), _ShieldController_coverageHistoryLimi
231
237
  if (!signature) {
232
238
  throw new Error('Signature not found');
233
239
  }
234
- const { status } = __classPrivateFieldGet(this, _ShieldController_instances, "m", _ShieldController_getCoverageStatus).call(this, signatureRequest.id);
240
+ const { status } = __classPrivateFieldGet(this, _ShieldController_instances, "m", _ShieldController_getCoverageShownStatus).call(this, signatureRequest.id);
235
241
  await __classPrivateFieldGet(this, _ShieldController_backend, "f").logSignature({
236
242
  signatureRequest,
237
243
  signature,
@@ -246,14 +252,14 @@ _ShieldController_backend = new WeakMap(), _ShieldController_coverageHistoryLimi
246
252
  if (!rawTransactionHex) {
247
253
  throw new Error('Raw transaction hex not found');
248
254
  }
249
- const { status } = __classPrivateFieldGet(this, _ShieldController_instances, "m", _ShieldController_getCoverageStatus).call(this, txMeta.id);
255
+ const { status } = __classPrivateFieldGet(this, _ShieldController_instances, "m", _ShieldController_getCoverageShownStatus).call(this, txMeta.id);
250
256
  await __classPrivateFieldGet(this, _ShieldController_backend, "f").logTransaction({
251
257
  txMeta,
252
258
  transactionHash,
253
259
  rawTransactionHex,
254
260
  status,
255
261
  });
256
- }, _ShieldController_getCoverageStatus = function _ShieldController_getCoverageStatus(itemId) {
262
+ }, _ShieldController_getCoverageShownStatus = function _ShieldController_getCoverageShownStatus(itemId) {
257
263
  // The status is assigned as follows:
258
264
  // - 'shown' if we have a result
259
265
  // - 'not_shown' if we don't have a result
@@ -1 +1 @@
1
- {"version":3,"file":"ShieldController.mjs","sourceRoot":"","sources":["../src/ShieldController.ts"],"names":[],"mappings":"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","sourcesContent":["import { BaseController } from '@metamask/base-controller';\nimport type {\n ControllerGetStateAction,\n ControllerStateChangeEvent,\n} from '@metamask/base-controller';\nimport type { Messenger } from '@metamask/messenger';\nimport { SignatureRequestStatus } from '@metamask/signature-controller';\nimport type {\n SignatureRequest,\n SignatureStateChange,\n} from '@metamask/signature-controller';\nimport { TransactionStatus } from '@metamask/transaction-controller';\nimport type {\n TransactionControllerStateChangeEvent,\n TransactionMeta,\n} from '@metamask/transaction-controller';\nimport { cloneDeep, isEqual } from 'lodash';\n\nimport { controllerName } from './constants';\nimport { projectLogger, createModuleLogger } from './logger';\nimport type {\n CoverageResult,\n NormalizeSignatureRequestFn,\n ShieldBackend,\n} from './types';\n\nconst log = createModuleLogger(projectLogger, 'ShieldController');\n\nexport type CoverageResultRecordEntry = {\n /**\n * History of coverage results, latest first.\n */\n results: CoverageResult[];\n};\n\nexport type ShieldControllerState = {\n /**\n * Coverage results by transaction ID.\n */\n coverageResults: Record<\n string, // txId\n CoverageResultRecordEntry\n >;\n /**\n * List of txIds ordered by time, latest first.\n */\n orderedTransactionHistory: string[];\n};\n\n/**\n * Get the default state for the ShieldController.\n *\n * @returns The default state for the ShieldController.\n */\nexport function getDefaultShieldControllerState(): ShieldControllerState {\n return {\n coverageResults: {},\n orderedTransactionHistory: [],\n };\n}\n\nexport type ShieldControllerGetStateAction = ControllerGetStateAction<\n typeof controllerName,\n ShieldControllerState\n>;\n\nexport type ShieldControllerCheckCoverageAction = {\n type: `${typeof controllerName}:checkCoverage`;\n handler: ShieldController['checkCoverage'];\n};\n\n/**\n * The internal actions available to the ShieldController.\n */\nexport type ShieldControllerActions =\n | ShieldControllerGetStateAction\n | ShieldControllerCheckCoverageAction;\n\nexport type ShieldControllerCoverageResultReceivedEvent = {\n type: `${typeof controllerName}:coverageResultReceived`;\n payload: [coverageResult: CoverageResult];\n};\n\nexport type ShieldControllerStateChangeEvent = ControllerStateChangeEvent<\n typeof controllerName,\n ShieldControllerState\n>;\n\n/**\n * The internal events available to the ShieldController.\n */\nexport type ShieldControllerEvents =\n | ShieldControllerCoverageResultReceivedEvent\n | ShieldControllerStateChangeEvent;\n\n/**\n * The external events available to the ShieldController.\n */\ntype AllowedEvents =\n | SignatureStateChange\n | TransactionControllerStateChangeEvent;\n\n/**\n * The messenger of the {@link ShieldController}.\n */\nexport type ShieldControllerMessenger = Messenger<\n typeof controllerName,\n ShieldControllerActions,\n ShieldControllerEvents | AllowedEvents\n>;\n\n/**\n * Metadata for the ShieldController state, describing how to \"anonymize\"\n * the state and which parts should be persisted.\n */\nconst metadata = {\n coverageResults: {\n includeInStateLogs: true,\n persist: true,\n includeInDebugSnapshot: false,\n usedInUi: true,\n },\n orderedTransactionHistory: {\n includeInStateLogs: true,\n persist: true,\n includeInDebugSnapshot: false,\n usedInUi: false,\n },\n};\n\nexport type ShieldControllerOptions = {\n messenger: ShieldControllerMessenger;\n state?: Partial<ShieldControllerState>;\n backend: ShieldBackend;\n transactionHistoryLimit?: number;\n coverageHistoryLimit?: number;\n /**\n * Normalize the signature request before sending it to the backend.\n * Please note that the reason this is not being done internally is to\n * align the request body (data & params) with the security-alerts API.\n * The same normalization function which is used to normalize security-alerts request should be used here.\n *\n * @param signatureRequest - The signature request to normalize.\n * @returns The normalized signature request.\n */\n normalizeSignatureRequest?: NormalizeSignatureRequestFn;\n};\n\nexport class ShieldController extends BaseController<\n typeof controllerName,\n ShieldControllerState,\n ShieldControllerMessenger\n> {\n readonly #backend: ShieldBackend;\n\n readonly #coverageHistoryLimit: number;\n\n readonly #transactionHistoryLimit: number;\n\n readonly #normalizeSignatureRequest?: NormalizeSignatureRequestFn;\n\n readonly #transactionControllerStateChangeHandler: (\n transactions: TransactionMeta[],\n previousTransactions: TransactionMeta[] | undefined,\n ) => void;\n\n readonly #signatureControllerStateChangeHandler: (\n signatureRequests: Record<string, SignatureRequest>,\n previousSignatureRequests: Record<string, SignatureRequest> | undefined,\n ) => void;\n\n #started: boolean;\n\n constructor(options: ShieldControllerOptions) {\n const {\n messenger,\n state,\n backend,\n transactionHistoryLimit = 100,\n coverageHistoryLimit = 10,\n normalizeSignatureRequest,\n } = options;\n super({\n name: controllerName,\n metadata,\n messenger,\n state: {\n ...getDefaultShieldControllerState(),\n ...state,\n },\n });\n\n this.#backend = backend;\n this.#coverageHistoryLimit = coverageHistoryLimit;\n this.#transactionHistoryLimit = transactionHistoryLimit;\n this.#transactionControllerStateChangeHandler =\n this.#handleTransactionControllerStateChange.bind(this);\n this.#signatureControllerStateChangeHandler =\n this.#handleSignatureControllerStateChange.bind(this);\n this.#started = false;\n this.#normalizeSignatureRequest = normalizeSignatureRequest;\n }\n\n start() {\n if (this.#started) {\n return;\n }\n this.#started = true;\n\n this.messenger.subscribe(\n 'TransactionController:stateChange',\n this.#transactionControllerStateChangeHandler,\n (state) => state.transactions,\n );\n\n this.messenger.subscribe(\n 'SignatureController:stateChange',\n this.#signatureControllerStateChangeHandler,\n (state) => state.signatureRequests,\n );\n }\n\n stop() {\n if (!this.#started) {\n return;\n }\n this.#started = false;\n\n this.messenger.unsubscribe(\n 'TransactionController:stateChange',\n this.#transactionControllerStateChangeHandler,\n );\n\n this.messenger.unsubscribe(\n 'SignatureController:stateChange',\n this.#signatureControllerStateChangeHandler,\n );\n }\n\n #handleSignatureControllerStateChange(\n signatureRequests: Record<string, SignatureRequest>,\n previousSignatureRequests: Record<string, SignatureRequest> | undefined,\n ) {\n const signatureRequestsArray = Object.values(signatureRequests);\n const previousSignatureRequestsArray = Object.values(\n previousSignatureRequests ?? {},\n );\n const previousSignatureRequestsById = new Map<string, SignatureRequest>(\n previousSignatureRequestsArray.map((request) => [request.id, request]),\n );\n for (const signatureRequest of signatureRequestsArray) {\n const previousSignatureRequest = previousSignatureRequestsById.get(\n signatureRequest.id,\n );\n\n // Check coverage if the signature request is new.\n if (!previousSignatureRequest) {\n this.checkSignatureCoverage(signatureRequest).catch(\n // istanbul ignore next\n (error) => log('Error checking coverage:', error),\n );\n }\n\n // Log signature once the signature request has been fulfilled.\n if (\n signatureRequest.status === SignatureRequestStatus.Signed &&\n signatureRequest.status !== previousSignatureRequest?.status\n ) {\n this.#logSignature(signatureRequest).catch(\n // istanbul ignore next\n (error) => log('Error logging signature:', error),\n );\n }\n }\n }\n\n #handleTransactionControllerStateChange(\n transactions: TransactionMeta[],\n previousTransactions: TransactionMeta[] | undefined,\n ) {\n const previousTransactionsById = new Map<string, TransactionMeta>(\n previousTransactions?.map((tx) => [tx.id, tx]) ?? [],\n );\n for (const transaction of transactions) {\n const previousTransaction = previousTransactionsById.get(transaction.id);\n\n if (\n // We don't need to check coverage for submitted or confirmed transactions.\n transaction.status !== TransactionStatus.submitted &&\n transaction.status !== TransactionStatus.confirmed\n ) {\n // Check if the simulation data has changed.\n const simulationDataChanged =\n // only check if the previous transaction has simulation data and if it has changed\n // this is to avoid checking coverage for the `TWICE` (once when it's added to the state and once when it's simulated for the first time).\n // we only need to update the coverage result when the simulation data has changed.\n previousTransaction?.simulationData &&\n !isEqual(\n transaction.simulationData,\n previousTransaction.simulationData,\n );\n\n // Check coverage if the transaction is new or if the simulation data has\n // changed.\n if (!previousTransaction || simulationDataChanged) {\n this.checkCoverage(transaction).catch(\n // istanbul ignore next\n (error) => log('Error checking coverage:', error),\n );\n }\n }\n\n // Log transaction once it has been submitted.\n if (\n transaction.status === TransactionStatus.submitted &&\n transaction.status !== previousTransaction?.status\n ) {\n this.#logTransaction(transaction).catch(\n // istanbul ignore next\n (error) => log('Error logging transaction:', error),\n );\n }\n }\n }\n\n /**\n * Checks the coverage of a transaction.\n *\n * @param txMeta - The transaction to check coverage for.\n * @returns The coverage result.\n */\n async checkCoverage(txMeta: TransactionMeta): Promise<CoverageResult> {\n // Check coverage\n const coverageId = this.#getLatestCoverageId(txMeta.id);\n const coverageResult = await this.#backend.checkCoverage({\n txMeta,\n coverageId,\n });\n\n // Publish coverage result\n this.messenger.publish(\n `${controllerName}:coverageResultReceived`,\n coverageResult,\n );\n\n // Update state\n this.#addCoverageResult(txMeta.id, coverageResult);\n\n return coverageResult;\n }\n\n /**\n * Checks the coverage of a signature request.\n *\n * @param signatureRequest - The signature request to check coverage for.\n * @returns The coverage result.\n */\n async checkSignatureCoverage(\n signatureRequest: SignatureRequest,\n ): Promise<CoverageResult> {\n // Check coverage\n const coverageId = this.#getLatestCoverageId(signatureRequest.id);\n\n // Normalize the signature request before sending it to the backend.\n // This is to ensure that the signature data is normalized and consistent as the security alerts api calls.\n const clonedSignatureRequest = cloneDeep(signatureRequest);\n const normalizedSignatureRequest =\n this.#normalizeSignatureRequest?.(clonedSignatureRequest) ??\n clonedSignatureRequest;\n const coverageResult = await this.#backend.checkSignatureCoverage({\n signatureRequest: normalizedSignatureRequest,\n coverageId,\n });\n\n // Publish coverage result\n this.messenger.publish(\n `${controllerName}:coverageResultReceived`,\n coverageResult,\n );\n\n // Update state\n this.#addCoverageResult(signatureRequest.id, coverageResult);\n\n return coverageResult;\n }\n\n #addCoverageResult(txId: string, coverageResult: CoverageResult) {\n // Assert the coverageId hasn't changed.\n const latestCoverageId = this.#getLatestCoverageId(txId);\n if (latestCoverageId && coverageResult.coverageId !== latestCoverageId) {\n throw new Error('Coverage ID has changed');\n }\n\n this.update((draft) => {\n // Fetch coverage result entry.\n let newEntry = false;\n let coverageResultEntry = draft.coverageResults[txId];\n\n // Create new entry if necessary.\n if (!coverageResultEntry) {\n newEntry = true;\n coverageResultEntry = {\n results: [],\n };\n draft.coverageResults[txId] = coverageResultEntry;\n }\n\n // Trim coverage history if necessary.\n if (coverageResultEntry.results.length >= this.#coverageHistoryLimit) {\n coverageResultEntry.results.pop();\n }\n\n // Add new result.\n coverageResultEntry.results.unshift(coverageResult);\n\n // Add to history if new entry.\n const { orderedTransactionHistory } = draft;\n let removedTxId: string | undefined;\n if (newEntry) {\n // Trim transaction history if necessary.\n if (orderedTransactionHistory.length >= this.#transactionHistoryLimit) {\n removedTxId = orderedTransactionHistory.pop();\n // Delete corresponding coverage result entry.\n if (removedTxId) {\n delete draft.coverageResults[removedTxId];\n }\n }\n // Add to history.\n orderedTransactionHistory.unshift(txId);\n }\n });\n }\n\n async #logSignature(signatureRequest: SignatureRequest) {\n const signature = signatureRequest.rawSig;\n if (!signature) {\n throw new Error('Signature not found');\n }\n\n const { status } = this.#getCoverageStatus(signatureRequest.id);\n\n await this.#backend.logSignature({\n signatureRequest,\n signature,\n status,\n });\n }\n\n async #logTransaction(txMeta: TransactionMeta) {\n const transactionHash = txMeta.hash;\n if (!transactionHash) {\n throw new Error('Transaction hash not found');\n }\n\n const rawTransactionHex = txMeta.rawTx;\n if (!rawTransactionHex) {\n throw new Error('Raw transaction hex not found');\n }\n\n const { status } = this.#getCoverageStatus(txMeta.id);\n\n await this.#backend.logTransaction({\n txMeta,\n transactionHash,\n rawTransactionHex,\n status,\n });\n }\n\n #getCoverageStatus(itemId: string) {\n // The status is assigned as follows:\n // - 'shown' if we have a result\n // - 'not_shown' if we don't have a result\n const coverageId = this.#getLatestCoverageId(itemId);\n let status = 'shown';\n if (!coverageId) {\n log('Coverage ID not found for', itemId);\n status = 'not_shown';\n }\n return { status };\n }\n\n #getLatestCoverageId(itemId: string): string | undefined {\n return this.state.coverageResults[itemId]?.results[0]?.coverageId;\n }\n}\n"]}
1
+ {"version":3,"file":"ShieldController.mjs","sourceRoot":"","sources":["../src/ShieldController.ts"],"names":[],"mappings":"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","sourcesContent":["import { BaseController } from '@metamask/base-controller';\nimport type {\n ControllerGetStateAction,\n ControllerStateChangeEvent,\n} from '@metamask/base-controller';\nimport type { Messenger } from '@metamask/messenger';\nimport { SignatureRequestStatus } from '@metamask/signature-controller';\nimport type {\n SignatureRequest,\n SignatureStateChange,\n} from '@metamask/signature-controller';\nimport { TransactionStatus } from '@metamask/transaction-controller';\nimport type {\n TransactionControllerStateChangeEvent,\n TransactionMeta,\n} from '@metamask/transaction-controller';\nimport { cloneDeep, isEqual } from 'lodash';\n\nimport { controllerName } from './constants';\nimport { projectLogger, createModuleLogger } from './logger';\nimport type {\n CoverageResult,\n NormalizeSignatureRequestFn,\n ShieldBackend,\n} from './types';\n\nconst log = createModuleLogger(projectLogger, 'ShieldController');\n\nexport type CoverageResultRecordEntry = {\n /**\n * History of coverage results, latest first.\n */\n results: CoverageResult[];\n};\n\nexport type ShieldControllerState = {\n /**\n * Coverage results by transaction ID.\n */\n coverageResults: Record<\n string, // txId\n CoverageResultRecordEntry\n >;\n /**\n * List of txIds ordered by time, latest first.\n */\n orderedTransactionHistory: string[];\n};\n\n/**\n * Get the default state for the ShieldController.\n *\n * @returns The default state for the ShieldController.\n */\nexport function getDefaultShieldControllerState(): ShieldControllerState {\n return {\n coverageResults: {},\n orderedTransactionHistory: [],\n };\n}\n\nexport type ShieldControllerGetStateAction = ControllerGetStateAction<\n typeof controllerName,\n ShieldControllerState\n>;\n\nexport type ShieldControllerCheckCoverageAction = {\n type: `${typeof controllerName}:checkCoverage`;\n handler: ShieldController['checkCoverage'];\n};\n\n/**\n * The internal actions available to the ShieldController.\n */\nexport type ShieldControllerActions =\n | ShieldControllerGetStateAction\n | ShieldControllerCheckCoverageAction;\n\nexport type ShieldControllerCoverageResultReceivedEvent = {\n type: `${typeof controllerName}:coverageResultReceived`;\n payload: [coverageResult: CoverageResult];\n};\n\nexport type ShieldControllerStateChangeEvent = ControllerStateChangeEvent<\n typeof controllerName,\n ShieldControllerState\n>;\n\n/**\n * The internal events available to the ShieldController.\n */\nexport type ShieldControllerEvents =\n | ShieldControllerCoverageResultReceivedEvent\n | ShieldControllerStateChangeEvent;\n\n/**\n * The external events available to the ShieldController.\n */\ntype AllowedEvents =\n | SignatureStateChange\n | TransactionControllerStateChangeEvent;\n\n/**\n * The messenger of the {@link ShieldController}.\n */\nexport type ShieldControllerMessenger = Messenger<\n typeof controllerName,\n ShieldControllerActions,\n ShieldControllerEvents | AllowedEvents\n>;\n\n/**\n * Metadata for the ShieldController state, describing how to \"anonymize\"\n * the state and which parts should be persisted.\n */\nconst metadata = {\n coverageResults: {\n includeInStateLogs: true,\n persist: true,\n includeInDebugSnapshot: false,\n usedInUi: true,\n },\n orderedTransactionHistory: {\n includeInStateLogs: true,\n persist: true,\n includeInDebugSnapshot: false,\n usedInUi: false,\n },\n};\n\nexport type ShieldControllerOptions = {\n messenger: ShieldControllerMessenger;\n state?: Partial<ShieldControllerState>;\n backend: ShieldBackend;\n transactionHistoryLimit?: number;\n coverageHistoryLimit?: number;\n /**\n * Normalize the signature request before sending it to the backend.\n * Please note that the reason this is not being done internally is to\n * align the request body (data & params) with the security-alerts API.\n * The same normalization function which is used to normalize security-alerts request should be used here.\n *\n * @param signatureRequest - The signature request to normalize.\n * @returns The normalized signature request.\n */\n normalizeSignatureRequest?: NormalizeSignatureRequestFn;\n};\n\nexport class ShieldController extends BaseController<\n typeof controllerName,\n ShieldControllerState,\n ShieldControllerMessenger\n> {\n readonly #backend: ShieldBackend;\n\n readonly #coverageHistoryLimit: number;\n\n readonly #transactionHistoryLimit: number;\n\n readonly #normalizeSignatureRequest?: NormalizeSignatureRequestFn;\n\n readonly #transactionControllerStateChangeHandler: (\n transactions: TransactionMeta[],\n previousTransactions: TransactionMeta[] | undefined,\n ) => void;\n\n readonly #signatureControllerStateChangeHandler: (\n signatureRequests: Record<string, SignatureRequest>,\n previousSignatureRequests: Record<string, SignatureRequest> | undefined,\n ) => void;\n\n #started: boolean;\n\n constructor(options: ShieldControllerOptions) {\n const {\n messenger,\n state,\n backend,\n transactionHistoryLimit = 100,\n coverageHistoryLimit = 10,\n normalizeSignatureRequest,\n } = options;\n super({\n name: controllerName,\n metadata,\n messenger,\n state: {\n ...getDefaultShieldControllerState(),\n ...state,\n },\n });\n\n this.#backend = backend;\n this.#coverageHistoryLimit = coverageHistoryLimit;\n this.#transactionHistoryLimit = transactionHistoryLimit;\n this.#transactionControllerStateChangeHandler =\n this.#handleTransactionControllerStateChange.bind(this);\n this.#signatureControllerStateChangeHandler =\n this.#handleSignatureControllerStateChange.bind(this);\n this.#started = false;\n this.#normalizeSignatureRequest = normalizeSignatureRequest;\n }\n\n /**\n * Start the ShieldController and subscribe to the transaction and signature controller state changes.\n */\n start(): void {\n if (this.#started) {\n return;\n }\n this.#started = true;\n\n this.messenger.subscribe(\n 'TransactionController:stateChange',\n this.#transactionControllerStateChangeHandler,\n (state) => state.transactions,\n );\n\n this.messenger.subscribe(\n 'SignatureController:stateChange',\n this.#signatureControllerStateChangeHandler,\n (state) => state.signatureRequests,\n );\n }\n\n /**\n * Stop the ShieldController and unsubscribe from the transaction and signature controller state changes.\n */\n stop(): void {\n if (!this.#started) {\n return;\n }\n this.#started = false;\n\n this.messenger.unsubscribe(\n 'TransactionController:stateChange',\n this.#transactionControllerStateChangeHandler,\n );\n\n this.messenger.unsubscribe(\n 'SignatureController:stateChange',\n this.#signatureControllerStateChangeHandler,\n );\n }\n\n #handleSignatureControllerStateChange(\n signatureRequests: Record<string, SignatureRequest>,\n previousSignatureRequests: Record<string, SignatureRequest> | undefined,\n ): void {\n const signatureRequestsArray = Object.values(signatureRequests);\n const previousSignatureRequestsArray = Object.values(\n previousSignatureRequests ?? {},\n );\n const previousSignatureRequestsById = new Map<string, SignatureRequest>(\n previousSignatureRequestsArray.map((request) => [request.id, request]),\n );\n for (const signatureRequest of signatureRequestsArray) {\n const previousSignatureRequest = previousSignatureRequestsById.get(\n signatureRequest.id,\n );\n\n // Check coverage if the signature request is new.\n if (!previousSignatureRequest) {\n this.checkSignatureCoverage(signatureRequest).catch(\n // istanbul ignore next\n (error) => log('Error checking coverage:', error),\n );\n }\n\n // Log signature once the signature request has been fulfilled.\n if (\n signatureRequest.status === SignatureRequestStatus.Signed &&\n signatureRequest.status !== previousSignatureRequest?.status\n ) {\n this.#logSignature(signatureRequest).catch(\n // istanbul ignore next\n (error) => log('Error logging signature:', error),\n );\n }\n }\n }\n\n #handleTransactionControllerStateChange(\n transactions: TransactionMeta[],\n previousTransactions: TransactionMeta[] | undefined,\n ): void {\n const previousTransactionsById = new Map<string, TransactionMeta>(\n previousTransactions?.map((tx) => [tx.id, tx]) ?? [],\n );\n for (const transaction of transactions) {\n const previousTransaction = previousTransactionsById.get(transaction.id);\n\n if (\n // We don't need to check coverage for submitted or confirmed transactions.\n transaction.status !== TransactionStatus.submitted &&\n transaction.status !== TransactionStatus.confirmed\n ) {\n // Check if the simulation data has changed.\n const simulationDataChanged =\n // only check if the previous transaction has simulation data and if it has changed\n // this is to avoid checking coverage for the `TWICE` (once when it's added to the state and once when it's simulated for the first time).\n // we only need to update the coverage result when the simulation data has changed.\n previousTransaction?.simulationData &&\n !isEqual(\n transaction.simulationData,\n previousTransaction.simulationData,\n );\n\n // Check coverage if the transaction is new or if the simulation data has\n // changed.\n if (!previousTransaction || simulationDataChanged) {\n this.checkCoverage(transaction).catch(\n // istanbul ignore next\n (error) => log('Error checking coverage:', error),\n );\n }\n }\n\n // Log transaction once it has been submitted.\n if (\n transaction.status === TransactionStatus.submitted &&\n transaction.status !== previousTransaction?.status\n ) {\n this.#logTransaction(transaction).catch(\n // istanbul ignore next\n (error) => log('Error logging transaction:', error),\n );\n }\n }\n }\n\n /**\n * Checks the coverage of a transaction.\n *\n * @param txMeta - The transaction to check coverage for.\n * @returns The coverage result.\n */\n async checkCoverage(txMeta: TransactionMeta): Promise<CoverageResult> {\n // Check coverage\n const coverageId = this.#getLatestCoverageId(txMeta.id);\n const coverageResult = await this.#backend.checkCoverage({\n txMeta,\n coverageId,\n });\n\n // Publish coverage result\n this.messenger.publish(\n `${controllerName}:coverageResultReceived`,\n coverageResult,\n );\n\n // Update state\n this.#addCoverageResult(txMeta.id, coverageResult);\n\n return coverageResult;\n }\n\n /**\n * Checks the coverage of a signature request.\n *\n * @param signatureRequest - The signature request to check coverage for.\n * @returns The coverage result.\n */\n async checkSignatureCoverage(\n signatureRequest: SignatureRequest,\n ): Promise<CoverageResult> {\n // Check coverage\n const coverageId = this.#getLatestCoverageId(signatureRequest.id);\n\n // Normalize the signature request before sending it to the backend.\n // This is to ensure that the signature data is normalized and consistent as the security alerts api calls.\n const clonedSignatureRequest = cloneDeep(signatureRequest);\n const normalizedSignatureRequest =\n this.#normalizeSignatureRequest?.(clonedSignatureRequest) ??\n clonedSignatureRequest;\n const coverageResult = await this.#backend.checkSignatureCoverage({\n signatureRequest: normalizedSignatureRequest,\n coverageId,\n });\n\n // Publish coverage result\n this.messenger.publish(\n `${controllerName}:coverageResultReceived`,\n coverageResult,\n );\n\n // Update state\n this.#addCoverageResult(signatureRequest.id, coverageResult);\n\n return coverageResult;\n }\n\n #addCoverageResult(txId: string, coverageResult: CoverageResult): void {\n // Assert the coverageId hasn't changed.\n const latestCoverageId = this.#getLatestCoverageId(txId);\n if (latestCoverageId && coverageResult.coverageId !== latestCoverageId) {\n throw new Error('Coverage ID has changed');\n }\n\n this.update((draft) => {\n // Fetch coverage result entry.\n let newEntry = false;\n let coverageResultEntry = draft.coverageResults[txId];\n\n // Create new entry if necessary.\n if (!coverageResultEntry) {\n newEntry = true;\n coverageResultEntry = {\n results: [],\n };\n draft.coverageResults[txId] = coverageResultEntry;\n }\n\n // Trim coverage history if necessary.\n if (coverageResultEntry.results.length >= this.#coverageHistoryLimit) {\n coverageResultEntry.results.pop();\n }\n\n // Add new result.\n coverageResultEntry.results.unshift(coverageResult);\n\n // Add to history if new entry.\n const { orderedTransactionHistory } = draft;\n let removedTxId: string | undefined;\n if (newEntry) {\n // Trim transaction history if necessary.\n if (orderedTransactionHistory.length >= this.#transactionHistoryLimit) {\n removedTxId = orderedTransactionHistory.pop();\n // Delete corresponding coverage result entry.\n if (removedTxId) {\n delete draft.coverageResults[removedTxId];\n }\n }\n // Add to history.\n orderedTransactionHistory.unshift(txId);\n }\n });\n }\n\n async #logSignature(signatureRequest: SignatureRequest): Promise<void> {\n const signature = signatureRequest.rawSig;\n if (!signature) {\n throw new Error('Signature not found');\n }\n\n const { status } = this.#getCoverageShownStatus(signatureRequest.id);\n\n await this.#backend.logSignature({\n signatureRequest,\n signature,\n status,\n });\n }\n\n async #logTransaction(txMeta: TransactionMeta): Promise<void> {\n const transactionHash = txMeta.hash;\n if (!transactionHash) {\n throw new Error('Transaction hash not found');\n }\n\n const rawTransactionHex = txMeta.rawTx;\n if (!rawTransactionHex) {\n throw new Error('Raw transaction hex not found');\n }\n\n const { status } = this.#getCoverageShownStatus(txMeta.id);\n\n await this.#backend.logTransaction({\n txMeta,\n transactionHash,\n rawTransactionHex,\n status,\n });\n }\n\n /**\n * Get the coverage shown status for a given item ID.\n *\n * @param itemId - The item ID to get the coverage status for.\n * @returns The coverage status.\n */\n #getCoverageShownStatus(itemId: string): { status: string } {\n // The status is assigned as follows:\n // - 'shown' if we have a result\n // - 'not_shown' if we don't have a result\n const coverageId = this.#getLatestCoverageId(itemId);\n let status = 'shown';\n if (!coverageId) {\n log('Coverage ID not found for', itemId);\n status = 'not_shown';\n }\n return { status };\n }\n\n #getLatestCoverageId(itemId: string): string | undefined {\n return this.state.coverageResults[itemId]?.results[0]?.coverageId;\n }\n}\n"]}
package/dist/backend.cjs CHANGED
@@ -10,7 +10,7 @@ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (
10
10
  if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
11
11
  return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
12
12
  };
13
- var _ShieldRemoteBackend_instances, _ShieldRemoteBackend_getAccessToken, _ShieldRemoteBackend_baseUrl, _ShieldRemoteBackend_fetch, _ShieldRemoteBackend_pollingPolicy, _ShieldRemoteBackend_initCoverageCheck, _ShieldRemoteBackend_getCoverageResult, _ShieldRemoteBackend_createHeaders;
13
+ var _ShieldRemoteBackend_instances, _ShieldRemoteBackend_getAccessToken, _ShieldRemoteBackend_baseUrl, _ShieldRemoteBackend_fetch, _ShieldRemoteBackend_pollingPolicy, _ShieldRemoteBackend_captureException, _ShieldRemoteBackend_initCoverageCheck, _ShieldRemoteBackend_getCoverageResult, _ShieldRemoteBackend_createHeaders;
14
14
  Object.defineProperty(exports, "__esModule", { value: true });
15
15
  exports.parseSignatureRequestMethod = exports.makeInitCoverageCheckBody = exports.ShieldRemoteBackend = void 0;
16
16
  const controller_utils_1 = require("@metamask/controller-utils");
@@ -20,12 +20,13 @@ const polling_with_policy_1 = require("./polling-with-policy.cjs");
20
20
  class ShieldRemoteBackend {
21
21
  constructor({ getAccessToken, getCoverageResultTimeout = 5000, // milliseconds
22
22
  getCoverageResultPollInterval = 1000, // milliseconds
23
- baseUrl, fetch: fetchFn, }) {
23
+ baseUrl, fetch: fetchFn, captureException: captureExceptionFn, }) {
24
24
  _ShieldRemoteBackend_instances.add(this);
25
25
  _ShieldRemoteBackend_getAccessToken.set(this, void 0);
26
26
  _ShieldRemoteBackend_baseUrl.set(this, void 0);
27
27
  _ShieldRemoteBackend_fetch.set(this, void 0);
28
28
  _ShieldRemoteBackend_pollingPolicy.set(this, void 0);
29
+ _ShieldRemoteBackend_captureException.set(this, void 0);
29
30
  __classPrivateFieldSet(this, _ShieldRemoteBackend_getAccessToken, getAccessToken, "f");
30
31
  __classPrivateFieldSet(this, _ShieldRemoteBackend_baseUrl, baseUrl, "f");
31
32
  __classPrivateFieldSet(this, _ShieldRemoteBackend_fetch, fetchFn, "f");
@@ -34,6 +35,14 @@ class ShieldRemoteBackend {
34
35
  backoff,
35
36
  maxRetries,
36
37
  }), "f");
38
+ __classPrivateFieldSet(this, _ShieldRemoteBackend_captureException, (error) => {
39
+ try {
40
+ captureExceptionFn?.(error);
41
+ }
42
+ catch {
43
+ // ignore error thrown when calling captureException
44
+ }
45
+ }, "f");
37
46
  }
38
47
  async checkCoverage(req) {
39
48
  let { coverageId } = req;
@@ -68,54 +77,78 @@ class ShieldRemoteBackend {
68
77
  };
69
78
  }
70
79
  async logSignature(req) {
71
- const initBody = makeInitSignatureCoverageCheckBody(req.signatureRequest);
72
- const body = {
73
- signature: req.signature,
74
- status: req.status,
75
- ...initBody,
76
- };
77
- // cancel the pending get coverage result request
78
- __classPrivateFieldGet(this, _ShieldRemoteBackend_pollingPolicy, "f").abortPendingRequest(req.signatureRequest.id);
79
- const res = await __classPrivateFieldGet(this, _ShieldRemoteBackend_fetch, "f").call(this, `${__classPrivateFieldGet(this, _ShieldRemoteBackend_baseUrl, "f")}/v1/signature/coverage/log`, {
80
- method: 'POST',
81
- headers: await __classPrivateFieldGet(this, _ShieldRemoteBackend_instances, "m", _ShieldRemoteBackend_createHeaders).call(this),
82
- body: JSON.stringify(body),
83
- });
84
- if (res.status !== 200) {
85
- throw new Error(`Failed to log signature: ${res.status}`);
80
+ try {
81
+ const initBody = makeInitSignatureCoverageCheckBody(req.signatureRequest);
82
+ const body = {
83
+ signature: req.signature,
84
+ status: req.status,
85
+ ...initBody,
86
+ };
87
+ // cancel the pending get coverage result request
88
+ __classPrivateFieldGet(this, _ShieldRemoteBackend_pollingPolicy, "f").abortPendingRequest(req.signatureRequest.id);
89
+ const res = await __classPrivateFieldGet(this, _ShieldRemoteBackend_fetch, "f").call(this, `${__classPrivateFieldGet(this, _ShieldRemoteBackend_baseUrl, "f")}/v1/signature/coverage/log`, {
90
+ method: 'POST',
91
+ headers: await __classPrivateFieldGet(this, _ShieldRemoteBackend_instances, "m", _ShieldRemoteBackend_createHeaders).call(this),
92
+ body: JSON.stringify(body),
93
+ });
94
+ if (res.status !== 200) {
95
+ throw new Error(`Failed to log signature: ${res.status}`);
96
+ }
97
+ }
98
+ catch (error) {
99
+ const sentryError = createSentryError('Failed to log signature', error);
100
+ __classPrivateFieldGet(this, _ShieldRemoteBackend_captureException, "f")?.call(this, sentryError);
101
+ // rethrow the original error
102
+ throw error;
86
103
  }
87
104
  }
88
105
  async logTransaction(req) {
89
- const initBody = makeInitCoverageCheckBody(req.txMeta);
90
- const body = {
91
- transactionHash: req.transactionHash,
92
- rawTransactionHex: req.rawTransactionHex,
93
- status: req.status,
94
- ...initBody,
95
- };
96
- // cancel the pending get coverage result request
97
- __classPrivateFieldGet(this, _ShieldRemoteBackend_pollingPolicy, "f").abortPendingRequest(req.txMeta.id);
98
- const res = await __classPrivateFieldGet(this, _ShieldRemoteBackend_fetch, "f").call(this, `${__classPrivateFieldGet(this, _ShieldRemoteBackend_baseUrl, "f")}/v1/transaction/coverage/log`, {
106
+ try {
107
+ const initBody = makeInitCoverageCheckBody(req.txMeta);
108
+ const body = {
109
+ transactionHash: req.transactionHash,
110
+ rawTransactionHex: req.rawTransactionHex,
111
+ status: req.status,
112
+ ...initBody,
113
+ };
114
+ // cancel the pending get coverage result request
115
+ __classPrivateFieldGet(this, _ShieldRemoteBackend_pollingPolicy, "f").abortPendingRequest(req.txMeta.id);
116
+ const res = await __classPrivateFieldGet(this, _ShieldRemoteBackend_fetch, "f").call(this, `${__classPrivateFieldGet(this, _ShieldRemoteBackend_baseUrl, "f")}/v1/transaction/coverage/log`, {
117
+ method: 'POST',
118
+ headers: await __classPrivateFieldGet(this, _ShieldRemoteBackend_instances, "m", _ShieldRemoteBackend_createHeaders).call(this),
119
+ body: JSON.stringify(body),
120
+ });
121
+ if (res.status !== 200) {
122
+ throw new Error(`Failed to log transaction: ${res.status}`);
123
+ }
124
+ }
125
+ catch (error) {
126
+ const sentryError = createSentryError('Failed to log transaction', error);
127
+ __classPrivateFieldGet(this, _ShieldRemoteBackend_captureException, "f")?.call(this, sentryError);
128
+ // rethrow the original error
129
+ throw error;
130
+ }
131
+ }
132
+ }
133
+ exports.ShieldRemoteBackend = ShieldRemoteBackend;
134
+ _ShieldRemoteBackend_getAccessToken = new WeakMap(), _ShieldRemoteBackend_baseUrl = new WeakMap(), _ShieldRemoteBackend_fetch = new WeakMap(), _ShieldRemoteBackend_pollingPolicy = new WeakMap(), _ShieldRemoteBackend_captureException = new WeakMap(), _ShieldRemoteBackend_instances = new WeakSet(), _ShieldRemoteBackend_initCoverageCheck = async function _ShieldRemoteBackend_initCoverageCheck(path, reqBody) {
135
+ try {
136
+ const res = await __classPrivateFieldGet(this, _ShieldRemoteBackend_fetch, "f").call(this, `${__classPrivateFieldGet(this, _ShieldRemoteBackend_baseUrl, "f")}/${path}`, {
99
137
  method: 'POST',
100
138
  headers: await __classPrivateFieldGet(this, _ShieldRemoteBackend_instances, "m", _ShieldRemoteBackend_createHeaders).call(this),
101
- body: JSON.stringify(body),
139
+ body: JSON.stringify(reqBody),
102
140
  });
103
141
  if (res.status !== 200) {
104
- throw new Error(`Failed to log transaction: ${res.status}`);
142
+ throw new Error(`Failed to init coverage check: ${res.status}`);
105
143
  }
144
+ return (await res.json());
106
145
  }
107
- }
108
- exports.ShieldRemoteBackend = ShieldRemoteBackend;
109
- _ShieldRemoteBackend_getAccessToken = new WeakMap(), _ShieldRemoteBackend_baseUrl = new WeakMap(), _ShieldRemoteBackend_fetch = new WeakMap(), _ShieldRemoteBackend_pollingPolicy = new WeakMap(), _ShieldRemoteBackend_instances = new WeakSet(), _ShieldRemoteBackend_initCoverageCheck = async function _ShieldRemoteBackend_initCoverageCheck(path, reqBody) {
110
- const res = await __classPrivateFieldGet(this, _ShieldRemoteBackend_fetch, "f").call(this, `${__classPrivateFieldGet(this, _ShieldRemoteBackend_baseUrl, "f")}/${path}`, {
111
- method: 'POST',
112
- headers: await __classPrivateFieldGet(this, _ShieldRemoteBackend_instances, "m", _ShieldRemoteBackend_createHeaders).call(this),
113
- body: JSON.stringify(reqBody),
114
- });
115
- if (res.status !== 200) {
116
- throw new Error(`Failed to init coverage check: ${res.status}`);
146
+ catch (error) {
147
+ const sentryError = createSentryError('Failed to init coverage check', error);
148
+ __classPrivateFieldGet(this, _ShieldRemoteBackend_captureException, "f")?.call(this, sentryError);
149
+ // rethrow the original error
150
+ throw error;
117
151
  }
118
- return (await res.json());
119
152
  }, _ShieldRemoteBackend_getCoverageResult = async function _ShieldRemoteBackend_getCoverageResult(requestId, coverageId, coverageResultUrl) {
120
153
  const reqBody = {
121
154
  coverageId,
@@ -138,7 +171,7 @@ _ShieldRemoteBackend_getAccessToken = new WeakMap(), _ShieldRemoteBackend_baseUr
138
171
  let errorMessage = 'Timeout waiting for coverage result';
139
172
  try {
140
173
  const errorJson = await res.json();
141
- errorMessage = `Failed to get coverage result: ${errorJson.message || errorJson.status}`;
174
+ errorMessage = `Failed to get coverage result: ${errorJson.message ?? errorJson.status}`;
142
175
  }
143
176
  catch {
144
177
  errorMessage = `Failed to get coverage result: ${res.status}`;
@@ -241,4 +274,16 @@ function computePollingIntervalAndRetryCount(timeout, pollInterval) {
241
274
  maxRetries,
242
275
  };
243
276
  }
277
+ /**
278
+ * Create an error instance with a readable message, a cause and a context for Sentry.
279
+ *
280
+ * @param errorMessage - The error message.
281
+ * @param cause - The cause of the error.
282
+ * @returns A Sentry error.
283
+ */
284
+ function createSentryError(errorMessage, cause) {
285
+ const error = new Error(errorMessage);
286
+ error.cause = cause;
287
+ return error;
288
+ }
244
289
  //# sourceMappingURL=backend.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"backend.cjs","sourceRoot":"","sources":["../src/backend.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n ConstantBackoff,\n DEFAULT_MAX_RETRIES,\n HttpError,\n} from '@metamask/controller-utils';\nimport {\n EthMethod,\n SignatureRequestType,\n} from '@metamask/signature-controller';\nimport type { SignatureRequest } from '@metamask/signature-controller';\nimport type { TransactionMeta } from '@metamask/transaction-controller';\nimport type { AuthorizationList } from '@metamask/transaction-controller';\nimport type { Json } from '@metamask/utils';\n\nimport { SignTypedDataVersion } from './constants';\nimport { PollingWithCockatielPolicy } from './polling-with-policy';\nimport type {\n CheckCoverageRequest,\n CheckSignatureCoverageRequest,\n CoverageResult,\n CoverageStatus,\n LogSignatureRequest,\n LogTransactionRequest,\n ShieldBackend,\n} from './types';\n\nexport type InitCoverageCheckRequest = {\n txParams: [\n {\n authorizationList?: AuthorizationList;\n from: string;\n to?: string;\n value?: string;\n data?: string;\n nonce?: string;\n },\n ];\n chainId: string;\n origin?: string;\n};\n\nexport type InitSignatureCoverageCheckRequest = {\n chainId: string;\n data: Json;\n from: string;\n method: string;\n origin?: string;\n};\n\nexport type InitCoverageCheckResponse = {\n coverageId: string;\n};\n\nexport type GetCoverageResultRequest = {\n coverageId: string;\n};\n\nexport type GetCoverageResultResponse = {\n message?: string;\n reasonCode?: string;\n status: CoverageStatus;\n metrics: {\n latency?: number;\n };\n};\n\nexport class ShieldRemoteBackend implements ShieldBackend {\n readonly #getAccessToken: () => Promise<string>;\n\n readonly #baseUrl: string;\n\n readonly #fetch: typeof globalThis.fetch;\n\n readonly #pollingPolicy: PollingWithCockatielPolicy;\n\n constructor({\n getAccessToken,\n getCoverageResultTimeout = 5000, // milliseconds\n getCoverageResultPollInterval = 1000, // milliseconds\n baseUrl,\n fetch: fetchFn,\n }: {\n getAccessToken: () => Promise<string>;\n getCoverageResultTimeout?: number;\n getCoverageResultPollInterval?: number;\n baseUrl: string;\n fetch: typeof globalThis.fetch;\n }) {\n this.#getAccessToken = getAccessToken;\n this.#baseUrl = baseUrl;\n this.#fetch = fetchFn;\n\n const { backoff, maxRetries } = computePollingIntervalAndRetryCount(\n getCoverageResultTimeout,\n getCoverageResultPollInterval,\n );\n\n this.#pollingPolicy = new PollingWithCockatielPolicy({\n backoff,\n maxRetries,\n });\n }\n\n async checkCoverage(req: CheckCoverageRequest): Promise<CoverageResult> {\n let { coverageId } = req;\n if (!coverageId) {\n const reqBody = makeInitCoverageCheckBody(req.txMeta);\n ({ coverageId } = await this.#initCoverageCheck(\n 'v1/transaction/coverage/init',\n reqBody,\n ));\n }\n\n const txCoverageResultUrl = `${this.#baseUrl}/v1/transaction/coverage/result`;\n const coverageResult = await this.#getCoverageResult(\n req.txMeta.id,\n coverageId,\n txCoverageResultUrl,\n );\n return {\n coverageId,\n message: coverageResult.message,\n reasonCode: coverageResult.reasonCode,\n status: coverageResult.status,\n metrics: coverageResult.metrics,\n };\n }\n\n async checkSignatureCoverage(\n req: CheckSignatureCoverageRequest,\n ): Promise<CoverageResult> {\n let { coverageId } = req;\n if (!coverageId) {\n const reqBody = makeInitSignatureCoverageCheckBody(req.signatureRequest);\n ({ coverageId } = await this.#initCoverageCheck(\n 'v1/signature/coverage/init',\n reqBody,\n ));\n }\n\n const signatureCoverageResultUrl = `${this.#baseUrl}/v1/signature/coverage/result`;\n const coverageResult = await this.#getCoverageResult(\n req.signatureRequest.id,\n coverageId,\n signatureCoverageResultUrl,\n );\n return {\n coverageId,\n message: coverageResult.message,\n reasonCode: coverageResult.reasonCode,\n status: coverageResult.status,\n metrics: coverageResult.metrics,\n };\n }\n\n async logSignature(req: LogSignatureRequest): Promise<void> {\n const initBody = makeInitSignatureCoverageCheckBody(req.signatureRequest);\n const body = {\n signature: req.signature,\n status: req.status,\n ...initBody,\n };\n\n // cancel the pending get coverage result request\n this.#pollingPolicy.abortPendingRequest(req.signatureRequest.id);\n\n const res = await this.#fetch(\n `${this.#baseUrl}/v1/signature/coverage/log`,\n {\n method: 'POST',\n headers: await this.#createHeaders(),\n body: JSON.stringify(body),\n },\n );\n if (res.status !== 200) {\n throw new Error(`Failed to log signature: ${res.status}`);\n }\n }\n\n async logTransaction(req: LogTransactionRequest): Promise<void> {\n const initBody = makeInitCoverageCheckBody(req.txMeta);\n\n const body = {\n transactionHash: req.transactionHash,\n rawTransactionHex: req.rawTransactionHex,\n status: req.status,\n ...initBody,\n };\n\n // cancel the pending get coverage result request\n this.#pollingPolicy.abortPendingRequest(req.txMeta.id);\n\n const res = await this.#fetch(\n `${this.#baseUrl}/v1/transaction/coverage/log`,\n {\n method: 'POST',\n headers: await this.#createHeaders(),\n body: JSON.stringify(body),\n },\n );\n if (res.status !== 200) {\n throw new Error(`Failed to log transaction: ${res.status}`);\n }\n }\n\n async #initCoverageCheck(\n path: string,\n reqBody: unknown,\n ): Promise<InitCoverageCheckResponse> {\n const res = await this.#fetch(`${this.#baseUrl}/${path}`, {\n method: 'POST',\n headers: await this.#createHeaders(),\n body: JSON.stringify(reqBody),\n });\n if (res.status !== 200) {\n throw new Error(`Failed to init coverage check: ${res.status}`);\n }\n return (await res.json()) as InitCoverageCheckResponse;\n }\n\n async #getCoverageResult(\n requestId: string,\n coverageId: string,\n coverageResultUrl: string,\n ): Promise<GetCoverageResultResponse> {\n const reqBody: GetCoverageResultRequest = {\n coverageId,\n };\n\n const headers = await this.#createHeaders();\n\n // Start measuring total end-to-end latency including retries and delays\n const startTime = Date.now();\n\n const getCoverageResultFn = async (signal: AbortSignal) => {\n const res = await this.#fetch(coverageResultUrl, {\n method: 'POST',\n headers,\n body: JSON.stringify(reqBody),\n signal,\n });\n\n if (res.status === 200) {\n // Return the result without latency here - we'll add total latency after polling completes\n return (await res.json()) as Omit<GetCoverageResultResponse, 'metrics'>;\n }\n\n // parse the error message from the response body\n let errorMessage = 'Timeout waiting for coverage result';\n try {\n const errorJson = await res.json();\n errorMessage = `Failed to get coverage result: ${errorJson.message || errorJson.status}`;\n } catch {\n errorMessage = `Failed to get coverage result: ${res.status}`;\n }\n throw new HttpError(res.status, errorMessage);\n };\n\n const result = await this.#pollingPolicy.start(\n requestId,\n getCoverageResultFn,\n );\n\n // Calculate total end-to-end latency including all retries and delays\n const now = Date.now();\n const totalLatency = now - startTime;\n\n return {\n ...result,\n metrics: { latency: totalLatency },\n } as GetCoverageResultResponse;\n }\n\n async #createHeaders() {\n const accessToken = await this.#getAccessToken();\n return {\n 'Content-Type': 'application/json',\n Authorization: `Bearer ${accessToken}`,\n };\n }\n}\n\n/**\n * Make the body for the init coverage check request.\n *\n * @param txMeta - The transaction metadata.\n * @returns The body for the init coverage check request.\n */\nexport function makeInitCoverageCheckBody(\n txMeta: TransactionMeta,\n): InitCoverageCheckRequest {\n return {\n txParams: [\n {\n authorizationList: txMeta.txParams.authorizationList,\n from: txMeta.txParams.from,\n to: txMeta.txParams.to,\n value: txMeta.txParams.value,\n data: txMeta.txParams.data,\n nonce: txMeta.txParams.nonce,\n },\n ],\n chainId: txMeta.chainId,\n origin: txMeta.origin,\n };\n}\n\n/**\n * Make the body for the init signature coverage check request.\n *\n * @param signatureRequest - The signature request.\n * @returns The body for the init signature coverage check request.\n */\nfunction makeInitSignatureCoverageCheckBody(\n signatureRequest: SignatureRequest,\n): InitSignatureCoverageCheckRequest {\n // TODO: confirm that do we still need to validate the signature data?\n // signature controller already validates the signature data before adding it to the state.\n // @link https://github.com/MetaMask/core/blob/main/packages/signature-controller/src/SignatureController.ts#L408\n const method = parseSignatureRequestMethod(signatureRequest);\n\n return {\n chainId: signatureRequest.chainId,\n data: signatureRequest.messageParams.data,\n from: signatureRequest.messageParams.from,\n method,\n origin: signatureRequest.messageParams.origin,\n };\n}\n\n/**\n * Parse the JSON-RPC method from the signature request.\n *\n * @param signatureRequest - The signature request.\n * @returns The JSON-RPC method.\n */\nexport function parseSignatureRequestMethod(\n signatureRequest: SignatureRequest,\n): string {\n if (signatureRequest.type === SignatureRequestType.TypedSign) {\n switch (signatureRequest.version) {\n case SignTypedDataVersion.V3:\n return EthMethod.SignTypedDataV3;\n case SignTypedDataVersion.V4:\n return EthMethod.SignTypedDataV4;\n case SignTypedDataVersion.V1:\n default:\n return SignatureRequestType.TypedSign;\n }\n }\n\n return signatureRequest.type;\n}\n\n/**\n * Compute the polling interval and retry count for the Cockatiel policy based on the timeout and poll interval given.\n *\n * @param timeout - The timeout in milliseconds.\n * @param pollInterval - The poll interval in milliseconds.\n * @returns The polling interval and retry count.\n */\nfunction computePollingIntervalAndRetryCount(\n timeout: number,\n pollInterval: number,\n) {\n const backoff = new ConstantBackoff(pollInterval);\n const computedMaxRetries = Math.floor(timeout / pollInterval) + 1;\n\n const maxRetries =\n isNaN(computedMaxRetries) || !isFinite(computedMaxRetries)\n ? DEFAULT_MAX_RETRIES\n : computedMaxRetries;\n\n return {\n backoff,\n maxRetries,\n };\n}\n"]}
1
+ {"version":3,"file":"backend.cjs","sourceRoot":"","sources":["../src/backend.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n ConstantBackoff,\n DEFAULT_MAX_RETRIES,\n HttpError,\n} from '@metamask/controller-utils';\nimport {\n EthMethod,\n SignatureRequestType,\n} from '@metamask/signature-controller';\nimport type { SignatureRequest } from '@metamask/signature-controller';\nimport type { TransactionMeta } from '@metamask/transaction-controller';\nimport type { AuthorizationList } from '@metamask/transaction-controller';\nimport type { Json } from '@metamask/utils';\n\nimport { SignTypedDataVersion } from './constants';\nimport { PollingWithCockatielPolicy } from './polling-with-policy';\nimport type {\n CheckCoverageRequest,\n CheckSignatureCoverageRequest,\n CoverageResult,\n CoverageStatus,\n LogSignatureRequest,\n LogTransactionRequest,\n ShieldBackend,\n} from './types';\n\nexport type InitCoverageCheckRequest = {\n txParams: [\n {\n authorizationList?: AuthorizationList;\n from: string;\n to?: string;\n value?: string;\n data?: string;\n nonce?: string;\n },\n ];\n chainId: string;\n origin?: string;\n};\n\nexport type InitSignatureCoverageCheckRequest = {\n chainId: string;\n data: Json;\n from: string;\n method: string;\n origin?: string;\n};\n\nexport type InitCoverageCheckResponse = {\n coverageId: string;\n};\n\nexport type GetCoverageResultRequest = {\n coverageId: string;\n};\n\nexport type GetCoverageResultResponse = {\n message?: string;\n reasonCode?: string;\n status: CoverageStatus;\n metrics: {\n latency?: number;\n };\n};\n\nexport class ShieldRemoteBackend implements ShieldBackend {\n readonly #getAccessToken: () => Promise<string>;\n\n readonly #baseUrl: string;\n\n readonly #fetch: typeof globalThis.fetch;\n\n readonly #pollingPolicy: PollingWithCockatielPolicy;\n\n readonly #captureException?: (error: Error) => void;\n\n constructor({\n getAccessToken,\n getCoverageResultTimeout = 5000, // milliseconds\n getCoverageResultPollInterval = 1000, // milliseconds\n baseUrl,\n fetch: fetchFn,\n captureException: captureExceptionFn,\n }: {\n getAccessToken: () => Promise<string>;\n getCoverageResultTimeout?: number;\n getCoverageResultPollInterval?: number;\n baseUrl: string;\n fetch: typeof globalThis.fetch;\n captureException?: (error: Error) => void;\n }) {\n this.#getAccessToken = getAccessToken;\n this.#baseUrl = baseUrl;\n this.#fetch = fetchFn;\n\n const { backoff, maxRetries } = computePollingIntervalAndRetryCount(\n getCoverageResultTimeout,\n getCoverageResultPollInterval,\n );\n\n this.#pollingPolicy = new PollingWithCockatielPolicy({\n backoff,\n maxRetries,\n });\n\n this.#captureException = (error: Error): void => {\n try {\n captureExceptionFn?.(error);\n } catch {\n // ignore error thrown when calling captureException\n }\n };\n }\n\n async checkCoverage(req: CheckCoverageRequest): Promise<CoverageResult> {\n let { coverageId } = req;\n if (!coverageId) {\n const reqBody = makeInitCoverageCheckBody(req.txMeta);\n ({ coverageId } = await this.#initCoverageCheck(\n 'v1/transaction/coverage/init',\n reqBody,\n ));\n }\n\n const txCoverageResultUrl = `${this.#baseUrl}/v1/transaction/coverage/result`;\n const coverageResult = await this.#getCoverageResult(\n req.txMeta.id,\n coverageId,\n txCoverageResultUrl,\n );\n return {\n coverageId,\n message: coverageResult.message,\n reasonCode: coverageResult.reasonCode,\n status: coverageResult.status,\n metrics: coverageResult.metrics,\n };\n }\n\n async checkSignatureCoverage(\n req: CheckSignatureCoverageRequest,\n ): Promise<CoverageResult> {\n let { coverageId } = req;\n if (!coverageId) {\n const reqBody = makeInitSignatureCoverageCheckBody(req.signatureRequest);\n ({ coverageId } = await this.#initCoverageCheck(\n 'v1/signature/coverage/init',\n reqBody,\n ));\n }\n\n const signatureCoverageResultUrl = `${this.#baseUrl}/v1/signature/coverage/result`;\n const coverageResult = await this.#getCoverageResult(\n req.signatureRequest.id,\n coverageId,\n signatureCoverageResultUrl,\n );\n return {\n coverageId,\n message: coverageResult.message,\n reasonCode: coverageResult.reasonCode,\n status: coverageResult.status,\n metrics: coverageResult.metrics,\n };\n }\n\n async logSignature(req: LogSignatureRequest): Promise<void> {\n try {\n const initBody = makeInitSignatureCoverageCheckBody(req.signatureRequest);\n const body = {\n signature: req.signature,\n status: req.status,\n ...initBody,\n };\n\n // cancel the pending get coverage result request\n this.#pollingPolicy.abortPendingRequest(req.signatureRequest.id);\n\n const res = await this.#fetch(\n `${this.#baseUrl}/v1/signature/coverage/log`,\n {\n method: 'POST',\n headers: await this.#createHeaders(),\n body: JSON.stringify(body),\n },\n );\n if (res.status !== 200) {\n throw new Error(`Failed to log signature: ${res.status}`);\n }\n } catch (error) {\n const sentryError = createSentryError(\n 'Failed to log signature',\n error as Error,\n );\n this.#captureException?.(sentryError);\n\n // rethrow the original error\n throw error;\n }\n }\n\n async logTransaction(req: LogTransactionRequest): Promise<void> {\n try {\n const initBody = makeInitCoverageCheckBody(req.txMeta);\n\n const body = {\n transactionHash: req.transactionHash,\n rawTransactionHex: req.rawTransactionHex,\n status: req.status,\n ...initBody,\n };\n\n // cancel the pending get coverage result request\n this.#pollingPolicy.abortPendingRequest(req.txMeta.id);\n\n const res = await this.#fetch(\n `${this.#baseUrl}/v1/transaction/coverage/log`,\n {\n method: 'POST',\n headers: await this.#createHeaders(),\n body: JSON.stringify(body),\n },\n );\n if (res.status !== 200) {\n throw new Error(`Failed to log transaction: ${res.status}`);\n }\n } catch (error) {\n const sentryError = createSentryError(\n 'Failed to log transaction',\n error as Error,\n );\n this.#captureException?.(sentryError);\n\n // rethrow the original error\n throw error;\n }\n }\n\n async #initCoverageCheck(\n path: string,\n reqBody: unknown,\n ): Promise<InitCoverageCheckResponse> {\n try {\n const res = await this.#fetch(`${this.#baseUrl}/${path}`, {\n method: 'POST',\n headers: await this.#createHeaders(),\n body: JSON.stringify(reqBody),\n });\n if (res.status !== 200) {\n throw new Error(`Failed to init coverage check: ${res.status}`);\n }\n return (await res.json()) as InitCoverageCheckResponse;\n } catch (error) {\n const sentryError = createSentryError(\n 'Failed to init coverage check',\n error as Error,\n );\n this.#captureException?.(sentryError);\n\n // rethrow the original error\n throw error;\n }\n }\n\n async #getCoverageResult(\n requestId: string,\n coverageId: string,\n coverageResultUrl: string,\n ): Promise<GetCoverageResultResponse> {\n const reqBody: GetCoverageResultRequest = {\n coverageId,\n };\n\n const headers = await this.#createHeaders();\n\n // Start measuring total end-to-end latency including retries and delays\n const startTime = Date.now();\n\n const getCoverageResultFn = async (\n signal: AbortSignal,\n ): Promise<Omit<GetCoverageResultResponse, 'metrics'>> => {\n const res = await this.#fetch(coverageResultUrl, {\n method: 'POST',\n headers,\n body: JSON.stringify(reqBody),\n signal,\n });\n\n if (res.status === 200) {\n // Return the result without latency here - we'll add total latency after polling completes\n return (await res.json()) as Omit<GetCoverageResultResponse, 'metrics'>;\n }\n\n // parse the error message from the response body\n let errorMessage = 'Timeout waiting for coverage result';\n try {\n const errorJson = await res.json();\n errorMessage = `Failed to get coverage result: ${errorJson.message ?? errorJson.status}`;\n } catch {\n errorMessage = `Failed to get coverage result: ${res.status}`;\n }\n throw new HttpError(res.status, errorMessage);\n };\n\n const result = await this.#pollingPolicy.start(\n requestId,\n getCoverageResultFn,\n );\n\n // Calculate total end-to-end latency including all retries and delays\n const now = Date.now();\n const totalLatency = now - startTime;\n\n return {\n ...result,\n metrics: { latency: totalLatency },\n } as GetCoverageResultResponse;\n }\n\n async #createHeaders(): Promise<Record<string, string>> {\n const accessToken = await this.#getAccessToken();\n return {\n 'Content-Type': 'application/json',\n Authorization: `Bearer ${accessToken}`,\n };\n }\n}\n\n/**\n * Make the body for the init coverage check request.\n *\n * @param txMeta - The transaction metadata.\n * @returns The body for the init coverage check request.\n */\nexport function makeInitCoverageCheckBody(\n txMeta: TransactionMeta,\n): InitCoverageCheckRequest {\n return {\n txParams: [\n {\n authorizationList: txMeta.txParams.authorizationList,\n from: txMeta.txParams.from,\n to: txMeta.txParams.to,\n value: txMeta.txParams.value,\n data: txMeta.txParams.data,\n nonce: txMeta.txParams.nonce,\n },\n ],\n chainId: txMeta.chainId,\n origin: txMeta.origin,\n };\n}\n\n/**\n * Make the body for the init signature coverage check request.\n *\n * @param signatureRequest - The signature request.\n * @returns The body for the init signature coverage check request.\n */\nfunction makeInitSignatureCoverageCheckBody(\n signatureRequest: SignatureRequest,\n): InitSignatureCoverageCheckRequest {\n // TODO: confirm that do we still need to validate the signature data?\n // signature controller already validates the signature data before adding it to the state.\n // @link https://github.com/MetaMask/core/blob/main/packages/signature-controller/src/SignatureController.ts#L408\n const method = parseSignatureRequestMethod(signatureRequest);\n\n return {\n chainId: signatureRequest.chainId,\n data: signatureRequest.messageParams.data,\n from: signatureRequest.messageParams.from,\n method,\n origin: signatureRequest.messageParams.origin,\n };\n}\n\n/**\n * Parse the JSON-RPC method from the signature request.\n *\n * @param signatureRequest - The signature request.\n * @returns The JSON-RPC method.\n */\nexport function parseSignatureRequestMethod(\n signatureRequest: SignatureRequest,\n): string {\n if (signatureRequest.type === SignatureRequestType.TypedSign) {\n switch (signatureRequest.version) {\n case SignTypedDataVersion.V3:\n return EthMethod.SignTypedDataV3;\n case SignTypedDataVersion.V4:\n return EthMethod.SignTypedDataV4;\n case SignTypedDataVersion.V1:\n default:\n return SignatureRequestType.TypedSign;\n }\n }\n\n return signatureRequest.type;\n}\n\n/**\n * Compute the polling interval and retry count for the Cockatiel policy based on the timeout and poll interval given.\n *\n * @param timeout - The timeout in milliseconds.\n * @param pollInterval - The poll interval in milliseconds.\n * @returns The polling interval and retry count.\n */\nfunction computePollingIntervalAndRetryCount(\n timeout: number,\n pollInterval: number,\n): { backoff: ConstantBackoff; maxRetries: number } {\n const backoff = new ConstantBackoff(pollInterval);\n const computedMaxRetries = Math.floor(timeout / pollInterval) + 1;\n\n const maxRetries =\n isNaN(computedMaxRetries) || !isFinite(computedMaxRetries)\n ? DEFAULT_MAX_RETRIES\n : computedMaxRetries;\n\n return {\n backoff,\n maxRetries,\n };\n}\n\n/**\n * Create an error instance with a readable message, a cause and a context for Sentry.\n *\n * @param errorMessage - The error message.\n * @param cause - The cause of the error.\n * @returns A Sentry error.\n */\nfunction createSentryError(errorMessage: string, cause: Error): Error {\n const error = new Error(errorMessage) as Error & {\n cause: Error;\n };\n error.cause = cause;\n return error;\n}\n"]}
@@ -42,12 +42,13 @@ export declare class ShieldRemoteBackend implements ShieldBackend {
42
42
  #private;
43
43
  constructor({ getAccessToken, getCoverageResultTimeout, // milliseconds
44
44
  getCoverageResultPollInterval, // milliseconds
45
- baseUrl, fetch: fetchFn, }: {
45
+ baseUrl, fetch: fetchFn, captureException: captureExceptionFn, }: {
46
46
  getAccessToken: () => Promise<string>;
47
47
  getCoverageResultTimeout?: number;
48
48
  getCoverageResultPollInterval?: number;
49
49
  baseUrl: string;
50
50
  fetch: typeof globalThis.fetch;
51
+ captureException?: (error: Error) => void;
51
52
  });
52
53
  checkCoverage(req: CheckCoverageRequest): Promise<CoverageResult>;
53
54
  checkSignatureCoverage(req: CheckSignatureCoverageRequest): Promise<CoverageResult>;
@@ -1 +1 @@
1
- {"version":3,"file":"backend.d.cts","sourceRoot":"","sources":["../src/backend.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,gBAAgB,EAAE,uCAAuC;AACvE,OAAO,KAAK,EAAE,eAAe,EAAE,yCAAyC;AACxE,OAAO,KAAK,EAAE,iBAAiB,EAAE,yCAAyC;AAC1E,OAAO,KAAK,EAAE,IAAI,EAAE,wBAAwB;AAI5C,OAAO,KAAK,EACV,oBAAoB,EACpB,6BAA6B,EAC7B,cAAc,EACd,cAAc,EACd,mBAAmB,EACnB,qBAAqB,EACrB,aAAa,EACd,oBAAgB;AAEjB,MAAM,MAAM,wBAAwB,GAAG;IACrC,QAAQ,EAAE;QACR;YACE,iBAAiB,CAAC,EAAE,iBAAiB,CAAC;YACtC,IAAI,EAAE,MAAM,CAAC;YACb,EAAE,CAAC,EAAE,MAAM,CAAC;YACZ,KAAK,CAAC,EAAE,MAAM,CAAC;YACf,IAAI,CAAC,EAAE,MAAM,CAAC;YACd,KAAK,CAAC,EAAE,MAAM,CAAC;SAChB;KACF,CAAC;IACF,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB,CAAC;AAEF,MAAM,MAAM,iCAAiC,GAAG;IAC9C,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,IAAI,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB,CAAC;AAEF,MAAM,MAAM,yBAAyB,GAAG;IACtC,UAAU,EAAE,MAAM,CAAC;CACpB,CAAC;AAEF,MAAM,MAAM,wBAAwB,GAAG;IACrC,UAAU,EAAE,MAAM,CAAC;CACpB,CAAC;AAEF,MAAM,MAAM,yBAAyB,GAAG;IACtC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,cAAc,CAAC;IACvB,OAAO,EAAE;QACP,OAAO,CAAC,EAAE,MAAM,CAAC;KAClB,CAAC;CACH,CAAC;AAEF,qBAAa,mBAAoB,YAAW,aAAa;;gBAS3C,EACV,cAAc,EACd,wBAA+B,EAAE,eAAe;IAChD,6BAAoC,EAAE,eAAe;IACrD,OAAO,EACP,KAAK,EAAE,OAAO,GACf,EAAE;QACD,cAAc,EAAE,MAAM,OAAO,CAAC,MAAM,CAAC,CAAC;QACtC,wBAAwB,CAAC,EAAE,MAAM,CAAC;QAClC,6BAA6B,CAAC,EAAE,MAAM,CAAC;QACvC,OAAO,EAAE,MAAM,CAAC;QAChB,KAAK,EAAE,OAAO,UAAU,CAAC,KAAK,CAAC;KAChC;IAgBK,aAAa,CAAC,GAAG,EAAE,oBAAoB,GAAG,OAAO,CAAC,cAAc,CAAC;IAyBjE,sBAAsB,CAC1B,GAAG,EAAE,6BAA6B,GACjC,OAAO,CAAC,cAAc,CAAC;IAyBpB,YAAY,CAAC,GAAG,EAAE,mBAAmB,GAAG,OAAO,CAAC,IAAI,CAAC;IAwBrD,cAAc,CAAC,GAAG,EAAE,qBAAqB,GAAG,OAAO,CAAC,IAAI,CAAC;CAqGhE;AAED;;;;;GAKG;AACH,wBAAgB,yBAAyB,CACvC,MAAM,EAAE,eAAe,GACtB,wBAAwB,CAe1B;AAyBD;;;;;GAKG;AACH,wBAAgB,2BAA2B,CACzC,gBAAgB,EAAE,gBAAgB,GACjC,MAAM,CAcR"}
1
+ {"version":3,"file":"backend.d.cts","sourceRoot":"","sources":["../src/backend.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,gBAAgB,EAAE,uCAAuC;AACvE,OAAO,KAAK,EAAE,eAAe,EAAE,yCAAyC;AACxE,OAAO,KAAK,EAAE,iBAAiB,EAAE,yCAAyC;AAC1E,OAAO,KAAK,EAAE,IAAI,EAAE,wBAAwB;AAI5C,OAAO,KAAK,EACV,oBAAoB,EACpB,6BAA6B,EAC7B,cAAc,EACd,cAAc,EACd,mBAAmB,EACnB,qBAAqB,EACrB,aAAa,EACd,oBAAgB;AAEjB,MAAM,MAAM,wBAAwB,GAAG;IACrC,QAAQ,EAAE;QACR;YACE,iBAAiB,CAAC,EAAE,iBAAiB,CAAC;YACtC,IAAI,EAAE,MAAM,CAAC;YACb,EAAE,CAAC,EAAE,MAAM,CAAC;YACZ,KAAK,CAAC,EAAE,MAAM,CAAC;YACf,IAAI,CAAC,EAAE,MAAM,CAAC;YACd,KAAK,CAAC,EAAE,MAAM,CAAC;SAChB;KACF,CAAC;IACF,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB,CAAC;AAEF,MAAM,MAAM,iCAAiC,GAAG;IAC9C,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,IAAI,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB,CAAC;AAEF,MAAM,MAAM,yBAAyB,GAAG;IACtC,UAAU,EAAE,MAAM,CAAC;CACpB,CAAC;AAEF,MAAM,MAAM,wBAAwB,GAAG;IACrC,UAAU,EAAE,MAAM,CAAC;CACpB,CAAC;AAEF,MAAM,MAAM,yBAAyB,GAAG;IACtC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,cAAc,CAAC;IACvB,OAAO,EAAE;QACP,OAAO,CAAC,EAAE,MAAM,CAAC;KAClB,CAAC;CACH,CAAC;AAEF,qBAAa,mBAAoB,YAAW,aAAa;;gBAW3C,EACV,cAAc,EACd,wBAA+B,EAAE,eAAe;IAChD,6BAAoC,EAAE,eAAe;IACrD,OAAO,EACP,KAAK,EAAE,OAAO,EACd,gBAAgB,EAAE,kBAAkB,GACrC,EAAE;QACD,cAAc,EAAE,MAAM,OAAO,CAAC,MAAM,CAAC,CAAC;QACtC,wBAAwB,CAAC,EAAE,MAAM,CAAC;QAClC,6BAA6B,CAAC,EAAE,MAAM,CAAC;QACvC,OAAO,EAAE,MAAM,CAAC;QAChB,KAAK,EAAE,OAAO,UAAU,CAAC,KAAK,CAAC;QAC/B,gBAAgB,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;KAC3C;IAwBK,aAAa,CAAC,GAAG,EAAE,oBAAoB,GAAG,OAAO,CAAC,cAAc,CAAC;IAyBjE,sBAAsB,CAC1B,GAAG,EAAE,6BAA6B,GACjC,OAAO,CAAC,cAAc,CAAC;IAyBpB,YAAY,CAAC,GAAG,EAAE,mBAAmB,GAAG,OAAO,CAAC,IAAI,CAAC;IAmCrD,cAAc,CAAC,GAAG,EAAE,qBAAqB,GAAG,OAAO,CAAC,IAAI,CAAC;CA6HhE;AAED;;;;;GAKG;AACH,wBAAgB,yBAAyB,CACvC,MAAM,EAAE,eAAe,GACtB,wBAAwB,CAe1B;AAyBD;;;;;GAKG;AACH,wBAAgB,2BAA2B,CACzC,gBAAgB,EAAE,gBAAgB,GACjC,MAAM,CAcR"}
@@ -42,12 +42,13 @@ export declare class ShieldRemoteBackend implements ShieldBackend {
42
42
  #private;
43
43
  constructor({ getAccessToken, getCoverageResultTimeout, // milliseconds
44
44
  getCoverageResultPollInterval, // milliseconds
45
- baseUrl, fetch: fetchFn, }: {
45
+ baseUrl, fetch: fetchFn, captureException: captureExceptionFn, }: {
46
46
  getAccessToken: () => Promise<string>;
47
47
  getCoverageResultTimeout?: number;
48
48
  getCoverageResultPollInterval?: number;
49
49
  baseUrl: string;
50
50
  fetch: typeof globalThis.fetch;
51
+ captureException?: (error: Error) => void;
51
52
  });
52
53
  checkCoverage(req: CheckCoverageRequest): Promise<CoverageResult>;
53
54
  checkSignatureCoverage(req: CheckSignatureCoverageRequest): Promise<CoverageResult>;
@@ -1 +1 @@
1
- {"version":3,"file":"backend.d.mts","sourceRoot":"","sources":["../src/backend.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,gBAAgB,EAAE,uCAAuC;AACvE,OAAO,KAAK,EAAE,eAAe,EAAE,yCAAyC;AACxE,OAAO,KAAK,EAAE,iBAAiB,EAAE,yCAAyC;AAC1E,OAAO,KAAK,EAAE,IAAI,EAAE,wBAAwB;AAI5C,OAAO,KAAK,EACV,oBAAoB,EACpB,6BAA6B,EAC7B,cAAc,EACd,cAAc,EACd,mBAAmB,EACnB,qBAAqB,EACrB,aAAa,EACd,oBAAgB;AAEjB,MAAM,MAAM,wBAAwB,GAAG;IACrC,QAAQ,EAAE;QACR;YACE,iBAAiB,CAAC,EAAE,iBAAiB,CAAC;YACtC,IAAI,EAAE,MAAM,CAAC;YACb,EAAE,CAAC,EAAE,MAAM,CAAC;YACZ,KAAK,CAAC,EAAE,MAAM,CAAC;YACf,IAAI,CAAC,EAAE,MAAM,CAAC;YACd,KAAK,CAAC,EAAE,MAAM,CAAC;SAChB;KACF,CAAC;IACF,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB,CAAC;AAEF,MAAM,MAAM,iCAAiC,GAAG;IAC9C,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,IAAI,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB,CAAC;AAEF,MAAM,MAAM,yBAAyB,GAAG;IACtC,UAAU,EAAE,MAAM,CAAC;CACpB,CAAC;AAEF,MAAM,MAAM,wBAAwB,GAAG;IACrC,UAAU,EAAE,MAAM,CAAC;CACpB,CAAC;AAEF,MAAM,MAAM,yBAAyB,GAAG;IACtC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,cAAc,CAAC;IACvB,OAAO,EAAE;QACP,OAAO,CAAC,EAAE,MAAM,CAAC;KAClB,CAAC;CACH,CAAC;AAEF,qBAAa,mBAAoB,YAAW,aAAa;;gBAS3C,EACV,cAAc,EACd,wBAA+B,EAAE,eAAe;IAChD,6BAAoC,EAAE,eAAe;IACrD,OAAO,EACP,KAAK,EAAE,OAAO,GACf,EAAE;QACD,cAAc,EAAE,MAAM,OAAO,CAAC,MAAM,CAAC,CAAC;QACtC,wBAAwB,CAAC,EAAE,MAAM,CAAC;QAClC,6BAA6B,CAAC,EAAE,MAAM,CAAC;QACvC,OAAO,EAAE,MAAM,CAAC;QAChB,KAAK,EAAE,OAAO,UAAU,CAAC,KAAK,CAAC;KAChC;IAgBK,aAAa,CAAC,GAAG,EAAE,oBAAoB,GAAG,OAAO,CAAC,cAAc,CAAC;IAyBjE,sBAAsB,CAC1B,GAAG,EAAE,6BAA6B,GACjC,OAAO,CAAC,cAAc,CAAC;IAyBpB,YAAY,CAAC,GAAG,EAAE,mBAAmB,GAAG,OAAO,CAAC,IAAI,CAAC;IAwBrD,cAAc,CAAC,GAAG,EAAE,qBAAqB,GAAG,OAAO,CAAC,IAAI,CAAC;CAqGhE;AAED;;;;;GAKG;AACH,wBAAgB,yBAAyB,CACvC,MAAM,EAAE,eAAe,GACtB,wBAAwB,CAe1B;AAyBD;;;;;GAKG;AACH,wBAAgB,2BAA2B,CACzC,gBAAgB,EAAE,gBAAgB,GACjC,MAAM,CAcR"}
1
+ {"version":3,"file":"backend.d.mts","sourceRoot":"","sources":["../src/backend.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,gBAAgB,EAAE,uCAAuC;AACvE,OAAO,KAAK,EAAE,eAAe,EAAE,yCAAyC;AACxE,OAAO,KAAK,EAAE,iBAAiB,EAAE,yCAAyC;AAC1E,OAAO,KAAK,EAAE,IAAI,EAAE,wBAAwB;AAI5C,OAAO,KAAK,EACV,oBAAoB,EACpB,6BAA6B,EAC7B,cAAc,EACd,cAAc,EACd,mBAAmB,EACnB,qBAAqB,EACrB,aAAa,EACd,oBAAgB;AAEjB,MAAM,MAAM,wBAAwB,GAAG;IACrC,QAAQ,EAAE;QACR;YACE,iBAAiB,CAAC,EAAE,iBAAiB,CAAC;YACtC,IAAI,EAAE,MAAM,CAAC;YACb,EAAE,CAAC,EAAE,MAAM,CAAC;YACZ,KAAK,CAAC,EAAE,MAAM,CAAC;YACf,IAAI,CAAC,EAAE,MAAM,CAAC;YACd,KAAK,CAAC,EAAE,MAAM,CAAC;SAChB;KACF,CAAC;IACF,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB,CAAC;AAEF,MAAM,MAAM,iCAAiC,GAAG;IAC9C,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,IAAI,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB,CAAC;AAEF,MAAM,MAAM,yBAAyB,GAAG;IACtC,UAAU,EAAE,MAAM,CAAC;CACpB,CAAC;AAEF,MAAM,MAAM,wBAAwB,GAAG;IACrC,UAAU,EAAE,MAAM,CAAC;CACpB,CAAC;AAEF,MAAM,MAAM,yBAAyB,GAAG;IACtC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,cAAc,CAAC;IACvB,OAAO,EAAE;QACP,OAAO,CAAC,EAAE,MAAM,CAAC;KAClB,CAAC;CACH,CAAC;AAEF,qBAAa,mBAAoB,YAAW,aAAa;;gBAW3C,EACV,cAAc,EACd,wBAA+B,EAAE,eAAe;IAChD,6BAAoC,EAAE,eAAe;IACrD,OAAO,EACP,KAAK,EAAE,OAAO,EACd,gBAAgB,EAAE,kBAAkB,GACrC,EAAE;QACD,cAAc,EAAE,MAAM,OAAO,CAAC,MAAM,CAAC,CAAC;QACtC,wBAAwB,CAAC,EAAE,MAAM,CAAC;QAClC,6BAA6B,CAAC,EAAE,MAAM,CAAC;QACvC,OAAO,EAAE,MAAM,CAAC;QAChB,KAAK,EAAE,OAAO,UAAU,CAAC,KAAK,CAAC;QAC/B,gBAAgB,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;KAC3C;IAwBK,aAAa,CAAC,GAAG,EAAE,oBAAoB,GAAG,OAAO,CAAC,cAAc,CAAC;IAyBjE,sBAAsB,CAC1B,GAAG,EAAE,6BAA6B,GACjC,OAAO,CAAC,cAAc,CAAC;IAyBpB,YAAY,CAAC,GAAG,EAAE,mBAAmB,GAAG,OAAO,CAAC,IAAI,CAAC;IAmCrD,cAAc,CAAC,GAAG,EAAE,qBAAqB,GAAG,OAAO,CAAC,IAAI,CAAC;CA6HhE;AAED;;;;;GAKG;AACH,wBAAgB,yBAAyB,CACvC,MAAM,EAAE,eAAe,GACtB,wBAAwB,CAe1B;AAyBD;;;;;GAKG;AACH,wBAAgB,2BAA2B,CACzC,gBAAgB,EAAE,gBAAgB,GACjC,MAAM,CAcR"}
package/dist/backend.mjs CHANGED
@@ -9,7 +9,7 @@ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (
9
9
  if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
10
10
  return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
11
11
  };
12
- var _ShieldRemoteBackend_instances, _ShieldRemoteBackend_getAccessToken, _ShieldRemoteBackend_baseUrl, _ShieldRemoteBackend_fetch, _ShieldRemoteBackend_pollingPolicy, _ShieldRemoteBackend_initCoverageCheck, _ShieldRemoteBackend_getCoverageResult, _ShieldRemoteBackend_createHeaders;
12
+ var _ShieldRemoteBackend_instances, _ShieldRemoteBackend_getAccessToken, _ShieldRemoteBackend_baseUrl, _ShieldRemoteBackend_fetch, _ShieldRemoteBackend_pollingPolicy, _ShieldRemoteBackend_captureException, _ShieldRemoteBackend_initCoverageCheck, _ShieldRemoteBackend_getCoverageResult, _ShieldRemoteBackend_createHeaders;
13
13
  import { ConstantBackoff, DEFAULT_MAX_RETRIES, HttpError } from "@metamask/controller-utils";
14
14
  import { EthMethod, SignatureRequestType } from "@metamask/signature-controller";
15
15
  import { SignTypedDataVersion } from "./constants.mjs";
@@ -17,12 +17,13 @@ import { PollingWithCockatielPolicy } from "./polling-with-policy.mjs";
17
17
  export class ShieldRemoteBackend {
18
18
  constructor({ getAccessToken, getCoverageResultTimeout = 5000, // milliseconds
19
19
  getCoverageResultPollInterval = 1000, // milliseconds
20
- baseUrl, fetch: fetchFn, }) {
20
+ baseUrl, fetch: fetchFn, captureException: captureExceptionFn, }) {
21
21
  _ShieldRemoteBackend_instances.add(this);
22
22
  _ShieldRemoteBackend_getAccessToken.set(this, void 0);
23
23
  _ShieldRemoteBackend_baseUrl.set(this, void 0);
24
24
  _ShieldRemoteBackend_fetch.set(this, void 0);
25
25
  _ShieldRemoteBackend_pollingPolicy.set(this, void 0);
26
+ _ShieldRemoteBackend_captureException.set(this, void 0);
26
27
  __classPrivateFieldSet(this, _ShieldRemoteBackend_getAccessToken, getAccessToken, "f");
27
28
  __classPrivateFieldSet(this, _ShieldRemoteBackend_baseUrl, baseUrl, "f");
28
29
  __classPrivateFieldSet(this, _ShieldRemoteBackend_fetch, fetchFn, "f");
@@ -31,6 +32,14 @@ export class ShieldRemoteBackend {
31
32
  backoff,
32
33
  maxRetries,
33
34
  }), "f");
35
+ __classPrivateFieldSet(this, _ShieldRemoteBackend_captureException, (error) => {
36
+ try {
37
+ captureExceptionFn?.(error);
38
+ }
39
+ catch {
40
+ // ignore error thrown when calling captureException
41
+ }
42
+ }, "f");
34
43
  }
35
44
  async checkCoverage(req) {
36
45
  let { coverageId } = req;
@@ -65,53 +74,77 @@ export class ShieldRemoteBackend {
65
74
  };
66
75
  }
67
76
  async logSignature(req) {
68
- const initBody = makeInitSignatureCoverageCheckBody(req.signatureRequest);
69
- const body = {
70
- signature: req.signature,
71
- status: req.status,
72
- ...initBody,
73
- };
74
- // cancel the pending get coverage result request
75
- __classPrivateFieldGet(this, _ShieldRemoteBackend_pollingPolicy, "f").abortPendingRequest(req.signatureRequest.id);
76
- const res = await __classPrivateFieldGet(this, _ShieldRemoteBackend_fetch, "f").call(this, `${__classPrivateFieldGet(this, _ShieldRemoteBackend_baseUrl, "f")}/v1/signature/coverage/log`, {
77
- method: 'POST',
78
- headers: await __classPrivateFieldGet(this, _ShieldRemoteBackend_instances, "m", _ShieldRemoteBackend_createHeaders).call(this),
79
- body: JSON.stringify(body),
80
- });
81
- if (res.status !== 200) {
82
- throw new Error(`Failed to log signature: ${res.status}`);
77
+ try {
78
+ const initBody = makeInitSignatureCoverageCheckBody(req.signatureRequest);
79
+ const body = {
80
+ signature: req.signature,
81
+ status: req.status,
82
+ ...initBody,
83
+ };
84
+ // cancel the pending get coverage result request
85
+ __classPrivateFieldGet(this, _ShieldRemoteBackend_pollingPolicy, "f").abortPendingRequest(req.signatureRequest.id);
86
+ const res = await __classPrivateFieldGet(this, _ShieldRemoteBackend_fetch, "f").call(this, `${__classPrivateFieldGet(this, _ShieldRemoteBackend_baseUrl, "f")}/v1/signature/coverage/log`, {
87
+ method: 'POST',
88
+ headers: await __classPrivateFieldGet(this, _ShieldRemoteBackend_instances, "m", _ShieldRemoteBackend_createHeaders).call(this),
89
+ body: JSON.stringify(body),
90
+ });
91
+ if (res.status !== 200) {
92
+ throw new Error(`Failed to log signature: ${res.status}`);
93
+ }
94
+ }
95
+ catch (error) {
96
+ const sentryError = createSentryError('Failed to log signature', error);
97
+ __classPrivateFieldGet(this, _ShieldRemoteBackend_captureException, "f")?.call(this, sentryError);
98
+ // rethrow the original error
99
+ throw error;
83
100
  }
84
101
  }
85
102
  async logTransaction(req) {
86
- const initBody = makeInitCoverageCheckBody(req.txMeta);
87
- const body = {
88
- transactionHash: req.transactionHash,
89
- rawTransactionHex: req.rawTransactionHex,
90
- status: req.status,
91
- ...initBody,
92
- };
93
- // cancel the pending get coverage result request
94
- __classPrivateFieldGet(this, _ShieldRemoteBackend_pollingPolicy, "f").abortPendingRequest(req.txMeta.id);
95
- const res = await __classPrivateFieldGet(this, _ShieldRemoteBackend_fetch, "f").call(this, `${__classPrivateFieldGet(this, _ShieldRemoteBackend_baseUrl, "f")}/v1/transaction/coverage/log`, {
103
+ try {
104
+ const initBody = makeInitCoverageCheckBody(req.txMeta);
105
+ const body = {
106
+ transactionHash: req.transactionHash,
107
+ rawTransactionHex: req.rawTransactionHex,
108
+ status: req.status,
109
+ ...initBody,
110
+ };
111
+ // cancel the pending get coverage result request
112
+ __classPrivateFieldGet(this, _ShieldRemoteBackend_pollingPolicy, "f").abortPendingRequest(req.txMeta.id);
113
+ const res = await __classPrivateFieldGet(this, _ShieldRemoteBackend_fetch, "f").call(this, `${__classPrivateFieldGet(this, _ShieldRemoteBackend_baseUrl, "f")}/v1/transaction/coverage/log`, {
114
+ method: 'POST',
115
+ headers: await __classPrivateFieldGet(this, _ShieldRemoteBackend_instances, "m", _ShieldRemoteBackend_createHeaders).call(this),
116
+ body: JSON.stringify(body),
117
+ });
118
+ if (res.status !== 200) {
119
+ throw new Error(`Failed to log transaction: ${res.status}`);
120
+ }
121
+ }
122
+ catch (error) {
123
+ const sentryError = createSentryError('Failed to log transaction', error);
124
+ __classPrivateFieldGet(this, _ShieldRemoteBackend_captureException, "f")?.call(this, sentryError);
125
+ // rethrow the original error
126
+ throw error;
127
+ }
128
+ }
129
+ }
130
+ _ShieldRemoteBackend_getAccessToken = new WeakMap(), _ShieldRemoteBackend_baseUrl = new WeakMap(), _ShieldRemoteBackend_fetch = new WeakMap(), _ShieldRemoteBackend_pollingPolicy = new WeakMap(), _ShieldRemoteBackend_captureException = new WeakMap(), _ShieldRemoteBackend_instances = new WeakSet(), _ShieldRemoteBackend_initCoverageCheck = async function _ShieldRemoteBackend_initCoverageCheck(path, reqBody) {
131
+ try {
132
+ const res = await __classPrivateFieldGet(this, _ShieldRemoteBackend_fetch, "f").call(this, `${__classPrivateFieldGet(this, _ShieldRemoteBackend_baseUrl, "f")}/${path}`, {
96
133
  method: 'POST',
97
134
  headers: await __classPrivateFieldGet(this, _ShieldRemoteBackend_instances, "m", _ShieldRemoteBackend_createHeaders).call(this),
98
- body: JSON.stringify(body),
135
+ body: JSON.stringify(reqBody),
99
136
  });
100
137
  if (res.status !== 200) {
101
- throw new Error(`Failed to log transaction: ${res.status}`);
138
+ throw new Error(`Failed to init coverage check: ${res.status}`);
102
139
  }
140
+ return (await res.json());
103
141
  }
104
- }
105
- _ShieldRemoteBackend_getAccessToken = new WeakMap(), _ShieldRemoteBackend_baseUrl = new WeakMap(), _ShieldRemoteBackend_fetch = new WeakMap(), _ShieldRemoteBackend_pollingPolicy = new WeakMap(), _ShieldRemoteBackend_instances = new WeakSet(), _ShieldRemoteBackend_initCoverageCheck = async function _ShieldRemoteBackend_initCoverageCheck(path, reqBody) {
106
- const res = await __classPrivateFieldGet(this, _ShieldRemoteBackend_fetch, "f").call(this, `${__classPrivateFieldGet(this, _ShieldRemoteBackend_baseUrl, "f")}/${path}`, {
107
- method: 'POST',
108
- headers: await __classPrivateFieldGet(this, _ShieldRemoteBackend_instances, "m", _ShieldRemoteBackend_createHeaders).call(this),
109
- body: JSON.stringify(reqBody),
110
- });
111
- if (res.status !== 200) {
112
- throw new Error(`Failed to init coverage check: ${res.status}`);
142
+ catch (error) {
143
+ const sentryError = createSentryError('Failed to init coverage check', error);
144
+ __classPrivateFieldGet(this, _ShieldRemoteBackend_captureException, "f")?.call(this, sentryError);
145
+ // rethrow the original error
146
+ throw error;
113
147
  }
114
- return (await res.json());
115
148
  }, _ShieldRemoteBackend_getCoverageResult = async function _ShieldRemoteBackend_getCoverageResult(requestId, coverageId, coverageResultUrl) {
116
149
  const reqBody = {
117
150
  coverageId,
@@ -134,7 +167,7 @@ _ShieldRemoteBackend_getAccessToken = new WeakMap(), _ShieldRemoteBackend_baseUr
134
167
  let errorMessage = 'Timeout waiting for coverage result';
135
168
  try {
136
169
  const errorJson = await res.json();
137
- errorMessage = `Failed to get coverage result: ${errorJson.message || errorJson.status}`;
170
+ errorMessage = `Failed to get coverage result: ${errorJson.message ?? errorJson.status}`;
138
171
  }
139
172
  catch {
140
173
  errorMessage = `Failed to get coverage result: ${res.status}`;
@@ -235,4 +268,16 @@ function computePollingIntervalAndRetryCount(timeout, pollInterval) {
235
268
  maxRetries,
236
269
  };
237
270
  }
271
+ /**
272
+ * Create an error instance with a readable message, a cause and a context for Sentry.
273
+ *
274
+ * @param errorMessage - The error message.
275
+ * @param cause - The cause of the error.
276
+ * @returns A Sentry error.
277
+ */
278
+ function createSentryError(errorMessage, cause) {
279
+ const error = new Error(errorMessage);
280
+ error.cause = cause;
281
+ return error;
282
+ }
238
283
  //# sourceMappingURL=backend.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"backend.mjs","sourceRoot":"","sources":["../src/backend.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n ConstantBackoff,\n DEFAULT_MAX_RETRIES,\n HttpError,\n} from '@metamask/controller-utils';\nimport {\n EthMethod,\n SignatureRequestType,\n} from '@metamask/signature-controller';\nimport type { SignatureRequest } from '@metamask/signature-controller';\nimport type { TransactionMeta } from '@metamask/transaction-controller';\nimport type { AuthorizationList } from '@metamask/transaction-controller';\nimport type { Json } from '@metamask/utils';\n\nimport { SignTypedDataVersion } from './constants';\nimport { PollingWithCockatielPolicy } from './polling-with-policy';\nimport type {\n CheckCoverageRequest,\n CheckSignatureCoverageRequest,\n CoverageResult,\n CoverageStatus,\n LogSignatureRequest,\n LogTransactionRequest,\n ShieldBackend,\n} from './types';\n\nexport type InitCoverageCheckRequest = {\n txParams: [\n {\n authorizationList?: AuthorizationList;\n from: string;\n to?: string;\n value?: string;\n data?: string;\n nonce?: string;\n },\n ];\n chainId: string;\n origin?: string;\n};\n\nexport type InitSignatureCoverageCheckRequest = {\n chainId: string;\n data: Json;\n from: string;\n method: string;\n origin?: string;\n};\n\nexport type InitCoverageCheckResponse = {\n coverageId: string;\n};\n\nexport type GetCoverageResultRequest = {\n coverageId: string;\n};\n\nexport type GetCoverageResultResponse = {\n message?: string;\n reasonCode?: string;\n status: CoverageStatus;\n metrics: {\n latency?: number;\n };\n};\n\nexport class ShieldRemoteBackend implements ShieldBackend {\n readonly #getAccessToken: () => Promise<string>;\n\n readonly #baseUrl: string;\n\n readonly #fetch: typeof globalThis.fetch;\n\n readonly #pollingPolicy: PollingWithCockatielPolicy;\n\n constructor({\n getAccessToken,\n getCoverageResultTimeout = 5000, // milliseconds\n getCoverageResultPollInterval = 1000, // milliseconds\n baseUrl,\n fetch: fetchFn,\n }: {\n getAccessToken: () => Promise<string>;\n getCoverageResultTimeout?: number;\n getCoverageResultPollInterval?: number;\n baseUrl: string;\n fetch: typeof globalThis.fetch;\n }) {\n this.#getAccessToken = getAccessToken;\n this.#baseUrl = baseUrl;\n this.#fetch = fetchFn;\n\n const { backoff, maxRetries } = computePollingIntervalAndRetryCount(\n getCoverageResultTimeout,\n getCoverageResultPollInterval,\n );\n\n this.#pollingPolicy = new PollingWithCockatielPolicy({\n backoff,\n maxRetries,\n });\n }\n\n async checkCoverage(req: CheckCoverageRequest): Promise<CoverageResult> {\n let { coverageId } = req;\n if (!coverageId) {\n const reqBody = makeInitCoverageCheckBody(req.txMeta);\n ({ coverageId } = await this.#initCoverageCheck(\n 'v1/transaction/coverage/init',\n reqBody,\n ));\n }\n\n const txCoverageResultUrl = `${this.#baseUrl}/v1/transaction/coverage/result`;\n const coverageResult = await this.#getCoverageResult(\n req.txMeta.id,\n coverageId,\n txCoverageResultUrl,\n );\n return {\n coverageId,\n message: coverageResult.message,\n reasonCode: coverageResult.reasonCode,\n status: coverageResult.status,\n metrics: coverageResult.metrics,\n };\n }\n\n async checkSignatureCoverage(\n req: CheckSignatureCoverageRequest,\n ): Promise<CoverageResult> {\n let { coverageId } = req;\n if (!coverageId) {\n const reqBody = makeInitSignatureCoverageCheckBody(req.signatureRequest);\n ({ coverageId } = await this.#initCoverageCheck(\n 'v1/signature/coverage/init',\n reqBody,\n ));\n }\n\n const signatureCoverageResultUrl = `${this.#baseUrl}/v1/signature/coverage/result`;\n const coverageResult = await this.#getCoverageResult(\n req.signatureRequest.id,\n coverageId,\n signatureCoverageResultUrl,\n );\n return {\n coverageId,\n message: coverageResult.message,\n reasonCode: coverageResult.reasonCode,\n status: coverageResult.status,\n metrics: coverageResult.metrics,\n };\n }\n\n async logSignature(req: LogSignatureRequest): Promise<void> {\n const initBody = makeInitSignatureCoverageCheckBody(req.signatureRequest);\n const body = {\n signature: req.signature,\n status: req.status,\n ...initBody,\n };\n\n // cancel the pending get coverage result request\n this.#pollingPolicy.abortPendingRequest(req.signatureRequest.id);\n\n const res = await this.#fetch(\n `${this.#baseUrl}/v1/signature/coverage/log`,\n {\n method: 'POST',\n headers: await this.#createHeaders(),\n body: JSON.stringify(body),\n },\n );\n if (res.status !== 200) {\n throw new Error(`Failed to log signature: ${res.status}`);\n }\n }\n\n async logTransaction(req: LogTransactionRequest): Promise<void> {\n const initBody = makeInitCoverageCheckBody(req.txMeta);\n\n const body = {\n transactionHash: req.transactionHash,\n rawTransactionHex: req.rawTransactionHex,\n status: req.status,\n ...initBody,\n };\n\n // cancel the pending get coverage result request\n this.#pollingPolicy.abortPendingRequest(req.txMeta.id);\n\n const res = await this.#fetch(\n `${this.#baseUrl}/v1/transaction/coverage/log`,\n {\n method: 'POST',\n headers: await this.#createHeaders(),\n body: JSON.stringify(body),\n },\n );\n if (res.status !== 200) {\n throw new Error(`Failed to log transaction: ${res.status}`);\n }\n }\n\n async #initCoverageCheck(\n path: string,\n reqBody: unknown,\n ): Promise<InitCoverageCheckResponse> {\n const res = await this.#fetch(`${this.#baseUrl}/${path}`, {\n method: 'POST',\n headers: await this.#createHeaders(),\n body: JSON.stringify(reqBody),\n });\n if (res.status !== 200) {\n throw new Error(`Failed to init coverage check: ${res.status}`);\n }\n return (await res.json()) as InitCoverageCheckResponse;\n }\n\n async #getCoverageResult(\n requestId: string,\n coverageId: string,\n coverageResultUrl: string,\n ): Promise<GetCoverageResultResponse> {\n const reqBody: GetCoverageResultRequest = {\n coverageId,\n };\n\n const headers = await this.#createHeaders();\n\n // Start measuring total end-to-end latency including retries and delays\n const startTime = Date.now();\n\n const getCoverageResultFn = async (signal: AbortSignal) => {\n const res = await this.#fetch(coverageResultUrl, {\n method: 'POST',\n headers,\n body: JSON.stringify(reqBody),\n signal,\n });\n\n if (res.status === 200) {\n // Return the result without latency here - we'll add total latency after polling completes\n return (await res.json()) as Omit<GetCoverageResultResponse, 'metrics'>;\n }\n\n // parse the error message from the response body\n let errorMessage = 'Timeout waiting for coverage result';\n try {\n const errorJson = await res.json();\n errorMessage = `Failed to get coverage result: ${errorJson.message || errorJson.status}`;\n } catch {\n errorMessage = `Failed to get coverage result: ${res.status}`;\n }\n throw new HttpError(res.status, errorMessage);\n };\n\n const result = await this.#pollingPolicy.start(\n requestId,\n getCoverageResultFn,\n );\n\n // Calculate total end-to-end latency including all retries and delays\n const now = Date.now();\n const totalLatency = now - startTime;\n\n return {\n ...result,\n metrics: { latency: totalLatency },\n } as GetCoverageResultResponse;\n }\n\n async #createHeaders() {\n const accessToken = await this.#getAccessToken();\n return {\n 'Content-Type': 'application/json',\n Authorization: `Bearer ${accessToken}`,\n };\n }\n}\n\n/**\n * Make the body for the init coverage check request.\n *\n * @param txMeta - The transaction metadata.\n * @returns The body for the init coverage check request.\n */\nexport function makeInitCoverageCheckBody(\n txMeta: TransactionMeta,\n): InitCoverageCheckRequest {\n return {\n txParams: [\n {\n authorizationList: txMeta.txParams.authorizationList,\n from: txMeta.txParams.from,\n to: txMeta.txParams.to,\n value: txMeta.txParams.value,\n data: txMeta.txParams.data,\n nonce: txMeta.txParams.nonce,\n },\n ],\n chainId: txMeta.chainId,\n origin: txMeta.origin,\n };\n}\n\n/**\n * Make the body for the init signature coverage check request.\n *\n * @param signatureRequest - The signature request.\n * @returns The body for the init signature coverage check request.\n */\nfunction makeInitSignatureCoverageCheckBody(\n signatureRequest: SignatureRequest,\n): InitSignatureCoverageCheckRequest {\n // TODO: confirm that do we still need to validate the signature data?\n // signature controller already validates the signature data before adding it to the state.\n // @link https://github.com/MetaMask/core/blob/main/packages/signature-controller/src/SignatureController.ts#L408\n const method = parseSignatureRequestMethod(signatureRequest);\n\n return {\n chainId: signatureRequest.chainId,\n data: signatureRequest.messageParams.data,\n from: signatureRequest.messageParams.from,\n method,\n origin: signatureRequest.messageParams.origin,\n };\n}\n\n/**\n * Parse the JSON-RPC method from the signature request.\n *\n * @param signatureRequest - The signature request.\n * @returns The JSON-RPC method.\n */\nexport function parseSignatureRequestMethod(\n signatureRequest: SignatureRequest,\n): string {\n if (signatureRequest.type === SignatureRequestType.TypedSign) {\n switch (signatureRequest.version) {\n case SignTypedDataVersion.V3:\n return EthMethod.SignTypedDataV3;\n case SignTypedDataVersion.V4:\n return EthMethod.SignTypedDataV4;\n case SignTypedDataVersion.V1:\n default:\n return SignatureRequestType.TypedSign;\n }\n }\n\n return signatureRequest.type;\n}\n\n/**\n * Compute the polling interval and retry count for the Cockatiel policy based on the timeout and poll interval given.\n *\n * @param timeout - The timeout in milliseconds.\n * @param pollInterval - The poll interval in milliseconds.\n * @returns The polling interval and retry count.\n */\nfunction computePollingIntervalAndRetryCount(\n timeout: number,\n pollInterval: number,\n) {\n const backoff = new ConstantBackoff(pollInterval);\n const computedMaxRetries = Math.floor(timeout / pollInterval) + 1;\n\n const maxRetries =\n isNaN(computedMaxRetries) || !isFinite(computedMaxRetries)\n ? DEFAULT_MAX_RETRIES\n : computedMaxRetries;\n\n return {\n backoff,\n maxRetries,\n };\n}\n"]}
1
+ {"version":3,"file":"backend.mjs","sourceRoot":"","sources":["../src/backend.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n ConstantBackoff,\n DEFAULT_MAX_RETRIES,\n HttpError,\n} from '@metamask/controller-utils';\nimport {\n EthMethod,\n SignatureRequestType,\n} from '@metamask/signature-controller';\nimport type { SignatureRequest } from '@metamask/signature-controller';\nimport type { TransactionMeta } from '@metamask/transaction-controller';\nimport type { AuthorizationList } from '@metamask/transaction-controller';\nimport type { Json } from '@metamask/utils';\n\nimport { SignTypedDataVersion } from './constants';\nimport { PollingWithCockatielPolicy } from './polling-with-policy';\nimport type {\n CheckCoverageRequest,\n CheckSignatureCoverageRequest,\n CoverageResult,\n CoverageStatus,\n LogSignatureRequest,\n LogTransactionRequest,\n ShieldBackend,\n} from './types';\n\nexport type InitCoverageCheckRequest = {\n txParams: [\n {\n authorizationList?: AuthorizationList;\n from: string;\n to?: string;\n value?: string;\n data?: string;\n nonce?: string;\n },\n ];\n chainId: string;\n origin?: string;\n};\n\nexport type InitSignatureCoverageCheckRequest = {\n chainId: string;\n data: Json;\n from: string;\n method: string;\n origin?: string;\n};\n\nexport type InitCoverageCheckResponse = {\n coverageId: string;\n};\n\nexport type GetCoverageResultRequest = {\n coverageId: string;\n};\n\nexport type GetCoverageResultResponse = {\n message?: string;\n reasonCode?: string;\n status: CoverageStatus;\n metrics: {\n latency?: number;\n };\n};\n\nexport class ShieldRemoteBackend implements ShieldBackend {\n readonly #getAccessToken: () => Promise<string>;\n\n readonly #baseUrl: string;\n\n readonly #fetch: typeof globalThis.fetch;\n\n readonly #pollingPolicy: PollingWithCockatielPolicy;\n\n readonly #captureException?: (error: Error) => void;\n\n constructor({\n getAccessToken,\n getCoverageResultTimeout = 5000, // milliseconds\n getCoverageResultPollInterval = 1000, // milliseconds\n baseUrl,\n fetch: fetchFn,\n captureException: captureExceptionFn,\n }: {\n getAccessToken: () => Promise<string>;\n getCoverageResultTimeout?: number;\n getCoverageResultPollInterval?: number;\n baseUrl: string;\n fetch: typeof globalThis.fetch;\n captureException?: (error: Error) => void;\n }) {\n this.#getAccessToken = getAccessToken;\n this.#baseUrl = baseUrl;\n this.#fetch = fetchFn;\n\n const { backoff, maxRetries } = computePollingIntervalAndRetryCount(\n getCoverageResultTimeout,\n getCoverageResultPollInterval,\n );\n\n this.#pollingPolicy = new PollingWithCockatielPolicy({\n backoff,\n maxRetries,\n });\n\n this.#captureException = (error: Error): void => {\n try {\n captureExceptionFn?.(error);\n } catch {\n // ignore error thrown when calling captureException\n }\n };\n }\n\n async checkCoverage(req: CheckCoverageRequest): Promise<CoverageResult> {\n let { coverageId } = req;\n if (!coverageId) {\n const reqBody = makeInitCoverageCheckBody(req.txMeta);\n ({ coverageId } = await this.#initCoverageCheck(\n 'v1/transaction/coverage/init',\n reqBody,\n ));\n }\n\n const txCoverageResultUrl = `${this.#baseUrl}/v1/transaction/coverage/result`;\n const coverageResult = await this.#getCoverageResult(\n req.txMeta.id,\n coverageId,\n txCoverageResultUrl,\n );\n return {\n coverageId,\n message: coverageResult.message,\n reasonCode: coverageResult.reasonCode,\n status: coverageResult.status,\n metrics: coverageResult.metrics,\n };\n }\n\n async checkSignatureCoverage(\n req: CheckSignatureCoverageRequest,\n ): Promise<CoverageResult> {\n let { coverageId } = req;\n if (!coverageId) {\n const reqBody = makeInitSignatureCoverageCheckBody(req.signatureRequest);\n ({ coverageId } = await this.#initCoverageCheck(\n 'v1/signature/coverage/init',\n reqBody,\n ));\n }\n\n const signatureCoverageResultUrl = `${this.#baseUrl}/v1/signature/coverage/result`;\n const coverageResult = await this.#getCoverageResult(\n req.signatureRequest.id,\n coverageId,\n signatureCoverageResultUrl,\n );\n return {\n coverageId,\n message: coverageResult.message,\n reasonCode: coverageResult.reasonCode,\n status: coverageResult.status,\n metrics: coverageResult.metrics,\n };\n }\n\n async logSignature(req: LogSignatureRequest): Promise<void> {\n try {\n const initBody = makeInitSignatureCoverageCheckBody(req.signatureRequest);\n const body = {\n signature: req.signature,\n status: req.status,\n ...initBody,\n };\n\n // cancel the pending get coverage result request\n this.#pollingPolicy.abortPendingRequest(req.signatureRequest.id);\n\n const res = await this.#fetch(\n `${this.#baseUrl}/v1/signature/coverage/log`,\n {\n method: 'POST',\n headers: await this.#createHeaders(),\n body: JSON.stringify(body),\n },\n );\n if (res.status !== 200) {\n throw new Error(`Failed to log signature: ${res.status}`);\n }\n } catch (error) {\n const sentryError = createSentryError(\n 'Failed to log signature',\n error as Error,\n );\n this.#captureException?.(sentryError);\n\n // rethrow the original error\n throw error;\n }\n }\n\n async logTransaction(req: LogTransactionRequest): Promise<void> {\n try {\n const initBody = makeInitCoverageCheckBody(req.txMeta);\n\n const body = {\n transactionHash: req.transactionHash,\n rawTransactionHex: req.rawTransactionHex,\n status: req.status,\n ...initBody,\n };\n\n // cancel the pending get coverage result request\n this.#pollingPolicy.abortPendingRequest(req.txMeta.id);\n\n const res = await this.#fetch(\n `${this.#baseUrl}/v1/transaction/coverage/log`,\n {\n method: 'POST',\n headers: await this.#createHeaders(),\n body: JSON.stringify(body),\n },\n );\n if (res.status !== 200) {\n throw new Error(`Failed to log transaction: ${res.status}`);\n }\n } catch (error) {\n const sentryError = createSentryError(\n 'Failed to log transaction',\n error as Error,\n );\n this.#captureException?.(sentryError);\n\n // rethrow the original error\n throw error;\n }\n }\n\n async #initCoverageCheck(\n path: string,\n reqBody: unknown,\n ): Promise<InitCoverageCheckResponse> {\n try {\n const res = await this.#fetch(`${this.#baseUrl}/${path}`, {\n method: 'POST',\n headers: await this.#createHeaders(),\n body: JSON.stringify(reqBody),\n });\n if (res.status !== 200) {\n throw new Error(`Failed to init coverage check: ${res.status}`);\n }\n return (await res.json()) as InitCoverageCheckResponse;\n } catch (error) {\n const sentryError = createSentryError(\n 'Failed to init coverage check',\n error as Error,\n );\n this.#captureException?.(sentryError);\n\n // rethrow the original error\n throw error;\n }\n }\n\n async #getCoverageResult(\n requestId: string,\n coverageId: string,\n coverageResultUrl: string,\n ): Promise<GetCoverageResultResponse> {\n const reqBody: GetCoverageResultRequest = {\n coverageId,\n };\n\n const headers = await this.#createHeaders();\n\n // Start measuring total end-to-end latency including retries and delays\n const startTime = Date.now();\n\n const getCoverageResultFn = async (\n signal: AbortSignal,\n ): Promise<Omit<GetCoverageResultResponse, 'metrics'>> => {\n const res = await this.#fetch(coverageResultUrl, {\n method: 'POST',\n headers,\n body: JSON.stringify(reqBody),\n signal,\n });\n\n if (res.status === 200) {\n // Return the result without latency here - we'll add total latency after polling completes\n return (await res.json()) as Omit<GetCoverageResultResponse, 'metrics'>;\n }\n\n // parse the error message from the response body\n let errorMessage = 'Timeout waiting for coverage result';\n try {\n const errorJson = await res.json();\n errorMessage = `Failed to get coverage result: ${errorJson.message ?? errorJson.status}`;\n } catch {\n errorMessage = `Failed to get coverage result: ${res.status}`;\n }\n throw new HttpError(res.status, errorMessage);\n };\n\n const result = await this.#pollingPolicy.start(\n requestId,\n getCoverageResultFn,\n );\n\n // Calculate total end-to-end latency including all retries and delays\n const now = Date.now();\n const totalLatency = now - startTime;\n\n return {\n ...result,\n metrics: { latency: totalLatency },\n } as GetCoverageResultResponse;\n }\n\n async #createHeaders(): Promise<Record<string, string>> {\n const accessToken = await this.#getAccessToken();\n return {\n 'Content-Type': 'application/json',\n Authorization: `Bearer ${accessToken}`,\n };\n }\n}\n\n/**\n * Make the body for the init coverage check request.\n *\n * @param txMeta - The transaction metadata.\n * @returns The body for the init coverage check request.\n */\nexport function makeInitCoverageCheckBody(\n txMeta: TransactionMeta,\n): InitCoverageCheckRequest {\n return {\n txParams: [\n {\n authorizationList: txMeta.txParams.authorizationList,\n from: txMeta.txParams.from,\n to: txMeta.txParams.to,\n value: txMeta.txParams.value,\n data: txMeta.txParams.data,\n nonce: txMeta.txParams.nonce,\n },\n ],\n chainId: txMeta.chainId,\n origin: txMeta.origin,\n };\n}\n\n/**\n * Make the body for the init signature coverage check request.\n *\n * @param signatureRequest - The signature request.\n * @returns The body for the init signature coverage check request.\n */\nfunction makeInitSignatureCoverageCheckBody(\n signatureRequest: SignatureRequest,\n): InitSignatureCoverageCheckRequest {\n // TODO: confirm that do we still need to validate the signature data?\n // signature controller already validates the signature data before adding it to the state.\n // @link https://github.com/MetaMask/core/blob/main/packages/signature-controller/src/SignatureController.ts#L408\n const method = parseSignatureRequestMethod(signatureRequest);\n\n return {\n chainId: signatureRequest.chainId,\n data: signatureRequest.messageParams.data,\n from: signatureRequest.messageParams.from,\n method,\n origin: signatureRequest.messageParams.origin,\n };\n}\n\n/**\n * Parse the JSON-RPC method from the signature request.\n *\n * @param signatureRequest - The signature request.\n * @returns The JSON-RPC method.\n */\nexport function parseSignatureRequestMethod(\n signatureRequest: SignatureRequest,\n): string {\n if (signatureRequest.type === SignatureRequestType.TypedSign) {\n switch (signatureRequest.version) {\n case SignTypedDataVersion.V3:\n return EthMethod.SignTypedDataV3;\n case SignTypedDataVersion.V4:\n return EthMethod.SignTypedDataV4;\n case SignTypedDataVersion.V1:\n default:\n return SignatureRequestType.TypedSign;\n }\n }\n\n return signatureRequest.type;\n}\n\n/**\n * Compute the polling interval and retry count for the Cockatiel policy based on the timeout and poll interval given.\n *\n * @param timeout - The timeout in milliseconds.\n * @param pollInterval - The poll interval in milliseconds.\n * @returns The polling interval and retry count.\n */\nfunction computePollingIntervalAndRetryCount(\n timeout: number,\n pollInterval: number,\n): { backoff: ConstantBackoff; maxRetries: number } {\n const backoff = new ConstantBackoff(pollInterval);\n const computedMaxRetries = Math.floor(timeout / pollInterval) + 1;\n\n const maxRetries =\n isNaN(computedMaxRetries) || !isFinite(computedMaxRetries)\n ? DEFAULT_MAX_RETRIES\n : computedMaxRetries;\n\n return {\n backoff,\n maxRetries,\n };\n}\n\n/**\n * Create an error instance with a readable message, a cause and a context for Sentry.\n *\n * @param errorMessage - The error message.\n * @param cause - The cause of the error.\n * @returns A Sentry error.\n */\nfunction createSentryError(errorMessage: string, cause: Error): Error {\n const error = new Error(errorMessage) as Error & {\n cause: Error;\n };\n error.cause = cause;\n return error;\n}\n"]}
@@ -20,7 +20,8 @@ class PollingWithCockatielPolicy {
20
20
  _PollingWithCockatielPolicy_instances.add(this);
21
21
  _PollingWithCockatielPolicy_policy.set(this, void 0);
22
22
  _PollingWithCockatielPolicy_requestEntry.set(this, new Map());
23
- const retryFilterPolicy = (0, cockatiel_1.handleWhen)(__classPrivateFieldGet(this, _PollingWithCockatielPolicy_instances, "m", _PollingWithCockatielPolicy_shouldRetry));
23
+ const shouldRetryFunc = __classPrivateFieldGet(this, _PollingWithCockatielPolicy_instances, "m", _PollingWithCockatielPolicy_shouldRetry).bind(this);
24
+ const retryFilterPolicy = (0, cockatiel_1.handleWhen)(shouldRetryFunc);
24
25
  __classPrivateFieldSet(this, _PollingWithCockatielPolicy_policy, (0, controller_utils_1.createServicePolicy)({
25
26
  ...policyOptions,
26
27
  retryFilterPolicy,
@@ -1 +1 @@
1
- {"version":3,"file":"polling-with-policy.cjs","sourceRoot":"","sources":["../src/polling-with-policy.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;AAAA,iEAA4E;AAK5E,yCAAuC;AAMvC,MAAa,0BAA0B;IAKrC,YAAY,gBAA4C,EAAE;;QAJjD,qDAAuB;QAEvB,mDAAgB,IAAI,GAAG,EAA2B,EAAC;QAG1D,MAAM,iBAAiB,GAAG,IAAA,sBAAU,EAAC,uBAAA,IAAI,sFAAa,CAAC,CAAC;QACxD,uBAAA,IAAI,sCAAW,IAAA,sCAAmB,EAAC;YACjC,GAAG,aAAa;YAChB,iBAAiB;SAClB,CAAC,MAAA,CAAC;IACL,CAAC;IAED,KAAK,CAAC,KAAK,CAAa,SAAiB,EAAE,SAAgC;QACzE,MAAM,eAAe,GAAG,uBAAA,IAAI,6FAAoB,MAAxB,IAAI,EAAqB,SAAS,CAAC,CAAC;QAE5D,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,MAAM,uBAAA,IAAI,0CAAQ,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE;gBAC7D,OAAO,SAAS,CAAC,MAAM,CAAC,CAAC;YAC3B,CAAC,EAAE,eAAe,CAAC,MAAM,CAAC,CAAC;YAC3B,OAAO,MAAM,CAAC;QAChB,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,IAAI,eAAe,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;gBACnC,MAAM,IAAI,KAAK,CAAC,mBAAmB,CAAC,CAAC;YACvC,CAAC;YACD,MAAM,KAAK,CAAC;QACd,CAAC;gBAAS,CAAC;YACT,wFAAwF;YACxF,oGAAoG;YACpG,oFAAoF;YACpF,IAAI,eAAe,KAAK,uBAAA,IAAI,gDAAc,CAAC,GAAG,CAAC,SAAS,CAAC,EAAE,CAAC;gBAC1D,uBAAA,IAAI,kFAAS,MAAb,IAAI,EAAU,SAAS,CAAC,CAAC;YAC3B,CAAC;QACH,CAAC;IACH,CAAC;IAED,mBAAmB,CAAC,SAAiB;QACnC,MAAM,eAAe,GAAG,uBAAA,IAAI,gDAAc,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;QAC1D,eAAe,EAAE,KAAK,EAAE,CAAC;QACzB,uBAAA,IAAI,kFAAS,MAAb,IAAI,EAAU,SAAS,CAAC,CAAC;IAC3B,CAAC;CAwBF;AAhED,gEAgEC;8QAtBqB,SAAiB;IACnC,0CAA0C;IAC1C,IAAI,CAAC,mBAAmB,CAAC,SAAS,CAAC,CAAC;IAEpC,oDAAoD;IACpD,MAAM,eAAe,GAAG,IAAI,eAAe,EAAE,CAAC;IAC9C,uBAAA,IAAI,gDAAc,CAAC,GAAG,CAAC,SAAS,EAAE,eAAe,CAAC,CAAC;IACnD,OAAO,eAAe,CAAC;AACzB,CAAC,qFAEQ,SAAiB;IACxB,uBAAA,IAAI,gDAAc,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;AACvC,CAAC,6FAEY,KAAY;IACvB,IAAI,KAAK,YAAY,4BAAS,EAAE,CAAC;QAC/B,0DAA0D;QAC1D,2EAA2E;QAC3E,OAAO,KAAK,CAAC,UAAU,GAAG,GAAG,IAAI,KAAK,CAAC,UAAU,GAAG,GAAG,CAAC;IAC1D,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC","sourcesContent":["import { createServicePolicy, HttpError } from '@metamask/controller-utils';\nimport type {\n CreateServicePolicyOptions,\n ServicePolicy,\n} from '@metamask/controller-utils';\nimport { handleWhen } from 'cockatiel';\n\nexport type RequestFn<ReturnType> = (\n signal: AbortSignal,\n) => Promise<ReturnType>;\n\nexport class PollingWithCockatielPolicy {\n readonly #policy: ServicePolicy;\n\n readonly #requestEntry = new Map<string, AbortController>();\n\n constructor(policyOptions: CreateServicePolicyOptions = {}) {\n const retryFilterPolicy = handleWhen(this.#shouldRetry);\n this.#policy = createServicePolicy({\n ...policyOptions,\n retryFilterPolicy,\n });\n }\n\n async start<ReturnType>(requestId: string, requestFn: RequestFn<ReturnType>) {\n const abortController = this.#addNewRequestEntry(requestId);\n\n try {\n const result = await this.#policy.execute(async ({ signal }) => {\n return requestFn(signal);\n }, abortController.signal);\n return result;\n } catch (error) {\n if (abortController.signal.aborted) {\n throw new Error('Request cancelled');\n }\n throw error;\n } finally {\n // Only cleanup if this abort controller is still active. If a new request with the same\n // requestId started while this one was running, it would have replaced with a new abort controller.\n // We must not delete the new request's controller when this older request finishes.\n if (abortController === this.#requestEntry.get(requestId)) {\n this.#cleanup(requestId);\n }\n }\n }\n\n abortPendingRequest(requestId: string) {\n const abortController = this.#requestEntry.get(requestId);\n abortController?.abort();\n this.#cleanup(requestId);\n }\n\n #addNewRequestEntry(requestId: string) {\n // abort the previous request if it exists\n this.abortPendingRequest(requestId);\n\n // create a new abort controller for the new request\n const abortController = new AbortController();\n this.#requestEntry.set(requestId, abortController);\n return abortController;\n }\n\n #cleanup(requestId: string) {\n this.#requestEntry.delete(requestId);\n }\n\n #shouldRetry(error: Error): boolean {\n if (error instanceof HttpError) {\n // Note: we don't retry on 5xx errors, only on 4xx errors.\n // but we won't retry on 400 coz it means that the request body is invalid.\n return error.httpStatus > 400 && error.httpStatus < 500;\n }\n return false;\n }\n}\n"]}
1
+ {"version":3,"file":"polling-with-policy.cjs","sourceRoot":"","sources":["../src/polling-with-policy.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;AAAA,iEAA4E;AAK5E,yCAAuC;AAMvC,MAAa,0BAA0B;IAKrC,YAAY,gBAA4C,EAAE;;QAJjD,qDAAuB;QAEvB,mDAAgB,IAAI,GAAG,EAA2B,EAAC;QAG1D,MAAM,eAAe,GAAG,uBAAA,IAAI,sFAAa,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACrD,MAAM,iBAAiB,GAAG,IAAA,sBAAU,EAAC,eAAe,CAAC,CAAC;QACtD,uBAAA,IAAI,sCAAW,IAAA,sCAAmB,EAAC;YACjC,GAAG,aAAa;YAChB,iBAAiB;SAClB,CAAC,MAAA,CAAC;IACL,CAAC;IAED,KAAK,CAAC,KAAK,CACT,SAAiB,EACjB,SAAgC;QAEhC,MAAM,eAAe,GAAG,uBAAA,IAAI,6FAAoB,MAAxB,IAAI,EAAqB,SAAS,CAAC,CAAC;QAE5D,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,MAAM,uBAAA,IAAI,0CAAQ,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE;gBAC7D,OAAO,SAAS,CAAC,MAAM,CAAC,CAAC;YAC3B,CAAC,EAAE,eAAe,CAAC,MAAM,CAAC,CAAC;YAC3B,OAAO,MAAM,CAAC;QAChB,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,IAAI,eAAe,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;gBACnC,MAAM,IAAI,KAAK,CAAC,mBAAmB,CAAC,CAAC;YACvC,CAAC;YACD,MAAM,KAAK,CAAC;QACd,CAAC;gBAAS,CAAC;YACT,wFAAwF;YACxF,oGAAoG;YACpG,oFAAoF;YACpF,IAAI,eAAe,KAAK,uBAAA,IAAI,gDAAc,CAAC,GAAG,CAAC,SAAS,CAAC,EAAE,CAAC;gBAC1D,uBAAA,IAAI,kFAAS,MAAb,IAAI,EAAU,SAAS,CAAC,CAAC;YAC3B,CAAC;QACH,CAAC;IACH,CAAC;IAED,mBAAmB,CAAC,SAAiB;QACnC,MAAM,eAAe,GAAG,uBAAA,IAAI,gDAAc,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;QAC1D,eAAe,EAAE,KAAK,EAAE,CAAC;QACzB,uBAAA,IAAI,kFAAS,MAAb,IAAI,EAAU,SAAS,CAAC,CAAC;IAC3B,CAAC;CAwBF;AApED,gEAoEC;8QAtBqB,SAAiB;IACnC,0CAA0C;IAC1C,IAAI,CAAC,mBAAmB,CAAC,SAAS,CAAC,CAAC;IAEpC,oDAAoD;IACpD,MAAM,eAAe,GAAG,IAAI,eAAe,EAAE,CAAC;IAC9C,uBAAA,IAAI,gDAAc,CAAC,GAAG,CAAC,SAAS,EAAE,eAAe,CAAC,CAAC;IACnD,OAAO,eAAe,CAAC;AACzB,CAAC,qFAEQ,SAAiB;IACxB,uBAAA,IAAI,gDAAc,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;AACvC,CAAC,6FAEY,KAAY;IACvB,IAAI,KAAK,YAAY,4BAAS,EAAE,CAAC;QAC/B,0DAA0D;QAC1D,2EAA2E;QAC3E,OAAO,KAAK,CAAC,UAAU,GAAG,GAAG,IAAI,KAAK,CAAC,UAAU,GAAG,GAAG,CAAC;IAC1D,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC","sourcesContent":["import { createServicePolicy, HttpError } from '@metamask/controller-utils';\nimport type {\n CreateServicePolicyOptions,\n ServicePolicy,\n} from '@metamask/controller-utils';\nimport { handleWhen } from 'cockatiel';\n\nexport type RequestFn<ReturnType> = (\n signal: AbortSignal,\n) => Promise<ReturnType>;\n\nexport class PollingWithCockatielPolicy {\n readonly #policy: ServicePolicy;\n\n readonly #requestEntry = new Map<string, AbortController>();\n\n constructor(policyOptions: CreateServicePolicyOptions = {}) {\n const shouldRetryFunc = this.#shouldRetry.bind(this);\n const retryFilterPolicy = handleWhen(shouldRetryFunc);\n this.#policy = createServicePolicy({\n ...policyOptions,\n retryFilterPolicy,\n });\n }\n\n async start<ReturnType>(\n requestId: string,\n requestFn: RequestFn<ReturnType>,\n ): Promise<ReturnType> {\n const abortController = this.#addNewRequestEntry(requestId);\n\n try {\n const result = await this.#policy.execute(async ({ signal }) => {\n return requestFn(signal);\n }, abortController.signal);\n return result;\n } catch (error) {\n if (abortController.signal.aborted) {\n throw new Error('Request cancelled');\n }\n throw error;\n } finally {\n // Only cleanup if this abort controller is still active. If a new request with the same\n // requestId started while this one was running, it would have replaced with a new abort controller.\n // We must not delete the new request's controller when this older request finishes.\n if (abortController === this.#requestEntry.get(requestId)) {\n this.#cleanup(requestId);\n }\n }\n }\n\n abortPendingRequest(requestId: string): void {\n const abortController = this.#requestEntry.get(requestId);\n abortController?.abort();\n this.#cleanup(requestId);\n }\n\n #addNewRequestEntry(requestId: string): AbortController {\n // abort the previous request if it exists\n this.abortPendingRequest(requestId);\n\n // create a new abort controller for the new request\n const abortController = new AbortController();\n this.#requestEntry.set(requestId, abortController);\n return abortController;\n }\n\n #cleanup(requestId: string): void {\n this.#requestEntry.delete(requestId);\n }\n\n #shouldRetry(error: Error): boolean {\n if (error instanceof HttpError) {\n // Note: we don't retry on 5xx errors, only on 4xx errors.\n // but we won't retry on 400 coz it means that the request body is invalid.\n return error.httpStatus > 400 && error.httpStatus < 500;\n }\n return false;\n }\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"polling-with-policy.d.cts","sourceRoot":"","sources":["../src/polling-with-policy.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,0BAA0B,EAE3B,mCAAmC;AAGpC,MAAM,MAAM,SAAS,CAAC,UAAU,IAAI,CAClC,MAAM,EAAE,WAAW,KAChB,OAAO,CAAC,UAAU,CAAC,CAAC;AAEzB,qBAAa,0BAA0B;;gBAKzB,aAAa,GAAE,0BAA+B;IAQpD,KAAK,CAAC,UAAU,EAAE,SAAS,EAAE,MAAM,EAAE,SAAS,EAAE,SAAS,CAAC,UAAU,CAAC;IAuB3E,mBAAmB,CAAC,SAAS,EAAE,MAAM;CA4BtC"}
1
+ {"version":3,"file":"polling-with-policy.d.cts","sourceRoot":"","sources":["../src/polling-with-policy.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,0BAA0B,EAE3B,mCAAmC;AAGpC,MAAM,MAAM,SAAS,CAAC,UAAU,IAAI,CAClC,MAAM,EAAE,WAAW,KAChB,OAAO,CAAC,UAAU,CAAC,CAAC;AAEzB,qBAAa,0BAA0B;;gBAKzB,aAAa,GAAE,0BAA+B;IASpD,KAAK,CAAC,UAAU,EACpB,SAAS,EAAE,MAAM,EACjB,SAAS,EAAE,SAAS,CAAC,UAAU,CAAC,GAC/B,OAAO,CAAC,UAAU,CAAC;IAuBtB,mBAAmB,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI;CA4B7C"}
@@ -1 +1 @@
1
- {"version":3,"file":"polling-with-policy.d.mts","sourceRoot":"","sources":["../src/polling-with-policy.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,0BAA0B,EAE3B,mCAAmC;AAGpC,MAAM,MAAM,SAAS,CAAC,UAAU,IAAI,CAClC,MAAM,EAAE,WAAW,KAChB,OAAO,CAAC,UAAU,CAAC,CAAC;AAEzB,qBAAa,0BAA0B;;gBAKzB,aAAa,GAAE,0BAA+B;IAQpD,KAAK,CAAC,UAAU,EAAE,SAAS,EAAE,MAAM,EAAE,SAAS,EAAE,SAAS,CAAC,UAAU,CAAC;IAuB3E,mBAAmB,CAAC,SAAS,EAAE,MAAM;CA4BtC"}
1
+ {"version":3,"file":"polling-with-policy.d.mts","sourceRoot":"","sources":["../src/polling-with-policy.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,0BAA0B,EAE3B,mCAAmC;AAGpC,MAAM,MAAM,SAAS,CAAC,UAAU,IAAI,CAClC,MAAM,EAAE,WAAW,KAChB,OAAO,CAAC,UAAU,CAAC,CAAC;AAEzB,qBAAa,0BAA0B;;gBAKzB,aAAa,GAAE,0BAA+B;IASpD,KAAK,CAAC,UAAU,EACpB,SAAS,EAAE,MAAM,EACjB,SAAS,EAAE,SAAS,CAAC,UAAU,CAAC,GAC/B,OAAO,CAAC,UAAU,CAAC;IAuBtB,mBAAmB,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI;CA4B7C"}
@@ -17,7 +17,8 @@ export class PollingWithCockatielPolicy {
17
17
  _PollingWithCockatielPolicy_instances.add(this);
18
18
  _PollingWithCockatielPolicy_policy.set(this, void 0);
19
19
  _PollingWithCockatielPolicy_requestEntry.set(this, new Map());
20
- const retryFilterPolicy = handleWhen(__classPrivateFieldGet(this, _PollingWithCockatielPolicy_instances, "m", _PollingWithCockatielPolicy_shouldRetry));
20
+ const shouldRetryFunc = __classPrivateFieldGet(this, _PollingWithCockatielPolicy_instances, "m", _PollingWithCockatielPolicy_shouldRetry).bind(this);
21
+ const retryFilterPolicy = handleWhen(shouldRetryFunc);
21
22
  __classPrivateFieldSet(this, _PollingWithCockatielPolicy_policy, createServicePolicy({
22
23
  ...policyOptions,
23
24
  retryFilterPolicy,
@@ -1 +1 @@
1
- {"version":3,"file":"polling-with-policy.mjs","sourceRoot":"","sources":["../src/polling-with-policy.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,OAAO,EAAE,mBAAmB,EAAE,SAAS,EAAE,mCAAmC;AAK5E,OAAO,EAAE,UAAU,EAAE,kBAAkB;AAMvC,MAAM,OAAO,0BAA0B;IAKrC,YAAY,gBAA4C,EAAE;;QAJjD,qDAAuB;QAEvB,mDAAgB,IAAI,GAAG,EAA2B,EAAC;QAG1D,MAAM,iBAAiB,GAAG,UAAU,CAAC,uBAAA,IAAI,sFAAa,CAAC,CAAC;QACxD,uBAAA,IAAI,sCAAW,mBAAmB,CAAC;YACjC,GAAG,aAAa;YAChB,iBAAiB;SAClB,CAAC,MAAA,CAAC;IACL,CAAC;IAED,KAAK,CAAC,KAAK,CAAa,SAAiB,EAAE,SAAgC;QACzE,MAAM,eAAe,GAAG,uBAAA,IAAI,6FAAoB,MAAxB,IAAI,EAAqB,SAAS,CAAC,CAAC;QAE5D,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,MAAM,uBAAA,IAAI,0CAAQ,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE;gBAC7D,OAAO,SAAS,CAAC,MAAM,CAAC,CAAC;YAC3B,CAAC,EAAE,eAAe,CAAC,MAAM,CAAC,CAAC;YAC3B,OAAO,MAAM,CAAC;QAChB,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,IAAI,eAAe,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;gBACnC,MAAM,IAAI,KAAK,CAAC,mBAAmB,CAAC,CAAC;YACvC,CAAC;YACD,MAAM,KAAK,CAAC;QACd,CAAC;gBAAS,CAAC;YACT,wFAAwF;YACxF,oGAAoG;YACpG,oFAAoF;YACpF,IAAI,eAAe,KAAK,uBAAA,IAAI,gDAAc,CAAC,GAAG,CAAC,SAAS,CAAC,EAAE,CAAC;gBAC1D,uBAAA,IAAI,kFAAS,MAAb,IAAI,EAAU,SAAS,CAAC,CAAC;YAC3B,CAAC;QACH,CAAC;IACH,CAAC;IAED,mBAAmB,CAAC,SAAiB;QACnC,MAAM,eAAe,GAAG,uBAAA,IAAI,gDAAc,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;QAC1D,eAAe,EAAE,KAAK,EAAE,CAAC;QACzB,uBAAA,IAAI,kFAAS,MAAb,IAAI,EAAU,SAAS,CAAC,CAAC;IAC3B,CAAC;CAwBF;8QAtBqB,SAAiB;IACnC,0CAA0C;IAC1C,IAAI,CAAC,mBAAmB,CAAC,SAAS,CAAC,CAAC;IAEpC,oDAAoD;IACpD,MAAM,eAAe,GAAG,IAAI,eAAe,EAAE,CAAC;IAC9C,uBAAA,IAAI,gDAAc,CAAC,GAAG,CAAC,SAAS,EAAE,eAAe,CAAC,CAAC;IACnD,OAAO,eAAe,CAAC;AACzB,CAAC,qFAEQ,SAAiB;IACxB,uBAAA,IAAI,gDAAc,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;AACvC,CAAC,6FAEY,KAAY;IACvB,IAAI,KAAK,YAAY,SAAS,EAAE,CAAC;QAC/B,0DAA0D;QAC1D,2EAA2E;QAC3E,OAAO,KAAK,CAAC,UAAU,GAAG,GAAG,IAAI,KAAK,CAAC,UAAU,GAAG,GAAG,CAAC;IAC1D,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC","sourcesContent":["import { createServicePolicy, HttpError } from '@metamask/controller-utils';\nimport type {\n CreateServicePolicyOptions,\n ServicePolicy,\n} from '@metamask/controller-utils';\nimport { handleWhen } from 'cockatiel';\n\nexport type RequestFn<ReturnType> = (\n signal: AbortSignal,\n) => Promise<ReturnType>;\n\nexport class PollingWithCockatielPolicy {\n readonly #policy: ServicePolicy;\n\n readonly #requestEntry = new Map<string, AbortController>();\n\n constructor(policyOptions: CreateServicePolicyOptions = {}) {\n const retryFilterPolicy = handleWhen(this.#shouldRetry);\n this.#policy = createServicePolicy({\n ...policyOptions,\n retryFilterPolicy,\n });\n }\n\n async start<ReturnType>(requestId: string, requestFn: RequestFn<ReturnType>) {\n const abortController = this.#addNewRequestEntry(requestId);\n\n try {\n const result = await this.#policy.execute(async ({ signal }) => {\n return requestFn(signal);\n }, abortController.signal);\n return result;\n } catch (error) {\n if (abortController.signal.aborted) {\n throw new Error('Request cancelled');\n }\n throw error;\n } finally {\n // Only cleanup if this abort controller is still active. If a new request with the same\n // requestId started while this one was running, it would have replaced with a new abort controller.\n // We must not delete the new request's controller when this older request finishes.\n if (abortController === this.#requestEntry.get(requestId)) {\n this.#cleanup(requestId);\n }\n }\n }\n\n abortPendingRequest(requestId: string) {\n const abortController = this.#requestEntry.get(requestId);\n abortController?.abort();\n this.#cleanup(requestId);\n }\n\n #addNewRequestEntry(requestId: string) {\n // abort the previous request if it exists\n this.abortPendingRequest(requestId);\n\n // create a new abort controller for the new request\n const abortController = new AbortController();\n this.#requestEntry.set(requestId, abortController);\n return abortController;\n }\n\n #cleanup(requestId: string) {\n this.#requestEntry.delete(requestId);\n }\n\n #shouldRetry(error: Error): boolean {\n if (error instanceof HttpError) {\n // Note: we don't retry on 5xx errors, only on 4xx errors.\n // but we won't retry on 400 coz it means that the request body is invalid.\n return error.httpStatus > 400 && error.httpStatus < 500;\n }\n return false;\n }\n}\n"]}
1
+ {"version":3,"file":"polling-with-policy.mjs","sourceRoot":"","sources":["../src/polling-with-policy.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,OAAO,EAAE,mBAAmB,EAAE,SAAS,EAAE,mCAAmC;AAK5E,OAAO,EAAE,UAAU,EAAE,kBAAkB;AAMvC,MAAM,OAAO,0BAA0B;IAKrC,YAAY,gBAA4C,EAAE;;QAJjD,qDAAuB;QAEvB,mDAAgB,IAAI,GAAG,EAA2B,EAAC;QAG1D,MAAM,eAAe,GAAG,uBAAA,IAAI,sFAAa,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACrD,MAAM,iBAAiB,GAAG,UAAU,CAAC,eAAe,CAAC,CAAC;QACtD,uBAAA,IAAI,sCAAW,mBAAmB,CAAC;YACjC,GAAG,aAAa;YAChB,iBAAiB;SAClB,CAAC,MAAA,CAAC;IACL,CAAC;IAED,KAAK,CAAC,KAAK,CACT,SAAiB,EACjB,SAAgC;QAEhC,MAAM,eAAe,GAAG,uBAAA,IAAI,6FAAoB,MAAxB,IAAI,EAAqB,SAAS,CAAC,CAAC;QAE5D,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,MAAM,uBAAA,IAAI,0CAAQ,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE;gBAC7D,OAAO,SAAS,CAAC,MAAM,CAAC,CAAC;YAC3B,CAAC,EAAE,eAAe,CAAC,MAAM,CAAC,CAAC;YAC3B,OAAO,MAAM,CAAC;QAChB,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,IAAI,eAAe,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;gBACnC,MAAM,IAAI,KAAK,CAAC,mBAAmB,CAAC,CAAC;YACvC,CAAC;YACD,MAAM,KAAK,CAAC;QACd,CAAC;gBAAS,CAAC;YACT,wFAAwF;YACxF,oGAAoG;YACpG,oFAAoF;YACpF,IAAI,eAAe,KAAK,uBAAA,IAAI,gDAAc,CAAC,GAAG,CAAC,SAAS,CAAC,EAAE,CAAC;gBAC1D,uBAAA,IAAI,kFAAS,MAAb,IAAI,EAAU,SAAS,CAAC,CAAC;YAC3B,CAAC;QACH,CAAC;IACH,CAAC;IAED,mBAAmB,CAAC,SAAiB;QACnC,MAAM,eAAe,GAAG,uBAAA,IAAI,gDAAc,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;QAC1D,eAAe,EAAE,KAAK,EAAE,CAAC;QACzB,uBAAA,IAAI,kFAAS,MAAb,IAAI,EAAU,SAAS,CAAC,CAAC;IAC3B,CAAC;CAwBF;8QAtBqB,SAAiB;IACnC,0CAA0C;IAC1C,IAAI,CAAC,mBAAmB,CAAC,SAAS,CAAC,CAAC;IAEpC,oDAAoD;IACpD,MAAM,eAAe,GAAG,IAAI,eAAe,EAAE,CAAC;IAC9C,uBAAA,IAAI,gDAAc,CAAC,GAAG,CAAC,SAAS,EAAE,eAAe,CAAC,CAAC;IACnD,OAAO,eAAe,CAAC;AACzB,CAAC,qFAEQ,SAAiB;IACxB,uBAAA,IAAI,gDAAc,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;AACvC,CAAC,6FAEY,KAAY;IACvB,IAAI,KAAK,YAAY,SAAS,EAAE,CAAC;QAC/B,0DAA0D;QAC1D,2EAA2E;QAC3E,OAAO,KAAK,CAAC,UAAU,GAAG,GAAG,IAAI,KAAK,CAAC,UAAU,GAAG,GAAG,CAAC;IAC1D,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC","sourcesContent":["import { createServicePolicy, HttpError } from '@metamask/controller-utils';\nimport type {\n CreateServicePolicyOptions,\n ServicePolicy,\n} from '@metamask/controller-utils';\nimport { handleWhen } from 'cockatiel';\n\nexport type RequestFn<ReturnType> = (\n signal: AbortSignal,\n) => Promise<ReturnType>;\n\nexport class PollingWithCockatielPolicy {\n readonly #policy: ServicePolicy;\n\n readonly #requestEntry = new Map<string, AbortController>();\n\n constructor(policyOptions: CreateServicePolicyOptions = {}) {\n const shouldRetryFunc = this.#shouldRetry.bind(this);\n const retryFilterPolicy = handleWhen(shouldRetryFunc);\n this.#policy = createServicePolicy({\n ...policyOptions,\n retryFilterPolicy,\n });\n }\n\n async start<ReturnType>(\n requestId: string,\n requestFn: RequestFn<ReturnType>,\n ): Promise<ReturnType> {\n const abortController = this.#addNewRequestEntry(requestId);\n\n try {\n const result = await this.#policy.execute(async ({ signal }) => {\n return requestFn(signal);\n }, abortController.signal);\n return result;\n } catch (error) {\n if (abortController.signal.aborted) {\n throw new Error('Request cancelled');\n }\n throw error;\n } finally {\n // Only cleanup if this abort controller is still active. If a new request with the same\n // requestId started while this one was running, it would have replaced with a new abort controller.\n // We must not delete the new request's controller when this older request finishes.\n if (abortController === this.#requestEntry.get(requestId)) {\n this.#cleanup(requestId);\n }\n }\n }\n\n abortPendingRequest(requestId: string): void {\n const abortController = this.#requestEntry.get(requestId);\n abortController?.abort();\n this.#cleanup(requestId);\n }\n\n #addNewRequestEntry(requestId: string): AbortController {\n // abort the previous request if it exists\n this.abortPendingRequest(requestId);\n\n // create a new abort controller for the new request\n const abortController = new AbortController();\n this.#requestEntry.set(requestId, abortController);\n return abortController;\n }\n\n #cleanup(requestId: string): void {\n this.#requestEntry.delete(requestId);\n }\n\n #shouldRetry(error: Error): boolean {\n if (error instanceof HttpError) {\n // Note: we don't retry on 5xx errors, only on 4xx errors.\n // but we won't retry on 400 coz it means that the request body is invalid.\n return error.httpStatus > 400 && error.httpStatus < 500;\n }\n return false;\n }\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@metamask/shield-controller",
3
- "version": "4.0.0",
3
+ "version": "4.1.0",
4
4
  "description": "Controller handling shield transaction coverage logic",
5
5
  "keywords": [
6
6
  "MetaMask",
@@ -49,11 +49,11 @@
49
49
  },
50
50
  "dependencies": {
51
51
  "@metamask/base-controller": "^9.0.0",
52
- "@metamask/controller-utils": "^11.16.0",
52
+ "@metamask/controller-utils": "^11.17.0",
53
53
  "@metamask/messenger": "^0.3.0",
54
54
  "@metamask/signature-controller": "^38.0.0",
55
- "@metamask/transaction-controller": "^62.5.0",
56
- "@metamask/utils": "^11.8.1",
55
+ "@metamask/transaction-controller": "^62.7.0",
56
+ "@metamask/utils": "^11.9.0",
57
57
  "cockatiel": "^3.1.2"
58
58
  },
59
59
  "devDependencies": {