Skip to content

feat(swift-sdk): expose rich transaction fields in WalletTransaction#3481

Draft
llbartekll wants to merge 2 commits intov3.1-devfrom
feat/swift-sdk-rich-tx-fields
Draft

feat(swift-sdk): expose rich transaction fields in WalletTransaction#3481
llbartekll wants to merge 2 commits intov3.1-devfrom
feat/swift-sdk-rich-tx-fields

Conversation

@llbartekll
Copy link
Copy Markdown
Contributor

@llbartekll llbartekll commented Apr 13, 2026

Summary

  • Add TxIO struct (address, amount, isMine) for transaction input/output records
  • Extend WalletTransaction with inputs, outputs, txType, direction, instantSendLocked fields (all with defaults for backward compatibility)
  • Update getTransactions() mapping to populate from FFITransactionRecord's input_details, output_details, transaction_type, direction, and context.islock_data

Motivation

dashwallet-ios function - (transaction list migration from DashSync to SwiftDashSDK) needs these fields to display full transaction details. The FFI already delivers this data via FFITransactionRecord — the Swift SDK was just dropping it on the floor.

Dependencies

Test plan

  • Both dashwallet targets build clean (dashwallet + dashpay)
  • Tap transaction in dashwallet → detail screen shows input addresses, direction, tx type
  • After rust-dashcore#640 merges + xcframework rebuild → output addresses also appear

🤖 Generated with Claude Code

Summary by CodeRabbit

Release Notes

  • New Features
    • Transactions now display detailed input and output information, including wallet addresses and amounts.
    • Added transaction direction, type, and Instant Send lock status visibility.
    • Wallet can now identify which transaction inputs and outputs belong to your account.

llbartekll and others added 2 commits April 13, 2026 09:43
The FFI's FFITransactionRecord already delivers input details, output
details, transaction type, direction, and InstantSend lock status —
but WalletTransaction was dropping them on the floor. This commit maps
the remaining fields so downstream consumers (dashwallet-ios) can
display full transaction details.

- Add TxIO struct (address, amount, isMine) for input/output records
- Extend WalletTransaction with inputs, outputs, txType, direction,
  instantSendLocked (all with defaults for backward compatibility)
- Update getTransactions() mapping to read from ffiTx.input_details,
  ffiTx.output_details, ffiTx.transaction_type, ffiTx.direction,
  ffiTx.context.islock_data

