WEB3 在 React搭建的Dapp中通过redux全局获取并存储用户ETH与自定义token与交易所存储数量

news2024/11/9 4:04:48

上文 web3 在React dapp中全局管理web3当前登录用户/智能合约等信息中 我们简单操作,将web3的公共信息都存在了window对象上

然后 我们先来启动一下环境
终端输入

ganache -d

在这里插入图片描述
打开项目 终端输入

truffle migrate --reset

在区块链上发布一下智能合约
在这里插入图片描述

然后 我们在 src下的 components 目录下创建两个组件
分别是 余额组件 balance.jsx 订单组件 Order.jsx
在这里插入图片描述
然后 在我们 src下的view下的index.jsx组件中引入他们

我们这里 直接导入 然后使用他们
在这里插入图片描述
那么 我们余额的管理 显然是不能用组件传值的 因为他要动态的去变动
redux就是一个非常不错的选择

那么 我们终端执行

npm i --save redux react-redux

引入一下依赖
在这里插入图片描述
然后 我们在src目录下创建文件夹 redux 下面创建一个 store.js
然后 我们还需要一个依赖
终端输入

npm i --save @reduxjs/toolkit

在这里插入图片描述
然后 我们在src下的redux 目录中创建一个文件夹目录叫 balanceSlice 下面创建一个index.js

参考代码如下

import {createSlice} from "@reduxjs/toolkit";

const balanceSlice = createSlice({
    name:"balance",
    initialState: {
      TokenWallet: "0", //用户自定义token的数量 因为要进行单位转换 所以 用了字符串类型
      TokenExchange: "0", //用户在交易所的token数量  依旧采取字符串类型
      EtherWallet: "0",  //用户的ETH值
      EtherExchange: "0"  //用户在交易所的ETH
    },
    reducers: {
        setTokenWallet(state,action) {
            state.TokenWallet = action.payload
        },
        setTokenExchange(state,action) {
            state.TokenExchange = action.payload
        },
        setEtherWallet(state,action) {
            state.EtherWallet = action.payload
        },
        setEtherExchange(state,action) {
            state.EtherExchange = action.payload
        }
    }
})

export const { setTokenWallet, setTokenExchange, setEtherWallet, setEtherExchange } = balanceSlice.actions;

export default balanceSlice.reducer;

这里 我们存储了当前登录用户的token与ETH 以及 当前用户放在交易所的 token与 ETH
然后 写了更改这些数据的set方法
最后 将我们的数据与几个set函数都导出去

然后 我们src下的 redux 下的 store.js 编写代码如下

import { configureStore } from "@reduxjs/toolkit";
import balanceReducer from "./balanceSlice";

const store = configureStore({
  reducer: {
    balance: balanceReducer
  }
});

export default store;

这里 我们导入 自己刚才写的 balanceSlice下的index 配置store

然后 我们找到 src目录下的 App.js 组件 编写代码如下

import React from 'react';
import Router from "./router/index";
import {Provider} from "react-redux"
import store from "./redux/store";

export default function App() {
  return (
    <Provider store={store}>
      <Router />
    </Provider>
  );
}

其实关键就在于 通过react-redux 导入Provider组件 嵌套我们的路由组件 让所有的路由组件都能享受到共享的数据资源
然后这个数据资源来自 我们配置的redux/store

然后 src目录下的 components目录下 Order.jsx
这里 我们保证这个组件格式不要有问题就好

import React from 'react';

export default function Order() {

  return (
    <div>
      订单组件
    </div>
  );
}

然后 我们在 src下的 components 下的 balance.jsx
编写代码如下

import React from 'react';
import { useSelector, useDispatch } from "react-redux";
import { setTokenWallet } from "../redux/balanceSlice";

export default function Balance() {
  const state = useSelector((state) => state.balance.TokenWallet);
  const dispatch = useDispatch()
  return (
    <div>
      测试组件{state}
      <button onClick={()=>{
        dispatch(setTokenWallet("1000"))
      }}>修改一下</button>
    </div>
  );
}

