fix address regressions
This commit is contained in:
parent
85ad9fcdb6
commit
671665c052
@ -5,8 +5,6 @@ var _ = bitcore.deps._;
|
|||||||
var $ = bitcore.util.preconditions;
|
var $ = bitcore.util.preconditions;
|
||||||
var Address = bitcore.Address;
|
var Address = bitcore.Address;
|
||||||
|
|
||||||
var BitcoreNode = require('../../');
|
|
||||||
|
|
||||||
var Addresses = {};
|
var Addresses = {};
|
||||||
|
|
||||||
var node;
|
var node;
|
||||||
|
|||||||
@ -11,17 +11,11 @@ var _ = bitcore.deps._;
|
|||||||
|
|
||||||
|
|
||||||
var mockAddresses = require('../data/addresses');
|
var mockAddresses = require('../data/addresses');
|
||||||
var mockTransactions = require('../data/transactions');
|
|
||||||
|
|
||||||
describe('BitcoreHTTP v1 addresses routes', function() {
|
describe('BitcoreHTTP v1 addresses routes', function() {
|
||||||
|
|
||||||
// mocks
|
// mocks
|
||||||
var transactionList = _.values(mockTransactions);
|
|
||||||
var nodeMock, agent;
|
var nodeMock, agent;
|
||||||
var txs_for_addr = function(addr) {
|
|
||||||
var amount = mockAddresses[addr].summary.transactions.length;
|
|
||||||
return transactionList.slice(0, amount);
|
|
||||||
};
|
|
||||||
var utxos_for_addrs = function(addrs) {
|
var utxos_for_addrs = function(addrs) {
|
||||||
return _.reduce(addrs, function(utxos, addr) {
|
return _.reduce(addrs, function(utxos, addr) {
|
||||||
return utxos.concat(mockAddresses[addr].utxos);
|
return utxos.concat(mockAddresses[addr].utxos);
|
||||||
@ -53,10 +47,7 @@ describe('BitcoreHTTP v1 addresses routes', function() {
|
|||||||
nodeMock.addressService.getSummary = function(address) {
|
nodeMock.addressService.getSummary = function(address) {
|
||||||
return Promise.resolve(mockAddresses[address.toString()].summary);
|
return Promise.resolve(mockAddresses[address.toString()].summary);
|
||||||
};
|
};
|
||||||
nodeMock.listTransactions = function(opts) {
|
nodeMock.addressService.getUnspent = function(addresses) {
|
||||||
return Promise.resolve(txs_for_addr(opts.address));
|
|
||||||
};
|
|
||||||
nodeMock.getUTXOs = function(addresses) {
|
|
||||||
return Promise.resolve(utxos_for_addrs(addresses));
|
return Promise.resolve(utxos_for_addrs(addresses));
|
||||||
};
|
};
|
||||||
agent = require('../app')(nodeMock);
|
agent = require('../app')(nodeMock);
|
||||||
@ -77,19 +68,7 @@ describe('BitcoreHTTP v1 addresses routes', function() {
|
|||||||
it('works with valid address ' + addr, function(cb) {
|
it('works with valid address ' + addr, function(cb) {
|
||||||
agent.get('/v1/addresses/' + addr)
|
agent.get('/v1/addresses/' + addr)
|
||||||
.expect(200)
|
.expect(200)
|
||||||
.expect(JSON.stringify(info.summary), cb);
|
.expect(info.summary, cb);
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
describe('/addresses/:address/transactions', function() {
|
|
||||||
it('fails with invalid address', function(cb) {
|
|
||||||
failsWithInvalidAddress(agent, '/v1/addresses/1BpbpfLdY7oBS9gK7aDXgvMgr1DpvNH3B2/transactions', cb);
|
|
||||||
});
|
|
||||||
_.keys(mockAddresses).forEach(function(addr) {
|
|
||||||
it('works with valid address ' + addr, function(cb) {
|
|
||||||
agent.get('/v1/addresses/' + addr + '/transactions')
|
|
||||||
.expect(200)
|
|
||||||
.expect(JSON.stringify(txs_for_addr(addr)), cb);
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@ -104,7 +83,7 @@ describe('BitcoreHTTP v1 addresses routes', function() {
|
|||||||
it('works with valid address ' + addr, function(cb) {
|
it('works with valid address ' + addr, function(cb) {
|
||||||
agent.get('/v1/addresses/' + addr + '/utxos')
|
agent.get('/v1/addresses/' + addr + '/utxos')
|
||||||
.expect(200)
|
.expect(200)
|
||||||
.expect(JSON.stringify(utxos_for_addrs([addr])), cb);
|
.expect(utxos_for_addrs([addr]), cb);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@ -118,7 +97,7 @@ describe('BitcoreHTTP v1 addresses routes', function() {
|
|||||||
var path = '/v1/addresses/' + list + '/utxos';
|
var path = '/v1/addresses/' + list + '/utxos';
|
||||||
agent.get(path)
|
agent.get(path)
|
||||||
.expect(200)
|
.expect(200)
|
||||||
.expect(JSON.stringify(utxos_for_addrs(addresses)), cb);
|
.expect(utxos_for_addrs(addresses), cb);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@ -3,7 +3,6 @@
|
|||||||
var Promise = require('bluebird');
|
var Promise = require('bluebird');
|
||||||
var bitcore = require('bitcore');
|
var bitcore = require('bitcore');
|
||||||
var TransactionService = require('./transaction');
|
var TransactionService = require('./transaction');
|
||||||
var RPC = require('bitcoind-rpc');
|
|
||||||
var _ = bitcore.deps._;
|
var _ = bitcore.deps._;
|
||||||
var $ = bitcore.util.preconditions;
|
var $ = bitcore.util.preconditions;
|
||||||
|
|
||||||
@ -15,8 +14,8 @@ function AddressService(opts) {
|
|||||||
opts = _.extend({}, opts);
|
opts = _.extend({}, opts);
|
||||||
this.transactionService = opts.transactionService;
|
this.transactionService = opts.transactionService;
|
||||||
this.blockService = opts.blockService;
|
this.blockService = opts.blockService;
|
||||||
this.database = opts.database || Promise.promisifyAll(new LevelUp(config.get('LevelUp')));
|
this.database = opts.database;
|
||||||
this.rpc = opts.rpc || Promise.promisifyAll(new RPC(config.get('RPC')));
|
this.rpc = opts.rpc;
|
||||||
}
|
}
|
||||||
|
|
||||||
AddressService.prototype.getSummary = function(address, confirmations) {
|
AddressService.prototype.getSummary = function(address, confirmations) {
|
||||||
|
|||||||
@ -6,7 +6,6 @@ var events = require('events');
|
|||||||
var Promise = require('bluebird');
|
var Promise = require('bluebird');
|
||||||
|
|
||||||
var bitcore = require('bitcore');
|
var bitcore = require('bitcore');
|
||||||
var _ = bitcore.deps._;
|
|
||||||
|
|
||||||
var AddressService = require('../../lib/services/address');
|
var AddressService = require('../../lib/services/address');
|
||||||
|
|
||||||
@ -43,7 +42,9 @@ describe('AddressService', function() {
|
|||||||
beforeEach(initialize);
|
beforeEach(initialize);
|
||||||
|
|
||||||
it('calls internal functions as expected', function(done) {
|
it('calls internal functions as expected', function(done) {
|
||||||
service.blockService = { getLatest: sinon.mock() };
|
service.blockService = {
|
||||||
|
getLatest: sinon.mock()
|
||||||
|
};
|
||||||
service.getAllOutputs = sinon.mock();
|
service.getAllOutputs = sinon.mock();
|
||||||
service.getSpent = sinon.mock();
|
service.getSpent = sinon.mock();
|
||||||
service.buildAddressSummary = sinon.mock();
|
service.buildAddressSummary = sinon.mock();
|
||||||
@ -105,17 +106,16 @@ describe('AddressService', function() {
|
|||||||
AddressService.processOutput = sinon.stub(AddressService, 'processOutput');
|
AddressService.processOutput = sinon.stub(AddressService, 'processOutput');
|
||||||
AddressService.processOutput.onFirstCall().returns('processed');
|
AddressService.processOutput.onFirstCall().returns('processed');
|
||||||
|
|
||||||
var element = {key: 'key', value: 'value'};
|
var element = {
|
||||||
|
key: 'key',
|
||||||
|
value: 'value'
|
||||||
|
};
|
||||||
var address = '12cbQLTFMXRnSzktFkuoG3eHoMeFtpTu3S';
|
var address = '12cbQLTFMXRnSzktFkuoG3eHoMeFtpTu3S';
|
||||||
service.getAllOutputs(address).then(function(arg) {
|
service.getAllOutputs(address).then(function(arg) {
|
||||||
service.database.createReadStream.firstCall.args[0].should.deep.equal(
|
service.database.createReadStream.firstCall.args[0].should.deep.equal({
|
||||||
{
|
gte: 'txa-12cbQLTFMXRnSzktFkuoG3eHoMeFtpTu3S-' + '0000000000000000000000000000000000000000000000000000000000000000-0',
|
||||||
gte: 'txa-12cbQLTFMXRnSzktFkuoG3eHoMeFtpTu3S-'
|
lte: 'txa-12cbQLTFMXRnSzktFkuoG3eHoMeFtpTu3S-' + 'ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff-4294967295'
|
||||||
+ '0000000000000000000000000000000000000000000000000000000000000000-0',
|
});
|
||||||
lte: 'txa-12cbQLTFMXRnSzktFkuoG3eHoMeFtpTu3S-'
|
|
||||||
+ 'ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff-4294967295'
|
|
||||||
}
|
|
||||||
);
|
|
||||||
AddressService.processOutput.firstCall.args[0].should.equal(element);
|
AddressService.processOutput.firstCall.args[0].should.equal(element);
|
||||||
AddressService.processOutput.reset();
|
AddressService.processOutput.reset();
|
||||||
arg[0].should.equal('processed');
|
arg[0].should.equal('processed');
|
||||||
@ -131,20 +131,23 @@ describe('AddressService', function() {
|
|||||||
var dataCall = new events.EventEmitter();
|
var dataCall = new events.EventEmitter();
|
||||||
service.database.createReadStream.onFirstCall().returns(dataCall);
|
service.database.createReadStream.onFirstCall().returns(dataCall);
|
||||||
|
|
||||||
var element = {key: 'key', value: JSON.stringify({a: 'b'})};
|
var element = {
|
||||||
|
key: 'key',
|
||||||
|
value: JSON.stringify({
|
||||||
|
a: 'b'
|
||||||
|
})
|
||||||
|
};
|
||||||
var address = '12cbQLTFMXRnSzktFkuoG3eHoMeFtpTu3S';
|
var address = '12cbQLTFMXRnSzktFkuoG3eHoMeFtpTu3S';
|
||||||
service.getSpent(address).then(function(arg) {
|
service.getSpent(address)
|
||||||
service.database.createReadStream.firstCall.args[0].should.deep.equal(
|
.then(function(arg) {
|
||||||
{
|
service.database.createReadStream.firstCall.args[0].should.deep.equal({
|
||||||
gte: 'txas-12cbQLTFMXRnSzktFkuoG3eHoMeFtpTu3S-'
|
gte: 'txas-12cbQLTFMXRnSzktFkuoG3eHoMeFtpTu3S-' + '0000000000000000000000000000000000000000000000000000000000000000-0',
|
||||||
+ '0000000000000000000000000000000000000000000000000000000000000000-0',
|
lte: 'txas-12cbQLTFMXRnSzktFkuoG3eHoMeFtpTu3S-' + 'ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff-4294967295'
|
||||||
lte: 'txas-12cbQLTFMXRnSzktFkuoG3eHoMeFtpTu3S-'
|
});
|
||||||
+ 'ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff-4294967295'
|
console.log(arguments);
|
||||||
}
|
arg[0].should.deep.equal('processed');
|
||||||
);
|
done();
|
||||||
arg[0].should.deep.equal({a: 'b'});
|
});
|
||||||
done();
|
|
||||||
});
|
|
||||||
|
|
||||||
dataCall.emit('data', element);
|
dataCall.emit('data', element);
|
||||||
dataCall.emit('end');
|
dataCall.emit('end');
|
||||||
@ -158,107 +161,203 @@ describe('AddressService', function() {
|
|||||||
var tip = {
|
var tip = {
|
||||||
height: 10
|
height: 10
|
||||||
};
|
};
|
||||||
var allOutputs = [
|
var allOutputs = [{
|
||||||
{
|
satoshis: 10,
|
||||||
|
txId: 'A',
|
||||||
|
outputIndex: 1,
|
||||||
|
heightConfirmed: 1
|
||||||
|
}];
|
||||||
|
|
||||||
|
it('calculates balance correctly for confirmed balance', function() {
|
||||||
|
var allOutputs = [{
|
||||||
satoshis: 10,
|
satoshis: 10,
|
||||||
txId: 'A',
|
txId: 'A',
|
||||||
outputIndex: 1,
|
outputIndex: 1,
|
||||||
heightConfirmed: 1
|
heightConfirmed: 1
|
||||||
}
|
}];
|
||||||
];
|
|
||||||
|
|
||||||
it('calculates balance correctly for confirmed balance', function() {
|
|
||||||
var allOutputs = [ { satoshis: 10, txId: 'A', outputIndex: 1, heightConfirmed: 1 } ];
|
|
||||||
var spendOutputs = [];
|
var spendOutputs = [];
|
||||||
|
|
||||||
service.buildAddressSummary(address, tip, allOutputs, spendOutputs).should.deep.equal({
|
service.buildAddressSummary(address, tip, allOutputs, spendOutputs).should.deep.equal({
|
||||||
address: address.toString(),
|
address: address.toString(),
|
||||||
transactions: ['A'],
|
transactions: ['A'],
|
||||||
confirmed: { balance: 10, sent: 0, received: 10 },
|
confirmed: {
|
||||||
unconfirmed: { balance: 10, sent: 0, received: 10 }
|
balance: 10,
|
||||||
|
sent: 0,
|
||||||
|
received: 10
|
||||||
|
},
|
||||||
|
unconfirmed: {
|
||||||
|
balance: 10,
|
||||||
|
sent: 0,
|
||||||
|
received: 10
|
||||||
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('calculates balance correctly for unconfirmed balance', function() {
|
it('calculates balance correctly for unconfirmed balance', function() {
|
||||||
var allOutputs = [
|
var allOutputs = [{
|
||||||
{ satoshis: 20, txId: 'B', outputIndex: 1, heightConfirmed: 10 }
|
satoshis: 20,
|
||||||
];
|
txId: 'B',
|
||||||
var spendOutputs = [ ];
|
outputIndex: 1,
|
||||||
|
heightConfirmed: 10
|
||||||
|
}];
|
||||||
|
var spendOutputs = [];
|
||||||
|
|
||||||
service.buildAddressSummary(address, tip, allOutputs, spendOutputs).should.deep.equal({
|
service.buildAddressSummary(address, tip, allOutputs, spendOutputs).should.deep.equal({
|
||||||
address: address.toString(),
|
address: address.toString(),
|
||||||
transactions: ['B'],
|
transactions: ['B'],
|
||||||
confirmed: { balance: 0, sent: 0, received: 0 },
|
confirmed: {
|
||||||
unconfirmed: { balance: 20, sent: 0, received: 20 }
|
balance: 0,
|
||||||
|
sent: 0,
|
||||||
|
received: 0
|
||||||
|
},
|
||||||
|
unconfirmed: {
|
||||||
|
balance: 20,
|
||||||
|
sent: 0,
|
||||||
|
received: 20
|
||||||
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('works with multiple transactions', function() {
|
it('works with multiple transactions', function() {
|
||||||
var allOutputs = [
|
var allOutputs = [{
|
||||||
{ satoshis: 10, txId: 'A', outputIndex: 1, heightConfirmed: 1 },
|
satoshis: 10,
|
||||||
{ satoshis: 20, txId: 'B', outputIndex: 1, heightConfirmed: 10 }
|
txId: 'A',
|
||||||
];
|
outputIndex: 1,
|
||||||
var spendOutputs = [
|
heightConfirmed: 1
|
||||||
{ spendInput: { prevTxId: 'A', outputIndex: 1 }, spentTx: 'A', heightSpent: 10 }
|
}, {
|
||||||
];
|
satoshis: 20,
|
||||||
|
txId: 'B',
|
||||||
|
outputIndex: 1,
|
||||||
|
heightConfirmed: 10
|
||||||
|
}];
|
||||||
|
var spendOutputs = [{
|
||||||
|
spendInput: {
|
||||||
|
prevTxId: 'A',
|
||||||
|
outputIndex: 1
|
||||||
|
},
|
||||||
|
spentTx: 'A',
|
||||||
|
heightSpent: 10
|
||||||
|
}];
|
||||||
|
|
||||||
service.buildAddressSummary(address, tip, allOutputs, spendOutputs).should.deep.equal({
|
service.buildAddressSummary(address, tip, allOutputs, spendOutputs).should.deep.equal({
|
||||||
address: address.toString(),
|
address: address.toString(),
|
||||||
transactions: ['A', 'B'],
|
transactions: ['A', 'B'],
|
||||||
confirmed: { balance: 10, sent: 0, received: 10 },
|
confirmed: {
|
||||||
unconfirmed: { balance: 20, sent: 10, received: 30 }
|
balance: 10,
|
||||||
|
sent: 0,
|
||||||
|
received: 10
|
||||||
|
},
|
||||||
|
unconfirmed: {
|
||||||
|
balance: 20,
|
||||||
|
sent: 10,
|
||||||
|
received: 30
|
||||||
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('works with a medium amount of transactions', function() {
|
it('works with a medium amount of transactions', function() {
|
||||||
var allOutputs = [
|
var allOutputs = [{
|
||||||
{ satoshis: 10, txId: 'A', outputIndex: 1, heightConfirmed: 1 },
|
satoshis: 10,
|
||||||
{ satoshis: 20, txId: 'B', outputIndex: 1, heightConfirmed: 5 },
|
txId: 'A',
|
||||||
{ satoshis: 30, txId: 'C', outputIndex: 1, heightConfirmed: 10 }
|
outputIndex: 1,
|
||||||
];
|
heightConfirmed: 1
|
||||||
var spendOutputs = [
|
}, {
|
||||||
{ spendInput: { prevTxId: 'A', outputIndex: 1 }, spentTx: 'D', heightSpent: 10 }
|
satoshis: 20,
|
||||||
];
|
txId: 'B',
|
||||||
|
outputIndex: 1,
|
||||||
|
heightConfirmed: 5
|
||||||
|
}, {
|
||||||
|
satoshis: 30,
|
||||||
|
txId: 'C',
|
||||||
|
outputIndex: 1,
|
||||||
|
heightConfirmed: 10
|
||||||
|
}];
|
||||||
|
var spendOutputs = [{
|
||||||
|
spendInput: {
|
||||||
|
prevTxId: 'A',
|
||||||
|
outputIndex: 1
|
||||||
|
},
|
||||||
|
spentTx: 'D',
|
||||||
|
heightSpent: 10
|
||||||
|
}];
|
||||||
|
|
||||||
service.buildAddressSummary(address, tip, allOutputs, spendOutputs).should.deep.equal({
|
service.buildAddressSummary(address, tip, allOutputs, spendOutputs).should.deep.equal({
|
||||||
address: address.toString(),
|
address: address.toString(),
|
||||||
transactions: ['A', 'B', 'C', 'D'],
|
transactions: ['A', 'B', 'C', 'D'],
|
||||||
confirmed: { balance: 30, sent: 0, received: 30 },
|
confirmed: {
|
||||||
unconfirmed: { balance: 50, sent: 10, received: 60 }
|
balance: 30,
|
||||||
|
sent: 0,
|
||||||
|
received: 30
|
||||||
|
},
|
||||||
|
unconfirmed: {
|
||||||
|
balance: 50,
|
||||||
|
sent: 10,
|
||||||
|
received: 60
|
||||||
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('works with a transaction that includes twice the same address', function() {
|
it('works with a transaction that includes twice the same address', function() {
|
||||||
var allOutputs = [
|
var allOutputs = [{
|
||||||
{ satoshis: 10, txId: 'A', outputIndex: 0, heightConfirmed: 1 },
|
satoshis: 10,
|
||||||
{ satoshis: 10, txId: 'A', outputIndex: 1, heightConfirmed: 1 },
|
txId: 'A',
|
||||||
];
|
outputIndex: 0,
|
||||||
|
heightConfirmed: 1
|
||||||
|
}, {
|
||||||
|
satoshis: 10,
|
||||||
|
txId: 'A',
|
||||||
|
outputIndex: 1,
|
||||||
|
heightConfirmed: 1
|
||||||
|
}, ];
|
||||||
var spendOutputs = [];
|
var spendOutputs = [];
|
||||||
|
|
||||||
service.buildAddressSummary(address, tip, allOutputs, spendOutputs).should.deep.equal({
|
service.buildAddressSummary(address, tip, allOutputs, spendOutputs).should.deep.equal({
|
||||||
address: address.toString(),
|
address: address.toString(),
|
||||||
transactions: ['A'],
|
transactions: ['A'],
|
||||||
confirmed: { balance: 20, sent: 0, received: 20 },
|
confirmed: {
|
||||||
unconfirmed: { balance: 20, sent: 0, received: 20 }
|
balance: 20,
|
||||||
|
sent: 0,
|
||||||
|
received: 20
|
||||||
|
},
|
||||||
|
unconfirmed: {
|
||||||
|
balance: 20,
|
||||||
|
sent: 0,
|
||||||
|
received: 20
|
||||||
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('confirmed spent transactions change the balance', function() {
|
it('confirmed spent transactions change the balance', function() {
|
||||||
var allOutputs = [
|
var allOutputs = [{
|
||||||
{ satoshis: 10, txId: 'A', outputIndex: 0, heightConfirmed: 1 },
|
satoshis: 10,
|
||||||
];
|
txId: 'A',
|
||||||
var spendOutputs = [
|
outputIndex: 0,
|
||||||
{ spendInput: { prevTxId: 'A', outputIndex: 0 }, spentTx: 'D', heightSpent: 2 }
|
heightConfirmed: 1
|
||||||
];
|
}, ];
|
||||||
|
var spendOutputs = [{
|
||||||
|
spendInput: {
|
||||||
|
prevTxId: 'A',
|
||||||
|
outputIndex: 0
|
||||||
|
},
|
||||||
|
spentTx: 'D',
|
||||||
|
heightSpent: 2
|
||||||
|
}];
|
||||||
|
|
||||||
service.buildAddressSummary(address, tip, allOutputs, spendOutputs).should.deep.equal({
|
service.buildAddressSummary(address, tip, allOutputs, spendOutputs).should.deep.equal({
|
||||||
address: address.toString(),
|
address: address.toString(),
|
||||||
transactions: ['A', 'D'],
|
transactions: ['A', 'D'],
|
||||||
confirmed: { balance: 0, sent: 10, received: 10 },
|
confirmed: {
|
||||||
unconfirmed: { balance: 0, sent: 10, received: 10 }
|
balance: 0,
|
||||||
|
sent: 10,
|
||||||
|
received: 10
|
||||||
|
},
|
||||||
|
unconfirmed: {
|
||||||
|
balance: 0,
|
||||||
|
sent: 10,
|
||||||
|
received: 10
|
||||||
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user