aboutsummaryrefslogtreecommitdiff
path: root/packages/taler-wallet-core/src/db.ts
diff options
context:
space:
mode:
authorÖzgür Kesim <oec-taler@kesim.org>2023-10-06 16:33:05 +0200
committerÖzgür Kesim <oec-taler@kesim.org>2023-10-06 16:33:05 +0200
commitfe7b51ef2736edbf04f5bbd9d19f2a2d04baccc2 (patch)
tree66c68c8d6a666f6e74dc663c9ee4f07879f6626c /packages/taler-wallet-core/src/db.ts
parent35611f0bf9cf67638b171c2a300fab1797d3d8f0 (diff)
parent97d7be7503168f4f3bbd05905d32aa76ca1636b2 (diff)
Merge branch 'master' into age-withdraw
Diffstat (limited to 'packages/taler-wallet-core/src/db.ts')
-rw-r--r--packages/taler-wallet-core/src/db.ts263
1 files changed, 163 insertions, 100 deletions
diff --git a/packages/taler-wallet-core/src/db.ts b/packages/taler-wallet-core/src/db.ts
index 239a6d4a4..46a073156 100644
--- a/packages/taler-wallet-core/src/db.ts
+++ b/packages/taler-wallet-core/src/db.ts
@@ -27,8 +27,8 @@ import {
structuredEncapsulate,
} from "@gnu-taler/idb-bridge";
import {
+ AbsoluteTime,
AgeCommitmentProof,
- AmountJson,
AmountString,
Amounts,
AttentionInfo,
@@ -45,23 +45,20 @@ import {
ExchangeAuditor,
ExchangeGlobalFees,
HashCodeString,
- InternationalizedString,
Logger,
- MerchantContractTerms,
- MerchantInfo,
PayCoinSelection,
- PeerContractTerms,
RefreshReason,
TalerErrorDetail,
TalerPreciseTimestamp,
TalerProtocolDuration,
TalerProtocolTimestamp,
+ //TalerProtocolTimestamp,
TransactionIdStr,
UnblindedSignature,
WireInfo,
codecForAny,
} from "@gnu-taler/taler-util";
-import { RetryInfo, TaskIdentifiers } from "./operations/common.js";
+import { DbRetryInfo, TaskIdentifiers } from "./operations/common.js";
import {
DbAccess,
DbReadOnlyTransaction,
@@ -151,6 +148,91 @@ 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;
+ }
+}
+
+export function timestampProtocolToDb(
+ stamp: TalerProtocolTimestamp,
+): DbProtocolTimestamp {
+ if (stamp.t_s === "never") {
+ return DB_TIMESTAMP_FOREVER as DbProtocolTimestamp;
+ } else {
+ let tUs = stamp.t_s * 1000000;
+ return tUs as DbProtocolTimestamp;
+ }
+}
+
+export function timestampProtocolFromDb(
+ stamp: DbProtocolTimestamp,
+): TalerProtocolTimestamp {
+ return TalerProtocolTimestamp.fromSeconds(Math.floor(stamp / 1000000));
+}
+
+export function timestampAbsoluteFromDb(
+ stamp: DbProtocolTimestamp | DbPreciseTimestamp,
+): AbsoluteTime {
+ if (stamp >= DB_TIMESTAMP_FOREVER) {
+ return AbsoluteTime.never();
+ }
+ return AbsoluteTime.fromMilliseconds(Math.floor(stamp / 1000));
+}
+
+export function timestampOptionalAbsoluteFromDb(
+ stamp: DbProtocolTimestamp | DbPreciseTimestamp | undefined,
+): AbsoluteTime | undefined {
+ if (stamp == null) {
+ return undefined;
+ }
+ if (stamp >= DB_TIMESTAMP_FOREVER) {
+ return AbsoluteTime.never();
+ }
+ return AbsoluteTime.fromMilliseconds(Math.floor(stamp / 1000));
+}
+
/**
* Format of the operation status code: 0x0abc_nnnn
@@ -217,7 +299,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 +350,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;
}
/**
@@ -349,22 +431,22 @@ export interface DenominationRecord {
/**
* Validity start date of the denomination.
*/
- stampStart: TalerProtocolTimestamp;
+ stampStart: DbProtocolTimestamp;
/**
* Date after which the currency can't be withdrawn anymore.
*/
- stampExpireWithdraw: TalerProtocolTimestamp;
+ stampExpireWithdraw: DbProtocolTimestamp;
/**
* Date after the denomination officially doesn't exist anymore.
*/
- stampExpireLegal: TalerProtocolTimestamp;
+ stampExpireLegal: DbProtocolTimestamp;
/**
* Data after which coins of this denomination can't be deposited anymore.
*/
- stampExpireDeposit: TalerProtocolTimestamp;
+ stampExpireDeposit: DbProtocolTimestamp;
/**
* Signature by the exchange's master key over the denomination
@@ -406,7 +488,7 @@ export interface DenominationRecord {
* Latest list issue date of the "/keys" response
* that includes this denomination.
*/
- listIssueDate: TalerProtocolTimestamp;
+ listIssueDate: DbProtocolTimestamp;
}
export namespace DenominationRecord {
@@ -418,10 +500,10 @@ export namespace DenominationRecord {
feeRefresh: Amounts.stringify(d.fees.feeRefresh),
feeRefund: Amounts.stringify(d.fees.feeRefund),
feeWithdraw: Amounts.stringify(d.fees.feeWithdraw),
- stampExpireDeposit: d.stampExpireDeposit,
- stampExpireLegal: d.stampExpireLegal,
- stampExpireWithdraw: d.stampExpireWithdraw,
- stampStart: d.stampStart,
+ stampExpireDeposit: timestampProtocolFromDb(d.stampExpireDeposit),
+ stampExpireLegal: timestampProtocolFromDb(d.stampExpireLegal),
+ stampExpireWithdraw: timestampProtocolFromDb(d.stampExpireWithdraw),
+ stampStart: timestampProtocolFromDb(d.stampStart),
value: Amounts.stringify(d.value),
exchangeBaseUrl: d.exchangeBaseUrl,
};
@@ -429,9 +511,9 @@ export namespace DenominationRecord {
}
export interface ExchangeSignkeysRecord {
- stampStart: TalerProtocolTimestamp;
- stampExpire: TalerProtocolTimestamp;
- stampEnd: TalerProtocolTimestamp;
+ stampStart: DbProtocolTimestamp;
+ stampExpire: DbProtocolTimestamp;
+ stampEnd: DbProtocolTimestamp;
signkeyPub: EddsaPublicKeyString;
masterSig: EddsaSignatureString;
@@ -488,7 +570,7 @@ export interface ExchangeDetailsRecord {
tosAccepted:
| {
etag: string;
- timestamp: TalerPreciseTimestamp;
+ timestamp: DbPreciseTimestamp;
}
| undefined;
@@ -500,25 +582,6 @@ export interface ExchangeDetailsRecord {
ageMask?: number;
}
-export interface ExchangeTosRecord {
- exchangeBaseUrl: string;
-
- etag: string;
-
- /**
- * Terms of service text or undefined if not downloaded yet.
- *
- * This is just used as a cache of the last downloaded ToS.
- *
- */
- termsOfServiceText: string | undefined;
-
- /**
- * Content-type of the last downloaded termsOfServiceText.
- */
- termsOfServiceContentType: string | undefined;
-}
-
export interface ExchangeDetailsPointer {
masterPublicKey: string;
@@ -528,7 +591,7 @@ export interface ExchangeDetailsPointer {
* Timestamp when the (masterPublicKey, currency) pointer
* has been updated.
*/
- updateClock: TalerPreciseTimestamp;
+ updateClock: DbPreciseTimestamp;
}
export enum ExchangeEntryDbRecordStatus {
@@ -549,11 +612,6 @@ export enum ExchangeEntryDbUpdateStatus {
}
/**
- * Timestamp stored as a IEEE 754 double, in milliseconds.
- */
-export type DbIndexableTimestampMs = number;
-
-/**
* Exchange record as stored in the wallet's database.
*/
export interface ExchangeEntryRecord {
@@ -563,11 +621,17 @@ export interface ExchangeEntryRecord {
baseUrl: string;
/**
+ * Currency hint for a preset exchange, relevant
+ * when we didn't contact a preset exchange yet.
+ */
+ presetCurrencyHint?: string;
+
+ /**
* When did we confirm the last withdrawal from this exchange?
*
* Used mostly in the UI to suggest exchanges.
*/
- lastWithdrawal?: TalerPreciseTimestamp;
+ lastWithdrawal?: DbPreciseTimestamp;
/**
* Pointer to the current exchange details.
@@ -588,17 +652,12 @@ export interface ExchangeEntryRecord {
/**
* Last time when the exchange /keys info was updated.
*/
- lastUpdate: TalerPreciseTimestamp | undefined;
+ lastUpdate: DbPreciseTimestamp | undefined;
/**
* Next scheduled update for the exchange.
- *
- * (This field must always be present, so we can index on the timestamp.)
- *
- * FIXME: To index on the timestamp, this needs to be a number of
- * binary timestamp!
*/
- nextUpdateStampMs: DbIndexableTimestampMs;
+ nextUpdateStamp: DbPreciseTimestamp;
lastKeysEtag: string | undefined;
@@ -608,7 +667,7 @@ export interface ExchangeEntryRecord {
* Updated whenever the exchange's denominations are updated or when
* the refresh check has been done.
*/
- nextRefreshCheckStampMs: DbIndexableTimestampMs;
+ nextRefreshCheckStamp: DbPreciseTimestamp;
/**
* Public key of the reserve that we're currently using for
@@ -823,7 +882,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.
@@ -838,7 +897,7 @@ export interface RewardRecord {
/**
* Timestamp, the tip can't be picked up anymore after this deadline.
*/
- rewardExpiration: TalerProtocolTimestamp;
+ rewardExpiration: DbProtocolTimestamp;
/**
* The exchange that will sign our coins, chosen by the merchant.
@@ -876,7 +935,7 @@ export interface RewardRecord {
*/
merchantRewardId: string;
- createdTimestamp: TalerPreciseTimestamp;
+ createdTimestamp: DbPreciseTimestamp;
/**
* The url to be redirected after the tip is accepted.
@@ -887,7 +946,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;
}
@@ -985,12 +1044,12 @@ export interface RefreshGroupRecord {
*/
statusPerCoin: RefreshCoinStatus[];
- timestampCreated: TalerPreciseTimestamp;
+ timestampCreated: DbPreciseTimestamp;
/**
* Timestamp when the refresh session finished.
*/
- timestampFinished: TalerPreciseTimestamp | undefined;
+ timestampFinished: DbPreciseTimestamp | undefined;
}
/**
@@ -1215,7 +1274,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;
@@ -1230,19 +1289,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).
@@ -1252,7 +1311,7 @@ export interface PurchaseRecord {
/**
* Continue querying the refund status until this deadline has expired.
*/
- autoRefundDeadline: TalerProtocolTimestamp | undefined;
+ autoRefundDeadline: DbProtocolTimestamp | undefined;
/**
* How much merchant has refund to be taken but the wallet
@@ -1292,12 +1351,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;
}
@@ -1405,12 +1464,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.
@@ -1501,9 +1560,9 @@ export interface RecoupGroupRecord {
exchangeBaseUrl: string;
- timestampStarted: TalerPreciseTimestamp;
+ timestampStarted: DbPreciseTimestamp;
- timestampFinished: TalerPreciseTimestamp | undefined;
+ timestampFinished: DbPreciseTimestamp | undefined;
/**
* Public keys that identify the coins being recouped
@@ -1537,7 +1596,7 @@ export type BackupProviderState =
}
| {
tag: BackupProviderStateTag.Ready;
- nextBackupTimestamp: TalerPreciseTimestamp;
+ nextBackupTimestamp: DbPreciseTimestamp;
}
| {
tag: BackupProviderStateTag.Retrying;
@@ -1582,7 +1641,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.
@@ -1633,7 +1692,7 @@ export interface DepositTrackingInfo {
// Raw wire transfer identifier of the deposit.
wireTransferId: string;
// When was the wire transfer given to the bank.
- timestampExecuted: TalerProtocolTimestamp;
+ timestampExecuted: DbProtocolTimestamp;
// Total amount transfer for this wtid (including fees)
amountRaw: AmountString;
// Wire fee amount for this exchange
@@ -1655,7 +1714,7 @@ export interface DepositGroupRecord {
*/
amount: AmountString;
- wireTransferDeadline: TalerProtocolTimestamp;
+ wireTransferDeadline: DbProtocolTimestamp;
merchantPub: string;
merchantPriv: string;
@@ -1685,9 +1744,9 @@ export interface DepositGroupRecord {
*/
counterpartyEffectiveDepositAmount: AmountString;
- timestampCreated: TalerPreciseTimestamp;
+ timestampCreated: DbPreciseTimestamp;
- timestampFinished: TalerPreciseTimestamp | undefined;
+ timestampFinished: DbPreciseTimestamp | undefined;
operationStatus: DepositOperationStatus;
@@ -1796,9 +1855,9 @@ export interface PeerPushDebitRecord {
*/
contractEncNonce: string;
- purseExpiration: TalerProtocolTimestamp;
+ purseExpiration: DbProtocolTimestamp;
- timestampCreated: TalerPreciseTimestamp;
+ timestampCreated: DbPreciseTimestamp;
abortRefreshGroupId?: string;
@@ -1871,7 +1930,7 @@ export interface PeerPullCreditRecord {
contractEncNonce: string;
- mergeTimestamp: TalerPreciseTimestamp;
+ mergeTimestamp: DbPreciseTimestamp;
mergeReserveRowId: number;
@@ -1923,7 +1982,7 @@ export interface PeerPushPaymentIncomingRecord {
contractPriv: string;
- timestamp: TalerPreciseTimestamp;
+ timestamp: DbPreciseTimestamp;
estimatedAmountEffective: AmountString;
@@ -1995,7 +2054,7 @@ export interface PeerPullPaymentIncomingRecord {
contractTermsHash: string;
- timestampCreated: TalerPreciseTimestamp;
+ timestampCreated: DbPreciseTimestamp;
/**
* Contract priv that we got from the other party.
@@ -2042,7 +2101,7 @@ export interface OperationRetryRecord {
lastError?: TalerErrorDetail;
- retryInfo: RetryInfo;
+ retryInfo: DbRetryInfo;
}
/**
@@ -2095,14 +2154,13 @@ export interface UserAttentionRecord {
/**
* When the notification was created.
- * FIXME: This should be a TalerPreciseTimestamp
*/
- createdMs: number;
+ created: DbPreciseTimestamp;
/**
* When the user mark this notification as read.
*/
- read: TalerPreciseTimestamp | undefined;
+ read: DbPreciseTimestamp | undefined;
}
export interface DbExchangeHandle {
@@ -2146,7 +2204,7 @@ export interface RefundGroupRecord {
/**
* Timestamp when the refund group was created.
*/
- timestampCreated: TalerPreciseTimestamp;
+ timestampCreated: DbPreciseTimestamp;
proposalId: string;
@@ -2198,12 +2256,12 @@ export interface RefundItemRecord {
/**
* Execution time as claimed by the merchant
*/
- executionTime: TalerProtocolTimestamp;
+ executionTime: DbProtocolTimestamp;
/**
* Time when the wallet became aware of the refund.
*/
- obtainedTime: TalerPreciseTimestamp;
+ obtainedTime: DbPreciseTimestamp;
refundAmount: AmountString;
@@ -2389,15 +2447,19 @@ export const WalletStoresV1 = {
"planchets",
describeContents<PlanchetRecord>({ keyPath: "coinPub" }),
{
- byGroupAgeCoin: describeIndex("byGroupAgeCoin", [
- "withdrawalGroupId",
- "ageWithdrawIdx",
- "coinIdx",
- ]),
- byGroupAndIndex: describeIndex("byGroupAndIndex", [
- "withdrawalGroupId",
- "coinIdx",
- ]),
+ byGroupAgeCoin: describeIndex(
+ "byGroupAgeCoin", [ "withdrawalGroupId", "ageWithdrawIdx", "coinIdx" ],
+ {
+ unique: true,
+ },
+ ),
+ byGroupAndIndex: describeIndex(
+ "byGroupAndIndex",
+ ["withdrawalGroupId", "coinIdx"],
+ {
+ unique: true,
+ },
+ ),
byGroup: describeIndex("byGroup", "withdrawalGroupId"),
byCoinEvHash: describeIndex("byCoinEv", "coinEvHash"),
},
@@ -3049,6 +3111,7 @@ export async function openTalerDatabase(
case "taler-wallet-main-v6":
case "taler-wallet-main-v7":
case "taler-wallet-main-v8":
+ case "taler-wallet-main-v9":
// We consider this a pre-release
// development version, no migration is done.
await metaDb