Skip to content

fix: use header file to define platform-wallet-ffi public ABI and force swift-sdk to use it#3553

Merged
QuantumExplorer merged 1 commit into
v3.1-devfrom
fix/ffi-config
Apr 28, 2026
Merged

fix: use header file to define platform-wallet-ffi public ABI and force swift-sdk to use it#3553
QuantumExplorer merged 1 commit into
v3.1-devfrom
fix/ffi-config

Conversation

@ZocoLini
Copy link
Copy Markdown
Collaborator

@ZocoLini ZocoLini commented Apr 27, 2026

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

    • Added automatic C header generation for platform wallet FFI during build process.
  • Bug Fixes

    • Standardized FFI result code handling across Swift SDK for consistent error reporting.
    • Fixed empty string detection in token operations.
  • Refactor

    • Consolidated FFI declarations and eliminated duplication between Rust and Swift.
    • Updated length/count parameters to use unsigned integers for improved type safety.
    • Simplified struct initialization patterns in Swift integration layer.

@github-actions github-actions Bot added this to the v3.1.0 milestone Apr 27, 2026
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Apr 27, 2026

Warning

Rate limit exceeded

@ZocoLini has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 15 minutes and 57 seconds before requesting another review.

To keep reviews running without waiting, you can enable usage-based add-on for your organization. This allows additional reviews beyond the hourly cap. Account admins can enable it under billing.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 94e184c0-e25a-49a9-b97b-3bee451b932f

📥 Commits

Reviewing files that changed from the base of the PR and between 908e4c1 and 6b28e6b.

