aboutsummaryrefslogtreecommitdiff
path: root/packages/taler-wallet-core/src/wallet.ts
diff options
context:
space:
mode:
Diffstat (limited to 'packages/taler-wallet-core/src/wallet.ts')
-rw-r--r--packages/taler-wallet-core/src/wallet.ts95
1 files changed, 68 insertions, 27 deletions
diff --git a/packages/taler-wallet-core/src/wallet.ts b/packages/taler-wallet-core/src/wallet.ts
index 194894e52..626409dd6 100644
--- a/packages/taler-wallet-core/src/wallet.ts
+++ b/packages/taler-wallet-core/src/wallet.ts
@@ -120,6 +120,7 @@ import {
codecForSharePaymentRequest,
GetCurrencyInfoResponse,
codecForGetCurrencyInfoRequest,
+ CreateStoredBackupResponse,
} from "@gnu-taler/taler-util";
import {
HttpRequestLibrary,
@@ -139,6 +140,8 @@ import {
clearDatabase,
exportDb,
importDb,
+ openStoredBackupsDatabase,
+ openTalerDatabase,
} from "./db.js";
import { DevExperimentHttpLib, applyDevExperiment } from "./dev-experiments.js";
import {
@@ -157,7 +160,6 @@ import {
getUserAttentionsUnreadCount,
markAttentionRequestAsRead,
} from "./operations/attention.js";
-import { exportBackup } from "./operations/backup/export.js";
import {
addBackupProvider,
codecForAddBackupProviderRequest,
@@ -165,13 +167,12 @@ import {
codecForRunBackupCycle,
getBackupInfo,
getBackupRecovery,
- importBackupPlain,
loadBackupRecovery,
processBackupForProvider,
removeBackupProvider,
runBackupCycle,
+ setWalletDeviceId,
} from "./operations/backup/index.js";
-import { setWalletDeviceId } from "./operations/backup/state.js";
import { getBalanceDetail, getBalances } from "./operations/balance.js";
import {
TaskIdentifiers,
@@ -189,6 +190,7 @@ import {
} from "./operations/deposits.js";
import {
acceptExchangeTermsOfService,
+ addPresetExchangeEntry,
downloadTosFromAcceptedFormat,
getExchangeDetails,
getExchangeRequestTimeout,
@@ -314,6 +316,7 @@ import {
getMaxPeerPushAmount,
convertWithdrawalAmount,
} from "./util/instructedAmountConversion.js";
+import { IDBFactory } from "@gnu-taler/idb-bridge";
const logger = new Logger("wallet.ts");
@@ -340,9 +343,8 @@ async function callOperationHandler(
return await processRecoupGroup(ws, pending.recoupGroupId);
case PendingTaskType.ExchangeCheckRefresh:
return await autoRefresh(ws, pending.exchangeBaseUrl);
- case PendingTaskType.Deposit: {
+ case PendingTaskType.Deposit:
return await processDepositGroup(ws, pending.depositGroupId);
- }
case PendingTaskType.Backup:
return await processBackupForProvider(ws, pending.backupProviderBaseUrl);
case PendingTaskType.PeerPushDebit:
@@ -533,6 +535,7 @@ async function fillDefaults(ws: InternalWalletState): Promise<void> {
await tx.auditorTrust.put(c);
}
for (const baseUrl of ws.config.builtin.exchanges) {
+ await addPresetExchangeEntry(tx, baseUrl);
const now = AbsoluteTime.now();
provideExchangeRecordInTx(ws, tx, baseUrl, now);
}
@@ -1021,6 +1024,23 @@ export async function getClientFromWalletState(
return client;
}
+async function createStoredBackup(
+ ws: InternalWalletState,
+): Promise<CreateStoredBackupResponse> {
+ const backup = await exportDb(ws.idb);
+ const backupsDb = await openStoredBackupsDatabase(ws.idb);
+ const name = `backup-${new Date().getTime()}`;
+ await backupsDb.mktxAll().runReadWrite(async (tx) => {
+ await tx.backupMeta.add({
+ name,
+ });
+ await tx.backupData.add(backup, name);
+ });
+ return {
+ name,
+ };
+}
+
/**
* Implementation of the "wallet-core" API.
*/
@@ -1037,6 +1057,14 @@ async function dispatchRequestInternal<Op extends WalletApiOperation>(
// FIXME: Can we make this more type-safe by using the request/response type
// definitions we already have?
switch (operation) {
+ case WalletApiOperation.CreateStoredBackup:
+ return createStoredBackup(ws);
+ case WalletApiOperation.DeleteStoredBackup:
+ return {};
+ case WalletApiOperation.ListStoredBackups:
+ return {};
+ case WalletApiOperation.RecoverStoredBackup:
+ return {};
case WalletApiOperation.InitWallet: {
logger.trace("initializing wallet");
ws.initCalled = true;
@@ -1378,9 +1406,6 @@ async function dispatchRequestInternal<Op extends WalletApiOperation>(
const req = codecForAcceptTipRequest().decode(payload);
return await acceptTip(ws, req.walletRewardId);
}
- case WalletApiOperation.ExportBackupPlain: {
- return exportBackup(ws);
- }
case WalletApiOperation.AddBackupProvider: {
const req = codecForAddBackupProviderRequest().decode(payload);
return await addBackupProvider(ws, req);
@@ -1531,13 +1556,11 @@ async function dispatchRequestInternal<Op extends WalletApiOperation>(
await clearDatabase(ws.db.idbHandle());
return {};
case WalletApiOperation.Recycle: {
- const backup = await exportBackup(ws);
- await clearDatabase(ws.db.idbHandle());
- await importBackupPlain(ws, backup);
+ throw Error("not implemented");
return {};
}
case WalletApiOperation.ExportDb: {
- const dbDump = await exportDb(ws.db.idbHandle());
+ const dbDump = await exportDb(ws.idb);
return dbDump;
}
case WalletApiOperation.ImportDb: {
@@ -1616,7 +1639,7 @@ export function getVersion(ws: InternalWalletState): WalletCoreVersion {
/**
* Handle a request to the wallet-core API.
*/
-export async function handleCoreApiRequest(
+async function handleCoreApiRequest(
ws: InternalWalletState,
operation: string,
id: string,
@@ -1652,14 +1675,14 @@ export class Wallet {
private _client: WalletCoreApiClient | undefined;
private constructor(
- db: DbAccess<typeof WalletStoresV1>,
+ idb: IDBFactory,
http: HttpRequestLibrary,
timer: TimerAPI,
cryptoWorkerFactory: CryptoWorkerFactory,
config?: WalletConfigParameter,
) {
this.ws = new InternalWalletStateImpl(
- db,
+ idb,
http,
timer,
cryptoWorkerFactory,
@@ -1675,21 +1698,20 @@ export class Wallet {
}
static async create(
- db: DbAccess<typeof WalletStoresV1>,
+ idb: IDBFactory,
http: HttpRequestLibrary,
timer: TimerAPI,
cryptoWorkerFactory: CryptoWorkerFactory,
config?: WalletConfigParameter,
): Promise<Wallet> {
- const w = new Wallet(db, http, timer, cryptoWorkerFactory, config);
+ const w = new Wallet(idb, http, timer, cryptoWorkerFactory, config);
w._client = await getClientFromWalletState(w.ws);
return w;
}
public static defaultConfig: Readonly<WalletConfig> = {
builtin: {
- //exchanges: ["https://exchange.demo.taler.net/"],
- exchanges: [],
+ exchanges: ["https://exchange.demo.taler.net/"],
auditors: [
{
currency: "KUDOS",
@@ -1724,19 +1746,22 @@ export class Wallet {
this.ws.stop();
}
- runPending(): Promise<void> {
+ async runPending(): Promise<void> {
+ await this.ws.ensureWalletDbOpen();
return runPending(this.ws);
}
- runTaskLoop(opts?: RetryLoopOpts): Promise<TaskLoopResult> {
+ async runTaskLoop(opts?: RetryLoopOpts): Promise<TaskLoopResult> {
+ await this.ws.ensureWalletDbOpen();
return runTaskLoop(this.ws, opts);
}
- handleCoreApiRequest(
+ async handleCoreApiRequest(
operation: string,
id: string,
payload: unknown,
): Promise<CoreApiResponse> {
+ await this.ws.ensureWalletDbOpen();
return handleCoreApiRequest(this.ws, operation, id, payload);
}
}
@@ -1800,12 +1825,17 @@ class InternalWalletStateImpl implements InternalWalletState {
config: Readonly<WalletConfig>;
+ private _db: DbAccess<typeof WalletStoresV1> | undefined = undefined;
+
+ get db(): DbAccess<typeof WalletStoresV1> {
+ if (!this._db) {
+ throw Error("db not initialized");
+ }
+ return this._db;
+ }
+
constructor(
- // FIXME: Make this a getter and make
- // the actual value nullable.
- // Check if we are in a DB migration / garbage collection
- // and throw an error in that case.
- public db: DbAccess<typeof WalletStoresV1>,
+ public idb: IDBFactory,
public http: HttpRequestLibrary,
public timer: TimerAPI,
cryptoWorkerFactory: CryptoWorkerFactory,
@@ -1820,6 +1850,17 @@ class InternalWalletStateImpl implements InternalWalletState {
}
}
+ async ensureWalletDbOpen(): Promise<void> {
+ if (this._db) {
+ return;
+ }
+ const myVersionChange = async (): Promise<void> => {
+ logger.info("version change requested for Taler DB");
+ };
+ const myDb = await openTalerDatabase(this.idb, myVersionChange);
+ this._db = myDb;
+ }
+
async getTransactionState(
ws: InternalWalletState,
tx: GetReadOnlyAccess<typeof WalletStoresV1>,