diff options
-rw-r--r-- | packages/taler-wallet-core/src/db.ts | 5 | ||||
-rw-r--r-- | packages/taler-wallet-core/src/operations/deposits.ts | 40 | ||||
-rw-r--r-- | packages/taler-wallet-core/src/operations/withdraw.ts | 82 |
3 files changed, 77 insertions, 50 deletions
diff --git a/packages/taler-wallet-core/src/db.ts b/packages/taler-wallet-core/src/db.ts index e6131334c..d2d01e100 100644 --- a/packages/taler-wallet-core/src/db.ts +++ b/packages/taler-wallet-core/src/db.ts @@ -1361,7 +1361,8 @@ export type WgInfo = | WgInfoBankPeerPush | WgInfoBankRecoup; -export interface WithdrawalKycPendingInfo { +export type KycUserType = "individual" | "business"; +export interface KycPendingInfo { paytoHash: string; requirementRow: number; } @@ -1380,7 +1381,7 @@ export interface WithdrawalGroupRecord { wgInfo: WgInfo; - kycPending?: WithdrawalKycPendingInfo; + kycPending?: KycPendingInfo; /** * Secret seed used to derive planchets. diff --git a/packages/taler-wallet-core/src/operations/deposits.ts b/packages/taler-wallet-core/src/operations/deposits.ts index b529e5ead..71caae5b3 100644 --- a/packages/taler-wallet-core/src/operations/deposits.ts +++ b/packages/taler-wallet-core/src/operations/deposits.ts @@ -21,6 +21,7 @@ import { AbsoluteTime, AmountJson, Amounts, + bytesToString, CancellationToken, canonicalJson, codecForDepositSuccess, @@ -35,6 +36,7 @@ import { ExchangeDepositRequest, GetFeeForDepositRequest, getRandomBytes, + hashTruncate32, hashWire, HttpStatusCode, Logger, @@ -44,6 +46,7 @@ import { PrepareDepositRequest, PrepareDepositResponse, RefreshReason, + stringToBytes, TalerErrorCode, TalerProtocolTimestamp, TrackDepositGroupRequest, @@ -59,6 +62,7 @@ import { TransactionStatus, } from "../db.js"; import { TalerError } from "../errors.js"; +import { checkKycStatus } from "../index.js"; import { InternalWalletState } from "../internal-wallet-state.js"; import { readSuccessResponseJsonOrThrow } from "../util/http.js"; import { OperationAttemptResult } from "../util/retries.js"; @@ -151,7 +155,28 @@ export async function processDepositGroup( if (depositGroup.transactionPerCoin[i] !== TransactionStatus.Wired) { const track = await trackDepositPermission(ws, depositGroup, perm); - updatedTxStatus = txStatusFromTrack(track); + + if (track.type === "accepted") { + if (!track.kyc_ok && track.requirement_row !== undefined) { + updatedTxStatus = TransactionStatus.KycRequired; + const { requirement_row: requirementRow } = track; + const paytoHash = encodeCrock( + hashTruncate32(stringToBytes(depositGroup.wire.payto_uri + "\0")), + ); + await checkKycStatus( + ws, + perm.exchange_url, + { paytoHash, requirementRow }, + "individual", + ); + } else { + updatedTxStatus = TransactionStatus.Accepted; + } + } else if (track.type === "wired") { + updatedTxStatus = TransactionStatus.Wired; + } else { + updatedTxStatus = TransactionStatus.Unknown; + } } if (updatedTxStatus !== undefined || updatedDeposit !== undefined) { @@ -199,19 +224,6 @@ export async function processDepositGroup( return OperationAttemptResult.finishedEmpty(); } -function txStatusFromTrack(t: TrackTransaction): TransactionStatus { - if (t.type === "accepted") { - if (!t.kyc_ok && t.requirement_row !== undefined) { - return TransactionStatus.KycRequired; - } - return TransactionStatus.Accepted; - } - if (t.type === "wired") { - return TransactionStatus.Wired; - } - return TransactionStatus.Unknown; -} - export async function trackDepositGroup( ws: InternalWalletState, req: TrackDepositGroupRequest, diff --git a/packages/taler-wallet-core/src/operations/withdraw.ts b/packages/taler-wallet-core/src/operations/withdraw.ts index a1a39bf32..c1cc94413 100644 --- a/packages/taler-wallet-core/src/operations/withdraw.ts +++ b/packages/taler-wallet-core/src/operations/withdraw.ts @@ -26,7 +26,6 @@ import { AmountJson, AmountLike, Amounts, - AmountString, BankWithdrawDetails, CancellationToken, canonicalizeBaseUrl, @@ -70,13 +69,14 @@ import { CoinSourceType, DenominationRecord, DenominationVerificationStatus, + KycPendingInfo, + KycUserType, PlanchetRecord, PlanchetStatus, WalletStoresV1, WgInfo, WithdrawalGroupRecord, WithdrawalGroupStatus, - WithdrawalKycPendingInfo, WithdrawalRecordType, } from "../db.js"; import { @@ -86,7 +86,6 @@ import { } from "../errors.js"; import { InternalWalletState } from "../internal-wallet-state.js"; import { - getExchangeTosStatus, makeCoinAvailable, makeExchangeListItem, runOperationWithErrorReporting, @@ -927,7 +926,7 @@ async function queryReserve( ); reserveUrl.searchParams.set("timeout_ms", "30000"); - logger.info(`querying reserve status via ${reserveUrl}`); + logger.info(`querying reserve status via ${reserveUrl.href}`); const resp = await ws.http.get(reserveUrl.href, { timeout: getReserveRequestTimeout(withdrawalGroup), @@ -1165,9 +1164,9 @@ export async function processWithdrawalGroup( let numFinished = 0; let numKycRequired = 0; let finishedForFirstTime = false; - let errorsPerCoin: Record<number, TalerErrorDetail> = {}; + const errorsPerCoin: Record<number, TalerErrorDetail> = {}; - let res = await ws.db + const res = await ws.db .mktx((x) => [x.coins, x.withdrawalGroups, x.planchets]) .runReadWrite(async (tx) => { const wg = await tx.withdrawalGroups.get(withdrawalGroupId); @@ -1210,39 +1209,22 @@ export async function processWithdrawalGroup( if (numKycRequired > 0) { if (kycInfo) { - const url = new URL( - `kyc-check/${kycInfo.requirementRow}/${kycInfo.paytoHash}/individual`, + await checkKycStatus( + ws, withdrawalGroup.exchangeBaseUrl, + kycInfo, + "individual", ); - logger.info(`kyc url ${url.href}`); - const kycStatusReq = await ws.http.fetch(url.href, { - method: "GET", - }); - logger.warn("kyc requested, but already fulfilled"); - if (kycStatusReq.status === HttpStatusCode.Ok) { - return { - type: OperationAttemptResultType.Pending, - result: undefined, - }; - } else if (kycStatusReq.status === HttpStatusCode.Accepted) { - const kycStatus = await kycStatusReq.json(); - logger.info(`kyc status: ${j2s(kycStatus)}`); - throw TalerError.fromDetail( - TalerErrorCode.WALLET_WITHDRAWAL_KYC_REQUIRED, - { - kycUrl: kycStatus.kyc_url, - }, - `KYC check required for withdrawal`, - ); - } else { - throw Error( - `unexpected response from kyc-check (${kycStatusReq.status})`, - ); - } + return { + type: OperationAttemptResultType.Pending, + result: undefined, + }; } else { throw TalerError.fromDetail( TalerErrorCode.WALLET_WITHDRAWAL_KYC_REQUIRED, - {}, + { + //FIXME we can't rise KYC error here since we don't have the url + } as any, `KYC check required for withdrawal (not yet implemented in wallet-core)`, ); } @@ -1270,6 +1252,38 @@ export async function processWithdrawalGroup( }; } +export async function checkKycStatus( + ws: InternalWalletState, + exchangeUrl: string, + kycInfo: KycPendingInfo, + userType: KycUserType, +): Promise<void> { + 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", + }); + logger.warn("kyc requested, but already fulfilled"); + if (kycStatusReq.status === HttpStatusCode.Ok) { + return; + } else if (kycStatusReq.status === HttpStatusCode.Accepted) { + const kycStatus = await kycStatusReq.json(); + logger.info(`kyc status: ${j2s(kycStatus)}`); + throw TalerError.fromDetail( + TalerErrorCode.WALLET_WITHDRAWAL_KYC_REQUIRED, + { + kycUrl: kycStatus.kyc_url, + }, + `KYC check required for withdrawal`, + ); + } else { + throw Error(`unexpected response from kyc-check (${kycStatusReq.status})`); + } +} + const AGE_MASK_GROUPS = "8:10:12:14:16:18" .split(":") .map((n) => parseInt(n, 10)); |