⛔ Files ignored due to path filters (1)
  • Cargo.lock is excluded by !**/*.lock
📒 Files selected for processing (49)
  • packages/rs-platform-wallet-ffi/Cargo.toml
  • packages/rs-platform-wallet-ffi/build.rs
  • packages/rs-platform-wallet-ffi/cbindgen.toml
  • packages/rs-platform-wallet-ffi/platform_wallet_ffi.h
  • packages/rs-platform-wallet-ffi/src/core_address_types.rs
  • packages/rs-platform-wallet-ffi/src/manager.rs
  • packages/rs-platform-wallet-ffi/src/persistence.rs
  • packages/rs-platform-wallet-ffi/src/tokens/burn.rs
  • packages/rs-platform-wallet-ffi/src/tokens/claim.rs
  • packages/rs-platform-wallet-ffi/src/tokens/destroy_frozen_funds.rs
  • packages/rs-platform-wallet-ffi/src/tokens/freeze.rs
  • packages/rs-platform-wallet-ffi/src/tokens/group_queries.rs
  • packages/rs-platform-wallet-ffi/src/tokens/mint.rs
  • packages/rs-platform-wallet-ffi/src/tokens/pause.rs
  • packages/rs-platform-wallet-ffi/src/tokens/resume.rs
  • packages/rs-platform-wallet-ffi/src/tokens/set_price.rs
  • packages/rs-platform-wallet-ffi/src/tokens/transfer.rs
  • packages/rs-platform-wallet-ffi/src/tokens/unfreeze.rs
  • packages/rs-platform-wallet-ffi/src/tokens/update_config.rs
  • packages/rs-platform-wallet-ffi/src/wallet_restore_types.rs
  • packages/rs-platform-wallet/src/wallet/tokens/group_queries.rs
  • packages/swift-sdk/Sources/SwiftDashSDK/FFI/KeychainSigner.swift
  • packages/swift-sdk/Sources/SwiftDashSDK/FFI/MnemonicResolverAndPersister.swift
  • packages/swift-sdk/Sources/SwiftDashSDK/PlatformWallet/AssetLock/AssetLockFFI.swift
  • packages/swift-sdk/Sources/SwiftDashSDK/PlatformWallet/AssetLock/ManagedAssetLockManager.swift
  • packages/swift-sdk/Sources/SwiftDashSDK/PlatformWallet/ContactRequest.swift
  • packages/swift-sdk/Sources/SwiftDashSDK/PlatformWallet/ContestVoteState.swift
  • packages/swift-sdk/Sources/SwiftDashSDK/PlatformWallet/CoreWallet/CoreWalletFFI.swift
  • packages/swift-sdk/Sources/SwiftDashSDK/PlatformWallet/CoreWallet/ManagedCoreWallet.swift
  • packages/swift-sdk/Sources/SwiftDashSDK/PlatformWallet/CoreWalletChangeSetFFI.swift
  • packages/swift-sdk/Sources/SwiftDashSDK/PlatformWallet/EstablishedContact.swift
  • packages/swift-sdk/Sources/SwiftDashSDK/PlatformWallet/IdentityManager.swift
  • packages/swift-sdk/Sources/SwiftDashSDK/PlatformWallet/IdentityRegistrationFFI.swift
  • packages/swift-sdk/Sources/SwiftDashSDK/PlatformWallet/ManagedIdentity.swift
  • packages/swift-sdk/Sources/SwiftDashSDK/PlatformWallet/ManagedPlatformAddressWallet.swift
  • packages/swift-sdk/Sources/SwiftDashSDK/PlatformWallet/ManagedPlatformWallet.swift
  • packages/swift-sdk/Sources/SwiftDashSDK/PlatformWallet/PlatformWallet.swift
  • packages/swift-sdk/Sources/SwiftDashSDK/PlatformWallet/PlatformWalletFFI.swift
  • packages/swift-sdk/Sources/SwiftDashSDK/PlatformWallet/PlatformWalletManager.swift
  • packages/swift-sdk/Sources/SwiftDashSDK/PlatformWallet/PlatformWalletManagerAddressSync.swift
  • packages/swift-sdk/Sources/SwiftDashSDK/PlatformWallet/PlatformWalletManagerFFI.swift
  • packages/swift-sdk/Sources/SwiftDashSDK/PlatformWallet/PlatformWalletManagerSPV.swift
  • packages/swift-sdk/Sources/SwiftDashSDK/PlatformWallet/PlatformWalletPersistenceHandler.swift
  • packages/swift-sdk/Sources/SwiftDashSDK/PlatformWallet/PlatformWalletTypes.swift
  • packages/swift-sdk/Sources/SwiftDashSDK/PlatformWallet/Tokens/TokenActions.swift
  • packages/swift-sdk/Sources/SwiftDashSDK/PlatformWallet/Tokens/TokenGroupActionQueries.swift
  • packages/swift-sdk/Sources/SwiftDashSDK/Security/KeychainManager.swift
  • packages/swift-sdk/SwiftExampleApp/SwiftExampleApp/Views/TransitionDetailView.swift
  • packages/swift-sdk/build_ios.sh
📝 Walkthrough

Walkthrough

This PR transitions the Rust platform wallet FFI from manually maintained C headers to automatically generated ones via cbindgen. It adds build-system infrastructure, removes hand-written headers, simplifies configuration, and updates all Swift FFI consumers to use result code constants and unsigned integer types consistently.

Changes

Cohort / File(s) Summary
Build System & Header Generation
packages/rs-platform-wallet-ffi/Cargo.toml, packages/rs-platform-wallet-ffi/build.rs, packages/rs-platform-wallet-ffi/cbindgen.toml
Added cbindgen v0.27 as build dependency; created build.rs to generate platform_wallet_ffi.h during build at target/<PROFILE>/include/<crate_name>/; simplified cbindgen.toml by removing namespace, export rules, struct/enum customizations while retaining function layout and enum naming settings.
Removed Hand-Written Header
packages/rs-platform-wallet-ffi/platform_wallet_ffi.h
Deleted complete 670-line C header including all FFI struct/enum/function declarations; header generation now handled by cbindgen.
Rust FFI Type Adjustments
packages/rs-platform-wallet-ffi/src/core_address_types.rs, packages/rs-platform-wallet-ffi/src/manager.rs, packages/rs-platform-wallet-ffi/src/wallet_restore_types.rs
Removed exported callback type aliases (PersistAccountAddressesFn, LoadWalletListFn, PersistAccountFn, PersistWalletMetadataFn); changed manager SDK pointer from *const Sdk to *const c_void with unsafe cast at call site.
Persistence Callbacks Consolidation
packages/rs-platform-wallet-ffi/src/persistence.rs
Inlined callback function pointer types directly into PersistenceCallbacks struct fields with expanded documentation; replaced type aliases with explicit unsafe extern "C" signatures.
Token Operation Normalization
packages/rs-platform-wallet-ffi/src/tokens/burn.rs, claim.rs, destroy_frozen_funds.rs, freeze.rs, mint.rs, pause.rs, resume.rs, set_price.rs, transfer.rs, unfreeze.rs, update_config.rs
Standardized empty public_note handling: changed from Ok(s) if s.is_empty() guard to explicit Ok("") match across all token functions.
Token Documentation
packages/rs-platform-wallet-ffi/src/tokens/group_queries.rs
Enhanced pending_group_actions JSON documentation with per-variant payload descriptions and concrete mint example.
Rust SDK Integration
packages/rs-platform-wallet/src/wallet/tokens/group_queries.rs
Updated fetch calls to pass &self.sdk directly instead of &*self.sdk.
Swift FFI Consolidation
packages/swift-sdk/Sources/SwiftDashSDK/FFI/KeychainSigner.swift, MnemonicResolverAndPersister.swift
Changed KeychainSigner.handle type from OpaquePointer to UnsafeMutablePointer<SignerHandle>; updated mnemonic/persist trampolines to use unsigned integer types (UInt) with appropriate casts.
Swift FFI File Removals
packages/swift-sdk/Sources/SwiftDashSDK/PlatformWallet/AssetLockFFI.swift, CoreWalletFFI.swift, IdentityRegistrationFFI.swift, PlatformWalletManagerFFI.swift, CoreWalletChangeSetFFI.swift
Deleted five FFI surface definition files; their declarations now imported from DashSDKFFI module.
Swift Result Code Standardization
packages/swift-sdk/Sources/SwiftDashSDK/PlatformWallet/EstablishedContact.swift, ContactRequest.swift, IdentityManager.swift, ManagedAssetLockManager.swift, ManagedCoreWallet.swift, ManagedIdentity.swift, ManagedPlatformAddressWallet.swift, ManagedPlatformWallet.swift, PlatformWallet.swift, PlatformWalletManager.swift, PlatformWalletManagerAddressSync.swift, PlatformWalletManagerSPV.swift, PlatformWalletTypes.swift, Tokens/TokenActions.swift, Tokens/TokenGroupActionQueries.swift
Replaced generic Success constant comparisons with explicit PLATFORM_WALLET_FFI_RESULT_SUCCESS and specific error codes (PLATFORM_WALLET_FFI_RESULT_ERROR_*) across all FFI calls; updated error throwing and nil-return logic.
Swift Unsigned Integer Alignment
packages/swift-sdk/Sources/SwiftDashSDK/PlatformWallet/ManagedPlatformWallet.swift, PlatformWalletPersistenceHandler.swift, ContestVoteState.swift, PlatformWalletManager.swift
Updated FFI count/length parameters to use UInt at call sites with explicit Int(...) casts for Swift collection operations; adjusted buffer pointer type handling to use typed pointers instead of raw pointers.
Swift FFI Module Consolidation
packages/swift-sdk/Sources/SwiftDashSDK/PlatformWallet/PlatformWalletFFI.swift
Collapsed from 1576 to 33 lines: added import DashSDKFFI, introduced FFIByteTuple32/20 type aliases and MnemonicResolverResult enum, removed all inline FFI struct/function declarations.
Swift Type Simplifications
packages/swift-sdk/Sources/SwiftDashSDK/PlatformWallet/PlatformWalletTypes.swift
Removed BlockTime public struct and related FFI conversion logic; updated identifier array decoding to use explicit pointer rebinding and type casts.
Swift Pointer Casting
packages/swift-sdk/Sources/SwiftDashSDK/PlatformWallet/PlatformWalletManagerAddressSync.swift, TransitionDetailView.swift
Changed callback/signer pointers to use typed UnsafePointer<...> where appropriate; wrapped KeychainSigner.handle with OpaquePointer(...) at call sites.
Build Configuration
packages/swift-sdk/build_ios.sh
Updated umbrella header generation to explicitly include platform-wallet-ffi header; removed dashcore header exclusion.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~65 minutes

Possibly related PRs

Suggested reviewers

  • shumkov
  • QuantumExplorer

Poem

🐰 A rabbit's ode to auto-generation magic,
No more headers by hand—no more tragic!
Cbindgen builds swift bridges with care,
Unsigned ints flow, FFI flows fair, 🎉
Pointers refined, the build system's delight!

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the main change: migrating platform-wallet-ffi to use a generated header file for the public ABI and updating swift-sdk to consume it.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/ffi-config

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.

@ZocoLini ZocoLini force-pushed the fix/ffi-config branch 5 times, most recently from 103b4ea to 908e4c1 Compare April 27, 2026 22:14
@ZocoLini ZocoLini marked this pull request as ready for review April 27, 2026 22:15
@thepastaclaw
Copy link
Copy Markdown
Collaborator

thepastaclaw commented Apr 27, 2026

🕓 Ready for review (commit 6b28e6b)

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Apr 27, 2026

✅ 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: "e2f647b212866f4ba9c58c7c1223b6de0cfda1c67065c732087ddd1928f48fd6"
)

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.

Copy link
Copy Markdown
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: 2

🧹 Nitpick comments (6)
packages/swift-sdk/Sources/SwiftDashSDK/PlatformWallet/PlatformWalletFFI.swift (1)

61-75: Consider scoping/renaming hashData and hashHex.

These are declared at module scope without an access modifier, so they are internal and visible across the entire SwiftDashSDK module under very generic names. hashData in particular is the kind of name that invites accidental shadowing or collisions when more hashing helpers get added later. Consider scoping them to a namespace (e.g., a FFITuple caseless enum) or extending Data / String so the call site reads Data(ffiTuple32:) / String(hexFFITuple32:).

♻️ Example: namespace under a caseless enum
-/// Convert a 32-byte FFI tuple into `Data` for SwiftData persistence.
-@inline(__always)
-func hashData(_ hash: FFIByteTuple32) -> Data {
-    Swift.withUnsafeBytes(of: hash) { Data($0) }
-}
-
-/// Hex-encode a 32-byte FFI tuple.
-@inline(__always)
-func hashHex(_ hash: FFIByteTuple32) -> String {
-    Swift.withUnsafeBytes(of: hash) { buf in
-        buf.map { String(format: "%02x", $0) }.joined()
-    }
-}
+enum FFITuple {
+    /// Convert a 32-byte FFI tuple into `Data` for SwiftData persistence.
+    `@inline`(__always)
+    static func data(_ hash: FFIByteTuple32) -> Data {
+        Swift.withUnsafeBytes(of: hash) { Data($0) }
+    }
+
+    /// Hex-encode a 32-byte FFI tuple.
+    `@inline`(__always)
+    static func hex(_ hash: FFIByteTuple32) -> String {
+        Swift.withUnsafeBytes(of: hash) { buf in
+            buf.map { String(format: "%02x", $0) }.joined()
+        }
+    }
+}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@packages/swift-sdk/Sources/SwiftDashSDK/PlatformWallet/PlatformWalletFFI.swift`
around lines 61 - 75, The helpers hashData(_:) and hashHex(_:) are module-scoped
with generic names that risk collisions; refactor by moving them into a narrow
namespace such as a caseless enum (e.g., FFITuple) or by adding typed
initializers/extensions (e.g., Data(ffiTuple32:) and String(hexFFITuple32:)) so
callers use FFITuple.hashData(_:), FFITuple.hashHex(_:), or the new
initializers; update uses of hashData and hashHex to the chosen scoped names and
keep the implementation using Swift.withUnsafeBytes(of: hash) with
FFIByteTuple32 unchanged.
packages/swift-sdk/Sources/SwiftDashSDK/PlatformWallet/PlatformWalletTypes.swift (1)

158-164: Pointer rebinding is correct — minor note on the precondition cast.

UnsafeRawPointer(array.items!) → assumingMemoryBound(to: UInt8.self) is the right way to flatten the imported (UInt8 × 32) tuple-pointer for row indexing.

One small note: Int(array.count) will trap if array.count (a usize/UInt) ever exceeds Int.max. In practice identity arrays are tiny so this is academic, but if you want to be paranoid, compare in the unsigned domain instead:

♻️ Optional unsigned-domain bounds check
-    precondition(index >= 0 && index < Int(array.count), "index out of range")
-    let raw = UnsafeRawPointer(array.items!)
+    precondition(index >= 0 && UInt(index) < array.count, "index out of range")
+    let raw = UnsafeRawPointer(array.items!)
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@packages/swift-sdk/Sources/SwiftDashSDK/PlatformWallet/PlatformWalletTypes.swift`
around lines 158 - 164, In identifierFromFFIArray, avoid casting array.count to
Int for the bounds check; instead keep the index non-negative and compare in the
unsigned domain by converting the non-negative index to UInt and comparing that
against array.count (i.e., replace the precondition that uses Int(array.count)
with one that checks index >= 0 and UInt(index) < array.count), leaving the
UnsafeRawPointer/assumingMemoryBound logic unchanged.
packages/swift-sdk/Sources/SwiftDashSDK/PlatformWallet/ManagedPlatformWallet.swift (1)

1693-1693: Minor inconsistency: explicit initializer vs. default initializer pattern used elsewhere.

The PR migrated FFI struct initializations to the default initializer form (e.g., line 1512 now uses ContactRequestHandleArray()). This call site still uses the explicit ContactRequestHandleArray(handles: nil, count: 0) form. Functionally equivalent, but worth aligning for consistency.

♻️ Proposed alignment
-            var array = ContactRequestHandleArray(handles: nil, count: 0)
+            var array = ContactRequestHandleArray()
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@packages/swift-sdk/Sources/SwiftDashSDK/PlatformWallet/ManagedPlatformWallet.swift`
at line 1693, Replace the explicit FFI struct initialization var array =
ContactRequestHandleArray(handles: nil, count: 0) with the default initializer
form used elsewhere (ContactRequestHandleArray()) in
ManagedPlatformWallet.swift; update the declaration of array to use
ContactRequestHandleArray() so it matches the other initializations (e.g., the
one near line 1512) for consistency.
packages/rs-platform-wallet-ffi/Cargo.toml (1)

50-52: Consider bumping cbindgen to 0.29 for recent improvements.

cbindgen = "0.27" works without issues, but the latest version is 0.29.2 with no breaking changes between versions. Since this is a build-dependency only, upgrading to 0.29 would provide bug fixes and feature additions from 0.28 and 0.29 with no compatibility risk.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/rs-platform-wallet-ffi/Cargo.toml` around lines 50 - 52, Update the
build-dependency entry for cbindgen in Cargo.toml from "0.27" to a 0.29.x
release (e.g., "0.29" or "0.29.2") to pick up recent fixes and features; locate
the [build-dependencies] section and change the cbindgen version string
accordingly (the unique symbol to edit is the cbindgen dependency entry).
packages/rs-platform-wallet-ffi/build.rs (2)

26-31: Builder error message could mislead.

.expect("Unable to generate bindings") swallows the underlying cbindgen::Error detail. When generation fails (e.g. a parse error in a transitively-included crate), the build log only prints "Unable to generate bindings", which makes diagnosis harder. Consider letting the error propagate via ? from a Result-returning helper or formatting the error explicitly.

♻️ Surface cbindgen errors
-    cbindgen::Builder::new()
-        .with_crate(&crate_dir)
-        .with_config(config)
-        .generate()
-        .expect("Unable to generate bindings")
-        .write_to_file(&output_path);
+    let bindings = cbindgen::Builder::new()
+        .with_crate(&crate_dir)
+        .with_config(config)
+        .generate()
+        .unwrap_or_else(|e| panic!("cbindgen failed for {}: {e}", crate_name));
+    bindings.write_to_file(&output_path);

As per coding guidelines, "Follow rustfmt defaults and keep code clippy-clean for Rust modules" — clippy may also suggest unwrap_or_else over expect with non-static context.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/rs-platform-wallet-ffi/build.rs` around lines 26 - 31, The cbindgen
generation call currently uses .generate().expect("Unable to generate bindings")
which hides the underlying cbindgen::Error; change the error handling in the
Builder chain (the cbindgen::Builder::new()... .generate() call) to propagate or
surface the original error (e.g. return a Result and use ? on generate(), or
replace expect with unwrap_or_else / map_err that formats and includes the
cbindgen::Error) so the build log prints the actual error details from
generate() instead of the static "Unable to generate bindings" message.

12-15: Fragile reliance on Cargo's internal OUT_DIR layout.

Path::ancestors().nth(3) assumes the exact target/<profile>/build/<crate>-<hash>/out shape. Cargo doesn't formally guarantee this layout, and it differs subtly under --target <triple> builds (where it becomes target/<triple>/<profile>/... — still 3 levels up, so this happens to work today). Consider adding a defensive check that target_dir ends with the expected profile component before writing into it, or surface the OUT_DIR value in the panic message so build failures are diagnosable.

♻️ Better diagnostics on failure
-    let target_dir = Path::new(&out_dir)
-        .ancestors()
-        .nth(3) // This line moves up to the target/<PROFILE> directory
-        .expect("Failed to find target dir");
+    let target_dir = Path::new(&out_dir)
+        .ancestors()
+        .nth(3) // target/<PROFILE> (or target/<triple>/<PROFILE> for cross-target)
+        .unwrap_or_else(|| panic!("Could not derive target dir from OUT_DIR={}", out_dir));
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/rs-platform-wallet-ffi/build.rs` around lines 12 - 15, The current
computation of target_dir using Path::ancestors().nth(3) is fragile; update the
logic around out_dir and target_dir (the Path::ancestors().nth(3) call and the
expect message) to verify the discovered directory actually ends with the
expected profile component (e.g. "debug" or "release") before proceeding, and
improve the panic/expect message to include the original OUT_DIR value and the
computed path for easier diagnostics; specifically, in the build.rs code that
defines target_dir and uses out_dir, add a defensive check on
target_dir.file_name() (or equivalent) against the PROFILE env var and change
the expect message to print both OUT_DIR and the computed target_dir when the
check fails.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@packages/rs-platform-wallet-ffi/src/persistence.rs`:
- Around line 163-179: The docstrings for the FFI callback fields
(on_persist_account_addresses_fn, on_persist_account_fn,
on_persist_wallet_metadata_fn) currently claim that non-zero return codes are
merely advisory and Rust will "log and continue", but the implementation (see
store_account_addresses and similar code paths) actually treats a non-zero rc as
an Err and aborts the persistence round; update the docstrings to reflect the
real behavior: state that callers must return 0 on success, any non-zero return
will be propagated as a PersistenceError and will abort the operation (contrast
to on_changeset_begin_fn / on_persist_address_balances_fn which are
log-and-continue), and mention that the C/Swift header generated by cbindgen
will expose this contract so clients must handle errors accordingly.

In
`@packages/swift-sdk/Sources/SwiftDashSDK/PlatformWallet/AssetLock/ManagedAssetLockManager.swift`:
- Around line 130-132: The current combined guard in ManagedAssetLockManager
(the one checking result, txBytesPtr and txLen) can produce a misleading
PlatformWalletError when result == PLATFORM_WALLET_FFI_RESULT_SUCCESS but the
returned buffer is nil/empty; split the check: first validate the FFI result
(throw PlatformWalletError(result:error:) only when the result indicates an
actual FFI error), then separately validate txBytesPtr and txLen and throw a
distinct, descriptive PlatformWalletError (e.g., "empty or nil transaction
buffer returned from FFI") when the buffer is missing or zero-length; apply the
same split-guard pattern to the createFundedProof and resume call sites so
SUCCESS-with-empty-buffer surfaces a clear error instead of falling through to
the generic result-based error.

---

Nitpick comments:
In `@packages/rs-platform-wallet-ffi/build.rs`:
- Around line 26-31: The cbindgen generation call currently uses
.generate().expect("Unable to generate bindings") which hides the underlying
cbindgen::Error; change the error handling in the Builder chain (the
cbindgen::Builder::new()... .generate() call) to propagate or surface the
original error (e.g. return a Result and use ? on generate(), or replace expect
with unwrap_or_else / map_err that formats and includes the cbindgen::Error) so
the build log prints the actual error details from generate() instead of the
static "Unable to generate bindings" message.
- Around line 12-15: The current computation of target_dir using
Path::ancestors().nth(3) is fragile; update the logic around out_dir and
target_dir (the Path::ancestors().nth(3) call and the expect message) to verify
the discovered directory actually ends with the expected profile component (e.g.
"debug" or "release") before proceeding, and improve the panic/expect message to
include the original OUT_DIR value and the computed path for easier diagnostics;
specifically, in the build.rs code that defines target_dir and uses out_dir, add
a defensive check on target_dir.file_name() (or equivalent) against the PROFILE
env var and change the expect message to print both OUT_DIR and the computed
target_dir when the check fails.

In `@packages/rs-platform-wallet-ffi/Cargo.toml`:
- Around line 50-52: Update the build-dependency entry for cbindgen in
Cargo.toml from "0.27" to a 0.29.x release (e.g., "0.29" or "0.29.2") to pick up
recent fixes and features; locate the [build-dependencies] section and change
the cbindgen version string accordingly (the unique symbol to edit is the
cbindgen dependency entry).

In
`@packages/swift-sdk/Sources/SwiftDashSDK/PlatformWallet/ManagedPlatformWallet.swift`:
- Line 1693: Replace the explicit FFI struct initialization var array =
ContactRequestHandleArray(handles: nil, count: 0) with the default initializer
form used elsewhere (ContactRequestHandleArray()) in
ManagedPlatformWallet.swift; update the declaration of array to use
ContactRequestHandleArray() so it matches the other initializations (e.g., the
one near line 1512) for consistency.

In
`@packages/swift-sdk/Sources/SwiftDashSDK/PlatformWallet/PlatformWalletFFI.swift`:
- Around line 61-75: The helpers hashData(_:) and hashHex(_:) are module-scoped
with generic names that risk collisions; refactor by moving them into a narrow
namespace such as a caseless enum (e.g., FFITuple) or by adding typed
initializers/extensions (e.g., Data(ffiTuple32:) and String(hexFFITuple32:)) so
callers use FFITuple.hashData(_:), FFITuple.hashHex(_:), or the new
initializers; update uses of hashData and hashHex to the chosen scoped names and
keep the implementation using Swift.withUnsafeBytes(of: hash) with
FFIByteTuple32 unchanged.

In
`@packages/swift-sdk/Sources/SwiftDashSDK/PlatformWallet/PlatformWalletTypes.swift`:
- Around line 158-164: In identifierFromFFIArray, avoid casting array.count to
Int for the bounds check; instead keep the index non-negative and compare in the
unsigned domain by converting the non-negative index to UInt and comparing that
against array.count (i.e., replace the precondition that uses Int(array.count)
with one that checks index >= 0 and UInt(index) < array.count), leaving the
UnsafeRawPointer/assumingMemoryBound logic unchanged.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 25ec70e4-05ff-4645-be87-0092a21988f1

📥 Commits

Reviewing files that changed from the base of the PR and between 897cb3b and 908e4c1.

⛔ Files ignored due to path filters (1)
  • Cargo.lock is excluded by !**/*.lock
