|
|
@ -41,7 +41,7 @@ function CopayServer(opts) { |
|
|
|
CopayServer.prototype.createWallet = function (opts, cb) { |
|
|
|
var self = this; |
|
|
|
|
|
|
|
self.getWallet({ id: opts.id }, function (err, wallet) { |
|
|
|
self.storage.fetchWallet(opts.id, function (err, wallet) { |
|
|
|
if (err) return cb(err); |
|
|
|
if (wallet) return cb('Wallet already exists'); |
|
|
|
|
|
|
@ -69,7 +69,9 @@ CopayServer.prototype.createWallet = function (opts, cb) { |
|
|
|
var self = this; |
|
|
|
|
|
|
|
self.storage.fetchWallet(opts.id, function (err, wallet) { |
|
|
|
if (err || !wallet) return cb(err); |
|
|
|
if (err) return cb(err); |
|
|
|
if (!wallet) return cb('Wallet not found'); |
|
|
|
|
|
|
|
if (opts.includeCopayers) { |
|
|
|
self.storage.fetchCopayers(wallet.id, function (err, copayers) { |
|
|
|
if (err) return cb(err); |
|
|
@ -109,8 +111,7 @@ CopayServer.prototype._runLocked = function (walletId, cb, task) { |
|
|
|
|
|
|
|
self._runLocked(opts.walletId, cb, function (cb) { |
|
|
|
self.getWallet({ id: opts.walletId, includeCopayers: true }, function (err, wallet) { |
|
|
|
if (err) return cb(err); |
|
|
|
if (!wallet) return cb('Wallet not found'); |
|
|
|
if (err || !wallet) return cb(err); |
|
|
|
if (_.find(wallet.copayers, { xPubKey: opts.xPubKey })) return cb('Copayer already in wallet'); |
|
|
|
if (wallet.copayers.length == wallet.n) return cb('Wallet full'); |
|
|
|
// TODO: validate copayer's extended public key using the public key from this wallet
|
|
|
@ -152,8 +153,7 @@ CopayServer.prototype._doCreateAddress = function (pkr, index, isChange) { |
|
|
|
|
|
|
|
self._runLocked(opts.walletId, cb, function (cb) { |
|
|
|
self.getWallet({ id: opts.walletId }, function (err, wallet) { |
|
|
|
if (err) return cb(err); |
|
|
|
if (!wallet) return cb('Wallet not found'); |
|
|
|
if (err || !wallet) return cb(err); |
|
|
|
|
|
|
|
var index = wallet.addressIndex++; |
|
|
|
self.storage.storeWallet(wallet, function (err) { |
|
|
@ -219,7 +219,7 @@ CopayServer.prototype._getUtxos = function (opts, cb) { |
|
|
|
var self = this; |
|
|
|
|
|
|
|
// Get addresses for this wallet
|
|
|
|
self.storage.getAddresses(opts.walletId, function (err, addresses) { |
|
|
|
self.storage.fetchAddresses(opts.walletId, function (err, addresses) { |
|
|
|
if (err) return cb(err); |
|
|
|
if (addresses.length == 0) return cb('The wallet has no addresses'); |
|
|
|
|
|
|
@ -268,14 +268,12 @@ CopayServer.prototype.createTx = function (opts, cb) { |
|
|
|
var self = this; |
|
|
|
|
|
|
|
self.getWallet({ id: opts.walletId }, function (err, wallet) { |
|
|
|
if (err) return cb(err); |
|
|
|
if (!wallet) return cb('Wallet not found'); |
|
|
|
if (err || !wallet) return cb(err); |
|
|
|
|
|
|
|
self._getUtxos({ walletId: wallet.id }, function (err, utxos) { |
|
|
|
if (err) return cb('Could not retrieve UTXOs'); |
|
|
|
if (err) return cb(err); |
|
|
|
|
|
|
|
self._doCreateTx(opts.copayerId, opts.toAddress, opts.amount, opts.changeAddress, utxos, function (err, tx) { |
|
|
|
if (err) return cb('Could not create transaction'); |
|
|
|
var tx = self._doCreateTx(opts.copayerId, opts.toAddress, opts.amount, opts.changeAddress, utxos); |
|
|
|
|
|
|
|
self.storage.storeTx(tx, function (err) { |
|
|
|
if (err) return cb(err); |
|
|
@ -284,7 +282,12 @@ CopayServer.prototype.createTx = function (opts, cb) { |
|
|
|
}); |
|
|
|
}); |
|
|
|
}); |
|
|
|
}); |
|
|
|
}; |
|
|
|
|
|
|
|
CopayServer.prototype._broadcastTx = function (tx, cb) { |
|
|
|
cb = cb || function () {}; |
|
|
|
|
|
|
|
throw 'not implemented'; |
|
|
|
}; |
|
|
|
|
|
|
|
/** |
|
|
@ -292,27 +295,35 @@ CopayServer.prototype.createTx = function (opts, cb) { |
|
|
|
* @param {Object} opts |
|
|
|
* @param {string} opts.walletId - The wallet id. |
|
|
|
* @param {string} opts.copayerId - The wallet id. |
|
|
|
* @param {string} opts.ntxid - The identifier of the transaction. |
|
|
|
* @param {string} opts.txProposalId - The identifier of the transaction. |
|
|
|
* @param {string} opts.signature - The signature of the tx for this copayer. |
|
|
|
*/ |
|
|
|
CopayServer.prototype.signTx = function (opts, cb) { |
|
|
|
var self = this; |
|
|
|
|
|
|
|
self.getWallet({ id: opts.walletId }, function (err, wallet) { |
|
|
|
if (err) return cb(err); |
|
|
|
if (!wallet) return cb('Wallet not found'); |
|
|
|
|
|
|
|
self._getUtxos({ walletId: wallet.id }, function (err, utxos) { |
|
|
|
if (err) return cb('Could not retrieve UTXOs'); |
|
|
|
|
|
|
|
self._doCreateTx(opts.copayerId, opts.toAddress, opts.amount, opts.changeAddress, utxos, function (err, tx) { |
|
|
|
if (err) return cb('Could not create transaction'); |
|
|
|
if (err || !wallet) return cb(err); |
|
|
|
|
|
|
|
self.storage.storeTx(tx, function (err) { |
|
|
|
self.fetchTx(wallet.id, opts.txProposalId, function (err, tx) { |
|
|
|
if (err) return cb(err); |
|
|
|
if (!tx) return cb('Transaction proposal not found'); |
|
|
|
var action = _.find(tx.actions, { copayerId: opts.copayerId }); |
|
|
|
if (action) return cb('Copayer already acted upon this transaction proposal'); |
|
|
|
if (tx.status != 'pending') return cb('The transaction proposal is not pending'); |
|
|
|
|
|
|
|
tx.sign(opts.copayerId, opts.signature); |
|
|
|
if (tx.isRejected()) { |
|
|
|
tx.status = 'rejected'; |
|
|
|
} else if (tx.isAccepted()) { |
|
|
|
tx.status = 'accepted'; |
|
|
|
} |
|
|
|
self.storage.storeTx(wallet.id, tx, function (err) { |
|
|
|
if (err) return cb(err); |
|
|
|
|
|
|
|
return cb(null, tx); |
|
|
|
}); |
|
|
|
if (tx.status == 'accepted'); |
|
|
|
self._broadcastTx(tx); |
|
|
|
|
|
|
|
return cb(); |
|
|
|
}); |
|
|
|
}); |
|
|
|
}); |
|
|
|