Mp 2881 finalize the borrow flow table (#308)
* MP-2881: fixed the buttons and adjusted the marketDetails * MP-2881: finished the borrow to wallet functionatlity * fix: renamed withdraw to borrowToWallet * fix: moved the useMemo return into functions * tidy: refactor * tidy: refactor
This commit is contained in:
parent
e1956ddbe9
commit
ac0658224e
@ -1,7 +1,7 @@
|
||||
import { useCallback } from 'react'
|
||||
|
||||
import Button from 'components/Button'
|
||||
import { Plus } from 'components/Icons'
|
||||
import { Plus, ReceiptCheck } from 'components/Icons'
|
||||
import useStore from 'store'
|
||||
import { getEnabledMarketAssets } from 'utils/assets'
|
||||
|
||||
@ -29,13 +29,15 @@ export default function BorrowActionButtons(props: Props) {
|
||||
return (
|
||||
<div className='flex flex-row space-x-2'>
|
||||
<Button
|
||||
leftIcon={debt ? <Plus /> : undefined}
|
||||
leftIcon={<Plus className='w-3' />}
|
||||
onClick={borrowHandler}
|
||||
color='secondary'
|
||||
text={debt ? 'Borrow more' : 'Borrow'}
|
||||
className='min-w-40 text-center'
|
||||
/>
|
||||
{debt && <Button color='secondary' text='Repay' onClick={repayHandler} />}
|
||||
{debt && (
|
||||
<Button color='tertiary' leftIcon={<ReceiptCheck />} text='Repay' onClick={repayHandler} />
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
@ -33,7 +33,7 @@ export default function BorrowTable(props: Props) {
|
||||
resetExpanded={table.resetExpanded}
|
||||
rowData={row}
|
||||
expandedActionButtons={<BorrowActionButtons data={row.original} />}
|
||||
expandedDetails={<MarketDetails data={row.original} />}
|
||||
expandedDetails={<MarketDetails data={row.original} type='borrow' />}
|
||||
/>
|
||||
)
|
||||
},
|
||||
|
@ -32,7 +32,7 @@ export default function LendingMarketsTable(props: Props) {
|
||||
resetExpanded={table.resetExpanded}
|
||||
rowData={row}
|
||||
expandedActionButtons={<LendingActionButtons data={row.original} />}
|
||||
expandedDetails={<MarketDetails data={row.original} />}
|
||||
expandedDetails={<MarketDetails data={row.original} type='lend' />}
|
||||
/>
|
||||
)
|
||||
},
|
||||
|
8
src/components/Icons/ReceiptCheck.svg
Normal file
8
src/components/Icons/ReceiptCheck.svg
Normal file
@ -0,0 +1,8 @@
|
||||
<svg viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path
|
||||
d="M5.99984 7L7.33317 8.33333L10.3332 5.33333M13.3332 14V5.2C13.3332 4.0799 13.3332 3.51984 13.1152 3.09202C12.9234 2.71569 12.6175 2.40973 12.2412 2.21799C11.8133 2 11.2533 2 10.1332 2H5.8665C4.7464 2 4.18635 2 3.75852 2.21799C3.3822 2.40973 3.07624 2.71569 2.88449 3.09202C2.6665 3.51984 2.6665 4.0799 2.6665 5.2V14L4.49984 12.6667L6.1665 14L7.99984 12.6667L9.83317 14L11.4998 12.6667L13.3332 14Z"
|
||||
stroke="currentColor"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
/>
|
||||
</svg>
|
After Width: | Height: | Size: 578 B |
@ -31,6 +31,7 @@ export { default as OverlayMark } from 'components/Icons/OverlayMark.svg'
|
||||
export { default as Plus } from 'components/Icons/Plus.svg'
|
||||
export { default as PlusCircled } from 'components/Icons/PlusCircled.svg'
|
||||
export { default as Questionmark } from 'components/Icons/Questionmark.svg'
|
||||
export { default as ReceiptCheck } from 'components/Icons/ReceiptCheck.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'
|
||||
@ -41,6 +42,6 @@ export { default as StarOutlined } from 'components/Icons/StarOutlined.svg'
|
||||
export { default as Subtract } from 'components/Icons/Subtract.svg'
|
||||
export { default as SwapIcon } from 'components/Icons/SwapIcon.svg'
|
||||
export { default as TrashBin } from 'components/Icons/TrashBin.svg'
|
||||
export { default as Wallet } from 'components/Icons/Wallet.svg'
|
||||
export { default as VerticalThreeLine } from 'components/Icons/VerticalThreeLine.svg'
|
||||
export { default as Wallet } from 'components/Icons/Wallet.svg'
|
||||
// @endindex
|
||||
|
@ -6,6 +6,7 @@ import useDisplayCurrencyPrice from 'hooks/useDisplayCurrencyPrice'
|
||||
|
||||
interface Props {
|
||||
data: BorrowMarketTableData | LendingMarketTableData
|
||||
type: 'borrow' | 'lend'
|
||||
}
|
||||
|
||||
interface Detail {
|
||||
@ -14,12 +15,13 @@ interface Detail {
|
||||
title: string
|
||||
}
|
||||
|
||||
export default function MarketDetails({ data }: Props) {
|
||||
export default function MarketDetails({ data, type }: Props) {
|
||||
const {
|
||||
convertAmount,
|
||||
getConversionRate,
|
||||
symbol: displayCurrencySymbol,
|
||||
} = useDisplayCurrencyPrice()
|
||||
|
||||
const {
|
||||
asset,
|
||||
marketMaxLtv,
|
||||
@ -30,48 +32,73 @@ export default function MarketDetails({ data }: Props) {
|
||||
|
||||
const totalBorrowed = marketDepositAmount.minus(marketLiquidityAmount)
|
||||
|
||||
const details: Detail[] = useMemo(
|
||||
() => [
|
||||
{
|
||||
amount: convertAmount(asset, marketDepositAmount).toNumber(),
|
||||
options: { abbreviated: true, suffix: ` ${displayCurrencySymbol}` },
|
||||
title: 'Total Supplied',
|
||||
},
|
||||
{
|
||||
amount: marketMaxLtv * 100,
|
||||
options: { minDecimals: 2, maxDecimals: 2, suffix: '%' },
|
||||
title: 'Max LTV',
|
||||
},
|
||||
{
|
||||
amount: marketLiquidationThreshold * 100,
|
||||
options: { minDecimals: 2, maxDecimals: 2, suffix: '%' },
|
||||
title: 'Liquidation Threshold',
|
||||
},
|
||||
{
|
||||
amount: getConversionRate(asset.denom).toNumber(),
|
||||
options: { minDecimals: 2, maxDecimals: 2, suffix: ` ${displayCurrencySymbol}` },
|
||||
title: 'Oracle Price',
|
||||
},
|
||||
{
|
||||
amount: totalBorrowed.dividedBy(marketDepositAmount).multipliedBy(100).toNumber(),
|
||||
options: { minDecimals: 2, maxDecimals: 2, suffix: '%' },
|
||||
title: 'Utilization Rate',
|
||||
},
|
||||
],
|
||||
[
|
||||
asset,
|
||||
marketDepositAmount,
|
||||
marketLiquidationThreshold,
|
||||
marketMaxLtv,
|
||||
displayCurrencySymbol,
|
||||
convertAmount,
|
||||
getConversionRate,
|
||||
totalBorrowed,
|
||||
],
|
||||
)
|
||||
const details: Detail[] = useMemo(() => {
|
||||
function getLendingMarketDetails() {
|
||||
return [
|
||||
{
|
||||
amount: convertAmount(asset, marketDepositAmount).toNumber(),
|
||||
options: { abbreviated: true, suffix: ` ${displayCurrencySymbol}` },
|
||||
title: 'Total Supplied',
|
||||
},
|
||||
{
|
||||
amount: marketMaxLtv * 100,
|
||||
options: { minDecimals: 2, maxDecimals: 2, suffix: '%' },
|
||||
title: 'Max LTV',
|
||||
},
|
||||
{
|
||||
amount: marketLiquidationThreshold * 100,
|
||||
options: { minDecimals: 2, maxDecimals: 2, suffix: '%' },
|
||||
title: 'Liquidation Threshold',
|
||||
},
|
||||
{
|
||||
amount: getConversionRate(asset.denom).toNumber(),
|
||||
options: { minDecimals: 2, maxDecimals: 2, suffix: ` ${displayCurrencySymbol}` },
|
||||
title: 'Oracle Price',
|
||||
},
|
||||
{
|
||||
amount: totalBorrowed.dividedBy(marketDepositAmount).multipliedBy(100).toNumber(),
|
||||
options: { minDecimals: 2, maxDecimals: 2, suffix: '%' },
|
||||
title: 'Utilization Rate',
|
||||
},
|
||||
]
|
||||
}
|
||||
|
||||
function getBorrowMarketDetails() {
|
||||
return [
|
||||
{
|
||||
amount: convertAmount(asset, totalBorrowed).toNumber(),
|
||||
options: { abbreviated: true, suffix: ` ${displayCurrencySymbol}` },
|
||||
title: 'Total Borrowed',
|
||||
},
|
||||
{
|
||||
amount: getConversionRate(asset.denom).toNumber(),
|
||||
options: { minDecimals: 2, maxDecimals: 2, suffix: ` ${displayCurrencySymbol}` },
|
||||
title: 'Oracle Price',
|
||||
},
|
||||
{
|
||||
amount: totalBorrowed.dividedBy(marketDepositAmount).multipliedBy(100).toNumber(),
|
||||
options: { minDecimals: 2, maxDecimals: 2, suffix: '%' },
|
||||
title: 'Utilization Rate',
|
||||
},
|
||||
]
|
||||
}
|
||||
|
||||
if (type === 'lend') return getLendingMarketDetails()
|
||||
return getBorrowMarketDetails()
|
||||
}, [
|
||||
type,
|
||||
asset,
|
||||
marketDepositAmount,
|
||||
marketMaxLtv,
|
||||
marketLiquidationThreshold,
|
||||
totalBorrowed,
|
||||
displayCurrencySymbol,
|
||||
convertAmount,
|
||||
getConversionRate,
|
||||
])
|
||||
|
||||
return (
|
||||
<div className='flex flex-1 justify-center rounded-md bg-white bg-opacity-5'>
|
||||
<div className='flex flex-1 justify-between rounded-md bg-white bg-opacity-5'>
|
||||
{details.map((detail, index) => (
|
||||
<TitleAndSubCell
|
||||
key={index}
|
||||
|
@ -7,7 +7,7 @@ import Card from 'components/Card'
|
||||
import Divider from 'components/Divider'
|
||||
import { ArrowRight } from 'components/Icons'
|
||||
import Modal from 'components/Modal'
|
||||
import Select from 'components/Select'
|
||||
import Switch from 'components/Switch'
|
||||
import Text from 'components/Text'
|
||||
import TitleAndSubCell from 'components/TitleAndSubCell'
|
||||
import TokenInputWithSlider from 'components/TokenInputWithSlider'
|
||||
@ -34,16 +34,12 @@ export default function BorrowModal() {
|
||||
const [percentage, setPercentage] = useState(0)
|
||||
const [amount, setAmount] = useState(BN(0))
|
||||
const [change, setChange] = useState<AccountChange | undefined>()
|
||||
const [selectedAccount, setSelectedAccount] = useState(currentAccount)
|
||||
const [isConfirming, setIsConfirming] = useToggle()
|
||||
const [borrowToWallet, setBorrowToWallet] = useToggle()
|
||||
const modal = useStore((s) => s.borrowModal)
|
||||
const borrow = useStore((s) => s.borrow)
|
||||
const repay = useStore((s) => s.repay)
|
||||
const asset = modal?.asset ?? ASSETS[0]
|
||||
const accounts = useStore((s) => s.accounts)
|
||||
const accountOptions = accounts?.map((account) => {
|
||||
return { value: account.id, label: `Account ${account.id}` }
|
||||
})
|
||||
const isRepay = modal?.isRepay ?? false
|
||||
|
||||
function resetState() {
|
||||
@ -53,21 +49,22 @@ export default function BorrowModal() {
|
||||
}
|
||||
|
||||
async function onConfirmClick() {
|
||||
if (!modal?.asset) return
|
||||
if (!modal?.asset || !currentAccount) return
|
||||
setIsConfirming(true)
|
||||
let result
|
||||
if (isRepay) {
|
||||
result = await repay({
|
||||
fee: hardcodedFee,
|
||||
accountId: selectedAccount?.id ?? '0',
|
||||
accountId: currentAccount.id,
|
||||
coin: BNCoin.fromDenomAndBigNumber(modal.asset.denom, amount),
|
||||
accountBalance: percentage === 100,
|
||||
})
|
||||
} else {
|
||||
result = await borrow({
|
||||
fee: hardcodedFee,
|
||||
accountId: selectedAccount?.id ?? '0',
|
||||
accountId: currentAccount.id,
|
||||
coin: { denom: modal.asset.denom, amount: amount.toString() },
|
||||
borrowToWallet,
|
||||
})
|
||||
}
|
||||
|
||||
@ -95,10 +92,6 @@ export default function BorrowModal() {
|
||||
|
||||
const max = BN(isRepay ? getDebtAmount(modal) : modal?.marketData?.liquidity?.amount ?? '0')
|
||||
|
||||
useEffect(() => {
|
||||
if (!selectedAccount) setSelectedAccount(currentAccount)
|
||||
}, [selectedAccount, currentAccount])
|
||||
|
||||
useEffect(() => {
|
||||
if (!modal?.asset) return
|
||||
|
||||
@ -167,19 +160,17 @@ export default function BorrowModal() {
|
||||
maxText='Max'
|
||||
/>
|
||||
<Divider className='my-6' />
|
||||
<Text size='lg' className='pb-2'>
|
||||
{isRepay ? 'Repay for' : 'Borrow to'}
|
||||
</Text>
|
||||
<div className='relative flex w-full'>
|
||||
<Select
|
||||
options={accountOptions ?? []}
|
||||
title='Accounts'
|
||||
defaultValue={selectedAccount?.id}
|
||||
containerClassName='w-full'
|
||||
onChange={(account) => {
|
||||
accounts && setSelectedAccount(accounts?.find((a) => a.id === account))
|
||||
}}
|
||||
className='w-full rounded-base border border-white/10 bg-white/5'
|
||||
<div className='flex flex-1 flex-wrap'>
|
||||
<Text className='mb-1 w-full'>Receive funds to Wallet</Text>
|
||||
<Text size='xs' className='text-white/50'>
|
||||
Your borrowed funds will directly go to your wallet
|
||||
</Text>
|
||||
</div>
|
||||
<div className='flex flex-wrap items-center justify-end'>
|
||||
<Switch
|
||||
name='borrow-to-wallet'
|
||||
checked={borrowToWallet}
|
||||
onChange={setBorrowToWallet}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
@ -192,7 +183,7 @@ export default function BorrowModal() {
|
||||
rightIcon={<ArrowRight />}
|
||||
/>
|
||||
</Card>
|
||||
<AccountSummary account={selectedAccount} change={change} />
|
||||
<AccountSummary account={currentAccount} change={change} />
|
||||
</div>
|
||||
</Modal>
|
||||
)
|
||||
|
@ -42,11 +42,20 @@ export default function createBroadcastSlice(
|
||||
|
||||
return {
|
||||
toast: null,
|
||||
borrow: async (options: { fee: StdFee; accountId: string; coin: Coin }) => {
|
||||
borrow: async (options: {
|
||||
fee: StdFee
|
||||
accountId: string
|
||||
coin: Coin
|
||||
borrowToWallet: boolean
|
||||
}) => {
|
||||
const borrowAction: Action = { borrow: options.coin }
|
||||
const withdrawAction: Action = { withdraw: options.coin }
|
||||
const actions = options.borrowToWallet ? [borrowAction, withdrawAction] : [borrowAction]
|
||||
|
||||
const msg: CreditManagerExecuteMsg = {
|
||||
update_credit_account: {
|
||||
account_id: options.accountId,
|
||||
actions: [{ borrow: options.coin }],
|
||||
actions,
|
||||
},
|
||||
}
|
||||
|
||||
@ -54,7 +63,9 @@ export default function createBroadcastSlice(
|
||||
|
||||
handleResponseMessages(
|
||||
response,
|
||||
`Borrowed ${formatAmountWithSymbol(options.coin)} to Account ${options.accountId}`,
|
||||
`Borrowed ${formatAmountWithSymbol(options.coin)} to ${
|
||||
options.borrowToWallet ? 'Wallet' : `Account ${options.accountId}`
|
||||
}`,
|
||||
)
|
||||
return !!response.result
|
||||
},
|
||||
|
@ -5,25 +5,26 @@
|
||||
* and run the @cosmwasm/ts-codegen generate command to regenerate this file.
|
||||
*/
|
||||
|
||||
import { CosmWasmClient, SigningCosmWasmClient, ExecuteResult } from '@cosmjs/cosmwasm-stargate'
|
||||
import { CosmWasmClient, ExecuteResult, SigningCosmWasmClient } from '@cosmjs/cosmwasm-stargate'
|
||||
import { Coin, StdFee } from '@cosmjs/amino'
|
||||
|
||||
import {
|
||||
InstantiateMsg,
|
||||
ExecuteMsg,
|
||||
OsmosisPriceSourceForString,
|
||||
ArrayOfPriceResponse,
|
||||
ArrayOfPriceSourceResponseForString,
|
||||
ConfigResponse,
|
||||
Decimal,
|
||||
Downtime,
|
||||
Identifier,
|
||||
OwnerUpdate,
|
||||
DowntimeDetector,
|
||||
ExecuteMsg,
|
||||
GeometricTwap,
|
||||
RedemptionRateForString,
|
||||
QueryMsg,
|
||||
ConfigResponse,
|
||||
Identifier,
|
||||
InstantiateMsg,
|
||||
OsmosisPriceSourceForString,
|
||||
OwnerUpdate,
|
||||
PriceResponse,
|
||||
PriceSourceResponseForString,
|
||||
ArrayOfPriceSourceResponseForString,
|
||||
ArrayOfPriceResponse,
|
||||
QueryMsg,
|
||||
RedemptionRateForString,
|
||||
} from './MarsOracleOsmosis.types'
|
||||
export interface MarsOracleOsmosisReadOnlyInterface {
|
||||
contractAddress: string
|
||||
|
@ -5,28 +5,29 @@
|
||||
* and run the @cosmwasm/ts-codegen generate command to regenerate this file.
|
||||
*/
|
||||
|
||||
import { UseQueryOptions, useQuery, useMutation, UseMutationOptions } from '@tanstack/react-query'
|
||||
import { useMutation, UseMutationOptions, useQuery, UseQueryOptions } from '@tanstack/react-query'
|
||||
import { ExecuteResult } from '@cosmjs/cosmwasm-stargate'
|
||||
import { StdFee, Coin } from '@cosmjs/amino'
|
||||
import { Coin, StdFee } from '@cosmjs/amino'
|
||||
|
||||
import {
|
||||
InstantiateMsg,
|
||||
ExecuteMsg,
|
||||
OsmosisPriceSourceForString,
|
||||
ArrayOfPriceResponse,
|
||||
ArrayOfPriceSourceResponseForString,
|
||||
ConfigResponse,
|
||||
Decimal,
|
||||
Downtime,
|
||||
Identifier,
|
||||
OwnerUpdate,
|
||||
DowntimeDetector,
|
||||
ExecuteMsg,
|
||||
GeometricTwap,
|
||||
RedemptionRateForString,
|
||||
QueryMsg,
|
||||
ConfigResponse,
|
||||
Identifier,
|
||||
InstantiateMsg,
|
||||
OsmosisPriceSourceForString,
|
||||
OwnerUpdate,
|
||||
PriceResponse,
|
||||
PriceSourceResponseForString,
|
||||
ArrayOfPriceSourceResponseForString,
|
||||
ArrayOfPriceResponse,
|
||||
QueryMsg,
|
||||
RedemptionRateForString,
|
||||
} from './MarsOracleOsmosis.types'
|
||||
import { MarsOracleOsmosisQueryClient, MarsOracleOsmosisClient } from './MarsOracleOsmosis.client'
|
||||
import { MarsOracleOsmosisClient, MarsOracleOsmosisQueryClient } from './MarsOracleOsmosis.client'
|
||||
export const marsOracleOsmosisQueryKeys = {
|
||||
contract: [
|
||||
{
|
||||
|
7
src/types/interfaces/store/broadcast.d.ts
vendored
7
src/types/interfaces/store/broadcast.d.ts
vendored
@ -12,7 +12,12 @@ interface BroadcastSlice {
|
||||
fee: StdFee
|
||||
funds?: Coin[]
|
||||
}) => Promise<BroadcastResult>
|
||||
borrow: (options: { fee: StdFee; accountId: string; coin: Coin }) => Promise<boolean>
|
||||
borrow: (options: {
|
||||
fee: StdFee
|
||||
accountId: string
|
||||
coin: Coin
|
||||
borrowToWallet: boolean
|
||||
}) => Promise<boolean>
|
||||
createAccount: (options: { fee: StdFee }) => Promise<string | null>
|
||||
deleteAccount: (options: { fee: StdFee; accountId: string }) => Promise<boolean>
|
||||
deposit: (options: { fee: StdFee; accountId: string; coin: Coin }) => Promise<boolean>
|
||||
|
Loading…
Reference in New Issue
Block a user