mirror of
https://github.com/kremalicious/metamask-extension.git
synced 2024-11-26 12:29:06 +01:00
2ccc1977bf
The PhishingController has been updated to v2. This release should dramatically reduce network traffic and double the update speed of the phishing list. This was accomplished by combining both of our phishing configurations into one list (the "stalelist"), then creating a separate list of the changes just the past few days (the "hotlist"). Now users will download a smaller list more frequently (every 30 minutes rather than every hour), whereas the full list is only updated every 4 days. The combined configuration means that we no longer know which list was responsible for each block. The phishing warning page has been updated to dynamically look this information up, to ensure users are still directed to the correct place to dispute a block. This update to the phishing warning page also includes the recent redesign.
408 lines
13 KiB
JavaScript
408 lines
13 KiB
JavaScript
import { strict as assert } from 'assert';
|
|
import sinon from 'sinon';
|
|
import proxyquire from 'proxyquire';
|
|
|
|
import { ApprovalRequestNotFoundError } from '@metamask/approval-controller';
|
|
import { PermissionsRequestNotFoundError } from '@metamask/permission-controller';
|
|
import nock from 'nock';
|
|
import { ORIGIN_METAMASK } from '../../shared/constants/app';
|
|
|
|
const Ganache = require('../../test/e2e/ganache');
|
|
|
|
const ganacheServer = new Ganache();
|
|
|
|
const browserPolyfillMock = {
|
|
runtime: {
|
|
id: 'fake-extension-id',
|
|
onInstalled: {
|
|
addListener: () => undefined,
|
|
},
|
|
onMessageExternal: {
|
|
addListener: () => undefined,
|
|
},
|
|
getPlatformInfo: async () => 'mac',
|
|
},
|
|
storage: {
|
|
local: {
|
|
get: sinon.stub().resolves({}),
|
|
set: sinon.stub().resolves(),
|
|
},
|
|
},
|
|
};
|
|
|
|
let loggerMiddlewareMock;
|
|
const createLoggerMiddlewareMock = () => (req, res, next) => {
|
|
if (loggerMiddlewareMock) {
|
|
loggerMiddlewareMock.requests.push(req);
|
|
next((cb) => {
|
|
loggerMiddlewareMock.responses.push(res);
|
|
cb();
|
|
});
|
|
return;
|
|
}
|
|
next();
|
|
};
|
|
|
|
const TEST_SEED =
|
|
'debris dizzy just program just float decrease vacant alarm reduce speak stadium';
|
|
|
|
const MetaMaskController = proxyquire('./metamask-controller', {
|
|
'./lib/createLoggerMiddleware': { default: createLoggerMiddlewareMock },
|
|
}).default;
|
|
|
|
describe('MetaMaskController', function () {
|
|
let metamaskController;
|
|
const sandbox = sinon.createSandbox();
|
|
const noop = () => undefined;
|
|
|
|
before(async function () {
|
|
await ganacheServer.start();
|
|
});
|
|
|
|
beforeEach(function () {
|
|
nock('https://static.metafi.codefi.network')
|
|
.persist()
|
|
.get('/api/v1/lists/stalelist.json')
|
|
.reply(
|
|
200,
|
|
JSON.stringify({
|
|
version: 2,
|
|
tolerance: 2,
|
|
fuzzylist: [],
|
|
allowlist: [],
|
|
blocklist: ['127.0.0.1'],
|
|
lastUpdated: 0,
|
|
}),
|
|
)
|
|
.get('/api/v1/lists/hotlist.json')
|
|
.reply(
|
|
200,
|
|
JSON.stringify([
|
|
{ url: '127.0.0.1', targetList: 'blocklist', timestamp: 0 },
|
|
]),
|
|
);
|
|
metamaskController = new MetaMaskController({
|
|
showUserConfirmation: noop,
|
|
encryptor: {
|
|
encrypt(_, object) {
|
|
this.object = object;
|
|
return Promise.resolve('mock-encrypted');
|
|
},
|
|
decrypt() {
|
|
return Promise.resolve(this.object);
|
|
},
|
|
},
|
|
initLangCode: 'en_US',
|
|
platform: {
|
|
showTransactionNotification: () => undefined,
|
|
getVersion: () => 'foo',
|
|
},
|
|
browser: browserPolyfillMock,
|
|
infuraProjectId: 'foo',
|
|
});
|
|
});
|
|
|
|
afterEach(function () {
|
|
sandbox.restore();
|
|
nock.cleanAll();
|
|
});
|
|
|
|
after(async function () {
|
|
await ganacheServer.quit();
|
|
});
|
|
|
|
describe('#addNewAccount', function () {
|
|
it('two parallel calls with same accountCount give same result', async function () {
|
|
await metamaskController.createNewVaultAndKeychain('test@123');
|
|
const [addNewAccountResult1, addNewAccountResult2] = await Promise.all([
|
|
metamaskController.addNewAccount(1),
|
|
metamaskController.addNewAccount(1),
|
|
]);
|
|
assert.deepEqual(
|
|
Object.keys(addNewAccountResult1.identities),
|
|
Object.keys(addNewAccountResult2.identities),
|
|
);
|
|
});
|
|
|
|
it('two successive calls with same accountCount give same result', async function () {
|
|
await metamaskController.createNewVaultAndKeychain('test@123');
|
|
const addNewAccountResult1 = await metamaskController.addNewAccount(1);
|
|
const addNewAccountResult2 = await metamaskController.addNewAccount(1);
|
|
assert.deepEqual(
|
|
Object.keys(addNewAccountResult1.identities),
|
|
Object.keys(addNewAccountResult2.identities),
|
|
);
|
|
});
|
|
|
|
it('two successive calls with different accountCount give different results', async function () {
|
|
await metamaskController.createNewVaultAndKeychain('test@123');
|
|
const addNewAccountResult1 = await metamaskController.addNewAccount(1);
|
|
const addNewAccountResult2 = await metamaskController.addNewAccount(2);
|
|
assert.notDeepEqual(addNewAccountResult1, addNewAccountResult2);
|
|
});
|
|
});
|
|
|
|
describe('#importAccountWithStrategy', function () {
|
|
it('two sequential calls with same strategy give same result', async function () {
|
|
let keyringControllerState1;
|
|
let keyringControllerState2;
|
|
const importPrivkey =
|
|
'4cfd3e90fc78b0f86bf7524722150bb8da9c60cd532564d7ff43f5716514f553';
|
|
|
|
await metamaskController.createNewVaultAndKeychain('test@123');
|
|
await Promise.all([
|
|
metamaskController.importAccountWithStrategy('Private Key', [
|
|
importPrivkey,
|
|
]),
|
|
Promise.resolve(1).then(() => {
|
|
keyringControllerState1 = JSON.stringify(
|
|
metamaskController.keyringController.memStore.getState(),
|
|
);
|
|
metamaskController.importAccountWithStrategy('Private Key', [
|
|
importPrivkey,
|
|
]);
|
|
}),
|
|
Promise.resolve(2).then(() => {
|
|
keyringControllerState2 = JSON.stringify(
|
|
metamaskController.keyringController.memStore.getState(),
|
|
);
|
|
}),
|
|
]);
|
|
assert.deepEqual(keyringControllerState1, keyringControllerState2);
|
|
});
|
|
});
|
|
|
|
describe('#createNewVaultAndRestore', function () {
|
|
it('two successive calls with same inputs give same result', async function () {
|
|
const result1 = await metamaskController.createNewVaultAndRestore(
|
|
'test@123',
|
|
TEST_SEED,
|
|
);
|
|
const result2 = await metamaskController.createNewVaultAndRestore(
|
|
'test@123',
|
|
TEST_SEED,
|
|
);
|
|
assert.deepEqual(result1, result2);
|
|
});
|
|
});
|
|
|
|
describe('#createNewVaultAndKeychain', function () {
|
|
it('two successive calls with same inputs give same result', async function () {
|
|
const result1 = await metamaskController.createNewVaultAndKeychain(
|
|
'test@123',
|
|
);
|
|
const result2 = await metamaskController.createNewVaultAndKeychain(
|
|
'test@123',
|
|
);
|
|
assert.notEqual(result1, undefined);
|
|
assert.deepEqual(result1, result2);
|
|
});
|
|
});
|
|
|
|
describe('#addToken', function () {
|
|
const address = '0x514910771af9ca656af840dff83e8264ecf986ca';
|
|
const symbol = 'LINK';
|
|
const decimals = 18;
|
|
|
|
it('two parallel calls with same token details give same result', async function () {
|
|
const supportsInterfaceStub = sinon
|
|
.stub()
|
|
.returns(Promise.resolve(false));
|
|
sinon
|
|
.stub(metamaskController.tokensController, '_createEthersContract')
|
|
.callsFake(() =>
|
|
Promise.resolve({ supportsInterface: supportsInterfaceStub }),
|
|
);
|
|
|
|
const [token1, token2] = await Promise.all([
|
|
metamaskController.getApi().addToken(address, symbol, decimals),
|
|
metamaskController.getApi().addToken(address, symbol, decimals),
|
|
]);
|
|
assert.deepEqual(token1, token2);
|
|
});
|
|
});
|
|
|
|
describe('#addCustomNetwork', function () {
|
|
const customRpc = {
|
|
chainId: '0x1',
|
|
chainName: 'DUMMY_CHAIN_NAME',
|
|
rpcUrl: 'DUMMY_RPCURL',
|
|
ticker: 'DUMMY_TICKER',
|
|
blockExplorerUrl: 'DUMMY_EXPLORER',
|
|
};
|
|
it('two successive calls with custom RPC details give same result', async function () {
|
|
await metamaskController.addCustomNetwork(customRpc);
|
|
const rpcList1Length =
|
|
metamaskController.preferencesController.store.getState()
|
|
.frequentRpcListDetail.length;
|
|
await metamaskController.addCustomNetwork(customRpc);
|
|
const rpcList2Length =
|
|
metamaskController.preferencesController.store.getState()
|
|
.frequentRpcListDetail.length;
|
|
assert.equal(rpcList1Length, rpcList2Length);
|
|
});
|
|
});
|
|
|
|
describe('#updateTransactionSendFlowHistory', function () {
|
|
it('two sequential calls with same history give same result', async function () {
|
|
const recipientAddress = '0xc42edfcc21ed14dda456aa0756c153f7985d8813';
|
|
|
|
await metamaskController.createNewVaultAndKeychain('test@123');
|
|
const accounts = await metamaskController.keyringController.getAccounts();
|
|
const txMeta = await metamaskController.getApi().addUnapprovedTransaction(
|
|
undefined,
|
|
{
|
|
from: accounts[0],
|
|
to: recipientAddress,
|
|
},
|
|
ORIGIN_METAMASK,
|
|
);
|
|
|
|
const [transaction1, transaction2] = await Promise.all([
|
|
metamaskController
|
|
.getApi()
|
|
.updateTransactionSendFlowHistory(txMeta.id, 2, ['foo1', 'foo2']),
|
|
Promise.resolve(1).then(() =>
|
|
metamaskController
|
|
.getApi()
|
|
.updateTransactionSendFlowHistory(txMeta.id, 2, ['foo1', 'foo2']),
|
|
),
|
|
]);
|
|
assert.deepEqual(transaction1, transaction2);
|
|
});
|
|
});
|
|
|
|
describe('#removePermissionsFor', function () {
|
|
it('should not propagate PermissionsRequestNotFoundError', function () {
|
|
const error = new PermissionsRequestNotFoundError('123');
|
|
metamaskController.permissionController = {
|
|
revokePermissions: () => {
|
|
throw error;
|
|
},
|
|
};
|
|
// Line below will not throw error, in case it throws this test case will fail.
|
|
metamaskController.removePermissionsFor({ subject: 'test_subject' });
|
|
});
|
|
|
|
it('should propagate Error other than PermissionsRequestNotFoundError', function () {
|
|
const error = new Error();
|
|
metamaskController.permissionController = {
|
|
revokePermissions: () => {
|
|
throw error;
|
|
},
|
|
};
|
|
assert.throws(() => {
|
|
metamaskController.removePermissionsFor({ subject: 'test_subject' });
|
|
}, error);
|
|
});
|
|
});
|
|
|
|
describe('#rejectPermissionsRequest', function () {
|
|
it('should not propagate PermissionsRequestNotFoundError', function () {
|
|
const error = new PermissionsRequestNotFoundError('123');
|
|
metamaskController.permissionController = {
|
|
rejectPermissionsRequest: () => {
|
|
throw error;
|
|
},
|
|
};
|
|
// Line below will not throw error, in case it throws this test case will fail.
|
|
metamaskController.rejectPermissionsRequest('DUMMY_ID');
|
|
});
|
|
|
|
it('should propagate Error other than PermissionsRequestNotFoundError', function () {
|
|
const error = new Error();
|
|
metamaskController.permissionController = {
|
|
rejectPermissionsRequest: () => {
|
|
throw error;
|
|
},
|
|
};
|
|
assert.throws(() => {
|
|
metamaskController.rejectPermissionsRequest('DUMMY_ID');
|
|
}, error);
|
|
});
|
|
});
|
|
|
|
describe('#acceptPermissionsRequest', function () {
|
|
it('should not propagate PermissionsRequestNotFoundError', function () {
|
|
const error = new PermissionsRequestNotFoundError('123');
|
|
metamaskController.permissionController = {
|
|
acceptPermissionsRequest: () => {
|
|
throw error;
|
|
},
|
|
};
|
|
// Line below will not throw error, in case it throws this test case will fail.
|
|
metamaskController.acceptPermissionsRequest('DUMMY_ID');
|
|
});
|
|
|
|
it('should propagate Error other than PermissionsRequestNotFoundError', function () {
|
|
const error = new Error();
|
|
metamaskController.permissionController = {
|
|
acceptPermissionsRequest: () => {
|
|
throw error;
|
|
},
|
|
};
|
|
assert.throws(() => {
|
|
metamaskController.acceptPermissionsRequest('DUMMY_ID');
|
|
}, error);
|
|
});
|
|
});
|
|
|
|
describe('#resolvePendingApproval', function () {
|
|
it('should not propagate ApprovalRequestNotFoundError', function () {
|
|
const error = new ApprovalRequestNotFoundError('123');
|
|
metamaskController.approvalController = {
|
|
accept: () => {
|
|
throw error;
|
|
},
|
|
};
|
|
// Line below will not throw error, in case it throws this test case will fail.
|
|
metamaskController.resolvePendingApproval('DUMMY_ID', 'DUMMY_VALUE');
|
|
});
|
|
|
|
it('should propagate Error other than ApprovalRequestNotFoundError', function () {
|
|
const error = new Error();
|
|
metamaskController.approvalController = {
|
|
accept: () => {
|
|
throw error;
|
|
},
|
|
};
|
|
assert.throws(() => {
|
|
metamaskController.resolvePendingApproval('DUMMY_ID', 'DUMMY_VALUE');
|
|
}, error);
|
|
});
|
|
});
|
|
|
|
describe('#rejectPendingApproval', function () {
|
|
it('should not propagate ApprovalRequestNotFoundError', function () {
|
|
const error = new ApprovalRequestNotFoundError('123');
|
|
metamaskController.approvalController = {
|
|
reject: () => {
|
|
throw error;
|
|
},
|
|
};
|
|
// Line below will not throw error, in case it throws this test case will fail.
|
|
metamaskController.rejectPendingApproval('DUMMY_ID', {
|
|
code: 1,
|
|
message: 'DUMMY_MESSAGE',
|
|
data: 'DUMMY_DATA',
|
|
});
|
|
});
|
|
|
|
it('should propagate Error other than ApprovalRequestNotFoundError', function () {
|
|
const error = new Error();
|
|
metamaskController.approvalController = {
|
|
reject: () => {
|
|
throw error;
|
|
},
|
|
};
|
|
assert.throws(() => {
|
|
metamaskController.rejectPendingApproval('DUMMY_ID', {
|
|
code: 1,
|
|
message: 'DUMMY_MESSAGE',
|
|
data: 'DUMMY_DATA',
|
|
});
|
|
}, error);
|
|
});
|
|
});
|
|
});
|