/ README.md
README.md
  1  Account Monitor
  2  ===============
  3  
  4  > Locally monitor accounts on EVM chains, without leaking information to RPC providers.
  5  
  6  # Why?
  7  The goal of this project is to notify users if something unexpected happened (account was compromised), in a way that preserves privacy from 3rd party services.
  8  
  9  # Limitations
 10  * For native token transfers, only outgoing transactions are detected (wen [EIP-7708](https://eip.tools/eip/7708)?) and those, only when using `Blocks` mode.
 11  * Smart contract wallets will not trigger any notifications when sending native tokens, even in `Blocks` mode.
 12  * While some types of transactions are properly identified, "complex" transactions (swaps/buy) will not be correctly categorized, but a notification will be sent (depending on spam filter options).
 13  * The token symbols come from [rotki assets](https://github.com/rotki/assets) which means that not all tokens are included and the list is only updated when Account Monitor is updated.
 14  * No notifications for previous transactions.
 15  
 16  # Features
 17  * Support any EVM chain (at least in `Events` mode).
 18  * Use [ntfy](https://ntfy.sh/) to allow self-hosted notifications.
 19  * Load accounts via a yaml on start and/or via an API call.
 20  * Script to load accounts from [rotki](https://rotki.com/).
 21  * Prometheus monitoring endpoint.
 22  
 23  # Quickstart
 24  
 25  Requirements: docker
 26  
 27  1. Clone this repository
 28  2. Copy `.env.example` to `.env`
 29  3. Configure variables in `.env` (requires an Alchemy API key and ntfy token)
 30  4. Copy `accounts.example.yaml` to `accounts.yaml`
 31  5. Modify `accounts.yaml` to remove the examples and add the accounts to monitor
 32  6. Run `docker-compose up`
 33  
 34  The instructions above use Alchemy to make them easy to follow, if you want to use another RPC provider (or even better, your own node), set the appropriate endpoint for `CHAIN_RPC_ETHEREUM` in `docker-compose.yaml`
 35  
 36  # Configuration
 37  Configuration is done via environment variables
 38  
 39  ## Global
 40  
 41  | Variable             | Type     | Required | Description                                                                                                                                                                                |
 42  | ---                  | ---      | ---      | ---                                                                                                                                                                                        |
 43  |`NTFY_TOKEN`          | `string` | `true`   | Ntfy's Auth token                                                                                                                                                                          |
 44  |`NTFY_URL`            | `string` | `true`   | Ntfy's server URL                                                                                                                                                                          |
 45  |`NTFY_TOPIC`          | `string` | `true`   | Topic to send notifications to                                                                                                                                                             |
 46  |`CHAINS`              | `string` | `true`   | Uppercase comma separated list of chains to monitor (any EVM chain is supported)                                                                                                           |
 47  |`STATIC_ACCOUNTS_PATH`| `string` | `false`  | Location from which to read the accounts to add during launch. This should be a yaml file with the same format as `accounts.example.yaml`. If not set, all accounts must be added via REST |
 48  
 49  ## Per Chain
 50  For each chain defined in `CHAINS` there should be a block with the following variables, with the defined suffix (`ETHEREUM` in this example)
 51  
 52  | Variable                           | Type                                              | Required | Default       | Description                                                                                                                                            |
 53  | ---                                | ---                                               | ---      | ---           | ---                                                                                                                                                    |
 54  |`CHAIN_RPC_ETHEREUM`                | `string`                                          | `true`   |               | HTTPS RPC of a chain                                                                                                                                   |
 55  | `CHAIN_NAME_ETHEREUM`              | `string`                                          | `true`   |               | Used in the notifications' message                                                                                                                     |
 56  | `CHAIN_BLOCKTME_ETHEREUM`          | `int`                                             | `true`   |               | Milliseconds in between blocks. When using `Event` mode, increasing this value will make fewer requests to the RPC, batching all blocks in an interval |
 57  | `CHAIN_MODE_ETHEREUM`              | `Blocks | Events`                            | `false`  | `Blocks`      | Method to use when queering RPCs for new transactions. See [Mode](#mode)                                                                               |
 58  | `CHAIN_SPAM_FILTER_LEVEL_ETHEREUM` | `None | KnownAssets | SelfSubmittedTxs` | `false`  | `KnownAssets` | Spam filter configuration for the chain, see [Spam Filter](#spam-filter)                                                                               |
 59  | `CHAIN_EXPLORER_ETHEREUM`          | `string`                                          | `false`  | `None`        | Domain of the chain's explorer, to include a link in the notification                                                                                  |
 60  | `CHAIN_ID_ETHEREUM`                | `int`                                             | `false`  |               | Chain ID. Only used for verification, will be ignored if not configured                                                                                |
 61  
 62  ### Mode
 63  One of the goals of this project is to be able to monitor accounts across all the EVM chains a user wants for free using an RPC provider. The two modes have important trade-offs, choose carefully. Neither method leaks any of the monitored accounts to the RPC providers.
 64  * **Events**: The events mode will **not** include outgoing transfers of native tokens nor transactions which do not emit any onchain Events/Logs, but setting a `CHAIN_BLOCKTME_chain` higher than the actual chain blocktime (5000 for 5s) allows users to scrape 6~7 chains using a free Alchemy account.
 65  * **Blocks**: Blocks mode uses a more expensive method to query RPCs but does include all outgoing transactions even if they only send native tokens or don't have any Events/Logs. Not all RPC Provider/Chains support this mode as it uses the newish method `eth_getBlockReceipts` (or Alchemy's version `alchemy_getTransactionReceipts`)
 66  
 67  ### Spam Filter
 68  Chains with cheap gas cause a lot of incoming spam/scam transactions. `CHAIN_SPAM_FILTER_LEVEL_chain` can be used to filter out unwanted notifications. The available options are: (from strict to noisy)
 69  * **SelfSubmittedTxs**: Only transactions sent by monitored accounts will trigger notifications. Will not notify of any incoming transactions. Not useful for use with Smart Contract Wallets.
 70  * **KnownAssets**: Transactions that pass SelfSubmittedTxs + Transactions where a known token (from [rotki assets](https://github.com/rotki/assets)) is transferred to or from a monitored account.
 71  * **None**: All transactions will trigger notifications.
 72  
 73  ## Debugging configuration
 74  The following environment variables can be used to debug Account Monitor
 75  
 76  
 77  | Variable       | Type      | Required | Default | Description                                                                                                                                |
 78  | ---            | ---       | ---      | ---     | ---                                                                                                                                        |
 79  | `RUST_LOG`     | `string`  | `false`  |         | Use `account_monitor=debug` to enable debugging                                                                                            |
 80  | `NTFY_DISABLE` | `boolean` | `false`  | `false` | Log notification message instead of sending it through ntfy. Makes ntfy env variables optional. RUST_LOG should be at least set to `info`. |
 81  | `DEBUG_BLOCK`  | `int`     | `false`  |         | Look for transactions in a single block. The program will exit when a transaction of a monitored account is found.                         |
 82  
 83  # API
 84  The API exposes a single endpoint to add a monitored account. There is no way to list the currently monitored accounts. Attempts to add an already monitored account, will be ignored.
 85  
 86  A reverse proxy can be used to manage access to the API endpoint.
 87  
 88  The following command can be used to add a new account:
 89  ```sh
 90  curl --json '{"address":"0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045", "label":"Vitalik"}' http://localhost:3030
 91  ```
 92  
 93  # Scripts
 94  A couple of helper scripts are available to facilitate adding accounts via the API.
 95  Both scripts need `LOADING_SCRIPTS_HOST` to be set (or included in `.env`) this should point to where Account Monitor is running.
 96  
 97  * `scripts/load_accounts_from_rotki.sh`: Requires rotki to be open and logged in. Will monitor all the user's Ethereum addresses setup in rotki.
 98  * `scripts/load_accounts_from_yaml.sh`: Receives the location of a yaml file with accounts as a parameter. The file should have the same format as [accounts.example.yaml](./accounts.example.yaml).
 99  
100  # Acknowledgments
101  Thanks to [rotki](https://rotki.com) for curating tokens and known addresses. And an awesome portfolio tracker.
102  
103  Thanks to [ntfy](https://ntfy.sh) for a building a simple to use notification server, compatible with computers, and phones with most OSs.
104  
105  # Contributing
106  Issues and PRs for this repository are welcome and managed in [Radicle](https://radicle.xyz/guides/user).
107  
108  Repository ID: [rad:z3SRsZ8YdvUg4UEkqffuHrFdFEcML](https://app.radicle.xyz/nodes/seed.radicle.garden/rad:z3SRsZ8YdvUg4UEkqffuHrFdFEcML)