diff options
Diffstat (limited to 'app/scripts/lib/inpage-provider.js')
-rw-r--r-- | app/scripts/lib/inpage-provider.js | 130 |
1 files changed, 72 insertions, 58 deletions
diff --git a/app/scripts/lib/inpage-provider.js b/app/scripts/lib/inpage-provider.js index 65354cd3d..92936de2f 100644 --- a/app/scripts/lib/inpage-provider.js +++ b/app/scripts/lib/inpage-provider.js @@ -1,7 +1,8 @@ -const Streams = require('mississippi') -const ObjectMultiplex = require('./obj-multiplex') +const pipe = require('pump') const StreamProvider = require('web3-stream-provider') -const RemoteStore = require('./remote-store.js').RemoteStore +const LocalStorageStore = require('obs-store') +const ObjectMultiplex = require('./obj-multiplex') +const createRandomId = require('./random-id') module.exports = MetamaskInpageProvider @@ -9,64 +10,89 @@ function MetamaskInpageProvider (connectionStream) { const self = this // setup connectionStream multiplexing - var multiStream = ObjectMultiplex() - Streams.pipe(connectionStream, multiStream, connectionStream, function (err) { - console.warn('MetamaskInpageProvider - lost connection to MetaMask') - if (err) throw err - }) - self.multiStream = multiStream - - // subscribe to metamask public config - var publicConfigStore = remoteStoreWithLocalStorageCache('MetaMask-Config') - var storeStream = publicConfigStore.createStream() - Streams.pipe(storeStream, multiStream.createStream('publicConfig'), storeStream, function (err) { - console.warn('MetamaskInpageProvider - lost connection to MetaMask publicConfig') - if (err) throw err - }) - self.publicConfigStore = publicConfigStore + var multiStream = self.multiStream = ObjectMultiplex() + pipe( + connectionStream, + multiStream, + connectionStream, + (err) => logStreamDisconnectWarning('MetaMask', err) + ) + + // subscribe to metamask public config (one-way) + self.publicConfigStore = new LocalStorageStore({ storageKey: 'MetaMask-Config' }) + pipe( + multiStream.createStream('publicConfig'), + self.publicConfigStore, + (err) => logStreamDisconnectWarning('MetaMask PublicConfigStore', err) + ) // connect to async provider - var asyncProvider = new StreamProvider() - Streams.pipe(asyncProvider, multiStream.createStream('provider'), asyncProvider, function (err) { - console.warn('MetamaskInpageProvider - lost connection to MetaMask provider') - if (err) throw err - }) - asyncProvider.on('error', console.error.bind(console)) - self.asyncProvider = asyncProvider + const asyncProvider = self.asyncProvider = new StreamProvider() + pipe( + asyncProvider, + multiStream.createStream('provider'), + asyncProvider, + (err) => logStreamDisconnectWarning('MetaMask RpcProvider', err) + ) + + self.idMap = {} // handle sendAsync requests via asyncProvider - self.sendAsync = function(payload, cb){ + self.sendAsync = function (payload, cb) { // rewrite request ids - var request = jsonrpcMessageTransform(payload, (message) => { - message.id = createRandomId() + var request = eachJsonMessage(payload, (message) => { + var newId = createRandomId() + self.idMap[newId] = message.id + message.id = newId return message }) // forward to asyncProvider - asyncProvider.sendAsync(request, cb) + asyncProvider.sendAsync(request, function (err, res) { + if (err) return cb(err) + // transform messages to original ids + eachJsonMessage(res, (message) => { + var oldId = self.idMap[message.id] + delete self.idMap[message.id] + message.id = oldId + return message + }) + cb(null, res) + }) } } MetamaskInpageProvider.prototype.send = function (payload) { const self = this - + let selectedAddress let result = null switch (payload.method) { case 'eth_accounts': // read from localStorage - selectedAddress = self.publicConfigStore.get('selectedAddress') + selectedAddress = self.publicConfigStore.getState().selectedAddress result = selectedAddress ? [selectedAddress] : [] break case 'eth_coinbase': // read from localStorage - selectedAddress = self.publicConfigStore.get('selectedAddress') - result = selectedAddress || '0x0000000000000000000000000000000000000000' + selectedAddress = self.publicConfigStore.getState().selectedAddress + result = selectedAddress + break + + case 'eth_uninstallFilter': + self.sendAsync(payload, noop) + result = true + break + + case 'net_version': + let networkVersion = self.publicConfigStore.getState().networkVersion + result = networkVersion break // throw not-supported Error default: - var message = 'The MetaMask Web3 object does not support synchronous methods. See https://github.com/MetaMask/faq/blob/master/DEVELOPERS.md#all-async---think-of-metamask-as-a-light-client for details.' + var link = 'https://github.com/MetaMask/faq/blob/master/DEVELOPERS.md#dizzy-all-async---think-of-metamask-as-a-light-client' + var message = `The MetaMask Web3 object does not support synchronous methods like ${payload.method} without a callback parameter. See ${link} for details.` throw new Error(message) } @@ -87,34 +113,22 @@ MetamaskInpageProvider.prototype.isConnected = function () { return true } -// util - -function remoteStoreWithLocalStorageCache (storageKey) { - // read local cache - var initState = JSON.parse(localStorage[storageKey] || '{}') - var store = new RemoteStore(initState) - // cache the latest state locally - store.subscribe(function (state) { - localStorage[storageKey] = JSON.stringify(state) - }) - - return store -} +MetamaskInpageProvider.prototype.isMetaMask = true -function createRandomId(){ - const extraDigits = 3 - // 13 time digits - const datePart = new Date().getTime() * Math.pow(10, extraDigits) - // 3 random digits - const extraPart = Math.floor(Math.random() * Math.pow(10, extraDigits)) - // 16 digits - return datePart + extraPart -} +// util -function jsonrpcMessageTransform(payload, transformFn){ +function eachJsonMessage (payload, transformFn) { if (Array.isArray(payload)) { return payload.map(transformFn) } else { return transformFn(payload) } -}
\ No newline at end of file +} + +function logStreamDisconnectWarning(remoteLabel, err){ + let warningMsg = `MetamaskInpageProvider - lost connection to ${remoteLabel}` + if (err) warningMsg += '\n' + err.stack + console.warn(warningMsg) +} + +function noop () {} |