这里 我们拿取了 TokenWallet 赋值给了state
然后 当按钮点击 我们调用 setTokenWallet修改TokenWallet值的函数
然后 我们启动项目

这里 我们项目运行起来 会看到 TokenWallet 的展示是完全OK的 一个0
在这里插入图片描述
然后我们点击修改一下的按钮 可以看到 setTokenWallet 已经成功修改了TokenWallet的值
在这里插入图片描述
好啦 那么 既然已经试过是可以用的了
我们 src下 components 下的 balance.jsx 余额组件 先改回一个正常的格式

import React from 'react';
//import { useSelector, useDispatch } from "react-redux";

export default function Balance() {
  //const state = useSelector((state) => state.balance.TokenWallet);
  return (
    <div>
      余额组件
    </div>
  );
}

然后 我们要做的是 在项目初始化时 就拿到用户的这些信息
那么 在哪里拿?
我们打开 src下的 redux下面的 balanceSlice 下的 index.js文件
在这里多引入一个依赖
在这里插入图片描述
@reduxjs/toolkit 下的 createAsyncThunk
用它来编写异步函数
然后 我们在最下面 这样写

这里 我们导出了一个异步函数 叫 loadBalanceData

然后 balance/fetchBalanceData是这个函数会生成的一个名字 一定要规范一点
然后 我们函数接受两个参数 第一个 是一个data数据对象 然后第二个 我们接受一个对象 里面必须有一个叫dispatch的字段 他是一个回调函数
简单说 这边异步的逻辑完成了 通过 dispatch 回调回去

export const loadBalanceData = createAsyncThunk(
    "balance/fetchBalanceData",
    async (data, {dispatch}) => {
        console.log(data)
    }
)

在这里插入图片描述
逻辑的话 我们先写的比较简单 就把data打印出来看了一下

然后问题来了 我们要在哪里调用呢?
没错 src下的 view下的 index组件
在这里插入图片描述
我们就要在他刚拿完WEB3信息的这个地方去调用 然后 data数据 就是要传这个web3 信息进去

我们直接改写代码如下

import { useEffect } from 'react';
import Web3 from "web3";
import grToken from "../build/grToken.json";
import Exchange from "../build/Exchange.json";
import Balance from "../components/balance";
import Orber from "../components/Order";
import { useDispatch } from "react-redux";
import { loadBalanceData } from "../redux/balanceSlice";
export default function PageIndex() {
  const dispatch = useDispatch()
  useEffect(() =>{
      async function start(){
          const WebData = await initialization()
          window.WebData = WebData;
          dispatch(loadBalanceData(WebData))
      }
      start();
  },[dispatch])

  // 获取web 信息
  async function initialization() {
      var web3 = new Web3(Web3.givenProvider || "http://localhost:8545");
      let account = await web3.eth.requestAccounts();
      let networkId = await web3.eth.net.getId();
      const token = await new web3.eth.Contract(grToken.abi,grToken.networks[networkId].address);
      const etoken = await new web3.eth.Contract(Exchange.abi,Exchange.networks[networkId].address);
      return {
        web3,
        account: account[0],
        grToken: token,
        Exchange: etoken
      }
  }
  return (
    <div>
      <Balance></Balance>
      <Orber></Orber>
      欢迎来到 Web3 练习的世界
    </div>
  );
}

做了部分语法改动 但其实说到底 唯一的改变就是 在initialization返回web3 信息成功后
我们调用了loadBalanceData 并传入了 我们刚获取到的web3 信息

然后 我们loadBalanceData其实也就输出了一下这个传入的data数据
在这里插入图片描述
运行代码 查看控制台 也看得到 他是成功将我们的这个web3对象成功的输出了出来
在这里插入图片描述
具体 要怎么获取到我们当前用户的grtoken 我们还是要看看 之前自己写的合约

