View Issue Details
| ID | Project | Category | View Status | Date Submitted | Last Update |
|---|---|---|---|---|---|
| 0012124 | Taler | wallet (iOS App) | public | 2026-11-12 02:30 | 2026-11-12 02:30 |
| Reporter | bot-cg [agent] | Assigned To | Resolution deadline | ||
| Implementer | Reviewer | ||||
| Release signed by | Deployed by | ||||
| Verifier | Communicator | CM_7 | |||
| Data protection authority notification required | No | ||||
| CSIRT notification required | No | ||||
| Estimated effort (hours) | Actual effort (hours) | 0 | |||
| Fast-track | No | ||||
| Work package | none | ||||
| Priority | normal | Severity | minor | Reproducibility | have not tried |
| Status | new | Resolution | open | ||
| Summary | 0012124: OIM history: transaction detail shows a negative balance ("Balance: -5.00" for the first withdrawal) while an outgoing payment is pending (patch attached) | ||||
| Description | Steps (iOS 27 simulator, fresh wallet, developer mode on so that OIM is available): 1. "Get demo cash": withdraw KUDOS 25. 2. Actions -> Send -> KUDOS 5.00 -> "Send KUDOS 5.00 now" -> Done. Nobody collects it, so it stays pending. Balances now reads "Balance: KUDOS 20.00 / Pending outgoing KUDOS 5.00". 3. Rotate to landscape (OIM), open the chest, tap the 20 note: the river history opens. 4. Tap the lake of the withdrawal. The detail card for the withdrawal (screenshot attached) shows the 25 that came in, as a 20 and a 5 note, under the line Balance: -5.00 A wallet whose first and only incoming transaction was +25 never had a balance of -5. Cause: OIMtransactions.computeData (TalerWallet1/Views/OIM/OIMtransactions.swift:255) starts from balance.available and walks the transaction list backwards, undoing each transaction to get "the balance before that transaction". The list it is given (TransactionsListView.swift:161) held the withdrawal and a refresh, but not the pending send -- yet the 5 of the pending send are already gone from "available". So 20 - 25 = -5, and with more history every point before the pending transaction is too low by the pending amount. The chart presentation (oimChart) is drawn from the same computed items. Separately, and I may be misreading the intent: the number shown is the balance *before* the tapped transaction (comment at line 301). Even with the arithmetic fixed the card for this withdrawal would say "Balance: 0.00" next to "25 SLE"; the balance after it might be what a user expects there. Suggested fix for the negative value (not compiled): put the pending outgoing amount back before walking backwards. diff --git a/TalerWallet1/Views/OIM/OIMtransactions.swift b/TalerWallet1/Views/OIM/OIMtransactions.swift index 444c057c..d88eacd7 100755 --- a/TalerWallet1/Views/OIM/OIMtransactions.swift +++ b/TalerWallet1/Views/OIM/OIMtransactions.swift @@ -238,7 +238,8 @@ struct OIMtransactions: View { cash.setTarget(.history) debugTick += 1 if computedItems.isEmpty { - computeData(from: history, balance: balance.available.value) // set chartMaxY, computedData + computeData(from: history, balance: balance.available.value, // set chartMaxY, computedData + pendingOutgoing: balance.pendingOutgoing.value) } showHistoryItems(oimChart ? Animation.talerDelay0 : 0.0) } @@ -252,7 +253,7 @@ struct OIMtransactions: View { @available(iOS 16.4, *) extension OIMtransactions { - func computeData(from history: [TalerTransaction], balance: Double) { + func computeData(from history: [TalerTransaction], balance: Double, pendingOutgoing: Double = 0) { /// Algorithm for the X value of the river of time /// Endpoint (now) is 0 /// same day transactions have no space between them @@ -261,7 +262,10 @@ extension OIMtransactions { /// month differs: add one more spacer /// year differs: add yet another spacer var historyItems: [HistoryItem] = [ HistoryItem(distance: 0, marker: .none, balance: balance, talerTX: nil) ] - var balance = balance + // Money in a pending outgoing transaction has already left `available`, but that + // transaction is not in `history`. Put it back before walking backwards, or every + // earlier balance is too low by that amount (and the oldest one negative). + var balance = balance + pendingOutgoing var maxBalance = balance let calendar = Calendar.current // or do we need (identifier: .gregorian) ? var lastTx = calendar.dateComponents([.year, .month, .day, .weekOfMonth], from: Date.now) Found by the UI fuzzing harness (scenario oim-history-detail, 2026-11-12). | ||||
| Tags | No tags attached. | ||||
| Attached Files | |||||