feat: lend and withdraw modals (#257)
* feat: lend/withdraw functionality * feat: addressed to pr discussions * rename: data hook members
This commit is contained in:
parent
f780de9d76
commit
2c399a2f16
@ -7,7 +7,7 @@ import { BN } from 'utils/helpers'
|
|||||||
const data: LendingMarketTableData = {
|
const data: LendingMarketTableData = {
|
||||||
asset: ASSETS[0],
|
asset: ASSETS[0],
|
||||||
marketDepositAmount: BN('890546916'),
|
marketDepositAmount: BN('890546916'),
|
||||||
accountDepositValue: BN('0.5498406009348686811'),
|
accountLentValue: BN('0.5498406009348686811'),
|
||||||
marketLiquidityAmount: BN('629396551'),
|
marketLiquidityAmount: BN('629396551'),
|
||||||
marketDepositCap: BN('2500000000000'),
|
marketDepositCap: BN('2500000000000'),
|
||||||
marketLiquidityRate: 0.017,
|
marketLiquidityRate: 0.017,
|
||||||
|
@ -3,9 +3,9 @@ import { CosmWasmClient } from '@cosmjs/cosmwasm-stargate'
|
|||||||
import { ENV } from 'constants/env'
|
import { ENV } from 'constants/env'
|
||||||
import { MarsAccountNftQueryClient } from 'types/generated/mars-account-nft/MarsAccountNft.client'
|
import { MarsAccountNftQueryClient } from 'types/generated/mars-account-nft/MarsAccountNft.client'
|
||||||
import { MarsCreditManagerQueryClient } from 'types/generated/mars-credit-manager/MarsCreditManager.client'
|
import { MarsCreditManagerQueryClient } from 'types/generated/mars-credit-manager/MarsCreditManager.client'
|
||||||
|
import { MarsIncentivesQueryClient } from 'types/generated/mars-incentives/MarsIncentives.client'
|
||||||
import { MarsMockOracleQueryClient } from 'types/generated/mars-mock-oracle/MarsMockOracle.client'
|
import { MarsMockOracleQueryClient } from 'types/generated/mars-mock-oracle/MarsMockOracle.client'
|
||||||
import { MarsMockRedBankQueryClient } from 'types/generated/mars-mock-red-bank/MarsMockRedBank.client'
|
import { MarsMockRedBankQueryClient } from 'types/generated/mars-mock-red-bank/MarsMockRedBank.client'
|
||||||
import { MarsMockRedBankReactQuery } from 'types/generated/mars-mock-red-bank/MarsMockRedBank.react-query'
|
|
||||||
import { MarsMockVaultQueryClient } from 'types/generated/mars-mock-vault/MarsMockVault.client'
|
import { MarsMockVaultQueryClient } from 'types/generated/mars-mock-vault/MarsMockVault.client'
|
||||||
import { MarsParamsQueryClient } from 'types/generated/mars-params/MarsParams.client'
|
import { MarsParamsQueryClient } from 'types/generated/mars-params/MarsParams.client'
|
||||||
|
|
||||||
@ -15,6 +15,7 @@ let _creditManagerQueryClient: MarsCreditManagerQueryClient
|
|||||||
let _oracleQueryClient: MarsMockOracleQueryClient
|
let _oracleQueryClient: MarsMockOracleQueryClient
|
||||||
let _redBankQueryClient: MarsMockRedBankQueryClient
|
let _redBankQueryClient: MarsMockRedBankQueryClient
|
||||||
let _paramsQueryClient: MarsParamsQueryClient
|
let _paramsQueryClient: MarsParamsQueryClient
|
||||||
|
let _incentivesQueryClient: MarsIncentivesQueryClient
|
||||||
|
|
||||||
const getClient = async () => {
|
const getClient = async () => {
|
||||||
try {
|
try {
|
||||||
@ -105,6 +106,19 @@ const getVaultQueryClient = async (address: string) => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const getIncentivesQueryClient = async () => {
|
||||||
|
try {
|
||||||
|
if (!_incentivesQueryClient) {
|
||||||
|
const client = await getClient()
|
||||||
|
_incentivesQueryClient = new MarsIncentivesQueryClient(client, ENV.ADDRESS_INCENTIVES)
|
||||||
|
}
|
||||||
|
|
||||||
|
return _incentivesQueryClient
|
||||||
|
} catch (error) {
|
||||||
|
throw error
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export {
|
export {
|
||||||
getClient,
|
getClient,
|
||||||
getAccountNftQueryClient,
|
getAccountNftQueryClient,
|
||||||
@ -113,4 +127,5 @@ export {
|
|||||||
getOracleQueryClient,
|
getOracleQueryClient,
|
||||||
getRedBankQueryClient,
|
getRedBankQueryClient,
|
||||||
getVaultQueryClient,
|
getVaultQueryClient,
|
||||||
|
getIncentivesQueryClient,
|
||||||
}
|
}
|
||||||
|
46
src/api/incentives/calculateAssetIncentivesApy.ts
Normal file
46
src/api/incentives/calculateAssetIncentivesApy.ts
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
import getMarket from 'api/markets/getMarket'
|
||||||
|
import getAssetIncentive from 'api/incentives/getAssetIncentive'
|
||||||
|
import getUnderlyingLiquidityAmount from 'api/markets/getMarketUnderlyingLiquidityAmount'
|
||||||
|
import { BN } from 'utils/helpers'
|
||||||
|
import { SECONDS_IN_A_YEAR } from 'utils/constants'
|
||||||
|
import getPrice from 'api/prices/getPrice'
|
||||||
|
import getMarsPrice from 'api/prices/getMarsPrice'
|
||||||
|
import { ASSETS } from 'constants/assets'
|
||||||
|
import { byDenom } from 'utils/array'
|
||||||
|
|
||||||
|
export default async function calculateAssetIncentivesApy(denom: string): Promise<number | null> {
|
||||||
|
try {
|
||||||
|
const [assetIncentive, market] = await Promise.all([getAssetIncentive(denom), getMarket(denom)])
|
||||||
|
|
||||||
|
if (!assetIncentive) return null
|
||||||
|
|
||||||
|
const [marketLiquidityAmount, assetPriceResponse, marsPrice] = await Promise.all([
|
||||||
|
getUnderlyingLiquidityAmount(market),
|
||||||
|
getPrice(denom),
|
||||||
|
getMarsPrice(),
|
||||||
|
])
|
||||||
|
|
||||||
|
const assetDecimals = (ASSETS.find(byDenom(denom)) as Asset).decimals
|
||||||
|
const marsDecimals = 6,
|
||||||
|
priceFeedDecimals = 6
|
||||||
|
|
||||||
|
const assetPrice = BN(assetPriceResponse.price).shiftedBy(assetDecimals - priceFeedDecimals)
|
||||||
|
const marketLiquidityValue = BN(marketLiquidityAmount)
|
||||||
|
.shiftedBy(-assetDecimals)
|
||||||
|
.multipliedBy(assetPrice)
|
||||||
|
|
||||||
|
const marketReturns = BN(market.liquidityRate).multipliedBy(marketLiquidityValue)
|
||||||
|
const annualEmission = BN(assetIncentive.emission_per_second)
|
||||||
|
.multipliedBy(SECONDS_IN_A_YEAR)
|
||||||
|
.shiftedBy(-marsDecimals)
|
||||||
|
.multipliedBy(marsPrice)
|
||||||
|
|
||||||
|
const totalAnnualReturnsValue = annualEmission.plus(marketReturns)
|
||||||
|
const incentivesApy = totalAnnualReturnsValue.dividedBy(marketLiquidityValue).multipliedBy(100)
|
||||||
|
|
||||||
|
return incentivesApy.toNumber()
|
||||||
|
} catch (ex) {
|
||||||
|
console.error(ex)
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
}
|
27
src/api/incentives/getAssetIncentive.ts
Normal file
27
src/api/incentives/getAssetIncentive.ts
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
import moment from 'moment'
|
||||||
|
|
||||||
|
import { getIncentivesQueryClient } from 'api/cosmwasm-client'
|
||||||
|
import { AssetIncentiveResponse } from 'types/generated/mars-incentives/MarsIncentives.types'
|
||||||
|
|
||||||
|
export default async function getAssetIncentive(
|
||||||
|
denom: string,
|
||||||
|
): Promise<AssetIncentiveResponse | null> {
|
||||||
|
try {
|
||||||
|
const client = await getIncentivesQueryClient()
|
||||||
|
const assetIncentive = await client.assetIncentive({
|
||||||
|
denom,
|
||||||
|
})
|
||||||
|
|
||||||
|
const { duration, start_time } = assetIncentive
|
||||||
|
const isValid = moment(start_time + duration).isBefore(moment.now())
|
||||||
|
|
||||||
|
if (!isValid) {
|
||||||
|
throw 'Asset incentive duration is end.'
|
||||||
|
}
|
||||||
|
|
||||||
|
return assetIncentive
|
||||||
|
} catch (ex) {
|
||||||
|
console.error(ex)
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
}
|
14
src/api/markets/getMarket.ts
Normal file
14
src/api/markets/getMarket.ts
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
import { ENV } from 'constants/env'
|
||||||
|
import { resolveMarketResponse } from 'utils/resolvers'
|
||||||
|
import { getClient, getRedBankQueryClient } from 'api/cosmwasm-client'
|
||||||
|
|
||||||
|
export default async function getMarket(denom: string): Promise<Market> {
|
||||||
|
try {
|
||||||
|
const client = await getRedBankQueryClient()
|
||||||
|
const market = await client.market({ denom })
|
||||||
|
|
||||||
|
return resolveMarketResponse(market)
|
||||||
|
} catch (ex) {
|
||||||
|
throw ex
|
||||||
|
}
|
||||||
|
}
|
@ -1,17 +1,10 @@
|
|||||||
import getMarkets from 'api/markets/getMarkets'
|
import getMarkets from 'api/markets/getMarkets'
|
||||||
import { getRedBankQueryClient } from 'api/cosmwasm-client'
|
import getUnderlyingLiquidityAmount from 'api/markets/getMarketUnderlyingLiquidityAmount'
|
||||||
|
|
||||||
export default async function getMarketDeposits(): Promise<Coin[]> {
|
export default async function getMarketDeposits(): Promise<Coin[]> {
|
||||||
try {
|
try {
|
||||||
const markets: Market[] = await getMarkets()
|
const markets: Market[] = await getMarkets()
|
||||||
const redBankQueryClient = await getRedBankQueryClient()
|
const depositQueries = markets.map(getUnderlyingLiquidityAmount)
|
||||||
|
|
||||||
const depositQueries = markets.map((asset) =>
|
|
||||||
redBankQueryClient.underlyingLiquidityAmount({
|
|
||||||
denom: asset.denom,
|
|
||||||
amountScaled: asset.collateralTotalScaled,
|
|
||||||
}),
|
|
||||||
)
|
|
||||||
const depositsResults = await Promise.all(depositQueries)
|
const depositsResults = await Promise.all(depositQueries)
|
||||||
|
|
||||||
return depositsResults.map<Coin>((deposit, index) => ({
|
return depositsResults.map<Coin>((deposit, index) => ({
|
||||||
|
15
src/api/markets/getMarketUnderlyingLiquidityAmount.ts
Normal file
15
src/api/markets/getMarketUnderlyingLiquidityAmount.ts
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
import { getRedBankQueryClient } from 'api/cosmwasm-client'
|
||||||
|
|
||||||
|
export default async function getUnderlyingLiquidityAmount(market: Market): Promise<string> {
|
||||||
|
try {
|
||||||
|
const client = await getRedBankQueryClient()
|
||||||
|
const marketLiquidityAmount: string = await client.underlyingLiquidityAmount({
|
||||||
|
denom: market.denom,
|
||||||
|
amountScaled: market.collateralTotalScaled,
|
||||||
|
})
|
||||||
|
|
||||||
|
return marketLiquidityAmount
|
||||||
|
} catch (ex) {
|
||||||
|
throw ex
|
||||||
|
}
|
||||||
|
}
|
@ -1,18 +1,12 @@
|
|||||||
import { getEnabledMarketAssets } from 'utils/assets'
|
import { getEnabledMarketAssets } from 'utils/assets'
|
||||||
import { resolveMarketResponses } from 'utils/resolvers'
|
import getMarket from 'api/markets/getMarket'
|
||||||
import { getRedBankQueryClient } from 'api/cosmwasm-client'
|
|
||||||
|
|
||||||
export default async function getMarkets(): Promise<Market[]> {
|
export default async function getMarkets(): Promise<Market[]> {
|
||||||
try {
|
try {
|
||||||
const enabledAssets = getEnabledMarketAssets()
|
const enabledAssets = getEnabledMarketAssets()
|
||||||
const redBankQueryClient = await getRedBankQueryClient()
|
const marketQueries = enabledAssets.map((asset) => getMarket(asset.denom))
|
||||||
|
|
||||||
const marketQueries = enabledAssets.map((asset) =>
|
return await Promise.all(marketQueries)
|
||||||
redBankQueryClient.market({ denom: asset.denom }),
|
|
||||||
)
|
|
||||||
const marketResults = await Promise.all(marketQueries)
|
|
||||||
|
|
||||||
return resolveMarketResponses(marketResults)
|
|
||||||
} catch (ex) {
|
} catch (ex) {
|
||||||
throw ex
|
throw ex
|
||||||
}
|
}
|
||||||
|
45
src/api/prices/getMarsPrice.ts
Normal file
45
src/api/prices/getMarsPrice.ts
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
import { BN } from 'utils/helpers'
|
||||||
|
import getPrice from 'api/prices/getPrice'
|
||||||
|
|
||||||
|
const MARS_MAINNET_DENOM = 'ibc/573FCD90FACEE750F55A8864EF7D38265F07E5A9273FA0E8DAFD39951332B580'
|
||||||
|
const MARS_OSMO_POOL_URL = 'https://lcd-osmosis.blockapsis.com/osmosis/gamm/v1beta1/pools/907'
|
||||||
|
|
||||||
|
interface PoolToken {
|
||||||
|
denom: string
|
||||||
|
amount: string
|
||||||
|
}
|
||||||
|
|
||||||
|
interface PoolAsset {
|
||||||
|
token: PoolToken
|
||||||
|
weight: string
|
||||||
|
}
|
||||||
|
|
||||||
|
const findPoolAssetByTokenDenom = (assets: PoolAsset[], denom: string) =>
|
||||||
|
assets.find((a) => a.token.denom === denom)
|
||||||
|
|
||||||
|
async function getMarsPrice() {
|
||||||
|
const marsOsmoRate = await getMarsOsmoRate()
|
||||||
|
const osmoPrice = await getPrice('uosmo')
|
||||||
|
|
||||||
|
return marsOsmoRate.multipliedBy(osmoPrice.price)
|
||||||
|
}
|
||||||
|
|
||||||
|
const getMarsOsmoRate = async () => {
|
||||||
|
const resp = await fetch(MARS_OSMO_POOL_URL).then((res) => res.json())
|
||||||
|
const spotPrice = calculateSpotPrice(resp.pool.pool_assets)
|
||||||
|
|
||||||
|
return BN(1).dividedBy(spotPrice)
|
||||||
|
}
|
||||||
|
|
||||||
|
const calculateSpotPrice = (poolAssets: PoolAsset[]) => {
|
||||||
|
const assetIn = findPoolAssetByTokenDenom(poolAssets, MARS_MAINNET_DENOM) as PoolAsset
|
||||||
|
|
||||||
|
const assetOut = findPoolAssetByTokenDenom(poolAssets, 'uosmo') as PoolAsset
|
||||||
|
|
||||||
|
const numerator = BN(assetIn.token.amount).div(assetIn.weight)
|
||||||
|
const denominator = BN(assetOut.token.amount).div(assetOut.weight)
|
||||||
|
|
||||||
|
return numerator.dividedBy(denominator)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default getMarsPrice
|
@ -12,7 +12,7 @@ import Text from 'components/Text'
|
|||||||
import useToggle from 'hooks/useToggle'
|
import useToggle from 'hooks/useToggle'
|
||||||
import useStore from 'store'
|
import useStore from 'store'
|
||||||
import { calculateAccountDeposits } from 'utils/accounts'
|
import { calculateAccountDeposits } from 'utils/accounts'
|
||||||
import { hardcodedFee } from 'utils/contants'
|
import { hardcodedFee } from 'utils/constants'
|
||||||
import { BN } from 'utils/helpers'
|
import { BN } from 'utils/helpers'
|
||||||
import { getPage, getRoute } from 'utils/route'
|
import { getPage, getRoute } from 'utils/route'
|
||||||
import usePrices from 'hooks/usePrices'
|
import usePrices from 'hooks/usePrices'
|
||||||
|
@ -12,7 +12,7 @@ import Overlay from 'components/Overlay'
|
|||||||
import Text from 'components/Text'
|
import Text from 'components/Text'
|
||||||
import useToggle from 'hooks/useToggle'
|
import useToggle from 'hooks/useToggle'
|
||||||
import useStore from 'store'
|
import useStore from 'store'
|
||||||
import { hardcodedFee } from 'utils/contants'
|
import { hardcodedFee } from 'utils/constants'
|
||||||
import { isNumber } from 'utils/parsers'
|
import { isNumber } from 'utils/parsers'
|
||||||
|
|
||||||
const menuClasses = 'absolute isolate flex w-full flex-wrap scrollbar-hide'
|
const menuClasses = 'absolute isolate flex w-full flex-wrap scrollbar-hide'
|
||||||
|
10
src/components/Account/CurrentAccountSummary.tsx
Normal file
10
src/components/Account/CurrentAccountSummary.tsx
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
import useCurrentAccount from 'hooks/useCurrentAccount'
|
||||||
|
import AccountSummary from 'components/Account/AccountSummary'
|
||||||
|
|
||||||
|
function CurrentAccountSummary({ change }: { change?: AccountChange }) {
|
||||||
|
const account = useCurrentAccount()
|
||||||
|
|
||||||
|
return <AccountSummary account={account} change={change} />
|
||||||
|
}
|
||||||
|
|
||||||
|
export default CurrentAccountSummary
|
@ -11,7 +11,7 @@ import { ASSETS } from 'constants/assets'
|
|||||||
import useToggle from 'hooks/useToggle'
|
import useToggle from 'hooks/useToggle'
|
||||||
import useStore from 'store'
|
import useStore from 'store'
|
||||||
import { getAmount } from 'utils/accounts'
|
import { getAmount } from 'utils/accounts'
|
||||||
import { hardcodedFee } from 'utils/contants'
|
import { hardcodedFee } from 'utils/constants'
|
||||||
import { BN } from 'utils/helpers'
|
import { BN } from 'utils/helpers'
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
|
@ -4,6 +4,7 @@ import Text from 'components/Text'
|
|||||||
import { Tooltip } from 'components/Tooltip'
|
import { Tooltip } from 'components/Tooltip'
|
||||||
import ConditionalWrapper from 'hocs/ConditionalWrapper'
|
import ConditionalWrapper from 'hocs/ConditionalWrapper'
|
||||||
import useCurrentAccountDeposits from 'hooks/useCurrentAccountDeposits'
|
import useCurrentAccountDeposits from 'hooks/useCurrentAccountDeposits'
|
||||||
|
import useLendAndReclaimModal from 'hooks/useLendAndReclaimModal'
|
||||||
import { byDenom } from 'utils/array'
|
import { byDenom } from 'utils/array'
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
@ -14,18 +15,19 @@ const buttonClassnames = 'm-0 flex w-40 text-lg'
|
|||||||
const iconClassnames = 'ml-0 mr-1 w-4 h-4'
|
const iconClassnames = 'ml-0 mr-1 w-4 h-4'
|
||||||
|
|
||||||
function LendingActionButtons(props: Props) {
|
function LendingActionButtons(props: Props) {
|
||||||
const { asset, accountDepositValue } = props.data
|
const { asset, accountLentValue: accountLendValue } = props.data
|
||||||
const accountDeposits = useCurrentAccountDeposits()
|
const accountDeposits = useCurrentAccountDeposits()
|
||||||
|
const { openLend, openReclaim } = useLendAndReclaimModal()
|
||||||
const assetDepositAmount = accountDeposits.find(byDenom(asset.denom))?.amount
|
const assetDepositAmount = accountDeposits.find(byDenom(asset.denom))?.amount
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className='flex flex-row space-x-2'>
|
<div className='flex flex-row space-x-2'>
|
||||||
{accountDepositValue && (
|
{accountLendValue && (
|
||||||
<Button
|
<Button
|
||||||
leftIcon={<ArrowDownLine />}
|
leftIcon={<ArrowDownLine />}
|
||||||
iconClassName={iconClassnames}
|
iconClassName={iconClassnames}
|
||||||
color='secondary'
|
color='secondary'
|
||||||
onClick={() => alert('hello!')}
|
onClick={() => openReclaim(props.data)}
|
||||||
className={buttonClassnames}
|
className={buttonClassnames}
|
||||||
>
|
>
|
||||||
Withdraw
|
Withdraw
|
||||||
@ -50,7 +52,7 @@ function LendingActionButtons(props: Props) {
|
|||||||
iconClassName={iconClassnames}
|
iconClassName={iconClassnames}
|
||||||
disabled={!assetDepositAmount}
|
disabled={!assetDepositAmount}
|
||||||
color='secondary'
|
color='secondary'
|
||||||
onClick={() => alert('hello!')}
|
onClick={() => openLend(props.data)}
|
||||||
className={buttonClassnames}
|
className={buttonClassnames}
|
||||||
>
|
>
|
||||||
Lend
|
Lend
|
||||||
|
@ -22,7 +22,7 @@ interface Props {
|
|||||||
function LendingMarketsTable(props: Props) {
|
function LendingMarketsTable(props: Props) {
|
||||||
const { title, data } = props
|
const { title, data } = props
|
||||||
const { symbol: displayCurrencySymbol } = useDisplayCurrencyPrice()
|
const { symbol: displayCurrencySymbol } = useDisplayCurrencyPrice()
|
||||||
const shouldShowAccountDeposit = !!data[0]?.accountDepositValue
|
const shouldShowAccountDeposit = !!data[0]?.accountLentValue
|
||||||
|
|
||||||
const rowRenderer = (row: Row<LendingMarketTableData>, table: Table<LendingMarketTableData>) => {
|
const rowRenderer = (row: Row<LendingMarketTableData>, table: Table<LendingMarketTableData>) => {
|
||||||
return (
|
return (
|
||||||
@ -64,9 +64,7 @@ function LendingMarketsTable(props: Props) {
|
|||||||
accessorKey: 'accountDepositValue',
|
accessorKey: 'accountDepositValue',
|
||||||
header: 'Deposited',
|
header: 'Deposited',
|
||||||
cell: ({ row }) => {
|
cell: ({ row }) => {
|
||||||
const accountDepositValue = (
|
const accountDepositValue = (row.original.accountLentValue as BigNumber).toNumber()
|
||||||
row.original.accountDepositValue as BigNumber
|
|
||||||
).toNumber()
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<FormattedNumber
|
<FormattedNumber
|
||||||
|
@ -38,8 +38,10 @@ export default function Modal(props: Props) {
|
|||||||
// close dialog on unmount
|
// close dialog on unmount
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const dialog = ref.current
|
const dialog = ref.current
|
||||||
dialog?.removeAttribute('open')
|
return () => {
|
||||||
return () => dialog.close()
|
dialog.removeAttribute('open')
|
||||||
|
dialog.close()
|
||||||
|
}
|
||||||
}, [])
|
}, [])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
97
src/components/Modals/AssetAmountSelectActionModal/index.tsx
Normal file
97
src/components/Modals/AssetAmountSelectActionModal/index.tsx
Normal file
@ -0,0 +1,97 @@
|
|||||||
|
import Image from 'next/image'
|
||||||
|
import { useState } from 'react'
|
||||||
|
|
||||||
|
import Button from 'components/Button'
|
||||||
|
import Card from 'components/Card'
|
||||||
|
import Divider from 'components/Divider'
|
||||||
|
import { ArrowRight } from 'components/Icons'
|
||||||
|
import Modal from 'components/Modal'
|
||||||
|
import Text from 'components/Text'
|
||||||
|
import TokenInputWithSlider from 'components/TokenInputWithSlider'
|
||||||
|
import { BN } from 'utils/helpers'
|
||||||
|
import { byDenom } from 'utils/array'
|
||||||
|
import CurrentAccountSummary from 'components/Account/CurrentAccountSummary'
|
||||||
|
import AssetImage from 'components/AssetImage'
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
asset: Asset
|
||||||
|
title: string
|
||||||
|
isOpen: boolean
|
||||||
|
coinBalances: Coin[]
|
||||||
|
contentHeader?: JSX.Element
|
||||||
|
actionButtonText: string
|
||||||
|
showLoaderInButton: boolean
|
||||||
|
accountSummaryChange?: AccountChange
|
||||||
|
onClose: () => void
|
||||||
|
onChange: (value: BigNumber) => void
|
||||||
|
onAction: (value: BigNumber) => void
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function AssetAmountSelectActionModal(props: Props) {
|
||||||
|
const {
|
||||||
|
asset,
|
||||||
|
title,
|
||||||
|
isOpen,
|
||||||
|
coinBalances,
|
||||||
|
contentHeader = null,
|
||||||
|
actionButtonText,
|
||||||
|
showLoaderInButton,
|
||||||
|
accountSummaryChange,
|
||||||
|
onClose,
|
||||||
|
onChange,
|
||||||
|
onAction,
|
||||||
|
} = 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 handleActionClick = () => {
|
||||||
|
onAction(amount)
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Modal
|
||||||
|
open={isOpen}
|
||||||
|
onClose={onClose}
|
||||||
|
header={
|
||||||
|
<span className='flex items-center gap-4 px-4'>
|
||||||
|
<AssetImage size={24} asset={asset} />
|
||||||
|
<Text>{title}</Text>
|
||||||
|
</span>
|
||||||
|
}
|
||||||
|
headerClassName='gradient-header pl-2 pr-2.5 py-2.5 border-b-white/5 border-b'
|
||||||
|
contentClassName='flex flex-col min-h-[400px]'
|
||||||
|
>
|
||||||
|
{contentHeader}
|
||||||
|
<div className='flex flex-grow items-start gap-6 p-6'>
|
||||||
|
<Card
|
||||||
|
className='flex flex-grow bg-white/5 p-4'
|
||||||
|
contentClassName='gap-6 flex flex-col justify-between h-full'
|
||||||
|
>
|
||||||
|
<TokenInputWithSlider
|
||||||
|
asset={asset}
|
||||||
|
onChange={handleAmountChange}
|
||||||
|
amount={amount}
|
||||||
|
max={maxAmount}
|
||||||
|
hasSelect
|
||||||
|
maxText='Max'
|
||||||
|
/>
|
||||||
|
<Divider />
|
||||||
|
<Button
|
||||||
|
onClick={handleActionClick}
|
||||||
|
showProgressIndicator={showLoaderInButton}
|
||||||
|
disabled={!amount.toNumber()}
|
||||||
|
className='w-full'
|
||||||
|
text={actionButtonText}
|
||||||
|
rightIcon={<ArrowRight />}
|
||||||
|
/>
|
||||||
|
</Card>
|
||||||
|
<CurrentAccountSummary change={accountSummaryChange} />
|
||||||
|
</div>
|
||||||
|
</Modal>
|
||||||
|
)
|
||||||
|
}
|
@ -14,7 +14,7 @@ import { ASSETS } from 'constants/assets'
|
|||||||
import useCurrentAccount from 'hooks/useCurrentAccount'
|
import useCurrentAccount from 'hooks/useCurrentAccount'
|
||||||
import useToggle from 'hooks/useToggle'
|
import useToggle from 'hooks/useToggle'
|
||||||
import useStore from 'store'
|
import useStore from 'store'
|
||||||
import { hardcodedFee } from 'utils/contants'
|
import { hardcodedFee } from 'utils/constants'
|
||||||
import { formatPercent, formatValue } from 'utils/formatters'
|
import { formatPercent, formatValue } from 'utils/formatters'
|
||||||
import { BN } from 'utils/helpers'
|
import { BN } from 'utils/helpers'
|
||||||
import AssetImage from 'components/AssetImage'
|
import AssetImage from 'components/AssetImage'
|
||||||
|
@ -10,7 +10,7 @@ import TokenInputWithSlider from 'components/TokenInputWithSlider'
|
|||||||
import useToggle from 'hooks/useToggle'
|
import useToggle from 'hooks/useToggle'
|
||||||
import useStore from 'store'
|
import useStore from 'store'
|
||||||
import { getAmount } from 'utils/accounts'
|
import { getAmount } from 'utils/accounts'
|
||||||
import { hardcodedFee } from 'utils/contants'
|
import { hardcodedFee } from 'utils/constants'
|
||||||
import { BN } from 'utils/helpers'
|
import { BN } from 'utils/helpers'
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
|
61
src/components/Modals/LendAndReclaim/DetailsHeader.tsx
Normal file
61
src/components/Modals/LendAndReclaim/DetailsHeader.tsx
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
import DisplayCurrency from 'components/DisplayCurrency'
|
||||||
|
import TitleAndSubCell from 'components/TitleAndSubCell'
|
||||||
|
import { FormattedNumber } from 'components/FormattedNumber'
|
||||||
|
import useAssetIncentivesApy from 'hooks/useAssetIncentiveApy'
|
||||||
|
import useCurrentWalletBalance from 'hooks/useCurrentWalletBalance'
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
data: LendingMarketTableData
|
||||||
|
}
|
||||||
|
|
||||||
|
function DetailsHeader({ data }: Props) {
|
||||||
|
const { asset, marketDepositCap, accountLentAmount: accountLendAmount } = data
|
||||||
|
const { data: assetApy } = useAssetIncentivesApy(asset.denom)
|
||||||
|
const balanceInWallet = useCurrentWalletBalance(asset.denom)
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className='flex gap-6 border-b border-b-white/5 px-6 py-4 gradient-header'>
|
||||||
|
{assetApy && (
|
||||||
|
<>
|
||||||
|
<TitleAndSubCell
|
||||||
|
title={
|
||||||
|
<>
|
||||||
|
<FormattedNumber amount={assetApy} options={{ suffix: '%' }} />
|
||||||
|
<FormattedNumber
|
||||||
|
className='ml-2 text-xs'
|
||||||
|
amount={assetApy / 365}
|
||||||
|
options={{ suffix: '%/day' }}
|
||||||
|
/>
|
||||||
|
</>
|
||||||
|
}
|
||||||
|
sub={'APY'}
|
||||||
|
/>
|
||||||
|
<div className='h-100 w-[1px] bg-white/10'></div>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
{accountLendAmount && (
|
||||||
|
<>
|
||||||
|
<TitleAndSubCell
|
||||||
|
title={<DisplayCurrency coin={{ denom: asset.denom, amount: accountLendAmount }} />}
|
||||||
|
sub={'Deposited'}
|
||||||
|
/>
|
||||||
|
<div className='h-100 w-[1px] bg-white/10'></div>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
{balanceInWallet && (
|
||||||
|
<>
|
||||||
|
<TitleAndSubCell title={<DisplayCurrency coin={balanceInWallet} />} sub={'In Wallet'} />
|
||||||
|
<div className='h-100 w-[1px] bg-white/10'></div>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
<TitleAndSubCell
|
||||||
|
title={
|
||||||
|
<DisplayCurrency coin={{ denom: asset.denom, amount: marketDepositCap.toString() }} />
|
||||||
|
}
|
||||||
|
sub={'Deposit Cap'}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default DetailsHeader
|
80
src/components/Modals/LendAndReclaim/index.tsx
Normal file
80
src/components/Modals/LendAndReclaim/index.tsx
Normal file
@ -0,0 +1,80 @@
|
|||||||
|
import { useState } from 'react'
|
||||||
|
|
||||||
|
import useStore from 'store'
|
||||||
|
import useToggle from 'hooks/useToggle'
|
||||||
|
import { hardcodedFee } from 'utils/constants'
|
||||||
|
import useCurrentAccount from 'hooks/useCurrentAccount'
|
||||||
|
import useLendAndReclaimModal from 'hooks/useLendAndReclaimModal'
|
||||||
|
import DetailsHeader from 'components/Modals/LendAndReclaim/DetailsHeader'
|
||||||
|
import AssetAmountSelectActionModal from 'components/Modals/AssetAmountSelectActionModal'
|
||||||
|
|
||||||
|
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)
|
||||||
|
const currentAccount = useCurrentAccount()
|
||||||
|
const { config, close } = useLendAndReclaimModal()
|
||||||
|
const [isConfirming, setIsConfirming] = useToggle()
|
||||||
|
const [accountChange, setAccountChange] = useState<AccountChange | undefined>()
|
||||||
|
|
||||||
|
if (!config || !currentAccount) return null
|
||||||
|
|
||||||
|
const { data, action } = config
|
||||||
|
const { asset } = data
|
||||||
|
|
||||||
|
const isLendAction = action === 'lend'
|
||||||
|
const actionText = isLendAction ? 'Lend' : 'Withdraw'
|
||||||
|
const coinBalances = currentAccount[isLendAction ? 'deposits' : 'lends'] ?? []
|
||||||
|
|
||||||
|
const handleAmountChange = (value: BigNumber) => {
|
||||||
|
setAccountChange(getAccountChange(isLendAction, value, asset.denom))
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleAction = async (value: BigNumber) => {
|
||||||
|
setIsConfirming(true)
|
||||||
|
|
||||||
|
const options = {
|
||||||
|
fee: hardcodedFee,
|
||||||
|
accountId: currentAccount.id,
|
||||||
|
coin: {
|
||||||
|
denom: asset.denom,
|
||||||
|
amount: value.toString(),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
await (isLendAction ? lend : reclaim)(options)
|
||||||
|
|
||||||
|
setIsConfirming(false)
|
||||||
|
close()
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<AssetAmountSelectActionModal
|
||||||
|
asset={asset}
|
||||||
|
isOpen={true}
|
||||||
|
contentHeader={<DetailsHeader data={data} />}
|
||||||
|
coinBalances={coinBalances}
|
||||||
|
actionButtonText={actionText}
|
||||||
|
showLoaderInButton={isConfirming}
|
||||||
|
accountSummaryChange={accountChange}
|
||||||
|
title={`${actionText} ${asset.symbol}`}
|
||||||
|
onClose={close}
|
||||||
|
onAction={handleAction}
|
||||||
|
onChange={handleAmountChange}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default LendAndReclaimModal
|
@ -3,15 +3,18 @@ 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'
|
||||||
|
|
||||||
export default function ModalsContainer() {
|
export default function ModalsContainer() {
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
|
<VaultModal />
|
||||||
<BorrowModal />
|
<BorrowModal />
|
||||||
<FundAndWithdrawModal />
|
<FundAndWithdrawModal />
|
||||||
<VaultModal />
|
<VaultModal />
|
||||||
<AddVaultBorrowAssetsModal />
|
<AddVaultBorrowAssetsModal />
|
||||||
<UnlockModal />
|
<UnlockModal />
|
||||||
|
<LendAndReclaimModal />
|
||||||
</>
|
</>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
|
import { hardcodedFee } from 'utils/constants'
|
||||||
import Button from 'components/Button'
|
import Button from 'components/Button'
|
||||||
import { Enter } from 'components/Icons'
|
import { Enter } from 'components/Icons'
|
||||||
import Text from 'components/Text'
|
import Text from 'components/Text'
|
||||||
import useStore from 'store'
|
import useStore from 'store'
|
||||||
import { hardcodedFee } from 'utils/contants'
|
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
depositedVault: DepositedVault
|
depositedVault: DepositedVault
|
||||||
|
@ -24,7 +24,7 @@ export default function TokenInputWithSlider(props: Props) {
|
|||||||
const [percentage, setPercentage] = useState(0)
|
const [percentage, setPercentage] = useState(0)
|
||||||
|
|
||||||
function onChangeSlider(percentage: number) {
|
function onChangeSlider(percentage: number) {
|
||||||
const newAmount = BN(percentage).div(100).times(props.max)
|
const newAmount = BN(percentage).div(100).times(props.max).integerValue()
|
||||||
setPercentage(percentage)
|
setPercentage(percentage)
|
||||||
setAmount(newAmount)
|
setAmount(newAmount)
|
||||||
props.onChange(newAmount)
|
props.onChange(newAmount)
|
||||||
|
7
src/hooks/useAssetIncentiveApy.ts
Normal file
7
src/hooks/useAssetIncentiveApy.ts
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
import useSWR from 'swr'
|
||||||
|
|
||||||
|
import calculateAssetIncentivesApy from 'api/incentives/calculateAssetIncentivesApy'
|
||||||
|
|
||||||
|
export default function useAssetIncentivesApy(denom: string) {
|
||||||
|
return useSWR(`assetIncentiveApy-${denom}`, () => calculateAssetIncentivesApy(denom))
|
||||||
|
}
|
6
src/hooks/useCurrentAccountLends.ts
Normal file
6
src/hooks/useCurrentAccountLends.ts
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
import useCurrentAccount from 'hooks/useCurrentAccount'
|
||||||
|
|
||||||
|
export default function useCurrentAccountLends() {
|
||||||
|
const account = useCurrentAccount()
|
||||||
|
return account?.lends ?? []
|
||||||
|
}
|
12
src/hooks/useCurrentWalletBalance.ts
Normal file
12
src/hooks/useCurrentWalletBalance.ts
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
import useStore from 'store'
|
||||||
|
import useWalletBalances from 'hooks/useWalletBalances'
|
||||||
|
import { byDenom } from 'utils/array'
|
||||||
|
|
||||||
|
function useCurrentWalletBalance(denom: string) {
|
||||||
|
const address = useStore((s) => s.address)
|
||||||
|
const { data: walletBalances } = useWalletBalances(address)
|
||||||
|
|
||||||
|
return walletBalances.find(byDenom(denom))
|
||||||
|
}
|
||||||
|
|
||||||
|
export default useCurrentWalletBalance
|
27
src/hooks/useLendAndReclaimModal.ts
Normal file
27
src/hooks/useLendAndReclaimModal.ts
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
import { useCallback } from 'react'
|
||||||
|
|
||||||
|
import useStore from 'store'
|
||||||
|
|
||||||
|
function useLendAndReclaimModal() {
|
||||||
|
const config = useStore((s) => s.lendAndReclaimModal)
|
||||||
|
|
||||||
|
const open = useCallback((action: LendAndReclaimModalAction, data: LendingMarketTableData) => {
|
||||||
|
const _config: LendAndReclaimModalConfig = {
|
||||||
|
action,
|
||||||
|
data,
|
||||||
|
}
|
||||||
|
|
||||||
|
useStore.setState({ lendAndReclaimModal: _config })
|
||||||
|
}, [])
|
||||||
|
|
||||||
|
const close = useCallback(() => {
|
||||||
|
useStore.setState({ lendAndReclaimModal: null })
|
||||||
|
}, [])
|
||||||
|
|
||||||
|
const openLend = useCallback((data: LendingMarketTableData) => open('lend', data), [open])
|
||||||
|
const openReclaim = useCallback((data: LendingMarketTableData) => open('reclaim', data), [open])
|
||||||
|
|
||||||
|
return { config, openLend, openReclaim, close }
|
||||||
|
}
|
||||||
|
|
||||||
|
export default useLendAndReclaimModal
|
@ -7,36 +7,36 @@ import useMarketDeposits from 'hooks/useMarketDeposits'
|
|||||||
import useMarketLiquidities from 'hooks/useMarketLiquidities'
|
import useMarketLiquidities from 'hooks/useMarketLiquidities'
|
||||||
import useDisplayCurrencyPrice from 'hooks/useDisplayCurrencyPrice'
|
import useDisplayCurrencyPrice from 'hooks/useDisplayCurrencyPrice'
|
||||||
import useDepositEnabledMarkets from 'hooks/useDepositEnabledMarkets'
|
import useDepositEnabledMarkets from 'hooks/useDepositEnabledMarkets'
|
||||||
import useCurrentAccountDeposits from 'hooks/useCurrentAccountDeposits'
|
import useCurrentAccountLends from 'hooks/useCurrentAccountLends'
|
||||||
|
|
||||||
function useLendingMarketAssetsTableData(): {
|
function useLendingMarketAssetsTableData(): {
|
||||||
lentAssets: LendingMarketTableData[]
|
accountLentAssets: LendingMarketTableData[]
|
||||||
availableAssets: LendingMarketTableData[]
|
availableAssets: LendingMarketTableData[]
|
||||||
} {
|
} {
|
||||||
const markets = useDepositEnabledMarkets()
|
const markets = useDepositEnabledMarkets()
|
||||||
const accountDeposits = useCurrentAccountDeposits()
|
const accountLentAmounts = useCurrentAccountLends()
|
||||||
// TODO: replace market deposits with account.lends when credit manager contract has lend feature
|
|
||||||
const { data: marketDeposits } = useMarketDeposits()
|
const { data: marketDeposits } = useMarketDeposits()
|
||||||
const { data: marketLiquidities } = useMarketLiquidities()
|
const { data: marketLiquidities } = useMarketLiquidities()
|
||||||
const { convertAmount } = useDisplayCurrencyPrice()
|
const { convertAmount } = useDisplayCurrencyPrice()
|
||||||
|
|
||||||
return useMemo(() => {
|
return useMemo(() => {
|
||||||
const lentAssets: LendingMarketTableData[] = [],
|
const accountLentAssets: LendingMarketTableData[] = [],
|
||||||
availableAssets: LendingMarketTableData[] = []
|
availableAssets: LendingMarketTableData[] = []
|
||||||
|
|
||||||
markets.forEach(({ denom, depositCap, liquidityRate, liquidationThreshold, maxLtv }) => {
|
markets.forEach(({ denom, depositCap, liquidityRate, liquidationThreshold, maxLtv }) => {
|
||||||
const asset = getAssetByDenom(denom) as Asset
|
const asset = getAssetByDenom(denom) as Asset
|
||||||
const marketDepositAmount = BN(marketDeposits.find(byDenom(denom))?.amount ?? 0)
|
const marketDepositAmount = BN(marketDeposits.find(byDenom(denom))?.amount ?? 0)
|
||||||
const marketLiquidityAmount = BN(marketLiquidities.find(byDenom(denom))?.amount ?? 0)
|
const marketLiquidityAmount = BN(marketLiquidities.find(byDenom(denom))?.amount ?? 0)
|
||||||
const accountDepositAmount = accountDeposits.find(byDenom(denom))?.amount
|
const accountLentAmount = accountLentAmounts.find(byDenom(denom))?.amount
|
||||||
const accountDepositValue = accountDepositAmount
|
const accountLentValue = accountLentAmount
|
||||||
? convertAmount(asset, accountDepositAmount)
|
? convertAmount(asset, accountLentAmount)
|
||||||
: undefined
|
: undefined
|
||||||
|
|
||||||
const lendingMarketAsset: LendingMarketTableData = {
|
const lendingMarketAsset: LendingMarketTableData = {
|
||||||
asset,
|
asset,
|
||||||
marketDepositAmount,
|
marketDepositAmount,
|
||||||
accountDepositValue,
|
accountLentValue,
|
||||||
|
accountLentAmount,
|
||||||
marketLiquidityAmount,
|
marketLiquidityAmount,
|
||||||
marketDepositCap: BN(depositCap),
|
marketDepositCap: BN(depositCap),
|
||||||
marketLiquidityRate: liquidityRate,
|
marketLiquidityRate: liquidityRate,
|
||||||
@ -44,13 +44,13 @@ function useLendingMarketAssetsTableData(): {
|
|||||||
marketMaxLtv: maxLtv,
|
marketMaxLtv: maxLtv,
|
||||||
}
|
}
|
||||||
|
|
||||||
;(lendingMarketAsset.accountDepositValue ? lentAssets : availableAssets).push(
|
;(lendingMarketAsset.accountLentValue ? accountLentAssets : availableAssets).push(
|
||||||
lendingMarketAsset,
|
lendingMarketAsset,
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
return { lentAssets, availableAssets }
|
return { accountLentAssets, availableAssets }
|
||||||
}, [markets, marketDeposits, marketLiquidities, accountDeposits, convertAmount])
|
}, [markets, marketDeposits, marketLiquidities, accountLentAmounts, convertAmount])
|
||||||
}
|
}
|
||||||
|
|
||||||
export default useLendingMarketAssetsTableData
|
export default useLendingMarketAssetsTableData
|
||||||
|
@ -5,5 +5,6 @@ import getWalletBalances from 'api/wallets/getWalletBalances'
|
|||||||
export default function useWalletBalances(address?: string) {
|
export default function useWalletBalances(address?: string) {
|
||||||
return useSWR(`walletBalances${address}`, () => getWalletBalances(address || ''), {
|
return useSWR(`walletBalances${address}`, () => getWalletBalances(address || ''), {
|
||||||
isPaused: () => !address,
|
isPaused: () => !address,
|
||||||
|
fallbackData: [],
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -3,12 +3,12 @@ import LendingMarketsTable from 'components/Earn/Lend/LendingMarketsTable'
|
|||||||
import useLendingMarketAssetsTableData from 'hooks/useLendingMarketAssetsTableData'
|
import useLendingMarketAssetsTableData from 'hooks/useLendingMarketAssetsTableData'
|
||||||
|
|
||||||
export default function LendPage() {
|
export default function LendPage() {
|
||||||
const { lentAssets, availableAssets } = useLendingMarketAssetsTableData()
|
const { accountLentAssets, availableAssets } = useLendingMarketAssetsTableData()
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Tab />
|
<Tab />
|
||||||
<LendingMarketsTable data={lentAssets} title='Lent Assets' />
|
<LendingMarketsTable data={accountLentAssets} title='Lent Assets' />
|
||||||
<LendingMarketsTable data={availableAssets} title='Available Markets' />
|
<LendingMarketsTable data={availableAssets} title='Available Markets' />
|
||||||
</>
|
</>
|
||||||
)
|
)
|
||||||
|
@ -6,11 +6,34 @@ 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'
|
||||||
|
|
||||||
export default function createBroadcastSlice(
|
export default function createBroadcastSlice(
|
||||||
set: SetState<Store>,
|
set: SetState<Store>,
|
||||||
get: GetState<Store>,
|
get: GetState<Store>,
|
||||||
): BroadcastSlice {
|
): BroadcastSlice {
|
||||||
|
const handleResponseMessages = (
|
||||||
|
response: BroadcastResult,
|
||||||
|
successMessage: string,
|
||||||
|
errorMessage?: string,
|
||||||
|
) => {
|
||||||
|
if (response.result?.response.code === 0) {
|
||||||
|
set({
|
||||||
|
toast: {
|
||||||
|
message: successMessage,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
const error = response.error ? response.error : response.result?.rawLogs
|
||||||
|
set({
|
||||||
|
toast: {
|
||||||
|
message: errorMessage ?? `Transaction failed: ${error}`,
|
||||||
|
isError: true,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
toast: null,
|
toast: null,
|
||||||
borrow: async (options: { fee: StdFee; accountId: string; coin: Coin }) => {
|
borrow: async (options: { fee: StdFee; accountId: string; coin: Coin }) => {
|
||||||
@ -23,24 +46,10 @@ export default function createBroadcastSlice(
|
|||||||
|
|
||||||
const response = await get().executeMsg({ msg, fee: options.fee })
|
const response = await get().executeMsg({ msg, fee: options.fee })
|
||||||
|
|
||||||
if (response.result?.response.code === 0) {
|
handleResponseMessages(
|
||||||
set({
|
response,
|
||||||
toast: {
|
`Borrowed ${formatAmountWithSymbol(options.coin)} to Account ${options.accountId}`,
|
||||||
message: `Borrowed ${formatAmountWithSymbol(options.coin)} to Account ${
|
)
|
||||||
options.accountId
|
|
||||||
}`,
|
|
||||||
},
|
|
||||||
})
|
|
||||||
} else {
|
|
||||||
const error = response.error ? response.error : response.result?.rawLogs
|
|
||||||
set({
|
|
||||||
toast: {
|
|
||||||
message: `Transaction failed: ${error}`,
|
|
||||||
isError: true,
|
|
||||||
},
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
return !!response.result
|
return !!response.result
|
||||||
},
|
},
|
||||||
createAccount: async (options: { fee: StdFee }) => {
|
createAccount: async (options: { fee: StdFee }) => {
|
||||||
@ -76,16 +85,9 @@ export default function createBroadcastSlice(
|
|||||||
const response = await get().executeMsg({ msg, fee: options.fee })
|
const response = await get().executeMsg({ msg, fee: options.fee })
|
||||||
|
|
||||||
set({ deleteAccountModal: false })
|
set({ deleteAccountModal: false })
|
||||||
if (response.result) {
|
|
||||||
set({ toast: { message: `Account ${options.accountId} deleted` } })
|
handleResponseMessages(response, `Account ${options.accountId} deleted`)
|
||||||
} else {
|
|
||||||
set({
|
|
||||||
toast: {
|
|
||||||
message: response.error ?? `Transaction failed: ${response.error}`,
|
|
||||||
isError: true,
|
|
||||||
},
|
|
||||||
})
|
|
||||||
}
|
|
||||||
return !!response.result
|
return !!response.result
|
||||||
},
|
},
|
||||||
deposit: async (options: { fee: StdFee; accountId: string; coin: Coin }) => {
|
deposit: async (options: { fee: StdFee; accountId: string; coin: Coin }) => {
|
||||||
@ -101,22 +103,11 @@ export default function createBroadcastSlice(
|
|||||||
}
|
}
|
||||||
|
|
||||||
const response = await get().executeMsg({ msg, fee: options.fee, funds: [options.coin] })
|
const response = await get().executeMsg({ msg, fee: options.fee, funds: [options.coin] })
|
||||||
if (response.result) {
|
|
||||||
set({
|
handleResponseMessages(
|
||||||
toast: {
|
response,
|
||||||
message: `Deposited ${formatAmountWithSymbol(options.coin)} to Account ${
|
`Deposited ${formatAmountWithSymbol(options.coin)} to Account ${options.accountId}`,
|
||||||
options.accountId
|
)
|
||||||
}`,
|
|
||||||
},
|
|
||||||
})
|
|
||||||
} else {
|
|
||||||
set({
|
|
||||||
toast: {
|
|
||||||
message: response.error ?? `Transaction failed: ${response.error}`,
|
|
||||||
isError: true,
|
|
||||||
},
|
|
||||||
})
|
|
||||||
}
|
|
||||||
return !!response.result
|
return !!response.result
|
||||||
},
|
},
|
||||||
unlock: async (options: { fee: StdFee; vault: Vault; amount: string }) => {
|
unlock: async (options: { fee: StdFee; vault: Vault; amount: string }) => {
|
||||||
@ -133,20 +124,7 @@ export default function createBroadcastSlice(
|
|||||||
funds: [],
|
funds: [],
|
||||||
})
|
})
|
||||||
|
|
||||||
if (response.result) {
|
handleResponseMessages(response, `Requested unlock for ${options.vault.name}`)
|
||||||
set({
|
|
||||||
toast: {
|
|
||||||
message: `Requested unlock for ${options.vault.name}`,
|
|
||||||
},
|
|
||||||
})
|
|
||||||
} else {
|
|
||||||
set({
|
|
||||||
toast: {
|
|
||||||
message: response.error ?? `Request unlocked failed: ${response.error}`,
|
|
||||||
isError: true,
|
|
||||||
},
|
|
||||||
})
|
|
||||||
}
|
|
||||||
return !!response.result
|
return !!response.result
|
||||||
},
|
},
|
||||||
withdraw: async (options: { fee: StdFee; accountId: string; coin: Coin }) => {
|
withdraw: async (options: { fee: StdFee; accountId: string; coin: Coin }) => {
|
||||||
@ -162,22 +140,11 @@ export default function createBroadcastSlice(
|
|||||||
}
|
}
|
||||||
|
|
||||||
const response = await get().executeMsg({ msg, fee: options.fee })
|
const response = await get().executeMsg({ msg, fee: options.fee })
|
||||||
if (response.result) {
|
|
||||||
set({
|
handleResponseMessages(
|
||||||
toast: {
|
response,
|
||||||
message: `Withdrew ${formatAmountWithSymbol(options.coin)} from Account ${
|
`Withdrew ${formatAmountWithSymbol(options.coin)} from Account ${options.accountId}`,
|
||||||
options.accountId
|
)
|
||||||
}`,
|
|
||||||
},
|
|
||||||
})
|
|
||||||
} else {
|
|
||||||
set({
|
|
||||||
toast: {
|
|
||||||
message: response.error ?? `Transaction failed: ${response.error}`,
|
|
||||||
isError: true,
|
|
||||||
},
|
|
||||||
})
|
|
||||||
}
|
|
||||||
return !!response.result
|
return !!response.result
|
||||||
},
|
},
|
||||||
executeMsg: async (options: {
|
executeMsg: async (options: {
|
||||||
@ -239,22 +206,52 @@ export default function createBroadcastSlice(
|
|||||||
}
|
}
|
||||||
|
|
||||||
const response = await get().executeMsg({ msg, fee: options.fee, funds: [] })
|
const response = await get().executeMsg({ msg, fee: options.fee, funds: [] })
|
||||||
if (response.result?.response.code === 0) {
|
|
||||||
set({
|
handleResponseMessages(
|
||||||
toast: {
|
response,
|
||||||
message: `Repayed ${formatAmountWithSymbol(options.coin)} to Account ${
|
`Repayed ${formatAmountWithSymbol(options.coin)} to Account ${options.accountId}`,
|
||||||
options.accountId
|
)
|
||||||
}`,
|
return !!response.result
|
||||||
},
|
},
|
||||||
})
|
lend: async (options: { fee: StdFee; accountId: string; coin: Coin }) => {
|
||||||
} else {
|
const msg = {
|
||||||
set({
|
update_credit_account: {
|
||||||
toast: {
|
account_id: options.accountId,
|
||||||
message: response.error ?? `Transaction failed: ${response.error}`,
|
actions: [
|
||||||
isError: true,
|
{
|
||||||
},
|
lend: options.coin,
|
||||||
})
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const response = await get().executeMsg({ msg, fee: options.fee })
|
||||||
|
|
||||||
|
handleResponseMessages(
|
||||||
|
response,
|
||||||
|
`Successfully deposited ${formatAmountWithSymbol(options.coin)}`,
|
||||||
|
)
|
||||||
|
return !!response.result
|
||||||
|
},
|
||||||
|
reclaim: async (options: { fee: StdFee; accountId: string; coin: Coin }) => {
|
||||||
|
const reclaim = { denom: options.coin.denom, amount: { exact: BN(options.coin.amount) } }
|
||||||
|
const msg = {
|
||||||
|
update_credit_account: {
|
||||||
|
account_id: options.accountId,
|
||||||
|
actions: [
|
||||||
|
{
|
||||||
|
reclaim,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
const response = await get().executeMsg({ msg, fee: options.fee })
|
||||||
|
|
||||||
|
handleResponseMessages(
|
||||||
|
response,
|
||||||
|
`Successfully deposited ${formatAmountWithSymbol(options.coin)}`,
|
||||||
|
)
|
||||||
return !!response.result
|
return !!response.result
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
@ -9,6 +9,7 @@ export default function createModalSlice(set: SetState<ModalSlice>, get: GetStat
|
|||||||
fundAccountModal: false,
|
fundAccountModal: false,
|
||||||
fundAndWithdrawModal: null,
|
fundAndWithdrawModal: null,
|
||||||
unlockModal: null,
|
unlockModal: null,
|
||||||
|
lendAndReclaimModal: null,
|
||||||
vaultModal: null,
|
vaultModal: null,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
284
src/types/generated/mars-incentives/MarsIncentives.client.ts
Normal file
284
src/types/generated/mars-incentives/MarsIncentives.client.ts
Normal file
@ -0,0 +1,284 @@
|
|||||||
|
// @ts-nocheck
|
||||||
|
/**
|
||||||
|
* This file was automatically generated by @cosmwasm/ts-codegen@0.30.0.
|
||||||
|
* DO NOT MODIFY IT BY HAND. Instead, modify the source JSONSchema file,
|
||||||
|
* and run the @cosmwasm/ts-codegen generate command to regenerate this file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { CosmWasmClient, SigningCosmWasmClient, ExecuteResult } from '@cosmjs/cosmwasm-stargate'
|
||||||
|
import { Coin, StdFee } from '@cosmjs/amino'
|
||||||
|
import {
|
||||||
|
InstantiateMsg,
|
||||||
|
ExecuteMsg,
|
||||||
|
Uint128,
|
||||||
|
Addr,
|
||||||
|
OwnerUpdate,
|
||||||
|
QueryMsg,
|
||||||
|
Decimal,
|
||||||
|
AssetIncentiveResponse,
|
||||||
|
ArrayOfAssetIncentiveResponse,
|
||||||
|
ConfigResponse,
|
||||||
|
} from './MarsIncentives.types'
|
||||||
|
export interface MarsIncentivesReadOnlyInterface {
|
||||||
|
contractAddress: string
|
||||||
|
config: () => Promise<ConfigResponse>
|
||||||
|
assetIncentive: ({ denom }: { denom: string }) => Promise<AssetIncentiveResponse>
|
||||||
|
assetIncentives: ({
|
||||||
|
limit,
|
||||||
|
startAfter,
|
||||||
|
}: {
|
||||||
|
limit?: number
|
||||||
|
startAfter?: string
|
||||||
|
}) => Promise<ArrayOfAssetIncentiveResponse>
|
||||||
|
userUnclaimedRewards: ({ user }: { user: string }) => Promise<Uint128>
|
||||||
|
}
|
||||||
|
export class MarsIncentivesQueryClient implements MarsIncentivesReadOnlyInterface {
|
||||||
|
client: CosmWasmClient
|
||||||
|
contractAddress: string
|
||||||
|
|
||||||
|
constructor(client: CosmWasmClient, contractAddress: string) {
|
||||||
|
this.client = client
|
||||||
|
this.contractAddress = contractAddress
|
||||||
|
this.config = this.config.bind(this)
|
||||||
|
this.assetIncentive = this.assetIncentive.bind(this)
|
||||||
|
this.assetIncentives = this.assetIncentives.bind(this)
|
||||||
|
this.userUnclaimedRewards = this.userUnclaimedRewards.bind(this)
|
||||||
|
}
|
||||||
|
|
||||||
|
config = async (): Promise<ConfigResponse> => {
|
||||||
|
return this.client.queryContractSmart(this.contractAddress, {
|
||||||
|
config: {},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
assetIncentive = async ({ denom }: { denom: string }): Promise<AssetIncentiveResponse> => {
|
||||||
|
return this.client.queryContractSmart(this.contractAddress, {
|
||||||
|
asset_incentive: {
|
||||||
|
denom,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
assetIncentives = async ({
|
||||||
|
limit,
|
||||||
|
startAfter,
|
||||||
|
}: {
|
||||||
|
limit?: number
|
||||||
|
startAfter?: string
|
||||||
|
}): Promise<ArrayOfAssetIncentiveResponse> => {
|
||||||
|
return this.client.queryContractSmart(this.contractAddress, {
|
||||||
|
asset_incentives: {
|
||||||
|
limit,
|
||||||
|
start_after: startAfter,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
userUnclaimedRewards = async ({ user }: { user: string }): Promise<Uint128> => {
|
||||||
|
return this.client.queryContractSmart(this.contractAddress, {
|
||||||
|
user_unclaimed_rewards: {
|
||||||
|
user,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
export interface MarsIncentivesInterface extends MarsIncentivesReadOnlyInterface {
|
||||||
|
contractAddress: string
|
||||||
|
sender: string
|
||||||
|
setAssetIncentive: (
|
||||||
|
{
|
||||||
|
denom,
|
||||||
|
duration,
|
||||||
|
emissionPerSecond,
|
||||||
|
startTime,
|
||||||
|
}: {
|
||||||
|
denom: string
|
||||||
|
duration?: number
|
||||||
|
emissionPerSecond?: Uint128
|
||||||
|
startTime?: number
|
||||||
|
},
|
||||||
|
fee?: number | StdFee | 'auto',
|
||||||
|
memo?: string,
|
||||||
|
_funds?: Coin[],
|
||||||
|
) => Promise<ExecuteResult>
|
||||||
|
balanceChange: (
|
||||||
|
{
|
||||||
|
denom,
|
||||||
|
totalAmountScaledBefore,
|
||||||
|
userAddr,
|
||||||
|
userAmountScaledBefore,
|
||||||
|
}: {
|
||||||
|
denom: string
|
||||||
|
totalAmountScaledBefore: Uint128
|
||||||
|
userAddr: Addr
|
||||||
|
userAmountScaledBefore: Uint128
|
||||||
|
},
|
||||||
|
fee?: number | StdFee | 'auto',
|
||||||
|
memo?: string,
|
||||||
|
_funds?: Coin[],
|
||||||
|
) => Promise<ExecuteResult>
|
||||||
|
claimRewards: (
|
||||||
|
fee?: number | StdFee | 'auto',
|
||||||
|
memo?: string,
|
||||||
|
_funds?: Coin[],
|
||||||
|
) => Promise<ExecuteResult>
|
||||||
|
updateConfig: (
|
||||||
|
{
|
||||||
|
addressProvider,
|
||||||
|
marsDenom,
|
||||||
|
}: {
|
||||||
|
addressProvider?: string
|
||||||
|
marsDenom?: string
|
||||||
|
},
|
||||||
|
fee?: number | StdFee | 'auto',
|
||||||
|
memo?: string,
|
||||||
|
_funds?: Coin[],
|
||||||
|
) => Promise<ExecuteResult>
|
||||||
|
updateOwner: (
|
||||||
|
ownerUpdate: OwnerUpdate,
|
||||||
|
fee?: number | StdFee | 'auto',
|
||||||
|
memo?: string,
|
||||||
|
_funds?: Coin[],
|
||||||
|
) => Promise<ExecuteResult>
|
||||||
|
}
|
||||||
|
export class MarsIncentivesClient
|
||||||
|
extends MarsIncentivesQueryClient
|
||||||
|
implements MarsIncentivesInterface
|
||||||
|
{
|
||||||
|
client: SigningCosmWasmClient
|
||||||
|
sender: string
|
||||||
|
contractAddress: string
|
||||||
|
|
||||||
|
constructor(client: SigningCosmWasmClient, sender: string, contractAddress: string) {
|
||||||
|
super(client, contractAddress)
|
||||||
|
this.client = client
|
||||||
|
this.sender = sender
|
||||||
|
this.contractAddress = contractAddress
|
||||||
|
this.setAssetIncentive = this.setAssetIncentive.bind(this)
|
||||||
|
this.balanceChange = this.balanceChange.bind(this)
|
||||||
|
this.claimRewards = this.claimRewards.bind(this)
|
||||||
|
this.updateConfig = this.updateConfig.bind(this)
|
||||||
|
this.updateOwner = this.updateOwner.bind(this)
|
||||||
|
}
|
||||||
|
|
||||||
|
setAssetIncentive = async (
|
||||||
|
{
|
||||||
|
denom,
|
||||||
|
duration,
|
||||||
|
emissionPerSecond,
|
||||||
|
startTime,
|
||||||
|
}: {
|
||||||
|
denom: string
|
||||||
|
duration?: number
|
||||||
|
emissionPerSecond?: Uint128
|
||||||
|
startTime?: number
|
||||||
|
},
|
||||||
|
fee: number | StdFee | 'auto' = 'auto',
|
||||||
|
memo?: string,
|
||||||
|
_funds?: Coin[],
|
||||||
|
): Promise<ExecuteResult> => {
|
||||||
|
return await this.client.execute(
|
||||||
|
this.sender,
|
||||||
|
this.contractAddress,
|
||||||
|
{
|
||||||
|
set_asset_incentive: {
|
||||||
|
denom,
|
||||||
|
duration,
|
||||||
|
emission_per_second: emissionPerSecond,
|
||||||
|
start_time: startTime,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
fee,
|
||||||
|
memo,
|
||||||
|
_funds,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
balanceChange = async (
|
||||||
|
{
|
||||||
|
denom,
|
||||||
|
totalAmountScaledBefore,
|
||||||
|
userAddr,
|
||||||
|
userAmountScaledBefore,
|
||||||
|
}: {
|
||||||
|
denom: string
|
||||||
|
totalAmountScaledBefore: Uint128
|
||||||
|
userAddr: Addr
|
||||||
|
userAmountScaledBefore: Uint128
|
||||||
|
},
|
||||||
|
fee: number | StdFee | 'auto' = 'auto',
|
||||||
|
memo?: string,
|
||||||
|
_funds?: Coin[],
|
||||||
|
): Promise<ExecuteResult> => {
|
||||||
|
return await this.client.execute(
|
||||||
|
this.sender,
|
||||||
|
this.contractAddress,
|
||||||
|
{
|
||||||
|
balance_change: {
|
||||||
|
denom,
|
||||||
|
total_amount_scaled_before: totalAmountScaledBefore,
|
||||||
|
user_addr: userAddr,
|
||||||
|
user_amount_scaled_before: userAmountScaledBefore,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
fee,
|
||||||
|
memo,
|
||||||
|
_funds,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
claimRewards = async (
|
||||||
|
fee: number | StdFee | 'auto' = 'auto',
|
||||||
|
memo?: string,
|
||||||
|
_funds?: Coin[],
|
||||||
|
): Promise<ExecuteResult> => {
|
||||||
|
return await this.client.execute(
|
||||||
|
this.sender,
|
||||||
|
this.contractAddress,
|
||||||
|
{
|
||||||
|
claim_rewards: {},
|
||||||
|
},
|
||||||
|
fee,
|
||||||
|
memo,
|
||||||
|
_funds,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
updateConfig = async (
|
||||||
|
{
|
||||||
|
addressProvider,
|
||||||
|
marsDenom,
|
||||||
|
}: {
|
||||||
|
addressProvider?: string
|
||||||
|
marsDenom?: string
|
||||||
|
},
|
||||||
|
fee: number | StdFee | 'auto' = 'auto',
|
||||||
|
memo?: string,
|
||||||
|
_funds?: Coin[],
|
||||||
|
): Promise<ExecuteResult> => {
|
||||||
|
return await this.client.execute(
|
||||||
|
this.sender,
|
||||||
|
this.contractAddress,
|
||||||
|
{
|
||||||
|
update_config: {
|
||||||
|
address_provider: addressProvider,
|
||||||
|
mars_denom: marsDenom,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
fee,
|
||||||
|
memo,
|
||||||
|
_funds,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
updateOwner = async (
|
||||||
|
ownerUpdate: OwnerUpdate,
|
||||||
|
fee: number | StdFee | 'auto' = 'auto',
|
||||||
|
memo?: string,
|
||||||
|
_funds?: Coin[],
|
||||||
|
): Promise<ExecuteResult> => {
|
||||||
|
return await this.client.execute(
|
||||||
|
this.sender,
|
||||||
|
this.contractAddress,
|
||||||
|
{
|
||||||
|
update_owner: ownerUpdate,
|
||||||
|
},
|
||||||
|
fee,
|
||||||
|
memo,
|
||||||
|
_funds,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,254 @@
|
|||||||
|
// @ts-nocheck
|
||||||
|
/**
|
||||||
|
* This file was automatically generated by @cosmwasm/ts-codegen@0.30.0.
|
||||||
|
* DO NOT MODIFY IT BY HAND. Instead, modify the source JSONSchema file,
|
||||||
|
* and run the @cosmwasm/ts-codegen generate command to regenerate this file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { UseQueryOptions, useQuery, useMutation, UseMutationOptions } from '@tanstack/react-query'
|
||||||
|
import { ExecuteResult } from '@cosmjs/cosmwasm-stargate'
|
||||||
|
import { StdFee, Coin } from '@cosmjs/amino'
|
||||||
|
import {
|
||||||
|
InstantiateMsg,
|
||||||
|
ExecuteMsg,
|
||||||
|
Uint128,
|
||||||
|
Addr,
|
||||||
|
OwnerUpdate,
|
||||||
|
QueryMsg,
|
||||||
|
Decimal,
|
||||||
|
AssetIncentiveResponse,
|
||||||
|
ArrayOfAssetIncentiveResponse,
|
||||||
|
ConfigResponse,
|
||||||
|
} from './MarsIncentives.types'
|
||||||
|
import { MarsIncentivesQueryClient, MarsIncentivesClient } from './MarsIncentives.client'
|
||||||
|
export const marsIncentivesQueryKeys = {
|
||||||
|
contract: [
|
||||||
|
{
|
||||||
|
contract: 'marsIncentives',
|
||||||
|
},
|
||||||
|
] as const,
|
||||||
|
address: (contractAddress: string | undefined) =>
|
||||||
|
[{ ...marsIncentivesQueryKeys.contract[0], address: contractAddress }] as const,
|
||||||
|
config: (contractAddress: string | undefined, args?: Record<string, unknown>) =>
|
||||||
|
[{ ...marsIncentivesQueryKeys.address(contractAddress)[0], method: 'config', args }] as const,
|
||||||
|
assetIncentive: (contractAddress: string | undefined, args?: Record<string, unknown>) =>
|
||||||
|
[
|
||||||
|
{ ...marsIncentivesQueryKeys.address(contractAddress)[0], method: 'asset_incentive', args },
|
||||||
|
] as const,
|
||||||
|
assetIncentives: (contractAddress: string | undefined, args?: Record<string, unknown>) =>
|
||||||
|
[
|
||||||
|
{ ...marsIncentivesQueryKeys.address(contractAddress)[0], method: 'asset_incentives', args },
|
||||||
|
] as const,
|
||||||
|
userUnclaimedRewards: (contractAddress: string | undefined, args?: Record<string, unknown>) =>
|
||||||
|
[
|
||||||
|
{
|
||||||
|
...marsIncentivesQueryKeys.address(contractAddress)[0],
|
||||||
|
method: 'user_unclaimed_rewards',
|
||||||
|
args,
|
||||||
|
},
|
||||||
|
] as const,
|
||||||
|
}
|
||||||
|
export interface MarsIncentivesReactQuery<TResponse, TData = TResponse> {
|
||||||
|
client: MarsIncentivesQueryClient | undefined
|
||||||
|
options?: Omit<
|
||||||
|
UseQueryOptions<TResponse, Error, TData>,
|
||||||
|
"'queryKey' | 'queryFn' | 'initialData'"
|
||||||
|
> & {
|
||||||
|
initialData?: undefined
|
||||||
|
}
|
||||||
|
}
|
||||||
|
export interface MarsIncentivesUserUnclaimedRewardsQuery<TData>
|
||||||
|
extends MarsIncentivesReactQuery<Uint128, TData> {
|
||||||
|
args: {
|
||||||
|
user: string
|
||||||
|
}
|
||||||
|
}
|
||||||
|
export function useMarsIncentivesUserUnclaimedRewardsQuery<TData = Uint128>({
|
||||||
|
client,
|
||||||
|
args,
|
||||||
|
options,
|
||||||
|
}: MarsIncentivesUserUnclaimedRewardsQuery<TData>) {
|
||||||
|
return useQuery<Uint128, Error, TData>(
|
||||||
|
marsIncentivesQueryKeys.userUnclaimedRewards(client?.contractAddress, args),
|
||||||
|
() =>
|
||||||
|
client
|
||||||
|
? client.userUnclaimedRewards({
|
||||||
|
user: args.user,
|
||||||
|
})
|
||||||
|
: Promise.reject(new Error('Invalid client')),
|
||||||
|
{ ...options, enabled: !!client && (options?.enabled != undefined ? options.enabled : true) },
|
||||||
|
)
|
||||||
|
}
|
||||||
|
export interface MarsIncentivesAssetIncentivesQuery<TData>
|
||||||
|
extends MarsIncentivesReactQuery<ArrayOfAssetIncentiveResponse, TData> {
|
||||||
|
args: {
|
||||||
|
limit?: number
|
||||||
|
startAfter?: string
|
||||||
|
}
|
||||||
|
}
|
||||||
|
export function useMarsIncentivesAssetIncentivesQuery<TData = ArrayOfAssetIncentiveResponse>({
|
||||||
|
client,
|
||||||
|
args,
|
||||||
|
options,
|
||||||
|
}: MarsIncentivesAssetIncentivesQuery<TData>) {
|
||||||
|
return useQuery<ArrayOfAssetIncentiveResponse, Error, TData>(
|
||||||
|
marsIncentivesQueryKeys.assetIncentives(client?.contractAddress, args),
|
||||||
|
() =>
|
||||||
|
client
|
||||||
|
? client.assetIncentives({
|
||||||
|
limit: args.limit,
|
||||||
|
startAfter: args.startAfter,
|
||||||
|
})
|
||||||
|
: Promise.reject(new Error('Invalid client')),
|
||||||
|
{ ...options, enabled: !!client && (options?.enabled != undefined ? options.enabled : true) },
|
||||||
|
)
|
||||||
|
}
|
||||||
|
export interface MarsIncentivesAssetIncentiveQuery<TData>
|
||||||
|
extends MarsIncentivesReactQuery<AssetIncentiveResponse, TData> {
|
||||||
|
args: {
|
||||||
|
denom: string
|
||||||
|
}
|
||||||
|
}
|
||||||
|
export function useMarsIncentivesAssetIncentiveQuery<TData = AssetIncentiveResponse>({
|
||||||
|
client,
|
||||||
|
args,
|
||||||
|
options,
|
||||||
|
}: MarsIncentivesAssetIncentiveQuery<TData>) {
|
||||||
|
return useQuery<AssetIncentiveResponse, Error, TData>(
|
||||||
|
marsIncentivesQueryKeys.assetIncentive(client?.contractAddress, args),
|
||||||
|
() =>
|
||||||
|
client
|
||||||
|
? client.assetIncentive({
|
||||||
|
denom: args.denom,
|
||||||
|
})
|
||||||
|
: Promise.reject(new Error('Invalid client')),
|
||||||
|
{ ...options, enabled: !!client && (options?.enabled != undefined ? options.enabled : true) },
|
||||||
|
)
|
||||||
|
}
|
||||||
|
export interface MarsIncentivesConfigQuery<TData>
|
||||||
|
extends MarsIncentivesReactQuery<ConfigResponse, TData> {}
|
||||||
|
export function useMarsIncentivesConfigQuery<TData = ConfigResponse>({
|
||||||
|
client,
|
||||||
|
options,
|
||||||
|
}: MarsIncentivesConfigQuery<TData>) {
|
||||||
|
return useQuery<ConfigResponse, Error, TData>(
|
||||||
|
marsIncentivesQueryKeys.config(client?.contractAddress),
|
||||||
|
() => (client ? client.config() : Promise.reject(new Error('Invalid client'))),
|
||||||
|
{ ...options, enabled: !!client && (options?.enabled != undefined ? options.enabled : true) },
|
||||||
|
)
|
||||||
|
}
|
||||||
|
export interface MarsIncentivesUpdateOwnerMutation {
|
||||||
|
client: MarsIncentivesClient
|
||||||
|
msg: OwnerUpdate
|
||||||
|
args?: {
|
||||||
|
fee?: number | StdFee | 'auto'
|
||||||
|
memo?: string
|
||||||
|
funds?: Coin[]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
export function useMarsIncentivesUpdateOwnerMutation(
|
||||||
|
options?: Omit<
|
||||||
|
UseMutationOptions<ExecuteResult, Error, MarsIncentivesUpdateOwnerMutation>,
|
||||||
|
'mutationFn'
|
||||||
|
>,
|
||||||
|
) {
|
||||||
|
return useMutation<ExecuteResult, Error, MarsIncentivesUpdateOwnerMutation>(
|
||||||
|
({ client, msg, args: { fee, memo, funds } = {} }) => client.updateOwner(msg, fee, memo, funds),
|
||||||
|
options,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
export interface MarsIncentivesUpdateConfigMutation {
|
||||||
|
client: MarsIncentivesClient
|
||||||
|
msg: {
|
||||||
|
addressProvider?: string
|
||||||
|
marsDenom?: string
|
||||||
|
}
|
||||||
|
args?: {
|
||||||
|
fee?: number | StdFee | 'auto'
|
||||||
|
memo?: string
|
||||||
|
funds?: Coin[]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
export function useMarsIncentivesUpdateConfigMutation(
|
||||||
|
options?: Omit<
|
||||||
|
UseMutationOptions<ExecuteResult, Error, MarsIncentivesUpdateConfigMutation>,
|
||||||
|
'mutationFn'
|
||||||
|
>,
|
||||||
|
) {
|
||||||
|
return useMutation<ExecuteResult, Error, MarsIncentivesUpdateConfigMutation>(
|
||||||
|
({ client, msg, args: { fee, memo, funds } = {} }) =>
|
||||||
|
client.updateConfig(msg, fee, memo, funds),
|
||||||
|
options,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
export interface MarsIncentivesClaimRewardsMutation {
|
||||||
|
client: MarsIncentivesClient
|
||||||
|
args?: {
|
||||||
|
fee?: number | StdFee | 'auto'
|
||||||
|
memo?: string
|
||||||
|
funds?: Coin[]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
export function useMarsIncentivesClaimRewardsMutation(
|
||||||
|
options?: Omit<
|
||||||
|
UseMutationOptions<ExecuteResult, Error, MarsIncentivesClaimRewardsMutation>,
|
||||||
|
'mutationFn'
|
||||||
|
>,
|
||||||
|
) {
|
||||||
|
return useMutation<ExecuteResult, Error, MarsIncentivesClaimRewardsMutation>(
|
||||||
|
({ client, args: { fee, memo, funds } = {} }) => client.claimRewards(fee, memo, funds),
|
||||||
|
options,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
export interface MarsIncentivesBalanceChangeMutation {
|
||||||
|
client: MarsIncentivesClient
|
||||||
|
msg: {
|
||||||
|
denom: string
|
||||||
|
totalAmountScaledBefore: Uint128
|
||||||
|
userAddr: Addr
|
||||||
|
userAmountScaledBefore: Uint128
|
||||||
|
}
|
||||||
|
args?: {
|
||||||
|
fee?: number | StdFee | 'auto'
|
||||||
|
memo?: string
|
||||||
|
funds?: Coin[]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
export function useMarsIncentivesBalanceChangeMutation(
|
||||||
|
options?: Omit<
|
||||||
|
UseMutationOptions<ExecuteResult, Error, MarsIncentivesBalanceChangeMutation>,
|
||||||
|
'mutationFn'
|
||||||
|
>,
|
||||||
|
) {
|
||||||
|
return useMutation<ExecuteResult, Error, MarsIncentivesBalanceChangeMutation>(
|
||||||
|
({ client, msg, args: { fee, memo, funds } = {} }) =>
|
||||||
|
client.balanceChange(msg, fee, memo, funds),
|
||||||
|
options,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
export interface MarsIncentivesSetAssetIncentiveMutation {
|
||||||
|
client: MarsIncentivesClient
|
||||||
|
msg: {
|
||||||
|
denom: string
|
||||||
|
duration?: number
|
||||||
|
emissionPerSecond?: Uint128
|
||||||
|
startTime?: number
|
||||||
|
}
|
||||||
|
args?: {
|
||||||
|
fee?: number | StdFee | 'auto'
|
||||||
|
memo?: string
|
||||||
|
funds?: Coin[]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
export function useMarsIncentivesSetAssetIncentiveMutation(
|
||||||
|
options?: Omit<
|
||||||
|
UseMutationOptions<ExecuteResult, Error, MarsIncentivesSetAssetIncentiveMutation>,
|
||||||
|
'mutationFn'
|
||||||
|
>,
|
||||||
|
) {
|
||||||
|
return useMutation<ExecuteResult, Error, MarsIncentivesSetAssetIncentiveMutation>(
|
||||||
|
({ client, msg, args: { fee, memo, funds } = {} }) =>
|
||||||
|
client.setAssetIncentive(msg, fee, memo, funds),
|
||||||
|
options,
|
||||||
|
)
|
||||||
|
}
|
94
src/types/generated/mars-incentives/MarsIncentives.types.ts
Normal file
94
src/types/generated/mars-incentives/MarsIncentives.types.ts
Normal file
@ -0,0 +1,94 @@
|
|||||||
|
// @ts-nocheck
|
||||||
|
/**
|
||||||
|
* This file was automatically generated by @cosmwasm/ts-codegen@0.30.0.
|
||||||
|
* DO NOT MODIFY IT BY HAND. Instead, modify the source JSONSchema file,
|
||||||
|
* and run the @cosmwasm/ts-codegen generate command to regenerate this file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
export interface InstantiateMsg {
|
||||||
|
address_provider: string
|
||||||
|
mars_denom: string
|
||||||
|
owner: string
|
||||||
|
}
|
||||||
|
export type ExecuteMsg =
|
||||||
|
| {
|
||||||
|
set_asset_incentive: {
|
||||||
|
denom: string
|
||||||
|
duration?: number | null
|
||||||
|
emission_per_second?: Uint128 | null
|
||||||
|
start_time?: number | null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
| {
|
||||||
|
balance_change: {
|
||||||
|
denom: string
|
||||||
|
total_amount_scaled_before: Uint128
|
||||||
|
user_addr: Addr
|
||||||
|
user_amount_scaled_before: Uint128
|
||||||
|
}
|
||||||
|
}
|
||||||
|
| {
|
||||||
|
claim_rewards: {}
|
||||||
|
}
|
||||||
|
| {
|
||||||
|
update_config: {
|
||||||
|
address_provider?: string | null
|
||||||
|
mars_denom?: string | null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
| {
|
||||||
|
update_owner: OwnerUpdate
|
||||||
|
}
|
||||||
|
export type Uint128 = string
|
||||||
|
export type Addr = string
|
||||||
|
export type OwnerUpdate =
|
||||||
|
| {
|
||||||
|
propose_new_owner: {
|
||||||
|
proposed: string
|
||||||
|
}
|
||||||
|
}
|
||||||
|
| 'clear_proposed'
|
||||||
|
| 'accept_proposed'
|
||||||
|
| 'abolish_owner_role'
|
||||||
|
| {
|
||||||
|
set_emergency_owner: {
|
||||||
|
emergency_owner: string
|
||||||
|
}
|
||||||
|
}
|
||||||
|
| 'clear_emergency_owner'
|
||||||
|
export type QueryMsg =
|
||||||
|
| {
|
||||||
|
config: {}
|
||||||
|
}
|
||||||
|
| {
|
||||||
|
asset_incentive: {
|
||||||
|
denom: string
|
||||||
|
}
|
||||||
|
}
|
||||||
|
| {
|
||||||
|
asset_incentives: {
|
||||||
|
limit?: number | null
|
||||||
|
start_after?: string | null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
| {
|
||||||
|
user_unclaimed_rewards: {
|
||||||
|
user: string
|
||||||
|
}
|
||||||
|
}
|
||||||
|
export type Decimal = string
|
||||||
|
export interface AssetIncentiveResponse {
|
||||||
|
denom: string
|
||||||
|
duration: number
|
||||||
|
emission_per_second: Uint128
|
||||||
|
index: Decimal
|
||||||
|
last_updated: number
|
||||||
|
start_time: number
|
||||||
|
}
|
||||||
|
export type ArrayOfAssetIncentiveResponse = AssetIncentiveResponse[]
|
||||||
|
export interface ConfigResponse {
|
||||||
|
address_provider: Addr
|
||||||
|
mars_denom: string
|
||||||
|
owner?: string | null
|
||||||
|
proposed_new_owner?: string | null
|
||||||
|
}
|
13
src/types/generated/mars-incentives/bundle.ts
Normal file
13
src/types/generated/mars-incentives/bundle.ts
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
// @ts-nocheck
|
||||||
|
/**
|
||||||
|
* This file was automatically generated by @cosmwasm/ts-codegen@0.30.0.
|
||||||
|
* DO NOT MODIFY IT BY HAND. Instead, modify the source JSONSchema file,
|
||||||
|
* and run the @cosmwasm/ts-codegen generate command to regenerate this file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import * as _3 from './MarsIncentives.types'
|
||||||
|
import * as _4 from './MarsIncentives.client'
|
||||||
|
import * as _5 from './MarsIncentives.react-query'
|
||||||
|
export namespace contracts {
|
||||||
|
export const MarsIncentives = { ..._3, ..._4, ..._5 }
|
||||||
|
}
|
3
src/types/interfaces/asset.d.ts
vendored
3
src/types/interfaces/asset.d.ts
vendored
@ -42,8 +42,9 @@ interface LendingMarketTableData {
|
|||||||
marketMaxLtv: number
|
marketMaxLtv: number
|
||||||
marketLiquidityRate: number
|
marketLiquidityRate: number
|
||||||
marketDepositCap: BigNumber
|
marketDepositCap: BigNumber
|
||||||
|
accountLentAmount?: string
|
||||||
marketDepositAmount: BigNumber
|
marketDepositAmount: BigNumber
|
||||||
accountDepositValue?: BigNumber
|
accountLentValue?: BigNumber
|
||||||
marketLiquidityAmount: BigNumber
|
marketLiquidityAmount: BigNumber
|
||||||
marketLiquidationThreshold: number
|
marketLiquidationThreshold: number
|
||||||
}
|
}
|
||||||
|
2
src/types/interfaces/store/broadcast.d.ts
vendored
2
src/types/interfaces/store/broadcast.d.ts
vendored
@ -16,6 +16,8 @@ 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>
|
||||||
|
reclaim: (options: { fee: StdFee; accountId: string; coin: Coin }) => Promise<boolean>
|
||||||
repay: (options: {
|
repay: (options: {
|
||||||
fee: StdFee
|
fee: StdFee
|
||||||
accountId: string
|
accountId: string
|
||||||
|
7
src/types/interfaces/store/modals.d.ts
vendored
7
src/types/interfaces/store/modals.d.ts
vendored
@ -7,6 +7,13 @@ interface ModalSlice {
|
|||||||
fundAndWithdrawModal: 'fund' | 'withdraw' | null
|
fundAndWithdrawModal: 'fund' | 'withdraw' | null
|
||||||
vaultModal: VaultModal | null
|
vaultModal: VaultModal | null
|
||||||
unlockModal: UnlockModal | null
|
unlockModal: UnlockModal | null
|
||||||
|
lendAndReclaimModal: LendAndReclaimModalConfig | null
|
||||||
|
}
|
||||||
|
|
||||||
|
type LendAndReclaimModalAction = 'lend' | 'reclaim'
|
||||||
|
interface LendAndReclaimModalConfig {
|
||||||
|
data: LendingMarketTableData
|
||||||
|
action: LendAndReclaimModalAction
|
||||||
}
|
}
|
||||||
|
|
||||||
interface BorrowModal {
|
interface BorrowModal {
|
||||||
|
@ -9,3 +9,5 @@ export const hardcodedFee = {
|
|||||||
],
|
],
|
||||||
gas: '5000000',
|
gas: '5000000',
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const SECONDS_IN_A_YEAR = 31540000
|
@ -16,7 +16,11 @@ export function resolvePositionResponse(response: CreditManagerPosition): Accoun
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function resolveMarketResponses(responses: RedBankMarket[]): Market[] {
|
export function resolveMarketResponses(responses: RedBankMarket[]): Market[] {
|
||||||
return responses.map((response) => ({
|
return responses.map(resolveMarketResponse)
|
||||||
|
}
|
||||||
|
|
||||||
|
export function resolveMarketResponse(response: RedBankMarket): Market {
|
||||||
|
return {
|
||||||
denom: response.denom,
|
denom: response.denom,
|
||||||
borrowRate: Number(response.borrow_rate),
|
borrowRate: Number(response.borrow_rate),
|
||||||
debtTotalScaled: response.debt_total_scaled,
|
debtTotalScaled: response.debt_total_scaled,
|
||||||
@ -27,5 +31,5 @@ export function resolveMarketResponses(responses: RedBankMarket[]): Market[] {
|
|||||||
maxLtv: Number(response.max_loan_to_value),
|
maxLtv: Number(response.max_loan_to_value),
|
||||||
liquidityRate: Number(response.liquidity_rate),
|
liquidityRate: Number(response.liquidity_rate),
|
||||||
liquidationThreshold: Number(response.liquidation_threshold),
|
liquidationThreshold: Number(response.liquidation_threshold),
|
||||||
}))
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user