打开 grtoken的合约 我们会发现 当年我们写了个对象 balanceOf
只需要提供当前账号的地址 就会返回对应的toekn
在这里插入图片描述
我们直接将src下redux 下 balanceSlice下的inex 中的 loadBalanceData代码更改如下

export const loadBalanceData = createAsyncThunk(
    "balance/fetchBalanceData",
    async (data, {dispatch}) => {
        //从data中将web3信息都结构出来
        const {
            web3,
            account,
            grToken,
            Exchange
        } = data;
        //用户当前用户token信息
        const TokenWallet = await grToken.methods.balanceOf(account).call()
        console.log(TokenWallet)
       //获取当前用户在交易所的token信息

    }
)

这里 我们通过grToken合约的balanceof函数 传入account当前用户 去获取当前用户的grtoken信息
这里注意要用 call 告诉他们操作不上链 不消耗燃料啊 这个很关键
然后我们拿到 控制台输出一下

我们运行代码
在这里插入图片描述
可以看到 我们用户的token 信息 就这样获取出来了 但是这个单位明显是有的问题的 我们要转换一下
但保持最小状态 是利于全局管理的 所以 我们是要转换 但绝对不是在这里转换 这里要存储数据 我们在redux中自然是要保持最小单位的数据管理

最后 等他获取成功了 我们调用 setTokenWallet让他把数据 赋值给我们全局的TokenWallet做管理
在这里插入图片描述
然后是交易所中的 grtoken
这里 我们还是要去看自己之前交易所合约
这里 我们也写了个 balanceof 需要传入当前要查的是哪一种token的地址 和 当前用户的地址
在这里插入图片描述
但是这个要注意下 o的大小写 这个也是我之前留的坑了
我们这里这样写

const TokenExchange = await Exchange.methods.balanceof(grToken.options.address,account).call()
console.log(TokenExchange)

通过Exchange交易所 合约 调用他的balanceof函数 这里 我们通过grToken合约对象 拿到他的地址 然后传入当前账号的地址
最后得到token信息
然后在控制台输出
在这里插入图片描述
运行结果如下
在这里插入图片描述
啊 0 没毛病啊
我们并没有往交易所中存储grtoken 所以是没什么问题的

好 那 这里 我们获取到了 就赋值回调一下
在这里插入图片描述
然后 获取用户当前的ETH 这个就比较简单了 我们很早就演示过
直接编写代码如下

const EtherWallet = await web3.eth.getBalance(account)
console.log(EtherWallet)

直接用web3 对象的getBalance 然后传入当前账号就可以了
运行代码 查看看着他打印
在这里插入图片描述
没有任何问题 还是一个最小单位 没有转换过的
在这里插入图片描述
然后 获取到之后 我们还是一样做个数据的写入
在这里插入图片描述
最后一个 获取在交易所中的 ETH

ETH的地址 我们之前写脚本的时候用过
在这里插入图片描述

const ETHER_ADDRESS = '0x0000000000000000000000000000000000000000';

我们直接将这个拿过来
写到我们 src下的 redux下的balanceSlice下的 index中
在这里插入图片描述
然后 我们最下面直接这样写

//获取当前用户交易所下的ETH
const EtherExchange = await Exchange.methods.balanceof(ETHER_ADDRESS,account).call()
console.log(EtherExchange)

还是用我们之前交易所写的balanceof 方法 这次 我们的token地址换成了 ETH 账号还是当前账号
一运行 也是零 没毛病啊 毕竟没有存过
在这里插入图片描述
最后 我们还是这样写入一下就好了
在这里插入图片描述

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

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

相关文章

FedAT:分层机制更新的联邦学习

文章链接&#xff1a;FedAT: A Communication-Efficient Federated Learning Method with Asynchronous Tiers under Non-IID Data 发表会议: SC’21 (International Conference for High Performance Computing, Networking, Storage, and Analysis) 高性能计算&#xff0c;体…

