gnunet-svn
[Top][All Lists]
Advanced

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

[taler-wallet-core] 02/02: wallet-core: request handler refactoring WIP


From: gnunet
Subject: [taler-wallet-core] 02/02: wallet-core: request handler refactoring WIP
Date: Sat, 29 Jun 2024 14:16:55 +0200

This is an automated email from the git hooks/post-receive script.

dold pushed a commit to branch master
in repository wallet-core.

commit 98d7a238a615e7dc801bbfdf85188197b91f6083
Author: Florian Dold <florian@dold.me>
AuthorDate: Sat Jun 29 14:16:34 2024 +0200

    wallet-core: request handler refactoring WIP
---
 packages/taler-util/src/wallet-types.ts            |   6 +
 packages/taler-wallet-cli/src/index.ts             |   9 +-
 packages/taler-wallet-core/src/wallet-api-types.ts |  16 +-
 packages/taler-wallet-core/src/wallet.ts           | 632 +++++++++++++--------
 4 files changed, 396 insertions(+), 267 deletions(-)

diff --git a/packages/taler-util/src/wallet-types.ts 
b/packages/taler-util/src/wallet-types.ts
index 42c0148e7..ec401f3f6 100644
--- a/packages/taler-util/src/wallet-types.ts
+++ b/packages/taler-util/src/wallet-types.ts
@@ -3457,3 +3457,9 @@ export const codecForGetQrCodesForPaytoRequest = () =>
 export interface GetQrCodesForPaytoResponse {
   codes: QrCodeSpec[];
 }
+
+export type EmptyObject = Record<string, never>;
+
+export const codecForEmptyObject = (): Codec<EmptyObject> =>
+  buildCodecForObject<EmptyObject>()
+    .build("EmptyObject");
\ No newline at end of file
diff --git a/packages/taler-wallet-cli/src/index.ts 
b/packages/taler-wallet-cli/src/index.ts
index c165b548c..be74e464b 100644
--- a/packages/taler-wallet-cli/src/index.ts
+++ b/packages/taler-wallet-cli/src/index.ts
@@ -1380,13 +1380,8 @@ advancedCli
 advancedCli
   .subcommand("pending", "pending", { help: "Show pending operations." })
   .action(async (args) => {
-    await withWallet(args, { lazyTaskLoop: true }, async (wallet) => {
-      const pending = await wallet.client.call(
-        WalletApiOperation.GetPendingOperations,
-        {},
-      );
-      console.log(JSON.stringify(pending, undefined, 2));
-    });
+    console.error("Subcommand removed due to deprecation.");
+    process.exit(1);
   });
 
 advancedCli
