From 13f0442736479fb6ea8d1ecc7311cdac354a4de5 Mon Sep 17 00:00:00 2001 From: Florian Dold Date: Sun, 12 Feb 2023 19:30:59 +0100 Subject: harness: finish kyc test We mock the KYC gateway now, use the new notification-based wallet API and the test is not experimental anymore. --- .../taler-wallet-core/src/operations/deposits.ts | 40 ++++++++++++++++++++-- .../taler-wallet-core/src/operations/withdraw.ts | 22 +++++++----- packages/taler-wallet-core/src/remote.ts | 30 ++++++++-------- 3 files changed, 67 insertions(+), 25 deletions(-) (limited to 'packages/taler-wallet-core/src') diff --git a/packages/taler-wallet-core/src/operations/deposits.ts b/packages/taler-wallet-core/src/operations/deposits.ts index e97738b55..4ff6a65cd 100644 --- a/packages/taler-wallet-core/src/operations/deposits.ts +++ b/packages/taler-wallet-core/src/operations/deposits.ts @@ -38,8 +38,10 @@ import { hashTruncate32, hashWire, HttpStatusCode, + j2s, Logger, MerchantContractTerms, + NotificationType, parsePaytoUri, PayCoinSelection, PrepareDepositRequest, @@ -61,7 +63,7 @@ import { TransactionStatus, } from "../db.js"; import { TalerError } from "../errors.js"; -import { checkKycStatus } from "../index.js"; +import { checkWithdrawalKycStatus, KycPendingInfo, KycUserType } from "../index.js"; import { InternalWalletState } from "../internal-wallet-state.js"; import { readSuccessResponseJsonOrThrow } from "../util/http.js"; import { OperationAttemptResult } from "../util/retries.js"; @@ -80,6 +82,40 @@ import { getTotalRefreshCost } from "./refresh.js"; */ const logger = new Logger("deposits.ts"); + +export async function checkDepositKycStatus( + ws: InternalWalletState, + exchangeUrl: string, + kycInfo: KycPendingInfo, + userType: KycUserType, +): Promise { + const url = new URL( + `kyc-check/${kycInfo.requirementRow}/${kycInfo.paytoHash}/${userType}`, + exchangeUrl, + ); + logger.info(`kyc url ${url.href}`); + const kycStatusReq = await ws.http.fetch(url.href, { + method: "GET", + }); + if (kycStatusReq.status === HttpStatusCode.Ok) { + logger.warn("kyc requested, but already fulfilled"); + return; + } else if (kycStatusReq.status === HttpStatusCode.Accepted) { + const kycStatus = await kycStatusReq.json(); + logger.info(`kyc status: ${j2s(kycStatus)}`); + // FIXME: This error code is totally wrong + throw TalerError.fromDetail( + TalerErrorCode.WALLET_WITHDRAWAL_KYC_REQUIRED, + { + kycUrl: kycStatus.kyc_url, + }, + `KYC check required for deposit`, + ); + } else { + throw Error(`unexpected response from kyc-check (${kycStatusReq.status})`); + } +} + /** * @see {processDepositGroup} */ @@ -162,7 +198,7 @@ export async function processDepositGroup( const paytoHash = encodeCrock( hashTruncate32(stringToBytes(depositGroup.wire.payto_uri + "\0")), ); - await checkKycStatus( + await checkDepositKycStatus( ws, perm.exchange_url, { paytoHash, requirementRow }, diff --git a/packages/taler-wallet-core/src/operations/withdraw.ts b/packages/taler-wallet-core/src/operations/withdraw.ts index 5c9854c0f..28754c77e 100644 --- a/packages/taler-wallet-core/src/operations/withdraw.ts +++ b/packages/taler-wallet-core/src/operations/withdraw.ts @@ -1250,12 +1250,7 @@ export async function processWithdrawalGroup( if (numKycRequired > 0) { if (kycInfo) { - await checkKycStatus( - ws, - withdrawalGroup.exchangeBaseUrl, - kycInfo, - "individual", - ); + await checkWithdrawalKycStatus(ws, withdrawalGroup, kycInfo, "individual"); return { type: OperationAttemptResultType.Pending, result: undefined, @@ -1293,12 +1288,13 @@ export async function processWithdrawalGroup( }; } -export async function checkKycStatus( +export async function checkWithdrawalKycStatus( ws: InternalWalletState, - exchangeUrl: string, + wg: WithdrawalGroupRecord, kycInfo: KycPendingInfo, userType: KycUserType, ): Promise { + const exchangeUrl = wg.exchangeBaseUrl; const url = new URL( `kyc-check/${kycInfo.requirementRow}/${kycInfo.paytoHash}/${userType}`, exchangeUrl, @@ -1307,12 +1303,20 @@ export async function checkKycStatus( const kycStatusReq = await ws.http.fetch(url.href, { method: "GET", }); - logger.warn("kyc requested, but already fulfilled"); if (kycStatusReq.status === HttpStatusCode.Ok) { + logger.warn("kyc requested, but already fulfilled"); return; } else if (kycStatusReq.status === HttpStatusCode.Accepted) { const kycStatus = await kycStatusReq.json(); logger.info(`kyc status: ${j2s(kycStatus)}`); + ws.notify({ + type: NotificationType.WithdrawalKycRequested, + kycUrl: kycStatus.kyc_url, + transactionId: makeTransactionId( + TransactionType.Withdrawal, + wg.withdrawalGroupId, + ), + }); throw TalerError.fromDetail( TalerErrorCode.WALLET_WITHDRAWAL_KYC_REQUIRED, { diff --git a/packages/taler-wallet-core/src/remote.ts b/packages/taler-wallet-core/src/remote.ts index 2628fea07..bc0be9d30 100644 --- a/packages/taler-wallet-core/src/remote.ts +++ b/packages/taler-wallet-core/src/remote.ts @@ -145,9 +145,14 @@ export function getClientFromRemoteWallet( export interface WalletNotificationWaiter { notify(wn: WalletNotification): void; - waitForNotificationCond( - cond: (n: WalletNotification) => boolean, - ): Promise; + waitForNotificationCond( + cond: (n: WalletNotification) => T | false | undefined, + ): Promise; +} + +interface NotificationCondEntry { + condition: (n: WalletNotification) => T | false | undefined; + promiseCapability: OpenedPromise; } /** @@ -157,22 +162,19 @@ export interface WalletNotificationWaiter { export function makeNotificationWaiter(): WalletNotificationWaiter { // Bookkeeping for waiting on notification conditions let nextCondIndex = 1; - const condMap: Map< - number, - { - condition: (n: WalletNotification) => boolean; - promiseCapability: OpenedPromise; - } - > = new Map(); + const condMap: Map> = new Map(); function onNotification(n: WalletNotification) { condMap.forEach((cond, condKey) => { - if (cond.condition(n)) { - cond.promiseCapability.resolve(); + const res = cond.condition(n); + if (res) { + cond.promiseCapability.resolve(res); } }); } - function waitForNotificationCond(cond: (n: WalletNotification) => boolean) { - const promCap = openPromise(); + function waitForNotificationCond( + cond: (n: WalletNotification) => T | false | undefined, + ) { + const promCap = openPromise(); condMap.set(nextCondIndex++, { condition: cond, promiseCapability: promCap, -- cgit v1.2.3