Skip to content

Switch RPC and Subsquid endpoints to mainnet - #647

Merged
n13 merged 6 commits into
mainfrom
n13/mainnet-endpoints
Sep 9, 2026
Merged

Switch RPC and Subsquid endpoints to mainnet#647
n13 merged 6 commits into
mainfrom
n13/mainnet-endpoints

Conversation

@n13

@n13 n13 commented Sep 9, 2026

Copy link
Copy Markdown
Collaborator

Endpoint changes

  • RPC: https://rpc1-mainnet.quantus.com, https://rpc2-mainnet.quantus.com (replaces a1/a2-planck.quantus.cat and matcha-latte).
  • Subsquid: https://subsquid-mainnet-app-1.quantus.com/v1/graphql, https://subsquid-mainnet-app-2.quantus.com/v1/graphql (replaces sub2). The /v1/graphql path comes from the iac nginx edge config, whose root location proxies straight to Hasura, same shape as sub2.
  • test_qr_payload.sh defaults to rpc1-mainnet.
  • Removed stillOnTestnet; nothing referenced it.
  • Added the mainnet genesis hash (0xfb5487…626fba, from the GM release plan) to knownNetworks so the cold wallet and Keystone review name mainnet payloads instead of showing Unknown.

Testnet UI removed

  • Faucet prompt: the home screen no longer shows "Get Testnet Tokens" on a zero balance. faucetUrl and the X-post launcher are gone.
  • Mining Rewards settings item: removed with the mining rewards screen, testnet rewards screen, redeem address and progress screens, provider, service, the bundled dirac/resonance/schrodinger miner lists, the axe icon, and the empty-state test.
  • Supabase: its only consumer was the mining rewards service (account id mappings), so Supabase.initialize, the env getters, and the supabase_flutter dependency are removed. SUPABASE_URL / SUPABASE_ANON_KEY are no longer read; they can be dropped from .env and CI secrets.
  • SDK: QuersiService.getMinerStats, getMiningAccountId, getOldMiningAccountId, the MinerStats model, SubstrateService.nonHDdilithiumKeypairFromMnemonic, telemetryUrl, and miningSetupGuideUrl had no remaining callers and are removed.
  • l10n: 55 keys removed from both arb files (homeGetTestnetTokens, swapDepositTestnetBanner, every settingsMining* / settingsTestnet*, and the redeem* keys except redeemCancel / redeemClose, which the encrypted send progress screen still uses). Generated localizations regenerated.

Test suites pass: quantus_sdk (non-native), mobile-app, cold-wallet-app.

Wormhole caches bound to the chain

The transfer and nullifier caches were keyed by generation and address only, so a miner that scanned on Planck and then selected Mainnet read Planck's scan height and spent nullifiers as mainnet's. Both files now carry the first 16 hex chars of the chain's genesis hash (wormhole_cache_v3_<genesis16>_<address16>.json), fetched once per WormholeUtxoService instance over the RPC it already uses for the chain head. Stale cleanup keeps current-generation files of every network, so switching back does not rescan; address-only v3 files from this branch are dropped like any earlier generation. A regression test switches between two networks within v3.

Out of scope

  • polkadart codegen source and bundled metadata stay on Planck (spec 147); the mainnet runtime (spec 152) update ships in a follow-up release.
  • All four mainnet hosts return Cloudflare 502 at the time of this PR, so the app has not been run against them yet.
  • miner-app chain list still has dev/dirac/planck with planck as default. A mainnet entry needs the node --chain id, so it is not a plain URL swap.
  • scripts/debug_subsquid.sh targets the old subsquid.quantus.com/graphql squid API with non-Hasura query syntax; it was already stale.

rpc1/rpc2-mainnet.quantus.com and subsquid-mainnet-app-1/2.quantus.com
replace the Planck nodes and sub2. Drops the unused stillOnTestnet flag,
points polkadart codegen and test_qr_payload.sh at the mainnet node, and
adds the mainnet genesis hash to knownNetworks so signers name it.
@n13 n13 added the bot-review Request automated review from review-bot label Sep 9, 2026

@dewabisma dewabisma left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM!

