From 9a52770140626f1f1de0408b9551c8789bd0b795 Mon Sep 17 00:00:00 2001 From: Andrew Schmidt Date: Mon, 10 Oct 2022 23:49:14 -0500 Subject: [PATCH 01/82] feat: paraswap feature updates (#1218) * fix: repay type select styling * fix: remove repay with collateral warning * feat: add slippage components * feat: add slippage select to tx modal * feat: update asset input styling * feat: redesign repay with collateral modal * run i18n * removed psp warning * fix: paraswap icon * fix: input box alignment * feat: add price impact tooltip * fix: slippage select styling * fix: update collateral repay modal styling * fix: don't allow frozen assets to be used as collateral repay * fix: match toggle button style from repay modal * fix: match bridge and faucet button styles with emode button * feat: update collateral swap modal up to design specs * chore: run i18n * fix: handle collateral balance being less than the debt amount when trying to repay * Automated cache update [skip cypress] * Automated cache update [skip cypress] * Automated cache update [skip cypress] * fix: remove weird stuff (#958) * fix: switch default env from staging to prod (#961) * fix: default env from staging to prod * feat: update env setup in CONTIRUBTING.md * fix: token click area (#963) * fix: token click area * fix: update some ui and build deps * fix: update babel loader * cleanup: remove caching service for stake (#937) * cleanup: remove caching service for stake * fix: remove unused var * fix: Use selected slippage when getting swap parameters instead of hard coded 1% * fix: handle repay collateral amount being less than the debt amount * chore: i18n * fix: reverting changes, matching latest design * fix: remove exluded dexes for testing * fix: remove console log * fix: don't exclude any pools from paraswap * chore: i18n * fix: show correct asset name in collateral repay actions when approving * feat: wip * feat: wip * feat: wip * feat: separate component for tx details * feat: continuing with design updates * chore: run i18n * feat: add supply balances after swap section * feat: refactor collateral repay * feat: update warning text * fix: warning styling * chore: i18n * chore: i18n * chore: i18n * fix: reset state when no there is invalid swap data * fix: remove console log * fix: added change handler back in so we can reset the state on asset change * fix: console logs * fix: cleanup swap/repay * feat: refactor swap and repay logic feat: refactor swap logic * chore: merge main (#1194) * chore: automated cache update [skip cypress] * feat: add maticx icons (#1106) * e2e - refactor (#1131) * init commands * test version with commands without timeouts * move all methods to CY commands * fix matic e-mode * add documentation * add cy.wait for max amount Co-authored-by: Nikita Boakrev * chore: automated cache update [skip cypress] * chore: add prettier commands (#1142) * chore: add prettierignore * chore: add prettier commands * chore: add combined linting commands * chore: run yarn lint:fix * chore: update lint-staged * chore: update contributors * chore: typo * chore: typos * chore: add license field * chore: automated cache update [skip cypress] * fix: lint-staged (#1145) * chore: automated cache update [skip cypress] * feat: refactor frozen warnings (#1141) * feat: improve frozen warning mappings * fix: clean up logic and make warnings responsive to frozen status * fix: trans tag wrapping * fix: simplify MarketWarning component * chore: run i18n * remove fantom market from CI while it frozen Co-authored-by: Nikita Boakrev * chore: automated cache update [skip cypress] * chore: automated cache update [skip cypress] * chore(i18n): synchronize translations from crowdin [skip cypress] * chore: automated cache update [skip cypress] * chore: automated cache update [skip cypress] * feat: removed warnings related to eth borrow being disabled (#1113) * feat: removed warnings related to eth borrow being disabled * chore: prettier * chore: fix missing param * turn on eth tests Co-authored-by: Mark Hinschberger Co-authored-by: Nikita Boakrev * feat: add custom error page templates (#1094) * chore: stub out the minimal error pages * feat: add custom 404 page * chore: i18n * chore: add 500 page * chore: cleanup * chore: remove img from 500 * chore: use native img tag * chore: add light/dark mode graphics * chore: more UI updates * chore: 500 page ideas * chore: 500 error updates * chore: test error boundary component in prod * chore: ignore for build (temp) * chore: remove error boundary component * chore: style updates * chore: remove throw * chore: merge branch 'main' into feat/error-pages * chore: use lint-staged pre-commit * fix: build fix * chore: post-merge cleanup * chore: post-merge cleanup * chore(i18n): synchronize translations from crowdin [skip cypress] * feat: warn about governance in borrow modal (#999) * chore(i18n): synchronize translations from crowdin [skip cypress] * chore(i18n): synchronize translations from crowdin [skip cypress] * fix: btc.b symbol (#1152) * fix-tests (#1159) Co-authored-by: Nikita Boakrev * fix: use correct blocktime (#1147) * fix: change item name (#1148) * chore: automated cache update [skip cypress] * chore: sort imports (#1127) Co-authored-by: Drew Cook * chore: revise contributing doc and PR template (#1158) * chore: update contributing doc * chore: lint * chore: add default PR template + labels * chore: move to be used as default * chore: lowercase labels * fix: typo * chore: add project, remove frontmatter from pr template * chore: projects fix * chore: remove projects from frontmatter * chore: update fork link * chore: use js code block * feat: add in wallet fork config section * feat: graph improvements (#1102) * chore: refactor graph component hierarchy * feat: initial component for graph time range selector * refactor: moved global style for ToggleButton to a styled component * fix: enforce a selection * fix: styles * fix: bad merge * refactor: move data fetching to graph containers * feat: handle selected time range in parent component * feat: initial hookup of time range selector * feat: removed 'Max' time selection from graphs * feat: add in loading/error states * feat: clean up graph styles * feat: add supply rate * chore: remove log * chore: add circle over supply rate * chore: supply APR logic * chore: show time/legend when loading * chore: test error state * chore: shorter graphs * fix: build * chore: remove unused component * chore: remove time selector from IRM graph * chore: add style changes to graphs * chore: i18n * chore: bump material and add react-transition-group * chore: more style updates * chore: more styling * feat: add interest rate strategy link (#1124) * feat: add link to interest rate strategy * fix: remove unnecessary typography tag * chore: i18n * chore: more styling * chore: cleanup * chore: removed TODO comment * fix: handle formatting dates behind UTC time, and don't include time for 6m and 1y time range * fix: remove console logs * fix: remove supply APY from interest rate model graph (#1160) * chore: log cleanup * chore: show % * fix: remove horizontal divider for util rate * chore: update eslintignore * fix: remove unused file * fix: re-render issue with loading spinner * chore: remove unused package * chore: hide charts for v3 and comment about bug * chore: remove log * feat: temporarily disable charts for polygon v2 Co-authored-by: Mark Grothe Co-authored-by: Andrew Schmidt * chore: add QA verification checklist item for reviews (#1175) * fix: remove duplicate warning (#1173) * chore(i18n): synchronize translations from crowdin [skip cypress] * chore: automated cache update [skip cypress] * chore: automated cache update [skip cypress] * chore: automated cache update [skip cypress] * chore: automated cache update [skip cypress] * fix(swap-modal): open swap modal on mobile (#1181) * chore: automated cache update [skip cypress] * fix: correct bridge message (#1168) * fix: you don't bridge ETH assets * fix: update po file * fix: split messages in two * chore: add @lidofinance/web3-ledgerhq-frame-connector (#1157) * fix: debt ceiling wording (#1171) * fix: tooltip wording * fix: use correct warning component and sort imports * chore: run i18n Co-authored-by: Drew Cook * feat: market search (#1174) * feat: wip * feat: wip * feat: wip * feat(search): styled to match designs * chore: i18n * feat(search): filter list based on search term * chore: lint * feat(search): auto focus on mobile, hide clear button when inactive * feat(search): search on underlying address * feat(search): show no results message * chore: i18n * feat(search): give input focus on clearing * refactor: asset list titles * feat(search): renamed file, cleanup * feat(search): cleanup * refactor: moved files * feat(search): set font size to 16px on mobile to prevent auto zooming * chore: small cleanup * feat(search): focus input on clear on mobile, make code consistent * chore: i18n * feat(search): adjust no results message for mobile * feat: graph improvements (#1102) * chore: refactor graph component hierarchy * feat: initial component for graph time range selector * refactor: moved global style for ToggleButton to a styled component * fix: enforce a selection * fix: styles * fix: bad merge * refactor: move data fetching to graph containers * feat: handle selected time range in parent component * feat: initial hookup of time range selector * feat: removed 'Max' time selection from graphs * feat: add in loading/error states * feat: clean up graph styles * feat: add supply rate * chore: remove log * chore: add circle over supply rate * chore: supply APR logic * chore: show time/legend when loading * chore: test error state * chore: shorter graphs * fix: build * chore: remove unused component * chore: remove time selector from IRM graph * chore: add style changes to graphs * chore: i18n * chore: bump material and add react-transition-group * chore: more style updates * chore: more styling * feat: add interest rate strategy link (#1124) * feat: add link to interest rate strategy * fix: remove unnecessary typography tag * chore: i18n * chore: more styling * chore: cleanup * chore: removed TODO comment * fix: handle formatting dates behind UTC time, and don't include time for 6m and 1y time range * fix: remove console logs * fix: remove supply APY from interest rate model graph (#1160) * chore: log cleanup * chore: show % * fix: remove horizontal divider for util rate * chore: update eslintignore * fix: remove unused file * fix: re-render issue with loading spinner * chore: remove unused package * chore: hide charts for v3 and comment about bug * chore: remove log * feat: temporarily disable charts for polygon v2 Co-authored-by: Mark Grothe Co-authored-by: Andrew Schmidt * chore: add QA verification checklist item for reviews (#1175) * fix: remove duplicate warning (#1173) * chore: i18n * chore: i18n * refactor: renamed prop * feat(search): added debounce to the input change handler * chore(i18n): synchronize translations from crowdin [skip cypress] * chore: automated cache update [skip cypress] * chore: automated cache update [skip cypress] * chore: automated cache update [skip cypress] * chore: automated cache update [skip cypress] * fix(swap-modal): open swap modal on mobile (#1181) * chore: automated cache update [skip cypress] * fix: correct bridge message (#1168) * fix: you don't bridge ETH assets * fix: update po file * fix: split messages in two * chore: i18n * fix: duplicate imports * chore: i18n * chore: i18n Co-authored-by: Drew Cook Co-authored-by: Andrew Schmidt Co-authored-by: Crowdin bot Co-authored-by: Cache bot Co-authored-by: Lukas * chore: automated cache update [skip cypress] * chore: lint and pre-commit updates (#1169) * chore: order imports * chore: add files from i18n in pre-commit Co-authored-by: Drew Cook * chore: automated cache update [skip cypress] * chore: automated cache update [skip cypress] * chore: automated cache update [skip cypress] * chore(i18n): synchronize translations from crowdin [skip cypress] * chore: automated cache update [skip cypress] * chore: automated cache update [skip cypress] * chore: automated cache update [skip cypress] * chore: automated cache update [skip cypress] * chore: use a fallback IPFS gateway for dynamic proposals (#1182) * chore: use a fallback IPFS gateway for dynamic proposals * fix: typo * fix: lint (#1185) * chore: update 404 image (#1184) * chore: update 404 image * chore: remove-brackets * fix tests Co-authored-by: Nikita Boakrev * feat: add watch mode only wallet address (#1178) * feat(WalletWidget): added Alert component * feat(mockWalletAddressContext): added mockWalletAddressContext * feat(WalletSelector): added input to wallet selector for mock address * feat(WatchOnlyModeTooltip): added WatchOnlyMode tooltip * feat(WalletSelector): use web3 context for set mock adddress * chore(WalletWidget): removed console log * feat(WalletWidget): added warning icon * chore: updated message.js * chore: updated message.js * feat(Web3Provider): updated condition to render Wallet Modal * feat(TxActionsWrapper): render warning text when using mockAddress * chore: updated messages * feat(WalletSelector): use utils to check if mock address is valid * feat(TxActionsWrapper): disabled button if mockAddress is present * chore: updated message.js * feat: do not render ChangeNetworkWarning when mockAddress is present * feat(WalletWidget): added buttons to switch network and disconnect * feat(WalletWidget): adjusted margin * chore(WalletWidget): removed Disconnect Wallet button * chore: removed temp value for max amount to borrow * chore: updated messages.po * chore: updated markdown to trigger git delta * chore: reverted changes to Code of Conduct md * chore: updated message.js * chore: unimport WatchOnlyModeToolTip to ensure message.js is updated * chore(cypress.config): removed eslint-disable * chore(WalletSelector): re-import WatchOnlyModeToolTip * feat(WalletWidget): set wallet widget to close when clicking switch wallet * feat(Web3Provider): when connect wallet, check and remove mock address * feat: if mockAddress is present, do not render approval help text and button * feat: on mobile, if mockAddress is present, render Close menu icon * feat(WalletWidget): update styling for warning text in mobile * feat(WalletWidget): on mobile, render CTAs at list buttom * feat(WalletWidget): add color styling to CTAs * feat(WalletWidget): styling for avatar icon on mobile * chore: updated message.js * feat(WalletWidget): update styling for warning icon background * feat(WalletWidget): use hideWalletAccountText variable to determine mockAddress styling * chore(WalletWidget): removed un-used improt * feat(WalletWidget): fine-tune warning icon color * feat(WalletWidget): updated styling to background and CTA buttons * feat(WalletWidget): added Divider * chore(WalletWidget): updated copy * feat(WalletSelector): use fullWifth props for button * feat(WalletSelector): use fullWidfth props for input * feat(WatchOnlyModeTooltip): re-named component with correct casing * feat(WalletSelector): added boolean state to check for valid address error * feat(WalletWidget): added handle switch wallet method * chore: updated messages.js * chore: code style changes * update tests * fix: use proper app header color * fix: prevent auto zoom on mobile on watch address input * test: don't set a watch wallet in cypress tests * feat: wrap in form to allow input by pressing enter * feat: add support for watching ens names * feat: add ENS to placeholder text * feat: enable watch button for ens inputs * chore: use proper submit button for form * chore: sx styles * fix tests Co-authored-by: matthew.lau Co-authored-by: Mark Grothe Co-authored-by: Nikita Boakrev Co-authored-by: Andrew Schmidt * chore: automated cache update [skip cypress] * chore: automated cache update [skip cypress] * chore: automated cache update [skip cypress] * chore: automated cache update [skip cypress] * chore: automated cache update [skip cypress] * chore(i18n): synchronize translations from crowdin [skip cypress] * chore: automated cache update [skip cypress] * chore: automated cache update [skip cypress] * chore: automated cache update [skip cypress] * chore: automated cache update [skip cypress] * chore: automated cache update [skip cypress] * chore: automated cache update [skip cypress] * chore: automated cache update [skip cypress] * chore: automated cache update [skip cypress] * chore: automated cache update [skip cypress] * chore: automated cache update [skip cypress] * chore: automated cache update [skip cypress] * chore: automated cache update [skip cypress] * chore: automated cache update [skip cypress] * chore: automated cache update [skip cypress] * chore: automated cache update [skip cypress] * chore: automated cache update [skip cypress] * chore: automated cache update [skip cypress] * chore: automated cache update [skip cypress] * chore: automated cache update [skip cypress] * fix: use gateway retry logic anywhere we fetch ipfs data (#1186) * fix: swap ipfs gateway * fix: replace pinata gateway with ipfs one * fix: use retry logic anywhere we try to get proposal from ipfs * fix: remove unused param * chore: add JSDoc comments Co-authored-by: Drew Cook * fix: lint Co-authored-by: Cache bot Co-authored-by: Lukas Co-authored-by: Nikita Co-authored-by: Nikita Boakrev Co-authored-by: Drew Cook Co-authored-by: Andrew Schmidt Co-authored-by: Crowdin bot Co-authored-by: Mark Hinschberger Co-authored-by: Jonathan Reem Co-authored-by: derasd Co-authored-by: slundy-ledger <96065469+slundy-ledger@users.noreply.github.com> Co-authored-by: 0xGraham Co-authored-by: matthew.lau * fix: ui polish for 'exactIn' swap case * refactor: swap and collateral repay hooks * chore: added jsdoc comments * fix: make sure input amount is valid, set correct slippage on swap * fix: error handling * fix: clean up merge files * fix: clean up merge files Co-authored-by: Mark Hinschberger Co-authored-by: Mark Grothe Co-authored-by: Cache bot Co-authored-by: Lukas Co-authored-by: Nikita Co-authored-by: Nikita Boakrev Co-authored-by: Drew Cook Co-authored-by: Crowdin bot Co-authored-by: Mark Hinschberger Co-authored-by: Jonathan Reem Co-authored-by: derasd Co-authored-by: slundy-ledger <96065469+slundy-ledger@users.noreply.github.com> Co-authored-by: 0xGraham Co-authored-by: matthew.lau --- package.json | 4 +- public/icons/other/paraswap.svg | 1 + src/components/transactions/AssetInput.tsx | 27 +- .../Borrow/BorrowModalContent.tsx | 2 +- .../FlowCommons/TxModalDetails.tsx | 36 +- .../Repay/CollateralRepayActions.tsx | 28 +- .../Repay/CollateralRepayModalContent.tsx | 246 +++++----- .../transactions/Repay/RepayModal.tsx | 5 +- .../transactions/Repay/RepayTypeSelector.tsx | 2 +- .../transactions/Swap/SwapActions.tsx | 24 +- .../transactions/Swap/SwapModalContent.tsx | 165 +++---- .../transactions/Swap/SwapModalDetails.tsx | 164 +++++++ src/helpers/useTransactionHandler.tsx | 1 + src/hooks/paraswap/common.ts | 460 ++++++++++++++++++ src/hooks/paraswap/useCollateralRepaySwap.tsx | 146 ++++++ src/hooks/paraswap/useCollateralSwap.tsx | 117 +++++ src/hooks/useModal.tsx | 7 +- src/hooks/useSwap.ts | 281 ----------- src/locales/en/messages.js | 2 +- src/locales/en/messages.po | 73 ++- src/locales/es/messages.po | 12 + .../BorrowedPositionsListItem.tsx | 2 +- .../BorrowedPositionsListMobileItem.tsx | 2 +- src/modules/dashboard/lists/SlippageList.tsx | 133 +++++ src/static-build/proposals.json | 8 +- yarn.lock | 16 +- 26 files changed, 1373 insertions(+), 591 deletions(-) create mode 100644 public/icons/other/paraswap.svg create mode 100644 src/components/transactions/Swap/SwapModalDetails.tsx create mode 100644 src/hooks/paraswap/common.ts create mode 100644 src/hooks/paraswap/useCollateralRepaySwap.tsx create mode 100644 src/hooks/paraswap/useCollateralSwap.tsx delete mode 100644 src/hooks/useSwap.ts create mode 100644 src/modules/dashboard/lists/SlippageList.tsx diff --git a/package.json b/package.json index 055ab6dc64..7d52b92ec5 100644 --- a/package.json +++ b/package.json @@ -32,8 +32,8 @@ "test:ci": "jest --ci" }, "dependencies": { - "@aave/contract-helpers": "1.5.1", - "@aave/math-utils": "1.5.1", + "@aave/contract-helpers": "1.6.0", + "@aave/math-utils": "1.6.0", "@apollo/client": "^3.5.10", "@emotion/cache": "11.10.3", "@emotion/react": "11.10.4", diff --git a/public/icons/other/paraswap.svg b/public/icons/other/paraswap.svg new file mode 100644 index 0000000000..a724bb22ce --- /dev/null +++ b/public/icons/other/paraswap.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/components/transactions/AssetInput.tsx b/src/components/transactions/AssetInput.tsx index 88aa692701..e53eb69930 100644 --- a/src/components/transactions/AssetInput.tsx +++ b/src/components/transactions/AssetInput.tsx @@ -74,6 +74,7 @@ export interface AssetInputProps { maxValue?: string; isMaxSelected?: boolean; inputTitle?: ReactNode; + balanceText?: string; } export const AssetInput = ({ @@ -89,6 +90,7 @@ export const AssetInput = ({ maxValue, inputTitle, isMaxSelected, + balanceText, }: AssetInputProps) => { const handleSelect = (event: SelectChangeEvent) => { const newAsset = assets.find((asset) => asset.symbol === event.target.value) as T; @@ -198,6 +200,7 @@ export const AssetInput = ({ '&.AssetInput__select .MuiOutlinedInput-notchedOutline': { display: 'none' }, '&.AssetInput__select .MuiSelect-icon': { color: 'text.primary', + right: '0%', }, }} renderValue={(symbol) => { @@ -248,15 +251,15 @@ export const AssetInput = ({ compact symbol="USD" variant="secondary12" - color="text.disabled" - symbolsColor="text.disabled" + color="text.muted" + symbolsColor="text.muted" flexGrow={1} /> {asset.balance && onChange && ( <> - Balance{' '} + {balanceText || 'Balance'}{' '} ({ symbolsColor="text.disabled" /> - + {!disableInput && ( + + )} )} diff --git a/src/components/transactions/Borrow/BorrowModalContent.tsx b/src/components/transactions/Borrow/BorrowModalContent.tsx index f08292a949..f8ca4818a6 100644 --- a/src/components/transactions/Borrow/BorrowModalContent.tsx +++ b/src/components/transactions/Borrow/BorrowModalContent.tsx @@ -74,7 +74,7 @@ const BorrowModeSwitch = ({ value={interestRateMode} exclusive onChange={(_, value) => setInterestRateMode(value)} - sx={{ width: '100%', mt: 0.5 }} + sx={{ width: '100%', height: '36px', p: '2px', mt: 0.5 }} > = ({ gasLimit, children }) => { +export const TxModalDetails: React.FC = ({ + gasLimit, + slippageSelector, + children, +}) => { return ( @@ -37,8 +42,10 @@ export const TxModalDetails: React.FC = ({ gasLimit, childr > {children} - - + + + {slippageSelector} + ); }; @@ -87,6 +94,7 @@ interface DetailsNumberLineWithSubProps { futureValueUSD: string; hideSymbolSuffix?: boolean; color?: string; + tokenIcon?: string; } export const DetailsNumberLineWithSub = ({ @@ -98,6 +106,7 @@ export const DetailsNumberLineWithSub = ({ futureValueUSD, hideSymbolSuffix, color, + tokenIcon, }: DetailsNumberLineWithSubProps) => { return ( @@ -116,6 +125,7 @@ export const DetailsNumberLineWithSub = ({ )} + {tokenIcon && } {!hideSymbolSuffix && ( @@ -209,15 +219,17 @@ export const DetailsIncentivesLine = ({ if (!incentives || incentives.filter((i) => i.incentiveAPR !== '0').length === 0) return null; return ( Rewards APR} captionVariant="description" mb={4} minHeight={24}> - - {futureSymbol && ( - <> - - - - - - )} + + + {futureSymbol && ( + <> + + + + + + )} + ); }; diff --git a/src/components/transactions/Repay/CollateralRepayActions.tsx b/src/components/transactions/Repay/CollateralRepayActions.tsx index 49bde9149b..4e0ef32f96 100644 --- a/src/components/transactions/Repay/CollateralRepayActions.tsx +++ b/src/components/transactions/Repay/CollateralRepayActions.tsx @@ -1,12 +1,8 @@ import { InterestRate } from '@aave/contract-helpers'; -import { normalize } from '@aave/math-utils'; import { Trans } from '@lingui/macro'; import { BoxProps } from '@mui/material'; -import { OptimalRate } from 'paraswap-core'; import { useTransactionHandler } from 'src/helpers/useTransactionHandler'; import { ComputedReserveData } from 'src/hooks/app-data-provider/useAppDataProvider'; -import { useProtocolDataContext } from 'src/hooks/useProtocolDataContext'; -import { getRepayCallData } from 'src/hooks/useSwap'; import { useTxBuilderContext } from 'src/hooks/useTxBuilder'; import { useWeb3Context } from 'src/libs/hooks/useWeb3Context'; @@ -21,11 +17,11 @@ export interface RepayActionProps extends BoxProps { isWrongNetwork: boolean; customGasPrice?: string; symbol: string; - priceRoute: OptimalRate | null; repayAllDebt: boolean; useFlashLoan: boolean; blocked: boolean; - maxSlippage: number; + swapCallData: string; + augustus: string; } export const CollateralRepayActions = ({ @@ -37,36 +33,25 @@ export const CollateralRepayActions = ({ sx, symbol, rateMode, - priceRoute, repayAllDebt, useFlashLoan, blocked, - maxSlippage, + swapCallData, + augustus, ...props }: RepayActionProps) => { const { lendingPool } = useTxBuilderContext(); - const { currentChainId: chainId, currentNetworkConfig } = useProtocolDataContext(); const { currentAccount } = useWeb3Context(); const { approval, action, requiresApproval, loadingTxns, approvalTxState, mainTxState } = useTransactionHandler({ handleGetTxns: async () => { - const { swapCallData, augustus, srcAmountWithSlippage } = await getRepayCallData({ - srcToken: fromAssetData.underlyingAsset, - srcDecimals: fromAssetData.decimals, - destToken: poolReserve.underlyingAsset, - destDecimals: poolReserve.decimals, - user: currentAccount, - route: priceRoute as OptimalRate, - chainId: currentNetworkConfig.underlyingChainId || chainId, - maxSlippage, - }); return lendingPool.paraswapRepayWithCollateral({ user: currentAccount, fromAsset: fromAssetData.underlyingAsset, fromAToken: fromAssetData.aTokenAddress, assetToRepay: poolReserve.underlyingAsset, - repayWithAmount: normalize(srcAmountWithSlippage, fromAssetData.decimals), + repayWithAmount, repayAmount, repayAllDebt, rateMode, @@ -79,7 +64,6 @@ export const CollateralRepayActions = ({ deps: [ repayWithAmount, repayAmount, - priceRoute, poolReserve.underlyingAsset, fromAssetData.underlyingAsset, repayAllDebt, @@ -91,7 +75,7 @@ export const CollateralRepayActions = ({ return ( @@ -52,69 +54,94 @@ export function CollateralRepayModalContent({ .map((userReserve) => ({ address: userReserve.underlyingAsset, balance: userReserve.underlyingBalance, + balanceUSD: userReserve.underlyingBalanceUSD, symbol: userReserve.reserve.symbol, iconSymbol: userReserve.reserve.iconSymbol, - aToken: true, - })); + })) + .sort((a, b) => Number(b.balanceUSD) - Number(a.balanceUSD)); const [tokenToRepayWith, setTokenToRepayWith] = useState(repayTokens[0]); + const tokenToRepayWithBalance = tokenToRepayWith.balance || '0'; - const fromAssetData = reserves.find( - (reserve) => reserve.underlyingAsset === tokenToRepayWith.address - ) as ComputedReserveData; - - const repayWithUserReserve = userReserves.find( - (userReserve) => userReserve.underlyingAsset === tokenToRepayWith.address - ) as ComputedUserReserveData; - - const [_amount, setAmount] = useState(''); + const [swapVariant, setSwapVariant] = useState('exactOut'); + const [amount, setAmount] = useState(''); const [maxSlippage, setMaxSlippage] = useState('0.5'); const amountRef = useRef(''); + const collateralReserveData = reserves.find( + (reserve) => reserve.underlyingAsset === tokenToRepayWith.address + ) as ComputedReserveData; + const debt = debtType === InterestRate.Stable ? userReserve?.stableBorrows || '0' : userReserve?.variableBorrows || '0'; const safeAmountToRepayAll = valueToBigNumber(debt).multipliedBy('1.0025'); - const isMaxSelected = _amount === '-1'; - const amount = isMaxSelected ? safeAmountToRepayAll.toString() : _amount; - const usdValue = valueToBigNumber(amount).multipliedBy(poolReserve.priceInUSD); + const isMaxSelected = amount === '-1'; + const repayAmount = isMaxSelected ? safeAmountToRepayAll.toString() : amount; + const repayAmountUsdValue = valueToBigNumber(repayAmount) + .multipliedBy(poolReserve.priceInUSD) + .toString(); - const { priceRoute, inputAmountUSD, inputAmount, outputAmount, outputAmountUSD } = useSwap({ - chainId: currentNetworkConfig.underlyingChainId || currentChainId, - userId: currentAccount, - variant: 'exactOut', - swapIn: { ...fromAssetData, amount: '0' }, - swapOut: { ...poolReserve, amount: amountRef.current }, - max: isMaxSelected, - skip: mainTxState.loading, - }); + // The slippage is factored into the collateral amount because when we swap for 'exactOut', positive slippage is applied on the collateral amount. + const collateralAmountRequiredToCoverDebt = safeAmountToRepayAll + .multipliedBy(100 + Number(maxSlippage)) + .dividedBy(100) + .dividedBy(collateralReserveData.priceInUSD); - // Calculations to get the max repayable debt depending on the balance and value of the - // selected collateral - const maxCollateral = valueToBigNumber(tokenToRepayWith?.balance || 0).multipliedBy( - fromAssetData.priceInMarketReferenceCurrency - ); - const maxDebtThatCanBeRepaidWithSelectedCollateral = maxCollateral.dividedBy( - poolReserve.priceInMarketReferenceCurrency - ); - const maxRepayableDebt = BigNumber.min( - maxDebtThatCanBeRepaidWithSelectedCollateral, - safeAmountToRepayAll - ); - const handleChange = (value: string) => { + const swapIn = { ...collateralReserveData, amount: tokenToRepayWithBalance }; + const swapOut = { ...poolReserve, amount: amountRef.current }; + if (swapVariant === 'exactIn') { + swapIn.amount = tokenToRepayWithBalance; + swapOut.amount = '0'; + } + + const repayAllDebt = + isMaxSelected && + valueToBigNumber(tokenToRepayWithBalance).gte(collateralAmountRequiredToCoverDebt); + + const { inputAmountUSD, inputAmount, outputAmount, outputAmountUSD, swapCallData, augustus } = + useCollateralRepaySwap({ + chainId: currentNetworkConfig.underlyingChainId || currentChainId, + userAddress: currentAccount, + variant: swapVariant, + swapIn, + swapOut, + max: repayAllDebt, + skip: mainTxState.loading, + maxSlippage: Number(maxSlippage), + }); + + const handleRepayAmountChange = (value: string) => { const maxSelected = value === '-1'; - amountRef.current = maxSelected ? maxRepayableDebt.toString(10) : value; - setAmount(value); + + if ( + maxSelected && + valueToBigNumber(tokenToRepayWithBalance).lt(collateralAmountRequiredToCoverDebt) + ) { + // The selected collateral amount is not enough to pay the full debt. We'll try to do a swap using the exact amount of collateral. + // The amount won't be known until we fetch the swap data, so we'll clear it out. Once the swap data is fetched, we'll set the amount. + amountRef.current = ''; + setAmount(''); + setSwapVariant('exactIn'); + } else { + amountRef.current = maxSelected ? safeAmountToRepayAll.toString(10) : value; + setAmount(value); + setSwapVariant('exactOut'); + } }; + // for v3 we need hf after withdraw collateral, because when removing collateral to repay // debt, hf could go under 1 then it would fail. If that is the case then we need // to use flashloan path + const repayWithUserReserve = userReserves.find( + (userReserve) => userReserve.underlyingAsset === tokenToRepayWith.address + ) as ComputedUserReserveData; const { hfAfterSwap, hfEffectOfFromAmount } = calculateHFAfterRepay({ amountToReceiveAfterSwap: outputAmount, amountToSwap: inputAmount, - fromAssetData, + fromAssetData: collateralReserveData, user, toAssetData: poolReserve, repayWithUserReserve, @@ -134,24 +161,26 @@ export function CollateralRepayModalContent({ // a safe amount to repay all. When this happens amountAfterRepay would be < 0 and // this would show as certain amount left to repay when we are actually repaying all debt const amountAfterRepay = valueToBigNumber(debt).minus(BigNumber.min(outputAmount, debt)); - const displayAmountAfterRepayInUsd = amountAfterRepay - .multipliedBy(poolReserve.formattedPriceInMarketReferenceCurrency) - .multipliedBy(marketReferencePriceInUsd) - .shiftedBy(-USD_DECIMALS); + const displayAmountAfterRepayInUsd = amountAfterRepay.multipliedBy(poolReserve.priceInUSD); + const collateralAmountAfterRepay = tokenToRepayWithBalance + ? valueToBigNumber(tokenToRepayWithBalance).minus(inputAmount) + : valueToBigNumber('0'); + const collateralAmountAfterRepayUSD = collateralAmountAfterRepay.multipliedBy( + collateralReserveData.priceInUSD + ); // calculate impact based on $ difference - const priceImpact = + let priceImpact = outputAmountUSD && outputAmountUSD !== '0' - ? new BigNumber(1) - .minus(new BigNumber(inputAmountUSD).dividedBy(outputAmountUSD)) - .toString(10) + ? new BigNumber(1).minus(new BigNumber(inputAmountUSD).dividedBy(outputAmountUSD)).toFixed(2) : '0'; + if (priceImpact === '-0.00') { + priceImpact = '0.00'; + } let blockingError: ErrorType | undefined = undefined; - const tokenToRepayWithUsdValue = valueToBigNumber(tokenToRepayWith?.balance || '0').multipliedBy( - fromAssetData.priceInUSD - ); - if (Number(usdValue) > Number(tokenToRepayWithUsdValue.toString(10))) { + + if (valueToBigNumber(tokenToRepayWithBalance).lt(inputAmount)) { blockingError = ErrorType.NOT_ENOUGH_COLLATERAL_TO_REPAY_WITH; } else if (disableFlashLoan) { blockingError = ErrorType.FLASH_LOAN_NOT_AVAILABLE; @@ -181,13 +210,12 @@ export function CollateralRepayModalContent({ symbol={poolReserve.symbol} /> ); - return ( <> Debt amount to repay} + inputTitle={Expected amount to repay} + balanceText="Borrow balance" /> + + + + + + + Price impact{' '} + % + + } + variant="secondary14" + /> + Collateral amount to repay with} + onChange={handleRepayAmountChange} + inputTitle={Collateral to repay with} + maxValue={tokenToRepayWithBalance} disableInput + balanceText="Collateral balance" /> {blockingError !== undefined && ( {handleBlocked()} )} - + } > - Price impact} captionVariant="subheader1"> - - - Minimum received} captionVariant="subheader1" sx={{ mt: 4 }}> - - - - Max slippage rate - - setMaxSlippage(value)} - exclusive - > - - 0.1% - - - 0.5% - - - 1% - - - - + Remaining debt} + description={Borrow balance after repay} futureValue={amountAfterRepay.toString()} futureValueUSD={displayAmountAfterRepayInUsd.toString()} symbol={symbol} + tokenIcon={poolReserve.iconSymbol} /> - Collateral balance after repay} + futureValue={collateralAmountAfterRepay.toString()} + futureValueUSD={collateralAmountAfterRepayUSD.toString()} + symbol={tokenToRepayWith.symbol} + tokenIcon={tokenToRepayWith.iconSymbol} /> @@ -268,17 +294,17 @@ export function CollateralRepayModalContent({ ); diff --git a/src/components/transactions/Repay/RepayModal.tsx b/src/components/transactions/Repay/RepayModal.tsx index 782cc23e7d..5ebaf5f3db 100644 --- a/src/components/transactions/Repay/RepayModal.tsx +++ b/src/components/transactions/Repay/RepayModal.tsx @@ -16,6 +16,7 @@ export const RepayModal = () => { const { type, close, args, mainTxState } = useModalContext() as ModalContextType<{ underlyingAsset: string; currentRateMode: InterestRate; + isFrozen: boolean; }>; const { userReserves } = useAppDataContext(); const { currentMarketData } = useProtocolDataContext(); @@ -25,12 +26,14 @@ export const RepayModal = () => { // 1. on chains with paraswap deployed // 2. when you have a different supplied(not necessarily collateral) asset then the one your debt is in // For repaying your debt with the same assets aToken you can use repayWithAToken on aave protocol v3 + // 3. the supplied asset is not frozen const collateralRepayPossible = isFeatureEnabled.collateralRepay(currentMarketData) && userReserves.some( (userReserve) => userReserve.scaledATokenBalance !== '0' && - userReserve.underlyingAsset !== args.underlyingAsset + userReserve.underlyingAsset !== args.underlyingAsset && + !args.isFrozen ); return ( diff --git a/src/components/transactions/Repay/RepayTypeSelector.tsx b/src/components/transactions/Repay/RepayTypeSelector.tsx index fb573c6f24..97981ea306 100644 --- a/src/components/transactions/Repay/RepayTypeSelector.tsx +++ b/src/components/transactions/Repay/RepayTypeSelector.tsx @@ -28,7 +28,7 @@ export function RepayTypeSelector({ value={repayType} exclusive onChange={(_, value) => setRepayType(value)} - sx={{ width: '100%' }} + sx={{ width: '100%', height: '36px', p: '2px' }} > diff --git a/src/components/transactions/Swap/SwapActions.tsx b/src/components/transactions/Swap/SwapActions.tsx index e05611eed6..fa45fde98b 100644 --- a/src/components/transactions/Swap/SwapActions.tsx +++ b/src/components/transactions/Swap/SwapActions.tsx @@ -1,9 +1,6 @@ import { Trans } from '@lingui/macro'; import { BoxProps } from '@mui/material'; -import { OptimalRate } from 'paraswap-core'; import { ComputedReserveData } from 'src/hooks/app-data-provider/useAppDataProvider'; -import { useProtocolDataContext } from 'src/hooks/useProtocolDataContext'; -import { getSwapCallData } from 'src/hooks/useSwap'; import { useTxBuilderContext } from 'src/hooks/useTxBuilder'; import { useWeb3Context } from 'src/libs/hooks/useWeb3Context'; @@ -19,9 +16,11 @@ export interface SwapActionProps extends BoxProps { customGasPrice?: string; symbol: string; blocked: boolean; - priceRoute: OptimalRate | null; isMaxSelected: boolean; useFlashLoan: boolean; + maxSlippage: number; + swapCallData: string; + augustus: string; } export const SwapActions = ({ @@ -31,27 +30,19 @@ export const SwapActions = ({ sx, poolReserve, targetReserve, - priceRoute, isMaxSelected, useFlashLoan, + maxSlippage, + swapCallData, + augustus, ...props }: SwapActionProps) => { const { lendingPool } = useTxBuilderContext(); - const { currentChainId: chainId, currentNetworkConfig } = useProtocolDataContext(); const { currentAccount } = useWeb3Context(); const { approval, action, requiresApproval, approvalTxState, mainTxState, loadingTxns } = useTransactionHandler({ handleGetTxns: async () => { - const { swapCallData, augustus } = await getSwapCallData({ - srcToken: poolReserve.underlyingAsset, - srcDecimals: poolReserve.decimals, - destToken: targetReserve.underlyingAsset, - destDecimals: targetReserve.decimals, - user: currentAccount, - route: priceRoute as OptimalRate, - chainId: currentNetworkConfig.underlyingChainId || chainId, - }); return lendingPool.swapCollateral({ fromAsset: poolReserve.underlyingAsset, toAsset: targetReserve.underlyingAsset, @@ -65,11 +56,10 @@ export const SwapActions = ({ swapCallData, }); }, - skip: !priceRoute || !amountToSwap || parseFloat(amountToSwap) === 0 || !currentAccount, + skip: !amountToSwap || parseFloat(amountToSwap) === 0 || !currentAccount, deps: [ amountToSwap, amountToReceive, - priceRoute, poolReserve.underlyingAsset, targetReserve.underlyingAsset, isMaxSelected, diff --git a/src/components/transactions/Swap/SwapModalContent.tsx b/src/components/transactions/Swap/SwapModalContent.tsx index a3acb9da6d..7d02d0cdd2 100644 --- a/src/components/transactions/Swap/SwapModalContent.tsx +++ b/src/components/transactions/Swap/SwapModalContent.tsx @@ -1,34 +1,30 @@ +import { SwitchVerticalIcon } from '@heroicons/react/outline'; import { Trans } from '@lingui/macro'; -import { Box, Typography } from '@mui/material'; +import { Box, SvgIcon, Typography } from '@mui/material'; import BigNumber from 'bignumber.js'; import React, { useRef, useState } from 'react'; +import { PriceImpactTooltip } from 'src/components/infoTooltips/PriceImpactTooltip'; import { FormattedNumber } from 'src/components/primitives/FormattedNumber'; -import { Row } from 'src/components/primitives/Row'; -import StyledToggleButton from 'src/components/StyledToggleButton'; -import StyledToggleButtonGroup from 'src/components/StyledToggleButtonGroup'; import { Asset, AssetInput } from 'src/components/transactions/AssetInput'; import { GasEstimationError } from 'src/components/transactions/FlowCommons/GasEstimationError'; -import { - DetailsHFLine, - DetailsIncentivesLine, - DetailsNumberLine, - TxModalDetails, -} from 'src/components/transactions/FlowCommons/TxModalDetails'; +import { TxModalDetails } from 'src/components/transactions/FlowCommons/TxModalDetails'; +import { useCollateralSwap } from 'src/hooks/paraswap/useCollateralSwap'; import { useModalContext } from 'src/hooks/useModal'; import { useProtocolDataContext } from 'src/hooks/useProtocolDataContext'; -import { useSwap } from 'src/hooks/useSwap'; import { useWeb3Context } from 'src/libs/hooks/useWeb3Context'; +import { ListSlippageButton } from 'src/modules/dashboard/lists/SlippageList'; import { remainingCap } from 'src/utils/getMaxAmountAvailableToSupply'; import { calculateHFAfterSwap } from 'src/utils/hfUtils'; import { - ComputedReserveData, + ComputedUserReserveData, useAppDataContext, } from '../../../hooks/app-data-provider/useAppDataProvider'; import { ModalWrapperProps } from '../FlowCommons/ModalWrapper'; import { TxSuccessView } from '../FlowCommons/Success'; import { ErrorType, flashLoanNotAvailable, useFlashloan } from '../utils'; import { SwapActions } from './SwapActions'; +import { SwapModalDetails } from './SwapModalDetails'; export type SupplyProps = { underlyingAsset: string; @@ -58,9 +54,9 @@ export const SwapModalContent = ({ const [targetReserve, setTargetReserve] = useState(swapTargets[0]); const [maxSlippage, setMaxSlippage] = useState('0.1'); - const swapTarget = reserves.find( + const swapTarget = user.userReservesData.find( (r) => r.underlyingAsset === targetReserve.address - ) as ComputedReserveData; + ) as ComputedUserReserveData; // a user can never swap more then 100% of available as the txn would fail on withdraw step const maxAmountToSwap = BigNumber.min( @@ -68,22 +64,28 @@ export const SwapModalContent = ({ new BigNumber(poolReserve.availableLiquidity).multipliedBy(0.99) ).toString(10); - const remainingCapBn = remainingCap(swapTarget); + const remainingCapBn = remainingCap(swapTarget.reserve); const isMaxSelected = _amount === '-1'; const amount = isMaxSelected ? maxAmountToSwap : _amount; - const { priceRoute, inputAmountUSD, inputAmount, outputAmount, outputAmountUSD, error } = useSwap( - { - chainId: currentNetworkConfig.underlyingChainId || currentChainId, - userId: currentAccount, - variant: 'exactIn', - swapIn: { ...poolReserve, amount: amountRef.current }, - swapOut: { ...swapTarget, amount: '0' }, - max: isMaxSelected, - skip: supplyTxState.loading, - } - ); + const { + inputAmountUSD, + inputAmount, + outputAmount, + outputAmountUSD, + error, + augustus, + swapCallData, + } = useCollateralSwap({ + chainId: currentNetworkConfig.underlyingChainId || currentChainId, + userAddress: currentAccount, + swapIn: { ...poolReserve, amount: amountRef.current }, + swapOut: { ...swapTarget.reserve, amount: '0' }, + max: isMaxSelected, + skip: supplyTxState.loading, + maxSlippage: Number(maxSlippage), + }); const minimumReceived = new BigNumber(outputAmount || '0') .multipliedBy(new BigNumber(100).minus(maxSlippage).dividedBy(100)) @@ -101,7 +103,7 @@ export const SwapModalContent = ({ fromAssetUserData: userReserve, user, toAmountAfterSlippage: minimumReceived, - toAssetData: swapTarget, + toAssetData: swapTarget.reserve, }); // if the hf would drop below 1 from the hf effect a flashloan should be used to mitigate liquidation @@ -165,9 +167,7 @@ export const SwapModalContent = ({ // calculate impact based on $ difference const priceImpact = outputAmountUSD && outputAmountUSD !== '0' - ? new BigNumber(1) - .minus(new BigNumber(inputAmountUSD).dividedBy(outputAmountUSD)) - .toString(10) + ? new BigNumber(1).minus(new BigNumber(inputAmountUSD).dividedBy(outputAmountUSD)).toFixed(2) : '0'; return ( @@ -189,85 +189,60 @@ export const SwapModalContent = ({ }, ]} maxValue={maxAmountToSwap} + inputTitle={Supplied asset amount} + balanceText="Supply balance" isMaxSelected={isMaxSelected} /> + + + + + + + Price impact{' '} + % + + } + variant="secondary14" + /> + Swap to} disableInput /> - - Price impact} captionVariant="subheader1"> - - - Minimum received} captionVariant="subheader1" sx={{ mt: 4 }}> - - - - Max slippage rate - - setMaxSlippage(value)} - exclusive - > - - 0.1% - - - 0.5% - - - 1% - - - - {blockingError !== undefined && ( + {error && ( - {handleBlocked()} + {error} )} - {error && ( + {!error && blockingError !== undefined && ( - {error} + {handleBlocked()} )} - - Supply apy} - value={poolReserve.supplyAPY} - futureValue={swapTarget.supplyAPY} - percent - /> - + } + > + - {showHealthFactor && ( - - )} {txError && } @@ -278,11 +253,13 @@ export const SwapModalContent = ({ amountToSwap={inputAmount} amountToReceive={minimumReceived} isWrongNetwork={isWrongNetwork} - targetReserve={swapTarget} + targetReserve={swapTarget.reserve} symbol={poolReserve.symbol} blocked={blockingError !== undefined} - priceRoute={priceRoute} useFlashLoan={shouldUseFlashloan} + maxSlippage={Number(maxSlippage)} + augustus={augustus} + swapCallData={swapCallData} /> ); diff --git a/src/components/transactions/Swap/SwapModalDetails.tsx b/src/components/transactions/Swap/SwapModalDetails.tsx new file mode 100644 index 0000000000..d6fe7b38b8 --- /dev/null +++ b/src/components/transactions/Swap/SwapModalDetails.tsx @@ -0,0 +1,164 @@ +import { valueToBigNumber } from '@aave/math-utils'; +import { ArrowNarrowRightIcon } from '@heroicons/react/outline'; +import { Trans } from '@lingui/macro'; +import { Box, SvgIcon, Typography, useTheme } from '@mui/material'; +import React from 'react'; +import { FormattedNumber } from 'src/components/primitives/FormattedNumber'; +import { Row } from 'src/components/primitives/Row'; +import { TokenIcon } from 'src/components/primitives/TokenIcon'; +import { + DetailsHFLine, + DetailsIncentivesLine, + DetailsNumberLine, +} from 'src/components/transactions/FlowCommons/TxModalDetails'; + +import { ComputedUserReserveData } from '../../../hooks/app-data-provider/useAppDataProvider'; + +export type SupplyModalDetailsProps = { + showHealthFactor: boolean; + healthFactor: string; + healthFactorAfterSwap: string; + swapSource: ComputedUserReserveData; + swapTarget: ComputedUserReserveData; + toAmount: string; + fromAmount: string; +}; + +export const SwapModalDetails = ({ + showHealthFactor, + healthFactor, + healthFactorAfterSwap, + swapSource, + swapTarget, + toAmount, + fromAmount, +}: SupplyModalDetailsProps) => { + const { palette } = useTheme(); + + const parseUsageString = (usage: boolean) => { + if (usage) { + return ( + + Yes + + ); + } else { + return ( + + No + + ); + } + }; + + const sourceAmountAfterSwap = valueToBigNumber(swapSource.underlyingBalance).minus( + valueToBigNumber(fromAmount) + ); + + const targetAmountAfterSwap = valueToBigNumber(swapTarget.underlyingBalance).plus( + valueToBigNumber(toAmount) + ); + + return ( + <> + {healthFactorAfterSwap && ( + + )} + Supply apy} + value={swapSource.reserve.supplyAPY} + futureValue={swapTarget.reserve.supplyAPY} + percent + /> + Can be collateral} captionVariant="description" mb={4}> + + {parseUsageString(swapSource.reserve.usageAsCollateralEnabled)} + + + + + + {parseUsageString(swapTarget.reserve.usageAsCollateralEnabled)} + + + + Liquidation threshold} + value={swapSource.reserve.formattedReserveLiquidationThreshold} + futureValue={swapTarget.reserve.formattedReserveLiquidationThreshold} + percent + visibleDecimals={0} + /> + + Supply balance after swap} + captionVariant="description" + mb={4} + align="flex-start" + > + + + + + + {swapSource.reserve.symbol} + + + + + + + + + + {swapTarget.reserve.symbol} + + + + + + + + ); +}; diff --git a/src/helpers/useTransactionHandler.tsx b/src/helpers/useTransactionHandler.tsx index d2ba452705..0461f1d6c2 100644 --- a/src/helpers/useTransactionHandler.tsx +++ b/src/helpers/useTransactionHandler.tsx @@ -110,6 +110,7 @@ export const useTransactionHandler = ({ const newPool: Pool = lendingPool as Pool; // deadline is an hour after signature const deadline = Math.floor(Date.now() / 1000 + 3600).toString(); + console.log('ERC20Approval', amount); const unsingedPayload = await newPool.signERC20Approval({ user: currentAccount, reserve: underlyingAsset, diff --git a/src/hooks/paraswap/common.ts b/src/hooks/paraswap/common.ts new file mode 100644 index 0000000000..6279daaba6 --- /dev/null +++ b/src/hooks/paraswap/common.ts @@ -0,0 +1,460 @@ +import { ChainId } from '@aave/contract-helpers'; +import { BigNumberZeroDecimal, normalize, normalizeBN, valueToBigNumber } from '@aave/math-utils'; +import { + constructBuildTx, + constructFetchFetcher, + constructGetRate, + constructPartialSDK, + TransactionParams, +} from '@paraswap/sdk'; +import { RateOptions } from '@paraswap/sdk/dist/rates'; +import { ContractMethod, OptimalRate, SwapSide } from 'paraswap-core'; + +import { ComputedReserveData } from '../app-data-provider/useAppDataProvider'; + +export type UseSwapProps = { + chainId: ChainId; + max: boolean; + maxSlippage: number; + swapIn: SwapReserveData; + swapOut: SwapReserveData; + userAddress: string; + skip?: boolean; +}; + +export type SwapReserveData = ComputedReserveData & { amount: string }; + +export type SwapData = Pick< + SwapReserveData, + 'amount' | 'underlyingAsset' | 'decimals' | 'supplyAPY' | 'variableBorrowAPY' +>; + +export type SwapVariant = 'exactIn' | 'exactOut'; + +type SwapTransactionParams = { + swapCallData: string; + augustus: string; + inputAmount: string; + outputAmount: string; + inputAmountUSD: string; + outputAmountUSD: string; +}; + +type GetSwapCallDataProps = { + srcToken: string; + srcDecimals: number; + destToken: string; + destDecimals: number; + user: string; + route: OptimalRate; + max?: boolean; + chainId: ChainId; + maxSlippage: number; +}; + +type GetSwapAndRepayCallDataProps = { + srcToken: string; + srcDecimals: number; + destToken: string; + destDecimals: number; + user: string; + route: OptimalRate; + max?: boolean; + chainId: ChainId; + maxSlippage: number; +}; + +const ParaSwap = (chainId: number) => { + const fetcher = constructFetchFetcher(fetch); // alternatively constructFetchFetcher + return constructPartialSDK( + { + network: chainId, + fetcher, + }, + constructBuildTx, + constructGetRate + ); +}; + +const mainnetParaswap = ParaSwap(ChainId.mainnet); +const polygonParaswap = ParaSwap(ChainId.polygon); +const avalancheParaswap = ParaSwap(ChainId.avalanche); +const fantomParaswap = ParaSwap(ChainId.fantom); +const arbitrumParaswap = ParaSwap(ChainId.arbitrum_one); +const optimismParaswap = ParaSwap(ChainId.optimism); + +export const getParaswap = (chainId: ChainId) => { + if (ChainId.mainnet === chainId) return mainnetParaswap; + if (ChainId.polygon === chainId) return polygonParaswap; + if (ChainId.avalanche === chainId) return avalancheParaswap; + if (ChainId.fantom === chainId) return fantomParaswap; + if (ChainId.arbitrum_one === chainId) return arbitrumParaswap; + if (ChainId.optimism === chainId) return optimismParaswap; + throw new Error('chain not supported'); +}; + +export const MESSAGE_MAP: { [key: string]: string } = { + ESTIMATED_LOSS_GREATER_THAN_MAX_IMPACT: + 'Price impact too high. Please try a different amount or asset pair.', + // not sure why this error-code is not upper-cased + 'No routes found with enough liquidity': 'No routes found with enough liquidity.', +}; + +/** + * Uses the Paraswap SDK to fetch the transaction parameters for a 'Sell', or 'Exact In' swap. + * This means that swap in amount is fixed, and the slippage will be applied to the amount received. + * There are two steps in fetching the transaction parameters. First an optimal route is determined + * using the Paraswap SDK. Then the transaction parameters are fetched using the optimal route. + * @param {SwapData} swapIn + * @param {SwapData} swapOut + * @param {ChainId} chainId + * @param {string} userAddress + * @param {number} maxSlippage + * @param {boolean} [max] + * @returns {Promise} + */ +export async function fetchExactInTxParams( + swapIn: SwapData, + swapOut: SwapData, + chainId: ChainId, + userAddress: string, + maxSlippage: number, + max?: boolean +): Promise { + if (!swapIn.amount || swapIn.amount === '0' || isNaN(+swapIn.amount)) { + return { + swapCallData: '', + augustus: '', + inputAmount: '0', + outputAmount: '0', + inputAmountUSD: '0', + outputAmountUSD: '0', + }; + } + + const swapInAmount = valueToBigNumber(swapIn.amount); + const amount = normalizeBN(swapInAmount, swapIn.decimals * -1); + + const options: RateOptions = { + partner: 'aave', + }; + + if (max) { + options.excludeContractMethods = [ContractMethod.simpleSwap]; + } + + const swapper = ExactInSwapper(chainId); + const route = await swapper.getRate( + amount.toFixed(0), + swapIn.underlyingAsset, + swapIn.decimals, + swapOut.underlyingAsset, + swapOut.decimals, + userAddress, + options + ); + + const { swapCallData, augustus, destAmountWithSlippage } = await swapper.getTransactionParams( + swapIn.underlyingAsset, + swapIn.decimals, + swapOut.underlyingAsset, + swapOut.decimals, + userAddress, + route, + maxSlippage + ); + + return { + swapCallData, + augustus, + inputAmount: swapIn.amount, + outputAmount: normalize(destAmountWithSlippage, swapOut.decimals), + inputAmountUSD: route.srcUSD, + outputAmountUSD: route.destUSD, + }; +} + +/** + * Uses the Paraswap SDK to fetch the transaction parameters for a 'Buy', or 'Exact Out' swap. + * This means that amount received is fixed, and positive slippage will be applied to the input amount. + * There are two steps in fetching the transaction parameters. First an optimal route is determined + * using the Paraswap SDK. Then the transaction parameters are fetched using the optimal route. + * @param {SwapData} swapIn + * @param {SwapData} swapOut + * @param {ChainId} chainId + * @param {string} userAddress + * @param {number} maxSlippage + * @param {boolean} max + * @returns {Promise} + */ +export async function fetchExactOutTxParams( + swapIn: SwapData, + swapOut: SwapData, + chainId: ChainId, + userAddress: string, + maxSlippage: number, + max: boolean +): Promise { + if (!swapOut.amount || swapOut.amount === '0' || isNaN(+swapOut.amount)) { + return { + swapCallData: '', + augustus: '', + inputAmount: '0', + outputAmount: '0', + inputAmountUSD: '0', + outputAmountUSD: '0', + }; + } + + let swapOutAmount = valueToBigNumber(swapOut.amount); + if (max) { + // variableBorrowAPY in most cases should be higher than stableRate so while this is slightly inaccurate it should be enough + swapOutAmount = swapOutAmount.plus( + swapOutAmount.multipliedBy(swapIn.variableBorrowAPY).dividedBy(360 * 24) + ); + } + const amount = normalizeBN(swapOutAmount, swapOut.decimals * -1); + + const options: RateOptions = { + partner: 'aave', + }; + + if (max) { + options.excludeContractMethods = [ContractMethod.simpleBuy]; + } + + const swapper = ExactOutSwapper(chainId); + + const route = await swapper.getRate( + amount.toFixed(0), + swapIn.underlyingAsset, + swapIn.decimals, + swapOut.underlyingAsset, + swapOut.decimals, + userAddress, + options + ); + + const { swapCallData, augustus, srcAmountWithSlippage } = await swapper.getTransactionParams( + swapIn.underlyingAsset, + swapIn.decimals, + swapOut.underlyingAsset, + swapOut.decimals, + userAddress, + route, + maxSlippage + ); + + return { + swapCallData, + augustus, + inputAmount: normalize(srcAmountWithSlippage, swapIn.decimals), + outputAmount: normalize(route.destAmount, swapOut.decimals), + inputAmountUSD: route.srcUSD, + outputAmountUSD: route.destUSD, + }; +} + +const ExactInSwapper = (chainId: ChainId) => { + const paraSwap = getParaswap(chainId); + + const getRate = async ( + amount: string, + srcToken: string, + srcDecimals: number, + destToken: string, + destDecimals: number, + userAddress: string, + options: RateOptions + ) => { + const priceRoute = await paraSwap.getRate({ + amount, + srcToken, + srcDecimals, + destToken, + destDecimals, + userAddress, + side: SwapSide.SELL, + options, + }); + + return priceRoute; + }; + + const getTransactionParams = async ( + srcToken: string, + srcDecimals: number, + destToken: string, + destDecimals: number, + user: string, + route: OptimalRate, + maxSlippage: number + ) => { + const { swapCallData, augustus, destAmountWithSlippage } = await getSwapCallData({ + srcToken, + srcDecimals, + destToken, + destDecimals, + user, + route, + chainId: chainId, + maxSlippage, + }); + + return { + swapCallData, + augustus, + destAmountWithSlippage, + }; + }; + + return { + getRate, + getTransactionParams, + }; +}; + +const ExactOutSwapper = (chainId: ChainId) => { + const paraSwap = getParaswap(chainId); + + const getRate = async ( + amount: string, + srcToken: string, + srcDecimals: number, + destToken: string, + destDecimals: number, + userAddress: string, + options: RateOptions + ) => { + const priceRoute = await paraSwap.getRate({ + amount, + srcToken, + srcDecimals, + destToken, + destDecimals, + userAddress, + side: SwapSide.BUY, + options, + }); + + return priceRoute; + }; + + const getTransactionParams = async ( + srcToken: string, + srcDecimals: number, + destToken: string, + destDecimals: number, + user: string, + route: OptimalRate, + maxSlippage: number + ) => { + const { swapCallData, augustus, srcAmountWithSlippage } = await getRepayCallData({ + srcToken, + srcDecimals, + destToken, + destDecimals, + user, + route, + chainId, + maxSlippage, + }); + + return { + swapCallData, + augustus, + srcAmountWithSlippage, + }; + }; + + return { + getRate, + getTransactionParams, + }; +}; + +const getSwapCallData = async ({ + srcToken, + srcDecimals, + destToken, + destDecimals, + user, + route, + chainId, + maxSlippage, +}: GetSwapCallDataProps) => { + const paraSwap = getParaswap(chainId); + const destAmountWithSlippage = new BigNumberZeroDecimal(route.destAmount) + .multipliedBy(100 - maxSlippage) + .dividedBy(100) + .toFixed(0); + + try { + const params = await paraSwap.buildTx( + { + srcToken, + destToken, + srcAmount: route.srcAmount, + destAmount: destAmountWithSlippage, + priceRoute: route, + userAddress: user, + partner: 'aave', + srcDecimals, + destDecimals, + }, + { ignoreChecks: true } + ); + + return { + swapCallData: (params as TransactionParams).data, + augustus: (params as TransactionParams).to, + destAmountWithSlippage, + }; + } catch (e) { + console.log(e); + throw new Error('Error getting txParams'); + } +}; + +const getRepayCallData = async ({ + srcToken, + srcDecimals, + destToken, + destDecimals, + user, + route, + chainId, + maxSlippage, +}: GetSwapAndRepayCallDataProps) => { + const paraSwap = getParaswap(chainId); + const srcAmountWithSlippage = new BigNumberZeroDecimal(route.srcAmount) + .multipliedBy(100 + maxSlippage) + .dividedBy(100) + .toFixed(0); + + try { + const params = await paraSwap.buildTx( + { + srcToken, + destToken, + srcAmount: srcAmountWithSlippage, + destAmount: route.destAmount, + priceRoute: route, + userAddress: user, + partner: 'aave', + srcDecimals, + destDecimals, + }, + { ignoreChecks: true } + ); + + return { + swapCallData: (params as TransactionParams).data, + augustus: (params as TransactionParams).to, + srcAmountWithSlippage, + }; + } catch (e) { + console.log(e); + throw new Error('Error getting txParams'); + } +}; diff --git a/src/hooks/paraswap/useCollateralRepaySwap.tsx b/src/hooks/paraswap/useCollateralRepaySwap.tsx new file mode 100644 index 0000000000..472d02e976 --- /dev/null +++ b/src/hooks/paraswap/useCollateralRepaySwap.tsx @@ -0,0 +1,146 @@ +import { useCallback, useEffect, useMemo, useState } from 'react'; + +import { + fetchExactInTxParams, + fetchExactOutTxParams, + MESSAGE_MAP, + SwapData, + SwapVariant, + UseSwapProps, +} from './common'; + +type UseRepayWithCollateralProps = UseSwapProps & { + variant: SwapVariant; +}; + +export const useCollateralRepaySwap = ({ + chainId, + max, + maxSlippage, + skip, + swapIn, + swapOut, + userAddress, + variant, +}: UseRepayWithCollateralProps) => { + const [loading, setLoading] = useState(false); + const [error, setError] = useState(''); + const [swapCallData, setSwapCallData] = useState(''); + const [augustus, setAugustus] = useState(''); + const [inputAmount, setInputAmount] = useState(''); + const [outputAmount, setOutputAmount] = useState(''); + const [outputAmountUSD, setOutputAmountUSD] = useState(''); + const [inputAmountUSD, setInputAmountUSD] = useState(''); + + const swapInData = useMemo(() => { + const swapData: SwapData = { + underlyingAsset: swapIn.underlyingAsset, + decimals: swapIn.decimals, + supplyAPY: swapIn.supplyAPY, + amount: swapIn.amount, + variableBorrowAPY: swapIn.variableBorrowAPY, + }; + return swapData; + }, [ + swapIn.amount, + swapIn.decimals, + swapIn.supplyAPY, + swapIn.underlyingAsset, + swapIn.variableBorrowAPY, + ]); + + const swapOutData = useMemo(() => { + const swapData: SwapData = { + underlyingAsset: swapOut.underlyingAsset, + decimals: swapOut.decimals, + supplyAPY: swapOut.supplyAPY, + amount: swapOut.amount, + variableBorrowAPY: swapOut.variableBorrowAPY, + }; + return swapData; + }, [ + swapOut.amount, + swapOut.decimals, + swapOut.supplyAPY, + swapOut.underlyingAsset, + swapOut.variableBorrowAPY, + ]); + + const exactInTx = useCallback(() => { + return fetchExactInTxParams(swapInData, swapOutData, chainId, userAddress, maxSlippage); + }, [chainId, maxSlippage, swapInData, swapOutData, userAddress]); + + const exactOutTx = useCallback( + () => fetchExactOutTxParams(swapInData, swapOutData, chainId, userAddress, maxSlippage, max), + [chainId, max, maxSlippage, swapInData, swapOutData, userAddress] + ); + + useEffect(() => { + if (skip) return; + + const fetchRoute = async () => { + if (!swapInData.underlyingAsset || !swapOutData.underlyingAsset) return; + + setLoading(true); + + try { + let route; + if (variant === 'exactIn') { + route = await exactInTx(); + } else { + route = await exactOutTx(); + } + setError(''); + setSwapCallData(route.swapCallData); + setAugustus(route.augustus); + setInputAmount(route.inputAmount); + setOutputAmount(route.outputAmount); + setInputAmountUSD(route.inputAmountUSD); + setOutputAmountUSD(route.outputAmountUSD); + } catch (e) { + console.error(e); + const message = MESSAGE_MAP[e.message] || 'There was an issue fetching data from Paraswap'; + setError(message); + } finally { + setLoading(false); + } + }; + + // Update the transaction on any dependency change + const timeout = setTimeout(() => { + fetchRoute(); + }, 400); + + // If there are no dependency changes, refresh every 15 seconds + const interval = setInterval( + () => { + fetchRoute(); + }, + error ? 3000 : 15000 + ); + + return () => { + clearTimeout(timeout); + clearInterval(interval); + }; + }, [ + exactInTx, + exactOutTx, + error, + skip, + variant, + swapInData.underlyingAsset, + swapOutData.underlyingAsset, + ]); + + return { + outputAmount, + outputAmountUSD, + inputAmount, + inputAmountUSD, + swapCallData, + augustus, + loading, + error, + }; +}; diff --git a/src/hooks/paraswap/useCollateralSwap.tsx b/src/hooks/paraswap/useCollateralSwap.tsx new file mode 100644 index 0000000000..319588f1b7 --- /dev/null +++ b/src/hooks/paraswap/useCollateralSwap.tsx @@ -0,0 +1,117 @@ +import { useCallback, useEffect, useMemo, useState } from 'react'; + +import { fetchExactInTxParams, MESSAGE_MAP, SwapData, UseSwapProps } from './common'; + +export const useCollateralSwap = ({ + swapIn, + swapOut, + userAddress, + max, + chainId, + skip, + maxSlippage, +}: UseSwapProps) => { + const [loading, setLoading] = useState(false); + const [error, setError] = useState(''); + const [swapCallData, setSwapCallData] = useState(''); + const [augustus, setAugustus] = useState(''); + const [inputAmount, setInputAmount] = useState(''); + const [outputAmount, setOutputAmount] = useState(''); + const [outputAmountUSD, setOutputAmountUSD] = useState(''); + const [inputAmountUSD, setInputAmountUSD] = useState(''); + + const swapInData = useMemo(() => { + const swapData: SwapData = { + underlyingAsset: swapIn.underlyingAsset, + decimals: swapIn.decimals, + supplyAPY: swapIn.supplyAPY, + amount: swapIn.amount, + variableBorrowAPY: swapIn.variableBorrowAPY, + }; + return swapData; + }, [ + swapIn.amount, + swapIn.decimals, + swapIn.supplyAPY, + swapIn.underlyingAsset, + swapIn.variableBorrowAPY, + ]); + + const swapOutData = useMemo(() => { + const swapData: SwapData = { + underlyingAsset: swapOut.underlyingAsset, + decimals: swapOut.decimals, + supplyAPY: swapOut.supplyAPY, + amount: swapOut.amount, + variableBorrowAPY: swapOut.variableBorrowAPY, + }; + return swapData; + }, [ + swapOut.amount, + swapOut.decimals, + swapOut.supplyAPY, + swapOut.underlyingAsset, + swapOut.variableBorrowAPY, + ]); + + const exactInTx = useCallback(() => { + return fetchExactInTxParams(swapInData, swapOutData, chainId, userAddress, maxSlippage, max); + }, [chainId, maxSlippage, swapInData, swapOutData, userAddress, max]); + + useEffect(() => { + if (skip) return; + + const fetchRoute = async () => { + if (!swapInData.underlyingAsset || !swapOutData.underlyingAsset) return; + + setLoading(true); + + try { + const route = await exactInTx(); + + setError(''); + setSwapCallData(route.swapCallData); + setAugustus(route.augustus); + setInputAmount(route.inputAmount); + setOutputAmount(route.outputAmount); + setInputAmountUSD(route.inputAmountUSD); + setOutputAmountUSD(route.outputAmountUSD); + } catch (e) { + console.error(e); + const message = MESSAGE_MAP[e.message] || 'There was an issue fetching data from Paraswap'; + setError(message); + } finally { + setLoading(false); + } + }; + + // Update the transaction on any dependency change + const timeout = setTimeout(() => { + fetchRoute(); + }, 400); + + // If there are no dependency changes, refresh every 15 seconds + const interval = setInterval( + () => { + fetchRoute(); + }, + error ? 3000 : 15000 + ); + + return () => { + clearTimeout(timeout); + clearInterval(interval); + }; + }, [exactInTx, error, skip, swapInData.underlyingAsset, swapOutData.underlyingAsset]); + + return { + outputAmount, + outputAmountUSD, + inputAmount, + inputAmountUSD, + swapCallData, + augustus, + loading, + error, + }; +}; diff --git a/src/hooks/useModal.tsx b/src/hooks/useModal.tsx index 1518c217aa..803ea11710 100644 --- a/src/hooks/useModal.tsx +++ b/src/hooks/useModal.tsx @@ -32,6 +32,7 @@ export interface ModalArgsType { stakeAssetName?: string; currentRateMode?: InterestRate; emode?: EmodeModalType; + isFrozen?: boolean; } export type TxStateType = { @@ -45,7 +46,7 @@ export interface ModalContextType { openSupply: (underlyingAsset: string) => void; openWithdraw: (underlyingAsset: string) => void; openBorrow: (underlyingAsset: string) => void; - openRepay: (underlyingAsset: string, currentRateMode: InterestRate) => void; + openRepay: (underlyingAsset: string, currentRateMode: InterestRate, isFrozen: boolean) => void; openCollateralChange: (underlyingAsset: string) => void; openRateSwitch: (underlyingAsset: string, currentRateMode: InterestRate) => void; openStake: (stakeAssetName: string, icon: string) => void; @@ -107,9 +108,9 @@ export const ModalContextProvider: React.FC = ({ children }) => { setType(ModalType.Borrow); setArgs({ underlyingAsset }); }, - openRepay: (underlyingAsset, currentRateMode) => { + openRepay: (underlyingAsset, currentRateMode, isFrozen) => { setType(ModalType.Repay); - setArgs({ underlyingAsset, currentRateMode }); + setArgs({ underlyingAsset, currentRateMode, isFrozen }); }, openCollateralChange: (underlyingAsset) => { setType(ModalType.CollateralChange); diff --git a/src/hooks/useSwap.ts b/src/hooks/useSwap.ts deleted file mode 100644 index 517e158698..0000000000 --- a/src/hooks/useSwap.ts +++ /dev/null @@ -1,281 +0,0 @@ -import { ChainId } from '@aave/contract-helpers'; -import { BigNumberZeroDecimal, normalize, normalizeBN, valueToBigNumber } from '@aave/math-utils'; -import { - constructBuildTx, - constructFetchFetcher, - constructGetRate, - constructPartialSDK, - TransactionParams, -} from '@paraswap/sdk'; -import { ContractMethod, OptimalRate, SwapSide } from 'paraswap-core'; -import { useCallback, useEffect, useState } from 'react'; - -import { ComputedReserveData } from './app-data-provider/useAppDataProvider'; - -const ParaSwap = (chainId: number) => { - const fetcher = constructFetchFetcher(fetch); // alternatively constructFetchFetcher - return constructPartialSDK( - { - network: chainId, - fetcher, - }, - constructBuildTx, - constructGetRate - ); -}; - -const mainnetParaswap = ParaSwap(ChainId.mainnet); -const polygonParaswap = ParaSwap(ChainId.polygon); -const avalancheParaswap = ParaSwap(ChainId.avalanche); -const fantomParaswap = ParaSwap(ChainId.fantom); -const arbitrumParaswap = ParaSwap(ChainId.arbitrum_one); -const optimismParaswap = ParaSwap(ChainId.optimism); - -const getParaswap = (chainId: ChainId) => { - if (ChainId.mainnet === chainId) return mainnetParaswap; - if (ChainId.polygon === chainId) return polygonParaswap; - if (ChainId.avalanche === chainId) return avalancheParaswap; - if (ChainId.fantom === chainId) return fantomParaswap; - if (ChainId.arbitrum_one === chainId) return arbitrumParaswap; - if (ChainId.optimism === chainId) return optimismParaswap; - throw new Error('chain not supported'); -}; - -type UseSwapProps = { - max?: boolean; - swapIn: ComputedReserveData & { amount: string }; - swapOut: ComputedReserveData & { amount: string }; - variant: 'exactIn' | 'exactOut'; - userId?: string; - chainId: ChainId; - skip?: boolean; -}; - -const MESSAGE_MAP = { - ESTIMATED_LOSS_GREATER_THAN_MAX_IMPACT: 'Price impact to high', - // not sure why this error-code is not upper-cased - 'No routes found with enough liquidity': 'No routes found with enough liquidity', -}; - -export const useSwap = ({ swapIn, swapOut, variant, userId, max, chainId, skip }: UseSwapProps) => { - const paraSwap = getParaswap(chainId); - const [loading, setLoading] = useState(false); - const [error, setError] = useState(''); - const [priceRoute, setPriceRoute] = useState(null); - - const fetchRoute = useCallback(async () => { - if (!swapIn.underlyingAsset || !swapOut.underlyingAsset || !userId) return; - if (variant === 'exactIn' && (!swapIn.amount || swapIn.amount === '0')) return; - if (variant === 'exactOut' && (!swapOut.amount || swapOut.amount === '0')) return; - setLoading(true); - let _amount = valueToBigNumber(variant === 'exactIn' ? swapIn.amount : swapOut.amount); - if (variant === 'exactIn' && max && swapIn.supplyAPY !== '0') { - _amount = _amount.plus(_amount.multipliedBy(swapIn.supplyAPY).dividedBy(360 * 24)); - } - if (variant === 'exactOut' && max) { - // variableBorrowAPY in most cases should be higher than stableRate so while this is slightly inaccurate it should be enough - _amount = _amount.plus(_amount.multipliedBy(swapIn.variableBorrowAPY).dividedBy(360 * 24)); - } - const amount = normalizeBN( - _amount, - (variant === 'exactIn' ? swapIn.decimals : swapOut.decimals) * -1 - ); - - try { - const excludedMethod = - variant === 'exactIn' ? ContractMethod.simpleSwap : ContractMethod.simpleBuy; - const response = await paraSwap.getRate({ - amount: amount.toFixed(0), - srcToken: swapIn.underlyingAsset, - srcDecimals: swapIn.decimals, - destToken: swapOut.underlyingAsset, - destDecimals: swapOut.decimals, - userAddress: userId, - side: variant === 'exactIn' ? SwapSide.SELL : SwapSide.BUY, - options: { - partner: 'aave', - excludeDEXS: - 'ParaSwapPool,ParaSwapPool2,ParaSwapPool3,ParaSwapPool4,ParaSwapPool5,ParaSwapPool6,ParaSwapPool7,ParaSwapPool8,ParaSwapPool9,ParaSwapPool10', - ...(max - ? { - excludeDEXS: - 'Balancer,ParaSwapPool,ParaSwapPool2,ParaSwapPool3,ParaSwapPool4,ParaSwapPool5,ParaSwapPool6,ParaSwapPool7,ParaSwapPool8,ParaSwapPool9,ParaSwapPool10', - excludeContractMethods: [excludedMethod], - } - : {}), - }, - }); - - setError(''); - setPriceRoute(response as OptimalRate); - } catch (e) { - console.log(e); - console.log(e.message); - const message = (MESSAGE_MAP as { [key: string]: string })[e.message]; - setError(message || 'There was an issue fetching data from Paraswap'); - } - setLoading(false); - }, [ - swapIn.amount, - swapIn.underlyingAsset, - swapIn.decimals, - swapOut.amount, - swapOut.underlyingAsset, - swapOut.decimals, - userId, - variant, - max, - chainId, - ]); - - // updates the route on input change - useEffect(() => { - if (skip) return; - setPriceRoute(null); - const timeout = setTimeout(fetchRoute, 400); - return () => clearTimeout(timeout); - }, [fetchRoute, skip]); - - // updates the route based on on interval - useEffect(() => { - if (skip) return; - const interval = setInterval(fetchRoute, error ? 3000 : 15000); - return () => clearInterval(interval); - }, [fetchRoute, error, skip]); - - if (priceRoute) { - return { - // full object needed for building the tx - priceRoute: priceRoute, - outputAmount: normalize( - priceRoute.destAmount ?? '0', - variant === 'exactIn' ? swapOut.decimals : swapOut.decimals - ), - outputAmountUSD: priceRoute.destUSD ?? '0', - inputAmount: normalize( - priceRoute.srcAmount ?? '0', - variant === 'exactIn' ? swapIn.decimals : swapIn.decimals - ), - inputAmountUSD: priceRoute.srcUSD ?? '0', - loading: loading, - error: error, - }; - } - return { - // full object needed for building the tx - priceRoute: null, - outputAmount: '0', - outputAmountUSD: '0', - inputAmount: '0', - inputAmountUSD: '0', - loading: loading, - error: error, - }; -}; - -type GetSwapCallDataProps = { - srcToken: string; - srcDecimals: number; - destToken: string; - destDecimals: number; - user: string; - route: OptimalRate; - max?: boolean; - chainId: ChainId; -}; - -type GetSwapAndRepayCallDataProps = { - srcToken: string; - srcDecimals: number; - destToken: string; - destDecimals: number; - user: string; - route: OptimalRate; - max?: boolean; - chainId: ChainId; - maxSlippage: number; -}; - -export const getSwapCallData = async ({ - srcToken, - srcDecimals, - destToken, - destDecimals, - user, - route, - chainId, -}: GetSwapCallDataProps) => { - const paraSwap = getParaswap(chainId); - const destAmountWithSlippage = new BigNumberZeroDecimal(route.destAmount) - .multipliedBy(99) - .dividedBy(100) - .toFixed(0); - - try { - const params = await paraSwap.buildTx( - { - srcToken, - destToken, - srcAmount: route.srcAmount, - destAmount: destAmountWithSlippage, - priceRoute: route, - userAddress: user, - partner: 'aave', - srcDecimals, - destDecimals, - }, - { ignoreChecks: true } - ); - - return { - swapCallData: (params as TransactionParams).data, - augustus: (params as TransactionParams).to, - }; - } catch (e) { - console.log(e); - throw new Error('Error getting txParams'); - } -}; - -export const getRepayCallData = async ({ - srcToken, - srcDecimals, - destToken, - destDecimals, - user, - route, - chainId, - maxSlippage, -}: GetSwapAndRepayCallDataProps) => { - const paraSwap = getParaswap(chainId); - const srcAmountWithSlippage = new BigNumberZeroDecimal(route.srcAmount) - .multipliedBy(100 + maxSlippage) - .dividedBy(100) - .toFixed(0); - - try { - const params = await paraSwap.buildTx( - { - srcToken, - destToken, - srcAmount: srcAmountWithSlippage, - destAmount: route.destAmount, - priceRoute: route, - userAddress: user, - partner: 'aave', - srcDecimals, - destDecimals, - }, - { ignoreChecks: true } - ); - - return { - swapCallData: (params as TransactionParams).data, - augustus: (params as TransactionParams).to, - srcAmountWithSlippage, - }; - } catch (e) { - console.log(e); - throw new Error('Error getting txParams'); - } -}; diff --git a/src/locales/en/messages.js b/src/locales/en/messages.js index 4b3036846e..792f1cbb23 100644 --- a/src/locales/en/messages.js +++ b/src/locales/en/messages.js @@ -1 +1 @@ -/*eslint-disable*/module.exports={messages:{"<0>Ampleforth is an asset affected by rebasing. Visit the <1>documentation or <2>Ampleforth's FAQ to learn more.":"<0>Ampleforth is an asset affected by rebasing. Visit the <1>documentation or <2>Ampleforth's FAQ to learn more.","<0>Attention: Parameter changes via governance can alter your account health factor and risk of liquidation. Follow the <1>Aave governance forum for updates.":"<0>Attention: Parameter changes via governance can alter your account health factor and risk of liquidation. Follow the <1>Aave governance forum for updates.","AAVE holders can stake their AAVE in the Safety Module to add more security to the protocol and earn Safety Incentives. In the case of a shortfall event, up to 30% of your stake can be slashed to cover the deficit, providing an additional layer of protection for the protocol.":"AAVE holders can stake their AAVE in the Safety Module to add more security to the protocol and earn Safety Incentives. In the case of a shortfall event, up to 30% of your stake can be slashed to cover the deficit, providing an additional layer of protection for the protocol.","ACTIVATE COOLDOWN":"ACTIVATE COOLDOWN","APR":"APR","APY":"APY","APY type":"APY type","APY, stable":"APY, stable","APY, variable":"APY, variable","AToken supply is not zero":"AToken supply is not zero","Aave Governance":"Aave Governance","Aave is a fully decentralized, community governed protocol by the AAVE token-holders. AAVE token-holders collectively discuss, propose, and vote on upgrades to the protocol. AAVE token-holders can either vote themselves on new proposals or delagate to an address of choice. To learn more check out the Governance documentation":"Aave is a fully decentralized, community governed protocol by the AAVE token-holders. AAVE token-holders collectively discuss, propose, and vote on upgrades to the protocol. AAVE token-holders can either vote themselves on new proposals or delagate to an address of choice. To learn more check out the Governance documentation","Aave per month":"Aave per month","Account":"Account","Action cannot be performed because the reserve is frozen":"Action cannot be performed because the reserve is frozen","Action cannot be performed because the reserve is paused":"Action cannot be performed because the reserve is paused","Action requires an active reserve":"Action requires an active reserve","Add to wallet":"Add to wallet","Add {0} to wallet to track your balance.":["Add ",["0"]," to wallet to track your balance."],"Address is not a contract":"Address is not a contract","All Assets":"All Assets","All done!":"All done!","All proposals":"All proposals","Allowance required action":"Allowance required action","Allows you to decide whether to use a supplied asset as collateral. An asset used as collateral will affect your borrowing power and health factor.":"Allows you to decide whether to use a supplied asset as collateral. An asset used as collateral will affect your borrowing power and health factor.","Allows you to switch between <0>variable and <1>stable interest rates, where variable rate can increase and decrease depending on the amount of liquidity in the reserve, and stable rate will stay the same for the duration of your loan.":"Allows you to switch between <0>variable and <1>stable interest rates, where variable rate can increase and decrease depending on the amount of liquidity in the reserve, and stable rate will stay the same for the duration of your loan.","Already on cooldown":"Already on cooldown","Amount":"Amount","Amount must be greater than 0":"Amount must be greater than 0","Ampleforth FAQ":"Ampleforth FAQ","An error has occurred fetching the proposal metadata from IPFS.":"An error has occurred fetching the proposal metadata from IPFS.","Approval":"Approval","Approve confirmed":"Approve confirmed","Approve to continue":"Approve to continue","Approved":"Approved","Approving {symbol}...":["Approving ",["symbol"],"..."],"Array parameters that should be equal length are not":"Array parameters that should be equal length are not","Asset":"Asset","Asset can only be used as collateral in isolation mode only.":"Asset can only be used as collateral in isolation mode only.","Asset cannot be used as collateral.":"Asset cannot be used as collateral.","Asset category":"Asset category","Asset is not borrowable in isolation mode":"Asset is not borrowable in isolation mode","Asset is not listed":"Asset is not listed","Asset supply is limited to a certain amount to reduce protocol exposure to the asset and to help manage risks involved.":"Asset supply is limited to a certain amount to reduce protocol exposure to the asset and to help manage risks involved.","Asset to delegate":"Asset to delegate","Assets":"Assets","Assets to borrow":"Assets to borrow","Assets to supply":"Assets to supply","Author":"Author","Available":"Available","Available assets":"Available assets","Available liquidity":"Available liquidity","Available rewards":"Available rewards","Available to borrow":"Available to borrow","Available to supply":"Available to supply","Back to Dashboard":"Back to Dashboard","Balance":"Balance","Be careful - You are very close to liquidation. Consider depositing more collateral or paying down some of your borrowed positions":"Be careful - You are very close to liquidation. Consider depositing more collateral or paying down some of your borrowed positions","Before supplying":"Before supplying","Before supplying, you need to approve its usage by the Aave protocol. You can learn more in our <0>FAQ":"Before supplying, you need to approve its usage by the Aave protocol. You can learn more in our <0>FAQ","Blocked Address":"Blocked Address","Borrow":"Borrow","Borrow APY rate":"Borrow APY rate","Borrow APY, stable":"Borrow APY, stable","Borrow APY, variable":"Borrow APY, variable","Borrow and repay in same block is not allowed":"Borrow and repay in same block is not allowed","Borrow cap":"Borrow cap","Borrow cap is exceeded":"Borrow cap is exceeded","Borrow power used":"Borrow power used","Borrow {symbol}":["Borrow ",["symbol"]],"Borrowed":"Borrowed","Borrowing is currently unavailable for {0}.":["Borrowing is currently unavailable for ",["0"],"."],"Borrowing is not enabled":"Borrowing is not enabled","Borrowing is unavailable because you’re using Isolation mode. To manage Isolation mode visit your <0>Dashboard.":"Borrowing is unavailable because you’re using Isolation mode. To manage Isolation mode visit your <0>Dashboard.","Borrowing is unavailable because you’ve enabled Efficiency Mode (E-Mode) and Isolation mode. To manage E-Mode and Isolation mode visit your <0>Dashboard.":"Borrowing is unavailable because you’ve enabled Efficiency Mode (E-Mode) and Isolation mode. To manage E-Mode and Isolation mode visit your <0>Dashboard.","Borrowing is unavailable because you’ve enabled Efficiency Mode (E-Mode) for {0} category. To manage E-Mode categories visit your <0>Dashboard.":["Borrowing is unavailable because you’ve enabled Efficiency Mode (E-Mode) for ",["0"]," category. To manage E-Mode categories visit your <0>Dashboard."],"Borrowing of this asset is limited to a certain amount to minimize liquidity pool insolvency.":"Borrowing of this asset is limited to a certain amount to minimize liquidity pool insolvency.","Borrowing power and assets are limited due to Isolation mode.":"Borrowing power and assets are limited due to Isolation mode.","Borrowing this amount will reduce your health factor and increase risk of liquidation.":"Borrowing this amount will reduce your health factor and increase risk of liquidation.","Borrowing {symbol}":["Borrowing ",["symbol"]],"CLAIM {symbol}":["CLAIM ",["symbol"]],"CLAIMING {symbol}":["CLAIMING ",["symbol"]],"Can be collateral":"Can be collateral","Can be executed":"Can be executed","Cancel":"Cancel","Cannot disable E-Mode":"Cannot disable E-Mode","Cap reached. Lower supply amount":"Cap reached. Lower supply amount","Claim":"Claim","Claim AAVE":"Claim AAVE","Claim all":"Claim all","Claim all rewards":"Claim all rewards","Claim {0}":["Claim ",["0"]],"Claimable AAVE":"Claimable AAVE","Claimed":"Claimed","Claiming":"Claiming","Close":"Close","Collateral":"Collateral","Collateral amount to repay with":"Collateral amount to repay with","Collateral is (mostly) the same currency that is being borrowed":"Collateral is (mostly) the same currency that is being borrowed","Collateral usage":"Collateral usage","Collateral usage is limited because of Isolation mode.":"Collateral usage is limited because of Isolation mode.","Collateral usage is limited because of isolation mode. <0>Learn More":"Collateral usage is limited because of isolation mode. <0>Learn More","Collateralization":"Collateralization","Collector Contract":"Collector Contract","Collector Info":"Collector Info","Connect wallet":"Connect wallet","Cooldown period":"Cooldown period","Cooldown period warning":"Cooldown period warning","Cooldown time left":"Cooldown time left","Cooldown to unstake":"Cooldown to unstake","Cooling down...":"Cooling down...","Copy address":"Copy address","Copy error message":"Copy error message","Copy error text":"Copy error text","Created":"Created","Current LTV":"Current LTV","Current differential":"Current differential","Current votes":"Current votes","Dark mode":"Dark mode","Dashboard":"Dashboard","Data couldn't be fetched, please reload graph.":"Data couldn't be fetched, please reload graph.","Debt":"Debt","Debt amount to repay":"Debt amount to repay","Debt ceiling is exceeded":"Debt ceiling is exceeded","Debt ceiling is not zero":"Debt ceiling is not zero","Debt ceiling limits the amount possible to borrow against this asset by protocol users. Debt ceiling is specific to assets in isolation mode and is denoted in USD.":"Debt ceiling limits the amount possible to borrow against this asset by protocol users. Debt ceiling is specific to assets in isolation mode and is denoted in USD.","Define Retry with Approval text":"Define Retry with Approval text","Delegate":"Delegate","Delegating":"Delegating","Delegation":"Delegation","Details":"Details","Developers":"Developers","Differential":"Differential","Disable E-Mode":"Disable E-Mode","Disable testnet":"Disable testnet","Disable {symbol} as collateral":["Disable ",["symbol"]," as collateral"],"Disabled":"Disabled","Disabling E-Mode":"Disabling E-Mode","Disabling this asset as collateral affects your borrowing power and Health Factor.":"Disabling this asset as collateral affects your borrowing power and Health Factor.","Disconnect Wallet":"Disconnect Wallet","Discord":"Discord","Discord channel":"Discord channel","Due to a precision bug in the stETH contract, this asset can not be used in flashloan transactions":"Due to a precision bug in the stETH contract, this asset can not be used in flashloan transactions","Due to the Horizon bridge exploit, certain assets on the Harmony network are not at parity with Ethereum, which affects the Aave V3 Harmony market.":"Due to the Horizon bridge exploit, certain assets on the Harmony network are not at parity with Ethereum, which affects the Aave V3 Harmony market.","E-Mode":"E-Mode","E-Mode Category":"E-Mode Category","E-Mode category":"E-Mode category","E-Mode increases your LTV for a selected category of assets up to 97%. <0>Learn more":"E-Mode increases your LTV for a selected category of assets up to 97%. <0>Learn more","E-Mode increases your LTV for a selected category of assets up to<0/>. <1>Learn more":"E-Mode increases your LTV for a selected category of assets up to<0/>. <1>Learn more","E-Mode increases your LTV for a selected category of assets, meaning that when E-mode is enabled, you will have higher borrowing power over assets of the same E-mode category which are defined by Aave Governance. You can enter E-Mode from your <0>Dashboard. To learn more about E-Mode and applied restrictions in <1>FAQ or <2>Aave V3 Technical Paper.":"E-Mode increases your LTV for a selected category of assets, meaning that when E-mode is enabled, you will have higher borrowing power over assets of the same E-mode category which are defined by Aave Governance. You can enter E-Mode from your <0>Dashboard. To learn more about E-Mode and applied restrictions in <1>FAQ or <2>Aave V3 Technical Paper.","Efficiency mode (E-Mode)":"Efficiency mode (E-Mode)","Emode":"Emode","Enable E-Mode":"Enable E-Mode","Enable {symbol} as collateral":["Enable ",["symbol"]," as collateral"],"Enabled":"Enabled","Enabled in isolation":"Enabled in isolation","Enabling E-Mode":"Enabling E-Mode","Enabling E-Mode only allows you to borrow assets belonging to the selected category. Please visit our <0>FAQ guide to learn more about how it works and the applied restrictions.":"Enabling E-Mode only allows you to borrow assets belonging to the selected category. Please visit our <0>FAQ guide to learn more about how it works and the applied restrictions.","Enabling this asset as collateral increases your borrowing power and Health Factor. However, it can get liquidated if your health factor drops below 1.":"Enabling this asset as collateral increases your borrowing power and Health Factor. However, it can get liquidated if your health factor drops below 1.","English":"English","Enter ETH address":"Enter ETH address","Enter an address to track in watch-only mode":"Enter an address to track in watch-only mode","Enter an amount":"Enter an amount","Error connecting. Try refreshing the page.":"Error connecting. Try refreshing the page.","Executed":"Executed","Expires":"Expires","FAQ":"FAQ","Faucet":"Faucet","Faucet {0}":["Faucet ",["0"]],"Filter":"Filter","For repayment of a specific type of debt, the user needs to have debt that type":"For repayment of a specific type of debt, the user needs to have debt that type","Forum discussion":"Forum discussion","French":"French","Funds in the Safety Module":"Funds in the Safety Module","Get ABP Token":"Get ABP Token","Github":"Github","Global settings":"Global settings","Go Back":"Go Back","Go back":"Go back","Go to Balancer Pool":"Go to Balancer Pool","Governance":"Governance","Greek":"Greek","Health factor":"Health factor","Health factor is lesser than the liquidation threshold":"Health factor is lesser than the liquidation threshold","Health factor is not below the threshold":"Health factor is not below the threshold","Hide":"Hide","I acknowledge the risks involved.":"I acknowledge the risks involved.","I understand how cooldown ({0}) and unstaking ({1}) work":["I understand how cooldown (",["0"],") and unstaking (",["1"],") work"],"If the error continues to happen,<0/> you may report it to this":"If the error continues to happen,<0/> you may report it to this","If the health factor goes below 1, the liquidation of your collateral might be triggered.":"If the health factor goes below 1, the liquidation of your collateral might be triggered.","If you DO NOT unstake within {0} of unstake window, you will need to activate cooldown process again.":["If you DO NOT unstake within ",["0"]," of unstake window, you will need to activate cooldown process again."],"If your loan to value goes above the liquidation threshold your collateral supplied may be liquidated.":"If your loan to value goes above the liquidation threshold your collateral supplied may be liquidated.","In E-Mode some assets are not borrowable. Exit E-Mode to get access to all assets":"In E-Mode some assets are not borrowable. Exit E-Mode to get access to all assets","In Isolation mode, you cannot supply other assets as collateral. A global debt ceiling limits the borrowing power of the isolated asset. To exit isolation mode disable {0} as collateral before borrowing another asset. Read more in our <0>FAQ":["In Isolation mode, you cannot supply other assets as collateral. A global debt ceiling limits the borrowing power of the isolated asset. To exit isolation mode disable ",["0"]," as collateral before borrowing another asset. Read more in our <0>FAQ"],"Inconsistent flashloan parameters":"Inconsistent flashloan parameters","Interest rate rebalance conditions were not met":"Interest rate rebalance conditions were not met","Interest rate strategy":"Interest rate strategy","Invalid amount to burn":"Invalid amount to burn","Invalid amount to mint":"Invalid amount to mint","Invalid bridge protocol fee":"Invalid bridge protocol fee","Invalid expiration":"Invalid expiration","Invalid flashloan premium":"Invalid flashloan premium","Invalid return value of the flashloan executor function":"Invalid return value of the flashloan executor function","Invalid signature":"Invalid signature","Isolated":"Isolated","Isolated Debt Ceiling":"Isolated Debt Ceiling","Isolated assets have limited borrowing power and other assets cannot be used as collateral.":"Isolated assets have limited borrowing power and other assets cannot be used as collateral.","Join the community discussion":"Join the community discussion","Language":"Language","Learn more":"Learn more","Learn more about risks involved":"Learn more about risks involved","Learn more in our <0>FAQ guide":"Learn more in our <0>FAQ guide","Links":"Links","Liquidation <0/> threshold":"Liquidation <0/> threshold","Liquidation at":"Liquidation at","Liquidation penalty":"Liquidation penalty","Liquidation risk":"Liquidation risk","Liquidation risk parameters":"Liquidation risk parameters","Liquidation threshold":"Liquidation threshold","Liquidation value":"Liquidation value","Loading data...":"Loading data...","Ltv validation failed":"Ltv validation failed","MAX":"MAX","Market":"Market","Markets":"Markets","Max":"Max","Max LTV":"Max LTV","Max slashing":"Max slashing","Max slippage rate":"Max slippage rate","Maximum amount available to borrow against this asset is limited because debt ceiling is at {0}%.":["Maximum amount available to borrow against this asset is limited because debt ceiling is at ",["0"],"%."],"Maximum amount available to borrow is limited because protocol borrow cap is nearly reached.":"Maximum amount available to borrow is limited because protocol borrow cap is nearly reached.","Maximum amount available to supply is <0/> {0} (<1/>).":["Maximum amount available to supply is <0/> ",["0"]," (<1/>)."],"Maximum amount available to supply is limited because protocol supply cap is at {0}%.":["Maximum amount available to supply is limited because protocol supply cap is at ",["0"],"%."],"Maximum loan to value":"Maximum loan to value","Menu":"Menu","Minimum received":"Minimum received","More":"More","NAY":"NAY","Need help connecting a wallet? <0>Read our FAQ":"Need help connecting a wallet? <0>Read our FAQ","Net APR":"Net APR","Net APY":"Net APY","Net APY is the combined effect of all supply and borrow positions on net worth, including incentives. It is possible to have a negative net APY if debt APY is higher than supply APY.":"Net APY is the combined effect of all supply and borrow positions on net worth, including incentives. It is possible to have a negative net APY if debt APY is higher than supply APY.","Net worth":"Net worth","Network":"Network","Network not supported for this wallet":"Network not supported for this wallet","New APY":"New APY","No rewards to claim":"No rewards to claim","No search results for":"No search results for","No voting power":"No voting power","None":"None","Not a valid address":"Not a valid address","Not enough balance on your wallet":"Not enough balance on your wallet","Not enough collateral to repay this amount of debt with":"Not enough collateral to repay this amount of debt with","Not enough staked balance":"Not enough staked balance","Not enough voting power to participate in this proposal":"Not enough voting power to participate in this proposal","Not reached":"Not reached","Nothing borrowed yet":"Nothing borrowed yet","Nothing staked":"Nothing staked","Nothing supplied yet":"Nothing supplied yet","Notify":"Notify","Ok, Close":"Ok, Close","Ok, I got it":"Ok, I got it","Operation not supported":"Operation not supported","Oracle price":"Oracle price","Overview":"Overview","Page not found":"Page not found","Participating in this {symbol} reserve gives annualized rewards.":["Participating in this ",["symbol"]," reserve gives annualized rewards."],"Pending...":"Pending...","Per the community, the Fantom market has been frozen.":"Per the community, the Fantom market has been frozen.","Please connect a wallet to view your personal information here.":"Please connect a wallet to view your personal information here.","Please connect your wallet to get free testnet assets.":"Please connect your wallet to get free testnet assets.","Please connect your wallet to see your supplies, borrowings, and open positions.":"Please connect your wallet to see your supplies, borrowings, and open positions.","Please enter a valid wallet address.":"Please enter a valid wallet address.","Please switch to {networkName}.":["Please switch to ",["networkName"],"."],"Please, connect your wallet":"Please, connect your wallet","Pool addresses provider is not registered":"Pool addresses provider is not registered","Price impact":"Price impact","Proposal details":"Proposal details","Proposal overview":"Proposal overview","Proposals":"Proposals","Proposition power":"Proposition power","Protocol borrow cap at 100% for this asset. Further borrowing unavailable.":"Protocol borrow cap at 100% for this asset. Further borrowing unavailable.","Protocol borrow cap is at 100% for this asset. Further borrowing unavailable.":"Protocol borrow cap is at 100% for this asset. Further borrowing unavailable.","Protocol debt ceiling is at 100% for this asset. Further borrowing against this asset is unavailable.":"Protocol debt ceiling is at 100% for this asset. Further borrowing against this asset is unavailable.","Protocol debt ceiling is at 100% for this asset. Futher borrowing against this asset is unavailable.":"Protocol debt ceiling is at 100% for this asset. Futher borrowing against this asset is unavailable.","Protocol supply cap at 100% for this asset. Further supply unavailable.":"Protocol supply cap at 100% for this asset. Further supply unavailable.","Protocol supply cap is at 100% for this asset. Further supply unavailable.":"Protocol supply cap is at 100% for this asset. Further supply unavailable.","Quorum":"Quorum","Raw-Ipfs":"Raw-Ipfs","Reached":"Reached","Received":"Received","Recipient address":"Recipient address","Rejected connection request":"Rejected connection request","Reload":"Reload","Reload the page":"Reload the page","Remaining debt":"Remaining debt","Remaining supply":"Remaining supply","Repay":"Repay","Repay with":"Repay with","Repay {symbol}":["Repay ",["symbol"]],"Repaying {symbol}":["Repaying ",["symbol"]],"Reserve Size":"Reserve Size","Reserve factor":"Reserve factor","Reserve factor is a percentage of interest which goes to a {0} that is controlled by Aave governance to promote ecosystem growth.":["Reserve factor is a percentage of interest which goes to a ",["0"]," that is controlled by Aave governance to promote ecosystem growth."],"Reserve status & configuration":"Reserve status & configuration","Retry What?":"Retry What?","Retry with Approval":"Retry with Approval","Retry with approval":"Retry with approval","Review approval tx details":"Review approval tx details","Review tx":"Review tx","Review tx details":"Review tx details","Reward(s) to claim":"Reward(s) to claim","Rewards APR":"Rewards APR","Risk details":"Risk details","SEE CHARTS":"SEE CHARTS","Safety of your deposited collateral against the borrowed assets and its underlying value.":"Safety of your deposited collateral against the borrowed assets and its underlying value.","Seatbelt report":"Seatbelt report","Seems like we can't switch the network automatically. Please check if you can change it from the wallet.":"Seems like we can't switch the network automatically. Please check if you can change it from the wallet.","Select":"Select","Select APY type to switch":"Select APY type to switch","Select language":"Select language","Select token to add":"Select token to add","Select token to view in block explorer":"Select token to view in block explorer","Setup notifications about your Health Factor using the Hal app.":"Setup notifications about your Health Factor using the Hal app.","Share on twitter":"Share on twitter","Show":"Show","Show assets with 0 balance":"Show assets with 0 balance","Since this asset is frozen, the only available actions are withdraw and repay which can be accessed from the <0>Dashboard":"Since this asset is frozen, the only available actions are withdraw and repay which can be accessed from the <0>Dashboard","Since this is a test network, you can get any of the assets if you have ETH on your wallet":"Since this is a test network, you can get any of the assets if you have ETH on your wallet","Something went wrong":"Something went wrong","Sorry, an unexpected error happened. In the meantime you may try reloading the page, or come back later.":"Sorry, an unexpected error happened. In the meantime you may try reloading the page, or come back later.","Sorry, we couldn't find the page you were looking for.":"Sorry, we couldn't find the page you were looking for.","Spanish":"Spanish","Stable":"Stable","Stable Interest Type is disabled for this currency":"Stable Interest Type is disabled for this currency","Stable borrowing is enabled":"Stable borrowing is enabled","Stable borrowing is not enabled":"Stable borrowing is not enabled","Stable debt supply is not zero":"Stable debt supply is not zero","Stable interest rate will <0>stay the same for the duration of your loan. Recommended for long-term loan periods and for users who prefer predictability.":"Stable interest rate will <0>stay the same for the duration of your loan. Recommended for long-term loan periods and for users who prefer predictability.","Stablecoin":"Stablecoin","Stake":"Stake","Stake AAVE":"Stake AAVE","Stake ABPT":"Stake ABPT","Stake cooldown activated":"Stake cooldown activated","Staked":"Staked","Staking":"Staking","Staking APR":"Staking APR","Started":"Started","State":"State","Supplied":"Supplied","Supply":"Supply","Supply APY":"Supply APY","Supply apy":"Supply apy","Supply balance":"Supply balance","Supply cap is exceeded":"Supply cap is exceeded","Supply cap on target reserve reached. Try lowering the amount.":"Supply cap on target reserve reached. Try lowering the amount.","Supply {symbol}":["Supply ",["symbol"]],"Supplying your":"Supplying your","Supplying {symbol}":["Supplying ",["symbol"]],"Swap":"Swap","Swapped":"Swapped","Swapping":"Swapping","Switch APY type":"Switch APY type","Switch E-Mode":"Switch E-Mode","Switch E-Mode category":"Switch E-Mode category","Switch Network":"Switch Network","Switch rate":"Switch rate","Switching E-Mode":"Switching E-Mode","Switching rate":"Switching rate","Test Assets":"Test Assets","Testnet mode":"Testnet mode","Testnet mode is ON":"Testnet mode is ON","The % of your total borrowing power used. This is based on the amount of your collateral supplied and the total amount that you can borrow.":"The % of your total borrowing power used. This is based on the amount of your collateral supplied and the total amount that you can borrow.","The Aave Balancer Pool Token (ABPT) is a liquidity pool token. You can receive ABPT by depositing a combination of AAVE + ETH in the Balancer liquidity pool. You can then stake your BPT in the Safety Module to secure the protocol and earn Safety Incentives.":"The Aave Balancer Pool Token (ABPT) is a liquidity pool token. You can receive ABPT by depositing a combination of AAVE + ETH in the Balancer liquidity pool. You can then stake your BPT in the Safety Module to secure the protocol and earn Safety Incentives.","The Maximum LTV ratio represents the maximum borrowing power of a specific collateral. For example, if a collateral has an LTV of 75%, the user can borrow up to 0.75 worth of ETH in the principal currency for every 1 ETH worth of collateral.":"The Maximum LTV ratio represents the maximum borrowing power of a specific collateral. For example, if a collateral has an LTV of 75%, the user can borrow up to 0.75 worth of ETH in the principal currency for every 1 ETH worth of collateral.","The Stable Rate is not enabled for this currency":"The Stable Rate is not enabled for this currency","The address of the pool addresses provider is invalid":"The address of the pool addresses provider is invalid","The app is running in testnet mode. Learn how it works in":"The app is running in testnet mode. Learn how it works in","The caller of the function is not an AToken":"The caller of the function is not an AToken","The caller of this function must be a pool":"The caller of this function must be a pool","The collateral balance is 0":"The collateral balance is 0","The collateral chosen cannot be liquidated":"The collateral chosen cannot be liquidated","The cooldown period is the time required prior to unstaking your tokens(10 days). You can only withdraw your assets from the Security Module after the cooldown period and within the active the unstake window.<0>Learn more":"The cooldown period is the time required prior to unstaking your tokens(10 days). You can only withdraw your assets from the Security Module after the cooldown period and within the active the unstake window.<0>Learn more","The cooldown period is {0}. After {1} of cooldown, you will enter unstake window of {2}. You will continue receiving rewards during cooldown and unstake window.":["The cooldown period is ",["0"],". After ",["1"]," of cooldown, you will enter unstake window of ",["2"],". You will continue receiving rewards during cooldown and unstake window."],"The effects on the health factor would cause liquidation. Try lowering the amount.":"The effects on the health factor would cause liquidation. Try lowering the amount.","The requested amount is greater than the max loan size in stable rate mode":"The requested amount is greater than the max loan size in stable rate mode","The total amount of your assets denominated in USD that can be used as collateral for borrowing assets.":"The total amount of your assets denominated in USD that can be used as collateral for borrowing assets.","The underlying asset cannot be rescued":"The underlying asset cannot be rescued","The underlying balance needs to be greater than 0":"The underlying balance needs to be greater than 0","The weighted average of APY for all borrowed assets, including incentives.":"The weighted average of APY for all borrowed assets, including incentives.","The weighted average of APY for all supplied assets, including incentives.":"The weighted average of APY for all supplied assets, including incentives.","There are not enough funds in the{0}reserve to borrow":["There are not enough funds in the",["0"],"reserve to borrow"],"There is not enough collateral to cover a new borrow":"There is not enough collateral to cover a new borrow","There was some error. Please try changing the parameters or <0><1>copy the error":"There was some error. Please try changing the parameters or <0><1>copy the error","These funds have been borrowed and are not available for withdrawal at this time.":"These funds have been borrowed and are not available for withdrawal at this time.","This action will reduce your health factor. Please be mindful of the increased risk of collateral liquidation.":"This action will reduce your health factor. Please be mindful of the increased risk of collateral liquidation.","This address is blocked on app.aave.com because it is associated with one or more":"This address is blocked on app.aave.com because it is associated with one or more","This asset has almost reached its borrow cap. There is only {messageValue} available to be borrowed from this market.":["This asset has almost reached its borrow cap. There is only ",["messageValue"]," available to be borrowed from this market."],"This asset has almost reached its supply cap. There can only be {messageValue} supplied to this market.":["This asset has almost reached its supply cap. There can only be ",["messageValue"]," supplied to this market."],"This asset has reached its borrow cap. Nothing is available to be borrowed from this market.":"This asset has reached its borrow cap. Nothing is available to be borrowed from this market.","This asset has reached its supply cap. Nothing is available to be supplied from this market.":"This asset has reached its supply cap. Nothing is available to be supplied from this market.","This asset is frozen due to an Aave Protocol Governance decision. <0>More details":"This asset is frozen due to an Aave Protocol Governance decision. <0>More details","This asset is frozen due to an Aave community decision. <0>More details":"This asset is frozen due to an Aave community decision. <0>More details","This gas calculation is only an estimation. Your wallet will set the price of the transaction. You can modify the gas settings directly from your wallet provider.":"This gas calculation is only an estimation. Your wallet will set the price of the transaction. You can modify the gas settings directly from your wallet provider.","This integration was<0>proposed and approvedby the community.":"This integration was<0>proposed and approvedby the community.","This is the total amount available for you to borrow. You can borrow based on your collateral and until the borrow cap is reached.":"This is the total amount available for you to borrow. You can borrow based on your collateral and until the borrow cap is reached.","This is the total amount that you are able to supply to in this reserve. You are able to supply your wallet balance up until the supply cap is reached.":"This is the total amount that you are able to supply to in this reserve. You are able to supply your wallet balance up until the supply cap is reached.","This represents the threshold at which a borrow position will be considered undercollateralized and subject to liquidation for each collateral. For example, if a collateral has a liquidation threshold of 80%, it means that the position will be liquidated when the debt value is worth 80% of the collateral value.":"This represents the threshold at which a borrow position will be considered undercollateralized and subject to liquidation for each collateral. For example, if a collateral has a liquidation threshold of 80%, it means that the position will be liquidated when the debt value is worth 80% of the collateral value.","Time left to be able to withdraw your staked asset.":"Time left to be able to withdraw your staked asset.","Time left to unstake":"Time left to unstake","Time left until the withdrawal window closes.":"Time left until the withdrawal window closes.","To borrow you need to supply any asset to be used as collateral.":"To borrow you need to supply any asset to be used as collateral.","To enable E-mode for the {0} category, all borrow positions outside of this cateogry must be closed.":["To enable E-mode for the ",["0"]," category, all borrow positions outside of this cateogry must be closed."],"To repay on behalf of a user an explicit amount to repay is needed":"To repay on behalf of a user an explicit amount to repay is needed","To request access for this permissioned market, please visit: <0>Acces Provider Name":"To request access for this permissioned market, please visit: <0>Acces Provider Name","Total available":"Total available","Total borrowed":"Total borrowed","Total borrows":"Total borrows","Total emission per day":"Total emission per day","Total market size":"Total market size","Total supplied":"Total supplied","Total voting power":"Total voting power","Total worth":"Total worth","Transaction failed":"Transaction failed","Transaction overview":"Transaction overview","Type of delegation":"Type of delegation","UNSTAKE {symbol}":["UNSTAKE ",["symbol"]],"UNSTAKING {symbol}":["UNSTAKING ",["symbol"]],"Unavailable":"Unavailable","Unbacked":"Unbacked","Unbacked mint cap is exceeded":"Unbacked mint cap is exceeded","Unstake now":"Unstake now","Unstake window":"Unstake window","Used as collateral":"Used as collateral","User cannot withdraw more than the available balance":"User cannot withdraw more than the available balance","User did not borrow the specified currency":"User did not borrow the specified currency","User does not have outstanding stable rate debt on this reserve":"User does not have outstanding stable rate debt on this reserve","User does not have outstanding variable rate debt on this reserve":"User does not have outstanding variable rate debt on this reserve","User is in isolation mode":"User is in isolation mode","User is trying to borrow multiple assets including a siloed one":"User is trying to borrow multiple assets including a siloed one","Utilization Rate":"Utilization Rate","VOTE NAY":"VOTE NAY","VOTE YAE":"VOTE YAE","Variable":"Variable","Variable debt supply is not zero":"Variable debt supply is not zero","Variable interest rate will <0>fluctuate based on the market conditions. Recommended for short-term positions.":"Variable interest rate will <0>fluctuate based on the market conditions. Recommended for short-term positions.","Version 2":"Version 2","Version 3":"Version 3","View contract":"View contract","View details":"View details","View on Explorer":"View on Explorer","Vote":"Vote","Vote NAY":"Vote NAY","Vote YAE":"Vote YAE","Voting power":"Voting power","Voting results":"Voting results","Wallet balance":"Wallet balance","Wallet not detected. Connect or install wallet and retry":"Wallet not detected. Connect or install wallet and retry","Wallets are provided by External Providers and by selecting you agree to Terms of those Providers. Your access to the wallet might be reliant on the External Provider being operational.":"Wallets are provided by External Providers and by selecting you agree to Terms of those Providers. Your access to the wallet might be reliant on the External Provider being operational.","Watch-only mode allows to see address positions in Aave, but you won't be able to perform transactions.":"Watch-only mode allows to see address positions in Aave, but you won't be able to perform transactions.","Watch-only mode.":"Watch-only mode.","Watch-only mode. Connect to a wallet to perform transactions.":"Watch-only mode. Connect to a wallet to perform transactions.","We couldn't find any asset matching your search. Try again with a different asset name, symbol, or address.":"We couldn't find any asset matching your search. Try again with a different asset name, symbol, or address.","We couldn’t detect a wallet. Connect a wallet to stake.":"We couldn’t detect a wallet. Connect a wallet to stake.","We suggest you go back to the Dashboard.":"We suggest you go back to the Dashboard.","When a liquidation occurs, liquidators repay up to 50% of the outstanding borrowed amount on behalf of the borrower. In return, they can buy the collateral at a discount and keep the difference (liquidation penalty) as a bonus.":"When a liquidation occurs, liquidators repay up to 50% of the outstanding borrowed amount on behalf of the borrower. In return, they can buy the collateral at a discount and keep the difference (liquidation penalty) as a bonus.","Why do I need to approve?":"Why do I need to approve?","With a voting power of <0/>":"With a voting power of <0/>","With testnet Faucet you can get free assets to test the Aave Protocol. Make sure to switch your wallet provider to the appropriate testnet network, select desired asset, and click ‘Faucet’ to get tokens transferred to your wallet. The assets on a testnet are not “real,” meaning they have no monetary value. <0>Learn more":"With testnet Faucet you can get free assets to test the Aave Protocol. Make sure to switch your wallet provider to the appropriate testnet network, select desired asset, and click ‘Faucet’ to get tokens transferred to your wallet. The assets on a testnet are not “real,” meaning they have no monetary value. <0>Learn more","Withdraw":"Withdraw","Withdraw {symbol}":["Withdraw ",["symbol"]],"Withdrawing this amount will reduce your health factor and increase risk of liquidation.":"Withdrawing this amount will reduce your health factor and increase risk of liquidation.","Withdrawing {symbol}":["Withdrawing ",["symbol"]],"Wrong Network":"Wrong Network","YAE":"YAE","You are entering Isolation mode":"You are entering Isolation mode","You can borrow this asset with a stable rate only if you borrow more than the amount you are supplying as collateral.":"You can borrow this asset with a stable rate only if you borrow more than the amount you are supplying as collateral.","You can not change Interest Type to stable as your borrowings are higher than your collateral":"You can not change Interest Type to stable as your borrowings are higher than your collateral","You can not disable E-Mode as your current collateralization level is above 80%, disabling E-Mode can cause liquidation. To exit E-Mode supply or repay borrowed positions.":"You can not disable E-Mode as your current collateralization level is above 80%, disabling E-Mode can cause liquidation. To exit E-Mode supply or repay borrowed positions.","You can not switch usage as collateral mode for this currency, because it will cause collateral call":"You can not switch usage as collateral mode for this currency, because it will cause collateral call","You can not use this currency as collateral":"You can not use this currency as collateral","You can not withdraw this amount because it will cause collateral call":"You can not withdraw this amount because it will cause collateral call","You can only withdraw your assets from the Security Module after the cooldown period ends and the unstake window is active.":"You can only withdraw your assets from the Security Module after the cooldown period ends and the unstake window is active.","You can report incident to our <0>Discord or <1>Github.":"You can report incident to our <0>Discord or <1>Github.","You cancelled the transaction.":"You cancelled the transaction.","You did not participate in this proposal":"You did not participate in this proposal","You do not have supplies in this currency":"You do not have supplies in this currency","You don’t have enough funds in your wallet to repay the full amount. If you proceed to repay with your current amount of funds, you will still have a small borrowing position in your dashboard.":"You don’t have enough funds in your wallet to repay the full amount. If you proceed to repay with your current amount of funds, you will still have a small borrowing position in your dashboard.","You have not borrow yet using this currency":"You have not borrow yet using this currency","You switched to {0} rate":["You switched to ",["0"]," rate"],"You unstake here":"You unstake here","You voted {0}":["You voted ",["0"]],"You will exit isolation mode and other tokens can now be used as collateral":"You will exit isolation mode and other tokens can now be used as collateral","You {action} <0/> {symbol}":["You ",["action"]," <0/> ",["symbol"]],"Your borrows":"Your borrows","Your current loan to value based on your collateral supplied.":"Your current loan to value based on your collateral supplied.","Your health factor and loan to value determine the assurance of your collateral. To avoid liquidations you can supply more collateral or repay borrow positions.":"Your health factor and loan to value determine the assurance of your collateral. To avoid liquidations you can supply more collateral or repay borrow positions.","Your info":"Your info","Your reward balance is 0":"Your reward balance is 0","Your supplies":"Your supplies","Your voting info":"Your voting info","Your {name} wallet is empty. Purchase or transfer assets or use <0>{0} to transfer your {network} assets.":["Your ",["name"]," wallet is empty. Purchase or transfer assets or use <0>",["0"]," to transfer your ",["network"]," assets."],"Your {name} wallet is empty. Purchase or transfer assets.":["Your ",["name"]," wallet is empty. Purchase or transfer assets."],"Your {networkName} wallet is empty. Get free test assets at":["Your ",["networkName"]," wallet is empty. Get free test assets at"],"Your {networkName} wallet is empty. Get free test {0} at":["Your ",["networkName"]," wallet is empty. Get free test ",["0"]," at"],"Zero address not valid":"Zero address not valid","assets":"assets","blocked activities":"blocked activities","copy the error":"copy the error","documentation":"documentation","ends":"ends","here.":"here.","is an asset affected by rebasing. Visit the":"is an asset affected by rebasing. Visit the","of":"of","on":"on","or":"or","please check that the amount you want to supply is not currently being used for staking. If it is being used for staking, your transaction might fail.":"please check that the amount you want to supply is not currently being used for staking. If it is being used for staking, your transaction might fail.","repaid":"repaid","staking view":"staking view","to learn more.":"to learn more.","tokens is not the same as staking them. If you wish to stake your":"tokens is not the same as staking them. If you wish to stake your","tokens, please go to the":"tokens, please go to the","withdrew":"withdrew","{0}":[["0"]],"{0} Balance":[["0"]," Balance"],"{0} Faucet":[["0"]," Faucet"],"{d}d":[["d"],"d"],"{h}h":[["h"],"h"],"{m}m":[["m"],"m"],"{networkName} Faucet":[["networkName"]," Faucet"],"{s}s":[["s"],"s"],"{tooltipText}":[["tooltipText"]]}}; \ No newline at end of file +/*eslint-disable*/module.exports={messages:{"<0>Ampleforth is an asset affected by rebasing. Visit the <1>documentation or <2>Ampleforth's FAQ to learn more.":"<0>Ampleforth is an asset affected by rebasing. Visit the <1>documentation or <2>Ampleforth's FAQ to learn more.","<0>Attention: Parameter changes via governance can alter your account health factor and risk of liquidation. Follow the <1>Aave governance forum for updates.":"<0>Attention: Parameter changes via governance can alter your account health factor and risk of liquidation. Follow the <1>Aave governance forum for updates.","<0>Slippage tolerance <1>{selectedSlippage}% <2>{0}":["<0>Slippage tolerance <1>",["selectedSlippage"],"% <2>",["0"],""],"AAVE holders can stake their AAVE in the Safety Module to add more security to the protocol and earn Safety Incentives. In the case of a shortfall event, up to 30% of your stake can be slashed to cover the deficit, providing an additional layer of protection for the protocol.":"AAVE holders can stake their AAVE in the Safety Module to add more security to the protocol and earn Safety Incentives. In the case of a shortfall event, up to 30% of your stake can be slashed to cover the deficit, providing an additional layer of protection for the protocol.","ACTIVATE COOLDOWN":"ACTIVATE COOLDOWN","APR":"APR","APY":"APY","APY type":"APY type","APY, stable":"APY, stable","APY, variable":"APY, variable","AToken supply is not zero":"AToken supply is not zero","Aave Governance":"Aave Governance","Aave is a fully decentralized, community governed protocol by the AAVE token-holders. AAVE token-holders collectively discuss, propose, and vote on upgrades to the protocol. AAVE token-holders can either vote themselves on new proposals or delagate to an address of choice. To learn more check out the Governance documentation":"Aave is a fully decentralized, community governed protocol by the AAVE token-holders. AAVE token-holders collectively discuss, propose, and vote on upgrades to the protocol. AAVE token-holders can either vote themselves on new proposals or delagate to an address of choice. To learn more check out the Governance documentation","Aave per month":"Aave per month","Account":"Account","Action cannot be performed because the reserve is frozen":"Action cannot be performed because the reserve is frozen","Action cannot be performed because the reserve is paused":"Action cannot be performed because the reserve is paused","Action requires an active reserve":"Action requires an active reserve","Add to wallet":"Add to wallet","Add {0} to wallet to track your balance.":["Add ",["0"]," to wallet to track your balance."],"Address is not a contract":"Address is not a contract","All Assets":"All Assets","All done!":"All done!","All proposals":"All proposals","Allowance required action":"Allowance required action","Allows you to decide whether to use a supplied asset as collateral. An asset used as collateral will affect your borrowing power and health factor.":"Allows you to decide whether to use a supplied asset as collateral. An asset used as collateral will affect your borrowing power and health factor.","Allows you to switch between <0>variable and <1>stable interest rates, where variable rate can increase and decrease depending on the amount of liquidity in the reserve, and stable rate will stay the same for the duration of your loan.":"Allows you to switch between <0>variable and <1>stable interest rates, where variable rate can increase and decrease depending on the amount of liquidity in the reserve, and stable rate will stay the same for the duration of your loan.","Already on cooldown":"Already on cooldown","Amount":"Amount","Amount must be greater than 0":"Amount must be greater than 0","Ampleforth FAQ":"Ampleforth FAQ","An error has occurred fetching the proposal metadata from IPFS.":"An error has occurred fetching the proposal metadata from IPFS.","Approval":"Approval","Approve confirmed":"Approve confirmed","Approve to continue":"Approve to continue","Approved":"Approved","Approving {symbol}...":["Approving ",["symbol"],"..."],"Array parameters that should be equal length are not":"Array parameters that should be equal length are not","Asset":"Asset","Asset can only be used as collateral in isolation mode only.":"Asset can only be used as collateral in isolation mode only.","Asset cannot be used as collateral.":"Asset cannot be used as collateral.","Asset category":"Asset category","Asset is not borrowable in isolation mode":"Asset is not borrowable in isolation mode","Asset is not listed":"Asset is not listed","Asset supply is limited to a certain amount to reduce protocol exposure to the asset and to help manage risks involved.":"Asset supply is limited to a certain amount to reduce protocol exposure to the asset and to help manage risks involved.","Asset to delegate":"Asset to delegate","Assets":"Assets","Assets to borrow":"Assets to borrow","Assets to supply":"Assets to supply","Author":"Author","Available":"Available","Available assets":"Available assets","Available liquidity":"Available liquidity","Available rewards":"Available rewards","Available to borrow":"Available to borrow","Available to supply":"Available to supply","Back to Dashboard":"Back to Dashboard","Balance":"Balance","Be careful - You are very close to liquidation. Consider depositing more collateral or paying down some of your borrowed positions":"Be careful - You are very close to liquidation. Consider depositing more collateral or paying down some of your borrowed positions","Before supplying":"Before supplying","Before supplying, you need to approve its usage by the Aave protocol. You can learn more in our <0>FAQ":"Before supplying, you need to approve its usage by the Aave protocol. You can learn more in our <0>FAQ","Blocked Address":"Blocked Address","Borrow":"Borrow","Borrow APY rate":"Borrow APY rate","Borrow APY, stable":"Borrow APY, stable","Borrow APY, variable":"Borrow APY, variable","Borrow and repay in same block is not allowed":"Borrow and repay in same block is not allowed","Borrow balance after repay":"Borrow balance after repay","Borrow cap":"Borrow cap","Borrow cap is exceeded":"Borrow cap is exceeded","Borrow power used":"Borrow power used","Borrow {symbol}":["Borrow ",["symbol"]],"Borrowed":"Borrowed","Borrowing is currently unavailable for {0}.":["Borrowing is currently unavailable for ",["0"],"."],"Borrowing is not enabled":"Borrowing is not enabled","Borrowing is unavailable because you’re using Isolation mode. To manage Isolation mode visit your <0>Dashboard.":"Borrowing is unavailable because you’re using Isolation mode. To manage Isolation mode visit your <0>Dashboard.","Borrowing is unavailable because you’ve enabled Efficiency Mode (E-Mode) and Isolation mode. To manage E-Mode and Isolation mode visit your <0>Dashboard.":"Borrowing is unavailable because you’ve enabled Efficiency Mode (E-Mode) and Isolation mode. To manage E-Mode and Isolation mode visit your <0>Dashboard.","Borrowing is unavailable because you’ve enabled Efficiency Mode (E-Mode) for {0} category. To manage E-Mode categories visit your <0>Dashboard.":["Borrowing is unavailable because you’ve enabled Efficiency Mode (E-Mode) for ",["0"]," category. To manage E-Mode categories visit your <0>Dashboard."],"Borrowing of this asset is limited to a certain amount to minimize liquidity pool insolvency.":"Borrowing of this asset is limited to a certain amount to minimize liquidity pool insolvency.","Borrowing power and assets are limited due to Isolation mode.":"Borrowing power and assets are limited due to Isolation mode.","Borrowing this amount will reduce your health factor and increase risk of liquidation.":"Borrowing this amount will reduce your health factor and increase risk of liquidation.","Borrowing {symbol}":["Borrowing ",["symbol"]],"CLAIM {symbol}":["CLAIM ",["symbol"]],"CLAIMING {symbol}":["CLAIMING ",["symbol"]],"Can be collateral":"Can be collateral","Can be executed":"Can be executed","Cancel":"Cancel","Cannot disable E-Mode":"Cannot disable E-Mode","Cap reached. Lower supply amount":"Cap reached. Lower supply amount","Claim":"Claim","Claim AAVE":"Claim AAVE","Claim all":"Claim all","Claim all rewards":"Claim all rewards","Claim {0}":["Claim ",["0"]],"Claimable AAVE":"Claimable AAVE","Claimed":"Claimed","Claiming":"Claiming","Close":"Close","Collateral":"Collateral","Collateral balance after repay":"Collateral balance after repay","Collateral is (mostly) the same currency that is being borrowed":"Collateral is (mostly) the same currency that is being borrowed","Collateral to repay with":"Collateral to repay with","Collateral usage":"Collateral usage","Collateral usage is limited because of Isolation mode.":"Collateral usage is limited because of Isolation mode.","Collateral usage is limited because of isolation mode. <0>Learn More":"Collateral usage is limited because of isolation mode. <0>Learn More","Collateralization":"Collateralization","Collector Contract":"Collector Contract","Collector Info":"Collector Info","Connect wallet":"Connect wallet","Cooldown period":"Cooldown period","Cooldown period warning":"Cooldown period warning","Cooldown time left":"Cooldown time left","Cooldown to unstake":"Cooldown to unstake","Cooling down...":"Cooling down...","Copy address":"Copy address","Copy error message":"Copy error message","Copy error text":"Copy error text","Created":"Created","Current LTV":"Current LTV","Current differential":"Current differential","Current votes":"Current votes","Dark mode":"Dark mode","Dashboard":"Dashboard","Data couldn't be fetched, please reload graph.":"Data couldn't be fetched, please reload graph.","Debt":"Debt","Debt ceiling is exceeded":"Debt ceiling is exceeded","Debt ceiling is not zero":"Debt ceiling is not zero","Debt ceiling limits the amount possible to borrow against this asset by protocol users. Debt ceiling is specific to assets in isolation mode and is denoted in USD.":"Debt ceiling limits the amount possible to borrow against this asset by protocol users. Debt ceiling is specific to assets in isolation mode and is denoted in USD.","Define Retry with Approval text":"Define Retry with Approval text","Delegate":"Delegate","Delegating":"Delegating","Delegation":"Delegation","Details":"Details","Developers":"Developers","Differential":"Differential","Disable E-Mode":"Disable E-Mode","Disable testnet":"Disable testnet","Disable {symbol} as collateral":["Disable ",["symbol"]," as collateral"],"Disabled":"Disabled","Disabling E-Mode":"Disabling E-Mode","Disabling this asset as collateral affects your borrowing power and Health Factor.":"Disabling this asset as collateral affects your borrowing power and Health Factor.","Disconnect Wallet":"Disconnect Wallet","Discord":"Discord","Discord channel":"Discord channel","Due to a precision bug in the stETH contract, this asset can not be used in flashloan transactions":"Due to a precision bug in the stETH contract, this asset can not be used in flashloan transactions","Due to the Horizon bridge exploit, certain assets on the Harmony network are not at parity with Ethereum, which affects the Aave V3 Harmony market.":"Due to the Horizon bridge exploit, certain assets on the Harmony network are not at parity with Ethereum, which affects the Aave V3 Harmony market.","E-Mode":"E-Mode","E-Mode Category":"E-Mode Category","E-Mode category":"E-Mode category","E-Mode increases your LTV for a selected category of assets up to 97%. <0>Learn more":"E-Mode increases your LTV for a selected category of assets up to 97%. <0>Learn more","E-Mode increases your LTV for a selected category of assets up to<0/>. <1>Learn more":"E-Mode increases your LTV for a selected category of assets up to<0/>. <1>Learn more","E-Mode increases your LTV for a selected category of assets, meaning that when E-mode is enabled, you will have higher borrowing power over assets of the same E-mode category which are defined by Aave Governance. You can enter E-Mode from your <0>Dashboard. To learn more about E-Mode and applied restrictions in <1>FAQ or <2>Aave V3 Technical Paper.":"E-Mode increases your LTV for a selected category of assets, meaning that when E-mode is enabled, you will have higher borrowing power over assets of the same E-mode category which are defined by Aave Governance. You can enter E-Mode from your <0>Dashboard. To learn more about E-Mode and applied restrictions in <1>FAQ or <2>Aave V3 Technical Paper.","Efficiency mode (E-Mode)":"Efficiency mode (E-Mode)","Emode":"Emode","Enable E-Mode":"Enable E-Mode","Enable {symbol} as collateral":["Enable ",["symbol"]," as collateral"],"Enabled":"Enabled","Enabled in isolation":"Enabled in isolation","Enabling E-Mode":"Enabling E-Mode","Enabling E-Mode only allows you to borrow assets belonging to the selected category. Please visit our <0>FAQ guide to learn more about how it works and the applied restrictions.":"Enabling E-Mode only allows you to borrow assets belonging to the selected category. Please visit our <0>FAQ guide to learn more about how it works and the applied restrictions.","Enabling this asset as collateral increases your borrowing power and Health Factor. However, it can get liquidated if your health factor drops below 1.":"Enabling this asset as collateral increases your borrowing power and Health Factor. However, it can get liquidated if your health factor drops below 1.","English":"English","Enter ETH address":"Enter ETH address","Enter an address to track in watch-only mode":"Enter an address to track in watch-only mode","Enter an amount":"Enter an amount","Error connecting. Try refreshing the page.":"Error connecting. Try refreshing the page.","Executed":"Executed","Expected amount to repay":"Expected amount to repay","Expires":"Expires","FAQ":"FAQ","Faucet":"Faucet","Faucet {0}":["Faucet ",["0"]],"Filter":"Filter","For repayment of a specific type of debt, the user needs to have debt that type":"For repayment of a specific type of debt, the user needs to have debt that type","Forum discussion":"Forum discussion","French":"French","Funds in the Safety Module":"Funds in the Safety Module","Get ABP Token":"Get ABP Token","Github":"Github","Global settings":"Global settings","Go Back":"Go Back","Go back":"Go back","Go to Balancer Pool":"Go to Balancer Pool","Governance":"Governance","Greek":"Greek","Health factor":"Health factor","Health factor is lesser than the liquidation threshold":"Health factor is lesser than the liquidation threshold","Health factor is not below the threshold":"Health factor is not below the threshold","Hide":"Hide","I acknowledge the risks involved.":"I acknowledge the risks involved.","I understand how cooldown ({0}) and unstaking ({1}) work":["I understand how cooldown (",["0"],") and unstaking (",["1"],") work"],"If the error continues to happen,<0/> you may report it to this":"If the error continues to happen,<0/> you may report it to this","If the health factor goes below 1, the liquidation of your collateral might be triggered.":"If the health factor goes below 1, the liquidation of your collateral might be triggered.","If you DO NOT unstake within {0} of unstake window, you will need to activate cooldown process again.":["If you DO NOT unstake within ",["0"]," of unstake window, you will need to activate cooldown process again."],"If your loan to value goes above the liquidation threshold your collateral supplied may be liquidated.":"If your loan to value goes above the liquidation threshold your collateral supplied may be liquidated.","In E-Mode some assets are not borrowable. Exit E-Mode to get access to all assets":"In E-Mode some assets are not borrowable. Exit E-Mode to get access to all assets","In Isolation mode, you cannot supply other assets as collateral. A global debt ceiling limits the borrowing power of the isolated asset. To exit isolation mode disable {0} as collateral before borrowing another asset. Read more in our <0>FAQ":["In Isolation mode, you cannot supply other assets as collateral. A global debt ceiling limits the borrowing power of the isolated asset. To exit isolation mode disable ",["0"]," as collateral before borrowing another asset. Read more in our <0>FAQ"],"Inconsistent flashloan parameters":"Inconsistent flashloan parameters","Interest rate rebalance conditions were not met":"Interest rate rebalance conditions were not met","Interest rate strategy":"Interest rate strategy","Invalid amount to burn":"Invalid amount to burn","Invalid amount to mint":"Invalid amount to mint","Invalid bridge protocol fee":"Invalid bridge protocol fee","Invalid expiration":"Invalid expiration","Invalid flashloan premium":"Invalid flashloan premium","Invalid return value of the flashloan executor function":"Invalid return value of the flashloan executor function","Invalid signature":"Invalid signature","Isolated":"Isolated","Isolated Debt Ceiling":"Isolated Debt Ceiling","Isolated assets have limited borrowing power and other assets cannot be used as collateral.":"Isolated assets have limited borrowing power and other assets cannot be used as collateral.","Join the community discussion":"Join the community discussion","Language":"Language","Learn more":"Learn more","Learn more about risks involved":"Learn more about risks involved","Learn more in our <0>FAQ guide":"Learn more in our <0>FAQ guide","Links":"Links","Liquidation <0/> threshold":"Liquidation <0/> threshold","Liquidation at":"Liquidation at","Liquidation penalty":"Liquidation penalty","Liquidation risk":"Liquidation risk","Liquidation risk parameters":"Liquidation risk parameters","Liquidation threshold":"Liquidation threshold","Liquidation value":"Liquidation value","Loading data...":"Loading data...","Ltv validation failed":"Ltv validation failed","MAX":"MAX","Market":"Market","Markets":"Markets","Max":"Max","Max LTV":"Max LTV","Max slashing":"Max slashing","Maximum amount available to borrow against this asset is limited because debt ceiling is at {0}%.":["Maximum amount available to borrow against this asset is limited because debt ceiling is at ",["0"],"%."],"Maximum amount available to borrow is limited because protocol borrow cap is nearly reached.":"Maximum amount available to borrow is limited because protocol borrow cap is nearly reached.","Maximum amount available to supply is <0/> {0} (<1/>).":["Maximum amount available to supply is <0/> ",["0"]," (<1/>)."],"Maximum amount available to supply is limited because protocol supply cap is at {0}%.":["Maximum amount available to supply is limited because protocol supply cap is at ",["0"],"%."],"Maximum loan to value":"Maximum loan to value","Menu":"Menu","More":"More","NAY":"NAY","Need help connecting a wallet? <0>Read our FAQ":"Need help connecting a wallet? <0>Read our FAQ","Net APR":"Net APR","Net APY":"Net APY","Net APY is the combined effect of all supply and borrow positions on net worth, including incentives. It is possible to have a negative net APY if debt APY is higher than supply APY.":"Net APY is the combined effect of all supply and borrow positions on net worth, including incentives. It is possible to have a negative net APY if debt APY is higher than supply APY.","Net worth":"Net worth","Network":"Network","Network not supported for this wallet":"Network not supported for this wallet","New APY":"New APY","No":"No","No rewards to claim":"No rewards to claim","No search results for":"No search results for","No voting power":"No voting power","None":"None","Not a valid address":"Not a valid address","Not enough balance on your wallet":"Not enough balance on your wallet","Not enough collateral to repay this amount of debt with":"Not enough collateral to repay this amount of debt with","Not enough staked balance":"Not enough staked balance","Not enough voting power to participate in this proposal":"Not enough voting power to participate in this proposal","Not reached":"Not reached","Nothing borrowed yet":"Nothing borrowed yet","Nothing staked":"Nothing staked","Nothing supplied yet":"Nothing supplied yet","Notify":"Notify","Ok, Close":"Ok, Close","Ok, I got it":"Ok, I got it","Operation not supported":"Operation not supported","Oracle price":"Oracle price","Overview":"Overview","Page not found":"Page not found","Participating in this {symbol} reserve gives annualized rewards.":["Participating in this ",["symbol"]," reserve gives annualized rewards."],"Pending...":"Pending...","Per the community, the Fantom market has been frozen.":"Per the community, the Fantom market has been frozen.","Please connect a wallet to view your personal information here.":"Please connect a wallet to view your personal information here.","Please connect your wallet to get free testnet assets.":"Please connect your wallet to get free testnet assets.","Please connect your wallet to see your supplies, borrowings, and open positions.":"Please connect your wallet to see your supplies, borrowings, and open positions.","Please enter a valid wallet address.":"Please enter a valid wallet address.","Please switch to {networkName}.":["Please switch to ",["networkName"],"."],"Please, connect your wallet":"Please, connect your wallet","Pool addresses provider is not registered":"Pool addresses provider is not registered","Powered by":"Powered by","Price impact <0/>%":"Price impact <0/>%","Proposal details":"Proposal details","Proposal overview":"Proposal overview","Proposals":"Proposals","Proposition power":"Proposition power","Protocol borrow cap at 100% for this asset. Further borrowing unavailable.":"Protocol borrow cap at 100% for this asset. Further borrowing unavailable.","Protocol borrow cap is at 100% for this asset. Further borrowing unavailable.":"Protocol borrow cap is at 100% for this asset. Further borrowing unavailable.","Protocol debt ceiling is at 100% for this asset. Further borrowing against this asset is unavailable.":"Protocol debt ceiling is at 100% for this asset. Further borrowing against this asset is unavailable.","Protocol debt ceiling is at 100% for this asset. Futher borrowing against this asset is unavailable.":"Protocol debt ceiling is at 100% for this asset. Futher borrowing against this asset is unavailable.","Protocol supply cap at 100% for this asset. Further supply unavailable.":"Protocol supply cap at 100% for this asset. Further supply unavailable.","Protocol supply cap is at 100% for this asset. Further supply unavailable.":"Protocol supply cap is at 100% for this asset. Further supply unavailable.","Quorum":"Quorum","Raw-Ipfs":"Raw-Ipfs","Reached":"Reached","Received":"Received","Recipient address":"Recipient address","Rejected connection request":"Rejected connection request","Reload":"Reload","Reload the page":"Reload the page","Remaining debt":"Remaining debt","Remaining supply":"Remaining supply","Repay":"Repay","Repay with":"Repay with","Repay {symbol}":["Repay ",["symbol"]],"Repaying {symbol}":["Repaying ",["symbol"]],"Reserve Size":"Reserve Size","Reserve factor":"Reserve factor","Reserve factor is a percentage of interest which goes to a {0} that is controlled by Aave governance to promote ecosystem growth.":["Reserve factor is a percentage of interest which goes to a ",["0"]," that is controlled by Aave governance to promote ecosystem growth."],"Reserve status & configuration":"Reserve status & configuration","Retry What?":"Retry What?","Retry with Approval":"Retry with Approval","Retry with approval":"Retry with approval","Review approval tx details":"Review approval tx details","Review tx":"Review tx","Review tx details":"Review tx details","Reward(s) to claim":"Reward(s) to claim","Rewards APR":"Rewards APR","Risk details":"Risk details","SEE CHARTS":"SEE CHARTS","Safety of your deposited collateral against the borrowed assets and its underlying value.":"Safety of your deposited collateral against the borrowed assets and its underlying value.","Seatbelt report":"Seatbelt report","Seems like we can't switch the network automatically. Please check if you can change it from the wallet.":"Seems like we can't switch the network automatically. Please check if you can change it from the wallet.","Select":"Select","Select APY type to switch":"Select APY type to switch","Select language":"Select language","Select slippage tolerance":"Select slippage tolerance","Select token to add":"Select token to add","Select token to view in block explorer":"Select token to view in block explorer","Setup notifications about your Health Factor using the Hal app.":"Setup notifications about your Health Factor using the Hal app.","Share on twitter":"Share on twitter","Show":"Show","Show assets with 0 balance":"Show assets with 0 balance","Since this asset is frozen, the only available actions are withdraw and repay which can be accessed from the <0>Dashboard":"Since this asset is frozen, the only available actions are withdraw and repay which can be accessed from the <0>Dashboard","Since this is a test network, you can get any of the assets if you have ETH on your wallet":"Since this is a test network, you can get any of the assets if you have ETH on your wallet","Something went wrong":"Something went wrong","Sorry, an unexpected error happened. In the meantime you may try reloading the page, or come back later.":"Sorry, an unexpected error happened. In the meantime you may try reloading the page, or come back later.","Sorry, we couldn't find the page you were looking for.":"Sorry, we couldn't find the page you were looking for.","Spanish":"Spanish","Stable":"Stable","Stable Interest Type is disabled for this currency":"Stable Interest Type is disabled for this currency","Stable borrowing is enabled":"Stable borrowing is enabled","Stable borrowing is not enabled":"Stable borrowing is not enabled","Stable debt supply is not zero":"Stable debt supply is not zero","Stable interest rate will <0>stay the same for the duration of your loan. Recommended for long-term loan periods and for users who prefer predictability.":"Stable interest rate will <0>stay the same for the duration of your loan. Recommended for long-term loan periods and for users who prefer predictability.","Stablecoin":"Stablecoin","Stake":"Stake","Stake AAVE":"Stake AAVE","Stake ABPT":"Stake ABPT","Stake cooldown activated":"Stake cooldown activated","Staked":"Staked","Staking":"Staking","Staking APR":"Staking APR","Started":"Started","State":"State","Supplied":"Supplied","Supplied asset amount":"Supplied asset amount","Supply":"Supply","Supply APY":"Supply APY","Supply apy":"Supply apy","Supply balance":"Supply balance","Supply balance after swap":"Supply balance after swap","Supply cap is exceeded":"Supply cap is exceeded","Supply cap on target reserve reached. Try lowering the amount.":"Supply cap on target reserve reached. Try lowering the amount.","Supply {symbol}":["Supply ",["symbol"]],"Supplying your":"Supplying your","Supplying {symbol}":["Supplying ",["symbol"]],"Swap":"Swap","Swap to":"Swap to","Swapped":"Swapped","Swapping":"Swapping","Switch APY type":"Switch APY type","Switch E-Mode":"Switch E-Mode","Switch E-Mode category":"Switch E-Mode category","Switch Network":"Switch Network","Switch rate":"Switch rate","Switching E-Mode":"Switching E-Mode","Switching rate":"Switching rate","Test Assets":"Test Assets","Testnet mode":"Testnet mode","Testnet mode is ON":"Testnet mode is ON","The % of your total borrowing power used. This is based on the amount of your collateral supplied and the total amount that you can borrow.":"The % of your total borrowing power used. This is based on the amount of your collateral supplied and the total amount that you can borrow.","The Aave Balancer Pool Token (ABPT) is a liquidity pool token. You can receive ABPT by depositing a combination of AAVE + ETH in the Balancer liquidity pool. You can then stake your BPT in the Safety Module to secure the protocol and earn Safety Incentives.":"The Aave Balancer Pool Token (ABPT) is a liquidity pool token. You can receive ABPT by depositing a combination of AAVE + ETH in the Balancer liquidity pool. You can then stake your BPT in the Safety Module to secure the protocol and earn Safety Incentives.","The Maximum LTV ratio represents the maximum borrowing power of a specific collateral. For example, if a collateral has an LTV of 75%, the user can borrow up to 0.75 worth of ETH in the principal currency for every 1 ETH worth of collateral.":"The Maximum LTV ratio represents the maximum borrowing power of a specific collateral. For example, if a collateral has an LTV of 75%, the user can borrow up to 0.75 worth of ETH in the principal currency for every 1 ETH worth of collateral.","The Stable Rate is not enabled for this currency":"The Stable Rate is not enabled for this currency","The address of the pool addresses provider is invalid":"The address of the pool addresses provider is invalid","The app is running in testnet mode. Learn how it works in":"The app is running in testnet mode. Learn how it works in","The caller of the function is not an AToken":"The caller of the function is not an AToken","The caller of this function must be a pool":"The caller of this function must be a pool","The collateral balance is 0":"The collateral balance is 0","The collateral chosen cannot be liquidated":"The collateral chosen cannot be liquidated","The cooldown period is the time required prior to unstaking your tokens(10 days). You can only withdraw your assets from the Security Module after the cooldown period and within the active the unstake window.<0>Learn more":"The cooldown period is the time required prior to unstaking your tokens(10 days). You can only withdraw your assets from the Security Module after the cooldown period and within the active the unstake window.<0>Learn more","The cooldown period is {0}. After {1} of cooldown, you will enter unstake window of {2}. You will continue receiving rewards during cooldown and unstake window.":["The cooldown period is ",["0"],". After ",["1"]," of cooldown, you will enter unstake window of ",["2"],". You will continue receiving rewards during cooldown and unstake window."],"The effects on the health factor would cause liquidation. Try lowering the amount.":"The effects on the health factor would cause liquidation. Try lowering the amount.","The requested amount is greater than the max loan size in stable rate mode":"The requested amount is greater than the max loan size in stable rate mode","The total amount of your assets denominated in USD that can be used as collateral for borrowing assets.":"The total amount of your assets denominated in USD that can be used as collateral for borrowing assets.","The underlying asset cannot be rescued":"The underlying asset cannot be rescued","The underlying balance needs to be greater than 0":"The underlying balance needs to be greater than 0","The weighted average of APY for all borrowed assets, including incentives.":"The weighted average of APY for all borrowed assets, including incentives.","The weighted average of APY for all supplied assets, including incentives.":"The weighted average of APY for all supplied assets, including incentives.","There are not enough funds in the{0}reserve to borrow":["There are not enough funds in the",["0"],"reserve to borrow"],"There is not enough collateral to cover a new borrow":"There is not enough collateral to cover a new borrow","There was some error. Please try changing the parameters or <0><1>copy the error":"There was some error. Please try changing the parameters or <0><1>copy the error","These funds have been borrowed and are not available for withdrawal at this time.":"These funds have been borrowed and are not available for withdrawal at this time.","This action will reduce your health factor. Please be mindful of the increased risk of collateral liquidation.":"This action will reduce your health factor. Please be mindful of the increased risk of collateral liquidation.","This address is blocked on app.aave.com because it is associated with one or more":"This address is blocked on app.aave.com because it is associated with one or more","This asset has almost reached its borrow cap. There is only {messageValue} available to be borrowed from this market.":["This asset has almost reached its borrow cap. There is only ",["messageValue"]," available to be borrowed from this market."],"This asset has almost reached its supply cap. There can only be {messageValue} supplied to this market.":["This asset has almost reached its supply cap. There can only be ",["messageValue"]," supplied to this market."],"This asset has reached its borrow cap. Nothing is available to be borrowed from this market.":"This asset has reached its borrow cap. Nothing is available to be borrowed from this market.","This asset has reached its supply cap. Nothing is available to be supplied from this market.":"This asset has reached its supply cap. Nothing is available to be supplied from this market.","This asset is frozen due to an Aave Protocol Governance decision. <0>More details":"This asset is frozen due to an Aave Protocol Governance decision. <0>More details","This asset is frozen due to an Aave community decision. <0>More details":"This asset is frozen due to an Aave community decision. <0>More details","This gas calculation is only an estimation. Your wallet will set the price of the transaction. You can modify the gas settings directly from your wallet provider.":"This gas calculation is only an estimation. Your wallet will set the price of the transaction. You can modify the gas settings directly from your wallet provider.","This integration was<0>proposed and approvedby the community.":"This integration was<0>proposed and approvedby the community.","This is the total amount available for you to borrow. You can borrow based on your collateral and until the borrow cap is reached.":"This is the total amount available for you to borrow. You can borrow based on your collateral and until the borrow cap is reached.","This is the total amount that you are able to supply to in this reserve. You are able to supply your wallet balance up until the supply cap is reached.":"This is the total amount that you are able to supply to in this reserve. You are able to supply your wallet balance up until the supply cap is reached.","This represents the threshold at which a borrow position will be considered undercollateralized and subject to liquidation for each collateral. For example, if a collateral has a liquidation threshold of 80%, it means that the position will be liquidated when the debt value is worth 80% of the collateral value.":"This represents the threshold at which a borrow position will be considered undercollateralized and subject to liquidation for each collateral. For example, if a collateral has a liquidation threshold of 80%, it means that the position will be liquidated when the debt value is worth 80% of the collateral value.","Time left to be able to withdraw your staked asset.":"Time left to be able to withdraw your staked asset.","Time left to unstake":"Time left to unstake","Time left until the withdrawal window closes.":"Time left until the withdrawal window closes.","To borrow you need to supply any asset to be used as collateral.":"To borrow you need to supply any asset to be used as collateral.","To enable E-mode for the {0} category, all borrow positions outside of this cateogry must be closed.":["To enable E-mode for the ",["0"]," category, all borrow positions outside of this cateogry must be closed."],"To repay on behalf of a user an explicit amount to repay is needed":"To repay on behalf of a user an explicit amount to repay is needed","To request access for this permissioned market, please visit: <0>Acces Provider Name":"To request access for this permissioned market, please visit: <0>Acces Provider Name","Total available":"Total available","Total borrowed":"Total borrowed","Total borrows":"Total borrows","Total emission per day":"Total emission per day","Total market size":"Total market size","Total supplied":"Total supplied","Total voting power":"Total voting power","Total worth":"Total worth","Transaction failed":"Transaction failed","Transaction overview":"Transaction overview","Type of delegation":"Type of delegation","UNSTAKE {symbol}":["UNSTAKE ",["symbol"]],"UNSTAKING {symbol}":["UNSTAKING ",["symbol"]],"Unavailable":"Unavailable","Unbacked":"Unbacked","Unbacked mint cap is exceeded":"Unbacked mint cap is exceeded","Unstake now":"Unstake now","Unstake window":"Unstake window","Used as collateral":"Used as collateral","User cannot withdraw more than the available balance":"User cannot withdraw more than the available balance","User did not borrow the specified currency":"User did not borrow the specified currency","User does not have outstanding stable rate debt on this reserve":"User does not have outstanding stable rate debt on this reserve","User does not have outstanding variable rate debt on this reserve":"User does not have outstanding variable rate debt on this reserve","User is in isolation mode":"User is in isolation mode","User is trying to borrow multiple assets including a siloed one":"User is trying to borrow multiple assets including a siloed one","Utilization Rate":"Utilization Rate","VOTE NAY":"VOTE NAY","VOTE YAE":"VOTE YAE","Variable":"Variable","Variable debt supply is not zero":"Variable debt supply is not zero","Variable interest rate will <0>fluctuate based on the market conditions. Recommended for short-term positions.":"Variable interest rate will <0>fluctuate based on the market conditions. Recommended for short-term positions.","Version 2":"Version 2","Version 3":"Version 3","View contract":"View contract","View details":"View details","View on Explorer":"View on Explorer","Vote":"Vote","Vote NAY":"Vote NAY","Vote YAE":"Vote YAE","Voting power":"Voting power","Voting results":"Voting results","Wallet balance":"Wallet balance","Wallet not detected. Connect or install wallet and retry":"Wallet not detected. Connect or install wallet and retry","Wallets are provided by External Providers and by selecting you agree to Terms of those Providers. Your access to the wallet might be reliant on the External Provider being operational.":"Wallets are provided by External Providers and by selecting you agree to Terms of those Providers. Your access to the wallet might be reliant on the External Provider being operational.","Watch-only mode allows to see address positions in Aave, but you won't be able to perform transactions.":"Watch-only mode allows to see address positions in Aave, but you won't be able to perform transactions.","Watch-only mode.":"Watch-only mode.","Watch-only mode. Connect to a wallet to perform transactions.":"Watch-only mode. Connect to a wallet to perform transactions.","We couldn't find any asset matching your search. Try again with a different asset name, symbol, or address.":"We couldn't find any asset matching your search. Try again with a different asset name, symbol, or address.","We couldn’t detect a wallet. Connect a wallet to stake.":"We couldn’t detect a wallet. Connect a wallet to stake.","We suggest you go back to the Dashboard.":"We suggest you go back to the Dashboard.","When a liquidation occurs, liquidators repay up to 50% of the outstanding borrowed amount on behalf of the borrower. In return, they can buy the collateral at a discount and keep the difference (liquidation penalty) as a bonus.":"When a liquidation occurs, liquidators repay up to 50% of the outstanding borrowed amount on behalf of the borrower. In return, they can buy the collateral at a discount and keep the difference (liquidation penalty) as a bonus.","Why do I need to approve?":"Why do I need to approve?","With a voting power of <0/>":"With a voting power of <0/>","With testnet Faucet you can get free assets to test the Aave Protocol. Make sure to switch your wallet provider to the appropriate testnet network, select desired asset, and click ‘Faucet’ to get tokens transferred to your wallet. The assets on a testnet are not “real,” meaning they have no monetary value. <0>Learn more":"With testnet Faucet you can get free assets to test the Aave Protocol. Make sure to switch your wallet provider to the appropriate testnet network, select desired asset, and click ‘Faucet’ to get tokens transferred to your wallet. The assets on a testnet are not “real,” meaning they have no monetary value. <0>Learn more","Withdraw":"Withdraw","Withdraw {symbol}":["Withdraw ",["symbol"]],"Withdrawing this amount will reduce your health factor and increase risk of liquidation.":"Withdrawing this amount will reduce your health factor and increase risk of liquidation.","Withdrawing {symbol}":["Withdrawing ",["symbol"]],"Wrong Network":"Wrong Network","YAE":"YAE","Yes":"Yes","You are entering Isolation mode":"You are entering Isolation mode","You can borrow this asset with a stable rate only if you borrow more than the amount you are supplying as collateral.":"You can borrow this asset with a stable rate only if you borrow more than the amount you are supplying as collateral.","You can not change Interest Type to stable as your borrowings are higher than your collateral":"You can not change Interest Type to stable as your borrowings are higher than your collateral","You can not disable E-Mode as your current collateralization level is above 80%, disabling E-Mode can cause liquidation. To exit E-Mode supply or repay borrowed positions.":"You can not disable E-Mode as your current collateralization level is above 80%, disabling E-Mode can cause liquidation. To exit E-Mode supply or repay borrowed positions.","You can not switch usage as collateral mode for this currency, because it will cause collateral call":"You can not switch usage as collateral mode for this currency, because it will cause collateral call","You can not use this currency as collateral":"You can not use this currency as collateral","You can not withdraw this amount because it will cause collateral call":"You can not withdraw this amount because it will cause collateral call","You can only withdraw your assets from the Security Module after the cooldown period ends and the unstake window is active.":"You can only withdraw your assets from the Security Module after the cooldown period ends and the unstake window is active.","You can report incident to our <0>Discord or <1>Github.":"You can report incident to our <0>Discord or <1>Github.","You cancelled the transaction.":"You cancelled the transaction.","You did not participate in this proposal":"You did not participate in this proposal","You do not have supplies in this currency":"You do not have supplies in this currency","You don’t have enough funds in your wallet to repay the full amount. If you proceed to repay with your current amount of funds, you will still have a small borrowing position in your dashboard.":"You don’t have enough funds in your wallet to repay the full amount. If you proceed to repay with your current amount of funds, you will still have a small borrowing position in your dashboard.","You have not borrow yet using this currency":"You have not borrow yet using this currency","You switched to {0} rate":["You switched to ",["0"]," rate"],"You unstake here":"You unstake here","You voted {0}":["You voted ",["0"]],"You will exit isolation mode and other tokens can now be used as collateral":"You will exit isolation mode and other tokens can now be used as collateral","You {action} <0/> {symbol}":["You ",["action"]," <0/> ",["symbol"]],"Your borrows":"Your borrows","Your current loan to value based on your collateral supplied.":"Your current loan to value based on your collateral supplied.","Your health factor and loan to value determine the assurance of your collateral. To avoid liquidations you can supply more collateral or repay borrow positions.":"Your health factor and loan to value determine the assurance of your collateral. To avoid liquidations you can supply more collateral or repay borrow positions.","Your info":"Your info","Your reward balance is 0":"Your reward balance is 0","Your supplies":"Your supplies","Your voting info":"Your voting info","Your {name} wallet is empty. Purchase or transfer assets or use <0>{0} to transfer your {network} assets.":["Your ",["name"]," wallet is empty. Purchase or transfer assets or use <0>",["0"]," to transfer your ",["network"]," assets."],"Your {name} wallet is empty. Purchase or transfer assets.":["Your ",["name"]," wallet is empty. Purchase or transfer assets."],"Your {networkName} wallet is empty. Get free test assets at":["Your ",["networkName"]," wallet is empty. Get free test assets at"],"Your {networkName} wallet is empty. Get free test {0} at":["Your ",["networkName"]," wallet is empty. Get free test ",["0"]," at"],"Zero address not valid":"Zero address not valid","assets":"assets","blocked activities":"blocked activities","copy the error":"copy the error","documentation":"documentation","ends":"ends","here.":"here.","is an asset affected by rebasing. Visit the":"is an asset affected by rebasing. Visit the","of":"of","on":"on","or":"or","please check that the amount you want to supply is not currently being used for staking. If it is being used for staking, your transaction might fail.":"please check that the amount you want to supply is not currently being used for staking. If it is being used for staking, your transaction might fail.","repaid":"repaid","staking view":"staking view","to learn more.":"to learn more.","tokens is not the same as staking them. If you wish to stake your":"tokens is not the same as staking them. If you wish to stake your","tokens, please go to the":"tokens, please go to the","withdrew":"withdrew","{0}":[["0"]],"{0} Balance":[["0"]," Balance"],"{0} Faucet":[["0"]," Faucet"],"{d}d":[["d"],"d"],"{h}h":[["h"],"h"],"{m}m":[["m"],"m"],"{networkName} Faucet":[["networkName"]," Faucet"],"{s}s":[["s"],"s"],"{tooltipText}":[["tooltipText"]]}}; \ No newline at end of file diff --git a/src/locales/en/messages.po b/src/locales/en/messages.po index dbba19a14d..7c10ea6dbe 100644 --- a/src/locales/en/messages.po +++ b/src/locales/en/messages.po @@ -21,6 +21,10 @@ msgstr "<0>Ampleforth is an asset affected by rebasing. Visit the <1>documen msgid "<0>Attention: Parameter changes via governance can alter your account health factor and risk of liquidation. Follow the <1>Aave governance forum for updates." msgstr "<0>Attention: Parameter changes via governance can alter your account health factor and risk of liquidation. Follow the <1>Aave governance forum for updates." +#: src/modules/dashboard/lists/SlippageList.tsx +msgid "<0>Slippage tolerance <1>{selectedSlippage}% <2>{0}" +msgstr "<0>Slippage tolerance <1>{selectedSlippage}% <2>{0}" + #: src/modules/staking/StakingHeader.tsx msgid "AAVE holders can stake their AAVE in the Safety Module to add more security to the protocol and earn Safety Incentives. In the case of a shortfall event, up to 30% of your stake can be slashed to cover the deficit, providing an additional layer of protection for the protocol." msgstr "AAVE holders can stake their AAVE in the Safety Module to add more security to the protocol and earn Safety Incentives. In the case of a shortfall event, up to 30% of your stake can be slashed to cover the deficit, providing an additional layer of protection for the protocol." @@ -262,7 +266,6 @@ msgstr "Available to supply" msgid "Back to Dashboard" msgstr "Back to Dashboard" -#: src/components/transactions/AssetInput.tsx #: src/components/transactions/ClaimRewards/ClaimRewardsModalContent.tsx #: src/modules/dashboard/lists/BorrowedPositionsList/BorrowedPositionsList.tsx #: src/modules/dashboard/lists/SuppliedPositionsList/SuppliedPositionsList.tsx @@ -314,6 +317,10 @@ msgstr "Borrow APY, variable" msgid "Borrow and repay in same block is not allowed" msgstr "Borrow and repay in same block is not allowed" +#: src/components/transactions/Repay/CollateralRepayModalContent.tsx +msgid "Borrow balance after repay" +msgstr "Borrow balance after repay" + #: src/modules/reserve-overview/ReserveConfiguration.tsx msgid "Borrow cap" msgstr "Borrow cap" @@ -378,6 +385,7 @@ msgstr "CLAIM {symbol}" msgid "CLAIMING {symbol}" msgstr "CLAIMING {symbol}" +#: src/components/transactions/Swap/SwapModalDetails.tsx #: src/modules/dashboard/lists/SupplyAssetsList/SupplyAssetsList.tsx #: src/modules/dashboard/lists/SupplyAssetsList/SupplyAssetsListMobileItem.tsx #: src/modules/reserve-overview/ReserveConfiguration.tsx @@ -446,13 +454,17 @@ msgid "Collateral" msgstr "Collateral" #: src/components/transactions/Repay/CollateralRepayModalContent.tsx -msgid "Collateral amount to repay with" -msgstr "Collateral amount to repay with" +msgid "Collateral balance after repay" +msgstr "Collateral balance after repay" #: src/ui-config/errorMapping.tsx msgid "Collateral is (mostly) the same currency that is being borrowed" msgstr "Collateral is (mostly) the same currency that is being borrowed" +#: src/components/transactions/Repay/CollateralRepayModalContent.tsx +msgid "Collateral to repay with" +msgstr "Collateral to repay with" + #: src/modules/reserve-overview/ReserveConfiguration.tsx #: src/modules/reserve-overview/ReserveConfiguration.tsx #: src/modules/reserve-overview/ReserveConfiguration.tsx @@ -551,10 +563,6 @@ msgstr "Data couldn't be fetched, please reload graph." msgid "Debt" msgstr "Debt" -#: src/components/transactions/Repay/CollateralRepayModalContent.tsx -msgid "Debt amount to repay" -msgstr "Debt amount to repay" - #: src/ui-config/errorMapping.tsx msgid "Debt ceiling is exceeded" msgstr "Debt ceiling is exceeded" @@ -734,6 +742,10 @@ msgstr "Error connecting. Try refreshing the page." msgid "Executed" msgstr "Executed" +#: src/components/transactions/Repay/CollateralRepayModalContent.tsx +msgid "Expected amount to repay" +msgstr "Expected amount to repay" + #: src/modules/governance/FormattedProposalTime.tsx msgid "Expires" msgstr "Expires" @@ -968,6 +980,7 @@ msgstr "Liquidation risk" msgid "Liquidation risk parameters" msgstr "Liquidation risk parameters" +#: src/components/transactions/Swap/SwapModalDetails.tsx #: src/modules/reserve-overview/ReserveConfiguration.tsx #: src/modules/reserve-overview/ReserveConfiguration.tsx msgid "Liquidation threshold" @@ -1011,11 +1024,6 @@ msgstr "Max LTV" msgid "Max slashing" msgstr "Max slashing" -#: src/components/transactions/Repay/CollateralRepayModalContent.tsx -#: src/components/transactions/Swap/SwapModalContent.tsx -msgid "Max slippage rate" -msgstr "Max slippage rate" - #: src/components/transactions/Warnings/DebtCeilingWarning.tsx msgid "Maximum amount available to borrow against this asset is limited because debt ceiling is at {0}%." msgstr "Maximum amount available to borrow against this asset is limited because debt ceiling is at {0}%." @@ -1041,11 +1049,6 @@ msgstr "Maximum loan to value" msgid "Menu" msgstr "Menu" -#: src/components/transactions/Repay/CollateralRepayModalContent.tsx -#: src/components/transactions/Swap/SwapModalContent.tsx -msgid "Minimum received" -msgstr "Minimum received" - #: src/layouts/MoreMenu.tsx msgid "More" msgstr "More" @@ -1086,6 +1089,10 @@ msgstr "Network not supported for this wallet" msgid "New APY" msgstr "New APY" +#: src/components/transactions/Swap/SwapModalDetails.tsx +msgid "No" +msgstr "No" + #: src/components/transactions/StakeRewardClaim/StakeRewardClaimModalContent.tsx msgid "No rewards to claim" msgstr "No rewards to claim" @@ -1210,10 +1217,14 @@ msgstr "Please, connect your wallet" msgid "Pool addresses provider is not registered" msgstr "Pool addresses provider is not registered" +#: src/modules/dashboard/lists/SlippageList.tsx +msgid "Powered by" +msgstr "Powered by" + #: src/components/transactions/Repay/CollateralRepayModalContent.tsx #: src/components/transactions/Swap/SwapModalContent.tsx -msgid "Price impact" -msgstr "Price impact" +msgid "Price impact <0/>%" +msgstr "Price impact <0/>%" #: pages/governance/proposal/[proposalId].governance.tsx msgid "Proposal details" @@ -1290,7 +1301,6 @@ msgstr "Reload" msgid "Reload the page" msgstr "Reload the page" -#: src/components/transactions/Repay/CollateralRepayModalContent.tsx #: src/components/transactions/Repay/RepayModalContent.tsx msgid "Remaining debt" msgstr "Remaining debt" @@ -1399,6 +1409,10 @@ msgstr "Select APY type to switch" msgid "Select language" msgstr "Select language" +#: src/modules/dashboard/lists/SlippageList.tsx +msgid "Select slippage tolerance" +msgstr "Select slippage tolerance" + #: src/modules/reserve-overview/AddTokenDropdown.tsx msgid "Select token to add" msgstr "Select token to add" @@ -1524,6 +1538,10 @@ msgstr "State" msgid "Supplied" msgstr "Supplied" +#: src/components/transactions/Swap/SwapModalContent.tsx +msgid "Supplied asset amount" +msgstr "Supplied asset amount" + #: pages/index.page.tsx #: src/components/transactions/Supply/SupplyModal.tsx #: src/modules/dashboard/lists/SuppliedPositionsList/SuppliedPositionsListItem.tsx @@ -1542,7 +1560,7 @@ msgstr "Supply" msgid "Supply APY" msgstr "Supply APY" -#: src/components/transactions/Swap/SwapModalContent.tsx +#: src/components/transactions/Swap/SwapModalDetails.tsx msgid "Supply apy" msgstr "Supply apy" @@ -1552,6 +1570,10 @@ msgstr "Supply apy" msgid "Supply balance" msgstr "Supply balance" +#: src/components/transactions/Swap/SwapModalDetails.tsx +msgid "Supply balance after swap" +msgstr "Supply balance after swap" + #: src/ui-config/errorMapping.tsx msgid "Supply cap is exceeded" msgstr "Supply cap is exceeded" @@ -1579,6 +1601,10 @@ msgstr "Supplying {symbol}" msgid "Swap" msgstr "Swap" +#: src/components/transactions/Swap/SwapModalContent.tsx +msgid "Swap to" +msgstr "Swap to" + #: src/components/transactions/Swap/SwapModalContent.tsx msgid "Swapped" msgstr "Swapped" @@ -2061,6 +2087,10 @@ msgstr "Wrong Network" msgid "YAE" msgstr "YAE" +#: src/components/transactions/Swap/SwapModalDetails.tsx +msgid "Yes" +msgstr "Yes" + #: src/components/transactions/Warnings/IsolationModeWarning.tsx msgid "You are entering Isolation mode" msgstr "You are entering Isolation mode" @@ -2264,6 +2294,7 @@ msgid "withdrew" msgstr "withdrew" #: src/components/MarketSwitcher.tsx +#: src/components/transactions/AssetInput.tsx #: src/components/transactions/StakeCooldown/StakeCooldownModalContent.tsx #: src/components/transactions/StakeCooldown/StakeCooldownModalContent.tsx #: src/modules/dashboard/DashboardEModeButton.tsx diff --git a/src/locales/es/messages.po b/src/locales/es/messages.po index 728fc13eb5..3272d7ae04 100644 --- a/src/locales/es/messages.po +++ b/src/locales/es/messages.po @@ -727,6 +727,10 @@ msgstr "Introduce la dirección ETH" msgid "Enter an address to track in watch-only mode" msgstr "Introduce una dirección para rastrear en modo de solo lectura" +#: src/components/WalletConnection/WalletSelector.tsx +msgid "Enter an address to track in watch-only mode" +msgstr "Introduce una dirección para rastrear en modo de solo lectura" + #: src/components/transactions/TxActionsWrapper.tsx msgid "Enter an amount" msgstr "Ingresa una cantidad" @@ -921,6 +925,10 @@ msgstr "Los activos aislados han limitado tu capacidad de préstamo y otros acti msgid "Join the community discussion" msgstr "Únete a la discusión de la comunidad" +#: src/components/transactions/Warnings/MarketWarning.tsx +msgid "Join the community discussion" +msgstr "Únete a la discusión de la comunidad" + #: src/layouts/components/LanguageSwitcher.tsx msgid "Language" msgstr "Idioma" @@ -1203,6 +1211,10 @@ msgstr "Por favor, conecta tu cartera para ver tus suministros, préstamos y pos msgid "Please enter a valid wallet address." msgstr "Por favor introduce una dirección de cartera válida." +#: src/components/WalletConnection/WalletSelector.tsx +msgid "Please enter a valid wallet address." +msgstr "Por favor introduce una dirección de cartera válida." + #: src/components/transactions/Warnings/ChangeNetworkWarning.tsx msgid "Please switch to {networkName}." msgstr "Por favor, cambia a {networkName}." diff --git a/src/modules/dashboard/lists/BorrowedPositionsList/BorrowedPositionsListItem.tsx b/src/modules/dashboard/lists/BorrowedPositionsList/BorrowedPositionsListItem.tsx index 019717973a..9ff5cc0662 100644 --- a/src/modules/dashboard/lists/BorrowedPositionsList/BorrowedPositionsListItem.tsx +++ b/src/modules/dashboard/lists/BorrowedPositionsList/BorrowedPositionsListItem.tsx @@ -77,7 +77,7 @@ export const BorrowedPositionsListItem = ({ diff --git a/src/modules/dashboard/lists/BorrowedPositionsList/BorrowedPositionsListMobileItem.tsx b/src/modules/dashboard/lists/BorrowedPositionsList/BorrowedPositionsListMobileItem.tsx index 08387b2c8f..c49c060d48 100644 --- a/src/modules/dashboard/lists/BorrowedPositionsList/BorrowedPositionsListMobileItem.tsx +++ b/src/modules/dashboard/lists/BorrowedPositionsList/BorrowedPositionsListMobileItem.tsx @@ -86,7 +86,7 @@ export const BorrowedPositionsListMobileItem = ({