browser: improve webpack build.

This commit is contained in:
Christopher Jeffrey 2017-12-14 19:07:25 -08:00
parent e4ad8b457f
commit 11c7dab3c4
No known key found for this signature in database
GPG Key ID: 8962AB9DE6666BBD
14 changed files with 458 additions and 590 deletions

View File

@ -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

View File

@ -1,106 +1,110 @@
<!DOCTYPE html>
<html>
<head>
<title>bcoin</title>
<style>
html {
height: 100%;
}
body {
height: 90%;
padding: 20px;
}
h1 {
font: 3em monospace;
margin: 10px;
padding: 0;
}
small {
margin: 10px;
width: 50%;
display: block;
}
.log {
padding: 5px;
margin-left: 10px;
overflow-y: scroll;
border: 1px solid black;
white-space: pre-wrap;
height: 40%;
width: 40%;
font: 1em monospace;
margin-top: 10px;
}
.wallet {
padding: 5px;
margin-left: 5px;
margin-top: 10px;
font: 1em monospace;
}
.rpc, .send {
padding: 5px;
margin-left: 5px;
margin-top: 10px;
font: 1em monospace;
}
#newaddr{
display: block;
margin-left: 10px;
}
.tx {
float: right;
font: 1em monospace;
padding: 5px;
border: 1px solid black;
margin-top: 10px;
}
a {
text-decoration: none;
}
.floating {
font: 1em monospace;
white-space: pre-wrap;
position: absolute;
display: none;
padding: 5px;
background: white;
border: 1px solid black;
width: 40%;
height: 30%;
top: 50%;
left: 50%;
margin-left: -20%;
margin-top: -15%;
overflow-y: scroll;
}
</style>
<script src="/bcoin.js"></script>
</head>
<body>
<h1>Bcoin, the browser full node</h1>
<small>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-&gt;tcp proxy.
Enjoy. (See the <a href="https://github.com/bcoin-org/bcoin" target="_blank">bcoin repo</a> for
more bitcoin magic).</small>
<div class="tx">
<div>Chain State: <span id="state"></span></div>
<div>Last 20 Blocks/TXs:</div>
<div id="tx"></div>
</div>
<div id="log" class="log"></div>
<form id="rpc" class="rpc" action="#">
<input type="text" name="cmd" id="cmd"
placeholder="RPC command (e.g. getblockchaininfo)">
</form>
<div id="wallet" class="wallet"></div>
<form id="send" class="send" action="#">
<input type="text" name="address" id="address" placeholder="Address">
<input type="text" name="amount" id="amount" placeholder="Amount (BTC)">
<input type="submit" value="Send">
</form>
<input type="button" id="newaddr" value="New Address">
<div id="floating" class="floating"></div>
<script src="/index.js"></script>
</body>
<html lang="en">
<head>
<title>bcoin</title>
<meta charset="utf-8">
<style>
html {
height: 100%;
}
body {
height: 90%;
padding: 20px;
}
h1 {
font: 3em monospace;
margin: 10px;
padding: 0;
}
small {
margin: 10px;
width: 50%;
display: block;
}
.log {
padding: 5px;
margin-left: 10px;
overflow-y: scroll;
border: 1px solid black;
white-space: pre-wrap;
height: 40%;
width: 40%;
font: 1em monospace;
margin-top: 10px;
}
.wallet {
padding: 5px;
margin-left: 5px;
margin-top: 10px;
font: 1em monospace;
}
.rpc, .send {
padding: 5px;
margin-left: 5px;
margin-top: 10px;
font: 1em monospace;
}
#newaddr{
display: block;
margin-left: 10px;
}
.tx {
float: right;
font: 1em monospace;
padding: 5px;
border: 1px solid black;
margin-top: 10px;
}
a {
text-decoration: none;
}
.floating {
font: 1em monospace;
white-space: pre-wrap;
position: absolute;
display: none;
padding: 5px;
background: white;
border: 1px solid black;
width: 40%;
height: 30%;
top: 50%;
left: 50%;
margin-left: -20%;
margin-top: -15%;
overflow-y: scroll;
}
</style>
<script src="/app.js" defer></script>
</head>
<body>
<h1>Bcoin, the browser full node</h1>
<small>
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-&gt;tcp
proxy. Enjoy. (See the
<a href="https://github.com/bcoin-org/bcoin"
target="_blank">bcoin repo</a>
for more bitcoin magic).
</small>
<div class="tx">
<div>Chain State: <span id="state"></span></div>
<div>Last 20 Blocks/TXs:</div>
<div id="tx"></div>
</div>
<div id="log" class="log"></div>
<form id="rpc" class="rpc" action="#">
<input type="text" name="cmd" id="cmd"
placeholder="RPC command (e.g. getblockchaininfo)">
</form>
<div id="wallet" class="wallet"></div>
<form id="send" class="send" action="#">
<input type="text" name="address" id="address" placeholder="Address">
<input type="text" name="amount" id="amount" placeholder="Amount (BTC)">
<input type="submit" value="Send">
</form>
<input type="button" id="newaddr" value="New Address">
<div id="floating" class="floating"></div>
</body>
</html>

