summaryrefslogtreecommitdiff
path: root/packages/taler-wallet-core/src/wallet.ts
diff options
context:
space:
mode:
authorFlorian Dold <florian@dold.me>2023-12-11 20:01:28 +0100
committerFlorian Dold <florian@dold.me>2023-12-12 15:42:34 +0100
commite31f18b8f129adb9cbe33158297a9cff56a7143e (patch)
treefc960e069a08ca1924a79c154f5ced26db709348 /packages/taler-wallet-core/src/wallet.ts
parent055645e17aa9424f299aa04f686de7574ab437c7 (diff)
downloadwallet-core-e31f18b8f129adb9cbe33158297a9cff56a7143e.tar.gz
wallet-core-e31f18b8f129adb9cbe33158297a9cff56a7143e.tar.bz2
wallet-core-e31f18b8f129adb9cbe33158297a9cff56a7143e.zip
wallet-core: towards better DD48 support
Diffstat (limited to 'packages/taler-wallet-core/src/wallet.ts')
-rw-r--r--packages/taler-wallet-core/src/wallet.ts262
1 files changed, 20 insertions, 242 deletions
diff --git a/packages/taler-wallet-core/src/wallet.ts b/packages/taler-wallet-core/src/wallet.ts
index 25cfd7f6f..c9612da5f 100644
--- a/packages/taler-wallet-core/src/wallet.ts
+++ b/packages/taler-wallet-core/src/wallet.ts
@@ -33,17 +33,10 @@ import {
CoreApiResponse,
CreateStoredBackupResponse,
DeleteStoredBackupRequest,
- DenomOperationMap,
DenominationInfo,
Duration,
- ExchangeDetailedResponse,
- ExchangeListItem,
- ExchangesListResponse,
ExchangesShortListResponse,
- FeeDescription,
GetCurrencySpecificationResponse,
- GetExchangeEntryByUrlResponse,
- GetExchangeTosResult,
InitResponse,
KnownBankAccounts,
KnownBankAccountsInfo,
@@ -194,7 +187,6 @@ import { getBalanceDetail, getBalances } from "./operations/balance.js";
import {
TaskIdentifiers,
TaskRunResult,
- getExchangeTosStatus,
makeExchangeListItem,
runTaskWithErrorReporting,
} from "./operations/common.js";
@@ -208,10 +200,11 @@ import {
import {
acceptExchangeTermsOfService,
addPresetExchangeEntry,
- downloadTosFromAcceptedFormat,
+ fetchFreshExchange,
+ getExchangeDetailedInfo,
getExchangeDetails,
- getExchangeRequestTimeout,
- updateExchangeFromUrl,
+ getExchangeTos,
+ getExchanges,
updateExchangeFromUrlHandler,
} from "./operations/exchanges.js";
import { getMerchantInfo } from "./operations/merchants.js";
@@ -296,11 +289,6 @@ import {
import { PendingTaskInfo, PendingTaskType } from "./pending-types.js";
import { assertUnreachable } from "./util/assertUnreachable.js";
import {
- createTimeline,
- selectBestForOverlappingDenominations,
- selectMinimumFee,
-} from "./util/denominations.js";
-import {
convertDepositAmount,
convertPeerPushAmount,
convertWithdrawalAmount,
@@ -520,12 +508,13 @@ async function runTaskLoop(
continue;
}
logger.trace(`running task ${p.id}`);
- await runTaskWithErrorReporting(ws, p.id, async () => {
+ const res = await runTaskWithErrorReporting(ws, p.id, async () => {
return await callOperationHandler(ws, p);
});
ws.notify({
type: NotificationType.PendingOperationProcessed,
id: p.id,
+ taskResultType: res.type,
});
if (ws.stopped) {
ws.isTaskLoopRunning = false;
@@ -549,6 +538,7 @@ async function runTaskLoop(
* already been applied.
*/
async function fillDefaults(ws: InternalWalletState): Promise<void> {
+ const notifications: WalletNotification[] = [];
await ws.db
.mktx((x) => [x.config, x.exchanges, x.exchangeDetails])
.runReadWrite(async (tx) => {
@@ -559,55 +549,23 @@ async function fillDefaults(ws: InternalWalletState): Promise<void> {
return;
}
for (const exch of ws.config.builtin.exchanges) {
- await addPresetExchangeEntry(
+ 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,
});
});
-}
-
-/**
- * Get the exchange ToS in the requested format.
- * Try to download in the accepted format not cached.
- */
-async function getExchangeTos(
- ws: InternalWalletState,
- exchangeBaseUrl: string,
- acceptedFormat?: string[],
-): Promise<GetExchangeTosResult> {
- // FIXME: download ToS in acceptable format if passed!
- const { exchangeDetails } = await updateExchangeFromUrl(ws, exchangeBaseUrl);
-
- const tosDownload = await downloadTosFromAcceptedFormat(
- ws,
- exchangeBaseUrl,
- getExchangeRequestTimeout(),
- acceptedFormat,
- );
-
- await ws.db
- .mktx((x) => [x.exchanges, x.exchangeDetails])
- .runReadWrite(async (tx) => {
- const d = await getExchangeDetails(tx, exchangeBaseUrl);
- if (d) {
- d.tosCurrentEtag = tosDownload.tosEtag;
- await tx.exchangeDetails.put(d);
- }
- });
-
- return {
- acceptedEtag: exchangeDetails.tosAccepted?.etag,
- currentEtag: tosDownload.tosEtag,
- content: tosDownload.tosText,
- contentType: tosDownload.tosContentType,
- tosStatus: getExchangeTosStatus(exchangeDetails),
- };
+ for (const notif of notifications) {
+ ws.notify(notif);
+ }
}
/**
@@ -680,185 +638,6 @@ async function forgetKnownBankAccounts(
return;
}
-async function getExchanges(
- ws: InternalWalletState,
-): Promise<ExchangesListResponse> {
- const exchanges: ExchangeListItem[] = [];
- await ws.db
- .mktx((x) => [
- x.exchanges,
- x.exchangeDetails,
- x.denominations,
- x.operationRetries,
- ])
- .runReadOnly(async (tx) => {
- const exchangeRecords = await tx.exchanges.iter().toArray();
- for (const r of exchangeRecords) {
- const exchangeDetails = await getExchangeDetails(tx, r.baseUrl);
- const opRetryRecord = await tx.operationRetries.get(
- TaskIdentifiers.forExchangeUpdate(r),
- );
- exchanges.push(
- makeExchangeListItem(r, exchangeDetails, opRetryRecord?.lastError),
- );
- }
- });
- return { exchanges };
-}
-
-async function getExchangeDetailedInfo(
- ws: InternalWalletState,
- exchangeBaseurl: string,
-): Promise<ExchangeDetailedResponse> {
- //TODO: should we use the forceUpdate parameter?
- const exchange = await ws.db
- .mktx((x) => [x.exchanges, x.exchangeDetails, x.denominations])
- .runReadOnly(async (tx) => {
- const ex = await tx.exchanges.get(exchangeBaseurl);
- const dp = ex?.detailsPointer;
- if (!dp) {
- return;
- }
- const { currency } = dp;
- const exchangeDetails = await getExchangeDetails(tx, ex.baseUrl);
- if (!exchangeDetails) {
- return;
- }
-
- const denominationRecords =
- await tx.denominations.indexes.byExchangeBaseUrl
- .iter(ex.baseUrl)
- .toArray();
-
- if (!denominationRecords) {
- return;
- }
-
- const denominations: DenominationInfo[] = denominationRecords.map((x) =>
- DenominationRecord.toDenomInfo(x),
- );
-
- return {
- info: {
- exchangeBaseUrl: ex.baseUrl,
- currency,
- paytoUris: exchangeDetails.wireInfo.accounts.map((x) => x.payto_uri),
- auditors: exchangeDetails.auditors,
- wireInfo: exchangeDetails.wireInfo,
- globalFees: exchangeDetails.globalFees,
- },
- denominations,
- };
- });
-
- if (!exchange) {
- throw Error(`exchange with base url "${exchangeBaseurl}" not found`);
- }
-
- const denoms = exchange.denominations.map((d) => ({
- ...d,
- group: Amounts.stringifyValue(d.value),
- }));
- const denomFees: DenomOperationMap<FeeDescription[]> = {
- deposit: createTimeline(
- denoms,
- "denomPubHash",
- "stampStart",
- "stampExpireDeposit",
- "feeDeposit",
- "group",
- selectBestForOverlappingDenominations,
- ),
- refresh: createTimeline(
- denoms,
- "denomPubHash",
- "stampStart",
- "stampExpireWithdraw",
- "feeRefresh",
- "group",
- selectBestForOverlappingDenominations,
- ),
- refund: createTimeline(
- denoms,
- "denomPubHash",
- "stampStart",
- "stampExpireWithdraw",
- "feeRefund",
- "group",
- selectBestForOverlappingDenominations,
- ),
- withdraw: createTimeline(
- denoms,
- "denomPubHash",
- "stampStart",
- "stampExpireWithdraw",
- "feeWithdraw",
- "group",
- selectBestForOverlappingDenominations,
- ),
- };
-
- const transferFees = Object.entries(
- exchange.info.wireInfo.feesForType,
- ).reduce((prev, [wireType, infoForType]) => {
- const feesByGroup = [
- ...infoForType.map((w) => ({
- ...w,
- fee: Amounts.stringify(w.closingFee),
- group: "closing",
- })),
- ...infoForType.map((w) => ({ ...w, fee: w.wireFee, group: "wire" })),
- ];
- prev[wireType] = createTimeline(
- feesByGroup,
- "sig",
- "startStamp",
- "endStamp",
- "fee",
- "group",
- selectMinimumFee,
- );
- return prev;
- }, {} as Record<string, FeeDescription[]>);
-
- const globalFeesByGroup = [
- ...exchange.info.globalFees.map((w) => ({
- ...w,
- fee: w.accountFee,
- group: "account",
- })),
- ...exchange.info.globalFees.map((w) => ({
- ...w,
- fee: w.historyFee,
- group: "history",
- })),
- ...exchange.info.globalFees.map((w) => ({
- ...w,
- fee: w.purseFee,
- group: "purse",
- })),
- ];
-
- const globalFees = createTimeline(
- globalFeesByGroup,
- "signature",
- "startDate",
- "endDate",
- "fee",
- "group",
- selectMinimumFee,
- );
-
- return {
- exchange: {
- ...exchange.info,
- denomFees,
- transferFees,
- globalFees,
- },
- };
-}
-
async function setCoinSuspended(
ws: InternalWalletState,
coinPub: string,
@@ -1059,7 +838,7 @@ async function handlePrepareWithdrawExchange(
throw Error("expected a taler://withdraw-exchange URI");
}
const exchangeBaseUrl = parsedUri.exchangeBaseUrl;
- const exchange = await updateExchangeFromUrl(ws, exchangeBaseUrl);
+ const exchange = await fetchFreshExchange(ws, exchangeBaseUrl);
if (exchange.exchangeDetails.masterPublicKey != parsedUri.exchangePub) {
throw Error("mismatch of exchange master public key (URI vs actual)");
}
@@ -1166,15 +945,14 @@ async function dispatchRequestInternal<Op extends WalletApiOperation>(
}
case WalletApiOperation.AddExchange: {
const req = codecForAddExchangeRequest().decode(payload);
- await updateExchangeFromUrl(ws, req.exchangeBaseUrl, {
- checkMasterPub: req.masterPub,
- forceNow: req.forceUpdate,
- });
+ await fetchFreshExchange(ws, req.exchangeBaseUrl);
return {};
}
case WalletApiOperation.UpdateExchangeEntry: {
const req = codecForUpdateExchangeEntryRequest().decode(payload);
- await updateExchangeFromUrl(ws, req.exchangeBaseUrl, {});
+ await fetchFreshExchange(ws, req.exchangeBaseUrl, {
+ forceUpdate: true,
+ });
return {};
}
case WalletApiOperation.ListExchanges: {
@@ -1896,7 +1674,7 @@ class InternalWalletStateImpl implements InternalWalletState {
exchangeOps: ExchangeOperations = {
getExchangeDetails,
- updateExchangeFromUrl,
+ updateExchangeFromUrl: fetchFreshExchange,
};
recoupOps: RecoupOperations = {