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

相关文章

CSS Padding 和 Margin 区别全解析

《CSSPadding和Margin区别全解析》CSS中的padding和margin是两个非常基础且重要的属性,它们用于控制元素周围的空白区域,本文将详细介绍padding和... 目录css Padding 和 Margin 全解析1. Padding: 内边距2. Margin: 外边距3. Padd

CSS will-change 属性示例详解

《CSSwill-change属性示例详解》will-change是一个CSS属性,用于告诉浏览器某个元素在未来可能会发生哪些变化,本文给大家介绍CSSwill-change属性详解,感... will-change 是一个 css 属性,用于告诉浏览器某个元素在未来可能会发生哪些变化。这可以帮助浏览器优化

CSS去除a标签的下划线的几种方法

《CSS去除a标签的下划线的几种方法》本文给大家分享在CSS中,去除a标签(超链接)的下划线的几种方法,本文给大家介绍的非常详细,感兴趣的朋友一起看看吧... 在 css 中,去除a标签(超链接)的下划线主要有以下几种方法:使用text-decoration属性通用选择器设置:使用a标签选择器,将tex

前端高级CSS用法示例详解

《前端高级CSS用法示例详解》在前端开发中,CSS(层叠样式表)不仅是用来控制网页的外观和布局,更是实现复杂交互和动态效果的关键技术之一,随着前端技术的不断发展,CSS的用法也日益丰富和高级,本文将深... 前端高级css用法在前端开发中,CSS(层叠样式表)不仅是用来控制网页的外观和布局,更是实现复杂交

Python将博客内容html导出为Markdown格式

《Python将博客内容html导出为Markdown格式》Python将博客内容html导出为Markdown格式,通过博客url地址抓取文章,分析并提取出文章标题和内容,将内容构建成html,再转... 目录一、为什么要搞?二、准备如何搞?三、说搞咱就搞!抓取文章提取内容构建html转存markdown

在React中引入Tailwind CSS的完整指南

《在React中引入TailwindCSS的完整指南》在现代前端开发中,使用UI库可以显著提高开发效率,TailwindCSS是一个功能类优先的CSS框架,本文将详细介绍如何在Reac... 目录前言一、Tailwind css 简介二、创建 React 项目使用 Create React App 创建项目

vue使用docxtemplater导出word

《vue使用docxtemplater导出word》docxtemplater是一种邮件合并工具,以编程方式使用并处理条件、循环,并且可以扩展以插入任何内容,下面我们来看看如何使用docxtempl... 目录docxtemplatervue使用docxtemplater导出word安装常用语法 封装导出方

Mysql表的简单操作(基本技能)

《Mysql表的简单操作(基本技能)》在数据库中,表的操作主要包括表的创建、查看、修改、删除等,了解如何操作这些表是数据库管理和开发的基本技能,本文给大家介绍Mysql表的简单操作,感兴趣的朋友一起看... 目录3.1 创建表 3.2 查看表结构3.3 修改表3.4 实践案例:修改表在数据库中,表的操作主要

C# WinForms存储过程操作数据库的实例讲解

《C#WinForms存储过程操作数据库的实例讲解》:本文主要介绍C#WinForms存储过程操作数据库的实例,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录一、存储过程基础二、C# 调用流程1. 数据库连接配置2. 执行存储过程(增删改)3. 查询数据三、事务处

Java使用Curator进行ZooKeeper操作的详细教程

《Java使用Curator进行ZooKeeper操作的详细教程》ApacheCurator是一个基于ZooKeeper的Java客户端库,它极大地简化了使用ZooKeeper的开发工作,在分布式系统... 目录1、简述2、核心功能2.1 CuratorFramework2.2 Recipes3、示例实践3