Skip to content

Conversation

@PastaPastaPasta
Copy link
Member

@PastaPastaPasta PastaPastaPasta commented Oct 30, 2025

Issue being fixed or feature implemented

Use mempool fetch all, and properly set sync height when we have multiple wallets

What was done?

How Has This Been Tested?

Tested locally

Breaking Changes

None

Checklist:

  • I have performed a self-review of my own code
  • I have commented my code, particularly in hard-to-understand areas
  • I have added or updated relevant unit/integration/functional/e2e tests
  • I have added "!" to the title and described breaking changes in the corresponding section if my code contains any
  • I have made corresponding changes to the documentation if needed

For repository code-owners and collaborators only

  • I have assigned this pull request to a milestone

Summary by CodeRabbit

  • New Features

    • Wallet creation now distinguishes between new and imported wallets, automatically configuring appropriate synchronization starting points per network.
  • Improvements

    • Updated mempool data retrieval strategy to optimize transaction fetching.
    • Enhanced wallet creation logging to track initialization state and sync configuration.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Oct 30, 2025

Walkthrough

The changes modify wallet creation logic to distinguish between imported and new wallets, with conditional initialization of birth heights and sync-from heights. Additionally, the SPV mempool strategy is switched from BloomFilter to FetchAll. The isImport parameter is threaded through the wallet service layer to determine initialization behavior.

Changes

Cohort / File(s) Summary
SPV Mempool Configuration
packages/swift-sdk/Sources/SwiftDashSDK/SPV/SPVClient.swift
Mempool strategy changed from BloomFilter (rawValue 1) to FetchAll (rawValue 0) during initialization
Wallet Import Support
packages/swift-sdk/SwiftExampleApp/SwiftExampleApp/Core/Services/WalletService.swift, packages/swift-sdk/SwiftExampleApp/SwiftExampleApp/Core/Wallet/WalletManager.swift
Added isImport: Bool parameter to wallet creation flow; birth height and per-network sync-from heights now conditionally set based on import state (fixed baselines for imports, SPV checkpoint-derived for new wallets); HDWallet instantiation updated to use isImported flag

Sequence Diagram

sequenceDiagram
    participant WalletService
    participant WalletManager
    participant HDWallet as HDWallet<br/>(Instantiation)

    WalletService->>WalletManager: createWallet(isImport: Bool)
    
    alt isImport = true
        Note over WalletManager: birthHeight = 730000 (mainnet)<br/>or 1 (other networks)
        Note over WalletManager: sync-from heights = fixed baselines
    else isImport = false
        Note over WalletManager: birthHeight = 0
        Note over WalletManager: sync-from heights = derived from<br/>SPV checkpoint heights
    end
    
    WalletManager->>HDWallet: HDWallet(isImported: isImport)
    HDWallet-->>WalletManager: wallet created
    WalletManager-->>WalletService: return HDWallet
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

  • Birth height and sync-from height logic: Verify conditional logic correctly assigns baselines for imported vs. new wallets across mainnet and other networks
  • isImport parameter threading: Confirm the flag properly flows from WalletService through WalletManager and is accurately reflected in HDWallet initialization
  • SPV mempool strategy: Validate that switching from BloomFilter to FetchAll aligns with intended mempool data retrieval behavior

Poem

🐰 A wallet can be fresh or imported, we say,

With birth heights set in a discerning way,

New wallets start at zero, clear and bright,

While imports plant roots at fixed heights,

SPV now fetches all, no filter to weigh! ✨

Pre-merge checks and finishing touches

❌ Failed checks (1 inconclusive)
Check name Status Explanation Resolution
Title Check ❓ Inconclusive The pull request title "fix: resolve a few issues in iOS example app" is thematically related to the changeset since it refers to fixes in the iOS example app context. However, the title uses the vague and non-descriptive phrase "resolve a few issues" without conveying what those specific issues are. The actual changes involve two distinct improvements: switching the mempool strategy from BloomFilter to FetchAll, and adjusting sync height logic based on import state for wallet creation. The title fails to communicate these meaningful details, making it generic and uninformative for someone reviewing git history. Consider revising the title to be more specific about the changes. A better title might be "fix: use mempool fetch all and properly set sync height for imported wallets" or "fix: switch to FetchAll mempool strategy and correct sync heights for imports," which would clearly communicate the two primary fixes without requiring reviewers to inspect the full changeset details.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch fix/ios-wallet-fixes

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
packages/swift-sdk/SwiftExampleApp/SwiftExampleApp/Core/Services/WalletService.swift (1)

322-350: Remove duplicate sync-from height logic.

The per-network sync-from heights are already set by WalletManager.createWallet at lines 164-191 in WalletManager.swift. This duplicate logic creates unnecessary code duplication and risks inconsistency if the two implementations diverge.

