summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFlorian Dold <florian@dold.me>2024-03-31 17:08:29 +0200
committerFlorian Dold <florian@dold.me>2024-03-31 17:08:29 +0200
commit863e468df9d70c3d7268e96378c03b1cf7333f88 (patch)
tree384c4d8b75bd9f60f77bd792845dac3a46b7e847
parentc0146d7e7c209159930d695ccc740570173fbc43 (diff)
downloadwallet-core-863e468df9d70c3d7268e96378c03b1cf7333f88.tar.gz
wallet-core-863e468df9d70c3d7268e96378c03b1cf7333f88.tar.bz2
wallet-core-863e468df9d70c3d7268e96378c03b1cf7333f88.zip
wallet-core: denom loss notifications
-rw-r--r--packages/taler-wallet-core/src/exchanges.ts120
1 files changed, 98 insertions, 22 deletions
diff --git a/packages/taler-wallet-core/src/exchanges.ts b/packages/taler-wallet-core/src/exchanges.ts
index 2680ede78..48d8d4972 100644
--- a/packages/taler-wallet-core/src/exchanges.ts
+++ b/packages/taler-wallet-core/src/exchanges.ts
@@ -137,7 +137,10 @@ import {
import { DbReadOnlyTransaction } from "./query.js";
import { createRecoupGroup } from "./recoup.js";
import { createRefreshGroup } from "./refresh.js";
-import { constructTransactionIdentifier } from "./transactions.js";
+import {
+ constructTransactionIdentifier,
+ notifyTransition,
+} from "./transactions.js";
import { WALLET_EXCHANGE_PROTOCOL_VERSION } from "./versions.js";
import { InternalWalletState, WalletExecutionContext } from "./wallet.js";
@@ -1419,8 +1422,6 @@ export async function updateExchangeFromUrlHandler(
let noFees = checkNoFees(keysInfo);
let peerPaymentsDisabled = checkPeerPaymentsDisabled(keysInfo);
- let denomLossResult: boolean = false;
-
const updated = await wex.db.runReadWriteTx(
[
"exchanges",
@@ -1565,7 +1566,7 @@ export async function updateExchangeFromUrlHandler(
logger.trace("done updating denominations in database");
- denomLossResult = await handleDenomLoss(
+ const denomLossResult = await handleDenomLoss(
wex,
tx,
newDetails.currency,
@@ -1581,6 +1582,7 @@ export async function updateExchangeFromUrlHandler(
exchangeDetails: newDetails,
oldExchangeState,
newExchangeState,
+ denomLossResult,
};
},
);
@@ -1589,11 +1591,10 @@ export async function updateExchangeFromUrlHandler(
throw Error("something went wrong with updating the exchange");
}
- if (denomLossResult) {
- wex.ws.notify({
- type: NotificationType.BalanceChange,
- hintTransactionId: "denom-loss:*",
- });
+ if (updated.denomLossResult) {
+ for (const notif of updated.denomLossResult.notifications) {
+ wex.ws.notify(notif);
+ }
}
logger.trace("done updating exchange info in database");
@@ -1689,6 +1690,10 @@ export async function updateExchangeFromUrlHandler(
return TaskRunResult.progress();
}
+interface DenomLossResult {
+ notifications: WalletNotification[];
+}
+
async function handleDenomLoss(
wex: WalletExecutionContext,
tx: WalletDbReadWriteTransaction<
@@ -1696,7 +1701,7 @@ async function handleDenomLoss(
>,
currency: string,
exchangeBaseUrl: string,
-): Promise<boolean> {
+): Promise<DenomLossResult> {
const coinAvailabilityRecs =
await tx.coinAvailability.indexes.byExchangeBaseUrl.getAll(exchangeBaseUrl);
const denomsVanished: string[] = [];
@@ -1706,6 +1711,10 @@ async function handleDenomLoss(
let amountExpired = Amount.zeroOfCurrency(currency);
let amountUnoffered = Amount.zeroOfCurrency(currency);
+ const result: DenomLossResult = {
+ notifications: [],
+ };
+
for (const coinAv of coinAvailabilityRecs) {
if (coinAv.freshCoinCount <= 0) {
continue;
@@ -1746,12 +1755,11 @@ async function handleDenomLoss(
continue;
}
}
- let hadLoss = false;
if (denomsVanished.length > 0) {
- hadLoss = true;
+ const denomLossEventId = encodeCrock(getRandomBytes(32));
await tx.denomLossEvents.add({
- denomLossEventId: encodeCrock(getRandomBytes(32)),
+ denomLossEventId,
amount: amountVanished.toString(),
currency,
exchangeBaseUrl,
@@ -1760,12 +1768,30 @@ async function handleDenomLoss(
status: DenomLossStatus.Done,
timestampCreated: timestampPreciseToDb(TalerPreciseTimestamp.now()),
});
+ const transactionId = constructTransactionIdentifier({
+ tag: TransactionType.DenomLoss,
+ denomLossEventId,
+ });
+ result.notifications.push({
+ type: NotificationType.TransactionStateTransition,
+ transactionId,
+ oldTxState: {
+ major: TransactionMajorState.None,
+ },
+ newTxState: {
+ major: TransactionMajorState.Done,
+ },
+ });
+ result.notifications.push({
+ type: NotificationType.BalanceChange,
+ hintTransactionId: transactionId,
+ });
}
if (denomsUnoffered.length > 0) {
- hadLoss = true;
+ const denomLossEventId = encodeCrock(getRandomBytes(32));
await tx.denomLossEvents.add({
- denomLossEventId: encodeCrock(getRandomBytes(32)),
+ denomLossEventId,
amount: amountUnoffered.toString(),
currency,
exchangeBaseUrl,
@@ -1774,12 +1800,30 @@ async function handleDenomLoss(
status: DenomLossStatus.Done,
timestampCreated: timestampPreciseToDb(TalerPreciseTimestamp.now()),
});
+ const transactionId = constructTransactionIdentifier({
+ tag: TransactionType.DenomLoss,
+ denomLossEventId,
+ });
+ result.notifications.push({
+ type: NotificationType.TransactionStateTransition,
+ transactionId,
+ oldTxState: {
+ major: TransactionMajorState.None,
+ },
+ newTxState: {
+ major: TransactionMajorState.Done,
+ },
+ });
+ result.notifications.push({
+ type: NotificationType.BalanceChange,
+ hintTransactionId: transactionId,
+ });
}
if (denomsExpired.length > 0) {
- hadLoss = true;
+ const denomLossEventId = encodeCrock(getRandomBytes(32));
await tx.denomLossEvents.add({
- denomLossEventId: encodeCrock(getRandomBytes(32)),
+ denomLossEventId,
amount: amountExpired.toString(),
currency,
exchangeBaseUrl,
@@ -1788,9 +1832,27 @@ async function handleDenomLoss(
status: DenomLossStatus.Done,
timestampCreated: timestampPreciseToDb(TalerPreciseTimestamp.now()),
});
+ const transactionId = constructTransactionIdentifier({
+ tag: TransactionType.DenomLoss,
+ denomLossEventId,
+ });
+ result.notifications.push({
+ type: NotificationType.TransactionStateTransition,
+ transactionId,
+ oldTxState: {
+ major: TransactionMajorState.None,
+ },
+ newTxState: {
+ major: TransactionMajorState.Done,
+ },
+ });
+ result.notifications.push({
+ type: NotificationType.BalanceChange,
+ hintTransactionId: transactionId,
+ });
}
- return hadLoss;
+ return result;
}
export function computeDenomLossTransactionStatus(
@@ -1827,10 +1889,24 @@ export class DenomLossTransactionContext implements TransactionContext {
throw new Error("Method not implemented.");
}
async deleteTransaction(): Promise<void> {
- await this.wex.db.runReadWriteTx(["denomLossEvents"], async (tx) => {
- await tx.denomLossEvents.delete(this.denomLossEventId);
- });
- throw new Error("Method not implemented.");
+ const transitionInfo = await this.wex.db.runReadWriteTx(
+ ["denomLossEvents"],
+ async (tx) => {
+ const rec = await tx.denomLossEvents.get(this.denomLossEventId);
+ if (rec) {
+ const oldTxState = computeDenomLossTransactionStatus(rec);
+ await tx.denomLossEvents.delete(this.denomLossEventId);
+ return {
+ oldTxState,
+ newTxState: {
+ major: TransactionMajorState.Deleted,
+ },
+ };
+ }
+ return undefined;
+ },
+ );
+ notifyTransition(this.wex, this.transactionId, transitionInfo);
}
constructor(