final polish

This commit is contained in:
Manuel Araoz 2015-04-30 08:45:48 -03:00
parent 46420b7930
commit 85ad9fcdb6
6 changed files with 125 additions and 37 deletions

View File

@ -1791,14 +1791,95 @@ Transaction broadcasted successfully
```
### Output routes
####GET '/v1/transactions/:txHash([A-Fa-f0-9]{64})/outputs'
####GET '/v1/transactions/:txHash([A-Fa-f0-9]{64})/outputs/:index([0-9]+)'
####GET '/v1/transactions/2ceea8fb53873ae3f61fb332bf844e5a35630a1a4885a212f84f63f39c638b5e/outputs'
```
[
{
"satoshis": 47203800,
"script": "OP_DUP OP_HASH160 20 0x7c8fe8004e1dfdf0826f357de9ff93db25a8239d OP_EQUALVERIFY OP_CHECKSIG"
},
{
"satoshis": 9490000,
"script": "OP_DUP OP_HASH160 20 0xbf158227da5604c112bdf5af744f30bb7e85c7bf OP_EQUALVERIFY OP_CHECKSIG"
}
]
```
####GET '/v1/transactions/2ceea8fb53873ae3f61fb332bf844e5a35630a1a4885a212f84f63f39c638b5e/outputs/1'
```
{
"satoshis": 9490000,
"script": "OP_DUP OP_HASH160 20 0xbf158227da5604c112bdf5af744f30bb7e85c7bf OP_EQUALVERIFY OP_CHECKSIG"
}
```
### Address routes
####GET '/v1/addresses/:address'
####GET '/v1/addresses/:address/transactions'
####GET '/v1/addresses/:addresses/utxos'
####GET '/v1/addresses/msWN7CbKLWh88P1Vr8pQa7DmZNSiy9xfkj'
```
{
"address": "mtBHBTKTZv74cytccymVq3weidcoy4o1UY",
"transactions": [
"88c844570a227fe89d82e4e20d41576b95df8aa790a799bf7114dbed83b788b0",
"d1cd5072cf4f6bff12e46a1e7949e58b544abed969313d65263141b9c94221cd"
],
"confirmed": {
"balance": 0,
"sent": 4900642709,
"received": 4900642709
},
"unconfirmed": {
"balance": 0,
"sent": 4900642709,
"received": 4900642709
}
}
```
####GET '/v1/addresses/:addresses/utxos'
```
[
{
"satoshis": 967008,
"script": "OP_DUP OP_HASH160 20 0x0b4322ac01719030a710b60b0a3397c074cf9edf OP_EQUALVERIFY OP_CHECKSIG",
"heightConfirmed": 410,
"address": "mgYW9pHcxjUSvqHwaJF48uFbrDfFoPAcjx",
"txId": "0c233e2730cb94dc85e32546060c2361d348921961ab957ae66acadf88a578f1",
"outputIndex": "1"
},
{
"satoshis": 568367,
"script": "OP_DUP OP_HASH160 20 0x0b4322ac01719030a710b60b0a3397c074cf9edf OP_EQUALVERIFY OP_CHECKSIG",
"heightConfirmed": 417,
"address": "mgYW9pHcxjUSvqHwaJF48uFbrDfFoPAcjx",
"txId": "0ca394ce3c2feecb2957b3aa5ecdc964f706e0b4ceec96bfc1ace526a80c67d1",
"outputIndex": "1"
},
{
"satoshis": 977315,
"script": "OP_DUP OP_HASH160 20 0x0b4322ac01719030a710b60b0a3397c074cf9edf OP_EQUALVERIFY OP_CHECKSIG",
"heightConfirmed": 421,
"address": "mgYW9pHcxjUSvqHwaJF48uFbrDfFoPAcjx",
"txId": "96bdd67bd1b80f70acc7cca454c5ca80cfc8ba621e0e93756c406977102b586a",
"outputIndex": "1"
},
{
"satoshis": 496223,
"script": "OP_DUP OP_HASH160 20 0x0b4322ac01719030a710b60b0a3397c074cf9edf OP_EQUALVERIFY OP_CHECKSIG",
"heightConfirmed": 420,
"address": "mgYW9pHcxjUSvqHwaJF48uFbrDfFoPAcjx",
"txId": "97d561085af6041e2b570dd07d4ee8b49a2d5667776f2112fac611727f949b3b",
"outputIndex": "1"
},
{
"satoshis": 123667,
"script": "OP_DUP OP_HASH160 20 0x0b4322ac01719030a710b60b0a3397c074cf9edf OP_EQUALVERIFY OP_CHECKSIG",
"heightConfirmed": 405,
"address": "mgYW9pHcxjUSvqHwaJF48uFbrDfFoPAcjx",
"txId": "e72f781efc41224cf37d1aa0c63fa4655a86b647233622e653b38eb3d379b1cc",
"outputIndex": "1"
}
]
```
## License

View File

@ -23,7 +23,7 @@ Addresses.setNode = function(aNode) {
* Finds an address' info by it's string representation
*/
Addresses.addressParam = function(req, res, next, address) {
if (!Address.isValid(address)) {
if (!Address.isValid(address, bitcore.Networks.defaultNetwork)) {
res.status(422);
res.send('/v1/addresses/ parameter must be a valid bitcoin address');
return;
@ -76,7 +76,7 @@ Addresses.utxos = function(req, res) {
$.checkState(_.all(req.addresses, function(addr) {
return addr instanceof Address;
}));
node.getUTXOs(req.addresses)
node.addressService.getUnspent(req.addresses)
.then(function(utxos) {
res.send(utxos);
});

View File

@ -87,18 +87,6 @@ Transactions.send = function(req, res) {
};
/*
* Returns a list of transactions given certain request options
*/
Transactions.list = function(req, res) {
var opts = {};
opts.address = req.address;
node.listTransactions(opts)
.then(function(transactions) {
res.send(transactions);
});
};
var buildIOHelper = function(name) {
$.checkArgument(name === 'inputs' || name === 'outputs');

View File

@ -44,7 +44,6 @@ function initRouter(node) {
// Address routes
router.get('/addresses/:address', Addresses.get);
router.get('/addresses/:address/transactions', Transactions.list);
router.get('/addresses/:addresses/utxos', Addresses.utxos);
// error routes

View File

@ -5,6 +5,7 @@ var bitcore = require('bitcore');
var TransactionService = require('./transaction');
var RPC = require('bitcoind-rpc');
var _ = bitcore.deps._;
var $ = bitcore.util.preconditions;
var NULLTXHASH = bitcore.util.buffer.emptyBuffer(32).toString('hex');
var LASTTXHASH = bitcore.util.buffer.fill(bitcore.util.buffer.emptyBuffer(32), -1).toString('hex');
@ -56,6 +57,7 @@ AddressService.processOutput = function(data) {
var retrieveOutputs = function(indexFunction, processElement) {
return function(address) {
$.checkArgument(address, 'address required');
var results = [];
var self = this;
@ -81,11 +83,44 @@ AddressService.prototype.getAllOutputs = retrieveOutputs(
AddressService.prototype.getSpent = retrieveOutputs(
TransactionService.Index.getSpentOutputsForAddress,
function(element) {
return JSON.parse(element.value);
function(e) {
return AddressService.processOutput(e);
}
);
AddressService.prototype.getUnspent = function(addrs) {
$.checkArgument(addrs, 'addresses required');
$.checkArgument(_.isArray(addrs), 'addresses is array required');
var self = this;
return Promise.all(addrs.map(function(addr) {
return self.getUnspentForAddress(addr);
}))
.then(function(results) {
return _.flatten(results);
});
};
AddressService.prototype.getUnspentForAddress = function(addr) {
$.checkArgument(addr, 'address required');
var all, spent;
var self = this;
return this.getAllOutputs(addr)
.then(function(s) {
all = s;
return self.getSpent(addr);
})
.then(function(s) {
spent = s;
return _.filter(all, function(out) {
return !_.contains(spent, out);
});
});
};
AddressService.prototype.buildAddressSummary = function(address, tip, allOutputs, spent, confirmations) {
var result = {};

View File

@ -206,8 +206,6 @@ BlockService.prototype.listBlocks = function(from, to, offset, limit) {
var start = from + offset;
var end = Math.min(to, start + limit);
var blocks = [];
//console.log(from, to, offset, limit);
//console.log(start, end);
// TODO: optimize: precompute heights and fetch all blocks in parallel?
var fetchBlock = function(height) {
if (height >= end) {
@ -284,37 +282,27 @@ BlockService.prototype.confirm = function(block, ops) {
ops = ops || [];
//console.log(0);
return Promise.try(function() {
//console.log(0.5);
self._setHeader(ops, block);
//console.log(1);
self._setNextBlock(ops, block.header.prevHash, block);
//console.log(3);
self._setBlockHeight(ops, block);
//console.log(3);
self._setBlockWork(ops, block);
//console.log(4);
self._setBlockByTs(ops, block);
//console.log(4.1);
self._setTip(ops, block);
//console.log(5);
return Promise.all(block.transactions.map(function(transaction) {
return self.transactionService._confirmTransaction(ops, block, transaction);
}));
})
.then(function() {
//console.log(6);
return self.database.batchAsync(ops);
})
.then(function() {
//console.log(7);
return block;
});
};
@ -373,17 +361,14 @@ BlockService.prototype._setBlockByTs = function(ops, block) {
/*
var self = this;
var key = Index.timestamp + block.header.time;
console.log('key', key);
return Promise.try(function() {
console.log('a');
return self.database.getAsync(key);
})
.then(function(result) {
console.log('b');
if (result === block.hash) {
return Promise.resolve();
} else {