Web console for Moonlight Protocol council administrators. Deploy contracts, manage Privacy Providers, and monitor your council.
- Deploy contracts: Deploy Channel Auth + Privacy Channel contract pairs from soroban-core GitHub releases
- Manage providers: Add and remove Privacy Providers on a Channel Auth contract
- Track councils: Local persistence of deployed contract IDs and provider membership
- Wallet auth: Connect via Freighter, LOBSTR, xBull, or WalletConnect. All transactions signed by the wallet.
# Install dependencies
deno install
# Build the app bundle
deno task build
# Start dev server (port 3020, watches for changes)
deno task dev
# Run integration tests (requires local-dev/up.sh running)
deno task testIntegration tests run against local infrastructure (Stellar standalone network via local-dev/up.sh):
# Start local infra first
cd ~/repos/local-dev && ./up.sh
# Run tests
cd ~/repos/council-console && deno task testThe test deploys Channel Auth + Privacy Channel contracts, adds a provider, verifies it, and removes it.
Static files are deployed to a public Tigris bucket on Fly.io.
- Bucket:
moonlight-council-console - URL: https://moonlight-council-console.fly.storage.tigris.dev/index.html
- Auto-deploy: push to
maintriggers the GitHub Actions workflow (.github/workflows/deploy.yml) - Secrets (set in GitHub repo settings):
TIGRIS_ACCESS_KEY_ID,TIGRIS_SECRET_ACCESS_KEY
Pipeline:
- Push to
maintriggersauto-version.yml(bumps version indeno.json, creates git tag) - Tag push (
v*) triggersdeploy.yml(builds production bundle, deploys to Tigris)
Auto-version uses conventional commits to determine the bump type:
feat:orfeat(...):merges bump the minor versionfeat!:orBREAKING CHANGEbumps major- Everything else bumps patch
The workflow skips commits starting with chore: bump version to prevent re-triggering itself. It uses a PAT (AUTO_VERSION_TOKEN) to bypass branch protection for the version bump commit.
deno task build -- --production
aws s3 sync public/ s3://moonlight-council-console/ \
--endpoint-url https://fly.storage.tigris.dev \
--acl public-read --deleteStatic SPA (no backend). Contract interactions go directly to Stellar RPC. Council state is stored in the browser's localStorage since no reverse lookup exists on-chain.
Browser
├── Wallet (Freighter) ── signs transactions
├── Stellar RPC ── deploys contracts, invokes functions
├── GitHub API ── fetches WASM binaries from soroban-core releases
├── PostHog ── UI analytics (production only)
└── Grafana OTLP ── operation traces (production only)
Required for CI deploys:
| Secret | Purpose |
|---|---|
TIGRIS_ACCESS_KEY_ID |
Tigris CDN upload |
TIGRIS_SECRET_ACCESS_KEY |
Tigris CDN upload |
POSTHOG_PROJECT_TOKEN |
PostHog analytics |
GRAFANA_OTLP_ENDPOINT |
OTEL trace export endpoint |
GRAFANA_OTLP_AUTH |
OTEL basic auth header |