aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFlorian Dold <florian@dold.me>2022-10-05 18:31:56 +0200
committerFlorian Dold <florian@dold.me>2022-10-05 18:31:56 +0200
commit957f9a5efb26194a7911cdaf722502ba09e5bd58 (patch)
treed7edfb20814d8f9cf418457de0a3ff86c7690308
parent99ace8b7d24416f2b184d66006c89b61935e132e (diff)
wallet-core: fix default auditor/exchange loading logic
-rw-r--r--packages/taler-wallet-cli/src/index.ts7
-rw-r--r--packages/taler-wallet-core/src/crypto/workers/worker-common.ts1
-rw-r--r--packages/taler-wallet-core/src/db.ts6
-rw-r--r--packages/taler-wallet-core/src/operations/backup/import.ts2
-rw-r--r--packages/taler-wallet-core/src/operations/exchanges.ts59
-rw-r--r--packages/taler-wallet-core/src/operations/pending.ts1
-rw-r--r--packages/taler-wallet-core/src/operations/withdraw.ts21
-rw-r--r--packages/taler-wallet-core/src/wallet.ts45
8 files changed, 74 insertions, 68 deletions
diff --git a/packages/taler-wallet-cli/src/index.ts b/packages/taler-wallet-cli/src/index.ts
index c1afbe15c..b55231b79 100644
--- a/packages/taler-wallet-cli/src/index.ts
+++ b/packages/taler-wallet-cli/src/index.ts
@@ -255,9 +255,9 @@ async function withWallet<T>(
console.error("Error details:", JSON.stringify(ed, undefined, 2));
process.exit(1);
} finally {
- logger.info("operation with wallet finished, stopping");
+ logger.trace("operation with wallet finished, stopping");
wallet.stop();
- logger.info("stopped wallet");
+ logger.trace("stopped wallet");
}
}
@@ -495,6 +495,7 @@ walletCli
talerWithdrawUri: uri,
},
);
+ console.log("accept withdrawal response", res);
}
break;
default:
@@ -731,7 +732,7 @@ const advancedCli = walletCli.subcommand("advancedArgs", "advanced", {
advancedCli
.subcommand("init", "init", {
- help: "Initialize the wallet (with DB) and exit."
+ help: "Initialize the wallet (with DB) and exit.",
})
.action(async (args) => {
await withWallet(args, async () => {});
diff --git a/packages/taler-wallet-core/src/crypto/workers/worker-common.ts b/packages/taler-wallet-core/src/crypto/workers/worker-common.ts
index dae6d1e28..459033526 100644
--- a/packages/taler-wallet-core/src/crypto/workers/worker-common.ts
+++ b/packages/taler-wallet-core/src/crypto/workers/worker-common.ts
@@ -37,7 +37,6 @@ export async function processRequestWithImpl(
reqMsg: CryptoWorkerRequestMessage,
impl: TalerCryptoInterfaceR,
): Promise<CryptoWorkerResponseMessage> {
- logger.info(`processing crypto request ${j2s(reqMsg)}`);
if (typeof reqMsg !== "object") {
logger.error("request must be an object");
return {
diff --git a/packages/taler-wallet-core/src/db.ts b/packages/taler-wallet-core/src/db.ts
index f8fddb255..16ae2cf8d 100644
--- a/packages/taler-wallet-core/src/db.ts
+++ b/packages/taler-wallet-core/src/db.ts
@@ -510,7 +510,7 @@ export interface ExchangeRecord {
permanent: boolean;
/**
- * Last time when the exchange was updated.
+ * Last time when the exchange was updated (both /keys and /wire).
*/
lastUpdate: TalerProtocolTimestamp | undefined;
@@ -521,6 +521,10 @@ export interface ExchangeRecord {
*/
nextUpdate: TalerProtocolTimestamp;
+ lastKeysEtag: string | undefined;
+
+ lastWireEtag: string | undefined;
+
/**
* Next time that we should check if coins need to be refreshed.
*
diff --git a/packages/taler-wallet-core/src/operations/backup/import.ts b/packages/taler-wallet-core/src/operations/backup/import.ts
index 9997dd09d..fb747ef1c 100644
--- a/packages/taler-wallet-core/src/operations/backup/import.ts
+++ b/packages/taler-wallet-core/src/operations/backup/import.ts
@@ -362,6 +362,8 @@ export async function importBackup(
lastUpdate: undefined,
nextUpdate: TalerProtocolTimestamp.now(),
nextRefreshCheck: TalerProtocolTimestamp.now(),
+ lastKeysEtag: undefined,
+ lastWireEtag: undefined,
});
}
diff --git a/packages/taler-wallet-core/src/operations/exchanges.ts b/packages/taler-wallet-core/src/operations/exchanges.ts
index 82222a5c4..60a4e91dd 100644
--- a/packages/taler-wallet-core/src/operations/exchanges.ts
+++ b/packages/taler-wallet-core/src/operations/exchanges.ts
@@ -63,7 +63,11 @@ import {
readSuccessResponseJsonOrThrow,
readSuccessResponseTextOrThrow,
} from "../util/http.js";
-import { DbAccess, GetReadOnlyAccess } from "../util/query.js";
+import {
+ DbAccess,
+ GetReadOnlyAccess,
+ GetReadWriteAccess,
+} from "../util/query.js";
import {
OperationAttemptResult,
OperationAttemptResultType,
@@ -316,33 +320,35 @@ async function downloadExchangeWireInfo(
return wireInfo;
}
-async function provideExchangeRecord(
+export async function provideExchangeRecordInTx(
ws: InternalWalletState,
+ tx: GetReadWriteAccess<{
+ exchanges: typeof WalletStoresV1.exchanges;
+ exchangeDetails: typeof WalletStoresV1.exchangeDetails;
+ }>,
baseUrl: string,
now: AbsoluteTime,
): Promise<{
exchange: ExchangeRecord;
exchangeDetails: ExchangeDetailsRecord | undefined;
}> {
- return await ws.db
- .mktx((x) => [x.exchanges, x.exchangeDetails])
- .runReadWrite(async (tx) => {
- let exchange = await tx.exchanges.get(baseUrl);
- if (!exchange) {
- const r: ExchangeRecord = {
- permanent: true,
- baseUrl: baseUrl,
- detailsPointer: undefined,
- lastUpdate: undefined,
- nextUpdate: AbsoluteTime.toTimestamp(now),
- nextRefreshCheck: AbsoluteTime.toTimestamp(now),
- };
- await tx.exchanges.put(r);
- exchange = r;
- }
- const exchangeDetails = await getExchangeDetails(tx, baseUrl);
- return { exchange, exchangeDetails };
- });
+ let exchange = await tx.exchanges.get(baseUrl);
+ if (!exchange) {
+ const r: ExchangeRecord = {
+ permanent: true,
+ baseUrl: baseUrl,
+ detailsPointer: undefined,
+ lastUpdate: undefined,
+ nextUpdate: AbsoluteTime.toTimestamp(now),
+ nextRefreshCheck: AbsoluteTime.toTimestamp(now),
+ lastKeysEtag: undefined,
+ lastWireEtag: undefined,
+ };
+ await tx.exchanges.put(r);
+ exchange = r;
+ }
+ const exchangeDetails = await getExchangeDetails(tx, baseUrl);
+ return { exchange, exchangeDetails };
}
interface ExchangeKeysDownloadResult {
@@ -499,15 +505,16 @@ export async function updateExchangeFromUrlHandler(
> {
const forceNow = options.forceNow ?? false;
logger.info(`updating exchange info for ${baseUrl}, forced: ${forceNow}`);
+ console.trace("here");
const now = AbsoluteTime.now();
baseUrl = canonicalizeBaseUrl(baseUrl);
- const { exchange, exchangeDetails } = await provideExchangeRecord(
- ws,
- baseUrl,
- now,
- );
+ const { exchange, exchangeDetails } = await ws.db
+ .mktx((x) => [x.exchanges, x.exchangeDetails])
+ .runReadWrite(async (tx) => {
+ return provideExchangeRecordInTx(ws, tx, baseUrl, now);
+ });
if (
!forceNow &&
diff --git a/packages/taler-wallet-core/src/operations/pending.ts b/packages/taler-wallet-core/src/operations/pending.ts
index 0dcd09e25..156feadbb 100644
--- a/packages/taler-wallet-core/src/operations/pending.ts
+++ b/packages/taler-wallet-core/src/operations/pending.ts
@@ -50,6 +50,7 @@ async function gatherExchangePending(
now: AbsoluteTime,
resp: PendingOperationsResponse,
): Promise<void> {
+ // FIXME: We should do a range query here based on the update time.
await tx.exchanges.iter().forEachAsync(async (exch) => {
const opTag = RetryTags.forExchangeUpdate(exch);
let opr = await tx.operationRetries.get(opTag);
diff --git a/packages/taler-wallet-core/src/operations/withdraw.ts b/packages/taler-wallet-core/src/operations/withdraw.ts
index 143f9ce33..d768bbeb2 100644
--- a/packages/taler-wallet-core/src/operations/withdraw.ts
+++ b/packages/taler-wallet-core/src/operations/withdraw.ts
@@ -1071,7 +1071,7 @@ export async function processWithdrawalGroup(
case WithdrawalGroupStatus.QueryingStatus: {
const doQueryAsync = async () => {
if (ws.stopped) {
- logger.info("not long-polling reserve, wallet already stopped");
+ logger.trace("not long-polling reserve, wallet already stopped");
await storeOperationPending(ws, retryTag);
return;
}
@@ -1080,7 +1080,7 @@ export async function processWithdrawalGroup(
try {
ws.activeLongpoll[retryTag] = {
cancel: () => {
- logger.info("cancel of reserve longpoll requested");
+ logger.trace("cancel of reserve longpoll requested");
cts.cancel();
},
};
@@ -1094,16 +1094,13 @@ export async function processWithdrawalGroup(
return;
}
delete ws.activeLongpoll[retryTag];
- logger.info(
- `active longpoll keys (2) ${Object.keys(ws.activeLongpoll)}`,
- );
if (!res.ready) {
await storeOperationPending(ws, retryTag);
}
ws.latch.trigger();
};
doQueryAsync();
- logger.info(
+ logger.trace(
"returning early from withdrawal for long-polling in background",
);
return {
@@ -1918,12 +1915,12 @@ export async function acceptWithdrawalFromUri(
);
}
- // Start withdrawal in the background.
- await processWithdrawalGroup(ws, withdrawalGroupId, { forceNow: true }).catch(
- (err) => {
- logger.error("Processing withdrawal (after creation) failed:", err);
- },
- );
+ // Start withdrawal in the background
+ processWithdrawalGroup(ws, withdrawalGroupId, {
+ forceNow: true,
+ }).catch((err) => {
+ logger.error("Processing withdrawal (after creation) failed:", err);
+ });
return {
reservePub: withdrawalGroup.reservePub,
diff --git a/packages/taler-wallet-core/src/wallet.ts b/packages/taler-wallet-core/src/wallet.ts
index 129ee458f..61525e476 100644
--- a/packages/taler-wallet-core/src/wallet.ts
+++ b/packages/taler-wallet-core/src/wallet.ts
@@ -155,6 +155,7 @@ import {
getExchangeDetails,
getExchangeRequestTimeout,
getExchangeTrust,
+ provideExchangeRecordInTx,
updateExchangeFromUrl,
updateExchangeFromUrlHandler,
updateExchangeTermsOfService,
@@ -583,32 +584,26 @@ async function runTaskLoop(
*/
async function fillDefaults(ws: InternalWalletState): Promise<void> {
await ws.db
- .mktx((x) => [x.config, x.auditorTrust])
+ .mktx((x) => [x.config, x.auditorTrust, x.exchanges, x.exchangeDetails])
.runReadWrite(async (tx) => {
- let applied = false;
- await tx.config.iter().forEach((x) => {
- if (x.key == "currencyDefaultsApplied" && x.value == true) {
- applied = true;
- }
- });
- if (!applied) {
- for (const c of builtinAuditors) {
- await tx.auditorTrust.put(c);
- }
+ const appliedRec = await tx.config.get("currencyDefaultsApplied");
+ let alreadyApplied = appliedRec ? !!appliedRec.value : false;
+ if (alreadyApplied) {
+ logger.info("defaults already applied");
+ return;
+ }
+ for (const c of builtinAuditors) {
+ await tx.auditorTrust.put(c);
+ }
+ for (const baseUrl of builtinExchanges) {
+ const now = AbsoluteTime.now();
+ provideExchangeRecordInTx(ws, tx, baseUrl, now);
}
- // FIXME: make sure exchanges are added transactionally to
- // DB in first-time default application
+ await tx.config.put({
+ key: "currencyDefaultsApplied",
+ value: true,
+ });
});
-
- for (const url of builtinExchanges) {
- try {
- await updateExchangeFromUrl(ws, url, { forceNow: true });
- } catch (e) {
- logger.warn(
- `could not update builtin exchange ${url} during wallet initialization`,
- );
- }
- }
}
async function getExchangeTos(
@@ -1719,12 +1714,12 @@ class InternalWalletStateImpl implements InternalWalletState {
* Stop ongoing processing.
*/
stop(): void {
- logger.info("stopping (at internal wallet state)");
+ logger.trace("stopping (at internal wallet state)");
this.stopped = true;
this.timerGroup.stopCurrentAndFutureTimers();
this.cryptoDispatcher.stop();
for (const key of Object.keys(this.activeLongpoll)) {
- logger.info(`cancelling active longpoll ${key}`);
+ logger.trace(`cancelling active longpoll ${key}`);
this.activeLongpoll[key].cancel();
}
}