@metamask/shield-controller 0.3.2 → 1.0.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 +35 -1
- package/dist/ShieldController.cjs +25 -20
- package/dist/ShieldController.cjs.map +1 -1
- package/dist/ShieldController.d.cts +16 -9
- package/dist/ShieldController.d.cts.map +1 -1
- package/dist/ShieldController.d.mts +16 -9
- package/dist/ShieldController.d.mts.map +1 -1
- package/dist/ShieldController.mjs +27 -21
- package/dist/ShieldController.mjs.map +1 -1
- package/dist/backend.cjs +29 -5
- package/dist/backend.cjs.map +1 -1
- package/dist/backend.d.cts +10 -1
- package/dist/backend.d.cts.map +1 -1
- package/dist/backend.d.mts +10 -1
- package/dist/backend.d.mts.map +1 -1
- package/dist/backend.mjs +27 -4
- package/dist/backend.mjs.map +1 -1
- package/dist/constants.cjs +12 -1
- package/dist/constants.cjs.map +1 -1
- package/dist/constants.d.cts +10 -0
- package/dist/constants.d.cts.map +1 -1
- package/dist/constants.d.mts +10 -0
- package/dist/constants.d.mts.map +1 -1
- package/dist/constants.mjs +11 -0
- package/dist/constants.mjs.map +1 -1
- package/dist/index.cjs +2 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +3 -3
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.mts +3 -3
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +1 -1
- package/dist/index.mjs.map +1 -1
- package/dist/types.cjs.map +1 -1
- package/dist/types.d.cts +1 -0
- package/dist/types.d.cts.map +1 -1
- package/dist/types.d.mts +1 -0
- package/dist/types.d.mts.map +1 -1
- package/dist/types.mjs.map +1 -1
- package/package.json +8 -6
package/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,38 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## [1.0.0]
|
|
11
|
+
|
|
12
|
+
### Added
|
|
13
|
+
|
|
14
|
+
- Add new controller action `ShieldControllerGetStateAction` ([#6497](https://github.com/MetaMask/core/pull/6497))
|
|
15
|
+
|
|
16
|
+
### Changed
|
|
17
|
+
|
|
18
|
+
- **BREAKING:** Use new `Messenger` from `@metamask/messenger` ([#6497](https://github.com/MetaMask/core/pull/6497))
|
|
19
|
+
- Previously, `ShieldController` accepted a `RestrictedMessenger` instance from `@metamask/base-controller`.
|
|
20
|
+
- **BREAKING:** Metadata property `anonymous` renamed to `includeInDebugSnapshot` ([#6497](https://github.com/MetaMask/core/pull/6497))
|
|
21
|
+
- **BREAKING:** Bump `@metamask/signature-controller` from `^34.0.0` to `^35.0.0` ([#6962](https://github.com/MetaMask/core/pull/6962))
|
|
22
|
+
- **BREAKING:** Bump `@metamask/transaction-controller` from `^60.0.0` to `^61.0.0` ([#6962](https://github.com/MetaMask/core/pull/6962))
|
|
23
|
+
- Bump `@metamask/base-controller` from `^8.4.2` to `^9.0.0` ([#6962](https://github.com/MetaMask/core/pull/6962))
|
|
24
|
+
|
|
25
|
+
## [0.4.0]
|
|
26
|
+
|
|
27
|
+
### Added
|
|
28
|
+
|
|
29
|
+
- Added optional constructor params, `normalizeSignatureRequest` function which normalize the requests for TypedSignature similar to the security-alerts API. ([#6906](https://github.com/MetaMask/core/pull/6906))
|
|
30
|
+
- Added util function, `parseSignatureRequestMethod` to correctly parse the Json-Rpc method value for the signature request. ([#6906](https://github.com/MetaMask/core/pull/6906))
|
|
31
|
+
|
|
32
|
+
### Changed
|
|
33
|
+
|
|
34
|
+
- Bump `@metamask/base-controller` from `^8.4.1` to `^8.4.2` ([#6917](https://github.com/MetaMask/core/pull/6917))
|
|
35
|
+
- Bump `@metamask/transaction-controller` from `^60.7.0` to `^60.8.0` ([#6883](https://github.com/MetaMask/core/pull/6883))
|
|
36
|
+
- Updated internal MessagingSystem subscriber for TransactionController and SignatureController `stateChange` events. ([#6906](https://github.com/MetaMask/core/pull/6906))
|
|
37
|
+
- Removed `personal_sign` check from the signature-coverage check. Now every signature requests will be sent to ruleset-engine.
|
|
38
|
+
- Updated `TransactionMeta.SimulationData` check conditional to shallow comparison instead of referential comparison, to avoid triggering unnecessary coverage-check requests.
|
|
39
|
+
- Removed signature data validation from the internal `makeInitSignatureCoverageCheckBody` function. ([#6906](https://github.com/MetaMask/core/pull/6906))
|
|
40
|
+
- As signature data is not always `string` (e.g. `eth_signTypedData` uses Array of Object) and the data is already validated in the SignatureController before adding to the state.
|
|
41
|
+
|
|
10
42
|
## [0.3.2]
|
|
11
43
|
|
|
12
44
|
### Changed
|
|
@@ -67,7 +99,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
67
99
|
|
|
68
100
|
- Initial release of the shield-controller package ([#6137](https://github.com/MetaMask/core/pull/6137)
|
|
69
101
|
|
|
70
|
-
[Unreleased]: https://github.com/MetaMask/core/compare/@metamask/shield-controller@0.
|
|
102
|
+
[Unreleased]: https://github.com/MetaMask/core/compare/@metamask/shield-controller@1.0.0...HEAD
|
|
103
|
+
[1.0.0]: https://github.com/MetaMask/core/compare/@metamask/shield-controller@0.4.0...@metamask/shield-controller@1.0.0
|
|
104
|
+
[0.4.0]: https://github.com/MetaMask/core/compare/@metamask/shield-controller@0.3.2...@metamask/shield-controller@0.4.0
|
|
71
105
|
[0.3.2]: https://github.com/MetaMask/core/compare/@metamask/shield-controller@0.3.1...@metamask/shield-controller@0.3.2
|
|
72
106
|
[0.3.1]: https://github.com/MetaMask/core/compare/@metamask/shield-controller@0.3.0...@metamask/shield-controller@0.3.1
|
|
73
107
|
[0.3.0]: https://github.com/MetaMask/core/compare/@metamask/shield-controller@0.2.0...@metamask/shield-controller@0.3.0
|
|
@@ -10,12 +10,13 @@ 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_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_getCoverageStatus, _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");
|
|
17
17
|
const signature_controller_1 = require("@metamask/signature-controller");
|
|
18
18
|
const transaction_controller_1 = require("@metamask/transaction-controller");
|
|
19
|
+
const lodash_1 = require("lodash");
|
|
19
20
|
const constants_1 = require("./constants.cjs");
|
|
20
21
|
const logger_1 = require("./logger.cjs");
|
|
21
22
|
const log = (0, logger_1.createModuleLogger)(logger_1.projectLogger, 'ShieldController');
|
|
@@ -39,19 +40,19 @@ const metadata = {
|
|
|
39
40
|
coverageResults: {
|
|
40
41
|
includeInStateLogs: true,
|
|
41
42
|
persist: true,
|
|
42
|
-
|
|
43
|
+
includeInDebugSnapshot: false,
|
|
43
44
|
usedInUi: true,
|
|
44
45
|
},
|
|
45
46
|
orderedTransactionHistory: {
|
|
46
47
|
includeInStateLogs: true,
|
|
47
48
|
persist: true,
|
|
48
|
-
|
|
49
|
+
includeInDebugSnapshot: false,
|
|
49
50
|
usedInUi: false,
|
|
50
51
|
},
|
|
51
52
|
};
|
|
52
53
|
class ShieldController extends base_controller_1.BaseController {
|
|
53
54
|
constructor(options) {
|
|
54
|
-
const { messenger, state, backend, transactionHistoryLimit = 100, coverageHistoryLimit = 10, } = options;
|
|
55
|
+
const { messenger, state, backend, transactionHistoryLimit = 100, coverageHistoryLimit = 10, normalizeSignatureRequest, } = options;
|
|
55
56
|
super({
|
|
56
57
|
name: constants_1.controllerName,
|
|
57
58
|
metadata,
|
|
@@ -65,6 +66,7 @@ class ShieldController extends base_controller_1.BaseController {
|
|
|
65
66
|
_ShieldController_backend.set(this, void 0);
|
|
66
67
|
_ShieldController_coverageHistoryLimit.set(this, void 0);
|
|
67
68
|
_ShieldController_transactionHistoryLimit.set(this, void 0);
|
|
69
|
+
_ShieldController_normalizeSignatureRequest.set(this, void 0);
|
|
68
70
|
_ShieldController_transactionControllerStateChangeHandler.set(this, void 0);
|
|
69
71
|
_ShieldController_signatureControllerStateChangeHandler.set(this, void 0);
|
|
70
72
|
_ShieldController_started.set(this, void 0);
|
|
@@ -74,22 +76,23 @@ class ShieldController extends base_controller_1.BaseController {
|
|
|
74
76
|
__classPrivateFieldSet(this, _ShieldController_transactionControllerStateChangeHandler, __classPrivateFieldGet(this, _ShieldController_instances, "m", _ShieldController_handleTransactionControllerStateChange).bind(this), "f");
|
|
75
77
|
__classPrivateFieldSet(this, _ShieldController_signatureControllerStateChangeHandler, __classPrivateFieldGet(this, _ShieldController_instances, "m", _ShieldController_handleSignatureControllerStateChange).bind(this), "f");
|
|
76
78
|
__classPrivateFieldSet(this, _ShieldController_started, false, "f");
|
|
79
|
+
__classPrivateFieldSet(this, _ShieldController_normalizeSignatureRequest, normalizeSignatureRequest, "f");
|
|
77
80
|
}
|
|
78
81
|
start() {
|
|
79
82
|
if (__classPrivateFieldGet(this, _ShieldController_started, "f")) {
|
|
80
83
|
return;
|
|
81
84
|
}
|
|
82
85
|
__classPrivateFieldSet(this, _ShieldController_started, true, "f");
|
|
83
|
-
this.
|
|
84
|
-
this.
|
|
86
|
+
this.messenger.subscribe('TransactionController:stateChange', __classPrivateFieldGet(this, _ShieldController_transactionControllerStateChangeHandler, "f"), (state) => state.transactions);
|
|
87
|
+
this.messenger.subscribe('SignatureController:stateChange', __classPrivateFieldGet(this, _ShieldController_signatureControllerStateChangeHandler, "f"), (state) => state.signatureRequests);
|
|
85
88
|
}
|
|
86
89
|
stop() {
|
|
87
90
|
if (!__classPrivateFieldGet(this, _ShieldController_started, "f")) {
|
|
88
91
|
return;
|
|
89
92
|
}
|
|
90
93
|
__classPrivateFieldSet(this, _ShieldController_started, false, "f");
|
|
91
|
-
this.
|
|
92
|
-
this.
|
|
94
|
+
this.messenger.unsubscribe('TransactionController:stateChange', __classPrivateFieldGet(this, _ShieldController_transactionControllerStateChangeHandler, "f"));
|
|
95
|
+
this.messenger.unsubscribe('SignatureController:stateChange', __classPrivateFieldGet(this, _ShieldController_signatureControllerStateChangeHandler, "f"));
|
|
93
96
|
}
|
|
94
97
|
/**
|
|
95
98
|
* Checks the coverage of a transaction.
|
|
@@ -105,7 +108,7 @@ class ShieldController extends base_controller_1.BaseController {
|
|
|
105
108
|
coverageId,
|
|
106
109
|
});
|
|
107
110
|
// Publish coverage result
|
|
108
|
-
this.
|
|
111
|
+
this.messenger.publish(`${constants_1.controllerName}:coverageResultReceived`, coverageResult);
|
|
109
112
|
// Update state
|
|
110
113
|
__classPrivateFieldGet(this, _ShieldController_instances, "m", _ShieldController_addCoverageResult).call(this, txMeta.id, coverageResult);
|
|
111
114
|
return coverageResult;
|
|
@@ -119,28 +122,31 @@ class ShieldController extends base_controller_1.BaseController {
|
|
|
119
122
|
async checkSignatureCoverage(signatureRequest) {
|
|
120
123
|
// Check coverage
|
|
121
124
|
const coverageId = __classPrivateFieldGet(this, _ShieldController_instances, "m", _ShieldController_getLatestCoverageId).call(this, signatureRequest.id);
|
|
125
|
+
// Normalize the signature request before sending it to the backend.
|
|
126
|
+
// This is to ensure that the signature data is normalized and consistent as the security alerts api calls.
|
|
127
|
+
const clonedSignatureRequest = (0, lodash_1.cloneDeep)(signatureRequest);
|
|
128
|
+
const normalizedSignatureRequest = __classPrivateFieldGet(this, _ShieldController_normalizeSignatureRequest, "f")?.call(this, clonedSignatureRequest) ??
|
|
129
|
+
clonedSignatureRequest;
|
|
122
130
|
const coverageResult = await __classPrivateFieldGet(this, _ShieldController_backend, "f").checkSignatureCoverage({
|
|
123
|
-
signatureRequest,
|
|
131
|
+
signatureRequest: normalizedSignatureRequest,
|
|
124
132
|
coverageId,
|
|
125
133
|
});
|
|
126
134
|
// Publish coverage result
|
|
127
|
-
this.
|
|
135
|
+
this.messenger.publish(`${constants_1.controllerName}:coverageResultReceived`, coverageResult);
|
|
128
136
|
// Update state
|
|
129
137
|
__classPrivateFieldGet(this, _ShieldController_instances, "m", _ShieldController_addCoverageResult).call(this, signatureRequest.id, coverageResult);
|
|
130
138
|
return coverageResult;
|
|
131
139
|
}
|
|
132
140
|
}
|
|
133
141
|
exports.ShieldController = ShieldController;
|
|
134
|
-
_ShieldController_backend = new WeakMap(), _ShieldController_coverageHistoryLimit = new WeakMap(), _ShieldController_transactionHistoryLimit = new WeakMap(), _ShieldController_transactionControllerStateChangeHandler = new WeakMap(), _ShieldController_signatureControllerStateChangeHandler = new WeakMap(), _ShieldController_started = new WeakMap(), _ShieldController_instances = new WeakSet(), _ShieldController_handleSignatureControllerStateChange = function _ShieldController_handleSignatureControllerStateChange(signatureRequests, previousSignatureRequests) {
|
|
142
|
+
_ShieldController_backend = new WeakMap(), _ShieldController_coverageHistoryLimit = new WeakMap(), _ShieldController_transactionHistoryLimit = new WeakMap(), _ShieldController_normalizeSignatureRequest = new WeakMap(), _ShieldController_transactionControllerStateChangeHandler = new WeakMap(), _ShieldController_signatureControllerStateChangeHandler = new WeakMap(), _ShieldController_started = new WeakMap(), _ShieldController_instances = new WeakSet(), _ShieldController_handleSignatureControllerStateChange = function _ShieldController_handleSignatureControllerStateChange(signatureRequests, previousSignatureRequests) {
|
|
135
143
|
const signatureRequestsArray = Object.values(signatureRequests);
|
|
136
144
|
const previousSignatureRequestsArray = Object.values(previousSignatureRequests ?? {});
|
|
137
145
|
const previousSignatureRequestsById = new Map(previousSignatureRequestsArray.map((request) => [request.id, request]));
|
|
138
146
|
for (const signatureRequest of signatureRequestsArray) {
|
|
139
147
|
const previousSignatureRequest = previousSignatureRequestsById.get(signatureRequest.id);
|
|
140
|
-
// Check coverage if the signature request is new
|
|
141
|
-
|
|
142
|
-
if (!previousSignatureRequest &&
|
|
143
|
-
signatureRequest.type === signature_controller_1.SignatureRequestType.PersonalSign) {
|
|
148
|
+
// Check coverage if the signature request is new.
|
|
149
|
+
if (!previousSignatureRequest) {
|
|
144
150
|
this.checkSignatureCoverage(signatureRequest).catch(
|
|
145
151
|
// istanbul ignore next
|
|
146
152
|
(error) => log('Error checking coverage:', error));
|
|
@@ -157,12 +163,11 @@ _ShieldController_backend = new WeakMap(), _ShieldController_coverageHistoryLimi
|
|
|
157
163
|
const previousTransactionsById = new Map(previousTransactions?.map((tx) => [tx.id, tx]) ?? []);
|
|
158
164
|
for (const transaction of transactions) {
|
|
159
165
|
const previousTransaction = previousTransactionsById.get(transaction.id);
|
|
166
|
+
// Check if the simulation data has changed.
|
|
167
|
+
const simulationDataNotChanged = (0, lodash_1.isEqual)(transaction.simulationData, previousTransaction?.simulationData);
|
|
160
168
|
// Check coverage if the transaction is new or if the simulation data has
|
|
161
169
|
// changed.
|
|
162
|
-
if (!previousTransaction ||
|
|
163
|
-
// Checking reference equality is sufficient because this object is
|
|
164
|
-
// replaced if the simulation data has changed.
|
|
165
|
-
previousTransaction.simulationData !== transaction.simulationData) {
|
|
170
|
+
if (!previousTransaction || !simulationDataNotChanged) {
|
|
166
171
|
this.checkCoverage(transaction).catch(
|
|
167
172
|
// istanbul ignore next
|
|
168
173
|
(error) => log('Error checking coverage:', error));
|
|
@@ -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 ControllerStateChangeEvent,\n RestrictedMessenger,\n} from '@metamask/base-controller';\nimport {\n SignatureRequestStatus,\n SignatureRequestType,\n type SignatureRequest,\n type SignatureStateChange,\n} from '@metamask/signature-controller';\nimport {\n TransactionStatus,\n type TransactionControllerStateChangeEvent,\n type TransactionMeta,\n} from '@metamask/transaction-controller';\n\nimport { controllerName } from './constants';\nimport { projectLogger, createModuleLogger } from './logger';\nimport type { CoverageResult, ShieldBackend } 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 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 = 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 actions available to the ShieldController.\n */\ntype AllowedActions = never;\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 = RestrictedMessenger<\n typeof controllerName,\n ShieldControllerActions | AllowedActions,\n ShieldControllerEvents | AllowedEvents,\n AllowedActions['type'],\n AllowedEvents['type']\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 anonymous: false,\n usedInUi: true,\n },\n orderedTransactionHistory: {\n includeInStateLogs: true,\n persist: true,\n anonymous: 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\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 #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 } = 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 }\n\n start() {\n if (this.#started) {\n return;\n }\n this.#started = true;\n\n this.messagingSystem.subscribe(\n 'TransactionController:stateChange',\n this.#transactionControllerStateChangeHandler,\n (state) => state.transactions,\n );\n\n this.messagingSystem.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.messagingSystem.unsubscribe(\n 'TransactionController:stateChange',\n this.#transactionControllerStateChangeHandler,\n );\n\n this.messagingSystem.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 and has type\n // `personal_sign`.\n if (\n !previousSignatureRequest &&\n signatureRequest.type === SignatureRequestType.PersonalSign\n ) {\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 // Check coverage if the transaction is new or if the simulation data has\n // changed.\n if (\n !previousTransaction ||\n // Checking reference equality is sufficient because this object is\n // replaced if the simulation data has changed.\n previousTransaction.simulationData !== transaction.simulationData\n ) {\n this.checkCoverage(transaction).catch(\n // istanbul ignore next\n (error) => log('Error checking coverage:', error),\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.messagingSystem.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 const coverageResult = await this.#backend.checkSignatureCoverage({\n signatureRequest,\n coverageId,\n });\n\n // Publish coverage result\n this.messagingSystem.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 { status } = this.#getCoverageStatus(txMeta.id);\n\n await this.#backend.logTransaction({\n txMeta,\n transactionHash,\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 {\n BaseController,\n type ControllerGetStateAction,\n type ControllerStateChangeEvent,\n} from '@metamask/base-controller';\nimport type { Messenger } from '@metamask/messenger';\nimport {\n SignatureRequestStatus,\n type SignatureRequest,\n type SignatureStateChange,\n} from '@metamask/signature-controller';\nimport {\n TransactionStatus,\n type TransactionControllerStateChangeEvent,\n type 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 // Check if the simulation data has changed.\n const simulationDataNotChanged = 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 || !simulationDataNotChanged) {\n this.checkCoverage(transaction).catch(\n // istanbul ignore next\n (error) => log('Error checking coverage:', error),\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 { status } = this.#getCoverageStatus(txMeta.id);\n\n await this.#backend.logTransaction({\n txMeta,\n transactionHash,\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,9 +1,9 @@
|
|
|
1
|
-
import { BaseController } from "@metamask/base-controller";
|
|
2
|
-
import type {
|
|
1
|
+
import { BaseController, type ControllerGetStateAction, type ControllerStateChangeEvent } from "@metamask/base-controller";
|
|
2
|
+
import type { Messenger } from "@metamask/messenger";
|
|
3
3
|
import { type SignatureRequest, type SignatureStateChange } from "@metamask/signature-controller";
|
|
4
4
|
import { type TransactionControllerStateChangeEvent, type TransactionMeta } from "@metamask/transaction-controller";
|
|
5
5
|
import { controllerName } from "./constants.cjs";
|
|
6
|
-
import type { CoverageResult, ShieldBackend } from "./types.cjs";
|
|
6
|
+
import type { CoverageResult, NormalizeSignatureRequestFn, ShieldBackend } from "./types.cjs";
|
|
7
7
|
export type CoverageResultRecordEntry = {
|
|
8
8
|
/**
|
|
9
9
|
* History of coverage results, latest first.
|
|
@@ -27,6 +27,7 @@ export type ShieldControllerState = {
|
|
|
27
27
|
* @returns The default state for the ShieldController.
|
|
28
28
|
*/
|
|
29
29
|
export declare function getDefaultShieldControllerState(): ShieldControllerState;
|
|
30
|
+
export type ShieldControllerGetStateAction = ControllerGetStateAction<typeof controllerName, ShieldControllerState>;
|
|
30
31
|
export type ShieldControllerCheckCoverageAction = {
|
|
31
32
|
type: `${typeof controllerName}:checkCoverage`;
|
|
32
33
|
handler: ShieldController['checkCoverage'];
|
|
@@ -34,7 +35,7 @@ export type ShieldControllerCheckCoverageAction = {
|
|
|
34
35
|
/**
|
|
35
36
|
* The internal actions available to the ShieldController.
|
|
36
37
|
*/
|
|
37
|
-
export type ShieldControllerActions = ShieldControllerCheckCoverageAction;
|
|
38
|
+
export type ShieldControllerActions = ShieldControllerGetStateAction | ShieldControllerCheckCoverageAction;
|
|
38
39
|
export type ShieldControllerCoverageResultReceivedEvent = {
|
|
39
40
|
type: `${typeof controllerName}:coverageResultReceived`;
|
|
40
41
|
payload: [coverageResult: CoverageResult];
|
|
@@ -44,10 +45,6 @@ export type ShieldControllerStateChangeEvent = ControllerStateChangeEvent<typeof
|
|
|
44
45
|
* The internal events available to the ShieldController.
|
|
45
46
|
*/
|
|
46
47
|
export type ShieldControllerEvents = ShieldControllerCoverageResultReceivedEvent | ShieldControllerStateChangeEvent;
|
|
47
|
-
/**
|
|
48
|
-
* The external actions available to the ShieldController.
|
|
49
|
-
*/
|
|
50
|
-
type AllowedActions = never;
|
|
51
48
|
/**
|
|
52
49
|
* The external events available to the ShieldController.
|
|
53
50
|
*/
|
|
@@ -55,13 +52,23 @@ type AllowedEvents = SignatureStateChange | TransactionControllerStateChangeEven
|
|
|
55
52
|
/**
|
|
56
53
|
* The messenger of the {@link ShieldController}.
|
|
57
54
|
*/
|
|
58
|
-
export type ShieldControllerMessenger =
|
|
55
|
+
export type ShieldControllerMessenger = Messenger<typeof controllerName, ShieldControllerActions, ShieldControllerEvents | AllowedEvents>;
|
|
59
56
|
export type ShieldControllerOptions = {
|
|
60
57
|
messenger: ShieldControllerMessenger;
|
|
61
58
|
state?: Partial<ShieldControllerState>;
|
|
62
59
|
backend: ShieldBackend;
|
|
63
60
|
transactionHistoryLimit?: number;
|
|
64
61
|
coverageHistoryLimit?: number;
|
|
62
|
+
/**
|
|
63
|
+
* Normalize the signature request before sending it to the backend.
|
|
64
|
+
* Please note that the reason this is not being done internally is to
|
|
65
|
+
* align the request body (data & params) with the security-alerts API.
|
|
66
|
+
* The same normalization function which is used to normalize security-alerts request should be used here.
|
|
67
|
+
*
|
|
68
|
+
* @param signatureRequest - The signature request to normalize.
|
|
69
|
+
* @returns The normalized signature request.
|
|
70
|
+
*/
|
|
71
|
+
normalizeSignatureRequest?: NormalizeSignatureRequestFn;
|
|
65
72
|
};
|
|
66
73
|
export declare class ShieldController extends BaseController<typeof controllerName, ShieldControllerState, ShieldControllerMessenger> {
|
|
67
74
|
#private;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ShieldController.d.cts","sourceRoot":"","sources":["../src/ShieldController.ts"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"ShieldController.d.cts","sourceRoot":"","sources":["../src/ShieldController.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,cAAc,EACd,KAAK,wBAAwB,EAC7B,KAAK,0BAA0B,EAChC,kCAAkC;AACnC,OAAO,KAAK,EAAE,SAAS,EAAE,4BAA4B;AACrD,OAAO,EAEL,KAAK,gBAAgB,EACrB,KAAK,oBAAoB,EAC1B,uCAAuC;AACxC,OAAO,EAEL,KAAK,qCAAqC,EAC1C,KAAK,eAAe,EACrB,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;IA4FJ;;;;;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;CAwH3B"}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import { BaseController } from "@metamask/base-controller";
|
|
2
|
-
import type {
|
|
1
|
+
import { BaseController, type ControllerGetStateAction, type ControllerStateChangeEvent } from "@metamask/base-controller";
|
|
2
|
+
import type { Messenger } from "@metamask/messenger";
|
|
3
3
|
import { type SignatureRequest, type SignatureStateChange } from "@metamask/signature-controller";
|
|
4
4
|
import { type TransactionControllerStateChangeEvent, type TransactionMeta } from "@metamask/transaction-controller";
|
|
5
5
|
import { controllerName } from "./constants.mjs";
|
|
6
|
-
import type { CoverageResult, ShieldBackend } from "./types.mjs";
|
|
6
|
+
import type { CoverageResult, NormalizeSignatureRequestFn, ShieldBackend } from "./types.mjs";
|
|
7
7
|
export type CoverageResultRecordEntry = {
|
|
8
8
|
/**
|
|
9
9
|
* History of coverage results, latest first.
|
|
@@ -27,6 +27,7 @@ export type ShieldControllerState = {
|
|
|
27
27
|
* @returns The default state for the ShieldController.
|
|
28
28
|
*/
|
|
29
29
|
export declare function getDefaultShieldControllerState(): ShieldControllerState;
|
|
30
|
+
export type ShieldControllerGetStateAction = ControllerGetStateAction<typeof controllerName, ShieldControllerState>;
|
|
30
31
|
export type ShieldControllerCheckCoverageAction = {
|
|
31
32
|
type: `${typeof controllerName}:checkCoverage`;
|
|
32
33
|
handler: ShieldController['checkCoverage'];
|
|
@@ -34,7 +35,7 @@ export type ShieldControllerCheckCoverageAction = {
|
|
|
34
35
|
/**
|
|
35
36
|
* The internal actions available to the ShieldController.
|
|
36
37
|
*/
|
|
37
|
-
export type ShieldControllerActions = ShieldControllerCheckCoverageAction;
|
|
38
|
+
export type ShieldControllerActions = ShieldControllerGetStateAction | ShieldControllerCheckCoverageAction;
|
|
38
39
|
export type ShieldControllerCoverageResultReceivedEvent = {
|
|
39
40
|
type: `${typeof controllerName}:coverageResultReceived`;
|
|
40
41
|
payload: [coverageResult: CoverageResult];
|
|
@@ -44,10 +45,6 @@ export type ShieldControllerStateChangeEvent = ControllerStateChangeEvent<typeof
|
|
|
44
45
|
* The internal events available to the ShieldController.
|
|
45
46
|
*/
|
|
46
47
|
export type ShieldControllerEvents = ShieldControllerCoverageResultReceivedEvent | ShieldControllerStateChangeEvent;
|
|
47
|
-
/**
|
|
48
|
-
* The external actions available to the ShieldController.
|
|
49
|
-
*/
|
|
50
|
-
type AllowedActions = never;
|
|
51
48
|
/**
|
|
52
49
|
* The external events available to the ShieldController.
|
|
53
50
|
*/
|
|
@@ -55,13 +52,23 @@ type AllowedEvents = SignatureStateChange | TransactionControllerStateChangeEven
|
|
|
55
52
|
/**
|
|
56
53
|
* The messenger of the {@link ShieldController}.
|
|
57
54
|
*/
|
|
58
|
-
export type ShieldControllerMessenger =
|
|
55
|
+
export type ShieldControllerMessenger = Messenger<typeof controllerName, ShieldControllerActions, ShieldControllerEvents | AllowedEvents>;
|
|
59
56
|
export type ShieldControllerOptions = {
|
|
60
57
|
messenger: ShieldControllerMessenger;
|
|
61
58
|
state?: Partial<ShieldControllerState>;
|
|
62
59
|
backend: ShieldBackend;
|
|
63
60
|
transactionHistoryLimit?: number;
|
|
64
61
|
coverageHistoryLimit?: number;
|
|
62
|
+
/**
|
|
63
|
+
* Normalize the signature request before sending it to the backend.
|
|
64
|
+
* Please note that the reason this is not being done internally is to
|
|
65
|
+
* align the request body (data & params) with the security-alerts API.
|
|
66
|
+
* The same normalization function which is used to normalize security-alerts request should be used here.
|
|
67
|
+
*
|
|
68
|
+
* @param signatureRequest - The signature request to normalize.
|
|
69
|
+
* @returns The normalized signature request.
|
|
70
|
+
*/
|
|
71
|
+
normalizeSignatureRequest?: NormalizeSignatureRequestFn;
|
|
65
72
|
};
|
|
66
73
|
export declare class ShieldController extends BaseController<typeof controllerName, ShieldControllerState, ShieldControllerMessenger> {
|
|
67
74
|
#private;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ShieldController.d.mts","sourceRoot":"","sources":["../src/ShieldController.ts"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"ShieldController.d.mts","sourceRoot":"","sources":["../src/ShieldController.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,cAAc,EACd,KAAK,wBAAwB,EAC7B,KAAK,0BAA0B,EAChC,kCAAkC;AACnC,OAAO,KAAK,EAAE,SAAS,EAAE,4BAA4B;AACrD,OAAO,EAEL,KAAK,gBAAgB,EACrB,KAAK,oBAAoB,EAC1B,uCAAuC;AACxC,OAAO,EAEL,KAAK,qCAAqC,EAC1C,KAAK,eAAe,EACrB,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;IA4FJ;;;;;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;CAwH3B"}
|
|
@@ -9,10 +9,12 @@ 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_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_getCoverageStatus, _ShieldController_getLatestCoverageId;
|
|
13
13
|
import { BaseController } from "@metamask/base-controller";
|
|
14
|
-
import { SignatureRequestStatus
|
|
14
|
+
import { SignatureRequestStatus } from "@metamask/signature-controller";
|
|
15
15
|
import { TransactionStatus } from "@metamask/transaction-controller";
|
|
16
|
+
import $lodash from "lodash";
|
|
17
|
+
const { cloneDeep, isEqual } = $lodash;
|
|
16
18
|
import { controllerName } from "./constants.mjs";
|
|
17
19
|
import { projectLogger, createModuleLogger } from "./logger.mjs";
|
|
18
20
|
const log = createModuleLogger(projectLogger, 'ShieldController');
|
|
@@ -35,19 +37,19 @@ const metadata = {
|
|
|
35
37
|
coverageResults: {
|
|
36
38
|
includeInStateLogs: true,
|
|
37
39
|
persist: true,
|
|
38
|
-
|
|
40
|
+
includeInDebugSnapshot: false,
|
|
39
41
|
usedInUi: true,
|
|
40
42
|
},
|
|
41
43
|
orderedTransactionHistory: {
|
|
42
44
|
includeInStateLogs: true,
|
|
43
45
|
persist: true,
|
|
44
|
-
|
|
46
|
+
includeInDebugSnapshot: false,
|
|
45
47
|
usedInUi: false,
|
|
46
48
|
},
|
|
47
49
|
};
|
|
48
50
|
export class ShieldController extends BaseController {
|
|
49
51
|
constructor(options) {
|
|
50
|
-
const { messenger, state, backend, transactionHistoryLimit = 100, coverageHistoryLimit = 10, } = options;
|
|
52
|
+
const { messenger, state, backend, transactionHistoryLimit = 100, coverageHistoryLimit = 10, normalizeSignatureRequest, } = options;
|
|
51
53
|
super({
|
|
52
54
|
name: controllerName,
|
|
53
55
|
metadata,
|
|
@@ -61,6 +63,7 @@ export class ShieldController extends BaseController {
|
|
|
61
63
|
_ShieldController_backend.set(this, void 0);
|
|
62
64
|
_ShieldController_coverageHistoryLimit.set(this, void 0);
|
|
63
65
|
_ShieldController_transactionHistoryLimit.set(this, void 0);
|
|
66
|
+
_ShieldController_normalizeSignatureRequest.set(this, void 0);
|
|
64
67
|
_ShieldController_transactionControllerStateChangeHandler.set(this, void 0);
|
|
65
68
|
_ShieldController_signatureControllerStateChangeHandler.set(this, void 0);
|
|
66
69
|
_ShieldController_started.set(this, void 0);
|
|
@@ -70,22 +73,23 @@ export class ShieldController extends BaseController {
|
|
|
70
73
|
__classPrivateFieldSet(this, _ShieldController_transactionControllerStateChangeHandler, __classPrivateFieldGet(this, _ShieldController_instances, "m", _ShieldController_handleTransactionControllerStateChange).bind(this), "f");
|
|
71
74
|
__classPrivateFieldSet(this, _ShieldController_signatureControllerStateChangeHandler, __classPrivateFieldGet(this, _ShieldController_instances, "m", _ShieldController_handleSignatureControllerStateChange).bind(this), "f");
|
|
72
75
|
__classPrivateFieldSet(this, _ShieldController_started, false, "f");
|
|
76
|
+
__classPrivateFieldSet(this, _ShieldController_normalizeSignatureRequest, normalizeSignatureRequest, "f");
|
|
73
77
|
}
|
|
74
78
|
start() {
|
|
75
79
|
if (__classPrivateFieldGet(this, _ShieldController_started, "f")) {
|
|
76
80
|
return;
|
|
77
81
|
}
|
|
78
82
|
__classPrivateFieldSet(this, _ShieldController_started, true, "f");
|
|
79
|
-
this.
|
|
80
|
-
this.
|
|
83
|
+
this.messenger.subscribe('TransactionController:stateChange', __classPrivateFieldGet(this, _ShieldController_transactionControllerStateChangeHandler, "f"), (state) => state.transactions);
|
|
84
|
+
this.messenger.subscribe('SignatureController:stateChange', __classPrivateFieldGet(this, _ShieldController_signatureControllerStateChangeHandler, "f"), (state) => state.signatureRequests);
|
|
81
85
|
}
|
|
82
86
|
stop() {
|
|
83
87
|
if (!__classPrivateFieldGet(this, _ShieldController_started, "f")) {
|
|
84
88
|
return;
|
|
85
89
|
}
|
|
86
90
|
__classPrivateFieldSet(this, _ShieldController_started, false, "f");
|
|
87
|
-
this.
|
|
88
|
-
this.
|
|
91
|
+
this.messenger.unsubscribe('TransactionController:stateChange', __classPrivateFieldGet(this, _ShieldController_transactionControllerStateChangeHandler, "f"));
|
|
92
|
+
this.messenger.unsubscribe('SignatureController:stateChange', __classPrivateFieldGet(this, _ShieldController_signatureControllerStateChangeHandler, "f"));
|
|
89
93
|
}
|
|
90
94
|
/**
|
|
91
95
|
* Checks the coverage of a transaction.
|
|
@@ -101,7 +105,7 @@ export class ShieldController extends BaseController {
|
|
|
101
105
|
coverageId,
|
|
102
106
|
});
|
|
103
107
|
// Publish coverage result
|
|
104
|
-
this.
|
|
108
|
+
this.messenger.publish(`${controllerName}:coverageResultReceived`, coverageResult);
|
|
105
109
|
// Update state
|
|
106
110
|
__classPrivateFieldGet(this, _ShieldController_instances, "m", _ShieldController_addCoverageResult).call(this, txMeta.id, coverageResult);
|
|
107
111
|
return coverageResult;
|
|
@@ -115,27 +119,30 @@ export class ShieldController extends BaseController {
|
|
|
115
119
|
async checkSignatureCoverage(signatureRequest) {
|
|
116
120
|
// Check coverage
|
|
117
121
|
const coverageId = __classPrivateFieldGet(this, _ShieldController_instances, "m", _ShieldController_getLatestCoverageId).call(this, signatureRequest.id);
|
|
122
|
+
// Normalize the signature request before sending it to the backend.
|
|
123
|
+
// This is to ensure that the signature data is normalized and consistent as the security alerts api calls.
|
|
124
|
+
const clonedSignatureRequest = cloneDeep(signatureRequest);
|
|
125
|
+
const normalizedSignatureRequest = __classPrivateFieldGet(this, _ShieldController_normalizeSignatureRequest, "f")?.call(this, clonedSignatureRequest) ??
|
|
126
|
+
clonedSignatureRequest;
|
|
118
127
|
const coverageResult = await __classPrivateFieldGet(this, _ShieldController_backend, "f").checkSignatureCoverage({
|
|
119
|
-
signatureRequest,
|
|
128
|
+
signatureRequest: normalizedSignatureRequest,
|
|
120
129
|
coverageId,
|
|
121
130
|
});
|
|
122
131
|
// Publish coverage result
|
|
123
|
-
this.
|
|
132
|
+
this.messenger.publish(`${controllerName}:coverageResultReceived`, coverageResult);
|
|
124
133
|
// Update state
|
|
125
134
|
__classPrivateFieldGet(this, _ShieldController_instances, "m", _ShieldController_addCoverageResult).call(this, signatureRequest.id, coverageResult);
|
|
126
135
|
return coverageResult;
|
|
127
136
|
}
|
|
128
137
|
}
|
|
129
|
-
_ShieldController_backend = new WeakMap(), _ShieldController_coverageHistoryLimit = new WeakMap(), _ShieldController_transactionHistoryLimit = new WeakMap(), _ShieldController_transactionControllerStateChangeHandler = new WeakMap(), _ShieldController_signatureControllerStateChangeHandler = new WeakMap(), _ShieldController_started = new WeakMap(), _ShieldController_instances = new WeakSet(), _ShieldController_handleSignatureControllerStateChange = function _ShieldController_handleSignatureControllerStateChange(signatureRequests, previousSignatureRequests) {
|
|
138
|
+
_ShieldController_backend = new WeakMap(), _ShieldController_coverageHistoryLimit = new WeakMap(), _ShieldController_transactionHistoryLimit = new WeakMap(), _ShieldController_normalizeSignatureRequest = new WeakMap(), _ShieldController_transactionControllerStateChangeHandler = new WeakMap(), _ShieldController_signatureControllerStateChangeHandler = new WeakMap(), _ShieldController_started = new WeakMap(), _ShieldController_instances = new WeakSet(), _ShieldController_handleSignatureControllerStateChange = function _ShieldController_handleSignatureControllerStateChange(signatureRequests, previousSignatureRequests) {
|
|
130
139
|
const signatureRequestsArray = Object.values(signatureRequests);
|
|
131
140
|
const previousSignatureRequestsArray = Object.values(previousSignatureRequests ?? {});
|
|
132
141
|
const previousSignatureRequestsById = new Map(previousSignatureRequestsArray.map((request) => [request.id, request]));
|
|
133
142
|
for (const signatureRequest of signatureRequestsArray) {
|
|
134
143
|
const previousSignatureRequest = previousSignatureRequestsById.get(signatureRequest.id);
|
|
135
|
-
// Check coverage if the signature request is new
|
|
136
|
-
|
|
137
|
-
if (!previousSignatureRequest &&
|
|
138
|
-
signatureRequest.type === SignatureRequestType.PersonalSign) {
|
|
144
|
+
// Check coverage if the signature request is new.
|
|
145
|
+
if (!previousSignatureRequest) {
|
|
139
146
|
this.checkSignatureCoverage(signatureRequest).catch(
|
|
140
147
|
// istanbul ignore next
|
|
141
148
|
(error) => log('Error checking coverage:', error));
|
|
@@ -152,12 +159,11 @@ _ShieldController_backend = new WeakMap(), _ShieldController_coverageHistoryLimi
|
|
|
152
159
|
const previousTransactionsById = new Map(previousTransactions?.map((tx) => [tx.id, tx]) ?? []);
|
|
153
160
|
for (const transaction of transactions) {
|
|
154
161
|
const previousTransaction = previousTransactionsById.get(transaction.id);
|
|
162
|
+
// Check if the simulation data has changed.
|
|
163
|
+
const simulationDataNotChanged = isEqual(transaction.simulationData, previousTransaction?.simulationData);
|
|
155
164
|
// Check coverage if the transaction is new or if the simulation data has
|
|
156
165
|
// changed.
|
|
157
|
-
if (!previousTransaction ||
|
|
158
|
-
// Checking reference equality is sufficient because this object is
|
|
159
|
-
// replaced if the simulation data has changed.
|
|
160
|
-
previousTransaction.simulationData !== transaction.simulationData) {
|
|
166
|
+
if (!previousTransaction || !simulationDataNotChanged) {
|
|
161
167
|
this.checkCoverage(transaction).catch(
|
|
162
168
|
// istanbul ignore next
|
|
163
169
|
(error) => log('Error checking coverage:', error));
|