aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--app/scripts/background.js238
-rw-r--r--app/scripts/contentscript.js28
-rw-r--r--app/scripts/inpage.js69
-rw-r--r--app/scripts/lib/local-message-stream.js53
-rw-r--r--app/scripts/lib/port-stream.js36
-rw-r--r--app/scripts/lib/stream-provider.js50
-rw-r--r--package.json4
7 files changed, 296 insertions, 182 deletions
diff --git a/app/scripts/background.js b/app/scripts/background.js
index ddb867219..c439558c8 100644
--- a/app/scripts/background.js
+++ b/app/scripts/background.js
@@ -1,7 +1,10 @@
+const ZeroClientProvider = require('web3-provider-skeleton')
+// const PortStream = require('./lib/port-stream.js')
const identitiesUrl = 'https://alpha.metamask.io/identities/'
-const messagingChannelName = 'metamask'
-var unsignedTxs = {}
+// var unsignedTxs = {}
+
+var zeroClient = ZeroClientProvider()
// setup badge click handler
chrome.browserAction.onClicked.addListener(function(activeTab) {
@@ -10,118 +13,131 @@ chrome.browserAction.onClicked.addListener(function(activeTab) {
// setup messaging
chrome.runtime.onConnect.addListener(connectRemote)
-chrome.runtime.onConnectExternal.addListener(connectRemote)
-function connectRemote(remote){
- remote.onMessage.addListener(handleMessage)
- exportUnsignedTxs(remote)
+// chrome.runtime.onConnectExternal.addListener(connectRemote)
+function connectRemote(remotePort){
+ remotePort.onMessage.addListener(onRpcRequest.bind(null, remotePort))
}
-// load from storage
-chrome.storage.sync.get(function(data){
- for (var key in data) {
- var serialized = data[key]
- var tx = deserializeTx(serialized)
- var hash = simpleHash(serialized)
- unsignedTxs[hash] = tx
- }
- updateBadge()
-})
+function onRpcRequest(remotePort, payload){
+ zeroClient.sendAsync(payload, function onPayloadHandled(err, response){
+ if (err) throw err
+ // console.log('MetaMaskPlugin - RPC complete:', payload, '->', response)
+ // if (typeof response !== 'object') {
+ // if (!response) {
+ // console.warn('-------------------------------')
+ // console.warn(payload, '->', response)
+ // console.warn('-------------------------------')
+ // }
+ remotePort.postMessage(response)
+ })
+}
-// listen to storage changes
-chrome.storage.onChanged.addListener(function(changes, namespace) {
- for (key in changes) {
- var storageChange = changes[key]
- if (storageChange.oldValue && !storageChange.newValue) {
- // was removed
- removeTransaction(storageChange.oldValue)
- } else if (!storageChange.oldValue && storageChange.newValue) {
- // was added
- addTransaction(deserializeTx(storageChange.newValue))
- }
- }
-})
+// // load from storage
+// chrome.storage.sync.get(function(data){
+// for (var key in data) {
+// var serialized = data[key]
+// var tx = deserializeTx(serialized)
+// var hash = simpleHash(serialized)
+// unsignedTxs[hash] = tx
+// }
+// updateBadge()
+// })
+
+// // listen to storage changes
+// chrome.storage.onChanged.addListener(function(changes, namespace) {
+// for (key in changes) {
+// var storageChange = changes[key]
+// if (storageChange.oldValue && !storageChange.newValue) {
+// // was removed
+// removeTransaction(storageChange.oldValue)
+// } else if (!storageChange.oldValue && storageChange.newValue) {
+// // was added
+// addTransaction(deserializeTx(storageChange.newValue))
+// }
+// }
+// })
// setup badge text
-updateBadge()
-
-function handleMessage(msg){
- console.log('got message!', msg.type)
- switch(msg.type){
+// updateBadge()
+
+// function updateBadge(){
+// var label = ''
+// var count = Object.keys(unsignedTxs).length
+// if (count) {
+// label = String(count)
+// }
+// chrome.browserAction.setBadgeText({text: label})
+// chrome.browserAction.setBadgeBackgroundColor({color: '#506F8B'})
+// }
+
+// function handleMessage(msg){
+// console.log('got message!', msg.type)
+// switch(msg.type){
- case 'addUnsignedTx':
- addTransaction(msg.payload)
- return
-
- case 'removeUnsignedTx':
- removeTransaction(msg.payload)
- return
-
- }
-}
-
-function addTransaction(tx){
- var serialized = serializeTx(tx)
- var hash = simpleHash(serialized)
- unsignedTxs[hash] = tx
- var data = {}
- data[hash] = serialized
- chrome.storage.sync.set(data)
- // trigger ui changes
- updateBadge()
-}
-
-function removeTransaction(serialized){
- var hash = simpleHash(serialized)
- delete unsignedTxs[hash]
- var data = {}
- data[hash] = undefined
- chrome.storage.sync.set(data)
- // trigger ui changes
- updateBadge()
-}
-
-function exportUnsignedTxs(remote){
- console.log('exporting txs!', unsignedTxs)
- var data = {
- type: 'importUnsignedTxs',
- payload: getValues(unsignedTxs),
- }
- remote.postMessage(data)
-}
-
-function updateBadge(){
- var label = ''
- var count = Object.keys(unsignedTxs).length
- if (count) {
- label = String(count)
- }
- chrome.browserAction.setBadgeText({text: label})
- chrome.browserAction.setBadgeBackgroundColor({color: '#506F8B'})
-}
-
-function simpleHash(input) {
- var hash = 0, i, chr, len
- if (input.length == 0) return hash
- for (i = 0, len = input.length; i < len; i++) {
- chr = input.charCodeAt(i)
- hash = ((hash << 5) - hash) + chr
- hash |= 0 // Convert to 32bit integer
- }
- return hash
-}
-
-function serializeTx(tx){
- return JSON.stringify(tx)
-}
-
-function deserializeTx(tx){
- return JSON.parse(tx)
-}
-
-function getValues(obj){
- var output = []
- for (var key in obj) {
- output.push(obj[key])
- }
- return output
-} \ No newline at end of file
+// case 'addUnsignedTx':
+// addTransaction(msg.payload)
+// return
+
+// case 'removeUnsignedTx':
+// removeTransaction(msg.payload)
+// return
+
+// }
+// }
+
+// function addTransaction(tx){
+// var serialized = serializeTx(tx)
+// var hash = simpleHash(serialized)
+// unsignedTxs[hash] = tx
+// var data = {}
+// data[hash] = serialized
+// chrome.storage.sync.set(data)
+// // trigger ui changes
+// updateBadge()
+// }
+
+// function removeTransaction(serialized){
+// var hash = simpleHash(serialized)
+// delete unsignedTxs[hash]
+// var data = {}
+// data[hash] = undefined
+// chrome.storage.sync.set(data)
+// // trigger ui changes
+// updateBadge()
+// }
+
+// function exportUnsignedTxs(remote){
+// console.log('exporting txs!', unsignedTxs)
+// var data = {
+// type: 'importUnsignedTxs',
+// payload: getValues(unsignedTxs),
+// }
+// remote.postMessage(data)
+// }
+
+// function simpleHash(input) {
+// var hash = 0, i, chr, len
+// if (input.length == 0) return hash
+// for (i = 0, len = input.length; i < len; i++) {
+// chr = input.charCodeAt(i)
+// hash = ((hash << 5) - hash) + chr
+// hash |= 0 // Convert to 32bit integer
+// }
+// return hash
+// }
+
+// function serializeTx(tx){
+// return JSON.stringify(tx)
+// }
+
+// function deserializeTx(tx){
+// return JSON.parse(tx)
+// }
+
+// function getValues(obj){
+// var output = []
+// for (var key in obj) {
+// output.push(obj[key])
+// }
+// return output
+// } \ No newline at end of file
diff --git a/app/scripts/contentscript.js b/app/scripts/contentscript.js
index 7a180d9a9..cce5c1274 100644
--- a/app/scripts/contentscript.js
+++ b/app/scripts/contentscript.js
@@ -1,6 +1,7 @@
-const allowedMessageTarget = 'metamask'
-const allowedMessageType = 'addUnsignedTx'
+const LocalMessageDuplexStream = require('./lib/local-message-stream.js')
+const PortStream = require('./lib/port-stream.js')
+console.log('content script!')
// inject in-page script
var scriptTag = document.createElement('script')
@@ -9,17 +10,14 @@ scriptTag.onload = function() { this.parentNode.removeChild(this) }
var container = document.head || document.documentElement
container.appendChild(scriptTag)
-// setup connection with background
-var metamaskPlugin = chrome.runtime.connect({name: 'metamask'})
+// setup communication to page and plugin
+var pageStream = new LocalMessageDuplexStream({
+ name: 'contentscript',
+ target: 'inpage',
+})
+var pluginPort = chrome.runtime.connect({name: 'metamask'})
+var pluginStream = new PortStream(pluginPort)
-// forward messages from inpage to background
-window.addEventListener('message', receiveMessage, false);
-function receiveMessage(event){
- var msg = event.data
- // validate message type
- if (typeof msg !== 'object') return
- if (msg.to !== allowedMessageTarget) return
- if (msg.type !== allowedMessageType) return
- // forward message
- metamaskPlugin.postMessage(msg)
-} \ No newline at end of file
+// forward communication across
+pageStream.pipe(pluginStream)
+pluginStream.pipe(pageStream) \ No newline at end of file
diff --git a/app/scripts/inpage.js b/app/scripts/inpage.js
index 5149bd37e..d45dde593 100644
--- a/app/scripts/inpage.js
+++ b/app/scripts/inpage.js
@@ -1,59 +1,18 @@
-const web3 = require('web3')
-const BlockAppsWeb3Provider = require('blockapps-web3')
-const Transaction = require('ethereumjs-tx')
-require('object.entries').shim()
+const Web3 = require('web3')
+const StreamProvider = require('./lib/stream-provider.js')
+const LocalMessageDuplexStream = require('./lib/local-message-stream.js')
-// const rpcUrl = 'https://rpc.metamask.io'
-// var provider = new MetamaskProvider(forwardPayload, rpcUrl)
-var provider = new BlockAppsWeb3Provider({
- host: 'http://hacknet.blockapps.net',
- // host: 'http://api.blockapps.net',
- transaction_signer: {
- // Can be any object that implements the following methods:
- hasAddress: function(address, callback) {
- console.log('metamask provider - asked for address ownership', address)
- callback(null, true)
- },
- signTransaction: function(txParams, callback) {
- txParams.gasLimit = txParams.gas
- var tx = new Transaction(txParams)
- tx.sign(new Buffer('0d0ba14043088cd629a978b49c8691deca5926f0271432bc0064e4745bac0a9f', 'hex'))
- callback(null, '0x'+tx.serialize().toString('hex'))
- },
- },
- coinbase: '0x00000000000',
- accounts: ['0x985095ef977ba75fb2bb79cd5c4b84c81392dff6'],
- // host: function(){ debugger },
-});
-
-const documentOrigin = window.location.origin
-const allowedMessageTarget = 'metamask'
-const allowedMessageType = 'addUnsignedTx'
-
-web3.setProvider(provider)
-// disable setProvider
-web3.setProvider = function(){}
-
-// injecting web3
-console.log('Metamask injected web3')
-
-
-// log all the stuff!
-// provider.verbosity = 1
-
-// web3.currentProvider.vm.onStep = function(data, cb){
-// console.log(data)
-// cb()
-// }
+// setup plugin communication
+var pluginStream = new LocalMessageDuplexStream({
+ name: 'inpage',
+ target: 'contentscript',
+})
+var remoteProvider = new StreamProvider()
+remoteProvider.pipe(pluginStream).pipe(remoteProvider)
+// create web3
+var web3 = new Web3(remoteProvider)
window.web3 = web3
-
-
-function forwardPayload(payload){
- window.postMessage({
- to: allowedMessageTarget,
- type: allowedMessageType,
- payload: payload,
- }, documentOrigin)
-} \ No newline at end of file
+web3.setProvider = function(){}
+console.log('Metamask injected web3') \ No newline at end of file
diff --git a/app/scripts/lib/local-message-stream.js b/app/scripts/lib/local-message-stream.js
new file mode 100644
index 000000000..42d193e04
--- /dev/null
+++ b/app/scripts/lib/local-message-stream.js
@@ -0,0 +1,53 @@
+const Duplex = require('readable-stream').Duplex
+const inherits = require('util').inherits
+
+module.exports = LocalMessageDuplexStream
+
+
+inherits(LocalMessageDuplexStream, Duplex)
+
+function LocalMessageDuplexStream(opts){
+ Duplex.call(this, {
+ objectMode: true,
+ })
+
+ // this._origin = opts.origin
+ this._name = opts.name
+ this._target = opts.target
+
+ // console.log('LocalMessageDuplexStream ('+this._name+') - initialized...')
+ window.addEventListener('message', this._onMessage.bind(this), false)
+}
+
+// private
+
+LocalMessageDuplexStream.prototype._onMessage = function(event){
+ var msg = event.data
+ // console.log('LocalMessageDuplexStream ('+this._name+') - heard message...')
+ // validate message
+ if (event.origin !== location.origin) return //console.log('LocalMessageDuplexStream ('+this._name+') - rejected - (event.origin !== location.origin) ')
+ if (typeof msg !== 'object') return //console.log('LocalMessageDuplexStream ('+this._name+') - rejected - (typeof msg !== "object") ')
+ if (msg.target !== this._name) return //console.log('LocalMessageDuplexStream ('+this._name+') - rejected - (msg.target !== this._name) ', msg.target, this._name)
+ if (!msg.data) return //console.log('LocalMessageDuplexStream ('+this._name+') - rejected - (!msg.data) ')
+ // console.log('LocalMessageDuplexStream ('+this._name+') - accepted', msg.data)
+ // forward message
+ this.push(msg.data)
+}
+
+// stream plumbing
+
+LocalMessageDuplexStream.prototype._read = noop
+
+LocalMessageDuplexStream.prototype._write = function(data, encoding, cb){
+ // console.log('LocalMessageDuplexStream ('+this._name+') - sending message...')
+ var message = {
+ target: this._target,
+ data: data,
+ }
+ window.postMessage(message, location.origin)
+ cb()
+}
+
+// util
+
+function noop(){} \ No newline at end of file
diff --git a/app/scripts/lib/port-stream.js b/app/scripts/lib/port-stream.js
new file mode 100644
index 000000000..d256efc9a
--- /dev/null
+++ b/app/scripts/lib/port-stream.js
@@ -0,0 +1,36 @@
+const Duplex = require('readable-stream').Duplex
+const inherits = require('util').inherits
+
+module.exports = PortDuplexStream
+
+
+inherits(PortDuplexStream, Duplex)
+
+function PortDuplexStream(port){
+ Duplex.call(this, {
+ objectMode: true,
+ })
+ this._port = port
+ port.onMessage.addListener(this._onMessage.bind(this))
+}
+
+// private
+
+PortDuplexStream.prototype._onMessage = function(msg){
+ // console.log('PortDuplexStream - saw message', msg)
+ this.push(msg)
+}
+
+// stream plumbing
+
+PortDuplexStream.prototype._read = noop
+
+PortDuplexStream.prototype._write = function(msg, encoding, cb){
+ // console.log('PortDuplexStream - sent message', msg)
+ this._port.postMessage(msg)
+ cb()
+}
+
+// util
+
+function noop(){} \ No newline at end of file
diff --git a/app/scripts/lib/stream-provider.js b/app/scripts/lib/stream-provider.js
new file mode 100644
index 000000000..3e7f443c8
--- /dev/null
+++ b/app/scripts/lib/stream-provider.js
@@ -0,0 +1,50 @@
+const Duplex = require('readable-stream').Duplex
+const inherits = require('util').inherits
+
+module.exports = StreamProvider
+
+
+inherits(StreamProvider, Duplex)
+
+function StreamProvider(){
+ Duplex.call(this, {
+ objectMode: true,
+ })
+
+ this._handlers = {}
+}
+
+// public
+
+StreamProvider.prototype.send = function(payload){
+ throw new Error('StreamProvider - does not support synchronous RPC calls')
+}
+
+StreamProvider.prototype.sendAsync = function(payload, callback){
+// console.log('StreamProvider - sending payload', payload)
+ this._handlers[payload.id] = callback
+ this.push(payload)
+}
+
+// private
+
+StreamProvider.prototype._onResponse = function(payload){
+// console.log('StreamProvider - got response', payload)
+ var callback = this._handlers[payload.id]
+ if (!callback) throw new Error('StreamProvider - Unknown response id')
+ delete this._handlers[payload.id]
+ callback(null, payload)
+}
+
+// stream plumbing
+
+StreamProvider.prototype._read = noop
+
+StreamProvider.prototype._write = function(msg, encoding, cb){
+ this._onResponse(msg)
+ cb()
+}
+
+// util
+
+function noop(){} \ No newline at end of file
diff --git a/package.json b/package.json
index ce897c4f4..5578052fb 100644
--- a/package.json
+++ b/package.json
@@ -8,7 +8,9 @@
"ethereumjs-tx": "^0.6.7",
"ethereumjs-util": "^1.3.5",
"object.entries": "^1.0.2",
- "web3": "^0.9.2"
+ "readable-stream": "^2.0.5",
+ "web3": "^0.15.1",
+ "web3-provider-engine": "^1.0.0"
},
"devDependencies": {
"grunt": "~0.4.1",