Skip to the content.

ette

EVM-based Blockchain Indexer, with historical data query & real-time notification support 😎

Deploy your ette instance today

banner

Table of Contents

Inspiration 🤔

I was looking for one tool which will be able to keep itself in sync with latest happenings on EVM based blockchain i.e. index blockchain data, while exposing REST & GraphQL API for querying blockchain data with various filters. That tool will also expose real time notification functionalities over websocket, when subscribed to topics.

It’s not that I was unable find any solution, but wasn’t fully satisfied with those, so I decided to write ette, which will do following

And that’s ette

Prerequisite 👍

running_ette

Make sure you’ve pgcrypto extension enabled on PostgreSQL Database.

Check existing extensions using : \dx

Create extension using : create extension pgcrypto;

Note : Redis v6.0.6 is required

Note : Setting password in Redis instance has been made optional from now on, though it’s recommended.

Installation 🛠

git clone git@github.com:username/ette.git
cd ette
RPCUrl=https://<domain-name>
WebsocketUrl=wss://<domain-name>
PORT=7000
DB_USER=user
DB_PASSWORD=password
DB_HOST=x.x.x.x
DB_PORT=5432
DB_NAME=ette
RedisConnection=tcp
RedisAddress=x.x.x.x:6379
RedisPassword=password
Domain=localhost
Production=yes
EtteMode=3
EtteGraphQLPlayGround=yes
ConcurrencyFactor=5
BlockConfirmations=200
BlockRange=1000
TimeRange=21600
SnapshotFile=snapshot.bin

Quick Tip : Setting deliveryCount is fully upto you. Please consider VM specifications before doing so.

{
    "plans": [
        {
            "name": "TIER 1",
            "deliveryCount": 50000
        },
        {
            "name": "TIER 2",
            "deliveryCount": 100000
        },
        {
            "name": "TIER 3",
            "deliveryCount": 500000
        },
        {
            "name": "TIER 4",
            "deliveryCount": 750000
        },
        {
            "name": "TIER 5",
            "deliveryCount": 1000000
        }
    ]
}
make build
./ette

# or directly run `ette` using 👇, which will first build, then run
make run
curl -s localhost:7000/v1/synced | jq
{
  "elapsed": "3m2.487237s",
  "eta": "87h51m38s",
  "processed": 4242,
  "synced": "0.35 %"
}
curl -s localhost:7000/v1/stat | jq

Production deployment of ette using systemd

Here’s a systemd unit file which you can create in /etc/systemd/system.

sudo touch /etc/systemd/system/ette.service # first do it

Now you can paste 👇 content in unit file, given that you’ve cloned ette in $HOME.

[Unit]
Description=ette - EVM Blockchain Indexer

[Service]
User=ubuntu
WorkingDirectory=/home/ubuntu/ette
ExecStart=/home/ubuntu/ette/ette
Restart=on-failure
RestartSec=10s

[Install]
WantedBy=multi-user.target

Time to load systemd.

sudo systemctl daemon-reload

Now you can enable ette, so that it can be automatically started after system boot up.

sudo systemctl enable ette.service

Finally you can start ette.

sudo systemctl start ette.service

You can also stop, running ette instance.

sudo systemctl stop ette.service

Restart an instance.

sudo systemctl restart ette.service

All logs ette produces can be inspected using 👇

sudo journalctl -u ette.service # oldest to newest
sudo journalctl -u ette.service --reverse # opposite of 👆

Latest log can be followed

sudo journalctl -u ette.service -f

Use Cases 🤯

ette is supposed to be deployed by anyone, interested in running a historical data query & real-time notification service for EVM-based blockchain(s).

All client requests are by default rate limited ( 50k requests/ day ). This rate limit is enforced on all APIKey(s) created by any single Ethereum Address. You can create multiple APIKey(s) from your account & accumulated requests made from those keys to be considered before dropping your requests.

If you need more requests per day, you can always asked your ette administrator to manually increase that from database table. [ Risky operation, needs to be done carefully. This is not recommended. ]

