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: update exchange


From: gnunet
Subject: [taler-wallet-core] branch master updated: wallet-core: update exchange inline, not in task
Date: Mon, 18 Dec 2023 23:04:04 +0100

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 f22f5f89c wallet-core: update exchange inline, not in task
f22f5f89c is described below

commit f22f5f89cc99fb0556b956b6432e4817d52378d2
Author: Florian Dold <florian@dold.me>
AuthorDate: Mon Dec 18 23:00:33 2023 +0100

    wallet-core: update exchange inline, not in task
    
    A task (such as refresh) can't wait until the exchange update task
    updates the exchange, as task handlers don't run concurrently.
    The previous behavior caused some transactions to block indefinitely
    when waiting for an updated exchange entry.
---
 packages/taler-wallet-core/src/host-impl.qtart.ts  |  11 +-
 .../taler-wallet-core/src/internal-wallet-state.ts |   8 +-
 .../taler-wallet-core/src/operations/exchanges.ts  | 224 +++++++++++----------
 .../src/operations/pay-merchant.ts                 |   2 +-
 .../taler-wallet-core/src/operations/refresh.ts    |  17 +-
 .../taler-wallet-core/src/operations/testing.ts    |   2 +-
 .../taler-wallet-core/src/operations/withdraw.ts   |  80 ++++----
 packages/taler-wallet-core/src/wallet.ts           |   6 +-
 8 files changed, 169 insertions(+), 181 deletions(-)

diff --git a/packages/taler-wallet-core/src/host-impl.qtart.ts 
b/packages/taler-wallet-core/src/host-impl.qtart.ts
index 686374beb..0fc346b44 100644
--- a/packages/taler-wallet-core/src/host-impl.qtart.ts
+++ b/packages/taler-wallet-core/src/host-impl.qtart.ts
@@ -30,20 +30,19 @@ import type {
 } from "@gnu-taler/idb-bridge";
 // eslint-disable-next-line no-duplicate-imports
 import {
+  AccessStats,
   BridgeIDBFactory,
   MemoryBackend,
   createSqliteBackend,
   shimIndexedDB,
 } from "@gnu-taler/idb-bridge";
-import { AccessStats } from "@gnu-taler/idb-bridge";
-import { SynchronousCryptoWorkerFactoryPlain } from 
"./crypto/workers/synchronousWorkerFactoryPlain.js";
-import { openTalerDatabase } from "./index.js";
-import { Logger, enableNativeLogging } from "@gnu-taler/taler-util";
+import { Logger } from "@gnu-taler/taler-util";
 import { createPlatformHttpLib } from "@gnu-taler/taler-util/http";
-import { SetTimeoutTimerAPI } from "./util/timer.js";
-import { Wallet } from "./wallet.js";
 import { qjsOs, qjsStd } from "@gnu-taler/taler-util/qtart";
+import { SynchronousCryptoWorkerFactoryPlain } from 
"./crypto/workers/synchronousWorkerFactoryPlain.js";
 import { DefaultNodeWalletArgs, makeTempfileId } from "./host-common.js";
+import { SetTimeoutTimerAPI } from "./util/timer.js";
+import { Wallet } from "./wallet.js";
 
 const logger = new Logger("host-impl.qtart.ts");
 
diff --git a/packages/taler-wallet-core/src/internal-wallet-state.ts 
b/packages/taler-wallet-core/src/internal-wallet-state.ts
index 20f8a7511..b1389a359 100644
--- a/packages/taler-wallet-core/src/internal-wallet-state.ts
+++ b/packages/taler-wallet-core/src/internal-wallet-state.ts
@@ -55,6 +55,7 @@ import {
 import { TimerGroup } from "./util/timer.js";
 import { WalletConfig } from "./wallet-api-types.js";
 import { IDBFactory } from "@gnu-taler/idb-bridge";
+import { ReadyExchangeSummary } from "./index.js";
 
 export const EXCHANGE_COINS_LOCK = "exchange-coins-lock";
 export const EXCHANGE_RESERVES_LOCK = "exchange-reserves-lock";
@@ -107,17 +108,14 @@ export interface ExchangeOperations {
     }>,
     exchangeBaseUrl: string,
   ): Promise<ExchangeDetailsRecord | undefined>;
