Skip to content

Commit ed74732

Browse files
committed
Merge branch 'main' into 230113-consolidate-TokenDetectionController-DetectTokensController
2 parents aed885a + 8c09b16 commit ed74732

17 files changed

Lines changed: 587 additions & 77 deletions

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@metamask/core-monorepo",
3-
"version": "112.0.0",
3+
"version": "113.0.0",
44
"private": true,
55
"description": "Monorepo for packages shared between MetaMask clients",
66
"repository": {

packages/transaction-controller/CHANGELOG.md

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,13 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
77

88
## [Unreleased]
99

10+
## [21.0.1]
11+
12+
### Fixed
13+
14+
- Resolves transaction custodian promise when setting transaction status to `submitted` or `failed` ([#3845](https://github.com/MetaMask/core/pull/3845))
15+
- Fix normalizer ensuring property `type` is always present in `TransactionParams` ([#3817](https://github.com/MetaMask/core/pull/3817))
16+
1017
## [21.0.0]
1118

1219
### Changed
@@ -457,7 +464,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
457464

458465
All changes listed after this point were applied to this package following the monorepo conversion.
459466

460-
[Unreleased]: https://github.com/MetaMask/core/compare/@metamask/transaction-controller@21.0.0...HEAD
467+
[Unreleased]: https://github.com/MetaMask/core/compare/@metamask/transaction-controller@21.0.1...HEAD
468+
[21.0.1]: https://github.com/MetaMask/core/compare/@metamask/transaction-controller@21.0.0...@metamask/transaction-controller@21.0.1
461469
[21.0.0]: https://github.com/MetaMask/core/compare/@metamask/transaction-controller@20.0.0...@metamask/transaction-controller@21.0.0
462470
[20.0.0]: https://github.com/MetaMask/core/compare/@metamask/transaction-controller@19.0.1...@metamask/transaction-controller@20.0.0
463471
[19.0.1]: https://github.com/MetaMask/core/compare/@metamask/transaction-controller@19.0.0...@metamask/transaction-controller@19.0.1

packages/transaction-controller/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@metamask/transaction-controller",
3-
"version": "21.0.0",
3+
"version": "21.0.1",
44
"description": "Stores transactions alongside their periodically updated statuses and manages interactions such as approval and cancellation",
55
"keywords": [
66
"MetaMask",

packages/user-operation-controller/CHANGELOG.md

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,18 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
77

88
## [Unreleased]
99

10+
## [3.0.0]
11+
12+
### Changed
13+
14+
- **BREAKING**: Add required `from` property to `PrepareUserOperationRequest` ([#3844](https://github.com/MetaMask/core/pull/3844))
15+
- **BREAKING**: Add required `from` property to `AddUserOperationRequest` ([#3844](https://github.com/MetaMask/core/pull/3844))
16+
- **BREAKING**: Make `smartContractAccount` optional in `AddUserOperationOptions` ([#3844](https://github.com/MetaMask/core/pull/3844))
17+
- Use current account snap by default if not provided ([#3844](https://github.com/MetaMask/core/pull/3844))
18+
- Delete user operation if rejected during approval ([#3844](https://github.com/MetaMask/core/pull/3844))
19+
- Set `userFeeLevel` to `custom` in transaction event if using a paymaster ([#3844](https://github.com/MetaMask/core/pull/3844))
20+
- Validate arguments when calling `addUserOperationFromTransaction` ([#3844](https://github.com/MetaMask/core/pull/3844))
21+
1022
## [2.0.0]
1123

1224
### Changed
@@ -31,6 +43,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
3143

3244
- Initial Release ([#3749](https://github.com/MetaMask/core/pull/3749))
3345

34-
[Unreleased]: https://github.com/MetaMask/core/compare/@metamask/user-operation-controller@2.0.0...HEAD
46+
[Unreleased]: https://github.com/MetaMask/core/compare/@metamask/user-operation-controller@3.0.0...HEAD
47+
[3.0.0]: https://github.com/MetaMask/core/compare/@metamask/user-operation-controller@2.0.0...@metamask/user-operation-controller@3.0.0
3548
[2.0.0]: https://github.com/MetaMask/core/compare/@metamask/user-operation-controller@1.0.0...@metamask/user-operation-controller@2.0.0
3649
[1.0.0]: https://github.com/MetaMask/core/releases/tag/@metamask/user-operation-controller@1.0.0

packages/user-operation-controller/package.json

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@metamask/user-operation-controller",
3-
"version": "2.0.0",
3+
"version": "3.0.0",
44
"description": "Creates user operations and manages their life cycle",
55
"keywords": [
66
"MetaMask",
@@ -37,9 +37,11 @@
3737
"@metamask/controller-utils": "^8.0.2",
3838
"@metamask/eth-query": "^4.0.0",
3939
"@metamask/gas-fee-controller": "^13.0.0",
40+
"@metamask/keyring-controller": "^12.2.0",
4041
"@metamask/network-controller": "^17.2.0",
4142
"@metamask/polling-controller": "^5.0.0",
42-
"@metamask/transaction-controller": "^21.0.0",
43+
"@metamask/rpc-errors": "^6.1.0",
44+
"@metamask/transaction-controller": "^21.0.1",
4345
"@metamask/utils": "^8.3.0",
4446
"ethereumjs-util": "^7.0.10",
4547
"immer": "^9.0.6",
@@ -60,8 +62,9 @@
6062
"peerDependencies": {
6163
"@metamask/approval-controller": "^5.1.2",
6264
"@metamask/gas-fee-controller": "^13.0.0",
65+
"@metamask/keyring-controller": "^12.2.0",
6366
"@metamask/network-controller": "^17.2.0",
64-
"@metamask/transaction-controller": "^21.0.0"
67+
"@metamask/transaction-controller": "^21.0.1"
6568
},
6669
"engines": {
6770
"node": ">=16.0.0"

packages/user-operation-controller/src/UserOperationController.test.ts

Lines changed: 61 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { ApprovalType } from '@metamask/controller-utils';
2+
import { errorCodes } from '@metamask/rpc-errors';
23
import {
34
determineTransactionType,
45
TransactionType,
@@ -9,6 +10,7 @@ import { EventEmitter } from 'stream';
910
import { ADDRESS_ZERO, EMPTY_BYTES, VALUE_ZERO } from './constants';
1011
import * as BundlerHelper from './helpers/Bundler';
1112
import * as PendingUserOperationTrackerHelper from './helpers/PendingUserOperationTracker';
13+
import { SnapSmartContractAccount } from './helpers/SnapSmartContractAccount';
1214
import type { UserOperationMetadata } from './types';
1315
import {
1416
UserOperationStatus,
@@ -39,6 +41,7 @@ jest.mock('./utils/gas-fees');
3941
jest.mock('./utils/validation');
4042
jest.mock('./helpers/Bundler');
4143
jest.mock('./helpers/PendingUserOperationTracker');
44+
jest.mock('./helpers/SnapSmartContractAccount');
4245

4346
const CHAIN_ID_MOCK = '0x5';
4447
const USER_OPERATION_HASH_MOCK = '0x123';
@@ -78,15 +81,16 @@ const SIGN_USER_OPERATION_RESPONSE_MOCK: SignUserOperationResponse = {
7881
signature: '0xB',
7982
};
8083

81-
const ADD_USER_OPERATION_REQUEST_MOCK = {
84+
const ADD_USER_OPERATION_REQUEST_MOCK: AddUserOperationRequest = {
8285
data: '0x1',
86+
from: '0x12',
8387
to: '0x2',
8488
value: '0x3',
8589
maxFeePerGas: '0x4',
8690
maxPriorityFeePerGas: '0x5',
8791
};
8892

89-
const ADD_USER_OPERATION_OPTIONS_MOCK = {
93+
const ADD_USER_OPERATION_OPTIONS_MOCK: AddUserOperationOptions = {
9094
networkClientId: NETWORK_CLIENT_ID_MOCK,
9195
origin: ORIGIN_MOCK,
9296
};
@@ -257,10 +261,10 @@ describe('UserOperationController', () => {
257261
updateGasFeesMock
258262
.mockImplementationOnce(async ({ metadata }) => {
259263
metadata.userOperation.maxFeePerGas =
260-
ADD_USER_OPERATION_REQUEST_MOCK.maxFeePerGas;
264+
ADD_USER_OPERATION_REQUEST_MOCK.maxFeePerGas as string;
261265

262266
metadata.userOperation.maxPriorityFeePerGas =
263-
ADD_USER_OPERATION_REQUEST_MOCK.maxPriorityFeePerGas;
267+
ADD_USER_OPERATION_REQUEST_MOCK.maxPriorityFeePerGas as string;
264268
})
265269
.mockImplementationOnce(async ({ metadata }) => {
266270
metadata.userOperation.maxFeePerGas = '0x6';
@@ -589,6 +593,26 @@ describe('UserOperationController', () => {
589593
);
590594
});
591595

596+
it('deletes user operation if rejected', async () => {
597+
const controller = new UserOperationController(optionsMock);
598+
599+
const error = new Error(ERROR_MESSAGE_MOCK);
600+
(error as unknown as Record<string, unknown>).code =
601+
errorCodes.provider.userRejectedRequest;
602+
603+
approvalControllerAddRequestMock.mockClear();
604+
approvalControllerAddRequestMock.mockRejectedValue(error);
605+
606+
const { hash } = await controller.addUserOperation(
607+
ADD_USER_OPERATION_REQUEST_MOCK,
608+
{ ...ADD_USER_OPERATION_OPTIONS_MOCK, smartContractAccount },
609+
);
610+
611+
await expect(hash()).rejects.toThrow(ERROR_MESSAGE_MOCK);
612+
613+
expect(Object.keys(controller.state.userOperations)).toHaveLength(0);
614+
});
615+
592616
// eslint-disable-next-line jest/expect-expect
593617
it('does not throw if hash function not invoked', async () => {
594618
const controller = new UserOperationController(optionsMock);
@@ -782,6 +806,24 @@ describe('UserOperationController', () => {
782806
expect(resultCallbackSuccessMock).not.toHaveBeenCalled();
783807
});
784808

809+
it('uses snap smart contract account if no smart contract account provided', async () => {
810+
const prepareMock = jest.spyOn(
811+
SnapSmartContractAccount.prototype,
812+
'prepareUserOperation',
813+
);
814+
815+
const controller = new UserOperationController(optionsMock);
816+
817+
await addUserOperation(controller, ADD_USER_OPERATION_REQUEST_MOCK, {
818+
...ADD_USER_OPERATION_OPTIONS_MOCK,
819+
smartContractAccount: undefined,
820+
});
821+
822+
await flushPromises();
823+
824+
expect(prepareMock).toHaveBeenCalledTimes(1);
825+
});
826+
785827
describe('if approval request resolved with updated transaction', () => {
786828
it('updates gas fees without regeneration if paymaster data not set', async () => {
787829
const controller = new UserOperationController(optionsMock);
@@ -1078,27 +1120,25 @@ describe('UserOperationController', () => {
10781120
});
10791121
});
10801122

1081-
if (method === 'addUserOperation') {
1082-
it('validates arguments', async () => {
1083-
const controller = new UserOperationController(optionsMock);
1123+
it('validates arguments', async () => {
1124+
const controller = new UserOperationController(optionsMock);
10841125

1085-
await addUserOperation(controller, ADD_USER_OPERATION_REQUEST_MOCK, {
1086-
...ADD_USER_OPERATION_OPTIONS_MOCK,
1087-
smartContractAccount,
1088-
});
1126+
await addUserOperation(controller, ADD_USER_OPERATION_REQUEST_MOCK, {
1127+
...ADD_USER_OPERATION_OPTIONS_MOCK,
1128+
smartContractAccount,
1129+
});
10891130

1090-
expect(validateAddUserOperationRequestMock).toHaveBeenCalledTimes(1);
1091-
expect(validateAddUserOperationRequestMock).toHaveBeenCalledWith(
1092-
ADD_USER_OPERATION_REQUEST_MOCK,
1093-
);
1131+
expect(validateAddUserOperationRequestMock).toHaveBeenCalledTimes(1);
1132+
expect(validateAddUserOperationRequestMock).toHaveBeenCalledWith(
1133+
ADD_USER_OPERATION_REQUEST_MOCK,
1134+
);
10941135

1095-
expect(validateAddUserOperationOptionsMock).toHaveBeenCalledTimes(1);
1096-
expect(validateAddUserOperationOptionsMock).toHaveBeenCalledWith({
1097-
...ADD_USER_OPERATION_OPTIONS_MOCK,
1098-
smartContractAccount,
1099-
});
1136+
expect(validateAddUserOperationOptionsMock).toHaveBeenCalledTimes(1);
1137+
expect(validateAddUserOperationOptionsMock).toHaveBeenCalledWith({
1138+
...ADD_USER_OPERATION_OPTIONS_MOCK,
1139+
smartContractAccount,
11001140
});
1101-
}
1141+
});
11021142

11031143
if (method === 'addUserOperationFromTransaction') {
11041144
it('sets data as undefined if empty string', async () => {

0 commit comments

Comments
 (0)