mirror of
https://github.com/kremalicious/metamask-extension.git
synced 2024-11-22 01:47:00 +01:00
parent
480512d14f
commit
b50fe3184a
@ -1,7 +1,7 @@
|
|||||||
import { ObservableStore } from '@metamask/obs-store';
|
import { ObservableStore } from '@metamask/obs-store';
|
||||||
import log from 'loglevel';
|
import log from 'loglevel';
|
||||||
import BN from 'bn.js';
|
import BN from 'bn.js';
|
||||||
import createId from '../lib/random-id';
|
import createId from '../../../shared/modules/random-id';
|
||||||
import { bnToHex } from '../lib/util';
|
import { bnToHex } from '../lib/util';
|
||||||
import getFetchWithTimeout from '../../../shared/modules/fetch-with-timeout';
|
import getFetchWithTimeout from '../../../shared/modules/fetch-with-timeout';
|
||||||
|
|
||||||
|
@ -22,7 +22,7 @@ import {
|
|||||||
import { NETWORK_EVENTS } from './network';
|
import { NETWORK_EVENTS } from './network';
|
||||||
|
|
||||||
const IncomingTransactionsController = proxyquire('./incoming-transactions', {
|
const IncomingTransactionsController = proxyquire('./incoming-transactions', {
|
||||||
'../lib/random-id': { default: () => 54321 },
|
'../../../shared/modules/random-id': { default: () => 54321 },
|
||||||
}).default;
|
}).default;
|
||||||
|
|
||||||
const FAKE_CHAIN_ID = '0x1338';
|
const FAKE_CHAIN_ID = '0x1338';
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import EventEmitter from 'safe-event-emitter';
|
import EventEmitter from 'safe-event-emitter';
|
||||||
import { ObservableStore } from '@metamask/obs-store';
|
import { ObservableStore } from '@metamask/obs-store';
|
||||||
import log from 'loglevel';
|
import log from 'loglevel';
|
||||||
import createId from '../../lib/random-id';
|
import createId from '../../../../shared/modules/random-id';
|
||||||
import { TRANSACTION_STATUSES } from '../../../../shared/constants/transaction';
|
import { TRANSACTION_STATUSES } from '../../../../shared/constants/transaction';
|
||||||
import { METAMASK_CONTROLLER_EVENTS } from '../../metamask-controller';
|
import { METAMASK_CONTROLLER_EVENTS } from '../../metamask-controller';
|
||||||
import { transactionMatchesNetwork } from '../../../../shared/modules/transaction.utils';
|
import { transactionMatchesNetwork } from '../../../../shared/modules/transaction.utils';
|
||||||
|
33
app/scripts/lib/createMetaRPCHandler.js
Normal file
33
app/scripts/lib/createMetaRPCHandler.js
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
import { ethErrors, serializeError } from 'eth-rpc-errors';
|
||||||
|
|
||||||
|
const createMetaRPCHandler = (api, outStream) => {
|
||||||
|
return (data) => {
|
||||||
|
if (!api[data.method]) {
|
||||||
|
outStream.write({
|
||||||
|
jsonrpc: '2.0',
|
||||||
|
error: ethErrors.rpc.methodNotFound({
|
||||||
|
message: `${data.method} not found`,
|
||||||
|
}),
|
||||||
|
id: data.id,
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
api[data.method](...data.params, (err, result) => {
|
||||||
|
if (err) {
|
||||||
|
outStream.write({
|
||||||
|
jsonrpc: '2.0',
|
||||||
|
error: serializeError(err, { shouldIncludeStack: true }),
|
||||||
|
id: data.id,
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
outStream.write({
|
||||||
|
jsonrpc: '2.0',
|
||||||
|
result,
|
||||||
|
id: data.id,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
export default createMetaRPCHandler;
|
61
app/scripts/lib/createMetaRPCHandler.test.js
Normal file
61
app/scripts/lib/createMetaRPCHandler.test.js
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
import assert from 'assert';
|
||||||
|
import { obj as createThoughStream } from 'through2';
|
||||||
|
import createMetaRPCHandler from './createMetaRPCHandler';
|
||||||
|
|
||||||
|
describe('createMetaRPCHandler', function () {
|
||||||
|
it('can call the api when handler receives a JSON-RPC request', function (done) {
|
||||||
|
const api = {
|
||||||
|
foo: (param1) => {
|
||||||
|
assert.strictEqual(param1, 'bar');
|
||||||
|
done();
|
||||||
|
},
|
||||||
|
};
|
||||||
|
const streamTest = createThoughStream();
|
||||||
|
const handler = createMetaRPCHandler(api, streamTest);
|
||||||
|
handler({
|
||||||
|
id: 1,
|
||||||
|
method: 'foo',
|
||||||
|
params: ['bar'],
|
||||||
|
});
|
||||||
|
});
|
||||||
|
it('can write the response to the outstream when api callback is called', function (done) {
|
||||||
|
const api = {
|
||||||
|
foo: (param1, cb) => {
|
||||||
|
assert.strictEqual(param1, 'bar');
|
||||||
|
cb(null, 'foobarbaz');
|
||||||
|
},
|
||||||
|
};
|
||||||
|
const streamTest = createThoughStream();
|
||||||
|
const handler = createMetaRPCHandler(api, streamTest);
|
||||||
|
handler({
|
||||||
|
id: 1,
|
||||||
|
method: 'foo',
|
||||||
|
params: ['bar'],
|
||||||
|
});
|
||||||
|
streamTest.on('data', (data) => {
|
||||||
|
assert.strictEqual(data.result, 'foobarbaz');
|
||||||
|
streamTest.end();
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
it('can write the error to the outstream when api callback is called with an error', function (done) {
|
||||||
|
const api = {
|
||||||
|
foo: (param1, cb) => {
|
||||||
|
assert.strictEqual(param1, 'bar');
|
||||||
|
cb(new Error('foo-error'));
|
||||||
|
},
|
||||||
|
};
|
||||||
|
const streamTest = createThoughStream();
|
||||||
|
const handler = createMetaRPCHandler(api, streamTest);
|
||||||
|
handler({
|
||||||
|
id: 1,
|
||||||
|
method: 'foo',
|
||||||
|
params: ['bar'],
|
||||||
|
});
|
||||||
|
streamTest.on('data', (data) => {
|
||||||
|
assert.strictEqual(data.error.message, 'foo-error');
|
||||||
|
streamTest.end();
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
@ -5,8 +5,8 @@ import { ethErrors } from 'eth-rpc-errors';
|
|||||||
import log from 'loglevel';
|
import log from 'loglevel';
|
||||||
import { MESSAGE_TYPE } from '../../../shared/constants/app';
|
import { MESSAGE_TYPE } from '../../../shared/constants/app';
|
||||||
import { METAMASK_CONTROLLER_EVENTS } from '../metamask-controller';
|
import { METAMASK_CONTROLLER_EVENTS } from '../metamask-controller';
|
||||||
|
import createId from '../../../shared/modules/random-id';
|
||||||
import { addHexPrefix } from './util';
|
import { addHexPrefix } from './util';
|
||||||
import createId from './random-id';
|
|
||||||
|
|
||||||
const hexRe = /^[0-9A-Fa-f]+$/gu;
|
const hexRe = /^[0-9A-Fa-f]+$/gu;
|
||||||
|
|
||||||
|
@ -4,7 +4,7 @@ import { ethErrors } from 'eth-rpc-errors';
|
|||||||
import log from 'loglevel';
|
import log from 'loglevel';
|
||||||
import { MESSAGE_TYPE } from '../../../shared/constants/app';
|
import { MESSAGE_TYPE } from '../../../shared/constants/app';
|
||||||
import { METAMASK_CONTROLLER_EVENTS } from '../metamask-controller';
|
import { METAMASK_CONTROLLER_EVENTS } from '../metamask-controller';
|
||||||
import createId from './random-id';
|
import createId from '../../../shared/modules/random-id';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents, and contains data about, an 'eth_getEncryptionPublicKey' type request. These are created when
|
* Represents, and contains data about, an 'eth_getEncryptionPublicKey' type request. These are created when
|
||||||
|
@ -4,7 +4,7 @@ import ethUtil from 'ethereumjs-util';
|
|||||||
import { ethErrors } from 'eth-rpc-errors';
|
import { ethErrors } from 'eth-rpc-errors';
|
||||||
import { MESSAGE_TYPE } from '../../../shared/constants/app';
|
import { MESSAGE_TYPE } from '../../../shared/constants/app';
|
||||||
import { METAMASK_CONTROLLER_EVENTS } from '../metamask-controller';
|
import { METAMASK_CONTROLLER_EVENTS } from '../metamask-controller';
|
||||||
import createId from './random-id';
|
import createId from '../../../shared/modules/random-id';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents, and contains data about, an 'eth_sign' type signature request. These are created when a signature for
|
* Represents, and contains data about, an 'eth_sign' type signature request. These are created when a signature for
|
||||||
|
81
app/scripts/lib/metaRPCClientFactory.js
Normal file
81
app/scripts/lib/metaRPCClientFactory.js
Normal file
@ -0,0 +1,81 @@
|
|||||||
|
import { EthereumRpcError } from 'eth-rpc-errors';
|
||||||
|
import SafeEventEmitter from 'safe-event-emitter';
|
||||||
|
import createRandomId from '../../../shared/modules/random-id';
|
||||||
|
|
||||||
|
class MetaRPCClient {
|
||||||
|
constructor(connectionStream) {
|
||||||
|
this.connectionStream = connectionStream;
|
||||||
|
this.notificationChannel = new SafeEventEmitter();
|
||||||
|
this.requests = new Map();
|
||||||
|
this.connectionStream.on('data', this.handleResponse.bind(this));
|
||||||
|
this.connectionStream.on('end', this.close.bind(this));
|
||||||
|
}
|
||||||
|
|
||||||
|
onNotification(handler) {
|
||||||
|
this.notificationChannel.addListener('notification', (data) => {
|
||||||
|
handler(data);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
close() {
|
||||||
|
this.notificationChannel.removeAllListeners();
|
||||||
|
}
|
||||||
|
|
||||||
|
handleResponse(data) {
|
||||||
|
const { id, result, error, method, params } = data;
|
||||||
|
const cb = this.requests.get(id);
|
||||||
|
|
||||||
|
if (method && params && id) {
|
||||||
|
// dont handle server-side to client-side requests
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (method && params && !id) {
|
||||||
|
// handle servier-side to client-side notification
|
||||||
|
this.notificationChannel.emit('notification', data);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!cb) {
|
||||||
|
// not found in request list
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (error) {
|
||||||
|
const e = new EthereumRpcError(error.code, error.message, error.data);
|
||||||
|
// preserve the stack from serializeError
|
||||||
|
e.stack = error.stack;
|
||||||
|
this.requests.delete(id);
|
||||||
|
cb(e);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.requests.delete(id);
|
||||||
|
|
||||||
|
cb(null, result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const metaRPCClientFactory = (connectionStream) => {
|
||||||
|
const metaRPCClient = new MetaRPCClient(connectionStream);
|
||||||
|
return new Proxy(metaRPCClient, {
|
||||||
|
get: (object, property) => {
|
||||||
|
if (object[property]) {
|
||||||
|
return object[property];
|
||||||
|
}
|
||||||
|
return (...p) => {
|
||||||
|
const cb = p[p.length - 1];
|
||||||
|
const params = p.slice(0, -1);
|
||||||
|
const id = createRandomId();
|
||||||
|
|
||||||
|
object.requests.set(id, cb);
|
||||||
|
object.connectionStream.write({
|
||||||
|
jsonrpc: '2.0',
|
||||||
|
method: property,
|
||||||
|
params,
|
||||||
|
id,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
},
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
export default metaRPCClientFactory;
|
88
app/scripts/lib/metaRPCClientFactory.test.js
Normal file
88
app/scripts/lib/metaRPCClientFactory.test.js
Normal file
@ -0,0 +1,88 @@
|
|||||||
|
import assert from 'assert';
|
||||||
|
import { obj as createThoughStream } from 'through2';
|
||||||
|
import metaRPCClientFactory from './metaRPCClientFactory';
|
||||||
|
|
||||||
|
describe('metaRPCClientFactory', function () {
|
||||||
|
it('should be able to make an rpc request with the method', function (done) {
|
||||||
|
const streamTest = createThoughStream((chunk) => {
|
||||||
|
assert.strictEqual(chunk.method, 'foo');
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
const metaRPCClient = metaRPCClientFactory(streamTest);
|
||||||
|
metaRPCClient.foo();
|
||||||
|
});
|
||||||
|
it('should be able to make an rpc request/response with the method and params and node-style callback', function (done) {
|
||||||
|
const streamTest = createThoughStream();
|
||||||
|
const metaRPCClient = metaRPCClientFactory(streamTest);
|
||||||
|
|
||||||
|
// make a "foo" method call
|
||||||
|
metaRPCClient.foo('bar', (_, result) => {
|
||||||
|
assert.strictEqual(result, 'foobarbaz');
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
|
||||||
|
// fake a response
|
||||||
|
metaRPCClient.requests.forEach((_, key) => {
|
||||||
|
streamTest.write({
|
||||||
|
jsonrpc: '2.0',
|
||||||
|
id: key,
|
||||||
|
result: 'foobarbaz',
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
it('should be able to make an rpc request/error with the method and params and node-style callback', function (done) {
|
||||||
|
const streamTest = createThoughStream();
|
||||||
|
const metaRPCClient = metaRPCClientFactory(streamTest);
|
||||||
|
|
||||||
|
// make a "foo" method call
|
||||||
|
metaRPCClient.foo('bar', (err) => {
|
||||||
|
assert.strictEqual(err.message, 'foo-message');
|
||||||
|
assert.strictEqual(err.code, 1);
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
|
||||||
|
metaRPCClient.requests.forEach((_, key) => {
|
||||||
|
streamTest.write({
|
||||||
|
jsonrpc: '2.0',
|
||||||
|
id: key,
|
||||||
|
error: {
|
||||||
|
code: 1,
|
||||||
|
message: 'foo-message',
|
||||||
|
},
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should be able to make an rpc request/response with the method and params and node-style callback with multiple instances of metaRPCClientFactory and the same connectionStream', function (done) {
|
||||||
|
const streamTest = createThoughStream();
|
||||||
|
const metaRPCClient = metaRPCClientFactory(streamTest);
|
||||||
|
const metaRPCClient2 = metaRPCClientFactory(streamTest);
|
||||||
|
|
||||||
|
// make a "foo" method call, followed by "baz" call on metaRPCClient2
|
||||||
|
metaRPCClient.foo('bar', (_, result) => {
|
||||||
|
assert.strictEqual(result, 'foobarbaz');
|
||||||
|
metaRPCClient2.baz('bar', (err) => {
|
||||||
|
assert.strictEqual(err, null);
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// fake a response
|
||||||
|
metaRPCClient.requests.forEach((_, key) => {
|
||||||
|
streamTest.write({
|
||||||
|
jsonrpc: '2.0',
|
||||||
|
id: key,
|
||||||
|
result: 'foobarbaz',
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// fake client2's response
|
||||||
|
metaRPCClient2.requests.forEach((_, key) => {
|
||||||
|
streamTest.write({
|
||||||
|
jsonrpc: '2.0',
|
||||||
|
id: key,
|
||||||
|
result: 'foobarbaz',
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
@ -5,8 +5,8 @@ import { ethErrors } from 'eth-rpc-errors';
|
|||||||
import log from 'loglevel';
|
import log from 'loglevel';
|
||||||
import { MESSAGE_TYPE } from '../../../shared/constants/app';
|
import { MESSAGE_TYPE } from '../../../shared/constants/app';
|
||||||
import { METAMASK_CONTROLLER_EVENTS } from '../metamask-controller';
|
import { METAMASK_CONTROLLER_EVENTS } from '../metamask-controller';
|
||||||
|
import createId from '../../../shared/modules/random-id';
|
||||||
import { addHexPrefix } from './util';
|
import { addHexPrefix } from './util';
|
||||||
import createId from './random-id';
|
|
||||||
|
|
||||||
const hexRe = /^[0-9A-Fa-f]+$/gu;
|
const hexRe = /^[0-9A-Fa-f]+$/gu;
|
||||||
|
|
||||||
|
@ -8,7 +8,7 @@ import log from 'loglevel';
|
|||||||
import jsonschema from 'jsonschema';
|
import jsonschema from 'jsonschema';
|
||||||
import { MESSAGE_TYPE } from '../../../shared/constants/app';
|
import { MESSAGE_TYPE } from '../../../shared/constants/app';
|
||||||
import { METAMASK_CONTROLLER_EVENTS } from '../metamask-controller';
|
import { METAMASK_CONTROLLER_EVENTS } from '../metamask-controller';
|
||||||
import createId from './random-id';
|
import createId from '../../../shared/modules/random-id';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents, and contains data about, an 'eth_signTypedData' type signature request. These are created when a
|
* Represents, and contains data about, an 'eth_signTypedData' type signature request. These are created when a
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
import EventEmitter from 'events';
|
import EventEmitter from 'events';
|
||||||
import pump from 'pump';
|
import pump from 'pump';
|
||||||
import Dnode from 'dnode';
|
|
||||||
import { ObservableStore } from '@metamask/obs-store';
|
import { ObservableStore } from '@metamask/obs-store';
|
||||||
import { storeAsStream } from '@metamask/obs-store/dist/asStream';
|
import { storeAsStream } from '@metamask/obs-store/dist/asStream';
|
||||||
import { JsonRpcEngine } from 'json-rpc-engine';
|
import { JsonRpcEngine } from 'json-rpc-engine';
|
||||||
@ -60,6 +59,7 @@ import accountImporter from './account-import-strategies';
|
|||||||
import seedPhraseVerifier from './lib/seed-phrase-verifier';
|
import seedPhraseVerifier from './lib/seed-phrase-verifier';
|
||||||
import MetaMetricsController from './controllers/metametrics';
|
import MetaMetricsController from './controllers/metametrics';
|
||||||
import { segment, segmentLegacy } from './lib/segment';
|
import { segment, segmentLegacy } from './lib/segment';
|
||||||
|
import createMetaRPCHandler from './lib/createMetaRPCHandler';
|
||||||
|
|
||||||
export const METAMASK_CONTROLLER_EVENTS = {
|
export const METAMASK_CONTROLLER_EVENTS = {
|
||||||
// Fired after state changes that impact the extension badge (unapproved msg count)
|
// Fired after state changes that impact the extension badge (unapproved msg count)
|
||||||
@ -598,7 +598,7 @@ export default class MetamaskController extends EventEmitter {
|
|||||||
/**
|
/**
|
||||||
* Returns an Object containing API Callback Functions.
|
* Returns an Object containing API Callback Functions.
|
||||||
* These functions are the interface for the UI.
|
* These functions are the interface for the UI.
|
||||||
* The API object can be transmitted over a stream with dnode.
|
* The API object can be transmitted over a stream via JSON-RPC.
|
||||||
*
|
*
|
||||||
* @returns {Object} Object containing API functions.
|
* @returns {Object} Object containing API functions.
|
||||||
*/
|
*/
|
||||||
@ -1996,36 +1996,34 @@ export default class MetamaskController extends EventEmitter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A method for providing our API over a stream using Dnode.
|
* A method for providing our API over a stream using JSON-RPC.
|
||||||
* @param {*} outStream - The stream to provide our API over.
|
* @param {*} outStream - The stream to provide our API over.
|
||||||
*/
|
*/
|
||||||
setupControllerConnection(outStream) {
|
setupControllerConnection(outStream) {
|
||||||
const api = this.getApi();
|
const api = this.getApi();
|
||||||
// the "weak: false" option is for nodejs only (eg unit tests)
|
|
||||||
// it is a workaround for node v12 support
|
|
||||||
const dnode = Dnode(api, { weak: false });
|
|
||||||
// report new active controller connection
|
// report new active controller connection
|
||||||
this.activeControllerConnections += 1;
|
this.activeControllerConnections += 1;
|
||||||
this.emit('controllerConnectionChanged', this.activeControllerConnections);
|
this.emit('controllerConnectionChanged', this.activeControllerConnections);
|
||||||
// connect dnode api to remote connection
|
|
||||||
pump(outStream, dnode, outStream, (err) => {
|
// set up postStream transport
|
||||||
// report new active controller connection
|
outStream.on('data', createMetaRPCHandler(api, outStream));
|
||||||
|
const handleUpdate = (update) => {
|
||||||
|
// send notification to client-side
|
||||||
|
outStream.write({
|
||||||
|
jsonrpc: '2.0',
|
||||||
|
method: 'sendUpdate',
|
||||||
|
params: [update],
|
||||||
|
});
|
||||||
|
};
|
||||||
|
this.on('update', handleUpdate);
|
||||||
|
outStream.on('end', () => {
|
||||||
this.activeControllerConnections -= 1;
|
this.activeControllerConnections -= 1;
|
||||||
this.emit(
|
this.emit(
|
||||||
'controllerConnectionChanged',
|
'controllerConnectionChanged',
|
||||||
this.activeControllerConnections,
|
this.activeControllerConnections,
|
||||||
);
|
);
|
||||||
// report any error
|
this.removeListener('update', handleUpdate);
|
||||||
if (err) {
|
|
||||||
log.error(err);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
dnode.on('remote', (remote) => {
|
|
||||||
// push updates to popup
|
|
||||||
const sendUpdate = (update) => remote.sendUpdate(update);
|
|
||||||
this.on('update', sendUpdate);
|
|
||||||
// remove update listener once the connection ends
|
|
||||||
dnode.on('end', () => this.removeListener('update', sendUpdate));
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1116,7 +1116,7 @@ describe('MetaMaskController', function () {
|
|||||||
});
|
});
|
||||||
|
|
||||||
describe('#setupTrustedCommunication', function () {
|
describe('#setupTrustedCommunication', function () {
|
||||||
it('sets up controller dnode api for trusted communication', async function () {
|
it('sets up controller JSON-RPC api for trusted communication', async function () {
|
||||||
const messageSender = {
|
const messageSender = {
|
||||||
url: 'http://mycrypto.com',
|
url: 'http://mycrypto.com',
|
||||||
tab: {},
|
tab: {},
|
||||||
|
@ -1,8 +1,7 @@
|
|||||||
import querystring from 'querystring';
|
import querystring from 'querystring';
|
||||||
import { EventEmitter } from 'events';
|
|
||||||
import dnode from 'dnode';
|
|
||||||
import PortStream from 'extension-port-stream';
|
import PortStream from 'extension-port-stream';
|
||||||
import extension from 'extensionizer';
|
import extension from 'extensionizer';
|
||||||
|
import createRandomId from '../../shared/modules/random-id';
|
||||||
import { setupMultiplex } from './lib/stream-utils';
|
import { setupMultiplex } from './lib/stream-utils';
|
||||||
import { getEnvironmentType } from './lib/util';
|
import { getEnvironmentType } from './lib/util';
|
||||||
import ExtensionPlatform from './platforms/extension';
|
import ExtensionPlatform from './platforms/extension';
|
||||||
@ -22,36 +21,15 @@ function start() {
|
|||||||
});
|
});
|
||||||
const connectionStream = new PortStream(extensionPort);
|
const connectionStream = new PortStream(extensionPort);
|
||||||
const mx = setupMultiplex(connectionStream);
|
const mx = setupMultiplex(connectionStream);
|
||||||
setupControllerConnection(
|
const backgroundConnection = mx.createStream('controller');
|
||||||
mx.createStream('controller'),
|
const continueLink = document.getElementById('unsafe-continue');
|
||||||
(err, metaMaskController) => {
|
continueLink.addEventListener('click', () => {
|
||||||
if (err) {
|
backgroundConnection.write({
|
||||||
return;
|
jsonrpc: '2.0',
|
||||||
}
|
method: 'safelistPhishingDomain',
|
||||||
|
params: [suspect.hostname],
|
||||||
const continueLink = document.getElementById('unsafe-continue');
|
id: createRandomId(),
|
||||||
continueLink.addEventListener('click', () => {
|
});
|
||||||
metaMaskController.safelistPhishingDomain(suspect.hostname);
|
window.location.href = suspect.href;
|
||||||
window.location.href = suspect.href;
|
});
|
||||||
});
|
|
||||||
},
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
function setupControllerConnection(connectionStream, cb) {
|
|
||||||
const eventEmitter = new EventEmitter();
|
|
||||||
// the "weak: false" option is for nodejs only (eg unit tests)
|
|
||||||
// it is a workaround for node v12 support
|
|
||||||
const metaMaskControllerDnode = dnode(
|
|
||||||
{
|
|
||||||
sendUpdate(state) {
|
|
||||||
eventEmitter.emit('update', state);
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{ weak: false },
|
|
||||||
);
|
|
||||||
connectionStream.pipe(metaMaskControllerDnode).pipe(connectionStream);
|
|
||||||
metaMaskControllerDnode.once('remote', (backgroundConnection) =>
|
|
||||||
cb(null, backgroundConnection),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
@ -2,11 +2,9 @@
|
|||||||
import 'abortcontroller-polyfill/dist/polyfill-patch-fetch';
|
import 'abortcontroller-polyfill/dist/polyfill-patch-fetch';
|
||||||
import '@formatjs/intl-relativetimeformat/polyfill';
|
import '@formatjs/intl-relativetimeformat/polyfill';
|
||||||
|
|
||||||
import { EventEmitter } from 'events';
|
|
||||||
import PortStream from 'extension-port-stream';
|
import PortStream from 'extension-port-stream';
|
||||||
import extension from 'extensionizer';
|
import extension from 'extensionizer';
|
||||||
|
|
||||||
import Dnode from 'dnode';
|
|
||||||
import Eth from 'ethjs';
|
import Eth from 'ethjs';
|
||||||
import EthQuery from 'eth-query';
|
import EthQuery from 'eth-query';
|
||||||
import StreamProvider from 'web3-stream-provider';
|
import StreamProvider from 'web3-stream-provider';
|
||||||
@ -19,6 +17,7 @@ import {
|
|||||||
import ExtensionPlatform from './platforms/extension';
|
import ExtensionPlatform from './platforms/extension';
|
||||||
import { setupMultiplex } from './lib/stream-utils';
|
import { setupMultiplex } from './lib/stream-utils';
|
||||||
import { getEnvironmentType } from './lib/util';
|
import { getEnvironmentType } from './lib/util';
|
||||||
|
import metaRPCClientFactory from './lib/metaRPCClientFactory';
|
||||||
|
|
||||||
start().catch(log.error);
|
start().catch(log.error);
|
||||||
|
|
||||||
@ -138,20 +137,6 @@ function setupWeb3Connection(connectionStream) {
|
|||||||
* @param {Function} cb - Called when the remote account manager connection is established
|
* @param {Function} cb - Called when the remote account manager connection is established
|
||||||
*/
|
*/
|
||||||
function setupControllerConnection(connectionStream, cb) {
|
function setupControllerConnection(connectionStream, cb) {
|
||||||
const eventEmitter = new EventEmitter();
|
const backgroundRPC = metaRPCClientFactory(connectionStream);
|
||||||
// the "weak: false" option is for nodejs only (eg unit tests)
|
cb(null, backgroundRPC);
|
||||||
// it is a workaround for node v12 support
|
|
||||||
const backgroundDnode = Dnode(
|
|
||||||
{
|
|
||||||
sendUpdate(state) {
|
|
||||||
eventEmitter.emit('update', state);
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{ weak: false },
|
|
||||||
);
|
|
||||||
connectionStream.pipe(backgroundDnode).pipe(connectionStream);
|
|
||||||
backgroundDnode.once('remote', function (backgroundConnection) {
|
|
||||||
backgroundConnection.on = eventEmitter.on.bind(eventEmitter);
|
|
||||||
cb(null, backgroundConnection);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
@ -107,7 +107,6 @@
|
|||||||
"currency-formatter": "^1.4.2",
|
"currency-formatter": "^1.4.2",
|
||||||
"debounce-stream": "^2.0.0",
|
"debounce-stream": "^2.0.0",
|
||||||
"deep-freeze-strict": "1.1.1",
|
"deep-freeze-strict": "1.1.1",
|
||||||
"dnode": "^1.2.2",
|
|
||||||
"end-of-stream": "^1.4.4",
|
"end-of-stream": "^1.4.4",
|
||||||
"eth-block-tracker": "^4.4.2",
|
"eth-block-tracker": "^4.4.2",
|
||||||
"eth-ens-namehash": "^2.0.8",
|
"eth-ens-namehash": "^2.0.8",
|
||||||
|
@ -2427,8 +2427,12 @@ export function requestAccountsPermissionWithId(origin) {
|
|||||||
* @param {string[]} accounts - The accounts to expose, if any.
|
* @param {string[]} accounts - The accounts to expose, if any.
|
||||||
*/
|
*/
|
||||||
export function approvePermissionsRequest(request, accounts) {
|
export function approvePermissionsRequest(request, accounts) {
|
||||||
return () => {
|
return (dispatch) => {
|
||||||
background.approvePermissionsRequest(request, accounts);
|
background.approvePermissionsRequest(request, accounts, (err) => {
|
||||||
|
if (err) {
|
||||||
|
dispatch(displayWarning(err.message));
|
||||||
|
}
|
||||||
|
});
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2455,8 +2459,12 @@ export function rejectPermissionsRequest(requestId) {
|
|||||||
* Clears the given permissions for the given origin.
|
* Clears the given permissions for the given origin.
|
||||||
*/
|
*/
|
||||||
export function removePermissionsFor(domains) {
|
export function removePermissionsFor(domains) {
|
||||||
return () => {
|
return (dispatch) => {
|
||||||
background.removePermissionsFor(domains);
|
background.removePermissionsFor(domains, (err) => {
|
||||||
|
if (err) {
|
||||||
|
dispatch(displayWarning(err.message));
|
||||||
|
}
|
||||||
|
});
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2464,8 +2472,12 @@ export function removePermissionsFor(domains) {
|
|||||||
* Clears all permissions for all domains.
|
* Clears all permissions for all domains.
|
||||||
*/
|
*/
|
||||||
export function clearPermissions() {
|
export function clearPermissions() {
|
||||||
return () => {
|
return (dispatch) => {
|
||||||
background.clearPermissions();
|
background.clearPermissions((err) => {
|
||||||
|
if (err) {
|
||||||
|
dispatch(displayWarning(err.message));
|
||||||
|
}
|
||||||
|
});
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2610,7 +2622,11 @@ export function getContractMethodData(data = '') {
|
|||||||
|
|
||||||
return getMethodDataAsync(fourBytePrefix).then(({ name, params }) => {
|
return getMethodDataAsync(fourBytePrefix).then(({ name, params }) => {
|
||||||
dispatch(loadingMethodDataFinished());
|
dispatch(loadingMethodDataFinished());
|
||||||
background.addKnownMethodData(fourBytePrefix, { name, params });
|
background.addKnownMethodData(fourBytePrefix, { name, params }, (err) => {
|
||||||
|
if (err) {
|
||||||
|
dispatch(displayWarning(err.message));
|
||||||
|
}
|
||||||
|
});
|
||||||
return { name, params };
|
return { name, params };
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
12
ui/index.js
12
ui/index.js
@ -128,8 +128,16 @@ async function startApp(metamaskState, backgroundConnection, opts) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
backgroundConnection.on('update', function (state) {
|
backgroundConnection.onNotification((data) => {
|
||||||
store.dispatch(actions.updateMetamaskState(state));
|
if (data.method === 'sendUpdate') {
|
||||||
|
store.dispatch(actions.updateMetamaskState(data.params[0]));
|
||||||
|
} else {
|
||||||
|
throw new Error(
|
||||||
|
`Internal JSON-RPC Notification Not Handled:\n\n ${JSON.stringify(
|
||||||
|
data,
|
||||||
|
)}`,
|
||||||
|
);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// global metamask api - used by tooling
|
// global metamask api - used by tooling
|
||||||
|
33
yarn.lock
33
yarn.lock
@ -8565,24 +8565,6 @@ dnd-core@^7.4.4:
|
|||||||
invariant "^2.2.4"
|
invariant "^2.2.4"
|
||||||
redux "^4.0.1"
|
redux "^4.0.1"
|
||||||
|
|
||||||
dnode-protocol@~0.2.2:
|
|
||||||
version "0.2.2"
|
|
||||||
resolved "https://registry.yarnpkg.com/dnode-protocol/-/dnode-protocol-0.2.2.tgz#51151d16fc3b5f84815ee0b9497a1061d0d1949d"
|
|
||||||
integrity sha1-URUdFvw7X4SBXuC5SXoQYdDRlJ0=
|
|
||||||
dependencies:
|
|
||||||
jsonify "~0.0.0"
|
|
||||||
traverse "~0.6.3"
|
|
||||||
|
|
||||||
dnode@^1.2.2:
|
|
||||||
version "1.2.2"
|
|
||||||
resolved "https://registry.yarnpkg.com/dnode/-/dnode-1.2.2.tgz#4ac3cfe26e292b3b39b8258ae7d94edc58132efa"
|
|
||||||
integrity sha1-SsPP4m4pKzs5uCWK59lO3FgTLvo=
|
|
||||||
dependencies:
|
|
||||||
dnode-protocol "~0.2.2"
|
|
||||||
jsonify "~0.0.0"
|
|
||||||
optionalDependencies:
|
|
||||||
weak "^1.0.0"
|
|
||||||
|
|
||||||
dns-packet@^4.0.0:
|
dns-packet@^4.0.0:
|
||||||
version "4.2.0"
|
version "4.2.0"
|
||||||
resolved "https://registry.yarnpkg.com/dns-packet/-/dns-packet-4.2.0.tgz#3fd6f5ff5a4ec3194ed0b15312693ffe8776b343"
|
resolved "https://registry.yarnpkg.com/dns-packet/-/dns-packet-4.2.0.tgz#3fd6f5ff5a4ec3194ed0b15312693ffe8776b343"
|
||||||
@ -17608,7 +17590,7 @@ nan@2.13.2:
|
|||||||
resolved "https://registry.yarnpkg.com/nan/-/nan-2.13.2.tgz#f51dc7ae66ba7d5d55e1e6d4d8092e802c9aefe7"
|
resolved "https://registry.yarnpkg.com/nan/-/nan-2.13.2.tgz#f51dc7ae66ba7d5d55e1e6d4d8092e802c9aefe7"
|
||||||
integrity sha512-TghvYc72wlMGMVMluVo9WRJc0mB8KxxF/gZ4YYFy7V2ZQX9l7rgbPg7vjS9mt6U5HXODVFVI2bOduCzwOMv/lw==
|
integrity sha512-TghvYc72wlMGMVMluVo9WRJc0mB8KxxF/gZ4YYFy7V2ZQX9l7rgbPg7vjS9mt6U5HXODVFVI2bOduCzwOMv/lw==
|
||||||
|
|
||||||
nan@^2.0.5, nan@^2.11.1, nan@^2.12.1, nan@^2.13.2, nan@^2.14.0, nan@^2.2.1:
|
nan@^2.11.1, nan@^2.12.1, nan@^2.13.2, nan@^2.14.0, nan@^2.2.1:
|
||||||
version "2.14.0"
|
version "2.14.0"
|
||||||
resolved "https://registry.yarnpkg.com/nan/-/nan-2.14.0.tgz#7818f722027b2459a86f0295d434d1fc2336c52c"
|
resolved "https://registry.yarnpkg.com/nan/-/nan-2.14.0.tgz#7818f722027b2459a86f0295d434d1fc2336c52c"
|
||||||
integrity sha512-INOFj37C7k3AfaNTtX8RhsTw7qRy7eLET14cROi9+5HAVbbHuIWUHEauBv5qT4Av2tWasiTY1Jw6puUNqRJXQg==
|
integrity sha512-INOFj37C7k3AfaNTtX8RhsTw7qRy7eLET14cROi9+5HAVbbHuIWUHEauBv5qT4Av2tWasiTY1Jw6puUNqRJXQg==
|
||||||
@ -24362,11 +24344,6 @@ tr46@^1.0.0, tr46@^1.0.1:
|
|||||||
dependencies:
|
dependencies:
|
||||||
punycode "^2.1.0"
|
punycode "^2.1.0"
|
||||||
|
|
||||||
traverse@~0.6.3:
|
|
||||||
version "0.6.6"
|
|
||||||
resolved "https://registry.yarnpkg.com/traverse/-/traverse-0.6.6.tgz#cbdf560fd7b9af632502fed40f918c157ea97137"
|
|
||||||
integrity sha1-y99WD9e5r2MlAv7UD5GMFX6pcTc=
|
|
||||||
|
|
||||||
tree-kill@^1.2.2:
|
tree-kill@^1.2.2:
|
||||||
version "1.2.2"
|
version "1.2.2"
|
||||||
resolved "https://registry.yarnpkg.com/tree-kill/-/tree-kill-1.2.2.tgz#4ca09a9092c88b73a7cdc5e8a01b507b0790a0cc"
|
resolved "https://registry.yarnpkg.com/tree-kill/-/tree-kill-1.2.2.tgz#4ca09a9092c88b73a7cdc5e8a01b507b0790a0cc"
|
||||||
@ -25417,14 +25394,6 @@ wcwidth@^1.0.0:
|
|||||||
dependencies:
|
dependencies:
|
||||||
defaults "^1.0.3"
|
defaults "^1.0.3"
|
||||||
|
|
||||||
weak@^1.0.0:
|
|
||||||
version "1.0.1"
|
|
||||||
resolved "https://registry.yarnpkg.com/weak/-/weak-1.0.1.tgz#ab99aab30706959aa0200cb8cf545bb9cb33b99e"
|
|
||||||
integrity sha1-q5mqswcGlZqgIAy4z1RbucszuZ4=
|
|
||||||
dependencies:
|
|
||||||
bindings "^1.2.1"
|
|
||||||
nan "^2.0.5"
|
|
||||||
|
|
||||||
web3-bzz@1.2.11:
|
web3-bzz@1.2.11:
|
||||||
version "1.2.11"
|
version "1.2.11"
|
||||||
resolved "https://registry.yarnpkg.com/web3-bzz/-/web3-bzz-1.2.11.tgz#41bc19a77444bd5365744596d778b811880f707f"
|
resolved "https://registry.yarnpkg.com/web3-bzz/-/web3-bzz-1.2.11.tgz#41bc19a77444bd5365744596d778b811880f707f"
|
||||||
|
Loading…
Reference in New Issue
Block a user