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: support KYC dire


From: gnunet
Subject: [taler-wallet-core] branch master updated: wallet-core: support KYC directly on deposit in deposit tx, test
Date: Thu, 05 Sep 2024 21:15:25 +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 5402b00b7 wallet-core: support KYC directly on deposit in deposit tx, 
test
5402b00b7 is described below

commit 5402b00b796011005f52e200c856832f225ffaf9
Author: Florian Dold <florian@dold.me>
AuthorDate: Thu Sep 5 21:15:22 2024 +0200

    wallet-core: support KYC directly on deposit in deposit tx, test
---
 .../integrationtests/test-kyc-deposit-deposit.ts   | 295 +++++++++++++++++++++
 .../src/integrationtests/testrunner.ts             |   2 +
 packages/taler-wallet-core/src/balance.ts          |   8 +-
 packages/taler-wallet-core/src/db.ts               |  13 +-
 packages/taler-wallet-core/src/deposits.ts         | 144 +++++++---
 .../taler-wallet-core/src/pay-peer-push-credit.ts  |   7 +-
 6 files changed, 423 insertions(+), 46 deletions(-)

diff --git 
a/packages/taler-harness/src/integrationtests/test-kyc-deposit-deposit.ts 
b/packages/taler-harness/src/integrationtests/test-kyc-deposit-deposit.ts
new file mode 100644
index 000000000..2ee58c7d8
--- /dev/null
+++ b/packages/taler-harness/src/integrationtests/test-kyc-deposit-deposit.ts
@@ -0,0 +1,295 @@
+/*
+ This file is part of GNU Taler
+ (C) 2020 Taler Systems S.A.
+
+ GNU Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+ */
+
+/**
+ * Imports.
+ */
+import {
+  TalerCorebankApiClient,
+  TransactionMajorState,
+  TransactionMinorState,
+} from "@gnu-taler/taler-util";
+import {
+  createSyncCryptoApi,
+  EddsaKeypairStrings,
+  WalletApiOperation,
+} from "@gnu-taler/taler-wallet-core";
+import { CoinConfig, defaultCoinConfig } from "../harness/denomStructures.js";
+import {
+  BankService,
+  DbInfo,
+  ExchangeService,
+  generateRandomPayto,
+  GlobalTestState,
+  HarnessExchangeBankAccount,
+  setupDb,
+  WalletClient,
+  WalletService,
+} from "../harness/harness.js";
+import {
+  EnvOptions,
+  postAmlDecisionNoRules,
+  withdrawViaBankV3,
+} from "../harness/helpers.js";
+
+interface KycTestEnv {
+  commonDb: DbInfo;
+  bankClient: TalerCorebankApiClient;
+  exchange: ExchangeService;
+  exchangeBankAccount: HarnessExchangeBankAccount;
+  walletClient: WalletClient;
+  walletService: WalletService;
+  amlKeypair: EddsaKeypairStrings;
+}
+
+async function createKycTestkudosEnvironment(
+  t: GlobalTestState,
+  coinConfig: CoinConfig[] = defaultCoinConfig.map((x) => x("TESTKUDOS")),
+  opts: EnvOptions = {},
+): Promise<KycTestEnv> {
+  const db = await setupDb(t);
+
+  const bank = await BankService.create(t, {
+    allowRegistrations: true,
+    currency: "TESTKUDOS",
+    database: db.connStr,
+    httpPort: 8082,
+  });
+
+  const exchange = ExchangeService.create(t, {
+    name: "testexchange-1",
+    currency: "TESTKUDOS",
+    httpPort: 8081,
+    database: db.connStr,
+  });
+
+  let receiverName = "Exchange";
+  let exchangeBankUsername = "exchange";
+  let exchangeBankPassword = "mypw";
+  let exchangePaytoUri = generateRandomPayto(exchangeBankUsername);
+
+  await exchange.addBankAccount("1", {
+    accountName: exchangeBankUsername,
+    accountPassword: exchangeBankPassword,
+    wireGatewayApiBaseUrl: new URL(
+      "accounts/exchange/taler-wire-gateway/",
+      bank.baseUrl,
+    ).href,
+    accountPaytoUri: exchangePaytoUri,
+  });
+
+  bank.setSuggestedExchange(exchange, exchangePaytoUri);
+
+  await bank.start();
+
+  await bank.pingUntilAvailable();
+
+  const bankClient = new TalerCorebankApiClient(bank.corebankApiBaseUrl, {
+    auth: {
+      username: "admin",
+      password: "adminpw",
+    },
+  });
+
+  await bankClient.registerAccountExtended({
+    name: receiverName,
+    password: exchangeBankPassword,
+    username: exchangeBankUsername,
+    is_taler_exchange: true,
+    payto_uri: exchangePaytoUri,
+  });
+
+  const ageMaskSpec = opts.ageMaskSpec;
+
+  if (ageMaskSpec) {
+    exchange.enableAgeRestrictions(ageMaskSpec);
+    // Enable age restriction for all coins.
+    exchange.addCoinConfigList(
+      coinConfig.map((x) => ({
+        ...x,
+        name: `${x.name}-age`,
+        ageRestricted: true,
+      })),
+    );
+    // For mixed age restrictions, we also offer coins without age restrictions
+    if (opts.mixedAgeRestriction) {
+      exchange.addCoinConfigList(
+        coinConfig.map((x) => ({ ...x, ageRestricted: false })),
+      );
+    }
+  } else {
+    exchange.addCoinConfigList(coinConfig);
+  }
+
+  await exchange.modifyConfig(async (config) => {
+    config.setString("exchange", "enable_kyc", "yes");
+
+    config.setString("KYC-RULE-R1", "operation_type", "deposit");
+    config.setString("KYC-RULE-R1", "enabled", "yes");
+    config.setString("KYC-RULE-R1", "exposed", "yes");
+    config.setString("KYC-RULE-R1", "is_and_combinator", "yes");
+    config.setString("KYC-RULE-R1", "threshold", "TESTKUDOS:5");
+    config.setString("KYC-RULE-R1", "timeframe", "1d");
+    config.setString("KYC-RULE-R1", "next_measures", "M1");
+
+    config.setString("KYC-MEASURE-M1", "check_name", "C1");
+    config.setString("KYC-MEASURE-M1", "context", "{}");
+    config.setString("KYC-MEASURE-M1", "program", "P1");
+
+    config.setString("AML-PROGRAM-P1", "command", "/bin/true");
+    config.setString("AML-PROGRAM-P1", "enabled", "true");
+    config.setString("AML-PROGRAM-P1", "description", "this does nothing");
+    config.setString("AML-PROGRAM-P1", "fallback", "M1");
+
+    config.setString("KYC-CHECK-C1", "type", "INFO");
+    config.setString("KYC-CHECK-C1", "description", "my check!");
+    config.setString("KYC-CHECK-C1", "fallback", "M1");
+  });
+
+  await exchange.start();
+
+  const cryptoApi = createSyncCryptoApi();
+  const amlKeypair = await cryptoApi.createEddsaKeypair({});
+
+  await exchange.enableAmlAccount(amlKeypair.pub, "Alice");
+
+  const walletService = new WalletService(t, {
+    name: "wallet",
+    useInMemoryDb: true,
+  });
+  await walletService.start();
+  await walletService.pingUntilAvailable();
+
+  const walletClient = new WalletClient({
+    name: "wallet",
+    unixPath: walletService.socketPath,
+    onNotification(n) {
+      console.log("got notification", n);
+    },
+  });
+  await walletClient.connect();
+  await walletClient.client.call(WalletApiOperation.InitWallet, {
+    config: {
+      testing: {
+        skipDefaults: true,
+      },
+    },
+  });
+
+  console.log("setup done!");
+
+  return {
+    commonDb: db,
+    exchange,
+    amlKeypair,
+    walletClient,
+    walletService,
+    bankClient,
+    exchangeBankAccount: {
+      accountName: "",
+      accountPassword: "",
+      accountPaytoUri: "",
+      wireGatewayApiBaseUrl: "",
+    },
+  };
+}
+
+export async function runKycDepositDepositTest(t: GlobalTestState) {
+  // Set up test environment
+
+  const { walletClient, bankClient, exchange, amlKeypair } =
+    await createKycTestkudosEnvironment(t);
+
+  // Withdraw digital cash into the wallet.
+
+  const wres = await withdrawViaBankV3(t, {
+    bankClient,
+    amount: "TESTKUDOS:50",
+    exchange: exchange,
+    walletClient: walletClient,
+  });
+
+  await wres.withdrawalFinishedCond;
+
+  const depositResp = await walletClient.call(
+    WalletApiOperation.CreateDepositGroup,
+    {
+      amount: "TESTKUDOS:10",
+      depositPaytoUri: wres.accountPaytoUri,
+    },
+  );
+
+  await walletClient.call(WalletApiOperation.TestingWaitTransactionState, {
+    transactionId: depositResp.transactionId,
+    txState: {
+      major: TransactionMajorState.Pending,
+      minor: TransactionMinorState.Track,
+    },
+  });
+
+  await exchange.runAggregatorOnceWithTimetravel({
+    timetravelMicroseconds: 1000 * 1000 * 60 * 60 * 3,
+  });
+
+  await exchange.runTransferOnceWithTimetravel({
+    timetravelMicroseconds: 1000 * 1000 * 60 * 60 * 3,
+  });
+
+  console.log("waiting for kyc-required");
+
+  await walletClient.call(WalletApiOperation.TestingWaitTransactionState, {
+    transactionId: depositResp.transactionId,
+    txState: {
+      major: TransactionMajorState.Pending,
+      minor: TransactionMinorState.KycRequired,
+    },
+  });
+
+  const txDetails = await walletClient.call(
+    WalletApiOperation.GetTransactionById,
+    {
+      transactionId: depositResp.transactionId,
+    },
+  );
+
+  const kycPaytoHash = txDetails.kycPaytoHash;
+
+  t.assertTrue(!!kycPaytoHash);
+
+  await postAmlDecisionNoRules(t, {
+    amlPriv: amlKeypair.priv,
+    amlPub: amlKeypair.pub,
+    exchangeBaseUrl: exchange.baseUrl,
+    paytoHash: kycPaytoHash,
+  });
+
+  await exchange.runAggregatorOnceWithTimetravel({
+    timetravelMicroseconds: 1000 * 1000 * 60 * 60 * 3,
+  });
+
+  await exchange.runTransferOnceWithTimetravel({
+    timetravelMicroseconds: 1000 * 1000 * 60 * 60 * 3,
+  });
+
+  await walletClient.call(WalletApiOperation.TestingWaitTransactionState, {
+    transactionId: depositResp.transactionId,
+    txState: {
+      major: TransactionMajorState.Done,
+    },
+  });
+}
+
+runKycDepositDepositTest.suites = ["wallet"];
diff --git a/packages/taler-harness/src/integrationtests/testrunner.ts 
b/packages/taler-harness/src/integrationtests/testrunner.ts
index f7ae50149..32bac3fdc 100644
--- a/packages/taler-harness/src/integrationtests/testrunner.ts
+++ b/packages/taler-harness/src/integrationtests/testrunner.ts
@@ -49,6 +49,7 @@ import { runFeeRegressionTest } from 
"./test-fee-regression.js";
 import { runForcedSelectionTest } from "./test-forced-selection.js";
 import { runKycBalanceWithdrawalTest } from "./test-kyc-balance-withdrawal.js";
 import { runKycDepositAggregateTest } from "./test-kyc-deposit-aggregate.js";