More features coming here, soon

Management using webUI 🖥

ette has one minimalistic webUI for generating & managing APIKey(s). It doesn’t have any password based login mechanism. You need to have Metamask browser plugin installed for logging into ette management webUI.

Once you’ve started ette on your machine, open browser & head to http://localhost:7000/v1/login.

You’ll be greeted with 👇

ui

Assuming you’ve Metamask browser plugin installed, you can click Login & you’ll be asked to sign a message of specific format, which will be validated by ette.

ui

Once logged in, you can find out all APIKey(s) created by you.

ui

If you’ve not any APIKey(s) created yet, go ahead & click Create new app. Again you’ll be asked to sign a message of specific format.

ui

And you’ll see new APIKey on your screen.

ui

You can create any number of APIKey(s), but rate limiting to be applied on aggregated requests from all those APIKey(s).

Now go ahead & use APIKey in header of historical data query requests/ payload of real-time notification subscription/ unsubscription request.

Double clicking on created APIKey toggles its enabled state, which is represented visually. 👇

ui

Enabled Text Color
Yes Green
No Red

Quick Tip: As you can create any number of APIKey(s) from one Ethereum address, if you feel any of those has been exposed, disabling those ensures all requests accompanied with those APIKey(s) to be dropped, by ette

Read further for usage examples.

Usage 🦾

ette exposes REST & GraphQL API for querying historical block, transaction & event related data. It can also play role of real time notification engine, when subscribed to supported topics.

All historical data query requests need to be strictly accompanied with valid APIKey as request header param 🤖

Historical Block Data ( REST API ) 🤩

You can query historical block data with various combination of query string params. 👇 is a comprehensive guide for consuming block data.

Path : /v1/block

Example code snippet can be found here

Query Params Method Description
hash=0x...&tx=yes GET Fetch all transactions present in a block, when block hash is known
number=1&tx=yes GET Fetch all transactions present in a block, when block number is known
hash=0x... GET Fetch block by hash
number=1 GET Fetch block by number
fromBlock=1&toBlock=10 GET Fetch blocks by block number range ( max 10 at a time )
fromTime=1604975929&toTime=1604975988 GET Fetch blocks by unix timestamp range ( max 60 seconds timespan )

Historical Transaction Data ( REST API ) 😎

It’s possible to query historical transactions data with various combination of query string params, where URL path is 👇

Path : /v1/transaction

Example code snippet can be found here

Query Params Method Description
hash=0x... GET Fetch transaction by txHash
nonce=1&fromAccount=0x... GET Fetch transaction, when tx sender’s address & account nonce are known
fromBlock=1&toBlock=10&deployer=0x... GET Find out what contracts are created by certain account within given block number range ( max 100 blocks )
fromTime=1604975929&toTime=1604975988&deployer=0x... GET Find out what contracts are created by certain account within given timestamp range ( max 600 seconds of timespan )
fromBlock=1&toBlock=100&fromAccount=0x...&toAccount=0x... GET Given block number range ( max 100 at a time ) & a pair of accounts, can find out all tx performed between that pair, where from & to fields are fixed
fromTime=1604975929&toTime=1604975988&fromAccount=0x...&toAccount=0x... GET Given time stamp range ( max 600 seconds of timespan ) & a pair of accounts, can find out all tx performed between that pair, where from & to fields are fixed
fromBlock=1&toBlock=100&fromAccount=0x... GET Given block number range ( max 100 at a time ) & an account, can find out all tx performed from that account
fromTime=1604975929&toTime=1604975988&fromAccount=0x... GET Given time stamp range ( max 600 seconds of span ) & an account, can find out all tx performed from that account
fromBlock=1&toBlock=100&toAccount=0x... GET Given block number range ( max 100 at a time ) & an account, can find out all tx where target was this address
fromTime=1604975929&toTime=1604975988&toAccount=0x... GET Given time stamp range ( max 600 seconds of span ) & an account, can find out all tx where target was this address

Historical Event Data ( REST API ) 🧐

