Help
Everything about watch.wallet on one page.
What we watch
- Bitcoin: BTC
- Ethereum: ETH, USDC, USDT
- Base: ETH, USDC, USDT
- Polygon: POL, USDC, USDT
- Solana: SOL, USDC, USDT
We read public balances from public sources: mempool.space for Bitcoin, public RPC nodes for Ethereum, Base, Polygon and Solana, and Coinbase for prices. You never connect a wallet or sign anything.
When it alerts
- The first read of a new watch is the baseline. After that, any change in any of the balances above is a move.
- Bitcoin counts a transaction as soon as it is in the mempool, before it confirms.
- With a dollar threshold (Watcher), we alert once the total moved since the last alert is worth at least that much. Small moves add up: ten $90 withdrawals still reach a $500 threshold.
- A read that fails (a node is down, a rate limit) never alerts. We try again and back off a source that keeps failing.
- A price watch fires once when the price reaches your level, then waits until the price is back on the other side (by half a percent) before it can fire again.
The phone call
On Watcher, tick "call me" on a watch and save your number. When it alerts we call: "watch.wallet alert: Cold wallet moved 0.5 E T H out. Press 1 to acknowledge." Pressing 1 marks the alert as seen. You can also acknowledge from the email, the push notification, the web, the CLI or the TUI.
Webhooks
On Watcher, set a webhook URL on your page. Every alert POSTs JSON to it:
{ "event": "watch.alert",
"alert": { "id": "…", "at": "…", "kind": "address", "summary": "Treasury moved: 0.5 ETH out (~$1,222)", "usd": 1222, "detail": { "changes": [ … ] } },
"watch": { "id": "…", "label": "Treasury", "chain": "base", "address": "0x…", "url": "https://watch.wallet.pit.world/w/…" } }
It carries x-watchwallet-signature: t=<unix>,v1=<hex>, where v1 is HMAC-SHA256 of t + "." + body with your webhook secret. Check it, and refuse a t more than five minutes old.
const [t, v1] = header.split(',').map((p) => p.split('=')[1])
const ok = crypto.createHmac('sha256', secret).update(`${t}.${rawBody}`).digest('hex') === v1
Webhook URLs must be https and resolve to a public address.
API, CLI and MCP
Make an API key on your page. Then:
export WATCHWALLET_KEY=ww_… bunx @profullstack/watchwallet status # your watches and last balances bunx @profullstack/watchwallet add ethereum 0x… --label=Cold --min-usd=100 --call bunx @profullstack/watchwallet price BTC below 60000 bunx @profullstack/watchwallet alerts # recent alerts bunx @profullstack/watchwallet ack # acknowledge them all bunx @profullstack/watchwallet rm Cold bunx @profullstack/watchwallet check solana <address> # no key needed bunx @profullstack/watchwallet # the TUI bunx @profullstack/watchwallet mcp # MCP server on stdio
curl "https://watch.wallet.pit.world/api/v1/check?chain=bitcoin&address=bc1q…"
curl https://watch.wallet.pit.world/api/v1/watches -H "authorization: Bearer $WATCHWALLET_KEY"
curl -X POST https://watch.wallet.pit.world/api/v1/watches -H "authorization: Bearer $WATCHWALLET_KEY" \
-H 'content-type: application/json' -d '{"kind":"address","chain":"base","address":"0x…","label":"Treasury"}'
Endpoints: GET /api/v1/me, GET|POST /api/v1/watches, GET|PATCH|DELETE /api/v1/watches/:id, POST /api/v1/watches/:id/(pause|resume), GET /api/v1/alerts, POST /api/v1/alerts/ack, POST /api/v1/alerts/:id/ack, and without a key GET /api/v1/check?chain=&address= (rate limited).
MCP tools: check_address (no key), list_watches, add_watch, add_price_watch, remove_watch, recent_alerts.
What we keep
Your email, the addresses and prices you watch, their last balances and your alerts. We never ask for a private key or a seed, and nothing here can move funds. Delete your account and it all goes.
Who runs this
Profullstack, Inc. Source: github.com/moshcoder/watch.wallet. Questions: alerts@pit.world.