robinhood-chain-alert-bot
Health Warn
- License — License: MIT
- Description — Repository has a description
- Active repo — Last push 0 days ago
- Low visibility — Only 6 GitHub stars
Code Warn
- network request — Outbound network request in docs/app.js
- network request — Outbound network request in scripts/capture-fixtures.ts
- process.env — Environment variable access in src/config.ts
Permissions Pass
- Permissions — No dangerous permissions requested
No AI report is available for this listing yet.
Real-time alert bot for Robinhood Chain - Telegram, Discord, and X (Twitter). Tracks new launches, graduations, whale trades, Stock Token premium/discount arbitrage, holder milestones, and liquidity-pull rug warnings. Free tier, x402 USDG premium.
hood-alerts
The alert layer for Robinhood Chain (chain ID 4663): Telegram and Discord bots, plus optional
X (Twitter) auto-posting, backed by one shared detection engine that watches launches, graduations,
whale trades, Stock Token price moves, on-chain premium/discount arbitrage, holder milestones, and
liquidity-pull rug warnings. Free tier plus x402 USDG premium.
What it detects
| Detector | Topic | Source |
|---|---|---|
| New token launch | launches (launches:noxa, launches:odyssey) |
NOXA (instant Uniswap v3 pool) and The Odyssey (bonding curve) |
| Bonding-curve graduation | graduations |
Odyssey curve fills and migrates to a locked Uniswap v3 pool |
| Whale trades | whales, or per-token token:0x… |
Odyssey curve trades and Uniswap v3 swaps, chain-wide, threshold in USD |
| Stock Token price moves | stock:SYMBOL |
Chainlink feed, rolling window, signed percent change |
| On-chain premium/discount (the arb signal) | premiums (premium tier) |
DEX mid vs Chainlink feed, hysteresis ladder at 1/2/3/5/10/20/50% |
| Holder milestones | per-token token:0x… |
Blockscout token_holders_count, crossing 10 through 100,000 |
| Liquidity-pull rug warning | rugs (premium tier), or per-token token:0x… |
tracked pool's quote-side (USDG/WETH) reserves dropping sharply |
Every event is deduped per fingerprint before it reaches a subscriber, routed through a
premium/quiet-hours/digest gate, and rendered as a platform-native card (Telegram HTML, Discord
embed, a compact X post, or a structured console log line) with links back to the chain explorer
and three.ws/markets/robinhood.
Quickstart (self-host)
npm install
npm run dev # tsx watch, console transport only if no bot tokens are set
With zero environment variables the engine still runs: detectors connect to the public Robinhood
Chain RPC, alerts print as structured JSON log lines (the console transport), and /healthz comes
up on :8080. That is the self-host smoke-test mode. Copy .env.example to .env and fill in a
Telegram and/or Discord bot token to go live on those platforms; see .env.example for every
variable, defaults, and what each detector threshold controls.
npm run build # tsc -> dist/
npm start # node dist/src/index.js
Creating the bots
- Telegram: message @BotFather,
/newbot, paste the token intoHOOD_ALERTS_TELEGRAM_TOKEN. The bot registers its command list on startup. - Discord: create an application at the
Developer Portal, add a bot, copy the bot token
intoHOOD_ALERTS_DISCORD_TOKENand the application id intoHOOD_ALERTS_DISCORD_APP_ID. Slash
commands register (guild-visible immediately) on startup.
Leaving either token unset disables that transport; the engine and the console transport keep
running regardless.
X (Twitter)
X is a broadcast-only transport: there is no inbound bot, so you cannot DM the account and get a
reply the way you can with Telegram or Discord. What it auto-posts is fixed at startup byHOOD_ALERTS_X_TOPICS (default launches,graduations,whales) instead of watch/unwatch
commands, parsed through the same topic resolver the bots use. Pick exactly one of two modes
via HOOD_ALERTS_X_MODE; see .env.example for the full variable list.
official: the real X API v2, POST /2/tweets, signed with your own developer app's OAuth1
user-context credentials. This is the normal, ToS-compliant path, and it costs money: X gates
posting behind a paid API tier. Check current pricing at
developer.x.com/en/portal/products/buy before
relying on it; it has changed before and can change again.
Setup: create an app at the developer portal, generate a
consumer key/secret (HOOD_ALERTS_X_API_KEY / HOOD_ALERTS_X_API_SECRET), then generate an
access token/secret with read and write permissions (HOOD_ALERTS_X_ACCESS_TOKEN /HOOD_ALERTS_X_ACCESS_SECRET). All four are required; hood-alerts signs every request itself with
Node's built-in crypto (HMAC-SHA1 per RFC 5849), no extra dependency.
xactions: posts through a self-hosted XActions
instance instead of the official API: browser-automation driving your own X session cookie. Free,
no developer account, no paid tier. This is not the official API and carries real ToS risk;
run it on an account you are prepared to lose if X acts on that. Point HOOD_ALERTS_XACTIONS_URL
at your running instance and HOOD_ALERTS_XACTIONS_TOKEN at its bearer token. Posting is
async/job-queued: hood-alerts treats a 2xx from POST {url}/api/posting/tweet as "accepted", not
"delivered", and logs that delivery is not confirmed synchronously (the real xactions API responds{ operationId, status: "queued" }, not a tweet id).
Both modes fail loudly: a configured mode missing any required credential logs a warning and
disables the X transport (Telegram, Discord, and the console transport keep running) instead of
crashing the process. Every X post is compacted to fit X's 280-character limit: title, the single
most important line, and the first link; only the text portion truncates, never the URL. Digests
(too many alerts to post individually) post the single most significant event plus a (+N more)
count, and log the full summarized batch, so nothing is silently dropped from the record even
though it is dropped from the post itself.
Bot commands
Both bots share one command router (src/commands/commands.ts), so the UX is identical modulo
native slash-command vs /command arg syntax:
watch <what> [threshold]
launches every new token (add noxa/odyssey to filter)
graduations Odyssey curves migrating to Uniswap v3
whales [usd] trades >= usd, chain-wide (default 5000)
premiums [pct] Stock Token DEX premium/discount vs Chainlink (premium tier)
rugs [pct] liquidity-pull rug warnings (premium tier)
<TICKER> a Stock Token: price moves + premium crossings (e.g. TSLA)
<0x address> a memecoin: whale trades, graduation, holders, liquidity
unwatch <what|all> stop watching
list your subscriptions
threshold <what> <n> change a subscription's threshold
digest on|off [min] batch alerts into digests (default 60 min)
quiet <from> <to> quiet hours in UTC (e.g. quiet 22 7); quiet off
premium premium status + how to upgrade
help this message
In a group chat or server, watch, unwatch, threshold, digest, and quiet are restricted to
admins; list, premium, and help are open to everyone.
Free vs premium
| Free | Premium | |
|---|---|---|
| Subscriptions | 3 | Unlimited |
| Delivery | Batched to at most one immediate alert per 60s; extras fold into a digest | Real-time, subject only to quiet hours / digest mode you set |
premiums (Stock Token arb signal) |
Not available | Included |
rugs (liquidity-pull warning) |
Not available | Included |
| Price | Free | HOOD_ALERTS_PREMIUM_PRICE_USDG (default 5) USDG for HOOD_ALERTS_PREMIUM_DAYS (default 30) days |
Premium is paid on Robinhood Chain via x402 using hood402 (USDG,
EIP-3009 transferWithAuthorization, chain 4663). The bot's premium command hands back aPOST /premium/activate?platform=...&chat=... URL: the first request gets a 402 challenge with
payment instructions, and any x402 client (hood402, x402-fetch) that can sign a USDG
authorization completes the purchase. The entitlement never activates before the transfer settles
on-chain, so a signature alone buys nothing.
Purchases stay disabled (503 + setup instructions) until the instance sets HOOD402_PAY_TO and
either HOOD402_FACILITATOR_URL (delegates verification and settlement, no gas key on this box) orHOOD402_SETTLER_KEY (this instance broadcasts the settlement itself). See .env.example for both
modes.
HTTP API
The same process that runs the bots serves a small Hono app on PORT (default 8080):
| Endpoint | Method | Returns |
|---|---|---|
/ |
GET | service metadata and endpoint list |
/healthz |
GET | uptime, last detector event time, per-event-type counts, whether premium purchases are enabled |
/premium/status?platform=telegram|discord|console|x&chat=<id> |
GET | { tier: 'free' | 'premium', expiresAt } for that chat |
/premium/activate?platform=...&chat=... |
POST | the x402 purchase flow: 402 challenge, then 200 + entitlement once payment settles |
Example: reading the alert engine's pure logic directly
src/engine/gate.ts and src/engine/topics.ts have no I/O and are safe to import standalone, for
example to preview how a threshold will gate before wiring a subscription:
import { gate } from './src/engine/gate.js'
import { resolveWatchTarget, parseTopic } from './src/engine/topics.js'
const target = resolveWatchTarget('whales') // { ok: true, topic: 'whales' }
if (target.ok) {
const topic = parseTopic(target.topic) // { kind: 'whales' }
const decision = gate(
{ premium: false, digest: false, quietStart: null, quietEnd: null, lastDeliveredAt: null, deliveredLastMinute: 0 },
Math.floor(Date.now() / 1000),
)
console.log(topic, decision) // { kind: 'whales' } { action: 'deliver' }
}
A threshold typed after the target (watch whales 10000) is parsed separately byCommands.watch(), not by resolveWatchTarget itself.
The package does not ship a public library entry point today (main/bin both point at the CLI
process in src/index.ts, which starts the bots and the HTTP server and does not export anything);
importing from src/ as above works in this checkout but is not a published API contract.
Configuration
Every variable, its default, and what it controls: .env.example. Highlights:
HOOD_ALERTS_RPC_URL— custom RPC; defaults to viem's publicrobinhoodchain RPC.HOOD_ALERTS_DB— SQLite path (subscriptions, entitlements, dedup, delivery log).:memory:
works for tests.HOOD_ALERTS_WHALE_FLOOR_USD/HOOD_ALERTS_WHALE_DEFAULT_USD— engine-side emission floor vs.
the default per-subscription threshold.HOOD_ALERTS_PRICE_WINDOW_S/HOOD_ALERTS_PRICE_DEFAULT_PCT— Chainlink rolling-window move
detector.HOOD_ALERTS_PREMIUM_POLL_S/HOOD_ALERTS_PREMIUM_DEFAULT_PCT— Stock Token arb poll cadence
and default ladder entry.HOOD_ALERTS_RUG_DEFAULT_PCT— default liquidity-pull threshold (percent of quote reserves).
Development
npm install
npm run typecheck # tsc --noEmit, strict + exactOptionalPropertyTypes
npm test # vitest: dedup/rate-limit gate, digest batching, topic parsing and
# matching, event fingerprinting/TTL, alert card rendering, config
# loading, the command router, and the subscriber/entitlement/delivery
# repositories — all offline, no chain or bot credentials required
npm run build # tsc -> dist/
The whale-classify and detectors suites run against real captured mainnet event streams intests/fixtures/ (real Uniswap v3 swaps, Odyssey bonding-curve trades, and Chainlink prices).
Refresh them any time with npm run capture-fixtures, which re-reads live chain 4663.
npm run test:live and npm run probe exercise the live detector set against real Robinhood Chain
RPC and, for probe, the console transport; they need real network access and are not part of the
offline unit suite above. npm run grant-premium comps or inspects a premium entitlement directly
in the database (handy for testing premium delivery before a payment rail is wired).
Local sibling packages
hood402, hoodkit, and hoodchain are consumed as file: dependencies of the other Robinhood
Chain repos in this workspace (../hood402, ../hoodkit, ../robinhood-chain-sdk) rather than
their published npm versions, so a change to any of them is picked up on the next npm install
here. A file: link keeps each sibling's own viem copy, so a patch-level skew (e.g. 2.55.2
here vs 2.55.1 in hood402) makes viem's structural Chain / WalletClient types diverge across
the two copies. src/premium/paywall.ts bridges that boundary explicitly (casting the local viem
clients to hood402's HoodBroadcaster / HoodConfirmer), so the build stays green across a patch
skew; the runtime objects are the same correct viem clients. Once the siblings are on npm and a
single viem resolves, the cast is a no-op.
Deploy
hood-alerts is one long-running process (engine + HTTP server + both bots), so run it as a service
with a warm instance, not a job. hoodchain/hoodkit/hood402 are ordinary published npm
dependencies (see package.json) — the Docker build needs no special context, just this directory:
docker build -t hood-alerts .
docker run -p 8080:8080 -v hood-alerts-data:/data hood-alerts
gcloud run deploy hood-alerts \
--source . \
--region us-central1 \
--min-instances=1 --no-cpu-throttling --port=8080 \
--set-env-vars=HOOD_ALERTS_TELEGRAM_TOKEN=…,HOOD_ALERTS_DISCORD_TOKEN=…,HOOD_ALERTS_DISCORD_APP_ID=…
The Run on Google Cloud button above does this for you. Mount a volume at /data (the defaultHOOD_ALERTS_DB path) so subscriptions, entitlements, and the delivery log survive restarts. The
container answers GET /healthz (confirmed: real on-chain pool discovery finishes and the server
starts serving within ~10s of boot); SIGTERM flushes pending digests before exit. Full self-host
and premium-wiring guide: the docs/ site.
Docs site (GitHub Pages, Cloudflare, or Vercel)
docs/ is a static, hand-built site (no framework, no build step): open docs/index.html locally,
or serve it from any static host. Its landing page renders a live premium/discount feed
client-side straight from the public RPC (real Chainlink feeds vs real DEX pools, no server).
- GitHub Pages (default, canonical home):
Settings → Pages → Deploy from a branch → main → /docs→ https://nirholas.github.io/robinhood-chain-alert-bot/. - Cloudflare / Vercel: click the buttons above —
wrangler.json/vercel.jsonat the repo
root point both atdocs/, no build command needed.
Architecture notes
- Console transport is not a fallback, it's the smoke-test mode. With no bot tokens configured
the engine still ingests real chain events and logs every alert/digest as structured JSON; that
is how a fresh self-host proves the pipeline works before touching Telegram or Discord. - The entitlement never activates before settlement.
PremiumPaywall.activate()callshood402's verify-then-settle flow and only writes the entitlement row after the on-chain
transfer succeeds. - Digest buffering is in-memory by design. A restart loses at most one pending batch, never a
subscription (subscriptions and the delivery log are in SQLite);AlertEngine.stop()flushes
every buffered digest before shutdown. - Auto-tracked pools expire; watched pools do not. A NOXA/Odyssey launch or graduation starts a
24h rug-watch on its pool automatically; a userwatch 0x…keeps that pool's liquidity monitor
running indefinitely.
Repo layout
src/index.ts CLI entry: wires config, db, engine, detectors, transports, HTTP server
src/config.ts environment -> validated Config
src/server.ts Hono app: /, /healthz, /premium/status, /premium/activate
src/engine/ event types, dedup fingerprinting, topic parsing/matching, the
digest buffer, the delivery gate, and the live detector set
src/engine/detectors/ pure per-signal detectors (price move, premium ladder, holder
milestones, liquidity pull, whale classification) plus live.ts,
which wires them to hoodchain/hoodkit streams
src/db/ better-sqlite3 repositories: subscribers, entitlements, deliveries
src/premium/paywall.ts the hood402 x402 purchase flow
src/transports/ Telegram (grammY), Discord (discord.js), X (OAuth1 API v2 or self-
hosted xactions), and console transports
src/commands/commands.ts the shared, platform-neutral command router
src/format/cards.ts alert -> platform-neutral card -> per-platform rendering
tests/ vitest unit suite + tests/fixtures (real captured chain events) +
tests/live (opt-in on-chain reads)
scripts/ capture-fixtures, live-probe, grant-premium (see Development above)
docs/ static GitHub Pages site with a live client-side premium feed
Dockerfile one-container build (engine + both bots), build from robinhood/
Notes
- Stock Tokens. Stock Tokens are tokenized debt securities (issuer: Robinhood Assets (Jersey)
Ltd) and may not be offered, sold, or delivered to US persons (additional limits: Canada, UK,
Switzerland). hood-alerts only ever displays price/premium data derived from public Chainlink
feeds and DEX pools; it never facilitates acquiring a Stock Token. - Liquidity-pull alerts are an early warning, not proof of a rug: always check the pool before
acting on one. - Not affiliated with Robinhood Markets, Inc.
License
MIT. See LICENSE.
Reviews (0)
Sign in to leave a review.
Leave a reviewNo results found