final polish
This commit is contained in:
parent
46420b7930
commit
85ad9fcdb6
91
README.md
91
README.md
@ -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
|
||||
|
||||
@ -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);
|
||||
});
|
||||
|
||||
@ -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');
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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 = {};
|
||||
|
||||
@ -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 {
|
||||
|
||||
Loading…
Reference in New Issue
Block a user