Browse Source

Jade to Pug, added Vout Ns, refactored database/pages, port in config, clean dependencies

stuff
xcps 7 years ago
parent
commit
887c852b55
  1. 2
      app.js
  2. 43
      bin/createUserAndDb.js
  3. 49
      bin/initdb.js
  4. 23
      bin/syncBlockchain.js
  5. 3
      bin/www
  6. 3
      config/config.json.example
  7. 10
      models/transaction.js
  8. 8
      models/vout.js
  9. 3
      package.json
  10. 46
      routes/address.js
  11. 2
      routes/block.js
  12. 49
      routes/transaction.js
  13. 0
      views/404.pug
  14. 15
      views/address.jade
  15. 21
      views/address.pug
  16. 6
      views/block.pug
  17. 0
      views/error.pug
  18. 2
      views/index.pug
  19. 0
      views/layout.pug
  20. 37
      views/transaction.jade
  21. 54
      views/transaction.pug

2
app.js

@ -16,7 +16,7 @@ var app = express(); @@ -16,7 +16,7 @@ var app = express();
// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'jade');
app.set('view engine', 'pug');
// uncomment after placing your favicon in /public
app.use(favicon(path.join(__dirname, 'public', 'favicon.ico')));

43
bin/createUserAndDb.js

@ -0,0 +1,43 @@ @@ -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);
}
});
}
});
}
});
});

49
bin/initdb.js

@ -1,51 +1,12 @@ @@ -1,51 +1,12 @@
#!/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');
models.sequelize.sync({force: true})
.then(() => {
console.log('Tables created');
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) => {
})
.catch((err) => {
console.log(err);
process.exit(0);
});
}
});
}
});
}
});
});

23
bin/syncBlockchain.js

