From 2ac70bc9a2176b0a5f817bc4526ffb71eefc8a2b Mon Sep 17 00:00:00 2001 From: tenthirtyone Date: Wed, 16 Aug 2017 16:30:33 -0400 Subject: [PATCH] Fixed Bcoin error returned as data, fixed dead /txs endpoint missing error, added ttl to bcoin requests but large addrs still take too long --- server/config/index.js | 1 + server/lib/api/address.js | 2 + server/lib/api/transaction.js | 289 ++++++++++++++++------------------ server/lib/db/blocks.js | 3 +- server/lib/db/transactions.js | 1 + 5 files changed, 141 insertions(+), 155 deletions(-) diff --git a/server/config/index.js b/server/config/index.js index 2dd1526..4c45558 100644 --- a/server/config/index.js +++ b/server/config/index.js @@ -29,6 +29,7 @@ const config = { ticker_prop: 'bitstamp', max_blocks: 72, max_txs: 10, + request_ttl: 100000, }, }; diff --git a/server/lib/api/address.js b/server/lib/api/address.js index ed0cab9..6359400 100644 --- a/server/lib/api/address.js +++ b/server/lib/api/address.js @@ -3,12 +3,14 @@ const request = require('request'); const config = require('../../config'); const API_URL = `http://${config.bcoin_http}:${config.bcoin['http-port']}`; +const TTL = config.api.request_ttl; module.exports = function AddressAPI(router) { router.get('/addr/:addr', (req, res) => { const addr = req.params.addr || ''; // Get Bcoin data return request(`${API_URL}/tx/address/${addr}`, + { timeout: TTL }, (error, bcoinRes, bcoinTxs) => { if (error) { logger.log('error', diff --git a/server/lib/api/transaction.js b/server/lib/api/transaction.js index fb79b87..6948402 100644 --- a/server/lib/api/transaction.js +++ b/server/lib/api/transaction.js @@ -5,6 +5,7 @@ const db = require('../db'); const API_URL = `http://${config.bcoin_http}:${config.bcoin['http-port']}`; const MAX_TXS = config.api.max_txs; +const TTL = config.api.request_ttl; module.exports = function transactionAPI(router) { // Txs by txid @@ -18,50 +19,52 @@ module.exports = function transactionAPI(router) { } const height = blockHeight; // Bcoin transaction data - return request(`${API_URL}/tx/${req.params.txid}`, (error, localRes, tx) => { - if (error) { - logger.log('error', - `${error}`); - return res.status(404).send(); - } - // Catch JSON errors - try { - tx = JSON.parse(tx); - } catch (e) { - logger.log('error', - `${e}`); - return res.status(404).send(); - } - if (!tx || !tx.hash) { - logger.log('error', - 'No results found'); - return res.status(404).send(); - } + return request(`${API_URL}/tx/${req.params.txid}`, + { timeout: TTL }, + (error, localRes, tx) => { + if (error) { + logger.log('error', + `${error}`); + return res.status(404).send(); + } + // Catch JSON errors + try { + tx = JSON.parse(tx); + } catch (e) { + logger.log('error', + `${e}`); + return res.status(404).send(); + } + if (!tx || !tx.hash) { + logger.log('error', + 'No results found'); + return res.status(404).send(); + } - // Return UI JSON - return res.send({ - txid: tx.hash, - version: tx.version, - time: tx.ps, - blocktime: tx.ps, - locktime: tx.locktime, - blockhash: tx.block, - fees: tx.fee / 1e8, - confirmations: (height - tx.height) + 1, - valueOut: tx.outputs.reduce((sum, output) => sum + output.value, 0) / 1e8, - vin: tx.inputs.map(input => ({ - addr: input.coin ? input.coin.address : '', - value: input.coin ? input.coin.value / 1e8 : 0, - })), - vout: tx.outputs.map(output => ({ - scriptPubKey: { - addresses: [output.address], - }, - value: output.value / 1e8, - })), - isCoinBase: tx.inputs[0].prevout.hash === '0000000000000000000000000000000000000000000000000000000000000000', + // Return UI JSON + return res.send({ + txid: tx.hash, + version: tx.version, + time: tx.ps, + blocktime: tx.ps, + locktime: tx.locktime, + blockhash: tx.block, + fees: tx.fee / 1e8, + confirmations: (height - tx.height) + 1, + valueOut: tx.outputs.reduce((sum, output) => sum + output.value, 0) / 1e8, + vin: tx.inputs.map(input => ({ + addr: input.coin ? input.coin.address : '', + value: input.coin ? input.coin.value / 1e8 : 0, + })), + vout: tx.outputs.map(output => ({ + scriptPubKey: { + addresses: [output.address], + }, + value: output.value / 1e8, + })), + isCoinBase: tx.inputs[0].prevout.hash === '0000000000000000000000000000000000000000000000000000000000000000', + }); }); - }); }); }); @@ -83,49 +86,53 @@ module.exports = function transactionAPI(router) { } const height = blockHeight; // Get Bcoin data - return request(`${API_URL}/block/${req.query.block}`, (error, localRes, block) => { - if (error) { - logger.log('error', - `${error}`); - } - // Catch JSON errors - try { - block = JSON.parse(block); - } catch (e) { - logger.log('error', - `${e}`); - return res.status(404).send(); - } - if (!block.txs.length) { - logger.log('error', - `${'No tx results'}`); - res.status(404).send(); - } - // Setup UI JSON - const totalPages = Math.ceil(block.txs.length / MAX_TXS); - block.txs = block.txs.slice(rangeStart, rangeEnd); + return request(`${API_URL}/block/${req.query.block}`, + { timeout: TTL }, + (error, localRes, block) => { + if (error) { + logger.log('error', + `${error}`); + return res.status(404).send(); + } + // Catch JSON errors + try { + block = JSON.parse(block); + } catch (e) { + logger.log('error', + `${e}`); + return res.status(404).send(); + } - return res.send({ - pagesTotal: totalPages, - txs: block.txs.map(tx => ({ - txid: tx.hash, - fees: tx.fee / 1e8, - confirmations: (height - block.height) + 1, - valueOut: tx.outputs.reduce((sum, output) => sum + output.value, 0) / 1e8, - vin: tx.inputs.map(input => ({ - addr: input.coin ? input.coin.address : '', - value: input.coin ? input.coin.value / 1e8 : 0, + if (block.error) { + logger.log('error', + `${'No tx results'}`); + return res.status(404).send(); + } + // Setup UI JSON + const totalPages = Math.ceil(block.txs.length / MAX_TXS); + block.txs = block.txs.slice(rangeStart, rangeEnd); + + return res.send({ + pagesTotal: totalPages, + txs: block.txs.map(tx => ({ + txid: tx.hash, + fees: tx.fee / 1e8, + confirmations: (height - block.height) + 1, + valueOut: tx.outputs.reduce((sum, output) => sum + output.value, 0) / 1e8, + vin: tx.inputs.map(input => ({ + addr: input.coin ? input.coin.address : '', + value: input.coin ? input.coin.value / 1e8 : 0, + })), + vout: tx.outputs.map(output => ({ + scriptPubKey: { + addresses: [output.address], + }, + value: output.value / 1e8, + })), + isCoinBase: tx.inputs[0].prevout.hash === '0000000000000000000000000000000000000000000000000000000000000000', })), - vout: tx.outputs.map(output => ({ - scriptPubKey: { - addresses: [output.address], - }, - value: output.value / 1e8, - })), - isCoinBase: tx.inputs[0].prevout.hash === '0000000000000000000000000000000000000000000000000000000000000000', - })), + }); }); - }); }); } else if (req.query.address) { // Get txs by address, start with best height to calc confirmations @@ -139,83 +146,57 @@ module.exports = function transactionAPI(router) { const height = blockHeight; const addr = req.query.address || ''; - return request(`${API_URL}/tx/address/${addr}`, (error, localRes, txs) => { - if (error) { - logger.log('error', - `${error}`); - return res.status(404).send(); - } - // Catch JSON errors - try { - txs = JSON.parse(txs); - } catch (e) { - logger.log('error', - `${e}`); - return res.status(404).send(); - } - // Setup UI JSON - return res.send({ - pagesTotal: 1, - txs: txs.map(tx => ({ - txid: tx.hash, - fees: tx.fee / 1e8, - confirmations: (height - tx.height) + 1, - valueOut: tx.outputs.reduce((sum, output) => sum + output.value, 0) / 1e8, - vin: tx.inputs.map(input => ({ - addr: input.coin ? input.coin.address : '', - value: input.coin ? input.coin.value / 1e8 : 0, + logger.log('debug', + 'Warning: Requesting data from Bcoin, may take some time'); + + return request(`${API_URL}/tx/address/${addr}`, + { timeout: TTL }, + (error, localRes, txs) => { + if (error) { + logger.log('error', + `${error}`); + return res.status(404).send(); + } + // Catch JSON errors + try { + txs = JSON.parse(txs); + } catch (e) { + logger.log('error', + `${e}`); + return res.status(404).send(); + } + // Bcoin returns error as part of data object + if (txs.error) { + logger.log('error', + `${'No tx results'}`); + return res.status(404).send(); + } + // Setup UI JSON + return res.send({ + pagesTotal: 1, + txs: txs.map(tx => ({ + txid: tx.hash, + fees: tx.fee / 1e8, + confirmations: (height - tx.height) + 1, + valueOut: tx.outputs.reduce((sum, output) => sum + output.value, 0) / 1e8, + vin: tx.inputs.map(input => ({ + addr: input.coin ? input.coin.address : '', + value: input.coin ? input.coin.value / 1e8 : 0, + })), + vout: tx.outputs.map(output => ({ + scriptPubKey: { + addresses: [output.address], + }, + value: output.value / 1e8, + })), + isCoinBase: tx.inputs[0].prevout.hash === '0000000000000000000000000000000000000000000000000000000000000000', })), - vout: tx.outputs.map(output => ({ - scriptPubKey: { - addresses: [output.address], - }, - value: output.value / 1e8, - })), - isCoinBase: tx.inputs[0].prevout.hash === '0000000000000000000000000000000000000000000000000000000000000000', - })), + }); }); - }); }); } else { // Get last n txs - db.txs.getTransactions( - {}, - {}, - MAX_TXS, - (err, txs) => { - if (err) { - logger.log('err', - `getTransactions: ${err}`); - res.status(404).send(); - } - return res.json({ - pagesTotal: 1, - txs: txs.map(tx => ({ - txid: tx.hash, - version: tx.version, - locktime: tx.locktime, - vin: tx.inputs.map(input => ({ - coinbase: input.script, - sequence: input.sequence, - n: 0, - })), - vout: tx.outputs.map(output => ({ - value: output.value, - n: 0, - scriptPubKey: { - hex: '', - asm: '', - addresses: [output.address], - type: output.type, - }, - spentTxid: '', - spentIndex: 0, - spentHeight: 0, - })), - })), - }); - }, - ); + return res.status(404).send({ error: 'Block hash or address expected' }); } }); diff --git a/server/lib/db/blocks.js b/server/lib/db/blocks.js index d0c9a53..deb101f 100644 --- a/server/lib/db/blocks.js +++ b/server/lib/db/blocks.js @@ -21,6 +21,7 @@ function getBlocks(params, options, limit, cb) { if (limit < 1) { limit = 1; } + // Query mongo Block.find( params, @@ -59,7 +60,7 @@ function getBestHeight(cb) { if (err) { logger.log('error', `getBlock: ${err.err}`); - return cb(err); + return cb(err, null); } return cb(null, block.height); }); diff --git a/server/lib/db/transactions.js b/server/lib/db/transactions.js index 455727d..905d578 100644 --- a/server/lib/db/transactions.js +++ b/server/lib/db/transactions.js @@ -26,6 +26,7 @@ function getTransactions(params, options, limit, cb) { params, defaultOptions, (err, txs) => { + console.log(txs) if (err) { logger.log('error', `getTransactions: ${err}`);