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

相关文章

Springboot的ThreadPoolTaskScheduler线程池轻松搞定15分钟不操作自动取消订单

《Springboot的ThreadPoolTaskScheduler线程池轻松搞定15分钟不操作自动取消订单》:本文主要介绍Springboot的ThreadPoolTaskScheduler线... 目录ThreadPoolTaskScheduler线程池实现15分钟不操作自动取消订单概要1,创建订单后

SpringBoot操作spark处理hdfs文件的操作方法

《SpringBoot操作spark处理hdfs文件的操作方法》本文介绍了如何使用SpringBoot操作Spark处理HDFS文件,包括导入依赖、配置Spark信息、编写Controller和Ser... 目录SpringBoot操作spark处理hdfs文件1、导入依赖2、配置spark信息3、cont

使用JavaScript操作本地存储

《使用JavaScript操作本地存储》这篇文章主要为大家详细介绍了JavaScript中操作本地存储的相关知识,文中的示例代码讲解详细,具有一定的借鉴价值,有需要的小伙伴可以参考一下... 目录本地存储:localStorage 和 sessionStorage基本使用方法1. localStorage

使用JavaScript将PDF页面中的标注扁平化的操作指南

《使用JavaScript将PDF页面中的标注扁平化的操作指南》扁平化(flatten)操作可以将标注作为矢量图形包含在PDF页面的内容中,使其不可编辑,DynamsoftDocumentViewer... 目录使用Dynamsoft Document Viewer打开一个PDF文件并启用标注添加功能扁平化

React实现原生APP切换效果

《React实现原生APP切换效果》最近需要使用Hybrid的方式开发一个APP,交互和原生APP相似并且需要IM通信,本文给大家介绍了使用React实现原生APP切换效果,文中通过代码示例讲解的非常... 目录背景需求概览技术栈实现步骤根据 react-router-dom 文档配置好路由添加过渡动画使用

JavaScript DOM操作与事件处理方法

《JavaScriptDOM操作与事件处理方法》本文通过一系列代码片段,详细介绍了如何使用JavaScript进行DOM操作、事件处理、属性操作、内容操作、尺寸和位置获取,以及实现简单的动画效果,涵... 目录前言1. 类名操作代码片段代码解析2. 属性操作代码片段代码解析3. 内容操作代码片段代码解析4.

Springboot使用RabbitMQ实现关闭超时订单(示例详解)

《Springboot使用RabbitMQ实现关闭超时订单(示例详解)》介绍了如何在SpringBoot项目中使用RabbitMQ实现订单的延时处理和超时关闭,通过配置RabbitMQ的交换机、队列和... 目录1.maven中引入rabbitmq的依赖:2.application.yml中进行rabbit

SpringBoot使用Apache POI库读取Excel文件的操作详解

《SpringBoot使用ApachePOI库读取Excel文件的操作详解》在日常开发中,我们经常需要处理Excel文件中的数据,无论是从数据库导入数据、处理数据报表,还是批量生成数据,都可能会遇到... 目录项目背景依赖导入读取Excel模板的实现代码实现代码解析ExcelDemoInfoDTO 数据传输

Python使用asyncio实现异步操作的示例

《Python使用asyncio实现异步操作的示例》本文主要介绍了Python使用asyncio实现异步操作的示例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋... 目录1. 基础概念2. 实现异步 I/O 的步骤2.1 定义异步函数2.2 使用 await 等待异

C#如何优雅地取消进程的执行之Cancellation详解

《C#如何优雅地取消进程的执行之Cancellation详解》本文介绍了.NET框架中的取消协作模型,包括CancellationToken的使用、取消请求的发送和接收、以及如何处理取消事件... 目录概述与取消线程相关的类型代码举例操作取消vs对象取消监听并响应取消请求轮询监听通过回调注册进行监听使用Wa