Quick Start
Get trustvc-chain-events running locally in under 5 minutes.
Step 1 — Pull the Image
Docker Hub (recommended)
docker pull trustvc/trustvc-chain-events:latest
GitHub Container Registry (alternative)
docker pull ghcr.io/trustvc/trustvc-chain-events:latest
Step 2 — Generate a Signing Key
The container signs every webhook delivery with an Ed25519 key. You keep the private key; your receiver uses the public key to verify payloads.
Option A — random seed (simplest)
openssl rand -base64 32
# example output: cZejchTTcxHUk8N+sbcOyVHZ3MVxzYQGYDCn+hFa4S4=
# Paste this value as SIGNING_PRIVATE_KEY in your .env
Option B — PEM key pair (keep the public key for verification)
openssl genpkey -algorithm ed25519 -out private.pem
openssl pkey -in private.pem -pubout -out public.pem
# Extract the 32-byte seed the container expects:
openssl pkey -in private.pem -outform DER | tail -c 32 | base64
# Paste this output as SIGNING_PRIVATE_KEY in your .env
SIGNING_PRIVATE_KEY must be the raw 32-byte Ed25519 seed encoded as base64 — not the PEM file itself. Use the extraction command above if you generated a PEM key.
Step 3 — Create config.json
Create a config.json in your working directory. At a minimum you need a chain, an RPC URL, and a webhook URL.
{
"chains": [
{
"chainKey": "ethereum-sepolia",
"rpcUrl": "wss://eth-sepolia.g.alchemy.com/v2/YOUR_API_KEY",
"registryAddresses": ["0xYourTokenRegistryAddress"],
"replayFromBlock": 6000000
}
],
"webhook": {
"url": "https://your-system.example.com/trustvc/events"
}
}
replayFromBlockSet this to the block number when your Token Registry was deployed. The container replays all events from that block on first start to catch up. Using 0 works but will scan the entire chain history.
You can leave registryAddresses as an empty array [] and add them later via the Registry API — useful when you do not know addresses at deploy time.
Step 4 — Create .env
# .env
SIGNING_PRIVATE_KEY="cZejchTTcxHUk8N+sbcOyVHZ3MVxzYQGYDCn+hFa4S4="
# Optional — PostgreSQL for state persistence
DB_HOST=localhost
DB_PORT=5432
DB_NAME=trustvcevents
DB_USER=postgres
DB_PASSWORD=secret
Step 5 — Run
With an env file (recommended)
docker run -d \
-v $(pwd)/config.json:/app/config.json:ro \
--env-file .env \
-p 8080:8080 \
--name trustvc-events \
trustvc/trustvc-chain-events:latest
With Docker Compose
services:
trustvc-events:
image: trustvc/trustvc-chain-events:latest
ports:
- "8080:8080"
volumes:
- ./config.json:/app/config.json:ro
env_file:
- .env
restart: unless-stopped
docker compose up -d
Step 6 — Verify
curl http://localhost:8080/health
{"status":"ok"}
Check the logs to confirm chains are connected and escrows are loaded:
docker logs trustvc-events
You should see output similar to:
INFO [startup]: trustvc-webhook-events starting version: "0.1.0"
INFO [startup]: Database connected
INFO [startup]: Chain worker ready chain: "ethereum-sepolia" escrows: 22
INFO [startup]: ✓ Server ready — listening for on-chain events
chains: "ethereum-sepolia (22 escrows)"
webhook: "https://your-system.example.com/trustvc/events"
If you see escrows: 0 in the "Chain worker ready" line but the final "Server ready" line shows the correct count, this is a display-only race condition in startup logging — the container is working correctly. The definitive count is always in the final summary.
What Happens Next
Once running, the container:
- Replays history — scans from
replayFromBlockto the current block to catch any events you missed - Subscribes to live blocks — uses WebSocket subscriptions (or polling for HTTP-transport chains) to receive new events in real time
- Signs and delivers — each event is signed with your Ed25519 key and POSTed to your webhook URL
- Retries on failure — uses exponential backoff (configurable via
retryAttemptsandretryBackoffMs)
See Webhook Payload & Verification for the full event schema and how to verify signatures on your receiver.