diff --git a/package.json b/package.json index 31e7006..c99916b 100644 --- a/package.json +++ b/package.json @@ -22,7 +22,7 @@ "@cosmjs/launchpad": "^0.27.1", "@cosmjs/proto-signing": "^0.29.5", "@cosmjs/stargate": "^0.29.5", - "@marsprotocol/wallet-connector": "^1.3.0", + "@marsprotocol/wallet-connector": "^1.4.2", "@material-ui/core": "^4.12.4", "@material-ui/icons": "^4.11.3", "@ramonak/react-progress-bar": "^5.0.3", diff --git a/sentry.client.config.js b/sentry.client.config.js deleted file mode 100644 index aa866db..0000000 --- a/sentry.client.config.js +++ /dev/null @@ -1,19 +0,0 @@ -// This file configures the initialization of Sentry on the browser. -// The config you add here will be used whenever a page is visited. -// https://docs.sentry.io/platforms/javascript/guides/nextjs/ - -import * as Sentry from '@sentry/nextjs' - -const SENTRY_DSN = process.env.SENTRY_DSN || process.env.NEXT_PUBLIC_SENTRY_DSN - -Sentry.init({ - environment: process.env.NEXT_PUBLIC_SENTRY_ENV, - dsn: SENTRY_DSN, - // Adjust this value in production, or use tracesSampler for greater control - tracesSampleRate: 0.5, - // ... - // Note: if you want to override the automatic release value, do not set a - // `release` value here - use the environment variable `SENTRY_RELEASE`, so - // that it will also get attached to your source maps - enabled: process.env.NODE_ENV !== 'development', -}) diff --git a/sentry.properties b/sentry.properties deleted file mode 100644 index 5ab042b..0000000 --- a/sentry.properties +++ /dev/null @@ -1,4 +0,0 @@ -defaults.url=https://sentry.io/ -defaults.org=delphi-mars -defaults.project=mars-dapp -cli.executable=../../../.npm/_npx/a8388072043b4cbc/node_modules/@sentry/cli/bin/sentry-cli diff --git a/sentry.server.config.js b/sentry.server.config.js deleted file mode 100644 index 320b83f..0000000 --- a/sentry.server.config.js +++ /dev/null @@ -1,18 +0,0 @@ -// This file configures the initialization of Sentry on the server. -// The config you add here will be used whenever the server handles a request. -// https://docs.sentry.io/platforms/javascript/guides/nextjs/ - -import * as Sentry from '@sentry/nextjs' - -const SENTRY_DSN = process.env.SENTRY_DSN || process.env.NEXT_PUBLIC_SENTRY_DSN - -Sentry.init({ - dsn: SENTRY_DSN, - // Adjust this value in production, or use tracesSampler for greater control - tracesSampleRate: 0.5, - // ... - // Note: if you want to override the automatic release value, do not set a - // `release` value here - use the environment variable `SENTRY_RELEASE`, so - // that it will also get attached to your source maps - enabled: process.env.NODE_ENV !== 'development', -}) diff --git a/src/components/common/Button/Button.tsx b/src/components/common/Button/Button.tsx index 41a8165..bec03ae 100644 --- a/src/components/common/Button/Button.tsx +++ b/src/components/common/Button/Button.tsx @@ -1,7 +1,6 @@ import classNames from 'classnames' import { CircularProgress } from 'components/common' -import React from 'react' -import { ReactNode } from 'react' +import React, { ReactNode } from 'react' import styles from './Button.module.scss' @@ -46,7 +45,7 @@ export const Button = React.forwardRef( styles[size], styles[color], styles[variant], - disabled && styles.disabled, + (disabled || showProgressIndicator) && styles.disabled, className, ) return ( diff --git a/src/components/common/ErrorMessage/ErrorMessage.module.scss b/src/components/common/ErrorMessage/ErrorMessage.module.scss new file mode 100644 index 0000000..439e202 --- /dev/null +++ b/src/components/common/ErrorMessage/ErrorMessage.module.scss @@ -0,0 +1,18 @@ +@import 'src/styles/master'; + +.errorMessage { + text-align: left; + @include margin(2, 0, -2); + display: block; + width: 100%; + @include typoXS; + color: $colorInfoWarning; + + &.center { + text-align: center; + } + + &.right { + text-align: right; + } +} diff --git a/src/components/common/ErrorMessage/ErrorMessage.tsx b/src/components/common/ErrorMessage/ErrorMessage.tsx new file mode 100644 index 0000000..2a859cf --- /dev/null +++ b/src/components/common/ErrorMessage/ErrorMessage.tsx @@ -0,0 +1,14 @@ +import classNames from 'classnames' + +import styles from './ErrorMessage.module.scss' + +interface Props { + errorMessage?: string + alignment?: 'left' | 'center' | 'right' +} + +export const ErrorMessage = (props: Props) => { + const classes = classNames(styles.errorMessage, props.alignment && styles[props.alignment]) + + return props.errorMessage ?

