feat(coinjoin): offer BIP44 or Shielded destination in post-sync move-funds prompt - #858
Merged
QuantumExplorer merged 4 commits intoAug 7, 2026
Conversation
…-funds prompt The first-sync "Move your mixed coins" popup previously always swept the leftover CoinJoin balance into the BIP44 spendable balance. When the balance is large enough to be worth shielding (>= 2x the shield pool fee + asset-lock base cost + L1 send-fee reserve, and the shielded sub-wallet is bound), a destination-choice sheet now offers: - Dash Wallet balance: the existing one-hop sweep. - Shielded balance: sweep CoinJoin -> own BIP44 receive address, wait for the swept outputs to become spendable, then asset-lock the net amount into the shielded pool (Type 18), with a step checklist. The user authenticates once: the sweep leg runs the spend gate and the asset lock skips its own via a new explicit alreadyAuthorized parameter on ShieldedTransferCoordinator.performAssetLock. Failure posture: the sweep-leg result is kept on the ViewModel, so "Try again" never re-sweeps an emptied CoinJoin account - it resumes from the UTXO wait, or resumes a committed asset lock on its exact outpoint (mirroring the transfer confirm sheet); a stuck lock that survives the session is picked up by the home tx list's ShieldedRecoverySheet. Every failure mode leaves the funds spendable in the BIP44 balance. Small balances keep the BIP44-only dialog, and the availability check fails closed to it. Plumbing: sweepCoinJoin(to:) now also returns the net swept duffs; the CrowdNode UTXO-wait helper is promoted for reuse (waitForFunds); ShieldedTransferStepList gains a positional (labels/currentIndex) init for stages the coordinator phases can't express; the wallet source's onMain trampoline is promoted for the availability check's host reads. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
Important Review skippedAuto reviews are disabled on base/target branches other than the default branch. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Plus Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
…lock Replaces the two-hop shielded destination (sweep CoinJoin -> BIP44, wait, asset-lock) with a single CoinJoin-funded drain asset lock: every mixed-coin UTXO funds the Type 18 lock directly (lock value = sum(inputs) - L1 fee, computed SDK-side) and the shielded pool receives lock_value - pool_fee. The mixed coins never hop through a transparent BIP44 address, and the flow is one transaction with one PIN prompt. - ShieldedTransferCoordinator.performAssetLock gains an AssetLockFundingSource (.bip44(amountDuffs:) | .coinJoinDrain) routed to the new SDK wrapper shieldedFundFromCoinJoinDrain; the historical amountDuffs entry point delegates unchanged. The alreadyAuthorized seam is removed - the coordinator's own gate is the flow's single prompt again. Resume-by-outpoint covers drain locks identically. - CoinJoinMoveFundsSheet: the shielded path is one coordinator run with the same step checklist as the internal transfer; auth-cancel returns to the destination choice; the CoinJoin balance is re-tallied on completion so the popup/Settings surfaces self-clear. - The dead two-hop plumbing is removed (sweepCoinJoinForShielding, waitForSweptCoinJoinFunds, the sweep net-amount return, waitForFunds, and their error strings). Consumes SwiftDashSDK's shieldedFundFromCoinJoinDrain (platform feat/coinjoin-asset-lock-funding, on rust-dashcore key-wallet drain support) - rebuild DashSDKFFI.xcframework after pulling platform. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…nation-e26edf Conflict resolution + semantic reconciliation: - project.pbxproj: keep only the CoinJoinMoveFundsSheet registration in the conflicted hunks (upstream re-sorted the shared ShieldedActivityHistory / PlatformAddress entries to new canonical positions). - HomeViewModel: the shield-destination availability check now reads the shared CoreToShieldedAmountPolicy.poolFeeCredits estimator upstream introduced, replacing the local shielded-fee + base-cost arithmetic. - ShieldedTransferCoordinator: upstream's minimum-amount execution backstop lands scoped to the .bip44 exact-amount funding case — the CoinJoin drain's lock value is SDK-computed and preflighted Rust-side against the pool fee, so no caller amount exists to check. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…he merge All four fixes are to upstream code that no longer compiled at swift-sdk-integration HEAD (the maya-swift-sdk merge, PR #916, landed after the finalizeAtomic refactor, PR #920, without rebasing over it): - CrowdNode error observers (OnlineAccountEmailController, CrowdNodePortalViewController): drop the `if let` on a value the preceding `compactMap { $0 }` already unwrapped — a non-optional binding is a compile error. - MAYA swap deposit (SwiftDashSDKTransactionSender.buildAndSignSwapDeposit): migrate from the removed split setFunding/buildSigned surface to finalizeAtomic, returning FinalizedCoreTransaction like every other send path; assertSwapDepositShape takes the serialized bytes + fee since the finalized handle exposes no raw `.data`. - WalletSendService.buildPreparedSwapDeposit: serialize via `serializedData()` (the PreparedStandardSend initializer now holds a FinalizedCoreTransaction). Candidate for cherry-pick to swift-sdk-integration — the base branch does not build without these. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
The first-sync "Move your mixed coins" popup previously always swept the leftover CoinJoin balance into the BIP44 spendable balance. This PR gives users a choice of destination when there is enough balance to make shielding worthwhile.
CoinJoinMoveFundsSheet) offers:WalletSendService.sweepCoinJoin).lock_value − pool_fee. No transparent intermediate hop, one transaction, one PIN prompt.The availability check fails closed (BIP44-only dialog) when the fee estimate or shielded binding is unavailable.
How
ShieldedTransferCoordinator.performAssetLockgains anAssetLockFundingSource(.bip44(amountDuffs:)|.coinJoinDrain) routed to the new SDK wrappershieldedFundFromCoinJoinDrain; the historicalamountDuffsentry point delegates unchanged, so the internal transfer and Send are untouched.ShieldedTransferStepListgains a positional (labels/currentIndex) init for the wallet leg's progress row.Failure posture
Every failure mode leaves the funds recoverable:
InternalTransferConfirmSheet.tryAgain); across relaunches the home tx list'sShieldedRecoverySheetpicks it up — identical to a BIP44-funded shielded transfer.shieldedSpendUnconfirmedsurfaces the shared non-retryable "submitted, awaiting sync" state.Cross-repo dependencies
Both upstream layers are merged — no pins or integration branches needed:
AssetLockFundingAccount+ drain mode (merged; in platform's rev pin).AssetLockFundingdrain variant with the post-build lock-value floor, family-aware proof/recovery lookups, owner-guarded reservation release,platform_wallet_manager_shielded_fund_from_asset_lock_coinjoin_drainFFI +shieldedFundFromCoinJoinDrainSwift wrapper (merged tov4.2-dev).To build this PR:
../platformonv4.2-dev(≥ 963f0d26fc), thencd ../platform/packages/swift-sdk && ./build_ios.sh --target ios --target sim. Verified: thedashpayscheme builds green against upstreamv4.2-devHEAD with that xcframework.Heads-up: swift-sdk-integration HEAD itself does not compile (the maya-swift-sdk merge #916 landed after the finalizeAtomic refactor #920 without rebasing). This branch carries the four-file fix as its own commit (
fix(build): repair swift-sdk-integration compile breaks…) — cherry-pick it to the base branch independently if desired.Notes
Verification
dashpayscheme build (arm64 simulator) against the rebuilt xcframework; key-wallet unit suites green (551 + 48, incl. 3 new drain/CoinJoin tests).🤖 Generated with Claude Code