diff options
Diffstat (limited to 'packages/taler-wallet-core/src/wallet.ts')
-rw-r--r-- | packages/taler-wallet-core/src/wallet.ts | 431 |
1 files changed, 235 insertions, 196 deletions
diff --git a/packages/taler-wallet-core/src/wallet.ts b/packages/taler-wallet-core/src/wallet.ts index 810c78583..b59f52840 100644 --- a/packages/taler-wallet-core/src/wallet.ts +++ b/packages/taler-wallet-core/src/wallet.ts @@ -331,28 +331,31 @@ type CancelFn = () => void; */ async function fillDefaults(wex: WalletExecutionContext): Promise<void> { const notifications: WalletNotification[] = []; - await wex.db.runReadWriteTx(["config", "exchanges"], async (tx) => { - const appliedRec = await tx.config.get("currencyDefaultsApplied"); - let alreadyApplied = appliedRec ? !!appliedRec.value : false; - if (alreadyApplied) { - logger.trace("defaults already applied"); - return; - } - for (const exch of wex.ws.config.builtin.exchanges) { - const resp = await addPresetExchangeEntry( - tx, - exch.exchangeBaseUrl, - exch.currencyHint, - ); - if (resp.notification) { - notifications.push(resp.notification); + await wex.db.runReadWriteTx( + { storeNames: ["config", "exchanges"] }, + async (tx) => { + const appliedRec = await tx.config.get("currencyDefaultsApplied"); + let alreadyApplied = appliedRec ? !!appliedRec.value : false; + if (alreadyApplied) { + logger.trace("defaults already applied"); + return; } - } - await tx.config.put({ - key: ConfigRecordKey.CurrencyDefaultsApplied, - value: true, - }); - }); + for (const exch of wex.ws.config.builtin.exchanges) { + const resp = await addPresetExchangeEntry( + tx, + exch.exchangeBaseUrl, + exch.currencyHint, + ); + if (resp.notification) { + notifications.push(resp.notification); + } + } + await tx.config.put({ + key: ConfigRecordKey.CurrencyDefaultsApplied, + value: true, + }); + }, + ); for (const notif of notifications) { wex.ws.notify(notif); } @@ -387,7 +390,7 @@ async function listKnownBankAccounts( currency?: string, ): Promise<KnownBankAccounts> { const accounts: KnownBankAccountsInfo[] = []; - await wex.db.runReadOnlyTx(["bankAccounts"], async (tx) => { + await wex.db.runReadOnlyTx({ storeNames: ["bankAccounts"] }, async (tx) => { const knownAccounts = await tx.bankAccounts.iter().toArray(); for (const r of knownAccounts) { if (currency && currency !== r.currency) { @@ -415,7 +418,7 @@ async function addKnownBankAccounts( alias: string, currency: string, ): Promise<void> { - await wex.db.runReadWriteTx(["bankAccounts"], async (tx) => { + await wex.db.runReadWriteTx({ storeNames: ["bankAccounts"] }, async (tx) => { tx.bankAccounts.put({ uri: payto, alias: alias, @@ -432,7 +435,7 @@ async function forgetKnownBankAccounts( wex: WalletExecutionContext, payto: string, ): Promise<void> { - await wex.db.runReadWriteTx(["bankAccounts"], async (tx) => { + await wex.db.runReadWriteTx({ storeNames: ["bankAccounts"] }, async (tx) => { const account = await tx.bankAccounts.get(payto); if (!account) { throw Error(`account not found: ${payto}`); @@ -447,39 +450,42 @@ async function setCoinSuspended( coinPub: string, suspended: boolean, ): Promise<void> { - await wex.db.runReadWriteTx(["coins", "coinAvailability"], async (tx) => { - const c = await tx.coins.get(coinPub); - if (!c) { - logger.warn(`coin ${coinPub} not found, won't suspend`); - return; - } - const coinAvailability = await tx.coinAvailability.get([ - c.exchangeBaseUrl, - c.denomPubHash, - c.maxAge, - ]); - checkDbInvariant(!!coinAvailability); - if (suspended) { - if (c.status !== CoinStatus.Fresh) { + await wex.db.runReadWriteTx( + { storeNames: ["coins", "coinAvailability"] }, + async (tx) => { + const c = await tx.coins.get(coinPub); + if (!c) { + logger.warn(`coin ${coinPub} not found, won't suspend`); return; } - if (coinAvailability.freshCoinCount === 0) { - throw Error( - `invalid coin count ${coinAvailability.freshCoinCount} in DB`, - ); - } - coinAvailability.freshCoinCount--; - c.status = CoinStatus.FreshSuspended; - } else { - if (c.status == CoinStatus.Dormant) { - return; + const coinAvailability = await tx.coinAvailability.get([ + c.exchangeBaseUrl, + c.denomPubHash, + c.maxAge, + ]); + checkDbInvariant(!!coinAvailability); + if (suspended) { + if (c.status !== CoinStatus.Fresh) { + return; + } + if (coinAvailability.freshCoinCount === 0) { + throw Error( + `invalid coin count ${coinAvailability.freshCoinCount} in DB`, + ); + } + coinAvailability.freshCoinCount--; + c.status = CoinStatus.FreshSuspended; + } else { + if (c.status == CoinStatus.Dormant) { + return; + } + coinAvailability.freshCoinCount++; + c.status = CoinStatus.Fresh; } - coinAvailability.freshCoinCount++; - c.status = CoinStatus.Fresh; - } - await tx.coins.put(c); - await tx.coinAvailability.put(coinAvailability); - }); + await tx.coins.put(c); + await tx.coinAvailability.put(coinAvailability); + }, + ); } /** @@ -488,55 +494,58 @@ async function setCoinSuspended( async function dumpCoins(wex: WalletExecutionContext): Promise<CoinDumpJson> { const coinsJson: CoinDumpJson = { coins: [] }; logger.info("dumping coins"); - await wex.db.runReadOnlyTx(["coins", "denominations"], async (tx) => { - const coins = await tx.coins.iter().toArray(); - for (const c of coins) { - const denom = await tx.denominations.get([ - c.exchangeBaseUrl, - c.denomPubHash, - ]); - if (!denom) { - logger.warn("no denom found for coin"); - continue; - } - const cs = c.coinSource; - let refreshParentCoinPub: string | undefined; - if (cs.type == CoinSourceType.Refresh) { - refreshParentCoinPub = cs.oldCoinPub; - } - let withdrawalReservePub: string | undefined; - if (cs.type == CoinSourceType.Withdraw) { - withdrawalReservePub = cs.reservePub; - } - const denomInfo = await getDenomInfo( - wex, - tx, - c.exchangeBaseUrl, - c.denomPubHash, - ); - if (!denomInfo) { - logger.warn("no denomination found for coin"); - continue; + await wex.db.runReadOnlyTx( + { storeNames: ["coins", "denominations"] }, + async (tx) => { + const coins = await tx.coins.iter().toArray(); + for (const c of coins) { + const denom = await tx.denominations.get([ + c.exchangeBaseUrl, + c.denomPubHash, + ]); + if (!denom) { + logger.warn("no denom found for coin"); + continue; + } + const cs = c.coinSource; + let refreshParentCoinPub: string | undefined; + if (cs.type == CoinSourceType.Refresh) { + refreshParentCoinPub = cs.oldCoinPub; + } + let withdrawalReservePub: string | undefined; + if (cs.type == CoinSourceType.Withdraw) { + withdrawalReservePub = cs.reservePub; + } + const denomInfo = await getDenomInfo( + wex, + tx, + c.exchangeBaseUrl, + c.denomPubHash, + ); + if (!denomInfo) { + logger.warn("no denomination found for coin"); + continue; + } + coinsJson.coins.push({ + coin_pub: c.coinPub, + denom_pub: denomInfo.denomPub, + denom_pub_hash: c.denomPubHash, + denom_value: denom.value, + exchange_base_url: c.exchangeBaseUrl, + refresh_parent_coin_pub: refreshParentCoinPub, + withdrawal_reserve_pub: withdrawalReservePub, + coin_status: c.status, + ageCommitmentProof: c.ageCommitmentProof, + spend_allocation: c.spendAllocation + ? { + amount: c.spendAllocation.amount, + id: c.spendAllocation.id, + } + : undefined, + }); } - coinsJson.coins.push({ - coin_pub: c.coinPub, - denom_pub: denomInfo.denomPub, - denom_pub_hash: c.denomPubHash, - denom_value: denom.value, - exchange_base_url: c.exchangeBaseUrl, - refresh_parent_coin_pub: refreshParentCoinPub, - withdrawal_reserve_pub: withdrawalReservePub, - coin_status: c.status, - ageCommitmentProof: c.ageCommitmentProof, - spend_allocation: c.spendAllocation - ? { - amount: c.spendAllocation.amount, - id: c.spendAllocation.id, - } - : undefined, - }); - } - }); + }, + ); return coinsJson; } @@ -713,7 +722,7 @@ async function dispatchRequestInternal( // Write to the DB to make sure that we're failing early in // case the DB is not writeable. try { - await wex.db.runReadWriteTx(["config"], async (tx) => { + await wex.db.runReadWriteTx({ storeNames: ["config"] }, async (tx) => { tx.config.put({ key: ConfigRecordKey.LastInitInfo, value: timestampProtocolToDb(TalerProtocolTimestamp.now()), @@ -824,20 +833,24 @@ async function dispatchRequestInternal( numLost: 0, numOffered: 0, }; - await wex.db.runReadOnlyTx(["denominations"], async (tx) => { - const denoms = await tx.denominations.indexes.byExchangeBaseUrl.getAll( - req.exchangeBaseUrl, - ); - for (const d of denoms) { - denomStats.numKnown++; - if (d.isOffered) { - denomStats.numOffered++; - } - if (d.isLost) { - denomStats.numLost++; + await wex.db.runReadOnlyTx( + { storeNames: ["denominations"] }, + async (tx) => { + const denoms = + await tx.denominations.indexes.byExchangeBaseUrl.getAll( + req.exchangeBaseUrl, + ); + for (const d of denoms) { + denomStats.numKnown++; + if (d.isOffered) { + denomStats.numOffered++; + } + if (d.isLost) { + denomStats.numLost++; + } } - } - }); + }, + ); return denomStats; } case WalletApiOperation.ListExchanges: { @@ -1026,7 +1039,7 @@ async function dispatchRequestInternal( const tasksInfo = await Promise.all( allTasksId.map(async (id) => { return await wex.db.runReadOnlyTx( - ["operationRetries"], + { storeNames: ["operationRetries"] }, async (tx) => { return tx.operationRetries.get(id); }, @@ -1245,89 +1258,112 @@ async function dispatchRequestInternal( const resp: ListGlobalCurrencyExchangesResponse = { exchanges: [], }; - await wex.db.runReadOnlyTx(["globalCurrencyExchanges"], async (tx) => { - const gceList = await tx.globalCurrencyExchanges.iter().toArray(); - for (const gce of gceList) { - resp.exchanges.push({ - currency: gce.currency, - exchangeBaseUrl: gce.exchangeBaseUrl, - exchangeMasterPub: gce.exchangeMasterPub, - }); - } - }); + await wex.db.runReadOnlyTx( + { storeNames: ["globalCurrencyExchanges"] }, + async (tx) => { + const gceList = await tx.globalCurrencyExchanges.iter().toArray(); + for (const gce of gceList) { + resp.exchanges.push({ + currency: gce.currency, + exchangeBaseUrl: gce.exchangeBaseUrl, + exchangeMasterPub: gce.exchangeMasterPub, + }); + } + }, + ); return resp; } case WalletApiOperation.ListGlobalCurrencyAuditors: { const resp: ListGlobalCurrencyAuditorsResponse = { auditors: [], }; - await wex.db.runReadOnlyTx(["globalCurrencyAuditors"], async (tx) => { - const gcaList = await tx.globalCurrencyAuditors.iter().toArray(); - for (const gca of gcaList) { - resp.auditors.push({ - currency: gca.currency, - auditorBaseUrl: gca.auditorBaseUrl, - auditorPub: gca.auditorPub, - }); - } - }); + await wex.db.runReadOnlyTx( + { storeNames: ["globalCurrencyAuditors"] }, + async (tx) => { + const gcaList = await tx.globalCurrencyAuditors.iter().toArray(); + for (const gca of gcaList) { + resp.auditors.push({ + currency: gca.currency, + auditorBaseUrl: gca.auditorBaseUrl, + auditorPub: gca.auditorPub, + }); + } + }, + ); return resp; } case WalletApiOperation.AddGlobalCurrencyExchange: { const req = codecForAddGlobalCurrencyExchangeRequest().decode(payload); - await wex.db.runReadWriteTx(["globalCurrencyExchanges"], async (tx) => { - const key = [req.currency, req.exchangeBaseUrl, req.exchangeMasterPub]; - const existingRec = - await tx.globalCurrencyExchanges.indexes.byCurrencyAndUrlAndPub.get( - key, - ); - if (existingRec) { - return; - } - wex.ws.exchangeCache.clear(); - await tx.globalCurrencyExchanges.add({ - currency: req.currency, - exchangeBaseUrl: req.exchangeBaseUrl, - exchangeMasterPub: req.exchangeMasterPub, - }); - }); + await wex.db.runReadWriteTx( + { storeNames: ["globalCurrencyExchanges"] }, + async (tx) => { + const key = [ + req.currency, + req.exchangeBaseUrl, + req.exchangeMasterPub, + ]; + const existingRec = + await tx.globalCurrencyExchanges.indexes.byCurrencyAndUrlAndPub.get( + key, + ); + if (existingRec) { + return; + } + wex.ws.exchangeCache.clear(); + await tx.globalCurrencyExchanges.add({ + currency: req.currency, + exchangeBaseUrl: req.exchangeBaseUrl, + exchangeMasterPub: req.exchangeMasterPub, + }); + }, + ); return {}; } case WalletApiOperation.RemoveGlobalCurrencyExchange: { const req = codecForRemoveGlobalCurrencyExchangeRequest().decode(payload); - await wex.db.runReadWriteTx(["globalCurrencyExchanges"], async (tx) => { - const key = [req.currency, req.exchangeBaseUrl, req.exchangeMasterPub]; - const existingRec = - await tx.globalCurrencyExchanges.indexes.byCurrencyAndUrlAndPub.get( - key, - ); - if (!existingRec) { - return; - } - wex.ws.exchangeCache.clear(); - checkDbInvariant(!!existingRec.id); - await tx.globalCurrencyExchanges.delete(existingRec.id); - }); + await wex.db.runReadWriteTx( + { storeNames: ["globalCurrencyExchanges"] }, + async (tx) => { + const key = [ + req.currency, + req.exchangeBaseUrl, + req.exchangeMasterPub, + ]; + const existingRec = + await tx.globalCurrencyExchanges.indexes.byCurrencyAndUrlAndPub.get( + key, + ); + if (!existingRec) { + return; + } + wex.ws.exchangeCache.clear(); + checkDbInvariant(!!existingRec.id); + await tx.globalCurrencyExchanges.delete(existingRec.id); + }, + ); return {}; } case WalletApiOperation.AddGlobalCurrencyAuditor: { const req = codecForAddGlobalCurrencyAuditorRequest().decode(payload); - await wex.db.runReadWriteTx(["globalCurrencyAuditors"], async (tx) => { - const key = [req.currency, req.auditorBaseUrl, req.auditorPub]; - const existingRec = - await tx.globalCurrencyAuditors.indexes.byCurrencyAndUrlAndPub.get( - key, - ); - if (existingRec) { - return; - } - await tx.globalCurrencyAuditors.add({ - currency: req.currency, - auditorBaseUrl: req.auditorBaseUrl, - auditorPub: req.auditorPub, - }); - wex.ws.exchangeCache.clear(); - }); + await wex.db.runReadWriteTx( + { storeNames: ["globalCurrencyAuditors"] }, + async (tx) => { + const key = [req.currency, req.auditorBaseUrl, req.auditorPub]; + const existingRec = + await tx.globalCurrencyAuditors.indexes.byCurrencyAndUrlAndPub.get( + key, + ); + if (existingRec) { + return; + } + await tx.globalCurrencyAuditors.add({ + currency: req.currency, + auditorBaseUrl: req.auditorBaseUrl, + auditorPub: req.auditorPub, + }); + wex.ws.exchangeCache.clear(); + }, + ); return {}; } case WalletApiOperation.TestingWaitTasksDone: { @@ -1336,19 +1372,22 @@ async function dispatchRequestInternal( } case WalletApiOperation.RemoveGlobalCurrencyAuditor: { const req = codecForRemoveGlobalCurrencyAuditorRequest().decode(payload); - await wex.db.runReadWriteTx(["globalCurrencyAuditors"], async (tx) => { - const key = [req.currency, req.auditorBaseUrl, req.auditorPub]; - const existingRec = - await tx.globalCurrencyAuditors.indexes.byCurrencyAndUrlAndPub.get( - key, - ); - if (!existingRec) { - return; - } - checkDbInvariant(!!existingRec.id); - await tx.globalCurrencyAuditors.delete(existingRec.id); - wex.ws.exchangeCache.clear(); - }); + await wex.db.runReadWriteTx( + { storeNames: ["globalCurrencyAuditors"] }, + async (tx) => { + const key = [req.currency, req.auditorBaseUrl, req.auditorPub]; + const existingRec = + await tx.globalCurrencyAuditors.indexes.byCurrencyAndUrlAndPub.get( + key, + ); + if (!existingRec) { + return; + } + checkDbInvariant(!!existingRec.id); + await tx.globalCurrencyAuditors.delete(existingRec.id); + wex.ws.exchangeCache.clear(); + }, + ); return {}; } case WalletApiOperation.ImportDb: { @@ -1434,7 +1473,7 @@ async function dispatchRequestInternal( let loopCount = 0; while (true) { logger.info(`looping test write tx, iteration ${loopCount}`); - await wex.db.runReadWriteTx(["config"], async (tx) => { + await wex.db.runReadWriteTx({ storeNames: ["config"] }, async (tx) => { await tx.config.put({ key: ConfigRecordKey.TestLoopTx, value: loopCount, |