mirror of
https://github.com/cerc-io/watcher-ts
synced 2024-11-19 20:36:19 +00:00
Merge pull request #288 from cerc-io/cleanup-readmes
Watcher docs updates
This commit is contained in:
commit
64a30b7a4d
15
.github/CONTRIBUTING.md
vendored
Normal file
15
.github/CONTRIBUTING.md
vendored
Normal file
@ -0,0 +1,15 @@
|
||||
# Contributing
|
||||
|
||||
To update versions in all packages run the following:
|
||||
|
||||
```bash
|
||||
yarn version:set <VERSION>
|
||||
yarn version:set-codegen <VERSION>
|
||||
```
|
||||
|
||||
Example:
|
||||
|
||||
```bash
|
||||
yarn version:set 0.2.20
|
||||
yarn version:set-codegen 0.2.20
|
||||
```
|
84
README.md
84
README.md
@ -1,58 +1,56 @@
|
||||
# watcher-ts
|
||||
|
||||
![Cute Panopticon](./docs/watchers-graphic.png)
|
||||
|
||||
Watchers make managing data in Dapp development as frictionless as possible. They do this by querying, transforming, and caching Ethereum state data cheaper and faster compared to existing solutions. This data also comes with evidence for generating cryptographic proofs to provide verification that the data is authentic. Public watchers are found in the [packages](/packages) directory.
|
||||
|
||||
Go [here](https://github.com/cerc-io/stack-orchestrator/tree/main/app/data/stacks/erc20) for a quick start demo of setting up the stack and deploying/using the erc20 watcher via the Laconic Stack Orchestrator.
|
||||
|
||||
|
||||
## Prerequisites
|
||||
|
||||
### User Mode
|
||||
|
||||
- `laconic-so` [Install](https://github.com/cerc-io/stack-orchestrator#setup)
|
||||
|
||||
The Laconic Stack Orchestrator provides all the tools to quickly get started with watchers.
|
||||
|
||||
### Developer Mode
|
||||
|
||||
- `yarn` [Install](https://yarnpkg.com/getting-started/install)
|
||||
- `postgres` [Install](https://www.postgresql.org/download/)
|
||||
|
||||
You'll need the above if you plan on digging into this repo, writing your own watchers, or experimenting with watchers not currently supported by Stack Orchestrator. See [CONTRIBUTING.md](.github/CONTRIBUTING.md) for more information.
|
||||
|
||||
## Services
|
||||
|
||||
The default configuration files used by watchers assume the following services are setup and running on localhost:
|
||||
|
||||
* [cerc-io/go-ethereum](https://github.com/cerc-io/go-ethereum/tree/v1.10.25-statediff-v4) on port 8545
|
||||
* [cerc-io/ipld-eth-server](https://github.com/cerc-io/ipld-eth-server) with native GQL API enabled, on port 8082
|
||||
* [cerc-io/ipld-eth-db](https://github.com/cerc-io/ipld-eth-db) to populate the postgres database for `ipld-eth-server`
|
||||
|
||||
These services are dockerized by the Laconic Stack Orchestrator (`laconic-so`). [Use it](https://github.com/cerc-io/stack-orchestrator) unless you plan on digging into those codebases. For more information on setting up these services up by hand, see [here](/docs/README.md)
|
||||
|
||||
## Setup
|
||||
|
||||
This project uses [yarn workspaces](https://classic.yarnpkg.com/en/docs/workspaces/).
|
||||
From the root of this repository, run:
|
||||
|
||||
Install packages (Node.JS v16.13.1):
|
||||
`yarn && yarn build`
|
||||
|
||||
```bash
|
||||
yarn
|
||||
```
|
||||
to download dependencies and build all the watchers.
|
||||
|
||||
Build packages:
|
||||
Orient yourself with the available CLI commands [here](docs/cli.md) and in some cases, watchers have in-depth demos (e.g. [mobymask](/packages/mobymask-watcher))
|
||||
|
||||
```bash
|
||||
yarn build
|
||||
```
|
||||
|
||||
[//]: # (TODO: ## Generating Watchers)
|
||||
|
||||
## Tests
|
||||
|
||||
* [graph-node](./packages/graph-node/README.md)
|
||||
|
||||
## Services
|
||||
## Further Reading
|
||||
|
||||
The default config files used by the watchers assume the following services are setup and running on localhost:
|
||||
[//]: # (TODO: link to docs.laconic.com when ready)
|
||||
|
||||
* `vulcanize/go-ethereum` on port 8545
|
||||
* `vulcanize/ipld-eth-server` with native GQL API enabled, on port 8082
|
||||
|
||||
### Note
|
||||
|
||||
* In `vulcanize/ipld-eth-server`, add the following statement to `[ethereum]` section in `environments/config.toml`:
|
||||
|
||||
`chainConfig = "./chain.json" # ETH_CHAIN_CONFIG`
|
||||
|
||||
## Watchers
|
||||
|
||||
* [eden-watcher](./packages/eden-watcher/README.md)
|
||||
* [erc20-watcher](./packages/erc20-watcher/README.md)
|
||||
* [erc721-watcher](./packages/erc721-watcher/README.md)
|
||||
* [graph-test-watcher](./packages/graph-test-watcher/README.md)
|
||||
* [mobymask-watcher](./packages/mobymask-watcher/README.md)
|
||||
|
||||
## Development
|
||||
|
||||
* To update versions in all packages run the following:
|
||||
|
||||
```bash
|
||||
yarn version:set <VERSION>
|
||||
yarn version:set-codegen <VERSION>
|
||||
```
|
||||
|
||||
Example
|
||||
|
||||
```bash
|
||||
yarn version:set 0.2.20
|
||||
yarn version:set-codegen 0.2.20
|
||||
```
|
||||
- [Watchers Blog Post](https://www.laconic.com/blog/laconic-watchers)
|
||||
|
85
docs/README.md
Normal file
85
docs/README.md
Normal file
@ -0,0 +1,85 @@
|
||||
# Watcher Documentation
|
||||
|
||||
This document is specifically focused on standing up a minimal core version of the Laconic Stack *without* using [Stack Orchestrator]( https://github.com/cerc-io/stack-orchestrator). If this is your first foray into the stack, start with Stack Orchestrator. To understand what is going on under the hood or to make contributions to this repo, this is a good place to start.
|
||||
|
||||
There are 3 main components to setting up an environment for running watchers:
|
||||
- core services
|
||||
- configure postgres
|
||||
- edit config file
|
||||
|
||||
After which you should be able to navigate to the `README.md` of any watcher and run through its demo using `yarn`. The common `yarn` CLI commands for watchers are documented [here](../cli.md).
|
||||
|
||||
## Core services
|
||||
|
||||
The following core services should be setup and running on localhost:
|
||||
|
||||
* `cerc-io/go-ethereum` [v1.10.26-statediff-4.2.2-alpha](https://github.com/cerc-io/go-ethereum/releases/tag/v1.10.26-statediff-4.2.2-alpha)
|
||||
on port 8545
|
||||
|
||||
* `cerc-io/ipld-eth-server` [v4.2.2-alpha](https://github.com/cerc-io/ipld-eth-server/releases/tag/v4.2.2-alpha) with native GQL API enabled, on port 8082
|
||||
|
||||
* `cerc-io/ipld-eth-db` [v4.2.2-alpha](https://github.com/cerc-io/ipld-eth-db/releases/tag/v4.2.2-alpha) is the postgres schema required for `ipld-eth-server`
|
||||
|
||||
## Setup Postgres
|
||||
|
||||
In this example, we use the `erc20-watcher`; for another watcher substitute with its name.
|
||||
|
||||
Create a postgres database for the watcher:
|
||||
|
||||
```bash
|
||||
sudo su - postgres
|
||||
createdb erc20-watcher
|
||||
```
|
||||
|
||||
Create a postgres database for the job queue:
|
||||
|
||||
```
|
||||
sudo su - postgres
|
||||
createdb erc20-watcher-job-queue
|
||||
```
|
||||
|
||||
Enable the `pgcrypto` [extension](https://github.com/timgit/pg-boss/tree/master/docs#database-install) on the job queue database.
|
||||
|
||||
```
|
||||
postgres@tesla:~$ psql -U postgres -h localhost erc20-watcher-job-queue
|
||||
Password for user postgres:
|
||||
psql (12.7 (Ubuntu 12.7-1.pgdg18.04+1))
|
||||
SSL connection (protocol: TLSv1.3, cipher: TLS_AES_256_GCM_SHA384, bits: 256, compression: off)
|
||||
Type "help" for help.
|
||||
|
||||
erc20-watcher-job-queue=# CREATE EXTENSION pgcrypto;
|
||||
CREATE EXTENSION
|
||||
erc20-watcher-job-queue=# exit
|
||||
```
|
||||
|
||||
## Config File
|
||||
|
||||
In each watchers' directory is a config file: `packages/<watcher>/environments/local.toml`:
|
||||
|
||||
* Update the database connection settings.
|
||||
* Update the `upstream` config and provide the `ipld-eth-server` GraphQL API endpoint.
|
||||
* Select "active" vs. "lazy" watcher depending on its kind.
|
||||
|
||||
For example:
|
||||
```toml
|
||||
[server]
|
||||
kind = "active"
|
||||
|
||||
[database]
|
||||
type = "postgres"
|
||||
host = "localhost"
|
||||
port = 5432
|
||||
database = "erc20-watcher"
|
||||
username = "postgres"
|
||||
password = "postgres"
|
||||
|
||||
[jobQueue]
|
||||
dbConnectionString = "postgres://postgres:postgres@localhost/erc20-watcher-job-queue"
|
||||
|
||||
[upstream]
|
||||
[upstream.ethServer]
|
||||
gqlApiEndpoint = "http://127.0.0.1:8082/graphql"
|
||||
rpcProviderEndpoint = "http://127.0.0.1:8081"
|
||||
```
|
||||
|
||||
Now that your environment is setup, you can test run any watcher!
|
127
docs/cli.md
Normal file
127
docs/cli.md
Normal file
@ -0,0 +1,127 @@
|
||||
## Watcher CLI commands
|
||||
|
||||
Non-exhaustive list of (yarn) CLI commands available for watchers. Assumes you have an environment setup either [by hand](./README.md) or using [Stack Orchestrator](https://github.com/cerc-io/stack-orchestrator), and have built `yarn && yarn build` a specific watcher.
|
||||
|
||||
If the watcher is an `active` watcher, run the job-runner:
|
||||
|
||||
```bash
|
||||
yarn job-runner
|
||||
```
|
||||
|
||||
```
|
||||
# For development.
|
||||
yarn server:dev
|
||||
|
||||
# For specifying config file.
|
||||
yarn server -f environments/local.toml
|
||||
```
|
||||
|
||||
If the watcher is `lazy` omit the above step, then run the server:
|
||||
|
||||
```bash
|
||||
yarn server
|
||||
```
|
||||
|
||||
This will enable the GraphQL playground at: `http://localhost:<port>/graphql`
|
||||
|
||||
where `<port>` is set in the `environments/local.toml` of each watcher.
|
||||
|
||||
To watch a contract:
|
||||
|
||||
```bash
|
||||
yarn watch:contract --address <contract-address> --kind <contract-kind> --checkpoint <true | false> --starting-block <block-number>
|
||||
```
|
||||
|
||||
* `address`: Address or identifier of the contract to be watched.
|
||||
* `kind`: Kind of the contract.
|
||||
* `checkpoint`: Turn checkpointing on (`true` | `false`).
|
||||
* `starting-block`: Starting block for the contract (default: `1`).
|
||||
|
||||
Example:
|
||||
|
||||
Watch a contract with its address and checkpointing on:
|
||||
|
||||
```bash
|
||||
yarn watch:contract --address 0x1F78641644feB8b64642e833cE4AFE93DD6e7833 --kind ERC20 --checkpoint true
|
||||
```
|
||||
|
||||
To fill a block range:
|
||||
|
||||
```bash
|
||||
yarn fill --start-block <from-block> --end-block <to-block>
|
||||
```
|
||||
|
||||
* `start-block`: Block number to start filling from.
|
||||
* `end-block`: Block number till which to fill.
|
||||
|
||||
To create a checkpoint for a contract:
|
||||
|
||||
```bash
|
||||
yarn checkpoint create --address <contract-address> --block-hash <block-hash>
|
||||
```
|
||||
|
||||
* `address`: Address or identifier of the contract for which to create a checkpoint.
|
||||
* `block-hash`: Hash of a block (in the pruned region) at which to create the checkpoint (default: latest canonical block hash).
|
||||
|
||||
To verify a checkpoint:
|
||||
|
||||
```bash
|
||||
yarn checkpoint verify --cid <checkpoint-cid>
|
||||
```
|
||||
|
||||
* `cid`: CID of the checkpoint for which to verify.
|
||||
|
||||
To reset the watcher to a previous block number:
|
||||
|
||||
```bash
|
||||
yarn reset watcher --block-number <previous-block-number>
|
||||
```
|
||||
|
||||
* `block-number`: Block number to which to reset the watcher.
|
||||
|
||||
To reset the job-queue:
|
||||
|
||||
```bash
|
||||
yarn reset job-queue
|
||||
```
|
||||
|
||||
To reset the state:
|
||||
|
||||
```bash
|
||||
yarn reset state --block-number <previous-block-number>
|
||||
```
|
||||
|
||||
## Import/Export State
|
||||
|
||||
To export and import the watcher state:
|
||||
|
||||
In the source watcher, export watcher state:
|
||||
|
||||
```bash
|
||||
yarn export-state --export-file [export-file-path] --block-number [snapshot-block-height]
|
||||
```
|
||||
|
||||
* `export-file`: Path of file to which to export the watcher data.
|
||||
* `block-number`: Block height at which to take snapshot for export.
|
||||
|
||||
In the target watcher, run the job-runner:
|
||||
|
||||
```bash
|
||||
yarn job-runner
|
||||
```
|
||||
|
||||
Import watcher state:
|
||||
|
||||
```bash
|
||||
yarn import-state --import-file <import-file-path>
|
||||
```
|
||||
|
||||
* `import-file`: Path of file from which to import the watcher data.
|
||||
|
||||
To inspect a CID:
|
||||
|
||||
```bash
|
||||
yarn inspect-cid --cid <cid>
|
||||
```
|
||||
|
||||
* `cid`: CID to be inspected.
|
BIN
docs/watchers-graphic.png
Normal file
BIN
docs/watchers-graphic.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 9.8 MiB |
20
packages/README.md
Normal file
20
packages/README.md
Normal file
@ -0,0 +1,20 @@
|
||||
# Watchers Directory
|
||||
|
||||
Here contains all the publicly available watchers for your experimenting purposes. For general information on setting up the stack and the CLI commands used to interact with watchers, see the [docs](/docs) directory.
|
||||
|
||||
## Customizing Watchers
|
||||
|
||||
* Indexing on an event:
|
||||
|
||||
* Edit the custom hook function `handleEvent` (triggered on an event) in [hooks.ts](./src/hooks.ts) to perform corresponding indexing using the `Indexer` object.
|
||||
|
||||
* While using the indexer storage methods for indexing, pass `diff` as true if default state is desired to be generated using the state variables being indexed.
|
||||
|
||||
* Generating state:
|
||||
|
||||
* Edit the custom hook function `createInitialState` (triggered if the watcher passes the start block, checkpoint: `true`) in [hooks.ts](./src/hooks.ts) to save an initial `State` using the `Indexer` object.
|
||||
|
||||
* Edit the custom hook function `createStateDiff` (triggered on a block) in [hooks.ts](./src/hooks.ts) to save the state in a `diff` `State` using the `Indexer` object. The default state (if exists) is updated.
|
||||
|
||||
* Edit the custom hook function `createStateCheckpoint` (triggered just before default and CLI checkpoint) in [hooks.ts](./src/hooks.ts) to save the state in a `checkpoint` `State` using the `Indexer` object.
|
||||
|
@ -2,79 +2,32 @@
|
||||
|
||||
## Setup
|
||||
|
||||
Create a postgres12 database for the job queue:
|
||||
|
||||
```
|
||||
sudo su - postgres
|
||||
createdb address-watcher-job-queue
|
||||
```
|
||||
|
||||
Enable the `pgcrypto` extension on the job queue database (https://github.com/timgit/pg-boss/blob/master/docs/usage.md#intro).
|
||||
|
||||
Example:
|
||||
|
||||
```
|
||||
postgres@tesla:~$ psql -U postgres -h localhost address-watcher-job-queue
|
||||
Password for user postgres:
|
||||
psql (12.7 (Ubuntu 12.7-1.pgdg18.04+1))
|
||||
SSL connection (protocol: TLSv1.3, cipher: TLS_AES_256_GCM_SHA384, bits: 256, compression: off)
|
||||
Type "help" for help.
|
||||
|
||||
address-watcher-job-queue=# CREATE EXTENSION pgcrypto;
|
||||
CREATE EXTENSION
|
||||
address-watcher-job-queue=# exit
|
||||
```
|
||||
|
||||
Create a postgres12 database for the address watcher:
|
||||
|
||||
```
|
||||
sudo su - postgres
|
||||
createdb address-watcher
|
||||
```
|
||||
|
||||
Update `environments/local.toml` with database connection settings for both the databases.
|
||||
|
||||
Update the `upstream` config in `environments/local.toml` and provide the `ipld-eth-server` GQL API and the tracing API (`debug_traceTransaction` RPC provider) endpoints.
|
||||
|
||||
## Run
|
||||
|
||||
Run the following scripts in different terminals.
|
||||
First try the [stack orchestrator](https://github.com/cerc-io/stack-orchestrator) to quickly get started. Advanced users can see [here](/docs/README.md) for instructions on setting up a local environment by hand.
|
||||
|
||||
Build files:
|
||||
|
||||
```
|
||||
yarn build
|
||||
```bash
|
||||
yarn && yarn build
|
||||
```
|
||||
|
||||
GQL server:
|
||||
## Run
|
||||
|
||||
```
|
||||
Run the following commands in different terminals:
|
||||
|
||||
GraphQL server:
|
||||
|
||||
```bash
|
||||
yarn server
|
||||
|
||||
# For development.
|
||||
yarn server:dev
|
||||
|
||||
# For specifying config file.
|
||||
yarn server -f environments/local.toml
|
||||
```
|
||||
|
||||
Job runner for processing the tracing requests queue:
|
||||
|
||||
```
|
||||
```bash
|
||||
yarn job-runner
|
||||
|
||||
# For development.
|
||||
yarn job-runner:dev
|
||||
|
||||
# For specifying config file.
|
||||
yarn job-runner -f environments/local.toml
|
||||
```
|
||||
|
||||
To fill a block range:
|
||||
|
||||
```
|
||||
```bash
|
||||
yarn fill --start-block 1 --end-block 1000
|
||||
|
||||
# For specifying config file.
|
||||
yarn fill -f environments/local.toml --start-block 1 --end-block 1000
|
||||
```
|
||||
|
@ -2,199 +2,15 @@
|
||||
|
||||
## Setup
|
||||
|
||||
* Run the following command to install required packages:
|
||||
First try the [stack orchestrator](https://github.com/cerc-io/stack-orchestrator) to quickly get started. Advanced users can see [here](/docs/README.md) for instructions on setting up a local environment by hand.
|
||||
|
||||
```bash
|
||||
yarn
|
||||
```
|
||||
|
||||
* Create a postgres12 database for the watcher:
|
||||
|
||||
```bash
|
||||
sudo su - postgres
|
||||
createdb eden-watcher
|
||||
```
|
||||
|
||||
* If the watcher is an `active` watcher:
|
||||
|
||||
Create database for the job queue and enable the `pgcrypto` extension on them (https://github.com/timgit/pg-boss/blob/master/docs/usage.md#intro):
|
||||
|
||||
```
|
||||
createdb eden-watcher-job-queue
|
||||
```
|
||||
|
||||
```
|
||||
postgres@tesla:~$ psql -U postgres -h localhost eden-watcher-job-queue
|
||||
Password for user postgres:
|
||||
psql (12.7 (Ubuntu 12.7-1.pgdg18.04+1))
|
||||
SSL connection (protocol: TLSv1.3, cipher: TLS_AES_256_GCM_SHA384, bits: 256, compression: off)
|
||||
Type "help" for help.
|
||||
|
||||
eden-watcher-job-queue=# CREATE EXTENSION pgcrypto;
|
||||
CREATE EXTENSION
|
||||
eden-watcher-job-queue=# exit
|
||||
```
|
||||
|
||||
* In the [config file](./environments/local.toml):
|
||||
|
||||
* Update the database connection settings.
|
||||
|
||||
* Update the `upstream` config and provide the `ipld-eth-server` GQL API endpoint.
|
||||
|
||||
* Update the `server` config with state checkpoint settings.
|
||||
|
||||
## Customize
|
||||
|
||||
* Indexing on an event:
|
||||
|
||||
* Edit the custom hook function `handleEvent` (triggered on an event) in [hooks.ts](./src/hooks.ts) to perform corresponding indexing using the `Indexer` object.
|
||||
|
||||
* While using the indexer storage methods for indexing, pass `diff` as true if default state is desired to be generated using the state variables being indexed.
|
||||
|
||||
* Generating state:
|
||||
|
||||
* Edit the custom hook function `createInitialState` (triggered if the watcher passes the start block, checkpoint: `true`) in [hooks.ts](./src/hooks.ts) to save an initial `State` using the `Indexer` object.
|
||||
|
||||
* Edit the custom hook function `createStateDiff` (triggered on a block) in [hooks.ts](./src/hooks.ts) to save the state in a `diff` `State` using the `Indexer` object. The default state (if exists) is updated.
|
||||
|
||||
* Edit the custom hook function `createStateCheckpoint` (triggered just before default and CLI checkpoint) in [hooks.ts](./src/hooks.ts) to save the state in a `checkpoint` `State` using the `Indexer` object.
|
||||
|
||||
## Run
|
||||
|
||||
* If the watcher is a `lazy` watcher:
|
||||
Setup with:
|
||||
|
||||
* Run the server:
|
||||
```bash
|
||||
yarn && yarn build
|
||||
```
|
||||
|
||||
```bash
|
||||
yarn server
|
||||
```
|
||||
|
||||
GQL console: http://localhost:3012/graphql
|
||||
|
||||
* If the watcher is an `active` watcher:
|
||||
|
||||
* Run the job-runner:
|
||||
|
||||
```bash
|
||||
yarn job-runner
|
||||
```
|
||||
|
||||
* Run the server:
|
||||
|
||||
```bash
|
||||
yarn server
|
||||
```
|
||||
|
||||
GQL console: http://localhost:3012/graphql
|
||||
|
||||
* To watch a contract:
|
||||
|
||||
```bash
|
||||
yarn watch:contract --address <contract-address> --kind <contract-kind> --checkpoint <true | false> --starting-block [block-number]
|
||||
```
|
||||
|
||||
* `address`: Address or identifier of the contract to be watched.
|
||||
* `kind`: Kind of the contract.
|
||||
* `checkpoint`: Turn checkpointing on (`true` | `false`).
|
||||
* `starting-block`: Starting block for the contract (default: `1`).
|
||||
|
||||
Examples:
|
||||
|
||||
Watch a contract with its address and checkpointing on:
|
||||
|
||||
```bash
|
||||
yarn watch:contract --address 0x1F78641644feB8b64642e833cE4AFE93DD6e7833 --kind ERC20 --checkpoint true
|
||||
```
|
||||
|
||||
Watch a contract with its identifier and checkpointing on:
|
||||
|
||||
```bash
|
||||
yarn watch:contract --address MyProtocol --kind protocol --checkpoint true
|
||||
```
|
||||
|
||||
* To fill a block range:
|
||||
|
||||
```bash
|
||||
yarn fill --start-block <from-block> --end-block <to-block>
|
||||
```
|
||||
|
||||
* `start-block`: Block number to start filling from.
|
||||
* `end-block`: Block number till which to fill.
|
||||
|
||||
* To create a checkpoint for a contract:
|
||||
|
||||
```bash
|
||||
yarn checkpoint create --address <contract-address> --block-hash [block-hash]
|
||||
```
|
||||
|
||||
* `address`: Address or identifier of the contract for which to create a checkpoint.
|
||||
* `block-hash`: Hash of a block (in the pruned region) at which to create the checkpoint (default: latest canonical block hash).
|
||||
|
||||
* To verify a checkpoint:
|
||||
|
||||
```bash
|
||||
yarn checkpoint verify --cid <checkpoint-cid>
|
||||
```
|
||||
|
||||
`cid`: CID of the checkpoint for which to verify.
|
||||
|
||||
* To reset the watcher to a previous block number:
|
||||
|
||||
* Reset watcher:
|
||||
|
||||
```bash
|
||||
yarn reset watcher --block-number <previous-block-number>
|
||||
```
|
||||
|
||||
* Reset job-queue:
|
||||
|
||||
```bash
|
||||
yarn reset job-queue
|
||||
```
|
||||
|
||||
* Reset state:
|
||||
|
||||
```bash
|
||||
yarn reset state --block-number <previous-block-number>
|
||||
```
|
||||
|
||||
* `block-number`: Block number to which to reset the watcher.
|
||||
|
||||
* To export and import the watcher state:
|
||||
|
||||
* In source watcher, export watcher state:
|
||||
|
||||
```bash
|
||||
yarn export-state --export-file [export-file-path] --block-number [snapshot-block-height]
|
||||
```
|
||||
|
||||
* `export-file`: Path of file to which to export the watcher data.
|
||||
* `block-number`: Block height at which to take snapshot for export.
|
||||
|
||||
* In target watcher, run job-runner:
|
||||
|
||||
```bash
|
||||
yarn job-runner
|
||||
```
|
||||
|
||||
* Import watcher state:
|
||||
|
||||
```bash
|
||||
yarn import-state --import-file <import-file-path>
|
||||
```
|
||||
|
||||
* `import-file`: Path of file from which to import the watcher data.
|
||||
|
||||
* Run server:
|
||||
|
||||
```bash
|
||||
yarn server
|
||||
```
|
||||
|
||||
* To inspect a CID:
|
||||
|
||||
```bash
|
||||
yarn inspect-cid --cid <cid>
|
||||
```
|
||||
|
||||
* `cid`: CID to be inspected.
|
||||
then checkout the [CLI guide](/docs/cli.md) for examples of commands that can be run on this watcher.
|
||||
|
@ -1,68 +1,8 @@
|
||||
# ERC20 Watcher
|
||||
|
||||
## Setup
|
||||
First try the [erc20 demo in stack orchestrator](https://github.com/cerc-io/stack-orchestrator/tree/main/app/data/stacks/erc20) to quickly get started. Advanced users can see [here](/docs/README.md) for instructions on setting up a local environment by hand.
|
||||
|
||||
Create a postgres12 database for the job queue:
|
||||
|
||||
```
|
||||
sudo su - postgres
|
||||
createdb erc20-watcher-job-queue
|
||||
```
|
||||
|
||||
Enable the `pgcrypto` extension on the job queue database (https://github.com/timgit/pg-boss/blob/master/docs/usage.md#intro).
|
||||
|
||||
Example:
|
||||
|
||||
```
|
||||
postgres@tesla:~$ psql -U postgres -h localhost erc20-watcher-job-queue
|
||||
Password for user postgres:
|
||||
psql (12.7 (Ubuntu 12.7-1.pgdg18.04+1))
|
||||
SSL connection (protocol: TLSv1.3, cipher: TLS_AES_256_GCM_SHA384, bits: 256, compression: off)
|
||||
Type "help" for help.
|
||||
|
||||
erc20-watcher-job-queue=# CREATE EXTENSION pgcrypto;
|
||||
CREATE EXTENSION
|
||||
erc20-watcher-job-queue=# exit
|
||||
```
|
||||
|
||||
Create a postgres12 database for the erc20 watcher:
|
||||
|
||||
```
|
||||
sudo su - postgres
|
||||
createdb erc20-watcher
|
||||
```
|
||||
|
||||
Update `environments/local.toml` with database connection settings for both the databases.
|
||||
```toml
|
||||
[database]
|
||||
type = "postgres"
|
||||
host = "localhost"
|
||||
port = 5432
|
||||
database = "erc20-watcher"
|
||||
username = "postgres"
|
||||
password = "postgres"
|
||||
|
||||
[jobQueue]
|
||||
dbConnectionString = "postgres://postgres:postgres@localhost/erc20-watcher-job-queue"
|
||||
```
|
||||
|
||||
Update the `upstream` config in `environments/local.toml`. Provide the `ipld-eth-server` GQL and RPC API endpoints.
|
||||
```toml
|
||||
[upstream]
|
||||
[upstream.ethServer]
|
||||
gqlApiEndpoint = "http://127.0.0.1:8082/graphql"
|
||||
rpcProviderEndpoint = "http://127.0.0.1:8081"
|
||||
```
|
||||
|
||||
Ensure that watcher is of active kind. Update the kind in `server` config to active.
|
||||
```toml
|
||||
[server]
|
||||
kind = "active"
|
||||
```
|
||||
|
||||
## Run
|
||||
|
||||
Follow the steps below or follow the [Demo](./demo.md)
|
||||
## Build
|
||||
|
||||
Build files:
|
||||
|
||||
@ -70,116 +10,170 @@ Build files:
|
||||
yarn build
|
||||
```
|
||||
|
||||
Run the watcher:
|
||||
|
||||
## Run
|
||||
|
||||
Start the job runner:
|
||||
|
||||
```bash
|
||||
$ yarn job-runner
|
||||
|
||||
# For development.
|
||||
$ yarn job-runner:dev
|
||||
|
||||
# For specifying config file.
|
||||
$ yarn job-runner -f environments/local.toml
|
||||
yarn job-runner
|
||||
```
|
||||
|
||||
Start the server:
|
||||
For development or to specify the config file:
|
||||
```bash
|
||||
yarn job-runner:dev
|
||||
yarn job-runner -f environments/local.toml
|
||||
```
|
||||
|
||||
Then, Start the server:
|
||||
|
||||
```bash
|
||||
$ yarn server
|
||||
|
||||
# For development.
|
||||
$ yarn server:dev
|
||||
|
||||
# For specifying config file.
|
||||
$ yarn server -f environments/local.toml
|
||||
yarn server
|
||||
```
|
||||
|
||||
GQL console: http://localhost:3001/graphql
|
||||
For development or to specify the config file:
|
||||
```bash
|
||||
yarn server:dev
|
||||
yarn server -f environments/local.toml
|
||||
```
|
||||
|
||||
See the GQL console at: http://localhost:3001/graphql
|
||||
Note: the port may be different depending on your configuration.
|
||||
|
||||
Deploy an ERC20 token:
|
||||
|
||||
```bash
|
||||
$ yarn token:deploy
|
||||
yarn token:deploy
|
||||
```
|
||||
In the output you'll see:
|
||||
|
||||
```bash
|
||||
GLD Token deployed to: 0xTokenAddress
|
||||
```
|
||||
|
||||
Export the address of the deployed token to a shell variable for later use:
|
||||
|
||||
```bash
|
||||
export TOKEN_ADDRESS=0xTokenAddress
|
||||
```
|
||||
|
||||
Start watching a token:
|
||||
|
||||
Get the main account address:
|
||||
```bash
|
||||
$ yarn watch:contract --address 0xTokenAddress --startingBlock <start-block> --kind ERC20 --checkpoint false
|
||||
|
||||
# For specifying config file.
|
||||
$ yarn watch:contract -f environments/local.toml --address 0xTokenAddress --startingBlock <start-block> --kind ERC20 --checkpoint false
|
||||
yarn account
|
||||
```
|
||||
|
||||
Example:
|
||||
and export it as well:
|
||||
|
||||
```bash
|
||||
$ yarn watch:contract --address 0xfE0034a874c2707c23F91D7409E9036F5e08ac34 --startingBlock 100 --kind ERC20 --checkpoint false
|
||||
export PRIMARY_ACCOUNT=0xPrimaryAccount
|
||||
```
|
||||
|
||||
Run the following command to watch the contract:
|
||||
|
||||
```bash
|
||||
yarn watch:contract --address $TOKEN_ADDRESS --kind ERC20 --checkpoint false
|
||||
```
|
||||
|
||||
For specifying a config file:
|
||||
```bash
|
||||
yarn watch:contract -f environments/local.toml --address 0xTokenAddress --kind ERC20 --checkpoint false
|
||||
```
|
||||
|
||||
To fill a block range:
|
||||
|
||||
```bash
|
||||
yarn fill --startBlock <from-block> --endBlock <to-block>
|
||||
|
||||
# For specifying config file.
|
||||
$ yarn fill -f environments/local.toml --startBlock <from-block> --endBlock <to-block>
|
||||
```
|
||||
|
||||
Example:
|
||||
To get the current block hash at any time, run:
|
||||
|
||||
```bash
|
||||
$ yarn fill --startBlock 1000 --endBlock 2000
|
||||
yarn block:latest
|
||||
```
|
||||
|
||||
### Example GQL Queries
|
||||
Add a new account to Metamask and export the account address to a shell variable for later use:
|
||||
|
||||
```text
|
||||
{
|
||||
name(blockHash: "0x5ef95c9847f15179b64fa57994355623f899aca097ad779421b8dff866a8b9c3", token: "0x1ca7c995f8eF0A2989BbcE08D5B7Efe50A584aa1") {
|
||||
```bash
|
||||
export RECIPIENT_ADDRESS=0xRecipientAddress
|
||||
```
|
||||
|
||||
Run the following GQL query against the [http://127.0.0.1:3001/graphql](http://127.0.0.1:3001/graphql) to get the name, symbol and total supply of the deployed token:
|
||||
|
||||
```graphql
|
||||
query {
|
||||
name(
|
||||
blockHash: "LATEST_BLOCK_HASH"
|
||||
token: "0xTokenAddress"
|
||||
) {
|
||||
value
|
||||
proof {
|
||||
data
|
||||
}
|
||||
}
|
||||
|
||||
symbol(blockHash: "0x5ef95c9847f15179b64fa57994355623f899aca097ad779421b8dff866a8b9c3", token: "0x1ca7c995f8eF0A2989BbcE08D5B7Efe50A584aa1") {
|
||||
symbol(
|
||||
blockHash: "LATEST_BLOCK_HASH"
|
||||
token: "0xTokenAddress"
|
||||
) {
|
||||
value
|
||||
proof {
|
||||
data
|
||||
}
|
||||
}
|
||||
|
||||
totalSupply(blockHash: "0x5ef95c9847f15179b64fa57994355623f899aca097ad779421b8dff866a8b9c3", token: "0x1ca7c995f8eF0A2989BbcE08D5B7Efe50A584aa1") {
|
||||
totalSupply(
|
||||
blockHash: "LATEST_BLOCK_HASH"
|
||||
token: "0xTokenAddress"
|
||||
) {
|
||||
value
|
||||
proof {
|
||||
data
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
balanceOf(blockHash: "0x5ef95c9847f15179b64fa57994355623f899aca097ad779421b8dff866a8b9c3", token: "0x1ca7c995f8eF0A2989BbcE08D5B7Efe50A584aa1", owner: "0xDC7d7A8920C8Eecc098da5B7522a5F31509b5Bfc") {
|
||||
Run the following GQL query to get balances for the main and the recipient account at the latest block hash:
|
||||
|
||||
```graphql
|
||||
query {
|
||||
fromBalanceOf: balanceOf(
|
||||
blockHash: "LATEST_BLOCK_HASH"
|
||||
token: "0xTokenAddress",
|
||||
# main/primary account having all the balance initially
|
||||
owner: "0xPrimaryAccount"
|
||||
) {
|
||||
value
|
||||
proof {
|
||||
data
|
||||
}
|
||||
}
|
||||
|
||||
allowance(blockHash: "0x81ed2b04af35b1b276281c37243212731202d5a191a27d07b22a605fd442998d", token: "0x1ca7c995f8eF0A2989BbcE08D5B7Efe50A584aa1", owner: "0xDC7d7A8920C8Eecc098da5B7522a5F31509b5Bfc", spender: "0xCA6D29232D1435D8198E3E5302495417dD073d61") {
|
||||
toBalanceOf: balanceOf(
|
||||
blockHash: "LATEST_BLOCK_HASH"
|
||||
token: "0xTokenAddress",
|
||||
owner: "0xRecipientAddress"
|
||||
) {
|
||||
value
|
||||
proof {
|
||||
data
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
events(blockHash: "0x3441ba476dff95c58528afe754ceec659e0ef8ff1b59244ec4545f4f9784a51c", token: "0x1ca7c995f8eF0A2989BbcE08D5B7Efe50A584aa1") {
|
||||
Run the following GQL subscription at the GraphQL endpoint:
|
||||
|
||||
```graphql
|
||||
subscription {
|
||||
onEvent {
|
||||
blockHash
|
||||
contract
|
||||
event {
|
||||
__typename
|
||||
... on TransferEvent {
|
||||
from
|
||||
to
|
||||
value
|
||||
}
|
||||
},
|
||||
... on ApprovalEvent {
|
||||
owner
|
||||
spender
|
||||
@ -192,3 +186,13 @@ $ yarn fill --startBlock 1000 --endBlock 2000
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Transfer tokens to the recipient account:
|
||||
|
||||
```bash
|
||||
yarn token:transfer --token $TOKEN_ADDRESS --to $RECIPIENT_ADDRESS --amount 100
|
||||
```
|
||||
|
||||
A Transfer event to the `RECIPIENT_ADDRESS` should be visible in the subscription.
|
||||
|
||||
Get the latest block hash again, then fire the GQL query above to get updated balances for the main (from) and the recipient (to) account.
|
||||
|
@ -1,200 +0,0 @@
|
||||
# Demo
|
||||
|
||||
* The following core services need to be running for the demo:
|
||||
* [ipld-eth-db](https://github.com/cerc-io/ipld-eth-db)
|
||||
* Version: [v4.2.3-alpha](https://github.com/cerc-io/ipld-eth-db/releases/tag/v4.2.3-alpha)
|
||||
* [geth](https://github.com/cerc-io/go-ethereum)
|
||||
* State diffing service should use `ipld-eth-db` for database.
|
||||
* Version: [v1.10.26-statediff-4.2.2-alpha](https://github.com/cerc-io/go-ethereum/releases/tag/v1.10.26-statediff-4.2.2-alpha)
|
||||
* Endpoint: http://127.0.0.1:8545
|
||||
* [ipld-eth-server](https://github.com/cerc-io/ipld-eth-server)
|
||||
* Should use `ipld-eth-db` for database.
|
||||
* Version: [v4.2.3-alpha](https://github.com/cerc-io/ipld-eth-server/releases/tag/v4.2.3-alpha)
|
||||
* Endpoints:
|
||||
* GQL: http://127.0.0.1:8082/graphql
|
||||
* RPC: http://127.0.0.1:8081
|
||||
|
||||
* Create a postgres12 database for the watcher:
|
||||
|
||||
```bash
|
||||
sudo su - postgres
|
||||
|
||||
# If database already exists
|
||||
# dropdb erc20-watcher
|
||||
|
||||
createdb erc20-watcher
|
||||
```
|
||||
|
||||
* Create database for the job queue and enable the `pgcrypto` extension on them (https://github.com/timgit/pg-boss/blob/master/docs/usage.md#intro):
|
||||
|
||||
```bash
|
||||
# If database already exists
|
||||
# dropdb erc20-watcher-job-queue
|
||||
|
||||
createdb erc20-watcher-job-queue
|
||||
```
|
||||
|
||||
```
|
||||
postgres@tesla:~$ psql -U postgres -h localhost erc20-watcher-job-queue
|
||||
Password for user postgres:
|
||||
psql (12.7 (Ubuntu 12.7-1.pgdg18.04+1))
|
||||
SSL connection (protocol: TLSv1.3, cipher: TLS_AES_256_GCM_SHA384, bits: 256, compression: off)
|
||||
Type "help" for help.
|
||||
|
||||
erc20-watcher-job-queue=# CREATE EXTENSION pgcrypto;
|
||||
CREATE EXTENSION
|
||||
erc20-watcher-job-queue=# exit
|
||||
```
|
||||
|
||||
* In the [config file](./environments/local.toml) update the `database` connection settings.
|
||||
|
||||
* In `watcher-ts` repo, follow the instructions in [Setup](../../README.md#setup) for installing and building packages.
|
||||
|
||||
```bash
|
||||
# After setup
|
||||
yarn && yarn build
|
||||
```
|
||||
|
||||
* Run the job-runner:
|
||||
|
||||
```bash
|
||||
yarn job-runner
|
||||
```
|
||||
|
||||
* Run the watcher:
|
||||
|
||||
```bash
|
||||
yarn server
|
||||
```
|
||||
|
||||
* Deploy an ERC20 token:
|
||||
|
||||
```bash
|
||||
yarn token:deploy
|
||||
# GLD Token deployed to: TOKEN_ADDRESS
|
||||
```
|
||||
|
||||
Export the address of the deployed token to a shell variable for later use:
|
||||
|
||||
```bash
|
||||
export TOKEN_ADDRESS="<TOKEN_ADDRESS>"
|
||||
```
|
||||
|
||||
* Run the following command to watch the contract:
|
||||
|
||||
```bash
|
||||
yarn watch:contract --address $TOKEN_ADDRESS --kind ERC20 --checkpoint false
|
||||
```
|
||||
|
||||
* Add a second account to Metamask and export the account address to a shell variable for later use:
|
||||
|
||||
```bash
|
||||
export RECIPIENT_ADDRESS="<RECIPIENT_ADDRESS>"
|
||||
```
|
||||
|
||||
* To get the current block hash at any time, run:
|
||||
|
||||
```bash
|
||||
yarn block:latest
|
||||
```
|
||||
|
||||
* Run the following GQL query against the [GraphQL endpoint](http://127.0.0.1:3001/graphql) to get name, symbol and total supply of the deployed token:
|
||||
|
||||
```graphql
|
||||
query {
|
||||
name(
|
||||
blockHash: "LATEST_BLOCK_HASH"
|
||||
token: "TOKEN_ADDRESS"
|
||||
) {
|
||||
value
|
||||
proof {
|
||||
data
|
||||
}
|
||||
}
|
||||
|
||||
symbol(
|
||||
blockHash: "LATEST_BLOCK_HASH"
|
||||
token: "TOKEN_ADDRESS"
|
||||
) {
|
||||
value
|
||||
proof {
|
||||
data
|
||||
}
|
||||
}
|
||||
|
||||
totalSupply(
|
||||
blockHash: "LATEST_BLOCK_HASH"
|
||||
token: "TOKEN_ADDRESS"
|
||||
) {
|
||||
value
|
||||
proof {
|
||||
data
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
* Run the following GQL query against the [GraphQL endpoint](http://127.0.0.1:3001/graphql) to get balances for the main and the recipient account at the latest block hash:
|
||||
|
||||
```graphql
|
||||
query {
|
||||
fromBalanceOf: balanceOf(
|
||||
blockHash: "LATEST_BLOCK_HASH"
|
||||
token: "TOKEN_ADDRESS",
|
||||
# main account having all the balance initially
|
||||
owner: "0xDC7d7A8920C8Eecc098da5B7522a5F31509b5Bfc"
|
||||
) {
|
||||
value
|
||||
proof {
|
||||
data
|
||||
}
|
||||
}
|
||||
toBalanceOf: balanceOf(
|
||||
blockHash: "LATEST_BLOCK_HASH"
|
||||
token: "TOKEN_ADDRESS",
|
||||
owner: "RECIPIENT_ADDRESS"
|
||||
) {
|
||||
value
|
||||
proof {
|
||||
data
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
* Run the following GQL subscription at the GraphQL endpoint:
|
||||
|
||||
```graphql
|
||||
subscription {
|
||||
onEvent {
|
||||
blockHash
|
||||
contract
|
||||
event {
|
||||
__typename
|
||||
... on TransferEvent {
|
||||
from
|
||||
to
|
||||
value
|
||||
},
|
||||
... on ApprovalEvent {
|
||||
owner
|
||||
spender
|
||||
value
|
||||
}
|
||||
}
|
||||
proof {
|
||||
data
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
* Transfer tokens to the recipient account:
|
||||
|
||||
```bash
|
||||
yarn token:transfer --token $TOKEN_ADDRESS --to $RECIPIENT_ADDRESS --amount 100
|
||||
```
|
||||
|
||||
* A Transfer event to RECIPIENT_ADDRESS shall be visible in the subscription at endpoint.
|
||||
|
||||
* Fire the GQL query above to get updated balances for the main (from) and the recipient (to) account.
|
@ -1,202 +1,305 @@
|
||||
# erc721-watcher
|
||||
|
||||
First try the [erc721 demo in stack orchestrator](https://github.com/cerc-io/stack-orchestrator/tree/main/app/data/stacks/erc721) to quickly get started. Advanced users can see [here](/docs/README.md) for instructions on setting up a local environment by hand.
|
||||
|
||||
## Setup
|
||||
|
||||
* Run the following command to install required packages:
|
||||
Run the following command to install required packages:
|
||||
|
||||
```bash
|
||||
yarn
|
||||
```bash
|
||||
yarn && yarn build
|
||||
```
|
||||
|
||||
If the watcher is "active", first run the job-runner:
|
||||
|
||||
```bash
|
||||
yarn job-runner
|
||||
```
|
||||
|
||||
then run the watcher:
|
||||
|
||||
```bash
|
||||
yarn server
|
||||
```
|
||||
|
||||
For "lazy" watchers, you only need to run the above command.
|
||||
|
||||
|
||||
Deploy an ERC721 token:
|
||||
|
||||
```bash
|
||||
yarn nft:deploy
|
||||
```
|
||||
```
|
||||
# NFT deployed to: 0xNFTAddress
|
||||
```
|
||||
Export the address of the deployed token to a shell variable for later use:
|
||||
|
||||
```bash
|
||||
export NFT_ADDRESS="0xNFTAddress"
|
||||
```
|
||||
|
||||
* Create a postgres12 database for the watcher:
|
||||
|
||||
```bash
|
||||
sudo su - postgres
|
||||
createdb erc721-watcher
|
||||
```
|
||||
|
||||
* If the watcher is an `active` watcher:
|
||||
|
||||
Create database for the job queue and enable the `pgcrypto` extension on them (https://github.com/timgit/pg-boss/blob/master/docs/usage.md#intro):
|
||||
|
||||
```
|
||||
createdb erc721-watcher-job-queue
|
||||
```
|
||||
|
||||
```
|
||||
postgres@tesla:~$ psql -U postgres -h localhost erc721-watcher-job-queue
|
||||
Password for user postgres:
|
||||
psql (12.7 (Ubuntu 12.7-1.pgdg18.04+1))
|
||||
SSL connection (protocol: TLSv1.3, cipher: TLS_AES_256_GCM_SHA384, bits: 256, compression: off)
|
||||
Type "help" for help.
|
||||
|
||||
erc721-watcher-job-queue=# CREATE EXTENSION pgcrypto;
|
||||
CREATE EXTENSION
|
||||
erc721-watcher-job-queue=# exit
|
||||
```
|
||||
|
||||
* The following core services should be setup and running on localhost:
|
||||
|
||||
* `vulcanize/go-ethereum` [v1.10.18-statediff-4.0.2-alpha](https://github.com/vulcanize/go-ethereum/releases/tag/v1.10.18-statediff-4.0.2-alpha) on port 8545
|
||||
|
||||
* `vulcanize/ipld-eth-server` [v4.0.3-alpha](https://github.com/vulcanize/ipld-eth-server/releases/tag/v4.0.3-alpha) with native GQL API enabled, on port 8082
|
||||
|
||||
* In the [config file](./environments/local.toml):
|
||||
|
||||
* Update the database connection settings.
|
||||
|
||||
* Update the `upstream` config and provide the `ipld-eth-server` GQL API endpoint.
|
||||
|
||||
* Update the `server` config with state checkpoint settings.
|
||||
|
||||
## Customize
|
||||
|
||||
* Indexing on an event:
|
||||
|
||||
* Edit the custom hook function `handleEvent` (triggered on an event) in [hooks.ts](./src/hooks.ts) to perform corresponding indexing using the `Indexer` object.
|
||||
|
||||
* While using the indexer storage methods for indexing, pass `diff` as true if default state is desired to be generated using the state variables being indexed.
|
||||
|
||||
* Generating state:
|
||||
|
||||
* Edit the custom hook function `createInitialState` (triggered if the watcher passes the start block, checkpoint: `true`) in [hooks.ts](./src/hooks.ts) to save an initial `State` using the `Indexer` object.
|
||||
|
||||
* Edit the custom hook function `createStateDiff` (triggered on a block) in [hooks.ts](./src/hooks.ts) to save the state in a `diff` `State` using the `Indexer` object. The default state (if exists) is updated.
|
||||
|
||||
* Edit the custom hook function `createStateCheckpoint` (triggered just before default and CLI checkpoint) in [hooks.ts](./src/hooks.ts) to save the state in a `checkpoint` `State` using the `Indexer` object.
|
||||
|
||||
## Run
|
||||
|
||||
Follow the steps below or follow the [Demo](./demo.md)
|
||||
|
||||
* Run the watcher:
|
||||
|
||||
* If the watcher is a `lazy` watcher:
|
||||
|
||||
* Run the server:
|
||||
|
||||
```bash
|
||||
yarn server
|
||||
```
|
||||
|
||||
GQL console: http://localhost:3006/graphql
|
||||
|
||||
* If the watcher is an `active` watcher:
|
||||
|
||||
* Run the job-runner:
|
||||
|
||||
```bash
|
||||
yarn job-runner
|
||||
```
|
||||
|
||||
* Run the server:
|
||||
|
||||
```bash
|
||||
yarn server
|
||||
```
|
||||
|
||||
GQL console: http://localhost:3012/graphql
|
||||
|
||||
* To watch a contract:
|
||||
|
||||
```bash
|
||||
yarn watch:contract --address <contract-address> --kind <contract-kind> --checkpoint <true | false> --starting-block [block-number]
|
||||
```
|
||||
|
||||
* `address`: Address or identifier of the contract to be watched.
|
||||
* `kind`: Kind of the contract.
|
||||
* `checkpoint`: Turn checkpointing on (`true` | `false`).
|
||||
* `starting-block`: Starting block for the contract (default: `1`).
|
||||
|
||||
Examples:
|
||||
|
||||
Watch a contract with its address and checkpointing on:
|
||||
|
||||
```bash
|
||||
yarn watch:contract --address 0x1F78641644feB8b64642e833cE4AFE93DD6e7833 --kind ERC721 --checkpoint true
|
||||
```
|
||||
|
||||
Watch a contract with its identifier and checkpointing on:
|
||||
|
||||
```bash
|
||||
yarn watch:contract --address MyProtocol --kind protocol --checkpoint true
|
||||
```
|
||||
|
||||
* To fill a block range:
|
||||
|
||||
```bash
|
||||
yarn fill --start-block <from-block> --end-block <to-block>
|
||||
```
|
||||
|
||||
* `start-block`: Block number to start filling from.
|
||||
* `end-block`: Block number till which to fill.
|
||||
|
||||
* To create a checkpoint for a contract:
|
||||
|
||||
```bash
|
||||
yarn checkpoint create --address <contract-address> --block-hash [block-hash]
|
||||
```
|
||||
|
||||
* `address`: Address or identifier of the contract for which to create a checkpoint.
|
||||
* `block-hash`: Hash of a block (in the pruned region) at which to create the checkpoint (default: latest canonical block hash).
|
||||
|
||||
* To reset the watcher to a previous block number:
|
||||
|
||||
* Reset watcher:
|
||||
|
||||
```bash
|
||||
yarn reset watcher --block-number <previous-block-number>
|
||||
```
|
||||
|
||||
* Reset job-queue:
|
||||
|
||||
```bash
|
||||
yarn reset job-queue
|
||||
```
|
||||
|
||||
* Reset state:
|
||||
|
||||
```bash
|
||||
yarn reset state --block-number <previous-block-number>
|
||||
```
|
||||
|
||||
* `block-number`: Block number to which to reset the watcher.
|
||||
|
||||
* To export and import the watcher state:
|
||||
|
||||
* In source watcher, export watcher state:
|
||||
|
||||
```bash
|
||||
yarn export-state --export-file [export-file-path] --block-number [snapshot-block-height]
|
||||
```
|
||||
|
||||
* `export-file`: Path of file to which to export the watcher data.
|
||||
* `block-number`: Block height at which to take snapshot for export.
|
||||
|
||||
* In target watcher, run job-runner:
|
||||
|
||||
```bash
|
||||
yarn job-runner
|
||||
```
|
||||
|
||||
* Import watcher state:
|
||||
|
||||
```bash
|
||||
yarn import-state --import-file <import-file-path>
|
||||
```
|
||||
|
||||
* `import-file`: Path of file from which to import the watcher data.
|
||||
|
||||
* Run server:
|
||||
|
||||
```bash
|
||||
yarn server
|
||||
```
|
||||
|
||||
* To inspect a CID:
|
||||
|
||||
```bash
|
||||
yarn inspect-cid --cid <cid>
|
||||
```
|
||||
|
||||
* `cid`: CID to be inspected.
|
||||
Run the following GQL mutation in generated watcher GraphQL endpoint http://127.0.0.1:3006/graphql
|
||||
|
||||
```graphql
|
||||
mutation {
|
||||
watchContract(
|
||||
address: "0xNFTAddress"
|
||||
kind: "ERC721"
|
||||
checkpoint: true
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
TODO: settle on WC (signer/primary/main...across the docs)
|
||||
|
||||
Get the signer (primary/main) account address and export to a shell variable:
|
||||
|
||||
```bash
|
||||
yarn account
|
||||
```
|
||||
|
||||
```bash
|
||||
export SIGNER_ADDRESS="0xSignerAddress"
|
||||
```
|
||||
|
||||
Connect MetaMask to `http://localhost:8545` (with chain ID `99`)
|
||||
|
||||
Add a an account to Metamask and export the account address to a shell variable for later use:
|
||||
|
||||
```bash
|
||||
export RECIPIENT_ADDRESS="0xRecipientAddress"
|
||||
```
|
||||
|
||||
To get the current block hash at any time, run:
|
||||
|
||||
```bash
|
||||
yarn block:latest
|
||||
```
|
||||
|
||||
Run the following GQL query (`eth_call`) in the GraphQL playground at http://127.0.0.1:3006/graphql
|
||||
|
||||
```graphql
|
||||
query {
|
||||
name(
|
||||
blockHash: "LATEST_BLOCK_HASH"
|
||||
contractAddress: "0xNFTAddress"
|
||||
) {
|
||||
value
|
||||
proof {
|
||||
data
|
||||
}
|
||||
}
|
||||
symbol(
|
||||
blockHash: "LATEST_BLOCK_HASH"
|
||||
contractAddress: "0xNFTAddress"
|
||||
) {
|
||||
value
|
||||
proof {
|
||||
data
|
||||
}
|
||||
}
|
||||
balanceOf(
|
||||
blockHash: "LATEST_BLOCK_HASH"
|
||||
contractAddress: "0xNFTAddress"
|
||||
owner: "0xSignerAddress"
|
||||
) {
|
||||
value
|
||||
proof {
|
||||
data
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Run the following GQL query (`storage`) in generated watcher GraphQL endpoint http://127.0.0.1:3006/graphql
|
||||
|
||||
```graphql
|
||||
query {
|
||||
_name(
|
||||
blockHash: "LATEST_BLOCK_HASH"
|
||||
contractAddress: "0xNFTAddress"
|
||||
) {
|
||||
value
|
||||
proof {
|
||||
data
|
||||
}
|
||||
}
|
||||
_symbol(
|
||||
blockHash: "LATEST_BLOCK_HASH"
|
||||
contractAddress: "0xNFTAddress"
|
||||
) {
|
||||
value
|
||||
proof {
|
||||
data
|
||||
}
|
||||
}
|
||||
_balances(
|
||||
blockHash: "LATEST_BLOCK_HASH"
|
||||
contractAddress: "0xNFTAddress"
|
||||
key0: "0xSignerAddress"
|
||||
) {
|
||||
value
|
||||
proof {
|
||||
data
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Run the following GQL subscription in the playground:
|
||||
|
||||
```graphql
|
||||
subscription {
|
||||
onEvent {
|
||||
event {
|
||||
__typename
|
||||
... on TransferEvent {
|
||||
from
|
||||
to
|
||||
tokenId
|
||||
},
|
||||
... on ApprovalEvent {
|
||||
owner
|
||||
approved
|
||||
tokenId
|
||||
}
|
||||
},
|
||||
block {
|
||||
number
|
||||
hash
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Mint token
|
||||
|
||||
```bash
|
||||
yarn nft:mint --nft $NFT_ADDRESS --to $SIGNER_ADDRESS --token-id 1
|
||||
```
|
||||
|
||||
- A Transfer event to 0xSignerAddress should be visible in the subscription.
|
||||
|
||||
- An auto-generated `diff_staged` `State` should be added with parent CID pointing to the initial `checkpoint` `State`.
|
||||
|
||||
- Custom property `transferCount` should be 1 initially.
|
||||
|
||||
- Run the `getState` query at the endpoint to get the latest `State` for 0xNFTAddress:
|
||||
|
||||
```graphql
|
||||
query {
|
||||
getState (
|
||||
blockHash: "EVENT_BLOCK_HASH"
|
||||
contractAddress: "0xNFTAddress"
|
||||
# kind: "checkpoint"
|
||||
# kind: "diff"
|
||||
kind: "diff_staged"
|
||||
) {
|
||||
cid
|
||||
block {
|
||||
cid
|
||||
hash
|
||||
number
|
||||
timestamp
|
||||
parentHash
|
||||
}
|
||||
contractAddress
|
||||
data
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
- `diff` States get created corresponding to the `diff_staged` blocks when their respective eth_blocks reach the pruned region.
|
||||
|
||||
- `data` contains the default state and also the custom state property `transferCount` that is indexed in [hooks.ts](./src/hooks.ts) file.
|
||||
|
||||
- Get the latest blockHash and run the following query for `transferCount` entity:
|
||||
|
||||
```graphql
|
||||
query {
|
||||
transferCount(
|
||||
block: {
|
||||
hash: "LATEST_BLOCK_HASH"
|
||||
}
|
||||
id: "0xNFTAddress"
|
||||
) {
|
||||
id
|
||||
count
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
*Note: Contract address is assigned to the Entity ID.*
|
||||
|
||||
With the latest blockHash, run the following query for `balanceOf` and `ownerOf` (`eth_call`):
|
||||
|
||||
```graphql
|
||||
query {
|
||||
fromBalanceOf: balanceOf(
|
||||
blockHash: "LATEST_BLOCK_HASH"
|
||||
contractAddress: "0xNFTAddress"
|
||||
owner: "0xSignerAddress"
|
||||
) {
|
||||
value
|
||||
proof {
|
||||
data
|
||||
}
|
||||
}
|
||||
toBalanceOf: balanceOf(
|
||||
blockHash: "LATEST_BLOCK_HASH"
|
||||
contractAddress: "0xNFTAddress"
|
||||
owner: "0xRecipientAddress"
|
||||
) {
|
||||
value
|
||||
proof {
|
||||
data
|
||||
}
|
||||
}
|
||||
ownerOf(
|
||||
blockHash: "LATEST_BLOCK_HASH"
|
||||
contractAddress: "0xNFTAddress"
|
||||
tokenId: 1
|
||||
) {
|
||||
value
|
||||
proof {
|
||||
data
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Transfer token
|
||||
|
||||
```bash
|
||||
yarn nft:transfer --nft $NFT_ADDRESS --from $SIGNER_ADDRESS --to $RECIPIENT_ADDRESS --token-id 1
|
||||
```
|
||||
|
||||
- An Approval event for SIGNER_ADDRESS shall be visible in the subscription at endpoint.
|
||||
|
||||
- A Transfer event to $RECIPIENT_ADDRESS shall be visible in the subscription at endpoint.
|
||||
|
||||
- An auto-generated `diff_staged` State should be added with parent CID pointing to the previous State.
|
||||
|
||||
- Custom property `transferCount` should be incremented after transfer. This can be checked in the `getState` query.
|
||||
|
||||
- Get the latest blockHash and replace the blockHash in the above `eth_call` query. The result should be different and the token should be transferred to the recipient.
|
||||
|
||||
- Run the `getState` query again at the endpoint with the event blockHash.
|
||||
|
||||
- Run the `transferCount` entity query again with the latest blockHash. The updated count should be returned.
|
||||
|
||||
- After the `diff` block has been created (can check if event block number pruned in yarn server log), create a checkpoint using CLI in `packages/erc721-watcher`:
|
||||
|
||||
```bash
|
||||
yarn checkpoint create --address $NFT_ADDRESS
|
||||
```
|
||||
|
||||
- Run the `getState` query again with the output blockHash and kind `checkpoint` at the endpoint.
|
||||
|
||||
- The latest checkpoint should have the aggregate of state diffs since the last checkpoint.
|
||||
- The `State` entries can be seen in pg-admin in table `state`.
|
||||
|
||||
- The state should have auto indexed data and also custom property `transferCount` according to code in [hooks](./src/hooks.ts) file `handleEvent` method.
|
||||
|
||||
For more `yarn` sub-commands available, see the [CLI guide](/docs/cli.md)
|
||||
|
@ -1,343 +0,0 @@
|
||||
# Demo
|
||||
|
||||
* The following core services need to be running for the demo:
|
||||
* [ipld-eth-db](https://github.com/cerc-io/ipld-eth-db)
|
||||
* Version: [v4.2.3-alpha](https://github.com/cerc-io/ipld-eth-db/releases/tag/v4.2.3-alpha)
|
||||
* [geth](https://github.com/cerc-io/go-ethereum)
|
||||
* State diffing service should use `ipld-eth-db` for database.
|
||||
* Version: [v1.10.26-statediff-4.2.2-alpha](https://github.com/cerc-io/go-ethereum/releases/tag/v1.10.26-statediff-4.2.2-alpha)
|
||||
* Endpoint: http://127.0.0.1:8545
|
||||
* [ipld-eth-server](https://github.com/cerc-io/ipld-eth-server)
|
||||
* Should use `ipld-eth-db` for database.
|
||||
* Version: [v4.2.3-alpha](https://github.com/cerc-io/ipld-eth-server/releases/tag/v4.2.3-alpha)
|
||||
* Endpoints:
|
||||
* GQL: http://127.0.0.1:8082/graphql
|
||||
* RPC: http://127.0.0.1:8081
|
||||
|
||||
* Create a postgres12 database for the watcher:
|
||||
|
||||
```bash
|
||||
sudo su - postgres
|
||||
|
||||
# If database already exists
|
||||
# dropdb erc721-watcher
|
||||
|
||||
createdb erc721-watcher
|
||||
```
|
||||
|
||||
* Create database for the job queue and enable the `pgcrypto` extension on them (https://github.com/timgit/pg-boss/blob/master/docs/usage.md#intro):
|
||||
|
||||
```bash
|
||||
# If database already exists
|
||||
# dropdb erc721-watcher-job-queue
|
||||
|
||||
createdb erc721-watcher-job-queue
|
||||
```
|
||||
|
||||
```
|
||||
postgres@tesla:~$ psql -U postgres -h localhost erc721-watcher-job-queue
|
||||
Password for user postgres:
|
||||
psql (12.7 (Ubuntu 12.7-1.pgdg18.04+1))
|
||||
SSL connection (protocol: TLSv1.3, cipher: TLS_AES_256_GCM_SHA384, bits: 256, compression: off)
|
||||
Type "help" for help.
|
||||
|
||||
erc721-watcher-job-queue=# CREATE EXTENSION pgcrypto;
|
||||
CREATE EXTENSION
|
||||
erc721-watcher-job-queue=# exit
|
||||
```
|
||||
|
||||
* In the [config file](./environments/local.toml) update the `database` connection settings.
|
||||
|
||||
* In `watcher-ts` repo, follow the instructions in [Setup](../../README.md#setup) for installing and building packages.
|
||||
|
||||
```bash
|
||||
# After setup
|
||||
yarn && yarn build
|
||||
```
|
||||
|
||||
* Run the job-runner:
|
||||
|
||||
```bash
|
||||
yarn job-runner
|
||||
```
|
||||
|
||||
* Run the watcher:
|
||||
|
||||
```bash
|
||||
yarn server
|
||||
```
|
||||
|
||||
* Deploy an ERC721 token:
|
||||
|
||||
```bash
|
||||
yarn nft:deploy
|
||||
# NFT deployed to: NFT_ADDRESS
|
||||
```
|
||||
|
||||
Export the address of the deployed token to a shell variable for later use:
|
||||
|
||||
```bash
|
||||
export NFT_ADDRESS="<NFT_ADDRESS>"
|
||||
```
|
||||
|
||||
* Run the following GQL mutation in generated watcher GraphQL endpoint http://127.0.0.1:3006/graphql
|
||||
|
||||
```graphql
|
||||
mutation {
|
||||
watchContract(
|
||||
address: "NFT_ADDRESS"
|
||||
kind: "ERC721"
|
||||
checkpoint: true
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
* Get the signer account address and export to a shell variable:
|
||||
|
||||
```bash
|
||||
yarn account
|
||||
```
|
||||
|
||||
```bash
|
||||
export SIGNER_ADDRESS="<SIGNER_ADDRESS>"
|
||||
```
|
||||
|
||||
* Connect MetaMask to `http://localhost:8545` (with chain ID `99`)
|
||||
|
||||
* Add a second account to Metamask and export the account address to a shell variable for later use:
|
||||
|
||||
```bash
|
||||
export RECIPIENT_ADDRESS="<RECIPIENT_ADDRESS>"
|
||||
```
|
||||
|
||||
* To get the current block hash at any time, run:
|
||||
|
||||
```bash
|
||||
yarn block:latest
|
||||
```
|
||||
|
||||
* Run the following GQL query (`eth_call`) in generated watcher GraphQL endpoint http://127.0.0.1:3006/graphql
|
||||
|
||||
```graphql
|
||||
query {
|
||||
name(
|
||||
blockHash: "LATEST_BLOCK_HASH"
|
||||
contractAddress: "NFT_ADDRESS"
|
||||
) {
|
||||
value
|
||||
proof {
|
||||
data
|
||||
}
|
||||
}
|
||||
symbol(
|
||||
blockHash: "LATEST_BLOCK_HASH"
|
||||
contractAddress: "NFT_ADDRESS"
|
||||
) {
|
||||
value
|
||||
proof {
|
||||
data
|
||||
}
|
||||
}
|
||||
balanceOf(
|
||||
blockHash: "LATEST_BLOCK_HASH"
|
||||
contractAddress: "NFT_ADDRESS"
|
||||
owner: "SIGNER_ADDRESS"
|
||||
) {
|
||||
value
|
||||
proof {
|
||||
data
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
* Run the following GQL query (`storage`) in generated watcher GraphQL endpoint http://127.0.0.1:3006/graphql
|
||||
|
||||
```graphql
|
||||
query {
|
||||
_name(
|
||||
blockHash: "LATEST_BLOCK_HASH"
|
||||
contractAddress: "NFT_ADDRESS"
|
||||
) {
|
||||
value
|
||||
proof {
|
||||
data
|
||||
}
|
||||
}
|
||||
_symbol(
|
||||
blockHash: "LATEST_BLOCK_HASH"
|
||||
contractAddress: "NFT_ADDRESS"
|
||||
) {
|
||||
value
|
||||
proof {
|
||||
data
|
||||
}
|
||||
}
|
||||
_balances(
|
||||
blockHash: "LATEST_BLOCK_HASH"
|
||||
contractAddress: "NFT_ADDRESS"
|
||||
key0: "SIGNER_ADDRESS"
|
||||
) {
|
||||
value
|
||||
proof {
|
||||
data
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
* Run the following GQL subscription in generated watcher GraphQL endpoint:
|
||||
|
||||
```graphql
|
||||
subscription {
|
||||
onEvent {
|
||||
event {
|
||||
__typename
|
||||
... on TransferEvent {
|
||||
from
|
||||
to
|
||||
tokenId
|
||||
},
|
||||
... on ApprovalEvent {
|
||||
owner
|
||||
approved
|
||||
tokenId
|
||||
}
|
||||
},
|
||||
block {
|
||||
number
|
||||
hash
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
* Mint token
|
||||
|
||||
```bash
|
||||
yarn nft:mint --nft $NFT_ADDRESS --to $SIGNER_ADDRESS --token-id 1
|
||||
```
|
||||
|
||||
* A Transfer event to SIGNER_ADDRESS shall be visible in the subscription at endpoint.
|
||||
|
||||
* An auto-generated `diff_staged` `State` should be added with parent CID pointing to the initial `checkpoint` `State`.
|
||||
|
||||
* Custom property `transferCount` should be 1 initially.
|
||||
|
||||
* Run the `getState` query at the endpoint to get the latest `State` for NFT_ADDRESS:
|
||||
|
||||
```graphql
|
||||
query {
|
||||
getState (
|
||||
blockHash: "EVENT_BLOCK_HASH"
|
||||
contractAddress: "NFT_ADDRESS"
|
||||
# kind: "checkpoint"
|
||||
# kind: "diff"
|
||||
kind: "diff_staged"
|
||||
) {
|
||||
cid
|
||||
block {
|
||||
cid
|
||||
hash
|
||||
number
|
||||
timestamp
|
||||
parentHash
|
||||
}
|
||||
contractAddress
|
||||
data
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
* `diff` States get created corresponding to the `diff_staged` blocks when their respective eth_blocks reach the pruned region.
|
||||
|
||||
* `data` contains the default state and also the custom state property `transferCount` that is indexed in [hooks.ts](./src/hooks.ts) file.
|
||||
|
||||
* Get the latest blockHash and run the following query for `transferCount` entity:
|
||||
|
||||
```graphql
|
||||
query {
|
||||
transferCount(
|
||||
block: {
|
||||
hash: "LATEST_BLOCK_HASH"
|
||||
}
|
||||
id: "NFT_ADDRESS"
|
||||
) {
|
||||
id
|
||||
count
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
*Note: Contract address is assigned to the Entity ID.*
|
||||
|
||||
* With the latest blockHash, run the following query for `balanceOf` and `ownerOf` (`eth_call`):
|
||||
|
||||
```graphql
|
||||
query {
|
||||
fromBalanceOf: balanceOf(
|
||||
blockHash: "LATEST_BLOCK_HASH"
|
||||
contractAddress: "NFT_ADDRESS"
|
||||
owner: "SIGNER_ADDRESS"
|
||||
) {
|
||||
value
|
||||
proof {
|
||||
data
|
||||
}
|
||||
}
|
||||
toBalanceOf: balanceOf(
|
||||
blockHash: "LATEST_BLOCK_HASH"
|
||||
contractAddress: "NFT_ADDRESS"
|
||||
owner: "RECIPIENT_ADDRESS"
|
||||
) {
|
||||
value
|
||||
proof {
|
||||
data
|
||||
}
|
||||
}
|
||||
ownerOf(
|
||||
blockHash: "LATEST_BLOCK_HASH"
|
||||
contractAddress: "NFT_ADDRESS"
|
||||
tokenId: 1
|
||||
) {
|
||||
value
|
||||
proof {
|
||||
data
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
* Transfer token
|
||||
|
||||
```bash
|
||||
yarn nft:transfer --nft $NFT_ADDRESS --from $SIGNER_ADDRESS --to $RECIPIENT_ADDRESS --token-id 1
|
||||
```
|
||||
|
||||
* An Approval event for SIGNER_ADDRESS shall be visible in the subscription at endpoint.
|
||||
|
||||
* A Transfer event to $RECIPIENT_ADDRESS shall be visible in the subscription at endpoint.
|
||||
|
||||
* An auto-generated `diff_staged` State should be added with parent CID pointing to the previous State.
|
||||
|
||||
* Custom property `transferCount` should be incremented after transfer. This can be checked in the `getState` query.
|
||||
|
||||
* Get the latest blockHash and replace the blockHash in the above `eth_call` query. The result should be different and the token should be transferred to the recipient.
|
||||
|
||||
* Run the `getState` query again at the endpoint with the event blockHash.
|
||||
|
||||
* Run the `transferCount` entity query again with the latest blockHash. The updated count should be returned.
|
||||
|
||||
* After the `diff` block has been created (can check if event block number pruned in yarn server log), create a checkpoint using CLI in `packages/erc721-watcher`:
|
||||
|
||||
```bash
|
||||
yarn checkpoint create --address $NFT_ADDRESS
|
||||
```
|
||||
|
||||
* Run the `getState` query again with the output blockHash and kind `checkpoint` at the endpoint.
|
||||
|
||||
* The latest checkpoint should have the aggregate of state diffs since the last checkpoint.
|
||||
|
||||
* The `State` entries can be seen in pg-admin in table `state`.
|
||||
|
||||
* The state should have auto indexed data and also custom property `transferCount` according to code in [hooks](./src/hooks.ts) file `handleEvent` method.
|
@ -2,201 +2,140 @@
|
||||
|
||||
## Setup
|
||||
|
||||
* Run the following command to install required packages:
|
||||
First try the [stack orchestrator](https://github.com/cerc-io/stack-orchestrator) to quickly get started. Advanced users can see [here](/docs/README.md) for instructions on setting up a local environment by hand.
|
||||
|
||||
```bash
|
||||
yarn
|
||||
```
|
||||
Run the following command to install required packages:
|
||||
|
||||
* Create a postgres12 database for the watcher:
|
||||
|
||||
```bash
|
||||
sudo su - postgres
|
||||
createdb graph-test-watcher
|
||||
```
|
||||
|
||||
* If the watcher is an `active` watcher:
|
||||
|
||||
Create database for the job queue and enable the `pgcrypto` extension on them (https://github.com/timgit/pg-boss/blob/master/docs/usage.md#intro):
|
||||
|
||||
```
|
||||
createdb graph-test-watcher-job-queue
|
||||
```
|
||||
|
||||
```
|
||||
postgres@tesla:~$ psql -U postgres -h localhost graph-test-watcher-job-queue
|
||||
Password for user postgres:
|
||||
psql (12.7 (Ubuntu 12.7-1.pgdg18.04+1))
|
||||
SSL connection (protocol: TLSv1.3, cipher: TLS_AES_256_GCM_SHA384, bits: 256, compression: off)
|
||||
Type "help" for help.
|
||||
|
||||
graph-test-watcher-job-queue=# CREATE EXTENSION pgcrypto;
|
||||
CREATE EXTENSION
|
||||
graph-test-watcher-job-queue=# exit
|
||||
```
|
||||
|
||||
* In the [config file](./environments/local.toml):
|
||||
|
||||
* Update the database connection settings.
|
||||
|
||||
* Update the `upstream` config and provide the `ipld-eth-server` GQL API endpoint.
|
||||
|
||||
* Update the `server` config with state checkpoint settings.
|
||||
|
||||
## Customize
|
||||
|
||||
* Indexing on an event:
|
||||
|
||||
* Edit the custom hook function `handleEvent` (triggered on an event) in [hooks.ts](./src/hooks.ts) to perform corresponding indexing using the `Indexer` object.
|
||||
|
||||
* While using the indexer storage methods for indexing, pass `diff` as true if default state is desired to be generated using the state variables being indexed.
|
||||
|
||||
* Generating state:
|
||||
|
||||
* Edit the custom hook function `createInitialState` (triggered if the watcher passes the start block, checkpoint: `true`) in [hooks.ts](./src/hooks.ts) to save an initial `State` using the `Indexer` object.
|
||||
|
||||
* Edit the custom hook function `createStateDiff` (triggered on a block) in [hooks.ts](./src/hooks.ts) to save the state in a `diff` `State` using the `Indexer` object. The default state (if exists) is updated.
|
||||
|
||||
* Edit the custom hook function `createStateCheckpoint` (triggered just before default and CLI checkpoint) in [hooks.ts](./src/hooks.ts) to save the state in a `checkpoint` `State` using the `Indexer` object.
|
||||
|
||||
* The existing example hooks in [hooks.ts](./src/hooks.ts) are for an `ERC20` contract.
|
||||
```bash
|
||||
yarn
|
||||
```
|
||||
|
||||
## Run
|
||||
|
||||
Follow the steps below or follow the [Demo](./demo.md)
|
||||
* In [packages/graph-node](../graph-node/), deploy an `Example` contract:
|
||||
|
||||
* Run the server:
|
||||
```bash
|
||||
yarn example:deploy
|
||||
```
|
||||
|
||||
* Set the returned address to the variable `$EXAMPLE_ADDRESS`:
|
||||
|
||||
```bash
|
||||
EXAMPLE_ADDRESS=<EXAMPLE_ADDRESS>
|
||||
```
|
||||
|
||||
* In [packages/graph-node/test/subgraph/example1/subgraph.yaml](../graph-node/test/subgraph/example1/subgraph.yaml):
|
||||
|
||||
* Set the source address for `Example1` datasource to the `EXAMPLE_ADDRESS`.
|
||||
* Set the `startBlock` less than or equal to the latest mined block.
|
||||
|
||||
* Build the example subgraph:
|
||||
|
||||
```bash
|
||||
yarn build:example
|
||||
```
|
||||
|
||||
* Run the job-runner:
|
||||
|
||||
```bash
|
||||
yarn job-runner
|
||||
```
|
||||
|
||||
* Run the watcher:
|
||||
|
||||
```bash
|
||||
yarn server
|
||||
```
|
||||
|
||||
GQL console: http://localhost:3008/graphql
|
||||
* The output from the block handler in the mapping code should be visible in the `job-runner` for each block.
|
||||
|
||||
* If the watcher is an `active` watcher:
|
||||
* Run the following GQL subscription at the graphql endpoint http://127.0.0.1:3008/graphql
|
||||
|
||||
* Run the job-runner:
|
||||
```graphql
|
||||
subscription {
|
||||
onEvent {
|
||||
event {
|
||||
__typename
|
||||
... on TestEvent {
|
||||
param1
|
||||
param2
|
||||
},
|
||||
},
|
||||
block {
|
||||
number
|
||||
hash
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
* In [packages/graph-node](../graph-node/), trigger the `Test` event by calling a example contract method:
|
||||
|
||||
```bash
|
||||
yarn example:test --address $EXAMPLE_ADDRESS
|
||||
```
|
||||
|
||||
* A `Test` event shall be visible in the subscription at endpoint.
|
||||
|
||||
* The subgraph entity `Category` should be updated in the database.
|
||||
|
||||
* An auto-generated `diff-staged` entry `State` should be added.
|
||||
|
||||
* Run the query for entity in at the endpoint:
|
||||
|
||||
```graphql
|
||||
query {
|
||||
category(
|
||||
block: { hash: "EVENT_BLOCK_HASH" },
|
||||
id: "1"
|
||||
) {
|
||||
__typename
|
||||
id
|
||||
count
|
||||
name
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
* Run the `getState` query at the endpoint to get the latest `State` for `EXAMPLE_ADDRESS`:
|
||||
|
||||
```graphql
|
||||
query {
|
||||
getState (
|
||||
blockHash: "EVENT_BLOCK_HASH"
|
||||
contractAddress: "EXAMPLE_ADDRESS"
|
||||
# kind: "checkpoint"
|
||||
# kind: "diff"
|
||||
kind: "diff_staged"
|
||||
) {
|
||||
cid
|
||||
block {
|
||||
cid
|
||||
hash
|
||||
number
|
||||
timestamp
|
||||
parentHash
|
||||
}
|
||||
contractAddress
|
||||
data
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
* `diff` states get created corresponding to the `diff_staged` states when their respective blocks reach the pruned region.
|
||||
|
||||
* In [packages/graph-test-watcher](./):
|
||||
|
||||
* After the `diff` state has been created, create a `checkpoint`:
|
||||
|
||||
```bash
|
||||
yarn job-runner
|
||||
yarn checkpoint create --address $EXAMPLE_ADDRESS
|
||||
```
|
||||
|
||||
* Run the server:
|
||||
* A `checkpoint` state should be created at the latest canonical block hash.
|
||||
|
||||
```bash
|
||||
yarn server
|
||||
```
|
||||
* Run the `getState` query again at the endpoint with the output `blockHash` and kind `checkpoint`.
|
||||
|
||||
* All the `State` entries can be seen in `pg-admin` in table `state`.
|
||||
|
||||
GQL console: http://localhost:3008/graphql
|
||||
|
||||
* To watch a contract:
|
||||
|
||||
```bash
|
||||
yarn watch:contract --address <contract-address> --kind <contract-kind> --checkpoint <true | false> --starting-block [block-number]
|
||||
```
|
||||
|
||||
* `address`: Address or identifier of the contract to be watched.
|
||||
* `kind`: Kind of the contract.
|
||||
* `checkpoint`: Turn checkpointing on (`true` | `false`).
|
||||
* `starting-block`: Starting block for the contract (default: `1`).
|
||||
|
||||
Examples:
|
||||
|
||||
Watch a contract with its address and checkpointing on:
|
||||
|
||||
```bash
|
||||
yarn watch:contract --address 0x1F78641644feB8b64642e833cE4AFE93DD6e7833 --kind ERC20 --checkpoint true
|
||||
```
|
||||
|
||||
Watch a contract with its identifier and checkpointing on:
|
||||
|
||||
```bash
|
||||
yarn watch:contract --address MyProtocol --kind protocol --checkpoint true
|
||||
```
|
||||
|
||||
* To fill a block range:
|
||||
|
||||
```bash
|
||||
yarn fill --start-block <from-block> --end-block <to-block>
|
||||
```
|
||||
|
||||
* `start-block`: Block number to start filling from.
|
||||
* `end-block`: Block number till which to fill.
|
||||
|
||||
* To create a checkpoint for a contract:
|
||||
|
||||
```bash
|
||||
yarn checkpoint create --address <contract-address> --block-hash [block-hash]
|
||||
```
|
||||
|
||||
* `address`: Address or identifier of the contract for which to create a checkpoint.
|
||||
* `block-hash`: Hash of a block (in the pruned region) at which to create the checkpoint (default: latest canonical block hash).
|
||||
|
||||
* To verify a checkpoint:
|
||||
|
||||
```bash
|
||||
yarn checkpoint verify --cid <checkpoint-cid>
|
||||
```
|
||||
|
||||
`cid`: CID of the checkpoint for which to verify.
|
||||
|
||||
* To reset the watcher to a previous block number:
|
||||
|
||||
* Reset watcher:
|
||||
|
||||
```bash
|
||||
yarn reset watcher --block-number <previous-block-number>
|
||||
```
|
||||
|
||||
* Reset job-queue:
|
||||
|
||||
```bash
|
||||
yarn reset job-queue
|
||||
```
|
||||
|
||||
* Reset state:
|
||||
|
||||
```bash
|
||||
yarn reset state --block-number <previous-block-number>
|
||||
```
|
||||
|
||||
* `block-number`: Block number to which to reset the watcher.
|
||||
|
||||
* To export and import the watcher state:
|
||||
|
||||
* In source watcher, export watcher state:
|
||||
|
||||
```bash
|
||||
yarn export-state --export-file [export-file-path] --block-number [snapshot-block-height]
|
||||
```
|
||||
|
||||
* `export-file`: Path of file to which to export the watcher data.
|
||||
* `block-number`: Block height at which to take snapshot for export.
|
||||
|
||||
* In target watcher, run job-runner:
|
||||
|
||||
```bash
|
||||
yarn job-runner
|
||||
```
|
||||
|
||||
* Import watcher state:
|
||||
|
||||
```bash
|
||||
yarn import-state --import-file <import-file-path>
|
||||
```
|
||||
|
||||
* `import-file`: Path of file from which to import the watcher data.
|
||||
|
||||
* Run server:
|
||||
|
||||
```bash
|
||||
yarn server
|
||||
```
|
||||
|
||||
* To inspect a CID:
|
||||
|
||||
```bash
|
||||
yarn inspect-cid --cid <cid>
|
||||
```
|
||||
|
||||
* `cid`: CID to be inspected.
|
||||
* The existing example hooks in [hooks.ts](./src/hooks.ts) are for an `ERC20` contract.
|
||||
|
@ -1,182 +0,0 @@
|
||||
# Demo
|
||||
|
||||
* The following core services need to be running for the demo:
|
||||
* [ipld-eth-db](https://github.com/cerc-io/ipld-eth-db)
|
||||
* Version: [v4.2.3-alpha](https://github.com/cerc-io/ipld-eth-db/releases/tag/v4.2.3-alpha)
|
||||
* [geth](https://github.com/cerc-io/go-ethereum)
|
||||
* State diffing service should use `ipld-eth-db` for database.
|
||||
* Version: [v1.10.26-statediff-4.2.2-alpha](https://github.com/cerc-io/go-ethereum/releases/tag/v1.10.26-statediff-4.2.2-alpha)
|
||||
* Endpoint: http://127.0.0.1:8545
|
||||
* [ipld-eth-server](https://github.com/cerc-io/ipld-eth-server)
|
||||
* Should use `ipld-eth-db` for database.
|
||||
* Version: [v4.2.3-alpha](https://github.com/cerc-io/ipld-eth-server/releases/tag/v4.2.3-alpha)
|
||||
* Endpoints:
|
||||
* GQL: http://127.0.0.1:8082/graphql
|
||||
* RPC: http://127.0.0.1:8081
|
||||
|
||||
* Create a postgres12 database for the watcher:
|
||||
|
||||
```bash
|
||||
sudo su - postgres
|
||||
|
||||
# If database already exists
|
||||
# dropdb graph-test-watcher
|
||||
|
||||
createdb graph-test-watcher
|
||||
```
|
||||
|
||||
* Create database for the job queue and enable the `pgcrypto` extension on them (https://github.com/timgit/pg-boss/blob/master/docs/usage.md#intro):
|
||||
|
||||
```bash
|
||||
# If database already exists
|
||||
# dropdb graph-test-watcher-job-queue
|
||||
|
||||
createdb graph-test-watcher-job-queue
|
||||
```
|
||||
|
||||
```
|
||||
postgres@tesla:~$ psql -U postgres -h localhost graph-test-watcher-job-queue
|
||||
Password for user postgres:
|
||||
psql (12.7 (Ubuntu 12.7-1.pgdg18.04+1))
|
||||
SSL connection (protocol: TLSv1.3, cipher: TLS_AES_256_GCM_SHA384, bits: 256, compression: off)
|
||||
Type "help" for help.
|
||||
|
||||
graph-test-watcher-job-queue=# CREATE EXTENSION pgcrypto;
|
||||
CREATE EXTENSION
|
||||
graph-test-watcher-job-queue=# exit
|
||||
```
|
||||
|
||||
* In the [config file](./environments/local.toml) update the `database` connection settings.
|
||||
|
||||
* In `watcher-ts` repo, follow the instructions in [Setup](../../README.md#setup) for installing and building packages.
|
||||
|
||||
```bash
|
||||
# After setup
|
||||
yarn && yarn build
|
||||
```
|
||||
|
||||
* In [packages/graph-node](../graph-node/), deploy an `Example` contract:
|
||||
|
||||
```bash
|
||||
yarn example:deploy
|
||||
```
|
||||
|
||||
* Set the returned address to the variable `$EXAMPLE_ADDRESS`:
|
||||
|
||||
```bash
|
||||
EXAMPLE_ADDRESS=<EXAMPLE_ADDRESS>
|
||||
```
|
||||
|
||||
* In [packages/graph-node/test/subgraph/example1/subgraph.yaml](../graph-node/test/subgraph/example1/subgraph.yaml):
|
||||
|
||||
* Set the source address for `Example1` datasource to the `EXAMPLE_ADDRESS`.
|
||||
* Set the `startBlock` less than or equal to the latest mined block.
|
||||
|
||||
* Build the example subgraph:
|
||||
|
||||
```bash
|
||||
yarn build:example
|
||||
```
|
||||
|
||||
* Run the job-runner:
|
||||
|
||||
```bash
|
||||
yarn job-runner
|
||||
```
|
||||
|
||||
* Run the watcher:
|
||||
|
||||
```bash
|
||||
yarn server
|
||||
```
|
||||
|
||||
* The output from the block handler in the mapping code should be visible in the `job-runner` for each block.
|
||||
|
||||
* Run the following GQL subscription at the graphql endpoint http://127.0.0.1:3008/graphql
|
||||
|
||||
```graphql
|
||||
subscription {
|
||||
onEvent {
|
||||
event {
|
||||
__typename
|
||||
... on TestEvent {
|
||||
param1
|
||||
param2
|
||||
},
|
||||
},
|
||||
block {
|
||||
number
|
||||
hash
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
* In [packages/graph-node](../graph-node/), trigger the `Test` event by calling a example contract method:
|
||||
|
||||
```bash
|
||||
yarn example:test --address $EXAMPLE_ADDRESS
|
||||
```
|
||||
|
||||
* A `Test` event shall be visible in the subscription at endpoint.
|
||||
|
||||
* The subgraph entity `Category` should be updated in the database.
|
||||
|
||||
* An auto-generated `diff-staged` entry `State` should be added.
|
||||
|
||||
* Run the query for entity in at the endpoint:
|
||||
|
||||
```graphql
|
||||
query {
|
||||
category(
|
||||
block: { hash: "EVENT_BLOCK_HASH" },
|
||||
id: "1"
|
||||
) {
|
||||
__typename
|
||||
id
|
||||
count
|
||||
name
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
* Run the `getState` query at the endpoint to get the latest `State` for `EXAMPLE_ADDRESS`:
|
||||
|
||||
```graphql
|
||||
query {
|
||||
getState (
|
||||
blockHash: "EVENT_BLOCK_HASH"
|
||||
contractAddress: "EXAMPLE_ADDRESS"
|
||||
# kind: "checkpoint"
|
||||
# kind: "diff"
|
||||
kind: "diff_staged"
|
||||
) {
|
||||
cid
|
||||
block {
|
||||
cid
|
||||
hash
|
||||
number
|
||||
timestamp
|
||||
parentHash
|
||||
}
|
||||
contractAddress
|
||||
data
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
* `diff` states get created corresponding to the `diff_staged` states when their respective blocks reach the pruned region.
|
||||
|
||||
* In [packages/graph-test-watcher](./):
|
||||
|
||||
* After the `diff` state has been created, create a `checkpoint`:
|
||||
|
||||
```bash
|
||||
yarn checkpoint create --address $EXAMPLE_ADDRESS
|
||||
```
|
||||
|
||||
* A `checkpoint` state should be created at the latest canonical block hash.
|
||||
|
||||
* Run the `getState` query again at the endpoint with the output `blockHash` and kind `checkpoint`.
|
||||
|
||||
* All the `State` entries can be seen in `pg-admin` in table `state`.
|
@ -1,192 +1,281 @@
|
||||
# mobymask-watcher
|
||||
# MobyMask Watcher
|
||||
|
||||
First try the [mobymask demo in stack orchestrator](https://github.com/cerc-io/stack-orchestrator/tree/main/app/data/stacks/mobymask) to quickly get started. Advanced users can see [here](/docs/README.md) for instructions on setting up a local environment by hand.
|
||||
|
||||
## Setup
|
||||
|
||||
* Run the following command to install required packages:
|
||||
Run the following command to install required packages:
|
||||
|
||||
```bash
|
||||
yarn
|
||||
```bash
|
||||
yarn && yarn build
|
||||
```
|
||||
|
||||
If the watcher is "lazy", run the server:
|
||||
|
||||
```bash
|
||||
yarn server
|
||||
```
|
||||
|
||||
GQL console: http://localhost:3010/graphql
|
||||
|
||||
If the watcher is "active", run the job-runner:
|
||||
|
||||
```bash
|
||||
yarn job-runner
|
||||
```
|
||||
then the server:
|
||||
|
||||
```bash
|
||||
yarn server
|
||||
```
|
||||
|
||||
Next, clone the MobyMask repo and checkout this branch:
|
||||
|
||||
```bash
|
||||
git clone https://github.com/cerc-io/MobyMask && cd MobyMask
|
||||
git checkout use-laconic-watcher-as-hosted-index
|
||||
```
|
||||
|
||||
Install the packages:
|
||||
```bash
|
||||
yarn
|
||||
```
|
||||
|
||||
Deploy the contract:
|
||||
```bash
|
||||
cd packages/hardhat
|
||||
|
||||
yarn deploy
|
||||
# deploying "PhisherRegistry" (tx: 0xaebeb2e883ece1f679304ec46f5dc61ca74f9e168427268a7dfa8802195b8de0)...: deployed at 0xMobyAddress with 2306221 gas
|
||||
# $ hardhat run scripts/publish.js
|
||||
# ✅ Published contracts to the subgraph package.
|
||||
# Done in 14.28s.
|
||||
```
|
||||
|
||||
Export the address of the deployed contract to a shell variable for later use:
|
||||
|
||||
```bash
|
||||
export MOBY_ADDRESS="0xMobyAddress"
|
||||
```
|
||||
|
||||
Run the following GQL mutation in watcher GraphQL endpoint http://127.0.0.1:3010/graphql
|
||||
|
||||
```graphql
|
||||
mutation {
|
||||
watchContract(
|
||||
address: "MOBY_ADDRESS"
|
||||
kind: "PhisherRegistry"
|
||||
checkpoint: true
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
Get the latest block
|
||||
|
||||
```graphql
|
||||
query {
|
||||
latestBlock {
|
||||
hash
|
||||
number
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
* Create a postgres12 database for the watcher:
|
||||
Run the following GQL query in GraphQL endpoint
|
||||
|
||||
```graphql
|
||||
query {
|
||||
isPhisher(
|
||||
blockHash: "LATEST_BLOCK_HASH"
|
||||
contractAddress: "MOBY_ADDRESS"
|
||||
key0: "TWT:phishername"
|
||||
) {
|
||||
value
|
||||
proof {
|
||||
data
|
||||
}
|
||||
}
|
||||
isMember(
|
||||
blockHash: "LATEST_BLOCK_HASH"
|
||||
contractAddress: "MOBY_ADDRESS"
|
||||
key0: "TWT:membername"
|
||||
) {
|
||||
value
|
||||
proof {
|
||||
data
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Run the following GQL subscription in generated watcher GraphQL endpoint:
|
||||
|
||||
```graphql
|
||||
subscription {
|
||||
onEvent {
|
||||
event {
|
||||
__typename
|
||||
... on PhisherStatusUpdatedEvent {
|
||||
entity
|
||||
isPhisher
|
||||
},
|
||||
... on MemberStatusUpdatedEvent {
|
||||
entity
|
||||
isMember
|
||||
}
|
||||
},
|
||||
block {
|
||||
number
|
||||
hash
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Update isPhiser and isMember lists with names
|
||||
|
||||
```bash
|
||||
yarn claimPhisher --contract $MOBY_ADDRESS --name phisherName
|
||||
```
|
||||
|
||||
```bash
|
||||
yarn claimMember --contract $MOBY_ADDRESS --name memberName
|
||||
```
|
||||
|
||||
- The events should be visible in the subscription at GQL endpoint. Note down the event blockHash from result.
|
||||
|
||||
- The isMember and isPhisher lists should be indexed. Check the database (mobymask-watcher) tables `is_phisher` and `is_member`, there should be entries at the event blockHash and the value should be true. The data is indexed in `handleEvent` method in the [hooks file](./src/hooks.ts).
|
||||
|
||||
Update the the previous query with event blockHash and check isPhisher and isMember in GraphQL playground
|
||||
|
||||
```graphql
|
||||
query {
|
||||
isPhisher(
|
||||
blockHash: "EVENT_BLOCK_HASH"
|
||||
contractAddress: "MOBY_ADDRESS",
|
||||
key0: "TWT:phishername"
|
||||
) {
|
||||
value
|
||||
proof {
|
||||
data
|
||||
}
|
||||
}
|
||||
|
||||
isMember(
|
||||
blockHash: "EVENT_BLOCK_HASH"
|
||||
contractAddress: "MOBY_ADDRESS",
|
||||
key0: "TWT:membername"
|
||||
) {
|
||||
value
|
||||
proof {
|
||||
data
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
The data is fetched from watcher database as it is already indexed.
|
||||
|
||||
## Additional Commands
|
||||
|
||||
To watch a contract, run:
|
||||
|
||||
```bash
|
||||
yarn watch:contract --address <contract-address> --kind <contract-kind> --checkpoint <true | false> --starting-block [block-number]
|
||||
```
|
||||
where:
|
||||
- `address`: Address or identifier of the contract to be watched.
|
||||
- `kind`: Kind of the contract.
|
||||
- `checkpoint`: Turn checkpointing on (`true` | `false`).
|
||||
- `starting-block`: Starting block for the contract (default: `1`).
|
||||
|
||||
Examples:
|
||||
|
||||
Watch a contract with its address and checkpointing on:
|
||||
|
||||
```bash
|
||||
yarn watch:contract --address 0x1F78641644feB8b64642e833cE4AFE93DD6e7833 --kind ERC20 --checkpoint true
|
||||
```
|
||||
|
||||
```bash
|
||||
sudo su - postgres
|
||||
createdb mobymask-watcher
|
||||
```
|
||||
Watch a contract with its identifier and checkpointing on:
|
||||
|
||||
* If the watcher is an `active` watcher:
|
||||
```bash
|
||||
yarn watch:contract --address MyProtocol --kind protocol --checkpoint true
|
||||
```
|
||||
|
||||
Create database for the job queue and enable the `pgcrypto` extension on them (https://github.com/timgit/pg-boss/blob/master/docs/usage.md#intro):
|
||||
To fill a block range:
|
||||
|
||||
```
|
||||
createdb mobymask-watcher-job-queue
|
||||
```
|
||||
```bash
|
||||
yarn fill --start-block <from-block> --end-block <to-block>
|
||||
```
|
||||
|
||||
```
|
||||
postgres@tesla:~$ psql -U postgres -h localhost mobymask-watcher-job-queue
|
||||
Password for user postgres:
|
||||
psql (12.7 (Ubuntu 12.7-1.pgdg18.04+1))
|
||||
SSL connection (protocol: TLSv1.3, cipher: TLS_AES_256_GCM_SHA384, bits: 256, compression: off)
|
||||
Type "help" for help.
|
||||
* `start-block`: Block number to start filling from.
|
||||
* `end-block`: Block number till which to fill.
|
||||
|
||||
mobymask-watcher-job-queue=# CREATE EXTENSION pgcrypto;
|
||||
CREATE EXTENSION
|
||||
mobymask-watcher-job-queue=# exit
|
||||
```
|
||||
To create a checkpoint for a contract:
|
||||
|
||||
* In the [config file](./environments/local.toml):
|
||||
```bash
|
||||
yarn checkpoint create --address <contract-address> --block-hash [block-hash]
|
||||
```
|
||||
|
||||
* Update the database connection settings.
|
||||
* `address`: Address or identifier of the contract for which to create a checkpoint.
|
||||
* `block-hash`: Hash of a block (in the pruned region) at which to create the checkpoint (default: latest canonical block hash).
|
||||
|
||||
* Update the `upstream` config and provide the `ipld-eth-server` GQL API endpoint.
|
||||
To reset the watcher to a previous block number:
|
||||
|
||||
* Update the `server` config with state checkpoint settings.
|
||||
```bash
|
||||
yarn reset watcher --block-number <previous-block-number>
|
||||
```
|
||||
|
||||
## Customize
|
||||
Reset job-queue:
|
||||
|
||||
* Indexing on an event:
|
||||
```bash
|
||||
yarn reset job-queue
|
||||
```
|
||||
|
||||
* Edit the custom hook function `handleEvent` (triggered on an event) in [hooks.ts](./src/hooks.ts) to perform corresponding indexing using the `Indexer` object.
|
||||
Reset state:
|
||||
|
||||
* While using the indexer storage methods for indexing, pass `diff` as true if default state is desired to be generated using the state variables being indexed.
|
||||
```bash
|
||||
yarn reset state --block-number <previous-block-number>
|
||||
```
|
||||
|
||||
* Generating state:
|
||||
* `block-number`: Block number to which to reset the watcher.
|
||||
|
||||
* Edit the custom hook function `createInitialState` (triggered if the watcher passes the start block, checkpoint: `true`) in [hooks.ts](./src/hooks.ts) to save an initial `State` using the `Indexer` object.
|
||||
To export and import the watcher state:
|
||||
|
||||
* Edit the custom hook function `createStateDiff` (triggered on a block) in [hooks.ts](./src/hooks.ts) to save the state in a `diff` `State` using the `Indexer` object. The default state (if exists) is updated.
|
||||
In the source watcher, export watcher state:
|
||||
|
||||
* Edit the custom hook function `createStateCheckpoint` (triggered just before default and CLI checkpoint) in [hooks.ts](./src/hooks.ts) to save the state in a `checkpoint` `State` using the `Indexer` object.
|
||||
```bash
|
||||
yarn export-state --export-file [export-file-path] --block-number [snapshot-block-height]
|
||||
```
|
||||
|
||||
## Run
|
||||
* `export-file`: Path of file to which to export the watcher data.
|
||||
* `block-number`: Block height at which to take snapshot for export.
|
||||
|
||||
Follow the steps below or follow the [Demo](./demo.md)
|
||||
In the target watcher, run job-runner:
|
||||
|
||||
* Run the server:
|
||||
```bash
|
||||
yarn job-runner
|
||||
```
|
||||
|
||||
```bash
|
||||
yarn server
|
||||
```
|
||||
Import watcher state:
|
||||
|
||||
GQL console: http://localhost:3010/graphql
|
||||
```bash
|
||||
yarn import-state --import-file <import-file-path>
|
||||
```
|
||||
|
||||
* If the watcher is an `active` watcher:
|
||||
* `import-file`: Path of file from which to import the watcher data.
|
||||
|
||||
* Run the job-runner:
|
||||
Run server:
|
||||
|
||||
```bash
|
||||
yarn job-runner
|
||||
```
|
||||
```bash
|
||||
yarn server
|
||||
```
|
||||
|
||||
* Run the server:
|
||||
To inspect a CID:
|
||||
|
||||
```bash
|
||||
yarn server
|
||||
```
|
||||
```bash
|
||||
yarn inspect-cid --cid <cid>
|
||||
```
|
||||
|
||||
GQL console: http://localhost:3010/graphql
|
||||
|
||||
* To watch a contract:
|
||||
|
||||
```bash
|
||||
yarn watch:contract --address <contract-address> --kind <contract-kind> --checkpoint <true | false> --starting-block [block-number]
|
||||
```
|
||||
|
||||
* `address`: Address or identifier of the contract to be watched.
|
||||
* `kind`: Kind of the contract.
|
||||
* `checkpoint`: Turn checkpointing on (`true` | `false`).
|
||||
* `starting-block`: Starting block for the contract (default: `1`).
|
||||
|
||||
Examples:
|
||||
|
||||
Watch a contract with its address and checkpointing on:
|
||||
|
||||
```bash
|
||||
yarn watch:contract --address 0x1F78641644feB8b64642e833cE4AFE93DD6e7833 --kind ERC20 --checkpoint true
|
||||
```
|
||||
|
||||
Watch a contract with its identifier and checkpointing on:
|
||||
|
||||
```bash
|
||||
yarn watch:contract --address MyProtocol --kind protocol --checkpoint true
|
||||
```
|
||||
|
||||
* To fill a block range:
|
||||
|
||||
```bash
|
||||
yarn fill --start-block <from-block> --end-block <to-block>
|
||||
```
|
||||
|
||||
* `start-block`: Block number to start filling from.
|
||||
* `end-block`: Block number till which to fill.
|
||||
|
||||
* To create a checkpoint for a contract:
|
||||
|
||||
```bash
|
||||
yarn checkpoint create --address <contract-address> --block-hash [block-hash]
|
||||
```
|
||||
|
||||
* `address`: Address or identifier of the contract for which to create a checkpoint.
|
||||
* `block-hash`: Hash of a block (in the pruned region) at which to create the checkpoint (default: latest canonical block hash).
|
||||
|
||||
* To reset the watcher to a previous block number:
|
||||
|
||||
* Reset watcher:
|
||||
|
||||
```bash
|
||||
yarn reset watcher --block-number <previous-block-number>
|
||||
```
|
||||
|
||||
* Reset job-queue:
|
||||
|
||||
```bash
|
||||
yarn reset job-queue
|
||||
```
|
||||
|
||||
* Reset state:
|
||||
|
||||
```bash
|
||||
yarn reset state --block-number <previous-block-number>
|
||||
```
|
||||
|
||||
* `block-number`: Block number to which to reset the watcher.
|
||||
|
||||
* To export and import the watcher state:
|
||||
|
||||
* In source watcher, export watcher state:
|
||||
|
||||
```bash
|
||||
yarn export-state --export-file [export-file-path] --block-number [snapshot-block-height]
|
||||
```
|
||||
|
||||
* `export-file`: Path of file to which to export the watcher data.
|
||||
* `block-number`: Block height at which to take snapshot for export.
|
||||
|
||||
* In target watcher, run job-runner:
|
||||
|
||||
```bash
|
||||
yarn job-runner
|
||||
```
|
||||
|
||||
* Import watcher state:
|
||||
|
||||
```bash
|
||||
yarn import-state --import-file <import-file-path>
|
||||
```
|
||||
|
||||
* `import-file`: Path of file from which to import the watcher data.
|
||||
|
||||
* Run server:
|
||||
|
||||
```bash
|
||||
yarn server
|
||||
```
|
||||
|
||||
* To inspect a CID:
|
||||
|
||||
```bash
|
||||
yarn inspect-cid --cid <cid>
|
||||
```
|
||||
|
||||
* `cid`: CID to be inspected.
|
||||
* `cid`: CID to be inspected.
|
||||
|
@ -1,219 +0,0 @@
|
||||
# Demo
|
||||
|
||||
* The following core services need to be running for the demo:
|
||||
* [ipld-eth-db](https://github.com/cerc-io/ipld-eth-db)
|
||||
* Version: [v4.2.3-alpha](https://github.com/cerc-io/ipld-eth-db/releases/tag/v4.2.3-alpha)
|
||||
* [geth](https://github.com/cerc-io/go-ethereum)
|
||||
* State diffing service should use `ipld-eth-db` for database.
|
||||
* Version: [v1.10.26-statediff-4.2.2-alpha](https://github.com/cerc-io/go-ethereum/releases/tag/v1.10.26-statediff-4.2.2-alpha)
|
||||
* Endpoint: http://127.0.0.1:8545
|
||||
* [ipld-eth-server](https://github.com/cerc-io/ipld-eth-server)
|
||||
* Should use `ipld-eth-db` for database.
|
||||
* Version: [v4.2.3-alpha](https://github.com/cerc-io/ipld-eth-server/releases/tag/v4.2.3-alpha)
|
||||
* Endpoints:
|
||||
* GQL: http://127.0.0.1:8082/graphql
|
||||
* RPC: http://127.0.0.1:8081
|
||||
|
||||
* Create a postgres12 database for the watcher:
|
||||
|
||||
```bash
|
||||
sudo su - postgres
|
||||
|
||||
# If database already exists
|
||||
# dropdb mobymask-watcher
|
||||
|
||||
createdb mobymask-watcher
|
||||
```
|
||||
|
||||
* Create database for the job queue and enable the `pgcrypto` extension on them (https://github.com/timgit/pg-boss/blob/master/docs/usage.md#intro):
|
||||
|
||||
```bash
|
||||
# If database already exists
|
||||
# dropdb mobymask-watcher-job-queue
|
||||
|
||||
createdb mobymask-watcher-job-queue
|
||||
```
|
||||
|
||||
```
|
||||
postgres@tesla:~$ psql -U postgres -h localhost mobymask-watcher-job-queue
|
||||
Password for user postgres:
|
||||
psql (12.7 (Ubuntu 12.7-1.pgdg18.04+1))
|
||||
SSL connection (protocol: TLSv1.3, cipher: TLS_AES_256_GCM_SHA384, bits: 256, compression: off)
|
||||
Type "help" for help.
|
||||
|
||||
mobymask-watcher-job-queue=# CREATE EXTENSION pgcrypto;
|
||||
CREATE EXTENSION
|
||||
mobymask-watcher-job-queue=# exit
|
||||
```
|
||||
|
||||
* In the [config file](./environments/local.toml) update the `database` connection settings.
|
||||
|
||||
* In `watcher-ts` repo, follow the instructions in [Setup](../../README.md#setup) for installing and building packages.
|
||||
|
||||
```bash
|
||||
# After setup
|
||||
yarn && yarn build
|
||||
```
|
||||
|
||||
* Run the job-runner:
|
||||
|
||||
```bash
|
||||
yarn job-runner
|
||||
```
|
||||
|
||||
* Change directory to `packages/mobymask-watcher/` and run the watcher:
|
||||
|
||||
```bash
|
||||
yarn server
|
||||
```
|
||||
|
||||
* Clone the [MobyMask](https://github.com/cerc-io/MobyMask) repo.
|
||||
|
||||
* Checkout to the branch with changes for using this watcher:
|
||||
|
||||
```bash
|
||||
# In MobyMask repo.
|
||||
git checkout use-laconic-watcher-as-hosted-index
|
||||
```
|
||||
|
||||
* Run yarn to install the packages
|
||||
|
||||
```bash
|
||||
yarn
|
||||
```
|
||||
|
||||
* Deploy the contract:
|
||||
|
||||
```bash
|
||||
cd packages/hardhat
|
||||
|
||||
yarn deploy
|
||||
# deploying "PhisherRegistry" (tx: 0xaebeb2e883ece1f679304ec46f5dc61ca74f9e168427268a7dfa8802195b8de0)...: deployed at <MOBY_ADDRESS> with 2306221 gas
|
||||
# $ hardhat run scripts/publish.js
|
||||
# ✅ Published contracts to the subgraph package.
|
||||
# Done in 14.28s.
|
||||
```
|
||||
|
||||
Export the address of the deployed contract to a shell variable for later use:
|
||||
|
||||
```bash
|
||||
export MOBY_ADDRESS="<MOBY_ADDRESS>"
|
||||
```
|
||||
|
||||
* Run the following GQL mutation in watcher GraphQL endpoint http://127.0.0.1:3010/graphql
|
||||
|
||||
```graphql
|
||||
mutation {
|
||||
watchContract(
|
||||
address: "MOBY_ADDRESS"
|
||||
kind: "PhisherRegistry"
|
||||
checkpoint: true
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
* Get the latest block
|
||||
|
||||
```graphql
|
||||
query {
|
||||
latestBlock {
|
||||
hash
|
||||
number
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
* Run the following GQL query in GraphQL endpoint
|
||||
|
||||
```graphql
|
||||
query {
|
||||
isPhisher(
|
||||
blockHash: "LATEST_BLOCK_HASH"
|
||||
contractAddress: "MOBY_ADDRESS"
|
||||
key0: "TWT:phishername"
|
||||
) {
|
||||
value
|
||||
proof {
|
||||
data
|
||||
}
|
||||
}
|
||||
isMember(
|
||||
blockHash: "LATEST_BLOCK_HASH"
|
||||
contractAddress: "MOBY_ADDRESS"
|
||||
key0: "TWT:membername"
|
||||
) {
|
||||
value
|
||||
proof {
|
||||
data
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
* Run the following GQL subscription in generated watcher GraphQL endpoint:
|
||||
|
||||
```graphql
|
||||
subscription {
|
||||
onEvent {
|
||||
event {
|
||||
__typename
|
||||
... on PhisherStatusUpdatedEvent {
|
||||
entity
|
||||
isPhisher
|
||||
},
|
||||
... on MemberStatusUpdatedEvent {
|
||||
entity
|
||||
isMember
|
||||
}
|
||||
},
|
||||
block {
|
||||
number
|
||||
hash
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
* Update isPhiser and isMember lists with names
|
||||
|
||||
```bash
|
||||
yarn claimPhisher --contract $MOBY_ADDRESS --name phisherName
|
||||
```
|
||||
|
||||
```bash
|
||||
yarn claimMember --contract $MOBY_ADDRESS --name memberName
|
||||
```
|
||||
|
||||
* The events should be visible in the subscription at GQL endpoint. Note down the event blockHash from result.
|
||||
|
||||
* The isMember and isPhisher lists should be indexed. Check the database (mobymask-watcher) tables `is_phisher` and `is_member`, there should be entries at the event blockHash and the value should be true. The data is indexed in `handleEvent` method in the [hooks file](./src/hooks.ts).
|
||||
|
||||
* Update the the previous query with event blockHash and check isPhisher and isMember in GraphQL playground
|
||||
|
||||
```graphql
|
||||
query {
|
||||
isPhisher(
|
||||
blockHash: "EVENT_BLOCK_HASH"
|
||||
contractAddress: "MOBY_ADDRESS",
|
||||
key0: "TWT:phishername"
|
||||
) {
|
||||
value
|
||||
proof {
|
||||
data
|
||||
}
|
||||
}
|
||||
|
||||
isMember(
|
||||
blockHash: "EVENT_BLOCK_HASH"
|
||||
contractAddress: "MOBY_ADDRESS",
|
||||
key0: "TWT:membername"
|
||||
) {
|
||||
value
|
||||
proof {
|
||||
data
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
The data is fetched from watcher database as it is already indexed.
|
Loading…
Reference in New Issue
Block a user