JS 实现区块链添加可视化功能

news2024/9/23 12:29:52

JS 实现区块链添加可视化功能

学习的最后一部分了,完整的资源在这里:https://download.csdn.net/download/weixin_42938619/87765530,有需求的可以自取。

最后一部分是增加一些可视化的功能,完整实现后如下:

在这里插入图片描述

在这里插入图片描述

HTML 部分是用 Angular 写的,Angular 的学习不在讨论的范围内,所以这里会将剩下的一些功能补全就是了。

添加查找对应 block

这里主要接收一个 blockId,随后通过 find 功能去查找对应的 block,找到返回对应的 Block,否则返回 null:

getBlock = (blockHash: string): Block | null => {
  return this.chain.find((block) => block.hash === blockHash) || null;
};

API 部分为:

app.get('/block/:blockHash', (req, res) => {
  const { blockHash } = req.params;
  const block = bitcoin.getBlock(blockHash);
  res.json({ block });
});

添加查找对应 transaction

这里需要做两重迭代,同时会返回对应的 transaction 和对应的 block:

getTransaction = (
  transactionId: string
): { transaction: Transaction | null; block: Block | null } => {
  for (const block of this.chain) {
    const transaction = block.transactions.find(
      (transaction) => transaction.transactionId === transactionId
    );

    if (transaction) return { transaction, block };
  }
  return { transaction: null, block: null };
};

api 部分:

app.get('/transaction/:transactionId', (req, res) => {
  const { transactionId } = req.params;
  const transactionAndBlock = bitcoin.getTransaction(transactionId);
  res.json(transactionAndBlock);
});

添加查找对应 address

同样进行两重迭代去查找对应地址的所有交易,为了可读性没有做其他的优化,毕竟从大 O 来说都是 O ( m n ) O(mn) O(mn)

getAddressData = (
  address: string
): { addressTransactions: Transaction[]; addressBalance: number } => {
  const addressTransactions: Transaction[] = [];
  for (const block of this.chain) {
    for (const transaction of block.transactions) {
      if (transaction.sender === address || transaction.recipient === address) {
        addressTransactions.push(transaction);
      }
    }
  }

  const addressBalance = addressTransactions.reduce(
    (accum: number, transaction: Transaction) => {
      if (transaction.recipient === address) accum += transaction.amount;
      else if (transaction.sender === address) accum -= transaction.amount;

      return accum;
    },
    0
  );

  return { addressTransactions, addressBalance };
};

api 部分:

app.get('/address/:address', (req, res) => {
  const { address } = req.params;
  const addressData = bitcoin.getAddressData(address);
  res.json({ addressData });
});

可视化部分

这里主要就是把 html 文件加进来,api 的加载部分如下:

app.get('/block-explorer', (req, res) => {
  res.sendFile('./block-explorer/index.html', {
    root: __dirname,
  });
});

html 部分如下:

