feat: finished deposit and withdraw
This commit is contained in:
parent
f609540809
commit
37be3240eb
@ -10,12 +10,12 @@ import Text from 'components/common/Text'
|
||||
import TokenInputWithSlider from 'components/common/TokenInput/TokenInputWithSlider'
|
||||
import AssetImage from 'components/common/assets/AssetImage'
|
||||
import { BN_ZERO } from 'constants/math'
|
||||
import useCurrentAccount from 'hooks/accounts/useCurrentAccount'
|
||||
import { BNCoin } from 'types/classes/BNCoin'
|
||||
import { byDenom } from 'utils/array'
|
||||
import { BN } from 'utils/helpers'
|
||||
|
||||
interface Props {
|
||||
account: Account
|
||||
asset: Asset
|
||||
title: string
|
||||
coinBalances: BNCoin[]
|
||||
@ -29,6 +29,7 @@ interface Props {
|
||||
|
||||
export default function AssetAmountSelectActionModal(props: Props) {
|
||||
const {
|
||||
account,
|
||||
asset,
|
||||
title,
|
||||
coinBalances,
|
||||
@ -41,7 +42,6 @@ export default function AssetAmountSelectActionModal(props: Props) {
|
||||
} = props
|
||||
const [amount, setAmount] = useState(BN_ZERO)
|
||||
const maxAmount = BN(coinBalances.find(byDenom(asset.denom))?.amount ?? 0)
|
||||
const account = useCurrentAccount()
|
||||
const handleAmountChange = useCallback(
|
||||
(value: BigNumber) => {
|
||||
setAmount(value)
|
||||
@ -54,7 +54,6 @@ export default function AssetAmountSelectActionModal(props: Props) {
|
||||
onAction(amount, amount.isEqualTo(maxAmount))
|
||||
}, [amount, maxAmount, onAction])
|
||||
|
||||
if (!account) return
|
||||
return (
|
||||
<Modal
|
||||
onClose={onClose}
|
||||
|
@ -23,6 +23,7 @@ interface Props {
|
||||
}
|
||||
|
||||
function LendAndReclaimModal({ currentAccount, config }: Props) {
|
||||
const account = useCurrentAccount()
|
||||
const lend = useStore((s) => s.lend)
|
||||
const reclaim = useStore((s) => s.reclaim)
|
||||
const { close } = useLendAndReclaimModal()
|
||||
@ -65,8 +66,11 @@ function LendAndReclaimModal({ currentAccount, config }: Props) {
|
||||
},
|
||||
[asset.denom, close, currentAccount.id, isLendAction, lend, reclaim],
|
||||
)
|
||||
if (!account) return null
|
||||
|
||||
return (
|
||||
<AssetAmountSelectActionModal
|
||||
account={account}
|
||||
asset={asset}
|
||||
contentHeader={<DetailsHeader data={data} />}
|
||||
coinBalances={coinBalances}
|
||||
|
@ -10,6 +10,7 @@ import {
|
||||
LendAndReclaimModalController,
|
||||
SettingsModal,
|
||||
UnlockModal,
|
||||
V1DepositAndWithdraw,
|
||||
VaultModal,
|
||||
WalletAssets,
|
||||
WithdrawFromVaultsModal,
|
||||
@ -32,6 +33,7 @@ export default function ModalsContainer() {
|
||||
<AlertDialogController />
|
||||
<HlsModal />
|
||||
<HlsManageModal />
|
||||
<V1DepositAndWithdraw />
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
83
src/components/Modals/V1DepositAndWithdraw/Deposit.tsx
Normal file
83
src/components/Modals/V1DepositAndWithdraw/Deposit.tsx
Normal file
@ -0,0 +1,83 @@
|
||||
import { useCallback, useEffect, useMemo, useState } from 'react'
|
||||
|
||||
import WalletBridges from 'components/Wallet/WalletBridges'
|
||||
import { BN_ZERO } from 'constants/math'
|
||||
import useBaseAsset from 'hooks/assets/useBasetAsset'
|
||||
import useCurrentWalletBalance from 'hooks/useCurrentWalletBalance'
|
||||
import { useUpdatedAccount } from 'hooks/useUpdatedAccount'
|
||||
import useWalletBalances from 'hooks/useWalletBalances'
|
||||
import useStore from 'store'
|
||||
import { BNCoin } from 'types/classes/BNCoin'
|
||||
import { byDenom } from 'utils/array'
|
||||
import { defaultFee } from 'utils/constants'
|
||||
import { BN } from 'utils/helpers'
|
||||
|
||||
import AssetAmountSelectActionModal from '../AssetAmountSelectActionModal'
|
||||
import DetailsHeader from '../LendAndReclaim/DetailsHeader'
|
||||
|
||||
interface Props {
|
||||
account: Account
|
||||
}
|
||||
|
||||
export default function Deposit(props: Props) {
|
||||
const { account } = props
|
||||
const baseAsset = useBaseAsset()
|
||||
const modal = useStore((s) => s.v1DepositAndWithdrawModal)
|
||||
const address = useStore((s) => s.address)
|
||||
const asset = modal?.data.asset ?? baseAsset
|
||||
const [fundingAsset, setFundingAsset] = useState<BNCoin>(
|
||||
BNCoin.fromDenomAndBigNumber(modal?.data.asset.denom ?? baseAsset.denom, BN_ZERO),
|
||||
)
|
||||
const { data: walletBalances } = useWalletBalances(address)
|
||||
const { simulateDeposits } = useUpdatedAccount(account)
|
||||
const balance = useCurrentWalletBalance(asset.denom)
|
||||
const v1Action = useStore((s) => s.v1Action)
|
||||
|
||||
const baseBalance = useMemo(
|
||||
() => walletBalances.find(byDenom(baseAsset.denom))?.amount ?? '0',
|
||||
[walletBalances, baseAsset],
|
||||
)
|
||||
|
||||
const close = useCallback(() => {
|
||||
useStore.setState({ v1DepositAndWithdrawModal: null })
|
||||
}, [])
|
||||
|
||||
const handleClick = useCallback(async () => {
|
||||
v1Action('deposit', fundingAsset)
|
||||
close()
|
||||
}, [v1Action, fundingAsset, close])
|
||||
|
||||
useEffect(() => {
|
||||
if (BN(baseBalance).isLessThan(defaultFee.amount[0].amount)) {
|
||||
useStore.setState({ focusComponent: { component: <WalletBridges /> } })
|
||||
}
|
||||
}, [baseBalance])
|
||||
|
||||
const onDebounce = useCallback(() => {
|
||||
simulateDeposits('lend', [fundingAsset])
|
||||
}, [fundingAsset, simulateDeposits])
|
||||
|
||||
const handleAmountChange = useCallback(
|
||||
(value: BigNumber) => {
|
||||
setFundingAsset(BNCoin.fromDenomAndBigNumber(asset.denom, value))
|
||||
},
|
||||
[asset.denom],
|
||||
)
|
||||
|
||||
if (!modal) return
|
||||
|
||||
return (
|
||||
<AssetAmountSelectActionModal
|
||||
account={account}
|
||||
asset={asset}
|
||||
contentHeader={<DetailsHeader data={modal.data} />}
|
||||
coinBalances={balance ? [BNCoin.fromCoin(balance)] : []}
|
||||
actionButtonText={`Deposit ${asset.symbol}`}
|
||||
title={`Deposit ${asset.symbol} into the Red Bank`}
|
||||
onClose={close}
|
||||
onAction={handleClick}
|
||||
onChange={handleAmountChange}
|
||||
onDebounce={onDebounce}
|
||||
/>
|
||||
)
|
||||
}
|
67
src/components/Modals/V1DepositAndWithdraw/Withdraw.tsx
Normal file
67
src/components/Modals/V1DepositAndWithdraw/Withdraw.tsx
Normal file
@ -0,0 +1,67 @@
|
||||
import { useCallback, useState } from 'react'
|
||||
|
||||
import { BN_ZERO } from 'constants/math'
|
||||
import useBaseAsset from 'hooks/assets/useBasetAsset'
|
||||
import useHealthComputer from 'hooks/useHealthComputer'
|
||||
import { useUpdatedAccount } from 'hooks/useUpdatedAccount'
|
||||
import useStore from 'store'
|
||||
import { BNCoin } from 'types/classes/BNCoin'
|
||||
|
||||
import AssetAmountSelectActionModal from '../AssetAmountSelectActionModal'
|
||||
import DetailsHeader from '../LendAndReclaim/DetailsHeader'
|
||||
|
||||
interface Props {
|
||||
account: Account
|
||||
}
|
||||
|
||||
export default function Withdraw(props: Props) {
|
||||
const { account } = props
|
||||
const baseAsset = useBaseAsset()
|
||||
const modal = useStore((s) => s.v1DepositAndWithdrawModal)
|
||||
const asset = modal?.data.asset ?? baseAsset
|
||||
const [withdrawAsset, setWithdrawAsset] = useState<BNCoin>(
|
||||
BNCoin.fromDenomAndBigNumber(modal?.data.asset.denom ?? baseAsset.denom, BN_ZERO),
|
||||
)
|
||||
const { computeMaxWithdrawAmount } = useHealthComputer(account)
|
||||
const maxWithdrawAmount = computeMaxWithdrawAmount(asset.denom)
|
||||
const { simulateWithdraw } = useUpdatedAccount(account)
|
||||
const balance = BNCoin.fromDenomAndBigNumber(asset.denom, maxWithdrawAmount)
|
||||
const v1Action = useStore((s) => s.v1Action)
|
||||
|
||||
const close = useCallback(() => {
|
||||
useStore.setState({ v1DepositAndWithdrawModal: null })
|
||||
}, [])
|
||||
|
||||
const handleClick = useCallback(async () => {
|
||||
v1Action('withdraw', withdrawAsset)
|
||||
close()
|
||||
}, [v1Action, withdrawAsset, close])
|
||||
|
||||
const onDebounce = useCallback(() => {
|
||||
simulateWithdraw(false, withdrawAsset)
|
||||
}, [withdrawAsset, simulateWithdraw])
|
||||
|
||||
const handleAmountChange = useCallback(
|
||||
(value: BigNumber) => {
|
||||
setWithdrawAsset(BNCoin.fromDenomAndBigNumber(asset.denom, value))
|
||||
},
|
||||
[asset.denom],
|
||||
)
|
||||
|
||||
if (!modal) return
|
||||
|
||||
return (
|
||||
<AssetAmountSelectActionModal
|
||||
account={account}
|
||||
asset={asset}
|
||||
contentHeader={<DetailsHeader data={modal.data} />}
|
||||
coinBalances={[balance]}
|
||||
actionButtonText={`Withdraw ${asset.symbol}`}
|
||||
title={`Withdraw ${asset.symbol} from the Red Bank`}
|
||||
onClose={close}
|
||||
onAction={handleClick}
|
||||
onChange={handleAmountChange}
|
||||
onDebounce={onDebounce}
|
||||
/>
|
||||
)
|
||||
}
|
16
src/components/Modals/V1DepositAndWithdraw/index.tsx
Normal file
16
src/components/Modals/V1DepositAndWithdraw/index.tsx
Normal file
@ -0,0 +1,16 @@
|
||||
import useAccount from 'hooks/accounts/useAccount'
|
||||
import useStore from 'store'
|
||||
|
||||
import Deposit from './Deposit'
|
||||
import Withdraw from './Withdraw'
|
||||
|
||||
export default function V1DepositAndWithdraw() {
|
||||
const address = useStore((s) => s.address)
|
||||
const { data: account } = useAccount(address)
|
||||
const modal = useStore<V1DepositAndWithdrawModal | null>((s) => s.v1DepositAndWithdrawModal)
|
||||
const isDeposit = modal?.type === 'deposit'
|
||||
|
||||
if (!modal || !account) return null
|
||||
if (isDeposit) return <Deposit account={account} />
|
||||
return <Withdraw account={account} />
|
||||
}
|
@ -4,11 +4,12 @@ export { default as AlertDialogController } from 'components/Modals/AlertDialog'
|
||||
export { default as BorrowModal } from 'components/Modals/BorrowModal'
|
||||
export { default as FundAndWithdrawModal } from 'components/Modals/FundWithdraw'
|
||||
export { default as GetStartedModal } from 'components/Modals/GetStartedModal'
|
||||
export { default as HlsModal } from 'components/Modals/HLS'
|
||||
export { default as HlsManageModal } from 'components/Modals/HLS/Manage'
|
||||
export { default as LendAndReclaimModalController } from 'components/Modals/LendAndReclaim'
|
||||
export { default as SettingsModal } from 'components/Modals/Settings'
|
||||
export { default as UnlockModal } from 'components/Modals/Unlock'
|
||||
export { default as V1DepositAndWithdraw } from 'components/Modals/V1DepositAndWithdraw'
|
||||
export { default as VaultModal } from 'components/Modals/Vault'
|
||||
export { default as WalletAssets } from 'components/Modals/WalletAssets'
|
||||
export { default as WithdrawFromVaultsModal } from 'components/Modals/WithdrawFromVaultsModal'
|
||||
export { default as HlsModal } from 'components/Modals/HLS'
|
||||
export { default as HlsManageModal } from 'components/Modals/HLS/Manage'
|
||||
|
@ -7,8 +7,8 @@ import Text from 'components/common/Text'
|
||||
import { TextLink } from 'components/common/TextLink'
|
||||
import { generateToastContent } from 'components/common/Toaster'
|
||||
import useTransactions from 'hooks/localStorage/useTransactions'
|
||||
import useStore from 'store'
|
||||
import useChainConfig from 'hooks/useChainConfig'
|
||||
import useStore from 'store'
|
||||
|
||||
export default function RecentTransactions() {
|
||||
const address = useStore((s) => s.address)
|
||||
@ -47,7 +47,9 @@ export default function RecentTransactions() {
|
||||
key={hash}
|
||||
>
|
||||
<div className='flex items-start justify-between w-full pb-2'>
|
||||
<Text className='flex font-bold'>Credit Account {accountId}</Text>
|
||||
<Text className='flex font-bold'>
|
||||
{accountId === address ? 'Red Bank' : `Credit Account ${accountId}`}
|
||||
</Text>
|
||||
<Text size='sm' className='text-white/70'>
|
||||
{moment.unix(timestamp).format('lll')}
|
||||
</Text>
|
||||
|
@ -11,11 +11,11 @@ import { TextLink } from 'components/common/TextLink'
|
||||
import { DEFAULT_SETTINGS } from 'constants/defaultSettings'
|
||||
import { LocalStorageKeys } from 'constants/localStorageKeys'
|
||||
import useLocalStorage from 'hooks/localStorage/useLocalStorage'
|
||||
import useChainConfig from 'hooks/useChainConfig'
|
||||
import useTransactionStore from 'hooks/useTransactionStore'
|
||||
import useStore from 'store'
|
||||
import { formatAmountWithSymbol } from 'utils/formatters'
|
||||
import { BN } from 'utils/helpers'
|
||||
import useChainConfig from 'hooks/useChainConfig'
|
||||
|
||||
const toastBodyClasses = classNames(
|
||||
'flex flex-wrap w-full group/transaction',
|
||||
@ -99,6 +99,13 @@ export default function Toaster() {
|
||||
if (!isError && toast.accountId) addTransaction(toast)
|
||||
const generalMessage = isError ? 'Transaction failed!' : 'Transaction completed successfully!'
|
||||
const showDetailElement = !!(!details && toast.hash)
|
||||
const address = useStore.getState().address
|
||||
|
||||
let target: string
|
||||
if (!isError) {
|
||||
target = toast.accountId === address ? 'Red Bank' : `Credit Account ${toast.accountId}`
|
||||
}
|
||||
|
||||
const Msg = () => (
|
||||
<div className='relative flex flex-wrap w-full m-0 isolate'>
|
||||
<div className='flex w-full gap-2 mb-2'>
|
||||
@ -141,7 +148,7 @@ export default function Toaster() {
|
||||
)}
|
||||
>
|
||||
{!isError && toast.accountId && (
|
||||
<Text className='mb-1 font-bold text-white'>{`Credit Account ${toast.accountId}`}</Text>
|
||||
<Text className='mb-1 font-bold text-white'>{target}</Text>
|
||||
)}
|
||||
{showDetailElement && toast.message && (
|
||||
<Text size='sm' className='w-full mb-1 text-white'>
|
||||
|
@ -37,7 +37,9 @@ export default function DepositButton(props: Props) {
|
||||
disabled={!hasBalance}
|
||||
color='tertiary'
|
||||
onClick={(e) => {
|
||||
useStore.setState({ fundAndWithdrawModal: 'fund' })
|
||||
useStore.setState({
|
||||
v1DepositAndWithdrawModal: { type: 'deposit', data: props.data },
|
||||
})
|
||||
e.stopPropagation()
|
||||
}}
|
||||
text='Deposit'
|
||||
|
@ -22,17 +22,23 @@ export default function Manage(props: Props) {
|
||||
{
|
||||
icon: <ArrowUpLine />,
|
||||
text: 'Deposit more',
|
||||
onClick: () => openLend(props.data),
|
||||
onClick: () =>
|
||||
useStore.setState({
|
||||
v1DepositAndWithdrawModal: { type: 'deposit', data: props.data },
|
||||
}),
|
||||
disabled: !hasBalance,
|
||||
disabledTooltip: `You don’t have any ${props.data.asset.symbol} in your Wallet.`,
|
||||
},
|
||||
{
|
||||
icon: <ArrowDownLine />,
|
||||
text: 'Withdraw',
|
||||
onClick: () => openReclaim(props.data),
|
||||
onClick: () =>
|
||||
useStore.setState({
|
||||
v1DepositAndWithdrawModal: { type: 'withdraw', data: props.data },
|
||||
}),
|
||||
},
|
||||
],
|
||||
[hasBalance, openLend, openReclaim, props.data],
|
||||
[hasBalance, props.data],
|
||||
)
|
||||
|
||||
return (
|
||||
|
@ -3,10 +3,12 @@ import useSWR from 'swr'
|
||||
import getAccount from 'api/accounts/getAccount'
|
||||
import getV1Positions from 'api/v1/getV1Positions'
|
||||
import useChainConfig from 'hooks/useChainConfig'
|
||||
import useStore from 'store'
|
||||
|
||||
export default function useAccount(accountId?: string, suspense?: boolean) {
|
||||
const chainConfig = useChainConfig()
|
||||
const isV1 = isNaN(parseInt(accountId || ''))
|
||||
const address = useStore((s) => s.address)
|
||||
const isV1 = accountId === address
|
||||
|
||||
const cacheKey = isV1
|
||||
? `chains/${chainConfig.id}/v1/user/${accountId}`
|
||||
|
@ -16,6 +16,7 @@ import {
|
||||
ExecuteMsg as CreditManagerExecuteMsg,
|
||||
ExecuteMsg,
|
||||
} from 'types/generated/mars-credit-manager/MarsCreditManager.types'
|
||||
import { ExecuteMsg as RedBankExecuteMsg } from 'types/generated/mars-red-bank/MarsRedBank.types'
|
||||
import { AccountKind } from 'types/generated/mars-rover-health-types/MarsRoverHealthTypes.types'
|
||||
import { byDenom, bySymbol } from 'utils/array'
|
||||
import { generateErrorMessage, getSingleValueFromBroadcastResult } from 'utils/broadcast'
|
||||
@ -30,7 +31,7 @@ import { getVaultDepositCoinsFromActions } from 'utils/vaults'
|
||||
function generateExecutionMessage(
|
||||
sender: string | undefined = '',
|
||||
contract: string,
|
||||
msg: CreditManagerExecuteMsg | AccountNftExecuteMsg | PythUpdateExecuteMsg,
|
||||
msg: CreditManagerExecuteMsg | AccountNftExecuteMsg | RedBankExecuteMsg | PythUpdateExecuteMsg,
|
||||
funds: Coin[],
|
||||
) {
|
||||
return new MsgExecuteContract({
|
||||
@ -1065,5 +1066,69 @@ export default function createBroadcastSlice(
|
||||
{ denom: get().chainConfig.assets[0].denom, amount: String(pythAssets.length) },
|
||||
])
|
||||
},
|
||||
v1Action: async (type: V1ActionType, coin: BNCoin) => {
|
||||
let msg: RedBankExecuteMsg
|
||||
let toastOptions: ToastObjectOptions = {
|
||||
action: type,
|
||||
accountId: get().address,
|
||||
changes: {},
|
||||
}
|
||||
let funds: Coin[] = []
|
||||
|
||||
switch (type) {
|
||||
case 'withdraw':
|
||||
msg = {
|
||||
withdraw: {
|
||||
amount: coin.amount.toString(),
|
||||
denom: coin.denom,
|
||||
},
|
||||
}
|
||||
toastOptions = {
|
||||
...toastOptions,
|
||||
changes: { deposits: [coin] },
|
||||
target: 'wallet',
|
||||
}
|
||||
break
|
||||
case 'repay':
|
||||
msg = {
|
||||
repay: {},
|
||||
}
|
||||
toastOptions.changes = { deposits: [coin] }
|
||||
funds = [coin.toCoin()]
|
||||
break
|
||||
case 'borrow':
|
||||
msg = {
|
||||
borrow: {
|
||||
amount: coin.amount.toString(),
|
||||
denom: coin.denom,
|
||||
},
|
||||
}
|
||||
toastOptions = {
|
||||
...toastOptions,
|
||||
changes: { debts: [coin] },
|
||||
target: 'wallet',
|
||||
}
|
||||
break
|
||||
default:
|
||||
msg = {
|
||||
deposit: {},
|
||||
}
|
||||
toastOptions.changes = { deposits: [coin] }
|
||||
funds = [coin.toCoin()]
|
||||
}
|
||||
|
||||
const redBankContract = get().chainConfig.contracts.redBank
|
||||
|
||||
const response = get().executeMsg({
|
||||
messages: [generateExecutionMessage(get().address, redBankContract, msg, funds)],
|
||||
})
|
||||
|
||||
get().setToast({
|
||||
response,
|
||||
options: toastOptions,
|
||||
})
|
||||
|
||||
return response.then((response) => !!response.result)
|
||||
},
|
||||
}
|
||||
}
|
||||
|
@ -19,5 +19,6 @@ export default function createModalSlice(set: SetState<ModalSlice>, get: GetStat
|
||||
vaultModal: null,
|
||||
walletAssetsModal: null,
|
||||
withdrawFromVaultsModal: null,
|
||||
v1DepositAndWithdrawModal: null,
|
||||
}
|
||||
}
|
||||
|
3
src/types/interfaces/store/broadcast.d.ts
vendored
3
src/types/interfaces/store/broadcast.d.ts
vendored
@ -167,4 +167,7 @@ interface BroadcastSlice {
|
||||
borrow: BNCoin[]
|
||||
reclaims: ActionCoin[]
|
||||
}) => Promise<boolean>
|
||||
v1Action: (type: V1ActionType, funds: BNCoin) => Promise<boolean>
|
||||
}
|
||||
|
||||
type V1ActionType = 'withdraw' | 'deposit' | 'borrow' | 'repay'
|
||||
|
6
src/types/interfaces/store/modals.d.ts
vendored
6
src/types/interfaces/store/modals.d.ts
vendored
@ -7,6 +7,7 @@ interface ModalSlice {
|
||||
hlsManageModal: HlsManageModal | null
|
||||
borrowModal: BorrowModal | null
|
||||
fundAndWithdrawModal: 'fund' | 'withdraw' | null
|
||||
v1DepositAndWithdrawModal: V1DepositAndWithdrawModal | null
|
||||
getStartedModal: boolean
|
||||
hlsInformationModal: boolean | null
|
||||
lendAndReclaimModal: LendAndReclaimModalConfig | null
|
||||
@ -84,3 +85,8 @@ interface HlsManageModal {
|
||||
}
|
||||
|
||||
type HlsStakingManageAction = 'deposit' | 'withdraw' | 'repay' | 'leverage'
|
||||
|
||||
interface V1DepositAndWithdrawModal {
|
||||
type: 'deposit' | 'withdraw'
|
||||
data: LendingMarketTableData
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user