Skip to content

fix(android): keep react-native-config BuildConfig from R8 so self-custodial wallet connects#3812

Merged
grimen merged 2 commits into
mainfrom
fix/android-react-native-config-r8
Jun 3, 2026
Merged

fix(android): keep react-native-config BuildConfig from R8 so self-custodial wallet connects#3812
grimen merged 2 commits into
mainfrom
fix/android-react-native-config-r8

Conversation

@grimen

@grimen grimen commented Jun 3, 2026

Copy link
Copy Markdown
Contributor

Problem

The self-custodial wallet shows "Wallet is offline — your non-custodial wallet can't reach the network right now" on Android release builds (Google Play internal testing) while working fine on iOS TestFlight.

Addresses blinkbitcoin/blink-wip#762.

Root cause

The secret reaches the build host fine (iOS and Android build from the same .env.ci). The values are stripped from the Android release binary by R8/ProGuard:

  • react-native-config reads its values on Android by reflection over the generated com.galoyapp.BuildConfig class.
  • Release builds enable minification (enableProguardInReleaseBuilds = true) and there was no keep rule for BuildConfig, so R8 removes the reflection-only constants.
  • At runtime Config.BREEZ_API_KEY is therefore null → the Breez SDK connects with an empty API key → auth fails → "Wallet is offline".
  • iOS has no R8 step, hence the asymmetry. react-native-config had no production consumer before the self-custodial feature, so the latent stripping went unnoticed.

Changes

  • android/app/proguard-rules.pro-keep class com.galoyapp.BuildConfig { *; } (the fix).
  • app/self-custodial/config.ts + bridge/lifecycle.ts — replace the silent apiKey: Config.BREEZ_API_KEY ?? "" with a lazy requireBreezApiKey() that throws "BREEZ_API_KEY is not configured for this build" at SDK init, so a misconfigured build fails loudly instead of faking a network outage.
  • ci/tasks/build.sh — after the Android release build, assert (via apkanalyzer) that every key from the consumed .env.ci survived into the release BuildConfig. Key list is derived from the env file the build actually used — nothing hardcoded — and it runs before the EXIT trap deletes .env.ci.
  • TestsrequireBreezApiKey() returns the key / throws when missing; initSdk forwards the key into config.apiKey.
  • docs/android-env-config-r8.md (+ index link) — full reproduce/verify procedure.

Verification

  • yarn jest __tests__/self-custodial54 suites, 795 tests passing.
  • Built a real minified release APK locally and inspected com.galoyapp.BuildConfig with apkanalyzer:
    • without the keep rule → BREEZ_API_KEY / SPARK_TOKEN_IDENTIFIER / BREEZ_NETWORK (and the whole BuildConfig class) stripped — reproduces the bug.
    • with the keep rule → all three fields retained with values — confirms the fix.

Note: a functional on-device "wallet comes online" check requires the real BREEZ_API_KEY (to authenticate against Breez), so it wasn't run locally. The BuildConfig-survival inspection is the faithful proxy for the exact failure mode, and the new CI gate enforces it on every release build.

🤖 Generated with Claude Code

grimen and others added 2 commits June 3, 2026 16:37
…stodial wallet connects

The self-custodial wallet showed "Wallet is offline" on Android release
builds (Play internal testing) while working on iOS. react-native-config
reads its values by reflection over com.galoyapp.BuildConfig; release
minification (R8) stripped those reflection-only constants, so
Config.BREEZ_API_KEY resolved to null and the Breez SDK connected with an
empty API key and failed to reach the network. iOS has no R8 step, which is
why it was unaffected; react-native-config had no production consumer before
the self-custodial feature, so the latent stripping went unnoticed.

- Add `-keep class com.galoyapp.BuildConfig { *; }` (the fix)
- Fail loud on a missing BREEZ_API_KEY via requireBreezApiKey() instead of
  silently using "" and surfacing a misleading "offline" error
- CI gate in ci/tasks/build.sh asserting every .env.ci key survives into the
  release BuildConfig (key list derived from the consumed env file, not hardcoded)
- Unit tests for requireBreezApiKey() and the initSdk apiKey wiring
- docs/android-env-config-r8.md: reproduce/verify procedure (minified APK + apkanalyzer)

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@grimen grimen requested a review from esaugomez31 June 3, 2026 15:40
@grimen grimen merged commit d14cd1a into main Jun 3, 2026
6 of 8 checks passed
@grimen grimen deleted the fix/android-react-native-config-r8 branch June 3, 2026 15:52
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