diff --git a/Makefile b/Makefile index caee01cc..27e9635d 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,9 @@ all: @npm run webpack +app: + @npm run webpack-app + browser: @npm run webpack-browser @@ -22,4 +25,4 @@ lint: test: @npm test -.PHONY: all browser compat node clean docs lint test +.PHONY: all app browser compat node clean docs lint test diff --git a/browser/index.html b/browser/index.html index 3e147a00..fc5a054e 100644 --- a/browser/index.html +++ b/browser/index.html @@ -1,106 +1,110 @@ - - -bcoin - - - - -

Bcoin, the browser full node

-Welcome. Your machine is currently validating the blockchain. -The blocks and wallet are stored on your local disk with indexed DB. You are -connecting to the actual bitcoin P2P network via a websocket->tcp proxy. -Enjoy. (See the bcoin repo for -more bitcoin magic). -
-
Chain State:
-
Last 20 Blocks/TXs:
-
-
-
-
- -
-
-
- - - -
- -
- - + + + bcoin + + + + + +

Bcoin, the browser full node

+ + Welcome. Your machine is currently validating the blockchain. The blocks + and wallet are stored on your local disk with indexed DB. You are + connecting to the actual bitcoin P2P network via a websocket->tcp + proxy. Enjoy. (See the + bcoin repo + for more bitcoin magic). + +
+
Chain State:
+
Last 20 Blocks/TXs:
+
+
+
+
+ +
+
+
+ + + +
+ +
+ diff --git a/browser/index.js b/browser/index.js deleted file mode 100644 index 400970ff..00000000 --- a/browser/index.js +++ /dev/null @@ -1,262 +0,0 @@ -;(function() { - -'use strict'; - -var util = bcoin.util; -var body = document.getElementsByTagName('body')[0]; -var log = document.getElementById('log'); -var wdiv = document.getElementById('wallet'); -var tdiv = document.getElementById('tx'); -var floating = document.getElementById('floating'); -var send = document.getElementById('send'); -var newaddr = document.getElementById('newaddr'); -var chainState = document.getElementById('state'); -var rpc = document.getElementById('rpc'); -var cmd = document.getElementById('cmd'); -var items = []; -var scrollback = 0; -var logger, node, wdb; - -window.onunhandledrejection = function(event) { - throw event.reason; -}; - -body.onmouseup = function() { - floating.style.display = 'none'; -}; - -floating.onmouseup = function(ev) { - ev.stopPropagation(); - return false; -}; - -function show(obj) { - const json = obj && obj.toJSON ? obj.toJSON() : null; - floating.innerHTML = escape(JSON.stringify(json, null, 2)); - floating.style.display = 'block'; -} - -logger = new bcoin.logger({ level: 'debug', console: true }); -logger.writeConsole = function(level, module, args) { - var name = bcoin.logger.levelsByVal[level]; - var msg = this.fmt(args, false); - if (++scrollback > 1000) { - log.innerHTML = ''; - scrollback = 1; - } - log.innerHTML += '' + util.now() + ' '; - if (name === 'error') { - log.innerHTML += ''; - log.innerHTML += '['; - log.innerHTML += name - log.innerHTML += '] '; - if (module) - log.innerHTML += '(' + module + ') '; - log.innerHTML += ''; - } else { - log.innerHTML += '['; - log.innerHTML += name - log.innerHTML += '] '; - if (module) - log.innerHTML += '(' + module + ') '; - } - log.innerHTML += escape(msg) + '\n'; - log.scrollTop = log.scrollHeight; -}; - -rpc.onsubmit = function(ev) { - var text = cmd.value || ''; - var argv = text.trim().split(/\s+/); - var method = argv.shift(); - var params = []; - var i, arg, param; - - cmd.value = ''; - - for (i = 0; i < argv.length; i++) { - arg = argv[i]; - try { - param = JSON.parse(arg); - } catch (e) { - param = arg; - } - params.push(param); - } - - node.rpc.execute({ method: method, params: params }).then(show, show); - - ev.preventDefault(); - ev.stopPropagation(); - - return false; -}; - -send.onsubmit = function(ev) { - var value = document.getElementById('amount').value; - var address = document.getElementById('address').value; - var tx, options; - - options = { - outputs: [{ - address: address, - value: bcoin.amount.value(value) - }] - }; - - wdb.primary.createTX(options).then(function(mtx) { - tx = mtx; - return wdb.primary.sign(tx); - }).then(function() { - return node.sendTX(tx); - }).then(function() { - show(tx); - }); - - ev.preventDefault(); - ev.stopPropagation(); - - return false; -}; - -newaddr.onmouseup = function() { - wdb.primary.createReceive().then(function() { - formatWallet(wdb.primary); - }); -}; - -function kb(size) { - size /= 1000; - return size.toFixed(2) + 'kb'; -} - -function create(html) { - var el = document.createElement('div'); - el.innerHTML = html; - return el.firstChild; -} - -function escape(html, encode) { - return html - .replace(!encode ? /&(?!#?\w+;)/g : /&/g, '&') - .replace(//g, '>') - .replace(/"/g, '"') - .replace(/'/g, '''); -} - -function addItem(item, entry) { - var height = entry ? entry.height : -1; - var el; - - if (items.length === 20) { - el = items.shift(); - tdiv.removeChild(el); - el.onmouseup = null; - } - - el = create('' + item.rhash() + ' (' + height - + ' - ' + kb(item.getSize()) + ')'); - tdiv.appendChild(el); - - setMouseup(el, item); - - items.push(el); - - chainState.innerHTML = '' - + 'tx=' + node.chain.db.state.tx - + ' coin=' + node.chain.db.state.coin - + ' value=' + bcoin.amount.btc(node.chain.db.state.value); -} - -function setMouseup(el, obj) { - el.onmouseup = function(ev) { - show(obj); - ev.stopPropagation(); - return false; - }; -} - -function formatWallet(wallet) { - var html = ''; - var json = wallet.master.toJSON(true); - var i, tx, el; - - html += 'Wallet
'; - - if (wallet.account.witness) { - html += 'Current Address (p2wpkh): ' - + wallet.getAddress() - + '
'; - html += 'Current Address (p2wpkh behind p2sh): ' - + wallet.getNestedAddress() - + '
'; - } else { - html += 'Current Address: ' + wallet.getAddress() + '
'; - } - - html += 'Extended Private Key: ' + json.key.xprivkey + '
'; - html += 'Mnemonic: ' + json.mnemonic.phrase + '
'; - - wallet.getBalance().then(function(balance) { - html += 'Confirmed Balance: ' - + bcoin.amount.btc(balance.confirmed) - + '
'; - - html += 'Unconfirmed Balance: ' - + bcoin.amount.btc(balance.unconfirmed) - + '
'; - - return wallet.getHistory(); - }).then(function(txs) { - return wallet.toDetails(txs); - }).then(function(txs) { - html += 'TXs:\n'; - wdiv.innerHTML = html; - - for (i = 0; i < txs.length; i++) { - tx = txs[i]; - - el = create( - '' - + tx.hash + ''); - - wdiv.appendChild(el); - setMouseup(el, tx.toJSON()); - } - }); -} - -node = new bcoin.fullnode({ - hash: true, - query: true, - prune: true, - network: 'main', - db: 'leveldb', - coinCache: 30000000, - logConsole: true, - workers: true, - workerFile: '/bcoin-worker.js', - logger: logger -}); - -wdb = node.use(bcoin.wallet.plugin); - -node.chain.on('block', addItem); -node.mempool.on('tx', addItem); - -node.open().then(function() { - return node.connect(); -}).then(function() { - node.startSync(); - - wdb.primary.on('balance', function() { - formatWallet(wdb.primary); - }); - - formatWallet(wdb.primary); -}).catch(function(err) { - throw err; -}); - -})(); diff --git a/browser/server.js b/browser/server.js index 3322d878..79dcc009 100644 --- a/browser/server.js +++ b/browser/server.js @@ -5,13 +5,10 @@ const fs = require('bfile'); const WSProxy = require('./wsproxy'); const index = fs.readFileSync(`${__dirname}/index.html`); -const indexjs = fs.readFileSync(`${__dirname}/index.js`); -const debug = fs.readFileSync(`${__dirname}/debug.html`); -const bcoin = fs.readFileSync(`${__dirname}/bcoin.js`); -const worker = fs.readFileSync(`${__dirname}/bcoin-worker.js`); +const app = fs.readFileSync(`${__dirname}/app.js`); +const worker = fs.readFileSync(`${__dirname}/worker.js`); const proxy = new WSProxy({ - pow: process.argv.indexOf('--pow') !== -1, ports: [8333, 18333, 18444, 28333, 28901] }); @@ -20,6 +17,8 @@ const server = bweb.server({ sockets: false }); +server.use(server.router()); + proxy.on('error', (err) => { console.error(err.stack); }); @@ -28,27 +27,15 @@ server.on('error', (err) => { console.error(err.stack); }); -server.get('/favicon.ico', (req, res) => { - res.send(404, '', 'txt'); -}); - server.get('/', (req, res) => { res.send(200, index, 'html'); }); -server.get('/index.js', (req, res) => { - res.send(200, indexjs, 'js'); +server.get('/app.js', (req, res) => { + res.send(200, app, 'js'); }); -server.get('/debug', (req, res) => { - res.send(200, debug, 'html'); -}); - -server.get('/bcoin.js', (req, res) => { - res.send(200, bcoin, 'js'); -}); - -server.get('/bcoin-worker.js', (req, res) => { +server.get('/worker.js', (req, res) => { res.send(200, worker, 'js'); }); diff --git a/browser/src/app.js b/browser/src/app.js new file mode 100644 index 00000000..77cc3eec --- /dev/null +++ b/browser/src/app.js @@ -0,0 +1,284 @@ +'use strict'; + +const Logger = require('blgr'); +const FullNode = require('../../lib/node/fullnode'); +const Amount = require('../../lib/btc/amount'); +const plugin = require('../../lib/wallet/plugin'); +const ProxySocket = require('./proxysocket'); + +const body = document.getElementsByTagName('body')[0]; +const log = document.getElementById('log'); +const wdiv = document.getElementById('wallet'); +const tdiv = document.getElementById('tx'); +const floating = document.getElementById('floating'); +const send = document.getElementById('send'); +const newaddr = document.getElementById('newaddr'); +const chainState = document.getElementById('state'); +const rpc = document.getElementById('rpc'); +const cmd = document.getElementById('cmd'); +const items = []; + +let scrollback = 0; + +const logger = new Logger({ + level: 'debug', + console: true +}); + +if (0) +logger.writeConsole = function writeConsole(level, module, args) { + const name = Logger.levelsByVal[level]; + const msg = this.fmt(args, false); + + if (++scrollback > 1000) { + log.innerHTML = ''; + scrollback = 1; + } + + const now = Math.floor(Date.now() / 1000); + + log.innerHTML += `${now} `; + + if (name === 'error') { + log.innerHTML += `[${name}] `; + if (module) + log.innerHTML += `(${module}) `; + log.innerHTML += ''; + } else { + log.innerHTML += `[${name}] `; + if (module) + log.innerHTML += `(${module}) `; + } + + log.innerHTML += escape(msg) + '\n'; + log.scrollTop = log.scrollHeight; +}; + +const node = new FullNode({ + hash: true, + query: true, + prune: true, + network: 'main', + memory: false, + coinCache: 30, + logConsole: true, + workers: true, + workerFile: '/worker.js', + createSocket: (port, host) => { + return ProxySocket.connect('ws://127.0.0.1:8080', port, host); + }, + logger: logger, + plugins: [plugin] +}); + +const {wdb} = node.require('walletdb'); + +window.onunhandledrejection = function onunhandledrejection(event) { + throw event.reason; +}; + +body.onmouseup = function onmouseup() { + floating.style.display = 'none'; +}; + +floating.onmouseup = function onmouseup(ev) { + ev.stopPropagation(); + return false; +}; + +function show(obj) { + const json = obj && obj.toJSON ? obj.toJSON() : null; + floating.innerHTML = escape(JSON.stringify(json, null, 2)); + floating.style.display = 'block'; +} + +rpc.onsubmit = function onsubmit(ev) { + const text = cmd.value || ''; + const argv = text.trim().split(/\s+/); + const method = argv.shift(); + const params = []; + + cmd.value = ''; + + for (const arg of argv) { + let param; + try { + param = JSON.parse(arg); + } catch (e) { + param = arg; + } + params.push(param); + } + + (async () => { + try { + const result = await node.rpc.execute({ method, params }); + show(result); + } catch (e) { + show(e); + } + })(); + + ev.preventDefault(); + ev.stopPropagation(); + + return false; +}; + +send.onsubmit = function onsubmit(ev) { + const value = document.getElementById('amount').value; + const address = document.getElementById('address').value; + + const options = { + outputs: [{ + address: address, + value: Amount.value(value) + }] + }; + + (async () => { + try { + const mtx = await wdb.primary.createTX(options); + await wdb.primary.sign(mtx); + await node.relay(mtx.toTX()); + show(mtx); + } catch (e) { + show(e); + } + })(); + + ev.preventDefault(); + ev.stopPropagation(); + + return false; +}; + +newaddr.onmouseup = function onmouseup() { + (async () => { + try { + await wdb.primary.createReceive(); + formatWallet(wdb.primary); + } catch (e) { + show(e); + } + })(); +}; + +function kb(size) { + size /= 1000; + return size.toFixed(2) + 'kb'; +} + +function create(html) { + const el = document.createElement('div'); + el.innerHTML = html; + return el.firstChild; +} + +function escape(html, encode) { + return html + .replace(!encode ? /&(?!#?\w+;)/g : /&/g, '&') + .replace(//g, '>') + .replace(/"/g, '"') + .replace(/'/g, '''); +} + +function addItem(item, entry) { + const height = entry ? entry.height : -1; + + if (items.length === 20) { + const el = items.shift(); + tdiv.removeChild(el); + el.onmouseup = null; + } + + const el = create('' + + `` + + `${item.rhash()} (${height} - ${kb(item.getSize())})` + + '' + ); + + tdiv.appendChild(el); + + setMouseup(el, item); + + items.push(el); + + chainState.innerHTML = '' + + `tx=${node.chain.db.state.tx} ` + + `coin=${node.chain.db.state.coin} ` + + `value=${Amount.btc(node.chain.db.state.value)}`; +} + +function setMouseup(el, obj) { + el.onmouseup = function onmouseup(ev) { + show(obj); + ev.stopPropagation(); + return false; + }; +} + +async function formatWallet(wallet) { + try { + await _formatWallet(wallet); + } catch (e) { + show(e); + } +} + +async function _formatWallet(wallet) { + const {key, mnemonic} = wallet.master.toJSON(node.network, true); + const account = await wallet.getAccount('default'); + const receive = account.receiveAddress(); + const nested = account.nestedAddress(); + const raddr = receive.toString(node.network); + const naddr = nested ? nested.toString(node.network) : null; + + let html = ''; + + html += 'Wallet
'; + + if (naddr) { + html += `Current Address (p2wpkh): ${raddr}
`; + html += `Current Address (p2wpkh behind p2sh): ${naddr}
`; + } else { + html += `Current Address: ${raddr}
`; + } + + html += `Extended Private Key: ${key.xprivkey}
`; + html += `Mnemonic: ${mnemonic.phrase}
`; + + const balance = await wallet.getBalance(); + + html += `Confirmed Balance: ${Amount.btc(balance.confirmed)}
`; + html += `Unconfirmed Balance: ${Amount.btc(balance.unconfirmed)}
`; + + const txs = await wallet.getHistory(); + const det = await wallet.toDetails(txs); + + html += 'TXs:\n'; + wdiv.innerHTML = html; + + for (const tx of det) { + const el = create( + `${tx.hash}`); + wdiv.appendChild(el); + setMouseup(el, tx.toJSON()); + } +} + +node.chain.on('block', addItem); +node.mempool.on('tx', addItem); + +(async () => { + await node.open(); + await node.connect(); + node.startSync(); + wdb.primary.on('balance', () => { + formatWallet(wdb.primary); + }); + formatWallet(wdb.primary); +})().catch((err) => { + throw err; +}); diff --git a/browser/proxysocket.js b/browser/src/proxysocket.js similarity index 67% rename from browser/proxysocket.js rename to browser/src/proxysocket.js index 8267f3f8..80f07177 100644 --- a/browser/proxysocket.js +++ b/browser/src/proxysocket.js @@ -9,20 +9,18 @@ const assert = require('assert'); const EventEmitter = require('events'); const bsock = require('bsock'); -const hash256 = require('bcrypto/lib/hash256'); -const bio = require('bufio'); class ProxySocket extends EventEmitter { constructor(uri) { super(); - this.info = null; + this.socket = bsock.socket(); + this.socket.reconnection = false; + this.socket.connect(uri); - this.socket = bsock.connect(uri); this.sendBuffer = []; this.recvBuffer = []; this.paused = false; - this.snonce = null; this.bytesWritten = 0; this.bytesRead = 0; this.remoteAddress = null; @@ -34,20 +32,6 @@ class ProxySocket extends EventEmitter { } init() { - this.socket.bind('info', (info) => { - if (this.closed) - return; - - this.info = info; - - if (info.pow) { - this.snonce = Buffer.from(info.snonce, 'hex'); - this.target = Buffer.from(info.target, 'hex'); - } - - this.emit('info', info); - }); - this.socket.on('error', (err) => { console.error(err); }); @@ -87,7 +71,7 @@ class ProxySocket extends EventEmitter { this.emit('timeout'); }); - this.socket.bind('disconnect', () => { + this.socket.on('disconnect', () => { if (this.closed) return; this.closed = true; @@ -104,37 +88,7 @@ class ProxySocket extends EventEmitter { return; } - if (!this.info) { - this.once('info', connect.bind(this, port, host)); - return; - } - - let nonce = 0; - - if (this.info.pow) { - const bw = bio.write(); - - bw.writeU32(nonce); - bw.writeBytes(this.snonce); - bw.writeU32(port); - bw.writeString(host, 'ascii'); - - const pow = bw.render(); - - console.log( - 'Solving proof of work to create socket (%d, %s) -- please wait.', - port, host); - - do { - nonce += 1; - assert(nonce <= 0xffffffff, 'Could not create socket.'); - pow.writeUInt32LE(nonce, 0, true); - } while (hash256.digest(pow).compare(this.target) > 0); - - console.log('Solved proof of work: %d', nonce); - } - - this.socket.fire('tcp connect', port, host, nonce); + this.socket.fire('tcp connect', port, host); for (const chunk of this.sendBuffer) this.write(chunk); @@ -157,15 +111,6 @@ class ProxySocket extends EventEmitter { } write(data, callback) { - if (!this.info) { - this.sendBuffer.push(data); - - if (callback) - callback(); - - return true; - } - this.bytesWritten += data.length; this.socket.fire('tcp data', data.toString('hex')); diff --git a/browser/wsproxy.js b/browser/wsproxy.js index d6b5748b..3b219dd5 100644 --- a/browser/wsproxy.js +++ b/browser/wsproxy.js @@ -4,13 +4,7 @@ const assert = require('assert'); const net = require('net'); const EventEmitter = require('events'); const bsock = require('bsock'); -const hash256 = require('bcrypto/lib/hash256'); const IP = require('binet'); -const bio = require('bufio'); - -const TARGET = Buffer.from( - '0000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff', - 'hex'); class WSProxy extends EventEmitter { constructor(options) { @@ -20,8 +14,6 @@ class WSProxy extends EventEmitter { options = {}; this.options = options; - this.target = options.target || TARGET; - this.pow = options.pow === true; this.ports = new Set(); this.io = bsock.server(); this.sockets = new WeakMap(); @@ -51,18 +43,16 @@ class WSProxy extends EventEmitter { // mutating the websocket object. this.sockets.set(ws, state); - ws.fire('info', state.toInfo()); - ws.on('error', (err) => { this.emit('error', err); }); - ws.bind('tcp connect', (port, host, nonce) => { - this.handleConnect(ws, port, host, nonce); + ws.bind('tcp connect', (port, host) => { + this.handleConnect(ws, port, host); }); } - handleConnect(ws, port, host, nonce) { + handleConnect(ws, port, host) { const state = this.sockets.get(ws); assert(state); @@ -80,30 +70,6 @@ class WSProxy extends EventEmitter { return; } - if (this.pow) { - if ((nonce >>> 0) !== nonce) { - this.log('Client did not solve proof of work (%s).', state.host); - ws.fire('tcp close'); - ws.destroy(); - return; - } - - const bw = bio.write(); - bw.writeU32(nonce); - bw.writeBytes(state.snonce); - bw.writeU32(port); - bw.writeString(host, 'ascii'); - - const pow = bw.render(); - - if (hash256.digest(pow).compare(this.target) > 0) { - this.log('Client did not solve proof of work (%s).', state.host); - ws.fire('tcp close'); - ws.destroy(); - return; - } - } - let raw, addr; try { raw = IP.toBuffer(host); @@ -206,7 +172,7 @@ class WSProxy extends EventEmitter { socket.resume(); }); - ws.bind('disconnect', () => { + ws.on('disconnect', () => { socket.destroy(); }); } @@ -223,22 +189,11 @@ class WSProxy extends EventEmitter { class SocketState { constructor(server, socket) { - this.pow = server.pow; - this.target = server.target; - this.snonce = nonce(); this.socket = null; this.host = socket.host; this.remoteHost = null; } - toInfo() { - return { - pow: this.pow, - target: this.target.toString('hex'), - snonce: this.snonce.toString('hex') - }; - } - connect(port, host) { this.socket = net.connect(port, host); this.remoteHost = IP.toHostname(host, port); @@ -246,11 +201,4 @@ class SocketState { } } -function nonce() { - const buf = Buffer.allocUnsafe(8); - buf.writeUInt32LE(Math.random() * 0x100000000, 0, true); - buf.writeUInt32LE(Math.random() * 0x100000000, 4, true); - return buf; -} - module.exports = WSProxy; diff --git a/lib/bcoin-browser.js b/lib/bcoin-browser.js index bcdae54e..9240c28d 100644 --- a/lib/bcoin-browser.js +++ b/lib/bcoin-browser.js @@ -33,12 +33,10 @@ bcoin.set = function set(network) { * Expose */ -/* // Blockchain bcoin.blockchain = require('./blockchain'); bcoin.Chain = require('./blockchain/chain'); bcoin.ChainEntry = require('./blockchain/chainentry'); -*/ // BTC bcoin.btc = require('./btc'); @@ -57,7 +55,6 @@ bcoin.HDPrivateKey = require('./hd/private'); bcoin.HDPublicKey = require('./hd/public'); bcoin.Mnemonic = require('./hd/mnemonic'); -/* // Mempool bcoin.mempool = require('./mempool'); bcoin.Fees = require('./mempool/fees'); @@ -79,7 +76,6 @@ bcoin.node = require('./node'); bcoin.Node = require('./node/node'); bcoin.FullNode = require('./node/fullnode'); bcoin.SPVNode = require('./node/spvnode'); -*/ // Primitives bcoin.primitives = require('./primitives'); @@ -117,7 +113,6 @@ bcoin.Witness = require('./script/witness'); bcoin.utils = require('./utils'); bcoin.util = require('./utils/util'); -/* // Wallet bcoin.wallet = require('./wallet'); bcoin.WalletDB = require('./wallet/walletdb'); @@ -125,7 +120,6 @@ bcoin.WalletDB = require('./wallet/walletdb'); // Workers bcoin.workers = require('./workers'); bcoin.WorkerPool = require('./workers/workerpool'); -*/ // Package Info bcoin.pkg = require('./pkg'); diff --git a/package.json b/package.json index 1ce27766..418efebb 100644 --- a/package.json +++ b/package.json @@ -69,7 +69,7 @@ "bcoin-spvnode": "./bin/spvnode" }, "scripts": { - "clean": "rm -f {browser/,}{bcoin.js,bcoin-worker.js}", + "clean": "rm -f {browser/,}{bcoin.js,bcoin-worker.js,app.js,worker.js}", "docs": "jsdoc -c jsdoc.json", "lint": "eslint $(cat .eslintfiles) || exit 0", "lint-file": "eslint", @@ -82,6 +82,6 @@ "webpack": "webpack --config webpack.browser.js", "webpack-browser": "webpack --config webpack.browser.js", "webpack-compat": "webpack --config webpack.compat.js", - "webpack-node": "webpack --config webpack.node.js" + "webpack-app": "webpack --config webpack.app.js" } } diff --git a/webpack.app.js b/webpack.app.js new file mode 100644 index 00000000..db860174 --- /dev/null +++ b/webpack.app.js @@ -0,0 +1,32 @@ +'use strict'; + +const Path = require('path'); +const webpack = require('webpack'); +const UglifyJsPlugin = require('uglifyjs-webpack-plugin'); +const str = JSON.stringify; +const env = process.env; + +module.exports = { + target: 'web', + entry: { + 'app': './browser/src/app', + 'worker': './lib/workers/worker' + }, + output: { + path: Path.join(__dirname, 'browser'), + filename: '[name].js' + }, + resolve: { + modules: ['node_modules'], + extensions: ['-browser.js', '.js', '.json'] + }, + plugins: [ + new webpack.DefinePlugin({ + 'process.env.BCOIN_NETWORK': + str(env.BCOIN_NETWORK || 'main'), + 'process.env.BCOIN_WORKER_FILE': + str(env.BCOIN_WORKER_FILE || '/bcoin-worker.js') + }), + new UglifyJsPlugin() + ] +}; diff --git a/webpack.browser.js b/webpack.browser.js index 7579f870..5a8eeb11 100644 --- a/webpack.browser.js +++ b/webpack.browser.js @@ -1,7 +1,7 @@ 'use strict'; +const Path = require('path'); const webpack = require('webpack'); -const path = require('path'); const UglifyJsPlugin = require('uglifyjs-webpack-plugin'); const str = JSON.stringify; const env = process.env; @@ -9,11 +9,13 @@ const env = process.env; module.exports = { target: 'web', entry: { - 'bcoin': './lib/bcoin-browser', + 'bcoin': './lib/bcoin', 'bcoin-worker': './lib/workers/worker' }, output: { - path: path.join(__dirname, 'browser'), + library: 'bcoin', + libraryTarget: 'umd', + path: Path.join(__dirname, 'browser'), filename: '[name].js' }, resolve: { @@ -27,10 +29,6 @@ module.exports = { 'process.env.BCOIN_WORKER_FILE': str(env.BCOIN_WORKER_FILE || '/bcoin-worker.js') }), - new UglifyJsPlugin({ - compress: { - warnings: true - } - }) + new UglifyJsPlugin() ] }; diff --git a/webpack.compat.js b/webpack.compat.js index 26a35267..4a1cef80 100644 --- a/webpack.compat.js +++ b/webpack.compat.js @@ -1,7 +1,7 @@ 'use strict'; +const Path = require('path'); const webpack = require('webpack'); -const path = require('path'); const UglifyJsPlugin = require('uglifyjs-webpack-plugin'); const str = JSON.stringify; const env = process.env; @@ -9,11 +9,13 @@ const env = process.env; module.exports = { target: 'web', entry: { - 'bcoin': './lib/bcoin-browser', + 'bcoin': './lib/bcoin', 'bcoin-worker': './lib/workers/worker' }, output: { - path: path.join(__dirname, 'browser'), + library: 'bcoin', + libraryTarget: 'umd', + path: Path.join(__dirname, 'browser'), filename: '[name].js' }, resolve: { @@ -23,7 +25,6 @@ module.exports = { module: { rules: [{ test: /\.js$/, - exclude: /node_modules\/(?!bcoin|elliptic|bn\.js|n64)/, loader: 'babel-loader' }] }, @@ -34,10 +35,6 @@ module.exports = { 'process.env.BCOIN_WORKER_FILE': str(env.BCOIN_WORKER_FILE || '/bcoin-worker.js') }), - new UglifyJsPlugin({ - compress: { - warnings: false - } - }) + new UglifyJsPlugin() ] }; diff --git a/webpack.node.js b/webpack.node.js deleted file mode 100644 index 110ce723..00000000 --- a/webpack.node.js +++ /dev/null @@ -1,49 +0,0 @@ -'use strict'; - -const webpack = require('webpack'); -const path = require('path'); -const UglifyJsPlugin = require('uglifyjs-webpack-plugin'); -const str = JSON.stringify; -const env = process.env; - -module.exports = { - target: 'node', - entry: { - 'bcoin': './lib/bcoin-browser', - 'bcoin-worker': './lib/workers/worker' - }, - output: { - path: __dirname, - filename: '[name].js', - libraryTarget: 'commonjs2' - }, - resolve: { - modules: ['node_modules'], - extensions: ['.node', '.js', '.json'], - alias: { - 'bindings': path.resolve(__dirname, 'webpack', 'bindings.js') - } - }, - node: { - __dirname: false, - __filename: false - }, - module: { - rules: [{ - test: /\.node$/, - loader: 'node-loader' - }] - }, - plugins: [ - new webpack.DefinePlugin({ - 'process.env.BCOIN_WORKER_FILE': - str(env.BCOIN_WORKER_FILE || 'bcoin-worker.js') - }), - new webpack.IgnorePlugin(/^utf-8-validate|bufferutil$/), - new UglifyJsPlugin({ - compress: { - warnings: true - } - }) - ] -}; diff --git a/webpack/bindings.js b/webpack/bindings.js deleted file mode 100644 index b8ed4ff1..00000000 --- a/webpack/bindings.js +++ /dev/null @@ -1,13 +0,0 @@ -'use strict'; - -module.exports = function bindings(name) { - switch (name) { - case 'leveldown': - return require('leveldown/build/Release/leveldown.node'); - case 'bcoin-native': - return require('bcoin-native/build/Release/bcoin-native.node'); - case 'secp256k1': - return require('secp256k1/build/Release/secp256k1.node'); - } - throw new Error(`Cannot find module "${name}".`); -};