Skip to content

feat(kmp): graduate shared-core to real KMP module — Base58 + randomBytes - #1201

Merged
bmc08gt merged 1 commit into
code/cashfrom
feat/kmp-shared-core-real
Aug 7, 2026
Merged

bmc08gt merged 1 commit into
code/cashfrom
feat/kmp-shared-core-real

Conversation

@bmc08gt

@bmc08gt bmc08gt commented Aug 7, 2026 •

Copy link
Copy Markdown
Collaborator

Summary

  • Converts libs:encryption:base58 from single-platform Android module to a proper KMP module with commonMain, androidMain, iosArm64, iosSimulatorArm64, and iosX64 targets
  • Base58.kt is pure Kotlin in commonMain (no JDK deps); JDK-only code stays in androidMain
  • kmp/shared-core slimmed to a thin umbrella: re-exports base58 via api() + export() in iOS framework blocks; spmDevBuild produces SharedCore.xcframework
  • Wires build-logic, version catalog, and root build for KMP: KmpLibraryConventionPlugin, catalog entries for kotlin-multiplatform, android-kotlin-multiplatform-library, and kmmbridge

Key technical finding

alias(libs.plugins.flipcash.kmp.library) in a plugins {} block means the convention plugin applies KMP programmatically — Gradle does NOT generate a type-safe kotlin {} accessor for the build script body. Using kotlin("multiplatform") directly in plugins {} is required for the accessor to work. The KmpLibraryConventionPlugin is registered for future modules but modules must use extensions.configure<KotlinMultiplatformExtension>{} if they use the alias form.

Test plan

  • :libs:encryption:base58:compileKotlinIosArm64 — PASS
  • :libs:encryption:base58:testAndroidHostTest — PASS (commonTest vectors gate)
  • :kmp:shared-core:compileKotlinIosArm64 — PASS
  • :kmp:shared-core:spmDevBuild — PASS (XCFramework at kmp/shared-core/build/XCFrameworks/debug/SharedCore.xcframework)
  • All 9 Android libs:encryption:base58 consumers compile — PASS
  • :apps:flipcash:app:compileDebugSources — PASS

@github-actions github-actions Bot added area: crypto Solana, keys, encryption, signing type: feature New functionality area: build-system Gradle, convention plugins, build-logic labels Aug 7, 2026
…k umbrella

Establishes the umbrella model for cross-platform code sharing:

- kmp/shared-core becomes a thin aggregator that api-exports real KMP
  modules and publishes ONE SharedCore XCFramework (KMMBridge/SPM) so iOS
  consumes everything through a single import. It owns no logic itself.
- :libs:encryption:base58 becomes the first real KMP module (the pilot):
  pure Base58 in commonMain, JDK-only helpers (encodeChecked/decodeChecked/
  hashTwice/decodeToBigInteger) in androidMain, iOS targets via the default
  hierarchy template (no manual source-set wiring). shared-core re-exports it.
- The base58.json cross-platform vector gate now runs on BOTH the JVM and
  native targets (commonTest + a readResource expect/actual).
- All 9 Android consumers keep depending on :libs:encryption:base58
  unchanged — the KMP module still exposes the Android variant.
- Adds a flipcash.kmp.library convention plugin (registered; to be adopted
  by the next KMP modules).

Verified: base58 iOS compile, host vector gate, all 9 consumers + app
compile, and :kmp:shared-core:spmDevBuild produces SharedCore.xcframework.
@bmc08gt
bmc08gt force-pushed the feat/kmp-shared-core-real branch from 372100a to 54eb4e6 Compare August 7, 2026 18:14
@bmc08gt
bmc08gt merged commit 19075c1 into code/cash Aug 7, 2026
2 of 3 checks passed
@bmc08gt
bmc08gt deleted the feat/kmp-shared-core-real branch August 7, 2026 18:16
bmc08gt added a commit that referenced this pull request Aug 7, 2026
KMP library modules (com.android.kotlin.multiplatform.library + withHostTest {})
expose `testAndroidHostTest`, not the `testDebugUnitTest` that com.android.library
modules expose. The flipcashTestDebug aggregate only bucketed modules into
android (`testDebugUnitTest`) and pure-JVM (`test`), so once base58 became a KMP
module (#1201) it landed in the android bucket and the aggregate depended on a
non-existent `:libs:encryption:base58:testDebugUnitTest` — silently skipping /
breaking the base58 vector gate in the aggregate. This PR's sha256/sha512/hmac
KMP conversions would extend the same fault.

Add a kmpUnitTestModules list (base58 + sha256/sha512/hmac), exclude it from the
android bucket, exclude the testless :kmp:shared-core umbrella, and depend on
`testAndroidHostTest` for the KMP modules so their host tests run in the aggregate.

Verified: `./gradlew flipcashTestDebug --dry-run` resolves the full task graph
(exit 0) with the KMP host-test tasks wired in.
bmc08gt added a commit that referenced this pull request Aug 7, 2026
)

* feat(kmp): convert sha256/sha512/hmac to KMP modules via kotlincrypto

* fix(kmp): wire KMP modules' testAndroidHostTest into flipcashTestDebug

KMP library modules (com.android.kotlin.multiplatform.library + withHostTest {})
expose `testAndroidHostTest`, not the `testDebugUnitTest` that com.android.library
modules expose. The flipcashTestDebug aggregate only bucketed modules into
android (`testDebugUnitTest`) and pure-JVM (`test`), so once base58 became a KMP
module (#1201) it landed in the android bucket and the aggregate depended on a
non-existent `:libs:encryption:base58:testDebugUnitTest` — silently skipping /
breaking the base58 vector gate in the aggregate. This PR's sha256/sha512/hmac
KMP conversions would extend the same fault.

Add a kmpUnitTestModules list (base58 + sha256/sha512/hmac), exclude it from the
android bucket, exclude the testless :kmp:shared-core umbrella, and depend on
`testAndroidHostTest` for the KMP modules so their host tests run in the aggregate.

Verified: `./gradlew flipcashTestDebug --dry-run` resolves the full task graph
(exit 0) with the KMP host-test tasks wired in.
bmc08gt added a commit that referenced this pull request Aug 7, 2026
…compile gate (#1205)

* fix(kmp): restore Java interop for sha256/sha512 KMP modules

- Sha256Hash.bytes: internal → public val (restores cross-module Kotlin
  access and the auto-generated Java getBytes() accessor; removes now-
  redundant explicit getBytes() method that would clash with the getter)
- Sha256Hash companion functions: add @JvmStatic so Java callers can
  resolve hash(), hashTwice(), wrap(), wrapReversed(), of(), twiceOf()
  as static methods
- PBKDF2SHA512.derive: add @JvmStatic so Java callers can call
  PBKDF2SHA512.derive(...) from a static context
- MnemonicCode.java: replace Sha256Hash.newDigest() (an androidMain
  extension, not Java-callable) with an inline MessageDigest.getInstance
  call; Sha256Hash.hash() now resolves via @JvmStatic above

* ci: add cred-free compile-check job to catch KMP interop regressions

Adds a compile-check job that runs :apps:flipcash:app:compileDebugSources
before the flipcash-tests job. This task compiles all Kotlin/Java sources
but stops before processDebugGoogleServices, so it requires no secrets.

The missing gate is what allowed the KMP conversions in #1201 and #1202
to land on code/cash without surfacing the Java interop breaks (missing
@JvmStatic, internal visibility) — those were only caught by compiling
the full consumer graph, which CI never did without creds.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area: build-system Gradle, convention plugins, build-logic area: crypto Solana, keys, encryption, signing type: feature New functionality

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant