Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Web3 1.0 "subscription" support #4001

Closed
wants to merge 3 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 1 addition & 2 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
npm-debug.log
node_modules
yarn.lock

yarn-error.log
app/bower_components
test/bower_components
package

# IDEs
.idea
Expand Down
8 changes: 4 additions & 4 deletions app/scripts/background.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,10 @@ const LocalStore = require('./lib/local-store')
const storeTransform = require('obs-store/lib/transform')
const asStream = require('obs-store/lib/asStream')
const ExtensionPlatform = require('./platforms/extension')
const Migrator = require('./lib/migrator/')
const migrations = require('./migrations/')
const PortStream = require('./lib/port-stream.js')
const NotificationManager = require('./lib/notification-manager.js')
const Migrator = require('./lib/migrator')
const migrations = require('./migrations')
const PortStream = require('./lib/port-stream')
const NotificationManager = require('./lib/notification-manager')
const MetamaskController = require('./metamask-controller')
const firstTimeState = require('./first-time-state')
const setupRaven = require('./lib/setupRaven')
Expand Down
2 changes: 1 addition & 1 deletion app/scripts/contentscript.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ const LocalMessageDuplexStream = require('post-message-stream')
const PongStream = require('ping-pong-stream/pong')
const ObjectMultiplex = require('obj-multiplex')
const extension = require('extensionizer')
const PortStream = require('./lib/port-stream.js')
const PortStream = require('./lib/port-stream')

const inpageContent = fs.readFileSync(path.join(__dirname, '..', '..', 'dist', 'chrome', 'inpage.js')).toString()
const inpageSuffix = '//# sourceURL=' + extension.extension.getURL('inpage.js') + '\n'
Expand Down
3 changes: 1 addition & 2 deletions app/scripts/controllers/balance.js
Original file line number Diff line number Diff line change
Expand Up @@ -59,12 +59,11 @@ class BalanceController {
}

