commit bd5e3a2bb6b8334d422d3eada2242f11595ea8a8
parent 6a1ebc106552be354906630c916a4639d05435a8
Author: Florian Dold <dold@taler.net>
Date: Thu, 23 Jul 2026 03:22:44 +0200
wallet: use typed clients in dbless and testing helpers
Diffstat:
2 files changed, 83 insertions(+), 100 deletions(-)
diff --git a/packages/taler-wallet-core/src/dbless.ts b/packages/taler-wallet-core/src/dbless.ts
@@ -42,13 +42,14 @@ import {
Logger,
Paytos,
Result,
+ TalerBankIntegrationHttpClient,
TalerCorebankApiClient,
TalerExchangeHttpClient,
TalerProtocolTimestamp,
+ TalerUriAction,
+ TalerUris,
+ TalerWireGatewayHttpClient,
UnblindedDenominationSignature,
- codecForAny,
- codecForBankWithdrawalOperationPostResponse,
- codecForBatchDepositSuccess,
encodeCrock,
getRandomBytes,
hashDenomPub,
@@ -56,13 +57,10 @@ import {
j2s,
succeedOrThrow,
} from "@gnu-taler/taler-util";
-import {
- HttpRequestLibrary,
- readSuccessResponseJsonOrThrow,
-} from "@gnu-taler/taler-util/http";
+import { HttpRequestLibrary } from "@gnu-taler/taler-util/http";
import { TalerCryptoInterface } from "./crypto/cryptoImplementation.js";
import { ExchangeInfo, downloadExchangeInfo } from "./exchanges.js";
-import { getBankStatusUrl, getBankWithdrawalInfo } from "./withdraw.js";
+import { getBankWithdrawalInfo } from "./withdraw.js";
export { downloadExchangeInfo };
@@ -108,7 +106,6 @@ export async function topupReserveWithBank(args: TopupReserveWithBankArgs) {
amount,
);
const bankInfo = await getBankWithdrawalInfo(http, wopi.taler_withdraw_uri);
- const bankStatusUrl = getBankStatusUrl(wopi.taler_withdraw_uri);
if (!bankInfo.exchange) {
throw Error("no suggested exchange");
}
@@ -117,16 +114,24 @@ export async function topupReserveWithBank(args: TopupReserveWithBankArgs) {
if (plainPaytoUris.length <= 0) {
throw new Error();
}
- const httpResp = await http.fetch(bankStatusUrl.href, {
- method: "POST",
- body: {
- reserve_pub: reservePub,
- selected_exchange: plainPaytoUris[0],
- },
- });
- await readSuccessResponseJsonOrThrow(
- httpResp,
- codecForBankWithdrawalOperationPostResponse(),
+ const uriResult = Result.orUndefined(
+ TalerUris.parseRestricted(wopi.taler_withdraw_uri, TalerUriAction.Withdraw),
+ );
+ if (!uriResult) {
+ throw Error(`can't parse withdrawal URI ${wopi.taler_withdraw_uri}`);
+ }
+ const bankIntegrationClient = new TalerBankIntegrationHttpClient(
+ uriResult.bankIntegrationApiBaseUrl,
+ { httpClient: http },
+ );
+ succeedOrThrow(
+ await bankIntegrationClient.completeWithdrawalOperationById(
+ uriResult.withdrawalOperationId,
+ {
+ reserve_pub: reservePub,
+ selected_exchange: plainPaytoUris[0],
+ },
+ ),
);
await bankClient.confirmWithdrawalOperation(bankUser.username, {
withdrawalOperationId: wopi.withdrawal_id,
@@ -359,12 +364,10 @@ export async function depositCoinBatch(args: {
refund_deadline: refundDeadline,
merchant_pub: merchantPub,
};
- const url = new URL(`batch-deposit`, args.exchangeBaseUrl);
- const httpResp = await http.fetch(url.href, {
- method: "POST",
- body: requestBody,
+ const exchangeClient = new TalerExchangeHttpClient(args.exchangeBaseUrl, {
+ httpClient: http,
});
- await readSuccessResponseJsonOrThrow(httpResp, codecForBatchDepositSuccess());
+ succeedOrThrow(await exchangeClient.batchDeposit({ body: requestBody }));
}
export async function refreshCoin(req: {
@@ -448,21 +451,22 @@ export async function createTestingReserve(args: {
}
const components = pt.fullPath.split("/");
const creditorAcct = components[components.length - 1];
- const fbReq = await http.fetch(
+ const wireGatewayClient = new TalerWireGatewayHttpClient(
new URL(
- `accounts/${creditorAcct}/taler-wire-gateway/admin/add-incoming`,
+ `accounts/${creditorAcct}/taler-wire-gateway/`,
corebankApiBaseUrl,
).href,
- {
- method: "POST",
+ { httpClient: http },
+ );
+ succeedOrThrow(
+ await wireGatewayClient.addIncoming({
body: {
- amount,
+ amount: amount as AmountString,
reserve_pub: reservePub,
debit_account: "payto://x-taler-bank/localhost/testdebtor",
},
- },
+ }),
);
- await readSuccessResponseJsonOrThrow(fbReq, codecForAny());
}
/**
@@ -475,14 +479,14 @@ export async function checkReserve(
reservePub: string,
longpollTimeoutMs: number = 500,
): Promise<void> {
- const reqUrl = new URL(`reserves/${reservePub}`, exchangeBaseUrl);
- if (longpollTimeoutMs) {
- reqUrl.searchParams.set("timeout_ms", `${longpollTimeoutMs}`);
- }
- const resp = await http.fetch(reqUrl.href, {
- method: "GET",
+ const exchangeClient = new TalerExchangeHttpClient(exchangeBaseUrl, {
+ httpClient: http,
});
- if (resp.status !== 200) {
+ const resp = await exchangeClient.getReserveStatus(
+ reservePub,
+ longpollTimeoutMs > 0,
+ );
+ if (resp.case !== "ok") {
throw new Error("reserve not okay");
}
}
diff --git a/packages/taler-wallet-core/src/testing.ts b/packages/taler-wallet-core/src/testing.ts
@@ -25,13 +25,12 @@
*/
import {
AbsoluteTime,
+ AccessToken,
addPaytoQueryParams,
Amounts,
AmountString,
checkLogicInvariant,
CheckPaymentResponse,
- codecForAny,
- codecForCheckPaymentResponse,
ConfirmPayResultType,
Duration,
IntegrationTestArgs,
@@ -42,7 +41,9 @@ import {
Paytos,
Result,
PreparePayResultType,
+ succeedOrThrow,
TalerCorebankApiClient,
+ TalerMerchantInstanceHttpClient,
TestingWaitBalanceRequest,
TestingWaitTransactionRequest,
TestPayArgs,
@@ -56,10 +57,7 @@ import {
URL,
WithdrawTestBalanceRequest,
} from "@gnu-taler/taler-util";
-import {
- HttpRequestLibrary,
- readSuccessResponseJsonOrThrow,
-} from "@gnu-taler/taler-util/http";
+import { HttpRequestLibrary } from "@gnu-taler/taler-util/http";
import { getBalanceDetail, getBalances } from "./balance.js";
import { genericWaitForState } from "./common.js";
import { createDepositGroup } from "./deposits.js";
@@ -170,21 +168,6 @@ async function withdrawTestBalanceImpl(
};
}
-/**
- * FIXME: User TalerMerchantInstanceHttpClient instead.
- */
-function getMerchantAuthHeader(m: MerchantBackendInfo): Record<string, string> {
- if (m.authToken) {
- return {
- Authorization: `Bearer ${m.authToken}`,
- };
- }
- return {};
-}
-
-/**
- * FIXME: User TalerMerchantInstanceHttpClient instead.
- */
async function refund(
http: HttpRequestLibrary,
merchantBackend: MerchantBackendInfo,
@@ -192,21 +175,20 @@ async function refund(
reason: string,
refundAmount: string,
): Promise<string> {
- const reqUrl = new URL(
- `private/orders/${orderId}/refund`,
+ const merchantClient = new TalerMerchantInstanceHttpClient(
merchantBackend.baseUrl,
+ http,
+ );
+ const r = succeedOrThrow(
+ await merchantClient.addRefund(
+ merchantBackend.authToken as AccessToken,
+ orderId,
+ {
+ reason,
+ refund: refundAmount as AmountString,
+ },
+ ),
);
- const refundReq = {
- order_id: orderId,
- reason,
- refund: refundAmount,
- };
- const resp = await http.fetch(reqUrl.href, {
- method: "POST",
- body: refundReq,
- headers: getMerchantAuthHeader(merchantBackend),
- });
- const r = await readSuccessResponseJsonOrThrow(resp, codecForAny());
const refundUri = r.taler_refund_uri;
if (!refundUri) {
throw Error("no refund URI in response");
@@ -214,9 +196,6 @@ async function refund(
return refundUri;
}
-/**
- * FIXME: User TalerMerchantInstanceHttpClient instead.
- */
async function createOrder(
http: HttpRequestLibrary,
merchantBackend: MerchantBackendInfo,
@@ -225,22 +204,21 @@ async function createOrder(
fulfillmentUrl: string,
): Promise<{ orderId: string }> {
const t = Math.floor(new Date().getTime() / 1000) + 15 * 60;
- const reqUrl = new URL("private/orders", merchantBackend.baseUrl).href;
- const orderReq = {
- order: {
- amount,
- summary,
- fulfillment_url: fulfillmentUrl,
- refund_deadline: { t_s: t },
- wire_transfer_deadline: { t_s: t },
- },
- };
- const resp = await http.fetch(reqUrl, {
- method: "POST",
- body: orderReq,
- headers: getMerchantAuthHeader(merchantBackend),
- });
- const r = await readSuccessResponseJsonOrThrow(resp, codecForAny());
+ const merchantClient = new TalerMerchantInstanceHttpClient(
+ merchantBackend.baseUrl,
+ http,
+ );
+ const r = succeedOrThrow(
+ await merchantClient.createOrder(merchantBackend.authToken as AccessToken, {
+ order: {
+ amount: amount as AmountString,
+ summary,
+ fulfillment_url: fulfillmentUrl,
+ refund_deadline: { t_s: t },
+ wire_transfer_deadline: { t_s: t },
+ },
+ }),
+ );
const orderId = r.order_id;
if (!orderId) {
throw Error("no order id in response");
@@ -248,20 +226,21 @@ async function createOrder(
return { orderId };
}
-/**
- * FIXME: User TalerMerchantInstanceHttpClient instead.
- */
async function checkPayment(
http: HttpRequestLibrary,
merchantBackend: MerchantBackendInfo,
orderId: string,
): Promise<CheckPaymentResponse> {
- const reqUrl = new URL(`private/orders/${orderId}`, merchantBackend.baseUrl);
- reqUrl.searchParams.set("order_id", orderId);
- const resp = await http.fetch(reqUrl.href, {
- headers: getMerchantAuthHeader(merchantBackend),
- });
- return readSuccessResponseJsonOrThrow(resp, codecForCheckPaymentResponse());
+ const merchantClient = new TalerMerchantInstanceHttpClient(
+ merchantBackend.baseUrl,
+ http,
+ );
+ return succeedOrThrow(
+ await merchantClient.getOrderDetails(
+ merchantBackend.authToken as AccessToken,
+ orderId,
+ ),
+ );
}
interface MakePaymentResult {