HTML页面通过Web3JS连接智能合约并调用其中接口

news2024/11/26 12:13:36

之前我们学习solidity 并用它编写了智能合约 登上区块链 然后也做了基本的测试
但是 其实在web3时代 前端依旧扮演者非常重要的角色
我们现在就来打通web3 从合约到页面的一个管理

首先 我们还是将自己的ganache环境起起来
在这里插入图片描述
然后 在我们之前智能合约的项目终端执行

truffle migrate

将我们的智能合约部署上去
在这里插入图片描述
然后 我们用MetaMask 导入我们ganache环境的第一个用户
在这里插入图片描述
然后 我们拿个html文件 编写代码如下

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <script src = "./js/web3.min.js"></script>
</head>
<body>
    <script type="module">
      var web3 = new Web3(Web3.givenProvider || "http://localhost:8545");
      let account = await web3.eth.requestAccounts();

    </script>
</body>
</html>

注意 他这里引入的web3.min.js 你们需要本地确实有这个文件
然后 我们运行

他这里就会需要我们选择链接授权用户 我们选择刚刚导入的ganache账号在这里插入图片描述
然后 我们在html中改一下代码 输出一下返回结果
在这里插入图片描述
再次运行 他就会将授权账号返回回来
在这里插入图片描述
那么 这样 就确认我们已经拿到它的一个授权了

但是 目前来讲 只是连到了我们的区块链 能拿到一些信息 但是 我们要拿区块链上的智能合约
web3.eth中有一个Contract函数
他接受两个参数
第一个参数 abi
可能很多人都熟悉API ABI的话差不多
也是基本的接口或者函数 只是 他是一种二进制的 JSON的交互智能合约 会比API更原始一点
然后 第二个参数是address
address的作用比较关键 就是 一个区块链上能部署很多智能合约 那么 它为什么就要连接你的呢?
我们每次部署智能合约都会输出这里一个contract address 就是填在里面 帮他找到你的合约的
在这里插入图片描述
那么 address知道怎么传了
但是 这个ABI估计大家还是有点懵
他其实就是让你传入 要用的这个合约上的接口
我们打开智能合约项目 找到 根目录下 编译生成的 build 下的 contracts下的 StudentStorage.json
在这里插入图片描述
这个文件 上来我们就会看到 ABI
在这里插入图片描述
我们直接点击 左侧 这个小箭头 将这个abi收起来
在这里插入图片描述
然后 将这里面的整个数组 复制 作为Contract的第一个参数 abi
在这里插入图片描述
在这个数组中 我们也能找到之前写的一些函数的信息
在这里插入图片描述
但是这里需要提醒 每次你改了智能合约 从小部署 他都会重新编译 这个json的内容也会改,所以你每次都要改这里的abi参数

可能很多人非常麻烦 之后呢确实我们可以处理到同一个文件夹 然后 我们web程序直接导入这个json 去取他里面的这个数据就好了
但是 目前来讲 我们还是快速建立功能

其实 address 也可以在build 下的 contracts下的 StudentStorage.json中找到
在这里插入图片描述
如图所见 如果编译过多次 那么 就会有很多个在这 直接取最后一个就好了
因为肯定是最新的
在这里插入图片描述
我们 HTML参考代码如下

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <script src = "./js/web3.min.js"></script>
</head>
<body>
    <script type="module">
      var web3 = new Web3(Web3.givenProvider || "http://localhost:8545");
      let account = await web3.eth.requestAccounts();
      console.log(account);
      const StudentStorage = await new web3.eth.Contract([
            {
            "inputs": [
                {
                "internalType": "uint256",
                "name": "",
                "type": "uint256"
                }
            ],
            "name": "userList",
            "outputs": [
                {
                "internalType": "uint256",
                "name": "id",
                "type": "uint256"
                },
                {
                "internalType": "string",
                "name": "name",
                "type": "string"
                },
                {
                "internalType": "uint256",
                "name": "age",
                "type": "uint256"
                }
            ],
            "stateMutability": "view",
            "type": "function",
            "constant": true
            },
            {
            "inputs": [
                {
                "internalType": "string",
                "name": "name",
                "type": "string"
                },
                {
                "internalType": "uint256",
                "name": "age",
                "type": "uint256"
                }
            ],
            "name": "addtList",
            "outputs": [
                {
                "internalType": "uint256",
                "name": "",
                "type": "uint256"
                }
            ],
            "stateMutability": "nonpayable",
            "type": "function"
            },
            {
            "inputs": [],
            "name": "queryList",
            "outputs": [
                {
                "components": [
                    {
                    "internalType": "uint256",
                    "name": "id",
                    "type": "uint256"
                    },
                    {
                    "internalType": "string",
                    "name": "name",
                    "type": "string"
                    },
                    {
                    "internalType": "uint256",
                    "name": "age",
                    "type": "uint256"
                    }
                ],
                "internalType": "struct StudentStorage.userData[]",
                "name": "",
                "type": "tuple[]"
                }
            ],
            "stateMutability": "view",
            "type": "function",
            "constant": true
            }
        ],
        "0x9d80C47da52731Df5649Ff81f8EAB664c0c80429"
    );
    console.log(StudentStorage);
    </script>
