wallet map.
This commit is contained in:
parent
86027e9668
commit
5095f78dbf
@ -79,6 +79,12 @@ function Network(options) {
|
|||||||
|
|
||||||
Network.primary = null;
|
Network.primary = null;
|
||||||
|
|
||||||
|
Network.main = null;
|
||||||
|
Network.testnet = null;
|
||||||
|
Network.regtest = null;
|
||||||
|
Network.segnet3 = null;
|
||||||
|
Network.segnet4 = null;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Update the height of the network.
|
* Update the height of the network.
|
||||||
* @param {Number} height
|
* @param {Number} height
|
||||||
|
|||||||
@ -110,6 +110,131 @@ TXDB.prototype._testFilter = function _testFilter(addresses) {
|
|||||||
return false;
|
return false;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Each address can potentially map to multiple
|
||||||
|
// accounts and wallets due to the fact that
|
||||||
|
// multisig accounts can have shared addresses.
|
||||||
|
// An address could map to 2 accounts on different
|
||||||
|
// wallets, or 2 accounts on the same wallet!
|
||||||
|
// In summary, bitcoin is hard. Use Bobchain instead.
|
||||||
|
//
|
||||||
|
// Table:
|
||||||
|
// [address-hash] -> [array of Path objects]
|
||||||
|
// '1edc6b6858fd12c64b26d8bd1e0e50d44b5bafb9':
|
||||||
|
// [Path {
|
||||||
|
// id: 'WLTZ3f5mMBsgWr1TcLzAdtLD8pkLcmWuBfPt',
|
||||||
|
// name: 'default',
|
||||||
|
// account: 0,
|
||||||
|
// change: 0,
|
||||||
|
// index: 0
|
||||||
|
// }]
|
||||||
|
//
|
||||||
|
|
||||||
|
// What we need:
|
||||||
|
// Table: Above.
|
||||||
|
// All: uniqified paths by id/name
|
||||||
|
// Outputs: Technically uniqified by ID, but id/name works too.
|
||||||
|
|
||||||
|
// What they need (api):
|
||||||
|
// outputs: [ - SAME AS OUTPUTS ABOVE!!!
|
||||||
|
// // Sum of value:
|
||||||
|
// { value: 0, id: wallet-id, name: account, index: account }
|
||||||
|
// ]
|
||||||
|
|
||||||
|
function WalletMap(table) {
|
||||||
|
var i, j, keys, key, paths, path;
|
||||||
|
|
||||||
|
this.inputs = [];
|
||||||
|
this.outputs = [];
|
||||||
|
this.paths = [];
|
||||||
|
this.accounts = null;
|
||||||
|
this.wallets = [];
|
||||||
|
this.table = null;
|
||||||
|
|
||||||
|
keys = Object.keys(table);
|
||||||
|
|
||||||
|
// Flatten paths and push all of
|
||||||
|
// them onto the `paths` array.
|
||||||
|
for (i = 0; i < keys.length; i++) {
|
||||||
|
key = keys[i];
|
||||||
|
paths = table[key];
|
||||||
|
for (j = 0; j < paths.length; j++) {
|
||||||
|
path = paths[j];
|
||||||
|
this.wallets.push(path.id);
|
||||||
|
this.paths.push(path);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this.wallets = utils.uniq(this.wallets);
|
||||||
|
this.accounts = uniq(this.paths);
|
||||||
|
this.table = table;
|
||||||
|
}
|
||||||
|
|
||||||
|
WalletMap.fromTX = function fromTX(table, tx) {
|
||||||
|
var map = new WalletMap(table);
|
||||||
|
var i, input, output;
|
||||||
|
|
||||||
|
for (i = 0; i < tx.inputs.length; i++) {
|
||||||
|
input = tx.inputs[i];
|
||||||
|
map.inputs.push(MapMember.fromMember(table, input));
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < tx.outputs.length; i++) {
|
||||||
|
output = tx.outputs[i];
|
||||||
|
map.outputs.push(MapMember.fromMember(table, output));
|
||||||
|
}
|
||||||
|
|
||||||
|
return map;
|
||||||
|
};
|
||||||
|
|
||||||
|
WalletMap.prototype.hasPaths = function hasPaths(address) {
|
||||||
|
var paths;
|
||||||
|
|
||||||
|
if (!address)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
paths = this.table[address];
|
||||||
|
|
||||||
|
return paths && paths.length !== 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
WalletMap.prototype.getPaths = function getPaths(address) {
|
||||||
|
return this.table[address];
|
||||||
|
};
|
||||||
|
|
||||||
|
function MapMember() {
|
||||||
|
this.value = 0;
|
||||||
|
this.hash = null;
|
||||||
|
this.wallets = [];
|
||||||
|
this.paths = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
MapMember.fromMember = function fromMember(table, io) {
|
||||||
|
var hash = io.getHash('hex');
|
||||||
|
var member = new MapMember();
|
||||||
|
var i, paths;
|
||||||
|
|
||||||
|
member.value = io.coin
|
||||||
|
? io.coin.value
|
||||||
|
: io.value || 0;
|
||||||
|
|
||||||
|
if (!hash)
|
||||||
|
return member;
|
||||||
|
|
||||||
|
paths = table[hash];
|
||||||
|
|
||||||
|
assert(paths);
|
||||||
|
|
||||||
|
member.hash = hash;
|
||||||
|
member.paths = paths;
|
||||||
|
|
||||||
|
for (i = 0; i < paths.length; i++)
|
||||||
|
member.wallets.push(paths[i].id);
|
||||||
|
|
||||||
|
member.wallets = utils.uniq(member.wallets);
|
||||||
|
|
||||||
|
return member;
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Map a transactions' addresses to wallet IDs.
|
* Map a transactions' addresses to wallet IDs.
|
||||||
* @param {TX} tx
|
* @param {TX} tx
|
||||||
@ -119,9 +244,7 @@ TXDB.prototype._testFilter = function _testFilter(addresses) {
|
|||||||
TXDB.prototype.getMap = function getMap(tx, callback) {
|
TXDB.prototype.getMap = function getMap(tx, callback) {
|
||||||
var i, input, output, address, addresses, map;
|
var i, input, output, address, addresses, map;
|
||||||
|
|
||||||
input = tx.getInputHashes('hex');
|
addresses = tx.getHashes('hex');
|
||||||
output = tx.getOutputHashes('hex');
|
|
||||||
addresses = utils.uniq(input.concat(output));
|
|
||||||
|
|
||||||
if (!this._testFilter(addresses))
|
if (!this._testFilter(addresses))
|
||||||
return callback();
|
return callback();
|
||||||
@ -130,31 +253,12 @@ TXDB.prototype.getMap = function getMap(tx, callback) {
|
|||||||
if (err)
|
if (err)
|
||||||
return callback(err);
|
return callback(err);
|
||||||
|
|
||||||
if (table.count === 0)
|
if (!table)
|
||||||
return callback();
|
return callback();
|
||||||
|
|
||||||
map = {
|
map = WalletMap.fromTX(table, tx);
|
||||||
table: table,
|
|
||||||
input: [],
|
|
||||||
output: [],
|
|
||||||
all: []
|
|
||||||
};
|
|
||||||
|
|
||||||
for (i = 0; i < input.length; i++) {
|
utils.print(map);
|
||||||
address = input[i];
|
|
||||||
assert(map.table[address]);
|
|
||||||
map.input = map.input.concat(map.table[address]);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (i = 0; i < output.length; i++) {
|
|
||||||
address = output[i];
|
|
||||||
assert(map.table[address]);
|
|
||||||
map.output = map.output.concat(map.table[address]);
|
|
||||||
}
|
|
||||||
|
|
||||||
map.input = uniq(map.input);
|
|
||||||
map.output = uniq(map.output);
|
|
||||||
map.all = uniq(map.input.concat(map.output));
|
|
||||||
|
|
||||||
return callback(null, map);
|
return callback(null, map);
|
||||||
});
|
});
|
||||||
@ -168,7 +272,8 @@ TXDB.prototype.getMap = function getMap(tx, callback) {
|
|||||||
|
|
||||||
TXDB.prototype.mapAddresses = function mapAddresses(address, callback) {
|
TXDB.prototype.mapAddresses = function mapAddresses(address, callback) {
|
||||||
var self = this;
|
var self = this;
|
||||||
var table = { count: 0 };
|
var table = {};
|
||||||
|
var count = 0;
|
||||||
var i, keys, values;
|
var i, keys, values;
|
||||||
|
|
||||||
return utils.forEachSerial(address, function(address, next) {
|
return utils.forEachSerial(address, function(address, next) {
|
||||||
@ -190,7 +295,7 @@ TXDB.prototype.mapAddresses = function mapAddresses(address, callback) {
|
|||||||
|
|
||||||
assert(!table[address]);
|
assert(!table[address]);
|
||||||
table[address] = values;
|
table[address] = values;
|
||||||
table.count += values.length;
|
count += values.length;
|
||||||
|
|
||||||
return next();
|
return next();
|
||||||
});
|
});
|
||||||
@ -198,6 +303,9 @@ TXDB.prototype.mapAddresses = function mapAddresses(address, callback) {
|
|||||||
if (err)
|
if (err)
|
||||||
return callback(err);
|
return callback(err);
|
||||||
|
|
||||||
|
if (count === 0)
|
||||||
|
return callback();
|
||||||
|
|
||||||
return callback(null, table);
|
return callback(null, table);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
@ -338,8 +446,8 @@ TXDB.prototype._add = function add(tx, map, callback, force) {
|
|||||||
batch.put('m/' + pad32(tx.ts) + '/' + hash, DUMMY);
|
batch.put('m/' + pad32(tx.ts) + '/' + hash, DUMMY);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i < map.all.length; i++) {
|
for (i = 0; i < map.accounts.length; i++) {
|
||||||
path = map.all[i];
|
path = map.accounts[i];
|
||||||
id = path.id + '/' + path.account;
|
id = path.id + '/' + path.account;
|
||||||
batch.put('T/' + id + '/' + hash, DUMMY);
|
batch.put('T/' + id + '/' + hash, DUMMY);
|
||||||
if (tx.ts === 0) {
|
if (tx.ts === 0) {
|
||||||
@ -362,7 +470,7 @@ TXDB.prototype._add = function add(tx, map, callback, force) {
|
|||||||
address = input.getHash('hex');
|
address = input.getHash('hex');
|
||||||
|
|
||||||
// Only add orphans if this input is ours.
|
// Only add orphans if this input is ours.
|
||||||
if (!address || !map.table[address].length)
|
if (!map.hasPaths(address))
|
||||||
return next();
|
return next();
|
||||||
|
|
||||||
self.getCoin(prevout.hash, prevout.index, function(err, coin) {
|
self.getCoin(prevout.hash, prevout.index, function(err, coin) {
|
||||||
@ -385,7 +493,7 @@ TXDB.prototype._add = function add(tx, map, callback, force) {
|
|||||||
|
|
||||||
updated = true;
|
updated = true;
|
||||||
|
|
||||||
paths = map.table[address];
|
paths = map.getPaths(address);
|
||||||
|
|
||||||
for (j = 0; j < paths.length; j++) {
|
for (j = 0; j < paths.length; j++) {
|
||||||
path = paths[j];
|
path = paths[j];
|
||||||
@ -462,7 +570,7 @@ TXDB.prototype._add = function add(tx, map, callback, force) {
|
|||||||
var coin;
|
var coin;
|
||||||
|
|
||||||
// Do not add unspents for outputs that aren't ours.
|
// Do not add unspents for outputs that aren't ours.
|
||||||
if (!address || !map.table[address].length)
|
if (!map.hasPaths(address))
|
||||||
return next();
|
return next();
|
||||||
|
|
||||||
if (output.script.isUnspendable())
|
if (output.script.isUnspendable())
|
||||||
@ -521,7 +629,7 @@ TXDB.prototype._add = function add(tx, map, callback, force) {
|
|||||||
return next(err);
|
return next(err);
|
||||||
|
|
||||||
if (!orphans) {
|
if (!orphans) {
|
||||||
paths = map.table[address];
|
paths = map.getPaths(address);
|
||||||
|
|
||||||
for (j = 0; j < paths.length; j++) {
|
for (j = 0; j < paths.length; j++) {
|
||||||
path = paths[j];
|
path = paths[j];
|
||||||
@ -749,8 +857,8 @@ TXDB.prototype._confirm = function _confirm(tx, map, callback, force) {
|
|||||||
batch.del('m/' + pad32(existing.ps) + '/' + hash);
|
batch.del('m/' + pad32(existing.ps) + '/' + hash);
|
||||||
batch.put('m/' + pad32(tx.ts) + '/' + hash, DUMMY);
|
batch.put('m/' + pad32(tx.ts) + '/' + hash, DUMMY);
|
||||||
|
|
||||||
for (i = 0; i < map.all.length; i++) {
|
for (i = 0; i < map.accounts.length; i++) {
|
||||||
path = map.all[i];
|
path = map.accounts[i];
|
||||||
id = path.id + '/' + path.account;
|
id = path.id + '/' + path.account;
|
||||||
batch.del('P/' + id + '/' + hash);
|
batch.del('P/' + id + '/' + hash);
|
||||||
batch.put('H/' + id + '/' + pad32(tx.height) + '/' + hash, DUMMY);
|
batch.put('H/' + id + '/' + pad32(tx.height) + '/' + hash, DUMMY);
|
||||||
@ -762,7 +870,7 @@ TXDB.prototype._confirm = function _confirm(tx, map, callback, force) {
|
|||||||
var address = output.getHash('hex');
|
var address = output.getHash('hex');
|
||||||
|
|
||||||
// Only update coins if this output is ours.
|
// Only update coins if this output is ours.
|
||||||
if (!address || !map.table[address].length)
|
if (!map.hasPaths(address))
|
||||||
return next();
|
return next();
|
||||||
|
|
||||||
self.getCoin(hash, i, function(err, coin) {
|
self.getCoin(hash, i, function(err, coin) {
|
||||||
@ -888,8 +996,8 @@ TXDB.prototype._remove = function remove(tx, map, callback, force) {
|
|||||||
batch.del('m/' + pad32(tx.ts) + '/' + hash);
|
batch.del('m/' + pad32(tx.ts) + '/' + hash);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i < map.all.length; i++) {
|
for (i = 0; i < map.accounts.length; i++) {
|
||||||
path = map.all[i];
|
path = map.accounts[i];
|
||||||
id = path.id + '/' + path.account;
|
id = path.id + '/' + path.account;
|
||||||
batch.del('T/' + id + '/' + hash);
|
batch.del('T/' + id + '/' + hash);
|
||||||
if (tx.ts === 0) {
|
if (tx.ts === 0) {
|
||||||
@ -916,10 +1024,10 @@ TXDB.prototype._remove = function remove(tx, map, callback, force) {
|
|||||||
if (!input.coin)
|
if (!input.coin)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (!address || !map.table[address].length)
|
if (!map.hasPaths(address))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
paths = map.table[address];
|
paths = map.getPaths(address);
|
||||||
|
|
||||||
for (j = 0; j < paths.length; j++) {
|
for (j = 0; j < paths.length; j++) {
|
||||||
path = paths[j];
|
path = paths[j];
|
||||||
@ -937,13 +1045,13 @@ TXDB.prototype._remove = function remove(tx, map, callback, force) {
|
|||||||
key = hash + '/' + i;
|
key = hash + '/' + i;
|
||||||
address = output.getHash('hex');
|
address = output.getHash('hex');
|
||||||
|
|
||||||
if (!address || !map.table[address].length)
|
if (!map.hasPaths(address))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (output.script.isUnspendable())
|
if (output.script.isUnspendable())
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
paths = map.table[address];
|
paths = map.getPaths(address);
|
||||||
|
|
||||||
for (j = 0; j < paths.length; j++) {
|
for (j = 0; j < paths.length; j++) {
|
||||||
path = paths[j];
|
path = paths[j];
|
||||||
@ -1040,8 +1148,8 @@ TXDB.prototype._unconfirm = function unconfirm(tx, map, callback, force) {
|
|||||||
batch.del('m/' + pad32(ts) + '/' + hash);
|
batch.del('m/' + pad32(ts) + '/' + hash);
|
||||||
batch.put('m/' + pad32(tx.ps) + '/' + hash, DUMMY);
|
batch.put('m/' + pad32(tx.ps) + '/' + hash, DUMMY);
|
||||||
|
|
||||||
for (i = 0; i < map.all.length; i++) {
|
for (i = 0; i < map.accounts.length; i++) {
|
||||||
path = map.all[i];
|
path = map.accounts[i];
|
||||||
id = path.id + '/' + path.account;
|
id = path.id + '/' + path.account;
|
||||||
batch.put('P/' + id + '/' + hash, DUMMY);
|
batch.put('P/' + id + '/' + hash, DUMMY);
|
||||||
batch.del('H/' + id + '/' + pad32(height) + '/' + hash);
|
batch.del('H/' + id + '/' + pad32(height) + '/' + hash);
|
||||||
|
|||||||
@ -125,35 +125,35 @@ WalletDB.prototype._init = function _init() {
|
|||||||
|
|
||||||
this.tx.on('tx', function(tx, map) {
|
this.tx.on('tx', function(tx, map) {
|
||||||
self.emit('tx', tx, map);
|
self.emit('tx', tx, map);
|
||||||
map.all.forEach(function(path) {
|
map.accounts.forEach(function(path) {
|
||||||
self.fire(path.id, 'tx', tx, path.name);
|
self.fire(path.id, 'tx', tx, path.name);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
this.tx.on('conflict', function(tx, map) {
|
this.tx.on('conflict', function(tx, map) {
|
||||||
self.emit('conflict', tx, map);
|
self.emit('conflict', tx, map);
|
||||||
map.all.forEach(function(path) {
|
map.accounts.forEach(function(path) {
|
||||||
self.fire(path.id, 'conflict', tx, path.name);
|
self.fire(path.id, 'conflict', tx, path.name);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
this.tx.on('confirmed', function(tx, map) {
|
this.tx.on('confirmed', function(tx, map) {
|
||||||
self.emit('confirmed', tx, map);
|
self.emit('confirmed', tx, map);
|
||||||
map.all.forEach(function(path) {
|
map.accounts.forEach(function(path) {
|
||||||
self.fire(path.id, 'confirmed', tx, path.name);
|
self.fire(path.id, 'confirmed', tx, path.name);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
this.tx.on('unconfirmed', function(tx, map) {
|
this.tx.on('unconfirmed', function(tx, map) {
|
||||||
self.emit('unconfirmed', tx, map);
|
self.emit('unconfirmed', tx, map);
|
||||||
map.all.forEach(function(path) {
|
map.accounts.forEach(function(path) {
|
||||||
self.fire(path.id, 'unconfirmed', tx, path.name);
|
self.fire(path.id, 'unconfirmed', tx, path.name);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
this.tx.on('updated', function(tx, map) {
|
this.tx.on('updated', function(tx, map) {
|
||||||
self.emit('updated', tx, map);
|
self.emit('updated', tx, map);
|
||||||
map.all.forEach(function(path) {
|
map.accounts.forEach(function(path) {
|
||||||
self.fire(path.id, 'updated', tx, path.name);
|
self.fire(path.id, 'updated', tx, path.name);
|
||||||
});
|
});
|
||||||
self.updateBalances(tx, map, function(err, balances) {
|
self.updateBalances(tx, map, function(err, balances) {
|
||||||
@ -186,21 +186,28 @@ WalletDB.prototype.updateBalances = function updateBalances(tx, map, callback) {
|
|||||||
var self = this;
|
var self = this;
|
||||||
var balances = {};
|
var balances = {};
|
||||||
|
|
||||||
utils.forEachSerial(map.output, function(path, next) {
|
utils.forEachSerial(map.outputs, function(output, next) {
|
||||||
if (self.listeners('balance').length === 0
|
utils.forEachSerial(output.wallets, function(id, next) {
|
||||||
&& !self.hasListener(path.id, 'balance')) {
|
if (self.listeners('balance').length === 0
|
||||||
return next();
|
&& !self.hasListener(id, 'balance')) {
|
||||||
}
|
return next();
|
||||||
|
}
|
||||||
|
|
||||||
if (balances[path.id] != null)
|
if (balances[id] != null)
|
||||||
return next();
|
return next();
|
||||||
|
|
||||||
self.getBalance(path.id, function(err, balance) {
|
self.getBalance(id, function(err, balance) {
|
||||||
|
if (err)
|
||||||
|
return next(err);
|
||||||
|
|
||||||
|
balances[id] = balance;
|
||||||
|
|
||||||
|
next();
|
||||||
|
});
|
||||||
|
}, function(err) {
|
||||||
if (err)
|
if (err)
|
||||||
return next(err);
|
return next(err);
|
||||||
|
|
||||||
balances[path.id] = balance;
|
|
||||||
|
|
||||||
next();
|
next();
|
||||||
});
|
});
|
||||||
}, function(err) {
|
}, function(err) {
|
||||||
@ -213,12 +220,19 @@ WalletDB.prototype.updateBalances = function updateBalances(tx, map, callback) {
|
|||||||
|
|
||||||
WalletDB.prototype.syncOutputs = function syncOutputs(tx, map, callback) {
|
WalletDB.prototype.syncOutputs = function syncOutputs(tx, map, callback) {
|
||||||
var self = this;
|
var self = this;
|
||||||
utils.forEachSerial(map.output, function(path, next) {
|
utils.forEachSerial(map.outputs, function(output, next) {
|
||||||
self.syncOutputDepth(path.id, tx, function(err, receive, change) {
|
utils.forEachSerial(output.wallets, function(id, next) {
|
||||||
|
self.syncOutputDepth(id, tx, function(err, receive, change) {
|
||||||
|
if (err)
|
||||||
|
return next(err);
|
||||||
|
self.fire(id, 'address', receive, change);
|
||||||
|
self.emit('address', receive, change, map);
|
||||||
|
next();
|
||||||
|
});
|
||||||
|
}, function(err) {
|
||||||
if (err)
|
if (err)
|
||||||
return next(err);
|
return next(err);
|
||||||
self.fire(path.id, 'address', receive, change, path.name);
|
|
||||||
self.emit('address', receive, change, map);
|
|
||||||
next();
|
next();
|
||||||
});
|
});
|
||||||
}, callback);
|
}, callback);
|
||||||
@ -702,7 +716,7 @@ WalletDB.prototype.saveAddress = function saveAddress(id, addresses, callback) {
|
|||||||
if (paths[id])
|
if (paths[id])
|
||||||
return next();
|
return next();
|
||||||
|
|
||||||
paths[id] = hash[1];
|
paths[id] = Path.fromKeyRing(id, hash[1]);
|
||||||
|
|
||||||
batch.put('W/' + hash[0], serializePaths(paths));
|
batch.put('W/' + hash[0], serializePaths(paths));
|
||||||
|
|
||||||
@ -1143,6 +1157,75 @@ WalletDB.prototype.getRedeem = function getRedeem(id, hash, callback) {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Path
|
||||||
|
* @constructor
|
||||||
|
*/
|
||||||
|
|
||||||
|
function Path() {
|
||||||
|
this.id = null;
|
||||||
|
this.name = null;
|
||||||
|
this.account = 0;
|
||||||
|
this.change = 0;
|
||||||
|
this.index = 0;
|
||||||
|
this.hash = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
Path.prototype.fromRaw = function fromRaw(data) {
|
||||||
|
var p = new BufferReader(data);
|
||||||
|
this.id = p.readVarString('utf8');
|
||||||
|
this.name = p.readVarString('utf8');
|
||||||
|
this.account = p.readU32();
|
||||||
|
this.change = p.readU32();
|
||||||
|
this.index = p.readU32();
|
||||||
|
return this;
|
||||||
|
};
|
||||||
|
|
||||||
|
Path.fromRaw = function fromRaw(data) {
|
||||||
|
return new Path().fromRaw(data);
|
||||||
|
};
|
||||||
|
|
||||||
|
Path.prototype.fromKeyRing = function fromKeyRing(id, address) {
|
||||||
|
this.id = id;
|
||||||
|
this.name = address.name;
|
||||||
|
this.account = address.account;
|
||||||
|
this.change = address.change;
|
||||||
|
this.index = address.index;
|
||||||
|
return this;
|
||||||
|
};
|
||||||
|
|
||||||
|
Path.fromKeyRing = function fromKeyRing(id, address) {
|
||||||
|
return new Path().fromKeyRing(id, address);
|
||||||
|
};
|
||||||
|
|
||||||
|
Path.prototype.toPath = function() {
|
||||||
|
return 'm/' + this.account
|
||||||
|
+ '\'/' + this.change
|
||||||
|
+ '/' + this.index;
|
||||||
|
};
|
||||||
|
|
||||||
|
Path.prototype.inspect = function() {
|
||||||
|
return '<Path: ' + this.id
|
||||||
|
+ '/' + this.name
|
||||||
|
+ ': ' + this.toPath()
|
||||||
|
+ '>';
|
||||||
|
};
|
||||||
|
|
||||||
|
Path.prototype.toRaw = function toRaw(writer) {
|
||||||
|
var p = new BufferWriter(writer);
|
||||||
|
|
||||||
|
p.writeVarString(this.id, 'utf8');
|
||||||
|
p.writeVarString(this.name, 'utf8');
|
||||||
|
p.writeU32(this.account);
|
||||||
|
p.writeU32(this.change);
|
||||||
|
p.writeU32(this.index);
|
||||||
|
|
||||||
|
if (!writer)
|
||||||
|
p = p.render();
|
||||||
|
|
||||||
|
return p;
|
||||||
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Helpers
|
* Helpers
|
||||||
*/
|
*/
|
||||||
@ -1150,17 +1233,11 @@ WalletDB.prototype.getRedeem = function getRedeem(id, hash, callback) {
|
|||||||
function parsePaths(data) {
|
function parsePaths(data) {
|
||||||
var p = new BufferReader(data);
|
var p = new BufferReader(data);
|
||||||
var out = {};
|
var out = {};
|
||||||
var id;
|
var path;
|
||||||
|
|
||||||
while (p.left()) {
|
while (p.left()) {
|
||||||
id = p.readVarString('utf8');
|
path = Path.fromRaw(p);
|
||||||
out[id] = {
|
out[path.id] = path;
|
||||||
id: id,
|
|
||||||
name: p.readVarString('utf8'),
|
|
||||||
account: p.readU32(),
|
|
||||||
change: p.readU32(),
|
|
||||||
index: p.readU32()
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return out;
|
return out;
|
||||||
@ -1174,11 +1251,7 @@ function serializePaths(out) {
|
|||||||
for (i = 0; i < keys.length; i++) {
|
for (i = 0; i < keys.length; i++) {
|
||||||
id = keys[i];
|
id = keys[i];
|
||||||
path = out[id];
|
path = out[id];
|
||||||
p.writeVarString(id, 'utf8');
|
path.toRaw(p);
|
||||||
p.writeVarString(path.name, 'utf8');
|
|
||||||
p.writeU32(path.account);
|
|
||||||
p.writeU32(path.change);
|
|
||||||
p.writeU32(path.index);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return p.render();
|
return p.render();
|
||||||
|
|||||||
@ -433,8 +433,10 @@ describe('Wallet', function() {
|
|||||||
var t3 = bcoin.mtx().addOutput(w2, 15000);
|
var t3 = bcoin.mtx().addOutput(w2, 15000);
|
||||||
w1.fill(t3, { rate: 10000 }, function(err) {
|
w1.fill(t3, { rate: 10000 }, function(err) {
|
||||||
assert(err);
|
assert(err);
|
||||||
assert(balance.total === 5460);
|
setTimeout(function() {
|
||||||
cb();
|
assert(balance.total === 5460);
|
||||||
|
cb();
|
||||||
|
}, 100);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user