Mp 3004 implement account balance amount when withdrawing 100 of lent asset (#263)

This commit is contained in:
Yusuf Seyrek 2023-06-23 18:52:49 +03:00 committed by GitHub
parent 2c399a2f16
commit 7fda98aeea
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 123 additions and 70 deletions

View File

@ -1,5 +1,4 @@
import Image from 'next/image'
import { useState } from 'react'
import { useCallback, useState } from 'react'
import Button from 'components/Button'
import Card from 'components/Card'
@ -24,7 +23,7 @@ interface Props {
accountSummaryChange?: AccountChange
onClose: () => void
onChange: (value: BigNumber) => void
onAction: (value: BigNumber) => void
onAction: (value: BigNumber, isMax: boolean) => void
}
export default function AssetAmountSelectActionModal(props: Props) {
@ -44,14 +43,17 @@ export default function AssetAmountSelectActionModal(props: Props) {
const [amount, setAmount] = useState(BN(0))
const maxAmount = BN(coinBalances.find(byDenom(asset.denom))?.amount ?? 0)
const handleAmountChange = (value: BigNumber) => {
setAmount(value)
onChange(value)
}
const handleAmountChange = useCallback(
(value: BigNumber) => {
setAmount(value)
onChange(value)
},
[onChange],
)
const handleActionClick = () => {
onAction(amount)
}
const handleActionClick = useCallback(() => {
onAction(amount, amount.eq(maxAmount))
}, [amount, maxAmount, onAction])
return (
<Modal

View File

@ -9,7 +9,7 @@ interface Props {
}
function DetailsHeader({ data }: Props) {
const { asset, marketDepositCap, accountLentAmount: accountLendAmount } = data
const { asset, marketDepositCap, accountLentAmount } = data
const { data: assetApy } = useAssetIncentivesApy(asset.denom)
const balanceInWallet = useCurrentWalletBalance(asset.denom)
@ -33,10 +33,10 @@ function DetailsHeader({ data }: Props) {
<div className='h-100 w-[1px] bg-white/10'></div>
</>
)}
{accountLendAmount && (
{accountLentAmount && (
<>
<TitleAndSubCell
title={<DisplayCurrency coin={{ denom: asset.denom, amount: accountLendAmount }} />}
title={<DisplayCurrency coin={{ denom: asset.denom, amount: accountLentAmount }} />}
sub={'Deposited'}
/>
<div className='h-100 w-[1px] bg-white/10'></div>

View File

@ -1,4 +1,4 @@
import { useState } from 'react'
import { useCallback, useState } from 'react'
import useStore from 'store'
import useToggle from 'hooks/useToggle'
@ -7,31 +7,29 @@ import useCurrentAccount from 'hooks/useCurrentAccount'
import useLendAndReclaimModal from 'hooks/useLendAndReclaimModal'
import DetailsHeader from 'components/Modals/LendAndReclaim/DetailsHeader'
import AssetAmountSelectActionModal from 'components/Modals/AssetAmountSelectActionModal'
import AccountBalanceSettableCoin from 'types/classes/AccountBalanceSettableCoin'
const getAccountChange = (isLend: boolean, value: BigNumber, denom: string): AccountChange => {
const makeCoin = (denom: string, shouldNegate: boolean) => [
{
amount: (shouldNegate ? value.negated() : value).toString(),
denom,
},
]
return {
deposits: makeCoin(denom, isLend),
lends: makeCoin(denom, !isLend),
}
}
function LendAndReclaimModal() {
const lend = useStore((s) => s.lend)
const reclaim = useStore((s) => s.reclaim)
function LendAndReclaimModalController() {
const currentAccount = useCurrentAccount()
const { config, close } = useLendAndReclaimModal()
const [isConfirming, setIsConfirming] = useToggle()
const [accountChange, setAccountChange] = useState<AccountChange | undefined>()
const { config } = useLendAndReclaimModal()
if (!config || !currentAccount) return null
return <LendAndReclaimModal currentAccount={currentAccount} config={config} />
}
interface Props {
currentAccount: Account
config: LendAndReclaimModalConfig
}
function LendAndReclaimModal({ currentAccount, config }: Props) {
const lend = useStore((s) => s.lend)
const reclaim = useStore((s) => s.reclaim)
const { close } = useLendAndReclaimModal()
const [isConfirming, setIsConfirming] = useToggle()
const [accountChange, setAccountChange] = useState<AccountChange | undefined>()
const { data, action } = config
const { asset } = data
@ -39,26 +37,34 @@ function LendAndReclaimModal() {
const actionText = isLendAction ? 'Lend' : 'Withdraw'
const coinBalances = currentAccount[isLendAction ? 'deposits' : 'lends'] ?? []
const handleAmountChange = (value: BigNumber) => {
setAccountChange(getAccountChange(isLendAction, value, asset.denom))
}
const handleAmountChange = useCallback(
(value: BigNumber) => {
setAccountChange(getAccountChange(isLendAction, value, asset.denom))
},
[asset.denom, isLendAction],
)
const handleAction = async (value: BigNumber) => {
setIsConfirming(true)
const handleAction = useCallback(
async (value: BigNumber, isMax: boolean) => {
setIsConfirming(true)
const options = {
fee: hardcodedFee,
accountId: currentAccount.id,
coin: {
denom: asset.denom,
amount: value.toString(),
},
}
await (isLendAction ? lend : reclaim)(options)
const coin = new AccountBalanceSettableCoin(
asset.denom,
value.integerValue().toString(),
isMax,
)
const options = {
fee: hardcodedFee,
accountId: currentAccount.id,
coin,
}
await (isLendAction ? lend : reclaim)(options)
setIsConfirming(false)
close()
}
setIsConfirming(false)
close()
},
[asset.denom, close, currentAccount.id, isLendAction, lend, reclaim, setIsConfirming],
)
return (
<AssetAmountSelectActionModal
@ -77,4 +83,18 @@ function LendAndReclaimModal() {
)
}
export default LendAndReclaimModal
const getAccountChange = (isLend: boolean, value: BigNumber, denom: string): AccountChange => {
const makeCoin = (denom: string, shouldNegate: boolean) => [
{
amount: (shouldNegate ? value.negated() : value).toString(),
denom,
},
]
return {
deposits: makeCoin(denom, isLend),
lends: makeCoin(denom, !isLend),
}
}
export default LendAndReclaimModalController

View File

@ -3,7 +3,7 @@ import BorrowModal from 'components/Modals/Borrow/BorrowModal'
import FundAndWithdrawModal from 'components/Modals/FundWithdraw/FundAndWithdrawModal'
import AddVaultBorrowAssetsModal from 'components/Modals/AddVaultAssets/AddVaultBorrowAssetsModal'
import UnlockModal from 'components/Modals/Unlock/UnlockModal'
import LendAndReclaimModal from 'components/Modals/LendAndReclaim'
import LendAndReclaimModalController from 'components/Modals/LendAndReclaim'
export default function ModalsContainer() {
return (
@ -14,7 +14,7 @@ export default function ModalsContainer() {
<VaultModal />
<AddVaultBorrowAssetsModal />
<UnlockModal />
<LendAndReclaimModal />
<LendAndReclaimModalController />
</>
)
}

View File

@ -43,12 +43,7 @@ export default function Toaster() {
{toast.message}
</Text>
<div className='absolute right-6 top-8 '>
<Button
leftIcon={<Cross />}
variant='transparent'
className='w-2'
iconClassName={classNames('w-2 h-2', toast.isError ? 'text-error' : 'text-success')}
/>
<Cross className={classNames('h-2 w-2', toast.isError ? 'text-error' : 'text-success')} />
</div>
</div>
)

View File

@ -6,7 +6,7 @@ import { ENV } from 'constants/env'
import { Store } from 'store'
import { getSingleValueFromBroadcastResult } from 'utils/broadcast'
import { formatAmountWithSymbol } from 'utils/formatters'
import { BN } from 'utils/helpers'
import AccountBalanceSettableCoin from 'types/classes/AccountBalanceSettableCoin'
export default function createBroadcastSlice(
set: SetState<Store>,
@ -213,7 +213,7 @@ export default function createBroadcastSlice(
)
return !!response.result
},
lend: async (options: { fee: StdFee; accountId: string; coin: Coin }) => {
lend: async (options: { fee: StdFee; accountId: string; coin: AccountBalanceSettableCoin }) => {
const msg = {
update_credit_account: {
account_id: options.accountId,
@ -233,14 +233,17 @@ export default function createBroadcastSlice(
)
return !!response.result
},
reclaim: async (options: { fee: StdFee; accountId: string; coin: Coin }) => {
const reclaim = { denom: options.coin.denom, amount: { exact: BN(options.coin.amount) } }
reclaim: async (options: {
fee: StdFee
accountId: string
coin: AccountBalanceSettableCoin
}) => {
const msg = {
update_credit_account: {
account_id: options.accountId,
actions: [
{
reclaim,
reclaim: options.coin.toActionCoin(),
},
],
},
@ -250,7 +253,7 @@ export default function createBroadcastSlice(
handleResponseMessages(
response,
`Successfully deposited ${formatAmountWithSymbol(options.coin)}`,
`Successfully withdrew ${formatAmountWithSymbol(options.coin)}`,
)
return !!response.result
},

View File

@ -0,0 +1,22 @@
import { ActionCoin } from 'types/generated'
class AccountBalanceSettableCoin implements Coin {
public denom: string
public amount: string
public setAccountBalance: boolean
constructor(denom: string, amount: string, setAccountBalance: boolean) {
this.denom = denom
this.amount = amount
this.setAccountBalance = setAccountBalance
}
toActionCoin(): ActionCoin {
return {
denom: this.denom,
amount: this.setAccountBalance ? 'account_balance' : { exact: this.amount },
}
}
}
export default AccountBalanceSettableCoin

1
src/types/generated.d.ts vendored Normal file
View File

@ -0,0 +1 @@
export { ActionCoin } from 'types/generated/mars-credit-manager/MarsCreditManager.types'

View File

@ -1,3 +1,5 @@
type AccountBalanceSettableCoin = import('types/classes/AccountBalanceSettableCoin')
interface BroadcastResult {
result?: import('@marsprotocol/wallet-connector').TxBroadcastResult
error?: string
@ -16,8 +18,16 @@ interface BroadcastSlice {
deposit: (options: { fee: StdFee; accountId: string; coin: Coin }) => Promise<boolean>
unlock: (options: { fee: StdFee; vault: Vault; amount: string }) => Promise<boolean>
withdraw: (options: { fee: StdFee; accountId: string; coin: Coin }) => Promise<boolean>
lend: (options: { fee: StdFee; accountId: string; coin: Coin }) => Promise<boolean>
reclaim: (options: { fee: StdFee; accountId: string; coin: Coin }) => Promise<boolean>
lend: (options: {
fee: StdFee
accountId: string
coin: AccountBalanceSettableCoin
}) => Promise<boolean>
reclaim: (options: {
fee: StdFee
accountId: string
coin: AccountBalanceSettableCoin
}) => Promise<boolean>
repay: (options: {
fee: StdFee
accountId: string

View File

@ -1,6 +1,6 @@
type Coin = {
readonly denom: string
readonly amount: string
denom: string
amount: string
}
type StdFee = {