http test. fix path parsing.
This commit is contained in:
parent
747c1a4949
commit
a60a48da9a
@ -133,7 +133,7 @@ function Fullnode(options) {
|
|||||||
port: this.options.httpPort || this.network.rpcPort,
|
port: this.options.httpPort || this.network.rpcPort,
|
||||||
host: this.options.httpHost || '0.0.0.0',
|
host: this.options.httpHost || '0.0.0.0',
|
||||||
apiKey: this.options.apiKey,
|
apiKey: this.options.apiKey,
|
||||||
auth: this.options.auth
|
walletAuth: this.options.walletAuth
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -221,6 +221,12 @@ HTTPBase.prototype._open = function open(callback) {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
HTTPBase.prototype._close = function close(callback) {
|
HTTPBase.prototype._close = function close(callback) {
|
||||||
|
if (this.io) {
|
||||||
|
this.server.once('close', callback);
|
||||||
|
this.io.close();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
this.server.close(callback);
|
this.server.close(callback);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -36,9 +36,19 @@ function HTTPClient(options) {
|
|||||||
this.options = options;
|
this.options = options;
|
||||||
this.network = bcoin.network.get(options.network);
|
this.network = bcoin.network.get(options.network);
|
||||||
|
|
||||||
this.uri = options.uri || 'localhost:' + this.network.rpcPort;
|
this.uri = options.uri || 'http://localhost:' + this.network.rpcPort;
|
||||||
this.id = null;
|
|
||||||
this.socket = null;
|
this.socket = null;
|
||||||
|
this.apiKey = options.apiKey;
|
||||||
|
this.auth = options.auth;
|
||||||
|
|
||||||
|
if (this.apiKey) {
|
||||||
|
if (typeof this.apiKey === 'string') {
|
||||||
|
assert(utils.isHex(this.apiKey), 'API key must be a hex string.');
|
||||||
|
this.apiKey = new Buffer(this.apiKey, 'hex');
|
||||||
|
}
|
||||||
|
assert(Buffer.isBuffer(this.apiKey));
|
||||||
|
assert(this.apiKey.length === 32, 'API key must be 32 bytes.');
|
||||||
|
}
|
||||||
|
|
||||||
// Open automatically.
|
// Open automatically.
|
||||||
this.open();
|
this.open();
|
||||||
@ -63,7 +73,7 @@ HTTPClient.prototype._open = function _open(callback) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!IOClient)
|
if (!IOClient)
|
||||||
return;
|
return callback();
|
||||||
|
|
||||||
this.socket = new IOClient(this.uri);
|
this.socket = new IOClient(this.uri);
|
||||||
|
|
||||||
@ -71,70 +81,70 @@ HTTPClient.prototype._open = function _open(callback) {
|
|||||||
self.emit('error', err);
|
self.emit('error', err);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
this.socket.on('version', function(info) {
|
||||||
|
if (info.network !== self.network.type)
|
||||||
|
self.emit('error', new Error('Wrong network.'));
|
||||||
|
});
|
||||||
|
|
||||||
|
this.socket.on('tx', function(tx, map) {
|
||||||
|
try {
|
||||||
|
tx = bcoin.tx.fromJSON(tx);
|
||||||
|
} catch (e) {
|
||||||
|
return self.emit('error', e);
|
||||||
|
}
|
||||||
|
self.emit('tx', tx, map);
|
||||||
|
});
|
||||||
|
|
||||||
|
this.socket.on('confirmed', function(tx, map) {
|
||||||
|
try {
|
||||||
|
tx = bcoin.tx.fromJSON(tx);
|
||||||
|
} catch (e) {
|
||||||
|
return self.emit('error', e);
|
||||||
|
}
|
||||||
|
self.emit('confirmed', tx, map);
|
||||||
|
});
|
||||||
|
|
||||||
|
this.socket.on('updated', function(tx, map) {
|
||||||
|
try {
|
||||||
|
tx = bcoin.tx.fromJSON(tx);
|
||||||
|
} catch (e) {
|
||||||
|
return self.emit('error', e);
|
||||||
|
}
|
||||||
|
self.emit('updated', tx, map);
|
||||||
|
});
|
||||||
|
|
||||||
|
this.socket.on('address', function(receive, change, map) {
|
||||||
|
receive = receive.map(function(address) {
|
||||||
|
return bcoin.keyring.fromJSON(address);
|
||||||
|
});
|
||||||
|
change = change.map(function(address) {
|
||||||
|
return bcoin.keyring.fromJSON(address);
|
||||||
|
});
|
||||||
|
self.emit('address', receive, change, map);
|
||||||
|
});
|
||||||
|
|
||||||
|
this.socket.on('balance', function(balance, id) {
|
||||||
|
self.emit('balance', {
|
||||||
|
confirmed: utils.satoshi(balance.confirmed),
|
||||||
|
unconfirmed: utils.satoshi(balance.unconfirmed),
|
||||||
|
total: utils.satoshi(balance.total)
|
||||||
|
}, id);
|
||||||
|
});
|
||||||
|
|
||||||
|
this.socket.on('balances', function(json) {
|
||||||
|
var balances = {};
|
||||||
|
Object.keys(json).forEach(function(id) {
|
||||||
|
balances[id] = {
|
||||||
|
confirmed: utils.satoshi(json[id].confirmed),
|
||||||
|
unconfirmed: utils.satoshi(json[id].unconfirmed),
|
||||||
|
total: utils.satoshi(json[id].total)
|
||||||
|
};
|
||||||
|
});
|
||||||
|
self.emit('balances', balances);
|
||||||
|
});
|
||||||
|
|
||||||
this.socket.on('connect', function() {
|
this.socket.on('connect', function() {
|
||||||
self.socket.on('version', function(info) {
|
callback();
|
||||||
assert(info.network === self.network.type, 'Wrong network.');
|
|
||||||
});
|
|
||||||
|
|
||||||
self.socket.on('tx', function(tx, map) {
|
|
||||||
try {
|
|
||||||
tx = bcoin.tx.fromJSON(tx);
|
|
||||||
} catch (e) {
|
|
||||||
return self.emit('error', e);
|
|
||||||
}
|
|
||||||
self.emit('tx', tx, map);
|
|
||||||
});
|
|
||||||
|
|
||||||
self.socket.on('confirmed', function(tx, map) {
|
|
||||||
try {
|
|
||||||
tx = bcoin.tx.fromJSON(tx);
|
|
||||||
} catch (e) {
|
|
||||||
return self.emit('error', e);
|
|
||||||
}
|
|
||||||
self.emit('confirmed', tx, map);
|
|
||||||
});
|
|
||||||
|
|
||||||
self.socket.on('updated', function(tx, map) {
|
|
||||||
try {
|
|
||||||
tx = bcoin.tx.fromJSON(tx);
|
|
||||||
} catch (e) {
|
|
||||||
return self.emit('error', e);
|
|
||||||
}
|
|
||||||
self.emit('updated', tx, map);
|
|
||||||
});
|
|
||||||
|
|
||||||
self.socket.on('balance', function(balance, id) {
|
|
||||||
self.emit('balance', {
|
|
||||||
confirmed: utils.satoshi(balance.confirmed),
|
|
||||||
unconfirmed: utils.satoshi(balance.unconfirmed),
|
|
||||||
total: utils.satoshi(balance.total)
|
|
||||||
}, id);
|
|
||||||
});
|
|
||||||
|
|
||||||
self.socket.on('address', function(receive, change, map) {
|
|
||||||
receive = receive.map(function(address) {
|
|
||||||
return bcoin.keyring.fromJSON(address);
|
|
||||||
});
|
|
||||||
change = change.map(function(address) {
|
|
||||||
return bcoin.keyring.fromJSON(address);
|
|
||||||
});
|
|
||||||
self.emit('address', receive, change, map);
|
|
||||||
});
|
|
||||||
|
|
||||||
self.socket.on('balances', function(json) {
|
|
||||||
var balances = {};
|
|
||||||
Object.keys(json).forEach(function(id) {
|
|
||||||
balances[id] = {
|
|
||||||
confirmed: utils.satoshi(json[id].confirmed),
|
|
||||||
unconfirmed: utils.satoshi(json[id].unconfirmed),
|
|
||||||
total: utils.satoshi(json[id].total)
|
|
||||||
};
|
|
||||||
});
|
|
||||||
self.emit('balances', balances);
|
|
||||||
});
|
|
||||||
|
|
||||||
self.loaded = true;
|
|
||||||
self.emit('open');
|
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -159,11 +169,11 @@ HTTPClient.prototype._close = function close(callback) {
|
|||||||
* @param {WalletID} id
|
* @param {WalletID} id
|
||||||
*/
|
*/
|
||||||
|
|
||||||
HTTPClient.prototype.join = function join(id) {
|
HTTPClient.prototype.join = function join(id, token) {
|
||||||
if (!this.socket)
|
if (!this.socket)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
this.socket.emit('join', id);
|
this.socket.emit('join', id, token);
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -182,8 +192,8 @@ HTTPClient.prototype.leave = function leave(id) {
|
|||||||
* Listen for events on all wallets.
|
* Listen for events on all wallets.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
HTTPClient.prototype.all = function all() {
|
HTTPClient.prototype.all = function all(token) {
|
||||||
this.join('!all');
|
this.join('!all', token);
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -205,8 +215,7 @@ HTTPClient.prototype.none = function none() {
|
|||||||
|
|
||||||
HTTPClient.prototype._request = function _request(method, endpoint, json, callback) {
|
HTTPClient.prototype._request = function _request(method, endpoint, json, callback) {
|
||||||
var self = this;
|
var self = this;
|
||||||
var query;
|
var query, network, height;
|
||||||
var networkType;
|
|
||||||
|
|
||||||
if (!callback) {
|
if (!callback) {
|
||||||
callback = json;
|
callback = json;
|
||||||
@ -218,19 +227,36 @@ HTTPClient.prototype._request = function _request(method, endpoint, json, callba
|
|||||||
json = true;
|
json = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (this.apiKey) {
|
||||||
|
if (method === 'get') {
|
||||||
|
query = query || {};
|
||||||
|
query.apiKey = this.apiKey.toString('hex');
|
||||||
|
} else {
|
||||||
|
json = json || {};
|
||||||
|
json.apiKey = this.apiKey.toString('hex');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
request({
|
request({
|
||||||
method: method,
|
method: method,
|
||||||
uri: this.uri + endpoint,
|
uri: this.uri + endpoint,
|
||||||
query: query,
|
query: query,
|
||||||
json: json,
|
json: json,
|
||||||
|
auth: this.auth,
|
||||||
expect: 'json'
|
expect: 'json'
|
||||||
}, function(err, res, body) {
|
}, function(err, res, body) {
|
||||||
if (err)
|
if (err)
|
||||||
return callback(err);
|
return callback(err);
|
||||||
|
|
||||||
networkType = res.headers['x-bcoin-network'];
|
network = res.headers['x-bcoin-network'];
|
||||||
assert(networkType === self.network.type, 'Wrong network.');
|
|
||||||
self.network.updateHeight(+res.headers['x-bcoin-height']);
|
if (network !== self.network.type)
|
||||||
|
return callback(new Error('Wrong network.'));
|
||||||
|
|
||||||
|
height = +res.headers['x-bcoin-height'];
|
||||||
|
|
||||||
|
if (utils.isNumber(height))
|
||||||
|
self.network.updateHeight(height);
|
||||||
|
|
||||||
if (res.statusCode === 404)
|
if (res.statusCode === 404)
|
||||||
return callback();
|
return callback();
|
||||||
@ -820,6 +846,40 @@ HTTPClient.prototype.walletSend = function walletSend(id, options, callback) {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generate a new token.
|
||||||
|
* @param {(String|Buffer)?} passphrase
|
||||||
|
* @param {Function} callback
|
||||||
|
*/
|
||||||
|
|
||||||
|
HTTPClient.prototype.walletRetoken = function walletRetoken(id, passphrase, callback) {
|
||||||
|
var options = { passphrase: passphrase };
|
||||||
|
|
||||||
|
callback = utils.ensure(callback);
|
||||||
|
|
||||||
|
return this._post('/wallet/' + id + '/retoken', options, function(err, body) {
|
||||||
|
if (err)
|
||||||
|
return callback(err);
|
||||||
|
|
||||||
|
return callback(null, body.token);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Change or set master key's passphrase.
|
||||||
|
* @param {(String|Buffer)?} old
|
||||||
|
* @param {String|Buffer} new_
|
||||||
|
* @param {Function} callback
|
||||||
|
*/
|
||||||
|
|
||||||
|
HTTPClient.prototype.walletSetPassphrase = function walletSetPassphrase(id, old, new_, callback) {
|
||||||
|
var options = { old: old, passphrase: new_ };
|
||||||
|
|
||||||
|
callback = utils.ensure(callback);
|
||||||
|
|
||||||
|
return this._post('/wallet/' + id + '/passphrase', options, callback);
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a transaction, fill.
|
* Create a transaction, fill.
|
||||||
* @param {WalletID} id
|
* @param {WalletID} id
|
||||||
|
|||||||
@ -32,6 +32,8 @@ function HTTPServer(options) {
|
|||||||
if (!options)
|
if (!options)
|
||||||
options = {};
|
options = {};
|
||||||
|
|
||||||
|
EventEmitter.call(this);
|
||||||
|
|
||||||
this.options = options;
|
this.options = options;
|
||||||
this.node = options.node;
|
this.node = options.node;
|
||||||
|
|
||||||
@ -221,7 +223,16 @@ HTTPServer.prototype._init = function _init() {
|
|||||||
if (req.password) {
|
if (req.password) {
|
||||||
assert(utils.isHex(req.password), 'API key must be a hex string.');
|
assert(utils.isHex(req.password), 'API key must be a hex string.');
|
||||||
assert(req.password.length === 64, 'API key must be 32 bytes.');
|
assert(req.password.length === 64, 'API key must be 32 bytes.');
|
||||||
options.apiKey = new Buffer(req.password, 'hex');
|
options.token = new Buffer(req.password, 'hex');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (req.headers['x-bcoin-api-key'])
|
||||||
|
params.apiKey = req.headers['x-bcoin-api-key'];
|
||||||
|
|
||||||
|
if (params.apiKey) {
|
||||||
|
assert(utils.isHex(params.apiKey), 'API key must be a hex string.');
|
||||||
|
assert(params.apiKey.length === 64, 'API key must be 32 bytes.');
|
||||||
|
options.apiKey = new Buffer(params.apiKey, 'hex');
|
||||||
}
|
}
|
||||||
|
|
||||||
req.options = options;
|
req.options = options;
|
||||||
@ -230,21 +241,20 @@ HTTPServer.prototype._init = function _init() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
this.use(function(req, res, next, send) {
|
this.use(function(req, res, next, send) {
|
||||||
if (req.path.length < 2 || req.path[0] !== 'wallet') {
|
if (self.apiKey) {
|
||||||
if (self.apiKey) {
|
if (!utils.ccmp(req.options.apiKey, self.apiKey)) {
|
||||||
if (!utils.ccmp(req.options.apiKey, self.apiKey)) {
|
send(403, { error: 'Forbidden.' });
|
||||||
res.setHeader('WWW-Authenticate', 'Basic realm="node"');
|
return;
|
||||||
send(401, { error: 'Unauthorized.' });
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return next();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!self.options.auth)
|
if (req.path.length < 2 || req.path[0] !== 'wallet')
|
||||||
return next();
|
return next();
|
||||||
|
|
||||||
self.walletdb.auth(req.options.id, req.options.apiKey, function(err) {
|
if (!self.options.walletAuth)
|
||||||
|
return next();
|
||||||
|
|
||||||
|
self.walletdb.auth(req.options.id, req.options.token, function(err) {
|
||||||
if (err) {
|
if (err) {
|
||||||
if (err.message === 'Wallet not found.')
|
if (err.message === 'Wallet not found.')
|
||||||
return next();
|
return next();
|
||||||
@ -255,6 +265,7 @@ HTTPServer.prototype._init = function _init() {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
self.logger.info('Successful auth for %s.', req.options.id);
|
||||||
next();
|
next();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@ -515,16 +526,6 @@ HTTPServer.prototype._init = function _init() {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
// Broadcast TX
|
|
||||||
this.post('/wallet/:id/broadcast', function(req, res, next, send) {
|
|
||||||
self.node.sendTX(req.options.tx, function(err) {
|
|
||||||
if (err)
|
|
||||||
return next(err);
|
|
||||||
|
|
||||||
send(200, { success: true });
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
// Send TX
|
// Send TX
|
||||||
this.post('/wallet/:id/send', function(req, res, next, send) {
|
this.post('/wallet/:id/send', function(req, res, next, send) {
|
||||||
var id = req.options.id;
|
var id = req.options.id;
|
||||||
@ -833,25 +834,17 @@ HTTPServer.prototype._initIO = function _initIO() {
|
|||||||
self.emit('error', err);
|
self.emit('error', err);
|
||||||
});
|
});
|
||||||
|
|
||||||
socket.on('join', function(id, apiKey) {
|
socket.on('join', function(id, token) {
|
||||||
if (!self.options.auth) {
|
if (!self.options.walletAuth) {
|
||||||
socket.join(id);
|
socket.join(id);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (id === '!all') {
|
self.walletdb.auth(id, token, function(err) {
|
||||||
if (self.apiKey) {
|
|
||||||
if (!utils.ccmp(apiKey, self.apiKey)) {
|
|
||||||
self.logger.info('Auth failure for %s.', id);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return socket.join(id);
|
|
||||||
}
|
|
||||||
self.walletdb.auth(id, apiKey, function(err) {
|
|
||||||
if (err) {
|
if (err) {
|
||||||
self.logger.info('Auth failure for %s: %s.', id, err.message);
|
self.logger.info('Auth failure for %s: %s.', id, err.message);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
self.logger.info('Successful auth for %s.', id);
|
||||||
socket.join(id);
|
socket.join(id);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@ -912,17 +905,13 @@ HTTPServer.prototype._initIO = function _initIO() {
|
|||||||
this.walletdb.on('address', function(receive, change, map) {
|
this.walletdb.on('address', function(receive, change, map) {
|
||||||
var summary = map.toJSON();
|
var summary = map.toJSON();
|
||||||
|
|
||||||
if (receive) {
|
receive = receive.map(function(address) {
|
||||||
receive = receive.map(function(address) {
|
return address.toJSON();
|
||||||
return address.toJSON();
|
});
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
if (change) {
|
change = change.map(function(address) {
|
||||||
change = change.map(function(address) {
|
return address.toJSON();
|
||||||
return address.toJSON();
|
});
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
map.getWallets().forEach(function(id) {
|
map.getWallets().forEach(function(id) {
|
||||||
self.server.io.to(id).emit('address', receive, change, summary);
|
self.server.io.to(id).emit('address', receive, change, summary);
|
||||||
|
|||||||
@ -37,6 +37,8 @@ function HTTPWallet(options) {
|
|||||||
|
|
||||||
this.client = new http.client(options);
|
this.client = new http.client(options);
|
||||||
this.uri = options.uri;
|
this.uri = options.uri;
|
||||||
|
this.id = null;
|
||||||
|
this.token = null;
|
||||||
|
|
||||||
this._init();
|
this._init();
|
||||||
}
|
}
|
||||||
@ -63,8 +65,8 @@ HTTPWallet.prototype._init = function _init() {
|
|||||||
self.emit('updated', tx, map);
|
self.emit('updated', tx, map);
|
||||||
});
|
});
|
||||||
|
|
||||||
this.client.on('balance', function(balance, map) {
|
this.client.on('balance', function(balance, id) {
|
||||||
self.emit('balance', balance, map);
|
self.emit('balance', balance, id);
|
||||||
});
|
});
|
||||||
|
|
||||||
this.client.on('address', function(receive, change, map) {
|
this.client.on('address', function(receive, change, map) {
|
||||||
@ -74,8 +76,6 @@ HTTPWallet.prototype._init = function _init() {
|
|||||||
this.client.on('error', function(err) {
|
this.client.on('error', function(err) {
|
||||||
self.emit('error', err);
|
self.emit('error', err);
|
||||||
});
|
});
|
||||||
|
|
||||||
this.client.join(this.id);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -84,12 +84,39 @@ HTTPWallet.prototype._init = function _init() {
|
|||||||
* @param {Function} callback
|
* @param {Function} callback
|
||||||
*/
|
*/
|
||||||
|
|
||||||
HTTPWallet.prototype.open = function open(callback) {
|
HTTPWallet.prototype.open = function open(options, callback) {
|
||||||
var self = this;
|
var self = this;
|
||||||
|
|
||||||
|
if (options.token) {
|
||||||
|
if (typeof options.token === 'string') {
|
||||||
|
assert(utils.isHex(options.token), 'API key must be a hex string.');
|
||||||
|
options.token = new Buffer(options.token, 'hex');
|
||||||
|
}
|
||||||
|
assert(Buffer.isBuffer(options.token));
|
||||||
|
assert(options.token.length === 32, 'API key must be 32 bytes.');
|
||||||
|
this.id = options.id;
|
||||||
|
this.client.auth = { username: 'x', password: options.token.toString('hex') };
|
||||||
|
}
|
||||||
|
|
||||||
this.client.open(function(err) {
|
this.client.open(function(err) {
|
||||||
if (err)
|
if (err)
|
||||||
return callback(err);
|
return callback(err);
|
||||||
self.createWallet(self.options, callback);
|
|
||||||
|
if (options.token) {
|
||||||
|
self.token = options.token;
|
||||||
|
self.client.join(options.id, options.token.toString('hex'));
|
||||||
|
return callback();
|
||||||
|
}
|
||||||
|
|
||||||
|
self.client.createWallet(options, function(err, wallet) {
|
||||||
|
if (err)
|
||||||
|
return callback(err);
|
||||||
|
self.id = wallet.id;
|
||||||
|
self.client.auth = { username: 'x', password: wallet.token };
|
||||||
|
self.token = new Buffer(wallet.token, 'hex');
|
||||||
|
self.client.join(self.id, wallet.token);
|
||||||
|
callback(null, wallet);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -179,16 +206,16 @@ HTTPWallet.prototype.zap = function zap(account, age, callback) {
|
|||||||
* @see Wallet#createTX
|
* @see Wallet#createTX
|
||||||
*/
|
*/
|
||||||
|
|
||||||
HTTPWallet.prototype.createTX = function createTX(tx, options, outputs, callback) {
|
HTTPWallet.prototype.createTX = function createTX(options, outputs, callback) {
|
||||||
return this.client.walletCreate(this.id, tx, options, outputs, callback);
|
return this.client.walletCreate(this.id, options, outputs, callback);
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @see HTTPClient#walletSend
|
* @see HTTPClient#walletSend
|
||||||
*/
|
*/
|
||||||
|
|
||||||
HTTPWallet.prototype.send = function send(tx, options, callback) {
|
HTTPWallet.prototype.send = function send(options, callback) {
|
||||||
return this.client.walletSend(this.id, tx, options, callback);
|
return this.client.walletSend(this.id, options, callback);
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -231,6 +258,31 @@ HTTPWallet.prototype.createAccount = function createAccount(options, callback) {
|
|||||||
return this.client.createWalletAccount(this.id, options, callback);
|
return this.client.createWalletAccount(this.id, options, callback);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see Wallet#setPassphrase
|
||||||
|
*/
|
||||||
|
|
||||||
|
HTTPWallet.prototype.setPassphrase = function setPassphrase(old, _new, callback) {
|
||||||
|
return this.client.walletSetPassphrase(this.id, old, _new, callback);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see Wallet#retoken
|
||||||
|
*/
|
||||||
|
|
||||||
|
HTTPWallet.prototype.retoken = function retoken(passphrase, callback) {
|
||||||
|
var self = this;
|
||||||
|
return this.client.walletRetoken(this.id, passphrase, function(err, token) {
|
||||||
|
if (err)
|
||||||
|
return callback(err);
|
||||||
|
|
||||||
|
self.client.auth = { username: 'x', password: token };
|
||||||
|
self.token = new Buffer(token, 'hex');
|
||||||
|
|
||||||
|
return callback(null, token);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Expose
|
* Expose
|
||||||
*/
|
*/
|
||||||
|
|||||||
@ -81,7 +81,7 @@ function SPVNode(options) {
|
|||||||
port: this.options.httpPort || this.network.rpcPort,
|
port: this.options.httpPort || this.network.rpcPort,
|
||||||
host: this.options.httpHost || '0.0.0.0',
|
host: this.options.httpHost || '0.0.0.0',
|
||||||
apiKey: this.options.apiKey,
|
apiKey: this.options.apiKey,
|
||||||
auth: this.options.auth
|
walletAuth: this.options.walletAuth
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1937,6 +1937,22 @@ WalletMap.prototype.fromTX = function fromTX(table, tx) {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Already have a member for this account.
|
||||||
|
// i.e. Different address, but same account.
|
||||||
|
if (member) {
|
||||||
|
// Increment value.
|
||||||
|
if (io.coin)
|
||||||
|
member.value += io.coin.value;
|
||||||
|
else if (io.value)
|
||||||
|
member.value += io.value;
|
||||||
|
|
||||||
|
// Set address and add path.
|
||||||
|
path.address = address;
|
||||||
|
member.paths.push(path);
|
||||||
|
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
// Create a member for this account.
|
// Create a member for this account.
|
||||||
assert(!member);
|
assert(!member);
|
||||||
member = MapMember.fromPath(path);
|
member = MapMember.fromPath(path);
|
||||||
@ -1966,7 +1982,8 @@ WalletMap.prototype.fromTX = function fromTX(table, tx) {
|
|||||||
// Update this guy last so the above if
|
// Update this guy last so the above if
|
||||||
// clause does not return true while
|
// clause does not return true while
|
||||||
// we're still iterating over paths.
|
// we're still iterating over paths.
|
||||||
hashes[hash] = true;
|
if (paths.length > 0)
|
||||||
|
hashes[hash] = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -377,6 +377,7 @@ Wallet.prototype.unlock = function unlock(passphrase, timeout, callback) {
|
|||||||
* It is represented as `m/44` (public) hashed
|
* It is represented as `m/44` (public) hashed
|
||||||
* and converted to an address with a prefix
|
* and converted to an address with a prefix
|
||||||
* of `0x03be04` (`WLT` in base58).
|
* of `0x03be04` (`WLT` in base58).
|
||||||
|
* @private
|
||||||
* @returns {Base58String}
|
* @returns {Base58String}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@ -400,6 +401,8 @@ Wallet.prototype.getID = function getID() {
|
|||||||
/**
|
/**
|
||||||
* Generate the wallet api key if none was passed in.
|
* Generate the wallet api key if none was passed in.
|
||||||
* It is represented as HASH256(m/44'->public|nonce).
|
* It is represented as HASH256(m/44'->public|nonce).
|
||||||
|
* @private
|
||||||
|
* @param {HDPrivateKey} master
|
||||||
* @param {Number} nonce
|
* @param {Number} nonce
|
||||||
* @returns {Buffer}
|
* @returns {Buffer}
|
||||||
*/
|
*/
|
||||||
@ -779,6 +782,12 @@ Wallet.prototype.deriveInputs = function deriveInputs(tx, callback) {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve a single keyring by address hash.
|
||||||
|
* @param {Hash} hash
|
||||||
|
* @param {Function} callback
|
||||||
|
*/
|
||||||
|
|
||||||
Wallet.prototype.getKeyring = function getKeyring(hash, callback) {
|
Wallet.prototype.getKeyring = function getKeyring(hash, callback) {
|
||||||
var self = this;
|
var self = this;
|
||||||
var address;
|
var address;
|
||||||
|
|||||||
@ -474,6 +474,7 @@ WalletDB.prototype.save = function save(wallet, callback) {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
WalletDB.prototype.auth = function auth(id, token, callback) {
|
WalletDB.prototype.auth = function auth(id, token, callback) {
|
||||||
|
var self = this;
|
||||||
var wallet;
|
var wallet;
|
||||||
|
|
||||||
if (!id)
|
if (!id)
|
||||||
@ -1154,14 +1155,14 @@ WalletDB.prototype.fetchWallet = function fetchWallet(id, callback, handler) {
|
|||||||
if (!wallet)
|
if (!wallet)
|
||||||
return callback(new Error('No wallet.'));
|
return callback(new Error('No wallet.'));
|
||||||
|
|
||||||
handler(wallet, function(err, result) {
|
handler(wallet, function(err, res1, res2) {
|
||||||
// Kill the reference.
|
// Kill the reference.
|
||||||
wallet.destroy();
|
wallet.destroy();
|
||||||
|
|
||||||
if (err)
|
if (err)
|
||||||
return callback(err);
|
return callback(err);
|
||||||
|
|
||||||
callback(null, result);
|
callback(null, res1, res2);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|||||||
178
test/http-test.js
Normal file
178
test/http-test.js
Normal file
@ -0,0 +1,178 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
var bn = require('bn.js');
|
||||||
|
var bcoin = require('../').set('regtest');
|
||||||
|
var constants = bcoin.protocol.constants;
|
||||||
|
var network = bcoin.protocol.network;
|
||||||
|
var utils = bcoin.utils;
|
||||||
|
var assert = require('assert');
|
||||||
|
var scriptTypes = constants.scriptTypes;
|
||||||
|
|
||||||
|
var dummyInput = {
|
||||||
|
prevout: {
|
||||||
|
hash: constants.NULL_HASH,
|
||||||
|
index: 0
|
||||||
|
},
|
||||||
|
coin: {
|
||||||
|
version: 1,
|
||||||
|
height: 0,
|
||||||
|
value: constants.MAX_MONEY,
|
||||||
|
script: new bcoin.script([]),
|
||||||
|
coinbase: false,
|
||||||
|
hash: constants.NULL_HASH,
|
||||||
|
index: 0
|
||||||
|
},
|
||||||
|
script: new bcoin.script([]),
|
||||||
|
witness: new bcoin.witness([]),
|
||||||
|
sequence: 0xffffffff
|
||||||
|
};
|
||||||
|
|
||||||
|
describe('HTTP', function() {
|
||||||
|
var request = bcoin.http.request;
|
||||||
|
var apiKey = utils.hash256(new Buffer([]));
|
||||||
|
var w, addr, hash;
|
||||||
|
|
||||||
|
this.timeout(15000);
|
||||||
|
|
||||||
|
var node = new bcoin.fullnode({
|
||||||
|
network: 'regtest',
|
||||||
|
apiKey: apiKey,
|
||||||
|
walletAuth: true
|
||||||
|
});
|
||||||
|
|
||||||
|
var wallet = new bcoin.http.wallet({
|
||||||
|
network: 'regtest',
|
||||||
|
apiKey: apiKey
|
||||||
|
});
|
||||||
|
|
||||||
|
node.on('error', function() {});
|
||||||
|
|
||||||
|
it('should open node', function(cb) {
|
||||||
|
constants.tx.COINBASE_MATURITY = 0;
|
||||||
|
node.open(cb);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should create wallet', function(cb) {
|
||||||
|
wallet.open({ id: 'test' }, function(err, wallet) {
|
||||||
|
assert.ifError(err);
|
||||||
|
assert.equal(wallet.id, 'test');
|
||||||
|
cb();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should get info', function(cb) {
|
||||||
|
wallet.client.getInfo(function(err, info) {
|
||||||
|
assert.ifError(err);
|
||||||
|
assert.equal(info.network, node.network.type);
|
||||||
|
assert.equal(info.version, constants.USER_VERSION);
|
||||||
|
assert.equal(info.agent, constants.USER_AGENT);
|
||||||
|
assert.equal(info.height, 0);
|
||||||
|
cb();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should get wallet info', function(cb) {
|
||||||
|
wallet.getInfo(function(err, wallet) {
|
||||||
|
assert.ifError(err);
|
||||||
|
assert.equal(wallet.id, 'test');
|
||||||
|
addr = wallet.account.receiveAddress;
|
||||||
|
assert.equal(typeof addr, 'string');
|
||||||
|
cb();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
/*
|
||||||
|
it('should get internal wallet', function(cb) {
|
||||||
|
node.walletdb.get('test', function(err, w_) {
|
||||||
|
assert.ifError(err);
|
||||||
|
assert(w_);
|
||||||
|
w = w_;
|
||||||
|
cb();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
*/
|
||||||
|
|
||||||
|
it('should fill with funds', function(cb) {
|
||||||
|
var balance, receive;
|
||||||
|
|
||||||
|
// Coinbase
|
||||||
|
var t1 = bcoin.mtx()
|
||||||
|
.addOutput(addr, 50460)
|
||||||
|
.addOutput(addr, 50460)
|
||||||
|
.addOutput(addr, 50460)
|
||||||
|
.addOutput(addr, 50460);
|
||||||
|
|
||||||
|
t1.addInput(dummyInput);
|
||||||
|
|
||||||
|
wallet.once('balance', function(b, id) {
|
||||||
|
balance = b;
|
||||||
|
});
|
||||||
|
|
||||||
|
wallet.once('address', function(r, c, map) {
|
||||||
|
receive = r[0];
|
||||||
|
});
|
||||||
|
|
||||||
|
node.walletdb.addTX(t1, function(err) {
|
||||||
|
assert.ifError(err);
|
||||||
|
setTimeout(function() {
|
||||||
|
return cb();
|
||||||
|
assert(receive);
|
||||||
|
assert.equal(receive.id, 'test');
|
||||||
|
assert.equal(receive.type, 'pubkeyhash');
|
||||||
|
assert.equal(receive.change, 0);
|
||||||
|
assert(balance);
|
||||||
|
assert.equal(balance.confirmed, 0);
|
||||||
|
assert.equal(balance.unconfirmed, 201840);
|
||||||
|
assert.equal(balance.total, 201840);
|
||||||
|
cb();
|
||||||
|
}, 2000);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should get balance', function(cb) {
|
||||||
|
wallet.getBalance(function(err, balance) {
|
||||||
|
assert.ifError(err);
|
||||||
|
assert.equal(balance.confirmed, 0);
|
||||||
|
assert.equal(balance.unconfirmed, 201840);
|
||||||
|
assert.equal(balance.total, 201840);
|
||||||
|
cb();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should send a tx', function(cb) {
|
||||||
|
var options = {
|
||||||
|
rate: 10000,
|
||||||
|
outputs: [{
|
||||||
|
value: 10000,
|
||||||
|
address: addr
|
||||||
|
}]
|
||||||
|
};
|
||||||
|
|
||||||
|
wallet.send(options, function(err, tx) {
|
||||||
|
assert.ifError(err);
|
||||||
|
assert(tx);
|
||||||
|
assert.equal(tx.inputs.length, 1);
|
||||||
|
assert.equal(tx.outputs.length, 2);
|
||||||
|
assert.equal(tx.getOutputValue(), 48190);
|
||||||
|
hash = tx.hash('hex');
|
||||||
|
node.walletdb.addTX(tx, function(err) {
|
||||||
|
assert.ifError(err);
|
||||||
|
cb();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should get a tx', function(cb) {
|
||||||
|
wallet.getTX(hash, function(err, tx) {
|
||||||
|
assert.ifError(err);
|
||||||
|
assert(tx);
|
||||||
|
assert.equal(tx.hash('hex'), hash);
|
||||||
|
cb();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should cleanup', function(cb) {
|
||||||
|
constants.tx.COINBASE_MATURITY = 100;
|
||||||
|
node.close(cb);
|
||||||
|
});
|
||||||
|
});
|
||||||
Loading…
Reference in New Issue
Block a user