@metamask/shield-controller 0.1.2 → 0.3.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 +29 -1
- package/dist/ShieldController.cjs +105 -5
- package/dist/ShieldController.cjs.map +1 -1
- package/dist/ShieldController.d.cts +10 -2
- package/dist/ShieldController.d.cts.map +1 -1
- package/dist/ShieldController.d.mts +10 -2
- package/dist/ShieldController.d.mts.map +1 -1
- package/dist/ShieldController.mjs +105 -5
- package/dist/ShieldController.mjs.map +1 -1
- package/dist/backend.cjs +101 -19
- package/dist/backend.cjs.map +1 -1
- package/dist/backend.d.cts +14 -3
- package/dist/backend.d.cts.map +1 -1
- package/dist/backend.d.mts +14 -3
- package/dist/backend.d.mts.map +1 -1
- package/dist/backend.mjs +101 -19
- package/dist/backend.mjs.map +1 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1 -1
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.mts +1 -1
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs.map +1 -1
- package/dist/types.cjs.map +1 -1
- package/dist/types.d.cts +26 -1
- package/dist/types.d.cts.map +1 -1
- package/dist/types.d.mts +26 -1
- package/dist/types.d.mts.map +1 -1
- package/dist/types.mjs.map +1 -1
- package/package.json +6 -4
package/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,32 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## [0.3.0]
|
|
11
|
+
|
|
12
|
+
### Added
|
|
13
|
+
|
|
14
|
+
- Log `not_shown` if result is not available ([#6667](https://github.com/MetaMask/core/pull/6667))
|
|
15
|
+
- Add `message` and `reasonCode` to coverage result type ([#6797](https://github.com/MetaMask/core/pull/6797))
|
|
16
|
+
|
|
17
|
+
### Changed
|
|
18
|
+
|
|
19
|
+
- Bump `@metamask/utils` from `^11.8.0` to `^11.8.1` ([#6708](https://github.com/MetaMask/core/pull/6708))
|
|
20
|
+
- **Breaking:** Change `checkCoverage` API to accept `coverageId` and skip `/init` if `coverageId` is provided ([#6792](https://github.com/MetaMask/core/pull/6792))
|
|
21
|
+
|
|
22
|
+
## [0.2.0]
|
|
23
|
+
|
|
24
|
+
### Added
|
|
25
|
+
|
|
26
|
+
- Add two new controller state metadata properties: `includeInStateLogs` and `usedInUi` ([#6504](https://github.com/MetaMask/core/pull/6504))
|
|
27
|
+
- Add signature coverage checking ([#6501](https://github.com/MetaMask/core/pull/6501))
|
|
28
|
+
- Add transaction and signature logging ([#6633](https://github.com/MetaMask/core/pull/6633))
|
|
29
|
+
|
|
30
|
+
### Changed
|
|
31
|
+
|
|
32
|
+
- Bump `@metamask/signature-controller` from `^33.0.0` to `^34.0.0` ([#6702](https://github.com/MetaMask/core/pull/6702))
|
|
33
|
+
- Bump `@metamask/base-controller` from `^8.2.0` to `^8.4.0` ([#6465](https://github.com/MetaMask/core/pull/6465), [#6632](https://github.com/MetaMask/core/pull/6632))
|
|
34
|
+
- Bump `@metamask/utils` from `^11.4.2` to `^11.8.0` ([#6588](https://github.com/MetaMask/core/pull/6588))
|
|
35
|
+
|
|
10
36
|
## [0.1.2]
|
|
11
37
|
|
|
12
38
|
### Fixed
|
|
@@ -25,7 +51,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
25
51
|
|
|
26
52
|
- Initial release of the shield-controller package ([#6137](https://github.com/MetaMask/core/pull/6137)
|
|
27
53
|
|
|
28
|
-
[Unreleased]: https://github.com/MetaMask/core/compare/@metamask/shield-controller@0.
|
|
54
|
+
[Unreleased]: https://github.com/MetaMask/core/compare/@metamask/shield-controller@0.3.0...HEAD
|
|
55
|
+
[0.3.0]: https://github.com/MetaMask/core/compare/@metamask/shield-controller@0.2.0...@metamask/shield-controller@0.3.0
|
|
56
|
+
[0.2.0]: https://github.com/MetaMask/core/compare/@metamask/shield-controller@0.1.2...@metamask/shield-controller@0.2.0
|
|
29
57
|
[0.1.2]: https://github.com/MetaMask/core/compare/@metamask/shield-controller@0.1.1...@metamask/shield-controller@0.1.2
|
|
30
58
|
[0.1.1]: https://github.com/MetaMask/core/compare/@metamask/shield-controller@0.1.0...@metamask/shield-controller@0.1.1
|
|
31
59
|
[0.1.0]: https://github.com/MetaMask/core/releases/tag/@metamask/shield-controller@0.1.0
|
|
@@ -10,10 +10,12 @@ 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_handleTransactionControllerStateChange,
|
|
13
|
+
var _ShieldController_instances, _ShieldController_backend, _ShieldController_coverageHistoryLimit, _ShieldController_transactionHistoryLimit, _ShieldController_transactionControllerStateChangeHandler, _ShieldController_signatureControllerStateChangeHandler, _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
|
+
const signature_controller_1 = require("@metamask/signature-controller");
|
|
18
|
+
const transaction_controller_1 = require("@metamask/transaction-controller");
|
|
17
19
|
const constants_1 = require("./constants.cjs");
|
|
18
20
|
const logger_1 = require("./logger.cjs");
|
|
19
21
|
const log = (0, logger_1.createModuleLogger)(logger_1.projectLogger, 'ShieldController');
|
|
@@ -35,12 +37,16 @@ exports.getDefaultShieldControllerState = getDefaultShieldControllerState;
|
|
|
35
37
|
*/
|
|
36
38
|
const metadata = {
|
|
37
39
|
coverageResults: {
|
|
40
|
+
includeInStateLogs: true,
|
|
38
41
|
persist: true,
|
|
39
42
|
anonymous: false,
|
|
43
|
+
usedInUi: true,
|
|
40
44
|
},
|
|
41
45
|
orderedTransactionHistory: {
|
|
46
|
+
includeInStateLogs: true,
|
|
42
47
|
persist: true,
|
|
43
48
|
anonymous: false,
|
|
49
|
+
usedInUi: false,
|
|
44
50
|
},
|
|
45
51
|
};
|
|
46
52
|
class ShieldController extends base_controller_1.BaseController {
|
|
@@ -60,16 +66,20 @@ class ShieldController extends base_controller_1.BaseController {
|
|
|
60
66
|
_ShieldController_coverageHistoryLimit.set(this, void 0);
|
|
61
67
|
_ShieldController_transactionHistoryLimit.set(this, void 0);
|
|
62
68
|
_ShieldController_transactionControllerStateChangeHandler.set(this, void 0);
|
|
69
|
+
_ShieldController_signatureControllerStateChangeHandler.set(this, void 0);
|
|
63
70
|
__classPrivateFieldSet(this, _ShieldController_backend, backend, "f");
|
|
64
71
|
__classPrivateFieldSet(this, _ShieldController_coverageHistoryLimit, coverageHistoryLimit, "f");
|
|
65
72
|
__classPrivateFieldSet(this, _ShieldController_transactionHistoryLimit, transactionHistoryLimit, "f");
|
|
66
73
|
__classPrivateFieldSet(this, _ShieldController_transactionControllerStateChangeHandler, __classPrivateFieldGet(this, _ShieldController_instances, "m", _ShieldController_handleTransactionControllerStateChange).bind(this), "f");
|
|
74
|
+
__classPrivateFieldSet(this, _ShieldController_signatureControllerStateChangeHandler, __classPrivateFieldGet(this, _ShieldController_instances, "m", _ShieldController_handleSignatureControllerStateChange).bind(this), "f");
|
|
67
75
|
}
|
|
68
76
|
start() {
|
|
69
77
|
this.messagingSystem.subscribe('TransactionController:stateChange', __classPrivateFieldGet(this, _ShieldController_transactionControllerStateChangeHandler, "f"), (state) => state.transactions);
|
|
78
|
+
this.messagingSystem.subscribe('SignatureController:stateChange', __classPrivateFieldGet(this, _ShieldController_signatureControllerStateChangeHandler, "f"), (state) => state.signatureRequests);
|
|
70
79
|
}
|
|
71
80
|
stop() {
|
|
72
81
|
this.messagingSystem.unsubscribe('TransactionController:stateChange', __classPrivateFieldGet(this, _ShieldController_transactionControllerStateChangeHandler, "f"));
|
|
82
|
+
this.messagingSystem.unsubscribe('SignatureController:stateChange', __classPrivateFieldGet(this, _ShieldController_signatureControllerStateChangeHandler, "f"));
|
|
73
83
|
}
|
|
74
84
|
/**
|
|
75
85
|
* Checks the coverage of a transaction.
|
|
@@ -79,16 +89,61 @@ class ShieldController extends base_controller_1.BaseController {
|
|
|
79
89
|
*/
|
|
80
90
|
async checkCoverage(txMeta) {
|
|
81
91
|
// Check coverage
|
|
82
|
-
const
|
|
92
|
+
const coverageId = __classPrivateFieldGet(this, _ShieldController_instances, "m", _ShieldController_getLatestCoverageId).call(this, txMeta.id);
|
|
93
|
+
const coverageResult = await __classPrivateFieldGet(this, _ShieldController_backend, "f").checkCoverage({
|
|
94
|
+
txMeta,
|
|
95
|
+
coverageId,
|
|
96
|
+
});
|
|
83
97
|
// Publish coverage result
|
|
84
98
|
this.messagingSystem.publish(`${constants_1.controllerName}:coverageResultReceived`, coverageResult);
|
|
85
99
|
// Update state
|
|
86
100
|
__classPrivateFieldGet(this, _ShieldController_instances, "m", _ShieldController_addCoverageResult).call(this, txMeta.id, coverageResult);
|
|
87
101
|
return coverageResult;
|
|
88
102
|
}
|
|
103
|
+
/**
|
|
104
|
+
* Checks the coverage of a signature request.
|
|
105
|
+
*
|
|
106
|
+
* @param signatureRequest - The signature request to check coverage for.
|
|
107
|
+
* @returns The coverage result.
|
|
108
|
+
*/
|
|
109
|
+
async checkSignatureCoverage(signatureRequest) {
|
|
110
|
+
// Check coverage
|
|
111
|
+
const coverageId = __classPrivateFieldGet(this, _ShieldController_instances, "m", _ShieldController_getLatestCoverageId).call(this, signatureRequest.id);
|
|
112
|
+
const coverageResult = await __classPrivateFieldGet(this, _ShieldController_backend, "f").checkSignatureCoverage({
|
|
113
|
+
signatureRequest,
|
|
114
|
+
coverageId,
|
|
115
|
+
});
|
|
116
|
+
// Publish coverage result
|
|
117
|
+
this.messagingSystem.publish(`${constants_1.controllerName}:coverageResultReceived`, coverageResult);
|
|
118
|
+
// Update state
|
|
119
|
+
__classPrivateFieldGet(this, _ShieldController_instances, "m", _ShieldController_addCoverageResult).call(this, signatureRequest.id, coverageResult);
|
|
120
|
+
return coverageResult;
|
|
121
|
+
}
|
|
89
122
|
}
|
|
90
123
|
exports.ShieldController = ShieldController;
|
|
91
|
-
_ShieldController_backend = new WeakMap(), _ShieldController_coverageHistoryLimit = new WeakMap(), _ShieldController_transactionHistoryLimit = new WeakMap(), _ShieldController_transactionControllerStateChangeHandler = new WeakMap(), _ShieldController_instances = new WeakSet(),
|
|
124
|
+
_ShieldController_backend = new WeakMap(), _ShieldController_coverageHistoryLimit = new WeakMap(), _ShieldController_transactionHistoryLimit = new WeakMap(), _ShieldController_transactionControllerStateChangeHandler = new WeakMap(), _ShieldController_signatureControllerStateChangeHandler = new WeakMap(), _ShieldController_instances = new WeakSet(), _ShieldController_handleSignatureControllerStateChange = function _ShieldController_handleSignatureControllerStateChange(signatureRequests, previousSignatureRequests) {
|
|
125
|
+
const signatureRequestsArray = Object.values(signatureRequests);
|
|
126
|
+
const previousSignatureRequestsArray = Object.values(previousSignatureRequests ?? {});
|
|
127
|
+
const previousSignatureRequestsById = new Map(previousSignatureRequestsArray.map((request) => [request.id, request]));
|
|
128
|
+
for (const signatureRequest of signatureRequestsArray) {
|
|
129
|
+
const previousSignatureRequest = previousSignatureRequestsById.get(signatureRequest.id);
|
|
130
|
+
// Check coverage if the signature request is new and has type
|
|
131
|
+
// `personal_sign`.
|
|
132
|
+
if (!previousSignatureRequest &&
|
|
133
|
+
signatureRequest.type === signature_controller_1.SignatureRequestType.PersonalSign) {
|
|
134
|
+
this.checkSignatureCoverage(signatureRequest).catch(
|
|
135
|
+
// istanbul ignore next
|
|
136
|
+
(error) => log('Error checking coverage:', error));
|
|
137
|
+
}
|
|
138
|
+
// Log signature once the signature request has been fulfilled.
|
|
139
|
+
if (signatureRequest.status === signature_controller_1.SignatureRequestStatus.Signed &&
|
|
140
|
+
signatureRequest.status !== previousSignatureRequest?.status) {
|
|
141
|
+
__classPrivateFieldGet(this, _ShieldController_instances, "m", _ShieldController_logSignature).call(this, signatureRequest).catch(
|
|
142
|
+
// istanbul ignore next
|
|
143
|
+
(error) => log('Error logging signature:', error));
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
}, _ShieldController_handleTransactionControllerStateChange = function _ShieldController_handleTransactionControllerStateChange(transactions, previousTransactions) {
|
|
92
147
|
const previousTransactionsById = new Map(previousTransactions?.map((tx) => [tx.id, tx]) ?? []);
|
|
93
148
|
for (const transaction of transactions) {
|
|
94
149
|
const previousTransaction = previousTransactionsById.get(transaction.id);
|
|
@@ -102,10 +157,20 @@ _ShieldController_backend = new WeakMap(), _ShieldController_coverageHistoryLimi
|
|
|
102
157
|
// istanbul ignore next
|
|
103
158
|
(error) => log('Error checking coverage:', error));
|
|
104
159
|
}
|
|
160
|
+
// Log transaction once it has been submitted.
|
|
161
|
+
if (transaction.status === transaction_controller_1.TransactionStatus.submitted &&
|
|
162
|
+
transaction.status !== previousTransaction?.status) {
|
|
163
|
+
__classPrivateFieldGet(this, _ShieldController_instances, "m", _ShieldController_logTransaction).call(this, transaction).catch(
|
|
164
|
+
// istanbul ignore next
|
|
165
|
+
(error) => log('Error logging transaction:', error));
|
|
166
|
+
}
|
|
105
167
|
}
|
|
106
|
-
}, _ShieldController_fetchCoverageResult = async function _ShieldController_fetchCoverageResult(txMeta) {
|
|
107
|
-
return __classPrivateFieldGet(this, _ShieldController_backend, "f").checkCoverage(txMeta);
|
|
108
168
|
}, _ShieldController_addCoverageResult = function _ShieldController_addCoverageResult(txId, coverageResult) {
|
|
169
|
+
// Assert the coverageId hasn't changed.
|
|
170
|
+
const latestCoverageId = __classPrivateFieldGet(this, _ShieldController_instances, "m", _ShieldController_getLatestCoverageId).call(this, txId);
|
|
171
|
+
if (latestCoverageId && coverageResult.coverageId !== latestCoverageId) {
|
|
172
|
+
throw new Error('Coverage ID has changed');
|
|
173
|
+
}
|
|
109
174
|
this.update((draft) => {
|
|
110
175
|
// Fetch coverage result entry.
|
|
111
176
|
let newEntry = false;
|
|
@@ -140,5 +205,40 @@ _ShieldController_backend = new WeakMap(), _ShieldController_coverageHistoryLimi
|
|
|
140
205
|
orderedTransactionHistory.unshift(txId);
|
|
141
206
|
}
|
|
142
207
|
});
|
|
208
|
+
}, _ShieldController_logSignature = async function _ShieldController_logSignature(signatureRequest) {
|
|
209
|
+
const signature = signatureRequest.rawSig;
|
|
210
|
+
if (!signature) {
|
|
211
|
+
throw new Error('Signature not found');
|
|
212
|
+
}
|
|
213
|
+
const { status } = __classPrivateFieldGet(this, _ShieldController_instances, "m", _ShieldController_getCoverageStatus).call(this, signatureRequest.id);
|
|
214
|
+
await __classPrivateFieldGet(this, _ShieldController_backend, "f").logSignature({
|
|
215
|
+
signatureRequest,
|
|
216
|
+
signature,
|
|
217
|
+
status,
|
|
218
|
+
});
|
|
219
|
+
}, _ShieldController_logTransaction = async function _ShieldController_logTransaction(txMeta) {
|
|
220
|
+
const transactionHash = txMeta.hash;
|
|
221
|
+
if (!transactionHash) {
|
|
222
|
+
throw new Error('Transaction hash not found');
|
|
223
|
+
}
|
|
224
|
+
const { status } = __classPrivateFieldGet(this, _ShieldController_instances, "m", _ShieldController_getCoverageStatus).call(this, txMeta.id);
|
|
225
|
+
await __classPrivateFieldGet(this, _ShieldController_backend, "f").logTransaction({
|
|
226
|
+
txMeta,
|
|
227
|
+
transactionHash,
|
|
228
|
+
status,
|
|
229
|
+
});
|
|
230
|
+
}, _ShieldController_getCoverageStatus = function _ShieldController_getCoverageStatus(itemId) {
|
|
231
|
+
// The status is assigned as follows:
|
|
232
|
+
// - 'shown' if we have a result
|
|
233
|
+
// - 'not_shown' if we don't have a result
|
|
234
|
+
const coverageId = __classPrivateFieldGet(this, _ShieldController_instances, "m", _ShieldController_getLatestCoverageId).call(this, itemId);
|
|
235
|
+
let status = 'shown';
|
|
236
|
+
if (!coverageId) {
|
|
237
|
+
log('Coverage ID not found for', itemId);
|
|
238
|
+
status = 'not_shown';
|
|
239
|
+
}
|
|
240
|
+
return { status };
|
|
241
|
+
}, _ShieldController_getLatestCoverageId = function _ShieldController_getLatestCoverageId(itemId) {
|
|
242
|
+
return this.state.coverageResults[itemId]?.results[0]?.coverageId;
|
|
143
243
|
};
|
|
144
244
|
//# sourceMappingURL=ShieldController.cjs.map
|
|
@@ -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 type {\n TransactionControllerStateChangeEvent,\n 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 = 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 persist: true,\n anonymous: false,\n },\n orderedTransactionHistory: {\n persist: true,\n anonymous: 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 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 }\n\n start() {\n this.messagingSystem.subscribe(\n 'TransactionController:stateChange',\n this.#transactionControllerStateChangeHandler,\n (state) => state.transactions,\n );\n }\n\n stop() {\n this.messagingSystem.unsubscribe(\n 'TransactionController:stateChange',\n this.#transactionControllerStateChangeHandler,\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 }\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 coverageResult = await this.#fetchCoverageResult(txMeta);\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 async #fetchCoverageResult(txMeta: TransactionMeta): Promise<CoverageResult> {\n return this.#backend.checkCoverage(txMeta);\n }\n\n #addCoverageResult(txId: string, coverageResult: CoverageResult) {\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"]}
|
|
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 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 }\n\n start() {\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 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,6 +1,7 @@
|
|
|
1
1
|
import { BaseController } from "@metamask/base-controller";
|
|
2
2
|
import type { ControllerStateChangeEvent, RestrictedMessenger } from "@metamask/base-controller";
|
|
3
|
-
import type
|
|
3
|
+
import { type SignatureRequest, type SignatureStateChange } from "@metamask/signature-controller";
|
|
4
|
+
import { type TransactionControllerStateChangeEvent, type TransactionMeta } from "@metamask/transaction-controller";
|
|
4
5
|
import { controllerName } from "./constants.cjs";
|
|
5
6
|
import type { CoverageResult, ShieldBackend } from "./types.cjs";
|
|
6
7
|
export type CoverageResultRecordEntry = {
|
|
@@ -50,7 +51,7 @@ type AllowedActions = never;
|
|
|
50
51
|
/**
|
|
51
52
|
* The external events available to the ShieldController.
|
|
52
53
|
*/
|
|
53
|
-
type AllowedEvents = TransactionControllerStateChangeEvent;
|
|
54
|
+
type AllowedEvents = SignatureStateChange | TransactionControllerStateChangeEvent;
|
|
54
55
|
/**
|
|
55
56
|
* The messenger of the {@link ShieldController}.
|
|
56
57
|
*/
|
|
@@ -74,6 +75,13 @@ export declare class ShieldController extends BaseController<typeof controllerNa
|
|
|
74
75
|
* @returns The coverage result.
|
|
75
76
|
*/
|
|
76
77
|
checkCoverage(txMeta: TransactionMeta): Promise<CoverageResult>;
|
|
78
|
+
/**
|
|
79
|
+
* Checks the coverage of a signature request.
|
|
80
|
+
*
|
|
81
|
+
* @param signatureRequest - The signature request to check coverage for.
|
|
82
|
+
* @returns The coverage result.
|
|
83
|
+
*/
|
|
84
|
+
checkSignatureCoverage(signatureRequest: SignatureRequest): Promise<CoverageResult>;
|
|
77
85
|
}
|
|
78
86
|
export {};
|
|
79
87
|
//# sourceMappingURL=ShieldController.d.cts.map
|
|
@@ -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,0BAA0B,EAC1B,mBAAmB,EACpB,kCAAkC;AACnC,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"ShieldController.d.cts","sourceRoot":"","sources":["../src/ShieldController.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,kCAAkC;AAC3D,OAAO,KAAK,EACV,0BAA0B,EAC1B,mBAAmB,EACpB,kCAAkC;AACnC,OAAO,EAGL,KAAK,gBAAgB,EACrB,KAAK,oBAAoB,EAC1B,uCAAuC;AACxC,OAAO,EAEL,KAAK,qCAAqC,EAC1C,KAAK,eAAe,EACrB,yCAAyC;AAE1C,OAAO,EAAE,cAAc,EAAE,wBAAoB;AAE7C,OAAO,KAAK,EAAE,cAAc,EAAE,aAAa,EAAE,oBAAgB;AAI7D,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,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,GAAG,mCAAmC,CAAC;AAE1E,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,cAAc,GAAG,KAAK,CAAC;AAE5B;;GAEG;AACH,KAAK,aAAa,GACd,oBAAoB,GACpB,qCAAqC,CAAC;AAE1C;;GAEG;AACH,MAAM,MAAM,yBAAyB,GAAG,mBAAmB,CACzD,OAAO,cAAc,EACrB,uBAAuB,GAAG,cAAc,EACxC,sBAAsB,GAAG,aAAa,EACtC,cAAc,CAAC,MAAM,CAAC,EACtB,aAAa,CAAC,MAAM,CAAC,CACtB,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;CAC/B,CAAC;AAEF,qBAAa,gBAAiB,SAAQ,cAAc,CAClD,OAAO,cAAc,EACrB,qBAAqB,EACrB,yBAAyB,CAC1B;;gBAiBa,OAAO,EAAE,uBAAuB;IA2B5C,KAAK;IAcL,IAAI;IA0FJ;;;;;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;CAiH3B"}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { BaseController } from "@metamask/base-controller";
|
|
2
2
|
import type { ControllerStateChangeEvent, RestrictedMessenger } from "@metamask/base-controller";
|
|
3
|
-
import type
|
|
3
|
+
import { type SignatureRequest, type SignatureStateChange } from "@metamask/signature-controller";
|
|
4
|
+
import { type TransactionControllerStateChangeEvent, type TransactionMeta } from "@metamask/transaction-controller";
|
|
4
5
|
import { controllerName } from "./constants.mjs";
|
|
5
6
|
import type { CoverageResult, ShieldBackend } from "./types.mjs";
|
|
6
7
|
export type CoverageResultRecordEntry = {
|
|
@@ -50,7 +51,7 @@ type AllowedActions = never;
|
|
|
50
51
|
/**
|
|
51
52
|
* The external events available to the ShieldController.
|
|
52
53
|
*/
|
|
53
|
-
type AllowedEvents = TransactionControllerStateChangeEvent;
|
|
54
|
+
type AllowedEvents = SignatureStateChange | TransactionControllerStateChangeEvent;
|
|
54
55
|
/**
|
|
55
56
|
* The messenger of the {@link ShieldController}.
|
|
56
57
|
*/
|
|
@@ -74,6 +75,13 @@ export declare class ShieldController extends BaseController<typeof controllerNa
|
|
|
74
75
|
* @returns The coverage result.
|
|
75
76
|
*/
|
|
76
77
|
checkCoverage(txMeta: TransactionMeta): Promise<CoverageResult>;
|
|
78
|
+
/**
|
|
79
|
+
* Checks the coverage of a signature request.
|
|
80
|
+
*
|
|
81
|
+
* @param signatureRequest - The signature request to check coverage for.
|
|
82
|
+
* @returns The coverage result.
|
|
83
|
+
*/
|
|
84
|
+
checkSignatureCoverage(signatureRequest: SignatureRequest): Promise<CoverageResult>;
|
|
77
85
|
}
|
|
78
86
|
export {};
|
|
79
87
|
//# sourceMappingURL=ShieldController.d.mts.map
|
|
@@ -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,0BAA0B,EAC1B,mBAAmB,EACpB,kCAAkC;AACnC,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"ShieldController.d.mts","sourceRoot":"","sources":["../src/ShieldController.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,kCAAkC;AAC3D,OAAO,KAAK,EACV,0BAA0B,EAC1B,mBAAmB,EACpB,kCAAkC;AACnC,OAAO,EAGL,KAAK,gBAAgB,EACrB,KAAK,oBAAoB,EAC1B,uCAAuC;AACxC,OAAO,EAEL,KAAK,qCAAqC,EAC1C,KAAK,eAAe,EACrB,yCAAyC;AAE1C,OAAO,EAAE,cAAc,EAAE,wBAAoB;AAE7C,OAAO,KAAK,EAAE,cAAc,EAAE,aAAa,EAAE,oBAAgB;AAI7D,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,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,GAAG,mCAAmC,CAAC;AAE1E,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,cAAc,GAAG,KAAK,CAAC;AAE5B;;GAEG;AACH,KAAK,aAAa,GACd,oBAAoB,GACpB,qCAAqC,CAAC;AAE1C;;GAEG;AACH,MAAM,MAAM,yBAAyB,GAAG,mBAAmB,CACzD,OAAO,cAAc,EACrB,uBAAuB,GAAG,cAAc,EACxC,sBAAsB,GAAG,aAAa,EACtC,cAAc,CAAC,MAAM,CAAC,EACtB,aAAa,CAAC,MAAM,CAAC,CACtB,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;CAC/B,CAAC;AAEF,qBAAa,gBAAiB,SAAQ,cAAc,CAClD,OAAO,cAAc,EACrB,qBAAqB,EACrB,yBAAyB,CAC1B;;gBAiBa,OAAO,EAAE,uBAAuB;IA2B5C,KAAK;IAcL,IAAI;IA0FJ;;;;;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;CAiH3B"}
|
|
@@ -9,8 +9,10 @@ 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_handleTransactionControllerStateChange,
|
|
12
|
+
var _ShieldController_instances, _ShieldController_backend, _ShieldController_coverageHistoryLimit, _ShieldController_transactionHistoryLimit, _ShieldController_transactionControllerStateChangeHandler, _ShieldController_signatureControllerStateChangeHandler, _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, SignatureRequestType } from "@metamask/signature-controller";
|
|
15
|
+
import { TransactionStatus } from "@metamask/transaction-controller";
|
|
14
16
|
import { controllerName } from "./constants.mjs";
|
|
15
17
|
import { projectLogger, createModuleLogger } from "./logger.mjs";
|
|
16
18
|
const log = createModuleLogger(projectLogger, 'ShieldController');
|
|
@@ -31,12 +33,16 @@ export function getDefaultShieldControllerState() {
|
|
|
31
33
|
*/
|
|
32
34
|
const metadata = {
|
|
33
35
|
coverageResults: {
|
|
36
|
+
includeInStateLogs: true,
|
|
34
37
|
persist: true,
|
|
35
38
|
anonymous: false,
|
|
39
|
+
usedInUi: true,
|
|
36
40
|
},
|
|
37
41
|
orderedTransactionHistory: {
|
|
42
|
+
includeInStateLogs: true,
|
|
38
43
|
persist: true,
|
|
39
44
|
anonymous: false,
|
|
45
|
+
usedInUi: false,
|
|
40
46
|
},
|
|
41
47
|
};
|
|
42
48
|
export class ShieldController extends BaseController {
|
|
@@ -56,16 +62,20 @@ export class ShieldController extends BaseController {
|
|
|
56
62
|
_ShieldController_coverageHistoryLimit.set(this, void 0);
|
|
57
63
|
_ShieldController_transactionHistoryLimit.set(this, void 0);
|
|
58
64
|
_ShieldController_transactionControllerStateChangeHandler.set(this, void 0);
|
|
65
|
+
_ShieldController_signatureControllerStateChangeHandler.set(this, void 0);
|
|
59
66
|
__classPrivateFieldSet(this, _ShieldController_backend, backend, "f");
|
|
60
67
|
__classPrivateFieldSet(this, _ShieldController_coverageHistoryLimit, coverageHistoryLimit, "f");
|
|
61
68
|
__classPrivateFieldSet(this, _ShieldController_transactionHistoryLimit, transactionHistoryLimit, "f");
|
|
62
69
|
__classPrivateFieldSet(this, _ShieldController_transactionControllerStateChangeHandler, __classPrivateFieldGet(this, _ShieldController_instances, "m", _ShieldController_handleTransactionControllerStateChange).bind(this), "f");
|
|
70
|
+
__classPrivateFieldSet(this, _ShieldController_signatureControllerStateChangeHandler, __classPrivateFieldGet(this, _ShieldController_instances, "m", _ShieldController_handleSignatureControllerStateChange).bind(this), "f");
|
|
63
71
|
}
|
|
64
72
|
start() {
|
|
65
73
|
this.messagingSystem.subscribe('TransactionController:stateChange', __classPrivateFieldGet(this, _ShieldController_transactionControllerStateChangeHandler, "f"), (state) => state.transactions);
|
|
74
|
+
this.messagingSystem.subscribe('SignatureController:stateChange', __classPrivateFieldGet(this, _ShieldController_signatureControllerStateChangeHandler, "f"), (state) => state.signatureRequests);
|
|
66
75
|
}
|
|
67
76
|
stop() {
|
|
68
77
|
this.messagingSystem.unsubscribe('TransactionController:stateChange', __classPrivateFieldGet(this, _ShieldController_transactionControllerStateChangeHandler, "f"));
|
|
78
|
+
this.messagingSystem.unsubscribe('SignatureController:stateChange', __classPrivateFieldGet(this, _ShieldController_signatureControllerStateChangeHandler, "f"));
|
|
69
79
|
}
|
|
70
80
|
/**
|
|
71
81
|
* Checks the coverage of a transaction.
|
|
@@ -75,15 +85,60 @@ export class ShieldController extends BaseController {
|
|
|
75
85
|
*/
|
|
76
86
|
async checkCoverage(txMeta) {
|
|
77
87
|
// Check coverage
|
|
78
|
-
const
|
|
88
|
+
const coverageId = __classPrivateFieldGet(this, _ShieldController_instances, "m", _ShieldController_getLatestCoverageId).call(this, txMeta.id);
|
|
89
|
+
const coverageResult = await __classPrivateFieldGet(this, _ShieldController_backend, "f").checkCoverage({
|
|
90
|
+
txMeta,
|
|
91
|
+
coverageId,
|
|
92
|
+
});
|
|
79
93
|
// Publish coverage result
|
|
80
94
|
this.messagingSystem.publish(`${controllerName}:coverageResultReceived`, coverageResult);
|
|
81
95
|
// Update state
|
|
82
96
|
__classPrivateFieldGet(this, _ShieldController_instances, "m", _ShieldController_addCoverageResult).call(this, txMeta.id, coverageResult);
|
|
83
97
|
return coverageResult;
|
|
84
98
|
}
|
|
99
|
+
/**
|
|
100
|
+
* Checks the coverage of a signature request.
|
|
101
|
+
*
|
|
102
|
+
* @param signatureRequest - The signature request to check coverage for.
|
|
103
|
+
* @returns The coverage result.
|
|
104
|
+
*/
|
|
105
|
+
async checkSignatureCoverage(signatureRequest) {
|
|
106
|
+
// Check coverage
|
|
107
|
+
const coverageId = __classPrivateFieldGet(this, _ShieldController_instances, "m", _ShieldController_getLatestCoverageId).call(this, signatureRequest.id);
|
|
108
|
+
const coverageResult = await __classPrivateFieldGet(this, _ShieldController_backend, "f").checkSignatureCoverage({
|
|
109
|
+
signatureRequest,
|
|
110
|
+
coverageId,
|
|
111
|
+
});
|
|
112
|
+
// Publish coverage result
|
|
113
|
+
this.messagingSystem.publish(`${controllerName}:coverageResultReceived`, coverageResult);
|
|
114
|
+
// Update state
|
|
115
|
+
__classPrivateFieldGet(this, _ShieldController_instances, "m", _ShieldController_addCoverageResult).call(this, signatureRequest.id, coverageResult);
|
|
116
|
+
return coverageResult;
|
|
117
|
+
}
|
|
85
118
|
}
|
|
86
|
-
_ShieldController_backend = new WeakMap(), _ShieldController_coverageHistoryLimit = new WeakMap(), _ShieldController_transactionHistoryLimit = new WeakMap(), _ShieldController_transactionControllerStateChangeHandler = new WeakMap(), _ShieldController_instances = new WeakSet(),
|
|
119
|
+
_ShieldController_backend = new WeakMap(), _ShieldController_coverageHistoryLimit = new WeakMap(), _ShieldController_transactionHistoryLimit = new WeakMap(), _ShieldController_transactionControllerStateChangeHandler = new WeakMap(), _ShieldController_signatureControllerStateChangeHandler = new WeakMap(), _ShieldController_instances = new WeakSet(), _ShieldController_handleSignatureControllerStateChange = function _ShieldController_handleSignatureControllerStateChange(signatureRequests, previousSignatureRequests) {
|
|
120
|
+
const signatureRequestsArray = Object.values(signatureRequests);
|
|
121
|
+
const previousSignatureRequestsArray = Object.values(previousSignatureRequests ?? {});
|
|
122
|
+
const previousSignatureRequestsById = new Map(previousSignatureRequestsArray.map((request) => [request.id, request]));
|
|
123
|
+
for (const signatureRequest of signatureRequestsArray) {
|
|
124
|
+
const previousSignatureRequest = previousSignatureRequestsById.get(signatureRequest.id);
|
|
125
|
+
// Check coverage if the signature request is new and has type
|
|
126
|
+
// `personal_sign`.
|
|
127
|
+
if (!previousSignatureRequest &&
|
|
128
|
+
signatureRequest.type === SignatureRequestType.PersonalSign) {
|
|
129
|
+
this.checkSignatureCoverage(signatureRequest).catch(
|
|
130
|
+
// istanbul ignore next
|
|
131
|
+
(error) => log('Error checking coverage:', error));
|
|
132
|
+
}
|
|
133
|
+
// Log signature once the signature request has been fulfilled.
|
|
134
|
+
if (signatureRequest.status === SignatureRequestStatus.Signed &&
|
|
135
|
+
signatureRequest.status !== previousSignatureRequest?.status) {
|
|
136
|
+
__classPrivateFieldGet(this, _ShieldController_instances, "m", _ShieldController_logSignature).call(this, signatureRequest).catch(
|
|
137
|
+
// istanbul ignore next
|
|
138
|
+
(error) => log('Error logging signature:', error));
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
}, _ShieldController_handleTransactionControllerStateChange = function _ShieldController_handleTransactionControllerStateChange(transactions, previousTransactions) {
|
|
87
142
|
const previousTransactionsById = new Map(previousTransactions?.map((tx) => [tx.id, tx]) ?? []);
|
|
88
143
|
for (const transaction of transactions) {
|
|
89
144
|
const previousTransaction = previousTransactionsById.get(transaction.id);
|
|
@@ -97,10 +152,20 @@ _ShieldController_backend = new WeakMap(), _ShieldController_coverageHistoryLimi
|
|
|
97
152
|
// istanbul ignore next
|
|
98
153
|
(error) => log('Error checking coverage:', error));
|
|
99
154
|
}
|
|
155
|
+
// Log transaction once it has been submitted.
|
|
156
|
+
if (transaction.status === TransactionStatus.submitted &&
|
|
157
|
+
transaction.status !== previousTransaction?.status) {
|
|
158
|
+
__classPrivateFieldGet(this, _ShieldController_instances, "m", _ShieldController_logTransaction).call(this, transaction).catch(
|
|
159
|
+
// istanbul ignore next
|
|
160
|
+
(error) => log('Error logging transaction:', error));
|
|
161
|
+
}
|
|
100
162
|
}
|
|
101
|
-
}, _ShieldController_fetchCoverageResult = async function _ShieldController_fetchCoverageResult(txMeta) {
|
|
102
|
-
return __classPrivateFieldGet(this, _ShieldController_backend, "f").checkCoverage(txMeta);
|
|
103
163
|
}, _ShieldController_addCoverageResult = function _ShieldController_addCoverageResult(txId, coverageResult) {
|
|
164
|
+
// Assert the coverageId hasn't changed.
|
|
165
|
+
const latestCoverageId = __classPrivateFieldGet(this, _ShieldController_instances, "m", _ShieldController_getLatestCoverageId).call(this, txId);
|
|
166
|
+
if (latestCoverageId && coverageResult.coverageId !== latestCoverageId) {
|
|
167
|
+
throw new Error('Coverage ID has changed');
|
|
168
|
+
}
|
|
104
169
|
this.update((draft) => {
|
|
105
170
|
// Fetch coverage result entry.
|
|
106
171
|
let newEntry = false;
|
|
@@ -135,5 +200,40 @@ _ShieldController_backend = new WeakMap(), _ShieldController_coverageHistoryLimi
|
|
|
135
200
|
orderedTransactionHistory.unshift(txId);
|
|
136
201
|
}
|
|
137
202
|
});
|
|
203
|
+
}, _ShieldController_logSignature = async function _ShieldController_logSignature(signatureRequest) {
|
|
204
|
+
const signature = signatureRequest.rawSig;
|
|
205
|
+
if (!signature) {
|
|
206
|
+
throw new Error('Signature not found');
|
|
207
|
+
}
|
|
208
|
+
const { status } = __classPrivateFieldGet(this, _ShieldController_instances, "m", _ShieldController_getCoverageStatus).call(this, signatureRequest.id);
|
|
209
|
+
await __classPrivateFieldGet(this, _ShieldController_backend, "f").logSignature({
|
|
210
|
+
signatureRequest,
|
|
211
|
+
signature,
|
|
212
|
+
status,
|
|
213
|
+
});
|
|
214
|
+
}, _ShieldController_logTransaction = async function _ShieldController_logTransaction(txMeta) {
|
|
215
|
+
const transactionHash = txMeta.hash;
|
|
216
|
+
if (!transactionHash) {
|
|
217
|
+
throw new Error('Transaction hash not found');
|
|
218
|
+
}
|
|
219
|
+
const { status } = __classPrivateFieldGet(this, _ShieldController_instances, "m", _ShieldController_getCoverageStatus).call(this, txMeta.id);
|
|
220
|
+
await __classPrivateFieldGet(this, _ShieldController_backend, "f").logTransaction({
|
|
221
|
+
txMeta,
|
|
222
|
+
transactionHash,
|
|
223
|
+
status,
|
|
224
|
+
});
|
|
225
|
+
}, _ShieldController_getCoverageStatus = function _ShieldController_getCoverageStatus(itemId) {
|
|
226
|
+
// The status is assigned as follows:
|
|
227
|
+
// - 'shown' if we have a result
|
|
228
|
+
// - 'not_shown' if we don't have a result
|
|
229
|
+
const coverageId = __classPrivateFieldGet(this, _ShieldController_instances, "m", _ShieldController_getLatestCoverageId).call(this, itemId);
|
|
230
|
+
let status = 'shown';
|
|
231
|
+
if (!coverageId) {
|
|
232
|
+
log('Coverage ID not found for', itemId);
|
|
233
|
+
status = 'not_shown';
|
|
234
|
+
}
|
|
235
|
+
return { status };
|
|
236
|
+
}, _ShieldController_getLatestCoverageId = function _ShieldController_getLatestCoverageId(itemId) {
|
|
237
|
+
return this.state.coverageResults[itemId]?.results[0]?.coverageId;
|
|
138
238
|
};
|
|
139
239
|
//# sourceMappingURL=ShieldController.mjs.map
|