nodejs、web3js开发以太坊

2023-09-21 11:20:33

nodejs、web3js开发以太坊

本案例主要利用nodejs和web3搭建一个供前端直接调用的接口,主要包含以下功能

获取地址余额   获取一个新的钱包   转账   获取gas   获取当前区块信息

环境

node18+     ganache

依赖

“cors”: “^2.8.5”,
“express”: “^4.18.2”,
“web3”: “^4.1.2”

详解

安装并运行ganache
npm install -g ganache
ganache

之后我们会看到以下的输出就证明我们已经安装成功了
在这里插入图片描述
我们可以通过私钥把钱包导入MetaMask
网络需要自己配置,主要参数就是ganache中提供这些
下图是我本地的网络配置,配置完成后就可以把私钥导入钱包了
在这里插入图片描述

创建一个web服务器实例

其中包含core处理跨域请求,解析json表单数据等
自定义JSON序列化方法,将BigInt转换为字符串这个是为了将后面获取区块数据的返回值转换为字符串配置的

const express = require("express")
const cors = require("cors")


const app = express()

app.use(express.json())		//处理json数据
app.use(cors())		//处理跨域请求

// 自定义JSON序列化方法,将BigInt转换为字符串
app.set('json replacer', (key, value) => {
    if (typeof value === 'bigint') {
        return value.toString();
    }
    return value;
});

const router = require("./router/index.js")
app.use('/api',router)

app.listen(3000,()=>{
	console.log("server is running ar http://127.0.0.1:3000")
})
创建web3erver.js文件

这个文件主要用来提供与web3交互的各种方法
导入web3d的包用require方法导入需要加上大括号
用import 方法导入需要再pachage.json中添加type:module
web3js文档地址
http://127.0.0.1:8545这个就是我们本地ganache提供的PRC服务,用于连接本地搭建的以太坊网络

const {Web3, errors} = require("web3")

const web3 = new Web3("http://127.0.0.1:8545")

//获取余额
const getBalance = async (address)=>{
    const res = await web3.eth.getBalance(address)
    const balance = parseFloat(web3.utils.fromWei(res,'ether')).toFixed(3)
    return balance
}

//获取一个新钱包
const getCount = async ()=>{
    const res = await web3.eth.accounts.create()
    return res
}

//转账
const sendEth = async(senderAddress,receiverAddress,privateKey,mount)=>{

const amountToSend = web3.utils.toWei(mount, 'ether'); // 替换为你要发送的以太数量
const gasPrice = web3.utils.toWei('500000', 'gwei'); // 替换为Gas价格
const gasLimit = 21000; // 替换为Gas限制
const chainId = 1337; // 替换为你的本地测试链的chainId

// 构建交易对象
const transactionObject = {
  from: senderAddress,
  to: receiverAddress,
  value: amountToSend,
  gasPrice: gasPrice,
  gas: gasLimit,
  nonce: await web3.eth.getTransactionCount(senderAddress),
  chainId: chainId,
};

// 签名交易
const signedTransaction = await web3.eth.accounts.signTransaction(transactionObject, privateKey);

// 发送交易
const result = await web3.eth.sendSignedTransaction(signedTransaction.rawTransaction)
  .on('transactionHash', (hash) => {

  })
  .on('receipt', (receipt) => {
  })
  .on('error', (error) => {
    console.error('交易错误:', error);
  });

return result.transactionHash
}

//获取gas
const getGasPrice = async()=>{
  const res = await web3.eth.getGasPrice()
  const price = web3.utils.fromWei(res,'ether')
  return price
}

//获取当前区块信息
const getBlock = async ()=>{
  const res = await web3.eth.getBlock()
  return res
}

module.exports = {
    getBalance,
    getCount,
    sendEth,
    getGasPrice,
    getBlock
}

路由模块

这个模块和我们平时写接口差不多没有什么区别

const express = require("express")
const routerHandler = require("../routerHandler/index.js")
const router = express.Router()

router.get('/balance',routerHandler.getBalance)

router.get('/getcount',routerHandler.getAccount)

router.post('/send',routerHandler.sendEth)

router.get('/gas',routerHandler.getGas)

router.get('/getblock',routerHandler.getBlock)


module.exports = router

路由函数处理模块

这个模块主要需要注意我们通过web3server里面各种方法得到的结果是一个promise对象,需要用async await 进一步解构才能得到结果,所以每个函数前面都加上了async

const {getBalance,getCount,sendEth,getGasPrice,getBlock} = require("../web3Server/server.js")

exports.getBalance = async (req,res)=>{
    const address = req.body.address
    const balance = await getBalance(address)
    return res.json({
        code:200,
        mag:"请求成功",
        data:balance
    })
}

exports.getAccount = async(req,res)=>{
    const data = await getCount()
    console.log(data)
    return res.json({
        code:200,
        msg:"请求成功",
        data:data
    })
}

exports.sendEth = async (req,res)=>{
    const senderAddress = req.body.senderAddress
    const receiverAddress = req.body.receiverAddress
    const privateKey = req.body.privateKey
    const count = req.body.count
    const result = await sendEth(senderAddress,receiverAddress,privateKey,count)
   if(result ==''){
    return res.json({
        code:400,
        msg:"请求失败"
    })
   }
   return res.json({
    code:200,
    msg:"请求成功",
    data:{
        "hash":result
    }
   })
}

