aboutsummaryrefslogtreecommitdiff
path: root/packages
diff options
context:
space:
mode:
authorFlorian Dold <florian@dold.me>2020-12-07 20:24:16 +0100
committerFlorian Dold <florian@dold.me>2020-12-07 20:24:16 +0100
commitbd88f3f44304f0389322b99ff62572f3f1d7c5c1 (patch)
tree6bf09d809afa44dce6ebcd6f00d20a2d913e2f6b /packages
parentbbd65fc4b78bf4b61142417fda44d43d955cb28d (diff)
backup schema WIP
Diffstat (limited to 'packages')
-rw-r--r--packages/taler-wallet-core/src/operations/backup.ts76
-rw-r--r--packages/taler-wallet-core/src/operations/exchanges.ts3
-rw-r--r--packages/taler-wallet-core/src/operations/withdraw.ts4
-rw-r--r--packages/taler-wallet-core/src/types/backupTypes.ts780
-rw-r--r--packages/taler-wallet-core/src/types/dbTypes.ts12
5 files changed, 790 insertions, 85 deletions
diff --git a/packages/taler-wallet-core/src/operations/backup.ts b/packages/taler-wallet-core/src/operations/backup.ts
index dbcb33374..948a4e7a3 100644
--- a/packages/taler-wallet-core/src/operations/backup.ts
+++ b/packages/taler-wallet-core/src/operations/backup.ts
@@ -29,7 +29,9 @@ import {
BackupCoin,
BackupCoinSource,
BackupCoinSourceType,
+ BackupDenomination,
BackupExchangeData,
+ BackupExchangeWireFee,
WalletBackupContentV1,
} from "../types/backupTypes";
import { TransactionHandle } from "../util/query";
@@ -128,21 +130,88 @@ export async function exportBackup(
): Promise<WalletBackupContentV1> {
await provideBackupState(ws);
return ws.db.runWithWriteTransaction(
- [Stores.config, Stores.exchanges, Stores.coins],
+ [Stores.config, Stores.exchanges, Stores.coins, Stores.denominations],
async (tx) => {
const bs = await getWalletBackupState(ws, tx);
const exchanges: BackupExchangeData[] = [];
const coins: BackupCoin[] = [];
+ const denominations: BackupDenomination[] = [];
await tx.iter(Stores.exchanges).forEach((ex) => {
+ // Only back up permanently added exchanges.
+
if (!ex.details) {
return;
}
+ if (!ex.wireInfo) {
+ return;
+ }
+ if (!ex.addComplete) {
+ return;
+ }
+ if (!ex.permanent) {
+ return;
+ }
+ const wi = ex.wireInfo;
+ const wireFees: BackupExchangeWireFee[] = [];
+
+ Object.keys(wi.feesForType).forEach((x) => {
+ for (const f of wi.feesForType[x]) {
+ wireFees.push({
+ wireType: x,
+ closingFee: Amounts.stringify(f.closingFee),
+ endStamp: f.endStamp,
+ sig: f.sig,
+ startStamp: f.startStamp,
+ wireFee: Amounts.stringify(f.wireFee),
+ });
+ }
+ });
+
exchanges.push({
- exchangeBaseUrl: ex.baseUrl,
- exchangeMasterPub: ex.details?.masterPublicKey,
+ baseUrl: ex.baseUrl,
+ accounts: ex.wireInfo.accounts.map((x) => ({
+ paytoUri: x.payto_uri,
+ })),
+ auditors: ex.details.auditors.map((x) => ({
+ auditorPub: x.auditor_pub,
+ auditorUrl: x.auditor_url,
+ denominationKeys: x.denomination_keys,
+ })),
+ masterPublicKey: ex.details.masterPublicKey,
+ currency: ex.details.currency,
+ protocolVersion: ex.details.protocolVersion,
+ wireFees,
+ signingKeys: ex.details.signingKeys.map((x) => ({
+ key: x.key,
+ masterSig: x.master_sig,
+ stampEnd: x.stamp_end,
+ stampExpire: x.stamp_expire,
+ stampStart: x.stamp_start,
+ })),
termsOfServiceAcceptedEtag: ex.termsOfServiceAcceptedEtag,
+ termsOfServiceLastEtag: ex.termsOfServiceLastEtag,
+ });
+ });
+
+ await tx.iter(Stores.denominations).forEach((denom) => {
+ denominations.push({
+ denomPub: denom.denomPub,
+ denomPubHash: denom.denomPubHash,
+ exchangeBaseUrl: canonicalizeBaseUrl(denom.exchangeBaseUrl),
+ feeDeposit: Amounts.stringify(denom.feeDeposit),
+ feeRefresh: Amounts.stringify(denom.feeRefresh),
+ feeRefund: Amounts.stringify(denom.feeRefund),
+ feeWithdraw: Amounts.stringify(denom.feeWithdraw),
+ isOffered: denom.isOffered,
+ isRevoked: denom.isRevoked,
+ masterSig: denom.masterSig,
+ stampExpireDeposit: denom.stampExpireDeposit,
+ stampExpireLegal: denom.stampExpireLegal,
+ stampExpireWithdraw: denom.stampExpireWithdraw,
+ stampStart: denom.stampStart,
+ value: Amounts.stringify(denom.value),
});
});
@@ -192,6 +261,7 @@ export async function exportBackup(
planchets: [],
refreshSessions: [],
reserves: [],
+ denominations: [],
walletRootPub: bs.walletRootPub,
};
diff --git a/packages/taler-wallet-core/src/operations/exchanges.ts b/packages/taler-wallet-core/src/operations/exchanges.ts
index d598e3987..b82700365 100644
--- a/packages/taler-wallet-core/src/operations/exchanges.ts
+++ b/packages/taler-wallet-core/src/operations/exchanges.ts
@@ -359,7 +359,6 @@ export async function acceptExchangeTermsOfService(
return;
}
r.termsOfServiceAcceptedEtag = etag;
- r.termsOfServiceAcceptedTimestamp = getTimestampNow();
await tx.put(Stores.exchanges, r);
});
}
@@ -490,9 +489,7 @@ async function updateExchangeFromUrlImpl(
updateStatus: ExchangeUpdateStatus.FetchKeys,
updateStarted: now,
updateReason: ExchangeUpdateReason.Initial,
- timestampAdded: getTimestampNow(),
termsOfServiceAcceptedEtag: undefined,
- termsOfServiceAcceptedTimestamp: undefined,
termsOfServiceLastEtag: undefined,
termsOfServiceText: undefined,
retryInfo: initRetryInfo(false),
diff --git a/packages/taler-wallet-core/src/operations/withdraw.ts b/packages/taler-wallet-core/src/operations/withdraw.ts
index b5670a82d..d09903cbb 100644
--- a/packages/taler-wallet-core/src/operations/withdraw.ts
+++ b/packages/taler-wallet-core/src/operations/withdraw.ts
@@ -793,9 +793,9 @@ export async function getExchangeWithdrawalInfo(
let tosAccepted = false;
- if (exchangeInfo.termsOfServiceAcceptedTimestamp) {
+ if (exchangeInfo.termsOfServiceLastEtag) {
if (
- exchangeInfo.termsOfServiceAcceptedEtag ==
+ exchangeInfo.termsOfServiceAcceptedEtag ===
exchangeInfo.termsOfServiceLastEtag
) {
tosAccepted = true;
diff --git a/packages/taler-wallet-core/src/types/backupTypes.ts b/packages/taler-wallet-core/src/types/backupTypes.ts
index 72d0486b1..cfbfdc49b 100644
--- a/packages/taler-wallet-core/src/types/backupTypes.ts
+++ b/packages/taler-wallet-core/src/types/backupTypes.ts
@@ -14,6 +14,7 @@
GNU Taler; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
*/
+import { Timestamp } from "../util/time";
/**
* Type declarations for backup.
@@ -21,6 +22,23 @@
* Contains some redundancy with the other type declarations,
* as the backup schema must be very stable.
*
+ * Current limitations:
+ * 1. Contracts that are claimed but not accepted aren't
+ * exported yet.
+ * 2. There is no garbage collection mechanism for the export yet.
+ * (But this should actually become the main GC mechanism!)
+ * 3. Reserve history isn't backed up yet.
+ * 4. Recoup metadata isn't exported yet.
+ *
+ * General considerations / decisions:
+ * 1. Information about previously occurring errors and
+ * retries is never backed up.
+ * 2. The ToS text of an exchange is never backed up.
+ * 3. Public keys are always exported in the backup
+ * and never recomputed (this allows the import to
+ * complete within a DB transaction that can't access
+ * the crypto worker).
+ *
* @author Florian Dold <dold@taler.net>
*/
@@ -51,19 +69,566 @@ export interface WalletBackupContentV1 {
*/
exchanges: BackupExchangeData[];
- reserves: ReserveBackupData[];
+ denominations: BackupDenomination[];
+
+ reserves: BackupReserveData[];
+
+ withdrawalGroups: BackupWithdrawalGroup[];
+
+ refreshGroups: BackupRefreshGroup[];
coins: BackupCoin[];
- planchets: BackupWithdrawalPlanchet[];
+ purchases: BackupPurchase[];
+}
+
+export enum BackupCoinSourceType {
+ Withdraw = "withdraw",
+ Refresh = "refresh",
+ Tip = "tip",
+}
+
+export interface BackupWithdrawCoinSource {
+ type: BackupCoinSourceType.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 BackupRefreshCoinSource {
+ type: BackupCoinSourceType.Refresh;
+ oldCoinPub: string;
+}
+
+export interface BackupTipCoinSource {
+ type: BackupCoinSourceType.Tip;
+ walletTipId: string;
+ coinIndex: number;
+}
+
+export type BackupCoinSource =
+ | BackupWithdrawCoinSource
+ | BackupRefreshCoinSource
+ | BackupTipCoinSource;
+
+export interface BackupCoin {
+ /**
+ * Where did the coin come from? Used for recouping coins.
+ */
+ coinSource: BackupCoinSource;
+
+ /**
+ * Public key of the coin.
+ */
+ coinPub: string;
+
+ /**
+ * Private key to authorize operations on the coin.
+ */
+ coinPriv: string;
+
+ /**
+ * Key used by the exchange used to sign the coin.
+ */
+ denomPub: string;
+
+ /**
+ * Hash of the public key that signs the coin.
+ */
+ denomPubHash: string;
+
+ /**
+ * Unblinded signature by the exchange.
+ */
+ denomSig: string;
+
+ /**
+ * Amount that's left on the coin.
+ */
+ currentAmount: BackupAmountString;
+
+ /**
+ * 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;
+
+ fresh: boolean;
+}
+
+/**
+ * Status of a tip we got from a merchant.
+ */
+export interface BackupTip {
+ /**
+ * Tip ID chosen by the wallet.
+ */
+ walletTipId: string;
+
+ /**
+ * The merchant's identifier for this tip.
+ */
+ merchantTipId: string;
+
+ /**
+ * Has the user accepted the tip? Only after the tip has been accepted coins
+ * withdrawn from the tip may be used.
+ */
+ acceptedTimestamp: Timestamp | undefined;
+
+ createdTimestamp: Timestamp;
+
+ /**
+ * Timestamp for when the wallet finished picking up the tip
+ * from the merchant.
+ */
+ pickedUpTimestamp: Timestamp | undefined;
+
+ /**
+ * The tipped amount.
+ */
+ tipAmountRaw: BackupAmountString;
+
+ tipAmountEffective: BackupAmountString;
+
+ /**
+ * Timestamp, the tip can't be picked up anymore after this deadline.
+ */
+ tipExpiration: Timestamp;
+
+ /**
+ * 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;
+
+ /**
+ * Planchets, the members included in TipPlanchetDetail will be sent to the
+ * merchant.
+ */
+ planchets?: {
+ blindingKey: string;
+ coinEv: string;
+ coinPriv: string;
+ coinPub: string;
+ }[];
+
+ totalCoinValue: BackupAmountString;
+ totalWithdrawCost: BackupAmountString;
+
+ selectedDenoms: {
+ denomPubHash: string;
+ count: number;
+ }[];
+}
+
+/**
+ * Reasons for why a coin is being refreshed.
+ */
+export enum BackupRefreshReason {
+ Manual = "manual",
+ Pay = "pay",
+ Refund = "refund",
+ AbortPay = "abort-pay",
+ Recoup = "recoup",
+ BackupRestored = "backup-restored",
+ Scheduled = "scheduled",
+}
+
+/**
+ * Planchet for a coin during refrehs.
+ */
+export interface BackupRefreshPlanchet {
+ /**
+ * Public key for the coin.
+ */
+ publicKey: string;
+ /**
+ * Private key for the coin.
+ */
+ privateKey: string;
+ /**
+ * Blinded public key.
+ */
+ coinEv: string;
+ /**
+ * Blinding key used.
+ */
+ blindingKey: string;
+}
+
+export interface BackupRefreshSessionRecord {
+ /**
+ * Public key that's being melted in this session.
+ */
+ meltCoinPub: string;
+
+ /**
+ * How much of the coin's value is melted away
+ * with this refresh session?
+ */
+ amountRefreshInput: BackupAmountString;
+
+ /**
+ * Sum of the value of denominations we want
+ * to withdraw in this session, without fees.
+ */
+ amountRefreshOutput: BackupAmountString;
+
+ /**
+ * Signature to confirm the melting.
+ */
+ confirmSig: string;
+
+ /**
+ * Hased denominations of the newly requested coins.
+ */
+ newDenomHashes: string[];
+
+ /**
+ * Denominations of the newly requested coins.
+ */
+ newDenoms: string[];
+
+ /**
+ * Planchets for each cut-and-choose instance.
+ */
+ planchetsForGammas: BackupRefreshPlanchet[][];
+
+ /**
+ * The transfer keys, kappa of them.
+ */
+ transferPubs: string[];
+
+ /**
+ * Private keys for the transfer public keys.
+ */
+ transferPrivs: string[];
+
+ /**
+ * The no-reveal-index after we've done the melting.
+ */
+ norevealIndex?: number;
+
+ /**
+ * Hash of the session.
+ */
+ hash: string;
+
+ /**
+ * Timestamp when the refresh session finished.
+ */
+ finishedTimestamp: Timestamp | undefined;
+
+ /**
+ * When has this refresh session been created?
+ */
+ timestampCreated: Timestamp;
+
+ /**
+ * Base URL for the exchange we're doing the refresh with.
+ */
+ exchangeBaseUrl: string;
+}
+
+export interface BackupRefreshGroup {
+ refreshGroupId: string;
+
+ reason: BackupRefreshReason;
+
+ oldCoinPubs: string[];
+
+ refreshSessionPerCoin: (BackupRefreshSessionRecord | undefined)[];
+
+ inputPerCoin: BackupAmountString[];
+
+ estimatedOutputPerCoin: BackupAmountString[];
+
+ /**
+ * Timestamp when the refresh session finished.
+ */
+ timestampFinished: Timestamp | undefined;
+}
+
+export interface BackupWithdrawalGroup {
+ withdrawalGroupId: string;
+
+ reservePub: string;
+
+ /**
+ * When was the withdrawal operation started started?
+ * Timestamp in milliseconds.
+ */
+ timestampStart: Timestamp;
+
+ /**
+ * When was the withdrawal operation completed?
+ */
+ timestampFinish?: Timestamp;
+
+ /**
+ * Amount including fees (i.e. the amount subtracted from the
+ * reserve to withdraw all coins in this withdrawal session).
+ */
+ rawWithdrawalAmount: BackupAmountString;
+
+ totalCoinValue: BackupAmountString;
+ totalWithdrawCost: BackupAmountString;
+
+ selectedDenoms: {
+ denomPubHash: string;
+ count: number;
+ }[];
- refreshSessions: BackupRefreshSession[];
+ /**
+ * One planchet/coin for each selected denomination.
+ */
+ planchets: {
+ blindingKey: string;
+ coinPriv: string;
+ coinPub: string;
+ }[];
+}
+
+export enum BackupRefundState {
+ Failed = "failed",
+ Applied = "applied",
+ Pending = "pending",
}
-export interface BackupRefreshSession {
+export interface BackupRefundItemCommon {
+ // Execution time as claimed by the merchant
+ executionTime: Timestamp;
+
+ /**
+ * Time when the wallet became aware of the refund.
+ */
+ obtainedTime: Timestamp;
+
+ refundAmount: BackupAmountString;
+ refundFee: BackupAmountString;
+ /**
+ * Upper bound on the refresh cost incurred by
+ * applying this refund.
+ *
+ * Might be lower in practice when two refunds on the same
+ * coin are refreshed in the same refresh operation.
+ */
+ totalRefreshCostBound: BackupAmountString;
+}
+
+/**
+ * Failed refund, either because the merchant did
+ * something wrong or it expired.
+ */
+export interface BackupRefundFailedItem extends BackupRefundItemCommon {
+ type: BackupRefundState.Failed;
}
+export interface BackupRefundPendingItem extends BackupRefundItemCommon {
+ type: BackupRefundState.Pending;
+}
+
+export interface BackupRefundAppliedItem extends BackupRefundItemCommon {
+ type: BackupRefundState.Applied;
+}
+
+/**
+ * State of one refund from the merchant, maintained by the wallet.
+ */
+export type BackupRefundItem =
+ | BackupRefundFailedItem
+ | BackupRefundPendingItem
+ | BackupRefundAppliedItem;
+
+export interface BackupPurchase {
+ /**
+ * Proposal ID for this purchase. Uniquely identifies the
+ * purchase and the proposal.
+ */
+ proposalId: string;
+
+ /**
+ * Contract terms we got from the merchant.
+ */
+ contractTermsRaw: string;
+
+ /**
+ * Amount requested by the merchant.
+ */
+ paymentAmount: BackupAmountString;
+
+ /**
+ * Public keys of the coins that were selected.
+ */
+ coinPubs: string[];
+
+ /**
+ * Deposit permission signature of each coin.
+ */
+ coinSigs: string[];
+
+ /**
+ * Amount that each coin contributes.
+ */
+ coinContributions: BackupAmountString[];
+
+ /**
+ * How much of the wire fees is the customer paying?
+ */
+ customerWireFees: BackupAmountString;
+
+ /**
+ * How much of the deposit fees is the customer paying?
+ */
+ customerDepositFees: BackupAmountString;
+
+ totalPayCost: BackupAmountString;
+
+ /**
+ * Timestamp of the first time that sending a payment to the merchant
+ * for this purchase was successful.
+ */
+ timestampFirstSuccessfulPay: Timestamp | undefined;
+
+ merchantPaySig: string | undefined;
+
+ /**
+ * When was the purchase made?
+ * Refers to the time that the user accepted.
+ */
+ timestampAccept: Timestamp;
+
+ /**
+ * Pending refunds for the purchase. A refund is pending
+ * when the merchant reports a transient error from the exchange.
+ */
+ refunds: { [refundKey: string]: BackupRefundItem };
+
+ /**
+ * When was the last refund made?
+ * Set to 0 if no refund was made on the purchase.
+ */
+ timestampLastRefundStatus: Timestamp | undefined;
+
+ abortStatus?: "abort-refund" | "abort-finished";
+
+ /**
+ * Continue querying the refund status until this deadline has expired.
+ */
+ autoRefundDeadline: Timestamp | undefined;
+}
+
+/**
+ * Info about one denomination in the backup.
+ *
+ * Note that the wallet only backs up validated denominations.
+ */
+export interface BackupDenomination {
+ /**
+ * Value of one coin of the denomination.
+ */
+ value: BackupAmountString;
+
+ /**
+ * The denomination public key.
+ */
+ denomPub: string;
+
+ /**
+ * Hash of the denomination public key.
+ * Stored in the database for faster lookups.
+ */
+ denomPubHash: string;
+
+ /**
+ * Fee for withdrawing.
+ */
+ feeWithdraw: BackupAmountString;
+
+ /**
+ * Fee for depositing.
+ */
+ feeDeposit: BackupAmountString;
+
+ /**
+ * Fee for refreshing.
+ */
+ feeRefresh: BackupAmountString;
+
+ /**
+ * Fee for refunding.
+ */
+ feeRefund: BackupAmountString;
+
+ /**
+ * Validity start date of the denomination.
+ */
+ stampStart: Timestamp;
+
+ /**
+ * Date after which the currency can't be withdrawn anymore.
+ */
+ stampExpireWithdraw: Timestamp;
+
+ /**
+ * Date after the denomination officially doesn't exist anymore.
+ */
+ stampExpireLegal: Timestamp;
+
+ /**
+ * Data after which coins of this denomination can't be deposited anymore.
+ */
+ stampExpireDeposit: Timestamp;
+
+ /**
+ * Signature by the exchange's master key over the denomination
+ * information.
+ */
+ masterSig: string;
+
+ /**
+ * 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;
+}
export interface BackupReserve {
reservePub: string;
@@ -82,7 +647,7 @@ export interface BackupReserve {
senderWire?: string;
}
-export interface ReserveBackupData {
+export interface BackupReserveData {
/**
* The reserve public key.
*/
@@ -98,118 +663,199 @@ export interface ReserveBackupData {
*/
exchangeBaseUrl: string;
- instructedAmount: string;
+ /**
+ * Time when the reserve was created.
+ */
+ timestampCreated: Timestamp;
+
+ /**
+ * Time when the information about this reserve was posted to the bank.
+ *
+ * Only applies if bankWithdrawStatusUrl is defined.
+ *
+ * Set to 0 if that hasn't happened yet.
+ */
+ timestampReserveInfoPosted: Timestamp | undefined;
+
+ /**
+ * Time when the reserve was confirmed by the bank.
+ *
+ * Set to undefined if not confirmed yet.
+ */
+ timestampBankConfirmed: Timestamp | undefined;
/**
* Wire information (as payto URI) for the bank account that
* transfered funds for this reserve.
*/
senderWire?: string;
-}
-export interface BackupExchangeData {
- exchangeBaseUrl: string;
- exchangeMasterPub: string;
+ /**
+ * Amount that was sent by the user to fund the reserve.
+ */
+ instructedAmount: BackupAmountString;
/**
- * ETag for last terms of service download.
+ * Extra state for when this is a withdrawal involving
+ * a Taler-integrated bank.
*/
- termsOfServiceAcceptedEtag: string | undefined;
+ bankInfo?: {
+ /**
+ * Status URL that the wallet will use to query the status
+ * of the Taler withdrawal operation on the bank's side.
+ */
+ statusUrl: string;
+
+ confirmUrl?: string;
+
+ /**
+ * Exchange payto URI that the bank will use to fund the reserve.
+ */
+ exchangePaytoUri: string;
+
+ /**
+ * Do we still need to register the reserve with the bank?
+ */
+ registerPending: boolean;
+ };
+
+ initialWithdrawalGroupId: string;
+
+ initialTotalCoinValue: BackupAmountString;
+
+ initialTotalWithdrawCost: BackupAmountString;
+ initialSelectedDenoms: {
+ denomPubHash: string;
+ count: number;
+ }[];
}
+export interface ExchangeBankAccount {
+ paytoUri: string;
+}
-export interface BackupWithdrawalPlanchet {
- coinSource: BackupWithdrawCoinSource | BackupTipCoinSource;
- blindingKey: string;
- coinPriv: string;
- coinPub: string;
- denomPubHash: string;
+/**
+ * Wire fee for one wire method as stored in the
+ * wallet's database.
+ */
+export interface BackupExchangeWireFee {
+ wireType: string;
/**
- * Base URL that identifies the exchange from which we are getting the
- * coin.
+ * Fee for wire transfers.
*/
- exchangeBaseUrl: string;
-}
+ wireFee: string;
+ /**
+ * Fees to close and refund a reserve.
+ */
+ closingFee: string;
-export enum BackupCoinSourceType {
- Withdraw = "withdraw",
- Refresh = "refresh",
- Tip = "tip",
-}
-
-export interface BackupWithdrawCoinSource {
- type: BackupCoinSourceType.Withdraw;
- withdrawalGroupId: string;
+ /**
+ * Start date of the fee.
+ */
+ startStamp: Timestamp;
/**
- * Index of the coin in the withdrawal session.
+ * End date of the fee.
*/
- coinIndex: number;
+ endStamp: Timestamp;
/**
- * Reserve public key for the reserve we got this coin from.
+ * Signature made by the exchange master key.
*/
- reservePub: string;
+ sig: string;
}
-export interface BackupRefreshCoinSource {
- type: BackupCoinSourceType.Refresh;
- oldCoinPub: string;
+/**
+ * Structure of one exchange signing key in the /keys response.
+ */
+export class BackupExchangeSignKey {
+ stampStart: Timestamp;
+ stampExpire: Timestamp;
+ stampEnd: Timestamp;
+ key: string;
+ masterSig: string;
}
-export interface BackupTipCoinSource {
- type: BackupCoinSourceType.Tip;
- walletTipId: string;
- coinIndex: number;
-}
+/**
+ * Signature by the auditor that a particular denomination key is audited.
+ */
+export class AuditorDenomSig {
+ /**
+ * Denomination public key's hash.
+ */
+ denom_pub_h: string;
-export type BackupCoinSource =
- | BackupWithdrawCoinSource
- | BackupRefreshCoinSource
- | BackupTipCoinSource;
+ /**
+ * The signature.
+ */
+ auditor_sig: string;
+}
/**
- * Coin that has been withdrawn and might have been
- * (partially) spent.
+ * Auditor information as given by the exchange in /keys.
*/
-export interface BackupCoin {
+export class BackupExchangeAuditor {
/**
- * Public key of the coin.
+ * Auditor's public key.
*/
- coinPub: string;
+ auditorPub: string;
/**
- * Private key of the coin.
+ * Base URL of the auditor.
*/
- coinPriv: string;
+ auditorUrl: string;
/**
- * Where did the coin come from (withdrawal/refresh/tip)?
- * Used for recouping coins.
+ * List of signatures for denominations by the auditor.
*/
- coinSource: BackupCoinSource;
+ denominationKeys: AuditorDenomSig[];
+}
+
+export interface BackupExchangeData {
+ /**
+ * Base url of the exchange.
+ */
+ baseUrl: string;
/**
- * Is the coin still fresh
+ * Master public key of the exchange.
*/
- fresh: boolean;
+ masterPublicKey: string;
/**
- * Blinding key used when withdrawing the coin.
- * Potentionally used again during payback.
+ * Auditors (partially) auditing the exchange.
*/
- blindingKey: string;
+ auditors: BackupExchangeAuditor[];
/**
- * Amount that's left on the coin.
+ * Currency that the exchange offers.
*/
- currentAmount: BackupAmountString;
+ currency: string;
/**
- * Base URL that identifies the exchange from which we got the
- * coin.
+ * Last observed protocol version.
*/
- exchangeBaseUrl: string;
+ protocolVersion: string;
+
+ /**
+ * Signing keys we got from the exchange, can also contain
+ * older signing keys that are not returned by /keys anymore.
+ */
+ signingKeys: BackupExchangeSignKey[];
+
+ wireFees: BackupExchangeWireFee[];
+
+ accounts: ExchangeBankAccount[];
+
+ /**
+ * ETag for last terms of service download.
+ */
+ termsOfServiceLastEtag: string | undefined;
+
+ /**
+ * ETag for last terms of service download.
+ */
+ termsOfServiceAcceptedEtag: string | undefined;
}
diff --git a/packages/taler-wallet-core/src/types/dbTypes.ts b/packages/taler-wallet-core/src/types/dbTypes.ts
index 26400dd3a..dc1ee1046 100644
--- a/packages/taler-wallet-core/src/types/dbTypes.ts
+++ b/packages/taler-wallet-core/src/types/dbTypes.ts
@@ -555,12 +555,9 @@ export interface ExchangeRecord {
wireInfo: ExchangeWireInfo | undefined;
/**
- * When was the exchange added to the wallet?
- */
- timestampAdded: Timestamp;
-
- /**
* Terms of service text or undefined if not downloaded yet.
+ *
+ * This is just used as a cache of the last downloaded ToS.
*/
termsOfServiceText: string | undefined;
@@ -575,11 +572,6 @@ export interface ExchangeRecord {
termsOfServiceAcceptedEtag: string | undefined;
/**
- * ETag for last terms of service download.
- */
- termsOfServiceAcceptedTimestamp: Timestamp | undefined;
-
- /**
* Time when the update to the exchange has been started or
* undefined if no update is in progress.
*/