diff --git a/packages/taler-wallet-core/src/wallet-api-types.ts 
b/packages/taler-wallet-core/src/wallet-api-types.ts
index c47bbce0b..cd17bc8cd 100644
--- a/packages/taler-wallet-core/src/wallet-api-types.ts
+++ b/packages/taler-wallet-core/src/wallet-api-types.ts
@@ -59,6 +59,7 @@ import {
   DeleteExchangeRequest,
   DeleteStoredBackupRequest,
   DeleteTransactionRequest,
+  EmptyObject,
   ExchangeDetailedResponse,
   ExchangesListResponse,
   ExchangesShortListResponse,
@@ -202,7 +203,6 @@ export enum WalletApiOperation {
   GetUserAttentionRequests = "getUserAttentionRequests",
   GetUserAttentionUnreadCount = "getUserAttentionUnreadCount",
   MarkAttentionRequestAsRead = "markAttentionRequestAsRead",
-  GetPendingOperations = "getPendingOperations",
   GetActiveTasks = "getActiveTasks",
   SetExchangeTosAccepted = "setExchangeTosAccepted",
   SetExchangeTosForgotten = "setExchangeTosForgotten",
@@ -287,8 +287,6 @@ export enum WalletApiOperation {
 
 // group: Initialization
 
-export type EmptyObject = Record<string, never>;
-
 /**
  * Initialize wallet-core.
  *
@@ -1142,17 +1140,6 @@ export type GetUserAttentionsUnreadCount = {
   response: UserAttentionsCountResponse;
 };
 
-/**
- * Get wallet-internal pending tasks.
- *
- * @deprecated
- */
-export type GetPendingTasksOp = {
-  op: WalletApiOperation.GetPendingOperations;
-  request: EmptyObject;
-  response: any;
-};
-
 export type GetActiveTasksOp = {
   op: WalletApiOperation.GetActiveTasks;
   request: EmptyObject;
@@ -1301,7 +1288,6 @@ export type WalletOperations = {
   [WalletApiOperation.GetTransactionById]: GetTransactionByIdOp;
   [WalletApiOperation.GetWithdrawalTransactionByUri]: 
GetWithdrawalTransactionByUriOp;
   [WalletApiOperation.RetryPendingNow]: RetryPendingNowOp;
-  [WalletApiOperation.GetPendingOperations]: GetPendingTasksOp;
   [WalletApiOperation.GetActiveTasks]: GetActiveTasksOp;
   [WalletApiOperation.GetUserAttentionRequests]: GetUserAttentionRequests;
   [WalletApiOperation.GetUserAttentionUnreadCount]: 
GetUserAttentionsUnreadCount;
diff --git a/packages/taler-wallet-core/src/wallet.ts 
b/packages/taler-wallet-core/src/wallet.ts
index c2ec17f48..536f559d4 100644
--- a/packages/taler-wallet-core/src/wallet.ts
+++ b/packages/taler-wallet-core/src/wallet.ts
@@ -24,29 +24,48 @@
  */
 import { IDBDatabase, IDBFactory } from "@gnu-taler/idb-bridge";
 import {
+  AbortTransactionRequest,
   AbsoluteTime,
+  AcceptManualWithdrawalRequest,
+  AcceptManualWithdrawalResult,
   ActiveTask,
   AddExchangeRequest,
+  AddKnownBankAccountsRequest,
   AmountJson,
   AmountString,
   Amounts,
   CancellationToken,
   CoinDumpJson,
   CoinStatus,
+  ConfirmPayRequest,
+  ConfirmPayResult,
   CoreApiResponse,
   CreateStoredBackupResponse,
   DeleteStoredBackupRequest,
   DenominationInfo,
   Duration,
+  EmptyObject,
   ExchangesShortListResponse,
+  FailTransactionRequest,
+  ForgetKnownBankAccountsRequest,
+  GetActiveTasksResponse,
+  GetContractTermsDetailsRequest,
   GetCurrencySpecificationRequest,
   GetCurrencySpecificationResponse,
+  GetDepositWireTypesForCurrencyRequest,
+  GetDepositWireTypesForCurrencyResponse,
+  GetExchangeTosRequest,
+  GetExchangeTosResult,
+  GetQrCodesForPaytoRequest,
+  GetQrCodesForPaytoResponse,
+  HintNetworkAvailabilityRequest,
   InitRequest,
   InitResponse,
   IntegrationTestArgs,
   IntegrationTestV2Args,
   KnownBankAccounts,
   KnownBankAccountsInfo,
+  ListExchangesForScopedCurrencyRequest,
   ListGlobalCurrencyAuditorsResponse,
   ListGlobalCurrencyExchangesResponse,
   Logger,
@@ -61,22 +80,28 @@ import {
   RecoverStoredBackupRequest,
   SharePaymentRequest,
   SharePaymentResult,
+  StartRefundQueryRequest,
   StoredBackupList,
+  SuspendTransactionRequest,
   TalerBankIntegrationHttpClient,
   TalerError,
   TalerErrorCode,
   TalerProtocolTimestamp,
   TalerUriAction,
+  TestingGetDenomStatsRequest,
   TestingGetDenomStatsResponse,
+  TestingGetReserveHistoryRequest,
   TestingListTasksForTransactionRequest,
   TestingListTasksForTransactionsResponse,
   TestingWaitTransactionRequest,
   TimerAPI,
   TimerGroup,
   TransactionType,
+  TransactionsResponse,
   UpdateExchangeEntryRequest,
   ValidateIbanRequest,
   ValidateIbanResponse,
+  WalletContractData,
   WalletCoreVersion,
   WalletNotification,
   WalletRunConfig,
@@ -106,6 +131,7 @@ import {
   codecForDeleteExchangeRequest,
   codecForDeleteStoredBackupRequest,
   codecForDeleteTransactionRequest,
+  codecForEmptyObject,
   codecForFailTransactionRequest,
   codecForForceRefreshRequest,
   codecForForgetKnownBankAccounts,
@@ -167,7 +193,6 @@ import {
   parseTalerUri,
   performanceNow,
   safeStringifyException,
-  sampleWalletCoreTransactions,
   setDangerousTimetravel,
   validateIban,
 } from "@gnu-taler/taler-util";
@@ -181,6 +206,7 @@ import {
   markAttentionRequestAsRead,
 } from "./attention.js";
 import {
+  RunBackupCycleRequest,
   addBackupProvider,
   codecForAddBackupProviderRequest,
   codecForRemoveBackupProvider,
@@ -318,7 +344,6 @@ import {
   WALLET_MERCHANT_PROTOCOL_VERSION,
 } from "./versions.js";
 import {
-  EmptyObject,
   WalletApiOperation,
   WalletCoreApiClient,
   WalletCoreResponseType,
@@ -693,18 +718,6 @@ async function handlePrepareWithdrawExchange(
   };
 }
 
-/**
- * Response returned from the pending operations API.
- *
- * @deprecated this is a placeholder for the response type of a deprecated 
wallet-core request.
- */
-export interface PendingOperationsResponse {
-  /**
-   * List of pending operations.
-   */
-  pendingOperations: any[];
-}
-
 async function handleRetryPendingNow(
   wex: WalletExecutionContext,
 ): Promise<EmptyObject> {
@@ -857,6 +870,343 @@ async function handleUpdateExchangeEntry(
   return {};
 }
 
+async function handleTestingGetDenomStats(
+  wex: WalletExecutionContext,
+  req: TestingGetDenomStatsRequest,
+): Promise<TestingGetDenomStatsResponse> {
+  const denomStats: TestingGetDenomStatsResponse = {
+    numKnown: 0,
+    numLost: 0,
+    numOffered: 0,
+  };
+  await wex.db.runReadOnlyTx({ storeNames: ["denominations"] }, async (tx) => {
+    const denoms = await tx.denominations.indexes.byExchangeBaseUrl.getAll(
+      req.exchangeBaseUrl,
+    );
+    for (const d of denoms) {
+      denomStats.numKnown++;
+      if (d.isOffered) {
+        denomStats.numOffered++;
+      }
+      if (d.isLost) {
+        denomStats.numLost++;
+      }
+    }
+  });
+  return denomStats;
+}
+
+async function handleListExchangesForScopedCurrency(
+  wex: WalletExecutionContext,
+  req: ListExchangesForScopedCurrencyRequest,
+): Promise<ExchangesShortListResponse> {
+  const exchangesResp = await listExchanges(wex);
+  const result: ExchangesShortListResponse = {
+    exchanges: [],
+  };
+  // Right now we only filter on the currency, as wallet-core doesn't
+  // fully support scoped currencies yet.
+  for (const exch of exchangesResp.exchanges) {
+    if (exch.currency === req.scope.currency) {
+      result.exchanges.push({
+        exchangeBaseUrl: exch.exchangeBaseUrl,
+      });
+    }
+  }
+  return result;
+}
+
+async function handleAddKnownBankAccount(
+  wex: WalletExecutionContext,
+  req: AddKnownBankAccountsRequest,
+): Promise<EmptyObject> {
+  await addKnownBankAccounts(wex, req.payto, req.alias, req.currency);
+  return {};
+}
+
+async function handleForgetKnownBankAccounts(
+  wex: WalletExecutionContext,
+  req: ForgetKnownBankAccountsRequest,
+): Promise<EmptyObject> {
+  await forgetKnownBankAccounts(wex, req.payto);
+  return {};
+}
+
+// FIXME: Doesn't have proper type!
+async function handleTestingGetReserveHistory(
+  wex: WalletExecutionContext,
+  req: TestingGetReserveHistoryRequest,
+): Promise<any> {
+  const reserve = await wex.db.runReadOnlyTx(
+    { storeNames: ["reserves"] },
+    async (tx) => {
+      return tx.reserves.indexes.byReservePub.get(req.reservePub);
+    },
+  );
+  if (!reserve) {
+    throw Error("no reserve pub found");
+  }
+  const sigResp = await wex.cryptoApi.signReserveHistoryReq({
+    reservePriv: reserve.reservePriv,
+    startOffset: 0,
+  });
+  const exchangeBaseUrl = req.exchangeBaseUrl;
+  const url = new URL(`reserves/${req.reservePub}/history`, exchangeBaseUrl);
+  const resp = await wex.http.fetch(url.href, {
+    headers: { ["Taler-Reserve-History-Signature"]: sigResp.sig },
+  });
+  const historyJson = await readSuccessResponseJsonOrThrow(resp, 
codecForAny());
+  return historyJson;
+}
+
+async function handleAcceptManualWithdrawal(
+  wex: WalletExecutionContext,
+  req: AcceptManualWithdrawalRequest,
+): Promise<AcceptManualWithdrawalResult> {
+  const res = await createManualWithdrawal(wex, {
+    amount: Amounts.parseOrThrow(req.amount),
+    exchangeBaseUrl: req.exchangeBaseUrl,
+    restrictAge: req.restrictAge,
+    forceReservePriv: req.forceReservePriv,
+  });
+  return res;
+}
+
+async function handleGetExchangeTos(
+  wex: WalletExecutionContext,
+  req: GetExchangeTosRequest,
+): Promise<GetExchangeTosResult> {
+  return getExchangeTos(
+    wex,
+    req.exchangeBaseUrl,
+    req.acceptedFormat,
+    req.acceptLanguage,
+  );
+}
+
+async function handleGetContractTermsDetails(
+  wex: WalletExecutionContext,
+  req: GetContractTermsDetailsRequest,
+): Promise<WalletContractData> {
+  if (req.proposalId) {
+    // FIXME: deprecated path
+    return getContractTermsDetails(wex, req.proposalId);
+  }
+  if (req.transactionId) {
+    const parsedTx = parseTransactionIdentifier(req.transactionId);
+    if (parsedTx?.tag === TransactionType.Payment) {
+      return getContractTermsDetails(wex, parsedTx.proposalId);
+    }
+    throw Error("transactionId is not a payment transaction");
+  }
+  throw Error("transactionId missing");
+}
+
+async function handleGetQrCodesForPayto(
+  wex: WalletExecutionContext,
+  req: GetQrCodesForPaytoRequest,
+): Promise<GetQrCodesForPaytoResponse> {
+  return {
+    codes: getQrCodesForPayto(req.paytoUri),
+  };
+}
+
+async function handleConfirmPay(
+  wex: WalletExecutionContext,
+  req: ConfirmPayRequest,
+): Promise<ConfirmPayResult> {
+  let transactionId;
+  if (req.proposalId) {
+    // legacy client support
+    transactionId = constructTransactionIdentifier({
+      tag: TransactionType.Payment,
+      proposalId: req.proposalId,
+    });
+  } else if (req.transactionId) {
+    transactionId = req.transactionId;
+  } else {
+    throw Error("transactionId or (deprecated) proposalId required");
+  }
+  return await confirmPay(wex, transactionId, req.sessionId);
+}
+
+async function handleAbortTransaction(
+  wex: WalletExecutionContext,
+  req: AbortTransactionRequest,
+): Promise<EmptyObject> {
+  await abortTransaction(wex, req.transactionId);
+  return {};
+}
+
+async function handleSuspendTransaction(
+  wex: WalletExecutionContext,
+  req: SuspendTransactionRequest,
+): Promise<EmptyObject> {
+  await suspendTransaction(wex, req.transactionId);
+  return {};
+}
+
+async function handleGetActiveTasks(
+  wex: WalletExecutionContext,
+  req: EmptyObject,
+): Promise<GetActiveTasksResponse> {
+  const allTasksId = (await getActiveTaskIds(wex.ws)).taskIds;
+
+  const tasksInfo = await Promise.all(
+    allTasksId.map(async (id) => {
+      return await wex.db.runReadOnlyTx(
+        { storeNames: ["operationRetries"] },
+        async (tx) => {
+          return tx.operationRetries.get(id);
+        },
+      );
+    }),
+  );
+
+  const tasks = allTasksId.map((taskId, i): ActiveTask => {
+    const transaction = convertTaskToTransactionId(taskId);
+    const d = tasksInfo[i];
+
+    const firstTry = !d
+      ? undefined
+      : timestampAbsoluteFromDb(d.retryInfo.firstTry);
+    const nextTry = !d
+      ? undefined
+      : timestampAbsoluteFromDb(d.retryInfo.nextRetry);
+    const counter = d?.retryInfo.retryCounter;
+    const lastError = d?.lastError;
+
+    return {
+      taskId: taskId,
+      retryCounter: counter,
+      firstTry,
+      nextTry,
+      lastError,
+      transaction,
+    };
+  });
+  return { tasks };
+}
+
+async function handleFailTransaction(
+  wex: WalletExecutionContext,
+  req: FailTransactionRequest,
+): Promise<EmptyObject> {
+  await failTransaction(wex, req.transactionId);
+  return {};
+}
+
+async function handleTestingGetSampleTransactions(
+  wex: WalletExecutionContext,
+  req: EmptyObject,
+): Promise<TransactionsResponse> {
+  // FIXME!
+  return { transactions: [] };
+  // These are out of date!
+  //return { transactions: sampleWalletCoreTransactions };
+}
+
+async function handleStartRefundQuery(
+  wex: WalletExecutionContext,
+  req: StartRefundQueryRequest,
+): Promise<EmptyObject> {
+  const txIdParsed = parseTransactionIdentifier(req.transactionId);
+  if (!txIdParsed) {
+    throw Error("invalid transaction ID");
+  }
+  if (txIdParsed.tag !== TransactionType.Payment) {
+    throw Error("expected payment transaction ID");
+  }
+  await startQueryRefund(wex, txIdParsed.proposalId);
+  return {};
+}
+
+async function handleAddBackupProvider(
+  wex: WalletExecutionContext,
+  req: RunBackupCycleRequest,
+): Promise<EmptyObject> {
+  await runBackupCycle(wex, req);
+  return {};
+}
+
+async function handleHintNetworkAvailability(
+  wex: WalletExecutionContext,
+  req: HintNetworkAvailabilityRequest,
+): Promise<EmptyObject> {
+  wex.ws.networkAvailable = req.isNetworkAvailable;
+  // When network becomes available, restart tasks as they're blocked
+  // waiting for the network.
+  // When network goes down, restart tasks so they notice the network
+  // is down and wait.
+  await restartAllRunningTasks(wex);
+  return {};
+}
+
+async function handleGetDepositWireTypesForCurrency(
+  wex: WalletExecutionContext,
+  req: GetDepositWireTypesForCurrencyRequest,
+): Promise<GetDepositWireTypesForCurrencyResponse> {
+  const wtSet: Set<string> = new Set();
+  await wex.db.runReadOnlyTx(
+    { storeNames: ["exchanges", "exchangeDetails"] },
+    async (tx) => {
+      const exchanges = await tx.exchanges.getAll();
+      for (const exchange of exchanges) {
+        const det = await getExchangeWireDetailsInTx(tx, exchange.baseUrl);
+        if (!det) {
+          continue;
+        }
+        if (det.currency !== req.currency) {
+          continue;
+        }
+        for (const acc of det.wireInfo.accounts) {
+          let usable = true;
+          for (const dr of acc.debit_restrictions) {
+            if (dr.type === "deny") {
+              usable = false;
+              break;
+            }
+          }
+          if (!usable) {
+            break;
+          }
+          const parsedPayto = parsePaytoUri(acc.payto_uri);
+          if (!parsedPayto) {
+            continue;
+          }
+          wtSet.add(parsedPayto.targetType);
+        }
+      }
+    },
+  );
+  return {
+    wireTypes: [...wtSet],
+  };
+}
+
+async function handleListGlobalCurrencyExchanges(
+  wex: WalletExecutionContext,
+  req: EmptyObject,
+): Promise<ListGlobalCurrencyExchangesResponse> {
+  const resp: ListGlobalCurrencyExchangesResponse = {
+    exchanges: [],
+  };
+  await wex.db.runReadOnlyTx(
+    { storeNames: ["globalCurrencyExchanges"] },
+    async (tx) => {
+      const gceList = await tx.globalCurrencyExchanges.iter().toArray();
+      for (const gce of gceList) {
+        resp.exchanges.push({
+          currency: gce.currency,
+          exchangeBaseUrl: gce.exchangeBaseUrl,
+          exchangeMasterPub: gce.exchangeMasterPub,
+        });
+      }
+    },
+  );
+  return resp;
+}
+
 /**
  * Implementation of the "wallet-core" API.
  */
@@ -944,30 +1294,7 @@ async function dispatchRequestInternal(
     }
     case WalletApiOperation.TestingGetDenomStats: {
       const req = codecForTestingGetDenomStatsRequest().decode(payload);
-      const denomStats: TestingGetDenomStatsResponse = {
-        numKnown: 0,
-        numLost: 0,
-        numOffered: 0,
-      };
-      await wex.db.runReadOnlyTx(
-        { storeNames: ["denominations"] },
-        async (tx) => {
-          const denoms =
-            await tx.denominations.indexes.byExchangeBaseUrl.getAll(
-              req.exchangeBaseUrl,
-            );
-          for (const d of denoms) {
-            denomStats.numKnown++;
-            if (d.isOffered) {
-              denomStats.numOffered++;
-            }
-            if (d.isLost) {
-              denomStats.numLost++;
-            }
-          }
-        },
-      );
-      return denomStats;
+      return handleTestingGetDenomStats(wex, req);
     }
     case WalletApiOperation.ListExchanges: {
       return await listExchanges(wex);
@@ -979,20 +1306,7 @@ async function dispatchRequestInternal(
     case WalletApiOperation.ListExchangesForScopedCurrency: {
       const req =
         codecForListExchangesForScopedCurrencyRequest().decode(payload);
-      const exchangesResp = await listExchanges(wex);
-      const result: ExchangesShortListResponse = {
-        exchanges: [],
-      };
-      // Right now we only filter on the currency, as wallet-core doesn't
-      // fully support scoped currencies yet.
-      for (const exch of exchangesResp.exchanges) {
-        if (exch.currency === req.scope.currency) {
-          result.exchanges.push({
-            exchangeBaseUrl: exch.exchangeBaseUrl,
-          });
-        }
-      }
-      return result;
+      return await handleListExchangesForScopedCurrency(wex, req);
     }
     case WalletApiOperation.GetExchangeDetailedInfo: {
       const req = codecForAddExchangeRequest().decode(payload);
@@ -1004,13 +1318,11 @@ async function dispatchRequestInternal(
     }
     case WalletApiOperation.AddKnownBankAccounts: {
       const req = codecForAddKnownBankAccounts().decode(payload);
-      await addKnownBankAccounts(wex, req.payto, req.alias, req.currency);
-      return {};
+      return await handleAddKnownBankAccount(wex, req);
     }
     case WalletApiOperation.ForgetKnownBankAccounts: {
       const req = codecForForgetKnownBankAccounts().decode(payload);
-      await forgetKnownBankAccounts(wex, req.payto);
-      return {};
+      return await handleForgetKnownBankAccounts(wex, req);
     }
     case WalletApiOperation.GetWithdrawalDetailsForUri: {
       const req = codecForGetWithdrawalDetailsForUri().decode(payload);
@@ -1018,48 +1330,16 @@ async function dispatchRequestInternal(
     }
     case WalletApiOperation.TestingGetReserveHistory: {
       const req = codecForTestingGetReserveHistoryRequest().decode(payload);
-      const reserve = await wex.db.runReadOnlyTx(
-        { storeNames: ["reserves"] },
-        async (tx) => {
-          return tx.reserves.indexes.byReservePub.get(req.reservePub);
-        },
-      );
-      if (!reserve) {
-        throw Error("no reserve pub found");
-      }
-      const sigResp = await wex.cryptoApi.signReserveHistoryReq({
-        reservePriv: reserve.reservePriv,
-        startOffset: 0,
-      });
-      const exchangeBaseUrl = req.exchangeBaseUrl;
-      const url = new URL(
-        `reserves/${req.reservePub}/history`,
-        exchangeBaseUrl,
-      );
-      const resp = await wex.http.fetch(url.href, {
-        headers: { ["Taler-Reserve-History-Signature"]: sigResp.sig },
-      });
-      const historyJson = await readSuccessResponseJsonOrThrow(
-        resp,
-        codecForAny(),
-      );
-      return historyJson;
+      return await handleTestingGetReserveHistory(wex, req);
     }
     case WalletApiOperation.AcceptManualWithdrawal: {
       const req = codecForAcceptManualWithdrawalRequest().decode(payload);
-      const res = await createManualWithdrawal(wex, {
-        amount: Amounts.parseOrThrow(req.amount),
-        exchangeBaseUrl: req.exchangeBaseUrl,
-        restrictAge: req.restrictAge,
-        forceReservePriv: req.forceReservePriv,
-      });
-      return res;
+      return await handleAcceptManualWithdrawal(wex, req);
     }
     case WalletApiOperation.GetWithdrawalDetailsForAmount: {
       const req =
         codecForGetWithdrawalDetailsForAmountRequest().decode(payload);
-      const resp = await getWithdrawalDetailsForAmount(wex, cts, req);
-      return resp;
+      return await getWithdrawalDetailsForAmount(wex, cts, req);
     }
     case WalletApiOperation.GetBalances: {
       return await getBalances(wex);
@@ -1080,12 +1360,6 @@ async function dispatchRequestInternal(
       const req = codecForUserAttentionsRequest().decode(payload);
       return await getUserAttentionsUnreadCount(wex, req);
     }
-    case WalletApiOperation.GetPendingOperations: {
-      // FIXME: Eventually remove the handler after deprecation period.
-      return {
-        pendingOperations: [],
-      } satisfies PendingOperationsResponse;
-    }
     case WalletApiOperation.SetExchangeTosAccepted: {
       const req = codecForAcceptExchangeTosRequest().decode(payload);
       await acceptExchangeTermsOfService(wex, req.exchangeBaseUrl);
@@ -1118,27 +1392,11 @@ async function dispatchRequestInternal(
     }
     case WalletApiOperation.GetExchangeTos: {
       const req = codecForGetExchangeTosRequest().decode(payload);
-      return getExchangeTos(
-        wex,
-        req.exchangeBaseUrl,
-        req.acceptedFormat,
-        req.acceptLanguage,
-      );
+      return await handleGetExchangeTos(wex, req);
     }
     case WalletApiOperation.GetContractTermsDetails: {
       const req = codecForGetContractTermsDetails().decode(payload);
-      if (req.proposalId) {
-        // FIXME: deprecated path
-        return getContractTermsDetails(wex, req.proposalId);
-      }
-      if (req.transactionId) {
-        const parsedTx = parseTransactionIdentifier(req.transactionId);
-        if (parsedTx?.tag === TransactionType.Payment) {
-          return getContractTermsDetails(wex, parsedTx.proposalId);
-        }
-        throw Error("transactionId is not a payment transaction");
-      }
-      throw Error("transactionId missing");
+      return handleGetContractTermsDetails(wex, req);
     }
     case WalletApiOperation.RetryPendingNow: {
       return handleRetryPendingNow(wex);
@@ -1165,78 +1423,26 @@ async function dispatchRequestInternal(
     }
     case WalletApiOperation.GetQrCodesForPayto: {
       const req = codecForGetQrCodesForPaytoRequest().decode(payload);
-      return {
-        codes: getQrCodesForPayto(req.paytoUri),
-      };
+      return handleGetQrCodesForPayto(wex, req);
     }
     case WalletApiOperation.ConfirmPay: {
       const req = codecForConfirmPayRequest().decode(payload);
-      let transactionId;
-      if (req.proposalId) {
-        // legacy client support
-        transactionId = constructTransactionIdentifier({
-          tag: TransactionType.Payment,
-          proposalId: req.proposalId,
-        });
-      } else if (req.transactionId) {
-        transactionId = req.transactionId;
-      } else {
-        throw Error("transactionId or (deprecated) proposalId required");
-      }
-      return await confirmPay(wex, transactionId, req.sessionId);
+      return handleConfirmPay(wex, req);
     }
     case WalletApiOperation.AbortTransaction: {
       const req = codecForAbortTransaction().decode(payload);
-      await abortTransaction(wex, req.transactionId);
-      return {};
+      return handleAbortTransaction(wex, req);
     }
     case WalletApiOperation.SuspendTransaction: {
       const req = codecForSuspendTransaction().decode(payload);
-      await suspendTransaction(wex, req.transactionId);
-      return {};
+      return handleSuspendTransaction(wex, req);
     }
     case WalletApiOperation.GetActiveTasks: {
-      const allTasksId = (await getActiveTaskIds(wex.ws)).taskIds;
-
-      const tasksInfo = await Promise.all(
-        allTasksId.map(async (id) => {
-          return await wex.db.runReadOnlyTx(
-            { storeNames: ["operationRetries"] },
-            async (tx) => {
-              return tx.operationRetries.get(id);
-            },
-          );
-        }),
-      );
-
-      const tasks = allTasksId.map((taskId, i): ActiveTask => {
-        const transaction = convertTaskToTransactionId(taskId);
-        const d = tasksInfo[i];
-
-        const firstTry = !d
-          ? undefined
-          : timestampAbsoluteFromDb(d.retryInfo.firstTry);
-        const nextTry = !d
-          ? undefined
-          : timestampAbsoluteFromDb(d.retryInfo.nextRetry);
-        const counter = d?.retryInfo.retryCounter;
-        const lastError = d?.lastError;
-
-        return {
-          taskId: taskId,
-          retryCounter: counter,
-          firstTry,
-          nextTry,
-          lastError,
-          transaction,
-        };
-      });
-      return { tasks };
+      return await handleGetActiveTasks(wex, {});
     }
     case WalletApiOperation.FailTransaction: {
       const req = codecForFailTransactionRequest().decode(payload);
-      await failTransaction(wex, req.transactionId);
-      return {};
+      return await handleFailTransaction(wex, req);
     }
     case WalletApiOperation.ResumeTransaction: {
       const req = codecForResumeTransaction().decode(payload);
@@ -1252,7 +1458,8 @@ async function dispatchRequestInternal(
       return {};
     }
     case WalletApiOperation.TestingGetSampleTransactions:
-      return { transactions: sampleWalletCoreTransactions };
+      const req = codecForEmptyObject().decode(payload);
+      return handleTestingGetSampleTransactions(wex, req);
     case WalletApiOperation.ForceRefresh: {
       const req = codecForForceRefreshRequest().decode(payload);
       return await forceRefresh(wex, req);
@@ -1263,15 +1470,7 @@ async function dispatchRequestInternal(
     }
     case WalletApiOperation.StartRefundQuery: {
       const req = codecForStartRefundQueryRequest().decode(payload);
-      const txIdParsed = parseTransactionIdentifier(req.transactionId);
-      if (!txIdParsed) {
-        throw Error("invalid transaction ID");
-      }
-      if (txIdParsed.tag !== TransactionType.Payment) {
-        throw Error("expected payment transaction ID");
-      }
-      await startQueryRefund(wex, txIdParsed.proposalId);
-      return {};
+      return handleStartRefundQuery(wex, req);
     }
     case WalletApiOperation.AddBackupProvider: {
       const req = codecForAddBackupProviderRequest().decode(payload);
@@ -1279,8 +1478,7 @@ async function dispatchRequestInternal(
     }
     case WalletApiOperation.RunBackupCycle: {
       const req = codecForRunBackupCycle().decode(payload);
-      await runBackupCycle(wex, req);
-      return {};
+      return handleAddBackupProvider(wex, req);
     }
     case WalletApiOperation.RemoveBackupProvider: {
       const req = codecForRemoveBackupProvider().decode(payload);
@@ -1307,13 +1505,7 @@ async function dispatchRequestInternal(
     }
     case WalletApiOperation.HintNetworkAvailability: {
       const req = codecForHintNetworkAvailabilityRequest().decode(payload);
-      wex.ws.networkAvailable = req.isNetworkAvailable;
-      // When network becomes available, restart tasks as they're blocked
-      // waiting for the network.
-      // When network goes down, restart tasks so they notice the network
-      // is down and wait.
-      await restartAllRunningTasks(wex);
-      return {};
+      return await handleHintNetworkAvailability(wex, req);
     }
     case WalletApiOperation.ConvertDepositAmount: {
       const req = codecForConvertAmountRequest.decode(payload);
@@ -1385,61 +1577,11 @@ async function dispatchRequestInternal(
     case WalletApiOperation.GetDepositWireTypesForCurrency: {
       const req =
         codecForGetDepositWireTypesForCurrencyRequest().decode(payload);
-      const wtSet: Set<string> = new Set();
-      await wex.db.runReadOnlyTx(
-        { storeNames: ["exchanges", "exchangeDetails"] },
-        async (tx) => {
-          const exchanges = await tx.exchanges.getAll();
-          for (const exchange of exchanges) {
-            const det = await getExchangeWireDetailsInTx(tx, exchange.baseUrl);
-            if (!det) {
-              continue;
-            }
-            if (det.currency !== req.currency) {
-              continue;
-            }
-            for (const acc of det.wireInfo.accounts) {
-              let usable = true;
-              for (const dr of acc.debit_restrictions) {
-                if (dr.type === "deny") {
-                  usable = false;
-                  break;
-                }
-              }
-              if (!usable) {
-                break;
-              }
-              const parsedPayto = parsePaytoUri(acc.payto_uri);
-              if (!parsedPayto) {
-                continue;
-              }
-              wtSet.add(parsedPayto.targetType);
-            }
-          }
-        },
-      );
-      return {
-        wireTypes: [...wtSet],
-      };
+      return handleGetDepositWireTypesForCurrency(wex, req);
     }
     case WalletApiOperation.ListGlobalCurrencyExchanges: {
-      const resp: ListGlobalCurrencyExchangesResponse = {
-        exchanges: [],
-      };
-      await wex.db.runReadOnlyTx(
-        { storeNames: ["globalCurrencyExchanges"] },
-        async (tx) => {
-          const gceList = await tx.globalCurrencyExchanges.iter().toArray();
-          for (const gce of gceList) {
-            resp.exchanges.push({
-              currency: gce.currency,
-              exchangeBaseUrl: gce.exchangeBaseUrl,
-              exchangeMasterPub: gce.exchangeMasterPub,
-            });
-          }
-        },
-      );
-      return resp;
+      const req = codecForEmptyObject().decode(payload);
+      return await handleListGlobalCurrencyExchanges(wex, req);
     }
     case WalletApiOperation.ListGlobalCurrencyAuditors: {
       const resp: ListGlobalCurrencyAuditorsResponse = {

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