bestBlockHeight set by node now. Less cb Hell.
This commit is contained in:
parent
1cb0a6b385
commit
3e7f263e18
@ -11,60 +11,53 @@ module.exports = function transactionAPI(router) {
|
||||
// Txs by txid
|
||||
router.get('/tx/:txid', (req, res) => {
|
||||
// Get max block height for calculating confirmations
|
||||
db.blocks.getBestHeight(
|
||||
(err, blockHeight) => {
|
||||
if (err) {
|
||||
logger.log('err', err);
|
||||
const height = db.blocks.bestHeight();
|
||||
// Bcoin transaction data
|
||||
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();
|
||||
}
|
||||
const height = blockHeight;
|
||||
// Bcoin transaction data
|
||||
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',
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@ -78,126 +71,111 @@ module.exports = function transactionAPI(router) {
|
||||
const rangeEnd = rangeStart + MAX_TXS;
|
||||
// get txs for blockhash, start with best height to calc confirmations
|
||||
if (req.query.block) {
|
||||
db.blocks.getBestHeight(
|
||||
(err, blockHeight) => {
|
||||
if (err) {
|
||||
logger.log('err', err);
|
||||
|
||||
const height = db.blocks.bestHeight();
|
||||
// Get Bcoin data
|
||||
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();
|
||||
}
|
||||
const height = blockHeight;
|
||||
// Get Bcoin data
|
||||
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();
|
||||
}
|
||||
|
||||
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);
|
||||
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',
|
||||
})),
|
||||
});
|
||||
});
|
||||
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',
|
||||
})),
|
||||
});
|
||||
});
|
||||
} else if (req.query.address) {
|
||||
// Get txs by address, start with best height to calc confirmations
|
||||
db.blocks.getBestHeight(
|
||||
(err, blockHeight) => {
|
||||
if (err) {
|
||||
logger.log('err', err);
|
||||
const height = db.blocks.bestHeight();
|
||||
const addr = req.query.address || '';
|
||||
|
||||
logger.log('debug',
|
||||
'Warning: Requesting data from Bcoin by address, 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();
|
||||
}
|
||||
|
||||
const height = blockHeight;
|
||||
const addr = req.query.address || '';
|
||||
|
||||
logger.log('debug',
|
||||
'Warning: Requesting data from Bcoin by address, 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',
|
||||
})),
|
||||
});
|
||||
});
|
||||
// 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',
|
||||
})),
|
||||
});
|
||||
});
|
||||
} else {
|
||||
// Get last n txs
|
||||
return res.status(404).send({ error: 'Block hash or address expected' });
|
||||
}
|
||||
// Get last n txs
|
||||
return res.status(404).send({ error: 'Block hash or address expected' });
|
||||
});
|
||||
|
||||
router.get('/rawtx/:txid', (req, res) => {
|
||||
|
||||
@ -4,6 +4,8 @@ const config = require('../../config');
|
||||
|
||||
const MAX_BLOCKS = config.api.max_blocks; // ~ 12 hours
|
||||
|
||||
let bestBlockHeight = 0;
|
||||
|
||||
function getBlocks(params, options, limit, cb) {
|
||||
// Do not return mongo ids
|
||||
const defaultOptions = { _id: 0 };
|
||||
@ -54,20 +56,31 @@ function getBlock(params, options, limit, cb) {
|
||||
return cb(null, blocks[0]);
|
||||
});
|
||||
}
|
||||
// Highest known height
|
||||
function getBestHeight(cb) {
|
||||
// Highest known height in mongo
|
||||
function getBestHeight() {
|
||||
getBlock({}, {}, 1, (err, block) => {
|
||||
if (err) {
|
||||
logger.log('error',
|
||||
`getBlock: ${err.err}`);
|
||||
return cb(err, null);
|
||||
`getBestHeight: ${err.err}`);
|
||||
return;
|
||||
}
|
||||
return cb(null, block.height);
|
||||
bestBlockHeight = block.height;
|
||||
});
|
||||
}
|
||||
// 1e9 limit = ~2M years from now
|
||||
// Mostly for sync to set height
|
||||
function bestHeight(height) {
|
||||
if (Number.isInteger(height) &&
|
||||
height > 0 &&
|
||||
height < 1 * 1e9) {
|
||||
bestBlockHeight = height;
|
||||
return bestBlockHeight;
|
||||
}
|
||||
return bestBlockHeight;
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
getBlock,
|
||||
getBlocks,
|
||||
getBestHeight,
|
||||
bestHeight,
|
||||
};
|
||||
|
||||
@ -2,6 +2,9 @@ const Transactions = require('../../models/transaction.js');
|
||||
const logger = require('../logger');
|
||||
const config = require('../../config');
|
||||
|
||||
// For now, blocks handles these calls.
|
||||
// These will be replaced with more advanced mongo
|
||||
|
||||
const MAX_TXS = config.api.max_txs;
|
||||
|
||||
function getTransactions(params, options, limit, cb) {
|
||||
@ -26,7 +29,6 @@ function getTransactions(params, options, limit, cb) {
|
||||
params,
|
||||
defaultOptions,
|
||||
(err, txs) => {
|
||||
console.log(txs)
|
||||
if (err) {
|
||||
logger.log('error',
|
||||
`getTransactions: ${err}`);
|
||||
|
||||
@ -3,6 +3,7 @@ const logger = require('../../lib/logger');
|
||||
const BlockParser = require('../parser').Block;
|
||||
const config = require('../../config');
|
||||
const socket = require('../../lib/api/socket');
|
||||
const db = require('../../lib/db');
|
||||
|
||||
const node = new FullNode(config.bcoin);
|
||||
|
||||
@ -18,6 +19,7 @@ function start() {
|
||||
node.chain.on('connect', (entry, block) => {
|
||||
BlockParser.parse(entry, block);
|
||||
socket.processBlock(entry, block);
|
||||
db.blocks.bestHeight(entry.height);
|
||||
});
|
||||
|
||||
node.on('error', (err) => {
|
||||
|
||||
Loading…
Reference in New Issue
Block a user