|
|
@ -1,12 +1,18 @@ |
|
|
|
const EventEmitter = require('events') |
|
|
|
const EventEmitter = require('events') |
|
|
|
const extend = require('xtend') |
|
|
|
const extend = require('xtend') |
|
|
|
const promiseToCallback = require('promise-to-callback') |
|
|
|
const promiseToCallback = require('promise-to-callback') |
|
|
|
const pipe = require('pump') |
|
|
|
const pump = require('pump') |
|
|
|
const Dnode = require('dnode') |
|
|
|
const Dnode = require('dnode') |
|
|
|
const ObservableStore = require('obs-store') |
|
|
|
const ObservableStore = require('obs-store') |
|
|
|
const EthStore = require('./lib/eth-store') |
|
|
|
const EthStore = require('./lib/eth-store') |
|
|
|
const EthQuery = require('eth-query') |
|
|
|
const EthQuery = require('eth-query') |
|
|
|
const streamIntoProvider = require('web3-stream-provider/handler') |
|
|
|
const RpcEngine = require('json-rpc-engine') |
|
|
|
|
|
|
|
const debounce = require('debounce') |
|
|
|
|
|
|
|
const createEngineStream = require('json-rpc-middleware-stream/engineStream') |
|
|
|
|
|
|
|
const createFilterMiddleware = require('eth-json-rpc-filters') |
|
|
|
|
|
|
|
const createOriginMiddleware = require('./lib/createOriginMiddleware') |
|
|
|
|
|
|
|
const createLoggerMiddleware = require('./lib/createLoggerMiddleware') |
|
|
|
|
|
|
|
const createProviderMiddleware = require('./lib/createProviderMiddleware') |
|
|
|
const setupMultiplex = require('./lib/stream-utils.js').setupMultiplex |
|
|
|
const setupMultiplex = require('./lib/stream-utils.js').setupMultiplex |
|
|
|
const KeyringController = require('./keyring-controller') |
|
|
|
const KeyringController = require('./keyring-controller') |
|
|
|
const NetworkController = require('./controllers/network') |
|
|
|
const NetworkController = require('./controllers/network') |
|
|
@ -24,8 +30,6 @@ const ConfigManager = require('./lib/config-manager') |
|
|
|
const nodeify = require('./lib/nodeify') |
|
|
|
const nodeify = require('./lib/nodeify') |
|
|
|
const accountImporter = require('./account-import-strategies') |
|
|
|
const accountImporter = require('./account-import-strategies') |
|
|
|
const getBuyEthUrl = require('./lib/buy-eth-url') |
|
|
|
const getBuyEthUrl = require('./lib/buy-eth-url') |
|
|
|
const debounce = require('debounce') |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const version = require('../manifest.json').version |
|
|
|
const version = require('../manifest.json').version |
|
|
|
|
|
|
|
|
|
|
|
module.exports = class MetamaskController extends EventEmitter { |
|
|
|
module.exports = class MetamaskController extends EventEmitter { |
|
|
@ -77,12 +81,13 @@ module.exports = class MetamaskController extends EventEmitter { |
|
|
|
|
|
|
|
|
|
|
|
// rpc provider
|
|
|
|
// rpc provider
|
|
|
|
this.provider = this.initializeProvider() |
|
|
|
this.provider = this.initializeProvider() |
|
|
|
|
|
|
|
this.blockTracker = this.provider |
|
|
|
|
|
|
|
|
|
|
|
// eth data query tools
|
|
|
|
// eth data query tools
|
|
|
|
this.ethQuery = new EthQuery(this.provider) |
|
|
|
this.ethQuery = new EthQuery(this.provider) |
|
|
|
this.ethStore = new EthStore({ |
|
|
|
this.ethStore = new EthStore({ |
|
|
|
provider: this.provider, |
|
|
|
provider: this.provider, |
|
|
|
blockTracker: this.provider, |
|
|
|
blockTracker: this.blockTracker, |
|
|
|
}) |
|
|
|
}) |
|
|
|
|
|
|
|
|
|
|
|
// key mgmt
|
|
|
|
// key mgmt
|
|
|
@ -109,7 +114,7 @@ module.exports = class MetamaskController extends EventEmitter { |
|
|
|
getNetwork: this.networkController.getNetworkState.bind(this), |
|
|
|
getNetwork: this.networkController.getNetworkState.bind(this), |
|
|
|
signTransaction: this.keyringController.signTransaction.bind(this.keyringController), |
|
|
|
signTransaction: this.keyringController.signTransaction.bind(this.keyringController), |
|
|
|
provider: this.provider, |
|
|
|
provider: this.provider, |
|
|
|
blockTracker: this.provider, |
|
|
|
blockTracker: this.blockTracker, |
|
|
|
ethQuery: this.ethQuery, |
|
|
|
ethQuery: this.ethQuery, |
|
|
|
ethStore: this.ethStore, |
|
|
|
ethStore: this.ethStore, |
|
|
|
}) |
|
|
|
}) |
|
|
@ -337,36 +342,43 @@ module.exports = class MetamaskController extends EventEmitter { |
|
|
|
setupUntrustedCommunication (connectionStream, originDomain) { |
|
|
|
setupUntrustedCommunication (connectionStream, originDomain) { |
|
|
|
// Check if new connection is blacklisted
|
|
|
|
// Check if new connection is blacklisted
|
|
|
|
if (this.blacklistController.checkForPhishing(originDomain)) { |
|
|
|
if (this.blacklistController.checkForPhishing(originDomain)) { |
|
|
|
console.log('MetaMask - sending phishing warning for', originDomain) |
|
|
|
log.debug('MetaMask - sending phishing warning for', originDomain) |
|
|
|
this.sendPhishingWarning(connectionStream, originDomain) |
|
|
|
this.sendPhishingWarning(connectionStream, originDomain) |
|
|
|
return |
|
|
|
return |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// setup multiplexing
|
|
|
|
// setup multiplexing
|
|
|
|
const mx = setupMultiplex(connectionStream) |
|
|
|
const mux = setupMultiplex(connectionStream) |
|
|
|
// connect features
|
|
|
|
// connect features
|
|
|
|
this.setupProviderConnection(mx.createStream('provider'), originDomain) |
|
|
|
this.setupProviderConnection(mux.createStream('provider'), originDomain) |
|
|
|
this.setupPublicConfig(mx.createStream('publicConfig')) |
|
|
|
this.setupPublicConfig(mux.createStream('publicConfig')) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
setupTrustedCommunication (connectionStream, originDomain) { |
|
|
|
setupTrustedCommunication (connectionStream, originDomain) { |
|
|
|
// setup multiplexing
|
|
|
|
// setup multiplexing
|
|
|
|
const mx = setupMultiplex(connectionStream) |
|
|
|
const mux = setupMultiplex(connectionStream) |
|
|
|
// connect features
|
|
|
|
// connect features
|
|
|
|
this.setupControllerConnection(mx.createStream('controller')) |
|
|
|
this.setupControllerConnection(mux.createStream('controller')) |
|
|
|
this.setupProviderConnection(mx.createStream('provider'), originDomain) |
|
|
|
this.setupProviderConnection(mux.createStream('provider'), originDomain) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
sendPhishingWarning (connectionStream, hostname) { |
|
|
|
sendPhishingWarning (connectionStream, hostname) { |
|
|
|
const mx = setupMultiplex(connectionStream) |
|
|
|
const mux = setupMultiplex(connectionStream) |
|
|
|
const phishingStream = mx.createStream('phishing') |
|
|
|
const phishingStream = mux.createStream('phishing') |
|
|
|
phishingStream.write({ hostname }) |
|
|
|
phishingStream.write({ hostname }) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
setupControllerConnection (outStream) { |
|
|
|
setupControllerConnection (outStream) { |
|
|
|
const api = this.getApi() |
|
|
|
const api = this.getApi() |
|
|
|
const dnode = Dnode(api) |
|
|
|
const dnode = Dnode(api) |
|
|
|
outStream.pipe(dnode).pipe(outStream) |
|
|
|
pump( |
|
|
|
|
|
|
|
outStream, |
|
|
|
|
|
|
|
dnode, |
|
|
|
|
|
|
|
outStream, |
|
|
|
|
|
|
|
(err) => { |
|
|
|
|
|
|
|
if (err) log.error(err) |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
) |
|
|
|
dnode.on('remote', (remote) => { |
|
|
|
dnode.on('remote', (remote) => { |
|
|
|
// push updates to popup
|
|
|
|
// push updates to popup
|
|
|
|
const sendUpdate = remote.sendUpdate.bind(remote) |
|
|
|
const sendUpdate = remote.sendUpdate.bind(remote) |
|
|
@ -374,27 +386,42 @@ module.exports = class MetamaskController extends EventEmitter { |
|
|
|
}) |
|
|
|
}) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
setupProviderConnection (outStream, originDomain) { |
|
|
|
setupProviderConnection (outStream, origin) { |
|
|
|
streamIntoProvider(outStream, this.provider, onRequest, onResponse) |
|
|
|
// setup json rpc engine stack
|
|
|
|
// append dapp origin domain to request
|
|
|
|
const engine = new RpcEngine() |
|
|
|
function onRequest (request) { |
|
|
|
|
|
|
|
request.origin = originDomain |
|
|
|
// create filter polyfill middleware
|
|
|
|
} |
|
|
|
const filterMiddleware = createFilterMiddleware({ |
|
|
|
// log rpc activity
|
|
|
|
provider: this.provider, |
|
|
|
function onResponse (err, request, response) { |
|
|
|
blockTracker: this.blockTracker, |
|
|
|
if (err) return console.error(err) |
|
|
|
}) |
|
|
|
if (response.error) { |
|
|
|
|
|
|
|
console.error('Error in RPC response:\n', response) |
|
|
|
engine.push(createOriginMiddleware({ origin })) |
|
|
|
} |
|
|
|
engine.push(createLoggerMiddleware({ origin })) |
|
|
|
if (request.isMetamaskInternal) return |
|
|
|
engine.push(filterMiddleware) |
|
|
|
log.info(`RPC (${originDomain}):`, request, '->', response) |
|
|
|
engine.push(createProviderMiddleware({ provider: this.provider })) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// setup connection
|
|
|
|
|
|
|
|
const providerStream = createEngineStream({ engine }) |
|
|
|
|
|
|
|
pump( |
|
|
|
|
|
|
|
outStream, |
|
|
|
|
|
|
|
providerStream, |
|
|
|
|
|
|
|
outStream, |
|
|
|
|
|
|
|
(err) => { |
|
|
|
|
|
|
|
// cleanup filter polyfill middleware
|
|
|
|
|
|
|
|
filterMiddleware.destroy() |
|
|
|
|
|
|
|
if (err) log.error(err) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
setupPublicConfig (outStream) { |
|
|
|
setupPublicConfig (outStream) { |
|
|
|
pipe( |
|
|
|
pump( |
|
|
|
this.publicConfigStore, |
|
|
|
this.publicConfigStore, |
|
|
|
outStream |
|
|
|
outStream, |
|
|
|
|
|
|
|
(err) => { |
|
|
|
|
|
|
|
if (err) log.error(err) |
|
|
|
|
|
|
|
} |
|
|
|
) |
|
|
|
) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|