📒 Files selected for processing (49)
  • packages/rs-platform-wallet-ffi/Cargo.toml
  • packages/rs-platform-wallet-ffi/build.rs
  • packages/rs-platform-wallet-ffi/cbindgen.toml
  • packages/rs-platform-wallet-ffi/platform_wallet_ffi.h
  • packages/rs-platform-wallet-ffi/src/core_address_types.rs
  • packages/rs-platform-wallet-ffi/src/manager.rs
  • packages/rs-platform-wallet-ffi/src/persistence.rs
  • packages/rs-platform-wallet-ffi/src/tokens/burn.rs
  • packages/rs-platform-wallet-ffi/src/tokens/claim.rs
  • packages/rs-platform-wallet-ffi/src/tokens/destroy_frozen_funds.rs
  • packages/rs-platform-wallet-ffi/src/tokens/freeze.rs
  • packages/rs-platform-wallet-ffi/src/tokens/group_queries.rs
  • packages/rs-platform-wallet-ffi/src/tokens/mint.rs
  • packages/rs-platform-wallet-ffi/src/tokens/pause.rs
  • packages/rs-platform-wallet-ffi/src/tokens/resume.rs
  • packages/rs-platform-wallet-ffi/src/tokens/set_price.rs
  • packages/rs-platform-wallet-ffi/src/tokens/transfer.rs
  • packages/rs-platform-wallet-ffi/src/tokens/unfreeze.rs
  • packages/rs-platform-wallet-ffi/src/tokens/update_config.rs
  • packages/rs-platform-wallet-ffi/src/wallet_restore_types.rs
  • packages/rs-platform-wallet/src/wallet/tokens/group_queries.rs
  • packages/swift-sdk/Sources/SwiftDashSDK/FFI/KeychainSigner.swift
  • packages/swift-sdk/Sources/SwiftDashSDK/FFI/MnemonicResolverAndPersister.swift
  • packages/swift-sdk/Sources/SwiftDashSDK/PlatformWallet/AssetLock/AssetLockFFI.swift
  • packages/swift-sdk/Sources/SwiftDashSDK/PlatformWallet/AssetLock/ManagedAssetLockManager.swift
  • packages/swift-sdk/Sources/SwiftDashSDK/PlatformWallet/ContactRequest.swift
  • packages/swift-sdk/Sources/SwiftDashSDK/PlatformWallet/ContestVoteState.swift
  • packages/swift-sdk/Sources/SwiftDashSDK/PlatformWallet/CoreWallet/CoreWalletFFI.swift
  • packages/swift-sdk/Sources/SwiftDashSDK/PlatformWallet/CoreWallet/ManagedCoreWallet.swift
  • packages/swift-sdk/Sources/SwiftDashSDK/PlatformWallet/CoreWalletChangeSetFFI.swift
  • packages/swift-sdk/Sources/SwiftDashSDK/PlatformWallet/EstablishedContact.swift
  • packages/swift-sdk/Sources/SwiftDashSDK/PlatformWallet/IdentityManager.swift
  • packages/swift-sdk/Sources/SwiftDashSDK/PlatformWallet/IdentityRegistrationFFI.swift
  • packages/swift-sdk/Sources/SwiftDashSDK/PlatformWallet/ManagedIdentity.swift
  • packages/swift-sdk/Sources/SwiftDashSDK/PlatformWallet/ManagedPlatformAddressWallet.swift
  • packages/swift-sdk/Sources/SwiftDashSDK/PlatformWallet/ManagedPlatformWallet.swift
  • packages/swift-sdk/Sources/SwiftDashSDK/PlatformWallet/PlatformWallet.swift
  • packages/swift-sdk/Sources/SwiftDashSDK/PlatformWallet/PlatformWalletFFI.swift
  • packages/swift-sdk/Sources/SwiftDashSDK/PlatformWallet/PlatformWalletManager.swift
  • packages/swift-sdk/Sources/SwiftDashSDK/PlatformWallet/PlatformWalletManagerAddressSync.swift
  • packages/swift-sdk/Sources/SwiftDashSDK/PlatformWallet/PlatformWalletManagerFFI.swift
  • packages/swift-sdk/Sources/SwiftDashSDK/PlatformWallet/PlatformWalletManagerSPV.swift
  • packages/swift-sdk/Sources/SwiftDashSDK/PlatformWallet/PlatformWalletPersistenceHandler.swift
  • packages/swift-sdk/Sources/SwiftDashSDK/PlatformWallet/PlatformWalletTypes.swift
  • packages/swift-sdk/Sources/SwiftDashSDK/PlatformWallet/Tokens/TokenActions.swift
  • packages/swift-sdk/Sources/SwiftDashSDK/PlatformWallet/Tokens/TokenGroupActionQueries.swift
  • packages/swift-sdk/Sources/SwiftDashSDK/Security/KeychainManager.swift
  • packages/swift-sdk/SwiftExampleApp/SwiftExampleApp/Views/TransitionDetailView.swift
  • packages/swift-sdk/build_ios.sh
💤 Files with no reviewable changes (7)
  • packages/swift-sdk/Sources/SwiftDashSDK/PlatformWallet/CoreWalletChangeSetFFI.swift
  • packages/swift-sdk/Sources/SwiftDashSDK/PlatformWallet/IdentityRegistrationFFI.swift
  • packages/swift-sdk/Sources/SwiftDashSDK/PlatformWallet/PlatformWalletManagerFFI.swift
  • packages/swift-sdk/Sources/SwiftDashSDK/PlatformWallet/AssetLock/AssetLockFFI.swift
  • packages/rs-platform-wallet-ffi/platform_wallet_ffi.h
  • packages/swift-sdk/Sources/SwiftDashSDK/PlatformWallet/CoreWallet/CoreWalletFFI.swift
  • packages/rs-platform-wallet-ffi/cbindgen.toml

Comment thread packages/rs-platform-wallet-ffi/src/persistence.rs
@QuantumExplorer QuantumExplorer merged commit 33fde4e into v3.1-dev Apr 28, 2026
34 checks passed
@QuantumExplorer QuantumExplorer deleted the fix/ffi-config branch April 28, 2026 04:06
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.

3 participants