ette lets you query historical event data, emitted by smart contracts, by combination of query string params.

Path : /v1/event

Query Params Method Description
blockHash=0x... GET Given blockhash, retrieves all events emitted by tx(s) present in block
blockHash=0x...&logIndex=1 GET Given blockhash and log index in block, attempts to retrieve associated event
blockNumber=123456&logIndex=2 GET Given block number and log index in block, attempts to retrieve associated event
txHash=0x... GET Given txhash, retrieves all events emitted during execution of this transaction
count=50&contract=0x... GET Returns last x ( <=50 ) events emitted by this contract
fromBlock=1&toBlock=10&contract=0x...&topic0=0x...&topic1=0x...&topic2=0x...&topic3=0x... GET Finding event(s) emitted from contract within given block range & also matching topic signatures {0, 1, 2, 3}
fromBlock=1&toBlock=10&contract=0x...&topic0=0x...&topic1=0x...&topic2=0x... GET Finding event(s) emitted from contract within given block range & also matching topic signatures {0, 1, 2}
fromBlock=1&toBlock=10&contract=0x...&topic0=0x...&topic1=0x... GET Finding event(s) emitted from contract within given block range & also matching topic signatures {0, 1}
fromBlock=1&toBlock=10&contract=0x...&topic0=0x... GET Finding event(s) emitted from contract within given block range & also matching topic signatures {0}
fromBlock=1&toBlock=10&contract=0x... GET Finding event(s) emitted from contract within given block range
fromTime=1604975929&toTime=1604975988&contract=0x...&topic0=0x...&topic1=0x...&topic2=0x...&topic3=0x... GET Finding event(s) emitted from contract within given time stamp range & also matching topic signatures {0, 1, 2, 3}
fromTime=1604975929&toTime=1604975988&contract=0x...&topic0=0x...&topic1=0x...&topic2=0x... GET Finding event(s) emitted from contract within given time stamp range & also matching topic signatures {0, 1, 2}
fromTime=1604975929&toTime=1604975988&contract=0x...&topic0=0x...&topic1=0x... GET Finding event(s) emitted from contract within given time stamp range & also matching topic signatures {0, 1}
fromTime=1604975929&toTime=1604975988&contract=0x...&topic0=0x... GET Finding event(s) emitted from contract within given time stamp range & also matching topic signatures {0}
fromTime=1604975929&toTime=1604975988&contract=0x... GET Finding event(s) emitted from contract within given time stamp range

Historical Block Data ( GraphQL API ) 🤩

You can query block data using GraphQL API.

Path: /v1/graphql

Method: POST

type Query {
    blockByHash(hash: String!): Block!
    blockByNumber(number: String!): Block!
    blocksByNumberRange(from: String!, to: String!): [Block!]!
    blocksByTimeRange(from: String!, to: String!): [Block!]!
}

Response will be of type 👇

type Block {
  hash: String!
  number: String!
  time: String!
  parentHash: String!
  difficulty: String!
  gasUsed: String!
  gasLimit: String!
  nonce: String!
  miner: String!
  size: Float!
  txRootHash: String!
  receiptRootHash: String!
}
Method Parameters Possible use case
blockByHash hash: String! When you know block hash & want to get whole block data back
blockByNumber number: String! When you know block number & want to get whole block data back
blocksByNumberRange from: String!, to: String! When you’ve a block number range & want to get all blocks in that range, in a single call
blocksByTimeRange from: String!, to: String! When you’ve unix timestamp range & want to get all blocks in that range, in a single call

Historical Transaction Data ( GraphQL API ) 🤩

You can query transaction data from ette, using following GraphQL methods.

Path: /v1/graphql

Method: POST