</body>
</html>

当然 Contract的函数 你们不能直接抄 但是什么 我已经说的够清楚了
我们页面控制台输出结果如下
在这里插入图片描述
能输出这个智能合约 我们就成功了

可能有人就会想 那么 既然我们用StudentStorage接了这个智能合约对象
是不是我们直接 StudentStorage.函数 就可以调用了呢?
其实不然
在这里插入图片描述
我们打开这个对象 发现 之前我们写的函数 并不在里面
不用急
我们里面必然会有一个 methods 打开你就会发现 我们的函数就都在里面了
在这里插入图片描述
然后 我们将html代码改写如下

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <script src = "./js/web3.min.js"></script>
</head>
<body>
    <input type="text" id="myname">
    <input type="number" id="myage">
    <button id="add">添加</button>
    <script type="module">
      var web3 = new Web3(Web3.givenProvider || "http://localhost:8545");
      let account = await web3.eth.requestAccounts();
      console.log(account);
      const StudentStorage = await new web3.eth.Contract([
            {
            "inputs": [
                {
                "internalType": "uint256",
                "name": "",
                "type": "uint256"
                }
            ],
            "name": "userList",
            "outputs": [
                {
                "internalType": "uint256",
                "name": "id",
                "type": "uint256"
                },
                {
                "internalType": "string",
                "name": "name",
                "type": "string"
                },
                {
                "internalType": "uint256",
                "name": "age",
                "type": "uint256"
                }
            ],
            "stateMutability": "view",
            "type": "function",
            "constant": true
            },
            {
            "inputs": [
                {
                "internalType": "string",
                "name": "name",
                "type": "string"
                },
                {
                "internalType": "uint256",
                "name": "age",
                "type": "uint256"
                }
            ],
            "name": "addtList",
            "outputs": [
                {
                "internalType": "uint256",
                "name": "",
                "type": "uint256"
                }
            ],
            "stateMutability": "nonpayable",
            "type": "function"
            },
            {
            "inputs": [],
            "name": "queryList",
            "outputs": [
                {
                "components": [
                    {
                    "internalType": "uint256",
                    "name": "id",
                    "type": "uint256"
                    },
                    {
                    "internalType": "string",
                    "name": "name",
                    "type": "string"
                    },
                    {
                    "internalType": "uint256",
                    "name": "age",
                    "type": "uint256"
                    }
                ],
                "internalType": "struct StudentStorage.userData[]",
                "name": "",
                "type": "tuple[]"
                }
            ],
            "stateMutability": "view",
            "type": "function",
            "constant": true
            }
        ],
        "0x9d80C47da52731Df5649Ff81f8EAB664c0c80429"
    );
    console.log(StudentStorage);

    async function getList() {
        let res = await StudentStorage.methods.queryList().call();
        console.log(res);
    }

    add.onclick = async function() {
        console.log(myname.value,myage.value)

        await StudentStorage.methods.addtList(myname.value,myage.value).send({from: account[0]})
        getList();
    }
    getList();
    </script>
</body>
</html>

这里 我们通过智能合约返回的StudentStorage对象做了一些操作
首先是 getList 这个方法异步调用了我们写在合约上的 queryList 函数 获取数组的长度
然后输出
因为我们之前合约上getList声明了一个 view 这样 表示 我们这个函数是不会改变合约上的内容 也不会改变区块链的
我们只是做个访问 所以 我们声明call 告诉它我们这个方法是不需要消耗燃料的
在这里插入图片描述
那么 我们的添加函数 调用了addtList 传入了 我们的 myname输入框 和 myage输入框的value
至于这个add.onclick 这里是一个基础 我们html中 调用id内容声明事件是直接可以通过id名去绑定的

