diff options
Diffstat (limited to 'library')
-rw-r--r-- | library/README.md | 6 | ||||
-rw-r--r-- | library/controller.js | 68 | ||||
-rw-r--r-- | library/example/index.html | 17 | ||||
-rw-r--r-- | library/example/index.js | 54 | ||||
-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/popup.js | 19 | ||||
-rw-r--r-- | library/server.js | 105 | ||||
-rw-r--r-- | library/server/index.html | 20 |
10 files changed, 377 insertions, 0 deletions
diff --git a/library/README.md b/library/README.md new file mode 100644 index 000000000..7dc291564 --- /dev/null +++ b/library/README.md @@ -0,0 +1,6 @@ +start the dual servers (dapp + mascara) +``` +node server.js +``` + +open the example dapp at `http://localhost:9002/`
\ No newline at end of file diff --git a/library/controller.js b/library/controller.js new file mode 100644 index 000000000..d5cd0525e --- /dev/null +++ b/library/controller.js @@ -0,0 +1,68 @@ +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 + }) + + // connectionStream.on('data', function(chunk){ console.log('connectionStream chuck', chunk) }) + // multiStream.on('data', function(chunk){ console.log('multiStream chuck', 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/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..a3f4b9859 --- /dev/null +++ b/library/example/index.js @@ -0,0 +1,54 @@ + +window.addEventListener('load', web3Detect) + +function web3Detect() { + if (global.web3) { + logToDom('web3 detected!') + startApp() + } else { + logToDom('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) + }) + }) + }) + +} + +function logToDom(message){ + document.body.appendChild(document.createTextNode(message)) + console.log(message) +}
\ No newline at end of file diff --git a/library/index.js b/library/index.js new file mode 100644 index 000000000..ded588967 --- /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('http://localhost:9001/popup/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/popup.js b/library/popup.js new file mode 100644 index 000000000..667b13371 --- /dev/null +++ b/library/popup.js @@ -0,0 +1,19 @@ +const injectCss = require('inject-css') +const MetaMaskUiCss = require('../ui/css') +const startPopup = require('../app/scripts/popup-core') +const setupIframe = require('./lib/setup-iframe.js') + + +var css = MetaMaskUiCss() +injectCss(css) + +var name = 'popup' +window.METAMASK_UI_TYPE = name + +var iframeStream = setupIframe({ + zeroClientProvider: 'http://127.0.0.1:9001', + sandboxAttributes: ['allow-scripts', 'allow-popups', 'allow-same-origin'], + container: document.body, +}) + +startPopup(iframeStream) diff --git a/library/server.js b/library/server.js new file mode 100644 index 000000000..bb0b24e50 --- /dev/null +++ b/library/server.js @@ -0,0 +1,105 @@ +const express = require('express') +const browserify = require('browserify') +const watchify = require('watchify') +const babelify = require('babelify') + +const zeroBundle = createBundle('./index.js') +const controllerBundle = createBundle('./controller.js') +const popupBundle = createBundle('./popup.js') +const appBundle = createBundle('./example/index.js') + +// +// Iframe Server +// + +const iframeServer = express() + +// serve popup window +iframeServer.get('/popup/scripts/popup.js', function(req, res){ + res.send(popupBundle.latest) +}) +iframeServer.use('/popup', express.static('../dist/chrome')) + +// serve controller bundle +iframeServer.get('/controller.js', function(req, res){ + res.send(controllerBundle.latest) +}) + +// serve background controller +iframeServer.use(express.static('./server')) + +// start the server +const mascaraPort = 9001 +iframeServer.listen(mascaraPort) +console.log(`Mascara service listening on port ${mascaraPort}`) + + +// +// 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')) + +// start the server +const dappPort = '9002' +dappServer.listen(dappPort) +console.log(`Dapp listening on port ${dappPort}`) + +// +// util +// + +function serveBundle(entryPoint){ + const bundle = createBundle(entryPoint) + return function(req, res){ + res.send(bundle.latest) + } +} + +function createBundle(entryPoint){ + + var bundleContainer = {} + + var bundler = browserify({ + entries: [entryPoint], + cache: {}, + packageCache: {}, + plugin: [watchify], + }) + + // global transpile + var bablePreset = require.resolve('babel-preset-es2015') + + bundler.transform(babelify, { + global: true, + presets: [bablePreset], + babelrc: false, + }) + + 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 |