New app: app.sidecoin

New app: app.sidecoin

Sidecoin is an eCash wallet with BIP-300/301 Drivechain sidechains. Android app, MIT licensed, ~74.5 MB, fdroid + playstore flavors. F-Droid builds the fdroid flavor only, which carries no proprietary dependencies.

Build verification

Version 26.9.30 (versionCode 20260930) from commit ecf636edc525efe7e6590914d5d2cafcba7ad187. CI (pipeline 2900638695) is green across all jobs, including fdroid build:

INFO: compared built binary to supplied reference binary successfully
INFO: supplied reference binary has allowed signer 42126930dd049c558fcebc7f5893fa83cba0021a24aafe447e4dc6b3452d65d4
INFO: success: app.sidecoin

fdroid lint app.sidecoin exits 0, and fdroid rewritemeta produces no diff for the committed metadata.

Reproducible Builds / upstream signature

This recipe uses route (a): a hosted Binaries: plus AllowedAPKSigningKeys:. F-Droid builds from source, apksigcopier compares the result against our published APK byte-for-byte, and only on a match does publish.py ship our signed APK. So the shipped binary keeps the upstream CN=APECS Dev signature.

The reference binary is the app-fdroid-release.apk asset on the v26.9.30 release (74,521,086 bytes, SHA-256 b9f22fb5102b4fc5e7194059fa7459ab63b1b90f5d4380931928ce743786d983).

The build became byte-reproducible in:

  • d9700ff — -ffile-prefix-map on every autolinked CMake target, so no absolute build paths leak into the native libraries.
  • 762805a — drop the content-derived ELF build-id, which -ffile-prefix-map cannot reach (it is seeded from the variable AGP .cxx/<hash>/ directory name).
  • 7aa639f — pin react_native_dev_server_ip. The React Native Gradle plugin fills that resource with the BUILDING machine's first non-loopback IPv4 (AgpConfiguratorUtils.getHostIpAddress), so resources.arsc differed between machines while every other entry matched. It is now fixed to localhost from a finalizeDsl callback on :app.
  • 362709c — drop the AGP-written Dependency metadata APK Signing Block (id 0x504b4453), which scanner.py rejects in the check apk job.

Verified locally by building the same commit twice with --rerun-tasks: both builds hash to b9f22fb5…, byte-identical. The CI fdroid build above then independently reproduced the same bytes from the hosted reference.

If verification ever fails, publish.py skips the release rather than silently re-signing, so this cannot ship a mismatched APK.

Store metadata

The en-US store text, icon, screenshot and changelog live in the source repo in the Triple-T layout that fdroidserver discovers under subdir (now apps/mobile/android/app):

apps/mobile/android/app/src/fdroid/play/
  listings/en-US/title.txt
  listings/en-US/short-description.txt
  listings/en-US/full-description.txt
  listings/en-US/graphics/icon/icon.png
  listings/en-US/graphics/phone-screenshots/1_dashboard.png
  release-notes/en-US/default.txt

Verified against update.py's copy_triple_t_store_metadata(): the …/*/src/*/play fallback discovers all four text entries and both graphics. No localized metadata is carried in this MR.

NonFreeNet

The wallet talks to third-party hosted services that are not free software and cannot be self-hosted from inside the app:

  • https://sidecoin.app/v1 — Sidecoin adapter
  • https://esplora.beta.ecash.ninja — Betanet explorer/API
  • https://esplora.signet.drivechain.info — Signet explorer/API
  • https://ecashfarm.com/v1 — ECX market price
  • https://supaqt.com/v1 — Coin News feeds

Declared as an anti-feature. All outbound hosts are chain, market or news related; there is no analytics, ad or telemetry host.

Ask the reviewer to look at

1. Skia prebuilt static libraries kept via scanignore (the only native binary still ignored). @shopify/react-native-skia's published package contains only prebuilt libs/android/<abi>/*.a, and its CMakeLists.txt imports them as IMPORTED STATIC targets. Deleting them makes :shopify-react-native-skia:buildCMake* fail on a missing libsvg.a. The package's only script (install-skia.mjs) re-downloads the same prebuilt tarball, and the npm tarball has no externals/skia checkout, so there is no source in the package to build from. scanignore is therefore the minimum change. Happy to switch to an srclib source build if you would prefer that. CONFIDENCE: 0 on whether ignoring the prebuilt .a files is acceptable.

2. Everything else is now source-built. react-native-sqlite-storage shipped only prebuilt .so files and no Android C/C++ sources, so there was nothing to compile — it has been removed. The history store now uses @op-engineering/op-sqlite, which compiles the SQLite amalgamation (cpp/sqlite3.c) from source in its own externalNativeBuild. Its packaged libsql/turso/sqlite-vec blobs are unused (their Gradle toggles default to false and we do not set them), and are excluded from the APK because jniLibs.srcDirs = []. They are removed from the scanned tree by the existing scandelete: node_modules. The SQLite scanignore entry is gone.

3. ARM-only APK. reactNativeArchitectures is pinned to arm64-v8a,armeabi-v7a, so the x86/x86_64 libraries (which exist only for emulators, 72.4 MB combined) are dropped. APK size went from 148,163,537 to 74,521,086 bytes (−49.7%) with no loss of device coverage. Precedent: ch.swissbitcoinpay.checkout.yml sets the same property.

Required

  • The app complies with the inclusion criteria
  • All related fdroiddata and RFP issues referenced — no issue; submission via this MR
  • Builds with fdroid build (verified above)
  • Upstream repo contains app metadata in a fastlane folder structure (Triple-T layout under src/fdroid/play/, see "Store metadata" above)
  • Releases are tagged — v26.9.30; AutoUpdateMode: Version + UpdateCheckMode: Tags are set

Suggested

  • External repos added as submodules instead of srclibs — no srclibs used
  • Enable Reproducible Builds — yes, we want this
  • Multiple APKs for native code — not needed: the release APK is ARM-only (arm64-v8a + armeabi-v7a) and carries no x86 code

Edited by Shomari

Merge request reports

Loading
Loading