[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[taler-wallet-core] branch master updated: scope info in tx details
From: |
gnunet |
Subject: |
[taler-wallet-core] branch master updated: scope info in tx details |
Date: |
Mon, 05 Aug 2024 15:44:19 +0200 |
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 50d183195 scope info in tx details
50d183195 is described below
commit 50d183195c94d0995aafd60f0fa3766f5f5ba256
Author: Sebastian <sebasjm@gmail.com>
AuthorDate: Mon Aug 5 10:41:53 2024 -0300
scope info in tx details
---
.../src/types-taler-wallet-transactions.ts | 5 +
packages/taler-util/src/types-taler-wallet.ts | 41 +++++
packages/taler-wallet-core/src/deposits.ts | 10 +-
packages/taler-wallet-core/src/exchanges.ts | 78 ++++++++++
packages/taler-wallet-core/src/pay-merchant.ts | 14 ++
.../taler-wallet-core/src/pay-peer-pull-credit.ts | 4 +-
.../taler-wallet-core/src/pay-peer-pull-debit.ts | 2 +
.../taler-wallet-core/src/pay-peer-push-credit.ts | 4 +-
.../taler-wallet-core/src/pay-peer-push-debit.ts | 2 +
packages/taler-wallet-core/src/refresh.ts | 2 +
packages/taler-wallet-core/src/withdraw.ts | 26 +++-
.../src/NavigationBar.tsx | 12 +-
.../src/components/BalanceTable.tsx | 6 +-
.../src/components/MultiActionButton.tsx | 18 +--
.../src/popup/Application.tsx | 51 ++++--
.../src/popup/BalancePage.tsx | 13 +-
.../src/wallet/Application.tsx | 172 ++++++++++++++-------
.../src/wallet/DepositPage/index.ts | 9 +-
.../src/wallet/DepositPage/state.ts | 9 +-
.../src/wallet/DepositPage/test.ts | 12 +-
.../src/wallet/History.stories.tsx | 79 ++++++++--
.../src/wallet/History.tsx | 67 ++++----
.../src/wallet/Transaction.stories.tsx | 1 +
.../src/wallet/Transaction.tsx | 24 +--
24 files changed, 496 insertions(+), 165 deletions(-)
diff --git a/packages/taler-util/src/types-taler-wallet-transactions.ts
b/packages/taler-util/src/types-taler-wallet-transactions.ts
index 6be6cc296..da3aaca2d 100644
--- a/packages/taler-util/src/types-taler-wallet-transactions.ts
+++ b/packages/taler-util/src/types-taler-wallet-transactions.ts
@@ -190,6 +190,11 @@ export interface TransactionCommon {
// main timestamp of the transaction
timestamp: TalerPreciseTimestamp;
+ /**
+ * Scope of this tx
+ */
+ scopes: ScopeInfo[];
+
/**
* Transaction state, as per DD37.
*/
diff --git a/packages/taler-util/src/types-taler-wallet.ts
b/packages/taler-util/src/types-taler-wallet.ts
index 7a5c1317b..55a2b07d5 100644
--- a/packages/taler-util/src/types-taler-wallet.ts
+++ b/packages/taler-util/src/types-taler-wallet.ts
@@ -577,6 +577,47 @@ export type ScopeInfoAuditor = {
export type ScopeInfo = ScopeInfoGlobal | ScopeInfoExchange | ScopeInfoAuditor;
+/**
+ * Shorter version of stringifyScopeInfo
+ *
+ * Format must be stable as it's used in the database.
+ */
+export function stringifyScopeInfoShort(si: ScopeInfo): string {
+ switch (si.type) {
+ case ScopeType.Global:
+ return `${si.currency}`;
+ case ScopeType.Exchange:
+ return `${si.currency}/${encodeURIComponent(si.url)}`;
+ case ScopeType.Auditor:
+ return `${si.currency}:${encodeURIComponent(si.url)}`;
+ }
+}
+export function parseScopeInfoShort(si: string): ScopeInfo | undefined {
+ const indexOfColon = si.indexOf(":");
+ const indexOfSlash = si.indexOf("/");
+ if (indexOfColon === -1 && indexOfColon === -1) {
+ return {
+ type: ScopeType.Global,
+ currency: si,
+ };
+ }
+ if (indexOfColon > 0) {
+ return {
+ type: ScopeType.Auditor,
+ currency: si.substring(0, indexOfColon),
+ url: decodeURIComponent(si.substring(indexOfColon + 1)),
+ };
+ }
+ if (indexOfSlash > 0) {
+ return {
+ type: ScopeType.Exchange,
+ currency: si.substring(0, indexOfSlash),
+ url: decodeURIComponent(si.substring(indexOfSlash + 1)),
+ };
+ }
+ return undefined;
+}
+
/**
* Encode scope info as a string.
*
diff --git a/packages/taler-wallet-core/src/deposits.ts
b/packages/taler-wallet-core/src/deposits.ts
index 37c73607a..2c931fc39 100644
--- a/packages/taler-wallet-core/src/deposits.ts
+++ b/packages/taler-wallet-core/src/deposits.ts
@@ -43,6 +43,7 @@ import {
PrepareDepositRequest,
PrepareDepositResponse,
RefreshReason,
+ ScopeInfo,
SelectedProspectiveCoin,
TalerError,
TalerErrorCode,
@@ -99,7 +100,13 @@ import {
timestampProtocolFromDb,
timestampProtocolToDb,
} from "./db.js";
-import { getExchangeWireDetailsInTx, getExchangeWireFee } from
"./exchanges.js";
+import {
+ getExchangeScopeInfo,
+ getExchangeScopeInfoOrUndefined,
+ getExchangeWireDetailsInTx,
+ getExchangeWireFee,
+ getScopeForAllExchanges,
+} from "./exchanges.js";
import {
extractContractData,
generateDepositPermissions,
@@ -193,6 +200,7 @@ export class DepositTransactionContext implements
TransactionContext {
return {
type: TransactionType.Deposit,
txState,
+ scopes: await getScopeForAllExchanges(tx, !dg.infoPerExchange? []:
Object.keys(dg.infoPerExchange)),
txActions: computeDepositTransactionActions(dg),
amountRaw: Amounts.stringify(dg.counterpartyEffectiveDepositAmount),
amountEffective: isUnsuccessfulTransaction(txState)
diff --git a/packages/taler-wallet-core/src/exchanges.ts
b/packages/taler-wallet-core/src/exchanges.ts
index 270cd6ded..5872d87bb 100644
--- a/packages/taler-wallet-core/src/exchanges.ts
+++ b/packages/taler-wallet-core/src/exchanges.ts
@@ -248,6 +248,83 @@ async function getExchangeRecordsInternal(
return details;
}
+export async function getScopeForAllCoins(
+ tx: WalletDbReadOnlyTransaction<
+ [
+ "exchanges",
+ "exchangeDetails",
+ "globalCurrencyExchanges",
+ "globalCurrencyAuditors",
+ ]
+ >,
+ exs: string[],
+): Promise<ScopeInfo[]> {
+ const queries = exs.map((exchange) => {
+ return getExchangeScopeInfoOrUndefined(tx, exchange);
+ });
+ const rs = await Promise.all(queries);
+ return rs.filter((d): d is ScopeInfo => d !== undefined);
+}
+
+export async function getScopeForAllExchanges(
+ tx: WalletDbReadOnlyTransaction<
+ [
+ "exchanges",
+ "exchangeDetails",
+ "globalCurrencyExchanges",
+ "globalCurrencyAuditors",
+ ]
+ >,
+ exs: string[],
+): Promise<ScopeInfo[]> {
+ const queries = exs.map((exchange) => {
+ return getExchangeScopeInfoOrUndefined(tx, exchange);
+ });
+ const rs = await Promise.all(queries);
+ return rs.filter((d): d is ScopeInfo => d !== undefined);
+}
+
+export async function getCoinScopeInfoOrUndefined(
+ tx: WalletDbReadOnlyTransaction<
+ [
+ "coins",
+ "exchanges",
+ "exchangeDetails",
+ "globalCurrencyExchanges",
+ "globalCurrencyAuditors",
+ ]
+ >,
+ coinPub: string,
+): Promise<ScopeInfo | undefined> {
+ const coin = await tx.coins.get(coinPub);
+ if (!coin) {
+ return undefined;
+ }
+ const det = await getExchangeRecordsInternal(tx, coin.exchangeBaseUrl);
+ if (!det) {
+ return undefined;
+ }
+ return internalGetExchangeScopeInfo(tx, det);
+}
+
+export async function getExchangeScopeInfoOrUndefined(
+ tx: WalletDbReadOnlyTransaction<
+ [
+ "exchanges",
+ "exchangeDetails",
+ "globalCurrencyExchanges",
+ "globalCurrencyAuditors",
+ ]
+ >,
+ exchangeBaseUrl: string,
+): Promise<ScopeInfo | undefined> {
+ const det = await getExchangeRecordsInternal(tx, exchangeBaseUrl);
+ if (!det) {
+ return undefined;
+ }
+ return internalGetExchangeScopeInfo(tx, det);
+}
+
export async function getExchangeScopeInfo(
tx: WalletDbReadOnlyTransaction<
[
@@ -2154,6 +2231,7 @@ export class DenomLossTransactionContext implements
TransactionContext {
return {
type: TransactionType.DenomLoss,
txState,
+ scopes: await getScopeForAllExchanges(tx, [rec.exchangeBaseUrl]),
txActions: [TransactionAction.Delete],
amountRaw: Amounts.stringify(rec.amount),
amountEffective: Amounts.stringify(rec.amount),
diff --git a/packages/taler-wallet-core/src/pay-merchant.ts
b/packages/taler-wallet-core/src/pay-merchant.ts
index f74e47213..726abb1e7 100644
--- a/packages/taler-wallet-core/src/pay-merchant.ts
+++ b/packages/taler-wallet-core/src/pay-merchant.ts
@@ -161,6 +161,7 @@ import {
getDenomInfo,
WalletExecutionContext,
} from "./wallet.js";
+import { getScopeForAllExchanges } from "./exchanges.js";
/**
* Logger.
@@ -276,6 +277,12 @@ export class PayMerchantTransactionContext implements
TransactionContext {
return {
type: TransactionType.Payment,
txState,
+ scopes: await getScopeForAllExchanges(
+ tx,
+ !purchaseRec.payInfo.payCoinSelection
+ ? []
+ : purchaseRec.payInfo.payCoinSelection.coinPubs,
+ ),
txActions: computePayMerchantTransactionActions(purchaseRec),
amountRaw: Amounts.stringify(contractData.amount),
amountEffective: isUnsuccessfulTransaction(txState)
@@ -617,10 +624,17 @@ export class RefundTransactionContext implements
TransactionContext {
summary_i18n: maybeContractData.summaryI18n,
};
}
+ const purchaseRecord = await tx.purchases.get(refundRecord.proposalId);
const txState = computeRefundTransactionState(refundRecord);
return {
type: TransactionType.Refund,
+ scopes: await getScopeForAllExchanges(
+ tx,
+ !purchaseRecord || !purchaseRecord.payInfo?.payCoinSelection
+ ? []
+ : purchaseRecord.payInfo.payCoinSelection.coinPubs,
+ ),
amountEffective: isUnsuccessfulTransaction(txState)
? Amounts.stringify(Amounts.zeroOfAmount(refundRecord.amountEffective))
: refundRecord.amountEffective,
diff --git a/packages/taler-wallet-core/src/pay-peer-pull-credit.ts
b/packages/taler-wallet-core/src/pay-peer-pull-credit.ts
index de180ccd5..7071010b8 100644
--- a/packages/taler-wallet-core/src/pay-peer-pull-credit.ts
+++ b/packages/taler-wallet-core/src/pay-peer-pull-credit.ts
@@ -83,7 +83,7 @@ import {
timestampPreciseFromDb,
timestampPreciseToDb,
} from "./db.js";
-import { fetchFreshExchange } from "./exchanges.js";
+import { fetchFreshExchange, getScopeForAllExchanges } from "./exchanges.js";
import {
codecForExchangePurseStatus,
getMergeReserveInfo,
@@ -194,6 +194,7 @@ export class PeerPullCreditTransactionContext implements
TransactionContext {
return {
type: TransactionType.PeerPullCredit,
txState,
+ scopes: await getScopeForAllExchanges(tx,
[pullCredit.exchangeBaseUrl]),
txActions: computePeerPullCreditTransactionActions(pullCredit),
amountEffective: isUnsuccessfulTransaction(txState)
? Amounts.stringify(Amounts.zeroOfAmount(wsr.instructedAmount))
@@ -228,6 +229,7 @@ export class PeerPullCreditTransactionContext implements
TransactionContext {
return {
type: TransactionType.PeerPullCredit,
txState,
+ scopes: await getScopeForAllExchanges(tx, [pullCredit.exchangeBaseUrl]),
txActions: computePeerPullCreditTransactionActions(pullCredit),
amountEffective: isUnsuccessfulTransaction(txState)
? Amounts.stringify(Amounts.zeroOfAmount(peerContractTerms.amount))
diff --git a/packages/taler-wallet-core/src/pay-peer-pull-debit.ts
b/packages/taler-wallet-core/src/pay-peer-pull-debit.ts
index dca228547..09ecbeb94 100644
--- a/packages/taler-wallet-core/src/pay-peer-pull-debit.ts
+++ b/packages/taler-wallet-core/src/pay-peer-pull-debit.ts
@@ -103,6 +103,7 @@ import {
parseTransactionIdentifier,
} from "./transactions.js";
import { WalletExecutionContext } from "./wallet.js";
+import { getScopeForAllExchanges } from "./exchanges.js";
const logger = new Logger("pay-peer-pull-debit.ts");
@@ -166,6 +167,7 @@ export class PeerPullDebitTransactionContext implements
TransactionContext {
return {
type: TransactionType.PeerPullDebit,
txState,
+ scopes: await getScopeForAllExchanges(tx, [pi.exchangeBaseUrl]),
txActions: computePeerPullDebitTransactionActions(pi),
amountEffective: isUnsuccessfulTransaction(txState)
? Amounts.stringify(Amounts.zeroOfAmount(pi.amount))
diff --git a/packages/taler-wallet-core/src/pay-peer-push-credit.ts
b/packages/taler-wallet-core/src/pay-peer-push-credit.ts
index 5199dbde4..830e2bd1b 100644
--- a/packages/taler-wallet-core/src/pay-peer-push-credit.ts
+++ b/packages/taler-wallet-core/src/pay-peer-push-credit.ts
@@ -79,7 +79,7 @@ import {
timestampPreciseFromDb,
timestampPreciseToDb,
} from "./db.js";
-import { fetchFreshExchange } from "./exchanges.js";
+import { fetchFreshExchange, getScopeForAllExchanges } from "./exchanges.js";
import {
codecForExchangePurseStatus,
getMergeReserveInfo,
@@ -183,6 +183,7 @@ export class PeerPushCreditTransactionContext implements
TransactionContext {
return {
type: TransactionType.PeerPushCredit,
txState,
+ scopes: await getScopeForAllExchanges(tx, [pushInc.exchangeBaseUrl]),
txActions: computePeerPushCreditTransactionActions(pushInc),
amountEffective: isUnsuccessfulTransaction(txState)
? Amounts.stringify(Amounts.zeroOfAmount(wg.instructedAmount))
@@ -207,6 +208,7 @@ export class PeerPushCreditTransactionContext implements
TransactionContext {
return {
type: TransactionType.PeerPushCredit,
txState,
+ scopes: await getScopeForAllExchanges(tx, [pushInc.exchangeBaseUrl]),
txActions: computePeerPushCreditTransactionActions(pushInc),
amountEffective: isUnsuccessfulTransaction(txState)
? Amounts.stringify(Amounts.zeroOfAmount(peerContractTerms.amount))
diff --git a/packages/taler-wallet-core/src/pay-peer-push-debit.ts
b/packages/taler-wallet-core/src/pay-peer-push-debit.ts
index b30ff334d..4485976b9 100644
--- a/packages/taler-wallet-core/src/pay-peer-push-debit.ts
+++ b/packages/taler-wallet-core/src/pay-peer-push-debit.ts
@@ -93,6 +93,7 @@ import {
notifyTransition,
} from "./transactions.js";
import { WalletExecutionContext } from "./wallet.js";
+import { getScopeForAllExchanges } from "./exchanges.js";
const logger = new Logger("pay-peer-push-debit.ts");
@@ -167,6 +168,7 @@ export class PeerPushDebitTransactionContext implements
TransactionContext {
return {
type: TransactionType.PeerPushDebit,
txState,
+ scopes: await getScopeForAllExchanges(tx,
[pushDebitRec.exchangeBaseUrl]),
txActions: computePeerPushDebitTransactionActions(pushDebitRec),
amountEffective: isUnsuccessfulTransaction(txState)
? Amounts.stringify(Amounts.zeroOfAmount(pushDebitRec.totalCost))
diff --git a/packages/taler-wallet-core/src/refresh.ts
b/packages/taler-wallet-core/src/refresh.ts
index a657ec445..b8bd3c0b7 100644
--- a/packages/taler-wallet-core/src/refresh.ts
+++ b/packages/taler-wallet-core/src/refresh.ts
@@ -122,6 +122,7 @@ import {
WalletExecutionContext,
} from "./wallet.js";
import { getCandidateWithdrawalDenomsTx } from "./withdraw.js";
+import { getScopeForAllExchanges } from "./exchanges.js";
const logger = new Logger("refresh.ts");
@@ -186,6 +187,7 @@ export class RefreshTransactionContext implements
TransactionContext {
return {
type: TransactionType.Refresh,
txState,
+ scopes: await getScopeForAllExchanges(tx,
!refreshGroupRecord.infoPerExchange? []:
Object.keys(refreshGroupRecord.infoPerExchange)),
txActions: computeRefreshTransactionActions(refreshGroupRecord),
refreshReason: refreshGroupRecord.reason,
amountEffective: isUnsuccessfulTransaction(txState)
diff --git a/packages/taler-wallet-core/src/withdraw.ts
b/packages/taler-wallet-core/src/withdraw.ts
index 09348baf7..406772d5f 100644
--- a/packages/taler-wallet-core/src/withdraw.ts
+++ b/packages/taler-wallet-core/src/withdraw.ts
@@ -160,6 +160,7 @@ import {
fetchFreshExchange,
getExchangePaytoUri,
getExchangeWireDetailsInTx,
+ getScopeForAllExchanges,
listExchanges,
lookupExchangeByUri,
markExchangeUsed,
@@ -182,6 +183,7 @@ const logger = new Logger("withdraw.ts");
function buildTransactionForBankIntegratedWithdraw(
wg: WithdrawalGroupRecord,
+ scopes: ScopeInfo[],
ort?: OperationRetryRecord,
): TransactionWithdrawal {
if (wg.wgInfo.withdrawalType !== WithdrawalRecordType.BankIntegrated) {
@@ -202,6 +204,7 @@ function buildTransactionForBankIntegratedWithdraw(
return {
type: TransactionType.Withdrawal,
txState,
+ scopes,
txActions: computeWithdrawalTransactionActions(wg),
exchangeBaseUrl: wg.exchangeBaseUrl,
amountEffective:
@@ -237,6 +240,7 @@ function buildTransactionForBankIntegratedWithdraw(
function buildTransactionForManualWithdraw(
wg: WithdrawalGroupRecord,
exchangeDetails: ExchangeWireDetails | undefined,
+ scopes: ScopeInfo[],
ort?: OperationRetryRecord,
): TransactionWithdrawal {
if (wg.wgInfo.withdrawalType !== WithdrawalRecordType.BankManual)
@@ -259,6 +263,7 @@ function buildTransactionForManualWithdraw(
return {
type: TransactionType.Withdrawal,
txState,
+ scopes,
txActions: computeWithdrawalTransactionActions(wg),
amountEffective: isUnsuccessfulTransaction(txState)
? Amounts.stringify(Amounts.zeroOfAmount(wg.instructedAmount))
@@ -318,6 +323,18 @@ export class WithdrawTransactionContext implements
TransactionContext {
if (!withdrawalGroupRecord) {
return undefined;
}
+ const exchangeDetails =
+ withdrawalGroupRecord.exchangeBaseUrl === undefined
+ ? undefined
+ : await getExchangeWireDetailsInTx(
+ tx,
+ withdrawalGroupRecord.exchangeBaseUrl,
+ );
+ const scopes = await getScopeForAllExchanges(
+ tx,
+ !exchangeDetails ? [] : [exchangeDetails.exchangeBaseUrl],
+ );
+
const ort = await tx.operationRetries.get(this.taskId);
if (
withdrawalGroupRecord.wgInfo.withdrawalType ===
@@ -325,16 +342,10 @@ export class WithdrawTransactionContext implements
TransactionContext {
) {
return buildTransactionForBankIntegratedWithdraw(
withdrawalGroupRecord,
+ scopes,
ort,
);
}
- const exchangeDetails =
- withdrawalGroupRecord.exchangeBaseUrl === undefined
- ? undefined
- : await getExchangeWireDetailsInTx(
- tx,
- withdrawalGroupRecord.exchangeBaseUrl,
- );
if (!exchangeDetails) {
logger.warn(
`transaction ${this.transactionId} is a manual withdrawal, but no
exchange wire details found`,
@@ -343,6 +354,7 @@ export class WithdrawTransactionContext implements
TransactionContext {
return buildTransactionForManualWithdraw(
withdrawalGroupRecord,
exchangeDetails,
+ scopes,
ort,
);
}
diff --git a/packages/taler-wallet-webextension/src/NavigationBar.tsx
b/packages/taler-wallet-webextension/src/NavigationBar.tsx
index fe348f7fb..d3a0ab37c 100644
--- a/packages/taler-wallet-webextension/src/NavigationBar.tsx
+++ b/packages/taler-wallet-webextension/src/NavigationBar.tsx
@@ -97,11 +97,11 @@ function pageDefinition<T extends object>(pattern: string):
PageLocation<T> {
export const Pages = {
welcome: "/welcome",
balance: "/balance",
- balanceHistory: pageDefinition<{ currency?: string }>(
- "/balance/history/:currency?",
+ balanceHistory: pageDefinition<{ scope?: string }>(
+ "/balance/history/:scope?",
),
- searchHistory: pageDefinition<{ currency?: string }>(
- "/search/history/:currency?",
+ searchHistory: pageDefinition<{ scope?: string }>(
+ "/search/history/:scope?",
),
balanceDeposit: pageDefinition<{ amount: string }>(
"/balance/deposit/:amount",
@@ -109,8 +109,8 @@ export const Pages = {
balanceTransaction: pageDefinition<{ tid: string }>(
"/balance/transaction/:tid",
),
- sendCash: pageDefinition<{ amount?: string }>("/destination/send/:amount"),
- receiveCash: pageDefinition<{ amount?: string
}>("/destination/get/:amount?"),
+ sendCash: pageDefinition<{ scope?: string }>("/destination/send/:scope"),
+ receiveCash: pageDefinition<{ scope?: string }>("/destination/get/:scope?"),
dev: "/dev",
exchanges: "/exchanges",
diff --git a/packages/taler-wallet-webextension/src/components/BalanceTable.tsx
b/packages/taler-wallet-webextension/src/components/BalanceTable.tsx
index 6dd577b88..a6ccc10ca 100644
--- a/packages/taler-wallet-webextension/src/components/BalanceTable.tsx
+++ b/packages/taler-wallet-webextension/src/components/BalanceTable.tsx
@@ -14,7 +14,7 @@
GNU Taler; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
*/
-import { Amounts, ScopeType, WalletBalance } from "@gnu-taler/taler-util";
+import { Amounts, ScopeInfo, ScopeType, WalletBalance } from
"@gnu-taler/taler-util";
import { Fragment, VNode, h } from "preact";
import {
TableWithRoundRows as TableWithRoundedRows
@@ -25,7 +25,7 @@ export function BalanceTable({
goToWalletHistory,
}: {
balances: WalletBalance[];
- goToWalletHistory: (currency: string) => void;
+ goToWalletHistory: (currency: ScopeInfo) => void;
}): VNode {
return (
<Fragment>
@@ -36,7 +36,7 @@ export function BalanceTable({
return (
<tr
key={idx}
- onClick={() => goToWalletHistory(av.currency)}
+ onClick={() => goToWalletHistory(entry.scopeInfo)}
style={{ cursor: "pointer" }}
>
<td>{av.currency}</td>
diff --git
a/packages/taler-wallet-webextension/src/components/MultiActionButton.tsx
b/packages/taler-wallet-webextension/src/components/MultiActionButton.tsx
index 7d3cf3f57..3f22e4849 100644
--- a/packages/taler-wallet-webextension/src/components/MultiActionButton.tsx
+++ b/packages/taler-wallet-webextension/src/components/MultiActionButton.tsx
@@ -20,10 +20,10 @@ import { Button } from "../mui/Button.js";
import arrowDown from "../svg/chevron-down.inline.svg";
import { ParagraphClickable } from "./styled/index.js";
-export interface Props {
- label: (s: string) => TranslatedString;
- actions: string[];
- onClick: (s: string) => Promise<void>;
+export interface Props<T> {
+ label: (s: T) => TranslatedString;
+ actions: T[];
+ onClick: (s: T) => Promise<void>;
}
/**
@@ -37,19 +37,19 @@ export interface Props {
*
* @returns
*/
-export function MultiActionButton({
+export function MultiActionButton<T>({
label,
actions,
onClick: doClick,
-}: Props): VNode {
- const defaultAction = actions.length > 0 ? actions[0] : "";
+}: Props<T>): VNode {
+ const defaultAction = actions.length > 0 ? actions[0] : "" as T;
const [opened, setOpened] = useState(false);
- const [selected, setSelected] = useState<string>(defaultAction);
+ const [selected, setSelected] = useState<T>(defaultAction);
const canChange = actions.length > 1;
const options = canChange ? actions.filter((a) => a !== selected) : [];
- function select(m: string): void {
+ function select(m: T): void {
setSelected(m);
setOpened(false);
}
diff --git a/packages/taler-wallet-webextension/src/popup/Application.tsx
b/packages/taler-wallet-webextension/src/popup/Application.tsx
index cbb9b50b2..8c732728e 100644
--- a/packages/taler-wallet-webextension/src/popup/Application.tsx
+++ b/packages/taler-wallet-webextension/src/popup/Application.tsx
@@ -20,21 +20,25 @@
* @author sebasjm
*/
+import {
+ ScopeInfo,
+ stringifyScopeInfoShort
+} from "@gnu-taler/taler-util";
import {
TranslationProvider,
useTranslationContext,
} from "@gnu-taler/web-util/browser";
import { createHashHistory } from "history";
-import { ComponentChildren, Fragment, h, VNode } from "preact";
-import { route, Route, Router } from "preact-router";
+import { ComponentChildren, Fragment, VNode, h } from "preact";
+import { Route, Router, route } from "preact-router";
import { useEffect, useState } from "preact/hooks";
+import { Pages, PopupNavBar, PopupNavBarOptions } from "../NavigationBar.js";
import PendingTransactions from "../components/PendingTransactions.js";
import { PopupBox } from "../components/styled/index.js";
import { AlertProvider } from "../context/alert.js";
import { IoCProviderForRuntime } from "../context/iocContext.js";
import { useTalerActionURL } from "../hooks/useTalerActionURL.js";
import { strings } from "../i18n/strings.js";
-import { Pages, PopupNavBar, PopupNavBarOptions } from "../NavigationBar.js";
import { platform } from "../platform/foreground.js";
import { BackupPage } from "../wallet/BackupPage.js";
import { ProviderDetailPage } from "../wallet/ProviderDetailPage.js";
@@ -68,7 +72,7 @@ function ApplicationView(): VNode {
}
function redirectToURL(str: string): void {
- platform.openNewURLFromPopup(new URL(str))
+ platform.openNewURLFromPopup(new URL(str));
}
return (
@@ -76,14 +80,26 @@ function ApplicationView(): VNode {
<Route
path={Pages.balance}
component={() => (
- <PopupTemplate path="balance" goToTransaction={redirectToTxInfo}
goToURL={redirectToURL}>
+ <PopupTemplate
+ path="balance"
+ goToTransaction={redirectToTxInfo}
+ goToURL={redirectToURL}
+ >
<BalancePage
goToWalletManualWithdraw={() =>
redirectTo(Pages.receiveCash({}))}
- goToWalletDeposit={(currency: string) =>
- redirectTo(Pages.sendCash({ amount: `${currency}:0` }))
+ goToWalletDeposit={(scope: ScopeInfo) =>
+ redirectTo(
+ Pages.sendCash({
+ scope: encodeURIComponent(stringifyScopeInfoShort(scope)),
+ }),
+ )
}
- goToWalletHistory={(currency: string) =>
- redirectTo(Pages.balanceHistory({ currency }))
+ goToWalletHistory={(scope: ScopeInfo) =>
+ redirectTo(
+ Pages.balanceHistory({
+ scope: encodeURIComponent(stringifyScopeInfoShort(scope)),
+ }),
+ )
}
/>
</PopupTemplate>
@@ -112,7 +128,11 @@ function ApplicationView(): VNode {
<Route
path={Pages.backup}
component={() => (
- <PopupTemplate path="backup" goToTransaction={redirectToTxInfo}
goToURL={redirectToURL}>
+ <PopupTemplate
+ path="backup"
+ goToTransaction={redirectToTxInfo}
+ goToURL={redirectToURL}
+ >
<BackupPage
onAddProvider={() => redirectTo(Pages.backupProviderAdd)}
/>
@@ -127,9 +147,9 @@ function ApplicationView(): VNode {
onPayProvider={(uri: string) =>
redirectTo(`${Pages.ctaPay}?talerPayUri=${uri}`)
}
- onWithdraw={(amount: string) =>
- redirectTo(Pages.receiveCash({ amount }))
- }
+ onWithdraw={async (_amount: string) => {
+ // redirectTo(Pages.receiveCash({ amount }))
+ }}
pid={pid}
onBack={() => redirectTo(Pages.backup)}
/>
@@ -219,7 +239,10 @@ function PopupTemplate({
}): VNode {
return (
<Fragment>
- <PendingTransactions goToTransaction={goToTransaction} goToURL={goToURL}
/>
+ <PendingTransactions
+ goToTransaction={goToTransaction}
+ goToURL={goToURL}
+ />
<PopupNavBar path={path} />
<PopupBox>
<AlertProvider>{children}</AlertProvider>
diff --git a/packages/taler-wallet-webextension/src/popup/BalancePage.tsx
b/packages/taler-wallet-webextension/src/popup/BalancePage.tsx
index 73bd8e96d..a819d50e7 100644
--- a/packages/taler-wallet-webextension/src/popup/BalancePage.tsx
+++ b/packages/taler-wallet-webextension/src/popup/BalancePage.tsx
@@ -17,6 +17,7 @@
import {
Amounts,
NotificationType,
+ ScopeInfo,
WalletBalance,
} from "@gnu-taler/taler-util";
import { WalletApiOperation } from "@gnu-taler/taler-wallet-core";
@@ -41,8 +42,8 @@ import { AddNewActionView } from
"../wallet/AddNewActionView.js";
import { NoBalanceHelp } from "./NoBalanceHelp.js";
export interface Props {
- goToWalletDeposit: (currency: string) => Promise<void>;
- goToWalletHistory: (currency: string) => Promise<void>;
+ goToWalletDeposit: (currency: ScopeInfo) => Promise<void>;
+ goToWalletHistory: (currency: ScopeInfo) => Promise<void>;
goToWalletManualWithdraw: () => Promise<void>;
}
@@ -70,8 +71,8 @@ export namespace State {
error: undefined;
balances: WalletBalance[];
addAction: ButtonHandler;
- goToWalletDeposit: (currency: string) => Promise<void>;
- goToWalletHistory: (currency: string) => Promise<void>;
+ goToWalletDeposit: (currency: ScopeInfo) => Promise<void>;
+ goToWalletHistory: (currency: ScopeInfo) => Promise<void>;
goToWalletManualWithdraw: ButtonHandler;
}
}
@@ -156,7 +157,7 @@ export function BalanceView(state: State.Balances): VNode {
.filter((b) => !Amounts.isZero(b.available))
.map((b) => {
b.flags
- return b.available.split(":")[0]
+ return b.scopeInfo
});
if (state.balances.length === 0) {
@@ -184,7 +185,7 @@ export function BalanceView(state: State.Balances): VNode {
</Button>
{currencyWithNonZeroAmount.length > 0 && (
<MultiActionButton
- label={(s) => i18n.str`Send ${s}`}
+ label={(s) => i18n.str`Send ${s.currency}`}
actions={currencyWithNonZeroAmount}
onClick={(c) => state.goToWalletDeposit(c)}
/>
diff --git a/packages/taler-wallet-webextension/src/wallet/Application.tsx
b/packages/taler-wallet-webextension/src/wallet/Application.tsx
index 893122c0f..4947eb7a9 100644
--- a/packages/taler-wallet-webextension/src/wallet/Application.tsx
+++ b/packages/taler-wallet-webextension/src/wallet/Application.tsx
@@ -22,10 +22,13 @@
import {
Amounts,
+ ScopeInfo,
TalerUri,
TalerUriAction,
TranslatedString,
+ parseScopeInfoShort,
parseTalerUri,
+ stringifyScopeInfoShort,
stringifyTalerUri,
} from "@gnu-taler/taler-util";
import {
@@ -96,7 +99,7 @@ export function Application(): VNode {
redirectTo(Pages.balanceTransaction({ tid }));
}
function redirectToURL(str: string): void {
- window.location.href = new URL(str).href
+ window.location.href = new URL(str).href;
}
return (
@@ -115,7 +118,10 @@ export function Application(): VNode {
<Route
path={Pages.qr}
component={() => (
- <WalletTemplate goToTransaction={redirectToTxInfo}
goToURL={redirectToURL}>
+ <WalletTemplate
+ goToTransaction={redirectToTxInfo}
+ goToURL={redirectToURL}
+ >
<QrReaderPage
onDetected={(talerActionUrl: TalerUri) => {
redirectTo(
@@ -132,7 +138,10 @@ export function Application(): VNode {
<Route
path={Pages.settings}
component={() => (
- <WalletTemplate goToTransaction={redirectToTxInfo}
goToURL={redirectToURL}>
+ <WalletTemplate
+ goToTransaction={redirectToTxInfo}
+ goToURL={redirectToURL}
+ >
<SettingsPage />
</WalletTemplate>
)}
@@ -159,17 +168,33 @@ export function Application(): VNode {
<Route
path={Pages.balanceHistory.pattern}
- component={({ currency }: { currency?: string }) => (
- <WalletTemplate path="balance"
goToTransaction={redirectToTxInfo} goToURL={redirectToURL}>
+ component={({ scope }: { scope?: string }) => (
+ <WalletTemplate
+ path="balance"
+ goToTransaction={redirectToTxInfo}
+ goToURL={redirectToURL}
+ >
<HistoryPage
- currency={currency}
- goToWalletDeposit={(currency: string) =>
- redirectTo(Pages.sendCash({ amount: `${currency}:0` }))
+ scope={
+ !scope
+ ? undefined
+ : parseScopeInfoShort((scope))
}
- goToWalletManualWithdraw={(currency?: string) =>
+ goToWalletDeposit={(scope: ScopeInfo) =>
+ redirectTo(
+ Pages.sendCash({
+ scope: encodeURIComponent(
+ stringifyScopeInfoShort(scope),
+ ),
+ }),
+ )
+ }
+ goToWalletManualWithdraw={(scope?: ScopeInfo) =>
redirectTo(
Pages.receiveCash({
- amount: !currency ? undefined : `${currency}:0`,
+ scope: !scope
+ ? undefined
+ : encodeURIComponent(stringifyScopeInfoShort(scope)),
}),
)
}
@@ -179,18 +204,34 @@ export function Application(): VNode {
/>
<Route
path={Pages.searchHistory.pattern}
- component={({ currency }: { currency?: string }) => (
- <WalletTemplate path="balance"
goToTransaction={redirectToTxInfo} goToURL={redirectToURL}>
+ component={({ scope }: { scope?: string }) => (
+ <WalletTemplate
+ path="balance"
+ goToTransaction={redirectToTxInfo}
+ goToURL={redirectToURL}
+ >
<HistoryPage
- currency={currency}
+ scope={
+ !scope
+ ? undefined
+ : parseScopeInfoShort((scope))
+ }
search
- goToWalletDeposit={(currency: string) =>
- redirectTo(Pages.sendCash({ amount: `${currency}:0` }))
+ goToWalletDeposit={(scope: ScopeInfo) =>
+ redirectTo(
+ Pages.sendCash({
+ scope: encodeURIComponent(
+ stringifyScopeInfoShort(scope),
+ ),
+ }),
+ )
}
- goToWalletManualWithdraw={(currency?: string) =>
+ goToWalletManualWithdraw={(scope?: ScopeInfo) =>
redirectTo(
Pages.receiveCash({
- amount: !currency ? undefined : `${currency}:0`,
+ scope: !scope
+ ? undefined
+ : encodeURIComponent(stringifyScopeInfoShort(scope)),
}),
)
}
@@ -239,8 +280,14 @@ export function Application(): VNode {
<WalletTemplate path="balance" goToURL={redirectToURL}>
<TransactionPage
tid={tid}
- goToWalletHistory={(currency?: string) =>
- redirectTo(Pages.balanceHistory({ currency }))
+ goToWalletHistory={(scope: ScopeInfo) =>
+ redirectTo(
+ Pages.balanceHistory({
+ scope: encodeURIComponent(
+ stringifyScopeInfoShort(scope),
+ ),
+ }),
+ )
}
/>
</WalletTemplate>
@@ -249,15 +296,22 @@ export function Application(): VNode {
<Route
path={Pages.balanceDeposit.pattern}
- component={({ amount }: { amount: string }) => (
+ component={({
+ scope,
+ amount,
+ }: {
+ scope: string;
+ amount?: string;
+ }) => (
<WalletTemplate path="balance" goToURL={redirectToURL}>
<DepositPage
- amount={amount}
- onCancel={(currency: string) => {
- redirectTo(Pages.balanceHistory({ currency }));
+ scope={parseScopeInfoShort((scope))}
+ amount={!amount ? undefined : Amounts.parse(amount)}
+ onCancel={(scope: ScopeInfo) => {
+ redirectTo(Pages.balanceHistory({ scope:
encodeURIComponent(stringifyScopeInfoShort(scope)) }));
}}
- onSuccess={(currency: string) => {
- redirectTo(Pages.balanceHistory({ currency }));
+ onSuccess={(scope: ScopeInfo) => {
+ redirectTo(Pages.balanceHistory({ scope:
encodeURIComponent(stringifyScopeInfoShort(scope)) }));
}}
/>
</WalletTemplate>
@@ -267,7 +321,11 @@ export function Application(): VNode {
<Route
path={Pages.backup}
component={() => (
- <WalletTemplate path="backup" goToTransaction={redirectToTxInfo}
goToURL={redirectToURL}>
+ <WalletTemplate
+ path="backup"
+ goToTransaction={redirectToTxInfo}
+ goToURL={redirectToURL}
+ >
<BackupPage
onAddProvider={() => redirectTo(Pages.backupProviderAdd)}
/>
@@ -283,8 +341,8 @@ export function Application(): VNode {
onPayProvider={(uri: string) =>
redirectTo(`${Pages.ctaPay}?talerPayUri=${uri}`)
}
- onWithdraw={(amount: string) =>
- redirectTo(Pages.receiveCash({ amount }))
+ onWithdraw={(_amount: string) =>
+ redirectTo(Pages.receiveCash({ scope: "FIXME missing" }))
}
onBack={() => redirectTo(Pages.backup)}
/>
@@ -314,7 +372,11 @@ export function Application(): VNode {
<Route
path={Pages.dev}
component={() => (
- <WalletTemplate path="dev" goToTransaction={redirectToTxInfo}
goToURL={redirectToURL}>
+ <WalletTemplate
+ path="dev"
+ goToTransaction={redirectToTxInfo}
+ goToURL={redirectToURL}
+ >
<DeveloperPage />
</WalletTemplate>
)}
@@ -349,8 +411,8 @@ export function Application(): VNode {
<CallToActionTemplate title={i18n.str`Digital cash payment`}>
<PaymentPage
talerPayUri={decodeURIComponent(talerUri)}
- goToWalletManualWithdraw={(amount?: string) =>
- redirectTo(Pages.receiveCash({ amount }))
+ goToWalletManualWithdraw={(_amount?: string) =>
+ redirectTo(Pages.receiveCash({ scope: "FIXME missing" }))
}
cancel={() => redirectTo(Pages.balance)}
onSuccess={(tid: string) =>
@@ -366,8 +428,8 @@ export function Application(): VNode {
<CallToActionTemplate title={i18n.str`Digital cash payment`}>
<PaymentTemplatePage
talerTemplateUri={decodeURIComponent(talerUri)}
- goToWalletManualWithdraw={(amount?: string) =>
- redirectTo(Pages.receiveCash({ amount }))
+ goToWalletManualWithdraw={(_amount?: string) =>
+ redirectTo(Pages.receiveCash({ scope: "FIXME missing" }))
}
cancel={() => redirectTo(Pages.balance)}
onSuccess={(tid: string) =>
@@ -417,7 +479,9 @@ export function Application(): VNode {
<CallToActionTemplate title={i18n.str`Digital cash withdrawal`}>
<WithdrawPageFromParams
onAmountChanged={async (newamount) => {
- const page = `${Pages.ctaWithdrawManual({ amount:
newamount })}?talerUri=${encodeURIComponent(talerUri)}`;
+ const page = `${Pages.ctaWithdrawManual({
+ amount: newamount,
+ })}?talerUri=${encodeURIComponent(talerUri)}`;
redirectTo(page);
}}
talerExchangeWithdrawUri={talerUri}
@@ -485,8 +549,8 @@ export function Application(): VNode {
<CallToActionTemplate title={i18n.str`Digital cash invoice`}>
<InvoicePayPage
talerPayPullUri={decodeURIComponent(talerUri)}
- goToWalletManualWithdraw={(amount?: string) =>
- redirectTo(Pages.receiveCash({ amount }))
+ goToWalletManualWithdraw={(_amount?: string) =>
+ redirectTo(Pages.receiveCash({ scope: "FIXME missing" }))
}
onClose={() => redirectTo(Pages.balance)}
onSuccess={(tid: string) =>
@@ -537,23 +601,26 @@ export function Application(): VNode {
<Route
path={Pages.ctaAddExchange}
component={({ talerUri }: { talerUri: string }) => {
- const tUri = parseTalerUri(decodeURIComponent(talerUri))
- const baseUrl = tUri?.type === TalerUriAction.AddExchange ?
tUri.exchangeBaseUrl : undefined
+ const tUri = parseTalerUri(decodeURIComponent(talerUri));
+ const baseUrl =
+ tUri?.type === TalerUriAction.AddExchange
+ ? tUri.exchangeBaseUrl
+ : undefined;
if (!baseUrl) {
- redirectTo(Pages.balanceHistory({}))
- return <div>
- invalid url {talerUri}
- </div>
+ redirectTo(Pages.balanceHistory({}));
+ return <div>invalid url {talerUri}</div>;
}
- return <CallToActionTemplate title={i18n.str`Add exchange`}>
- <ConfirmAddExchangeView
- url={baseUrl}
- status="confirm"
- error={undefined}
- onCancel={() => redirectTo(Pages.balanceHistory({}))}
- onConfirm={() => redirectTo(Pages.balanceHistory({}))}
- />
- </CallToActionTemplate>
+ return (
+ <CallToActionTemplate title={i18n.str`Add exchange`}>
+ <ConfirmAddExchangeView
+ url={baseUrl}
+ status="confirm"
+ error={undefined}
+ onCancel={() => redirectTo(Pages.balanceHistory({}))}
+ onConfirm={() => redirectTo(Pages.balanceHistory({}))}
+ />
+ </CallToActionTemplate>
+ );
}}
/>
{/**
@@ -665,7 +732,8 @@ function WalletTemplate({
<WalletNavBar path={path} />
<PendingTransactions
goToTransaction={goToTransaction}
- goToURL={goToURL} />
+ goToURL={goToURL}
+ />
<WalletBox>
<AlertProvider>
<CurrentAlerts />
diff --git a/packages/taler-wallet-webextension/src/wallet/DepositPage/index.ts
b/packages/taler-wallet-webextension/src/wallet/DepositPage/index.ts
index daba6aba4..11642861a 100644
--- a/packages/taler-wallet-webextension/src/wallet/DepositPage/index.ts
+++ b/packages/taler-wallet-webextension/src/wallet/DepositPage/index.ts
@@ -14,7 +14,7 @@
GNU Taler; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
*/
-import { AmountJson, PaytoUri } from "@gnu-taler/taler-util";
+import { AmountJson, PaytoUri, ScopeInfo } from "@gnu-taler/taler-util";
import { ErrorAlertView } from "../../components/CurrentAlerts.js";
import { Loading } from "../../components/Loading.js";
import { ErrorAlert } from "../../context/alert.js";
@@ -34,9 +34,10 @@ import {
} from "./views.js";
export interface Props {
- amount?: string;
- onCancel: (currency: string) => void;
- onSuccess: (currency: string) => void;
+ scope?:ScopeInfo;
+ amount?: AmountJson;
+ onCancel: (scope: ScopeInfo) => void;
+ onSuccess: (scope: ScopeInfo) => void;
}
export type State =
diff --git a/packages/taler-wallet-webextension/src/wallet/DepositPage/state.ts
b/packages/taler-wallet-webextension/src/wallet/DepositPage/state.ts
index b674665cf..f45c9ddd5 100644
--- a/packages/taler-wallet-webextension/src/wallet/DepositPage/state.ts
+++ b/packages/taler-wallet-webextension/src/wallet/DepositPage/state.ts
@@ -32,14 +32,15 @@ import { RecursiveState } from "../../utils/index.js";
import { Props, State } from "./index.js";
export function useComponentState({
- amount: amountStr,
+ amount,
+ scope,
onCancel,
onSuccess,
}: Props): RecursiveState<State> {
const api = useBackendContext();
const { i18n } = useTranslationContext();
const { pushAlertOnError } = useAlertContext();
- const parsed = amountStr === undefined ? undefined :
Amounts.parse(amountStr);
+ const parsed = amount;
const currency = parsed !== undefined ? parsed.currency : undefined;
const hook = useAsyncAsHook(async () => {
@@ -214,7 +215,7 @@ export function useComponentState({
amount: amountStr,
depositPaytoUri,
});
- onSuccess(currency);
+ onSuccess(scope!);
}
return {
@@ -250,7 +251,7 @@ export function useComponentState({
currentAccount,
cancelHandler: {
onClick: pushAlertOnError(async () => {
- onCancel(currency);
+ onCancel(scope!);
}),
},
depositHandler: {
diff --git a/packages/taler-wallet-webextension/src/wallet/DepositPage/test.ts
b/packages/taler-wallet-webextension/src/wallet/DepositPage/test.ts
index 1144095e1..7f22ea0ed 100644
--- a/packages/taler-wallet-webextension/src/wallet/DepositPage/test.ts
+++ b/packages/taler-wallet-webextension/src/wallet/DepositPage/test.ts
@@ -24,6 +24,7 @@ import {
Amounts,
AmountString,
parsePaytoUri,
+ ScopeInfo,
ScopeType,
stringifyPaytoUri
} from "@gnu-taler/taler-util";
@@ -36,21 +37,26 @@ import { createWalletApiMock } from "../../test-utils.js";
import { useComponentState } from "./state.js";
const currency = "EUR";
-const amount = `${currency}:0`;
+const amount = Amounts.parseOrThrow(`${currency}:0`);
const withoutFee = (value: number): AmountResponse => ({
effectiveAmount: `${currency}:${value}` as AmountString,
rawAmount: `${currency}:${value}` as AmountString,
});
+const defaultScope: ScopeInfo = {
+ type: ScopeType.Global,
+ currency
+}
+
+
const withSomeFee = (value: number, fee: number): AmountResponse => ({
effectiveAmount: `${currency}:${value}` as AmountString,
rawAmount: `${currency}:${value - fee}` as AmountString,
});
-
describe("DepositPage states", () => {
it("should have status 'no-enough-balance' when balance is empty", async ()
=> {
const { handler, TestingContext } = createWalletApiMock();
- const props = { amount, onCancel: nullFunction, onSuccess: nullFunction };
+ const props = { scope: defaultScope, amount, onCancel: nullFunction,
onSuccess: nullFunction };
handler.addWalletCallResponse(WalletApiOperation.GetBalances, undefined, {
balances: [
diff --git a/packages/taler-wallet-webextension/src/wallet/History.stories.tsx
b/packages/taler-wallet-webextension/src/wallet/History.stories.tsx
index dda10d561..470ad0514 100644
--- a/packages/taler-wallet-webextension/src/wallet/History.stories.tsx
+++ b/packages/taler-wallet-webextension/src/wallet/History.stories.tsx
@@ -169,7 +169,12 @@ export const SomeBalanceWithNoTransactions =
tests.createExample(
transactionsByDate: {
"11/11/11": [],
},
- balances: [
+ scope: {
+ currency: "Ásd",
+ type: ScopeType.Auditor,
+ url: "",
+ },
+ balances: [
{
available: "TESTKUDOS:10" as AmountString,
flags: [],
@@ -184,7 +189,7 @@ export const SomeBalanceWithNoTransactions =
tests.createExample(
},
},
],
- balanceIndex: 0,
+
},
);
@@ -192,6 +197,11 @@ export const OneSimpleTransaction =
tests.createExample(TestedComponent, {
transactionsByDate: {
"11/11/11": [exampleData.withdraw],
},
+ scope: {
+ currency: "Ásd",
+ type: ScopeType.Auditor,
+ url: "",
+ },
balances: [
{
flags: [],
@@ -207,7 +217,7 @@ export const OneSimpleTransaction =
tests.createExample(TestedComponent, {
},
},
],
- balanceIndex: 0,
+
});
export const TwoTransactionsAndZeroBalance = tests.createExample(
@@ -216,7 +226,12 @@ export const TwoTransactionsAndZeroBalance =
tests.createExample(
transactionsByDate: {
"11/11/11": [exampleData.withdraw, exampleData.deposit],
},
- balances: [
+ scope: {
+ currency: "Ásd",
+ type: ScopeType.Auditor,
+ url: "",
+ },
+ balances: [
{
flags: [],
available: "USD:0" as AmountString,
@@ -231,7 +246,7 @@ export const TwoTransactionsAndZeroBalance =
tests.createExample(
},
},
],
- balanceIndex: 0,
+
},
);
@@ -246,6 +261,11 @@ export const OneTransactionPending =
tests.createExample(TestedComponent, {
},
],
},
+ scope: {
+ currency: "Ásd",
+ type: ScopeType.Auditor,
+ url: "",
+ },
balances: [
{
flags: [],
@@ -261,7 +281,7 @@ export const OneTransactionPending =
tests.createExample(TestedComponent, {
},
},
],
- balanceIndex: 0,
+
});
export const SomeTransactions = tests.createExample(TestedComponent, {
@@ -283,6 +303,11 @@ export const SomeTransactions =
tests.createExample(TestedComponent, {
exampleData.deposit,
],
},
+ scope: {
+ currency: "Ásd",
+ type: ScopeType.Auditor,
+ url: "",
+ },
balances: [
{
flags: [],
@@ -298,7 +323,7 @@ export const SomeTransactions =
tests.createExample(TestedComponent, {
},
},
],
- balanceIndex: 0,
+
});
export const SomeTransactionsInDifferentStates = tests.createExample(
@@ -379,7 +404,12 @@ export const SomeTransactionsInDifferentStates =
tests.createExample(
exampleData.deposit,
],
},
- balances: [
+ scope: {
+ currency: "Ásd",
+ type: ScopeType.Auditor,
+ url: "",
+ },
+ balances: [
{
flags: [],
available: "USD:10" as AmountString,
@@ -394,7 +424,7 @@ export const SomeTransactionsInDifferentStates =
tests.createExample(
},
},
],
- balanceIndex: 0,
+
},
);
@@ -412,7 +442,12 @@ export const SomeTransactionsWithTwoCurrencies =
tests.createExample(
exampleData.deposit,
],
},
- balances: [
+ scope: {
+ currency: "Ásd",
+ type: ScopeType.Auditor,
+ url: "",
+ },
+ balances: [
{
flags: [],
available: "USD:0" as AmountString,
@@ -440,7 +475,7 @@ export const SomeTransactionsWithTwoCurrencies =
tests.createExample(
},
},
],
- balanceIndex: 0,
+
},
);
@@ -448,6 +483,11 @@ export const FiveOfficialCurrencies =
tests.createExample(TestedComponent, {
transactionsByDate: {
"11/11/11": [exampleData.withdraw],
},
+ scope: {
+ currency: "Ásd",
+ type: ScopeType.Auditor,
+ url: "",
+ },
balances: [
{
flags: [],
@@ -515,7 +555,7 @@ export const FiveOfficialCurrencies =
tests.createExample(TestedComponent, {
},
},
],
- balanceIndex: 0,
+
});
export const FiveOfficialCurrenciesWithHighValue = tests.createExample(
@@ -524,7 +564,12 @@ export const FiveOfficialCurrenciesWithHighValue =
tests.createExample(
transactionsByDate: {
"11/11/11": [exampleData.withdraw],
},
- balances: [
+ scope: {
+ currency: "Ásd",
+ type: ScopeType.Auditor,
+ url: "",
+ },
+ balances: [
{
flags: [],
available: "USD:881001321230000" as AmountString,
@@ -591,7 +636,7 @@ export const FiveOfficialCurrenciesWithHighValue =
tests.createExample(
},
},
],
- balanceIndex: 0,
+
},
);
@@ -604,6 +649,11 @@ export const PeerToPeer =
tests.createExample(TestedComponent, {
exampleData.push_debit,
],
},
+ scope: {
+ currency: "Ásd",
+ type: ScopeType.Auditor,
+ url: "",
+ },
balances: [
{
flags: [],
@@ -619,5 +669,4 @@ export const PeerToPeer =
tests.createExample(TestedComponent, {
},
},
],
- balanceIndex: 0,
});
diff --git a/packages/taler-wallet-webextension/src/wallet/History.tsx
b/packages/taler-wallet-webextension/src/wallet/History.tsx
index f81e6db9f..59315d61f 100644
--- a/packages/taler-wallet-webextension/src/wallet/History.tsx
+++ b/packages/taler-wallet-webextension/src/wallet/History.tsx
@@ -18,9 +18,11 @@ import {
AbsoluteTime,
Amounts,
NotificationType,
+ ScopeInfo,
ScopeType,
Transaction,
WalletBalance,
+ stringifyScopeInfoShort,
} from "@gnu-taler/taler-util";
import { WalletApiOperation } from "@gnu-taler/taler-wallet-core";
import { useTranslationContext } from "@gnu-taler/web-util/browser";
@@ -49,35 +51,36 @@ import { TextField } from "../mui/TextField.js";
import { TextFieldHandler } from "../mui/handlers.js";
interface Props {
- currency?: string;
+ scope?: ScopeInfo;
search?: boolean;
- goToWalletDeposit: (currency: string) => Promise<void>;
- goToWalletManualWithdraw: (currency?: string) => Promise<void>;
+ goToWalletDeposit: (scope: ScopeInfo) => Promise<void>;
+ goToWalletManualWithdraw: (scope?: ScopeInfo) => Promise<void>;
}
export function HistoryPage({
- currency: _c,
+ scope,
search: showSearch,
goToWalletManualWithdraw,
goToWalletDeposit,
}: Props): VNode {
const { i18n } = useTranslationContext();
const api = useBackendContext();
- const [balanceIndex, setBalanceIndex] = useState<number>(0);
+ const [selectedScope, setSelectedScope] = useState(scope);
const [search, setSearch] = useState<string>();
const [settings] = useSettings();
const state = useAsyncAsHook(async () => {
const b = await api.wallet.call(WalletApiOperation.GetBalances, {});
- const balance =
- b.balances.length > 0 ? b.balances[balanceIndex] : undefined;
+ const balances = b.balances;
+ // const balance =
+ // b.balances.length > 0 ? b.balances[balanceIndex] : undefined;
const tx = await api.wallet.call(WalletApiOperation.GetTransactions, {
- scopeInfo: showSearch ? undefined : balance?.scopeInfo,
+ scopeInfo: showSearch ? undefined : selectedScope,
sort: "descending",
includeRefreshes: settings.showRefeshTransactions,
search,
});
- return { b, tx };
- }, [balanceIndex, search]);
+ return { balances, transactions: tx.transactions };
+ }, [selectedScope, search]);
useEffect(() => {
return api.listener.onUpdateNotification(
@@ -103,7 +106,7 @@ export function HistoryPage({
);
}
- if (!state.response.b.balances.length) {
+ if (!state.response.balances.length) {
return (
<NoBalanceHelp
goToWalletManualWithdraw={{
@@ -113,7 +116,7 @@ export function HistoryPage({
);
}
- const byDate = state.response.tx.transactions.reduce(
+ const txsByDate = state.response.transactions.reduce(
(rv, x) => {
const startDay =
x.timestamp.t_s === "never"
@@ -141,41 +144,48 @@ export function HistoryPage({
setSearch(d);
}),
}}
- transactionsByDate={byDate}
+ transactionsByDate={txsByDate}
/>
);
}
return (
<HistoryView
- balanceIndex={balanceIndex}
- changeBalanceIndex={(b) => setBalanceIndex(b)}
- balances={state.response.b.balances}
+ scope={selectedScope ?? state.response.balances[0].scopeInfo}
+ changeScope={(b) => setSelectedScope(b)}
+ balances={state.response.balances}
goToWalletManualWithdraw={goToWalletManualWithdraw}
goToWalletDeposit={goToWalletDeposit}
- transactionsByDate={byDate}
+ transactionsByDate={txsByDate}
/>
);
}
export function HistoryView({
balances,
- balanceIndex,
- changeBalanceIndex,
+ scope,
+ changeScope,
transactionsByDate,
goToWalletManualWithdraw,
goToWalletDeposit,
}: {
- balanceIndex: number;
- changeBalanceIndex: (s: number) => void;
- goToWalletDeposit: (currency: string) => Promise<void>;
- goToWalletManualWithdraw: (currency?: string) => Promise<void>;
+ scope: ScopeInfo;
+ changeScope: (scope: ScopeInfo) => void;
+ goToWalletDeposit: (scope: ScopeInfo) => Promise<void>;
+ goToWalletManualWithdraw: (scope?: ScopeInfo) => Promise<void>;
transactionsByDate: Record<string, Transaction[]>;
balances: WalletBalance[];
}): VNode {
const { i18n } = useTranslationContext();
+ const scopeStr = stringifyScopeInfoShort(scope);
+ const balanceIndex = balances.findIndex(
+ (b) => stringifyScopeInfoShort(b.scopeInfo) === scopeStr,
+ );
const balance = balances[balanceIndex];
+ if (!balance) {
+ return <div>unkown scope</div>;
+ }
const available = balance
? Amounts.jsonifyAmount(balance.available)
@@ -200,9 +210,7 @@ export function HistoryView({
tooltip="Transfer money to the wallet"
startIcon={DownloadIcon}
variant="contained"
- onClick={() =>
- goToWalletManualWithdraw(balance.scopeInfo.currency)
- }
+ onClick={() => goToWalletManualWithdraw(balance.scopeInfo)}
>
<i18n.Translate>Receive</i18n.Translate>
</Button>
@@ -212,7 +220,7 @@ export function HistoryView({
startIcon={UploadIcon}
variant="outlined"
color="primary"
- onClick={() => goToWalletDeposit(balance.scopeInfo.currency)}
+ onClick={() => goToWalletDeposit(balance.scopeInfo)}
>
<i18n.Translate>Send</i18n.Translate>
</Button>
@@ -238,9 +246,8 @@ export function HistoryView({
}}
value={balanceIndex}
onChange={(e) => {
- changeBalanceIndex(
- Number.parseInt(e.currentTarget.value, 10),
- );
+ const bIdx = Number.parseInt(e.currentTarget.value, 10);
+ changeScope(balances[bIdx].scopeInfo);
}}
>
{balances.map((entry, index) => {
diff --git
a/packages/taler-wallet-webextension/src/wallet/Transaction.stories.tsx
b/packages/taler-wallet-webextension/src/wallet/Transaction.stories.tsx
index 5e096bf97..e45bfc1b1 100644
--- a/packages/taler-wallet-webextension/src/wallet/Transaction.stories.tsx
+++ b/packages/taler-wallet-webextension/src/wallet/Transaction.stories.tsx
@@ -61,6 +61,7 @@ export default {
const commonTransaction: TransactionCommon = {
error: undefined,
amountRaw: "KUDOS:11" as AmountString,
+ scopes: [],
amountEffective: "KUDOS:9.2" as AmountString,
txState: {
major: TransactionMajorState.Done,
diff --git a/packages/taler-wallet-webextension/src/wallet/Transaction.tsx
b/packages/taler-wallet-webextension/src/wallet/Transaction.tsx
index 339ded173..3bd6a9fba 100644
--- a/packages/taler-wallet-webextension/src/wallet/Transaction.tsx
+++ b/packages/taler-wallet-webextension/src/wallet/Transaction.tsx
@@ -25,6 +25,8 @@ import {
OrderShortInfo,
parsePaytoUri,
PaytoUri,
+ ScopeInfo,
+ ScopeType,
stringifyPaytoUri,
TalerErrorCode,
TalerPreciseTimestamp,
@@ -78,7 +80,7 @@ import { assertUnreachable } from "../utils/index.js";
interface Props {
tid: string;
- goToWalletHistory: (currency?: string) => Promise<void>;
+ goToWalletHistory: (scope: ScopeInfo) => Promise<void>;
}
export function TransactionPage({ tid, goToWalletHistory }: Props): VNode {
@@ -116,7 +118,11 @@ export function TransactionPage({ tid, goToWalletHistory
}: Props): VNode {
);
}
- const currency = Amounts.parse(state.response.amountRaw)?.currency;
+ const currency = Amounts.parse(state.response.amountEffective)!.currency;
+ const txScope = !state.response.scopes.length ? {
+ type: ScopeType.Global as const,
+ currency,
+ } : state.response.scopes[0]
return (
<TransactionView
@@ -125,44 +131,44 @@ export function TransactionPage({ tid, goToWalletHistory
}: Props): VNode {
await api.wallet.call(WalletApiOperation.FailTransaction, {
transactionId,
});
- goToWalletHistory(currency);
+ // goToWalletHistory(txScope);
}}
onSuspend={async () => {
await api.wallet.call(WalletApiOperation.SuspendTransaction, {
transactionId,
});
- goToWalletHistory(currency);
+ // goToWalletHistory(txScope);
}}
onResume={async () => {
await api.wallet.call(WalletApiOperation.ResumeTransaction, {
transactionId,
});
- goToWalletHistory(currency);
+ // goToWalletHistory(txScope);
}}
onAbort={async () => {
await api.wallet.call(WalletApiOperation.AbortTransaction, {
transactionId,
});
- goToWalletHistory(currency);
+ // goToWalletHistory(txScope);
}}
onRetry={async () => {
await api.wallet.call(WalletApiOperation.RetryTransaction, {
transactionId,
});
- goToWalletHistory(currency);
+ // goToWalletHistory(txScope);
}}
onDelete={async () => {
await api.wallet.call(WalletApiOperation.DeleteTransaction, {
transactionId,
});
- goToWalletHistory(currency);
+ goToWalletHistory(txScope);
}}
onRefund={async (transactionId) => {
await api.wallet.call(WalletApiOperation.StartRefundQuery, {
transactionId,
});
}}
- onBack={() => goToWalletHistory(currency)}
+ onBack={() => goToWalletHistory(txScope)}
/>
);
}
--
To stop receiving notification emails like this one, please contact
gnunet@gnunet.org.
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [taler-wallet-core] branch master updated: scope info in tx details,
gnunet <=