taler-util,wallet-core: implement TalerPreciseTimestamp

Fixes #7703
This commit is contained in:
Florian Dold 2023-05-26 12:19:32 +02:00
parent 557dcec30d
commit cd8f76db61
No known key found for this signature in database
GPG Key ID: D2E4F00F29D02A4B
44 changed files with 274 additions and 208 deletions

View File

@ -1473,7 +1473,7 @@ async function updateUploadFees(
x, x,
).amount; ).amount;
}; };
const expirationTime = AbsoluteTime.fromTimestamp(expiration); const expirationTime = AbsoluteTime.fromProtocolTimestamp(expiration);
const years = Duration.toIntegerYears(Duration.getRemaining(expirationTime)); const years = Duration.toIntegerYears(Duration.getRemaining(expirationTime));
logger.info(`computing fees for ${years} years`); logger.info(`computing fees for ${years} years`);
// For now, we compute fees for *all* available providers. // For now, we compute fees for *all* available providers.

View File

@ -59,7 +59,7 @@ export async function runAgeRestrictionsPeerTest(t: GlobalTestState) {
restrictAge: 13, restrictAge: 13,
}); });
const purse_expiration = AbsoluteTime.toTimestamp( const purse_expiration = AbsoluteTime.toProtocolTimestamp(
AbsoluteTime.addDuration( AbsoluteTime.addDuration(
AbsoluteTime.now(), AbsoluteTime.now(),
Duration.fromSpec({ days: 2 }), Duration.fromSpec({ days: 2 }),

View File

@ -177,7 +177,7 @@ export async function runExchangeTimetravelTest(t: GlobalTestState) {
return { return {
denomPub: x.denom_pub, denomPub: x.denom_pub,
expireDeposit: AbsoluteTime.stringify( expireDeposit: AbsoluteTime.stringify(
AbsoluteTime.fromTimestamp(x.stamp_expire_deposit), AbsoluteTime.fromProtocolTimestamp(x.stamp_expire_deposit),
), ),
}; };
}); });
@ -186,7 +186,7 @@ export async function runExchangeTimetravelTest(t: GlobalTestState) {
return { return {
denomPub: x.denom_pub, denomPub: x.denom_pub,
expireDeposit: AbsoluteTime.stringify( expireDeposit: AbsoluteTime.stringify(
AbsoluteTime.fromTimestamp(x.stamp_expire_deposit), AbsoluteTime.fromProtocolTimestamp(x.stamp_expire_deposit),
), ),
}; };
}); });
@ -196,7 +196,7 @@ export async function runExchangeTimetravelTest(t: GlobalTestState) {
console.log( console.log(
"list issue date", "list issue date",
AbsoluteTime.stringify(AbsoluteTime.fromTimestamp(keys1.list_issue_date)), AbsoluteTime.stringify(AbsoluteTime.fromProtocolTimestamp(keys1.list_issue_date)),
); );
console.log("num denoms", keys1.denoms.length); console.log("num denoms", keys1.denoms.length);
console.log("denoms", JSON.stringify(denomPubs1, undefined, 2)); console.log("denoms", JSON.stringify(denomPubs1, undefined, 2));
@ -205,7 +205,7 @@ export async function runExchangeTimetravelTest(t: GlobalTestState) {
console.log( console.log(
"list issue date", "list issue date",
AbsoluteTime.stringify(AbsoluteTime.fromTimestamp(keys2.list_issue_date)), AbsoluteTime.stringify(AbsoluteTime.fromProtocolTimestamp(keys2.list_issue_date)),
); );
console.log("num denoms", keys2.denoms.length); console.log("num denoms", keys2.denoms.length);
console.log("denoms", JSON.stringify(denomPubs2, undefined, 2)); console.log("denoms", JSON.stringify(denomPubs2, undefined, 2));
@ -227,7 +227,7 @@ export async function runExchangeTimetravelTest(t: GlobalTestState) {
); );
console.log( console.log(
`the new /keys response was issued ${AbsoluteTime.stringify( `the new /keys response was issued ${AbsoluteTime.stringify(
AbsoluteTime.fromTimestamp(keys2.list_issue_date), AbsoluteTime.fromProtocolTimestamp(keys2.list_issue_date),
)}`, )}`,
); );
console.log( console.log(

View File

@ -275,7 +275,7 @@ export async function runLibeufinBasicTest(t: GlobalTestState) {
summary: "Buy me!", summary: "Buy me!",
amount: "EUR:5", amount: "EUR:5",
fulfillment_url: "taler://fulfillment-success/thx", fulfillment_url: "taler://fulfillment-success/thx",
wire_transfer_deadline: AbsoluteTime.toTimestamp(AbsoluteTime.now()), wire_transfer_deadline: AbsoluteTime.toProtocolTimestamp(AbsoluteTime.now()),
}; };
await makeTestPayment(t, { wallet, merchant, order }); await makeTestPayment(t, { wallet, merchant, order });

View File

@ -75,7 +75,7 @@ export async function runPeerToPeerPullTest(t: GlobalTestState) {
await withdrawalDoneCond; await withdrawalDoneCond;
const purse_expiration = AbsoluteTime.toTimestamp( const purse_expiration = AbsoluteTime.toProtocolTimestamp(
AbsoluteTime.addDuration( AbsoluteTime.addDuration(
AbsoluteTime.now(), AbsoluteTime.now(),
Duration.fromSpec({ days: 2 }), Duration.fromSpec({ days: 2 }),

View File

@ -47,7 +47,7 @@ export async function runPeerToPeerPushTest(t: GlobalTestState) {
await wallet1.runUntilDone(); await wallet1.runUntilDone();
const purse_expiration = AbsoluteTime.toTimestamp( const purse_expiration = AbsoluteTime.toProtocolTimestamp(
AbsoluteTime.addDuration( AbsoluteTime.addDuration(
AbsoluteTime.now(), AbsoluteTime.now(),
Duration.fromSpec({ days: 2 }), Duration.fromSpec({ days: 2 }),

View File

@ -50,7 +50,7 @@ export async function runRefundGoneTest(t: GlobalTestState) {
summary: "Buy me!", summary: "Buy me!",
amount: "TESTKUDOS:5", amount: "TESTKUDOS:5",
fulfillment_url: "taler://fulfillment-success/thx", fulfillment_url: "taler://fulfillment-success/thx",
pay_deadline: AbsoluteTime.toTimestamp( pay_deadline: AbsoluteTime.toProtocolTimestamp(
AbsoluteTime.addDuration( AbsoluteTime.addDuration(
AbsoluteTime.now(), AbsoluteTime.now(),
durationFromSpec({ durationFromSpec({

View File

@ -63,7 +63,7 @@
* Imports. * Imports.
*/ */
import { DenominationPubKey, UnblindedSignature } from "./taler-types.js"; import { DenominationPubKey, UnblindedSignature } from "./taler-types.js";
import { TalerProtocolDuration, TalerProtocolTimestamp } from "./time.js"; import { TalerProtocolDuration, TalerProtocolTimestamp, TalerPreciseTimestamp } from "./time.js";
export const BACKUP_TAG = "gnu-taler-wallet-backup-content" as const; export const BACKUP_TAG = "gnu-taler-wallet-backup-content" as const;
/** /**
@ -148,7 +148,7 @@ export interface WalletBackupContentV1 {
* This timestamp should only be advanced if the content * This timestamp should only be advanced if the content
* of the backup changes. * of the backup changes.
*/ */
timestamp: TalerProtocolTimestamp; timestamp: TalerPreciseTimestamp;
/** /**
* Per-exchange data sorted by exchange master public key. * Per-exchange data sorted by exchange master public key.
@ -274,14 +274,14 @@ export type BackupWgInfo =
* *
* Set to undefined if that hasn't happened yet. * Set to undefined if that hasn't happened yet.
*/ */
timestamp_reserve_info_posted?: TalerProtocolTimestamp; timestamp_reserve_info_posted?: TalerPreciseTimestamp;
/** /**
* Time when the reserve was confirmed by the bank. * Time when the reserve was confirmed by the bank.
* *
* Set to undefined if not confirmed yet. * Set to undefined if not confirmed yet.
*/ */
timestamp_bank_confirmed?: TalerProtocolTimestamp; timestamp_bank_confirmed?: TalerPreciseTimestamp;
} }
| { | {
type: BackupWgType.PeerPullCredit; type: BackupWgType.PeerPullCredit;
@ -315,9 +315,9 @@ export interface BackupWithdrawalGroup {
exchange_base_url: string; exchange_base_url: string;
timestamp_created: TalerProtocolTimestamp; timestamp_created: TalerPreciseTimestamp;
timestamp_finish?: TalerProtocolTimestamp; timestamp_finish?: TalerPreciseTimestamp;
operation_status: BackupOperationStatus; operation_status: BackupOperationStatus;
@ -473,9 +473,9 @@ export interface BackupRecoupGroup {
/** /**
* Timestamp when the recoup was started. * Timestamp when the recoup was started.
*/ */
timestamp_created: TalerProtocolTimestamp; timestamp_created: TalerPreciseTimestamp;
timestamp_finish?: TalerProtocolTimestamp; timestamp_finish?: TalerPreciseTimestamp;
finish_clock?: TalerProtocolTimestamp; finish_clock?: TalerProtocolTimestamp;
// FIXME: Use some enum here! // FIXME: Use some enum here!
finish_is_failure?: boolean; finish_is_failure?: boolean;
@ -633,14 +633,14 @@ export interface BackupTip {
* Has the user accepted the tip? Only after the tip has been accepted coins * Has the user accepted the tip? Only after the tip has been accepted coins
* withdrawn from the tip may be used. * withdrawn from the tip may be used.
*/ */
timestamp_accepted: TalerProtocolTimestamp | undefined; timestamp_accepted: TalerPreciseTimestamp | undefined;
/** /**
* When was the tip first scanned by the wallet? * When was the tip first scanned by the wallet?
*/ */
timestamp_created: TalerProtocolTimestamp; timestamp_created: TalerPreciseTimestamp;
timestamp_finished?: TalerProtocolTimestamp; timestamp_finished?: TalerPreciseTimestamp;
finish_is_failure?: boolean; finish_is_failure?: boolean;
/** /**
@ -765,9 +765,9 @@ export interface BackupRefreshGroup {
*/ */
old_coins: BackupRefreshOldCoin[]; old_coins: BackupRefreshOldCoin[];
timestamp_created: TalerProtocolTimestamp; timestamp_created: TalerPreciseTimestamp;
timestamp_finish?: TalerProtocolTimestamp; timestamp_finish?: TalerPreciseTimestamp;
finish_is_failure?: boolean; finish_is_failure?: boolean;
} }
@ -940,7 +940,7 @@ export interface BackupPurchase {
* Timestamp of the first time that sending a payment to the merchant * Timestamp of the first time that sending a payment to the merchant
* for this purchase was successful. * for this purchase was successful.
*/ */
timestamp_first_successful_pay: TalerProtocolTimestamp | undefined; timestamp_first_successful_pay: TalerPreciseTimestamp | undefined;
/** /**
* Signature by the merchant confirming the payment. * Signature by the merchant confirming the payment.
@ -952,13 +952,13 @@ export interface BackupPurchase {
*/ */
pos_confirmation: string | undefined; pos_confirmation: string | undefined;
timestamp_proposed: TalerProtocolTimestamp; timestamp_proposed: TalerPreciseTimestamp;
/** /**
* When was the purchase made? * When was the purchase made?
* Refers to the time that the user accepted. * Refers to the time that the user accepted.
*/ */
timestamp_accepted: TalerProtocolTimestamp | undefined; timestamp_accepted: TalerPreciseTimestamp | undefined;
/** /**
* Pending refunds for the purchase. A refund is pending * Pending refunds for the purchase. A refund is pending
@ -1186,7 +1186,7 @@ export interface BackupExchange {
* *
* Used to facilitate automatic merging. * Used to facilitate automatic merging.
*/ */
update_clock: TalerProtocolTimestamp; update_clock: TalerPreciseTimestamp;
} }
/** /**
@ -1258,7 +1258,7 @@ export interface BackupExchangeDetails {
/** /**
* Timestamp when the ToS has been accepted. * Timestamp when the ToS has been accepted.
*/ */
tos_accepted_timestamp: TalerProtocolTimestamp | undefined; tos_accepted_timestamp: TalerPreciseTimestamp | undefined;
} }
export enum BackupProposalStatus { export enum BackupProposalStatus {

View File

@ -25,8 +25,9 @@ import { Codec, renderContext, Context } from "./codec.js";
declare const flavor_AbsoluteTime: unique symbol; declare const flavor_AbsoluteTime: unique symbol;
declare const flavor_TalerProtocolTimestamp: unique symbol; declare const flavor_TalerProtocolTimestamp: unique symbol;
declare const flavor_TalerWalletDbTimestamp: unique symbol; declare const flavor_TalerPreciseTimestamp: unique symbol;
// FIXME: Make this opaque!
export interface AbsoluteTime { export interface AbsoluteTime {
/** /**
* Timestamp in milliseconds. * Timestamp in milliseconds.
@ -45,7 +46,7 @@ export interface TalerProtocolTimestamp {
readonly _flavor?: typeof flavor_TalerProtocolTimestamp; readonly _flavor?: typeof flavor_TalerProtocolTimestamp;
} }
export interface TalerWalletDbTimestamp { export interface TalerPreciseTimestamp {
/** /**
* Seconds (as integer) since epoch. * Seconds (as integer) since epoch.
*/ */
@ -56,12 +57,32 @@ export interface TalerWalletDbTimestamp {
*/ */
readonly off_us?: number; readonly off_us?: number;
readonly _flavor?: typeof flavor_TalerWalletDbTimestamp; readonly _flavor?: typeof flavor_TalerPreciseTimestamp;
}
export namespace TalerPreciseTimestamp {
export function now(): TalerPreciseTimestamp {
const absNow = AbsoluteTime.now();
return AbsoluteTime.toPreciseTimestamp(absNow);
}
export function round(t: TalerPreciseTimestamp): TalerProtocolTimestamp {
return {
t_s: t.t_s,
}
}
export function fromSeconds(s: number): TalerPreciseTimestamp {
return {
t_s: Math.floor(s),
off_us: (s - Math.floor(s)) / 1000 / 1000,
};
}
} }
export namespace TalerProtocolTimestamp { export namespace TalerProtocolTimestamp {
export function now(): TalerProtocolTimestamp { export function now(): TalerProtocolTimestamp {
return AbsoluteTime.toTimestamp(AbsoluteTime.now()); return AbsoluteTime.toProtocolTimestamp(AbsoluteTime.now());
} }
export function zero(): TalerProtocolTimestamp { export function zero(): TalerProtocolTimestamp {
@ -81,6 +102,7 @@ export namespace TalerProtocolTimestamp {
t_s: s, t_s: s,
}; };
} }
export function min( export function min(
t1: TalerProtocolTimestamp, t1: TalerProtocolTimestamp,
t2: TalerProtocolTimestamp, t2: TalerProtocolTimestamp,
@ -309,7 +331,7 @@ export namespace AbsoluteTime {
return cmp(t, now()) <= 0; return cmp(t, now()) <= 0;
} }
export function fromTimestamp(t: TalerProtocolTimestamp): AbsoluteTime { export function fromProtocolTimestamp(t: TalerProtocolTimestamp): AbsoluteTime {
if (t.t_s === "never") { if (t.t_s === "never") {
return { t_ms: "never" }; return { t_ms: "never" };
} }
@ -318,7 +340,31 @@ export namespace AbsoluteTime {
}; };
} }
export function toTimestamp(at: AbsoluteTime): TalerProtocolTimestamp { export function fromPreciseTimestamp(t: TalerPreciseTimestamp): AbsoluteTime {
if (t.t_s === "never") {
return { t_ms: "never" };
}
const offsetUs = t.off_us ?? 0;
return {
t_ms: t.t_s * 1000 + offsetUs / 1000,
};
}
export function toPreciseTimestamp(at: AbsoluteTime): TalerPreciseTimestamp {
if (at.t_ms == "never") {
return {
t_s: "never",
};
}
const t_s = Math.floor(at.t_ms / 1000);
const off_us = Math.floor(1000 * (at.t_ms - t_s * 1000));
return {
t_s,
off_us,
}
}
export function toProtocolTimestamp(at: AbsoluteTime): TalerProtocolTimestamp {
if (at.t_ms === "never") { if (at.t_ms === "never") {
return { t_s: "never" }; return { t_s: "never" };
} }

View File

@ -24,7 +24,7 @@
/** /**
* Imports. * Imports.
*/ */
import { TalerProtocolTimestamp } from "./time.js"; import { TalerPreciseTimestamp, TalerProtocolTimestamp } from "./time.js";
import { import {
AmountString, AmountString,
Product, Product,
@ -141,7 +141,7 @@ export interface TransactionCommon {
type: TransactionType; type: TransactionType;
// main timestamp of the transaction // main timestamp of the transaction
timestamp: TalerProtocolTimestamp; timestamp: TalerPreciseTimestamp;
/** /**
* Transaction state, as per DD37. * Transaction state, as per DD37.

View File

@ -1112,7 +1112,7 @@ peerCli
partialContractTerms: { partialContractTerms: {
amount: args.initiatePayPull.amount, amount: args.initiatePayPull.amount,
summary: args.initiatePayPull.summary ?? "Invoice", summary: args.initiatePayPull.summary ?? "Invoice",
purse_expiration: AbsoluteTime.toTimestamp(purseExpiration), purse_expiration: AbsoluteTime.toProtocolTimestamp(purseExpiration),
}, },
}, },
); );
@ -1168,7 +1168,7 @@ peerCli
partialContractTerms: { partialContractTerms: {
amount: args.payPush.amount, amount: args.payPush.amount,
summary: args.payPush.summary ?? "Payment", summary: args.payPush.summary ?? "Payment",
purse_expiration: AbsoluteTime.toTimestamp(purseExpiration), purse_expiration: AbsoluteTime.toProtocolTimestamp(purseExpiration),
}, },
}, },
); );

View File

@ -14,7 +14,7 @@
GNU Taler; see the file COPYING. If not, see <http://www.gnu.org/licenses/> GNU Taler; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
*/ */
import { AbsoluteTime } from "@gnu-taler/taler-util"; import { AbsoluteTime, TalerErrorCode } from "@gnu-taler/taler-util";
import test from "ava"; import test from "ava";
import { CryptoDispatcher, CryptoWorkerFactory } from "./crypto-dispatcher.js"; import { CryptoDispatcher, CryptoWorkerFactory } from "./crypto-dispatcher.js";
import { import {
@ -72,7 +72,7 @@ export class MyCryptoWorker implements CryptoWorker {
id: msg.id, id: msg.id,
type: "error", type: "error",
error: { error: {
code: 42, code: TalerErrorCode.ANASTASIS_EMAIL_INVALID,
when: AbsoluteTime.now(), when: AbsoluteTime.now(),
hint: "bla", hint: "bla",
}, },

View File

@ -57,6 +57,7 @@ import {
AttentionInfo, AttentionInfo,
Logger, Logger,
CoinPublicKeyString, CoinPublicKeyString,
TalerPreciseTimestamp,
} from "@gnu-taler/taler-util"; } from "@gnu-taler/taler-util";
import { import {
DbAccess, DbAccess,
@ -236,14 +237,14 @@ export interface ReserveBankInfo {
* *
* Set to undefined if that hasn't happened yet. * Set to undefined if that hasn't happened yet.
*/ */
timestampReserveInfoPosted: TalerProtocolTimestamp | undefined; timestampReserveInfoPosted: TalerPreciseTimestamp | undefined;
/** /**
* Time when the reserve was confirmed by the bank. * Time when the reserve was confirmed by the bank.
* *
* Set to undefined if not confirmed yet. * Set to undefined if not confirmed yet.
*/ */
timestampBankConfirmed: TalerProtocolTimestamp | undefined; timestampBankConfirmed: TalerPreciseTimestamp | undefined;
} }
/** /**
@ -516,7 +517,7 @@ export interface ExchangeDetailsRecord {
tosAccepted: tosAccepted:
| { | {
etag: string; etag: string;
timestamp: TalerProtocolTimestamp; timestamp: TalerPreciseTimestamp;
} }
| undefined; | undefined;
@ -556,7 +557,7 @@ export interface ExchangeDetailsPointer {
* Timestamp when the (masterPublicKey, currency) pointer * Timestamp when the (masterPublicKey, currency) pointer
* has been updated. * has been updated.
*/ */
updateClock: TalerProtocolTimestamp; updateClock: TalerPreciseTimestamp;
} }
/** /**
@ -573,7 +574,7 @@ export interface ExchangeRecord {
* *
* Used mostly in the UI to suggest exchanges. * Used mostly in the UI to suggest exchanges.
*/ */
lastWithdrawal?: TalerProtocolTimestamp; lastWithdrawal?: TalerPreciseTimestamp;
/** /**
* Pointer to the current exchange details. * Pointer to the current exchange details.
@ -595,14 +596,14 @@ export interface ExchangeRecord {
/** /**
* Last time when the exchange was updated (both /keys and /wire). * Last time when the exchange was updated (both /keys and /wire).
*/ */
lastUpdate: TalerProtocolTimestamp | undefined; lastUpdate: TalerPreciseTimestamp | undefined;
/** /**
* Next scheduled update for the exchange. * Next scheduled update for the exchange.
* *
* (This field must always be present, so we can index on the timestamp.) * (This field must always be present, so we can index on the timestamp.)
*/ */
nextUpdate: TalerProtocolTimestamp; nextUpdate: TalerPreciseTimestamp;
lastKeysEtag: string | undefined; lastKeysEtag: string | undefined;
@ -614,7 +615,7 @@ export interface ExchangeRecord {
* Updated whenever the exchange's denominations are updated or when * Updated whenever the exchange's denominations are updated or when
* the refresh check has been done. * the refresh check has been done.
*/ */
nextRefreshCheck: TalerProtocolTimestamp; nextRefreshCheck: TalerPreciseTimestamp;
/** /**
* Public key of the reserve that we're currently using for * Public key of the reserve that we're currently using for
@ -803,7 +804,7 @@ export interface TipRecord {
* Has the user accepted the tip? Only after the tip has been accepted coins * Has the user accepted the tip? Only after the tip has been accepted coins
* withdrawn from the tip may be used. * withdrawn from the tip may be used.
*/ */
acceptedTimestamp: TalerProtocolTimestamp | undefined; acceptedTimestamp: TalerPreciseTimestamp | undefined;
/** /**
* The tipped amount. * The tipped amount.
@ -856,7 +857,7 @@ export interface TipRecord {
*/ */
merchantTipId: string; merchantTipId: string;
createdTimestamp: TalerProtocolTimestamp; createdTimestamp: TalerPreciseTimestamp;
/** /**
* The url to be redirected after the tip is accepted. * The url to be redirected after the tip is accepted.
@ -866,7 +867,7 @@ export interface TipRecord {
* Timestamp for when the wallet finished picking up the tip * Timestamp for when the wallet finished picking up the tip
* from the merchant. * from the merchant.
*/ */
pickedUpTimestamp: TalerProtocolTimestamp | undefined; pickedUpTimestamp: TalerPreciseTimestamp | undefined;
} }
export enum RefreshCoinStatus { export enum RefreshCoinStatus {
@ -974,12 +975,12 @@ export interface RefreshGroupRecord {
*/ */
statusPerCoin: RefreshCoinStatus[]; statusPerCoin: RefreshCoinStatus[];
timestampCreated: TalerProtocolTimestamp; timestampCreated: TalerPreciseTimestamp;
/** /**
* Timestamp when the refresh session finished. * Timestamp when the refresh session finished.
*/ */
timestampFinished: TalerProtocolTimestamp | undefined; timestampFinished: TalerPreciseTimestamp | undefined;
} }
/** /**
@ -1233,7 +1234,7 @@ export interface PurchaseRecord {
* Timestamp of the first time that sending a payment to the merchant * Timestamp of the first time that sending a payment to the merchant
* for this purchase was successful. * for this purchase was successful.
*/ */
timestampFirstSuccessfulPay: TalerProtocolTimestamp | undefined; timestampFirstSuccessfulPay: TalerPreciseTimestamp | undefined;
merchantPaySig: string | undefined; merchantPaySig: string | undefined;
@ -1242,13 +1243,13 @@ export interface PurchaseRecord {
/** /**
* When was the purchase record created? * When was the purchase record created?
*/ */
timestamp: TalerProtocolTimestamp; timestamp: TalerPreciseTimestamp;
/** /**
* When was the purchase made? * When was the purchase made?
* Refers to the time that the user accepted. * Refers to the time that the user accepted.
*/ */
timestampAccept: TalerProtocolTimestamp | undefined; timestampAccept: TalerPreciseTimestamp | undefined;
/** /**
* Pending refunds for the purchase. A refund is pending * Pending refunds for the purchase. A refund is pending
@ -1262,7 +1263,7 @@ export interface PurchaseRecord {
* When was the last refund made? * When was the last refund made?
* Set to 0 if no refund was made on the purchase. * Set to 0 if no refund was made on the purchase.
*/ */
timestampLastRefundStatus: TalerProtocolTimestamp | undefined; timestampLastRefundStatus: TalerPreciseTimestamp | undefined;
/** /**
* Last session signature that we submitted to /pay (if any). * Last session signature that we submitted to /pay (if any).
@ -1312,12 +1313,12 @@ export interface WalletBackupConfState {
/** /**
* Timestamp stored in the last backup. * Timestamp stored in the last backup.
*/ */
lastBackupTimestamp?: TalerProtocolTimestamp; lastBackupTimestamp?: TalerPreciseTimestamp;
/** /**
* Last time we tried to do a backup. * Last time we tried to do a backup.
*/ */
lastBackupCheckTimestamp?: TalerProtocolTimestamp; lastBackupCheckTimestamp?: TalerPreciseTimestamp;
lastBackupNonce?: string; lastBackupNonce?: string;
} }
@ -1421,12 +1422,12 @@ export interface WithdrawalGroupRecord {
* When was the withdrawal operation started started? * When was the withdrawal operation started started?
* Timestamp in milliseconds. * Timestamp in milliseconds.
*/ */
timestampStart: TalerProtocolTimestamp; timestampStart: TalerPreciseTimestamp;
/** /**
* When was the withdrawal operation completed? * When was the withdrawal operation completed?
*/ */
timestampFinish?: TalerProtocolTimestamp; timestampFinish?: TalerPreciseTimestamp;
/** /**
* Current status of the reserve. * Current status of the reserve.
@ -1517,9 +1518,9 @@ export interface RecoupGroupRecord {
exchangeBaseUrl: string; exchangeBaseUrl: string;
timestampStarted: TalerProtocolTimestamp; timestampStarted: TalerPreciseTimestamp;
timestampFinished: TalerProtocolTimestamp | undefined; timestampFinished: TalerPreciseTimestamp | undefined;
/** /**
* Public keys that identify the coins being recouped * Public keys that identify the coins being recouped
@ -1553,7 +1554,7 @@ export type BackupProviderState =
} }
| { | {
tag: BackupProviderStateTag.Ready; tag: BackupProviderStateTag.Ready;
nextBackupTimestamp: TalerProtocolTimestamp; nextBackupTimestamp: TalerPreciseTimestamp;
} }
| { | {
tag: BackupProviderStateTag.Retrying; tag: BackupProviderStateTag.Retrying;
@ -1598,7 +1599,7 @@ export interface BackupProviderRecord {
* Does NOT correspond to the timestamp of the backup, * Does NOT correspond to the timestamp of the backup,
* which only changes when the backup content changes. * which only changes when the backup content changes.
*/ */
lastBackupCycleTimestamp?: TalerProtocolTimestamp; lastBackupCycleTimestamp?: TalerPreciseTimestamp;
/** /**
* Proposal that we're currently trying to pay for. * Proposal that we're currently trying to pay for.
@ -1693,9 +1694,9 @@ export interface DepositGroupRecord {
*/ */
effectiveDepositAmount: AmountString; effectiveDepositAmount: AmountString;
timestampCreated: TalerProtocolTimestamp; timestampCreated: TalerPreciseTimestamp;
timestampFinished: TalerProtocolTimestamp | undefined; timestampFinished: TalerPreciseTimestamp | undefined;
operationStatus: DepositOperationStatus; operationStatus: DepositOperationStatus;
@ -1728,7 +1729,7 @@ export interface GhostDepositGroupRecord {
* When multiple deposits for the same contract terms hash * When multiple deposits for the same contract terms hash
* have a different timestamp, we choose the earliest one. * have a different timestamp, we choose the earliest one.
*/ */
timestamp: TalerProtocolTimestamp; timestamp: TalerPreciseTimestamp;
contractTermsHash: string; contractTermsHash: string;
@ -1821,7 +1822,7 @@ export interface PeerPushPaymentInitiationRecord {
purseExpiration: TalerProtocolTimestamp; purseExpiration: TalerProtocolTimestamp;
timestampCreated: TalerProtocolTimestamp; timestampCreated: TalerPreciseTimestamp;
/** /**
* Status of the peer push payment initiation. * Status of the peer push payment initiation.
@ -1882,7 +1883,7 @@ export interface PeerPullPaymentInitiationRecord {
contractTerms: PeerContractTerms; contractTerms: PeerContractTerms;
mergeTimestamp: TalerProtocolTimestamp; mergeTimestamp: TalerPreciseTimestamp;
mergeReserveRowId: number; mergeReserveRowId: number;
@ -1924,7 +1925,7 @@ export interface PeerPushPaymentIncomingRecord {
contractPriv: string; contractPriv: string;
timestamp: TalerProtocolTimestamp; timestamp: TalerPreciseTimestamp;
estimatedAmountEffective: AmountString; estimatedAmountEffective: AmountString;
@ -1984,7 +1985,7 @@ export interface PeerPullPaymentIncomingRecord {
contractTerms: PeerContractTerms; contractTerms: PeerContractTerms;
timestampCreated: TalerProtocolTimestamp; timestampCreated: TalerPreciseTimestamp;
/** /**
* Contract priv that we got from the other party. * Contract priv that we got from the other party.
@ -2081,7 +2082,7 @@ export interface UserAttentionRecord {
/** /**
* When the user mark this notification as read. * When the user mark this notification as read.
*/ */
read: TalerProtocolTimestamp | undefined; read: TalerPreciseTimestamp | undefined;
} }
export interface DbExchangeHandle { export interface DbExchangeHandle {
@ -2125,7 +2126,7 @@ export interface RefundGroupRecord {
/** /**
* Timestamp when the refund group was created. * Timestamp when the refund group was created.
*/ */
timestampCreated: TalerProtocolTimestamp; timestampCreated: TalerPreciseTimestamp;
proposalId: string; proposalId: string;
@ -2180,7 +2181,7 @@ export interface RefundItemRecord {
/** /**
* Time when the wallet became aware of the refund. * Time when the wallet became aware of the refund.
*/ */
obtainedTime: TalerProtocolTimestamp; obtainedTime: TalerPreciseTimestamp;
refundAmount: AmountString; refundAmount: AmountString;

View File

@ -256,7 +256,7 @@ export async function depositCoin(args: {
const depositPayto = const depositPayto =
args.depositPayto ?? "payto://x-taler-bank/localhost/foo"; args.depositPayto ?? "payto://x-taler-bank/localhost/foo";
const wireSalt = args.wireSalt ?? encodeCrock(getRandomBytes(16)); const wireSalt = args.wireSalt ?? encodeCrock(getRandomBytes(16));
const timestampNow = AbsoluteTime.toTimestamp(AbsoluteTime.now()); const timestampNow = AbsoluteTime.toProtocolTimestamp(AbsoluteTime.now());
const contractTermsHash = const contractTermsHash =
args.contractTermsHash ?? encodeCrock(getRandomBytes(64)); args.contractTermsHash ?? encodeCrock(getRandomBytes(64));
const depositTimestamp = timestampNow; const depositTimestamp = timestampNow;

View File

@ -22,6 +22,7 @@ import {
AttentionInfo, AttentionInfo,
Logger, Logger,
TalerProtocolTimestamp, TalerProtocolTimestamp,
TalerPreciseTimestamp,
UserAttentionByIdRequest, UserAttentionByIdRequest,
UserAttentionPriority, UserAttentionPriority,
UserAttentionsCountResponse, UserAttentionsCountResponse,
@ -95,7 +96,7 @@ export async function markAttentionRequestAsRead(
if (!ua) throw Error("attention request not found"); if (!ua) throw Error("attention request not found");
tx.userAttention.put({ tx.userAttention.put({
...ua, ...ua,
read: TalerProtocolTimestamp.now(), read: TalerPreciseTimestamp.now(),
}); });
}); });
} }

View File

@ -62,6 +62,7 @@ import {
Logger, Logger,
stringToBytes, stringToBytes,
WalletBackupContentV1, WalletBackupContentV1,
TalerPreciseTimestamp,
} from "@gnu-taler/taler-util"; } from "@gnu-taler/taler-util";
import { import {
CoinSourceType, CoinSourceType,
@ -521,7 +522,7 @@ export async function exportBackup(
}); });
}); });
const ts = AbsoluteTime.toTimestamp(AbsoluteTime.now()); const ts = TalerPreciseTimestamp.now();
if (!bs.lastBackupTimestamp) { if (!bs.lastBackupTimestamp) {
bs.lastBackupTimestamp = ts; bs.lastBackupTimestamp = ts;
@ -565,7 +566,7 @@ export async function exportBackup(
bs.lastBackupNonce = encodeCrock(getRandomBytes(32)); bs.lastBackupNonce = encodeCrock(getRandomBytes(32));
logger.trace( logger.trace(
`setting timestamp to ${AbsoluteTime.toIsoString( `setting timestamp to ${AbsoluteTime.toIsoString(
AbsoluteTime.fromTimestamp(ts), AbsoluteTime.fromPreciseTimestamp(ts),
)} and nonce to ${bs.lastBackupNonce}`, )} and nonce to ${bs.lastBackupNonce}`,
); );
await tx.config.put({ await tx.config.put({

View File

@ -35,6 +35,7 @@ import {
PayCoinSelection, PayCoinSelection,
RefreshReason, RefreshReason,
TalerProtocolTimestamp, TalerProtocolTimestamp,
TalerPreciseTimestamp,
WalletBackupContentV1, WalletBackupContentV1,
WireInfo, WireInfo,
} from "@gnu-taler/taler-util"; } from "@gnu-taler/taler-util";
@ -349,8 +350,8 @@ export async function importBackup(
}, },
permanent: true, permanent: true,
lastUpdate: undefined, lastUpdate: undefined,
nextUpdate: TalerProtocolTimestamp.now(), nextUpdate: TalerPreciseTimestamp.now(),
nextRefreshCheck: TalerProtocolTimestamp.now(), nextRefreshCheck: TalerPreciseTimestamp.now(),
lastKeysEtag: undefined, lastKeysEtag: undefined,
lastWireEtag: undefined, lastWireEtag: undefined,
}); });

View File

@ -71,6 +71,7 @@ import {
TalerErrorCode, TalerErrorCode,
TalerErrorDetail, TalerErrorDetail,
TalerProtocolTimestamp, TalerProtocolTimestamp,
TalerPreciseTimestamp,
URL, URL,
WalletBackupContentV1, WalletBackupContentV1,
} from "@gnu-taler/taler-util"; } from "@gnu-taler/taler-util";
@ -246,9 +247,9 @@ interface BackupForProviderArgs {
backupProviderBaseUrl: string; backupProviderBaseUrl: string;
} }
function getNextBackupTimestamp(): TalerProtocolTimestamp { function getNextBackupTimestamp(): TalerPreciseTimestamp {
// FIXME: Randomize! // FIXME: Randomize!
return AbsoluteTime.toTimestamp( return AbsoluteTime.toPreciseTimestamp(
AbsoluteTime.addDuration( AbsoluteTime.addDuration(
AbsoluteTime.now(), AbsoluteTime.now(),
durationFromSpec({ minutes: 5 }), durationFromSpec({ minutes: 5 }),
@ -329,7 +330,7 @@ async function runBackupCycleForProvider(
if (!prov) { if (!prov) {
return; return;
} }
prov.lastBackupCycleTimestamp = TalerProtocolTimestamp.now(); prov.lastBackupCycleTimestamp = TalerPreciseTimestamp.now();
prov.state = { prov.state = {
tag: BackupProviderStateTag.Ready, tag: BackupProviderStateTag.Ready,
nextBackupTimestamp: getNextBackupTimestamp(), nextBackupTimestamp: getNextBackupTimestamp(),
@ -442,7 +443,7 @@ async function runBackupCycleForProvider(
return; return;
} }
prov.lastBackupHash = encodeCrock(currentBackupHash); prov.lastBackupHash = encodeCrock(currentBackupHash);
prov.lastBackupCycleTimestamp = TalerProtocolTimestamp.now(); prov.lastBackupCycleTimestamp = TalerPreciseTimestamp.now();
prov.state = { prov.state = {
tag: BackupProviderStateTag.Ready, tag: BackupProviderStateTag.Ready,
nextBackupTimestamp: getNextBackupTimestamp(), nextBackupTimestamp: getNextBackupTimestamp(),
@ -676,7 +677,7 @@ export async function addBackupProvider(
if (req.activate) { if (req.activate) {
oldProv.state = { oldProv.state = {
tag: BackupProviderStateTag.Ready, tag: BackupProviderStateTag.Ready,
nextBackupTimestamp: TalerProtocolTimestamp.now(), nextBackupTimestamp: TalerPreciseTimestamp.now(),
}; };
logger.info("setting existing backup provider to active"); logger.info("setting existing backup provider to active");
await tx.backupProviders.put(oldProv); await tx.backupProviders.put(oldProv);
@ -698,7 +699,7 @@ export async function addBackupProvider(
if (req.activate) { if (req.activate) {
state = { state = {
tag: BackupProviderStateTag.Ready, tag: BackupProviderStateTag.Ready,
nextBackupTimestamp: TalerProtocolTimestamp.now(), nextBackupTimestamp: TalerPreciseTimestamp.now(),
}; };
} else { } else {
state = { state = {
@ -773,8 +774,8 @@ export interface ProviderInfo {
* Last communication issue with the provider. * Last communication issue with the provider.
*/ */
lastError?: TalerErrorDetail; lastError?: TalerErrorDetail;
lastSuccessfulBackupTimestamp?: TalerProtocolTimestamp; lastSuccessfulBackupTimestamp?: TalerPreciseTimestamp;
lastAttemptedBackupTimestamp?: TalerProtocolTimestamp; lastAttemptedBackupTimestamp?: TalerPreciseTimestamp;
paymentProposalIds: string[]; paymentProposalIds: string[];
backupProblem?: BackupProblem; backupProblem?: BackupProblem;
paymentStatus: ProviderPaymentStatus; paymentStatus: ProviderPaymentStatus;
@ -894,7 +895,7 @@ async function getProviderPaymentInfo(
return { return {
type: ProviderPaymentType.Paid, type: ProviderPaymentType.Paid,
paidUntil: AbsoluteTime.addDuration( paidUntil: AbsoluteTime.addDuration(
AbsoluteTime.fromTimestamp(status.contractTerms.timestamp), AbsoluteTime.fromProtocolTimestamp(status.contractTerms.timestamp),
durationFromSpec({ years: 1 }), //FIXME: take this from the contract term durationFromSpec({ years: 1 }), //FIXME: take this from the contract term
), ),
}; };
@ -1010,7 +1011,7 @@ async function backupRecoveryTheirs(
shouldRetryFreshProposal: false, shouldRetryFreshProposal: false,
state: { state: {
tag: BackupProviderStateTag.Ready, tag: BackupProviderStateTag.Ready,
nextBackupTimestamp: TalerProtocolTimestamp.now(), nextBackupTimestamp: TalerPreciseTimestamp.now(),
}, },
uids: [encodeCrock(getRandomBytes(32))], uids: [encodeCrock(getRandomBytes(32))],
}); });

View File

@ -51,6 +51,7 @@ import {
stringToBytes, stringToBytes,
TalerErrorCode, TalerErrorCode,
TalerProtocolTimestamp, TalerProtocolTimestamp,
TalerPreciseTimestamp,
TrackTransaction, TrackTransaction,
TransactionMajorState, TransactionMajorState,
TransactionMinorState, TransactionMinorState,
@ -779,7 +780,7 @@ export async function processDepositGroup(
} }
} }
if (allDepositedAndWired) { if (allDepositedAndWired) {
dg.timestampFinished = TalerProtocolTimestamp.now(); dg.timestampFinished = TalerPreciseTimestamp.now();
dg.operationStatus = DepositOperationStatus.Finished; dg.operationStatus = DepositOperationStatus.Finished;
await tx.depositGroups.put(dg); await tx.depositGroups.put(dg);
} }
@ -858,9 +859,9 @@ async function getExchangeWireFee(
} }
const fee = fees.find((x) => { const fee = fees.find((x) => {
return AbsoluteTime.isBetween( return AbsoluteTime.isBetween(
AbsoluteTime.fromTimestamp(time), AbsoluteTime.fromProtocolTimestamp(time),
AbsoluteTime.fromTimestamp(x.startStamp), AbsoluteTime.fromProtocolTimestamp(x.startStamp),
AbsoluteTime.fromTimestamp(x.endStamp), AbsoluteTime.fromProtocolTimestamp(x.endStamp),
); );
}); });
if (!fee) { if (!fee) {
@ -952,7 +953,7 @@ export async function prepareDepositGroup(
}); });
const now = AbsoluteTime.now(); const now = AbsoluteTime.now();
const nowRounded = AbsoluteTime.toTimestamp(now); const nowRounded = AbsoluteTime.toProtocolTimestamp(now);
const contractTerms: MerchantContractTerms = { const contractTerms: MerchantContractTerms = {
exchanges: exchangeInfos, exchanges: exchangeInfos,
amount: req.amount, amount: req.amount,
@ -966,7 +967,7 @@ export async function prepareDepositGroup(
wire_transfer_deadline: nowRounded, wire_transfer_deadline: nowRounded,
order_id: "", order_id: "",
h_wire: "", h_wire: "",
pay_deadline: AbsoluteTime.toTimestamp( pay_deadline: AbsoluteTime.toProtocolTimestamp(
AbsoluteTime.addDuration(now, durationFromSpec({ hours: 1 })), AbsoluteTime.addDuration(now, durationFromSpec({ hours: 1 })),
), ),
merchant: { merchant: {
@ -1066,7 +1067,7 @@ export async function createDepositGroup(
}); });
const now = AbsoluteTime.now(); const now = AbsoluteTime.now();
const nowRounded = AbsoluteTime.toTimestamp(now); const nowRounded = AbsoluteTime.toProtocolTimestamp(now);
const noncePair = await ws.cryptoApi.createEddsaKeypair({}); const noncePair = await ws.cryptoApi.createEddsaKeypair({});
const merchantPair = await ws.cryptoApi.createEddsaKeypair({}); const merchantPair = await ws.cryptoApi.createEddsaKeypair({});
const wireSalt = encodeCrock(getRandomBytes(16)); const wireSalt = encodeCrock(getRandomBytes(16));
@ -1084,7 +1085,7 @@ export async function createDepositGroup(
wire_transfer_deadline: nowRounded, wire_transfer_deadline: nowRounded,
order_id: "", order_id: "",
h_wire: wireHash, h_wire: wireHash,
pay_deadline: AbsoluteTime.toTimestamp( pay_deadline: AbsoluteTime.toProtocolTimestamp(
AbsoluteTime.addDuration(now, durationFromSpec({ hours: 1 })), AbsoluteTime.addDuration(now, durationFromSpec({ hours: 1 })),
), ),
merchant: { merchant: {
@ -1150,7 +1151,7 @@ export async function createDepositGroup(
depositGroupId, depositGroupId,
noncePriv: noncePair.priv, noncePriv: noncePair.priv,
noncePub: noncePair.pub, noncePub: noncePair.pub,
timestampCreated: AbsoluteTime.toTimestamp(now), timestampCreated: AbsoluteTime.toPreciseTimestamp(now),
timestampFinished: undefined, timestampFinished: undefined,
transactionPerCoin: payCoinSel.coinSel.coinPubs.map( transactionPerCoin: payCoinSel.coinSel.coinPubs.map(
() => DepositElementStatus.Unknown, () => DepositElementStatus.Unknown,
@ -1260,8 +1261,8 @@ export async function getCounterpartyEffectiveDepositAmount(
const fee = exchangeDetails.wireInfo.feesForType[wireType].find((x) => { const fee = exchangeDetails.wireInfo.feesForType[wireType].find((x) => {
return AbsoluteTime.isBetween( return AbsoluteTime.isBetween(
AbsoluteTime.now(), AbsoluteTime.now(),
AbsoluteTime.fromTimestamp(x.startStamp), AbsoluteTime.fromProtocolTimestamp(x.startStamp),
AbsoluteTime.fromTimestamp(x.endStamp), AbsoluteTime.fromProtocolTimestamp(x.endStamp),
); );
})?.wireFee; })?.wireFee;
if (fee) { if (fee) {
@ -1337,8 +1338,8 @@ export async function getTotalFeesForDepositAmount(
(x) => { (x) => {
return AbsoluteTime.isBetween( return AbsoluteTime.isBetween(
AbsoluteTime.now(), AbsoluteTime.now(),
AbsoluteTime.fromTimestamp(x.startStamp), AbsoluteTime.fromProtocolTimestamp(x.startStamp),
AbsoluteTime.fromTimestamp(x.endStamp), AbsoluteTime.fromProtocolTimestamp(x.endStamp),
); );
}, },
)?.wireFee; )?.wireFee;

View File

@ -43,6 +43,7 @@ import {
Recoup, Recoup,
TalerError, TalerError,
TalerErrorCode, TalerErrorCode,
TalerPreciseTimestamp,
TalerProtocolDuration, TalerProtocolDuration,
TalerProtocolTimestamp, TalerProtocolTimestamp,
URL, URL,
@ -229,7 +230,7 @@ export async function acceptExchangeTermsOfService(
if (d) { if (d) {
d.tosAccepted = { d.tosAccepted = {
etag: etag || d.tosCurrentEtag, etag: etag || d.tosCurrentEtag,
timestamp: TalerProtocolTimestamp.now(), timestamp: TalerPreciseTimestamp.now(),
}; };
await tx.exchangeDetails.put(d); await tx.exchangeDetails.put(d);
} }
@ -407,8 +408,8 @@ export async function provideExchangeRecordInTx(
baseUrl: baseUrl, baseUrl: baseUrl,
detailsPointer: undefined, detailsPointer: undefined,
lastUpdate: undefined, lastUpdate: undefined,
nextUpdate: AbsoluteTime.toTimestamp(now), nextUpdate: AbsoluteTime.toPreciseTimestamp(now),
nextRefreshCheck: AbsoluteTime.toTimestamp(now), nextRefreshCheck: AbsoluteTime.toPreciseTimestamp(now),
lastKeysEtag: undefined, lastKeysEtag: undefined,
lastWireEtag: undefined, lastWireEtag: undefined,
}; };
@ -497,7 +498,7 @@ async function downloadExchangeKeysInfo(
protocolVersion: exchangeKeysJsonUnchecked.version, protocolVersion: exchangeKeysJsonUnchecked.version,
signingKeys: exchangeKeysJsonUnchecked.signkeys, signingKeys: exchangeKeysJsonUnchecked.signkeys,
reserveClosingDelay: exchangeKeysJsonUnchecked.reserve_closing_delay, reserveClosingDelay: exchangeKeysJsonUnchecked.reserve_closing_delay,
expiry: AbsoluteTime.toTimestamp( expiry: AbsoluteTime.toProtocolTimestamp(
getExpiry(resp, { getExpiry(resp, {
minDuration: durationFromSpec({ hours: 1 }), minDuration: durationFromSpec({ hours: 1 }),
}), }),
@ -601,7 +602,9 @@ export async function updateExchangeFromUrlHandler(
if ( if (
!forceNow && !forceNow &&
exchangeDetails !== undefined && exchangeDetails !== undefined &&
!AbsoluteTime.isExpired(AbsoluteTime.fromTimestamp(exchange.nextUpdate)) !AbsoluteTime.isExpired(
AbsoluteTime.fromPreciseTimestamp(exchange.nextUpdate),
)
) { ) {
logger.info("using existing exchange info"); logger.info("using existing exchange info");
return { return {
@ -724,15 +727,17 @@ export async function updateExchangeFromUrlHandler(
if (existingDetails?.rowId) { if (existingDetails?.rowId) {
newDetails.rowId = existingDetails.rowId; newDetails.rowId = existingDetails.rowId;
} }
r.lastUpdate = TalerProtocolTimestamp.now(); r.lastUpdate = TalerPreciseTimestamp.now();
r.nextUpdate = keysInfo.expiry; r.nextUpdate = AbsoluteTime.toPreciseTimestamp(
AbsoluteTime.fromProtocolTimestamp(keysInfo.expiry),
);
// New denominations might be available. // New denominations might be available.
r.nextRefreshCheck = TalerProtocolTimestamp.now(); r.nextRefreshCheck = TalerPreciseTimestamp.now();
if (detailsPointerChanged) { if (detailsPointerChanged) {
r.detailsPointer = { r.detailsPointer = {
currency: newDetails.currency, currency: newDetails.currency,
masterPublicKey: newDetails.masterPublicKey, masterPublicKey: newDetails.masterPublicKey,
updateClock: TalerProtocolTimestamp.now(), updateClock: TalerPreciseTimestamp.now(),
}; };
} }
await tx.exchanges.put(r); await tx.exchanges.put(r);

View File

@ -66,6 +66,7 @@ import {
TalerError, TalerError,
TalerErrorCode, TalerErrorCode,
TalerErrorDetail, TalerErrorDetail,
TalerPreciseTimestamp,
TalerProtocolTimestamp, TalerProtocolTimestamp,
TalerProtocolViolationError, TalerProtocolViolationError,
TalerUriAction, TalerUriAction,
@ -621,7 +622,7 @@ async function createPurchase(
noncePriv: priv, noncePriv: priv,
noncePub: pub, noncePub: pub,
claimToken, claimToken,
timestamp: AbsoluteTime.toTimestamp(AbsoluteTime.now()), timestamp: TalerPreciseTimestamp.now(),
merchantBaseUrl, merchantBaseUrl,
orderId, orderId,
proposalId: proposalId, proposalId: proposalId,
@ -682,7 +683,7 @@ async function storeFirstPaySuccess(
tag: TransactionType.Payment, tag: TransactionType.Payment,
proposalId, proposalId,
}); });
const now = AbsoluteTime.toTimestamp(AbsoluteTime.now()); const now = AbsoluteTime.toPreciseTimestamp(AbsoluteTime.now());
const transitionInfo = await ws.db const transitionInfo = await ws.db
.mktx((x) => [x.purchases, x.contractTerms]) .mktx((x) => [x.purchases, x.contractTerms])
.runReadWrite(async (tx) => { .runReadWrite(async (tx) => {
@ -721,7 +722,7 @@ async function storeFirstPaySuccess(
const ar = Duration.fromTalerProtocolDuration(protoAr); const ar = Duration.fromTalerProtocolDuration(protoAr);
logger.info("auto_refund present"); logger.info("auto_refund present");
purchase.purchaseStatus = PurchaseStatus.QueryingAutoRefund; purchase.purchaseStatus = PurchaseStatus.QueryingAutoRefund;
purchase.autoRefundDeadline = AbsoluteTime.toTimestamp( purchase.autoRefundDeadline = AbsoluteTime.toProtocolTimestamp(
AbsoluteTime.addDuration(AbsoluteTime.now(), ar), AbsoluteTime.addDuration(AbsoluteTime.now(), ar),
); );
} }
@ -923,7 +924,7 @@ async function unblockBackup(
.forEachAsync(async (bp) => { .forEachAsync(async (bp) => {
bp.state = { bp.state = {
tag: BackupProviderStateTag.Ready, tag: BackupProviderStateTag.Ready,
nextBackupTimestamp: TalerProtocolTimestamp.now(), nextBackupTimestamp: TalerPreciseTimestamp.now(),
}; };
tx.backupProviders.put(bp); tx.backupProviders.put(bp);
}); });
@ -1422,7 +1423,7 @@ export async function confirmPay(
totalPayCost: Amounts.stringify(payCostInfo), totalPayCost: Amounts.stringify(payCostInfo),
}; };
p.lastSessionId = sessionId; p.lastSessionId = sessionId;
p.timestampAccept = TalerProtocolTimestamp.now(); p.timestampAccept = TalerPreciseTimestamp.now();
p.purchaseStatus = PurchaseStatus.Paying; p.purchaseStatus = PurchaseStatus.Paying;
await tx.purchases.put(p); await tx.purchases.put(p);
await spendCoins(ws, tx, { await spendCoins(ws, tx, {
@ -1925,7 +1926,7 @@ async function processPurchaseAutoRefund(
if ( if (
!purchase.autoRefundDeadline || !purchase.autoRefundDeadline ||
AbsoluteTime.isExpired( AbsoluteTime.isExpired(
AbsoluteTime.fromTimestamp(purchase.autoRefundDeadline), AbsoluteTime.fromProtocolTimestamp(purchase.autoRefundDeadline),
) )
) { ) {
const transitionInfo = await ws.db const transitionInfo = await ws.db
@ -2068,9 +2069,9 @@ async function processPurchaseAbortingRefund(
coin_pub: payCoinSelection.coinPubs[i], coin_pub: payCoinSelection.coinPubs[i],
refund_amount: Amounts.stringify(payCoinSelection.coinContributions[i]), refund_amount: Amounts.stringify(payCoinSelection.coinContributions[i]),
rtransaction_id: 0, rtransaction_id: 0,
execution_time: AbsoluteTime.toTimestamp( execution_time: AbsoluteTime.toProtocolTimestamp(
AbsoluteTime.addDuration( AbsoluteTime.addDuration(
AbsoluteTime.fromTimestamp(download.contractData.timestamp), AbsoluteTime.fromProtocolTimestamp(download.contractData.timestamp),
Duration.fromSpec({ seconds: 1 }), Duration.fromSpec({ seconds: 1 }),
), ),
), ),
@ -2267,7 +2268,7 @@ async function storeRefunds(
}); });
const newRefundGroupId = encodeCrock(randomBytes(32)); const newRefundGroupId = encodeCrock(randomBytes(32));
const now = TalerProtocolTimestamp.now(); const now = TalerPreciseTimestamp.now();
const download = await expectProposalDownload(ws, purchase); const download = await expectProposalDownload(ws, purchase);
const currency = Amounts.currencyOf(download.contractData.amount); const currency = Amounts.currencyOf(download.contractData.amount);

View File

@ -78,6 +78,7 @@ import {
TransactionState, TransactionState,
TransactionMajorState, TransactionMajorState,
TransactionMinorState, TransactionMinorState,
TalerPreciseTimestamp,
} from "@gnu-taler/taler-util"; } from "@gnu-taler/taler-util";
import { SpendCoinDetails } from "../crypto/cryptoImplementation.js"; import { SpendCoinDetails } from "../crypto/cryptoImplementation.js";
import { import {
@ -728,7 +729,7 @@ export async function initiatePeerPushDebit(
purseExpiration: purseExpiration, purseExpiration: purseExpiration,
pursePriv: pursePair.priv, pursePriv: pursePair.priv,
pursePub: pursePair.pub, pursePub: pursePair.pub,
timestampCreated: TalerProtocolTimestamp.now(), timestampCreated: TalerPreciseTimestamp.now(),
status: PeerPushPaymentInitiationStatus.PendingCreatePurse, status: PeerPushPaymentInitiationStatus.PendingCreatePurse,
contractTerms: contractTerms, contractTerms: contractTerms,
coinSel: { coinSel: {
@ -889,7 +890,7 @@ export async function preparePeerPushCredit(
exchangeBaseUrl: exchangeBaseUrl, exchangeBaseUrl: exchangeBaseUrl,
mergePriv: dec.mergePriv, mergePriv: dec.mergePriv,
pursePub: pursePub, pursePub: pursePub,
timestamp: TalerProtocolTimestamp.now(), timestamp: TalerPreciseTimestamp.now(),
contractTermsHash, contractTermsHash,
status: PeerPushPaymentIncomingStatus.Proposed, status: PeerPushPaymentIncomingStatus.Proposed,
withdrawalGroupId, withdrawalGroupId,
@ -1450,7 +1451,7 @@ export async function preparePeerPullDebit(
contractPriv: contractPriv, contractPriv: contractPriv,
exchangeBaseUrl: exchangeBaseUrl, exchangeBaseUrl: exchangeBaseUrl,
pursePub: pursePub, pursePub: pursePub,
timestampCreated: TalerProtocolTimestamp.now(), timestampCreated: TalerPreciseTimestamp.now(),
contractTerms, contractTerms,
status: PeerPullPaymentIncomingStatus.Proposed, status: PeerPullPaymentIncomingStatus.Proposed,
totalCostEstimated: Amounts.stringify(totalAmount), totalCostEstimated: Amounts.stringify(totalAmount),
@ -1668,7 +1669,7 @@ export async function processPeerPullCredit(
contractTermsHash: pullIni.contractTermsHash, contractTermsHash: pullIni.contractTermsHash,
flags: WalletAccountMergeFlags.CreateWithPurseFee, flags: WalletAccountMergeFlags.CreateWithPurseFee,
mergePriv: pullIni.mergePriv, mergePriv: pullIni.mergePriv,
mergeTimestamp: pullIni.mergeTimestamp, mergeTimestamp: TalerPreciseTimestamp.round(pullIni.mergeTimestamp),
purseAmount: pullIni.contractTerms.amount, purseAmount: pullIni.contractTerms.amount,
purseExpiration: purseExpiration, purseExpiration: purseExpiration,
purseFee: purseFee, purseFee: purseFee,
@ -1680,7 +1681,7 @@ export async function processPeerPullCredit(
const reservePurseReqBody: ExchangeReservePurseRequest = { const reservePurseReqBody: ExchangeReservePurseRequest = {
merge_sig: sigRes.mergeSig, merge_sig: sigRes.mergeSig,
merge_timestamp: pullIni.mergeTimestamp, merge_timestamp: TalerPreciseTimestamp.round(pullIni.mergeTimestamp),
h_contract_terms: pullIni.contractTermsHash, h_contract_terms: pullIni.contractTermsHash,
merge_pub: pullIni.mergePub, merge_pub: pullIni.mergePub,
min_age: 0, min_age: 0,
@ -1788,8 +1789,8 @@ async function getPreferredExchangeForCurrency(
if (candidate.lastWithdrawal && e.lastWithdrawal) { if (candidate.lastWithdrawal && e.lastWithdrawal) {
if ( if (
AbsoluteTime.cmp( AbsoluteTime.cmp(
AbsoluteTime.fromTimestamp(e.lastWithdrawal), AbsoluteTime.fromPreciseTimestamp(e.lastWithdrawal),
AbsoluteTime.fromTimestamp(candidate.lastWithdrawal), AbsoluteTime.fromPreciseTimestamp(candidate.lastWithdrawal),
) > 0 ) > 0
) { ) {
candidate = e; candidate = e;
@ -1874,7 +1875,7 @@ export async function initiatePeerPullPayment(
exchangeBaseUrl: exchangeBaseUrl, exchangeBaseUrl: exchangeBaseUrl,
}); });
const mergeTimestamp = TalerProtocolTimestamp.now(); const mergeTimestamp = TalerPreciseTimestamp.now();
const pursePair = await ws.cryptoApi.createEddsaKeypair({}); const pursePair = await ws.cryptoApi.createEddsaKeypair({});
const mergePair = await ws.cryptoApi.createEddsaKeypair({}); const mergePair = await ws.cryptoApi.createEddsaKeypair({});

View File

@ -79,7 +79,7 @@ async function gatherExchangePending(
const opTag = TaskIdentifiers.forExchangeUpdate(exch); const opTag = TaskIdentifiers.forExchangeUpdate(exch);
let opr = await tx.operationRetries.get(opTag); let opr = await tx.operationRetries.get(opTag);
const timestampDue = const timestampDue =
opr?.retryInfo.nextRetry ?? AbsoluteTime.fromTimestamp(exch.nextUpdate); opr?.retryInfo.nextRetry ?? AbsoluteTime.fromPreciseTimestamp(exch.nextUpdate);
resp.pendingOperations.push({ resp.pendingOperations.push({
type: PendingTaskType.ExchangeUpdate, type: PendingTaskType.ExchangeUpdate,
...getPendingCommon(ws, opTag, timestampDue), ...getPendingCommon(ws, opTag, timestampDue),
@ -94,7 +94,7 @@ async function gatherExchangePending(
resp.pendingOperations.push({ resp.pendingOperations.push({
type: PendingTaskType.ExchangeCheckRefresh, type: PendingTaskType.ExchangeCheckRefresh,
...getPendingCommon(ws, opTag, timestampDue), ...getPendingCommon(ws, opTag, timestampDue),
timestampDue: AbsoluteTime.fromTimestamp(exch.nextRefreshCheck), timestampDue: AbsoluteTime.fromPreciseTimestamp(exch.nextRefreshCheck),
givesLifeness: false, givesLifeness: false,
exchangeBaseUrl: exch.baseUrl, exchangeBaseUrl: exch.baseUrl,
}); });
@ -333,7 +333,7 @@ async function gatherBackupPending(
const opId = TaskIdentifiers.forBackup(bp); const opId = TaskIdentifiers.forBackup(bp);
const retryRecord = await tx.operationRetries.get(opId); const retryRecord = await tx.operationRetries.get(opId);
if (bp.state.tag === BackupProviderStateTag.Ready) { if (bp.state.tag === BackupProviderStateTag.Ready) {
const timestampDue = AbsoluteTime.fromTimestamp( const timestampDue = AbsoluteTime.fromPreciseTimestamp(
bp.state.nextBackupTimestamp, bp.state.nextBackupTimestamp,
); );
resp.pendingOperations.push({ resp.pendingOperations.push({

View File

@ -36,6 +36,7 @@ import {
NotificationType, NotificationType,
RefreshReason, RefreshReason,
TalerProtocolTimestamp, TalerProtocolTimestamp,
TalerPreciseTimestamp,
URL, URL,
} from "@gnu-taler/taler-util"; } from "@gnu-taler/taler-util";
import { import {
@ -424,7 +425,7 @@ export async function processRecoupGroupHandler(
if (!rg2) { if (!rg2) {
return; return;
} }
rg2.timestampFinished = TalerProtocolTimestamp.now(); rg2.timestampFinished = TalerPreciseTimestamp.now();
if (rg2.scheduleRefreshCoins.length > 0) { if (rg2.scheduleRefreshCoins.length > 0) {
const refreshGroupId = await createRefreshGroup( const refreshGroupId = await createRefreshGroup(
ws, ws,
@ -460,7 +461,7 @@ export async function createRecoupGroup(
exchangeBaseUrl: exchangeBaseUrl, exchangeBaseUrl: exchangeBaseUrl,
coinPubs: coinPubs, coinPubs: coinPubs,
timestampFinished: undefined, timestampFinished: undefined,
timestampStarted: TalerProtocolTimestamp.now(), timestampStarted: TalerPreciseTimestamp.now(),
recoupFinishedPerCoin: coinPubs.map(() => false), recoupFinishedPerCoin: coinPubs.map(() => false),
scheduleRefreshCoins: [], scheduleRefreshCoins: [],
}; };

View File

@ -48,6 +48,7 @@ import {
RefreshReason, RefreshReason,
TalerErrorCode, TalerErrorCode,
TalerErrorDetail, TalerErrorDetail,
TalerPreciseTimestamp,
TalerProtocolTimestamp, TalerProtocolTimestamp,
TransactionMajorState, TransactionMajorState,
TransactionState, TransactionState,
@ -156,10 +157,10 @@ function updateGroupStatus(rg: RefreshGroupRecord): void {
); );
if (allDone) { if (allDone) {
if (anyFrozen) { if (anyFrozen) {
rg.timestampFinished = AbsoluteTime.toTimestamp(AbsoluteTime.now()); rg.timestampFinished = TalerPreciseTimestamp.now();
rg.operationStatus = RefreshOperationStatus.FinishedWithError; rg.operationStatus = RefreshOperationStatus.FinishedWithError;
} else { } else {
rg.timestampFinished = AbsoluteTime.toTimestamp(AbsoluteTime.now()); rg.timestampFinished = TalerPreciseTimestamp.now();
rg.operationStatus = RefreshOperationStatus.Finished; rg.operationStatus = RefreshOperationStatus.Finished;
} }
} }
@ -1046,12 +1047,12 @@ export async function createRefreshGroup(
estimatedOutputPerCoin: estimatedOutputPerCoin.map((x) => estimatedOutputPerCoin: estimatedOutputPerCoin.map((x) =>
Amounts.stringify(x), Amounts.stringify(x),
), ),
timestampCreated: TalerProtocolTimestamp.now(), timestampCreated: TalerPreciseTimestamp.now(),
}; };
if (oldCoinPubs.length == 0) { if (oldCoinPubs.length == 0) {
logger.warn("created refresh group with zero coins"); logger.warn("created refresh group with zero coins");
refreshGroup.timestampFinished = TalerProtocolTimestamp.now(); refreshGroup.timestampFinished = TalerPreciseTimestamp.now();
refreshGroup.operationStatus = RefreshOperationStatus.Finished; refreshGroup.operationStatus = RefreshOperationStatus.Finished;
} }
@ -1075,8 +1076,8 @@ export async function createRefreshGroup(
* Timestamp after which the wallet would do the next check for an auto-refresh. * Timestamp after which the wallet would do the next check for an auto-refresh.
*/ */
function getAutoRefreshCheckThreshold(d: DenominationRecord): AbsoluteTime { function getAutoRefreshCheckThreshold(d: DenominationRecord): AbsoluteTime {
const expireWithdraw = AbsoluteTime.fromTimestamp(d.stampExpireWithdraw); const expireWithdraw = AbsoluteTime.fromProtocolTimestamp(d.stampExpireWithdraw);
const expireDeposit = AbsoluteTime.fromTimestamp(d.stampExpireDeposit); const expireDeposit = AbsoluteTime.fromProtocolTimestamp(d.stampExpireDeposit);
const delta = AbsoluteTime.difference(expireWithdraw, expireDeposit); const delta = AbsoluteTime.difference(expireWithdraw, expireDeposit);
const deltaDiv = durationMul(delta, 0.75); const deltaDiv = durationMul(delta, 0.75);
return AbsoluteTime.addDuration(expireWithdraw, deltaDiv); return AbsoluteTime.addDuration(expireWithdraw, deltaDiv);
@ -1086,8 +1087,8 @@ function getAutoRefreshCheckThreshold(d: DenominationRecord): AbsoluteTime {
* Timestamp after which the wallet would do an auto-refresh. * Timestamp after which the wallet would do an auto-refresh.
*/ */
function getAutoRefreshExecuteThreshold(d: DenominationRecord): AbsoluteTime { function getAutoRefreshExecuteThreshold(d: DenominationRecord): AbsoluteTime {
const expireWithdraw = AbsoluteTime.fromTimestamp(d.stampExpireWithdraw); const expireWithdraw = AbsoluteTime.fromProtocolTimestamp(d.stampExpireWithdraw);
const expireDeposit = AbsoluteTime.fromTimestamp(d.stampExpireDeposit); const expireDeposit = AbsoluteTime.fromProtocolTimestamp(d.stampExpireDeposit);
const delta = AbsoluteTime.difference(expireWithdraw, expireDeposit); const delta = AbsoluteTime.difference(expireWithdraw, expireDeposit);
const deltaDiv = durationMul(delta, 0.5); const deltaDiv = durationMul(delta, 0.5);
return AbsoluteTime.addDuration(expireWithdraw, deltaDiv); return AbsoluteTime.addDuration(expireWithdraw, deltaDiv);
@ -1174,7 +1175,7 @@ export async function autoRefresh(
logger.info( logger.info(
`next refresh check at ${AbsoluteTime.toIsoString(minCheckThreshold)}`, `next refresh check at ${AbsoluteTime.toIsoString(minCheckThreshold)}`,
); );
exchange.nextRefreshCheck = AbsoluteTime.toTimestamp(minCheckThreshold); exchange.nextRefreshCheck = AbsoluteTime.toPreciseTimestamp(minCheckThreshold);
await tx.exchanges.put(exchange); await tx.exchanges.put(exchange);
}); });
return OperationAttemptResult.finishedEmpty(); return OperationAttemptResult.finishedEmpty();

View File

@ -536,7 +536,7 @@ export async function runIntegrationTest2(
partialContractTerms: { partialContractTerms: {
amount: `${currency}:1`, amount: `${currency}:1`,
summary: "Payment Peer Push Test", summary: "Payment Peer Push Test",
purse_expiration: AbsoluteTime.toTimestamp( purse_expiration: AbsoluteTime.toProtocolTimestamp(
AbsoluteTime.addDuration( AbsoluteTime.addDuration(
AbsoluteTime.now(), AbsoluteTime.now(),
Duration.fromSpec({ hours: 1 }), Duration.fromSpec({ hours: 1 }),
@ -557,7 +557,7 @@ export async function runIntegrationTest2(
partialContractTerms: { partialContractTerms: {
amount: `${currency}:1`, amount: `${currency}:1`,
summary: "Payment Peer Pull Test", summary: "Payment Peer Pull Test",
purse_expiration: AbsoluteTime.toTimestamp( purse_expiration: AbsoluteTime.toProtocolTimestamp(
AbsoluteTime.addDuration( AbsoluteTime.addDuration(
AbsoluteTime.now(), AbsoluteTime.now(),
Duration.fromSpec({ hours: 1 }), Duration.fromSpec({ hours: 1 }),

View File

@ -33,6 +33,7 @@ import {
parseTipUri, parseTipUri,
PrepareTipResult, PrepareTipResult,
TalerErrorCode, TalerErrorCode,
TalerPreciseTimestamp,
TalerProtocolTimestamp, TalerProtocolTimestamp,
TipPlanchetDetail, TipPlanchetDetail,
TransactionMajorState, TransactionMajorState,
@ -160,7 +161,7 @@ export async function prepareTip(
exchangeBaseUrl: tipPickupStatus.exchange_url, exchangeBaseUrl: tipPickupStatus.exchange_url,
next_url: tipPickupStatus.next_url, next_url: tipPickupStatus.next_url,
merchantBaseUrl: res.merchantBaseUrl, merchantBaseUrl: res.merchantBaseUrl,
createdTimestamp: TalerProtocolTimestamp.now(), createdTimestamp: TalerPreciseTimestamp.now(),
merchantTipId: res.merchantTipId, merchantTipId: res.merchantTipId,
tipAmountEffective: Amounts.stringify(selectedDenoms.totalCoinValue), tipAmountEffective: Amounts.stringify(selectedDenoms.totalCoinValue),
denomsSel: selectedDenoms, denomsSel: selectedDenoms,
@ -365,7 +366,7 @@ export async function processTip(
if (tr.pickedUpTimestamp) { if (tr.pickedUpTimestamp) {
return; return;
} }
tr.pickedUpTimestamp = TalerProtocolTimestamp.now(); tr.pickedUpTimestamp = TalerPreciseTimestamp.now();
await tx.tips.put(tr); await tx.tips.put(tr);
for (const cr of newCoinRecords) { for (const cr of newCoinRecords) {
await makeCoinAvailable(ws, tx, cr); await makeCoinAvailable(ws, tx, cr);
@ -390,7 +391,7 @@ export async function acceptTip(
logger.error("tip not found"); logger.error("tip not found");
return undefined; return undefined;
} }
tipRecord.acceptedTimestamp = TalerProtocolTimestamp.now(); tipRecord.acceptedTimestamp = TalerPreciseTimestamp.now();
await tx.tips.put(tipRecord); await tx.tips.put(tipRecord);
return tipRecord; return tipRecord;

View File

@ -30,6 +30,7 @@ import {
stringifyPayPullUri, stringifyPayPullUri,
stringifyPayPushUri, stringifyPayPushUri,
TalerErrorCode, TalerErrorCode,
TalerPreciseTimestamp,
TalerProtocolTimestamp, TalerProtocolTimestamp,
Transaction, Transaction,
TransactionByIdRequest, TransactionByIdRequest,
@ -472,7 +473,7 @@ function buildTransactionForPeerPullCredit(
amountRaw: Amounts.stringify(wsr.instructedAmount), amountRaw: Amounts.stringify(wsr.instructedAmount),
exchangeBaseUrl: wsr.exchangeBaseUrl, exchangeBaseUrl: wsr.exchangeBaseUrl,
// Old transactions don't have it! // Old transactions don't have it!
timestamp: pullCredit.mergeTimestamp ?? TalerProtocolTimestamp.now(), timestamp: pullCredit.mergeTimestamp ?? TalerPreciseTimestamp.now(),
info: { info: {
expiration: wsr.wgInfo.contractTerms.purse_expiration, expiration: wsr.wgInfo.contractTerms.purse_expiration,
summary: wsr.wgInfo.contractTerms.summary, summary: wsr.wgInfo.contractTerms.summary,
@ -1171,8 +1172,8 @@ export async function getTransactions(
const txCmp = (h1: Transaction, h2: Transaction) => { const txCmp = (h1: Transaction, h2: Transaction) => {
const tsCmp = AbsoluteTime.cmp( const tsCmp = AbsoluteTime.cmp(
AbsoluteTime.fromTimestamp(h1.timestamp), AbsoluteTime.fromPreciseTimestamp(h1.timestamp),
AbsoluteTime.fromTimestamp(h2.timestamp), AbsoluteTime.fromPreciseTimestamp(h2.timestamp),
); );
if (tsCmp === 0) { if (tsCmp === 0) {
return Math.sign(txOrder[h1.type] - txOrder[h2.type]); return Math.sign(txOrder[h1.type] - txOrder[h2.type]);

View File

@ -66,6 +66,7 @@ import {
TransactionState, TransactionState,
TransactionMajorState, TransactionMajorState,
TransactionMinorState, TransactionMinorState,
TalerPreciseTimestamp,
} from "@gnu-taler/taler-util"; } from "@gnu-taler/taler-util";
import { EddsaKeypair } from "../crypto/cryptoImplementation.js"; import { EddsaKeypair } from "../crypto/cryptoImplementation.js";
import { import {
@ -1327,7 +1328,7 @@ export async function processWithdrawalGroup(
} }
const txStatusOld = computeWithdrawalTransactionStatus(wg); const txStatusOld = computeWithdrawalTransactionStatus(wg);
wg.status = WithdrawalGroupStatus.Finished; wg.status = WithdrawalGroupStatus.Finished;
wg.timestampFinish = TalerProtocolTimestamp.now(); wg.timestampFinish = TalerPreciseTimestamp.now();
const txStatusNew = computeWithdrawalTransactionStatus(wg); const txStatusNew = computeWithdrawalTransactionStatus(wg);
await tx.withdrawalGroups.put(wg); await tx.withdrawalGroups.put(wg);
return { return {
@ -1428,7 +1429,7 @@ export async function processWithdrawalGroup(
logger.info(`now withdrawn ${numFinished} of ${numTotalCoins} coins`); logger.info(`now withdrawn ${numFinished} of ${numTotalCoins} coins`);
if (wg.timestampFinish === undefined && numFinished === numTotalCoins) { if (wg.timestampFinish === undefined && numFinished === numTotalCoins) {
finishedForFirstTime = true; finishedForFirstTime = true;
wg.timestampFinish = TalerProtocolTimestamp.now(); wg.timestampFinish = TalerPreciseTimestamp.now();
wg.status = WithdrawalGroupStatus.Finished; wg.status = WithdrawalGroupStatus.Finished;
} }
@ -1613,8 +1614,8 @@ export async function getExchangeWithdrawalInfo(
} }
if ( if (
AbsoluteTime.cmp( AbsoluteTime.cmp(
AbsoluteTime.fromTimestamp(expireDeposit), AbsoluteTime.fromProtocolTimestamp(expireDeposit),
AbsoluteTime.fromTimestamp(earliestDepositExpiration), AbsoluteTime.fromProtocolTimestamp(earliestDepositExpiration),
) < 0 ) < 0
) { ) {
earliestDepositExpiration = expireDeposit; earliestDepositExpiration = expireDeposit;
@ -1910,7 +1911,7 @@ async function registerReserveWithBank(
if (r.wgInfo.withdrawalType !== WithdrawalRecordType.BankIntegrated) { if (r.wgInfo.withdrawalType !== WithdrawalRecordType.BankIntegrated) {
throw Error("invariant failed"); throw Error("invariant failed");
} }
r.wgInfo.bankInfo.timestampReserveInfoPosted = AbsoluteTime.toTimestamp( r.wgInfo.bankInfo.timestampReserveInfoPosted = AbsoluteTime.toPreciseTimestamp(
AbsoluteTime.now(), AbsoluteTime.now(),
); );
const oldTxState = computeWithdrawalTransactionStatus(r); const oldTxState = computeWithdrawalTransactionStatus(r);
@ -1994,7 +1995,7 @@ async function processReserveBankStatus(
if (r.wgInfo.withdrawalType !== WithdrawalRecordType.BankIntegrated) { if (r.wgInfo.withdrawalType !== WithdrawalRecordType.BankIntegrated) {
throw Error("invariant failed"); throw Error("invariant failed");
} }
const now = AbsoluteTime.toTimestamp(AbsoluteTime.now()); const now = AbsoluteTime.toPreciseTimestamp(AbsoluteTime.now());
const oldTxState = computeWithdrawalTransactionStatus(r); const oldTxState = computeWithdrawalTransactionStatus(r);
r.wgInfo.bankInfo.timestampBankConfirmed = now; r.wgInfo.bankInfo.timestampBankConfirmed = now;
r.status = WithdrawalGroupStatus.FailedBankAborted; r.status = WithdrawalGroupStatus.FailedBankAborted;
@ -2044,7 +2045,7 @@ async function processReserveBankStatus(
const oldTxState = computeWithdrawalTransactionStatus(r); const oldTxState = computeWithdrawalTransactionStatus(r);
if (status.transfer_done) { if (status.transfer_done) {
logger.info("withdrawal: transfer confirmed by bank."); logger.info("withdrawal: transfer confirmed by bank.");
const now = AbsoluteTime.toTimestamp(AbsoluteTime.now()); const now = AbsoluteTime.toPreciseTimestamp(AbsoluteTime.now());
r.wgInfo.bankInfo.timestampBankConfirmed = now; r.wgInfo.bankInfo.timestampBankConfirmed = now;
r.status = WithdrawalGroupStatus.PendingQueryingStatus; r.status = WithdrawalGroupStatus.PendingQueryingStatus;
// FIXME: Notification is deprecated with DD37. // FIXME: Notification is deprecated with DD37.
@ -2105,7 +2106,7 @@ export async function internalCreateWithdrawalGroup(
): Promise<WithdrawalGroupRecord> { ): Promise<WithdrawalGroupRecord> {
const reserveKeyPair = const reserveKeyPair =
args.reserveKeyPair ?? (await ws.cryptoApi.createEddsaKeypair({})); args.reserveKeyPair ?? (await ws.cryptoApi.createEddsaKeypair({}));
const now = AbsoluteTime.toTimestamp(AbsoluteTime.now()); const now = AbsoluteTime.toPreciseTimestamp(AbsoluteTime.now());
const secretSeed = encodeCrock(getRandomBytes(32)); const secretSeed = encodeCrock(getRandomBytes(32));
const canonExchange = canonicalizeBaseUrl(args.exchangeBaseUrl); const canonExchange = canonicalizeBaseUrl(args.exchangeBaseUrl);
const amount = args.amount; const amount = args.amount;
@ -2200,7 +2201,7 @@ export async function internalCreateWithdrawalGroup(
const exchange = await tx.exchanges.get(withdrawalGroup.exchangeBaseUrl); const exchange = await tx.exchanges.get(withdrawalGroup.exchangeBaseUrl);
if (exchange) { if (exchange) {
exchange.lastWithdrawal = TalerProtocolTimestamp.now(); exchange.lastWithdrawal = TalerPreciseTimestamp.now();
await tx.exchanges.put(exchange); await tx.exchanges.put(exchange);
} }

View File

@ -577,8 +577,8 @@ export async function selectCandidates(
]?.find((x) => { ]?.find((x) => {
return AbsoluteTime.isBetween( return AbsoluteTime.isBetween(
AbsoluteTime.now(), AbsoluteTime.now(),
AbsoluteTime.fromTimestamp(x.startStamp), AbsoluteTime.fromProtocolTimestamp(x.startStamp),
AbsoluteTime.fromTimestamp(x.endStamp), AbsoluteTime.fromProtocolTimestamp(x.endStamp),
); );
})?.wireFee; })?.wireFee;
if (wireFeeStr) { if (wireFeeStr) {

View File

@ -42,7 +42,7 @@ const VALUES: AmountString[] = Array.from({ length: 10 }).map(
(undef, t) => `USD:${t}`, (undef, t) => `USD:${t}`,
); );
const TIMESTAMPS = Array.from({ length: 20 }).map((undef, t_s) => ({ t_s })); const TIMESTAMPS = Array.from({ length: 20 }).map((undef, t_s) => ({ t_s }));
const ABS_TIME = TIMESTAMPS.map((m) => AbsoluteTime.fromTimestamp(m)); const ABS_TIME = TIMESTAMPS.map((m) => AbsoluteTime.fromProtocolTimestamp(m));
function normalize( function normalize(
list: DenominationInfo[], list: DenominationInfo[],

View File

@ -326,7 +326,7 @@ export function createTimeline<Type extends object>(
fee: Amounts.stringify(fee), fee: Amounts.stringify(fee),
group, group,
id, id,
moment: AbsoluteTime.fromTimestamp(stampStart), moment: AbsoluteTime.fromProtocolTimestamp(stampStart),
denom, denom,
}); });
ps.push({ ps.push({
@ -334,7 +334,7 @@ export function createTimeline<Type extends object>(
fee: Amounts.stringify(fee), fee: Amounts.stringify(fee),
group, group,
id, id,
moment: AbsoluteTime.fromTimestamp(stampEnd), moment: AbsoluteTime.fromProtocolTimestamp(stampEnd),
denom, denom,
}); });
return ps; return ps;
@ -457,8 +457,8 @@ export function isWithdrawableDenom(
denomselAllowLate?: boolean, denomselAllowLate?: boolean,
): boolean { ): boolean {
const now = AbsoluteTime.now(); const now = AbsoluteTime.now();
const start = AbsoluteTime.fromTimestamp(d.stampStart); const start = AbsoluteTime.fromProtocolTimestamp(d.stampStart);
const withdrawExpire = AbsoluteTime.fromTimestamp(d.stampExpireWithdraw); const withdrawExpire = AbsoluteTime.fromProtocolTimestamp(d.stampExpireWithdraw);
const started = AbsoluteTime.cmp(now, start) >= 0; const started = AbsoluteTime.cmp(now, start) >= 0;
let lastPossibleWithdraw: AbsoluteTime; let lastPossibleWithdraw: AbsoluteTime;
if (denomselAllowLate) { if (denomselAllowLate) {

View File

@ -136,7 +136,7 @@ export function PendingTransactionsView({
</Typography> </Typography>
&nbsp;-&nbsp; &nbsp;-&nbsp;
<Time <Time
timestamp={AbsoluteTime.fromTimestamp(t.timestamp)} timestamp={AbsoluteTime.fromPreciseTimestamp(t.timestamp)}
format="dd MMMM yyyy" format="dd MMMM yyyy"
/> />
</Grid> </Grid>

View File

@ -179,7 +179,7 @@ export function HiddenView({ showHandler }: States.Hidden): VNode {
} }
export function ShowView({ contractTerms, hideHandler }: States.Show): VNode { export function ShowView({ contractTerms, hideHandler }: States.Show): VNode {
const createdAt = AbsoluteTime.fromTimestamp(contractTerms.timestamp); const createdAt = AbsoluteTime.fromProtocolTimestamp(contractTerms.timestamp);
const { i18n } = useTranslationContext(); const { i18n } = useTranslationContext();
return ( return (
@ -266,7 +266,7 @@ export function ShowView({ contractTerms, hideHandler }: States.Show): VNode {
<td> <td>
{contractTerms.deliveryDate && ( {contractTerms.deliveryDate && (
<Time <Time
timestamp={AbsoluteTime.fromTimestamp( timestamp={AbsoluteTime.fromProtocolTimestamp(
contractTerms.deliveryDate, contractTerms.deliveryDate,
)} )}
format="dd MMMM yyyy, HH:mm" format="dd MMMM yyyy, HH:mm"
@ -299,7 +299,7 @@ export function ShowView({ contractTerms, hideHandler }: States.Show): VNode {
<td> <td>
{contractTerms.timestamp && ( {contractTerms.timestamp && (
<Time <Time
timestamp={AbsoluteTime.fromTimestamp( timestamp={AbsoluteTime.fromProtocolTimestamp(
contractTerms.timestamp, contractTerms.timestamp,
)} )}
format="dd MMMM yyyy, HH:mm" format="dd MMMM yyyy, HH:mm"
@ -314,7 +314,7 @@ export function ShowView({ contractTerms, hideHandler }: States.Show): VNode {
<td> <td>
{ {
<Time <Time
timestamp={AbsoluteTime.fromTimestamp( timestamp={AbsoluteTime.fromProtocolTimestamp(
contractTerms.refundDeadline, contractTerms.refundDeadline,
)} )}
format="dd MMMM yyyy, HH:mm" format="dd MMMM yyyy, HH:mm"
@ -349,7 +349,7 @@ export function ShowView({ contractTerms, hideHandler }: States.Show): VNode {
<td> <td>
{ {
<Time <Time
timestamp={AbsoluteTime.fromTimestamp( timestamp={AbsoluteTime.fromProtocolTimestamp(
contractTerms.payDeadline, contractTerms.payDeadline,
)} )}
format="dd MMMM yyyy, HH:mm" format="dd MMMM yyyy, HH:mm"

View File

@ -53,7 +53,7 @@ export function TransactionItem(props: { tx: Transaction }): VNode {
amount={tx.amountEffective} amount={tx.amountEffective}
debitCreditIndicator={"credit"} debitCreditIndicator={"credit"}
title={new URL(tx.exchangeBaseUrl).hostname} title={new URL(tx.exchangeBaseUrl).hostname}
timestamp={AbsoluteTime.fromTimestamp(tx.timestamp)} timestamp={AbsoluteTime.fromPreciseTimestamp(tx.timestamp)}
iconPath={"W"} iconPath={"W"}
pending={ pending={
tx.txState.major === TransactionMajorState.Pending tx.txState.major === TransactionMajorState.Pending
@ -76,7 +76,7 @@ export function TransactionItem(props: { tx: Transaction }): VNode {
amount={tx.amountEffective} amount={tx.amountEffective}
debitCreditIndicator={"credit"} debitCreditIndicator={"credit"}
title={new URL(tx.exchangeBaseUrl).hostname} title={new URL(tx.exchangeBaseUrl).hostname}
timestamp={AbsoluteTime.fromTimestamp(tx.timestamp)} timestamp={AbsoluteTime.fromPreciseTimestamp(tx.timestamp)}
iconPath={"I"} iconPath={"I"}
pending={ pending={
tx.txState.major === TransactionMajorState.Pending tx.txState.major === TransactionMajorState.Pending
@ -100,7 +100,7 @@ export function TransactionItem(props: { tx: Transaction }): VNode {
debitCreditIndicator={"debit"} debitCreditIndicator={"debit"}
title={tx.info.merchant.name} title={tx.info.merchant.name}
subtitle={tx.info.summary} subtitle={tx.info.summary}
timestamp={AbsoluteTime.fromTimestamp(tx.timestamp)} timestamp={AbsoluteTime.fromPreciseTimestamp(tx.timestamp)}
iconPath={"P"} iconPath={"P"}
pending={ pending={
tx.txState.major === TransactionMajorState.Pending tx.txState.major === TransactionMajorState.Pending
@ -121,7 +121,7 @@ export function TransactionItem(props: { tx: Transaction }): VNode {
? tx.paymentInfo.merchant.name ? tx.paymentInfo.merchant.name
: "--unknown merchant--" : "--unknown merchant--"
} //FIXME: DD37 wallet-core is not returning this value } //FIXME: DD37 wallet-core is not returning this value
timestamp={AbsoluteTime.fromTimestamp(tx.timestamp)} timestamp={AbsoluteTime.fromPreciseTimestamp(tx.timestamp)}
iconPath={"R"} iconPath={"R"}
pending={ pending={
tx.txState.major === TransactionMajorState.Pending tx.txState.major === TransactionMajorState.Pending
@ -137,7 +137,7 @@ export function TransactionItem(props: { tx: Transaction }): VNode {
amount={tx.amountEffective} amount={tx.amountEffective}
debitCreditIndicator={"credit"} debitCreditIndicator={"credit"}
title={new URL(tx.merchantBaseUrl).hostname} title={new URL(tx.merchantBaseUrl).hostname}
timestamp={AbsoluteTime.fromTimestamp(tx.timestamp)} timestamp={AbsoluteTime.fromPreciseTimestamp(tx.timestamp)}
iconPath={"T"} iconPath={"T"}
pending={ pending={
tx.txState.major === TransactionMajorState.Pending tx.txState.major === TransactionMajorState.Pending
@ -153,7 +153,7 @@ export function TransactionItem(props: { tx: Transaction }): VNode {
amount={tx.amountEffective} amount={tx.amountEffective}
debitCreditIndicator={"credit"} debitCreditIndicator={"credit"}
title={"Refresh"} title={"Refresh"}
timestamp={AbsoluteTime.fromTimestamp(tx.timestamp)} timestamp={AbsoluteTime.fromPreciseTimestamp(tx.timestamp)}
iconPath={"R"} iconPath={"R"}
pending={ pending={
tx.txState.major === TransactionMajorState.Pending tx.txState.major === TransactionMajorState.Pending
@ -169,7 +169,7 @@ export function TransactionItem(props: { tx: Transaction }): VNode {
amount={tx.amountEffective} amount={tx.amountEffective}
debitCreditIndicator={"debit"} debitCreditIndicator={"debit"}
title={tx.targetPaytoUri} title={tx.targetPaytoUri}
timestamp={AbsoluteTime.fromTimestamp(tx.timestamp)} timestamp={AbsoluteTime.fromPreciseTimestamp(tx.timestamp)}
iconPath={"D"} iconPath={"D"}
pending={ pending={
tx.txState.major === TransactionMajorState.Pending tx.txState.major === TransactionMajorState.Pending
@ -185,7 +185,7 @@ export function TransactionItem(props: { tx: Transaction }): VNode {
amount={tx.amountEffective} amount={tx.amountEffective}
debitCreditIndicator={"credit"} debitCreditIndicator={"credit"}
title={tx.info.summary || "Invoice"} title={tx.info.summary || "Invoice"}
timestamp={AbsoluteTime.fromTimestamp(tx.timestamp)} timestamp={AbsoluteTime.fromPreciseTimestamp(tx.timestamp)}
iconPath={"I"} iconPath={"I"}
pending={ pending={
tx.txState.major === TransactionMajorState.Pending tx.txState.major === TransactionMajorState.Pending
@ -201,7 +201,7 @@ export function TransactionItem(props: { tx: Transaction }): VNode {
amount={tx.amountEffective} amount={tx.amountEffective}
debitCreditIndicator={"debit"} debitCreditIndicator={"debit"}
title={tx.info.summary || "Invoice"} title={tx.info.summary || "Invoice"}
timestamp={AbsoluteTime.fromTimestamp(tx.timestamp)} timestamp={AbsoluteTime.fromPreciseTimestamp(tx.timestamp)}
iconPath={"I"} iconPath={"I"}
pending={ pending={
tx.txState.major === TransactionMajorState.Pending tx.txState.major === TransactionMajorState.Pending
@ -217,7 +217,7 @@ export function TransactionItem(props: { tx: Transaction }): VNode {
amount={tx.amountEffective} amount={tx.amountEffective}
debitCreditIndicator={"credit"} debitCreditIndicator={"credit"}
title={tx.info.summary || "Transfer"} title={tx.info.summary || "Transfer"}
timestamp={AbsoluteTime.fromTimestamp(tx.timestamp)} timestamp={AbsoluteTime.fromPreciseTimestamp(tx.timestamp)}
iconPath={"T"} iconPath={"T"}
pending={ pending={
tx.txState.major === TransactionMajorState.Pending tx.txState.major === TransactionMajorState.Pending
@ -233,7 +233,7 @@ export function TransactionItem(props: { tx: Transaction }): VNode {
amount={tx.amountEffective} amount={tx.amountEffective}
debitCreditIndicator={"debit"} debitCreditIndicator={"debit"}
title={tx.info.summary || "Transfer"} title={tx.info.summary || "Transfer"}
timestamp={AbsoluteTime.fromTimestamp(tx.timestamp)} timestamp={AbsoluteTime.fromPreciseTimestamp(tx.timestamp)}
iconPath={"T"} iconPath={"T"}
pending={ pending={
tx.txState.major === TransactionMajorState.Pending tx.txState.major === TransactionMajorState.Pending

View File

@ -123,7 +123,7 @@ export function useComponentState({
raw, raw,
goToWalletManualWithdraw, goToWalletManualWithdraw,
summary, summary,
expiration: expiration ? AbsoluteTime.fromTimestamp(expiration) : undefined, expiration: expiration ? AbsoluteTime.fromProtocolTimestamp(expiration) : undefined,
}; };
if (!foundBalance) { if (!foundBalance) {

View File

@ -93,7 +93,7 @@ export function BaseView(state: SupportedStates): VNode {
title={i18n.str`Valid until`} title={i18n.str`Valid until`}
text={ text={
<Time <Time
timestamp={AbsoluteTime.fromTimestamp( timestamp={AbsoluteTime.fromProtocolTimestamp(
contractTerms.pay_deadline, contractTerms.pay_deadline,
)} )}
format="dd MMMM yyyy, HH:mm" format="dd MMMM yyyy, HH:mm"

View File

@ -86,7 +86,7 @@ export function useComponentState({
onClick: pushAlertOnError(accept), onClick: pushAlertOnError(accept),
}, },
summary, summary,
expiration: expiration ? AbsoluteTime.fromTimestamp(expiration) : undefined, expiration: expiration ? AbsoluteTime.fromProtocolTimestamp(expiration) : undefined,
cancel: { cancel: {
onClick: pushAlertOnError(onClose), onClick: pushAlertOnError(onClose),
}, },

View File

@ -26,7 +26,7 @@ import {
ShowRecoveryInfo, ShowRecoveryInfo,
} from "./BackupPage.js"; } from "./BackupPage.js";
import * as tests from "@gnu-taler/web-util/testing"; import * as tests from "@gnu-taler/web-util/testing";
import { TalerProtocolTimestamp } from "@gnu-taler/taler-util"; import { TalerPreciseTimestamp, TalerProtocolTimestamp } from "@gnu-taler/taler-util";
export default { export default {
title: "backup", title: "backup",
@ -39,7 +39,7 @@ export const LotOfProviders = tests.createExample(TestedComponent, {
name: "sync.demo", name: "sync.demo",
syncProviderBaseUrl: "http://sync.taler:9967/", syncProviderBaseUrl: "http://sync.taler:9967/",
lastSuccessfulBackupTimestamp: lastSuccessfulBackupTimestamp:
TalerProtocolTimestamp.fromSeconds(1625063925), TalerPreciseTimestamp.fromSeconds(1625063925),
paymentProposalIds: [ paymentProposalIds: [
"43Q5WWRJPNS4SE9YKS54H9THDS94089EDGXW9EHBPN6E7M184XEG", "43Q5WWRJPNS4SE9YKS54H9THDS94089EDGXW9EHBPN6E7M184XEG",
], ],
@ -60,7 +60,7 @@ export const LotOfProviders = tests.createExample(TestedComponent, {
name: "sync.demo", name: "sync.demo",
syncProviderBaseUrl: "http://sync.taler:9967/", syncProviderBaseUrl: "http://sync.taler:9967/",
lastSuccessfulBackupTimestamp: lastSuccessfulBackupTimestamp:
TalerProtocolTimestamp.fromSeconds(1625063925), TalerPreciseTimestamp.fromSeconds(1625063925),
paymentProposalIds: [ paymentProposalIds: [
"43Q5WWRJPNS4SE9YKS54H9THDS94089EDGXW9EHBPN6E7M184XEG", "43Q5WWRJPNS4SE9YKS54H9THDS94089EDGXW9EHBPN6E7M184XEG",
], ],
@ -171,7 +171,7 @@ export const OneProvider = tests.createExample(TestedComponent, {
name: "sync.demo", name: "sync.demo",
syncProviderBaseUrl: "http://sync.taler:9967/", syncProviderBaseUrl: "http://sync.taler:9967/",
lastSuccessfulBackupTimestamp: lastSuccessfulBackupTimestamp:
TalerProtocolTimestamp.fromSeconds(1625063925), TalerPreciseTimestamp.fromSeconds(1625063925),
paymentProposalIds: [ paymentProposalIds: [
"43Q5WWRJPNS4SE9YKS54H9THDS94089EDGXW9EHBPN6E7M184XEG", "43Q5WWRJPNS4SE9YKS54H9THDS94089EDGXW9EHBPN6E7M184XEG",
], ],

View File

@ -199,7 +199,7 @@ export function BackupView({
status={provider.paymentStatus} status={provider.paymentStatus}
timestamp={ timestamp={
provider.lastSuccessfulBackupTimestamp provider.lastSuccessfulBackupTimestamp
? AbsoluteTime.fromTimestamp( ? AbsoluteTime.fromPreciseTimestamp(
provider.lastSuccessfulBackupTimestamp, provider.lastSuccessfulBackupTimestamp,
) )
: undefined : undefined

View File

@ -19,7 +19,7 @@
* @author Sebastian Javier Marchano (sebasjm) * @author Sebastian Javier Marchano (sebasjm)
*/ */
import { AbsoluteTime, TalerProtocolTimestamp } from "@gnu-taler/taler-util"; import { AbsoluteTime, TalerPreciseTimestamp, TalerProtocolTimestamp } from "@gnu-taler/taler-util";
import { ProviderPaymentType } from "@gnu-taler/taler-wallet-core"; import { ProviderPaymentType } from "@gnu-taler/taler-wallet-core";
import * as tests from "@gnu-taler/web-util/testing"; import * as tests from "@gnu-taler/web-util/testing";
import { ProviderView as TestedComponent } from "./ProviderDetailPage.js"; import { ProviderView as TestedComponent } from "./ProviderDetailPage.js";
@ -40,7 +40,7 @@ export const Active = tests.createExample(TestedComponent, {
name: "sync.demo", name: "sync.demo",
syncProviderBaseUrl: "http://sync.taler:9967/", syncProviderBaseUrl: "http://sync.taler:9967/",
lastSuccessfulBackupTimestamp: lastSuccessfulBackupTimestamp:
TalerProtocolTimestamp.fromSeconds(1625063925), TalerPreciseTimestamp.fromSeconds(1625063925),
paymentProposalIds: [ paymentProposalIds: [
"43Q5WWRJPNS4SE9YKS54H9THDS94089EDGXW9EHBPN6E7M184XEG", "43Q5WWRJPNS4SE9YKS54H9THDS94089EDGXW9EHBPN6E7M184XEG",
], ],
@ -64,9 +64,9 @@ export const ActiveErrorSync = tests.createExample(TestedComponent, {
name: "sync.demo", name: "sync.demo",
syncProviderBaseUrl: "http://sync.taler:9967/", syncProviderBaseUrl: "http://sync.taler:9967/",
lastSuccessfulBackupTimestamp: lastSuccessfulBackupTimestamp:
TalerProtocolTimestamp.fromSeconds(1625063925), TalerPreciseTimestamp.fromSeconds(1625063925),
lastAttemptedBackupTimestamp: lastAttemptedBackupTimestamp:
TalerProtocolTimestamp.fromSeconds(1625063925078), TalerPreciseTimestamp.fromSeconds(1625063925078),
paymentProposalIds: [ paymentProposalIds: [
"43Q5WWRJPNS4SE9YKS54H9THDS94089EDGXW9EHBPN6E7M184XEG", "43Q5WWRJPNS4SE9YKS54H9THDS94089EDGXW9EHBPN6E7M184XEG",
], ],
@ -99,7 +99,7 @@ export const ActiveBackupProblemUnreadable = tests.createExample(
name: "sync.demo", name: "sync.demo",
syncProviderBaseUrl: "http://sync.taler:9967/", syncProviderBaseUrl: "http://sync.taler:9967/",
lastSuccessfulBackupTimestamp: lastSuccessfulBackupTimestamp:
TalerProtocolTimestamp.fromSeconds(1625063925), TalerPreciseTimestamp.fromSeconds(1625063925),
paymentProposalIds: [ paymentProposalIds: [
"43Q5WWRJPNS4SE9YKS54H9THDS94089EDGXW9EHBPN6E7M184XEG", "43Q5WWRJPNS4SE9YKS54H9THDS94089EDGXW9EHBPN6E7M184XEG",
], ],
@ -127,7 +127,7 @@ export const ActiveBackupProblemDevice = tests.createExample(TestedComponent, {
name: "sync.demo", name: "sync.demo",
syncProviderBaseUrl: "http://sync.taler:9967/", syncProviderBaseUrl: "http://sync.taler:9967/",
lastSuccessfulBackupTimestamp: lastSuccessfulBackupTimestamp:
TalerProtocolTimestamp.fromSeconds(1625063925078), TalerPreciseTimestamp.fromSeconds(1625063925078),
paymentProposalIds: [ paymentProposalIds: [
"43Q5WWRJPNS4SE9YKS54H9THDS94089EDGXW9EHBPN6E7M184XEG", "43Q5WWRJPNS4SE9YKS54H9THDS94089EDGXW9EHBPN6E7M184XEG",
], ],

View File

@ -151,7 +151,7 @@ export function ProviderView({
}: ViewProps): VNode { }: ViewProps): VNode {
const { i18n } = useTranslationContext(); const { i18n } = useTranslationContext();
const lb = info.lastSuccessfulBackupTimestamp const lb = info.lastSuccessfulBackupTimestamp
? AbsoluteTime.fromTimestamp(info.lastSuccessfulBackupTimestamp) ? AbsoluteTime.fromPreciseTimestamp(info.lastSuccessfulBackupTimestamp)
: undefined; : undefined;
const isPaid = const isPaid =
info.paymentStatus.type === ProviderPaymentType.Paid || info.paymentStatus.type === ProviderPaymentType.Paid ||

View File

@ -23,6 +23,7 @@ import {
AbsoluteTime, AbsoluteTime,
PaymentStatus, PaymentStatus,
RefreshReason, RefreshReason,
TalerPreciseTimestamp,
TalerProtocolTimestamp, TalerProtocolTimestamp,
TransactionCommon, TransactionCommon,
TransactionDeposit, TransactionDeposit,
@ -245,7 +246,7 @@ export const WithdrawFiveMinutesAgo = tests.createExample(
() => ({ () => ({
transaction: { transaction: {
...exampleData.withdraw, ...exampleData.withdraw,
timestamp: TalerProtocolTimestamp.fromSeconds( timestamp: TalerPreciseTimestamp.fromSeconds(
new Date().getTime() / 1000 - 60 * 5, new Date().getTime() / 1000 - 60 * 5,
), ),
}, },
@ -257,7 +258,7 @@ export const WithdrawFiveMinutesAgoAndPending = tests.createExample(
() => ({ () => ({
transaction: { transaction: {
...exampleData.withdraw, ...exampleData.withdraw,
timestamp: TalerProtocolTimestamp.fromSeconds( timestamp: TalerPreciseTimestamp.fromSeconds(
new Date().getTime() / 1000 - 60 * 5, new Date().getTime() / 1000 - 60 * 5,
), ),
txState: { txState: {

View File

@ -25,6 +25,7 @@ import {
parsePaytoUri, parsePaytoUri,
PaytoUri, PaytoUri,
stringifyPaytoUri, stringifyPaytoUri,
TalerPreciseTimestamp,
TalerProtocolTimestamp, TalerProtocolTimestamp,
Transaction, Transaction,
TransactionDeposit, TransactionDeposit,
@ -585,7 +586,7 @@ export function TransactionView({
on{" "} on{" "}
{ {
<Time <Time
timestamp={AbsoluteTime.fromTimestamp( timestamp={AbsoluteTime.fromProtocolTimestamp(
r.timestamp, r.timestamp,
)} )}
format="dd MMMM yyyy" format="dd MMMM yyyy"
@ -671,7 +672,7 @@ export function TransactionView({
if (transaction.type === TransactionType.Deposit) { if (transaction.type === TransactionType.Deposit) {
const payto = parsePaytoUri(transaction.targetPaytoUri); const payto = parsePaytoUri(transaction.targetPaytoUri);
const wireTime = AbsoluteTime.fromTimestamp( const wireTime = AbsoluteTime.fromProtocolTimestamp(
transaction.wireTransferDeadline, transaction.wireTransferDeadline,
); );
const shouldBeWired = wireTime.t_ms !== "never" && isPast(wireTime.t_ms); const shouldBeWired = wireTime.t_ms !== "never" && isPast(wireTime.t_ms);
@ -1204,7 +1205,7 @@ function DeliveryDetails({
</td> </td>
<td> <td>
<Time <Time
timestamp={AbsoluteTime.fromTimestamp(date)} timestamp={AbsoluteTime.fromProtocolTimestamp(date)}
format="dd MMMM yyyy, HH:mm" format="dd MMMM yyyy, HH:mm"
/> />
</td> </td>
@ -1768,7 +1769,7 @@ function Header({
kind, kind,
type, type,
}: { }: {
timestamp: TalerProtocolTimestamp; timestamp: TalerPreciseTimestamp;
total: AmountJson; total: AmountJson;
children: ComponentChildren; children: ComponentChildren;
kind: Kind; kind: Kind;
@ -1785,7 +1786,7 @@ function Header({
<div> <div>
<SubTitle>{children}</SubTitle> <SubTitle>{children}</SubTitle>
<Time <Time
timestamp={AbsoluteTime.fromTimestamp(timestamp)} timestamp={AbsoluteTime.fromPreciseTimestamp(timestamp)}
format="dd MMMM yyyy, HH:mm" format="dd MMMM yyyy, HH:mm"
/> />
</div> </div>