From 4ffca702853771bb3807f3881d710b3fbb6d6191 Mon Sep 17 00:00:00 2001 From: Florian Dold Date: Tue, 9 Jan 2024 18:37:43 +0100 Subject: -misc. minor fixes, docs --- .../src/operations/pay-merchant.ts | 48 +++++++++++ .../taler-wallet-core/src/operations/refresh.ts | 57 +++++++++++-- .../taler-wallet-core/src/util/promiseUtils.ts | 5 ++ packages/taler-wallet-core/src/wallet.ts | 95 +--------------------- 4 files changed, 106 insertions(+), 99 deletions(-) (limited to 'packages/taler-wallet-core') diff --git a/packages/taler-wallet-core/src/operations/pay-merchant.ts b/packages/taler-wallet-core/src/operations/pay-merchant.ts index 5d58f4c2f..a81311702 100644 --- a/packages/taler-wallet-core/src/operations/pay-merchant.ts +++ b/packages/taler-wallet-core/src/operations/pay-merchant.ts @@ -30,11 +30,13 @@ import { AbsoluteTime, AmountJson, Amounts, + AmountString, codecForAbortResponse, codecForMerchantContractTerms, codecForMerchantOrderRefundPickupResponse, codecForMerchantOrderStatusPaid, codecForMerchantPayResponse, + codecForMerchantPostOrderResponse, codecForProposal, CoinDepositPermission, CoinRefreshRequest, @@ -53,12 +55,15 @@ import { MerchantCoinRefundStatus, MerchantContractTerms, MerchantPayResponse, + MerchantUsingTemplateDetails, NotificationType, + parsePayTemplateUri, parsePayUri, parseTalerUri, PayCoinSelection, PreparePayResult, PreparePayResultType, + PreparePayTemplateRequest, randomBytes, RefreshReason, SharePaymentResult, @@ -1209,6 +1214,49 @@ export async function preparePayForUri( return checkPaymentByProposalId(ws, proposalId, uriResult.sessionId); } +export async function preparePayForTemplate( + ws: InternalWalletState, + req: PreparePayTemplateRequest, +): Promise { + const url = parsePayTemplateUri(req.talerPayTemplateUri); + const templateDetails: MerchantUsingTemplateDetails = {}; + if (!url) { + throw Error("invalid taler-template URI"); + } + if ( + url.templateParams.amount !== undefined && + typeof url.templateParams.amount === "string" + ) { + templateDetails.amount = (req.templateParams.amount ?? + url.templateParams.amount) as AmountString | undefined; + } + if ( + url.templateParams.summary !== undefined && + typeof url.templateParams.summary === "string" + ) { + templateDetails.summary = + req.templateParams.summary ?? url.templateParams.summary; + } + const reqUrl = new URL(`templates/${url.templateId}`, url.merchantBaseUrl); + const httpReq = await ws.http.fetch(reqUrl.href, { + method: "POST", + body: templateDetails, + }); + const resp = await readSuccessResponseJsonOrThrow( + httpReq, + codecForMerchantPostOrderResponse(), + ); + + const payUri = stringifyPayUri({ + merchantBaseUrl: url.merchantBaseUrl, + orderId: resp.order_id, + sessionId: "", + claimToken: resp.token, + }); + + return await preparePayForUri(ws, payUri); +} + /** * Generate deposit permissions for a purchase. * diff --git a/packages/taler-wallet-core/src/operations/refresh.ts b/packages/taler-wallet-core/src/operations/refresh.ts index a8bcb28d1..390433f66 100644 --- a/packages/taler-wallet-core/src/operations/refresh.ts +++ b/packages/taler-wallet-core/src/operations/refresh.ts @@ -36,6 +36,7 @@ import { ExchangeProtocolVersion, ExchangeRefreshRevealRequest, fnutil, + ForceRefreshRequest, getErrorDetailFromException, getRandomBytes, HashCodeString, @@ -79,8 +80,6 @@ import { } from "../db.js"; import { getCandidateWithdrawalDenomsTx, - isWithdrawableDenom, - PendingTaskType, RefreshSessionRecord, timestampPreciseToDb, timestampProtocolFromDb, @@ -93,13 +92,8 @@ import { import { assertUnreachable } from "../util/assertUnreachable.js"; import { selectWithdrawalDenominations } from "../util/coinSelection.js"; import { checkDbInvariant } from "../util/invariants.js"; +import { GetReadOnlyAccess, GetReadWriteAccess } from "../util/query.js"; import { - DbReadWriteTransaction, - GetReadOnlyAccess, - GetReadWriteAccess, -} from "../util/query.js"; -import { - constructTaskIdentifier, makeCoinAvailable, makeCoinsVisible, TaskRunResult, @@ -1449,3 +1443,50 @@ export async function abortRefreshGroup( ws.workAvailable.trigger(); notifyTransition(ws, transactionId, transitionInfo); } + +export async function forceRefresh( + ws: InternalWalletState, + req: ForceRefreshRequest, +): Promise<{ refreshGroupId: RefreshGroupId }> { + if (req.coinPubList.length == 0) { + throw Error("refusing to create empty refresh group"); + } + const refreshGroupId = await ws.db + .mktx((x) => [ + x.refreshGroups, + x.coinAvailability, + x.denominations, + x.coins, + ]) + .runReadWrite(async (tx) => { + let coinPubs: CoinRefreshRequest[] = []; + for (const c of req.coinPubList) { + const coin = await tx.coins.get(c); + if (!coin) { + throw Error(`coin (pubkey ${c}) not found`); + } + const denom = await ws.getDenomInfo( + ws, + tx, + coin.exchangeBaseUrl, + coin.denomPubHash, + ); + checkDbInvariant(!!denom); + coinPubs.push({ + coinPub: c, + amount: denom?.value, + }); + } + return await createRefreshGroup( + ws, + tx, + Amounts.currencyOf(coinPubs[0].amount), + coinPubs, + RefreshReason.Manual, + ); + }); + + return { + refreshGroupId, + }; +} diff --git a/packages/taler-wallet-core/src/util/promiseUtils.ts b/packages/taler-wallet-core/src/util/promiseUtils.ts index 23f1c06a5..df4cc343b 100644 --- a/packages/taler-wallet-core/src/util/promiseUtils.ts +++ b/packages/taler-wallet-core/src/util/promiseUtils.ts @@ -14,6 +14,11 @@ TALER; see the file COPYING. If not, see */ +/** + * An opened promise. + * + * @see {@link openPromise} + */ export interface OpenedPromise { promise: Promise; resolve: (val: T) => void; diff --git a/packages/taler-wallet-core/src/wallet.ts b/packages/taler-wallet-core/src/wallet.ts index ff1f991dd..da34ff37f 100644 --- a/packages/taler-wallet-core/src/wallet.ts +++ b/packages/taler-wallet-core/src/wallet.ts @@ -28,7 +28,6 @@ import { AmountString, Amounts, CoinDumpJson, - CoinRefreshRequest, CoinStatus, CoreApiResponse, CreateStoredBackupResponse, @@ -41,12 +40,10 @@ import { KnownBankAccounts, KnownBankAccountsInfo, Logger, - MerchantUsingTemplateDetails, NotificationType, PrepareWithdrawExchangeRequest, PrepareWithdrawExchangeResponse, RecoverStoredBackupRequest, - RefreshReason, ScopeType, StoredBackupList, TalerError, @@ -56,7 +53,6 @@ import { TestingWaitTransactionRequest, TransactionState, TransactionType, - URL, ValidateIbanResponse, WalletCoreVersion, WalletNotification, @@ -97,7 +93,6 @@ import { codecForIntegrationTestV2Args, codecForListExchangesForScopedCurrencyRequest, codecForListKnownBankAccounts, - codecForMerchantPostOrderResponse, codecForPrepareDepositRequest, codecForPreparePayRequest, codecForPreparePayTemplateRequest, @@ -123,12 +118,10 @@ import { codecForUserAttentionsRequest, codecForValidateIbanRequest, codecForWithdrawTestBalance, - constructPayUri, durationFromSpec, durationMin, getErrorDetailFromException, j2s, - parsePayTemplateUri, parsePaytoUri, parseTalerUri, sampleWalletCoreTransactions, @@ -136,7 +129,6 @@ import { validateIban, } from "@gnu-taler/taler-util"; 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, @@ -211,6 +203,7 @@ import { computeRefundTransactionState, confirmPay, getContractTermsDetails, + preparePayForTemplate, preparePayForUri, processPurchase, sharePayment, @@ -247,6 +240,7 @@ import { autoRefresh, computeRefreshTransactionState, createRefreshGroup, + forceRefresh, processRefreshGroup, } from "./operations/refresh.js"; import { @@ -1115,46 +1109,7 @@ async function dispatchRequestInternal( } case WalletApiOperation.PreparePayForTemplate: { const req = codecForPreparePayTemplateRequest().decode(payload); - const url = parsePayTemplateUri(req.talerPayTemplateUri); - const templateDetails: MerchantUsingTemplateDetails = {}; - if (!url) { - throw Error("invalid taler-template URI"); - } - if ( - url.templateParams.amount !== undefined && - typeof url.templateParams.amount === "string" - ) { - templateDetails.amount = (req.templateParams.amount ?? - url.templateParams.amount) as AmountString | undefined; - } - if ( - url.templateParams.summary !== undefined && - typeof url.templateParams.summary === "string" - ) { - templateDetails.summary = - req.templateParams.summary ?? url.templateParams.summary; - } - const reqUrl = new URL( - `templates/${url.templateId}`, - url.merchantBaseUrl, - ); - const httpReq = await ws.http.fetch(reqUrl.href, { - method: "POST", - body: templateDetails, - }); - const resp = await readSuccessResponseJsonOrThrow( - httpReq, - codecForMerchantPostOrderResponse(), - ); - - const payUri = constructPayUri( - url.merchantBaseUrl, - resp.order_id, - "", - resp.token, - ); - - return await preparePayForUri(ws, payUri); + return preparePayForTemplate(ws, req); } case WalletApiOperation.ConfirmPay: { const req = codecForConfirmPayRequest().decode(payload); @@ -1205,49 +1160,7 @@ async function dispatchRequestInternal( return { transactions: sampleWalletCoreTransactions }; case WalletApiOperation.ForceRefresh: { const req = codecForForceRefreshRequest().decode(payload); - if (req.coinPubList.length == 0) { - throw Error("refusing to create empty refresh group"); - } - const refreshGroupId = await ws.db - .mktx((x) => [ - x.refreshGroups, - x.coinAvailability, - x.denominations, - x.coins, - ]) - .runReadWrite(async (tx) => { - let coinPubs: CoinRefreshRequest[] = []; - for (const c of req.coinPubList) { - const coin = await tx.coins.get(c); - if (!coin) { - throw Error(`coin (pubkey ${c}) not found`); - } - const denom = await ws.getDenomInfo( - ws, - tx, - coin.exchangeBaseUrl, - coin.denomPubHash, - ); - checkDbInvariant(!!denom); - coinPubs.push({ - coinPub: c, - amount: denom?.value, - }); - } - return await createRefreshGroup( - ws, - tx, - Amounts.currencyOf(coinPubs[0].amount), - coinPubs, - RefreshReason.Manual, - ); - }); - processRefreshGroup(ws, refreshGroupId.refreshGroupId).catch((x) => { - logger.error(x); - }); - return { - refreshGroupId, - }; + return await forceRefresh(ws, req); } case WalletApiOperation.PrepareReward: { const req = codecForPrepareRewardRequest().decode(payload); -- cgit v1.2.3