Skip to content

Commit

Permalink
feat(ponder-ens): introduce plugin architecture (#3)
Browse files Browse the repository at this point in the history
This change allows defining simple ponder plugins per supported subnames. Only one plugin can be active during indexing, and to select it, please set the `ACTIVE_PLUGIN` env var to the name of one of the available plugins (see `src/plugins` directory). For example:
```
ACTIVE_PLUGIN=eth
ACTIVE_PLUGIN=base.eth
```

Also, please [make sure to know](https://ponder.sh/docs/getting-started/database#database-schema) how to use the `DATABASE_SCHEMA` env var.

### Examples

Running indexer with the requested subname plugin for ponder:

```
ACTIVE_PLUGIN=base.eth DATABASE_SCHEMA=my_base_eth pnpm start 
```
  • Loading branch information
tk-o authored Jan 8, 2025
1 parent 0f2b36a commit 7bdc380
Show file tree
Hide file tree
Showing 40 changed files with 4,544 additions and 602 deletions.
19 changes: 19 additions & 0 deletions .env.local.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# RPC configuration
# Follow the format: RPC_URL_{chainId}={rpcUrl}

RPC_URL_1=https://ethereum-rpc.publicnode.com
RPC_URL_8453=https://base-rpc.publicnode.com
RPC_URL_59144=https://linea-rpc.publicnode.com

# Identify which indexer plugin to activate (see `src/plugins` for available plugins)

ACTIVE_PLUGIN=base.eth

# Database configuration

# This is where the indexer will create the tables defined in ponder.schema.ts
# No two indexer instances can use the same database schema at the same time. This prevents data corruption.
# @link https://ponder.sh/docs/api-reference/database#database-schema-rules
DATABASE_SCHEMA=subname_index_base.eth
# The indexer will use Postgres with that as the connection string. If not defined, the indexer will use PSlite.
DATABASE_URL=postgresql://dbuser:abcd1234@localhost:5432/my_database
31 changes: 31 additions & 0 deletions .github/workflows/static-analysis.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
name: Static Analysis

on:
push:
branches:
- main
pull_request:
branches:
- main

jobs:
biome-ci:
runs-on: ubuntu-latest

steps:
- name: Checkout repository
uses: actions/checkout@v3

- name: Set up Node.js
uses: actions/setup-node@v3
with:
node-version: '18'

- name: Install pnpm
run: npm install -g pnpm

- name: Install dependencies
run: pnpm install

- name: Run Biome CI
run: pnpm biome ci
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -160,7 +160,7 @@ various resources use both null and zeroAddress to indicate emptiness, this is h

### ens indexing plugin

l2 ens deployments are very similar — write plugin to make configuring source addresses easy and pass node that domains in these handlers are implicitly parented to (assuming that l2 deployments make nodes against the NAMEHASH_ZERO i.e. every name is basically a 2LD)
l2 ens deployments are very similar — write plugin to make configuring source addresses easy and pass node that domains in these handlers are implicitly parented to (assuming that l2 deployments make nodes against the ROOT_NODE i.e. every name is basically a 2LD)

### registry

Expand Down
2 changes: 1 addition & 1 deletion biome.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
},
"files": {
"ignoreUnknown": false,
"ignore": []
"ignore": [".ponder", "generated"]
},
"formatter": {
"enabled": true,
Expand Down
5 changes: 4 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
},
"dependencies": {
"hono": "^4.6.14",
"ponder": "^0.8.8",
"ponder": "^0.8.17",
"viem": "^2.21.57"
},
"devDependencies": {
Expand All @@ -23,5 +23,8 @@
},
"engines": {
"node": ">=18.14"
},
"resolutions": {
"vite": "5.1.8"
}
}
51 changes: 27 additions & 24 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

123 changes: 27 additions & 96 deletions ponder.config.ts
Original file line number Diff line number Diff line change
@@ -1,98 +1,29 @@
import { createConfig, factory, mergeAbis } from "ponder";
import { http, getAbiItem } from "viem";
import { ACTIVE_PLUGIN } from "./src/lib/plugin-helpers";
import {
activate as activateEthBase,
config as ethBaseConfig,
ownedName as ethBaseOwnedName,
} from "./src/plugins/base.eth/ponder.config";
import {
activate as activateEth,
config as ethConfig,
ownedName as ethOwnedName,
} from "./src/plugins/eth/ponder.config";

