View Issue Details
| ID | Project | Category | View Status | Date Submitted | Last Update |
|---|---|---|---|---|---|
| 0011983 | Taler | wallet (iOS App) | public | 2026-11-09 20:13 | 2026-11-09 20:13 |
| 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 | 0011983: Deposit: nothing bounds how long "Depositing..." waits -- the wallet-core channel has no deadline, and Abort dismisses the screen without cancelling | ||||
| Description | Nothing on the deposit path bounds how long the app will wait for wallet-core. If the answer never comes, "Depositing..." spins for as long as the user is prepared to look at it, and the one control on the screen does not cancel anything. **There is no deadline anywhere on the path.** * `DepositAmountAction.startDeposit` (TalerWallet1/Views/Actions/Banking/ DepositAmountAction.swift:78-93) sets `depositStarted = true` and awaits `model.createDepositGroup(...)` in a `Task` with no timeout. * `WalletModel.sendRequest` (TalerWallet1/Model/WalletModel.swift:189-211) awaits and rethrows; it has no timeout. * `WalletCore.sendFormattedRequest` (TalerWallet1/Backend/ WalletCore.swift:626-629) is a bare `withCheckedThrowingContinuation`. If wallet-core never calls back, the continuation is never resumed and the `await` never returns. There is no deadline in the channel at all, for any operation. **And `createDepositGroup` really does wait on the network.** In wallet-core it calls `getExchangesForDeposit` (taler-wallet-core/src/deposits.ts, inside `createDepositGroup`), so an exchange that does not answer is enough to produce the state above. **What the user is left with.** While `depositStarted` is true the view is a `LoadingView("Depositing...")` with `navigationBarBackButtonHidden(true)` and `interactiveDismissDisabled()` -- the back gesture and the back button are both gone on purpose -- and a single "Abort" button whose action is `dismissTop(stack.push())` (:109-118). That dismisses the screen. It does not cancel the `Task`, does not cancel the wallet-core request, and says nothing about what happened to the deposit. So the choices are: wait with no stated limit, or leave with no answer. **This is about a non-answer, not a swallowed error.** An error *does* surface here: `createDepositGroup` is called with the default `viewHandles: false`, so `sendRequest`'s catch calls `setError` (WalletModel.swift:174-180) and the user gets an alert. That is the difference from 11980, where wallet-core answered 7046 and the view discarded it with `try?`. Here the complaint is the case wallet-core never answers, which no amount of error handling reaches. **Why 30 s is the right order of magnitude.** The exchange round trips inside a deposit are the same ones a withdrawal makes, and on the harness's own deployment a full bank-integrated withdrawal reaches `Done` in about 30 s end to end, of which 30 s is one deliberate `timeout_ms=30000` long poll on `/reserves`. A deposit that has not answered in 30 s is not a slow network. **Not deposit-specific.** The missing deadline is in the shared channel, so every operation inherits it. Deposit is where it shows worst because this screen deliberately removes the exits; `withdraw` and the P2P screens reach the same continuation. | ||||
| Steps To Reproduce | 1. Fund a wallet (empty-wallet screen -> "Get demo cash", KUDOS 25) and add a bank account (Settings -> Bank Accounts -> +, any valid IBAN). 2. Make wallet-core's responses disappear, using the app's own dev experiment facility -- no proxy needed: xcrun simctl openurl booted \ 'taler://dev-experiment/start-tc?drop_resp=1' 3. Actions -> Deposit -> the account -> enter an amount -> "Deposit <amount>". Observed: "Depositing..." with no back button, no swipe-to-dismiss and an "Abort" button. It stays. Abort returns to the previous screen without cancelling the operation or saying what became of it. Expected: a deadline -- some tens of seconds -- after which the screen says the deposit could not be confirmed and offers a retry; and an Abort that cancels rather than just hides. Found while measuring the harness's deterministic `deposit` scenario, whose step budget for this tap was 240 s. That budget is now 30 s, and a new scenario `deposit-no-response` performs exactly the three steps above and asserts that something appears within it. | ||||
| Additional Information | Suggested shape, smallest first: 1. A deadline at the call site, which needs no change to the channel: let result = try await withThrowingTaskGroup(of: DepositGroupResult?.self) { g in g.addTask { try await model.createDepositGroup(...) } g.addTask { try? await Task.sleep(nanoseconds: 30_000_000_000); return nil } let first = try await g.next() g.cancelAll() return first ?? nil } with `nil` rendered as "the deposit could not be confirmed" plus a retry. 2. Better, because every screen inherits it: a timeout in `WalletCore.sendFormattedRequest`, resuming the continuation with a timeout error when wallet-core has not answered within some per-operation budget. The budget cannot be one number for every operation -- a withdrawal's own long poll is 30 s by design -- so it would have to be a property of the request type. 3. Separately, "Abort" should cancel. It currently calls `dismissTop`, so the `Task` and the wallet-core operation both continue behind a screen the user has left. Related: 11980 (same flow family, but there wallet-core answered and the view dropped the answer), 11937 (loading states shown for operations that finish in 21-50 ms -- the same `LoadingView`, the opposite end of the same missing policy). | ||||
| Tags | No tags attached. | ||||
| Date Modified | Username | Field | Change |
|---|---|---|---|
| 2026-11-09 20:13 | bot-cg | New Issue |