Redis安装与常用命令

目录 一、Reids简介 二、Redis安装 2.1 Linux安装 2.2 Windows安装 三、Redis常用命令 3.1 Redis字符串 3.2 Redis哈希(Hash) 3.3 Redis列表&#xff08;List&#xff09; 3.4 Redis集合&#xff08;Set&#xff09; 一、Reids简介 Redis&#xff08;Remote Dictiona…

11.Z-Stack协议栈使用

f8wConfig.cfg文件 选择信道、设置PAN ID 选择信道 #define DEFAULT_CHANLIST 0x00000800 DEFAULT_CHANLIST 表明Zigbee模块要工作的网络&#xff0c;当有多个信道参数值进行或操作之后&#xff0c;把结果作为 DEFAULT_CHANLIST值 对于路由器、终端、协调器的意义&#xff1…

【Linux网络】Linux网络抓包工具tcpdump

一、tcpdump介绍 tcpdump 是一个Linux的网络抓包工具。它允许用户拦截和显示发送或收到过网络连接到该计算机的TCP/IP和其他数据包。tcpdump 适用于大多数的类Unix系统操作系统(如linux,BSD等)。 二、安装&用法说明 1&#xff09;安装 $ yum -y install tcpdump2&#…

【知网检索征稿】第九届社会科学与经济发展国际学术会议 (ICSSED 2024)

第九届社会科学与经济发展国际学术会议 (ICSSED 2024) 2024 9th International Conference on Social Sciences and Economic Development 第九届社会科学与经济发展国际学术会议(ICSSED 2024)定于2024年3月22-24日在中国北京隆重举行。会议主要围绕社会科学与经济发展等研究…

Everything结合内网穿透搭建在线资料库,一秒实现随时随地访问

Everythingcpolar搭建在线资料库&#xff0c;实现随时随地访问 文章目录 Everythingcpolar搭建在线资料库&#xff0c;实现随时随地访问前言1.软件安装完成后&#xff0c;打开Everything2.登录cpolar官网 设置空白数据隧道3.将空白数据隧道与本地Everything软件结合起来总结 前…

(免费领源码)Java#MYSQL在线学习平台09650-计算机毕业设计项目选题推荐

目 录 摘要 1 绪论 1.1 选题背景及意义 1.2国内外现状分析 1.3论文结构与章节安排 2 在线学习平台系统分析 2.1 可行性分析 2.2 系统业务流程分析 2.3 系统功能分析 2.3.1 功能性分析 2.3.2 非功能性分析 2.4 系统用例分析 2.5本章小结 3 在线学习平台总体设计 …

nginx 常用优化配置项教程

本文目录 跨域配置 动静分离 反向代理-负载均衡 配置SLL证书 资源压缩 缓存机制 IP黑白名单 防盗链 大文件传输优化 跨域问题 产生原因 产生跨域问题的主要原因就在于 「同源策略」 &#xff0c;为了保证用户信息安全&#xff0c;防止恶意网站窃取数据&#xff0c;…

每日一题 2103. 环和杆 (简单)

简单题&#xff0c;直接统计就行 class Solution:def countPoints(self, rings: str) -> int:n len(rings) // 2cnt [[0, 0, 0] for _ in range(10)]for i in range(0, 2*n, 2):if rings[i] "R":cnt[int(rings[i 1])][0] 1if rings[i] "G":cnt[i…

阿里云多款ECS产品全面升级 性能最多提升40%

“阿里云始终围绕‘稳定、安全、性能、成本、弹性’的目标不断创新&#xff0c;为客户创造业务价值。”10月31日&#xff0c;杭州云栖大会上&#xff0c;阿里云弹性计算计算产品线负责人张献涛表示&#xff0c;通过持续的产品和技术创新&#xff0c;阿里云发布了HPC优化实例等多…

