Недавно новый друг в твиттере упомянул, что было бы полезно, если бы они могли получать данные из своих растровых блоков и показывать их так, как им хочется. Я был заинтригован, и мне понравилась идея о том, что люди самостоятельно изучают данные блока. Итак, однажды вечером я создал HTML-файл, который извлекает все данные о транзакциях данного блока и отображает их в различных формах, включая простые 2D-диаграммы и таблицу.

Вот пошаговое описание того, как я подошел к задаче.

TLDR:
Если вам просто нужен код, посетите мой github:
https://github.com/ZacharyWeiner/bitmap-viz

Не забывайте писать мне в Twitter/X, чтобы узнать больше: DevelopingZack

Начиная

Во-первых, нам нужно импортировать библиотеку Plotly.js, которая предоставляет бесплатную библиотеку с открытым исходным кодом для создания интерактивных диаграмм. Для этого просто используйте следующий тег сценария:

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

Затем мы настраиваем элементы HTML, которые будут содержать наши данные и диаграммы. Нам нужно создать элементы для каждой диаграммы, которую мы хотим отобразить, а также для таблицы данных и поля ввода для идентификатора блока:

<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: получение данных

Теперь мы используем JavaScript для получения данных из API блокчейна. Мы создаем две асинхронные функции: fetchPage(), которая извлекает одну страницу данных, и fetchAllPages(), которая многократно вызывает fetchPage() до тех пор, пока не будут получены все страницы (мы также инициализируем панель загрузки, чтобы показывать пользователям, когда страница думает).

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";
}

После получения данных они передаются функции displayDataInTable(), которая отображает данные в таблице.

JavaScript: отображение данных

Функция displayDataInTable() создает строку таблицы для каждой транзакции с ячейкой таблицы для каждого поля в данных транзакции.

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();
}

После отображения данных функция вызывает createTreemap(), create3dBar() и create3dScatter() для создания диаграмм.

Далее мы рассмотрим каждую из этих функций.

JavaScript: создание диаграмм

Вот краткий обзор каждой функции создания диаграмм:

  • createTreemap(): Эта функция создает древовидную диаграмму для комиссии за транзакцию и ее размера.
  • create3dBar(): Эта функция создает трехмерную гистограмму, показывающую взаимосвязь между комиссией за транзакцию, размером и весом.
  • create3dScatter(): Эта функция создает трехмерную точечную диаграмму с теми же корреляциями.
  1. createTreemap(): Древовидная карта отображает иерархические данные в виде набора вложенных прямоугольников. В нашем случае мы можем визуализировать размер транзакции и комиссию.
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():
Это создает трехмерную гистограмму, показывающую корреляцию между комиссией за транзакцию, размером и весом.

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():
Эта функция создает трехмерную точечную диаграмму, показывающую те же корреляции, что и трехмерная гистограмма.

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);
}

Не забудьте вызвать эти функции после того, как ваши данные будут получены и отображены.

Обратите внимание, вам нужно будет настроить их в соответствии с вашими потребностями. Это общие иллюстрации. Вам также потребуется обрабатывать ситуации, когда транзакции не имеют определенных свойств. Эти функции предполагают, что свойства «размер», «вес» и «комиссия» доступны для всех транзакций, что может быть не всегда так.

Заключение

В предоставленных функциях JavaScript мы визуализировали данные транзакций блокчейна тремя различными способами. С помощью функции createTreemap() мы отобразили размер транзакции и комиссию в иерархической структуре, которая обеспечивает интуитивно понятное представление относительных пропорций этих двух свойств. Затем функция create3dBar() сделала еще один шаг вперед, сопоставив размер транзакции, вес и комиссию на трехмерной гистограмме, эффективно продемонстрировав взаимосвязь между этими тремя аспектами. Наконец, функция create3dScatter() отобразила те же корреляции, но в формате 3D-графика рассеяния, предлагая уникальное представление о том, как эти свойства соотносятся друг с другом в пространстве данных транзакций блокчейна.

Подпишитесь на меня в Twitter/X, чтобы узнать больше:
нажмите здесь -› DevelopingZack