[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[taler-wallet-core] 02/02: auto-refund
From: |
gnunet |
Subject: |
[taler-wallet-core] 02/02: auto-refund |
Date: |
Sat, 07 Dec 2019 18:42:23 +0100 |
This is an automated email from the git hooks/post-receive script.
dold pushed a commit to branch master
in repository wallet-core.
commit 165486a11268ab3d8009506916cd22d233cd248b
Author: Florian Dold <address@hidden>
AuthorDate: Sat Dec 7 18:42:18 2019 +0100
auto-refund
---
src/dbTypes.ts | 7 ++++++-
src/util/helpers.ts | 36 ++++++++++++++++++++++++------------
src/wallet-impl/pay.ts | 45 ++++++++++++++++++++++++++++++++++++++++-----
src/wallet-impl/tip.ts | 4 ++--
4 files changed, 72 insertions(+), 20 deletions(-)
diff --git a/src/dbTypes.ts b/src/dbTypes.ts
index 55304061..3ffade4e 100644
--- a/src/dbTypes.ts
+++ b/src/dbTypes.ts
@@ -788,7 +788,7 @@ export interface TipRecord {
/**
* Timestamp, the tip can't be picked up anymore after this deadline.
*/
- deadline: number;
+ deadline: Timestamp;
/**
* The exchange that will sign our coins, chosen by the merchant.
@@ -1066,6 +1066,11 @@ export interface PurchaseRecord {
* Last error (or undefined) for querying the refund status with the
merchant.
*/
lastRefundApplyError: OperationError | undefined;
+
+ /**
+ * Continue querying the refund status until this deadline has expired.
+ */
+ autoRefundDeadline: Timestamp | undefined;
}
/**
diff --git a/src/util/helpers.ts b/src/util/helpers.ts
index eb8a1c7b..3831e84a 100644
--- a/src/util/helpers.ts
+++ b/src/util/helpers.ts
@@ -24,7 +24,7 @@
import { AmountJson } from "./amounts";
import * as Amounts from "./amounts";
-import { Timestamp } from "../walletTypes";
+import { Timestamp, Duration } from "../walletTypes";
/**
* Show an amount in a form suitable for the user.
@@ -152,25 +152,37 @@ export function extractTalerStampOrThrow(stamp: string):
Timestamp {
}
/**
- * Check if a timestamp is in the right format.
+ * Extract a duration from a Taler duration string.
*/
-export function timestampCheck(stamp: string): boolean {
- return getTalerStampSec(stamp) !== null;
+export function extractTalerDuration(duration: string): Duration | undefined {
+ const m = duration.match(/\/?Delay\(([0-9]*)\)\/?/);
+ if (!m || !m[1]) {
+ return undefined;
+ }
+ return {
+ d_ms: parseInt(m[1], 10) * 1000,
+ };
}
-
/**
- * Get a JavaScript Date object from a Taler date string.
- * Returns null if input is not in the right format.
+ * Extract a duration from a Taler duration string.
*/
-export function getTalerStampDate(stamp: string): Date | null {
- const sec = getTalerStampSec(stamp);
- if (sec == null) {
- return null;
+export function extractTalerDurationOrThrow(duration: string): Duration {
+ const r = extractTalerDuration(duration);
+ if (!r) {
+ throw Error("invalid duration");
}
- return new Date(sec * 1000);
+ return r;
+}
+
+/**
+ * Check if a timestamp is in the right format.
+ */
+export function timestampCheck(stamp: string): boolean {
+ return getTalerStampSec(stamp) !== null;
}
+
/**
* Compute the hash function of a JSON object.
*/
diff --git a/src/wallet-impl/pay.ts b/src/wallet-impl/pay.ts
index 7076f905..c39feeec 100644
--- a/src/wallet-impl/pay.ts
+++ b/src/wallet-impl/pay.ts
@@ -62,6 +62,8 @@ import {
strcmp,
canonicalJson,
extractTalerStampOrThrow,
+ extractTalerDurationOrThrow,
+ extractTalerDuration,
} from "../util/helpers";
import { Logger } from "../util/logging";
import { InternalWalletState } from "./state";
@@ -359,6 +361,7 @@ async function recordConfirmPay(
lastRefundApplyError: undefined,
refundApplyRetryInfo: initRetryInfo(),
firstSuccessfulPayTimestamp: undefined,
+ autoRefundDeadline: undefined,
};
await runWithWriteTransaction(
@@ -704,9 +707,23 @@ export async function submitPay(
// FIXME: properly display error
throw Error("merchant payment signature invalid");
}
+ const isFirst = purchase.firstSuccessfulPayTimestamp === undefined;
purchase.firstSuccessfulPayTimestamp = getTimestampNow();
purchase.lastPayError = undefined;
purchase.payRetryInfo = initRetryInfo(false);
+ if (isFirst) {
+ const ar = purchase.contractTerms.auto_refund;
+ if (ar) {
+ const autoRefundDelay = extractTalerDuration(ar);
+ if (autoRefundDelay) {
+ purchase.refundStatusRequested = true;
+ purchase.autoRefundDeadline = {
+ t_ms: getTimestampNow().t_ms + autoRefundDelay.d_ms,
+ }
+ }
+ }
+ }
+
const modifiedCoins: CoinRecord[] = [];
for (const pc of purchase.payReq.coins) {
const c = await oneShotGet(ws.db, Stores.coins, pc.coin_pub);
@@ -1064,11 +1081,6 @@ async function acceptRefundResponse(
return;
}
- p.lastRefundStatusTimestamp = getTimestampNow();
- p.lastRefundStatusError = undefined;
- p.refundStatusRetryInfo = initRetryInfo();
- p.refundStatusRequested = false;
-
for (const perm of refundPermissions) {
if (
!p.refundsPending[perm.merchant_sig] &&
@@ -1079,6 +1091,29 @@ async function acceptRefundResponse(
}
}
+ // Are we done with querying yet, or do we need to do another round
+ // after a retry delay?
+ let queryDone = true;
+
+ if (numNewRefunds === 0) {
+ if (p.autoRefundDeadline && p.autoRefundDeadline.t_ms <
getTimestampNow().t_ms) {
+ queryDone = false;
+ }
+ }
+
+ if (queryDone) {
+ p.lastRefundStatusTimestamp = getTimestampNow();
+ p.lastRefundStatusError = undefined;
+ p.refundStatusRetryInfo = initRetryInfo();
+ p.refundStatusRequested = false;
+ } else {
+ // No error, but we need to try again!
+ p.lastRefundStatusTimestamp = getTimestampNow();
+ p.refundStatusRetryInfo.retryCounter++;
+ updateRetryInfoTimeout(p.refundStatusRetryInfo);
+ p.lastRefundStatusError = undefined;
+ }
+
if (numNewRefunds) {
p.lastRefundApplyError = undefined;
p.refundApplyRetryInfo = initRetryInfo();
diff --git a/src/wallet-impl/tip.ts b/src/wallet-impl/tip.ts
index 9cfaed93..11e029fc 100644
--- a/src/wallet-impl/tip.ts
+++ b/src/wallet-impl/tip.ts
@@ -23,7 +23,7 @@ import { TipPickupGetResponse, TipPlanchetDetail, TipResponse
} from "../talerTy
import * as Amounts from "../util/amounts";
import { Stores, PlanchetRecord, WithdrawalSessionRecord, initRetryInfo,
updateRetryInfoTimeout } from "../dbTypes";
import { getWithdrawDetailsForAmount, getVerifiedWithdrawDenomList,
processWithdrawSession } from "./withdraw";
-import { getTalerStampSec } from "../util/helpers";
+import { getTalerStampSec, extractTalerStampOrThrow } from "../util/helpers";
import { updateExchangeFromUrl } from "./exchanges";
import { getRandomBytes, encodeCrock } from "../crypto/talerCrypto";
import { guardOperationException } from "./errors";
@@ -68,7 +68,7 @@ export async function getTipStatus(
tipId,
accepted: false,
amount,
- deadline: getTalerStampSec(tipPickupStatus.stamp_expire)!,
+ deadline: extractTalerStampOrThrow(tipPickupStatus.stamp_expire),
exchangeUrl: tipPickupStatus.exchange_url,
merchantBaseUrl: res.merchantBaseUrl,
nextUrl: undefined,
--
To stop receiving notification emails like this one, please contact
address@hidden.