summaryrefslogtreecommitdiff
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.ts431
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,