2017-09-08 06:19:24 +02:00
const pump = require ( 'pump' )
2017-08-25 00:44:40 +02:00
const RpcEngine = require ( 'json-rpc-engine' )
2018-05-14 14:33:47 +02:00
const createErrorMiddleware = require ( './createErrorMiddleware' )
2017-09-07 19:08:07 +02:00
const createIdRemapMiddleware = require ( 'json-rpc-engine/src/idRemapMiddleware' )
2017-08-25 00:44:40 +02:00
const createStreamMiddleware = require ( 'json-rpc-middleware-stream' )
2017-01-25 04:47:00 +01:00
const LocalStorageStore = require ( 'obs-store' )
2017-11-28 22:09:18 +01:00
const asStream = require ( 'obs-store/lib/asStream' )
2017-09-08 07:47:08 +02:00
const ObjectMultiplex = require ( 'obj-multiplex' )
2016-05-23 00:23:16 +02:00
module . exports = MetamaskInpageProvider
2016-06-21 22:18:32 +02:00
function MetamaskInpageProvider ( connectionStream ) {
2016-05-23 00:23:16 +02:00
const self = this
2016-06-21 22:18:32 +02:00
// setup connectionStream multiplexing
2017-09-08 07:47:08 +02:00
const mux = self . mux = new ObjectMultiplex ( )
2017-09-08 06:19:24 +02:00
pump (
2017-01-25 04:47:00 +01:00
connectionStream ,
2017-09-08 07:47:08 +02:00
mux ,
2017-01-25 04:47:00 +01:00
connectionStream ,
( err ) => logStreamDisconnectWarning ( 'MetaMask' , err )
)
// subscribe to metamask public config (one-way)
self . publicConfigStore = new LocalStorageStore ( { storageKey : 'MetaMask-Config' } )
2017-11-28 22:09:18 +01:00
2017-09-08 06:19:24 +02:00
pump (
2017-09-08 07:47:08 +02:00
mux . createStream ( 'publicConfig' ) ,
2017-11-28 22:09:18 +01:00
asStream ( self . publicConfigStore ) ,
2017-01-25 04:47:00 +01:00
( err ) => logStreamDisconnectWarning ( 'MetaMask PublicConfigStore' , err )
)
2016-05-23 00:23:16 +02:00
2017-08-02 23:26:10 +02:00
// ignore phishing warning message (handled elsewhere)
2017-09-08 07:47:08 +02:00
mux . ignoreStream ( 'phishing' )
2017-08-02 23:26:10 +02:00
2016-05-23 00:23:16 +02:00
// connect to async provider
2017-08-25 00:44:40 +02:00
const streamMiddleware = createStreamMiddleware ( )
2017-09-08 06:19:24 +02:00
pump (
2017-08-25 00:44:40 +02:00
streamMiddleware . stream ,
2017-09-08 07:47:08 +02:00
mux . createStream ( 'provider' ) ,
2017-08-25 00:44:40 +02:00
streamMiddleware . stream ,
2017-01-25 04:47:00 +01:00
( err ) => logStreamDisconnectWarning ( 'MetaMask RpcProvider' , err )
)
2017-05-21 05:37:47 +02:00
2017-08-25 00:44:40 +02:00
// handle sendAsync requests via dapp-side rpc engine
2017-09-11 23:21:09 +02:00
const rpcEngine = new RpcEngine ( )
rpcEngine . push ( createIdRemapMiddleware ( ) )
2018-05-14 14:33:47 +02:00
rpcEngine . push ( createErrorMiddleware ( ) )
2017-09-11 23:21:09 +02:00
rpcEngine . push ( streamMiddleware )
self . rpcEngine = rpcEngine
2017-09-08 20:52:00 +02:00
}
2017-08-25 00:44:40 +02:00
2017-09-08 20:52:00 +02:00
// handle sendAsync requests via asyncProvider
// also remap ids inbound and outbound
MetamaskInpageProvider . prototype . sendAsync = function ( payload , cb ) {
const self = this
2018-07-27 21:23:05 +02:00
if ( payload . method === 'eth_signTypedData' ) {
console . warn ( 'MetaMask: This experimental version of eth_signTypedData will be deprecated in the next release in favor of the standard as defined in EIP-712. See https://git.io/fNzPl for more information on the new standard.' )
}
2017-09-11 23:21:09 +02:00
self . rpcEngine . handle ( payload , cb )
2016-05-23 00:23:16 +02:00
}
2017-09-08 20:52:00 +02:00
2016-06-21 22:18:32 +02:00
MetamaskInpageProvider . prototype . send = function ( payload ) {
2016-05-23 00:23:16 +02:00
const self = this
2016-10-05 20:10:39 +02:00
2017-01-31 00:25:12 +01:00
let selectedAddress
2016-08-11 22:31:00 +02:00
let result = null
2016-05-23 00:23:16 +02:00
switch ( payload . method ) {
case 'eth_accounts' :
// read from localStorage
2017-01-31 00:25:12 +01:00
selectedAddress = self . publicConfigStore . getState ( ) . selectedAddress
result = selectedAddress ? [ selectedAddress ] : [ ]
2016-05-23 00:23:16 +02:00
break
case 'eth_coinbase' :
// read from localStorage
2017-01-31 00:25:12 +01:00
selectedAddress = self . publicConfigStore . getState ( ) . selectedAddress
2017-08-24 01:13:33 +02:00
result = selectedAddress || null
2016-05-23 00:23:16 +02:00
break
2016-11-23 19:48:20 +01:00
case 'eth_uninstallFilter' :
self . sendAsync ( payload , noop )
result = true
break
2017-02-09 00:51:22 +01:00
case 'net_version' :
2017-04-27 06:05:45 +02:00
const networkVersion = self . publicConfigStore . getState ( ) . networkVersion
2017-08-28 19:41:01 +02:00
result = networkVersion || null
2017-02-09 00:51:22 +01:00
break
2016-08-11 22:23:49 +02:00
// throw not-supported Error
2016-05-23 00:23:16 +02:00
default :
2016-10-05 20:10:39 +02:00
var link = 'https://github.com/MetaMask/faq/blob/master/DEVELOPERS.md#dizzy-all-async---think-of-metamask-as-a-light-client'
2016-10-20 00:16:27 +02:00
var message = ` The MetaMask Web3 object does not support synchronous methods like ${ payload . method } without a callback parameter. See ${ link } for details. `
2016-08-11 22:23:49 +02:00
throw new Error ( message )
2016-05-23 00:23:16 +02:00
}
// return the result
return {
id : payload . id ,
jsonrpc : payload . jsonrpc ,
result : result ,
}
}
2016-06-21 22:18:32 +02:00
MetamaskInpageProvider . prototype . isConnected = function ( ) {
2016-05-23 00:23:16 +02:00
return true
}
2017-01-02 21:20:09 +01:00
MetamaskInpageProvider . prototype . isMetaMask = true
2016-05-23 00:23:16 +02:00
// util
2017-04-27 06:05:45 +02:00
function logStreamDisconnectWarning ( remoteLabel , err ) {
2017-01-25 04:47:00 +01:00
let warningMsg = ` MetamaskInpageProvider - lost connection to ${ remoteLabel } `
if ( err ) warningMsg += '\n' + err . stack
console . warn ( warningMsg )
}
2016-11-23 19:48:20 +01:00
function noop ( ) { }