conda命令克隆(复制)环境方法及问题解决

背景&#xff1a;与同事进行工作交接&#xff0c;在服务器上想直接拷贝他的环境过来&#xff0c;直接复制anaconda3/envs里的环境包过来后续安装包的时候由于路径是原来的路径会安装到对方环境里&#xff0c;因此使用conda命令来进行环境克隆。 &#xff08;Linux/服务器中&am…

【广州华锐互动】有机化合物结构3D虚拟展示帮助学生更好地理解和掌握复杂化学知识

随着科技的发展&#xff0c;我们的学习方式正在发生深刻的变化。其中&#xff0c;有机化合物结构3D虚拟展示作为一种新兴的教学方式&#xff0c;正在逐渐被广泛接受和应用。这种新型的展示方式对于提高学生的学习效率&#xff0c;增强学习体验&#xff0c;以及推动化学教育的发…

十六章反射与注解总结

16.1 反射 反射&#xff08;Reflection&#xff09;是指在运行时获取类的信息&#xff0c;并可以动态调用类的方法、访问或修改类的属性&#xff0c;以及构造对象的能力。 Java的反射提供了一套API&#xff0c;允许你在运行时检查类的结构、调用类的方法、获取和设置类的属性&…

curl(一)基础

一 基础入门 ① 本文讲解curl的版本 curl支持的协议 国密curl ② 升级curl 后续&#xff1a; 注意新版本的新特性备注&#xff1a; 升级的必要性 yum 升级 curl 源码编译安装curl ③ curl排错参数 1、-v 或 --verbose --> 重点 2、--trace 和 --trace-ascii --…

小红书薯多功能引流脚本,精准引流工具,内置私信点赞关注评论回复各项功能【引流软件+引流教程】

软件介绍&#xff1a; 多个高级功能精准引流 精准留痕引流&#xff0c;功能非常多 设备需求&#xff1a; 适用于安卓7.0版本&#xff0c;鸿蒙&#xff0c;模拟器均可使用 文章分享者&#xff1a;Linxiaoyu2022 文章的来源&#xff1a;vipwz.blog.csdn.net 有任何互联网问…

Java作业二

一、使用方法编写求圆面积和周长的程序&#xff0c;运行时提示输入圆半径&#xff0c;然后输出计算结果。运行效果如下图所示&#xff1a; import java.util.Scanner;public class Test {public static void main(String[] args) {Scanner input new Scanner(System.in);Syste…

安卓抓包之小黄鸟

下载安装 下载地址: https://download.csdn.net/download/yijianxiangde100/88496463 安装apk 即可。 证书配置:

SQL INNER JOIN 关键字(内部连接)

SQL INNER JOIN 关键字&#xff08;内部连接&#xff09; 内部链接INNER JOIN关键字选择两个表中具有匹配值的记录。 SQL INNER JOIN 语法 SELECT column_name(s) FROM table1 INNER JOIN table2 ON table1.column_name table2.column_name; 注释&#xff1a;INNER JOIN 与 …

NEFU数字图像处理(4)图像几何变换

一、图像几何变换基础 1.1概述 定义&#xff1a; 使原始图像能够按照需要&#xff0c;产生大小、形状、位置等方面的几何变化 本质特征&#xff1a; 图像几何变换不是改变图像的像素值&#xff0c;而是改变像素所在的位置。 1.2相关概念 二维图像几何变换可通过矩阵线性变换来…

中心线提取的全卷积网络【IPMI 2019】

论文地址&#xff1a;Excellent-Paper-For-Daily-Reading/medicine at main 类别&#xff1a;医学 时间&#xff1a;2023/11/02 摘要 论文提出了一种将端到端可训练多任务全卷积网络(FCN)与最小路径提取器相结合的中心线提取框架。FCN同时计算中心线距离图和检测分支端点。…