fix(android): keep react-native-config BuildConfig from R8 so self-custodial wallet connects#3812
Merged
Merged
Conversation
…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>
esaugomez31
approved these changes
Jun 3, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
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-configreads its values on Android by reflection over the generatedcom.galoyapp.BuildConfigclass.enableProguardInReleaseBuilds = true) and there was no keep rule forBuildConfig, so R8 removes the reflection-only constants.Config.BREEZ_API_KEYis thereforenull→ the Breez SDK connects with an empty API key → auth fails → "Wallet is offline".react-native-confighad 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 silentapiKey: Config.BREEZ_API_KEY ?? ""with a lazyrequireBreezApiKey()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 (viaapkanalyzer) that every key from the consumed.env.cisurvived into the releaseBuildConfig. Key list is derived from the env file the build actually used — nothing hardcoded — and it runs before theEXITtrap deletes.env.ci.requireBreezApiKey()returns the key / throws when missing;initSdkforwards the key intoconfig.apiKey.docs/android-env-config-r8.md(+ index link) — full reproduce/verify procedure.Verification
yarn jest __tests__/self-custodial→ 54 suites, 795 tests passing.com.galoyapp.BuildConfigwithapkanalyzer:BREEZ_API_KEY/SPARK_TOKEN_IDENTIFIER/BREEZ_NETWORK(and the wholeBuildConfigclass) stripped — reproduces the bug.🤖 Generated with Claude Code