type Query {
    transaction(hash: String!): Transaction!
  
    transactionCountByBlockHash(hash: String!): Int!
    transactionsByBlockHash(hash: String!): [Transaction!]!
  
    transactionCountByBlockNumber(number: String!): Int!
    transactionsByBlockNumber(number: String!): [Transaction!]!
  
    transactionCountFromAccountByNumberRange(account: String!, from: String!, to: String!): Int!
    transactionsFromAccountByNumberRange(account: String!, from: String!, to: String!): [Transaction!]!
  
    transactionCountFromAccountByTimeRange(account: String!, from: String!, to: String!): Int!
    transactionsFromAccountByTimeRange(account: String!, from: String!, to: String!): [Transaction!]!
  
    transactionCountToAccountByNumberRange(account: String!, from: String!, to: String!): Int!
    transactionsToAccountByNumberRange(account: String!, from: String!, to: String!): [Transaction!]!

    transactionCountToAccountByTimeRange(account: String!, from: String!, to: String!): Int!
    transactionsToAccountByTimeRange(account: String!, from: String!, to: String!): [Transaction!]!

    transactionCountBetweenAccountsByNumberRange(fromAccount: String!, toAccount: String!, from: String!, to: String!): Int!
    transactionsBetweenAccountsByNumberRange(fromAccount: String!, toAccount: String!, from: String!, to: String!): [Transaction!]!

    transactionCountBetweenAccountsByTimeRange(fromAccount: String!, toAccount: String!, from: String!, to: String!): Int!
    transactionsBetweenAccountsByTimeRange(fromAccount: String!, toAccount: String!, from: String!, to: String!): [Transaction!]!

    contractsCreatedFromAccountByNumberRange(account: String!, from: String!, to: String!): [Transaction!]!
    contractsCreatedFromAccountByTimeRange(account: String!, from: String!, to: String!): [Transaction!]!
    transactionFromAccountWithNonce(account: String!, nonce: String!): Transaction!
}

Response will be of type 👇

type Transaction {
  hash: String!
  from: String!
  to: String!
  contract: String!
  value: String!
  data: String!
  gas: String!
  gasPrice: String!
  cost: String!
  nonce: String!
  state: String!
  blockHash: String!
}
Method Parameters Possible use case
transaction hash: String! When you know txHash & want to get that tx data
transactionCountByBlockHash hash: String! When you know block hash & want to get count of tx(s) packed in that block
transactionsByBlockHash hash: String! When you know block hash & want to get all tx(s) packed in that block
transactionCountByBlockNumber number: String! When you know block number & want to get count of tx(s) packed in that block
transactionsByBlockNumber number: String! When you know block number & want to get all tx(s) packed in that block
transactionCountFromAccountByNumberRange account: String!, from: String!, to: String! When you know tx sender address, block number range & want to find out how many tx(s) were sent by this address in that certain block number range
transactionsFromAccountByNumberRange account: String!, from: String!, to: String! When you know tx sender address, block number range & want to find out all tx(s) that were sent by this address in that certain block number range
transactionCountFromAccountByTimeRange account: String!, from: String!, to: String! When you know tx sender address, unix time stamp range & want to find out how many tx(s) were sent by this address in that certain timespan
transactionsFromAccountByTimeRange account: String!, from: String!, to: String! When you know tx sender address, unix time stamp range & want to find out all tx(s) that were sent by this address in that certain timespan
transactionCountToAccountByNumberRange account: String!, from: String!, to: String! When you know tx receiver address, block number range & want to find out how many tx(s) were sent to this address in that certain block number range
transactionsToAccountByNumberRange account: String!, from: String!, to: String! When you know tx receiver address, block number range & want to find out all tx(s) that were sent to this address in that certain block number range
transactionCountToAccountByTimeRange account: String!, from: String!, to: String! When you know tx receiver address, unix time stamp range & want to find out how many tx(s) were sent to this address in that certain timespan
transactionsToAccountByTimeRange account: String!, from: String!, to: String! When you know tx receiver address, unix time stamp range & want to find out all tx(s) that were sent to this address in that certain timespan
transactionCountBetweenAccountsByNumberRange fromAccount: String!, toAccount: String!, from: String!, to: String! When you know tx sender & receiver addresses, block number range & want to find out how many tx(s) were sent from sender to receiver in that certain block number range
transactionsBetweenAccountsByNumberRange fromAccount: String!, toAccount: String!, from: String!, to: String! When you know tx sender & receiver addresses, block number range & want to find out all tx(s) that were sent from sender to receiver in that certain block number range
transactionCountBetweenAccountsByTimeRange fromAccount: String!, toAccount: String!, from: String!, to: String! When you know tx sender & receiver addresses, unix timestamp range & want to find out how many tx(s) were sent from sender to receiver in that certain timespan
transactionsBetweenAccountsByTimeRange fromAccount: String!, toAccount: String!, from: String!, to: String! When you know tx sender & receiver addresses, unix timestamp range & want to find out all tx(s) that were sent from sender to receiver in that certain timespan
contractsCreatedFromAccountByNumberRange account: String!, from: String!, to: String! When you know EOA’s ( externally owned account ) address & want to find out all contracts created by that account in block number range
contractsCreatedFromAccountByTimeRange account: String!, from: String!, to: String! When you know EOA’s ( externally owned account ) address & want to find out all contracts created by that account in certain time span
transactionFromAccountWithNonce account: String!, nonce: String! When you have EOA’s address & nonce value of it, you can pin point to that tx. This can be used to iterate through all tx(s) from this account, by updating nonce.