import { BaseRegistrar } from "./abis/BaseRegistrar";
import { EthRegistrarController } from "./abis/EthRegistrarController";
import { EthRegistrarControllerOld } from "./abis/EthRegistrarControllerOld";
import { LegacyPublicResolver } from "./abis/LegacyPublicResolver";
import { NameWrapper } from "./abis/NameWrapper";
import { Registry } from "./abis/Registry";
import { Resolver } from "./abis/Resolver";
type AllConfigs = typeof ethConfig & typeof ethBaseConfig;

// just for testing...
const END_BLOCK = 12_000_000;

const RESOLVER_ABI = mergeAbis([LegacyPublicResolver, Resolver]);

const REGISTRY_OLD_ADDRESS = "0x314159265dd8dbb310642f98f50c066173c1259b";
const REGISTRY_ADDRESS = "0x00000000000C2E074eC69A0dFb2997BA6C7d2e1e";

const BASE_REGISTRAR_ADDRESS = "0x57f1887a8BF19b14fC0dF6Fd9B2acc9Af147eA85";
const ETH_REGISTRAR_CONTROLLER_OLD_ADDRESS = "0x283Af0B28c62C092C9727F1Ee09c02CA627EB7F5";
const ETH_REGISTRAR_CONTROLLER_ADDRESS = "0x253553366Da8546fC250F225fe3d25d0C782303b";
const NAME_WRAPPER_ADDRESS = "0xD4416b13d2b3a9aBae7AcD5D6C2BbDBE25686401";

export default createConfig({
networks: {
mainnet: {
chainId: 1,
transport: http(process.env.PONDER_RPC_URL_1),
},
},
contracts: {
RegistryOld: {
network: "mainnet",
abi: Registry,
address: REGISTRY_OLD_ADDRESS,
startBlock: 3327417,
endBlock: END_BLOCK,
},
Registry: {
network: "mainnet",
abi: Registry,
address: REGISTRY_ADDRESS,
startBlock: 9380380,
endBlock: END_BLOCK,
},
OldRegistryResolvers: {
network: "mainnet",
abi: RESOLVER_ABI,
address: factory({
address: REGISTRY_OLD_ADDRESS,
event: getAbiItem({ abi: Registry, name: "NewResolver" }),
parameter: "resolver",
}),
startBlock: 9380380,
endBlock: END_BLOCK,
},
Resolver: {
network: "mainnet",
abi: RESOLVER_ABI,
address: factory({
address: REGISTRY_ADDRESS,
event: getAbiItem({ abi: Registry, name: "NewResolver" }),
parameter: "resolver",
}),
startBlock: 9380380,
endBlock: END_BLOCK,
},
BaseRegistrar: {
network: "mainnet",
abi: BaseRegistrar,
address: BASE_REGISTRAR_ADDRESS,
startBlock: 9380410,
endBlock: END_BLOCK,
},
EthRegistrarControllerOld: {
network: "mainnet",
abi: EthRegistrarControllerOld,
address: ETH_REGISTRAR_CONTROLLER_OLD_ADDRESS,
startBlock: 9380471,
endBlock: END_BLOCK,
},
EthRegistrarController: {
network: "mainnet",
abi: EthRegistrarController,
address: ETH_REGISTRAR_CONTROLLER_ADDRESS,
startBlock: Math.min(16925618, END_BLOCK),
endBlock: END_BLOCK,
},
NameWrapper: {
network: "mainnet",
abi: NameWrapper,
address: NAME_WRAPPER_ADDRESS,
startBlock: Math.min(16925608, END_BLOCK),
endBlock: END_BLOCK,
},
},
});
// here we export only a single 'plugin's config, by type it as every config
// this makes all of the mapping types happy at typecheck-time, but only the relevant
// config is run at runtime
export default ((): AllConfigs => {
switch (ACTIVE_PLUGIN) {
case ethOwnedName:
activateEth();
return ethConfig as AllConfigs;
case ethBaseOwnedName:
activateEthBase();
return ethBaseConfig as AllConfigs;
default:
throw new Error(`Unsupported ACTIVE_PLUGIN: ${ACTIVE_PLUGIN}`);
}
})();
Loading

0 comments on commit 7bdc380

Please sign in to comment.