-  updateExchangeFromUrl(
+  fetchFreshExchange(
     ws: InternalWalletState,
     baseUrl: string,
     options?: {
       forceNow?: boolean;
       cancellationToken?: CancellationToken;
     },
-  ): Promise<{
-    exchange: ExchangeEntryRecord;
-    exchangeDetails: ExchangeDetailsRecord;
-  }>;
+  ): Promise<ReadyExchangeSummary>;
 }
 
 export interface RecoupOperations {
diff --git a/packages/taler-wallet-core/src/operations/exchanges.ts 
b/packages/taler-wallet-core/src/operations/exchanges.ts
index bf7d4424a..fe6060499 100644
--- a/packages/taler-wallet-core/src/operations/exchanges.ts
+++ b/packages/taler-wallet-core/src/operations/exchanges.ts
@@ -37,6 +37,7 @@ import {
   ExchangeGlobalFees,
   ExchangeListItem,
   ExchangeSignKeyJson,
+  ExchangeTosStatus,
   ExchangeWireAccount,
   ExchangesListResponse,
   FeeDescription,
@@ -84,12 +85,15 @@ import {
   ExchangeEntryDbRecordStatus,
   ExchangeEntryDbUpdateStatus,
   OpenedPromise,
+  PendingTaskType,
   WalletDbReadWriteTransaction,
   createTimeline,
   isWithdrawableDenom,
   openPromise,
   selectBestForOverlappingDenominations,
   selectMinimumFee,
+  timestampOptionalAbsoluteFromDb,
+  timestampOptionalPreciseFromDb,
   timestampPreciseFromDb,
   timestampPreciseToDb,
   timestampProtocolToDb,
@@ -102,9 +106,11 @@ import {
   TaskIdentifiers,
   TaskRunResult,
   TaskRunResultType,
+  constructTaskIdentifier,
   getExchangeState,
   getExchangeTosStatusFromRecord,
   makeExchangeListItem,
+  runTaskWithErrorReporting,
 } from "./common.js";
 
 const logger = new Logger("exchanges.ts");
@@ -629,7 +635,7 @@ async function downloadTosFromAcceptedFormat(
  * If the update is forced, the exchange is put into an updating state
  * even if the old information should still be up to date.
  *
- * For backwards compatibility, if the exchange entry doesn't exist,
+ * If the exchange entry doesn't exist,
  * a new ephemeral entry is created.
  */
 export async function startUpdateExchangeEntry(
@@ -740,76 +746,18 @@ export function createNotificationWaiter(
 }
 
 /**
- * Wait until an exchange entry got successfully updated.
- *
- * Reject with an exception if the update encountered an error.
+ * Basic information about an exchange in a ready state.
  */
-export async function waitExchangeEntryUpdated(
-  ws: InternalWalletState,
-  exchangeBaseUrl: string,
-  cancellationToken?: CancellationToken,
-): Promise<{
-  exchange: ExchangeEntryRecord;
-  exchangeDetails: ExchangeDetailsRecord;
-}> {
-  exchangeBaseUrl = canonicalizeBaseUrl(exchangeBaseUrl);
-
-  const waiter = createNotificationWaiter(
-    ws,
-    (notif) =>
-      notif.type == NotificationType.ExchangeStateTransition &&
-      notif.exchangeBaseUrl === exchangeBaseUrl,
-  );
-
-  const taskId = TaskIdentifiers.forExchangeUpdateFromUrl(exchangeBaseUrl);
-
-  while (1) {
-    const { exchange, retryRecord } = await ws.db
-      .mktx((x) => [x.exchanges, x.exchangeDetails, x.operationRetries])
-      .runReadOnly(async (tx) => {
-        const exchange = await tx.exchanges.get(exchangeBaseUrl);
-        const retryRecord = await tx.operationRetries.get(taskId);
-        return { exchange, retryRecord };
-      });
-
-    if (!exchange) {
-      throw Error("exchange does not exist anymore");
-    }
-
-    switch (exchange.updateStatus) {
-      case ExchangeEntryDbUpdateStatus.Ready:
-        const details = await ws.db
-          .mktx((x) => [x.exchanges, x.exchangeDetails])
-          .runReadOnly(async (tx) => {
-            return getExchangeDetails(tx, exchangeBaseUrl);
-          });
-        if (!details) {
-          throw Error("exchange entry inconsistent");
-        }
-        waiter.cancel();
-        return { exchange, exchangeDetails: details };
-      case ExchangeEntryDbUpdateStatus.ReadyUpdate:
-      case ExchangeEntryDbUpdateStatus.InitialUpdate: {
-        waiter.cancel();
-        if (retryRecord?.lastError) {
-          throw TalerError.fromUncheckedDetail(retryRecord.lastError);
-        }
-        break;
-      }
-      case ExchangeEntryDbUpdateStatus.UnavailableUpdate:
-        waiter.cancel();
-        if (retryRecord?.lastError) {
-          throw TalerError.fromUncheckedDetail(retryRecord.lastError);
-        } else {
-          throw Error(
-            "updating exchange failed, error info unavailable (bug!)",
-          );
-        }
-    }
-
-    await waiter.waitNext();
-  }
-  throw Error("not reached");
+export interface ReadyExchangeSummary {
+  exchangeBaseUrl: string;
+  currency: string;
+  masterPub: string;
+  tosStatus: ExchangeTosStatus;
+  tosAcceptedEtag: string | undefined;
+  tosCurrentEtag: string | undefined;
+  wireInfo: WireInfo;
+  protocolVersionRange: string;
+  tosAcceptedTimestamp: TalerPreciseTimestamp | undefined;
 }
 
 /**
@@ -834,21 +782,81 @@ export async function fetchFreshExchange(
     forceUpdate?: boolean;
     expectedMasterPub?: string;
   } = {},
-): Promise<{
-  exchange: ExchangeEntryRecord;
-  exchangeDetails: ExchangeDetailsRecord;
-}> {
+): Promise<ReadyExchangeSummary> {
   const canonUrl = canonicalizeBaseUrl(baseUrl);
-  await startUpdateExchangeEntry(ws, canonUrl, {
-    forceUpdate: options.forceUpdate,
+  const operationId = constructTaskIdentifier({
+    tag: PendingTaskType.ExchangeUpdate,
+    exchangeBaseUrl: canonUrl,
   });
-  const res = await waitExchangeEntryUpdated(
-    ws,
-    canonUrl,
-    options.cancellationToken,
-  );
+
+  const oldExchange = await ws.db
+    .mktx((x) => [x.exchanges])
+    .runReadOnly(async (tx) => {
+      return tx.exchanges.get(canonUrl);
+    });
+
+  let needsUpdate = false;
+
+  if (!oldExchange || options.forceUpdate) {
+    needsUpdate = true;
+    await startUpdateExchangeEntry(ws, canonUrl, {
+      forceUpdate: options.forceUpdate,
+    });
+  } else {
+    const nextUpdate = timestampOptionalAbsoluteFromDb(
+      oldExchange.nextUpdateStamp,
+    );
+    if (nextUpdate == null || AbsoluteTime.isExpired(nextUpdate)) {
+      needsUpdate = true;
+    }
+  }
+
+  if (needsUpdate) {
+    await runTaskWithErrorReporting(ws, operationId, () =>
+      updateExchangeFromUrlHandler(ws, canonUrl),
+    );
+  }
+
+  const { exchange, exchangeDetails } = await ws.db
+    .mktx((x) => [x.exchanges, x.exchangeDetails])
+    .runReadOnly(async (tx) => {
+      const exchange = await tx.exchanges.get(canonUrl);
+      const exchangeDetails = await getExchangeDetails(tx, canonUrl);
+      return { exchange, exchangeDetails };
+    });
+
+  if (!exchange) {
+    throw Error("exchange entry does not exist anymore");
+  }
+
+  switch (exchange.updateStatus) {
+    case ExchangeEntryDbUpdateStatus.Ready:
+    case ExchangeEntryDbUpdateStatus.ReadyUpdate:
+      break;
+    default:
+      throw Error("unable to update exchange");
+  }
+
+  if (!exchangeDetails) {
+    throw Error("invariant failed");
+  }
+
+  const res: ReadyExchangeSummary = {
+    currency: exchangeDetails.currency,
+    exchangeBaseUrl: canonUrl,
+    masterPub: exchangeDetails.masterPublicKey,
+    tosStatus: getExchangeTosStatusFromRecord(exchange),
+    tosAcceptedEtag: exchange.tosAcceptedEtag,
+    wireInfo: exchangeDetails.wireInfo,
+    protocolVersionRange: exchangeDetails.protocolVersionRange,
+    tosCurrentEtag: exchange.tosCurrentEtag,
+    tosAcceptedTimestamp: timestampOptionalPreciseFromDb(
+      exchange.tosAcceptedTimestamp,
+    ),
+  };
+
   if (options.expectedMasterPub) {
-    if (res.exchangeDetails.masterPublicKey !== options.expectedMasterPub) {
+    if (res.masterPub !== options.expectedMasterPub) {
       throw Error(
         "public key of the exchange does not match expected public key",
       );
@@ -1187,10 +1195,7 @@ export async function getExchangeTos(
   acceptLanguage?: string,
 ): Promise<GetExchangeTosResult> {
   // FIXME: download ToS in acceptable format if passed!
-  const { exchange, exchangeDetails } = await fetchFreshExchange(
-    ws,
-    exchangeBaseUrl,
-  );
+  const exch = await fetchFreshExchange(ws, exchangeBaseUrl);
 
   const tosDownload = await downloadTosFromAcceptedFormat(
     ws,
@@ -1211,12 +1216,12 @@ export async function getExchangeTos(
     });
 
   return {
-    acceptedEtag: exchange.tosAcceptedEtag,
+    acceptedEtag: exch.tosAcceptedEtag,
     currentEtag: tosDownload.tosEtag,
     content: tosDownload.tosText,
     contentType: tosDownload.tosContentType,
     contentLanguage: tosDownload.tosContentLanguage,
-    tosStatus: getExchangeTosStatusFromRecord(exchange),
+    tosStatus: exch.tosStatus,
     tosAvailableLanguages: tosDownload.tosAvailableLanguages,
   };
 }
@@ -1364,26 +1369,29 @@ export async function getExchangeDetailedInfo(
 
   const transferFees = Object.entries(
     exchange.info.wireInfo.feesForType,
-  ).reduce((prev, [wireType, infoForType]) => {
-    const feesByGroup = [
-      ...infoForType.map((w) => ({
-        ...w,
-        fee: Amounts.stringify(w.closingFee),
-        group: "closing",
-      })),
-      ...infoForType.map((w) => ({ ...w, fee: w.wireFee, group: "wire" })),
-    ];
-    prev[wireType] = createTimeline(
-      feesByGroup,
-      "sig",
-      "startStamp",
-      "endStamp",
-      "fee",
-      "group",
-      selectMinimumFee,
-    );
-    return prev;
-  }, {} as Record<string, FeeDescription[]>);
+  ).reduce(
+    (prev, [wireType, infoForType]) => {
+      const feesByGroup = [
+        ...infoForType.map((w) => ({
+          ...w,
+          fee: Amounts.stringify(w.closingFee),
+          group: "closing",
+        })),
+        ...infoForType.map((w) => ({ ...w, fee: w.wireFee, group: "wire" })),
+      ];
+      prev[wireType] = createTimeline(
+        feesByGroup,
+        "sig",
+        "startStamp",
+        "endStamp",
+        "fee",
+        "group",
+        selectMinimumFee,
+      );
+      return prev;
+    },
+    {} as Record<string, FeeDescription[]>,
+  );
 
   const globalFeesByGroup = [
     ...exchange.info.globalFees.map((w) => ({
diff --git a/packages/taler-wallet-core/src/operations/pay-merchant.ts 
b/packages/taler-wallet-core/src/operations/pay-merchant.ts
index 17a879d90..078f0faf9 100644
--- a/packages/taler-wallet-core/src/operations/pay-merchant.ts
+++ b/packages/taler-wallet-core/src/operations/pay-merchant.ts
@@ -1278,7 +1278,7 @@ export async function generateDepositPermissions(
  * Run the operation handler for a payment
  * and return the result as a {@link ConfirmPayResult}.
  */
-export async function runPayForConfirmPay(
+async function runPayForConfirmPay(
   ws: InternalWalletState,
   proposalId: string,
 ): Promise<ConfirmPayResult> {
diff --git a/packages/taler-wallet-core/src/operations/refresh.ts 
b/packages/taler-wallet-core/src/operations/refresh.ts
index 3bbbc2a4b..5ea8fae23 100644
--- a/packages/taler-wallet-core/src/operations/refresh.ts
+++ b/packages/taler-wallet-core/src/operations/refresh.ts
@@ -99,11 +99,7 @@ import {
   TaskRunResult,
   TaskRunResultType,
 } from "./common.js";
-import {
-  fetchFreshExchange,
-  startUpdateExchangeEntry,
-  waitExchangeEntryUpdated,
-} from "./exchanges.js";
+import { fetchFreshExchange } from "./exchanges.js";
 import {
   constructTransactionIdentifier,
   notifyTransition,
@@ -226,10 +222,7 @@ async function provideRefreshSession(
 
   const { refreshGroup, coin } = d;
 
-  const { exchange } = await fetchFreshExchange(ws, coin.exchangeBaseUrl);
-  if (!exchange) {
-    throw Error("db inconsistent: exchange of coin not found");
-  }
+  const exch = await fetchFreshExchange(ws, coin.exchangeBaseUrl);
 
   // FIXME: use helper functions from withdraw.ts
   // to update and filter withdrawable denoms.
@@ -240,7 +233,7 @@ async function provideRefreshSession(
       const oldDenom = await ws.getDenomInfo(
         ws,
         tx,
-        exchange.baseUrl,
+        exch.exchangeBaseUrl,
         coin.denomPubHash,
       );
 
@@ -251,7 +244,7 @@ async function provideRefreshSession(
       // FIXME: use an index here, based on the withdrawal expiration time.
       const availableDenoms: DenominationRecord[] =
         await tx.denominations.indexes.byExchangeBaseUrl
-          .iter(exchange.baseUrl)
+          .iter(exch.exchangeBaseUrl)
           .toArray();
 
       const availableAmount = Amounts.sub(
@@ -872,7 +865,7 @@ export async function processRefreshGroup(
     return TaskRunResult.finished();
   }
   // Process refresh sessions of the group in parallel.
-  logger.trace("processing refresh sessions for old coins");
+  logger.trace("processing refresh sessions for $ old coins");
   let errors: TalerErrorDetail[] = [];
   let inShutdown = false;
   const ps = refreshGroup.oldCoinPubs.map((x, i) =>
diff --git a/packages/taler-wallet-core/src/operations/testing.ts 
b/packages/taler-wallet-core/src/operations/testing.ts
index a03d54d3a..d75fb54a7 100644
--- a/packages/taler-wallet-core/src/operations/testing.ts
+++ b/packages/taler-wallet-core/src/operations/testing.ts
@@ -581,7 +581,7 @@ export async function runIntegrationTest2(
 
   const exchangeInfo = await fetchFreshExchange(ws, args.exchangeBaseUrl);
 
-  const currency = exchangeInfo.exchangeDetails.currency;
+  const currency = exchangeInfo.currency;
 
   const amountToWithdraw = Amounts.parseOrThrow(`${currency}:10`);
   const amountToSpend = Amounts.parseOrThrow(`${currency}:2`);
diff --git a/packages/taler-wallet-core/src/operations/withdraw.ts 
b/packages/taler-wallet-core/src/operations/withdraw.ts
index 8a718dd49..3dffab7d6 100644
--- a/packages/taler-wallet-core/src/operations/withdraw.ts
+++ b/packages/taler-wallet-core/src/operations/withdraw.ts
@@ -136,6 +136,7 @@ import {
   getExchangeDetails,
   getExchangePaytoUri,
   fetchFreshExchange,
+  ReadyExchangeSummary,
 } from "./exchanges.js";
 import {
   TransitionInfo,
@@ -616,9 +617,10 @@ export async function getCandidateWithdrawalDenoms(
   return await ws.db
     .mktx((x) => [x.denominations])
     .runReadOnly(async (tx) => {
-      const allDenoms = await 
tx.denominations.indexes.byExchangeBaseUrl.getAll(
-        exchangeBaseUrl,
-      );
+      const allDenoms =
+        await tx.denominations.indexes.byExchangeBaseUrl.getAll(
+          exchangeBaseUrl,
+        );
       return allDenoms.filter((d) =>
         isWithdrawableDenom(d, ws.config.testing.denomselAllowLate),
       );
@@ -870,10 +872,10 @@ async function handleKycRequired(
             amlStatus === AmlStatus.normal || amlStatus === undefined
               ? WithdrawalGroupStatus.PendingKyc
               : amlStatus === AmlStatus.pending
-              ? WithdrawalGroupStatus.PendingAml
-              : amlStatus === AmlStatus.fronzen
-              ? WithdrawalGroupStatus.SuspendedAml
-              : assertUnreachable(amlStatus);
+                ? WithdrawalGroupStatus.PendingAml
+                : amlStatus === AmlStatus.fronzen
+                  ? WithdrawalGroupStatus.SuspendedAml
+                  : assertUnreachable(amlStatus);
 
           notificationKycUrl = kycUrl;
 
@@ -1508,10 +1510,7 @@ async function processWithdrawalGroupPendingReady(
     withdrawalGroupId,
   });
 
-  await ws.exchangeOps.updateExchangeFromUrl(
-    ws,
-    withdrawalGroup.exchangeBaseUrl,
-  );
+  await ws.exchangeOps.fetchFreshExchange(ws, withdrawalGroup.exchangeBaseUrl);
 
   if (withdrawalGroup.denomsSel.selectedDenoms.length === 0) {
     logger.warn("Finishing empty withdrawal group (no denoms)");
@@ -1549,9 +1548,8 @@ async function processWithdrawalGroupPendingReady(
   await ws.db
     .mktx((x) => [x.planchets])
     .runReadOnly(async (tx) => {
-      const planchets = await tx.planchets.indexes.byGroup.getAll(
-        withdrawalGroupId,
-      );
+      const planchets =
+        await tx.planchets.indexes.byGroup.getAll(withdrawalGroupId);
       for (const p of planchets) {
         if (p.planchetStatus === PlanchetStatus.WithdrawalDone) {
           wgContext.planchetsFinished.add(p.coinPub);
@@ -1759,19 +1757,18 @@ export async function getExchangeWithdrawalInfo(
   ageRestricted: number | undefined,
 ): Promise<ExchangeWithdrawalDetails> {
   logger.trace("updating exchange");
-  const { exchange, exchangeDetails } =
-    await ws.exchangeOps.updateExchangeFromUrl(ws, exchangeBaseUrl);
+  const exchange = await ws.exchangeOps.fetchFreshExchange(ws, 
exchangeBaseUrl);
 
-  if (exchangeDetails.currency != instructedAmount.currency) {
+  if (exchange.currency != instructedAmount.currency) {
     // Specifiying the amount in the conversion input currency is not yet 
supported.
     // We might add support for it later.
     throw new Error(
-      `withdrawal only supported when specifying target currency 
${exchangeDetails.currency}`,
+      `withdrawal only supported when specifying target currency 
${exchange.currency}`,
     );
   }
 
   const withdrawalAccountsList = await fetchWithdrawalAccountInfo(ws, {
-    exchangeDetails,
+    exchange,
     instructedAmount,
   });
 
@@ -1799,7 +1796,7 @@ export async function getExchangeWithdrawalInfo(
 
   const exchangeWireAccounts: string[] = [];
 
-  for (const account of exchangeDetails.wireInfo.accounts) {
+  for (const account of exchange.wireInfo.accounts) {
     exchangeWireAccounts.push(account.payto_uri);
   }
 
@@ -1839,17 +1836,18 @@ export async function getExchangeWithdrawalInfo(
   const possibleDenoms = await ws.db
     .mktx((x) => [x.denominations])
     .runReadOnly(async (tx) => {
-      const ds = await tx.denominations.indexes.byExchangeBaseUrl.getAll(
-        exchangeBaseUrl,
-      );
+      const ds =
+        await tx.denominations.indexes.byExchangeBaseUrl.getAll(
+          exchangeBaseUrl,
+        );
       return ds.filter((x) => x.isOffered);
     });
 
   let versionMatch;
-  if (exchangeDetails.protocolVersionRange) {
+  if (exchange.protocolVersionRange) {
     versionMatch = LibtoolVersion.compare(
       WALLET_EXCHANGE_PROTOCOL_VERSION,
-      exchangeDetails.protocolVersionRange,
+      exchange.protocolVersionRange,
     );
 
     if (
@@ -1859,7 +1857,7 @@ export async function getExchangeWithdrawalInfo(
     ) {
       logger.warn(
         `wallet's support for exchange protocol version 
${WALLET_EXCHANGE_PROTOCOL_VERSION} might be outdated ` +
-          `(exchange has ${exchangeDetails.protocolVersionRange}), checking 
for updates`,
+          `(exchange has ${exchange.protocolVersionRange}), checking for 
updates`,
       );
     }
   }
@@ -1871,7 +1869,7 @@ export async function getExchangeWithdrawalInfo(
     }
   }
 
-  const paytoUris = exchangeDetails.wireInfo.accounts.map((x) => x.payto_uri);
+  const paytoUris = exchange.wireInfo.accounts.map((x) => x.payto_uri);
   if (!paytoUris) {
     throw Error("exchange is in invalid state");
   }
@@ -1881,7 +1879,7 @@ export async function getExchangeWithdrawalInfo(
     exchangePaytoUris: paytoUris,
     exchangeWireAccounts,
     exchangeCreditAccountDetails: withdrawalAccountsList,
-    exchangeVersion: exchangeDetails.protocolVersionRange || "unknown",
+    exchangeVersion: exchange.protocolVersionRange || "unknown",
     numOfferedDenoms: possibleDenoms.length,
     selectedDenoms,
     // FIXME: delete this field / replace by something we can display to the 
user
@@ -1923,7 +1921,7 @@ export async function getWithdrawalDetailsForUri(
     // FIXME: right now the exchange gets permanently added,
     // we might want to only temporarily add it.
     try {
-      await ws.exchangeOps.updateExchangeFromUrl(ws, info.suggestedExchange);
+      await ws.exchangeOps.fetchFreshExchange(ws, info.suggestedExchange);
     } catch (e) {
       // We still continued if it failed, as other exchanges might be 
available.
       // We don't want to fail if the bank-suggested exchange is 
broken/offline.
@@ -2289,7 +2287,6 @@ export interface PrepareCreateWithdrawalGroupResult {
   creationInfo?: {
     amount: AmountJson;
     canonExchange: string;
-    exchangeDetails: ExchangeDetailsRecord;
   };
 }
 
@@ -2376,7 +2373,6 @@ export async function 
internalPrepareCreateWithdrawalGroup(
   };
 
   const exchangeInfo = await fetchFreshExchange(ws, canonExchange);
-  const exchangeDetails = exchangeInfo.exchangeDetails;
   const transactionId = constructTransactionIdentifier({
     tag: TransactionType.Withdrawal,
     withdrawalGroupId: withdrawalGroup.withdrawalGroupId,
@@ -2388,7 +2384,6 @@ export async function 
internalPrepareCreateWithdrawalGroup(
     creationInfo: {
       canonExchange,
       amount,
-      exchangeDetails,
     },
   };
 }
@@ -2411,8 +2406,6 @@ export async function 
internalPerformCreateWithdrawalGroup(
   if (!prep.creationInfo) {
     return { withdrawalGroup, transitionInfo: undefined };
   }
-  const { amount, canonExchange, exchangeDetails } = prep.creationInfo;
-
   await tx.withdrawalGroups.add(withdrawalGroup);
   await tx.reserves.put({
     reservePub: withdrawalGroup.reservePub,
@@ -2529,13 +2522,13 @@ export async function acceptWithdrawalFromUri(
     withdrawInfo.wireTypes,
   );
 
-  const { exchangeDetails } = await ws.exchangeOps.updateExchangeFromUrl(
+  const exchange = await ws.exchangeOps.fetchFreshExchange(
     ws,
     selectedExchange,
   );
 
   const withdrawalAccountList = await fetchWithdrawalAccountInfo(ws, {
-    exchangeDetails,
+    exchange,
     instructedAmount: withdrawInfo.amount,
   });
 
@@ -2666,14 +2659,14 @@ async function fetchAccount(
 async function fetchWithdrawalAccountInfo(
   ws: InternalWalletState,
   req: {
-    exchangeDetails: ExchangeDetailsRecord;
+    exchange: ReadyExchangeSummary;
     instructedAmount: AmountJson;
     reservePub?: string;
   },
 ): Promise<WithdrawalExchangeAccountDetails[]> {
-  const { exchangeDetails, instructedAmount } = req;
+  const { exchange, instructedAmount } = req;
   const withdrawalAccounts: WithdrawalExchangeAccountDetails[] = [];
-  for (let acct of exchangeDetails.wireInfo.accounts) {
+  for (let acct of exchange.wireInfo.accounts) {
     const acctInfo = await fetchAccount(
       ws,
       req.instructedAmount,
@@ -2704,12 +2697,9 @@ export async function createManualWithdrawal(
 ): Promise<AcceptManualWithdrawalResult> {
   const { exchangeBaseUrl } = req;
   const amount = Amounts.parseOrThrow(req.amount);
-  const { exchangeDetails } = await ws.exchangeOps.updateExchangeFromUrl(
-    ws,
-    exchangeBaseUrl,
-  );
+  const exchange = await ws.exchangeOps.fetchFreshExchange(ws, 
exchangeBaseUrl);
 
-  if (exchangeDetails.currency != amount.currency) {
+  if (exchange.currency != amount.currency) {
     throw Error(
       "manual withdrawal with conversion from foreign currency is not yet 
supported",
     );
@@ -2719,7 +2709,7 @@ export async function createManualWithdrawal(
   );
 
   const withdrawalAccountsList = await fetchWithdrawalAccountInfo(ws, {
-    exchangeDetails,
+    exchange,
     instructedAmount: amount,
     reservePub: reserveKeyPair.pub,
   });
diff --git a/packages/taler-wallet-core/src/wallet.ts 
b/packages/taler-wallet-core/src/wallet.ts
index da6ffa41f..2d422e59c 100644
--- a/packages/taler-wallet-core/src/wallet.ts
+++ b/packages/taler-wallet-core/src/wallet.ts
@@ -844,12 +844,12 @@ async function handlePrepareWithdrawExchange(
   }
   const exchangeBaseUrl = parsedUri.exchangeBaseUrl;
   const exchange = await fetchFreshExchange(ws, exchangeBaseUrl);
-  if (exchange.exchangeDetails.masterPublicKey != parsedUri.exchangePub) {
+  if (exchange.masterPub != parsedUri.exchangePub) {
     throw Error("mismatch of exchange master public key (URI vs actual)");
   }
   if (parsedUri.amount) {
     const amt = Amounts.parseOrThrow(parsedUri.amount);
-    if (amt.currency !== exchange.exchangeDetails.currency) {
+    if (amt.currency !== exchange.currency) {
       throw Error("mismatch of currency (URI vs exchange)");
     }
   }
@@ -1689,7 +1689,7 @@ class InternalWalletStateImpl implements 
InternalWalletState {
 
   exchangeOps: ExchangeOperations = {
     getExchangeDetails,
-    updateExchangeFromUrl: fetchFreshExchange,
+    fetchFreshExchange,
   };
 
   recoupOps: RecoupOperations = {

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