diff --git a/server/config/index.js b/server/config/index.js index 827006d..4c45558 100644 --- a/server/config/index.js +++ b/server/config/index.js @@ -4,7 +4,7 @@ const config = { bcoin_http: 'localhost', bcoin: { network: 'main', - db: 'mem', + db: 'leveldb', prefix: '.', checkpoints: true, workers: false, diff --git a/server/lib/api/transaction.js b/server/lib/api/transaction.js index c834902..535ada3 100644 --- a/server/lib/api/transaction.js +++ b/server/lib/api/transaction.js @@ -13,65 +13,50 @@ module.exports = function transactionAPI(router) { // Get max block height for calculating confirmations 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 txid = req.params.txid || ''; - // 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', - }); + db.blocks.getTxById(txid, (err, transaction) => { + if (err) { + logger.log('err', + `getTxById: ${err}`); + return err; + } + const tx = transaction; + 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', }); + }); }); // /txs is overloaded. Next ver separate concerns // query by block // query by address - // last n txs + // last n txs - haha jk YOU 404 router.get('/txs', (req, res) => { const pageNum = parseInt(req.query.pageNum, 10) || 0; const rangeStart = pageNum * MAX_TXS; const rangeEnd = rangeStart + MAX_TXS; // get txs for blockhash, start with best height to calc confirmations if (req.query.block) { - const height = db.blocks.bestHeight(); // Get Bcoin data return request(`${API_URL}/block/${req.query.block}`, diff --git a/server/lib/db/blocks.js b/server/lib/db/blocks.js index 5659d34..0cdba0c 100644 --- a/server/lib/db/blocks.js +++ b/server/lib/db/blocks.js @@ -6,6 +6,8 @@ const MAX_BLOCKS = config.api.max_blocks; // ~ 12 hours let bestBlockHeight = 0; +// This naive querying will be replaced by more advanced mongo + function getBlocks(params, options, limit, cb) { // Do not return mongo ids const defaultOptions = { _id: 0 }; @@ -56,7 +58,7 @@ function getBlock(params, options, limit, cb) { return cb(null, blocks[0]); }); } -// Highest known height in mongo +// Highest known height in mongo - Not Used function getBestHeight() { getBlock({}, {}, 1, (err, block) => { if (err) { @@ -79,8 +81,25 @@ function bestHeight(height) { return bestBlockHeight; } +function getTxById(txid, cb) { + getBlock( + { 'txs.hash': txid }, + {}, + 1, + (err, block) => { + if (err) { + logger.log('err', + `/rawblock/:blockHash: ${err}`); + return cb(err); + } + const transaction = block.txs.filter(tx => tx.hash === txid).reduce(a => a[0]); + return cb(null, transaction); + }); +} + module.exports = { getBlock, getBlocks, bestHeight, + getTxById, }; diff --git a/server/lib/parser/block.js b/server/lib/parser/block.js index b19b2b9..34b3d3d 100644 --- a/server/lib/parser/block.js +++ b/server/lib/parser/block.js @@ -23,11 +23,13 @@ function parse(entry, block) { nonce: blockJSON.nonce, txs: block.txs.map((tx) => { const txJSON = tx.toJSON(); + const txRAW = tx.toRaw(); return { hash: txJSON.hash, witnessHash: txJSON.witnessHash, fee: txJSON.fee, rate: txJSON.rate, + size: txRAW.length, ps: txJSON.ps, height: entry.height, block: util.revHex(entry.hash), @@ -71,6 +73,13 @@ function parse(entry, block) { } }); } +// Fill in behind blocks and update tx inputs +function updateInputs(txid, address) { + // Use txid and output address to get value + // Get addr / value from prev out + // update input + +} module.exports = { parse, diff --git a/server/models/input.js b/server/models/input.js index a6ebc1b..dc29b43 100644 --- a/server/models/input.js +++ b/server/models/input.js @@ -3,6 +3,7 @@ const mongoose = require('mongoose'); const Schema = mongoose.Schema; const InputSchema = new Schema({ + value: { type: Number, default: 0 }, prevout: { type: Object, default: {} }, script: { type: String, default: '' }, witness: { type: String, default: '' },