区块链以太坊使用Web3实现任何数据上链存储公开查询

时间:2024-04-13 09:23:07

前言:最近应公司项目需求,前后对区块链了解了一周,主要研究了 以太坊和智能合约的交互,通过geth控制台或者web3,创建账户,查询余额,发起交易,与合约交互查询代币余额等。

实现方法实际上就是调用交易方法传入自定义data,前提data必须转成16进制

环境搭建

系统: ubuntu18
以太坊客户端
使用工具及依赖: nodejs,web3

搭建以太坊客户端

这里给出两种方案:

一:自行搭建geth节点(同步链上数据对硬件有要求,可以使用dev模式)

参考:https://blog.****.net/u012213581/article/details/89058956

二:(推荐)使用Infura接入以太网节点,无需自行搭建geth

这篇文章有详细介绍:https://blog.****.net/TurkeyCock/article/details/85103434

编写交互代码

web3中文手册:http://cw.hubwiz.com/card/c/web3.js-1.0/1/1/1/

最新系统自带npm,node

[email protected]:~$ npm -v
3.5.2
[email protected]:~$ node -v
v8.10.0

创建目录,安装web3依赖

cd /opt
sudo mkdir web3test
chmod 777 web3test/ -R
cd web3test
npm install web3

安装完成后编辑代码
vim testweb3tran.js 或者 IDE编辑后上传到指定位置/opt/web3test/

引用server服务

var express = require("express");
var app = express();
var server = require("http").createServer(app);
var net = require('net');

创建web3对象

let Web3=require('web3');
let fs=require('fs');
let web3;

if(typeof web3 !== 'undefined'){ //检查是否已有web3实例
    web3 = new Web3(web3.currentProvider)
}else{
    //否则就连接到给出节点
    web3 = new Web3(new web3.providers.HttpProvider('https://ropsten.infura.io/v3/<PROJECT ID>'));
	//测试节点:https://ropsten.infura.io/v3/<PROJECT ID>
	//主网节点:https://mainnet.infura.io/v3/<PROJECT ID>
	//记得替换自己的 PROJECT ID
	//或者连接本地geth节点:http://127.0.0.1:8545 前提开启 --rpc --rpcport 8545
}

console.log(web3.version) //查看web3版本

节点连接成功检测

web3.eth.getBlock(0, function(error, result){
if(!error)
    console.log("connect should be success")
else
    console.log("something wrong,the connection might be failed")
})

添加web访问路由,通过curl访问 curl http://127.0.0.1:8081/savedata?str=你要存储的数据

app.get("/savedata", function(req, res) {
	let account = '0x...发起交易的地址'
	let user2 = '0x...交易接收账户的地址,可以自己转给自己'
	let strdata = '0x' + Buffer.from(req.query.str).toString('hex')
	
	//开发节点其实可以直接使用web3.eth.sendTransaction,正式节点会报错,可能需要解锁,所以直接使用私钥调用
	//这里说下测试中踏过的坑,geth开发节点创建用户 personal.newAccount("输入密码") 不会输出私钥,需要自行查询
	//参考:https://blog.****.net/northeastsqure/article/details/79476831
	var privateKey = '转出账户的私钥'

	 var tx = {
		from: account,
		to: user2,
		//gasPrice: "20000000000",	//可以默认,有需要可以查下如何设置gas节省旷工费
		gas: 27052,	//如果报错gas过小,请把值调大
		nonce:1,	//每次交易不能重复,不然会报错{"code":-32000,"message":"nonce too low"}
		value:web3.utils.toWei('0', 'ether'),	//单位转换
		data: strdata	//十六进制数据
	  }; 
	  
	  // !!!主网交易需要付手续费!!! 
	  web3.eth.accounts.signTransaction(tx, privateKey).then(signed => {
		var tran = web3.eth.sendSignedTransaction(signed.rawTransaction);

		tran.on('confirmation', (confirmationNumber, receipt) => {
		  console.log('confirmation: ' + confirmationNumber);
		});

		tran.on('transactionHash', hash => {
			console.log('hash');
			console.log(hash);
		  
			if(hash){
				res.writeHead(200, { "Content-Type": "application/json;charset=UTF-8" });

				var data={
					errcode:'0',
					errmsg:'成功',
					data:hash
				};

				res.end(JSON.stringify(data));
			}else{
				var data={
					errcode:'1',
					errmsg:'错误'
				};
						
				res.writeHead(200, { "Content-Type": "application/json;charset=UTF-8" });
				res.end(JSON.stringify(data));
			}
		});
		
		tran.on('receipt', receipt => {
		  console.log('reciept');
		  console.log(receipt);
		});
		
		tran.on('error', console.error);
	  });
})

根据交易返回的hash查询交易详情,该接口只返回存入数据,详细数据自行打印

app.get("/gettran",function(req,res){
	let hash = req.query.hash
	
	web3.eth.getTransaction(hash,function(error,result){
		if(result !== false){
			res.writeHead(200, { "Content-Type": "application/json;charset=UTF-8" });
			
			var data={
				errcode:'0',
				errmsg:'成功',
				data:web3.utils.hexToString(result.input)	//十六进制转utf-8字符
			};

			res.end(JSON.stringify(data));
		}else{
			var data={
				errcode:'1',
				errmsg:'错误'
			};

			res.writeHead(200, { "Content-Type": "application/json;charset=UTF-8" });
			res.end(JSON.stringify(data));
		}
	})
})

该接口可以查询账户余额 传参:addr 账户地址

app.get("/getbalance", function(req, res) {
	var addr = req.query.addr
	if(!addr){
		var data = {
			errcode:'1',
			errmsg:'缺少地址'
		};
		
		res.writeHead(200, { "Content-Type": "application/json;charset=UTF-8" });
		res.end(JSON.stringify(data));
		return;
	}
	
	web3.eth.getBalance(addr,function (error,result) {

		if(result !== false){
			res.writeHead(200, { "Content-Type": "application/json;charset=UTF-8" });
			
			var data={
				errcode:'0',
				errmsg:'成功',
				data:(result == 0 ? 0 : (result / 1000000000000000000))	//这里wei转ether 可以调用web3.utils.fromWei(result, 'ether')
			};

			res.end(JSON.stringify(data));
		}else{
			var data={
				errcode:'1',
				errmsg:'错误'
			};
					
			res.writeHead(200, { "Content-Type": "application/json;charset=UTF-8" });
			res.end(JSON.stringify(data));
		}
	});
})

OK,启动Server

server.listen(8081)

启动Node服务

node testweb3tran.js

可以使用命令

curl http://127.0.01:8081/

或者浏览器直接访问
http://127.0.01:8081/

再强调一遍主网账户需要付手续费
区块链以太坊使用Web3实现任何数据上链存储公开查询
区块链以太坊使用Web3实现任何数据上链存储公开查询

使用etherscan查询账户信息

https://etherscan.io

输入账户地址查询
区块链以太坊使用Web3实现任何数据上链存储公开查询
交易详细:input Ddata 就是我们的十六进制自定义数据
区块链以太坊使用Web3实现任何数据上链存储公开查询
博主第一次发文章,有描述不当处请指点,欢迎评论区留言讨论 ????