commit bdc9d168abf0a74c7b491a0804cc8edf9447cb69
parent 367df7aa26633b99343cbb53de381af650f8e549
Author: Sebastian <sebasjm@taler-systems.com>
Date: Mon, 8 Dec 2025 13:01:26 -0300
fix #10723
Diffstat:
6 files changed, 71 insertions(+), 36 deletions(-)
diff --git a/packages/taler-util/src/iban.ts b/packages/taler-util/src/iban.ts
@@ -116,6 +116,21 @@ function mod97(digits: number[]): number {
return modAccum;
}
+export function convertHUF_BBANtoIBAN(value: string) {
+ if (value.length <= 24) {
+ return opKnownFailure(ParseIbanError.TOO_SHORT);
+ }
+ if (value.length >= 16) {
+ return opKnownFailure(ParseIbanError.TOO_LONG);
+ }
+ if (/[0-9+]/.test(value)) {
+ return opKnownFailure(ParseIbanError.INVALID_CHARSET);
+ }
+
+ const bban = value.length === 16 ? `${value}00000000` : value;
+ return opFixedSuccess<IbanString>(constructIban("HU", bban));
+}
+
/**
* Check the IBAN is correct and return canonical form
* @param ibanString
diff --git a/packages/taler-wallet-core/src/wallet.ts b/packages/taler-wallet-core/src/wallet.ts
@@ -257,6 +257,7 @@ import {
codecForValidateIbanRequest,
codecForWithdrawTestBalance,
constructIban,
+ convertHUF_BBANtoIBAN,
encodeCrock,
getErrorDetailFromException,
getQrCodesForPayto,
@@ -1946,20 +1947,11 @@ export async function handleConvertIbanAccountFieldToPayto(
): Promise<ConvertIbanAccountFieldToPaytoResponse> {
const strippedInput = req.value.replace(/[- ]/g, "");
if (req.currency === "HUF") {
- if (
- strippedInput.length <= 24 &&
- strippedInput.length >= 16 &&
- /[0-9+]/.test(strippedInput)
- ) {
- let bban: string;
- if (strippedInput.length === 16) {
- bban = `${strippedInput}00000000`;
- } else {
- bban = strippedInput;
- }
+ const iban = convertHUF_BBANtoIBAN(strippedInput);
+ if (iban.type === "ok") {
return {
ok: true,
- paytoUri: `payto://iban/${constructIban("HU", bban)}`,
+ paytoUri: iban.body,
type: "iban",
};
} else {
diff --git a/packages/taler-wallet-webextension/src/components/PendingTransactions.tsx b/packages/taler-wallet-webextension/src/components/PendingTransactions.tsx
@@ -48,7 +48,7 @@ export function PendingTransactions({
}: Props): VNode {
const api = useBackendContext();
const state = useAsyncAsHook(() =>
- api.wallet.call(WalletApiOperation.GetTransactions, {}),
+ api.wallet.call(WalletApiOperation.GetTransactionsV2, {}),
);
useEffect(() => {
diff --git a/packages/taler-wallet-webextension/src/wallet/ManageAccount/index.ts b/packages/taler-wallet-webextension/src/wallet/ManageAccount/index.ts
@@ -14,7 +14,7 @@
GNU Taler; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
*/
-import { WalletBankAccountInfo, ScopeInfo, PaytoString } from "@gnu-taler/taler-util";
+import { WalletBankAccountInfo, ScopeInfo, PaytoString, WireTypeDetails } from "@gnu-taler/taler-util";
import { ErrorAlertView } from "../../components/CurrentAlerts.js";
import { Loading } from "../../components/Loading.js";
import { ErrorAlert } from "../../context/alert.js";
@@ -55,6 +55,7 @@ export namespace State {
currency: string;
accountType: SelectFieldHandler;
uri: TextFieldHandler;
+ details: WireTypeDetails;
alias: TextFieldHandler;
onAccountAdded: ButtonHandler;
onCancel: ButtonHandler;
diff --git a/packages/taler-wallet-webextension/src/wallet/ManageAccount/state.ts b/packages/taler-wallet-webextension/src/wallet/ManageAccount/state.ts
@@ -19,6 +19,7 @@ import {
PaytoString,
stringifyPaytoUri,
WalletBankAccountInfo,
+ WireTypeDetails,
} from "@gnu-taler/taler-util";
import { WalletApiOperation } from "@gnu-taler/taler-wallet-core";
import { useTranslationContext } from "@gnu-taler/web-util/browser";
@@ -79,7 +80,7 @@ export function useComponentState({
};
}
- if (hook2.response.wireTypes.length === 0) {
+ if (hook2.response.wireTypeDetails.length === 0) {
return {
status: "error",
error: {
@@ -94,16 +95,18 @@ export function useComponentState({
const [payto, setPayto] = useState("");
const [label, setLabel] = useState("");
- const [type, setType] = useState(hook2.response.wireTypes[0]);
-
- const accountType: Record<string, string> = {};
- hook2.response.wireTypes.forEach((t) => {
- if (t === "iban") {
- accountType[t] = "IBAN";
- } else if (t === "x-taler-bank") {
- accountType[t] = "x-taler-bank";
- } else if (t === "bitcoin") {
- accountType[t] = "Bitcoin";
+ const [type, setType] = useState(hook2.response.wireTypeDetails[0]);
+
+ const detailsByType: Record<string, WireTypeDetails> = {};
+ const accountTypeName: Record<string, string> = {};
+ hook2.response.wireTypeDetails.forEach((t) => {
+ detailsByType[t.paymentTargetType] = t;
+ if (t.paymentTargetType === "iban") {
+ accountTypeName[t.paymentTargetType] = "IBAN";
+ } else if (t.paymentTargetType === "x-taler-bank") {
+ accountTypeName[t.paymentTargetType] = "x-taler-bank";
+ } else if (t.paymentTargetType === "bitcoin") {
+ accountTypeName[t.paymentTargetType] = "Bitcoin";
}
});
@@ -151,11 +154,12 @@ export function useComponentState({
status: "ready",
error: undefined,
currency: scope.currency,
+ details: type,
accountType: {
- list: accountType,
- value: type,
+ list: accountTypeName,
+ value: type.paymentTargetType,
onChange: pushAlertOnError(async (v) => {
- setType(v);
+ setType(detailsByType[v]);
}),
},
selectAccount: async (w) => {
diff --git a/packages/taler-wallet-webextension/src/wallet/ManageAccount/views.tsx b/packages/taler-wallet-webextension/src/wallet/ManageAccount/views.tsx
@@ -16,6 +16,7 @@
import {
BtAddrString,
+ convertHUF_BBANtoIBAN,
HostPortPath,
IbanString,
InternationalizationAPI,
@@ -28,7 +29,8 @@ import {
PaytoUriIBAN,
PaytoUriTalerBank,
TranslatedString,
- WalletBankAccountInfo
+ WalletBankAccountInfo,
+ WireTypeDetails,
} from "@gnu-taler/taler-util";
import { useTranslationContext } from "@gnu-taler/web-util/browser";
import { styled } from "@linaria/react";
@@ -44,7 +46,10 @@ import { State } from "./index.js";
type AccountType = "bitcoin" | "x-taler-bank" | "iban";
type ComponentFormByAccountType = {
- [type in AccountType]: (props: { field: TextFieldHandler }) => VNode;
+ [type in AccountType]: (props: {
+ field: TextFieldHandler;
+ details: WireTypeDetails;
+ }) => VNode;
};
type ComponentListByAccountType = {
@@ -52,6 +57,7 @@ type ComponentListByAccountType = {
list: WalletBankAccountInfo[];
onDelete: (a: WalletBankAccountInfo) => Promise<void>;
onSelect: (ac: WalletBankAccountInfo) => void;
+ details: WireTypeDetails;
}) => VNode;
};
@@ -86,6 +92,7 @@ export function ReadyView({
error,
accountType,
accountByType,
+ details,
alias,
onAccountAdded,
deleteAccount,
@@ -141,6 +148,7 @@ export function ReadyView({
<CustomFieldByAccountType
type={accountType.value as AccountType}
field={uri}
+ details={details}
/>
</p>
</div>
@@ -181,6 +189,7 @@ export function ReadyView({
list={list}
onDelete={deleteAccount}
onSelect={selectAccount}
+ details={details}
/>
);
})}
@@ -467,8 +476,10 @@ function undefinedIfEmpty<T extends object>(obj: T): T | undefined {
function TalerBankAddressAccount({
field,
+ details,
}: {
field: TextFieldHandler;
+ details: WireTypeDetails;
}): VNode {
const { i18n } = useTranslationContext();
const [host, setHost] = useState<string | undefined>(undefined);
@@ -541,12 +552,19 @@ function translateIbanError(
// const bicRegex = /^[A-Z]{6}[A-Z2-9][A-NP-Z0-9]([A-Z0-9]{3})?$/;
// const ibanRegex = /^[A-Z]{2}[0-9]{2}[a-zA-Z0-9]{1,30}$/;
-function IbanAddressAccount({ field }: { field: TextFieldHandler }): VNode {
+function IbanAddressAccount({
+ field,
+ details,
+}: {
+ field: TextFieldHandler;
+ details: WireTypeDetails;
+}): VNode {
const { i18n } = useTranslationContext();
// const [bic, setBic] = useState<string | undefined>(undefined);
const [iban, setIban] = useState<string | undefined>(undefined);
const [name, setName] = useState<string | undefined>(undefined);
const bic = "";
+
const errorsFN = (iban: string | undefined, name: string | undefined) =>
undefinedIfEmpty({
// bic: !bic
@@ -554,9 +572,7 @@ function IbanAddressAccount({ field }: { field: TextFieldHandler }): VNode {
// : !bicRegex.test(bic)
// ? i18n.str`Invalid bic`
// : undefined,
- iban: !iban
- ? i18n.str`Required`
- : validateIBAN(iban, i18n),
+ iban: !iban ? i18n.str`Required` : validateIBAN(iban, i18n, details),
name: !name ? i18n.str`Can't be empty` : undefined,
});
const errors = errorsFN(iban, name);
@@ -634,9 +650,11 @@ function IbanAddressAccount({ field }: { field: TextFieldHandler }): VNode {
function CustomFieldByAccountType({
type,
field,
+ details,
}: {
type: AccountType;
field: TextFieldHandler;
+ details: WireTypeDetails;
}): VNode {
// const { i18n } = useTranslationContext();
@@ -644,7 +662,7 @@ function CustomFieldByAccountType({
return (
<div>
- <AccountForm field={field} />
+ <AccountForm field={field} details={details} />
</div>
);
}
@@ -652,11 +670,16 @@ function CustomFieldByAccountType({
function validateIBAN(
iban: string,
i18n: ReturnType<typeof useTranslationContext>["i18n"],
+ details: WireTypeDetails,
): TranslatedString | undefined {
if (!iban) {
return i18n.str`Required`;
}
- const result = parseIban(iban);
+
+ const result =
+ details.preferredEntryType === "bban"
+ ? convertHUF_BBANtoIBAN(iban) // FIXME: this only works for HU
+ : parseIban(iban);
if (result.type === "ok") {
return undefined;
}