web3 React Dapp书写订单 买入/取消操作

2023-11-11 20:44

本文主要是介绍web3 React Dapp书写订单 买入/取消操作,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

好 上文web3 前端dapp从redux过滤出 (我创建与别人创建)正在执行的订单 并展示在Table上中 我们过滤出了 我创建的 与 别人创建的 且 未完成 未取消的订单数据
这边 我们起一下 ganache 环境

ganache -d

在这里插入图片描述
然后 我们项目 发布一下智能合约

truffle migrate --reset

在这里插入图片描述
然后 登录一下 MetaMask
在这里插入图片描述
在 运行一下测试脚本

truffle exec .\scripts\test.js

然后 打开我们的项目 在根目录下的 scripts 目录中 创建一个文件 我这里叫 createOrder.js
编写代码如下

//指定以token grtoken合约
const GrToken = artifacts.require("grToken.sol")
//交易所合约
const Exchange = artifacts.require("Exchange.sol")
//定义E代理地址
const ETHER_ADDRESS = '0x0000000000000000000000000000000000000000';const toWei = (bn) => {return web3.utils.toWei(bn.toString(), "ether");
}module.exports = async function(callback) {const grTokenDai = await GrToken.deployed();const exchage = await Exchange.deployed();//获取用户列表const accounts = await web3.eth.getAccounts();//循环用 accounts 用户列表中第一个用户创建 五个订单for (let i = 1; i <= 5; i++) {await exchage.makeOrder(grTokenDai.address,toWei(101), ETHER_ADDRESS ,toWei(0.01),{from: accounts[0]});}//循环用 accounts 用户列表中第二个用户创建 五个订单for (let i = 1; i <= 5; i++) {await exchage.makeOrder(grTokenDai.address,toWei(101), ETHER_ADDRESS ,toWei(0.01),{from: accounts[1]});}callback()
}

这里 我们直接脚本执行 第一和第二个用户 分别创建出 五个订单 方便 我们后期操作
然后 我们终端运行

truffle exec .\scripts\createOrder.js

在这里插入图片描述
然后 启动我们的dapp
这里 我们第一个用户 已经可用看到非常多订单信息了
在这里插入图片描述
然后 我们 MetaMask 切换一下当前账户
在这里插入图片描述
我们切换成第二个用户
然后刷新dapp
在这里插入图片描述
也是能看到自己的订单和第一个用户创建的订单

然后 我们将 src目录下的 components 下的 Order.jsx 组件代码更改如下

import React from 'react';
import { Card, Col, Row ,Table,Button } from 'antd';
import {useSelector} from "react-redux"
import moment from "moment"function converTime(t){return moment(t*1000).format("YYYY/MM/DD")
}function convert(unit) {return window.WebData ? unit&&window.WebData.web3.utils.fromWei(unit, "ether") : ""
}function getRenderOrder(order,type) {if(!window.WebData) {return []}const account = window.WebData.account//收集起所有 已完成 或 已取消的数据idlet filterIds = [...order.Cancelorders,...order.Fillorders].map(item=>item.id)let makeorders = order.Allorders.filter(item=> !filterIds.includes(item.id))if (type === 1) {return makeorders.filter(item=>item.user === account)} else {return makeorders.filter(item=>item.user !== account)}
}export default function Order() {const order = useSelector(state => state.order)const columns = [{title: 'ETH',dataIndex: 'amountGive',render:(amountGive)=><b>{ convert(amountGive) }</b>,key: 'amountGive'},{title: 'GrToken',dataIndex: 'amountGet',render:(amountGet)=><b>{ convert(amountGet) }</b>,key: 'amountGet'},{title: '创建时间',dataIndex: 'timestamp',render:(timestamp)=><div>{ converTime(timestamp) }</div>,key: 'timestamp'},];const columns1 = [...columns,{title: '操作',render:(item)=><Button type = "text">取消</Button>}]const columns2 = [...columns,{title: '操作',render:(item)=><Button type = "text">买入</Button>}]return (<div style = {{marginTop:'10px'}}><Row><Col span={8}><Card title="已完成" bordered={false} style = {{ margin: '10px' }}><Table dataSource={order.Fillorders} columns={columns} rowKey={item=> item.id}/></Card></Col><Col span={8}><Card title="我创建的" bordered={false} style = {{ margin: '10px' }}><Table dataSource={getRenderOrder(order,1)} columns={columns1} rowKey={item=> item.id}/></Card></Col><Col span={8}><Card title="其他交易中订单" bordered={false} style = {{ margin: '10px' }}><Table dataSource={getRenderOrder(order,2)} columns={columns2} rowKey={item=> item.id}/></Card></Col></Row></div>);
}

