mirror of
https://github.com/GOSTSec/gostexplr
synced 2025-02-05 19:34:26 +00:00
Jade to Pug, added Vout Ns, refactored database/pages, port in config, clean dependencies
This commit is contained in:
parent
1557733a48
commit
887c852b55
2
app.js
2
app.js
@ -16,7 +16,7 @@ var app = express();
|
|||||||
|
|
||||||
// view engine setup
|
// view engine setup
|
||||||
app.set('views', path.join(__dirname, 'views'));
|
app.set('views', path.join(__dirname, 'views'));
|
||||||
app.set('view engine', 'jade');
|
app.set('view engine', 'pug');
|
||||||
|
|
||||||
// uncomment after placing your favicon in /public
|
// uncomment after placing your favicon in /public
|
||||||
app.use(favicon(path.join(__dirname, 'public', 'favicon.ico')));
|
app.use(favicon(path.join(__dirname, 'public', 'favicon.ico')));
|
||||||
|
43
bin/createUserAndDb.js
Normal file
43
bin/createUserAndDb.js
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
#!/usr/bin/env node
|
||||||
|
var exec = require('child_process').exec;
|
||||||
|
var models = require('../models');
|
||||||
|
var env = require('../config/config.json')['env'] || 'development';
|
||||||
|
var config = require(__dirname + '/../config/config.json')['database'][env];
|
||||||
|
|
||||||
|
if (process.argv.length < 4) {
|
||||||
|
console.log('Provide root user name and password for mysql');
|
||||||
|
process.exit(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
const dropUserDB = `mysql -u${process.argv[2]} -p${process.argv[3]} -e "drop database ${config.database};drop user ${config.username}"`
|
||||||
|
const createdb = `mysql -u${process.argv[2]} -p${process.argv[3]} -e "create database ${config.database}"`;
|
||||||
|
const createUser = `mysql -u${process.argv[2]} -p${process.argv[3]} -e "create user ${config.username} identified by '${config.password}'"`;
|
||||||
|
const grantAccess = `mysql -u${process.argv[2]} -p${process.argv[3]} -e "grant all on ${config.database}.* to ${config.username}"`;
|
||||||
|
|
||||||
|
exec(dropUserDB, function(err,stdout,stderr) {
|
||||||
|
console.log(stdout);
|
||||||
|
exec(createdb, function(err,stdout,stderr) {
|
||||||
|
if (err) {
|
||||||
|
console.log(err);
|
||||||
|
process.exit(0);
|
||||||
|
} else {
|
||||||
|
console.log(stdout);
|
||||||
|
exec(createUser, function(err, stdout, stderr) {
|
||||||
|
if (err) {
|
||||||
|
console.log(err);
|
||||||
|
process.exit(0);
|
||||||
|
} else {
|
||||||
|
console.log(stdout);
|
||||||
|
exec(grantAccess, function(err, stdout, stderr) {
|
||||||
|
if (err) {
|
||||||
|
console.log(err);
|
||||||
|
} else {
|
||||||
|
console.log(`\nUSER (${config.username}) AND DATABASE (${config.database}) CREATED SUCCESSFULLY`);
|
||||||
|
console.log(stdout);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
@ -1,51 +1,12 @@
|
|||||||
#!/usr/bin/env node
|
#!/usr/bin/env node
|
||||||
var exec = require('child_process').exec;
|
|
||||||
var models = require('../models');
|
var models = require('../models');
|
||||||
var env = require('../config/config.json')['env'] || 'development';
|
|
||||||
var config = require(__dirname + '/../config/config.json')['database'][env];
|
|
||||||
|
|
||||||
if (process.argv.length < 4) {
|
models.sequelize.sync({force: true})
|
||||||
console.log('Provide root user name and password for mysql');
|
.then(() => {
|
||||||
|
console.log('Tables created');
|
||||||
|
process.exit(0);
|
||||||
|
})
|
||||||
|
.catch((err) => {
|
||||||
|
console.log(err);
|
||||||
process.exit(0);
|
process.exit(0);
|
||||||
}
|
|
||||||
|
|
||||||
const dropUserDB = `mysql -u${process.argv[2]} -p${process.argv[3]} -e "drop database ${config.database};drop user ${config.username}"`
|
|
||||||
const createdb = `mysql -u${process.argv[2]} -p${process.argv[3]} -e "create database ${config.database}"`;
|
|
||||||
const createUser = `mysql -u${process.argv[2]} -p${process.argv[3]} -e "create user ${config.username} identified by '${config.password}'"`;
|
|
||||||
const grantAccess = `mysql -u${process.argv[2]} -p${process.argv[3]} -e "grant all on ${config.database}.* to ${config.username}"`;
|
|
||||||
|
|
||||||
exec(dropUserDB, function(err,stdout,stderr) {
|
|
||||||
console.log(stdout);
|
|
||||||
exec(createdb, function(err,stdout,stderr) {
|
|
||||||
if (err) {
|
|
||||||
console.log(err);
|
|
||||||
process.exit(0);
|
|
||||||
} else {
|
|
||||||
console.log(stdout);
|
|
||||||
exec(createUser, function(err, stdout, stderr) {
|
|
||||||
if (err) {
|
|
||||||
console.log(err);
|
|
||||||
process.exit(0);
|
|
||||||
} else {
|
|
||||||
console.log(stdout);
|
|
||||||
exec(grantAccess, function(err, stdout, stderr) {
|
|
||||||
if (err) {
|
|
||||||
console.log(err);
|
|
||||||
} else {
|
|
||||||
console.log(stdout);
|
|
||||||
models.sequelize.sync({force: true})
|
|
||||||
.then(() => {
|
|
||||||
console.log(`\nUSER (${config.username}) AND DATABASE (${config.database}) CREATED SUCCESSFULLY`);
|
|
||||||
process.exit(0);
|
|
||||||
})
|
|
||||||
.catch((err) => {
|
|
||||||
console.log(err);
|
|
||||||
process.exit(0);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
@ -39,7 +39,6 @@ async function saveTransaction(txid, blockHeight) {
|
|||||||
id: 1
|
id: 1
|
||||||
}));
|
}));
|
||||||
const tx = JSON.parse(res_tx)['result'];
|
const tx = JSON.parse(res_tx)['result'];
|
||||||
// console.log('tx:', tx);
|
|
||||||
if (tx === null) {
|
if (tx === null) {
|
||||||
await models.Failure.create({
|
await models.Failure.create({
|
||||||
msg: `${txid} fetching failed`,
|
msg: `${txid} fetching failed`,
|
||||||
@ -50,11 +49,17 @@ async function saveTransaction(txid, blockHeight) {
|
|||||||
txid: tx.txid,
|
txid: tx.txid,
|
||||||
BlockHeight: blockHeight,
|
BlockHeight: blockHeight,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Loop over vouts
|
||||||
for (var i = 0; i < tx.vout.length; i++) {
|
for (var i = 0; i < tx.vout.length; i++) {
|
||||||
const vout = tx.vout[i];
|
const vout = tx.vout[i];
|
||||||
|
|
||||||
const m_vout = await models.Vout.create({
|
const m_vout = await models.Vout.create({
|
||||||
|
n: vout.n,
|
||||||
value: vout.value,
|
value: vout.value,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Loop over addresses in vout
|
||||||
for (var y = 0; y < vout.scriptPubKey.addresses.length; y++) {
|
for (var y = 0; y < vout.scriptPubKey.addresses.length; y++) {
|
||||||
const address = vout.scriptPubKey.addresses[y];
|
const address = vout.scriptPubKey.addresses[y];
|
||||||
let m_address = await models.Address.findOne({
|
let m_address = await models.Address.findOne({
|
||||||
@ -69,18 +74,26 @@ async function saveTransaction(txid, blockHeight) {
|
|||||||
}
|
}
|
||||||
await m_vout.addAddresses(m_address);
|
await m_vout.addAddresses(m_address);
|
||||||
}
|
}
|
||||||
await transaction.addVouts(m_vout);
|
await transaction.addVouts(m_vout, {through: {direction: 1}});
|
||||||
}
|
}
|
||||||
for (var i = 0; i < tx.vin.length; i++) {
|
for (var i = 0; i < tx.vin.length; i++) {
|
||||||
const vin = tx.vin[i];
|
const vin = tx.vin[i];
|
||||||
if (vin.txid) {
|
if (vin.txid) {
|
||||||
const trans = await models.Transaction.findOne({
|
const vout = await models.Vout.findAll({
|
||||||
|
include: {
|
||||||
|
model: models.Transaction,
|
||||||
|
where: {
|
||||||
|
txid: vin.txid,
|
||||||
|
},
|
||||||
|
},
|
||||||
where: {
|
where: {
|
||||||
txid: vin.txid,
|
n: vin.vout,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
if (trans) {
|
if (vout) {
|
||||||
await transaction.addTxtx(trans);
|
await transaction.addVouts(vout, { through: { direction: 0, }, });
|
||||||
|
} else {
|
||||||
|
throw('Couldnt find vout for VIN');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
3
bin/www
3
bin/www
@ -8,12 +8,13 @@ var app = require('../app');
|
|||||||
var debug = require('debug')('gostexplr:server');
|
var debug = require('debug')('gostexplr:server');
|
||||||
var http = require('http');
|
var http = require('http');
|
||||||
var models = require('../models');
|
var models = require('../models');
|
||||||
|
var config = require('../config/config.json');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get port from environment and store in Express.
|
* Get port from environment and store in Express.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
var port = normalizePort(process.env.PORT || '3000');
|
var port = config['port'] || '3000';
|
||||||
app.set('port', port);
|
app.set('port', port);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -30,5 +30,6 @@
|
|||||||
"hostname": "127.0.0.1",
|
"hostname": "127.0.0.1",
|
||||||
"port": 9376
|
"port": 9376
|
||||||
},
|
},
|
||||||
"env": "production"
|
"env": "production",
|
||||||
|
"port": 3000
|
||||||
}
|
}
|
||||||
|
@ -11,21 +11,21 @@ module.exports = (sequelize, DataTypes) => {
|
|||||||
}],
|
}],
|
||||||
});
|
});
|
||||||
|
|
||||||
const TxToTx = sequelize.define('TxToTx', {}, {
|
const TransactionVouts = sequelize.define('TransactionVouts', {
|
||||||
|
'direction': DataTypes.TINYINT(1),
|
||||||
|
}, {
|
||||||
timestamps: false,
|
timestamps: false,
|
||||||
});
|
});
|
||||||
|
|
||||||
Transaction.belongsToMany(Transaction, { through: TxToTx, as: 'txtx' });
|
|
||||||
|
|
||||||
Transaction.associate = function (models) {
|
Transaction.associate = function (models) {
|
||||||
models.Transaction.belongsTo(models.Block, {
|
models.Transaction.belongsTo(models.Block, {
|
||||||
onDelete: "CASCADE",
|
onDelete: "CASCADE",
|
||||||
foreignKey: {
|
foreignKey: {
|
||||||
allowNull: false
|
allowNull: false
|
||||||
}
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
models.Transaction.hasMany(models.Vout);
|
models.Transaction.belongsToMany(models.Vout, { through: 'TransactionVouts' });
|
||||||
};
|
};
|
||||||
|
|
||||||
return Transaction;
|
return Transaction;
|
||||||
|
@ -2,19 +2,15 @@
|
|||||||
|
|
||||||
module.exports = (sequelize, DataTypes) => {
|
module.exports = (sequelize, DataTypes) => {
|
||||||
const Vout = sequelize.define('Vout', {
|
const Vout = sequelize.define('Vout', {
|
||||||
|
n: DataTypes.MEDIUMINT.UNSIGNED,
|
||||||
value: DataTypes.DECIMAL(16, 8),
|
value: DataTypes.DECIMAL(16, 8),
|
||||||
}, {
|
}, {
|
||||||
timestamps: false,
|
timestamps: false,
|
||||||
});
|
});
|
||||||
|
|
||||||
Vout.associate = function (models) {
|
Vout.associate = function (models) {
|
||||||
models.Vout.belongsTo(models.Transaction, {
|
|
||||||
onDelete: "CASCADE",
|
|
||||||
foreignKey: {
|
|
||||||
allowNull: false
|
|
||||||
}
|
|
||||||
});
|
|
||||||
models.Vout.belongsToMany(models.Address, { through: 'AddressVout' });
|
models.Vout.belongsToMany(models.Address, { through: 'AddressVout' });
|
||||||
|
models.Vout.belongsToMany(models.Transaction, { through: 'TransactionVouts' });
|
||||||
};
|
};
|
||||||
|
|
||||||
return Vout;
|
return Vout;
|
||||||
|
@ -6,6 +6,7 @@
|
|||||||
"scripts": {
|
"scripts": {
|
||||||
"start": "node ./bin/www",
|
"start": "node ./bin/www",
|
||||||
"initdb": "node ./bin/initdb.js",
|
"initdb": "node ./bin/initdb.js",
|
||||||
|
"createUserAndDb": "node ./bin/createUserAndDb.js",
|
||||||
"syncBlockchain": "node ./bin/syncBlockchain.js",
|
"syncBlockchain": "node ./bin/syncBlockchain.js",
|
||||||
"addN": "node ./bin/addNToVouts.js"
|
"addN": "node ./bin/addNToVouts.js"
|
||||||
},
|
},
|
||||||
@ -22,10 +23,10 @@
|
|||||||
"debug": "~2.6.9",
|
"debug": "~2.6.9",
|
||||||
"express": "~4.15.5",
|
"express": "~4.15.5",
|
||||||
"forever": "^0.15.3",
|
"forever": "^0.15.3",
|
||||||
"jade": "~1.11.0",
|
|
||||||
"morgan": "~1.9.0",
|
"morgan": "~1.9.0",
|
||||||
"mysql": "^2.15.0",
|
"mysql": "^2.15.0",
|
||||||
"mysql2": "^1.5.1",
|
"mysql2": "^1.5.1",
|
||||||
|
"pug": "^2.0.0-rc.4",
|
||||||
"sequelize": "^4.32.2",
|
"sequelize": "^4.32.2",
|
||||||
"sequelize-cli": "^3.2.0",
|
"sequelize-cli": "^3.2.0",
|
||||||
"serve-favicon": "~2.4.5"
|
"serve-favicon": "~2.4.5"
|
||||||
|
@ -5,36 +5,38 @@ var router = express.Router();
|
|||||||
/* GET home page. */
|
/* GET home page. */
|
||||||
router.get('/:address/:offset*?', async function(req, res, next) {
|
router.get('/:address/:offset*?', async function(req, res, next) {
|
||||||
|
|
||||||
const addrss = encodeURI(req.params.address);
|
const safe_address = encodeURI(req.params.address);
|
||||||
|
|
||||||
|
const address = await models.Address.findOne({
|
||||||
|
where: {
|
||||||
|
address: safe_address,
|
||||||
|
},
|
||||||
|
include: {
|
||||||
|
model: models.Vout,
|
||||||
|
include: {
|
||||||
|
model: models.Transaction,
|
||||||
|
include: {
|
||||||
|
model: models.Vout,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
if (address === null) {
|
||||||
|
res.status(404).render('404');
|
||||||
|
return;
|
||||||
|
}
|
||||||
const limit = 30;
|
const limit = 30;
|
||||||
const paramPage = parseInt(req.params.offset);
|
const paramPage = parseInt(req.params.offset);
|
||||||
const page = isNaN(paramPage) || paramPage < 1 ? 1 : paramPage;
|
const page = isNaN(paramPage) || paramPage < 1 ? 1 : paramPage;
|
||||||
const offset = 30 * (page - 1);
|
const offset = 30 * (page - 1);
|
||||||
const txes = await models.sequelize.query(`
|
|
||||||
SELECT txid
|
|
||||||
FROM Transactions as t
|
|
||||||
LEFT JOIN Vouts as v
|
|
||||||
ON v.TransactionId=t.id
|
|
||||||
LEFT JOIN AddressVouts as av
|
|
||||||
ON v.id=av.VoutId
|
|
||||||
LEFT JOIN Addresses as a
|
|
||||||
ON a.id=av.AddressId
|
|
||||||
WHERE a.address='${addrss}'
|
|
||||||
LIMIT ${limit}
|
|
||||||
OFFSET ${offset};
|
|
||||||
`);
|
|
||||||
|
|
||||||
if (txes === null) {
|
const nextpage = address.Vouts.length === 30 ? page + 1 : null;
|
||||||
res.status(404).render('404');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const nextpage = txes[0].length === 30 ? page + 1 : null;
|
|
||||||
const prevpage = page > 1 ? page - 1 : null;
|
const prevpage = page > 1 ? page - 1 : null;
|
||||||
|
console.log(address.toJSON());
|
||||||
|
|
||||||
res.render('address', {
|
res.render('address', {
|
||||||
address: addrss,
|
address: address.toJSON(),
|
||||||
txes: txes[0],
|
|
||||||
nextpage,
|
nextpage,
|
||||||
prevpage,
|
prevpage,
|
||||||
});
|
});
|
||||||
|
@ -13,10 +13,12 @@ router.get('/:hash', async function(req, res, next) {
|
|||||||
model: models.Transaction,
|
model: models.Transaction,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
if (blockInstance === null) {
|
if (blockInstance === null) {
|
||||||
res.status(404).render('404');
|
res.status(404).render('404');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const lastBlock = await models.Block.findOne({
|
const lastBlock = await models.Block.findOne({
|
||||||
attributes: [
|
attributes: [
|
||||||
[models.sequelize.fn('MAX', models.sequelize.col('height')), 'maxheight']
|
[models.sequelize.fn('MAX', models.sequelize.col('height')), 'maxheight']
|
||||||
|
@ -15,27 +15,34 @@ router.get('/:txid', async function(req, res, next) {
|
|||||||
model: models.Block,
|
model: models.Block,
|
||||||
},{
|
},{
|
||||||
model: models.Vout,
|
model: models.Vout,
|
||||||
include: {
|
include: [
|
||||||
model: models.Address,
|
{
|
||||||
}
|
model: models.Address,
|
||||||
}, {
|
}, {
|
||||||
model: models.Transaction,
|
model: models.Transaction,
|
||||||
as: 'txtx',
|
include: {
|
||||||
}],
|
model: models.Vout,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
],
|
||||||
|
},],
|
||||||
});
|
});
|
||||||
|
|
||||||
if (transaction === null) {
|
if (transaction === null) {
|
||||||
res.status(404).render('404');
|
res.status(404).render('404');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const vouts = [];
|
|
||||||
transaction.Vouts.forEach((vout) => {
|
// const vouts = [];
|
||||||
vout.Addresses.forEach((address) => {
|
// transaction.Vouts.forEach((vout) => {
|
||||||
vouts.push({
|
// vout.Addresses.forEach((address) => {
|
||||||
address: address.address,
|
// vouts.push({
|
||||||
value: vout.value,
|
// address: address.address,
|
||||||
});
|
// value: vout.value,
|
||||||
});
|
// });
|
||||||
});
|
// });
|
||||||
|
// });
|
||||||
|
|
||||||
const lastBlock = await models.Block.findOne({
|
const lastBlock = await models.Block.findOne({
|
||||||
attributes: [
|
attributes: [
|
||||||
[models.sequelize.fn('MAX', models.sequelize.col('height')), 'maxheight']
|
[models.sequelize.fn('MAX', models.sequelize.col('height')), 'maxheight']
|
||||||
@ -43,10 +50,20 @@ router.get('/:txid', async function(req, res, next) {
|
|||||||
raw: true,
|
raw: true,
|
||||||
});
|
});
|
||||||
const confirmations = lastBlock.maxheight - transaction.Block.height + 1;
|
const confirmations = lastBlock.maxheight - transaction.Block.height + 1;
|
||||||
transaction.blockTime = transaction.Block.time.toUTCString();
|
|
||||||
|
const txJson = transaction.toJSON();
|
||||||
|
// txJson.vins = txJson.Vouts.filter({TransactionVouts: {direction: 0}});
|
||||||
|
// txJson.vouts txJson.Vouts.filter({TransactionVouts: {direction: 1}});
|
||||||
|
const txTemplate = Object.assign(txJson, {
|
||||||
|
vins: txJson.Vouts.filter((vout) => vout.TransactionVouts.direction === 0),
|
||||||
|
vouts: txJson.Vouts.filter((vout) => vout.TransactionVouts.direction === 1),
|
||||||
|
});
|
||||||
|
|
||||||
|
txTemplate.blockTime = transaction.Block.time.toUTCString();
|
||||||
|
|
||||||
res.render('transaction', {
|
res.render('transaction', {
|
||||||
transaction,
|
transaction: txTemplate,
|
||||||
vouts,
|
// vouts,
|
||||||
confirmations,
|
confirmations,
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -1,15 +0,0 @@
|
|||||||
extends layout
|
|
||||||
|
|
||||||
block content
|
|
||||||
h3 Address
|
|
||||||
div= address
|
|
||||||
|
|
||||||
h3 Transactions
|
|
||||||
each val in txes
|
|
||||||
div
|
|
||||||
a(href='/transaction/#{val.txid}/') #{val.txid}
|
|
||||||
div.pagination
|
|
||||||
if prevpage
|
|
||||||
a(href='/address/#{address}/#{prevpage}/', style='float:left') Back
|
|
||||||
if nextpage
|
|
||||||
a(href='/address/#{address}/#{nextpage}/', style='float:right') Next
|
|
21
views/address.pug
Normal file
21
views/address.pug
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
extends layout
|
||||||
|
|
||||||
|
block content
|
||||||
|
h3 Address
|
||||||
|
div= address.address
|
||||||
|
|
||||||
|
h3 Transactions
|
||||||
|
table
|
||||||
|
each vout in address.Vouts
|
||||||
|
tr
|
||||||
|
if vout.Transactions[0].TransactionVouts.direction == 1
|
||||||
|
td OUT
|
||||||
|
else
|
||||||
|
td IN
|
||||||
|
td
|
||||||
|
a(href=`/transaction/${vout.Transactions[0].txid}/`) #{vout.Transactions[0].txid}
|
||||||
|
div.pagination
|
||||||
|
if prevpage
|
||||||
|
a(href=`/address/#{address}/${prevpage}/`, style='float:left') Back
|
||||||
|
if nextpage
|
||||||
|
a(href=`/address/${address}/${nextpage}/`, style='float:right') Next
|
@ -9,13 +9,13 @@ block content
|
|||||||
tr
|
tr
|
||||||
td.capitalize #{key}
|
td.capitalize #{key}
|
||||||
td
|
td
|
||||||
a(href='/block/#{block.nextblockhash}/') #{block.nextblockhash}
|
a(href=`/block/${block.nextblockhash}/`) #{block.nextblockhash}
|
||||||
-continue
|
-continue
|
||||||
if (key === 'previousblockhash')
|
if (key === 'previousblockhash')
|
||||||
tr
|
tr
|
||||||
td.capitalize #{key}
|
td.capitalize #{key}
|
||||||
td
|
td
|
||||||
a(href='/block/#{block.previousblockhash}/') #{block.previousblockhash}
|
a(href=`/block/${block.previousblockhash}/`) #{block.previousblockhash}
|
||||||
-continue
|
-continue
|
||||||
if (key === 'Transactions')
|
if (key === 'Transactions')
|
||||||
-continue
|
-continue
|
||||||
@ -26,5 +26,5 @@ block content
|
|||||||
h3 Transactions
|
h3 Transactions
|
||||||
each tx in block.Transactions
|
each tx in block.Transactions
|
||||||
div
|
div
|
||||||
a(href='/transaction/#{tx.txid}/') #{tx.txid}
|
a(href=`/transaction/${tx.txid}/`) #{tx.txid}
|
||||||
|
|
@ -8,4 +8,4 @@ block content
|
|||||||
tr
|
tr
|
||||||
td #{block.height}
|
td #{block.height}
|
||||||
td
|
td
|
||||||
a(href='/block/#{block.hash}/') #{block.hash}
|
a(href='/block/' + block.hash + '/') #{block.hash}
|
@ -1,37 +0,0 @@
|
|||||||
extends layout
|
|
||||||
|
|
||||||
block content
|
|
||||||
h3 Transaction
|
|
||||||
|
|
||||||
table
|
|
||||||
tr
|
|
||||||
td Hash
|
|
||||||
td #{transaction.txid}
|
|
||||||
tr
|
|
||||||
td Block
|
|
||||||
td
|
|
||||||
a(href='/block/#{transaction.Block.hash}/') #{transaction.Block.hash}
|
|
||||||
tr
|
|
||||||
td Block time
|
|
||||||
td #{transaction.blockTime}
|
|
||||||
tr
|
|
||||||
td Confirmations
|
|
||||||
td #{confirmations}
|
|
||||||
|
|
||||||
h3 In
|
|
||||||
if transaction.txtx.length
|
|
||||||
table
|
|
||||||
each val in transaction.txtx
|
|
||||||
tr
|
|
||||||
td
|
|
||||||
a(href='/transaction/#{val.txid}/') #{val.txid}
|
|
||||||
else
|
|
||||||
div Mined
|
|
||||||
|
|
||||||
h3 Out
|
|
||||||
table
|
|
||||||
each val in vouts
|
|
||||||
tr
|
|
||||||
td
|
|
||||||
a(href='/address/#{val.address}/') #{val.address}
|
|
||||||
td #{val.value}
|
|
54
views/transaction.pug
Normal file
54
views/transaction.pug
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
extends layout
|
||||||
|
|
||||||
|
block content
|
||||||
|
h3 Transaction
|
||||||
|
|
||||||
|
table
|
||||||
|
tr
|
||||||
|
td Hash
|
||||||
|
td #{transaction.txid}
|
||||||
|
tr
|
||||||
|
td Block
|
||||||
|
td
|
||||||
|
a(href=`/block/${transaction.Block.hash}/`) #{transaction.Block.hash}
|
||||||
|
tr
|
||||||
|
td Block time
|
||||||
|
td #{transaction.blockTime}
|
||||||
|
tr
|
||||||
|
td Confirmations
|
||||||
|
td #{confirmations}
|
||||||
|
|
||||||
|
h3 In
|
||||||
|
if transaction.vins.length
|
||||||
|
table
|
||||||
|
tr
|
||||||
|
th Address
|
||||||
|
th Value
|
||||||
|
th Transaction
|
||||||
|
each vin in transaction.vins
|
||||||
|
tr
|
||||||
|
td
|
||||||
|
a(href=`/address/${vin.Addresses[0].address}/`) #{vin.Addresses[0].address}
|
||||||
|
td #{vin.value}
|
||||||
|
td
|
||||||
|
a(href=`/transaction/${vin.Transactions[0].txid}/`) #{vin.Transactions[0].txid}
|
||||||
|
else
|
||||||
|
div Mined
|
||||||
|
|
||||||
|
h3 Out
|
||||||
|
table
|
||||||
|
tr
|
||||||
|
th Address
|
||||||
|
th Value
|
||||||
|
th Transaction
|
||||||
|
each vout in transaction.vouts
|
||||||
|
each address in vout.Addresses
|
||||||
|
tr
|
||||||
|
td
|
||||||
|
a(href=`/address/${address.address}/`) #{address.address}
|
||||||
|
td #{vout.value}
|
||||||
|
td
|
||||||
|
if vout.Transactions[0].TransactionVouts.direction == 0
|
||||||
|
a(href=`/transaction/${vout.Transactions[0].txid}/`) #{vout.Transactions[0].txid}
|
||||||
|
else
|
||||||
|
span No yet
|
Loading…
x
Reference in New Issue
Block a user