Historical Event Data ( GraphQL API ) 🤩

You can ask ette for event data using GraphQL API.

Path: /v1/graphql

Method: POST

type Query {
    eventsFromContractByNumberRange(contract: String!, from: String!, to: String!): [Event!]!
    eventsFromContractByTimeRange(contract: String!, from: String!, to: String!): [Event!]!
    eventsByBlockHash(hash: String!): [Event!]!
    eventsByTxHash(hash: String!): [Event!]!
    eventsFromContractWithTopicsByNumberRange(contract: String!, from: String!, to: String!, topics: [String!]!): [Event!]!
    eventsFromContractWithTopicsByTimeRange(contract: String!, from: String!, to: String!, topics: [String!]!): [Event!]!
    lastXEventsFromContract(contract: String!, x: Int!): [Event!]!
    eventByBlockHashAndLogIndex(hash: String!, index: String!): Event!
    eventByBlockNumberAndLogIndex(number: String!, index: String!): Event!
}

Response will be of type 👇

type Event {
  origin: String!
  index: String!
  topics: [String!]!
  data: String!
  txHash: String!
  blockHash: String!
}
Method Parameters Possible use case
eventsFromContractByNumberRange contract: String!, from: String!, to: String! When you’ve one contract address, block number range & you want to find out all events emitted by that contract in given block range
eventsFromContractByTimeRange contract: String!, from: String!, to: String! When you know contract address, unix time stamp range & you want to find out all events emitted by that contract in given timespan
eventsByBlockHash hash: String! When you’ve block hash & want to find out all events emitted in tx(s) packed in that block
eventsByTxHash hash: String! When you’ve txHash & want to find out all events emitted during execution of that tx
eventsFromContractWithTopicsByNumberRange contract: String!, from: String!, to: String!, topics: [String!]! When you’ve smart contract address, block number range & an ordered list of event log’s topic signature(s), you can find out all events emitted by that contract with specific signature(s) in block range
eventsFromContractWithTopicsByTimeRange contract: String!, from: String!, to: String!, topics: [String!]! When you’ve smart contract address, unix time stamp range & an ordered list of event log’s topic signature(s), you can find out all events emitted by that contract with specific signature(s) in given timespan
lastXEventsFromContract contract: String!, x: Int! When you know just contract address & want to find out last X events emitted by that contract [ Very useful sometimes 😅 ]
eventByBlockHashAndLogIndex hash: String!, index: String! When you know block hash, index of event log in block & want to get back specific event in that position
eventByBlockHashAndLogIndex number: String!, index: String! When you know block number, index of event log in block & want to get back specific event in that position

Browser based GraphQL Playground : /v1/graphql-playground 👇🤩

graphql_playground


Real time notification for mined blocks ⛏

pubsub-ette