然后 调用了addtList 将这些函数添加进去 但是 这个函数是改变了我们合约内容的 所以它会消耗燃料
那么 这个谁来承担呢?
我们web3.eth.requestAccounts()获取了MetaMask的账号授权列表 我们直接取0下标 然第一个用户去扣这个燃料

我们尝试输入内容 然后点击添加
在这里插入图片描述
然后 我们在控制台 console 中 输出的myname.value,myage.value在控制台上了 然后MetaMask弹出 让我们确认燃料
我们直接确定
在这里插入图片描述
我们知道 当我们执行成功 他会调用getList
这里 也成功展示出我们添加后的数组
在这里插入图片描述
但是 智能合约添加的操作 很多会要当前用户的信息 例如我们这里添加一个用户 他会需要知道 谁记录的这条信息 就是 在操作是顺带将操作的这个用户的信息传过来

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

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

相关文章

Python-Go 文件操作和异常操作

目录 python的异常操作 异常是什么&#xff1f; 错误与异常的区别&#xff1a; 常见异常 Traceback 错误回溯 异常处理 异常处理的定义&#xff08;try - except&#xff09; 扩展&#xff08;可以捕获不同的错误、多except语句&#xff09;&#xff08;else - finall…

PFC离散元仿真,3DEC非连续岩石力学与结构问题分析

一、背景&#xff1a; 随着我国经济的发展&#xff0c;岩土工程涉及的要求从材料、理论到施工工艺都提出了全方位的系统升级。在岩土工程分析设计中&#xff0c;3DEC和PFC软件快速建模也一直是岩土工作者所关注的问题。3DEC是非连续岩石力学与结构问题的首选分析程序&#xff0…

C语言图书管理系统

一&#xff0c;开发环境 操作系统&#xff1a;windows10, windows11, linux, mac等。开发工具&#xff1a;Qt, vscode, visual studio等开发语言&#xff1a;c 二&#xff0c;功能需求 1. 图书信息管理&#xff1a; 这个功能的主要任务是保存和管理图书的所有信息。这应该包…

C++数据结构X篇_09_C++实现栈的顺序存储与链式存储

本篇参考C实现队列的顺序存储与链式存储整理&#xff0c;先搞懂结构框架&#xff0c;后期根据视频利用c对内容实现&#xff0c;也可以对c有更高的提升。 文章目录 1. 顺序存储2. 链式存储 队列是一种特殊的数据存储结构&#xff0c;与栈不同的是其数据存储与访问顺序为先进先出…

Python教程:全局变量和局部变量

变量的作用域始终是Python学习中一个必须理解掌握的环节&#xff0c;下面我们从局部变量和全局变量开始全面解析Python中变量的作用域。 所谓局部变量&#xff0c;指的是定义在函数内的变量。定义在函数内的变量&#xff0c;只能在函数内使用&#xff0c;它与函数外具有相同名…

GlasgowSmile-v2靶机复盘

GlasgowSmile-v2靶机复盘 这是一个非常难的靶机 这个靶机是直接给我们ip地址的&#xff0c;所以就不用去找ip地址了&#xff0c;直接对ip进行一个扫描。 发现开通了22&#xff0c;80&#xff0c;83&#xff0c;但是8080端口是个开启我们无法访问的状态&#xff0c;所以可以猜…

【Redis】—— Redis的RDB持久化机制

&#x1f4a7; 【 R e d i s 】—— R e d i s 的 R D B 持久化机制 \color{#FF1493}{【Redis】 —— Redis的RDB持久化机制} 【Redis】——Redis的RDB持久化机制&#x1f4a7; &#x1f337; 仰望天空&#xff0c;妳我亦是行人.✨ &#x1f984; 个人主页——微风撞…

Springboot -- Mybatis + Mybatis Generate + KingbaseES8(pgsql) + 静态多数据源

&#x1f3db;&#x1f3db;&#x1f3db; 以下内容记录一次 Springboot 项目整和人大金仓数据库的过程 &#x1f3db;&#x1f3db;&#x1f3db; 文章目录 KingBaseES8SpringBoot整合KES8(pgsql)修改pom文件配置多数据源配置文件配置类 代码生成器配置JsonTypeHandler修改配…

[HDCTF2019]Maze(初识逆向)

下载附件解压&#xff0c;为了方便&#xff0c;我将文件名改为了maze.exe 一般我们先查壳&#xff0c;确实存在UPX壳 对于刚接触逆向的我&#xff0c;一键脱掉哈哈哈 不过还是要说一下&#xff0c;这种脱壳处理有可能会产生其它损坏或者影响&#xff0c;需要进行一定的修复 可…

