[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[taler-wallet-core] branch master updated: wallet-core: use new /kyc-che
From: |
gnunet |
Subject: |
[taler-wallet-core] branch master updated: wallet-core: use new /kyc-check/H_PAYTO API, fix test |
Date: |
Tue, 03 Sep 2024 21:15:28 +0200 |
This is an automated email from the git hooks/post-receive script.
dold pushed a commit to branch master
in repository wallet-core.
The following commit(s) were added to refs/heads/master by this push:
new a9b1e425b wallet-core: use new /kyc-check/H_PAYTO API, fix test
a9b1e425b is described below
commit a9b1e425bba7023740ec2883f18fb9e636f48759
Author: Florian Dold <florian@dold.me>
AuthorDate: Tue Sep 3 21:15:18 2024 +0200
wallet-core: use new /kyc-check/H_PAYTO API, fix test
---
.../src/integrationtests/test-kyc-peer-pull.ts | 42 ++++++-------
packages/taler-util/src/payto.ts | 29 +++++++++
packages/taler-util/src/types-taler-common.ts | 18 +-----
packages/taler-util/src/types-taler-exchange.ts | 4 +-
packages/taler-wallet-core/src/db.ts | 20 ++-----
packages/taler-wallet-core/src/deposits.ts | 17 +++---
packages/taler-wallet-core/src/exchanges.ts | 17 ++++--
.../taler-wallet-core/src/pay-peer-pull-credit.ts | 69 +++++++++++----------
.../taler-wallet-core/src/pay-peer-push-credit.ts | 64 +++++++++++---------
packages/taler-wallet-core/src/withdraw.ts | 70 +++++++++-------------
10 files changed, 177 insertions(+), 173 deletions(-)
diff --git a/packages/taler-harness/src/integrationtests/test-kyc-peer-pull.ts
b/packages/taler-harness/src/integrationtests/test-kyc-peer-pull.ts
index c6de961ab..cc5787f26 100644
--- a/packages/taler-harness/src/integrationtests/test-kyc-peer-pull.ts
+++ b/packages/taler-harness/src/integrationtests/test-kyc-peer-pull.ts
@@ -252,25 +252,6 @@ export async function runKycPeerPullTest(t:
GlobalTestState) {
summary: "test123",
});
- const prepRes = await w0.walletClient.call(
- WalletApiOperation.PreparePeerPullDebit,
- {
- talerUri: pullRes.talerUri,
- },
- );
-
- await w0.walletClient.call(WalletApiOperation.ConfirmPeerPullDebit, {
- transactionId: prepRes.transactionId,
- });
-
- await walletClient.call(WalletApiOperation.TestingWaitTransactionState, {
- transactionId: pullRes.transactionId as TransactionIdStr,
- txState: {
- major: TransactionMajorState.Pending,
- minor: TransactionMinorState.MergeKycRequired,
- },
- });
-
const txDet = await walletClient.call(WalletApiOperation.GetTransactionById,
{
transactionId: pullRes.transactionId,
});
@@ -288,6 +269,25 @@ export async function runKycPeerPullTest(t:
GlobalTestState) {
paytoHash: kycPaytoHash,
});
+ await walletClient.call(WalletApiOperation.TestingWaitTransactionState, {
+ transactionId: pullRes.transactionId as TransactionIdStr,
+ txState: {
+ major: TransactionMajorState.Pending,
+ minor: TransactionMinorState.Ready,
+ },
+ });
+
+ const prepRes = await w0.walletClient.call(
+ WalletApiOperation.PreparePeerPullDebit,
+ {
+ talerUri: pullRes.talerUri,
+ },
+ );
+
+ await w0.walletClient.call(WalletApiOperation.ConfirmPeerPullDebit, {
+ transactionId: prepRes.transactionId,
+ });
+
await walletClient.call(WalletApiOperation.TestingWaitTransactionState, {
transactionId: pullRes.transactionId as TransactionIdStr,
txState: {
@@ -297,7 +297,7 @@ export async function runKycPeerPullTest(t:
GlobalTestState) {
}
/**
- * Initiate a pull debit transaction, wait until the transaction
+ * Initiate a pull credit transaction, wait until the transaction
* is ready.
*/
async function doPeerPullCredit(
@@ -332,7 +332,7 @@ async function doPeerPullCredit(
transactionId: initRet.transactionId,
txState: {
major: TransactionMajorState.Pending,
- minor: TransactionMinorState.Ready,
+ minor: TransactionMinorState.MergeKycRequired,
},
});
diff --git a/packages/taler-util/src/payto.ts b/packages/taler-util/src/payto.ts
index f50f97e58..76b5ff0cf 100644
--- a/packages/taler-util/src/payto.ts
+++ b/packages/taler-util/src/payto.ts
@@ -218,6 +218,35 @@ export function hashPaytoUri(p: PaytoUri | string):
Uint8Array {
return hashTruncate32(stringToBytes(paytoUri + "\0"));
}
+export function stringifyReservePaytoUri(
+ exchangeBaseUrl: string,
+ reservePub: string,
+): string {
+ const url = new URL(exchangeBaseUrl);
+ let target: string;
+ let domainWithOptPort: string;
+ if (url.protocol === "https:") {
+ target = "taler-reserve";
+ if (url.port != "443" && url.port !== "") {
+ domainWithOptPort = `${url.hostname}:${url.port}`;
+ } else {
+ domainWithOptPort = `${url.hostname}`;
+ }
+ } else {
+ target = "taler-reserve-http";
+ if (url.port != "80" && url.port !== "") {
+ domainWithOptPort = `${url.hostname}:${url.port}`;
+ } else {
+ domainWithOptPort = `${url.hostname}`;
+ }
+ }
+ let optPath = "";
+ if (url.pathname !== "/" && url.pathname !== "") {
+ optPath = url.pathname;
+ }
+ return `payto://${target}/${domainWithOptPort}${optPath}/${reservePub}`;
+}
+
/**
* Parse a valid payto:// uri into a PaytoUri object
* RFC 8905
diff --git a/packages/taler-util/src/types-taler-common.ts
b/packages/taler-util/src/types-taler-common.ts
index 1db365ea7..dd983cf2e 100644
--- a/packages/taler-util/src/types-taler-common.ts
+++ b/packages/taler-util/src/types-taler-common.ts
@@ -40,7 +40,7 @@ import {
codecForString,
codecOptional,
} from "./codec.js";
-import { codecForEither, ReservePub } from "./index.js";
+import { ReservePub, codecForEither } from "./index.js";
import {
TalerProtocolDuration,
TalerProtocolTimestamp,
@@ -291,21 +291,6 @@ export type HashCodeString = string;
export type WireSalt = string;
-export interface WalletKycUuid {
- // UUID that the wallet should use when initiating
- // the KYC check.
- requirement_row: number;
-
- // Hash of the payto:// account URI for the wallet.
- h_payto: string;
-}
-
-export const codecForWalletKycUuid = (): Codec<WalletKycUuid> =>
- buildCodecForObject<WalletKycUuid>()
- .property("requirement_row", codecForNumber())
- .property("h_payto", codecForString())
- .build("WalletKycUuid");
-
export interface MerchantUsingTemplateDetails {
summary?: string;
amount?: AmountString;
@@ -545,7 +530,6 @@ export interface ReserveAccount {
signingKey: SigningKey;
}
-
export type PaginationParams = {
/**
* row identifier as the starting point of the query
diff --git a/packages/taler-util/src/types-taler-exchange.ts
b/packages/taler-util/src/types-taler-exchange.ts
index 19f573f4b..bc8165991 100644
--- a/packages/taler-util/src/types-taler-exchange.ts
+++ b/packages/taler-util/src/types-taler-exchange.ts
@@ -1616,7 +1616,7 @@ export interface LegitimizationNeededResponse {
// transaction was blocked and how to lift it. The account holder
// should use the number to check for the account's AML/KYC status
// using the /kyc-check/$REQUIREMENT_ROW endpoint.
- requirement_row: Integer;
+ requirement_row: Integer | undefined;
}
export interface AccountKycStatus {
@@ -2422,7 +2422,7 @@ export const codecForLegitimizationNeededResponse =
.property("hint", codecOptional(codecForString()))
.property("h_payto", codecForString())
.property("account_pub", codecOptional(codecForString()))
- .property("requirement_row", codecForNumber())
+ .property("requirement_row", codecOptional(codecForNumber()))
.build("TalerExchangeApi.LegitimizationNeededResponse");
export const codecForAccountKycStatus = (): Codec<AccountKycStatus> =>
diff --git a/packages/taler-wallet-core/src/db.ts
b/packages/taler-wallet-core/src/db.ts
index c48a43f11..21ec3f033 100644
--- a/packages/taler-wallet-core/src/db.ts
+++ b/packages/taler-wallet-core/src/db.ts
@@ -1466,11 +1466,6 @@ export type WgInfo =
export type KycUserType = "individual" | "business";
-export interface KycPendingInfo {
- paytoHash: string;
- requirementRow: number;
-}
-
/**
* Group of withdrawal operations that need to be executed.
* (Either for a normal withdrawal or from a reward.)
@@ -1486,9 +1481,7 @@ export interface WithdrawalGroupRecord {
wgInfo: WgInfo;
- kycPending?: KycPendingInfo;
-
- kycUrl?: string;
+ kycPaytoHash?: string;
kycAccessToken?: string;
@@ -1838,8 +1831,7 @@ export interface DepositGroupRecord {
}
export interface DepositKycInfo {
- kycUrl: string;
- requirementRow: number;
+ accessToken: string;
paytoHash: string;
exchangeBaseUrl: string;
}
@@ -2029,9 +2021,7 @@ export interface PeerPullCreditRecord {
*/
status: PeerPullPaymentCreditStatus;
- kycInfo?: KycPendingInfo;
-
- kycUrl?: string;
+ kycPaytoHash?: string;
kycAccessToken?: string;
@@ -2109,9 +2099,7 @@ export interface PeerPushPaymentIncomingRecord {
*/
currency: string | undefined;
- kycInfo?: KycPendingInfo;
-
- kycUrl?: string;
+ kycPaytoHash?: string;
kycAccessToken?: string;
}
diff --git a/packages/taler-wallet-core/src/deposits.ts
b/packages/taler-wallet-core/src/deposits.ts
index e4b378f44..34b19df80 100644
--- a/packages/taler-wallet-core/src/deposits.ts
+++ b/packages/taler-wallet-core/src/deposits.ts
@@ -88,9 +88,9 @@ import {
DepositElementStatus,
DepositGroupRecord,
DepositInfoPerExchange,
+ DepositKycInfo,
DepositOperationStatus,
DepositTrackingInfo,
- KycPendingInfo,
RefreshOperationStatus,
WalletDbAllStoresReadOnlyTransaction,
WalletDbReadWriteTransaction,
@@ -779,7 +779,7 @@ async function processDepositGroupPendingKyc(
}
const url = new URL(
- `kyc-check/${kycInfo.requirementRow}`,
+ `kyc-check/${kycInfo.paytoHash}`,
kycInfo.exchangeBaseUrl,
);
@@ -839,14 +839,14 @@ async function processDepositGroupPendingKyc(
async function transitionToKycRequired(
wex: WalletExecutionContext,
depositGroup: DepositGroupRecord,
- kycInfo: KycPendingInfo,
+ kycInfo: DepositKycInfo,
exchangeUrl: string,
): Promise<TaskRunResult> {
const { depositGroupId } = depositGroup;
const ctx = new DepositTransactionContext(wex, depositGroupId);
- const url = new URL(`kyc-check/${kycInfo.requirementRow}`, exchangeUrl);
+ const url = new URL(`kyc-check/${kycInfo.paytoHash}`, exchangeUrl);
logger.info(`kyc url ${url.href}`);
const kycStatusReq = await wex.http.fetch(url.href, {
method: "GET",
@@ -870,9 +870,8 @@ async function transitionToKycRequired(
const oldTxState = computeDepositTransactionStatus(dg);
dg.kycInfo = {
exchangeBaseUrl: exchangeUrl,
- kycUrl: kycStatus.kyc_url,
paytoHash: kycInfo.paytoHash,
- requirementRow: kycInfo.requirementRow,
+ accessToken: null as any, // FIXME!
};
await tx.depositGroups.put(dg);
await ctx.updateTransactionMeta(tx);
@@ -938,10 +937,10 @@ async function processDepositGroupPendingTrack(
const paytoHash = encodeCrock(
hashTruncate32(stringToBytes(depositGroup.wire.payto_uri + "\0")),
);
- const { requirement_row: requirementRow } = track;
- const kycInfo: KycPendingInfo = {
+ const kycInfo: DepositKycInfo = {
paytoHash,
- requirementRow,
+ exchangeBaseUrl: exchangeBaseUrl,
+ accessToken: null as any, // FIXME!
};
return transitionToKycRequired(
wex,
diff --git a/packages/taler-wallet-core/src/exchanges.ts
b/packages/taler-wallet-core/src/exchanges.ts
index fe78c63aa..2c0386d0c 100644
--- a/packages/taler-wallet-core/src/exchanges.ts
+++ b/packages/taler-wallet-core/src/exchanges.ts
@@ -101,10 +101,12 @@ import {
encodeCrock,
getRandomBytes,
hashDenomPub,
+ hashPaytoUri,
j2s,
makeErrorDetail,
makeTalerErrorDetail,
parsePaytoUri,
+ stringifyReservePaytoUri,
} from "@gnu-taler/taler-util";
import {
HttpRequestLibrary,
@@ -3370,8 +3372,7 @@ async function handleExchangeKycRespLegi(
accountPriv: reserve.reservePriv,
accountPub: reserve.reservePub,
});
- const requirementRow = kycBody.requirement_row;
- const reqUrl = new URL(`kyc-check/${requirementRow}`, exchangeBaseUrl);
+ const reqUrl = new URL(`kyc-check/${kycBody.h_payto}`, exchangeBaseUrl);
const resp = await wex.http.fetch(reqUrl.href, {
method: "GET",
headers: {
@@ -3466,13 +3467,19 @@ async function handleExchangeKycPendingLegitimization(
accountPriv: reserve.reservePriv,
accountPub: reserve.reservePub,
});
- const requirementRow = reserve.requirementRow;
- checkDbInvariant(!!requirementRow, "requirement row");
+
+ const reservePayto = stringifyReservePaytoUri(
+ exchange.baseUrl,
+ reserve.reservePub,
+ );
+
+ const paytoHash = encodeCrock(hashPaytoUri(reservePayto));
+
const resp = await wex.ws.runLongpollQueueing(
wex,
exchange.baseUrl,
async (timeoutMs) => {
- const reqUrl = new URL(`kyc-check/${requirementRow}`, exchange.baseUrl);
+ const reqUrl = new URL(`kyc-check/${paytoHash}`, exchange.baseUrl);
reqUrl.searchParams.set("timeout_ms", `${timeoutMs}`);
logger.info(`long-polling wallet KYC status at ${reqUrl.href}`);
return await wex.http.fetch(reqUrl.href, {
diff --git a/packages/taler-wallet-core/src/pay-peer-pull-credit.ts
b/packages/taler-wallet-core/src/pay-peer-pull-credit.ts
index 45ca93a40..7c69fbaa9 100644
--- a/packages/taler-wallet-core/src/pay-peer-pull-credit.ts
+++ b/packages/taler-wallet-core/src/pay-peer-pull-credit.ts
@@ -43,11 +43,11 @@ import {
TransactionState,
TransactionType,
WalletAccountMergeFlags,
- WalletKycUuid,
assertUnreachable,
checkDbInvariant,
+ codecForAccountKycStatus,
codecForAny,
- codecForWalletKycUuid,
+ codecForLegitimizationNeededResponse,
encodeCrock,
getRandomBytes,
j2s,
@@ -55,7 +55,10 @@ import {
stringifyTalerUri,
talerPaytoFromExchangeReserve,
} from "@gnu-taler/taler-util";
-import { readSuccessResponseJsonOrThrow } from "@gnu-taler/taler-util/http";
+import {
+ readResponseJsonOrThrow,
+ readSuccessResponseJsonOrThrow,
+} from "@gnu-taler/taler-util/http";
import {
PendingTaskType,
TaskIdStr,
@@ -71,7 +74,6 @@ import {
runWithClientCancellation,
} from "./common.js";
import {
- KycPendingInfo,
OperationRetryRecord,
PeerPullCreditRecord,
PeerPullPaymentCreditStatus,
@@ -262,6 +264,14 @@ export class PeerPullCreditTransactionContext implements
TransactionContext {
TaskIdentifiers.forPeerPullPaymentInitiation(pullCredit);
let pullCreditOrt = await tx.operationRetries.get(pullCreditOpId);
+ let kycUrl: string | undefined = undefined;
+ if (pullCredit.kycPaytoHash) {
+ kycUrl = new URL(
+ `kyc-spa/${pullCredit.kycPaytoHash}`,
+ pullCredit.exchangeBaseUrl,
+ ).href;
+ }
+
if (wsr) {
if (wsr.wgInfo.withdrawalType !== WithdrawalRecordType.PeerPullCredit) {
throw Error(`Unexpected withdrawalType: ${wsr.wgInfo.withdrawalType}`);
@@ -308,7 +318,8 @@ export class PeerPullCreditTransactionContext implements
TransactionContext {
tag: TransactionType.PeerPullCredit,
pursePub: pullCredit.pursePub,
}),
- kycUrl: pullCredit.kycUrl,
+ // FIXME: Is this the KYC URL of the withdrawal group?!
+ kycUrl: kycUrl,
...(wsrOrt?.lastError
? {
error: silentWithdrawalErrorForInvoice
@@ -343,7 +354,9 @@ export class PeerPullCreditTransactionContext implements
TransactionContext {
tag: TransactionType.PeerPullCredit,
pursePub: pullCredit.pursePub,
}),
- kycUrl: pullCredit.kycUrl,
+ kycUrl,
+ kycAccessToken: pullCredit.kycAccessToken,
+ kycPaytoHash: pullCredit.kycPaytoHash,
...(pullCreditOrt?.lastError ? { error: pullCreditOrt.lastError } : {}),
};
}
@@ -758,7 +771,7 @@ async function longpollKycStatus(
wex: WalletExecutionContext,
pursePub: string,
exchangeUrl: string,
- kycInfo: KycPendingInfo,
+ kycPaytoHash: string,
): Promise<TaskRunResult> {
// FIXME: What if this changes? Should be part of the p2p record
const mergeReserveInfo = await getMergeReserveInfo(wex, {
@@ -771,7 +784,7 @@ async function longpollKycStatus(
});
const ctx = new PeerPullCreditTransactionContext(wex, pursePub);
- const url = new URL(`kyc-check/${kycInfo.requirementRow}`, exchangeUrl);
+ const url = new URL(`kyc-check/${kycPaytoHash}`, exchangeUrl);
const kycStatusRes = await wex.ws.runLongpollQueueing(
wex,
url.hostname,
@@ -1049,9 +1062,9 @@ async function handlePeerPullCreditCreatePurse(
if (httpResp.status === HttpStatusCode.UnavailableForLegalReasons) {
const respJson = await httpResp.json();
- const kycPending = codecForWalletKycUuid().decode(respJson);
+ const kycPending = codecForLegitimizationNeededResponse().decode(respJson);
logger.info(`kyc uuid response: ${j2s(kycPending)}`);
- return processPeerPullCreditKycRequired(wex, pullIni, kycPending);
+ return processPeerPullCreditKycRequired(wex, pullIni, kycPending.h_payto);
}
const resp = await readSuccessResponseJsonOrThrow(httpResp, codecForAny());
@@ -1111,14 +1124,14 @@ export async function processPeerPullCredit(
case PeerPullPaymentCreditStatus.PendingReady:
return queryPurseForPeerPullCredit(wex, pullIni);
case PeerPullPaymentCreditStatus.PendingMergeKycRequired: {
- if (!pullIni.kycInfo) {
- throw Error("invalid state, kycInfo required");
+ if (!pullIni.kycPaytoHash) {
+ throw Error("invalid state, kycPaytoHash required");
}
return await longpollKycStatus(
wex,
pursePub,
pullIni.exchangeBaseUrl,
- pullIni.kycInfo,
+ pullIni.kycPaytoHash,
);
}
case PeerPullPaymentCreditStatus.PendingCreatePurse:
@@ -1217,13 +1230,7 @@ async function processPeerPullCreditBalanceKyc(
return TransitionResult.stay();
}
rec.status = PeerPullPaymentCreditStatus.PendingBalanceKycRequired;
- delete rec.kycInfo;
rec.kycAccessToken = ret.walletKycAccessToken;
- // FIXME: #9109 this should not be constructed here, it should be an
opaque URL from exchange response
- rec.kycUrl = new URL(
- `kyc-spa/${ret.walletKycAccessToken}`,
- exchangeBaseUrl,
- ).href;
return TransitionResult.transition(rec);
});
return TaskRunResult.progress();
@@ -1235,7 +1242,7 @@ async function processPeerPullCreditBalanceKyc(
async function processPeerPullCreditKycRequired(
wex: WalletExecutionContext,
peerIni: PeerPullCreditRecord,
- kycPending: WalletKycUuid,
+ kycPayoHash: string,
): Promise<TaskRunResult> {
const ctx = new PeerPullCreditTransactionContext(wex, peerIni.pursePub);
const { pursePub } = peerIni;
@@ -1250,10 +1257,7 @@ async function processPeerPullCreditKycRequired(
accountPub: mergeReserveInfo.reservePub,
});
- const url = new URL(
- `kyc-check/${kycPending.requirement_row}`,
- peerIni.exchangeBaseUrl,
- );
+ const url = new URL(`kyc-check/${kycPayoHash}`, peerIni.exchangeBaseUrl);
logger.info(`kyc url ${url.href}`);
const kycStatusRes = await wex.http.fetch(url.href, {
@@ -1271,7 +1275,10 @@ async function processPeerPullCreditKycRequired(
logger.warn("kyc requested, but already fulfilled");
return TaskRunResult.backoff();
} else if (kycStatusRes.status === HttpStatusCode.Accepted) {
- const kycStatus = await kycStatusRes.json();
+ const kycStatus = await readResponseJsonOrThrow(
+ kycStatusRes,
+ codecForAccountKycStatus(),
+ );
logger.info(`kyc status: ${j2s(kycStatus)}`);
const { transitionInfo, result } = await wex.db.runReadWriteTx(
{ storeNames: ["peerPullCredit", "transactionsMeta"] },
@@ -1284,11 +1291,11 @@ async function processPeerPullCreditKycRequired(
};
}
const oldTxState = computePeerPullCreditTransactionState(peerInc);
- peerInc.kycInfo = {
- paytoHash: kycPending.h_payto,
- requirementRow: kycPending.requirement_row,
- };
- peerInc.kycUrl = kycStatus.kyc_url;
+ peerInc.kycPaytoHash = kycPayoHash;
+ logger.info(
+ `setting peer-pull-credit kyc payto hash to ${kycPayoHash}`,
+ );
+ peerInc.kycAccessToken = kycStatus.access_token;
peerInc.status = PeerPullPaymentCreditStatus.PendingMergeKycRequired;
const newTxState = computePeerPullCreditTransactionState(peerInc);
await tx.peerPullCredit.put(peerInc);
@@ -1300,7 +1307,7 @@ async function processPeerPullCreditKycRequired(
},
);
notifyTransition(wex, ctx.transactionId, transitionInfo);
- return TaskRunResult.backoff();
+ return result;
} else {
throw Error(`unexpected response from kyc-check (${kycStatusRes.status})`);
}
diff --git a/packages/taler-wallet-core/src/pay-peer-push-credit.ts
b/packages/taler-wallet-core/src/pay-peer-push-credit.ts
index 7c131c45a..d18f8712d 100644
--- a/packages/taler-wallet-core/src/pay-peer-push-credit.ts
+++ b/packages/taler-wallet-core/src/pay-peer-push-credit.ts
@@ -23,6 +23,7 @@ import {
ExchangePurseMergeRequest,
ExchangeWalletKycStatus,
HttpStatusCode,
+ LegitimizationNeededResponse,
Logger,
NotificationType,
PeerContractTerms,
@@ -37,13 +38,13 @@ import {
TransactionState,
TransactionType,
WalletAccountMergeFlags,
- WalletKycUuid,
assertUnreachable,
checkDbInvariant,
+ codecForAccountKycStatus,
codecForAny,
codecForExchangeGetContractResponse,
+ codecForLegitimizationNeededResponse,
codecForPeerContractTerms,
- codecForWalletKycUuid,
decodeCrock,
eddsaGetPublic,
encodeCrock,
@@ -52,7 +53,10 @@ import {
parsePayPushUri,
talerPaytoFromExchangeReserve,
} from "@gnu-taler/taler-util";
-import { readSuccessResponseJsonOrThrow } from "@gnu-taler/taler-util/http";
+import {
+ readResponseJsonOrThrow,
+ readSuccessResponseJsonOrThrow,
+} from "@gnu-taler/taler-util/http";
import {
PendingTaskType,
TaskIdStr,
@@ -67,7 +71,6 @@ import {
requireExchangeTosAcceptedOrThrow,
} from "./common.js";
import {
- KycPendingInfo,
OperationRetryRecord,
PeerPushCreditStatus,
PeerPushPaymentIncomingRecord,
@@ -263,6 +266,11 @@ export class PeerPushCreditTransactionContext implements
TransactionContext {
const peerContractTerms = ct.contractTermsRaw;
+ let kycUrl: string | undefined = undefined;
+ if (wg?.kycAccessToken && wg.exchangeBaseUrl) {
+ kycUrl = new URL(`kyc-spa/${wg.kycAccessToken}`,
wg.exchangeBaseUrl).href;
+ }
+
if (wg) {
if (wg.wgInfo.withdrawalType !== WithdrawalRecordType.PeerPushCredit) {
throw Error("invalid withdrawal group type for push payment credit");
@@ -291,8 +299,8 @@ export class PeerPushCreditTransactionContext implements
TransactionContext {
tag: TransactionType.PeerPushCredit,
peerPushCreditId: pushInc.peerPushCreditId,
}),
- kycUrl: wg.kycUrl,
- kycPaytoHash: wg.kycPending?.paytoHash,
+ kycUrl,
+ kycPaytoHash: wg.kycPaytoHash,
...(wgRetryRecord?.lastError ? { error: wgRetryRecord.lastError } :
{}),
};
}
@@ -313,8 +321,8 @@ export class PeerPushCreditTransactionContext implements
TransactionContext {
expiration: peerContractTerms.purse_expiration,
summary: peerContractTerms.summary,
},
- kycUrl: pushInc.kycUrl,
- kycPaytoHash: pushInc.kycInfo?.paytoHash,
+ kycUrl,
+ kycPaytoHash: pushInc.kycPaytoHash,
timestamp: timestampPreciseFromDb(pushInc.timestamp),
transactionId: constructTransactionIdentifier({
tag: TransactionType.PeerPushCredit,
@@ -750,7 +758,7 @@ async function longpollKycStatus(
wex: WalletExecutionContext,
peerPushCreditId: string,
exchangeUrl: string,
- kycInfo: KycPendingInfo,
+ kycPaytoHash: string,
): Promise<TaskRunResult> {
const ctx = new PeerPushCreditTransactionContext(wex, peerPushCreditId);
@@ -764,7 +772,7 @@ async function longpollKycStatus(
accountPub: mergeReserveInfo.reservePub,
});
- const url = new URL(`kyc-check/${kycInfo.requirementRow}`, exchangeUrl);
+ const url = new URL(`kyc-check/${kycPaytoHash}`, exchangeUrl);
logger.info(`kyc url ${url.href}`);
const kycStatusRes = await wex.ws.runLongpollQueueing(
wex,
@@ -816,7 +824,7 @@ async function longpollKycStatus(
async function processPeerPushCreditKycRequired(
wex: WalletExecutionContext,
peerInc: PeerPushPaymentIncomingRecord,
- kycPending: WalletKycUuid,
+ kycPending: LegitimizationNeededResponse,
): Promise<TaskRunResult> {
const transactionId = constructTransactionIdentifier({
tag: TransactionType.PeerPushCredit,
@@ -839,7 +847,7 @@ async function processPeerPushCreditKycRequired(
});
const url = new URL(
- `kyc-check/${kycPending.requirement_row}`,
+ `kyc-check/${kycPending.h_payto}`,
peerInc.exchangeBaseUrl,
);
@@ -863,6 +871,10 @@ async function processPeerPushCreditKycRequired(
} else if (kycStatusRes.status === HttpStatusCode.Accepted) {
const kycStatus = await kycStatusRes.json();
logger.info(`kyc status: ${j2s(kycStatus)}`);
+ const statusResp = await readResponseJsonOrThrow(
+ kycStatusRes,
+ codecForAccountKycStatus(),
+ );
const { transitionInfo, result } = await wex.db.runReadWriteTx(
{ storeNames: ["peerPushCredit", "transactionsMeta"] },
async (tx) => {
@@ -874,11 +886,8 @@ async function processPeerPushCreditKycRequired(
};
}
const oldTxState = computePeerPushCreditTransactionState(peerInc);
- peerInc.kycInfo = {
- paytoHash: kycPending.h_payto,
- requirementRow: kycPending.requirement_row,
- };
- peerInc.kycUrl = kycStatus.kyc_url;
+ peerInc.kycPaytoHash = kycPending.h_payto;
+ peerInc.kycAccessToken = statusResp.access_token;
peerInc.status = PeerPushCreditStatus.PendingMergeKycRequired;
const newTxState = computePeerPushCreditTransactionState(peerInc);
await tx.peerPushCredit.put(peerInc);
@@ -979,9 +988,12 @@ async function handlePendingMerge(
if (mergeHttpResp.status === HttpStatusCode.UnavailableForLegalReasons) {
const respJson = await mergeHttpResp.json();
- const kycPending = codecForWalletKycUuid().decode(respJson);
- logger.info(`kyc uuid response: ${j2s(kycPending)}`);
- return processPeerPushCreditKycRequired(wex, peerInc, kycPending);
+ const kycLegiNeededResp =
+ codecForLegitimizationNeededResponse().decode(respJson);
+ logger.info(
+ `kyc legitimization needed response: ${j2s(kycLegiNeededResp)}`,
+ );
+ return processPeerPushCreditKycRequired(wex, peerInc, kycLegiNeededResp);
}
logger.trace(`merge request: ${j2s(mergeReq)}`);
@@ -1163,14 +1175,14 @@ export async function processPeerPushCredit(
switch (peerInc.status) {
case PeerPushCreditStatus.PendingMergeKycRequired: {
- if (!peerInc.kycInfo) {
- throw Error("invalid state, kycInfo required");
+ if (!peerInc.kycPaytoHash) {
+ throw Error("invalid state, kycPaytoHash required");
}
return await longpollKycStatus(
wex,
peerPushCreditId,
peerInc.exchangeBaseUrl,
- peerInc.kycInfo,
+ peerInc.kycPaytoHash,
);
}
case PeerPushCreditStatus.PendingMerge: {
@@ -1255,13 +1267,7 @@ async function processPeerPushCreditBalanceKyc(
return TransitionResult.stay();
}
rec.status = PeerPushCreditStatus.PendingBalanceKycRequired;
- delete rec.kycInfo;
rec.kycAccessToken = ret.walletKycAccessToken;
- // FIXME: #9109 this should not be constructed here, it should be an
opaque URL from exchange response
- rec.kycUrl = new URL(
- `kyc-spa/${ret.walletKycAccessToken}`,
- exchangeBaseUrl,
- ).href;
return TransitionResult.transition(rec);
});
return TaskRunResult.progress();
diff --git a/packages/taler-wallet-core/src/withdraw.ts
b/packages/taler-wallet-core/src/withdraw.ts
index b0c27bd8a..0d47e08c7 100644
--- a/packages/taler-wallet-core/src/withdraw.ts
+++ b/packages/taler-wallet-core/src/withdraw.ts
@@ -93,8 +93,8 @@ import {
codecForCashinConversionResponse,
codecForConversionBankConfig,
codecForExchangeWithdrawBatchResponse,
+ codecForLegitimizationNeededResponse,
codecForReserveStatus,
- codecForWalletKycUuid,
codecForWithdrawOperationStatusResponse,
encodeCrock,
getErrorDetailFromException,
@@ -135,7 +135,6 @@ import {
CoinSourceType,
DenominationRecord,
DenominationVerificationStatus,
- KycPendingInfo,
OperationRetryRecord,
PlanchetRecord,
PlanchetStatus,
@@ -241,9 +240,9 @@ function buildTransactionForBankIntegratedWithdraw(
wg.status === WithdrawalGroupStatus.Done ||
wg.status === WithdrawalGroupStatus.PendingReady,
},
- kycUrl: wg.kycUrl,
+ kycUrl: kycDetails?.kycUrl,
kycAccessToken: wg.kycAccessToken,
- kycPaytoHash: wg.kycPending?.paytoHash,
+ kycPaytoHash: wg.kycPaytoHash,
timestamp: timestampPreciseFromDb(wg.timestampStart),
transactionId: constructTransactionIdentifier({
tag: TransactionType.Withdrawal,
@@ -302,7 +301,7 @@ function buildTransactionForManualWithdraw(
wg.status === WithdrawalGroupStatus.PendingReady,
reserveClosingDelay: exchangeDetails?.reserveClosingDelay ?? { d_us: 0 },
},
- kycUrl: wg.kycUrl,
+ kycUrl: kycDetails?.kycUrl,
exchangeBaseUrl: wg.exchangeBaseUrl,
timestamp: timestampPreciseFromDb(wg.timestampStart),
transactionId: constructTransactionIdentifier({
@@ -365,13 +364,20 @@ export class WithdrawTransactionContext implements
TransactionContext {
let kycDetails: TxKycDetails | undefined = undefined;
+ if (!exchangeBaseUrl) {
+ return undefined;
+ }
+
switch (withdrawalGroupRecord.status) {
case WithdrawalGroupStatus.PendingKyc:
case WithdrawalGroupStatus.SuspendedKyc: {
kycDetails = {
kycAccessToken: withdrawalGroupRecord.kycAccessToken,
- kycPaytoHash: withdrawalGroupRecord.kycPending?.paytoHash,
- kycUrl: withdrawalGroupRecord.kycUrl,
+ kycPaytoHash: withdrawalGroupRecord.kycPaytoHash,
+ kycUrl: new URL(
+ `kyc-spa/${withdrawalGroupRecord.kycAccessToken}`,
+ exchangeBaseUrl,
+ ).href,
};
break;
}
@@ -1027,13 +1033,8 @@ async function processWithdrawalGroupBalanceKyc(
return TransitionResult.stay();
}
wg.status = WithdrawalGroupStatus.PendingBalanceKyc;
- wg.kycPending = undefined;
wg.kycAccessToken = ret.walletKycAccessToken;
- // FIXME: #9109 this should not be constructed here, it should be an
opaque URL from exchange response
- wg.kycUrl = new URL(
- `kyc-spa/${ret.walletKycAccessToken}`,
- exchangeBaseUrl,
- ).href;
+ delete wg.kycPaytoHash;
return TransitionResult.transition(wg);
});
return TaskRunResult.progress();
@@ -1152,7 +1153,9 @@ export async function getBankWithdrawalInfo(
if (resp.detail) {
throw TalerError.fromUncheckedDetail(resp.detail);
} else {
- throw TalerError.fromException(new Error("failed to get bank remote
config"))
+ throw TalerError.fromException(
+ new Error("failed to get bank remote config"),
+ );
}
}
const { body: status } = resp;
@@ -1347,13 +1350,6 @@ interface WithdrawalBatchResult {
batchResp: ExchangeWithdrawBatchResponse;
}
-// FIXME: Move to exchange API types
-enum ExchangeAmlStatus {
- Normal = 0,
- Pending = 1,
- Frozen = 2,
-}
-
/**
* Transition a transaction from pending(ready)
* into a pending(kyc|aml) state, in case KYC is required.
@@ -1367,20 +1363,17 @@ async function handleKycRequired(
): Promise<void> {
logger.info("withdrawal requires KYC");
const respJson = await resp.json();
- const uuidResp = codecForWalletKycUuid().decode(respJson);
+ const legiRequiredResp =
+ codecForLegitimizationNeededResponse().decode(respJson);
const withdrawalGroupId = withdrawalGroup.withdrawalGroupId;
const ctx = new WithdrawTransactionContext(wex, withdrawalGroupId);
- logger.info(`kyc uuid response: ${j2s(uuidResp)}`);
+ logger.info(`kyc uuid response: ${j2s(legiRequiredResp)}`);
const exchangeUrl = withdrawalGroup.exchangeBaseUrl;
- const kycInfo: KycPendingInfo = {
- paytoHash: uuidResp.h_payto,
- requirementRow: uuidResp.requirement_row,
- };
const sigResp = await wex.cryptoApi.signWalletKycAuth({
accountPriv: withdrawalGroup.reservePriv,
accountPub: withdrawalGroup.reservePub,
});
- const url = new URL(`kyc-check/${kycInfo.requirementRow}`, exchangeUrl);
+ const url = new URL(`kyc-check/${legiRequiredResp.h_payto}`, exchangeUrl);
logger.info(`kyc url ${url.href}`);
// We do not longpoll here, as this is the initial request to get
information about the KYC.
const kycStatusRes = await wex.http.fetch(url.href, {
@@ -1434,16 +1427,7 @@ async function handleKycRequired(
if (wg2.status !== WithdrawalGroupStatus.PendingReady) {
return TransitionResult.stay();
}
- // FIXME: Why not just store the whole kycState?!
- wg2.kycPending = {
- paytoHash: uuidResp.h_payto,
- requirementRow: uuidResp.requirement_row,
- };
- // FIXME: #9109 this should not be constructed here, it should be an
opaque URL from exchange response
- wg2.kycUrl = new URL(
- `kyc-spa/${kycStatus.access_token}`,
- exchangeUrl,
- ).href;
+ wg2.kycPaytoHash = legiRequiredResp.h_payto;
wg2.kycAccessToken = kycStatus.access_token;
wg2.status = WithdrawalGroupStatus.PendingKyc;
return TransitionResult.transition(wg2);
@@ -2019,12 +2003,12 @@ async function processWithdrawalGroupPendingKyc(
wex,
withdrawalGroup.withdrawalGroupId,
);
- const kycInfo = withdrawalGroup.kycPending;
- if (!kycInfo) {
+ const kycPaytoHash = withdrawalGroup.kycPaytoHash;
+ if (!kycPaytoHash) {
throw Error("no kyc info available in pending(kyc)");
}
const exchangeUrl = withdrawalGroup.exchangeBaseUrl;
- const url = new URL(`kyc-check/${kycInfo.requirementRow}`, exchangeUrl);
+ const url = new URL(`kyc-check/${kycPaytoHash}`, exchangeUrl);
const sigResp = await wex.cryptoApi.signWalletKycAuth({
accountPriv: withdrawalGroup.reservePriv,
accountPub: withdrawalGroup.reservePub,
@@ -2056,8 +2040,8 @@ async function processWithdrawalGroupPendingKyc(
}
switch (rec.status) {
case WithdrawalGroupStatus.PendingKyc: {
- delete rec.kycPending;
- delete rec.kycUrl;
+ delete rec.kycAccessToken;
+ delete rec.kycAccessToken;
rec.status = WithdrawalGroupStatus.PendingReady;
return TransitionResult.transition(rec);
}
--
To stop receiving notification emails like this one, please contact
gnunet@gnunet.org.
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [taler-wallet-core] branch master updated: wallet-core: use new /kyc-check/H_PAYTO API, fix test,
gnunet <=