summaryrefslogtreecommitdiff
path: root/packages/taler-wallet-core/src/wallet.ts
diff options
context:
space:
mode:
authorFlorian Dold <florian@dold.me>2024-02-19 12:49:17 +0100
committerFlorian Dold <florian@dold.me>2024-02-19 17:47:35 +0100
commit1ec521b9d214b286e747b3ccb3113730ac3a2509 (patch)
tree2f3d2b2906810dca45859b8cbfb8d18d53b27e80 /packages/taler-wallet-core/src/wallet.ts
parent1034ecb5f20bd8c75e37e0b4b454ea6c1f4c1da6 (diff)
downloadwallet-core-1ec521b9d214b286e747b3ccb3113730ac3a2509.tar.gz
wallet-core-1ec521b9d214b286e747b3ccb3113730ac3a2509.tar.bz2
wallet-core-1ec521b9d214b286e747b3ccb3113730ac3a2509.zip
wallet-core: simplify/unify DB access
Diffstat (limited to 'packages/taler-wallet-core/src/wallet.ts')
-rw-r--r--packages/taler-wallet-core/src/wallet.ts303
1 files changed, 150 insertions, 153 deletions
diff --git a/packages/taler-wallet-core/src/wallet.ts b/packages/taler-wallet-core/src/wallet.ts
index cfe171bd0..45970e770 100644
--- a/packages/taler-wallet-core/src/wallet.ts
+++ b/packages/taler-wallet-core/src/wallet.ts
@@ -141,6 +141,8 @@ import {
CoinSourceType,
ConfigRecordKey,
DenominationRecord,
+ WalletDbReadOnlyTransaction,
+ WalletDbReadWriteTransaction,
WalletStoresV1,
clearDatabase,
exportDb,
@@ -268,11 +270,7 @@ import {
getMaxPeerPushAmount,
} from "./util/instructedAmountConversion.js";
import { checkDbInvariant } from "./util/invariants.js";
-import {
- DbAccess,
- GetReadOnlyAccess,
- GetReadWriteAccess,
-} from "./util/query.js";
+import { DbAccess } from "./util/query.js";
import { TimerAPI, TimerGroup } from "./util/timer.js";
import {
WALLET_BANK_CONVERSION_API_PROTOCOL_VERSION,
@@ -306,30 +304,28 @@ async function runTaskLoop(
*/
async function fillDefaults(ws: InternalWalletState): Promise<void> {
const notifications: WalletNotification[] = [];
- await ws.db
- .mktx((x) => [x.config, x.exchanges, x.exchangeDetails])
- .runReadWrite(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 ws.config.builtin.exchanges) {
- const resp = await addPresetExchangeEntry(
- tx,
- exch.exchangeBaseUrl,
- exch.currencyHint,
- );
- if (resp.notification) {
- notifications.push(resp.notification);
- }
+ await ws.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 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,
- });
+ }
+ await tx.config.put({
+ key: ConfigRecordKey.CurrencyDefaultsApplied,
+ value: true,
});
+ });
for (const notif of notifications) {
ws.notify(notif);
}
@@ -344,25 +340,23 @@ async function listKnownBankAccounts(
currency?: string,
): Promise<KnownBankAccounts> {
const accounts: KnownBankAccountsInfo[] = [];
- await ws.db
- .mktx((x) => [x.bankAccounts])
- .runReadOnly(async (tx) => {
- const knownAccounts = await tx.bankAccounts.iter().toArray();
- for (const r of knownAccounts) {
- if (currency && currency !== r.currency) {
- continue;
- }
- const payto = parsePaytoUri(r.uri);
- if (payto) {
- accounts.push({
- uri: payto,
- alias: r.alias,
- kyc_completed: r.kycCompleted,
- currency: r.currency,
- });
- }
+ await ws.db.runReadOnlyTx(["bankAccounts"], async (tx) => {
+ const knownAccounts = await tx.bankAccounts.iter().toArray();
+ for (const r of knownAccounts) {
+ if (currency && currency !== r.currency) {
+ continue;
}
- });
+ const payto = parsePaytoUri(r.uri);
+ if (payto) {
+ accounts.push({
+ uri: payto,
+ alias: r.alias,
+ kyc_completed: r.kycCompleted,
+ currency: r.currency,
+ });
+ }
+ }
+ });
return { accounts };
}
@@ -374,16 +368,14 @@ async function addKnownBankAccounts(
alias: string,
currency: string,
): Promise<void> {
- await ws.db
- .mktx((x) => [x.bankAccounts])
- .runReadWrite(async (tx) => {
- tx.bankAccounts.put({
- uri: payto,
- alias: alias,
- currency: currency,
- kycCompleted: false,
- });
+ await ws.db.runReadWriteTx(["bankAccounts"], async (tx) => {
+ tx.bankAccounts.put({
+ uri: payto,
+ alias: alias,
+ currency: currency,
+ kycCompleted: false,
});
+ });
return;
}
@@ -393,15 +385,13 @@ async function forgetKnownBankAccounts(
ws: InternalWalletState,
payto: string,
): Promise<void> {
- await ws.db
- .mktx((x) => [x.bankAccounts])
- .runReadWrite(async (tx) => {
- const account = await tx.bankAccounts.get(payto);
- if (!account) {
- throw Error(`account not found: ${payto}`);
- }
- tx.bankAccounts.delete(account.uri);
- });
+ await ws.db.runReadWriteTx(["bankAccounts"], async (tx) => {
+ const account = await tx.bankAccounts.get(payto);
+ if (!account) {
+ throw Error(`account not found: ${payto}`);
+ }
+ tx.bankAccounts.delete(account.uri);
+ });
return;
}
@@ -410,41 +400,39 @@ async function setCoinSuspended(
coinPub: string,
suspended: boolean,
): Promise<void> {
- await ws.db
- .mktx((x) => [x.coins, x.coinAvailability])
- .runReadWrite(async (tx) => {
- const c = await tx.coins.get(coinPub);
- if (!c) {
- logger.warn(`coin ${coinPub} not found, won't suspend`);
+ await ws.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) {
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;
+ if (coinAvailability.freshCoinCount === 0) {
+ throw Error(
+ `invalid coin count ${coinAvailability.freshCoinCount} in DB`,
+ );
}
- await tx.coins.put(c);
- await tx.coinAvailability.put(coinAvailability);
- });
+ coinAvailability.freshCoinCount--;
+ c.status = CoinStatus.FreshSuspended;
+ } else {
+ if (c.status == CoinStatus.Dormant) {
+ return;
+ }
+ coinAvailability.freshCoinCount++;
+ c.status = CoinStatus.Fresh;
+ }
+ await tx.coins.put(c);
+ await tx.coinAvailability.put(coinAvailability);
+ });
}
/**
@@ -453,57 +441,55 @@ async function setCoinSuspended(
async function dumpCoins(ws: InternalWalletState): Promise<CoinDumpJson> {
const coinsJson: CoinDumpJson = { coins: [] };
logger.info("dumping coins");
- await ws.db
- .mktx((x) => [x.coins, x.denominations, x.withdrawalGroups])
- .runReadOnly(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 ws.getDenomInfo(
- ws,
- 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,
- });
+ await ws.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 ws.getDenomInfo(
+ ws,
+ 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,
+ });
+ }
+ });
return coinsJson;
}
@@ -534,7 +520,7 @@ async function createStoredBackup(
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 backupsDb.runAllStoresReadWriteTx(async (tx) => {
await tx.backupMeta.add({
name,
});
@@ -552,7 +538,7 @@ async function listStoredBackups(
storedBackups: [],
};
const backupsDb = await openStoredBackupsDatabase(ws.idb);
- await backupsDb.mktxAll().runReadWrite(async (tx) => {
+ await backupsDb.runAllStoresReadWriteTx(async (tx) => {
await tx.backupMeta.iter().forEach((x) => {
storedBackups.storedBackups.push({
name: x.name,
@@ -567,7 +553,7 @@ async function deleteStoredBackup(
req: DeleteStoredBackupRequest,
): Promise<void> {
const backupsDb = await openStoredBackupsDatabase(ws.idb);
- await backupsDb.mktxAll().runReadWrite(async (tx) => {
+ await backupsDb.runAllStoresReadWriteTx(async (tx) => {
await tx.backupData.delete(req.name);
await tx.backupMeta.delete(req.name);
});
@@ -580,7 +566,7 @@ async function recoverStoredBackup(
logger.info(`Recovering stored backup ${req.name}`);
const { name } = req;
const backupsDb = await openStoredBackupsDatabase(ws.idb);
- const bd = await backupsDb.mktxAll().runReadWrite(async (tx) => {
+ const bd = await backupsDb.runAllStoresReadWriteTx(async (tx) => {
const backupMeta = tx.backupMeta.get(name);
if (!backupMeta) {
throw Error("backup not found");
@@ -1526,7 +1512,20 @@ class InternalWalletStateImpl implements InternalWalletState {
async getTransactionState(
ws: InternalWalletState,
- tx: GetReadOnlyAccess<typeof WalletStoresV1>,
+ tx: WalletDbReadOnlyTransaction<
+ [
+ "depositGroups",
+ "withdrawalGroups",
+ "purchases",
+ "refundGroups",
+ "peerPullCredit",
+ "peerPullDebit",
+ "peerPushDebit",
+ "peerPushCredit",
+ "rewards",
+ "refreshGroups",
+ ]
+ >,
transactionId: string,
): Promise<TransactionState | undefined> {
const parsedTxId = parseTransactionIdentifier(transactionId);
@@ -1613,9 +1612,7 @@ class InternalWalletStateImpl implements InternalWalletState {
async getDenomInfo(
ws: InternalWalletState,
- tx: GetReadWriteAccess<{
- denominations: typeof WalletStoresV1.denominations;
- }>,
+ tx: WalletDbReadWriteTransaction<["denominations"]>,
exchangeBaseUrl: string,
denomPubHash: string,
): Promise<DenominationInfo | undefined> {