Skip to content

Commit

Permalink
Add watcher for Polls contract (#1) (#1)
Browse files Browse the repository at this point in the history
* Yarn init and setup lerna

* Generate watcher for Polls contract

* Add custom methods for unhandled types

* Fix methods to save and load values of unhandled type from local DB

* Set PropColMaps for custom methods

---------

Co-authored-by: Dhruv Srivastava <dhruvdhs.ds@gmail.com>
  • Loading branch information
nikugogoi and dafaqdhruv authored Apr 11, 2023
1 parent a1e0ca0 commit 7b857ec
Show file tree
Hide file tree
Showing 61 changed files with 13,503 additions and 0 deletions.
5 changes: 5 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
node_modules/
dist/
out/
.vscode

1 change: 1 addition & 0 deletions .npmrc
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
@cerc-io:registry=https://git.vdb.to/api/packages/cerc-io/npm/
8 changes: 8 additions & 0 deletions lerna.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"packages": [
"packages/*"
],
"useWorkspaces": true,
"version": "0.0.0",
"npmClient": "yarn"
}
15 changes: 15 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{
"name": "azimuth-watcher-ts",
"private": true,
"license": "AGPL-3.0",
"workspaces": [
"packages/*"
],
"scripts": {
"build": "lerna run build --stream",
"lint": "lerna run lint --stream -- --max-warnings=0"
},
"devDependencies": {
"lerna": "^6.6.1"
}
}
2 changes: 2 additions & 0 deletions packages/polls-watcher/.eslintignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
# Don't lint build output.
dist
28 changes: 28 additions & 0 deletions packages/polls-watcher/.eslintrc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
{
"env": {
"browser": true,
"es2021": true
},
"extends": [
"semistandard",
"plugin:@typescript-eslint/recommended"
],
"parser": "@typescript-eslint/parser",
"parserOptions": {
"ecmaVersion": 12,
"sourceType": "module"
},
"plugins": [
"@typescript-eslint"
],
"rules": {
"indent": ["error", 2, { "SwitchCase": 1 }],
"@typescript-eslint/no-explicit-any": "off",
"@typescript-eslint/explicit-module-boundary-types": [
"warn",
{
"allowArgumentsExplicitlyTypedAsAny": true
}
]
}
}
204 changes: 204 additions & 0 deletions packages/polls-watcher/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,204 @@
# polls-watcher

## Setup

* Run the following command to install required packages:

```bash
yarn
```

* Create a postgres12 database for the watcher:

```bash
sudo su - postgres
createdb polls-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 polls-watcher-job-queue
```

```
postgres@tesla:~$ psql -U postgres -h localhost polls-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.
polls-watcher-job-queue=# CREATE EXTENSION pgcrypto;
CREATE EXTENSION
polls-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.

### GQL Caching

To enable GQL requests caching:

* Update the `server.gqlCache` config with required settings.

* In the GQL [schema file](./src/schema.gql), use the `cacheControl` directive to apply cache hints at schema level.

* Eg. Set `inheritMaxAge` to true for non-scalar fields of a type.

* In the GQL [resolvers file](./src/resolvers.ts), uncomment the `setGQLCacheHints()` calls in resolvers for required queries.

## Run

* If the watcher is a `lazy` watcher:

* Run the server:

```bash
yarn server
```

GQL console: http://localhost:3009/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:3009/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.
66 changes: 66 additions & 0 deletions packages/polls-watcher/environments/local.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
[server]
host = "127.0.0.1"
port = 3009
kind = "lazy"

# Checkpointing state.
checkpointing = true

# Checkpoint interval in number of blocks.
checkpointInterval = 2000

# Enable state creation
# CAUTION: Disable only if state creation is not desired or can be filled subsequently
enableState = true

# Boolean to filter logs by contract.
filterLogs = false

# Max block range for which to return events in eventsInRange GQL query.
# Use -1 for skipping check on block range.
maxEventsBlockRange = 1000

# GQL cache settings
[server.gqlCache]
enabled = true

# Max in-memory cache size (in bytes) (default 8 MB)
# maxCacheSize

# GQL cache-control max-age settings (in seconds)
maxAge = 15

[metrics]
host = "127.0.0.1"
port = 9000
[metrics.gql]
port = 9001

[database]
type = "postgres"
host = "localhost"
port = 5432
database = "polls-watcher"
username = "postgres"
password = "postgres"
synchronize = true
logging = false

[upstream]
[upstream.ethServer]
gqlApiEndpoint = "http://127.0.0.1:8082/graphql"
rpcProviderEndpoint = "http://127.0.0.1:8081"

[upstream.cache]
name = "requests"
enabled = false
deleteOnStart = false

[jobQueue]
dbConnectionString = "postgres://postgres:postgres@localhost/polls-watcher-job-queue"
maxCompletionLagInSecs = 300
jobDelayInMilliSecs = 100
eventsInBatch = 50
blockDelayInMilliSecs = 2000
prefetchBlocksInMem = true
prefetchBlockCount = 10
Loading

0 comments on commit 7b857ec

Please sign in to comment.