View Issue Details

IDProjectCategoryView StatusLast Update
0012108Talerwallet (WebExtension)public2026-11-11 02:09
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 
Summary0012108: WebExtension: wire-transfer instructions for a withdrawal differ from DD 88 / Android / iOS (no steps, no "subject is mandatory" warning, no timing)
DescriptionAfter a manual withdrawal the web wallet's "Pending withdrawal" screen explains the bank transfer with different and much shorter text than the Android and iOS wallets, which both follow DD 88 "Wallet Withdrawal Experience" (taler-docs design-documents/088-wallet-withdraw.rst, section "Wire transfer instructions"; the DD says Android, iOS and WebExtension should follow it).

What the user sees (withdraw-exchange link for exchange.demo.taler.net, KUDOS 5):
- Android / iOS: "You need to transfer KUDOS 5.00 from your regular bank account to the payment service to receive KUDOS 5.00 as digital cash in this wallet."; "Step 1: ... copy and paste recipient and account/IBAN ..."; "Step 2: Copy this code and paste it into the subject/purpose field ..." with "This is mandatory, otherwise your money will not arrive in this wallet."; "Step 3: Finish the wire transfer of ... then this withdrawal will proceed automatically. Depending on your bank the transfer can take from minutes to two working days, please be patient." (before-android-1.png, before-android-2.png, before-ios-1.png, before-ios-2.png).
- WebExtension: "Transfer this amount to receive KUDOS:5 as digital cash." and "Copy these details exactly into your banking app. The payment reference is required." (before-web-1.png, before-web-full.png). Missing: that the transfer must come from the user's own bank account, that a missing subject means the money does not arrive, and that the withdrawal then continues by itself after up to two working days.

Code (origin/master bf2e571a2): packages/wallet-webui/src/screens/WireTransferScreen.tsx:148-152 (amount card text), :326-352 (instructions: one hint line and the field list); the fields are built in routes/withdrawal-model.ts:195-206. Android: transfer/TransferIBAN.kt and strings withdraw_manual_ready_intro / withdraw_manual_step_* / withdraw_manual_ready_warning; iOS: Views/Transactions/ManualDetailsWireV.swift:27, 279-285, 318-338.

Patch (web-wire-transfer-steps.patch), withdrawals only (the deposit KYC-auth variant of the same screen is unchanged):
- amount card: "You need to transfer <amount> from your regular bank account to the exchange to receive <amount> as digital cash in this wallet." ("exchange" as elsewhere in the web wallet);
- "Step 1: ..." before the account fields; the payment-reference field is marked in withdrawal-model.ts (WireFieldView.reference) and preceded by "Step 2: ..." and a warning box "This is mandatory, otherwise your money will not arrive in this wallet."; "Step 3: Finish the wire transfer of <amount> ... two working days, please be patient." after the fields.
Six new msgids, wording taken from the Android/iOS strings.
Verified: wc-web build (Chrome MV3 extension) and after-web-1.png, after-web-2.png, after-web-full.png. `pnpm run typecheck` reports the same 29 pre-existing errors as origin/master (observations/peer-credit refactor in progress), none in the changed files.

