mirror of
https://github.com/seigler/dash-visualizer
synced 2025-07-27 09:46:09 +00:00
publish: ⚡ Change main live canvas to act like a mempool
generated from commit a69343066a57714e451b4ba65608b63ad38c0266
This commit is contained in:
parent
473b01e2f0
commit
c99258d224
5 changed files with 198 additions and 116 deletions
26
bundle.css
26
bundle.css
|
@ -34,7 +34,17 @@ a {
|
||||||
margin-left: 80vw;
|
margin-left: 80vw;
|
||||||
padding-top: 2.5vw;
|
padding-top: 2.5vw;
|
||||||
}
|
}
|
||||||
.block:first-child {
|
#hero, .block {
|
||||||
|
width: 15vw;
|
||||||
|
height: 15vw;
|
||||||
|
-webkit-box-shadow: 0.1em 0.1em 1em hsla(0, 0%, 0%, 0.5);
|
||||||
|
box-shadow: 0.1em 0.1em 1em hsla(0, 0%, 0%, 0.5);
|
||||||
|
background-color: #dad7b7;
|
||||||
|
margin: 0 auto 1em;
|
||||||
|
position: relative;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
#hero {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
left: 41.125%;
|
left: 41.125%;
|
||||||
top: 50%;
|
top: 50%;
|
||||||
|
@ -45,26 +55,16 @@ a {
|
||||||
transform: translate(-50%,-50%);
|
transform: translate(-50%,-50%);
|
||||||
}
|
}
|
||||||
@media (max-height: 82.5vw) {
|
@media (max-height: 82.5vw) {
|
||||||
.block:first-child {
|
#hero {
|
||||||
width: calc(100vh - 5vw);
|
width: calc(100vh - 5vw);
|
||||||
height: calc(100vh - 5vw);
|
height: calc(100vh - 5vw);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.block.solo {
|
#hero.solo {
|
||||||
left: 50%;
|
left: 50%;
|
||||||
width: 95vmin;
|
width: 95vmin;
|
||||||
height: 95vmin;
|
height: 95vmin;
|
||||||
}
|
}
|
||||||
.block {
|
|
||||||
width: 15vw;
|
|
||||||
height: 15vw;
|
|
||||||
-webkit-box-shadow: 0.1em 0.1em 1em hsla(0, 0%, 0%, 0.5);
|
|
||||||
box-shadow: 0.1em 0.1em 1em hsla(0, 0%, 0%, 0.5);
|
|
||||||
background-color: #dad7b7;
|
|
||||||
margin: 0 auto 1em;
|
|
||||||
position: relative;
|
|
||||||
overflow: hidden;
|
|
||||||
}
|
|
||||||
.explorer-link {
|
.explorer-link {
|
||||||
display: none;
|
display: none;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
|
|
File diff suppressed because one or more lines are too long
283
bundle.js
283
bundle.js
|
@ -18863,6 +18863,13 @@ var App =
|
||||||
function () {
|
function () {
|
||||||
function App() {
|
function App() {
|
||||||
_classCallCheck(this, App);
|
_classCallCheck(this, App);
|
||||||
|
|
||||||
|
this.blockRefs = [];
|
||||||
|
this.mempoolRefs = [];
|
||||||
|
this.blockList = document.getElementById('blockList');
|
||||||
|
this.connectionStatus = document.getElementById('connectionStatus');
|
||||||
|
this.hero = document.getElementById('hero');
|
||||||
|
this.blockColors = ['000000'];
|
||||||
}
|
}
|
||||||
|
|
||||||
_createClass(App, [{
|
_createClass(App, [{
|
||||||
|
@ -18870,94 +18877,109 @@ function () {
|
||||||
value: function () {
|
value: function () {
|
||||||
var _init = _asyncToGenerator(
|
var _init = _asyncToGenerator(
|
||||||
/*#__PURE__*/
|
/*#__PURE__*/
|
||||||
regeneratorRuntime.mark(function _callee() {
|
regeneratorRuntime.mark(function _callee2() {
|
||||||
var _this = this;
|
var _this = this;
|
||||||
|
|
||||||
var block, txs, pages, prevHash, i;
|
var block, txs, pages, prevHash;
|
||||||
return regeneratorRuntime.wrap(function _callee$(_context) {
|
return regeneratorRuntime.wrap(function _callee2$(_context2) {
|
||||||
while (1) {
|
while (1) {
|
||||||
switch (_context.prev = _context.next) {
|
switch (_context2.prev = _context2.next) {
|
||||||
case 0:
|
case 0:
|
||||||
this.domRefList = [];
|
|
||||||
this.blockList = document.getElementById('blockList');
|
|
||||||
this.blockList.style.setProperty('--private-color', _constants.COLORS["private"]);
|
|
||||||
this.blockList.style.setProperty('--instant-color', _constants.COLORS.instant);
|
|
||||||
this.connectionStatus = document.getElementById('connectionStatus');
|
|
||||||
this.currentBlock = document.createElement('div');
|
|
||||||
this.currentBlock.className = 'block';
|
|
||||||
this.blockList.appendChild(this.currentBlock);
|
|
||||||
this.blockColors = ['000000'];
|
|
||||||
block = new URL(window.location).searchParams.get('block');
|
block = new URL(window.location).searchParams.get('block');
|
||||||
|
|
||||||
if (!(block != null)) {
|
if (!(block != null)) {
|
||||||
_context.next = 26;
|
_context2.next = 5;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// display one block
|
return _context2.delegateYield(
|
||||||
this.currentBlock.classList.add('solo');
|
/*#__PURE__*/
|
||||||
this.connectionStatus.className = 'is-loading';
|
regeneratorRuntime.mark(function _callee() {
|
||||||
txs = [];
|
var txListener, i;
|
||||||
pages = 1;
|
return regeneratorRuntime.wrap(function _callee$(_context) {
|
||||||
prevHash = null;
|
while (1) {
|
||||||
i = 0;
|
switch (_context.prev = _context.next) {
|
||||||
|
case 0:
|
||||||
|
// display one block
|
||||||
|
_this.hero.classList.add('solo');
|
||||||
|
|
||||||
case 17:
|
_this.connectionStatus.className = 'is-loading';
|
||||||
if (!(i < pages)) {
|
txs = [];
|
||||||
_context.next = 23;
|
pages = 1;
|
||||||
break;
|
prevHash = null;
|
||||||
}
|
txListener = _this.onTransactionBuilder(_this.hero, false);
|
||||||
|
i = 0;
|
||||||
|
|
||||||
_context.next = 20;
|
case 7:
|
||||||
return fetch("https://insight.dash.org/insight-api/txs?block=".concat(block, "&pageNum=").concat(i)).then(function (resp) {
|
if (!(i < pages)) {
|
||||||
return resp.json();
|
_context.next = 13;
|
||||||
}).then(function (thisBlockData) {
|
break;
|
||||||
// console.log({i, pages, prevHash, thisBlockData});
|
}
|
||||||
if (!prevHash && thisBlockData.txs.length > 0) {
|
|
||||||
return fetch('https://insight.dash.org/insight-api/block-index/' + (thisBlockData.txs[0].blockheight - 1)).then(function (resp) {
|
|
||||||
return resp.json();
|
|
||||||
}).then(function (prevBlockData) {
|
|
||||||
prevHash = prevBlockData.blockHash;
|
|
||||||
_this.blockColors = App.generateColors(prevHash);
|
|
||||||
pages = thisBlockData.pagesTotal;
|
|
||||||
|
|
||||||
for (var j = 0; j < thisBlockData.txs.length; ++j) {
|
_context.next = 10;
|
||||||
_this.onTransaction(thisBlockData.txs[j]);
|
return fetch("https://insight.dash.org/insight-api/txs?block=".concat(block, "&pageNum=").concat(i)).then(function (resp) {
|
||||||
|
return resp.json();
|
||||||
|
}).then(function (thisBlockData) {
|
||||||
|
if (!prevHash && thisBlockData.txs.length > 0) {
|
||||||
|
return fetch('https://insight.dash.org/insight-api/block-index/' + (thisBlockData.txs[0].blockheight - 1)).then(function (resp) {
|
||||||
|
return resp.json();
|
||||||
|
}).then(function (prevBlockData) {
|
||||||
|
prevHash = prevBlockData.blockHash;
|
||||||
|
_this.blockColors = App.generateColors(prevHash);
|
||||||
|
|
||||||
|
_this.applyColors(_this.hero);
|
||||||
|
|
||||||
|
pages = thisBlockData.pagesTotal;
|
||||||
|
|
||||||
|
for (var j = 0; j < thisBlockData.txs.length; ++j) {
|
||||||
|
txListener(thisBlockData.txs[j]);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
for (var j = 0; j < thisBlockData.txs.length; ++j) {
|
||||||
|
txListener(thisBlockData.txs[j]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
case 10:
|
||||||
|
++i;
|
||||||
|
_context.next = 7;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 13:
|
||||||
|
_this.connectionStatus.className = 'is-loaded';
|
||||||
|
|
||||||
|
case 14:
|
||||||
|
case "end":
|
||||||
|
return _context.stop();
|
||||||
}
|
}
|
||||||
});
|
|
||||||
} else {
|
|
||||||
for (var j = 0; j < thisBlockData.txs.length; ++j) {
|
|
||||||
_this.onTransaction(thisBlockData.txs[j]);
|
|
||||||
}
|
}
|
||||||
}
|
}, _callee);
|
||||||
});
|
})(), "t0", 3);
|
||||||
|
|
||||||
case 20:
|
case 3:
|
||||||
++i;
|
_context2.next = 13;
|
||||||
_context.next = 17;
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 23:
|
case 5:
|
||||||
this.connectionStatus.className = 'is-loaded';
|
_context2.next = 7;
|
||||||
_context.next = 34;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 26:
|
|
||||||
_context.next = 28;
|
|
||||||
return fetch('https://insight.dash.org/api/status?q=getLastBlockHash').then(function (resp) {
|
return fetch('https://insight.dash.org/api/status?q=getLastBlockHash').then(function (resp) {
|
||||||
return resp.json();
|
return resp.json();
|
||||||
}).then(function (data) {
|
}).then(function (data) {
|
||||||
_this.blockColors = App.generateColors(data.lastblockhash);
|
_this.blockColors = App.generateColors(data.lastblockhash);
|
||||||
|
|
||||||
|
_this.applyColors(_this.hero);
|
||||||
});
|
});
|
||||||
|
|
||||||
case 28:
|
case 7:
|
||||||
this.socket = _socket["default"].connect("https://insight.dash.org:443/");
|
this.socket = _socket["default"].connect("https://insight.dash.org:443/");
|
||||||
this.socket.on('connect', function () {
|
this.socket.on('connect', function () {
|
||||||
_this.connectionStatus.className = 'is-connected'; // Join the room.
|
_this.connectionStatus.className = 'is-connected'; // Join the room.
|
||||||
|
|
||||||
_this.socket.emit('subscribe', 'inv');
|
_this.socket.emit('subscribe', 'inv');
|
||||||
});
|
});
|
||||||
this.socket.on('tx', this.onTransaction.bind(this));
|
this.socket.on('tx', this.onTransactionBuilder(this.hero, true).bind(this));
|
||||||
this.socket.on('block', this.onBlock.bind(this));
|
this.socket.on('block', this.onBlock.bind(this));
|
||||||
this.socket.on('disconnect', function () {
|
this.socket.on('disconnect', function () {
|
||||||
_this.connectionStatus.className = 'is-disconnected';
|
_this.connectionStatus.className = 'is-disconnected';
|
||||||
|
@ -18966,12 +18988,12 @@ function () {
|
||||||
_this.connectionStatus.className = 'is-connecting';
|
_this.connectionStatus.className = 'is-connecting';
|
||||||
});
|
});
|
||||||
|
|
||||||
case 34:
|
case 13:
|
||||||
case "end":
|
case "end":
|
||||||
return _context.stop();
|
return _context2.stop();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}, _callee, this);
|
}, _callee2, this);
|
||||||
}));
|
}));
|
||||||
|
|
||||||
function init() {
|
function init() {
|
||||||
|
@ -18980,9 +19002,23 @@ function () {
|
||||||
|
|
||||||
return init;
|
return init;
|
||||||
}()
|
}()
|
||||||
|
}, {
|
||||||
|
key: "applyColors",
|
||||||
|
value: function applyColors(target) {
|
||||||
|
for (var i in this.blockColors) {
|
||||||
|
var color = this.blockColors[i];
|
||||||
|
target.style.setProperty("--color-".concat(i), '#' + color);
|
||||||
|
}
|
||||||
|
}
|
||||||
}, {
|
}, {
|
||||||
key: "onBlock",
|
key: "onBlock",
|
||||||
value: function onBlock(data) {
|
value: function onBlock(data) {
|
||||||
|
var _this2 = this;
|
||||||
|
|
||||||
|
var completedBlock = document.createElement('div');
|
||||||
|
completedBlock.className = 'block';
|
||||||
|
completedBlock.id = data;
|
||||||
|
this.applyColors(completedBlock);
|
||||||
this.blockColors = App.generateColors(data);
|
this.blockColors = App.generateColors(data);
|
||||||
var blockLink = document.createElement('a');
|
var blockLink = document.createElement('a');
|
||||||
blockLink.className = 'explorer-link';
|
blockLink.className = 'explorer-link';
|
||||||
|
@ -18990,56 +19026,101 @@ function () {
|
||||||
blockLink.target = '_blank';
|
blockLink.target = '_blank';
|
||||||
blockLink.setAttribute('rel', 'noopener');
|
blockLink.setAttribute('rel', 'noopener');
|
||||||
blockLink.appendChild(document.createTextNode('🗗'));
|
blockLink.appendChild(document.createTextNode('🗗'));
|
||||||
this.currentBlock.appendChild(blockLink);
|
fetch('https://insight.dash.org/insight-api/block/' + data).then(function (resp) {
|
||||||
this.currentBlock = document.createElement('div');
|
return resp.json();
|
||||||
this.currentBlock.className = 'block';
|
}).then(function (data) {
|
||||||
|
var mined = [];
|
||||||
|
|
||||||
if (this.domRefList.unshift(this.currentBlock) > 16) {
|
for (var i in data.tx) {
|
||||||
var toDelete = this.domRefList.pop();
|
var txid = data.tx[i];
|
||||||
toDelete.remove();
|
var paint = document.getElementById(txid);
|
||||||
}
|
|
||||||
|
|
||||||
this.blockList.insertBefore(this.currentBlock, this.blockList.firstChild);
|
if (paint) {
|
||||||
|
mined.push(paint);
|
||||||
|
completedBlock.insertBefore(paint, completedBlock.firstChild);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_this2.mempoolRefs = _this2.mempoolRefs.filter(function (item) {
|
||||||
|
return !mined.includes(item);
|
||||||
|
});
|
||||||
|
|
||||||
|
_this2.mempoolRefs.forEach(function (item) {
|
||||||
|
item.classList.add('stale');
|
||||||
|
item.data_ignored = item.data_ignored ? item.data_ignored + 1 : 1;
|
||||||
|
});
|
||||||
|
|
||||||
|
_this2.mempoolRefs.filter(function (item) {
|
||||||
|
if (item.data_ignored > 4) {
|
||||||
|
_this2.hero.removeChild(item);
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
|
||||||
|
completedBlock.appendChild(blockLink);
|
||||||
|
|
||||||
|
if (_this2.blockRefs.unshift(_this2.completedBlock) > 8) {
|
||||||
|
var toDelete = _this2.blockRefs.pop();
|
||||||
|
|
||||||
|
toDelete.remove();
|
||||||
|
}
|
||||||
|
|
||||||
|
_this2.blockList.insertBefore(completedBlock, _this2.blockList.firstChild);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}, {
|
}, {
|
||||||
key: "onTransaction",
|
key: "onTransactionBuilder",
|
||||||
value: function onTransaction(data) {
|
value: function onTransactionBuilder(target) {
|
||||||
var isMixing = App.isPrivateSend(data.vout);
|
var _this3 = this;
|
||||||
var isInstant = data.txlock || data.vin && data.vin.length <= 4;
|
|
||||||
var tx = {
|
var addToMempool = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
|
||||||
mixing: isMixing,
|
return function (data) {
|
||||||
instant: isInstant,
|
var isMixing = App.isPrivateSend(data.vout);
|
||||||
value: data.valueOut,
|
var isInstant = data.txlock || data.vin && data.vin.length <= 4;
|
||||||
x: parseInt(data.txid.slice(0, 4), 16) / 65536,
|
var isSimple = data.txlock || data.vin && data.vin.length <= 1;
|
||||||
y: parseInt(data.txid.slice(4, 8), 16) / 65536,
|
var tx = {
|
||||||
rotation: parseInt(data.txid.slice(16, 17), 16) / 16,
|
id: data.txid,
|
||||||
paintIndex: parseInt(data.txid.slice(17, 21), 16) / 65536,
|
mixing: isMixing,
|
||||||
color: isMixing ? _constants.COLORS["private"] : isInstant ? _constants.COLORS.instant : this.blockColors[Math.floor(parseInt(data.txid.slice(21, 23), 16) / 256 * this.blockColors.length)]
|
instant: isInstant,
|
||||||
|
simple: isSimple,
|
||||||
|
value: data.valueOut,
|
||||||
|
x: parseInt(data.txid.slice(0, 4), 16) / 65536,
|
||||||
|
y: parseInt(data.txid.slice(4, 8), 16) / 65536,
|
||||||
|
rotation: parseInt(data.txid.slice(16, 17), 16) / 16,
|
||||||
|
paintIndex: parseInt(data.txid.slice(17, 21), 16) / 65536,
|
||||||
|
color: isMixing ? _constants.COLORS.black : !isSimple ? _constants.COLORS.white : 'var(--color-' + Math.floor(parseInt(data.txid.slice(21, 23), 16) / 256 * _this3.blockColors.length) + ')'
|
||||||
|
};
|
||||||
|
console.log('tx: ' + tx.value + (tx.mixing ? ' mixing' : '') + (isInstant ? ' instant' : ''));
|
||||||
|
var paint = document.createElement('div');
|
||||||
|
paint.id = tx.id;
|
||||||
|
paint.classList.add('paint');
|
||||||
|
paint.style.maskImage = 'url(assets/paint/' + (tx.value > 10 ? _constants.PAINT.big[Math.floor(tx.paintIndex * 12)] : _constants.PAINT.small[Math.floor(tx.paintIndex * 11)]) + ')';
|
||||||
|
paint.style.setProperty('-webkit-mask-image', paint.style.maskImage);
|
||||||
|
paint.style.setProperty('--x', tx.x);
|
||||||
|
paint.style.setProperty('--y', tx.y);
|
||||||
|
paint.style.setProperty('--size', Math.log(1 + tx.value) / Math.log(2));
|
||||||
|
paint.style.setProperty('--rotation', tx.rotation * 360 + 'deg');
|
||||||
|
paint.style.setProperty('--color', tx.color);
|
||||||
|
|
||||||
|
if (addToMempool && _this3.mempoolRefs.unshift(paint) > 200) {
|
||||||
|
var toDelete = _this3.mempoolRefs.pop();
|
||||||
|
|
||||||
|
toDelete.remove();
|
||||||
|
}
|
||||||
|
|
||||||
|
target.appendChild(paint);
|
||||||
};
|
};
|
||||||
console.log('tx: ' + tx.value + (tx.mixing ? ' mixing' : '') + (tx.instant ? ' instant' : ''));
|
|
||||||
var paint = document.createElement('div');
|
|
||||||
paint.classList.add('paint');
|
|
||||||
paint.style.maskImage = 'url(assets/paint/' + (tx.value > 10 ? _constants.PAINT.big[Math.floor(tx.paintIndex * 12)] : _constants.PAINT.small[Math.floor(tx.paintIndex * 11)]) + ')';
|
|
||||||
paint.style.setProperty('-webkit-mask-image', paint.style.maskImage);
|
|
||||||
paint.style.setProperty('--x', tx.x);
|
|
||||||
paint.style.setProperty('--y', tx.y);
|
|
||||||
paint.style.setProperty('--size', Math.log(1 + tx.value) / Math.log(2));
|
|
||||||
paint.style.setProperty('--rotation', tx.rotation * 360 + 'deg');
|
|
||||||
paint.style.setProperty('--color', '#' + tx.color);
|
|
||||||
this.currentBlock.appendChild(paint, this.currentBlock.firstChild);
|
|
||||||
}
|
}
|
||||||
}], [{
|
}], [{
|
||||||
key: "generateColors",
|
key: "generateColors",
|
||||||
value: function generateColors(blockHash) {
|
value: function generateColors(blockHash) {
|
||||||
// https://github.com/c0bra/color-scheme-js
|
|
||||||
var schemeTypes = ['contrast', 'triade', 'triade', 'tetrade', 'tetrade', 'analogic', 'analogic', 'analogic', 'analogic'];
|
|
||||||
var hue = Math.floor(parseInt(blockHash.slice(-3), 16) / 4096 * 360);
|
var hue = Math.floor(parseInt(blockHash.slice(-3), 16) / 4096 * 360);
|
||||||
var schemeFraction = parseInt(blockHash.slice(-5, -3), 16) / 256;
|
|
||||||
var scheme = schemeTypes[Math.floor(schemeFraction * schemeTypes.length)];
|
|
||||||
var blockColorScheme = new _colorScheme["default"]();
|
var blockColorScheme = new _colorScheme["default"]();
|
||||||
blockColorScheme.from_hue(hue).scheme(scheme).add_complement(true);
|
blockColorScheme.from_hue(hue).scheme('analogic').add_complement(true);
|
||||||
var colors = blockColorScheme.colors();
|
var colors = blockColorScheme.colors();
|
||||||
console.log('New color scheme: ' + scheme + ' based on %chue ' + hue, 'background-color:#' + colors[0]);
|
|
||||||
return colors;
|
return colors;
|
||||||
}
|
}
|
||||||
}, {
|
}, {
|
||||||
|
@ -19074,8 +19155,8 @@ exports.PAINT = exports.COLORS = exports.PSDENOMINATIONS = void 0;
|
||||||
var PSDENOMINATIONS = [1000010000, 100001000, 10000100, 1000010, 100001];
|
var PSDENOMINATIONS = [1000010000, 100001000, 10000100, 1000010, 100001];
|
||||||
exports.PSDENOMINATIONS = PSDENOMINATIONS;
|
exports.PSDENOMINATIONS = PSDENOMINATIONS;
|
||||||
var COLORS = {
|
var COLORS = {
|
||||||
"private": '000000',
|
black: '#000000',
|
||||||
instant: 'ffffff'
|
white: '#ffffff'
|
||||||
};
|
};
|
||||||
exports.COLORS = COLORS;
|
exports.COLORS = COLORS;
|
||||||
var PAINT = {
|
var PAINT = {
|
||||||
|
|
File diff suppressed because one or more lines are too long
|
@ -8,6 +8,7 @@
|
||||||
<body>
|
<body>
|
||||||
<div id="connectionStatus" class="is-connecting"></div>
|
<div id="connectionStatus" class="is-connecting"></div>
|
||||||
|
|
||||||
|
<div id="hero"></div>
|
||||||
<div id="blockList"></div>
|
<div id="blockList"></div>
|
||||||
|
|
||||||
<script src="bundle.js"></script>
|
<script src="bundle.js"></script>
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue