|
|
blockchainExplorer = function(){
|
|
|
|
|
|
// Init array
|
|
|
var _known_blocks = null;
|
|
|
var _liste_blocks = null;
|
|
|
var _classes = ['bg-grey-even','bg-grey-odd'];
|
|
|
var _cur_class = 0;
|
|
|
var _cur_methode = 'hasard';
|
|
|
var _mode = 1;
|
|
|
var _infos = false;
|
|
|
var _flag_nav = true;
|
|
|
|
|
|
function _precisionRound(number) {
|
|
|
var precision = 4;
|
|
|
var factor = Math.pow(10, precision);
|
|
|
return Math.round((number/100000000) * factor) / factor;
|
|
|
}
|
|
|
|
|
|
function _getblockNameFromHash(hash)
|
|
|
{
|
|
|
var retour = '';
|
|
|
if (_known_blocks != null)
|
|
|
_known_blocks.forEach(function(item){
|
|
|
if (hash == item.hash) retour = item.name;
|
|
|
});
|
|
|
return retour;
|
|
|
}
|
|
|
|
|
|
function _getblocHashFromName(name)
|
|
|
{
|
|
|
var retour = '';
|
|
|
if (_known_blocks != null)
|
|
|
_known_blocks.forEach(function(item){
|
|
|
if (name == item.name) retour = item.hash;
|
|
|
});
|
|
|
return retour;
|
|
|
}
|
|
|
|
|
|
function _convertUTCDateToLocalDate(date) {
|
|
|
var newDate = new Date(date.getTime()+date.getTimezoneOffset()*60*1000);
|
|
|
|
|
|
var offset = date.getTimezoneOffset() / 60;
|
|
|
var hours = date.getHours();
|
|
|
|
|
|
newDate.setHours(hours - offset);
|
|
|
|
|
|
return newDate;
|
|
|
}
|
|
|
|
|
|
function _formatDate(unixtime)
|
|
|
{
|
|
|
var ladate = new Date(unixtime*1000);
|
|
|
var ladateStr = "";
|
|
|
|
|
|
// ladate = _convertUTCDateToLocalDate(ladate);
|
|
|
|
|
|
ladateStr += ladate.getFullYear();
|
|
|
ladateStr += "/" +("00"+(ladate.getMonth()+1)).slice(-2);
|
|
|
ladateStr += "/" +("00" + ladate.getDate()).slice(-2);
|
|
|
ladateStr += " " +("00" + ladate.getHours()).slice(-2);
|
|
|
ladateStr += ":" +("00" + ladate.getMinutes()).slice(-2);
|
|
|
// ladateStr += ":" +("00" + ladate.getSeconds()).slice(-2);
|
|
|
|
|
|
return ladateStr;
|
|
|
}
|
|
|
|
|
|
function _addInfoForBlock(block)
|
|
|
{
|
|
|
var contenu = '';
|
|
|
var downloadingImage = new Image();
|
|
|
var div_label = block.height;
|
|
|
|
|
|
_cur_class = 1 - _cur_class;
|
|
|
|
|
|
_flag_nav = false;
|
|
|
|
|
|
blockName = _getblockNameFromHash(block.hash);
|
|
|
if (block.hash == _liste_blocks['TOP']) {
|
|
|
blockName = 'LAST BLOCK';
|
|
|
if (_mode == 1) div_label = 'LAST';
|
|
|
}
|
|
|
if (blockName == '') blockName = 'block';
|
|
|
else blockName = '<b>'+blockName+'</b>';
|
|
|
|
|
|
visibility='hidden';
|
|
|
if (_infos) visibility='visible';
|
|
|
|
|
|
contenu += '<div id="img_'+block.height+'" style="color:black;height:220px">';
|
|
|
contenu += ' <table class="block_infos" width="100%" align="center" height="220px" style="margin-top:3px;visibility:'+visibility+';background:rgba(255,255,255,0.7)">';
|
|
|
contenu += ' <tr><td>'+blockName+'</td><td align="right"><b>'+block.height+'</b></td></tr>';
|
|
|
contenu += ' <tr><td>timestamp </td><td align="right"><b>'+_formatDate(block.time)+'</b></td></tr>';
|
|
|
contenu += ' <tr><td>nonce</td><td align="right"><b>'+block.nonce+'</b></td></tr>';
|
|
|
contenu += ' <tr><td>nb tx</td><td align="right"><b>'+block.n_tx+'</b></td></tr>';
|
|
|
contenu += ' <tr><td>outputs</td><td align="right"><b>'+_precisionRound(block.topisto_outputs).toFixed(4)+'</b></td></tr>';
|
|
|
contenu += ' <tr><td>inputs</td><td align="right"><b>'+_precisionRound(block.topisto_inputs).toFixed(4)+'</b></td></tr>';
|
|
|
contenu += ' <tr><td>fees</td><td align="right"><b>'+_precisionRound(block.topisto_fees).toFixed(4)+'</b></td></tr>';
|
|
|
contenu += ' <tr><td>reward</td><td align="right"><b>'+_precisionRound(block.topisto_reward).toFixed(4)+'</b></td></tr>';
|
|
|
contenu += ' </table>';
|
|
|
contenu += '</div>';
|
|
|
|
|
|
|
|
|
$('#info_'+div_label).html(contenu);
|
|
|
|
|
|
downloadingImage.onload = function(){
|
|
|
var div0 = document.getElementById('img_'+block.height);
|
|
|
div0.style.backgroundImage = "url(" + this.src + ")";
|
|
|
div0.style.backgroundRepeat = "no-repeat";
|
|
|
div0.style.backgroundPosition = "center";
|
|
|
div0.style.backgroundSize = "auto 100%";
|
|
|
_flag_nav = true;
|
|
|
};
|
|
|
downloadingImage.src = 'images/block_image.php?methode='+_cur_methode+'&hash='+block.hash;
|
|
|
|
|
|
return true;
|
|
|
}
|
|
|
|
|
|
function _addDiv(block_height)
|
|
|
{
|
|
|
var contenu = '';
|
|
|
|
|
|
contenu += '<div id="block_'+block_height+'" class="container-fluid '+_classes[_cur_class]+'">';
|
|
|
contenu += ' <div class="row">';
|
|
|
contenu += '###BLOCK_DESC###';
|
|
|
contenu += ' </div>';
|
|
|
contenu += '</div>';
|
|
|
|
|
|
return contenu;
|
|
|
}
|
|
|
|
|
|
function _addDivForBlock(block_height, onTop = false)
|
|
|
{
|
|
|
var lediv = document.getElementById('info_'+block_height);
|
|
|
if (lediv === null)
|
|
|
{
|
|
|
var tmp;
|
|
|
var contenu = _addDiv(block_height);
|
|
|
var block_desc = '';
|
|
|
|
|
|
block_desc += ' <div class="col-sm-12" id="info_'+block_height+'">';
|
|
|
block_desc += ' <div class="loading">LOADING ...</div>';
|
|
|
block_desc += ' </div>';
|
|
|
|
|
|
tmp = contenu.replace('###BLOCK_DESC###',block_desc)
|
|
|
|
|
|
if (onTop) {
|
|
|
tmp += $('#blockchain').html();
|
|
|
$('#blockchain').html(tmp);
|
|
|
} else {
|
|
|
$('#blockchain').append(tmp);
|
|
|
}
|
|
|
}
|
|
|
return true;
|
|
|
}
|
|
|
|
|
|
function _addDivForVoid()
|
|
|
{
|
|
|
return _addDivForBlock('void');
|
|
|
}
|
|
|
|
|
|
function _gotoBlock(block_name)
|
|
|
{
|
|
|
$(document).scrollTop( $("#explorer").offset().top );
|
|
|
// Bloquer la navigation pendant le calcul
|
|
|
if (!flag_nav)
|
|
|
{
|
|
|
window.alert('A block image is currently computed, please wait ...');
|
|
|
return false;
|
|
|
}
|
|
|
flag_nav = false;
|
|
|
|
|
|
if (block_name == 'NEXT')
|
|
|
{
|
|
|
flag_nav = true;
|
|
|
|
|
|
// Supprimer un block
|
|
|
if (cur_height.length < 3)
|
|
|
{
|
|
|
window.alert('No Next Block, you are at '+$('#blockSelector').val()+' block !');
|
|
|
return false;
|
|
|
}
|
|
|
|
|
|
_liste_blocks['PREVIOUS'] = _liste_blocks['BLOCK_'+cur_height[cur_height.length-1]];
|
|
|
cur_height.pop();
|
|
|
|
|
|
_toggleForwardBtn();
|
|
|
|
|
|
$('#block_'+cur_height[cur_height.length-2]).slideDown(400, function() {
|
|
|
// Animation complete.
|
|
|
$('#blockchain').children('div:last').remove();
|
|
|
_cur_class = 1 - _cur_class;
|
|
|
});
|
|
|
|
|
|
} else {
|
|
|
// Ajouter un block
|
|
|
_addDivForBlock(cur_height[cur_height.length-1] - 1);
|
|
|
|
|
|
// Décaler d'un block vers le haut
|
|
|
if (cur_height.length > 1) $('#block_'+cur_height[cur_height.length-2]).slideUp();
|
|
|
|
|
|
block_hash = '';
|
|
|
if (block_name != 'LAST') block_hash = '?block_hash='+_liste_blocks[block_name];
|
|
|
$.getJSON('data/getBlockInfo.php'+block_hash, function( data ) {
|
|
|
_liste_blocks['PREVIOUS'] = data.prev;
|
|
|
_liste_blocks['BLOCK_'+data.height] = data.hash;
|
|
|
_addInfoForBlock(data);
|
|
|
|
|
|
_toggleForwardBtn();
|
|
|
});
|
|
|
}
|
|
|
|
|
|
return true;
|
|
|
}
|
|
|
|
|
|
function _addTopBlock(data, flag = false)
|
|
|
{
|
|
|
if (flag) return "_addTopBlock";
|
|
|
|
|
|
var old_hash = _liste_blocks['TOP'];
|
|
|
|
|
|
if (old_hash == data.hash) return false;
|
|
|
|
|
|
// Maintenir la liste des blocks
|
|
|
_liste_blocks['TOP'] = data.hash;
|
|
|
_liste_blocks['BLOCK_'+data.height] = data.hash;
|
|
|
|
|
|
// Rafraîchir l'ancien block TOP
|
|
|
if (_mode == 0) {
|
|
|
$.getJSON('data/getBlockInfo.php?block_hash='+old_hash, function( old ) {
|
|
|
_addInfoForBlock(old);
|
|
|
});
|
|
|
_addDivForBlock(data.height,true);
|
|
|
}
|
|
|
|
|
|
// Mettre les infos dans le div
|
|
|
_addInfoForBlock(data);
|
|
|
|
|
|
topistoConsole.log('Last Block on top : '+data.hash);
|
|
|
}
|
|
|
|
|
|
function _maintenirListe(data){
|
|
|
_liste_blocks['BLOCK_'+data.height] = data.hash;
|
|
|
_liste_blocks['LENGTH'] += 1;
|
|
|
|
|
|
// Récursivité pour précharger par paquets
|
|
|
// Tant qu'on n'est pas sur le GENESIS
|
|
|
if (data.height > 0)
|
|
|
switch(_mode)
|
|
|
{
|
|
|
case 0:
|
|
|
// En mode "Full Blockchain", on suit le chainage
|
|
|
_liste_blocks['BOTTOM'] = data.prev;
|
|
|
break;
|
|
|
case 1:
|
|
|
// En mode "Blocks Connus", on prend le prochain de la liste
|
|
|
_liste_blocks['BOTTOM'] = _known_blocks[0].hash;
|
|
|
for(i = 0; i < _known_blocks.length; i++){
|
|
|
if (data.height == _known_blocks[i].height)
|
|
|
_liste_blocks['BOTTOM'] = _known_blocks[i+1].hash;
|
|
|
}
|
|
|
//_liste_blocks['BOTTOM'] = _known_blocks[_liste_blocks['LENGTH']-1].hash;
|
|
|
break;
|
|
|
}
|
|
|
|
|
|
if (data.height > 0)
|
|
|
if (_liste_blocks['LENGTH'] % 15)
|
|
|
_addBottomBlock();
|
|
|
}
|
|
|
|
|
|
function _addBottomBlock()
|
|
|
{
|
|
|
// Mettre les infos du block
|
|
|
block_hash = '?block_hash='+_liste_blocks['BOTTOM'];
|
|
|
$.getJSON('data/getBlockInfo.php'+block_hash, function( data ) {
|
|
|
|
|
|
console.log('add '+ data.height + ' : ' + _liste_blocks['BOTTOM']);
|
|
|
|
|
|
// Ajouter un div
|
|
|
_addDivForBlock(data.height, false);
|
|
|
|
|
|
// Mettre les infos dans le div
|
|
|
_addInfoForBlock(data);
|
|
|
|
|
|
// Maintenir la Liste
|
|
|
_maintenirListe(data);
|
|
|
});
|
|
|
}
|
|
|
|
|
|
function _initBlockchain(block_name)
|
|
|
{
|
|
|
var block_hash_url = 'data/getBlockInfo.php';
|
|
|
|
|
|
_liste_blocks = [];
|
|
|
_liste_blocks['LENGTH'] = 0;
|
|
|
|
|
|
$(document).scrollTop( $("#explorer").offset().top );
|
|
|
$('#blockchain').html('');
|
|
|
|
|
|
if (block_name != 'LAST') block_hash_url += '?block_hash='+_getblocHashFromName(block_name);
|
|
|
|
|
|
$.getJSON(block_hash_url, function( data ) {
|
|
|
|
|
|
div_label = data.height;
|
|
|
if (_mode == 1)
|
|
|
if (block_name == 'LAST')
|
|
|
div_label = 'LAST';
|
|
|
|
|
|
_liste_blocks['TOP'] = data.hash;
|
|
|
|
|
|
_addDivForBlock(div_label);
|
|
|
|
|
|
_addInfoForBlock(data);
|
|
|
|
|
|
_maintenirListe(data);
|
|
|
|
|
|
// Cela fout le boxon pour l'instant
|
|
|
blockchainListener.addBlockHook(_addTopBlock);
|
|
|
});
|
|
|
|
|
|
return true;
|
|
|
}
|
|
|
|
|
|
function _blockSelectorChange()
|
|
|
{
|
|
|
_initBlockchain($('#blockSelector').val());
|
|
|
}
|
|
|
|
|
|
function _initBlockSelector()
|
|
|
{
|
|
|
// Init the selector
|
|
|
var select = $('#blockSelector');
|
|
|
|
|
|
$.each(_liste_blocks, function (key, bloc) {
|
|
|
select.append(new Option(bloc.name, bloc.name));
|
|
|
});
|
|
|
}
|
|
|
|
|
|
function _init(mode, infos)
|
|
|
{
|
|
|
_mode = mode;
|
|
|
_infos = infos;
|
|
|
|
|
|
if (_known_blocks == null)
|
|
|
{
|
|
|
$.getJSON('data/getKnownBlocksList.php', function( data ) {
|
|
|
|
|
|
_known_blocks = data;
|
|
|
_known_blocks.sort(function(a,b){
|
|
|
// sort desc ...
|
|
|
if (parseInt(a.height) < parseInt(b.height)) return 1;
|
|
|
if (parseInt(a.height) > parseInt(b.height)) return -1;
|
|
|
return 0;
|
|
|
});
|
|
|
return true;
|
|
|
});
|
|
|
}
|
|
|
|
|
|
return _initBlockchain('LAST');
|
|
|
}
|
|
|
|
|
|
function _toggleInfos()
|
|
|
{
|
|
|
var infos = Array.from(document.getElementsByClassName('block_infos'));
|
|
|
_infos = ! _infos;
|
|
|
infos.forEach((item, index) => {
|
|
|
if (_infos) item.style.visibility = 'visible';
|
|
|
else item.style.visibility = 'hidden';
|
|
|
});
|
|
|
}
|
|
|
|
|
|
function _getLength() {
|
|
|
if ( _liste_blocks === null) return 0;
|
|
|
return _liste_blocks['LENGTH'];
|
|
|
}
|
|
|
|
|
|
return {
|
|
|
|
|
|
addTopBlock: _addTopBlock,
|
|
|
addBottomBlock: _addBottomBlock,
|
|
|
getblocHashFromName: _getblocHashFromName,
|
|
|
|
|
|
toggleInfos: _toggleInfos,
|
|
|
getLength: _getLength,
|
|
|
|
|
|
init: _init
|
|
|
};
|
|
|
}();
|