Assisted by LLM
Steps To ReproduceWithdraw from an exchange without bank integration (e.g. taler://withdraw-exchange/exchange.demo.taler.net/?a=KUDOS%3A5), accept ToS, Withdraw, read the "Pending withdrawal" screen.
TagsNo tags attached.
Attached Files
before-web-1.png (156,636 bytes)   
before-web-1.png (156,636 bytes)   
before-web-full.png (159,694 bytes)   
before-web-full.png (159,694 bytes)   
before-android-1.png (171,138 bytes)   
before-android-1.png (171,138 bytes)   
before-android-2.png (171,138 bytes)   
before-android-2.png (171,138 bytes)   
before-ios-1.png (313,964 bytes)
before-ios-2.png (537,502 bytes)
after-web-1.png (166,504 bytes)   
after-web-1.png (166,504 bytes)   
after-web-2.png (200,965 bytes)   
after-web-2.png (200,965 bytes)   
after-web-full.png (263,154 bytes)
web-wire-transfer-steps.patch (5,548 bytes)   
diff --git a/packages/wallet-webui/src/routes/withdrawal-model.ts b/packages/wallet-webui/src/routes/withdrawal-model.ts
index 7ce8098c6..b46ba1588 100644
--- a/packages/wallet-webui/src/routes/withdrawal-model.ts
+++ b/packages/wallet-webui/src/routes/withdrawal-model.ts
@@ -19,6 +19,8 @@ import { i18n } from "../i18n/runtime.js";
 export interface WireFieldView {
   label: string;
   value: string;
+  /** The subject / payment reference the exchange needs to credit the transfer. */
+  reference?: boolean;
 }
 
 export interface WireOptionView {
@@ -202,7 +204,11 @@ export function wireOptions(
           if (amount) fields.push({ label: i18n.str`Amount`, value: amount });
           if (subject)
             // Translators: Subject or remittance reference for a bank transfer.
-            fields.push({ label: i18n.str`Payment reference`, value: subject });
+            fields.push({
+              label: i18n.str`Payment reference`,
+              value: subject,
+              reference: true,
+            });
           return {
             id: `${accountIndex}-${optionIndex}`,
             label:
diff --git a/packages/wallet-webui/src/screens/WireTransferScreen.tsx b/packages/wallet-webui/src/screens/WireTransferScreen.tsx
index 9a69c205f..d780dce75 100644
--- a/packages/wallet-webui/src/screens/WireTransferScreen.tsx
+++ b/packages/wallet-webui/src/screens/WireTransferScreen.tsx
@@ -147,8 +147,8 @@ export function WireTransferScreen(props: {
       ) : (
         <Card class="text-center">
           <p class="text-3xl font-semibold">{props.amountRaw}</p>
-          {/* Translators: %1$s is the effective digital-cash amount after fees. */}
-          <p class="mt-2 text-secondary">{i18n.str`Transfer this amount to receive ${props.amountEffective} as digital cash.`}</p>
+          {/* Translators: %1$s is the amount to wire, %2$s the effective digital-cash amount after fees. */}
+          <p class="mt-2 text-secondary">{i18n.str`You need to transfer ${props.amountRaw} from your regular bank account to the exchange to receive ${props.amountEffective} as digital cash in this wallet.`}</p>
         </Card>
       )}
       {props.options.length === 0 ? (
@@ -326,11 +326,28 @@ export function WireTransferScreen(props: {
                     {!blockedReason && option.fields.length > 0 && (
                       <div>
                         <h4 class="text-lg font-semibold">{i18n.str`Wire transfer instructions`}</h4>
-                        {/* Translators: The payment reference identifies this bank transfer to the exchange. */}
-                        <p class="mt-2 text-sm text-secondary">{i18n.str`Copy these details exactly into your banking app. The payment reference is required.`}</p>
+                        {isKycAuth ? (
+                          /* Translators: The payment reference identifies this bank transfer to the exchange. */
+                          <p class="mt-2 text-sm text-secondary">{i18n.str`Copy these details exactly into your banking app. The payment reference is required.`}</p>
+                        ) : (
+                          <p class="mt-2 text-sm text-secondary">{
+                            /* Translators: Step 1 of 3 of the wire-transfer instructions (DD 88). */ i18n.str`Step 1: If you don't already have it in your banking favorites list, then copy and paste recipient and account into the matching fields in your banking app or website (and save it as favorite for the next time):`
+                          }</p>
+                        )}
                         <dl class="mt-5 space-y-5">
                           {option.fields.map((field) => (
                             <div key={`${field.label}-${field.value}`}>
+                              {!isKycAuth && field.reference && (
+                                <div class="mb-4 space-y-3">
+                                  <p class="text-sm text-secondary">{
+                                    /* Translators: Step 2 of 3 of the wire-transfer instructions (DD 88). */ i18n.str`Step 2: Copy this code and paste it into the subject/purpose field in your banking app or website:`
+                                  }</p>
+                                  <p
+                                    role="note"
+                                    class="rounded-xl bg-warningContainer p-3 text-sm font-medium text-onWarningContainer"
+                                  >{i18n.str`This is mandatory, otherwise your money will not arrive in this wallet.`}</p>
+                                </div>
+                              )}
                               <dt class="text-sm text-secondary">
                                 {field.label}
                               </dt>
@@ -351,6 +368,11 @@ export function WireTransferScreen(props: {
                             </div>
                           ))}
                         </dl>
+                        {!isKycAuth && (
+                          <p class="mt-5 text-sm text-secondary">{
+                            /* Translators: Step 3 of 3 of the wire-transfer instructions (DD 88); %1$s is the amount to wire. */ i18n.str`Step 3: Finish the wire transfer of ${props.amountRaw} in your banking app or website, then this withdrawal will proceed automatically. Depending on your bank the transfer can take from minutes to two working days, please be patient.`
+                          }</p>
+                        )}
                       </div>
                     )}
                   </Card>
web-wire-transfer-steps.patch (5,548 bytes)   

Required notifications

Address or linkRemarkAdded byNotifiedActions

Activities

Issue History

Date ModifiedUsernameFieldChange
2026-11-11 02:09bot-cgNew Issue
2026-11-11 02:09bot-cgFile Added: before-web-1.png
2026-11-11 02:09bot-cgFile Added: before-web-full.png
2026-11-11 02:09bot-cgFile Added: before-android-1.png
2026-11-11 02:09bot-cgFile Added: before-android-2.png
2026-11-11 02:09bot-cgFile Added: before-ios-1.png
2026-11-11 02:09bot-cgFile Added: before-ios-2.png
2026-11-11 02:09bot-cgFile Added: after-web-1.png
2026-11-11 02:09bot-cgFile Added: after-web-2.png
2026-11-11 02:09bot-cgFile Added: after-web-full.png
2026-11-11 02:09bot-cgFile Added: web-wire-transfer-steps.patch