aboutsummaryrefslogtreecommitdiff
path: root/src/wallet-impl
diff options
context:
space:
mode:
Diffstat (limited to 'src/wallet-impl')
-rw-r--r--src/wallet-impl/exchanges.ts69
-rw-r--r--src/wallet-impl/tip.ts4
-rw-r--r--src/wallet-impl/withdraw.ts37
3 files changed, 88 insertions, 22 deletions
diff --git a/src/wallet-impl/exchanges.ts b/src/wallet-impl/exchanges.ts
index 9810b9b91..1e5f86b4f 100644
--- a/src/wallet-impl/exchanges.ts
+++ b/src/wallet-impl/exchanges.ts
@@ -16,11 +16,7 @@
import { InternalWalletState } from "./state";
import { WALLET_CACHE_BREAKER_CLIENT_VERSION } from "../wallet";
-import {
- KeysJson,
- Denomination,
- ExchangeWireJson,
-} from "../talerTypes";
+import { KeysJson, Denomination, ExchangeWireJson } from "../talerTypes";
import { getTimestampNow, OperationError } from "../walletTypes";
import {
ExchangeRecord,
@@ -222,6 +218,62 @@ async function updateExchangeWithKeys(
);
}
+async function updateExchangeWithTermsOfService(
+ ws: InternalWalletState,
+ exchangeBaseUrl: string,
+) {
+ const exchange = await oneShotGet(ws.db, Stores.exchanges, exchangeBaseUrl);
+ if (!exchange) {
+ return;
+ }
+ if (exchange.updateStatus != ExchangeUpdateStatus.FETCH_TERMS) {
+ return;
+ }
+ const reqUrl = new URL("terms", exchangeBaseUrl);
+ reqUrl.searchParams.set("cacheBreaker", WALLET_CACHE_BREAKER_CLIENT_VERSION);
+ const headers = {
+ Accept: "text/plain",
+ };
+
+ 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 tosEtag = resp.headers.get("etag") || undefined;
+
+ await runWithWriteTransaction(ws.db, [Stores.exchanges], async tx => {
+ const r = await tx.get(Stores.exchanges, exchangeBaseUrl);
+ if (!r) {
+ return;
+ }
+ if (r.updateStatus != ExchangeUpdateStatus.FETCH_TERMS) {
+ return;
+ }
+ r.termsOfServiceText = tosText;
+ r.termsOfServiceLastEtag = tosEtag;
+ r.updateStatus = ExchangeUpdateStatus.FINISHED;
+ await tx.put(Stores.exchanges, r);
+ });
+}
+
+export async function acceptExchangeTermsOfService(
+ ws: InternalWalletState,
+ exchangeBaseUrl: string,
+ etag: string | undefined,
+) {
+ await runWithWriteTransaction(ws.db, [Stores.exchanges], async tx => {
+ const r = await tx.get(Stores.exchanges, exchangeBaseUrl);
+ if (!r) {
+ return;
+ }
+ r.termsOfServiceAcceptedEtag = etag;
+ r.termsOfServiceAcceptedTimestamp = getTimestampNow();
+ await tx.put(Stores.exchanges, r);
+ });
+}
+
/**
* Fetch wire information for an exchange and store it in the database.
*
@@ -309,7 +361,7 @@ async function updateExchangeWithWireInfo(
accounts: wireInfo.accounts,
feesForType: feesForType,
};
- r.updateStatus = ExchangeUpdateStatus.FINISHED;
+ r.updateStatus = ExchangeUpdateStatus.FETCH_TERMS;
r.lastError = undefined;
await tx.put(Stores.exchanges, r);
});
@@ -350,6 +402,10 @@ async function updateExchangeFromUrlImpl(
updateStarted: now,
updateReason: "initial",
timestampAdded: getTimestampNow(),
+ termsOfServiceAcceptedEtag: undefined,
+ termsOfServiceAcceptedTimestamp: undefined,
+ termsOfServiceLastEtag: undefined,
+ termsOfServiceText: undefined,
};
await oneShotPut(ws.db, Stores.exchanges, newExchangeRecord);
} else {
@@ -373,6 +429,7 @@ async function updateExchangeFromUrlImpl(
await updateExchangeWithKeys(ws, baseUrl);
await updateExchangeWithWireInfo(ws, baseUrl);
+ await updateExchangeWithTermsOfService(ws, baseUrl);
const updatedExchange = await oneShotGet(ws.db, Stores.exchanges, baseUrl);
diff --git a/src/wallet-impl/tip.ts b/src/wallet-impl/tip.ts
index 41463ab18..22ec37793 100644
--- a/src/wallet-impl/tip.ts
+++ b/src/wallet-impl/tip.ts
@@ -22,7 +22,7 @@ import { TipStatus, getTimestampNow, OperationError, NotificationType } from "..
import { TipPickupGetResponse, TipPlanchetDetail, TipResponse } from "../talerTypes";
import * as Amounts from "../util/amounts";
import { Stores, PlanchetRecord, WithdrawalSessionRecord, initRetryInfo, updateRetryInfoTimeout } from "../dbTypes";
-import { getWithdrawDetailsForAmount, getVerifiedWithdrawDenomList, processWithdrawSession } from "./withdraw";
+import { getExchangeWithdrawalInfo, getVerifiedWithdrawDenomList, processWithdrawSession } from "./withdraw";
import { getTalerStampSec, extractTalerStampOrThrow } from "../util/helpers";
import { updateExchangeFromUrl } from "./exchanges";
import { getRandomBytes, encodeCrock } from "../crypto/talerCrypto";
@@ -58,7 +58,7 @@ export async function getTipStatus(
]);
if (!tipRecord) {
- const withdrawDetails = await getWithdrawDetailsForAmount(
+ const withdrawDetails = await getExchangeWithdrawalInfo(
ws,
tipPickupStatus.exchange_url,
amount,
diff --git a/src/wallet-impl/withdraw.ts b/src/wallet-impl/withdraw.ts
index cd3989972..d8b2b599c 100644
--- a/src/wallet-impl/withdraw.ts
+++ b/src/wallet-impl/withdraw.ts
@@ -29,8 +29,8 @@ import * as Amounts from "../util/amounts";
import {
getTimestampNow,
AcceptWithdrawalResponse,
- DownloadedWithdrawInfo,
- ReserveCreationInfo,
+ BankWithdrawDetails,
+ ExchangeWithdrawDetails,
WithdrawDetails,
OperationError,
NotificationType,
@@ -106,12 +106,12 @@ export function getWithdrawDenomList(
/**
* Get information about a withdrawal from
- * a taler://withdraw URI.
+ * a taler://withdraw URI by asking the bank.
*/
-export async function getWithdrawalInfo(
+async function getBankWithdrawalInfo(
ws: InternalWalletState,
talerWithdrawUri: string,
-): Promise<DownloadedWithdrawInfo> {
+): Promise<BankWithdrawDetails> {
const uriResult = parseWithdrawUri(talerWithdrawUri);
if (!uriResult) {
throw Error("can't parse URL");
@@ -140,7 +140,7 @@ export async function acceptWithdrawal(
talerWithdrawUri: string,
selectedExchange: string,
): Promise<AcceptWithdrawalResponse> {
- const withdrawInfo = await getWithdrawalInfo(ws, talerWithdrawUri);
+ const withdrawInfo = await getBankWithdrawalInfo(ws, talerWithdrawUri);
const exchangeWire = await getExchangePaytoUri(
ws,
selectedExchange,
@@ -572,11 +572,11 @@ async function processWithdrawSessionImpl(
return;
}
-export async function getWithdrawDetailsForAmount(
+export async function getExchangeWithdrawalInfo(
ws: InternalWalletState,
baseUrl: string,
amount: AmountJson,
-): Promise<ReserveCreationInfo> {
+): Promise<ExchangeWithdrawDetails> {
const exchangeInfo = await updateExchangeFromUrl(ws, baseUrl);
const exchangeDetails = exchangeInfo.details;
if (!exchangeDetails) {
@@ -650,7 +650,15 @@ export async function getWithdrawDetailsForAmount(
}
}
- const ret: ReserveCreationInfo = {
+ let tosAccepted = false;
+
+ if (exchangeInfo.termsOfServiceAcceptedTimestamp) {
+ if (exchangeInfo.termsOfServiceAcceptedEtag == exchangeInfo.termsOfServiceLastEtag) {
+ tosAccepted = true;
+ }
+ }
+
+ const ret: ExchangeWithdrawDetails = {
earliestDepositExpiration,
exchangeInfo,
exchangeWireAccounts,
@@ -665,6 +673,7 @@ export async function getWithdrawDetailsForAmount(
walletVersion: WALLET_PROTOCOL_VERSION,
wireFees: exchangeWireInfo,
withdrawFee: acc,
+ termsOfServiceAccepted: tosAccepted,
};
return ret;
}
@@ -674,17 +683,17 @@ export async function getWithdrawDetailsForUri(
talerWithdrawUri: string,
maybeSelectedExchange?: string,
): Promise<WithdrawDetails> {
- const info = await getWithdrawalInfo(ws, talerWithdrawUri);
- let rci: ReserveCreationInfo | undefined = undefined;
+ const info = await getBankWithdrawalInfo(ws, talerWithdrawUri);
+ let rci: ExchangeWithdrawDetails | undefined = undefined;
if (maybeSelectedExchange) {
- rci = await getWithdrawDetailsForAmount(
+ rci = await getExchangeWithdrawalInfo(
ws,
maybeSelectedExchange,
info.amount,
);
}
return {
- withdrawInfo: info,
- reserveCreationInfo: rci,
+ bankWithdrawDetails: info,
+ exchangeWithdrawDetails: rci,
};
}