n13 added 2 commits September 9, 2026 18:26
The home screen no longer offers testnet tokens on a zero balance; there
is no faucet. The Mining Rewards settings item goes away with its screens,
redeem flow, provider, service, bundled testnet miner lists, and l10n. The
only Supabase consumer was that service, so its init and dependency go
too, along with the SDK miner-stats helpers nothing else called.

@n13 n13 left a comment

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewer model: GPT 5.6 Sol

Verdict (advisory): Request changes

Blocking findings:

  1. [High] Invalidate or namespace persisted Wormhole state when changing genesisquantus_sdk/lib/src/constants/app_constants.dart:14-17. The released wallet already writes wormhole_nullifiers_v2_<address>.json, and both that cache and the current transfer cache are keyed only by address, not by genesis/network (wormhole_utxo_service.dart:175-187). After this update the same files are read against mainnet. Because a nullifier is recomputed only from the wallet secret and transferCount (wormhole_utxo_service.dart:648-659), a transfer number that was spent on Planck is immediately classified as spent on mainnet without querying mainnet. Current-main builds can also merge Planck transfer rows or skip the mainnet history range using Planck's much larger cachedUpToBlock. Namespace both caches by genesis hash, or at minimum bump/clear both cache generations as part of this switch, and add an upgrade regression covering an existing Planck cache.

  2. [High] Keep the miner's UTXO discovery on the chain it is miningquantus_sdk/lib/src/constants/app_constants.dart:14-17. miner-app still defaults to Planck (miner_config.dart:139-145), but its balance and withdrawal screens instantiate WormholeUtxoService, which now gets mainnet RPC and GraphQL from these shared constants. The claim flow discovers those mainnet UTXOs first and only later uses the explicitly supplied Planck rpcUrl for proofs/submission. A Planck miner therefore shows the wrong reward balance and cannot reliably withdraw it; if the same address has mainnet UTXOs, the flow attempts to prove them against Planck. Pass the selected chain's RPC/indexer into UTXO discovery, or move the miner to mainnet atomically rather than redirecting only its shared SDK services.

  3. [Medium] Make the second GraphQL endpoint handle HTTP 5xx from the firstquantus_sdk/lib/src/constants/app_constants.dart:15-17. During this review both new origins returned Cloudflare 502 and later recovered independently. RedundantEndpointService.post() currently treats every HTTP response as success and stops iterating; GraphQlEndpointService.query() checks the status only after post() has returned. Thus an app-1 502 never reaches app-2 even if app-2 is healthy. Treat retryable 5xx responses as endpoint failures inside the failover boundary and cover first-502/second-200 behavior.

Validation:

  • Reviewed full diff 0ad19057...f0edaf04; git diff --check, changed-Dart formatting, shell syntax, localization-member consistency, and removed-symbol searches passed.
  • Full mobile suite passed (426 tests); full non-native SDK and cold-wallet suites passed.
  • Both RPC endpoints answered over HTTPS and WSS with mainnet genesis 0xfb5487...626fba and runtime 152/transaction 6. Both GraphQL origins currently pass /healthz and the SDK's transfer query.
  • GitHub Analyze is red only for the unchanged base import in mobile-app/test/unit/regular_send_strategy_test.dart:2; all other package analyzers passed before that failure.

@n13 n13 removed the bot-review Request automated review from review-bot label Sep 9, 2026
…over

- Wormhole caches: one generation constant for both the transfer and the
  nullifier file, bumped to v3 for the mainnet switch. The files are keyed
  by address only, so Planck-era transfers and nullifiers would otherwise be
  read against mainnet and a transfer count spent on Planck would count as
  spent here. Earlier generations of an address are deleted on first read.
- Miner app: balance, withdrawal and claim discovery use the selected
  chain's RPC and indexer through MinerSettingsService.utxoService(),
  replacing the stub that never configured anything. Mainnet is added as
  the default chain and Planck points at its real indexer.
- Endpoint failover: an HTTP 5xx is an endpoint failure inside
  RedundantEndpointService, so the next endpoint is tried; a 4xx is
  returned unchanged. The HTTP client is injectable for tests.
@n13 n13 added the bot-review Request automated review from review-bot label Sep 9, 2026

@n13 n13 left a comment

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewer model: GPT 5.6 Sol

Verdict (advisory): Request changes

