diff --git a/package.json b/package.json index 0d346def7..9f4611eca 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "mars-v2-frontend", - "version": "2.2.4", + "version": "2.3.0", "homepage": "./", "private": false, "license": "SEE LICENSE IN LICENSE FILE", @@ -20,11 +20,9 @@ ] }, "dependencies": { - "@cosmjs/cosmwasm-stargate": "^0.32.2", + "@cosmjs/cosmwasm-stargate": "^0.32.3", "@delphi-labs/shuttle-react": "^3.19.1", - "@keplr-wallet/cosmos": "^0.12.70", - "@splinetool/react-spline": "^2.2.6", - "@splinetool/runtime": "^1.0.55", + "@keplr-wallet/cosmos": "^0.12.74", "@tailwindcss/container-queries": "^0.1.1", "@tanstack/react-table": "^8.13.2", "@tippyjs/react": "^4.2.6", @@ -35,14 +33,14 @@ "lodash.debounce": "^4.0.8", "lodash.throttle": "^4.1.1", "moment": "^2.30.1", - "next": "^14.1.0", + "next": "^14.1.3", "react": "^18.2.0", "react-device-detect": "^2.2.3", "react-dom": "^18.2.0", "react-draggable": "^4.4.6", "react-helmet-async": "^2.0.4", "react-qr-code": "^2.0.12", - "react-router-dom": "^6.22.2", + "react-router-dom": "^6.22.3", "react-spring": "^9.7.3", "react-toastify": "^10.0.4", "react-use-clipboard": "^1.0.9", @@ -58,19 +56,19 @@ "@types/lodash.throttle": "^4.1.9", "@types/node": "^20.11.24", "@types/react": "18.2.61", - "@types/react-dom": "18.2.19", + "@types/react-dom": "18.2.21", "@types/react-helmet": "^6.1.11", "autoprefixer": "^10.4.17", "dotenv": "^16.4.5", "dotenv-cli": "^7.3.0", "eslint": "^8.57.0", - "eslint-config-next": "^14.1.0", + "eslint-config-next": "^14.1.3", "eslint-plugin-import": "^2.29.1", "husky": "^9.0.11", "identity-obj-proxy": "^3.0.0", "lint-staged": "^15.2.2", "prettier": "^3.2.5", - "prettier-plugin-tailwindcss": "^0.5.11", + "prettier-plugin-tailwindcss": "^0.5.12", "shelljs": "^0.8.5", "tailwindcss": "^3.4.1", "typescript": "5.3.3" diff --git a/public/favicon.svg b/public/favicon.svg index 61cec0dc9..b9c4d5ed1 100644 --- a/public/favicon.svg +++ b/public/favicon.svg @@ -1,29 +1,145 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/public/safari-pinned-tab.svg b/public/safari-pinned-tab.svg index 6d6896b38..4715467eb 100644 --- a/public/safari-pinned-tab.svg +++ b/public/safari-pinned-tab.svg @@ -1,247 +1,138 @@ - - - - -Created by potrace 1.14, written by Peter Selinger 2001-2017 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/public/tradingview.css b/public/tradingview.css index 8ba9b612a..b6f050ea4 100644 --- a/public/tradingview.css +++ b/public/tradingview.css @@ -330,6 +330,13 @@ button[class^='button-'][class*='secondary-']:hover { background-image: linear-gradient(0deg, var(--tv-background), transparent) !important; } +[class^='noWrapWrapper-'] * { + pointer-events: none !important; + border: none !important; + background: transparent !important; + outline: none !important; +} + html.theme-dark ::selection { background: var(--tv-background) !important; color: var(--tv-menu-text-hover) !important; diff --git a/src/components/Modals/v1/Deposit.tsx b/src/components/Modals/v1/Deposit.tsx index cb9000f29..42eee7efd 100644 --- a/src/components/Modals/v1/Deposit.tsx +++ b/src/components/Modals/v1/Deposit.tsx @@ -1,5 +1,7 @@ import { useCallback, useEffect, useMemo, useState } from 'react' +import AssetAmountSelectActionModal from 'components/Modals/AssetAmountSelectActionModal' +import DetailsHeader from 'components/Modals/LendAndReclaim/DetailsHeader' import WalletBridges from 'components/Wallet/WalletBridges' import { BN_ZERO } from 'constants/math' import useBaseAsset from 'hooks/assets/useBasetAsset' @@ -9,10 +11,7 @@ import useWalletBalances from 'hooks/useWalletBalances' import useStore from 'store' import { BNCoin } from 'types/classes/BNCoin' import { byDenom } from 'utils/array' -import { defaultFee } from 'utils/constants' import { BN } from 'utils/helpers' -import AssetAmountSelectActionModal from 'components/Modals/AssetAmountSelectActionModal' -import DetailsHeader from 'components/Modals/LendAndReclaim/DetailsHeader' interface Props { account: Account @@ -47,7 +46,7 @@ export default function Deposit(props: Props) { }, [v1Action, fundingAsset, close]) useEffect(() => { - if (BN(baseBalance).isLessThan(defaultFee.amount[0].amount)) { + if (BN(baseBalance).isZero()) { useStore.setState({ focusComponent: { component: } }) } }, [baseBalance]) diff --git a/src/components/Wallet/WalletBridges.tsx b/src/components/Wallet/WalletBridges.tsx index 504f46bd3..3f3400985 100644 --- a/src/components/Wallet/WalletBridges.tsx +++ b/src/components/Wallet/WalletBridges.tsx @@ -2,14 +2,15 @@ import { useShuttle } from '@delphi-labs/shuttle-react' import Image from 'next/image' import { useCallback, useEffect, useMemo } from 'react' +import WalletFetchBalancesAndAccounts from 'components/Wallet/WalletFetchBalancesAndAccounts' +import WalletSelect from 'components/Wallet/WalletSelect' import Button from 'components/common/Button' import FullOverlayContent from 'components/common/FullOverlayContent' import { ChevronRight } from 'components/common/Icons' import Text from 'components/common/Text' -import WalletFetchBalancesAndAccounts from 'components/Wallet/WalletFetchBalancesAndAccounts' -import WalletSelect from 'components/Wallet/WalletSelect' import { BRIDGES } from 'constants/bridges' import useBaseAsset from 'hooks/assets/useBasetAsset' +import useChainConfig from 'hooks/useChainConfig' import useCurrentWallet from 'hooks/useCurrentWallet' import useToggle from 'hooks/useToggle' import useWalletBalances from 'hooks/useWalletBalances' @@ -17,7 +18,6 @@ import useStore from 'store' import { byDenom } from 'utils/array' import { defaultFee } from 'utils/constants' import { BN } from 'utils/helpers' -import useChainConfig from 'hooks/useChainConfig' function Bridge({ name, url, image }: Bridge) { return ( diff --git a/src/components/Wallet/WalletConnectButton.tsx b/src/components/Wallet/WalletConnectButton.tsx index 68b0f38c6..1f7798789 100644 --- a/src/components/Wallet/WalletConnectButton.tsx +++ b/src/components/Wallet/WalletConnectButton.tsx @@ -23,7 +23,7 @@ export default function WalletConnectButton(props: Props) { const handleClick = useCallback(() => { const component = hasAgreedToTerms ? : - useStore.setState({ focusComponent: { component } }) + useStore.setState({ focusComponent: { component }, mobileNavExpanded: false }) }, [hasAgreedToTerms]) return ( diff --git a/src/components/Wallet/WalletConnecting.tsx b/src/components/Wallet/WalletConnecting.tsx index 8babc8c82..ffbb563a0 100644 --- a/src/components/Wallet/WalletConnecting.tsx +++ b/src/components/Wallet/WalletConnecting.tsx @@ -10,7 +10,6 @@ import useChainConfig from 'hooks/useChainConfig' import useCurrentWallet from 'hooks/useCurrentWallet' import useToggle from 'hooks/useToggle' import useStore from 'store' -import { getUrl } from 'utils/url' interface Props { providerId?: string @@ -54,7 +53,7 @@ export default function WalletConnecting(props: Props) { setIsConnecting(true) try { const response = await connect({ extensionProviderId, chainId: chainConfig.id }) - const cosmClient = await CosmWasmClient.connect(getUrl(chainConfig.endpoints.rpc)) + const cosmClient = await CosmWasmClient.connect(chainConfig.endpoints.rpc) const walletClient: WalletClient = { broadcast, cosmWasmClient: cosmClient, @@ -138,7 +137,7 @@ export default function WalletConnecting(props: Props) { setIsConnecting(true) try { await mobileConnect({ mobileProviderId, chainId: chainConfig.id }) - const cosmClient = await CosmWasmClient.connect(getUrl(chainConfig.endpoints.rpc)) + const cosmClient = await CosmWasmClient.connect(chainConfig.endpoints.rpc) const walletClient: WalletClient = { broadcast, cosmWasmClient: cosmClient, diff --git a/src/components/Wallet/WalletFetchBalancesAndAccounts.tsx b/src/components/Wallet/WalletFetchBalancesAndAccounts.tsx index e006fc759..c9ecd2391 100644 --- a/src/components/Wallet/WalletFetchBalancesAndAccounts.tsx +++ b/src/components/Wallet/WalletFetchBalancesAndAccounts.tsx @@ -79,8 +79,9 @@ function Content() { ]) if (isLoadingAccounts || isLoadingBalances) return - if (BN(baseBalance).isLessThan(defaultFee.amount[0].amount)) return + if (BN(baseBalance).isZero()) return if (accountIds && accountIds.length === 0 && !isV1) return + if (isV1) useStore.setState({ focusComponent: null }) return null } diff --git a/src/components/Wallet/WalletSelect.tsx b/src/components/Wallet/WalletSelect.tsx index 84cf34c88..e355cd276 100644 --- a/src/components/Wallet/WalletSelect.tsx +++ b/src/components/Wallet/WalletSelect.tsx @@ -58,7 +58,6 @@ export default function WalletSelect(props: Props) { const chainConfig = useChainConfig() const { extensionProviders, mobileProviders, mobileConnect } = useShuttle() const [qrCodeUrl, setQRCodeUrl] = useState('') - const address = useStore((s) => s.address) const [error, setError] = useState(props.error) const [isLoading, setIsLoading] = useState(false) const sortedExtensionProviders = extensionProviders.sort((a, b) => +b - +a) @@ -102,7 +101,7 @@ export default function WalletSelect(props: Props) { } useEffect(() => { - if (!address && !recentWallet) return + if (!recentWallet) return useStore.setState({ focusComponent: { component: , @@ -111,7 +110,7 @@ export default function WalletSelect(props: Props) { }, }, }) - }, [address, recentWallet]) + }, [recentWallet]) useEffect(() => { if (error?.message && error?.title) { diff --git a/src/components/Wallet/index.tsx b/src/components/Wallet/index.tsx index 7b70ca626..d343a3276 100644 --- a/src/components/Wallet/index.tsx +++ b/src/components/Wallet/index.tsx @@ -13,7 +13,7 @@ export default function Wallet() { const address = useStore((s) => s.address) useEffect(() => { - if (address) return + if (address && currentWallet?.account.address === address) return useStore.setState({ address: undefined, userDomain: undefined, diff --git a/src/components/account/AccountFund/AccountFundContent.tsx b/src/components/account/AccountFund/AccountFundContent.tsx index ac824c45a..a92d293fa 100644 --- a/src/components/account/AccountFund/AccountFundContent.tsx +++ b/src/components/account/AccountFund/AccountFundContent.tsx @@ -17,7 +17,6 @@ import useWalletBalances from 'hooks/useWalletBalances' import useStore from 'store' import { BNCoin } from 'types/classes/BNCoin' import { byDenom } from 'utils/array' -import { defaultFee } from 'utils/constants' import { getCapLeftWithBuffer } from 'utils/generic' import { BN } from 'utils/helpers' @@ -90,7 +89,7 @@ export default function AccountFundContent(props: Props) { }, [props.accountId, deposit, fundingAssets, isLending, props.isFullPage]) useEffect(() => { - if (BN(baseBalance).isLessThan(defaultFee.amount[0].amount)) { + if (BN(baseBalance).isZero()) { useStore.setState({ focusComponent: { component: } }) } }, [baseBalance]) diff --git a/src/components/account/AccountMenuContent.tsx b/src/components/account/AccountMenuContent.tsx index a2f081345..8b3711240 100644 --- a/src/components/account/AccountMenuContent.tsx +++ b/src/components/account/AccountMenuContent.tsx @@ -1,7 +1,7 @@ import classNames from 'classnames' import { useCallback } from 'react' -import { useLocation, useNavigate, useSearchParams } from 'react-router-dom' import { isMobile } from 'react-device-detect' +import { useLocation, useNavigate, useSearchParams } from 'react-router-dom' import WalletBridges from 'components/Wallet/WalletBridges' import AccountCreateFirst from 'components/account/AccountCreateFirst' @@ -12,15 +12,12 @@ import { Account, Plus, PlusCircled } from 'components/common/Icons' import Overlay from 'components/common/Overlay' import Text from 'components/common/Text' import useAccountIds from 'hooks/accounts/useAccountIds' -import useBaseAsset from 'hooks/assets/useBasetAsset' import useEnableAutoLendGlobal from 'hooks/localStorage/useEnableAutoLendGlobal' import useAccountId from 'hooks/useAccountId' import useAutoLend from 'hooks/useAutoLend' -import useCurrentWalletBalance from 'hooks/useCurrentWalletBalance' +import useHasFundsForTxFee from 'hooks/useHasFundsForTxFee' import useToggle from 'hooks/useToggle' import useStore from 'store' -import { defaultFee } from 'utils/constants' -import { BN } from 'utils/helpers' import { isNumber } from 'utils/parsers' import { getPage, getRoute } from 'utils/route' @@ -40,10 +37,9 @@ export default function AccountMenuContent(props: Props) { const [searchParams] = useSearchParams() const createAccount = useStore((s) => s.createAccount) - const baseAsset = useBaseAsset() const [showMenu, setShowMenu] = useToggle() const [isCreating, setIsCreating] = useToggle() - const transactionFeeCoinBalance = useCurrentWalletBalance(baseAsset.denom) + const hasFundsForTxFee = useHasFundsForTxFee() const [enableAutoLendGlobal] = useEnableAutoLendGlobal() const { enableAutoLendAccountId } = useAutoLend() @@ -51,13 +47,6 @@ export default function AccountMenuContent(props: Props) { const isAccountSelected = hasCreditAccounts && accountId && isNumber(accountId) && accountIds.includes(accountId) - const checkHasFunds = useCallback(() => { - return ( - transactionFeeCoinBalance && - BN(transactionFeeCoinBalance.amount).isGreaterThan(defaultFee.amount[0].amount) - ) - }, [transactionFeeCoinBalance]) - const performCreateAccount = useCallback(async () => { setShowMenu(false) setIsCreating(true) @@ -90,7 +79,7 @@ export default function AccountMenuContent(props: Props) { const handleCreateAccountClick = useCallback(() => { setShowMenu(!showMenu) - if (!checkHasFunds() && !hasCreditAccounts) { + if (!hasFundsForTxFee && !hasCreditAccounts) { useStore.setState({ focusComponent: { component: } }) return } @@ -98,7 +87,7 @@ export default function AccountMenuContent(props: Props) { useStore.setState({ focusComponent: { component: } }) return } - }, [checkHasFunds, hasCreditAccounts, setShowMenu, showMenu]) + }, [hasFundsForTxFee, hasCreditAccounts, setShowMenu, showMenu]) if (!address) return null diff --git a/src/components/common/Button/ActionButton.tsx b/src/components/common/Button/ActionButton.tsx index 49c5c022e..c27ef847d 100644 --- a/src/components/common/Button/ActionButton.tsx +++ b/src/components/common/Button/ActionButton.tsx @@ -18,7 +18,6 @@ export default function ActionButton(props: Props) { const defaultProps = { className, color, variant, size } const address = useStore((s) => s.address) const isV1 = useStore((s) => s.isV1) - const { data: accountIds } = useAccountIds(address || '') const selectedAccountId = useAccountId() @@ -29,7 +28,7 @@ export default function ActionButton(props: Props) { if (!address) return - if (accountIds && accountIds.length === 0) { + if (accountIds && accountIds.length === 0 && !isV1) { return ( @@ -14,16 +13,15 @@ function DefaultPageHead() { - - - + + + - {isMobile ? ( - - ) : ( - - )} + ) } diff --git a/src/components/common/LeverageSlider/index.tsx b/src/components/common/LeverageSlider/index.tsx index eb4f0ee42..56e226a80 100644 --- a/src/components/common/LeverageSlider/index.tsx +++ b/src/components/common/LeverageSlider/index.tsx @@ -66,8 +66,8 @@ function LeverageSlider(props: Props) { 'relative w-full appearance-none bg-transparent hover:cursor-pointer', '[&::-webkit-slider-runnable-track]:bg-white [&::-webkit-slider-runnable-track]:bg-opacity-20 [&::-webkit-slider-runnable-track]:h-[9px] [&::-webkit-slider-runnable-track]:rounded-lg', '[&::-moz-range-track]:bg-white [&::-moz-range-track]:bg-opacity-20 [&::-moz-range-track]:h-1 [&::-moz-range-track]:pb-[5px] [&::-moz-range-track]:rounded-lg', - '[&::-webkit-slider-thumb]:appearance-none [&::-webkit-slider-thumb]:-mt-1 [&::-webkit-slider-thumb]:w-[33px] [&::-webkit-slider-thumb]:h-4', - '[&::-moz-range-thumb]:appearance-none [&::-moz-range-thumb]:opacity-0 [&::-moz-range-thumb]:w-[33px] [&::-moz-range-thumb]:h-4', + '[&::-webkit-slider-thumb]:appearance-none [&::-webkit-slider-thumb]:bg-transparent [&::-webkit-slider-thumb]:-mt-1 [&::-webkit-slider-thumb]:w-[33px] [&::-webkit-slider-thumb]:h-4', + '[&::-moz-range-thumb]:appearance-none [&::-moz-range-thumb]:bg-transparent [&::-moz-range-thumb]:opacity-0 [&::-moz-range-thumb]:w-[33px] [&::-moz-range-thumb]:h-4', )} type='range' value={value.toFixed(2)} diff --git a/src/components/common/MigrationBanner.tsx b/src/components/common/MigrationBanner.tsx deleted file mode 100644 index 65ca62055..000000000 --- a/src/components/common/MigrationBanner.tsx +++ /dev/null @@ -1,47 +0,0 @@ -import Card from 'components/common/Card' -import { Cross, ExclamationMarkCircled } from 'components/common/Icons' -import Text from 'components/common/Text' -import { TextLink } from 'components/common/TextLink' -import { DEFAULT_SETTINGS } from 'constants/defaultSettings' -import { LocalStorageKeys } from 'constants/localStorageKeys' -import useLocalStorage from 'hooks/localStorage/useLocalStorage' -import useStore from 'store' -import { DocURL } from 'types/enums/docURL' - -export default function MigrationBanner() { - const [_, setMigrationBanner] = useLocalStorage( - LocalStorageKeys.MIGRATION_BANNER, - DEFAULT_SETTINGS.migrationBanner, - ) - - const showMigrationBanner = useStore((s) => s.migrationBanner) - - if (!showMigrationBanner) return null - return ( - -
- -
- - If you have funds on{' '} - - Mars v1, - - please withdraw them and deposit them on Mars v2 to migrate. - -
setMigrationBanner(false)} - > - -
-
- ) -} diff --git a/src/components/common/MobileNotSupported.tsx b/src/components/common/MobileNotSupported.tsx deleted file mode 100644 index b2c9dcae9..000000000 --- a/src/components/common/MobileNotSupported.tsx +++ /dev/null @@ -1,33 +0,0 @@ -import Spline from '@splinetool/react-spline' - -import Button from 'components/common/Button' -import Text from 'components/common/Text' -import { DocURL } from 'types/enums/docURL' - -export default function MobileNotSupported() { - return ( -
-
- - - Mars is not available on mobile - - - Mars doesn't support mobile devices yet, please visit us later or use a desktop - -
-
-
-
- ) -} diff --git a/src/components/header/ChainSelect.tsx b/src/components/header/ChainSelect.tsx index f67a64cba..b6c065b4f 100644 --- a/src/components/header/ChainSelect.tsx +++ b/src/components/header/ChainSelect.tsx @@ -85,6 +85,7 @@ export default function ChainSelect(props: Props) { setCurrentChainId(chainConfig.id) mutate(() => true) useStore.setState({ + mobileNavExpanded: false, chainConfig, isV1: false, client: undefined, @@ -114,6 +115,7 @@ export default function ChainSelect(props: Props) { setCurrentChainId(chainConfig.id) useStore.setState({ chainConfig, + mobileNavExpanded: false, }) } window.open(outpost?.url, outpost?.target) diff --git a/src/components/header/navigation/mobile/MobileNavigation.tsx b/src/components/header/navigation/mobile/MobileNavigation.tsx index 9cd4ee120..82f3e022e 100644 --- a/src/components/header/navigation/mobile/MobileNavigation.tsx +++ b/src/components/header/navigation/mobile/MobileNavigation.tsx @@ -1,6 +1,6 @@ import { useShuttle } from '@delphi-labs/shuttle-react' import classNames from 'classnames' -import { useCallback, useMemo } from 'react' +import { useCallback, useEffect, useMemo } from 'react' import { useLocation, useNavigate, useSearchParams } from 'react-router-dom' import AccountMenu from 'components/account/AccountMenu' @@ -38,8 +38,22 @@ export default function MobileNavigation(props: Props) { const menu = useMemo(() => menuTree(walletId, chainConfig), [walletId, chainConfig, menuTree]) + useEffect(() => { + if (mobileNavExpanded) { + document.body.classList.add('h-screen-full', 'overflow-hidden') + } else { + document.body.classList.remove('h-screen-full', 'overflow-hidden') + } + + return () => { + document.body.classList.remove('h-screen-full', 'overflow-hidden') + } + }, [mobileNavExpanded]) + const selectPage = useCallback( (page: Page) => { + window.scrollTo(0, 0) + if (typeof window !== 'undefined') setTimeout(() => window.scrollTo(0, 0), 200) useStore.setState({ mobileNavExpanded: false }) if (page.includes('http')) { window.open(page, '_blank') @@ -53,7 +67,7 @@ export default function MobileNavigation(props: Props) { return (