Full address history with DataTables ajax loading

This commit is contained in:
joeuhren
2020-11-19 21:37:42 -07:00
parent da7330ded6
commit fd277bc674
7 changed files with 276 additions and 176 deletions
+36
View File
@@ -132,6 +132,42 @@ app.use('/ext/getbasicstats', function(req,res){
});
});
app.use('/ext/getaddresstxsajax', function(req,res){
if(req.query.length > settings.txcount){
req.query.length = settings.txcount;
}
db.get_address_txs_ajax(req.query.address, req.query.start, req.query.length,function(txs, count){
var data = [];
for(i=0; i<txs.length; i++){
if(typeof txs[i].txid !== "undefined") {
var out = 0
var vin = 0
txs[i].vout.forEach(function (r) {
if (r.addresses == req.query.address) {
out = r.amount;
}
});
txs[i].vin.forEach(function (s) {
if (s.addresses == req.query.address) {
vin = s.amount
}
});
var row = [];
row.push(new Date((txs[i].timestamp) * 1000).toUTCString());
row.push(txs[i].txid);
row.push(out);
row.push(vin);
data.push(row);
}
}
res.json({"data":data, "draw": req.query.draw, "recordsTotal": count, "recordsFiltered": count});
});
});
app.use('/ext/connections', function(req,res){
db.get_peers(function(peers){
res.send({data: peers});
+93 -37
View File
@@ -2,6 +2,7 @@ var mongoose = require('mongoose')
, Stats = require('../models/stats')
, Markets = require('../models/markets')
, Address = require('../models/address')
, AddressTx = require('../models/addresstx')
, Tx = require('../models/tx')
, Richlist = require('../models/richlist')
, Peers = require('../models/peers')
@@ -59,43 +60,39 @@ function update_address(hash, txid, amount, type, cb) {
return cb();
});
} else {
// ensure tx doesnt already exist in address.txs
lib.is_unique(address.txs, txid, function(unique, index) {
var tx_array = address.txs;
var received = address.received;
var sent = address.sent;
if (type == 'vin') {
sent = sent + amount;
} else {
received = received + amount;
}
if (unique == true) {
tx_array.push({addresses: txid, type: type});
if ( tx_array.length > settings.txcount ) {
tx_array.shift();
}
Address.updateOne({a_id:hash}, {
txs: tx_array,
received: received,
sent: sent,
balance: received - sent
}, function() {
return cb();
});
} else {
if (type == tx_array[index].type) {
return cb(); //duplicate
//Considering no duplicate
var tx_array = [];
var received = address.received;
var sent = address.sent;
if (type == 'vin') {
sent = sent + amount;
} else {
received = received + amount;
}
tx_array.push({addresses: txid, type: type});
Address.updateOne({a_id:hash}, {
received: received,
sent: sent,
balance: received - sent
}, function() {
var newAddressTx = new AddressTx({
a_id: hash,
addresses: txid,
type: type
});
newAddressTx.save(function(err) {
if (err) {
return cb(err);
} else {
Address.updateOne({a_id:hash}, {
txs: tx_array,
received: received,
sent: sent,
balance: received - sent
}, function() {
return cb();
});
//console.log('address saved: %s', hash);
//console.log(newAddress);
return cb();
}
}
});
return cb();
});
}
} else {
@@ -103,14 +100,12 @@ function update_address(hash, txid, amount, type, cb) {
if (type == 'vin') {
var newAddress = new Address({
a_id: hash,
txs: [ {addresses: txid, type: 'vin'} ],
sent: amount,
balance: amount,
});
} else {
var newAddress = new Address({
a_id: hash,
txs: [ {addresses: txid, type: 'vout'} ],
received: amount,
balance: amount,
});
@@ -122,6 +117,21 @@ function update_address(hash, txid, amount, type, cb) {
} else {
//console.log('address saved: %s', hash);
//console.log(newAddress);
var newAddressTx = new AddressTx({
a_id: hash,
addresses: txid,
type: type
});
newAddressTx.save(function(err) {
if (err) {
return cb(err);
} else {
//console.log('address saved: %s', hash);
//console.log(newAddress);
return cb();
}
});
return cb();
}
});
@@ -394,6 +404,52 @@ module.exports = {
});
},
get_address_txs_ajax: function(hash, start, length, cb) {
var totalCount = 0;
Address.findOne({a_id: hash}, function(err, addressTotalTxs) {
if(err) {
return cb(err);
} else {
AddressTx.find({a_id: hash}).count({}, function(err, count){
if(err) {
return cb(err);
} else {
totalCount = count;
AddressTx.find({a_id: hash}).sort({_id: 'desc'}).skip(Number(start)).limit(Number(length)).exec(function (err, address) {
if (err) {
return cb(err);
} else {
//console.log(address);
var txs = [];
var count = address.length;
var hashes = address;
var txs = [];
lib.syncLoop(count, function (loop) {
var i = loop.iteration();
find_tx(hashes[i].addresses, function (tx) {
if (tx) {
txs.push(tx);
loop.next();
} else {
txs.push("1. Not found");
loop.next();
}
})
}, function () {
return cb(txs, totalCount);
});
}
});
}
});
}
});
},
create_market: function(coin, exchange, market, cb) {
var newMarkets = new Markets({
market: market,
+10
View File
@@ -0,0 +1,10 @@
var mongoose = require('mongoose')
, Schema = mongoose.Schema;
var AddressTXSchema = new Schema({
a_id: { type: String, index: true},
addresses: { type: String, lowercase: true},
type: { type: String }
}, {id: false});
module.exports = mongoose.model('AddressTx', AddressTXSchema);
+28 -46
View File
@@ -1,10 +1,10 @@
var express = require('express')
, router = express.Router()
, settings = require('../lib/settings')
, locale = require('../lib/locale')
, db = require('../lib/database')
, lib = require('../lib/explorer')
, qr = require('qr-image');
, router = express.Router()
, settings = require('../lib/settings')
, locale = require('../lib/locale')
, db = require('../lib/database')
, lib = require('../lib/explorer')
, qr = require('qr-image');
function route_get_block(res, blockhash) {
lib.get_block(blockhash, function (block) {
@@ -96,25 +96,7 @@ function route_get_address(res, hash, count) {
db.get_address(hash, false, function(address) {
if (address) {
var txs = [];
var hashes = address.txs.reverse();
if (address.txs.length < count) {
count = address.txs.length;
}
lib.syncLoop(count, function (loop) {
var i = loop.iteration();
db.get_tx(hashes[i].addresses, function(tx) {
if (tx) {
txs.push(tx);
loop.next();
} else {
loop.next();
}
});
}, function(){
res.render('address', { active: 'address', address: address, txs: txs});
});
res.render('address', { active: 'address', address: address, txs: txs});
} else {
route_get_index(res, hash + ' not found');
}
@@ -192,22 +174,22 @@ router.get('/network', function(req, res) {
router.get('/reward', function(req, res){
//db.get_stats(settings.coin, function (stats) {
console.log(stats);
db.get_heavy(settings.coin, function (heavy) {
//heavy = heavy;
var votes = heavy.votes;
votes.sort(function (a,b) {
if (a.count < b.count) {
return -1;
} else if (a.count > b.count) {
return 1;
} else {
return 0;
}
});
res.render('reward', { active: 'reward', stats: stats, heavy: heavy, votes: heavy.votes });
console.log(stats);
db.get_heavy(settings.coin, function (heavy) {
//heavy = heavy;
var votes = heavy.votes;
votes.sort(function (a,b) {
if (a.count < b.count) {
return -1;
} else if (a.count > b.count) {
return 1;
} else {
return 0;
}
});
res.render('reward', { active: 'reward', stats: stats, heavy: heavy, votes: heavy.votes });
});
//});
});
@@ -281,12 +263,12 @@ router.get('/ext/summary', function(req, res) {
lib.get_difficulty(function(difficulty) {
difficultyHybrid = ''
if (difficulty['proof-of-work']) {
if (settings.index.difficulty == 'Hybrid') {
difficultyHybrid = 'POS: ' + difficulty['proof-of-stake'];
difficulty = 'POW: ' + difficulty['proof-of-work'];
} else if (settings.index.difficulty == 'POW') {
difficulty = difficulty['proof-of-work'];
} else {
if (settings.index.difficulty == 'Hybrid') {
difficultyHybrid = 'POS: ' + difficulty['proof-of-stake'];
difficulty = 'POW: ' + difficulty['proof-of-work'];
} else if (settings.index.difficulty == 'POW') {
difficulty = difficulty['proof-of-work'];
} else {
difficulty = difficulty['proof-of-stake'];
}
}
+44 -41
View File
@@ -1,11 +1,12 @@
var mongoose = require('mongoose')
, db = require('../lib/database')
, Tx = require('../models/tx')
, Address = require('../models/address')
, Richlist = require('../models/richlist')
, Stats = require('../models/stats')
, settings = require('../lib/settings')
, fs = require('fs');
, db = require('../lib/database')
, Tx = require('../models/tx')
, Address = require('../models/address')
, AddressTx = require('../models/addresstx')
, Richlist = require('../models/richlist')
, Stats = require('../models/stats')
, settings = require('../lib/settings')
, fs = require('fs');
var mode = 'update';
var database = 'index';
@@ -23,10 +24,10 @@ function usage() {
console.log('check checks index for (and adds) any missing transactions/addresses');
console.log('reindex Clears index then resyncs from genesis to current block');
console.log('');
console.log('notes:');
console.log('notes:');
console.log('* \'current block\' is the latest created block when script is executed.');
console.log('* The market database only supports (& defaults to) reindex mode.');
console.log('* If check mode finds missing data(ignoring new data since last sync),');
console.log('* If check mode finds missing data(ignoring new data since last sync),');
console.log(' index_timeout in settings.json is set too low.')
console.log('');
process.exit(0);
@@ -39,17 +40,17 @@ if (process.argv[2] == 'index') {
} else {
switch(process.argv[3])
{
case 'update':
mode = 'update';
break;
case 'check':
mode = 'check';
break;
case 'reindex':
mode = 'reindex';
break;
default:
usage();
case 'update':
mode = 'update';
break;
case 'check':
mode = 'check';
break;
case 'reindex':
mode = 'reindex';
break;
default:
usage();
}
}
} else if (process.argv[2] == 'market'){
@@ -87,7 +88,7 @@ function remove_lock(cb) {
});
} else {
return cb();
}
}
}
function is_locked(cb) {
@@ -102,7 +103,7 @@ function is_locked(cb) {
});
} else {
return cb();
}
}
}
function exit() {
@@ -140,34 +141,36 @@ is_locked(function (exists) {
db.get_stats(settings.coin, function(stats){
if (settings.heavy == true) {
db.update_heavy(settings.coin, stats.count, 20, function(){
});
}
if (mode == 'reindex') {
Tx.remove({}, function(err) {
Address.remove({}, function(err2) {
Richlist.updateOne({coin: settings.coin}, {
received: [],
balance: [],
}, function(err3) {
Stats.updateOne({coin: settings.coin}, {
last: 0,
}, function() {
console.log('index cleared (reindex)');
});
db.update_tx_db(settings.coin, 1, stats.count, settings.update_timeout, function(){
db.update_richlist('received', function(){
db.update_richlist('balance', function(){
db.get_stats(settings.coin, function(nstats){
console.log('reindex complete (block: %s)', nstats.last);
exit();
Tx.remove({}, function(err) {
Address.remove({}, function(err2) {
AddressTx.remove({}, function(err3) {
Richlist.updateOne({coin: settings.coin}, {
received: [],
balance: [],
}, function(err3) {
Stats.updateOne({coin: settings.coin}, {
last: 0,
}, function() {
console.log('index cleared (reindex)');
});
db.update_tx_db(settings.coin, 1, stats.count, settings.update_timeout, function(){
db.update_richlist('received', function(){
db.update_richlist('balance', function(){
db.get_stats(settings.coin, function(nstats){
console.log('reindex complete (block: %s)', nstats.last);
exit();
});
});
});
});
});
});
});
});
});
} else if (mode == 'check') {
db.update_tx_db(settings.coin, 1, stats.count, settings.check_timeout, function(){
db.get_stats(settings.coin, function(nstats){
+9 -15
View File
@@ -4,25 +4,25 @@ block content
- var balance = (address.received - address.sent) / 100000000;
- var sent = address.sent /100000000
- var received = address.received / 100000000
img.qrcode.pull-right.hidden-xs(src='/qr/' + address.a_id)
img.qrcode.pull-right.hidden-xs(src='/qr/' + address.a_id)
.col-xs-12.col-md-10.col-md-offset-1
.panel.panel-default.panel-address-summary
.panel-heading(style='position:relative;')
.panel-heading(style='position:relative;')
strong #{address.a_id}
if settings.labels[address.a_id]
if settings.labels[address.a_id].type
if settings.labels[address.a_id].type
label(class='label label-' + settings.labels[address.a_id].type + ' pull-right hidden-xs', style='margin-left:15px;')
=settings.labels[address.a_id].label
if settings.labels[address.a_id].url
a(href=settings.labels[address.a_id].url, target='_blank')
span.fa.fa-question-circle(style='margin-left:5px;')
else
label.label.label-default.pull-right.hidden-xs(style='margin-left:15px;')
label.label.label-default.pull-right.hidden-xs(style='margin-left:15px;')
=settings.labels[address.a_id].label
if settings.labels[address.a_id].url
a(href=settings.labels[address.a_id].url, target='_blank')
span.fa.fa-question-circle(style='margin-left:5px;')
table.table.table-bordered.table-striped.summary-table
table.table.table-bordered.table-striped.summary-table
thead
tr
if settings.show_sent_received == true
@@ -31,23 +31,17 @@ block content
if settings.show_sent_received == true
th #{settings.locale.total_received} (#{settings.symbol})
th #{settings.locale.rl_balance} (#{settings.symbol})
tbody
tbody
tr
if settings.show_sent_received == true
if settings.show_sent_received == true
td #{sent.toFixed(8)}
if address.a_id !== 'coinbase'
if settings.show_sent_received == true
td #{received.toFixed(8)}
td #{balance.toFixed(8)}
.panel.panel-default.hidden-xs
.panel-heading
strong #{settings.locale.ex_latest_transactions}
table.table.table-bordered.table-striped.history-table
include ./includes/address_history.pug
.panel.panel-default.hidden-lg.hidden-md
.panel.panel-default
.panel-heading
strong #{settings.locale.ex_latest_transactions}
table.table.table-bordered.table-striped
include ./includes/address_history.pug
.footer-padding
.footer-padding
+56 -37
View File
@@ -1,38 +1,57 @@
thead
tr
th #{settings.locale.timestamp}
th #{settings.locale.tx_hash}
th #{settings.locale.mkt_amount} (#{settings.symbol})
tbody
each tx in txs
- var time = format_unixtime(tx.timestamp)
script.
var hashAddress = "#{address.a_id}";
$(document).ready(function () {
var rtable = $('#address-txs').dataTable({
autoWidth: true,
searching: false,
ordering: false,
responsive: true,
lengthChange: true,
processing: true,
serverSide: true,
ajax: {
"url": '/ext/getaddresstxsajax',
"data": {
"address": hashAddress
}
},
rowCallback: function (row, data, index) {
var timestamp = data[0]; //variables for better readability
var txhash = data[1]; //variables for better readability
var out = data[2]; //variables for better readability
var vin = data[3]; //variables for better readability
$("td:eq(0)", row).html(timestamp);
$("td:eq(1)", row).html('<a href="/tx/' + txhash + '">' + txhash + '</a>');
var amount = 0;
if(out > 0 && vin > 0) {
amount = (out - vin) / 100000000
if (amount < 0) {
amount = amount * -1
$("td:eq(2)", row).html("-" + amount.toFixed(8)).addClass("info");
} else if (amount > 0) {
ammount = amount.toFixed(8);
$("td:eq(2)", row).html("+" + amount).addClass("info");
} else {
$("td:eq(2)", row).html(amount.toFixed(8)).addClass("info");
}
}else if(out > 0) {
amount = out / 100000000;
$("td:eq(2)", row).html("+" + amount.toFixed(8)).addClass("success");
}else{
amount = vin / 100000000;
$("td:eq(2)", row).html("-" + amount.toFixed(8)).addClass("danger");
}
},
});
});
table#address-txs.table.table-bordered.table-striped
thead
tr
td #{time}
td
a(href='/tx/' + tx.txid) #{tx.txid}
- var out = 0
- var vin = 0
each r in tx.vout
if r.addresses == address.a_id
- out = r.amount
each s in tx.vin
if s.addresses == address.a_id
- vin = s.amount
if out > 0 && vin > 0
td.info
- var amount = (out - vin) / 100000000
if amount < 0
- amount = amount * -1
| - #{amount.toFixed(8)}
else if amount > 0
| + #{amount.toFixed(8)}
else
| #{amount.toFixed(8)}
else if out > 0
td.success
- var amount = out / 100000000
| + #{amount.toFixed(8)}
else
td.danger
- var amount = vin / 100000000
| - #{amount.toFixed(8)}
th.hidden-xs #{settings.locale.timestamp}
th.hidden-xs #{settings.locale.tx_hash}
th #{settings.locale.mkt_amount} (#{settings.symbol})
tbody