async _getPendingTransactions () {
const pending = this.txController.getFilteredTxList({
return this.txController.getFilteredTxList({
from: this.address,
status: 'submitted',
err: undefined,
})
return pending
}

_validateParams (opts) {
Expand Down
8 changes: 4 additions & 4 deletions app/scripts/controllers/network.js
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
const assert = require('assert')
const EventEmitter = require('events')
const createMetamaskProvider = require('web3-provider-engine/zero.js')
const SubproviderFromProvider = require('web3-provider-engine/subproviders/web3.js')
const createMetamaskProvider = require('web3-provider-engine/zero')
const SubproviderFromProvider = require('web3-provider-engine/subproviders/provider')
const createInfuraProvider = require('eth-json-rpc-infura/src/createProvider')
const ObservableStore = require('obs-store')
const ComposedStore = require('obs-store/lib/composed')
const extend = require('xtend')
const EthQuery = require('eth-query')
const createEventEmitterProxy = require('../lib/events-proxy.js')
const networkConfig = require('../config.js')
const createEventEmitterProxy = require('../lib/events-proxy')
const networkConfig = require('../config')
const log = require('loglevel')
const { OLD_UI_NETWORK_TYPE, DEFAULT_RPC } = networkConfig.enums
const INFURA_PROVIDER_TYPES = ['ropsten', 'rinkeby', 'kovan', 'mainnet']
Expand Down
28 changes: 21 additions & 7 deletions app/scripts/inpage.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
/*global Web3*/
cleanContextForImports()
require('web3/dist/web3.min.js')
require('web3/dist/web3.min')
const log = require('loglevel')
const LocalMessageDuplexStream = require('post-message-stream')
const setupDappAutoReload = require('./lib/auto-reload.js')
const MetamaskInpageProvider = require('./lib/inpage-provider.js')
const setupDappAutoReload = require('./lib/auto-reload')
const MetamaskInpageProvider = require('./lib/inpage-provider')
restoreContextAfterImports()

log.setDefaultLevel(process.env.METAMASK_DEBUG ? 'debug' : 'warn')
Expand All @@ -14,13 +14,13 @@ log.setDefaultLevel(process.env.METAMASK_DEBUG ? 'debug' : 'warn')
//

// setup background connection
var metamaskStream = new LocalMessageDuplexStream({
const metamaskStream = new LocalMessageDuplexStream({
name: 'inpage',
target: 'contentscript',
})

// compose the inpage provider
var inpageProvider = new MetamaskInpageProvider(metamaskStream)
const inpageProvider = new MetamaskInpageProvider(metamaskStream)

//
// setup web3
Expand All @@ -33,7 +33,7 @@ if (typeof window.web3 !== 'undefined') {
or MetaMask and another web3 extension. Please remove one
and try again.`)
}
var web3 = new Web3(inpageProvider)
const web3 = new Web3(inpageProvider)
web3.setProvider = function () {
log.debug('MetaMask - overrode web3.setProvider')
}
Expand All @@ -47,14 +47,28 @@ inpageProvider.publicConfigStore.subscribe(function (state) {
web3.eth.defaultAccount = state.selectedAddress
})

// clear subscriptions
function clearSubscriptions () {
if (inpageProvider.subscriptions) {
inpageProvider.sendAsync({
jsonrpc: '2.0',
method: 'eth_unsubscribe',
params: inpageProvider.subscriptions,
}, () => {
console.log('cleared subscriptions')
})
}
}
window.onbeforeunload = clearSubscriptions

//
// util
//

// need to make sure we aren't affected by overlapping namespaces
// and that we dont affect the app with our namespace
// mostly a fix for web3's BigNumber if AMD's "define" is defined...
var __define
let __define

function cleanContextForImports () {
__define = global.define
Expand Down
59 changes: 53 additions & 6 deletions app/scripts/lib/inpage-provider.js
Original file line number Diff line number Diff line change
@@ -1,15 +1,21 @@
const pump = require('pump')
const RpcEngine = require('json-rpc-engine')
const asStream = require('obs-store/lib/asStream')
const createIdRemapMiddleware = require('json-rpc-engine/src/idRemapMiddleware')
const createStreamMiddleware = require('json-rpc-middleware-stream')
const EventEmitter = require('events')
const { inherits } = require('util')
const LocalStorageStore = require('obs-store')
const asStream = require('obs-store/lib/asStream')
const ObjectMultiplex = require('obj-multiplex')
const pump = require('pump')
const RpcEngine = require('json-rpc-engine')
const { noop, override } = require('./util')

module.exports = MetamaskInpageProvider

inherits(MetamaskInpageProvider, EventEmitter)

function MetamaskInpageProvider (connectionStream) {
const self = this
EventEmitter.call(self)

// setup connectionStream multiplexing
const mux = self.mux = new ObjectMultiplex()
Expand All @@ -34,6 +40,22 @@ function MetamaskInpageProvider (connectionStream) {

// connect to async provider
const streamMiddleware = createStreamMiddleware()
override(streamMiddleware.stream, 'write', function (original) {
return function (res, encoding, cb) {
// eth_subscription's do not have an id, therfore cannot be remapped
// responses should be emitted onto the web3 current provider
if (res.method === 'eth_subscription') {
// if has subscription registered on inpage provider, emit subscription
// data onto the current provider
if (self.subscriptions.indexOf(res.params.subscription) > -1) {
self.emit('data', res)
}
} else {
// call original funtion
original.apply(this, arguments)
}
}
})
pump(
streamMiddleware.stream,
mux.createStream('provider'),
Expand All @@ -46,16 +68,41 @@ function MetamaskInpageProvider (connectionStream) {
rpcEngine.push(createIdRemapMiddleware())
rpcEngine.push(streamMiddleware)
self.rpcEngine = rpcEngine

// subscription ids
self.subscriptions = []
}

MetamaskInpageProvider.prototype._handleSubscriptionRequest = function (payload, cb) {
const self = this
self.rpcEngine.handle(payload, (error, response) => {
if (error) {
cb(error, null)
} else {
payload.method === 'eth_subscribe' ?
self.subscriptions.push(response.result) :
payload.params.forEach(p => {
self.subscriptions = self.subscriptions.filter(s => s !== p)
})
cb(null, response)
}
})
}

MetamaskInpageProvider.prototype._handleRequest = function (payload, cb) {
const self = this
isSubscriptionRequest(payload) ?
self._handleSubscriptionRequest(payload, cb) :
self.rpcEngine.handle(payload, cb)
}

// handle sendAsync requests via asyncProvider
// also remap ids inbound and outbound
MetamaskInpageProvider.prototype.sendAsync = function (payload, cb) {
const self = this
self.rpcEngine.handle(payload, cb)
self._handleRequest(payload, cb)
}


MetamaskInpageProvider.prototype.send = function (payload) {
const self = this

Expand Down Expand Up @@ -115,4 +162,4 @@ function logStreamDisconnectWarning (remoteLabel, err) {
console.warn(warningMsg)
}

function noop () {}
function isSubscriptionRequest (request) { return request.method === 'eth_subscribe' || request.method === 'eth_unsubscribe' }
8 changes: 8 additions & 0 deletions app/scripts/lib/util.js
Original file line number Diff line number Diff line change
Expand Up @@ -50,11 +50,19 @@ function BnMultiplyByFraction (targetBN, numerator, denominator) {
return targetBN.mul(numBN).div(denomBN)
}

function override (object, methodName, callback) {
object[methodName] = callback(object[methodName])
}

function noop () {}

module.exports = {
getStack,
getEnvironmentType,
sufficientBalance,
hexToBn,
bnToHex,
BnMultiplyByFraction,
override,
noop,
}
10 changes: 5 additions & 5 deletions app/scripts/metamask-controller.js
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ module.exports = class MetamaskController extends EventEmitter {

/**
* @constructor
* @param {Object} opts
* @param {Object} opts
*/
constructor (opts) {
super()
Expand Down Expand Up @@ -398,8 +398,6 @@ module.exports = class MetamaskController extends EventEmitter {
}
}



//=============================================================================
// VAULT / KEYRING RELATED METHODS
//=============================================================================
Expand Down Expand Up @@ -832,13 +830,13 @@ module.exports = class MetamaskController extends EventEmitter {
cb(null, this.getState())
}

markPasswordForgotten(cb) {
markPasswordForgotten (cb) {
this.configManager.setPasswordForgotten(true)
this.sendUpdate()
cb()
}

unMarkPasswordForgotten(cb) {
unMarkPasswordForgotten (cb) {
this.configManager.setPasswordForgotten(false)
this.sendUpdate()
cb()
Expand Down Expand Up @@ -912,6 +910,8 @@ module.exports = class MetamaskController extends EventEmitter {

// setup connection
const providerStream = createEngineStream({ engine })
// data event listener
this.provider.on('data', (err, data) => !err ? providerStream.emit('data', data) : log.error(err))
pump(
outStream,
providerStream,
Expand Down
2 changes: 1 addition & 1 deletion app/scripts/notice-controller.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
const EventEmitter = require('events').EventEmitter
const EventEmitter = require('events')
const semver = require('semver')
const extend = require('xtend')
const ObservableStore = require('obs-store')
Expand Down
4 changes: 2 additions & 2 deletions app/scripts/popup-core.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
const EventEmitter = require('events').EventEmitter
const EventEmitter = require('events')
const async = require('async')
const Dnode = require('dnode')
const Eth = require('ethjs')
const EthQuery = require('eth-query')
const launchMetamaskUi = require('../../ui')
const StreamProvider = require('web3-stream-provider')
const setupMultiplex = require('./lib/stream-utils.js').setupMultiplex
const setupMultiplex = require('./lib/stream-utils').setupMultiplex


module.exports = initializePopup
Expand Down
2 changes: 1 addition & 1 deletion app/scripts/ui.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ const injectCss = require('inject-css')
const OldMetaMaskUiCss = require('../../old-ui/css')
const NewMetaMaskUiCss = require('../../ui/css')
const startPopup = require('./popup-core')
const PortStream = require('./lib/port-stream.js')
const PortStream = require('./lib/port-stream')
const { getEnvironmentType } = require('./lib/util')
const { ENVIRONMENT_TYPE_NOTIFICATION } = require('./lib/enums')
const extension = require('extensionizer')
Expand Down
2 changes: 1 addition & 1 deletion mascara/test/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ var path = require('path')
var browserify = require('browserify');
var tests = fs.readdirSync(path.join(__dirname, 'lib'))
var bundlePath = path.join(__dirname, 'test-bundle.js')
var b = browserify();
var b = browserify()

// Remove old bundle
try {
Expand Down
Loading