So far we have introduced three components focused on the purpose of "collecting data. The component we present here, Event Indexer, follows the same objective, but with a slightly different means. It subscribes to events issued on-chain and stores the confirmed event information in the component.
The Event Indexer specifies events issued from EVM-compatible blockchain contracts, and subscribes to and stores those events. It is possible to specify a block number to start subscribing to and collect all events issued in subsequent blocks. This component allows monitoring of the various actions that occur in the contract itself, which is difficult to collect with Snapshot Indexer. To learn more about Events in Ethereum, please see below.
https://ethereum.org/developers/docs/smart-contracts/anatomy#events-and-logs
Let's build an Event Indexer that subscribes to ERC-20's Transfer event, which is typical of smart contracts.
https://eips.ethereum.org/EIPS/eip-20#events
Completed Component Definition
Target the DAI of ERC20 token, Ethereum's stable coin, and build an Event Indexer that collects DAI transfers.
Prerequisite
The Chainsight CLI requires several tools and a csx
installation. Please refer to the following articles for this preliminary preparation.
https://dev.to/hide_yoshi/step-by-step-creating-an-evm-price-oracle-with-chainsight-469g
Create a project & add a manifest template
As before, build from an empty project; use csx new --no-samples
to create a template.
% csx new --no-samples event_indexer_pj
Feb 13 12:56:29.488 INFO Start creating new project 'event_indexer_pj'...
Feb 13 12:56:29.489 INFO Project 'event_indexer_pj' created successfully
Feb 13 12:56:29.489 INFO You can add components with:
cd event_indexer_pj && csx add
Then use csx add
to add the Event Indexer, selecting the event_indexer type.
% cd event_indexer_pj
% csx add
✔ Please input Component Name to add · dai_transfer_subscriber
✔ Please select Component Type to add · event_indexer
Feb 13 12:57:22.481 INFO Start creating new component 'dai_transfer_subscriber'...
Feb 13 12:57:22.484 INFO EventIndexer component 'dai_transfer_subscriber' added successfully
From here, we will update the manifest so that DAI Transfer Events can be collected. The fields to be configured are a bit similar to those in the Snapshot Indexer EVM. The datasource
field is important for setting the events to be subscribed to. Let's take a look at the generated manifest.
datasource:
id: '0000000000000000000000000000000000000000'
event:
identifier: EventIdentifier
interface: null
network:
rpc_url: https://polygon-mumbai.infura.io/v3/${INFURA_MUMBAI_RPC_URL_KEY}
chain_id: 80001
from: 37730337
contract_type: ERC-20
batch_size: null
The parameters that need to be modified this time are the id
, event
, network
and from
fields. Specify the blockchain network and its contract to be subscribed to in id
, network
, the RPC URL of the Ethereum blockchain, the chain ID, and the contract address of the DAI.
datasource:
id: 0x6B175474E89094C44Da98b954EedeAC495271d0F
event: ...
network:
rpc_url: https://polygon-mumbai.infura.io/v3/${INFURA_MUMBAI_RPC_URL_KEY}
chain_id: 80001
...
Specify the event to be retrieved in event, the name to identify the event, and the ABI of the contract. Obtain the ABI for ERC20, which will be called this time, from the link below and create interfaces/ERC20.json
.
https://etherscan.io/token/0x6b175474e89094c44da98b954eedeac495271d0f#code
Then from
specifies the block at the start of the subscription.
Finally, event
and from
should be specified as follows.
datasource:
id: ...
event:
identifier: Transfer
interface: ERC20.json
network: ...
from: 17660942
The final manifest is as follows
version: v1
metadata:
label: Dai Transfer Subscriber by Hands-on
type: event_indexer
description: 'Collect Transfer Event of DAI token. This is a sample of the components that will be built in the Hands-on article.'
tags:
datasource:
id: 0x6B175474E89094C44Da98b954EedeAC495271d0F
event:
identifier: Transfer
interface: ERC20.json
network:
rpc_url: https://eth-mainnet.g.alchemy.com/v2/${ALCHEMY_KEY}
chain_id: 1
from: 17660942
contract_type: ERC-20
batch_size: null
interval: 1800 # 30min
cycles: null
Generate a code & build a module
Let's generate the canister code with csx generate
. If you actually run this command, you will get the following output.
% csx generate
Feb 15 01:24:21.749 INFO Start code generation for project 'event_indexer_pj'
Feb 15 01:24:21.749 INFO Load env file: "./.env"
Feb 15 01:24:21.752 INFO [dai_transfer_subscriber] Start processing...
Feb 15 01:24:21.752 INFO [dai_transfer_subscriber] Interface file 'ERC20.json' copied from builtin interface
Feb 15 01:24:21.753 INFO [dai_transfer_subscriber] Generate interfaces (.did files) ...
Feb 15 01:24:23.007 INFO [dai_transfer_subscriber] Succeeded: Generate interfaces (.did files)
Feb 15 01:24:23.007 INFO Project 'event_indexer_pj' codes/resources generated successfully
There is no need to implement any additional logic in Event Indexer. The build process can be executed as is.
You can generate modules from code with csx build
. Let's run it.
% csx build
Feb 13 13:17:44.320 INFO Start building project 'event_indexer_pj'
Feb 13 13:17:44.320 INFO Load env file: "./.env"
Feb 13 13:17:44.321 INFO Start code generation for project 'event_indexer_pj'
Feb 13 13:17:44.321 INFO Load env file: "./.env"
Feb 13 13:17:44.321 INFO [dai_transfer_subscriber] Start processing...
Feb 13 13:17:44.321 INFO [dai_transfer_subscriber] Interface file 'ERC20.json' copied from builtin interface
Feb 13 13:17:44.389 INFO [dai_transfer_subscriber] Generate interfaces (.did files) ...
Feb 13 13:18:12.780 INFO [dai_transfer_subscriber] Succeeded: Generate interfaces (.did files)
Feb 13 13:18:12.780 INFO Project 'event_indexer_pj' codes/resources generated successfully
Feb 13 13:18:12.780 INFO Start building...
Feb 13 13:18:12.781 INFO Compile canisters...
Feb 13 13:18:51.182 INFO Succeeded: Compile canisters
Feb 13 13:18:51.182 INFO Shrink/Optimize modules...
Feb 13 13:18:51.304 INFO Succeeded: Shrink/Optimize modules
Feb 13 13:18:51.304 INFO Add metadata to modules...
Feb 13 13:18:51.416 INFO Succeeded: Add metadata to modules
Feb 13 13:19:14.065 INFO Project 'event_indexer_pj' built successfully
If you get logs like the above for this one as well, you are done. Finally, deploy and start the component!
Deploy a component
Deploy this component on the Chainsight Platform with csx deploy and csx exec as in previous hands-on sessions.
csx deploy --network ic --component dai_transfer_subscriber
csx exec --network ic --component dai_transfer_subscriber
When you run these, you should get the following logs.
% csx deploy && csx exec
Feb 13 13:19:15.970 INFO Checking environments...
Feb 13 13:19:15.970 INFO Running command: 'dfx ping http://127.0.0.1:4943'
Feb 13 13:19:16.033 INFO Suceeded: dfx ping http://127.0.0.1:4943
Feb 13 13:19:16.033 INFO Running command: 'dfx identity whoami'
Feb 13 13:19:16.093 INFO Suceeded: dfx identity whoami
Feb 13 13:19:16.093 INFO Running command: 'dfx identity get-principal'
Feb 13 13:19:16.167 INFO Suceeded: dfx identity get-principal
Feb 13 13:19:16.167 INFO Running command: 'dfx identity get-wallet'
Feb 13 13:19:20.479 INFO Suceeded: dfx identity get-wallet
Feb 13 13:19:20.479 INFO Checking environments finished successfully
Feb 13 13:19:20.479 INFO Start deploying project 'event_indexer_pj'...
Feb 13 13:19:20.480 INFO Running command: 'dfx canister create --all'
Feb 13 13:19:23.138 INFO Suceeded: dfx canister create --all
Feb 13 13:19:23.138 INFO Running command: 'dfx build --all'
Feb 13 13:19:23.402 INFO Suceeded: dfx build --all
Feb 13 13:19:23.402 INFO Running command: 'dfx canister install --all'
Feb 13 13:19:28.884 INFO Suceeded: dfx canister install --all
Feb 13 13:19:28.885 INFO Running command: 'dfx canister update-settings --add-controller 7fpuj-hqaaa-aaaal-acg7q-cai dai_transfer_subscriber'
Feb 13 13:19:31.795 INFO Suceeded: dfx canister update-settings --add-controller 7fpuj-hqaaa-aaaal-acg7q-cai dai_transfer_subscriber
Feb 13 13:19:31.981 INFO Current deployed status:
Canister Name: __Candid_UI
Canister Id: {"local": "b77ix-eeaaa-aaaaa-qaada-cai"}
Controllers: k245a-2cvyi-rcnzj-cpq6h-dcy7o-qrg4b-325bv-5c3om-jfceo-ikmjz-aqe
Module Hash: 0x934756863c010898a24345ce4842d173b3ea7639a8eb394a0d027a9423c70b5c
Canister Name: dai_transfer_subscriber
Canister Id: {"local": "bw4dl-smaaa-aaaaa-qaacq-cai"}
Controllers: 7fpuj-hqaaa-aaaal-acg7q-cai br5f7-7uaaa-aaaaa-qaaca-cai k245a-2cvyi-rcnzj-cpq6h-dcy7o-qrg4b-325bv-5c3om-jfceo-ikmjz-aqe
Module Hash: 0x80b8cbaa5c666cbd3dce384cf964d883828d78ac2ee2f2ffa1f9287b521499f8
Feb 13 13:19:32.030 INFO Execute canister processing...
Feb 13 13:19:32.030 INFO Load env file: "./.env"
Feb 13 13:19:32.030 INFO Start processing for commands generation...
Feb 13 13:19:32.031 INFO Script for Component "dai_transfer_subscriber" generated successfully
Feb 13 13:19:32.031 INFO Entrypoint Script generated successfully
Feb 13 13:19:32.031 INFO Start processing for commands execution...
Feb 13 13:19:32.031 INFO Run scripts to execute commands for deployed components
Feb 13 13:20:02.789 INFO Executed './scripts/entrypoint.sh' successfully
Feb 13 13:20:02.789 INFO Project "event_indexer_pj" canisters executed successfully
The deployment and operation start instruction is now complete! Now all you have to do is wait for the interval of the automatic execution and you can refer to the data.
Event Indexer has the following interface to retrieve data. Try using these to call components.
events_from_to : (nat64, nat64) -> (vec record { nat64; vec Transfer }) query;
events_latest_n : (nat64) -> (vec record { nat64; vec Transfer }) query;
get_last_indexed : () -> (nat64) query;
This concludes our hands-on with Event Indexer. We will continue to create and publish new hands-on sessions in the future, so please look forward to them!
Written by Megared@Chainsight