remove bitcore-wallet-utils dependency
This commit is contained in:
parent
ea5926229c
commit
eb006c3db3
|
@ -10,7 +10,7 @@ var fs = require('fs');
|
|||
var path = require('path');
|
||||
var nodemailer = require('nodemailer');
|
||||
|
||||
var WalletUtils = require('bitcore-wallet-utils');
|
||||
var Utils = require('./utils');
|
||||
var Storage = require('./storage');
|
||||
var MessageBroker = require('./messagebroker');
|
||||
var Lock = require('./lock');
|
||||
|
@ -227,7 +227,7 @@ EmailService.prototype._getDataForTemplate = function(notification, recipient, c
|
|||
if (data.amount) {
|
||||
try {
|
||||
var unit = recipient.unit.toLowerCase();
|
||||
data.amount = WalletUtils.formatAmount(+data.amount, unit) + ' ' + UNIT_LABELS[unit];
|
||||
data.amount = Utils.formatAmount(+data.amount, unit) + ' ' + UNIT_LABELS[unit];
|
||||
} catch (ex) {
|
||||
return cb(new Error('Could not format amount', ex));
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
'use strict';
|
||||
|
||||
var WalletUtils = require('bitcore-wallet-utils');
|
||||
var Bitcore = WalletUtils.Bitcore;
|
||||
var Bitcore = require('bitcore-lib');
|
||||
var Constants = require('../constants');
|
||||
|
||||
function Address() {};
|
||||
|
||||
|
@ -18,7 +18,7 @@ Address.create = function(opts) {
|
|||
x.path = opts.path;
|
||||
x.publicKeys = opts.publicKeys;
|
||||
x.network = Bitcore.Address(x.address).toObject().network;
|
||||
x.type = opts.type || WalletUtils.SCRIPT_TYPES.P2SH;
|
||||
x.type = opts.type || Constants.SCRIPT_TYPES.P2SH;
|
||||
x.hasActivity = undefined;
|
||||
return x;
|
||||
};
|
||||
|
@ -34,7 +34,7 @@ Address.fromObj = function(obj) {
|
|||
x.isChange = obj.isChange;
|
||||
x.path = obj.path;
|
||||
x.publicKeys = obj.publicKeys;
|
||||
x.type = obj.type || WalletUtils.SCRIPT_TYPES.P2SH;
|
||||
x.type = obj.type || Constants.SCRIPT_TYPES.P2SH;
|
||||
x.hasActivity = obj.hasActivity;
|
||||
return x;
|
||||
};
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
var _ = require('lodash');
|
||||
var $ = require('preconditions').singleton();
|
||||
|
||||
var WalletUtils = require('bitcore-wallet-utils');
|
||||
var Bitcore = require('bitcore-lib');
|
||||
var Constants = require('../constants');
|
||||
|
||||
var BIP45_SHARED_INDEX = 0x80000000 - 1;
|
||||
|
||||
|
@ -13,8 +14,8 @@ AddressManager.create = function(opts) {
|
|||
var x = new AddressManager();
|
||||
|
||||
x.version = 2;
|
||||
x.derivationStrategy = opts.derivationStrategy || WalletUtils.DERIVATION_STRATEGIES.BIP45;
|
||||
$.checkState(_.contains(_.values(WalletUtils.DERIVATION_STRATEGIES), x.derivationStrategy));
|
||||
x.derivationStrategy = opts.derivationStrategy || Constants.DERIVATION_STRATEGIES.BIP45;
|
||||
$.checkState(_.contains(_.values(Constants.DERIVATION_STRATEGIES), x.derivationStrategy));
|
||||
|
||||
x.receiveAddressIndex = 0;
|
||||
x.changeAddressIndex = 0;
|
||||
|
@ -27,7 +28,7 @@ AddressManager.fromObj = function(obj) {
|
|||
var x = new AddressManager();
|
||||
|
||||
x.version = obj.version;
|
||||
x.derivationStrategy = obj.derivationStrategy || WalletUtils.DERIVATION_STRATEGIES.BIP45;
|
||||
x.derivationStrategy = obj.derivationStrategy || Constants.DERIVATION_STRATEGIES.BIP45;
|
||||
x.receiveAddressIndex = obj.receiveAddressIndex;
|
||||
x.changeAddressIndex = obj.changeAddressIndex;
|
||||
x.copayerIndex = obj.copayerIndex;
|
||||
|
@ -36,7 +37,7 @@ AddressManager.fromObj = function(obj) {
|
|||
};
|
||||
|
||||
AddressManager.supportsCopayerBranches = function(derivationStrategy) {
|
||||
return derivationStrategy == WalletUtils.DERIVATION_STRATEGIES.BIP45;
|
||||
return derivationStrategy == Constants.DERIVATION_STRATEGIES.BIP45;
|
||||
};
|
||||
|
||||
AddressManager.prototype._incrementIndex = function(isChange) {
|
||||
|
@ -58,7 +59,7 @@ AddressManager.prototype.rewindIndex = function(isChange, n) {
|
|||
|
||||
AddressManager.prototype.getCurrentAddressPath = function(isChange) {
|
||||
return 'm/' +
|
||||
(this.derivationStrategy == WalletUtils.DERIVATION_STRATEGIES.BIP45 ? this.copayerIndex + '/' : '') +
|
||||
(this.derivationStrategy == Constants.DERIVATION_STRATEGIES.BIP45 ? this.copayerIndex + '/' : '') +
|
||||
(isChange ? 1 : 0) + '/' +
|
||||
(isChange ? this.changeAddressIndex : this.receiveAddressIndex);
|
||||
};
|
||||
|
|
|
@ -3,17 +3,22 @@
|
|||
var $ = require('preconditions').singleton();
|
||||
var _ = require('lodash');
|
||||
var util = require('util');
|
||||
|
||||
var Uuid = require('uuid');
|
||||
var sjcl = require('sjcl');
|
||||
|
||||
var Address = require('./address');
|
||||
var AddressManager = require('./addressmanager');
|
||||
var WalletUtils = require('bitcore-wallet-utils');
|
||||
var Bitcore = WalletUtils.Bitcore;
|
||||
var HDPublicKey = Bitcore.HDPublicKey;
|
||||
var Bitcore = require('bitcore-lib');
|
||||
var Constants = require('../constants');
|
||||
var Utils = require('../utils');
|
||||
|
||||
function Copayer() {};
|
||||
|
||||
Copayer._xPubToCopayerId = function(xpub) {
|
||||
var hash = sjcl.hash.sha256.hash(xpub);
|
||||
return sjcl.codec.hex.fromBits(hash);
|
||||
};
|
||||
|
||||
Copayer.create = function(opts) {
|
||||
opts = opts || {};
|
||||
$.checkArgument(opts.xPubKey, 'Missing copayer extended public key')
|
||||
|
@ -27,7 +32,7 @@ Copayer.create = function(opts) {
|
|||
x.version = 2;
|
||||
x.createdOn = Math.floor(Date.now() / 1000);
|
||||
x.xPubKey = opts.xPubKey;
|
||||
x.id = WalletUtils.xPubToCopayerId(x.xPubKey);
|
||||
x.id = Copayer._xPubToCopayerId(x.xPubKey);
|
||||
x.name = opts.name;
|
||||
x.requestPubKey = opts.requestPubKey;
|
||||
x.signature = opts.signature;
|
||||
|
@ -36,7 +41,7 @@ Copayer.create = function(opts) {
|
|||
signature: opts.signature,
|
||||
}];
|
||||
|
||||
var derivationStrategy = opts.derivationStrategy || WalletUtils.DERIVATION_STRATEGIES.BIP45;
|
||||
var derivationStrategy = opts.derivationStrategy || Constants.DERIVATION_STRATEGIES.BIP45;
|
||||
if (AddressManager.supportsCopayerBranches(derivationStrategy)) {
|
||||
x.addressManager = AddressManager.create({
|
||||
derivationStrategy: derivationStrategy,
|
||||
|
@ -82,7 +87,7 @@ Copayer.prototype.createAddress = function(wallet, isChange) {
|
|||
$.checkState(wallet.isComplete());
|
||||
|
||||
var path = this.addressManager.getNewAddressPath(isChange);
|
||||
var raw = Address.create(WalletUtils.deriveAddress(wallet.addressType, wallet.publicKeyRing, path, wallet.m, wallet.network));
|
||||
var raw = Address.create(Utils.deriveAddress(wallet.addressType, wallet.publicKeyRing, path, wallet.m, wallet.network));
|
||||
var address = Address.create(_.extend(raw, {
|
||||
walletId: wallet.id,
|
||||
type: wallet.addressType,
|
||||
|
|
|
@ -7,9 +7,9 @@ var log = require('npmlog');
|
|||
log.debug = log.verbose;
|
||||
log.disableColor();
|
||||
|
||||
var WalletUtils = require('bitcore-wallet-utils');
|
||||
var Bitcore = WalletUtils.Bitcore;
|
||||
var Address = Bitcore.Address;
|
||||
var Bitcore = require('bitcore-lib');
|
||||
var Constants = require('../constants');
|
||||
var Utils = require('../utils');
|
||||
|
||||
var TxProposalAction = require('./txproposalaction');
|
||||
|
||||
|
@ -76,8 +76,8 @@ TxProposal.create = function(opts) {
|
|||
x.excludeUnconfirmedUtxos = opts.excludeUnconfirmedUtxos;
|
||||
x.proposalSignaturePubKey = opts.proposalSignaturePubKey;
|
||||
x.proposalSignaturePubKeySig = opts.proposalSignaturePubKeySig;
|
||||
x.derivationStrategy = opts.derivationStrategy || WalletUtils.DERIVATION_STRATEGIES.BIP45;
|
||||
x.addressType = opts.addressType || WalletUtils.SCRIPT_TYPES.P2SH;
|
||||
x.derivationStrategy = opts.derivationStrategy || Constants.DERIVATION_STRATEGIES.BIP45;
|
||||
x.addressType = opts.addressType || Constants.SCRIPT_TYPES.P2SH;
|
||||
x.customData = opts.customData;
|
||||
|
||||
if (_.isFunction(TxProposal._create[x.type])) {
|
||||
|
@ -125,8 +125,8 @@ TxProposal.fromObj = function(obj) {
|
|||
x.excludeUnconfirmedUtxos = obj.excludeUnconfirmedUtxos;
|
||||
x.proposalSignaturePubKey = obj.proposalSignaturePubKey;
|
||||
x.proposalSignaturePubKeySig = obj.proposalSignaturePubKeySig;
|
||||
x.derivationStrategy = obj.derivationStrategy || WalletUtils.DERIVATION_STRATEGIES.BIP45;
|
||||
x.addressType = obj.addressType || WalletUtils.SCRIPT_TYPES.P2SH;
|
||||
x.derivationStrategy = obj.derivationStrategy || Constants.DERIVATION_STRATEGIES.BIP45;
|
||||
x.addressType = obj.addressType || Constants.SCRIPT_TYPES.P2SH;
|
||||
x.customData = obj.customData;
|
||||
|
||||
return x;
|
||||
|
@ -164,7 +164,7 @@ TxProposal.prototype._getCurrentSignatures = function() {
|
|||
TxProposal.prototype.getBitcoreTx = function() {
|
||||
var self = this;
|
||||
|
||||
var t = WalletUtils.buildTx(this);
|
||||
var t = Utils.buildTx(this);
|
||||
|
||||
var sigs = this._getCurrentSignatures();
|
||||
_.each(sigs, function(x) {
|
||||
|
|
|
@ -8,7 +8,8 @@ var Uuid = require('uuid');
|
|||
var Address = require('./address');
|
||||
var Copayer = require('./copayer');
|
||||
var AddressManager = require('./addressmanager');
|
||||
var WalletUtils = require('bitcore-wallet-utils');
|
||||
var Constants = require('../constants');
|
||||
var Utils = require('../utils');
|
||||
|
||||
function Wallet() {};
|
||||
|
||||
|
@ -29,8 +30,8 @@ Wallet.create = function(opts) {
|
|||
x.copayers = [];
|
||||
x.pubKey = opts.pubKey;
|
||||
x.network = opts.network;
|
||||
x.derivationStrategy = opts.derivationStrategy || WalletUtils.DERIVATION_STRATEGIES.BIP45;
|
||||
x.addressType = opts.addressType || WalletUtils.SCRIPT_TYPES.P2SH;
|
||||
x.derivationStrategy = opts.derivationStrategy || Constants.DERIVATION_STRATEGIES.BIP45;
|
||||
x.addressType = opts.addressType || Constants.SCRIPT_TYPES.P2SH;
|
||||
|
||||
x.addressManager = AddressManager.create({
|
||||
derivationStrategy: x.derivationStrategy,
|
||||
|
@ -56,8 +57,8 @@ Wallet.fromObj = function(obj) {
|
|||
});
|
||||
x.pubKey = obj.pubKey;
|
||||
x.network = obj.network;
|
||||
x.derivationStrategy = obj.derivationStrategy || WalletUtils.DERIVATION_STRATEGIES.BIP45;
|
||||
x.addressType = obj.addressType || WalletUtils.SCRIPT_TYPES.P2SH;
|
||||
x.derivationStrategy = obj.derivationStrategy || Constants.DERIVATION_STRATEGIES.BIP45;
|
||||
x.addressType = obj.addressType || Constants.SCRIPT_TYPES.P2SH;
|
||||
x.addressManager = AddressManager.fromObj(obj.addressManager);
|
||||
x.scanStatus = obj.scanStatus;
|
||||
|
||||
|
@ -153,7 +154,7 @@ Wallet.prototype.createAddress = function(isChange) {
|
|||
var self = this;
|
||||
|
||||
var path = this.addressManager.getNewAddressPath(isChange);
|
||||
var raw = WalletUtils.deriveAddress(this.addressType, this.publicKeyRing, path, this.m, this.network);
|
||||
var raw = Utils.deriveAddress(this.addressType, this.publicKeyRing, path, this.m, this.network);
|
||||
var address = Address.create(_.extend(raw, {
|
||||
walletId: self.id,
|
||||
type: self.addressType,
|
||||
|
|
125
lib/server.js
125
lib/server.js
|
@ -6,13 +6,11 @@ var log = require('npmlog');
|
|||
log.debug = log.verbose;
|
||||
log.disableColor();
|
||||
var EmailValidator = require('email-validator');
|
||||
var Stringify = require('json-stable-stringify');
|
||||
|
||||
var WalletUtils = require('bitcore-wallet-utils');
|
||||
var Bitcore = WalletUtils.Bitcore;
|
||||
var PublicKey = Bitcore.PublicKey;
|
||||
var HDPublicKey = Bitcore.HDPublicKey;
|
||||
var Address = Bitcore.Address;
|
||||
var Bitcore = require('bitcore-lib');
|
||||
|
||||
var Constants = require('./constants');
|
||||
var ClientError = require('./errors/clienterror');
|
||||
var Errors = require('./errors/errordefinitions');
|
||||
|
||||
|
@ -51,52 +49,6 @@ function WalletService() {
|
|||
this.notifyTicker = 0;
|
||||
};
|
||||
|
||||
WalletService.SCRIPT_TYPES = {
|
||||
P2SH: 'P2SH',
|
||||
P2PKH: 'P2PKH',
|
||||
};
|
||||
WalletService.DERIVATION_STRATEGIES = {
|
||||
BIP44: 'BIP44',
|
||||
BIP45: 'BIP45',
|
||||
};
|
||||
|
||||
WalletService.DEFAULT_FEE_PER_KB = 10000;
|
||||
WalletService.MIN_FEE_PER_KB = 0;
|
||||
WalletService.MAX_FEE_PER_KB = 1000000;
|
||||
WalletService.MAX_TX_FEE = 1 * 1e8;
|
||||
|
||||
WalletService.MAX_KEYS = 100;
|
||||
|
||||
// Time after which a Tx proposal can be erased by any copayer. in seconds
|
||||
WalletService.DELETE_LOCKTIME = 24 * 3600;
|
||||
|
||||
// Allowed consecutive txp rejections before backoff is applied.
|
||||
WalletService.BACKOFF_OFFSET = 3;
|
||||
|
||||
// Time a copayer need to wait to create a new TX after her tx previous proposal we rejected. (incremental). in Minutes.
|
||||
WalletService.BACKOFF_TIME = 2;
|
||||
|
||||
WalletService.MAX_MAIN_ADDRESS_GAP = 20;
|
||||
|
||||
// Fund scanning parameters
|
||||
WalletService.SCAN_CONFIG = {
|
||||
maxGap: WalletService.MAX_MAIN_ADDRESS_GAP,
|
||||
};
|
||||
|
||||
WalletService.FEE_LEVELS = [{
|
||||
name: 'priority',
|
||||
nbBlocks: 1,
|
||||
defaultValue: 50000
|
||||
}, {
|
||||
name: 'normal',
|
||||
nbBlocks: 2,
|
||||
defaultValue: 20000
|
||||
}, {
|
||||
name: 'economy',
|
||||
nbBlocks: 6,
|
||||
defaultValue: 10000
|
||||
}];
|
||||
|
||||
|
||||
/**
|
||||
* Gets the current version of BWS
|
||||
|
@ -247,11 +199,11 @@ WalletService.prototype.createWallet = function(opts, cb) {
|
|||
|
||||
opts.supportBIP44AndP2PKH = _.isBoolean(opts.supportBIP44AndP2PKH) ? opts.supportBIP44AndP2PKH : true;
|
||||
|
||||
var derivationStrategy = opts.supportBIP44AndP2PKH ? WalletService.DERIVATION_STRATEGIES.BIP44 : WalletService.DERIVATION_STRATEGIES.BIP45;
|
||||
var addressType = (opts.n == 1 && opts.supportBIP44AndP2PKH) ? WalletService.SCRIPT_TYPES.P2PKH : WalletService.SCRIPT_TYPES.P2SH;
|
||||
var derivationStrategy = opts.supportBIP44AndP2PKH ? Constants.DERIVATION_STRATEGIES.BIP44 : Constants.DERIVATION_STRATEGIES.BIP45;
|
||||
var addressType = (opts.n == 1 && opts.supportBIP44AndP2PKH) ? Constants.SCRIPT_TYPES.P2PKH : Constants.SCRIPT_TYPES.P2SH;
|
||||
|
||||
try {
|
||||
pubKey = new PublicKey.fromString(opts.pubKey);
|
||||
pubKey = new Bitcore.PublicKey.fromString(opts.pubKey);
|
||||
} catch (ex) {
|
||||
return cb(new ClientError('Invalid public key'));
|
||||
};
|
||||
|
@ -367,6 +319,7 @@ WalletService.prototype.getStatus = function(opts, cb) {
|
|||
});
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* Verifies a signature
|
||||
* @param text
|
||||
|
@ -374,10 +327,21 @@ WalletService.prototype.getStatus = function(opts, cb) {
|
|||
* @param pubKeys
|
||||
*/
|
||||
WalletService.prototype._verifySignature = function(text, signature, pubkey) {
|
||||
return WalletUtils.verifyMessage(text, signature, pubkey);
|
||||
return Utils.verifyMessage(text, signature, pubkey);
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* Verifies a request public key
|
||||
* @param requestPubKey
|
||||
* @param signature
|
||||
* @param xPubKey
|
||||
*/
|
||||
WalletService.prototype._verifyRequestPubKey = function(requestPubKey, signature, xPubKey) {
|
||||
var pub = (new Bitcore.HDPublicKey(xPubKey)).derive(Constants.PATHS.REQUEST_KEY_AUTH).publicKey;
|
||||
return Utils.verifyMessage(requestPubKey, signature, pub.toString());
|
||||
};
|
||||
|
||||
/*
|
||||
* Verifies signature againt a collection of pubkeys
|
||||
* @param text
|
||||
|
@ -530,11 +494,11 @@ WalletService.prototype.addAccess = function(opts, cb) {
|
|||
id: opts.copayerId
|
||||
}).xPubKey;
|
||||
|
||||
if (!WalletUtils.verifyRequestPubKey(opts.requestPubKey, opts.signature, xPubKey)) {
|
||||
if (!self._verifyRequestPubKey(opts.requestPubKey, opts.signature, xPubKey)) {
|
||||
return cb(Errors.NOT_AUTHORIZED);
|
||||
}
|
||||
|
||||
if (copayer.requestPubKeys.length > WalletService.MAX_KEYS)
|
||||
if (copayer.requestPubKeys.length > Constants.MAX_KEYS)
|
||||
return cb(Errors.TOO_MANY_KEYS);
|
||||
|
||||
self._addKeyToCopayer(wallet, copayer, opts, cb);
|
||||
|
@ -576,6 +540,10 @@ WalletService.prototype._clientSupportsTXPv2 = function() {
|
|||
return true;
|
||||
};
|
||||
|
||||
WalletService._getCopayerHash = function(name, xPubKey, requestPubKey) {
|
||||
return [name, xPubKey, requestPubKey].join('|');
|
||||
};
|
||||
|
||||
/**
|
||||
* Joins a wallet in creation.
|
||||
* @param {Object} opts
|
||||
|
@ -606,17 +574,17 @@ WalletService.prototype.joinWallet = function(opts, cb) {
|
|||
|
||||
if (opts.supportBIP44AndP2PKH) {
|
||||
// New client trying to join legacy wallet
|
||||
if (wallet.derivationStrategy == WalletService.DERIVATION_STRATEGIES.BIP45) {
|
||||
if (wallet.derivationStrategy == Constants.DERIVATION_STRATEGIES.BIP45) {
|
||||
return cb(new ClientError('The wallet you are trying to join was created with an older version of the client app.'));
|
||||
}
|
||||
} else {
|
||||
// Legacy client trying to join new wallet
|
||||
if (wallet.derivationStrategy == WalletService.DERIVATION_STRATEGIES.BIP44) {
|
||||
if (wallet.derivationStrategy == Constants.DERIVATION_STRATEGIES.BIP44) {
|
||||
return cb(new ClientError(Errors.codes.UPGRADE_NEEDED, 'To join this wallet you need to upgrade your client app.'));
|
||||
}
|
||||
}
|
||||
|
||||
var hash = WalletUtils.getCopayerHash(opts.name, opts.xPubKey, opts.requestPubKey);
|
||||
var hash = WalletService._getCopayerHash(opts.name, opts.xPubKey, opts.requestPubKey);
|
||||
if (!self._verifySignature(hash, opts.copayerSignature, wallet.pubKey)) {
|
||||
return cb(new ClientError());
|
||||
}
|
||||
|
@ -714,8 +682,8 @@ WalletService.prototype._canCreateAddress = function(ignoreMaxGap, cb) {
|
|||
if (err) return cb(err);
|
||||
var latestAddresses = _.takeRight(_.reject(addresses, {
|
||||
isChange: true
|
||||
}), WalletService.MAX_MAIN_ADDRESS_GAP);
|
||||
if (latestAddresses.length < WalletService.MAX_MAIN_ADDRESS_GAP || _.any(latestAddresses, {
|
||||
}), Constants.MAX_MAIN_ADDRESS_GAP);
|
||||
if (latestAddresses.length < Constants.MAX_MAIN_ADDRESS_GAP || _.any(latestAddresses, {
|
||||
hasActivity: true
|
||||
})) return cb(null, true);
|
||||
|
||||
|
@ -1034,7 +1002,7 @@ WalletService.prototype.getFeeLevels = function(opts, cb) {
|
|||
if (network != 'livenet' && network != 'testnet')
|
||||
return cb(new ClientError('Invalid network'));
|
||||
|
||||
var levels = WalletService.FEE_LEVELS;
|
||||
var levels = Constants.FEE_LEVELS;
|
||||
var samplePoints = _.uniq(_.pluck(levels, 'nbBlocks'));
|
||||
self._sampleFeeLevels(network, samplePoints, function(err, feeSamples) {
|
||||
var values = _.map(levels, function(level) {
|
||||
|
@ -1157,7 +1125,7 @@ WalletService.prototype._selectTxInputs = function(txp, utxosToExclude, cb) {
|
|||
|
||||
WalletService.prototype._canCreateTx = function(copayerId, cb) {
|
||||
var self = this;
|
||||
self.storage.fetchLastTxs(self.walletId, copayerId, 5 + WalletService.BACKOFF_OFFSET, function(err, txs) {
|
||||
self.storage.fetchLastTxs(self.walletId, copayerId, 5 + Constants.BACKOFF_OFFSET, function(err, txs) {
|
||||
if (err) return cb(err);
|
||||
|
||||
if (!txs.length)
|
||||
|
@ -1167,7 +1135,7 @@ WalletService.prototype._canCreateTx = function(copayerId, cb) {
|
|||
status: 'rejected'
|
||||
});
|
||||
|
||||
var exceededRejections = lastRejections.length - WalletService.BACKOFF_OFFSET;
|
||||
var exceededRejections = lastRejections.length - Constants.BACKOFF_OFFSET;
|
||||
if (exceededRejections <= 0)
|
||||
return cb(null, true);
|
||||
|
||||
|
@ -1175,7 +1143,7 @@ WalletService.prototype._canCreateTx = function(copayerId, cb) {
|
|||
var lastTxTs = txs[0].createdOn;
|
||||
var now = Math.floor(Date.now() / 1000);
|
||||
var timeSinceLastRejection = now - lastTxTs;
|
||||
var backoffTime = 60 * Math.pow(WalletService.BACKOFF_TIME, exceededRejections);
|
||||
var backoffTime = 60 * Math.pow(Constants.BACKOFF_TIME, exceededRejections);
|
||||
|
||||
if (timeSinceLastRejection <= backoffTime)
|
||||
log.debug('Not allowing to create TX: timeSinceLastRejection/backoffTime', timeSinceLastRejection, backoffTime);
|
||||
|
@ -1185,6 +1153,19 @@ WalletService.prototype._canCreateTx = function(copayerId, cb) {
|
|||
};
|
||||
|
||||
|
||||
WalletService._getProposalHash = function(proposalHeader) {
|
||||
function getOldHash(toAddress, amount, message, payProUrl) {
|
||||
return [toAddress, amount, (message || ''), (payProUrl || '')].join('|');
|
||||
};
|
||||
|
||||
// For backwards compatibility
|
||||
if (arguments.length > 1) {
|
||||
return getOldHash.apply(this, arguments);
|
||||
}
|
||||
|
||||
return Stringify(proposalHeader);
|
||||
};
|
||||
|
||||
/**
|
||||
* Creates a new transaction proposal.
|
||||
* @param {Object} opts
|
||||
|
@ -1225,8 +1206,8 @@ WalletService.prototype.createTx = function(opts, cb) {
|
|||
valid: false
|
||||
})) return;
|
||||
|
||||
var feePerKb = opts.feePerKb || WalletService.DEFAULT_FEE_PER_KB;
|
||||
if (feePerKb < WalletService.MIN_FEE_PER_KB || feePerKb > WalletService.MAX_FEE_PER_KB)
|
||||
var feePerKb = opts.feePerKb || Constants.DEFAULT_FEE_PER_KB;
|
||||
if (feePerKb < Constants.MIN_FEE_PER_KB || feePerKb > Constants.MAX_FEE_PER_KB)
|
||||
return cb(new ClientError('Invalid fee per KB value'));
|
||||
|
||||
self._runLocked(cb, function(cb) {
|
||||
|
@ -1237,7 +1218,7 @@ WalletService.prototype.createTx = function(opts, cb) {
|
|||
var copayer = wallet.getCopayer(self.copayerId);
|
||||
var hash;
|
||||
if (!opts.type || opts.type == Model.TxProposal.Types.SIMPLE) {
|
||||
hash = WalletUtils.getProposalHash(opts.toAddress, opts.amount, opts.message, opts.payProUrl);
|
||||
hash = WalletService._getProposalHash(opts.toAddress, opts.amount, opts.message, opts.payProUrl);
|
||||
} else {
|
||||
// should match bwc api _computeProposalSignature
|
||||
var header = {
|
||||
|
@ -1247,7 +1228,7 @@ WalletService.prototype.createTx = function(opts, cb) {
|
|||
message: opts.message,
|
||||
payProUrl: opts.payProUrl
|
||||
};
|
||||
hash = WalletUtils.getProposalHash(header)
|
||||
hash = WalletService._getProposalHash(header)
|
||||
}
|
||||
|
||||
var signingKey = self._getSigningKey(hash, opts.proposalSignature, copayer.requestPubKeys)
|
||||
|
@ -1376,7 +1357,7 @@ WalletService.prototype.removeWallet = function(opts, cb) {
|
|||
WalletService.prototype.getRemainingDeleteLockTime = function(txp) {
|
||||
var now = Math.floor(Date.now() / 1000);
|
||||
|
||||
var lockTimeRemaining = txp.createdOn + WalletService.DELETE_LOCKTIME - now;
|
||||
var lockTimeRemaining = txp.createdOn + Constants.DELETE_LOCKTIME - now;
|
||||
if (lockTimeRemaining < 0)
|
||||
return 0;
|
||||
|
||||
|
@ -1956,7 +1937,7 @@ WalletService.prototype.scan = function(opts, cb) {
|
|||
function scanBranch(derivator, cb) {
|
||||
var inactiveCounter = 0;
|
||||
var allAddresses = [];
|
||||
var gap = WalletService.SCAN_CONFIG.maxGap;
|
||||
var gap = Constants.SCAN_CONFIG.maxGap;
|
||||
|
||||
async.whilst(function() {
|
||||
return inactiveCounter < gap;
|
||||
|
|
152
lib/utils.js
152
lib/utils.js
|
@ -1,6 +1,13 @@
|
|||
var $ = require('preconditions').singleton();
|
||||
var _ = require('lodash');
|
||||
|
||||
var Bitcore = require('bitcore-lib');
|
||||
var Address = Bitcore.Address;
|
||||
var crypto = Bitcore.crypto;
|
||||
var encoding = Bitcore.encoding;
|
||||
|
||||
var Constants = require('./constants');
|
||||
|
||||
var Utils = {};
|
||||
|
||||
Utils.checkRequired = function(obj, args) {
|
||||
|
@ -22,7 +29,6 @@ Utils.strip = function(number) {
|
|||
return (parseFloat(number.toPrecision(12)));
|
||||
}
|
||||
|
||||
|
||||
/* TODO: It would be nice to be compatible with bitcoind signmessage. How
|
||||
* the hash is calculated there? */
|
||||
Utils.hashMessage = function(text) {
|
||||
|
@ -33,15 +39,6 @@ Utils.hashMessage = function(text) {
|
|||
return ret;
|
||||
};
|
||||
|
||||
|
||||
Utils.signMessage = function(text, privKey) {
|
||||
$.checkArgument(text);
|
||||
var priv = new PrivateKey(privKey);
|
||||
var hash = Utils.hashMessage(text);
|
||||
return crypto.ECDSA.sign(hash, priv, 'little').toString();
|
||||
};
|
||||
|
||||
|
||||
Utils.verifyMessage = function(text, signature, pubKey) {
|
||||
$.checkArgument(text);
|
||||
$.checkArgument(pubKey);
|
||||
|
@ -49,7 +46,7 @@ Utils.verifyMessage = function(text, signature, pubKey) {
|
|||
if (!signature)
|
||||
return false;
|
||||
|
||||
var pub = new PublicKey(pubKey);
|
||||
var pub = new Bitcore.PublicKey(pubKey);
|
||||
var hash = Utils.hashMessage(text);
|
||||
|
||||
try {
|
||||
|
@ -60,5 +57,138 @@ Utils.verifyMessage = function(text, signature, pubKey) {
|
|||
}
|
||||
};
|
||||
|
||||
Utils.newBitcoreTransaction = function() {
|
||||
return new Bitcore.Transaction();
|
||||
};
|
||||
|
||||
Utils.buildTx = function(txp) {
|
||||
var t = Utils.newBitcoreTransaction();
|
||||
|
||||
$.checkState(_.contains(_.values(Constants.SCRIPT_TYPES), txp.addressType));
|
||||
|
||||
switch (txp.addressType) {
|
||||
case Constants.SCRIPT_TYPES.P2SH:
|
||||
_.each(txp.inputs, function(i) {
|
||||
t.from(i, i.publicKeys, txp.requiredSignatures);
|
||||
});
|
||||
break;
|
||||
case Constants.SCRIPT_TYPES.P2PKH:
|
||||
t.from(txp.inputs);
|
||||
break;
|
||||
}
|
||||
|
||||
if (txp.toAddress && txp.amount && !txp.outputs) {
|
||||
t.to(txp.toAddress, txp.amount);
|
||||
} else if (txp.outputs) {
|
||||
_.each(txp.outputs, function(o) {
|
||||
$.checkState(!o.script != !o.toAddress, 'Output should have either toAddress or script specified');
|
||||
if (o.script) {
|
||||
t.addOutput(new Bitcore.Transaction.Output({
|
||||
script: o.script,
|
||||
satoshis: o.amount
|
||||
}));
|
||||
} else {
|
||||
t.to(o.toAddress, o.amount);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if (_.startsWith(txp.version, '1.')) {
|
||||
Bitcore.Transaction.FEE_SECURITY_MARGIN = 1;
|
||||
t.feePerKb(txp.feePerKb);
|
||||
} else {
|
||||
t.fee(txp.fee);
|
||||
}
|
||||
|
||||
t.change(txp.changeAddress.address);
|
||||
|
||||
// Shuffle outputs for improved privacy
|
||||
if (t.outputs.length > 1) {
|
||||
$.checkState(t.outputs.length == txp.outputOrder.length);
|
||||
t.sortOutputs(function(outputs) {
|
||||
return _.map(txp.outputOrder, function(i) {
|
||||
return outputs[i];
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// Validate inputs vs outputs independently of Bitcore
|
||||
var totalInputs = _.reduce(txp.inputs, function(memo, i) {
|
||||
return +i.satoshis + memo;
|
||||
}, 0);
|
||||
var totalOutputs = _.reduce(t.outputs, function(memo, o) {
|
||||
return +o.satoshis + memo;
|
||||
}, 0);
|
||||
|
||||
$.checkState(totalInputs - totalOutputs <= Constants.MAX_TX_FEE);
|
||||
|
||||
return t;
|
||||
};
|
||||
|
||||
Utils.deriveAddress = function(scriptType, publicKeyRing, path, m, network) {
|
||||
$.checkArgument(_.contains(_.values(Constants.SCRIPT_TYPES), scriptType));
|
||||
|
||||
var publicKeys = _.map(publicKeyRing, function(item) {
|
||||
var xpub = new Bitcore.HDPublicKey(item.xPubKey);
|
||||
return xpub.derive(path).publicKey;
|
||||
});
|
||||
|
||||
var bitcoreAddress;
|
||||
switch (scriptType) {
|
||||
case Constants.SCRIPT_TYPES.P2SH:
|
||||
bitcoreAddress = Address.createMultisig(publicKeys, m, network);
|
||||
break;
|
||||
case Constants.SCRIPT_TYPES.P2PKH:
|
||||
$.checkState(_.isArray(publicKeys) && publicKeys.length == 1);
|
||||
bitcoreAddress = Address.fromPublicKey(publicKeys[0], network);
|
||||
break;
|
||||
}
|
||||
|
||||
return {
|
||||
address: bitcoreAddress.toString(),
|
||||
path: path,
|
||||
publicKeys: _.invoke(publicKeys, 'toString'),
|
||||
};
|
||||
};
|
||||
|
||||
Utils.formatAmount = function(satoshis, unit, opts) {
|
||||
var UNITS = {
|
||||
btc: {
|
||||
toSatoshis: 100000000,
|
||||
maxDecimals: 6,
|
||||
minDecimals: 2,
|
||||
},
|
||||
bit: {
|
||||
toSatoshis: 100,
|
||||
maxDecimals: 0,
|
||||
minDecimals: 0,
|
||||
},
|
||||
};
|
||||
|
||||
$.shouldBeNumber(satoshis);
|
||||
$.checkArgument(_.contains(_.keys(UNITS), unit));
|
||||
|
||||
function addSeparators(nStr, thousands, decimal, minDecimals) {
|
||||
nStr = nStr.replace('.', decimal);
|
||||
var x = nStr.split(decimal);
|
||||
var x0 = x[0];
|
||||
var x1 = x[1];
|
||||
|
||||
x1 = _.dropRightWhile(x1, function(n, i) {
|
||||
return n == '0' && i >= minDecimals;
|
||||
}).join('');
|
||||
var x2 = x.length > 1 ? decimal + x1 : '';
|
||||
|
||||
x0 = x0.replace(/\B(?=(\d{3})+(?!\d))/g, thousands);
|
||||
return x0 + x2;
|
||||
}
|
||||
|
||||
opts = opts || {};
|
||||
|
||||
var u = UNITS[unit];
|
||||
var amount = (satoshis / u.toSatoshis).toFixed(u.maxDecimals);
|
||||
return addSeparators(amount, opts.thousandsSeparator || ',', opts.decimalSeparator || '.', u.minDecimals);
|
||||
};
|
||||
|
||||
|
||||
module.exports = Utils;
|
||||
|
|
26
package.json
26
package.json
|
@ -20,12 +20,12 @@
|
|||
"dependencies": {
|
||||
"async": "^0.9.0",
|
||||
"bitcore-lib": "^0.13.7",
|
||||
"bitcore-wallet-utils": "~1.0.0",
|
||||
"body-parser": "^1.11.0",
|
||||
"coveralls": "^2.11.2",
|
||||
"email-validator": "^1.0.1",
|
||||
"express": "^4.10.0",
|
||||
"inherits": "^2.0.1",
|
||||
"json-stable-stringify": "^1.0.0",
|
||||
"locker": "^0.1.0",
|
||||
"locker-server": "^0.1.3",
|
||||
"lodash": "^3.10.1",
|
||||
|
@ -64,14 +64,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"
|
||||
},
|
||||
"bitcoreNode": "./bitcorenode",
|
||||
"contributors": [{
|
||||
"name": "Braydon Fuller",
|
||||
"email": "braydon@bitpay.com"
|
||||
}, {
|
||||
"name": "Ivan Socolsky",
|
||||
"email": "ivan@bitpay.com"
|
||||
}, {
|
||||
"name": "Matias Alejo Garcia",
|
||||
"email": "ematiu@gmail.com"
|
||||
}]
|
||||
"contributors": [
|
||||
{
|
||||
"name": "Braydon Fuller",
|
||||
"email": "braydon@bitpay.com"
|
||||
},
|
||||
{
|
||||
"name": "Ivan Socolsky",
|
||||
"email": "ivan@bitpay.com"
|
||||
},
|
||||
{
|
||||
"name": "Matias Alejo Garcia",
|
||||
"email": "ematiu@gmail.com"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
|
@ -15,9 +15,10 @@ var tingodb = require('tingodb')({
|
|||
memStore: true
|
||||
});
|
||||
|
||||
var Bitcore = require('bitcore-lib');
|
||||
|
||||
var Constants = require('../../lib/constants');
|
||||
var Utils = require('../../lib/utils');
|
||||
var WalletUtils = require('bitcore-wallet-utils');
|
||||
var Bitcore = WalletUtils.Bitcore;
|
||||
var Storage = require('../../lib/storage');
|
||||
|
||||
var Model = require('../../lib/model');
|
||||
|
@ -29,6 +30,18 @@ var TestData = require('../testdata');
|
|||
var CLIENT_VERSION = 'bwc-0.1.1';
|
||||
|
||||
var helpers = {};
|
||||
|
||||
helpers.signMessage = function(text, privKey) {
|
||||
var priv = new Bitcore.PrivateKey(privKey);
|
||||
var hash = Utils.hashMessage(text);
|
||||
return Bitcore.crypto.ECDSA.sign(hash, priv, 'little').toString();
|
||||
};
|
||||
|
||||
helpers.signRequestPubKey = function(requestPubKey, xPrivKey) {
|
||||
var priv = new Bitcore.HDPrivateKey(xPrivKey).derive(Constants.PATHS.REQUEST_KEY_AUTH).privateKey;
|
||||
return helpers.signMessage(requestPubKey, priv);
|
||||
};
|
||||
|
||||
helpers.getAuthServer = function(copayerId, cb) {
|
||||
var verifyStub = sinon.stub(WalletService.prototype, '_verifySignature');
|
||||
verifyStub.returns(true);
|
||||
|
@ -52,11 +65,11 @@ helpers._generateCopayersTestData = function(n) {
|
|||
|
||||
var xpriv_45H = xpriv.derive(45, true);
|
||||
var xpub_45H = Bitcore.HDPublicKey(xpriv_45H);
|
||||
var id45 = WalletUtils.xPubToCopayerId(xpub_45H.toString());
|
||||
var id45 = Copayer._xPubToCopayerId(xpub_45H.toString());
|
||||
|
||||
var xpriv_44H_0H_0H = xpriv.derive(44, true).derive(0, true).derive(0, true);
|
||||
var xpub_44H_0H_0H = Bitcore.HDPublicKey(xpriv_44H_0H_0H);
|
||||
var id44 = WalletUtils.xPubToCopayerId(xpub_44H_0H_0H.toString());
|
||||
var id44 = Copayer._xPubToCopayerId(xpub_44H_0H_0H.toString());
|
||||
|
||||
var xpriv_1H = xpriv.derive(1, true);
|
||||
var xpub_1H = Bitcore.HDPublicKey(xpriv_1H);
|
||||
|
@ -80,8 +93,8 @@ helpers._generateCopayersTestData = function(n) {
|
|||
};
|
||||
|
||||
helpers.getSignedCopayerOpts = function(opts) {
|
||||
var hash = WalletUtils.getCopayerHash(opts.name, opts.xPubKey, opts.requestPubKey);
|
||||
opts.copayerSignature = WalletUtils.signMessage(hash, TestData.keyPair.priv);
|
||||
var hash = WalletService._getCopayerHash(opts.name, opts.xPubKey, opts.requestPubKey);
|
||||
opts.copayerSignature = helpers.signMessage(hash, TestData.keyPair.priv);
|
||||
return opts;
|
||||
};
|
||||
|
||||
|
@ -141,7 +154,6 @@ helpers.randomTXID = function() {
|
|||
return Bitcore.crypto.Hash.sha256(new Buffer(Math.random() * 100000)).toString('hex');;
|
||||
};
|
||||
|
||||
|
||||
helpers.toSatoshi = function(btc) {
|
||||
if (_.isArray(btc)) {
|
||||
return _.map(btc, helpers.toSatoshi);
|
||||
|
@ -168,10 +180,10 @@ helpers.stubUtxos = function(server, wallet, amounts, cb) {
|
|||
|
||||
var scriptPubKey;
|
||||
switch (wallet.addressType) {
|
||||
case WalletUtils.SCRIPT_TYPES.P2SH:
|
||||
case Constants.SCRIPT_TYPES.P2SH:
|
||||
scriptPubKey = Bitcore.Script.buildMultisigOut(address.publicKeys, wallet.m).toScriptHashOut();
|
||||
break;
|
||||
case WalletUtils.SCRIPT_TYPES.P2PKH:
|
||||
case Constants.SCRIPT_TYPES.P2PKH:
|
||||
scriptPubKey = Bitcore.Script.buildPublicKeyHashOut(address.address);
|
||||
break;
|
||||
}
|
||||
|
@ -242,7 +254,46 @@ helpers.stubAddressActivity = function(activeAddresses) {
|
|||
};
|
||||
};
|
||||
|
||||
helpers.clientSign = WalletUtils.signTxp;
|
||||
helpers.clientSign = function(txp, xPrivKey) {
|
||||
var self = this;
|
||||
|
||||
function getBaseAddressDerivationPath(derivationStrategy, network, account) {
|
||||
if (derivationStrategy == Constants.DERIVATION_STRATEGIES.BIP45) return "m/45'";
|
||||
return "m/44'/" + (network == 'livenet' ? "0'" : "1'") + "/" + account + "'";
|
||||
};
|
||||
|
||||
function deriveXPrivFromMaster(masterXPriv, derivationStrategy, network, account) {
|
||||
var path = getBaseAddressDerivationPath(derivationStrategy, network, account || 0);
|
||||
return new Bitcore.HDPrivateKey(masterXPriv, network).derive(path);
|
||||
};
|
||||
|
||||
//Derive proper key to sign, for each input
|
||||
var privs = [];
|
||||
var derived = {};
|
||||
|
||||
var network = new Bitcore.Address(txp.changeAddress.address).network.name;
|
||||
var xpriv = deriveXPrivFromMaster(xPrivKey, txp.derivationStrategy, network);
|
||||
|
||||
_.each(txp.inputs, function(i) {
|
||||
if (!derived[i.path]) {
|
||||
derived[i.path] = xpriv.derive(i.path).privateKey;
|
||||
privs.push(derived[i.path]);
|
||||
}
|
||||
});
|
||||
|
||||
var t = Utils.buildTx(txp);
|
||||
|
||||
var signatures = _.map(privs, function(priv, i) {
|
||||
return t.getSignatures(priv);
|
||||
});
|
||||
|
||||
signatures = _.map(_.sortBy(_.flatten(signatures), 'inputIndex'), function(s) {
|
||||
return s.signature.toDER().toString('hex');
|
||||
});
|
||||
|
||||
return signatures;
|
||||
};
|
||||
|
||||
|
||||
helpers.createProposalOptsLegacy = function(toAddress, amount, message, signingKey, feePerKb) {
|
||||
var opts = {
|
||||
|
@ -253,10 +304,10 @@ helpers.createProposalOptsLegacy = function(toAddress, amount, message, signingK
|
|||
};
|
||||
if (feePerKb) opts.feePerKb = feePerKb;
|
||||
|
||||
var hash = WalletUtils.getProposalHash(toAddress, opts.amount, message);
|
||||
var hash = WalletService._getProposalHash(toAddress, opts.amount, message);
|
||||
|
||||
try {
|
||||
opts.proposalSignature = WalletUtils.signMessage(hash, signingKey);
|
||||
opts.proposalSignature = helpers.signMessage(hash, signingKey);
|
||||
} catch (ex) {}
|
||||
|
||||
return opts;
|
||||
|
@ -295,7 +346,7 @@ helpers.createProposalOpts = function(type, outputs, signingKey, moreOpts) {
|
|||
if (type == Model.TxProposal.Types.SIMPLE) {
|
||||
opts.toAddress = outputs[0].toAddress;
|
||||
opts.amount = outputs[0].amount;
|
||||
hash = WalletUtils.getProposalHash(opts.toAddress, opts.amount,
|
||||
hash = WalletService._getProposalHash(opts.toAddress, opts.amount,
|
||||
opts.message, opts.payProUrl);
|
||||
} else if (type == Model.TxProposal.Types.MULTIPLEOUTPUTS) {
|
||||
opts.outputs = outputs;
|
||||
|
@ -304,11 +355,11 @@ helpers.createProposalOpts = function(type, outputs, signingKey, moreOpts) {
|
|||
message: opts.message,
|
||||
payProUrl: opts.payProUrl
|
||||
};
|
||||
hash = WalletUtils.getProposalHash(header);
|
||||
hash = WalletService._getProposalHash(header);
|
||||
}
|
||||
|
||||
try {
|
||||
opts.proposalSignature = WalletUtils.signMessage(hash, signingKey);
|
||||
opts.proposalSignature = helpers.signMessage(hash, signingKey);
|
||||
} catch (ex) {}
|
||||
|
||||
return opts;
|
||||
|
@ -836,7 +887,7 @@ describe('Wallet service', function() {
|
|||
var xpriv = TestData.copayers[0].xPrivKey;
|
||||
var priv = TestData.copayers[0].privKey_1H_0;
|
||||
|
||||
var sig = WalletUtils.signMessage('hello world', priv);
|
||||
var sig = helpers.signMessage('hello world', priv);
|
||||
|
||||
WalletService.getInstanceWithAuth({
|
||||
copayerId: wallet.copayers[0].id,
|
||||
|
@ -858,7 +909,7 @@ describe('Wallet service', function() {
|
|||
var opts = {
|
||||
copayerId: 'dummy',
|
||||
message: message,
|
||||
signature: WalletUtils.signMessage(message, TestData.copayers[0].privKey_1H_0),
|
||||
signature: helpers.signMessage(message, TestData.copayers[0].privKey_1H_0),
|
||||
};
|
||||
WalletService.getInstanceWithAuth(opts, function(err, server) {
|
||||
err.code.should.equal('NOT_AUTHORIZED');
|
||||
|
@ -1512,7 +1563,7 @@ describe('Wallet service', function() {
|
|||
var message = 'hello world';
|
||||
var opts = {
|
||||
message: message,
|
||||
signature: WalletUtils.signMessage(message, TestData.copayers[0].privKey_1H_0),
|
||||
signature: helpers.signMessage(message, TestData.copayers[0].privKey_1H_0),
|
||||
};
|
||||
server.verifyMessageSignature(opts, function(err, isValid) {
|
||||
should.not.exist(err);
|
||||
|
@ -1525,7 +1576,7 @@ describe('Wallet service', function() {
|
|||
var message = 'hello world';
|
||||
var opts = {
|
||||
message: message,
|
||||
signature: WalletUtils.signMessage(message, TestData.copayers[0].privKey_1H_0),
|
||||
signature: helpers.signMessage(message, TestData.copayers[0].privKey_1H_0),
|
||||
};
|
||||
helpers.getAuthServer(wallet.copayers[1].id, function(server) {
|
||||
server.verifyMessageSignature(opts, function(err, isValid) {
|
||||
|
@ -1719,8 +1770,8 @@ describe('Wallet service', function() {
|
|||
});
|
||||
|
||||
it('should fail to create more consecutive addresses with no activity than allowed', function(done) {
|
||||
var MAX_MAIN_ADDRESS_GAP_old = WalletService.MAX_MAIN_ADDRESS_GAP;
|
||||
WalletService.MAX_MAIN_ADDRESS_GAP = 2;
|
||||
var MAX_MAIN_ADDRESS_GAP_old = Constants.MAX_MAIN_ADDRESS_GAP;
|
||||
Constants.MAX_MAIN_ADDRESS_GAP = 2;
|
||||
helpers.stubAddressActivity([]);
|
||||
async.map(_.range(2), function(i, next) {
|
||||
server.createAddress({}, next);
|
||||
|
@ -1746,7 +1797,7 @@ describe('Wallet service', function() {
|
|||
should.exist(address);
|
||||
address.path.should.equal('m/0/3');
|
||||
|
||||
WalletService.MAX_MAIN_ADDRESS_GAP = MAX_MAIN_ADDRESS_GAP_old;
|
||||
Constants.MAX_MAIN_ADDRESS_GAP = MAX_MAIN_ADDRESS_GAP_old;
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
@ -1755,8 +1806,8 @@ describe('Wallet service', function() {
|
|||
});
|
||||
|
||||
it('should cache address activity', function(done) {
|
||||
var MAX_MAIN_ADDRESS_GAP_old = WalletService.MAX_MAIN_ADDRESS_GAP;
|
||||
WalletService.MAX_MAIN_ADDRESS_GAP = 2;
|
||||
var MAX_MAIN_ADDRESS_GAP_old = Constants.MAX_MAIN_ADDRESS_GAP;
|
||||
Constants.MAX_MAIN_ADDRESS_GAP = 2;
|
||||
helpers.stubAddressActivity([]);
|
||||
async.map(_.range(2), function(i, next) {
|
||||
server.createAddress({}, next);
|
||||
|
@ -1770,7 +1821,7 @@ describe('Wallet service', function() {
|
|||
server.createAddress({}, function(err, address) {
|
||||
should.not.exist(err);
|
||||
getAddressActivitySpy.callCount.should.equal(1);
|
||||
WalletService.MAX_MAIN_ADDRESS_GAP = MAX_MAIN_ADDRESS_GAP_old;
|
||||
Constants.MAX_MAIN_ADDRESS_GAP = MAX_MAIN_ADDRESS_GAP_old;
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
@ -2014,7 +2065,7 @@ describe('Wallet service', function() {
|
|||
var opts, reqPrivKey, ws;
|
||||
var getAuthServer = function(copayerId, privKey, cb) {
|
||||
var msg = 'dummy';
|
||||
var sig = WalletUtils.signMessage(msg, privKey);
|
||||
var sig = helpers.signMessage(msg, privKey);
|
||||
WalletService.getInstanceWithAuth({
|
||||
copayerId: copayerId,
|
||||
message: msg,
|
||||
|
@ -2030,9 +2081,9 @@ describe('Wallet service', function() {
|
|||
var requestPubKey = reqPrivKey.toPublicKey();
|
||||
|
||||
var xPrivKey = TestData.copayers[0].xPrivKey_44H_0H_0H;
|
||||
var sig = WalletUtils.signRequestPubKey(requestPubKey, xPrivKey);
|
||||
var sig = helpers.signRequestPubKey(requestPubKey, xPrivKey);
|
||||
|
||||
var copayerId = WalletUtils.xPubToCopayerId(TestData.copayers[0].xPubKey_44H_0H_0H);
|
||||
var copayerId = Model.Copayer._xPubToCopayerId(TestData.copayers[0].xPubKey_44H_0H_0H);
|
||||
opts = {
|
||||
copayerId: copayerId,
|
||||
requestPubKey: requestPubKey,
|
||||
|
@ -2424,7 +2475,7 @@ describe('Wallet service', function() {
|
|||
tx.isAccepted().should.equal.false;
|
||||
tx.isRejected().should.equal.false;
|
||||
tx.amount.should.equal(helpers.toSatoshi(80));
|
||||
var estimatedFee = WalletUtils.DEFAULT_FEE_PER_KB * 400 / 1000; // fully signed tx should have about 400 bytes
|
||||
var estimatedFee = Constants.DEFAULT_FEE_PER_KB * 400 / 1000; // fully signed tx should have about 400 bytes
|
||||
tx.fee.should.be.within(0.9 * estimatedFee, 1.1 * estimatedFee);
|
||||
server.getPendingTxs({}, function(err, txs) {
|
||||
should.not.exist(err);
|
||||
|
@ -2679,7 +2730,7 @@ describe('Wallet service', function() {
|
|||
var txOpts = helpers.createSimpleProposalOpts('18PzpUFkFZE8zKWUPvfykkTxmB9oMR8qP7', 3.5, TestData.copayers[0].privKey_1H_0);
|
||||
server.createTx(txOpts, function(err, tx) {
|
||||
should.not.exist(err);
|
||||
var estimatedFee = WalletUtils.DEFAULT_FEE_PER_KB * 1300 / 1000; // fully signed tx should have about 1300 bytes
|
||||
var estimatedFee = Constants.DEFAULT_FEE_PER_KB * 1300 / 1000; // fully signed tx should have about 1300 bytes
|
||||
tx.fee.should.be.within(0.9 * estimatedFee, 1.1 * estimatedFee);
|
||||
done();
|
||||
});
|
||||
|
@ -3075,7 +3126,7 @@ describe('Wallet service', function() {
|
|||
});
|
||||
},
|
||||
function(next) {
|
||||
var clock = sinon.useFakeTimers(Date.now() + (WalletService.BACKOFF_TIME + 2) * 60 * 1000, 'Date');
|
||||
var clock = sinon.useFakeTimers(Date.now() + (Constants.BACKOFF_TIME + 2) * 60 * 1000, 'Date');
|
||||
var txOpts = helpers.createSimpleProposalOpts('18PzpUFkFZE8zKWUPvfykkTxmB9oMR8qP7', 1, TestData.copayers[0].privKey_1H_0);
|
||||
server.createTx(txOpts, function(err, tx) {
|
||||
clock.restore();
|
||||
|
@ -3087,7 +3138,7 @@ describe('Wallet service', function() {
|
|||
},
|
||||
function(next) {
|
||||
// Do not allow a 5th tx before backoff time
|
||||
var clock = sinon.useFakeTimers(Date.now() + (WalletService.BACKOFF_TIME + 2) * 60 * 1000 + 1, 'Date');
|
||||
var clock = sinon.useFakeTimers(Date.now() + (Constants.BACKOFF_TIME + 2) * 60 * 1000 + 1, 'Date');
|
||||
var txOpts = helpers.createSimpleProposalOpts('18PzpUFkFZE8zKWUPvfykkTxmB9oMR8qP7', 1, TestData.copayers[0].privKey_1H_0);
|
||||
server.createTx(txOpts, function(err, tx) {
|
||||
clock.restore();
|
||||
|
@ -4547,7 +4598,7 @@ describe('Wallet service', function() {
|
|||
|
||||
server.getPendingTxs({}, function(err, txs) {
|
||||
should.not.exist(err);
|
||||
txs[0].deleteLockTime.should.be.above(WalletService.DELETE_LOCKTIME - 10);
|
||||
txs[0].deleteLockTime.should.be.above(Constants.DELETE_LOCKTIME - 10);
|
||||
|
||||
var clock = sinon.useFakeTimers(Date.now() + 1 + 24 * 3600 * 1000, 'Date');
|
||||
server.removePendingTx({
|
||||
|
@ -4572,7 +4623,7 @@ describe('Wallet service', function() {
|
|||
}, function(err) {
|
||||
should.not.exist(err);
|
||||
|
||||
var clock = sinon.useFakeTimers(Date.now() + 2000 + WalletService.DELETE_LOCKTIME * 1000, 'Date');
|
||||
var clock = sinon.useFakeTimers(Date.now() + 2000 + Constants.DELETE_LOCKTIME * 1000, 'Date');
|
||||
server2.removePendingTx({
|
||||
txProposalId: txp.id
|
||||
}, function(err) {
|
||||
|
@ -4897,12 +4948,12 @@ describe('Wallet service', function() {
|
|||
|
||||
describe('#scan', function() {
|
||||
var server, wallet;
|
||||
var scanConfigOld = WalletService.SCAN_CONFIG;
|
||||
var scanConfigOld = Constants.SCAN_CONFIG;
|
||||
|
||||
describe('1-of-1 wallet (BIP44 & P2PKH)', function() {
|
||||
beforeEach(function(done) {
|
||||
this.timeout(5000);
|
||||
WalletService.SCAN_CONFIG.maxGap = 2;
|
||||
Constants.SCAN_CONFIG.maxGap = 2;
|
||||
|
||||
helpers.createAndJoinWallet(1, 1, function(s, w) {
|
||||
server = s;
|
||||
|
@ -4911,7 +4962,7 @@ describe('Wallet service', function() {
|
|||
});
|
||||
});
|
||||
afterEach(function() {
|
||||
WalletService.SCAN_CONFIG = scanConfigOld;
|
||||
Constants.SCAN_CONFIG = scanConfigOld;
|
||||
});
|
||||
|
||||
it('should scan main addresses', function(done) {
|
||||
|
@ -5094,7 +5145,7 @@ describe('Wallet service', function() {
|
|||
|
||||
beforeEach(function(done) {
|
||||
this.timeout(5000);
|
||||
WalletService.SCAN_CONFIG.maxGap = 2;
|
||||
Constants.SCAN_CONFIG.maxGap = 2;
|
||||
|
||||
helpers.createAndJoinWallet(1, 2, {
|
||||
supportBIP44AndP2PKH: false
|
||||
|
@ -5105,7 +5156,7 @@ describe('Wallet service', function() {
|
|||
});
|
||||
});
|
||||
afterEach(function() {
|
||||
WalletService.SCAN_CONFIG = scanConfigOld;
|
||||
Constants.SCAN_CONFIG = scanConfigOld;
|
||||
});
|
||||
|
||||
it('should scan main addresses', function(done) {
|
||||
|
@ -5173,10 +5224,10 @@ describe('Wallet service', function() {
|
|||
|
||||
describe('#startScan', function() {
|
||||
var server, wallet;
|
||||
var scanConfigOld = WalletService.SCAN_CONFIG;
|
||||
var scanConfigOld = Constants.SCAN_CONFIG;
|
||||
beforeEach(function(done) {
|
||||
this.timeout(5000);
|
||||
WalletService.SCAN_CONFIG.maxGap = 2;
|
||||
Constants.SCAN_CONFIG.maxGap = 2;
|
||||
|
||||
helpers.createAndJoinWallet(1, 1, {
|
||||
supportBIP44AndP2PKH: false
|
||||
|
@ -5187,7 +5238,7 @@ describe('Wallet service', function() {
|
|||
});
|
||||
});
|
||||
afterEach(function() {
|
||||
WalletService.SCAN_CONFIG = scanConfigOld;
|
||||
Constants.SCAN_CONFIG = scanConfigOld;
|
||||
server.messageBroker.removeAllListeners();
|
||||
});
|
||||
|
||||
|
@ -5245,7 +5296,7 @@ describe('Wallet service', function() {
|
|||
});
|
||||
it('should start multiple asynchronous scans for different wallets', function(done) {
|
||||
helpers.stubAddressActivity(['3K2VWMXheGZ4qG35DyGjA2dLeKfaSr534A']);
|
||||
WalletService.SCAN_CONFIG.scanWindow = 1;
|
||||
Constants.SCAN_CONFIG.scanWindow = 1;
|
||||
|
||||
var scans = 0;
|
||||
server.messageBroker.onMessage(function(n) {
|
||||
|
@ -5321,7 +5372,7 @@ describe('Wallet service', function() {
|
|||
should.not.exist(err);
|
||||
should.exist(tx);
|
||||
tx.amount.should.equal(helpers.toSatoshi(80));
|
||||
tx.fee.should.equal(WalletUtils.DEFAULT_FEE_PER_KB);
|
||||
tx.fee.should.equal(Constants.DEFAULT_FEE_PER_KB);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
@ -5411,7 +5462,7 @@ describe('Wallet service', function() {
|
|||
should.not.exist(err);
|
||||
should.exist(tx);
|
||||
tx.amount.should.equal(helpers.toSatoshi(80));
|
||||
tx.fee.should.equal(WalletUtils.DEFAULT_FEE_PER_KB);
|
||||
tx.fee.should.equal(Constants.DEFAULT_FEE_PER_KB);
|
||||
helpers.getAuthServer(wallet.copayers[0].id, function(server) {
|
||||
var signatures = helpers.clientSign(tx, TestData.copayers[0].xPrivKey);
|
||||
server.signTx({
|
||||
|
|
|
@ -5,8 +5,7 @@ var chai = require('chai');
|
|||
var sinon = require('sinon');
|
||||
var should = chai.should();
|
||||
var TxProposal = require('../../lib/model/txproposal');
|
||||
var Bitcore = require('bitcore-wallet-utils').Bitcore;
|
||||
var WalletUtils = require('bitcore-wallet-utils');
|
||||
var Bitcore = require('bitcore-lib');
|
||||
|
||||
describe('TXProposal', function() {
|
||||
|
||||
|
|
Loading…
Reference in New Issue