Skip to content

Commit

Permalink
chore: merge 7.24.1 into 7.24.2 (#10013)
Browse files Browse the repository at this point in the history
## **Description**

Merge into release 7.24.2

## **Related issues**

Fixes:

## **Manual testing steps**

1. Go to this page...
2.
3.

## **Screenshots/Recordings**

<!-- If applicable, add screenshots and/or recordings to visualize the
before and after of your change. -->

### **Before**

<!-- [screenshots/recordings] -->

### **After**

<!-- [screenshots/recordings] -->

## **Pre-merge author checklist**

- [ ] I’ve followed [MetaMask Contributor
Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile
Coding
Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md).
- [ ] I've completed the PR template to the best of my ability
- [ ] I’ve included tests if applicable
- [ ] I’ve documented my code using [JSDoc](https://jsdoc.app/) format
if applicable
- [ ] I’ve applied the right labels on the PR (see [labeling
guidelines](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/LABELING_GUIDELINES.md)).
Not required for external contributors.

## **Pre-merge reviewer checklist**

- [ ] I've manually tested the PR (e.g. pull and build branch, run the
app, test code being changed).
- [ ] I confirm that this PR addresses all acceptance criteria described
in the ticket it closes and includes the necessary testing evidence such
as recordings and or screenshots.

---------

Co-authored-by: tommasini <46944231+tommasini@users.noreply.github.com>
Co-authored-by: Cal Leung <cleun007@gmail.com>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: Cal Leung <cal.leung@consensys.net>
Co-authored-by: Mark Stacey <markjstacey@gmail.com>
  • Loading branch information
6 people authored Jun 15, 2024
1 parent e32f46f commit 9bd819b
Show file tree
Hide file tree
Showing 12 changed files with 677 additions and 55 deletions.
10 changes: 5 additions & 5 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,13 @@
### Fixed
- [#9905](https://github.com/MetaMask/metamask-mobile/pull/9905): fix: remove metametrics redundant calls and improve compliance


## 7.24.1 - Jun 13, 2024
### Fixed
- [#9943](https://github.com/MetaMask/metamask-mobile/pull/9943): fix: duplicate accounts
- [#9974](https://github.com/MetaMask/metamask-mobile/pull/9974): fix: fix(ramp): memoize asset before passing it to balance hook (#9968)
- [#9978](https://github.com/MetaMask/metamask-mobile/pull/9978): fix: Engine does not exist, network controller is missing ids
- [#9946](https://github.com/MetaMask/metamask-mobile/pull/9946): fix: Update help center URLs
- [#9943](https://github.com/MetaMask/metamask-mobile/pull/9943): fix: Remove duplicate accounts (#9943)
- [#10006](https://github.com/MetaMask/metamask-mobile/pull/10006): fix: Fix order of accounts (#10006)
- [#10004](https://github.com/MetaMask/metamask-mobile/pull/10004): fix: Synchronize account names (#10004)
- [#9974](https://github.com/MetaMask/metamask-mobile/pull/9974): fix: Fix freeze on buy and sell flow (#9974)
- [#9980](https://github.com/MetaMask/metamask-mobile/pull/9980): fix: Fix initialization crash / login error "Engine does not exist (#9980)

## 7.24.0 - Jun 11, 2024
### Added
Expand Down
2 changes: 1 addition & 1 deletion android/app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -181,7 +181,7 @@ android {
applicationId "io.metamask"
minSdkVersion rootProject.ext.minSdkVersion
targetSdkVersion rootProject.ext.targetSdkVersion
versionCode 1347
versionCode 1348
versionName "7.24.2"
testBuildType System.getProperty('testBuildType', 'debug')
missingDimensionStrategy 'react-native-camera', 'general'
Expand Down
106 changes: 67 additions & 39 deletions app/selectors/accountsController.test.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { AccountsControllerState } from '@metamask/accounts-controller';
import { captureException } from '@sentry/react-native';
import { Hex, isValidChecksumAddress } from '@metamask/utils';
import { InternalAccount } from '@metamask/keyring-api';
import DefaultPreference from 'react-native-default-preference';
import {
selectSelectedInternalAccount,
Expand All @@ -13,9 +14,48 @@ import {
expectedUuid2,
internalAccount1,
MOCK_ADDRESS_2,
createMockInternalAccount,
createMockUuidFromAddress,
} from '../util/test/accountsControllerTestUtils';
import { RootState } from '../reducers';
import { AGREED } from '../constants/storage';
import {
MOCK_KEYRINGS,
MOCK_KEYRING_CONTROLLER,
} from './keyringController/testUtils';

/**
* Generates a mocked AccountsController state
* The internal accounts are generated in reverse order relative to the mock keyrings that are used for generation
*
* @returns - A mocked state of AccountsController
*/
const MOCK_GENERATED_ACCOUNTS_CONTROLLER_REVERSED =
(): AccountsControllerState => {
const reversedKeyringAccounts = [...MOCK_KEYRINGS]
.reverse()
.flatMap((keyring) => [...keyring.accounts].reverse());
const accountsForInternalAccounts = reversedKeyringAccounts.reduce(
(record, keyringAccount, index) => {
const lowercasedKeyringAccount = keyringAccount.toLowerCase();
const accountName = `Account ${index}`;
const uuid = createMockUuidFromAddress(lowercasedKeyringAccount);
const internalAccount = createMockInternalAccount(
lowercasedKeyringAccount,
accountName,
);
record[uuid] = internalAccount;
return record;
},
{} as Record<string, InternalAccount>,
);
return {
internalAccounts: {
accounts: accountsForInternalAccounts,
selectedAccount: Object.values(accountsForInternalAccounts)[0].id,
},
};
};

jest.mock('@sentry/react-native', () => ({
captureException: jest.fn(),
Expand Down Expand Up @@ -84,47 +124,35 @@ describe('Accounts Controller Selectors', () => {
});
});
describe('selectInternalAccounts', () => {
it('returns all internal accounts in the accounts controller state', () => {
expect(
selectInternalAccounts({
engine: {
backgroundState: {
AccountsController: MOCK_ACCOUNTS_CONTROLLER_STATE,
},
it(`returns internal accounts of the accounts controller sorted by the keyring controller's accounts`, () => {
const mockAccountsControllerReversed =
MOCK_GENERATED_ACCOUNTS_CONTROLLER_REVERSED();
const internalAccountsResult = selectInternalAccounts({
engine: {
backgroundState: {
KeyringController: MOCK_KEYRING_CONTROLLER,
AccountsController: mockAccountsControllerReversed,
},
} as RootState),
).toEqual([
{
address: '0xc4955c0d639d99699bfd7ec54d9fafee40e4d272',
id: expectedUuid,
metadata: { name: 'Account 1', keyring: { type: 'HD Key Tree' } },
options: {},
methods: [
'personal_sign',
'eth_sign',
'eth_signTransaction',
'eth_signTypedData_v1',
'eth_signTypedData_v3',
'eth_signTypedData_v4',
],
type: 'eip155:eoa',
},
{
address: '0xc4966c0d659d99699bfd7eb54d8fafee40e4a756',
id: expectedUuid2,
metadata: { name: 'Account 2', keyring: { type: 'HD Key Tree' } },
options: {},
methods: [
'personal_sign',
'eth_sign',
'eth_signTransaction',
'eth_signTypedData_v1',
'eth_signTypedData_v3',
'eth_signTypedData_v4',
],
type: 'eip155:eoa',
},
]);
} as RootState);
const expectedInteralAccountsResult = Object.values(
mockAccountsControllerReversed.internalAccounts.accounts,
).reverse();

const internalAccountAddressesResult = internalAccountsResult.map(
(account) => account.address,
);
const expectedAccountAddressesResult = [...MOCK_KEYRINGS].flatMap(
(keyring) => keyring.accounts,
);

// Ensure accounts are correct
expect(internalAccountsResult).toEqual(expectedInteralAccountsResult);

// Ensure that order of internal accounts match order of keyring accounts
expect(internalAccountAddressesResult).toEqual(
expectedAccountAddressesResult,
);
});
});
describe('selectSelectedInternalAccountChecksummedAddress', () => {
Expand Down
34 changes: 32 additions & 2 deletions app/selectors/accountsController.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,43 @@ import { captureException } from '@sentry/react-native';
import { createSelector } from 'reselect';
import { RootState } from '../reducers';
import { createDeepEqualSelector } from './util';
import { selectFlattenedKeyringAccounts } from './keyringController';

/**
*
* @param state - Root redux state
* @returns - AccountsController state
*/
const selectAccountsControllerState = (state: RootState) =>
state.engine.backgroundState.AccountsController;

/**
* A memoized selector that returns internal accounts from the AccountsController, sorted by the order of KeyringController's keyring accounts
*/
export const selectInternalAccounts = createDeepEqualSelector(
selectAccountsControllerState,
(accountControllerState) =>
Object.values(accountControllerState.internalAccounts.accounts),
selectFlattenedKeyringAccounts,
(accountControllerState, orderedKeyringAccounts) => {
const keyringAccountsMap = new Map(
orderedKeyringAccounts.map((account, index) => [
account.toLowerCase(),
index,
]),
);
const sortedAccounts = Object.values(
accountControllerState.internalAccounts.accounts,
).sort(
(a, b) =>
(keyringAccountsMap.get(a.address.toLowerCase()) || 0) -
(keyringAccountsMap.get(b.address.toLowerCase()) || 0),
);
return sortedAccounts;
},
);

/**
* A memoized selector that returns the selected internal account from the AccountsController
*/
export const selectSelectedInternalAccount = createDeepEqualSelector(
selectAccountsControllerState,
(accountsControllerState: AccountsControllerState) => {
Expand All @@ -31,6 +58,9 @@ export const selectSelectedInternalAccount = createDeepEqualSelector(
},
);

/**
* A memoized selector that returns the selected internal account address in checksum format
*/
export const selectSelectedInternalAccountChecksummedAddress = createSelector(
selectSelectedInternalAccount,
(account) => {
Expand Down
43 changes: 43 additions & 0 deletions app/selectors/keyringController/index.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import { selectKeyrings, selectFlattenedKeyringAccounts } from './index';
import { RootState } from '../../reducers';
import {
MOCK_SIMPLE_ACCOUNTS,
MOCK_QR_ACCOUNTS,
MOCK_HD_ACCOUNTS,
MOCK_KEYRINGS,
MOCK_KEYRING_CONTROLLER,
} from './testUtils';

describe('KeyringController Selectors', () => {
describe('selectKeyrings', () => {
it('returns keyrings', () => {
expect(
selectKeyrings({
engine: {
backgroundState: {
KeyringController: MOCK_KEYRING_CONTROLLER,
},
},
} as RootState),
).toEqual(MOCK_KEYRINGS);
});
});
describe('selectFlattenedKeyringAccounts', () => {
it('returns flattened keyring accounts', () => {
const expectedOrderedKeyringAccounts = [
...MOCK_SIMPLE_ACCOUNTS,
...MOCK_QR_ACCOUNTS,
...MOCK_HD_ACCOUNTS,
];
expect(
selectFlattenedKeyringAccounts({
engine: {
backgroundState: {
KeyringController: MOCK_KEYRING_CONTROLLER,
},
},
} as RootState),
).toEqual(expectedOrderedKeyringAccounts);
});
});
});
31 changes: 31 additions & 0 deletions app/selectors/keyringController/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import { RootState } from '../../reducers';
import { createDeepEqualSelector } from '../util';

/**
*
* @param state - Root Redux state
* @returns - KeyringController state
*/
const selectKeyringControllerState = (state: RootState) =>
state.engine.backgroundState.KeyringController;

/**
* A memoized selector that retrieves keyrings from the KeyringController
*/
export const selectKeyrings = createDeepEqualSelector(
selectKeyringControllerState,
(keyringControllerState) => keyringControllerState.keyrings,
);

/**
* A memoized selector that returns the list of accounts from all keyrings in the form of a flattened array of strings.
*/
export const selectFlattenedKeyringAccounts = createDeepEqualSelector(
selectKeyrings,
(keyrings) => {
const flattenedKeyringAccounts = keyrings.flatMap(
(keyring) => keyring.accounts,
);
return flattenedKeyringAccounts;
},
);
18 changes: 18 additions & 0 deletions app/selectors/keyringController/testUtils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import {
KeyringControllerState,
KeyringObject,
KeyringTypes,
} from '@metamask/keyring-controller';

export const MOCK_SIMPLE_ACCOUNTS = ['0x1', '0x2'];
export const MOCK_QR_ACCOUNTS = ['0x3', '0x4'];
export const MOCK_HD_ACCOUNTS = ['0x5', '0x6'];
export const MOCK_KEYRINGS: KeyringObject[] = [
{ accounts: MOCK_SIMPLE_ACCOUNTS, type: KeyringTypes.simple },
{ accounts: MOCK_QR_ACCOUNTS, type: KeyringTypes.qr },
{ accounts: MOCK_HD_ACCOUNTS, type: KeyringTypes.hd },
];
export const MOCK_KEYRING_CONTROLLER: KeyringControllerState = {
isUnlocked: true,
keyrings: MOCK_KEYRINGS,
};
Loading

0 comments on commit 9bd819b

Please sign in to comment.