diff --git a/README.md b/README.md index 45e70da..d25a060 100644 --- a/README.md +++ b/README.md @@ -71,6 +71,7 @@ Returns: Returns: * totalAmount: Wallet's total balance * lockedAmount: Current balance of outstanding transaction proposals, that cannot be used on new transactions. + * byAddress array ['address', 'path', 'amount']: A list of addresses holding funds. ## POST Endpoinds `/v1/wallets/`: Create a new Wallet diff --git a/lib/server.js b/lib/server.js index 9506e3f..f31c648 100644 --- a/lib/server.js +++ b/lib/server.js @@ -441,6 +441,22 @@ WalletService.prototype.getBalance = function(opts, cb) { return sum + utxo.satoshis; }, 0)); + // Compute balance by address + var byAddress = {}; + _.each(_.indexBy(utxos, 'address'), function(value, key) { + byAddress[key] = { + address: key, + path: value.path, + amount: 0, + }; + }); + + _.each(utxos, function(utxo) { + byAddress[utxo.address].amount += utxo.satoshis; + }); + + balance.byAddress = _.values(byAddress); + return cb(null, balance); }); }; diff --git a/test/integration/server.js b/test/integration/server.js index 4b348c2..011df7b 100644 --- a/test/integration/server.js +++ b/test/integration/server.js @@ -550,7 +550,6 @@ describe('Copay server', function() { }); }); - describe('#verifyMessageSignature', function() { var server, wallet; beforeEach(function(done) { @@ -646,6 +645,77 @@ describe('Copay server', function() { }); }); + describe('#getBalance', function() { + var server, wallet; + beforeEach(function(done) { + helpers.createAndJoinWallet(1, 1, function(s, w) { + server = s; + wallet = w; + done(); + }); + }); + + it('should get balance', function(done) { + helpers.stubUtxos(server, wallet, [1, 2, 3], function() { + server.getBalance({}, function(err, balance) { + should.not.exist(err); + should.exist(balance); + balance.totalAmount.should.equal(helpers.toSatoshi(6)); + balance.lockedAmount.should.equal(0); + should.exist(balance.byAddress); + balance.byAddress.length.should.equal(2); + balance.byAddress[0].amount.should.equal(helpers.toSatoshi(4)); + balance.byAddress[1].amount.should.equal(helpers.toSatoshi(2)); + server.getMainAddresses({}, function(err, addresses) { + should.not.exist(err); + var addresses = _.uniq(_.pluck(addresses, 'address')); + _.intersection(addresses, _.pluck(balance.byAddress, 'address')).length.should.equal(2); + done(); + }); + }); + }); + }); + it('should get balance when there are no addresses', function(done) { + server.getBalance({}, function(err, balance) { + should.not.exist(err); + should.exist(balance); + balance.totalAmount.should.equal(0); + balance.lockedAmount.should.equal(0); + should.exist(balance.byAddress); + balance.byAddress.length.should.equal(0); + done(); + }); + }); + it('should get balance when there are no funds', function(done) { + blockExplorer.getUnspentUtxos = sinon.stub().callsArgWith(1, null, []); + server.createAddress({}, function(err, address) { + should.not.exist(err); + server.getBalance({}, function(err, balance) { + should.not.exist(err); + should.exist(balance); + balance.totalAmount.should.equal(0); + balance.lockedAmount.should.equal(0); + should.exist(balance.byAddress); + balance.byAddress.length.should.equal(0); + done(); + }); + }); + }); + it('should only include addresses with balance', function(done) { + helpers.stubUtxos(server, wallet, 1, function(utxos) { + server.createAddress({}, function(err, address) { + should.not.exist(err); + server.getBalance({}, function(err, balance) { + should.not.exist(err); + balance.byAddress.length.should.equal(1); + balance.byAddress[0].amount.should.equal(helpers.toSatoshi(1)); + balance.byAddress[0].address.should.equal(utxos[0].address); + done(); + }); + }); + }); + }); + }); describe('Wallet not complete tests', function() { it('should fail to create address when wallet is not complete', function(done) { @@ -710,7 +780,6 @@ describe('Copay server', function() { }); }); - describe('#createTx', function() { var server, wallet; beforeEach(function(done) { @@ -959,7 +1028,6 @@ describe('Copay server', function() { }); }); - describe('#rejectTx', function() { var server, wallet, txid; @@ -1356,7 +1424,6 @@ describe('Copay server', function() { }); }); - describe('Tx proposal workflow', function() { var server, wallet; beforeEach(function(done) { @@ -1682,8 +1749,6 @@ describe('Copay server', function() { }); }); - - describe('Notifications', function() { var server, wallet; @@ -1901,7 +1966,6 @@ describe('Copay server', function() { }); }); - describe('#removePendingTx', function() { var server, wallet, txp; beforeEach(function(done) { @@ -2037,7 +2101,6 @@ describe('Copay server', function() { }); }); - describe('#getTxHistory', function() { var server, wallet, mainAddresses, changeAddresses; beforeEach(function(done) {