fixing tos request
This commit is contained in:
parent
021d508337
commit
fbf501e727
@ -578,7 +578,7 @@ export interface GetExchangeTosResult {
|
||||
/**
|
||||
* Markdown version of the current ToS.
|
||||
*/
|
||||
tos: string;
|
||||
content: string;
|
||||
|
||||
/**
|
||||
* Version tag of the current ToS.
|
||||
@ -590,6 +590,11 @@ export interface GetExchangeTosResult {
|
||||
* if any.
|
||||
*/
|
||||
acceptedEtag: string | undefined;
|
||||
|
||||
/**
|
||||
* Accepted content type
|
||||
*/
|
||||
contentType: string;
|
||||
}
|
||||
|
||||
export interface TestPayArgs {
|
||||
@ -648,11 +653,13 @@ export const codecForForceExchangeUpdateRequest = (): Codec<AddExchangeRequest>
|
||||
|
||||
export interface GetExchangeTosRequest {
|
||||
exchangeBaseUrl: string;
|
||||
acceptedFormat?: string[];
|
||||
}
|
||||
|
||||
export const codecForGetExchangeTosRequest = (): Codec<GetExchangeTosRequest> =>
|
||||
buildCodecForObject<GetExchangeTosRequest>()
|
||||
.property("exchangeBaseUrl", codecForString())
|
||||
.property("acceptedFormat", codecOptional(codecForList(codecForString())))
|
||||
.build("GetExchangeTosRequest");
|
||||
|
||||
export interface AcceptManualWithdrawalRequest {
|
||||
|
@ -71,6 +71,7 @@ export interface ExchangeOperations {
|
||||
updateExchangeFromUrl(
|
||||
ws: InternalWalletState,
|
||||
baseUrl: string,
|
||||
acceptedFormat?: string[],
|
||||
forceNow?: boolean,
|
||||
): Promise<{
|
||||
exchange: ExchangeRecord;
|
||||
|
@ -278,6 +278,7 @@ async function downloadExchangeWithWireInfo(
|
||||
export async function updateExchangeFromUrl(
|
||||
ws: InternalWalletState,
|
||||
baseUrl: string,
|
||||
acceptedFormat?: string[],
|
||||
forceNow = false,
|
||||
): Promise<{
|
||||
exchange: ExchangeRecord;
|
||||
@ -286,7 +287,7 @@ export async function updateExchangeFromUrl(
|
||||
const onOpErr = (e: TalerErrorDetails): Promise<void> =>
|
||||
handleExchangeUpdateError(ws, baseUrl, e);
|
||||
return await guardOperationException(
|
||||
() => updateExchangeFromUrlImpl(ws, baseUrl, forceNow),
|
||||
() => updateExchangeFromUrlImpl(ws, baseUrl, acceptedFormat, forceNow),
|
||||
onOpErr,
|
||||
);
|
||||
}
|
||||
@ -411,6 +412,7 @@ async function downloadKeysInfo(
|
||||
async function updateExchangeFromUrlImpl(
|
||||
ws: InternalWalletState,
|
||||
baseUrl: string,
|
||||
acceptedFormat?: string[],
|
||||
forceNow = false,
|
||||
): Promise<{
|
||||
exchange: ExchangeRecord;
|
||||
@ -468,7 +470,23 @@ async function updateExchangeFromUrlImpl(
|
||||
|
||||
logger.info("finished validating exchange /wire info");
|
||||
|
||||
const tosDownload = await downloadExchangeWithTermsOfService(
|
||||
let tosFound: ExchangeTosDownloadResult | undefined;
|
||||
//Remove this when exchange supports multiple content-type in accept header
|
||||
if (acceptedFormat) for (const format of acceptedFormat) {
|
||||
const resp = await downloadExchangeWithTermsOfService(
|
||||
baseUrl,
|
||||
ws.http,
|
||||
timeout,
|
||||
format
|
||||
);
|
||||
if (resp.tosContentType === format) {
|
||||
tosFound = resp
|
||||
break
|
||||
}
|
||||
}
|
||||
// If none of the specified format was found try text/plain
|
||||
const tosDownload = tosFound !== undefined ? tosFound :
|
||||
await downloadExchangeWithTermsOfService(
|
||||
baseUrl,
|
||||
ws.http,
|
||||
timeout,
|
||||
|
@ -920,7 +920,7 @@ export async function autoRefresh(
|
||||
exchangeBaseUrl: string,
|
||||
): Promise<void> {
|
||||
logger.info(`doing auto-refresh check for '${exchangeBaseUrl}'`);
|
||||
await updateExchangeFromUrl(ws, exchangeBaseUrl, true);
|
||||
await updateExchangeFromUrl(ws, exchangeBaseUrl, undefined, true);
|
||||
let minCheckThreshold = timestampAddDuration(
|
||||
getTimestampNow(),
|
||||
durationFromSpec({ days: 1 }),
|
||||
|
@ -66,8 +66,6 @@ import {
|
||||
WALLET_BANK_INTEGRATION_PROTOCOL_VERSION,
|
||||
WALLET_EXCHANGE_PROTOCOL_VERSION,
|
||||
} from "../versions.js";
|
||||
import { stringify } from "querystring";
|
||||
import { downloadExchangeWithTermsOfService, ExchangeTosDownloadResult } from "./exchanges";
|
||||
|
||||
/**
|
||||
* Logger for this file.
|
||||
@ -133,11 +131,6 @@ export interface ExchangeWithdrawDetails {
|
||||
*/
|
||||
termsOfServiceAccepted: boolean;
|
||||
|
||||
/**
|
||||
* Tos
|
||||
*/
|
||||
tosRequested: ExchangeTosDownloadResult | undefined
|
||||
|
||||
/**
|
||||
* The exchange is trusted directly.
|
||||
*/
|
||||
@ -937,7 +930,6 @@ export async function getExchangeWithdrawalInfo(
|
||||
ws: InternalWalletState,
|
||||
baseUrl: string,
|
||||
amount: AmountJson,
|
||||
tosAcceptedFormat?: string[],
|
||||
): Promise<ExchangeWithdrawDetails> {
|
||||
const {
|
||||
exchange,
|
||||
@ -1004,34 +996,6 @@ export async function getExchangeWithdrawalInfo(
|
||||
}
|
||||
}
|
||||
|
||||
const noTosDownloaded =
|
||||
exchangeDetails.termsOfServiceContentType === undefined ||
|
||||
exchangeDetails.termsOfServiceAcceptedEtag === undefined ||
|
||||
exchangeDetails.termsOfServiceText === undefined;
|
||||
|
||||
let tosFound: ExchangeTosDownloadResult | undefined = noTosDownloaded ? undefined : {
|
||||
tosContentType: exchangeDetails.termsOfServiceContentType!,
|
||||
tosEtag: exchangeDetails.termsOfServiceAcceptedEtag!,
|
||||
tosText: exchangeDetails.termsOfServiceText!,
|
||||
};
|
||||
|
||||
try {
|
||||
if (tosAcceptedFormat) for (const format of tosAcceptedFormat) {
|
||||
const resp = await downloadExchangeWithTermsOfService(
|
||||
exchangeDetails.exchangeBaseUrl,
|
||||
ws.http,
|
||||
{ d_ms: 1000 },
|
||||
format
|
||||
);
|
||||
if (resp.tosContentType === format) {
|
||||
tosFound = resp
|
||||
break
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
tosFound = undefined
|
||||
}
|
||||
|
||||
const withdrawFee = Amounts.sub(
|
||||
selectedDenoms.totalWithdrawCost,
|
||||
selectedDenoms.totalCoinValue,
|
||||
@ -1054,7 +1018,6 @@ export async function getExchangeWithdrawalInfo(
|
||||
walletVersion: WALLET_EXCHANGE_PROTOCOL_VERSION,
|
||||
withdrawFee,
|
||||
termsOfServiceAccepted: tosAccepted,
|
||||
tosRequested: tosFound
|
||||
};
|
||||
return ret;
|
||||
}
|
||||
|
@ -217,7 +217,7 @@ async function processOnePendingOperation(
|
||||
logger.trace(`running pending ${JSON.stringify(pending, undefined, 2)}`);
|
||||
switch (pending.type) {
|
||||
case PendingTaskType.ExchangeUpdate:
|
||||
await updateExchangeFromUrl(ws, pending.exchangeBaseUrl, forceNow);
|
||||
await updateExchangeFromUrl(ws, pending.exchangeBaseUrl, undefined, forceNow);
|
||||
break;
|
||||
case PendingTaskType.Refresh:
|
||||
await processRefreshGroup(ws, pending.refreshGroupId, forceNow);
|
||||
@ -452,20 +452,24 @@ async function acceptManualWithdrawal(
|
||||
async function getExchangeTos(
|
||||
ws: InternalWalletState,
|
||||
exchangeBaseUrl: string,
|
||||
acceptedFormat?: string[],
|
||||
): Promise<GetExchangeTosResult> {
|
||||
const { exchange, exchangeDetails } = await updateExchangeFromUrl(
|
||||
const { exchangeDetails } = await updateExchangeFromUrl(
|
||||
ws,
|
||||
exchangeBaseUrl,
|
||||
acceptedFormat,
|
||||
);
|
||||
const tos = exchangeDetails.termsOfServiceText;
|
||||
const content = exchangeDetails.termsOfServiceText;
|
||||
const currentEtag = exchangeDetails.termsOfServiceLastEtag;
|
||||
if (!tos || !currentEtag) {
|
||||
const contentType = exchangeDetails.termsOfServiceContentType;
|
||||
if (content === undefined || currentEtag === undefined || contentType === undefined) {
|
||||
throw Error("exchange is in invalid state");
|
||||
}
|
||||
return {
|
||||
acceptedEtag: exchangeDetails.termsOfServiceAcceptedEtag,
|
||||
currentEtag,
|
||||
tos,
|
||||
content,
|
||||
contentType,
|
||||
};
|
||||
}
|
||||
|
||||
@ -485,7 +489,7 @@ async function getExchanges(
|
||||
if (!dp) {
|
||||
continue;
|
||||
}
|
||||
const { currency, masterPublicKey } = dp;
|
||||
const { currency } = dp;
|
||||
const exchangeDetails = await getExchangeDetails(tx, r.baseUrl);
|
||||
if (!exchangeDetails) {
|
||||
continue;
|
||||
@ -684,7 +688,7 @@ async function dispatchRequestInternal(
|
||||
}
|
||||
case "addExchange": {
|
||||
const req = codecForAddExchangeRequest().decode(payload);
|
||||
await updateExchangeFromUrl(ws, req.exchangeBaseUrl, req.forceUpdate);
|
||||
await updateExchangeFromUrl(ws, req.exchangeBaseUrl, undefined, req.forceUpdate);
|
||||
return {};
|
||||
}
|
||||
case "listExchanges": {
|
||||
@ -696,7 +700,7 @@ async function dispatchRequestInternal(
|
||||
}
|
||||
case "getExchangeWithdrawalInfo": {
|
||||
const req = codecForGetExchangeWithdrawalInfo().decode(payload);
|
||||
return await getExchangeWithdrawalInfo(ws, req.exchangeBaseUrl, req.amount, req.tosAcceptedFormat);
|
||||
return await getExchangeWithdrawalInfo(ws, req.exchangeBaseUrl, req.amount);
|
||||
}
|
||||
case "acceptManualWithdrawal": {
|
||||
const req = codecForAcceptManualWithdrawalRequet().decode(payload);
|
||||
@ -744,7 +748,7 @@ async function dispatchRequestInternal(
|
||||
}
|
||||
case "getExchangeTos": {
|
||||
const req = codecForGetExchangeTosRequest().decode(payload);
|
||||
return getExchangeTos(ws, req.exchangeBaseUrl);
|
||||
return getExchangeTos(ws, req.exchangeBaseUrl , req.acceptedFormat);
|
||||
}
|
||||
case "retryPendingNow": {
|
||||
await runPending(ws, true);
|
||||
|
@ -790,16 +790,18 @@ export const NewTerms = createExample(TestedComponent, {
|
||||
exchangeBaseUrl: 'exchange.test.taler.net',
|
||||
paytoUris: ['asd'],
|
||||
}],
|
||||
exchangeBaseUrl: 'exchange.demo.taler.net',
|
||||
details: {
|
||||
exchangeInfo: {
|
||||
baseUrl: 'exchange.demo.taler.net'
|
||||
} as ExchangeRecord,
|
||||
withdrawFee: {
|
||||
content: '',
|
||||
contentType: '',
|
||||
currentEtag: '',
|
||||
acceptedEtag: undefined,
|
||||
},
|
||||
withdrawalFee: {
|
||||
currency: 'USD',
|
||||
fraction: 0,
|
||||
value: 0
|
||||
},
|
||||
} as ExchangeWithdrawDetails,
|
||||
amount: {
|
||||
currency: 'USD',
|
||||
value: 2,
|
||||
@ -826,16 +828,18 @@ export const TermsReviewingPLAIN = createExample(TestedComponent, {
|
||||
exchangeBaseUrl: 'exchange.test.taler.net',
|
||||
paytoUris: ['asd'],
|
||||
}],
|
||||
exchangeBaseUrl: 'exchange.demo.taler.net',
|
||||
details: {
|
||||
exchangeInfo: {
|
||||
baseUrl: 'exchange.demo.taler.net'
|
||||
} as ExchangeRecord,
|
||||
withdrawFee: {
|
||||
content: '',
|
||||
contentType: '',
|
||||
currentEtag: '',
|
||||
acceptedEtag: undefined,
|
||||
},
|
||||
withdrawalFee: {
|
||||
currency: 'USD',
|
||||
fraction: 0,
|
||||
value: 0
|
||||
},
|
||||
} as ExchangeWithdrawDetails,
|
||||
amount: {
|
||||
currency: 'USD',
|
||||
value: 2,
|
||||
@ -863,16 +867,18 @@ export const TermsReviewingHTML = createExample(TestedComponent, {
|
||||
exchangeBaseUrl: 'exchange.test.taler.net',
|
||||
paytoUris: ['asd'],
|
||||
}],
|
||||
exchangeBaseUrl: 'exchange.demo.taler.net',
|
||||
details: {
|
||||
exchangeInfo: {
|
||||
baseUrl: 'exchange.demo.taler.net'
|
||||
} as ExchangeRecord,
|
||||
withdrawFee: {
|
||||
content: '',
|
||||
contentType: '',
|
||||
currentEtag: '',
|
||||
acceptedEtag: undefined,
|
||||
},
|
||||
withdrawalFee: {
|
||||
currency: 'USD',
|
||||
fraction: 0,
|
||||
value: 0
|
||||
},
|
||||
} as ExchangeWithdrawDetails,
|
||||
amount: {
|
||||
currency: 'USD',
|
||||
value: 2,
|
||||
@ -915,16 +921,18 @@ export const TermsReviewingPDF = createExample(TestedComponent, {
|
||||
exchangeBaseUrl: 'exchange.test.taler.net',
|
||||
paytoUris: ['asd'],
|
||||
}],
|
||||
exchangeBaseUrl: 'exchange.demo.taler.net',
|
||||
details: {
|
||||
exchangeInfo: {
|
||||
baseUrl: 'exchange.demo.taler.net'
|
||||
} as ExchangeRecord,
|
||||
withdrawFee: {
|
||||
content: '',
|
||||
contentType: '',
|
||||
currentEtag: '',
|
||||
acceptedEtag: undefined,
|
||||
},
|
||||
withdrawalFee: {
|
||||
currency: 'USD',
|
||||
fraction: 0,
|
||||
value: 0
|
||||
},
|
||||
} as ExchangeWithdrawDetails,
|
||||
amount: {
|
||||
currency: 'USD',
|
||||
value: 2,
|
||||
@ -953,16 +961,18 @@ export const TermsReviewingXML = createExample(TestedComponent, {
|
||||
exchangeBaseUrl: 'exchange.test.taler.net',
|
||||
paytoUris: ['asd'],
|
||||
}],
|
||||
exchangeBaseUrl: 'exchange.demo.taler.net',
|
||||
details: {
|
||||
exchangeInfo: {
|
||||
baseUrl: 'exchange.demo.taler.net'
|
||||
} as ExchangeRecord,
|
||||
withdrawFee: {
|
||||
content: '',
|
||||
contentType: '',
|
||||
currentEtag: '',
|
||||
acceptedEtag: undefined,
|
||||
},
|
||||
withdrawalFee: {
|
||||
currency: 'USD',
|
||||
fraction: 0,
|
||||
value: 0
|
||||
},
|
||||
} as ExchangeWithdrawDetails,
|
||||
amount: {
|
||||
currency: 'USD',
|
||||
value: 2,
|
||||
@ -990,16 +1000,18 @@ export const NewTermsAccepted = createExample(TestedComponent, {
|
||||
exchangeBaseUrl: 'exchange.test.taler.net',
|
||||
paytoUris: ['asd'],
|
||||
}],
|
||||
exchangeBaseUrl: 'exchange.demo.taler.net',
|
||||
details: {
|
||||
exchangeInfo: {
|
||||
baseUrl: 'exchange.demo.taler.net'
|
||||
} as ExchangeRecord,
|
||||
withdrawFee: {
|
||||
content: '',
|
||||
contentType: '',
|
||||
currentEtag: '',
|
||||
acceptedEtag: undefined,
|
||||
},
|
||||
withdrawalFee: {
|
||||
currency: 'USD',
|
||||
fraction: 0,
|
||||
value: 0
|
||||
},
|
||||
} as ExchangeWithdrawDetails,
|
||||
amount: {
|
||||
currency: 'USD',
|
||||
value: 2,
|
||||
@ -1026,16 +1038,18 @@ export const TermsShowAgainXML = createExample(TestedComponent, {
|
||||
exchangeBaseUrl: 'exchange.test.taler.net',
|
||||
paytoUris: ['asd'],
|
||||
}],
|
||||
exchangeBaseUrl: 'exchange.demo.taler.net',
|
||||
details: {
|
||||
exchangeInfo: {
|
||||
baseUrl: 'exchange.demo.taler.net'
|
||||
} as ExchangeRecord,
|
||||
withdrawFee: {
|
||||
content: '',
|
||||
contentType: '',
|
||||
currentEtag: '',
|
||||
acceptedEtag: undefined,
|
||||
},
|
||||
withdrawalFee: {
|
||||
currency: 'USD',
|
||||
fraction: 0,
|
||||
value: 0
|
||||
},
|
||||
} as ExchangeWithdrawDetails,
|
||||
amount: {
|
||||
currency: 'USD',
|
||||
value: 2,
|
||||
@ -1050,6 +1064,7 @@ export const TermsShowAgainXML = createExample(TestedComponent, {
|
||||
},
|
||||
status: 'new'
|
||||
},
|
||||
reviewed: true,
|
||||
reviewing: true,
|
||||
})
|
||||
|
||||
@ -1063,16 +1078,18 @@ export const TermsChanged = createExample(TestedComponent, {
|
||||
exchangeBaseUrl: 'exchange.test.taler.net',
|
||||
paytoUris: ['asd'],
|
||||
}],
|
||||
exchangeBaseUrl: 'exchange.demo.taler.net',
|
||||
details: {
|
||||
exchangeInfo: {
|
||||
baseUrl: 'exchange.demo.taler.net'
|
||||
} as ExchangeRecord,
|
||||
withdrawFee: {
|
||||
content: '',
|
||||
contentType: '',
|
||||
currentEtag: '',
|
||||
acceptedEtag: undefined,
|
||||
},
|
||||
withdrawalFee: {
|
||||
currency: 'USD',
|
||||
fraction: 0,
|
||||
value: 0
|
||||
},
|
||||
} as ExchangeWithdrawDetails,
|
||||
amount: {
|
||||
currency: 'USD',
|
||||
value: 2,
|
||||
@ -1099,16 +1116,18 @@ export const TermsNotFound = createExample(TestedComponent, {
|
||||
exchangeBaseUrl: 'exchange.test.taler.net',
|
||||
paytoUris: ['asd'],
|
||||
}],
|
||||
exchangeBaseUrl: 'exchange.demo.taler.net',
|
||||
details: {
|
||||
exchangeInfo: {
|
||||
baseUrl: 'exchange.demo.taler.net'
|
||||
} as ExchangeRecord,
|
||||
withdrawFee: {
|
||||
content: '',
|
||||
contentType: '',
|
||||
currentEtag: '',
|
||||
acceptedEtag: undefined,
|
||||
},
|
||||
withdrawalFee: {
|
||||
currency: 'USD',
|
||||
fraction: 0,
|
||||
value: 0
|
||||
},
|
||||
} as ExchangeWithdrawDetails,
|
||||
amount: {
|
||||
currency: 'USD',
|
||||
value: 2,
|
||||
@ -1131,16 +1150,18 @@ export const TermsAlreadyAccepted = createExample(TestedComponent, {
|
||||
exchangeBaseUrl: 'exchange.test.taler.net',
|
||||
paytoUris: ['asd'],
|
||||
}],
|
||||
exchangeBaseUrl: 'exchange.demo.taler.net',
|
||||
details: {
|
||||
exchangeInfo: {
|
||||
baseUrl: 'exchange.demo.taler.net'
|
||||
} as ExchangeRecord,
|
||||
withdrawFee: {
|
||||
content: '',
|
||||
contentType: '',
|
||||
currentEtag: '',
|
||||
acceptedEtag: undefined,
|
||||
},
|
||||
withdrawalFee: {
|
||||
currency: 'USD',
|
||||
fraction: amountFractionalBase * 0.5,
|
||||
value: 0
|
||||
},
|
||||
} as ExchangeWithdrawDetails,
|
||||
amount: {
|
||||
currency: 'USD',
|
||||
value: 2,
|
||||
@ -1164,16 +1185,18 @@ export const WithoutFee = createExample(TestedComponent, {
|
||||
exchangeBaseUrl: 'exchange.test.taler.net',
|
||||
paytoUris: ['asd'],
|
||||
}],
|
||||
exchangeBaseUrl: 'exchange.demo.taler.net',
|
||||
details: {
|
||||
exchangeInfo: {
|
||||
baseUrl: 'exchange.demo.taler.net'
|
||||
} as ExchangeRecord,
|
||||
withdrawFee: {
|
||||
content: '',
|
||||
contentType: '',
|
||||
currentEtag: '',
|
||||
acceptedEtag: undefined,
|
||||
},
|
||||
withdrawalFee: {
|
||||
currency: 'USD',
|
||||
fraction: 0,
|
||||
value: 0
|
||||
value: 0,
|
||||
},
|
||||
} as ExchangeWithdrawDetails,
|
||||
amount: {
|
||||
currency: 'USD',
|
||||
value: 2,
|
||||
|
@ -21,7 +21,7 @@
|
||||
* @author Florian Dold
|
||||
*/
|
||||
|
||||
import { AmountJson, Amounts, ExchangeListItem, i18n, WithdrawUriInfoResponse } from '@gnu-taler/taler-util';
|
||||
import { AmountJson, Amounts, ExchangeListItem, GetExchangeTosResult, i18n, WithdrawUriInfoResponse } from '@gnu-taler/taler-util';
|
||||
import { ExchangeWithdrawDetails } from '@gnu-taler/taler-wallet-core/src/operations/withdraw';
|
||||
import { useState } from "preact/hooks";
|
||||
import { Fragment } from 'preact/jsx-runtime';
|
||||
@ -33,7 +33,7 @@ import { SelectList } from '../components/SelectList';
|
||||
import { ButtonSuccess, ButtonWarning, LinkSuccess, LinkWarning, TermsOfService, WalletAction } from '../components/styled';
|
||||
import { useAsyncAsHook } from '../hooks/useAsyncAsHook';
|
||||
import {
|
||||
acceptWithdrawal, getExchangeWithdrawalInfo, getWithdrawalDetailsForUri, setExchangeTosAccepted, listExchanges
|
||||
acceptWithdrawal, getExchangeWithdrawalInfo, getWithdrawalDetailsForUri, setExchangeTosAccepted, listExchanges, getExchangeTos
|
||||
} from "../wxApi";
|
||||
import { wxMain } from '../wxBackend.js';
|
||||
|
||||
@ -42,7 +42,9 @@ interface Props {
|
||||
}
|
||||
|
||||
export interface ViewProps {
|
||||
details: ExchangeWithdrawDetails;
|
||||
details: GetExchangeTosResult;
|
||||
withdrawalFee: AmountJson;
|
||||
exchangeBaseUrl: string;
|
||||
amount: AmountJson;
|
||||
onSwitchExchange: (ex: string) => void;
|
||||
onWithdraw: () => Promise<void>;
|
||||
@ -54,8 +56,8 @@ export interface ViewProps {
|
||||
terms: {
|
||||
value?: TermsDocument;
|
||||
status: TermsStatus;
|
||||
},
|
||||
knownExchanges: ExchangeListItem[]
|
||||
};
|
||||
knownExchanges: ExchangeListItem[];
|
||||
|
||||
};
|
||||
|
||||
@ -94,7 +96,7 @@ function amountToString(text: AmountJson) {
|
||||
return `${amount} ${aj.currency}`
|
||||
}
|
||||
|
||||
export function View({ details, knownExchanges, amount, onWithdraw, onSwitchExchange, terms, reviewing, onReview, onAccept, reviewed, confirmed }: ViewProps) {
|
||||
export function View({ details, withdrawalFee, exchangeBaseUrl, knownExchanges, amount, onWithdraw, onSwitchExchange, terms, reviewing, onReview, onAccept, reviewed, confirmed }: ViewProps) {
|
||||
const needsReview = terms.status === 'changed' || terms.status === 'new'
|
||||
|
||||
const [switchingExchange, setSwitchingExchange] = useState<string | undefined>(undefined)
|
||||
@ -107,12 +109,12 @@ export function View({ details, knownExchanges, amount, onWithdraw, onSwitchExch
|
||||
{i18n.str`Digital cash withdrawal`}
|
||||
</h2>
|
||||
<section>
|
||||
<Part title="Total to withdraw" text={amountToString(Amounts.sub(amount, details.withdrawFee).amount)} kind='positive' />
|
||||
<Part title="Total to withdraw" text={amountToString(Amounts.sub(amount, withdrawalFee).amount)} kind='positive' />
|
||||
<Part title="Chosen amount" text={amountToString(amount)} kind='neutral' />
|
||||
{Amounts.isNonZero(details.withdrawFee) &&
|
||||
<Part title="Exchange fee" text={amountToString(details.withdrawFee)} kind='negative' />
|
||||
{Amounts.isNonZero(withdrawalFee) &&
|
||||
<Part title="Exchange fee" text={amountToString(withdrawalFee)} kind='negative' />
|
||||
}
|
||||
<Part title="Exchange" text={details.exchangeInfo.baseUrl} kind='neutral' big />
|
||||
<Part title="Exchange" text={exchangeBaseUrl} kind='neutral' big />
|
||||
</section>
|
||||
{!reviewing &&
|
||||
<section>
|
||||
@ -190,7 +192,7 @@ export function View({ details, knownExchanges, amount, onWithdraw, onSwitchExch
|
||||
{terms.status === 'new' && !reviewed && !reviewing &&
|
||||
<ButtonSuccess
|
||||
upperCased
|
||||
disabled={!details.exchangeInfo.baseUrl}
|
||||
disabled={!exchangeBaseUrl}
|
||||
onClick={() => onReview(true)}
|
||||
>
|
||||
{i18n.str`Review exchange terms of service`}
|
||||
@ -199,7 +201,7 @@ export function View({ details, knownExchanges, amount, onWithdraw, onSwitchExch
|
||||
{terms.status === 'changed' && !reviewed && !reviewing &&
|
||||
<ButtonWarning
|
||||
upperCased
|
||||
disabled={!details.exchangeInfo.baseUrl}
|
||||
disabled={!exchangeBaseUrl}
|
||||
onClick={() => onReview(true)}
|
||||
>
|
||||
{i18n.str`Review new version of terms of service`}
|
||||
@ -208,7 +210,7 @@ export function View({ details, knownExchanges, amount, onWithdraw, onSwitchExch
|
||||
{(terms.status === 'accepted' || (needsReview && reviewed)) &&
|
||||
<ButtonSuccess
|
||||
upperCased
|
||||
disabled={!details.exchangeInfo.baseUrl || confirmed}
|
||||
disabled={!exchangeBaseUrl || confirmed}
|
||||
onClick={onWithdraw}
|
||||
>
|
||||
{i18n.str`Confirm withdrawal`}
|
||||
@ -220,7 +222,7 @@ export function View({ details, knownExchanges, amount, onWithdraw, onSwitchExch
|
||||
</LinkWarning>
|
||||
<ButtonWarning
|
||||
upperCased
|
||||
disabled={!details.exchangeInfo.baseUrl}
|
||||
disabled={!exchangeBaseUrl}
|
||||
onClick={onWithdraw}
|
||||
>
|
||||
{i18n.str`Withdraw anyway`}
|
||||
@ -249,11 +251,13 @@ export function WithdrawPageWithParsedURI({ uri, uriInfo }: { uri: string, uriIn
|
||||
const exchange = customExchange || uriInfo.defaultExchangeBaseUrl || thisCurrencyExchanges[0]?.exchangeBaseUrl
|
||||
const detailsHook = useAsyncAsHook(async () => {
|
||||
if (!exchange) throw Error('no default exchange')
|
||||
return getExchangeWithdrawalInfo({
|
||||
const tos = await getExchangeTos(exchange, ['text/xml'])
|
||||
const info = await getExchangeWithdrawalInfo({
|
||||
exchangeBaseUrl: exchange,
|
||||
amount: withdrawAmount,
|
||||
tosAcceptedFormat: ['text/xml']
|
||||
})
|
||||
return {tos, info}
|
||||
})
|
||||
|
||||
if (!detailsHook) {
|
||||
@ -267,7 +271,7 @@ export function WithdrawPageWithParsedURI({ uri, uriInfo }: { uri: string, uriIn
|
||||
|
||||
const onAccept = async (): Promise<void> => {
|
||||
try {
|
||||
await setExchangeTosAccepted(details.exchangeInfo.baseUrl, details.tosRequested?.tosEtag)
|
||||
await setExchangeTosAccepted(exchange, details.tos.currentEtag)
|
||||
setReviewed(true)
|
||||
} catch (e) {
|
||||
if (e instanceof Error) {
|
||||
@ -278,9 +282,9 @@ export function WithdrawPageWithParsedURI({ uri, uriInfo }: { uri: string, uriIn
|
||||
|
||||
const onWithdraw = async (): Promise<void> => {
|
||||
setConfirmed(true)
|
||||
console.log("accepting exchange", details.exchangeDetails.exchangeBaseUrl);
|
||||
console.log("accepting exchange", exchange);
|
||||
try {
|
||||
const res = await acceptWithdrawal(uri, details.exchangeInfo.baseUrl);
|
||||
const res = await acceptWithdrawal(uri, exchange);
|
||||
console.log("accept withdrawal response", res);
|
||||
if (res.confirmTransferUrl) {
|
||||
document.location.href = res.confirmTransferUrl;
|
||||
@ -290,17 +294,18 @@ export function WithdrawPageWithParsedURI({ uri, uriInfo }: { uri: string, uriIn
|
||||
}
|
||||
};
|
||||
|
||||
const termsContent: TermsDocument | undefined = !details.tosRequested ? undefined : parseTermsOfServiceContent(details.tosRequested.tosContentType, details.tosRequested.tosText);
|
||||
const termsContent: TermsDocument | undefined = parseTermsOfServiceContent(details.tos.contentType, details.tos.content);
|
||||
|
||||
const status: TermsStatus = !termsContent ? 'notfound' : (
|
||||
!details.exchangeDetails.termsOfServiceAcceptedEtag ? 'new' : (
|
||||
details.tosRequested?.tosEtag !== details.exchangeDetails.termsOfServiceAcceptedEtag ? 'changed' : 'accepted'
|
||||
!details.tos.acceptedEtag ? 'new' : (
|
||||
details.tos.acceptedEtag !== details.tos.currentEtag ? 'changed' : 'accepted'
|
||||
))
|
||||
|
||||
|
||||
return <View onWithdraw={onWithdraw}
|
||||
// setCancelled={setCancelled} setSelecting={setSelecting}
|
||||
details={details} amount={withdrawAmount}
|
||||
details={details.tos} amount={withdrawAmount}
|
||||
exchangeBaseUrl={exchange}
|
||||
withdrawalFee={details.info.withdrawFee} //FIXME
|
||||
terms={{
|
||||
status, value: termsContent
|
||||
}}
|
||||
@ -309,7 +314,6 @@ export function WithdrawPageWithParsedURI({ uri, uriInfo }: { uri: string, uriIn
|
||||
confirmed={confirmed}
|
||||
reviewed={reviewed} onAccept={onAccept}
|
||||
reviewing={reviewing} onReview={setReviewing}
|
||||
// terms={[]}
|
||||
/>
|
||||
}
|
||||
export function WithdrawPage({ talerWithdrawUri }: Props): JSX.Element {
|
||||
|
@ -45,6 +45,7 @@ import {
|
||||
AmountJson,
|
||||
ExchangesListRespose,
|
||||
AddExchangeRequest,
|
||||
GetExchangeTosResult,
|
||||
} from "@gnu-taler/taler-util";
|
||||
import { AddBackupProviderRequest, BackupProviderState, OperationFailedError, RemoveBackupProviderRequest } from "@gnu-taler/taler-wallet-core";
|
||||
import { BackupInfo } from "@gnu-taler/taler-wallet-core";
|
||||
@ -327,11 +328,14 @@ export function getExchangeWithdrawalInfo(
|
||||
): Promise<ExchangeWithdrawDetails> {
|
||||
return callBackend("getExchangeWithdrawalInfo", req);
|
||||
}
|
||||
// export const codecForAddExchangeRequest = (): Codec<AddExchangeRequest> =>
|
||||
// buildCodecForObject<AddExchangeRequest>()
|
||||
// .property("exchangeBaseUrl", codecForString())
|
||||
// .property("forceUpdate", codecOptional(codecForBoolean()))
|
||||
// .build("AddExchangeRequest");
|
||||
export function getExchangeTos(
|
||||
exchangeBaseUrl: string,
|
||||
acceptedFormat: string[],
|
||||
): Promise<GetExchangeTosResult> {
|
||||
return callBackend("getExchangeTos", {
|
||||
exchangeBaseUrl, acceptedFormat
|
||||
});
|
||||
}
|
||||
|
||||
export function addExchange(
|
||||
req: AddExchangeRequest,
|
||||
|
Loading…
Reference in New Issue
Block a user