diff --git a/.env b/.env index ab2f5fb..e69de29 100644 --- a/.env +++ b/.env @@ -1,2 +0,0 @@ -NEXT_PUBLIC_NETWORK=mainnet -NEXT_PUBLIC_STAGE=production \ No newline at end of file diff --git a/.env.example b/.env.example index c00edd2..bb9ac83 100644 --- a/.env.example +++ b/.env.example @@ -1,4 +1,14 @@ -NEXT_PUBLIC_NETWORK=mainnet -NEXT_PUBLIC_RPC=https://rpc-osmosis.blockapsis.com -NEXT_PUBLIC_GQL=https://osmosis-node.marsprotocol.io/GGSFGSFGFG34/osmosis-hive-front/graphql -NEXT_PUBLIC_REST=https://lcd-osmosis.blockapsis.com \ No newline at end of file +# OSMOSIS-1 # +NEXT_PUBLIC_OSMOSIS_RPC=https://rpc-osmosis.blockapsis.com +NEXT_PUBLIC_OSMOSIS_REST=https://lcd-osmosis.blockapsis.com +NEXT_PUBLIC_OSMOSIS_GQL=https://osmosis-node.marsprotocol.io/GGSFGSFGFG34/osmosis-hive-front/graphql + +# OSMO-TEST-5 # +NEXT_PUBLIC_OSMOSIS_TEST_RPC=https://rpc.osmotest5.osmosis.zone +NEXT_PUBLIC_OSMOSIS_TEST_REST=https://lcd.osmotest5.osmosis.zone +NEXT_PUBLIC_OSMOSIS_TEST_GQL=https://testnet-osmosis-node.marsprotocol.io/XF32UOOU55CX/osmosis-hive-front/graphql + +# PION-1 # +NEXT_PUBLIC_NEUTRON_TEST_RPC=https://rpc-palvus.pion-1.ntrn.tech/ +NEXT_PUBLIC_NEUTRON_TEST_REST=https://rest-palvus.pion-1.ntrn.tech/ +NEXT_PUBLIC_NEUTRON_TEST_GQL=https://testnet-neutron-gql.marsprotocol.io/graphql \ No newline at end of file diff --git a/.env.production b/.env.production index f988fe1..e69ca5b 100644 --- a/.env.production +++ b/.env.production @@ -1,7 +1,17 @@ # DO NOT EDIT THIS FILE WHEN USING DOCKER # These values are used to replace the values in the built app, # you should pass environment variables as defined in README.md -NEXT_PUBLIC_NETWORK=APP_NEXT_NETWORK -NEXT_PUBLIC_RPC=APP_NEXT_RPC -NEXT_PUBLIC_GQL=APP_NEXT_GQL -NEXT_PUBLIC_REST=APP_NEXT_REST \ No newline at end of file +# OSMOSIS-1 # +NEXT_PUBLIC_OSMOSIS_RPC=APP_NEXT_OSMOSIS_RPC +NEXT_PUBLIC_OSMOSIS_REST=APP_NEXT_OSMOSIS_REST +NEXT_PUBLIC_OSMOSIS_GQL=APP_NEXT_OSMOSIS_GQL + +# OSMO-TEST-5 # +NEXT_PUBLIC_OSMOSIS_TEST_RPC=APP_NEXT_OSMOSIS_TEST_RPC +NEXT_PUBLIC_OSMOSIS_TEST_REST=APP_NEXT_OSMOSIS_TEST_REST +NEXT_PUBLIC_OSMOSIS_TEST_GQL=APP_NEXT_OSMOSIS_TEST_GQL + +# PION-1 # +NEXT_PUBLIC_NEUTRON_TEST_RPC=APP_NEXT_NEUTRON_TEST_RPC +NEXT_PUBLIC_NEUTRON_TEST_REST=APP_NEXT_NEUTRON_TEST_REST +NEXT_PUBLIC_NEUTRON_TEST_GQL=APP_NEXT_NEUTRON_TEST_GQL \ No newline at end of file diff --git a/README.md b/README.md index a406aa5..b333212 100644 --- a/README.md +++ b/README.md @@ -31,10 +31,15 @@ We allow the use of environment variables to be passed to the Docker container t |Variable|Description|Default| |--------|-----------|-------| -|NETWORK|Flag for mainnet or testnet|mainnet| -|URL_GQL|The Hive GraphQL endpoint to use|https://osmosis-node.marsprotocol.io/GGSFGSFGFG34/osmosis-hive-front/graphql| -|URL_REST|The node REST endpoint to use|https://lcd-osmosis.blockapsis.com| -|URL_RPC|The node RPC endpoint to use|https://rpc-osmosis.blockapsis.com| +|URL_OSMOSIS_GQL|The Osmosis Hive GraphQL endpoint to use|https://osmosis-node.marsprotocol.io/GGSFGSFGFG34/osmosis-hive-front/graphql| +|URL_OSMOSIS_REST|The Osmosis node REST endpoint to use|https://lcd-osmosis.blockapsis.com| +|URL_OSMOSIS_RPC|The Osmosis node RPC endpoint to use|https://rpc-osmosis.blockapsis.com| +|URL_OSMOSIS_TEST_GQL|The Osmosis Testnet Hive GraphQL endpoint to use|https://testnet-osmosis-node.marsprotocol.io/XF32UOOU55CX/osmosis-hive-front/graphql| +|URL_OSMOSIS_TEST_REST|The Osmosis Testnet node REST endpoint to use|https://lcd.osmotest5.osmosis.zone| +|URL_OSMOSIS_TEST_RPC|The Osmosis Testnet node RPC endpoint to use|https://rpc.osmotest5.osmosis.zone| +|URL_NEUTRON_TEST_GQL|The Neutron Testnet Hive GraphQL endpoint to use|https://testnet-neutron-gql.marsprotocol.io/graphql| +|URL_NEUTRON_TEST_REST|The Neutron Testnet node REST endpoint to use|https://rest-palvus.pion-1.ntrn.tech| +|URL_NEUTRON_TEST_RPC|The Neutron Testnet node RPC endpoint to use|https://rpc-palvus.pion-1.ntrn.tech| **Sample Docker run command** @@ -43,9 +48,15 @@ This command will start the container in interactive mode with port 3000 bound t ```sh docker run -it -p 3000:3000 \ -e NETWORK=mainnet \ - -e URL_GQL=https://your-hive-endpoint.com \ - -e URL_REST=https://your-rest-endpoint.com \ - -e URL_RPC=https://your-rpc-endpoint.com marsprotocol/interface:latest + -e URL_OSMOSIS_GQL=https://your-osmosis-hive-endpoint.com \ + -e URL_OSMOSIS_REST=https://your-osmosis-rest-endpoint.com \ + -e URL_OSMOSIS_RPC=https://your-osmosis-rpc-endpoint.com \ + -e URL_OSMOSIS_TEST_GQL=https://your-osmosis-testnet-hive-endpoint.com \ + -e URL_OSMOSIS_TEST_REST=https://your-osmosis-testnet-rest-endpoint.com \ + -e URL_OSMOSIS_TEST_RPC=https://your-osmosis-testnet-rpc-endpoint.com \ + -e URL_NEUTRON_TEST_GQL=https://your-neutron-testnet-hive-endpoint.com \ + -e URL_NEUTRON_TEST_REST=https://your-neutron-testnet-rest-endpoint.com \ + -e URL_NEUTRON_TEST_RPC=https://your-neutron-testnet-rpc-endpoint.com marsprotocol/interface:latest ``` ## 3. Text and translations diff --git a/entrypoint.sh b/entrypoint.sh index bc99004..4bc030d 100755 --- a/entrypoint.sh +++ b/entrypoint.sh @@ -4,10 +4,15 @@ set +x nextFolder='/app/.next' # create the config file from environment variables envFilename='override.conf' -echo "APP_NEXT_NETWORK=$NETWORK" >> $envFilename -echo "APP_NEXT_GQL=$URL_GQL" >> $envFilename -echo "APP_NEXT_REST=$URL_REST" >> $envFilename -echo "APP_NEXT_RPC=$URL_RPC" >> $envFilename +echo "APP_NEXT_OSMOSIS_RPC=$URL_OSMOSIS_RPC" >> $envFilename +echo "APP_NEXT_OSMOSIS_REST=$URL_OSMOSIS_REST" >> $envFilename +echo "APP_NEXT_OSMOSIS_GQL=$URL_OSMOSIS_GQL" >> $envFilename +echo "APP_NEXT_OSMOSIS_TEST_RPC=$URL_OSMOSIS_TEST_RPC" >> $envFilename +echo "APP_NEXT_OSMOSIS_TEST_REST=$URL_OSMOSIS_TEST_REST" >> $envFilename +echo "APP_NEXT_OSMOSIS_TEST_GQL=$URL_OSMOSIS_TEST_GQL" >> $envFilename +echo "APP_NEXT_NEUTRON_TEST_RPC=$URL_NEUTRON_TEST_RPC" >> $envFilename +echo "APP_NEXT_NEUTRON_TEST_REST=$URL_NEUTRON_TEST_REST" >> $envFilename +echo "APP_NEXT_NEUTRON_TEST_GQL=$URL_NEUTRON_TEST_GQL" >> $envFilename function apply_path { # read all config file while read line; do diff --git a/next.config.js b/next.config.js index 0f9327d..9f21f0d 100644 --- a/next.config.js +++ b/next.config.js @@ -4,7 +4,6 @@ const path = require('path') const moduleExports = { reactStrictMode: true, - experimental: { images: { unoptimized: true } }, sassOptions: { includePaths: [path.join(__dirname, 'src/styles')], }, diff --git a/package.json b/package.json index a16d370..c57615a 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "mars", "homepage": "./", - "version": "1.4.9", + "version": "1.5.0", "license": "SEE LICENSE IN LICENSE FILE", "private": false, "scripts": { @@ -22,7 +22,7 @@ "@cosmjs/launchpad": "^0.27.1", "@cosmjs/proto-signing": "^0.30.1", "@cosmjs/stargate": "^0.30.1", - "@marsprotocol/wallet-connector": "^1.5.8", + "@marsprotocol/wallet-connector": "^1.8.6", "@material-ui/core": "^4.12.4", "@material-ui/icons": "^4.11.3", "@ramonak/react-progress-bar": "^5.0.3", diff --git a/src/components/common/CircularProgress/CircularProgress.tsx b/src/components/common/CircularProgress/CircularProgress.tsx index b8d45ea..66a4f28 100644 --- a/src/components/common/CircularProgress/CircularProgress.tsx +++ b/src/components/common/CircularProgress/CircularProgress.tsx @@ -7,15 +7,21 @@ interface Props { color?: string size?: number className?: string + forceAnimation?: boolean } -export const CircularProgress = ({ color = '#FFFFFF', size = 20, className }: Props) => { +export const CircularProgress = ({ + color = '#FFFFFF', + size = 20, + className, + forceAnimation = false, +}: Props) => { const enableAnimations = useStore((s) => s.enableAnimations) const borderWidth = `${size / 10}px` const borderColor = `${color} transparent transparent transparent` const loaderClasses = classNames(styles.loader, className) - if (!enableAnimations) return
...
+ if (!enableAnimations && !forceAnimation) return
...
return (
diff --git a/src/components/common/Containers/CommonContainer.tsx b/src/components/common/Containers/CommonContainer.tsx index 4251189..c8064c4 100644 --- a/src/components/common/Containers/CommonContainer.tsx +++ b/src/components/common/Containers/CommonContainer.tsx @@ -1,6 +1,5 @@ import { CosmWasmClient } from '@cosmjs/cosmwasm-stargate' import { - ChainInfoID, getChainInfo, getClient, useWallet, @@ -9,7 +8,6 @@ import { } from '@marsprotocol/wallet-connector' import { useQueryClient } from '@tanstack/react-query' import { MARS_SYMBOL } from 'constants/appConstants' -import { NETWORK } from 'constants/env' import { useBlockHeight, useDepositAndDebt, @@ -20,12 +18,14 @@ import { useUserDebt, useUserIcns, } from 'hooks/queries' +import { usePythVaa } from 'hooks/queries/usePythVaa' import { useSpotPrice } from 'hooks/queries/useSpotPrice' import { useUserCollaterals } from 'hooks/queries/useUserCollaterals' import { ReactNode, useEffect, useState } from 'react' import useStore from 'store' import { State } from 'types/enums' -import { Network } from 'types/enums/network' + +import { MigrationInProgress } from '../MigrationInProgress/MigrationInProgress' interface CommonContainerProps { children: ReactNode @@ -35,70 +35,76 @@ export const CommonContainer = ({ children }: CommonContainerProps) => { // ------------------ // EXTERNAL HOOKS // --------------- - const { recentWallet, simulate, sign, broadcast } = useWallet() - const { status } = useWalletManager() + const { simulate, sign, broadcast } = useWallet() + const { status, connectedWallet } = useWalletManager() const queryClient = useQueryClient() - const chainInfo = recentWallet?.network - ? getChainInfo(recentWallet?.network.chainId as ChainInfoID) - : undefined - const address = status !== WalletConnectionStatus.Connected ? '' : recentWallet?.account.address - const [cosmWasmClient, setCosmWasmClient] = useState() // ------------------ // STORE STATE // ------------------ - const chainID = useStore((s) => s.chainInfo?.chainId) + const assetPricesUSDState = useStore((s) => s.assetPricesUSDState) + const assetPricesUSD = useStore((s) => s.assetPricesUSD) + const chainId = useStore((s) => s.currentNetwork) const exchangeRates = useStore((s) => s.exchangeRates) const exchangeRatesState = useStore((s) => s.exchangeRatesState) - const isNetworkLoaded = useStore((s) => s.isNetworkLoaded) - const rpc = useStore((s) => s.chainInfo?.rpc) + const networkConfig = useStore((s) => s.networkConfig) const marketDeposits = useStore((s) => s.marketDeposits) const marketInfo = useStore((s) => s.marketInfo) const marketIncentiveInfo = useStore((s) => s.marketIncentiveInfo) + const migrationInProgress = useStore((s) => s.migrationInProgress) const redBankState = useStore((s) => s.redBankState) + const rpc = useStore((s) => s.networkConfig.rpcUrl) const userBalances = useStore((s) => s.userBalances) const userBalancesState = useStore((s) => s.userBalancesState) const userDebts = useStore((s) => s.userDebts) const userDeposits = useStore((s) => s.userDeposits) const userWalletAddress = useStore((s) => s.userWalletAddress) const whitelistedAssets = useStore((s) => s.whitelistedAssets) - const loadNetworkConfig = useStore((s) => s.loadNetworkConfig) const setRedBankAssets = useStore((s) => s.setRedBankAssets) - const setChainInfo = useStore((s) => s.setChainInfo) - const setCurrentNetwork = useStore((s) => s.setCurrentNetwork) const setLcdClient = useStore((s) => s.setLcdClient) - const setClient = useStore((s) => s.setClient) + const setChainInfo = useStore((s) => s.setChainInfo) const setUserBalancesState = useStore((s) => s.setUserBalancesState) const setUserWalletAddress = useStore((s) => s.setUserWalletAddress) + const pythVaa = useStore((s) => s.pythVaa) // ------------------ // SETTERS // ------------------ + useEffect(() => { - if (NETWORK === 'mainnet') { - setCurrentNetwork(Network.MAINNET) + if (status !== WalletConnectionStatus.Connected && cosmWasmClient) { + setCosmWasmClient(undefined) + useStore.setState({ + client: undefined, + creditManagerClient: undefined, + accountNftClient: undefined, + userWalletAddress: '', + }) } - loadNetworkConfig() - }, [loadNetworkConfig, setCurrentNetwork]) + }, [status, cosmWasmClient]) useEffect(() => { - if (!chainInfo) return + const chainInfo = getChainInfo(chainId, { + rpc: networkConfig.rpcUrl, + rest: networkConfig.restUrl, + }) setChainInfo(chainInfo) - }, [chainInfo, setChainInfo]) + }, [chainId, networkConfig, setChainInfo]) useEffect(() => { - setUserWalletAddress(address || '') - }, [setUserWalletAddress, address]) + if (!connectedWallet || connectedWallet.network.chainId !== chainId) return + setUserWalletAddress(connectedWallet.account.address) + }, [setUserWalletAddress, connectedWallet, chainId]) useEffect(() => { - if (!rpc || !chainID) return - setLcdClient(rpc, chainID) - }, [rpc, chainID, setLcdClient]) + if (!rpc || !chainId) return + setLcdClient(rpc, chainId) + }, [rpc, chainId, setLcdClient]) useEffect(() => { - if (userDebts && userDeposits && userBalances) { + if (userBalances) { setUserBalancesState(State.READY) } else { setUserBalancesState(State.ERROR) @@ -106,10 +112,10 @@ export const CommonContainer = ({ children }: CommonContainerProps) => { }, [userDebts, userDeposits, userBalances, setUserBalancesState]) useEffect(() => { - if (!recentWallet) return + if (!connectedWallet || connectedWallet.network.chainId !== chainId) return if (!cosmWasmClient) { const getCosmWasmClient = async () => { - const cosmClient = await getClient(recentWallet.network.rpc) + const cosmClient = await getClient(networkConfig.rpcUrl) setCosmWasmClient(cosmClient) } @@ -117,19 +123,22 @@ export const CommonContainer = ({ children }: CommonContainerProps) => { return } - const client = { - broadcast, - cosmWasmClient, - recentWallet, - sign, - simulate, - } - setClient(client) - }, [simulate, sign, recentWallet, cosmWasmClient, broadcast, setClient]) + useStore.setState({ + client: { + broadcast, + cosmWasmClient, + connectedWallet, + sign, + simulate, + }, + }) + }, [simulate, sign, connectedWallet, cosmWasmClient, broadcast, networkConfig, chainId]) useEffect(() => { setRedBankAssets() }, [ + assetPricesUSD, + assetPricesUSDState, exchangeRatesState, redBankState, userBalancesState, @@ -151,17 +160,19 @@ export const CommonContainer = ({ children }: CommonContainerProps) => { // ------------------ // QUERY RELATED // ------------------ + useUsdPrice() useBlockHeight() - useRedBank() useUserBalance() useUserIcns() useUserDebt() useUserCollaterals() useMarsOracle() useSpotPrice(MARS_SYMBOL) - useUsdPrice() useDepositAndDebt() useRedBank() + usePythVaa() - return <>{isNetworkLoaded && children} + if (migrationInProgress) return + + return <>{children} } diff --git a/src/components/common/Containers/FieldsContainer.tsx b/src/components/common/Containers/FieldsContainer.tsx index f7cd570..8cad06e 100644 --- a/src/components/common/Containers/FieldsContainer.tsx +++ b/src/components/common/Containers/FieldsContainer.tsx @@ -1,4 +1,4 @@ -import React, { ReactNode, useEffect } from 'react' +import { ReactNode, useEffect } from 'react' import useStore from 'store' import { AccountNftClient, CreditManagerClient } from 'types/classes' @@ -8,24 +8,39 @@ interface FieldsContainerProps { export const FieldsContainer = ({ children }: FieldsContainerProps) => { const client = useStore((s) => s.client) + const currentNetwork = useStore((s) => s.currentNetwork) const networkConfig = useStore((s) => s.networkConfig) const userWalletAddress = useStore((s) => s.userWalletAddress) + const getVaults = useStore((s) => s.getVaults) const setCreditManagerMsgComposer = useStore((s) => s.setCreditManagerMsgComposer) - useEffect(() => { - if (!client || !networkConfig) return - useStore.setState({ - creditManagerClient: new CreditManagerClient(networkConfig?.contracts.creditManager, client), - }) - useStore.setState({ - accountNftClient: new AccountNftClient(networkConfig?.contracts.accountNft, client), - }) - }, [client, networkConfig]) + const creditManagerAddress = networkConfig.contracts.creditManager + const accountNftContractAddress = networkConfig.contracts.accountNft useEffect(() => { - if (!userWalletAddress || !networkConfig?.contracts.creditManager) return + if (!networkConfig.isFieldsEnabled || !creditManagerAddress || !accountNftContractAddress) + return + if (!client || client.connectedWallet.network.chainId !== currentNetwork) return + useStore.setState({ + creditManagerClient: new CreditManagerClient(creditManagerAddress, client), + accountNftClient: new AccountNftClient(accountNftContractAddress, client), + apys: null, + }) + + getVaults({ refetch: true }) + }, [ + client, + networkConfig, + accountNftContractAddress, + creditManagerAddress, + currentNetwork, + getVaults, + ]) + + useEffect(() => { + if (!userWalletAddress || !networkConfig.contracts.creditManager) return setCreditManagerMsgComposer(userWalletAddress, networkConfig.contracts.creditManager) - }, [userWalletAddress, networkConfig, setCreditManagerMsgComposer]) + }, [userWalletAddress, networkConfig.contracts.creditManager, setCreditManagerMsgComposer]) return <>{children} } diff --git a/src/components/common/CosmosWalletConnectProvider/CosmosWalletConnectProvider.tsx b/src/components/common/CosmosWalletConnectProvider/CosmosWalletConnectProvider.tsx index d0a5b42..20e8fe3 100644 --- a/src/components/common/CosmosWalletConnectProvider/CosmosWalletConnectProvider.tsx +++ b/src/components/common/CosmosWalletConnectProvider/CosmosWalletConnectProvider.tsx @@ -1,7 +1,9 @@ -import { ChainInfoID, WalletID, WalletManagerProvider } from '@marsprotocol/wallet-connector' +import { WalletID, WalletManagerProvider } from '@marsprotocol/wallet-connector' import { CircularProgress, SVG } from 'components/common' -import { NETWORK } from 'constants/env' -import { useEffect, useState } from 'react' +import { SUPPORTED_CHAINS } from 'constants/appConstants' +import { getCurrentChainId } from 'libs/chainId' +import { useEffect } from 'react' +import useStore from 'store' import styles from './CosmosWalletConnectProvider.module.scss' @@ -10,42 +12,36 @@ type Props = { } export const CosmosWalletConnectProvider = ({ children }: Props) => { - const [chainInfoOverrides, setChainInfoOverrides] = useState<{ - rpc: string - rest: string - chainID: ChainInfoID - }>() - const [enabledWallets, setEnabledWallets] = useState([]) + const currentNetwork = useStore((s) => s.currentNetwork) + const setCurrentNetwork = useStore((s) => s.setCurrentNetwork) + const loadNetworkConfig = useStore((s) => s.loadNetworkConfig) + const networkConfig = useStore((s) => s.networkConfig) useEffect(() => { - if (chainInfoOverrides) return + setCurrentNetwork(getCurrentChainId()) + loadNetworkConfig() + }, [loadNetworkConfig, setCurrentNetwork]) - const fetchConfig = async () => { - const file = await import( - `../../../configs/${NETWORK !== 'mainnet' ? 'osmo-test-5' : 'osmosis-1'}.ts` - ) - - const networkConfig: NetworkConfig = file.NETWORK_CONFIG - - setChainInfoOverrides({ - rpc: networkConfig.rpcUrl, - rest: networkConfig.restUrl, - chainID: networkConfig.name, - }) - setEnabledWallets(networkConfig.wallets) - } - - fetchConfig() - }) - - if (!chainInfoOverrides || !enabledWallets?.length) return null + const supportedChains = SUPPORTED_CHAINS.map((chain) => chain.chainId) return ( } - defaultChainId={chainInfoOverrides.chainID} - enabledWallets={enabledWallets} + defaultChainId={currentNetwork} + enabledWallets={[ + WalletID.Keplr, + WalletID.Xdefi, + WalletID.StationWallet, + WalletID.Leap, + WalletID.Cosmostation, + WalletID.KeplrMobile, + WalletID.CosmostationMobile, + ]} persistent renderLoader={() => (
diff --git a/src/components/common/DisplayCurrency/DisplayCurrency.tsx b/src/components/common/DisplayCurrency/DisplayCurrency.tsx index 1368c00..1c47e21 100644 --- a/src/components/common/DisplayCurrency/DisplayCurrency.tsx +++ b/src/components/common/DisplayCurrency/DisplayCurrency.tsx @@ -1,6 +1,5 @@ import { Coin } from '@cosmjs/stargate' import { AnimatedNumber } from 'components/common' -import { useEffect, useState } from 'react' import useStore from 'store' interface Props { @@ -21,15 +20,7 @@ export const DisplayCurrency = ({ const networkConfig = useStore((s) => s.networkConfig) const convertToDisplayCurrency = useStore((s) => s.convertToDisplayCurrency) const amount = convertToDisplayCurrency(coin) - const [displayCurrency, setDisplayCurrency] = useState( - networkConfig?.displayCurrency, - ) - - useEffect(() => { - if (!networkConfig) return - if (displayCurrency.denom !== networkConfig?.displayCurrency.denom) - setDisplayCurrency(networkConfig?.displayCurrency) - }, [networkConfig?.displayCurrency, displayCurrency.denom, networkConfig]) + const displayCurrency = networkConfig.displayCurrency if (!displayCurrency) return null diff --git a/src/components/common/Footer/Footer.tsx b/src/components/common/Footer/Footer.tsx index 46fe14f..2ef1b8e 100644 --- a/src/components/common/Footer/Footer.tsx +++ b/src/components/common/Footer/Footer.tsx @@ -1,6 +1,5 @@ import { WalletID } from '@marsprotocol/wallet-connector' import { SVG } from 'components/common' -import { FIELDS_FEATURE } from 'constants/appConstants' import { getCouncilLink } from 'libs/council' import { useTranslation } from 'react-i18next' import useStore from 'store' @@ -13,6 +12,8 @@ export const Footer = () => { const { t } = useTranslation() const client = useStore((s) => s.client) + const currentNetwork = useStore((s) => s.currentNetwork) + const networkConfig = useStore((s) => s.networkConfig) return (
diff --git a/src/components/common/Header/Header.tsx b/src/components/common/Header/Header.tsx index 4d3acee..2d4c769 100644 --- a/src/components/common/Header/Header.tsx +++ b/src/components/common/Header/Header.tsx @@ -1,13 +1,13 @@ import { WalletID } from '@marsprotocol/wallet-connector' import classNames from 'classnames' import { IncentivesButton, Settings, SVG } from 'components/common' -import { FIELDS_FEATURE } from 'constants/appConstants' import { getCouncilLink } from 'libs/council' import Link from 'next/link' import { useRouter } from 'next/router' import { useTranslation } from 'react-i18next' import useStore from 'store' +import { ChainSelect } from './ChainSelect' import { Connect } from './Connect' import styles from './Header.module.scss' @@ -15,6 +15,8 @@ export const Header = () => { const { t } = useTranslation() const router = useRouter() const client = useStore((s) => s.client) + const networkConfig = useStore((s) => s.networkConfig) + const currentNetwork = useStore((s) => s.currentNetwork) return (
@@ -33,7 +35,7 @@ export const Header = () => { > {t('global.redBank')} - {FIELDS_FEATURE && ( + {networkConfig.isFieldsEnabled && ( { )} @@ -57,6 +59,7 @@ export const Header = () => {
+
diff --git a/src/components/common/Header/IncentivesButton.tsx b/src/components/common/Header/IncentivesButton.tsx index 2f90886..7da03cf 100644 --- a/src/components/common/Header/IncentivesButton.tsx +++ b/src/components/common/Header/IncentivesButton.tsx @@ -35,7 +35,7 @@ export const IncentivesButton = () => { const otherAssets = useStore((s) => s.otherAssets) const userWalletAddress = useStore((s) => s.userWalletAddress) const unclaimedRewards = useStore((s) => s.userUnclaimedRewards) - const incentivesContractAddress = useStore((s) => s.networkConfig?.contracts.incentives) + const incentivesContractAddress = useStore((s) => s.networkConfig.contracts.incentives) const chainInfo = useStore((s) => s.chainInfo) const executeMsg = useStore((s) => s.executeMsg) diff --git a/src/components/common/Header/Settings.tsx b/src/components/common/Header/Settings.tsx index 37d4d35..6e71ec6 100644 --- a/src/components/common/Header/Settings.tsx +++ b/src/components/common/Header/Settings.tsx @@ -3,10 +3,11 @@ import { useQueryClient } from '@tanstack/react-query' import BigNumber from 'bignumber.js' import classNames from 'classnames' import { Button, NumberInput, SVG, Toggle, Tooltip } from 'components/common' -import { DISPLAY_CURRENCY_KEY, ENABLE_ANIMATIONS_KEY, FIELDS_FEATURE } from 'constants/appConstants' -import React, { useState } from 'react' +import { DISPLAY_CURRENCY_KEY, ENABLE_ANIMATIONS_KEY } from 'constants/appConstants' +import React, { useEffect, useState } from 'react' import { Trans, useTranslation } from 'react-i18next' import useStore from 'store' +import { State } from 'types/enums' import styles from './Settings.module.scss' @@ -18,6 +19,7 @@ export const Settings = () => { const slippage = useStore((s) => s.slippage) const networkConfig = useStore((s) => s.networkConfig) const currencyAssets = useStore((s) => s.currencyAssets) + const calculateExchangeRates = useStore((s) => s.calculateExchangeRates) const [customSlippage, setCustomSlippage] = useState(0) const [inputRef, setInputRef] = useState>() const [isCustom, setIsCustom] = useState(false) @@ -26,7 +28,7 @@ export const Settings = () => { const exchangeRates = useStore((s) => s.exchangeRates) const [displayCurrency, setDisplayCurrency] = useState( - networkConfig?.displayCurrency, + networkConfig.displayCurrency, ) const onInputChange = (value: number) => { @@ -67,7 +69,7 @@ export const Settings = () => { const changeDisplayCurrency = (denom: string) => { const selectedAsset = currencyAssets.find((asset) => asset.denom === denom) - if (!selectedAsset || !networkConfig || !exchangeRates?.length) return + if (!selectedAsset || !exchangeRates?.length) return const newDisplayCurrency = { denom: selectedAsset.denom, prefix: selectedAsset.prefix ?? '', @@ -76,14 +78,23 @@ export const Settings = () => { } const exchangeRate = exchangeRates.find((rate) => rate.denom === newDisplayCurrency.denom) - if (!exchangeRate) return + if (!exchangeRate && newDisplayCurrency.denom !== 'usd') return setDisplayCurrency(newDisplayCurrency) - useStore.setState({ networkConfig: { ...networkConfig, displayCurrency: newDisplayCurrency } }) - useStore.setState({ baseToDisplayCurrencyRatio: 1 / Number(exchangeRate.amount) }) + useStore.setState({ + networkConfig: { ...networkConfig, displayCurrency: newDisplayCurrency }, + exchangeRates: [], + exchangeRatesState: State.INITIALISING, + }) localStorage.setItem(DISPLAY_CURRENCY_KEY, JSON.stringify(newDisplayCurrency)) queryClient.invalidateQueries() + calculateExchangeRates() } + useEffect(() => { + if (networkConfig.displayCurrency && networkConfig.displayCurrency !== displayCurrency) + setDisplayCurrency(networkConfig.displayCurrency) + }, [networkConfig.displayCurrency, displayCurrency]) + if (status !== WalletConnectionStatus.Connected) return null return ( @@ -139,7 +150,7 @@ export const Settings = () => {
- {FIELDS_FEATURE && ( + {networkConfig.isFieldsEnabled && ( <>

{t('fields.settings')}

diff --git a/src/components/common/InputSlider/InputSlider.tsx b/src/components/common/InputSlider/InputSlider.tsx index fae4005..1273dcf 100644 --- a/src/components/common/InputSlider/InputSlider.tsx +++ b/src/components/common/InputSlider/InputSlider.tsx @@ -4,7 +4,6 @@ import BigNumber from 'bignumber.js' import { getLeverageRatio } from 'functions/fields' import { formatValue, roundToDecimals } from 'libs/parse' import throttle from 'lodash.throttle' -import React from 'react' import { useTranslation } from 'react-i18next' import colors from 'styles/_assets.module.scss' @@ -67,6 +66,7 @@ export const InputSlider = ({ // ------------------------- // Presentation // ------------------------- + const leverageRatio = getLeverageRatio(leverageMax, maxValue) const marksArray = minValue === 0 && maxValue === 100 diff --git a/src/components/common/Layout/Layout.tsx b/src/components/common/Layout/Layout.tsx index 818e0bc..d45b7ed 100644 --- a/src/components/common/Layout/Layout.tsx +++ b/src/components/common/Layout/Layout.tsx @@ -1,12 +1,12 @@ -import { useWalletManager, WalletConnectionStatus } from '@marsprotocol/wallet-connector' +import { useWallet, useWalletManager, WalletConnectionStatus } from '@marsprotocol/wallet-connector' import classNames from 'classnames' import { Footer, Header, MobileNav, TermsOfService } from 'components/common' import { FieldsNotConnected } from 'components/fields' import { RedbankNotConnected } from 'components/redbank' -import { SESSION_WALLET_KEY, TERMS_OF_SERVICE } from 'constants/appConstants' +import { TERMS_OF_SERVICE } from 'constants/appConstants' import { useAnimations } from 'hooks/data' import { useRouter } from 'next/router' -import React, { useEffect } from 'react' +import React, { useEffect, useState } from 'react' import useStore from 'store' type Props = { @@ -19,16 +19,20 @@ export const Layout = ({ children }: Props) => { const router = useRouter() const { status } = useWalletManager() + const currentNetwork = useStore((s) => s.currentNetwork) + const { wallets } = useWallet() + const [isConnected, setIsConnected] = useState(false) + const [wasConnectedBefore, setWasConnectedBefore] = useState(false) useAnimations() const enableAnimations = useStore((s) => s.enableAnimations) - const isConnected = status === WalletConnectionStatus.Connected const backgroundClasses = classNames('background', !isConnected && 'night') const vaultConfigs = useStore((s) => s.vaultConfigs) - const wasConnectedBefore = - localStorage.getItem(SESSION_WALLET_KEY) && - localStorage.getItem(SESSION_WALLET_KEY) !== '[]' && - status !== WalletConnectionStatus.Errored + + useEffect(() => { + setIsConnected(status === WalletConnectionStatus.Connected) + setWasConnectedBefore(!!wallets.find((w) => w.network.chainId === currentNetwork)) + }, [status, wallets, currentNetwork]) useEffect(() => { if (!isConnected) { diff --git a/src/components/common/MigrationInProgress/MigrationInProgress.module.scss b/src/components/common/MigrationInProgress/MigrationInProgress.module.scss new file mode 100644 index 0000000..1cde2bd --- /dev/null +++ b/src/components/common/MigrationInProgress/MigrationInProgress.module.scss @@ -0,0 +1,34 @@ +@import 'src/styles/master'; + +.container { + position: fixed; + left: 0; + top: 0; + z-index: 1; + right: 0; + bottom: 0; + display: grid; + place-items: center; + + .card { + max-width: min(rem-calc(500), 95vw); + @include padding(2, 0, 4, 0); + justify-content: center; + display: flex; + flex-wrap: wrap; + + .headline { + @include margin(4, 0); + @include typoLcaps; + text-align: center; + width: 100%; + } + + .text { + @include typoM; + @include margin(0, 0, 4); + text-align: center; + width: 100%; + } + } +} diff --git a/src/components/common/MigrationInProgress/MigrationInProgress.tsx b/src/components/common/MigrationInProgress/MigrationInProgress.tsx new file mode 100644 index 0000000..fb01a56 --- /dev/null +++ b/src/components/common/MigrationInProgress/MigrationInProgress.tsx @@ -0,0 +1,21 @@ +import { Card, CircularProgress } from 'components/common' +import { useTranslation } from 'react-i18next' + +import styles from './MigrationInProgress.module.scss' + +export const MigrationInProgress = () => { + const { t } = useTranslation() + + return ( + <> +
+ +

{t('common.migration.headline')}

+

{t('common.migration.info')}

+ +
+
+
+ + ) +} diff --git a/src/components/common/MobileNav/MobileNav.tsx b/src/components/common/MobileNav/MobileNav.tsx index 2c642fe..eee8cb0 100644 --- a/src/components/common/MobileNav/MobileNav.tsx +++ b/src/components/common/MobileNav/MobileNav.tsx @@ -1,7 +1,6 @@ import { WalletID } from '@marsprotocol/wallet-connector' import classNames from 'classnames' import { SVG } from 'components/common' -import { FIELDS_FEATURE } from 'constants/appConstants' import { getCouncilLink } from 'libs/council' import Link from 'next/link' import { useRouter } from 'next/router' @@ -14,6 +13,8 @@ export const MobileNav = () => { const { t } = useTranslation() const router = useRouter() const client = useStore((s) => s.client) + const networkConfig = useStore((s) => s.networkConfig) + const currentNetwork = useStore((s) => s.currentNetwork) return (