From 0325e311cbed1a4bce46355112730ad46f461b1d Mon Sep 17 00:00:00 2001 From: Bob van der Helm <34470358+bobthebuidlr@users.noreply.github.com> Date: Thu, 2 Nov 2023 10:40:34 +0100 Subject: [PATCH] Mp 3360 create vault position (#607) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * 🔧 Small fixes * ✨ Deposit into HLS Vault + Groudnwork for HLS Staking * Adjusted according to feedback * Adjusted according to feedback --- .../HLS/Farm/AvailableHLSVaults.tsx | 34 ++-- .../HLS/Farm/Table/Columns/Deposit.tsx | 20 ++- .../HLS/Farm/Table/Columns/Name.tsx | 2 + .../HLS/Staking/AvailableHLSStakingAssets.tsx | 46 ++++- .../HLS/Staking/Table/Columns/MaxLTV.tsx | 23 +++ .../HLS/Staking/Table/Columns/MaxLeverage.tsx | 20 +++ .../HLS/Staking/Table/Columns/Name.tsx | 32 ++++ .../Table/Columns/useAvailableColumns.tsx | 39 ++++ src/components/Modals/HLS/Content.tsx | 142 --------------- src/components/Modals/HLS/Content/index.tsx | 168 ++++++++++++++++++ .../Modals/HLS/Content/useAccordionItems.tsx | 127 +++++++++++++ .../HLS/Content/useStakingController.tsx | 59 ++++++ .../Modals/HLS/Content/useVaultController.tsx | 128 +++++++++++++ src/components/Modals/HLS/Header.tsx | 4 +- src/components/Modals/HLS/Leverage.tsx | 1 + src/components/Modals/HLS/LeverageSummary.tsx | 10 +- src/components/Modals/HLS/SubTitles.tsx | 4 +- .../Modals/HLS/Summary/ApyBreakdown.tsx | 2 +- src/components/Modals/HLS/Summary/index.tsx | 17 +- src/components/Modals/HLS/index.tsx | 40 +++-- .../Modals/Vault/VaultBorrowings.tsx | 1 + .../Modals/Vault/VaultModalContent.tsx | 1 + src/constants/accounts.ts | 13 ++ src/constants/vaults.ts | 1 + src/hooks/broadcast/useDepositVault.ts | 37 +++- src/hooks/useDepositHlsVault.ts | 28 +-- src/hooks/useHealthComputer.tsx | 6 +- src/hooks/useVault.tsx | 9 + src/store/slices/broadcast.ts | 10 +- src/types/interfaces/store/broadcast.d.ts | 1 + src/types/interfaces/store/modals.d.ts | 3 +- src/types/interfaces/vaults.d.ts | 1 + src/utils/accounts.ts | 9 + 33 files changed, 821 insertions(+), 217 deletions(-) create mode 100644 src/components/HLS/Staking/Table/Columns/MaxLTV.tsx create mode 100644 src/components/HLS/Staking/Table/Columns/MaxLeverage.tsx create mode 100644 src/components/HLS/Staking/Table/Columns/Name.tsx create mode 100644 src/components/HLS/Staking/Table/Columns/useAvailableColumns.tsx delete mode 100644 src/components/Modals/HLS/Content.tsx create mode 100644 src/components/Modals/HLS/Content/index.tsx create mode 100644 src/components/Modals/HLS/Content/useAccordionItems.tsx create mode 100644 src/components/Modals/HLS/Content/useStakingController.tsx create mode 100644 src/components/Modals/HLS/Content/useVaultController.tsx create mode 100644 src/constants/accounts.ts create mode 100644 src/hooks/useVault.tsx diff --git a/src/components/HLS/Farm/AvailableHLSVaults.tsx b/src/components/HLS/Farm/AvailableHLSVaults.tsx index 59800e8b..6a4be563 100644 --- a/src/components/HLS/Farm/AvailableHLSVaults.tsx +++ b/src/components/HLS/Farm/AvailableHLSVaults.tsx @@ -1,7 +1,7 @@ import { Suspense, useMemo } from 'react' -import { NAME_META } from 'components/Earn/Farm/Table/Columns/Name' -import useAvailableColumns from 'components/Earn/Farm/Table/Columns/useAvailableColumns' +import { NAME_META } from 'components/HLS/Farm/Table/Columns/Name' +import useAvailableColumns from 'components/HLS/Farm/Table/Columns/useAvailableColumns' import Table from 'components/Table' import { ENV } from 'constants/env' import { BN_ZERO } from 'constants/math' @@ -38,20 +38,22 @@ function Fallback() { const columns = useAvailableColumns({ isLoading: true }) const vaults = ENV.NETWORK === NETWORK.TESTNET ? TESTNET_VAULTS_META_DATA : VAULTS_META_DATA - const mockVaults: Vault[] = vaults.map((vault) => ({ - ...vault, - apy: null, - apr: null, - ltv: { - max: 0, - liq: 0, - }, - cap: { - denom: 'denom', - used: BN_ZERO, - max: BN_ZERO, - }, - })) + const mockVaults: Vault[] = vaults + .filter((v) => v.isHls) + .map((vault) => ({ + ...vault, + apy: null, + apr: null, + ltv: { + max: 0, + liq: 0, + }, + cap: { + denom: 'denom', + used: BN_ZERO, + max: BN_ZERO, + }, + })) return ( ( LocalStorageKeys.HLS_INFORMATION, @@ -27,7 +28,12 @@ export default function Deposit(props: Props) { const { open: openAlertDialog, close } = useAlertDialog() - const enterVaultHandler = useCallback(() => { + const openHlsModal = useCallback( + () => useStore.setState({ hlsModal: { strategy, vault } }), + [strategy, vault], + ) + + const handleOnClick = useCallback(() => { if (!showHlsInfo) { openHlsModal() return @@ -72,17 +78,13 @@ export default function Deposit(props: Props) { onClick: (isChecked: boolean) => setShowHlsInfo(!isChecked), }, }) - }, [close, openAlertDialog, setShowHlsInfo, showHlsInfo]) - - function openHlsModal() { - useStore.setState({ hlsModal: { vault } }) - } + }, [close, openAlertDialog, openHlsModal, setShowHlsInfo, showHlsInfo]) if (props.isLoading) return return (
- +
) } diff --git a/src/components/HLS/Farm/Table/Columns/Name.tsx b/src/components/HLS/Farm/Table/Columns/Name.tsx index 45aec3b4..36c6d658 100644 --- a/src/components/HLS/Farm/Table/Columns/Name.tsx +++ b/src/components/HLS/Farm/Table/Columns/Name.tsx @@ -2,6 +2,8 @@ import React from 'react' import TitleAndSubCell from 'components/TitleAndSubCell' +export const NAME_META = { id: 'name', accessorKey: 'denoms.primary', header: 'Name' } + interface Props { strategy: HLSStrategy } diff --git a/src/components/HLS/Staking/AvailableHLSStakingAssets.tsx b/src/components/HLS/Staking/AvailableHLSStakingAssets.tsx index f230a3fa..ba42a01c 100644 --- a/src/components/HLS/Staking/AvailableHLSStakingAssets.tsx +++ b/src/components/HLS/Staking/AvailableHLSStakingAssets.tsx @@ -1,3 +1,45 @@ -export default function AvailableHlsStakingAssets() { - return null +import { Suspense } from 'react' + +import { NAME_META } from 'components/HLS/Farm/Table/Columns/Name' +import useAvailableColumns from 'components/HLS/Staking/Table/Columns/useAvailableColumns' +import Table from 'components/Table' +import useHLSStakingAssets from 'hooks/useHLSStakingAssets' +import { getEnabledMarketAssets } from 'utils/assets' + +const title = 'Available HLS Staking' + +function Content() { + const assets = getEnabledMarketAssets() + const { data: hlsStrategies } = useHLSStakingAssets() + const columns = useAvailableColumns({ isLoading: false }) + + return ( +
+ ) +} + +export default function AvailableHlsVaults() { + return ( + }> + + + ) +} + +function Fallback() { + const columns = useAvailableColumns({ isLoading: true }) + + return ( +
+ ) } diff --git a/src/components/HLS/Staking/Table/Columns/MaxLTV.tsx b/src/components/HLS/Staking/Table/Columns/MaxLTV.tsx new file mode 100644 index 00000000..101f0a46 --- /dev/null +++ b/src/components/HLS/Staking/Table/Columns/MaxLTV.tsx @@ -0,0 +1,23 @@ +import React from 'react' + +import { FormattedNumber } from 'components/FormattedNumber' +import Loading from 'components/Loading' + +export const LTV_MAX_META = { accessorKey: 'maxLTV', header: 'Max LTV' } + +interface Props { + strategy: HLSStrategy + isLoading: boolean +} +export default function MaxLtv(props: Props) { + const { strategy } = props + if (props.isLoading) return + return ( + + ) +} diff --git a/src/components/HLS/Staking/Table/Columns/MaxLeverage.tsx b/src/components/HLS/Staking/Table/Columns/MaxLeverage.tsx new file mode 100644 index 00000000..52e04ec2 --- /dev/null +++ b/src/components/HLS/Staking/Table/Columns/MaxLeverage.tsx @@ -0,0 +1,20 @@ +import React from 'react' + +import { FormattedNumber } from 'components/FormattedNumber' + +export const MAX_LEV_META = { accessorKey: 'maxLeverage', header: 'Max Leverage' } + +interface Props { + strategy: HLSStrategy +} + +export default function MaxLeverage(props: Props) { + return ( + + ) +} diff --git a/src/components/HLS/Staking/Table/Columns/Name.tsx b/src/components/HLS/Staking/Table/Columns/Name.tsx new file mode 100644 index 00000000..ed81d0c8 --- /dev/null +++ b/src/components/HLS/Staking/Table/Columns/Name.tsx @@ -0,0 +1,32 @@ +import React from 'react' + +import DoubleLogo from 'components/DoubleLogo' +import Loading from 'components/Loading' +import TitleAndSubCell from 'components/TitleAndSubCell' +import { getAssetByDenom } from 'utils/assets' + +export const NAME_META = { id: 'name', header: 'Vault', accessorKey: 'denoms.deposit' } +interface Props { + strategy: HLSStrategy +} + +export default function Name(props: Props) { + const { strategy } = props + const depositAsset = getAssetByDenom(props.strategy.denoms.deposit) + const borrowAsset = getAssetByDenom(props.strategy.denoms.borrow) + + return ( +
+ + {depositAsset && borrowAsset ? ( + + ) : ( + + )} +
+ ) +} diff --git a/src/components/HLS/Staking/Table/Columns/useAvailableColumns.tsx b/src/components/HLS/Staking/Table/Columns/useAvailableColumns.tsx new file mode 100644 index 00000000..92bec800 --- /dev/null +++ b/src/components/HLS/Staking/Table/Columns/useAvailableColumns.tsx @@ -0,0 +1,39 @@ +import { ColumnDef } from '@tanstack/react-table' +import React, { useMemo } from 'react' + +import Deposit, { DEPOSIT_META } from 'components/HLS/Farm/Table/Columns/Deposit' +import MaxLeverage, { MAX_LEV_META } from 'components/HLS/Staking/Table/Columns/MaxLeverage' +import MaxLTV, { LTV_MAX_META } from 'components/HLS/Staking/Table/Columns/MaxLTV' +import Name, { NAME_META } from 'components/HLS/Staking/Table/Columns/Name' + +interface Props { + isLoading: boolean +} + +export default function useAvailableColumns(props: Props) { + return useMemo[]>( + () => [ + { + ...NAME_META, + cell: ({ row }) => , + }, + { + ...MAX_LEV_META, + cell: ({ row }) => , + }, + { + ...LTV_MAX_META, + cell: ({ row }) => ( + + ), + }, + { + ...DEPOSIT_META, + cell: ({ row }) => ( + + ), + }, + ], + [props.isLoading], + ) +} diff --git a/src/components/Modals/HLS/Content.tsx b/src/components/Modals/HLS/Content.tsx deleted file mode 100644 index 4ff400d6..00000000 --- a/src/components/Modals/HLS/Content.tsx +++ /dev/null @@ -1,142 +0,0 @@ -import React, { useMemo, useState } from 'react' - -import Accordion from 'components/Accordion' -import { Item } from 'components/AccordionContent' -import CreateAccount from 'components/Modals/HLS/CreateAccount' -import Leverage from 'components/Modals/HLS/Leverage' -import ProvideCollateral from 'components/Modals/HLS/ProvideCollateral' -import SelectAccount from 'components/Modals/HLS/SelectAccount' -import { CollateralSubTitle, LeverageSubTitle, SubTitle } from 'components/Modals/HLS/SubTitles' -import Summary from 'components/Modals/HLS/Summary' -import { BN_ZERO } from 'constants/math' -import useAccounts from 'hooks/useAccounts' -import useCurrentWalletBalance from 'hooks/useCurrentWalletBalance' -import useDepositHlsVault from 'hooks/useDepositHlsVault' -import useIsOpenArray from 'hooks/useIsOpenArray' -import useStore from 'store' -import { getAssetByDenom } from 'utils/assets' -import { BN } from 'utils/helpers' - -interface Props { - vault: Vault -} - -export default function Content(props: Props) { - const [selectedAccount, setSelectedAccount] = useState(null) - const [isOpen, toggleIsOpen] = useIsOpenArray(4, false) - const address = useStore((s) => s.address) - const { data: hlsAccounts } = useAccounts('high_levered_strategy', address) - const collateralAsset = getAssetByDenom(props.vault.denoms.primary) - const borrowAsset = getAssetByDenom(props.vault.denoms.secondary) - const walletCollateralAsset = useCurrentWalletBalance(props.vault.denoms.primary) - const { setDepositAmount, depositAmount, setBorrowAmount, borrowAmount, positionValue } = - useDepositHlsVault({ - vault: props.vault, - }) - - const items: Item[] = useMemo(() => { - if (!collateralAsset || !borrowAsset) return [] - return [ - { - title: 'Provide Collateral', - renderContent: () => ( - toggleIsOpen(1)} - max={BN(walletCollateralAsset?.amount || 0)} - /> - ), - renderSubTitle: () => ( - - ), - isOpen: isOpen[0], - - toggleOpen: toggleIsOpen, - }, - { - title: 'Leverage', - renderContent: () => ( - toggleIsOpen(2)} - /> - ), - renderSubTitle: () => ( - // TODO: Add leverage - - ), - isOpen: isOpen[1], - toggleOpen: toggleIsOpen, - }, - ...[ - hlsAccounts.length > 2 - ? { - title: 'Select HLS Account', - renderContent: () => ( - toggleIsOpen(3)} - /> - ), - renderSubTitle: () => - selectedAccount && !isOpen[2] ? ( - - ) : null, - isOpen: isOpen[2], - toggleOpen: toggleIsOpen, - } - : { - title: 'Create HLS Account', - renderContent: () => , - renderSubTitle: () => null, - isOpen: isOpen[2], - toggleOpen: toggleIsOpen, - }, - ], - { - title: 'Summary', - renderContent: () => ( - { - // TODO: Implement tx execution - }} - /> - ), - renderSubTitle: () => null, - isOpen: isOpen[3], - toggleOpen: toggleIsOpen, - }, - ] - }, [ - collateralAsset, - borrowAsset, - isOpen, - toggleIsOpen, - hlsAccounts, - depositAmount, - setDepositAmount, - walletCollateralAsset?.amount, - selectedAccount, - borrowAmount, - positionValue, - props.vault, - ]) - - return -} diff --git a/src/components/Modals/HLS/Content/index.tsx b/src/components/Modals/HLS/Content/index.tsx new file mode 100644 index 00000000..bd960bfa --- /dev/null +++ b/src/components/Modals/HLS/Content/index.tsx @@ -0,0 +1,168 @@ +import React, { useMemo, useState } from 'react' + +import Accordion from 'components/Accordion' +import useStakingController from 'components/Modals/HLS/Content//useStakingController' +import useVaultController from 'components/Modals/HLS/Content//useVaultController' +import useAccordionItems from 'components/Modals/HLS/Content/useAccordionItems' +import { EMPTY_ACCOUNT_HLS } from 'constants/accounts' +import useAccounts from 'hooks/useAccounts' +import useCurrentWalletBalance from 'hooks/useCurrentWalletBalance' +import useIsOpenArray from 'hooks/useIsOpenArray' +import useVault from 'hooks/useVault' +import useStore from 'store' +import { isAccountEmpty } from 'utils/accounts' +import { getAssetByDenom } from 'utils/assets' + +interface Props { + borrowDenom: string + collateralDenom: string + vaultAddress: string | null +} + +export default function Controller(props: Props) { + const collateralAsset = getAssetByDenom(props.collateralDenom) + const borrowAsset = getAssetByDenom(props.borrowDenom) + const [selectedAccount, setSelectedAccount] = useState(EMPTY_ACCOUNT_HLS) + const [isOpen, toggleIsOpen] = useIsOpenArray(4, false) + const address = useStore((s) => s.address) + const { data: hlsAccounts } = useAccounts('high_levered_strategy', address) + const emptyHlsAccounts = useMemo( + () => hlsAccounts.filter((account) => isAccountEmpty(account)), + [hlsAccounts], + ) + const walletCollateralAsset = useCurrentWalletBalance(props.collateralDenom) + const vault = useVault(props.vaultAddress || '') + + if (!collateralAsset || !borrowAsset) return null + + if (vault) + return ( + + ) + + return ( + + ) +} + +interface ContentProps { + borrowAsset: Asset + collateralAsset: Asset + emptyHlsAccounts: Account[] + hlsAccounts: Account[] + isOpen: boolean[] + selectedAccount: Account + setSelectedAccount: (account: Account) => void + toggleIsOpen: (index: number) => void + walletCollateralAsset: Coin | undefined +} + +interface VaultContentProps extends ContentProps { + vault: Vault +} + +function Vault(props: VaultContentProps) { + const { + borrowAmount, + depositAmount, + execute, + leverage, + maxBorrowAmount, + onChangeCollateral, + onChangeDebt, + positionValue, + updatedAccount, + } = useVaultController({ + vault: props.vault, + collateralAsset: props.collateralAsset, + borrowAsset: props.borrowAsset, + selectedAccount: props.selectedAccount, + }) + + const items = useAccordionItems({ + apy: props.vault.apy || 0, + borrowAmount, + borrowAsset: props.borrowAsset, + collateralAsset: props.collateralAsset, + depositAmount, + emptyHlsAccounts: props.emptyHlsAccounts, + execute, + hlsAccounts: props.hlsAccounts, + isOpen: props.isOpen, + leverage, + maxBorrowAmount, + onChangeCollateral, + onChangeDebt, + positionValue, + selectedAccount: props.selectedAccount, + setSelectedAccount: props.setSelectedAccount, + toggleIsOpen: props.toggleIsOpen, + updatedAccount, + walletCollateralAsset: props.walletCollateralAsset, + }) + + return +} + +function StakingContent(props: ContentProps) { + const { + depositAmount, + onChangeCollateral, + updatedAccount, + borrowAmount, + onChangeDebt, + leverage, + maxBorrowAmount, + positionValue, + execute, + } = useStakingController({ + collateralAsset: props.collateralAsset, + borrowAsset: props.borrowAsset, + selectedAccount: props.selectedAccount, + }) + + const items = useAccordionItems({ + borrowAmount, + borrowAsset: props.borrowAsset, + collateralAsset: props.collateralAsset, + depositAmount, + emptyHlsAccounts: props.emptyHlsAccounts, + execute, + hlsAccounts: props.hlsAccounts, + isOpen: props.isOpen, + leverage, + onChangeCollateral, + onChangeDebt, + positionValue, + selectedAccount: props.selectedAccount, + setSelectedAccount: props.setSelectedAccount, + toggleIsOpen: props.toggleIsOpen, + updatedAccount, + maxBorrowAmount, + apy: 0, // TODO: Implement APY + walletCollateralAsset: props.walletCollateralAsset, + }) + + return +} diff --git a/src/components/Modals/HLS/Content/useAccordionItems.tsx b/src/components/Modals/HLS/Content/useAccordionItems.tsx new file mode 100644 index 00000000..f3547a12 --- /dev/null +++ b/src/components/Modals/HLS/Content/useAccordionItems.tsx @@ -0,0 +1,127 @@ +import React, { useMemo } from 'react' + +import CreateAccount from 'components/Modals/HLS/CreateAccount' +import Leverage from 'components/Modals/HLS/Leverage' +import ProvideCollateral from 'components/Modals/HLS/ProvideCollateral' +import SelectAccount from 'components/Modals/HLS/SelectAccount' +import { CollateralSubTitle, LeverageSubTitle, SubTitle } from 'components/Modals/HLS/SubTitles' +import Summary from 'components/Modals/HLS/Summary' +import { BN } from 'utils/helpers' + +interface Props { + apy: number + borrowAmount: BigNumber + borrowAsset: Asset + collateralAsset: Asset + depositAmount: BigNumber + emptyHlsAccounts: Account[] + execute: () => void + hlsAccounts: Account[] + isOpen: boolean[] + leverage: number + maxBorrowAmount: BigNumber + onChangeCollateral: (amount: BigNumber) => void + onChangeDebt: (amount: BigNumber) => void + positionValue: BigNumber + selectedAccount: Account | null + setSelectedAccount: (account: Account) => void + toggleIsOpen: (index: number) => void + updatedAccount: Account | undefined + walletCollateralAsset: Coin | undefined +} + +export default function useAccordionItems(props: Props) { + return useMemo(() => { + return [ + { + title: 'Provide Collateral', + renderContent: () => ( + props.toggleIsOpen(1)} + // TODO: Add check for deposit cap + max={BN(props.walletCollateralAsset?.amount || 0)} + /> + ), + renderSubTitle: () => ( + + ), + isOpen: props.isOpen[0], + + toggleOpen: props.toggleIsOpen, + }, + { + title: 'Leverage', + renderContent: () => ( + props.toggleIsOpen(2)} + max={props.maxBorrowAmount} + /> + ), + renderSubTitle: () => ( + + ), + isOpen: props.isOpen[1], + toggleOpen: props.toggleIsOpen, + }, + ...[ + props.hlsAccounts.length > 2 + ? { + title: 'Select HLS Account', + renderContent: () => ( + props.toggleIsOpen(3)} + /> + ), + renderSubTitle: () => + props.selectedAccount && !props.isOpen[2] ? ( + + ) : null, + isOpen: props.isOpen[2], + toggleOpen: props.toggleIsOpen, + } + : { + title: 'Create HLS Account', + renderContent: () => , + renderSubTitle: () => null, + isOpen: props.isOpen[2], + toggleOpen: props.toggleIsOpen, + }, + ], + { + title: 'Summary', + renderContent: () => ( + + ), + renderSubTitle: () => null, + isOpen: props.isOpen[3], + toggleOpen: props.toggleIsOpen, + }, + ] + }, [props]) +} diff --git a/src/components/Modals/HLS/Content/useStakingController.tsx b/src/components/Modals/HLS/Content/useStakingController.tsx new file mode 100644 index 00000000..e545ed09 --- /dev/null +++ b/src/components/Modals/HLS/Content/useStakingController.tsx @@ -0,0 +1,59 @@ +import { useCallback } from 'react' + +import useDepositHlsVault from 'hooks/useDepositHlsVault' +import { useUpdatedAccount } from 'hooks/useUpdatedAccount' +import { BN } from 'utils/helpers' + +interface Props { + borrowAsset: Asset + collateralAsset: Asset + selectedAccount: Account +} + +export default function useVaultController(props: Props) { + const { collateralAsset, borrowAsset, selectedAccount } = props + + const { + leverage, + setDepositAmount, + depositAmount, + setBorrowAmount, + borrowAmount, + positionValue, + } = useDepositHlsVault({ + collateralDenom: collateralAsset.denom, + borrowDenom: borrowAsset.denom, + }) + + const actions = [] + + const { updatedAccount, simulateVaultDeposit } = useUpdatedAccount(selectedAccount) + + const execute = () => null + + const onChangeCollateral = useCallback( + (amount: BigNumber) => { + setDepositAmount(amount) + }, + [setDepositAmount], + ) + + const onChangeDebt = useCallback( + (amount: BigNumber) => { + setBorrowAmount(amount) + }, + [setBorrowAmount], + ) + + return { + borrowAmount, + depositAmount, + execute, + leverage, + maxBorrowAmount: BN(0), + onChangeCollateral, + onChangeDebt, + positionValue, + updatedAccount, + } +} diff --git a/src/components/Modals/HLS/Content/useVaultController.tsx b/src/components/Modals/HLS/Content/useVaultController.tsx new file mode 100644 index 00000000..24867de9 --- /dev/null +++ b/src/components/Modals/HLS/Content/useVaultController.tsx @@ -0,0 +1,128 @@ +import { useCallback, useMemo } from 'react' + +import useDepositVault from 'hooks/broadcast/useDepositVault' +import useDepositHlsVault from 'hooks/useDepositHlsVault' +import useHealthComputer from 'hooks/useHealthComputer' +import { useUpdatedAccount } from 'hooks/useUpdatedAccount' +import useStore from 'store' +import { BNCoin } from 'types/classes/BNCoin' + +interface Props { + borrowAsset: Asset + collateralAsset: Asset + selectedAccount: Account + vault: Vault +} + +export default function useVaultController(props: Props) { + const { vault, collateralAsset, borrowAsset, selectedAccount } = props + + const depositIntoVault = useStore((s) => s.depositIntoVault) + + const { + leverage, + setDepositAmount, + depositAmount, + setBorrowAmount, + borrowAmount, + positionValue, + } = useDepositHlsVault({ + collateralDenom: collateralAsset.denom, + borrowDenom: borrowAsset.denom, + }) + + const { actions } = useDepositVault({ + vault, + reclaims: [], + deposits: [BNCoin.fromDenomAndBigNumber(collateralAsset.denom, depositAmount)], + borrowings: [BNCoin.fromDenomAndBigNumber(borrowAsset.denom, borrowAmount)], + kind: 'high_levered_strategy', + }) + + const { updatedAccount, simulateVaultDeposit } = useUpdatedAccount(selectedAccount) + const { computeMaxBorrowAmount } = useHealthComputer(updatedAccount) + + const maxBorrowAmount = useMemo( + // TODO: Check that the amount is actually the HLS amount + // TODO: Add check for market liquidity + // TODO: Add check for deposit cap + () => { + return computeMaxBorrowAmount(props.borrowAsset.denom, { + vault: { address: props.vault?.address }, + }).plus(borrowAmount) + }, + [borrowAmount, computeMaxBorrowAmount, props.borrowAsset.denom, props.vault?.address], + ) + + const execute = useCallback(() => { + depositIntoVault({ + accountId: selectedAccount.id, + actions, + deposits: [BNCoin.fromDenomAndBigNumber(collateralAsset.denom, depositAmount)], + borrowings: [BNCoin.fromDenomAndBigNumber(borrowAsset.denom, borrowAmount)], + isCreate: true, + kind: 'high_levered_strategy', + }) + useStore.setState({ hlsModal: null }) + }, [ + actions, + borrowAmount, + depositAmount, + depositIntoVault, + borrowAsset.denom, + collateralAsset.denom, + selectedAccount.id, + ]) + + const onChangeCollateral = useCallback( + (amount: BigNumber) => { + setDepositAmount(amount) + + simulateVaultDeposit( + vault.address, + [BNCoin.fromDenomAndBigNumber(collateralAsset.denom, amount)], + [BNCoin.fromDenomAndBigNumber(borrowAsset.denom, borrowAmount)], + ) + }, + [ + borrowAmount, + borrowAsset, + collateralAsset, + vault.address, + setDepositAmount, + simulateVaultDeposit, + ], + ) + + const onChangeDebt = useCallback( + (amount: BigNumber) => { + setBorrowAmount(amount) + + simulateVaultDeposit( + vault.address, + [BNCoin.fromDenomAndBigNumber(collateralAsset.denom, depositAmount)], + [BNCoin.fromDenomAndBigNumber(borrowAsset.denom, amount)], + ) + }, + [ + borrowAsset, + collateralAsset, + depositAmount, + vault.address, + setBorrowAmount, + simulateVaultDeposit, + ], + ) + + return { + borrowAmount, + depositAmount, + execute, + leverage, + maxBorrowAmount, + onChangeCollateral, + onChangeDebt, + positionValue, + updatedAccount, + } +} diff --git a/src/components/Modals/HLS/Header.tsx b/src/components/Modals/HLS/Header.tsx index 78f87c36..1e395f90 100644 --- a/src/components/Modals/HLS/Header.tsx +++ b/src/components/Modals/HLS/Header.tsx @@ -16,12 +16,12 @@ export default function Header(props: Props) { if (!primaryAsset || !secondaryAsset) return null return ( - +
{`${primaryAsset.symbol} - ${secondaryAsset.symbol}`} HLS - +
) } diff --git a/src/components/Modals/HLS/Leverage.tsx b/src/components/Modals/HLS/Leverage.tsx index 92e87063..3e133b88 100644 --- a/src/components/Modals/HLS/Leverage.tsx +++ b/src/components/Modals/HLS/Leverage.tsx @@ -21,6 +21,7 @@ export default function Leverage(props: Props) { asset={props.asset} max={props.max} onChange={props.onChangeAmount} + maxText='Max borrow' />