aboutsummaryrefslogtreecommitdiff
path: root/packages/taler-wallet-core/src/operations/backup
diff options
context:
space:
mode:
Diffstat (limited to 'packages/taler-wallet-core/src/operations/backup')
-rw-r--r--packages/taler-wallet-core/src/operations/backup/export.ts93
-rw-r--r--packages/taler-wallet-core/src/operations/backup/import.ts89
-rw-r--r--packages/taler-wallet-core/src/operations/backup/index.ts10
3 files changed, 167 insertions, 25 deletions
diff --git a/packages/taler-wallet-core/src/operations/backup/export.ts b/packages/taler-wallet-core/src/operations/backup/export.ts
index 35d5e6ef7..b39e6dc27 100644
--- a/packages/taler-wallet-core/src/operations/backup/export.ts
+++ b/packages/taler-wallet-core/src/operations/backup/export.ts
@@ -25,6 +25,7 @@
* Imports.
*/
import {
+ AbsoluteTime,
Amounts,
BackupBackupProvider,
BackupBackupProviderTerms,
@@ -35,6 +36,7 @@ import {
BackupExchange,
BackupExchangeDetails,
BackupExchangeWireFee,
+ BackupOperationStatus,
BackupProposal,
BackupProposalStatus,
BackupPurchase,
@@ -44,30 +46,35 @@ import {
BackupRefreshSession,
BackupRefundItem,
BackupRefundState,
- BackupReserve,
BackupTip,
+ BackupWgInfo,
+ BackupWgType,
BackupWithdrawalGroup,
+ BACKUP_VERSION_MAJOR,
+ BACKUP_VERSION_MINOR,
canonicalizeBaseUrl,
canonicalJson,
- Logger,
- WalletBackupContentV1,
- hash,
encodeCrock,
getRandomBytes,
+ hash,
+ Logger,
stringToBytes,
- AbsoluteTime,
+ WalletBackupContentV1,
} from "@gnu-taler/taler-util";
-import { InternalWalletState } from "../../internal-wallet-state.js";
import {
AbortStatus,
CoinSourceType,
CoinStatus,
DenominationRecord,
+ OperationStatus,
ProposalStatus,
RefreshCoinStatus,
RefundState,
WALLET_BACKUP_STATE_KEY,
+ WithdrawalRecordType,
} from "../../db.js";
+import { InternalWalletState } from "../../internal-wallet-state.js";
+import { assertUnreachable } from "../../util/assertUnreachable.js";
import { getWalletBackupState, provideBackupState } from "./state.js";
const logger = new Logger("backup/export.ts");
@@ -100,31 +107,75 @@ export async function exportBackup(
const backupDenominationsByExchange: {
[url: string]: BackupDenomination[];
} = {};
- const backupReservesByExchange: { [url: string]: BackupReserve[] } = {};
const backupPurchases: BackupPurchase[] = [];
const backupProposals: BackupProposal[] = [];
const backupRefreshGroups: BackupRefreshGroup[] = [];
const backupBackupProviders: BackupBackupProvider[] = [];
const backupTips: BackupTip[] = [];
const backupRecoupGroups: BackupRecoupGroup[] = [];
- const withdrawalGroupsByReserve: {
- [reservePub: string]: BackupWithdrawalGroup[];
- } = {};
+ const backupWithdrawalGroups: BackupWithdrawalGroup[] = [];
await tx.withdrawalGroups.iter().forEachAsync(async (wg) => {
- const withdrawalGroups = (withdrawalGroupsByReserve[wg.reservePub] ??=
- []);
- withdrawalGroups.push({
+ let info: BackupWgInfo;
+ switch (wg.wgInfo.withdrawalType) {
+ case WithdrawalRecordType.BankIntegrated:
+ info = {
+ type: BackupWgType.BankIntegrated,
+ exchange_payto_uri: wg.wgInfo.bankInfo.exchangePaytoUri,
+ taler_withdraw_uri: wg.wgInfo.bankInfo.talerWithdrawUri,
+ confirm_url: wg.wgInfo.bankInfo.confirmUrl,
+ timestamp_bank_confirmed:
+ wg.wgInfo.bankInfo.timestampBankConfirmed,
+ timestamp_reserve_info_posted:
+ wg.wgInfo.bankInfo.timestampReserveInfoPosted,
+ };
+ break;
+ case WithdrawalRecordType.BankManual:
+ info = {
+ type: BackupWgType.BankManual,
+ };
+ break;
+ case WithdrawalRecordType.PeerPullCredit:
+ info = {
+ type: BackupWgType.PeerPullCredit,
+ contract_priv: wg.wgInfo.contractPriv,
+ contract_terms: wg.wgInfo.contractTerms,
+ };
+ break;
+ case WithdrawalRecordType.PeerPushCredit:
+ info = {
+ type: BackupWgType.PeerPushCredit,
+ contract_terms: wg.wgInfo.contractTerms,
+ };
+ break;
+ case WithdrawalRecordType.Recoup:
+ info = {
+ type: BackupWgType.Recoup,
+ };
+ break;
+ default:
+ assertUnreachable(wg.wgInfo);
+ }
+ backupWithdrawalGroups.push({
raw_withdrawal_amount: Amounts.stringify(wg.rawWithdrawalAmount),
- selected_denoms: wg.denomsSel.selectedDenoms.map((x) => ({
- count: x.count,
- denom_pub_hash: x.denomPubHash,
- })),
+ info,
timestamp_created: wg.timestampStart,
timestamp_finish: wg.timestampFinish,
withdrawal_group_id: wg.withdrawalGroupId,
secret_seed: wg.secretSeed,
- selected_denoms_id: wg.denomSelUid,
+ exchange_base_url: wg.exchangeBaseUrl,
+ instructed_amount: Amounts.stringify(wg.instructedAmount),
+ reserve_priv: wg.reservePriv,
+ restrict_age: wg.restrictAge,
+ operation_status:
+ wg.operationStatus == OperationStatus.Finished
+ ? BackupOperationStatus.Finished
+ : BackupOperationStatus.Pending,
+ selected_denoms_uid: wg.denomSelUid,
+ selected_denoms: wg.denomsSel.selectedDenoms.map((x) => ({
+ count: x.count,
+ denom_pub_hash: x.denomPubHash,
+ })),
});
});
@@ -299,7 +350,6 @@ export async function exportBackup(
tos_accepted_timestamp: ex.termsOfServiceAcceptedTimestamp,
denominations:
backupDenominationsByExchange[ex.exchangeBaseUrl] ?? [],
- reserves: backupReservesByExchange[ex.exchangeBaseUrl] ?? [],
});
});
@@ -439,7 +489,8 @@ export async function exportBackup(
const backupBlob: WalletBackupContentV1 = {
schema_id: "gnu-taler-wallet-backup-content",
- schema_version: 1,
+ schema_version: BACKUP_VERSION_MAJOR,
+ minor_version: BACKUP_VERSION_MINOR,
exchanges: backupExchanges,
exchange_details: backupExchangeDetails,
wallet_root_pub: bs.walletRootPub,
@@ -456,6 +507,8 @@ export async function exportBackup(
intern_table: {},
error_reports: [],
tombstones: [],
+ // FIXME!
+ withdrawal_groups: backupWithdrawalGroups,
};
// If the backup changed, we change our nonce and timestamp.
diff --git a/packages/taler-wallet-core/src/operations/backup/import.ts b/packages/taler-wallet-core/src/operations/backup/import.ts
index be09952cd..507a6cf10 100644
--- a/packages/taler-wallet-core/src/operations/backup/import.ts
+++ b/packages/taler-wallet-core/src/operations/backup/import.ts
@@ -24,6 +24,7 @@ import {
BackupPurchase,
BackupRefreshReason,
BackupRefundState,
+ BackupWgType,
codecForContractTerms,
DenomKeyType,
j2s,
@@ -53,8 +54,11 @@ import {
WalletContractData,
WalletRefundItem,
WalletStoresV1,
+ WgInfo,
+ WithdrawalRecordType,
} from "../../db.js";
import { InternalWalletState } from "../../internal-wallet-state.js";
+import { assertUnreachable } from "../../util/assertUnreachable.js";
import {
checkDbInvariant,
checkLogicInvariant,
@@ -444,6 +448,91 @@ export async function importBackup(
}
}
+ for (const backupWg of backupBlob.withdrawal_groups) {
+ const reservePub = cryptoComp.reservePrivToPub[backupWg.reserve_priv];
+ checkLogicInvariant(!!reservePub);
+ const ts = makeEventId(TombstoneTag.DeleteReserve, reservePub);
+ if (tombstoneSet.has(ts)) {
+ continue;
+ }
+ const existingWg = await tx.withdrawalGroups.get(
+ backupWg.withdrawal_group_id,
+ );
+ if (existingWg) {
+ continue;
+ }
+ let wgInfo: WgInfo;
+ switch (backupWg.info.type) {
+ case BackupWgType.BankIntegrated:
+ wgInfo = {
+ withdrawalType: WithdrawalRecordType.BankIntegrated,
+ bankInfo: {
+ exchangePaytoUri: backupWg.info.exchange_payto_uri,
+ talerWithdrawUri: backupWg.info.taler_withdraw_uri,
+ confirmUrl: backupWg.info.confirm_url,
+ timestampBankConfirmed:
+ backupWg.info.timestamp_bank_confirmed,
+ timestampReserveInfoPosted:
+ backupWg.info.timestamp_reserve_info_posted,
+ },
+ };
+ break;
+ case BackupWgType.BankManual:
+ wgInfo = {
+ withdrawalType: WithdrawalRecordType.BankManual,
+ };
+ break;
+ case BackupWgType.PeerPullCredit:
+ wgInfo = {
+ withdrawalType: WithdrawalRecordType.PeerPullCredit,
+ contractTerms: backupWg.info.contract_terms,
+ contractPriv: backupWg.info.contract_priv,
+ };
+ break;
+ case BackupWgType.PeerPushCredit:
+ wgInfo = {
+ withdrawalType: WithdrawalRecordType.PeerPushCredit,
+ contractTerms: backupWg.info.contract_terms,
+ };
+ break;
+ case BackupWgType.Recoup:
+ wgInfo = {
+ withdrawalType: WithdrawalRecordType.Recoup,
+ };
+ break;
+ default:
+ assertUnreachable(backupWg.info);
+ }
+ await tx.withdrawalGroups.put({
+ withdrawalGroupId: backupWg.withdrawal_group_id,
+ exchangeBaseUrl: backupWg.exchange_base_url,
+ instructedAmount: Amounts.parseOrThrow(backupWg.instructed_amount),
+ secretSeed: backupWg.secret_seed,
+ operationStatus: backupWg.timestamp_finish
+ ? OperationStatus.Finished
+ : OperationStatus.Pending,
+ denomsSel: await getDenomSelStateFromBackup(
+ tx,
+ backupWg.exchange_base_url,
+ backupWg.selected_denoms,
+ ),
+ denomSelUid: backupWg.selected_denoms_uid,
+ rawWithdrawalAmount: Amounts.parseOrThrow(
+ backupWg.raw_withdrawal_amount,
+ ),
+ reservePriv: backupWg.reserve_priv,
+ reservePub,
+ reserveStatus: backupWg.timestamp_finish
+ ? ReserveRecordStatus.Dormant
+ : ReserveRecordStatus.QueryingStatus, // FIXME!
+ timestampStart: backupWg.timestamp_created,
+ wgInfo,
+ restrictAge: backupWg.restrict_age,
+ senderWire: undefined, // FIXME!
+ timestampFinish: backupWg.timestamp_finish,
+ });
+ }
+
// FIXME: import reserves with new schema
// for (const backupReserve of backupExchangeDetails.reserves) {
diff --git a/packages/taler-wallet-core/src/operations/backup/index.ts b/packages/taler-wallet-core/src/operations/backup/index.ts
index c7c93e909..b69c0b7b7 100644
--- a/packages/taler-wallet-core/src/operations/backup/index.ts
+++ b/packages/taler-wallet-core/src/operations/backup/index.ts
@@ -187,11 +187,11 @@ async function computeBackupCryptoData(
cryptoData.rsaDenomPubToHash[backupDenom.denom_pub.rsa_public_key] =
encodeCrock(hashDenomPub(backupDenom.denom_pub));
}
- for (const backupReserve of backupExchangeDetails.reserves) {
- cryptoData.reservePrivToPub[backupReserve.reserve_priv] = encodeCrock(
- eddsaGetPublic(decodeCrock(backupReserve.reserve_priv)),
- );
- }
+ }
+ for (const backupWg of backupContent.withdrawal_groups) {
+ cryptoData.reservePrivToPub[backupWg.reserve_priv] = encodeCrock(
+ eddsaGetPublic(decodeCrock(backupWg.reserve_priv)),
+ );
}
for (const prop of backupContent.proposals) {
const { h: contractTermsHash } = await cryptoApi.hashString({