Skip to content

Feat: Prebuilt Binaries - #23

Closed
Psycarlo wants to merge 2 commits into
bitcoindevkit:masterfrom
Psycarlo:feat/prebuilt-binaries
Closed

Psycarlo wants to merge 2 commits into
bitcoindevkit:masterfrom
Psycarlo:feat/prebuilt-binaries

Conversation

@Psycarlo

@Psycarlo Psycarlo commented Aug 5, 2026

Copy link
Copy Markdown

Prebuilt native binaries + Expo support

Makes bdk-rn installable with a plain npm install / npx expo install. No Rust toolchain, no manual tarball download.

How it works

  • Release workflow (.github/workflows/release.yml): pushing a v* tag builds the Rust binaries (Android: arm64-v8a, armeabi-v7a, x86, x86_64 · iOS: device + arm64/x86_64 simulators), attaches them as zips to a GitHub Release with SHA-256 checksums and build provenance attestation, then publishes to npm via trusted publishing. Checksums are injected into the published package.json; binaries are stripped so the tarball stays small.
  • Postinstall (scripts/postinstall.js): downloads the zips for the matching release, verifies checksums, extracts them into place. Supports BDK_RN_SKIP_POSTINSTALL, BDK_RN_BINARY_BASE_URL (mirror), and BDK_RN_ARTIFACTS_DIR (offline installs).
  • Expo config plugin (app.plugin.js): fails prebuild with a clear error if the New Architecture is disabled; sets required gradle properties.

Before the first release

  • npm access to the bdk-rn package name
  • Configure this repo as a trusted publisher on npmjs.com
  • Bump the version (the v1.0.0 tag already exists; the workflow refuses existing releases)

@Psycarlo

Copy link
Copy Markdown
Author

@thunderbiscuit can you look into this?

@Psycarlo Psycarlo closed this by deleting the head repository Sep 2, 2026
@thunderbiscuit

Copy link
Copy Markdown
Member

@Psycarlo I still like what you had in there! We've been swamped with the Red Team stuff but I do plan on merging this, and I am today working on the 3.1 release of bdk-ffi, which should make its way into bdk-rn.

Can I consider this PR still good code or did you have a reason to close it that should make me not merge it?

@Psycarlo

Psycarlo commented Sep 2, 2026

Copy link
Copy Markdown
Author

@thunderbiscuit my bad. I deleted head repository by mistake. Please use this code, still good. Not sure how can you reuse this code now and keep me as a contributor.

@bennyhodl

Copy link
Copy Markdown

Note

🤖 Opus 5 (1M context) responding on behalf of bennyhodl

Building the binaries in CI is the right call. The ask is to drop the postinstall and ship them
in the npm tarball instead.

An install script that downloads breaks under --ignore-scripts, behind proxies, and offline, and
leaves the published tarball non-self-contained.

npm already covers integrity. The registry stores a sha512 per tarball that every package manager
verifies and every lockfile pins. npm publish --provenance — one flag, and this PR already uses
trusted publishing — signs an attestation binding the tarball to the workflow run and commit. Both
cover only what is in the tarball, which is why the script hand-rolls SHA-256 today.

Size: npm's 256 MiB limit is on the compressed tarball, not unpacked (onnxruntime-node publishes
at 283 MB unpacked). bdk-rn projects to ~95 MB packed.

Three changes, independent of the above:

1. android.useSharedLibrary: true

Android currently links a static archive per ABI instead of a linked .so. On iOS the same crate
is 166 MB as an archive vs 14 MB linked; expect a similar ratio across the four ABIs. The .so
must not be stripped or ubrn's bindings generation breaks, so build Android under plain release
rather than release-smaller, which sets strip = "debuginfo".

2. Gate uniffi/cli behind a feature in bdk-ffi

40 MB — 27% of every iOS slice — is the bindgen toolchain: uniffi_bindgen 24.5 MB, goblin
3.1 MB, clap_builder 2.9 MB, plus weedle, uniffi_udl, toml, cargo_metadata. None of it
runs on device. It's there because uniffi = { features = ["cli"] } is a normal dependency and
crate-type = ["staticlib"] bundles the full graph.

uniffi = { version = "=0.31.2", default-features = false }

[features]
uniffi-bindgen = ["uniffi/cli"]

[[bin]]
name = "uniffi-bindgen"
required-features = ["uniffi-bindgen"]

Bindgen stays available via cargo build --features uniffi-bindgen for bdk-swift/kotlin/python.
This is a bdk-ffi change, not bdk-rn, and needs testing against those targets.

3. Remove x86_64-apple-ios from ubrn.config.yaml

Listed but not built — the xcframework has only ios-arm64 and ios-arm64-simulator. Removing it
changes nothing today and stops it later becoming a third ~166 MB slice. It's the Intel Mac
simulator. @thunderbiscuit — supported target or not?


Referencesddk-ffi publishes this way (@bennyblader/ddk-rn,
103 MB unpacked / 38 MB tarball, no install scripts):

Measurements and methodology: https://gist.github.com/bennyhodl/559c8b8b96eb6fb455a63669364c573c

@thunderbiscuit

Copy link
Copy Markdown
Member

Thanks guys for your input, I'm currently drafting something that will pull from both those approaches @Psycarlo @bennyhodl. I'll tag you both there when that's done and we can see if that solves everyone's problems.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants