Visualizing Bitcoin & Bitmap Transactions with HTML and JavaScript

Zachary Weiner
4 min readJul 31, 2023

--

Recently a new friend on twitter mentioned that it would be helpful if they could get the data from their bitmap blocks and show it how ever they wanted. I was intrigued, and liked the idea of people exploring the block data on their own. So late one afternoon I built an HTML file that fetches all the transaction data of a given block and displays it in various forms including basic 2D charts and a table.

Here’s a walk-through of how I approached the task.

TLDR:
If you just want the code, visit my github:
https://github.com/ZacharyWeiner/bitmap-viz

Don’t forget to me on Twitter/X for more: DevelopingZack

Getting Started

First, we need to import the Plotly.js library, which provides a free open source library for creating interactive charts. To achieve this, simply use the following script tag:

<script src="https://cdn.plot.ly/plotly-latest.min.js"></script>

Next, we set up the HTML elements that will contain our data and charts. We need to create elements for each chart we want to display, as well as for the data table and the input field for the block ID:

<h2>Bitcoin Transaction Data</h2>
<input type="text" id="blockID" placeholder="Enter Block ID">
<button onclick="fetchAllPages()">Fetch Data</button>
<button onclick="downloadCSV()">Download CSV</button>
<br/>
<div id="loading"></div>
<div id="totalTransactions"> </div>
<label> Fee Treemap </label>
<div id="treemap"></div>
<label> Size Treemap </label>
<div id="treemap2"></div>
<label> 3D Bar </label>
<div id="threeDBar"></div>
<label> 3D Scatter </label>
<div id="scatter3d"></div>
<div id="inputHistogram"></div>
<div id="outputHistogram"></div>
<div id="displayData">
<table id="transactionTable">
<!-- Table headers and data will go here -->
</table>
</div>

JavaScript: Fetching the Data

Now, we use JavaScript to fetch the data from the blockchain API. We create two asynchronous functions: fetchPage() which fetches a single page of data, and fetchAllPages() which repeatedly calls fetchPage() until all pages are fetched (we also initialize the loading panel to show the users when the page is thinking).

let transactionData = [];
document.getElementById("loading").style.display = "none";
async function fetchPage(page, blockID) {
let response = await fetch(`https://chain.api.btc.com/v3/block/${blockID}/tx?page=${page}`);
let data = await response.json();
return data;
}
async function fetchAllPages() {
let blockID = document.getElementById('blockID').value;
document.getElementById("loading").style.display = "block";
if (!blockID) {
alert("Please enter a Block ID");
return;
}

let page = 1;
transactionData = []; // Reset transaction data for new block ID
while (true) {
let data = await fetchPage(page, blockID);
if (!data.data.list || data.data.list.length === 0) {
break;
}
transactionData = transactionData.concat(data.data.list);
page++;
}
transactionData = transactionData.filter(t => !t.is_coinbase)
document.getElementById("totalTransactions").text = transactionData.length + 1;
displayDataInTable();
document.getElementById("loading").style.display = "none";
}

After fetching the data, it’s passed to the displayDataInTable() function which displays the data in the table.

JavaScript: Displaying the Data

The displayDataInTable() function creates a table row for each transaction, with a table cell for each field in the transaction data.

function displayDataInTable() {
let table = document.getElementById('transactionTable');
table.innerHTML = '';
let headerRow = document.createElement('tr');
Object.keys(transactionData[0]).forEach(key => {
let th = document.createElement('th');
th.textContent = key;
headerRow.appendChild(th);
});
table.appendChild(headerRow);
transactionData.forEach(transaction => {
let row = document.createElement('tr');
Object.values(transaction).forEach(value => {
let td = document.createElement('td');
if (Array.isArray(value) && value.length > 0 && typeof value[0] === 'object') {
value = value.map(v => JSON.stringify(v));
}
td.textContent = value;
row.appendChild(td);
});
table.appendChild(row);
});
createTreemap();
create3dBar();
create3dScatter();
}

After displaying the data, the function calls createTreemap(), create3dBar(), and create3dScatter() to generate the charts.

Next we will walk through each of these functions.

JavaScript: Creating the Charts

Here’s a brief overview of each chart-generating function:

  • createTreemap(): This function creates a treemap chart for transaction fee and size.
  • create3dBar(): This function creates a 3D bar chart showing the correlation between transaction fee, size, and weight.
  • create3dScatter(): This function creates a 3D scatter plot with the same correlations.
  1. createTreemap(): A treemap displays hierarchical data as a set of nested rectangles. In our case, we can visualize transaction size and fee.
function createTreemap() {
let treemapData = transactionData.map((transaction, i) => ({
type: "treemap",
labels: [transaction.hash],
parents: [""],
values: [transaction.size],
text: [transaction.fee]
}));
let treemapLayout = {
title: 'Transaction Treemap'
};
Plotly.newPlot('treemap', treemapData, treemapLayout);
}

2. create3dBar():
This creates a 3D bar chart showing the correlation between transaction fee, size, and weight.

function create3dBar() {
let bar3dData = [{
x: transactionData.map(transaction => transaction.size),
y: transactionData.map(transaction => transaction.weight),
z: transactionData.map(transaction => transaction.fee),
type: "bar3d"
}];
let bar3dLayout = {
title: 'Transaction 3D Bar'
};
Plotly.newPlot('threeDBar', bar3dData, bar3dLayout);
}

3. create3dScatter():
This function creates a 3D scatter plot showing the same correlations as the 3D bar chart.

function create3dScatter() {
let scatter3dData = [{
x: transactionData.map(transaction => transaction.size),
y: transactionData.map(transaction => transaction.weight),
z: transactionData.map(transaction => transaction.fee),
mode: 'markers',
type: 'scatter3d'
}];
let scatter3dLayout = {
title: 'Transaction 3D Scatter'
};
Plotly.newPlot('scatter3d', scatter3dData, scatter3dLayout);
}

Remember to call these functions after your data is fetched and displayed.

Please note, you will need to adjust these to your needs. They are general illustrations. You’ll also need to handle situations where transactions don’t have certain properties. These functions assume the properties ‘size’, ‘weight’, and ‘fee’ are available on all transactions, which may not always be the case.

Conclusion

In the provided JavaScript functions, we visualized blockchain transaction data in three different ways. With the createTreemap() function, we displayed transaction size and fee in a hierarchical structure, which provides an intuitive representation of these two properties' relative proportions. The create3dBar() function then took this a step further by correlating transaction size, weight, and fee in a 3D bar chart, effectively demonstrating the interrelationships between these three aspects. Finally, the create3dScatter() function displayed these same correlations but in a 3D scatter plot format, offering a unique view on how these properties relate to each other in the blockchain transaction data space.

Follow me on Twitter/X for more:
click this ->
DevelopingZack

--

--

Zachary Weiner

Founder @MagicDapp.io & @AlphaDapp.com | Find @DevelopingZack on Twitter & Telegram