Remove lines 322-350 from WalletService since WalletManager handles this:

             // Load the newly created wallet
             await loadWallet(wallet)

-            // Set per-network sync-from heights
-            // Imported wallets: mainnet=730000, testnet=0, devnet=0
-            // New wallets: use current known tip for the selected network (fallback to latestHeaderHeight/checkpoint)
-            let isImported = isImport
-            if isImported {
-                // Imported wallet: use fixed per-network baselines
-                wallet.syncFromMainnet = 730_000
-                wallet.syncFromTestnet = 0
-                wallet.syncFromDevnet = 0
-            } else {
-                // New wallet: per selected network, use the latest checkpoint height of that chain
-                let nets = networks ?? [walletNetwork]
-                for n in nets {
-                    switch n {
-                    case .mainnet:
-                        let cp = SPVClient.latestCheckpointHeight(forNetwork: .init(rawValue: 0)) ?? 0
-                        print("[WalletService] New wallet baseline mainnet checkpoint=\(cp)")
-                        wallet.syncFromMainnet = Int(cp)
-                    case .testnet:
-                        let cp = SPVClient.latestCheckpointHeight(forNetwork: .init(rawValue: 1)) ?? 0
-                        print("[WalletService] New wallet baseline testnet checkpoint=\(cp)")
-                        wallet.syncFromTestnet = Int(cp)
-                    case .devnet:
-                        let cp = SPVClient.latestCheckpointHeight(forNetwork: .init(rawValue: 2)) ?? 0
-                        print("[WalletService] New wallet baseline devnet checkpoint=\(cp)")
-                        wallet.syncFromDevnet = Int(cp)
-                    }
-                }
-            }
-
-            // Persist sync-from changes
-            try modelContainer?.mainContext.save()
-            
             print("=== WalletService.createWallet SUCCESS ===")
             return wallet
packages/swift-sdk/SwiftExampleApp/SwiftExampleApp/Core/Wallet/WalletManager.swift (1)

202-206: Update importWallet to use the isImport parameter.

The importWallet method doesn't pass isImport: true to createWallet, then manually sets wallet.isImported = true afterwards. This bypasses the new birthHeight and sync-from heights logic designed for imported wallets.

Apply this diff to properly use the isImport parameter:

     func importWallet(label: String, network: Network, mnemonic: String, pin: String) async throws -> HDWallet {
-        let wallet = try await createWallet(label: label, network: network, mnemonic: mnemonic, pin: pin)
-        wallet.isImported = true
-        try modelContainer.mainContext.save()
-        return wallet
+        return try await createWallet(label: label, network: network, mnemonic: mnemonic, pin: pin, isImport: true)
     }
🧹 Nitpick comments (1)
packages/swift-sdk/Sources/SwiftDashSDK/SPV/SPVClient.swift (1)

350-350: Document the mempool strategy change.

The mempool strategy was changed from BloomFilter (rawValue: 1) to FetchAll (rawValue: 0). While this aligns with the PR objectives ("Use mempool fetch all"), the rationale and implications should be documented.

Add a comment explaining the change:

         // Enable mempool tracking and ensure detailed events are available
         dash_spv_ffi_config_set_mempool_tracking(configPtr, true)
-        dash_spv_ffi_config_set_mempool_strategy(configPtr, FFIMempoolStrategy(rawValue: 0)) // FetchAll
+        // Use FetchAll strategy to retrieve all mempool transactions (vs BloomFilter which only fetches matching transactions)
+        // This ensures we don't miss any relevant mempool activity across multiple wallets
+        dash_spv_ffi_config_set_mempool_strategy(configPtr, FFIMempoolStrategy(rawValue: 0)) // FetchAll
         _ = dash_spv_ffi_config_set_fetch_mempool_transactions(configPtr, true)
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 43f6b94 and da14db1.

📒 Files selected for processing (3)
  • packages/swift-sdk/Sources/SwiftDashSDK/SPV/SPVClient.swift (1 hunks)
  • packages/swift-sdk/SwiftExampleApp/SwiftExampleApp/Core/Services/WalletService.swift (1 hunks)
  • packages/swift-sdk/SwiftExampleApp/SwiftExampleApp/Core/Wallet/WalletManager.swift (3 hunks)
🧰 Additional context used
📓 Path-based instructions (3)
packages/swift-sdk/**/*.swift

📄 CodeRabbit inference engine (CLAUDE.md)

Make DPP types public in Swift where needed for visibility

Files:

  • packages/swift-sdk/Sources/SwiftDashSDK/SPV/SPVClient.swift
  • packages/swift-sdk/SwiftExampleApp/SwiftExampleApp/Core/Wallet/WalletManager.swift
  • packages/swift-sdk/SwiftExampleApp/SwiftExampleApp/Core/Services/WalletService.swift
