Conversation
- Replace jcenter() with mavenCentral() plus the Aliyun JCenter mirror, which still serves the six JCenter-only artifacts (anko-commons, xfetch2, loadingview, circleindicator, blurry, gradientview) - Drop LeakCanary 1.x: its DisplayLeakActivity has intent filters without android:exported, which makes installs fail on API 31+; no code usage
The previous fix read DAOInfo.sourceAssetId, but the native wallet core never emits that key, so it always fell back to the old behavior. The actual bug: checkAmount() balance-checked every amount entry including receive legs - in a swap the wallet doesn't hold the target asset yet, so 'not enough funds' always fired. Skip entries with spend == false; fee is still checked against BEAM. Also fix setAmounts() using the dialog-level assetId (amounts[0]) for every row's icon instead of the row's own assetID, which made both legs of a swap show the first asset's icon.
builds.beam.mw/mainnet/latest has served stale 2021 (v5.2) libraries for years; the app calls newer JNI methods (e.g. Wallet.enableBodyRequests) that are missing there, crashing with UnsatisfiedLinkError at runtime. Download the libwallet-jni-<abi> artifacts from the latest successful master Build run on BeamMW/beam instead, and strip them when llvm-strip is available (CI artifacts are unstripped, ~111 MB each).
The masternet network no longer exists. Drop the product flavor, its source set (res, google-services.json, gitignored jniLibs dir), proguard config, lib download script/gradle task, and all FLAVOR_MASTERNET code paths. Retarget the main shortcuts.xml (xml-v25) from the masternet package to mainnet - it pointed at masternet even in mainnet builds, so app shortcuts could never resolve.
GitHub Actions workflow that runs assembleMainnetRelease on push to master/v7.4 and on pull requests, uploading the arm64-v8a and universal release APKs as artifacts. Getting a green run on the pinned AGP 3.5 / Gradle 6.1.1 toolchain required: committing gradle-wrapper.jar (fresh checkouts could not run ./gradlew without it); installing an isolated minimal SDK (android-32 + build-tools 28.0.3) because AGP 3.5 cannot parse the runner's newer SDK metadata; running sdkmanager under JDK 17 while the build itself uses JDK 11; skipping native-lib stripping via packagingOptions.doNotStrip; and blanking the runner's ANDROID_NDK_* env vars so AGP 3.5's strip task degrades to a warning instead of failing on the incompatible NDK.
The native core can pass null for any WalletAddressDTO string field - token-address callbacks leave walletID/label null, which crashed the iOS wallet on the faucet screen (ios-wallet#587). WalletAddress's constructor called source.walletID.replaceFirst(...) directly, so the same core behavior NPEs here. Make the DTO's string fields nullable (JNI constructor signature is unchanged) and default them at the boundary. (cherry picked from commit 5085536)
The 'get coins' banner and Settings > faucet opened faucet.beamprivacy.community, whose domain no longer resolves (NXDOMAIN). Navigate to the BEAM Faucet dApp in the in-app browser instead (preferring the live apps-list entry, falling back to the known plugin-faucet URL). Removes the now-dead faucet-address generation/subscription and external-link plumbing from the wallet and settings screens. (cherry picked from commit d26f59a)
generateRegularAddress(amount, assetId) re-tokenises the persisted default address, so opening Receive always returned the same address. Switch to generateNewAddress(), which mints and persists a fresh address per call (delivered via subOnAddressCreated). The offline / max-privacy tokens are still regenerated only when amount/asset change, so editing the amount does not mint a new address per keystroke. (cherry picked from commit f14ac51)
Reword receive_description / receive_description_2 to 'online vs offline' consistently and make the 12-hour window mean 'open and connect your wallet once within 12 hours', matching the iOS wallet. (cherry picked from commit 64cd0b6)
The Regular address on a random node is the plain SBBS address. Surface
an inline italic hint under it ('use for CEX withdrawals and mining') so
users know the SBBS address is the one to use for exchange withdrawals
and mining pools, and extend sbbs_address_new to mention mining too.
(cherry picked from commit 39bd103)
The seed-verification and wallet-creation flows share the same fragments (WelcomeSeed -> WelcomeConfirm -> Password -> WelcomeProgress) and were distinguished only by the volatile static App.isAuthenticated. That flag resets to false on process death, while the navigation back-stack is restored - so if the OS killed the app while the user was on the verify screens, the restored flow read isAuthenticated=false, generated a NEW mnemonic, and ran the create path (removeDatabase() + createWallet()), destroying the existing wallet. Thread an explicit, durable isVerification nav-argument from the verify entry point (DoubleAuthorization VerificationSeed) through WelcomeSeed and WelcomeConfirm, and gate every create-vs-verify decision on it instead of App.isAuthenticated. Nav-args are persisted in the saved instance state and survive process death, and are scoped to the navigation instance so they can't leak into a later create/restore. Verified in the emulator: creating a new wallet still works; verifying an existing wallet's seed shows the real seed and returns to the wallet without wiping. (cherry picked from commit 247fb309396e127af8429d0ec6712ce79c6e1a9d)
Keep comments focused on the code; tracker references belong in commit messages, not the source. (cherry picked from commit 23eb3ed214c4cc654a3fa8d53f0759bdd5d8c120)
Automatic restore shows the wallet from onProgress(), i.e. on the next sync-progress event after the snapshot import finishes. When the wallet is already synced at that point, no further sync event arrives, so the restore hangs on the progress screen (retrying works because the unfinished-restore cleanup resets state and timing differs). When recovery import finishes in RESTORE_AUTOMATIC mode and the wallet is already synced, show the wallet directly instead of waiting for a sync event that will never come. Scoped to automatic restore so the own-node and create/open paths are untouched. Needs verification on a physical device (the already-synced hang is not reproducible in the emulator). (cherry picked from commit 6254c3fb462ded075a39c019587a6d5307bd92df)
Android refuses to install unsigned APKs (INSTALL_PARSE_FAILED_NO_CERTIFICATES; 'App not installed as package appears to be invalid' in the UI), so the raw assembleMainnetRelease artifacts were uninstallable for testers. Sign them in CI with a dedicated test keystore held in the repo secrets (CI_KEYSTORE_B64 / CI_KEYSTORE_PASS): apksigner applies v1+v2+v3 schemes, successive CI builds can update over each other, and the key is unrelated to the Play release key, so CI builds and store installs stay cleanly separated. Fork PRs receive no secrets and fall back to uploading the unsigned APKs.
The #645 nav-arg refactor made WelcomeSeed generate the existing seed only when isVerification is set. The display-seed entry (DoubleAuthorization DisplaySeed -> WelcomeSeed with onlyDisplay=true, isVerification=false) therefore fell through to Api.createMnemonic() and showed a brand-new mnemonic instead of the wallet's own seed. (The screen is currently only reachable in code - no Settings row constructs SeedPhrase mode - but the 'Show seed phrase' title/mode are wired and clearly meant to exist.) Drive the seed source off onlyDisplay || isVerification so both the verify and the display paths read the persisted seed; only the create flow mints a fresh one.
The swap-confirm fix skips balance checks on receive legs (spend == false). A request that carries only receive legs would then run checkAmount without validating anything, even though the transaction fee still debits BEAM. Add a fee-only check for that case so an unaffordable fee still disables Confirm.
Two sources of bloat in the release artifacts: - CI shipped unstripped ~111 MB native libraries. The workflow blanked ANDROID_NDK_LATEST_HOME along with the vars AGP reads, but that one is read only by android-wallet-mainnet.sh to locate the NDK's llvm-strip; blanking it disabled stripping on CI. Keep it set (AGP still can't see the NDK via ANDROID_NDK_ROOT/HOME/ANDROID_NDK) so the fetch script strips each lib to ~11 MB. - The universal APK carried two extra full copies of the arm64 library under lib/armeabi/ and lib/armv8/, and a standalone armeabi split APK was built containing 64-bit code. Both trace to the fetch script's legacy-copy loop plus 'armeabi' in the ABI splits. armeabi has been dead since NDK r17 and no minSdk-23 device can load it. Drop the copy loop and the split entry. Verified locally (already-stripped libs): universal native payload 625 MB -> 43 MB, arm64 APK 46 MB -> 22 MB, no armeabi/armv8 entries, no armeabi split APK; the signed release installs and launches.
Set versionName 7.4 / versionCode 513 for the release. The 'vX.Y' label
was built inline as "v " + BuildConfig.VERSION_NAME in four screens, which
also rendered with a stray space ("v 7.3"). Add AppConfig.APP_VERSION_LABEL
as the single source ("v" + version, no space) and point Settings, Welcome
Create, Welcome Open and Welcome Progress at it.
The Receive-screen copy touched by this branch existed only in English: receive_description carried stale wording in every locale (and was untranslated English in 5 of them), and receive_description_2, sbbs_address_new and sbbs_address_hint were absent everywhere (rendering as English fallback). Update receive_description and add the three missing keys, in de fr es it nl fi sv tr id zh ja ko th vi ru uk be sr cs, matching each locale's existing terminology (Serbian in Cyrillic; SBBS/CEX/Beam kept as-is).
The beamtestnet network target is no longer maintained; mainnet is the only shipping flavor. Drop the product flavor and its proguard config, source set (icons, colors, testnet strings, gitignored jniLibs dir), the testnet lib-download script + gradle task, and every FLAVOR_TESTNET code path (explorer/appslist/faucet/DAO/restore URLs, the BEAMX testnet asset id, the testnet-only 'Share DB' settings entries and seed long-press copy, log-share subject). mainnet keeps its .mainnet applicationId suffix so existing installs still update. This also makes the hardcoded .mainnet package in xml-v25/shortcuts.xml correct again (no other flavor to serve).
Every locale was missing the same ~215 English string keys (added since the last translation sync), rendering as English fallback. Translate them for cs de es fr id it ja ko nl ru sr sv th uk vi zh, each consistent with the locale's existing terminology, with format placeholders and line breaks preserved. Serbian uses Cyrillic. fi/tr/be still pending.
Complete the localization sweep for the three locales whose translation agents were interrupted: Belarusian, Finnish and Turkish. All 19 locales now carry every English string key; placeholders and line breaks verified against the source.
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.
Summary
Gets the app building, running, and releasable again on the pinned AGP 3.5 / Gradle 6.1.1 toolchain, fixes the open wallet-safety and dApp-swap bugs, ports the first batch of platform-agnostic fixes from the iOS v7.4 PR (BeamMW/ios-wallet#594), slims the release APKs, drops the dead testnet flavor, and fills every locale's missing strings. The app version is set to 7.4. Everything is verified in the emulator (mainnet, random node) except where noted.
Dependency resolution after the JCenter sunset (#648).
jcenter()replaced withmavenCentral()plus the Aliyun JCenter mirror, which still serves the six JCenter-only artifacts (anko-commons, xfetch2, loadingview, circleindicator, blurry, gradientview). LeakCanary 1.x dropped — itsDisplayLeakActivitydeclares intent filters withoutandroid:exported, which makes installs fail outright on API 31+, and nothing referenced it.Native libs now come from BeamMW/beam CI artifacts (currently 7.5.14510).
builds.beam.mw/mainnet/latesthas served stale 2021 (v5.2) libraries for years; the Kotlin side calls JNI methods that don't exist there (e.g.Wallet.enableBodyRequests), which crashes withUnsatisfiedLinkErrorat runtime rather than failing the build.android-wallet-mainnet.shnow downloads thelibwallet-jni-<abi>artifacts from the latest successful master Build run on BeamMW/beam and strips them withllvm-strip. The.sos stay gitignored — run the script after checkout.Release CI, signed and slim. GitHub Actions workflow runs
assembleMainnetReleaseon pushes to master/v7.4 and on PRs, uploading the arm64-v8a and universal release APKs as artifacts. The APKs are signed in CI (apksigner, v1+v2+v3 schemes) with a dedicated test keystore held in the repo secrets, so the artifacts install directly — without it Android rejects the unsigned output as "package appears to be invalid". The CI key is deliberately not the Play release key: CI builds update over each other, but can't update a Play-store install (uninstall first) and vice versa. Fork PRs get no secrets and fall back to unsigned artifacts. Getting a green run on the frozen toolchain required committinggradle-wrapper.jar(a fresh checkout can't run./gradlewwithout it), installing an isolated minimal SDK (android-32 + build-tools 28.0.3 — AGP 3.5 can't parse the runner's newer SDK metadata), and running sdkmanager under JDK 17 while the build itself uses JDK 11. AGP's own strip task is disabled (doNotStrip+ the AGP-readANDROID_NDK_*vars blanked so it degrades to a warning);ANDROID_NDK_LATEST_HOMEis left set so the fetch script can still locate the NDK'sllvm-strip.Smaller release APKs. Two sources of bloat removed: CI was shipping unstripped ~111 MB native libraries (the fetch script's strip step was disabled by an over-broad NDK-env blanking), and the universal APK carried two full byte-identical copies of the arm64 library under
lib/armeabi/andlib/armv8/plus a standalonearmeabisplit APK containing 64-bit code — all dead since NDK r17 and unloadable on any minSdk-23 device. Dropping the fetch script's legacy-copy loop andarmeabifrom the ABI splits, and keeping the strip step alive on CI, takes the universal APK's native payload from ~625 MB to ~43 MB and the arm64 APK from ~46 MB to ~22 MB.Masternet and beamtestnet flavors removed. Neither network target is maintained; mainnet is the only shipping flavor. Drops both product flavors, their source sets, proguard configs, lib-download scripts/gradle tasks, and every
FLAVOR_MASTERNET/FLAVOR_TESTNETcode path (explorer / appslist / faucet / DAO / restore URLs, the testnet BEAMX asset id, the testnet-only "Share DB" settings entries and seed long-press copy). mainnet keeps its.mainnetapplicationId suffix so existing installs still update, andxml-v25/shortcuts.xml(previously pointing at the masternet package, so app shortcuts never resolved) is now correct with a single flavor to serve.dApp swap confirm always said "not enough funds" (#653).
checkAmount()balance-checked every amount entry, including receive legs — in a swap the wallet doesn't hold the target asset yet, so the check always failed. Only spend legs are checked now; the fee is still checked against BEAM, including a fee-only check for the edge case where a request carries no spend legs. Also fixes both legs of a swap showing the first asset's icon:setAmounts()used the dialog-level assetId for every row instead of the row's own.Wallet wiped after verifying the seed (#645). The seed-verification and wallet-creation flows share the same fragments (WelcomeSeed → WelcomeConfirm → Password → WelcomeProgress), distinguished only by the volatile static
App.isAuthenticated. That flag resets on process death while the navigation back-stack is restored — so if the OS killed the app on the verify screens, the restored flow read it as "create", generated a new mnemonic, and ranremoveDatabase()+createWallet(), destroying the existing wallet. Every create-vs-verify decision is now gated on a durableisVerificationnav-argument, which is persisted in the saved instance state and survives process death. The display-seed path is driven off the same durable arg, so "show seed phrase" always reads the wallet's real seed rather than minting a fresh mnemonic.Automatic restore stuck the first time (#647). Automatic restore showed the wallet only from
onProgress(), i.e. on the next sync-progress event after the snapshot import — when the wallet is already synced at that point, no event arrives and restore hangs on the progress screen. Retrying works because the unfinished-restore cleanup resets state and the timing differs, which matches the "stuck first time, second time it always works" report. On recovery-complete withisSynced(), the wallet is now shown directly; scoped toRESTORE_AUTOMATICso the own-node and create/open paths are untouched. Still needs a physical-device check — the already-synced hang doesn't reproduce in the emulator.Guard against null strings in JNI address callbacks. The native core can pass null for any
WalletAddressDTOstring field — token-address callbacks leavewalletID/labelnull, which is what crashed the iOS wallet's faucet screen (BeamMW/ios-wallet#587).WalletAddress's constructor calledsource.walletID.replaceFirst(...)directly, so the same core behavior NPEs here. The DTO's string fields are now nullable (JNI constructor signature unchanged) and defaulted at the boundary."Get coins" opens the Faucet dApp. The wallet banner and the Settings entry opened
faucet.beamprivacy.community, whose domain no longer resolves (NXDOMAIN). They now open the BEAM Faucet dApp in the in-app browser (live apps-list entry preferred, known plugin-faucet URL as fallback), and the dead faucet-address generation/subscription plumbing is gone from the wallet and settings screens.Receive screen.
generateRegularAddress()re-tokenises the persisted default address, so opening Receive always showed the same one. Switched togenerateNewAddress(), which mints a fresh SBBS address per call. Offline / max-privacy tokens still regenerate only when amount or asset changes, so editing the amount doesn't mint a new address per keystroke.Version label. App version set to 7.4 (
versionCode513). ThevX.Ylabel shown on the welcome/settings screens is now built from a singleAppConfig.APP_VERSION_LABELconstant instead of four inline"v " + …copies (which also rendered a stray space,v 7.3).Complete localization. Every one of the 19 locales was missing the same ~215 English string keys (added since the last translation sync, rendering as English fallback), and the reworded Receive strings existed only in English. All 19 locales now carry every string key, translated consistently with each locale's existing terminology, with format placeholders (
%s,%1$s, …) and line breaks preserved and parity-checked against the source; Serbian is in Cyrillic.Not in this PR
wallet.dbcleanup before init, random-node create skipping the sync UI, stuck "Restored 100%", sync listener removed before its early-return), recovery-progress throttling (the core fires ~8000 events/sec), phase-aware sync-screen messages, Edit Address expiry-to-Never, the node settings restructure + Node Peers screen, and Public Offline pinned atop the Active addresses list.beam/android/jni.cppcompiled intolibwallet-jni.so, and the published Android lib is built with IPFS off and no asset-swap support — so these need core-repo work and a lib rebuild before anything can happen here.Before merge
Closes #648, closes #653, closes #645, closes #643, closes #644.