1
0
mirror of https://github.com/kremalicious/metamask-extension.git synced 2024-10-23 03:36:18 +02:00
metamask-extension/app/scripts/controllers/preferences.test.js

741 lines
24 KiB
JavaScript
Raw Normal View History

import { strict as assert } from 'assert';
import sinon from 'sinon';
2021-02-26 16:40:25 +01:00
import {
MAINNET_CHAIN_ID,
RINKEBY_CHAIN_ID,
} from '../../../shared/constants/network';
import PreferencesController from './preferences';
describe('preferences controller', function () {
let preferencesController;
let network;
2021-02-26 16:40:25 +01:00
let currentChainId;
let triggerNetworkChange;
let switchToMainnet;
let switchToRinkeby;
const migrateAddressBookState = sinon.stub();
beforeEach(function () {
2021-02-26 16:40:25 +01:00
currentChainId = MAINNET_CHAIN_ID;
network = {
getCurrentChainId: () => currentChainId,
on: sinon.spy(),
};
2020-11-03 00:41:28 +01:00
preferencesController = new PreferencesController({
migrateAddressBookState,
network,
});
2021-02-26 16:40:25 +01:00
triggerNetworkChange = network.on.firstCall.args[1];
switchToMainnet = () => {
currentChainId = MAINNET_CHAIN_ID;
triggerNetworkChange();
};
switchToRinkeby = () => {
currentChainId = RINKEBY_CHAIN_ID;
triggerNetworkChange();
};
});
Update address book state upon custom RPC chainId edit (#9493) When the `chainId` for a custom RPC endpoint is edited, we now migrate the corresponding address book entries to ensure they are not orphaned. The address book entries are grouped by the `metamask.network` state, which unfortunately was sometimes the `chainId`, and sometimes the `networkId`. It was always the `networkId` for built-in Infura networks, but for custom RPC endpoints it would be set to the user-set `chainId` field, with a fallback to the `networkId` of the network. A recent change will force users to enter valid `chainId`s on all custom networks, which will be normalized to be hex-prefixed. As a result, address book contacts will now be keyed by a different string. The contact entries are now migrated when this edit takes place. There are some edge cases where two separate entries share the same set of contacts. For example, if two entries have the same `chainId`, or if they had the same `networkId` and had no `chainId` set. When the `chainId` is edited in such cases, the contacts are duplicated on both networks. This is the best we can do, as we don't have any way to know which network the contacts _should_ be on. The `typed-message-manager` unit tests have also been updated as part of this commit because the addition of `sinon.restore()` to the preferences controller tests ended up clearing a test object in-between individual tests in that file. The test object is now re-constructed before each individual test.
2020-10-07 19:32:17 +02:00
afterEach(function () {
sinon.restore();
});
describe('setAddresses', function () {
it('should keep a map of addresses to names and addresses in the store', function () {
preferencesController.setAddresses(['0xda22le', '0x7e57e2']);
const { identities } = preferencesController.store.getState();
assert.deepEqual(identities, {
'0xda22le': {
name: 'Account 1',
address: '0xda22le',
},
'0x7e57e2': {
name: 'Account 2',
address: '0x7e57e2',
},
});
});
2018-07-31 01:09:17 +02:00
it('should create account tokens for each account in the store', function () {
preferencesController.setAddresses(['0xda22le', '0x7e57e2']);
2018-07-31 01:09:17 +02:00
const { accountTokens } = preferencesController.store.getState();
2018-07-31 01:09:17 +02:00
assert.deepEqual(accountTokens, {
'0xda22le': {},
'0x7e57e2': {},
});
});
2018-07-31 01:09:17 +02:00
it('should replace its list of addresses', function () {
preferencesController.setAddresses(['0xda22le', '0x7e57e2']);
preferencesController.setAddresses(['0xda22le77', '0x7e57e277']);
const { identities } = preferencesController.store.getState();
assert.deepEqual(identities, {
'0xda22le77': {
name: 'Account 1',
address: '0xda22le77',
},
'0x7e57e277': {
name: 'Account 2',
address: '0x7e57e277',
},
});
});
});
2018-07-16 22:08:19 +02:00
describe('removeAddress', function () {
it('should remove an address from state', function () {
preferencesController.setAddresses(['0xda22le', '0x7e57e2']);
2018-07-16 22:08:19 +02:00
preferencesController.removeAddress('0xda22le');
2018-07-16 22:08:19 +02:00
2020-11-03 00:41:28 +01:00
assert.equal(
preferencesController.store.getState().identities['0xda22le'],
undefined,
);
});
2018-07-16 22:08:19 +02:00
2018-07-31 01:09:17 +02:00
it('should remove an address from state and respective tokens', function () {
preferencesController.setAddresses(['0xda22le', '0x7e57e2']);
2018-07-31 01:09:17 +02:00
preferencesController.removeAddress('0xda22le');
2018-07-31 01:09:17 +02:00
2020-11-03 00:41:28 +01:00
assert.equal(
preferencesController.store.getState().accountTokens['0xda22le'],
undefined,
);
});
2018-07-31 01:09:17 +02:00
2018-07-16 22:08:19 +02:00
it('should switch accounts if the selected address is removed', function () {
preferencesController.setAddresses(['0xda22le', '0x7e57e2']);
2018-07-16 22:08:19 +02:00
preferencesController.setSelectedAddress('0x7e57e2');
preferencesController.removeAddress('0x7e57e2');
2018-07-16 22:08:19 +02:00
assert.equal(preferencesController.getSelectedAddress(), '0xda22le');
});
});
2018-07-16 22:08:19 +02:00
describe('setAccountLabel', function () {
it('should update a label for the given account', function () {
preferencesController.setAddresses(['0xda22le', '0x7e57e2']);
2020-11-03 00:41:28 +01:00
assert.deepEqual(
preferencesController.store.getState().identities['0xda22le'],
{
name: 'Account 1',
address: '0xda22le',
},
);
preferencesController.setAccountLabel('0xda22le', 'Dazzle');
2020-11-03 00:41:28 +01:00
assert.deepEqual(
preferencesController.store.getState().identities['0xda22le'],
{
name: 'Dazzle',
address: '0xda22le',
},
);
});
});
describe('getTokens', function () {
it('should return an empty list initially', async function () {
preferencesController.setAddresses(['0x7e57e2']);
await preferencesController.setSelectedAddress('0x7e57e2');
const tokens = preferencesController.getTokens();
assert.equal(tokens.length, 0, 'empty list of tokens');
});
});
describe('addToken', function () {
it('should add that token to its state', async function () {
const address = '0xabcdef1234567';
const symbol = 'ABBR';
const decimals = 5;
preferencesController.setAddresses(['0x7e57e2']);
await preferencesController.setSelectedAddress('0x7e57e2');
await preferencesController.addToken(address, symbol, decimals);
const tokens = preferencesController.getTokens();
assert.equal(tokens.length, 1, 'one token added');
const added = tokens[0];
assert.equal(added.address, address, 'set address correctly');
assert.equal(added.symbol, symbol, 'set symbol correctly');
assert.equal(added.decimals, decimals, 'set decimals correctly');
});
it('should allow updating a token value', async function () {
const address = '0xabcdef1234567';
const symbol = 'ABBR';
const decimals = 5;
preferencesController.setAddresses(['0x7e57e2']);
await preferencesController.setSelectedAddress('0x7e57e2');
await preferencesController.addToken(address, symbol, decimals);
const newDecimals = 6;
await preferencesController.addToken(address, symbol, newDecimals);
const tokens = preferencesController.getTokens();
assert.equal(tokens.length, 1, 'one token added');
const added = tokens[0];
assert.equal(added.address, address, 'set address correctly');
assert.equal(added.symbol, symbol, 'set symbol correctly');
assert.equal(added.decimals, newDecimals, 'updated decimals correctly');
});
it('should allow adding tokens to two separate addresses', async function () {
const address = '0xabcdef1234567';
const symbol = 'ABBR';
const decimals = 5;
preferencesController.setAddresses(['0x7e57e2', '0xda22le']);
await preferencesController.setSelectedAddress('0x7e57e2');
await preferencesController.addToken(address, symbol, decimals);
2020-11-03 00:41:28 +01:00
assert.equal(
preferencesController.getTokens().length,
1,
'one token added for 1st address',
);
await preferencesController.setSelectedAddress('0xda22le');
await preferencesController.addToken(address, symbol, decimals);
2020-11-03 00:41:28 +01:00
assert.equal(
preferencesController.getTokens().length,
1,
'one token added for 2nd address',
);
});
it('should add token per account', async function () {
const addressFirst = '0xabcdef1234567';
const addressSecond = '0xabcdef1234568';
const symbolFirst = 'ABBR';
const symbolSecond = 'ABBB';
const decimals = 5;
preferencesController.setAddresses(['0x7e57e2', '0xda22le']);
await preferencesController.setSelectedAddress('0x7e57e2');
await preferencesController.addToken(addressFirst, symbolFirst, decimals);
const tokensFirstAddress = preferencesController.getTokens();
await preferencesController.setSelectedAddress('0xda22le');
2020-11-03 00:41:28 +01:00
await preferencesController.addToken(
addressSecond,
symbolSecond,
decimals,
);
const tokensSeconAddress = preferencesController.getTokens();
2020-11-03 00:41:28 +01:00
assert.notEqual(
tokensFirstAddress,
tokensSeconAddress,
'add different tokens for two account and tokens are equal',
);
});
it('should add token per network', async function () {
const addressFirst = '0xabcdef1234567';
const addressSecond = '0xabcdef1234568';
const symbolFirst = 'ABBR';
const symbolSecond = 'ABBB';
const decimals = 5;
await preferencesController.addToken(addressFirst, symbolFirst, decimals);
const tokensFirstAddress = preferencesController.getTokens();
2021-02-26 16:40:25 +01:00
switchToRinkeby();
2020-11-03 00:41:28 +01:00
await preferencesController.addToken(
addressSecond,
symbolSecond,
decimals,
);
const tokensSeconAddress = preferencesController.getTokens();
2020-11-03 00:41:28 +01:00
assert.notEqual(
tokensFirstAddress,
tokensSeconAddress,
'add different tokens for two networks and tokens are equal',
);
});
});
describe('removeToken', function () {
it('should remove the only token from its state', async function () {
preferencesController.setAddresses(['0x7e57e2']);
await preferencesController.setSelectedAddress('0x7e57e2');
await preferencesController.addToken('0xa', 'A', 5);
await preferencesController.removeToken('0xa');
const tokens = preferencesController.getTokens();
assert.equal(tokens.length, 0, 'one token removed');
});
it('should remove a token from its state', async function () {
preferencesController.setAddresses(['0x7e57e2']);
await preferencesController.setSelectedAddress('0x7e57e2');
await preferencesController.addToken('0xa', 'A', 4);
await preferencesController.addToken('0xb', 'B', 5);
await preferencesController.removeToken('0xa');
const tokens = preferencesController.getTokens();
assert.equal(tokens.length, 1, 'one token removed');
const [token1] = tokens;
assert.deepEqual(token1, { address: '0xb', symbol: 'B', decimals: 5 });
});
it('should remove a token from its state on corresponding address', async function () {
preferencesController.setAddresses(['0x7e57e2', '0x7e57e3']);
await preferencesController.setSelectedAddress('0x7e57e2');
await preferencesController.addToken('0xa', 'A', 4);
await preferencesController.addToken('0xb', 'B', 5);
await preferencesController.setSelectedAddress('0x7e57e3');
await preferencesController.addToken('0xa', 'A', 4);
await preferencesController.addToken('0xb', 'B', 5);
const initialTokensSecond = preferencesController.getTokens();
await preferencesController.setSelectedAddress('0x7e57e2');
await preferencesController.removeToken('0xa');
const tokensFirst = preferencesController.getTokens();
assert.equal(tokensFirst.length, 1, 'one token removed in account');
const [token1] = tokensFirst;
assert.deepEqual(token1, { address: '0xb', symbol: 'B', decimals: 5 });
await preferencesController.setSelectedAddress('0x7e57e3');
const tokensSecond = preferencesController.getTokens();
2020-11-03 00:41:28 +01:00
assert.deepEqual(
tokensSecond,
initialTokensSecond,
'token deleted for account',
);
});
it('should remove a token from its state on corresponding network', async function () {
await preferencesController.addToken('0xa', 'A', 4);
await preferencesController.addToken('0xb', 'B', 5);
2021-02-26 16:40:25 +01:00
switchToRinkeby();
await preferencesController.addToken('0xa', 'A', 4);
await preferencesController.addToken('0xb', 'B', 5);
const initialTokensSecond = preferencesController.getTokens();
2021-02-26 16:40:25 +01:00
switchToMainnet();
await preferencesController.removeToken('0xa');
const tokensFirst = preferencesController.getTokens();
assert.equal(tokensFirst.length, 1, 'one token removed in network');
const [token1] = tokensFirst;
assert.deepEqual(token1, { address: '0xb', symbol: 'B', decimals: 5 });
2021-02-26 16:40:25 +01:00
switchToRinkeby();
const tokensSecond = preferencesController.getTokens();
2020-11-03 00:41:28 +01:00
assert.deepEqual(
tokensSecond,
initialTokensSecond,
'token deleted for network',
);
});
});
describe('on setSelectedAddress', function () {
it('should update tokens from its state on corresponding address', async function () {
preferencesController.setAddresses(['0x7e57e2', '0x7e57e3']);
await preferencesController.setSelectedAddress('0x7e57e2');
await preferencesController.addToken('0xa', 'A', 4);
await preferencesController.addToken('0xb', 'B', 5);
await preferencesController.setSelectedAddress('0x7e57e3');
await preferencesController.addToken('0xa', 'C', 4);
await preferencesController.addToken('0xb', 'D', 5);
await preferencesController.setSelectedAddress('0x7e57e2');
const initialTokensFirst = preferencesController.getTokens();
await preferencesController.setSelectedAddress('0x7e57e3');
const initialTokensSecond = preferencesController.getTokens();
2020-11-03 00:41:28 +01:00
assert.notDeepEqual(
initialTokensFirst,
initialTokensSecond,
'tokens not equal for different accounts and tokens',
);
await preferencesController.setSelectedAddress('0x7e57e2');
const tokensFirst = preferencesController.getTokens();
await preferencesController.setSelectedAddress('0x7e57e3');
const tokensSecond = preferencesController.getTokens();
2020-11-03 00:41:28 +01:00
assert.deepEqual(
tokensFirst,
initialTokensFirst,
'tokens equal for same account',
);
2020-11-03 00:41:28 +01:00
assert.deepEqual(
tokensSecond,
initialTokensSecond,
'tokens equal for same account',
);
});
});
describe('on updateStateNetworkType', function () {
it('should remove a token from its state on corresponding network', async function () {
await preferencesController.addToken('0xa', 'A', 4);
await preferencesController.addToken('0xb', 'B', 5);
const initialTokensFirst = preferencesController.getTokens();
2021-02-26 16:40:25 +01:00
switchToRinkeby();
await preferencesController.addToken('0xa', 'C', 4);
await preferencesController.addToken('0xb', 'D', 5);
const initialTokensSecond = preferencesController.getTokens();
2020-11-03 00:41:28 +01:00
assert.notDeepEqual(
initialTokensFirst,
initialTokensSecond,
'tokens not equal for different networks and tokens',
);
2021-02-26 16:40:25 +01:00
switchToMainnet();
const tokensFirst = preferencesController.getTokens();
2021-02-26 16:40:25 +01:00
switchToRinkeby();
const tokensSecond = preferencesController.getTokens();
2020-11-03 00:41:28 +01:00
assert.deepEqual(
tokensFirst,
initialTokensFirst,
'tokens equal for same network',
);
2020-11-03 00:41:28 +01:00
assert.deepEqual(
tokensSecond,
initialTokensSecond,
'tokens equal for same network',
);
});
});
2018-08-22 00:17:57 +02:00
describe('on watchAsset', function () {
let req, stubHandleWatchAssetERC20;
const sandbox = sinon.createSandbox();
2018-08-22 00:17:57 +02:00
beforeEach(function () {
req = { method: 'wallet_watchAsset', params: {} };
2020-11-03 00:41:28 +01:00
stubHandleWatchAssetERC20 = sandbox.stub(
preferencesController,
'_handleWatchAssetERC20',
);
});
after(function () {
sandbox.restore();
});
2018-08-22 00:17:57 +02:00
it('should error if passed no type', async function () {
await assert.rejects(
() => preferencesController.requestWatchAsset(req),
{ message: 'Asset of type "undefined" not supported.' },
'should have errored',
);
});
it('should error if method is not supported', async function () {
req.params.type = 'someasset';
await assert.rejects(
() => preferencesController.requestWatchAsset(req),
{ message: 'Asset of type "someasset" not supported.' },
'should have errored',
);
});
it('should handle ERC20 type', async function () {
req.params.type = 'ERC20';
await preferencesController.requestWatchAsset(req);
sandbox.assert.called(stubHandleWatchAssetERC20);
});
});
2018-08-22 00:17:57 +02:00
describe('on watchAsset of type ERC20', function () {
let req;
2018-08-22 00:17:57 +02:00
const sandbox = sinon.createSandbox();
beforeEach(function () {
req = { params: { type: 'ERC20' } };
});
after(function () {
sandbox.restore();
});
2018-08-22 00:17:57 +02:00
it('should add suggested token', async function () {
const address = '0xabcdef1234567';
const symbol = 'ABBR';
const decimals = 5;
const image = 'someimage';
req.params.options = { address, symbol, decimals, image };
2018-08-22 00:17:57 +02:00
2020-11-03 00:41:28 +01:00
sandbox
.stub(preferencesController, '_validateERC20AssetParams')
.returns(true);
preferencesController.openPopup = async () => undefined;
2018-08-22 00:17:57 +02:00
await preferencesController._handleWatchAssetERC20(req.params.options);
const suggested = preferencesController.getSuggestedTokens();
2020-11-03 00:41:28 +01:00
assert.equal(
Object.keys(suggested).length,
1,
`one token added ${Object.keys(suggested)}`,
);
2018-08-22 00:17:57 +02:00
assert.equal(
suggested[address].address,
address,
'set address correctly',
);
assert.equal(suggested[address].symbol, symbol, 'set symbol correctly');
2020-11-03 00:41:28 +01:00
assert.equal(
suggested[address].decimals,
decimals,
'set decimals correctly',
);
assert.equal(suggested[address].image, image, 'set image correctly');
});
2018-08-22 00:17:57 +02:00
it('should add token correctly if user confirms', async function () {
const address = '0xabcdef1234567';
const symbol = 'ABBR';
const decimals = 5;
const image = 'someimage';
req.params.options = { address, symbol, decimals, image };
2018-08-22 00:17:57 +02:00
2020-11-03 00:41:28 +01:00
sandbox
.stub(preferencesController, '_validateERC20AssetParams')
.returns(true);
2018-09-27 20:19:09 +02:00
preferencesController.openPopup = async () => {
await preferencesController.addToken(address, symbol, decimals, image);
};
await preferencesController._handleWatchAssetERC20(req.params.options);
const tokens = preferencesController.getTokens();
assert.equal(tokens.length, 1, `one token added`);
const added = tokens[0];
assert.equal(added.address, address, 'set address correctly');
assert.equal(added.symbol, symbol, 'set symbol correctly');
assert.equal(added.decimals, decimals, 'set decimals correctly');
const assetImages = preferencesController.getAssetImages();
assert.ok(assetImages[address], `set image correctly`);
});
it('should validate ERC20 asset correctly', async function () {
const validate = preferencesController._validateERC20AssetParams;
2020-11-03 00:41:28 +01:00
assert.doesNotThrow(() =>
validate({
address: '0xd26114cd6EE289AccF82350c8d8487fedB8A0C07',
2020-11-03 00:41:28 +01:00
symbol: 'ABC',
decimals: 0,
}),
);
assert.doesNotThrow(() =>
validate({
address: '0xd26114cd6EE289AccF82350c8d8487fedB8A0C07',
symbol: 'ABCDEFGHIJK',
decimals: 0,
}),
);
2020-11-03 00:41:28 +01:00
assert.throws(
() => validate({ symbol: 'ABC', decimals: 0 }),
'missing address should fail',
);
2020-11-03 00:41:28 +01:00
assert.throws(
() =>
validate({
address: '0xd26114cd6EE289AccF82350c8d8487fedB8A0C07',
2020-11-03 00:41:28 +01:00
decimals: 0,
}),
'missing symbol should fail',
);
2020-11-03 00:41:28 +01:00
assert.throws(
() =>
validate({
address: '0xd26114cd6EE289AccF82350c8d8487fedB8A0C07',
2020-11-03 00:41:28 +01:00
symbol: 'ABC',
}),
'missing decimals should fail',
);
2020-11-03 00:41:28 +01:00
assert.throws(
() =>
validate({
address: '0xd26114cd6EE289AccF82350c8d8487fedB8A0C07',
symbol: 'ABCDEFGHIJKLM',
decimals: 0,
}),
'long symbol should fail',
);
assert.throws(
() =>
validate({
address: '0xd26114cd6EE289AccF82350c8d8487fedB8A0C07',
symbol: '',
2020-11-03 00:41:28 +01:00
decimals: 0,
}),
'empty symbol should fail',
);
2020-11-03 00:41:28 +01:00
assert.throws(
() =>
validate({
address: '0xd26114cd6EE289AccF82350c8d8487fedB8A0C07',
2020-11-03 00:41:28 +01:00
symbol: 'ABC',
decimals: -1,
}),
'decimals < 0 should fail',
);
2020-11-03 00:41:28 +01:00
assert.throws(
() =>
validate({
address: '0xd26114cd6EE289AccF82350c8d8487fedB8A0C07',
2020-11-03 00:41:28 +01:00
symbol: 'ABC',
decimals: 38,
}),
'decimals > 36 should fail',
);
2020-11-03 00:41:28 +01:00
assert.throws(
() => validate({ address: '0x123', symbol: 'ABC', decimals: 0 }),
2020-11-03 00:41:28 +01:00
'invalid address should fail',
);
});
});
describe('setPasswordForgotten', function () {
it('should default to false', function () {
const state = preferencesController.store.getState();
assert.equal(state.forgottenPassword, false);
});
it('should set the forgottenPassword property in state', function () {
2020-11-03 00:41:28 +01:00
assert.equal(
preferencesController.store.getState().forgottenPassword,
false,
);
preferencesController.setPasswordForgotten(true);
2020-11-03 00:41:28 +01:00
assert.equal(
preferencesController.store.getState().forgottenPassword,
true,
);
});
});
describe('#updateRpc', function () {
Update address book state upon custom RPC chainId edit (#9493) When the `chainId` for a custom RPC endpoint is edited, we now migrate the corresponding address book entries to ensure they are not orphaned. The address book entries are grouped by the `metamask.network` state, which unfortunately was sometimes the `chainId`, and sometimes the `networkId`. It was always the `networkId` for built-in Infura networks, but for custom RPC endpoints it would be set to the user-set `chainId` field, with a fallback to the `networkId` of the network. A recent change will force users to enter valid `chainId`s on all custom networks, which will be normalized to be hex-prefixed. As a result, address book contacts will now be keyed by a different string. The contact entries are now migrated when this edit takes place. There are some edge cases where two separate entries share the same set of contacts. For example, if two entries have the same `chainId`, or if they had the same `networkId` and had no `chainId` set. When the `chainId` is edited in such cases, the contacts are duplicated on both networks. This is the best we can do, as we don't have any way to know which network the contacts _should_ be on. The `typed-message-manager` unit tests have also been updated as part of this commit because the addition of `sinon.restore()` to the preferences controller tests ended up clearing a test object in-between individual tests in that file. The test object is now re-constructed before each individual test.
2020-10-07 19:32:17 +02:00
it('should update the rpcDetails properly', async function () {
2020-11-03 00:41:28 +01:00
preferencesController.store.updateState({
frequentRpcListDetail: [{}, { rpcUrl: 'test', chainId: '0x1' }, {}],
});
await preferencesController.updateRpc({ rpcUrl: 'test', chainId: '0x1' });
2020-11-03 00:41:28 +01:00
await preferencesController.updateRpc({
rpcUrl: 'test/1',
chainId: '0x1',
});
2020-11-03 00:41:28 +01:00
await preferencesController.updateRpc({
rpcUrl: 'test/2',
chainId: '0x1',
});
2020-11-03 00:41:28 +01:00
await preferencesController.updateRpc({
rpcUrl: 'test/3',
chainId: '0x1',
});
const list = preferencesController.getFrequentRpcListDetail();
assert.deepEqual(list[1], { rpcUrl: 'test', chainId: '0x1' });
});
Update address book state upon custom RPC chainId edit (#9493) When the `chainId` for a custom RPC endpoint is edited, we now migrate the corresponding address book entries to ensure they are not orphaned. The address book entries are grouped by the `metamask.network` state, which unfortunately was sometimes the `chainId`, and sometimes the `networkId`. It was always the `networkId` for built-in Infura networks, but for custom RPC endpoints it would be set to the user-set `chainId` field, with a fallback to the `networkId` of the network. A recent change will force users to enter valid `chainId`s on all custom networks, which will be normalized to be hex-prefixed. As a result, address book contacts will now be keyed by a different string. The contact entries are now migrated when this edit takes place. There are some edge cases where two separate entries share the same set of contacts. For example, if two entries have the same `chainId`, or if they had the same `networkId` and had no `chainId` set. When the `chainId` is edited in such cases, the contacts are duplicated on both networks. This is the best we can do, as we don't have any way to know which network the contacts _should_ be on. The `typed-message-manager` unit tests have also been updated as part of this commit because the addition of `sinon.restore()` to the preferences controller tests ended up clearing a test object in-between individual tests in that file. The test object is now re-constructed before each individual test.
2020-10-07 19:32:17 +02:00
it('should migrate address book entries if chainId changes', async function () {
2020-11-03 00:41:28 +01:00
preferencesController.store.updateState({
frequentRpcListDetail: [{}, { rpcUrl: 'test', chainId: '1' }, {}],
});
await preferencesController.updateRpc({ rpcUrl: 'test', chainId: '0x1' });
assert(migrateAddressBookState.calledWith('1', '0x1'));
});
});
describe('adding and removing from frequentRpcListDetail', function () {
it('should add custom RPC url to state', function () {
preferencesController.addToFrequentRpcList('rpc_url', '0x1');
assert.deepEqual(
preferencesController.store.getState().frequentRpcListDetail,
2020-11-03 00:41:28 +01:00
[
{
rpcUrl: 'rpc_url',
chainId: '0x1',
ticker: 'ETH',
nickname: '',
rpcPrefs: {},
},
],
);
preferencesController.addToFrequentRpcList('rpc_url', '0x1');
assert.deepEqual(
preferencesController.store.getState().frequentRpcListDetail,
2020-11-03 00:41:28 +01:00
[
{
rpcUrl: 'rpc_url',
chainId: '0x1',
ticker: 'ETH',
nickname: '',
rpcPrefs: {},
},
],
);
});
it('should throw if chainId is invalid', function () {
2020-11-03 00:41:28 +01:00
assert.throws(() => {
preferencesController.addToFrequentRpcList('rpc_url', '1');
}, 'should throw on invalid chainId');
});
it('should remove custom RPC url from state', function () {
preferencesController.addToFrequentRpcList('rpc_url', '0x1');
2020-11-03 00:41:28 +01:00
assert.deepEqual(
preferencesController.store.getState().frequentRpcListDetail,
[
{
rpcUrl: 'rpc_url',
chainId: '0x1',
ticker: 'ETH',
nickname: '',
rpcPrefs: {},
},
],
);
preferencesController.removeFromFrequentRpcList('other_rpc_url');
preferencesController.removeFromFrequentRpcList('http://localhost:8545');
preferencesController.removeFromFrequentRpcList('rpc_url');
2020-11-03 00:41:28 +01:00
assert.deepEqual(
preferencesController.store.getState().frequentRpcListDetail,
[],
);
});
});
describe('setUsePhishDetect', function () {
it('should default to true', function () {
const state = preferencesController.store.getState();
assert.equal(state.usePhishDetect, true);
});
it('should set the usePhishDetect property in state', function () {
assert.equal(preferencesController.store.getState().usePhishDetect, true);
preferencesController.setUsePhishDetect(false);
assert.equal(
preferencesController.store.getState().usePhishDetect,
false,
);
});
});
});