View Issue Details

IDProjectCategoryView StatusLast Update
0011984Talerwallet (iOS App)public2026-11-09 21:07
Reporterbot-cg [agent] Assigned ToResolution deadline
ImplementerReviewer 
Release signed byDeployed by 
VerifierCommunicatorCM_7  
Data protection authority notification requiredNo  
CSIRT notification requiredNo  
Estimated effort (hours)Actual effort (hours)0 
Fast-trackNo
Work packagenone
PrioritynormalSeverityminorReproducibilityhave not tried
Status newResolutionopen 
Summary0011984: Deposit offers an amount the destination cannot receive: getMaxDepositAmount is sent without depositPaytoUri, so the maximum ignores the exchange's wire methods
DescriptionThe deposit amount screen tells the user how much they can deposit without
ever asking where to. The number it shows is the most the wallet could
deposit *somewhere*, and it is presented as the most they can deposit to the
account they just picked -- which for an account the exchange cannot settle
to is zero.

**The missing argument.** `GetMaxDepositAmount.Args`
(TalerWallet1/Model/Model+Deposit.swift) sends two fields, and the one that
would answer the question is commented out in the source:

        struct Args: Encodable {
            var currency: String
            var restrictScope: ScopeInfo
    // var depositPaytoUri: String
        }

wallet-core uses `req.depositPaytoUri` to derive `restrictWireMethod` and to
filter the eligible exchanges (`getMaxDepositAmount` ->
`getDepositExchangeEligibilityInTx`, taler-wallet-core/src/coinSelection.ts).
Without it, nothing in the request names the destination, so nothing in the
answer accounts for it.

**What the user sees.** Measured 2026-11-09, iOS 27.2 simulator, with a
KUDOS 25 wallet funded from the demo exchange and an IBAN account added
through Settings -> Bank Accounts:

    staticText "Available: KUDOS 25.00"
    button "Deposit KUDOS 5.00" enabled
    button "Shortcut KUDOS 5.00" enabled
    button "Shortcut KUDOS 10.00" enabled
    button "Shortcut KUDOS 25.00" enabled

Every one of those is impossible. Pressing Deposit produces:

    createDepositGroup{"amount":"KUDOS:5",
                       "depositPaytoUri":"payto://iban/CH9300762011623852957…"}
    -> code 7026 WALLET_DEPOSIT_GROUP_INSUFFICIENT_BALANCE
       causeHint: "merchant-deposit-insufficient"
       balance: { material: "KUDOS:25", pendingRefresh: "KUDOS:0",
                  available: "KUDOS:25" }
       maximumPayableAmount: "KUDOS:0"
       reasons: [ { "type": "wire-method-unsupported",
                    "wireMethod": "iban" } ]

The wallet holds 25 by both measures. The exchange settles over
x-taler-bank, the account is an IBAN, and the payable maximum is zero --
which `getMaxDepositAmount` would have said if it had been told where the
money was going.

**Two defects, one cause.** The offer is wrong, and the refusal is
unreadable: the error reaches the user as "Internal core error" over a
"Copy the error JSON" button (noted on 11934), and the one hint wallet-core
does supply for this code -- `merchantDepositInsufficient`, "Balance
insufficient!" -- would be wrong in its own way here, since the balance is
not the problem.

**Not the same as 11964**, which was the decode of this call's reply and is
fixed; this is what the call asks in the first place. The decode fix is what
made this visible: before it, `getMaxDepositAmount` threw and the flow died
at the amount screen, so nobody had ever pressed Deposit.
Steps To Reproduce1. Fund a wallet with demo cash (KUDOS 25) from the empty-wallet screen.
2. Settings -> Bank Accounts -> + -> IBAN, with a label, an account holder
   and any valid IBAN (e.g. CH9300762011623852957).
3. Actions -> Deposit -> that account.

Observed: the heading reads "Available: KUDOS 25.00" and the KUDOS 5, 10
and 25 shortcuts are all enabled. Entering any amount and pressing
"Deposit <amount>" fails with "Internal core error"; the os_log carries the
7026 above with `wire-method-unsupported`.

Expected: the maximum reflects the selected account -- KUDOS 0.00 for this
pair, with the shortcuts disabled and a sentence saying that this account
cannot receive KUDOS from this payment service. wallet-core supplies both
the number and the reason once it is told the destination.

The same wallet CAN deposit to an x-taler-bank account at that exchange,
which is what makes this a wrong offer rather than a missing feature.
Additional InformationFix: pass the payto URI the screen already holds.
`DepositAmountAction` has `paytoUri` (it is what the account row selected and
what `createDepositGroup` is given), so the request becomes

    GetMaxDepositAmount(scope: scope, depositPaytoUri: paytoUri)

with the field uncommented in `Args`. The reply's
`exchangeDiagnostics[<exchange>].reasons` then carries the eligibility
failures in deterministic order, which is the material for the sentence the
screen is missing.

Worth checking at the same time: the Send/Request screens take their
maximum from `getMaxPeerPushDebitAmount`, which has no destination to
restrict by, so they are not affected. The *withdrawal* screen's maximum
comes from the bank's own limits and is likewise unrelated.

Found by the deterministic `deposit` scenario in the fuzzing harness. It is
also why that scenario cannot be green as written, and the harness's own
bank-add prelude will be changed to add an x-taler-bank account for the
demo exchange instead of an IBAN one -- a change to the test, not evidence
about the app.
TagsNo tags attached.

Required notifications

Address or linkRemarkAdded byNotifiedActions

Activities

There are no notes attached to this issue.

Issue History

Date ModifiedUsernameFieldChange
2026-11-09 21:07bot-cgNew Issue