http wallet.

This commit is contained in:
Christopher Jeffrey 2016-06-02 05:25:14 -07:00
parent aa163bce33
commit 2f492dfc89
No known key found for this signature in database
GPG Key ID: 8962AB9DE6666BBD
6 changed files with 453 additions and 269 deletions

View File

@ -41,18 +41,12 @@ function createWallet(callback) {
if (argv.lookahead)
options.lookahead = argv.lookahead >>> 0;
if (argv.derivation)
options.derivation = argv.derivation;
if (argv.m)
options.m = argv.m >>> 0;
if (argv.n)
options.n = argv.n >>> 0;
if (argv.copay != null)
options.copayBIP45 = !!argv.copay;
if (argv.witness != null)
options.witness = !!argv.witness;
@ -63,7 +57,6 @@ function createWallet(callback) {
if (err)
return callback(err);
utils.print(wallet);
wallet.destroy();
callback();
});
}
@ -75,7 +68,7 @@ function addKey(callback) {
keys = keys.split(',');
else
keys = argv.args;
client.addKey(id, keys, function(err, wallet) {
client.addKey(id, argv.account, keys, function(err, wallet) {
if (err)
return callback(err);
utils.print('added');
@ -90,7 +83,7 @@ function removeKey(callback) {
keys = keys.split(',');
else
keys = argv.args;
client.removeKey(id, keys, function(err) {
client.removeKey(id, argv.account, keys, function(err) {
if (err)
return callback(err);
utils.print('removed');
@ -101,7 +94,7 @@ function removeKey(callback) {
function getWallet(callback) {
var id = getID();
var passphrase = argv.args[0];
client.getWallet(id, passphrase, function(err, wallet) {
client.getWallet(id, argv.account, passphrase, function(err, wallet) {
if (err)
return callback(err);
utils.print(wallet);
@ -185,7 +178,7 @@ function getCoin(callback) {
function getWalletHistory(callback) {
var id = getID();
client.getWalletHistory(id, function(err, txs) {
client.getWalletHistory(id, argv.account, function(err, txs) {
if (err)
return callback(err);
utils.print(txs);
@ -195,7 +188,7 @@ function getWalletHistory(callback) {
function listenWallet(callback) {
var id = getID();
client.listenWallet(id);
client.join(id);
client.on('tx', function(tx, map) {
utils.print('TX:');
utils.print(tx);
@ -220,7 +213,7 @@ function listenWallet(callback) {
function getBalance(callback) {
var id = getID();
client.getWalletBalance(id, function(err, balance) {
client.getWalletBalance(id, argv.account, function(err, balance) {
if (err)
return callback(err);
utils.print('Confirmed: %s', utils.btc(balance.confirmed));
@ -241,15 +234,16 @@ function getMempool(callback) {
function send(callback) {
var id = getID();
var options = {};
var options = { account: argv.account, passphrase: argv.passphrase };
var output = {};
if (argv.script) {
options.script = new bcoin.script(new Buffer(argv.script, 'hex'));
options.value = utils.satoshi(argv.value || argv.args[0]);
output.script = new bcoin.script(new Buffer(argv.script, 'hex'));
output.value = utils.satoshi(argv.value || argv.args[0]);
} else {
options.address = argv.address || argv.args[0];
options.value = utils.satoshi(argv.value || argv.args[1]);
output.address = argv.address || argv.args[0];
output.value = utils.satoshi(argv.value || argv.args[1]);
}
client.walletSend(id, options, function(err, tx) {
client.walletSend(id, options, [output], function(err, tx) {
if (err)
return callback(err);
utils.print(tx);
@ -259,9 +253,8 @@ function send(callback) {
function zap(callback) {
var id = getID();
var now = (argv.now >>> 0) || utils.now();
var age = (argv.age >>> 0) || 72 * 60 * 60;
client.walletZap(id, now, age, function(err) {
client.walletZap(id, argv.account, age, function(err) {
if (err)
return callback(err);
utils.print('zapped');
@ -309,7 +302,7 @@ function main(callback) {
utils.print(' $ balance [id]: Get wallet balance.');
utils.print(' $ history [id]: View wallet TX history.');
utils.print(' $ send [id] [address] [value] --script [code]: Send transaction.');
utils.print(' $ zap [id] --now [now] --age [age]: Zap pending wallet TXs.');
utils.print(' $ zap [id] --age [age]: Zap pending wallet TXs.');
utils.print(' $ mempool: Get mempool snapshot.');
utils.print(' $ tx [hash/address]: View transactions.');
utils.print(' $ coin [hash+index/address]: View coins.');
@ -374,7 +367,7 @@ function parseArg(argv) {
client.getInfo(function(err, info) {
if (err) {
console.error(err.stack + '');
return process.exit(1);
//return process.exit(1);
}
if (!argv.args[0])

View File

@ -99,7 +99,7 @@ HTTPBase.prototype._initRouter = function _initRouter() {
function done(err) {
if (err) {
send(res, 400, { error: err.stack + '' });
send(res, 400, { error: err.message + '' });
try {
req.destroy();
req.socket.destroy();
@ -372,7 +372,7 @@ function compilePath(path) {
return { regex: path, map: map };
var regex = path
.replace(/([^\/]+)\?/g, '(?:$1)?')
.replace(/(\/[^\/]+)\?/g, '(?:$1)?')
.replace(/\.(?!\+)/g, '\\.')
.replace(/\*/g, '.*?')
.replace(/%/g, '\\')

View File

@ -136,7 +136,7 @@ HTTPClient.prototype.open = function open(callback) {
* @param {WalletID} id
*/
HTTPClient.prototype.listenWallet = function listenWallet(id) {
HTTPClient.prototype.join = function join(id) {
if (!this.socket)
return;
@ -148,7 +148,7 @@ HTTPClient.prototype.listenWallet = function listenWallet(id) {
* @param {WalletID} id
*/
HTTPClient.prototype.unlistenWallet = function unlistenWallet(id) {
HTTPClient.prototype.leave = function leave(id) {
if (!this.socket)
return;
@ -159,16 +159,16 @@ HTTPClient.prototype.unlistenWallet = function unlistenWallet(id) {
* Listen for events on all wallets.
*/
HTTPClient.prototype.listenAll = function listenAll() {
this.listenWallet('!all');
HTTPClient.prototype.all = function all() {
this.join('!all');
};
/**
* Unlisten for events on all wallets.
*/
HTTPClient.prototype.unlistenAll = function unlistenAll() {
this.unlistenWallet('!all');
HTTPClient.prototype.none = function none() {
this.leave('!all');
};
/**
@ -233,8 +233,11 @@ HTTPClient.prototype._request = function _request(method, endpoint, json, callba
if (!body)
return callback(new Error('No body.'));
if (res.statusCode !== 200)
if (res.statusCode !== 200) {
if (body.error)
return callback(new Error(body.error));
return callback(new Error('Status code: ' + res.statusCode));
}
try {
return callback(null, body);
@ -299,7 +302,7 @@ HTTPClient.prototype._del = function _del(endpoint, json, callback) {
* @param {Function} callback - Returns [Error, Object].
*/
HTTPClient.prototype._createWallet = function createWallet(options, callback) {
HTTPClient.prototype.createWallet = function createWallet(options, callback) {
return this._post('/wallet', options, callback);
};
@ -310,71 +313,27 @@ HTTPClient.prototype._createWallet = function createWallet(options, callback) {
* @param {Function} callback - Returns [Error, Object].
*/
HTTPClient.prototype._getWallet = function getWallet(id, callback) {
HTTPClient.prototype.getWallet = function getWallet(id, callback) {
return this._get('/wallet/' + id, callback);
};
/**
* Get wallet and setup http provider (note that the
* passphrase is _not_ sent over the wire).
* @param {WalletID} id
* @param {String?} passphrase
* @param {Function} callback - Returns [Error, {@link Wallet}].
*/
HTTPClient.prototype.getWallet = function getWallet(id, passphrase, callback) {
var self = this;
return this._getWallet(id, function(err, json) {
if (err)
return callback(err);
try {
json = bcoin.wallet.parseJSON(json, passphrase);
} catch (e) {
return callback(e);
}
json.provider = new bcoin.http.provider(self.options);
return callback(null, new bcoin.wallet(json));
});
};
/**
* Get wallet and setup http provider (note that the
* passphrase is _not_ sent over the wire).
* @param {WalletID} id
* @param {String?} passphrase
* @param {Function} callback - Returns [Error, {@link Wallet}].
*/
HTTPClient.prototype.createWallet = function createWallet(options, callback) {
var self = this;
return this._createWallet(options, function(err, json) {
if (err)
return callback(err);
try {
json = bcoin.wallet.parseJSON(json, options.passphrase);
} catch (e) {
return callback(e);
}
json.provider = new bcoin.http.provider(self.options);
return callback(null, new bcoin.wallet(json));
});
};
/**
* Get wallet transaction history.
* @param {WalletID} id
* @param {Function} callback - Returns [Error, {@link TX}[]].
*/
HTTPClient.prototype.getWalletHistory = function getWalletHistory(id, callback) {
return this._get('/wallet/' + id + '/tx/history', function(err, body) {
HTTPClient.prototype.getWalletHistory = function getWalletHistory(id, account, callback) {
var options;
if (typeof account === 'function') {
callback = account;
account = null;
}
options = { account: account };
return this._get('/wallet/' + id + '/tx/history', options, function(err, body) {
if (err)
return callback(err);
@ -399,8 +358,17 @@ HTTPClient.prototype.getWalletHistory = function getWalletHistory(id, callback)
* @param {Function} callback - Returns [Error, {@link Coin}[]].
*/
HTTPClient.prototype.getWalletCoins = function getWalletCoins(id, callback) {
return this._get('/wallet/' + id + '/coin', function(err, body) {
HTTPClient.prototype.getWalletCoins = function getWalletCoins(id, account, callback) {
var options;
if (typeof account === 'function') {
callback = account;
account = null;
}
options = { account: account };
return this._get('/wallet/' + id + '/coin', options, function(err, body) {
if (err)
return callback(err);
@ -425,8 +393,17 @@ HTTPClient.prototype.getWalletCoins = function getWalletCoins(id, callback) {
* @param {Function} callback - Returns [Error, {@link TX}[]].
*/
HTTPClient.prototype.getWalletUnconfirmed = function getUnconfirmed(id, callback) {
return this._get('/wallet/' + id + '/tx/unconfirmed', function(err, body) {
HTTPClient.prototype.getWalletUnconfirmed = function getUnconfirmed(id, account, callback) {
var options;
if (typeof account === 'function') {
callback = account;
account = null;
}
options = { account: account };
return this._get('/wallet/' + id + '/tx/unconfirmed', options, function(err, body) {
if (err)
return callback(err);
@ -451,8 +428,17 @@ HTTPClient.prototype.getWalletUnconfirmed = function getUnconfirmed(id, callback
* @param {Function} callback - Returns [Error, {@link Balance}].
*/
HTTPClient.prototype.getWalletBalance = function getBalance(id, callback) {
return this._get('/wallet/' + id + '/balance', function(err, body) {
HTTPClient.prototype.getWalletBalance = function getBalance(id, account, callback) {
var options;
if (typeof account === 'function') {
callback = account;
account = null;
}
options = { account: account };
return this._get('/wallet/' + id + '/balance', options, function(err, body) {
if (err)
return callback(err);
@ -474,8 +460,16 @@ HTTPClient.prototype.getWalletBalance = function getBalance(id, callback) {
* @param {Function} callback - Returns [Error, {@link TX}[]].
*/
HTTPClient.prototype.getWalletLast = function getWalletLast(id, limit, callback) {
var options = { limit: limit };
HTTPClient.prototype.getWalletLast = function getWalletLast(id, account, limit, callback) {
var options;
if (typeof account === 'function') {
callback = account;
account = null;
}
options = { account: account, limit: limit };
return this._get('/wallet/' + id + '/tx/last', options, function(err, body) {
if (err)
return callback(err);
@ -506,7 +500,16 @@ HTTPClient.prototype.getWalletLast = function getWalletLast(id, limit, callback)
* @param {Function} callback - Returns [Error, {@link TX}[]].
*/
HTTPClient.prototype.getWalletRange = function getWalletRange(id, options, callback) {
HTTPClient.prototype.getWalletRange = function getWalletRange(id, account, options, callback) {
if (typeof options === 'function') {
callback = options;
options = account;
account = null;
}
if (!options.account)
options.account = account;
return this._get('/wallet/' + id + '/tx/range', options, function(err, body) {
if (err)
return callback(err);
@ -534,10 +537,20 @@ HTTPClient.prototype.getWalletRange = function getWalletRange(id, options, callb
* @param {Function} callback - Returns [Error, {@link TX}[]].
*/
HTTPClient.prototype.getWalletTX = function getTX(id, hash, callback) {
HTTPClient.prototype.getWalletTX = function getTX(id, account, hash, callback) {
var options;
if (typeof hash === 'function') {
callback = hash;
hash = account;
account = null;
}
options = { account: account };
hash = utils.revHex(hash);
return this._get('/wallet/' + id + '/tx/' + hash, function(err, body) {
return this._get('/wallet/' + id + '/tx/' + hash, options, function(err, body) {
if (err)
return callback(err);
@ -563,13 +576,22 @@ HTTPClient.prototype.getWalletTX = function getTX(id, hash, callback) {
* @param {Function} callback - Returns [Error, {@link Coin}[]].
*/
HTTPClient.prototype.getWalletCoin = function getCoin(id, hash, index, callback) {
var path;
HTTPClient.prototype.getWalletCoin = function getCoin(id, account, hash, index, callback) {
var options, path;
if (typeof hash === 'function') {
callback = index;
index = hash;
hash = account;
account = null;
}
options = { account: account };
hash = utils.revHex(hash);
path = '/wallet/' + id + '/coin/' + hash + '/' + index;
return this._get(path, function(err, body) {
return this._get(path, options, function(err, body) {
if (err)
return callback(err);
@ -586,28 +608,6 @@ HTTPClient.prototype.getWalletCoin = function getCoin(id, hash, index, callback)
});
};
/**
* Sync wallet receive and change depth with the server.
* @param {WalletID} id
* @param {Object} options
* @param {Number} options.receiveDepth
* @param {Number} options.changeDepth
* @param {Function} callback
*/
HTTPClient.prototype.syncWallet = function syncWallet(id, options, callback) {
var body = {
receiveDepth: options.receiveDepth,
changeDepth: options.changeDepth
};
return this._put('/wallet/' + id, body, function(err) {
if (err)
return callback(err);
return callback();
});
};
/**
* Get coins that pertain to an address from the mempool or chain database.
* Takes into account spent coins in the mempool.
@ -774,15 +774,114 @@ HTTPClient.prototype.broadcast = function broadcast(tx, callback) {
* @param {Function} callback - Returns [Error, {@link TX}].
*/
HTTPClient.prototype.walletSend = function walletSend(id, options, callback) {
var body = {
address: options.address,
value: utils.btc(options.value)
HTTPClient.prototype.walletSend = function walletSend(id, options, outputs, callback) {
if (typeof outputs === 'function') {
callback = outputs;
outputs = null;
}
options = utils.merge({}, options);
options.outputs = outputs || options.outputs || [];
if (!Array.isArray(options.outputs))
options.outputs = [options.outputs];
options.outputs = options.outputs.map(function(output) {
return {
value: utils.btc(output.value),
address: output.address && output.address.toBase58
? output.address.toBase58()
: output.address,
script: output.script ? output.script.toRaw('hex') : null
}
});
callback = utils.ensure(callback);
return this._post('/wallet/' + id + '/send', options, function(err, body) {
if (err)
return callback(err);
try {
body = bcoin.tx.fromJSON(body);
} catch (e) {
return callback(e);
}
return callback(null, body);
});
};
/**
* Create a transaction, fill.
* @param {WalletID} id
* @param {Object} options
* @param {Base58Address} options.address
* @param {Amount} options.value
* @param {Function} callback - Returns [Error, {@link TX}].
*/
HTTPClient.prototype.walletCreate = function walletCreate(id, options, outputs, callback) {
if (typeof outputs === 'function') {
callback = outputs;
outputs = null;
}
options = utils.merge({}, options);
options.outputs = outputs || options.outputs || [];
if (!Array.isArray(options.outputs))
options.outputs = [options.outputs];
options.outputs = options.outputs.map(function(output) {
return {
value: utils.btc(output.value),
address: output.address && output.address.toBase58
? output.address.toBase58()
: output.address,
script: output.script ? output.script.toRaw('hex') : null
}
});
callback = utils.ensure(callback);
return this._post('/wallet/' + id + '/create', options, function(err, body) {
if (err)
return callback(err);
try {
body = bcoin.tx.fromJSON(body);
} catch (e) {
return callback(e);
}
return callback(null, body);
});
};
/**
* Sign a transaction.
* @param {WalletID} id
* @param {Object} options
* @param {Function} callback - Returns [Error, {@link TX}].
*/
HTTPClient.prototype.walletSign = function walletCreate(id, account, options, callback) {
var body;
if (typeof options === 'function') {
callback = options;
options = account;
account = null;
}
body = {
account: account || options.account
};
callback = utils.ensure(callback);
return this._post('/wallet/' + id + '/send', body, function(err, body) {
return this._post('/wallet/' + id + '/sign', body, function(err, body) {
if (err)
return callback(err);
@ -803,15 +902,21 @@ HTTPClient.prototype.walletSend = function walletSend(id, options, callback) {
* @param {Function} callback
*/
HTTPClient.prototype.zapWallet = function zapWallet(id, now, age, callback) {
var body = {
now: now,
HTTPClient.prototype.walletZap = function walletZap(id, account, age, callback) {
var body;
if (typeof age === 'function') {
callback = age;
age = account;
account = null;
}
body = {
account: account,
age: age
};
assert(utils.isNumber(now));
assert(utils.isNumber(age));
assert(now >= age);
callback = utils.ensure(callback);
@ -830,14 +935,24 @@ HTTPClient.prototype.zapWallet = function zapWallet(id, now, age, callback) {
* @param {Function} callback
*/
HTTPClient.prototype.addKey = function addKey(id, keys, callback) {
HTTPClient.prototype.addKey = function addKey(id, account, keys, callback) {
var options;
if (typeof keys === 'function') {
callback = keys;
keys = account;
account = null;
}
if (!Array.isArray(keys))
keys = [keys];
keys = keys.map(function(key) {
return key || key.xpubkey;
return key.xpubkey || key;
});
options = { account: account, keys: keys };
callback = utils.ensure(callback);
return this._put('/wallet/' + id + '/key', keys, function(err) {
@ -856,13 +971,23 @@ HTTPClient.prototype.addKey = function addKey(id, keys, callback) {
*/
HTTPClient.prototype.removeKey = function removeKey(id, keys, callback) {
var options;
if (typeof keys === 'function') {
callback = keys;
keys = account;
account = null;
}
if (!Array.isArray(keys))
keys = [keys];
keys = keys.map(function(key) {
return key || key.xpubkey;
return key.xpubkey || key;
});
options = { account: account, keys: keys };
callback = utils.ensure(callback);
return this._del('/wallet/' + id + '/key', keys, function(err) {

View File

@ -75,9 +75,12 @@ HTTPServer.prototype._init = function _init() {
});
this.use(function(req, res, next, send) {
var params = utils.merge({}, req.query, req.body, req.params);
var params = utils.merge({}, req.params, req.query, req.body);
var options = {};
bcoin.debug('Params:');
bcoin.debug(params);
if (params.id) {
assert(params.id !== '!all');
options.id = params.id;
@ -147,6 +150,9 @@ HTTPServer.prototype._init = function _init() {
}
}
if (params.account)
options.account = params.account;
if (params.now)
options.now = params.now >>> 0;
@ -313,24 +319,57 @@ HTTPServer.prototype._init = function _init() {
});
});
// Get wallet
this.get('/wallet/:id', function(req, res, next, send) {
self.walletdb.getJSON(req.options.id, function(err, json) {
// Mempool snapshot
this.get('/mempool', function(req, res, next, send) {
self.node.mempool.getHistory(function(err, txs) {
if (err)
return next(err);
if (!json)
if (!txs.length)
return send(404);
send(200, json);
utils.forEach(txs, function(tx, next) {
self.node.fillHistory(tx, next);
}, function(err) {
if (err)
return next(err);
send(200, txs.map(function(tx) {
return tx.toJSON();
}));
});
});
});
// Broadcast TX
this.post('/broadcast', function(req, res, next, send) {
self.node.sendTX(req.options.tx, function(err) {
if (err)
return next(err);
send(200, {
success: true
});
});
});
// Get wallet
this.get('/wallet/:id', function(req, res, next, send) {
self.walletdb.getInfo(req.options.id, function(err, wallet) {
if (err)
return next(err);
if (!wallet)
return send(404);
send(200, wallet.toJSON());
});
});
// Create/get wallet
this.post(['/wallet', '/wallet/:id'], function(req, res, next, send) {
this.post('/wallet/:id?', function(req, res, next, send) {
var json;
self.walletdb.ensure(req.options, function(err, wallet) {
var json;
if (err)
return next(err);
@ -344,29 +383,38 @@ HTTPServer.prototype._init = function _init() {
});
});
// Send TX
this.post('/wallet/:id/send', function(req, res, next, send) {
// Create/get account
this.post('/wallet/:id/:account', function(req, res, next, send) {
var id = req.options.id;
var passphrase = req.options.passphrase;
var account = req.options.account;
var options = req.options;
self.walletdb.makeAccount(id, account, options, function(err, account) {
if (err)
return next(err);
if (!account)
return send(404);
send(200, account.toJSON());
});
});
// Send TX
this.post('/wallet/:id/:account?/send', function(req, res, next, send) {
var id = req.options.id;
var options = req.options;
var outputs = req.options.outputs;
if (!Array.isArray(outputs))
return send(400);
self.walletdb.get(id, passphrase, function(err, wallet) {
self.walletdb.createTX(id, options, outputs, function(err, tx) {
if (err)
return next(err);
if (!wallet)
return send(404);
wallet.createTX(outputs, function(err, tx) {
if (err) {
wallet.destroy();
self.walletdb.sign(id, tx, options, function(err) {
if (err)
return next(err);
}
wallet.destroy();
self.node.sendTX(tx, function(err) {
if (err)
@ -378,29 +426,43 @@ HTTPServer.prototype._init = function _init() {
});
});
// Zap Wallet TXs
this.post('/wallet/:id/zap', function(req, res, next, send) {
// Create TX
this.post('/wallet/:id/:account?/create', function(req, res, next, send) {
var id = req.options.id;
var now = req.options.now;
var age = req.options.age;
var options = req.options;
var outputs = req.options.outputs;
self.walletdb.zapWallet(id, now, age, function(err) {
if (!Array.isArray(outputs))
return send(400);
self.walletdb.createTX(id, options, outputs, function(err, tx) {
if (err)
return next(err);
send(200, {
success: true
});
send(200, tx.toJSON());
});
});
// Update wallet / sync address depth
this.put('/wallet/:id', function(req, res, next, send) {
// Sign TX
this.post('/wallet/:id/:account?/sign', function(req, res, next, send) {
var id = req.options.id;
var receive = req.options.receiveDepth;
var change = req.options.changeDepth;
var options = req.options;
self.walletdb.setDepth(id, receive, change, function(err) {
self.walletdb.sign(id, tx, options, function(err) {
if (err)
return next(err);
send(200, tx.toJSON());
});
});
// Zap Wallet TXs
this.post('/wallet/:id/:account?/zap', function(req, res, next, send) {
var id = req.options.id;
var account = req.options.account;
var age = req.options.age;
self.walletdb.zap(id, account, age, function(err) {
if (err)
return next(err);
@ -411,8 +473,11 @@ HTTPServer.prototype._init = function _init() {
});
// Add key
this.put('/wallet/:id/key', function(req, res, next, send) {
self.walletdb.addKey(req.options.id, req.options.keys, function(err) {
this.put('/wallet/:id/:account?/key', function(req, res, next, send) {
var id = req.options.id;
var account = req.options.account;
var keys = req.options.keys;
self.walletdb.addKey(id, account, keys, function(err) {
if (err)
return next(err);
@ -421,8 +486,11 @@ HTTPServer.prototype._init = function _init() {
});
// Remove key
this.del('/wallet/:id/key', function(req, res, next, send) {
self.walletdb.removeKey(req.options.id, req.options.keys, function(err) {
this.del('/wallet/:id/:account?/key', function(req, res, next, send) {
var id = req.options.id;
var account = req.options.account;
var keys = req.options.keys;
self.walletdb.removeKey(id, account, keys, function(err) {
if (err)
return next(err);
@ -431,8 +499,10 @@ HTTPServer.prototype._init = function _init() {
});
// Wallet Balance
this.get('/wallet/:id/balance', function(req, res, next, send) {
self.walletdb.getBalance(req.options.id, function(err, balance) {
this.get('/wallet/:id/:account?/balance', function(req, res, next, send) {
var id = req.options.id;
var account = req.options.account;
self.walletdb.getBalance(id, account, function(err, balance) {
if (err)
return next(err);
@ -448,8 +518,10 @@ HTTPServer.prototype._init = function _init() {
});
// Wallet UTXOs
this.get('/wallet/:id/coin', function(req, res, next, send) {
self.walletdb.getCoins(req.options.id, function(err, coins) {
this.get('/wallet/:id/:account?/coin', function(req, res, next, send) {
var id = req.options.id;
var account = req.options.account;
self.walletdb.getCoins(id, account, function(err, coins) {
if (err)
return next(err);
@ -462,10 +534,10 @@ HTTPServer.prototype._init = function _init() {
});
});
// Wallet TX
this.get('/wallet/:id/coin/:hash/:index', function(req, res, next, send) {
var hash = req.options.hash;
var index = req.options.index;
// Wallet Coin
this.get('/wallet/:id/:account?/coin/:hash/:index', function(req, res, next, send) {
var id = req.options.id;
var account = req.options.account;
self.walletdb.getCoin(hash, index, function(err, coin) {
if (err)
return next(err);
@ -478,8 +550,10 @@ HTTPServer.prototype._init = function _init() {
});
// Wallet TXs
this.get('/wallet/:id/tx/history', function(req, res, next, send) {
self.walletdb.getHistory(req.options.id, function(err, txs) {
this.get('/wallet/:id/:account?/tx/history', function(req, res, next, send) {
var id = req.options.id;
var account = req.options.account;
self.walletdb.getHistory(id, account, function(err, txs) {
if (err)
return next(err);
@ -500,54 +574,60 @@ HTTPServer.prototype._init = function _init() {
});
// Wallet Pending TXs
this.get('/wallet/:id/tx/unconfirmed', function(req, res, next, send) {
self.walletdb.getUnconfirmed(req.options.id, function(err, txs) {
if (err)
return next(err);
if (!txs.length)
return send(404);
utils.forEach(txs, function(tx, next) {
self.walletdb.fillHistory(tx, next);
}, function(err) {
if (err)
return next(err);
send(200, txs.map(function(tx) {
return tx.toJSON();
}));
});
});
});
// Wallet TXs within time range
this.get('/wallet/:id/tx/range', function(req, res, next, send) {
self.walletdb.getRange(req.options.id, req.options, function(err, txs) {
if (err)
return next(err);
if (!txs.length)
return send(404);
utils.forEach(txs, function(tx, next) {
self.walletdb.fillHistory(tx, next);
}, function(err) {
if (err)
return next(err);
send(200, txs.map(function(tx) {
return tx.toJSON();
}));
});
});
});
// Wallet TXs within time range
this.get('/wallet/:id/tx/last', function(req, res, next, send) {
this.get('/wallet/:id/:account?/tx/unconfirmed', function(req, res, next, send) {
var id = req.options.id;
var account = req.options.account;
self.walletdb.getUnconfirmed(id, account, function(err, txs) {
if (err)
return next(err);
if (!txs.length)
return send(404);
utils.forEach(txs, function(tx, next) {
self.walletdb.fillHistory(tx, next);
}, function(err) {
if (err)
return next(err);
send(200, txs.map(function(tx) {
return tx.toJSON();
}));
});
});
});
// Wallet TXs within time range
this.get('/wallet/:id/:account?/tx/range', function(req, res, next, send) {
var id = req.options.id;
var account = req.options.account;
var options = req.options;
self.walletdb.getRange(id, account, options, function(err, txs) {
if (err)
return next(err);
if (!txs.length)
return send(404);
utils.forEach(txs, function(tx, next) {
self.walletdb.fillHistory(tx, next);
}, function(err) {
if (err)
return next(err);
send(200, txs.map(function(tx) {
return tx.toJSON();
}));
});
});
});
// Wallet TXs within time range
this.get('/wallet/:id/:account?/tx/last', function(req, res, next, send) {
var id = req.options.id;
var account = req.options.account;
var limit = req.options.limit;
self.walletdb.getRange(id, limit, function(err, txs) {
self.walletdb.getRange(id, account, limit, function(err, txs) {
if (err)
return next(err);
@ -568,7 +648,7 @@ HTTPServer.prototype._init = function _init() {
});
// Wallet TX
this.get('/wallet/:id/tx/:hash', function(req, res, next, send) {
this.get('/wallet/:id/:account?/tx/:hash', function(req, res, next, send) {
self.walletdb.getTX(req.options.hash, function(err, tx) {
if (err)
return next(err);
@ -584,40 +664,6 @@ HTTPServer.prototype._init = function _init() {
});
});
// Broadcast TX
this.post('/broadcast', function(req, res, next, send) {
self.pool.sendTX(req.options.tx, function(err) {
if (err)
return next(err);
send(200, {
success: true
});
});
});
// Mempool snapshot
this.get('/mempool', function(req, res, next, send) {
self.node.mempool.getHistory(function(err, txs) {
if (err)
return next(err);
if (!txs.length)
return send(404);
utils.forEach(txs, function(tx, next) {
self.node.fillHistory(tx, next);
}, function(err) {
if (err)
return next(err);
send(200, txs.map(function(tx) {
return tx.toJSON();
}));
});
});
});
this.server.on('error', function(err) {
self.emit('error', err);
});

View File

@ -1397,7 +1397,8 @@ Wallet.prototype.toJSON = function toJSON() {
id: this.id,
initialized: this.initialized,
accountDepth: this.accountDepth,
master: this.master.toJSON()
master: this.master.toJSON(),
account: this.account ? this.account.toJSON() : null
};
};
@ -2154,6 +2155,12 @@ Account.prototype.toJSON = function toJSON() {
accountIndex: this.accountIndex,
receiveDepth: this.receiveDepth,
changeDepth: this.changeDepth,
receiveAddress: this.receiveAddress
? this.receiveAddress.getAddress()
: null,
changeAddress: this.changeAddress
? this.changeAddress.getAddress()
: null,
accountKey: this.accountKey.xpubkey,
keys: this.keys.map(function(key) {
return key.xpubkey;

View File

@ -928,6 +928,7 @@ WalletDB.prototype.zap = function zap(id, account, age, callback) {
* Parse arguments and return an id
* consisting of `walletid/accountname`.
* @private
* @param {WalletID} id
* @param {String|Number} account
* @param {Function} errback
* @param {Function} callback - Returns [String, Function].
@ -1088,6 +1089,18 @@ WalletDB.prototype.getInfo = function getInfo(id, callback) {
});
};
WalletDB.prototype.makeAccount = function makeAccount(id, account, options, callback) {
this.fetchWallet(id, callback, function(wallet, callback) {
wallet.hasAccount(account, function(err, exists) {
if (err)
return callback(err);
if (exists)
return wallet.getAccount(account, callback);
return wallet.createAccount(options, callback);
});
});
};
WalletDB.prototype.getRedeem = function getRedeem(id, hash, callback) {
this.fetchWallet(id, callback, function(wallet, callback) {
wallet.getRedeem(hash, callback);