这里 我们引入了 Button 按钮
然后 重新加了 两个 表头数据 columns1 和 columns2
他们都合并了 columns 原本的数据结果 然后多加了一列 叫操作 对应一个Button按钮
我创建的 叫取消
另一个叫 买入 买入别人创建的订单

然后 这里 我们先找到 antd 文档中的 对话框
在这里插入图片描述
首先 这里 我们需要 从react中引入 useState 然后从antd中 引入 Modal对话框组件
在这里插入图片描述
然后 定义一下 对话框开关 和当前操作的订单id 以及逻辑函数

//控制对话框的 布尔值
const [isModalOpen, setIsModalOpen] = useState(false);
//记录当前正在操作的订单id
const [currentId, setCurrentId] = useState(null);//点击取消订单时触发
const triggerCancellation = (id) => {setIsModalOpen(true);setCurrentId(id);
}
//对话框点击 确定 时触发
const handleOk = () => {setIsModalOpen(false);
};
//取消 或 关闭 对话框时触发
const handleCancel = () => {setIsModalOpen(false);
};

在这里插入图片描述
然后 在元素中写出这个Modal对话框组件
在这里插入图片描述
最后 在取消订单的按钮 绑定上 onClick 开启对话框函数
在这里插入图片描述
item.id 表示 我们调用函数时 将当前订单的id 传进来
然后 我们运行项目 点击取消订单
对话框 就弹出来了
在这里插入图片描述
至于取消订单的具体逻辑 我们直接来看交易所代码 我们之前写了个cancelorder函数 用来取消订单 它只需要一个参数 订单的id 然后其他的具体逻辑 我们会自己调事件的
在这里插入图片描述
这里 我们先换回第一个账号吧
在这里插入图片描述
然后 我们将刚才在 src下 components 下的 Order.jsx中 的 handleOk编写代码如下

//对话框点击 确定 时触发const handleOk = () => {const {account,Exchange} = window.WebData;Exchange.methods.cancelorder(currentId).send({from: account})setIsModalOpen(false);};

这里 我们函数也写了注释了 他是只有用户点击确认之后才触发的 就表示 用户已经确定 要取消这个订单了
然后 我们通过我们存在window上的 WebData对象 拿到 交易所智能合约Exchange对象 和 account当前登录用户
然后通过Exchange 调用我们自己写的 取消订单 cancelorder函数 传入 我们之前存起来的 当前订单id currentId 然后 指定 send 因为 我们这个操作是要上链的
然后 我们传入当前用户为from 字段
然后 我们运行代码 点击取消订单
在这里插入图片描述
然后点击确定
在这里插入图片描述
然后 页面右侧 就会弹出这个操作提示按钮 因为这设计到了 燃料操作
在这里插入图片描述
我们直接点击确认
在这里插入图片描述
一路确认 最后完成之后 我们的数据并不会自动更新 因为我们没有订阅 但是 当你手动刷新界面 会发现 我们取消的那条 3ETH 的订单就没有了 因为已经被取消掉了
在这里插入图片描述
然后 我们也可以看MetaMask下面这个活动 会将你取消订单的动作记录下来
在这里插入图片描述
这样 就确认了 我们取消订单的功能 确实是好用的 然后 我们来看买入
我们先加上 逻辑层的一些控制对话框代码

//控制买入弹出开启
const [buy, setBuy] = useState(false);
//取消 或 关闭 对话框时触发
const buyCancel = () => {setBuy(false);
};
//对话框点击 确定 时触发
const buyleOk = () => {setIsModalOpen(false);
};
//点击买入订单时触发
const startBuying = (id) => {setBuy(true);setCurrentId(id);
}

在这里插入图片描述
然后 我们在元素层 加上 买入确定的对话框
在这里插入图片描述
这样 我们点击买入 提示弹窗就出来了
在这里插入图片描述
然后 我们交易所中 也写了一个 fillorder 函数 他也是 只需要一个参数id
通过id完成订单买入
在这里插入图片描述
这样 我们直接将 刚才写的 buyleOk 函数 改成这样就好了

//对话框点击 确定 时触发
const buyleOk = () => {const {account,Exchange} = window.WebData;Exchange.methods.fillorder(currentId).send({from: account})setBuy(false);
};

逻辑还是跟取消订单差不多 用户确定之后 从我们挂在 window上的WebData 对象中 结构出 当前用户和交易所合约对象
然后 我们通过交易所对象 调用fillorder函数 传入当前操作订单的id
他也会改变链上结构 要用send
当前用户为from字段

