上一篇我們提到如何監聽 Event,並從中取得 log 資訊,但如果要從交易的收據中取得 log 資訊該如何做呢?讓我們繼續看下去~
我們透過 ProviderService 中的 getReceipt(txHash: string)
來取得收據資訊,並看看 logs
中的資料:
會發現 data
是 hex 格式的,我們根本無法用肉眼判斷到底 log 寫了些什麼,那我們到底要怎麼樣才能夠轉換成我們看得懂的資訊呢?答案就是 web3.js 有提供解碼的功能讓我們進行解碼。
在解碼 log 之前,我們回頭看 logs
裡面的資料,會發現有一個 topics
的東西,這個在上一篇有稍微提到,但並沒有說明,因為我覺得在這裡做說明效果會比較好,所以原諒我前面沒有解釋
這個可以當作是log的索引,可能有多個 topic ,也可能只有一個,但不可能都沒有,因為 **第一個 topic 為 Event 經過雜湊運算後的hash值 ** ,而後面其他的 topic 都是 Event 中有 indexed
的參數,如果沒有特別設置 indexed
就不會有,而我們的 done
沒有特別設置。
我們將解碼的方法定義在 Web3Utils 中。先將 web3-eth-abi
引入:
import * as ABI from 'web3-eth-abi';
設計回傳的型別為 Observable
。由於解碼 log 需要使用到該 Event 的 ABI ,所以要從 Resume 的 ABI 找出事件名稱相符且類型為 event
的資料,如果沒有找到的話,就透過 rxjs
的 throwError
拋出錯誤;找到的話就依序將 Event 的 inputs
、 logs 中的 data
以及 topics
帶入 decodeLog()
中,並用 rxjs
的 of
來傳出資料:
import { Observable, throwError, of } from 'rxjs';
public static decodeLog(eventName: string, receipt: any): Observable<any> {
const abi = ResumeContract.abi.find(item => item.name === eventName && item.type === 'event');
if (!abi) {
return throwError(`Not found event: ${ eventName }`);
}
const inputs = abi.inputs;
const logs = receipt.logs;
return of(ABI.decodeLog(inputs, logs[0].data, logs[0].topics));
}
在 app.component.ts
中做測試:
constructor(private provider: ProviderService {
const tx = '0xb22815db37363b7695adabc536e3a45ec4e76d6837b7cdaaa4cdde955e27e232';
this.provider.getReceipt(tx).pipe(
mergeMap(receipt => Web3Utils.decodeLog('done', receipt))
).subscribe(
log => console.log(log),
err => console.error(err)
);
}
從開發人員工具看結果:
透過 web3.js 提供的解碼功能讓收據中的 log 資訊變得可讀,這個功能可以應用在觀看交易內容時,順帶把解碼後的 log 資訊呈現出來,十分好用的功能!
你好,最近重新實作(想將其改成自己所需的作品),但不知為何BN以及decodeLog這兩個會顯示錯誤
直接把您的原檔解壓縮一樣會發生上述情形
你能夠說明一下你的安裝步驟嗎?
我這邊重新跑一遍是沒有問題的,想了解一下會不會是安裝的過程有疏漏?
npm install -g @angular/cli
解壓縮檔案,而後進入其資料夾
npm install web3
npm install bootstrap
npm install @ng-bootstrap/ng-bootstrap
npm run patch-webpack
npm install @truffle/contract
這樣
發現了一個問題所在,我在前次安裝的時候,把web3安裝在前一個資料夾,所以程式碼搜尋不到
(就是我是在C槽下,ng新的專案,但install的時候還沒切入新的資料夾中)
問題已解決
有找出問題就好,加油!
我檔案結構是如下:
Resume folder
|-e2e
|-node_modules
|-plugins
|-src
|-truffle
但是,我跟你的程式去做,它仍然出現"Property ‘decodeLog’ does not exit on type typeof import",是否我安裝web3去了錯誤位置?
我在node_modules/web3-utils/types/index.d.ts,它是有export decodeLog。但是,我不明白我的程式怎樣會是找不到呢?
Thank you very much.
你好,看起來是新版的 web3 更改了作法,要改成下方這樣:
import { AbiCoder } from 'web3-eth-abi';
然後將其實例化:
private static ABI = new AbiCoder();
並在方法中調用:
this.ABI.decodeLog(inputs, logs[0].data, logs[0].topics);
感謝你的提醒!
當我在web3-utils.ts加入private static ABI = new AbiCoder();後去compile,它會出現"
Uncaught TypeError: web3_eth_abi__WEBPACK_IMPORTED_MODULE_4__.AbiCoder is not a constructor
ts web3-utils.ts:19"
private static ABI = new AbiCoder();是不是不是加入去web3-utils.ts?
thank you very much.
你好,我這邊用新版 web3 去編譯是可以過的。