aboutsummaryrefslogtreecommitdiff
path: root/packages/taler-wallet-core/src/operations
diff options
context:
space:
mode:
Diffstat (limited to 'packages/taler-wallet-core/src/operations')
-rw-r--r--packages/taler-wallet-core/src/operations/attention.ts6
-rw-r--r--packages/taler-wallet-core/src/operations/common.ts45
-rw-r--r--packages/taler-wallet-core/src/operations/deposits.ts8
-rw-r--r--packages/taler-wallet-core/src/operations/exchanges.ts56
-rw-r--r--packages/taler-wallet-core/src/operations/pay-merchant.ts22
-rw-r--r--packages/taler-wallet-core/src/operations/pay-peer-push-debit.ts8
-rw-r--r--packages/taler-wallet-core/src/operations/pending.ts113
-rw-r--r--packages/taler-wallet-core/src/operations/refresh.ts14
-rw-r--r--packages/taler-wallet-core/src/operations/reward.ts6
-rw-r--r--packages/taler-wallet-core/src/operations/transactions.ts17
-rw-r--r--packages/taler-wallet-core/src/operations/withdraw.test.ts114
11 files changed, 250 insertions, 159 deletions
diff --git a/packages/taler-wallet-core/src/operations/attention.ts b/packages/taler-wallet-core/src/operations/attention.ts
index 1030db0a6..92d69e93e 100644
--- a/packages/taler-wallet-core/src/operations/attention.ts
+++ b/packages/taler-wallet-core/src/operations/attention.ts
@@ -31,7 +31,7 @@ import {
UserAttentionUnreadList,
} from "@gnu-taler/taler-util";
import { InternalWalletState } from "../internal-wallet-state.js";
-import { timestampPreciseToDb } from "../index.js";
+import { timestampPreciseFromDb, timestampPreciseToDb } from "../index.js";
const logger = new Logger("operations/attention.ts");
@@ -75,7 +75,7 @@ export async function getUserAttentions(
return;
pending.push({
info: x.info,
- when: TalerPreciseTimestamp.fromMilliseconds(x.createdMs),
+ when: timestampPreciseFromDb(x.created),
read: x.read !== undefined,
});
});
@@ -118,7 +118,7 @@ export async function addAttentionRequest(
await tx.userAttention.put({
info,
entityId,
- createdMs: AbsoluteTime.now().t_ms as number,
+ created: timestampPreciseToDb(TalerPreciseTimestamp.now()),
read: undefined,
});
});
diff --git a/packages/taler-wallet-core/src/operations/common.ts b/packages/taler-wallet-core/src/operations/common.ts
index 50dd3dc5c..e8e492c08 100644
--- a/packages/taler-wallet-core/src/operations/common.ts
+++ b/packages/taler-wallet-core/src/operations/common.ts
@@ -40,6 +40,7 @@ import {
TalerError,
TalerErrorCode,
TalerErrorDetail,
+ TalerPreciseTimestamp,
TombstoneIdStr,
TransactionIdStr,
TransactionType,
@@ -49,6 +50,7 @@ import { CryptoApiStoppedError } from "../crypto/workers/crypto-dispatcher.js";
import {
BackupProviderRecord,
CoinRecord,
+ DbPreciseTimestamp,
DepositGroupRecord,
ExchangeDetailsRecord,
ExchangeEntryDbRecordStatus,
@@ -62,6 +64,7 @@ import {
RecoupGroupRecord,
RefreshGroupRecord,
RewardRecord,
+ timestampPreciseToDb,
WalletStoresV1,
WithdrawalGroupRecord,
} from "../db.js";
@@ -360,11 +363,11 @@ async function storePendingTaskError(
retryRecord = {
id: pendingTaskId,
lastError: e,
- retryInfo: RetryInfo.reset(),
+ retryInfo: DbRetryInfo.reset(),
};
} else {
retryRecord.lastError = e;
- retryRecord.retryInfo = RetryInfo.increment(retryRecord.retryInfo);
+ retryRecord.retryInfo = DbRetryInfo.increment(retryRecord.retryInfo);
}
await tx.operationRetries.put(retryRecord);
return taskToTransactionNotification(ws, tx, pendingTaskId, e);
@@ -383,7 +386,7 @@ export async function resetPendingTaskTimeout(
if (retryRecord) {
// Note that we don't reset the lastError, it should still be visible
// while the retry runs.
- retryRecord.retryInfo = RetryInfo.reset();
+ retryRecord.retryInfo = DbRetryInfo.reset();
await tx.operationRetries.put(retryRecord);
}
return taskToTransactionNotification(ws, tx, pendingTaskId, undefined);
@@ -403,14 +406,14 @@ async function storePendingTaskPending(
if (!retryRecord) {
retryRecord = {
id: pendingTaskId,
- retryInfo: RetryInfo.reset(),
+ retryInfo: DbRetryInfo.reset(),
};
} else {
if (retryRecord.lastError) {
hadError = true;
}
delete retryRecord.lastError;
- retryRecord.retryInfo = RetryInfo.increment(retryRecord.retryInfo);
+ retryRecord.retryInfo = DbRetryInfo.increment(retryRecord.retryInfo);
}
await tx.operationRetries.put(retryRecord);
if (hadError) {
@@ -736,9 +739,9 @@ export interface TaskRunLongpollResult {
type: TaskRunResultType.Longpoll;
}
-export interface RetryInfo {
- firstTry: AbsoluteTime;
- nextRetry: AbsoluteTime;
+export interface DbRetryInfo {
+ firstTry: DbPreciseTimestamp;
+ nextRetry: DbPreciseTimestamp;
retryCounter: number;
}
@@ -755,7 +758,7 @@ const defaultRetryPolicy: RetryPolicy = {
};
function updateTimeout(
- r: RetryInfo,
+ r: DbRetryInfo,
p: RetryPolicy = defaultRetryPolicy,
): void {
const now = AbsoluteTime.now();
@@ -763,7 +766,9 @@ function updateTimeout(
throw Error("assertion failed");
}
if (p.backoffDelta.d_ms === "forever") {
- r.nextRetry = AbsoluteTime.never();
+ r.nextRetry = timestampPreciseToDb(
+ AbsoluteTime.toPreciseTimestamp(AbsoluteTime.never()),
+ );
return;
}
@@ -775,12 +780,12 @@ function updateTimeout(
(p.maxTimeout.d_ms === "forever"
? nextIncrement
: Math.min(p.maxTimeout.d_ms, nextIncrement));
- r.nextRetry = AbsoluteTime.fromMilliseconds(t);
+ r.nextRetry = timestampPreciseToDb(TalerPreciseTimestamp.fromMilliseconds(t));
}
-export namespace RetryInfo {
+export namespace DbRetryInfo {
export function getDuration(
- r: RetryInfo | undefined,
+ r: DbRetryInfo | undefined,
p: RetryPolicy = defaultRetryPolicy,
): Duration {
if (!r) {
@@ -797,11 +802,11 @@ export namespace RetryInfo {
};
}
- export function reset(p: RetryPolicy = defaultRetryPolicy): RetryInfo {
- const now = AbsoluteTime.now();
- const info = {
- firstTry: now,
- nextRetry: now,
+ export function reset(p: RetryPolicy = defaultRetryPolicy): DbRetryInfo {
+ const now = TalerPreciseTimestamp.now();
+ const info: DbRetryInfo = {
+ firstTry: timestampPreciseToDb(now),
+ nextRetry: timestampPreciseToDb(now),
retryCounter: 0,
};
updateTimeout(info, p);
@@ -809,9 +814,9 @@ export namespace RetryInfo {
}
export function increment(
- r: RetryInfo | undefined,
+ r: DbRetryInfo | undefined,
p: RetryPolicy = defaultRetryPolicy,
- ): RetryInfo {
+ ): DbRetryInfo {
if (!r) {
return reset(p);
}
diff --git a/packages/taler-wallet-core/src/operations/deposits.ts b/packages/taler-wallet-core/src/operations/deposits.ts
index cb40f8f22..111d15989 100644
--- a/packages/taler-wallet-core/src/operations/deposits.ts
+++ b/packages/taler-wallet-core/src/operations/deposits.ts
@@ -74,6 +74,8 @@ import {
createRefreshGroup,
getTotalRefreshCost,
timestampPreciseToDb,
+ timestampProtocolFromDb,
+ timestampProtocolToDb,
} from "../index.js";
import { InternalWalletState } from "../internal-wallet-state.js";
import { assertUnreachable } from "../util/assertUnreachable.js";
@@ -800,7 +802,7 @@ async function processDepositGroupPendingTrack(
amountRaw: Amounts.stringify(raw),
wireFee: Amounts.stringify(wireFee),
exchangePub: track.exchange_pub,
- timestampExecuted: track.execution_time,
+ timestampExecuted: timestampProtocolToDb(track.execution_time),
wireTransferId: track.wtid,
},
id: track.exchange_sig,
@@ -1393,7 +1395,9 @@ export async function createDepositGroup(
counterpartyEffectiveDepositAmount: Amounts.stringify(
counterpartyEffectiveDepositAmount,
),
- wireTransferDeadline: contractTerms.wire_transfer_deadline,
+ wireTransferDeadline: timestampProtocolToDb(
+ contractTerms.wire_transfer_deadline,
+ ),
wire: {
payto_uri: req.depositPaytoUri,
salt: wireSalt,
diff --git a/packages/taler-wallet-core/src/operations/exchanges.ts b/packages/taler-wallet-core/src/operations/exchanges.ts
index 60d55252a..5e966b719 100644
--- a/packages/taler-wallet-core/src/operations/exchanges.ts
+++ b/packages/taler-wallet-core/src/operations/exchanges.ts
@@ -74,7 +74,9 @@ import {
ExchangeEntryDbRecordStatus,
ExchangeEntryDbUpdateStatus,
isWithdrawableDenom,
+ timestampPreciseFromDb,
timestampPreciseToDb,
+ timestampProtocolToDb,
WalletDbReadWriteTransaction,
} from "../index.js";
import { InternalWalletState, TrustInfo } from "../internal-wallet-state.js";
@@ -317,8 +319,12 @@ export async function addPresetExchangeEntry(
detailsPointer: undefined,
lastUpdate: undefined,
lastKeysEtag: undefined,
- nextRefreshCheckStampMs: AbsoluteTime.getStampMsNever(),
- nextUpdateStampMs: AbsoluteTime.getStampMsNever(),
+ nextRefreshCheckStamp: timestampPreciseToDb(
+ AbsoluteTime.toPreciseTimestamp(AbsoluteTime.never()),
+ ),
+ nextUpdateStamp: timestampPreciseToDb(
+ AbsoluteTime.toPreciseTimestamp(AbsoluteTime.never()),
+ ),
};
await tx.exchanges.put(r);
}
@@ -344,8 +350,12 @@ export async function provideExchangeRecordInTx(
baseUrl: baseUrl,
detailsPointer: undefined,
lastUpdate: undefined,
- nextUpdateStampMs: AbsoluteTime.getStampMsNever(),
- nextRefreshCheckStampMs: AbsoluteTime.getStampMsNever(),
+ nextUpdateStamp: timestampPreciseToDb(
+ AbsoluteTime.toPreciseTimestamp(AbsoluteTime.never()),
+ ),
+ nextRefreshCheckStamp: timestampPreciseToDb(
+ AbsoluteTime.toPreciseTimestamp(AbsoluteTime.never()),
+ ),
lastKeysEtag: undefined,
};
await tx.exchanges.put(r);
@@ -446,13 +456,19 @@ async function downloadExchangeKeysInfo(
isRevoked: false,
value: Amounts.stringify(value),
currency: value.currency,
- stampExpireDeposit: denomIn.stamp_expire_deposit,
- stampExpireLegal: denomIn.stamp_expire_legal,
- stampExpireWithdraw: denomIn.stamp_expire_withdraw,
- stampStart: denomIn.stamp_start,
+ stampExpireDeposit: timestampProtocolToDb(
+ denomIn.stamp_expire_deposit,
+ ),
+ stampExpireLegal: timestampProtocolToDb(denomIn.stamp_expire_legal),
+ stampExpireWithdraw: timestampProtocolToDb(
+ denomIn.stamp_expire_withdraw,
+ ),
+ stampStart: timestampProtocolToDb(denomIn.stamp_start),
verificationStatus: DenominationVerificationStatus.Unverified,
masterSig: denomIn.master_sig,
- listIssueDate: exchangeKeysJsonUnchecked.list_issue_date,
+ listIssueDate: timestampProtocolToDb(
+ exchangeKeysJsonUnchecked.list_issue_date,
+ ),
fees: {
feeDeposit: Amounts.stringify(denomGroup.fee_deposit),
feeRefresh: Amounts.stringify(denomGroup.fee_refresh),
@@ -614,7 +630,9 @@ export async function updateExchangeFromUrlHandler(
!forceNow &&
exchangeDetails !== undefined &&
!AbsoluteTime.isExpired(
- AbsoluteTime.fromStampMs(exchange.nextUpdateStampMs),
+ AbsoluteTime.fromPreciseTimestamp(
+ timestampPreciseFromDb(exchange.nextUpdateStamp),
+ ),
)
) {
logger.trace("using existing exchange info");
@@ -755,11 +773,15 @@ export async function updateExchangeFromUrlHandler(
newDetails.rowId = existingDetails.rowId;
}
r.lastUpdate = timestampPreciseToDb(TalerPreciseTimestamp.now());
- r.nextUpdateStampMs = AbsoluteTime.toStampMs(
- AbsoluteTime.fromProtocolTimestamp(keysInfo.expiry),
+ r.nextUpdateStamp = timestampPreciseToDb(
+ AbsoluteTime.toPreciseTimestamp(
+ AbsoluteTime.fromProtocolTimestamp(keysInfo.expiry),
+ ),
);
// New denominations might be available.
- r.nextRefreshCheckStampMs = AbsoluteTime.getStampMsNow();
+ r.nextRefreshCheckStamp = timestampPreciseToDb(
+ TalerPreciseTimestamp.now(),
+ );
if (detailsPointerChanged) {
r.detailsPointer = {
currency: newDetails.currency,
@@ -777,9 +799,9 @@ export async function updateExchangeFromUrlHandler(
exchangeDetailsRowId: drRowId.key,
masterSig: sk.master_sig,
signkeyPub: sk.key,
- stampEnd: sk.stamp_end,
- stampExpire: sk.stamp_expire,
- stampStart: sk.stamp_start,
+ stampEnd: timestampProtocolToDb(sk.stamp_end),
+ stampExpire: timestampProtocolToDb(sk.stamp_expire),
+ stampStart: timestampProtocolToDb(sk.stamp_start),
});
}
@@ -814,7 +836,7 @@ export async function updateExchangeFromUrlHandler(
);
}
} else {
- x.listIssueDate = keysInfo.listIssueDate;
+ x.listIssueDate = timestampProtocolToDb(keysInfo.listIssueDate);
if (!x.isOffered) {
x.isOffered = true;
logger.info(
diff --git a/packages/taler-wallet-core/src/operations/pay-merchant.ts b/packages/taler-wallet-core/src/operations/pay-merchant.ts
index 97bf6e2a6..157541ed3 100644
--- a/packages/taler-wallet-core/src/operations/pay-merchant.ts
+++ b/packages/taler-wallet-core/src/operations/pay-merchant.ts
@@ -104,6 +104,8 @@ import {
RefundItemRecord,
RefundItemStatus,
timestampPreciseToDb,
+ timestampProtocolFromDb,
+ timestampProtocolToDb,
} from "../index.js";
import {
EXCHANGE_COINS_LOCK,
@@ -115,7 +117,7 @@ import { checkDbInvariant } from "../util/invariants.js";
import { GetReadOnlyAccess } from "../util/query.js";
import {
constructTaskIdentifier,
- RetryInfo,
+ DbRetryInfo,
runLongpollAsync,
runTaskWithErrorReporting,
spendCoins,
@@ -217,11 +219,13 @@ async function failProposalPermanently(
notifyTransition(ws, transactionId, transitionInfo);
}
-function getProposalRequestTimeout(retryInfo?: RetryInfo): Duration {
+function getProposalRequestTimeout(retryInfo?: DbRetryInfo): Duration {
return Duration.clamp({
lower: Duration.fromSpec({ seconds: 1 }),
upper: Duration.fromSpec({ seconds: 60 }),
- value: retryInfo ? RetryInfo.getDuration(retryInfo) : Duration.fromSpec({}),
+ value: retryInfo
+ ? DbRetryInfo.getDuration(retryInfo)
+ : Duration.fromSpec({}),
});
}
@@ -738,8 +742,10 @@ async function storeFirstPaySuccess(
const ar = Duration.fromTalerProtocolDuration(protoAr);
logger.info("auto_refund present");
purchase.purchaseStatus = PurchaseStatus.PendingQueryingAutoRefund;
- purchase.autoRefundDeadline = AbsoluteTime.toProtocolTimestamp(
- AbsoluteTime.addDuration(AbsoluteTime.now(), ar),
+ purchase.autoRefundDeadline = timestampProtocolToDb(
+ AbsoluteTime.toProtocolTimestamp(
+ AbsoluteTime.addDuration(AbsoluteTime.now(), ar),
+ ),
);
}
await tx.purchases.put(purchase);
@@ -2343,7 +2349,9 @@ async function processPurchaseAutoRefund(
if (
!purchase.autoRefundDeadline ||
AbsoluteTime.isExpired(
- AbsoluteTime.fromProtocolTimestamp(purchase.autoRefundDeadline),
+ AbsoluteTime.fromProtocolTimestamp(
+ timestampProtocolFromDb(purchase.autoRefundDeadline),
+ ),
)
) {
const transitionInfo = await ws.db
@@ -2804,7 +2812,7 @@ async function storeRefunds(
const status: RefundItemStatus = getItemStatus(rf);
const newItem: RefundItemRecord = {
coinPub: rf.coin_pub,
- executionTime: rf.execution_time,
+ executionTime: timestampProtocolToDb(rf.execution_time),
obtainedTime: timestampPreciseToDb(now),
refundAmount: rf.refund_amount,
refundGroupId: newGroup.refundGroupId,
diff --git a/packages/taler-wallet-core/src/operations/pay-peer-push-debit.ts b/packages/taler-wallet-core/src/operations/pay-peer-push-debit.ts
index b3d0eb132..a7b9f79eb 100644
--- a/packages/taler-wallet-core/src/operations/pay-peer-push-debit.ts
+++ b/packages/taler-wallet-core/src/operations/pay-peer-push-debit.ts
@@ -56,10 +56,13 @@ import {
RefreshOperationStatus,
createRefreshGroup,
timestampPreciseToDb,
+ timestampProtocolFromDb,
+ timestampProtocolToDb,
} from "../index.js";
import { InternalWalletState } from "../internal-wallet-state.js";
import { PendingTaskType } from "../pending-types.js";
import { assertUnreachable } from "../util/assertUnreachable.js";
+import { PeerCoinRepair, selectPeerCoins } from "../util/coinSelection.js";
import { checkLogicInvariant } from "../util/invariants.js";
import {
TaskRunResult,
@@ -78,7 +81,6 @@ import {
notifyTransition,
stopLongpolling,
} from "./transactions.js";
-import { PeerCoinRepair, selectPeerCoins } from "../util/coinSelection.js";
const logger = new Logger("pay-peer-push-debit.ts");
@@ -208,7 +210,7 @@ async function processPeerPushDebitCreateReserve(
mergePub: peerPushInitiation.mergePub,
minAge: 0,
purseAmount: peerPushInitiation.amount,
- purseExpiration,
+ purseExpiration: timestampProtocolFromDb(purseExpiration),
pursePriv: peerPushInitiation.pursePriv,
});
@@ -667,7 +669,7 @@ export async function initiatePeerPushDebit(
exchangeBaseUrl: sel.exchangeBaseUrl,
mergePriv: mergePair.priv,
mergePub: mergePair.pub,
- purseExpiration: purseExpiration,
+ purseExpiration: timestampProtocolToDb(purseExpiration),
pursePriv: pursePair.priv,
pursePub: pursePair.pub,
timestampCreated: timestampPreciseToDb(TalerPreciseTimestamp.now()),
diff --git a/packages/taler-wallet-core/src/operations/pending.ts b/packages/taler-wallet-core/src/operations/pending.ts
index 120d316ce..1819aa1b8 100644
--- a/packages/taler-wallet-core/src/operations/pending.ts
+++ b/packages/taler-wallet-core/src/operations/pending.ts
@@ -21,43 +21,46 @@
/**
* Imports.
*/
+import { GlobalIDB } from "@gnu-taler/idb-bridge";
+import { AbsoluteTime, TransactionRecordFilter } from "@gnu-taler/taler-util";
import {
- PurchaseStatus,
- WalletStoresV1,
BackupProviderStateTag,
- RefreshCoinStatus,
- PeerPushDebitStatus,
- PeerPullDebitRecordStatus,
- PeerPushCreditStatus,
- PeerPullPaymentCreditStatus,
- WithdrawalGroupStatus,
- RewardRecordStatus,
- DepositOperationStatus,
- RefreshGroupRecord,
- WithdrawalGroupRecord,
+ DepositElementStatus,
DepositGroupRecord,
- RewardRecord,
- PurchaseRecord,
+ DepositOperationStatus,
+ ExchangeEntryDbUpdateStatus,
PeerPullCreditRecord,
+ PeerPullDebitRecordStatus,
+ PeerPullPaymentCreditStatus,
PeerPullPaymentIncomingRecord,
+ PeerPushCreditStatus,
PeerPushDebitRecord,
+ PeerPushDebitStatus,
PeerPushPaymentIncomingRecord,
+ PurchaseRecord,
+ PurchaseStatus,
+ RefreshCoinStatus,
+ RefreshGroupRecord,
+ RefreshOperationStatus,
RefundGroupRecord,
RefundGroupStatus,
- ExchangeEntryDbUpdateStatus,
- RefreshOperationStatus,
- DepositElementStatus,
+ RewardRecord,
+ RewardRecordStatus,
+ WalletStoresV1,
+ WithdrawalGroupRecord,
+ WithdrawalGroupStatus,
+ timestampAbsoluteFromDb,
+ timestampOptionalAbsoluteFromDb,
timestampPreciseFromDb,
+ timestampPreciseToDb,
} from "../db.js";
+import { InternalWalletState } from "../internal-wallet-state.js";
import {
PendingOperationsResponse,
PendingTaskType,
TaskId,
} from "../pending-types.js";
-import { AbsoluteTime, TransactionRecordFilter } from "@gnu-taler/taler-util";
-import { InternalWalletState } from "../internal-wallet-state.js";
import { GetReadOnlyAccess } from "../util/query.js";
-import { GlobalIDB } from "@gnu-taler/idb-bridge";
import { TaskIdentifiers } from "./common.js";
function getPendingCommon(
@@ -100,12 +103,14 @@ async function gatherExchangePending(
}
const opTag = TaskIdentifiers.forExchangeUpdate(exch);
let opr = await tx.operationRetries.get(opTag);
- const timestampDue =
- opr?.retryInfo.nextRetry ??
- AbsoluteTime.fromStampMs(exch.nextUpdateStampMs);
+ const timestampDue = opr?.retryInfo.nextRetry ?? exch.nextRefreshCheckStamp;
resp.pendingOperations.push({
type: PendingTaskType.ExchangeUpdate,
- ...getPendingCommon(ws, opTag, timestampDue),
+ ...getPendingCommon(
+ ws,
+ opTag,
+ AbsoluteTime.fromPreciseTimestamp(timestampPreciseFromDb(timestampDue)),
+ ),
givesLifeness: false,
exchangeBaseUrl: exch.baseUrl,
lastError: opr?.lastError,
@@ -116,8 +121,16 @@ async function gatherExchangePending(
if (!opr?.lastError) {
resp.pendingOperations.push({
type: PendingTaskType.ExchangeCheckRefresh,
- ...getPendingCommon(ws, opTag, timestampDue),
- timestampDue: AbsoluteTime.fromStampMs(exch.nextRefreshCheckStampMs),
+ ...getPendingCommon(
+ ws,
+ opTag,
+ AbsoluteTime.fromPreciseTimestamp(
+ timestampPreciseFromDb(timestampDue),
+ ),
+ ),
+ timestampDue: AbsoluteTime.fromPreciseTimestamp(
+ timestampPreciseFromDb(exch.nextRefreshCheckStamp),
+ ),
givesLifeness: false,
exchangeBaseUrl: exch.baseUrl,
});
@@ -166,7 +179,9 @@ async function gatherRefreshPending(
}
const opId = TaskIdentifiers.forRefresh(r);
const retryRecord = await tx.operationRetries.get(opId);
- const timestampDue = retryRecord?.retryInfo.nextRetry ?? AbsoluteTime.now();
+ const timestampDue =
+ timestampOptionalAbsoluteFromDb(retryRecord?.retryInfo.nextRetry) ??
+ AbsoluteTime.now();
resp.pendingOperations.push({
type: PendingTaskType.Refresh,
...getPendingCommon(ws, opId, timestampDue),
@@ -223,8 +238,8 @@ async function gatherWithdrawalPending(
opr = {
id: opTag,
retryInfo: {
- firstTry: now,
- nextRetry: now,
+ firstTry: timestampPreciseToDb(AbsoluteTime.toPreciseTimestamp(now)),
+ nextRetry: timestampPreciseToDb(AbsoluteTime.toPreciseTimestamp(now)),
retryCounter: 0,
},
};
@@ -234,7 +249,8 @@ async function gatherWithdrawalPending(
...getPendingCommon(
ws,
opTag,
- opr.retryInfo?.nextRetry ?? AbsoluteTime.now(),
+ timestampOptionalAbsoluteFromDb(opr.retryInfo?.nextRetry) ??
+ AbsoluteTime.now(),
),
givesLifeness: true,
withdrawalGroupId: wsr.withdrawalGroupId,
@@ -286,7 +302,9 @@ async function gatherDepositPending(
}
const opId = TaskIdentifiers.forDeposit(dg);
const retryRecord = await tx.operationRetries.get(opId);
- const timestampDue = retryRecord?.retryInfo.nextRetry ?? AbsoluteTime.now();
+ const timestampDue =
+ timestampOptionalAbsoluteFromDb(retryRecord?.retryInfo.nextRetry) ??
+ AbsoluteTime.now();
resp.pendingOperations.push({
type: PendingTaskType.Deposit,
...getPendingCommon(ws, opId, timestampDue),
@@ -331,13 +349,15 @@ async function gatherRewardPending(
await iterRecordsForReward(tx, { onlyState: "nonfinal" }, async (tip) => {
const opId = TaskIdentifiers.forTipPickup(tip);
const retryRecord = await tx.operationRetries.get(opId);
- const timestampDue = retryRecord?.retryInfo.nextRetry ?? AbsoluteTime.now();
+ const timestampDue =
+ timestampOptionalAbsoluteFromDb(retryRecord?.retryInfo.nextRetry) ??
+ AbsoluteTime.now();
if (tip.acceptedTimestamp) {
resp.pendingOperations.push({
type: PendingTaskType.RewardPickup,
...getPendingCommon(ws, opId, timestampDue),
givesLifeness: true,
- timestampDue: retryRecord?.retryInfo.nextRetry ?? AbsoluteTime.now(),
+ timestampDue,
merchantBaseUrl: tip.merchantBaseUrl,
tipId: tip.walletRewardId,
merchantTipId: tip.merchantRewardId,
@@ -391,7 +411,9 @@ async function gatherPurchasePending(
await iterRecordsForPurchase(tx, { onlyState: "nonfinal" }, async (pr) => {
const opId = TaskIdentifiers.forPay(pr);
const retryRecord = await tx.operationRetries.get(opId);
- const timestampDue = retryRecord?.retryInfo.nextRetry ?? AbsoluteTime.now();
+ const timestampDue =
+ timestampOptionalAbsoluteFromDb(retryRecord?.retryInfo.nextRetry) ??
+ AbsoluteTime.now();
resp.pendingOperations.push({
type: PendingTaskType.Purchase,
...getPendingCommon(ws, opId, timestampDue),
@@ -420,7 +442,9 @@ async function gatherRecoupPending(
}
const opId = TaskIdentifiers.forRecoup(rg);
const retryRecord = await tx.operationRetries.get(opId);
- const timestampDue = retryRecord?.retryInfo.nextRetry ?? AbsoluteTime.now();
+ const timestampDue =
+ timestampOptionalAbsoluteFromDb(retryRecord?.retryInfo.nextRetry) ??
+ AbsoluteTime.now();
resp.pendingOperations.push({
type: PendingTaskType.Recoup,
...getPendingCommon(ws, opId, timestampDue),
@@ -445,8 +469,8 @@ async function gatherBackupPending(
const opId = TaskIdentifiers.forBackup(bp);
const retryRecord = await tx.operationRetries.get(opId);
if (bp.state.tag === BackupProviderStateTag.Ready) {
- const timestampDue = AbsoluteTime.fromPreciseTimestamp(
- timestampPreciseFromDb(bp.state.nextBackupTimestamp),
+ const timestampDue = timestampAbsoluteFromDb(
+ bp.state.nextBackupTimestamp,
);
resp.pendingOperations.push({
type: PendingTaskType.Backup,
@@ -457,7 +481,8 @@ async function gatherBackupPending(
});
} else if (bp.state.tag === BackupProviderStateTag.Retrying) {
const timestampDue =
- retryRecord?.retryInfo?.nextRetry ?? AbsoluteTime.now();
+ timestampOptionalAbsoluteFromDb(retryRecord?.retryInfo?.nextRetry) ??
+ AbsoluteTime.now();
resp.pendingOperations.push({
type: PendingTaskType.Backup,
...getPendingCommon(ws, opId, timestampDue),
@@ -504,7 +529,8 @@ async function gatherPeerPullInitiationPending(
const opId = TaskIdentifiers.forPeerPullPaymentInitiation(pi);
const retryRecord = await tx.operationRetries.get(opId);
const timestampDue =
- retryRecord?.retryInfo.nextRetry ?? AbsoluteTime.now();
+ timestampOptionalAbsoluteFromDb(retryRecord?.retryInfo.nextRetry) ??
+ AbsoluteTime.now();
resp.pendingOperations.push({
type: PendingTaskType.PeerPullCredit,
...getPendingCommon(ws, opId, timestampDue),
@@ -550,7 +576,8 @@ async function gatherPeerPullDebitPending(
const opId = TaskIdentifiers.forPeerPullPaymentDebit(pi);
const retryRecord = await tx.operationRetries.get(opId);
const timestampDue =
- retryRecord?.retryInfo.nextRetry ?? AbsoluteTime.now();
+ timestampOptionalAbsoluteFromDb(retryRecord?.retryInfo.nextRetry) ??
+ AbsoluteTime.now();
resp.pendingOperations.push({
type: PendingTaskType.PeerPullDebit,
...getPendingCommon(ws, opId, timestampDue),
@@ -596,7 +623,8 @@ async function gatherPeerPushInitiationPending(
const opId = TaskIdentifiers.forPeerPushPaymentInitiation(pi);
const retryRecord = await tx.operationRetries.get(opId);
const timestampDue =
- retryRecord?.retryInfo.nextRetry ?? AbsoluteTime.now();
+ timestampOptionalAbsoluteFromDb(retryRecord?.retryInfo.nextRetry) ??
+ AbsoluteTime.now();
resp.pendingOperations.push({
type: PendingTaskType.PeerPushDebit,
...getPendingCommon(ws, opId, timestampDue),
@@ -646,7 +674,8 @@ async function gatherPeerPushCreditPending(
const opId = TaskIdentifiers.forPeerPushCredit(pi);
const retryRecord = await tx.operationRetries.get(opId);
const timestampDue =
- retryRecord?.retryInfo.nextRetry ?? AbsoluteTime.now();
+ timestampOptionalAbsoluteFromDb(retryRecord?.retryInfo.nextRetry) ??
+ AbsoluteTime.now();
resp.pendingOperations.push({
type: PendingTaskType.PeerPushCredit,
...getPendingCommon(ws, opId, timestampDue),
diff --git a/packages/taler-wallet-core/src/operations/refresh.ts b/packages/taler-wallet-core/src/operations/refresh.ts
index dc1d53627..95aedbbd6 100644
--- a/packages/taler-wallet-core/src/operations/refresh.ts
+++ b/packages/taler-wallet-core/src/operations/refresh.ts
@@ -81,6 +81,7 @@ import {
PendingTaskType,
RefreshSessionRecord,
timestampPreciseToDb,
+ timestampProtocolFromDb,
} from "../index.js";
import {
EXCHANGE_COINS_LOCK,
@@ -1125,10 +1126,10 @@ export async function createRefreshGroup(
*/
function getAutoRefreshCheckThreshold(d: DenominationRecord): AbsoluteTime {
const expireWithdraw = AbsoluteTime.fromProtocolTimestamp(
- d.stampExpireWithdraw,
+ timestampProtocolFromDb(d.stampExpireWithdraw),
);
const expireDeposit = AbsoluteTime.fromProtocolTimestamp(
- d.stampExpireDeposit,
+ timestampProtocolFromDb(d.stampExpireDeposit),
);
const delta = AbsoluteTime.difference(expireWithdraw, expireDeposit);
const deltaDiv = durationMul(delta, 0.75);
@@ -1140,10 +1141,10 @@ function getAutoRefreshCheckThreshold(d: DenominationRecord): AbsoluteTime {
*/
function getAutoRefreshExecuteThreshold(d: DenominationRecord): AbsoluteTime {
const expireWithdraw = AbsoluteTime.fromProtocolTimestamp(
- d.stampExpireWithdraw,
+ timestampProtocolFromDb(d.stampExpireWithdraw),
);
const expireDeposit = AbsoluteTime.fromProtocolTimestamp(
- d.stampExpireDeposit,
+ timestampProtocolFromDb(d.stampExpireDeposit),
);
const delta = AbsoluteTime.difference(expireWithdraw, expireDeposit);
const deltaDiv = durationMul(delta, 0.5);
@@ -1227,8 +1228,9 @@ export async function autoRefresh(
logger.trace(
`next refresh check at ${AbsoluteTime.toIsoString(minCheckThreshold)}`,
);
- exchange.nextRefreshCheckStampMs =
- AbsoluteTime.toStampMs(minCheckThreshold);
+ exchange.nextRefreshCheckStamp = timestampPreciseToDb(
+ AbsoluteTime.toPreciseTimestamp(minCheckThreshold),
+ );
await tx.exchanges.put(exchange);
});
return TaskRunResult.finished();
diff --git a/packages/taler-wallet-core/src/operations/reward.ts b/packages/taler-wallet-core/src/operations/reward.ts
index 3681dc4f5..ddcfb20ac 100644
--- a/packages/taler-wallet-core/src/operations/reward.ts
+++ b/packages/taler-wallet-core/src/operations/reward.ts
@@ -52,6 +52,8 @@ import {
RewardRecordStatus,
timestampPreciseFromDb,
timestampPreciseToDb,
+ timestampProtocolFromDb,
+ timestampProtocolToDb,
} from "../db.js";
import { makeErrorDetail } from "@gnu-taler/taler-util";
import { InternalWalletState } from "../internal-wallet-state.js";
@@ -201,7 +203,7 @@ export async function prepareTip(
acceptedTimestamp: undefined,
status: RewardRecordStatus.DialogAccept,
rewardAmountRaw: Amounts.stringify(amount),
- rewardExpiration: tipPickupStatus.expiration,
+ rewardExpiration: timestampProtocolToDb(tipPickupStatus.expiration),
exchangeBaseUrl: tipPickupStatus.exchange_url,
next_url: tipPickupStatus.next_url,
merchantBaseUrl: res.merchantBaseUrl,
@@ -231,7 +233,7 @@ export async function prepareTip(
rewardAmountRaw: Amounts.stringify(tipRecord.rewardAmountRaw),
exchangeBaseUrl: tipRecord.exchangeBaseUrl,
merchantBaseUrl: tipRecord.merchantBaseUrl,
- expirationTimestamp: tipRecord.rewardExpiration,
+ expirationTimestamp: timestampProtocolFromDb(tipRecord.rewardExpiration),
rewardAmountEffective: Amounts.stringify(tipRecord.rewardAmountEffective),
walletRewardId: tipRecord.walletRewardId,
transactionId,
diff --git a/packages/taler-wallet-core/src/operations/transactions.ts b/packages/taler-wallet-core/src/operations/transactions.ts
index 41bdae249..cf2006406 100644
--- a/packages/taler-wallet-core/src/operations/transactions.ts
+++ b/packages/taler-wallet-core/src/operations/transactions.ts
@@ -20,6 +20,7 @@
import {
AbsoluteTime,
Amounts,
+ DepositTransactionTrackingState,
j2s,
Logger,
NotificationType,
@@ -69,6 +70,7 @@ import {
GetReadOnlyAccess,
timestampOptionalPreciseFromDb,
timestampPreciseFromDb,
+ timestampProtocolFromDb,
WalletStoresV1,
} from "../index.js";
import { InternalWalletState } from "../internal-wallet-state.js";
@@ -809,6 +811,17 @@ function buildTransactionForDeposit(
}
}
+ const trackingState: DepositTransactionTrackingState[] = [];
+
+ for (const ts of Object.values(dg.trackingState ?? {})) {
+ trackingState.push({
+ amountRaw: ts.amountRaw,
+ timestampExecuted: timestampProtocolFromDb(ts.timestampExecuted),
+ wireFee: ts.wireFee,
+ wireTransferId: ts.wireTransferId,
+ });
+ }
+
return {
type: TransactionType.Deposit,
txState: computeDepositTransactionStatus(dg),
@@ -817,7 +830,7 @@ function buildTransactionForDeposit(
amountEffective: Amounts.stringify(dg.totalPayCost),
timestamp: timestampPreciseFromDb(dg.timestampCreated),
targetPaytoUri: dg.wire.payto_uri,
- wireTransferDeadline: dg.wireTransferDeadline,
+ wireTransferDeadline: timestampProtocolFromDb(dg.wireTransferDeadline),
transactionId: constructTransactionIdentifier({
tag: TransactionType.Deposit,
depositGroupId: dg.depositGroupId,
@@ -830,7 +843,7 @@ function buildTransactionForDeposit(
)) /
dg.statusPerCoin.length,
depositGroupId: dg.depositGroupId,
- trackingState: Object.values(dg.trackingState ?? {}),
+ trackingState,
deposited,
...(ort?.lastError ? { error: ort.lastError } : {}),
};
diff --git a/packages/taler-wallet-core/src/operations/withdraw.test.ts b/packages/taler-wallet-core/src/operations/withdraw.test.ts
index 2d9286610..cb8aa5e81 100644
--- a/packages/taler-wallet-core/src/operations/withdraw.test.ts
+++ b/packages/taler-wallet-core/src/operations/withdraw.test.ts
@@ -16,7 +16,11 @@
import { Amounts, DenomKeyType } from "@gnu-taler/taler-util";
import test from "ava";
-import { DenominationRecord, DenominationVerificationStatus } from "../db.js";
+import {
+ DenominationRecord,
+ DenominationVerificationStatus,
+ timestampProtocolToDb,
+} from "../db.js";
import { selectWithdrawalDenominations } from "../util/coinSelection.js";
test("withdrawal selection bug repro", (t) => {
@@ -64,22 +68,22 @@ test("withdrawal selection bug repro", (t) => {
isRevoked: false,
masterSig:
"4F0P456CNNTTWK8BFJHGM3JTD6FVVNZY8EP077GYAHDJ5Y81S5RQ3SMS925NXMDVG9A88JAAP0E2GDZBC21PP5NHFFVWHAW3AVT8J3R",
- stampExpireDeposit: {
+ stampExpireDeposit: timestampProtocolToDb({
t_s: 1742909388,
- },
- stampExpireLegal: {
+ }),
+ stampExpireLegal: timestampProtocolToDb({
t_s: 1900589388,
- },
- stampExpireWithdraw: {
+ }),
+ stampExpireWithdraw: timestampProtocolToDb({
t_s: 1679837388,
- },
- stampStart: {
+ }),
+ stampStart: timestampProtocolToDb({
t_s: 1585229388,
- },
+ }),
verificationStatus: DenominationVerificationStatus.Unverified,
currency: "KUDOS",
value: "KUDOS:1000",
- listIssueDate: { t_s: 0 },
+ listIssueDate: timestampProtocolToDb({ t_s: 0 }),
},
{
denomPub: {
@@ -119,22 +123,22 @@ test("withdrawal selection bug repro", (t) => {
isRevoked: false,
masterSig:
"P99AW82W46MZ0AKW7Z58VQPXFNTJQM9DVTYPBDF6KVYF38PPVDAZTV7JQ8TY7HGEC7JJJAY4E7AY7J3W1WV10DAZZQHHKTAVTSRAC20",
- stampExpireDeposit: {
+ stampExpireDeposit: timestampProtocolToDb({
t_s: 1742909388,
- },
- stampExpireLegal: {
+ }),
+ stampExpireLegal: timestampProtocolToDb({
t_s: 1900589388,
- },
- stampExpireWithdraw: {
+ }),
+ stampExpireWithdraw: timestampProtocolToDb({
t_s: 1679837388,
- },
- stampStart: {
+ }),
+ stampStart: timestampProtocolToDb({
t_s: 1585229388,
- },
+ }),
verificationStatus: DenominationVerificationStatus.Unverified,
value: "KUDOS:10",
currency: "KUDOS",
- listIssueDate: { t_s: 0 },
+ listIssueDate: timestampProtocolToDb({ t_s: 0 }),
},
{
denomPub: {
@@ -173,22 +177,22 @@ test("withdrawal selection bug repro", (t) => {
isRevoked: false,
masterSig:
"8S4VZGHE5WE0N5ZVCHYW9KZZR4YAKK15S46MV1HR1QB9AAMH3NWPW4DCR4NYGJK33Q8YNFY80SWNS6XKAP5DEVK933TM894FJ2VGE3G",
- stampExpireDeposit: {
+ stampExpireDeposit: timestampProtocolToDb({
t_s: 1742909388,
- },
- stampExpireLegal: {
+ }),
+ stampExpireLegal: timestampProtocolToDb({
t_s: 1900589388,
- },
- stampExpireWithdraw: {
+ }),
+ stampExpireWithdraw: timestampProtocolToDb({
t_s: 1679837388,
- },
- stampStart: {
+ }),
+ stampStart: timestampProtocolToDb({
t_s: 1585229388,
- },
+ }),
verificationStatus: DenominationVerificationStatus.Unverified,
value: "KUDOS:5",
currency: "KUDOS",
- listIssueDate: { t_s: 0 },
+ listIssueDate: timestampProtocolToDb({ t_s: 0 }),
},
{
denomPub: {
@@ -228,22 +232,22 @@ test("withdrawal selection bug repro", (t) => {
isRevoked: false,
masterSig:
"E3AWGAG8VB42P3KXM8B04Z6M483SX59R3Y4T53C3NXCA2NPB6C7HVCMVX05DC6S58E9X40NGEBQNYXKYMYCF3ASY2C4WP1WCZ4ME610",
- stampExpireDeposit: {
+ stampExpireDeposit: timestampProtocolToDb({
t_s: 1742909388,
- },
- stampExpireLegal: {
+ }),
+ stampExpireLegal: timestampProtocolToDb({
t_s: 1900589388,
- },
- stampExpireWithdraw: {
+ }),
+ stampExpireWithdraw: timestampProtocolToDb({
t_s: 1679837388,
- },
- stampStart: {
+ }),
+ stampStart: timestampProtocolToDb({
t_s: 1585229388,
- },
+ }),
verificationStatus: DenominationVerificationStatus.Unverified,
value: "KUDOS:1",
currency: "KUDOS",
- listIssueDate: { t_s: 0 },
+ listIssueDate: timestampProtocolToDb({ t_s: 0 }),
},
{
denomPub: {
@@ -282,18 +286,18 @@ test("withdrawal selection bug repro", (t) => {
isRevoked: false,
masterSig:
"0ES1RKV002XB4YP21SN0QB7RSDHGYT0XAE65JYN8AVJAA6H7JZFN7JADXT521DJS89XMGPZGR8GCXF1516Y0Q9QDV00E6NMFA6CF838",
- stampExpireDeposit: {
+ stampExpireDeposit: timestampProtocolToDb({
t_s: 1742909388,
- },
- stampExpireLegal: {
+ }),
+ stampExpireLegal: timestampProtocolToDb({
t_s: 1900589388,
- },
- stampExpireWithdraw: {
+ }),
+ stampExpireWithdraw: timestampProtocolToDb({
t_s: 1679837388,
- },
- stampStart: {
+ }),
+ stampStart: timestampProtocolToDb({
t_s: 1585229388,
- },
+ }),
verificationStatus: DenominationVerificationStatus.Unverified,
value: Amounts.stringify({
currency: "KUDOS",
@@ -301,7 +305,7 @@ test("withdrawal selection bug repro", (t) => {
value: 0,
}),
currency: "KUDOS",
- listIssueDate: { t_s: 0 },
+ listIssueDate: timestampProtocolToDb({ t_s: 0 }),
},
{
denomPub: {
@@ -340,22 +344,22 @@ test("withdrawal selection bug repro", (t) => {
isRevoked: false,
masterSig:
"58QEB6C6N7602E572E3JYANVVJ9BRW0V9E2ZFDW940N47YVQDK9SAFPWBN5YGT3G1742AFKQ0CYR4DM2VWV0Z0T1XMEKWN6X2EZ9M0R",
- stampExpireDeposit: {
+ stampExpireDeposit: timestampProtocolToDb({
t_s: 1742909388,
- },
- stampExpireLegal: {
+ }),
+ stampExpireLegal: timestampProtocolToDb({
t_s: 1900589388,
- },
- stampExpireWithdraw: {
+ }),
+ stampExpireWithdraw: timestampProtocolToDb({
t_s: 1679837388,
- },
- stampStart: {
+ }),
+ stampStart: timestampProtocolToDb({
t_s: 1585229388,
- },
+ }),
verificationStatus: DenominationVerificationStatus.Unverified,
value: "KUDOS:2",
currency: "KUDOS",
- listIssueDate: { t_s: 0 },
+ listIssueDate: timestampProtocolToDb({ t_s: 0 }),
},
];