HyperCore Order Monitor is a production-ready Next.js app that tracks Hyperliquid Core (L1) trading orders in real time using Quicknode Streams with intelligent, real-time filtering powered by Quicknode KV Store.
Add or remove trader addresses through the UI (single or bulk import), and the Quicknode Streams filter updates instantly via KV Store lists. No stream restart required - start monitoring a whale trader and see their orders immediately.
Toggle which order statuses you want to track (open, filled, cancelled, rejected, etc.) directly from the UI with a categorized status filter panel. Changes sync to KV Store in real-time, and the stream filter adjusts automatically - only the events you care about reach your webhook.
Filtering happens at the stream level using Quicknode Streams Filter and Quicknode KV lists, not in your application code. This means you only process the exact data you need - no wasted bandwidth or compute on irrelevant orders.
Live order feed with rich order details powered by Server-Sent Events (SSE) - see new orders appear instantly without polling.
Pre-built scripts for Quicknode Streams setup and activation, plus Prisma migrations and database seeding - get up and running in minutes.
Hyperliquid Core (L1)
-> Quicknode Streams + KV
-> POST /api/webhook/streams (signature verified)
-> OrderLog upsert + SSE emit
-> Live UI order feed
- Node.js 20+ and a package manager (pnpm/npm/yarn)
- Quicknode account with API key that has Streams + KV access
- Public webhook URL for local development (use ngrok or similar tunneling service)
- Git for cloning the repository
Optional (for ENS name resolution):
- Ethereum mainnet RPC URL from Quicknode
| Variable | Required | Description | Where to Get |
|---|---|---|---|
QN_API_KEY |
Yes | Quicknode API key with Streams + KV access | Quicknode Dashboard |
APP_URL |
Yes | Public webhook URL (must be reachable by Quicknode) | Use ngrok for local dev (see setup below) |
QN_STREAM_SECURITY_TOKEN |
Yes | Stream security token | Generated by pnpm run setup:streams |
DATABASE_URL |
Yes | SQLite database path | file:./dev.db (default) |
QN_EVM_ENDPOINT |
No | Ethereum RPC for ENS name resolution | Quicknode Endpoints |
ADMIN_API_KEY |
Production | API key for admin endpoint protection | Generate secure random string |
NEXT_PUBLIC_APP_NAME |
No | Application display name | HyperCore Order Monitor (default) |
Important Notes:
- Never commit
.envto git - it contains sensitive credentials QN_API_KEYmust have both Streams and KV permissions enabledAPP_URLmust be set before runningsetup:streams(it becomes the webhook destination)ADMIN_API_KEYis optional for local dev but required for production deployments
git clone https://github.com/quiknode-labs/qn-hypercore-order-monitor.git
cd qn-hypercore-order-monitor# Using pnpm
pnpm install
# OR using npm
npm install
# OR using yarn
yarn installcp .env.example .env.env file NOW before proceeding. You must configure:
-
QN_API_KEY: Get from Quicknode Dashboard- Ensure your API key has Streams and KV permissions enabled
-
APP_URL: Your public webhook URL (required for stream setup)- For local development, use ngrok (see below)
- This URL must be publicly accessible by Quicknode
# Install ngrok (macOS)
brew install ngrok
# OR download from https://ngrok.com/download
# Start ngrok tunnel pointing to port 3000
ngrok http 3000Copy the https:// URL from ngrok output (e.g., https://abc123.ngrok-free.app) and add it to your .env file:
APP_URL="https://abc123.ngrok-free.app"Tip: Keep ngrok running in a separate terminal. The URL remains valid as long as ngrok is running.
# Using pnpm
pnpm prisma migrate dev --name hypercore-order-monitor
pnpm db:seed
# OR using npm
npm run prisma migrate dev --name hypercore-order-monitor
npm run db:seed
# OR using yarn
yarn prisma migrate dev --name hypercore-order-monitor
yarn db:seedWhat db:seed does:
- Creates all available status filters in the database
- Enables successful order statuses by default:
open,filled,triggered - Adds one sample trader address (
0xd48374090fe4df231f7002d592b6c67c4c875b1a) to help you get started - This sample address will be used for filter testing during stream creation (Step 6)
- The same address and activated statuses will be added to the KV Store lists during
setup:streams
# Using pnpm
pnpm run setup:streams
# OR using npm
npm run setup:streams
# OR using yarn
yarn run setup:streamsThis script will:
- Create KV lists for address and status filtering with initial data from the database
- Test the filter on a known block
- Create a paused stream with your
APP_URLas the destination - Print a
QN_STREAM_SECURITY_TOKEN
Copy the security token from the output and add it to your .env file:
QN_STREAM_SECURITY_TOKEN="qnsec_..."# Using pnpm
pnpm dev
# OR using npm
npm run dev
# OR using yarn
yarn dev# Using pnpm
pnpm run activate:streams
# OR using npm
npm run activate:streams
# OR using yarn
yarn run activate:streams- Open http://localhost:3000
- Orders from monitored traders will start flowing to your webhook in real-time
- Add more traders using the "Add Monitored Trader" form, or use bulk import with these sample whale traders:
0xf17de447fdfa1778db06111e3cbdc878332adab2, Whale 1
0x0b506be94c45382b11685cff769e5e76fcd8bd65, Whale 2
0x4911505cbb6cc71f71b59ef1ec0ee99f6c57a8a0, Whale 3
0xaa44894f7c04c77fcf2807576834b93f6a8cb844, Whale 4
0x4ce87901d7356250156afd04fef88ea492f53f88, Whale 5
0x019514701c6f9d887926b3b8da7444b69f57d4df, Whale 6
0x1ee7a73cb5b0b6b056d8138085b2009e6a6bedf5, Whale 7
0x7e280c1b204072a5f3e346fa57e0105d68ef6efd, Whale 8
0xa289ee1e56c0d5d041db762e6123e78af0f7d9ad, Whale 9
When you add a trader:
- The address is immediately added to the KV Store
userstream_hl_userslist - The Quicknode Stream filter picks it up instantly - no restart needed
- Orders from this trader will start flowing to your webhook in real-time
Customize tracked statuses:
- Click on the Status Filter panel in the UI
- Toggle statuses on/off (e.g., enable
cancelledandrejectedto track failed orders) - Changes sync to the KV Store
userstream_hl_statuseslist immediately - The stream filter updates automatically - only enabled status orders reach your webhook
Once configured, orders matching your filters will stream in real-time!
hypercore-order-monitor.mov
Live order feed showing real-time trading activity from monitored Hyperliquid traders
This application includes admin API endpoints that must be protected in production. For local development, authentication is optional.
Add an admin API key to your .env file:
# Generate a secure random string (e.g., using openssl)
openssl rand -base64 32
# Add to .env
ADMIN_API_KEY="your-secure-random-key-here"The following endpoints require Authorization: Bearer <ADMIN_API_KEY> header:
POST /api/users- Add monitored traderPOST /api/users/bulk- Bulk add tradersPATCH /api/users- Update trader infoDELETE /api/users- Remove traderGET /api/orders- List ordersPATCH /api/statuses- Update status filtersPOST /api/statuses/reset- Reset status filters
Example authenticated request:
curl -X POST http://localhost:3000/api/users \
-H "Authorization: Bearer your-admin-api-key" \
-H "Content-Type: application/json" \
-d '{"walletAddress": "0x..."}'GET /api/users- List monitored traders (read-only)GET /api/statuses- List status filters (read-only)POST /api/webhook/streams- Quicknode webhook (uses signature verification)GET /api/sse- Server-Sent Events streamGET /api/health- Health check
Note: The webhook endpoint (/api/webhook/streams) uses Quicknode's signature verification and does not require the admin API key.
The application implements basic rate limiting to prevent abuse:
- Bulk operations are limited to 50 addresses per request
- Consider implementing additional rate limiting for production deployments
- Never commit
.envto version control - it contains sensitive credentials - Rotate credentials regularly - especially after team changes
- Use strong, randomly generated API keys - minimum 32 characters
- Enable CORS restrictions if deploying behind a specific domain
- Monitor logs for unauthorized access attempts
- Use HTTPS for all production deployments
If you discover a security vulnerability, please:
- Do not open a public GitHub issue
- Email the maintainers or file a private security advisory
- Provide details about the vulnerability and steps to reproduce
Learn more about Quicknode Streams and KV Store in the official documentation.
The HyperCore filter is already provided:
filters/hl-orders-filter.js
When you run pnpm run setup:streams, it will:
- Create KV lists:
userstream_hl_usersanduserstream_hl_statuses - Seed status list with
open,filled,triggered - Test the filter on a known block
- Create a stream (paused) and print the security token
You can override options with key=value arguments:
pnpm run setup:streams chain=hypercore-mainnet name="HyperCore Order Monitor" test_block_number=862932944Activate the most recently created stream:
pnpm run activate:streamsFor more details, see the Quicknode Streams Documentation.
Order status filtering is implemented in two places:
- Database:
StatusFiltertable (source of truth) - Quicknode KV list:
userstream_hl_statuses(drives stream filter)
Default enabled statuses:
open, filled, triggered
Toggles in the UI call /api/statuses and sync to KV immediately.
If you need to reconcile KV with the database (for example after manual edits), run:
pnpm run sync:statuses
To reconcile monitored traders in KV with the database, run:
pnpm run sync:users
SQLite is used by default. Prisma schema lives in prisma/schema.prisma.
Common commands:
pnpm prisma migrate dev --name hypercore-order-monitor
pnpm db:seed
pnpm prisma studio
Webhook endpoint: POST /api/webhook/streams
Required headers:
x-qn-noncex-qn-timestampx-qn-signature
Payload example:
docs/PAYLOAD-STRUCTURE.json
The request can be gzip-compressed. The handler auto-detects content-encoding: gzip.
GET /api/health- health checkGET /api/users- list monitored tradersPOST /api/users- add trader (walletAddress, optionalname)PATCH /api/users?id=...- update trader name/displayNameDELETE /api/users?id=...- remove traderPOST /api/users/bulk- bulk add (newline-separated, supports "address, label")GET /api/orders- list orders with filtersGET /api/statuses- list status filtersPATCH /api/statuses- update enabled status filtersPOST /api/statuses/reset- reset to default statusesPOST /api/webhook/streams- Quicknode Streams webhookPOST /api/webhook/test- local-only webhook testGET /api/sse- SSE stream of order events
filters/
hl-orders-filter.js # HyperCore Streams filter
scripts/
setup-streams.ts # Creates KV lists + stream
activate-streams.ts # Activates stream by id
reset-kv.ts # Deletes HyperCore KV lists
prisma/
schema.prisma # SQLite schema
seed.ts # Seeds StatusFilter defaults
src/
app/ # App Router routes + pages
components/ # UI components
lib/ # Quicknode, webhook, SSE helpers
types/ # Shared types
docs/
PAYLOAD-STRUCTURE.json # Sample stream payload
pnpm dev
pnpm build
pnpm start
pnpm lint
pnpm typecheck
pnpm test
pnpm run setup:streams
pnpm run activate:streams
pnpm db:seed
pnpm reset:kv
pnpm sync:statuses
pnpm sync:users
Unit tests use Vitest. Webhook and SSE routes have dedicated tests under src/app/api/__tests__.
pnpm test
Missing webhook events:
- Ensure
APP_URLis publicly reachable and the stream is active - Check that ngrok is still running (URLs expire when ngrok stops)
- Verify stream status in Quicknode Dashboard
- Check logs:
pnpm run activate:streamsshould show stream as "running"
401 Unauthorized from webhook:
- Verify
QN_STREAM_SECURITY_TOKENmatches the token from setup output - Check Quicknode signature headers are present (
x-qn-signature,x-qn-timestamp,x-qn-nonce) - Ensure you haven't modified the webhook URL after stream creation
KV list errors:
- Confirm
QN_API_KEYhas both Streams and KV access enabled - Check your Quicknode Dashboard API Keys for permissions
- Verify KV lists exist:
userstream_hl_usersanduserstream_hl_statuses
ENS resolution issues:
- Confirm
QN_EVM_ENDPOINTpoints to Ethereum mainnet - Get an Ethereum endpoint from Quicknode
- ENS resolution is optional - addresses will work without it
Authentication errors (401):
- If you set
ADMIN_API_KEY, ensure you're sending it in requests - Check header format:
Authorization: Bearer <your-key> - For local development,
ADMIN_API_KEYcan be left empty
- Quicknode Streams Guides
- Quicknode KV Store Docs
- Quicknode Support
- GitHub Issues for this repository
MIT
