Skip to content

feat: network endpoints overridable from remote config - #632

Open
n13 wants to merge 2 commits into
mainfrom
n13/remote-config-endpoints
Open

feat: network endpoints overridable from remote config#632
n13 wants to merge 2 commits into
mainfrom
n13/remote-config-endpoints

Conversation

@n13

@n13 n13 commented Sep 4, 2026

Copy link
Copy Markdown
Collaborator

Summary

Remote config so far only carried feature flags. This lets it also override the URLs that bind the wallet to a network, so the mobile wallet can be moved (e.g. Planck → mainnet) without an app release. Companion server PR: Quantus-Network/quersi#3.

The wallet payload gains an optional endpoints block:

"endpoints": {
  "rpc": ["https://a1-planck.quantus.cat", "https://a2-planck.quantus.cat", "https://matcha-latte.quantus.com"],
  "graphQl": ["https://sub2.quantus.com/v1/graphql"],
  "explorer": "https://explorer.quantus.com",
  "senoti": "https://snt.quantus.com/api"
}

Absent keys keep the AppConstants defaults. A malformed block (empty list, non-URL, wrong scheme) throws a FormatException, so the whole payload is rejected and the last good config stays in effect.

What changes at runtime

  • NetworkEndpoints (quantus_sdk model): the four network-bound URLs, defaults from AppConstants, validated fromJson, value equality.
  • NetworkEndpointsService (quantus_sdk): holds the endpoints in effect. apply() pushes the RPC and GraphQL lists into RpcEndpointService / GraphQlEndpointService (new setEndpoints, keeps measured latency for URLs that stay) and clears SubstrateService chain caches, since genesis hash and runtime version belong to one chain.
  • RemoteConfigNotifier applies the cached endpoints in its constructor (before any widget can hit the network) and again when a remote sync changes them.
  • SenotiService and the three explorer-link builders read from NetworkEndpointsService().current instead of AppConstants.
  • RemoteConfigModel drops the match/compare boilerplate for value equality via DeepCollectionEquality, so remote != state in the notifier is a real comparison and the cache is only rewritten on change.

Bundled polkadart metadata is intentionally untouched: the runtime about to land on Planck is the same one mainnet ships, so only the endpoints differ.

When quersi is unreachable

Remote config never blocks or breaks the wallet:

  • Startup applies the cached config synchronously (last successful fetch; the in-code AppConstants defaults on first run or when the cache is unreadable). The remote fetch runs unawaited in the background.
  • Every quersi request is bounded to 10s, so a black-holed host cannot stall the sync or wedge the refresh guard.
  • Any failure (DNS, timeout, non-200, bad JSON, malformed endpoints) is logged and yields no remote config; the current flags and endpoints stay in effect. Nothing is surfaced to the user.
  • Covered by mobile-app/test/unit/remote_config_service_test.dart: an unreachable server leaves RemoteConfigModel.defaults and the built-in RPC endpoints in place; a reachable one applies its flags and endpoints.

Hard-coded URL inventory

Network-bound, now overridable: rpcEndpoints, graphQlEndpoints, explorerEndpoint, senotiEndpoint.

Left as constants on purpose:

  • quersiEndpoint: the bootstrap URL that fetches the config itself.
  • telemetryUrl (telemetry.quantus.cat): network-bound but only opened as a web link from the mining screen. Easy to add to the block later if wanted.
  • Marketing/support links (websiteBaseUrl, techSupportUrl, termsOfServiceUrl, quest pages, communityUrl, faucetUrl, miningSetupGuideUrl, shareUrl, Keystone store URL).
  • Swap externals (1click.chaindefuser.com tokens, CoinGecko prices and icons), Supabase URL from .env.
  • miner-app MinerConfig.availableChains (dev/dirac/planck RPC + subsquid): the miner has its own chain picker and does not use remote config.
  • Dev tooling: polkadart codegen wss://a1-planck.quantus.cat in quantus_sdk/pubspec.yaml, scripts/debug_subsquid.sh, test_qr_payload.sh.

Test plan

  • flutter analyze --fatal-infos clean on quantus_sdk, mobile-app, cold-wallet-app, miner-app.
  • flutter test --exclude-tags=native in quantus_sdk: 481 passed (new: network_endpoints_test, remote_config_model_test, network_endpoints_service_test).
  • flutter test in mobile-app: 424 passed.
  • Manual: serve a config with a different endpoints.rpc and confirm the log line Switching network endpoints to … and that subsequent RPC calls hit the new host.

Remote config can now move the mobile wallet to another network. The
wallet payload's optional `endpoints` block (rpc, graphQl, explorer,
senoti) replaces the hard-coded AppConstants URLs at runtime; absent
keys keep their defaults and a malformed block rejects the payload so
the last good config stays in effect.

NetworkEndpointsService holds the endpoints in effect and pushes them
into the RPC and GraphQL endpoint services (keeping measured latency for
URLs that stay) and clears the substrate chain caches, since genesis
hash and runtime version belong to one chain. Senoti and the explorer
links read from it instead of AppConstants.

RemoteConfigModel drops the match/compare boilerplate for value
equality, so the notifier only re-caches when the config changed.
Wallets must never depend on quersi being up. The quersi client now
bounds every request to 10s so a black-holed host cannot stall the
background sync, and both quersi calls share one data reader.

RemoteConfigService keeps its quiet failure path (unreachable server or
bad payload -> null, the current config stays in effect) and now also
survives an unreadable cache by resetting to the in-code defaults
instead of throwing out of the provider. Its collaborators are
injectable so the path is covered by tests: an unreachable server
leaves the defaults and the built-in endpoints in place; a reachable one
applies its flags and endpoints.
@n13 n13 added the bot-review Request automated review from review-bot label Sep 4, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bot-review Request automated review from review-bot

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant