Compare commits

...

8 Commits

15 changed files with 153 additions and 37 deletions

View File

@ -1,4 +1,4 @@
FROM golang:1.23.0-bookworm as build FROM golang:1.23.3-bookworm as build
ENV CGO_ENABLED=1 ENV CGO_ENABLED=1

View File

@ -2,18 +2,21 @@
![GitHub Tag](https://img.shields.io/github/v/tag/grassrootseconomics/eth-indexer) ![GitHub Tag](https://img.shields.io/github/v/tag/grassrootseconomics/eth-indexer)
A lightweight Postgres chain indexer designed to couple with [eth-tracker](https://github.com/grassrootseconomics/eth-tracker) to index all relevant GE related blockchain data on any EVM chain. A lightweight Postgres chain indexer designed to couple with
[eth-tracker](https://github.com/grassrootseconomics/eth-tracker) to index all
relevant GE related blockchain data on any EVM chain.
## Getting Started ## Getting Started
### Prerequisites ### Prerequisites
* Git - Git
* Docker - Docker
* Postgres server - Postgres server
* Access to a `eth-tracker` instance - Access to a `eth-tracker` instance
See [docker-compose.yaml](dev/docker-compose.yaml) for an example on how to run and deploy a single instance. See [docker-compose.yaml](dev/docker-compose.yaml) for an example on how to run
and deploy a single instance.
### 1. Build the Docker image ### 1. Build the Docker image
@ -34,7 +37,9 @@ For an example, see `dev/docker-compose.postgres.yaml`.
### 3. Update config values ### 3. Update config values
See `.env.example` on how to override default values defined in `config.toml` using env variables. Alternatively, mount your own config.toml either during build time or Docker runtime. See `.env.example` on how to override default values defined in `config.toml`
using env variables. Alternatively, mount your own config.toml either during
build time or Docker runtime.
```bash ```bash
# Override only specific config values # Override only specific config values
@ -44,10 +49,10 @@ mv .env.example .env
Special env variables: Special env variables:
* DEV=* - DEV=*
Refer to [`config.toml`](config.toml) to understand different config value settings.
Refer to [`config.toml`](config.toml) to understand different config value
settings.
### 4. Run the indexer ### 4. Run the indexer

View File

@ -12,12 +12,12 @@ import (
"syscall" "syscall"
"time" "time"
"github.com/grassrootseconomics/eth-indexer/internal/api" "github.com/grassrootseconomics/eth-indexer/v2/internal/api"
"github.com/grassrootseconomics/eth-indexer/internal/cache" "github.com/grassrootseconomics/eth-indexer/v2/internal/cache"
"github.com/grassrootseconomics/eth-indexer/internal/handler" "github.com/grassrootseconomics/eth-indexer/v2/internal/handler"
"github.com/grassrootseconomics/eth-indexer/internal/store" "github.com/grassrootseconomics/eth-indexer/v2/internal/store"
"github.com/grassrootseconomics/eth-indexer/internal/sub" "github.com/grassrootseconomics/eth-indexer/v2/internal/sub"
"github.com/grassrootseconomics/eth-indexer/internal/util" "github.com/grassrootseconomics/eth-indexer/v2/internal/util"
"github.com/grassrootseconomics/ethutils" "github.com/grassrootseconomics/ethutils"
"github.com/knadh/koanf/v2" "github.com/knadh/koanf/v2"
) )

View File

@ -1,8 +1,8 @@
package main package main
import ( import (
"github.com/grassrootseconomics/eth-indexer/internal/handler" "github.com/grassrootseconomics/eth-indexer/v2/internal/handler"
"github.com/grassrootseconomics/eth-indexer/pkg/router" "github.com/grassrootseconomics/eth-indexer/v2/pkg/router"
) )
func bootstrapRouter(handlerContainer *handler.Handler) *router.Router { func bootstrapRouter(handlerContainer *handler.Handler) *router.Router {
@ -20,7 +20,7 @@ func bootstrapRouter(handlerContainer *handler.Handler) *router.Router {
) )
router.RegisterRoute( router.RegisterRoute(
"TRACKER.TOKEN_BURN", "TRACKER.TOKEN_BURN",
handlerContainer.IndexTokenMint, handlerContainer.IndexTokenBurn,
handlerContainer.AddToken, handlerContainer.AddToken,
) )
router.RegisterRoute( router.RegisterRoute(
@ -38,6 +38,15 @@ func bootstrapRouter(handlerContainer *handler.Handler) *router.Router {
handlerContainer.IndexFaucetGive, handlerContainer.IndexFaucetGive,
handlerContainer.FaucetHealthCheck, handlerContainer.FaucetHealthCheck,
) )
router.RegisterRoute(
"TRACKER.OWNERSHIP_TRANSFERRED",
handlerContainer.IndexOwnershipChange,
)
router.RegisterRoute(
"TRACKER.INDEX_REMOVE",
handlerContainer.IndexRemove,
)
return router return router
} }

4
go.mod
View File

@ -1,6 +1,6 @@
module github.com/grassrootseconomics/eth-indexer module github.com/grassrootseconomics/eth-indexer/v2
go 1.23.0 go 1.23.3
require ( require (
github.com/VictoriaMetrics/metrics v1.35.1 github.com/VictoriaMetrics/metrics v1.35.1

View File

@ -47,7 +47,7 @@ func (h *Handler) AddToken(ctx context.Context, event event.Event) error {
if err := h.chainProvider.Client.CallCtx( if err := h.chainProvider.Client.CallCtx(
ctx, ctx,
eth.CallFunc(contractAddress, decimalsGetter).Returns(&tokenDecimals), eth.CallFunc(contractAddress, sinkAddressGetter).Returns(&sinkAddress),
); err != nil { ); err != nil {
// This will most likely revert if the contract does not have a sinkAddress // This will most likely revert if the contract does not have a sinkAddress
// Instead of handling the error we just ignore it and set the value to 0 // Instead of handling the error we just ignore it and set the value to 0

View File

@ -3,8 +3,8 @@ package handler
import ( import (
"log/slog" "log/slog"
"github.com/grassrootseconomics/eth-indexer/internal/cache" "github.com/grassrootseconomics/eth-indexer/v2/internal/cache"
"github.com/grassrootseconomics/eth-indexer/internal/store" "github.com/grassrootseconomics/eth-indexer/v2/internal/store"
"github.com/grassrootseconomics/ethutils" "github.com/grassrootseconomics/ethutils"
) )

View File

@ -0,0 +1,11 @@
package handler
import (
"context"
"github.com/grassrootseconomics/eth-tracker/pkg/event"
)
func (h *Handler) IndexRemove(ctx context.Context, event event.Event) error {
return h.store.RemoveContractAddress(ctx, event)
}

View File

@ -0,0 +1,11 @@
package handler
import (
"context"
"github.com/grassrootseconomics/eth-tracker/pkg/event"
)
func (h *Handler) IndexOwnershipChange(ctx context.Context, event event.Event) error {
return h.store.InsertOwnershipChange(ctx, event)
}

View File

@ -36,8 +36,11 @@ type (
InsertFaucetGive string `query:"insert-faucet-give"` InsertFaucetGive string `query:"insert-faucet-give"`
InsertPoolSwap string `query:"insert-pool-swap"` InsertPoolSwap string `query:"insert-pool-swap"`
InsertPoolDeposit string `query:"insert-pool-deposit"` InsertPoolDeposit string `query:"insert-pool-deposit"`
InsertOwnershipChange string `query:"insert-ownership-change"`
InsertToken string `query:"insert-token"` InsertToken string `query:"insert-token"`
InsertPool string `query:"insert-pool"` InsertPool string `query:"insert-pool"`
RemovePool string `query:"remove-pool"`
RemoveToken string `query:"remove-token"`
} }
) )
@ -199,6 +202,25 @@ func (pg *Pg) InsertPoolDeposit(ctx context.Context, eventPayload event.Event) e
}) })
} }
func (pg *Pg) InsertOwnershipChange(ctx context.Context, eventPayload event.Event) error {
return pg.executeTransaction(ctx, func(tx pgx.Tx) error {
txID, err := pg.insertTx(ctx, tx, eventPayload)
if err != nil {
return err
}
_, err = tx.Exec(
ctx,
pg.queries.InsertOwnershipChange,
txID,
eventPayload.Payload["previousOwner"].(string),
eventPayload.Payload["newOwner"].(string),
eventPayload.ContractAddress,
)
return err
})
}
func (pg *Pg) InsertToken(ctx context.Context, contractAddress string, name string, symbol string, decimals uint8, sinkAddress string) error { func (pg *Pg) InsertToken(ctx context.Context, contractAddress string, name string, symbol string, decimals uint8, sinkAddress string) error {
return pg.executeTransaction(ctx, func(tx pgx.Tx) error { return pg.executeTransaction(ctx, func(tx pgx.Tx) error {
_, err := tx.Exec( _, err := tx.Exec(
@ -227,6 +249,30 @@ func (pg *Pg) InsertPool(ctx context.Context, contractAddress string, name strin
}) })
} }
func (pg *Pg) RemoveContractAddress(ctx context.Context, eventPayload event.Event) error {
return pg.executeTransaction(ctx, func(tx pgx.Tx) error {
_, err := tx.Exec(
ctx,
pg.queries.RemovePool,
eventPayload.Payload["address"].(string),
)
if err != nil {
return err
}
_, err = tx.Exec(
ctx,
pg.queries.RemoveToken,
eventPayload.Payload["address"].(string),
)
if err != nil {
return err
}
return nil
})
}
func (pg *Pg) insertTx(ctx context.Context, tx pgx.Tx, eventPayload event.Event) (int, error) { func (pg *Pg) insertTx(ctx context.Context, tx pgx.Tx, eventPayload event.Event) (int, error) {
var txID int var txID int
if err := tx.QueryRow( if err := tx.QueryRow(

View File

@ -15,8 +15,10 @@ type (
InsertFaucetGive(context.Context, event.Event) error InsertFaucetGive(context.Context, event.Event) error
InsertPoolSwap(context.Context, event.Event) error InsertPoolSwap(context.Context, event.Event) error
InsertPoolDeposit(context.Context, event.Event) error InsertPoolDeposit(context.Context, event.Event) error
InsertOwnershipChange(context.Context, event.Event) error
InsertToken(context.Context, string, string, string, uint8, string) error InsertToken(context.Context, string, string, string, uint8, string) error
InsertPool(context.Context, string, string, string) error InsertPool(context.Context, string, string, string) error
RemoveContractAddress(context.Context, event.Event) error
Pool() *pgxpool.Pool Pool() *pgxpool.Pool
Close() Close()
} }

View File

@ -6,7 +6,7 @@ import (
"log/slog" "log/slog"
"time" "time"
"github.com/grassrootseconomics/eth-indexer/pkg/router" "github.com/grassrootseconomics/eth-indexer/v2/pkg/router"
"github.com/nats-io/nats.go" "github.com/nats-io/nats.go"
"github.com/nats-io/nats.go/jetstream" "github.com/nats-io/nats.go/jetstream"
) )

View File

@ -0,0 +1,7 @@
CREATE TABLE IF NOT EXISTS ownership_change (
id INT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
tx_id INT REFERENCES tx(id),
previous_owner VARCHAR(42) NOT NULL DEFAULT '0x0000000000000000000000000000000000000000',
new_owner VARCHAR(42) NOT NULL DEFAULT '0x0000000000000000000000000000000000000000',
contract_address VARCHAR(42) NOT NULL DEFAULT '0x0000000000000000000000000000000000000000'
);

View File

@ -0,0 +1,5 @@
ALTER TABLE tokens
ADD COLUMN removed BOOLEAN NOT NULL DEFAULT false;
ALTER TABLE pools
ADD COLUMN removed BOOLEAN NOT NULL DEFAULT false;

View File

@ -104,6 +104,18 @@ INSERT INTO pool_deposit(
contract_address contract_address
) VALUES($1, $2, $3, $4, $5) ON CONFLICT DO NOTHING ) VALUES($1, $2, $3, $4, $5) ON CONFLICT DO NOTHING
--name: insert-ownership-change
-- $1: tx_id
-- $2: previous_owner
-- $3: new_owner
-- $4: contract_address
INSERT INTO ownership_change(
tx_id,
previous_owner,
new_owner,
contract_address
) VALUES($1, $2, $3, $4) ON CONFLICT DO NOTHING
--name: insert-token --name: insert-token
-- $1: contract_address -- $1: contract_address
-- $2: token_name -- $2: token_name
@ -122,8 +134,16 @@ INSERT INTO tokens(
-- $1: contract_address -- $1: contract_address
-- $2: pool_name -- $2: pool_name
-- $3: pool_symbol -- $3: pool_symbol
INSERT INTO tokens( INSERT INTO pools(
contract_address, contract_address,
pool_name, pool_name,
pool_symbol pool_symbol
) VALUES ($1, $2, $3) ON CONFLICT DO NOTHING ) VALUES ($1, $2, $3) ON CONFLICT DO NOTHING
--name: remove-pool
-- $1: contract_address
UPDATE pools SET removed = true WHERE contract_address = $1
--name: remove-token
-- $1: contract_address
UPDATE tokens SET removed = true WHERE contract_address = $1