Canonical setup guide:
docs/ENVIRONMENT_SETUP.md
This guide walks you through setting up a local development environment for NotifyChain. By the end, you will have the listener service, the dashboard, the frontend analytics app, and the smart contracts building and running on your machine.
For the canonical contribution workflow, start with
CONTRIBUTOR_DEVELOPMENT_WORKFLOW_GUIDE.md.
For a shorter setup path, see LOCAL_DEVELOPMENT.md.
That document contains step-by-step instructions to install required tools,
clone the repository, configure the listener and dashboard, build contracts, and
verify your installation (including CI-parity checks).
For day-to-day development after setup, see LOCAL_DEVELOPMENT.md. For Git workflow (fork, branch, PR), see CONTRIBUTOR_DEVELOPMENT_WORKFLOW_GUIDE.md.
Goal: a new contributor should be able to set up NotifyChain from scratch on a clean machine without asking maintainers for help.
- Required Dependencies
- Clone the Repository
- Listener Service Setup
- Dashboard Setup
- Frontend (Next.js Analytics) Setup
- Smart Contracts Setup
- Environment Variables Reference
- Full-Stack Verification Checklist
- Running Tests
- VS Code Setup (Recommended)
- Troubleshooting & FAQ
- Smart Contracts Setup
- Environment Variables Reference
- Running Tests
- VS Code Setup
- Troubleshooting & FAQ
| Dependency | Minimum Version | Install | Used By |
|---|---|---|---|
| Rust (stable) | stable | rustup.rs | Smart contracts |
wasm32-unknown-unknown |
— | rustup target add wasm32-unknown-unknown |
Soroban contracts |
| Stellar CLI | latest | cargo install --locked stellar-cli --features opt |
Contract build/deploy |
| Node.js | 22 | nodejs.org or nvm |
Listener, Dashboard |
| Git | — | your package manager | Version control |
| Dependency | Minimum Version | Install Method | Used By |
|---|---|---|---|
| Rust | stable | rustup.rs | Smart contracts |
wasm32-unknown-unknown |
— | rustup target add wasm32-unknown-unknown |
Soroban contracts |
| Stellar CLI | latest | cargo install --locked stellar-cli --features opt |
Contract build/deploy |
| Node.js | 18 (dashboard), 20 (listener) | nodejs.org or nvm |
Listener, Dashboard |
| npm | comes with Node | — | Package management |
| Git | — | Your package manager or git-scm.com | Version control |
- macOS: Install Xcode Command Line Tools first:
xcode-select --install - Linux: Install build tools first:
sudo apt install build-essential - Windows: Install Visual Studio Build Tools with the "C++ build tools" workload (needed for native
sqlite3bindings)
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
source "$HOME/.cargo/env"
rustup target add wasm32-unknown-unknown
cargo install --locked stellar-cli --features opt
# Verify
rustc --version && cargo --version && stellar --versionDocker removes the need to install Node.js or manage per-service env files. All you need is Docker Desktop (or Docker Engine + Compose on Linux).
# 1. Copy the root env file (only needed once)
cp .env.example .env
# 2. Edit .env — at minimum set CONTRACT_ADDRESSES to your deployed contract ID
# 3. Build images and start listener + dashboard
docker compose up --build| Service | URL |
|---|---|
| Dashboard (Vite HMR) | http://localhost:5173 |
| Listener API | http://localhost:8787 |
| Listener health check | http://localhost:8787/health |
The SQLite database is stored in a named Docker volume (listener_data) and persists across container restarts.
docker compose up --build # rebuild images and start (needed after code changes)
docker compose up # start with existing images
docker compose down # stop and remove containers
docker compose down -v # stop and delete the database volume (full reset)
docker compose logs -f listener # tail listener logs
docker compose logs -f dashboard # tail dashboard logs
docker compose restart listener # restart one service after env changeEdit .env at the repo root, then:
git clone https://github.com/Core-Foundry/Notify-Chain.git
cd Notify-Chain
docker compose restart listener # for most listener settings
docker compose up --build dashboard # required if VITE_* vars changed (baked in at build time)docker compose down -v # removes listener_data volume
docker compose up # fresh start — migrations run automatically on bootThe Rust/Soroban contract is a build-only component — no runtime container exists for it. Build and test it locally following Smart Contracts Setup.
Follow sections 2–9 below to set up each component directly on your machine.
Fork the repo on GitHub first, then:
git clone https://github.com/YOUR-USERNAME/Notify-Chain.git
cd Notify-Chain
git remote add upstream https://github.com/Core-Foundry/Notify-Chain.gitVerify remotes:
git remote -v
# origin https://github.com/YOUR-USERNAME/Notify-Chain.git (fetch)
# upstream https://github.com/Core-Foundry/Notify-Chain.git (fetch)The listener is the core off-chain service that polls the Stellar network, processes contract events, and delivers notifications.
cd listener
npm installIf
npm installfails withnode-gyporsqlite3errors, see Troubleshooting.
cp .env.example .envMinimum required values in listener/.env:
STELLAR_RPC_URL=https://soroban-testnet.stellar.org:443
CONTRACT_ADDRESSES=[{"address":"YOUR_CONTRACT_ID","events":["*"]}]For Discord notifications, also add:
DISCORD_WEBHOOK_URL=https://discord.com/api/webhooks/YOUR_WEBHOOK_ID/YOUR_TOKEN
DISCORD_WEBHOOK_ID=YOUR_WEBHOOK_IDFull variable reference: Environment Variables Reference.
npm run migrateThis creates listener/data/notifications.db and runs all schema migrations.
npm run devVerify it's working:
curl http://localhost:8787/health
curl http://localhost:8787/api/events| Command | Purpose |
|---|---|
npm run dev |
Start in dev mode (ts-node, hot reload) |
npm run build |
Compile TypeScript |
npm start |
Run compiled production build |
npm test |
Run all tests |
npm run typecheck |
TypeScript type check (no emit) |
npm run lint |
ESLint |
npm run migrate |
Initialize or update SQLite schema |
The dashboard is a React + Vite app that visualizes events from the listener's API.
cd dashboard
npm installcp .env.example .envDefault .env.example works for local development:
VITE_EVENTS_API_URL=http://localhost:8787/api/events
VITE_STELLAR_NETWORK=TESTNETnpm run devOpen http://localhost:5173. The dashboard fetches from the listener API.
| Command | Purpose |
|---|---|
npm run dev |
Start Vite dev server |
npm run build |
TypeScript check + Vite production build |
npm test |
Run all tests |
npm run lint |
ESLint (zero warnings) |
npm run preview |
Preview production build locally |
npm run benchmark |
Run rendering performance benchmarks |
Only needed if you're modifying or deploying contracts.
cd contract
stellar contract buildOutput goes to contract/target/wasm32-unknown-unknown/release/.
cd contract/contracts/hello-world
cargo test# Generate and fund a testnet identity
stellar keys generate my-identity --network testnet
stellar keys fund my-identity --network testnet
# Deploy
cd contract
stellar contract deploy \
--wasm target/wasm32-unknown-unknown/release/hello_world.wasm \
--source my-identity \
--network testnet
# Contract ID is printed on success| Command | Purpose |
|---|---|
stellar contract build |
Build all contracts |
cargo test |
Run contract unit tests |
cargo fmt --all |
Format Rust code |
cargo fmt --all -- --check |
Verify formatting (used in CI) |
stellar contract deploy ... |
Deploy to testnet |
stellar contract invoke ... |
Call a contract function |
| Variable | Required | Default | Description |
|---|---|---|---|
STELLAR_RPC_URL |
Yes | https://soroban-testnet.stellar.org:443 |
Soroban RPC endpoint |
CONTRACT_ADDRESSES |
Yes | [] |
JSON array: [{"address":"C...","events":["*"]}] |
STELLAR_NETWORK |
No | testnet |
Network passphrase |
POLL_INTERVAL_MS |
No | 30000 |
Time between RPC polls (ms) |
MAX_RECONNECT_ATTEMPTS |
No | 5 |
Max RPC failures before stopping |
RECONNECT_DELAY_MS |
No | 5000 |
Base delay between reconnect attempts |
EVENTS_API_PORT |
No | 8787 |
HTTP server port |
EVENTS_API_CORS_ORIGIN |
No | http://localhost:5173 |
Allowed CORS origin |
DATABASE_PATH |
No | ./data/notifications.db |
SQLite file path |
DISCORD_WEBHOOK_URL |
No | — | Discord webhook URL |
DISCORD_WEBHOOK_ID |
No | — | Discord webhook ID (required with URL) |
RETRY_BASE_DELAY_MS |
No | 5000 |
Base delay for notification retry backoff |
RETRY_MAX_RETRIES |
No | 5 |
Max retry attempts for failed notifications |
SCHEDULER_ENABLED |
No | true |
Enable notification scheduler |
SCHEDULER_POLL_INTERVAL_MS |
No | 10000 |
Scheduler poll frequency (ms) |
SCHEDULER_BATCH_SIZE |
No | 10 |
Max notifications per scheduler cycle |
RATE_LIMIT_ENABLED |
No | true |
Enable HTTP API rate limiting |
RATE_LIMIT_MAX_REQUESTS |
No | 60 |
Max requests per window per client |
LOG_LEVEL |
No | info |
Winston log level (error,warn,info,debug) |
NODE_ENV |
No | — | Set to production for JSON log output |
| Variable | Required | Default | Description |
|---|---|---|---|
VITE_EVENTS_API_URL |
No | http://localhost:8787/api/events |
Listener API endpoint |
VITE_STELLAR_NETWORK |
No | TESTNET |
Stellar network (TESTNET or MAINNET) |
STELLAR_RPC_URL=https://soroban-testnet.stellar.org:443
CONTRACT_ADDRESSES=[{"address":"C...","events":["*"]}]
EVENTS_API_PORT=8787
EVENTS_API_CORS_ORIGIN=http://localhost:5173
DATABASE_PATH=./data/notifications.dbRun these before opening any PR.
cd contract/contracts/hello-world
cargo fmt --all -- --check # must be clean
cargo testcd listener
npm run typecheck
npm run lint
npm testcd dashboard
npm run lint
npm run build
npm test# Dashboard
npm run lint && npm run build && npm test
# Listener
npm run lint && npm run typecheck && npm test
# Contracts
cargo fmt --all -- --check
cargo test --workspace --all-features --verbose
cargo test fuzz_ --verbose -- --nocapture- rust-analyzer
- CodeLLDB — Rust debugger
- ESLint
- Prettier
- Better TOML
The repo includes this already:
{
"rust-analyzer.cargo.target": "wasm32-unknown-unknown",
"rust-analyzer.checkOnSave.allTargets": false
}This prevents false-positive errors from non-Wasm platform checks.
Native sqlite3 bindings must be compiled for your platform:
npm rebuild sqlite3
# If that fails:
npm uninstall sqlite3 && npm installOn Windows, ensure Visual Studio Build Tools are installed with the "C++ build tools" workload.
- Confirm the contract ID in
CONTRACT_ADDRESSESis deployed on the same network asSTELLAR_RPC_URL. - Check the RPC is reachable:
curl -X POST https://soroban-testnet.stellar.org:443 \ -H "Content-Type: application/json" \ -d '{"jsonrpc":"2.0","id":1,"method":"getHealth"}'
- Check listener logs for poll output — look for
"Received events".
source "$HOME/.cargo/env"
# Or reinstall:
cargo install --locked stellar-cli --features optcd listener
mkdir -p data
npm run migrate# macOS/Linux — find and kill the process
lsof -i :8787
kill -9 <PID>
# Or change the port in listener/.env
EVENTS_API_PORT=8788- Is the listener running? (
npm run devinlistener/) - Does
VITE_EVENTS_API_URLindashboard/.envmatch the listener port? - Restart the Vite dev server after editing
.env.
rustup target add wasm32-unknown-unknowncd listener && npm install && npm run migrate
cd dashboard && npm install
cd contract && stellar contract buildWith Docker, rebuild after pulling:
docker compose up --buildVITE_EVENTS_API_URL is baked in at image build time. If you changed it in .env, you need to rebuild:
docker compose up --build dashboardAlso confirm the listener is healthy before the dashboard starts:
docker compose ps # check listener status shows "healthy"
docker compose logs listenerdocker compose down -v # removes the volume
docker compose up --build # fresh start, migrations run automatically- Search open issues — your problem may already be reported.
- Search open issues — your problem may already be reported.
- Read the detailed Troubleshooting Guide.
- Open a new issue with:
- Your OS and version
- Output of
rustc --version,node --version,stellar --version - The full error message and stack trace
- Steps you have already tried
- Search open issues.
- Open a new issue with: your OS, output of
rustc --version && node --version && stellar --version, the full error and stack trace, and steps already tried.
Notify-Chain/
├── contract/ # Soroban smart contract workspace
│ ├── contracts/hello-world/ # AutoShare notification contract
│ │ └── src/ # Rust source + tests
│ └── Cargo.toml # Workspace config
│
├── listener/ # Off-chain listener service (Node.js/TypeScript)
│ ├── Dockerfile # Multi-stage Docker image
│ ├── .dockerignore
│ ├── src/
│ │ ├── api/ # HTTP API (events, health, schedule)
│ │ ├── services/ # Core: subscriber, dedup, notifier, scheduler
│ │ ├── store/ # SQLite repositories + in-memory registry
│ │ ├── database/ # Schema and client
│ │ ├── types/ # TypeScript type definitions
│ │ └── index.ts # Entry point
│ └── src/__tests__/ # Integration tests
│
├── dashboard/ # React + Vite event dashboard
│ ├── Dockerfile # Multi-stage Docker image (dev + production)
│ ├── .dockerignore
│ └── src/
│ ├── components/ # UI components
│ ├── services/ # API client
│ ├── store/ # Zustand state
│ └── pages/ # Page components
│
├── docker-compose.yml # Orchestrates listener + dashboard
├── .env.example # Root env template for Docker Compose
├── .dockerignore # Root-level build context exclusions
│
├── .github/
│ ├── workflows/ci.yml # CI pipeline
│ ├── dependabot.yml # Automated dependency updates
│ └── pull_request_template.md # PR description template
│
├── CONTRIBUTING.md # Workflow, standards, PR guidelines ← start here
├── CONTRIBUTOR_SETUP.md # This file — local environment setup
├── CONTRIBUTOR_DEVELOPMENT_WORKFLOW_GUIDE.md
├── CONTRIBUTOR_ARCHITECTURE_DEEP_DIVE.md
└── ARCHITECTURE_OVERVIEW.md