gnunet-svn
[Top][All Lists]
Advanced

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

[taler-wallet-core] branch master updated: deposit from wallet webex: wi


From: gnunet
Subject: [taler-wallet-core] branch master updated: deposit from wallet webex: wip
Date: Thu, 23 Dec 2021 19:17:49 +0100

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

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

The following commit(s) were added to refs/heads/master by this push:
     new 2e71117f deposit from wallet webex: wip
2e71117f is described below

commit 2e71117f59e0ae6106930e705ae6a54a9839281b
Author: Sebastian <sebasjm@gmail.com>
AuthorDate: Thu Dec 23 15:17:36 2021 -0300

    deposit from wallet webex: wip
---
 packages/taler-util/src/walletTypes.ts             |  28 ++-
 .../src/crypto/workers/cryptoImplementation.ts     |   4 +-
 .../taler-wallet-core/src/operations/deposits.ts   | 250 ++++++++++++++++++++-
 packages/taler-wallet-core/src/operations/pay.ts   |  63 +-----
 packages/taler-wallet-core/src/wallet-api-types.ts |   5 +-
 packages/taler-wallet-core/src/wallet.ts           |  39 +++-
 .../src/NavigationBar.tsx                          |   1 +
 .../src/components/BalanceTable.tsx                |  18 +-
 .../src/components/styled/index.tsx                |   4 +
 .../src/popup/BalancePage.tsx                      |  24 +-
 .../src/popup/DeveloperPage.tsx                    |  68 ++++--
 .../src/popupEntryPoint.tsx                        |   4 +
 .../src/wallet/BalancePage.tsx                     |  42 ++--
 .../src/wallet/DepositPage.stories.tsx             |  52 +++++
 .../src/wallet/DepositPage.tsx                     | 234 +++++++++++++++++++
 .../src/wallet/Transaction.tsx                     |  10 +-
 .../src/walletEntryPoint.tsx                       |   8 +
 packages/taler-wallet-webextension/src/wxApi.ts    |  23 +-
 18 files changed, 758 insertions(+), 119 deletions(-)

diff --git a/packages/taler-util/src/walletTypes.ts 
b/packages/taler-util/src/walletTypes.ts
index ced30e4d..4158dde9 100644
--- a/packages/taler-util/src/walletTypes.ts
+++ b/packages/taler-util/src/walletTypes.ts
@@ -54,6 +54,7 @@ import {
 } from "./talerTypes.js";
 import { OrderShortInfo, codecForOrderShortInfo } from 
"./transactionsTypes.js";
 import { BackupRecovery } from "./backupTypes.js";
