diff options
Diffstat (limited to 'src/operations/exchanges.ts')
-rw-r--r-- | src/operations/exchanges.ts | 118 |
1 files changed, 35 insertions, 83 deletions
diff --git a/src/operations/exchanges.ts b/src/operations/exchanges.ts index 6f5ff1d30..ff2cd3da6 100644 --- a/src/operations/exchanges.ts +++ b/src/operations/exchanges.ts @@ -16,12 +16,11 @@ import { InternalWalletState } from "./state"; import { - ExchangeKeysJson, Denomination, codecForExchangeKeysJson, codecForExchangeWireJson, } from "../types/talerTypes"; -import { OperationError } from "../types/walletTypes"; +import { OperationErrorDetails } from "../types/walletTypes"; import { ExchangeRecord, ExchangeUpdateStatus, @@ -38,6 +37,7 @@ import { parsePaytoUri } from "../util/payto"; import { OperationFailedAndReportedError, guardOperationException, + makeErrorDetails, } from "./errors"; import { WALLET_CACHE_BREAKER_CLIENT_VERSION, @@ -46,6 +46,11 @@ import { import { getTimestampNow } from "../util/time"; import { compare } from "../util/libtoolVersion"; import { createRecoupGroup, processRecoupGroup } from "./recoup"; +import { TalerErrorCode } from "../TalerErrorCode"; +import { + readSuccessResponseJsonOrThrow, + readSuccessResponseTextOrThrow, +} from "../util/http"; async function denominationRecordFromKeys( ws: InternalWalletState, @@ -77,7 +82,7 @@ async function denominationRecordFromKeys( async function setExchangeError( ws: InternalWalletState, baseUrl: string, - err: OperationError, + err: OperationErrorDetails, ): Promise<void> { console.log(`last error for exchange ${baseUrl}:`, err); const mut = (exchange: ExchangeRecord): ExchangeRecord => { @@ -102,88 +107,40 @@ async function updateExchangeWithKeys( if (existingExchangeRecord?.updateStatus != ExchangeUpdateStatus.FetchKeys) { return; } + const keysUrl = new URL("keys", baseUrl); keysUrl.searchParams.set("cacheBreaker", WALLET_CACHE_BREAKER_CLIENT_VERSION); - let keysResp; - try { - const r = await ws.http.get(keysUrl.href); - if (r.status !== 200) { - throw Error(`unexpected status for keys: ${r.status}`); - } - keysResp = await r.json(); - } catch (e) { - const m = `Fetching keys failed: ${e.message}`; - const opErr = { - type: "network", - details: { - requestUrl: e.config?.url, - }, - message: m, - }; - await setExchangeError(ws, baseUrl, opErr); - throw new OperationFailedAndReportedError(opErr); - } - let exchangeKeysJson: ExchangeKeysJson; - try { - exchangeKeysJson = codecForExchangeKeysJson().decode(keysResp); - } catch (e) { - const m = `Parsing /keys response failed: ${e.message}`; - const opErr = { - type: "protocol-violation", - details: {}, - message: m, - }; - await setExchangeError(ws, baseUrl, opErr); - throw new OperationFailedAndReportedError(opErr); - } - - const lastUpdateTimestamp = exchangeKeysJson.list_issue_date; - if (!lastUpdateTimestamp) { - const m = `Parsing /keys response failed: invalid list_issue_date.`; - const opErr = { - type: "protocol-violation", - details: {}, - message: m, - }; - await setExchangeError(ws, baseUrl, opErr); - throw new OperationFailedAndReportedError(opErr); - } + const resp = await ws.http.get(keysUrl.href); + const exchangeKeysJson = await readSuccessResponseJsonOrThrow( + resp, + codecForExchangeKeysJson(), + ); if (exchangeKeysJson.denoms.length === 0) { - const m = "exchange doesn't offer any denominations"; - const opErr = { - type: "protocol-violation", - details: {}, - message: m, - }; + const opErr = makeErrorDetails( + TalerErrorCode.WALLET_EXCHANGE_DENOMINATIONS_INSUFFICIENT, + "exchange doesn't offer any denominations", + { + exchangeBaseUrl: baseUrl, + }, + ); await setExchangeError(ws, baseUrl, opErr); throw new OperationFailedAndReportedError(opErr); } const protocolVersion = exchangeKeysJson.version; - if (!protocolVersion) { - const m = "outdate exchange, no version in /keys response"; - const opErr = { - type: "protocol-violation", - details: {}, - message: m, - }; - await setExchangeError(ws, baseUrl, opErr); - throw new OperationFailedAndReportedError(opErr); - } const versionRes = compare(WALLET_EXCHANGE_PROTOCOL_VERSION, protocolVersion); if (versionRes?.compatible != true) { - const m = "exchange protocol version not compatible with wallet"; - const opErr = { - type: "protocol-incompatible", - details: { + const opErr = makeErrorDetails( + TalerErrorCode.WALLET_EXCHANGE_PROTOCOL_VERSION_INCOMPATIBLE, + "exchange protocol version not compatible with wallet", + { exchangeProtocolVersion: protocolVersion, walletProtocolVersion: WALLET_EXCHANGE_PROTOCOL_VERSION, }, - message: m, - }; + ); await setExchangeError(ws, baseUrl, opErr); throw new OperationFailedAndReportedError(opErr); } @@ -197,6 +154,8 @@ async function updateExchangeWithKeys( ), ); + const lastUpdateTimestamp = getTimestampNow(); + const recoupGroupId: string | undefined = undefined; await ws.db.runWithWriteTransaction( @@ -331,11 +290,7 @@ async function updateExchangeWithTermsOfService( }; const resp = await ws.http.get(reqUrl.href, { headers }); - if (resp.status !== 200) { - throw Error(`/terms response has unexpected status code (${resp.status})`); - } - - const tosText = await resp.text(); + const tosText = await readSuccessResponseTextOrThrow(resp); const tosEtag = resp.headers.get("etag") || undefined; await ws.db.runWithWriteTransaction([Stores.exchanges], async (tx) => { @@ -393,14 +348,11 @@ async function updateExchangeWithWireInfo( reqUrl.searchParams.set("cacheBreaker", WALLET_CACHE_BREAKER_CLIENT_VERSION); const resp = await ws.http.get(reqUrl.href); - if (resp.status !== 200) { - throw Error(`/wire response has unexpected status code (${resp.status})`); - } - const wiJson = await resp.json(); - if (!wiJson) { - throw Error("/wire response malformed"); - } - const wireInfo = codecForExchangeWireJson().decode(wiJson); + const wireInfo = await readSuccessResponseJsonOrThrow( + resp, + codecForExchangeWireJson(), + ); + for (const a of wireInfo.accounts) { console.log("validating exchange acct"); const isValid = await ws.cryptoApi.isValidWireAccount( @@ -461,7 +413,7 @@ export async function updateExchangeFromUrl( baseUrl: string, forceNow = false, ): Promise<ExchangeRecord> { - const onOpErr = (e: OperationError): Promise<void> => + const onOpErr = (e: OperationErrorDetails): Promise<void> => setExchangeError(ws, baseUrl, e); return await guardOperationException( () => updateExchangeFromUrlImpl(ws, baseUrl, forceNow), |