@ -39,7 +39,6 @@ async function saveTransaction(txid, blockHeight) { @@ -39,7 +39,6 @@ async function saveTransaction(txid, blockHeight) {
id: 1
}));
const tx = JSON.parse(res_tx)['result'];
// console.log('tx:', tx);
if (tx === null) {
await models.Failure.create({
msg: `${txid} fetching failed`,
@ -50,11 +49,17 @@ async function saveTransaction(txid, blockHeight) { @@ -50,11 +49,17 @@ async function saveTransaction(txid, blockHeight) {
txid: tx.txid,
BlockHeight: blockHeight,
});
// Loop over vouts
for (var i = 0; i < tx.vout.length; i++) {
const vout = tx.vout[i];
const m_vout = await models.Vout.create({
n: vout.n,
value: vout.value,
});
// Loop over addresses in vout
for (var y = 0; y < vout.scriptPubKey.addresses.length; y++) {
const address = vout.scriptPubKey.addresses[y];
let m_address = await models.Address.findOne({
@ -69,18 +74,26 @@ async function saveTransaction(txid, blockHeight) { @@ -69,18 +74,26 @@ async function saveTransaction(txid, blockHeight) {
}
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++) {
const vin = tx.vin[i];
if (vin.txid) {
const trans = await models.Transaction.findOne({
const vout = await models.Vout.findAll({
include: {
model: models.Transaction,
where: {
txid: vin.txid,
},
},
where: {
n: vin.vout,
},
});
if (trans) {
await transaction.addTxtx(trans);
if (vout) {
await transaction.addVouts(vout, { through: { direction: 0, }, });
} else {
throw('Couldnt find vout for VIN');
}
}
}

3
bin/www

@ -8,12 +8,13 @@ var app = require('../app'); @@ -8,12 +8,13 @@ var app = require('../app');
var debug = require('debug')('gostexplr:server');
var http = require('http');
var models = require('../models');
var config = require('../config/config.json');
/**
* Get port from environment and store in Express.
*/
var port = normalizePort(process.env.PORT || '3000');
var port = config['port'] || '3000';
app.set('port', port);
/**

3
config/config.json.example

@ -30,5 +30,6 @@ @@ -30,5 +30,6 @@
"hostname": "127.0.0.1",
"port": 9376
},
"env": "production"
"env": "production",
"port": 3000
}

10
models/transaction.js

@ -11,21 +11,21 @@ module.exports = (sequelize, DataTypes) => { @@ -11,21 +11,21 @@ module.exports = (sequelize, DataTypes) => {
}],
});
const TxToTx = sequelize.define('TxToTx', {}, {
const TransactionVouts = sequelize.define('TransactionVouts', {
'direction': DataTypes.TINYINT(1),
}, {
timestamps: false,
});
Transaction.belongsToMany(Transaction, { through: TxToTx, as: 'txtx' });
Transaction.associate = function (models) {
models.Transaction.belongsTo(models.Block, {
onDelete: "CASCADE",
foreignKey: {
allowNull: false
}
},
});
models.Transaction.hasMany(models.Vout);
models.Transaction.belongsToMany(models.Vout, { through: 'TransactionVouts' });
};
return Transaction;

8
models/vout.js

@ -2,19 +2,15 @@ @@ -2,19 +2,15 @@
module.exports = (sequelize, DataTypes) => {
const Vout = sequelize.define('Vout', {
n: DataTypes.MEDIUMINT.UNSIGNED,
value: DataTypes.DECIMAL(16, 8),
}, {
timestamps: false,
});
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.Transaction, { through: 'TransactionVouts' });
};
return Vout;

3
package.json

@ -6,6 +6,7 @@ @@ -6,6 +6,7 @@
"scripts": {
"start": "node ./bin/www",
"initdb": "node ./bin/initdb.js",
"createUserAndDb": "node ./bin/createUserAndDb.js",
"syncBlockchain": "node ./bin/syncBlockchain.js",
"addN": "node ./bin/addNToVouts.js"
},
@ -22,10 +23,10 @@ @@ -22,10 +23,10 @@
"debug": "~2.6.9",
"express": "~4.15.5",
"forever": "^0.15.3",
"jade": "~1.11.0",
"morgan": "~1.9.0",
"mysql": "^2.15.0",
"mysql2": "^1.5.1",
"pug": "^2.0.0-rc.4",
"sequelize": "^4.32.2",
"sequelize-cli": "^3.2.0",
"serve-favicon": "~2.4.5"

46
routes/address.js

@ -5,36 +5,38 @@ var router = express.Router(); @@ -5,36 +5,38 @@ var router = express.Router();
/* GET home page. */
router.get('/:address/:offset*?', async function(req, res, next) {
const addrss = encodeURI(req.params.address);
const limit = 30;
const paramPage = parseInt(req.params.offset);
const page = isNaN(paramPage) || paramPage < 1 ? 1 : paramPage;
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};
`);
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 (txes === null) {
if (address === null) {
res.status(404).render('404');
return;
}
const limit = 30;
const paramPage = parseInt(req.params.offset);
const page = isNaN(paramPage) || paramPage < 1 ? 1 : paramPage;
const offset = 30 * (page - 1);
const nextpage = txes[0].length === 30 ? page + 1 : null;
const nextpage = address.Vouts.length === 30 ? page + 1 : null;
const prevpage = page > 1 ? page - 1 : null;
console.log(address.toJSON());
res.render('address', {
address: addrss,
txes: txes[0],
address: address.toJSON(),
nextpage,
prevpage,
});

2
routes/block.js

@ -13,10 +13,12 @@ router.get('/:hash', async function(req, res, next) { @@ -13,10 +13,12 @@ router.get('/:hash', async function(req, res, next) {
model: models.Transaction,
},
});
if (blockInstance === null) {
res.status(404).render('404');
return;
}
const lastBlock = await models.Block.findOne({
attributes: [
[models.sequelize.fn('MAX', models.sequelize.col('height')), 'maxheight']

49
routes/transaction.js

@ -15,27 +15,34 @@ router.get('/:txid', async function(req, res, next) { @@ -15,27 +15,34 @@ router.get('/:txid', async function(req, res, next) {
model: models.Block,
},{
model: models.Vout,
include: {
include: [
{
model: models.Address,
}
}, {
model: models.Transaction,
as: 'txtx',
}],
include: {
model: models.Vout,
},
}
],
},],
});
if (transaction === null) {
res.status(404).render('404');
return;
}
const vouts = [];
transaction.Vouts.forEach((vout) => {
vout.Addresses.forEach((address) => {
vouts.push({
address: address.address,
value: vout.value,
});
});
});
// const vouts = [];
// transaction.Vouts.forEach((vout) => {
// vout.Addresses.forEach((address) => {
// vouts.push({
// address: address.address,
// value: vout.value,
// });
// });
// });
const lastBlock = await models.Block.findOne({
attributes: [
[models.sequelize.fn('MAX', models.sequelize.col('height')), 'maxheight']
@ -43,10 +50,20 @@ router.get('/:txid', async function(req, res, next) { @@ -43,10 +50,20 @@ router.get('/:txid', async function(req, res, next) {
raw: true,
});
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', {
transaction,
vouts,
transaction: txTemplate,
// vouts,
confirmations,
});
});

0
views/404.jade → views/404.pug

15
views/address.jade

@ -1,15 +0,0 @@ @@ -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

@ -0,0 +1,21 @@ @@ -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

6
views/block.jade → views/block.pug

@ -9,13 +9,13 @@ block content @@ -9,13 +9,13 @@ block content
tr
td.capitalize #{key}
td
a(href='/block/#{block.nextblockhash}/') #{block.nextblockhash}
a(href=`/block/${block.nextblockhash}/`) #{block.nextblockhash}
-continue
if (key === 'previousblockhash')
tr
td.capitalize #{key}
td
a(href='/block/#{block.previousblockhash}/') #{block.previousblockhash}
a(href=`/block/${block.previousblockhash}/`) #{block.previousblockhash}
-continue
if (key === 'Transactions')
-continue
@ -26,5 +26,5 @@ block content @@ -26,5 +26,5 @@ block content
h3 Transactions
each tx in block.Transactions
div
a(href='/transaction/#{tx.txid}/') #{tx.txid}
a(href=`/transaction/${tx.txid}/`) #{tx.txid}

0
views/error.jade → views/error.pug

2
views/index.jade → views/index.pug

@ -8,4 +8,4 @@ block content @@ -8,4 +8,4 @@ block content
tr
td #{block.height}
td
a(href='/block/#{block.hash}/') #{block.hash}
a(href='/block/' + block.hash + '/') #{block.hash}

0
views/layout.jade → views/layout.pug

37
views/transaction.jade

@ -1,37 +0,0 @@ @@ -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

@ -0,0 +1,54 @@ @@ -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…
Cancel
Save