aboutsummaryrefslogtreecommitdiff
path: root/packages/demobank-ui/src/utils.ts
diff options
context:
space:
mode:
authorSebastian <sebasjm@gmail.com>2024-03-08 14:09:31 -0300
committerSebastian <sebasjm@gmail.com>2024-03-08 14:09:31 -0300
commitddd32a690bd13b1eb1aef1356a1d59fd64e254bf (patch)
tree44126872f6e8195a3617e2002c696c0afa13fb0d /packages/demobank-ui/src/utils.ts
parente0e82cdf07930d766081e42203c5a4e66d43191f (diff)
demobank => bank
Diffstat (limited to 'packages/demobank-ui/src/utils.ts')
-rw-r--r--packages/demobank-ui/src/utils.ts447
1 files changed, 0 insertions, 447 deletions
diff --git a/packages/demobank-ui/src/utils.ts b/packages/demobank-ui/src/utils.ts
deleted file mode 100644
index 8b0febe42..000000000
--- a/packages/demobank-ui/src/utils.ts
+++ /dev/null
@@ -1,447 +0,0 @@
-/*
- This file is part of GNU Taler
- (C) 2022-2024 Taler Systems S.A.
-
- GNU Taler is free software; you can redistribute it and/or modify it under the
- terms of the GNU General Public License as published by the Free Software
- Foundation; either version 3, or (at your option) any later version.
-
- GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
- WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
- A PARTICULAR PURPOSE. See the GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License along with
- GNU Taler; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
- */
-
-import {
- AmountString,
- PaytoString,
- TalerError,
- TalerErrorCode,
- TranslatedString,
-} from "@gnu-taler/taler-util";
-import {
- ErrorNotification,
- InternationalizationAPI,
- notify,
- notifyError,
- useTranslationContext,
-} from "@gnu-taler/web-util/browser";
-
-/**
- * Validate (the number part of) an amount. If needed,
- * replace comma with a dot. Returns 'false' whenever
- * the input is invalid, the valid amount otherwise.
- */
-const amountRegex = /^[0-9]+(.[0-9]+)?$/;
-export function validateAmount(
- maybeAmount: string | undefined,
-): string | undefined {
- if (!maybeAmount || !amountRegex.test(maybeAmount)) {
- return;
- }
- return maybeAmount;
-}
-
-/**
- * Extract IBAN from a Payto URI.
- */
-export function getIbanFromPayto(url: string): string {
- const pathSplit = new URL(url).pathname.split("/");
- let lastIndex = pathSplit.length - 1;
- // Happens if the path ends with "/".
- if (pathSplit[lastIndex] === "") lastIndex--;
- const iban = pathSplit[lastIndex];
- return iban;
-}
-
-export function undefinedIfEmpty<T extends object>(obj: T): T | undefined {
- return Object.keys(obj).some(
- (k) => (obj as Record<string, T>)[k] !== undefined,
- )
- ? obj
- : undefined;
-}
-
-export type PartialButDefined<T> = {
- [P in keyof T]: T[P] | undefined;
-};
-
-/**
- * every non-map field can be undefined
- */
-export type WithIntermediate<Type> = {
- [prop in keyof Type]: Type[prop] extends PaytoString
- ? Type[prop] | undefined
- : Type[prop] extends AmountString
- ? Type[prop] | undefined
- : Type[prop] extends TranslatedString
- ? Type[prop] | undefined
- : Type[prop] extends object
- ? WithIntermediate<Type[prop]>
- : Type[prop] | undefined;
-};
-export type RecursivePartial<Type> = {
- [P in keyof Type]?: Type[P] extends (infer U)[]
- ? RecursivePartial<U>[]
- : Type[P] extends object
- ? RecursivePartial<Type[P]>
- : Type[P];
-};
-export type ErrorMessageMappingFor<Type> = {
- [prop in keyof Type]+?: Exclude<Type[prop], undefined> extends PaytoString // enumerate known object
- ? TranslatedString
- : Exclude<Type[prop], undefined> extends AmountString
- ? TranslatedString
- : Exclude<Type[prop], undefined> extends TranslatedString
- ? TranslatedString
- : // arrays: every element
- Exclude<Type[prop], undefined> extends (infer U)[]
- ? ErrorMessageMappingFor<U>[]
- : // map: every field
- Exclude<Type[prop], undefined> extends object
- ? ErrorMessageMappingFor<Type[prop]>
- : TranslatedString;
-};
-
-export enum TanChannel {
- SMS = "sms",
- EMAIL = "email",
-}
-export enum CashoutStatus {
- // The payment was initiated after a valid
- // TAN was received by the bank.
- CONFIRMED = "confirmed",
-
- // The cashout was created and now waits
- // for the TAN by the author.
- PENDING = "pending",
-}
-
-export const PAGE_SIZE = 5;
-
-type Translator = ReturnType<typeof useTranslationContext>["i18n"];
-
-export async function withRuntimeErrorHandling<T>(
- i18n: Translator,
- cb: () => Promise<T>,
-): Promise<void> {
- try {
- await cb();
- } catch (error: unknown) {
- if (error instanceof TalerError) {
- notify(buildRequestErrorMessage(i18n, error));
- } else {
- notifyError(
- i18n.str`Operation failed, please report`,
- (error instanceof Error
- ? error.message
- : JSON.stringify(error)) as TranslatedString,
- );
- }
- }
-}
-
-export function buildRequestErrorMessage(
- i18n: Translator,
- cause: TalerError,
-): ErrorNotification {
- let result: ErrorNotification;
- switch (cause.errorDetail.code) {
- case TalerErrorCode.WALLET_HTTP_REQUEST_GENERIC_TIMEOUT: {
- result = {
- type: "error",
- title: i18n.str`Request timeout`,
- description: cause.message as TranslatedString,
- debug: JSON.stringify(cause.errorDetail, undefined, 2),
- };
- break;
- }
- case TalerErrorCode.WALLET_HTTP_REQUEST_THROTTLED: {
- result = {
- type: "error",
- title: i18n.str`Request throttled`,
- description: cause.message as TranslatedString,
- debug: JSON.stringify(cause.errorDetail, undefined, 2),
- };
- break;
- }
- case TalerErrorCode.WALLET_RECEIVED_MALFORMED_RESPONSE: {
- result = {
- type: "error",
- title: i18n.str`Malformed response`,
- description: cause.message as TranslatedString,
- debug: JSON.stringify(cause.errorDetail, undefined, 2),
- };
- break;
- }
- case TalerErrorCode.WALLET_NETWORK_ERROR: {
- result = {
- type: "error",
- title: i18n.str`Network error`,
- description: cause.message as TranslatedString,
- debug: JSON.stringify(cause.errorDetail, undefined, 2),
- };
- break;
- }
- case TalerErrorCode.WALLET_UNEXPECTED_REQUEST_ERROR: {
- result = {
- type: "error",
- title: i18n.str`Unexpected request error`,
- description: cause.message as TranslatedString,
- debug: JSON.stringify(cause.errorDetail, undefined, 2),
- };
- break;
- }
- default: {
- result = {
- type: "error",
- title: i18n.str`Unexpected error`,
- description: cause.message as TranslatedString,
- debug: JSON.stringify(cause.errorDetail, undefined, 2),
- };
- break;
- }
- }
- return result;
-}
-
-export const COUNTRY_TABLE = {
- AE: "U.A.E.",
- AF: "Afghanistan",
- AL: "Albania",
- AM: "Armenia",
- AN: "Netherlands Antilles",
- AR: "Argentina",
- AT: "Austria",
- AU: "Australia",
- AZ: "Azerbaijan",
- BA: "Bosnia and Herzegovina",
- BD: "Bangladesh",
- BE: "Belgium",
- BG: "Bulgaria",
- BH: "Bahrain",
- BN: "Brunei Darussalam",
- BO: "Bolivia",
- BR: "Brazil",
- BT: "Bhutan",
- BY: "Belarus",
- BZ: "Belize",
- CA: "Canada",
- CG: "Congo",
- CH: "Switzerland",
- CI: "Cote d'Ivoire",
- CL: "Chile",
- CM: "Cameroon",
- CN: "People's Republic of China",
- CO: "Colombia",
- CR: "Costa Rica",
- CS: "Serbia and Montenegro",
- CZ: "Czech Republic",
- DE: "Germany",
- DK: "Denmark",
- DO: "Dominican Republic",
- DZ: "Algeria",
- EC: "Ecuador",
- EE: "Estonia",
- EG: "Egypt",
- ER: "Eritrea",
- ES: "Spain",
- ET: "Ethiopia",
- FI: "Finland",
- FO: "Faroe Islands",
- FR: "France",
- GB: "United Kingdom",
- GD: "Caribbean",
- GE: "Georgia",
- GL: "Greenland",
- GR: "Greece",
- GT: "Guatemala",
- HK: "Hong Kong",
- // HK: "Hong Kong S.A.R.",
- HN: "Honduras",
- HR: "Croatia",
- HT: "Haiti",
- HU: "Hungary",
- ID: "Indonesia",
- IE: "Ireland",
- IL: "Israel",
- IN: "India",
- IQ: "Iraq",
- IR: "Iran",
- IS: "Iceland",
- IT: "Italy",
- JM: "Jamaica",
- JO: "Jordan",
- JP: "Japan",
- KE: "Kenya",
- KG: "Kyrgyzstan",
- KH: "Cambodia",
- KR: "South Korea",
- KW: "Kuwait",
- KZ: "Kazakhstan",
- LA: "Laos",
- LB: "Lebanon",
- LI: "Liechtenstein",
- LK: "Sri Lanka",
- LT: "Lithuania",
- LU: "Luxembourg",
- LV: "Latvia",
- LY: "Libya",
- MA: "Morocco",
- MC: "Principality of Monaco",
- MD: "Moldava",
- // MD: "Moldova",
- ME: "Montenegro",
- MK: "Former Yugoslav Republic of Macedonia",
- ML: "Mali",
- MM: "Myanmar",
- MN: "Mongolia",
- MO: "Macau S.A.R.",
- MT: "Malta",
- MV: "Maldives",
- MX: "Mexico",
- MY: "Malaysia",
- NG: "Nigeria",
- NI: "Nicaragua",
- NL: "Netherlands",
- NO: "Norway",
- NP: "Nepal",
- NZ: "New Zealand",
- OM: "Oman",
- PA: "Panama",
- PE: "Peru",
- PH: "Philippines",
- PK: "Islamic Republic of Pakistan",
- PL: "Poland",
- PR: "Puerto Rico",
- PT: "Portugal",
- PY: "Paraguay",
- QA: "Qatar",
- RE: "Reunion",
- RO: "Romania",
- RS: "Serbia",
- RU: "Russia",
- RW: "Rwanda",
- SA: "Saudi Arabia",
- SE: "Sweden",
- SG: "Singapore",
- SI: "Slovenia",
- SK: "Slovak",
- SN: "Senegal",
- SO: "Somalia",
- SR: "Suriname",
- SV: "El Salvador",
- SY: "Syria",
- TH: "Thailand",
- TJ: "Tajikistan",
- TM: "Turkmenistan",
- TN: "Tunisia",
- TR: "Turkey",
- TT: "Trinidad and Tobago",
- TW: "Taiwan",
- TZ: "Tanzania",
- UA: "Ukraine",
- US: "United States",
- UY: "Uruguay",
- VA: "Vatican",
- VE: "Venezuela",
- VN: "Viet Nam",
- YE: "Yemen",
- ZA: "South Africa",
- ZW: "Zimbabwe",
-};
-
-/**
- * An IBAN is validated by converting it into an integer and performing a
- * basic mod-97 operation (as described in ISO 7064) on it.
- * If the IBAN is valid, the remainder equals 1.
- *
- * The algorithm of IBAN validation is as follows:
- * 1.- Check that the total IBAN length is correct as per the country. If not, the IBAN is invalid
- * 2.- Move the four initial characters to the end of the string
- * 3.- Replace each letter in the string with two digits, thereby expanding the string, where A = 10, B = 11, ..., Z = 35
- * 4.- Interpret the string as a decimal integer and compute the remainder of that number on division by 97
- *
- * If the remainder is 1, the check digit test is passed and the IBAN might be valid.
- *
- */
-const IBAN_REGEX = /^[A-Z][A-Z0-9]*$/;
-export function validateIBAN(
- account: string,
- i18n: InternationalizationAPI,
-): TranslatedString | undefined {
- if (!IBAN_REGEX.test(account)) {
- return i18n.str`IBAN only have uppercased letters and numbers`
- }
- // Check total length
- if (account.length < 4)
- return i18n.str`IBAN numbers have more that 4 digits`;
- if (account.length > 34)
- return i18n.str`IBAN numbers have less that 34 digits`;
-
- const A_code = "A".charCodeAt(0);
- const Z_code = "Z".charCodeAt(0);
- const IBAN = account.toUpperCase();
- // check supported country
- const code = IBAN.substring(0, 2);
- const found = code in COUNTRY_TABLE;
- if (!found) return i18n.str`IBAN country code not found`;
-
- // 2.- Move the four initial characters to the end of the string
- const step2 = IBAN.substring(4) + account.substring(0, 4);
- const step3 = Array.from(step2)
- .map((letter) => {
- const code = letter.charCodeAt(0);
- if (code < A_code || code > Z_code) return letter;
- return `${letter.charCodeAt(0) - "A".charCodeAt(0) + 10}`;
- })
- .join("");
-
- const checksum = calculate_iban_checksum(step3);
- if (checksum !== 1)
- return i18n.str`IBAN number is not valid, checksum is wrong`;
- return undefined;
-}
-
-function calculate_iban_checksum(str: string): number {
- const numberStr = str.substring(0, 5);
- const rest = str.substring(5);
- const number = parseInt(numberStr, 10);
- const result = number % 97;
- if (rest.length > 0) {
- return calculate_iban_checksum(`${result}${rest}`);
- }
- return result;
-}
-
-const USERNAME_REGEX = /^[A-Za-z][A-Za-z0-9]*$/;
-
-export function validateTalerBank(
- account: string,
- i18n: InternationalizationAPI,
-): TranslatedString | undefined {
- if (!USERNAME_REGEX.test(account)) {
- return i18n.str`Account only have letters and numbers`
- }
- return undefined
-}
-
-export function validateRawIBAN(
- payto: string,
- i18n: InternationalizationAPI,
-): TranslatedString | undefined {
- return undefined
-}
-
-
-
-export function validateRawTalerBank(
- payto: string,
- currentHost: string,
- i18n: InternationalizationAPI,
-): TranslatedString | undefined {
- return undefined
-}
-