diff options
author | Florian Dold <florian@dold.me> | 2023-09-13 16:08:51 +0200 |
---|---|---|
committer | Florian Dold <florian@dold.me> | 2023-09-14 19:18:01 +0200 |
commit | f4587c44fd6a6d76384cd671550890255c3fe650 (patch) | |
tree | f3eab7032e7ec4a6e49ffdf85ea57e3874b84130 | |
parent | 59ef010b0e1f1eaf938a20a46f52d7c94af7b10d (diff) |
wallet-core: use typed microsecond timestamps in DB
17 files changed, 216 insertions, 143 deletions
diff --git a/packages/taler-util/src/time.ts b/packages/taler-util/src/time.ts index 46ed37637..a63f9b296 100644 --- a/packages/taler-util/src/time.ts +++ b/packages/taler-util/src/time.ts @@ -52,6 +52,10 @@ export interface TalerProtocolTimestamp { readonly _flavor?: typeof flavor_TalerProtocolTimestamp; } +/** + * Precise timestamp, typically used in the wallet-core + * API but not in other Taler APIs so far. + */ export interface TalerPreciseTimestamp { /** * Seconds (as integer) since epoch. diff --git a/packages/taler-wallet-core/src/db.ts b/packages/taler-wallet-core/src/db.ts index 9bf9a29cc..cebe3635b 100644 --- a/packages/taler-wallet-core/src/db.ts +++ b/packages/taler-wallet-core/src/db.ts @@ -28,7 +28,6 @@ import { } from "@gnu-taler/idb-bridge"; import { AgeCommitmentProof, - AmountJson, AmountString, Amounts, AttentionInfo, @@ -45,12 +44,8 @@ import { ExchangeAuditor, ExchangeGlobalFees, HashCodeString, - InternationalizedString, Logger, - MerchantContractTerms, - MerchantInfo, PayCoinSelection, - PeerContractTerms, RefreshReason, TalerErrorDetail, TalerPreciseTimestamp, @@ -151,6 +146,53 @@ export const CURRENT_DB_CONFIG_KEY = "currentMainDbName"; */ export const WALLET_DB_MINOR_VERSION = 1; +declare const symDbProtocolTimestamp: unique symbol; + +declare const symDbPreciseTimestamp: unique symbol; + +/** + * Timestamp, stored as microseconds. + * + * Always rounded to a full second. + */ +export type DbProtocolTimestamp = number & { [symDbProtocolTimestamp]: true }; + +/** + * Timestamp, stored as microseconds. + */ +export type DbPreciseTimestamp = number & { [symDbPreciseTimestamp]: true }; + +const DB_TIMESTAMP_FOREVER = Number.MAX_SAFE_INTEGER; + +export function timestampPreciseFromDb( + dbTs: DbPreciseTimestamp, +): TalerPreciseTimestamp { + return TalerPreciseTimestamp.fromMilliseconds(Math.floor(dbTs / 1000)); +} + +export function timestampOptionalPreciseFromDb( + dbTs: DbPreciseTimestamp | undefined, +): TalerPreciseTimestamp | undefined { + if (!dbTs) { + return undefined; + } + return TalerPreciseTimestamp.fromMilliseconds(Math.floor(dbTs / 1000)); +} + +export function timestampPreciseToDb( + stamp: TalerPreciseTimestamp, +): DbPreciseTimestamp { + if (stamp.t_s === "never") { + return DB_TIMESTAMP_FOREVER as DbPreciseTimestamp; + } else { + let tUs = stamp.t_s * 1000000; + if (stamp.off_us) { + tUs == stamp.off_us; + } + return tUs as DbPreciseTimestamp; + } +} + /** * Format of the operation status code: 0x0abc_nnnn @@ -217,7 +259,7 @@ export enum WithdrawalGroupStatus { * Exchange is doing AML checks. */ PendingAml = 0x0100_0006, - SuspendedAml = 0x0100_0006, + SuspendedAml = 0x0110_0006, /** * The corresponding withdraw record has been created. @@ -268,14 +310,14 @@ export interface ReserveBankInfo { * * Set to undefined if that hasn't happened yet. */ - timestampReserveInfoPosted: TalerPreciseTimestamp | undefined; + timestampReserveInfoPosted: DbPreciseTimestamp | undefined; /** * Time when the reserve was confirmed by the bank. * * Set to undefined if not confirmed yet. */ - timestampBankConfirmed: TalerPreciseTimestamp | undefined; + timestampBankConfirmed: DbPreciseTimestamp | undefined; } /** @@ -488,7 +530,7 @@ export interface ExchangeDetailsRecord { tosAccepted: | { etag: string; - timestamp: TalerPreciseTimestamp; + timestamp: DbPreciseTimestamp; } | undefined; @@ -528,7 +570,7 @@ export interface ExchangeDetailsPointer { * Timestamp when the (masterPublicKey, currency) pointer * has been updated. */ - updateClock: TalerPreciseTimestamp; + updateClock: DbPreciseTimestamp; } export enum ExchangeEntryDbRecordStatus { @@ -567,7 +609,7 @@ export interface ExchangeEntryRecord { * * Used mostly in the UI to suggest exchanges. */ - lastWithdrawal?: TalerPreciseTimestamp; + lastWithdrawal?: DbPreciseTimestamp; /** * Pointer to the current exchange details. @@ -588,7 +630,7 @@ export interface ExchangeEntryRecord { /** * Last time when the exchange /keys info was updated. */ - lastUpdate: TalerPreciseTimestamp | undefined; + lastUpdate: DbPreciseTimestamp | undefined; /** * Next scheduled update for the exchange. @@ -816,7 +858,7 @@ export interface RewardRecord { * Has the user accepted the tip? Only after the tip has been accepted coins * withdrawn from the tip may be used. */ - acceptedTimestamp: TalerPreciseTimestamp | undefined; + acceptedTimestamp: DbPreciseTimestamp | undefined; /** * The tipped amount. @@ -869,7 +911,7 @@ export interface RewardRecord { */ merchantRewardId: string; - createdTimestamp: TalerPreciseTimestamp; + createdTimestamp: DbPreciseTimestamp; /** * The url to be redirected after the tip is accepted. @@ -880,7 +922,7 @@ export interface RewardRecord { * Timestamp for when the wallet finished picking up the tip * from the merchant. */ - pickedUpTimestamp: TalerPreciseTimestamp | undefined; + pickedUpTimestamp: DbPreciseTimestamp | undefined; status: RewardRecordStatus; } @@ -978,12 +1020,12 @@ export interface RefreshGroupRecord { */ statusPerCoin: RefreshCoinStatus[]; - timestampCreated: TalerPreciseTimestamp; + timestampCreated: DbPreciseTimestamp; /** * Timestamp when the refresh session finished. */ - timestampFinished: TalerPreciseTimestamp | undefined; + timestampFinished: DbPreciseTimestamp | undefined; } /** @@ -1208,7 +1250,7 @@ export interface PurchaseRecord { * Timestamp of the first time that sending a payment to the merchant * for this purchase was successful. */ - timestampFirstSuccessfulPay: TalerPreciseTimestamp | undefined; + timestampFirstSuccessfulPay: DbPreciseTimestamp | undefined; merchantPaySig: string | undefined; @@ -1223,19 +1265,19 @@ export interface PurchaseRecord { /** * When was the purchase record created? */ - timestamp: TalerPreciseTimestamp; + timestamp: DbPreciseTimestamp; /** * When was the purchase made? * Refers to the time that the user accepted. */ - timestampAccept: TalerPreciseTimestamp | undefined; + timestampAccept: DbPreciseTimestamp | undefined; /** * When was the last refund made? * Set to 0 if no refund was made on the purchase. */ - timestampLastRefundStatus: TalerPreciseTimestamp | undefined; + timestampLastRefundStatus: DbPreciseTimestamp | undefined; /** * Last session signature that we submitted to /pay (if any). @@ -1285,12 +1327,12 @@ export interface WalletBackupConfState { /** * Timestamp stored in the last backup. */ - lastBackupTimestamp?: TalerPreciseTimestamp; + lastBackupTimestamp?: DbPreciseTimestamp; /** * Last time we tried to do a backup. */ - lastBackupCheckTimestamp?: TalerPreciseTimestamp; + lastBackupCheckTimestamp?: DbPreciseTimestamp; lastBackupNonce?: string; } @@ -1398,12 +1440,12 @@ export interface WithdrawalGroupRecord { * When was the withdrawal operation started started? * Timestamp in milliseconds. */ - timestampStart: TalerPreciseTimestamp; + timestampStart: DbPreciseTimestamp; /** * When was the withdrawal operation completed? */ - timestampFinish?: TalerPreciseTimestamp; + timestampFinish?: DbPreciseTimestamp; /** * Current status of the reserve. @@ -1494,9 +1536,9 @@ export interface RecoupGroupRecord { exchangeBaseUrl: string; - timestampStarted: TalerPreciseTimestamp; + timestampStarted: DbPreciseTimestamp; - timestampFinished: TalerPreciseTimestamp | undefined; + timestampFinished: DbPreciseTimestamp | undefined; /** * Public keys that identify the coins being recouped @@ -1530,7 +1572,7 @@ export type BackupProviderState = } | { tag: BackupProviderStateTag.Ready; - nextBackupTimestamp: TalerPreciseTimestamp; + nextBackupTimestamp: DbPreciseTimestamp; } | { tag: BackupProviderStateTag.Retrying; @@ -1575,7 +1617,7 @@ export interface BackupProviderRecord { * Does NOT correspond to the timestamp of the backup, * which only changes when the backup content changes. */ - lastBackupCycleTimestamp?: TalerPreciseTimestamp; + lastBackupCycleTimestamp?: DbPreciseTimestamp; /** * Proposal that we're currently trying to pay for. @@ -1678,9 +1720,9 @@ export interface DepositGroupRecord { */ counterpartyEffectiveDepositAmount: AmountString; - timestampCreated: TalerPreciseTimestamp; + timestampCreated: DbPreciseTimestamp; - timestampFinished: TalerPreciseTimestamp | undefined; + timestampFinished: DbPreciseTimestamp | undefined; operationStatus: DepositOperationStatus; @@ -1791,7 +1833,7 @@ export interface PeerPushDebitRecord { purseExpiration: TalerProtocolTimestamp; - timestampCreated: TalerPreciseTimestamp; + timestampCreated: DbPreciseTimestamp; abortRefreshGroupId?: string; @@ -1864,7 +1906,7 @@ export interface PeerPullCreditRecord { contractEncNonce: string; - mergeTimestamp: TalerPreciseTimestamp; + mergeTimestamp: DbPreciseTimestamp; mergeReserveRowId: number; @@ -1916,7 +1958,7 @@ export interface PeerPushPaymentIncomingRecord { contractPriv: string; - timestamp: TalerPreciseTimestamp; + timestamp: DbPreciseTimestamp; estimatedAmountEffective: AmountString; @@ -1988,7 +2030,7 @@ export interface PeerPullPaymentIncomingRecord { contractTermsHash: string; - timestampCreated: TalerPreciseTimestamp; + timestampCreated: DbPreciseTimestamp; /** * Contract priv that we got from the other party. @@ -2095,7 +2137,7 @@ export interface UserAttentionRecord { /** * When the user mark this notification as read. */ - read: TalerPreciseTimestamp | undefined; + read: DbPreciseTimestamp | undefined; } export interface DbExchangeHandle { @@ -2139,7 +2181,7 @@ export interface RefundGroupRecord { /** * Timestamp when the refund group was created. */ - timestampCreated: TalerPreciseTimestamp; + timestampCreated: DbPreciseTimestamp; proposalId: string; @@ -2196,7 +2238,7 @@ export interface RefundItemRecord { /** * Time when the wallet became aware of the refund. */ - obtainedTime: TalerPreciseTimestamp; + obtainedTime: DbPreciseTimestamp; refundAmount: AmountString; diff --git a/packages/taler-wallet-core/src/operations/attention.ts b/packages/taler-wallet-core/src/operations/attention.ts index 7d84b43ef..1030db0a6 100644 --- a/packages/taler-wallet-core/src/operations/attention.ts +++ b/packages/taler-wallet-core/src/operations/attention.ts @@ -31,6 +31,7 @@ import { UserAttentionUnreadList, } from "@gnu-taler/taler-util"; import { InternalWalletState } from "../internal-wallet-state.js"; +import { timestampPreciseToDb } from "../index.js"; const logger = new Logger("operations/attention.ts"); @@ -94,7 +95,7 @@ export async function markAttentionRequestAsRead( if (!ua) throw Error("attention request not found"); tx.userAttention.put({ ...ua, - read: TalerPreciseTimestamp.now(), + read: timestampPreciseToDb(TalerPreciseTimestamp.now()), }); }); } diff --git a/packages/taler-wallet-core/src/operations/backup/index.ts b/packages/taler-wallet-core/src/operations/backup/index.ts index a5e8dbd42..7a2771c57 100644 --- a/packages/taler-wallet-core/src/operations/backup/index.ts +++ b/packages/taler-wallet-core/src/operations/backup/index.ts @@ -84,6 +84,9 @@ import { ConfigRecord, ConfigRecordKey, WalletBackupConfState, + timestampOptionalPreciseFromDb, + timestampPreciseFromDb, + timestampPreciseToDb, } from "../../db.js"; import { InternalWalletState } from "../../internal-wallet-state.js"; import { assertUnreachable } from "../../util/assertUnreachable.js"; @@ -259,10 +262,12 @@ async function runBackupCycleForProvider( if (!prov) { return; } - prov.lastBackupCycleTimestamp = TalerPreciseTimestamp.now(); + prov.lastBackupCycleTimestamp = timestampPreciseToDb( + TalerPreciseTimestamp.now(), + ); prov.state = { tag: BackupProviderStateTag.Ready, - nextBackupTimestamp: getNextBackupTimestamp(), + nextBackupTimestamp: timestampPreciseToDb(getNextBackupTimestamp()), }; await tx.backupProviders.put(prov); }); @@ -361,10 +366,12 @@ async function runBackupCycleForProvider( return; } prov.lastBackupHash = encodeCrock(currentBackupHash); - prov.lastBackupCycleTimestamp = TalerPreciseTimestamp.now(); + prov.lastBackupCycleTimestamp = timestampPreciseToDb( + TalerPreciseTimestamp.now(), + ); prov.state = { tag: BackupProviderStateTag.Ready, - nextBackupTimestamp: getNextBackupTimestamp(), + nextBackupTimestamp: timestampPreciseToDb(getNextBackupTimestamp()), }; await tx.backupProviders.put(prov); }); @@ -594,7 +601,9 @@ export async function addBackupProvider( if (req.activate) { oldProv.state = { tag: BackupProviderStateTag.Ready, - nextBackupTimestamp: TalerPreciseTimestamp.now(), + nextBackupTimestamp: timestampPreciseToDb( + TalerPreciseTimestamp.now(), + ), }; logger.info("setting existing backup provider to active"); await tx.backupProviders.put(oldProv); @@ -616,7 +625,9 @@ export async function addBackupProvider( if (req.activate) { state = { tag: BackupProviderStateTag.Ready, - nextBackupTimestamp: TalerPreciseTimestamp.now(), + nextBackupTimestamp: timestampPreciseToDb( + TalerPreciseTimestamp.now(), + ), }; } else { state = { @@ -840,7 +851,9 @@ export async function getBackupInfo( providers.push({ active: x.provider.state.tag !== BackupProviderStateTag.Provisional, syncProviderBaseUrl: x.provider.baseUrl, - lastSuccessfulBackupTimestamp: x.provider.lastBackupCycleTimestamp, + lastSuccessfulBackupTimestamp: timestampOptionalPreciseFromDb( + x.provider.lastBackupCycleTimestamp, + ), paymentProposalIds: x.provider.paymentProposalIds, lastError: x.provider.state.tag === BackupProviderStateTag.Retrying @@ -917,7 +930,9 @@ async function backupRecoveryTheirs( shouldRetryFreshProposal: false, state: { tag: BackupProviderStateTag.Ready, - nextBackupTimestamp: TalerPreciseTimestamp.now(), + nextBackupTimestamp: timestampPreciseToDb( + TalerPreciseTimestamp.now(), + ), }, uids: [encodeCrock(getRandomBytes(32))], }); diff --git a/packages/taler-wallet-core/src/operations/deposits.ts b/packages/taler-wallet-core/src/operations/deposits.ts index 2de8f30a1..cb40f8f22 100644 --- a/packages/taler-wallet-core/src/operations/deposits.ts +++ b/packages/taler-wallet-core/src/operations/deposits.ts @@ -73,6 +73,7 @@ import { RefreshOperationStatus, createRefreshGroup, getTotalRefreshCost, + timestampPreciseToDb, } from "../index.js"; import { InternalWalletState } from "../internal-wallet-state.js"; import { assertUnreachable } from "../util/assertUnreachable.js"; @@ -857,7 +858,9 @@ async function processDepositGroupPendingTrack( } } if (allWired) { - dg.timestampFinished = TalerPreciseTimestamp.now(); + dg.timestampFinished = timestampPreciseToDb( + TalerPreciseTimestamp.now(), + ); dg.operationStatus = DepositOperationStatus.Finished; await tx.depositGroups.put(dg); } @@ -1375,7 +1378,9 @@ export async function createDepositGroup( amount: contractData.amount, noncePriv: noncePair.priv, noncePub: noncePair.pub, - timestampCreated: AbsoluteTime.toPreciseTimestamp(now), + timestampCreated: timestampPreciseToDb( + AbsoluteTime.toPreciseTimestamp(now), + ), timestampFinished: undefined, statusPerCoin: payCoinSel.coinSel.coinPubs.map( () => DepositElementStatus.DepositPending, diff --git a/packages/taler-wallet-core/src/operations/exchanges.ts b/packages/taler-wallet-core/src/operations/exchanges.ts index 43a08ed3b..60d55252a 100644 --- a/packages/taler-wallet-core/src/operations/exchanges.ts +++ b/packages/taler-wallet-core/src/operations/exchanges.ts @@ -74,6 +74,7 @@ import { ExchangeEntryDbRecordStatus, ExchangeEntryDbUpdateStatus, isWithdrawableDenom, + timestampPreciseToDb, WalletDbReadWriteTransaction, } from "../index.js"; import { InternalWalletState, TrustInfo } from "../internal-wallet-state.js"; @@ -174,7 +175,7 @@ export async function acceptExchangeTermsOfService( if (d) { d.tosAccepted = { etag: etag || d.tosCurrentEtag, - timestamp: TalerPreciseTimestamp.now(), + timestamp: timestampPreciseToDb(TalerPreciseTimestamp.now()), }; await tx.exchangeDetails.put(d); } @@ -753,7 +754,7 @@ export async function updateExchangeFromUrlHandler( if (existingDetails?.rowId) { newDetails.rowId = existingDetails.rowId; } - r.lastUpdate = TalerPreciseTimestamp.now(); + r.lastUpdate = timestampPreciseToDb(TalerPreciseTimestamp.now()); r.nextUpdateStampMs = AbsoluteTime.toStampMs( AbsoluteTime.fromProtocolTimestamp(keysInfo.expiry), ); @@ -763,7 +764,7 @@ export async function updateExchangeFromUrlHandler( r.detailsPointer = { currency: newDetails.currency, masterPublicKey: newDetails.masterPublicKey, - updateClock: TalerPreciseTimestamp.now(), + updateClock: timestampPreciseToDb(TalerPreciseTimestamp.now()), }; } await tx.exchanges.put(r); diff --git a/packages/taler-wallet-core/src/operations/pay-merchant.ts b/packages/taler-wallet-core/src/operations/pay-merchant.ts index fe0cbeda0..97bf6e2a6 100644 --- a/packages/taler-wallet-core/src/operations/pay-merchant.ts +++ b/packages/taler-wallet-core/src/operations/pay-merchant.ts @@ -103,6 +103,7 @@ import { RefundGroupStatus, RefundItemRecord, RefundItemStatus, + timestampPreciseToDb, } from "../index.js"; import { EXCHANGE_COINS_LOCK, @@ -644,7 +645,7 @@ async function createPurchase( noncePriv: priv, noncePub: pub, claimToken, - timestamp: TalerPreciseTimestamp.now(), + timestamp: timestampPreciseToDb(TalerPreciseTimestamp.now()), merchantBaseUrl, orderId, proposalId: proposalId, @@ -717,7 +718,7 @@ async function storeFirstPaySuccess( if (purchase.purchaseStatus === PurchaseStatus.PendingPaying) { purchase.purchaseStatus = PurchaseStatus.Done; } - purchase.timestampFirstSuccessfulPay = now; + purchase.timestampFirstSuccessfulPay = timestampPreciseToDb(now); purchase.lastSessionId = sessionId; purchase.merchantPaySig = payResponse.sig; purchase.posConfirmation = payResponse.pos_confirmation; @@ -941,7 +942,9 @@ async function unblockBackup( .forEachAsync(async (bp) => { bp.state = { tag: BackupProviderStateTag.Ready, - nextBackupTimestamp: TalerPreciseTimestamp.now(), + nextBackupTimestamp: timestampPreciseToDb( + TalerPreciseTimestamp.now(), + ), }; tx.backupProviders.put(bp); }); @@ -1447,7 +1450,7 @@ export async function confirmPay( totalPayCost: Amounts.stringify(payCostInfo), }; p.lastSessionId = sessionId; - p.timestampAccept = TalerPreciseTimestamp.now(); + p.timestampAccept = timestampPreciseToDb(TalerPreciseTimestamp.now()); p.purchaseStatus = PurchaseStatus.PendingPaying; await tx.purchases.put(p); await spendCoins(ws, tx, { @@ -2791,7 +2794,7 @@ async function storeRefunds( proposalId: purchase.proposalId, refundGroupId: newRefundGroupId, status: RefundGroupStatus.Pending, - timestampCreated: now, + timestampCreated: timestampPreciseToDb(now), amountEffective: Amounts.stringify( Amounts.zeroOfCurrency(currency), ), @@ -2802,7 +2805,7 @@ async function storeRefunds( const newItem: RefundItemRecord = { coinPub: rf.coin_pub, executionTime: rf.execution_time, - obtainedTime: now, + obtainedTime: timestampPreciseToDb(now), refundAmount: rf.refund_amount, refundGroupId: newGroup.refundGroupId, rtxid: rf.rtransaction_id, diff --git a/packages/taler-wallet-core/src/operations/pay-peer-pull-credit.ts b/packages/taler-wallet-core/src/operations/pay-peer-pull-credit.ts index 0355eb152..6ec8822ab 100644 --- a/packages/taler-wallet-core/src/operations/pay-peer-pull-credit.ts +++ b/packages/taler-wallet-core/src/operations/pay-peer-pull-credit.ts @@ -60,6 +60,9 @@ import { PeerPullPaymentCreditStatus, WithdrawalGroupStatus, WithdrawalRecordType, + timestampOptionalPreciseFromDb, + timestampPreciseFromDb, + timestampPreciseToDb, updateExchangeFromUrl, } from "../index.js"; import { InternalWalletState } from "../internal-wallet-state.js"; @@ -395,12 +398,14 @@ async function handlePeerPullCreditCreatePurse( nonce: pullIni.contractEncNonce, }); + const mergeTimestamp = timestampPreciseFromDb(pullIni.mergeTimestamp); + const purseExpiration = contractTerms.purse_expiration; const sigRes = await ws.cryptoApi.signReservePurseCreate({ contractTermsHash: pullIni.contractTermsHash, flags: WalletAccountMergeFlags.CreateWithPurseFee, mergePriv: pullIni.mergePriv, - mergeTimestamp: TalerPreciseTimestamp.round(pullIni.mergeTimestamp), + mergeTimestamp: TalerPreciseTimestamp.round(mergeTimestamp), purseAmount: pullIni.amount, purseExpiration: purseExpiration, purseFee: purseFee, @@ -412,7 +417,7 @@ async function handlePeerPullCreditCreatePurse( const reservePurseReqBody: ExchangeReservePurseRequest = { merge_sig: sigRes.mergeSig, - merge_timestamp: TalerPreciseTimestamp.round(pullIni.mergeTimestamp), + merge_timestamp: TalerPreciseTimestamp.round(mergeTimestamp), h_contract_terms: pullIni.contractTermsHash, merge_pub: pullIni.mergePub, min_age: 0, @@ -695,11 +700,17 @@ async function getPreferredExchangeForCurrency( if (candidate.lastWithdrawal && !e.lastWithdrawal) { continue; } - if (candidate.lastWithdrawal && e.lastWithdrawal) { + const exchangeLastWithdrawal = timestampOptionalPreciseFromDb( + e.lastWithdrawal, + ); + const candidateLastWithdrawal = timestampOptionalPreciseFromDb( + candidate.lastWithdrawal, + ); + if (exchangeLastWithdrawal && candidateLastWithdrawal) { if ( AbsoluteTime.cmp( - AbsoluteTime.fromPreciseTimestamp(e.lastWithdrawal), - AbsoluteTime.fromPreciseTimestamp(candidate.lastWithdrawal), + AbsoluteTime.fromPreciseTimestamp(exchangeLastWithdrawal), + AbsoluteTime.fromPreciseTimestamp(candidateLastWithdrawal), ) > 0 ) { candidate = e; @@ -741,8 +752,6 @@ export async function initiatePeerPullPayment( exchangeBaseUrl: exchangeBaseUrl, }); - const mergeTimestamp = TalerPreciseTimestamp.now(); - const pursePair = await ws.cryptoApi.createEddsaKeypair({}); const mergePair = await ws.cryptoApi.createEddsaKeypair({}); @@ -766,6 +775,8 @@ export async function initiatePeerPullPayment( undefined, ); + const mergeTimestamp = TalerPreciseTimestamp.now(); + const transitionInfo = await ws.db .mktx((x) => [x.peerPullCredit, x.contractTerms]) .runReadWrite(async (tx) => { @@ -778,7 +789,7 @@ export async function initiatePeerPullPayment( mergePriv: mergePair.priv, mergePub: mergePair.pub, status: PeerPullPaymentCreditStatus.PendingCreatePurse, - mergeTimestamp, + mergeTimestamp: timestampPreciseToDb(mergeTimestamp), contractEncNonce, mergeReserveRowId: mergeReserveRowId, contractPriv: contractKeyPair.priv, diff --git a/packages/taler-wallet-core/src/operations/pay-peer-pull-debit.ts b/packages/taler-wallet-core/src/operations/pay-peer-pull-debit.ts index 5bcfa3418..48cbf574f 100644 --- a/packages/taler-wallet-core/src/operations/pay-peer-pull-debit.ts +++ b/packages/taler-wallet-core/src/operations/pay-peer-pull-debit.ts @@ -59,6 +59,7 @@ import { PendingTaskType, RefreshOperationStatus, createRefreshGroup, + timestampPreciseToDb, } from "../index.js"; import { assertUnreachable } from "../util/assertUnreachable.js"; import { checkLogicInvariant } from "../util/invariants.js"; @@ -595,7 +596,7 @@ export async function preparePeerPullDebit( contractPriv: contractPriv, exchangeBaseUrl: exchangeBaseUrl, pursePub: pursePub, - timestampCreated: TalerPreciseTimestamp.now(), + timestampCreated: timestampPreciseToDb(TalerPreciseTimestamp.now()), contractTermsHash, amount: contractTerms.amount, status: PeerPullDebitRecordStatus.DialogProposed, diff --git a/packages/taler-wallet-core/src/operations/pay-peer-push-credit.ts b/packages/taler-wallet-core/src/operations/pay-peer-push-credit.ts index 89d9e3b49..e4698c203 100644 --- a/packages/taler-wallet-core/src/operations/pay-peer-push-credit.ts +++ b/packages/taler-wallet-core/src/operations/pay-peer-push-credit.ts @@ -59,6 +59,7 @@ import { PendingTaskType, WithdrawalGroupStatus, WithdrawalRecordType, + timestampPreciseToDb, } from "../index.js"; import { assertUnreachable } from "../util/assertUnreachable.js"; import { checkDbInvariant } from "../util/invariants.js"; @@ -129,12 +130,10 @@ export async function preparePeerPushCredit( amountEffective: existing.existingPushInc.estimatedAmountEffective, amountRaw: existing.existingContractTerms.amount, contractTerms: existing.existingContractTerms, - peerPushCreditId: - existing.existingPushInc.peerPushCreditId, + peerPushCreditId: existing.existingPushInc.peerPushCreditId, transactionId: constructTransactionIdentifier({ tag: TransactionType.PeerPushCredit, - peerPushCreditId: - existing.existingPushInc.peerPushCreditId, + peerPushCreditId: existing.existingPushInc.peerPushCreditId, }), }; } @@ -196,7 +195,7 @@ export async function preparePeerPushCredit( exchangeBaseUrl: exchangeBaseUrl, mergePriv: dec.mergePriv, pursePub: pursePub, - timestamp: TalerPreciseTimestamp.now(), + timestamp: timestampPreciseToDb(TalerPreciseTimestamp.now()), contractTermsHash, status: PeerPushCreditStatus.DialogProposed, withdrawalGroupId, @@ -263,16 +262,11 @@ async function longpollKycStatus( const transitionInfo = await ws.db .mktx((x) => [x.peerPushCredit]) .runReadWrite(async (tx) => { - const peerInc = await tx.peerPushCredit.get( - peerPushCreditId, - ); + const peerInc = await tx.peerPushCredit.get(peerPushCreditId); if (!peerInc) { return; } - if ( - peerInc.status !== - PeerPushCreditStatus.PendingMergeKycRequired - ) { + if (peerInc.status !== PeerPushCreditStatus.PendingMergeKycRequired) { return; } const oldTxState = computePeerPushCreditTransactionState(peerInc); @@ -333,9 +327,7 @@ async function processPeerPushCreditKycRequired( const { transitionInfo, result } = await ws.db .mktx((x) => [x.peerPushCredit]) .runReadWrite(async (tx) => { - const peerInc = await tx.peerPushCredit.get( - peerPushCreditId, - ); + const peerInc = await tx.peerPushCredit.get(peerPushCreditId); if (!peerInc) { return { transitionInfo: undefined, @@ -466,9 +458,7 @@ async function handlePendingMerge( x.exchangeDetails, ]) .runReadWrite(async (tx) => { - const peerInc = await tx.peerPushCredit.get( - peerPushCreditId, - ); + const peerInc = await tx.peerPushCredit.get(peerPushCreditId); if (!peerInc) { return undefined; } @@ -520,9 +510,7 @@ async function handlePendingWithdrawing( const transitionInfo = await ws.db .mktx((x) => [x.peerPushCredit, x.withdrawalGroups]) .runReadWrite(async (tx) => { - const ppi = await tx.peerPushCredit.get( - peerInc.peerPushCreditId, - ); + const ppi = await tx.peerPushCredit.get(peerInc.peerPushCreditId); if (!ppi) { finished = true; return; @@ -631,9 +619,7 @@ export async function confirmPeerPushCredit( } peerPushCreditId = parsedTx.peerPushCreditId; } else { - throw Error( - "no transaction ID (or deprecated peerPushCreditId) provided", - ); + throw Error("no transaction ID (or deprecated peerPushCreditId) provided"); } await ws.db @@ -683,9 +669,7 @@ export async function suspendPeerPushCreditTransaction( const transitionInfo = await ws.db .mktx((x) => [x.peerPushCredit]) .runReadWrite(async (tx) => { - const pushCreditRec = await tx.peerPushCredit.get( - peerPushCreditId, - ); + const pushCreditRec = await tx.peerPushCredit.get(peerPushCreditId); if (!pushCreditRec) { logger.warn(`peer push credit ${peerPushCreditId} not found`); return; @@ -746,9 +730,7 @@ export async function abortPeerPushCreditTransaction( const transitionInfo = await ws.db .mktx((x) => [x.peerPushCredit]) .runReadWrite(async (tx) => { - const pushCreditRec = await tx.peerPushCredit.get( - peerPushCreditId, - ); + const pushCreditRec = await tx.peerPushCredit.get(peerPushCreditId); if (!pushCreditRec) { logger.warn(`peer push credit ${peerPushCreditId} not found`); return; @@ -820,9 +802,7 @@ export async function resumePeerPushCreditTransaction( const transitionInfo = await ws.db .mktx((x) => [x.peerPushCredit]) .runReadWrite(async (tx) => { - const pushCreditRec = await tx.peerPushCredit.get( - peerPushCreditId, - ); + const pushCreditRec = await tx.peerPushCredit.get(peerPushCreditId); if (!pushCreditRec) { logger.warn(`peer push credit ${peerPushCreditId} not found`); return; 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 e80ffc059..b3d0eb132 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 @@ -55,6 +55,7 @@ import { PeerPushDebitStatus, RefreshOperationStatus, createRefreshGroup, + timestampPreciseToDb, } from "../index.js"; import { InternalWalletState } from "../internal-wallet-state.js"; import { PendingTaskType } from "../pending-types.js"; @@ -669,7 +670,7 @@ export async function initiatePeerPushDebit( purseExpiration: purseExpiration, pursePriv: pursePair.priv, pursePub: pursePair.pub, - timestampCreated: TalerPreciseTimestamp.now(), + timestampCreated: timestampPreciseToDb(TalerPreciseTimestamp.now()), status: PeerPushDebitStatus.PendingCreatePurse, contractEncNonce, coinSel: { diff --git a/packages/taler-wallet-core/src/operations/pending.ts b/packages/taler-wallet-core/src/operations/pending.ts index 6115f848b..120d316ce 100644 --- a/packages/taler-wallet-core/src/operations/pending.ts +++ b/packages/taler-wallet-core/src/operations/pending.ts @@ -47,6 +47,7 @@ import { ExchangeEntryDbUpdateStatus, RefreshOperationStatus, DepositElementStatus, + timestampPreciseFromDb, } from "../db.js"; import { PendingOperationsResponse, @@ -445,7 +446,7 @@ async function gatherBackupPending( const retryRecord = await tx.operationRetries.get(opId); if (bp.state.tag === BackupProviderStateTag.Ready) { const timestampDue = AbsoluteTime.fromPreciseTimestamp( - bp.state.nextBackupTimestamp, + timestampPreciseFromDb(bp.state.nextBackupTimestamp), ); resp.pendingOperations.push({ type: PendingTaskType.Backup, diff --git a/packages/taler-wallet-core/src/operations/recoup.ts b/packages/taler-wallet-core/src/operations/recoup.ts index 6a18e5de6..782e98d1c 100644 --- a/packages/taler-wallet-core/src/operations/recoup.ts +++ b/packages/taler-wallet-core/src/operations/recoup.ts @@ -47,6 +47,7 @@ import { WithdrawCoinSource, WithdrawalGroupStatus, WithdrawalRecordType, + timestampPreciseToDb, } from "../db.js"; import { InternalWalletState } from "../internal-wallet-state.js"; import { checkDbInvariant } from "../util/invariants.js"; @@ -391,7 +392,7 @@ export async function processRecoupGroup( if (!rg2) { return; } - rg2.timestampFinished = TalerPreciseTimestamp.now(); + rg2.timestampFinished = timestampPreciseToDb(TalerPreciseTimestamp.now()); if (rg2.scheduleRefreshCoins.length > 0) { const refreshGroupId = await createRefreshGroup( ws, @@ -424,7 +425,7 @@ export async function createRecoupGroup( exchangeBaseUrl: exchangeBaseUrl, coinPubs: coinPubs, timestampFinished: undefined, - timestampStarted: TalerPreciseTimestamp.now(), + timestampStarted: timestampPreciseToDb(TalerPreciseTimestamp.now()), recoupFinishedPerCoin: coinPubs.map(() => false), scheduleRefreshCoins: [], }; diff --git a/packages/taler-wallet-core/src/operations/refresh.ts b/packages/taler-wallet-core/src/operations/refresh.ts index 75adbc860..dc1d53627 100644 --- a/packages/taler-wallet-core/src/operations/refresh.ts +++ b/packages/taler-wallet-core/src/operations/refresh.ts @@ -80,6 +80,7 @@ import { isWithdrawableDenom, PendingTaskType, RefreshSessionRecord, + timestampPreciseToDb, } from "../index.js"; import { EXCHANGE_COINS_LOCK, @@ -157,10 +158,10 @@ function updateGroupStatus(rg: RefreshGroupRecord): { final: boolean } { ); if (allFinal) { if (anyFailed) { - rg.timestampFinished = TalerPreciseTimestamp.now(); + rg.timestampFinished = timestampPreciseToDb(TalerPreciseTimestamp.now()); rg.operationStatus = RefreshOperationStatus.Failed; } else { - rg.timestampFinished = TalerPreciseTimestamp.now(); + rg.timestampFinished = timestampPreciseToDb(TalerPreciseTimestamp.now()); rg.operationStatus = RefreshOperationStatus.Finished; } return { final: true }; @@ -1099,12 +1100,14 @@ export async function createRefreshGroup( expectedOutputPerCoin: estimatedOutputPerCoin.map((x) => Amounts.stringify(x), ), - timestampCreated: TalerPreciseTimestamp.now(), + timestampCreated: timestampPreciseToDb(TalerPreciseTimestamp.now()), }; if (oldCoinPubs.length == 0) { logger.warn("created refresh group with zero coins"); - refreshGroup.timestampFinished = TalerPreciseTimestamp.now(); + refreshGroup.timestampFinished = timestampPreciseToDb( + TalerPreciseTimestamp.now(), + ); refreshGroup.operationStatus = RefreshOperationStatus.Finished; } diff --git a/packages/taler-wallet-core/src/operations/reward.ts b/packages/taler-wallet-core/src/operations/reward.ts index 6ae021174..3681dc4f5 100644 --- a/packages/taler-wallet-core/src/operations/reward.ts +++ b/packages/taler-wallet-core/src/operations/reward.ts @@ -50,6 +50,8 @@ import { DenominationRecord, RewardRecord, RewardRecordStatus, + timestampPreciseFromDb, + timestampPreciseToDb, } from "../db.js"; import { makeErrorDetail } from "@gnu-taler/taler-util"; import { InternalWalletState } from "../internal-wallet-state.js"; @@ -203,7 +205,7 @@ export async function prepareTip( exchangeBaseUrl: tipPickupStatus.exchange_url, next_url: tipPickupStatus.next_url, merchantBaseUrl: res.merchantBaseUrl, - createdTimestamp: TalerPreciseTimestamp.now(), + createdTimestamp: timestampPreciseToDb(TalerPreciseTimestamp.now()), merchantRewardId: res.merchantRewardId, rewardAmountEffective: Amounts.stringify(selectedDenoms.totalCoinValue), denomsSel: selectedDenoms, @@ -411,7 +413,7 @@ export async function processTip( return; } const oldTxState = computeRewardTransactionStatus(tr); - tr.pickedUpTimestamp = TalerPreciseTimestamp.now(); + tr.pickedUpTimestamp = timestampPreciseToDb(TalerPreciseTimestamp.now()); tr.status = RewardRecordStatus.Done; await tx.rewards.put(tr); const newTxState = computeRewardTransactionStatus(tr); @@ -448,7 +450,9 @@ export async function acceptTip( return { tipRecord }; } const oldTxState = computeRewardTransactionStatus(tipRecord); - tipRecord.acceptedTimestamp = TalerPreciseTimestamp.now(); + tipRecord.acceptedTimestamp = timestampPreciseToDb( + TalerPreciseTimestamp.now(), + ); tipRecord.status = RewardRecordStatus.PendingPickup; await tx.rewards.put(tipRecord); const newTxState = computeRewardTransactionStatus(tipRecord); diff --git a/packages/taler-wallet-core/src/operations/transactions.ts b/packages/taler-wallet-core/src/operations/transactions.ts index d7b277faf..41bdae249 100644 --- a/packages/taler-wallet-core/src/operations/transactions.ts +++ b/packages/taler-wallet-core/src/operations/transactions.ts @@ -65,7 +65,12 @@ import { WithdrawalGroupStatus, WithdrawalRecordType, } from "../db.js"; -import { GetReadOnlyAccess, WalletStoresV1 } from "../index.js"; +import { + GetReadOnlyAccess, + timestampOptionalPreciseFromDb, + timestampPreciseFromDb, + WalletStoresV1, +} from "../index.js"; import { InternalWalletState } from "../internal-wallet-state.js"; import { PendingTaskType } from "../pending-types.js"; import { assertUnreachable } from "../util/assertUnreachable.js"; @@ -470,7 +475,7 @@ function buildTransactionForPushPaymentDebit( expiration: contractTerms.purse_expiration, summary: contractTerms.summary, }, - timestamp: pi.timestampCreated, + timestamp: timestampPreciseFromDb(pi.timestampCreated), talerUri: stringifyPayPushUri({ exchangeBaseUrl: pi.exchangeBaseUrl, contractPriv: pi.contractPriv, @@ -501,7 +506,7 @@ function buildTransactionForPullPaymentDebit( expiration: contractTerms.purse_expiration, summary: contractTerms.summary, }, - timestamp: pi.timestampCreated, + timestamp: timestampPreciseFromDb(pi.timestampCreated), transactionId: constructTransactionIdentifier({ tag: TransactionType.PeerPullDebit, peerPullDebitId: pi.peerPullDebitId, @@ -543,8 +548,7 @@ function buildTransactionForPeerPullCredit( amountEffective: Amounts.stringify(wsr.denomsSel.totalCoinValue), amountRaw: Amounts.stringify(wsr.instructedAmount), exchangeBaseUrl: wsr.exchangeBaseUrl, - // Old transactions don't have it! - timestamp: pullCredit.mergeTimestamp ?? TalerPreciseTimestamp.now(), + timestamp: timestampPreciseFromDb(pullCredit.mergeTimestamp), info: { expiration: peerContractTerms.purse_expiration, summary: peerContractTerms.summary, @@ -575,8 +579,7 @@ function buildTransactionForPeerPullCredit( amountEffective: Amounts.stringify(pullCredit.estimatedAmountEffective), amountRaw: Amounts.stringify(peerContractTerms.amount), exchangeBaseUrl: pullCredit.exchangeBaseUrl, - // Old transactions don't have it! - timestamp: pullCredit.mergeTimestamp ?? TalerProtocolTimestamp.now(), + timestamp: timestampPreciseFromDb(pullCredit.mergeTimestamp), info: { expiration: peerContractTerms.purse_expiration, summary: peerContractTerms.summary, @@ -617,7 +620,7 @@ function buildTransactionForPeerPushCredit( expiration: peerContractTerms.purse_expiration, summary: peerContractTerms.summary, }, - timestamp: wsr.timestampStart, + timestamp: timestampPreciseFromDb(wsr.timestampStart), transactionId: constructTransactionIdentifier({ tag: TransactionType.PeerPushCredit, peerPushCreditId: pushInc.peerPushCreditId, @@ -640,7 +643,7 @@ function buildTransactionForPeerPushCredit( summary: peerContractTerms.summary, }, kycUrl: pushInc.kycUrl, - timestamp: pushInc.timestamp, + timestamp: timestampPreciseFromDb(pushInc.timestamp), transactionId: constructTransactionIdentifier({ tag: TransactionType.PeerPushCredit, peerPushCreditId: pushInc.peerPushCreditId, @@ -673,7 +676,7 @@ function buildTransactionForBankIntegratedWithdraw( }, kycUrl: wgRecord.kycUrl, exchangeBaseUrl: wgRecord.exchangeBaseUrl, - timestamp: wgRecord.timestampStart, + timestamp: timestampPreciseFromDb(wgRecord.timestampStart), transactionId: constructTransactionIdentifier({ tag: TransactionType.Withdrawal, withdrawalGroupId: wgRecord.withdrawalGroupId, @@ -717,7 +720,7 @@ function buildTransactionForManualWithdraw( }, kycUrl: withdrawalGroup.kycUrl, exchangeBaseUrl: withdrawalGroup.exchangeBaseUrl, - timestamp: withdrawalGroup.timestampStart, + timestamp: timestampPreciseFromDb(withdrawalGroup.timestampStart), transactionId: constructTransactionIdentifier({ tag: TransactionType.Withdrawal, withdrawalGroupId: withdrawalGroup.withdrawalGroupId, @@ -748,7 +751,7 @@ function buildTransactionForRefund( tag: TransactionType.Payment, proposalId: refundRecord.proposalId, }), - timestamp: refundRecord.timestampCreated, + timestamp: timestampPreciseFromDb(refundRecord.timestampCreated), transactionId: constructTransactionIdentifier({ tag: TransactionType.Refund, refundGroupId: refundRecord.refundGroupId, @@ -786,7 +789,7 @@ function buildTransactionForRefresh( refreshOutputAmount: Amounts.stringify(outputAmount), originatingTransactionId: refreshGroupRecord.reasonDetails?.originatingTransactionId, - timestamp: refreshGroupRecord.timestampCreated, + timestamp: timestampPreciseFromDb(refreshGroupRecord.timestampCreated), transactionId: constructTransactionIdentifier({ tag: TransactionType.Refresh, refreshGroupId: refreshGroupRecord.refreshGroupId, @@ -812,7 +815,7 @@ function buildTransactionForDeposit( txActions: computeDepositTransactionActions(dg), amountRaw: Amounts.stringify(dg.counterpartyEffectiveDepositAmount), amountEffective: Amounts.stringify(dg.totalPayCost), - timestamp: dg.timestampCreated, + timestamp: timestampPreciseFromDb(dg.timestampCreated), targetPaytoUri: dg.wire.payto_uri, wireTransferDeadline: dg.wireTransferDeadline, transactionId: constructTransactionIdentifier({ @@ -845,7 +848,7 @@ function buildTransactionForTip( txActions: computeTipTransactionActions(tipRecord), amountEffective: Amounts.stringify(tipRecord.rewardAmountEffective), amountRaw: Amounts.stringify(tipRecord.rewardAmountRaw), - timestamp: tipRecord.acceptedTimestamp, + timestamp: timestampPreciseFromDb(tipRecord.acceptedTimestamp), transactionId: constructTransactionIdentifier({ tag: TransactionType.Reward, walletRewardId: tipRecord.walletRewardId, @@ -922,7 +925,7 @@ async function buildTransactionForPurchase( : Amounts.stringify(purchaseRecord.refundAmountAwaiting), refunds, posConfirmation: purchaseRecord.posConfirmation, - timestamp, + timestamp: timestampPreciseFromDb(timestamp), transactionId: constructTransactionIdentifier({ tag: TransactionType.Payment, proposalId: purchaseRecord.proposalId, diff --git a/packages/taler-wallet-core/src/operations/withdraw.ts b/packages/taler-wallet-core/src/operations/withdraw.ts index 32e63f4f6..fb503d75f 100644 --- a/packages/taler-wallet-core/src/operations/withdraw.ts +++ b/packages/taler-wallet-core/src/operations/withdraw.ts @@ -131,6 +131,7 @@ import { ExchangeEntryDbUpdateStatus, PendingTaskType, isWithdrawableDenom, + timestampPreciseToDb, } from "../index.js"; import { TransitionInfo, @@ -1325,7 +1326,7 @@ async function processWithdrawalGroupAbortingBank( } const txStatusOld = computeWithdrawalTransactionStatus(wg); wg.status = WithdrawalGroupStatus.AbortedBank; - wg.timestampFinish = TalerPreciseTimestamp.now(); + wg.timestampFinish = timestampPreciseToDb(TalerPreciseTimestamp.now()); const txStatusNew = computeWithdrawalTransactionStatus(wg); await tx.withdrawalGroups.put(wg); return { @@ -1458,7 +1459,7 @@ async function processWithdrawalGroupPendingReady( } const txStatusOld = computeWithdrawalTransactionStatus(wg); wg.status = WithdrawalGroupStatus.Done; - wg.timestampFinish = TalerPreciseTimestamp.now(); + wg.timestampFinish = timestampPreciseToDb(TalerPreciseTimestamp.now()); const txStatusNew = computeWithdrawalTransactionStatus(wg); await tx.withdrawalGroups.put(wg); return { @@ -1554,7 +1555,7 @@ async function processWithdrawalGroupPendingReady( const oldTxState = computeWithdrawalTransactionStatus(wg); logger.info(`now withdrawn ${numFinished} of ${numTotalCoins} coins`); if (wg.timestampFinish === undefined && numFinished === numTotalCoins) { - wg.timestampFinish = TalerPreciseTimestamp.now(); + wg.timestampFinish = timestampPreciseToDb(TalerPreciseTimestamp.now()); wg.status = WithdrawalGroupStatus.Done; await makeCoinsVisible(ws, tx, transactionId); } @@ -2047,8 +2048,9 @@ async function registerReserveWithBank( if (r.wgInfo.withdrawalType !== WithdrawalRecordType.BankIntegrated) { throw Error("invariant failed"); } - r.wgInfo.bankInfo.timestampReserveInfoPosted = - AbsoluteTime.toPreciseTimestamp(AbsoluteTime.now()); + r.wgInfo.bankInfo.timestampReserveInfoPosted = timestampPreciseToDb( + AbsoluteTime.toPreciseTimestamp(AbsoluteTime.now()), + ); const oldTxState = computeWithdrawalTransactionStatus(r); r.status = WithdrawalGroupStatus.PendingWaitConfirmBank; const newTxState = computeWithdrawalTransactionStatus(r); @@ -2130,7 +2132,7 @@ async function processReserveBankStatus( } const now = AbsoluteTime.toPreciseTimestamp(AbsoluteTime.now()); const oldTxState = computeWithdrawalTransactionStatus(r); - r.wgInfo.bankInfo.timestampBankConfirmed = now; + r.wgInfo.bankInfo.timestampBankConfirmed = timestampPreciseToDb(now); r.status = WithdrawalGroupStatus.FailedBankAborted; const newTxState = computeWithdrawalTransactionStatus(r); await tx.withdrawalGroups.put(r); @@ -2179,7 +2181,7 @@ async function processReserveBankStatus( if (status.transfer_done) { logger.info("withdrawal: transfer confirmed by bank."); const now = AbsoluteTime.toPreciseTimestamp(AbsoluteTime.now()); - r.wgInfo.bankInfo.timestampBankConfirmed = now; + r.wgInfo.bankInfo.timestampBankConfirmed = timestampPreciseToDb(now); r.status = WithdrawalGroupStatus.PendingQueryingStatus; } else { logger.info("withdrawal: transfer not yet confirmed by bank"); @@ -2285,7 +2287,7 @@ export async function internalPrepareCreateWithdrawalGroup( denomsSel: initialDenomSel, exchangeBaseUrl: canonExchange, instructedAmount: Amounts.stringify(amount), - timestampStart: now, + timestampStart: timestampPreciseToDb(now), rawWithdrawalAmount: initialDenomSel.totalWithdrawCost, effectiveWithdrawalAmount: initialDenomSel.totalCoinValue, secretSeed, @@ -2339,8 +2341,7 @@ export async function internalPerformCreateWithdrawalGroup( if (!prep.creationInfo) { return { withdrawalGroup, transitionInfo: undefined }; } - const { amount, canonExchange, exchangeDetails } = - prep.creationInfo; + const { amount, canonExchange, exchangeDetails } = prep.creationInfo; await tx.withdrawalGroups.add(withdrawalGroup); await tx.reserves.put({ @@ -2350,7 +2351,7 @@ export async function internalPerformCreateWithdrawalGroup( const exchange = await tx.exchanges.get(withdrawalGroup.exchangeBaseUrl); if (exchange) { - exchange.lastWithdrawal = TalerPreciseTimestamp.now(); + exchange.lastWithdrawal = timestampPreciseToDb(TalerPreciseTimestamp.now()); exchange.entryStatus = ExchangeEntryDbRecordStatus.Used; await tx.exchanges.put(exchange); } @@ -2541,11 +2542,7 @@ export async function createManualWithdrawal( }); const exchangePaytoUris = await ws.db - .mktx((x) => [ - x.withdrawalGroups, - x.exchanges, - x.exchangeDetails, - ]) + .mktx((x) => [x.withdrawalGroups, x.exchanges, x.exchangeDetails]) .runReadOnly(async (tx) => { return await getFundingPaytoUris(tx, withdrawalGroup.withdrawalGroupId); }); |