写在最前:以下所有代码基于web3.js与geth交互使用websocket方式,
版本:1.1.0-beta.22
测试通过并已成功在生产环境运行
1.启动geth服务器
geth --datadir /path/to/datadir/ --rpc --rpcapi db,eth,net,personal,web3 --ws --wsapi db,eth,net,personal,web3 --wsorigins=*
2.web3.js连接geth服务器
2.1首先使用合约部署后得到的json文件
connect.js
exports.getWeb3AndContract = (name) => {
const Web3 = require("web3");
const fs = require("fs");
var address = "contract address";//合约地址,发布合约后得到的地址
var contractFileContent = JSON.parse(fs.readFileSync("path/to/contract.json"));
var web3 = new Web3();
web3.setProvider(new Web3.providers.WebsocketProvider("ws://localhost:8546"));
var contract = new web3.eth.Contract(contractFileContent.abi, address);
return {"web3":web3, "contract":contract};
}
2.2编写合约方法、合约事件
method.js
exports.RollLottery = function (contract, web3, taskGuid) {
web3.eth.getCoinbase().then((resp) => {
console.log("get current gas price");
web3.eth.getGasPrice((err, res) => { //获取当前的gasPrice
var currentGasPrice = 0;
if (err === null) {
console.log("current gas price is: " + res);
currentGasPrice = res * 5;
}
console.log("[RollLottery]");
contract.methods.RollLottery(taskGuid) //taskGuid,你的执行参数,注意数据类型必须和合约内对应方法的参数类型一致,否则会发生错误
//.send({from:resp,value:web3.utils.toWei(payNumber, 'ether'), gas:150000})
.send({from:resp,value:0, gasPrice:currentGasPrice,gas:150000})
.once('transactionHash', (hash)=>{
//当合约正确执行后,这里会返回合约执行后生成的hash值
console.log('once transactionHash: ' + hash);
})
.once('receipt', (receipt)=>{
//console.log("once receipt: " + receipt);
})
.on('confirmation', (confNumber, receipt)=>{
//当合约执行发出的区块被矿工挖出并确认时,这里会有返回值
//console.log("on confirmation: " + confNumber);
//console.log("on confirmation:");
//console.log(receipt);
})
.on('error', (error)=>{
//合约执行失败,这里会有返回值
console.log('on error: ' + error);
})
.then(function(result, error){
//错误发生时的异常捕获
// console.log("error:");
// console.log(error);
// console.log("result:");
// console.log(result);
});
}).then((ex) => {
//获取当前gasPrice的错误异常捕获
console.log("ge current gas price error: " + ex);
});
}).catch((err)=>{console.log('getCoinbase error: ' + err);});
}
watch.js
exports.LotteryLogRandNumberBC = (web3, contract) => {
var _this = this;
contract.events.LogRandNumberBC({fromBlock:"latest", toBlock:"latest"})
.on('data', (event) => {
//event.returnValues将会是一个json对象,里面包含合约中事件返回值,注意,键名和合约中的变量名称完全一致。
console.log("[(Lottery)LogRandNumberBC Event] on data event: (returnValues)");
console.log(event.returnValues);
var taskGuid = event.returnValues.taskID;
var winNumber = event.returnValues.randomNum;
var txHash = event.transactionHash;
//todo something.
})
.on('changed', (event) => {
// console.log("[(Lottery)LogRandNumberBC Event] on changed event:");
// console.log(event);
})
.on('error', (error) => {
console.log("[(Lottery)LogRandNumberBC Event] on error:");
console.log(error);
});
return false;
};
2.3调用合约方法
lottery_server.js
//引入connect.js
const web3AndContract = require("connect");
//引入合约方法
const Methods = require("method");
//初始化连接
var lottery = web3AndContract.getWeb3AndContract("lottery");
//调用合约方法
blackJackAllMethods.RollLottery(lottery.contract, lottery.web3, taskGuid);
执行合约方法部分数据返回:
2.4开始监听合约事件
lottery_watcher.js
//引入connect.js
const web3AndContract = require("connect");
//引入合约事件
const lotteryAllWatchers = require("watch");
//初始化合约事件
var lottery = web3AndContract.getWeb3AndContract("lottery");
//调用合约事件,开始监听
lotteryAllWatchers.LotteryLogRandNumberBC(lottery.web3, lottery.contract);
监听合约事件部分数据返回:
注意:执行监听任务时,脚本将处于等待接收消息状态,建议使用守护进程方式以后台形式运行。
3.部分合约代码(solidity)
pragma solidity ^0.4.2;
contract Lottery {
/*
* checks only owner address is calling
*/
modifier onlyOwner
{
require(msg.sender == owner);
_;
}
/*
* game vars
*/
address public owner;
uint private randomNumber; //上一次的randomNumber会参与到下一次的随机数产生
/*
* events
*/
event LogRandNumberBC(uint64 taskID,uint16 randomNum); //这里是event事件定义,当事件执行后,"taskID、randomNum"数据将会被返回
/*
* init
*/
constructor() public {
owner = msg.sender;
}
function RollLottery(uint64 taskID) public
onlyOwner
{
uint16 randResult;
randomNumber = uint(keccak256(randomNumber,taskID,block.difficulty)) * uint(blockhash(block.number - 1));
randResult = uint16(randomNumber % 1000);
emit LogRandNumberBC(taskID,randResult);
}
function ()
public payable
{
return;
}
/* only owner address can set owner address */
function ownerChangeOwner(address newOwner) public
onlyOwner
{
owner = newOwner;
}
/* only owner address can suicide - emergency */
function ownerkill() public
onlyOwner
{
selfdestruct(owner);
}
}
4.在区块链服务器上查看合约运行情况
以太坊区块链有两个环境地址:一个测试地址,一个正式地址
- 测试地址:
https://ropsten.etherscan.io,访问https://ropsten.etherscan.io/tx/你的方法或事件hash,可以查询结果
- 正式地址:
https://etherscan.io ,访问https://etherscan.io/tx/你的方法或事件hash,可以查询结果
5.更多web3.js文档
https://web3js.readthedocs.io/en/1.0/web3-eth-contract.html