|
|
@ -13,6 +13,7 @@ var PublicKey = Bitcore.PublicKey; |
|
|
|
var HDPublicKey = Bitcore.HDPublicKey; |
|
|
|
var Explorers = require('bitcore-explorers'); |
|
|
|
|
|
|
|
var ClientError = require('./clienterror'); |
|
|
|
var Utils = require('./utils'); |
|
|
|
var Storage = require('./storage'); |
|
|
|
var SignUtils = require('./signutils'); |
|
|
@ -57,9 +58,9 @@ CopayServer.prototype.createWallet = function(opts, cb) { |
|
|
|
pubKey; |
|
|
|
|
|
|
|
Utils.checkRequired(opts, ['id', 'name', 'm', 'n', 'pubKey']); |
|
|
|
if (!Wallet.verifyCopayerLimits(opts.m, opts.n)) return cb('Invalid m/n combination'); |
|
|
|
if (!Wallet.verifyCopayerLimits(opts.m, opts.n)) return cb(new ClientError('Invalid combination of required copayers / total copayers')); |
|
|
|
var network = opts.network || 'livenet'; |
|
|
|
if (network != 'livenet' && network != 'testnet') return cb('Invalid network'); |
|
|
|
if (network != 'livenet' && network != 'testnet') return cb(new ClientError('Invalid network')); |
|
|
|
|
|
|
|
try { |
|
|
|
pubKey = new PublicKey.fromString(opts.pubKey); |
|
|
@ -69,7 +70,7 @@ CopayServer.prototype.createWallet = function(opts, cb) { |
|
|
|
|
|
|
|
self.storage.fetchWallet(opts.id, function(err, wallet) { |
|
|
|
if (err) return cb(err); |
|
|
|
if (wallet) return cb('Wallet already exists'); |
|
|
|
if (wallet) return cb(new ClientError('WEXISTS', 'Wallet already exists')); |
|
|
|
|
|
|
|
var wallet = new Wallet({ |
|
|
|
id: opts.id, |
|
|
@ -95,7 +96,7 @@ CopayServer.prototype.getWallet = function(opts, cb) { |
|
|
|
|
|
|
|
self.storage.fetchWallet(opts.id, function(err, wallet) { |
|
|
|
if (err) return cb(err); |
|
|
|
if (!wallet) return cb('Wallet not found'); |
|
|
|
if (!wallet) return cb(new ClientError('Wallet not found')); |
|
|
|
return cb(null, wallet); |
|
|
|
}); |
|
|
|
}; |
|
|
@ -132,13 +133,13 @@ CopayServer.prototype.joinWallet = function(opts, cb) { |
|
|
|
if (err) return cb(err); |
|
|
|
|
|
|
|
if (!self._verifySignature(opts.xPubKey, opts.xPubKeySignature, wallet.pubKey)) { |
|
|
|
return cb('Bad request'); |
|
|
|
return cb(new ClientError()); |
|
|
|
} |
|
|
|
|
|
|
|
if (_.find(wallet.copayers, { |
|
|
|
xPubKey: opts.xPubKey |
|
|
|
})) return cb('Copayer already in wallet'); |
|
|
|
if (wallet.copayers.length == wallet.n) return cb('Wallet full'); |
|
|
|
})) return cb(new ClientError('CINWALLET', 'Copayer already in wallet')); |
|
|
|
if (wallet.copayers.length == wallet.n) return cb(new ClientError('WFULL', 'Wallet full')); |
|
|
|
|
|
|
|
var copayer = new Copayer({ |
|
|
|
id: opts.id, |
|
|
@ -234,7 +235,7 @@ CopayServer.prototype.verifyMessageSignature = function(opts, cb) { |
|
|
|
if (err) return cb(err); |
|
|
|
|
|
|
|
var copayer = wallet.getCopayer(opts.copayerId); |
|
|
|
if (!copayer) return cb('Copayer not found'); |
|
|
|
if (!copayer) return cb(new ClientError('Copayer not found')); |
|
|
|
|
|
|
|
var isValid = self._verifySignature(opts.message, opts.signature, copayer.signingPubKey); |
|
|
|
return cb(null, isValid); |
|
|
@ -268,7 +269,7 @@ CopayServer.prototype._getUtxos = function(opts, cb) { |
|
|
|
// Get addresses for this wallet
|
|
|
|
self.storage.fetchAddresses(opts.walletId, function(err, addresses) { |
|
|
|
if (err) return cb(err); |
|
|
|
if (addresses.length == 0) return cb('The wallet has no addresses'); |
|
|
|
if (addresses.length == 0) return cb(new ClientError('The wallet has no addresses')); |
|
|
|
|
|
|
|
var addresses = _.pluck(addresses, 'address'); |
|
|
|
|
|
|
@ -417,8 +418,9 @@ CopayServer.prototype.createTx = function(opts, cb) { |
|
|
|
}); |
|
|
|
|
|
|
|
txp.inputs = self._selectUtxos(txp, utxos); |
|
|
|
if (!txp.inputs) |
|
|
|
return cb('insufficient funds') |
|
|
|
if (!txp.inputs) { |
|
|
|
return cb(new ClientError('INSUFFICIENTFUNDS', 'Insufficient funds')); |
|
|
|
} |
|
|
|
|
|
|
|
// no need to do this now: // TODO remove this comment
|
|
|
|
//self._createRawTx(txp);
|
|
|
@ -453,12 +455,12 @@ CopayServer.prototype.signTx = function(opts, cb) { |
|
|
|
|
|
|
|
self.fetchTx(opts.walletId, opts.txProposalId, function(err, txp) { |
|
|
|
if (err) return cb(err); |
|
|
|
if (!txp) return cb('Transaction proposal not found'); |
|
|
|
if (!txp) return cb(new ClientError('Transaction proposal not found')); |
|
|
|
var action = _.find(txp.actions, { |
|
|
|
copayerId: opts.copayerId |
|
|
|
}); |
|
|
|
if (action) return cb('Copayer already voted on this transaction proposal'); |
|
|
|
if (txp.status != 'pending') return cb('The transaction proposal is not pending'); |
|
|
|
if (action) return cb(new ClientError('CVOTED', 'Copayer already voted on this transaction proposal')); |
|
|
|
if (txp.status != 'pending') return cb(new ClientError('TXNOTPENDING', 'The transaction proposal is not pending')); |
|
|
|
|
|
|
|
txp.sign(opts.copayerId, opts.signature); |
|
|
|
|
|
|
@ -495,12 +497,12 @@ CopayServer.prototype.rejectTx = function(opts, cb) { |
|
|
|
|
|
|
|
self.fetchTx(opts.walletId, opts.txProposalId, function(err, txp) { |
|
|
|
if (err) return cb(err); |
|
|
|
if (!txp) return cb('Transaction proposal not found'); |
|
|
|
if (!txp) return cb(new ClientError('Transaction proposal not found')); |
|
|
|
var action = _.find(txp.actions, { |
|
|
|
copayerId: opts.copayerId |
|
|
|
}); |
|
|
|
if (action) return cb('Copayer already voted on this transaction proposal'); |
|
|
|
if (txp.status != 'pending') return cb('The transaction proposal is not pending'); |
|
|
|
if (action) return cb(new ClientError('CVOTED', 'Copayer already voted on this transaction proposal')); |
|
|
|
if (txp.status != 'pending') return cb(new ClientError('TXNOTPENDING', 'The transaction proposal is not pending')); |
|
|
|
|
|
|
|
txp.reject(opts.copayerId); |
|
|
|
|
|
|
|