Merge pull request #701 from matiu/feat/cash-utxo

add coin to getUtxo
This commit is contained in:
Matias Alejo Garcia 2017-09-14 18:40:11 -03:00 committed by GitHub
commit 12dee6fd59
6 changed files with 1090 additions and 899 deletions

View File

@ -7,6 +7,13 @@ var encoding = bitcore.encoding;
var secp256k1 = require('secp256k1'); var secp256k1 = require('secp256k1');
var Utils = {}; var Utils = {};
var Bitcore = require('bitcore-lib');
var Bitcore_ = {
btc: Bitcore,
bch: require('bitcore-lib-cash')
};
Utils.getMissingFields = function(obj, args) { Utils.getMissingFields = function(obj, args) {
args = [].concat(args); args = [].concat(args);
@ -186,4 +193,30 @@ Utils.checkValueInCollection = function(value, collection) {
return _.contains(_.values(collection), value); return _.contains(_.values(collection), value);
}; };
Utils.getAddressCoin = function(address) {
try {
new Bitcore_['btc'].Address(address);
return 'btc';
} catch (e) {
try {
new Bitcore_['bch'].Address(address);
return 'bch';
} catch (e) {
return;
}
}
};
Utils.translateAddress = function(address, coin) {
var origCoin = Utils.getAddressCoin(address);
var origAddress = new Bitcore_[origCoin].Address(address);
var origObj = origAddress.toObject();
var result = Bitcore_[coin].Address.fromObject(origObj)
return result.toString();
};
module.exports = Utils; module.exports = Utils;

View File

@ -1077,7 +1077,8 @@ WalletService.prototype._getUtxos = function(coin, addresses, cb) {
var self = this; var self = this;
if (addresses.length == 0) return cb(null, []); if (addresses.length == 0) return cb(null, []);
var networkName = Bitcore.Address(addresses[0]).toObject().network;
var networkName = Bitcore_[coin].Address(addresses[0]).toObject().network;
var bc = self._getBlockchainExplorer(coin, networkName); var bc = self._getBlockchainExplorer(coin, networkName);
if (!bc) return cb(new Error('Could not get blockchain explorer instance')); if (!bc) return cb(new Error('Could not get blockchain explorer instance'));
@ -1106,20 +1107,16 @@ WalletService.prototype._getUtxosForCurrentWallet = function(opts, cb) {
return utxo.txid + '|' + utxo.vout return utxo.txid + '|' + utxo.vout
}; };
var coin, allAddresses, allUtxos, utxoIndex; var coin, allAddresses, allUtxos, utxoIndex, addressStrs;
async.series([ async.series([
function(next) { function(next) {
if (opts.coin) { self.getWallet({}, function(err, wallet) {
coin = opts.coin; if (err) return next(err);
next();
} else { coin = wallet.coin;
self.getWallet({}, function(err, wallet) { return next();
coin = wallet.coin; });
return next();
});
}
}, },
function(next) { function(next) {
if (_.isArray(opts.addresses)) { if (_.isArray(opts.addresses)) {
@ -1128,13 +1125,23 @@ WalletService.prototype._getUtxosForCurrentWallet = function(opts, cb) {
} }
self.storage.fetchAddresses(self.walletId, function(err, addresses) { self.storage.fetchAddresses(self.walletId, function(err, addresses) {
allAddresses = addresses; allAddresses = addresses;
if (allAddresses.length == 0) return cb(null, []);
return next(); return next();
}); });
}, },
function(next) { function(next) {
if (allAddresses.length == 0) return cb(null, []); addressStrs = _.pluck(allAddresses, 'address');
if (!opts.coin) return next();
coin = opts.coin;
addressStrs = _.map(addressStrs, function(a) {
return Utils.translateAddress(a, coin);
});
next();
},
function(next) {
var addressStrs = _.pluck(allAddresses, 'address');
self._getUtxos(coin, addressStrs, function(err, utxos) { self._getUtxos(coin, addressStrs, function(err, utxos) {
if (err) return next(err); if (err) return next(err);
@ -1206,16 +1213,17 @@ WalletService.prototype.getUtxos = function(opts, cb) {
opts = opts || {}; opts = opts || {};
opts.coin = opts.coin || Defaults.COIN; if (opts.coin) {
if (!Utils.checkValueInCollection(opts.coin, Constants.COINS)) if (!Utils.checkValueInCollection(opts.coin, Constants.COINS))
return cb(new ClientError('Invalid coin')); return cb(new ClientError('Invalid coin'));
}
if (_.isUndefined(opts.addresses)) { if (_.isUndefined(opts.addresses)) {
self._getUtxosForCurrentWallet({ self._getUtxosForCurrentWallet({
coin: opts.coin coin: opts.coin
}, cb); }, cb);
} else { } else {
self._getUtxos(opts.coin, opts.addresses, cb); self._getUtxos(Utils.getAddressCoin(opts.addresses[0]), opts.addresses, cb);
} }
}; };
@ -1922,6 +1930,7 @@ WalletService.prototype._canCreateTx = function(cb) {
}; };
WalletService.prototype._validateOutputs = function(opts, wallet, cb) { WalletService.prototype._validateOutputs = function(opts, wallet, cb) {
var A = Bitcore_[wallet.coin].Address;
var dustThreshold = Math.max(Defaults.MIN_OUTPUT_AMOUNT, Bitcore_[wallet.coin].Transaction.DUST_AMOUNT); var dustThreshold = Math.max(Defaults.MIN_OUTPUT_AMOUNT, Bitcore_[wallet.coin].Transaction.DUST_AMOUNT);
if (_.isEmpty(opts.outputs)) return new ClientError('No outputs were specified'); if (_.isEmpty(opts.outputs)) return new ClientError('No outputs were specified');
@ -1936,7 +1945,7 @@ WalletService.prototype._validateOutputs = function(opts, wallet, cb) {
var toAddress = {}; var toAddress = {};
try { try {
toAddress = new Bitcore.Address(output.toAddress); toAddress = new A(output.toAddress);
} catch (ex) { } catch (ex) {
return Errors.INVALID_ADDRESS; return Errors.INVALID_ADDRESS;
} }

View File

@ -2,7 +2,7 @@
"name": "bitcore-wallet-service", "name": "bitcore-wallet-service",
"description": "A service for Mutisig HD Bitcoin Wallets", "description": "A service for Mutisig HD Bitcoin Wallets",
"author": "BitPay Inc", "author": "BitPay Inc",
"version": "2.0.0", "version": "2.1.0",
"licence": "MIT", "licence": "MIT",
"keywords": [ "keywords": [
"bitcoin", "bitcoin",
@ -71,14 +71,18 @@
"coveralls": "./node_modules/.bin/istanbul cover ./node_modules/mocha/bin/_mocha --report lcovonly -- -R spec && cat ./coverage/lcov.info | ./node_modules/coveralls/bin/coveralls.js && rm -rf ./coverage" "coveralls": "./node_modules/.bin/istanbul cover ./node_modules/mocha/bin/_mocha --report lcovonly -- -R spec && cat ./coverage/lcov.info | ./node_modules/coveralls/bin/coveralls.js && rm -rf ./coverage"
}, },
"bitcoreNode": "./bitcorenode", "bitcoreNode": "./bitcorenode",
"contributors": [{ "contributors": [
"name": "Braydon Fuller", {
"email": "braydon@bitpay.com" "name": "Braydon Fuller",
}, { "email": "braydon@bitpay.com"
"name": "Ivan Socolsky", },
"email": "ivan@bitpay.com" {
}, { "name": "Ivan Socolsky",
"name": "Matias Alejo Garcia", "email": "ivan@bitpay.com"
"email": "ematiu@gmail.com" },
}] {
"name": "Matias Alejo Garcia",
"email": "ematiu@gmail.com"
}
]
} }

View File

@ -277,6 +277,8 @@ helpers.stubUtxos = function(server, wallet, amounts, opts, cb) {
if (!helpers._utxos) helpers._utxos = {}; if (!helpers._utxos) helpers._utxos = {};
var S = Bitcore_[wallet.coin].Script;
async.waterfall([ async.waterfall([
function(next) { function(next) {
@ -298,10 +300,10 @@ helpers.stubUtxos = function(server, wallet, amounts, opts, cb) {
var scriptPubKey; var scriptPubKey;
switch (wallet.addressType) { switch (wallet.addressType) {
case Constants.SCRIPT_TYPES.P2SH: case Constants.SCRIPT_TYPES.P2SH:
scriptPubKey = Bitcore.Script.buildMultisigOut(address.publicKeys, wallet.m).toScriptHashOut(); scriptPubKey = S.buildMultisigOut(address.publicKeys, wallet.m).toScriptHashOut();
break; break;
case Constants.SCRIPT_TYPES.P2PKH: case Constants.SCRIPT_TYPES.P2PKH:
scriptPubKey = Bitcore.Script.buildPublicKeyHashOut(address.address); scriptPubKey = S.buildPublicKeyHashOut(address.address);
break; break;
} }
should.exist(scriptPubKey); should.exist(scriptPubKey);

File diff suppressed because it is too large Load Diff

View File

@ -131,4 +131,42 @@ describe('Utils', function() {
}); });
}); });
}); });
describe('#getAddressCoin', function() {
it('should identify btc as coin for 1LqBGSKuX5yYUonjxT5qGfpUsXKYYWeabA', function() {
Utils.getAddressCoin('1LqBGSKuX5yYUonjxT5qGfpUsXKYYWeabA').should.equal('btc');
});
it('should identify bch as coin for CcJ4qUfyQ8x5NwhAeCQkrBSWVeXxXghcNz', function() {
Utils.getAddressCoin('CcJ4qUfyQ8x5NwhAeCQkrBSWVeXxXghcNz').should.equal('bch');
});
it('should return null for 1L', function() {
should.not.exist(Utils.getAddressCoin('1L'));
});
});
describe('#translateAddress', function() {
it('should translate address from btc to bch', function() {
var res = Utils.translateAddress('1LqBGSKuX5yYUonjxT5qGfpUsXKYYWeabA', 'bch');
res.should.equal('CcJ4qUfyQ8x5NwhAeCQkrBSWVeXxXghcNz');
});
it('should translate address from bch to btc', function() {
var res = Utils.translateAddress('HBf8isgS8EXG1r3X6GP89FmooUmiJ42wHS', 'btc');
res.should.equal('36q2G5FMGvJbPgAVEaiyAsFGmpkhPKwk2r');
});
it('should keep the address if there is nothing to do (bch)', function() {
var res = Utils.translateAddress('CcJ4qUfyQ8x5NwhAeCQkrBSWVeXxXghcNz', 'bch');
res.should.equal('CcJ4qUfyQ8x5NwhAeCQkrBSWVeXxXghcNz');
});
it('should keep the address if there is nothing to do (btc)', function() {
var res = Utils.translateAddress('1LqBGSKuX5yYUonjxT5qGfpUsXKYYWeabA', 'btc');
should.exist(res);
res.should.equal('1LqBGSKuX5yYUonjxT5qGfpUsXKYYWeabA');
});
});
}); });