CSM Sentinel is a Telegram bot that sends you notifications for your CSM Node Operator events.
This bot was developed and is maintained by @skhomuti, a member of the Lido Protocol community, to simplify the process of subscribing to the important events for CSM. You can either run the bot yourself or use the community-supported public instance, depending on your privacy preferences.
These bots are owned by @skhomuti: Ethereum and Hoodi. The Holesky instance is no longer supported.
Please note that no guarantee is given for the availability of the bot. Also consider privacy concerns when using a public instance.
First, you need to create a bot on Telegram. You can do this by talking to the BotFather.
Then, you need to create a .env by copying one of the .env.sample.ethereum or .env.sample.hoodi files and filling in the required fields:
TOKEN: The token you received from the BotFatherWEB3_SOCKET_PROVIDER: The websocket provider for your node. Preferably, use your own local node e.g. you already have for CSM validators. But it is also possible to use a public node of any web3 providers.
All other fields are pre-filled with the contracts from the corresponding network.
Run the CSM Sentinel using Docker compose:
docker compose up -dOr using Docker:
docker build -t csm-sentinel .
docker volume create csm-sentinel-persistent
docker run -d --env-file=.env --name csm-sentinel -v csm-sentinel-persistent:/app/.storage csm-sentinelPublic container images are published to GitHub Container Registry for this repository:
docker pull ghcr.io/skhomuti/csm-sentinel:latestImage tags follow the Git ref that triggered the workflow:
- Pull requests build the image for validation but do not publish it
- Each merge to
mainrefreshes a draft prerelease suggestion in GitHub Releases - Publishing a prerelease with tag
vX.Y.ZrcNpublishesghcr.io/skhomuti/csm-sentinel:X.Y.ZrcN - Publishing a stable release with tag
vX.Y.Zpublishesghcr.io/skhomuti/csm-sentinel:X.Y.Z,X.Y,X, andlatest
Suggested prerelease bumps are driven by pull request labels:
release:majorfor breaking changesrelease:minorfor backward-compatible featuresrelease:patchfor fixes and other release-worthy changes
If no release:* label is applied, the next draft prerelease treats the change as a patch.
Install dependencies and run the bot with uv:
uv sync
uv run python -m sentinel.mainIf you are running the bot on the same machine as the eth-docker, you can use the execution client with no need to expose it outside the container.
You need to use a special docker-compose file that connects the Sentinel instance to the eth-docker network.
docker compose -f docker-compose-ethd.yml up -dWEB3_SOCKET_PROVIDER env variable is set to ws://execution:8546 via docker-compose file,
so you don't need to specify it in the .env file.
Pass the BLOCK_FROM environment variable to specify the block the bot should start monitoring events from.
Note that this may result in duplicate events if you set it to a block that the bot has already processed before.
BLOCK_FROM=0 allows you to skip processing past blocks and always start from the head.
In general, you don't need to set this variable.
BLOCK_BATCH_SIZE controls how many blocks are fetched per RPC request when processing historical events.
The default value is 10000.
PROCESS_BLOCKS_REQUESTS_PER_SECOND caps how many historical RPC requests process_blocks_from
issues per second when backfilling. Leave unset to disable throttling.
Some maintenance commands are restricted to admins. To enable them, set your Telegram user ID in the ADMIN_IDS environment variable.
How to find your Telegram user ID:
- Open a chat with
@userinfobot, send/start, and copy the numericIdvalue.
Configure the ID in your .env:
# Single admin
ADMIN_IDS=123456789
# Multiple admins (comma or space separated)
ADMIN_IDS=123456789,987654321
# or
ADMIN_IDS=123456789 987654321
Admins can broadcast messages via the in-bot Admin panel:
- Open
Admin→Broadcast. - Choose
All subscribersto send a message to every chat subscribed to any node operator, then enter your message. - Or choose
By node operatorand enter comma-separated node operator IDs (e.g.,1,2,3), then enter your message.
End-to-end verification for on-chain events lives under tests/integration. Each
scenario replays a real transaction through a lightweight harness that exposes the
same process_blocks_from and subscribe entrypoints as the real subscription, allowing
EventMessages to render the expected Markdown for every event.
To enable the suite:
- Install a local fork provider:
- Ensure
.envcontains aWEB3_SOCKET_PROVIDERthat can serve archive data; the tests reuse this value as the fork source (WebSocket URLs are translated to their HTTP equivalents automatically)
Each test spawns a dedicated local fork pinned to the case's block to keep state deterministic. Run the suite with:
uv run pytest -m integration