diff --git a/.env.local b/.env.local index 9926d7b0c..ae8178ec0 100644 --- a/.env.local +++ b/.env.local @@ -9,6 +9,9 @@ REACT_APP_TEST_FIRST_BLOCK=0 REACT_APP_PORTIS_ID=469a25c8-1101-4c57-823d-c47cb328f788 +REACT_APP_WHITELIST=false +REACT_APP_WHITELIST_TOKEN= + REACT_APP_YBUG_ID= REACT_APP_MAIL_SRV=https://mailservice.sovryn.app/ diff --git a/.env.mainnet.local b/.env.mainnet.local index f4a51235e..f232587a2 100644 --- a/.env.mainnet.local +++ b/.env.mainnet.local @@ -6,6 +6,9 @@ REACT_APP_SENTRY_DSN= REACT_APP_PORTIS_ID=469a25c8-1101-4c57-823d-c47cb328f788 +REACT_APP_WHITELIST=false +REACT_APP_WHITELIST_TOKEN=0x576aE218aeCfD4CbD2DBe07250b47e26060932B1 + REACT_APP_YBUG_ID= REACT_APP_MAIL_SRV=https://mailservice.sovryn.app/ diff --git a/.env.production b/.env.production index 18e5d3e65..5e2b99127 100644 --- a/.env.production +++ b/.env.production @@ -5,6 +5,9 @@ REACT_APP_SENTRY_DSN=https://2981633dd7f04f0d9fb3facf8c1332b8@o459269.ingest.sen REACT_APP_PORTIS_ID=469a25c8-1101-4c57-823d-c47cb328f788 +REACT_APP_WHITELIST=true +REACT_APP_WHITELIST_TOKEN=0x576aE218aeCfD4CbD2DBe07250b47e26060932B1 + REACT_APP_YBUG_ID=3f1jrxvzrhkn1b975t8b REACT_APP_MAIL_SRV=https://mailservice.sovryn.app/ diff --git a/.env.testnet b/.env.testnet index 4017adb13..cb3469911 100644 --- a/.env.testnet +++ b/.env.testnet @@ -7,3 +7,6 @@ REACT_APP_PORTIS_ID=469a25c8-1101-4c57-823d-c47cb328f788 REACT_APP_YBUG_ID=3f1jrxvzrhkn1b975t8b REACT_APP_MAIL_SRV=https://mailservice.sovryn.app/ + +REACT_APP_WHITELIST=false +REACT_APP_WHITELIST_TOKEN= diff --git a/src/app/components/Header/index.tsx b/src/app/components/Header/index.tsx index 6af0bc92a..f7dc6300b 100644 --- a/src/app/components/Header/index.tsx +++ b/src/app/components/Header/index.tsx @@ -11,6 +11,7 @@ import WalletConnector from '../../containers/WalletConnector'; import styled from 'styled-components'; import { Icon, Menu, MenuItem, Popover } from '@blueprintjs/core'; import { media } from '../../../styles/media'; +import { WhitelistedNotification } from '../WhitelistedNotification/Loadable'; export function Header() { const history = useHistory(); @@ -84,6 +85,7 @@ export function Header() { + ); } diff --git a/src/app/components/LenderBalance/index.tsx b/src/app/components/LenderBalance/index.tsx deleted file mode 100644 index 7b64530f3..000000000 --- a/src/app/components/LenderBalance/index.tsx +++ /dev/null @@ -1,121 +0,0 @@ -/** - * - * LenderBalance - * - */ -import React, { useEffect, useState } from 'react'; -import { Asset } from '../../../types/asset'; -import { bignumber } from 'mathjs'; -import { useAccount } from '../../hooks/useAccount'; -import { Tooltip } from '@blueprintjs/core'; -import { weiTo18, weiTo4 } from '../../../utils/blockchain/math-helpers'; -import { useLending_profitOf } from '../../hooks/lending/useLending_profitOf'; -import { useLending_assetBalanceOf } from '../../hooks/lending/useLending_assetBalanceOf'; -import { UnLendBalance } from '../UnLendBalance/Loadable'; -import { useLending_supplyInterestRate } from '../../hooks/lending/useLending_supplyInterestRate'; - -interface Props { - asset: Asset; -} - -/** - * @deprecated - * @param props - * @constructor - */ -export function LenderBalance(props: Props) { - const owner = useAccount(); - const { value: balanceCall } = useLending_assetBalanceOf(props.asset, owner); - const { value: profitCall } = useLending_profitOf(props.asset, owner); - const { value: interestCall } = useLending_supplyInterestRate(props.asset); - const [balance, setBalance] = useState( - bignumber(balanceCall).minus(profitCall).toString(), - ); - const [profit, setProfit] = useState(profitCall); - const [ticker, setTicker] = useState('0'); - - useEffect(() => { - setBalance(bignumber(balanceCall).minus(profitCall).toString()); - }, [balanceCall, profitCall]); - - useEffect(() => { - setTicker( - bignumber(balance) - .mul( - bignumber(interestCall).div(100).div(31536000 /* seconds in year */), - ) - .div(10 ** 18) - .toFixed(0), - ); - }, [balance, interestCall]); - - useEffect(() => { - const ms = 1000; - const diff = bignumber(ticker).div(1000).div(ms); - let value = bignumber(profitCall).add(profit); - const interval = setInterval(() => { - value = value.add(diff); - setProfit(value.toFixed(0)); - }, ms); - return () => { - clearInterval(interval); - }; - // eslint-disable-next-line react-hooks/exhaustive-deps - }, [profitCall, ticker]); - - if (bignumber(balance).greaterThan(0)) { - return ( - <> -
-
-
-
- Balance Lent -
-
- - {weiTo18(balance)} {props.asset} - - } - > - <> - {weiTo4(balance)} - - {` ${props.asset}`} - - - -
-
-
-
Profit
-
- - {weiTo18(profit)} {props.asset} - - } - > - <> - {weiTo4(profit)} - - {` ${props.asset}`} - - - -
-
-
- -
- - ); - } - - return <>; -} diff --git a/src/app/components/UnLendBalance/Loadable.tsx b/src/app/components/UnLendBalance/Loadable.tsx deleted file mode 100644 index 57e5d6ae1..000000000 --- a/src/app/components/UnLendBalance/Loadable.tsx +++ /dev/null @@ -1,15 +0,0 @@ -/** - * - * Asynchronously loads the component for LendingPage - * - */ - -import { lazyLoad } from 'utils/loadable'; - -/** - * @deprecated - */ -export const UnLendBalance = lazyLoad( - () => import('./index'), - module => module.UnLendBalance, -); diff --git a/src/app/components/UnLendBalance/index.tsx b/src/app/components/UnLendBalance/index.tsx deleted file mode 100644 index 06d1f8add..000000000 --- a/src/app/components/UnLendBalance/index.tsx +++ /dev/null @@ -1,37 +0,0 @@ -/** - * - * UnLendBalance - * - */ -import React, { useState } from 'react'; -import { Asset } from '../../../types/asset'; -import { WithdrawLentAmount } from '../../containers/WithdrawLentAmount/Loadable'; - -interface Props { - asset: Asset; -} - -/** - * @deprecated - * @param props - * @constructor - */ -export function UnLendBalance(props: Props) { - const [isOpen, setOpen] = useState(false); - return ( -
- - setOpen(false)} - /> -
- ); -} diff --git a/src/app/components/WhitelistedNotification/Loadable.tsx b/src/app/components/WhitelistedNotification/Loadable.tsx new file mode 100644 index 000000000..52bab513b --- /dev/null +++ b/src/app/components/WhitelistedNotification/Loadable.tsx @@ -0,0 +1,12 @@ +/** + * + * Asynchronously loads the component for WhitelistedNotification + * + */ + +import { lazyLoad } from 'utils/loadable'; + +export const WhitelistedNotification = lazyLoad( + () => import('./index'), + module => module.WhitelistedNotification, +); diff --git a/src/app/components/WhitelistedNotification/index.tsx b/src/app/components/WhitelistedNotification/index.tsx new file mode 100644 index 000000000..9143d9eac --- /dev/null +++ b/src/app/components/WhitelistedNotification/index.tsx @@ -0,0 +1,24 @@ +import React from 'react'; +import { useIsWhitelisted } from '../../hooks/whitelist/useIsWhitelisted'; +import { Icon } from '@blueprintjs/core/lib/esm/components/icon/icon'; + +export function WhitelistedNotification() { + const isWhitelisted = useIsWhitelisted(); + + if (isWhitelisted) return <>; + + return ( +
+
+
+ +
+
+ Currently Sovryn is available for invited users only and your wallet + is not yet whitelisted. All interactions is disabled until you switch + to whitelisted wallet or get whitelisted for current one. +
+
+
+ ); +} diff --git a/src/app/containers/LendBorrowSovryn/BorrowingContainer/index.tsx b/src/app/containers/LendBorrowSovryn/BorrowingContainer/index.tsx index 7e6596f7f..783a31f38 100644 --- a/src/app/containers/LendBorrowSovryn/BorrowingContainer/index.tsx +++ b/src/app/containers/LendBorrowSovryn/BorrowingContainer/index.tsx @@ -1,6 +1,6 @@ import React, { useEffect, useState } from 'react'; +import { useDispatch } from 'react-redux'; import { useAssetBalanceOf } from '../../../hooks/useAssetBalanceOf'; -import { useIsConnected } from '../../../hooks/useAccount'; import { useWeiAmount } from '../../../hooks/useWeiAmount'; import { useApproveAndBorrow } from '../../../hooks/trading/useApproveAndBorrow'; import { useIsAmountWithinLimits } from '../../../hooks/useIsAmountWithinLimits'; @@ -17,8 +17,8 @@ import { weiTo4 } from '../../../../utils/blockchain/math-helpers'; import { TradeButton } from '../../../components/TradeButton'; import { SendTxProgress } from '../../../components/SendTxProgress'; import { bignumber } from 'mathjs'; -import { useDispatch } from 'react-redux'; import { actions } from '../slice'; +import { useCanInteract } from '../../../hooks/useCanInteract'; type Props = { currency: Asset; @@ -27,7 +27,7 @@ type Props = { const BorrowingContainer: React.FC = ({ currency }) => { const dispatch = useDispatch(); const [amount, setAmount] = useState(''); - const isConnected = useIsConnected(); + const isConnected = useCanInteract(); const borrowAmount = useWeiAmount(amount); // BORROW diff --git a/src/app/containers/LiquidityAddContainer/index.tsx b/src/app/containers/LiquidityAddContainer/index.tsx index 6d33749b2..8751ded22 100644 --- a/src/app/containers/LiquidityAddContainer/index.tsx +++ b/src/app/containers/LiquidityAddContainer/index.tsx @@ -20,12 +20,12 @@ import { AmountField } from '../AmountField'; import { AssetWalletBalance } from '../../components/AssetWalletBalance'; import { TradeButton } from '../../components/TradeButton'; import { useAssetBalanceOf } from '../../hooks/useAssetBalanceOf'; -import { useIsConnected } from '../../hooks/useAccount'; +import { useCanInteract } from '../../hooks/useCanInteract'; interface Props {} export function LiquidityAddContainer(props: Props) { - const isConnected = useIsConnected(); + const isConnected = useCanInteract(); const tokens = liquidityPools.map(item => ({ key: item.source, target: item.target, diff --git a/src/app/containers/LiquidityRemoveContainer/index.tsx b/src/app/containers/LiquidityRemoveContainer/index.tsx index 895625555..6ece230be 100644 --- a/src/app/containers/LiquidityRemoveContainer/index.tsx +++ b/src/app/containers/LiquidityRemoveContainer/index.tsx @@ -23,13 +23,13 @@ import { useRemoveLiquidityReturnAndFee } from '../../hooks/amm/useRemoveLiquidi import { FieldGroup } from '../../components/FieldGroup'; import { AmountField } from '../AmountField'; import { TradeButton } from '../../components/TradeButton'; -import { useIsConnected } from '../../hooks/useAccount'; import { useApproveAndRemoveLiquidity } from '../../hooks/amm/useApproveAndRemoveLiquidity'; +import { useCanInteract } from 'app/hooks/useCanInteract'; interface Props {} export function LiquidityRemoveContainer(props: Props) { - const isConnected = useIsConnected(); + const isConnected = useCanInteract(); const tokens = liquidityPools.map(item => ({ key: item.source, label: item.tokenLabel, diff --git a/src/app/containers/MarginTradeForm/index.tsx b/src/app/containers/MarginTradeForm/index.tsx index 84f66531b..276349387 100644 --- a/src/app/containers/MarginTradeForm/index.tsx +++ b/src/app/containers/MarginTradeForm/index.tsx @@ -20,7 +20,6 @@ import { AmountField } from '../AmountField'; import { FormSelect } from '../../components/FormSelect'; import { FieldGroup } from '../../components/FieldGroup'; import { AssetWalletBalance } from '../../components/AssetWalletBalance'; -import { useIsConnected } from '../../hooks/useAccount'; import { TradeButton } from '../../components/TradeButton'; import { SendTxProgress } from '../../components/SendTxProgress'; import { useApproveAndTrade } from '../../hooks/trading/useApproveAndTrade'; @@ -28,13 +27,14 @@ import { useIsAmountWithinLimits } from '../../hooks/useIsAmountWithinLimits'; import { weiTo18 } from '../../../utils/blockchain/math-helpers'; import { useAssetBalanceOf } from '../../hooks/useAssetBalanceOf'; import { AssetsDictionary } from '../../../utils/blockchain/assets-dictionary'; +import { useCanInteract } from 'app/hooks/useCanInteract'; const s = translations.marginTradeForm; interface Props {} export function MarginTradeForm(props: Props) { - const isConnected = useIsConnected(); + const isConnected = useCanInteract(); const { tradingPair } = useSelector(selectTradingPage); const pair = TradingPairDictionary.get(tradingPair); diff --git a/src/app/containers/RepayPositionHandler/RepayPositionForm.tsx b/src/app/containers/RepayPositionHandler/RepayPositionForm.tsx index f0a99f418..2ff78e285 100644 --- a/src/app/containers/RepayPositionHandler/RepayPositionForm.tsx +++ b/src/app/containers/RepayPositionHandler/RepayPositionForm.tsx @@ -20,12 +20,14 @@ import { useAssetBalanceOf } from '../../hooks/useAssetBalanceOf'; import { weiTo18, weiTo4 } from '../../../utils/blockchain/math-helpers'; import { DummyField } from '../../components/DummyField'; import { useApproveAndCloseWithDeposit } from '../../hooks/trading/useApproveAndCloseWithDeposit'; +import { useCanInteract } from '../../hooks/useCanInteract'; interface Props { loan: ActiveLoan; } export function RepayPositionForm({ loan }: Props) { + const canInteract = useCanInteract(); const { asset } = AssetsDictionary.getByTokenContractAddress(loan.loanToken); const { value: balance } = useAssetBalanceOf(asset); @@ -79,7 +81,7 @@ export function RepayPositionForm({ loan }: Props) { send()} /> diff --git a/src/app/containers/SwapTradeForm/index.tsx b/src/app/containers/SwapTradeForm/index.tsx index 1897be08f..c40a35d42 100644 --- a/src/app/containers/SwapTradeForm/index.tsx +++ b/src/app/containers/SwapTradeForm/index.tsx @@ -14,7 +14,6 @@ import { weiTo18, weiToFixed } from '../../../utils/blockchain/math-helpers'; import { TradeButton } from '../../components/TradeButton'; import { Asset } from '../../../types/asset'; import { useWeiAmount } from '../../hooks/useWeiAmount'; -import { useIsConnected } from '../../hooks/useAccount'; import { translations } from 'locales/i18n'; import { DummyField } from '../../components/DummyField'; import { LoadableValue } from '../../components/LoadableValue'; @@ -26,6 +25,7 @@ import { useSwapNetwork_approveAndConvertByPath } from '../../hooks/swap-network import { SendTxProgress } from '../../components/SendTxProgress'; import { AssetWalletBalance } from '../../components/AssetWalletBalance'; import { useAssetBalanceOf } from '../../hooks/useAssetBalanceOf'; +import { useCanInteract } from '../../hooks/useCanInteract'; const s = translations.swapTradeForm; @@ -39,7 +39,7 @@ const color = 'var(--teal)'; export function SwapTradeForm(props: Props) { const { t } = useTranslation(); - const isConnected = useIsConnected(); + const isConnected = useCanInteract(); const [amount, setAmount] = useState(''); const [sourceToken, setSourceToken] = useState(Asset.DOC); diff --git a/src/app/containers/TopUpTradingPositionHandler/index.tsx b/src/app/containers/TopUpTradingPositionHandler/index.tsx index dcfd4c014..533ffbecc 100644 --- a/src/app/containers/TopUpTradingPositionHandler/index.tsx +++ b/src/app/containers/TopUpTradingPositionHandler/index.tsx @@ -20,6 +20,7 @@ import { DialogButton } from '../../components/DialogButton'; import { AmountField } from '../AmountField'; import { DummyField } from '../../components/DummyField'; import { FieldGroup } from '../../components/FieldGroup'; +import { useCanInteract } from '../../hooks/useCanInteract'; interface Props { item: ActiveLoan; @@ -28,6 +29,7 @@ interface Props { } export function TopUpTradingPositionHandler(props: Props) { + const canInteract = useCanInteract(); const tokenDetails = AssetsDictionary.getByTokenContractAddress( props.item.collateralToken, ); @@ -94,7 +96,7 @@ export function TopUpTradingPositionHandler(props: Props) { handleConfirm()} - disabled={rest.loading || !valid} + disabled={rest.loading || !valid || !canInteract} loading={rest.loading} /> diff --git a/src/app/containers/TradingToken/index.tsx b/src/app/containers/TradingToken/index.tsx deleted file mode 100644 index 497f4bec2..000000000 --- a/src/app/containers/TradingToken/index.tsx +++ /dev/null @@ -1,122 +0,0 @@ -/** - * - * TradingToken - * - */ -import React, { useCallback, useEffect, useState } from 'react'; -import { Asset } from '../../../types/asset'; -import { LeverageSelector } from '../../components/LeverageSelector'; -import { TradingPosition } from '../../../types/trading-position'; -import { TradingPositionSelector } from '../../components/TradingPositionSelector'; -import { BorrowInterestRate } from '../../components/BorrowInterestRate'; -import { BorrowAssetPrice } from '../../components/BorrowAssetPrice'; -import { BorrowLiquidationPrice } from '../../components/BorrowLiquidationPrice'; -import { TradeDialog } from '../../components/TradeDialog'; -import { useWeiAmount } from '../../hooks/useWeiAmount'; -import btcIcon from 'assets/images/rBTC-logo.png'; -import { AssetsDictionary } from '../../../utils/blockchain/assets-dictionary'; - -interface Props { - marketToken: Asset; -} - -/** - * @deprecated - * @param props - * @constructor - */ -export function TradingToken(props: Props) { - const [position, setPosition] = useState(TradingPosition.LONG); - - const resolveLoanToken = useCallback(() => { - if (position === TradingPosition.LONG) { - return Asset.DOC; - } - return Asset.BTC; - }, [position]); - - const [leverage, setLeverage] = useState(2); - const [loanToken, setLoanToken] = useState(resolveLoanToken()); - const [collateral, setCollateral] = useState( - AssetsDictionary.get(loanToken).getCollateralAssets()[0], - ); - - const [amount, setAmount] = useState('0'); - const weiAmount = useWeiAmount(amount); - - useEffect(() => { - setLoanToken(resolveLoanToken()); - // eslint-disable-next-line - }, [position]); - - return ( -
-
- -

- {props.marketToken} -

-
- -
-
-
-
- setPosition(value)} - /> -
-
- setLeverage(value)} - position={position} - /> -
-
-
- -
-
- -
-
-
-
- setCollateral(value)} - onChangeAmount={value => setAmount(value)} - /> -
-
- ); -} - -TradingToken.defaultProps = { - marketToken: Asset.BTC, -}; diff --git a/src/app/containers/WalletProvider/index.tsx b/src/app/containers/WalletProvider/index.tsx index 6a3025984..63e44e929 100644 --- a/src/app/containers/WalletProvider/index.tsx +++ b/src/app/containers/WalletProvider/index.tsx @@ -6,13 +6,13 @@ import React from 'react'; import { useInjectReducer, useInjectSaga } from 'utils/redux-injectors'; -import { reducer, sliceKey } from './slice'; -import { walletProviderSaga } from './saga'; import { eventsSlice, reducer as eventsReducer, } from 'store/global/events-store/slice'; import { eventsStateSaga } from 'store/global/events-store/saga'; +import { reducer, sliceKey } from './slice'; +import { walletProviderSaga } from './saga'; interface Props { children: React.ReactNode; diff --git a/src/app/containers/WalletProvider/saga.ts b/src/app/containers/WalletProvider/saga.ts index 6d55bc62c..6d7ac461d 100644 --- a/src/app/containers/WalletProvider/saga.ts +++ b/src/app/containers/WalletProvider/saga.ts @@ -7,10 +7,11 @@ import { take, takeEvery, } from 'redux-saga/effects'; -import { actions } from './slice'; -import { Sovryn } from '../../../utils/sovryn'; -import { selectWalletProvider } from './selectors'; import { PayloadAction } from '@reduxjs/toolkit'; +import { Sovryn } from 'utils/sovryn'; +import { contractReader } from 'utils/sovryn/contract-reader'; +import { selectWalletProvider } from './selectors'; +import { actions } from './slice'; function createBlockChannels({ web3 }) { return eventChannel(emit => { @@ -128,9 +129,33 @@ function* walletDisconnected() { yield put(actions.accountChanged('')); } +function* accountChangedSaga({ payload }: PayloadAction<{ address: string }>) { + const state = yield select(selectWalletProvider); + if (state.whitelist.enabled) { + yield put(actions.whitelistCheck()); + } +} + +function* whitelistCheckSaga() { + const state = yield select(selectWalletProvider); + try { + const result = yield call( + [contractReader, contractReader.call], + 'whitelistToken' as any, + 'balanceOf', + [state.address], + ); + yield put(actions.whitelistChecked(result > 0)); + } catch (e) { + yield put(actions.whitelistChecked(false)); + } +} + export function* walletProviderSaga() { yield takeLatest(actions.chainChanged.type, callCreateBlockChannels); yield takeLatest(actions.connected.type, walletConnected); yield takeLatest(actions.disconnected.type, walletDisconnected); yield takeEvery(actions.blockReceived.type, processBlockHeader); + yield takeEvery(actions.accountChanged.type, accountChangedSaga); + yield takeEvery(actions.whitelistCheck.type, whitelistCheckSaga); } diff --git a/src/app/containers/WalletProvider/slice.ts b/src/app/containers/WalletProvider/slice.ts index d7c66b4ea..48dbbe9e1 100644 --- a/src/app/containers/WalletProvider/slice.ts +++ b/src/app/containers/WalletProvider/slice.ts @@ -15,6 +15,15 @@ export const initialState: ContainerState = { // todo ? transactions: {}, transactionStack: [], + whitelist: { + enabled: + !!process.env.REACT_APP_WHITELIST_TOKEN && + process.env.REACT_APP_WHITELIST === 'true', + loading: false, + loaded: false, + whitelisted: false, + isDialogOpen: false, + }, }; const walletProviderSlice = createSlice({ @@ -75,6 +84,20 @@ const walletProviderSlice = createSlice({ }, processBlock(state, action: PayloadAction) {}, + + whitelistCheck(state) { + state.whitelist.loading = true; + state.whitelist.loaded = false; + }, + whitelistChecked(state, { payload }: PayloadAction) { + state.whitelist.whitelisted = payload; + state.whitelist.isDialogOpen = !payload; + state.whitelist.loading = false; + state.whitelist.loaded = true; + }, + whitelistDialog(state, { payload }: PayloadAction) { + state.whitelist.isDialogOpen = payload; + }, }, }); diff --git a/src/app/containers/WalletProvider/types.ts b/src/app/containers/WalletProvider/types.ts index e2111e831..95915a3f1 100644 --- a/src/app/containers/WalletProvider/types.ts +++ b/src/app/containers/WalletProvider/types.ts @@ -11,6 +11,16 @@ export interface WalletProviderState { // todo ? transactions: any; transactionStack: string[]; + // whitelisting + whitelist: IWhitelist; } export type ContainerState = WalletProviderState; + +export interface IWhitelist { + enabled: boolean; + loading: boolean; + loaded: boolean; + whitelisted: boolean; + isDialogOpen: boolean; +} diff --git a/src/app/containers/WithdrawLentAmount/Loadable.ts b/src/app/containers/WithdrawLentAmount/Loadable.ts deleted file mode 100644 index 53342fb9c..000000000 --- a/src/app/containers/WithdrawLentAmount/Loadable.ts +++ /dev/null @@ -1,15 +0,0 @@ -/** - * - * Asynchronously loads the component for WithdrawLentAmount - * - */ - -import { lazyLoad } from 'utils/loadable'; - -/** - * @deprecated - */ -export const WithdrawLentAmount = lazyLoad( - () => import('./index'), - module => module.WithdrawLentAmount, -); diff --git a/src/app/containers/WithdrawLentAmount/index.tsx b/src/app/containers/WithdrawLentAmount/index.tsx deleted file mode 100644 index 1ee1ea768..000000000 --- a/src/app/containers/WithdrawLentAmount/index.tsx +++ /dev/null @@ -1,90 +0,0 @@ -/** - * - * WithdrawLentAmount - * - */ - -import React, { useCallback, useEffect, useState } from 'react'; -import { Asset } from 'types/asset'; -import { useAccount } from '../../hooks/useAccount'; -import { useUnLendTokensRBTC } from '../../hooks/useUnLendTokensRBTC'; -import { WithdrawLentDialog } from '../../components/WithdrawLentDialog'; -import { weiTo18, weiToBigInt } from '../../../utils/blockchain/math-helpers'; -import { bignumber, min } from 'mathjs'; -import { useUnLendTokens } from '../../hooks/useUnLendTokens'; -import { useLending_totalAssetSupply } from '../../hooks/lending/useLending_totalAssetSupply'; -import { useLending_totalAssetBorrow } from '../../hooks/lending/useLending_totalAssetBorrow'; -import { useLending_assetBalanceOf } from '../../hooks/lending/useLending_assetBalanceOf'; -import { useLending_tokenPrice } from '../../hooks/lending/useLending_tokenPrice'; - -interface Props { - asset: Asset; - isOpen: boolean; - onClose: () => void; -} - -/** - * @deprecated - * @param props - * @constructor - */ -export function WithdrawLentAmount(props: Props) { - const { value: userBalance } = useLending_assetBalanceOf( - props.asset, - useAccount(), - ); - const { value: totalAssetSupply } = useLending_totalAssetSupply(props.asset); - const { value: totalAssetBorrow } = useLending_totalAssetBorrow(props.asset); - const { value: tokenPrice } = useLending_tokenPrice(props.asset); - - const calculateBalance = useCallback(() => { - const availableAssets = bignumber(totalAssetSupply).minus(totalAssetBorrow); - return min(bignumber(userBalance), availableAssets).toString(); - }, [totalAssetSupply, totalAssetBorrow, userBalance]); - - const [balance, setBalance] = useState(calculateBalance()); - const [amount, setAmount] = useState(weiTo18(balance)); - const fixedAmount = weiToBigInt(amount); - const { unLend: unlendToken, ...txTokenState } = useUnLendTokens(props.asset); - const { unLend: unlendBtc, ...txBtcState } = useUnLendTokensRBTC(props.asset); - - const [, /*txAmount*/ setTxAmount] = useState('0'); - - useEffect(() => { - setBalance(calculateBalance()); - }, [userBalance, totalAssetBorrow, totalAssetSupply, calculateBalance]); - - useEffect(() => { - setAmount(weiTo18(balance)); - }, [balance]); - - useEffect(() => { - setTxAmount( - bignumber(amount) - .div(tokenPrice) - .mul(10 ** 36) - .toFixed(0), - ); - }, [amount, tokenPrice]); - - const handleUnLendClick = useCallback(() => { - if (props.asset === Asset.BTC) { - unlendBtc(fixedAmount); - } else { - unlendToken(fixedAmount); - } - }, [props.asset, unlendBtc, fixedAmount, unlendToken]); - - return ( - setAmount(value)} - onConfirm={() => handleUnLendClick()} - txState={props.asset === Asset.BTC ? txBtcState : txTokenState} - isOpen={props.isOpen} - onClose={() => props.onClose()} - /> - ); -} diff --git a/src/app/hooks/useCanInteract.ts b/src/app/hooks/useCanInteract.ts new file mode 100644 index 000000000..1526bf746 --- /dev/null +++ b/src/app/hooks/useCanInteract.ts @@ -0,0 +1,13 @@ +import { useIsConnected } from './useAccount'; +import { useSelector } from 'react-redux'; +import { selectWalletProvider } from '../containers/WalletProvider/selectors'; + +// For disabling buttons while check is in progress, user not yet connected and etc. +export function useCanInteract() { + const isConnected = useIsConnected(); + const { whitelist } = useSelector(selectWalletProvider); + return ( + (isConnected && !whitelist.enabled) || + (isConnected && whitelist.loaded && whitelist.whitelisted) + ); +} diff --git a/src/app/hooks/whitelist/useIsWhitelisted.ts b/src/app/hooks/whitelist/useIsWhitelisted.ts new file mode 100644 index 000000000..ade0c761a --- /dev/null +++ b/src/app/hooks/whitelist/useIsWhitelisted.ts @@ -0,0 +1,13 @@ +import { useSelector } from 'react-redux'; +import { selectWalletProvider } from 'app/containers/WalletProvider/selectors'; +import { useIsConnected } from '../useAccount'; + +// For showing notifications when check is completed and user is not whitelisted for sure. +export function useIsWhitelisted() { + const isConnected = useIsConnected(); + const { whitelist } = useSelector(selectWalletProvider); + if (!isConnected || !whitelist.enabled || !whitelist.loaded) { + return true; + } + return whitelist.whitelisted; +} diff --git a/src/utils/blockchain/contracts.testnet.ts b/src/utils/blockchain/contracts.testnet.ts index 7d2729d9d..a2d614ab6 100644 --- a/src/utils/blockchain/contracts.testnet.ts +++ b/src/utils/blockchain/contracts.testnet.ts @@ -78,4 +78,12 @@ export const contracts = { abi: tokenAbi, blockNumber: 1218844, }, + ...(process.env.REACT_APP_WHITELIST_TOKEN && + process.env.REACT_APP_WHITELIST === 'true' && { + whitelistToken: { + address: process.env.REACT_APP_WHITELIST_TOKEN, + abi: tokenAbi, + blockNumber: 1218844, + }, + }), }; diff --git a/src/utils/blockchain/contracts.ts b/src/utils/blockchain/contracts.ts index c18b09bea..395186b2f 100644 --- a/src/utils/blockchain/contracts.ts +++ b/src/utils/blockchain/contracts.ts @@ -78,4 +78,12 @@ export const contracts = { abi: tokenAbi, blockNumber: 2742648, }, + ...(process.env.REACT_APP_WHITELIST_TOKEN && + process.env.REACT_APP_WHITELIST === 'true' && { + whitelistToken: { + address: process.env.REACT_APP_WHITELIST_TOKEN, + abi: tokenAbi, + blockNumber: 1218844, + }, + }), }; diff --git a/src/utils/classifiers.ts b/src/utils/classifiers.ts index 4ff975739..aa5a79872 100644 --- a/src/utils/classifiers.ts +++ b/src/utils/classifiers.ts @@ -23,12 +23,14 @@ export const networkNames = { }; export const rpcNodes = { - 30: 'https://mainnet.sovryn.app/rpc', + // 30: 'https://mainnet.sovryn.app/rpc', + 30: 'https://mainnetbackup.sovryn.app/rpc', 31: 'https://testnet.sovryn.app/rpc', }; export const readNodes = { - 30: 'wss://mainnet.sovryn.app/ws', + // 30: 'wss://mainnet.sovryn.app/ws', + 30: 'wss://mainnetbackup.sovryn.app/ws', 31: 'wss://testnet.sovryn.app/ws', // 30: 'https://public-node.rsk.co', // 31: 'https://public-node.testnet.rsk.co',