From 7439bea0d8a0988e7e46b586eb41e2307d56ca2e Mon Sep 17 00:00:00 2001 From: Bob van der Helm <34470358+bobthebuidlr@users.noreply.github.com> Date: Wed, 8 Nov 2023 13:05:39 +0100 Subject: [PATCH] Hls staking manage actions (#622) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * ✨Add basic modal for HLS staking * ✨UI components for Manage * ✨All Manage actions (except change lev) * 🐛hls intro icons + checkbox, hide repay when no debt, clickable dropdown * fix build --- src/api/hls/getHLSStakingAccounts.ts | 6 +- .../Account/Health/HealthTooltip.tsx | 4 +- src/components/Button/DropDownButton.tsx | 11 +- src/components/Checkbox.tsx | 6 +- .../HLS/Farm/Table/Columns/Deposit.tsx | 8 +- .../HLS/Staking/Table/Columns/Manage.tsx | 46 +++- src/components/Icons/Circle.svg | 10 + src/components/Icons/Scale.svg | 5 + src/components/Icons/index.ts | 2 + src/components/Modal.tsx | 4 +- src/components/Modals/AlertDialog/index.tsx | 2 +- .../HLS/{ => Deposit}/CreateAccount.tsx | 0 .../Modals/HLS/{ => Deposit}/Leverage.tsx | 2 +- .../HLS/{ => Deposit}/LeverageSummary.tsx | 20 +- .../HLS/{ => Deposit}/ProvideCollateral.tsx | 0 .../HLS/{ => Deposit}/SelectAccount.tsx | 0 .../Modals/HLS/{ => Deposit}/SubTitles.tsx | 0 .../{ => Deposit}/Summary/ApyBreakdown.tsx | 0 .../{ => Deposit}/Summary/AssetSummary.tsx | 2 +- .../HLS/{ => Deposit}/Summary/Container.tsx | 0 .../{ => Deposit}/Summary/YourPosition.tsx | 10 +- .../HLS/{ => Deposit}/Summary/index.tsx | 4 +- .../Modals/HLS/{Content => Deposit}/index.tsx | 6 +- .../useAccordionItems.tsx | 16 +- .../useStakingController.tsx | 39 +--- .../useVaultController.tsx | 0 src/components/Modals/HLS/Header.tsx | 8 +- .../Modals/HLS/Manage/ChangeLeverage.tsx | 10 + src/components/Modals/HLS/Manage/Deposit.tsx | 204 ++++++++++++++++++ src/components/Modals/HLS/Manage/Repay.tsx | 98 +++++++++ src/components/Modals/HLS/Manage/Withdraw.tsx | 62 ++++++ src/components/Modals/HLS/Manage/index.tsx | 60 ++++-- src/components/Modals/HLS/index.tsx | 2 +- .../Modals/ModalContentWithSummary.tsx | 38 ++++ src/components/SummaryItems.tsx | 25 +++ src/components/Tooltip/index.tsx | 6 +- src/hooks/HLS/useClosePositionActions.ts | 59 +++++ src/hooks/HLS/useDepositActions.ts | 38 ++++ src/hooks/useDepositHlsVault.ts | 44 ++++ src/hooks/useUpdatedAccount/index.ts | 18 +- src/store/slices/broadcast.ts | 37 +++- .../interfaces/components/SummaryItems.d.ts | 5 + src/types/interfaces/store/broadcast.d.ts | 5 + src/types/interfaces/store/modals.d.ts | 5 +- 44 files changed, 805 insertions(+), 122 deletions(-) create mode 100644 src/components/Icons/Circle.svg create mode 100644 src/components/Icons/Scale.svg rename src/components/Modals/HLS/{ => Deposit}/CreateAccount.tsx (100%) rename src/components/Modals/HLS/{ => Deposit}/Leverage.tsx (91%) rename src/components/Modals/HLS/{ => Deposit}/LeverageSummary.tsx (58%) rename src/components/Modals/HLS/{ => Deposit}/ProvideCollateral.tsx (100%) rename src/components/Modals/HLS/{ => Deposit}/SelectAccount.tsx (100%) rename src/components/Modals/HLS/{ => Deposit}/SubTitles.tsx (100%) rename src/components/Modals/HLS/{ => Deposit}/Summary/ApyBreakdown.tsx (100%) rename src/components/Modals/HLS/{ => Deposit}/Summary/AssetSummary.tsx (94%) rename src/components/Modals/HLS/{ => Deposit}/Summary/Container.tsx (100%) rename src/components/Modals/HLS/{ => Deposit}/Summary/YourPosition.tsx (85%) rename src/components/Modals/HLS/{ => Deposit}/Summary/index.tsx (88%) rename src/components/Modals/HLS/{Content => Deposit}/index.tsx (95%) rename src/components/Modals/HLS/{Content => Deposit}/useAccordionItems.tsx (89%) rename src/components/Modals/HLS/{Content => Deposit}/useStakingController.tsx (63%) rename src/components/Modals/HLS/{Content => Deposit}/useVaultController.tsx (100%) create mode 100644 src/components/Modals/HLS/Manage/ChangeLeverage.tsx create mode 100644 src/components/Modals/HLS/Manage/Deposit.tsx create mode 100644 src/components/Modals/HLS/Manage/Repay.tsx create mode 100644 src/components/Modals/HLS/Manage/Withdraw.tsx create mode 100644 src/components/Modals/ModalContentWithSummary.tsx create mode 100644 src/components/SummaryItems.tsx create mode 100644 src/hooks/HLS/useClosePositionActions.ts create mode 100644 src/hooks/HLS/useDepositActions.ts create mode 100644 src/types/interfaces/components/SummaryItems.d.ts diff --git a/src/api/hls/getHLSStakingAccounts.ts b/src/api/hls/getHLSStakingAccounts.ts index 180e049f..3b5ab3eb 100644 --- a/src/api/hls/getHLSStakingAccounts.ts +++ b/src/api/hls/getHLSStakingAccounts.ts @@ -13,12 +13,10 @@ export default async function getHLSStakingAccounts( const hlsAccountsWithStrategy: HLSAccountWithStrategy[] = [] activeAccounts.forEach((account) => { - if (account.deposits.length === 0 || account.debts.length === 0) return + if (account.deposits.length === 0) return const strategy = hlsStrategies.find( - (strategy) => - strategy.denoms.deposit === account.deposits.at(0).denom && - strategy.denoms.borrow === account.debts.at(0).denom, + (strategy) => strategy.denoms.deposit === account.deposits.at(0).denom, ) if (!strategy) return diff --git a/src/components/Account/Health/HealthTooltip.tsx b/src/components/Account/Health/HealthTooltip.tsx index 6682990d..14a84dff 100644 --- a/src/components/Account/Health/HealthTooltip.tsx +++ b/src/components/Account/Health/HealthTooltip.tsx @@ -1,4 +1,4 @@ -import React, { useMemo } from 'react' +import React, { ReactElement, useMemo } from 'react' import { CircularProgress } from 'components/CircularProgress' import Text from 'components/Text' @@ -8,7 +8,7 @@ import { BN } from 'utils/helpers' interface Props { health: number healthFactor: number - children: React.ReactNode + children: ReactElement } function HealthTooltipContent({ health, healthFactor }: { health: number; healthFactor: number }) { diff --git a/src/components/Button/DropDownButton.tsx b/src/components/Button/DropDownButton.tsx index 0ea46a6e..18a7bc21 100644 --- a/src/components/Button/DropDownButton.tsx +++ b/src/components/Button/DropDownButton.tsx @@ -2,6 +2,7 @@ import Button from 'components/Button' import { ChevronDown } from 'components/Icons' import Text from 'components/Text' import { Tooltip } from 'components/Tooltip' +import useToggle from 'hooks/useToggle' interface Props extends ButtonProps { items: DropDownItem[] @@ -9,6 +10,7 @@ interface Props extends ButtonProps { } export default function DropDownButton(props: Props) { + const [isOpen, toggleIsOpen] = useToggle(false) return ( } @@ -17,8 +19,15 @@ export default function DropDownButton(props: Props) { contentClassName='!bg-white/10 border border-white/20 backdrop-blur-xl !p-0' interactive hideArrow + visible={isOpen} + onClickOutside={() => toggleIsOpen(false)} > - } iconClassName='w-3 h-3' {...props} /> + toggleIsOpen()} + rightIcon={} + iconClassName='w-3 h-3' + {...props} + /> ) } diff --git a/src/components/Checkbox.tsx b/src/components/Checkbox.tsx index 807b0586..0ca9b94d 100644 --- a/src/components/Checkbox.tsx +++ b/src/components/Checkbox.tsx @@ -13,13 +13,9 @@ interface Props { export default function Checkbox(props: Props) { return ( <> - + props.onChange(props.checked)} - id={`${props.name}-id`} name={props.name} checked={props.checked} type='checkbox' diff --git a/src/components/HLS/Farm/Table/Columns/Deposit.tsx b/src/components/HLS/Farm/Table/Columns/Deposit.tsx index b9cc0d62..0a3541df 100644 --- a/src/components/HLS/Farm/Table/Columns/Deposit.tsx +++ b/src/components/HLS/Farm/Table/Columns/Deposit.tsx @@ -2,7 +2,7 @@ import classNames from 'classnames' import { useCallback } from 'react' import ActionButton from 'components/Button/ActionButton' -import { Enter } from 'components/Icons' +import { Circle, Enter, TrashBin, Wallet } from 'components/Icons' import Loading from 'components/Loading' import Text from 'components/Text' import { LocalStorageKeys } from 'constants/localStorageKeys' @@ -91,18 +91,18 @@ export default function Deposit(props: Props) { const INFO_ITEMS = [ { - icon: , + icon: , title: 'One account, one position', description: 'A minted HLS account can only have a single position tied to it, in order to limit risk.', }, { - icon: , + icon: , title: 'Funded from your wallet', description: 'To fund your HLS position, funds will have to come directly from your wallet.', }, { - icon: , + icon: , title: 'Accounts are reusable', description: 'If you exited a position from a minted account, this account can be reused for a new position.', diff --git a/src/components/HLS/Staking/Table/Columns/Manage.tsx b/src/components/HLS/Staking/Table/Columns/Manage.tsx index cd71ecae..ca4c3c85 100644 --- a/src/components/HLS/Staking/Table/Columns/Manage.tsx +++ b/src/components/HLS/Staking/Table/Columns/Manage.tsx @@ -1,7 +1,8 @@ import React, { useCallback, useMemo } from 'react' import DropDownButton from 'components/Button/DropDownButton' -import { ArrowDownLine, HandCoins, Plus } from 'components/Icons' +import { ArrowDownLine, Cross, HandCoins, Plus, Scale } from 'components/Icons' +import useCloseHlsStakingPosition from 'hooks/HLS/useClosePositionActions' import useStore from 'store' export const MANAGE_META = { id: 'manage' } @@ -12,32 +13,55 @@ interface Props { export default function Manage(props: Props) { const openModal = useCallback( - (action: 'deposit' | 'withdraw' | 'repay') => + (action: HlsStakingManageAction) => useStore.setState({ - hlsManageModal: { staking: { strategy: props.account.strategy, action } }, + hlsManageModal: { + accountId: props.account.id, + staking: { strategy: props.account.strategy, action }, + }, }), - [props.account.strategy], + [props.account.id, props.account.strategy], ) + const actions = useCloseHlsStakingPosition({ account: props.account }) + + const closeHlsStakingPosition = useStore((s) => s.closeHlsStakingPosition) + + const hasNoDebt = useMemo(() => props.account.debts.length === 0, [props.account.debts.length]) + const ITEMS: DropDownItem[] = useMemo( () => [ + { + icon: , + text: 'Change leverage', + onClick: () => openModal('leverage'), + }, { icon: , text: 'Deposit more', onClick: () => openModal('deposit'), }, + ...(hasNoDebt + ? [] + : [ + { + icon: , + text: 'Repay', + onClick: () => openModal('repay'), + }, + ]), { - icon: , - text: 'Repay', - onClick: () => openModal('repay'), - }, - { - icon: , + icon: , text: 'Withdraw', onClick: () => openModal('withdraw'), }, + { + icon: , + text: 'Close Position', + onClick: () => closeHlsStakingPosition({ accountId: props.account.id, actions }), + }, ], - [openModal], + [actions, closeHlsStakingPosition, openModal, props.account.id], ) return diff --git a/src/components/Icons/Circle.svg b/src/components/Icons/Circle.svg new file mode 100644 index 00000000..fcbf46c3 --- /dev/null +++ b/src/components/Icons/Circle.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/src/components/Icons/Scale.svg b/src/components/Icons/Scale.svg new file mode 100644 index 00000000..87e7b220 --- /dev/null +++ b/src/components/Icons/Scale.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/src/components/Icons/index.ts b/src/components/Icons/index.ts index 5e010b1c..4b503b77 100644 --- a/src/components/Icons/index.ts +++ b/src/components/Icons/index.ts @@ -14,6 +14,7 @@ export { default as ChevronDown } from 'components/Icons/ChevronDown.svg' export { default as ChevronLeft } from 'components/Icons/ChevronLeft.svg' export { default as ChevronRight } from 'components/Icons/ChevronRight.svg' export { default as ChevronUp } from 'components/Icons/ChevronUp.svg' +export { default as Circle } from 'components/Icons/Circle.svg' export { default as Compass } from 'components/Icons/Compass.svg' export { default as Copy } from 'components/Icons/Copy.svg' export { default as Cross } from 'components/Icons/Cross.svg' @@ -43,6 +44,7 @@ export { default as PlusCircled } from 'components/Icons/PlusCircled.svg' export { default as PlusSquared } from 'components/Icons/PlusSquared.svg' export { default as Questionmark } from 'components/Icons/Questionmark.svg' export { default as ReceiptCheck } from 'components/Icons/ReceiptCheck.svg' +export { default as Scale } from 'components/Icons/Scale.svg' export { default as Search } from 'components/Icons/Search.svg' export { default as Shield } from 'components/Icons/Shield.svg' export { default as SortAsc } from 'components/Icons/SortAsc.svg' diff --git a/src/components/Modal.tsx b/src/components/Modal.tsx index d82ada7c..14175290 100644 --- a/src/components/Modal.tsx +++ b/src/components/Modal.tsx @@ -4,7 +4,7 @@ import { ReactNode, useEffect, useRef } from 'react' import EscButton from 'components/Button/EscButton' import Card from 'components/Card' -interface Props { +export interface ModalProps { header: string | ReactNode headerClassName?: string hideCloseBtn?: boolean @@ -18,7 +18,7 @@ interface Props { dialogId?: string } -export default function Modal(props: Props) { +export default function Modal(props: ModalProps) { const ref: React.RefObject = useRef(null) const modalClassName = props.modalClassName ?? 'max-w-modal' diff --git a/src/components/Modals/AlertDialog/index.tsx b/src/components/Modals/AlertDialog/index.tsx index 623eadb1..68512648 100644 --- a/src/components/Modals/AlertDialog/index.tsx +++ b/src/components/Modals/AlertDialog/index.tsx @@ -75,7 +75,7 @@ function AlertDialog(props: Props) { )} {checkbox && ( { + const items: SummaryItem[] = useMemo(() => { return [ // TODO: Get APY numbers { @@ -33,18 +32,5 @@ export default function LeverageSummary(props: Props) { ] }, [borrowAsset?.borrowRate, props.asset.symbol, props.positionValue]) - return ( - - {items.map((item) => ( - - {item.title} - - - ))} - - ) + return } diff --git a/src/components/Modals/HLS/ProvideCollateral.tsx b/src/components/Modals/HLS/Deposit/ProvideCollateral.tsx similarity index 100% rename from src/components/Modals/HLS/ProvideCollateral.tsx rename to src/components/Modals/HLS/Deposit/ProvideCollateral.tsx diff --git a/src/components/Modals/HLS/SelectAccount.tsx b/src/components/Modals/HLS/Deposit/SelectAccount.tsx similarity index 100% rename from src/components/Modals/HLS/SelectAccount.tsx rename to src/components/Modals/HLS/Deposit/SelectAccount.tsx diff --git a/src/components/Modals/HLS/SubTitles.tsx b/src/components/Modals/HLS/Deposit/SubTitles.tsx similarity index 100% rename from src/components/Modals/HLS/SubTitles.tsx rename to src/components/Modals/HLS/Deposit/SubTitles.tsx diff --git a/src/components/Modals/HLS/Summary/ApyBreakdown.tsx b/src/components/Modals/HLS/Deposit/Summary/ApyBreakdown.tsx similarity index 100% rename from src/components/Modals/HLS/Summary/ApyBreakdown.tsx rename to src/components/Modals/HLS/Deposit/Summary/ApyBreakdown.tsx diff --git a/src/components/Modals/HLS/Summary/AssetSummary.tsx b/src/components/Modals/HLS/Deposit/Summary/AssetSummary.tsx similarity index 94% rename from src/components/Modals/HLS/Summary/AssetSummary.tsx rename to src/components/Modals/HLS/Deposit/Summary/AssetSummary.tsx index 031b9916..db4e08e8 100644 --- a/src/components/Modals/HLS/Summary/AssetSummary.tsx +++ b/src/components/Modals/HLS/Deposit/Summary/AssetSummary.tsx @@ -3,7 +3,7 @@ import React from 'react' import AmountAndValue from 'components/AmountAndValue' import AssetImage from 'components/Asset/AssetImage' import { FormattedNumber } from 'components/FormattedNumber' -import Container from 'components/Modals/HLS/Summary/Container' +import Container from 'components/Modals/HLS/Deposit/Summary/Container' import Text from 'components/Text' interface Props { diff --git a/src/components/Modals/HLS/Summary/Container.tsx b/src/components/Modals/HLS/Deposit/Summary/Container.tsx similarity index 100% rename from src/components/Modals/HLS/Summary/Container.tsx rename to src/components/Modals/HLS/Deposit/Summary/Container.tsx diff --git a/src/components/Modals/HLS/Summary/YourPosition.tsx b/src/components/Modals/HLS/Deposit/Summary/YourPosition.tsx similarity index 85% rename from src/components/Modals/HLS/Summary/YourPosition.tsx rename to src/components/Modals/HLS/Deposit/Summary/YourPosition.tsx index f0769ebc..dc8201fd 100644 --- a/src/components/Modals/HLS/Summary/YourPosition.tsx +++ b/src/components/Modals/HLS/Deposit/Summary/YourPosition.tsx @@ -3,8 +3,8 @@ import React, { useMemo } from 'react' import DisplayCurrency from 'components/DisplayCurrency' import { FormattedNumber } from 'components/FormattedNumber' import { InfoCircle } from 'components/Icons' -import AprBreakdown from 'components/Modals/HLS/Summary/ApyBreakdown' -import Container from 'components/Modals/HLS/Summary/Container' +import AprBreakdown from 'components/Modals/HLS/Deposit/Summary/ApyBreakdown' +import Container from 'components/Modals/HLS/Deposit/Summary/Container' import Text from 'components/Text' import { Tooltip } from 'components/Tooltip' import { BNCoin } from 'types/classes/BNCoin' @@ -63,8 +63,10 @@ export default function YourPosition(props: Props) { type='info' className='items-center flex gap-2 group-hover/apytooltip:text-white text-white/60 cursor-pointer' > - Net APY{' '} - + <> + Net APY{' '} + + > (LocalStorageKeys.SLIPPAGE, DEFAULT_SETTINGS.slippage) const addToStakingStrategy = useStore((s) => s.addToStakingStrategy) const { @@ -28,40 +23,14 @@ export default function useVaultController(props: Props) { setBorrowAmount, borrowAmount, positionValue, + borrowCoin, + depositCoin, + actions, } = useDepositHlsVault({ collateralDenom: collateralAsset.denom, borrowDenom: borrowAsset.denom, }) - const depositCoin = useMemo( - () => BNCoin.fromDenomAndBigNumber(collateralAsset.denom, depositAmount), - [collateralAsset.denom, depositAmount], - ) - - const borrowCoin = useMemo( - () => BNCoin.fromDenomAndBigNumber(borrowAsset.denom, borrowAmount), - [borrowAsset.denom, borrowAmount], - ) - - const actions: Action[] = useMemo( - () => [ - { - deposit: depositCoin.toCoin(), - }, - { - borrow: borrowCoin.toCoin(), - }, - { - swap_exact_in: { - denom_out: collateralAsset.denom, - slippage: slippage.toString(), - coin_in: BNCoin.fromDenomAndBigNumber(borrowAsset.denom, borrowAmount).toActionCoin(), - }, - }, - ], - [borrowAmount, borrowAsset.denom, borrowCoin, collateralAsset.denom, depositCoin, slippage], - ) - const { updatedAccount, addDeposits } = useUpdatedAccount(selectedAccount) const { computeMaxBorrowAmount } = useHealthComputer(updatedAccount) diff --git a/src/components/Modals/HLS/Content/useVaultController.tsx b/src/components/Modals/HLS/Deposit/useVaultController.tsx similarity index 100% rename from src/components/Modals/HLS/Content/useVaultController.tsx rename to src/components/Modals/HLS/Deposit/useVaultController.tsx diff --git a/src/components/Modals/HLS/Header.tsx b/src/components/Modals/HLS/Header.tsx index 2e963a10..f38c5b07 100644 --- a/src/components/Modals/HLS/Header.tsx +++ b/src/components/Modals/HLS/Header.tsx @@ -7,16 +7,18 @@ import Text from 'components/Text' interface Props { primaryAsset: Asset secondaryAsset: Asset + action?: HlsStakingManageAction } export default function Header(props: Props) { return ( - {`${props.secondaryAsset.symbol} - ${props.primaryAsset.symbol}`} + {`${props.primaryAsset.symbol}/${props.secondaryAsset.symbol}`} + {props.action && - {props.action}} ) diff --git a/src/components/Modals/HLS/Manage/ChangeLeverage.tsx b/src/components/Modals/HLS/Manage/ChangeLeverage.tsx new file mode 100644 index 00000000..6cb40d3f --- /dev/null +++ b/src/components/Modals/HLS/Manage/ChangeLeverage.tsx @@ -0,0 +1,10 @@ +interface Props { + account: Account + action: HlsStakingManageAction + borrowAsset: Asset + collateralAsset: Asset +} + +export default function Repay(props: Props) { + return <>> +} diff --git a/src/components/Modals/HLS/Manage/Deposit.tsx b/src/components/Modals/HLS/Manage/Deposit.tsx new file mode 100644 index 00000000..33c8c445 --- /dev/null +++ b/src/components/Modals/HLS/Manage/Deposit.tsx @@ -0,0 +1,204 @@ +import BigNumber from 'bignumber.js' +import React, { useCallback, useEffect, useMemo } from 'react' + +import Button from 'components/Button' +import Divider from 'components/Divider' +import SummaryItems from 'components/SummaryItems' +import Switch from 'components/Switch' +import Text from 'components/Text' +import TokenInputWithSlider from 'components/TokenInput/TokenInputWithSlider' +import { BN_ZERO } from 'constants/math' +import useDepositActions from 'hooks/HLS/useDepositActions' +import useBorrowAsset from 'hooks/useBorrowAsset' +import useCurrentWalletBalance from 'hooks/useCurrentWalletBalance' +import useHealthComputer from 'hooks/useHealthComputer' +import usePrices from 'hooks/usePrices' +import useToggle from 'hooks/useToggle' +import { useUpdatedAccount } from 'hooks/useUpdatedAccount' +import useStore from 'store' +import { BNCoin } from 'types/classes/BNCoin' +import { calculateAccountLeverage } from 'utils/accounts' +import { byDenom } from 'utils/array' +import { getCoinAmount, getCoinValue } from 'utils/formatters' +import { BN } from 'utils/helpers' + +interface Props { + account: Account + action: HlsStakingManageAction + borrowAsset: Asset + collateralAsset: Asset +} + +export default function Deposit(props: Props) { + const { addedDeposits, addedDebts, updatedAccount, simulateHlsStakingDeposit } = + useUpdatedAccount(props.account) + const { computeMaxBorrowAmount } = useHealthComputer(updatedAccount) + const { data: prices } = usePrices() + const [keepLeverage, toggleKeepLeverage] = useToggle(true) + const collateralAssetAmountInWallet = BN( + useCurrentWalletBalance(props.collateralAsset.denom)?.amount || '0', + ) + const addToStakingStrategy = useStore((s) => s.addToStakingStrategy) + const borrowRate = useBorrowAsset(props.borrowAsset.denom)?.borrowRate || 0 + + const currentLeverage = useMemo( + () => calculateAccountLeverage(props.account, prices).toNumber(), + [prices, props.account], + ) + + const depositCoin = useMemo( + () => + BNCoin.fromDenomAndBigNumber( + props.collateralAsset.denom, + addedDeposits.find(byDenom(props.collateralAsset.denom))?.amount || BN_ZERO, + ), + [addedDeposits, props.collateralAsset.denom], + ) + + const borrowCoin = useMemo( + () => + BNCoin.fromDenomAndBigNumber( + props.borrowAsset.denom, + addedDebts.find(byDenom(props.borrowAsset.denom))?.amount || BN_ZERO, + ), + [addedDebts, props.borrowAsset.denom], + ) + + const maxBorrowAmount = useMemo( + () => computeMaxBorrowAmount(props.collateralAsset.denom, 'deposit'), + [computeMaxBorrowAmount, props.collateralAsset.denom], + ) + + useEffect(() => { + if (borrowCoin.amount.isGreaterThan(maxBorrowAmount)) { + simulateHlsStakingDeposit( + BNCoin.fromDenomAndBigNumber(props.collateralAsset.denom, depositCoin.amount), + BNCoin.fromDenomAndBigNumber(props.borrowAsset.denom, maxBorrowAmount), + ) + } + }, [ + borrowCoin.amount, + depositCoin.amount, + maxBorrowAmount, + props.borrowAsset.denom, + props.collateralAsset.denom, + simulateHlsStakingDeposit, + ]) + + const actions = useDepositActions({ depositCoin, borrowCoin }) + + const currentDebt: BigNumber = useMemo( + () => props.account.debts.find(byDenom(props.borrowAsset.denom)).amount || BN_ZERO, + [props.account.debts, props.borrowAsset.denom], + ) + + const handleDeposit = useCallback(() => { + useStore.setState({ hlsManageModal: null }) + addToStakingStrategy({ + accountId: props.account.id, + actions, + depositCoin, + borrowCoin, + }) + }, [actions, addToStakingStrategy, borrowCoin, depositCoin, props.account.id]) + + const handleOnChange = useCallback( + (amount: BigNumber) => { + let additionalDebt = BN_ZERO + + if (currentLeverage > 1 && keepLeverage) { + const depositValue = getCoinValue( + BNCoin.fromDenomAndBigNumber(props.collateralAsset.denom, amount), + prices, + ) + const borrowValue = BN(currentLeverage - 1).times(depositValue) + additionalDebt = getCoinAmount(props.borrowAsset.denom, borrowValue, prices) + } + + simulateHlsStakingDeposit( + BNCoin.fromDenomAndBigNumber(props.collateralAsset.denom, amount), + BNCoin.fromDenomAndBigNumber(props.borrowAsset.denom, additionalDebt), + ) + }, + [ + currentLeverage, + keepLeverage, + prices, + props.borrowAsset.denom, + props.collateralAsset.denom, + simulateHlsStakingDeposit, + ], + ) + + const items: SummaryItem[] = useMemo( + () => [ + ...(keepLeverage + ? [ + { + title: 'Borrow rate', + amount: borrowRate, + options: { + suffix: `%`, + minDecimals: 2, + maxDecimals: 2, + }, + }, + { + title: 'Additional Borrow Amount', + amount: borrowCoin.amount.toNumber(), + options: { + suffix: ` ${props.borrowAsset.symbol}`, + abbreviated: true, + decimals: props.borrowAsset.decimals, + }, + }, + { + title: 'New Debt Amount', + amount: currentDebt.plus(borrowCoin.amount).toNumber(), + options: { + suffix: ` ${props.borrowAsset.symbol}`, + abbreviated: true, + decimals: props.borrowAsset.decimals, + }, + }, + ] + : []), + ], + [ + borrowCoin.amount, + borrowRate, + currentDebt, + keepLeverage, + props.borrowAsset.decimals, + props.borrowAsset.symbol, + ], + ) + + return ( + <> + + + + + + Keep leverage + + Automatically borrow more funds to keep leverage + + + + + + + + + + > + ) +} diff --git a/src/components/Modals/HLS/Manage/Repay.tsx b/src/components/Modals/HLS/Manage/Repay.tsx new file mode 100644 index 00000000..f7b4a57f --- /dev/null +++ b/src/components/Modals/HLS/Manage/Repay.tsx @@ -0,0 +1,98 @@ +import BigNumber from 'bignumber.js' +import { useCallback, useMemo } from 'react' + +import Button from 'components/Button' +import SummaryItems from 'components/SummaryItems' +import TokenInputWithSlider from 'components/TokenInput/TokenInputWithSlider' +import { BN_ZERO } from 'constants/math' +import useCurrentWalletBalance from 'hooks/useCurrentWalletBalance' +import { useUpdatedAccount } from 'hooks/useUpdatedAccount' +import useStore from 'store' +import { BNCoin } from 'types/classes/BNCoin' +import { byDenom } from 'utils/array' +import { BN } from 'utils/helpers' + +interface Props { + account: Account + action: HlsStakingManageAction + borrowAsset: Asset + collateralAsset: Asset +} + +export default function Repay(props: Props) { + const { removeDebts, removedDebts } = useUpdatedAccount(props.account) + const borrowAssetAmountInWallet = BN( + useCurrentWalletBalance(props.borrowAsset.denom)?.amount || '0', + ) + const repay = useStore((s) => s.repay) + + const currentDebt: BigNumber = useMemo( + () => props.account.debts.find(byDenom(props.borrowAsset.denom)).amount || BN_ZERO, + [props.account.debts, props.borrowAsset.denom], + ) + + const repayAmount: BigNumber = useMemo( + () => removedDebts.find(byDenom(props.borrowAsset.denom))?.amount || BN_ZERO, + [removedDebts, props.borrowAsset.denom], + ) + + const maxRepayAmount = useMemo( + () => BigNumber.min(borrowAssetAmountInWallet.toNumber(), currentDebt), + [borrowAssetAmountInWallet, currentDebt], + ) + + const items: SummaryItem[] = useMemo( + () => [ + { + title: 'Total Debt Repayable', + amount: currentDebt.toNumber(), + options: { + suffix: ` ${props.borrowAsset.symbol}`, + abbreviated: true, + decimals: props.borrowAsset.decimals, + }, + }, + { + title: 'New Debt Amount', + amount: currentDebt.minus(repayAmount).toNumber(), + options: { + suffix: ` ${props.borrowAsset.symbol}`, + abbreviated: true, + decimals: props.borrowAsset.decimals, + }, + }, + ], + [currentDebt, props.borrowAsset.decimals, props.borrowAsset.symbol, repayAmount], + ) + + const handleRepay = useCallback(() => { + useStore.setState({ hlsManageModal: null }) + repay({ + accountId: props.account.id, + coin: BNCoin.fromDenomAndBigNumber(props.borrowAsset.denom, repayAmount), + fromWallet: true, + }) + }, [props.account.id, props.borrowAsset.denom, repay, repayAmount]) + + const handleOnChange = useCallback( + (amount: BigNumber) => + removeDebts([BNCoin.fromDenomAndBigNumber(props.borrowAsset.denom, amount)]), + [props.borrowAsset.denom, removeDebts], + ) + + return ( + <> + + + + + + > + ) +} diff --git a/src/components/Modals/HLS/Manage/Withdraw.tsx b/src/components/Modals/HLS/Manage/Withdraw.tsx new file mode 100644 index 00000000..6dbb0f0b --- /dev/null +++ b/src/components/Modals/HLS/Manage/Withdraw.tsx @@ -0,0 +1,62 @@ +import React, { useCallback, useMemo } from 'react' + +import Button from 'components/Button' +import TokenInputWithSlider from 'components/TokenInput/TokenInputWithSlider' +import { BN_ZERO } from 'constants/math' +import useHealthComputer from 'hooks/useHealthComputer' +import { useUpdatedAccount } from 'hooks/useUpdatedAccount' +import useStore from 'store' +import { BNCoin } from 'types/classes/BNCoin' +import { byDenom } from 'utils/array' + +interface Props { + account: Account + action: HlsStakingManageAction + borrowAsset: Asset + collateralAsset: Asset +} + +export default function Withdraw(props: Props) { + const { removedDeposits, removeDeposits, updatedAccount } = useUpdatedAccount(props.account) + const { computeMaxWithdrawAmount } = useHealthComputer(updatedAccount) + const withdraw = useStore((s) => s.withdraw) + const handleChange = useCallback( + (amount: BigNumber) => + removeDeposits([BNCoin.fromDenomAndBigNumber(props.collateralAsset.denom, amount)]), + [removeDeposits, props.collateralAsset.denom], + ) + + const removedDeposit = useMemo( + () => removedDeposits.find(byDenom(props.collateralAsset.denom)), + [props.collateralAsset.denom, removedDeposits], + ) + + const maxWithdrawAmount = useMemo(() => { + const currentWithdrawAmount = removedDeposit?.amount || BN_ZERO + const extraWithdrawAmount = computeMaxWithdrawAmount(props.collateralAsset.denom) + return currentWithdrawAmount.plus(extraWithdrawAmount) + }, [computeMaxWithdrawAmount, props.collateralAsset.denom, removedDeposit?.amount]) + + const onClick = useCallback(() => { + useStore.setState({ hlsManageModal: null }) + withdraw({ + accountId: props.account.id, + coins: [{ coin: removedDeposit }], + borrow: [], + reclaims: [], + }) + }, [props.account.id, removedDeposit, withdraw]) + + return ( + <> + + + > + ) +} diff --git a/src/components/Modals/HLS/Manage/index.tsx b/src/components/Modals/HLS/Manage/index.tsx index 2a77dded..d7a5be43 100644 --- a/src/components/Modals/HLS/Manage/index.tsx +++ b/src/components/Modals/HLS/Manage/index.tsx @@ -1,40 +1,74 @@ -import React from 'react' +import React, { useCallback } from 'react' -import Modal from 'components/Modal' import Header from 'components/Modals/HLS/Header' +import ChangeLeverage from 'components/Modals/HLS/Manage/ChangeLeverage' +import Deposit from 'components/Modals/HLS/Manage/Deposit' +import Repay from 'components/Modals/HLS/Manage/Repay' +import Withdraw from 'components/Modals/HLS/Manage/Withdraw' +import ModalContentWithSummary from 'components/Modals/ModalContentWithSummary' +import useAccount from 'hooks/useAccount' import useStore from 'store' import { getAssetByDenom } from 'utils/assets' export default function HlsManageModalController() { const modal = useStore((s) => s.hlsManageModal) - + const { data: account } = useAccount(modal?.accountId) const collateralAsset = getAssetByDenom(modal?.staking.strategy.denoms.deposit || '') const borrowAsset = getAssetByDenom(modal?.staking.strategy.denoms.borrow || '') - if (!modal || !collateralAsset || !borrowAsset) return null + if (!modal || !collateralAsset || !borrowAsset || !account) return null - return + return ( + + ) } interface Props { + account: Account + action: HlsStakingManageAction borrowAsset: Asset collateralAsset: Asset } function HlsModal(props: Props) { + const updatedAccount = useStore((s) => s.updatedAccount) function handleClose() { useStore.setState({ hlsManageModal: null }) } + const ContentComponent = useCallback(() => { + switch (props.action) { + case 'deposit': + return + case 'withdraw': + return + case 'repay': + return + case 'leverage': + return + default: + return null + } + }, [props]) + return ( - } - headerClassName='gradient-header pl-2 pr-2.5 py-3 border-b-white/5 border-b' - contentClassName='flex flex-col p-6' - modalClassName='max-w-modal-md' + + } onClose={handleClose} - > - Some kind of text here - + content={} + isContentCard + /> ) } diff --git a/src/components/Modals/HLS/index.tsx b/src/components/Modals/HLS/index.tsx index 132bc9a8..d249f25c 100644 --- a/src/components/Modals/HLS/index.tsx +++ b/src/components/Modals/HLS/index.tsx @@ -1,7 +1,7 @@ import React from 'react' import Modal from 'components/Modal' -import Content from 'components/Modals/HLS/Content' +import Content from 'components/Modals/HLS/Deposit' import Header from 'components/Modals/HLS/Header' import useStore from 'store' import { getAssetByDenom } from 'utils/assets' diff --git a/src/components/Modals/ModalContentWithSummary.tsx b/src/components/Modals/ModalContentWithSummary.tsx new file mode 100644 index 00000000..39fc2ec4 --- /dev/null +++ b/src/components/Modals/ModalContentWithSummary.tsx @@ -0,0 +1,38 @@ +import classNames from 'classnames' +import React from 'react' + +import AccountSummary from 'components/Account/AccountSummary' +import Card from 'components/Card' +import Modal, { ModalProps } from 'components/Modal' +import useStore from 'store' + +interface Props extends ModalProps { + account: Account + isContentCard?: boolean +} + +export default function ModalContentWithSummary(props: Props) { + const updatedAccount = useStore((s) => s.updatedAccount) + return ( + + {props.isContentCard ? ( + + {props.content} + + ) : ( + props.content + )} + + + ) +} diff --git a/src/components/SummaryItems.tsx b/src/components/SummaryItems.tsx new file mode 100644 index 00000000..4689875c --- /dev/null +++ b/src/components/SummaryItems.tsx @@ -0,0 +1,25 @@ +import React from 'react' + +import { FormattedNumber } from 'components/FormattedNumber' +import Text from 'components/Text' + +interface Props { + items: SummaryItem[] +} + +export default function SummaryItems(props: Props) { + return ( + + {props.items.map((item) => ( + + {item.title} + + + ))} + + ) +} diff --git a/src/components/Tooltip/index.tsx b/src/components/Tooltip/index.tsx index f12c9867..f230bc42 100644 --- a/src/components/Tooltip/index.tsx +++ b/src/components/Tooltip/index.tsx @@ -1,4 +1,4 @@ -import Tippy from '@tippyjs/react' +import Tippy, { TippyProps } from '@tippyjs/react' import classNames from 'classnames' import { ReactNode } from 'react' @@ -8,10 +8,9 @@ import { DEFAULT_SETTINGS } from 'constants/defaultSettings' import { LocalStorageKeys } from 'constants/localStorageKeys' import useLocalStorage from 'hooks/useLocalStorage' -interface Props { +interface Props extends TippyProps { content: ReactNode | string type: TooltipType - children?: ReactNode | string className?: string delay?: number interactive?: boolean @@ -45,6 +44,7 @@ export const Tooltip = (props: Props) => { className={props.contentClassName} /> )} + {...props} > {props.children ? ( (LocalStorageKeys.SLIPPAGE, DEFAULT_SETTINGS.slippage) + const { data: prices } = usePrices() + + const collateralDenom = props.account.strategy.denoms.deposit + const borrowDenom = props.account.strategy.denoms.borrow + + const debtAmount: BigNumber = useMemo( + () => + props.account.debts.find((debt) => debt.denom === props.account.strategy.denoms.borrow) + ?.amount || BN_ZERO, + [props.account.debts, props.account.strategy.denoms.borrow], + ) + + const swapInAmount = useMemo(() => { + const targetValue = getCoinValue(BNCoin.fromDenomAndBigNumber(borrowDenom, debtAmount), prices) + return getCoinAmount(collateralDenom, targetValue, prices) + .times(1 + slippage) + .integerValue() + }, [slippage, borrowDenom, debtAmount, prices, collateralDenom]) + + return useMemo( + () => [ + ...(debtAmount.isZero() + ? [] + : [ + { + swap_exact_in: { + coin_in: BNCoin.fromDenomAndBigNumber(collateralDenom, swapInAmount).toActionCoin(), + denom_out: borrowDenom, + slippage: slippage.toString(), + }, + }, + { + repay: { + coin: BNCoin.fromDenomAndBigNumber(borrowDenom, debtAmount).toActionCoin(), + }, + }, + ]), + { refund_all_coin_balances: {} }, + ], + [borrowDenom, collateralDenom, debtAmount, slippage, swapInAmount], + ) +} diff --git a/src/hooks/HLS/useDepositActions.ts b/src/hooks/HLS/useDepositActions.ts new file mode 100644 index 00000000..40629b45 --- /dev/null +++ b/src/hooks/HLS/useDepositActions.ts @@ -0,0 +1,38 @@ +import { useMemo } from 'react' + +import { DEFAULT_SETTINGS } from 'constants/defaultSettings' +import { LocalStorageKeys } from 'constants/localStorageKeys' +import useLocalStorage from 'hooks/useLocalStorage' +import { BNCoin } from 'types/classes/BNCoin' + +interface Props { + borrowCoin: BNCoin + depositCoin: BNCoin +} + +export default function useDepositActions(props: Props) { + const [slippage] = useLocalStorage(LocalStorageKeys.SLIPPAGE, DEFAULT_SETTINGS.slippage) + + return useMemo( + () => [ + { + deposit: props.depositCoin.toCoin(), + }, + ...(props.borrowCoin.amount.isZero() + ? [] + : [ + { + borrow: props.borrowCoin.toCoin(), + }, + { + swap_exact_in: { + denom_out: props.depositCoin.denom, + slippage: slippage.toString(), + coin_in: props.borrowCoin.toActionCoin(), + }, + }, + ]), + ], + [props.borrowCoin, props.depositCoin, slippage], + ) +} diff --git a/src/hooks/useDepositHlsVault.ts b/src/hooks/useDepositHlsVault.ts index e1e81c0d..aa18d513 100644 --- a/src/hooks/useDepositHlsVault.ts +++ b/src/hooks/useDepositHlsVault.ts @@ -1,8 +1,12 @@ import { useMemo, useState } from 'react' +import { DEFAULT_SETTINGS } from 'constants/defaultSettings' +import { LocalStorageKeys } from 'constants/localStorageKeys' import { BN_ZERO } from 'constants/math' +import useLocalStorage from 'hooks/useLocalStorage' import usePrices from 'hooks/usePrices' import { BNCoin } from 'types/classes/BNCoin' +import { Action } from 'types/generated/mars-credit-manager/MarsCreditManager.types' import { getCoinValue } from 'utils/formatters' interface Props { @@ -11,10 +15,21 @@ interface Props { } export default function useDepositHlsVault(props: Props) { const { data: prices } = usePrices() + const [slippage] = useLocalStorage(LocalStorageKeys.SLIPPAGE, DEFAULT_SETTINGS.slippage) const [depositAmount, setDepositAmount] = useState(BN_ZERO) const [borrowAmount, setBorrowAmount] = useState(BN_ZERO) + const depositCoin = useMemo( + () => BNCoin.fromDenomAndBigNumber(props.collateralDenom, depositAmount), + [depositAmount, props.collateralDenom], + ) + + const borrowCoin = useMemo( + () => BNCoin.fromDenomAndBigNumber(props.borrowDenom, borrowAmount), + [borrowAmount, props.borrowDenom], + ) + const { positionValue, leverage } = useMemo(() => { const collateralValue = getCoinValue( BNCoin.fromDenomAndBigNumber(props.collateralDenom, depositAmount), @@ -31,6 +46,32 @@ export default function useDepositHlsVault(props: Props) { } }, [borrowAmount, depositAmount, prices, props.collateralDenom, props.borrowDenom]) + const actions: Action[] = useMemo( + () => [ + { + deposit: depositCoin.toCoin(), + }, + ...(borrowAmount.isZero() + ? [] + : [ + { + borrow: borrowCoin.toCoin(), + }, + { + swap_exact_in: { + denom_out: props.collateralDenom, + slippage: slippage.toString(), + coin_in: BNCoin.fromDenomAndBigNumber( + props.borrowDenom, + borrowAmount, + ).toActionCoin(), + }, + }, + ]), + ], + [borrowAmount, borrowCoin, depositCoin, props.borrowDenom, props.collateralDenom, slippage], + ) + return { setDepositAmount, depositAmount, @@ -38,5 +79,8 @@ export default function useDepositHlsVault(props: Props) { borrowAmount, positionValue, leverage, + depositCoin, + borrowCoin, + actions, } } diff --git a/src/hooks/useUpdatedAccount/index.ts b/src/hooks/useUpdatedAccount/index.ts index eb13bcf6..dcd5ebd4 100644 --- a/src/hooks/useUpdatedAccount/index.ts +++ b/src/hooks/useUpdatedAccount/index.ts @@ -16,6 +16,7 @@ import useStore from 'store' import { BNCoin } from 'types/classes/BNCoin' import { cloneAccount } from 'utils/accounts' import { byDenom } from 'utils/array' +import { getCoinAmount, getCoinValue } from 'utils/formatters' import { getValueFromBNCoins } from 'utils/helpers' export interface VaultValue { @@ -37,6 +38,7 @@ export function useUpdatedAccount(account?: Account) { const [addedVaultValues, addVaultValues] = useState([]) const [addedLends, addLends] = useState([]) const [removedLends, removeLends] = useState([]) + const [addedTrades, addTrades] = useState([]) const removeDepositAndLendsByDenom = useCallback( (denom: string) => { @@ -151,6 +153,18 @@ export function useUpdatedAccount(account?: Account) { [account, addDebts, addDeposits, addLends, removeDeposits, removeLends], ) + const simulateHlsStakingDeposit = useCallback( + (depositCoin: BNCoin, borrowCoin: BNCoin) => { + addDeposits([depositCoin]) + addDebts([borrowCoin]) + const additionalDebtValue = getCoinValue(borrowCoin, prices) + + const tradeOutputAmount = getCoinAmount(depositCoin.denom, additionalDebtValue, prices) + addTrades([BNCoin.fromDenomAndBigNumber(depositCoin.denom, tradeOutputAmount)]) + }, + [prices], + ) + const simulateVaultDeposit = useCallback( (address: string, coins: BNCoin[], borrowCoins: BNCoin[]) => { if (!account) return @@ -179,7 +193,7 @@ export function useUpdatedAccount(account?: Account) { if (!account) return const accountCopy = cloneAccount(account) - accountCopy.deposits = addCoins(addedDeposits, [...accountCopy.deposits]) + accountCopy.deposits = addCoins([...addedDeposits, ...addedTrades], [...accountCopy.deposits]) accountCopy.debts = addCoins(addedDebts, [...accountCopy.debts]) accountCopy.vaults = addValueToVaults( addedVaultValues, @@ -205,6 +219,7 @@ export function useUpdatedAccount(account?: Account) { removedLends, availableVaults, prices, + addedTrades, ]) return { @@ -225,6 +240,7 @@ export function useUpdatedAccount(account?: Account) { removedLends, simulateBorrow, simulateDeposits, + simulateHlsStakingDeposit, simulateLending, simulateRepay, simulateTrade, diff --git a/src/store/slices/broadcast.ts b/src/store/slices/broadcast.ts index 8b08faaa..28ceb415 100644 --- a/src/store/slices/broadcast.ts +++ b/src/store/slices/broadcast.ts @@ -232,6 +232,32 @@ export default function createBroadcastSlice( return response.then((response) => !!response.result) }, + closeHlsStakingPosition: async (options: { accountId: string; actions: Action[] }) => { + const msg: CreditManagerExecuteMsg = { + update_credit_account: { + account_id: options.accountId, + actions: options.actions, + }, + } + + const response = get().executeMsg({ + messages: [generateExecutionMessage(get().address, ENV.ADDRESS_CREDIT_MANAGER, msg, [])], + }) + + get().setToast({ + response, + options: { + action: 'deposit', + message: `Exited HLS strategy`, + }, + }) + + const response_1 = await response + return response_1.result + ? getSingleValueFromBroadcastResult(response_1.result, 'wasm', 'token_id') + : null + }, + createAccount: async (accountKind: AccountKind) => { const msg: CreditManagerExecuteMsg = { create_credit_account: accountKind, @@ -538,8 +564,10 @@ export default function createBroadcastSlice( coin: BNCoin accountBalance?: boolean lend?: BNCoin + fromWallet?: boolean }) => { const actions: Action[] = [ + ...(options.fromWallet ? [{ deposit: options.coin.toCoin() }] : []), { repay: { coin: options.coin.toActionCoin(options.accountBalance), @@ -558,7 +586,14 @@ export default function createBroadcastSlice( } const response = get().executeMsg({ - messages: [generateExecutionMessage(get().address, ENV.ADDRESS_CREDIT_MANAGER, msg, [])], + messages: [ + generateExecutionMessage( + get().address, + ENV.ADDRESS_CREDIT_MANAGER, + msg, + options.fromWallet ? [options.coin.toCoin()] : [], + ), + ], }) get().setToast({ diff --git a/src/types/interfaces/components/SummaryItems.d.ts b/src/types/interfaces/components/SummaryItems.d.ts new file mode 100644 index 00000000..fcb2837d --- /dev/null +++ b/src/types/interfaces/components/SummaryItems.d.ts @@ -0,0 +1,5 @@ +interface SummaryItem { + amount: number + options: FormatOptions + title: string +} diff --git a/src/types/interfaces/store/broadcast.d.ts b/src/types/interfaces/store/broadcast.d.ts index d5bb2470..fe8a29b8 100644 --- a/src/types/interfaces/store/broadcast.d.ts +++ b/src/types/interfaces/store/broadcast.d.ts @@ -92,6 +92,10 @@ interface BroadcastSlice { borrowToWallet: boolean }) => Promise claimRewards: (options: { accountId: string }) => ExecutableTx + closeHlsStakingPosition: (options: { + accountId: string + actions: Action[] + }) => Promise createAccount: ( accountKind: import('types/generated/mars-rover-health-types/MarsRoverHealthTypes.types').AccountKind, ) => Promise @@ -113,6 +117,7 @@ interface BroadcastSlice { coin: BNCoin accountBalance?: boolean lend?: BNCoin + fromWallet?: boolean }) => Promise setToast: (toast: ToastObject) => void swap: (options: { diff --git a/src/types/interfaces/store/modals.d.ts b/src/types/interfaces/store/modals.d.ts index 99da422f..ceef9fa6 100644 --- a/src/types/interfaces/store/modals.d.ts +++ b/src/types/interfaces/store/modals.d.ts @@ -76,8 +76,11 @@ interface HlsModal { } interface HlsManageModal { + accountId: string staking: { strategy: HLSStrategy - action: 'deposit' | 'withdraw' | 'repay' + action: HlsStakingManageAction } } + +type HlsStakingManageAction = 'deposit' | 'withdraw' | 'repay' | 'leverage'