Visio使用

1.Visio中字母上下标快捷键&#xff1a; 选中要成为上标的文字,ctrlshift"" 选中要成为下标的文字,ctrl"" 2.导入CAD文件 从 AutoCAD 版本 2007 到 2017 导入 .dwg 或 .dxf 文件。 3.编辑CAD文件 右键图形—CAD绘图对象—转换 选择高级 将默认选项改…

居安思危,测试员被裁了还能干什么?

2019年迎来了一大波大佬级公司裁员&#xff0c;包括了阿里、美团、知乎……。它们是各行业的独角兽公司&#xff0c;既是媒体关注的焦点&#xff0c;也是代表了行业风向的指针。 2019年的互联网&#xff0c;已经过了蓬勃发展期&#xff0c;接下来要迎接的更加平稳、规律的发展…

ECM能耗管理云平台

能源是企业运营中不可或缺的要素之一&#xff0c;直接影响企业的成本和竞争力。能源消耗和碳排放不断增长&#xff0c;对环境和可持续发展造成了严重影响。越来越多的企业开始关注并实施能耗管理云平台系统&#xff0c;以实现更高的能源效率、降低碳排放。 ECM能耗管理云平台系…

数分面试题:魔方涂色

问题&#xff1a;现在有一个正方体&#xff0c;现在有6种颜色&#xff0c;给正方体的每一面涂一种颜色&#xff0c;有多少种涂色方法。 注意&#xff01;正方体是可以旋转的&#xff0c;如果旋转正方体之后&#xff0c;涂色效果和另一种涂色效果相同&#xff0c;那么算是一种涂…

车载开发月薪10k与30k的区别,就是CAN总线技术

CAN&#xff08;Controller Area Network&#xff09;总线是一种实时通信协议&#xff0c;是一种广泛应用于车载电子系统中的网络技术。CAN总线技术最初是由德国Bosch公司开发的&#xff0c;用于汽车电子控制系统&#xff08;ECU&#xff09;之间的通信&#xff0c;它能够在车辆…

Linux的shell脚本

Linux的shell脚本 &#x1f607;博主简介&#xff1a;我是一名正在攻读研究生学位的人工智能专业学生&#xff0c;我可以为计算机、人工智能相关本科生和研究生提供排忧解惑的服务。如果您有任何问题或困惑&#xff0c;欢迎随时来交流哦&#xff01;&#x1f604; ✨座右铭&…

Ai数字人浪潮来袭,超写实数字人系统出世,为企业打造定制化服务

数字人概念首次出现在80年代&#xff0c;最初在音乐领域应用&#xff0c;使用手绘技术进行生成。随着时间的推移&#xff0c;传统手绘被CG和动作捕捉等技术取代&#xff0c;从而使虚拟数字人的制作变得更加简化并降低成本。因此&#xff0c;虚拟数字人产业进入产业化探索阶段。…

SpringBoot快速实践 --Ⅰ

文章目录 启动一个SpringBoot项目如何替换内嵌容器玩转SpringBoot配置全局异常处理过滤器拦截器使用Lombok简洁代码使用IDEA HTTP Client进行接口调试 启动一个SpringBoot项目 如果你觉得使用官网来创建太慢了&#xff0c;那你直接把以前项目的依赖粘过来就行了&#xff1a; …

pytorch LBFGS

LBFGS pytorch的LBFGS也是一个优化器 但是与一般的优化器不同 平常我们的顺序是 losscriterion(predict, gt) optim.zero_grad() loss.backward() optim.step()而LBFGS是 def closure():optim.zero_grad()loss criterion(predict, gt)loss.backward()return lossoptim.step…

5.EFLK(ELK+filebeat)+filter过滤

文章目录 EFLK&#xff08;ELKfilebeat&#xff09;部署filebeat修改配置文件logstash配置 logstash的filter过滤grok(正则捕获插件)内置正则表达式调用自定义表达式 mutate(数据修改插件)重命名字段添加字段删除字段转换数据类型替换字段内容以"|"为分割符拆分数据成…

系统升级丨让VR全景制作简单再简单

最高端的VR全景 往往只需要最朴素的制作方式 酷雷曼3D VR数字化升级平台4.0版本 闪耀上线 全新的后台界面 丝滑的编辑工具 无需代码 不用建模 简单拖拉拽移 依然有手就行 轻松搭建VR元宇宙空间 1、界面升级&#xff0c;让VR创作更加可视 全新视觉设计 酷雷曼3D VR…