From 94509eebab5b98ecc33023a95457da7329052b7e Mon Sep 17 00:00:00 2001 From: Ivan Socolsky Date: Fri, 30 Jan 2015 17:37:30 -0300 Subject: [PATCH] . --- lib/server.js | 71 ++++++++++++++++++++++++++++++++------------- test/integration.js | 24 +++++++++++++-- 2 files changed, 73 insertions(+), 22 deletions(-) diff --git a/lib/server.js b/lib/server.js index 76e5ff7..d12c60b 100644 --- a/lib/server.js +++ b/lib/server.js @@ -222,18 +222,57 @@ CopayServer.prototype._getUtxos = function (opts, cb) { bc.getUnspentUtxos(addresses, function (err, utxos) { if (err) return cb(err); - // TODO: filter 'locked' utxos + self.getPendingTxs({ walletId: opts.walletId }, function (err, txps) { + if (err) return cb(err); + + var inputs = _.chain(txps) + .pluck('input') + .flatten() + .map(function (utxo) { return utxo.txid + '|' + utxo.vout }); - return cb(null, utxos); + var dictionary = _.groupBy(utxos, function (utxo) { + return utxo.txid + '|' + utxo.vout; + }); + + _.each(inputs, function (input) { + if (dictionary[input]) { + dictionary[input].locked = true; + } + }); + + return cb(null, utxos); + }); }); }); }; -CopayServer.prototype._createRawTx = function (tx) { + +/** + * Creates a new transaction proposal. + * @param {Object} opts + * @param {string} opts.walletId - The wallet id. + * @returns {Object} balance - Total amount & locked amount. + */ + CopayServer.prototype.getBalance = function (opts, cb) { + var self = this; + + self._getUtxos({ walletId: opts.walletId }, function (err, utxos) { + if (err) return cb(err); + + var balance = {}; + balance.totalAmount = _.reduce(utxos, function(sum, utxo) { return sum + utxo.amount; }); + balance.lockedAmount = _.reduce(_.without(utxos, { locked: true }), function(sum, utxo) { return sum + utxo.amount; }); + + return cb(null, balance); + }); +}; + + +CopayServer.prototype._createRawTx = function (txp, utxos) { var rawTx = new Bitcore.Transaction() - .from(tx.inputs) - .to(tx.toAddress, tx.amount) - .change(tx.changeAddress); + .from(utxos) + .to(txp.toAddress, txp.amount) + .change(txp.changeAddress); return rawTx; }; @@ -258,16 +297,19 @@ CopayServer.prototype.createTx = function (opts, cb) { self._getUtxos({ walletId: wallet.id }, function (err, utxos) { if (err) return cb(err); + utxos = _.without(utxos, { locked: true }); + var txp = new TxProposal({ creatorId: opts.copayerId, toAddress: opts.toAddress, amount: opts.amount, changeAddress: opts.changeAddress, - inputs: utxos, requiredSignatures: wallet.m, maxRejections: wallet.n - wallet.m, }); - txp.rawTx = self._createRawTx(txp); + txp.rawTx = self._createRawTx(txp, utxos); + + // TODO: assign used inputs self.storage.storeTx(wallet.id, txp, function (err) { if (err) return cb(err); @@ -345,17 +387,7 @@ CopayServer.prototype.rejectTx = function (opts, cb) { self.storage.storeTx(opts.walletId, txp, function (err) { if (err) return cb(err); - if (txp.status == 'accepted'); - self._broadcastTx(txp.rawTx, function (err, txid) { - if (err) return cb(err); - - tx.setBroadcasted(txid); - self.storage.storeTx(opts.walletId, txp, function (err) { - if (err) return cb(err); - - return cb(); - }); - }); + return cb(); }); }); }; @@ -364,7 +396,6 @@ CopayServer.prototype.rejectTx = function (opts, cb) { * Retrieves all pending transaction proposals. * @param {Object} opts * @param {string} opts.walletId - The wallet id. - * @param {string} opts.copayerId - The wallet id. * @returns {TxProposal[]} Transaction proposal. */ CopayServer.prototype.getPendingTxs = function (opts, cb) { diff --git a/test/integration.js b/test/integration.js index 7300f0b..dfcd580 100644 --- a/test/integration.js +++ b/test/integration.js @@ -48,6 +48,17 @@ helpers.createAndJoinWallet = function (id, m, n, cb) { }); }); }; +helpers.createUtxos = function (amounts) { + amounts = [].concat(amounts); + + return _.map(amounts, function (amount) { + return { + txid: 'dummy' + Math.random(), + vout: Math.floor((Math.random() * 10) + 1), + amount: amount, + }; + }); +}; var db, storage; var server; @@ -403,7 +414,7 @@ describe('Copay server', function() { it('should create tx', function (done) { var bc = sinon.stub(); - bc.getUnspentUtxos = sinon.stub().callsArgWith(1, null, ['utxo1', 'utxo2']); + bc.getUnspentUtxos = sinon.stub().callsArgWith(1, null, helpers.createUtxos([100, 200])); server._getBlockExplorer = sinon.stub().returns(bc); server._createRawTx = sinon.stub().returns('raw'); @@ -426,9 +437,18 @@ describe('Copay server', function() { server.getPendingTxs({ walletId: '123' }, function (err, txs) { should.not.exist(err); txs.length.should.equal(1); + done(); }); - done(); }); }); + + it.skip('should fail to create tx when insufficient funds', function (done) { + }); + + it.skip('should create tx when there is a pending tx and enough UTXOs', function (done) { + }); + + it.skip('should fail to create tx when there is a pending tx and not enough UTXOs', function (done) { + }); }); });