diff options
22 files changed, 236 insertions, 150 deletions
diff --git a/app/scripts/lib/auto-faucet.js b/app/scripts/lib/auto-faucet.js index 73b73dfe6..38d54ba5e 100644 --- a/app/scripts/lib/auto-faucet.js +++ b/app/scripts/lib/auto-faucet.js @@ -3,9 +3,11 @@ const METAMASK_DEBUG = 'GULP_METAMASK_DEBUG' const env = process.env.METAMASK_ENV module.exports = function (address) { - if (METAMASK_DEBUG || env === 'test') return // Don't faucet in development or test - let data = address - let headers = new Headers() + // Don't faucet in development or test + if (METAMASK_DEBUG === true || env === 'test') return + global.log.info('auto-fauceting:', address) + const data = address + const headers = new Headers() headers.append('Content-type', 'application/rawdata') fetch(uri, { method: 'POST', diff --git a/app/scripts/lib/buy-eth-url.js b/app/scripts/lib/buy-eth-url.js new file mode 100644 index 000000000..91a1ec322 --- /dev/null +++ b/app/scripts/lib/buy-eth-url.js @@ -0,0 +1,19 @@ +module.exports = getBuyEthUrl + +function getBuyEthUrl({ network, amount, address }){ + let url + switch (network) { + case '1': + url = `https://buy.coinbase.com/?code=9ec56d01-7e81-5017-930c-513daa27bb6a&amount=${amount}&address=${address}&crypto_currency=ETH` + break + + case '3': + url = 'https://faucet.metamask.io/' + break + + case '42': + url = 'https://github.com/kovan-testnet/faucet' + break + } + return url +}
\ No newline at end of file diff --git a/app/scripts/metamask-controller.js b/app/scripts/metamask-controller.js index edb9bbbd9..2b8fc9cb8 100644 --- a/app/scripts/metamask-controller.js +++ b/app/scripts/metamask-controller.js @@ -23,6 +23,7 @@ const ConfigManager = require('./lib/config-manager') const autoFaucet = require('./lib/auto-faucet') const nodeify = require('./lib/nodeify') const accountImporter = require('./account-import-strategies') +const getBuyEthUrl = require('./lib/buy-eth-url') const version = require('../manifest.json').version @@ -614,24 +615,8 @@ module.exports = class MetamaskController extends EventEmitter { buyEth (address, amount) { if (!amount) amount = '5' - const network = this.getNetworkState() - let url - - switch (network) { - case '1': - url = `https://buy.coinbase.com/?code=9ec56d01-7e81-5017-930c-513daa27bb6a&amount=${amount}&address=${address}&crypto_currency=ETH` - break - - case '3': - url = 'https://faucet.metamask.io/' - break - - case '42': - url = 'https://github.com/kovan-testnet/faucet' - break - } - + const url = getBuyEthUrl({ network, address, amount }) if (url) this.platform.openWindow({ url }) } diff --git a/app/scripts/platforms/sw.js b/app/scripts/platforms/sw.js new file mode 100644 index 000000000..007d8dc5b --- /dev/null +++ b/app/scripts/platforms/sw.js @@ -0,0 +1,24 @@ + +class SwPlatform { + + // + // Public + // + + reload () { + // you cant actually do this + global.location.reload() + } + + openWindow ({ url }) { + // this doesnt actually work + global.open(url, '_blank') + } + + getVersion () { + return '<unable to read version>' + } + +} + +module.exports = SwPlatform diff --git a/app/scripts/platforms/window.js b/app/scripts/platforms/window.js new file mode 100644 index 000000000..1527c008b --- /dev/null +++ b/app/scripts/platforms/window.js @@ -0,0 +1,22 @@ + +class WindowPlatform { + + // + // Public + // + + reload () { + global.location.reload() + } + + openWindow ({ url }) { + global.open(url, '_blank') + } + + getVersion () { + return '<unable to read version>' + } + +} + +module.exports = WindowPlatform diff --git a/mascara/example/index.js b/mascara/example/app.js index aae7ccd19..aae7ccd19 100644 --- a/mascara/example/index.js +++ b/mascara/example/app.js diff --git a/mascara/example/index.html b/mascara/example/app/index.html index 47d6da34f..02323e5f9 100644 --- a/mascara/example/index.html +++ b/mascara/example/app/index.html @@ -3,15 +3,13 @@ <html lang="en"> <head> <meta charset="utf-8"> - <title>MetaMask ZeroClient Example</title> - + <script src="http://localhost:9001/metamascara.js"></script> </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/mascara/example/server.js b/mascara/example/server.js new file mode 100644 index 000000000..d39c19600 --- /dev/null +++ b/mascara/example/server.js @@ -0,0 +1,31 @@ +const express = require('express') +const createMetamascaraServer = require('../server/') +const createBundle = require('../server/util').createBundle +const serveBundle = require('../server/util').serveBundle + +// +// Iframe Server +// + +const mascaraServer = createMetamascaraServer() + +// start the server +const mascaraPort = 9001 +mascaraServer.listen(mascaraPort) +console.log(`Mascara service listening on port ${mascaraPort}`) + + +// +// Dapp Server +// + +const dappServer = express() + +// serve dapp bundle +serveBundle(dappServer, '/app.js', createBundle(require.resolve('./app.js'))) +dappServer.use(express.static(__dirname + '/app/')) + +// start the server +const dappPort = '9002' +dappServer.listen(dappPort) +console.log(`Dapp listening on port ${dappPort}`) diff --git a/mascara/server/index.html b/mascara/proxy/index.html index 2308dd98b..b83fc41af 100644 --- a/mascara/server/index.html +++ b/mascara/proxy/index.html @@ -15,6 +15,6 @@ <body> Hello! I am the MetaMask iframe. - <script src="/controller.js"></script> + <script src="./proxy.js"></script> </body> </html>
\ No newline at end of file diff --git a/mascara/server.js b/mascara/server.js deleted file mode 100644 index 67c89f11b..000000000 --- a/mascara/server.js +++ /dev/null @@ -1,103 +0,0 @@ -const express = require('express') -const browserify = require('browserify') -const watchify = require('watchify') -const babelify = require('babelify') - -const zeroBundle = createBundle('./src/mascara.js') -const controllerBundle = createBundle('./src/dapp-connection.js') -const popupBundle = createBundle('./src/popup.js') -const swBuild = createBundle('./src/background.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) -}) -iframeServer.get('/popup/sw-build.js', function(req, res){ - console.log('/sw-build.js') - res.setHeader('Content-Type', 'application/javascript') - res.send(swBuild.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], - }) - - 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/mascara/server/index.js b/mascara/server/index.js new file mode 100644 index 000000000..9fd664eee --- /dev/null +++ b/mascara/server/index.js @@ -0,0 +1,32 @@ +const express = require('express') +const createBundle = require('./util').createBundle +const serveBundle = require('./util').serveBundle + +module.exports = createMetamascaraServer + + +function createMetamascaraServer(){ + + // start bundlers + const metamascaraBundle = createBundle('./src/mascara.js') + const proxyBundle = createBundle('./src/proxy.js') + const uiBundle = createBundle('./src/ui.js') + const backgroundBuild = createBundle('./src/background.js') + + // serve bundles + const server = express() + // ui window + serveBundle(server, '/ui.js', uiBundle) + server.use(express.static(__dirname+'/../ui/')) + server.use(express.static(__dirname+'/../../dist/chrome')) + // metamascara + serveBundle(server, '/metamascara.js', metamascaraBundle) + // proxy + serveBundle(server, '/proxy/proxy.js', proxyBundle) + server.use('/proxy/', express.static(__dirname+'/../proxy')) + // background + serveBundle(server, '/background.js', backgroundBuild) + + return server + +} diff --git a/mascara/server/util.js b/mascara/server/util.js new file mode 100644 index 000000000..6e25b35d8 --- /dev/null +++ b/mascara/server/util.js @@ -0,0 +1,45 @@ +const browserify = require('browserify') +const watchify = require('watchify') + +module.exports = { + serveBundle, + createBundle, +} + + +function serveBundle(server, path, bundle){ + server.get(path, function(req, res){ + res.setHeader('Content-Type', 'application/javascript; charset=UTF-8') + res.send(bundle.latest) + }) +} + +function createBundle(entryPoint){ + + var bundleContainer = {} + + var bundler = browserify({ + entries: [entryPoint], + cache: {}, + packageCache: {}, + plugin: [watchify], + }) + + bundler.on('update', bundle) + bundle() + + return bundleContainer + + function bundle() { + bundler.bundle(function(err, result){ + if (err) { + console.log(`Bundle failed! (${entryPoint})`) + console.error(err) + return + } + console.log(`Bundle updated! (${entryPoint})`) + bundleContainer.latest = result.toString() + }) + } + +} diff --git a/mascara/src/background.js b/mascara/src/background.js index 6f9fb3d13..957570050 100644 --- a/mascara/src/background.js +++ b/mascara/src/background.js @@ -8,6 +8,7 @@ const PortStream = require('../../app/scripts/lib/port-stream.js') const DbController = require('./lib/index-db-controller') +const SwPlatform = require('../../app/scripts/platforms/sw') const MetamaskController = require('../../app/scripts/metamask-controller') const extension = {} //require('../../app/scripts/lib/extension') @@ -17,7 +18,8 @@ const migrations = require('../../app/scripts/migrations/') const firstTimeState = require('../../app/scripts/first-time-state') const STORAGE_KEY = 'metamask-config' -const METAMASK_DEBUG = 'GULP_METAMASK_DEBUG' +// const METAMASK_DEBUG = 'GULP_METAMASK_DEBUG' +const METAMASK_DEBUG = true let popupIsOpen = false const log = require('loglevel') @@ -70,7 +72,11 @@ function setupController (initState, client) { // MetaMask Controller // + const platform = new SwPlatform() + const controller = new MetamaskController({ + // platform specific implementation + platform, // User confirmation callbacks: showUnconfirmedMessage: noop, unlockAccountMessage: noop, diff --git a/mascara/src/lib/setup-provider.js b/mascara/src/lib/setup-provider.js index 4f2432ae4..62335b18d 100644 --- a/mascara/src/lib/setup-provider.js +++ b/mascara/src/lib/setup-provider.js @@ -4,14 +4,14 @@ const MetamaskInpageProvider = require('../../../app/scripts/lib/inpage-provider module.exports = getProvider -function getProvider(){ +function getProvider(opts){ 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://localhost:9001', + zeroClientProvider: opts.mascaraUrl, sandboxAttributes: ['allow-scripts', 'allow-popups', 'allow-same-origin'], container: document.body, }) diff --git a/mascara/src/mascara.js b/mascara/src/mascara.js index 759353c1b..f9bed7e52 100644 --- a/mascara/src/mascara.js +++ b/mascara/src/mascara.js @@ -1,15 +1,22 @@ const Web3 = require('web3') const setupProvider = require('./lib/setup-provider.js') +const MASACARA_DOMAIN = 'http://localhost:9001' + // // setup web3 // -var provider = setupProvider() -hijackProvider(provider) + +var provider = setupProvider({ + mascaraUrl: MASACARA_DOMAIN + '/proxy/', +}) +instrumentForUserInteractionTriggers(provider) + var web3 = new Web3(provider) web3.setProvider = function(){ console.log('MetaMask - overrode web3.setProvider') } + // // // export web3 @@ -25,12 +32,12 @@ var shouldPop = false window.addEventListener('click', function(){ if (!shouldPop) return shouldPop = false - window.open('http://localhost:9001/popup/popup.html', '', 'width=360 height=500') + window.open(MASACARA_DOMAIN, '', 'width=360 height=500') console.log('opening window...') }) -function hijackProvider(provider){ +function instrumentForUserInteractionTriggers(provider){ var _super = provider.sendAsync.bind(provider) provider.sendAsync = function(payload, cb){ if (payload.method === 'eth_sendTransaction') { diff --git a/mascara/src/dapp-connection.js b/mascara/src/proxy.js index 30680c9d7..e580076c1 100644 --- a/mascara/src/dapp-connection.js +++ b/mascara/src/proxy.js @@ -4,7 +4,7 @@ const SwStream = require('sw-stream/lib/sw-stream.js') const SetupUntrustedComunication = ('./lib/setup-untrusted-connection.js') const background = new SWcontroller({ - fileName: '/popup/sw-build.js', + fileName: '/background.js', }) const pageStream = new ParentStream() diff --git a/mascara/src/popup.js b/mascara/src/ui.js index ef7759a81..c4866867b 100644 --- a/mascara/src/popup.js +++ b/mascara/src/ui.js @@ -4,8 +4,13 @@ const SwStream = require('sw-stream/lib/sw-stream.js') const MetaMaskUiCss = require('../../ui/css') const setupIframe = require('./lib/setup-iframe.js') const MetamaskInpageProvider = require('../../app/scripts/lib/inpage-provider.js') +const MetamascaraPlatform = require('../../app/scripts/platforms/window') const startPopup = require('../../app/scripts/popup-core') +// create platform global +global.platform = new MetamascaraPlatform() + + var css = MetaMaskUiCss() injectCss(css) const container = document.getElementById('app-content') @@ -14,7 +19,7 @@ var name = 'popup' window.METAMASK_UI_TYPE = name const background = new SWcontroller({ - fileName: '/popup/sw-build.js', + fileName: '/background.js', }) // Setup listener for when the service worker is read @@ -33,4 +38,4 @@ background.on('ready', (readSw) => { }) background.startWorker() -console.log('hello from /library/popup.js') +console.log('hello from MetaMascara ui!') diff --git a/mascara/ui/index.html b/mascara/ui/index.html new file mode 100644 index 000000000..c5eeb05ef --- /dev/null +++ b/mascara/ui/index.html @@ -0,0 +1,11 @@ +<!doctype html> +<html> + <head> + <meta charset="utf-8"> + <title>MetaMask Plugin</title> + </head> + <body> + <div id="app-content"></div> + <script src="./ui.js" type="text/javascript" charset="utf-8"></script> + </body> +</html>
\ No newline at end of file diff --git a/ui/app/actions.js b/ui/app/actions.js index 60b4c6f03..8934299e7 100644 --- a/ui/app/actions.js +++ b/ui/app/actions.js @@ -1,3 +1,5 @@ +const getBuyEthUrl = require('../../app/scripts/lib/buy-eth-url') + var actions = { _setBackgroundConnection: _setBackgroundConnection, @@ -833,10 +835,10 @@ function showSendPage () { } } -function buyEth (address, amount) { +function buyEth (opts) { return (dispatch) => { - log.debug(`background.buyEth`) - background.buyEth(address, amount) + const url = getBuyEthUrl(opts) + global.platform.openWindow({ url }) dispatch({ type: actions.BUY_ETH, }) diff --git a/ui/app/components/buy-button-subview.js b/ui/app/components/buy-button-subview.js index 2b1675b6d..6810303e1 100644 --- a/ui/app/components/buy-button-subview.js +++ b/ui/app/components/buy-button-subview.js @@ -104,7 +104,8 @@ BuyButtonSubview.prototype.render = function () { } BuyButtonSubview.prototype.formVersionSubview = function () { - if (this.props.network === '1') { + const network = this.props.network + if (network === '1') { if (this.props.buyView.formView.coinbase) { return h(CoinbaseForm, this.props) } else if (this.props.buyView.formView.shapeshift) { @@ -123,15 +124,15 @@ BuyButtonSubview.prototype.formVersionSubview = function () { marginBottom: '15px', }, }, 'In order to access this feature, please switch to the Main Network'), - ((this.props.network === '3') || (this.props.network === '42')) ? h('h3.text-transform-uppercase', 'or go to the') : null, - (this.props.network === '3') ? h('button.text-transform-uppercase', { - onClick: () => this.props.dispatch(actions.buyEth()), + ((network === '3') || (network === '42')) ? h('h3.text-transform-uppercase', 'or go to the') : null, + (network === '3') ? h('button.text-transform-uppercase', { + onClick: () => this.props.dispatch(actions.buyEth({ network })), style: { marginTop: '15px', }, }, 'Ropsten Test Faucet') : null, - (this.props.network === '42') ? h('button.text-transform-uppercase', { - onClick: () => this.props.dispatch(actions.buyEth()), + (network === '42') ? h('button.text-transform-uppercase', { + onClick: () => this.props.dispatch(actions.buyEth({ network })), style: { marginTop: '15px', }, diff --git a/ui/app/components/coinbase-form.js b/ui/app/components/coinbase-form.js index 40f5719bb..fd5816a21 100644 --- a/ui/app/components/coinbase-form.js +++ b/ui/app/components/coinbase-form.js @@ -112,7 +112,7 @@ CoinbaseForm.prototype.toCoinbase = function () { var message if (isValidAddress(address) && isValidAmountforCoinBase(amount).valid) { - props.dispatch(actions.buyEth(address, props.buyView.amount)) + props.dispatch(actions.buyEth({ network: '1', address, amount: props.buyView.amount })) } else if (!isValidAmountforCoinBase(amount).valid) { message = isValidAmountforCoinBase(amount).message return props.dispatch(actions.displayWarning(message)) diff --git a/ui/app/components/transaction-list-item.js b/ui/app/components/transaction-list-item.js index 0052d9c70..9fef52355 100644 --- a/ui/app/components/transaction-list-item.js +++ b/ui/app/components/transaction-list-item.js @@ -7,7 +7,6 @@ const addressSummary = require('../util').addressSummary const explorerLink = require('../../lib/explorer-link') const CopyButton = require('./copyButton') const vreme = new (require('vreme')) -const extension = require('extensionizer') const Tooltip = require('./tooltip') const TransactionIcon = require('./transaction-list-item-icon') @@ -50,7 +49,7 @@ TransactionListItem.prototype.render = function () { event.stopPropagation() if (!transaction.hash || !isLinkable) return var url = explorerLink(transaction.hash, parseInt(network)) - extension.tabs.create({ url }) + global.platform.openWindow({ url }) }, style: { padding: '20px 0', @@ -63,7 +62,7 @@ TransactionListItem.prototype.render = function () { event.stopPropagation() if (!isTx || isPending) return var url = `https://metamask.github.io/eth-tx-viz/?tx=${transaction.hash}` - extension.tabs.create({ url }) + global.platform.openWindow({ url }) }, }, [ h(TransactionIcon, { txParams, transaction, isTx, isMsg }), |