Note: FFIOutputDetail only has { index, role } — no address or amount.
Output addresses are not available from the FFI yet. Input addresses
are fully populated from FFIInputDetail.

Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>
FFIOutputDetail now includes address and value fields (added in
rust-dashcore PR #640). Update the getTransactions() mapping to
read them into TxIO, enabling dashwallet-ios to display "Received at"
and "Sent to" addresses in the transaction detail screen.

Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>
@github-actions github-actions bot added this to the v3.1.0 milestone Apr 13, 2026
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Apr 13, 2026

📝 Walkthrough

Walkthrough

This pull request extends the WalletTransaction struct with detailed transaction input and output information by introducing a new TxIO struct and populating transaction inputs/outputs from decoded FFI data, along with additional transaction properties including type, direction, and instant send lock status.

Changes

Cohort / File(s) Summary
Transaction IO Structure
packages/swift-sdk/Sources/SwiftDashSDK/KeyWallet/ManagedAccount.swift
Added new public TxIO struct to represent transaction inputs/outputs with address, amount, and ownership flag. Extended WalletTransaction with inputs, outputs, txType, direction, and instantSendLocked properties, updated initializer with corresponding parameters (with defaults), and modified getTransactions() to decode FFI transaction details into TxIO records.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~12 minutes

Poem

🐰 With inputs and outputs so fine,
Each transaction now shows what is mine,
TxIO records dance in the light,
Making wallet details just right!

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately describes the main change: exposing new rich transaction fields (inputs, outputs, txType, direction, instantSendLocked) in the WalletTransaction struct, which is the primary purpose of this PR.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

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

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/swift-sdk-rich-tx-fields

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.

@thepastaclaw
Copy link
Copy Markdown
Collaborator

thepastaclaw commented Apr 13, 2026

Review Gate

Commit: 6015040b

  • Debounce: 1438m ago (need 30m)

  • CI checks: build failure: Swift SDK build / Swift SDK and Example build (warnings as errors)

  • CodeRabbit review: comment found

  • Off-peak hours: off-peak (12:42 AM PT Tuesday)

  • Run review now (check to override)

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: 1

🤖 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/swift-sdk/Sources/SwiftDashSDK/KeyWallet/ManagedAccount.swift`:
- Around line 100-107: The input mapping currently hardcodes isMine: false in
ManagedAccount.swift when building inputs, causing misclassification; update the
loop that builds inputs (the section that iterates ffiTx.input_details and
appends TxIO) to inspect the FFIInputDetail.role field (analogous to the output
handling that checks detail.role == FFI_OUTPUT_ROLE_RECEIVED || detail.role ==
FFI_OUTPUT_ROLE_CHANGE) and set isMine = true when the role indicates the input
is wallet-owned, otherwise false; if FFIInputDetail does not expose a role
field, document that fact in a comment and request exposing ownership metadata
from the FFI so inputs can be classified properly.
🪄 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: bf28c4df-585c-42fe-8228-64c201125e2f

📥 Commits

Reviewing files that changed from the base of the PR and between c061bd4 and 6015040.

📒 Files selected for processing (1)
  • packages/swift-sdk/Sources/SwiftDashSDK/KeyWallet/ManagedAccount.swift

Comment on lines +100 to +107
// Convert input details
var inputs: [TxIO] = []
if ffiTx.input_details_count > 0, let inputsPtr = ffiTx.input_details {
for j in 0..<ffiTx.input_details_count {
let detail = inputsPtr.advanced(by: j).pointee
let address = detail.address != nil ? String(cString: detail.address) : ""
inputs.append(TxIO(address: address, amount: detail.value, isMine: false))
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

# 1) Locate FFI type declarations surfaced in repo sources/interfaces.
fd -i 'DashSDKFFI|ffi' .

# 2) Inspect symbols related to input details and ownership flags.
rg -n -C3 --iglob '*.h' --iglob '*.swiftinterface' --iglob '*.swift' \
  'FFIInputDetail|input_details|is_mine|isMine|role|address|value'

Repository: dashpay/platform

Length of output: 50374


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Read the ManagedAccount.swift file to see the context around lines 100-107
echo "=== ManagedAccount.swift lines 95-115 ==="
sed -n '95,115p' packages/swift-sdk/Sources/SwiftDashSDK/KeyWallet/ManagedAccount.swift

echo -e "\n=== Searching for FFIInputDetail definition ==="
# Search in FFI-related files for FFIInputDetail struct/type definition
rg -n 'struct FFIInputDetail|class FFIInputDetail|FFIInputDetail.*{' packages/swift-sdk/ --type swift --type c --type h -A 10 | head -100

echo -e "\n=== Searching for input_details and is_mine patterns ==="
# Look for is_mine or similar ownership fields in FFI bindings
rg -n 'is_mine|isMine' packages/swift-sdk/Sources/SwiftDashSDK/FFI/ --type swift --type h -B 2 -A 2

echo -e "\n=== Checking FFI header files for input detail structure ==="
# Search in header files for input detail field definitions
fd -e h packages/swift-sdk/Sources/SwiftDashSDK/FFI/ -exec grep -l "input_details" {} \;

Repository: dashpay/platform

Length of output: 1327


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Simpler search for FFIInputDetail
echo "=== Searching for FFIInputDetail definition ==="
rg 'FFIInputDetail' packages/swift-sdk/Sources/SwiftDashSDK/FFI/ --type swift --type h -B 2 -A 5

echo -e "\n=== Looking for input detail structure in header files ==="
find packages/swift-sdk -name "*.h" -type f | xargs grep -l "input_detail" 2>/dev/null || echo "No .h files with input_detail found"

echo -e "\n=== Searching for is_mine field in codebase ==="
rg 'is_mine|isMine' packages/swift-sdk/Sources/SwiftDashSDK/ --type swift -B 1 -A 1

echo -e "\n=== Looking at the full TxIO struct definition ==="
rg 'struct TxIO' packages/swift-sdk/Sources/SwiftDashSDK/ --type swift -A 10

echo -e "\n=== Check imports and FFI files ==="
ls -la packages/swift-sdk/Sources/SwiftDashSDK/FFI/

Repository: dashpay/platform

Length of output: 107


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "=== Searching entire repo for FFIInputDetail ==="
rg 'FFIInputDetail' . --type swift --type h --type rust 2>/dev/null | head -30

echo -e "\n=== Looking for input_detail in FFI packages ==="
rg 'input_detail' packages/rs-sdk-ffi/ packages/rs-platform-wallet-ffi/ --type rust --type h 2>/dev/null | head -30

echo -e "\n=== Check ManagedAccount.swift for TxIO and isMine usage ==="
rg 'struct TxIO|class TxIO|var isMine' packages/swift-sdk/Sources/SwiftDashSDK/ --type swift -A 5 -B 1

echo -e "\n=== Check if similar patterns with ownership exist elsewhere ==="
rg 'isMine.*false|isMine.*true' packages/swift-sdk/ --type swift

echo -e "\n=== Look for transaction parsing to understand data available ==="
grep -r 'input_details_count\|output_details_count' packages/swift-sdk/ --include="*.swift" 2>/dev/null | head -20

Repository: dashpay/platform

Length of output: 108


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "=== Read ManagedAccount.swift imports and beginning ==="
head -50 packages/swift-sdk/Sources/SwiftDashSDK/KeyWallet/ManagedAccount.swift

echo -e "\n=== Check for bridging header ==="
find packages/swift-sdk -name "*Bridging*" -o -name "*bridging*" 2>/dev/null | xargs cat 2>/dev/null

echo -e "\n=== Look at FFI module structure ==="
ls -la packages/swift-sdk/Sources/SwiftDashSDK/FFI/ 2>/dev/null || echo "FFI dir listing failed"

echo -e "\n=== Check if ffiTx is defined in module imports ==="
rg 'import.*FFI|typealias.*ffiTx' packages/swift-sdk/Sources/SwiftDashSDK/KeyWallet/ --type swift -B 2 -A 2

echo -e "\n=== Look for WalletTransaction struct to understand input handling ==="
rg 'struct WalletTransaction|func getTransactions' packages/swift-sdk/Sources/SwiftDashSDK/KeyWallet/ManagedAccount.swift -A 20 | head -60

Repository: dashpay/platform

Length of output: 11111


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "=== Check output detail handling for comparison ==="
sed -n '112,130p' packages/swift-sdk/Sources/SwiftDashSDK/KeyWallet/ManagedAccount.swift

echo -e "\n=== Search for output isMine patterns ==="
rg 'outputs.append.*isMine' packages/swift-sdk/Sources/SwiftDashSDK/ --type swift -B 2 -A 2

echo -e "\n=== Look for Package.swift or dependency declarations ==="
find packages/swift-sdk -name "Package.swift" -o -name "*.podspec" | xargs cat 2>/dev/null | grep -A 20 "DashSDKFFI\|dependency" | head -40

echo -e "\n=== Check git for when DashSDKFFI was introduced ==="
git log --oneline --all -S "DashSDKFFI" -- packages/swift-sdk 2>/dev/null | head -10

echo -e "\n=== Search for any is_mine field usage anywhere in codebase ==="
rg 'is_mine|\.isMine\s*=' packages/swift-sdk/Sources/SwiftDashSDK/ --type swift

Repository: dashpay/platform

Length of output: 3455


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "=== Search for FFI_OUTPUT_ROLE and similar input role constants ==="
rg 'FFI_OUTPUT_ROLE|FFI_INPUT_ROLE' packages/swift-sdk/ --type swift --type h

echo -e "\n=== Search for role field usage with input details ==="
rg 'input.*role|detail\.role' packages/swift-sdk/Sources/SwiftDashSDK/ --type swift -B 3 -A 3

echo -e "\n=== Look at the full getTransactions method around input/output handling ==="
sed -n '57,145p' packages/swift-sdk/Sources/SwiftDashSDK/KeyWallet/ManagedAccount.swift

Repository: dashpay/platform

Length of output: 4849


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "=== Check recent commits about input detail mapping ==="
git log --all --oneline --grep="input" -- packages/swift-sdk | head -15

echo -e "\n=== Check for any documentation about FFIInputDetail fields ==="
rg 'FFIInputDetail|input_detail.*struct' packages/ --type rust --type h -A 15 | head -80

echo -e "\n=== Look for rs-dashcore-ffi or FFI binding definitions ==="
find packages -name "*.rs" -path "*/ffi/*" | xargs grep -l "input_detail\|InputDetail" 2>/dev/null | head -5

echo -e "\n=== Check the Rust FFI crate for input/output detail definitions ==="
rg 'pub struct.*InputDetail|pub struct.*OutputDetail' packages/rs-sdk-ffi packages/rs-platform-wallet-ffi --type rust -A 10

Repository: dashpay/platform

Length of output: 180


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "=== List FFI framework contents ==="
find packages/swift-sdk -name "DashSDKFFI.xcframework" -o -name "*.modulemap" -o -name "module.modulemap" 2>/dev/null | head -10

echo -e "\n=== Check for input detail in rust bindings broadly ==="
find packages -type f -name "*.rs" | xargs grep -l "input.*detail\|struct.*Detail" 2>/dev/null | grep -E "(ffi|binding)" | head -10

echo -e "\n=== Search in rs-sdk-ffi directory ==="
find packages/rs-sdk-ffi -type f -name "*.rs" | head -20

echo -e "\n=== Look for input_detail in any rust file ==="
rg 'input.*detail|InputDetail' packages/ --type rust --max-count 20

echo -e "\n=== Check if there's C header with FFIInputDetail ==="
find packages -name "*.h" | xargs grep -l "input_detail\|InputDetail" 2>/dev/null

Repository: dashpay/platform

Length of output: 152


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "=== Check if FFIInputDetail is mentioned anywhere or similar patterns ==="
rg 'FFIInputDetail|FFIOutputDetail' packages/swift-sdk/ --type swift -B 2 -A 2

echo -e "\n=== Check commit that added output role mapping ==="
git log --all -p --grep="output.*role\|FFI_OUTPUT_ROLE" -- packages/swift-sdk | head -100

echo -e "\n=== Check latest commits to ManagedAccount.swift ==="
git log --oneline -- packages/swift-sdk/Sources/SwiftDashSDK/KeyWallet/ManagedAccount.swift | head -20

echo -e "\n=== Look at the specific commit that added input_details mapping ==="
git show 6015040bd:packages/swift-sdk/Sources/SwiftDashSDK/KeyWallet/ManagedAccount.swift 2>/dev/null | grep -A 20 "Convert input details" | head -25

Repository: dashpay/platform

Length of output: 133


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "=== Try to find what fields are accessed on input/output detail ==="
grep -n 'detail\.' packages/swift-sdk/Sources/SwiftDashSDK/KeyWallet/ManagedAccount.swift | grep -E "input|output" -A 5 -B 5

echo -e "\n=== Look at commit history for this file ==="
git log --oneline -20 packages/swift-sdk/Sources/SwiftDashSDK/KeyWallet/ManagedAccount.swift

echo -e "\n=== Check if there are any TODOs or FIXMEs related to isMine ==="
rg 'TODO|FIXME|XXX' packages/swift-sdk/Sources/SwiftDashSDK/KeyWallet/ManagedAccount.swift -B 2 -A 2

echo -e "\n=== Look at TxIO struct definition to understand the field ==="
rg 'struct TxIO|class TxIO' packages/swift-sdk/Sources/SwiftDashSDK/ -A 10 --type swift

Repository: dashpay/platform

Length of output: 832


Map input ownership from FFIInputDetail role field, matching output detail handling

Line 106 hardcodes isMine: false for all inputs, which will misclassify wallet-owned inputs in outgoing and internal transactions. This breaks sender/owner UI logic and contradicts the output detail handling at line 116, which correctly checks detail.role == FFI_OUTPUT_ROLE_RECEIVED || detail.role == FFI_OUTPUT_ROLE_CHANGE.

Update input mapping to check the role field if available on FFIInputDetail, or document why inputs lack ownership metadata if the field is not exposed:

Current code (lines 105-107)
for j in 0..<ffiTx.input_details_count {
    let detail = inputsPtr.advanced(by: j).pointee
    let address = detail.address != nil ? String(cString: detail.address) : ""
    inputs.append(TxIO(address: address, amount: detail.value, isMine: false))
}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/swift-sdk/Sources/SwiftDashSDK/KeyWallet/ManagedAccount.swift`
around lines 100 - 107, The input mapping currently hardcodes isMine: false in
ManagedAccount.swift when building inputs, causing misclassification; update the
loop that builds inputs (the section that iterates ffiTx.input_details and
appends TxIO) to inspect the FFIInputDetail.role field (analogous to the output
handling that checks detail.role == FFI_OUTPUT_ROLE_RECEIVED || detail.role ==
FFI_OUTPUT_ROLE_CHANGE) and set isMine = true when the role indicates the input
is wallet-owned, otherwise false; if FFIInputDetail does not expose a role
field, document that fact in a comment and request exposing ownership metadata
from the FFI so inputs can be classified properly.

@llbartekll llbartekll marked this pull request as draft April 14, 2026 07:42
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.

2 participants