From e671880b9e11b020c3fc797fb45e6e4b8ee3ee62 Mon Sep 17 00:00:00 2001 From: Florian Dold Date: Mon, 5 Jun 2023 13:33:14 +0200 Subject: [PATCH] wallet-core: use long-polling for P2P kyc --- package.json | 2 +- packages/idb-bridge/package.json | 2 +- packages/taler-harness/package.json | 2 +- packages/taler-util/package.json | 2 +- packages/taler-util/src/transactions-types.ts | 4 + packages/taler-wallet-cli/package.json | 2 +- packages/taler-wallet-core/package.json | 2 +- packages/taler-wallet-core/src/db.ts | 4 + .../src/operations/common.ts | 1 - .../src/operations/pay-peer-common.ts | 8 + .../src/operations/pay-peer-pull-credit.ts | 200 ++++++++++++++--- .../src/operations/pay-peer-push-credit.ts | 209 +++++++++++++++--- .../src/operations/transactions.ts | 40 +++- packages/taler-wallet-embedded/package.json | 2 +- packages/web-util/package.json | 2 +- pnpm-lock.yaml | 36 +-- 16 files changed, 419 insertions(+), 99 deletions(-) diff --git a/package.json b/package.json index 058d2d7f8..9ce6d628e 100644 --- a/package.json +++ b/package.json @@ -15,6 +15,6 @@ "eslint": "^8.29.0", "eslint-config-prettier": "^8.5.0", "nx": "15.0.1", - "prettier": "^2.7.1" + "prettier": "^2.8.8" } } diff --git a/packages/idb-bridge/package.json b/packages/idb-bridge/package.json index 63f1a5bbf..fc325cf35 100644 --- a/packages/idb-bridge/package.json +++ b/packages/idb-bridge/package.json @@ -25,7 +25,7 @@ "@types/node": "^18.11.17", "ava": "^4.3.3", "esm": "^3.2.25", - "prettier": "^2.5.1", + "prettier": "^2.8.8", "rimraf": "^3.0.2", "typescript": "^4.9.4" }, diff --git a/packages/taler-harness/package.json b/packages/taler-harness/package.json index b1def3b9a..e3e807cc2 100644 --- a/packages/taler-harness/package.json +++ b/packages/taler-harness/package.json @@ -33,7 +33,7 @@ "devDependencies": { "@types/node": "^18.11.17", "esbuild": "^0.17.7", - "prettier": "^2.5.1", + "prettier": "^2.8.8", "rimraf": "^3.0.2", "typescript": "^4.9.4" }, diff --git a/packages/taler-util/package.json b/packages/taler-util/package.json index 3a6c5a0a8..93a77b22b 100644 --- a/packages/taler-util/package.json +++ b/packages/taler-util/package.json @@ -62,7 +62,7 @@ "@types/node": "^18.11.17", "ava": "^4.3.3", "esbuild": "^0.17.7", - "prettier": "^2.5.1", + "prettier": "^2.8.8", "rimraf": "^3.0.2", "typescript": "^4.9.4" }, diff --git a/packages/taler-util/src/transactions-types.ts b/packages/taler-util/src/transactions-types.ts index 5f5b9d112..82d847e80 100644 --- a/packages/taler-util/src/transactions-types.ts +++ b/packages/taler-util/src/transactions-types.ts @@ -345,6 +345,8 @@ export interface TransactionPeerPullCredit extends TransactionCommon { * URI to send to the other party. */ talerUri: string; + + kycUrl: string | undefined; } /** @@ -413,6 +415,8 @@ export interface TransactionPeerPushCredit extends TransactionCommon { * Amount that actually was (or will be) added to the wallet's balance. */ amountEffective: AmountString; + + kycUrl: string | undefined; } export enum PaymentStatus { diff --git a/packages/taler-wallet-cli/package.json b/packages/taler-wallet-cli/package.json index 1a5364766..0daadd5e1 100644 --- a/packages/taler-wallet-cli/package.json +++ b/packages/taler-wallet-cli/package.json @@ -32,7 +32,7 @@ ], "devDependencies": { "@types/node": "^18.11.17", - "prettier": "^2.5.1", + "prettier": "^2.8.8", "rimraf": "^3.0.2", "typedoc": "^0.23.16", "typescript": "^4.9.4" diff --git a/packages/taler-wallet-core/package.json b/packages/taler-wallet-core/package.json index 05fe89fd2..46e1c3667 100644 --- a/packages/taler-wallet-core/package.json +++ b/packages/taler-wallet-core/package.json @@ -64,7 +64,7 @@ "eslint-plugin-react-hooks": "^4.3.0", "jed": "^1.1.1", "po2json": "^0.4.5", - "prettier": "^2.5.1", + "prettier": "^2.8.8", "rimraf": "^3.0.2", "typedoc": "^0.23.16", "typescript": "^4.9.4" diff --git a/packages/taler-wallet-core/src/db.ts b/packages/taler-wallet-core/src/db.ts index 0e5d1c100..3f19822c8 100644 --- a/packages/taler-wallet-core/src/db.ts +++ b/packages/taler-wallet-core/src/db.ts @@ -1921,6 +1921,8 @@ export interface PeerPullPaymentInitiationRecord { kycInfo?: KycPendingInfo; + kycUrl?: string; + withdrawalGroupId: string | undefined; } @@ -1989,6 +1991,8 @@ export interface PeerPushPaymentIncomingRecord { currency: string | undefined; kycInfo?: KycPendingInfo; + + kycUrl?: string; } export enum PeerPullDebitRecordStatus { diff --git a/packages/taler-wallet-core/src/operations/common.ts b/packages/taler-wallet-core/src/operations/common.ts index 203bf6788..ef5c54002 100644 --- a/packages/taler-wallet-core/src/operations/common.ts +++ b/packages/taler-wallet-core/src/operations/common.ts @@ -36,7 +36,6 @@ import { TalerErrorDetail, TombstoneIdStr, TransactionIdStr, - TransactionType, } from "@gnu-taler/taler-util"; import { WalletStoresV1, diff --git a/packages/taler-wallet-core/src/operations/pay-peer-common.ts b/packages/taler-wallet-core/src/operations/pay-peer-common.ts index 4b1dd31a5..717b25f49 100644 --- a/packages/taler-wallet-core/src/operations/pay-peer-common.ts +++ b/packages/taler-wallet-core/src/operations/pay-peer-common.ts @@ -25,19 +25,26 @@ import { Codec, CoinPublicKeyString, CoinStatus, + HttpStatusCode, Logger, + NotificationType, PayPeerInsufficientBalanceDetails, + TalerError, + TalerErrorCode, TalerProtocolTimestamp, UnblindedSignature, buildCodecForObject, codecForAmountString, codecForTimestamp, codecOptional, + j2s, strcmp, } from "@gnu-taler/taler-util"; import { SpendCoinDetails } from "../crypto/cryptoImplementation.js"; import { DenominationRecord, + KycPendingInfo, + KycUserType, PeerPushPaymentCoinSelection, ReserveRecord, } from "../db.js"; @@ -45,6 +52,7 @@ import { InternalWalletState } from "../internal-wallet-state.js"; import { checkDbInvariant } from "../util/invariants.js"; import { getPeerPaymentBalanceDetailsInTx } from "./balance.js"; import { getTotalRefreshCost } from "./refresh.js"; +import { OperationAttemptLongpollResult, OperationAttemptResult, OperationAttemptResultType } from "../util/retries.js"; const logger = new Logger("operations/peer-to-peer.ts"); diff --git a/packages/taler-wallet-core/src/operations/pay-peer-pull-credit.ts b/packages/taler-wallet-core/src/operations/pay-peer-pull-credit.ts index b9c9728a1..333202a69 100644 --- a/packages/taler-wallet-core/src/operations/pay-peer-pull-credit.ts +++ b/packages/taler-wallet-core/src/operations/pay-peer-pull-credit.ts @@ -26,6 +26,7 @@ import { InitiatePeerPullCreditRequest, InitiatePeerPullCreditResponse, Logger, + TalerErrorCode, TalerPreciseTimestamp, TransactionAction, TransactionMajorState, @@ -33,12 +34,14 @@ import { TransactionState, TransactionType, WalletAccountMergeFlags, + WalletKycUuid, codecForAny, codecForWalletKycUuid, constructPayPullUri, encodeCrock, getRandomBytes, j2s, + makeErrorDetail, } from "@gnu-taler/taler-util"; import { readSuccessResponseJsonOrErrorCode, @@ -46,6 +49,8 @@ import { throwUnexpectedRequestError, } from "@gnu-taler/taler-util/http"; import { + KycPendingInfo, + KycUserType, PeerPullPaymentInitiationRecord, PeerPullPaymentInitiationStatus, WithdrawalGroupStatus, @@ -167,6 +172,75 @@ export async function queryPurseForPeerPullCredit( }; } +async function longpollKycStatus( + ws: InternalWalletState, + pursePub: string, + exchangeUrl: string, + kycInfo: KycPendingInfo, + userType: KycUserType, +): Promise { + const transactionId = constructTransactionIdentifier({ + tag: TransactionType.PeerPullCredit, + pursePub, + }); + const retryTag = constructTaskIdentifier({ + tag: PendingTaskType.PeerPullCredit, + pursePub, + }); + + runLongpollAsync(ws, retryTag, async (ct) => { + const url = new URL( + `kyc-check/${kycInfo.requirementRow}/${kycInfo.paytoHash}/${userType}`, + exchangeUrl, + ); + url.searchParams.set("timeout_ms", "10000"); + logger.info(`kyc url ${url.href}`); + const kycStatusRes = await ws.http.fetch(url.href, { + method: "GET", + cancellationToken: ct, + }); + if ( + kycStatusRes.status === HttpStatusCode.Ok || + //FIXME: NoContent is not expected https://docs.taler.net/core/api-exchange.html#post--purses-$PURSE_PUB-merge + // remove after the exchange is fixed or clarified + kycStatusRes.status === HttpStatusCode.NoContent + ) { + const transitionInfo = await ws.db + .mktx((x) => [x.peerPullPaymentInitiations]) + .runReadWrite(async (tx) => { + const peerIni = await tx.peerPullPaymentInitiations.get( + pursePub, + ); + if (!peerIni) { + return; + } + if ( + peerIni.status !== PeerPullPaymentInitiationStatus.PendingMergeKycRequired + ) { + return; + } + const oldTxState = computePeerPullCreditTransactionState(peerIni); + peerIni.status = PeerPullPaymentInitiationStatus.PendingCreatePurse; + const newTxState = computePeerPullCreditTransactionState(peerIni); + await tx.peerPullPaymentInitiations.put(peerIni); + return { oldTxState, newTxState }; + }); + notifyTransition(ws, transactionId, transitionInfo); + return { ready: true }; + } else if (kycStatusRes.status === HttpStatusCode.Accepted) { + // FIXME: Do we have to update the URL here? + return { ready: false }; + } else { + throw Error( + `unexpected response from kyc-check (${kycStatusRes.status})`, + ); + } + }); + return { + type: OperationAttemptResultType.Longpoll, + }; +} + export async function processPeerPullCredit( ws: InternalWalletState, pursePub: string, @@ -233,20 +307,16 @@ export async function processPeerPullCredit( type: OperationAttemptResultType.Longpoll, }; case PeerPullPaymentInitiationStatus.PendingMergeKycRequired: { - const transactionId = constructTransactionIdentifier({ - tag: TransactionType.PeerPullCredit, - pursePub: pullIni.pursePub, - }); - if (pullIni.kycInfo) { - await checkWithdrawalKycStatus( - ws, - pullIni.exchangeBaseUrl, - transactionId, - pullIni.kycInfo, - "individual", - ); + if (!pullIni.kycInfo) { + throw Error("invalid state, kycInfo required"); } - break; + return await longpollKycStatus( + ws, + pursePub, + pullIni.exchangeBaseUrl, + pullIni.kycInfo, + "individual", + ); } case PeerPullPaymentInitiationStatus.PendingCreatePurse: break; @@ -325,26 +395,7 @@ export async function processPeerPullCredit( const respJson = await httpResp.json(); const kycPending = codecForWalletKycUuid().decode(respJson); logger.info(`kyc uuid response: ${j2s(kycPending)}`); - - await ws.db - .mktx((x) => [x.peerPullPaymentInitiations]) - .runReadWrite(async (tx) => { - const peerIni = await tx.peerPullPaymentInitiations.get(pursePub); - if (!peerIni) { - return; - } - peerIni.kycInfo = { - paytoHash: kycPending.h_payto, - requirementRow: kycPending.requirement_row, - }; - peerIni.status = - PeerPullPaymentInitiationStatus.PendingMergeKycRequired; - await tx.peerPullPaymentInitiations.put(peerIni); - }); - return { - type: OperationAttemptResultType.Pending, - result: undefined, - }; + return processPeerPullCreditKycRequired(ws, pullIni, kycPending); } const resp = await readSuccessResponseJsonOrThrow(httpResp, codecForAny()); @@ -368,6 +419,89 @@ export async function processPeerPullCredit( }; } +async function processPeerPullCreditKycRequired( + ws: InternalWalletState, + peerIni: PeerPullPaymentInitiationRecord, + kycPending: WalletKycUuid, +): Promise { + const transactionId = constructTransactionIdentifier({ + tag: TransactionType.PeerPullCredit, + pursePub: peerIni.pursePub, + }); + const { pursePub } = peerIni; + + const userType = "individual"; + const url = new URL( + `kyc-check/${kycPending.requirement_row}/${kycPending.h_payto}/${userType}`, + peerIni.exchangeBaseUrl, + ); + + logger.info(`kyc url ${url.href}`); + const kycStatusRes = await ws.http.fetch(url.href, { + method: "GET", + }); + + if ( + kycStatusRes.status === HttpStatusCode.Ok || + //FIXME: NoContent is not expected https://docs.taler.net/core/api-exchange.html#post--purses-$PURSE_PUB-merge + // remove after the exchange is fixed or clarified + kycStatusRes.status === HttpStatusCode.NoContent + ) { + logger.warn("kyc requested, but already fulfilled"); + return { + type: OperationAttemptResultType.Finished, + result: undefined, + }; + } else if (kycStatusRes.status === HttpStatusCode.Accepted) { + const kycStatus = await kycStatusRes.json(); + logger.info(`kyc status: ${j2s(kycStatus)}`); + const { transitionInfo, result } = await ws.db + .mktx((x) => [x.peerPullPaymentInitiations]) + .runReadWrite(async (tx) => { + const peerInc = await tx.peerPullPaymentInitiations.get( + pursePub, + ); + if (!peerInc) { + return { + transitionInfo: undefined, + result: OperationAttemptResult.finishedEmpty(), + }; + } + const oldTxState = computePeerPullCreditTransactionState(peerInc); + peerInc.kycInfo = { + paytoHash: kycPending.h_payto, + requirementRow: kycPending.requirement_row, + }; + peerInc.kycUrl = kycStatus.kyc_url; + peerInc.status = PeerPullPaymentInitiationStatus.PendingMergeKycRequired; + const newTxState = computePeerPullCreditTransactionState(peerInc); + await tx.peerPullPaymentInitiations.put(peerInc); + // We'll remove this eventually! New clients should rely on the + // kycUrl field of the transaction, not the error code. + const res: OperationAttemptResult = { + type: OperationAttemptResultType.Error, + errorDetail: makeErrorDetail( + TalerErrorCode.WALLET_WITHDRAWAL_KYC_REQUIRED, + { + kycUrl: kycStatus.kyc_url, + }, + ), + }; + return { + transitionInfo: { oldTxState, newTxState }, + result: res, + }; + }); + notifyTransition(ws, transactionId, transitionInfo); + return { + type: OperationAttemptResultType.Pending, + result: undefined, + }; + } else { + throw Error(`unexpected response from kyc-check (${kycStatusRes.status})`); + } +} + /** * Check fees and available exchanges for a peer push payment initiation. */ diff --git a/packages/taler-wallet-core/src/operations/pay-peer-push-credit.ts b/packages/taler-wallet-core/src/operations/pay-peer-push-credit.ts index 69e0f3c27..91b0b6022 100644 --- a/packages/taler-wallet-core/src/operations/pay-peer-push-credit.ts +++ b/packages/taler-wallet-core/src/operations/pay-peer-push-credit.ts @@ -44,10 +44,16 @@ import { TransactionMajorState, TransactionMinorState, TransactionState, + TalerError, + TalerErrorCode, + WalletKycUuid, + makeErrorDetail, } from "@gnu-taler/taler-util"; import { readSuccessResponseJsonOrThrow } from "@gnu-taler/taler-util/http"; import { InternalWalletState, + KycPendingInfo, + KycUserType, PeerPullDebitRecordStatus, PeerPushPaymentIncomingRecord, PeerPushPaymentIncomingStatus, @@ -62,9 +68,12 @@ import { queryCoinInfosForSelection, talerPaytoFromExchangeReserve, } from "./pay-peer-common.js"; -import { constructTransactionIdentifier, notifyTransition, stopLongpolling } from "./transactions.js"; import { - checkWithdrawalKycStatus, + constructTransactionIdentifier, + notifyTransition, + stopLongpolling, +} from "./transactions.js"; +import { getExchangeWithdrawalInfo, internalCreateWithdrawalGroup, } from "./withdraw.js"; @@ -75,6 +84,7 @@ import { constructTaskIdentifier, } from "../util/retries.js"; import { assertUnreachable } from "../util/assertUnreachable.js"; +import { runLongpollAsync } from "./common.js"; const logger = new Logger("pay-peer-push-credit.ts"); @@ -215,6 +225,156 @@ export async function preparePeerPushCredit( }; } +async function longpollKycStatus( + ws: InternalWalletState, + peerPushPaymentIncomingId: string, + exchangeUrl: string, + kycInfo: KycPendingInfo, + userType: KycUserType, +): Promise { + const transactionId = constructTransactionIdentifier({ + tag: TransactionType.PeerPushCredit, + peerPushPaymentIncomingId, + }); + const retryTag = constructTaskIdentifier({ + tag: PendingTaskType.PeerPushCredit, + peerPushPaymentIncomingId, + }); + + runLongpollAsync(ws, retryTag, async (ct) => { + const url = new URL( + `kyc-check/${kycInfo.requirementRow}/${kycInfo.paytoHash}/${userType}`, + exchangeUrl, + ); + url.searchParams.set("timeout_ms", "10000"); + logger.info(`kyc url ${url.href}`); + const kycStatusRes = await ws.http.fetch(url.href, { + method: "GET", + cancellationToken: ct, + }); + if ( + kycStatusRes.status === HttpStatusCode.Ok || + //FIXME: NoContent is not expected https://docs.taler.net/core/api-exchange.html#post--purses-$PURSE_PUB-merge + // remove after the exchange is fixed or clarified + kycStatusRes.status === HttpStatusCode.NoContent + ) { + const transitionInfo = await ws.db + .mktx((x) => [x.peerPushPaymentIncoming]) + .runReadWrite(async (tx) => { + const peerInc = await tx.peerPushPaymentIncoming.get( + peerPushPaymentIncomingId, + ); + if (!peerInc) { + return; + } + if ( + peerInc.status !== + PeerPushPaymentIncomingStatus.PendingMergeKycRequired + ) { + return; + } + const oldTxState = computePeerPushCreditTransactionState(peerInc); + peerInc.status = PeerPushPaymentIncomingStatus.PendingMerge; + const newTxState = computePeerPushCreditTransactionState(peerInc); + await tx.peerPushPaymentIncoming.put(peerInc); + return { oldTxState, newTxState }; + }); + notifyTransition(ws, transactionId, transitionInfo); + return { ready: true }; + } else if (kycStatusRes.status === HttpStatusCode.Accepted) { + // FIXME: Do we have to update the URL here? + return { ready: false }; + } else { + throw Error( + `unexpected response from kyc-check (${kycStatusRes.status})`, + ); + } + }); + return { + type: OperationAttemptResultType.Longpoll, + }; +} + +async function processPeerPushCreditKycRequired( + ws: InternalWalletState, + peerInc: PeerPushPaymentIncomingRecord, + kycPending: WalletKycUuid, +): Promise { + const transactionId = constructTransactionIdentifier({ + tag: TransactionType.PeerPushCredit, + peerPushPaymentIncomingId: peerInc.peerPushPaymentIncomingId, + }); + const { peerPushPaymentIncomingId } = peerInc; + + const userType = "individual"; + const url = new URL( + `kyc-check/${kycPending.requirement_row}/${kycPending.h_payto}/${userType}`, + peerInc.exchangeBaseUrl, + ); + + logger.info(`kyc url ${url.href}`); + const kycStatusRes = await ws.http.fetch(url.href, { + method: "GET", + }); + + if ( + kycStatusRes.status === HttpStatusCode.Ok || + //FIXME: NoContent is not expected https://docs.taler.net/core/api-exchange.html#post--purses-$PURSE_PUB-merge + // remove after the exchange is fixed or clarified + kycStatusRes.status === HttpStatusCode.NoContent + ) { + logger.warn("kyc requested, but already fulfilled"); + return { + type: OperationAttemptResultType.Finished, + result: undefined, + }; + } else if (kycStatusRes.status === HttpStatusCode.Accepted) { + const kycStatus = await kycStatusRes.json(); + logger.info(`kyc status: ${j2s(kycStatus)}`); + const { transitionInfo, result } = await ws.db + .mktx((x) => [x.peerPushPaymentIncoming]) + .runReadWrite(async (tx) => { + const peerInc = await tx.peerPushPaymentIncoming.get( + peerPushPaymentIncomingId, + ); + if (!peerInc) { + return { + transitionInfo: undefined, + result: OperationAttemptResult.finishedEmpty(), + }; + } + const oldTxState = computePeerPushCreditTransactionState(peerInc); + peerInc.kycInfo = { + paytoHash: kycPending.h_payto, + requirementRow: kycPending.requirement_row, + }; + peerInc.kycUrl = kycStatus.kyc_url; + peerInc.status = PeerPushPaymentIncomingStatus.PendingMergeKycRequired; + const newTxState = computePeerPushCreditTransactionState(peerInc); + await tx.peerPushPaymentIncoming.put(peerInc); + // We'll remove this eventually! New clients should rely on the + // kycUrl field of the transaction, not the error code. + const res: OperationAttemptResult = { + type: OperationAttemptResultType.Error, + errorDetail: makeErrorDetail( + TalerErrorCode.WALLET_WITHDRAWAL_KYC_REQUIRED, + { + kycUrl: kycStatus.kyc_url, + }, + ), + }; + return { + transitionInfo: { oldTxState, newTxState }, + result: res, + }; + }); + notifyTransition(ws, transactionId, transitionInfo); + return result; + } else { + throw Error(`unexpected response from kyc-check (${kycStatusRes.status})`); + } +} + export async function processPeerPushCredit( ws: InternalWalletState, peerPushPaymentIncomingId: string, @@ -246,17 +406,15 @@ export async function processPeerPushCredit( const amount = Amounts.parseOrThrow(contractTerms.amount); if ( - peerInc.status === PeerPushPaymentIncomingStatus.PendingMergeKycRequired && - peerInc.kycInfo + peerInc.status === PeerPushPaymentIncomingStatus.PendingMergeKycRequired ) { - const txId = constructTransactionIdentifier({ - tag: TransactionType.PeerPushCredit, - peerPushPaymentIncomingId: peerInc.peerPushPaymentIncomingId, - }); - await checkWithdrawalKycStatus( + if (!peerInc.kycInfo) { + throw Error("invalid state, kycInfo required"); + } + return await longpollKycStatus( ws, + peerPushPaymentIncomingId, peerInc.exchangeBaseUrl, - txId, peerInc.kycInfo, "individual", ); @@ -298,33 +456,16 @@ export async function processPeerPushCredit( reserve_sig: sigRes.accountSig, }; - const mergeHttpResp = await ws.http.postJson(mergePurseUrl.href, mergeReq); + const mergeHttpResp = await ws.http.fetch(mergePurseUrl.href, { + method: "POST", + body: mergeReq, + }); if (mergeHttpResp.status === HttpStatusCode.UnavailableForLegalReasons) { const respJson = await mergeHttpResp.json(); const kycPending = codecForWalletKycUuid().decode(respJson); logger.info(`kyc uuid response: ${j2s(kycPending)}`); - - await ws.db - .mktx((x) => [x.peerPushPaymentIncoming]) - .runReadWrite(async (tx) => { - const peerInc = await tx.peerPushPaymentIncoming.get( - peerPushPaymentIncomingId, - ); - if (!peerInc) { - return; - } - peerInc.kycInfo = { - paytoHash: kycPending.h_payto, - requirementRow: kycPending.requirement_row, - }; - peerInc.status = PeerPushPaymentIncomingStatus.PendingMergeKycRequired; - await tx.peerPushPaymentIncoming.put(peerInc); - }); - return { - type: OperationAttemptResultType.Pending, - result: undefined, - }; + processPeerPushCreditKycRequired(ws, peerInc, kycPending); } logger.trace(`merge request: ${j2s(mergeReq)}`); @@ -412,7 +553,6 @@ export async function confirmPeerPushCredit( }; } - export async function processPeerPullDebit( ws: InternalWalletState, peerPullPaymentIncomingId: string, @@ -483,7 +623,6 @@ export async function processPeerPullDebit( }; } - export async function suspendPeerPushCreditTransaction( ws: InternalWalletState, peerPushPaymentIncomingId: string, @@ -767,4 +906,4 @@ export function computePeerPushCreditTransactionActions( default: assertUnreachable(pushCreditRecord.status); } -} \ No newline at end of file +} diff --git a/packages/taler-wallet-core/src/operations/transactions.ts b/packages/taler-wallet-core/src/operations/transactions.ts index 1bd024d28..6fe0f1390 100644 --- a/packages/taler-wallet-core/src/operations/transactions.ts +++ b/packages/taler-wallet-core/src/operations/transactions.ts @@ -117,10 +117,38 @@ import { suspendWithdrawalTransaction, computeWithdrawalTransactionActions, } from "./withdraw.js"; -import { computePeerPullCreditTransactionState, computePeerPullCreditTransactionActions, suspendPeerPullCreditTransaction, failPeerPullCreditTransaction, resumePeerPullCreditTransaction, abortPeerPullCreditTransaction } from "./pay-peer-pull-credit.js"; -import { computePeerPullDebitTransactionState, computePeerPullDebitTransactionActions, suspendPeerPullDebitTransaction, failPeerPullDebitTransaction, resumePeerPullDebitTransaction, abortPeerPullDebitTransaction } from "./pay-peer-pull-debit.js"; -import { computePeerPushCreditTransactionState, computePeerPushCreditTransactionActions, suspendPeerPushCreditTransaction, failPeerPushCreditTransaction, resumePeerPushCreditTransaction, abortPeerPushCreditTransaction } from "./pay-peer-push-credit.js"; -import { computePeerPushDebitTransactionState, computePeerPushDebitTransactionActions, suspendPeerPushDebitTransaction, failPeerPushDebitTransaction, resumePeerPushDebitTransaction, abortPeerPushDebitTransaction } from "./pay-peer-push-debit.js"; +import { + computePeerPullCreditTransactionState, + computePeerPullCreditTransactionActions, + suspendPeerPullCreditTransaction, + failPeerPullCreditTransaction, + resumePeerPullCreditTransaction, + abortPeerPullCreditTransaction, +} from "./pay-peer-pull-credit.js"; +import { + computePeerPullDebitTransactionState, + computePeerPullDebitTransactionActions, + suspendPeerPullDebitTransaction, + failPeerPullDebitTransaction, + resumePeerPullDebitTransaction, + abortPeerPullDebitTransaction, +} from "./pay-peer-pull-debit.js"; +import { + computePeerPushCreditTransactionState, + computePeerPushCreditTransactionActions, + suspendPeerPushCreditTransaction, + failPeerPushCreditTransaction, + resumePeerPushCreditTransaction, + abortPeerPushCreditTransaction, +} from "./pay-peer-push-credit.js"; +import { + computePeerPushDebitTransactionState, + computePeerPushDebitTransactionActions, + suspendPeerPushDebitTransaction, + failPeerPushDebitTransaction, + resumePeerPushDebitTransaction, + abortPeerPushDebitTransaction, +} from "./pay-peer-push-debit.js"; const logger = new Logger("taler-wallet-core:transactions.ts"); @@ -510,6 +538,7 @@ function buildTransactionForPeerPullCredit( tag: TransactionType.PeerPullCredit, pursePub: pullCredit.pursePub, }), + kycUrl: pullCredit.kycUrl, ...(wsrOrt?.lastError ? { error: silentWithdrawalErrorForInvoice @@ -541,6 +570,7 @@ function buildTransactionForPeerPullCredit( tag: TransactionType.PeerPullCredit, pursePub: pullCredit.pursePub, }), + kycUrl: pullCredit.kycUrl, ...(pullCreditOrt?.lastError ? { error: pullCreditOrt.lastError } : {}), }; } @@ -573,6 +603,7 @@ function buildTransactionForPeerPushCredit( tag: TransactionType.PeerPushCredit, peerPushPaymentIncomingId: pushInc.peerPushPaymentIncomingId, }), + kycUrl: pushInc.kycUrl, ...(wsrOrt?.lastError ? { error: wsrOrt.lastError } : {}), }; } @@ -589,6 +620,7 @@ function buildTransactionForPeerPushCredit( expiration: peerContractTerms.purse_expiration, summary: peerContractTerms.summary, }, + kycUrl: pushInc.kycUrl, timestamp: pushInc.timestamp, transactionId: constructTransactionIdentifier({ tag: TransactionType.PeerPushCredit, diff --git a/packages/taler-wallet-embedded/package.json b/packages/taler-wallet-embedded/package.json index a57a4d6d7..0e8a13a82 100644 --- a/packages/taler-wallet-embedded/package.json +++ b/packages/taler-wallet-embedded/package.json @@ -29,7 +29,7 @@ "devDependencies": { "@types/node": "^18.11.17", "esbuild": "^0.17.7", - "prettier": "^2.5.1", + "prettier": "^2.8.8", "rimraf": "^3.0.2" }, "dependencies": { diff --git a/packages/web-util/package.json b/packages/web-util/package.json index 0041e73d0..c13e43965 100644 --- a/packages/web-util/package.json +++ b/packages/web-util/package.json @@ -53,7 +53,7 @@ "postcss-load-config": "^4.0.1", "preact": "10.11.3", "preact-render-to-string": "^5.2.6", - "prettier": "^2.5.1", + "prettier": "^2.8.8", "rimraf": "^3.0.2", "sass": "1.56.1", "swr": "2.0.3", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 6e705ee90..5c5e8feca 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -11,7 +11,7 @@ importers: eslint: ^8.29.0 eslint-config-prettier: ^8.5.0 nx: 15.0.1 - prettier: ^2.7.1 + prettier: ^2.8.8 devDependencies: '@babel/core': 7.13.16 '@linaria/esbuild': 3.0.0-beta.23 @@ -20,7 +20,7 @@ importers: eslint: 8.29.0 eslint-config-prettier: 8.5.0_eslint@8.29.0 nx: 15.0.1 - prettier: 2.7.1 + prettier: 2.8.8 packages/anastasis-core: specifiers: @@ -209,7 +209,7 @@ importers: '@types/node': ^18.11.17 ava: ^4.3.3 esm: ^3.2.25 - prettier: ^2.5.1 + prettier: ^2.8.8 rimraf: ^3.0.2 tslib: ^2.4.0 typescript: ^4.9.4 @@ -219,7 +219,7 @@ importers: '@types/node': 18.11.17 ava: 4.3.3 esm: 3.2.25 - prettier: 2.7.1 + prettier: 2.8.8 rimraf: 3.0.2 typescript: 4.9.4 @@ -391,7 +391,7 @@ importers: '@types/node': ^18.11.17 axios: ^0.27.2 esbuild: ^0.17.7 - prettier: ^2.5.1 + prettier: ^2.8.8 rimraf: ^3.0.2 tslib: ^2.4.0 typescript: ^4.9.4 @@ -403,7 +403,7 @@ importers: devDependencies: '@types/node': 18.11.17 esbuild: 0.17.7 - prettier: 2.7.1 + prettier: 2.8.8 rimraf: 3.0.2 typescript: 4.9.4 @@ -415,7 +415,7 @@ importers: esbuild: ^0.17.7 fflate: ^0.7.4 jed: ^1.1.1 - prettier: ^2.5.1 + prettier: ^2.8.8 rimraf: ^3.0.2 tslib: ^2.4.0 typescript: ^4.9.4 @@ -428,7 +428,7 @@ importers: '@types/node': 18.11.17 ava: 4.3.3 esbuild: 0.17.7 - prettier: 2.7.1 + prettier: 2.8.8 rimraf: 3.0.2 typescript: 4.9.4 @@ -437,7 +437,7 @@ importers: '@gnu-taler/taler-util': workspace:* '@gnu-taler/taler-wallet-core': workspace:* '@types/node': ^18.11.17 - prettier: ^2.5.1 + prettier: ^2.8.8 rimraf: ^3.0.2 tslib: ^2.4.0 typedoc: ^0.23.16 @@ -448,7 +448,7 @@ importers: tslib: 2.4.0 devDependencies: '@types/node': 18.11.17 - prettier: 2.7.1 + prettier: 2.8.8 rimraf: 3.0.2 typedoc: 0.23.18_typescript@4.9.4 typescript: 4.9.4 @@ -475,7 +475,7 @@ importers: fflate: ^0.7.4 jed: ^1.1.1 po2json: ^0.4.5 - prettier: ^2.5.1 + prettier: ^2.8.8 rimraf: ^3.0.2 tslib: ^2.4.0 typedoc: ^0.23.16 @@ -503,7 +503,7 @@ importers: eslint-plugin-react-hooks: 4.6.0_eslint@8.26.0 jed: 1.1.1 po2json: 0.4.5 - prettier: 2.7.1 + prettier: 2.8.8 rimraf: 3.0.2 typedoc: 0.23.18_typescript@4.9.4 typescript: 4.9.4 @@ -515,7 +515,7 @@ importers: '@gnu-taler/taler-wallet-core': workspace:* '@types/node': ^18.11.17 esbuild: ^0.17.7 - prettier: ^2.5.1 + prettier: ^2.8.8 rimraf: ^3.0.2 tslib: ^2.4.0 dependencies: @@ -526,7 +526,7 @@ importers: devDependencies: '@types/node': 18.11.17 esbuild: 0.17.7 - prettier: 2.7.1 + prettier: 2.8.8 rimraf: 3.0.2 packages/taler-wallet-webextension: @@ -621,7 +621,7 @@ importers: postcss-load-config: ^4.0.1 preact: 10.11.3 preact-render-to-string: ^5.2.6 - prettier: ^2.5.1 + prettier: ^2.8.8 rimraf: ^3.0.2 sass: 1.56.1 swr: 2.0.3 @@ -655,7 +655,7 @@ importers: postcss-load-config: 4.0.1_postcss@8.4.23 preact: 10.11.3 preact-render-to-string: 5.2.6_preact@10.11.3 - prettier: 2.7.1 + prettier: 2.8.8 rimraf: 3.0.2 sass: 1.56.1 swr: 2.0.3 @@ -14170,8 +14170,8 @@ packages: engines: {node: '>=4'} dev: true - /prettier/2.7.1: - resolution: {integrity: sha512-ujppO+MkdPqoVINuDFDRLClm7D78qbDt0/NR+wp5FqEZOoTNAjPHWj17QRhu7geIHJfcNhRk1XVQmF8Bp3ye+g==} + /prettier/2.8.8: + resolution: {integrity: sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==} engines: {node: '>=10.13.0'} hasBin: true dev: true