For listening to blocks getting mined, connect to /v1/ws endpoint using websocket client library & once connected, you need to send subscription request with 👇 payload ( JSON encoded )

{
    "name": "block",
    "type": "subscribe",
    "apiKey": "0x..."
}

If everything goes fine, your subscription will be confirmed with 👇 response ( JSON encoded )

{
    "code": 1,
    "message": "Subscribed to `block`"
}

After that as long as your machine is reachable, ette will keep notifying you about new blocks getting mined in 👇 form

{
  "hash": "0x08f50b4795667528f6c0fdda31a0d270aae60dbe7bc4ea950ae1f71aaa01eabc",
  "number": 7015086,
  "time": 1605328635,
  "parentHash": "0x5ec0faff8b48e201e366a3f6c505eb274904e034c1565da2241f1327e9bad459",
  "difficulty": "6",
  "gasUsed": 78746,
  "gasLimit": 20000000,
  "nonce": 0,
  "miner": "0x0000000000000000000000000000000000000000",
  "size": 1044,
  "txRootHash": "0x088d6142b1d79803c851b1d839888b1e9f26c31e1266b4e221121f2cd8e85f86",
  "receiptRootHash": "0xca3949d52f113935ac08bae15e0816cd0472f01590f0fe0b65584bfb3aa324a6"
}

If you want to cancel subscription, consider sending 👇

{
    "name": "block",
    "type": "unsubscribe",
    "apiKey": "0x..."
}

You’ll receive 👇 response, confirming unsubscription

{
    "code": 1,
    "message": "Unsubscribed from `block`"
}

Sample code can be found here

Real time notification for transactions ⚡️

For listening to any transaction happening in network in real-time, send 👇 JSON encoded payload to /v1/ws

{
    "name": "transaction/<from-address>/<to-address>",
    "type": "subscribe",
    "apiKey": "0x..."
}

Here we’ve some examples :

{
    "name": "transaction/*/*",
    "type": "subscribe",
    "apiKey": "0x..."
}

Sample Code can be found here

{
    "name": "transaction/0x4774fEd3f2838f504006BE53155cA9cbDDEe9f0c/*",
    "type": "subscribe",
    "apiKey": "0x..."
}

Sample Code can be found here

{
    "name": "transaction/*/0x4774fEd3f2838f504006BE53155cA9cbDDEe9f0c",
    "type": "subscribe",
    "apiKey": "0x..."
}

Sample Code can be found here

{
    "name": "transaction/0xc9D50e0a571aDd06C7D5f1452DcE2F523FB711a1/0x4774fEd3f2838f504006BE53155cA9cbDDEe9f0c",
    "type": "subscribe",
    "apiKey": "0x..."
}

Sample Code can be found here

If everything goes fine, your subscription will be confirmed with 👇 response ( JSON encoded )

{
    "code": 1,
    "message": "Subscribed to `transaction`",
    "apiKey": "0x..."
}

After that as long as your machine is reachable, ette will keep notifying you about every transaction happening in 👇 form, where criterias matching

{
  "hash": "0x08cfda79bd68ad280c7786e5dd349ab81981c52ea5cdd8e31be0a4b54b976555",
  "from": "0xc9D50e0a571aDd06C7D5f1452DcE2F523FB711a1",
  "to": "0x4774fEd3f2838f504006BE53155cA9cbDDEe9f0c",
  "contract": "",
  "value": "",
  "data": "0x35086d290000000000000000000000000000000000000000000000000000000000000360",
  "gas": 200000,
  "gasPrice": "1000000000",
  "cost": "200000000000000",
  "nonce": 19899,
  "state": 1,
  "blockHash": "0xc29170d33141602a95b915c954c1068a380ef5169178eef2538beb6edb005810"
}

If you want to cancel subscription, consider sending 👇, while replacing <from-address> & <to-address> with specific addresses you used when subscribing.

{
    "name": "transaction/<from-address>/<to-address>",
    "type": "unsubscribe",
    "apiKey": "0x..."
}

You’ll receive 👇 response, confirming unsubscription

