これは何?
- web3.jsからether.js派になった@salvaがetherjsの使い方を雑にメモするよ
- イベントのとり方
- RLPエンコードされたEventデータをデコードするところまでやるよ
やること
- 適当なコトントラクトからイベントを取得
- イベント開始取得点のblockNumberを適当に指定
- RLPデコードしてイベントの中身を取り出す
コード例
// ethersライブラリの読み込み
import { ethers } from "ethers";
// RLP(ないしABIの)デコーダ
import { defaultAbiCoder } from 'ethers/utils/abi-coder';
// 適当に設定のこと
const address = "XXXX"
const abi = []
// イベント取得の開始点にしたいblockNumber
fromBlockNumber = 1000
// providerを適当に作るURLをhttp://localhost:8545のような形で与える
const provider = new ethers.providers.JsonRpcProvider(ethereumURL);
// イベントの取得開始点を設定
provider.resetEventsBlock(fromBlockNumber)
// contract Objectを作成
const contract = new ethers.Contract(address, abi, provider)
// contractオブジェクトからfilter関数を叩いてfilterを生成
const eventName = "SampleEvent"
const filter = contract.filters[eventName]()
// イベントデータのデコードに使うイベントのinterfaceオブジェクト
const eventInterface = contract.interface.events[eventName
contract.on(filter, (...args) => {
const arg1 = args[0]
const arg2 = args[1]
// eventオブジェクト
const event = args[args.length - 1]
const eventRLPData = event.data // RLPエンコードされたイベントデータ
const decodedEvent = defaultAbiCoder.decode(eventInterface.inputs, eventRLPData)
console.log(decodedEvent
})
Pros / Cons
- Pros
- ether.js + TypeScriptの方が型定義がしっかりしているので使いやすい
- 例えば末尾に示すようなABIの型定義などをつかってゴニョゴニョしたりするコードがweb3に比べるとシュッとかける
* Contractオブジェクトを生成するとRLPのデコードに必要なオブジェクトなどを同時に作ってくれるので、使いやすい感がある
- Cons
- 現行のバージョン(4.x) ではイベントのフィルターにblockNumberが使えない
おまけ
FuntionFragment, EventFrangmentのような型が定義されており、JSONに書かれたABIを読み込むときなどにうまく使えるので便利
import ethers from "ethers"
import { FunctionFragment, EventFragment } from "ethers/utils"
export interface ContractListConfig {
readonly contracts: ContractConfig[]
}
interface ContractConfig {
readonly name: string
readonly address: string
readonly deployedBlockNumber: number
readonly abi: (FunctionFragment|EventFragment)[] // ABIの配列の要素の型定義
}