diff options
Diffstat (limited to 'packages/taler-wallet-core/src/wallet.ts')
-rw-r--r-- | packages/taler-wallet-core/src/wallet.ts | 95 |
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>, |