{
    "code": 1,
    "message": "Unsubscribed from `transaction`"
}

Real-time notification for events 📧

For listening to any events getting emitted by smart contracts deployed on network, you need to send 👇 JSON encoded payload to /v1/ws endpoint, after connecting over websocket

{
    "name": "event/<contract-address>/<topic-0-signature>/<topic-1-signature>/<topic-2-signature>/<topic-3-signature>",
    "type": "subscribe",
    "apiKey": "0x..."
}

Here we’ve some examples :

{
    "name": "event/*/*/*/*/*",
    "type": "subscribe",
    "apiKey": "0x..."
}
{
    "name": "event/0xcb3fA413B23b12E402Cfcd8FA120f983FB70d8E8/*/*/*/*",
    "type": "subscribe",
    "apiKey": "0x..."
}
{
    "name": "event/0xcb3fA413B23b12E402Cfcd8FA120f983FB70d8E8/0x2ab93f65628379309f36cb125e90d7c902454a545c4f8b8cb0794af75c24b807/*/*/*",
    "type": "subscribe",
    "apiKey": "0x..."
}
{
    "name": "event/*/0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef/*/*/*",
    "type": "subscribe",
    "apiKey": "0x..."
}

Sample code can be found here

If everything goes fine, your subscription will be confirmed with 👇 JSON encoded response

{
    "code": 1,
    "message": "Subscribed to `event`"
}

After that as long as your machine is reachable, ette will keep notifying you about every event emitted by smart contracts, to which you’ve subscribed to, in 👇 format

{
  "origin": "0x0000000000000000000000000000000000001010",
  "index": 3,
  "topics": [
    "0x4dfe1bbbcf077ddc3e01291eea2d5c70c2b422b415d95645b9adcfd678cb1d63",
    "0x0000000000000000000000000000000000000000000000000000000000001010",
    "0x0000000000000000000000004d31abd8533c00436b2145795cc4cef207c3364f",
    "0x00000000000000000000000042eefcda06ead475cde3731b8eb138e88cd0bac3"
  ],
  "data": "0x0000000000000000000000000000000000000000000000000000454b2247e2000000000000000000000000000000000000000000000000001a96ae0b49dfc60000000000000000000000000000000000000000000000003a0df005a45c3dd5dd0000000000000000000000000000000000000000000000001a9668c02797e40000000000000000000000000000000000000000000000003a0df04aef7e85b7dd",
  "txHash": "0xfdc5a29fdd57a53953a542f4c46b0ece5423227f26b1191e58d32973b4d81dc9",
  "blockHash": "0x08e9ac45e4041a4309c6f5dd42b0fc78e00ca0cb8603965465206b22a63d07fb"
}

If you want to cancel subscription, consider sending 👇, while replacing <contract-address>, <topic-{0,1,2,3}-signature> with specific values you used when subscribing.

{
    "name": "event/<contract-address>/<topic-0-signature>/<topic-1-signature>/<topic-2-signature>/<topic-3-signature>",
    "type": "unsubscribe",
    "apiKey": "0x..."
}

You’ll receive 👇 response, confirming unsubscription

{
    "code": 1,
    "message": "Unsubscribed from `event`"
}

Note: If graceful unsubscription not done, when ette finds client unreachable, it’ll remove client subscription

Take snapshot of existing data store ➡️

Assuming you’ve already a running instance of ette for some EVM compatible chain, you can always attempt to take snapshot of whole backing data store, so that if you need to spin up another instance of ette, you won’t require to sync whole chain data, rather you use this binary data file, which can be used by ette for restoring from snapshot data.

Setting EtteMode = 4, attempts to take snapshot of DB.

taking-snapshot

Restore data from snapshot ⬅️

Once you’ve snapshotted binary encoded data file, you can attempt to restore from this & rebuild whole data store, with out syncing whole chain data. EtteMode = 5, attempts to do 👇.

restoring-from-snapshot

Once that’s done, consider restarting ette in desired mode so that it can keep itself in sync with latest chain happenings.

More coming soon