使用Web3js和以太坊客户端交互,实现任意数据上链存储公开查询
前言:最近应公司项目需求,前后对区块链了解了一周,主要研究了 以太坊和智能合约的交互,通过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/
再强调一遍主网账户需要付手续费
使用etherscan查询账户信息
输入账户地址查询
交易详细:input Ddata 就是我们的十六进制自定义数据
博主第一次发文章,有描述不当处请指点,欢迎评论区留言讨论 ????