| Guardian Spy | Connects to the wormhole p2p network and publishes all VAAs to a websocket |
| Spy Listener | Filters VAAs from the Spy and adds them to the incoming queue in Redis |
| REST Listener | Accepts HTTP requests to relay VAAs and writes them to the incoming queue in Redis |
| Redis | A durable queue for storing VAAs before they are relayed |
| Relayer | Scans the Redis incoming queue and moves acceptable VAAs to the working queue. It then completes the transfer and pays gas fees on the destination chain. |
| Wallet Monitor | Presents a prometheus endpoint for monitoring wallet balances of native tokens (for paying gas fees) and non-native tokens as relayer profit |
If Redis is temporarily down, the Listener will queue outstanding transactions in memory. When Redis comes back online, the Listener writes them all to Redis.
### Architecture Diagram
This is a rough diagram of how the components fit together:
┌────────────────────────────────────────┐
│ Wormhole Guardian Peer to Peer Network │
└───────────────────┬────────────────────┘
│
┌──────▼───────┐
│ Guardian Spy │
└──────┬───────┘
│
┌──────▼───────┐
│ Spy Listener │
└──────┬───────┘
│
┌───▼───┐ ┌───────────────┐
│ Redis │◄───┤ REST Listener │
└───┬───┘ └───────────────┘
│
┌────▼────┐
│ Relayer │
└─────────┘
│
┌────────▼───────┐
│ Wallet Monitor │
└────────────────┘
Environment Variables
---------------------
### Listener
These are for configuring the spy and rest listener. See [.env.tilt.listener](.env.tilt.listener) for examples:
| Name | Description |
|------|-------------|
| `SPY_SERVICE_HOST` | host & port string to connect to the spy |
| `SPY_SERVICE_FILTERS` | Addresses to monitor (Wormhole core bridge contract addresses) array of ["chainId","emitterAddress"]. Emitter addresses are native strings. |
| `REDIS_HOST` | Redis host / ip to connect to |
| `REDIS_PORT` | Redis port |
| `REST_PORT` | Rest listener port to listen on. |
| `READINESS_PORT` | Kubernetes readiness probe port to listen on. |
| `LOG_LEVEL` | log level, such as debug |
| `SUPPORTED_TOKENS` | Origin assets that will attempt to be relayed. Array of ["chainId","address"], address should be a native string. |
### Relayer
These are for configuring the actual relayer. See [.env.tilt.relayer](.env.tilt.relayer) for examples:
| Name | Description |
|------|-------------|
| `SUPPORTED_CHAINS` | The configuration for each chain which will be relayed. See [chainConfigs.example.json](src/chainConfigs.example.json) for the format. Of note, `walletPrivateKey` is an array, and a separate worker will be spun up for every private key provided. |
| `REDIS_HOST` | host of the redis service, should be the same as in the spy_listener |
| `REDIS_PORT` | port for redis to connect to |
| `PROM_PORT` | port where prometheus monitoring will listen |
| `READINESS_PORT` | port for kubernetes readiness probe |
| `CLEAR_REDIS_ON_INIT` | boolean, if `true` the relayer will clear the INCOMING and WORKING Redis tables before it starts up. |
| `DEMOTE_WORKING_ON_INIT` | boolean, if `true` the relayer will move everything from the WORKING Redis table to the INCOMING one. |
| `LOG_LEVEL` | log level, debug or info |
Building
--------
### Building the Spy
To build the guardiand / spy container from source:
The spy connects to the wormhole guardian peer to peer network and listens for new VAAs. It publishes those via a socket and websocket that the listener subscribes to. If you want to run the spy built from source, change `ghcr.io/certusone/guardiand:latest` to `guardian` after building the `guardian` image.