commit 18e533c5252d2337b89f28f4219f784ad33f5d0f Author: Joshua Seigler Date: Fri Sep 9 19:26:29 2016 -0400 initial commit diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..d825041 --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +/bower_components/ +/node_modules/ +/.brackets.json diff --git a/README.md b/README.md new file mode 100644 index 0000000..32d51ce --- /dev/null +++ b/README.md @@ -0,0 +1,7 @@ +This simple project uses the Insight Web Sockets API and Socket.io to stream transactions from the Dash blockchain as they are broadcast. + +## Installation +Download the project. No build step is necessary. + +## Usage +Open `index.html`. \ No newline at end of file diff --git a/app.js b/app.js new file mode 100644 index 0000000..37f1150 --- /dev/null +++ b/app.js @@ -0,0 +1,76 @@ +'use strict'; + +var socket = io("http://insight.masternode.io:3000/"); + +function playSound(url){ + var audio = document.createElement('audio'); + audio.style.display = "none"; + audio.src = url; + audio.autoplay = true; + audio.loop = false; + audio.onended = function(){ + audio.remove() //Remove when played. + }; + document.body.appendChild(audio); +} + +function scrollToEnd() { + window.scrollTo(0,document.body.scrollHeight); +} + +var onTransaction = function(data) { + console.log(data); + playSound('assets/bell.mp3'); + var tx = document.createElement('div'); + tx.className = 'tx'; + var txValue = document.createElement('a'); + txValue.className = 'txValue'; + txValue.href = 'http://insight.masternode.io:3000/tx/' + data.txid; + txValue.target = '_blank'; + txValue.setAttribute('rel', 'noopener'); + var txOutputs = document.createElement('div'); + txOutputs.className = 'txOutputs'; + txValue.appendChild(document.createTextNode(data.valueOut)); + tx.appendChild(txValue); + tx.appendChild(txOutputs); + var transactions = data.vout.sort(function(a, b) { // sort descending by tx value + return b[Object.keys(b)[0]] - a[Object.keys(a)[0]]; + }); + transactions.forEach(function(value, index, array) { + var txOut = document.createElement('div'); + var outputSatoshis = value[Object.keys(value)[0]]; + txOut.className = 'txOut'; + txOut.style.width = (outputSatoshis * 0.00001).toFixed(4) + 'px'; + txOut.title = (value[Object.keys(value)[0]] * 0.00000001); + txOutputs.appendChild(txOut); + }); + document.getElementById('transactionList').appendChild(tx); + scrollToEnd(); +}; + +var onBlock = function(data) { + console.log(data); + playSound('assets/whoosh.mp3'); + var newBlock = document.createElement('a'); + newBlock.className = 'blockDivider'; + newBlock.href = 'http://insight.masternode.io:3000/block/' + data; + newBlock.target = '_blank'; + newBlock.setAttribute('rel', 'noopener'); + newBlock.appendChild(document.createTextNode(data)); + document.getElementById('transactionList').appendChild(newBlock); + scrollToEnd(); +}; + +socket.on('connect', function() { + document.getElementById('connectionStatus').className = 'is-connected'; + // Join the room. + socket.emit('subscribe', 'inv'); +}) +socket.on('tx', onTransaction); +socket.on('block', onBlock); +socket.on('disconnect', function() { + document.getElementById('connectionStatus').className = 'is-disconnected'; +}); +socket.on('reconnecting', function() { + document.getElementById('connectionStatus').className = 'is-connecting'; +}); diff --git a/assets/bell.mp3 b/assets/bell.mp3 new file mode 100644 index 0000000..9afb2cf Binary files /dev/null and b/assets/bell.mp3 differ diff --git a/assets/whoosh.mp3 b/assets/whoosh.mp3 new file mode 100644 index 0000000..d3492c2 Binary files /dev/null and b/assets/whoosh.mp3 differ diff --git a/index.html b/index.html new file mode 100644 index 0000000..f137148 --- /dev/null +++ b/index.html @@ -0,0 +1,17 @@ + + + + + Dash transaction visualizer + + + +
+ +
+
+ + + + + diff --git a/style.css b/style.css new file mode 100644 index 0000000..c60083f --- /dev/null +++ b/style.css @@ -0,0 +1,111 @@ +body { + padding: 2em 0 4em; + margin: 0; + box-sizing: border-box; + font-family: sans-serif; + background-image: linear-gradient(to bottom right, hsl(208, 73%, 43%), hsl(208, 73%, 21.5%)); + background-color: hsl(208, 73%, 43%); + color: white; + min-height: 100vh; +} +* { + box-sizing: inherit; + transition: color 0.1s; +} +a { + color: inherit; + text-decoration: none; +} +#transactionList { + padding: 0 1em; +} +.tx { + position: relative; + margin: 4px auto; + border-radius: 4px; + width: 20em; + min-width: 80%; + max-width: 100%; + z-index: 1; +} +.txValue { + display: block; + flex: 0 0 auto; + line-height: 1.25; +} +.txOutputs { + display: flex; + flex-wrap: nowrap; + flex-direction: row; + align-content: stretch; +} +.txOut { + position: relative; + flex: 1 1 auto; + border-bottom: 2px solid white; + border-width: 0 2px 2px 0; + text-align: right; + height: 0.25em; +} +.txOut:after { + content: ''; + width: 2px; + height: 0.75em; + background: linear-gradient(to bottom, rgba(255,255,255,0), rgba(255,255,255,0.5) 80%, white); + position: absolute; + right: 0; + bottom: 0; +} + +.blockDivider { + display: block; + margin: -2em -1em 1em; + background: linear-gradient(to bottom, rgba(255,255,255,0), rgba(255,255,255,0.125)); + padding: 2.5em 1em 0; + color: rgba(0,0,0,0); + text-align: center; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; +} +.blockDivider:hover, .blockDivider:focus { + color: inherit; +} + +#connectionStatus { + position: fixed; + top: 0; + right: 0; + font-size: 0.8em; + background: white; + border-radius: 0 0 0 0.5em; + border: solid black; + border-width: 0 0 0.1em 0.1em; + padding: 0.5em; +} +#connectionStatus:before { + display: block; + text-transform: uppercase; + font-weight: bold; + width: 8em; + text-align: center; + transition: transform 0.5s; + transform: none; +} +#connectionStatus.is-disconnected:before { + content: 'Disconnected'; + color: red; +} +#connectionStatus.is-connecting:before { + content: 'Connecting...'; + color: black; +} +#connectionStatus.is-connected:before { + content: 'Connected'; + color: green; +} +#connectionStatus.is-connected { + transition: transform 0.5s; + transition-delay: 2s; + transform: translate3d(0, -100%, 0); +}