{"id":35595997,"url":"https://github.com/luisschwab/smaug","last_synced_at":"2026-01-24T22:12:01.215Z","repository":{"id":314211370,"uuid":"1052994708","full_name":"luisschwab/smaug","owner":"luisschwab","description":"smaug 🐉 guards your coins and sends you an email if they move","archived":false,"fork":false,"pushed_at":"2026-01-20T22:25:20.000Z","size":349,"stargazers_count":5,"open_issues_count":0,"forks_count":1,"subscribers_count":1,"default_branch":"master","last_synced_at":"2026-01-21T08:26:06.973Z","etag":null,"topics":["bitcoin","network","security"],"latest_commit_sha":null,"homepage":"","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/luisschwab.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2025-09-08T20:53:35.000Z","updated_at":"2026-01-20T22:25:24.000Z","dependencies_parsed_at":null,"dependency_job_id":"04d3ccbe-4fbd-479b-abe4-33b8552c8867","html_url":"https://github.com/luisschwab/smaug","commit_stats":null,"previous_names":["luisschwab/smaug"],"tags_count":7,"template":false,"template_full_name":null,"purl":"pkg:github/luisschwab/smaug","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/luisschwab%2Fsmaug","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/luisschwab%2Fsmaug/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/luisschwab%2Fsmaug/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/luisschwab%2Fsmaug/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/luisschwab","download_url":"https://codeload.github.com/luisschwab/smaug/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/luisschwab%2Fsmaug/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28738099,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-24T21:19:41.845Z","status":"ssl_error","status_checked_at":"2026-01-24T21:13:38.675Z","response_time":89,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["bitcoin","network","security"],"created_at":"2026-01-05T00:52:06.998Z","updated_at":"2026-01-24T22:12:01.210Z","avatar_url":"https://github.com/luisschwab.png","language":"Rust","funding_links":[],"categories":[],"sub_categories":[],"readme":"# smaug 🐉\n\n\u003cp align=\"center\"\u003e\n  \u003cimg src=\"smaug.jpg\" width=\"50%\" alt=\"Smaug\"\u003e\n\u003c/p\u003e\n\n\u003e Well, thief! I smell you, I hear your breath, I feel your air. Where are you?\n\u003e\n\u003e Come now, don't be shy... step into the light.\n\u003e\n\u003e There you are, Thief in the Shadows!\n\n`smaug` is a tool that keeps watch of your UTXOs. If you subscribe to an address and UTXOs from it move,\n`smaug` will send you an email to warn you.\n\n## Use Case\n\nLet's say you use [BIP85](https://bip85.com) to derive child seeds from a master seed,\nand you only keep a physical backup of the master seed. It's critical to know if that seed has been\ncompromised (e.g.: an unauthorized person has access to it). If you deposit some bitcoin on an address\nof the master seed and subscribe to that address, you'll be notified via email if that money ever moves.\nIf it does move, it means that your master seed has been compromised, giving you time to move your funds\nfrom child seeds elsewhere before an attacker gets his hands on them.\n\n## Usage\n\nInstall the Rust toolchain:\n```shell\ncurl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh\n```\n\nClone this repository and install the binary:\n```\ngit clone https://github.com/luisschwab/smaug\ncd smaug\ncargo install --path .\n```\n\nGet these SMTP credentials from your provider (or from yourself, if you're into that kind of thing):\n- SMTP username\n- SMTP password\n- SMTP server\n- SMTP port\n\nCreate a TOML file with these fields:\n\n```toml\n# The netowrk to operate in: bitcoin, signet, testnet, testnet4\nnetwork = \"testnet4\"\n# Optional: The URL of an Esplora API.\n# If no Esplora API is defined, the Mempool.space API will be used by default.\nesplora_url = \"https://mempool.space/testnet4/api\"\n# A list of addresses to watch\naddresses = [\n    \"tb1pk3su3yelyq4349c23rrmk0xa34dpmxght2t2ssenqj9vz9s4692shkkxxd\",\n    \"tb1pp0aea5wv49f43t30hex2x5avlxelxlac7uwrjr0u57k7xnld3qzqnulr5q\",\n    \"tb1punh3uhchgyaa0h95pxwyjkatn7qvulm6043gzfqwvmqw3f9vyetstd73va\"\n]\n# Whether to send an email with the addresses you subscribed to\nnotify_subscriptions = true\n# Whether to send an email about deposits to the addresses you subscribed to\nnotify_deposits = true\n# The email addresses of notification recipients\nrecipient_emails = [\"bilbo@baggins.net\"]\n# The SMTP username\nsmtp_username = \"smaug@erebor.com\"\n# The SMTP password\nsmtp_password = \"50m3r4nd0mp455w0rd\"\n# The SMTP server\nsmtp_server = \"smtp.erebor.com\"\n# The SMTP port\nsmtp_port = 1337\n```\n\nThen run it (you should get an email about your subscribed addresses, if set):\n\n```shell\nsmaug -c config.toml\n[2025-09-11T04:50:35Z INFO  smaug] Successfully parsed configuration from `config.toml`\n[2025-09-11T04:50:36Z INFO  smaug::smaug] Subscribed to address tb1pk3su3yelyq4349c23rrmk0xa34dpmxght2t2ssenqj9vz9s4692shkkxxd at height 101596\n[2025-09-11T04:50:36Z INFO  smaug::smaug] Subscribed to address tb1pp0aea5wv49f43t30hex2x5avlxelxlac7uwrjr0u57k7xnld3qzqnulr5q at height 101596\n[2025-09-11T04:50:36Z INFO  smaug::smaug] Subscribed to address tb1punh3uhchgyaa0h95pxwyjkatn7qvulm6043gzfqwvmqw3f9vyetstd73va at height 101596\n[2025-09-11T04:50:41Z INFO  smaug::email] Sent email to bilbo@baggins.net\n[2025-09-11T04:52:33Z INFO  smaug::smaug] Fetching state at height 101597...\n[2025-09-11T05:12:34Z INFO  smaug::smaug] Fetching state at height 101598...\n[2025-09-11T05:12:41Z INFO  smaug::smaug] Heads up, someone withdrew 1,000,000 sats from address tb1pk3su3yelyq4349c23rrmk0xa34dpmxght2t2ssenqj9vz9s4692shkkxxd\n[2025-09-11T05:12:42Z INFO  smaug::smaug] Sent email to bilbo@baggins.net\n\n```\n\nOptionally, use the example [`systemd`](./smaug.service.example) service provided here:\n```shell\ncp smaug.service.example /etc/systemd/system/smaug.service\nsystemctl daemon-reload\nsystemctl enable smaug.service\nsystemctl start smaug.service\n```\n\n## Architecture\n\n`smaug` is very simple: it hits the `/address/{address}/utxo` Esplora endpoint to get the current state\nof the address (what UTXOs are locked to it). Then, it does long polling to the same endpoint\nand computes the differences between the last state and the current state, here called `Event`s.\nThese get classified in `Event::Deposit` or `Event::Withdrawal`, `smaug` logs it and notifies\nthe recipients via email.\n\n\u003cp align=\"center\"\u003e\n  \u003cimg src=\"smaug-diagram.png\" width=\"80%\" alt=\"\"\u003e\n\u003c/p\u003e\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fluisschwab%2Fsmaug","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fluisschwab%2Fsmaug","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fluisschwab%2Fsmaug/lists"}