packages/swift-sdk/**

📄 CodeRabbit inference engine (AGENTS.md)

Keep the Swift app and SDK code in packages/swift-sdk

Files:

  • packages/swift-sdk/Sources/SwiftDashSDK/SPV/SPVClient.swift
  • packages/swift-sdk/SwiftExampleApp/SwiftExampleApp/Core/Wallet/WalletManager.swift
  • packages/swift-sdk/SwiftExampleApp/SwiftExampleApp/Core/Services/WalletService.swift
packages/swift-sdk/SwiftExampleApp/**/*.swift

📄 CodeRabbit inference engine (packages/swift-sdk/SwiftExampleApp/CLAUDE.md)

packages/swift-sdk/SwiftExampleApp/**/*.swift: Use Core SDK functions with the dash_core_sdk_* prefix
Use Platform SDK functions with the dash_sdk_* prefix
Use Unified SDK functions with the dash_unified_sdk_* prefix
Prefer using PersistentToken predicate helpers (e.g., mintableTokensPredicate, tokensWithControlRulePredicate) instead of manual filtering

Files:

  • packages/swift-sdk/SwiftExampleApp/SwiftExampleApp/Core/Wallet/WalletManager.swift
  • packages/swift-sdk/SwiftExampleApp/SwiftExampleApp/Core/Services/WalletService.swift
🧠 Learnings (1)
📚 Learning: 2025-09-07T22:19:59.217Z
Learnt from: CR
PR: dashpay/platform#0
File: packages/swift-sdk/SwiftExampleApp/CLAUDE.md:0-0
Timestamp: 2025-09-07T22:19:59.217Z
Learning: Applies to packages/swift-sdk/SwiftExampleApp/**/{PersistentPublicKey,PersistentIdentity}*.swift : Link private keys to PersistentPublicKey, not to PersistentIdentity

Applied to files:

  • packages/swift-sdk/SwiftExampleApp/SwiftExampleApp/Core/Wallet/WalletManager.swift
🧬 Code graph analysis (1)
packages/swift-sdk/SwiftExampleApp/SwiftExampleApp/Core/Wallet/WalletManager.swift (3)
packages/swift-sdk/SwiftExampleApp/SwiftExampleApp/Core/Services/WalletService.swift (2)
  • createWallet (289-363)
  • error (78-80)
packages/swift-sdk/Sources/SwiftDashSDK/KeyWallet/WalletManager.swift (2)
  • addWalletAndSerialize (603-674)
  • addWalletAndSerialize (686-757)
packages/swift-sdk/Sources/SwiftDashSDK/SPV/SPVClient.swift (1)
  • latestCheckpointHeight (975-991)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (4)
  • GitHub Check: Build Docker images (RS-DAPI, rs-dapi, rs-dapi) / Build RS-DAPI image
  • GitHub Check: Build JS packages / Build JS
  • GitHub Check: Rust crates security audit
  • GitHub Check: Swift SDK and Example build (warnings as errors)
🔇 Additional comments (2)
packages/swift-sdk/SwiftExampleApp/SwiftExampleApp/Core/Wallet/WalletManager.swift (2)

92-105: LGTM! Clear birthHeight logic for imported vs. new wallets.

The birthHeight calculation correctly distinguishes between imported wallets (which need to sync from a historical point) and new wallets (which can use the latest checkpoint). The use of 1 instead of 0 for non-mainnet imported wallets is well-documented to avoid FFI misinterpretation.


164-191: LGTM! Proper per-network sync baseline initialization.

The per-network sync-from heights are correctly set based on wallet type:

  • Imported wallets use fixed historical baselines
  • New wallets query the latest checkpoint for each enabled network
  • Graceful handling of nil checkpoint values with optional binding

@github-actions
Copy link

✅ DashSDKFFI.xcframework built for this PR.

SwiftPM (host the zip at a stable URL, then use):

.binaryTarget(
  name: "DashSDKFFI",
  url: "https://your.cdn.example/DashSDKFFI.xcframework.zip",
  checksum: "1c58d8634be55469c2b3fe1753e2525cceaf7c1099c3ef07221c1f728ded9c75"
)

Xcode manual integration:

  • Download 'DashSDKFFI.xcframework' artifact from the run link above.
  • Drag it into your app target (Frameworks, Libraries & Embedded Content) and set Embed & Sign.
  • If using the Swift wrapper package, point its binaryTarget to the xcframework location or add the package and place the xcframework at the expected path.

@QuantumExplorer QuantumExplorer merged commit c5e70aa into v2.2-dev Oct 30, 2025
19 checks passed
@QuantumExplorer QuantumExplorer deleted the fix/ios-wallet-fixes branch October 30, 2025 19:05
@thephez thephez added this to the v2.2.0 milestone Dec 22, 2025
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.

4 participants