然后 我们运行代码
然后 我们记好 自己 ETH的数量 因为我们的grtoken存在燃料的概念 所以 可能有点额外扣除 我们就看ETH
然后 我们点击买入
在这里插入图片描述
然后我们选择确定
在这里插入图片描述
然后 界面右侧 会弹出操作提示 这里 我们点击确定
在这里插入图片描述
因为没有订阅 所以 我们界面并不会自动更新 但我们刷新界面 我们看三个点
ETH 加了 0.01 然后 我们完成的订单多了一条 别人的订单 少了一条
在这里插入图片描述
这就说明 我们操作成功了

最后 我们订单组件的代码是这样

import React, { useState } from 'react';import { Card, Col, Row ,Table,Button, Modal } from 'antd';
import {useSelector} from "react-redux"
import moment from "moment"function converTime(t){return moment(t*1000).format("YYYY/MM/DD")
}function convert(unit) {return window.WebData ? unit&&window.WebData.web3.utils.fromWei(unit, "ether") : ""
}function getRenderOrder(order,type) {if(!window.WebData) {return []}const account = window.WebData.account//收集起所有 已完成 或 已取消的数据idlet filterIds = [...order.Cancelorders,...order.Fillorders].map(item=>item.id)let makeorders = order.Allorders.filter(item=> !filterIds.includes(item.id))if (type === 1) {return makeorders.filter(item=>item.user === account)} else {return makeorders.filter(item=>item.user !== account)}
}export default function Order() {//控制对话框的 布尔值const [isModalOpen, setIsModalOpen] = useState(false);//记录当前正在操作的订单idconst [currentId, setCurrentId] = useState(null);//点击取消订单时触发const triggerCancellation = (id) => {setIsModalOpen(true);setCurrentId(id);}//对话框点击 确定 时触发const handleOk = () => {const {account,Exchange} = window.WebData;Exchange.methods.cancelorder(currentId).send({from: account})setIsModalOpen(false);};//取消 或 关闭 对话框时触发const handleCancel = () => {setIsModalOpen(false);};//控制买入弹出开启const [buy, setBuy] = useState(false);//取消 或 关闭 对话框时触发const buyCancel = () => {setBuy(false);};//对话框点击 确定 时触发const buyleOk = () => {const {account,Exchange} = window.WebData;Exchange.methods.fillorder(currentId).send({from: account})setBuy(false);};//点击买入订单时触发const startBuying = (id) => {setBuy(true);setCurrentId(id);}const order = useSelector(state => state.order)const columns = [{title: 'ETH',dataIndex: 'amountGive',render:(amountGive)=><b>{ convert(amountGive) }</b>,key: 'amountGive'},{title: 'GrToken',dataIndex: 'amountGet',render:(amountGet)=><b>{ convert(amountGet) }</b>,key: 'amountGet'},{title: '创建时间',dataIndex: 'timestamp',render:(timestamp)=><div>{ converTime(timestamp) }</div>,key: 'timestamp'},];const columns1 = [...columns,{title: '操作',render:(item)=><Button type = "text" onClick={()=>{triggerCancellation(item.id)}}>取消</Button>}]const columns2 = [...columns,{title: '操作',render:(item)=><Button type = "text" onClick={()=>{startBuying(item.id)}}>买入</Button>}]return (<div style = {{marginTop:'10px'}}><Row><Col span={8}><Card title="已完成" bordered={false} style = {{ margin: '10px' }}><Table dataSource={order.Fillorders} columns={columns} rowKey={item=> item.id}/></Card></Col><Col span={8}><Card title="我创建的" bordered={false} style = {{ margin: '10px' }}><Table dataSource={getRenderOrder(order,1)} columns={columns1} rowKey={item=> item.id}/></Card></Col><Col span={8}><Card title="其他交易中订单" bordered={false} style = {{ margin: '10px' }}><Table dataSource={getRenderOrder(order,2)} columns={columns2} rowKey={item=> item.id}/></Card></Col></Row><Modaltitle="操作提示"open={isModalOpen}okText="确定"cancelText="取消"onOk={handleOk}onCancel={handleCancel}><p>您确定要取消当前订单吗?</p></Modal><Modaltitle="操作提示"open={buy}okText="确定"cancelText="取消"onOk={buyleOk}onCancel={buyCancel}><p>您确认要买入当前订单吗?</p></Modal></div>);
}

