Skip to content

feat: Android host adapter (android/truapi-host) + hosts/android submodule#289

Open
TarikGul wants to merge 8 commits into
worktree-issue-96-mobile-followupfrom
tg/truapi-rust-core
Open

feat: Android host adapter (android/truapi-host) + hosts/android submodule#289
TarikGul wants to merge 8 commits into
worktree-issue-96-mobile-followupfrom
tg/truapi-rust-core

Conversation

@TarikGul

@TarikGul TarikGul commented Jul 17, 2026

Copy link
Copy Markdown
Member

Android TrUAPI host adapter

Brings Android to parity with the iOS host adapter (ios/truapi-host): the truapi repo owns a Kotlin host-adapter package, and vendors the Android app as a submodule so the core can be built and diagnosed against it.

What this adds

  • android/truapi-host/ — the Kotlin host-adapter package over the truapi-server UniFFI core, the analogue of ios/truapi-host. TrUAPIHost.kt exposes the current FFI surface: HostBridge (device/remote permission split, a single confirmUserAction, chainConnect/Send/Close, lookupPreimage, theme, feature support), HostStorage + HostCoreStorage, TrUAPIHostCore (WS-bridge lifecycle, local-session activation, permission-authorization status, native change notifications), and LocalhostBridgeBootstrap. Products in a WebView reach the core over the localhost WebSocket bridge; the core signs on-device (signing-host role) with no separate phone.

  • Build tooling (Makefile): uniffi-kotlin (generate Kotlin bindings), android-jni (cargo-ndk cross-compile of libtruapi_server.so per ABI), and android-publish-local. check-android-parity fails if the canonical TrUAPIHost.kt shell drifts from the copy vendored in the app (skips cleanly when the submodule is uninitialized). Generated bindings and jniLibs are gitignored.

  • hosts/android submodule — vendors polkadot-app-android-v2 (branch tg/truapi-rust-core), mirroring hosts/ios. .gitmodules uses the HTTPS URL. Its app-side integration (a bindings/truapi-host rust-android module, a functional DefaultHostBridge + WebSocketChainProvider, and an instrumented diagnostics harness) lives in that repo's companion PR.

Verified on an Android emulator

The vendored app drives the host playground through the core end-to-end: the built-in Diagnosis sweep runs every TrUAPI method, with on-device signing/ permission approval prompts (no phone). All Signing methods pass and sign
locally; Account/Entropy/Local Storage/Notifications/Permissions pass. Remaining failures are funding/allowance-gated (Payment needs a balance; Preimage/Resource Allocation need on-chain allowances) or unimplemented on this host (Chat), consistent with the deployed-host diagnosis.

Notes

  • The canonical package is shell-only, matching ios/truapi-host (no default-host/chain-provider helpers — those are app-side).
  • TrUAPIHost.kt is duplicated between here and the vendored app copy; make check-android-parity guards against drift until it's single-sourced.
  • JitPack distribution is documented as the target but is not yet wired (no root jitpack.yml); local integration uses make android-publish-local + mavenLocal(). Noted in android/truapi-host/README.md.

TarikGul added 7 commits July 17, 2026 13:39
Add the android/truapi-host package (Kotlin host adapter shell over the
truapi-server UniFFI core, localhost WebSocket bridge transport) matched to the
current core FFI surface: HostCoreStorage, a single confirmUserAction, local
signing session activation, and LocalhostBridgeBootstrap.

Add Makefile targets uniffi-kotlin (Kotlin binding generation), android-jni
(cargo-ndk cross-compile of libtruapi_server.so per ABI), and
android-publish-local; gitignore the generated bindings and jniLibs.
- android-publish-local no longer depends on android-jni: the AAR does not
  bundle the cdylib, so publishing only needs the Kotlin bindings (JitPack has
  no NDK).
- README: flag that the JitPack distribution is not yet wired up (no
  jitpack.yml at the repo root) and document the INTERNET permission the
  consuming app must declare.
