Mp 3004 implement account balance amount when withdrawing 100 of lent asset (#263)
This commit is contained in:
parent
2c399a2f16
commit
7fda98aeea
@ -1,5 +1,4 @@
|
|||||||
import Image from 'next/image'
|
import { useCallback, useState } from 'react'
|
||||||
import { useState } from 'react'
|
|
||||||
|
|
||||||
import Button from 'components/Button'
|
import Button from 'components/Button'
|
||||||
import Card from 'components/Card'
|
import Card from 'components/Card'
|
||||||
@ -24,7 +23,7 @@ interface Props {
|
|||||||
accountSummaryChange?: AccountChange
|
accountSummaryChange?: AccountChange
|
||||||
onClose: () => void
|
onClose: () => void
|
||||||
onChange: (value: BigNumber) => void
|
onChange: (value: BigNumber) => void
|
||||||
onAction: (value: BigNumber) => void
|
onAction: (value: BigNumber, isMax: boolean) => void
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function AssetAmountSelectActionModal(props: Props) {
|
export default function AssetAmountSelectActionModal(props: Props) {
|
||||||
@ -44,14 +43,17 @@ export default function AssetAmountSelectActionModal(props: Props) {
|
|||||||
const [amount, setAmount] = useState(BN(0))
|
const [amount, setAmount] = useState(BN(0))
|
||||||
const maxAmount = BN(coinBalances.find(byDenom(asset.denom))?.amount ?? 0)
|
const maxAmount = BN(coinBalances.find(byDenom(asset.denom))?.amount ?? 0)
|
||||||
|
|
||||||
const handleAmountChange = (value: BigNumber) => {
|
const handleAmountChange = useCallback(
|
||||||
setAmount(value)
|
(value: BigNumber) => {
|
||||||
onChange(value)
|
setAmount(value)
|
||||||
}
|
onChange(value)
|
||||||
|
},
|
||||||
|
[onChange],
|
||||||
|
)
|
||||||
|
|
||||||
const handleActionClick = () => {
|
const handleActionClick = useCallback(() => {
|
||||||
onAction(amount)
|
onAction(amount, amount.eq(maxAmount))
|
||||||
}
|
}, [amount, maxAmount, onAction])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Modal
|
<Modal
|
||||||
|
@ -9,7 +9,7 @@ interface Props {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function DetailsHeader({ data }: Props) {
|
function DetailsHeader({ data }: Props) {
|
||||||
const { asset, marketDepositCap, accountLentAmount: accountLendAmount } = data
|
const { asset, marketDepositCap, accountLentAmount } = data
|
||||||
const { data: assetApy } = useAssetIncentivesApy(asset.denom)
|
const { data: assetApy } = useAssetIncentivesApy(asset.denom)
|
||||||
const balanceInWallet = useCurrentWalletBalance(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>
|
<div className='h-100 w-[1px] bg-white/10'></div>
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
{accountLendAmount && (
|
{accountLentAmount && (
|
||||||
<>
|
<>
|
||||||
<TitleAndSubCell
|
<TitleAndSubCell
|
||||||
title={<DisplayCurrency coin={{ denom: asset.denom, amount: accountLendAmount }} />}
|
title={<DisplayCurrency coin={{ denom: asset.denom, amount: accountLentAmount }} />}
|
||||||
sub={'Deposited'}
|
sub={'Deposited'}
|
||||||
/>
|
/>
|
||||||
<div className='h-100 w-[1px] bg-white/10'></div>
|
<div className='h-100 w-[1px] bg-white/10'></div>
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { useState } from 'react'
|
import { useCallback, useState } from 'react'
|
||||||
|
|
||||||
import useStore from 'store'
|
import useStore from 'store'
|
||||||
import useToggle from 'hooks/useToggle'
|
import useToggle from 'hooks/useToggle'
|
||||||
@ -7,31 +7,29 @@ import useCurrentAccount from 'hooks/useCurrentAccount'
|
|||||||
import useLendAndReclaimModal from 'hooks/useLendAndReclaimModal'
|
import useLendAndReclaimModal from 'hooks/useLendAndReclaimModal'
|
||||||
import DetailsHeader from 'components/Modals/LendAndReclaim/DetailsHeader'
|
import DetailsHeader from 'components/Modals/LendAndReclaim/DetailsHeader'
|
||||||
import AssetAmountSelectActionModal from 'components/Modals/AssetAmountSelectActionModal'
|
import AssetAmountSelectActionModal from 'components/Modals/AssetAmountSelectActionModal'
|
||||||
|
import AccountBalanceSettableCoin from 'types/classes/AccountBalanceSettableCoin'
|
||||||
|
|
||||||
const getAccountChange = (isLend: boolean, value: BigNumber, denom: string): AccountChange => {
|
function LendAndReclaimModalController() {
|
||||||
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)
|
|
||||||
const currentAccount = useCurrentAccount()
|
const currentAccount = useCurrentAccount()
|
||||||
const { config, close } = useLendAndReclaimModal()
|
const { config } = useLendAndReclaimModal()
|
||||||
const [isConfirming, setIsConfirming] = useToggle()
|
|
||||||
const [accountChange, setAccountChange] = useState<AccountChange | undefined>()
|
|
||||||
|
|
||||||
if (!config || !currentAccount) return null
|
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 { data, action } = config
|
||||||
const { asset } = data
|
const { asset } = data
|
||||||
|
|
||||||
@ -39,26 +37,34 @@ function LendAndReclaimModal() {
|
|||||||
const actionText = isLendAction ? 'Lend' : 'Withdraw'
|
const actionText = isLendAction ? 'Lend' : 'Withdraw'
|
||||||
const coinBalances = currentAccount[isLendAction ? 'deposits' : 'lends'] ?? []
|
const coinBalances = currentAccount[isLendAction ? 'deposits' : 'lends'] ?? []
|
||||||
|
|
||||||
const handleAmountChange = (value: BigNumber) => {
|
const handleAmountChange = useCallback(
|
||||||
setAccountChange(getAccountChange(isLendAction, value, asset.denom))
|
(value: BigNumber) => {
|
||||||
}
|
setAccountChange(getAccountChange(isLendAction, value, asset.denom))
|
||||||
|
},
|
||||||
|
[asset.denom, isLendAction],
|
||||||
|
)
|
||||||
|
|
||||||
const handleAction = async (value: BigNumber) => {
|
const handleAction = useCallback(
|
||||||
setIsConfirming(true)
|
async (value: BigNumber, isMax: boolean) => {
|
||||||
|
setIsConfirming(true)
|
||||||
|
|
||||||
const options = {
|
const coin = new AccountBalanceSettableCoin(
|
||||||
fee: hardcodedFee,
|
asset.denom,
|
||||||
accountId: currentAccount.id,
|
value.integerValue().toString(),
|
||||||
coin: {
|
isMax,
|
||||||
denom: asset.denom,
|
)
|
||||||
amount: value.toString(),
|
const options = {
|
||||||
},
|
fee: hardcodedFee,
|
||||||
}
|
accountId: currentAccount.id,
|
||||||
await (isLendAction ? lend : reclaim)(options)
|
coin,
|
||||||
|
}
|
||||||
|
await (isLendAction ? lend : reclaim)(options)
|
||||||
|
|
||||||
setIsConfirming(false)
|
setIsConfirming(false)
|
||||||
close()
|
close()
|
||||||
}
|
},
|
||||||
|
[asset.denom, close, currentAccount.id, isLendAction, lend, reclaim, setIsConfirming],
|
||||||
|
)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<AssetAmountSelectActionModal
|
<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
|
||||||
|
@ -3,7 +3,7 @@ import BorrowModal from 'components/Modals/Borrow/BorrowModal'
|
|||||||
import FundAndWithdrawModal from 'components/Modals/FundWithdraw/FundAndWithdrawModal'
|
import FundAndWithdrawModal from 'components/Modals/FundWithdraw/FundAndWithdrawModal'
|
||||||
import AddVaultBorrowAssetsModal from 'components/Modals/AddVaultAssets/AddVaultBorrowAssetsModal'
|
import AddVaultBorrowAssetsModal from 'components/Modals/AddVaultAssets/AddVaultBorrowAssetsModal'
|
||||||
import UnlockModal from 'components/Modals/Unlock/UnlockModal'
|
import UnlockModal from 'components/Modals/Unlock/UnlockModal'
|
||||||
import LendAndReclaimModal from 'components/Modals/LendAndReclaim'
|
import LendAndReclaimModalController from 'components/Modals/LendAndReclaim'
|
||||||
|
|
||||||
export default function ModalsContainer() {
|
export default function ModalsContainer() {
|
||||||
return (
|
return (
|
||||||
@ -14,7 +14,7 @@ export default function ModalsContainer() {
|
|||||||
<VaultModal />
|
<VaultModal />
|
||||||
<AddVaultBorrowAssetsModal />
|
<AddVaultBorrowAssetsModal />
|
||||||
<UnlockModal />
|
<UnlockModal />
|
||||||
<LendAndReclaimModal />
|
<LendAndReclaimModalController />
|
||||||
</>
|
</>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -43,12 +43,7 @@ export default function Toaster() {
|
|||||||
{toast.message}
|
{toast.message}
|
||||||
</Text>
|
</Text>
|
||||||
<div className='absolute right-6 top-8 '>
|
<div className='absolute right-6 top-8 '>
|
||||||
<Button
|
<Cross className={classNames('h-2 w-2', toast.isError ? 'text-error' : 'text-success')} />
|
||||||
leftIcon={<Cross />}
|
|
||||||
variant='transparent'
|
|
||||||
className='w-2'
|
|
||||||
iconClassName={classNames('w-2 h-2', toast.isError ? 'text-error' : 'text-success')}
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
|
@ -6,7 +6,7 @@ import { ENV } from 'constants/env'
|
|||||||
import { Store } from 'store'
|
import { Store } from 'store'
|
||||||
import { getSingleValueFromBroadcastResult } from 'utils/broadcast'
|
import { getSingleValueFromBroadcastResult } from 'utils/broadcast'
|
||||||
import { formatAmountWithSymbol } from 'utils/formatters'
|
import { formatAmountWithSymbol } from 'utils/formatters'
|
||||||
import { BN } from 'utils/helpers'
|
import AccountBalanceSettableCoin from 'types/classes/AccountBalanceSettableCoin'
|
||||||
|
|
||||||
export default function createBroadcastSlice(
|
export default function createBroadcastSlice(
|
||||||
set: SetState<Store>,
|
set: SetState<Store>,
|
||||||
@ -213,7 +213,7 @@ export default function createBroadcastSlice(
|
|||||||
)
|
)
|
||||||
return !!response.result
|
return !!response.result
|
||||||
},
|
},
|
||||||
lend: async (options: { fee: StdFee; accountId: string; coin: Coin }) => {
|
lend: async (options: { fee: StdFee; accountId: string; coin: AccountBalanceSettableCoin }) => {
|
||||||
const msg = {
|
const msg = {
|
||||||
update_credit_account: {
|
update_credit_account: {
|
||||||
account_id: options.accountId,
|
account_id: options.accountId,
|
||||||
@ -233,14 +233,17 @@ export default function createBroadcastSlice(
|
|||||||
)
|
)
|
||||||
return !!response.result
|
return !!response.result
|
||||||
},
|
},
|
||||||
reclaim: async (options: { fee: StdFee; accountId: string; coin: Coin }) => {
|
reclaim: async (options: {
|
||||||
const reclaim = { denom: options.coin.denom, amount: { exact: BN(options.coin.amount) } }
|
fee: StdFee
|
||||||
|
accountId: string
|
||||||
|
coin: AccountBalanceSettableCoin
|
||||||
|
}) => {
|
||||||
const msg = {
|
const msg = {
|
||||||
update_credit_account: {
|
update_credit_account: {
|
||||||
account_id: options.accountId,
|
account_id: options.accountId,
|
||||||
actions: [
|
actions: [
|
||||||
{
|
{
|
||||||
reclaim,
|
reclaim: options.coin.toActionCoin(),
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
@ -250,7 +253,7 @@ export default function createBroadcastSlice(
|
|||||||
|
|
||||||
handleResponseMessages(
|
handleResponseMessages(
|
||||||
response,
|
response,
|
||||||
`Successfully deposited ${formatAmountWithSymbol(options.coin)}`,
|
`Successfully withdrew ${formatAmountWithSymbol(options.coin)}`,
|
||||||
)
|
)
|
||||||
return !!response.result
|
return !!response.result
|
||||||
},
|
},
|
||||||
|
22
src/types/classes/AccountBalanceSettableCoin.ts
Normal file
22
src/types/classes/AccountBalanceSettableCoin.ts
Normal 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
1
src/types/generated.d.ts
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
export { ActionCoin } from 'types/generated/mars-credit-manager/MarsCreditManager.types'
|
14
src/types/interfaces/store/broadcast.d.ts
vendored
14
src/types/interfaces/store/broadcast.d.ts
vendored
@ -1,3 +1,5 @@
|
|||||||
|
type AccountBalanceSettableCoin = import('types/classes/AccountBalanceSettableCoin')
|
||||||
|
|
||||||
interface BroadcastResult {
|
interface BroadcastResult {
|
||||||
result?: import('@marsprotocol/wallet-connector').TxBroadcastResult
|
result?: import('@marsprotocol/wallet-connector').TxBroadcastResult
|
||||||
error?: string
|
error?: string
|
||||||
@ -16,8 +18,16 @@ interface BroadcastSlice {
|
|||||||
deposit: (options: { fee: StdFee; accountId: string; coin: Coin }) => Promise<boolean>
|
deposit: (options: { fee: StdFee; accountId: string; coin: Coin }) => Promise<boolean>
|
||||||
unlock: (options: { fee: StdFee; vault: Vault; amount: string }) => Promise<boolean>
|
unlock: (options: { fee: StdFee; vault: Vault; amount: string }) => Promise<boolean>
|
||||||
withdraw: (options: { fee: StdFee; accountId: string; coin: Coin }) => Promise<boolean>
|
withdraw: (options: { fee: StdFee; accountId: string; coin: Coin }) => Promise<boolean>
|
||||||
lend: (options: { fee: StdFee; accountId: string; coin: Coin }) => Promise<boolean>
|
lend: (options: {
|
||||||
reclaim: (options: { fee: StdFee; accountId: string; coin: Coin }) => Promise<boolean>
|
fee: StdFee
|
||||||
|
accountId: string
|
||||||
|
coin: AccountBalanceSettableCoin
|
||||||
|
}) => Promise<boolean>
|
||||||
|
reclaim: (options: {
|
||||||
|
fee: StdFee
|
||||||
|
accountId: string
|
||||||
|
coin: AccountBalanceSettableCoin
|
||||||
|
}) => Promise<boolean>
|
||||||
repay: (options: {
|
repay: (options: {
|
||||||
fee: StdFee
|
fee: StdFee
|
||||||
accountId: string
|
accountId: string
|
||||||
|
4
src/types/stargate.d.ts
vendored
4
src/types/stargate.d.ts
vendored
@ -1,6 +1,6 @@
|
|||||||
type Coin = {
|
type Coin = {
|
||||||
readonly denom: string
|
denom: string
|
||||||
readonly amount: string
|
amount: string
|
||||||
}
|
}
|
||||||
|
|
||||||
type StdFee = {
|
type StdFee = {
|
||||||
|
Loading…
Reference in New Issue
Block a user