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:
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.
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.
- 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
Problem
Funds received via DashPay contact payments land in per-contact DIP-15
dashpay_receivalaccounts. The Swift SDK's send paths cannot spend them:CoreTransactionBuilder.AccountTypeis only{bip44, bip32, coinJoin}— no DashPay variant, so a receival account cannot be named.sendDashPayPaymentfunds strictly from BIP44 account 0.dashpay_receival_accountsare 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:finalize_signed_payment_from_funding_path(rs-platform-walletwallet/core/send.rs) — token-minting single-account build+sign from an account-level derivation path; the only path that can reach aDashpayReceivingFundsaccount. Reservation is recorded against the resolved account; change routes to BIP44/0 (privacy: funding domains never unioned — guardrails inwallet/funding_privacy.rs); watch-only external accounts refused. FFI:core_wallet_build_signed_payment_with_token.accountBalancesrows now carryderivationPath(FFIAccountBalanceEntryFFI.derivation_path, ABI-additive last field) so the app can pass the exact string asfunding_path— no hand-built paths.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
DashSDKFFI.xcframeworkfrom a platform rev that includes the primitives above (they are C-ABI;rs-platform-wallet-ffialready exports them on the branch).core_wallet_build_signed_payment_with_token(+ the existing broadcast/release-by-token pair) and thederivation_pathfield on account-balance rows.AccountBalanceEntryFFIgained 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), appdashpay/dash-wallet@ 88a7d751 (feat/kotlin-sdk-phase1).🤖 Generated with Claude Code