aboutsummaryrefslogtreecommitdiff
path: root/packages/taler-wallet-core/src/db.ts
diff options
context:
space:
mode:
Diffstat (limited to 'packages/taler-wallet-core/src/db.ts')
-rw-r--r--packages/taler-wallet-core/src/db.ts817
1 files changed, 294 insertions, 523 deletions
diff --git a/packages/taler-wallet-core/src/db.ts b/packages/taler-wallet-core/src/db.ts
index b52a503bc..25757ef25 100644
--- a/packages/taler-wallet-core/src/db.ts
+++ b/packages/taler-wallet-core/src/db.ts
@@ -22,59 +22,59 @@ import {
IDBDatabase,
IDBFactory,
IDBObjectStore,
+ IDBRequest,
IDBTransaction,
structuredEncapsulate,
} from "@gnu-taler/idb-bridge";
import {
AgeCommitmentProof,
- AmountJson,
AmountString,
+ Amounts,
+ AttentionInfo,
+ Codec,
CoinEnvelope,
+ CoinPublicKeyString,
CoinRefreshRequest,
CoinStatus,
- MerchantContractTerms,
+ DenomSelectionState,
DenominationInfo,
DenominationPubKey,
- DenomSelectionState,
EddsaPublicKeyString,
EddsaSignatureString,
ExchangeAuditor,
ExchangeGlobalFees,
+ HashCodeString,
InternationalizedString,
- Location,
+ Logger,
+ MerchantContractTerms,
MerchantInfo,
PayCoinSelection,
PeerContractTerms,
- Product,
RefreshReason,
TalerErrorDetail,
+ TalerPreciseTimestamp,
TalerProtocolDuration,
TalerProtocolTimestamp,
TransactionIdStr,
UnblindedSignature,
WireInfo,
- HashCodeString,
- Amounts,
- AttentionInfo,
- Logger,
- CoinPublicKeyString,
- TalerPreciseTimestamp,
+ codecForAny,
} from "@gnu-taler/taler-util";
+import { RetryInfo, TaskIdentifiers } from "./operations/common.js";
import {
DbAccess,
DbReadOnlyTransaction,
DbReadWriteTransaction,
- describeContents,
- describeIndex,
- describeStore,
GetReadWriteAccess,
IndexDescriptor,
- openDatabase,
StoreDescriptor,
StoreNames,
StoreWithIndexes,
+ describeContents,
+ describeIndex,
+ describeStore,
+ openDatabase,
} from "./util/query.js";
-import { RetryInfo, TaskIdentifiers } from "./operations/common.js";
/**
* This file contains the database schema of the Taler wallet together
@@ -99,12 +99,25 @@ import { RetryInfo, TaskIdentifiers } from "./operations/common.js";
*/
/**
+ FIXMEs:
+ - Contract terms can be quite large. We currently tend to read the
+ full contract terms from the DB quite often.
+ Instead, we should probably extract what we need into a separate object
+ store.
+ - More object stores should have an "id" primary key,
+ as this makes referencing less expensive.
+ - Coin selections should probably go into a separate object store.
+ - Some records should be split up into an extra "details" record
+ that we don't always need to iterate over.
+ */
+
+/**
* Name of the Taler database. This is effectively the major
* version of the DB schema. Whenever it changes, custom import logic
* for all previous versions must be written, which should be
* avoided.
*/
-export const TALER_WALLET_MAIN_DB_NAME = "taler-wallet-main-v9";
+export const TALER_WALLET_MAIN_DB_NAME = "taler-wallet-main-v10";
/**
* Name of the metadata database. This database is used
@@ -115,10 +128,17 @@ export const TALER_WALLET_MAIN_DB_NAME = "taler-wallet-main-v9";
export const TALER_WALLET_META_DB_NAME = "taler-wallet-meta";
/**
- * Stored backups, mainly created when manually importing a backup.
+ * Name of the "stored backups" database.
+ * Stored backups are created before manually importing a backup.
+ * We use IndexedDB for this purpose, since we don't have file system
+ * access on some platforms.
*/
-export const TALER_WALLET_STORED_BACKUPS_DB_NAME = "taler-wallet-stored-backups";
+export const TALER_WALLET_STORED_BACKUPS_DB_NAME =
+ "taler-wallet-stored-backups";
+/**
+ * Name of the "meta config" database.
+ */
export const CURRENT_DB_CONFIG_KEY = "currentMainDbName";
/**
@@ -128,26 +148,26 @@ export const CURRENT_DB_CONFIG_KEY = "currentMainDbName";
* backwards-compatible way or object stores and indices
* are added.
*/
-export const WALLET_DB_MINOR_VERSION = 10;
+export const WALLET_DB_MINOR_VERSION = 1;
/**
- * Ranges for operation status fields.
- *
- * All individual enums should make sure that the values they
- * defined are in the right range.
+ * Format of the operation status code: 0x0abc_nnnn
+
+ * a=1: active
+ * 0x0100_nnnn: pending
+ * 0x0101_nnnn: dialog
+ * 0x0102_nnnn: (reserved)
+ * 0x0103_nnnn: aborting
+ * 0x0110_nnnn: suspended
+ * 0x0113_nnnn: suspended-aborting
+ * a=5: final
+ * 0x0500_nnnn: done
+ * 0x0501_nnnn: failed
+ * 0x0502_nnnn: expired
+ * 0x0503_nnnn: aborted
+ *
+ * nnnn=0000 should always be the most generic minor state for the major state
*/
-export enum OperationStatusRange {
- // Operations that need to be actively processed.
- ACTIVE_START = 10,
- ACTIVE_END = 29,
- // Operations that are suspended and might
- // expire, but nothing else can be done.
- SUSPENDED_START = 30,
- SUSPENDED_END = 49,
- // Operations that don't need any attention or processing.
- DORMANT_START = 50,
- DORMANT_END = 69,
-}
/**
* Status of a withdrawal.
@@ -156,71 +176,70 @@ export enum WithdrawalGroupStatus {
/**
* Reserve must be registered with the bank.
*/
- PendingRegisteringBank = 10,
+ PendingRegisteringBank = 0x0100_0001,
+ SuspendedRegisteringBank = 0x0110_0001,
/**
* We've registered reserve's information with the bank
* and are now waiting for the user to confirm the withdraw
* with the bank (typically 2nd factor auth).
*/
- PendingWaitConfirmBank = 11,
+ PendingWaitConfirmBank = 0x0100_0002,
+ SuspendedWaitConfirmBank = 0x0110_0002,
/**
* Querying reserve status with the exchange.
*/
- PendingQueryingStatus = 12,
+ PendingQueryingStatus = 0x0100_0003,
+ SuspendedQueryingStatus = 0x0110_0003,
/**
* Ready for withdrawal.
*/
- PendingReady = 13,
+ PendingReady = 0x0100_0004,
+ SuspendedReady = 0x0110_0004,
/**
* We are telling the bank that we don't want to complete
* the withdrawal!
*/
- AbortingBank = 14,
+ AbortingBank = 0x0103_0001,
+ SuspendedAbortingBank = 0x0113_0001,
/**
* Exchange wants KYC info from the user.
*/
- PendingKyc = 16,
+ PendingKyc = 0x0100_0005,
+ SuspendedKyc = 0x0110_005,
/**
* Exchange is doing AML checks.
*/
- PendingAml = 17,
-
- SuspendedRegisteringBank = 30,
- SuspendedWaitConfirmBank = 31,
- SuspendedQueryingStatus = 32,
- SuspendedReady = 33,
- SuspendedAbortingBank = 34,
- SuspendedKyc = 35,
- SuspendedAml = 36,
+ PendingAml = 0x0100_0006,
+ SuspendedAml = 0x0100_0006,
/**
* The corresponding withdraw record has been created.
* No further processing is done, unless explicitly requested
* by the user.
*/
- Finished = 50,
+ Done = 0x0500_0000,
/**
* The bank aborted the withdrawal.
*/
- FailedBankAborted = 51,
+ FailedBankAborted = 0x0501_0001,
- FailedAbortingBank = 59,
+ FailedAbortingBank = 0x0501_0002,
/**
* Aborted in a state where we were supposed to
* talk to the exchange. Money might have been
* wired or not.
*/
- AbortedExchange = 60,
+ AbortedExchange = 0x0503_0001,
- AbortedBank = 61,
+ AbortedBank = 0x0503_0002,
}
/**
@@ -259,78 +278,23 @@ export interface ReserveBankInfo {
}
/**
- * Record that indicates the wallet trusts
- * a particular auditor.
- */
-export interface AuditorTrustRecord {
- /**
- * Currency that we trust this auditor for.
- */
- currency: string;
-
- /**
- * Base URL of the auditor.
- */
- auditorBaseUrl: string;
-
- /**
- * Public key of the auditor.
- */
- auditorPub: string;
-
- /**
- * UIDs for the operation of adding this auditor
- * as a trusted auditor.
- *
- * (Used for backup/sync merging and tombstones.)
- */
- uids: string[];
-}
-
-/**
- * Record to indicate trust for a particular exchange.
- */
-export interface ExchangeTrustRecord {
- /**
- * Currency that we trust this exchange for.
- */
- currency: string;
-
- /**
- * Canonicalized exchange base URL.
- */
- exchangeBaseUrl: string;
-
- /**
- * Master public key of the exchange.
- */
- exchangeMasterPub: string;
-
- /**
- * UIDs for the operation of adding this exchange
- * as trusted.
- */
- uids: string[];
-}
-
-/**
* Status of a denomination.
*/
export enum DenominationVerificationStatus {
/**
- * Verification was delayed.
+ * Verification was delayed (pending).
*/
- Unverified = OperationStatusRange.ACTIVE_START,
+ Unverified = 0x0100_0000,
/**
* Verified as valid.
*/
- VerifiedGood = OperationStatusRange.DORMANT_START,
+ VerifiedGood = 0x0500_0000,
/**
* Verified as invalid.
*/
- VerifiedBad = OperationStatusRange.DORMANT_START + 1,
+ VerifiedBad = 0x0501_0000,
}
export interface DenomFees {
@@ -359,12 +323,14 @@ export interface DenomFees {
* Denomination record as stored in the wallet's database.
*/
export interface DenominationRecord {
+ /**
+ * Currency of the denomination.
+ *
+ * Stored separately as we have an index on it.
+ */
currency: string;
- // FIXME: Use binary encoding of amount instead?
- amountVal: number;
-
- amountFrac: number;
+ value: AmountString;
/**
* The denomination public key.
@@ -443,14 +409,6 @@ export interface DenominationRecord {
}
export namespace DenominationRecord {
- export function getValue(d: DenominationRecord): AmountJson {
- return {
- currency: d.currency,
- fraction: d.amountFrac,
- value: d.amountVal,
- };
- }
-
export function toDenomInfo(d: DenominationRecord): DenominationInfo {
return {
denomPub: d.denomPub,
@@ -463,7 +421,7 @@ export namespace DenominationRecord {
stampExpireLegal: d.stampExpireLegal,
stampExpireWithdraw: d.stampExpireWithdraw,
stampStart: d.stampStart,
- value: Amounts.stringify(DenominationRecord.getValue(d)),
+ value: Amounts.stringify(d.value),
exchangeBaseUrl: d.exchangeBaseUrl,
};
}
@@ -578,6 +536,7 @@ export enum ExchangeEntryDbRecordStatus {
Used = 3,
}
+// FIXME: Use status ranges for this as well?
export enum ExchangeEntryDbUpdateStatus {
Initial = 1,
InitialUpdate = 2,
@@ -658,9 +617,9 @@ export interface ExchangeEntryRecord {
}
export enum PlanchetStatus {
- Pending = 10 /* ACTIVE_START */,
- KycRequired = 11 /* ACTIVE_START + 1 */,
- WithdrawalDone = 50 /* DORMANT_START */,
+ Pending = 0x0100_0000,
+ KycRequired = 0x0100_0001,
+ WithdrawalDone = 0x0500_000,
}
/**
@@ -933,50 +892,45 @@ export interface RewardRecord {
}
export enum RewardRecordStatus {
- PendingPickup = 10,
-
- SuspendidPickup = 20,
-
- DialogAccept = 30,
-
- Done = 50,
- Aborted = 51,
+ PendingPickup = 0x0100_0000,
+ SuspendedPickup = 0x0110_0000,
+ DialogAccept = 0x0101_0000,
+ Done = 0x0500_0000,
+ Aborted = 0x0500_0000,
}
export enum RefreshCoinStatus {
- Pending = OperationStatusRange.ACTIVE_START,
- Finished = OperationStatusRange.DORMANT_START,
+ Pending = 0x0100_0000,
+ Finished = 0x0500_0000,
/**
* The refresh for this coin has been frozen, because of a permanent error.
* More info in lastErrorPerCoin.
*/
- Failed = OperationStatusRange.DORMANT_START + 1,
-}
-
-export enum OperationStatus {
- Finished = OperationStatusRange.DORMANT_START,
- Pending = OperationStatusRange.ACTIVE_START,
+ Failed = 0x0501_000,
}
export enum RefreshOperationStatus {
- Pending = 10 /* ACTIVE_START */,
- Suspended = 20 /* DORMANT_START + 2 */,
+ Pending = 0x0100_0000,
+ Suspended = 0x0110_0000,
- Finished = 50 /* DORMANT_START */,
- Failed = 51 /* DORMANT_START + 1 */,
+ Finished = 0x0500_000,
+ Failed = 0x0501_000,
}
/**
* Status of a single element of a deposit group.
*/
export enum DepositElementStatus {
- Unknown = 10,
- Accepted = 20,
- KycRequired = 30,
- Wired = 40,
- RefundSuccess = 50,
- RefundFailed = 51,
+ DepositPending = 0x0100_0000,
+ /**
+ * Accepted, but tracking.
+ */
+ Tracking = 0x0100_0001,
+ KycRequired = 0x0100_0002,
+ Wired = 0x0500_0000,
+ RefundSuccess = 0x0503_0000,
+ RefundFailed = 0x0501_0000,
}
/**
@@ -991,16 +945,10 @@ export interface RefreshReasonDetails {
* Group of refresh operations. The refreshed coins do not
* have to belong to the same exchange, but must have the same
* currency.
- *
- * FIXME: Should include the currency as a top-level field,
- * but we need to write a migration for that.
*/
export interface RefreshGroupRecord {
operationStatus: RefreshOperationStatus;
- // FIXME: Put this into a different object store?
- lastErrorPerCoin: { [coinIndex: number]: TalerErrorDetail };
-
/**
* Unique, randomly generated identifier for this group of
* refresh operations.
@@ -1009,8 +957,6 @@ export interface RefreshGroupRecord {
/**
* Currency of this refresh group.
- *
- * FIXME: Write a migration to add this to earlier DB versions.
*/
currency: string;
@@ -1026,13 +972,9 @@ export interface RefreshGroupRecord {
oldCoinPubs: string[];
- // FIXME: Should this go into a separate
- // object store for faster updates?
- refreshSessionPerCoin: (RefreshSessionRecord | undefined)[];
-
inputPerCoin: AmountString[];
- estimatedOutputPerCoin: AmountString[];
+ expectedOutputPerCoin: AmountString[];
/**
* Flag for each coin whether refreshing finished.
@@ -1054,6 +996,13 @@ export interface RefreshGroupRecord {
* Ongoing refresh
*/
export interface RefreshSessionRecord {
+ refreshGroupId: string;
+
+ /**
+ * Index of the coin in the refresh group.
+ */
+ coinIndex: number;
+
/**
* 512-bit secret that can be used to derive
* the other cryptographic material for the refresh session.
@@ -1078,6 +1027,8 @@ export interface RefreshSessionRecord {
* The no-reveal-index after we've done the melting.
*/
norevealIndex?: number;
+
+ lastError?: TalerErrorDetail;
}
export enum RefundReason {
@@ -1106,9 +1057,6 @@ export interface AllowedExchangeInfo {
* processing in the wallet.
*/
export interface WalletContractData {
- products?: Product[];
- summaryI18n: { [lang_tag: string]: string } | undefined;
-
/**
* Fulfillment URL, or the empty string if the order has no fulfillment URL.
*
@@ -1126,6 +1074,7 @@ export interface WalletContractData {
orderId: string;
merchantBaseUrl: string;
summary: string;
+ summaryI18n: { [lang_tag: string]: string } | undefined;
autoRefund: TalerProtocolDuration | undefined;
maxWireFee: AmountString;
wireFeeAmortization: number;
@@ -1137,89 +1086,90 @@ export interface WalletContractData {
wireInfoHash: string;
maxDepositFee: AmountString;
minimumAge?: number;
- deliveryDate: TalerProtocolTimestamp | undefined;
- deliveryLocation: Location | undefined;
}
export enum PurchaseStatus {
/**
* Not downloaded yet.
*/
- PendingDownloadingProposal = 10,
+ PendingDownloadingProposal = 0x0100_0000,
+ SuspendedDownloadingProposal = 0x0110_0000,
/**
* The user has accepted the proposal.
*/
- PendingPaying = 11,
+ PendingPaying = 0x0100_0001,
+ SuspendedPaying = 0x0110_0001,
/**
* Currently in the process of aborting with a refund.
*/
- AbortingWithRefund = 12,
+ AbortingWithRefund = 0x0103_0000,
+ SuspendedAbortingWithRefund = 0x0113_0000,
/**
* Paying a second time, likely with different session ID
*/
- PendingPayingReplay = 13,
+ PendingPayingReplay = 0x0100_0002,
+ SuspendedPayingReplay = 0x0110_0002,
/**
* Query for refunds (until query succeeds).
*/
- PendingQueryingRefund = 14,
+ PendingQueryingRefund = 0x0100_0003,
+ SuspendedQueryingRefund = 0x0110_0003,
/**
* Query for refund (until auto-refund deadline is reached).
*/
- PendingQueryingAutoRefund = 15,
+ PendingQueryingAutoRefund = 0x0100_0004,
+ SuspendedQueryingAutoRefund = 0x0110_0004,
- PendingAcceptRefund = 16,
-
- SuspendedDownloadingProposal = 20,
- SuspendedPaying = 21,
- SuspendedAbortingWithRefund = 22,
- SuspendedPayingReplay = 23,
- SuspendedQueryingRefund = 24,
- SuspendedQueryingAutoRefund = 25,
- SuspendedPendingAcceptRefund = 26,
+ PendingAcceptRefund = 0x0100_0005,
+ SuspendedPendingAcceptRefund = 0x0100_0005,
/**
* Proposal downloaded, but the user needs to accept/reject it.
*/
- DialogProposed = 30,
+ DialogProposed = 0x0101_0000,
+
/**
* Proposal shared to other wallet or read from other wallet
* the user needs to accept/reject it.
*/
- DialogShared = 31,
+ DialogShared = 0x0101_0001,
/**
* The user has rejected the proposal.
*/
- AbortedProposalRefused = 50,
+ AbortedProposalRefused = 0x0503_0000,
/**
* Downloading or processing the proposal has failed permanently.
*/
- FailedClaim = 51,
+ FailedClaim = 0x0501_0000,
+
+ /**
+ * Payment was successful.
+ */
+ Done = 0x0500_0000,
/**
* Downloaded proposal was detected as a re-purchase.
*/
- RepurchaseDetected = 52,
+ DoneRepurchaseDetected = 0x0500_0001,
/**
* The payment has been aborted.
*/
- AbortedIncompletePayment = 53,
+ AbortedIncompletePayment = 0x0503_0000,
/**
- * Payment was successful.
+ * Tried to abort, but aborting failed or was cancelled.
*/
- Done = 54,
+ FailedAbort = 0x0501_0001,
- FailedAbort = 55,
-
- AbortedRefunded = 56,
+ AbortedRefunded = 0x0503_0000,
}
/**
@@ -1334,14 +1284,6 @@ export interface PurchaseRecord {
timestampAccept: TalerPreciseTimestamp | undefined;
/**
- * Pending refunds for the purchase. A refund is pending
- * when the merchant reports a transient error from the exchange.
- *
- * FIXME: Put this into a separate object store?
- */
- // refunds: { [refundKey: string]: WalletRefundItem };
-
- /**
* When was the last refund made?
* Set to 0 if no refund was made on the purchase.
*/
@@ -1404,6 +1346,7 @@ export interface WalletBackupConfState {
lastBackupNonce?: string;
}
+// FIXME: Should these be numeric codes?
export const enum WithdrawalRecordType {
BankManual = "bank-manual",
BankIntegrated = "bank-integrated",
@@ -1428,7 +1371,8 @@ export interface WgInfoBankManual {
export interface WgInfoBankPeerPull {
withdrawalType: WithdrawalRecordType.PeerPullCredit;
- contractTerms: any;
+ // FIXME: include a transaction ID here?
+
/**
* Needed to quickly construct the taler:// URI for the counterparty
* without a join.
@@ -1439,7 +1383,7 @@ export interface WgInfoBankPeerPull {
export interface WgInfoBankPeerPush {
withdrawalType: WithdrawalRecordType.PeerPushCredit;
- contractTerms: any;
+ // FIXME: include a transaction ID here?
}
export interface WgInfoBankRecoup {
@@ -1713,19 +1657,21 @@ export interface BackupProviderRecord {
}
export enum DepositOperationStatus {
- PendingDeposit = 10,
- Aborting = 11,
- PendingTrack = 12,
- PendingKyc = 13,
+ PendingDeposit = 0x0100_0000,
+ PendingTrack = 0x0100_0001,
+ PendingKyc = 0x0100_0002,
+
+ Aborting = 0x0103_0000,
- SuspendedDeposit = 20,
- SuspendedAborting = 21,
- SuspendedTrack = 22,
- SuspendedKyc = 23,
+ SuspendedDeposit = 0x0110_0000,
+ SuspendedTrack = 0x0110_0001,
+ SuspendedKyc = 0x0110_0002,
- Finished = 50,
- Failed = 51,
- Aborted = 52,
+ SuspendedAborting = 0x0113_0000,
+
+ Finished = 0x0500_0000,
+ Failed = 0x0501_0000,
+ Aborted = 0x0503_0000,
}
export interface DepositTrackingInfo {
@@ -1777,10 +1723,8 @@ export interface DepositGroupRecord {
/**
* The counterparty effective deposit amount.
- *
- * FIXME: If possible, rename to counterpartyEffectiveDepositAmount.
*/
- effectiveDepositAmount: AmountString;
+ counterpartyEffectiveDepositAmount: AmountString;
timestampCreated: TalerPreciseTimestamp;
@@ -1788,11 +1732,7 @@ export interface DepositGroupRecord {
operationStatus: DepositOperationStatus;
- // FIXME: Duplication between this and transactionPerCoin!
- depositedPerCoin: boolean[];
-
- // FIXME: Improve name!
- transactionPerCoin: DepositElementStatus[];
+ statusPerCoin: DepositElementStatus[];
/**
* When the deposit transaction was aborted and
@@ -1816,31 +1756,6 @@ export interface DepositKycInfo {
exchangeBaseUrl: string;
}
-/**
- * Record for a deposits that the wallet observed
- * as a result of double spending, but which is not
- * present in the wallet's own database otherwise.
- */
-export interface GhostDepositGroupRecord {
- /**
- * When multiple deposits for the same contract terms hash
- * have a different timestamp, we choose the earliest one.
- */
- timestamp: TalerPreciseTimestamp;
-
- contractTermsHash: string;
-
- deposits: {
- coinPub: string;
- amount: AmountString;
- timestamp: TalerProtocolTimestamp;
- depositFee: AmountString;
- merchantPub: string;
- coinSig: string;
- wireHash: string;
- }[];
-}
-
export interface TombstoneRecord {
/**
* Tombstone ID, with the syntax "tmb:<type>:<key>".
@@ -1848,24 +1763,24 @@ export interface TombstoneRecord {
id: string;
}
-export enum PeerPushPaymentInitiationStatus {
+export enum PeerPushDebitStatus {
/**
* Initiated, but no purse created yet.
*/
- PendingCreatePurse = 10 /* ACTIVE_START */,
- PendingReady = 11,
- AbortingDeletePurse = 12,
- AbortingRefresh = 13,
+ PendingCreatePurse = 0x0100_0000 /* ACTIVE_START */,
+ PendingReady = 0x0100_0001,
+ AbortingDeletePurse = 0x0103_0000,
+ AbortingRefresh = 0x0103_0001,
- SuspendedCreatePurse = 30,
- SuspendedReady = 31,
- SuspendedAbortingDeletePurse = 32,
- SuspendedAbortingRefresh = 33,
+ SuspendedCreatePurse = 0x0110_0000,
+ SuspendedReady = 0x0110_0001,
+ SuspendedAbortingDeletePurse = 0x0113_0000,
+ SuspendedAbortingRefresh = 0x0113_0001,
- Done = 50 /* DORMANT_START */,
- Aborted = 51,
- Failed = 52,
- Expired = 53,
+ Done = 0x0500_0000,
+ Aborted = 0x0503_0000,
+ Failed = 0x0501_0000,
+ Expired = 0x0502_0000,
}
export interface PeerPushPaymentCoinSelection {
@@ -1876,7 +1791,7 @@ export interface PeerPushPaymentCoinSelection {
/**
* Record for a push P2P payment that this wallet initiated.
*/
-export interface PeerPushPaymentInitiationRecord {
+export interface PeerPushDebitRecord {
/**
* What exchange are funds coming from?
*/
@@ -1922,11 +1837,6 @@ export interface PeerPushPaymentInitiationRecord {
*/
contractEncNonce: string;
- /**
- * FIXME: Put those in a different object store!
- */
- contractTerms: PeerContractTerms;
-
purseExpiration: TalerProtocolTimestamp;
timestampCreated: TalerPreciseTimestamp;
@@ -1936,32 +1846,34 @@ export interface PeerPushPaymentInitiationRecord {
/**
* Status of the peer push payment initiation.
*/
- status: PeerPushPaymentInitiationStatus;
+ status: PeerPushDebitStatus;
}
-export enum PeerPullPaymentInitiationStatus {
- PendingCreatePurse = 10 /* ACTIVE_START */,
+export enum PeerPullPaymentCreditStatus {
+ PendingCreatePurse = 0x0100_0000,
/**
* Purse created, waiting for the other party to accept the
* invoice and deposit money into it.
*/
- PendingReady = 11 /* ACTIVE_START + 1 */,
- PendingMergeKycRequired = 12 /* ACTIVE_START + 2 */,
- PendingWithdrawing = 13,
- AbortingDeletePurse = 14,
+ PendingReady = 0x0100_0001,
+ PendingMergeKycRequired = 0x0100_0002,
+ PendingWithdrawing = 0x0100_0003,
+
+ AbortingDeletePurse = 0x0103_0000,
+
+ SuspendedCreatePurse = 0x0110_0000,
+ SuspendedReady = 0x0110_0001,
+ SuspendedMergeKycRequired = 0x0110_0002,
+ SuspendedWithdrawing = 0x0110_0000,
- SuspendedCreatePurse = 30,
- SuspendedReady = 31,
- SuspendedMergeKycRequired = 32,
- SuspendedWithdrawing = 33,
- SuspendedAbortingDeletePurse = 34,
+ SuspendedAbortingDeletePurse = 0x0113_0000,
- Done = 50 /* DORMANT_START */,
- Failed = 51,
- Aborted = 52,
+ Done = 0x0500_0000,
+ Failed = 0x0501_0000,
+ Aborted = 0x0503_0000,
}
-export interface PeerPullPaymentInitiationRecord {
+export interface PeerPullCreditRecord {
/**
* What exchange are we using for the payment request?
*/
@@ -1969,6 +1881,7 @@ export interface PeerPullPaymentInitiationRecord {
/**
* Amount requested.
+ * FIXME: What type of instructed amount is i?
*/
amount: AmountString;
@@ -1999,11 +1912,6 @@ export interface PeerPullPaymentInitiationRecord {
contractEncNonce: string;
- /**
- * FIXME: Put in separate object store!
- */
- contractTerms: PeerContractTerms;
-
mergeTimestamp: TalerPreciseTimestamp;
mergeReserveRowId: number;
@@ -2011,7 +1919,7 @@ export interface PeerPullPaymentInitiationRecord {
/**
* Status of the peer pull payment initiation.
*/
- status: PeerPullPaymentInitiationStatus;
+ status: PeerPullPaymentCreditStatus;
kycInfo?: KycPendingInfo;
@@ -2020,24 +1928,24 @@ export interface PeerPullPaymentInitiationRecord {
withdrawalGroupId: string | undefined;
}
-export enum PeerPushPaymentIncomingStatus {
- PendingMerge = 10 /* ACTIVE_START */,
- PendingMergeKycRequired = 11 /* ACTIVE_START + 1 */,
+export enum PeerPushCreditStatus {
+ PendingMerge = 0x0100_0000,
+ PendingMergeKycRequired = 0x0100_0001,
/**
* Merge was successful and withdrawal group has been created, now
* everything is in the hand of the withdrawal group.
*/
- PendingWithdrawing = 12,
+ PendingWithdrawing = 0x0100_0002,
- SuspendedMerge = 20,
- SuspendedMergeKycRequired = 21,
- SuspendedWithdrawing = 22,
+ SuspendedMerge = 0x0110_0000,
+ SuspendedMergeKycRequired = 0x0110_0001,
+ SuspendedWithdrawing = 0x0110_0002,
- DialogProposed = 30 /* USER_ATTENTION_START */,
+ DialogProposed = 0x0101_0000,
- Done = 50 /* DORMANT_START */,
- Aborted = 51,
- Failed = 52,
+ Done = 0x0500_0000,
+ Aborted = 0x0503_0000,
+ Failed = 0x0501_0000,
}
/**
@@ -2046,7 +1954,7 @@ export enum PeerPushPaymentIncomingStatus {
* Unique: (exchangeBaseUrl, pursePub)
*/
export interface PeerPushPaymentIncomingRecord {
- peerPushPaymentIncomingId: string;
+ peerPushCreditId: string;
exchangeBaseUrl: string;
@@ -2069,7 +1977,7 @@ export interface PeerPushPaymentIncomingRecord {
/**
* Status of the peer push payment incoming initiation.
*/
- status: PeerPushPaymentIncomingStatus;
+ status: PeerPushCreditStatus;
/**
* Associated withdrawal group.
@@ -2090,17 +1998,17 @@ export interface PeerPushPaymentIncomingRecord {
}
export enum PeerPullDebitRecordStatus {
- PendingDeposit = 10 /* ACTIVE_START */,
- AbortingRefresh = 11,
+ PendingDeposit = 0x0100_0001,
+ AbortingRefresh = 0x0103_0001,
- SuspendedDeposit = 20,
- SuspendedAbortingRefresh = 21,
+ SuspendedDeposit = 0x0110_0001,
+ SuspendedAbortingRefresh = 0x0113_0001,
- DialogProposed = 30 /* USER_ATTENTION_START */,
+ DialogProposed = 0x0101_0001,
- DonePaid = 50 /* DORMANT_START */,
- Aborted = 51,
- Failed = 52,
+ Done = 0x0500_0000,
+ Aborted = 0x0503_0000,
+ Failed = 0x0501_0000,
}
export interface PeerPullPaymentCoinSelection {
@@ -2118,7 +2026,7 @@ export interface PeerPullPaymentCoinSelection {
* AKA PeerPullDebit.
*/
export interface PeerPullPaymentIncomingRecord {
- peerPullPaymentIncomingId: string;
+ peerPullDebitId: string;
pursePub: string;
@@ -2184,8 +2092,7 @@ export interface OperationRetryRecord {
*/
export interface CoinAvailabilityRecord {
currency: string;
- amountVal: number;
- amountFrac: number;
+ value: AmountString;
denomPubHash: string;
exchangeBaseUrl: string;
@@ -2263,10 +2170,10 @@ export interface CurrencySettingsRecord {
}
export enum RefundGroupStatus {
- Pending = 10,
- Done = 50,
- Failed = 51,
- Aborted = 52,
+ Pending = 0x0100_0000,
+ Done = 0x0500_0000,
+ Failed = 0x0501_0000,
+ Aborted = 0x0503_0000,
}
/**
@@ -2302,16 +2209,16 @@ export enum RefundItemStatus {
*
* We'll try again!
*/
- Pending = 10,
+ Pending = 0x0100_0000,
/**
* Refund was obtained successfully.
*/
- Done = 50,
+ Done = 0x0500_0000,
/**
* Permanent error reported by the exchange
* for the refund.
*/
- Failed = 51,
+ Failed = 0x0501_0000,
}
/**
@@ -2327,7 +2234,9 @@ export interface RefundItemRecord {
refundGroupId: string;
- // Execution time as claimed by the merchant
+ /**
+ * Execution time as claimed by the merchant
+ */
executionTime: TalerProtocolTimestamp;
/**
@@ -2337,22 +2246,15 @@ export interface RefundItemRecord {
refundAmount: AmountString;
- //refundFee: AmountString;
-
- /**
- * Upper bound on the refresh cost incurred by
- * applying this refund.
- *
- * Might be lower in practice when two refunds on the same
- * coin are refreshed in the same refresh operation.
- */
- //totalRefreshCostBound: AmountString;
-
coinPub: string;
rtxid: number;
}
+export function passthroughCodec<T>(): Codec<T> {
+ return codecForAny();
+}
+
/**
* Schema definition for the IndexedDB
* wallet database.
@@ -2362,7 +2264,6 @@ export const WalletStoresV1 = {
"currencySettings",
describeContents<CurrencySettingsRecord>({
keyPath: ["currency"],
- versionAdded: 3,
}),
{},
),
@@ -2411,42 +2312,11 @@ export const WalletStoresV1 = {
byReservePub: describeIndex("byReservePub", "reservePub", {}),
},
),
- exchangeTos: describeStore(
- "exchangeTos",
- describeContents<ExchangeTosRecord>({
- keyPath: ["exchangeBaseUrl", "etag"],
- }),
- {},
- ),
config: describeStore(
"config",
describeContents<ConfigRecord>({ keyPath: "key" }),
{},
),
- auditorTrust: describeStore(
- "auditorTrust",
- describeContents<AuditorTrustRecord>({
- keyPath: ["currency", "auditorBaseUrl"],
- }),
- {
- byAuditorPub: describeIndex("byAuditorPub", "auditorPub"),
- byUid: describeIndex("byUid", "uids", {
- multiEntry: true,
- }),
- },
- ),
- exchangeTrust: describeStore(
- "exchangeTrust",
- describeContents<ExchangeTrustRecord>({
- keyPath: ["currency", "exchangeBaseUrl"],
- }),
- {
- byExchangeMasterPub: describeIndex(
- "byExchangeMasterPub",
- "exchangeMasterPub",
- ),
- },
- ),
denominations: describeStore(
"denominations",
describeContents<DenominationRecord>({
@@ -2499,6 +2369,13 @@ export const WalletStoresV1 = {
byStatus: describeIndex("byStatus", "operationStatus"),
},
),
+ refreshSessions: describeStore(
+ "refreshSessions",
+ describeContents<RefreshSessionRecord>({
+ keyPath: ["refreshGroupId", "coinIndex"],
+ }),
+ {},
+ ),
recoupGroups: describeStore(
"recoupGroups",
describeContents<RecoupGroupRecord>({
@@ -2607,17 +2484,10 @@ export const WalletStoresV1 = {
}),
{},
),
- ghostDepositGroups: describeStore(
- "ghostDepositGroups",
- describeContents<GhostDepositGroupRecord>({
- keyPath: "contractTermsHash",
- }),
- {},
- ),
- peerPushPaymentIncoming: describeStore(
- "peerPushPaymentIncoming",
+ peerPushCredit: describeStore(
+ "peerPushCredit",
describeContents<PeerPushPaymentIncomingRecord>({
- keyPath: "peerPushPaymentIncomingId",
+ keyPath: "peerPushCreditId",
}),
{
byExchangeAndPurse: describeIndex("byExchangeAndPurse", [
@@ -2628,24 +2498,21 @@ export const WalletStoresV1 = {
"byExchangeAndContractPriv",
["exchangeBaseUrl", "contractPriv"],
{
- versionAdded: 5,
unique: true,
},
),
byWithdrawalGroupId: describeIndex(
"byWithdrawalGroupId",
"withdrawalGroupId",
- {
- versionAdded: 5,
- },
+ {},
),
byStatus: describeIndex("byStatus", "status"),
},
),
- peerPullPaymentIncoming: describeStore(
- "peerPullPaymentIncoming",
+ peerPullDebit: describeStore(
+ "peerPullDebit",
describeContents<PeerPullPaymentIncomingRecord>({
- keyPath: "peerPullPaymentIncomingId",
+ keyPath: "peerPullDebitId",
}),
{
byExchangeAndPurse: describeIndex("byExchangeAndPurse", [
@@ -2656,16 +2523,15 @@ export const WalletStoresV1 = {
"byExchangeAndContractPriv",
["exchangeBaseUrl", "contractPriv"],
{
- versionAdded: 5,
unique: true,
},
),
byStatus: describeIndex("byStatus", "status"),
},
),
- peerPullPaymentInitiations: describeStore(
- "peerPullPaymentInitiations",
- describeContents<PeerPullPaymentInitiationRecord>({
+ peerPullCredit: describeStore(
+ "peerPullCredit",
+ describeContents<PeerPullCreditRecord>({
keyPath: "pursePub",
}),
{
@@ -2673,15 +2539,13 @@ export const WalletStoresV1 = {
byWithdrawalGroupId: describeIndex(
"byWithdrawalGroupId",
"withdrawalGroupId",
- {
- versionAdded: 5,
- },
+ {},
),
},
),
- peerPushPaymentInitiations: describeStore(
- "peerPushPaymentInitiations",
- describeContents<PeerPushPaymentInitiationRecord>({
+ peerPushDebit: describeStore(
+ "peerPushDebit",
+ describeContents<PeerPushDebitRecord>({
keyPath: "pursePub",
}),
{
@@ -2706,7 +2570,6 @@ export const WalletStoresV1 = {
"userAttention",
describeContents<UserAttentionRecord>({
keyPath: ["entityId", "info.type"],
- versionAdded: 2,
}),
{},
),
@@ -2714,20 +2577,16 @@ export const WalletStoresV1 = {
"refundGroups",
describeContents<RefundGroupRecord>({
keyPath: "refundGroupId",
- versionAdded: 7,
}),
{
byProposalId: describeIndex("byProposalId", "proposalId"),
- byStatus: describeIndex("byStatus", "status", {
- versionAdded: 10,
- }),
+ byStatus: describeIndex("byStatus", "status", {}),
},
),
refundItems: describeStore(
"refundItems",
describeContents<RefundItemRecord>({
keyPath: "id",
- versionAdded: 7,
autoIncrement: true,
}),
{
@@ -2742,7 +2601,6 @@ export const WalletStoresV1 = {
"fixups",
describeContents<FixupRecord>({
keyPath: "fixupName",
- versionAdded: 2,
}),
{},
),
@@ -2845,11 +2703,10 @@ export async function exportSingleDb(
dbName,
undefined,
() => {
- // May not happen, since we're not requesting a specific version
- throw Error("unexpected version change");
+ logger.info(`unexpected onversionchange in exportSingleDb of ${dbName}`);
},
() => {
- logger.info("unexpected onupgradeneeded");
+ logger.info(`unexpected onupgradeneeded in exportSingleDb of ${dbName}`);
},
);
@@ -2861,7 +2718,7 @@ export async function exportSingleDb(
return new Promise((resolve, reject) => {
const tx = myDb.transaction(Array.from(myDb.objectStoreNames));
tx.addEventListener("complete", () => {
- myDb.close();
+ //myDb.close();
resolve(singleDbDump);
});
// tslint:disable-next-line:prefer-for-of
@@ -2897,6 +2754,7 @@ export async function exportSingleDb(
if (store.keyPath == null) {
rec.key = structuredEncapsulate(cursor.key);
}
+ storeDump.records.push(rec);
cursor.continue();
}
});
@@ -2925,21 +2783,22 @@ async function recoverFromDump(
db: IDBDatabase,
dbDump: DbDumpDatabase,
): Promise<void> {
- return new Promise((resolve, reject) => {
- const tx = db.transaction(Array.from(db.objectStoreNames), "readwrite");
- tx.addEventListener("complete", () => {
- resolve();
- });
- for (let i = 0; i < db.objectStoreNames.length; i++) {
- const name = db.objectStoreNames[i];
- const storeDump = dbDump.stores[name];
- if (!storeDump) continue;
- for (let rec of storeDump.records) {
- tx.objectStore(name).put(rec.value, rec.key);
- }
+ const tx = db.transaction(Array.from(db.objectStoreNames), "readwrite");
+ const txProm = promiseFromTransaction(tx);
+ const storeNames = db.objectStoreNames;
+ for (let i = 0; i < storeNames.length; i++) {
+ const name = db.objectStoreNames[i];
+ const storeDump = dbDump.stores[name];
+ if (!storeDump) continue;
+ await promiseFromRequest(tx.objectStore(name).clear());
+ logger.info(`importing ${storeDump.records.length} records into ${name}`);
+ for (let rec of storeDump.records) {
+ await promiseFromRequest(tx.objectStore(name).put(rec.value, rec.key));
+ logger.info("importing record done");
}
- tx.commit();
- });
+ }
+ tx.commit();
+ return await txProm;
}
function checkDbDump(x: any): x is DbDump {
@@ -2969,106 +2828,7 @@ export interface FixupDescription {
/**
* Manual migrations between minor versions of the DB schema.
*/
-export const walletDbFixups: FixupDescription[] = [
- {
- name: "RefreshGroupRecord_currency",
- async fn(tx): Promise<void> {
- await tx.refreshGroups.iter().forEachAsync(async (rg) => {
- if (rg.currency) {
- return;
- }
- // Empty refresh group without input coin, delete it!
- if (rg.inputPerCoin.length === 0) {
- await tx.refreshGroups.delete(rg.refreshGroupId);
- return;
- }
- rg.currency = Amounts.parseOrThrow(rg.inputPerCoin[0]).currency;
- await tx.refreshGroups.put(rg);
- });
- },
- },
- {
- name: "DepositGroupRecord_transactionPerCoin",
- async fn(tx): Promise<void> {
- await tx.depositGroups.iter().forEachAsync(async (dg) => {
- if (dg.transactionPerCoin) {
- return;
- }
- dg.transactionPerCoin = dg.depositedPerCoin.map(
- (c) => DepositElementStatus.Unknown,
- );
- await tx.depositGroups.put(dg);
- });
- },
- },
- {
- name: "PeerPullPaymentIncomingRecord_totalCostEstimated_add",
- async fn(tx): Promise<void> {
- await tx.peerPullPaymentIncoming.iter().forEachAsync(async (pi) => {
- if (pi.totalCostEstimated) {
- return;
- }
- // Not really the cost, but a good substitute for older transactions
- // that don't sture the effective cost of the transaction.
- pi.totalCostEstimated = pi.contractTerms.amount;
- await tx.peerPullPaymentIncoming.put(pi);
- });
- },
- },
- {
- name: "PeerPushPaymentIncomingRecord_totalCostEstimated_add",
- async fn(tx): Promise<void> {
- await tx.peerPushPaymentIncoming.iter().forEachAsync(async (pi) => {
- if (pi.estimatedAmountEffective) {
- return;
- }
- const contractTerms = await tx.contractTerms.get(pi.contractTermsHash);
- if (!contractTerms) {
- // Not sure what we can do here!
- } else {
- // Not really the cost, but a good substitute for older transactions
- // that don't sture the effective cost of the transaction.
- pi.estimatedAmountEffective = contractTerms.contractTermsRaw.amount;
- await tx.peerPushPaymentIncoming.put(pi);
- }
- });
- },
- },
- {
- name: "PeerPullPaymentInitiationRecord_estimatedAmountEffective_add",
- async fn(tx): Promise<void> {
- await tx.peerPullPaymentInitiations.iter().forEachAsync(async (pi) => {
- if (pi.estimatedAmountEffective) {
- return;
- }
- pi.estimatedAmountEffective = pi.amount;
- await tx.peerPullPaymentInitiations.put(pi);
- });
- },
- },
- {
- name: "PeerPushPaymentInitiationRecord_ALL_removeLegacyTx",
- async fn(tx): Promise<void> {
- await tx.peerPushPaymentInitiations.iter().forEachAsync(async (pi) => {
- // Remove legacy transactions that don't have the totalCost field yet.
- if (!pi.totalCost) {
- await tx.peerPushPaymentInitiations.delete(pi.pursePub);
- }
- });
- },
- },
- {
- name: "CoinAvailabilityRecord_visibleCoinCount_add",
- async fn(tx): Promise<void> {
- await tx.coinAvailability.iter().forEachAsync(async (r) => {
- if (r.visibleCoinCount == null) {
- r.visibleCoinCount = r.freshCoinCount;
- await tx.coinAvailability.put(r);
- }
- });
- },
- },
-];
+export const walletDbFixups: FixupDescription[] = [];
const logger = new Logger("db.ts");
@@ -3196,6 +2956,17 @@ function promiseFromTransaction(transaction: IDBTransaction): Promise<void> {
});
}
+export function promiseFromRequest(request: IDBRequest): Promise<any> {
+ return new Promise((resolve, reject) => {
+ request.onsuccess = () => {
+ resolve(request.result);
+ };
+ request.onerror = () => {
+ reject(request.error);
+ };
+ });
+}
+
/**
* Purge all data in the given database.
*/