commit bcc6f2b106699145a0f75f44b27a0e49adcbb57a
parent 0e198ee7e361ec7cdee0c0996d2224c744dbbb14
Author: Florian Dold <dold@taler.net>
Date: Tue, 28 Jul 2026 16:11:42 +0200
wallet: don't materialize recoup groups as transactions
A recoup group got a transaction-meta record but has no transaction context,
so a single revocation made getTransactions throw for the whole wallet.
Diffstat:
1 file changed, 17 insertions(+), 17 deletions(-)
diff --git a/packages/taler-wallet-core/src/recoup.ts b/packages/taler-wallet-core/src/recoup.ts
@@ -279,6 +279,12 @@ export async function processRecoupGroup(
}
let recoupGroup = await wex.runWalletDbTx(async (tx) => {
+ // Drops a meta record left behind by an older wallet version, which would
+ // otherwise keep breaking getTransactions until the next DB migration.
+ await new RecoupTransactionContext(
+ wex,
+ recoupGroupId,
+ ).updateTransactionMeta(tx);
return tx.getRecoupGroup(recoupGroupId);
});
if (!recoupGroup) {
@@ -410,24 +416,18 @@ export class RecoupTransactionContext implements TransactionContext {
});
}
+ /**
+ * A recoup group is not a materialized transaction yet: lookupFullTransaction
+ * below, getContextForTransaction, rematerializeTransactions and the
+ * shepherd's retry notifications all leave recoup out. Writing a meta record
+ * anyway would put an entry in the transaction list that nothing can render,
+ * and getTransactions would then fail for the *whole* wallet.
+ *
+ * So only ever remove the record here. That also repairs wallets that
+ * already stored one before this was fixed.
+ */
async updateTransactionMeta(tx: WalletDbTransaction): Promise<void> {
- const recoupRec = await tx.getRecoupGroup(this.recoupGroupId);
- if (!recoupRec) {
- await tx.deleteTransactionMeta(this.transactionId);
- return;
- }
- const exch = await tx.getExchange(recoupRec.exchangeBaseUrl);
- if (!exch || !exch.detailsPointer) {
- await tx.deleteTransactionMeta(this.transactionId);
- return;
- }
- await tx.upsertTransactionMeta({
- transactionId: this.transactionId,
- status: recoupRec.operationStatus,
- timestamp: recoupRec.timestampStarted,
- currency: exch.detailsPointer?.currency,
- exchanges: [recoupRec.exchangeBaseUrl],
- });
+ await tx.deleteTransactionMeta(this.transactionId);
}
userAbortTransaction(): Promise<void> {