2022-08-26 06:08:51 +02:00
|
|
|
/*
|
|
|
|
This file is part of GNU Taler
|
|
|
|
(C) 2022 Taler Systems S.A.
|
|
|
|
|
|
|
|
GNU Taler is free software; you can redistribute it and/or modify it under the
|
|
|
|
terms of the GNU General Public License as published by the Free Software
|
|
|
|
Foundation; either version 3, or (at your option) any later version.
|
|
|
|
|
|
|
|
GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
|
|
|
|
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
|
|
|
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
|
|
|
|
|
|
|
You should have received a copy of the GNU General Public License along with
|
|
|
|
GNU Taler; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
|
|
|
|
*/
|
|
|
|
|
2022-10-14 16:40:38 +02:00
|
|
|
import { FeeDescription, FeeDescriptionPair } from "@gnu-taler/taler-util";
|
2022-08-26 06:08:51 +02:00
|
|
|
import { styled } from "@linaria/react";
|
2022-09-12 15:57:13 +02:00
|
|
|
import { Fragment, h, VNode } from "preact";
|
|
|
|
import { useState } from "preact/hooks";
|
2022-08-26 06:08:51 +02:00
|
|
|
import { Amount } from "../../components/Amount.js";
|
2022-11-04 19:38:58 +01:00
|
|
|
import { ErrorMessage } from "../../components/ErrorMessage.js";
|
2022-09-12 15:57:13 +02:00
|
|
|
import { SelectList } from "../../components/SelectList.js";
|
2022-10-14 16:40:38 +02:00
|
|
|
import { Input, SvgIcon } from "../../components/styled/index.js";
|
2022-10-14 21:12:24 +02:00
|
|
|
import { TermsOfService } from "../../components/TermsOfService/index.js";
|
2022-08-26 06:08:51 +02:00
|
|
|
import { Time } from "../../components/Time.js";
|
2022-09-12 15:57:13 +02:00
|
|
|
import { useTranslationContext } from "../../context/translation.js";
|
2022-10-14 16:40:38 +02:00
|
|
|
import { State as SelectExchangeState } from "../../hooks/useSelectedExchange.js";
|
2022-08-26 06:08:51 +02:00
|
|
|
import { Button } from "../../mui/Button.js";
|
2022-09-12 15:57:13 +02:00
|
|
|
import arrowDown from "../../svg/chevron-down.svg";
|
|
|
|
import { State } from "./index.js";
|
2022-08-26 06:08:51 +02:00
|
|
|
|
|
|
|
const ButtonGroup = styled.div`
|
|
|
|
& > button {
|
|
|
|
margin-left: 8px;
|
|
|
|
margin-right: 8px;
|
|
|
|
}
|
|
|
|
`;
|
2022-10-14 16:40:38 +02:00
|
|
|
const ButtonGroupFooter = styled.div`
|
|
|
|
& {
|
|
|
|
display: flex;
|
|
|
|
justify-content: space-between;
|
|
|
|
}
|
|
|
|
& > button {
|
|
|
|
margin-left: 8px;
|
|
|
|
margin-right: 8px;
|
|
|
|
}
|
|
|
|
`;
|
2022-08-26 06:08:51 +02:00
|
|
|
|
|
|
|
const FeeDescriptionTable = styled.table`
|
|
|
|
& {
|
|
|
|
margin-bottom: 20px;
|
|
|
|
width: 100%;
|
|
|
|
border-collapse: collapse;
|
|
|
|
}
|
|
|
|
td {
|
|
|
|
padding: 8px;
|
|
|
|
}
|
|
|
|
td.fee {
|
|
|
|
text-align: center;
|
|
|
|
}
|
|
|
|
th.fee {
|
|
|
|
text-align: center;
|
|
|
|
}
|
|
|
|
td.value {
|
|
|
|
text-align: right;
|
2022-10-12 20:58:10 +02:00
|
|
|
width: 15%;
|
2022-08-26 06:08:51 +02:00
|
|
|
white-space: nowrap;
|
|
|
|
}
|
|
|
|
td.icon {
|
|
|
|
width: 24px;
|
|
|
|
}
|
|
|
|
td.icon > div {
|
|
|
|
width: 24px;
|
|
|
|
height: 24px;
|
|
|
|
margin: 0px;
|
|
|
|
}
|
|
|
|
td.expiration {
|
|
|
|
text-align: center;
|
|
|
|
}
|
|
|
|
|
|
|
|
tr[data-main="true"] {
|
|
|
|
background-color: #add8e662;
|
|
|
|
}
|
|
|
|
tr[data-main="true"] > td.value,
|
|
|
|
tr[data-main="true"] > td.expiration,
|
|
|
|
tr[data-main="true"] > td.fee {
|
|
|
|
border-bottom: lightgray solid 1px;
|
|
|
|
}
|
|
|
|
tr[data-hidden="true"] {
|
|
|
|
display: none;
|
|
|
|
}
|
|
|
|
tbody > tr.value[data-hasMore="true"],
|
|
|
|
tbody > tr.value[data-hasMore="true"] > td {
|
|
|
|
cursor: pointer;
|
|
|
|
}
|
|
|
|
th {
|
|
|
|
position: sticky;
|
|
|
|
top: 0;
|
|
|
|
background-color: white;
|
|
|
|
}
|
|
|
|
`;
|
|
|
|
|
|
|
|
const Container = styled.div`
|
|
|
|
display: flex;
|
|
|
|
flex-direction: column;
|
|
|
|
& > * {
|
|
|
|
margin-bottom: 20px;
|
|
|
|
}
|
|
|
|
`;
|
|
|
|
|
2022-10-14 21:12:24 +02:00
|
|
|
export function PrivacyContentView({
|
|
|
|
exchangeUrl,
|
|
|
|
onClose,
|
|
|
|
}: State.ShowingPrivacy): VNode {
|
|
|
|
const { i18n } = useTranslationContext();
|
|
|
|
return (
|
|
|
|
<div>
|
|
|
|
<Button variant="outlined" onClick={onClose.onClick}>
|
|
|
|
<i18n.Translate>Close</i18n.Translate>
|
|
|
|
</Button>
|
|
|
|
<div>show privacy terms for {exchangeUrl}</div>
|
|
|
|
</div>
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
export function TosContentView({
|
|
|
|
exchangeUrl,
|
|
|
|
onClose,
|
|
|
|
}: State.ShowingTos): VNode {
|
|
|
|
const { i18n } = useTranslationContext();
|
|
|
|
return (
|
|
|
|
<div>
|
|
|
|
<Button variant="outlined" onClick={onClose.onClick}>
|
|
|
|
<i18n.Translate>Close</i18n.Translate>
|
|
|
|
</Button>
|
|
|
|
<TermsOfService exchangeUrl={exchangeUrl} />
|
|
|
|
</div>
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2022-10-12 20:58:10 +02:00
|
|
|
export function NoExchangesView({
|
|
|
|
currency,
|
|
|
|
}: SelectExchangeState.NoExchange): VNode {
|
2022-08-26 06:08:51 +02:00
|
|
|
const { i18n } = useTranslationContext();
|
2022-09-21 01:26:41 +02:00
|
|
|
if (!currency) {
|
2023-01-09 12:38:48 +01:00
|
|
|
return <ErrorMessage title={i18n.str`Could not find any exchange`} />;
|
2022-09-21 01:26:41 +02:00
|
|
|
}
|
2022-09-13 16:07:39 +02:00
|
|
|
return (
|
2022-11-04 19:38:58 +01:00
|
|
|
<ErrorMessage
|
2023-01-09 12:38:48 +01:00
|
|
|
title={i18n.str`Could not find any exchange for the currency ${currency}`}
|
2022-11-04 19:38:58 +01:00
|
|
|
/>
|
2022-09-13 16:07:39 +02:00
|
|
|
);
|
2022-08-26 06:08:51 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
export function ComparingView({
|
|
|
|
exchanges,
|
|
|
|
selected,
|
|
|
|
onReset,
|
|
|
|
onSelect,
|
2022-12-20 19:23:33 +01:00
|
|
|
coinOperationTimeline,
|
|
|
|
globalFeeTimeline,
|
|
|
|
wireFeeTimeline,
|
|
|
|
missingWireTYpe,
|
|
|
|
newWireType,
|
2022-10-14 21:12:24 +02:00
|
|
|
onShowPrivacy,
|
|
|
|
onShowTerms,
|
2022-08-26 06:08:51 +02:00
|
|
|
}: State.Comparing): VNode {
|
|
|
|
const { i18n } = useTranslationContext();
|
|
|
|
return (
|
|
|
|
<Container>
|
|
|
|
<h2>
|
|
|
|
<i18n.Translate>Service fee description</i18n.Translate>
|
|
|
|
</h2>
|
|
|
|
|
|
|
|
<section>
|
|
|
|
<div
|
|
|
|
style={{
|
|
|
|
display: "flex",
|
|
|
|
flexWrap: "wrap",
|
|
|
|
alignItems: "center",
|
|
|
|
justifyContent: "space-between",
|
|
|
|
}}
|
|
|
|
>
|
|
|
|
<p>
|
|
|
|
<Input>
|
|
|
|
<SelectList
|
|
|
|
label={
|
|
|
|
<i18n.Translate>
|
|
|
|
Select {selected.currency} exchange
|
|
|
|
</i18n.Translate>
|
|
|
|
}
|
|
|
|
list={exchanges.list}
|
|
|
|
name="lang"
|
|
|
|
value={exchanges.value}
|
|
|
|
onChange={exchanges.onChange}
|
|
|
|
/>
|
|
|
|
</Input>
|
|
|
|
</p>
|
|
|
|
<ButtonGroup>
|
|
|
|
<Button variant="outlined" onClick={onReset.onClick}>
|
2022-09-13 16:07:39 +02:00
|
|
|
<i18n.Translate>Reset</i18n.Translate>
|
2022-08-26 06:08:51 +02:00
|
|
|
</Button>
|
|
|
|
<Button variant="contained" onClick={onSelect.onClick}>
|
2022-09-13 16:07:39 +02:00
|
|
|
<i18n.Translate>Use this exchange</i18n.Translate>
|
2022-08-26 06:08:51 +02:00
|
|
|
</Button>
|
|
|
|
</ButtonGroup>
|
|
|
|
</div>
|
|
|
|
</section>
|
|
|
|
<section>
|
|
|
|
<dl>
|
2022-09-13 16:07:39 +02:00
|
|
|
<dt>
|
|
|
|
<i18n.Translate>Auditors</i18n.Translate>
|
|
|
|
</dt>
|
2022-08-26 06:08:51 +02:00
|
|
|
{selected.auditors.length === 0 ? (
|
2022-09-13 16:07:39 +02:00
|
|
|
<dd style={{ color: "red" }}>
|
|
|
|
<i18n.Translate>Doesn't have auditors</i18n.Translate>
|
|
|
|
</dd>
|
2022-08-26 06:08:51 +02:00
|
|
|
) : (
|
|
|
|
selected.auditors.map((a) => {
|
|
|
|
<dd>{a.auditor_url}</dd>;
|
|
|
|
})
|
|
|
|
)}
|
|
|
|
</dl>
|
|
|
|
<table>
|
|
|
|
<tr>
|
2022-09-13 16:07:39 +02:00
|
|
|
<td>
|
|
|
|
<i18n.Translate>currency</i18n.Translate>
|
|
|
|
</td>
|
2022-08-26 06:08:51 +02:00
|
|
|
<td>{selected.currency}</td>
|
|
|
|
</tr>
|
|
|
|
</table>
|
|
|
|
</section>
|
|
|
|
<section>
|
2022-09-13 16:07:39 +02:00
|
|
|
<h2>
|
2022-12-20 19:23:33 +01:00
|
|
|
<i18n.Translate>Coin operations</i18n.Translate>
|
2022-09-13 16:07:39 +02:00
|
|
|
</h2>
|
2022-12-20 19:23:33 +01:00
|
|
|
<p>
|
|
|
|
<i18n.Translate>
|
|
|
|
Every operation in this section may be different by denomination
|
|
|
|
value and is valid for a period of time. The exchange will charge
|
|
|
|
the indicated amount every time a coin is used in such operation.
|
|
|
|
</i18n.Translate>
|
|
|
|
</p>
|
2022-09-13 16:07:39 +02:00
|
|
|
<p>
|
|
|
|
<i18n.Translate>Deposits</i18n.Translate>
|
|
|
|
</p>
|
2022-08-26 06:08:51 +02:00
|
|
|
<FeeDescriptionTable>
|
|
|
|
<thead>
|
|
|
|
<tr>
|
|
|
|
<th> </th>
|
2022-09-13 16:07:39 +02:00
|
|
|
<th>
|
|
|
|
<i18n.Translate>Denomination</i18n.Translate>
|
|
|
|
</th>
|
|
|
|
<th class="fee">
|
2022-11-18 15:29:24 +01:00
|
|
|
<i18n.Translate>Current</i18n.Translate>
|
|
|
|
</th>
|
|
|
|
<th class="fee">
|
|
|
|
<i18n.Translate>Selected</i18n.Translate>
|
2022-09-13 16:07:39 +02:00
|
|
|
</th>
|
|
|
|
<th>
|
|
|
|
<i18n.Translate>Until</i18n.Translate>
|
|
|
|
</th>
|
2022-08-26 06:08:51 +02:00
|
|
|
</tr>
|
|
|
|
</thead>
|
|
|
|
<tbody>
|
2022-11-18 15:29:24 +01:00
|
|
|
<RenderFeePairByValue
|
2022-12-20 19:23:33 +01:00
|
|
|
list={coinOperationTimeline.deposit}
|
2022-11-18 15:29:24 +01:00
|
|
|
sorting={(a, b) => Number(a) - Number(b)}
|
|
|
|
/>
|
2022-08-26 06:08:51 +02:00
|
|
|
</tbody>
|
|
|
|
</FeeDescriptionTable>
|
2022-09-13 16:07:39 +02:00
|
|
|
<p>
|
|
|
|
<i18n.Translate>Withdrawals</i18n.Translate>
|
|
|
|
</p>
|
2022-08-26 06:08:51 +02:00
|
|
|
<FeeDescriptionTable>
|
|
|
|
<thead>
|
|
|
|
<tr>
|
|
|
|
<th> </th>
|
2022-09-13 16:07:39 +02:00
|
|
|
<th>
|
|
|
|
<i18n.Translate>Denomination</i18n.Translate>
|
|
|
|
</th>
|
|
|
|
<th class="fee">
|
2022-12-20 19:23:33 +01:00
|
|
|
<i18n.Translate>Current</i18n.Translate>
|
|
|
|
</th>
|
|
|
|
<th class="fee">
|
|
|
|
<i18n.Translate>Selected</i18n.Translate>
|
2022-09-13 16:07:39 +02:00
|
|
|
</th>
|
|
|
|
<th>
|
|
|
|
<i18n.Translate>Until</i18n.Translate>
|
|
|
|
</th>
|
2022-08-26 06:08:51 +02:00
|
|
|
</tr>
|
|
|
|
</thead>
|
|
|
|
<tbody>
|
2022-11-18 15:29:24 +01:00
|
|
|
<RenderFeePairByValue
|
2022-12-20 19:23:33 +01:00
|
|
|
list={coinOperationTimeline.withdraw}
|
2022-11-18 15:29:24 +01:00
|
|
|
sorting={(a, b) => Number(a) - Number(b)}
|
|
|
|
/>
|
2022-08-26 06:08:51 +02:00
|
|
|
</tbody>
|
|
|
|
</FeeDescriptionTable>
|
2022-09-13 16:07:39 +02:00
|
|
|
<p>
|
|
|
|
<i18n.Translate>Refunds</i18n.Translate>
|
|
|
|
</p>
|
2022-08-26 06:08:51 +02:00
|
|
|
<FeeDescriptionTable>
|
|
|
|
<thead>
|
|
|
|
<tr>
|
|
|
|
<th> </th>
|
2022-09-13 16:07:39 +02:00
|
|
|
<th>
|
|
|
|
<i18n.Translate>Denomination</i18n.Translate>
|
|
|
|
</th>
|
|
|
|
<th class="fee">
|
2022-12-20 19:23:33 +01:00
|
|
|
<i18n.Translate>Current</i18n.Translate>
|
|
|
|
</th>
|
|
|
|
<th class="fee">
|
|
|
|
<i18n.Translate>Selected</i18n.Translate>
|
2022-09-13 16:07:39 +02:00
|
|
|
</th>
|
|
|
|
<th>
|
|
|
|
<i18n.Translate>Until</i18n.Translate>
|
|
|
|
</th>
|
2022-08-26 06:08:51 +02:00
|
|
|
</tr>
|
|
|
|
</thead>
|
|
|
|
<tbody>
|
2022-11-18 15:29:24 +01:00
|
|
|
<RenderFeePairByValue
|
2022-12-20 19:23:33 +01:00
|
|
|
list={coinOperationTimeline.refund}
|
2022-11-18 15:29:24 +01:00
|
|
|
sorting={(a, b) => Number(a) - Number(b)}
|
|
|
|
/>
|
2022-08-26 06:08:51 +02:00
|
|
|
</tbody>
|
|
|
|
</FeeDescriptionTable>{" "}
|
2022-09-13 16:07:39 +02:00
|
|
|
<p>
|
|
|
|
<i18n.Translate>Refresh</i18n.Translate>
|
|
|
|
</p>
|
2022-08-26 06:08:51 +02:00
|
|
|
<FeeDescriptionTable>
|
|
|
|
<thead>
|
|
|
|
<tr>
|
|
|
|
<th> </th>
|
2022-09-13 16:07:39 +02:00
|
|
|
<th>
|
|
|
|
<i18n.Translate>Denomination</i18n.Translate>
|
|
|
|
</th>
|
|
|
|
<th class="fee">
|
2022-12-20 19:23:33 +01:00
|
|
|
<i18n.Translate>Current</i18n.Translate>
|
|
|
|
</th>
|
|
|
|
<th class="fee">
|
|
|
|
<i18n.Translate>Selected</i18n.Translate>
|
2022-09-13 16:07:39 +02:00
|
|
|
</th>
|
|
|
|
<th>
|
|
|
|
<i18n.Translate>Until</i18n.Translate>
|
|
|
|
</th>
|
2022-08-26 06:08:51 +02:00
|
|
|
</tr>
|
|
|
|
</thead>
|
|
|
|
<tbody>
|
2022-11-18 15:29:24 +01:00
|
|
|
<RenderFeePairByValue
|
2022-12-20 19:23:33 +01:00
|
|
|
list={coinOperationTimeline.refresh}
|
2022-11-18 15:29:24 +01:00
|
|
|
sorting={(a, b) => Number(a) - Number(b)}
|
|
|
|
/>
|
2022-08-26 06:08:51 +02:00
|
|
|
</tbody>
|
|
|
|
</FeeDescriptionTable>{" "}
|
|
|
|
</section>
|
2022-12-20 19:23:33 +01:00
|
|
|
<section>
|
|
|
|
<h2>
|
|
|
|
<i18n.Translate>Transfer operations</i18n.Translate>
|
|
|
|
</h2>
|
|
|
|
<p>
|
|
|
|
<i18n.Translate>
|
|
|
|
Every operation in this section may be different by transfer type
|
|
|
|
and is valid for a period of time. The exchange will charge the
|
|
|
|
indicated amount every time a transfer is made.
|
|
|
|
</i18n.Translate>
|
|
|
|
</p>
|
|
|
|
{missingWireTYpe.map((type) => {
|
|
|
|
return (
|
|
|
|
<p key={type}>
|
|
|
|
Wire <b>{type}</b> is not supported for this exchange.
|
|
|
|
</p>
|
|
|
|
);
|
|
|
|
})}
|
|
|
|
{newWireType.map((type) => {
|
|
|
|
return (
|
|
|
|
<Fragment key={type}>
|
|
|
|
<p>
|
|
|
|
Wire <b>{type}</b> is not supported for the previous exchange.
|
|
|
|
</p>
|
|
|
|
<FeeDescriptionTable>
|
|
|
|
<thead>
|
|
|
|
<tr>
|
|
|
|
<th> </th>
|
|
|
|
<th>
|
|
|
|
<i18n.Translate>Operation</i18n.Translate>
|
|
|
|
</th>
|
|
|
|
<th class="fee">
|
|
|
|
<i18n.Translate>Fee</i18n.Translate>
|
|
|
|
</th>
|
|
|
|
<th>
|
|
|
|
<i18n.Translate>Until</i18n.Translate>
|
|
|
|
</th>
|
|
|
|
</tr>
|
|
|
|
</thead>
|
|
|
|
<tbody>
|
|
|
|
<RenderFeeDescriptionByValue
|
|
|
|
list={selected.transferFees[type]}
|
|
|
|
/>
|
|
|
|
</tbody>
|
|
|
|
</FeeDescriptionTable>
|
|
|
|
</Fragment>
|
|
|
|
);
|
|
|
|
})}
|
|
|
|
{Object.entries(wireFeeTimeline).map(([type, fees], idx) => {
|
|
|
|
return (
|
|
|
|
<Fragment key={idx}>
|
|
|
|
<p>{type}</p>
|
|
|
|
<FeeDescriptionTable>
|
|
|
|
<thead>
|
|
|
|
<tr>
|
|
|
|
<th> </th>
|
|
|
|
<th>
|
|
|
|
<i18n.Translate>Operation</i18n.Translate>
|
|
|
|
</th>
|
|
|
|
<th class="fee">
|
|
|
|
<i18n.Translate>Current</i18n.Translate>
|
|
|
|
</th>
|
|
|
|
<th class="fee">
|
|
|
|
<i18n.Translate>Selected</i18n.Translate>
|
|
|
|
</th>
|
|
|
|
<th>
|
|
|
|
<i18n.Translate>Until</i18n.Translate>
|
|
|
|
</th>
|
|
|
|
</tr>
|
|
|
|
</thead>
|
|
|
|
<tbody>
|
|
|
|
<RenderFeePairByValue
|
|
|
|
list={fees}
|
|
|
|
sorting={(a, b) => a.localeCompare(b)}
|
|
|
|
/>
|
|
|
|
</tbody>
|
|
|
|
</FeeDescriptionTable>
|
|
|
|
</Fragment>
|
|
|
|
);
|
|
|
|
})}
|
|
|
|
</section>
|
|
|
|
<section>
|
|
|
|
<h2>
|
|
|
|
<i18n.Translate>Wallet operations</i18n.Translate>
|
|
|
|
</h2>
|
|
|
|
<p>
|
|
|
|
<i18n.Translate>
|
|
|
|
Every operation in this section may be different by transfer type
|
|
|
|
and is valid for a period of time. The exchange will charge the
|
|
|
|
indicated amount every time a transfer is made.
|
|
|
|
</i18n.Translate>
|
|
|
|
</p>
|
|
|
|
<FeeDescriptionTable>
|
|
|
|
<thead>
|
|
|
|
<tr>
|
|
|
|
<th> </th>
|
|
|
|
<th>
|
|
|
|
<i18n.Translate>Feature</i18n.Translate>
|
|
|
|
</th>
|
|
|
|
<th class="fee">
|
|
|
|
<i18n.Translate>Current</i18n.Translate>
|
|
|
|
</th>
|
|
|
|
<th class="fee">
|
|
|
|
<i18n.Translate>Selected</i18n.Translate>
|
|
|
|
</th>
|
|
|
|
<th>
|
|
|
|
<i18n.Translate>Until</i18n.Translate>
|
|
|
|
</th>
|
|
|
|
</tr>
|
|
|
|
</thead>
|
|
|
|
<tbody>
|
|
|
|
<RenderFeePairByValue
|
|
|
|
list={globalFeeTimeline}
|
|
|
|
sorting={(a, b) => a.localeCompare(b)}
|
|
|
|
/>
|
|
|
|
</tbody>
|
|
|
|
</FeeDescriptionTable>
|
|
|
|
</section>
|
|
|
|
<section>
|
|
|
|
<ButtonGroupFooter>
|
|
|
|
<Button onClick={onShowPrivacy.onClick} variant="outlined">
|
|
|
|
Privacy policy
|
|
|
|
</Button>
|
|
|
|
<Button onClick={onShowTerms.onClick} variant="outlined">
|
|
|
|
Terms of service
|
|
|
|
</Button>
|
|
|
|
</ButtonGroupFooter>
|
|
|
|
</section>
|
2022-08-26 06:08:51 +02:00
|
|
|
<section>
|
2022-10-14 16:40:38 +02:00
|
|
|
<ButtonGroupFooter>
|
2022-10-14 21:12:24 +02:00
|
|
|
<Button onClick={onShowPrivacy.onClick} variant="outlined">
|
|
|
|
Privacy policy
|
|
|
|
</Button>
|
|
|
|
<Button onClick={onShowTerms.onClick} variant="outlined">
|
|
|
|
Terms of service
|
|
|
|
</Button>
|
2022-10-14 16:40:38 +02:00
|
|
|
</ButtonGroupFooter>
|
2022-08-26 06:08:51 +02:00
|
|
|
</section>
|
|
|
|
</Container>
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
export function ReadyView({
|
|
|
|
exchanges,
|
|
|
|
selected,
|
|
|
|
onClose,
|
2022-10-14 21:12:24 +02:00
|
|
|
onShowPrivacy,
|
|
|
|
onShowTerms,
|
2022-08-26 06:08:51 +02:00
|
|
|
}: State.Ready): VNode {
|
|
|
|
const { i18n } = useTranslationContext();
|
|
|
|
|
|
|
|
return (
|
|
|
|
<Container>
|
|
|
|
<h2>
|
|
|
|
<i18n.Translate>Service fee description</i18n.Translate>
|
|
|
|
</h2>
|
2022-10-12 20:58:10 +02:00
|
|
|
<p>
|
|
|
|
All fee indicated below are in the same and only currency the exchange
|
|
|
|
works.
|
|
|
|
</p>
|
2022-08-26 06:08:51 +02:00
|
|
|
<section>
|
|
|
|
<div
|
|
|
|
style={{
|
|
|
|
display: "flex",
|
|
|
|
flexWrap: "wrap",
|
|
|
|
alignItems: "center",
|
|
|
|
justifyContent: "space-between",
|
|
|
|
}}
|
|
|
|
>
|
2022-10-12 20:58:10 +02:00
|
|
|
{Object.keys(exchanges.list).length === 1 ? (
|
|
|
|
<Fragment>
|
|
|
|
<p>Exchange: {selected.exchangeBaseUrl}</p>
|
|
|
|
</Fragment>
|
|
|
|
) : (
|
|
|
|
<p>
|
|
|
|
<Input>
|
|
|
|
<SelectList
|
|
|
|
label={
|
|
|
|
<i18n.Translate>
|
|
|
|
Select {selected.currency} exchange
|
|
|
|
</i18n.Translate>
|
|
|
|
}
|
|
|
|
list={exchanges.list}
|
|
|
|
name="lang"
|
|
|
|
value={exchanges.value}
|
|
|
|
onChange={exchanges.onChange}
|
|
|
|
/>
|
|
|
|
</Input>
|
|
|
|
</p>
|
|
|
|
)}
|
2022-08-26 06:08:51 +02:00
|
|
|
<Button variant="outlined" onClick={onClose.onClick}>
|
2022-09-13 16:07:39 +02:00
|
|
|
<i18n.Translate>Close</i18n.Translate>
|
2022-08-26 06:08:51 +02:00
|
|
|
</Button>
|
|
|
|
</div>
|
|
|
|
</section>
|
|
|
|
<section>
|
|
|
|
<dl>
|
|
|
|
<dt>Auditors</dt>
|
|
|
|
{selected.auditors.length === 0 ? (
|
2022-09-13 16:07:39 +02:00
|
|
|
<dd style={{ color: "red" }}>
|
|
|
|
<i18n.Translate>Doesn't have auditors</i18n.Translate>
|
|
|
|
</dd>
|
2022-08-26 06:08:51 +02:00
|
|
|
) : (
|
|
|
|
selected.auditors.map((a) => {
|
|
|
|
<dd>{a.auditor_url}</dd>;
|
|
|
|
})
|
|
|
|
)}
|
|
|
|
</dl>
|
|
|
|
<table>
|
|
|
|
<tr>
|
2022-09-13 16:07:39 +02:00
|
|
|
<td>
|
2022-10-12 20:58:10 +02:00
|
|
|
<i18n.Translate>Currency</i18n.Translate>
|
|
|
|
</td>
|
|
|
|
<td>
|
|
|
|
<b>{selected.currency}</b>
|
2022-09-13 16:07:39 +02:00
|
|
|
</td>
|
2022-08-26 06:08:51 +02:00
|
|
|
</tr>
|
|
|
|
</table>
|
|
|
|
</section>
|
|
|
|
<section>
|
2022-09-13 16:07:39 +02:00
|
|
|
<h2>
|
2022-10-12 20:58:10 +02:00
|
|
|
<i18n.Translate>Coin operations</i18n.Translate>
|
2022-09-13 16:07:39 +02:00
|
|
|
</h2>
|
2022-10-12 20:58:10 +02:00
|
|
|
<p>
|
|
|
|
<i18n.Translate>
|
|
|
|
Every operation in this section may be different by denomination
|
|
|
|
value and is valid for a period of time. The exchange will charge
|
|
|
|
the indicated amount every time a coin is used in such operation.
|
|
|
|
</i18n.Translate>
|
|
|
|
</p>
|
2022-09-13 16:07:39 +02:00
|
|
|
<p>
|
|
|
|
<i18n.Translate>Deposits</i18n.Translate>
|
|
|
|
</p>
|
2022-08-26 06:08:51 +02:00
|
|
|
<FeeDescriptionTable>
|
|
|
|
<thead>
|
|
|
|
<tr>
|
|
|
|
<th> </th>
|
2022-09-13 16:07:39 +02:00
|
|
|
<th>
|
|
|
|
<i18n.Translate>Denomination</i18n.Translate>
|
|
|
|
</th>
|
|
|
|
<th class="fee">
|
|
|
|
<i18n.Translate>Fee</i18n.Translate>
|
|
|
|
</th>
|
|
|
|
<th>
|
|
|
|
<i18n.Translate>Until</i18n.Translate>
|
|
|
|
</th>
|
2022-08-26 06:08:51 +02:00
|
|
|
</tr>
|
|
|
|
</thead>
|
|
|
|
<tbody>
|
2022-10-12 20:58:10 +02:00
|
|
|
<RenderFeeDescriptionByValue
|
|
|
|
list={selected.denomFees.deposit}
|
|
|
|
sorting={(a, b) => Number(a) - Number(b)}
|
|
|
|
/>
|
2022-08-26 06:08:51 +02:00
|
|
|
</tbody>
|
|
|
|
</FeeDescriptionTable>
|
2022-09-13 16:07:39 +02:00
|
|
|
<p>
|
|
|
|
<i18n.Translate>Withdrawals</i18n.Translate>
|
|
|
|
</p>
|
2022-08-26 06:08:51 +02:00
|
|
|
<FeeDescriptionTable>
|
|
|
|
<thead>
|
|
|
|
<tr>
|
|
|
|
<th> </th>
|
2022-09-13 16:07:39 +02:00
|
|
|
<th>
|
|
|
|
<i18n.Translate>Denomination</i18n.Translate>
|
|
|
|
</th>
|
|
|
|
<th class="fee">
|
|
|
|
<i18n.Translate>Fee</i18n.Translate>
|
|
|
|
</th>
|
|
|
|
<th>
|
|
|
|
<i18n.Translate>Until</i18n.Translate>
|
|
|
|
</th>
|
2022-08-26 06:08:51 +02:00
|
|
|
</tr>
|
|
|
|
</thead>
|
|
|
|
<tbody>
|
2022-10-12 20:58:10 +02:00
|
|
|
<RenderFeeDescriptionByValue
|
|
|
|
list={selected.denomFees.withdraw}
|
|
|
|
sorting={(a, b) => Number(a) - Number(b)}
|
|
|
|
/>
|
2022-08-26 06:08:51 +02:00
|
|
|
</tbody>
|
|
|
|
</FeeDescriptionTable>
|
2022-09-13 16:07:39 +02:00
|
|
|
<p>
|
|
|
|
<i18n.Translate>Refunds</i18n.Translate>
|
|
|
|
</p>
|
2022-08-26 06:08:51 +02:00
|
|
|
<FeeDescriptionTable>
|
|
|
|
<thead>
|
|
|
|
<tr>
|
|
|
|
<th> </th>
|
2022-09-13 16:07:39 +02:00
|
|
|
<th>
|
|
|
|
<i18n.Translate>Denomination</i18n.Translate>
|
|
|
|
</th>
|
|
|
|
<th class="fee">
|
|
|
|
<i18n.Translate>Fee</i18n.Translate>
|
|
|
|
</th>
|
|
|
|
<th>
|
|
|
|
<i18n.Translate>Until</i18n.Translate>
|
|
|
|
</th>
|
2022-08-26 06:08:51 +02:00
|
|
|
</tr>
|
|
|
|
</thead>
|
|
|
|
<tbody>
|
2022-10-12 20:58:10 +02:00
|
|
|
<RenderFeeDescriptionByValue
|
|
|
|
list={selected.denomFees.refund}
|
|
|
|
sorting={(a, b) => Number(a) - Number(b)}
|
|
|
|
/>
|
2022-08-26 06:08:51 +02:00
|
|
|
</tbody>
|
|
|
|
</FeeDescriptionTable>{" "}
|
2022-09-13 16:07:39 +02:00
|
|
|
<p>
|
|
|
|
<i18n.Translate>Refresh</i18n.Translate>
|
|
|
|
</p>
|
2022-08-26 06:08:51 +02:00
|
|
|
<FeeDescriptionTable>
|
|
|
|
<thead>
|
|
|
|
<tr>
|
|
|
|
<th> </th>
|
2022-09-13 16:07:39 +02:00
|
|
|
<th>
|
|
|
|
<i18n.Translate>Denomination</i18n.Translate>
|
|
|
|
</th>
|
|
|
|
<th class="fee">
|
|
|
|
<i18n.Translate>Fee</i18n.Translate>
|
|
|
|
</th>
|
|
|
|
<th>
|
|
|
|
<i18n.Translate>Until</i18n.Translate>
|
|
|
|
</th>
|
2022-08-26 06:08:51 +02:00
|
|
|
</tr>
|
|
|
|
</thead>
|
|
|
|
<tbody>
|
2022-10-12 20:58:10 +02:00
|
|
|
<RenderFeeDescriptionByValue
|
|
|
|
list={selected.denomFees.refresh}
|
|
|
|
sorting={(a, b) => Number(a) - Number(b)}
|
|
|
|
/>
|
2022-08-26 06:08:51 +02:00
|
|
|
</tbody>
|
2022-10-12 20:58:10 +02:00
|
|
|
</FeeDescriptionTable>
|
2022-08-26 06:08:51 +02:00
|
|
|
</section>
|
|
|
|
<section>
|
2022-10-12 20:58:10 +02:00
|
|
|
<h2>
|
|
|
|
<i18n.Translate>Transfer operations</i18n.Translate>
|
|
|
|
</h2>
|
|
|
|
<p>
|
|
|
|
<i18n.Translate>
|
|
|
|
Every operation in this section may be different by transfer type
|
|
|
|
and is valid for a period of time. The exchange will charge the
|
|
|
|
indicated amount every time a transfer is made.
|
|
|
|
</i18n.Translate>
|
|
|
|
</p>
|
|
|
|
{Object.entries(selected.transferFees).map(([type, fees], idx) => {
|
|
|
|
return (
|
|
|
|
<Fragment key={idx}>
|
|
|
|
<p>{type}</p>
|
|
|
|
<FeeDescriptionTable>
|
|
|
|
<thead>
|
|
|
|
<tr>
|
|
|
|
<th> </th>
|
|
|
|
<th>
|
|
|
|
<i18n.Translate>Operation</i18n.Translate>
|
|
|
|
</th>
|
|
|
|
<th class="fee">
|
|
|
|
<i18n.Translate>Fee</i18n.Translate>
|
|
|
|
</th>
|
|
|
|
<th>
|
|
|
|
<i18n.Translate>Until</i18n.Translate>
|
|
|
|
</th>
|
|
|
|
</tr>
|
|
|
|
</thead>
|
|
|
|
<tbody>
|
|
|
|
<RenderFeeDescriptionByValue list={fees} />
|
|
|
|
</tbody>
|
|
|
|
</FeeDescriptionTable>
|
|
|
|
</Fragment>
|
|
|
|
);
|
|
|
|
})}
|
|
|
|
</section>
|
|
|
|
<section>
|
|
|
|
<h2>
|
|
|
|
<i18n.Translate>Wallet operations</i18n.Translate>
|
|
|
|
</h2>
|
|
|
|
<p>
|
|
|
|
<i18n.Translate>
|
|
|
|
Every operation in this section may be different by transfer type
|
|
|
|
and is valid for a period of time. The exchange will charge the
|
|
|
|
indicated amount every time a transfer is made.
|
|
|
|
</i18n.Translate>
|
|
|
|
</p>
|
|
|
|
<FeeDescriptionTable>
|
2022-08-26 06:08:51 +02:00
|
|
|
<thead>
|
|
|
|
<tr>
|
2022-10-12 20:58:10 +02:00
|
|
|
<th> </th>
|
|
|
|
<th>
|
|
|
|
<i18n.Translate>Feature</i18n.Translate>
|
|
|
|
</th>
|
|
|
|
<th class="fee">
|
2022-09-13 16:07:39 +02:00
|
|
|
<i18n.Translate>Fee</i18n.Translate>
|
2022-10-12 20:58:10 +02:00
|
|
|
</th>
|
|
|
|
<th>
|
|
|
|
<i18n.Translate>Until</i18n.Translate>
|
|
|
|
</th>
|
2022-08-26 06:08:51 +02:00
|
|
|
</tr>
|
|
|
|
</thead>
|
|
|
|
<tbody>
|
2022-10-12 20:58:10 +02:00
|
|
|
<RenderFeeDescriptionByValue list={selected.globalFees} />
|
2022-08-26 06:08:51 +02:00
|
|
|
</tbody>
|
2022-10-12 20:58:10 +02:00
|
|
|
</FeeDescriptionTable>
|
2022-08-26 06:08:51 +02:00
|
|
|
</section>
|
|
|
|
<section>
|
2022-10-14 16:40:38 +02:00
|
|
|
<ButtonGroupFooter>
|
2022-10-14 21:12:24 +02:00
|
|
|
<Button onClick={onShowPrivacy.onClick} variant="outlined">
|
|
|
|
Privacy policy
|
|
|
|
</Button>
|
|
|
|
<Button onClick={onShowTerms.onClick} variant="outlined">
|
|
|
|
Terms of service
|
|
|
|
</Button>
|
2022-10-14 16:40:38 +02:00
|
|
|
</ButtonGroupFooter>
|
2022-08-26 06:08:51 +02:00
|
|
|
</section>
|
|
|
|
</Container>
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
function FeeDescriptionRowsGroup({
|
|
|
|
infos,
|
|
|
|
}: {
|
|
|
|
infos: FeeDescription[];
|
|
|
|
}): VNode {
|
|
|
|
const [expanded, setExpand] = useState(false);
|
|
|
|
const hasMoreInfo = infos.length > 1;
|
|
|
|
return (
|
|
|
|
<Fragment>
|
|
|
|
{infos.map((info, idx) => {
|
|
|
|
const main = idx === 0;
|
|
|
|
return (
|
|
|
|
<tr
|
|
|
|
key={idx}
|
|
|
|
class="value"
|
2022-10-12 20:58:10 +02:00
|
|
|
data-hasMore={hasMoreInfo}
|
2022-08-26 06:08:51 +02:00
|
|
|
data-main={main}
|
|
|
|
data-hidden={!main && !expanded}
|
|
|
|
onClick={() => setExpand((p) => !p)}
|
|
|
|
>
|
|
|
|
<td class="icon">
|
|
|
|
{hasMoreInfo && main ? (
|
|
|
|
<SvgIcon
|
|
|
|
title="Select this contact"
|
|
|
|
dangerouslySetInnerHTML={{ __html: arrowDown }}
|
|
|
|
color="currentColor"
|
|
|
|
transform={expanded ? "" : "rotate(-90deg)"}
|
|
|
|
/>
|
|
|
|
) : undefined}
|
|
|
|
</td>
|
2022-10-12 20:58:10 +02:00
|
|
|
<td class="value">{main ? info.group : ""}</td>
|
2022-08-26 06:08:51 +02:00
|
|
|
{info.fee ? (
|
|
|
|
<td class="fee">{<Amount value={info.fee} hideCurrency />}</td>
|
|
|
|
) : undefined}
|
|
|
|
<td class="expiration">
|
|
|
|
<Time timestamp={info.until} format="dd-MMM-yyyy" />
|
|
|
|
</td>
|
|
|
|
</tr>
|
|
|
|
);
|
|
|
|
})}
|
|
|
|
</Fragment>
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
function FeePairRowsGroup({ infos }: { infos: FeeDescriptionPair[] }): VNode {
|
|
|
|
const [expanded, setExpand] = useState(false);
|
|
|
|
const hasMoreInfo = infos.length > 1;
|
|
|
|
return (
|
|
|
|
<Fragment>
|
|
|
|
{infos.map((info, idx) => {
|
|
|
|
const main = idx === 0;
|
|
|
|
return (
|
|
|
|
<tr
|
|
|
|
key={idx}
|
|
|
|
class="value"
|
2022-10-12 20:58:10 +02:00
|
|
|
data-hasMore={hasMoreInfo}
|
2022-08-26 06:08:51 +02:00
|
|
|
data-main={main}
|
|
|
|
data-hidden={!main && !expanded}
|
|
|
|
onClick={() => setExpand((p) => !p)}
|
|
|
|
>
|
|
|
|
<td class="icon">
|
|
|
|
{hasMoreInfo && main ? (
|
|
|
|
<SvgIcon
|
2022-11-18 15:29:24 +01:00
|
|
|
title="Expand"
|
2022-08-26 06:08:51 +02:00
|
|
|
dangerouslySetInnerHTML={{ __html: arrowDown }}
|
|
|
|
color="currentColor"
|
|
|
|
transform={expanded ? "" : "rotate(-90deg)"}
|
|
|
|
/>
|
|
|
|
) : undefined}
|
|
|
|
</td>
|
2022-10-12 20:58:10 +02:00
|
|
|
<td class="value">{main ? info.group : ""}</td>
|
2022-08-26 06:08:51 +02:00
|
|
|
{info.left ? (
|
|
|
|
<td class="fee">{<Amount value={info.left} hideCurrency />}</td>
|
|
|
|
) : (
|
|
|
|
<td class="fee"> --- </td>
|
|
|
|
)}
|
|
|
|
{info.right ? (
|
|
|
|
<td class="fee">{<Amount value={info.right} hideCurrency />}</td>
|
|
|
|
) : (
|
|
|
|
<td class="fee"> --- </td>
|
|
|
|
)}
|
|
|
|
<td class="expiration">
|
2022-11-18 15:29:24 +01:00
|
|
|
<Time timestamp={info.until} format="dd-MMM-yyyy HH:mm:ss" />
|
2022-08-26 06:08:51 +02:00
|
|
|
</td>
|
|
|
|
</tr>
|
|
|
|
);
|
|
|
|
})}
|
|
|
|
</Fragment>
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Group by value and then render using FeePairRowsGroup
|
|
|
|
* @param param0
|
|
|
|
* @returns
|
|
|
|
*/
|
2022-11-18 15:29:24 +01:00
|
|
|
function RenderFeePairByValue({
|
|
|
|
list,
|
|
|
|
sorting,
|
|
|
|
}: {
|
|
|
|
list: FeeDescriptionPair[];
|
|
|
|
sorting?: (a: string, b: string) => number;
|
|
|
|
}): VNode {
|
|
|
|
const grouped = list.reduce((prev, cur) => {
|
|
|
|
if (!prev[cur.group]) {
|
|
|
|
prev[cur.group] = [];
|
|
|
|
}
|
|
|
|
prev[cur.group].push(cur);
|
|
|
|
return prev;
|
|
|
|
}, {} as Record<string, FeeDescriptionPair[]>);
|
|
|
|
const p = Object.keys(grouped)
|
|
|
|
.sort(sorting)
|
|
|
|
.map((i, idx) => <FeePairRowsGroup key={idx} infos={grouped[i]} />);
|
|
|
|
return <Fragment>{p}</Fragment>;
|
2022-08-26 06:08:51 +02:00
|
|
|
}
|
|
|
|
/**
|
|
|
|
*
|
|
|
|
* Group by value and then render using FeeDescriptionRowsGroup
|
|
|
|
* @param param0
|
|
|
|
* @returns
|
|
|
|
*/
|
|
|
|
function RenderFeeDescriptionByValue({
|
2022-10-12 20:58:10 +02:00
|
|
|
list,
|
|
|
|
sorting,
|
2022-08-26 06:08:51 +02:00
|
|
|
}: {
|
2022-10-12 20:58:10 +02:00
|
|
|
list: FeeDescription[];
|
|
|
|
sorting?: (a: string, b: string) => number;
|
2022-08-26 06:08:51 +02:00
|
|
|
}): VNode {
|
2022-10-12 20:58:10 +02:00
|
|
|
const grouped = list.reduce((prev, cur) => {
|
|
|
|
if (!prev[cur.group]) {
|
|
|
|
prev[cur.group] = [];
|
|
|
|
}
|
|
|
|
prev[cur.group].push(cur);
|
|
|
|
return prev;
|
|
|
|
}, {} as Record<string, FeeDescription[]>);
|
|
|
|
const p = Object.keys(grouped)
|
|
|
|
.sort(sorting)
|
|
|
|
.map((i, idx) => <FeeDescriptionRowsGroup key={idx} infos={grouped[i]} />);
|
|
|
|
return <Fragment>{p}</Fragment>;
|
2022-08-26 06:08:51 +02:00
|
|
|
}
|