Web3 Javascript Events & Logs API
在Blockchain世界里,每一笔交易(transaction)都必须等待矿工将资料写入block后,交易才能算真正完成。Ethereum提供了Evernts&Logs机制,让使用者或者其他contract可以藉由追踪Events&Logs来确认事件是否完成。可是说Events&Logs是contract之间或contract与Dapp的一道桥梁。当我们跟contract互动发生的事件称之为Event,而contract将事件写入到日志中称之为Log,日志一样会被纪录在block之中来供人查阅。
block除了纪录contract状态之外也会纪录Logs
Event&Logs用途
Events&Logs主要的用途有以下三种:
Receive data from contracts
Asynchronous Notifications
Cheap data storage
Receive data for transaction
当对contract的function发起sendTransaction呼叫时,会回传transaction hash。必须等到矿工把这次的transaction写入block中,contract的状态才会改变,呼叫contract的动作才算真正完成。我们可以利用event的机制来帮助我们得知什么时候contract的状态改变并获得改变后的值。
Asynchronous Notifications
利用Events&Logs机制,可以用来监听contract的状态,并且可以根据特定的情形触发特定的操作。例如当收到买家转来的款项,通知卖家把货寄出。
卖家可以利用追踪event的方式判断顾客是否付款
Cheap data for transaction
EventS&Logs可以拿来当作比较便宜的储存空间,像是存放加密的客户身份(Encrypted customer identity)。因为储存log data每一byte只需要花费8 gas。contract data则每一byte需要625 gas(20000 Gas/32-byte)。资料存放log中相较contract算是比较便宜。有一点要特别注意,虽然存放在log比较便宜,但contract却无法直接存取log中的资料。
Web3.js Events&Log API
在Web3.js主要有两种途径可以获得contract log,分别是Filter Instance和Contract Event Instance。这两种途径都分别提供的get()和watch()的功能。使用下方contract event来介绍实际该怎么使用Web3.js Events&Logs API
event NumberSetEvent(address indexed caller, bytes32 indexed oldNum, bytes32 indexed newNum)
当有人去修改contract变数值时,NumberSetEvent会将修改人的帐户地址(address)和原本contract变数值(oldNum)跟要修改的值(newNum)纪录到Log中。
Filter Instance Get/Watch Log
在建立Filter Instance之前我们必须要先设定一些参数。建立一个JSOM object里面存放Log的相关讯息。
fromBlock: 从哪一个block
toBlock: 到那一个block结束
address: contract address
topics: 指名你想要读取哪一个Log
topics是一个Array,其中第一个值是event的signature,是将event hash过后所得的值。存放在block中纪录的就是event hash。第二、三和四个值分别对应event的第一(address)、二(oldNum)和三(newNum)参数。这边可以指定要取得特定值的log,例如对应newNum第四个值写成
0x0000000000000000000000000000000000000000000000000000000000000005
代表只拿newNum等于5的log。null代表不指定。
function getOptionObject(){
var options = {
"fromBlock": "0", // from block
"toBlock": "latest", // to block
"address": address, // contract address
"topics": [
web3. sha3(NumberSetEvent('address,bytes32,bytes32)'),
null, // specific caller value
null, // specific oldNum
null // specific newNum
]
};
return options;
}
使用web3.eth.filter来生成filter instance,参数就是刚刚建好的JSON object(options)。使用filter instance get()就可以在callback function拿到回传的log。以我们范例还来说就是拿从第一个到最后一个block中所有的log。回传会是一个array。
/* Get contract log data from filter instance*/
function getFilterEvents(){
var options = getOptionObject();
var filterGet = web3.eth.filter(options);
filterGet.get(function(error, result){
if(error) {
// error handle
} else {
for(var i = 0; i < result.length ; i++){
// print every log data
console.log(result[i]);
}
}
});
}
Watch顾名思义就是监控,当我们使用filter instance的watch()便会开始监控contract event,一旦有变动便会呼叫callback function执行对应的动作。若想要停止监控只要呼叫stopWatching()即可。
/* Watch contract log by filter instance */
function startWatchFilterEvents(){
var options = getOptionObject();
filterWatch = web3.eth.filter(options);
filterWatch.watch(function(error, result){
if(error){
/ / error handle
} else {
// print watch log
console.log(result);
}
});
}/* Stop watch contract log /*
filterWatch.stopWatching();
Contract Event Instance Get/Watch Log
除了Web3的Filter Instance之外我们还可以利用Web3 Contract Event Instance来取得log。先利用contract abi和contract address来建立contract instance。需要建立contract event instance必须提供两个参数,分别是:
indexedEventValues: 指定block等相关讯息(fromBlock, toBlock,…)。
additionFilterOptions: 指定要获取的event条件,类似Filter options参数的topic。只不过它不需要event signature。写法可以参考下方范例。
当indexedEventValues和additionFilterOptions都准备好,就可以利用contract instance来建立contract event instance。方式如下:
contractInstance.EVENT_NAME(
indexedEventValues, additionalFilterOptions);
EVENT_NAME就是event的名字,以范例来说就是NumberSetEvent。
function createContractEventInstance(){
var contract = web3.eth.contract(abi);
var contractInstance = contract.at(address);
var additionalFilterOptions = {
"fromBlock": "0",
"toBlock": "latest"
}; var indexedEventValues = {
"newNum": "0x0000000000000000000000000000000000000000000000000000000000000005"
}; // contractInstance.EVENT_NAME, NumberSetEvent is EVENT_NAME
return contractInstance.NumberSetEvent(
indexedEventValues, additionalFilterOptions);
}
生成contract event instance后,就可以使用get()和watch()来获取log资讯。使用方法基本上跟Filter Instance获取log方式相同。
/* Get contract log from contract event instance */
function getContractEvents() {
var event = createContractEventInstance();
event.get(function(error, result){
if(error){
console.log("Get event error:", error);
} else {
for(var i = 0; i < result.length ; i++){
console.log(result[i]);
}
}
});
}
/* Watch contract log by contract event instance */
function startWatchContractEvents() {
var contractEvent = createContractEventInstance();
contractEvent.watch(function(error, result){
if(error){
console.log("Get event error:", error);
} else {
console.log(result);
}
});
}/* Stop watching */
contractEvent.stopWatching()
结尾
这边谈论到Ethereum Events&Logs机制。主要聚焦在Event&Logs是什么东西和Web3.js该如何去使用它。因为还没有学习到smart contract的编写,所以有些东西打算保留到那时再提。到这里算是把个人觉得Web3.js一些比较常见的基础操作都稍微介绍过一遍。以上若有发现错误的地方,或者我的观念有误,拜托各位大大不吝啬给于纠正。
本文链接地址:https://www.wwsww.cn/btbjiaoxue/6248.html 郑重声明:本文版权归原作者所有,转载文章仅为传播更多信息之目的,如作者信息标记有误,请第一时间联系我们修改或删除,多谢。
标签: