simplified and cached address derivation
This commit is contained in:
parent
8032bae431
commit
a8f0401e8e
6 changed files with 297 additions and 381 deletions
|
|
@ -13,13 +13,12 @@ angular.module('copayApp.controllers').controller('ReceiveController',
|
|||
var w = $rootScope.wallet;
|
||||
$scope.loading = true;
|
||||
$scope.isNewAddr = false;
|
||||
w.generateAddress(null, function() {
|
||||
$timeout(function() {
|
||||
controllerUtils.updateAddressList();
|
||||
$scope.loading = false;
|
||||
$scope.isNewAddr = true;
|
||||
}, 1);
|
||||
});
|
||||
w.generateAddress(null);
|
||||
$timeout(function() {
|
||||
controllerUtils.updateAddressList();
|
||||
$scope.loading = false;
|
||||
$scope.isNewAddr = true;
|
||||
}, 1);
|
||||
};
|
||||
|
||||
$scope.openAddressModal = function(address) {
|
||||
|
|
|
|||
|
|
@ -42,10 +42,21 @@ function PublicKeyRing(opts) {
|
|||
this.publicKeysCache = {};
|
||||
this.nicknameFor = opts.nicknameFor || {};
|
||||
this.copayerIds = [];
|
||||
this.addressToPath = {};
|
||||
|
||||
this.resetCache();
|
||||
};
|
||||
|
||||
PublicKeyRing.prototype.resetCache = function() {
|
||||
this.cache = {};
|
||||
this.cache.addressToPath = {};
|
||||
this.cache.receiveAddresses = [];
|
||||
this.cache.changeAddresses = [];
|
||||
|
||||
// Non persistent cache
|
||||
this._isChange = {};
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @desc Returns an object with only the keys needed to rebuild a PublicKeyRing
|
||||
*
|
||||
|
|
@ -99,9 +110,9 @@ PublicKeyRing.fromObj = function(opts) {
|
|||
pkr.addCopayer(opts.copayersExtPubKeys[k]);
|
||||
}
|
||||
|
||||
if (opts._cache){
|
||||
if (opts.cache) {
|
||||
log.debug('PublicKeyRing: Using address cache');
|
||||
pkr._cacheAddressMap = opts._cache;
|
||||
pkr.cache = opts.cache;
|
||||
}
|
||||
|
||||
return pkr;
|
||||
|
|
@ -129,7 +140,7 @@ PublicKeyRing.prototype.toObj = function() {
|
|||
return b.extendedPublicKeyString();
|
||||
}),
|
||||
nicknameFor: this.nicknameFor,
|
||||
_cache: this._cacheAddressMap
|
||||
cache: this.cache,
|
||||
};
|
||||
};
|
||||
|
||||
|
|
@ -300,20 +311,12 @@ PublicKeyRing.prototype.addCopayer = function(newHexaExtendedPublicKey, nickname
|
|||
PublicKeyRing.prototype.getPubKeys = function(index, isChange, copayerIndex) {
|
||||
this._checkKeys();
|
||||
|
||||
log.warn('Slow pubkey derivation...');
|
||||
var path = HDPath.Branch(index, isChange, copayerIndex);
|
||||
var pubKeys = this.publicKeysCache[path];
|
||||
if (!pubKeys) {
|
||||
pubKeys = _.map(this.copayersHK, function(hdKey) {
|
||||
var pubKeys = _.map(this.copayersHK, function(hdKey) {
|
||||
return hdKey.derive(path).eckey.public;
|
||||
});
|
||||
this.publicKeysCache[path] = pubKeys.map(function(pk) {
|
||||
return pk.toString('hex');
|
||||
});
|
||||
} else {
|
||||
pubKeys = pubKeys.map(function(s) {
|
||||
return new Buffer(s, 'hex');
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
return pubKeys;
|
||||
};
|
||||
|
||||
|
|
@ -347,31 +350,24 @@ PublicKeyRing.prototype.getRedeemScript = function(index, isChange, copayerIndex
|
|||
* @param {number} copayerIndex - the index of the copayer that requested the derivation
|
||||
* @returns {bitcore.Address}
|
||||
*/
|
||||
PublicKeyRing.prototype.getAddress = function(index, isChange, id) {
|
||||
PublicKeyRing.prototype._getAddress = function(index, isChange, id) {
|
||||
var copayerIndex = this.getCosigner(id);
|
||||
if (!this._cachedAddress(index, isChange, id)) {
|
||||
var path = HDPath.FullBranch(index, isChange, copayerIndex);
|
||||
|
||||
console.log('[PublicKeyRing.js.338] CACHE MISS'); //TODO
|
||||
var script = this.getRedeemScript(index, isChange, copayerIndex);
|
||||
var address = Address.fromScript(script, this.network.name);
|
||||
this.addressToPath[address.toString()] = HDPath.FullBranch(index, isChange, copayerIndex);
|
||||
this._cacheAddress(index, isChange, copayerIndex, address);
|
||||
}
|
||||
return this._cachedAddress(index, isChange, copayerIndex);
|
||||
log.info('Generating Address:', index, isChange, copayerIndex);
|
||||
var script = this.getRedeemScript(index, isChange, copayerIndex);
|
||||
var address = Address.fromScript(script, this.network.name).toString();
|
||||
|
||||
this._cacheAddress(address, path, isChange);
|
||||
return address;
|
||||
};
|
||||
PublicKeyRing.prototype._cacheAddress = function(index, isChange, copayerIndex, address) {
|
||||
var changeIndex = isChange ? 1 : 0;
|
||||
if (!this._cacheAddressMap) this._cacheAddressMap = {};
|
||||
if (!this._cacheAddressMap[index]) this._cacheAddressMap[index] = {};
|
||||
if (!this._cacheAddressMap[index][changeIndex]) this._cacheAddressMap[index][changeIndex] = {};
|
||||
this._cacheAddressMap[index][changeIndex][copayerIndex] = address;
|
||||
};
|
||||
PublicKeyRing.prototype._cachedAddress = function(index, isChange, copayerIndex) {
|
||||
var changeIndex = isChange ? 1 : 0;
|
||||
if (!this._cacheAddressMap) return undefined;
|
||||
if (!this._cacheAddressMap[index]) return undefined;
|
||||
if (!this._cacheAddressMap[index][changeIndex]) return undefined;
|
||||
return this._cacheAddressMap[index][changeIndex][copayerIndex];
|
||||
|
||||
PublicKeyRing.prototype._cacheAddress = function(address, path, isChange) {
|
||||
this.cache.addressToPath[address] = path;
|
||||
if (isChange)
|
||||
this.cache.changeAddresses.push(address);
|
||||
else
|
||||
this.cache.receiveAddresses.push(address);
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -401,26 +397,12 @@ PublicKeyRing.prototype.getHDParams = function(id) {
|
|||
* @return {HDPath}
|
||||
*/
|
||||
PublicKeyRing.prototype.pathForAddress = function(address) {
|
||||
var path = this.addressToPath[address];
|
||||
this._checkAndRebuildCache();
|
||||
var path = this.cache.addressToPath[address];
|
||||
if (!path) throw new Error('Couldn\'t find path for address ' + address);
|
||||
return path;
|
||||
};
|
||||
|
||||
/**
|
||||
* @desc
|
||||
* Get the hexadecimal representation of a P2SH script
|
||||
*
|
||||
* @param {number} index - index to use when generating the address
|
||||
* @param {boolean} isChange - generate a change address or a receive addres
|
||||
* @param {number|string} pubkey - index of the copayer, or his public key
|
||||
* @returns {string} hexadecimal encoded P2SH hash
|
||||
*/
|
||||
PublicKeyRing.prototype.getScriptPubKeyHex = function(index, isChange, pubkey) {
|
||||
var copayerIndex = this.getCosigner(pubkey);
|
||||
var addr = this.getAddress(index, isChange, copayerIndex);
|
||||
return Script.createP2SH(addr.payload()).getBuffer().toString('hex');
|
||||
};
|
||||
|
||||
/**
|
||||
* @desc
|
||||
* Generates a new address and updates the last index used
|
||||
|
|
@ -433,26 +415,44 @@ PublicKeyRing.prototype.getScriptPubKeyHex = function(index, isChange, pubkey) {
|
|||
*/
|
||||
PublicKeyRing.prototype.generateAddress = function(isChange, pubkey) {
|
||||
isChange = !!isChange;
|
||||
var HDParams = this.getHDParams(pubkey);
|
||||
var index = isChange ? HDParams.getChangeIndex() : HDParams.getReceiveIndex();
|
||||
var ret = this.getAddress(index, isChange, HDParams.copayerIndex);
|
||||
HDParams.increment(isChange);
|
||||
var hdParams = this.getHDParams(pubkey);
|
||||
var index = isChange ? hdParams.getChangeIndex() : hdParams.getReceiveIndex();
|
||||
var ret = this._getAddress(index, isChange, hdParams.copayerIndex);
|
||||
hdParams.increment(isChange);
|
||||
return ret;
|
||||
};
|
||||
|
||||
/**
|
||||
* @desc
|
||||
* Retrieve the addresses from a getAddressInfo return object
|
||||
* @desc Is an address is from this wallet?
|
||||
*
|
||||
* {@see PublicKeyRing#getAddressInfo}
|
||||
* @returns {string[]} the result of retrieving the addresses from calling
|
||||
* @param {string} address
|
||||
* @return {boolean}
|
||||
*/
|
||||
PublicKeyRing.prototype.getAddresses = function(opts) {
|
||||
return this.getAddressesInfo(opts).map(function(info) {
|
||||
return info.address;
|
||||
});
|
||||
PublicKeyRing.prototype.addressIsOwn = function(address) {
|
||||
return !!this.cache.addressToPath[address];
|
||||
};
|
||||
|
||||
/**
|
||||
* @desc Is an address is a change address?
|
||||
*
|
||||
* @param {string} address
|
||||
* @return {boolean}
|
||||
*/
|
||||
PublicKeyRing.prototype.addressIsChange = function(address) {
|
||||
this._checkAndRebuildCache();
|
||||
|
||||
if (!this.cache.addressToPath[address])
|
||||
return null;
|
||||
|
||||
//Memoization Only, never stored.
|
||||
if (_.isUndefined(this._isChange[address])) {
|
||||
this._isChange[address] = _.indexOf(this.cache.changeAddresses, address) >= 0;
|
||||
}
|
||||
return !!this._isChange[address];
|
||||
};
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @desc
|
||||
* Maps a copayer's public key to his index in the keyring
|
||||
|
|
@ -478,79 +478,46 @@ PublicKeyRing.prototype.getCosigner = function(pubKey) {
|
|||
return index;
|
||||
};
|
||||
|
||||
|
||||
|
||||
PublicKeyRing.prototype.buildAddressCache = function() {
|
||||
var ret = [];
|
||||
var self = this;
|
||||
|
||||
log.info('Rebuilding Address Cache...this will take a while');
|
||||
_.each(this.indexes, function(index) {
|
||||
for (var i = 0; i < index.receiveIndex; i++) {
|
||||
self._getAddress(i, false, index.copayerIndex);
|
||||
}
|
||||
for (var i = 0; i < index.changeIndex; i++) {
|
||||
self._getAddress(i, true, index.copayerIndex);
|
||||
}
|
||||
});
|
||||
log.info('...done!');
|
||||
};
|
||||
|
||||
|
||||
PublicKeyRing.prototype._checkAndRebuildCache = function(opts) {
|
||||
// If cache exists, it has to be updated
|
||||
if (_.isEmpty(this.cache.addressToPath)) {
|
||||
this.buildAddressCache();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @desc
|
||||
* Gets information about addresses for a copayer
|
||||
*
|
||||
* @see PublicKeyRing#getAddressesInfoForIndex
|
||||
* @param {Object} opts
|
||||
* @param {string|number} pubkey - the pubkey or index of a copayer in the ring
|
||||
* @returns {AddressInfo[]}
|
||||
*/
|
||||
PublicKeyRing.prototype.getAddressesInfo = function(opts, pubkey) {
|
||||
|
||||
console.log('[PublicKeyRing.js.474] STARTED'); //TODO
|
||||
var ret = [];
|
||||
var self = this;
|
||||
var copayerIndex = pubkey && this.getCosigner(pubkey);
|
||||
console.log('[PublicKeyRing.js.478:copayerIndex:]',copayerIndex); //TODO
|
||||
this.indexes.forEach(function(index) {
|
||||
console.log('[PublicKeyRing.js.479:index:]',index); //TODO
|
||||
ret = ret.concat(self.getAddressesInfoForIndex(index, opts, copayerIndex));
|
||||
});
|
||||
console.log('[PublicKeyRing.js.474] END'); //TODO
|
||||
PublicKeyRing.prototype.getAddresses = function() {
|
||||
this._checkAndRebuildCache();
|
||||
var ret = this.cache.receiveAddresses.concat(this.cache.changeAddresses);
|
||||
return ret;
|
||||
};
|
||||
|
||||
/**
|
||||
* @typedef AddressInfo
|
||||
* @property {bitcore.Address} address - the address generated
|
||||
* @property {string} addressStr - the base58 encoded address
|
||||
* @property {boolean} isChange - true if it's a change address
|
||||
* @property {boolean} owned - true if it's an address generated by a copayer
|
||||
*/
|
||||
/**
|
||||
* @desc
|
||||
* Retrieves info about addresses generated by a copayer
|
||||
*
|
||||
* @param {HDParams} index - HDParams of the copayer
|
||||
* @param {Object} opts
|
||||
* @param {boolean} opts.excludeChange - don't append information about change addresses
|
||||
* @param {boolean} opts.excludeMain - don't append information about receive addresses
|
||||
* @param {string|number|undefined} copayerIndex - copayer index, pubkey, or undefined to fetch info
|
||||
* about shared addresses
|
||||
* @return {AddressInfo[]} a list of AddressInfo
|
||||
*/
|
||||
PublicKeyRing.prototype.getAddressesInfoForIndex = function(index, opts, copayerIndex) {
|
||||
opts = opts || {};
|
||||
var isOwned = index.copayerIndex === HDPath.SHARED_INDEX || index.copayerIndex === copayerIndex;
|
||||
var ret = [];
|
||||
var appendAddressInfo = function(address, isChange) {
|
||||
ret.push({
|
||||
address: address,
|
||||
addressStr: address.toString(),
|
||||
isChange: isChange,
|
||||
owned: isOwned
|
||||
});
|
||||
|
||||
console.log('[PublicKeyRing.js.518] Appending address'); //TODO
|
||||
};
|
||||
|
||||
console.log('[PublicKeyRing.js.519] getAddressesInfoForIndex'); //TODO
|
||||
for (var i = 0; !opts.excludeChange && i < index.changeIndex; i++) {
|
||||
appendAddressInfo(this.getAddress(i, true, index.copayerIndex), true);
|
||||
}
|
||||
|
||||
console.log('[PublicKeyRing.js.526]'); //TODO
|
||||
for (var i = 0; !opts.excludeMain && i < index.receiveIndex; i++) {
|
||||
appendAddressInfo(this.getAddress(i, false, index.copayerIndex), false);
|
||||
}
|
||||
|
||||
|
||||
console.log('[PublicKeyRing.js.534] CACHE IS' , this._cacheAddressMap); //TODO
|
||||
|
||||
return ret;
|
||||
};
|
||||
|
||||
/**
|
||||
* @desc
|
||||
|
|
@ -722,25 +689,6 @@ PublicKeyRing.prototype._mergePubkeys = function(inPKR) {
|
|||
return hasChanged;
|
||||
};
|
||||
|
||||
/**
|
||||
* @desc
|
||||
* Merges this public key ring with another one, optionally ignoring the
|
||||
* wallet id
|
||||
*
|
||||
* @param {PublicKeyRing} inPkr
|
||||
* @param {boolean} ignoreId
|
||||
* @return {boolean} true if the internal state has changed
|
||||
*/
|
||||
PublicKeyRing.prototype.merge = function(inPKR, ignoreId) {
|
||||
this._checkInPKR(inPKR, ignoreId);
|
||||
|
||||
var hasChanged = false;
|
||||
hasChanged |= this.mergeIndexes(inPKR.indexes);
|
||||
hasChanged |= this._mergePubkeys(inPKR);
|
||||
|
||||
return !!hasChanged;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @desc
|
||||
|
|
@ -763,4 +711,25 @@ PublicKeyRing.prototype.mergeIndexes = function(indexes) {
|
|||
}
|
||||
|
||||
|
||||
/**
|
||||
* @desc
|
||||
* Merges this public key ring with another one, optionally ignoring the
|
||||
* wallet id
|
||||
*
|
||||
* @param {PublicKeyRing} inPkr
|
||||
* @param {boolean} ignoreId
|
||||
* @return {boolean} true if the internal state has changed
|
||||
*/
|
||||
PublicKeyRing.prototype.merge = function(inPKR, ignoreId) {
|
||||
this._checkInPKR(inPKR, ignoreId);
|
||||
|
||||
var hasChanged = false;
|
||||
hasChanged |= this.mergeIndexes(inPKR.indexes);
|
||||
hasChanged |= this._mergePubkeys(inPKR);
|
||||
|
||||
return !!hasChanged;
|
||||
};
|
||||
|
||||
|
||||
|
||||
module.exports = PublicKeyRing;
|
||||
|
|
|
|||
|
|
@ -887,7 +887,6 @@ Wallet.prototype._lockIncomming = function() {
|
|||
|
||||
Wallet.prototype._setBlockchainListeners = function() {
|
||||
|
||||
console.log('[Wallet.js.889] address'); //TODO
|
||||
var self = this;
|
||||
self.blockchain.removeAllListeners();
|
||||
self.subscribeToAddresses();
|
||||
|
|
@ -902,14 +901,12 @@ console.log('[Wallet.js.889] address'); //TODO
|
|||
log.debug('Wallet:' + self.id + 'blockchain disconnect event');
|
||||
self.emitAndKeepAlive('insightError');
|
||||
});
|
||||
|
||||
self.blockchain.on('tx', function(tx) {
|
||||
log.debug('Wallet:' + self.id + ' blockchain tx event');
|
||||
var addresses = self.getAddressesInfo();
|
||||
var addr = _.findWhere(addresses, {
|
||||
addressStr: tx.address
|
||||
});
|
||||
if (addr) {
|
||||
self.emitAndKeepAlive('tx', tx.address, addr.isChange);
|
||||
var addresses = self.getAddresses();
|
||||
if (_.indexOf(addresses,tx.address)>=0) {
|
||||
self.emitAndKeepAlive('tx', tx.address, self.addressIsChange(tx.address));
|
||||
}
|
||||
});
|
||||
|
||||
|
|
@ -1055,6 +1052,7 @@ Wallet.prototype.toObj = function() {
|
|||
settings: this.settings,
|
||||
networkNonce: this.network.getHexNonce(), //yours
|
||||
networkNonces: this.network.getHexNonces(), //copayers
|
||||
publicKeyRing: this.publicKeyRing.toObj(),
|
||||
txProposals: this.txProposals.toObj(),
|
||||
privateKey: this.privateKey ? this.privateKey.toObj() : undefined,
|
||||
addressBook: this.addressBook,
|
||||
|
|
@ -1376,21 +1374,15 @@ Wallet.prototype._doGenerateAddress = function(isChange) {
|
|||
return this.publicKeyRing.generateAddress(isChange, this.publicKey);
|
||||
};
|
||||
|
||||
/**
|
||||
* @callback addressCallback
|
||||
* @param {string} addr - all the addresses of the wallet
|
||||
*/
|
||||
/**
|
||||
* @desc Generate a new address
|
||||
* @param {boolean} isChange - whether to generate a change address or a receive address
|
||||
* @param {addressCallback} cb
|
||||
* @return {string[]} a list of all the addresses generated so far for the wallet
|
||||
*/
|
||||
Wallet.prototype.generateAddress = function(isChange, cb) {
|
||||
Wallet.prototype.generateAddress = function(isChange) {
|
||||
var addr = this._doGenerateAddress(isChange);
|
||||
this.sendIndexes();
|
||||
this._newAddresses();
|
||||
if (cb) return cb(addr);
|
||||
return addr;
|
||||
};
|
||||
|
||||
|
|
@ -1844,12 +1836,21 @@ Wallet.prototype.parsePaymentRequest = function(options, rawData) {
|
|||
*/
|
||||
Wallet.prototype._getPayProRefundOutputs = function(txp) {
|
||||
var pkr = this.publicKeyRing;
|
||||
var index = pkr.getHDParams(this.publicKey);
|
||||
var amount = +txp.merchant.total.toString(10);
|
||||
|
||||
var output = new PayPro.Output();
|
||||
var script = pkr.getScriptPubKeyHex(index.changeIndex, true, this.pubkey);
|
||||
output.set('script', new Buffer(script, 'hex'));
|
||||
var opts = JSON.parse(txp.builder.vanilla.opts);
|
||||
if (!opts.remainderOut) {
|
||||
log.warn('no remainder set. Not setting refund in PayPro');
|
||||
return;
|
||||
}
|
||||
console.log('[Wallet.js.1842:builder:]',txp.builder.vanilla.opts); //TODO
|
||||
var addrStr = opts.remainderOut.address;
|
||||
var addr = new bitcore.Address(addrStr);
|
||||
var script = bitcore.Script.createP2SH(addr.payload()).getBuffer();
|
||||
log.debug('PayPro refund address set to:' + addrStr);
|
||||
|
||||
output.set('script', script);
|
||||
output.set('amount', amount);
|
||||
return [output];
|
||||
};
|
||||
|
|
@ -1867,7 +1868,6 @@ Wallet.prototype.createPayProPayment = function(txp) {
|
|||
var tx = txp.builder.build();
|
||||
var txBuf = tx.serialize();
|
||||
|
||||
var refund_outputs = this._getPayProRefundOutputs(txp);
|
||||
|
||||
// We send this to the serve after receiving a PaymentRequest
|
||||
var pay = new PayPro();
|
||||
|
|
@ -1878,9 +1878,11 @@ Wallet.prototype.createPayProPayment = function(txp) {
|
|||
merchant_data = new Buffer(merchant_data, 'hex');
|
||||
pay.set('merchant_data', merchant_data);
|
||||
}
|
||||
|
||||
pay.set('transactions', [txBuf]);
|
||||
pay.set('refund_to', refund_outputs);
|
||||
|
||||
var refund_outputs = this._getPayProRefundOutputs(txp);
|
||||
if (refund_outputs)
|
||||
pay.set('refund_to', refund_outputs);
|
||||
|
||||
// Unused for now
|
||||
// options.memo = '';
|
||||
|
|
@ -2002,28 +2004,32 @@ Wallet.prototype.getAddressesStr = function(opts) {
|
|||
|
||||
Wallet.prototype.subscribeToAddresses = function() {
|
||||
if (!this.publicKeyRing.isComplete()) return;
|
||||
console.log('[Wallet.js.2002:subscribeToAddresses:]'); //TODO
|
||||
|
||||
var addrInfo = this.publicKeyRing.getAddressesInfo();
|
||||
this.blockchain.subscribe(_.pluck(addrInfo, 'addressStr'));
|
||||
log.debug('Subscribed to ' + addrInfo.length + ' addresses');
|
||||
var addresses = this.publicKeyRing.getAddresses();
|
||||
this.blockchain.subscribe(addresses);
|
||||
log.debug('Subscribed to ' + addresses.length + ' addresses');
|
||||
};
|
||||
|
||||
/**
|
||||
* @desc Alias for {@link PublicKeyRing#getAddressesInfo}
|
||||
*/
|
||||
Wallet.prototype.getAddressesInfo = function(opts) {
|
||||
return this.publicKeyRing.getAddressesInfo(opts, this.publicKey);
|
||||
};
|
||||
/**
|
||||
* @desc Returns true if a given address was generated by deriving our master public key
|
||||
* @return {boolean}
|
||||
*/
|
||||
Wallet.prototype.addressIsOwn = function(addrStr) {
|
||||
return !!this.publicKeyRing.addressToPath[addrStr];
|
||||
return this.publicKeyRing.addressIsOwn(addrStr);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @desc Returns true if a given address is a change address (remainder)
|
||||
* @param addrStr
|
||||
* @return {boolean}
|
||||
*/
|
||||
Wallet.prototype.addressIsChange = function(addrStr) {
|
||||
return this.publicKeyRing.addressIsChange(addrStr);
|
||||
};
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Estimate a tx fee in satoshis given its input count
|
||||
* (only used when spending all wallet funds)
|
||||
|
|
@ -2110,7 +2116,7 @@ Wallet.prototype.maxRejectCount = function() {
|
|||
// TODO: Can we add cache to getUnspent?
|
||||
Wallet.prototype.getUnspent = function(cb) {
|
||||
var self = this;
|
||||
this.blockchain.getUnspent(this.getAddressesStr(), function(err, unspentList) {
|
||||
this.blockchain.getUnspent(this.getAddresses(), function(err, unspentList) {
|
||||
|
||||
if (err) {
|
||||
return cb(err);
|
||||
|
|
@ -2372,7 +2378,8 @@ Wallet.prototype.deriveAddresses = function(index, amount, isChange, copayerInde
|
|||
|
||||
var ret = new Array(amount);
|
||||
for (var i = 0; i < amount; i++) {
|
||||
ret[i] = this.publicKeyRing.getAddress(index + i, isChange, copayerIndex).toString();
|
||||
// TODO
|
||||
ret[i] = this.publicKeyRing._getAddress(index + i, isChange, copayerIndex).toString();
|
||||
}
|
||||
return ret;
|
||||
};
|
||||
|
|
@ -2534,7 +2541,7 @@ Wallet.prototype.getTransactionHistory = function(opts, cb) {
|
|||
}
|
||||
opts = opts || {};
|
||||
|
||||
var addresses = self.getAddressesInfo();
|
||||
var addresses = self.getAddresses();
|
||||
var proposals = self.txProposals.txps;
|
||||
var satToUnit = 1 / self.settings.unitToSatoshi;
|
||||
|
||||
|
|
@ -2544,33 +2551,26 @@ Wallet.prototype.getTransactionHistory = function(opts, cb) {
|
|||
function extractInsOuts(tx) {
|
||||
// Inputs
|
||||
var inputs = _.map(tx.vin, function(item) {
|
||||
var addr = _.findWhere(addresses, {
|
||||
addressStr: item.addr
|
||||
});
|
||||
return {
|
||||
type: 'in',
|
||||
address: addr ? addr.addressStr : item.addr,
|
||||
isMine: !_.isUndefined(addr),
|
||||
isChange: addr ? !!addr.isChange : false,
|
||||
address: item.addr,
|
||||
isMine: self.addressIsOwn(item.addr),
|
||||
isChange: self.addressIsChange(item.addr),
|
||||
amountSat: item.valueSat,
|
||||
}
|
||||
});
|
||||
var outputs = _.map(tx.vout, function(item) {
|
||||
var addr;
|
||||
var itemAddr;
|
||||
// If classic multisig, ignore
|
||||
if (item.scriptPubKey && item.scriptPubKey.addresses.length == 1) {
|
||||
itemAddr = item.scriptPubKey.addresses[0];
|
||||
addr = _.findWhere(addresses, {
|
||||
addressStr: itemAddr,
|
||||
});
|
||||
}
|
||||
|
||||
return {
|
||||
type: 'out',
|
||||
address: addr ? addr.addressStr : itemAddr,
|
||||
isMine: !_.isUndefined(addr),
|
||||
isChange: addr ? !!addr.isChange : false,
|
||||
address: itemAddr,
|
||||
isMine: self.addressIsOwn(itemAddr),
|
||||
isChange: self.addressIsChange(itemAddr),
|
||||
label: self.addressBook[itemAddr] ? self.addressBook[itemAddr].label : undefined,
|
||||
amountSat: parseInt((item.value * bitcore.util.COIN).toFixed(0)),
|
||||
}
|
||||
|
|
@ -2608,6 +2608,8 @@ Wallet.prototype.getTransactionHistory = function(opts, cb) {
|
|||
|
||||
var fees = parseInt((tx.fees * bitcore.util.COIN).toFixed(0));
|
||||
var amount;
|
||||
|
||||
|
||||
if (amountIn == (amountOut + amountOutChange + (amountIn > 0 ? fees : 0))) {
|
||||
tx.action = 'moved';
|
||||
amount = amountOut;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue