2021-06-10 10:37:49 +02:00
|
|
|
/*
|
|
|
|
This file is part of GNU Taler
|
2022-09-20 21:44:21 +02:00
|
|
|
(C) 2021-2022 Taler Systems S.A.
|
2021-06-10 10:37:49 +02:00
|
|
|
|
|
|
|
GNU Taler is free software; you can redistribute it and/or modify it under the
|
|
|
|
terms of the GNU General Public License as published by the Free Software
|
|
|
|
Foundation; either version 3, or (at your option) any later version.
|
|
|
|
|
|
|
|
GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
|
|
|
|
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
|
|
|
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
|
|
|
|
|
|
|
You should have received a copy of the GNU General Public License along with
|
|
|
|
GNU Taler; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
|
|
|
|
*/
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Imports.
|
|
|
|
*/
|
2023-01-11 14:19:24 +01:00
|
|
|
import {
|
|
|
|
Event,
|
|
|
|
IDBDatabase,
|
|
|
|
IDBFactory,
|
2023-01-12 19:50:36 +01:00
|
|
|
IDBObjectStore,
|
2023-09-01 10:52:15 +02:00
|
|
|
IDBRequest,
|
2023-01-11 14:19:24 +01:00
|
|
|
IDBTransaction,
|
2023-08-30 15:54:44 +02:00
|
|
|
structuredEncapsulate,
|
2023-01-11 14:19:24 +01:00
|
|
|
} from "@gnu-taler/idb-bridge";
|
2021-01-13 00:50:56 +01:00
|
|
|
import {
|
2022-10-15 21:26:36 +02:00
|
|
|
AgeCommitmentProof,
|
2023-09-12 13:48:52 +02:00
|
|
|
AmountJson,
|
2021-05-12 14:16:01 +02:00
|
|
|
AmountString,
|
2023-09-08 13:33:21 +02:00
|
|
|
Amounts,
|
|
|
|
AttentionInfo,
|
|
|
|
Codec,
|
2022-10-15 21:26:36 +02:00
|
|
|
CoinEnvelope,
|
2023-09-08 13:33:21 +02:00
|
|
|
CoinPublicKeyString,
|
2022-10-15 21:26:36 +02:00
|
|
|
CoinRefreshRequest,
|
|
|
|
CoinStatus,
|
2023-09-08 13:33:21 +02:00
|
|
|
DenomSelectionState,
|
2022-10-15 21:26:36 +02:00
|
|
|
DenominationInfo,
|
2021-11-17 10:23:22 +01:00
|
|
|
DenominationPubKey,
|
2022-10-15 21:26:36 +02:00
|
|
|
EddsaPublicKeyString,
|
|
|
|
EddsaSignatureString,
|
|
|
|
ExchangeAuditor,
|
|
|
|
ExchangeGlobalFees,
|
2023-09-08 13:33:21 +02:00
|
|
|
HashCodeString,
|
2021-05-12 14:16:01 +02:00
|
|
|
InternationalizedString,
|
2023-09-08 13:33:21 +02:00
|
|
|
Logger,
|
|
|
|
MerchantContractTerms,
|
2021-05-12 14:16:01 +02:00
|
|
|
MerchantInfo,
|
2022-10-15 21:26:36 +02:00
|
|
|
PayCoinSelection,
|
|
|
|
PeerContractTerms,
|
2021-05-12 14:16:01 +02:00
|
|
|
RefreshReason,
|
2022-03-22 21:16:38 +01:00
|
|
|
TalerErrorDetail,
|
2023-09-08 13:33:21 +02:00
|
|
|
TalerPreciseTimestamp,
|
2022-03-18 15:32:41 +01:00
|
|
|
TalerProtocolDuration,
|
2022-10-15 21:26:36 +02:00
|
|
|
TalerProtocolTimestamp,
|
2022-10-14 22:38:40 +02:00
|
|
|
TransactionIdStr,
|
2022-10-15 21:26:36 +02:00
|
|
|
UnblindedSignature,
|
|
|
|
WireInfo,
|
2023-09-07 20:35:46 +02:00
|
|
|
codecForAny,
|
2021-05-12 14:16:01 +02:00
|
|
|
} from "@gnu-taler/taler-util";
|
2023-09-08 13:33:21 +02:00
|
|
|
import { RetryInfo, TaskIdentifiers } from "./operations/common.js";
|
2022-10-15 21:26:36 +02:00
|
|
|
import {
|
2023-01-11 14:19:24 +01:00
|
|
|
DbAccess,
|
2023-08-29 20:35:49 +02:00
|
|
|
DbReadOnlyTransaction,
|
|
|
|
DbReadWriteTransaction,
|
2023-01-11 14:19:24 +01:00
|
|
|
GetReadWriteAccess,
|
|
|
|
IndexDescriptor,
|
|
|
|
StoreDescriptor,
|
2023-08-29 20:35:49 +02:00
|
|
|
StoreNames,
|
2023-01-11 14:19:24 +01:00
|
|
|
StoreWithIndexes,
|
2023-09-08 13:33:21 +02:00
|
|
|
describeContents,
|
|
|
|
describeIndex,
|
|
|
|
describeStore,
|
|
|
|
openDatabase,
|
2022-10-15 21:26:36 +02:00
|
|
|
} from "./util/query.js";
|
2019-07-31 01:33:56 +02:00
|
|
|
|
2022-09-20 21:44:21 +02:00
|
|
|
/**
|
|
|
|
* This file contains the database schema of the Taler wallet together
|
|
|
|
* with some helper functions.
|
|
|
|
*
|
|
|
|
* Some design considerations:
|
|
|
|
* - By convention, each object store must have a corresponding "<Name>Record"
|
|
|
|
* interface defined for it.
|
|
|
|
* - For records that represent operations, there should be exactly
|
|
|
|
* one top-level enum field that indicates the status of the operation.
|
|
|
|
* This field should be present even if redundant, because the field
|
|
|
|
* will have an index.
|
|
|
|
* - Amounts are stored as strings, except when they are needed for
|
|
|
|
* indexing.
|
2022-09-21 20:46:45 +02:00
|
|
|
* - Every record that has a corresponding transaction item must have
|
|
|
|
* an index for a mandatory timestamp field.
|
2022-09-20 21:44:21 +02:00
|
|
|
* - Optional fields should be avoided, use "T | undefined" instead.
|
2022-09-21 21:13:31 +02:00
|
|
|
* - Do all records have some obvious, indexed field that can
|
|
|
|
* be used for range queries?
|
2022-09-20 21:44:21 +02:00
|
|
|
*
|
|
|
|
* @author Florian Dold <dold@taler.net>
|
|
|
|
*/
|
|
|
|
|
2023-09-08 11:45:31 +02:00
|
|
|
/**
|
|
|
|
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.
|
2023-09-08 12:26:58 +02:00
|
|
|
- More object stores should have an "id" primary key,
|
|
|
|
as this makes referencing less expensive.
|
2023-09-08 13:33:21 +02:00
|
|
|
- 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.
|
2023-09-08 11:45:31 +02:00
|
|
|
*/
|
|
|
|
|
2020-05-08 14:15:23 +02:00
|
|
|
/**
|
2020-09-08 17:46:11 +02:00
|
|
|
* 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.
|
2020-05-08 14:15:23 +02:00
|
|
|
*/
|
2023-09-07 20:35:46 +02:00
|
|
|
export const TALER_WALLET_MAIN_DB_NAME = "taler-wallet-main-v10";
|
2021-01-13 00:50:56 +01:00
|
|
|
|
2021-08-19 13:48:36 +02:00
|
|
|
/**
|
|
|
|
* Name of the metadata database. This database is used
|
|
|
|
* to track major migrations of the main Taler database.
|
|
|
|
*
|
|
|
|
* (Minor migrations are handled via upgrade transactions.)
|
|
|
|
*/
|
2023-08-30 16:51:51 +02:00
|
|
|
export const TALER_WALLET_META_DB_NAME = "taler-wallet-meta";
|
2021-01-13 00:50:56 +01:00
|
|
|
|
2023-08-30 18:33:56 +02:00
|
|
|
/**
|
2023-09-06 10:48:16 +02:00
|
|
|
* 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.
|
2023-08-30 18:33:56 +02:00
|
|
|
*/
|
2023-09-01 10:52:15 +02:00
|
|
|
export const TALER_WALLET_STORED_BACKUPS_DB_NAME =
|
|
|
|
"taler-wallet-stored-backups";
|
2023-08-30 18:33:56 +02:00
|
|
|
|
2023-09-06 10:48:16 +02:00
|
|
|
/**
|
|
|
|
* Name of the "meta config" database.
|
|
|
|
*/
|
2021-08-19 13:48:36 +02:00
|
|
|
export const CURRENT_DB_CONFIG_KEY = "currentMainDbName";
|
2019-07-31 01:33:56 +02:00
|
|
|
|
2019-12-13 13:10:20 +01:00
|
|
|
/**
|
2020-05-08 14:15:23 +02:00
|
|
|
* Current database minor version, should be incremented
|
|
|
|
* each time we do minor schema changes on the database.
|
|
|
|
* A change is considered minor when fields are added in a
|
|
|
|
* backwards-compatible way or object stores and indices
|
|
|
|
* are added.
|
2019-12-13 13:10:20 +01:00
|
|
|
*/
|
2023-09-07 20:35:46 +02:00
|
|
|
export const WALLET_DB_MINOR_VERSION = 1;
|
2020-11-16 14:12:37 +01:00
|
|
|
|
2023-09-06 10:48:16 +02:00
|
|
|
/**
|
2023-09-07 20:35:46 +02:00
|
|
|
* 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
|
2022-10-14 21:00:13 +02:00
|
|
|
*/
|
2022-09-21 20:46:45 +02:00
|
|
|
|
2022-09-20 21:44:21 +02:00
|
|
|
/**
|
|
|
|
* Status of a withdrawal.
|
|
|
|
*/
|
2022-09-21 20:46:45 +02:00
|
|
|
export enum WithdrawalGroupStatus {
|
2021-03-17 17:56:37 +01:00
|
|
|
/**
|
|
|
|
* Reserve must be registered with the bank.
|
|
|
|
*/
|
2023-09-08 11:45:31 +02:00
|
|
|
PendingRegisteringBank = 0x0100_0001,
|
|
|
|
SuspendedRegisteringBank = 0x0110_0001,
|
2021-03-17 17:56:37 +01:00
|
|
|
|
|
|
|
/**
|
|
|
|
* 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).
|
|
|
|
*/
|
2023-09-08 11:45:31 +02:00
|
|
|
PendingWaitConfirmBank = 0x0100_0002,
|
|
|
|
SuspendedWaitConfirmBank = 0x0110_0002,
|
2021-03-17 17:56:37 +01:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Querying reserve status with the exchange.
|
|
|
|
*/
|
2023-09-08 11:45:31 +02:00
|
|
|
PendingQueryingStatus = 0x0100_0003,
|
|
|
|
SuspendedQueryingStatus = 0x0110_0003,
|
2021-03-17 17:56:37 +01:00
|
|
|
|
2022-09-23 21:47:38 +02:00
|
|
|
/**
|
|
|
|
* Ready for withdrawal.
|
|
|
|
*/
|
2023-09-08 11:45:31 +02:00
|
|
|
PendingReady = 0x0100_0004,
|
|
|
|
SuspendedReady = 0x0110_0004,
|
2022-09-23 21:47:38 +02:00
|
|
|
|
2023-04-25 23:56:57 +02:00
|
|
|
/**
|
|
|
|
* We are telling the bank that we don't want to complete
|
|
|
|
* the withdrawal!
|
|
|
|
*/
|
2023-09-08 11:45:31 +02:00
|
|
|
AbortingBank = 0x0103_0001,
|
|
|
|
SuspendedAbortingBank = 0x0113_0001,
|
2023-04-25 23:56:57 +02:00
|
|
|
|
2023-05-02 10:04:58 +02:00
|
|
|
/**
|
|
|
|
* Exchange wants KYC info from the user.
|
|
|
|
*/
|
2023-09-08 11:45:31 +02:00
|
|
|
PendingKyc = 0x0100_0005,
|
|
|
|
SuspendedKyc = 0x0110_005,
|
2023-05-02 10:04:58 +02:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Exchange is doing AML checks.
|
|
|
|
*/
|
2023-09-08 11:45:31 +02:00
|
|
|
PendingAml = 0x0100_0006,
|
|
|
|
SuspendedAml = 0x0100_0006,
|
2023-05-02 10:04:58 +02:00
|
|
|
|
2021-03-17 17:56:37 +01:00
|
|
|
/**
|
|
|
|
* The corresponding withdraw record has been created.
|
|
|
|
* No further processing is done, unless explicitly requested
|
|
|
|
* by the user.
|
|
|
|
*/
|
2023-09-07 20:35:46 +02:00
|
|
|
Done = 0x0500_0000,
|
2021-03-17 17:56:37 +01:00
|
|
|
|
|
|
|
/**
|
|
|
|
* The bank aborted the withdrawal.
|
|
|
|
*/
|
2023-09-08 11:45:31 +02:00
|
|
|
FailedBankAborted = 0x0501_0001,
|
2023-04-25 23:56:57 +02:00
|
|
|
|
2023-09-08 11:45:31 +02:00
|
|
|
FailedAbortingBank = 0x0501_0002,
|
2023-05-05 10:56:42 +02:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Aborted in a state where we were supposed to
|
|
|
|
* talk to the exchange. Money might have been
|
|
|
|
* wired or not.
|
|
|
|
*/
|
2023-09-07 20:35:46 +02:00
|
|
|
AbortedExchange = 0x0503_0001,
|
2023-06-06 17:07:09 +02:00
|
|
|
|
2023-09-07 20:35:46 +02:00
|
|
|
AbortedBank = 0x0503_0002,
|
2021-03-17 17:56:37 +01:00
|
|
|
}
|
|
|
|
|
2021-08-19 13:48:36 +02:00
|
|
|
/**
|
2022-10-14 21:00:13 +02:00
|
|
|
* Extra info about a withdrawal that is used
|
2021-08-19 13:48:36 +02:00
|
|
|
* with a bank-integrated withdrawal.
|
|
|
|
*/
|
2021-03-17 17:56:37 +01:00
|
|
|
export interface ReserveBankInfo {
|
2022-08-24 19:44:24 +02:00
|
|
|
talerWithdrawUri: string;
|
2021-03-17 17:56:37 +01:00
|
|
|
|
2021-08-19 13:48:36 +02:00
|
|
|
/**
|
|
|
|
* URL that the user can be redirected to, and allows
|
|
|
|
* them to confirm (or abort) the bank-integrated withdrawal.
|
|
|
|
*/
|
2022-09-21 21:13:31 +02:00
|
|
|
confirmUrl: string | undefined;
|
2021-03-17 17:56:37 +01:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Exchange payto URI that the bank will use to fund the reserve.
|
|
|
|
*/
|
|
|
|
exchangePaytoUri: string;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Time when the information about this reserve was posted to the bank.
|
|
|
|
*
|
|
|
|
* Only applies if bankWithdrawStatusUrl is defined.
|
|
|
|
*
|
2022-01-12 16:54:38 +01:00
|
|
|
* Set to undefined if that hasn't happened yet.
|
2021-03-17 17:56:37 +01:00
|
|
|
*/
|
2023-05-26 12:19:32 +02:00
|
|
|
timestampReserveInfoPosted: TalerPreciseTimestamp | undefined;
|
2021-03-17 17:56:37 +01:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Time when the reserve was confirmed by the bank.
|
|
|
|
*
|
|
|
|
* Set to undefined if not confirmed yet.
|
|
|
|
*/
|
2023-05-26 12:19:32 +02:00
|
|
|
timestampBankConfirmed: TalerPreciseTimestamp | undefined;
|
2021-03-17 17:56:37 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Status of a denomination.
|
|
|
|
*/
|
2021-08-24 15:43:06 +02:00
|
|
|
export enum DenominationVerificationStatus {
|
2021-03-17 17:56:37 +01:00
|
|
|
/**
|
2023-09-08 11:45:31 +02:00
|
|
|
* Verification was delayed (pending).
|
2021-03-17 17:56:37 +01:00
|
|
|
*/
|
2023-09-08 11:45:31 +02:00
|
|
|
Unverified = 0x0100_0000,
|
2022-09-21 21:13:31 +02:00
|
|
|
|
2021-03-17 17:56:37 +01:00
|
|
|
/**
|
|
|
|
* Verified as valid.
|
|
|
|
*/
|
2023-09-07 20:35:46 +02:00
|
|
|
VerifiedGood = 0x0500_0000,
|
2022-09-21 21:13:31 +02:00
|
|
|
|
2021-03-17 17:56:37 +01:00
|
|
|
/**
|
|
|
|
* Verified as invalid.
|
|
|
|
*/
|
2023-09-07 20:35:46 +02:00
|
|
|
VerifiedBad = 0x0501_0000,
|
2021-03-17 17:56:37 +01:00
|
|
|
}
|
|
|
|
|
2022-09-14 21:27:03 +02:00
|
|
|
export interface DenomFees {
|
2021-03-17 17:56:37 +01:00
|
|
|
/**
|
|
|
|
* Fee for withdrawing.
|
|
|
|
*/
|
2022-11-02 17:42:14 +01:00
|
|
|
feeWithdraw: AmountString;
|
2021-03-17 17:56:37 +01:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Fee for depositing.
|
|
|
|
*/
|
2022-11-02 17:42:14 +01:00
|
|
|
feeDeposit: AmountString;
|
2021-03-17 17:56:37 +01:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Fee for refreshing.
|
|
|
|
*/
|
2022-11-02 17:42:14 +01:00
|
|
|
feeRefresh: AmountString;
|
2021-03-17 17:56:37 +01:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Fee for refunding.
|
|
|
|
*/
|
2022-11-02 17:42:14 +01:00
|
|
|
feeRefund: AmountString;
|
2022-09-14 21:27:03 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Denomination record as stored in the wallet's database.
|
|
|
|
*/
|
|
|
|
export interface DenominationRecord {
|
2023-09-08 13:33:21 +02:00
|
|
|
/**
|
|
|
|
* Currency of the denomination.
|
|
|
|
*
|
|
|
|
* Stored separately as we have an index on it.
|
|
|
|
*/
|
2022-09-14 21:27:03 +02:00
|
|
|
currency: string;
|
|
|
|
|
2023-09-08 13:33:21 +02:00
|
|
|
value: AmountString;
|
2022-09-14 21:27:03 +02:00
|
|
|
|
|
|
|
/**
|
|
|
|
* The denomination public key.
|
|
|
|
*/
|
|
|
|
denomPub: DenominationPubKey;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Hash of the denomination public key.
|
|
|
|
* Stored in the database for faster lookups.
|
|
|
|
*/
|
|
|
|
denomPubHash: string;
|
|
|
|
|
|
|
|
fees: DenomFees;
|
2021-03-17 17:56:37 +01:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Validity start date of the denomination.
|
|
|
|
*/
|
2022-03-18 15:32:41 +01:00
|
|
|
stampStart: TalerProtocolTimestamp;
|
2021-03-17 17:56:37 +01:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Date after which the currency can't be withdrawn anymore.
|
|
|
|
*/
|
2022-03-18 15:32:41 +01:00
|
|
|
stampExpireWithdraw: TalerProtocolTimestamp;
|
2021-03-17 17:56:37 +01:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Date after the denomination officially doesn't exist anymore.
|
|
|
|
*/
|
2022-03-18 15:32:41 +01:00
|
|
|
stampExpireLegal: TalerProtocolTimestamp;
|
2021-03-17 17:56:37 +01:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Data after which coins of this denomination can't be deposited anymore.
|
|
|
|
*/
|
2022-03-18 15:32:41 +01:00
|
|
|
stampExpireDeposit: TalerProtocolTimestamp;
|
2021-03-17 17:56:37 +01:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Signature by the exchange's master key over the denomination
|
|
|
|
* information.
|
|
|
|
*/
|
|
|
|
masterSig: string;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Did we verify the signature on the denomination?
|
|
|
|
*/
|
2021-08-24 15:43:06 +02:00
|
|
|
verificationStatus: DenominationVerificationStatus;
|
2021-03-17 17:56:37 +01:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Was this denomination still offered by the exchange the last time
|
|
|
|
* we checked?
|
|
|
|
* Only false when the exchange redacts a previously published denomination.
|
|
|
|
*/
|
|
|
|
isOffered: boolean;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Did the exchange revoke the denomination?
|
|
|
|
* When this field is set to true in the database, the same transaction
|
|
|
|
* should also mark all affected coins as revoked.
|
|
|
|
*/
|
|
|
|
isRevoked: boolean;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Base URL of the exchange.
|
|
|
|
*/
|
|
|
|
exchangeBaseUrl: string;
|
2021-06-11 13:26:18 +02:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Master public key of the exchange that made the signature
|
|
|
|
* on the denomination.
|
|
|
|
*/
|
|
|
|
exchangeMasterPub: string;
|
2021-08-19 13:48:36 +02:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Latest list issue date of the "/keys" response
|
|
|
|
* that includes this denomination.
|
|
|
|
*/
|
2022-03-18 15:32:41 +01:00
|
|
|
listIssueDate: TalerProtocolTimestamp;
|
2021-03-17 17:56:37 +01:00
|
|
|
}
|
|
|
|
|
2022-09-14 21:27:03 +02:00
|
|
|
export namespace DenominationRecord {
|
2022-09-16 17:35:06 +02:00
|
|
|
export function toDenomInfo(d: DenominationRecord): DenominationInfo {
|
2022-09-14 21:27:03 +02:00
|
|
|
return {
|
|
|
|
denomPub: d.denomPub,
|
|
|
|
denomPubHash: d.denomPubHash,
|
2022-11-02 17:42:14 +01:00
|
|
|
feeDeposit: Amounts.stringify(d.fees.feeDeposit),
|
|
|
|
feeRefresh: Amounts.stringify(d.fees.feeRefresh),
|
|
|
|
feeRefund: Amounts.stringify(d.fees.feeRefund),
|
|
|
|
feeWithdraw: Amounts.stringify(d.fees.feeWithdraw),
|
2022-09-14 21:27:03 +02:00
|
|
|
stampExpireDeposit: d.stampExpireDeposit,
|
|
|
|
stampExpireLegal: d.stampExpireLegal,
|
|
|
|
stampExpireWithdraw: d.stampExpireWithdraw,
|
|
|
|
stampStart: d.stampStart,
|
2023-09-08 13:33:21 +02:00
|
|
|
value: Amounts.stringify(d.value),
|
2022-09-15 20:16:42 +02:00
|
|
|
exchangeBaseUrl: d.exchangeBaseUrl,
|
2022-09-14 21:27:03 +02:00
|
|
|
};
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-10-15 16:03:48 +02:00
|
|
|
export interface ExchangeSignkeysRecord {
|
|
|
|
stampStart: TalerProtocolTimestamp;
|
|
|
|
stampExpire: TalerProtocolTimestamp;
|
|
|
|
stampEnd: TalerProtocolTimestamp;
|
|
|
|
signkeyPub: EddsaPublicKeyString;
|
|
|
|
masterSig: EddsaSignatureString;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Exchange details that thiis signkeys record belongs to.
|
|
|
|
*/
|
|
|
|
exchangeDetailsRowId: number;
|
|
|
|
}
|
|
|
|
|
2021-08-19 13:48:36 +02:00
|
|
|
/**
|
2022-10-14 21:00:13 +02:00
|
|
|
* Exchange details for a particular
|
|
|
|
* (exchangeBaseUrl, masterPublicKey, currency) tuple.
|
2021-08-19 13:48:36 +02:00
|
|
|
*/
|
2021-06-02 13:23:51 +02:00
|
|
|
export interface ExchangeDetailsRecord {
|
2022-10-15 16:03:48 +02:00
|
|
|
rowId?: number;
|
|
|
|
|
2021-03-17 17:56:37 +01:00
|
|
|
/**
|
|
|
|
* Master public key of the exchange.
|
|
|
|
*/
|
|
|
|
masterPublicKey: string;
|
|
|
|
|
2021-06-02 13:23:51 +02:00
|
|
|
exchangeBaseUrl: string;
|
2021-03-17 17:56:37 +01:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Currency that the exchange offers.
|
|
|
|
*/
|
|
|
|
currency: string;
|
|
|
|
|
2021-06-02 13:23:51 +02:00
|
|
|
/**
|
|
|
|
* Auditors (partially) auditing the exchange.
|
|
|
|
*/
|
2021-11-27 20:56:58 +01:00
|
|
|
auditors: ExchangeAuditor[];
|
2021-06-02 13:23:51 +02:00
|
|
|
|
2021-03-17 17:56:37 +01:00
|
|
|
/**
|
|
|
|
* Last observed protocol version.
|
|
|
|
*/
|
2022-10-14 21:00:13 +02:00
|
|
|
protocolVersionRange: string;
|
2021-03-17 17:56:37 +01:00
|
|
|
|
2022-03-18 15:32:41 +01:00
|
|
|
reserveClosingDelay: TalerProtocolDuration;
|
2021-03-17 17:56:37 +01:00
|
|
|
|
2022-10-12 19:36:30 +02:00
|
|
|
/**
|
|
|
|
* Fees for exchange services
|
|
|
|
*/
|
2022-10-12 20:58:10 +02:00
|
|
|
globalFees: ExchangeGlobalFees[];
|
2022-10-14 18:40:04 +02:00
|
|
|
|
2021-06-02 13:23:51 +02:00
|
|
|
/**
|
2022-10-14 22:10:03 +02:00
|
|
|
* Etag of the current ToS of the exchange.
|
2021-06-02 13:23:51 +02:00
|
|
|
*/
|
2022-10-14 22:10:03 +02:00
|
|
|
tosCurrentEtag: string;
|
2021-06-02 13:23:51 +02:00
|
|
|
|
2021-09-13 20:32:06 +02:00
|
|
|
/**
|
2022-10-14 22:10:03 +02:00
|
|
|
* Information about ToS acceptance from the user.
|
2021-09-13 20:32:06 +02:00
|
|
|
*/
|
2022-10-14 22:10:03 +02:00
|
|
|
tosAccepted:
|
|
|
|
| {
|
|
|
|
etag: string;
|
2023-05-26 12:19:32 +02:00
|
|
|
timestamp: TalerPreciseTimestamp;
|
2022-10-14 22:10:03 +02:00
|
|
|
}
|
|
|
|
| undefined;
|
2021-09-13 20:32:06 +02:00
|
|
|
|
2022-10-14 22:10:03 +02:00
|
|
|
wireInfo: WireInfo;
|
2022-11-01 15:31:48 +01:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Age restrictions supported by the exchange (bitmask).
|
|
|
|
*/
|
|
|
|
ageMask?: number;
|
2022-10-14 22:10:03 +02:00
|
|
|
}
|
2021-06-02 13:23:51 +02:00
|
|
|
|
2022-10-14 22:10:03 +02:00
|
|
|
export interface ExchangeTosRecord {
|
|
|
|
exchangeBaseUrl: string;
|
|
|
|
|
|
|
|
etag: string;
|
2021-06-02 13:23:51 +02:00
|
|
|
|
2021-06-14 11:45:05 +02:00
|
|
|
/**
|
2022-10-14 22:10:03 +02:00
|
|
|
* Terms of service text or undefined if not downloaded yet.
|
|
|
|
*
|
|
|
|
* This is just used as a cache of the last downloaded ToS.
|
2021-06-15 18:52:43 +02:00
|
|
|
*
|
2021-06-14 11:45:05 +02:00
|
|
|
*/
|
2022-10-14 22:10:03 +02:00
|
|
|
termsOfServiceText: string | undefined;
|
2021-06-14 11:45:05 +02:00
|
|
|
|
2022-10-14 22:10:03 +02:00
|
|
|
/**
|
|
|
|
* Content-type of the last downloaded termsOfServiceText.
|
|
|
|
*/
|
|
|
|
termsOfServiceContentType: string | undefined;
|
2021-03-17 17:56:37 +01:00
|
|
|
}
|
|
|
|
|
2021-06-02 13:23:51 +02:00
|
|
|
export interface ExchangeDetailsPointer {
|
|
|
|
masterPublicKey: string;
|
2021-11-23 23:51:12 +01:00
|
|
|
|
2021-06-02 13:23:51 +02:00
|
|
|
currency: string;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Timestamp when the (masterPublicKey, currency) pointer
|
|
|
|
* has been updated.
|
|
|
|
*/
|
2023-05-26 12:19:32 +02:00
|
|
|
updateClock: TalerPreciseTimestamp;
|
2021-03-17 17:56:37 +01:00
|
|
|
}
|
|
|
|
|
2023-08-30 15:54:44 +02:00
|
|
|
export enum ExchangeEntryDbRecordStatus {
|
|
|
|
Preset = 1,
|
|
|
|
Ephemeral = 2,
|
|
|
|
Used = 3,
|
|
|
|
}
|
|
|
|
|
2023-09-08 11:45:31 +02:00
|
|
|
// FIXME: Use status ranges for this as well?
|
2023-08-30 15:54:44 +02:00
|
|
|
export enum ExchangeEntryDbUpdateStatus {
|
|
|
|
Initial = 1,
|
|
|
|
InitialUpdate = 2,
|
|
|
|
Suspended = 3,
|
|
|
|
Failed = 4,
|
|
|
|
OutdatedUpdate = 5,
|
|
|
|
Ready = 6,
|
|
|
|
ReadyUpdate = 7,
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Timestamp stored as a IEEE 754 double, in milliseconds.
|
|
|
|
*/
|
|
|
|
export type DbIndexableTimestampMs = number;
|
|
|
|
|
2021-03-17 17:56:37 +01:00
|
|
|
/**
|
|
|
|
* Exchange record as stored in the wallet's database.
|
|
|
|
*/
|
2023-08-30 15:54:44 +02:00
|
|
|
export interface ExchangeEntryRecord {
|
2021-03-17 17:56:37 +01:00
|
|
|
/**
|
|
|
|
* Base url of the exchange.
|
|
|
|
*/
|
|
|
|
baseUrl: string;
|
|
|
|
|
2023-02-19 23:13:44 +01:00
|
|
|
/**
|
|
|
|
* When did we confirm the last withdrawal from this exchange?
|
|
|
|
*
|
|
|
|
* Used mostly in the UI to suggest exchanges.
|
|
|
|
*/
|
2023-05-26 12:19:32 +02:00
|
|
|
lastWithdrawal?: TalerPreciseTimestamp;
|
2023-02-19 23:13:44 +01:00
|
|
|
|
2021-08-19 13:48:36 +02:00
|
|
|
/**
|
|
|
|
* Pointer to the current exchange details.
|
2022-10-14 21:00:13 +02:00
|
|
|
*
|
|
|
|
* Should usually not change. Only changes when the
|
|
|
|
* exchange advertises a different master public key and/or
|
|
|
|
* currency.
|
2022-10-16 20:15:55 +02:00
|
|
|
*
|
2022-11-02 17:09:59 +01:00
|
|
|
* We could use a rowID here, but having the currency in the
|
2022-11-02 17:42:14 +01:00
|
|
|
* details pointer lets us do fewer DB queries
|
2021-08-19 13:48:36 +02:00
|
|
|
*/
|
2021-06-02 13:23:51 +02:00
|
|
|
detailsPointer: ExchangeDetailsPointer | undefined;
|
2021-03-17 17:56:37 +01:00
|
|
|
|
2023-08-30 15:54:44 +02:00
|
|
|
entryStatus: ExchangeEntryDbRecordStatus;
|
|
|
|
|
|
|
|
updateStatus: ExchangeEntryDbUpdateStatus;
|
2021-03-17 17:56:37 +01:00
|
|
|
|
|
|
|
/**
|
2023-08-30 15:54:44 +02:00
|
|
|
* Last time when the exchange /keys info was updated.
|
2021-03-17 17:56:37 +01:00
|
|
|
*/
|
2023-05-26 12:19:32 +02:00
|
|
|
lastUpdate: TalerPreciseTimestamp | undefined;
|
2021-03-17 17:56:37 +01:00
|
|
|
|
|
|
|
/**
|
2021-06-10 16:32:37 +02:00
|
|
|
* Next scheduled update for the exchange.
|
2021-06-09 15:14:17 +02:00
|
|
|
*
|
2021-06-10 16:32:37 +02:00
|
|
|
* (This field must always be present, so we can index on the timestamp.)
|
2023-08-30 15:54:44 +02:00
|
|
|
*
|
|
|
|
* FIXME: To index on the timestamp, this needs to be a number of
|
|
|
|
* binary timestamp!
|
2021-03-17 17:56:37 +01:00
|
|
|
*/
|
2023-08-30 15:54:44 +02:00
|
|
|
nextUpdateStampMs: DbIndexableTimestampMs;
|
2021-03-17 17:56:37 +01:00
|
|
|
|
2022-10-05 18:31:56 +02:00
|
|
|
lastKeysEtag: string | undefined;
|
|
|
|
|
2021-06-10 16:32:37 +02:00
|
|
|
/**
|
|
|
|
* Next time that we should check if coins need to be refreshed.
|
|
|
|
*
|
|
|
|
* Updated whenever the exchange's denominations are updated or when
|
|
|
|
* the refresh check has been done.
|
|
|
|
*/
|
2023-08-30 15:54:44 +02:00
|
|
|
nextRefreshCheckStampMs: DbIndexableTimestampMs;
|
2021-03-17 17:56:37 +01:00
|
|
|
|
2022-07-12 17:41:14 +02:00
|
|
|
/**
|
|
|
|
* Public key of the reserve that we're currently using for
|
|
|
|
* receiving P2P payments.
|
|
|
|
*/
|
2022-10-14 22:56:29 +02:00
|
|
|
currentMergeReserveRowId?: number;
|
2021-03-17 17:56:37 +01:00
|
|
|
}
|
|
|
|
|
2022-10-14 21:00:13 +02:00
|
|
|
export enum PlanchetStatus {
|
2023-09-08 11:45:31 +02:00
|
|
|
Pending = 0x0100_0000,
|
|
|
|
KycRequired = 0x0100_0001,
|
|
|
|
WithdrawalDone = 0x0500_000,
|
2022-10-14 21:00:13 +02:00
|
|
|
}
|
|
|
|
|
2021-03-17 17:56:37 +01:00
|
|
|
/**
|
|
|
|
* A coin that isn't yet signed by an exchange.
|
|
|
|
*/
|
|
|
|
export interface PlanchetRecord {
|
|
|
|
/**
|
|
|
|
* Public key of the coin.
|
|
|
|
*/
|
|
|
|
coinPub: string;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Private key of the coin.
|
|
|
|
*/
|
|
|
|
coinPriv: string;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Withdrawal group that this planchet belongs to
|
|
|
|
* (or the empty string).
|
|
|
|
*/
|
|
|
|
withdrawalGroupId: string;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Index within the withdrawal group (or -1).
|
|
|
|
*/
|
|
|
|
coinIdx: number;
|
|
|
|
|
2022-10-14 21:00:13 +02:00
|
|
|
planchetStatus: PlanchetStatus;
|
2021-03-17 17:56:37 +01:00
|
|
|
|
2022-03-22 21:16:38 +01:00
|
|
|
lastError: TalerErrorDetail | undefined;
|
2021-03-17 17:56:37 +01:00
|
|
|
|
|
|
|
denomPubHash: string;
|
|
|
|
|
|
|
|
blindingKey: string;
|
|
|
|
|
|
|
|
withdrawSig: string;
|
|
|
|
|
2022-02-21 12:40:51 +01:00
|
|
|
coinEv: CoinEnvelope;
|
2021-03-17 17:56:37 +01:00
|
|
|
|
|
|
|
coinEvHash: string;
|
2022-04-19 17:12:43 +02:00
|
|
|
|
|
|
|
ageCommitmentProof?: AgeCommitmentProof;
|
2021-03-17 17:56:37 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
export enum CoinSourceType {
|
|
|
|
Withdraw = "withdraw",
|
|
|
|
Refresh = "refresh",
|
2023-08-03 18:35:07 +02:00
|
|
|
Reward = "reward",
|
2021-03-17 17:56:37 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
export interface WithdrawCoinSource {
|
|
|
|
type: CoinSourceType.Withdraw;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Can be the empty string for orphaned coins.
|
|
|
|
*/
|
|
|
|
withdrawalGroupId: string;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Index of the coin in the withdrawal session.
|
|
|
|
*/
|
|
|
|
coinIndex: number;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Reserve public key for the reserve we got this coin from.
|
|
|
|
*/
|
|
|
|
reservePub: string;
|
|
|
|
}
|
|
|
|
|
|
|
|
export interface RefreshCoinSource {
|
|
|
|
type: CoinSourceType.Refresh;
|
2022-11-02 13:40:03 +01:00
|
|
|
refreshGroupId: string;
|
2021-03-17 17:56:37 +01:00
|
|
|
oldCoinPub: string;
|
|
|
|
}
|
|
|
|
|
2023-08-03 18:35:07 +02:00
|
|
|
export interface RewardCoinSource {
|
|
|
|
type: CoinSourceType.Reward;
|
|
|
|
walletRewardId: string;
|
2021-03-17 17:56:37 +01:00
|
|
|
coinIndex: number;
|
|
|
|
}
|
|
|
|
|
2023-08-05 23:19:55 +02:00
|
|
|
export type CoinSource =
|
|
|
|
| WithdrawCoinSource
|
|
|
|
| RefreshCoinSource
|
|
|
|
| RewardCoinSource;
|
2021-03-17 17:56:37 +01:00
|
|
|
|
|
|
|
/**
|
|
|
|
* CoinRecord as stored in the "coins" data store
|
|
|
|
* of the wallet database.
|
|
|
|
*/
|
|
|
|
export interface CoinRecord {
|
|
|
|
/**
|
|
|
|
* Where did the coin come from? Used for recouping coins.
|
|
|
|
*/
|
|
|
|
coinSource: CoinSource;
|
|
|
|
|
2023-06-26 19:27:34 +02:00
|
|
|
/**
|
|
|
|
* Source transaction ID of the coin.
|
|
|
|
*
|
|
|
|
* Used to make the coin visible after the transaction
|
|
|
|
* has entered a final state.
|
|
|
|
*/
|
|
|
|
sourceTransactionId?: string;
|
|
|
|
|
2021-03-17 17:56:37 +01:00
|
|
|
/**
|
|
|
|
* Public key of the coin.
|
|
|
|
*/
|
|
|
|
coinPub: string;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Private key to authorize operations on the coin.
|
|
|
|
*/
|
|
|
|
coinPriv: string;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Hash of the public key that signs the coin.
|
|
|
|
*/
|
|
|
|
denomPubHash: string;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Unblinded signature by the exchange.
|
|
|
|
*/
|
2021-11-17 10:23:22 +01:00
|
|
|
denomSig: UnblindedSignature;
|
2021-03-17 17:56:37 +01:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Base URL that identifies the exchange from which we got the
|
|
|
|
* coin.
|
|
|
|
*/
|
|
|
|
exchangeBaseUrl: string;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Blinding key used when withdrawing the coin.
|
|
|
|
* Potentionally used again during payback.
|
|
|
|
*/
|
|
|
|
blindingKey: string;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Hash of the coin envelope.
|
|
|
|
*
|
|
|
|
* Stored here for indexing purposes, so that when looking at a
|
|
|
|
* reserve history, we can quickly find the coin for a withdrawal transaction.
|
|
|
|
*/
|
|
|
|
coinEvHash: string;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Status of the coin.
|
|
|
|
*/
|
|
|
|
status: CoinStatus;
|
2021-06-22 18:43:11 +02:00
|
|
|
|
2023-06-26 19:27:34 +02:00
|
|
|
/**
|
|
|
|
* Non-zero for visible.
|
|
|
|
*
|
|
|
|
* A coin is visible when it is fresh and the
|
|
|
|
* source transaction is in a final state.
|
|
|
|
*/
|
|
|
|
visible?: number;
|
|
|
|
|
2021-06-22 18:43:11 +02:00
|
|
|
/**
|
|
|
|
* Information about what the coin has been allocated for.
|
2022-09-21 21:13:31 +02:00
|
|
|
*
|
|
|
|
* Used for:
|
|
|
|
* - Diagnostics
|
|
|
|
* - Idempotency of applying a coin selection (e.g. after re-selection)
|
2021-06-22 18:43:11 +02:00
|
|
|
*/
|
2022-10-15 11:52:07 +02:00
|
|
|
spendAllocation: CoinAllocation | undefined;
|
2022-04-19 17:12:43 +02:00
|
|
|
|
2022-10-14 21:00:13 +02:00
|
|
|
/**
|
|
|
|
* Maximum age of purchases that can be made with this coin.
|
|
|
|
*
|
2022-10-15 16:25:44 +02:00
|
|
|
* (Used for indexing, redundant with {@link ageCommitmentProof}).
|
2022-10-14 21:00:13 +02:00
|
|
|
*/
|
2022-09-16 16:20:47 +02:00
|
|
|
maxAge: number;
|
|
|
|
|
2022-09-21 21:13:31 +02:00
|
|
|
ageCommitmentProof: AgeCommitmentProof | undefined;
|
2021-06-22 18:43:11 +02:00
|
|
|
}
|
|
|
|
|
2022-10-14 21:00:13 +02:00
|
|
|
/**
|
|
|
|
* Coin allocation, i.e. what a coin has been used for.
|
|
|
|
*/
|
2021-06-22 18:43:11 +02:00
|
|
|
export interface CoinAllocation {
|
2022-10-14 22:38:40 +02:00
|
|
|
/**
|
|
|
|
* ID of the allocation, should be the ID of the transaction that
|
|
|
|
*/
|
|
|
|
id: TransactionIdStr;
|
2021-06-22 18:43:11 +02:00
|
|
|
amount: AmountString;
|
2021-03-17 17:56:37 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2023-08-03 18:35:07 +02:00
|
|
|
* Status of a reward we got from a merchant.
|
2021-03-17 17:56:37 +01:00
|
|
|
*/
|
2023-08-03 18:35:07 +02:00
|
|
|
export interface RewardRecord {
|
2021-03-17 17:56:37 +01:00
|
|
|
/**
|
|
|
|
* Has the user accepted the tip? Only after the tip has been accepted coins
|
|
|
|
* withdrawn from the tip may be used.
|
|
|
|
*/
|
2023-05-26 12:19:32 +02:00
|
|
|
acceptedTimestamp: TalerPreciseTimestamp | undefined;
|
2021-03-17 17:56:37 +01:00
|
|
|
|
|
|
|
/**
|
|
|
|
* The tipped amount.
|
|
|
|
*/
|
2023-08-03 18:35:07 +02:00
|
|
|
rewardAmountRaw: AmountString;
|
2021-03-17 17:56:37 +01:00
|
|
|
|
2022-09-20 21:44:21 +02:00
|
|
|
/**
|
|
|
|
* Effect on the balance (including fees etc).
|
|
|
|
*/
|
2023-08-03 18:35:07 +02:00
|
|
|
rewardAmountEffective: AmountString;
|
2021-03-17 17:56:37 +01:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Timestamp, the tip can't be picked up anymore after this deadline.
|
|
|
|
*/
|
2023-08-03 18:35:07 +02:00
|
|
|
rewardExpiration: TalerProtocolTimestamp;
|
2021-03-17 17:56:37 +01:00
|
|
|
|
|
|
|
/**
|
|
|
|
* The exchange that will sign our coins, chosen by the merchant.
|
|
|
|
*/
|
|
|
|
exchangeBaseUrl: string;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Base URL of the merchant that is giving us the tip.
|
|
|
|
*/
|
|
|
|
merchantBaseUrl: string;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Denomination selection made by the wallet for picking up
|
|
|
|
* this tip.
|
2022-09-20 21:44:21 +02:00
|
|
|
*
|
|
|
|
* FIXME: Put this into some DenomSelectionCacheRecord instead of
|
|
|
|
* storing it here!
|
2021-03-17 17:56:37 +01:00
|
|
|
*/
|
|
|
|
denomsSel: DenomSelectionState;
|
|
|
|
|
2021-05-12 13:34:49 +02:00
|
|
|
denomSelUid: string;
|
|
|
|
|
2021-03-17 17:56:37 +01:00
|
|
|
/**
|
|
|
|
* Tip ID chosen by the wallet.
|
|
|
|
*/
|
2023-08-03 18:35:07 +02:00
|
|
|
walletRewardId: string;
|
2021-03-17 17:56:37 +01:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Secret seed used to derive planchets for this tip.
|
|
|
|
*/
|
|
|
|
secretSeed: string;
|
|
|
|
|
|
|
|
/**
|
2023-08-03 18:35:07 +02:00
|
|
|
* The merchant's identifier for this reward.
|
2021-03-17 17:56:37 +01:00
|
|
|
*/
|
2023-08-03 18:35:07 +02:00
|
|
|
merchantRewardId: string;
|
2021-03-17 17:56:37 +01:00
|
|
|
|
2023-05-26 12:19:32 +02:00
|
|
|
createdTimestamp: TalerPreciseTimestamp;
|
2021-03-17 17:56:37 +01:00
|
|
|
|
2023-02-01 17:00:12 +01:00
|
|
|
/**
|
|
|
|
* The url to be redirected after the tip is accepted.
|
|
|
|
*/
|
|
|
|
next_url: string | undefined;
|
2023-05-30 09:33:32 +02:00
|
|
|
|
2021-03-17 17:56:37 +01:00
|
|
|
/**
|
|
|
|
* Timestamp for when the wallet finished picking up the tip
|
|
|
|
* from the merchant.
|
|
|
|
*/
|
2023-05-26 12:19:32 +02:00
|
|
|
pickedUpTimestamp: TalerPreciseTimestamp | undefined;
|
2023-05-30 09:33:32 +02:00
|
|
|
|
2023-08-03 18:35:07 +02:00
|
|
|
status: RewardRecordStatus;
|
2023-05-30 09:33:32 +02:00
|
|
|
}
|
|
|
|
|
2023-08-03 18:35:07 +02:00
|
|
|
export enum RewardRecordStatus {
|
2023-09-07 20:35:46 +02:00
|
|
|
PendingPickup = 0x0100_0000,
|
|
|
|
SuspendedPickup = 0x0110_0000,
|
|
|
|
DialogAccept = 0x0101_0000,
|
|
|
|
Done = 0x0500_0000,
|
|
|
|
Aborted = 0x0500_0000,
|
2021-03-17 17:56:37 +01:00
|
|
|
}
|
|
|
|
|
2021-08-24 14:25:46 +02:00
|
|
|
export enum RefreshCoinStatus {
|
2023-09-07 20:35:46 +02:00
|
|
|
Pending = 0x0100_0000,
|
|
|
|
Finished = 0x0500_0000,
|
2021-08-24 14:25:46 +02:00
|
|
|
|
|
|
|
/**
|
|
|
|
* The refresh for this coin has been frozen, because of a permanent error.
|
|
|
|
* More info in lastErrorPerCoin.
|
|
|
|
*/
|
2023-09-07 20:35:46 +02:00
|
|
|
Failed = 0x0501_000,
|
2022-01-11 21:00:12 +01:00
|
|
|
}
|
|
|
|
|
2022-10-14 21:00:13 +02:00
|
|
|
export enum RefreshOperationStatus {
|
2023-09-07 20:35:46 +02:00
|
|
|
Pending = 0x0100_0000,
|
|
|
|
Suspended = 0x0110_0000,
|
2023-05-30 12:28:21 +02:00
|
|
|
|
2023-09-07 20:35:46 +02:00
|
|
|
Finished = 0x0500_000,
|
|
|
|
Failed = 0x0501_000,
|
2022-10-14 21:00:13 +02:00
|
|
|
}
|
|
|
|
|
2023-04-22 14:17:49 +02:00
|
|
|
/**
|
|
|
|
* Status of a single element of a deposit group.
|
|
|
|
*/
|
|
|
|
export enum DepositElementStatus {
|
2023-09-08 12:54:31 +02:00
|
|
|
DepositPending = 0x0100_0000,
|
|
|
|
/**
|
|
|
|
* Accepted, but tracking.
|
|
|
|
*/
|
|
|
|
Tracking = 0x0100_0001,
|
2023-09-07 20:35:46 +02:00
|
|
|
KycRequired = 0x0100_0002,
|
|
|
|
Wired = 0x0500_0000,
|
|
|
|
RefundSuccess = 0x0503_0000,
|
|
|
|
RefundFailed = 0x0501_0000,
|
2023-01-15 21:48:41 +01:00
|
|
|
}
|
|
|
|
|
2023-01-11 17:12:08 +01:00
|
|
|
/**
|
|
|
|
* Additional information about the reason of a refresh.
|
|
|
|
*/
|
|
|
|
export interface RefreshReasonDetails {
|
2023-02-14 13:28:10 +01:00
|
|
|
originatingTransactionId?: string;
|
2023-01-11 17:12:08 +01:00
|
|
|
proposalId?: string;
|
|
|
|
}
|
|
|
|
|
2023-01-05 18:45:49 +01:00
|
|
|
/**
|
|
|
|
* Group of refresh operations. The refreshed coins do not
|
|
|
|
* have to belong to the same exchange, but must have the same
|
|
|
|
* currency.
|
|
|
|
*/
|
2021-03-17 17:56:37 +01:00
|
|
|
export interface RefreshGroupRecord {
|
2022-10-14 21:00:13 +02:00
|
|
|
operationStatus: RefreshOperationStatus;
|
2022-01-11 21:00:12 +01:00
|
|
|
|
2021-08-24 14:25:46 +02:00
|
|
|
/**
|
|
|
|
* Unique, randomly generated identifier for this group of
|
|
|
|
* refresh operations.
|
|
|
|
*/
|
2021-03-17 17:56:37 +01:00
|
|
|
refreshGroupId: string;
|
|
|
|
|
2023-01-05 18:45:49 +01:00
|
|
|
/**
|
|
|
|
* Currency of this refresh group.
|
|
|
|
*/
|
|
|
|
currency: string;
|
|
|
|
|
2021-08-24 14:25:46 +02:00
|
|
|
/**
|
|
|
|
* Reason why this refresh group has been created.
|
|
|
|
*/
|
2021-03-17 17:56:37 +01:00
|
|
|
reason: RefreshReason;
|
|
|
|
|
2023-01-11 17:12:08 +01:00
|
|
|
/**
|
|
|
|
* Extra information depending on the reason.
|
|
|
|
*/
|
|
|
|
reasonDetails?: RefreshReasonDetails;
|
|
|
|
|
2021-03-17 17:56:37 +01:00
|
|
|
oldCoinPubs: string[];
|
|
|
|
|
2022-11-02 17:42:14 +01:00
|
|
|
inputPerCoin: AmountString[];
|
2021-03-17 17:56:37 +01:00
|
|
|
|
2023-09-08 12:26:58 +02:00
|
|
|
expectedOutputPerCoin: AmountString[];
|
2021-03-17 17:56:37 +01:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Flag for each coin whether refreshing finished.
|
|
|
|
* If a coin can't be refreshed (remaining value too small),
|
|
|
|
* it will be marked as finished, but no refresh session will
|
|
|
|
* be created.
|
|
|
|
*/
|
2021-08-24 14:25:46 +02:00
|
|
|
statusPerCoin: RefreshCoinStatus[];
|
2021-03-17 17:56:37 +01:00
|
|
|
|
2023-05-26 12:19:32 +02:00
|
|
|
timestampCreated: TalerPreciseTimestamp;
|
2021-03-17 17:56:37 +01:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Timestamp when the refresh session finished.
|
|
|
|
*/
|
2023-05-26 12:19:32 +02:00
|
|
|
timestampFinished: TalerPreciseTimestamp | undefined;
|
2021-03-17 17:56:37 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Ongoing refresh
|
|
|
|
*/
|
|
|
|
export interface RefreshSessionRecord {
|
2023-09-08 12:26:58 +02:00
|
|
|
refreshGroupId: string;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Index of the coin in the refresh group.
|
|
|
|
*/
|
|
|
|
coinIndex: number;
|
|
|
|
|
2021-03-17 17:56:37 +01:00
|
|
|
/**
|
|
|
|
* 512-bit secret that can be used to derive
|
|
|
|
* the other cryptographic material for the refresh session.
|
|
|
|
*/
|
|
|
|
sessionSecretSeed: string;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Sum of the value of denominations we want
|
|
|
|
* to withdraw in this session, without fees.
|
|
|
|
*/
|
2022-11-02 17:42:14 +01:00
|
|
|
amountRefreshOutput: AmountString;
|
2021-03-17 17:56:37 +01:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Hashed denominations of the newly requested coins.
|
|
|
|
*/
|
|
|
|
newDenoms: {
|
|
|
|
denomPubHash: string;
|
|
|
|
count: number;
|
|
|
|
}[];
|
|
|
|
|
|
|
|
/**
|
|
|
|
* The no-reveal-index after we've done the melting.
|
|
|
|
*/
|
|
|
|
norevealIndex?: number;
|
2023-09-08 12:26:58 +02:00
|
|
|
|
|
|
|
lastError?: TalerErrorDetail;
|
2021-03-17 17:56:37 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
export enum RefundReason {
|
|
|
|
/**
|
|
|
|
* Normal refund given by the merchant.
|
|
|
|
*/
|
|
|
|
NormalRefund = "normal-refund",
|
|
|
|
/**
|
|
|
|
* Refund from an aborted payment.
|
|
|
|
*/
|
|
|
|
AbortRefund = "abort-pay-refund",
|
|
|
|
}
|
|
|
|
|
2022-10-08 23:45:49 +02:00
|
|
|
export enum PurchaseStatus {
|
2022-10-08 20:56:57 +02:00
|
|
|
/**
|
|
|
|
* Not downloaded yet.
|
|
|
|
*/
|
2023-09-07 20:35:46 +02:00
|
|
|
PendingDownloadingProposal = 0x0100_0000,
|
|
|
|
SuspendedDownloadingProposal = 0x0110_0000,
|
2022-10-08 20:56:57 +02:00
|
|
|
|
|
|
|
/**
|
|
|
|
* The user has accepted the proposal.
|
|
|
|
*/
|
2023-09-07 20:35:46 +02:00
|
|
|
PendingPaying = 0x0100_0001,
|
|
|
|
SuspendedPaying = 0x0110_0001,
|
2022-10-08 20:56:57 +02:00
|
|
|
|
2022-10-14 22:38:40 +02:00
|
|
|
/**
|
|
|
|
* Currently in the process of aborting with a refund.
|
|
|
|
*/
|
2023-09-07 20:35:46 +02:00
|
|
|
AbortingWithRefund = 0x0103_0000,
|
|
|
|
SuspendedAbortingWithRefund = 0x0113_0000,
|
2022-10-08 20:56:57 +02:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Paying a second time, likely with different session ID
|
|
|
|
*/
|
2023-09-07 20:35:46 +02:00
|
|
|
PendingPayingReplay = 0x0100_0002,
|
|
|
|
SuspendedPayingReplay = 0x0110_0002,
|
2022-10-08 20:56:57 +02:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Query for refunds (until query succeeds).
|
|
|
|
*/
|
2023-09-07 20:35:46 +02:00
|
|
|
PendingQueryingRefund = 0x0100_0003,
|
|
|
|
SuspendedQueryingRefund = 0x0110_0003,
|
2022-10-08 20:56:57 +02:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Query for refund (until auto-refund deadline is reached).
|
|
|
|
*/
|
2023-09-07 20:35:46 +02:00
|
|
|
PendingQueryingAutoRefund = 0x0100_0004,
|
|
|
|
SuspendedQueryingAutoRefund = 0x0110_0004,
|
2022-10-08 20:56:57 +02:00
|
|
|
|
2023-09-07 20:35:46 +02:00
|
|
|
PendingAcceptRefund = 0x0100_0005,
|
|
|
|
SuspendedPendingAcceptRefund = 0x0100_0005,
|
2023-05-25 11:52:20 +02:00
|
|
|
|
2022-10-08 20:56:57 +02:00
|
|
|
/**
|
|
|
|
* Proposal downloaded, but the user needs to accept/reject it.
|
|
|
|
*/
|
2023-09-07 20:35:46 +02:00
|
|
|
DialogProposed = 0x0101_0000,
|
|
|
|
|
2023-07-03 17:42:44 +02:00
|
|
|
/**
|
|
|
|
* Proposal shared to other wallet or read from other wallet
|
|
|
|
* the user needs to accept/reject it.
|
|
|
|
*/
|
2023-09-07 20:35:46 +02:00
|
|
|
DialogShared = 0x0101_0001,
|
2022-10-08 20:56:57 +02:00
|
|
|
|
|
|
|
/**
|
|
|
|
* The user has rejected the proposal.
|
|
|
|
*/
|
2023-09-07 20:35:46 +02:00
|
|
|
AbortedProposalRefused = 0x0503_0000,
|
2022-10-08 20:56:57 +02:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Downloading or processing the proposal has failed permanently.
|
|
|
|
*/
|
2023-09-07 20:35:46 +02:00
|
|
|
FailedClaim = 0x0501_0000,
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Payment was successful.
|
|
|
|
*/
|
|
|
|
Done = 0x0500_0000,
|
2022-10-08 20:56:57 +02:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Downloaded proposal was detected as a re-purchase.
|
|
|
|
*/
|
2023-09-07 20:35:46 +02:00
|
|
|
DoneRepurchaseDetected = 0x0500_0001,
|
2022-10-08 20:56:57 +02:00
|
|
|
|
|
|
|
/**
|
|
|
|
* The payment has been aborted.
|
|
|
|
*/
|
2023-09-07 20:35:46 +02:00
|
|
|
AbortedIncompletePayment = 0x0503_0000,
|
2022-10-08 20:56:57 +02:00
|
|
|
|
|
|
|
/**
|
2023-09-07 20:35:46 +02:00
|
|
|
* Tried to abort, but aborting failed or was cancelled.
|
2022-10-08 20:56:57 +02:00
|
|
|
*/
|
2023-09-07 20:35:46 +02:00
|
|
|
FailedAbort = 0x0501_0001,
|
2023-06-05 10:29:04 +02:00
|
|
|
|
2023-09-07 20:35:46 +02:00
|
|
|
AbortedRefunded = 0x0503_0000,
|
2022-10-08 20:56:57 +02:00
|
|
|
}
|
|
|
|
|
2022-10-09 02:23:06 +02:00
|
|
|
/**
|
|
|
|
* Partial information about the downloaded proposal.
|
|
|
|
* Only contains data that is relevant for indexing on the
|
|
|
|
* "purchases" object stores.
|
|
|
|
*/
|
2022-10-14 22:38:40 +02:00
|
|
|
export interface ProposalDownloadInfo {
|
2022-10-09 02:23:06 +02:00
|
|
|
contractTermsHash: string;
|
|
|
|
fulfillmentUrl?: string;
|
|
|
|
currency: string;
|
|
|
|
contractTermsMerchantSig: string;
|
2022-10-08 20:56:57 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
export interface PurchasePayInfo {
|
|
|
|
payCoinSelection: PayCoinSelection;
|
2022-11-02 17:42:14 +01:00
|
|
|
totalPayCost: AmountString;
|
2022-10-08 20:56:57 +02:00
|
|
|
payCoinSelectionUid: string;
|
2021-03-17 17:56:37 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Record that stores status information about one purchase, starting from when
|
|
|
|
* the customer accepts a proposal. Includes refund status if applicable.
|
2022-10-08 20:56:57 +02:00
|
|
|
*
|
2022-10-14 21:00:13 +02:00
|
|
|
* Key: {@link proposalId}
|
|
|
|
* Operation status: {@link purchaseStatus}
|
2021-03-17 17:56:37 +01:00
|
|
|
*/
|
|
|
|
export interface PurchaseRecord {
|
|
|
|
/**
|
|
|
|
* Proposal ID for this purchase. Uniquely identifies the
|
|
|
|
* purchase and the proposal.
|
2022-10-08 20:56:57 +02:00
|
|
|
* Assigned by the wallet.
|
2021-03-17 17:56:37 +01:00
|
|
|
*/
|
|
|
|
proposalId: string;
|
|
|
|
|
2022-10-08 20:56:57 +02:00
|
|
|
/**
|
|
|
|
* Order ID, assigned by the merchant.
|
|
|
|
*/
|
|
|
|
orderId: string;
|
|
|
|
|
|
|
|
merchantBaseUrl: string;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Claim token used when downloading the contract terms.
|
|
|
|
*/
|
|
|
|
claimToken: string | undefined;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Session ID we got when downloading the contract.
|
|
|
|
*/
|
|
|
|
downloadSessionId: string | undefined;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* If this purchase is a repurchase, this field identifies the original purchase.
|
|
|
|
*/
|
|
|
|
repurchaseProposalId: string | undefined;
|
|
|
|
|
2022-10-08 23:45:49 +02:00
|
|
|
purchaseStatus: PurchaseStatus;
|
2022-10-08 20:56:57 +02:00
|
|
|
|
2021-03-17 17:56:37 +01:00
|
|
|
/**
|
|
|
|
* Private key for the nonce.
|
|
|
|
*/
|
|
|
|
noncePriv: string;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Public key for the nonce.
|
|
|
|
*/
|
|
|
|
noncePub: string;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Downloaded and parsed proposal data.
|
|
|
|
*/
|
2022-10-14 22:38:40 +02:00
|
|
|
download: ProposalDownloadInfo | undefined;
|
2021-03-17 17:56:37 +01:00
|
|
|
|
2022-10-08 20:56:57 +02:00
|
|
|
payInfo: PurchasePayInfo | undefined;
|
2021-05-12 13:34:49 +02:00
|
|
|
|
2021-03-17 17:56:37 +01:00
|
|
|
/**
|
|
|
|
* Pending removals from pay coin selection.
|
2021-05-12 14:16:01 +02:00
|
|
|
*
|
2021-03-17 17:56:37 +01:00
|
|
|
* Used when a the pay coin selection needs to be changed
|
|
|
|
* because a coin became known as double-spent or invalid,
|
|
|
|
* but a new coin selection can't immediately be done, as
|
|
|
|
* there is not enough balance (e.g. when waiting for a refresh).
|
|
|
|
*/
|
|
|
|
pendingRemovedCoinPubs?: string[];
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Timestamp of the first time that sending a payment to the merchant
|
|
|
|
* for this purchase was successful.
|
|
|
|
*/
|
2023-05-26 12:19:32 +02:00
|
|
|
timestampFirstSuccessfulPay: TalerPreciseTimestamp | undefined;
|
2021-03-17 17:56:37 +01:00
|
|
|
|
|
|
|
merchantPaySig: string | undefined;
|
|
|
|
|
2023-04-03 17:13:13 +02:00
|
|
|
posConfirmation: string | undefined;
|
|
|
|
|
2023-07-03 17:42:44 +02:00
|
|
|
/**
|
|
|
|
* This purchase was created by sharing nonce or
|
|
|
|
* did the wallet made the nonce public
|
|
|
|
*/
|
|
|
|
shared: boolean;
|
|
|
|
|
2022-10-08 20:56:57 +02:00
|
|
|
/**
|
|
|
|
* When was the purchase record created?
|
|
|
|
*/
|
2023-05-26 12:19:32 +02:00
|
|
|
timestamp: TalerPreciseTimestamp;
|
2022-10-08 20:56:57 +02:00
|
|
|
|
2021-03-17 17:56:37 +01:00
|
|
|
/**
|
|
|
|
* When was the purchase made?
|
|
|
|
* Refers to the time that the user accepted.
|
|
|
|
*/
|
2023-05-26 12:19:32 +02:00
|
|
|
timestampAccept: TalerPreciseTimestamp | undefined;
|
2021-03-17 17:56:37 +01:00
|
|
|
|
|
|
|
/**
|
|
|
|
* When was the last refund made?
|
|
|
|
* Set to 0 if no refund was made on the purchase.
|
|
|
|
*/
|
2023-05-26 12:19:32 +02:00
|
|
|
timestampLastRefundStatus: TalerPreciseTimestamp | undefined;
|
2021-03-17 17:56:37 +01:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Last session signature that we submitted to /pay (if any).
|
|
|
|
*/
|
|
|
|
lastSessionId: string | undefined;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Continue querying the refund status until this deadline has expired.
|
|
|
|
*/
|
2022-03-18 15:32:41 +01:00
|
|
|
autoRefundDeadline: TalerProtocolTimestamp | undefined;
|
2021-08-24 15:08:34 +02:00
|
|
|
|
2022-05-14 23:09:33 +02:00
|
|
|
/**
|
|
|
|
* How much merchant has refund to be taken but the wallet
|
|
|
|
* did not picked up yet
|
|
|
|
*/
|
2022-11-02 17:42:14 +01:00
|
|
|
refundAmountAwaiting: AmountString | undefined;
|
2021-03-17 17:56:37 +01:00
|
|
|
}
|
|
|
|
|
2022-10-12 22:27:50 +02:00
|
|
|
export enum ConfigRecordKey {
|
|
|
|
WalletBackupState = "walletBackupState",
|
|
|
|
CurrencyDefaultsApplied = "currencyDefaultsApplied",
|
|
|
|
DevMode = "devMode",
|
|
|
|
}
|
2021-06-14 11:21:29 +02:00
|
|
|
|
2021-03-17 17:56:37 +01:00
|
|
|
/**
|
|
|
|
* Configuration key/value entries to configure
|
|
|
|
* the wallet.
|
|
|
|
*/
|
2021-06-14 11:21:29 +02:00
|
|
|
export type ConfigRecord =
|
|
|
|
| {
|
2022-10-12 22:27:50 +02:00
|
|
|
key: ConfigRecordKey.WalletBackupState;
|
2022-09-05 18:12:30 +02:00
|
|
|
value: WalletBackupConfState;
|
|
|
|
}
|
2022-10-12 22:27:50 +02:00
|
|
|
| { key: ConfigRecordKey.CurrencyDefaultsApplied; value: boolean }
|
|
|
|
| { key: ConfigRecordKey.DevMode; value: boolean };
|
2021-06-14 11:21:29 +02:00
|
|
|
|
|
|
|
export interface WalletBackupConfState {
|
|
|
|
deviceId: string;
|
|
|
|
walletRootPub: string;
|
|
|
|
walletRootPriv: string;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Last hash of the canonicalized plain-text backup.
|
|
|
|
*/
|
|
|
|
lastBackupPlainHash?: string;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Timestamp stored in the last backup.
|
|
|
|
*/
|
2023-05-26 12:19:32 +02:00
|
|
|
lastBackupTimestamp?: TalerPreciseTimestamp;
|
2021-06-14 11:21:29 +02:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Last time we tried to do a backup.
|
|
|
|
*/
|
2023-05-26 12:19:32 +02:00
|
|
|
lastBackupCheckTimestamp?: TalerPreciseTimestamp;
|
2021-06-14 11:21:29 +02:00
|
|
|
lastBackupNonce?: string;
|
2021-03-17 17:56:37 +01:00
|
|
|
}
|
|
|
|
|
2023-09-07 20:35:46 +02:00
|
|
|
// FIXME: Should these be numeric codes?
|
2022-08-24 22:17:19 +02:00
|
|
|
export const enum WithdrawalRecordType {
|
|
|
|
BankManual = "bank-manual",
|
|
|
|
BankIntegrated = "bank-integrated",
|
|
|
|
PeerPullCredit = "peer-pull-credit",
|
|
|
|
PeerPushCredit = "peer-push-credit",
|
2022-08-26 01:18:01 +02:00
|
|
|
Recoup = "recoup",
|
2022-08-24 22:17:19 +02:00
|
|
|
}
|
|
|
|
|
2022-08-24 22:42:30 +02:00
|
|
|
export interface WgInfoBankIntegrated {
|
|
|
|
withdrawalType: WithdrawalRecordType.BankIntegrated;
|
|
|
|
/**
|
|
|
|
* Extra state for when this is a withdrawal involving
|
|
|
|
* a Taler-integrated bank.
|
|
|
|
*/
|
|
|
|
bankInfo: ReserveBankInfo;
|
|
|
|
}
|
|
|
|
|
|
|
|
export interface WgInfoBankManual {
|
|
|
|
withdrawalType: WithdrawalRecordType.BankManual;
|
|
|
|
}
|
|
|
|
|
|
|
|
export interface WgInfoBankPeerPull {
|
|
|
|
withdrawalType: WithdrawalRecordType.PeerPullCredit;
|
|
|
|
|
2023-09-08 11:45:31 +02:00
|
|
|
// FIXME: include a transaction ID here?
|
|
|
|
|
2022-08-24 22:42:30 +02:00
|
|
|
/**
|
|
|
|
* Needed to quickly construct the taler:// URI for the counterparty
|
|
|
|
* without a join.
|
|
|
|
*/
|
|
|
|
contractPriv: string;
|
|
|
|
}
|
|
|
|
|
|
|
|
export interface WgInfoBankPeerPush {
|
|
|
|
withdrawalType: WithdrawalRecordType.PeerPushCredit;
|
2022-09-01 13:41:22 +02:00
|
|
|
|
2023-09-08 11:45:31 +02:00
|
|
|
// FIXME: include a transaction ID here?
|
2022-08-24 22:42:30 +02:00
|
|
|
}
|
|
|
|
|
2022-08-26 01:18:01 +02:00
|
|
|
export interface WgInfoBankRecoup {
|
|
|
|
withdrawalType: WithdrawalRecordType.Recoup;
|
|
|
|
}
|
|
|
|
|
2022-08-24 22:42:30 +02:00
|
|
|
export type WgInfo =
|
|
|
|
| WgInfoBankIntegrated
|
|
|
|
| WgInfoBankManual
|
|
|
|
| WgInfoBankPeerPull
|
2022-08-26 01:18:01 +02:00
|
|
|
| WgInfoBankPeerPush
|
|
|
|
| WgInfoBankRecoup;
|
2022-08-24 22:42:30 +02:00
|
|
|
|
2023-01-17 19:59:30 +01:00
|
|
|
export type KycUserType = "individual" | "business";
|
2023-04-21 22:02:34 +02:00
|
|
|
|
2023-01-17 19:59:30 +01:00
|
|
|
export interface KycPendingInfo {
|
2023-01-10 17:31:01 +01:00
|
|
|
paytoHash: string;
|
|
|
|
requirementRow: number;
|
|
|
|
}
|
2021-03-17 17:56:37 +01:00
|
|
|
/**
|
|
|
|
* Group of withdrawal operations that need to be executed.
|
2023-08-03 18:35:07 +02:00
|
|
|
* (Either for a normal withdrawal or from a reward.)
|
2021-03-17 17:56:37 +01:00
|
|
|
*
|
|
|
|
* The withdrawal group record is only created after we know
|
|
|
|
* the coin selection we want to withdraw.
|
|
|
|
*/
|
|
|
|
export interface WithdrawalGroupRecord {
|
2022-01-12 16:54:38 +01:00
|
|
|
/**
|
|
|
|
* Unique identifier for the withdrawal group.
|
|
|
|
*/
|
2021-03-17 17:56:37 +01:00
|
|
|
withdrawalGroupId: string;
|
|
|
|
|
2022-08-24 22:42:30 +02:00
|
|
|
wgInfo: WgInfo;
|
2022-08-24 22:17:19 +02:00
|
|
|
|
2023-01-17 19:59:30 +01:00
|
|
|
kycPending?: KycPendingInfo;
|
2023-01-10 17:31:01 +01:00
|
|
|
|
2023-06-21 12:21:48 +02:00
|
|
|
kycUrl?: string;
|
|
|
|
|
2021-03-17 17:56:37 +01:00
|
|
|
/**
|
|
|
|
* Secret seed used to derive planchets.
|
2022-08-09 15:00:45 +02:00
|
|
|
* Stored since planchets are created lazily.
|
2021-03-17 17:56:37 +01:00
|
|
|
*/
|
|
|
|
secretSeed: string;
|
|
|
|
|
2022-01-12 16:54:38 +01:00
|
|
|
/**
|
|
|
|
* Public key of the reserve that we're withdrawing from.
|
|
|
|
*/
|
2021-03-17 17:56:37 +01:00
|
|
|
reservePub: string;
|
|
|
|
|
2022-08-09 15:00:45 +02:00
|
|
|
/**
|
|
|
|
* The reserve private key.
|
2022-08-26 01:18:01 +02:00
|
|
|
*
|
|
|
|
* FIXME: Already in the reserves object store, redundant!
|
2022-08-09 15:00:45 +02:00
|
|
|
*/
|
|
|
|
reservePriv: string;
|
|
|
|
|
2022-01-12 16:54:38 +01:00
|
|
|
/**
|
|
|
|
* The exchange base URL that we're withdrawing from.
|
|
|
|
* (Redundantly stored, as the reserve record also has this info.)
|
|
|
|
*/
|
2021-03-17 17:56:37 +01:00
|
|
|
exchangeBaseUrl: string;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* When was the withdrawal operation started started?
|
|
|
|
* Timestamp in milliseconds.
|
|
|
|
*/
|
2023-05-26 12:19:32 +02:00
|
|
|
timestampStart: TalerPreciseTimestamp;
|
2021-03-17 17:56:37 +01:00
|
|
|
|
|
|
|
/**
|
|
|
|
* When was the withdrawal operation completed?
|
|
|
|
*/
|
2023-05-26 12:19:32 +02:00
|
|
|
timestampFinish?: TalerPreciseTimestamp;
|
2021-03-17 17:56:37 +01:00
|
|
|
|
2022-08-09 15:00:45 +02:00
|
|
|
/**
|
|
|
|
* Current status of the reserve.
|
|
|
|
*/
|
2022-09-21 20:46:45 +02:00
|
|
|
status: WithdrawalGroupStatus;
|
2022-08-09 15:00:45 +02:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Wire information (as payto URI) for the bank account that
|
|
|
|
* transferred funds for this reserve.
|
2022-10-16 20:15:55 +02:00
|
|
|
*
|
2022-10-15 21:26:36 +02:00
|
|
|
* FIXME: Doesn't this belong to the bankAccounts object store?
|
2022-08-09 15:00:45 +02:00
|
|
|
*/
|
|
|
|
senderWire?: string;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Restrict withdrawals from this reserve to this age.
|
|
|
|
*/
|
|
|
|
restrictAge?: number;
|
|
|
|
|
2022-10-16 22:18:24 +02:00
|
|
|
/**
|
|
|
|
* Amount that was sent by the user to fund the reserve.
|
|
|
|
*/
|
2022-11-02 17:42:14 +01:00
|
|
|
instructedAmount: AmountString;
|
2022-10-16 22:18:24 +02:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Amount that was observed when querying the reserve that
|
|
|
|
* we are withdrawing from.
|
|
|
|
*
|
|
|
|
* Useful for diagnostics.
|
|
|
|
*/
|
2022-11-02 17:42:14 +01:00
|
|
|
reserveBalanceAmount?: AmountString;
|
2022-10-16 22:18:24 +02:00
|
|
|
|
2021-03-17 17:56:37 +01:00
|
|
|
/**
|
|
|
|
* Amount including fees (i.e. the amount subtracted from the
|
|
|
|
* reserve to withdraw all coins in this withdrawal session).
|
2022-10-16 22:18:24 +02:00
|
|
|
*
|
|
|
|
* (Initial amount confirmed by the user, might differ with denomSel
|
|
|
|
* on reselection.)
|
2021-03-17 17:56:37 +01:00
|
|
|
*/
|
2022-11-02 17:42:14 +01:00
|
|
|
rawWithdrawalAmount: AmountString;
|
2021-03-17 17:56:37 +01:00
|
|
|
|
2022-10-16 22:18:24 +02:00
|
|
|
/**
|
|
|
|
* Amount that will be added to the balance when the withdrawal succeeds.
|
|
|
|
*
|
|
|
|
* (Initial amount confirmed by the user, might differ with denomSel
|
|
|
|
* on reselection.)
|
|
|
|
*/
|
2022-11-02 17:42:14 +01:00
|
|
|
effectiveWithdrawalAmount: AmountString;
|
2022-10-16 22:18:24 +02:00
|
|
|
|
2022-01-12 16:54:38 +01:00
|
|
|
/**
|
|
|
|
* Denominations selected for withdrawal.
|
|
|
|
*/
|
2021-03-17 17:56:37 +01:00
|
|
|
denomsSel: DenomSelectionState;
|
|
|
|
|
2022-01-12 16:54:38 +01:00
|
|
|
/**
|
|
|
|
* UID of the denomination selection.
|
2022-02-21 12:40:51 +01:00
|
|
|
*
|
2022-01-12 16:54:38 +01:00
|
|
|
* Used for merging backups.
|
2022-02-21 12:40:51 +01:00
|
|
|
*
|
2022-01-12 16:54:38 +01:00
|
|
|
* FIXME: Should this not also include a timestamp for more logical merging?
|
|
|
|
*/
|
2021-05-12 13:34:49 +02:00
|
|
|
denomSelUid: string;
|
2021-03-17 17:56:37 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
export interface BankWithdrawUriRecord {
|
|
|
|
/**
|
|
|
|
* The withdraw URI we got from the bank.
|
|
|
|
*/
|
|
|
|
talerWithdrawUri: string;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Reserve that was created for the withdraw URI.
|
|
|
|
*/
|
|
|
|
reservePub: string;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Status of recoup operations that were grouped together.
|
|
|
|
*
|
|
|
|
* The remaining amount of involved coins should be set to zero
|
|
|
|
* in the same transaction that inserts the RecoupGroupRecord.
|
|
|
|
*/
|
|
|
|
export interface RecoupGroupRecord {
|
|
|
|
/**
|
|
|
|
* Unique identifier for the recoup group record.
|
|
|
|
*/
|
|
|
|
recoupGroupId: string;
|
|
|
|
|
2022-08-26 01:18:01 +02:00
|
|
|
exchangeBaseUrl: string;
|
|
|
|
|
2023-05-26 12:19:32 +02:00
|
|
|
timestampStarted: TalerPreciseTimestamp;
|
2021-03-17 17:56:37 +01:00
|
|
|
|
2023-05-26 12:19:32 +02:00
|
|
|
timestampFinished: TalerPreciseTimestamp | undefined;
|
2021-03-17 17:56:37 +01:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Public keys that identify the coins being recouped
|
|
|
|
* as part of this session.
|
|
|
|
*
|
|
|
|
* (Structured like this to enable multiEntry indexing in IndexedDB.)
|
|
|
|
*/
|
|
|
|
coinPubs: string[];
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Array of flags to indicate whether the recoup finished on each individual coin.
|
|
|
|
*/
|
|
|
|
recoupFinishedPerCoin: boolean[];
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Public keys of coins that should be scheduled for refreshing
|
|
|
|
* after all individual recoups are done.
|
|
|
|
*/
|
2022-10-15 11:52:07 +02:00
|
|
|
scheduleRefreshCoins: CoinRefreshRequest[];
|
2021-03-17 17:56:37 +01:00
|
|
|
}
|
|
|
|
|
2021-06-25 13:27:06 +02:00
|
|
|
export enum BackupProviderStateTag {
|
|
|
|
Provisional = "provisional",
|
2021-03-17 17:56:37 +01:00
|
|
|
Ready = "ready",
|
2021-06-25 13:27:06 +02:00
|
|
|
Retrying = "retrying",
|
2021-03-17 17:56:37 +01:00
|
|
|
}
|
|
|
|
|
2021-06-25 13:27:06 +02:00
|
|
|
export type BackupProviderState =
|
|
|
|
| {
|
2022-09-05 18:12:30 +02:00
|
|
|
tag: BackupProviderStateTag.Provisional;
|
|
|
|
}
|
2021-06-25 13:27:06 +02:00
|
|
|
| {
|
2022-09-05 18:12:30 +02:00
|
|
|
tag: BackupProviderStateTag.Ready;
|
2023-05-26 12:19:32 +02:00
|
|
|
nextBackupTimestamp: TalerPreciseTimestamp;
|
2022-09-05 18:12:30 +02:00
|
|
|
}
|
2021-06-25 13:27:06 +02:00
|
|
|
| {
|
2022-09-05 18:12:30 +02:00
|
|
|
tag: BackupProviderStateTag.Retrying;
|
|
|
|
};
|
2021-06-25 13:27:06 +02:00
|
|
|
|
2021-05-12 14:16:01 +02:00
|
|
|
export interface BackupProviderTerms {
|
|
|
|
supportedProtocolVersion: string;
|
|
|
|
annualFee: AmountString;
|
|
|
|
storageLimitInMegabytes: number;
|
|
|
|
}
|
|
|
|
|
2021-03-17 17:56:37 +01:00
|
|
|
export interface BackupProviderRecord {
|
2021-05-21 11:47:11 +02:00
|
|
|
/**
|
|
|
|
* Base URL of the provider.
|
2021-06-02 13:23:51 +02:00
|
|
|
*
|
2021-05-21 11:47:11 +02:00
|
|
|
* Primary key for the record.
|
|
|
|
*/
|
2021-03-17 17:56:37 +01:00
|
|
|
baseUrl: string;
|
|
|
|
|
2021-07-15 20:03:45 +02:00
|
|
|
/**
|
|
|
|
* Name of the provider
|
|
|
|
*/
|
|
|
|
name: string;
|
|
|
|
|
2021-03-17 17:56:37 +01:00
|
|
|
/**
|
|
|
|
* Terms of service of the provider.
|
|
|
|
* Might be unavailable in the DB in certain situations
|
|
|
|
* (such as loading a recovery document).
|
|
|
|
*/
|
2021-05-12 14:16:01 +02:00
|
|
|
terms?: BackupProviderTerms;
|
2021-03-17 17:56:37 +01:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Hash of the last encrypted backup that we already merged
|
|
|
|
* or successfully uploaded ourselves.
|
|
|
|
*/
|
|
|
|
lastBackupHash?: string;
|
|
|
|
|
2021-06-23 13:06:32 +02:00
|
|
|
/**
|
|
|
|
* Last time that we successfully uploaded a backup (or
|
|
|
|
* the uploaded backup was already current).
|
|
|
|
*
|
|
|
|
* Does NOT correspond to the timestamp of the backup,
|
|
|
|
* which only changes when the backup content changes.
|
|
|
|
*/
|
2023-05-26 12:19:32 +02:00
|
|
|
lastBackupCycleTimestamp?: TalerPreciseTimestamp;
|
2021-03-17 17:56:37 +01:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Proposal that we're currently trying to pay for.
|
|
|
|
*
|
|
|
|
* (Also included in paymentProposalIds.)
|
2021-06-25 13:27:06 +02:00
|
|
|
*
|
|
|
|
* FIXME: Make this part of a proper BackupProviderState?
|
2021-03-17 17:56:37 +01:00
|
|
|
*/
|
|
|
|
currentPaymentProposalId?: string;
|
|
|
|
|
2022-11-25 03:16:01 +01:00
|
|
|
shouldRetryFreshProposal: boolean;
|
|
|
|
|
2021-03-17 17:56:37 +01:00
|
|
|
/**
|
|
|
|
* Proposals that were used to pay (or attempt to pay) the provider.
|
|
|
|
*
|
|
|
|
* Stored to display a history of payments to the provider, and
|
|
|
|
* to make sure that the wallet isn't overpaying.
|
|
|
|
*/
|
|
|
|
paymentProposalIds: string[];
|
|
|
|
|
2021-06-25 13:27:06 +02:00
|
|
|
state: BackupProviderState;
|
2021-05-12 14:16:01 +02:00
|
|
|
|
|
|
|
/**
|
|
|
|
* UIDs for the operation that added the backup provider.
|
|
|
|
*/
|
|
|
|
uids: string[];
|
2021-03-17 17:56:37 +01:00
|
|
|
}
|
|
|
|
|
2023-04-23 22:49:42 +02:00
|
|
|
export enum DepositOperationStatus {
|
2023-09-07 20:35:46 +02:00
|
|
|
PendingDeposit = 0x0100_0000,
|
|
|
|
PendingTrack = 0x0100_0001,
|
|
|
|
PendingKyc = 0x0100_0002,
|
|
|
|
|
|
|
|
Aborting = 0x0103_0000,
|
2023-05-25 19:26:40 +02:00
|
|
|
|
2023-09-07 20:35:46 +02:00
|
|
|
SuspendedDeposit = 0x0110_0000,
|
|
|
|
SuspendedTrack = 0x0110_0001,
|
|
|
|
SuspendedKyc = 0x0110_0002,
|
2023-05-25 19:26:40 +02:00
|
|
|
|
2023-09-07 20:35:46 +02:00
|
|
|
SuspendedAborting = 0x0113_0000,
|
|
|
|
|
|
|
|
Finished = 0x0500_0000,
|
|
|
|
Failed = 0x0501_0000,
|
|
|
|
Aborted = 0x0503_0000,
|
2023-04-23 22:49:42 +02:00
|
|
|
}
|
|
|
|
|
2023-04-24 20:24:23 +02:00
|
|
|
export interface DepositTrackingInfo {
|
|
|
|
// Raw wire transfer identifier of the deposit.
|
|
|
|
wireTransferId: string;
|
|
|
|
// When was the wire transfer given to the bank.
|
|
|
|
timestampExecuted: TalerProtocolTimestamp;
|
|
|
|
// Total amount transfer for this wtid (including fees)
|
|
|
|
amountRaw: AmountString;
|
|
|
|
// Wire fee amount for this exchange
|
|
|
|
wireFee: AmountString;
|
|
|
|
|
|
|
|
exchangePub: string;
|
|
|
|
}
|
|
|
|
|
2021-03-17 17:56:37 +01:00
|
|
|
/**
|
|
|
|
* Group of deposits made by the wallet.
|
|
|
|
*/
|
|
|
|
export interface DepositGroupRecord {
|
|
|
|
depositGroupId: string;
|
|
|
|
|
2023-09-12 13:48:52 +02:00
|
|
|
currency: string;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Instructed amount.
|
|
|
|
*/
|
|
|
|
amount: AmountString;
|
|
|
|
|
|
|
|
wireTransferDeadline: TalerProtocolTimestamp;
|
|
|
|
|
2021-03-17 17:56:37 +01:00
|
|
|
merchantPub: string;
|
|
|
|
merchantPriv: string;
|
|
|
|
|
|
|
|
noncePriv: string;
|
|
|
|
noncePub: string;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Wire information used by all deposits in this
|
|
|
|
* deposit group.
|
|
|
|
*/
|
|
|
|
wire: {
|
|
|
|
payto_uri: string;
|
|
|
|
salt: string;
|
|
|
|
};
|
|
|
|
|
|
|
|
contractTermsHash: string;
|
|
|
|
|
|
|
|
payCoinSelection: PayCoinSelection;
|
|
|
|
|
2021-06-22 18:43:11 +02:00
|
|
|
payCoinSelectionUid: string;
|
|
|
|
|
2022-11-02 17:42:14 +01:00
|
|
|
totalPayCost: AmountString;
|
2021-03-17 17:56:37 +01:00
|
|
|
|
2023-04-05 17:38:34 +02:00
|
|
|
/**
|
|
|
|
* The counterparty effective deposit amount.
|
|
|
|
*/
|
2023-09-08 12:54:31 +02:00
|
|
|
counterpartyEffectiveDepositAmount: AmountString;
|
2021-03-17 17:56:37 +01:00
|
|
|
|
2023-05-26 12:19:32 +02:00
|
|
|
timestampCreated: TalerPreciseTimestamp;
|
2021-03-17 17:56:37 +01:00
|
|
|
|
2023-05-26 12:19:32 +02:00
|
|
|
timestampFinished: TalerPreciseTimestamp | undefined;
|
2021-03-17 17:56:37 +01:00
|
|
|
|
2023-04-23 22:49:42 +02:00
|
|
|
operationStatus: DepositOperationStatus;
|
2023-01-15 21:48:41 +01:00
|
|
|
|
2023-09-08 12:54:31 +02:00
|
|
|
statusPerCoin: DepositElementStatus[];
|
2023-03-29 20:14:02 +02:00
|
|
|
|
2023-04-23 22:49:42 +02:00
|
|
|
/**
|
|
|
|
* When the deposit transaction was aborted and
|
|
|
|
* refreshes were tried, we create a refresh
|
|
|
|
* group and store the ID here.
|
|
|
|
*/
|
|
|
|
abortRefreshGroupId?: string;
|
|
|
|
|
2023-06-26 12:48:20 +02:00
|
|
|
kycInfo?: DepositKycInfo;
|
|
|
|
|
2023-04-23 22:49:42 +02:00
|
|
|
// FIXME: Do we need this and should it be in this object store?
|
2023-03-29 20:14:02 +02:00
|
|
|
trackingState?: {
|
2023-04-24 20:24:23 +02:00
|
|
|
[signature: string]: DepositTrackingInfo;
|
2023-03-29 20:14:02 +02:00
|
|
|
};
|
2021-03-17 17:56:37 +01:00
|
|
|
}
|
|
|
|
|
2023-06-26 12:48:20 +02:00
|
|
|
export interface DepositKycInfo {
|
|
|
|
kycUrl: string;
|
|
|
|
requirementRow: number;
|
|
|
|
paytoHash: string;
|
|
|
|
exchangeBaseUrl: string;
|
|
|
|
}
|
|
|
|
|
2021-05-12 15:26:15 +02:00
|
|
|
export interface TombstoneRecord {
|
|
|
|
/**
|
2022-10-15 21:26:36 +02:00
|
|
|
* Tombstone ID, with the syntax "tmb:<type>:<key>".
|
2021-05-12 15:26:15 +02:00
|
|
|
*/
|
|
|
|
id: string;
|
|
|
|
}
|
|
|
|
|
2023-09-07 20:35:46 +02:00
|
|
|
export enum PeerPushDebitStatus {
|
2022-11-02 17:02:42 +01:00
|
|
|
/**
|
|
|
|
* Initiated, but no purse created yet.
|
|
|
|
*/
|
2023-09-07 20:35:46 +02:00
|
|
|
PendingCreatePurse = 0x0100_0000 /* ACTIVE_START */,
|
|
|
|
PendingReady = 0x0100_0001,
|
|
|
|
AbortingDeletePurse = 0x0103_0000,
|
|
|
|
AbortingRefresh = 0x0103_0001,
|
2023-05-05 10:56:42 +02:00
|
|
|
|
2023-09-07 20:35:46 +02:00
|
|
|
SuspendedCreatePurse = 0x0110_0000,
|
|
|
|
SuspendedReady = 0x0110_0001,
|
|
|
|
SuspendedAbortingDeletePurse = 0x0113_0000,
|
|
|
|
SuspendedAbortingRefresh = 0x0113_0001,
|
2023-05-05 10:56:42 +02:00
|
|
|
|
2023-09-07 20:35:46 +02:00
|
|
|
Done = 0x0500_0000,
|
|
|
|
Aborted = 0x0503_0000,
|
|
|
|
Failed = 0x0501_0000,
|
|
|
|
Expired = 0x0502_0000,
|
2022-01-11 21:00:12 +01:00
|
|
|
}
|
|
|
|
|
2023-01-12 15:11:32 +01:00
|
|
|
export interface PeerPushPaymentCoinSelection {
|
|
|
|
contributions: AmountString[];
|
|
|
|
coinPubs: CoinPublicKeyString[];
|
|
|
|
}
|
|
|
|
|
2022-06-21 12:40:12 +02:00
|
|
|
/**
|
|
|
|
* Record for a push P2P payment that this wallet initiated.
|
|
|
|
*/
|
2023-09-07 20:35:46 +02:00
|
|
|
export interface PeerPushDebitRecord {
|
2022-06-21 12:40:12 +02:00
|
|
|
/**
|
|
|
|
* What exchange are funds coming from?
|
|
|
|
*/
|
|
|
|
exchangeBaseUrl: string;
|
|
|
|
|
2023-01-12 15:11:32 +01:00
|
|
|
/**
|
|
|
|
* Instructed amount.
|
|
|
|
*/
|
2022-06-21 12:40:12 +02:00
|
|
|
amount: AmountString;
|
|
|
|
|
2023-01-13 02:24:19 +01:00
|
|
|
totalCost: AmountString;
|
|
|
|
|
2023-01-12 15:11:32 +01:00
|
|
|
coinSel: PeerPushPaymentCoinSelection;
|
|
|
|
|
2022-11-02 17:02:42 +01:00
|
|
|
contractTermsHash: HashCodeString;
|
|
|
|
|
2022-06-21 12:40:12 +02:00
|
|
|
/**
|
|
|
|
* Purse public key. Used as the primary key to look
|
|
|
|
* up this record.
|
|
|
|
*/
|
|
|
|
pursePub: string;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Purse private key.
|
|
|
|
*/
|
|
|
|
pursePriv: string;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Public key of the merge capability of the purse.
|
|
|
|
*/
|
|
|
|
mergePub: string;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Private key of the merge capability of the purse.
|
|
|
|
*/
|
|
|
|
mergePriv: string;
|
|
|
|
|
2022-07-12 17:41:14 +02:00
|
|
|
contractPriv: string;
|
2023-01-12 15:11:32 +01:00
|
|
|
contractPub: string;
|
|
|
|
|
2023-06-06 15:00:10 +02:00
|
|
|
/**
|
|
|
|
* 24 byte nonce.
|
|
|
|
*/
|
|
|
|
contractEncNonce: string;
|
|
|
|
|
2022-06-21 12:40:12 +02:00
|
|
|
purseExpiration: TalerProtocolTimestamp;
|
|
|
|
|
2023-05-26 12:19:32 +02:00
|
|
|
timestampCreated: TalerPreciseTimestamp;
|
2022-11-02 17:02:42 +01:00
|
|
|
|
2023-06-05 17:58:20 +02:00
|
|
|
abortRefreshGroupId?: string;
|
|
|
|
|
2022-06-21 12:40:12 +02:00
|
|
|
/**
|
2022-11-02 17:02:42 +01:00
|
|
|
* Status of the peer push payment initiation.
|
2022-06-21 12:40:12 +02:00
|
|
|
*/
|
2023-09-07 20:35:46 +02:00
|
|
|
status: PeerPushDebitStatus;
|
2022-06-21 12:40:12 +02:00
|
|
|
}
|
|
|
|
|
2023-09-07 20:35:46 +02:00
|
|
|
export enum PeerPullPaymentCreditStatus {
|
|
|
|
PendingCreatePurse = 0x0100_0000,
|
2023-02-20 21:26:08 +01:00
|
|
|
/**
|
|
|
|
* Purse created, waiting for the other party to accept the
|
|
|
|
* invoice and deposit money into it.
|
|
|
|
*/
|
2023-09-07 20:35:46 +02:00
|
|
|
PendingReady = 0x0100_0001,
|
|
|
|
PendingMergeKycRequired = 0x0100_0002,
|
|
|
|
PendingWithdrawing = 0x0100_0003,
|
2023-05-28 18:03:28 +02:00
|
|
|
|
2023-09-07 20:35:46 +02:00
|
|
|
AbortingDeletePurse = 0x0103_0000,
|
2023-05-28 18:03:28 +02:00
|
|
|
|
2023-09-07 20:35:46 +02:00
|
|
|
SuspendedCreatePurse = 0x0110_0000,
|
|
|
|
SuspendedReady = 0x0110_0001,
|
|
|
|
SuspendedMergeKycRequired = 0x0110_0002,
|
2023-09-08 11:45:31 +02:00
|
|
|
SuspendedWithdrawing = 0x0110_0000,
|
2023-09-07 20:35:46 +02:00
|
|
|
|
|
|
|
SuspendedAbortingDeletePurse = 0x0113_0000,
|
|
|
|
|
|
|
|
Done = 0x0500_0000,
|
|
|
|
Failed = 0x0501_0000,
|
|
|
|
Aborted = 0x0503_0000,
|
2023-02-20 21:26:08 +01:00
|
|
|
}
|
|
|
|
|
2023-09-07 20:35:46 +02:00
|
|
|
export interface PeerPullCreditRecord {
|
2022-08-23 11:29:45 +02:00
|
|
|
/**
|
|
|
|
* What exchange are we using for the payment request?
|
|
|
|
*/
|
|
|
|
exchangeBaseUrl: string;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Amount requested.
|
2023-09-08 11:45:31 +02:00
|
|
|
* FIXME: What type of instructed amount is i?
|
2022-08-23 11:29:45 +02:00
|
|
|
*/
|
|
|
|
amount: AmountString;
|
|
|
|
|
2023-02-23 16:07:14 +01:00
|
|
|
estimatedAmountEffective: AmountString;
|
|
|
|
|
2022-08-23 11:29:45 +02:00
|
|
|
/**
|
|
|
|
* Purse public key. Used as the primary key to look
|
|
|
|
* up this record.
|
|
|
|
*/
|
|
|
|
pursePub: string;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Purse private key.
|
|
|
|
*/
|
|
|
|
pursePriv: string;
|
|
|
|
|
|
|
|
/**
|
2022-11-02 17:02:42 +01:00
|
|
|
* Hash of the contract terms. Also
|
|
|
|
* used to look up the contract terms in the DB.
|
2022-08-23 11:29:45 +02:00
|
|
|
*/
|
2022-11-02 17:02:42 +01:00
|
|
|
contractTermsHash: string;
|
|
|
|
|
2023-01-12 16:57:51 +01:00
|
|
|
mergePub: string;
|
|
|
|
mergePriv: string;
|
|
|
|
|
|
|
|
contractPub: string;
|
|
|
|
contractPriv: string;
|
|
|
|
|
2023-06-06 15:00:10 +02:00
|
|
|
contractEncNonce: string;
|
|
|
|
|
2023-05-26 12:19:32 +02:00
|
|
|
mergeTimestamp: TalerPreciseTimestamp;
|
2023-01-12 16:57:51 +01:00
|
|
|
|
|
|
|
mergeReserveRowId: number;
|
|
|
|
|
2022-11-02 17:02:42 +01:00
|
|
|
/**
|
|
|
|
* Status of the peer pull payment initiation.
|
|
|
|
*/
|
2023-09-07 20:35:46 +02:00
|
|
|
status: PeerPullPaymentCreditStatus;
|
2023-02-20 00:36:02 +01:00
|
|
|
|
2023-03-29 05:06:24 +02:00
|
|
|
kycInfo?: KycPendingInfo;
|
|
|
|
|
2023-06-05 13:33:14 +02:00
|
|
|
kycUrl?: string;
|
|
|
|
|
2023-02-20 00:36:02 +01:00
|
|
|
withdrawalGroupId: string | undefined;
|
|
|
|
}
|
|
|
|
|
2023-09-07 20:35:46 +02:00
|
|
|
export enum PeerPushCreditStatus {
|
|
|
|
PendingMerge = 0x0100_0000,
|
|
|
|
PendingMergeKycRequired = 0x0100_0001,
|
2023-02-20 00:36:02 +01:00
|
|
|
/**
|
|
|
|
* Merge was successful and withdrawal group has been created, now
|
|
|
|
* everything is in the hand of the withdrawal group.
|
|
|
|
*/
|
2023-09-07 20:35:46 +02:00
|
|
|
PendingWithdrawing = 0x0100_0002,
|
2023-05-28 18:03:28 +02:00
|
|
|
|
2023-09-07 20:35:46 +02:00
|
|
|
SuspendedMerge = 0x0110_0000,
|
|
|
|
SuspendedMergeKycRequired = 0x0110_0001,
|
|
|
|
SuspendedWithdrawing = 0x0110_0002,
|
2023-05-28 18:03:28 +02:00
|
|
|
|
2023-09-07 20:35:46 +02:00
|
|
|
DialogProposed = 0x0101_0000,
|
2023-05-28 18:03:28 +02:00
|
|
|
|
2023-09-07 20:35:46 +02:00
|
|
|
Done = 0x0500_0000,
|
|
|
|
Aborted = 0x0503_0000,
|
|
|
|
Failed = 0x0501_0000,
|
2022-08-23 11:29:45 +02:00
|
|
|
}
|
|
|
|
|
2022-06-21 12:40:12 +02:00
|
|
|
/**
|
2022-07-12 17:41:14 +02:00
|
|
|
* Record for a push P2P payment that this wallet was offered.
|
|
|
|
*
|
2022-08-09 15:00:45 +02:00
|
|
|
* Unique: (exchangeBaseUrl, pursePub)
|
2022-06-21 12:40:12 +02:00
|
|
|
*/
|
2022-07-12 17:41:14 +02:00
|
|
|
export interface PeerPushPaymentIncomingRecord {
|
2023-09-07 20:35:46 +02:00
|
|
|
peerPushCreditId: string;
|
2022-08-09 15:00:45 +02:00
|
|
|
|
2022-07-12 17:41:14 +02:00
|
|
|
exchangeBaseUrl: string;
|
|
|
|
|
|
|
|
pursePub: string;
|
|
|
|
|
|
|
|
mergePriv: string;
|
|
|
|
|
|
|
|
contractPriv: string;
|
|
|
|
|
2023-05-26 12:19:32 +02:00
|
|
|
timestamp: TalerPreciseTimestamp;
|
2022-07-12 17:41:14 +02:00
|
|
|
|
2023-02-20 03:22:43 +01:00
|
|
|
estimatedAmountEffective: AmountString;
|
|
|
|
|
2022-11-02 17:02:42 +01:00
|
|
|
/**
|
|
|
|
* Hash of the contract terms. Also
|
|
|
|
* used to look up the contract terms in the DB.
|
|
|
|
*/
|
|
|
|
contractTermsHash: string;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Status of the peer push payment incoming initiation.
|
|
|
|
*/
|
2023-09-07 20:35:46 +02:00
|
|
|
status: PeerPushCreditStatus;
|
2023-02-20 00:36:02 +01:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Associated withdrawal group.
|
|
|
|
*/
|
|
|
|
withdrawalGroupId: string | undefined;
|
2023-02-20 03:22:43 +01:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Currency of the peer push payment credit transaction.
|
|
|
|
*
|
|
|
|
* Mandatory in current schema version, optional for compatibility
|
|
|
|
* with older (ver_minor<4) DB versions.
|
|
|
|
*/
|
|
|
|
currency: string | undefined;
|
2023-03-29 05:06:24 +02:00
|
|
|
|
|
|
|
kycInfo?: KycPendingInfo;
|
2023-06-05 13:33:14 +02:00
|
|
|
|
|
|
|
kycUrl?: string;
|
2022-11-02 17:02:42 +01:00
|
|
|
}
|
2022-07-12 17:41:14 +02:00
|
|
|
|
2023-05-28 18:03:28 +02:00
|
|
|
export enum PeerPullDebitRecordStatus {
|
2023-09-07 20:35:46 +02:00
|
|
|
PendingDeposit = 0x0100_0001,
|
|
|
|
AbortingRefresh = 0x0103_0001,
|
2023-05-28 18:03:28 +02:00
|
|
|
|
2023-09-07 20:35:46 +02:00
|
|
|
SuspendedDeposit = 0x0110_0001,
|
|
|
|
SuspendedAbortingRefresh = 0x0113_0001,
|
2023-05-28 18:03:28 +02:00
|
|
|
|
2023-09-07 20:35:46 +02:00
|
|
|
DialogProposed = 0x0101_0001,
|
2023-05-28 18:03:28 +02:00
|
|
|
|
2023-09-07 20:35:46 +02:00
|
|
|
Done = 0x0500_0000,
|
|
|
|
Aborted = 0x0503_0000,
|
|
|
|
Failed = 0x0501_0000,
|
2022-07-12 17:41:14 +02:00
|
|
|
}
|
2022-06-21 12:40:12 +02:00
|
|
|
|
2023-02-19 23:13:44 +01:00
|
|
|
export interface PeerPullPaymentCoinSelection {
|
|
|
|
contributions: AmountString[];
|
|
|
|
coinPubs: CoinPublicKeyString[];
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Total cost based on the coin selection.
|
|
|
|
* Non undefined after status === "Accepted"
|
|
|
|
*/
|
|
|
|
totalCost: AmountString | undefined;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* AKA PeerPullDebit.
|
|
|
|
*/
|
2022-08-24 11:11:02 +02:00
|
|
|
export interface PeerPullPaymentIncomingRecord {
|
2023-09-07 20:35:46 +02:00
|
|
|
peerPullDebitId: string;
|
2022-08-24 11:11:02 +02:00
|
|
|
|
|
|
|
pursePub: string;
|
|
|
|
|
|
|
|
exchangeBaseUrl: string;
|
|
|
|
|
2023-09-12 13:48:52 +02:00
|
|
|
amount: AmountString;
|
|
|
|
|
|
|
|
contractTermsHash: string;
|
2022-08-24 11:11:02 +02:00
|
|
|
|
2023-05-26 12:19:32 +02:00
|
|
|
timestampCreated: TalerPreciseTimestamp;
|
2022-08-24 22:17:19 +02:00
|
|
|
|
2023-02-19 23:13:44 +01:00
|
|
|
/**
|
|
|
|
* Contract priv that we got from the other party.
|
|
|
|
*/
|
2022-08-24 11:11:02 +02:00
|
|
|
contractPriv: string;
|
2022-11-02 17:02:42 +01:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Status of the peer push payment incoming initiation.
|
|
|
|
*/
|
2023-05-28 18:03:28 +02:00
|
|
|
status: PeerPullDebitRecordStatus;
|
2023-01-18 21:31:34 +01:00
|
|
|
|
|
|
|
/**
|
2023-02-19 23:13:44 +01:00
|
|
|
* Estimated total cost when the record was created.
|
2023-01-18 21:31:34 +01:00
|
|
|
*/
|
2023-02-19 23:13:44 +01:00
|
|
|
totalCostEstimated: AmountString;
|
|
|
|
|
2023-06-05 18:38:17 +02:00
|
|
|
abortRefreshGroupId?: string;
|
|
|
|
|
2023-02-19 23:13:44 +01:00
|
|
|
coinSel?: PeerPullPaymentCoinSelection;
|
2022-08-24 11:11:02 +02:00
|
|
|
}
|
|
|
|
|
2022-09-21 21:47:00 +02:00
|
|
|
/**
|
|
|
|
* Store for extra information about a reserve.
|
|
|
|
*
|
|
|
|
* Mostly used to store the private key for a reserve and to allow
|
|
|
|
* other records to reference the reserve key pair via a small row ID.
|
2022-11-02 15:00:05 +01:00
|
|
|
*
|
|
|
|
* In the future, we might also store KYC info about a reserve here.
|
2022-09-21 21:47:00 +02:00
|
|
|
*/
|
2022-08-26 01:18:01 +02:00
|
|
|
export interface ReserveRecord {
|
2022-09-21 21:47:00 +02:00
|
|
|
rowId?: number;
|
2022-08-26 01:18:01 +02:00
|
|
|
reservePub: string;
|
|
|
|
reservePriv: string;
|
|
|
|
}
|
|
|
|
|
2022-09-05 18:12:30 +02:00
|
|
|
export interface OperationRetryRecord {
|
|
|
|
/**
|
|
|
|
* Unique identifier for the operation. Typically of
|
|
|
|
* the format `${opType}-${opUniqueKey}`
|
2022-09-16 17:35:06 +02:00
|
|
|
*
|
2023-02-20 20:14:37 +01:00
|
|
|
* @see {@link TaskIdentifiers}
|
2022-09-05 18:12:30 +02:00
|
|
|
*/
|
|
|
|
id: string;
|
|
|
|
|
|
|
|
lastError?: TalerErrorDetail;
|
|
|
|
|
|
|
|
retryInfo: RetryInfo;
|
|
|
|
}
|
|
|
|
|
2022-09-16 16:20:47 +02:00
|
|
|
/**
|
|
|
|
* Availability of coins of a given denomination (and age restriction!).
|
|
|
|
*
|
|
|
|
* We can't store this information with the denomination record, as one denomination
|
|
|
|
* can be withdrawn with multiple age restrictions.
|
|
|
|
*/
|
|
|
|
export interface CoinAvailabilityRecord {
|
|
|
|
currency: string;
|
2023-09-08 13:33:21 +02:00
|
|
|
value: AmountString;
|
2022-09-16 16:20:47 +02:00
|
|
|
denomPubHash: string;
|
|
|
|
exchangeBaseUrl: string;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Age restriction on the coin, or 0 for no age restriction (or
|
|
|
|
* denomination without age restriction support).
|
|
|
|
*/
|
|
|
|
maxAge: number;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Number of fresh coins of this denomination that are available.
|
|
|
|
*/
|
|
|
|
freshCoinCount: number;
|
2023-06-26 19:27:34 +02:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Number of fresh coins that are available
|
|
|
|
* and visible, i.e. the source transaction is in
|
|
|
|
* a final state.
|
|
|
|
*/
|
2023-06-28 17:22:27 +02:00
|
|
|
visibleCoinCount: number;
|
2022-09-16 16:20:47 +02:00
|
|
|
}
|
|
|
|
|
2022-10-09 02:23:06 +02:00
|
|
|
export interface ContractTermsRecord {
|
|
|
|
/**
|
|
|
|
* Contract terms hash.
|
|
|
|
*/
|
|
|
|
h: string;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Contract terms JSON.
|
|
|
|
*/
|
|
|
|
contractTermsRaw: any;
|
|
|
|
}
|
|
|
|
|
2022-11-25 03:16:01 +01:00
|
|
|
export interface UserAttentionRecord {
|
|
|
|
info: AttentionInfo;
|
|
|
|
|
|
|
|
entityId: string;
|
2023-05-26 13:52:00 +02:00
|
|
|
|
2022-11-25 03:16:01 +01:00
|
|
|
/**
|
|
|
|
* When the notification was created.
|
2023-05-26 13:52:00 +02:00
|
|
|
* FIXME: This should be a TalerPreciseTimestamp
|
2022-11-25 03:16:01 +01:00
|
|
|
*/
|
|
|
|
createdMs: number;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* When the user mark this notification as read.
|
|
|
|
*/
|
2023-05-26 12:19:32 +02:00
|
|
|
read: TalerPreciseTimestamp | undefined;
|
2022-11-25 03:16:01 +01:00
|
|
|
}
|
|
|
|
|
2023-02-12 21:13:30 +01:00
|
|
|
export interface DbExchangeHandle {
|
|
|
|
url: string;
|
|
|
|
exchangeMasterPub: string;
|
|
|
|
}
|
|
|
|
|
|
|
|
export interface DbAuditorHandle {
|
|
|
|
url: string;
|
|
|
|
auditorPub: string;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Work in progress for regional currencies
|
|
|
|
export interface CurrencySettingsRecord {
|
|
|
|
currency: string;
|
|
|
|
|
|
|
|
globalScopeExchanges: DbExchangeHandle[];
|
|
|
|
|
|
|
|
globalScopeAuditors: DbAuditorHandle[];
|
|
|
|
|
|
|
|
// Used to decide which auditor to show the currency under
|
|
|
|
// when multiple auditors apply.
|
|
|
|
auditorPriority: string[];
|
|
|
|
|
|
|
|
// Later, we might add stuff related to how the currency is rendered.
|
|
|
|
}
|
|
|
|
|
2023-05-05 19:03:44 +02:00
|
|
|
export enum RefundGroupStatus {
|
2023-09-07 20:35:46 +02:00
|
|
|
Pending = 0x0100_0000,
|
|
|
|
Done = 0x0500_0000,
|
|
|
|
Failed = 0x0501_0000,
|
|
|
|
Aborted = 0x0503_0000,
|
2023-05-05 19:03:44 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Metadata about a group of refunds with the merchant.
|
|
|
|
*/
|
|
|
|
export interface RefundGroupRecord {
|
|
|
|
status: RefundGroupStatus;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Timestamp when the refund group was created.
|
|
|
|
*/
|
2023-05-26 12:19:32 +02:00
|
|
|
timestampCreated: TalerPreciseTimestamp;
|
2023-05-05 19:03:44 +02:00
|
|
|
|
|
|
|
proposalId: string;
|
|
|
|
|
|
|
|
refundGroupId: string;
|
|
|
|
|
|
|
|
refreshGroupId?: string;
|
|
|
|
|
|
|
|
amountRaw: AmountString;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Estimated effective amount, based on
|
|
|
|
* refund fees and refresh costs.
|
|
|
|
*/
|
|
|
|
amountEffective: AmountString;
|
|
|
|
}
|
|
|
|
|
|
|
|
export enum RefundItemStatus {
|
|
|
|
/**
|
|
|
|
* Intermittent error that the merchant is
|
|
|
|
* reporting from the exchange.
|
|
|
|
*
|
|
|
|
* We'll try again!
|
|
|
|
*/
|
2023-09-07 20:35:46 +02:00
|
|
|
Pending = 0x0100_0000,
|
2023-05-05 19:03:44 +02:00
|
|
|
/**
|
|
|
|
* Refund was obtained successfully.
|
|
|
|
*/
|
2023-09-07 20:35:46 +02:00
|
|
|
Done = 0x0500_0000,
|
2023-05-05 19:03:44 +02:00
|
|
|
/**
|
|
|
|
* Permanent error reported by the exchange
|
|
|
|
* for the refund.
|
|
|
|
*/
|
2023-09-07 20:35:46 +02:00
|
|
|
Failed = 0x0501_0000,
|
2023-05-05 19:03:44 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Refund for a single coin in a payment with a merchant.
|
|
|
|
*/
|
|
|
|
export interface RefundItemRecord {
|
|
|
|
/**
|
|
|
|
* Auto-increment DB record ID.
|
|
|
|
*/
|
|
|
|
id?: number;
|
|
|
|
|
|
|
|
status: RefundItemStatus;
|
|
|
|
|
|
|
|
refundGroupId: string;
|
|
|
|
|
2023-09-07 20:35:46 +02:00
|
|
|
/**
|
|
|
|
* Execution time as claimed by the merchant
|
|
|
|
*/
|
2023-05-05 19:03:44 +02:00
|
|
|
executionTime: TalerProtocolTimestamp;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Time when the wallet became aware of the refund.
|
|
|
|
*/
|
2023-05-26 12:19:32 +02:00
|
|
|
obtainedTime: TalerPreciseTimestamp;
|
2023-05-05 19:03:44 +02:00
|
|
|
|
|
|
|
refundAmount: AmountString;
|
|
|
|
|
|
|
|
coinPub: string;
|
|
|
|
|
|
|
|
rtxid: number;
|
|
|
|
}
|
|
|
|
|
2023-09-07 20:35:46 +02:00
|
|
|
export function passthroughCodec<T>(): Codec<T> {
|
|
|
|
return codecForAny();
|
|
|
|
}
|
|
|
|
|
2022-09-20 21:44:21 +02:00
|
|
|
/**
|
|
|
|
* Schema definition for the IndexedDB
|
|
|
|
* wallet database.
|
|
|
|
*/
|
2021-06-09 15:14:17 +02:00
|
|
|
export const WalletStoresV1 = {
|
2023-02-12 21:13:30 +01:00
|
|
|
currencySettings: describeStore(
|
|
|
|
"currencySettings",
|
|
|
|
describeContents<CurrencySettingsRecord>({
|
|
|
|
keyPath: ["currency"],
|
|
|
|
}),
|
|
|
|
{},
|
|
|
|
),
|
2022-09-16 16:20:47 +02:00
|
|
|
coinAvailability: describeStore(
|
|
|
|
"coinAvailability",
|
|
|
|
describeContents<CoinAvailabilityRecord>({
|
|
|
|
keyPath: ["exchangeBaseUrl", "denomPubHash", "maxAge"],
|
|
|
|
}),
|
|
|
|
{
|
|
|
|
byExchangeAgeAvailability: describeIndex("byExchangeAgeAvailability", [
|
|
|
|
"exchangeBaseUrl",
|
|
|
|
"maxAge",
|
|
|
|
"freshCoinCount",
|
|
|
|
]),
|
|
|
|
},
|
|
|
|
),
|
2021-06-09 15:14:17 +02:00
|
|
|
coins: describeStore(
|
2022-09-13 13:25:41 +02:00
|
|
|
"coins",
|
|
|
|
describeContents<CoinRecord>({
|
2021-06-09 15:14:17 +02:00
|
|
|
keyPath: "coinPub",
|
|
|
|
}),
|
|
|
|
{
|
|
|
|
byBaseUrl: describeIndex("byBaseUrl", "exchangeBaseUrl"),
|
|
|
|
byDenomPubHash: describeIndex("byDenomPubHash", "denomPubHash"),
|
2022-09-16 16:20:47 +02:00
|
|
|
byExchangeDenomPubHashAndAgeAndStatus: describeIndex(
|
|
|
|
"byExchangeDenomPubHashAndAgeAndStatus",
|
|
|
|
["exchangeBaseUrl", "denomPubHash", "maxAge", "status"],
|
|
|
|
),
|
2021-06-09 15:14:17 +02:00
|
|
|
byCoinEvHash: describeIndex("byCoinEvHash", "coinEvHash"),
|
2023-06-26 19:27:34 +02:00
|
|
|
bySourceTransactionId: describeIndex(
|
|
|
|
"bySourceTransactionId",
|
|
|
|
"sourceTransactionId",
|
|
|
|
{
|
|
|
|
versionAdded: 9,
|
|
|
|
},
|
|
|
|
),
|
2021-06-09 15:14:17 +02:00
|
|
|
},
|
|
|
|
),
|
2022-08-26 01:18:01 +02:00
|
|
|
reserves: describeStore(
|
2022-09-13 13:25:41 +02:00
|
|
|
"reserves",
|
|
|
|
describeContents<ReserveRecord>({
|
2022-09-21 21:47:00 +02:00
|
|
|
keyPath: "rowId",
|
|
|
|
autoIncrement: true,
|
2022-08-26 01:18:01 +02:00
|
|
|
}),
|
2022-09-21 21:47:00 +02:00
|
|
|
{
|
|
|
|
byReservePub: describeIndex("byReservePub", "reservePub", {}),
|
|
|
|
},
|
2022-08-26 01:18:01 +02:00
|
|
|
),
|
2021-06-09 15:14:17 +02:00
|
|
|
config: describeStore(
|
2022-09-13 13:25:41 +02:00
|
|
|
"config",
|
|
|
|
describeContents<ConfigRecord>({ keyPath: "key" }),
|
2021-06-09 15:14:17 +02:00
|
|
|
{},
|
|
|
|
),
|
|
|
|
denominations: describeStore(
|
2022-09-13 13:25:41 +02:00
|
|
|
"denominations",
|
|
|
|
describeContents<DenominationRecord>({
|
2021-06-09 15:14:17 +02:00
|
|
|
keyPath: ["exchangeBaseUrl", "denomPubHash"],
|
|
|
|
}),
|
|
|
|
{
|
|
|
|
byExchangeBaseUrl: describeIndex("byExchangeBaseUrl", "exchangeBaseUrl"),
|
|
|
|
},
|
|
|
|
),
|
|
|
|
exchanges: describeStore(
|
2022-09-13 13:25:41 +02:00
|
|
|
"exchanges",
|
2023-08-30 15:54:44 +02:00
|
|
|
describeContents<ExchangeEntryRecord>({
|
2021-06-09 15:14:17 +02:00
|
|
|
keyPath: "baseUrl",
|
|
|
|
}),
|
|
|
|
{},
|
|
|
|
),
|
|
|
|
exchangeDetails: describeStore(
|
2022-09-13 13:25:41 +02:00
|
|
|
"exchangeDetails",
|
|
|
|
describeContents<ExchangeDetailsRecord>({
|
2022-10-15 16:03:48 +02:00
|
|
|
keyPath: "rowId",
|
|
|
|
autoIncrement: true,
|
2021-06-09 15:14:17 +02:00
|
|
|
}),
|
2022-10-15 16:03:48 +02:00
|
|
|
{
|
|
|
|
byPointer: describeIndex(
|
|
|
|
"byDetailsPointer",
|
|
|
|
["exchangeBaseUrl", "currency", "masterPublicKey"],
|
|
|
|
{
|
|
|
|
unique: true,
|
|
|
|
},
|
|
|
|
),
|
|
|
|
},
|
|
|
|
),
|
2023-01-11 17:12:08 +01:00
|
|
|
exchangeSignKeys: describeStore(
|
2022-10-15 16:03:48 +02:00
|
|
|
"exchangeSignKeys",
|
|
|
|
describeContents<ExchangeSignkeysRecord>({
|
|
|
|
keyPath: ["exchangeDetailsRowId", "signkeyPub"],
|
|
|
|
}),
|
|
|
|
{
|
|
|
|
byExchangeDetailsRowId: describeIndex("byExchangeDetailsRowId", [
|
|
|
|
"exchangeDetailsRowId",
|
|
|
|
]),
|
|
|
|
},
|
2021-06-09 15:14:17 +02:00
|
|
|
),
|
|
|
|
refreshGroups: describeStore(
|
2022-09-13 13:25:41 +02:00
|
|
|
"refreshGroups",
|
|
|
|
describeContents<RefreshGroupRecord>({
|
2021-03-17 17:56:37 +01:00
|
|
|
keyPath: "refreshGroupId",
|
2021-06-09 15:14:17 +02:00
|
|
|
}),
|
2022-01-11 21:00:12 +01:00
|
|
|
{
|
|
|
|
byStatus: describeIndex("byStatus", "operationStatus"),
|
|
|
|
},
|
2021-06-09 15:14:17 +02:00
|
|
|
),
|
2023-09-08 12:26:58 +02:00
|
|
|
refreshSessions: describeStore(
|
|
|
|
"refreshSessions",
|
|
|
|
describeContents<RefreshSessionRecord>({
|
|
|
|
keyPath: ["refreshGroupId", "coinIndex"],
|
|
|
|
}),
|
|
|
|
{},
|
|
|
|
),
|
2021-06-09 15:14:17 +02:00
|
|
|
recoupGroups: describeStore(
|
2022-09-13 13:25:41 +02:00
|
|
|
"recoupGroups",
|
|
|
|
describeContents<RecoupGroupRecord>({
|
2021-06-09 15:14:17 +02:00
|
|
|
keyPath: "recoupGroupId",
|
|
|
|
}),
|
|
|
|
{},
|
|
|
|
),
|
|
|
|
purchases: describeStore(
|
2022-09-13 13:25:41 +02:00
|
|
|
"purchases",
|
|
|
|
describeContents<PurchaseRecord>({ keyPath: "proposalId" }),
|
2021-03-17 17:56:37 +01:00
|
|
|
{
|
2022-10-08 23:45:49 +02:00
|
|
|
byStatus: describeIndex("byStatus", "purchaseStatus"),
|
2021-06-09 15:14:17 +02:00
|
|
|
byFulfillmentUrl: describeIndex(
|
|
|
|
"byFulfillmentUrl",
|
2022-10-09 02:23:06 +02:00
|
|
|
"download.fulfillmentUrl",
|
2021-06-09 15:14:17 +02:00
|
|
|
),
|
2022-10-08 20:56:57 +02:00
|
|
|
byUrlAndOrderId: describeIndex("byUrlAndOrderId", [
|
|
|
|
"merchantBaseUrl",
|
|
|
|
"orderId",
|
|
|
|
]),
|
2021-03-17 17:56:37 +01:00
|
|
|
},
|
|
|
|
),
|
2023-08-03 18:35:07 +02:00
|
|
|
rewards: describeStore(
|
|
|
|
"rewards",
|
|
|
|
describeContents<RewardRecord>({ keyPath: "walletRewardId" }),
|
2021-06-09 15:14:17 +02:00
|
|
|
{
|
2023-08-03 18:35:07 +02:00
|
|
|
byMerchantTipIdAndBaseUrl: describeIndex("byMerchantRewardIdAndBaseUrl", [
|
|
|
|
"merchantRewardId",
|
2021-06-09 15:14:17 +02:00
|
|
|
"merchantBaseUrl",
|
|
|
|
]),
|
2023-06-06 16:47:32 +02:00
|
|
|
byStatus: describeIndex("byStatus", "status", {
|
|
|
|
versionAdded: 8,
|
|
|
|
}),
|
2021-06-09 15:14:17 +02:00
|
|
|
},
|
|
|
|
),
|
|
|
|
withdrawalGroups: describeStore(
|
2022-09-13 13:25:41 +02:00
|
|
|
"withdrawalGroups",
|
|
|
|
describeContents<WithdrawalGroupRecord>({
|
2021-06-09 15:14:17 +02:00
|
|
|
keyPath: "withdrawalGroupId",
|
|
|
|
}),
|
|
|
|
{
|
2022-09-21 20:46:45 +02:00
|
|
|
byStatus: describeIndex("byStatus", "status"),
|
2022-08-24 19:44:24 +02:00
|
|
|
byTalerWithdrawUri: describeIndex(
|
|
|
|
"byTalerWithdrawUri",
|
2022-08-25 17:49:24 +02:00
|
|
|
"wgInfo.bankInfo.talerWithdrawUri",
|
2022-08-24 19:44:24 +02:00
|
|
|
),
|
2021-06-09 15:14:17 +02:00
|
|
|
},
|
|
|
|
),
|
|
|
|
planchets: describeStore(
|
2022-09-13 13:25:41 +02:00
|
|
|
"planchets",
|
|
|
|
describeContents<PlanchetRecord>({ keyPath: "coinPub" }),
|
2021-06-09 15:14:17 +02:00
|
|
|
{
|
|
|
|
byGroupAndIndex: describeIndex("byGroupAndIndex", [
|
|
|
|
"withdrawalGroupId",
|
|
|
|
"coinIdx",
|
|
|
|
]),
|
|
|
|
byGroup: describeIndex("byGroup", "withdrawalGroupId"),
|
|
|
|
byCoinEvHash: describeIndex("byCoinEv", "coinEvHash"),
|
|
|
|
},
|
|
|
|
),
|
|
|
|
bankWithdrawUris: describeStore(
|
2022-09-13 13:25:41 +02:00
|
|
|
"bankWithdrawUris",
|
|
|
|
describeContents<BankWithdrawUriRecord>({
|
2021-06-09 15:14:17 +02:00
|
|
|
keyPath: "talerWithdrawUri",
|
|
|
|
}),
|
|
|
|
{},
|
|
|
|
),
|
|
|
|
backupProviders: describeStore(
|
2022-09-13 13:25:41 +02:00
|
|
|
"backupProviders",
|
|
|
|
describeContents<BackupProviderRecord>({
|
2021-06-09 15:14:17 +02:00
|
|
|
keyPath: "baseUrl",
|
|
|
|
}),
|
2021-06-25 13:27:06 +02:00
|
|
|
{
|
|
|
|
byPaymentProposalId: describeIndex(
|
|
|
|
"byPaymentProposalId",
|
|
|
|
"paymentProposalIds",
|
|
|
|
{
|
|
|
|
multiEntry: true,
|
|
|
|
},
|
|
|
|
),
|
|
|
|
},
|
2021-06-09 15:14:17 +02:00
|
|
|
),
|
|
|
|
depositGroups: describeStore(
|
2022-09-13 13:25:41 +02:00
|
|
|
"depositGroups",
|
|
|
|
describeContents<DepositGroupRecord>({
|
2021-06-09 15:14:17 +02:00
|
|
|
keyPath: "depositGroupId",
|
|
|
|
}),
|
2022-01-11 21:00:12 +01:00
|
|
|
{
|
|
|
|
byStatus: describeIndex("byStatus", "operationStatus"),
|
|
|
|
},
|
2021-06-09 15:14:17 +02:00
|
|
|
),
|
|
|
|
tombstones: describeStore(
|
2022-09-13 13:25:41 +02:00
|
|
|
"tombstones",
|
|
|
|
describeContents<TombstoneRecord>({ keyPath: "id" }),
|
2021-06-09 15:14:17 +02:00
|
|
|
{},
|
|
|
|
),
|
2022-09-05 18:12:30 +02:00
|
|
|
operationRetries: describeStore(
|
2022-09-13 13:25:41 +02:00
|
|
|
"operationRetries",
|
|
|
|
describeContents<OperationRetryRecord>({
|
2022-09-05 18:12:30 +02:00
|
|
|
keyPath: "id",
|
|
|
|
}),
|
|
|
|
{},
|
|
|
|
),
|
2023-09-07 20:35:46 +02:00
|
|
|
peerPushCredit: describeStore(
|
|
|
|
"peerPushCredit",
|
2022-09-13 13:25:41 +02:00
|
|
|
describeContents<PeerPushPaymentIncomingRecord>({
|
2023-09-07 20:35:46 +02:00
|
|
|
keyPath: "peerPushCreditId",
|
2022-07-12 17:41:14 +02:00
|
|
|
}),
|
2022-08-09 15:00:45 +02:00
|
|
|
{
|
|
|
|
byExchangeAndPurse: describeIndex("byExchangeAndPurse", [
|
|
|
|
"exchangeBaseUrl",
|
|
|
|
"pursePub",
|
|
|
|
]),
|
2023-02-20 00:36:02 +01:00
|
|
|
byExchangeAndContractPriv: describeIndex(
|
|
|
|
"byExchangeAndContractPriv",
|
|
|
|
["exchangeBaseUrl", "contractPriv"],
|
|
|
|
{
|
|
|
|
unique: true,
|
|
|
|
},
|
|
|
|
),
|
|
|
|
byWithdrawalGroupId: describeIndex(
|
|
|
|
"byWithdrawalGroupId",
|
|
|
|
"withdrawalGroupId",
|
2023-09-07 20:35:46 +02:00
|
|
|
{},
|
2023-02-20 00:36:02 +01:00
|
|
|
),
|
2022-11-02 18:31:05 +01:00
|
|
|
byStatus: describeIndex("byStatus", "status"),
|
2022-08-09 15:00:45 +02:00
|
|
|
},
|
2022-07-12 17:41:14 +02:00
|
|
|
),
|
2023-09-07 20:35:46 +02:00
|
|
|
peerPullDebit: describeStore(
|
|
|
|
"peerPullDebit",
|
2022-09-13 13:25:41 +02:00
|
|
|
describeContents<PeerPullPaymentIncomingRecord>({
|
2023-09-07 20:35:46 +02:00
|
|
|
keyPath: "peerPullDebitId",
|
2022-08-24 11:11:02 +02:00
|
|
|
}),
|
|
|
|
{
|
|
|
|
byExchangeAndPurse: describeIndex("byExchangeAndPurse", [
|
|
|
|
"exchangeBaseUrl",
|
|
|
|
"pursePub",
|
|
|
|
]),
|
2023-02-19 23:13:44 +01:00
|
|
|
byExchangeAndContractPriv: describeIndex(
|
|
|
|
"byExchangeAndContractPriv",
|
|
|
|
["exchangeBaseUrl", "contractPriv"],
|
|
|
|
{
|
|
|
|
unique: true,
|
|
|
|
},
|
|
|
|
),
|
2022-11-02 18:31:05 +01:00
|
|
|
byStatus: describeIndex("byStatus", "status"),
|
2022-08-24 11:11:02 +02:00
|
|
|
},
|
|
|
|
),
|
2023-09-07 20:35:46 +02:00
|
|
|
peerPullCredit: describeStore(
|
|
|
|
"peerPullCredit",
|
|
|
|
describeContents<PeerPullCreditRecord>({
|
2022-09-13 13:25:41 +02:00
|
|
|
keyPath: "pursePub",
|
|
|
|
}),
|
2022-11-02 18:31:05 +01:00
|
|
|
{
|
|
|
|
byStatus: describeIndex("byStatus", "status"),
|
2023-02-20 00:36:02 +01:00
|
|
|
byWithdrawalGroupId: describeIndex(
|
|
|
|
"byWithdrawalGroupId",
|
|
|
|
"withdrawalGroupId",
|
2023-09-08 11:45:31 +02:00
|
|
|
{},
|
2023-02-20 00:36:02 +01:00
|
|
|
),
|
2022-11-02 18:31:05 +01:00
|
|
|
},
|
2022-08-24 22:17:19 +02:00
|
|
|
),
|
2023-09-07 20:35:46 +02:00
|
|
|
peerPushDebit: describeStore(
|
|
|
|
"peerPushDebit",
|
|
|
|
describeContents<PeerPushDebitRecord>({
|
2022-09-13 13:25:41 +02:00
|
|
|
keyPath: "pursePub",
|
|
|
|
}),
|
2022-11-02 18:31:05 +01:00
|
|
|
{
|
|
|
|
byStatus: describeIndex("byStatus", "status"),
|
|
|
|
},
|
2022-08-23 11:29:45 +02:00
|
|
|
),
|
2022-09-23 20:17:29 +02:00
|
|
|
bankAccounts: describeStore(
|
|
|
|
"bankAccounts",
|
|
|
|
describeContents<BankAccountsRecord>({
|
|
|
|
keyPath: "uri",
|
|
|
|
}),
|
|
|
|
{},
|
|
|
|
),
|
2022-10-09 02:23:06 +02:00
|
|
|
contractTerms: describeStore(
|
|
|
|
"contractTerms",
|
|
|
|
describeContents<ContractTermsRecord>({
|
|
|
|
keyPath: "h",
|
|
|
|
}),
|
|
|
|
{},
|
|
|
|
),
|
2022-11-25 03:16:01 +01:00
|
|
|
userAttention: describeStore(
|
|
|
|
"userAttention",
|
|
|
|
describeContents<UserAttentionRecord>({
|
|
|
|
keyPath: ["entityId", "info.type"],
|
2023-01-11 14:19:24 +01:00
|
|
|
}),
|
|
|
|
{},
|
|
|
|
),
|
2023-05-05 19:03:44 +02:00
|
|
|
refundGroups: describeStore(
|
|
|
|
"refundGroups",
|
|
|
|
describeContents<RefundGroupRecord>({
|
|
|
|
keyPath: "refundGroupId",
|
|
|
|
}),
|
|
|
|
{
|
|
|
|
byProposalId: describeIndex("byProposalId", "proposalId"),
|
2023-09-08 11:45:31 +02:00
|
|
|
byStatus: describeIndex("byStatus", "status", {}),
|
2023-05-05 19:03:44 +02:00
|
|
|
},
|
|
|
|
),
|
|
|
|
refundItems: describeStore(
|
|
|
|
"refundItems",
|
|
|
|
describeContents<RefundItemRecord>({
|
|
|
|
keyPath: "id",
|
|
|
|
autoIncrement: true,
|
|
|
|
}),
|
|
|
|
{
|
|
|
|
byCoinPubAndRtxid: describeIndex("byCoinPubAndRtxid", [
|
|
|
|
"coinPub",
|
|
|
|
"rtxid",
|
|
|
|
]),
|
|
|
|
byRefundGroupId: describeIndex("byRefundGroupId", ["refundGroupId"]),
|
|
|
|
},
|
|
|
|
),
|
2023-01-11 14:19:24 +01:00
|
|
|
fixups: describeStore(
|
|
|
|
"fixups",
|
|
|
|
describeContents<FixupRecord>({
|
|
|
|
keyPath: "fixupName",
|
2022-11-25 03:16:01 +01:00
|
|
|
}),
|
|
|
|
{},
|
|
|
|
),
|
2021-03-17 17:56:37 +01:00
|
|
|
};
|
|
|
|
|
2023-08-29 20:35:49 +02:00
|
|
|
export type WalletDbReadOnlyTransaction<
|
|
|
|
Stores extends StoreNames<typeof WalletStoresV1> & string,
|
|
|
|
> = DbReadOnlyTransaction<typeof WalletStoresV1, Stores>;
|
|
|
|
|
2023-08-30 15:54:44 +02:00
|
|
|
export type WalletDbReadWriteTransaction<
|
2023-08-29 20:35:49 +02:00
|
|
|
Stores extends StoreNames<typeof WalletStoresV1> & string,
|
|
|
|
> = DbReadWriteTransaction<typeof WalletStoresV1, Stores>;
|
|
|
|
|
2023-01-11 14:19:24 +01:00
|
|
|
/**
|
|
|
|
* An applied migration.
|
|
|
|
*/
|
|
|
|
export interface FixupRecord {
|
|
|
|
fixupName: string;
|
|
|
|
}
|
|
|
|
|
2022-09-23 20:17:29 +02:00
|
|
|
/**
|
|
|
|
* User accounts
|
|
|
|
*/
|
|
|
|
export interface BankAccountsRecord {
|
|
|
|
uri: string;
|
|
|
|
currency: string;
|
2022-09-23 21:00:51 +02:00
|
|
|
kycCompleted: boolean;
|
2022-09-23 20:17:29 +02:00
|
|
|
alias: string;
|
|
|
|
}
|
|
|
|
|
2021-06-14 11:21:29 +02:00
|
|
|
export interface MetaConfigRecord {
|
|
|
|
key: string;
|
|
|
|
value: any;
|
|
|
|
}
|
|
|
|
|
2021-06-09 15:14:17 +02:00
|
|
|
export const walletMetadataStore = {
|
|
|
|
metaConfig: describeStore(
|
2022-09-13 13:25:41 +02:00
|
|
|
"metaConfig",
|
|
|
|
describeContents<MetaConfigRecord>({ keyPath: "key" }),
|
2021-06-09 15:14:17 +02:00
|
|
|
{},
|
|
|
|
),
|
2021-03-17 17:56:37 +01:00
|
|
|
};
|
2021-12-01 18:16:40 +01:00
|
|
|
|
2023-08-30 18:01:18 +02:00
|
|
|
export interface StoredBackupMeta {
|
|
|
|
name: string;
|
|
|
|
}
|
|
|
|
|
|
|
|
export const StoredBackupStores = {
|
|
|
|
backupMeta: describeStore(
|
|
|
|
"backupMeta",
|
2023-08-30 18:33:56 +02:00
|
|
|
describeContents<StoredBackupMeta>({ keyPath: "name" }),
|
2023-08-30 18:01:18 +02:00
|
|
|
{},
|
|
|
|
),
|
|
|
|
backupData: describeStore("backupData", describeContents<any>({}), {}),
|
|
|
|
};
|
|
|
|
|
2023-08-30 15:54:44 +02:00
|
|
|
export interface DbDumpRecord {
|
|
|
|
/**
|
|
|
|
* Key, serialized with structuredEncapsulated.
|
2023-08-30 16:08:51 +02:00
|
|
|
*
|
|
|
|
* Only present for out-of-line keys (i.e. no key path).
|
2023-08-30 15:54:44 +02:00
|
|
|
*/
|
2023-08-30 16:08:51 +02:00
|
|
|
key?: any;
|
2023-08-30 15:54:44 +02:00
|
|
|
/**
|
|
|
|
* Value, serialized with structuredEncapsulated.
|
|
|
|
*/
|
|
|
|
value: any;
|
|
|
|
}
|
|
|
|
|
|
|
|
export interface DbIndexDump {
|
|
|
|
keyPath: string | string[];
|
|
|
|
multiEntry: boolean;
|
|
|
|
unique: boolean;
|
|
|
|
}
|
|
|
|
|
|
|
|
export interface DbStoreDump {
|
|
|
|
keyPath?: string | string[];
|
|
|
|
autoIncrement: boolean;
|
|
|
|
indexes: { [indexName: string]: DbIndexDump };
|
|
|
|
records: DbDumpRecord[];
|
|
|
|
}
|
|
|
|
|
|
|
|
export interface DbDumpDatabase {
|
|
|
|
version: number;
|
|
|
|
stores: { [storeName: string]: DbStoreDump };
|
|
|
|
}
|
|
|
|
|
|
|
|
export interface DbDump {
|
|
|
|
databases: {
|
|
|
|
[name: string]: DbDumpDatabase;
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2023-08-30 16:51:51 +02:00
|
|
|
export async function exportSingleDb(
|
|
|
|
idb: IDBFactory,
|
|
|
|
dbName: string,
|
|
|
|
): Promise<DbDumpDatabase> {
|
|
|
|
const myDb = await openDatabase(
|
|
|
|
idb,
|
|
|
|
dbName,
|
|
|
|
undefined,
|
|
|
|
() => {
|
2023-09-01 10:52:15 +02:00
|
|
|
logger.info(`unexpected onversionchange in exportSingleDb of ${dbName}`);
|
2023-08-30 16:51:51 +02:00
|
|
|
},
|
|
|
|
() => {
|
2023-09-01 10:52:15 +02:00
|
|
|
logger.info(`unexpected onupgradeneeded in exportSingleDb of ${dbName}`);
|
2023-08-30 16:51:51 +02:00
|
|
|
},
|
|
|
|
);
|
2023-08-30 15:54:44 +02:00
|
|
|
|
2023-08-30 16:51:51 +02:00
|
|
|
const singleDbDump: DbDumpDatabase = {
|
|
|
|
version: myDb.version,
|
2023-08-30 15:54:44 +02:00
|
|
|
stores: {},
|
2021-12-01 18:16:40 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
return new Promise((resolve, reject) => {
|
2023-08-30 16:51:51 +02:00
|
|
|
const tx = myDb.transaction(Array.from(myDb.objectStoreNames));
|
2021-12-01 18:16:40 +01:00
|
|
|
tx.addEventListener("complete", () => {
|
2023-09-01 10:52:15 +02:00
|
|
|
//myDb.close();
|
2023-08-30 16:51:51 +02:00
|
|
|
resolve(singleDbDump);
|
2021-12-01 18:16:40 +01:00
|
|
|
});
|
|
|
|
// tslint:disable-next-line:prefer-for-of
|
2023-08-30 16:51:51 +02:00
|
|
|
for (let i = 0; i < myDb.objectStoreNames.length; i++) {
|
|
|
|
const name = myDb.objectStoreNames[i];
|
2023-08-30 15:54:44 +02:00
|
|
|
const store = tx.objectStore(name);
|
|
|
|
const storeDump: DbStoreDump = {
|
|
|
|
autoIncrement: store.autoIncrement,
|
|
|
|
keyPath: store.keyPath,
|
|
|
|
indexes: {},
|
|
|
|
records: [],
|
|
|
|
};
|
|
|
|
const indexNames = store.indexNames;
|
|
|
|
for (let j = 0; j < indexNames.length; j++) {
|
|
|
|
const idxName = indexNames[j];
|
|
|
|
const index = store.index(idxName);
|
|
|
|
storeDump.indexes[idxName] = {
|
|
|
|
keyPath: index.keyPath,
|
|
|
|
multiEntry: index.multiEntry,
|
|
|
|
unique: index.unique,
|
|
|
|
};
|
|
|
|
}
|
2023-08-30 16:51:51 +02:00
|
|
|
singleDbDump.stores[name] = storeDump;
|
2023-08-30 15:54:44 +02:00
|
|
|
store.openCursor().addEventListener("success", (e: Event) => {
|
|
|
|
const cursor = (e.target as any).result;
|
|
|
|
if (cursor) {
|
2023-08-30 16:08:51 +02:00
|
|
|
const rec: DbDumpRecord = {
|
2023-08-30 15:54:44 +02:00
|
|
|
value: structuredEncapsulate(cursor.value),
|
2023-08-30 16:08:51 +02:00
|
|
|
};
|
|
|
|
// Only store key if necessary, i.e. when
|
|
|
|
// the key is not stored as part of the object via
|
|
|
|
// a key path.
|
|
|
|
if (store.keyPath == null) {
|
|
|
|
rec.key = structuredEncapsulate(cursor.key);
|
|
|
|
}
|
2023-09-01 10:52:15 +02:00
|
|
|
storeDump.records.push(rec);
|
2023-08-30 15:54:44 +02:00
|
|
|
cursor.continue();
|
|
|
|
}
|
|
|
|
});
|
2021-12-01 18:16:40 +01:00
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
2022-01-13 05:30:26 +01:00
|
|
|
|
2023-08-30 16:51:51 +02:00
|
|
|
export async function exportDb(idb: IDBFactory): Promise<DbDump> {
|
|
|
|
const dbDump: DbDump = {
|
|
|
|
databases: {},
|
|
|
|
};
|
|
|
|
|
|
|
|
dbDump.databases[TALER_WALLET_META_DB_NAME] = await exportSingleDb(
|
|
|
|
idb,
|
|
|
|
TALER_WALLET_META_DB_NAME,
|
|
|
|
);
|
|
|
|
dbDump.databases[TALER_WALLET_MAIN_DB_NAME] = await exportSingleDb(
|
|
|
|
idb,
|
|
|
|
TALER_WALLET_MAIN_DB_NAME,
|
|
|
|
);
|
|
|
|
|
|
|
|
return dbDump;
|
|
|
|
}
|
|
|
|
|
2022-09-14 21:27:03 +02:00
|
|
|
async function recoverFromDump(
|
|
|
|
db: IDBDatabase,
|
2023-08-30 17:18:18 +02:00
|
|
|
dbDump: DbDumpDatabase,
|
2022-09-14 21:27:03 +02:00
|
|
|
): Promise<void> {
|
2023-09-01 10:52:15 +02:00
|
|
|
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");
|
2022-01-13 05:30:26 +01:00
|
|
|
}
|
2023-09-01 10:52:15 +02:00
|
|
|
}
|
|
|
|
tx.commit();
|
|
|
|
return await txProm;
|
2022-09-13 18:39:25 +02:00
|
|
|
}
|
|
|
|
|
2023-08-30 17:18:18 +02:00
|
|
|
function checkDbDump(x: any): x is DbDump {
|
|
|
|
return "databases" in x;
|
|
|
|
}
|
2022-09-13 18:39:25 +02:00
|
|
|
|
2023-08-30 17:18:18 +02:00
|
|
|
export async function importDb(db: IDBDatabase, dumpJson: any): Promise<void> {
|
|
|
|
const d = dumpJson;
|
|
|
|
if (checkDbDump(d)) {
|
|
|
|
const walletDb = d.databases[TALER_WALLET_MAIN_DB_NAME];
|
|
|
|
if (!walletDb) {
|
|
|
|
throw Error(
|
|
|
|
`unable to import, main wallet database (${TALER_WALLET_MAIN_DB_NAME}) not found`,
|
|
|
|
);
|
2022-09-13 18:39:25 +02:00
|
|
|
}
|
2023-08-30 17:18:18 +02:00
|
|
|
await recoverFromDump(db, walletDb);
|
|
|
|
} else {
|
|
|
|
throw Error("unable to import, doesn't look like a valid DB dump");
|
2022-09-13 18:39:25 +02:00
|
|
|
}
|
2022-01-13 05:30:26 +01:00
|
|
|
}
|
2023-01-11 14:19:24 +01:00
|
|
|
|
|
|
|
export interface FixupDescription {
|
|
|
|
name: string;
|
|
|
|
fn(tx: GetReadWriteAccess<typeof WalletStoresV1>): Promise<void>;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Manual migrations between minor versions of the DB schema.
|
|
|
|
*/
|
2023-09-07 20:35:46 +02:00
|
|
|
export const walletDbFixups: FixupDescription[] = [];
|
2023-01-11 14:19:24 +01:00
|
|
|
|
|
|
|
const logger = new Logger("db.ts");
|
|
|
|
|
|
|
|
export async function applyFixups(
|
|
|
|
db: DbAccess<typeof WalletStoresV1>,
|
|
|
|
): Promise<void> {
|
2023-02-23 15:52:32 +01:00
|
|
|
logger.trace("applying fixups");
|
2023-01-11 14:19:24 +01:00
|
|
|
await db.mktxAll().runReadWrite(async (tx) => {
|
|
|
|
for (const fixupInstruction of walletDbFixups) {
|
2023-02-23 15:52:32 +01:00
|
|
|
logger.trace(`checking fixup ${fixupInstruction.name}`);
|
2023-01-11 14:19:24 +01:00
|
|
|
const fixupRecord = await tx.fixups.get(fixupInstruction.name);
|
|
|
|
if (fixupRecord) {
|
2023-02-23 15:52:32 +01:00
|
|
|
continue;
|
2023-01-11 14:19:24 +01:00
|
|
|
}
|
|
|
|
logger.info(`applying DB fixup ${fixupInstruction.name}`);
|
|
|
|
await fixupInstruction.fn(tx);
|
2023-01-11 14:20:23 +01:00
|
|
|
await tx.fixups.put({
|
|
|
|
fixupName: fixupInstruction.name,
|
|
|
|
});
|
2023-01-11 14:19:24 +01:00
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2023-01-23 13:56:22 +01:00
|
|
|
/**
|
|
|
|
* Upgrade an IndexedDB in an upgrade transaction.
|
|
|
|
*
|
|
|
|
* The upgrade is made based on a store map, i.e. the metadata
|
|
|
|
* structure that describes all the object stores and indexes.
|
|
|
|
*/
|
2023-01-11 14:19:24 +01:00
|
|
|
function upgradeFromStoreMap(
|
2023-01-23 13:56:22 +01:00
|
|
|
storeMap: any, // FIXME: nail down type
|
2023-01-11 14:19:24 +01:00
|
|
|
db: IDBDatabase,
|
|
|
|
oldVersion: number,
|
|
|
|
newVersion: number,
|
|
|
|
upgradeTransaction: IDBTransaction,
|
|
|
|
): void {
|
|
|
|
if (oldVersion === 0) {
|
|
|
|
for (const n in storeMap) {
|
|
|
|
const swi: StoreWithIndexes<
|
|
|
|
any,
|
|
|
|
StoreDescriptor<unknown>,
|
|
|
|
any
|
|
|
|
> = storeMap[n];
|
|
|
|
const storeDesc: StoreDescriptor<unknown> = swi.store;
|
|
|
|
const s = db.createObjectStore(swi.storeName, {
|
|
|
|
autoIncrement: storeDesc.autoIncrement,
|
|
|
|
keyPath: storeDesc.keyPath,
|
|
|
|
});
|
|
|
|
for (const indexName in swi.indexMap as any) {
|
|
|
|
const indexDesc: IndexDescriptor = swi.indexMap[indexName];
|
|
|
|
s.createIndex(indexDesc.name, indexDesc.keyPath, {
|
|
|
|
multiEntry: indexDesc.multiEntry,
|
|
|
|
unique: indexDesc.unique,
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (oldVersion === newVersion) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
logger.info(`upgrading database from ${oldVersion} to ${newVersion}`);
|
|
|
|
for (const n in storeMap) {
|
|
|
|
const swi: StoreWithIndexes<any, StoreDescriptor<unknown>, any> = storeMap[
|
|
|
|
n
|
|
|
|
];
|
|
|
|
const storeDesc: StoreDescriptor<unknown> = swi.store;
|
|
|
|
const storeAddedVersion = storeDesc.versionAdded ?? 0;
|
2023-01-12 19:50:36 +01:00
|
|
|
let s: IDBObjectStore;
|
2023-02-20 15:07:30 +01:00
|
|
|
if (storeAddedVersion > oldVersion) {
|
|
|
|
// Be tolerant if object store already exists.
|
|
|
|
// Probably means somebody deployed without
|
|
|
|
// adding the "addedInVersion" attribute.
|
|
|
|
if (!upgradeTransaction.objectStoreNames.contains(swi.storeName)) {
|
|
|
|
try {
|
|
|
|
s = db.createObjectStore(swi.storeName, {
|
|
|
|
autoIncrement: storeDesc.autoIncrement,
|
|
|
|
keyPath: storeDesc.keyPath,
|
|
|
|
});
|
|
|
|
} catch (e) {
|
|
|
|
const moreInfo = e instanceof Error ? ` Reason: ${e.message}` : "";
|
|
|
|
throw Error(
|
|
|
|
`Migration failed. Could not create store ${swi.storeName}.${moreInfo}`,
|
|
|
|
);
|
|
|
|
}
|
2023-01-23 13:56:22 +01:00
|
|
|
}
|
2023-01-12 19:50:36 +01:00
|
|
|
}
|
2023-02-20 15:07:30 +01:00
|
|
|
|
|
|
|
s = upgradeTransaction.objectStore(swi.storeName);
|
|
|
|
|
2023-01-11 14:19:24 +01:00
|
|
|
for (const indexName in swi.indexMap as any) {
|
|
|
|
const indexDesc: IndexDescriptor = swi.indexMap[indexName];
|
|
|
|
const indexAddedVersion = indexDesc.versionAdded ?? 0;
|
|
|
|
if (indexAddedVersion <= oldVersion) {
|
|
|
|
continue;
|
|
|
|
}
|
2023-01-23 13:56:22 +01:00
|
|
|
// Be tolerant if index already exists.
|
|
|
|
// Probably means somebody deployed without
|
|
|
|
// adding the "addedInVersion" attribute.
|
|
|
|
if (!s.indexNames.contains(indexDesc.name)) {
|
|
|
|
try {
|
|
|
|
s.createIndex(indexDesc.name, indexDesc.keyPath, {
|
|
|
|
multiEntry: indexDesc.multiEntry,
|
|
|
|
unique: indexDesc.unique,
|
|
|
|
});
|
|
|
|
} catch (e) {
|
|
|
|
const moreInfo = e instanceof Error ? ` Reason: ${e.message}` : "";
|
|
|
|
throw Error(
|
2023-01-23 13:56:50 +01:00
|
|
|
`Migration failed. Could not create index ${indexDesc.name}/${indexDesc.keyPath}. ${moreInfo}`,
|
2023-01-23 13:56:22 +01:00
|
|
|
);
|
|
|
|
}
|
2023-01-12 19:50:36 +01:00
|
|
|
}
|
2023-01-11 14:19:24 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
function promiseFromTransaction(transaction: IDBTransaction): Promise<void> {
|
|
|
|
return new Promise<void>((resolve, reject) => {
|
|
|
|
transaction.oncomplete = () => {
|
|
|
|
resolve();
|
|
|
|
};
|
|
|
|
transaction.onerror = () => {
|
|
|
|
reject();
|
|
|
|
};
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2023-09-01 10:52:15 +02:00
|
|
|
export function promiseFromRequest(request: IDBRequest): Promise<any> {
|
|
|
|
return new Promise((resolve, reject) => {
|
|
|
|
request.onsuccess = () => {
|
|
|
|
resolve(request.result);
|
|
|
|
};
|
|
|
|
request.onerror = () => {
|
|
|
|
reject(request.error);
|
|
|
|
};
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2023-01-11 14:19:24 +01:00
|
|
|
/**
|
|
|
|
* Purge all data in the given database.
|
|
|
|
*/
|
|
|
|
export function clearDatabase(db: IDBDatabase): Promise<void> {
|
|
|
|
// db.objectStoreNames is a DOMStringList, so we need to convert
|
|
|
|
let stores: string[] = [];
|
|
|
|
for (let i = 0; i < db.objectStoreNames.length; i++) {
|
|
|
|
stores.push(db.objectStoreNames[i]);
|
|
|
|
}
|
|
|
|
const tx = db.transaction(stores, "readwrite");
|
|
|
|
for (const store of stores) {
|
|
|
|
tx.objectStore(store).clear();
|
|
|
|
}
|
|
|
|
return promiseFromTransaction(tx);
|
|
|
|
}
|
|
|
|
|
|
|
|
function onTalerDbUpgradeNeeded(
|
|
|
|
db: IDBDatabase,
|
|
|
|
oldVersion: number,
|
|
|
|
newVersion: number,
|
|
|
|
upgradeTransaction: IDBTransaction,
|
|
|
|
) {
|
|
|
|
upgradeFromStoreMap(
|
|
|
|
WalletStoresV1,
|
|
|
|
db,
|
|
|
|
oldVersion,
|
|
|
|
newVersion,
|
|
|
|
upgradeTransaction,
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
function onMetaDbUpgradeNeeded(
|
|
|
|
db: IDBDatabase,
|
|
|
|
oldVersion: number,
|
|
|
|
newVersion: number,
|
|
|
|
upgradeTransaction: IDBTransaction,
|
|
|
|
) {
|
|
|
|
upgradeFromStoreMap(
|
|
|
|
walletMetadataStore,
|
|
|
|
db,
|
|
|
|
oldVersion,
|
|
|
|
newVersion,
|
|
|
|
upgradeTransaction,
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2023-08-30 18:01:18 +02:00
|
|
|
function onStoredBackupsDbUpgradeNeeded(
|
|
|
|
db: IDBDatabase,
|
|
|
|
oldVersion: number,
|
|
|
|
newVersion: number,
|
|
|
|
upgradeTransaction: IDBTransaction,
|
|
|
|
) {
|
|
|
|
upgradeFromStoreMap(
|
|
|
|
StoredBackupStores,
|
|
|
|
db,
|
|
|
|
oldVersion,
|
|
|
|
newVersion,
|
|
|
|
upgradeTransaction,
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
export async function openStoredBackupsDatabase(
|
|
|
|
idbFactory: IDBFactory,
|
|
|
|
): Promise<DbAccess<typeof StoredBackupStores>> {
|
|
|
|
const backupsDbHandle = await openDatabase(
|
|
|
|
idbFactory,
|
2023-08-30 18:33:56 +02:00
|
|
|
TALER_WALLET_STORED_BACKUPS_DB_NAME,
|
2023-08-30 18:01:18 +02:00
|
|
|
1,
|
|
|
|
() => {},
|
|
|
|
onStoredBackupsDbUpgradeNeeded,
|
|
|
|
);
|
|
|
|
|
|
|
|
const handle = new DbAccess(backupsDbHandle, StoredBackupStores);
|
|
|
|
return handle;
|
|
|
|
}
|
|
|
|
|
2023-01-11 14:19:24 +01:00
|
|
|
/**
|
|
|
|
* Return a promise that resolves
|
|
|
|
* to the taler wallet db.
|
2023-02-15 23:32:42 +01:00
|
|
|
*
|
|
|
|
* @param onVersionChange Called when another client concurrenctly connects to the database
|
|
|
|
* with a higher version.
|
2023-01-11 14:19:24 +01:00
|
|
|
*/
|
|
|
|
export async function openTalerDatabase(
|
|
|
|
idbFactory: IDBFactory,
|
|
|
|
onVersionChange: () => void,
|
|
|
|
): Promise<DbAccess<typeof WalletStoresV1>> {
|
|
|
|
const metaDbHandle = await openDatabase(
|
|
|
|
idbFactory,
|
2023-08-30 16:51:51 +02:00
|
|
|
TALER_WALLET_META_DB_NAME,
|
2023-01-11 14:19:24 +01:00
|
|
|
1,
|
|
|
|
() => {},
|
|
|
|
onMetaDbUpgradeNeeded,
|
|
|
|
);
|
|
|
|
|
|
|
|
const metaDb = new DbAccess(metaDbHandle, walletMetadataStore);
|
|
|
|
let currentMainVersion: string | undefined;
|
|
|
|
await metaDb
|
|
|
|
.mktx((stores) => [stores.metaConfig])
|
|
|
|
.runReadWrite(async (tx) => {
|
|
|
|
const dbVersionRecord = await tx.metaConfig.get(CURRENT_DB_CONFIG_KEY);
|
|
|
|
if (!dbVersionRecord) {
|
2023-08-30 16:51:51 +02:00
|
|
|
currentMainVersion = TALER_WALLET_MAIN_DB_NAME;
|
2023-01-11 14:19:24 +01:00
|
|
|
await tx.metaConfig.put({
|
|
|
|
key: CURRENT_DB_CONFIG_KEY,
|
2023-08-30 16:51:51 +02:00
|
|
|
value: TALER_WALLET_MAIN_DB_NAME,
|
2023-01-11 14:19:24 +01:00
|
|
|
});
|
|
|
|
} else {
|
|
|
|
currentMainVersion = dbVersionRecord.value;
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
2023-08-30 16:51:51 +02:00
|
|
|
if (currentMainVersion !== TALER_WALLET_MAIN_DB_NAME) {
|
2023-01-11 14:19:24 +01:00
|
|
|
switch (currentMainVersion) {
|
|
|
|
case "taler-wallet-main-v2":
|
|
|
|
case "taler-wallet-main-v3":
|
|
|
|
case "taler-wallet-main-v4": // temporary, we might migrate v4 later
|
|
|
|
case "taler-wallet-main-v5":
|
|
|
|
case "taler-wallet-main-v6":
|
|
|
|
case "taler-wallet-main-v7":
|
|
|
|
case "taler-wallet-main-v8":
|
|
|
|
// We consider this a pre-release
|
|
|
|
// development version, no migration is done.
|
|
|
|
await metaDb
|
|
|
|
.mktx((stores) => [stores.metaConfig])
|
|
|
|
.runReadWrite(async (tx) => {
|
|
|
|
await tx.metaConfig.put({
|
|
|
|
key: CURRENT_DB_CONFIG_KEY,
|
2023-08-30 16:51:51 +02:00
|
|
|
value: TALER_WALLET_MAIN_DB_NAME,
|
2023-01-11 14:19:24 +01:00
|
|
|
});
|
|
|
|
});
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
throw Error(
|
|
|
|
`major migration from database major=${currentMainVersion} not supported`,
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
const mainDbHandle = await openDatabase(
|
|
|
|
idbFactory,
|
2023-08-30 16:51:51 +02:00
|
|
|
TALER_WALLET_MAIN_DB_NAME,
|
2023-01-11 14:19:24 +01:00
|
|
|
WALLET_DB_MINOR_VERSION,
|
|
|
|
onVersionChange,
|
|
|
|
onTalerDbUpgradeNeeded,
|
|
|
|
);
|
|
|
|
|
|
|
|
const handle = new DbAccess(mainDbHandle, WalletStoresV1);
|
|
|
|
|
|
|
|
await applyFixups(handle);
|
|
|
|
|
|
|
|
return handle;
|
|
|
|
}
|
|
|
|
|
|
|
|
export async function deleteTalerDatabase(
|
|
|
|
idbFactory: IDBFactory,
|
|
|
|
): Promise<void> {
|
|
|
|
return new Promise((resolve, reject) => {
|
2023-08-30 16:51:51 +02:00
|
|
|
const req = idbFactory.deleteDatabase(TALER_WALLET_MAIN_DB_NAME);
|
2023-01-11 14:19:24 +01:00
|
|
|
req.onerror = () => reject(req.error);
|
|
|
|
req.onsuccess = () => resolve();
|
|
|
|
});
|
|
|
|
}
|