Skip to content

Commit

Permalink
copy changes from #8886
Browse files Browse the repository at this point in the history
  • Loading branch information
tommasini committed Mar 8, 2024
1 parent 047e3fe commit f37edd7
Show file tree
Hide file tree
Showing 7 changed files with 810 additions and 13 deletions.
91 changes: 87 additions & 4 deletions app/store/migrations/029.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,19 @@ const oldState = {
},
],
},
TokensController: {
allTokens: { '1': { '0x123': { address: '0x123' } } },
allIgnoredTokens: { '1': { '0x123': { address: '0x123' } } },
allDetectedTokens: { '1': { '0x123': { address: '0x123' } } },
},
TokenRatesController: {
contractExchangeRatesByChainId: { '1': { ETH: { '0x123': 0.0001 } } },
},
TokenListController: {
tokensChainsCache: {
'1': { timeStamp: 1, data: { '0x123': { address: '0x123' } } },
},
},
},
},
networkOnboarded: {
Expand Down Expand Up @@ -160,6 +173,19 @@ const expectedNewState = {
},
],
},
TokensController: {
allTokens: { '0x1': { '0x123': { address: '0x123' } } },
allIgnoredTokens: { '0x1': { '0x123': { address: '0x123' } } },
allDetectedTokens: { '0x1': { '0x123': { address: '0x123' } } },
},
TokenRatesController: {
contractExchangeRatesByChainId: { '0x1': { ETH: { '0x123': 0.0001 } } },
},
TokenListController: {
tokensChainsCache: {
'0x1': { timeStamp: 1, data: { '0x123': { address: '0x123' } } },
},
},
},
},
networkOnboarded: {
Expand Down Expand Up @@ -360,11 +386,68 @@ describe('Migration #29', () => {
errorMessage: "Migration 29: Invalid TransactionController state: 'null'",
scenario: 'TransactionController state is invalid',
},
{
state: merge({}, initialRootState, {
engine: {
backgroundState: {
...initialBackgroundState,
NetworkController: {
...initialBackgroundState.NetworkController,
networkDetails: {
isEIP1559Compatible: true,
},
networkConfigurations: {},
},
TokensController: null,
},
},
}),
errorMessage: "Migration 29: Invalid TokensController state: 'null'",
scenario: 'TokensController state is invalid',
},
{
state: merge({}, initialRootState, {
engine: {
backgroundState: {
...initialBackgroundState,
NetworkController: {
...initialBackgroundState.NetworkController,
networkDetails: {
isEIP1559Compatible: true,
},
networkConfigurations: {},
},
TokenRatesController: null,
},
},
}),
errorMessage: "Migration 29: Invalid TokenRatesController state: 'null'",
scenario: 'TokenRatesController state is invalid',
},
{
state: merge({}, initialRootState, {
engine: {
backgroundState: {
...initialBackgroundState,
NetworkController: {
...initialBackgroundState.NetworkController,
networkDetails: {
isEIP1559Compatible: true,
},
networkConfigurations: {},
},
TokenListController: null,
},
},
}),
errorMessage: "Migration 29: Invalid TokenListController state: 'null'",
scenario: 'TokenListController state is invalid',
},
];

for (const { errorMessage, scenario, state } of invalidStates) {
it(`should capture exception if ${scenario}`, () => {
const newState = migration(state);
it(`should capture exception if ${scenario}`, async () => {
const newState = await migration(state);

expect(newState).toStrictEqual(state);
expect(mockedCaptureException).toHaveBeenCalledWith(expect.any(Error));
Expand All @@ -374,8 +457,8 @@ describe('Migration #29', () => {
});
}

it('All states changing as expected', () => {
const newState = migration(oldState);
it('All states changing as expected', async () => {
const newState = await migration(oldState);

expect(newState).toStrictEqual(expectedNewState);
});
Expand Down
204 changes: 202 additions & 2 deletions app/store/migrations/029.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,14 @@ import {
AddressBookEntry,
AddressBookState,
} from '@metamask/address-book-controller';
import { Nft, NftContract, NftState } from '@metamask/assets-controllers';
import {
Nft,
NftContract,
NftState,
TokenListState,
TokenRatesState,
TokensState,
} from '@metamask/assets-controllers';

/**
* Converting chain id on decimal format to hexadecimal format
Expand All @@ -28,7 +35,8 @@ import { Nft, NftContract, NftState } from '@metamask/assets-controllers';
* @param {any} state - Redux state.
* @returns Migrated Redux state.
*/
export default function migrate(state: unknown) {
export default async function migrate(stateAsync: unknown) {
const state = await stateAsync;
// Chaning chain id to hexadecimal chain Id on the networks already on the local state
if (!isObject(state)) {
captureException(
Expand Down Expand Up @@ -484,5 +492,197 @@ export default function migrate(state: unknown) {
);
}

const tokenListControllerState =
state?.engine?.backgroundState?.TokenListController;
const newTokenListControllerState = state?.engine?.backgroundState
?.TokenListController as TokenListState;

if (!isObject(tokenListControllerState)) {
captureException(
new Error(
`Migration 29: Invalid TokenListController state: '${JSON.stringify(
tokenListControllerState,
)}'`,
),
);
return state;
}

if (
!hasProperty(tokenListControllerState, 'tokensChainsCache') ||
!isObject(tokenListControllerState.tokensChainsCache)
) {
captureException(
new Error(
`Migration 29: Invalid tokenListControllerState tokensChainsCache: '${JSON.stringify(
tokenListControllerState.tokensChainsCache,
)}'`,
),
);
return state;
}

if (Object.keys(tokenListControllerState.tokensChainsCache).length) {
Object.keys(tokenListControllerState.tokensChainsCache).forEach(
(chainId) => {
if (!isHexString(chainId)) {
const hexChainId = toHex(chainId);
newTokenListControllerState.tokensChainsCache[hexChainId] =
//@ts-expect-error Is verified on Line 508 that tokenChainsCache is a property
tokenListControllerState.tokensChainsCache[chainId];

if (isObject(tokenListControllerState.tokensChainsCache)) {
delete tokenListControllerState.tokensChainsCache[chainId];
}
}
},
);
}

const tokenRatesControllerState =
state?.engine?.backgroundState?.TokenRatesController;
const newTokenRatesControllerState = state?.engine?.backgroundState
?.TokenRatesController as TokenRatesState;

if (!isObject(tokenRatesControllerState)) {
captureException(
new Error(
`Migration 29: Invalid TokenRatesController state: '${JSON.stringify(
tokenRatesControllerState,
)}'`,
),
);
return state;
}

if (
isObject(tokenRatesControllerState.contractExchangeRatesByChainId) &&
Object.keys(tokenRatesControllerState.contractExchangeRatesByChainId).length
) {
Object.keys(
tokenRatesControllerState.contractExchangeRatesByChainId,
).forEach((chainId) => {
if (!isHexString(chainId)) {
const hexChainId = toHex(chainId);
newTokenRatesControllerState.contractExchangeRatesByChainId[
hexChainId
] =
//@ts-expect-error Is verified on Line 558 that contractExchangeRatesByChainId is a property
tokenRatesControllerState.contractExchangeRatesByChainId[chainId];

if (
isObject(tokenRatesControllerState.contractExchangeRatesByChainId)
) {
delete tokenRatesControllerState.contractExchangeRatesByChainId[
chainId
];
}
}
});
}

const tokensControllerState =
state?.engine?.backgroundState?.TokensController;
const newTokensControllerState = state?.engine?.backgroundState
?.TokensController as TokensState;

if (!isObject(tokensControllerState)) {
captureException(
new Error(
`Migration 29: Invalid TokensController state: '${JSON.stringify(
tokensControllerState,
)}'`,
),
);
return state;
}

if (
!hasProperty(tokensControllerState, 'allTokens') ||
!isObject(tokensControllerState.allTokens)
) {
captureException(
new Error(
`Migration 29: Invalid TokensController allTokens: '${JSON.stringify(
tokensControllerState.allTokens,
)}'`,
),
);
return state;
}

if (Object.keys(tokensControllerState.allTokens).length) {
Object.keys(tokensControllerState.allTokens).forEach((chainId) => {
if (!isHexString(chainId)) {
const hexChainId = toHex(chainId);
newTokensControllerState.allTokens[hexChainId] =
//@ts-expect-error Is verified on Line 613 that allTokens is a property
tokensControllerState.allTokens[chainId];

if (isObject(tokensControllerState.allTokens)) {
delete tokensControllerState.allTokens[chainId];
}
}
});
}

if (
!hasProperty(tokensControllerState, 'allIgnoredTokens') ||
!isObject(tokensControllerState.allIgnoredTokens)
) {
captureException(
new Error(
`Migration 29: Invalid TokensController allIgnoredTokens: '${JSON.stringify(
tokensControllerState.allIgnoredTokens,
)}'`,
),
);
return state;
}

if (Object.keys(tokensControllerState.allIgnoredTokens).length) {
Object.keys(tokensControllerState.allIgnoredTokens).forEach((chainId) => {
if (!isHexString(chainId)) {
const hexChainId = toHex(chainId);
newTokensControllerState.allIgnoredTokens[hexChainId] =
//@ts-expect-error Is verified on Line 643 that allIgnoredTokens is a property
tokensControllerState.allIgnoredTokens[chainId];

if (isObject(tokensControllerState.allIgnoredTokens)) {
delete tokensControllerState.allIgnoredTokens[chainId];
}
}
});
}

if (
!hasProperty(tokensControllerState, 'allDetectedTokens') ||
!isObject(tokensControllerState.allDetectedTokens)
) {
captureException(
new Error(
`Migration 29: Invalid TokensController allDetectedTokens: '${JSON.stringify(
tokensControllerState.allDetectedTokens,
)}'`,
),
);
return state;
}

if (Object.keys(tokensControllerState.allDetectedTokens).length) {
Object.keys(tokensControllerState.allDetectedTokens).forEach((chainId) => {
if (!isHexString(chainId)) {
const hexChainId = toHex(chainId);
newTokensControllerState.allDetectedTokens[hexChainId] =
//@ts-expect-error Is verified on Line 671 that allIgnoredTokens is a property
tokensControllerState.allDetectedTokens[chainId];

if (isObject(tokensControllerState.allDetectedTokens)) {
delete tokensControllerState.allDetectedTokens[chainId];
}
}
});
}

return state;
}
12 changes: 6 additions & 6 deletions app/store/migrations/030.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,8 +50,8 @@ describe('Migration #30', () => {
];

for (const { errorMessage, scenario, state } of invalidStates) {
it(`should capture exception if ${scenario}`, () => {
const newState = migrate(state);
it(`should capture exception if ${scenario}`, async () => {
const newState = await migrate(state);

expect(newState).toStrictEqual(state);
expect(mockedCaptureException).toHaveBeenCalledWith(expect.any(Error));
Expand All @@ -61,7 +61,7 @@ describe('Migration #30', () => {
});
}

it('should not change anything if security alert is already enabled', () => {
it('should not change anything if security alert is already enabled', async () => {
const oldState = {
engine: {
backgroundState: {
Expand All @@ -72,11 +72,11 @@ describe('Migration #30', () => {
},
};

const migratedState = migrate(oldState);
const migratedState = await migrate(oldState);
expect(migratedState).toStrictEqual(expectedState);
});

it('should enable security alert if it is not enabled', () => {
it('should enable security alert if it is not enabled', async () => {
const oldState = {
engine: {
backgroundState: {
Expand All @@ -86,7 +86,7 @@ describe('Migration #30', () => {
},
},
};
const migratedState = migrate(oldState);
const migratedState = await migrate(oldState);
expect(migratedState).toStrictEqual(expectedState);
});
});
3 changes: 2 additions & 1 deletion app/store/migrations/030.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@ import { isObject } from '@metamask/utils';
* @param {any} state - Redux state.
* @returns Migrated Redux state.
*/
export default function migrate(state: unknown) {
export default async function migrate(stateAsync: unknown) {
const state = await stateAsync;
if (!isObject(state)) {
captureException(
new Error(`Migration 30: Invalid root state: '${typeof state}'`),
Expand Down
Loading

0 comments on commit f37edd7

Please sign in to comment.