Chainwatch is a small Rust CLI/TUI tool for monitoring Arbitrum transactions and surfacing interesting activity such as whale transfers and Stylus-related interactions.
It can run in two modes:
- Streaming mode: subscribes to new blocks over WebSocket and watches live transactions.
- Snapshot mode: fetches a specific block (or the latest block) from an RPC endpoint.
- Live transaction streaming from an Arbitrum WebSocket endpoint
- Block inspection from an RPC endpoint
- Whale detection based on a configurable threshold
- Stylus contract detection for transaction recipients
- Optional terminal UI for browsing recent and cached transactions
- SQLite persistence for saved transactions
- Rust 1.85+ (the project currently targets the 2024 edition)
- A WebSocket endpoint for streaming
- An HTTP RPC endpoint for block fetching
- A SQLite database URL
Choose one of the following installation paths.
This is the simplest path if a prebuilt binary is available for your platform.
-
Download the latest release archive from the Releases page for your OS.
-
Extract the archive and place the executable somewhere in your
PATH, or run it directly from the extracted folder. -
Create a
.envfile with the required endpoints and database URLDATABASE_URL=sqlite:chainwatch.db WS_URL=wss://your-arbitrum-ws-endpoint RPC_URL=https://your-arbitrum-rpc-endpoint
-
Initialize the SQLite table if needed
The app expects a table named
transactions. A starter schema is available in src/migrations/_init.sql.Example:
sqlite3 chainwatch.db < src/migrations/_init.sql -
Run the app
./chainwatch --stream
Use this if you want to compile from the current source tree or if no binary is available for your platform.
-
Install Rust 1.85+.
-
Clone the repository and build it
git clone <repo-url> cd chainwatch cargo build --release
-
Create a
.envfile with the required endpoints and database URLDATABASE_URL=sqlite:data/chainwatch.db WS_URL=wss://your-arbitrum-ws-endpoint RPC_URL=https://your-arbitrum-rpc-endpoint
-
Initialize the SQLite table if needed
Example:
sqlite3 data/chainwatch.db < src/migrations/_init.sql -
Run the built binary
./target/release/chainwatch --stream
--stream,-s: enable streaming mode over WebSocket--block <BLOCK>,-b: fetch a specific block number; if omitted in snapshot mode, the latest block is used--threshold <THRESHOLD>,-t: minimum transaction value to classify as a whale transfer. The value is interpreted as ETH and converted internally to wei--ui,-u: enable the terminal UI--ws <WS_URL>,-w: WebSocket URL override--rpc <RPC_URL>,-r: RPC URL override--db-url <DB_URL>,-d: SQLite database URL override
Stream live transactions with the terminal UI:
chainwatch --stream --uiFetch the latest block and print the transactions:
chainwatch --block 12345678Stream with a higher whale threshold:
chainwatch --stream --threshold 50Use explicit endpoint overrides:
chainwatch --stream --ws wss://example.ws --rpc https://example.rpc --db-url sqlite:chainwatch.dbEach transaction is evaluated for two markers:
- Whale transfer: the value is greater than or equal to the configured threshold
- Stylus interaction: the recipient address appears to contain Stylus bytecode
Transactions that match either condition are persisted to the SQLite database.
The app writes detected transactions into a SQLite table named transactions with the following columns:
block_numbertx_hashfrom_addrto_addreth_valueis_whaleis_stylusdetected_at
When running with --ui, the interface supports:
Tab/Left/Rightto switch between viewsj/korUp/Downto move through cached transactionsqto quit
- If the app exits with a missing environment variable error, make sure
.envcontainsDATABASE_URL,WS_URL, andRPC_URL, or pass the values directly with the CLI flags. - If the database table is missing, initialize it using src/migrations/_init.sql.
- If the WebSocket or RPC connection fails, verify that the endpoint is reachable and supports the required network.