mirror of
https://github.com/kremalicious/metamask-extension.git
synced 2024-12-23 01:39:44 +01:00
Merge pull request #113 from MetaMask/i53
publicConfigStore for sync provider and selected address
This commit is contained in:
commit
83b8741bbb
@ -9,8 +9,8 @@ const MetaMaskProvider = require('./lib/zero.js')
|
|||||||
const IdentityStore = require('./lib/idStore')
|
const IdentityStore = require('./lib/idStore')
|
||||||
const createTxNotification = require('./lib/tx-notification.js')
|
const createTxNotification = require('./lib/tx-notification.js')
|
||||||
const configManager = require('./lib/config-manager-singleton')
|
const configManager = require('./lib/config-manager-singleton')
|
||||||
const jsonParseStream = require('./lib/stream-utils.js').jsonParseStream
|
const setupMultiplex = require('./lib/stream-utils.js').setupMultiplex
|
||||||
const jsonStringifyStream = require('./lib/stream-utils.js').jsonStringifyStream
|
const HostStore = require('./lib/remote-store.js').HostStore
|
||||||
|
|
||||||
//
|
//
|
||||||
// connect to other contexts
|
// connect to other contexts
|
||||||
@ -22,15 +22,27 @@ function connectRemote(remotePort){
|
|||||||
var portStream = new PortStream(remotePort)
|
var portStream = new PortStream(remotePort)
|
||||||
if (isMetaMaskInternalProcess) {
|
if (isMetaMaskInternalProcess) {
|
||||||
// communication with popup
|
// communication with popup
|
||||||
handleInternalCommunication(portStream)
|
setupTrustedCommunication(portStream)
|
||||||
} else {
|
} else {
|
||||||
// communication with page
|
// communication with page
|
||||||
handleEthRpcRequestStream(portStream)
|
setupUntrustedCommunication(portStream)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function handleEthRpcRequestStream(stream){
|
function setupUntrustedCommunication(connectionStream){
|
||||||
stream.on('data', onRpcRequest.bind(null, stream))
|
// setup multiplexing
|
||||||
|
var mx = setupMultiplex(connectionStream)
|
||||||
|
// connect features
|
||||||
|
setupProviderConnection(mx.createStream('provider'))
|
||||||
|
setupPublicConfig(mx.createStream('publicConfig'))
|
||||||
|
}
|
||||||
|
|
||||||
|
function setupTrustedCommunication(connectionStream){
|
||||||
|
// setup multiplexing
|
||||||
|
var mx = setupMultiplex(connectionStream)
|
||||||
|
// connect features
|
||||||
|
setupControllerConnection(mx.createStream('controller'))
|
||||||
|
setupProviderConnection(mx.createStream('provider'))
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
@ -68,6 +80,47 @@ function getState(){
|
|||||||
return state
|
return state
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// public store
|
||||||
|
//
|
||||||
|
|
||||||
|
// get init state
|
||||||
|
var initPublicState = extend(
|
||||||
|
idStoreToPublic(idStore.getState()),
|
||||||
|
configToPublic(configManager.getConfig())
|
||||||
|
)
|
||||||
|
|
||||||
|
var publicConfigStore = new HostStore(initPublicState)
|
||||||
|
|
||||||
|
// subscribe to changes
|
||||||
|
configManager.subscribe(function(state){
|
||||||
|
storeSetFromObj(publicConfigStore, configToPublic(state))
|
||||||
|
})
|
||||||
|
idStore.on('update', function(state){
|
||||||
|
storeSetFromObj(publicConfigStore, idStoreToPublic(state))
|
||||||
|
})
|
||||||
|
|
||||||
|
// idStore substate
|
||||||
|
function idStoreToPublic(state){
|
||||||
|
return {
|
||||||
|
selectedAddress: state.selectedAddress,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// config substate
|
||||||
|
function configToPublic(state){
|
||||||
|
return {
|
||||||
|
provider: state.provider,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// dump obj into store
|
||||||
|
function storeSetFromObj(store, obj){
|
||||||
|
Object.keys(obj).forEach(function(key){
|
||||||
|
store.set(key, obj[key])
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// handle rpc requests
|
// handle rpc requests
|
||||||
function onRpcRequest(remoteStream, payload){
|
function onRpcRequest(remoteStream, payload){
|
||||||
// console.log('MetaMaskPlugin - incoming payload:', payload)
|
// console.log('MetaMaskPlugin - incoming payload:', payload)
|
||||||
@ -84,27 +137,20 @@ function onRpcRequest(remoteStream, payload){
|
|||||||
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// popup integration
|
// remote features
|
||||||
//
|
//
|
||||||
|
|
||||||
function handleInternalCommunication(portStream){
|
function setupPublicConfig(stream){
|
||||||
// setup multiplexing
|
var storeStream = publicConfigStore.createStream()
|
||||||
var mx = ObjectMultiplex()
|
stream.pipe(storeStream).pipe(stream)
|
||||||
portStream.pipe(mx).pipe(portStream)
|
|
||||||
mx.on('error', function(err) {
|
|
||||||
console.error(err)
|
|
||||||
// portStream.destroy()
|
|
||||||
})
|
|
||||||
portStream.on('error', function(err) {
|
|
||||||
console.error(err)
|
|
||||||
mx.destroy()
|
|
||||||
})
|
|
||||||
linkDnode(mx.createStream('dnode'))
|
|
||||||
handleEthRpcRequestStream(mx.createStream('provider'))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function linkDnode(stream){
|
function setupProviderConnection(stream){
|
||||||
var connection = Dnode({
|
stream.on('data', onRpcRequest.bind(null, stream))
|
||||||
|
}
|
||||||
|
|
||||||
|
function setupControllerConnection(stream){
|
||||||
|
var dnode = Dnode({
|
||||||
getState: function(cb){ cb(null, getState()) },
|
getState: function(cb){ cb(null, getState()) },
|
||||||
setRpcTarget: setRpcTarget,
|
setRpcTarget: setRpcTarget,
|
||||||
useEtherscanProvider: useEtherscanProvider,
|
useEtherscanProvider: useEtherscanProvider,
|
||||||
@ -119,8 +165,8 @@ function linkDnode(stream){
|
|||||||
clearSeedWordCache: idStore.clearSeedWordCache.bind(idStore),
|
clearSeedWordCache: idStore.clearSeedWordCache.bind(idStore),
|
||||||
exportAccount: idStore.exportAccount.bind(idStore),
|
exportAccount: idStore.exportAccount.bind(idStore),
|
||||||
})
|
})
|
||||||
stream.pipe(connection).pipe(stream)
|
stream.pipe(dnode).pipe(stream)
|
||||||
connection.on('remote', function(remote){
|
dnode.on('remote', function(remote){
|
||||||
|
|
||||||
// push updates to popup
|
// push updates to popup
|
||||||
ethStore.on('update', sendUpdate)
|
ethStore.on('update', sendUpdate)
|
||||||
|
@ -1,31 +1,42 @@
|
|||||||
const XHR = window.XMLHttpRequest
|
|
||||||
|
|
||||||
// bring in web3 but rename on window
|
|
||||||
const Web3 = require('web3')
|
|
||||||
delete window.Web3
|
|
||||||
window.MetamaskWeb3 = Web3
|
|
||||||
|
|
||||||
const createPayload = require('web3-provider-engine/util/create-payload')
|
const createPayload = require('web3-provider-engine/util/create-payload')
|
||||||
const StreamProvider = require('./lib/stream-provider.js')
|
const StreamProvider = require('./lib/stream-provider.js')
|
||||||
const LocalMessageDuplexStream = require('./lib/local-message-stream.js')
|
const LocalMessageDuplexStream = require('./lib/local-message-stream.js')
|
||||||
|
const setupMultiplex = require('./lib/stream-utils.js').setupMultiplex
|
||||||
|
const RemoteStore = require('./lib/remote-store.js').RemoteStore
|
||||||
|
const Web3 = require('web3')
|
||||||
|
|
||||||
const RPC_URL = 'https://testrpc.metamask.io/'
|
// rename on window
|
||||||
|
delete window.Web3
|
||||||
|
window.MetamaskWeb3 = Web3
|
||||||
|
|
||||||
|
const DEFAULT_RPC_URL = 'https://rpc.metamask.io/'
|
||||||
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// setup plugin communication
|
// setup plugin communication
|
||||||
//
|
//
|
||||||
|
|
||||||
|
// setup background connection
|
||||||
var pluginStream = new LocalMessageDuplexStream({
|
var pluginStream = new LocalMessageDuplexStream({
|
||||||
name: 'inpage',
|
name: 'inpage',
|
||||||
target: 'contentscript',
|
target: 'contentscript',
|
||||||
})
|
})
|
||||||
|
var mx = setupMultiplex(pluginStream)
|
||||||
|
// connect features
|
||||||
var remoteProvider = new StreamProvider()
|
var remoteProvider = new StreamProvider()
|
||||||
remoteProvider.pipe(pluginStream).pipe(remoteProvider)
|
remoteProvider.pipe(mx.createStream('provider')).pipe(remoteProvider)
|
||||||
|
|
||||||
pluginStream.on('error', console.error.bind(console))
|
|
||||||
remoteProvider.on('error', console.error.bind(console))
|
remoteProvider.on('error', console.error.bind(console))
|
||||||
|
|
||||||
|
var initState = JSON.parse(localStorage['MetaMask-Config'] || '{}')
|
||||||
|
var publicConfigStore = new RemoteStore(initState)
|
||||||
|
var storeStream = publicConfigStore.createStream()
|
||||||
|
storeStream.pipe(mx.createStream('publicConfig')).pipe(storeStream)
|
||||||
|
|
||||||
|
publicConfigStore.subscribe(function(state){
|
||||||
|
localStorage['MetaMask-Config'] = JSON.stringify(state)
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// global web3
|
// global web3
|
||||||
//
|
//
|
||||||
@ -42,42 +53,39 @@ console.log('MetaMask - injected web3')
|
|||||||
// handle synchronous requests
|
// handle synchronous requests
|
||||||
//
|
//
|
||||||
|
|
||||||
// handle accounts cache
|
global.publicConfigStore = publicConfigStore
|
||||||
var accountsCache = JSON.parse(localStorage['MetaMask-Accounts'] || '[]')
|
|
||||||
web3.eth.defaultAccount = accountsCache[0]
|
|
||||||
|
|
||||||
setInterval(populateAccountsCache, 4000)
|
// set web3 defaultAcount
|
||||||
function populateAccountsCache(){
|
publicConfigStore.subscribe(function(state){
|
||||||
remoteProvider.sendAsync(createPayload({
|
web3.eth.defaultAccount = state.selectedAddress
|
||||||
method: 'eth_accounts',
|
})
|
||||||
params: [],
|
|
||||||
isMetamaskInternal: true,
|
|
||||||
}), function(err, response){
|
|
||||||
if (err) return console.error('MetaMask - Error polling accounts')
|
|
||||||
// update localStorage
|
|
||||||
var accounts = response.result
|
|
||||||
if (accounts.toString() !== accountsCache.toString()) {
|
|
||||||
accountsCache = accounts
|
|
||||||
web3.eth.defaultAccount = accountsCache[0]
|
|
||||||
localStorage['MetaMask-Accounts'] = JSON.stringify(accounts)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// handle synchronous methods via standard http provider
|
// setup sync http provider
|
||||||
var syncProvider = new Web3.providers.HttpProvider(RPC_URL)
|
var providerConfig = publicConfigStore.get('provider') || {}
|
||||||
|
var providerUrl = providerConfig.rpcTarget ? providerConfig.rpcTarget : DEFAULT_RPC_URL
|
||||||
|
var syncProvider = new Web3.providers.HttpProvider(providerUrl)
|
||||||
|
publicConfigStore.subscribe(function(state){
|
||||||
|
if (!state.provider) return
|
||||||
|
if (!state.provider.rpcTarget || state.provider.rpcTarget === providerUrl) return
|
||||||
|
providerUrl = state.provider.rpcTarget
|
||||||
|
syncProvider = new Web3.providers.HttpProvider(providerUrl)
|
||||||
|
})
|
||||||
|
|
||||||
|
// handle sync methods
|
||||||
remoteProvider.send = function(payload){
|
remoteProvider.send = function(payload){
|
||||||
var result = null
|
var result = null
|
||||||
switch (payload.method) {
|
switch (payload.method) {
|
||||||
|
|
||||||
case 'eth_accounts':
|
case 'eth_accounts':
|
||||||
// read from localStorage
|
// read from localStorage
|
||||||
result = accountsCache
|
var selectedAddress = publicConfigStore.get('selectedAddress')
|
||||||
|
result = selectedAddress ? [selectedAddress] : []
|
||||||
break
|
break
|
||||||
|
|
||||||
case 'eth_coinbase':
|
case 'eth_coinbase':
|
||||||
// read from localStorage
|
// read from localStorage
|
||||||
result = accountsCache[0] || '0x0000000000000000000000000000000000000000'
|
var selectedAddress = publicConfigStore.get('selectedAddress')
|
||||||
|
result = selectedAddress || '0x0000000000000000000000000000000000000000'
|
||||||
break
|
break
|
||||||
|
|
||||||
// fallback to normal rpc
|
// fallback to normal rpc
|
||||||
|
@ -15,6 +15,8 @@ const migrations = require('./migrations')
|
|||||||
*/
|
*/
|
||||||
module.exports = ConfigManager
|
module.exports = ConfigManager
|
||||||
function ConfigManager() {
|
function ConfigManager() {
|
||||||
|
// ConfigManager is observable and will emit updates
|
||||||
|
this._subs = []
|
||||||
|
|
||||||
/* The migrator exported on the config-manager
|
/* The migrator exported on the config-manager
|
||||||
* has two methods the user should be concerned with:
|
* has two methods the user should be concerned with:
|
||||||
@ -47,6 +49,7 @@ ConfigManager.prototype.setConfig = function(config) {
|
|||||||
var data = this.migrator.getData()
|
var data = this.migrator.getData()
|
||||||
data.config = config
|
data.config = config
|
||||||
this.setData(data)
|
this.setData(data)
|
||||||
|
this._emitUpdates(config)
|
||||||
}
|
}
|
||||||
|
|
||||||
ConfigManager.prototype.getConfig = function() {
|
ConfigManager.prototype.getConfig = function() {
|
||||||
@ -127,6 +130,30 @@ ConfigManager.prototype.clearWallet = function() {
|
|||||||
this.setData(data)
|
this.setData(data)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ConfigManager.prototype.setData = function(data) {
|
||||||
|
this.migrator.saveData(data)
|
||||||
|
}
|
||||||
|
|
||||||
|
// observable
|
||||||
|
|
||||||
|
ConfigManager.prototype.subscribe = function(fn){
|
||||||
|
this._subs.push(fn)
|
||||||
|
var unsubscribe = this.unsubscribe.bind(this, fn)
|
||||||
|
return unsubscribe
|
||||||
|
}
|
||||||
|
|
||||||
|
ConfigManager.prototype.unsubscribe = function(fn){
|
||||||
|
var index = this._subs.indexOf(fn)
|
||||||
|
if (index !== -1) this._subs.splice(index, 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
ConfigManager.prototype._emitUpdates = function(state){
|
||||||
|
this._subs.forEach(function(handler){
|
||||||
|
handler(state)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
function loadData() {
|
function loadData() {
|
||||||
|
|
||||||
var oldData = getOldStyleData()
|
var oldData = getOldStyleData()
|
||||||
|
@ -11,7 +11,7 @@ function ObjectMultiplex(opts){
|
|||||||
var data = chunk.data
|
var data = chunk.data
|
||||||
var substream = mx.streams[name]
|
var substream = mx.streams[name]
|
||||||
if (!substream) {
|
if (!substream) {
|
||||||
console.warn("orphaned data for stream " + name)
|
console.warn('orphaned data for stream ' + name)
|
||||||
} else {
|
} else {
|
||||||
substream.push(data)
|
substream.push(data)
|
||||||
}
|
}
|
||||||
|
97
app/scripts/lib/remote-store.js
Normal file
97
app/scripts/lib/remote-store.js
Normal file
@ -0,0 +1,97 @@
|
|||||||
|
const Dnode = require('dnode')
|
||||||
|
const inherits = require('util').inherits
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
HostStore: HostStore,
|
||||||
|
RemoteStore: RemoteStore,
|
||||||
|
}
|
||||||
|
|
||||||
|
function BaseStore(initState){
|
||||||
|
this._state = initState || {}
|
||||||
|
this._subs = []
|
||||||
|
}
|
||||||
|
|
||||||
|
BaseStore.prototype.set = function(key, value){
|
||||||
|
throw Error('Not implemented.')
|
||||||
|
}
|
||||||
|
|
||||||
|
BaseStore.prototype.get = function(key){
|
||||||
|
return this._state[key]
|
||||||
|
}
|
||||||
|
|
||||||
|
BaseStore.prototype.subscribe = function(fn){
|
||||||
|
this._subs.push(fn)
|
||||||
|
var unsubscribe = this.unsubscribe.bind(this, fn)
|
||||||
|
return unsubscribe
|
||||||
|
}
|
||||||
|
|
||||||
|
BaseStore.prototype.unsubscribe = function(fn){
|
||||||
|
var index = this._subs.indexOf(fn)
|
||||||
|
if (index !== -1) this._subs.splice(index, 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
BaseStore.prototype._emitUpdates = function(state){
|
||||||
|
this._subs.forEach(function(handler){
|
||||||
|
handler(state)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// host
|
||||||
|
//
|
||||||
|
|
||||||
|
inherits(HostStore, BaseStore)
|
||||||
|
function HostStore(initState, opts){
|
||||||
|
BaseStore.call(this, initState)
|
||||||
|
}
|
||||||
|
|
||||||
|
HostStore.prototype.set = function(key, value){
|
||||||
|
this._state[key] = value
|
||||||
|
process.nextTick(this._emitUpdates.bind(this, this._state))
|
||||||
|
}
|
||||||
|
|
||||||
|
HostStore.prototype.createStream = function(){
|
||||||
|
var dnode = Dnode({
|
||||||
|
// update: this._didUpdate.bind(this),
|
||||||
|
})
|
||||||
|
dnode.on('remote', this._didConnect.bind(this))
|
||||||
|
return dnode
|
||||||
|
}
|
||||||
|
|
||||||
|
HostStore.prototype._didConnect = function(remote){
|
||||||
|
this.subscribe(function(state){
|
||||||
|
remote.update(state)
|
||||||
|
})
|
||||||
|
remote.update(this._state)
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// remote
|
||||||
|
//
|
||||||
|
|
||||||
|
inherits(RemoteStore, BaseStore)
|
||||||
|
function RemoteStore(initState, opts){
|
||||||
|
BaseStore.call(this, initState)
|
||||||
|
this._remote = null
|
||||||
|
}
|
||||||
|
|
||||||
|
RemoteStore.prototype.set = function(key, value){
|
||||||
|
this._remote.set(key, value)
|
||||||
|
}
|
||||||
|
|
||||||
|
RemoteStore.prototype.createStream = function(){
|
||||||
|
var dnode = Dnode({
|
||||||
|
update: this._didUpdate.bind(this),
|
||||||
|
})
|
||||||
|
dnode.once('remote', this._didConnect.bind(this))
|
||||||
|
return dnode
|
||||||
|
}
|
||||||
|
|
||||||
|
RemoteStore.prototype._didConnect = function(remote){
|
||||||
|
this._remote = remote
|
||||||
|
}
|
||||||
|
|
||||||
|
RemoteStore.prototype._didUpdate = function(state){
|
||||||
|
this._state = state
|
||||||
|
this._emitUpdates(state)
|
||||||
|
}
|
@ -1,9 +1,11 @@
|
|||||||
const Through = require('through2')
|
const Through = require('through2')
|
||||||
|
const ObjectMultiplex = require('./obj-multiplex')
|
||||||
|
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
jsonParseStream: jsonParseStream,
|
jsonParseStream: jsonParseStream,
|
||||||
jsonStringifyStream: jsonStringifyStream,
|
jsonStringifyStream: jsonStringifyStream,
|
||||||
|
setupMultiplex: setupMultiplex,
|
||||||
}
|
}
|
||||||
|
|
||||||
function jsonParseStream(){
|
function jsonParseStream(){
|
||||||
@ -19,3 +21,17 @@ function jsonStringifyStream(){
|
|||||||
cb()
|
cb()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function setupMultiplex(connectionStream){
|
||||||
|
var mx = ObjectMultiplex()
|
||||||
|
connectionStream.pipe(mx).pipe(connectionStream)
|
||||||
|
mx.on('error', function(err) {
|
||||||
|
console.error(err)
|
||||||
|
// connectionStream.destroy()
|
||||||
|
})
|
||||||
|
connectionStream.on('error', function(err) {
|
||||||
|
console.error(err)
|
||||||
|
mx.destroy()
|
||||||
|
})
|
||||||
|
return mx
|
||||||
|
}
|
@ -1,7 +1,6 @@
|
|||||||
const url = require('url')
|
const url = require('url')
|
||||||
const EventEmitter = require('events').EventEmitter
|
const EventEmitter = require('events').EventEmitter
|
||||||
const async = require('async')
|
const async = require('async')
|
||||||
const ObjectMultiplex = require('./lib/obj-multiplex')
|
|
||||||
const Dnode = require('dnode')
|
const Dnode = require('dnode')
|
||||||
const Web3 = require('web3')
|
const Web3 = require('web3')
|
||||||
const MetaMaskUi = require('../../ui')
|
const MetaMaskUi = require('../../ui')
|
||||||
@ -9,6 +8,7 @@ const MetaMaskUiCss = require('../../ui/css')
|
|||||||
const injectCss = require('inject-css')
|
const injectCss = require('inject-css')
|
||||||
const PortStream = require('./lib/port-stream.js')
|
const PortStream = require('./lib/port-stream.js')
|
||||||
const StreamProvider = require('./lib/stream-provider.js')
|
const StreamProvider = require('./lib/stream-provider.js')
|
||||||
|
const setupMultiplex = require('./lib/stream-utils.js').setupMultiplex
|
||||||
|
|
||||||
// setup app
|
// setup app
|
||||||
var css = MetaMaskUiCss()
|
var css = MetaMaskUiCss()
|
||||||
@ -24,21 +24,13 @@ function connectToAccountManager(cb){
|
|||||||
var pluginPort = chrome.runtime.connect({name: 'popup'})
|
var pluginPort = chrome.runtime.connect({name: 'popup'})
|
||||||
var portStream = new PortStream(pluginPort)
|
var portStream = new PortStream(pluginPort)
|
||||||
// setup multiplexing
|
// setup multiplexing
|
||||||
var mx = ObjectMultiplex()
|
var mx = setupMultiplex(portStream)
|
||||||
portStream.pipe(mx).pipe(portStream)
|
// connect features
|
||||||
mx.on('error', function(err) {
|
setupControllerConnection(mx.createStream('controller'), cb)
|
||||||
console.error(err)
|
setupWeb3Connection(mx.createStream('provider'))
|
||||||
portStream.destroy()
|
|
||||||
})
|
|
||||||
portStream.on('error', function(err) {
|
|
||||||
console.error(err)
|
|
||||||
mx.destroy()
|
|
||||||
})
|
|
||||||
linkDnode(mx.createStream('dnode'), cb)
|
|
||||||
linkWeb3(mx.createStream('provider'))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function linkWeb3(stream){
|
function setupWeb3Connection(stream){
|
||||||
var remoteProvider = new StreamProvider()
|
var remoteProvider = new StreamProvider()
|
||||||
remoteProvider.pipe(stream).pipe(remoteProvider)
|
remoteProvider.pipe(stream).pipe(remoteProvider)
|
||||||
stream.on('error', console.error.bind(console))
|
stream.on('error', console.error.bind(console))
|
||||||
@ -46,7 +38,7 @@ function linkWeb3(stream){
|
|||||||
global.web3 = new Web3(remoteProvider)
|
global.web3 = new Web3(remoteProvider)
|
||||||
}
|
}
|
||||||
|
|
||||||
function linkDnode(stream, cb){
|
function setupControllerConnection(stream, cb){
|
||||||
var eventEmitter = new EventEmitter()
|
var eventEmitter = new EventEmitter()
|
||||||
var background = Dnode({
|
var background = Dnode({
|
||||||
sendUpdate: function(state){
|
sendUpdate: function(state){
|
||||||
|
Loading…
Reference in New Issue
Block a user