taler-typescript-core

Wallet core logic and WebUIs for various components
Log | Files | Refs | Submodules | README | LICENSE

commit a6524293f1fd25704b876048f7b564000d76b6e3
parent 54ead87bbea0d1c8a8ba49ab9f3e345161153de0
Author: Florian Dold <florian@dold.me>
Date:   Tue,  8 Jul 2025 21:28:40 +0200

wallet-core: unify deposit kyc and deposit kyc auth handling

Diffstat:
Mpackages/taler-wallet-core/src/deposits.ts | 118++++++++++++-------------------------------------------------------------------
1 file changed, 18 insertions(+), 100 deletions(-)

diff --git a/packages/taler-wallet-core/src/deposits.ts b/packages/taler-wallet-core/src/deposits.ts @@ -1108,6 +1108,10 @@ async function processDepositGroupPendingKyc( kycInfo.lastDeny = algoRes.lastDeny; kycInfo.lastRuleGen = algoRes.lastRuleGen; + const requiresAuth = + algoRes.lastCheckStatus === HttpStatusCode.Conflict || + algoRes.lastCheckStatus === HttpStatusCode.Forbidden; + // Now store the result. return await wex.db.runReadWriteTx( @@ -1120,8 +1124,20 @@ async function processDepositGroupPendingKyc( const oldTxState = computeDepositTransactionStatus(newDg); switch (newDg.operationStatus) { case DepositOperationStatus.PendingAggregateKyc: + if (requiresAuth) { + throw Error("kyc auth during aggregation not yet supported"); + } break; case DepositOperationStatus.PendingDepositKyc: + if (requiresAuth) { + newDg.operationStatus = + DepositOperationStatus.PendingDepositKycAuth; + } + break; + case DepositOperationStatus.PendingDepositKycAuth: + if (!requiresAuth) { + newDg.operationStatus = DepositOperationStatus.PendingDepositKyc; + } break; default: return TaskRunResult.backoff(); @@ -1140,103 +1156,6 @@ async function processDepositGroupPendingKyc( ); } -async function processDepositGroupPendingKycAuth( - wex: WalletExecutionContext, - depositGroup: DepositGroupRecord, -): Promise<TaskRunResult> { - const { depositGroupId } = depositGroup; - const ctx = new DepositTransactionContext(wex, depositGroupId); - - const kycInfo = depositGroup.kycInfo; - - if (!kycInfo) { - throw Error( - "invalid DB state, in pending(kyc-auth), but no kycInfo present", - ); - } - - const sigResp = await wex.cryptoApi.signWalletKycAuth({ - accountPriv: depositGroup.merchantPriv, - accountPub: depositGroup.merchantPub, - }); - - const url = new URL( - `kyc-check/${kycInfo.paytoHash}`, - kycInfo.exchangeBaseUrl, - ); - - // lpt=1 => wait for the KYC auth transfer (access token available) - url.searchParams.set("lpt", "1"); - logger.info(`kyc url ${url.href}`); - const kycStatusRes = await cancelableLongPoll(wex, url, { - headers: { - ["Account-Owner-Signature"]: sigResp.sig, - ["Account-Owner-Pub"]: depositGroup.merchantPub, - }, - }); - - logger.info(`merchant pub: ${depositGroup.merchantPub}`); - - logger.info( - `kyc-check for auth longpoll result status: ${kycStatusRes.status}`, - ); - - switch (kycStatusRes.status) { - case HttpStatusCode.Ok: - return await transitionKycAuthSuccess(ctx); - case HttpStatusCode.NoContent: - return await transitionKycAuthSuccess(ctx); - case HttpStatusCode.Accepted: - return await transitionKycAuthSuccess(ctx); - case HttpStatusCode.Conflict: - case HttpStatusCode.Forbidden: - // FIXME: Also check error code - logger.info("kyc auth still pending"); - return TaskRunResult.longpollReturnedPending(); - default: - throwUnexpectedRequestError( - kycStatusRes, - await readTalerErrorResponse(kycStatusRes), - ); - } -} - -async function transitionKycAuthSuccess( - ctx: DepositTransactionContext, -): Promise<TaskRunResult> { - const didTransition = await ctx.wex.db.runReadWriteTx( - { storeNames: ["depositGroups", "transactionsMeta"] }, - async (tx) => { - const newDg = await tx.depositGroups.get(ctx.depositGroupId); - if (!newDg) { - return false; - } - const oldTxState = computeDepositTransactionStatus(newDg); - switch (newDg.operationStatus) { - case DepositOperationStatus.PendingDepositKycAuth: - newDg.operationStatus = DepositOperationStatus.PendingDeposit; - break; - default: - return false; - } - await tx.depositGroups.put(newDg); - await ctx.updateTransactionMeta(tx); - const newTxState = computeDepositTransactionStatus(newDg); - applyNotifyTransition(tx.notify, ctx.transactionId, { - oldTxState, - newTxState, - balanceEffect: BalanceEffect.None, - }); - return true; - }, - ); - if (didTransition) { - return TaskRunResult.progress(); - } else { - return TaskRunResult.backoff(); - } -} - /** * Finds the reserve key pair of the most recent withdrawal * with the given exchange. @@ -1540,7 +1459,7 @@ async function processDepositGroupTrack( let allWired = true; - const transitionInfo = await wex.db.runReadWriteTx( + await wex.db.runReadWriteTx( { storeNames: ["depositGroups", "transactionsMeta"] }, async (tx) => { const dg = await tx.depositGroups.get(depositGroupId); @@ -1892,13 +1811,12 @@ export async function processDepositGroup( return processDepositGroupTrack(wex, depositGroup); case DepositOperationStatus.PendingAggregateKyc: case DepositOperationStatus.PendingDepositKyc: + case DepositOperationStatus.PendingDepositKycAuth: return processDepositGroupPendingKyc(wex, depositGroup); case DepositOperationStatus.PendingDeposit: return processDepositGroupPendingDeposit(wex, depositGroup); case DepositOperationStatus.Aborting: return processDepositGroupAborting(wex, depositGroup); - case DepositOperationStatus.PendingDepositKycAuth: - return processDepositGroupPendingKycAuth(wex, depositGroup); } return TaskRunResult.finished();