Skip to content

Swift SDK: DashPay contact-received funds are unspendable (receival accounts unreachable by the send path) #4255

Description

@bfoss765

Problem

Funds received via DashPay contact payments land in per-contact DIP-15 dashpay_receival accounts. The Swift SDK's send paths cannot spend them:

  • CoreTransactionBuilder.AccountType is only {bip44, bip32, coinJoin} — no DashPay variant, so a receival account cannot be named.
  • sendDashPayPayment funds strictly from BIP44 account 0.
  • dashpay_receival_accounts are summed into the balance but excluded from every coin-selection path.

Net effect: a wallet funded solely by contact payments shows a balance but every send fails with CoreInsufficientFunds (BIP44 account 0 empty). Verified on Android with the identical Rust core before the fix below; the Swift surface has the same limitation (confirmed by FFI review — no receival-capable selector is exported to Swift).

What Android/Kotlin now does (reference implementation)

Fixed on branch bfoss765/platform:kotlinSDK-v4-qa3 (rev f01dc1a), on-device verified on testnet:

  1. finalize_signed_payment_from_funding_path (rs-platform-wallet wallet/core/send.rs) — token-minting single-account build+sign from an account-level derivation path; the only path that can reach a DashpayReceivingFunds account. Reservation is recorded against the resolved account; change routes to BIP44/0 (privacy: funding domains never unioned — guardrails in wallet/funding_privacy.rs); watch-only external accounts refused. FFI: core_wallet_build_signed_payment_with_token.
  2. accountBalances rows now carry derivationPath (FFI AccountBalanceEntryFFI.derivation_path, ABI-additive last field) so the app can pass the exact string as funding_path — no hand-built paths.
  3. App wiring: on the specific CoreInsufficientFunds(BIP44/0) failure, pick the single receival account with sufficient confirmed funds, build via funding path, broadcast via the reservation token, release on failure. Never combine multiple contacts' accounts in one tx.

What iOS needs

  • Rebuild DashSDKFFI.xcframework from a platform rev that includes the primitives above (they are C-ABI; rs-platform-wallet-ffi already exports them on the branch).
  • Swift bindings for core_wallet_build_signed_payment_with_token (+ the existing broadcast/release-by-token pair) and the derivation_path field on account-balance rows.
  • App-side fallback mirroring the Android wiring (single account, largest sufficient, original error rethrown when funds are split across contacts).
  • Note: AccountBalanceEntryFFI gained an appended field — any Swift consumer indexing that struct by stride must be regenerated.

Context

Part of the dashj→SDK cutover: post-cutover there is no legacy engine to fall back to, so this is the only spend path for contact-received funds. Android details/commits: kotlinSDK-v4-qa3 @ f01dc1a (platform), app dashpay/dash-wallet @ 88a7d751 (feat/kotlin-sdk-phase1).

🤖 Generated with Claude Code

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions