hood-alerts

Self-host

hood-alerts is one long-running process: the detection engine, an HTTP server (/healthz plus the premium endpoints), and both bots, each enabled by the presence of its token. It is a service, not a cron job.

Run it locally

git clone https://github.com/nirholas/hood-alerts
cd hood-alerts
# Until the sibling packages are on npm, link them locally:
npm i ../robinhood-chain-sdk ../hoodkit ../hood402
npm install
cp .env.example .env      # fill in what you use (all optional)
npm run build && npm start

With zero configuration it runs the engine plus the console transport, printing every alert it detects to stdout. That is the smoke test:

npm run probe             # 90s live detection against mainnet 4663, no tokens
npm run probe -- --token 0xTOKEN --seconds 300

Add the bots

Env varHow to get it
HOOD_ALERTS_TELEGRAM_TOKENMessage @BotFather, run /newbot, copy the token.
HOOD_ALERTS_DISCORD_TOKEN
HOOD_ALERTS_DISCORD_APP_ID
Create an app at the Discord Developer Portal; copy the Bot token and Application ID. Invite it with applications.commands + bot scopes.
HOOD_ALERTS_X_MODE=official
HOOD_ALERTS_X_API_KEY / _API_SECRET / _ACCESS_TOKEN / _ACCESS_SECRET
X API v2 (OAuth1, user-context). Create an app at developer.x.com with read+write access, copy the four credentials. Needs a posting-capable API tier — check current pricing there.
HOOD_ALERTS_X_MODE=xactions
HOOD_ALERTS_XACTIONS_URL / _XACTIONS_TOKEN
Free, self-hosted alternative: point at your own running xactions instance. Browser-session automation, not the official API — ToS risk, delivery isn't confirmed synchronously.
HOOD_ALERTS_X_TOPICSComma-separated topics to auto-post (default launches,graduations,whales). No inbound X bot, so this is fixed at startup, not set via a chat command.

Each transport is optional: set only the tokens you want. The others stay disabled and log a warning.

Premium payments

Premium purchase endpoints stay off (returning a helpful 503) until you set a receiving address and one settlement mode:

Env varPurpose
HOOD402_PAY_TOAddress that receives premium USDG. Required to sell premium.
HOOD402_FACILITATOR_URLSettlement mode A: delegate verify + settle to a hood402 facilitator. No gas key on this box.
HOOD402_SETTLER_KEYSettlement mode B: self-settle by broadcasting transferWithAuthorization yourself. A funded gas key.
HOOD_ALERTS_PREMIUM_PRICE_USDG
HOOD_ALERTS_PREMIUM_DAYS
Price and duration of one purchase. Defaults: 5 USDG for 30 days.
Prefer facilitator mode. If you use a settler key, treat it like any hot wallet: fund it with only the ETH gas it needs, and never commit it. Every wallet key comes from the environment; nothing is read from code.

To comp a chat or test premium delivery before wiring a rail:

npm run grant-premium -- grant telegram <chatId> --days 30
npm run grant-premium -- status telegram <chatId>
npm run grant-premium -- revoke telegram <chatId>

Deploy to Cloud Run

The build context is the parent robinhood/ directory so the local file: siblings resolve.

# From robinhood/ (the parent of hood-alerts/)
docker build -f hood-alerts/Dockerfile -t hood-alerts .

# Push and deploy (long-running service: keep one warm instance)
gcloud run deploy hood-alerts \
  --image=REGION-docker.pkg.dev/PROJECT/repo/hood-alerts:latest \
  --min-instances=1 --no-cpu-throttling \
  --set-env-vars=HOOD_ALERTS_TELEGRAM_TOKEN=…,HOOD_ALERTS_DISCORD_TOKEN=…,HOOD_ALERTS_DISCORD_APP_ID=… \
  --set-env-vars=HOOD402_PAY_TO=0x… \
  --port=8080

Mount a persistent volume at /data (the default HOOD_ALERTS_DB path) so subscriptions, entitlements, and the delivery log survive restarts. The container answers GET /healthz with uptime, the last event time, and per-type event counts; graceful shutdown on SIGTERM flushes any pending digests.

Configuration reference

Every knob is an environment variable with a sensible default; see .env.example in the repo for the full annotated list, including detector thresholds (HOOD_ALERTS_WHALE_FLOOR_USD, HOOD_ALERTS_PRICE_WINDOW_S, HOOD_ALERTS_RUG_DEFAULT_PCT, and more).

See it on the instrument

Every env var above that tunes a detector also shows up in that channel's config on the signal timeline — e.g. whales, premium/discount, liquidity pulls.