diff --git a/public/assets/locales/fa/translation.json b/public/assets/locales/fa/translation.json index 0adb2e0c..034d07df 100644 --- a/public/assets/locales/fa/translation.json +++ b/public/assets/locales/fa/translation.json @@ -337,8 +337,6 @@ "cancel": "لغو", "seconds": "ثانیه", "submitPaymentReq": "ثبت درخواست واریز", - "noInventory": "موجودی کافی نیست !", - "allowableWithdraw": "حداقل مقدار مجاز برداشت رعایت نشده است.", "fillAddress": "وارد کردن آدرس الزامیست.", "important": "مهم", "DepositTETHContentBefore": "فقط ETH تستی شبکه Ropsten مورد قبول قرار می گیرد! برای دریافت رایگان به ", @@ -354,7 +352,11 @@ "network": "شبکه", "selectNetwork": " شبکه را انتخاب کنید", "gettingAddress": "درحال گرفتن آدرس...", - "errorGettingAddress": "خطا در گرفتن آدرس" + "errorGettingAddress": "خطا در گرفتن آدرس", + + "noInventory": "موجودی کافی نیست !", + "noInventorywithdrawFee": "با احتساب کارمزد، موجودی کافی نیست !", + "allowableWithdraw": "حداقل مقدار مجاز برداشت رعایت نشده است." }, "CallbackPage": { "ok": "واریز وجه با موفقیت انجام شد.", @@ -380,6 +382,7 @@ "inventory": "موجودی بعد از تراکنش", "freeWallet": "موجودی قابل برداشت", "minWithdraw": "حداقل مقدار برداشت", + "maxWithdrawal": "حداکثر مقدار برداشت", "minDeposit": "حداقل مقدار واریز", "maxWithdraw": "سقف برداشت روزانه شما", "maxMonthWithdraw": "سقف برداشت ماهانه شما", diff --git a/src/components/NumberInput/NumberInput.js b/src/components/NumberInput/NumberInput.js index 54de1716..ee5904b9 100644 --- a/src/components/NumberInput/NumberInput.js +++ b/src/components/NumberInput/NumberInput.js @@ -62,7 +62,7 @@ const NumberInput = (props) => { customClass="hint-icon" />
- { alerts.map((alert , index) => {alert}) } + { alerts?.map((alert , index) => {alert}) }
} diff --git a/src/components/Popup/Popup.js b/src/components/Popup/Popup.js index 16038f1b..b844d591 100644 --- a/src/components/Popup/Popup.js +++ b/src/components/Popup/Popup.js @@ -11,6 +11,8 @@ import {useGetCurrencyInfo} from "../../queries"; import Loading from "../Loading/Loading"; import Error from "../Error/Error"; import PopupAddress from "./PopupAddress/PopupAddress"; +import i18n from "i18next"; +import {getCurrencyNameOrAlias} from "../../utils/utils"; const Popup = ({currency, closePopup}) => { @@ -18,6 +20,8 @@ const Popup = ({currency, closePopup}) => { const isLogin = useSelector((state) => state.auth.isLogin) + const language = i18n.language + const currencies = useSelector((state) => state.exchange.currencies) const [networkName, setNetworkName] = useState({value: 0, error: []}); @@ -75,7 +79,7 @@ const Popup = ({currency, closePopup}) => { return (
-

{t("deposit")} {t("currency." + currency)}

+

{t("deposit")} {getCurrencyNameOrAlias(currencies[currency], language)}

{content()} diff --git a/src/components/TextInput/TextInput.js b/src/components/TextInput/TextInput.js index 5cca9b97..4aeccb93 100644 --- a/src/components/TextInput/TextInput.js +++ b/src/components/TextInput/TextInput.js @@ -35,17 +35,21 @@ const TextInput = (props) => { const type = useSelector((state) => state.exchange.dateType) const optionClassHandler = (state) => { - let className = classes.selectOptions + let className = classes.selectOptions; if (state.isFocused) { - className = className + " " + classes.isFocused + className += " " + classes.isFocused; } if (state.isSelected) { - className = className + " " + classes.isSelected + className += " " + classes.isSelected; + } + if (state.isDisabled) { + className += " " + classes.disabledOption; // اضافه کردن کلاس برای گزینه‌های غیرفعال } return className; - } + }; + const calenderTypeHandler = () => { if (type === "Hijri" && i18n.language === "en") { diff --git a/src/components/TextInput/TextInput.module.css b/src/components/TextInput/TextInput.module.css index ed9c9756..0891552f 100644 --- a/src/components/TextInput/TextInput.module.css +++ b/src/components/TextInput/TextInput.module.css @@ -209,4 +209,10 @@ /*width: 1px !important;*/ } +.disabledOption { + color: var(--gray) !important; + background-color: var(--deActive) !important; + cursor: not-allowed !important; +} + diff --git a/src/index.js b/src/index.js index 2758ac78..e2b29805 100644 --- a/src/index.js +++ b/src/index.js @@ -76,6 +76,7 @@ i18n }); + const Toast = () => { return { const query = useQuery(); @@ -34,6 +35,8 @@ const Browser = () => { const title = useSelector((state) => state.exchange.title) const description = useSelector((state) => state.exchange.description) + const currencies = useSelector((state) => state.exchange.currencies) + const fees = useSelector((state) => state.exchange.fees) theme === "DARK" ? document.body.classList.add('dark') : document.body.classList.remove('dark'); diff --git a/src/main/Browser/Pages/AllMarket/components/AllMarketInfo/AllMarketInfo.js b/src/main/Browser/Pages/AllMarket/components/AllMarketInfo/AllMarketInfo.js index 049e5d9f..e4797e16 100644 --- a/src/main/Browser/Pages/AllMarket/components/AllMarketInfo/AllMarketInfo.js +++ b/src/main/Browser/Pages/AllMarket/components/AllMarketInfo/AllMarketInfo.js @@ -1,4 +1,4 @@ -import React, {useState} from 'react'; +import React, {useEffect, useState} from 'react'; import classes from './AllMarketInfo.module.css' import Icon from "../../../../../../components/Icon/Icon"; import AllMarketInfoCard from "./components/AllMarketInfoCard/AllMarketInfoCard"; @@ -9,6 +9,8 @@ import Loading from "../../../../../../components/Loading/Loading"; import Error from "../../../../../../components/Error/Error"; import {setMarketInterval} from "../../../../../../store/actions"; import {useTranslation} from "react-i18next"; +import i18n from "i18next"; +import {getCurrencyNameOrAlias} from "../../../../../../utils/utils"; const AllMarketInfo = () => { @@ -21,13 +23,22 @@ const AllMarketInfo = () => { const interval = useSelector((state) => state.global.marketInterval) const quote = activeCurrency === "" ? null : activeCurrency + const language = i18n.language + const currencies = useSelector((state) => state.exchange.currencies) + const {data: overview, isLoading, error} = useOverview(null, interval, quote) - const {data: currencies} = useGetQuoteCurrencies() + const {data: quoteCurrencies, isLoading:quoteCurrenciesIsLoading, error:quoteCurrenciesError} = useGetQuoteCurrencies() + + useEffect(() => { + if (quoteCurrencies?.length > 0) { + setActiveCurrency(quoteCurrencies[0]); + } + }, [quoteCurrencies]); const content = () => { - if (isLoading) return
- if (error) return
+ if (isLoading || quoteCurrenciesIsLoading) return
+ if (error || quoteCurrenciesError) return
else return <> {card ? @@ -44,8 +55,8 @@ const AllMarketInfo = () => { setCard(prevState => !prevState)}/>

setActiveCurrency("")}>{t("market.title")}

- {currencies?.map((currency) => - setActiveCurrency(currency)} key={currency}>{t("currency." + currency)} + {quoteCurrencies?.map((currency) => + setActiveCurrency(currency)} key={currency}>{getCurrencyNameOrAlias(currencies[currency], language)} )}
diff --git a/src/main/Browser/Pages/AllMarket/components/AllMarketInfo/components/AllMarketInfoCard/AllMarketInfoCard.js b/src/main/Browser/Pages/AllMarket/components/AllMarketInfo/components/AllMarketInfoCard/AllMarketInfoCard.js index a3741bbd..ac5d2983 100644 --- a/src/main/Browser/Pages/AllMarket/components/AllMarketInfo/components/AllMarketInfoCard/AllMarketInfoCard.js +++ b/src/main/Browser/Pages/AllMarket/components/AllMarketInfo/components/AllMarketInfoCard/AllMarketInfoCard.js @@ -3,7 +3,7 @@ import classes from './AllMarketInfoCard.module.css' import {useTranslation} from "react-i18next"; import {images} from "../../../../../../../../assets/images"; import Button from "../../../../../../../../components/Button/Button"; -import {BN} from "../../../../../../../../utils/utils"; +import {BN, getCurrencyNameOrAlias} from "../../../../../../../../utils/utils"; import {setActivePairInitiate} from "../../../../../../../../store/actions"; import {Panel} from "../../../../../../Routes/routes"; import {useNavigate} from "react-router-dom"; @@ -16,6 +16,8 @@ const AllMarketInfoCard = ({data, activeCurrency}) => { const {t} = useTranslation(); const navigate = useNavigate(); const dispatch = useDispatch(); + const language = i18n.language + const currencies = useSelector((state) => state.exchange.currencies) const allExchangeSymbols = useSelector((state) => state.exchange.symbols) const [showButton, setShowButton] = useState(null) @@ -53,33 +55,38 @@ const AllMarketInfoCard = ({data, activeCurrency}) => {
MouseEnterEventHandler(index)} onMouseLeave={MouseLeaveEventHandler}>
-
+
- {tr?.base} - {activeCurrency ? t("currency." + tr?.base) : tr?.base + " / " + tr?.quote} + {activeCurrency ? + <> + {getCurrencyNameOrAlias(currencies[tr?.base], language)} + {tr?.base} + + : tr?.base + " / " + tr?.quote}
- 0 ? "text-green" : "text-red"} direction-ltr mr-05`}>{new BN(tr.priceChangePercent).toFormat(2)} % + 0 ? "text-green" : tr.priceChangePercent < 0 ? "text-red" : ""} direction-ltr`}>{tr.priceChangePercent === 0 ? "0 %" : `${new BN(tr.priceChangePercent).toFormat(2)} %`}
{t("MarketInfo.lastPrice")}: - 0 ? "text-green" : "text-red"} fs-01`}>{new BN(tr.lastPrice).toFormat()} {t("currency." + tr?.quote)} + 0 ? "text-green" : "text-red"} fs-01`}>{new BN(tr.lastPrice).toFormat()} {tr?.quote}
{t("MarketInfo.lowPrice")}: - {new BN(tr.lowPrice).toFormat()} + {new BN(tr.lowPrice).decimalPlaces(currencies[tr?.quote]?.precision ?? 0).toFormat()} {tr?.quote}
{t("MarketInfo.highPrice")}: - {new BN(tr.highPrice).toFormat()} + {new BN(tr.highPrice).decimalPlaces(currencies[tr?.quote]?.precision ?? 0).toFormat()} {tr?.quote}
{t("MarketInfo.volume")}: - {new BN(tr.volume).toFormat()} + {new BN(tr.volume).decimalPlaces(currencies[tr?.base]?.precision ?? 0).toFormat()} {tr?.base}
diff --git a/src/main/Browser/Pages/AllMarket/components/AllMarketInfo/components/AllMarketInfoTable/AllMarketInfoTable.js b/src/main/Browser/Pages/AllMarket/components/AllMarketInfo/components/AllMarketInfoTable/AllMarketInfoTable.js index ca325345..10369eb9 100644 --- a/src/main/Browser/Pages/AllMarket/components/AllMarketInfo/components/AllMarketInfoTable/AllMarketInfoTable.js +++ b/src/main/Browser/Pages/AllMarket/components/AllMarketInfo/components/AllMarketInfoTable/AllMarketInfoTable.js @@ -3,7 +3,7 @@ import classes from './AllMarketInfoTable.module.css' import {useTranslation} from "react-i18next"; import {images} from "../../../../../../../../assets/images"; import Button from "../../../../../../../../components/Button/Button"; -import {BN} from "../../../../../../../../utils/utils"; +import {BN, getCurrencyNameOrAlias} from "../../../../../../../../utils/utils"; import i18n from "i18next"; import {setActivePairInitiate} from "../../../../../../../../store/actions"; import {Panel} from "../../../../../../Routes/routes"; @@ -17,6 +17,9 @@ const AllMarketInfTable = ({data, activeCurrency}) => { const dispatch = useDispatch(); const allExchangeSymbols = useSelector((state) => state.exchange.symbols) + const language = i18n.language + const currencies = useSelector((state) => state.exchange.currencies) + const navigateToPanel = (symbol) => { const selectedPair = allExchangeSymbols.find( s => s.symbol === symbol) dispatch(setActivePairInitiate(selectedPair, 0)) @@ -25,17 +28,17 @@ const AllMarketInfTable = ({data, activeCurrency}) => { let head = (
- {t("MarketInfo.name")} + {t("MarketInfo.name")} {t("MarketInfo.lastPrice")} - {t("MarketInfo.priceChange")} + {t("MarketInfo.priceChange")} {t("MarketInfo.lowPrice")} {t("MarketInfo.highPrice")} - {t("MarketInfo.volume")} + {t("MarketInfo.volume")} {/*{t("MarketInfo.lowPrice")} {t("MarketInfo.highPrice")}*/} - {t("MarketInfo.chart")}{/* - {t("MarketInfo.details")} - {t("MarketInfo.trade")}*/} + {t("MarketInfo.chart")} + +
); @@ -44,25 +47,36 @@ const AllMarketInfTable = ({data, activeCurrency}) => { {data.map((tr, index) => { return (
- - {tr?.base} + {tr?.base} - {activeCurrency ? t("currency." + tr?.base) : tr?.base + " / " + tr?.quote} + {activeCurrency ? + <> + {getCurrencyNameOrAlias(currencies[tr?.base], language)} + {tr?.base} + + + : tr?.base + " / " + tr?.quote} - 0 ? "text-green" : "text-red"}`}>{new BN(tr.lastPrice).toFormat()} {t("currency." + tr?.quote)} + 0 ? "text-green" : "text-red"}`}>{new BN(tr.lastPrice).decimalPlaces(currencies[tr?.quote]?.precision ?? 0).toFormat()} {tr?.quote} + + + + + 0 ? "text-green" : tr.priceChangePercent < 0 ? "text-red" : ""} direction-ltr`}>{tr.priceChangePercent === 0 ? "0 %" : `${new BN(tr.priceChangePercent).toFormat(2)} %`} + - 0 ? "text-green" : "text-red"} direction-ltr`}>{new BN(tr?.priceChangePercent).toFormat(2)} % - {new BN(tr?.lowPrice).toFormat()} + {new BN(tr?.lowPrice).decimalPlaces(currencies[tr?.quote]?.precision ?? 0).toFormat()} {tr?.quote} - {new BN(tr?.highPrice).toFormat()} + {new BN(tr?.highPrice).decimalPlaces(currencies[tr?.quote]?.precision ?? 0).toFormat()} {tr?.quote} - {new BN(tr?.volume).toFormat()} + {new BN(tr?.volume).decimalPlaces(currencies[tr?.base]?.precision ?? 0).toFormat()} {tr?.base} {/*{tr.lowPrice} {tr.highPrice}*/} - + { - const {t} = useTranslation(); + const language = i18n.language + const currencies = useSelector((state) => state.exchange.currencies) return ( <> - {mostDecreasedPrice?.pairInfo?.baseAsset} - {t("currency." + mostDecreasedPrice?.pairInfo?.baseAsset)} + {getCurrencyNameOrAlias(currencies[mostDecreasedPrice?.pairInfo?.baseAsset], language)}
{mostDecreasedPrice?.pairInfo?.quoteAsset} - {new BN(mostDecreasedPrice?.lastPrice).toFormat()} + {new BN(mostDecreasedPrice?.lastPrice).decimalPlaces(currencies[mostDecreasedPrice.pairInfo.quoteAsset]?.precision ?? 0).toFormat()}
- 0 ? "text-green" : "text-red"} direction-ltr`}>{new BN(mostDecreasedPrice?.priceChangePercent).toFormat(2)} % + 0 ? "text-green" : mostDecreasedPrice?.priceChangePercent < 0 ? "text-red" : ""} direction-ltr`}>{mostDecreasedPrice?.priceChangePercent === 0 ? "0 %" : `${new BN(mostDecreasedPrice?.priceChangePercent).toFormat(2)} %`}
); diff --git a/src/main/Browser/Pages/AllMarket/components/PriceInfo/components/MostIncreasedPrice/MostIncreasedPrice.js b/src/main/Browser/Pages/AllMarket/components/PriceInfo/components/MostIncreasedPrice/MostIncreasedPrice.js index 1e4b60a8..213a4ebe 100644 --- a/src/main/Browser/Pages/AllMarket/components/PriceInfo/components/MostIncreasedPrice/MostIncreasedPrice.js +++ b/src/main/Browser/Pages/AllMarket/components/PriceInfo/components/MostIncreasedPrice/MostIncreasedPrice.js @@ -1,26 +1,29 @@ import React from 'react'; import {images} from "../../../../../../../../assets/images"; import i18n from "i18next"; -import {BN} from "../../../../../../../../utils/utils"; +import {BN, getCurrencyNameOrAlias} from "../../../../../../../../utils/utils"; import {useTranslation} from "react-i18next"; +import {useSelector} from "react-redux"; const MostIncreasedPrice = ({mostIncreasedPrice}) => { const {t} = useTranslation(); + const language = i18n.language + const currencies = useSelector((state) => state.exchange.currencies) return ( <> - {mostIncreasedPrice?.pairInfo?.baseAsset} - {t("currency." + mostIncreasedPrice?.pairInfo?.baseAsset)} + {getCurrencyNameOrAlias(currencies[mostIncreasedPrice?.pairInfo?.baseAsset], language)}
{mostIncreasedPrice?.pairInfo?.quoteAsset} - {new BN(mostIncreasedPrice?.lastPrice).toFormat()} + {new BN(mostIncreasedPrice?.lastPrice).decimalPlaces(currencies[mostIncreasedPrice.pairInfo.quoteAsset]?.precision ?? 0).toFormat()}
- 0 ? "text-green" : "text-red"} direction-ltr`}>{new BN(mostIncreasedPrice?.priceChangePercent).toFormat(2)} % + 0 ? "text-green" : mostIncreasedPrice?.priceChangePercent < 0 ? "text-red" : ""} direction-ltr`}>{mostIncreasedPrice?.priceChangePercent === 0 ? "0 %" : `${new BN(mostIncreasedPrice?.priceChangePercent).toFormat(2)} %`}
); diff --git a/src/main/Browser/Pages/AllMarket/components/VolumeInfo/components/MostTrades/MostTrades.js b/src/main/Browser/Pages/AllMarket/components/VolumeInfo/components/MostTrades/MostTrades.js index 6eda6b87..54697300 100644 --- a/src/main/Browser/Pages/AllMarket/components/VolumeInfo/components/MostTrades/MostTrades.js +++ b/src/main/Browser/Pages/AllMarket/components/VolumeInfo/components/MostTrades/MostTrades.js @@ -1,20 +1,22 @@ import React from 'react'; import {images} from "../../../../../../../../assets/images"; import i18n from "i18next"; -import {BN} from "../../../../../../../../utils/utils"; +import {BN, getCurrencyNameOrAlias} from "../../../../../../../../utils/utils"; import {useTranslation} from "react-i18next"; +import {useSelector} from "react-redux"; const MostTrades = ({mostTrades}) => { - const {t} = useTranslation(); + const language = i18n.language + const currencies = useSelector((state) => state.exchange.currencies) return ( <> - {mostTrades?.pairInfo?.baseAsset} - {t("currency." + mostTrades?.pairInfo?.baseAsset)} + {getCurrencyNameOrAlias(currencies[mostTrades?.pairInfo?.baseAsset], language)}
{new BN(mostTrades?.tradeCount).toFormat()}
diff --git a/src/main/Browser/Pages/AllMarket/components/VolumeInfo/components/MostVolume/MostVolume.js b/src/main/Browser/Pages/AllMarket/components/VolumeInfo/components/MostVolume/MostVolume.js index 8ca16917..3555cafc 100644 --- a/src/main/Browser/Pages/AllMarket/components/VolumeInfo/components/MostVolume/MostVolume.js +++ b/src/main/Browser/Pages/AllMarket/components/VolumeInfo/components/MostVolume/MostVolume.js @@ -1,23 +1,25 @@ import React from 'react'; import {images} from "../../../../../../../../assets/images"; import i18n from "i18next"; -import {BN} from "../../../../../../../../utils/utils"; +import {BN, getCurrencyNameOrAlias} from "../../../../../../../../utils/utils"; import {useTranslation} from "react-i18next"; +import {useSelector} from "react-redux"; const MostVolume = ({mostVolume}) => { - const {t} = useTranslation(); + const language = i18n.language + const currencies = useSelector((state) => state.exchange.currencies) return ( <> - {mostVolume?.pairInfo?.baseAsset} - {t("currency." + mostVolume?.pairInfo?.baseAsset)} + {getCurrencyNameOrAlias(currencies[mostVolume?.pairInfo?.baseAsset], language)}
{mostVolume?.pairInfo?.baseAsset} - {new BN(mostVolume?.volume).toFormat()} + {new BN(mostVolume?.volume).decimalPlaces(currencies[mostVolume?.pairInfo?.baseAsset]?.precision ?? 0).toFormat()}
{/*++ to do ++*/} diff --git a/src/main/Browser/Pages/EasyTrading/components/EasyOrder/EasyOrder.js b/src/main/Browser/Pages/EasyTrading/components/EasyOrder/EasyOrder.js index 8ae33257..c65ab7ee 100644 --- a/src/main/Browser/Pages/EasyTrading/components/EasyOrder/EasyOrder.js +++ b/src/main/Browser/Pages/EasyTrading/components/EasyOrder/EasyOrder.js @@ -3,7 +3,7 @@ import classes from './EasyOrder.module.css' import {Trans, useTranslation} from "react-i18next"; import {useDispatch, useSelector} from "react-redux"; import {useGetUserAccount} from "../../../../../../queries/hooks/useGetUserAccount"; -import {BN, parsePriceString} from "../../../../../../utils/utils"; +import {BN, getCurrencyNameOrAlias, parsePriceString} from "../../../../../../utils/utils"; import {useOrderBook} from "../../../../../../queries"; import {toast} from "react-hot-toast"; import {createOrder} from "js-api-client"; @@ -13,6 +13,7 @@ import TextInput from "../../../../../../components/TextInput/TextInput"; import Icon from "../../../../../../components/Icon/Icon"; import NumberInput from "../../../../../../components/NumberInput/NumberInput"; import Button from "../../../../../../components/Button/Button"; +import i18n from "i18next"; const EasyOrder = () => { @@ -22,7 +23,9 @@ const EasyOrder = () => { const [isLoading, setIsLoading] = useState(false) const isLogin = useSelector((state) => state.auth.isLogin) - const symbols = useSelector((state) => state.exchange.symbols) + const language = i18n.language + const currencies = useSelector((state) => state.exchange.currencies) + const pairsList = useSelector((state) => state.exchange.pairsList) const [alert, setAlert] = useState({ submit: false, @@ -30,8 +33,6 @@ const EasyOrder = () => { totalPrice: null, }); - - const [order, setOrder] = useState({ tradeFee: new BN(0), stopLimit: false, @@ -43,31 +44,38 @@ const EasyOrder = () => { }); const handleAvailableAssets = () => { - const availableAssets = []; - for (const symbol of symbols) { - if (!availableAssets.includes(symbol.baseAsset)) availableAssets.push(symbol.baseAsset) - if (!availableAssets.includes(symbol.quoteAsset)) availableAssets.push(symbol.quoteAsset) - } - return availableAssets; - } + const availableAssets = new Set(); + Object.values(pairsList).forEach(pair => { + availableAssets.add(pair.baseAsset); + availableAssets.add(pair.quoteAsset); + }); + return Array.from(availableAssets); + }; const handleAvailableDest = (buy) => { - const dest = [] - for (const symbol of symbols) { - if (symbol.baseAsset === buy) dest.push(symbol.quoteAsset) - if (symbol.quoteAsset === buy) dest.push(symbol.baseAsset) - } - return dest - } + const dest = new Set(); + Object.values(pairsList).forEach(pair => { + if (pair.baseAsset === buy) dest.add(pair.quoteAsset); + if (pair.quoteAsset === buy) dest.add(pair.baseAsset); + }); + return Array.from(dest); + }; + + + const findPair = (buy, sell) => + Object.values(pairsList)?.find(pair => + (pair.baseAsset === buy && pair.quoteAsset === sell) || + (pair.baseAsset === sell && pair.quoteAsset === buy) + ); - const findPair = (buy, sell) => symbols?.find(s => ((s?.baseAsset === buy) && (s?.quoteAsset === sell)) || ((s?.baseAsset === sell) && (s?.quoteAsset === buy))) + const pairsArray = Object.values(pairsList); const [selected, setSelected] = useState({ - buy: symbols[0].baseAsset, - sell: symbols[0].quoteAsset, - pair: findPair(symbols[0].baseAsset, symbols[0].quoteAsset), + buy: pairsArray[0]?.baseAsset, + sell: pairsArray[0]?.quoteAsset, + pair: findPair(pairsArray[0]?.baseAsset, pairsArray[0]?.quoteAsset), type: "ask" - }) + }); const reversePair = () => { @@ -117,23 +125,24 @@ const EasyOrder = () => { let newAlert = null value = parsePriceString(value); const reqAmount = new BN(value); - let range = "baseRange" - if (selected.type === "bid") range = "quoteRange" - if (reqAmount.isZero() && reqAmount.isLessThan(selected.pair[range].min)) { + let selectedCurrency = "baseAsset" + if (selected.type === "bid") selectedCurrency = "quoteAsset" + + if (reqAmount.isZero() && reqAmount.isLessThan(currencies[selected.pair[selectedCurrency]].minOrder)) { newAlert = } - if (!reqAmount.mod(selected.pair[range].step).isZero()) { + if (!reqAmount.mod(currencies[selected.pair[selectedCurrency]].step).isZero()) { newAlert = } setAlert({...alert, reqAmount: newAlert}); @@ -146,28 +155,30 @@ const EasyOrder = () => { }); }; + const totalPriceHandler = (value) => { let newAlert = null value = parsePriceString(value); const totalPrice = new BN(value); - let range = "quoteRange" - if (selected.type === "bid") range = "baseRange" - if (totalPrice.isZero() && totalPrice.isLessThan(selected.pair[range].min)) { + let selectedCurrency = "quoteAsset" + if (selected.type === "bid") selectedCurrency = "baseAsset" + + if (totalPrice.isZero() && totalPrice.isLessThan(currencies[selected.pair[selectedCurrency]].minOrder)) { newAlert = } - if (!totalPrice.mod(selected.pair[range].step).isZero()) { + if (!totalPrice.mod(currencies[selected.pair[selectedCurrency]].step).isZero()) { newAlert = } setAlert({...alert, totalPrice: newAlert}); @@ -184,8 +195,8 @@ const EasyOrder = () => { if (order.pricePerUnit.isEqualTo(0)) return toast.error(t("orders.hasNoOffer")); let totalPrice = new BN(userAccount?.wallets[selected?.sell]?.free); let reqAmount = totalPrice.dividedBy(order.pricePerUnit) - if (!reqAmount.mod(selected.pair?.[selected.type === "ask" ? "baseRange" : "quoteRange"].step).isZero()) { - reqAmount = reqAmount.minus(reqAmount.mod(selected.pair?.[selected.type === "ask" ? "baseRange" : "quoteRange"].step)); + if (!reqAmount.mod(currencies[selected.pair?.[selected.type === "ask" ? "baseAsset" : "quoteAsset"]].step).isZero()) { + reqAmount = reqAmount.minus(reqAmount.mod(currencies[selected.pair?.[selected.type === "ask" ? "baseAsset" : "quoteAsset"]].step)); } buyPriceHandler( reqAmount.toFormat(), @@ -201,7 +212,7 @@ const EasyOrder = () => { setIsLoading(true) const newOrder = {...order} if (selected.type === "bid") { - newOrder.reqAmount = order.totalPrice.decimalPlaces(selected.pair?.baseAssetPrecision) + newOrder.reqAmount = order.totalPrice.decimalPlaces(currencies[selected?.pair?.baseAsset].precision) } createOrder(selected.pair?.symbol, selected.type === "ask" ? "BUY" : "SELL", newOrder) .then((res) => { @@ -217,8 +228,8 @@ const EasyOrder = () => { toast.success( { const buyOnChangeHandler = (e) => { const newBuy = e.value; - const sellOptions = handleAvailableDest(newBuy) + const sellOptions = handleAvailableDest(newBuy); + + setOptions(prevOptions => ({ + ...prevOptions, + sell: sellOptions, + })); - setOptions({ - ...options, - "sell": sellOptions, - }) const sell = sellOptions.includes(selected.sell) ? selected.sell : sellOptions[0]; - const pair = findPair(newBuy, sell) + const pair = findPair(newBuy, sell) || {}; setSelected({ buy: newBuy, sell, pair, - type: newBuy === pair.baseAsset ? "ask" : "bid" - }) + type: pair.baseAsset === newBuy ? "ask" : "bid" + }); + setOrder({ tradeFee: new BN(0), stopLimit: false, @@ -270,22 +283,26 @@ const EasyOrder = () => { reqAmount: new BN(0), pricePerUnit: new BN(0), totalPrice: new BN(0), - }) + }); + setAlert({ submit: false, reqAmount: null, totalPrice: null, - }) - } + }); + }; + const sellOnChangeHandler = (e) => { const newSell = e.value; - const pair = findPair(selected.buy, newSell) - setSelected({ - ...selected, + const pair = findPair(selected.buy, newSell) || {}; + + setSelected(prevSelected => ({ + ...prevSelected, sell: newSell, pair, type: selected.buy === pair.baseAsset ? "ask" : "bid" - }) + })); + setOrder({ tradeFee: new BN(0), stopLimit: false, @@ -294,35 +311,25 @@ const EasyOrder = () => { reqAmount: new BN(0), pricePerUnit: new BN(0), totalPrice: new BN(0), - }) + }); + setAlert({ submit: false, reqAmount: null, totalPrice: null, - }) - } + }); + }; const showBestPrice = () => { if (order.pricePerUnit.isZero()) return 0 if (selected.type === "ask") return order.pricePerUnit.toFormat() - return new BN(1).dividedBy(order.pricePerUnit).decimalPlaces(selected.pair?.baseAssetPrecision).toFormat() + return new BN(1).dividedBy(order.pricePerUnit).decimalPlaces(currencies[selected?.pair?.baseAsset].precision).toFormat() } -/* useEffect(() => { - if (order.totalPrice.isGreaterThan(userAccount?.wallets[selected?.sell]?.free)) { - return setAlert({ - ...alert, - totalPrice: t('orders.notEnoughBalance') - }) - } - }, [order.totalPrice])*/ - - return (
{t("MarketTitle.easyTrading")} -
@@ -334,9 +341,10 @@ const EasyOrder = () => { value: o, label:
- {t('currency.' + o)} + {getCurrencyNameOrAlias(currencies[o], language)}
} } @@ -345,15 +353,15 @@ const EasyOrder = () => { type="select" value={{ value: selected?.buy, - label: t('currency.' + selected?.buy), + label: getCurrencyNameOrAlias(currencies[selected?.buy], language), }} onchange={buyOnChangeHandler} customClass={`width-90 ${classes.thisInput} mb-1`} />
-

{t("MarketInfo.lastPrice")}{" "} {t("currency." + selected?.buy)}:

- {showBestPrice()}{" "}{t("currency." + selected?.sell)} +

{t("MarketInfo.lastPrice")}{" "} {getCurrencyNameOrAlias(currencies[selected?.buy], language)}:

+ {showBestPrice()}{" "}{ getCurrencyNameOrAlias(currencies[selected?.sell], language)}
@@ -373,9 +381,9 @@ const EasyOrder = () => { label:
- {t('currency.' + o)} + {getCurrencyNameOrAlias(currencies[o], language)}
} } @@ -384,7 +392,7 @@ const EasyOrder = () => { type="select" value={{ value: selected?.sell, - label: selected?.sell ? t('currency.' + selected?.sell) : t("PersonalizationForm.placeholder"), + label: selected?.sell ? getCurrencyNameOrAlias(currencies[selected?.sell], language) : t("PersonalizationForm.placeholder"), }} onchange={sellOnChangeHandler} customClass={`width-90 ${classes.thisInput} my-1`} @@ -393,24 +401,25 @@ const EasyOrder = () => {

{t("orders.availableAmount")}:{" "}

{new BN(userAccount?.wallets[selected?.sell]?.free || 0).toFormat()}{" "}{t("currency." + selected?.sell)} + onClick={fillBuyByWallet}>{new BN(userAccount?.wallets[selected?.sell]?.free || 0).decimalPlaces(currencies[selected?.sell]?.precision ?? 0).toFormat()}{" "}{getCurrencyNameOrAlias(currencies[selected?.sell], language)}
buyPriceHandler(e.target.value)} alert={alert.reqAmount} customClass={`width-90 mb-1 mt-5`} isAllowed={isAllowed} /> + totalPriceHandler(e.target.value)} alert={alert.totalPrice} customClass={`width-90 my-1`} diff --git a/src/main/Browser/Pages/Landing/components/MarketInfo/MarketInfo.js b/src/main/Browser/Pages/Landing/components/MarketInfo/MarketInfo.js index c88dee96..e89d2f38 100644 --- a/src/main/Browser/Pages/Landing/components/MarketInfo/MarketInfo.js +++ b/src/main/Browser/Pages/Landing/components/MarketInfo/MarketInfo.js @@ -1,4 +1,4 @@ -import React, {useState} from 'react'; +import React, {useEffect, useState} from 'react'; import classes from './MarketInfo.module.css' import Icon from "../../../../../../components/Icon/Icon"; import MarketInfoTable from "./components/MarketInfoTable/MarketInfoTable"; @@ -10,24 +10,40 @@ import Loading from "../../../../../../components/Loading/Loading"; import Error from "../../../../../../components/Error/Error"; import {useTranslation} from "react-i18next"; import i18n from "i18next"; +import {useSelector} from "react-redux"; +import {getCurrencyNameOrAlias} from "../../../../../../utils/utils"; const MarketInfo = () => { const {t} = useTranslation(); const [card, setCard] = useState(false) - const [activeCurrency, setActiveCurrency] = useState("") + + const [activeCurrency, setActiveCurrency] = useState(""); const interval = "24h" + + + const quote = activeCurrency === "" ? null : activeCurrency + const currencies = useSelector((state) => state.exchange.currencies) + const language = i18n.language + const {data: overview, isLoading, error} = useOverview(null, interval, quote) - const {data: currencies} = useGetQuoteCurrencies() + const {data: quoteCurrencies, isLoading:quoteCurrenciesIsLoading, error:quoteCurrenciesError} = useGetQuoteCurrencies() + + + useEffect(() => { + if (quoteCurrencies?.length > 0) { + setActiveCurrency(quoteCurrencies[0]); + } + }, [quoteCurrencies]); const content = () => { - if (isLoading) return
- if (error) return
+ if (isLoading || quoteCurrenciesIsLoading) return
+ if (error || quoteCurrenciesError) return
else return <> {card ? @@ -50,8 +66,11 @@ const MarketInfo = () => { ( {t("marketInterval." + interval)} )
- {currencies?.map((currency) => - setActiveCurrency(currency)} key={currency}>{t("currency." + currency)} + {quoteCurrencies?.map((currency) => + setActiveCurrency(currency)} key={currency}> + {getCurrencyNameOrAlias(currencies[currency], language)} + {/*{t("currency." + currency)}*/} + )}
diff --git a/src/main/Browser/Pages/Landing/components/MarketInfo/components/MarketInfoCard/MarketInfoCard.js b/src/main/Browser/Pages/Landing/components/MarketInfo/components/MarketInfoCard/MarketInfoCard.js index 91e2f346..7f786523 100644 --- a/src/main/Browser/Pages/Landing/components/MarketInfo/components/MarketInfoCard/MarketInfoCard.js +++ b/src/main/Browser/Pages/Landing/components/MarketInfo/components/MarketInfoCard/MarketInfoCard.js @@ -2,17 +2,20 @@ import React from 'react'; import classes from './MarketInfoCard.module.css' import {images} from "../../../../../../../../assets/images"; import {useTranslation} from "react-i18next"; -import {BN} from "../../../../../../../../utils/utils"; +import {BN, getCurrencyNameOrAlias} from "../../../../../../../../utils/utils"; import {setActivePairInitiate} from "../../../../../../../../store/actions"; import {Panel} from "../../../../../../Routes/routes"; import {useNavigate} from "react-router-dom"; import {useDispatch, useSelector} from "react-redux"; +import i18n from "i18next"; const MarketInfoCard = ({data, activeCurrency}) => { const {t} = useTranslation(); const navigate = useNavigate(); const dispatch = useDispatch(); + const language = i18n.language + const currencies = useSelector((state) => state.exchange.currencies) const allExchangeSymbols = useSelector((state) => state.exchange.symbols) const backgroundBar = (percent) => { @@ -38,19 +41,23 @@ const MarketInfoCard = ({data, activeCurrency}) => { return (
navigateToPanel(tr.symbol)}>
- {tr?.base}
- {activeCurrency ? t("currency." + tr?.base) : tr?.base + " / " + tr?.quote} - 0 ? "text-green" : "text-red"} direction-ltr`}>{new BN(tr.priceChangePercent).toFormat(2)} % + {activeCurrency ? + <> + {getCurrencyNameOrAlias(currencies[tr?.base], language)} + {tr?.base} + + : tr?.base + " / " + tr?.quote} + 0 ? "text-green" : tr.priceChangePercent < 0 ? "text-red" : ""} direction-ltr`}>{tr.priceChangePercent === 0 ? "0 %" : `${new BN(tr.priceChangePercent).toFormat(2)} %`} +
- 0 ? "text-green" : "text-red"} fs-02`}>{new BN(tr.lastPrice).toFormat()} {t("currency." + tr?.quote)} + 0 ? "text-green" : "text-red"} fs-02`}>{new BN(tr.lastPrice).decimalPlaces(currencies[tr?.quote]?.precision ?? 0).toFormat()} {tr?.quote}
{t("MarketInfo.volume")}: - {new BN(tr.volume).toFormat()} + {new BN(tr.volume).decimalPlaces(currencies[tr?.base]?.precision ?? 0).toFormat()} {tr?.base}
{ const {t} = useTranslation(); const navigate = useNavigate(); const dispatch = useDispatch(); + const language = i18n.language + const currencies = useSelector((state) => state.exchange.currencies) const allExchangeSymbols = useSelector((state) => state.exchange.symbols) const navigateToPanel = (symbol) => { @@ -24,36 +26,43 @@ const MarketInfoTable = ({data, activeCurrency}) => { let head = (
- {t("MarketInfo.name")} - {t("MarketInfo.lastPrice")} + {t("MarketInfo.name")} + {t("MarketInfo.lastPrice")} {t("MarketInfo.priceChange")} {t("MarketInfo.volume")} {t("MarketInfo.chart")}
); + const base64Data = "PHN2ZyB4bWxucz0naHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmcnIHhtbG5zOnhsaW5rPSdodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rJyB4bWxuczpqZnJlZXN2Zz0naHR0cDovL3d3dy5qZnJlZS5vcmcvamZyZWVzdmcvc3ZnJyB3aWR0aD0nMTAwJyBoZWlnaHQ9JzM1JyB0ZXh0LXJlbmRlcmluZz0nYXV0bycgc2hhcGUtcmVuZGVyaW5nPSdhdXRvJz48ZGVmcz48Y2xpcFBhdGggaWQ9J18xMTIzOTc0MzA1MTMzY2xpcC0wJz48cGF0aCBkPSdNMTIsOEwxMiwyN0w4OCwyN0w4OCw4WicvPjwvY2xpcFBhdGg+PC9kZWZzPjxsaW5lIHgxPScxNS40NScgeTE9JzI0LjIzJyB4Mj0nMTcuMScgeTI9JzIyLjAyJyBzdHlsZT0nc3Ryb2tlLXdpZHRoOjEuMDtzdHJva2U6cmdiKDI1NSwyNTUsMjU1KTtzdHJva2Utb3BhY2l0eToxLjA7c3Ryb2tlLWxpbmVjYXA6c3F1YXJlO3N0cm9rZS1saW5lam9pbjpiZXZlbDtzdHJva2UtbWl0ZXJsaW1pdDoxMDtzaGFwZS1yZW5kZXJpbmc6Z2VvbWV0cmljUHJlY2lzaW9uJyBjbGlwLXBhdGg9J3VybCgjXzExMjM5NzQzMDUxMzNjbGlwLTApJy8+PGxpbmUgeDE9JzE3LjEnIHkxPScyMi4wMicgeDI9JzE4Ljc0JyB5Mj0nMjMuMjcnIHN0eWxlPSdzdHJva2Utd2lkdGg6MS4wO3N0cm9rZTpyZ2IoMjU1LDI1NSwyNTUpO3N0cm9rZS1vcGFjaXR5OjEuMDtzdHJva2UtbGluZWNhcDpzcXVhcmU7c3Ryb2tlLWxpbmVqb2luOmJldmVsO3N0cm9rZS1taXRlcmxpbWl0OjEwO3NoYXBlLXJlbmRlcmluZzpnZW9tZXRyaWNQcmVjaXNpb24nIGNsaXAtcGF0aD0ndXJsKCNfMTEyMzk3NDMwNTEzM2NsaXAtMCknLz48bGluZSB4MT0nMTguNzQnIHkxPScyMy4yNycgeDI9JzIwLjM5JyB5Mj0nMjAuNTcnIHN0eWxlPSdzdHJva2Utd2lkdGg6MS4wO3N0cm9rZTpyZ2IoMjU1LDI1NSwyNTUpO3N0cm9rZS1vcGFjaXR5OjEuMDtzdHJva2UtbGluZWNhcDpzcXVhcmU7c3Ryb2tlLWxpbmVqb2luOmJldmVsO3N0cm9rZS1taXRlcmxpbWl0OjEwO3NoYXBlLXJlbmRlcmluZzpnZW9tZXRyaWNQcmVjaXNpb24nIGNsaXAtcGF0aD0ndXJsKCNfMTEyMzk3NDMwNTEzM2NsaXAtMCknLz48bGluZSB4MT0nMjAuMzknIHkxPScyMC41NycgeDI9JzIyLjAzJyB5Mj0nMjYuMTYnIHN0eWxlPSdzdHJva2Utd2lkdGg6MS4wO3N0cm9rZTpyZ2IoMjU1LDI1NSwyNTUpO3N0cm9rZS1vcGFjaXR5OjEuMDtzdHJva2UtbGluZWNhcDpzcXVhcmU7c3Ryb2tlLWxpbmVqb2luOmJldmVsO3N0cm9rZS1taXRlcmxpbWl0OjEwO3NoYXBlLXJlbmRlcmluZzpnZW9tZXRyaWNQcmVjaXNpb24nIGNsaXAtcGF0aD0ndXJsKCNfMTEyMzk3NDMwNTEzM2NsaXAtMCknLz48bGluZSB4MT0nMjIuMDMnIHkxPScyNi4xNicgeDI9JzIzLjY4JyB5Mj0nMTkuNDUnIHN0eWxlPSdzdHJva2Utd2lkdGg6MS4wO3N0cm9rZTpyZ2IoMjU1LDI1NSwyNTUpO3N0cm9rZS1vcGFjaXR5OjEuMDtzdHJva2UtbGluZWNhcDpzcXVhcmU7c3Ryb2tlLWxpbmVqb2luOmJldmVsO3N0cm9rZS1taXRlcmxpbWl0OjEwO3NoYXBlLXJlbmRlcmluZzpnZW9tZXRyaWNQcmVjaXNpb24nIGNsaXAtcGF0aD0ndXJsKCNfMTEyMzk3NDMwNTEzM2NsaXAtMCknLz48bGluZSB4MT0nMjMuNjgnIHkxPScxOS40NScgeDI9JzI1LjMyJyB5Mj0nMjIuOCcgc3R5bGU9J3N0cm9rZS13aWR0aDoxLjA7c3Ryb2tlOnJnYigyNTUsMjU1LDI1NSk7c3Ryb2tlLW9wYWNpdHk6MS4wO3N0cm9rZS1saW5lY2FwOnNxdWFyZTtzdHJva2UtbGluZWpvaW46YmV2ZWw7c3Ryb2tlLW1pdGVybGltaXQ6MTA7c2hhcGUtcmVuZGVyaW5nOmdlb21ldHJpY1ByZWNpc2lvbicgY2xpcC1wYXRoPSd1cmwoI18xMTIzOTc0MzA1MTMzY2xpcC0wKScvPjxsaW5lIHgxPScyNS4zMicgeTE9JzIyLjgnIHgyPScyNi45NycgeTI9JzIzLjYzJyBzdHlsZT0nc3Ryb2tlLXdpZHRoOjEuMDtzdHJva2U6cmdiKDI1NSwyNTUsMjU1KTtzdHJva2Utb3BhY2l0eToxLjA7c3Ryb2tlLWxpbmVjYXA6c3F1YXJlO3N0cm9rZS1saW5lam9pbjpiZXZlbDtzdHJva2UtbWl0ZXJsaW1pdDoxMDtzaGFwZS1yZW5kZXJpbmc6Z2VvbWV0cmljUHJlY2lzaW9uJyBjbGlwLXBhdGg9J3VybCgjXzExMjM5NzQzMDUxMzNjbGlwLTApJy8+PGxpbmUgeDE9JzI2Ljk3JyB5MT0nMjMuNjMnIHgyPScyOC42MScgeTI9JzI0LjY4JyBzdHlsZT0nc3Ryb2tlLXdpZHRoOjEuMDtzdHJva2U6cmdiKDI1NSwyNTUsMjU1KTtzdHJva2Utb3BhY2l0eToxLjA7c3Ryb2tlLWxpbmVjYXA6c3F1YXJlO3N0cm9rZS1saW5lam9pbjpiZXZlbDtzdHJva2UtbWl0ZXJsaW1pdDoxMDtzaGFwZS1yZW5kZXJpbmc6Z2VvbWV0cmljUHJlY2lzaW9uJyBjbGlwLXBhdGg9J3VybCgjXzExMjM5NzQzMDUxMzNjbGlwLTApJy8+PGxpbmUgeDE9JzI4LjYxJyB5MT0nMjQuNjgnIHgyPSczMC4yNicgeTI9JzE5LjY3JyBzdHlsZT0nc3Ryb2tlLXdpZHRoOjEuMDtzdHJva2U6cmdiKDI1NSwyNTUsMjU1KTtzdHJva2Utb3BhY2l0eToxLjA7c3Ryb2tlLWxpbmVjYXA6c3F1YXJlO3N0cm9rZS1saW5lam9pbjpiZXZlbDtzdHJva2UtbWl0ZXJsaW1pdDoxMDtzaGFwZS1yZW5kZXJpbmc6Z2VvbWV0cmljUHJlY2lzaW9uJyBjbGlwLXBhdGg9J3VybCgjXzExMjM5NzQzMDUxMzNjbGlwLTApJy8+PGxpbmUgeDE9JzMwLjI2JyB5MT0nMTkuNjcnIHgyPSczMS45JyB5Mj0nMjMuMzQnIHN0eWxlPSdzdHJva2Utd2lkdGg6MS4wO3N0cm9rZTpyZ2IoMjU1LDI1NSwyNTUpO3N0cm9rZS1vcGFjaXR5OjEuMDtzdHJva2UtbGluZWNhcDpzcXVhcmU7c3Ryb2tlLWxpbmVqb2luOmJldmVsO3N0cm9rZS1taXRlcmxpbWl0OjEwO3NoYXBlLXJlbmRlcmluZzpnZW9tZXRyaWNQcmVjaXNpb24nIGNsaXAtcGF0aD0ndXJsKCNfMTEyMzk3NDMwNTEzM2NsaXAtMCknLz48bGluZSB4MT0nMzEuOScgeTE9JzIzLjM0JyB4Mj0nMzMuNTUnIHkyPScyMi42Mycgc3R5bGU9J3N0cm9rZS13aWR0aDoxLjA7c3Ryb2tlOnJnYigyNTUsMjU1LDI1NSk7c3Ryb2tlLW9wYWNpdHk6MS4wO3N0cm9rZS1saW5lY2FwOnNxdWFyZTtzdHJva2UtbGluZWpvaW46YmV2ZWw7c3Ryb2tlLW1pdGVybGltaXQ6MTA7c2hhcGUtcmVuZGVyaW5nOmdlb21ldHJpY1ByZWNpc2lvbicgY2xpcC1wYXRoPSd1cmwoI18xMTIzOTc0MzA1MTMzY2xpcC0wKScvPjxsaW5lIHgxPSczMy41NScgeTE9JzIyLjYzJyB4Mj0nMzUuMTknIHkyPScxOC4yOScgc3R5bGU9J3N0cm9rZS13aWR0aDoxLjA7c3Ryb2tlOnJnYigyNTUsMjU1LDI1NSk7c3Ryb2tlLW9wYWNpdHk6MS4wO3N0cm9rZS1saW5lY2FwOnNxdWFyZTtzdHJva2UtbGluZWpvaW46YmV2ZWw7c3Ryb2tlLW1pdGVybGltaXQ6MTA7c2hhcGUtcmVuZGVyaW5nOmdlb21ldHJpY1ByZWNpc2lvbicgY2xpcC1wYXRoPSd1cmwoI18xMTIzOTc0MzA1MTMzY2xpcC0wKScvPjxsaW5lIHgxPSczNS4xOScgeTE9JzE4LjI5JyB4Mj0nMzYuODQnIHkyPScxNy42Micgc3R5bGU9J3N0cm9rZS13aWR0aDoxLjA7c3Ryb2tlOnJnYigyNTUsMjU1LDI1NSk7c3Ryb2tlLW9wYWNpdHk6MS4wO3N0cm9rZS1saW5lY2FwOnNxdWFyZTtzdHJva2UtbGluZWpvaW46YmV2ZWw7c3Ryb2tlLW1pdGVybGltaXQ6MTA7c2hhcGUtcmVuZGVyaW5nOmdlb21ldHJpY1ByZWNpc2lvbicgY2xpcC1wYXRoPSd1cmwoI18xMTIzOTc0MzA1MTMzY2xpcC0wKScvPjxsaW5lIHgxPSczNi44NCcgeTE9JzE3LjYyJyB4Mj0nMzguNDgnIHkyPScxNi4xNicgc3R5bGU9J3N0cm9rZS13aWR0aDoxLjA7c3Ryb2tlOnJnYigyNTUsMjU1LDI1NSk7c3Ryb2tlLW9wYWNpdHk6MS4wO3N0cm9rZS1saW5lY2FwOnNxdWFyZTtzdHJva2UtbGluZWpvaW46YmV2ZWw7c3Ryb2tlLW1pdGVybGltaXQ6MTA7c2hhcGUtcmVuZGVyaW5nOmdlb21ldHJpY1ByZWNpc2lvbicgY2xpcC1wYXRoPSd1cmwoI18xMTIzOTc0MzA1MTMzY2xpcC0wKScvPjxsaW5lIHgxPSczOC40OCcgeTE9JzE2LjE2JyB4Mj0nNDAuMTMnIHkyPScyMS44NCcgc3R5bGU9J3N0cm9rZS13aWR0aDoxLjA7c3Ryb2tlOnJnYigyNTUsMjU1LDI1NSk7c3Ryb2tlLW9wYWNpdHk6MS4wO3N0cm9rZS1saW5lY2FwOnNxdWFyZTtzdHJva2UtbGluZWpvaW46YmV2ZWw7c3Ryb2tlLW1pdGVybGltaXQ6MTA7c2hhcGUtcmVuZGVyaW5nOmdlb21ldHJpY1ByZWNpc2lvbicgY2xpcC1wYXRoPSd1cmwoI18xMTIzOTc0MzA1MTMzY2xpcC0wKScvPjxsaW5lIHgxPSc0MC4xMycgeTE9JzIxLjg0JyB4Mj0nNDEuNzcnIHkyPScxOS40Nycgc3R5bGU9J3N0cm9rZS13aWR0aDoxLjA7c3Ryb2tlOnJnYigyNTUsMjU1LDI1NSk7c3Ryb2tlLW9wYWNpdHk6MS4wO3N0cm9rZS1saW5lY2FwOnNxdWFyZTtzdHJva2UtbGluZWpvaW46YmV2ZWw7c3Ryb2tlLW1pdGVybGltaXQ6MTA7c2hhcGUtcmVuZGVyaW5nOmdlb21ldHJpY1ByZWNpc2lvbicgY2xpcC1wYXRoPSd1cmwoI18xMTIzOTc0MzA1MTMzY2xpcC0wKScvPjxsaW5lIHgxPSc0MS43NycgeTE9JzE5LjQ3JyB4Mj0nNDMuNDInIHkyPScyMi4zOScgc3R5bGU9J3N0cm9rZS13aWR0aDoxLjA7c3Ryb2tlOnJnYigyNTUsMjU1LDI1NSk7c3Ryb2tlLW9wYWNpdHk6MS4wO3N0cm9rZS1saW5lY2FwOnNxdWFyZTtzdHJva2UtbGluZWpvaW46YmV2ZWw7c3Ryb2tlLW1pdGVybGltaXQ6MTA7c2hhcGUtcmVuZGVyaW5nOmdlb21ldHJpY1ByZWNpc2lvbicgY2xpcC1wYXRoPSd1cmwoI18xMTIzOTc0MzA1MTMzY2xpcC0wKScvPjxsaW5lIHgxPSc0My40MicgeTE9JzIyLjM5JyB4Mj0nNDUuMDYnIHkyPScxNS45Micgc3R5bGU9J3N0cm9rZS13aWR0aDoxLjA7c3Ryb2tlOnJnYigyNTUsMjU1LDI1NSk7c3Ryb2tlLW9wYWNpdHk6MS4wO3N0cm9rZS1saW5lY2FwOnNxdWFyZTtzdHJva2UtbGluZWpvaW46YmV2ZWw7c3Ryb2tlLW1pdGVybGltaXQ6MTA7c2hhcGUtcmVuZGVyaW5nOmdlb21ldHJpY1ByZWNpc2lvbicgY2xpcC1wYXRoPSd1cmwoI18xMTIzOTc0MzA1MTMzY2xpcC0wKScvPjxsaW5lIHgxPSc0NS4wNicgeTE9JzE1LjkyJyB4Mj0nNDYuNzEnIHkyPScxNS42OScgc3R5bGU9J3N0cm9rZS13aWR0aDoxLjA7c3Ryb2tlOnJnYigyNTUsMjU1LDI1NSk7c3Ryb2tlLW9wYWNpdHk6MS4wO3N0cm9rZS1saW5lY2FwOnNxdWFyZTtzdHJva2UtbGluZWpvaW46YmV2ZWw7c3Ryb2tlLW1pdGVybGltaXQ6MTA7c2hhcGUtcmVuZGVyaW5nOmdlb21ldHJpY1ByZWNpc2lvbicgY2xpcC1wYXRoPSd1cmwoI18xMTIzOTc0MzA1MTMzY2xpcC0wKScvPjxsaW5lIHgxPSc0Ni43MScgeTE9JzE1LjY5JyB4Mj0nNDguMzUnIHkyPScyMC4wNCcgc3R5bGU9J3N0cm9rZS13aWR0aDoxLjA7c3Ryb2tlOnJnYigyNTUsMjU1LDI1NSk7c3Ryb2tlLW9wYWNpdHk6MS4wO3N0cm9rZS1saW5lY2FwOnNxdWFyZTtzdHJva2UtbGluZWpvaW46YmV2ZWw7c3Ryb2tlLW1pdGVybGltaXQ6MTA7c2hhcGUtcmVuZGVyaW5nOmdlb21ldHJpY1ByZWNpc2lvbicgY2xpcC1wYXRoPSd1cmwoI18xMTIzOTc0MzA1MTMzY2xpcC0wKScvPjxsaW5lIHgxPSc0OC4zNScgeTE9JzIwLjA0JyB4Mj0nNTAnIHkyPScxNS4zNCcgc3R5bGU9J3N0cm9rZS13aWR0aDoxLjA7c3Ryb2tlOnJnYigyNTUsMjU1LDI1NSk7c3Ryb2tlLW9wYWNpdHk6MS4wO3N0cm9rZS1saW5lY2FwOnNxdWFyZTtzdHJva2UtbGluZWpvaW46YmV2ZWw7c3Ryb2tlLW1pdGVybGltaXQ6MTA7c2hhcGUtcmVuZGVyaW5nOmdlb21ldHJpY1ByZWNpc2lvbicgY2xpcC1wYXRoPSd1cmwoI18xMTIzOTc0MzA1MTMzY2xpcC0wKScvPjxsaW5lIHgxPSc1MCcgeTE9JzE1LjM0JyB4Mj0nNTEuNjUnIHkyPScyMS4xNycgc3R5bGU9J3N0cm9rZS13aWR0aDoxLjA7c3Ryb2tlOnJnYigyNTUsMjU1LDI1NSk7c3Ryb2tlLW9wYWNpdHk6MS4wO3N0cm9rZS1saW5lY2FwOnNxdWFyZTtzdHJva2UtbGluZWpvaW46YmV2ZWw7c3Ryb2tlLW1pdGVybGltaXQ6MTA7c2hhcGUtcmVuZGVyaW5nOmdlb21ldHJpY1ByZWNpc2lvbicgY2xpcC1wYXRoPSd1cmwoI18xMTIzOTc0MzA1MTMzY2xpcC0wKScvPjxsaW5lIHgxPSc1MS42NScgeTE9JzIxLjE3JyB4Mj0nNTMuMjknIHkyPScyMC42JyBzdHlsZT0nc3Ryb2tlLXdpZHRoOjEuMDtzdHJva2U6cmdiKDI1NSwyNTUsMjU1KTtzdHJva2Utb3BhY2l0eToxLjA7c3Ryb2tlLWxpbmVjYXA6c3F1YXJlO3N0cm9rZS1saW5lam9pbjpiZXZlbDtzdHJva2UtbWl0ZXJsaW1pdDoxMDtzaGFwZS1yZW5kZXJpbmc6Z2VvbWV0cmljUHJlY2lzaW9uJyBjbGlwLXBhdGg9J3VybCgjXzExMjM5NzQzMDUxMzNjbGlwLTApJy8+PGxpbmUgeDE9JzUzLjI5JyB5MT0nMjAuNicgeDI9JzU0Ljk0JyB5Mj0nMTUuNzQnIHN0eWxlPSdzdHJva2Utd2lkdGg6MS4wO3N0cm9rZTpyZ2IoMjU1LDI1NSwyNTUpO3N0cm9rZS1vcGFjaXR5OjEuMDtzdHJva2UtbGluZWNhcDpzcXVhcmU7c3Ryb2tlLWxpbmVqb2luOmJldmVsO3N0cm9rZS1taXRlcmxpbWl0OjEwO3NoYXBlLXJlbmRlcmluZzpnZW9tZXRyaWNQcmVjaXNpb24nIGNsaXAtcGF0aD0ndXJsKCNfMTEyMzk3NDMwNTEzM2NsaXAtMCknLz48bGluZSB4MT0nNTQuOTQnIHkxPScxNS43NCcgeDI9JzU2LjU4JyB5Mj0nMTYuNzknIHN0eWxlPSdzdHJva2Utd2lkdGg6MS4wO3N0cm9rZTpyZ2IoMjU1LDI1NSwyNTUpO3N0cm9rZS1vcGFjaXR5OjEuMDtzdHJva2UtbGluZWNhcDpzcXVhcmU7c3Ryb2tlLWxpbmVqb2luOmJldmVsO3N0cm9rZS1taXRlcmxpbWl0OjEwO3NoYXBlLXJlbmRlcmluZzpnZW9tZXRyaWNQcmVjaXNpb24nIGNsaXAtcGF0aD0ndXJsKCNfMTEyMzk3NDMwNTEzM2NsaXAtMCknLz48bGluZSB4MT0nNTYuNTgnIHkxPScxNi43OScgeDI9JzU4LjIzJyB5Mj0nMTkuOCcgc3R5bGU9J3N0cm9rZS13aWR0aDoxLjA7c3Ryb2tlOnJnYigyNTUsMjU1LDI1NSk7c3Ryb2tlLW9wYWNpdHk6MS4wO3N0cm9rZS1saW5lY2FwOnNxdWFyZTtzdHJva2UtbGluZWpvaW46YmV2ZWw7c3Ryb2tlLW1pdGVybGltaXQ6MTA7c2hhcGUtcmVuZGVyaW5nOmdlb21ldHJpY1ByZWNpc2lvbicgY2xpcC1wYXRoPSd1cmwoI18xMTIzOTc0MzA1MTMzY2xpcC0wKScvPjxsaW5lIHgxPSc1OC4yMycgeTE9JzE5LjgnIHgyPSc1OS44NycgeTI9JzEzLjk2JyBzdHlsZT0nc3Ryb2tlLXdpZHRoOjEuMDtzdHJva2U6cmdiKDI1NSwyNTUsMjU1KTtzdHJva2Utb3BhY2l0eToxLjA7c3Ryb2tlLWxpbmVjYXA6c3F1YXJlO3N0cm9rZS1saW5lam9pbjpiZXZlbDtzdHJva2UtbWl0ZXJsaW1pdDoxMDtzaGFwZS1yZW5kZXJpbmc6Z2VvbWV0cmljUHJlY2lzaW9uJyBjbGlwLXBhdGg9J3VybCgjXzExMjM5NzQzMDUxMzNjbGlwLTApJy8+PGxpbmUgeDE9JzU5Ljg3JyB5MT0nMTMuOTYnIHgyPSc2MS41MicgeTI9JzE4LjEnIHN0eWxlPSdzdHJva2Utd2lkdGg6MS4wO3N0cm9rZTpyZ2IoMjU1LDI1NSwyNTUpO3N0cm9rZS1vcGFjaXR5OjEuMDtzdHJva2UtbGluZWNhcDpzcXVhcmU7c3Ryb2tlLWxpbmVqb2luOmJldmVsO3N0cm9rZS1taXRlcmxpbWl0OjEwO3NoYXBlLXJlbmRlcmluZzpnZW9tZXRyaWNQcmVjaXNpb24nIGNsaXAtcGF0aD0ndXJsKCNfMTEyMzk3NDMwNTEzM2NsaXAtMCknLz48bGluZSB4MT0nNjEuNTInIHkxPScxOC4xJyB4Mj0nNjMuMTYnIHkyPScxMScgc3R5bGU9J3N0cm9rZS13aWR0aDoxLjA7c3Ryb2tlOnJnYigyNTUsMjU1LDI1NSk7c3Ryb2tlLW9wYWNpdHk6MS4wO3N0cm9rZS1saW5lY2FwOnNxdWFyZTtzdHJva2UtbGluZWpvaW46YmV2ZWw7c3Ryb2tlLW1pdGVybGltaXQ6MTA7c2hhcGUtcmVuZGVyaW5nOmdlb21ldHJpY1ByZWNpc2lvbicgY2xpcC1wYXRoPSd1cmwoI18xMTIzOTc0MzA1MTMzY2xpcC0wKScvPjxsaW5lIHgxPSc2My4xNicgeTE9JzExJyB4Mj0nNjQuODEnIHkyPScxMS4xMicgc3R5bGU9J3N0cm9rZS13aWR0aDoxLjA7c3Ryb2tlOnJnYigyNTUsMjU1LDI1NSk7c3Ryb2tlLW9wYWNpdHk6MS4wO3N0cm9rZS1saW5lY2FwOnNxdWFyZTtzdHJva2UtbGluZWpvaW46YmV2ZWw7c3Ryb2tlLW1pdGVybGltaXQ6MTA7c2hhcGUtcmVuZGVyaW5nOmdlb21ldHJpY1ByZWNpc2lvbicgY2xpcC1wYXRoPSd1cmwoI18xMTIzOTc0MzA1MTMzY2xpcC0wKScvPjxsaW5lIHgxPSc2NC44MScgeTE9JzExLjEyJyB4Mj0nNjYuNDUnIHkyPScxNC43Nicgc3R5bGU9J3N0cm9rZS13aWR0aDoxLjA7c3Ryb2tlOnJnYigyNTUsMjU1LDI1NSk7c3Ryb2tlLW9wYWNpdHk6MS4wO3N0cm9rZS1saW5lY2FwOnNxdWFyZTtzdHJva2UtbGluZWpvaW46YmV2ZWw7c3Ryb2tlLW1pdGVybGltaXQ6MTA7c2hhcGUtcmVuZGVyaW5nOmdlb21ldHJpY1ByZWNpc2lvbicgY2xpcC1wYXRoPSd1cmwoI18xMTIzOTc0MzA1MTMzY2xpcC0wKScvPjxsaW5lIHgxPSc2Ni40NScgeTE9JzE0Ljc2JyB4Mj0nNjguMScgeTI9JzExLjg3JyBzdHlsZT0nc3Ryb2tlLXdpZHRoOjEuMDtzdHJva2U6cmdiKDI1NSwyNTUsMjU1KTtzdHJva2Utb3BhY2l0eToxLjA7c3Ryb2tlLWxpbmVjYXA6c3F1YXJlO3N0cm9rZS1saW5lam9pbjpiZXZlbDtzdHJva2UtbWl0ZXJsaW1pdDoxMDtzaGFwZS1yZW5kZXJpbmc6Z2VvbWV0cmljUHJlY2lzaW9uJyBjbGlwLXBhdGg9J3VybCgjXzExMjM5NzQzMDUxMzNjbGlwLTApJy8+PGxpbmUgeDE9JzY4LjEnIHkxPScxMS44NycgeDI9JzY5Ljc0JyB5Mj0nMTYuMTcnIHN0eWxlPSdzdHJva2Utd2lkdGg6MS4wO3N0cm9rZTpyZ2IoMjU1LDI1NSwyNTUpO3N0cm9rZS1vcGFjaXR5OjEuMDtzdHJva2UtbGluZWNhcDpzcXVhcmU7c3Ryb2tlLWxpbmVqb2luOmJldmVsO3N0cm9rZS1taXRlcmxpbWl0OjEwO3NoYXBlLXJlbmRlcmluZzpnZW9tZXRyaWNQcmVjaXNpb24nIGNsaXAtcGF0aD0ndXJsKCNfMTEyMzk3NDMwNTEzM2NsaXAtMCknLz48bGluZSB4MT0nNjkuNzQnIHkxPScxNi4xNycgeDI9JzcxLjM5JyB5Mj0nMTQuMzgnIHN0eWxlPSdzdHJva2Utd2lkdGg6MS4wO3N0cm9rZTpyZ2IoMjU1LDI1NSwyNTUpO3N0cm9rZS1vcGFjaXR5OjEuMDtzdHJva2UtbGluZWNhcDpzcXVhcmU7c3Ryb2tlLWxpbmVqb2luOmJldmVsO3N0cm9rZS1taXRlcmxpbWl0OjEwO3NoYXBlLXJlbmRlcmluZzpnZW9tZXRyaWNQcmVjaXNpb24nIGNsaXAtcGF0aD0ndXJsKCNfMTEyMzk3NDMwNTEzM2NsaXAtMCknLz48bGluZSB4MT0nNzEuMzknIHkxPScxNC4zOCcgeDI9JzczLjAzJyB5Mj0nMTYuMScgc3R5bGU9J3N0cm9rZS13aWR0aDoxLjA7c3Ryb2tlOnJnYigyNTUsMjU1LDI1NSk7c3Ryb2tlLW9wYWNpdHk6MS4wO3N0cm9rZS1saW5lY2FwOnNxdWFyZTtzdHJva2UtbGluZWpvaW46YmV2ZWw7c3Ryb2tlLW1pdGVybGltaXQ6MTA7c2hhcGUtcmVuZGVyaW5nOmdlb21ldHJpY1ByZWNpc2lvbicgY2xpcC1wYXRoPSd1cmwoI18xMTIzOTc0MzA1MTMzY2xpcC0wKScvPjxsaW5lIHgxPSc3My4wMycgeTE9JzE2LjEnIHgyPSc3NC42OCcgeTI9JzEwLjY2JyBzdHlsZT0nc3Ryb2tlLXdpZHRoOjEuMDtzdHJva2U6cmdiKDI1NSwyNTUsMjU1KTtzdHJva2Utb3BhY2l0eToxLjA7c3Ryb2tlLWxpbmVjYXA6c3F1YXJlO3N0cm9rZS1saW5lam9pbjpiZXZlbDtzdHJva2UtbWl0ZXJsaW1pdDoxMDtzaGFwZS1yZW5kZXJpbmc6Z2VvbWV0cmljUHJlY2lzaW9uJyBjbGlwLXBhdGg9J3VybCgjXzExMjM5NzQzMDUxMzNjbGlwLTApJy8+PGxpbmUgeDE9Jzc0LjY4JyB5MT0nMTAuNjYnIHgyPSc3Ni4zMicgeTI9JzEyLjUxJyBzdHlsZT0nc3Ryb2tlLXdpZHRoOjEuMDtzdHJva2U6cmdiKDI1NSwyNTUsMjU1KTtzdHJva2Utb3BhY2l0eToxLjA7c3Ryb2tlLWxpbmVjYXA6c3F1YXJlO3N0cm9rZS1saW5lam9pbjpiZXZlbDtzdHJva2UtbWl0ZXJsaW1pdDoxMDtzaGFwZS1yZW5kZXJpbmc6Z2VvbWV0cmljUHJlY2lzaW9uJyBjbGlwLXBhdGg9J3VybCgjXzExMjM5NzQzMDUxMzNjbGlwLTApJy8+PGxpbmUgeDE9Jzc2LjMyJyB5MT0nMTIuNTEnIHgyPSc3Ny45NycgeTI9JzE1LjE2JyBzdHlsZT0nc3Ryb2tlLXdpZHRoOjEuMDtzdHJva2U6cmdiKDI1NSwyNTUsMjU1KTtzdHJva2Utb3BhY2l0eToxLjA7c3Ryb2tlLWxpbmVjYXA6c3F1YXJlO3N0cm9rZS1saW5lam9pbjpiZXZlbDtzdHJva2UtbWl0ZXJsaW1pdDoxMDtzaGFwZS1yZW5kZXJpbmc6Z2VvbWV0cmljUHJlY2lzaW9uJyBjbGlwLXBhdGg9J3VybCgjXzExMjM5NzQzMDUxMzNjbGlwLTApJy8+PGxpbmUgeDE9Jzc3Ljk3JyB5MT0nMTUuMTYnIHgyPSc3OS42MScgeTI9JzgnIHN0eWxlPSdzdHJva2Utd2lkdGg6MS4wO3N0cm9rZTpyZ2IoMjU1LDI1NSwyNTUpO3N0cm9rZS1vcGFjaXR5OjEuMDtzdHJva2UtbGluZWNhcDpzcXVhcmU7c3Ryb2tlLWxpbmVqb2luOmJldmVsO3N0cm9rZS1taXRlcmxpbWl0OjEwO3NoYXBlLXJlbmRlcmluZzpnZW9tZXRyaWNQcmVjaXNpb24nIGNsaXAtcGF0aD0ndXJsKCNfMTEyMzk3NDMwNTEzM2NsaXAtMCknLz48bGluZSB4MT0nNzkuNjEnIHkxPSc4JyB4Mj0nODEuMjYnIHkyPSc5LjknIHN0eWxlPSdzdHJva2Utd2lkdGg6MS4wO3N0cm9rZTpyZ2IoMjU1LDI1NSwyNTUpO3N0cm9rZS1vcGFjaXR5OjEuMDtzdHJva2UtbGluZWNhcDpzcXVhcmU7c3Ryb2tlLWxpbmVqb2luOmJldmVsO3N0cm9rZS1taXRlcmxpbWl0OjEwO3NoYXBlLXJlbmRlcmluZzpnZW9tZXRyaWNQcmVjaXNpb24nIGNsaXAtcGF0aD0ndXJsKCNfMTEyMzk3NDMwNTEzM2NsaXAtMCknLz48bGluZSB4MT0nODEuMjYnIHkxPSc5LjknIHgyPSc4Mi45JyB5Mj0nMTAuNzknIHN0eWxlPSdzdHJva2Utd2lkdGg6MS4wO3N0cm9rZTpyZ2IoMjU1LDI1NSwyNTUpO3N0cm9rZS1vcGFjaXR5OjEuMDtzdHJva2UtbGluZWNhcDpzcXVhcmU7c3Ryb2tlLWxpbmVqb2luOmJldmVsO3N0cm9rZS1taXRlcmxpbWl0OjEwO3NoYXBlLXJlbmRlcmluZzpnZW9tZXRyaWNQcmVjaXNpb24nIGNsaXAtcGF0aD0ndXJsKCNfMTEyMzk3NDMwNTEzM2NsaXAtMCknLz48bGluZSB4MT0nODIuOScgeTE9JzEwLjc5JyB4Mj0nODQuNTUnIHkyPScxMS4wNycgc3R5bGU9J3N0cm9rZS13aWR0aDoxLjA7c3Ryb2tlOnJnYigyNTUsMjU1LDI1NSk7c3Ryb2tlLW9wYWNpdHk6MS4wO3N0cm9rZS1saW5lY2FwOnNxdWFyZTtzdHJva2UtbGluZWpvaW46YmV2ZWw7c3Ryb2tlLW1pdGVybGltaXQ6MTA7c2hhcGUtcmVuZGVyaW5nOmdlb21ldHJpY1ByZWNpc2lvbicgY2xpcC1wYXRoPSd1cmwoI18xMTIzOTc0MzA1MTMzY2xpcC0wKScvPjwvc3ZnPg==" + const svgBase64 = `data:image/svg+xml;base64,${base64Data}`; + + let body = ( <> {data.map((tr, index) => { return (
navigateToPanel(tr.symbol)}> - - {tr?.base} + {tr?.base} - {activeCurrency ? t("currency." + tr?.base) : tr?.base + " / " + tr?.quote} + {activeCurrency ? + <> + {getCurrencyNameOrAlias(currencies[tr?.base], language)} + {tr?.base} + + : tr?.base + " / " + tr?.quote} - 0 ? "text-green" : "text-red"}`}>{new BN(tr.lastPrice).toFormat()} {t("currency." + tr?.quote)} - 0 ? "text-green" : "text-red"} direction-ltr`}>{new BN(tr.priceChangePercent).toFormat(2)} % - {new BN(tr.volume).toFormat()} + + 0 ? "text-green" : "text-red"}`}>{new BN(tr.lastPrice).decimalPlaces(currencies[tr?.quote]?.precision ?? 0).toFormat()} {tr?.quote} + + 0 ? "text-green" : tr.priceChangePercent < 0 ? "text-red" : ""} direction-ltr`}>{tr.priceChangePercent === 0 ? "0 %" : `${new BN(tr.priceChangePercent).toFormat(2)} %`} + + {new BN(tr.volume).decimalPlaces(currencies[tr?.base]?.precision ?? 0).toFormat()} {tr?.base} + - {""} - {t("comingSoon")} - + {svgBase64 && SVG Example} +
) })} diff --git a/src/main/Browser/Pages/Landing/components/MarketInfo/components/MarketInfoTable/MarketInfoTable.module.css b/src/main/Browser/Pages/Landing/components/MarketInfo/components/MarketInfoTable/MarketInfoTable.module.css index cf0d2b65..8e700398 100644 --- a/src/main/Browser/Pages/Landing/components/MarketInfo/components/MarketInfoTable/MarketInfoTable.module.css +++ b/src/main/Browser/Pages/Landing/components/MarketInfo/components/MarketInfoTable/MarketInfoTable.module.css @@ -11,5 +11,6 @@ } .filter { - filter: blur(4px); + /*filter: invert(51%) sepia(94%) saturate(370%) hue-rotate(109deg) brightness(87%) contrast(92%);*/ + filter: invert(38%) sepia(77%) saturate(5872%) hue-rotate(347deg) brightness(93%) contrast(79%); } \ No newline at end of file diff --git a/src/main/Browser/Pages/Landing/components/MarketView/components/MostDecreasedPrice/MostDecreasedPrice.js b/src/main/Browser/Pages/Landing/components/MarketView/components/MostDecreasedPrice/MostDecreasedPrice.js index 0f4ca3d7..19d40377 100644 --- a/src/main/Browser/Pages/Landing/components/MarketView/components/MostDecreasedPrice/MostDecreasedPrice.js +++ b/src/main/Browser/Pages/Landing/components/MarketView/components/MostDecreasedPrice/MostDecreasedPrice.js @@ -1,13 +1,15 @@ import React from 'react'; import classes from "../../MarketView.module.css"; -import {images} from "../../../../../../../../assets/images"; import i18n from "i18next"; -import {BN} from "../../../../../../../../utils/utils"; +import {BN, getCurrencyNameOrAlias} from "../../../../../../../../utils/utils"; import {useTranslation} from "react-i18next"; +import {useSelector} from "react-redux"; const MostDecreasedPrice = ({mostDecreasedPrice}) => { const {t} = useTranslation(); + const language = i18n.language + const currencies = useSelector((state) => state.exchange.currencies) return (
@@ -16,21 +18,22 @@ const MostDecreasedPrice = ({mostDecreasedPrice}) => {
{mostDecreasedPrice.pairInfo.baseAsset} - {t("currency." + mostDecreasedPrice.pairInfo.baseAsset)} + {getCurrencyNameOrAlias(currencies[mostDecreasedPrice.pairInfo.baseAsset], language)}
{mostDecreasedPrice.pairInfo.quoteAsset} - {new BN(mostDecreasedPrice?.lastPrice).toFormat()} + {new BN(mostDecreasedPrice?.lastPrice).decimalPlaces(currencies[mostDecreasedPrice.pairInfo.quoteAsset]?.precision ?? 0).toFormat()}
- 0 ? "text-green" : "text-red"} direction-ltr`}>{new BN(mostDecreasedPrice?.priceChangePercent).toFormat(2)} % + 0 ? "text-green" : mostDecreasedPrice?.priceChangePercent < 0 ? "text-red" : ""} direction-ltr`}>{mostDecreasedPrice?.priceChangePercent === 0 ? "0 %" : `${new BN(mostDecreasedPrice?.priceChangePercent).toFormat(2)} %`}
+ ); }; diff --git a/src/main/Browser/Pages/Landing/components/MarketView/components/MostIncreasedPrice/MostIncreasedPrice.js b/src/main/Browser/Pages/Landing/components/MarketView/components/MostIncreasedPrice/MostIncreasedPrice.js index 9e75edf6..52c44b5a 100644 --- a/src/main/Browser/Pages/Landing/components/MarketView/components/MostIncreasedPrice/MostIncreasedPrice.js +++ b/src/main/Browser/Pages/Landing/components/MarketView/components/MostIncreasedPrice/MostIncreasedPrice.js @@ -2,12 +2,15 @@ import React from 'react'; import classes from "../../MarketView.module.css"; import {images} from "../../../../../../../../assets/images"; import i18n from "i18next"; -import {BN} from "../../../../../../../../utils/utils"; +import {BN, getCurrencyNameOrAlias} from "../../../../../../../../utils/utils"; import {useTranslation} from "react-i18next"; +import {useSelector} from "react-redux"; const MostIncreasedPrice = ({mostIncreasedPrice}) => { const {t} = useTranslation(); + const language = i18n.language + const currencies = useSelector((state) => state.exchange.currencies) return (
@@ -16,18 +19,18 @@ const MostIncreasedPrice = ({mostIncreasedPrice}) => {
{mostIncreasedPrice.pairInfo.baseAsset} - {t("currency." + mostIncreasedPrice.pairInfo.baseAsset)} + {getCurrencyNameOrAlias(currencies[mostIncreasedPrice.pairInfo.baseAsset], language)}
{mostIncreasedPrice.pairInfo.quoteAsset} - {new BN(mostIncreasedPrice?.lastPrice).toFormat()} + {new BN(mostIncreasedPrice?.lastPrice).decimalPlaces(currencies[mostIncreasedPrice.pairInfo.quoteAsset]?.precision ?? 0).toFormat()}
- 0 ? "text-green" : "text-red"} direction-ltr`}>{new BN(mostIncreasedPrice?.priceChangePercent).toFormat(2)} % + 0 ? "text-green" : mostIncreasedPrice?.priceChangePercent < 0 ? "text-red" : ""} direction-ltr`}>{mostIncreasedPrice?.priceChangePercent === 0 ? "0 %" : `${new BN(mostIncreasedPrice?.priceChangePercent).toFormat(2)} %`}
diff --git a/src/main/Browser/Pages/Landing/components/MarketView/components/MostVolume/MostVolume.js b/src/main/Browser/Pages/Landing/components/MarketView/components/MostVolume/MostVolume.js index 591a1538..4524f627 100644 --- a/src/main/Browser/Pages/Landing/components/MarketView/components/MostVolume/MostVolume.js +++ b/src/main/Browser/Pages/Landing/components/MarketView/components/MostVolume/MostVolume.js @@ -2,12 +2,15 @@ import React from 'react'; import classes from "../../MarketView.module.css"; import {images} from "../../../../../../../../assets/images"; import i18n from "i18next"; -import {BN} from "../../../../../../../../utils/utils"; +import {BN, getCurrencyNameOrAlias} from "../../../../../../../../utils/utils"; import {useTranslation} from "react-i18next"; +import {useSelector} from "react-redux"; const MostVolume = ({mostVolume}) => { const {t} = useTranslation(); + const language = i18n.language + const currencies = useSelector((state) => state.exchange.currencies) return (
@@ -16,18 +19,17 @@ const MostVolume = ({mostVolume}) => {
{mostVolume.pairInfo.baseAsset} - {t("currency." + mostVolume.pairInfo.baseAsset)} + {getCurrencyNameOrAlias(currencies[mostVolume?.pairInfo?.baseAsset], language)}
- {mostVolume.pairInfo.baseAsset} - {new BN(mostVolume?.volume).toFormat()} + {mostVolume?.pairInfo?.baseAsset} + {new BN(mostVolume?.volume).decimalPlaces(currencies[mostVolume?.pairInfo?.baseAsset]?.precision ?? 0).toFormat()}
- {/*++ to do ++*/} {/* 0 ? "text-green" : "text-red"} direction-ltr`}>{new BN(mostVolume?.change).toFormat(2)} %*/}
diff --git a/src/main/Browser/Pages/Login/components/LoginForm/LoginForm.js b/src/main/Browser/Pages/Login/components/LoginForm/LoginForm.js index 5d575f84..5f5c6513 100644 --- a/src/main/Browser/Pages/Login/components/LoginForm/LoginForm.js +++ b/src/main/Browser/Pages/Login/components/LoginForm/LoginForm.js @@ -90,9 +90,11 @@ const LoginForm = () => { }) .catch((err) => { if (err?.response?.status === 401) { + setShowVerifyEmail(false) return setLoginError(t("login.wrongPassword")); } if (err?.response?.status === 403) { + setShowVerifyEmail(false) setLoginError(t("login.wrongOTP")); return setNeedOTP(true) } @@ -100,6 +102,7 @@ const LoginForm = () => { setShowVerifyEmail(true) return setLoginError(t("login.accountNotActive")); } + setShowVerifyEmail(false) setLoginError(t("login.loginError")); }) .finally(() => { diff --git a/src/main/Browser/Pages/UserPanel/Sections/Content/components/History/components/DepositHistory/DepositHistory.js b/src/main/Browser/Pages/UserPanel/Sections/Content/components/History/components/DepositHistory/DepositHistory.js index 465d475f..b71b40e4 100644 --- a/src/main/Browser/Pages/UserPanel/Sections/Content/components/History/components/DepositHistory/DepositHistory.js +++ b/src/main/Browser/Pages/UserPanel/Sections/Content/components/History/components/DepositHistory/DepositHistory.js @@ -13,6 +13,7 @@ import i18n from "i18next"; import ToggleSwitch from "../../../../../../../../../../components/ToggleSwitch/ToggleSwitch"; import Button from "../../../../../../../../../../components/Button/Button"; import DepositHistoryTable from "../DepositHistoryTable/DepositHistoryTable"; +import {getCurrencyNameOrAlias} from "../../../../../../../../../../utils/utils"; const DepositHistory = () => { @@ -20,6 +21,10 @@ const DepositHistory = () => { const {t} = useTranslation(); const coins = useSelector((state) => state.exchange.assets) + const language = i18n.language + const currencies = useSelector((state) => state.exchange.currencies) + + const [query, setQuery] = useState({ "currency": null, // optional "category": null, // optional [DEPOSIT, FEE, TRADE, WITHDRAW, ORDER_CANCEL, ORDER_CREATE, ORDER_FINALIZED] @@ -54,8 +59,10 @@ const DepositHistory = () => { categoryOptions.push({value: o, label: t('TransactionCategory.' + o)}) }) - coins.forEach((o) => { - currenciesOptions.push({value: o, label: t('currency.' + o)}) + + + Object.keys(currencies).forEach((o) => { + currenciesOptions.push({value: o, label: getCurrencyNameOrAlias(currencies[o], language)}) }) @@ -137,7 +144,7 @@ const DepositHistory = () => { type="select" value={{ value: query?.currency, - label: query?.currency ? t('currency.'+ query?.currency) : t('all'), + label: query?.currency ? getCurrencyNameOrAlias(currencies[query?.currency], language) : t('all'), }} onchange={(e) => setQuery({...query, currency: e.value, offset:0})} customClass={`width-20 ${classes.thisInput}`} diff --git a/src/main/Browser/Pages/UserPanel/Sections/Content/components/History/components/DepositHistoryTable/DepositHistoryTable.js b/src/main/Browser/Pages/UserPanel/Sections/Content/components/History/components/DepositHistoryTable/DepositHistoryTable.js index 1e070d7a..9d58a785 100644 --- a/src/main/Browser/Pages/UserPanel/Sections/Content/components/History/components/DepositHistoryTable/DepositHistoryTable.js +++ b/src/main/Browser/Pages/UserPanel/Sections/Content/components/History/components/DepositHistoryTable/DepositHistoryTable.js @@ -4,12 +4,17 @@ import {useTranslation} from "react-i18next"; import {useSelector} from "react-redux"; import Date from "../../../../../../../../../../components/Date/Date"; import moment from "moment-jalaali"; -import {BN} from "../../../../../../../../../../utils/utils"; +import {BN, getCurrencyNameOrAlias} from "../../../../../../../../../../utils/utils"; +import i18n from "i18next"; const DepositHistoryTable = ({txs, offset}) => { const {t} = useTranslation(); + const language = i18n.language + const currencies = useSelector((state) => state.exchange.currencies) + + let head = (
{t("date")} @@ -37,7 +42,7 @@ const DepositHistoryTable = ({txs, offset}) => { - {t("currency." + tr.currency )} + {getCurrencyNameOrAlias(currencies[tr.currency], language)} @@ -45,7 +50,7 @@ const DepositHistoryTable = ({txs, offset}) => { - {new BN(tr?.amount).toFormat()} + {new BN(tr?.amount).decimalPlaces(currencies[tr.currency].precision).toFormat()} diff --git a/src/main/Browser/Pages/UserPanel/Sections/Content/components/History/components/Transactions/Transactions.js b/src/main/Browser/Pages/UserPanel/Sections/Content/components/History/components/Transactions/Transactions.js index 933d0064..9dca0f66 100644 --- a/src/main/Browser/Pages/UserPanel/Sections/Content/components/History/components/Transactions/Transactions.js +++ b/src/main/Browser/Pages/UserPanel/Sections/Content/components/History/components/Transactions/Transactions.js @@ -13,12 +13,16 @@ import ToggleSwitch from "../../../../../../../../../../components/ToggleSwitch/ import Button from "../../../../../../../../../../components/Button/Button"; import TransactionsTable from "../TransactionsTable/TransactionsTable"; import {useGetTransactionsHistory} from "../../../../../../../../../../queries"; +import {getCurrencyNameOrAlias} from "../../../../../../../../../../utils/utils"; const Transactions = () => { const {t} = useTranslation(); const coins = useSelector((state) => state.exchange.assets) + const language = i18n.language + const currencies = useSelector((state) => state.exchange.currencies) + const [query, setQuery] = useState({ "currency": null, // optional "category": null, // optional [DEPOSIT, FEE, TRADE, WITHDRAW, ORDER_CANCEL, ORDER_CREATE, ORDER_FINALIZED] @@ -52,8 +56,8 @@ const Transactions = () => { categoryOptions.push({value: o, label: t('TransactionCategory.' + o)}) }) - coins.forEach((o) => { - currenciesOptions.push({value: o, label: t('currency.' + o)}) + Object.keys(currencies).forEach((o) => { + currenciesOptions.push({value: o, label: getCurrencyNameOrAlias(currencies[o], language)}) }) const scrollRef = useRef(null); @@ -131,7 +135,7 @@ const Transactions = () => { type="select" value={{ value: query?.currency, - label: query?.currency ? t('currency.'+ query?.currency) : t('all'), + label: query?.currency ? getCurrencyNameOrAlias(currencies[query?.currency], language) : t('all'), }} onchange={(e) => setQuery({...query, currency: e.value, offset:0})} customClass={`width-20 ${classes.thisInput}`} diff --git a/src/main/Browser/Pages/UserPanel/Sections/Content/components/History/components/TransactionsTable/TransactionsTable.js b/src/main/Browser/Pages/UserPanel/Sections/Content/components/History/components/TransactionsTable/TransactionsTable.js index d434f2c9..f82de9d5 100644 --- a/src/main/Browser/Pages/UserPanel/Sections/Content/components/History/components/TransactionsTable/TransactionsTable.js +++ b/src/main/Browser/Pages/UserPanel/Sections/Content/components/History/components/TransactionsTable/TransactionsTable.js @@ -3,11 +3,16 @@ import classes from './TransactionsTable.module.css'; import {useTranslation} from "react-i18next"; import Date from "../../../../../../../../../../components/Date/Date"; import moment from "moment-jalaali"; -import {BN} from "../../../../../../../../../../utils/utils"; +import {BN, getCurrencyNameOrAlias} from "../../../../../../../../../../utils/utils"; +import i18n from "i18next"; +import {useSelector} from "react-redux"; const TransactionsTable = ({txs}) => { const {t} = useTranslation(); + const language = i18n.language + const currencies = useSelector((state) => state.exchange.currencies) + let head = (
{t("date")} @@ -35,13 +40,15 @@ const TransactionsTable = ({txs}) => { {t("TransactionCategory." + tr.category )} - {t("currency." + tr.currency )} + {getCurrencyNameOrAlias(currencies[tr.currency], language)} {new BN(tr?.balanceChange).toFormat()} + {new BN(tr?.balanceChange).decimalPlaces(currencies[tr.currency].precision).toFormat()} {new BN(tr?.balance).toFormat()} + {new BN(tr?.balance).decimalPlaces(currencies[tr.currency].precision).toFormat()}
diff --git a/src/main/Browser/Pages/UserPanel/Sections/Content/components/History/components/WithdrawHistory/WithdrawHistory.js b/src/main/Browser/Pages/UserPanel/Sections/Content/components/History/components/WithdrawHistory/WithdrawHistory.js index 0a5333e4..85872412 100644 --- a/src/main/Browser/Pages/UserPanel/Sections/Content/components/History/components/WithdrawHistory/WithdrawHistory.js +++ b/src/main/Browser/Pages/UserPanel/Sections/Content/components/History/components/WithdrawHistory/WithdrawHistory.js @@ -13,12 +13,16 @@ import i18n from "i18next"; import ToggleSwitch from "../../../../../../../../../../components/ToggleSwitch/ToggleSwitch"; import Button from "../../../../../../../../../../components/Button/Button"; import WithdrawHistoryTable from "../WithdrawHistoryTable/WithdrawHistoryTable"; +import {getCurrencyNameOrAlias} from "../../../../../../../../../../utils/utils"; const WithdrawHistory = () => { const {t} = useTranslation(); const coins = useSelector((state) => state.exchange.assets) + const language = i18n.language + const currencies = useSelector((state) => state.exchange.currencies) + const [query, setQuery] = useState({ "currency": null, // optional "category": null, // optional [DEPOSIT, FEE, TRADE, WITHDRAW, ORDER_CANCEL, ORDER_CREATE, ORDER_FINALIZED] @@ -53,11 +57,13 @@ const WithdrawHistory = () => { categoryOptions.push({value: o, label: t('TransactionCategory.' + o)}) }) - coins.forEach((o) => { - currenciesOptions.push({value: o, label: t('currency.' + o)}) + + Object.keys(currencies).forEach((o) => { + currenciesOptions.push({value: o, label: getCurrencyNameOrAlias(currencies[o], language)}) }) + const scrollRef = useRef(null); @@ -137,7 +143,7 @@ const WithdrawHistory = () => { type="select" value={{ value: query?.currency, - label: query?.currency ? t('currency.'+ query?.currency) : t('all'), + label: query?.currency ? getCurrencyNameOrAlias(currencies[query?.currency], language) : t('all'), }} onchange={(e) => setQuery({...query, currency: e.value, offset:0})} customClass={`width-20 ${classes.thisInput}`} diff --git a/src/main/Browser/Pages/UserPanel/Sections/Content/components/History/components/WithdrawHistoryTable/WithdrawHistoryTable.js b/src/main/Browser/Pages/UserPanel/Sections/Content/components/History/components/WithdrawHistoryTable/WithdrawHistoryTable.js index e80af9c9..96b8fb76 100644 --- a/src/main/Browser/Pages/UserPanel/Sections/Content/components/History/components/WithdrawHistoryTable/WithdrawHistoryTable.js +++ b/src/main/Browser/Pages/UserPanel/Sections/Content/components/History/components/WithdrawHistoryTable/WithdrawHistoryTable.js @@ -3,14 +3,21 @@ import classes from './WithdrawHistoryTable.module.css' import {useTranslation} from "react-i18next"; import Date from "../../../../../../../../../../components/Date/Date"; import moment from "moment-jalaali"; -import {BN} from "../../../../../../../../../../utils/utils"; +import {BN, getCurrencyNameOrAlias} from "../../../../../../../../../../utils/utils"; import Icon from "../../../../../../../../../../components/Icon/Icon"; +import i18n from "i18next"; +import {useSelector} from "react-redux"; const WithdrawHistoryTable = ({txs, offset}) => { + const {t} = useTranslation(); + const language = i18n.language + const currencies = useSelector((state) => state.exchange.currencies) + + const [isOpen, setIsOpen] = useState(false); - const {t} = useTranslation(); + let head = (
@@ -41,7 +48,7 @@ const WithdrawHistoryTable = ({txs, offset}) => { - {t("currency." + tr.currency )} + {getCurrencyNameOrAlias(currencies[tr.currency], language)} @@ -49,11 +56,11 @@ const WithdrawHistoryTable = ({txs, offset}) => { - {new BN(tr?.amount).toFormat()} + {new BN(tr?.amount).decimalPlaces(currencies[tr.currency].precision).toFormat()} - {new BN(tr?.appliedFee).toFormat()} + {new BN(tr?.appliedFee).decimalPlaces(currencies[tr.currency].precision).toFormat()} diff --git a/src/main/Browser/Pages/UserPanel/Sections/Content/components/Market/components/LastTrades/LastTrades.js b/src/main/Browser/Pages/UserPanel/Sections/Content/components/Market/components/LastTrades/LastTrades.js index 93f04e00..74622aac 100644 --- a/src/main/Browser/Pages/UserPanel/Sections/Content/components/Market/components/LastTrades/LastTrades.js +++ b/src/main/Browser/Pages/UserPanel/Sections/Content/components/Market/components/LastTrades/LastTrades.js @@ -27,6 +27,8 @@ const LastTrades = () => {
} + + return (
diff --git a/src/main/Browser/Pages/UserPanel/Sections/Content/components/Market/components/LastTrades/components/LastTradesTable/LastTradesTable.js b/src/main/Browser/Pages/UserPanel/Sections/Content/components/Market/components/LastTrades/components/LastTradesTable/LastTradesTable.js index 779f523b..73078cd3 100644 --- a/src/main/Browser/Pages/UserPanel/Sections/Content/components/Market/components/LastTrades/components/LastTradesTable/LastTradesTable.js +++ b/src/main/Browser/Pages/UserPanel/Sections/Content/components/Market/components/LastTrades/components/LastTradesTable/LastTradesTable.js @@ -2,15 +2,20 @@ import React from "react"; import classes from "./LastTradesTable.module.css"; import {useTranslation} from "react-i18next"; import moment from "moment-jalaali"; -import {connect} from "react-redux"; +import {connect, useSelector} from "react-redux"; import ScrollBar from "../../../../../../../../../../../../components/ScrollBar"; import {BN} from "../../../../../../../../../../../../utils/utils"; import Date from "../../../../../../../../../../../../components/Date/Date"; +import i18n from "i18next"; const LastTradesTable = (props) => { const {t} = useTranslation(); const {activePair, data} = props + + const language = i18n.language + const currencies = useSelector((state) => state.exchange.currencies) + return (
@@ -38,9 +43,9 @@ const LastTradesTable = (props) => { {moment(tr.time).format("HH:mm:ss")} - {amount.decimalPlaces(activePair.baseAssetPrecision).toFormat()} - {pricePerUnit.decimalPlaces(activePair.quoteAssetPrecision).toFormat()} - {totalPrice.decimalPlaces(activePair.quoteAssetPrecision).toFormat()} + {amount.decimalPlaces(currencies[activePair.baseAsset].precision).toFormat()} + {pricePerUnit.decimalPlaces(currencies[activePair.quoteAsset].precision).toFormat()} + {totalPrice.decimalPlaces(currencies[activePair.quoteAsset].precision).toFormat()} ); })} diff --git a/src/main/Browser/Pages/UserPanel/Sections/Content/components/Market/components/MyOrders/components/OpenOrders/OpenOrders.js b/src/main/Browser/Pages/UserPanel/Sections/Content/components/Market/components/MyOrders/components/OpenOrders/OpenOrders.js index db2602c2..a0891f7b 100644 --- a/src/main/Browser/Pages/UserPanel/Sections/Content/components/Market/components/MyOrders/components/OpenOrders/OpenOrders.js +++ b/src/main/Browser/Pages/UserPanel/Sections/Content/components/Market/components/MyOrders/components/OpenOrders/OpenOrders.js @@ -12,6 +12,7 @@ import Error from "../../../../../../../../../../../../components/Error/Error"; import {useMyOpenOrders} from "../../../../../../../../../../../../queries"; import {cancelOrderByOrderID} from "js-api-client"; import Date from "../../../../../../../../../../../../components/Date/Date"; +import i18n from "i18next"; const OpenOrders = () => { @@ -19,9 +20,13 @@ const OpenOrders = () => { const {t} = useTranslation(); const [openOrder, setOpenOrder] = useState(null) + const language = i18n.language + const currencies = useSelector((state) => state.exchange.currencies) const activePair = useSelector((state) => state.exchange.activePair) const lastTransaction = useSelector((state) => state.auth.lastTransaction); + + const {data, isLoading, error, refetch} = useMyOpenOrders(activePair.symbol) useEffect(() => { @@ -71,9 +76,9 @@ const OpenOrders = () => { {moment(tr.time).format("HH:mm:ss")} - {origQty.decimalPlaces(activePair.baseAssetPrecision).toFormat()} - {pricePerUnit.decimalPlaces(activePair.quoteAssetPrecision).toFormat()} - {totalPrice.decimalPlaces(activePair.quoteAssetPrecision).toFormat()} + {origQty.decimalPlaces(currencies[activePair.baseAsset].precision).toFormat()} + {pricePerUnit.decimalPlaces(currencies[activePair.quoteAsset].precision).toFormat()} + {totalPrice.decimalPlaces(currencies[activePair.quoteAsset].precision).toFormat()} {executedQty.dividedBy(origQty).multipliedBy(100).toFormat(0)} {

{t("myOrders.tradedAmount")} :{" "} - {executedQty.decimalPlaces(activePair.baseAssetPrecision).toFormat()} + {executedQty.decimalPlaces(currencies[activePair.baseAsset].precision).toFormat()}

{

{t("myOrders.tradedPrice")} :{" "} - {executedQty.multipliedBy(pricePerUnit).decimalPlaces(activePair.baseAssetPrecision).toFormat()} + {executedQty.multipliedBy(pricePerUnit).decimalPlaces(currencies[activePair.baseAsset].precision).toFormat()}

diff --git a/src/main/Browser/Pages/UserPanel/Sections/Content/components/Market/components/MyOrders/components/OrdersHistory/OrdersHistory.js b/src/main/Browser/Pages/UserPanel/Sections/Content/components/Market/components/MyOrders/components/OrdersHistory/OrdersHistory.js index 42b66593..946b4749 100644 --- a/src/main/Browser/Pages/UserPanel/Sections/Content/components/Market/components/MyOrders/components/OrdersHistory/OrdersHistory.js +++ b/src/main/Browser/Pages/UserPanel/Sections/Content/components/Market/components/MyOrders/components/OrdersHistory/OrdersHistory.js @@ -9,6 +9,8 @@ import Icon from "../../../../../../../../../../../../components/Icon/Icon"; import {useMyOrderHistory} from "../../../../../../../../../../../../queries"; import Error from "../../../../../../../../../../../../components/Error/Error"; import Date from "../../../../../../../../../../../../components/Date/Date"; +import i18n from "i18next"; +import {BN} from "../../../../../../../../../../../../utils/utils"; const OrdersHistory = () => { const {t} = useTranslation(); @@ -17,6 +19,9 @@ const OrdersHistory = () => { const activePair = useSelector((state) => state.exchange.activePair) const lastTransaction = useSelector((state) => state.auth.lastTransaction); + const language = i18n.language + const currencies = useSelector((state) => state.exchange.currencies) + const {data, isLoading, error, refetch} = useMyOrderHistory(activePair.symbol) useEffect(() => { @@ -53,10 +58,16 @@ const OrdersHistory = () => { {moment(tr.time).format("HH:mm:ss")} - {tr.origQty} - {tr.price.toLocaleString()} - {(tr.origQty * tr.price).toLocaleString()} + + + {new BN(tr.origQty).decimalPlaces(currencies[activePair.baseAsset].precision).toFormat()} + + {new BN(tr.price).decimalPlaces(currencies[activePair.quoteAsset].precision).toFormat()} + + {new BN(tr.origQty).multipliedBy(tr.price).decimalPlaces(currencies[activePair.quoteAsset].precision).toFormat()} + {t("orderStatus." + tr.status)} + {openOrder === index ? ( setOpenOrder(null)}> { @@ -20,6 +21,9 @@ const Trades = () => { const activePair = useSelector((state) => state.exchange.activePair) const lastTransaction = useSelector((state) => state.auth.lastTransaction); + const language = i18n.language + const currencies = useSelector((state) => state.exchange.currencies) + const {data, isLoading, error, refetch} = useMyTrades(activePair.symbol) useEffect(() => { @@ -58,9 +62,10 @@ const Trades = () => { {moment(tr.time).format("HH:mm:ss")} - {tr.qty} - {tr.price.toLocaleString()} - {(tr.qty * tr.price).toLocaleString()} + {new BN(tr.qty).decimalPlaces(currencies[activePair.baseAsset].precision).toFormat()} + {new BN(tr.price).decimalPlaces(currencies[activePair.quoteAsset].precision).toFormat()} + {new BN(tr.qty).multipliedBy(tr.price).decimalPlaces(currencies[activePair.quoteAsset].precision).toFormat()} + {openOrder === index ? ( setOpenOrder(null)}> { style={{display: openOrder === index ? "revert" : "none"}}>

{t("myOrders.orderId")} : {tr.orderId}

- {t("commission")} : {new BN(tr.commission).toFormat()} {t("currency." + tr.commissionAsset.toUpperCase())} + {t("commission")} : {new BN(tr.commission).decimalPlaces(currencies[tr.commissionAsset.toUpperCase()].precision).toFormat()} + {getCurrencyNameOrAlias(currencies[tr.commissionAsset.toUpperCase()], language)}

diff --git a/src/main/Browser/Pages/UserPanel/Sections/Content/components/Market/components/Order/components/BuyOrder/BuyOrder.js b/src/main/Browser/Pages/UserPanel/Sections/Content/components/Market/components/Order/components/BuyOrder/BuyOrder.js index 47312f06..0954ee66 100644 --- a/src/main/Browser/Pages/UserPanel/Sections/Content/components/Market/components/Order/components/BuyOrder/BuyOrder.js +++ b/src/main/Browser/Pages/UserPanel/Sections/Content/components/Market/components/Order/components/BuyOrder/BuyOrder.js @@ -3,13 +3,14 @@ import {toast} from "react-hot-toast"; import classes from "../../Order.module.css"; import React, {useEffect, useState} from "react"; import {Trans, useTranslation} from "react-i18next"; -import {BN, parsePriceString} from "../../../../../../../../../../../../utils/utils"; +import {BN, getCurrencyNameOrAlias, parsePriceString} from "../../../../../../../../../../../../utils/utils"; import NumberInput from "../../../../../../../../../../../../components/NumberInput/NumberInput"; import Button from "../../../../../../../../../../../../components/Button/Button"; import {setLastTransaction} from "../../../../../../../../../../../../store/actions/auth"; import {images} from "../../../../../../../../../../../../assets/images"; import {useGetUserAccount} from "../../../../../../../../../../../../queries/hooks/useGetUserAccount"; import {createOrder} from "js-api-client"; +import i18n from "i18next"; const BuyOrder = () => { @@ -23,6 +24,9 @@ const BuyOrder = () => { const bestBuyPrice = useSelector((state) => state.exchange.activePairOrders.bestBuyPrice) const selectedBuyOrder = useSelector((state) => state.exchange.activePairOrders.selectedBuyOrder) + const language = i18n.language + const currencies = useSelector((state) => state.exchange.currencies) + const tradeFee = useSelector((state) => state.auth.tradeFee) const isLogin = useSelector((state) => state.auth.isLogin) @@ -71,26 +75,27 @@ const BuyOrder = () => { const currencyValidator = (key, val, rule) => { - if (!val.isZero() && val.isLessThan(rule.min)) { + + if (!val.isZero() && val.isLessThan(currencies[rule].minOrder)) { return setAlert({ ...alert, [key]: ( ), }); } - if (!val.mod(rule.step).isZero()) { + if (!val.mod(currencies?.[rule]?.step).isZero()) { return setAlert({ ...alert, [key]: () }) } @@ -102,12 +107,14 @@ const BuyOrder = () => { switch (key) { case "reqAmount": const reqAmount = new BN(value); - currencyValidator("reqAmount", reqAmount, activePair.baseRange); + currencyValidator("reqAmount", reqAmount, activePair.baseAsset); setOrder({ ...order, reqAmount, - totalPrice: reqAmount.multipliedBy(order.pricePerUnit).decimalPlaces(activePair.quoteAssetPrecision), - tradeFee: reqAmount.multipliedBy(tradeFee[activePair.quoteAsset]).decimalPlaces(activePair.baseAssetPrecision), + /*totalPrice: reqAmount.multipliedBy(order.pricePerUnit).decimalPlaces(activePair.quoteAssetPrecision),*/ + totalPrice: reqAmount.multipliedBy(order.pricePerUnit).decimalPlaces(currencies[activePair.quoteAsset].precision), + /*tradeFee: reqAmount.multipliedBy(tradeFee[activePair.quoteAsset]).decimalPlaces(activePair.baseAssetPrecision),*/ + tradeFee: reqAmount.multipliedBy(tradeFee[activePair.quoteAsset]).decimalPlaces(currencies[activePair.baseAsset].precision), }); break; case "pricePerUnit": @@ -115,20 +122,24 @@ const BuyOrder = () => { setOrder({ ...order, pricePerUnit: pricePerUnit, - totalPrice: pricePerUnit.multipliedBy(order.reqAmount).decimalPlaces(activePair.quoteAssetPrecision), - tradeFee: order.reqAmount.multipliedBy(tradeFee[activePair.quoteAsset]).decimalPlaces(activePair.baseAssetPrecision), + /*totalPrice: pricePerUnit.multipliedBy(order.reqAmount).decimalPlaces(activePair.quoteAssetPrecision),*/ + totalPrice: pricePerUnit.multipliedBy(order.reqAmount).decimalPlaces(currencies[activePair.quoteAsset].precision), + /*tradeFee: order.reqAmount.multipliedBy(tradeFee[activePair.quoteAsset]).decimalPlaces(activePair.baseAssetPrecision),*/ + tradeFee: order.reqAmount.multipliedBy(tradeFee[activePair.quoteAsset]).decimalPlaces(currencies[activePair.baseAsset].precision), }); break; case "totalPrice": const totalPrice = new BN(value); - const req = totalPrice.dividedBy(order.pricePerUnit).decimalPlaces(activePair.baseAssetPrecision); + /*const req = totalPrice.dividedBy(order.pricePerUnit).decimalPlaces(activePair.baseAssetPrecision);*/ + const req = totalPrice.dividedBy(order.pricePerUnit).decimalPlaces(currencies[activePair.baseAsset].precision); setOrder({ ...order, reqAmount: req.isFinite() ? req : new BN(0), totalPrice, - tradeFee: req.isFinite() ? req.multipliedBy(tradeFee[activePair.quoteAsset]).decimalPlaces(activePair.baseAssetPrecision) : new BN(0), + /*tradeFee: req.isFinite() ? req.multipliedBy(tradeFee[activePair.quoteAsset]).decimalPlaces(activePair.baseAssetPrecision) : new BN(0),*/ + tradeFee: req.isFinite() ? req.multipliedBy(tradeFee[activePair.quoteAsset]).decimalPlaces(currencies[activePair.baseAsset].precision) : new BN(0), }); - currencyValidator("reqAmount", req, activePair.baseRange); + currencyValidator("reqAmount", req, activePair.baseAsset); break; default: } @@ -151,7 +162,7 @@ const BuyOrder = () => { useEffect(() => { setOrder((prevState) => ({ ...order, - tradeFee: prevState.totalPrice.multipliedBy(tradeFee[activePair.quoteAsset]).decimalPlaces(activePair.baseAssetPrecision), + tradeFee: prevState.totalPrice.multipliedBy(tradeFee[activePair.quoteAsset]).decimalPlaces(currencies[activePair.baseAsset].precision), })); }, [tradeFee]); @@ -169,10 +180,10 @@ const BuyOrder = () => { ...order, reqAmount, pricePerUnit: pricePerUnit, - totalPrice: reqAmount.multipliedBy(pricePerUnit).decimalPlaces(activePair.quoteAssetPrecision), - tradeFee: reqAmount.multipliedBy(tradeFee[activePair.quoteAsset]).decimalPlaces(activePair.baseAssetPrecision), + totalPrice: reqAmount.multipliedBy(pricePerUnit).decimalPlaces(currencies[activePair.quoteAsset].precision), + tradeFee: reqAmount.multipliedBy(tradeFee[activePair.quoteAsset]).decimalPlaces(currencies[activePair.baseAsset].precision), }); - currencyValidator("reqAmount", reqAmount, activePair.baseRange); + currencyValidator("reqAmount", reqAmount, activePair.baseAsset); }, [selectedBuyOrder]); @@ -181,9 +192,9 @@ const BuyOrder = () => { if (order.pricePerUnit.isEqualTo(0)) { const pricePerUnit = new BN(bestBuyPrice) let totalPrice = new BN(quote); - let reqAmount = totalPrice.dividedBy(pricePerUnit).decimalPlaces(activePair.baseAssetPrecision) - if (!reqAmount.mod(activePair.baseRange.step).isZero()) { - reqAmount = reqAmount.minus(reqAmount.mod(activePair.baseRange.step)); + let reqAmount = totalPrice.dividedBy(pricePerUnit).decimalPlaces(currencies[activePair.baseAsset].precision) + if (!reqAmount.mod(currencies[activePair.baseAsset].step).isZero()) { + reqAmount = reqAmount.minus(reqAmount.mod(currencies[activePair.baseAsset].step)); totalPrice = reqAmount.multipliedBy(pricePerUnit); } setOrder({ @@ -191,13 +202,13 @@ const BuyOrder = () => { reqAmount, pricePerUnit, totalPrice, - tradeFee: reqAmount.multipliedBy(tradeFee[activePair.quoteAsset]).decimalPlaces(activePair.baseAssetPrecision), + tradeFee: reqAmount.multipliedBy(tradeFee[activePair.quoteAsset]).decimalPlaces(currencies[activePair.baseAsset].precision), }); } else { let totalPrice = new BN(quote); - let reqAmount = totalPrice.dividedBy(order.pricePerUnit).decimalPlaces(activePair.baseAssetPrecision) - if (!reqAmount.mod(activePair.baseRange.step).isZero()) { - reqAmount = reqAmount.minus(reqAmount.mod(activePair.baseRange.step)); + let reqAmount = totalPrice.dividedBy(order.pricePerUnit).decimalPlaces(currencies[activePair.baseAsset].precision) + if (!reqAmount.mod(currencies[activePair.baseAsset].step).isZero()) { + reqAmount = reqAmount.minus(reqAmount.mod(currencies[activePair.baseAsset].step)); } buyPriceHandler( reqAmount.toFormat(), @@ -236,8 +247,8 @@ const BuyOrder = () => { toast.success( { }}> {t("orders.availableAmount")}:{" "} - {new BN(quote).toFormat()}{" "} - {t("currency." + activePair.quoteAsset)} + {new BN(quote).toFormat()}{" "}{getCurrencyNameOrAlias(currencies[activePair.quoteAsset], language)}

{ @@ -283,7 +293,7 @@ const BuyOrder = () => { }}> {t("orders.bestOffer")}:{" "} - {new BN(bestBuyPrice).toFormat()}{" "}{t("currency." + activePair.quoteAsset)} + {new BN(bestBuyPrice).toFormat()}{" "}{getCurrencyNameOrAlias(currencies[activePair.quoteAsset], language)}

@@ -313,9 +323,9 @@ const BuyOrder = () => { buyPriceHandler(e.target.value, "reqAmount")} alert={alert.reqAmount} isAllowed={isAllowed} @@ -326,18 +336,18 @@ const BuyOrder = () => { customClass={classes.stopMarket} lead={t("orders.pricePerUnit")} prefix="~" - after={t("currency." + activePair.quoteAsset)} + after={getCurrencyNameOrAlias(currencies[activePair.quoteAsset], language)} value={order.pricePerUnit.toFormat()} - maxDecimal={activePair.quoteAssetPrecision} + maxDecimal={currencies[activePair.quoteAsset].precision} onchange={(e) => buyPriceHandler(e.target.value, "pricePerUnit")} isAllowed={isAllowed} /> ) : ( buyPriceHandler(e.target.value, "pricePerUnit")} isAllowed={isAllowed} /> @@ -356,8 +366,8 @@ const BuyOrder = () => { buyPriceHandler(e.target.value, "totalPrice")} alert={alert.totalPrice} isAllowed={isAllowed} @@ -367,12 +377,12 @@ const BuyOrder = () => {

{t("orders.tradeFee")}:{" "} {order.tradeFee.toFormat()}{" "} - {t("currency." + activePair.baseAsset)} + {getCurrencyNameOrAlias(currencies[activePair.baseAsset], language)}

{t("orders.getAmount")}:{" "} - {order.reqAmount.minus(order.tradeFee).decimalPlaces(activePair.baseAssetPrecision).toFormat()}{" "} - {t("currency." + activePair.baseAsset)} + {order.reqAmount.minus(order.tradeFee).decimalPlaces(currencies[activePair.baseAsset].precision).toFormat()}{" "} + {getCurrencyNameOrAlias(currencies[activePair.baseAsset], language)}

+ + + +
+ ); +}; + +export default OnChainWithdraw; diff --git a/src/main/Browser/Pages/UserPanel/Sections/Content/components/Wallet/components/DepositWithdraw/components/Withdrawal/Module/OnChainWithdraw/OnChainWithdraw.module.css b/src/main/Browser/Pages/UserPanel/Sections/Content/components/Wallet/components/DepositWithdraw/components/Withdrawal/Module/OnChainWithdraw/OnChainWithdraw.module.css new file mode 100644 index 00000000..5dfe8445 --- /dev/null +++ b/src/main/Browser/Pages/UserPanel/Sections/Content/components/Wallet/components/DepositWithdraw/components/Withdrawal/Module/OnChainWithdraw/OnChainWithdraw.module.css @@ -0,0 +1,44 @@ +.thisInput :global(.lead) { + width: 28%; +} +.thisInput :global(.selectExternalClass) { + width: 78% !important; +} + +.thisInput :global(input) { + width: 78% !important; +} + +.addressInput :global(.lead) { + width: 18% !important; +} +.addressInput :global(input) { + width: 82% !important; +} + +.withdrawalInput :global(.lead) { + width: 24%; +} +.withdrawalInput :global(input) { + width: 76% !important; +} +.withdrawNumberInput :global(.lead) { + width: 50%; +} +.withdrawNumberInput :global(input) { + width: 50% !important; +} + + +.thisButton.withdrawal{ + background-color: var(--orange); + color: #000; + border: 1px solid var(--cardBorder); +} + +.thisButton:disabled,.button[disabled] { + /*border: 0.3vh solid var(--cardBodyAlpha);*/ + background: var(--cardBodyAlpha); + color: var(--textColor); + cursor: not-allowed; +} diff --git a/src/main/Browser/Pages/UserPanel/Sections/Content/components/Wallet/components/DepositWithdraw/components/Withdrawal/Withdrawal.js b/src/main/Browser/Pages/UserPanel/Sections/Content/components/Wallet/components/DepositWithdraw/components/Withdrawal/Withdrawal.js new file mode 100644 index 00000000..c5bb7be2 --- /dev/null +++ b/src/main/Browser/Pages/UserPanel/Sections/Content/components/Wallet/components/DepositWithdraw/components/Withdrawal/Withdrawal.js @@ -0,0 +1,57 @@ +import React, {useMemo} from 'react'; +import {useTranslation} from "react-i18next"; +import {useParams} from "react-router-dom"; +import {useSelector} from "react-redux"; +import {useGetGatewaysByCurrency} from "../../../../../../../../../../../../queries"; +import Loading from "../../../../../../../../../../../../components/Loading/Loading"; +import Error from "../../../../../../../../../../../../components/Error/Error"; +import OnChainDeposit from "../Deposit/Module/OnChainDeposit/OnChainDeposit"; +import OnChainWithdraw from "./Module/OnChainWithdraw/OnChainWithdraw"; + +const Withdrawal = () => { + + const {t} = useTranslation(); + const {id} = useParams(); + const currencies = useSelector((state) => state.exchange.currencies) + + const { data, isLoading, error } = useGetGatewaysByCurrency(id, { + includeManualGateways: false, + includeOffChainGateways: true, + includeOnChainGateways: true + }); + + const { hasOnChain, hasOffChain } = useMemo(() => ({ + hasOnChain: data?.some(gateway => gateway.type === "OnChain"), + hasOffChain: data?.some(gateway => gateway.type === "OffChain") + }), [data]); + + if (!currencies[id]?.withdrawAllowed) return
+ {t("noData")} +
+ if (isLoading) return + if (error) return + if (data.length <= 0 ) return
+ {t("noData")} +
+ + switch (true) { + case hasOnChain && hasOffChain: + return
+ {t("comingSoon")} +
; + case hasOnChain: + return ; + case hasOffChain: + return
+ {t("comingSoon")} +
; + default: + return ( +
+ {t("noData")} +
+ ); + } +}; + +export default Withdrawal; diff --git a/src/main/Browser/Pages/UserPanel/Sections/Content/components/Wallet/components/WithdrawTx/WithdrawTx.js b/src/main/Browser/Pages/UserPanel/Sections/Content/components/Wallet/components/WithdrawTx/WithdrawTx.js index 1fac782a..50b8007c 100644 --- a/src/main/Browser/Pages/UserPanel/Sections/Content/components/Wallet/components/WithdrawTx/WithdrawTx.js +++ b/src/main/Browser/Pages/UserPanel/Sections/Content/components/Wallet/components/WithdrawTx/WithdrawTx.js @@ -10,12 +10,18 @@ import WithdrawTxTable from "../WithdrawTxTable/WithdrawTxTable"; import * as Routes from "../../../../../../../../Routes/routes"; import Icon from "../../../../../../../../../../components/Icon/Icon"; import i18n from "i18next"; +import {useSelector} from "react-redux"; +import {getCurrencyNameOrAlias} from "../../../../../../../../../../utils/utils"; const WithdrawTx = () => { const {id} = useParams(); const {t} = useTranslation(); + const language = i18n.language + const currencies = useSelector((state) => state.exchange.currencies) + + const query = { "currency": id, // optional "category": null, // optional [DEPOSIT, FEE, TRADE, WITHDRAW, ORDER_CANCEL, ORDER_CREATE, ORDER_FINALIZED] @@ -44,7 +50,7 @@ const WithdrawTx = () => { diff --git a/src/main/Browser/Pages/UserPanel/Sections/Content/components/Wallet/components/WithdrawTxTable/WithdrawTxTable.js b/src/main/Browser/Pages/UserPanel/Sections/Content/components/Wallet/components/WithdrawTxTable/WithdrawTxTable.js index 5429ec10..b8296d17 100644 --- a/src/main/Browser/Pages/UserPanel/Sections/Content/components/Wallet/components/WithdrawTxTable/WithdrawTxTable.js +++ b/src/main/Browser/Pages/UserPanel/Sections/Content/components/Wallet/components/WithdrawTxTable/WithdrawTxTable.js @@ -11,11 +11,17 @@ import {cancelWithdrawReq} from "js-api-client/client/withdraw"; import toast from "react-hot-toast"; import {useGetWithdrawHistory} from "../../../../../../../../../../queries"; import {useParams} from "react-router-dom"; +import i18n from "i18next"; +import {useSelector} from "react-redux"; const WithdrawTxTable = ({txs}) => { const {t} = useTranslation(); + const language = i18n.language + const currencies = useSelector((state) => state.exchange.currencies) + + const [isOpen, setIsOpen] = useState(false); const [isLoading, setIsLoading] = useState(false) @@ -88,10 +94,8 @@ const WithdrawTxTable = ({txs}) => { {tr.destNetwork ?? "- - -"}
- - - {new BN(tr?.amount).toFormat()} + {new BN(tr?.amount).decimalPlaces(currencies[tr.currency].precision).toFormat()} @@ -107,7 +111,7 @@ const WithdrawTxTable = ({txs}) => {
{t("history.fee")} - {new BN(tr?.appliedFee).toFormat()} + {new BN(tr?.appliedFee).decimalPlaces(currencies[tr.currency].precision).toFormat()}
diff --git a/src/main/Browser/Pages/UserPanel/Sections/Header/components/MarketHeader/MarketHeader.js b/src/main/Browser/Pages/UserPanel/Sections/Header/components/MarketHeader/MarketHeader.js index 79443266..81b7c3bd 100644 --- a/src/main/Browser/Pages/UserPanel/Sections/Header/components/MarketHeader/MarketHeader.js +++ b/src/main/Browser/Pages/UserPanel/Sections/Header/components/MarketHeader/MarketHeader.js @@ -2,11 +2,12 @@ import React, {useEffect, useState} from "react"; import classes from "./MarketHeader.module.css"; import {useTranslation} from "react-i18next"; import {useSelector} from "react-redux"; -import {BN} from "../../../../../../../../utils/utils"; +import {BN, getCurrencyNameOrAlias} from "../../../../../../../../utils/utils"; import Icon from "../../../../../../../../components/Icon/Icon"; import Popup from "../../../../../../../../components/Popup/Popup"; import {useGetUserAccount} from "../../../../../../../../queries/hooks/useGetUserAccount"; import {useGetLastPrices} from "../../../../../../../../queries/hooks/useGetLastPrices"; +import i18n from "i18next"; const MarketHeader = () => { @@ -19,6 +20,9 @@ const MarketHeader = () => { const base = userAccount?.wallets[activePair.baseAsset]?.free || 0 const quote = userAccount?.wallets[activePair.quoteAsset]?.free || 0 + const language = i18n.language + const currencies = useSelector((state) => state.exchange.currencies) + const [showPopUp, setShowPopUp] = useState(false); const [showPopUpAsset, setShowPopUpAsset] = useState(null); @@ -42,8 +46,8 @@ const MarketHeader = () => { return ( <>
-

{t("currency." + activePair.baseAsset)}/{t("currency." + activePair.quoteAsset)}

-

{t("header.lastPrice")}:{" "}{" "}{new BN(lastPrices[activePair.symbol] || 0).toFormat()+" "+t("currency." + activePair.quoteAsset)}

+

{getCurrencyNameOrAlias(currencies[activePair?.baseAsset], language)}/{getCurrencyNameOrAlias(currencies[activePair?.quoteAsset], language)}

+

{t("header.lastPrice")}:{" "}{" "}{new BN(lastPrices[activePair.symbol] || 0).decimalPlaces(currencies[activePair?.quoteAsset]?.precision ?? 0).toFormat() +" "+ getCurrencyNameOrAlias(currencies[activePair?.quoteAsset], language)}

{t("header.availableBalance")}

@@ -51,12 +55,12 @@ const MarketHeader = () => {
ClickHandler(activePair.baseAsset)}/> {/*{ new BN (base).decimalPlaces(activePair.baseAssetPrecision).toFormat()}*/} - { new BN (base).toFormat()} - {t("currency." + activePair.baseAsset)} + { new BN (base).decimalPlaces(currencies[activePair?.baseAsset]?.precision ?? 0).toFormat()} + {getCurrencyNameOrAlias(currencies[activePair?.baseAsset], language)}
- { new BN(quote).toFormat()} - {t("currency." + activePair.quoteAsset)} + { new BN(quote).decimalPlaces(currencies[activePair?.quoteAsset]?.precision ?? 0).toFormat()} + {getCurrencyNameOrAlias(currencies[activePair?.quoteAsset], language)} ClickHandler(activePair.quoteAsset)}/>
diff --git a/src/main/Browser/Pages/UserPanel/Sections/Header/components/WalletHeader/WalletHeader.js b/src/main/Browser/Pages/UserPanel/Sections/Header/components/WalletHeader/WalletHeader.js index 23f75804..8a0cd742 100644 --- a/src/main/Browser/Pages/UserPanel/Sections/Header/components/WalletHeader/WalletHeader.js +++ b/src/main/Browser/Pages/UserPanel/Sections/Header/components/WalletHeader/WalletHeader.js @@ -2,10 +2,11 @@ import React from "react"; import classes from "./WalletHeader.module.css"; import {useTranslation} from "react-i18next"; import {useParams} from "react-router-dom"; -import {BN} from "../../../../../../../../utils/utils"; +import {BN, getCurrencyNameOrAlias} from "../../../../../../../../utils/utils"; import {useGetUserAccount} from "../../../../../../../../queries/hooks/useGetUserAccount"; import {useGetUserAssets} from "../../../../../../../../queries"; import {useSelector} from "react-redux"; +import i18n from "i18next"; const WalletHeader = () => { const {id} = useParams() @@ -17,28 +18,34 @@ const WalletHeader = () => { const {data: estimateValue , isLoading, error} = useGetUserAssets(refCurrency) const allEstimateValue = (isLoading || error) ? 0 : (estimateValue?.find( q => q.asset === id )) + const language = i18n.language + const currencies = useSelector((state) => state.exchange.currencies) + return ( <>
-

{t("currency." + id)}

+

{getCurrencyNameOrAlias(currencies[id], language)}

{id}
{t("header.free")} - {new BN(userAccount?.wallets[id]?.free || 0).toFormat()} - ( {refCurrency === id ? new BN(userAccount?.wallets[id]?.free || 0).toFormat() : new BN(allEstimateValue?.free || 0).toFormat()} {t("currency."+refCurrency)} ) + + {new BN(userAccount?.wallets[id]?.free || 0).decimalPlaces(currencies[id]?.precision ?? 0).toFormat()} + ({ refCurrency === id ? new BN(userAccount?.wallets[id]?.free || 0).decimalPlaces(currencies[id]?.precision ?? 0).toFormat() : new BN(allEstimateValue?.free || 0).decimalPlaces(currencies[refCurrency]?.precision ?? 0).toFormat()} {refCurrency} )
{t("header.locked")} - {new BN(userAccount?.wallets[id]?.locked || 0).toFormat()} - ( {refCurrency === id ? new BN(userAccount?.wallets[id]?.locked || 0).toFormat() : new BN(allEstimateValue?.locked || 0).toFormat()} {t("currency."+refCurrency)} ) + + {new BN(userAccount?.wallets[id]?.locked || 0).decimalPlaces(currencies[id]?.precision ?? 0).toFormat()} + ({ refCurrency === id ? new BN(userAccount?.wallets[id]?.locked || 0).decimalPlaces(currencies[id]?.precision ?? 0).toFormat() : new BN(allEstimateValue?.locked || 0).decimalPlaces(currencies[refCurrency]?.precision ?? 0).toFormat()} {refCurrency} )
{t("header.inWithdrawalProcess")} - {new BN(userAccount?.wallets[id]?.withdraw || 0).toFormat()} - ( {refCurrency === id ? new BN(userAccount?.wallets[id]?.withdraw || 0).toFormat() : new BN(allEstimateValue?.withdrawing || 0).toFormat()} {t("currency."+refCurrency)} ) + + {new BN(userAccount?.wallets[id]?.withdraw || 0).decimalPlaces(currencies[id]?.precision ?? 0).toFormat()} + ({ refCurrency === id ? new BN(userAccount?.wallets[id]?.withdraw || 0).decimalPlaces(currencies[id]?.precision ?? 0).toFormat() : new BN(allEstimateValue?.withdrawing || 0).decimalPlaces(currencies[refCurrency]?.precision ?? 0).toFormat()} {refCurrency} )
diff --git a/src/main/Browser/Pages/UserPanel/Sections/SubMenu/components/MarketSubMenu/MarketSubMenu.js b/src/main/Browser/Pages/UserPanel/Sections/SubMenu/components/MarketSubMenu/MarketSubMenu.js index f7aa2128..c30f6e10 100644 --- a/src/main/Browser/Pages/UserPanel/Sections/SubMenu/components/MarketSubMenu/MarketSubMenu.js +++ b/src/main/Browser/Pages/UserPanel/Sections/SubMenu/components/MarketSubMenu/MarketSubMenu.js @@ -12,6 +12,9 @@ const MarketSubMenu = () => { const {t} = useTranslation(); const [activeTab] = useState(JSON.parse(localStorage.getItem("activeMarketTab")) || 1); const symbols = useSelector((state) => state.exchange.symbols) + + const pairsList = useSelector((state) => state.exchange.pairsList) + const fav = useSelector((state) => state.auth.favoritePairs) const dispatch = useDispatch(); @@ -31,10 +34,11 @@ const MarketSubMenu = () => { fav.includes(p.symbol))} + pairs={Object.values(pairsList).filter(pair => fav.includes(pair.symbol))} favPair={fav} addFav={(selected) => addToFav(selected)} /> + ), }, { @@ -43,7 +47,7 @@ const MarketSubMenu = () => { addToFav(selected)} /> @@ -57,7 +61,7 @@ const MarketSubMenu = () => { id="2" type="BTC" favPair={fav} - pairs={symbols.filter(p => (p.baseAsset === "BTC" || p.quoteAsset === "BTC"))} + pairs={Object.values(pairsList).filter(pair => pair.baseAsset === "BTC" || pair.quoteAsset === "BTC")} addFav={(selected) => addToFav(selected)} /> ), @@ -70,7 +74,7 @@ const MarketSubMenu = () => { id="3" type="USDT" favPair={fav} - pairs={symbols.filter(p => (p.baseAsset === "USDT" || p.quoteAsset === "USDT"))} + pairs={Object.values(pairsList).filter(pair => pair.baseAsset === "USDT" || pair.quoteAsset === "USDT")} addFav={(selected) => addToFav(selected)} /> ), diff --git a/src/main/Browser/Pages/UserPanel/Sections/SubMenu/components/MarketSubMenu/components/MarketCard/MarketCard.js b/src/main/Browser/Pages/UserPanel/Sections/SubMenu/components/MarketSubMenu/components/MarketCard/MarketCard.js index 8db19022..a26f4941 100644 --- a/src/main/Browser/Pages/UserPanel/Sections/SubMenu/components/MarketSubMenu/components/MarketCard/MarketCard.js +++ b/src/main/Browser/Pages/UserPanel/Sections/SubMenu/components/MarketSubMenu/components/MarketCard/MarketCard.js @@ -7,7 +7,13 @@ const MarketCard = ({type, ...props}) => { return (
- {props.pairs.map((pair) => )} + + { + Object.keys(props?.pairs) + + .map((pair) => ) + } +
); diff --git a/src/main/Browser/Pages/UserPanel/Sections/SubMenu/components/MarketSubMenu/components/MarketPairCard/MarketCard.module.css b/src/main/Browser/Pages/UserPanel/Sections/SubMenu/components/MarketSubMenu/components/MarketPairCard/MarketCard.module.css index cf953119..7783ea07 100644 --- a/src/main/Browser/Pages/UserPanel/Sections/SubMenu/components/MarketSubMenu/components/MarketPairCard/MarketCard.module.css +++ b/src/main/Browser/Pages/UserPanel/Sections/SubMenu/components/MarketSubMenu/components/MarketPairCard/MarketCard.module.css @@ -6,7 +6,7 @@ width: 14%; } .marketCardContent { - width: 86%; + width: 84%; } .selected { background-color: var(--mainContent); diff --git a/src/main/Browser/Pages/UserPanel/Sections/SubMenu/components/MarketSubMenu/components/MarketPairCard/MarketPairCard.js b/src/main/Browser/Pages/UserPanel/Sections/SubMenu/components/MarketSubMenu/components/MarketPairCard/MarketPairCard.js index 53881382..4fd9fe49 100644 --- a/src/main/Browser/Pages/UserPanel/Sections/SubMenu/components/MarketSubMenu/components/MarketPairCard/MarketPairCard.js +++ b/src/main/Browser/Pages/UserPanel/Sections/SubMenu/components/MarketSubMenu/components/MarketPairCard/MarketPairCard.js @@ -3,42 +3,48 @@ import classes from "./MarketCard.module.css"; import {useDispatch, useSelector} from "react-redux"; import {images} from "../../../../../../../../../../assets/images"; import Icon from "../../../../../../../../../../components/Icon/Icon"; -import {BN} from "../../../../../../../../../../utils/utils"; +import {BN, getCurrencyNameOrAlias} from "../../../../../../../../../../utils/utils"; import {setActivePairInitiate} from "../../../../../../../../../../store/actions"; import {useGetLastPrices} from "../../../../../../../../../../queries/hooks/useGetLastPrices"; +import i18n from "i18next"; const MarketPairCard = ({id, pair, favPair, addFav}) => { const activePair = useSelector((state) => state.exchange.activePair.symbol) const {data: prices} = useGetLastPrices() + + const language = i18n.language + const currencies = useSelector((state) => state.exchange.currencies) + const dispatch = useDispatch(); - const changeActivePair = () =>{ + /*const changeActivePair = () =>{ if (activePair !== pair.symbol) dispatch(setActivePairInitiate(pair, id)) - } + }*/ + + const changeActivePair = () => { + const pairSymbolFormatted = `${pair.baseAsset}_${pair.quoteAsset}`; + if (activePair !== pairSymbolFormatted) { + dispatch(setActivePairInitiate(`${pair.baseAsset}_${pair.quoteAsset}`, id)); + } + }; + return (
+ className={`width-100 row jc-between ai-center px-1 py-05 cursor-pointer double-striped border-bottom ${classes.container} ${activePair === pair.symbol ? classes.selected : ""} `}>
{pair.symbol}
-
-
{ - e.stopPropagation(); - addFav(pair.symbol); - }} - data-name={pair.symbol}> - -
- {pair.baseAsset + " / " + pair.quoteAsset} +
+ {e.stopPropagation();addFav(pair?.symbol);}}/> + {pair?.baseAsset + " / " + pair?.quoteAsset }
-
- {new BN(prices[pair.symbol] || 0).toFormat()} +
+ {new BN(prices[pair?.symbol] || 0).decimalPlaces(currencies[pair?.quoteAsset]?.precision ?? 0).toFormat()}
diff --git a/src/main/Browser/Pages/UserPanel/Sections/SubMenu/components/WalletSubMenu/WalletSubMenu.js b/src/main/Browser/Pages/UserPanel/Sections/SubMenu/components/WalletSubMenu/WalletSubMenu.js index 918710ed..ec68212d 100644 --- a/src/main/Browser/Pages/UserPanel/Sections/SubMenu/components/WalletSubMenu/WalletSubMenu.js +++ b/src/main/Browser/Pages/UserPanel/Sections/SubMenu/components/WalletSubMenu/WalletSubMenu.js @@ -8,15 +8,35 @@ import WalletBalance from "./components/WalletBalance/WalletBalance"; import ScrollBar from "../../../../../../../../components/ScrollBar"; import {useGetUserAccount} from "../../../../../../../../queries/hooks/useGetUserAccount"; import Loading from "../../../../../../../../components/Loading/Loading"; +import i18n from "i18next"; const WalletSubMenu = () => { const {t} = useTranslation(); const [showZero, setShowZero] = useState(false); const assets = useSelector((state) => state.exchange.assets) - console.log("assets", assets) + const language = i18n.language + const currencies = useSelector((state) => state.exchange.currencies) + const {data: data, isLoading} = useGetUserAccount() - console.log("data", data) + + + const wallets = Object.keys(currencies) + .map(symbol => ({ + symbol, + name: currencies[symbol].name, + alias: currencies[symbol].alias, + icon: currencies[symbol].icon, + order: currencies[symbol].order, + isActive: currencies[symbol].isActive, + free: data?.wallets?.[symbol]?.free || 0, + })) + .filter(wallet => wallet.isActive || wallet.free > 0); + + wallets.sort((a, b) => { + if (b.free !== a.free) return b.free - a.free; + return a.order - b.order; + }); return (
@@ -35,9 +55,23 @@ const WalletSubMenu = () => {
- {assets?.filter(asset => data?.wallets?.[asset]?.free > 0) + + { + wallets.map((wallet) => ( + + )) + } + + {/*{assets?.filter(asset => data?.wallets?.[asset]?.free > 0) .concat(assets.filter(asset => data?.wallets?.[asset]?.free === 0)) - .map((name) => )} + .map((name) => )}*/}
diff --git a/src/main/Browser/Pages/UserPanel/Sections/SubMenu/components/WalletSubMenu/WalletSubMenu.module.css b/src/main/Browser/Pages/UserPanel/Sections/SubMenu/components/WalletSubMenu/WalletSubMenu.module.css index 0b0b25fe..845a3031 100644 --- a/src/main/Browser/Pages/UserPanel/Sections/SubMenu/components/WalletSubMenu/WalletSubMenu.module.css +++ b/src/main/Browser/Pages/UserPanel/Sections/SubMenu/components/WalletSubMenu/WalletSubMenu.module.css @@ -106,3 +106,9 @@ .selected:last-child:before{ width: 0; } + +.iconDisabled { + filter: grayscale(0.75); + opacity: 0.9;/* + background-color: var(--lightGray)*/ +} \ No newline at end of file diff --git a/src/main/Browser/Pages/UserPanel/Sections/SubMenu/components/WalletSubMenu/components/WalletBalance/WalletBalance.js b/src/main/Browser/Pages/UserPanel/Sections/SubMenu/components/WalletSubMenu/components/WalletBalance/WalletBalance.js index abfaa719..78f59625 100644 --- a/src/main/Browser/Pages/UserPanel/Sections/SubMenu/components/WalletSubMenu/components/WalletBalance/WalletBalance.js +++ b/src/main/Browser/Pages/UserPanel/Sections/SubMenu/components/WalletSubMenu/components/WalletBalance/WalletBalance.js @@ -2,9 +2,10 @@ import React from 'react'; import classes from '../../WalletSubMenu.module.css' import {useTranslation} from "react-i18next"; import {images} from "../../../../../../../../../../assets/images"; -import {BN} from "../../../../../../../../../../utils/utils"; +import {BN, getCurrencyNameOrAlias} from "../../../../../../../../../../utils/utils"; import {useGetUserAssetsEstimatedValue} from "../../../../../../../../../../queries"; import {useSelector} from "react-redux"; +import i18n from "i18next"; const WalletBalance = () => { @@ -13,6 +14,10 @@ const WalletBalance = () => { const {data , isLoading, error} = useGetUserAssetsEstimatedValue(refCurrency) const totalValue = (isLoading || error) ? 0 : data.value + const language = i18n.language + const currencies = useSelector((state) => state.exchange.currencies) + + return (
{ {t("WalletSubMenu.approximate")}
- {new BN(totalValue).toFormat()}{" "}{t("currency."+refCurrency)} + {new BN(totalValue).decimalPlaces(currencies[refCurrency]?.precision ?? 0).toFormat()}{" "}{getCurrencyNameOrAlias(currencies[refCurrency], language)}
diff --git a/src/main/Browser/Pages/UserPanel/Sections/SubMenu/components/WalletSubMenu/components/WalletListItem/WalletListItem.js b/src/main/Browser/Pages/UserPanel/Sections/SubMenu/components/WalletSubMenu/components/WalletListItem/WalletListItem.js index 2a871ce3..039f7294 100644 --- a/src/main/Browser/Pages/UserPanel/Sections/SubMenu/components/WalletSubMenu/components/WalletListItem/WalletListItem.js +++ b/src/main/Browser/Pages/UserPanel/Sections/SubMenu/components/WalletSubMenu/components/WalletListItem/WalletListItem.js @@ -4,45 +4,52 @@ import {NavLink} from "react-router-dom"; import {useTranslation} from "react-i18next"; import {images} from "../../../../../../../../../../assets/images"; import * as Routes from "../../../../../../../../Routes/routes"; -import {BN} from "../../../../../../../../../../utils/utils"; +import {BN, getCurrencyNameOrAlias} from "../../../../../../../../../../utils/utils"; import {useGetUserAccount} from "../../../../../../../../../../queries/hooks/useGetUserAccount"; import {useGetUserAssets} from "../../../../../../../../../../queries"; import {useSelector} from "react-redux"; +import i18n from "i18next"; + +const WalletListItem = ({symbol, data, assetName, freeWallet, showZero}) => { -const WalletListItem = ({assetName, showZero}) => { const {t} = useTranslation(); + const language = i18n.language + const currencies = useSelector((state) => state.exchange.currencies) + const refCurrency = useSelector((state) => state.exchange.baseCurrency) const {data: userAccount} = useGetUserAccount() const free = userAccount?.wallets[assetName]?.free || 0 const {data: estimateValue , isLoading, error} = useGetUserAssets(refCurrency) - const freeEstimateValue = (isLoading || error) ? 0 : (estimateValue?.find( q => q.asset === assetName )?.free || 0) + const freeEstimateValue = (isLoading || error) ? 0 : (estimateValue?.find( q => q.asset === symbol )?.free || 0) + + const active = currencies[symbol]?.isActive if (showZero && free === 0) return <> return ( - isActive ? "width-100 row ai-center cursor-pointer position-relative px-1 py-105 " + classes.selected : "width-100 row ai-center cursor-pointer position-relative px-1 py-105" + isActive ? `width-100 row ai-center cursor-pointer position-relative px-1 py-105 ${!active && 'text-gray'} ${classes.selected}` : `width-100 row ai-center cursor-pointer position-relative px-1 py-105 ${!active && 'text-gray'}` } - to={Routes.Wallet + "/" + assetName}> + to={Routes.Wallet + "/" + symbol}>
{assetName}
- {assetName} - {t("currency." + assetName)} + {symbol} + {getCurrencyNameOrAlias(currencies[symbol], language)}
- {new BN(free).toFormat() + " "} {t("currency." + assetName)} + {new BN(freeWallet).decimalPlaces(currencies[symbol]?.precision ?? 0).toFormat() + " "} {getCurrencyNameOrAlias(currencies[symbol], language)} - ~ {refCurrency === assetName ? new BN(free).toFormat() : new BN(freeEstimateValue).toFormat()} {t("currency."+refCurrency)} + ~ {refCurrency === assetName ? new BN(free).decimalPlaces(currencies[refCurrency]?.precision ?? 0).toFormat() : new BN(freeEstimateValue).decimalPlaces(currencies[refCurrency]?.precision ?? 0).toFormat()} {t("currency."+refCurrency)}
diff --git a/src/queries/hooks/useGetGatewaysByCurrency.js b/src/queries/hooks/useGetGatewaysByCurrency.js new file mode 100644 index 00000000..ad3fad88 --- /dev/null +++ b/src/queries/hooks/useGetGatewaysByCurrency.js @@ -0,0 +1,13 @@ +import {useQuery} from "@tanstack/react-query"; +import {getGatewaysByCurrency} from "js-api-client"; + +export const useGetGatewaysByCurrency = (currency = "", config = {}) => { + return useQuery({ + queryKey: ['gateways', currency, config], + queryFn: async () => { + const { data } = await getGatewaysByCurrency(currency, config); + return data?.gateways; + }, + enabled: !!currency, + }); +}; diff --git a/src/queries/index.js b/src/queries/index.js index b4d09d5b..1ae9b4db 100644 --- a/src/queries/index.js +++ b/src/queries/index.js @@ -25,4 +25,5 @@ export {useGetUserAssetsEstimatedValue} from "./hooks/useGetUserAssetsEstimatedV export {useGetBuyAndSellHistory} from "./hooks/useGetBuyAndSellHistory"; export {useGetWithdrawHistory} from "./hooks/useGetWithdrawHistory"; export {useGetDepositHistory} from "./hooks/useGetDepositHistory"; -export {useGetTransactionsHistory} from "./hooks/useGetTransactionsHistory"; \ No newline at end of file +export {useGetTransactionsHistory} from "./hooks/useGetTransactionsHistory"; +export {useGetGatewaysByCurrency} from "./hooks/useGetGatewaysByCurrency"; \ No newline at end of file diff --git a/src/setup/configs/configs.js b/src/setup/configs/configs.js index 2feded4f..8fcf72ac 100644 --- a/src/setup/configs/configs.js +++ b/src/setup/configs/configs.js @@ -8,6 +8,6 @@ export const defaultConfigs = { ], "defaultTheme": "DARK", "supportEmail": "supportEmail@gmail.com", - "baseCurrency": "TUSDT", + "baseCurrency": "USDT", "dateType": "Hijri" } \ No newline at end of file diff --git a/src/store/actions/actionTypes.js b/src/store/actions/actionTypes.js index 1c897a99..699da1ab 100644 --- a/src/store/actions/actionTypes.js +++ b/src/store/actions/actionTypes.js @@ -53,4 +53,9 @@ export const SET_USER_CONFIG = "SET_USER_CONFIG" export const SET_FAV_PAIR = "SET_FAV_PAIR" export const SET_FAV_PAIR_INITIATE = "SET_FAV_PAIR_INITIATE" -export const GET_USER_CONFIGS_INITIATE = "GET_USER_CONFIGS_INITIATE" \ No newline at end of file +export const GET_USER_CONFIGS_INITIATE = "GET_USER_CONFIGS_INITIATE" + + +export const GET_CURRENCIES = "GET_CURRENCIES"; +export const GET_PAIRS = "GET_PAIRS"; +export const GET_FEES = "GET_FEES"; \ No newline at end of file diff --git a/src/store/actions/exchange.js b/src/store/actions/exchange.js index 79c0d27a..2261c7af 100644 --- a/src/store/actions/exchange.js +++ b/src/store/actions/exchange.js @@ -1,4 +1,5 @@ import * as actionTypes from "./actionTypes"; +import {GET_FEES} from "./actionTypes"; export const setActivePairInitiate = (pair, activeTab) => { return { @@ -97,4 +98,23 @@ export const setExchangeConfigs = configs => { type: actionTypes.SET_EXCHANGE_CONFIG, configs: configs }; +}; + +export const getCurrencies = currencies => { + return { + type: actionTypes.GET_CURRENCIES, + currencies, + }; +}; +export const getPairs = pairs => { + return { + type: actionTypes.GET_PAIRS, + pairs, + }; +}; +export const getFees = fees => { + return { + type: actionTypes.GET_FEES, + fees, + }; }; \ No newline at end of file diff --git a/src/store/actions/index.js b/src/store/actions/index.js index 0acfe700..36947b0a 100644 --- a/src/store/actions/index.js +++ b/src/store/actions/index.js @@ -22,8 +22,10 @@ export { setIPGInitiate, setVerifyEmailLock, setVerifyEmailLockInitiate, - setExchangeConfigs - + setExchangeConfigs, + getCurrencies, + getPairs, + getFees } from "./exchange"; export { diff --git a/src/store/reducers/exchangeReducer.js b/src/store/reducers/exchangeReducer.js index a34e2f46..087fc3cd 100644 --- a/src/store/reducers/exchangeReducer.js +++ b/src/store/reducers/exchangeReducer.js @@ -4,7 +4,7 @@ const initialState = { assets: [], pairs: [], symbols: [], - activePair: {}, + activePair: [], activePairOrders: { bestBuyPrice: 0, bestSellPrice: 0, @@ -27,9 +27,14 @@ const initialState = { defaultTheme: "", supportEmail: "", baseCurrency: "", - dateType: "" + dateType: "", + currencies: [], + pairsList: [], + fees: [], }; + + const exchangeReducer = (state = initialState, action) => { switch (action.type) { case actionTypes.SET_IPG: @@ -42,13 +47,32 @@ const exchangeReducer = (state = initialState, action) => { ...state, verifyEmailLock: action.verifyEmailLockTime, }; - case actionTypes.SET_ACTIVE_PAIR: + /*case actionTypes.SET_ACTIVE_PAIR: return { ...state, activePair: { ...state.activePair, ...action.pair, - name: action.pair.baseAsset + "/" + action.pair.quoteAsset + // name: action.pair.baseAsset + "/" + action.pair.quoteAsset + }, + activePairOrders: { + ...state.activePairOrders, + bestBuyPrice: 0, + bestSellPrice: 0, + lastTradePrice: 0, + }, + };*/ + + + case actionTypes.SET_ACTIVE_PAIR: + const [baseAsset, quoteAsset] = action.pair.split('_'); + return { + ...state, + activePair: { + symbol: `${baseAsset}${quoteAsset}`, + pair: action.pair, + baseAsset: baseAsset, + quoteAsset: quoteAsset, }, activePairOrders: { ...state.activePairOrders, @@ -57,6 +81,7 @@ const exchangeReducer = (state = initialState, action) => { lastTradePrice: 0, }, }; + case actionTypes.SET_BEST_BUY_PRICE: return { ...state, @@ -105,6 +130,23 @@ const exchangeReducer = (state = initialState, action) => { ...state, ...action.configs }; + + case actionTypes.GET_CURRENCIES: + return { + ...state, + currencies: action.currencies, + }; + case actionTypes.GET_PAIRS: + return { + ...state, + pairsList: action.pairs, + }; + case actionTypes.GET_FEES: + return { + ...state, + fees: action.fees, + }; + default: return state; } diff --git a/src/store/sagas/global.js b/src/store/sagas/global.js index 3bf4294c..d5de38aa 100644 --- a/src/store/sagas/global.js +++ b/src/store/sagas/global.js @@ -21,7 +21,7 @@ export function* setThemeSaga(action) { } export function* setActivePair(action) { - yield call([localStorage, 'setItem'], "activePair", action.pair.symbol) + yield call([localStorage, 'setItem'], "activePair", action.pair) yield call([localStorage, 'setItem'], "activeMarketTab", action.activeTab) yield put(actions.setActivePair(action.pair)); } @@ -53,8 +53,9 @@ function* getExchangeInfo() { for (let i = 0; i < 10; i++) { try { - const {data: {symbols}} = yield call(axios.get, '/api/v3/exchangeInfo') - return symbols + const {data} = yield call(axios.get, '/api/v3/exchangeInfo') + + return data } catch (err) { if (i < 2) { yield delay(1000) @@ -65,6 +66,70 @@ function* getExchangeInfo() { throw new Error('getExchangeInfo failed!') } } +/*function* fetchCurrencies() { + for (let i = 0; i < 10; i++) { + try { + const response = yield call(axios.get, '/wallet/currency'); + const { currencies } = response.data; + return currencies; + } catch (err) { + if (i < 9) { + yield delay(1000); + } else { + throw new Error('Failed to fetch currencies after 10 attempts.'); + } + } + } +}*/ + +/*function* fetchCurrencies() { + const formData = new URLSearchParams(); + formData.append('includeManualGateways', 'true'); + formData.append('includeOffChainGateways', 'true'); + formData.append('includeOnChainGateways', 'true'); + + for (let i = 0; i < 10; i++) { + try { + const response = yield call(axios.post, '/wallet/currency', formData, { + headers: { + 'Content-Type': 'application/x-www-form-urlencoded' + } + }); + + const { currencies } = response.data; + return currencies; + } catch (err) { + if (i < 9) { + yield delay(1000); + } else { + throw new Error('Failed to fetch currencies after 10 attempts.'); + } + } + } +}*/ + +function* fetchCurrencies() { + const params = { + includeManualGateways: false, + includeOffChainGateways: true, + includeOnChainGateways: true + }; + + for (let i = 0; i < 10; i++) { + try { + const response = yield call(axios.get, '/wallet/currency', { params }); + + const { currencies } = response.data; + return currencies; + } catch (err) { + if (i < 9) { + yield delay(1000); + } else { + throw new Error('Failed to fetch currencies after 10 attempts.'); + } + } + } +} export function* loadConfig(action) { @@ -100,10 +165,66 @@ export function* loadConfig(action) { try { + const exchangeInfo = yield call(getExchangeInfo); + + const currencies = yield call(fetchCurrencies); + + + /*const currenciesMap = currencies.reduce((acc, currency) => { + acc[currency.symbol] = currency; + return acc; + }, {});*/ + + const currenciesMap = currencies.reduce((acc, currency) => { + const precisionValue = currency.precision.toString(); + const decimalPlaces = precisionValue.includes('.') + ? precisionValue.split('.')[1].length + : 0; + + const decimalFactor = Number((Math.pow(10, -decimalPlaces)).toFixed(decimalPlaces)); + + acc[currency.symbol] = { + ...currency, + precision: decimalPlaces, + minOrder: decimalFactor, + step: decimalFactor, + }; + return acc; + }, {}); + + yield put(actions.getCurrencies(currenciesMap)); + + const pairsList = exchangeInfo.symbols; + const pairsListMap = pairsList.reduce((acc, pair) => { + /*acc[pair.symbol] = pair;*/ + const key = `${pair.baseAsset}_${pair.quoteAsset}`; + acc[key] = { + symbol: pair.symbol, + baseAsset: pair.baseAsset, + quoteAsset: pair.quoteAsset, + orderTypes: pair.orderTypes, + }; + return acc; + }, {}); + yield put(actions.getPairs(pairsListMap)); + + const fees = exchangeInfo.fees; + const feesMap = fees.reduce((acc, fee) => { + acc[fee.pair] = fee; + /* acc[pair.symbol] = { + symbol: pair.symbol, + baseAsset: pair.baseAsset, + quoteAsset: pair.quoteAsset, + orderTypes: pair.orderTypes, + };*/ + return acc; + }, {}); + yield put(actions.getFees(feesMap)); + const localTheme = yield call([localStorage, 'getItem'], 'theme') if (localTheme) appTheme = localTheme; - const symbols = yield call(getExchangeInfo) + const symbols = exchangeInfo.symbols for (const symbol of symbols) { if (symbol.symbol.toUpperCase().includes("NLN")) continue if (!assets.includes(symbol.baseAsset)) { @@ -125,11 +246,21 @@ export function* loadConfig(action) { lastPrice[symbol.symbol] = 0 } yield put(actions.setExchange({pairs, assets, symbols, lastPrice})); + /*yield put(actions.getCurrencies({currencies}));*/ yield put(actions.setUserAccountInfo({wallets, tradeFee})); const activePair = yield call([localStorage, 'getItem'], 'activePair') - const lastActivePair = symbols.find(symbol => symbol.symbol === activePair) - yield put(actions.setActivePair(lastActivePair || symbols[0])); + const lastActivePair = Object.keys(pairsListMap).includes(activePair) ? activePair : null; + + /*const lastActivePair = lastActivePairKey ? pairsListMap[lastActivePairKey] : null;*/ + + + + /*const lastActivePair = symbols.find(symbol => symbol.symbol === activePair)*/ + + + + yield put(actions.setActivePair(lastActivePair || Object.keys(pairsListMap)[0])); } catch (e) { yield put(actions.setError(true)) diff --git a/src/utils/utils.js b/src/utils/utils.js index 07535afa..7888f187 100644 --- a/src/utils/utils.js +++ b/src/utils/utils.js @@ -32,6 +32,10 @@ export const encodeQueryData = (params) => { } export const BN = BigNumber.clone({ + + DECIMAL_PLACES: 8, + ROUNDING_MODE: BigNumber.ROUND_DOWN, + FORMAT: { groupSize: 3, groupSeparator: ',', @@ -72,4 +76,19 @@ export const timeValidator = str => { return /^(2[0-3]|[01]?[0-9]):([0-5]?[0-9])$/.test(str); } -export const toAbsoluteUrl = (path) => process.env.PUBLIC_URL + path \ No newline at end of file +export const toAbsoluteUrl = (path) => process.env.PUBLIC_URL + path + +export function getCurrencyNameOrAlias(currency, lang) { + + const languagesConfig = { fa: "alias", en: "name", ar: "alias" }; + const langOption = languagesConfig[lang] || 'name'; + + if (!currency || typeof currency !== 'object') { + return '-'; + } + + const name = currency.name || '-'; + const alias = currency.alias || '-'; + + return langOption === 'alias' ? alias : name; +} diff --git a/yarn.lock b/yarn.lock index 245ad7d2..d4504862 100644 --- a/yarn.lock +++ b/yarn.lock @@ -9486,8 +9486,8 @@ __metadata: "js-api-client@https://github.com/opexdev/js-api-client.git#develop": version: 1.0.0-beta2 - resolution: "js-api-client@https://github.com/opexdev/js-api-client.git#commit=c352c8f2dc8f7d225090061d519ae579278ae960" - checksum: 61b0c4519dfd1dd0092d417d6cc28e7b97c0c425da37506c2a7c35d94db72e57bf1956787614cbc7059111f8438675a3b3745e50e5dd0b68b027ff8032d07069 + resolution: "js-api-client@https://github.com/opexdev/js-api-client.git#commit=e3bb06671718e426e03d618c6a742e079c6a1449" + checksum: 6dd6286f1df7fa812ed56d5fe20f16dadc057cfda979d349379e90a2b76e189cfcda6aba48bdc974f7722bdb7f24233c4a631c89038d7b8192d7e90e3e3fc351 languageName: node linkType: hard