wallet: drop wallet map in favor of path info and tx details.
This commit is contained in:
parent
914bc8435d
commit
abd267b7d2
@ -2909,37 +2909,36 @@ RPC.prototype._toWalletTX = function _toWalletTX(tx, callback) {
|
||||
var self = this;
|
||||
var receive, member, json;
|
||||
|
||||
this.walletdb.tx.getMap(tx, function(err, map) {
|
||||
this.walletdb.tx.toDetails(this.wallet.id, tx, function(err, details) {
|
||||
if (err)
|
||||
return callback(err);
|
||||
|
||||
if (!map)
|
||||
if (!details)
|
||||
return callback(new RPCError('TX not found.'));
|
||||
|
||||
receive = map.inputs.length === 0;
|
||||
member = receive ? map.outputs[0] : map.inputs[0];
|
||||
assert(member);
|
||||
receive = details.isReceive();
|
||||
member = details.getMember();
|
||||
|
||||
json = {
|
||||
amount: +utils.btc(tx.getOutputValue()),
|
||||
confirmations: tx.getConfirmations(self.chain.height),
|
||||
blockhash: tx.block ? utils.revHex(tx.block) : null,
|
||||
blockindex: tx.index,
|
||||
blocktime: tx.ts,
|
||||
txid: tx.rhash,
|
||||
amount: +utils.btc(details.getValue()),
|
||||
confirmations: details.confirmations,
|
||||
blockhash: details.block ? utils.revHex(details.block) : null,
|
||||
blockindex: details.index,
|
||||
blocktime: details.ts,
|
||||
txid: utils.revHex(details.hash),
|
||||
walletconflicts: [],
|
||||
time: tx.ps,
|
||||
timereceived: tx.ps,
|
||||
time: details.ps,
|
||||
timereceived: details.ps,
|
||||
'bip125-replaceable': 'no',
|
||||
details: [{
|
||||
account: member.name,
|
||||
address: member.paths[0].address.toBase58(self.network),
|
||||
account: member.path.name,
|
||||
address: member.address.toBase58(self.network),
|
||||
category: receive ? 'receive' : 'send',
|
||||
amount: +utils.btc(member.value),
|
||||
label: member.name,
|
||||
label: member.path.name,
|
||||
vout: 0
|
||||
}],
|
||||
hex: tx.toRaw().toString('hex')
|
||||
hex: details.tx.toRaw().toString('hex')
|
||||
};
|
||||
|
||||
callback(null, json);
|
||||
@ -3199,32 +3198,31 @@ RPC.prototype._toListTX = function _toListTX(tx, callback) {
|
||||
var self = this;
|
||||
var receive, member, json;
|
||||
|
||||
this.walletdb.tx.getMap(tx, function(err, map) {
|
||||
this.walletdb.tx.toDetails(this.wallet.id, tx, function(err, details) {
|
||||
if (err)
|
||||
return callback(err);
|
||||
|
||||
if (!map)
|
||||
if (!details)
|
||||
return callback(new RPCError('TX not found.'));
|
||||
|
||||
receive = map.inputs.length === 0;
|
||||
member = receive ? map.outputs[0] : map.inputs[0];
|
||||
assert(member);
|
||||
receive = details.isReceive();
|
||||
member = details.getMember();
|
||||
|
||||
json = {
|
||||
account: member.name,
|
||||
address: member.paths[0].address.toBase58(self.network),
|
||||
account: member.path.name,
|
||||
address: member.address.toBase58(self.network),
|
||||
category: receive ? 'receive' : 'send',
|
||||
amount: +utils.btc(member.value),
|
||||
label: member.name,
|
||||
label: member.path.name,
|
||||
vout: 0,
|
||||
confirmations: tx.getConfirmations(self.chain.height),
|
||||
blockhash: tx.block ? utils.revHex(tx.block) : null,
|
||||
blockindex: tx.index,
|
||||
blocktime: tx.ts,
|
||||
txid: tx.rhash,
|
||||
confirmations: details.confirmations,
|
||||
blockhash: details.block ? utils.revHex(details.block) : null,
|
||||
blockindex: details.index,
|
||||
blocktime: details.ts,
|
||||
txid: utils.revHex(details.hash),
|
||||
walletconflicts: [],
|
||||
time: tx.ps,
|
||||
timereceived: tx.ps,
|
||||
time: details.ps,
|
||||
timereceived: details.ps,
|
||||
'bip125-replaceable': 'no'
|
||||
};
|
||||
|
||||
|
||||
@ -968,49 +968,36 @@ HTTPServer.prototype._initIO = function _initIO() {
|
||||
});
|
||||
});
|
||||
|
||||
this.walletdb.on('tx', function(tx, map) {
|
||||
var summary = map.toJSON();
|
||||
tx = tx.toJSON();
|
||||
map.getWallets().forEach(function(id) {
|
||||
self.server.io.to(id).emit('wallet tx', tx, summary);
|
||||
});
|
||||
self.server.io.to('!all').emit('wallet tx', tx, summary);
|
||||
this.walletdb.on('tx', function(id, tx, details) {
|
||||
details = details.toJSON();
|
||||
self.server.io.to(id).emit('wallet tx', details);
|
||||
self.server.io.to('!all').emit('wallet tx', id, details);
|
||||
});
|
||||
|
||||
this.walletdb.on('confirmed', function(tx, map) {
|
||||
var summary = map.toJSON();
|
||||
tx = tx.toJSON();
|
||||
map.getWallets().forEach(function(id) {
|
||||
self.server.io.to(id).emit('wallet confirmed', tx, summary);
|
||||
});
|
||||
self.server.io.to('!all').emit('wallet confirmed', tx, summary);
|
||||
this.walletdb.on('confirmed', function(id, tx, details) {
|
||||
details = details.toJSON();
|
||||
self.server.io.to(id).emit('wallet confirmed', details);
|
||||
self.server.io.to('!all').emit('wallet confirmed', id, details);
|
||||
});
|
||||
|
||||
this.walletdb.on('updated', function(tx, map) {
|
||||
var summary = map.toJSON();
|
||||
tx = tx.toJSON();
|
||||
map.getWallets().forEach(function(id) {
|
||||
self.server.io.to(id).emit('wallet updated', tx, summary);
|
||||
});
|
||||
self.server.io.to('!all').emit('wallet updated', tx, summary);
|
||||
this.walletdb.on('updated', function(id, tx, details) {
|
||||
details = details.toJSON();
|
||||
self.server.io.to(id).emit('wallet updated', details);
|
||||
self.server.io.to('!all').emit('wallet updated', id, details);
|
||||
});
|
||||
|
||||
this.walletdb.on('balances', function(balances) {
|
||||
var json = {};
|
||||
Object.keys(balances).forEach(function(id) {
|
||||
json[id] = {
|
||||
confirmed: utils.btc(balances[id].confirmed),
|
||||
unconfirmed: utils.btc(balances[id].unconfirmed),
|
||||
total: utils.btc(balances[id].total)
|
||||
};
|
||||
self.server.io.to(id).emit('wallet balance', json[id], id);
|
||||
self.server.io.to('!all').emit('wallet balance', json[id], id);
|
||||
});
|
||||
self.server.io.to('!all').emit('wallet balances', json);
|
||||
this.walletdb.on('balance', function(id, balance, details) {
|
||||
balance = {
|
||||
confirmed: utils.btc(balance.confirmed),
|
||||
unconfirmed: utils.btc(balance.unconfirmed),
|
||||
total: utils.btc(balance.total)
|
||||
};
|
||||
self.server.io.to(id).emit('wallet balance', balance);
|
||||
self.server.io.to('!all').emit('wallet balance', id, balance);
|
||||
});
|
||||
|
||||
this.walletdb.on('address', function(receive, change, map) {
|
||||
var summary = map.toJSON();
|
||||
this.walletdb.on('address', function(id, receive, change, details) {
|
||||
details = details.toJSON();
|
||||
|
||||
receive = receive.map(function(address) {
|
||||
return address.toJSON();
|
||||
@ -1020,11 +1007,8 @@ HTTPServer.prototype._initIO = function _initIO() {
|
||||
return address.toJSON();
|
||||
});
|
||||
|
||||
map.getWallets().forEach(function(id) {
|
||||
self.server.io.to(id).emit('wallet address', receive, change, summary);
|
||||
});
|
||||
|
||||
self.server.io.to('!all').emit('wallet address', receive, change, summary);
|
||||
self.server.io.to(id).emit('wallet address', receive, change, details);
|
||||
self.server.io.to('!all').emit('wallet address', id, receive, change, details);
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -1030,18 +1030,19 @@ Wallet.prototype.getOutputPaths = function getOutputPaths(tx, callback) {
|
||||
* Sync address depths based on a transaction's outputs.
|
||||
* This is used for deriving new addresses when
|
||||
* a confirmed transaction is seen.
|
||||
* @param {WalletMap} map
|
||||
* @param {WalletMap} info
|
||||
* @param {Function} callback - Returns [Errr, Boolean]
|
||||
* (true if new addresses were allocated).
|
||||
*/
|
||||
|
||||
Wallet.prototype.syncOutputDepth = function syncOutputDepth(map, callback) {
|
||||
Wallet.prototype.syncOutputDepth = function syncOutputDepth(info, callback) {
|
||||
var self = this;
|
||||
var change = [];
|
||||
var receive = [];
|
||||
var accounts = {};
|
||||
var i, path, unlock;
|
||||
|
||||
unlock = this.writeLock.lock(syncOutputDepth, [map, callback]);
|
||||
unlock = this.writeLock.lock(syncOutputDepth, [info, callback]);
|
||||
|
||||
if (!unlock)
|
||||
return;
|
||||
@ -1050,8 +1051,22 @@ Wallet.prototype.syncOutputDepth = function syncOutputDepth(map, callback) {
|
||||
|
||||
this.start();
|
||||
|
||||
utils.forEachSerial(map.outputs, function(output, next) {
|
||||
var paths = output.paths;
|
||||
for (i = 0; i < info.paths.length; i++) {
|
||||
path = info.paths[i];
|
||||
|
||||
if (path.id !== this.id)
|
||||
continue;
|
||||
|
||||
if (!accounts[path.account])
|
||||
accounts[path.account] = [];
|
||||
|
||||
accounts[path.account].push(path);
|
||||
}
|
||||
|
||||
accounts = utils.values(accounts);
|
||||
|
||||
utils.forEachSerial(accounts, function(paths, next) {
|
||||
var account = paths[0].account;
|
||||
var receiveDepth = -1;
|
||||
var changeDepth = -1;
|
||||
|
||||
@ -1070,7 +1085,7 @@ Wallet.prototype.syncOutputDepth = function syncOutputDepth(map, callback) {
|
||||
receiveDepth += 2;
|
||||
changeDepth += 2;
|
||||
|
||||
self.getAccount(output.account, function(err, account) {
|
||||
self.getAccount(account, function(err, account) {
|
||||
if (err)
|
||||
return next(err);
|
||||
|
||||
|
||||
@ -101,35 +101,35 @@ WalletDB.prototype._init = function _init() {
|
||||
});
|
||||
}
|
||||
|
||||
function handleEvent(event, tx, map) {
|
||||
var i, path;
|
||||
function handleEvent(event, tx, info) {
|
||||
var i, id, details;
|
||||
|
||||
self.emit(event, tx, map);
|
||||
|
||||
for (i = 0; i < map.accounts.length; i++) {
|
||||
path = map.accounts[i];
|
||||
self.fire(path.id, event, tx, path.name);
|
||||
for (i = 0; i < info.wallets.length; i++) {
|
||||
id = info.wallets[i];
|
||||
details = info.toDetails(id);
|
||||
self.emit(event, id, tx, details);
|
||||
self.fire(id, event, tx, details);
|
||||
}
|
||||
}
|
||||
|
||||
this.tx.on('tx', function(tx, map) {
|
||||
handleEvent('tx', tx, map);
|
||||
this.tx.on('tx', function(tx, info) {
|
||||
handleEvent('tx', tx, info);
|
||||
});
|
||||
|
||||
this.tx.on('conflict', function(tx, map) {
|
||||
handleEvent('conflict', tx, map);
|
||||
this.tx.on('conflict', function(tx, info) {
|
||||
handleEvent('conflict', tx, info);
|
||||
});
|
||||
|
||||
this.tx.on('confirmed', function(tx, map) {
|
||||
handleEvent('confirmed', tx, map);
|
||||
this.tx.on('confirmed', function(tx, info) {
|
||||
handleEvent('confirmed', tx, info);
|
||||
});
|
||||
|
||||
this.tx.on('unconfirmed', function(tx, map) {
|
||||
handleEvent('unconfirmed', tx, map);
|
||||
this.tx.on('unconfirmed', function(tx, info) {
|
||||
handleEvent('unconfirmed', tx, info);
|
||||
});
|
||||
|
||||
this.tx.on('updated', function(tx, map) {
|
||||
handleEvent('updated', tx, map);
|
||||
this.tx.on('updated', function(tx, info) {
|
||||
handleEvent('updated', tx, info);
|
||||
});
|
||||
};
|
||||
|
||||
@ -248,16 +248,15 @@ WalletDB.prototype.commit = function commit(id, callback) {
|
||||
* Emit balance events after a tx is saved.
|
||||
* @private
|
||||
* @param {TX} tx
|
||||
* @param {WalletMap} map
|
||||
* @param {WalletMap} info
|
||||
* @param {Function} callback
|
||||
*/
|
||||
|
||||
WalletDB.prototype.updateBalances = function updateBalances(tx, map, callback) {
|
||||
WalletDB.prototype.updateBalances = function updateBalances(tx, info, callback) {
|
||||
var self = this;
|
||||
var balances = {};
|
||||
var i, id, keys;
|
||||
var details;
|
||||
|
||||
utils.forEachSerial(map.getOutputWallets(), function(id, next) {
|
||||
utils.forEachSerial(info.wallets, function(id, next) {
|
||||
if (self.listeners('balances').length === 0
|
||||
&& !self.hasListener(id, 'balance')) {
|
||||
return next();
|
||||
@ -267,44 +266,34 @@ WalletDB.prototype.updateBalances = function updateBalances(tx, map, callback) {
|
||||
if (err)
|
||||
return next(err);
|
||||
|
||||
balances[id] = balance;
|
||||
details = info.toDetails(id);
|
||||
self.emit('balance', id, balance, details);
|
||||
self.fire(id, 'balance', balance, details);
|
||||
|
||||
next();
|
||||
});
|
||||
}, function(err) {
|
||||
if (err)
|
||||
return callback(err);
|
||||
|
||||
keys = Object.keys(balances);
|
||||
|
||||
for (i = 0; i < keys.length; i++) {
|
||||
id = keys[i];
|
||||
self.fire(id, 'balance', balances[id]);
|
||||
}
|
||||
|
||||
self.emit('balances', balances, map);
|
||||
|
||||
return callback(null, balances);
|
||||
});
|
||||
}, callback);
|
||||
};
|
||||
|
||||
/**
|
||||
* Derive new addresses after a tx is saved.
|
||||
* @private
|
||||
* @param {TX} tx
|
||||
* @param {WalletMap} map
|
||||
* @param {WalletMap} info
|
||||
* @param {Function} callback
|
||||
*/
|
||||
|
||||
WalletDB.prototype.syncOutputs = function syncOutputs(tx, map, callback) {
|
||||
WalletDB.prototype.syncOutputs = function syncOutputs(tx, info, callback) {
|
||||
var self = this;
|
||||
var details;
|
||||
|
||||
utils.forEachSerial(map.getOutputWallets(), function(id, next) {
|
||||
self.syncOutputDepth(id, map, function(err, receive, change) {
|
||||
utils.forEachSerial(info.wallets, function(id, next) {
|
||||
self.syncOutputDepth(id, info, function(err, receive, change) {
|
||||
if (err)
|
||||
return next(err);
|
||||
self.fire(id, 'address', receive, change);
|
||||
self.emit('address', receive, change, map);
|
||||
details = info.toDetails(id);
|
||||
self.emit('address', id, receive, change, details);
|
||||
self.fire(id, 'address', receive, change, details);
|
||||
next();
|
||||
});
|
||||
}, callback);
|
||||
@ -314,17 +303,17 @@ WalletDB.prototype.syncOutputs = function syncOutputs(tx, map, callback) {
|
||||
* Derive new addresses and emit balance.
|
||||
* @private
|
||||
* @param {TX} tx
|
||||
* @param {WalletMap} map
|
||||
* @param {WalletMap} info
|
||||
* @param {Function} callback
|
||||
*/
|
||||
|
||||
WalletDB.prototype.handleTX = function handleTX(tx, map, callback) {
|
||||
WalletDB.prototype.handleTX = function handleTX(tx, info, callback) {
|
||||
var self = this;
|
||||
this.syncOutputs(tx, map, function(err) {
|
||||
this.syncOutputs(tx, info, function(err) {
|
||||
if (err)
|
||||
return callback(err);
|
||||
|
||||
self.updateBalances(tx, map, callback);
|
||||
self.updateBalances(tx, info, callback);
|
||||
});
|
||||
};
|
||||
|
||||
@ -1366,9 +1355,9 @@ WalletDB.prototype.fetchWallet = function fetchWallet(id, callback, handler) {
|
||||
});
|
||||
};
|
||||
|
||||
WalletDB.prototype.syncOutputDepth = function syncOutputDepth(id, map, callback) {
|
||||
WalletDB.prototype.syncOutputDepth = function syncOutputDepth(id, info, callback) {
|
||||
this.fetchWallet(id, callback, function(wallet, callback) {
|
||||
wallet.syncOutputDepth(map, callback);
|
||||
wallet.syncOutputDepth(info, callback);
|
||||
});
|
||||
};
|
||||
|
||||
@ -1591,6 +1580,7 @@ Path.prototype.toJSON = function toJSON() {
|
||||
return {
|
||||
id: this.id,
|
||||
name: this.name,
|
||||
change: this.change === 1,
|
||||
path: this.toPath()
|
||||
};
|
||||
};
|
||||
@ -1636,48 +1626,6 @@ Path.prototype.toKey = function toKey() {
|
||||
return this.id + '/' + this.account;
|
||||
};
|
||||
|
||||
/**
|
||||
* Convert path to a compact json object.
|
||||
* @returns {Object}
|
||||
*/
|
||||
|
||||
Path.prototype.toCompact = function toCompact() {
|
||||
return {
|
||||
path: 'm/' + this.change + '/' + this.index,
|
||||
address: this.address ? this.address.toBase58() : null
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* Inject properties from compact json object.
|
||||
* @private
|
||||
* @param {Object} json
|
||||
*/
|
||||
|
||||
Path.prototype.fromCompact = function fromCompact(json) {
|
||||
var indexes = bcoin.hd.parsePath(json.path, constants.hd.MAX_INDEX);
|
||||
|
||||
assert(indexes.length === 2);
|
||||
|
||||
this.change = indexes[0];
|
||||
this.index = indexes[1];
|
||||
this.address = json.address
|
||||
? bcoin.address.fromBase58(json.address)
|
||||
: null;
|
||||
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* Instantiate path from compact json object.
|
||||
* @param {Object} json
|
||||
* @returns {Path}
|
||||
*/
|
||||
|
||||
Path.fromCompact = function fromCompact(json) {
|
||||
return new Path().fromCompact(json);
|
||||
};
|
||||
|
||||
/**
|
||||
* Inspect the path.
|
||||
* @returns {String}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user