From b63937703ce1e269055497ee14ac90a28de2fc74 Mon Sep 17 00:00:00 2001 From: Florian Dold Date: Wed, 6 Sep 2023 13:24:34 +0200 Subject: move bank API client to taler-util, update typescript config --- packages/taler-wallet-core/src/bank-api-client.ts | 340 ---------------------- packages/taler-wallet-core/src/dbless.ts | 6 +- packages/taler-wallet-core/src/index.ts | 2 - packages/taler-wallet-core/src/wallet.ts | 6 +- 4 files changed, 3 insertions(+), 351 deletions(-) delete mode 100644 packages/taler-wallet-core/src/bank-api-client.ts (limited to 'packages/taler-wallet-core/src') diff --git a/packages/taler-wallet-core/src/bank-api-client.ts b/packages/taler-wallet-core/src/bank-api-client.ts deleted file mode 100644 index f1289525d..000000000 --- a/packages/taler-wallet-core/src/bank-api-client.ts +++ /dev/null @@ -1,340 +0,0 @@ -/* - This file is part of GNU Taler - (C) 2022 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 - */ - -/** - * Client for the Taler (demo-)bank. - */ - -/** - * Imports. - */ -import { - AmountString, - base64FromArrayBuffer, - buildCodecForObject, - Codec, - codecForAny, - codecForString, - encodeCrock, - generateIban, - getRandomBytes, - j2s, - Logger, - stringToBytes, - TalerError, - TalerErrorCode, -} from "@gnu-taler/taler-util"; -import { - checkSuccessResponseOrThrow, - createPlatformHttpLib, - HttpRequestLibrary, - readSuccessResponseJsonOrThrow, -} from "@gnu-taler/taler-util/http"; - -const logger = new Logger("bank-api-client.ts"); - -export enum CreditDebitIndicator { - Credit = "credit", - Debit = "debit", -} - -export interface BankAccountBalanceResponse { - balance: { - amount: AmountString; - credit_debit_indicator: CreditDebitIndicator; - }; -} - -export interface BankServiceHandle { - readonly bankAccessApiBaseUrl: string; - readonly http: HttpRequestLibrary; -} - -export interface BankUser { - username: string; - password: string; - accountPaytoUri: string; -} - -export interface WithdrawalOperationInfo { - withdrawal_id: string; - taler_withdraw_uri: string; -} - -/** - * FIXME: Rename, this is not part of the integration test harness anymore. - */ -export interface HarnessExchangeBankAccount { - accountName: string; - accountPassword: string; - accountPaytoUri: string; - wireGatewayApiBaseUrl: string; -} - -/** - * Helper function to generate the "Authorization" HTTP header. - */ -function makeBasicAuthHeader(username: string, password: string): string { - const auth = `${username}:${password}`; - const authEncoded: string = base64FromArrayBuffer(stringToBytes(auth)); - return `Basic ${authEncoded}`; -} - -const codecForWithdrawalOperationInfo = (): Codec => - buildCodecForObject() - .property("withdrawal_id", codecForString()) - .property("taler_withdraw_uri", codecForString()) - .build("WithdrawalOperationInfo"); - -export interface BankAccessApiClientArgs { - auth?: { username: string; password: string }; - httpClient?: HttpRequestLibrary; -} - -export interface BankAccessApiCreateTransactionRequest { - amount: AmountString; - paytoUri: string; -} - -export class WireGatewayApiClientArgs { - auth?: { - username: string; - password: string; - }; - httpClient?: HttpRequestLibrary; -} - -/** - * This API look like it belongs to harness - * but it will be nice to have in utils to be used by others - */ -export class WireGatewayApiClient { - httpLib; - - constructor( - private baseUrl: string, - private args: WireGatewayApiClientArgs = {}, - ) { - this.httpLib = args.httpClient ?? createPlatformHttpLib(); - } - - private makeAuthHeader(): Record { - const auth = this.args.auth; - if (auth) { - return { - Authorization: makeBasicAuthHeader(auth.username, auth.password), - }; - } - return {}; - } - - async adminAddIncoming(params: { - amount: string; - reservePub: string; - debitAccountPayto: string; - }): Promise { - let url = new URL(`admin/add-incoming`, this.baseUrl); - const resp = await this.httpLib.fetch(url.href, { - method: "POST", - body: { - amount: params.amount, - reserve_pub: params.reservePub, - debit_account: params.debitAccountPayto, - }, - headers: this.makeAuthHeader(), - }); - logger.info(`add-incoming response status: ${resp.status}`); - await checkSuccessResponseOrThrow(resp); - } -} - -/** - * This API look like it belongs to harness - * but it will be nice to have in utils to be used by others - */ -export class BankAccessApiClient { - httpLib: HttpRequestLibrary; - - constructor( - private baseUrl: string, - private args: BankAccessApiClientArgs = {}, - ) { - this.httpLib = args.httpClient ?? createPlatformHttpLib(); - } - - setAuth(auth: { username: string; password: string }) { - this.args.auth = auth; - } - - private makeAuthHeader(): Record { - if (!this.args.auth) { - return {}; - } - const authHeaderValue = makeBasicAuthHeader( - this.args.auth.username, - this.args.auth.password, - ); - return { - Authorization: authHeaderValue, - }; - } - - async getAccountBalance( - username: string, - ): Promise { - const url = new URL(`accounts/${username}`, this.baseUrl); - const resp = await this.httpLib.fetch(url.href, { - headers: this.makeAuthHeader(), - }); - return await resp.json(); - } - - async getTransactions(username: string): Promise { - const reqUrl = new URL(`accounts/${username}/transactions`, this.baseUrl); - const resp = await this.httpLib.fetch(reqUrl.href, { - method: "GET", - headers: { - ...this.makeAuthHeader(), - }, - }); - - const res = await readSuccessResponseJsonOrThrow(resp, codecForAny()); - logger.info(`result: ${j2s(res)}`); - } - - async createTransaction( - username: string, - req: BankAccessApiCreateTransactionRequest, - ): Promise { - const reqUrl = new URL(`accounts/${username}/transactions`, this.baseUrl); - - const resp = await this.httpLib.fetch(reqUrl.href, { - method: "POST", - body: req, - headers: this.makeAuthHeader(), - }); - - return await readSuccessResponseJsonOrThrow(resp, codecForAny()); - } - - async registerAccount( - username: string, - password: string, - options: { - iban?: string; - } = {}, - ): Promise { - const url = new URL("testing/register", this.baseUrl); - const resp = await this.httpLib.fetch(url.href, { - method: "POST", - body: { - username, - password, - iban: options?.iban, - }, - }); - let paytoUri = `payto://x-taler-bank/localhost/${username}`; - if (resp.status !== 200 && resp.status !== 202 && resp.status !== 204) { - logger.error(`${j2s(await resp.json())}`); - throw TalerError.fromDetail( - TalerErrorCode.GENERIC_UNEXPECTED_REQUEST_ERROR, - { - httpStatusCode: resp.status, - }, - ); - } - try { - // Pybank has no body, thus this might throw. - const respJson = await resp.json(); - // LibEuFin demobank returns payto URI in response - if (respJson.paytoUri) { - paytoUri = respJson.paytoUri; - } - } catch (e) { - // Do nothing - } - return { - password, - username, - accountPaytoUri: paytoUri, - }; - } - - async createRandomBankUser(): Promise { - const username = "user-" + encodeCrock(getRandomBytes(10)).toLowerCase(); - const password = "pw-" + encodeCrock(getRandomBytes(10)).toLowerCase(); - // FIXME: This is just a temporary workaround, because demobank is running out of short IBANs - const iban = generateIban("DE", 15); - return await this.registerAccount(username, password, { - iban, - }); - } - - async createWithdrawalOperation( - user: string, - amount: string, - ): Promise { - const url = new URL(`accounts/${user}/withdrawals`, this.baseUrl); - const resp = await this.httpLib.fetch(url.href, { - method: "POST", - body: { - amount, - }, - headers: this.makeAuthHeader(), - }); - return readSuccessResponseJsonOrThrow( - resp, - codecForWithdrawalOperationInfo(), - ); - } - - async confirmWithdrawalOperation( - username: string, - wopi: WithdrawalOperationInfo, - ): Promise { - const url = new URL( - `accounts/${username}/withdrawals/${wopi.withdrawal_id}/confirm`, - this.baseUrl, - ); - logger.info(`confirming withdrawal operation via ${url.href}`); - const resp = await this.httpLib.fetch(url.href, { - method: "POST", - body: {}, - headers: this.makeAuthHeader(), - }); - - logger.info(`response status ${resp.status}`); - const respJson = await readSuccessResponseJsonOrThrow(resp, codecForAny()); - - // FIXME: We don't check the status here! - } - - async abortWithdrawalOperation( - accountName: string, - wopi: WithdrawalOperationInfo, - ): Promise { - const url = new URL( - `accounts/${accountName}/withdrawals/${wopi.withdrawal_id}/abort`, - this.baseUrl, - ); - const resp = await this.httpLib.fetch(url.href, { - method: "POST", - body: {}, - headers: this.makeAuthHeader(), - }); - await readSuccessResponseJsonOrThrow(resp, codecForAny()); - } -} diff --git a/packages/taler-wallet-core/src/dbless.ts b/packages/taler-wallet-core/src/dbless.ts index 357b7d289..0aad477e4 100644 --- a/packages/taler-wallet-core/src/dbless.ts +++ b/packages/taler-wallet-core/src/dbless.ts @@ -52,7 +52,7 @@ import { HttpRequestLibrary, readSuccessResponseJsonOrThrow, } from "@gnu-taler/taler-util/http"; -import { BankAccessApiClient, BankServiceHandle } from "./bank-api-client.js"; +import { BankAccessApiClient } from "../../taler-util/src/bank-api-client.js"; import { TalerCryptoInterface } from "./crypto/cryptoImplementation.js"; import { DenominationRecord } from "./db.js"; import { isWithdrawableDenom } from "./index.js"; @@ -117,10 +117,6 @@ export async function topupReserveWithDemobank( args: TopupReserveWithDemobankArgs, ) { const { http, bankAccessApiBaseUrl, amount, exchangeInfo, reservePub } = args; - const bankHandle: BankServiceHandle = { - bankAccessApiBaseUrl: bankAccessApiBaseUrl, - http, - }; const bankClient = new BankAccessApiClient(bankAccessApiBaseUrl); const bankUser = await bankClient.createRandomBankUser(); const wopi = await bankClient.createWithdrawalOperation( diff --git a/packages/taler-wallet-core/src/index.ts b/packages/taler-wallet-core/src/index.ts index d64f7d5e6..643d65620 100644 --- a/packages/taler-wallet-core/src/index.ts +++ b/packages/taler-wallet-core/src/index.ts @@ -44,8 +44,6 @@ export * from "./operations/backup/index.js"; export * from "./operations/exchanges.js"; -export * from "./bank-api-client.js"; - export * from "./operations/withdraw.js"; export * from "./operations/refresh.js"; diff --git a/packages/taler-wallet-core/src/wallet.ts b/packages/taler-wallet-core/src/wallet.ts index f42365c00..9a3b8f235 100644 --- a/packages/taler-wallet-core/src/wallet.ts +++ b/packages/taler-wallet-core/src/wallet.ts @@ -129,10 +129,8 @@ import { codecForTestingSetTimetravelRequest, setDangerousTimetravel, } from "@gnu-taler/taler-util"; -import { - HttpRequestLibrary, - readSuccessResponseJsonOrThrow, -} from "@gnu-taler/taler-util/http"; +import type { HttpRequestLibrary } from "@gnu-taler/taler-util/http"; +import { readSuccessResponseJsonOrThrow } from "@gnu-taler/taler-util/http"; import { TalerCryptoInterface } from "./crypto/cryptoImplementation.js"; import { CryptoDispatcher, -- cgit v1.2.3