<!DOCTYPE html>
<html>
  <head>
    <title>Block Explorer</title>
    <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.6/angular.min.js"></script>
    <script
      src="https://code.jquery.com/jquery-3.3.1.min.js"
      integrity="sha256-FgpCb/KJQlLNfOu91ta32o/NMZxltwRo8QtmkMRdAu8="
      crossorigin="anonymous"
    ></script>
    <script
      src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"
      integrity="sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa"
      crossorigin="anonymous"
    ></script>
    <link
      rel="stylesheet"
      type="text/css"
      href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css"
    />
  </head>

  <body ng-app="BlockExplorer">
    <div class="container" ng-controller="MainController">
      <div class="row">
        <div class="col-md-8 offset-md-2">
          <h1 id="page-title">Block Explorer</h1>
        </div>
      </div>
      <div class="row">
        <div class="col-md-6 offset-md-3">
          <form ng-submit="search(searchValue)">
            <div class="form-group">
              <input type="text" class="form-control" ng-model="searchValue" />
            </div>
            <div class="form-group">
              <select class="form-control" ng-model="searchType">
                <option value="block">Block Hash</option>
                <option value="transaction">Transaction ID</option>
                <option value="address">Address</option>
              </select>
            </div>
            <button
              type="submit"
              class="btn btn-primary margin-auto btn-search"
            >
              Search
            </button>
            <p
              ng-if="!block && !transaction && !addressData && initialSearchMade"
              class="no-data-text"
            >
              No data found for search.
            </p>
          </form>
        </div>
      </div>
      <div class="row">
        <div class="col-md-10 offset-md-1">
          <!-- 'display block' table -->
          <h3 class="table-title" ng-if="block">Block</h3>
          <table class="table table-striped" ng-if="block">
            <tbody>
              <tr>
                <td class="bold">Block Hash</td>
                <td>{{ block.hash }}</td>
              </tr>
              <tr>
                <td class="bold">Index</td>
                <td>{{ block.index }}</td>
              </tr>
              <tr>
                <td class="bold">Time Stamp</td>
                <td>{{ block.timestamp }}</td>
              </tr>
              <tr>
                <td class="bold">Nonce</td>
                <td>{{ block.nonce }}</td>
              </tr>
              <tr>
                <td class="bold">Previous Hash</td>
                <td>{{ block.previousBlockHash }}</td>
              </tr>
              <tr>
                <td class="bold">Number Transactions</td>
                <td>{{ block.transactions.length }}</td>
              </tr>
            </tbody>
          </table>
          <!-- end 'display block' table -->

          <!-- 'display transaction' table -->
          <h3 class="table-title" ng-if="transaction">Transaction</h3>
          <table class="table table-striped" ng-if="transaction">
            <tbody>
              <tr>
                <td class="bold">Sender</td>
                <td>{{ transaction.sender }}</td>
              </tr>
              <tr>
                <td class="bold">Recipient</td>
                <td>{{ transaction.recipient }}</td>
              </tr>
              <tr>
                <td class="bold">Amount</td>
                <td>{{ transaction.amount }}</td>
              </tr>
            </tbody>
          </table>
          <!-- end 'display transaction' table -->

          <!-- 'display address' table -->
          <h3 class="table-title" ng-if="addressData">Address</h3>
          <p id="balance-text" ng-if="addressData">
            (Balance: {{ addressData.addressBalance }})
          </p>
          <table class="table table-striped" ng-if="addressData">
            <thead>
              <tr>
                <th scope="col">Sender</th>
                <th scope="col">Recipient</th>
                <th scope="col">Amount</th>
              </tr>
            </thead>
            <tbody>
              <tr ng-repeat="transaction in addressData.addressTransactions">
                <td>{{ transaction.sender }}</td>
                <td>{{ transaction.recipient }}</td>
                <td>{{ transaction.amount }}</td>
              </tr>
            </tbody>
          </table>
          <!-- end 'display address' table -->
        </div>
      </div>
    </div>

    <script>
      window.app = angular.module('BlockExplorer', []);

      app.controller('MainController', function ($scope, $http) {
        $scope.block = null;
        $scope.transaction = null;
        $scope.addressData = null;
        $scope.initialSearchMade = false;

        $scope.fetchBlock = function (blockHash) {
          $http.get(`/block/${blockHash}`).then((response) => {
            $scope.block = response.data.block;
            $scope.transaction = null;
            $scope.addressData = null;
          });
        };

        $scope.fetchTransaction = function (transactionId) {
          $http.get(`/transaction/${transactionId}`).then((response) => {
            $scope.transaction = response.data.transaction;
            $scope.block = null;
            $scope.addressData = null;
          });
        };

        $scope.fetchAddressData = function (address) {
          $http.get(`/address/${address}`).then((response) => {
            $scope.addressData = response.data.addressData;
            if (!$scope.addressData.addressTransactions.length)
              $scope.addressData = null;
            $scope.block = null;
            $scope.transaction = null;
          });
        };

        $scope.search = function (searchValue) {
          $scope.initialSearchMade = true;
          if ($scope.searchType === 'block') {
            $scope.fetchBlock(searchValue);
          } else if ($scope.searchType === 'transaction') {
            $scope.fetchTransaction(searchValue);
          } else if ($scope.searchType === 'address') {
            $scope.fetchAddressData(searchValue);
          }
        };
      });
    </script>

    <style type="text/css">
      html,
      body {
        min-height: 100vh;
        background-color: #e8e8e8;
      }
      .container {
        padding-top: 50px;
        padding-bottom: 50px;
      }
      #page-title {
        text-align: center;
        margin-bottom: 40px;
      }
      .table-title {
        margin-bottom: 20px;
        text-align: center;
      }
      .table {
        background-color: #ffffff;
        box-shadow: 2px 2px 15px -3px rgba(0, 0, 0, 0.75);
      }
      #balance-text {
        text-align: center;
        margin-top: -20px;
        margin-bottom: 30px;
      }
      .margin-auto {
        margin: auto;
        display: block;
      }
      .btn-search {
        margin-bottom: 50px;
      }
      .bold {
        font-weight: 700;
      }
      .no-data-text {
        color: red;
        text-align: center;
      }
    </style>
  </body>
