commit
12dee6fd59
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
26
package.json
26
package.json
|
@ -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"
|
||||||
|
}
|
||||||
|
]
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
@ -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');
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
Loading…
Reference in New Issue