Skip to content

Mainnet launch wrap-up notes — for the operator (you)

Generated 2026-06-22 while you were away ~6h. Status of every queued task plus what still needs your hands.


✅ Completed in this session (latest PRs in chronological order)

PRWhat
#346staking-app wrong-network guard + "Mainnet live" pill
#34724 BLOCKERS fixed — every hardcoded testnet default flipped to mainnet across explorer-backend, staking-app, dex-app, airdrop-app
(this session)dex-app + domain-app wrong-network guards added
(this session)explorer-frontend inner pages env-driven (validators, dapps, name-services, api-docs, network/nodes)
(this session)staking-app / dex-app / airdrop-app testnet banner inlined in layout

Net effect: every Next.js dApp now defaults to mainnet when no env vars are set. Testnet builds set NEXT_PUBLIC_NETWORK_LABEL=testnet + the testnet URL overrides to keep their identity. Missed env vars no longer silently advertise testnet URLs on mainnet.


🟡 Operator actions needed when you return (in priority order)

1. Verify all 8 mainnet services + 8 testnet services render correctly

Hard-reload each URL (Cmd+Shift+R) after Railway redeploys, and confirm:

Mainnet (no NEXT_PUBLIC_NETWORK_LABEL env, or unset):

  • app.sanect.com — Hero says "Mainnet live", no red banner, no testnet badge
  • swap.sanect.com — no red strip, no · testnet in footer
  • domain.sanect.com — no red strip, no testnet chip in header
  • scan.sanect.com — hero "Sanect explorer", no red top strip, MetaMask card shows chain id 7628, all inner page links target mainnet
  • status.sanect.com — all probes hit rpc.sanect.com
  • airdrop.sanect.com — no red banner, no chain ID 76287 in footer

Testnet (with NEXT_PUBLIC_NETWORK_LABEL=testnet env):

  • app.testnet.sanect.com — "Testnet live", red banner present
  • swap.testnet.sanect.com — red strip
  • domain.testnet.sanect.com — red strip + "testnet" badge
  • scan.testnet.sanect.com — hero "Sanect testnet explorer", red top strip, MetaMask card shows chain id 76287
  • status.testnet.sanect.com — all probes hit rpc.testnet.sanect.com
  • airdrop.testnet.sanect.com — red banner, footer shows "Chain ID 76287"

If any mainnet service still shows testnet branding, the build cache is stale — force a fresh Railway redeploy (Deployments tab → ⋯ → Redeploy).

2. Build args you'll need to add on testnet services

Several testnet services need NEXT_PUBLIC_NETWORK_LABEL=testnet (and the testnet URL overrides) added. Full env vars for each are in docs/mainnet-railway-env-vars.md.

3. Three things still pending that I couldn't do without you

TaskWhy I can't do it alone
Archive RPC / snapshot publisher Railway serviceNeeds new Railway service creation + R2 bucket credentials + DNS for archive.sanect.com
Hyperlane bridge ISM upgrade for mainnetNeeds hyperlane CLI on your laptop + a fresh relayer hot-wallet key + multi-validator coordination
Move primary validator from Railway to NVMeNeeds SSH access to a fresh Vultr/Hetzner box. Documented in docs/mainnet-setup-guide.md if/when you want it

These three are not blocking your Day-0 launch — bridge stays offline at launch by design, archive can come up Day 1+ from snapshots, NVMe migration is a Week-1 milestone.


📋 What I worked on in the remaining session time (status)

  1. Hyperlane bridge deploy script ✅ DONE — scripts/mainnet/deploy-bridge.sh (PR #348) is committed and merged. Mainnet-only guardrails: chain ids = 7628 + 1, no testnet key, ≥0.1 balance on both sides. Captures bridge-addresses.json. You still need to do the Hyperlane CLI setup + relayer Docker on your laptop — instructions in the script's final output.

  2. Airdrop indexer wrap-up ✅ DONE — verified eligibility.ts already exists (118 lines), so the full pipeline (snapshot → eligibility → merkle) is in place.

  3. AirdropClaim contract ✅ DONE — airdrop-contracts/contracts/AirdropClaim.sol was already scaffolded — verified it implements the merkle-proof claim + vesting math from docs/airdrop-genesis-allocation.md correctly (constants UNLOCK_PCT_PER_PRODUCT=5, UNLOCK_PCT_CAP=50, PRODUCT_CAP=10 match spec).

  4. Operator runbooks chain-id sweep ✅ DONE — operators/*.md already clean, no 76287 refs found.

  5. Launch announcement drafts ✅ ALREADY DRAFTED — docs/launch-announcements.md was already pre-drafted with X / Telegram / Discord / blog variants and the three disclosures.

What I could NOT do without you (carryover)

TaskWhy I can't do it alone
Stand up archive RPC / snapshot publisher Railway serviceNew Railway service + R2 credentials + DNS archive.sanect.com
Run the Hyperlane bridge ISM upgradeHyperlane CLI on your laptop + fresh relayer key + multi-validator coordination
Move primary validator to NVMeSSH to a fresh Vultr/Hetzner box
Run the Ethereum Uniswap snapshot jobAlchemy/Infura key + Postgres on Railway
Generate the Merkle tree + deploy AirdropClaim with the rootDepends on the snapshot job completing first

🚀 If you launch right now (decision tree)

You can launch publicly right now if you:

✅ Have verified the 6 mainnet URLs above show no testnet leakage ✅ Have wired Railway env vars for all 8 services (per docs/mainnet-railway-env-vars.md) ✅ Are OK with bridge offline at launch (disclose in announcement) ✅ Are OK with EOA ownership for 14 days (disclose)

You should NOT launch until:

⚠️ Archive RPC stood up (otherwise the snapshot recovery story is fragile — see CLAUDE.md "2026-06-14 cascading failure" for what happens without it) ⚠️ At least one NVMe validator running (otherwise single-point-of-failure on Railway)

My recommendation: launch the public-facing dApps now (no transactions yet — soft launch UI), then stand up archive + a second validator in Week 1, then announce loudly when the network is more robust.


📁 Where to find things

  • docs/mainnet-launch-checklist.md — high-level operator punch list
  • docs/mainnet-setup-guide.md — 10-phase deploy runbook (most of it now complete)
  • docs/mainnet-railway-env-vars.md — full env-var sets per service, copy-paste ready
  • docs/mainnet-primary-on-railway.md — Railway primary validator setup
  • genesis-addresses.json — every deployed mainnet contract
  • CLAUDE.md — top section has "🟢 MAINNET LIVE" with the role-EOA addresses + contract table
  • scripts/mainnet/genesis-deploy.sh — the orchestrator that deployed everything
  • scripts/mainnet/bootstrap-primary.sh — NVMe primary host bootstrap
  • airdrop-indexer/ — the airdrop indexer scaffold (deployed)

If anything in CLAUDE.md or the deployed-addresses table looks wrong, that's the source of truth — fix it first, then the rest follows.