View File

@ -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 += '<span style="color:blue;">' + util.now() + '</span> ';
if (name === 'error') {
log.innerHTML += '<span style="color:red;">';
log.innerHTML += '[';
log.innerHTML += name
log.innerHTML += '] ';
if (module)
log.innerHTML += '(' + module + ') ';
log.innerHTML += '</span>';
} 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, '&amp;')
.replace(/</g, '&lt;')
.replace(/>/g, '&gt;')
.replace(/"/g, '&quot;')
.replace(/'/g, '&#39;');
}
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('<a style="display:block;" href="#'
+ item.rhash() + '">' + item.rhash() + ' (' + height
+ ' - ' + kb(item.getSize()) + ')</a>');
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 += '<b>Wallet</b><br>';
if (wallet.account.witness) {
html += 'Current Address (p2wpkh): <b>'
+ wallet.getAddress()
+ '</b><br>';
html += 'Current Address (p2wpkh behind p2sh): <b>'
+ wallet.getNestedAddress()
+ '</b><br>';
} else {
html += 'Current Address: <b>' + wallet.getAddress() + '</b><br>';
}
html += 'Extended Private Key: <b>' + json.key.xprivkey + '</b><br>';
html += 'Mnemonic: <b>' + json.mnemonic.phrase + '</b><br>';
wallet.getBalance().then(function(balance) {
html += 'Confirmed Balance: <b>'
+ bcoin.amount.btc(balance.confirmed)
+ '</b><br>';
html += 'Unconfirmed Balance: <b>'
+ bcoin.amount.btc(balance.unconfirmed)
+ '</b><br>';
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(
'<a style="display:block;" href="#' + tx.hash + '">'
+ tx.hash + '</a>');
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;
});
})();

View File

@ -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');
});

284
browser/src/app.js Normal file
View File

@ -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 += `<span style="color:blue;">${now}</span> `;
if (name === 'error') {
log.innerHTML += `<span style="color:red;">[${name}] `;
if (module)
log.innerHTML += `(${module}) `;
log.innerHTML += '</span>';
} 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, '&amp;')
.replace(/</g, '&lt;')
.replace(/>/g, '&gt;')
.replace(/"/g, '&quot;')
.replace(/'/g, '&#39;');
}
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(''
+ `<a style="display:block;" href="#${item.rhash()}">`
+ `${item.rhash()} (${height} - ${kb(item.getSize())})`
+ '</a>'
);
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 += '<b>Wallet</b><br>';
if (naddr) {
html += `Current Address (p2wpkh): <b>${raddr}</b><br>`;
html += `Current Address (p2wpkh behind p2sh): <b>${naddr}</b><br>`;
} else {
html += `Current Address: <b>${raddr}</b><br>`;
}
html += `Extended Private Key: <b>${key.xprivkey}</b><br>`;
html += `Mnemonic: <b>${mnemonic.phrase}</b><br>`;
const balance = await wallet.getBalance();
html += `Confirmed Balance: <b>${Amount.btc(balance.confirmed)}</b><br>`;
html += `Unconfirmed Balance: <b>${Amount.btc(balance.unconfirmed)}</b><br>`;
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(
`<a style="display:block;" href="#${tx.hash}">${tx.hash}</a>`);
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;
});

View File

@ -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'));

View File

@ -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;

View File

@ -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');

View File

@ -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"
}
}

32
webpack.app.js Normal file
View File

@ -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()
]
};

View File

@ -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()
]
};

View File

@ -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()
]
};

View File

@ -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
}
})
]
};

View File

@ -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}".`);
};