+import { runKycDepositDepositTest } from "./test-kyc-deposit-deposit.js";
 import { runKycExchangeWalletTest } from "./test-kyc-exchange-wallet.js";
 import { runKycFormWithdrawalTest } from "./test-kyc-form-withdrawal.js";
 import { runKycNewMeasureTest } from "./test-kyc-new-measure.js";
@@ -260,6 +261,7 @@ const allTests: TestMainFunction[] = [
   runKycFormWithdrawalTest,
   runKycBalanceWithdrawalTest,
   runKycNewMeasureTest,
+  runKycDepositDepositTest,
 ];
 
 export interface TestRunSpec {
diff --git a/packages/taler-wallet-core/src/balance.ts 
b/packages/taler-wallet-core/src/balance.ts
index 396efda1f..99979f59a 100644
--- a/packages/taler-wallet-core/src/balance.ts
+++ b/packages/taler-wallet-core/src/balance.ts
@@ -449,14 +449,14 @@ export async function getBalancesInsideTransaction(
       for (const [e, x] of Object.entries(perExchange)) {
         const currency = Amounts.currencyOf(dgRecord.amount);
         switch (dgRecord.operationStatus) {
-          case DepositOperationStatus.SuspendedKyc:
-          case DepositOperationStatus.PendingKyc:
+          case DepositOperationStatus.SuspendedAggregateKyc:
+          case DepositOperationStatus.PendingAggregateKyc:
             await balanceStore.setFlagOutgoingKyc(currency, e);
         }
 
         switch (dgRecord.operationStatus) {
-          case DepositOperationStatus.SuspendedKyc:
-          case DepositOperationStatus.PendingKyc:
+          case DepositOperationStatus.SuspendedAggregateKyc:
+          case DepositOperationStatus.PendingAggregateKyc:
           case DepositOperationStatus.PendingTrack:
           case DepositOperationStatus.SuspendedAborting:
           case DepositOperationStatus.SuspendedDeposit:
diff --git a/packages/taler-wallet-core/src/db.ts 
b/packages/taler-wallet-core/src/db.ts
index 99b69135a..ba33c5555 100644
--- a/packages/taler-wallet-core/src/db.ts
+++ b/packages/taler-wallet-core/src/db.ts
@@ -1725,15 +1725,18 @@ export interface BackupProviderRecord {
 
 export enum DepositOperationStatus {
   PendingDeposit = 0x0100_0000,
+  SuspendedDeposit = 0x0110_0000,
+
   PendingTrack = 0x0100_0001,
-  PendingKyc = 0x0100_0002,
+  SuspendedTrack = 0x0110_0001,
 
-  Aborting = 0x0103_0000,
+  PendingAggregateKyc = 0x0100_0002,
+  SuspendedAggregateKyc = 0x0110_0002,
 
-  SuspendedDeposit = 0x0110_0000,
-  SuspendedTrack = 0x0110_0001,
-  SuspendedKyc = 0x0110_0002,
+  PendingDepositKyc = 0x0100_0003,
+  SuspendedDepositKyc = 0x0110_0003,
 
+  Aborting = 0x0103_0000,
   SuspendedAborting = 0x0113_0000,
 
   Finished = 0x0500_0000,
diff --git a/packages/taler-wallet-core/src/deposits.ts 
b/packages/taler-wallet-core/src/deposits.ts
index da69530f7..371d7cf70 100644
--- a/packages/taler-wallet-core/src/deposits.ts
+++ b/packages/taler-wallet-core/src/deposits.ts
@@ -63,6 +63,7 @@ import {
   checkLogicInvariant,
   codecForAccountKycStatus,
   codecForBatchDepositSuccess,
+  codecForLegitimizationNeededResponse,
   codecForTackTransactionAccepted,
   codecForTackTransactionWired,
   encodeCrock,
@@ -94,7 +95,6 @@ import {
   DepositElementStatus,
   DepositGroupRecord,
   DepositInfoPerExchange,
-  DepositKycInfo,
   DepositOperationStatus,
   DepositTrackingInfo,
   RefreshOperationStatus,
@@ -293,11 +293,23 @@ export class DepositTransactionContext implements 
TransactionContext {
         const oldState = computeDepositTransactionStatus(dg);
         let newOpStatus: DepositOperationStatus | undefined;
         switch (dg.operationStatus) {
+          case DepositOperationStatus.Aborted:
+          case DepositOperationStatus.Failed:
+          case DepositOperationStatus.Finished:
+          case DepositOperationStatus.SuspendedAborting:
+          case DepositOperationStatus.SuspendedAggregateKyc:
+          case DepositOperationStatus.SuspendedDeposit:
+          case DepositOperationStatus.SuspendedDepositKyc:
+          case DepositOperationStatus.SuspendedTrack:
+            break;
+          case DepositOperationStatus.PendingDepositKyc:
+            newOpStatus = DepositOperationStatus.SuspendedDepositKyc;
+            break;
           case DepositOperationStatus.PendingDeposit:
             newOpStatus = DepositOperationStatus.SuspendedDeposit;
             break;
-          case DepositOperationStatus.PendingKyc:
-            newOpStatus = DepositOperationStatus.SuspendedKyc;
+          case DepositOperationStatus.PendingAggregateKyc:
+            newOpStatus = DepositOperationStatus.SuspendedAggregateKyc;
             break;
           case DepositOperationStatus.PendingTrack:
             newOpStatus = DepositOperationStatus.SuspendedTrack;
@@ -305,6 +317,8 @@ export class DepositTransactionContext implements 
TransactionContext {
           case DepositOperationStatus.Aborting:
             newOpStatus = DepositOperationStatus.SuspendedAborting;
             break;
+          default:
+            assertUnreachable(dg.operationStatus);
         }
         if (!newOpStatus) {
           return undefined;
@@ -376,18 +390,32 @@ export class DepositTransactionContext implements 
TransactionContext {
         const oldState = computeDepositTransactionStatus(dg);
         let newOpStatus: DepositOperationStatus | undefined;
         switch (dg.operationStatus) {
+          case DepositOperationStatus.Aborted:
+          case DepositOperationStatus.Aborting:
+          case DepositOperationStatus.Failed:
+          case DepositOperationStatus.Finished:
+          case DepositOperationStatus.PendingAggregateKyc:
+          case DepositOperationStatus.PendingDeposit:
+          case DepositOperationStatus.PendingDepositKyc:
+          case DepositOperationStatus.PendingTrack:
+            break;
+          case DepositOperationStatus.SuspendedDepositKyc:
+            newOpStatus = DepositOperationStatus.PendingDepositKyc;
+            break;
           case DepositOperationStatus.SuspendedDeposit:
             newOpStatus = DepositOperationStatus.PendingDeposit;
             break;
           case DepositOperationStatus.SuspendedAborting:
             newOpStatus = DepositOperationStatus.Aborting;
             break;
-          case DepositOperationStatus.SuspendedKyc:
-            newOpStatus = DepositOperationStatus.PendingKyc;
+          case DepositOperationStatus.SuspendedAggregateKyc:
+            newOpStatus = DepositOperationStatus.PendingAggregateKyc;
             break;
           case DepositOperationStatus.SuspendedTrack:
             newOpStatus = DepositOperationStatus.PendingTrack;
             break;
+          default:
+            assertUnreachable(dg.operationStatus);
         }
         if (!newOpStatus) {
           return undefined;
@@ -459,7 +487,7 @@ export function computeDepositTransactionStatus(
         major: TransactionMajorState.Pending,
         minor: TransactionMinorState.Deposit,
       };
-    case DepositOperationStatus.PendingKyc:
+    case DepositOperationStatus.PendingAggregateKyc:
       return {
         major: TransactionMajorState.Pending,
         minor: TransactionMinorState.KycRequired,
@@ -469,7 +497,7 @@ export function computeDepositTransactionStatus(
         major: TransactionMajorState.Pending,
         minor: TransactionMinorState.Track,
       };
-    case DepositOperationStatus.SuspendedKyc:
+    case DepositOperationStatus.SuspendedAggregateKyc:
       return {
         major: TransactionMajorState.Suspended,
         minor: TransactionMinorState.KycRequired,
@@ -499,6 +527,18 @@ export function computeDepositTransactionStatus(
       return {
         major: TransactionMajorState.SuspendedAborting,
       };
+    case DepositOperationStatus.PendingDepositKyc:
+      return {
+        major: TransactionMajorState.Pending,
+        // We lie to the UI by hiding the specific KYC state.
+        minor: TransactionMinorState.KycRequired,
+      };
+    case DepositOperationStatus.SuspendedDepositKyc:
+      return {
+        major: TransactionMajorState.Suspended,
+        // We lie to the UI by hiding the specific KYC state.
+        minor: TransactionMinorState.KycRequired,
+      };
     default:
       assertUnreachable(dg.operationStatus);
   }
@@ -534,7 +574,7 @@ export function computeDepositTransactionActions(
       return [TransactionAction.Delete];
     case DepositOperationStatus.SuspendedAborting:
       return [TransactionAction.Resume, TransactionAction.Fail];
-    case DepositOperationStatus.PendingKyc:
+    case DepositOperationStatus.PendingAggregateKyc:
       return [
         TransactionAction.Retry,
         TransactionAction.Suspend,
@@ -546,10 +586,14 @@ export function computeDepositTransactionActions(
         TransactionAction.Suspend,
         TransactionAction.Abort,
       ];
-    case DepositOperationStatus.SuspendedKyc:
+    case DepositOperationStatus.SuspendedAggregateKyc:
       return [TransactionAction.Resume, TransactionAction.Fail];
     case DepositOperationStatus.SuspendedTrack:
       return [TransactionAction.Resume, TransactionAction.Abort];
+    case DepositOperationStatus.PendingDepositKyc:
+      return [TransactionAction.Resume, TransactionAction.Abort];
+    case DepositOperationStatus.SuspendedDepositKyc:
+      return [TransactionAction.Suspend, TransactionAction.Abort];
     default:
       assertUnreachable(dg.operationStatus);
   }
@@ -778,6 +822,10 @@ async function processDepositGroupAborting(
   return waitForRefreshOnDepositGroup(wex, depositGroup);
 }
 
+/**
+ * Process the transaction in states where KYC is required.
+ * Used for both the deposit KYC and aggregate KYC.
+ */
 async function processDepositGroupPendingKyc(
   wex: WalletExecutionContext,
   depositGroup: DepositGroupRecord,
@@ -832,8 +880,6 @@ async function processDepositGroupPendingKyc(
 
   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 wex.db.runReadWriteTx(
@@ -843,20 +889,26 @@ async function processDepositGroupPendingKyc(
         if (!newDg) {
           return;
         }
-        if (newDg.operationStatus !== DepositOperationStatus.PendingKyc) {
-          return;
-        }
         const oldTxState = computeDepositTransactionStatus(newDg);
-        newDg.operationStatus = DepositOperationStatus.PendingTrack;
-        const newTxState = computeDepositTransactionStatus(newDg);
+        switch (newDg.operationStatus) {
+          case DepositOperationStatus.PendingAggregateKyc:
+            newDg.operationStatus = DepositOperationStatus.PendingTrack;
+            break;
+          case DepositOperationStatus.PendingDeposit:
+            newDg.operationStatus = DepositOperationStatus.PendingDeposit;
+            break;
+          default:
+            return;
+        }
         await tx.depositGroups.put(newDg);
         await ctx.updateTransactionMeta(tx);
+        const newTxState = computeDepositTransactionStatus(newDg);
         return { oldTxState, newTxState };
       },
     );
     notifyTransition(wex, transactionId, transitionInfo);
   } else if (kycStatusRes.status === HttpStatusCode.Accepted) {
-    // FIXME: Do we have to update the URL here?
+    logger.info("kyc still pending");
   } else {
     throw Error(`unexpected response from kyc-check (${kycStatusRes.status})`);
   }
@@ -907,7 +959,7 @@ async function getLastWithdrawalKeyPair(
 async function transitionToKycRequired(
   wex: WalletExecutionContext,
   depositGroup: DepositGroupRecord,
-  kycInfo: DepositKycInfo,
+  kycPaytoHash: string,
   exchangeUrl: string,
 ): Promise<TaskRunResult> {
   const { depositGroupId } = depositGroup;
@@ -924,7 +976,7 @@ async function transitionToKycRequired(
     accountPub: lastReserveKeypair.pub,
   });
 
-  const url = new URL(`kyc-check/${kycInfo.paytoHash}`, exchangeUrl);
+  const url = new URL(`kyc-check/${kycPaytoHash}`, exchangeUrl);
   logger.info(`kyc url ${url.href}`);
   const kycStatusResp = await wex.http.fetch(url.href, {
     method: "GET",
@@ -948,14 +1000,20 @@ async function transitionToKycRequired(
         if (!dg) {
           return undefined;
         }
-        if (dg.operationStatus !== DepositOperationStatus.PendingTrack) {
-          return undefined;
-        }
         const oldTxState = computeDepositTransactionStatus(dg);
-        dg.operationStatus = DepositOperationStatus.PendingKyc;
+        switch (dg.operationStatus) {
+          case DepositOperationStatus.PendingTrack:
+            dg.operationStatus = DepositOperationStatus.PendingAggregateKyc;
+            break;
+          case DepositOperationStatus.PendingDeposit:
+            dg.operationStatus = DepositOperationStatus.PendingDepositKyc;
+            break;
+          default:
+            return;
+        }
         dg.kycInfo = {
           exchangeBaseUrl: exchangeUrl,
-          paytoHash: kycInfo.paytoHash,
+          paytoHash: kycPaytoHash,
           accessToken: statusResp.access_token,
         };
         await tx.depositGroups.put(dg);
@@ -1026,15 +1084,10 @@ async function processDepositGroupPendingTrack(
           const paytoHash = encodeCrock(
             hashTruncate32(stringToBytes(depositGroup.wire.payto_uri + "\0")),
           );
-          const kycInfo: DepositKycInfo = {
-            paytoHash,
-            exchangeBaseUrl: exchangeBaseUrl,
-            accessToken: undefined,
-          };
           return transitionToKycRequired(
             wex,
             depositGroup,
-            kycInfo,
+            paytoHash,
             exchangeBaseUrl,
           );
         } else {
@@ -1292,7 +1345,7 @@ async function processDepositGroupPendingDeposit(
   }
 
   // We need to do one batch per exchange.
-  for (const exchangeUrl of exchanges.values()) {
+  for (const exchangeBaseUrl of exchanges.values()) {
     const coins: BatchDepositRequestCoin[] = [];
     const batchIndexes: number[] = [];
 
@@ -1309,7 +1362,7 @@ async function processDepositGroupPendingDeposit(
 
     for (let i = 0; i < depositPermissions.length; i++) {
       const perm = depositPermissions[i];
-      if (perm.exchange_url != exchangeUrl) {
+      if (perm.exchange_url != exchangeBaseUrl) {
         continue;
       }
       coins.push({
@@ -1325,7 +1378,7 @@ async function processDepositGroupPendingDeposit(
 
     // Check for cancellation before making network request.
     cancellationToken?.throwIfCancelled();
-    const url = new URL(`batch-deposit`, exchangeUrl);
+    const url = new URL(`batch-deposit`, exchangeBaseUrl);
     logger.info(`depositing to ${url.href}`);
     logger.trace(`deposit request: ${j2s(batchReq)}`);
     const httpResp = await wex.http.fetch(url.href, {
@@ -1333,6 +1386,28 @@ async function processDepositGroupPendingDeposit(
       body: batchReq,
       cancellationToken: cancellationToken,
     });
+
+    switch (httpResp.status) {
+      case HttpStatusCode.Accepted:
+      case HttpStatusCode.Ok:
+        break;
+      case HttpStatusCode.UnavailableForLegalReasons: {
+        const kycLegiNeededResp = await readResponseJsonOrThrow(
+          httpResp,
+          codecForLegitimizationNeededResponse(),
+        );
+        logger.info(
+          `kyc legitimization needed response: ${j2s(kycLegiNeededResp)}`,
+        );
+        return transitionToKycRequired(
+          wex,
+          depositGroup,
+          kycLegiNeededResp.h_payto,
+          exchangeBaseUrl,
+        );
+      }
+    }
+
     await readSuccessResponseJsonOrThrow(
       httpResp,
       codecForBatchDepositSuccess(),
@@ -1406,7 +1481,8 @@ export async function processDepositGroup(
   switch (depositGroup.operationStatus) {
     case DepositOperationStatus.PendingTrack:
       return processDepositGroupPendingTrack(wex, depositGroup);
-    case DepositOperationStatus.PendingKyc:
+    case DepositOperationStatus.PendingAggregateKyc:
+    case DepositOperationStatus.PendingDepositKyc:
       return processDepositGroupPendingKyc(wex, depositGroup);
     case DepositOperationStatus.PendingDeposit:
       return processDepositGroupPendingDeposit(wex, depositGroup);
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 fd6d40bcf..865e7e6a3 100644
--- a/packages/taler-wallet-core/src/pay-peer-push-credit.ts
+++ b/packages/taler-wallet-core/src/pay-peer-push-credit.ts
@@ -986,9 +986,10 @@ async function handlePendingMerge(
   });
 
   if (mergeHttpResp.status === HttpStatusCode.UnavailableForLegalReasons) {
-    const respJson = await mergeHttpResp.json();
-    const kycLegiNeededResp =
-      codecForLegitimizationNeededResponse().decode(respJson);
+    const kycLegiNeededResp = await readResponseJsonOrThrow(
+      mergeHttpResp,
+      codecForLegitimizationNeededResponse(),
+    );
     logger.info(
       `kyc legitimization needed response: ${j2s(kycLegiNeededResp)}`,
     );

-- 
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]