</html>

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/505612.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

基于yolov7开发构建学生课堂行为检测识别系统

yolov7也是一款非常出众的目标检测模型&#xff0c;在我之前的文章中也有非常详细的教程系列的文章&#xff0c;感兴趣的话可以自行移步阅读即可。 《基于YOLOV7的桥梁基建裂缝检测》 《YOLOv7基于自己的数据集从零构建模型完整训练、推理计算超详细教程》 《基于YOLOv7融合…

windows 编译 opencv

编译需要的基础工具 #cmake是配置构建工具&#xff0c;mingw是编译工具 cmake CMake是一款跨平台的编译管理工具&#xff0c;可以自动生成各种不同编译环境&#xff08;如Makefile、Visual Studio Solution等&#xff09;&#xff0c;从而实现在不同平台上进行代码编译的目的…

PLC与无线开关量测控终端之间Modbus通信实例

本方案是基于Modbus RTU协议下实现的1主多从自组网无线通信形式&#xff0c;主站为S7-1200 PLC&#xff0c;DTD433H作为从站。DTD433H具备输入和输出开关量信号功能&#xff0c;信号传输方向由用户原系统主从设备所实现的功能决定。方案中采用无线开关量信号测控终端DTD433H与欧…

python调用海康sdk报错问题

sdk参考&#xff1a; (68条消息) Python调用海康威视网络相机_调用海康SDK_python 海康威视_有一点点麻瓜的博客-CSDN博客https://blog.csdn.net/yinweizhehd/article/details/118722052 报错1&#xff1a; 生成解决方案的时候&#xff0c;显示LNK2001&#xff1a;无法解析的…

【AI大模型】SparkDesk讯飞星火认知大模型震撼发布,国产AI技术再创新高!

文章目录 前言SparkDesk讯飞星火认知大模型简介语言理解知识问答逻辑推理数学题解答代码理解与编写亲自体验写在最后 前言 5月6日&#xff0c;讯飞星火认知大模型成果发布会在安徽合肥举行。科大讯飞董事长刘庆峰、研究院院长刘聪发布讯飞星火认知大模型&#xff0c;现场实测大…

C++面向对象编程

面向对象编程 面向对象编程和面向过程编程面向过程面向对象 类型设计类的成员函数对象的创建和使用C对象模型this指针构造函数和析构函数构造函数定义和使用析构函数的定义和使用 对象的生存周期拷贝构造函数深拷贝与浅拷贝 运算符的重载 面向对象编程和面向过程编程 面向过程…

设计模式之【适配器模式】,两个人之间确实需要月老的搭线~

文章目录 一、什么是适配器模式1、适配器模式使用场景2、代理、桥接、装饰器、适配器 4 种设计模式的区别3、适配器模式结构 二、类适配器1、实例 三、对象适配器1、实例 四、接口适配器1、实例 五、源码中的应用 一、什么是适配器模式 适配器模式&#xff08;Adapter Design …

第2天学习Docker——Docker安装

一、前言 Docker 是一个用于开发、传送和运行应用程序的开放平台。Docker 使您能够将应用程序与基础设施分开&#xff0c;以便您可以快速交付软件。使用 Docker&#xff0c;您可以像管理应用程序一样管理基础设施。通过利用 Docker 的快速交付、测试和部署代码的方法&#xff0…

vue3学习一 setup

vue3中没有 data 等配置项&#xff0c; 并且它的引入方式也不是像vue2中的 import vue就可以了&#xff0c; 而是用到什么再引入什么&#xff0c; 其中 setup() 函数&#xff0c; 是最大的区别 vue3中的 setup 有点像vue2中的 data , 但又不完全是 setup 会在 生命周期create…

关于C语言

C99是啥 很多书籍开篇会突然提到C99标准&#xff0c;因此这里搜了一下。 C99是C语言的官方标准第二版。1999年12月1日&#xff0c;国际标准化组织和国际电工委员会旗下的C语言标准委员会正式发布了这个标准文件 &#xff1b; C99是在C89和C90的基础上发展起来的&#xff0c;增加…

