gnunet-svn
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[taler-wallet-core] branch master updated: wallet-core: use long-polling


From: gnunet
Subject: [taler-wallet-core] branch master updated: wallet-core: use long-polling for P2P kyc
Date: Mon, 05 Jun 2023 13:33:18 +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 e671880b9 wallet-core: use long-polling for P2P kyc
e671880b9 is described below

commit e671880b9e11b020c3fc797fb45e6e4b8ee3ee62
Author: Florian Dold <florian@dold.me>
AuthorDate: Mon Jun 5 13:33:14 2023 +0200

    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 +
 .../taler-wallet-core/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<OperationAttemptResult> {
+  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<OperationAttemptResult> {
+  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<OperationAttemptResult> {
+  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<OperationAttemptResult> {
+  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

-- 
To stop receiving notification emails like this one, please contact
gnunet@gnunet.org.



reply via email to

[Prev in Thread] Current Thread [Next in Thread]