diff options
-rw-r--r-- | library/controller.js | 67 | ||||
-rw-r--r-- | library/example/README.md | 5 | ||||
-rw-r--r-- | library/example/index.html | 17 | ||||
-rw-r--r-- | library/example/index.js | 51 | ||||
-rw-r--r-- | library/index.js | 44 | ||||
-rw-r--r-- | library/lib/setup-iframe.js | 19 | ||||
-rw-r--r-- | library/lib/setup-provider.js | 25 | ||||
-rw-r--r-- | library/server.js | 85 | ||||
-rw-r--r-- | library/server/index.html | 20 | ||||
-rw-r--r-- | package.json | 7 |
10 files changed, 338 insertions, 2 deletions
diff --git a/library/controller.js b/library/controller.js new file mode 100644 index 000000000..24b841f5e --- /dev/null +++ b/library/controller.js @@ -0,0 +1,67 @@ +const ZeroClientProvider = require('web3-provider-engine/zero') +const ParentStream = require('iframe-stream').ParentStream +const handleRequestsFromStream = require('web3-stream-provider/handler') +const Streams = require('mississippi') +const ObjectMultiplex = require('../app/scripts/lib/obj-multiplex') + + +initializeZeroClient() + +function initializeZeroClient() { + + var provider = ZeroClientProvider({ + // rpcUrl: configManager.getCurrentRpcAddress(), + rpcUrl: 'https://morden.infura.io/', + // account mgmt + // getAccounts: function(cb){ + // var selectedAddress = idStore.getSelectedAddress() + // var result = selectedAddress ? [selectedAddress] : [] + // cb(null, result) + // }, + getAccounts: function(cb){ + cb(null, ['0x8F331A98aC5C9431d04A5d6Bf8Fa84ed7Ed439f3'.toLowerCase()]) + }, + // tx signing + // approveTransaction: addUnconfirmedTx, + // signTransaction: idStore.signTransaction.bind(idStore), + signTransaction: function(txParams, cb){ + var privKey = new Buffer('7ef33e339ba5a5af0e57fa900ad0ae53deaa978c21ef30a0947532135eb639a8', 'hex') + var Transaction = require('ethereumjs-tx') + console.log('signing tx:', txParams) + txParams.gasLimit = txParams.gas + var tx = new Transaction(txParams) + tx.sign(privKey) + var serialiedTx = '0x'+tx.serialize().toString('hex') + cb(null, serialiedTx) + }, + // msg signing + // approveMessage: addUnconfirmedMsg, + // signMessage: idStore.signMessage.bind(idStore), + }) + + provider.on('block', function(block){ + console.log('BLOCK CHANGED:', '#'+block.number.toString('hex'), '0x'+block.hash.toString('hex')) + }) + + var connectionStream = new ParentStream() + // setup connectionStream multiplexing + var multiStream = ObjectMultiplex() + Streams.pipe(connectionStream, multiStream, connectionStream, function(err){ + console.warn('MetamaskIframe - lost connection to Dapp') + if (err) throw err + }) + + multiStream.on('data', function(chunk){ console.log(chunk) }) + + var providerStream = multiStream.createStream('provider') + handleRequestsFromStream(providerStream, provider, logger) + + function logger(err, request, response){ + if (err) return console.error(err.stack) + if (!request.isMetamaskInternal) { + console.log('MetaMaskIframe - RPC complete:', request, '->', response) + if (response.error) console.error('Error in RPC response:\n'+response.error.message) + } + } + +}
\ No newline at end of file diff --git a/library/example/README.md b/library/example/README.md new file mode 100644 index 000000000..2a5a1cce0 --- /dev/null +++ b/library/example/README.md @@ -0,0 +1,5 @@ +``` +trap 'kill %1' SIGINT +beefy frame.js:bundle.js 9001 --live & \ +beefy example/index.js:bundle.js index.js:zero.js --cwd example/ 9002 --live --open +```
\ No newline at end of file diff --git a/library/example/index.html b/library/example/index.html new file mode 100644 index 000000000..47d6da34f --- /dev/null +++ b/library/example/index.html @@ -0,0 +1,17 @@ +<!doctype html> + +<html lang="en"> +<head> + <meta charset="utf-8"> + + <title>MetaMask ZeroClient Example</title> + +</head> + +<body> + <button class="action-button-1">SYNC TX</button> + <button class="action-button-2">ASYNC TX</button> + <script src="./zero.js"></script> + <script src="./app.js"></script> +</body> +</html>
\ No newline at end of file diff --git a/library/example/index.js b/library/example/index.js new file mode 100644 index 000000000..91d2237c2 --- /dev/null +++ b/library/example/index.js @@ -0,0 +1,51 @@ + +window.addEventListener('load', web3Detect) + +function web3Detect() { + if (global.web3) { + document.body.innerHTML += 'web3 detected!' + console.log('web3 detected!') + startApp() + } else { + document.body.innerHTML += 'no web3 detected!' + console.log('no web3 detected!') + } +} + +function startApp(){ + console.log('app started') + + var primaryAccount = null + console.log('getting main account...') + web3.eth.getAccounts(function(err, addresses){ + if (err) throw err + console.log('set address') + primaryAccount = addresses[0] + }) + + document.querySelector('.action-button-1').addEventListener('click', function(){ + console.log('saw click') + console.log('sending tx') + web3.eth.sendTransaction({ + from: primaryAccount, + value: 0, + }, function(err, txHash){ + if (err) throw err + console.log('sendTransaction result:', err || txHash) + }) + }) + document.querySelector('.action-button-2').addEventListener('click', function(){ + console.log('saw click') + setTimeout(function(){ + console.log('sending tx') + web3.eth.sendTransaction({ + from: primaryAccount, + value: 0, + }, function(err, txHash){ + if (err) throw err + console.log('sendTransaction result:', err || txHash) + }) + }) + }) + +} diff --git a/library/index.js b/library/index.js new file mode 100644 index 000000000..6e43181c9 --- /dev/null +++ b/library/index.js @@ -0,0 +1,44 @@ +const Web3 = require('web3') +const setupProvider = require('./lib/setup-provider.js') + +// +// setup web3 +// + +var provider = setupProvider() +hijackProvider(provider) +var web3 = new Web3(provider) +web3.setProvider = function(){ + console.log('MetaMask - overrode web3.setProvider') +} +console.log('metamask lib hijacked provider') + +// +// export web3 +// + +global.web3 = web3 + +// +// ui stuff +// + +var shouldPop = false +window.addEventListener('click', function(){ + if (!shouldPop) return + shouldPop = false + window.open('popup.html', '', 'width=1000') + console.log('opening window...') +}) + + +function hijackProvider(provider){ + var _super = provider.sendAsync.bind(provider) + provider.sendAsync = function(payload, cb){ + if (payload.method === 'eth_sendTransaction') { + console.log('saw send') + shouldPop = true + } + _super(payload, cb) + } +}
\ No newline at end of file diff --git a/library/lib/setup-iframe.js b/library/lib/setup-iframe.js new file mode 100644 index 000000000..db67163df --- /dev/null +++ b/library/lib/setup-iframe.js @@ -0,0 +1,19 @@ +const Iframe = require('iframe') +const IframeStream = require('iframe-stream').IframeStream + +module.exports = setupIframe + + +function setupIframe(opts) { + opts = opts || {} + var frame = Iframe({ + src: opts.zeroClientProvider || 'https://zero.metamask.io/', + container: opts.container || document.head, + sandboxAttributes: opts.sandboxAttributes || ['allow-scripts', 'allow-popups'], + }) + var iframe = frame.iframe + iframe.style.setProperty('display', 'none') + var iframeStream = new IframeStream(iframe) + + return iframeStream +} diff --git a/library/lib/setup-provider.js b/library/lib/setup-provider.js new file mode 100644 index 000000000..9efd209cb --- /dev/null +++ b/library/lib/setup-provider.js @@ -0,0 +1,25 @@ +const setupIframe = require('./setup-iframe.js') +const MetamaskInpageProvider = require('../../app/scripts/lib/inpage-provider.js') + +module.exports = getProvider + + +function getProvider(){ + + if (global.web3) { + console.log('MetaMask ZeroClient - using environmental web3 provider') + return global.web3.currentProvider + } + + console.log('MetaMask ZeroClient - injecting zero-client iframe!') + var iframeStream = setupIframe({ + zeroClientProvider: 'http://127.0.0.1:9001', + sandboxAttributes: ['allow-scripts', 'allow-popups', 'allow-same-origin'], + container: document.body, + }) + + var inpageProvider = new MetamaskInpageProvider(iframeStream) + return inpageProvider + +} + diff --git a/library/server.js b/library/server.js new file mode 100644 index 000000000..7c764a4a7 --- /dev/null +++ b/library/server.js @@ -0,0 +1,85 @@ +const express = require('express') +const browserify = require('browserify') +const watchify = require('watchify') +const babelify = require('babelify') +const path = require('path') + +const zeroBundle = createBundle('./index.js') +const controllerBundle = createBundle('./controller.js') +const appBundle = createBundle('./example/index.js') + +// +// Iframe Server +// + +const iframeServer = express() + +// serve controller bundle +iframeServer.get('/controller.js', function(req, res){ + res.send(controllerBundle.latest) +}) + +// serve static +iframeServer.use(express.static('./server')) + +iframeServer.listen('9001') + + +// +// Dapp Server +// + +const dappServer = express() + + +// serve metamask-lib bundle +dappServer.get('/zero.js', function(req, res){ + res.send(zeroBundle.latest) +}) + +// serve dapp bundle +dappServer.get('/app.js', function(req, res){ + res.send(appBundle.latest) +}) + +// serve static +dappServer.use(express.static('./example')) + +const dappPort = '9002' +dappServer.listen(dappPort) +console.log(`Dapp listening on port ${dappPort}`) + +function createBundle(entryPoint){ + + var bundleContainer = {} + + var bundler = browserify({ + entries: [entryPoint], + cache: {}, + packageCache: {}, + plugin: [watchify], + }) + + // global transpile + var bablePreset = path.resolve(__dirname, '../node_modules/babel-preset-es2015') + + bundler.transform(babelify, { + global: true, + presets: [bablePreset], + }) + + + bundler.on('update', bundle) + bundle() + + return bundleContainer + + function bundle() { + bundler.bundle(function(err, result){ + if (err) throw err + console.log(`Bundle updated! (${entryPoint})`) + bundleContainer.latest = result.toString() + }) + } + +} diff --git a/library/server/index.html b/library/server/index.html new file mode 100644 index 000000000..2308dd98b --- /dev/null +++ b/library/server/index.html @@ -0,0 +1,20 @@ +<!doctype html> + +<html lang="en"> +<head> + <meta charset="utf-8"> + + <title>MetaMask ZeroClient Iframe</title> + <meta name="description" content="MetaMask ZeroClient"> + <meta name="author" content="MetaMask"> + + <!--[if lt IE 9]> + <script src="http://html5shiv.googlecode.com/svn/trunk/html5.js"></script> + <![endif]--> +</head> + +<body> + Hello! I am the MetaMask iframe. + <script src="/controller.js"></script> +</body> +</html>
\ No newline at end of file diff --git a/package.json b/package.json index 1fc9a5f7d..c75772a34 100644 --- a/package.json +++ b/package.json @@ -8,7 +8,7 @@ "lint": "gulp lint", "dev": "gulp dev", "dist": "gulp dist", - "test": "npm run fastTest && npm run ci", + "test": "npm run fastTest && npm run ci && npm run lint", "fastTest": "mocha --require test/helper.js --compilers js:babel-register --recursive \"test/unit/**/*.js\"", "watch": "mocha watch --compilers js:babel-register --recursive \"test/unit/**/*.js\"", "ui": "node development/genStates.js && beefy ui-dev.js:bundle.js --live --open --index=./development/index.html --cwd ./", @@ -45,9 +45,12 @@ "eth-store": "^1.1.0", "ethereumjs-tx": "^1.0.0", "ethereumjs-util": "^4.4.0", + "express": "^4.14.0", "gulp-eslint": "^2.0.0", "hat": "0.0.3", "identicon.js": "^1.2.1", + "iframe": "^1.0.0", + "iframe-stream": "^1.0.2", "inject-css": "^0.1.1", "jazzicon": "^1.1.3", "menu-droppo": "^1.1.0", @@ -76,7 +79,7 @@ "three.js": "^0.73.2", "through2": "^2.0.1", "vreme": "^3.0.2", - "web3": "^0.17.0-alpha", + "web3": "ethereum/web3.js#260ac6e78a8ce4b2e13f5bb0fdb65f4088585876", "web3-provider-engine": "^8.0.2", "web3-stream-provider": "^2.0.6", "xtend": "^4.0.1" |