Repository navigation
Conversation
Converts network:jwt, currency-math, encryption:keys, datetime and messaging onto flipcash.kmp.app.library and gives encryption:utils a jvmShared source set for its java.*/protobuf helpers. Adds :libs:parcelable, a common Parcelable/@parcelize stand-in that typealiases android.os.Parcelable on Android, so parcelable models can live in commonMain. currency-math's test fixtures become :libs:currency-math:test-fixtures, and the desktop build reads the curve tables from the classpath.
…lable A common @parcelize class implemented the JVM Parcelable's abstract members on Android only, so it failed to compile for jvm. Parcelable is now a member-free marker; PublicKey, which writes its own parcel format, implements ManualParcelable.
Timber, SystemClock and android.database.SQLException move behind PlatformLog actuals; FileTree stays in androidMain and plugs in through LogFileStore. The library had debug and release values for NOTIFY_ERRORS, which a single-variant KMP target can't carry, so the app now sets BuildFlags from its own BuildConfig at startup.
ResourceHelper keeps the members that return plain types in commonMain. The four that return Drawable, Typeface, DisplayMetrics and File move to AndroidResourceHelper, which only the access-key screens use; the app binds both. FakeResourceHelper moves from testFixtures to :ui:resources:test-fixtures, since the KMP library target has no testFixtures.
…droid+jvm Currency icons sit behind an expect object (null on desktop), and SocialProfile's file extension lookup gets a JVM copy of the AOSP MimeTypeMap rules.
services:opencode now builds for jvm with Hilt wiring left in androidMain. Its keys came from the Java JNI class com.getcode.ed25519.Ed25519, which has no desktop equivalent, so: - ed25519 gains a jvmShared source set with a Kotlin Ed25519 object (same members as the Java class) over Ed25519Kmp. KeyPair keeps the Base64 string fields and its Parcelable form, so stored keys are unchanged. Callers move from com.getcode.ed25519 to com.getcode.ed25519kmp. - mnemonic's DerivedKey, MnemonicPhrase and MnemonicCache, and utils' Ed25519 extensions, move from androidMain to jvmShared. - logging gains a plain Log (Timber on Android) for the two opencode files that logged without trace()'s gating. - toInstantFromMillis moves to datetime's commonMain. - UserManager reads BuildFlags.isDebug instead of opencode's BuildConfig, which a KMP library no longer generates. The KMP Android target now compiles Java (withJava()): Hilt's KSP processors emit hilt_aggregated_deps as Java, and without it the app graph lost every opencode @module binding. Adds HeadlessBalanceTest (jvmTest), which fetches token balances from the OCP backend over grpc-okhttp with no UI or DI. It reads the phrase from FLIPCASH_TEST_MNEMONIC or flipcash.test.mnemonic in local.properties and skips when neither is set.
services:flipcash now applies flipcash.kmp.app.library with Hilt run through kspAndroid. Android-only pieces sit behind seams: - UserManager takes an AnalyticsIdentifier instead of MixpanelAPI; FlipcashModule binds it to Mixpanel.identify. - ForegroundGate is a common interface; the process-lifecycle implementation stays in androidMain. - ChatId's hand-written parcel code moves to ManualParcelable. - KeyPair derivation goes through the byte-seed path shared with services:opencode, so derived keys are unchanged. Test fakes move to :services:flipcash:test-fixtures. shared:analytics reads BuildFlags.isDebug instead of this module's BuildConfig.
FlipcashDatabase, its DAOs, entities and migrations now live in commonMain. Migrations run on SQLiteConnection, MessageDao's raw query takes a RoomRawQuery, and init() takes a builder factory: Android passes Room.databaseBuilder(context), desktop opens a file through BundledSQLiteDriver. isOpen() stays Android-only, since Room exposes RoomDatabase.isOpen there alone.
The module keeps everything it had in androidMain, with the dependencies flipcash.android.feature used to add. Only the blocklist and activity feed models, which persistence:sources maps to and from, move to commonMain.
Data sources call a common inTransaction instead of room-ktx's withTransaction, which Room KMP only offers on Android. Android keeps withTransaction; the JVM runs the block on Room's writer connection. Token icons encode with java.util.Base64, which matches Android's NO_WRAP output. The draft data source and its mappers use Uri, so they stay in androidMain.
This was referenced Oct 23, 2026
Collaborator
Author
|
Landed in #1894 as one squash against code/cash. |
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.
Stacked on #1838. This moves the data stack behind
features/balanceonto an android + jvm KMP target, so a desktop build can fetch the balance with the same services, Room database and data sources the Android app uses. No UI moves here; that's A2.What moved
flipcash.kmp.app.library, added in #1838, is the convention plugin for modules that target only Android and the JVM. Because both targets are JVMs,commonMaincan usejava.*directly, which keeps most conversions to a plugin swap and agit mv.Modules this PR moves onto it:
network:jwt,currency-math,encryption:keys,datetime,messaging,parcelable,logging,ui:resources,currency,models,locale:public,connectivity:public,services:opencode,services:flipcash,persistence:db,persistence:sources,tokens:core, andapps:flipcash:core(models only; its Compose code stays inandroidMainuntil A2).The seams that needed writing by hand:
libs:parcelableexposes a common@Parcelize/Parcelablealias. Classes with hand-written parcel code implementManualParcelable, which on Android is a sub-interface ofandroid.os.Parcelable.PlatformLogexpect/actual, aLogFileStoreinterface for the file tree, andBuildFlags, set from the app'sBuildConfiginTraceInitializer. Library modules on the KMP android target don't get aBuildConfig.ResourceHelperis common; the Android-typed members moved toAndroidResourceHelper, which onlyaccesskeyuses.com.getcode.ed25519kmp.Ed25519with the same members (about 150 imports). Key derivation that went throughBase64.DEFAULTnow derives from the byte seed and produces the same key.UserManagertakes anAnalyticsIdentifierinstead ofMixpanelAPI;FlipcashModulebinds it to Mixpanel.SQLiteConnection, the database uses@ConstructedBy, andwithTransactiongoes through aninTransactionexpect/actual. The JVM opens the database withBundledSQLiteDriver.Build shape changes on Android
kspAndroid; only the app and notifications modules use@AndroidEntryPoint, so libraries didn't need the plugin. Modules with a Hilt@ModuleneedwithJava()on the android target, or the app's graph can't see their bindings.testFixturesaren't available on the KMP android target, soui:resourcesandservices:flipcasheach get a:test-fixturesmodule (ascoroutinesdid in feat(kmp): add a jvm() target to the shared KMP libraries #1838), and their consumers point at it.NOTIFY_ERRORSin the app'sBuildConfigis now set per build type and copied intoBuildFlags; nothing read the old field.Headless balance test
services:opencodehas ajvmTestthat derives the owner from a recovery phrase and callsgetTokenAccountsover a plain grpc-okhttp channel. It reads the phrase fromFLIPCASH_TEST_MNEMONICorflipcash.test.mnemonicinlocal.properties, and skips when neither is set, so CI stays green without a credential.It hasn't run against the backend yet: no phrase is configured on the machine that built this.
Not in this PR
shared:tokens(the token coordinator),shared:transaction-history, and movingshared:fundingout ofandroidMainare deferred to A2.shared:tokensdepends onamount-entry,onramp:*,shareableandhaze, so converting it means converting UI modules first.