{props.errorMessage}

: null +} diff --git a/src/components/common/Header/IncentivesButton.module.scss b/src/components/common/Header/IncentivesButton.module.scss index d6bc8e1..7343eff 100644 --- a/src/components/common/Header/IncentivesButton.module.scss +++ b/src/components/common/Header/IncentivesButton.module.scss @@ -220,15 +220,6 @@ button { width: 100%; } - - .error { - @include margin(2, 0, 0); - @include typoS; - width: 100%; - text-align: center; - font-weight: $fontWeightSemibold; - color: $colorInfoLoss; - } } } diff --git a/src/components/common/Header/IncentivesButton.tsx b/src/components/common/Header/IncentivesButton.tsx index dc55f94..b7f6b26 100644 --- a/src/components/common/Header/IncentivesButton.tsx +++ b/src/components/common/Header/IncentivesButton.tsx @@ -1,7 +1,15 @@ import { ChainInfoID, SimpleChainInfoList, TxBroadcastResult } from '@marsprotocol/wallet-connector' import { useQueryClient } from '@tanstack/react-query' import classNames from 'classnames' -import { AnimatedNumber, Button, DisplayCurrency, SVG, Tooltip, TxLink } from 'components/common' +import { + AnimatedNumber, + Button, + DisplayCurrency, + ErrorMessage, + SVG, + Tooltip, + TxLink, +} from 'components/common' import { MARS_DECIMALS, MARS_SYMBOL } from 'constants/appConstants' import { getClaimUserRewardsMsgOptions } from 'functions/messages' import { useEstimateFee } from 'hooks/queries' @@ -36,6 +44,7 @@ export const IncentivesButton = () => { // --------------- const [showDetails, setShowDetails] = useState(false) const [disabled, setDisabled] = useState(true) + const [fetching, setFetching] = useState(false) const [submitted, setSubmitted] = useState(false) const [response, setResponse] = useState() const [error, setError] = useState() @@ -53,6 +62,7 @@ export const IncentivesButton = () => { const onClickAway = useCallback(() => { setShowDetails(false) setResponse(undefined) + setError(undefined) }, []) useEffect(() => { @@ -64,12 +74,22 @@ export const IncentivesButton = () => { return getClaimUserRewardsMsgOptions() }, [hasUnclaimedRewards]) - const { data: fee } = useEstimateFee({ + const { data: fee, error: feeError } = useEstimateFee({ msg: txMsgOptions?.msg, funds: [], contract: incentivesContractAddress, }) + if (feeError && error !== feeError && !fee) { + setError(feeError as string) + } + + useEffect(() => { + const isFetching = submitted || (!fee && !response && hasUnclaimedRewards) + if (fetching === isFetching) return + setFetching(isFetching) + }, [submitted, fetching, fee, response, hasUnclaimedRewards]) + useEffect(() => { if (error) { setDisabled(!hasUnclaimedRewards) @@ -186,8 +206,8 @@ export const IncentivesButton = () => { )}
diff --git a/src/components/common/InputSection/InputSection.module.scss b/src/components/common/InputSection/InputSection.module.scss index 73ecbac..5b69114 100644 --- a/src/components/common/InputSection/InputSection.module.scss +++ b/src/components/common/InputSection/InputSection.module.scss @@ -153,6 +153,7 @@ display: flex; justify-content: center; margin-bottom: space(3); + flex-wrap: wrap; } } diff --git a/src/components/common/InputSection/InputSection.tsx b/src/components/common/InputSection/InputSection.tsx index 48adcbd..30562d9 100644 --- a/src/components/common/InputSection/InputSection.tsx +++ b/src/components/common/InputSection/InputSection.tsx @@ -18,6 +18,7 @@ interface Props { disabled?: boolean amountUntilDepositCap: number activeView: ViewType + walletBalance: number inputCallback: (value: number) => void onEnterHandler: () => void setAmountCallback: (value: number) => void @@ -33,6 +34,7 @@ export const InputSection = ({ disabled, amountUntilDepositCap, activeView, + walletBalance, inputCallback, onEnterHandler, setAmountCallback, @@ -90,15 +92,14 @@ export const InputSection = ({ useEffect( () => { + if (asset.denom !== baseCurrency.denom || !checkForMaxValue) return if ( - amount >= maxUsableAmount && - asset.denom === baseCurrency.denom && - !depositWarning && - checkForMaxValue + (activeView === ViewType.Repay && walletBalance <= amount) || + (activeView === ViewType.Deposit && amount >= maxUsableAmount) ) { - setDepositWarning(true) + if (!depositWarning) setDepositWarning(true) } else { - setDepositWarning(false) + if (depositWarning) setDepositWarning(false) } }, // eslint-disable-next-line react-hooks/exhaustive-deps [sliderValue, amount, maxUsableAmount], diff --git a/src/components/common/MobileNav/MobileNav.module.scss b/src/components/common/MobileNav/MobileNav.module.scss index 8501305..ec472c0 100644 --- a/src/components/common/MobileNav/MobileNav.module.scss +++ b/src/components/common/MobileNav/MobileNav.module.scss @@ -27,7 +27,7 @@ opacity: 0.4; &.active { - filter: grayscale(0); + filter: unset; opacity: 1; } @@ -37,9 +37,23 @@ @include typoXScaps; } - svg { + .icon { width: rem-calc(50); - height: auto; + height: rem-calc(50); + display: block; + + svg { + width: 100%; + height: auto; + } + + &.redBank { + background: url('../../../images/redbank.svg'); + } + + &.farm { + background: url('../../../images/farm.svg'); + } } } } diff --git a/src/components/common/MobileNav/MobileNav.tsx b/src/components/common/MobileNav/MobileNav.tsx index 45d8f0e..7767bf9 100644 --- a/src/components/common/MobileNav/MobileNav.tsx +++ b/src/components/common/MobileNav/MobileNav.tsx @@ -20,11 +20,14 @@ export const MobileNav = () => { passHref className={classNames(styles.nav, !router.pathname.includes('farm') && styles.active)} > - +
{t('global.redBank')} + - +
+ +
{t('global.council')}
{FIELDS_FEATURE && ( @@ -33,7 +36,7 @@ export const MobileNav = () => { passHref className={classNames(styles.nav, router.pathname.includes('farm') && styles.active)} > - +
{t('global.fields')} )} diff --git a/src/components/common/Tutorial/Tutorial.tsx b/src/components/common/Tutorial/Tutorial.tsx index f7413a8..f0067ca 100644 --- a/src/components/common/Tutorial/Tutorial.tsx +++ b/src/components/common/Tutorial/Tutorial.tsx @@ -52,11 +52,14 @@ export const Tutorial = (props: Props) => { }, [tutorialStep, props.step]) const hideTutorial = () => { - localStorage.setItem( - props.type === 'fields' ? FIELDS_TUTORIAL_KEY : RED_BANK_TUTORIAL_KEY, - 'true', - ) + if (props.type === 'fields') { + localStorage.setItem(FIELDS_TUTORIAL_KEY, 'true') + return + } + localStorage.setItem(RED_BANK_TUTORIAL_KEY, 'true') + useStore.setState({ showRedBankTutorial: false }) } + const handleButtonClick = () => { if (props.step === 3) hideTutorial() setTutorialStep(props.type) diff --git a/src/components/common/TxModal/Action.module.scss b/src/components/common/TxModal/Action.module.scss index 150ae1c..288de50 100644 --- a/src/components/common/TxModal/Action.module.scss +++ b/src/components/common/TxModal/Action.module.scss @@ -72,12 +72,6 @@ opacity: 0.4; margin-bottom: space(9); } - - .actionButton { - display: flex; - justify-content: center; - margin-bottom: space(3); - } } .feeTooltipContent { diff --git a/src/components/common/TxModal/Action.tsx b/src/components/common/TxModal/Action.tsx index 9a48ed4..9e60472 100644 --- a/src/components/common/TxModal/Action.tsx +++ b/src/components/common/TxModal/Action.tsx @@ -8,6 +8,7 @@ import { Card, ConnectButton, DisplayCurrency, + ErrorMessage, InputSection, } from 'components/common' import { findByDenom } from 'functions' @@ -44,6 +45,7 @@ interface Props { totalBorrowBaseCurrencyAmount: number actionButtonSpec: ModalActionButton submitted: boolean + feeError?: string txFee?: Coin activeView: ViewType denom: string @@ -64,6 +66,7 @@ export const Action = ({ totalBorrowBaseCurrencyAmount, actionButtonSpec, submitted, + feeError, txFee, activeView, denom, @@ -313,22 +316,22 @@ export const Action = ({ if (microValue >= maxUsableAmount) microValue = maxUsableAmount setAmountCallback(Number(formatValue(microValue, 0, 0, false, false, false, false, false))) - setCapHit(amount > amountUntilDepositCap) + setCapHit(amount > amountUntilDepositCap && activeView === ViewType.Deposit) } const produceTabActionButton = () => { return ( -
diff --git a/src/components/redbank/RedbankAction/RedbankAction.tsx b/src/components/redbank/RedbankAction/RedbankAction.tsx index 7de97ae..17bbc47 100644 --- a/src/components/redbank/RedbankAction/RedbankAction.tsx +++ b/src/components/redbank/RedbankAction/RedbankAction.tsx @@ -120,7 +120,7 @@ export const RedbankAction = React.memo( } }, [activeView, amount, redBankContractAddress, denom, isMax, userBalances]) - const { data: fee } = useEstimateFee({ + const { data: fee, error: feeError } = useEstimateFee({ msg: txMsgOptions?.msg, funds: activeView === ViewType.Deposit || activeView === ViewType.Repay @@ -131,8 +131,8 @@ export const RedbankAction = React.memo( const produceActionButtonSpec = (): ModalActionButton => { return { - disabled: !Number(amount) || amount === 0 || typeof fee === 'undefined' || submitted, - fetching: !!Number(amount) && amount > 0 && typeof fee === 'undefined' && !capHit, + disabled: amount === 0 || capHit, + fetching: (amount > 0 && typeof fee === 'undefined') || submitted, text: t(`redbank.${activeView.toLowerCase()}`), clickHandler: handleAction, color: 'primary', @@ -157,10 +157,14 @@ export const RedbankAction = React.memo( // @ts-ignore funds: txMsgOptions.funds || [], contract: redBankContractAddress, - fee, + fee: fee, }) - setResponse(res) + if (res?.response.code !== 0) { + setError(res?.rawLogs) + } else { + setResponse(res) + } } catch (error) { const e = error as { message: string } setError(e.message as string) @@ -248,6 +252,7 @@ export const RedbankAction = React.memo( ) : ( { } const result = await client.simulate(simulateOptions) - return result.success - ? { - amount: result.fee ? result.fee.amount : [], - gas: new BigNumber(result.fee ? result.fee.gas : 0) - .multipliedBy(gasAdjustment) - .toFixed(0), - } - : null - } catch { - return null + + if (result.success) { + return { + amount: result.fee ? result.fee.amount : [], + gas: new BigNumber(result.fee ? result.fee.gas : 0) + .multipliedBy(gasAdjustment) + .toFixed(0), + } + } + throw result.error + } catch (e) { + throw e } }, { diff --git a/src/images/farm.svg b/src/images/farm.svg new file mode 100644 index 0000000..9550936 --- /dev/null +++ b/src/images/farm.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/images/redbank.svg b/src/images/redbank.svg new file mode 100644 index 0000000..075a959 --- /dev/null +++ b/src/images/redbank.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/pages/_document.tsx b/src/pages/_document.tsx index 4eda6ee..d898ebe 100644 --- a/src/pages/_document.tsx +++ b/src/pages/_document.tsx @@ -18,7 +18,7 @@ export default function Document() { - + { return } + const vaultCap = (availableVault.vaultCap?.max || 0) * VAULT_DEPOSIT_BUFFER + const isVaultCapReached = availableVault.vaultCap + ? availableVault.vaultCap.used + position.values.total > vaultCap + : false + const isDisabled = position.values.total === 0 || isVaultCapReached + return ( router.replace('/farm')} - tooltip={'placeholder'} + tooltip={ + <> + {t('fields.tooltips.editPosition')} +
+
+ {t('fields.tooltips.apy.available')} + + } > @@ -41,11 +55,11 @@ const Create = () => {