但是 目前体验比较差 因为我们操作完成 不会自动更新 需要手动刷新界面数据才会更新
因为 我们需要对这些事件进行订阅
那么 我们下文继续

这篇关于web3 React Dapp书写订单 买入/取消操作的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/392727

相关文章

Go异常处理、泛型和文件操作实例代码

《Go异常处理、泛型和文件操作实例代码》Go语言的异常处理机制与传统的面向对象语言(如Java、C#)所使用的try-catch结构有所不同,它采用了自己独特的设计理念和方法,:本文主要介绍Go异... 目录一:异常处理常见的异常处理向上抛中断程序恢复程序二:泛型泛型函数泛型结构体泛型切片泛型 map三:文

SpringBoot返回文件让前端下载的几种方式

《SpringBoot返回文件让前端下载的几种方式》文章介绍了开发中文件下载的两种常见解决方案,并详细描述了通过后端进行下载的原理和步骤,包括一次性读取到内存和分块写入响应输出流两种方法,此外,还提供... 目录01 背景02 一次性读取到内存,通过响应输出流输出到前端02 将文件流通过循环写入到响应输出流

SpringBoot+Vue3整合SSE实现实时消息推送功能

《SpringBoot+Vue3整合SSE实现实时消息推送功能》在日常开发中,我们经常需要实现实时消息推送的功能,这篇文章将基于SpringBoot和Vue3来简单实现一个入门级的例子,下面小编就和大... 目录前言先大概介绍下SSE后端实现(SpringBoot)前端实现(vue3)1. 数据类型定义2.

MySQL基本表查询操作汇总之单表查询+多表操作大全

《MySQL基本表查询操作汇总之单表查询+多表操作大全》本文全面介绍了MySQL单表查询与多表操作的关键技术,包括基本语法、高级查询、表别名使用、多表连接及子查询等,并提供了丰富的实例,感兴趣的朋友跟... 目录一、单表查询整合(一)通用模版展示(二)举例说明(三)注意事项(四)Mapper简单举例简单查询

Nginx概念、架构、配置与虚拟主机实战操作指南

《Nginx概念、架构、配置与虚拟主机实战操作指南》Nginx是一个高性能的HTTP服务器、反向代理服务器、负载均衡器和IMAP/POP3/SMTP代理服务器,它支持高并发连接,资源占用低,功能全面且... 目录Nginx 深度解析:概念、架构、配置与虚拟主机实战一、Nginx 的概念二、Nginx 的特点

MySQL 数据库进阶之SQL 数据操作与子查询操作大全

《MySQL数据库进阶之SQL数据操作与子查询操作大全》本文详细介绍了SQL中的子查询、数据添加(INSERT)、数据修改(UPDATE)和数据删除(DELETE、TRUNCATE、DROP)操作... 目录一、子查询:嵌套在查询中的查询1.1 子查询的基本语法1.2 子查询的实战示例二、数据添加:INSE

使用Python在PDF中绘制多种图形的操作示例

《使用Python在PDF中绘制多种图形的操作示例》在进行PDF自动化处理时,人们往往首先想到的是文本生成、图片嵌入或表格绘制等常规需求,然而在许多实际业务场景中,能够在PDF中灵活绘制图形同样至关重... 目录1. 环境准备2. 创建 PDF 文档与页面3. 在 PDF 中绘制不同类型的图形python

Java 操作 MinIO详细步骤

《Java操作MinIO详细步骤》本文详细介绍了如何使用Java操作MinIO,涵盖了从环境准备、核心API详解到实战场景的全过程,文章从基础的桶和对象操作开始,到大文件分片上传、预签名URL生成... 目录Java 操作 MinIO 全指南:从 API 详解到实战场景引言:为什么选择 MinIO?一、环境

前端Visual Studio Code安装配置教程之下载、汉化、常用组件及基本操作

《前端VisualStudioCode安装配置教程之下载、汉化、常用组件及基本操作》VisualStudioCode是微软推出的一个强大的代码编辑器,功能强大,操作简单便捷,还有着良好的用户界面,... 目录一、Visual Studio Code下载二、汉化三、常用组件1、Auto Rename Tag2

在DataGrip中操作MySQL完整流程步骤(从登录到数据查询)

《在DataGrip中操作MySQL完整流程步骤(从登录到数据查询)》DataGrip是JetBrains公司出品的一款现代化数据库管理工具,支持多种数据库系统,包括MySQL,:本文主要介绍在D... 目录前言一、登录 mysql 服务器1.1 打开 DataGrip 并添加数据源1.2 配置 MySQL