paritytech / paritytech/host-rust-core
Re-introduce RFC-006 payment.topUp / balanceSubscribe on the TrUAPI runtime (iOS + Android)
@pgherveou is already working on this.
Since Sep 17, 2026.
- Dominant language
- Swift
- Stars
- 10
- Forks
- 3
- Avg merge
- 1d 10h
- Merged PRs (30d)
- 148
Description
Background
Product top-up used to work. Both phones implemented paymentTopUp and the balance subscription behind the native product container: iOS ProductsNativeApi+Payment.swift → IncomingPaymentService (polkadot-ios-community#85 "Top up durability"), Android HostApiInteractor.resolveTopUpSource → TopUpSource.Onboard (polkadot-app-android-v2#1002). A product handed over ProductAccount { derivationIndex }, the host watched the account, signed Coinage.load_recycler_with_external_asset_unpaid from it, and the money showed up in the user's coinage balance.
TrUAPI is now the standard product runtime (iOS Nightly defaults to it; Android is landing its binding). On that runtime the payment surface was never carried over: truapi-server's Payment::top_up answers Unknown("Payments are not supported in dot.li") and balance_subscribe answers PermissionDenied (runtime/capabilities/payment.rs), and the iOS RustHostRuntimeBridge exposes no payment hooks that could override it. The working implementation is still in the apps, one runtime over, unreachable from a TrUAPI product.
Why it matters now
Humanity's Daily Dollar pays each winner's prize on chain into the product account //product//peopl.<tld>/0 as a pUSD balance. Coinage has no deposit address, so the only way that prize becomes spendable is the host's payment.topUp({ source: ProductAccount { derivationIndex: 0 } }). Humanity calls it right after a claim and again at every app start (humanity-spa#134, #136, #137) — and every call dies at the stub.
On paseo-next-v2 the test identity's prize account 5CXjDEKmQhsRKPwbR8eCjBio8Bt4Gv6J9UkkA7uHCkE9hGG7 holds 4 pUSD from four claimed draws and has never signed anything. Every dollar a user wins is sitting on an account no wallet shows.
Ask
Re-introduce on the TrUAPI runtime, on iOS and Android, routed to the top-up the apps already have:
payment.topUpwith theProductAccountsourcepayment.balanceSubscribe
payment.request / statusSubscribe are not needed for this.
To decide along the way
- The native container's
paymentTopUptook a 32-byte top-up id and offeredtopUpStatusSubscribe(Detecting → Claimed / ClaimedPartially / NotClaimed).HostPaymentTopUpRequestin@parity/truapihas neither. Either the bridge makes up an id per call, or RFC-0006 growsid+ a status subscription so a product can learn a top-up endedNotClaimed. ProductAccountmust resolve to the same accounttruapi-server/src/host_logic/product_account.rsderives (soft junctionu32 LE ++ blake2("product-account-index")[..28]). iOS'sProductAccountId.derivationPath()already matches.
Related
- #334 — iOS integration tracker; the unchecked line "Route payment functions and subscriptions for products … through the native/shared core" is this.
- paritytech/humanity-spa#134, #136, #137 — the product side.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Assessment
This issue has not been assessed yet.