…dule

Mirror hosts/ios: vendor the Android app at hosts/android (tracking branch
tg/truapi-rust-core) so the truapi repo can build and diagnose the app against
its own core. .gitmodules uses the HTTPS URL to match hosts/ios; document the
mobile host adapter packages and host submodules in the README layout.
Advance the submodule pin to include DefaultHostBridge + WebSocketChainProvider
and the connected-session diagnostics test, so the vendored app builds and
diagnoses against a working host.
Advance the hosts/android submodule to the hardened host bridge (deny-by-default
confirmations, lifecycle/storage fixes) and add a check-android-parity make
target that fails if the canonical android/truapi-host TrUAPIHost.kt shell
drifts from the copy vendored in the app (hosts/android). The target skips
cleanly when the submodule is not initialized, so it is safe to run in any
checkout and to wire into CI.
@TarikGul TarikGul changed the title Android wiring feat: Android host adapter (android/truapi-host) + hosts/android submodule Jul 23, 2026
@pgherveou

Copy link
Copy Markdown
Collaborator

will test it out

One note before before I look into the code.
We have to be make sure the mobile integration is using the signing host logic and not the pairing host logic as mobile apps are accounts holder.

I am a bit surprised that this work without some of the changes to the signing host that I pushed to
#264 and backported in #288

@TarikGul

TarikGul commented Jul 23, 2026

Copy link
Copy Markdown
Member Author

@pgherveou Calrification: so signing did fail with the ring-vrf path which was expected but for sr25519 signing worked fine. I only used the signing host - no pairing at all.

This is the list of pass fail:

✅ Passed (37)

Account
- Account/connection_status_subscribe
- Account/get_account
- Account/get_account_alias
- Account/get_legacy_accounts
- Account/get_user_id
- Account/request_login

Chain (all)
- Chain/get_head_header, get_head_body, get_head_storage
- Chain/call_head
- Chain/unpin_head, continue_head, stop_head_operation
- Chain/get_spec_genesis_hash, get_spec_chain_name, get_spec_properties
- Chain/broadcast_transaction, stop_transaction

Signing (all — on-device sr25519)
- Signing/create_transaction
- Signing/create_transaction_with_legacy_account
- Signing/sign_raw, sign_payload
- Signing/sign_raw_with_legacy_account, sign_payload_with_legacy_account

Entropy — Entropy/derive
Local Storage — read, write, clear
Notifications — send_push_notification, cancel_push_notification
Permissions — request_device_permission, request_remote_permission
System — handshake, feature_supported, navigate_to
Theme — Theme/subscribe

❌ Failed (27)

Chat (all — not implemented in core)
- create_room, register_bot, list_subscribe, post_message, action_subscribe, custom_message_render_subscri

Coin Payment (all — need a funded balance)
- create_purse, query_purse, rebalance_purse, delete_purse, create_receivable, listen_for_payment

Payment (all — need a funded balance)
- balance_subscribe, top_up, request, status_subscribe

Statement Store (all — not implemented in core)
- subscribe, create_proof, submit, create_proof_authenticated

Preimage — lookup_subscribe, submit (allowance-gated)
Resource Allocation — request (allowance-gated / native-only)
Account — create_account_proof (ring-VRF; comes from  #288)

@TarikGul

Copy link
Copy Markdown
Member Author

Holding this until #288 lands. Two things depend on it:

  1. Signing host: mobile is an account holder, so it signs through the signing host. The respondToPairing surface isn't exposed over the native binding yet, and that's part of the signing-host work in feat(core): implement missing signing host fn #288.
  2. create_account_proof: this is the ring-VRF path, which is the one method that fails right now on the emulator. feat(core): implement missing signing host fn #288 backports the signing-host ring-VRF changes that make it work.

Once #288 is in the mobile base I'll wire respondToPairing.

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.

2 participants