独立站平台选哪个好?5个独立站平台优缺点分析

选择适合自己的独立站平台需要综合考虑多个方面的因素&#xff0c;包括平台的优缺点、自己的需求和预算等因素。下面是几个常见的独立站平台的优缺点分析供您参考&#xff1a; 一、Shopify&#xff1a; 优点&#xff1a;简单易用&#xff0c;拥有丰富的主题和应用程序&#xf…

JavaScript实现求1-100之间不能被3整除的数之和,求100以内偶数的和的两个程序代码

以下为实现求1-100之间不能被3整除数之和求100以内偶数的和的两个程序代码和运行截图 目录 前言 一、实现输入两个数比较两个数的大小 1.1 运行流程及思想 1.2 代码段 1.3 JavaScript语句代码 1.4 运行截图 二、求100以内偶数的和 2.1 运行流程及思想 2.2 代码段 2.3…

泰坦尼克号幸存者预测(案例)----决策树版

1、导入需要的库 import pandas as pd from sklearn.tree import DecisionTreeClassifier import matplotlib.pyplot as plt from sklearn.model_selection import GridSearchCV2、导入数据 在此下载泰坦尼克号训练数据 data pd.read_csv(r"F:\data\train1.csv") …

内网安全:Cobalt Strike 安装.

内网安全&#xff1a;Cobalt Strike 安装. Cobalt Strike是一款渗透测试神器&#xff08;又称为CS&#xff09;。拥有多种协议主机上线方式&#xff0c;集成了端口转发&#xff0c;socket代理&#xff0c;office攻击&#xff0c;文件捆绑&#xff0c;钓鱼&#xff0c;提权&…

哈希算法原理与应用:确保数据完整性和安全性的关键技术

哈希算法是一种将任意长度的消息映射为固定长度摘要或哈希值的算法。哈希算法主要被用于验证数据的完整性和安全性。哈希算法的应用广泛&#xff0c;例如在密码学中用于验证数据完整性和数字签名&#xff0c;也用于检索数据和进行散列分布式存储。下面将详细介绍哈希算法的原理…

《Linux 内核设计与实现》12. 内存管理

文章目录 页区获得页获得填充为 0 的页释放页 kmalloc()gfp_mask 标志kfree()vmalloc() slab 层slab 层的设计slab 分配器的接口 在栈上的静态分配单页内核栈 高端内存的映射永久映射临时映射 每个 CPU 的分配新的每个 CPU 接口 页 struct page 结构表示系统中的物理页&#x…

区间预测 | MATLAB实现QRCNN卷积神经网络分位数回归时间序列区间预测

区间预测 | MATLAB实现QRCNN卷积神经网络分位数回归时间序列区间预测 目录 区间预测 | MATLAB实现QRCNN卷积神经网络分位数回归时间序列区间预测效果一览基本介绍模型描述程序设计参考资料 效果一览 基本介绍 区间预测 | MATLAB实现QRCNN卷积神经网络分位数回归时间序列区间预测…

超级详细的 FinalShell 安装 及使用教程

一、引言 FinalShell 是一款免费的国产的集 SSH 工具、服务器管理、远程桌面加速的良心软件&#xff0c;同时支持 Windows,macOS,Linux&#xff0c;它不单单是一个 SSH 工具&#xff0c;完整的说法应该叫一体化的的服务器&#xff0c;网络管理软件&#xff0c;在很大程度上可以…

新唐NUC980使用记录(5.10.y内核):在用户应用中使用GPIO

文章目录 目的使用参考与演示使用参考存在的问题问题定位修改设备树使用测试 总结设备树文件内容 目的 GPIO是最基础的外设&#xff0c;使用频率也非常高&#xff0c;这篇文章将简单体验在NUC980 Liunx用户应用中使用GPIO功能。 这篇文章中内容均在下面的开发板上进行测试&am…

【java EE】Redis基础

Redis基础 业务中会遇到的问题&#xff1a; 数据量巨大数据模式的不确定性数据的频繁读数据的频繁更改大量数据的统计分析 集中数据库的特点 Redis简介&#xff1a; Redis&#xff08;Remote Dictionary Server&#xff09;是一个使用ANSI C语言编写的开源数据库高性能的 …