Skip to content
Merged
Show file tree
Hide file tree
Changes from 11 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
58 changes: 26 additions & 32 deletions app/scripts/migrations/191.ts
Original file line number Diff line number Diff line change
@@ -1,44 +1,38 @@
import { hasProperty, isObject } from '@metamask/utils';

type VersionedData = {
meta: { version: number };
data: Record<string, unknown>;
};
import { hasProperty } from '@metamask/utils';
import type { Migrate } from './types';

export const version = 191;

/**
* This migration removes the `preventPollingOnNetworkRestart` property from
* TokenListController state.
* Migration that removes `null` seedWords and forgottenPassword values from the persisted state.
*
* If the `seedWords` property exists on the data object and its value is
* `null`, this migration deletes the property and records `seedWords` in
* the set of changed keys.
*
* Background:
* - The `preventPollingOnNetworkRestart` property was used to control polling behavior
* - This property has been removed from the TokenListController
* - This migration cleans up the obsolete property from persisted state
* If the `forgottenPassword` property exists on the data object and its value is
* `null`, this migration deletes the property and records `forgottenPassword` in
* the set of changed keys.
*
* @param versionedData - Versioned MetaMask extension state
* @param changedControllers - Set of controller names that were modified
* @param versionedData - The versioned data object to migrate.
* @param changedKeys - A set used to record keys that were modified.
*/
export async function migrate(
versionedData: VersionedData,
changedControllers: Set<string>,
): Promise<void> {
export const migrate = (async (versionedData, changedKeys) => {
versionedData.meta.version = version;

const state = versionedData.data;

if (!hasProperty(state, 'TokenListController')) {
return;
}

const tokenListControllerState = state.TokenListController;

if (!isObject(tokenListControllerState)) {
return;
if (
hasProperty(versionedData.data, 'seedWords') &&
versionedData.data.seedWords === null
) {
delete versionedData.data.seedWords;
changedKeys.add('seedWords');
}

if (hasProperty(tokenListControllerState, 'preventPollingOnNetworkRestart')) {
delete tokenListControllerState.preventPollingOnNetworkRestart;
changedControllers.add('TokenListController');
if (
hasProperty(versionedData.data, 'forgottenPassword') &&
versionedData.data.forgottenPassword === null
) {
delete versionedData.data.forgottenPassword;
changedKeys.add('forgottenPassword');
}
}
}) satisfies Migrate;
167 changes: 167 additions & 0 deletions app/scripts/migrations/194.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,167 @@
import { cloneDeep } from 'lodash';
import { migrate, version } from './191';

const VERSION = version;
const OLD_VERSION = VERSION - 1;

describe(`migration #${VERSION}`, () => {
it('removes seedWords when value is null', async () => {
const oldStorage = {
meta: { version: OLD_VERSION },
data: {
seedWords: null,
PreferencesController: {
showTestNetworks: true,
},
},
};

const versionedData = cloneDeep(oldStorage);
const changedKeys = new Set<string>();

await migrate(versionedData, changedKeys);

expect(versionedData.meta.version).toBe(VERSION);
expect('seedWords' in versionedData.data).toBe(false);
expect(versionedData.data).toStrictEqual({
PreferencesController: {
showTestNetworks: true,
},
});
expect(changedKeys).toStrictEqual(new Set(['seedWords']));
});

it('keeps seedWords when value is not null', async () => {
const oldStorage = {
meta: { version: OLD_VERSION },
data: {
seedWords: 'mock-seed-phrase',
},
};

const versionedData = cloneDeep(oldStorage);
const changedKeys = new Set<string>();

await migrate(versionedData, changedKeys);

expect(versionedData.meta.version).toBe(VERSION);
expect(versionedData.data).toStrictEqual(oldStorage.data);
expect(changedKeys.size).toBe(0);
});

it('handles state when seedWords property does not exist', async () => {
const oldStorage = {
meta: { version: OLD_VERSION },
data: {
PreferencesController: {
showTestNetworks: true,
},
},
};

const versionedData = cloneDeep(oldStorage);
const changedKeys = new Set<string>();

await migrate(versionedData, changedKeys);

expect(versionedData.meta.version).toBe(VERSION);
expect('seedWords' in versionedData.data).toBe(false);
expect(versionedData.data).toStrictEqual(oldStorage.data);
expect(changedKeys.size).toBe(0);
});

it('removes forgottenPassword when value is null', async () => {
const oldStorage = {
meta: { version: OLD_VERSION },
data: {
forgottenPassword: null,
PreferencesController: {
showTestNetworks: true,
},
},
};

const versionedData = cloneDeep(oldStorage);
const changedKeys = new Set<string>();

await migrate(versionedData, changedKeys);

expect(versionedData.meta.version).toBe(VERSION);
expect('forgottenPassword' in versionedData.data).toBe(false);
expect(versionedData.data).toStrictEqual({
PreferencesController: {
showTestNetworks: true,
},
});
expect(changedKeys).toStrictEqual(new Set(['forgottenPassword']));
});

it('keeps forgottenPassword when value is not null', async () => {
const oldStorage = {
meta: { version: OLD_VERSION },
data: {
forgottenPassword: true,
},
};

const versionedData = cloneDeep(oldStorage);
const changedKeys = new Set<string>();

await migrate(versionedData, changedKeys);

expect(versionedData.meta.version).toBe(VERSION);
expect(versionedData.data).toStrictEqual(oldStorage.data);
expect(changedKeys.size).toBe(0);
});

it('handles state when forgottenPassword property does not exist', async () => {
const oldStorage = {
meta: { version: OLD_VERSION },
data: {
PreferencesController: {
showTestNetworks: true,
},
},
};

const versionedData = cloneDeep(oldStorage);
const changedKeys = new Set<string>();

await migrate(versionedData, changedKeys);

expect(versionedData.meta.version).toBe(VERSION);
expect('forgottenPassword' in versionedData.data).toBe(false);
expect(versionedData.data).toStrictEqual(oldStorage.data);
expect(changedKeys.size).toBe(0);
});

it('removes both seedWords and forgottenPassword when both are null', async () => {
const oldStorage = {
meta: { version: OLD_VERSION },
data: {
seedWords: null,
forgottenPassword: null,
PreferencesController: {
showTestNetworks: true,
},
},
};

const versionedData = cloneDeep(oldStorage);
const changedKeys = new Set<string>();

await migrate(versionedData, changedKeys);

expect(versionedData.meta.version).toBe(VERSION);
expect('seedWords' in versionedData.data).toBe(false);
expect('forgottenPassword' in versionedData.data).toBe(false);
expect(versionedData.data).toStrictEqual({
PreferencesController: {
showTestNetworks: true,
},
});
expect(changedKeys).toStrictEqual(
new Set(['seedWords', 'forgottenPassword']),
);
});
});
38 changes: 38 additions & 0 deletions app/scripts/migrations/194.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import { hasProperty } from '@metamask/utils';
import type { Migrate } from './types';

export const version = 191;

/**
* Migration that removes `null` seedWords and forgottenPassword values from the persisted state.
*
* If the `seedWords` property exists on the data object and its value is
* `null`, this migration deletes the property and records `seedWords` in
* the set of changed keys.
*
* If the `forgottenPassword` property exists on the data object and its value is
* `null`, this migration deletes the property and records `forgottenPassword` in
* the set of changed keys.
*
* @param versionedData - The versioned data object to migrate.
* @param changedKeys - A set used to record keys that were modified.
*/
export const migrate = (async (versionedData, changedKeys) => {
versionedData.meta.version = version;

if (
hasProperty(versionedData.data, 'seedWords') &&
versionedData.data.seedWords === null
) {
delete versionedData.data.seedWords;
changedKeys.add('seedWords');
}

if (
hasProperty(versionedData.data, 'forgottenPassword') &&
versionedData.data.forgottenPassword === null
) {
delete versionedData.data.forgottenPassword;
changedKeys.add('forgottenPassword');
}
}) satisfies Migrate;
1 change: 1 addition & 0 deletions app/scripts/migrations/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -229,6 +229,7 @@ const migrations = [
require('./191'),
require('./192'),
require('./193'),
require('./194'),
];

export default migrations;
Loading
Loading