nifty-wallet/app/scripts/lib/inpage-provider.js

132 lines
4.0 KiB
JavaScript
Raw Normal View History

2016-05-22 15:23:16 -07:00
const HttpProvider = require('web3/lib/web3/httpprovider')
const Streams = require('mississippi')
const ObjectMultiplex = require('./obj-multiplex')
2016-05-22 18:02:27 -07:00
const StreamProvider = require('web3-stream-provider')
2016-05-22 15:23:16 -07:00
const RemoteStore = require('./remote-store.js').RemoteStore
const MetamaskConfig = require('../config.js')
module.exports = MetamaskInpageProvider
2016-06-21 13:18:32 -07:00
function MetamaskInpageProvider (connectionStream) {
2016-05-22 15:23:16 -07:00
const self = this
2016-06-21 13:18:32 -07:00
// setup connectionStream multiplexing
2016-05-22 15:23:16 -07:00
var multiStream = ObjectMultiplex()
2016-06-21 13:18:32 -07:00
Streams.pipe(connectionStream, multiStream, connectionStream, function (err) {
2016-05-22 15:23:16 -07:00
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()
2016-06-21 13:18:32 -07:00
Streams.pipe(storeStream, multiStream.createStream('publicConfig'), storeStream, function (err) {
2016-05-22 15:23:16 -07:00
console.warn('MetamaskInpageProvider - lost connection to MetaMask publicConfig')
if (err) throw err
})
self.publicConfigStore = publicConfigStore
// connect to sync provider
self.syncProvider = createSyncProvider(publicConfigStore.get('provider'))
// subscribe to publicConfig to update the syncProvider on change
2016-06-21 13:18:32 -07:00
publicConfigStore.subscribe(function (state) {
2016-05-22 15:23:16 -07:00
self.syncProvider = createSyncProvider(state.provider)
})
// connect to async provider
var asyncProvider = new StreamProvider()
2016-06-21 13:18:32 -07:00
Streams.pipe(asyncProvider, multiStream.createStream('provider'), asyncProvider, function (err) {
2016-05-22 15:23:16 -07:00
console.warn('MetamaskInpageProvider - lost connection to MetaMask provider')
if (err) throw err
})
asyncProvider.on('error', console.error.bind(console))
self.asyncProvider = asyncProvider
// overwrite own sendAsync method
self.sendAsync = asyncProvider.sendAsync.bind(asyncProvider)
}
2016-06-21 13:18:32 -07:00
MetamaskInpageProvider.prototype.send = function (payload) {
2016-05-22 15:23:16 -07:00
const self = this
2016-06-21 13:56:04 -07:00
let selectedAddress
2016-05-22 15:23:16 -07:00
var result = null
switch (payload.method) {
case 'eth_accounts':
// read from localStorage
2016-06-21 13:56:04 -07:00
selectedAddress = self.publicConfigStore.get('selectedAddress')
2016-05-22 15:23:16 -07:00
result = selectedAddress ? [selectedAddress] : []
break
case 'eth_coinbase':
// read from localStorage
2016-06-21 13:56:04 -07:00
selectedAddress = self.publicConfigStore.get('selectedAddress')
2016-05-22 15:23:16 -07:00
result = selectedAddress || '0x0000000000000000000000000000000000000000'
break
// fallback to normal rpc
default:
return self.syncProvider.send(payload)
}
// return the result
return {
id: payload.id,
jsonrpc: payload.jsonrpc,
result: result,
}
}
2016-06-21 13:18:32 -07:00
MetamaskInpageProvider.prototype.sendAsync = function () {
2016-05-22 15:23:16 -07:00
throw new Error('MetamaskInpageProvider - sendAsync not overwritten')
}
2016-06-21 13:18:32 -07:00
MetamaskInpageProvider.prototype.isConnected = function () {
2016-05-22 15:23:16 -07:00
return true
}
// util
2016-06-21 13:18:32 -07:00
function createSyncProvider (providerConfig) {
2016-05-22 15:23:16 -07:00
providerConfig = providerConfig || {}
2016-06-21 13:56:04 -07:00
let syncProviderUrl
2016-05-22 15:23:16 -07:00
if (providerConfig.rpcTarget) {
syncProviderUrl = providerConfig.rpcTarget
} else {
2016-06-21 13:18:32 -07:00
switch (providerConfig.type) {
2016-05-22 15:23:16 -07:00
case 'testnet':
syncProviderUrl = MetamaskConfig.network.testnet
break
case 'mainnet':
syncProviderUrl = MetamaskConfig.network.mainnet
break
default:
syncProviderUrl = MetamaskConfig.network.default
}
}
const provider = new HttpProvider(syncProviderUrl)
// Stubbing out the send method to throw on sync methods:
provider.send = function() {
var message = 'The MetaMask Web3 object does not support synchronous methods. See https://github.com/MetaMask/faq#all-async---think-of-metamask-as-a-light-client for details.'
throw new Error(message)
}
return provider
2016-05-22 15:23:16 -07:00
}
2016-06-21 13:18:32 -07:00
function remoteStoreWithLocalStorageCache (storageKey) {
2016-05-22 15:23:16 -07:00
// read local cache
var initState = JSON.parse(localStorage[storageKey] || '{}')
var store = new RemoteStore(initState)
// cache the latest state locally
2016-06-21 13:18:32 -07:00
store.subscribe(function (state) {
2016-05-22 15:23:16 -07:00
localStorage[storageKey] = JSON.stringify(state)
})
return store
2016-06-21 13:18:32 -07:00
}