commit 08dbab158e9e38cfc3fb95125cbcb24f28512955
parent b9755dd70ae0f0cffe41197fca05ee3794ad3e17
Author: Florian Dold <florian@dold.me>
Date: Thu, 19 Mar 2026 22:42:16 +0100
wallet-core: handle EXCHANGE_RESERVES_PURSE_EXPIRATION_BEFORE_NOW in peer-pull-credit
Diffstat:
2 files changed, 20 insertions(+), 6 deletions(-)
diff --git a/packages/taler-util/src/http-client/exchange-client.ts b/packages/taler-util/src/http-client/exchange-client.ts
@@ -20,6 +20,7 @@ import {
HttpRequestOptions,
HttpResponse,
readSuccessResponseJsonOrThrow,
+ readTalerErrorResponse,
} from "../http-common.js";
import { HttpStatusCode } from "../http-status-codes.js";
import { createPlatformHttpLib } from "../http.js";
@@ -118,7 +119,9 @@ import {
Logger,
LongpollQueue,
PaytoHash,
+ TalerErrorCode,
opKnownFailureWithBody,
+ opKnownTalerFailure,
signAmlDecision,
signAmlQuery,
} from "../index.js";
@@ -443,6 +446,7 @@ export class TalerExchangeHttpClient {
| OperationFail<HttpStatusCode.PaymentRequired>
| OperationFail<HttpStatusCode.Forbidden>
| OperationFail<HttpStatusCode.NotFound>
+ | OperationFail<TalerErrorCode.EXCHANGE_RESERVES_PURSE_EXPIRATION_BEFORE_NOW>
| OperationAlternative<HttpStatusCode.Conflict, PurseConflictPartial>
| OperationAlternative<
HttpStatusCode.UnavailableForLegalReasons,
@@ -473,6 +477,15 @@ export class TalerExchangeHttpClient {
resp.status,
codecForLegitimizationNeededResponse(),
);
+ case HttpStatusCode.BadRequest: {
+ const details = await readTalerErrorResponse(resp);
+ switch (details.code) {
+ case TalerErrorCode.EXCHANGE_RESERVES_PURSE_EXPIRATION_BEFORE_NOW:
+ return opKnownTalerFailure(details.code, details);
+ default:
+ return opUnknownHttpFailure(resp, details);
+ }
+ }
default:
return opUnknownHttpFailure(resp);
}
diff --git a/packages/taler-wallet-core/src/pay-peer-pull-credit.ts b/packages/taler-wallet-core/src/pay-peer-pull-credit.ts
@@ -123,9 +123,7 @@ export class PeerPullCreditTransactionContext implements TransactionContext {
});
}
- async updateTransactionMeta(
- tx: WalletIndexedDbTransaction,
- ): Promise<void> {
+ async updateTransactionMeta(tx: WalletIndexedDbTransaction): Promise<void> {
const rec = await tx.peerPullCredit.get(this.pursePub);
if (rec == null) {
await tx.transactionsMeta.delete(this.pursePub);
@@ -140,9 +138,7 @@ export class PeerPullCreditTransactionContext implements TransactionContext {
}
}
- async deleteTransactionInTx(
- tx: WalletIndexedDbTransaction,
- ): Promise<void> {
+ async deleteTransactionInTx(tx: WalletIndexedDbTransaction): Promise<void> {
const [rec, h] = await this.getRecordHandle(tx);
if (!rec) {
return;
@@ -859,6 +855,11 @@ async function processPeerPullCreditCreatePurse(
return TaskRunResult.finished();
case HttpStatusCode.PaymentRequired:
throw Error(`unexpected reserve merge response ${resp.case}`);
+ case TalerErrorCode.EXCHANGE_RESERVES_PURSE_EXPIRATION_BEFORE_NOW:
+ await ctx.failTransaction(
+ resp.detail ? { code: resp.detail?.code } : undefined,
+ );
+ return TaskRunResult.finished();
default:
assertUnreachable(resp);
}