+import { PaytoUri } from "./payto.js";
 
 /**
  * Response for the create reserve request to the wallet.
@@ -525,6 +526,10 @@ export interface ExchangesListRespose {
   exchanges: ExchangeListItem[];
 }
 
+export interface KnownBankAccounts {
+  accounts: PaytoUri[];
+}
+
 export interface ExchangeTos {
   acceptedVersion?: string;
   currentVersion?: string;
@@ -737,12 +742,19 @@ export const codecForApplyRefundRequest = (): 
Codec<ApplyRefundRequest> =>
 export interface GetWithdrawalDetailsForUriRequest {
   talerWithdrawUri: string;
 }
-
 export const codecForGetWithdrawalDetailsForUri = (): 
Codec<GetWithdrawalDetailsForUriRequest> =>
   buildCodecForObject<GetWithdrawalDetailsForUriRequest>()
     .property("talerWithdrawUri", codecForString())
     .build("GetWithdrawalDetailsForUriRequest");
 
+export interface ListKnownBankAccountsRequest {
+  currency?: string;
+}
+export const codecForListKnownBankAccounts = (): 
Codec<ListKnownBankAccountsRequest> =>
+  buildCodecForObject<ListKnownBankAccountsRequest>()
+    .property("currency", codecOptional(codecForString()))
+    .build("ListKnownBankAccountsRequest");
+
 export interface GetExchangeWithdrawalInfo {
   exchangeBaseUrl: string;
   amount: AmountJson;
@@ -965,11 +977,23 @@ export const codecForAbortPayWithRefundRequest = (): 
Codec<AbortPayWithRefundReq
     .property("proposalId", codecForString())
     .build("AbortPayWithRefundRequest");
 
+export interface GetFeeForDepositRequest {
+  depositPaytoUri: string;
+  amount: AmountString;
+}
+
 export interface CreateDepositGroupRequest {
   depositPaytoUri: string;
-  amount: string;
+  amount: AmountString;
 }
 
+
+export const codecForGetFeeForDeposit = (): Codec<GetFeeForDepositRequest> =>
+  buildCodecForObject<GetFeeForDepositRequest>()
+    .property("amount", codecForAmountString())
+    .property("depositPaytoUri", codecForString())
+    .build("GetFeeForDepositRequest");
+
 export const codecForCreateDepositGroupRequest = (): 
Codec<CreateDepositGroupRequest> =>
   buildCodecForObject<CreateDepositGroupRequest>()
     .property("amount", codecForAmountString())
diff --git 
a/packages/taler-wallet-core/src/crypto/workers/cryptoImplementation.ts 
b/packages/taler-wallet-core/src/crypto/workers/cryptoImplementation.ts
index 04bc2d9b..b5987582 100644
--- a/packages/taler-wallet-core/src/crypto/workers/cryptoImplementation.ts
+++ b/packages/taler-wallet-core/src/crypto/workers/cryptoImplementation.ts
@@ -162,7 +162,7 @@ async function myEddsaSign(
 export class CryptoImplementation {
   static enableTracing = false;
 
-  constructor(private primitiveWorker?: PrimitiveWorker) {}
+  constructor(private primitiveWorker?: PrimitiveWorker) { }
 
   /**
    * Create a pre-coin of the given denomination to be withdrawn from then 
given
@@ -369,7 +369,7 @@ export class CryptoImplementation {
     sig: string,
     masterPub: string,
   ): boolean {
-    if (versionCurrent === 10) {
+    if (versionCurrent === 10 || versionCurrent === 11) {
       const paytoHash = hash(stringToBytes(paytoUri + "\0"));
       const p = buildSigPS(TalerSignaturePurpose.MASTER_WIRE_DETAILS)
         .put(paytoHash)
diff --git a/packages/taler-wallet-core/src/operations/deposits.ts 
b/packages/taler-wallet-core/src/operations/deposits.ts
index f90172a4..6d28c23e 100644
--- a/packages/taler-wallet-core/src/operations/deposits.ts
+++ b/packages/taler-wallet-core/src/operations/deposits.ts
@@ -15,6 +15,7 @@
  */
 
 import {
+  AmountJson,
   Amounts,
   buildCodecForObject,
   canonicalJson,
@@ -28,6 +29,7 @@ import {
   decodeCrock,
   DenomKeyType,
   durationFromSpec,
+  GetFeeForDepositRequest,
   getTimestampNow,
   Logger,
   NotificationType,
@@ -35,6 +37,7 @@ import {
   TalerErrorDetails,
   Timestamp,
   timestampAddDuration,
+  timestampIsBetween,
   timestampTruncateToSecond,
   TrackDepositGroupRequest,
   TrackDepositGroupResponse,
@@ -49,7 +52,7 @@ import {
 } from "@gnu-taler/taler-util";
 import { DepositGroupRecord } from "../db.js";
 import { guardOperationException } from "../errors.js";
-import { selectPayCoins } from "../util/coinSelection.js";
+import { PayCoinSelection, selectPayCoins } from "../util/coinSelection.js";
 import { readSuccessResponseJsonOrThrow } from "../util/http.js";
 import { initRetryInfo, updateRetryInfoTimeout } from "../util/retries.js";
 import { getExchangeDetails } from "./exchanges.js";
@@ -58,11 +61,11 @@ import {
   extractContractData,
   generateDepositPermissions,
   getCandidatePayCoins,
-  getEffectiveDepositAmount,
   getTotalPaymentCost,
   hashWire,
   hashWireLegacy,
 } from "./pay.js";
+import { getTotalRefreshCost } from "./refresh.js";
 
 /**
  * Logger.
@@ -342,6 +345,100 @@ export async function trackDepositGroup(
   };
 }
 
+export async function getFeeForDeposit(
+  ws: InternalWalletState,
+  req: GetFeeForDepositRequest,
+): Promise<DepositFee> {
+  const p = parsePaytoUri(req.depositPaytoUri);
+  if (!p) {
+    throw Error("invalid payto URI");
+  }
+
+  const amount = Amounts.parseOrThrow(req.amount);
+
+  const exchangeInfos: { url: string; master_pub: string }[] = [];
+
+  await ws.db
+    .mktx((x) => ({
+      exchanges: x.exchanges,
+      exchangeDetails: x.exchangeDetails,
+    }))
+    .runReadOnly(async (tx) => {
+      const allExchanges = await tx.exchanges.iter().toArray();
+      for (const e of allExchanges) {
+        const details = await getExchangeDetails(tx, e.baseUrl);
+        if (!details) {
+          continue;
+        }
+        exchangeInfos.push({
+          master_pub: details.masterPublicKey,
+          url: e.baseUrl,
+        });
+      }
+    });
+
+  const timestamp = getTimestampNow();
+  const timestampRound = timestampTruncateToSecond(timestamp);
+  // const noncePair = await ws.cryptoApi.createEddsaKeypair();
+  // const merchantPair = await ws.cryptoApi.createEddsaKeypair();
+  // const wireSalt = encodeCrock(getRandomBytes(16));
+  // const wireHash = hashWire(req.depositPaytoUri, wireSalt);
+  // const wireHashLegacy = hashWireLegacy(req.depositPaytoUri, wireSalt);
+  const contractTerms: ContractTerms = {
+    auditors: [],
+    exchanges: exchangeInfos,
+    amount: req.amount,
+    max_fee: Amounts.stringify(amount),
+    max_wire_fee: Amounts.stringify(amount),
+    wire_method: p.targetType,
+    timestamp: timestampRound,
+    merchant_base_url: "",
+    summary: "",
+    nonce: "",
+    wire_transfer_deadline: timestampRound,
+    order_id: "",
+    h_wire: "",
+    pay_deadline: timestampAddDuration(
+      timestampRound,
+      durationFromSpec({ hours: 1 }),
+    ),
+    merchant: {
+      name: "",
+    },
+    merchant_pub: "",
+    refund_deadline: { t_ms: 0 },
+  };
+
+  const contractData = extractContractData(
+    contractTerms,
+    "",
+    "",
+  );
+
+  const candidates = await getCandidatePayCoins(ws, contractData);
+
+  const payCoinSel = selectPayCoins({
+    candidates,
+    contractTermsAmount: contractData.amount,
+    depositFeeLimit: contractData.maxDepositFee,
+    wireFeeAmortization: contractData.wireFeeAmortization ?? 1,
+    wireFeeLimit: contractData.maxWireFee,
+    prevPayCoins: [],
+  });
+
+  if (!payCoinSel) {
+    throw Error("insufficient funds");
+  }
+
+  return await getTotalFeeForDepositAmount(
+    ws,
+    p.targetType,
+    amount,
+    payCoinSel,
+  );
+
+}
+
 export async function createDepositGroup(
   ws: InternalWalletState,
   req: CreateDepositGroupRequest,
@@ -495,3 +592,152 @@ export async function createDepositGroup(
 
   return { depositGroupId };
 }
+
+/**
+ * Get the amount that will be deposited on the merchant's bank
+ * account, not considering aggregation.
+ */
+export async function getEffectiveDepositAmount(
+  ws: InternalWalletState,
+  wireType: string,
+  pcs: PayCoinSelection,
+): Promise<AmountJson> {
+  const amt: AmountJson[] = [];
+  const fees: AmountJson[] = [];
+  const exchangeSet: Set<string> = new Set();
+
+  await ws.db
+    .mktx((x) => ({
+      coins: x.coins,
+      denominations: x.denominations,
+      exchanges: x.exchanges,
+      exchangeDetails: x.exchangeDetails,
+    }))
+    .runReadOnly(async (tx) => {
+      for (let i = 0; i < pcs.coinPubs.length; i++) {
+        const coin = await tx.coins.get(pcs.coinPubs[i]);
+        if (!coin) {
+          throw Error("can't calculate deposit amount, coin not found");
+        }
+        const denom = await tx.denominations.get([
+          coin.exchangeBaseUrl,
+          coin.denomPubHash,
+        ]);
+        if (!denom) {
+          throw Error("can't find denomination to calculate deposit amount");
+        }
+        amt.push(pcs.coinContributions[i]);
+        fees.push(denom.feeDeposit);
+        exchangeSet.add(coin.exchangeBaseUrl);
+      }
+
+      for (const exchangeUrl of exchangeSet.values()) {
+        const exchangeDetails = await getExchangeDetails(tx, exchangeUrl);
+        if (!exchangeDetails) {
+          continue;
+        }
+
+        // FIXME/NOTE: the line below _likely_ throws exception
+        // about "find method not found on undefined" when the wireType
+        // is not supported by the Exchange.
+        const fee = exchangeDetails.wireInfo.feesForType[wireType].find((x) => 
{
+          return timestampIsBetween(
+            getTimestampNow(),
+            x.startStamp,
+            x.endStamp,
+          );
+        })?.wireFee;
+        if (fee) {
+          fees.push(fee);
+        }
+      }
+    });
+  return Amounts.sub(Amounts.sum(amt).amount, Amounts.sum(fees).amount).amount;
+}
+
+export interface DepositFee {
+  coin: AmountJson;
+  wire: AmountJson;
+  refresh: AmountJson;
+}
+
+/**
+ * Get the fee amount that will be charged when trying to deposit the
+ * specified amount using the selected coins and the wire method.
+ */
+export async function getTotalFeeForDepositAmount(
+  ws: InternalWalletState,
+  wireType: string,
+  total: AmountJson,
+  pcs: PayCoinSelection,
+): Promise<DepositFee> {
+  const wireFee: AmountJson[] = [];
+  const coinFee: AmountJson[] = [];
+  const refreshFee: AmountJson[] = [];
+  const exchangeSet: Set<string> = new Set();
+
+  // let acc: AmountJson = Amounts.getZero(total.currency);
+
+  await ws.db
+    .mktx((x) => ({
+      coins: x.coins,
+      denominations: x.denominations,
+      exchanges: x.exchanges,
+      exchangeDetails: x.exchangeDetails,
+    }))
+    .runReadOnly(async (tx) => {
+      for (let i = 0; i < pcs.coinPubs.length; i++) {
+        const coin = await tx.coins.get(pcs.coinPubs[i]);
+        if (!coin) {
+          throw Error("can't calculate deposit amount, coin not found");
+        }
+        const denom = await tx.denominations.get([
+          coin.exchangeBaseUrl,
+          coin.denomPubHash,
+        ]);
+        if (!denom) {
+          throw Error("can't find denomination to calculate deposit amount");
+        }
+        // const cc = pcs.coinContributions[i]
+        // acc = Amounts.add(acc, cc).amount
+        coinFee.push(denom.feeDeposit);
+        exchangeSet.add(coin.exchangeBaseUrl);
+
+        const allDenoms = await tx.denominations.indexes.byExchangeBaseUrl
+          .iter(coin.exchangeBaseUrl)
+          .filter((x) =>
+            Amounts.isSameCurrency(x.value, pcs.coinContributions[i]),
+          );
+        const amountLeft = Amounts.sub(denom.value, pcs.coinContributions[i])
+          .amount;
+        const refreshCost = getTotalRefreshCost(allDenoms, denom, amountLeft);
+        refreshFee.push(refreshCost);
+      }
+
+      for (const exchangeUrl of exchangeSet.values()) {
+        const exchangeDetails = await getExchangeDetails(tx, exchangeUrl);
+        if (!exchangeDetails) {
+          continue;
+        }
+        // FIXME/NOTE: the line below _likely_ throws exception
+        // about "find method not found on undefined" when the wireType
+        // is not supported by the Exchange.
+        const fee = exchangeDetails.wireInfo.feesForType[wireType].find((x) => 
{
+          return timestampIsBetween(
+            getTimestampNow(),
+            x.startStamp,
+            x.endStamp,
+          );
+        })?.wireFee;
+        if (fee) {
+          wireFee.push(fee);
+        }
+      }
+    });
+
+  return {
+    coin: coinFee.length === 0 ? Amounts.getZero(total.currency) : 
Amounts.sum(coinFee).amount,
+    wire: wireFee.length === 0 ? Amounts.getZero(total.currency) : 
Amounts.sum(wireFee).amount,
+    refresh: refreshFee.length === 0 ? Amounts.getZero(total.currency) : 
Amounts.sum(refreshFee).amount
+  };
+}
diff --git a/packages/taler-wallet-core/src/operations/pay.ts 
b/packages/taler-wallet-core/src/operations/pay.ts
index 63ccc653..89930120 100644
--- a/packages/taler-wallet-core/src/operations/pay.ts
+++ b/packages/taler-wallet-core/src/operations/pay.ts
@@ -177,66 +177,6 @@ export async function getTotalPaymentCost(
     });
 }
 
-/**
- * Get the amount that will be deposited on the merchant's bank
- * account, not considering aggregation.
- */
-export async function getEffectiveDepositAmount(
-  ws: InternalWalletState,
-  wireType: string,
-  pcs: PayCoinSelection,
-): Promise<AmountJson> {
-  const amt: AmountJson[] = [];
-  const fees: AmountJson[] = [];
-  const exchangeSet: Set<string> = new Set();
-
-  await ws.db
-    .mktx((x) => ({
-      coins: x.coins,
-      denominations: x.denominations,
-      exchanges: x.exchanges,
-      exchangeDetails: x.exchangeDetails,
-    }))
-    .runReadOnly(async (tx) => {
-      for (let i = 0; i < pcs.coinPubs.length; i++) {
-        const coin = await tx.coins.get(pcs.coinPubs[i]);
-        if (!coin) {
-          throw Error("can't calculate deposit amount, coin not found");
-        }
-        const denom = await tx.denominations.get([
-          coin.exchangeBaseUrl,
-          coin.denomPubHash,
-        ]);
-        if (!denom) {
-          throw Error("can't find denomination to calculate deposit amount");
-        }
-        amt.push(pcs.coinContributions[i]);
-        fees.push(denom.feeDeposit);
-        exchangeSet.add(coin.exchangeBaseUrl);
-      }
-      for (const exchangeUrl of exchangeSet.values()) {
-        const exchangeDetails = await getExchangeDetails(tx, exchangeUrl);
-        if (!exchangeDetails) {
-          continue;
-        }
-        // FIXME/NOTE: the line below _likely_ throws exception
-        // about "find method not found on undefined" when the wireType
-        // is not supported by the Exchange.
-        const fee = exchangeDetails.wireInfo.feesForType[wireType].find((x) => 
{
-          return timestampIsBetween(
-            getTimestampNow(),
-            x.startStamp,
-            x.endStamp,
-          );
-        })?.wireFee;
-        if (fee) {
-          fees.push(fee);
-        }
-      }
-    });
-  return Amounts.sub(Amounts.sum(amt).amount, Amounts.sum(fees).amount).amount;
-}
-
 function isSpendableCoin(coin: CoinRecord, denom: DenominationRecord): boolean 
{
   if (coin.suspended) {
     return false;
@@ -585,8 +525,7 @@ async function incrementPurchasePayRetry(
       pr.payRetryInfo.retryCounter++;
       updateRetryInfoTimeout(pr.payRetryInfo);
       logger.trace(
-        `retrying pay in ${
-          getDurationRemaining(pr.payRetryInfo.nextRetry).d_ms
+        `retrying pay in ${getDurationRemaining(pr.payRetryInfo.nextRetry).d_ms
         } ms`,
       );
       pr.lastPayError = err;
diff --git a/packages/taler-wallet-core/src/wallet-api-types.ts 
b/packages/taler-wallet-core/src/wallet-api-types.ts
index 445c0539..0555b0ce 100644
--- a/packages/taler-wallet-core/src/wallet-api-types.ts
+++ b/packages/taler-wallet-core/src/wallet-api-types.ts
@@ -83,6 +83,7 @@ export enum WalletApiOperation {
   AddExchange = "addExchange",
   GetTransactions = "getTransactions",
   ListExchanges = "listExchanges",
+  ListKnownBankAccounts = "listKnownBankAccounts",
   GetWithdrawalDetailsForUri = "getWithdrawalDetailsForUri",
   GetWithdrawalDetailsForAmount = "getWithdrawalDetailsForAmount",
   AcceptManualWithdrawal = "acceptManualWithdrawal",
@@ -279,11 +280,11 @@ export type WalletOperations = {
 
 export type RequestType<
   Op extends WalletApiOperation & keyof WalletOperations
-> = WalletOperations[Op] extends { request: infer T } ? T : never;
+  > = WalletOperations[Op] extends { request: infer T } ? T : never;
 
 export type ResponseType<
   Op extends WalletApiOperation & keyof WalletOperations
-> = WalletOperations[Op] extends { response: infer T } ? T : never;
+  > = WalletOperations[Op] extends { response: infer T } ? T : never;
 
 export interface WalletCoreApiClient {
   call<Op extends WalletApiOperation & keyof WalletOperations>(
diff --git a/packages/taler-wallet-core/src/wallet.ts 
b/packages/taler-wallet-core/src/wallet.ts
index ed0046c5..2f94d5e8 100644
--- a/packages/taler-wallet-core/src/wallet.ts
+++ b/packages/taler-wallet-core/src/wallet.ts
@@ -41,6 +41,10 @@ import {
   codecForWithdrawFakebankRequest,
   URL,
   parsePaytoUri,
+  KnownBankAccounts,
+  PaytoUri,
+  codecForGetFeeForDeposit,
+  codecForListKnownBankAccounts,
 } from "@gnu-taler/taler-util";
 import {
   addBackupProvider,
@@ -58,6 +62,7 @@ import { exportBackup } from "./operations/backup/export.js";
 import { getBalances } from "./operations/balance.js";
 import {
   createDepositGroup,
+  getFeeForDeposit,
   processDepositGroup,
   trackDepositGroup,
 } from "./operations/deposits.js";
@@ -495,6 +500,30 @@ async function getExchangeTos(
   };
 }
 
+async function listKnownBankAccounts(
+  ws: InternalWalletState,
+  currency?: string,
+): Promise<KnownBankAccounts> {
+  const accounts: PaytoUri[] = []
+  await ws.db
+    .mktx((x) => ({
+      reserves: x.reserves,
+    }))
+    .runReadOnly(async (tx) => {
+      const reservesRecords = await tx.reserves.iter().toArray()
+      for (const r of reservesRecords) {
+        if (currency && currency !== r.currency) {
+          continue
+        }
+        const payto = r.senderWire ? parsePaytoUri(r.senderWire) : undefined
+        if (payto) {
+          accounts.push(payto)
+        }
+      }
+    })
+  return { accounts }
+}
+
 async function getExchanges(
   ws: InternalWalletState,
 ): Promise<ExchangesListRespose> {
@@ -728,6 +757,10 @@ async function dispatchRequestInternal(
     case "listExchanges": {
       return await getExchanges(ws);
     }
+    case "listKnownBankAccounts": {
+      const req = codecForListKnownBankAccounts().decode(payload);
+      return await listKnownBankAccounts(ws, req.currency);
+    }
     case "getWithdrawalDetailsForUri": {
       const req = codecForGetWithdrawalDetailsForUri().decode(payload);
       return await getWithdrawalDetailsForUri(ws, req.talerWithdrawUri);
@@ -881,6 +914,10 @@ async function dispatchRequestInternal(
       const resp = await getBackupInfo(ws);
       return resp;
     }
+    case "getFeeForDeposit": {
+      const req = codecForGetFeeForDeposit().decode(payload);
+      return await getFeeForDeposit(ws, req);
+    }
     case "createDepositGroup": {
       const req = codecForCreateDepositGroupRequest().decode(payload);
       return await createDepositGroup(ws, req);
@@ -1004,7 +1041,7 @@ export async function handleCoreApiRequest(
       try {
         logger.error("Caught unexpected exception:");
         logger.error(e.stack);
-      } catch (e) {}
+      } catch (e) { }
       return {
         type: "error",
         operation,
diff --git a/packages/taler-wallet-webextension/src/NavigationBar.tsx 
b/packages/taler-wallet-webextension/src/NavigationBar.tsx
index 8dc73efd..e7108679 100644
--- a/packages/taler-wallet-webextension/src/NavigationBar.tsx
+++ b/packages/taler-wallet-webextension/src/NavigationBar.tsx
@@ -34,6 +34,7 @@ export enum Pages {
   welcome = "/welcome",
   balance = "/balance",
   manual_withdraw = "/manual-withdraw",
+  deposit = "/deposit/:currency",
   settings = "/settings",
   dev = "/dev",
   cta = "/cta",
diff --git a/packages/taler-wallet-webextension/src/components/BalanceTable.tsx 
b/packages/taler-wallet-webextension/src/components/BalanceTable.tsx
index e1c19cc2..cf396e12 100644
--- a/packages/taler-wallet-webextension/src/components/BalanceTable.tsx
+++ b/packages/taler-wallet-webextension/src/components/BalanceTable.tsx
@@ -16,9 +16,18 @@
 
 import { amountFractionalBase, Amounts, Balance } from "@gnu-taler/taler-util";
 import { h, VNode } from "preact";
-import { TableWithRoundRows as TableWithRoundedRows } from "./styled/index";
+import {
+  ButtonPrimary,
+  TableWithRoundRows as TableWithRoundedRows,
+} from "./styled/index";
 
-export function BalanceTable({ balances }: { balances: Balance[] }): VNode {
+export function BalanceTable({
+  balances,
+  goToWalletDeposit,
+}: {
+  balances: Balance[];
+  goToWalletDeposit: (currency: string) => void;
+}): VNode {
   const currencyFormatter = new Intl.NumberFormat("en-US");
   return (
     <TableWithRoundedRows>
@@ -40,6 +49,11 @@ export function BalanceTable({ balances }: { balances: 
Balance[] }): VNode {
             >
               {v}
             </td>
+            <td>
+              <ButtonPrimary onClick={() => goToWalletDeposit(av.currency)}>
+                Deposit
+              </ButtonPrimary>
+            </td>
           </tr>
         );
       })}
diff --git a/packages/taler-wallet-webextension/src/components/styled/index.tsx 
b/packages/taler-wallet-webextension/src/components/styled/index.tsx
index a5c9f283..216a1fab 100644
--- a/packages/taler-wallet-webextension/src/components/styled/index.tsx
+++ b/packages/taler-wallet-webextension/src/components/styled/index.tsx
@@ -716,6 +716,10 @@ export const InputWithLabel = styled.div<{ invalid?: 
boolean }>`
   }
 `;
 
+export const ErrorText = styled.div`
+  color: red;
+`;
+
 export const ErrorBox = styled.div`
   border: 2px solid #f5c6cb;
   border-radius: 0.25em;
diff --git a/packages/taler-wallet-webextension/src/popup/BalancePage.tsx 
b/packages/taler-wallet-webextension/src/popup/BalancePage.tsx
index 33164783..40499b87 100644
--- a/packages/taler-wallet-webextension/src/popup/BalancePage.tsx
+++ b/packages/taler-wallet-webextension/src/popup/BalancePage.tsx
@@ -21,18 +21,21 @@ import { ButtonPrimary, ErrorBox } from 
"../components/styled/index";
 import { HookResponse, useAsyncAsHook } from "../hooks/useAsyncAsHook";
 import { PageLink } from "../renderHtml";
 import * as wxApi from "../wxApi";
-
+interface Props {
+  goToWalletDeposit: (currency: string) => void;
+  goToWalletManualWithdraw: () => void;
+}
 export function BalancePage({
   goToWalletManualWithdraw,
-}: {
-  goToWalletManualWithdraw: () => void;
-}): VNode {
+  goToWalletDeposit,
+}: Props): VNode {
   const state = useAsyncAsHook(wxApi.getBalance);
   return (
     <BalanceView
       balance={state}
       Linker={PageLink}
       goToWalletManualWithdraw={goToWalletManualWithdraw}
+      goToWalletDeposit={goToWalletDeposit}
     />
   );
 }
@@ -40,12 +43,14 @@ export interface BalanceViewProps {
   balance: HookResponse<BalancesResponse>;
   Linker: typeof PageLink;
   goToWalletManualWithdraw: () => void;
+  goToWalletDeposit: (currency: string) => void;
 }
 
 export function BalanceView({
   balance,
   Linker,
   goToWalletManualWithdraw,
+  goToWalletDeposit,
 }: BalanceViewProps): VNode {
   if (!balance) {
     return <div>Loading...</div>;
@@ -71,7 +76,8 @@ export function BalanceView({
             <Linker pageName="/welcome">help</Linker> getting started?
           </i18n.Translate>
         </p>
-        <footer style={{ justifyContent: "space-around" }}>
+        <footer style={{ justifyContent: "space-between" }}>
+          <div />
           <ButtonPrimary onClick={goToWalletManualWithdraw}>
             Withdraw
           </ButtonPrimary>
@@ -83,9 +89,13 @@ export function BalanceView({
   return (
     <Fragment>
       <section>
-        <BalanceTable balances={balance.response.balances} />
+        <BalanceTable
+          balances={balance.response.balances}
+          goToWalletDeposit={goToWalletDeposit}
+        />
       </section>
-      <footer style={{ justifyContent: "space-around" }}>
+      <footer style={{ justifyContent: "space-between" }}>
+        <div />
         <ButtonPrimary onClick={goToWalletManualWithdraw}>
           Withdraw
         </ButtonPrimary>
diff --git a/packages/taler-wallet-webextension/src/popup/DeveloperPage.tsx 
b/packages/taler-wallet-webextension/src/popup/DeveloperPage.tsx
index b3255524..b689004c 100644
--- a/packages/taler-wallet-webextension/src/popup/DeveloperPage.tsx
+++ b/packages/taler-wallet-webextension/src/popup/DeveloperPage.tsx
@@ -43,14 +43,17 @@ export function DeveloperPage(): VNode {
       ? []
       : operationsResponse.response.pendingOperations;
 
-  return <View status={status} 
-    timedOut={timedOut} 
-    operations={operations} 
-    onDownloadDatabase={async () => {
-      const db = await wxApi.exportDB()
-      return JSON.stringify(db)
-    }}
-  />;
+  return (
+    <View
+      status={status}
+      timedOut={timedOut}
+      operations={operations}
+      onDownloadDatabase={async () => {
+        const db = await wxApi.exportDB();
+        return JSON.stringify(db);
+      }}
+    />
+  );
 }
 
 export interface Props {
@@ -64,14 +67,21 @@ function hashObjectId(o: any): string {
   return JSON.stringify(o);
 }
 
-export function View({ status, timedOut, operations, onDownloadDatabase }: 
Props): VNode {
-  const [downloadedDatabase, setDownloadedDatabase] = useState<{time: Date; 
content: string}|undefined>(undefined)
+export function View({
+  status,
+  timedOut,
+  operations,
+  onDownloadDatabase,
+}: Props): VNode {
+  const [downloadedDatabase, setDownloadedDatabase] = useState<
+    { time: Date; content: string } | undefined
+  >(undefined);
   async function onExportDatabase(): Promise<void> {
-    const content = await onDownloadDatabase()
+    const content = await onDownloadDatabase();
     setDownloadedDatabase({
       time: new Date(),
-      content
-    })
+      content,
+    });
   }
   return (
     <div>
@@ -83,9 +93,27 @@ export function View({ status, timedOut, operations, 
onDownloadDatabase }: Props
       <button onClick={confirmReset}>reset</button>
       <br />
       <button onClick={onExportDatabase}>export database</button>
-      {downloadedDatabase && <div>
-        Database exported at <Time timestamp={{t_ms: 
downloadedDatabase.time.getTime()}} format="yyyy/MM/dd HH:mm:ss" /> <a 
href={`data:text/plain;charset=utf-8;base64,${btoa(downloadedDatabase.content)}`}
 download={`taler-wallet-database-${format(downloadedDatabase.time, 
'yyyy/MM/dd_HH:mm')}.json`}>click here</a> to download
-        </div>}
+      {downloadedDatabase && (
+        <div>
+          Database exported at
+          <Time
+            timestamp={{ t_ms: downloadedDatabase.time.getTime() }}
+            format="yyyy/MM/dd HH:mm:ss"
+          />
+          <a
+            href={`data:text/plain;charset=utf-8;base64,${toBase64(
+              downloadedDatabase.content,
+            )}`}
+            download={`taler-wallet-database-${format(
+              downloadedDatabase.time,
+              "yyyy/MM/dd_HH:mm",
+            )}.json`}
+          >
+            click here
+          </a>
+          to download
+        </div>
+      )}
       <br />
       <Diagnostics diagnostics={status} timedOut={timedOut} />
       {operations && operations.length > 0 && (
@@ -109,6 +137,14 @@ export function View({ status, timedOut, operations, 
onDownloadDatabase }: Props
   );
 }
 
+function toBase64(str: string): string {
+  return btoa(
+    encodeURIComponent(str).replace(/%([0-9A-F]{2})/g, function (match, p1) {
+      return String.fromCharCode(parseInt(p1, 16));
+    }),
+  );
+}
+
 export function reload(): void {
   try {
     // eslint-disable-next-line no-undef
diff --git a/packages/taler-wallet-webextension/src/popupEntryPoint.tsx 
b/packages/taler-wallet-webextension/src/popupEntryPoint.tsx
index 56891375..ac1872fb 100644
--- a/packages/taler-wallet-webextension/src/popupEntryPoint.tsx
+++ b/packages/taler-wallet-webextension/src/popupEntryPoint.tsx
@@ -84,6 +84,9 @@ function Application() {
               goToWalletManualWithdraw={() =>
                 goToWalletPage(Pages.manual_withdraw)
               }
+              goToWalletDeposit={(currency: string) =>
+                goToWalletPage(Pages.deposit.replace(":currency", currency))
+              }
             />
             <Route path={Pages.settings} component={SettingsPage} />
             <Route
@@ -107,6 +110,7 @@ function Application() {
             />
 
             <Route path={Pages.history} component={HistoryPage} />
+
             <Route
               path={Pages.backup}
               component={BackupPage}
diff --git a/packages/taler-wallet-webextension/src/wallet/BalancePage.tsx 
b/packages/taler-wallet-webextension/src/wallet/BalancePage.tsx
index 0a891064..52edbbe5 100644
--- a/packages/taler-wallet-webextension/src/wallet/BalancePage.tsx
+++ b/packages/taler-wallet-webextension/src/wallet/BalancePage.tsx
@@ -24,7 +24,9 @@ import * as wxApi from "../wxApi";
 
 export function BalancePage({
   goToWalletManualWithdraw,
+  goToWalletDeposit,
 }: {
+  goToWalletDeposit: (currency: string) => void;
   goToWalletManualWithdraw: () => void;
 }): VNode {
   const state = useAsyncAsHook(wxApi.getBalance);
@@ -33,6 +35,7 @@ export function BalancePage({
       balance={state}
       Linker={PageLink}
       goToWalletManualWithdraw={goToWalletManualWithdraw}
+      goToWalletDeposit={goToWalletDeposit}
     />
   );
 }
@@ -41,12 +44,14 @@ export interface BalanceViewProps {
   balance: HookResponse<BalancesResponse>;
   Linker: typeof PageLink;
   goToWalletManualWithdraw: () => void;
+  goToWalletDeposit: (currency: string) => void;
 }
 
 export function BalanceView({
   balance,
   Linker,
   goToWalletManualWithdraw,
+  goToWalletDeposit,
 }: BalanceViewProps): VNode {
   if (!balance) {
     return <div>Loading...</div>;
@@ -65,28 +70,35 @@ export function BalanceView({
   }
   if (balance.response.balances.length === 0) {
     return (
-      <p>
-        <Centered style={{ marginTop: 100 }}>
-          <i18n.Translate>
-            You have no balance to show. Need some{" "}
-            <Linker pageName="/welcome">help</Linker> getting started?
-          </i18n.Translate>
-          <div>
-            <ButtonPrimary onClick={goToWalletManualWithdraw}>
-              Withdraw
-            </ButtonPrimary>
-          </div>
-        </Centered>
-      </p>
+      <Fragment>
+        <p>
+          <Centered style={{ marginTop: 100 }}>
+            <i18n.Translate>
+              You have no balance to show. Need some{" "}
+              <Linker pageName="/welcome">help</Linker> getting started?
+            </i18n.Translate>
+          </Centered>
+        </p>
+        <footer style={{ justifyContent: "space-between" }}>
+          <div />
+          <ButtonPrimary onClick={goToWalletManualWithdraw}>
+            Withdraw
+          </ButtonPrimary>
+        </footer>
+      </Fragment>
     );
   }
 
   return (
     <Fragment>
       <section>
-        <BalanceTable balances={balance.response.balances} />
+        <BalanceTable
+          balances={balance.response.balances}
+          goToWalletDeposit={goToWalletDeposit}
+        />
       </section>
-      <footer style={{ justifyContent: "space-around" }}>
+      <footer style={{ justifyContent: "space-between" }}>
+        <div />
         <ButtonPrimary onClick={goToWalletManualWithdraw}>
           Withdraw
         </ButtonPrimary>
diff --git 
a/packages/taler-wallet-webextension/src/wallet/DepositPage.stories.tsx 
b/packages/taler-wallet-webextension/src/wallet/DepositPage.stories.tsx
new file mode 100644
index 00000000..346b85d4
--- /dev/null
+++ b/packages/taler-wallet-webextension/src/wallet/DepositPage.stories.tsx
@@ -0,0 +1,52 @@
+/*
+ This file is part of GNU Taler
+ (C) 2021 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/>
+ */
+
+/**
+ *
+ * @author Sebastian Javier Marchano (sebasjm)
+ */
+
+import { AmountJson, Amounts, parsePaytoUri } from "@gnu-taler/taler-util";
+import { DepositFee } from 
"@gnu-taler/taler-wallet-core/src/operations/deposits";
+import { createExample } from "../test-utils";
+import { View as TestedComponent } from "./DepositPage";
+
+export default {
+  title: "wallet/deposit",
+  component: TestedComponent,
+  argTypes: {},
+};
+
+async function alwaysReturnFeeToOne(): Promise<DepositFee> {
+  const fee = {
+    currency: "EUR",
+    value: 1,
+    fraction: 0,
+  };
+  return { coin: fee, refresh: fee, wire: fee };
+}
+
+export const WithEmptyAccountList = createExample(TestedComponent, {
+  knownBankAccounts: [],
+  balance: Amounts.parseOrThrow("USD:10"),
+  onCalculateFee: alwaysReturnFeeToOne,
+});
+
+export const WithSomeBankAccounts = createExample(TestedComponent, {
+  knownBankAccounts: [parsePaytoUri("payto://iban/ES8877998399652238")!],
+  balance: Amounts.parseOrThrow("EUR:10"),
+  onCalculateFee: alwaysReturnFeeToOne,
+});
diff --git a/packages/taler-wallet-webextension/src/wallet/DepositPage.tsx 
b/packages/taler-wallet-webextension/src/wallet/DepositPage.tsx
new file mode 100644
index 00000000..d4759c53
--- /dev/null
+++ b/packages/taler-wallet-webextension/src/wallet/DepositPage.tsx
@@ -0,0 +1,234 @@
+/*
+ This file is part of TALER
+ (C) 2016 GNUnet e.V.
+
+ 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.
+
+ 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
+ TALER; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+*/
+
+import {
+  AmountJson,
+  Amounts,
+  AmountString,
+  PaytoUri,
+} from "@gnu-taler/taler-util";
+import { DepositFee } from 
"@gnu-taler/taler-wallet-core/src/operations/deposits";
+import { Fragment, h, VNode } from "preact";
+import { useEffect, useState } from "preact/hooks";
+import { Part } from "../components/Part";
+import { SelectList } from "../components/SelectList";
+import {
+  ButtonPrimary,
+  ErrorText,
+  Input,
+  InputWithLabel,
+} from "../components/styled";
+import { useAsyncAsHook } from "../hooks/useAsyncAsHook";
+import * as wxApi from "../wxApi";
+
+interface Props {
+  currency: string;
+}
+export function DepositPage({ currency }: Props): VNode {
+  const [success, setSuccess] = useState(false);
+
+  const state = useAsyncAsHook(async () => {
+    const balance = await wxApi.getBalance();
+    const bs = balance.balances.filter((b) => 
b.available.startsWith(currency));
+    const currencyBalance =
+      bs.length === 0
+        ? Amounts.getZero(currency)
+        : Amounts.parseOrThrow(bs[0].available);
+    const knownAccounts = await wxApi.listKnownBankAccounts(currency);
+    return { accounts: knownAccounts.accounts, currencyBalance };
+  });
+
+  const accounts =
+    state === undefined ? [] : state.hasError ? [] : state.response.accounts;
+
+  const currencyBalance =
+    state === undefined
+      ? Amounts.getZero(currency)
+      : state.hasError
+      ? Amounts.getZero(currency)
+      : state.response.currencyBalance;
+
+  async function doSend(account: string, amount: AmountString): Promise<void> {
+    await wxApi.createDepositGroup(account, amount);
+    setSuccess(true);
+  }
+
+  async function getFeeForAmount(
+    account: string,
+    amount: AmountString,
+  ): Promise<DepositFee> {
+    return await wxApi.getFeeForDeposit(account, amount);
+  }
+
+  if (accounts.length === 0) return <div>loading..</div>;
+  if (success) return <div>deposit created</div>;
+  return (
+    <View
+      knownBankAccounts={accounts}
+      balance={currencyBalance}
+      onSend={doSend}
+      onCalculateFee={getFeeForAmount}
+    />
+  );
+}
+
+interface ViewProps {
+  knownBankAccounts: Array<PaytoUri>;
+  balance: AmountJson;
+  onSend: (account: string, amount: AmountString) => Promise<void>;
+  onCalculateFee: (
+    account: string,
+    amount: AmountString,
+  ) => Promise<DepositFee>;
+}
+
+export function View({
+  knownBankAccounts,
+  balance,
+  onSend,
+  onCalculateFee,
+}: ViewProps): VNode {
+  const accountMap = createLabelsForBankAccount(knownBankAccounts);
+  const [accountIdx, setAccountIdx] = useState(0);
+  const [amount, setAmount] = useState<number | undefined>(undefined);
+  const [fee, setFee] = useState<DepositFee | undefined>(undefined);
+  const currency = balance.currency;
+  const amountStr: AmountString = `${currency}:${amount}`;
+
+  const account = knownBankAccounts[accountIdx];
+  const accountURI = `payto://${account.targetType}/${account.targetPath}`;
+  useEffect(() => {
+    if (amount === undefined) return;
+    onCalculateFee(accountURI, amountStr).then((result) => {
+      setFee(result);
+    });
+  }, [amount]);
+
+  if (!balance) {
+    return <div>no balance</div>;
+  }
+  if (!knownBankAccounts || !knownBankAccounts.length) {
+    return <div>there is no known bank account to send money to</div>;
+  }
+  const parsedAmount =
+    amount === undefined ? undefined : Amounts.parse(amountStr);
+  const isDirty = amount !== 0;
+  const error = !isDirty
+    ? undefined
+    : !parsedAmount
+    ? "Invalid amount"
+    : Amounts.cmp(balance, parsedAmount) === -1
+    ? `To much, your current balance is ${balance.value}`
+    : undefined;
+
+  return (
+    <Fragment>
+      <h2>Send {currency} to your account</h2>
+      <section>
+        <Input>
+          <SelectList
+            label="Bank account IBAN number"
+            list={accountMap}
+            name="account"
+            value={String(accountIdx)}
+            onChange={(s) => setAccountIdx(parseInt(s, 10))}
+          />
+        </Input>
+        <InputWithLabel invalid={!!error}>
+          <label>Amount to send</label>
+          <div>
+            <span>{currency}</span>
+            <input
+              type="number"
+              value={amount}
+              onInput={(e) => {
+                const num = parseFloat(e.currentTarget.value);
+                console.log(num);
+                if (!Number.isNaN(num)) {
+                  setAmount(num);
+                } else {
+                  setAmount(undefined);
+                  setFee(undefined);
+                }
+              }}
+            />
+          </div>
+          {error && <ErrorText>{error}</ErrorText>}
+        </InputWithLabel>
+        {!error && fee && (
+          <div style={{ textAlign: "center" }}>
+            <Part
+              title="Exchange fee"
+              text={Amounts.stringify(Amounts.sum([fee.wire, 
fee.coin]).amount)}
+              kind="negative"
+            />
+            <Part
+              title="Change cost"
+              text={Amounts.stringify(fee.refresh)}
+              kind="negative"
+            />
+            {parsedAmount && (
+              <Part
+                title="Total received"
+                text={Amounts.stringify(
+                  Amounts.sub(
+                    parsedAmount,
+                    Amounts.sum([fee.wire, fee.coin]).amount,
+                  ).amount,
+                )}
+                kind="positive"
+              />
+            )}
+          </div>
+        )}
+      </section>
+      <footer>
+        <div />
+        <ButtonPrimary
+          disabled={!parsedAmount}
+          onClick={() => onSend(accountURI, amountStr)}
+        >
+          Send
+        </ButtonPrimary>
+      </footer>
+    </Fragment>
+  );
+}
+
+function createLabelsForBankAccount(knownBankAccounts: Array<PaytoUri>): {
+  [label: number]: string;
+} {
+  if (!knownBankAccounts) return {};
+  return knownBankAccounts.reduce((prev, cur, i) => {
+    let label = cur.targetPath;
+    if (cur.isKnown) {
+      switch (cur.targetType) {
+        case "x-taler-bank": {
+          label = cur.account;
+          break;
+        }
+        case "iban": {
+          label = cur.iban;
+          break;
+        }
+      }
+    }
+    return {
+      ...prev,
+      [i]: label,
+    };
+  }, {} as { [label: number]: string });
+}
diff --git a/packages/taler-wallet-webextension/src/wallet/Transaction.tsx 
b/packages/taler-wallet-webextension/src/wallet/Transaction.tsx
index 22947d0c..8172e02a 100644
--- a/packages/taler-wallet-webextension/src/wallet/Transaction.tsx
+++ b/packages/taler-wallet-webextension/src/wallet/Transaction.tsx
@@ -369,8 +369,8 @@ export function TransactionView({
 
   if (transaction.type === TransactionType.Deposit) {
     const fee = Amounts.sub(
-      Amounts.parseOrThrow(transaction.amountRaw),
       Amounts.parseOrThrow(transaction.amountEffective),
+      Amounts.parseOrThrow(transaction.amountRaw),
     ).amount;
     return (
       <TransactionTemplate>
@@ -379,15 +379,15 @@ export function TransactionView({
         <br />
         <Part
           big
-          title="Total deposit"
+          title="Total send"
           text={amountToString(transaction.amountEffective)}
-          kind="negative"
+          kind="neutral"
         />
         <Part
           big
-          title="Purchase amount"
+          title="Deposit amount"
           text={amountToString(transaction.amountRaw)}
-          kind="neutral"
+          kind="positive"
         />
         <Part big title="Fee" text={amountToString(fee)} kind="negative" />
       </TransactionTemplate>
diff --git a/packages/taler-wallet-webextension/src/walletEntryPoint.tsx 
b/packages/taler-wallet-webextension/src/walletEntryPoint.tsx
index 714e3fe5..a38add3c 100644
--- a/packages/taler-wallet-webextension/src/walletEntryPoint.tsx
+++ b/packages/taler-wallet-webextension/src/walletEntryPoint.tsx
@@ -45,6 +45,7 @@ import { WalletBox } from "./components/styled";
 import { ProviderDetailPage } from "./wallet/ProviderDetailPage";
 import { ProviderAddPage } from "./wallet/ProviderAddPage";
 import { ExchangeAddPage } from "./wallet/ExchangeAddPage";
+import { DepositPage } from "./wallet/DepositPage";
 
 function main(): void {
   try {
@@ -105,6 +106,9 @@ function Application(): VNode {
             path={Pages.balance}
             component={withLogoAndNavBar(BalancePage)}
             goToWalletManualWithdraw={() => route(Pages.manual_withdraw)}
+            goToWalletDeposit={(currency: string) =>
+              route(Pages.deposit.replace(":currency", currency))
+            }
           />
           <Route
             path={Pages.settings}
@@ -145,6 +149,10 @@ function Application(): VNode {
             component={withLogoAndNavBar(ManualWithdrawPage)}
           />
 
+          <Route
+            path={Pages.deposit}
+            component={withLogoAndNavBar(DepositPage)}
+          />
           <Route
             path={Pages.reset_required}
             component={() => <div>no yet implemented</div>}
diff --git a/packages/taler-wallet-webextension/src/wxApi.ts 
b/packages/taler-wallet-webextension/src/wxApi.ts
index 4d8b932d..64a506c1 100644
--- a/packages/taler-wallet-webextension/src/wxApi.ts
+++ b/packages/taler-wallet-webextension/src/wxApi.ts
@@ -24,10 +24,11 @@
 import {
   AcceptExchangeTosRequest,
   AcceptManualWithdrawalResult, AcceptTipRequest, AcceptWithdrawalResponse,
-  AddExchangeRequest, ApplyRefundResponse, BalancesResponse, ConfirmPayResult,
-  CoreApiResponse, DeleteTransactionRequest, ExchangesListRespose,
+  AddExchangeRequest, AmountJson, AmountString, ApplyRefundResponse, 
BalancesResponse, ConfirmPayResult,
+  CoreApiResponse, CreateDepositGroupRequest, CreateDepositGroupResponse, 
DeleteTransactionRequest, ExchangesListRespose,
   GetExchangeTosResult, GetExchangeWithdrawalInfo,
-  GetWithdrawalDetailsForUriRequest, NotificationType, PreparePayResult, 
PrepareTipRequest,
+  GetFeeForDepositRequest,
+  GetWithdrawalDetailsForUriRequest, KnownBankAccounts, NotificationType, 
PreparePayResult, PrepareTipRequest,
   PrepareTipResult, RetryTransactionRequest,
   SetWalletDeviceIdRequest, TransactionsResponse, WalletDiagnostics, 
WithdrawUriInfoResponse
 } from "@gnu-taler/taler-util";
@@ -36,6 +37,7 @@ import {
   PendingOperationsResponse,
   RemoveBackupProviderRequest
 } from "@gnu-taler/taler-wallet-core";
+import { DepositFee } from 
"@gnu-taler/taler-wallet-core/src/operations/deposits";
 import { ExchangeWithdrawDetails } from 
"@gnu-taler/taler-wallet-core/src/operations/withdraw";
 import { MessageFromBackend } from "./wxBackend.js";
 
@@ -119,6 +121,18 @@ export function resetDb(): Promise<void> {
   return callBackend("reset-db", {});
 }
 
+export function getFeeForDeposit(depositPaytoUri: string, amount: 
AmountString): Promise<DepositFee> {
+  return callBackend("getFeeForDeposit", {
+    depositPaytoUri, amount
+  } as GetFeeForDepositRequest);
+}
+
+export function createDepositGroup(depositPaytoUri: string, amount: 
AmountString): Promise<CreateDepositGroupResponse> {
+  return callBackend("createDepositGroup", {
+    depositPaytoUri, amount
+  } as CreateDepositGroupRequest);
+}
+
 /**
  * Get balances for all currencies/exchanges.
  */
@@ -170,6 +184,9 @@ export function listKnownCurrencies(): 
Promise<ListOfKnownCurrencies> {
 export function listExchanges(): Promise<ExchangesListRespose> {
   return callBackend("listExchanges", {});
 }
+export function listKnownBankAccounts(currency?: string): 
Promise<KnownBankAccounts> {
+  return callBackend("listKnownBankAccounts", { currency });
+}
 
 /**
  * Get information about the current state of wallet backups.

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