diff options
author | Florian Dold <florian@dold.me> | 2023-12-11 20:01:28 +0100 |
---|---|---|
committer | Florian Dold <florian@dold.me> | 2023-12-12 15:42:34 +0100 |
commit | e31f18b8f129adb9cbe33158297a9cff56a7143e (patch) | |
tree | fc960e069a08ca1924a79c154f5ced26db709348 /packages/taler-wallet-core/src/wallet.ts | |
parent | 055645e17aa9424f299aa04f686de7574ab437c7 (diff) | |
download | wallet-core-e31f18b8f129adb9cbe33158297a9cff56a7143e.tar.xz |
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.ts | 262 |
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 = { |