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 (total === 0) {
|
||||||
if (chainConstant === 0)
|
if (chainConstant === 0)
|
||||||
return chainCheck(1);
|
return chainCheck(1);
|
||||||
|
if (isAccount)
|
||||||
|
return callback(null, accounts[accountIndex]);
|
||||||
return callback(null, accounts);
|
return callback(null, accounts);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -276,7 +278,7 @@ HDPrivateKey.prototype.scan44 = function scan44(options, txByAddress, callback)
|
|||||||
if (isAccount) {
|
if (isAccount) {
|
||||||
if (chainConstant === 0)
|
if (chainConstant === 0)
|
||||||
return chainCheck(1);
|
return chainCheck(1);
|
||||||
return callback(null, accounts[0]);
|
return callback(null, accounts[accountIndex]);
|
||||||
}
|
}
|
||||||
|
|
||||||
return scanner(accountIndex + 1);
|
return scanner(accountIndex + 1);
|
||||||
|
|||||||
@ -664,6 +664,175 @@ Wallet.prototype.syncOutputDepth = function syncOutputDepth(tx) {
|
|||||||
this.setReceiveDepth(depth.receive + 1);
|
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) {
|
Wallet.prototype.scriptInputs = function scriptInputs(tx, index) {
|
||||||
this.fillPrevout(tx);
|
this.fillPrevout(tx);
|
||||||
var addresses = this.deriveInputs(tx);
|
var addresses = this.deriveInputs(tx);
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user