exports.getGas = async (req,res)=>{
    const price = await getGasPrice()
    if(!price){
        return res.json({
            code:"400",
            msg:"请求失败"
        })
    }
    return res.json({
        code:"200",
        msg:"请求成功",
        data:`${price}ETH`

    })
}

//需要再router前面定义JSON序列化方法,将BigInt转换为字符串
exports.getBlock = async (req,res)=>{
    const result =await getBlock()
    if(!result){
        return res.json({
            code:400,
            msg:"请求失败"
        })
    }
    return res.json({
        code:200,
        msg:"请求成功",
        data:result
    })
}

测试

直接发起请求即可,除了转账需要参数以外,其他接口都不需要参数,直接发起请求就可以拿到结果
在这里插入图片描述

完整代码

https://github.com/Traderxue/node-web3

更多推荐

JS操作字符串面试题系列(2)-每天做5题

目录前排提示JS操作字符串方法学习系列(1)-每天学习10个方法JS操作字符串方法学习系列(2)-每天学习10个方法JS操作字符串方法学习系列(3)-每天学习10个方法JS操作字符串方法学习系列(4)-每天学习10个方法JS操作字符串方法学习系列(5)-每天学习10个方法题目6.如何将字符串转换为大写?7.如何从字符串

【深度学习】 Python 和 NumPy 系列教程(十八):Matplotlib详解:2、3d绘图类型(4)3D曲面图(3D Surface Plot)

目录一、前言二、实验环境三、Matplotlib详解1、2d绘图类型2、3d绘图类型0.设置中文字体1.3D线框图(3DLinePlot)2.3D散点图(3DScatterPlot)3.3D条形图(3DBarPlot)4.3D曲面图(3DSurfacePlot)一、前言Python是一种高级编程语言,由Guidovan

轻量级的Python IDE —— Thonny

现在的开发工具太多了,而且每个开发工具都致力于做成最好用最智能的工具,所以功能越堆越多,越怼越智能。安装这些开发工具比较烧脑,经常需要经过许多配置步骤。作为一个Python开发者来说,好多人光是这些配置都要弄半天。配置好之后,打开软件,发现满屏都是菜单、按钮,无从下手,学习这些功能使用又是一大难题。推荐一款超级轻量级的

Java源码分析(二)Double

本篇是源码分析的第二篇,上篇我们一起分析了Integer类的源码,本篇一起学习下Double类的源码,看下其实现。一、Double类图首先,相比Integer,Double类的源码只有1000+行代码。如下是Integer及其关联类/接口的类图:​通过Integer类的类图,我们总结下它的特点:Double类继承自抽象

《Linux 内核编码风格》官方手册!

这是一篇官方手册译文,分享给大家这是一个简短的文档,描述了Linux内核的首选编码风格。编码风格非常个人化,这是我必须要维护的代码(指Linux内核代码)的编码风格,对于其他项目代码,我也希望使用它。写内核代码时请至少考虑本文提出的风格。首先,我建议打印出GNU编码标准,然后不要阅读。烧掉它们,这是一个很棒的象征性动作

mariadb

1.[root@localhostsystem]#yuminstall-ymariadb-server已加载插件:fastestmirror,langpacksLoadingmirrorspeedsfromcachedhostfile*base:ftp.sjtu.edu.cn*extras:ftp.sjtu.edu.c

网络安全攻防对抗之隐藏通信隧道技术整理

完成内网信息收集工作后,渗透测试人员需要判断流量是否出得去、进得来。隐藏通信隧道技术常用于在访问受限的网络环境中追踪数据流向和在非受信任的网络中实现安全的数据传输。一、隐藏通信隧道基础知识(一)隐藏通信隧道概述一般的网络通信,先在两台机器之间建立TCP连接,然后进行正常的数据通信。在知道IP地址的情况下,可以直接发送报

Flink中的批和流

批处理的特点是有界、持久、大量,非常适合需要访问全部记录才能完成的计算工作,一般用于离线统计。流处理的特点是无界、实时,无需针对整个数据集执行操作,而是对通过系统传输的每个数据项执行操作,一般用于实时统计。而在Flink中,一切都是由流组成的,Flink认为有界数据集是无界数据流的一种特例,离线数据是有界限的流,实时数

MySQL如何高效实现刷脏页,了解原理并学会配置

目录一、什么是刷脏页二、MySQL刷脏页的策略三、MySQL刷脏页的实现原理四、MySQL如何实现刷脏页一、什么是刷脏页在MySQL中,刷脏页是指将内存中已被修改的数据页(也称为脏页)写回到磁盘的过程。当MySQL执行数据更新操作时,会将修改后的数据先写入内存的缓存区(称为脏页),然后通过后台线程将这些脏页定期或根据一

【MySQL】专栏合集,从基础概念到调优

作者简介前言博主之前写过一个MySQL的系列,从基础概念、SQL到底层原理、优化,专栏地址:https://blog.csdn.net/joker_zjn/category_12305262.html?spm=1001.2014.3001.5482本文会是这个系列的清单,拉通来聊一聊Mysql从基础概念一直到优化的相关

爬虫 — Js 逆向案例四网易云音乐评论

目标网站:https://music.163.com/#/song?id=2054300084需求:获取评论内容,用户名案例分析1、分析网站加载方式动态加载,抓包找到目标url:https://music.163.com/weapi/comment/resource/comments/get?csrf_token=2、

热文推荐