Blocking finding:

  1. [High] Namespace or clear the current-generation Wormhole caches when the miner switches chainsquantus_sdk/lib/src/services/wormhole_utxo_service.dart:181-200, miner-app/lib/src/services/miner_settings_service.dart:45-47. utxoService() now correctly binds discovery to the selected chain's endpoints, but both cache filenames still contain only the generation and address prefix. saveChainId() changes only the preference. After the miner creates v3 transfer/nullifier caches on Planck and the user selects Mainnet (or vice versa), deleteStaleCaches() deliberately preserves those same v3 files and the new chain reads them. The cached height can suppress part or all of the new chain's transfer scan, while transfers and spent nullifiers from the old chain are evaluated as if they belonged to the new one, yielding a wrong rewards balance and unreliable claim discovery. Include a stable network/genesis namespace in both cache keys, or clear the Wormhole caches atomically whenever the selected chain changes, and add a regression that switches between two networks within cache generation v3.

Validation:

  • Reviewed the complete 0ad19057...2ad6f018 diff and the incremental fixes since the prior review; no other blocking findings found.
  • git diff --check, changed-Dart formatting (27 files), shell syntax, localization consistency, removed-symbol searches, and the 9 focused endpoint/cache/pagination tests passed.
  • Full mobile, non-native SDK, and cold-wallet suites passed. The miner's 12 runnable tests passed; its overall suite remains red because the pre-existing test/widget_test.dart placeholder has no main.
  • Local Melos analysis completed cleanly for cold wallet, miner, and SDK before the strict 10-second cap stopped the mobile package; the current-head GitHub Analyze and dependency-cooldown checks both passed.
  • Both mainnet RPCs returned genesis 0xfb5487...626fba and runtime 152 / transaction 6; both GraphQL origins passed health and the SDK transfer query. Live runtime metadata retains the bundled spec-147 pallet/call indices and top-level call field signatures.

@n13 n13 removed the bot-review Request automated review from review-bot label Sep 9, 2026
Both cache files were keyed by generation and address only, so a miner
that scanned on Planck and then selected Mainnet read Planck's scan height
and spent nullifiers as if they were mainnet's. The files now carry the
first 16 hex chars of the chain's genesis hash, fetched once per service
instance over the same RPC discovery already uses. Stale cleanup keeps
current-generation files of every network, so switching back does not
rescan. RpcEndpointService.forUrls takes a client for tests.
@n13 n13 added the bot-review Request automated review from review-bot label Sep 9, 2026

@n13 n13 left a comment

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewer model: GPT 5.6 Sol

Verdict (advisory): Approve

No blocking findings at 43d7cee01568ef6eab50981279b841b9cf6d9817.

The latest commit resolves the remaining cross-chain cache issue: transfer and spent-nullifier files are now namespaced by a genesis-derived network ID, pre-v3 files are removed, and current-generation caches for other networks are preserved without being read on the selected chain. Miner balance discovery, claim discovery, proof RPC, and submission are consequently bound to the same selected chain. The mainnet endpoint switch, 5xx failover, testnet reward/Supabase removal, generated localization changes, and signer-visible genesis naming are otherwise consistent across their callers.

Validation:

  • Reviewed the complete 0ad19057...43d7cee0 diff, prior review thread, and the incremental 2ad6f018...43d7cee0 fix; git diff --check, shell syntax, removed-symbol searches, and formatting of all 27 changed Dart files passed.
  • Full suites passed: quantus_sdk non-native (480), mobile app (426), cold wallet (285), and all 12 runnable miner tests. The focused cache/failover/pagination set passed 10/10.
  • Local strict analysis passed for cold wallet, miner, and SDK before the required 10-second cap stopped the mobile package; GitHub Analyze passed at this exact head. Direct flutter gen-l10n is unavailable because this repository does not enable flutter.generate; the committed generated localizations compiled in the full mobile suite, and the locale-key mismatch is unchanged from base.
  • Both mainnet RPCs returned genesis 0xfb5487c0be6ae4ade2d41d16e50465129861636c2b8d61fa94d7a19631626fba and runtime 152 / transaction 6. Both GraphQL origins accepted the SDK transfer query and were caught up exactly to the RPC head at validation time.

@n13
n13 merged commit 56a9304 into main Sep 9, 2026
4 checks passed
@n13 n13 removed the bot-review Request automated review from review-bot label Sep 9, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants