add hd scanning to wallet.
This commit is contained in:
parent
239902b752
commit
2a5c35cf05
@ -268,6 +268,8 @@ HDPrivateKey.prototype.scan44 = function scan44(options, txByAddress, callback)
|
||||
if (total === 0) {
|
||||
if (chainConstant === 0)
|
||||
return chainCheck(1);
|
||||
if (isAccount)
|
||||
return callback(null, accounts[accountIndex]);
|
||||
return callback(null, accounts);
|
||||
}
|
||||
|
||||
@ -276,7 +278,7 @@ HDPrivateKey.prototype.scan44 = function scan44(options, txByAddress, callback)
|
||||
if (isAccount) {
|
||||
if (chainConstant === 0)
|
||||
return chainCheck(1);
|
||||
return callback(null, accounts[0]);
|
||||
return callback(null, accounts[accountIndex]);
|
||||
}
|
||||
|
||||
return scanner(accountIndex + 1);
|
||||
|
||||
@ -664,6 +664,175 @@ Wallet.prototype.syncOutputDepth = function syncOutputDepth(tx) {
|
||||
this.setReceiveDepth(depth.receive + 1);
|
||||
};
|
||||
|
||||
Wallet.prototype.scan = function scan(txByAddress, callback) {
|
||||
function done(err, depths) {
|
||||
if (err)
|
||||
return callback(err);
|
||||
|
||||
if (depths.changeDepth >= this.changeDepth)
|
||||
this.setChangeDepth(depths.changeDepth + 1);
|
||||
|
||||
if (depths.receiveDepth >= this.receiveDepth)
|
||||
this.setReceiveDepth(depths.receiveDepth + 1);
|
||||
}
|
||||
|
||||
if (this.derivation === 'bip44')
|
||||
return this._scan44({ current: true }, txByAddress, done);
|
||||
|
||||
if (this.derivation === 'bip45')
|
||||
return this._scan45({}, txByAddress, done);
|
||||
};
|
||||
|
||||
Wallet.prototype._scan44 = function scan44(options, txByAddress, callback) {
|
||||
var self = this;
|
||||
var accounts = [];
|
||||
var isAccount = this.master.isAccount44();
|
||||
var _accountKey = this.accountKey;
|
||||
|
||||
assert(this._initialized);
|
||||
|
||||
return (function chainCheck(change) {
|
||||
return (function scanner(accountIndex) {
|
||||
var addressIndex = 0;
|
||||
var total = 0;
|
||||
var gap = 0;
|
||||
|
||||
if (options.current)
|
||||
accountIndex = self.accountIndex;
|
||||
|
||||
// 1. derive the first account's node (index = 0)
|
||||
self.accountKey = isAccount
|
||||
? self.master
|
||||
: self.master.deriveAccount44(accountIndex);
|
||||
|
||||
if (isAccount)
|
||||
accountIndex = new bn(self.master.childIndex).toNumber() - constants.hd.hardened;
|
||||
|
||||
// 2. derive the external chain node of this account
|
||||
// 3. scan addresses of the external chain;
|
||||
// respect the gap limit described below
|
||||
return (function next() {
|
||||
var address = self.deriveAddress(change, addressIndex++);
|
||||
var addr = address.getAddress();
|
||||
|
||||
return txByAddress(addr, function(err, txs) {
|
||||
var result;
|
||||
|
||||
if (err) {
|
||||
self.accountKey = _accountKey;
|
||||
return callback(err);
|
||||
}
|
||||
|
||||
if (txs) {
|
||||
if (typeof txs === 'boolean')
|
||||
result = txs;
|
||||
else if (typeof txs === 'number')
|
||||
result = txs > 0;
|
||||
else if (Array.isArray(txs))
|
||||
result = txs.length > 0;
|
||||
else
|
||||
result = false;
|
||||
}
|
||||
|
||||
if (result) {
|
||||
total++;
|
||||
gap = 0;
|
||||
return next();
|
||||
}
|
||||
|
||||
if (++gap < 20)
|
||||
return next();
|
||||
|
||||
assert(accounts[accountIndex] == null || change === true);
|
||||
|
||||
if (change === false)
|
||||
accounts[accountIndex] = { receiveDepth: addressIndex };
|
||||
else
|
||||
accounts[accountIndex].changeDepth = addressIndex;
|
||||
|
||||
// 4. if no transactions are found on the
|
||||
// external chain, stop discovery
|
||||
if (total === 0) {
|
||||
if (change === false)
|
||||
return chainCheck(true);
|
||||
self.accountKey = _accountKey;
|
||||
if (isAccount || options.current)
|
||||
return callback(null, accounts[accountIndex]);
|
||||
return callback(null, accounts);
|
||||
}
|
||||
|
||||
// 5. if there are some transactions, increase
|
||||
// the account index and go to step 1
|
||||
if (isAccount || options.current) {
|
||||
if (change === false)
|
||||
return chainCheck(true);
|
||||
self.accountKey = _accountKey;
|
||||
return callback(null, accounts[accountIndex]);
|
||||
}
|
||||
|
||||
return scanner(accountIndex + 1);
|
||||
});
|
||||
})();
|
||||
})(0);
|
||||
})(false);
|
||||
};
|
||||
|
||||
Wallet.prototype._scan45 = function scan45(options, txByAddress, callback) {
|
||||
var depths = { changeDepth: 0, receiveDepth: 0 };
|
||||
|
||||
assert(this._initialized);
|
||||
|
||||
return (function chainCheck(change) {
|
||||
var addressIndex = 0;
|
||||
var total = 0;
|
||||
var gap = 0;
|
||||
|
||||
return (function next() {
|
||||
var address = self.deriveAddress(change, addressIndex++);
|
||||
var addr = address.getAddress();
|
||||
|
||||
return txByAddress(addr, function(err, txs) {
|
||||
var result;
|
||||
|
||||
if (err)
|
||||
return callback(err);
|
||||
|
||||
if (txs) {
|
||||
if (typeof txs === 'boolean')
|
||||
result = txs;
|
||||
else if (typeof txs === 'number')
|
||||
result = txs > 0;
|
||||
else if (Array.isArray(txs))
|
||||
result = txs.length > 0;
|
||||
else
|
||||
result = false;
|
||||
}
|
||||
|
||||
if (result) {
|
||||
total++;
|
||||
gap = 0;
|
||||
return next();
|
||||
}
|
||||
|
||||
if (++gap < 20)
|
||||
return next();
|
||||
|
||||
assert(depths.receiveDepth === 0 || change === true);
|
||||
|
||||
if (change === false)
|
||||
depths.receiveDepth = addressIndex;
|
||||
else
|
||||
depths.changeDepth = addressIndex;
|
||||
|
||||
if (change === false)
|
||||
return chainCheck(true);
|
||||
|
||||
return callback(null, depths);
|
||||
});
|
||||
})();
|
||||
})(false);
|
||||
};
|
||||
|
||||
Wallet.prototype.scriptInputs = function scriptInputs(tx, index) {
|
||||
this.fillPrevout(tx);
|
||||
var addresses = this.deriveInputs(tx);
|
||||
|
||||
Loading…
Reference in New Issue
Block a user