✨ added caching for api requests (#513)
This commit is contained in:
parent
44196f1a10
commit
fe9040b29f
@ -1,3 +1,4 @@
|
|||||||
|
import { cacheFn, positionsCache } from 'api/cache'
|
||||||
import { getCreditManagerQueryClient } from 'api/cosmwasm-client'
|
import { getCreditManagerQueryClient } from 'api/cosmwasm-client'
|
||||||
import getDepositedVaults from 'api/vaults/getDepositedVaults'
|
import getDepositedVaults from 'api/vaults/getDepositedVaults'
|
||||||
import { BNCoin } from 'types/classes/BNCoin'
|
import { BNCoin } from 'types/classes/BNCoin'
|
||||||
@ -6,9 +7,13 @@ import { Positions } from 'types/generated/mars-credit-manager/MarsCreditManager
|
|||||||
export default async function getAccount(accountId: string): Promise<Account> {
|
export default async function getAccount(accountId: string): Promise<Account> {
|
||||||
const creditManagerQueryClient = await getCreditManagerQueryClient()
|
const creditManagerQueryClient = await getCreditManagerQueryClient()
|
||||||
|
|
||||||
const accountPosition: Positions = await creditManagerQueryClient.positions({ accountId })
|
const accountPosition: Positions = await cacheFn(
|
||||||
|
() => creditManagerQueryClient.positions({ accountId }),
|
||||||
|
positionsCache,
|
||||||
|
`account/${accountId}`,
|
||||||
|
)
|
||||||
|
|
||||||
const depositedVaults = await getDepositedVaults(accountId)
|
const depositedVaults = await getDepositedVaults(accountId, accountPosition)
|
||||||
|
|
||||||
if (accountPosition) {
|
if (accountPosition) {
|
||||||
return {
|
return {
|
||||||
|
62
src/api/cache.ts
Normal file
62
src/api/cache.ts
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
import {
|
||||||
|
ArrayOfCoin,
|
||||||
|
Positions,
|
||||||
|
VaultUtilizationResponse,
|
||||||
|
} from 'types/generated/mars-credit-manager/MarsCreditManager.types'
|
||||||
|
import { ArrayOfActiveEmission } from 'types/generated/mars-incentives/MarsIncentives.types'
|
||||||
|
import { PriceResponse } from 'types/generated/mars-oracle-osmosis/MarsOracleOsmosis.types'
|
||||||
|
import {
|
||||||
|
AssetParamsBaseForAddr,
|
||||||
|
TotalDepositResponse,
|
||||||
|
VaultConfigBaseForAddr,
|
||||||
|
} from 'types/generated/mars-params/MarsParams.types'
|
||||||
|
import { ArrayOfMarket } from 'types/generated/mars-red-bank/MarsRedBank.types'
|
||||||
|
|
||||||
|
interface Cache<T> extends Map<string, { data: T | null; timestamp: number }> {}
|
||||||
|
|
||||||
|
let totalRequests: number = 0
|
||||||
|
let cachedRequests: number = 0
|
||||||
|
|
||||||
|
export async function cacheFn<T>(
|
||||||
|
fn: () => Promise<T>,
|
||||||
|
cache: Cache<T>,
|
||||||
|
key: string,
|
||||||
|
staleAfter: number = 5,
|
||||||
|
) {
|
||||||
|
const cachedData = cache.get(key)?.data
|
||||||
|
const isStale = (cache.get(key)?.timestamp || 0) + 1000 * staleAfter < new Date().getTime()
|
||||||
|
|
||||||
|
totalRequests += 1
|
||||||
|
|
||||||
|
if (cachedData && !isStale) {
|
||||||
|
cachedRequests += 1
|
||||||
|
return cachedData
|
||||||
|
}
|
||||||
|
|
||||||
|
const data = await fn()
|
||||||
|
cache.set(key, { data, timestamp: new Date().getTime() })
|
||||||
|
|
||||||
|
return data
|
||||||
|
}
|
||||||
|
|
||||||
|
export const positionsCache: Cache<Positions> = new Map()
|
||||||
|
export const aprsCacheResponse: Cache<Response> = new Map()
|
||||||
|
export const aprsCache: Cache<AprResponse> = new Map()
|
||||||
|
export const vaultConfigsCache: Cache<VaultConfigBaseForAddr[]> = new Map()
|
||||||
|
export const vaultUtilizationCache: Cache<VaultUtilizationResponse> = new Map()
|
||||||
|
export const unlockPositionsCache: Cache<VaultExtensionResponse> = new Map()
|
||||||
|
export const estimateWithdrawCache: Cache<Coin[]> = new Map()
|
||||||
|
export const previewRedeemCache: Cache<string> = new Map()
|
||||||
|
export const priceCache: Cache<BigNumber> = new Map()
|
||||||
|
export const pythPriceCache: Cache<PythConfidenceData> = new Map()
|
||||||
|
export const oraclePriceCache: Cache<PriceResponse[]> = new Map()
|
||||||
|
export const poolPriceCache: Cache<PriceResponse[]> = new Map()
|
||||||
|
export const emissionsCache: Cache<ArrayOfActiveEmission> = new Map()
|
||||||
|
export const marketCache: Cache<Market> = new Map()
|
||||||
|
export const marketsCache: Cache<ArrayOfMarket> = new Map()
|
||||||
|
export const underlyingLiquidityAmountCache: Cache<string> = new Map()
|
||||||
|
export const unclaimedRewardsCache: Cache<ArrayOfCoin> = new Map()
|
||||||
|
export const totalDepositCache: Cache<TotalDepositResponse> = new Map()
|
||||||
|
export const allParamsCache: Cache<AssetParamsBaseForAddr[]> = new Map()
|
||||||
|
export const underlyingDebtCache: Cache<string> = new Map()
|
||||||
|
export const previewDepositCache: Cache<{ vaultAddress: string; amount: string }> = new Map()
|
@ -1,3 +1,4 @@
|
|||||||
|
import { cacheFn, emissionsCache } from 'api/cache'
|
||||||
import { getIncentivesQueryClient } from 'api/cosmwasm-client'
|
import { getIncentivesQueryClient } from 'api/cosmwasm-client'
|
||||||
import getPrice from 'api/prices/getPrice'
|
import getPrice from 'api/prices/getPrice'
|
||||||
import { ASSETS } from 'constants/assets'
|
import { ASSETS } from 'constants/assets'
|
||||||
@ -10,9 +11,15 @@ export default async function getTotalActiveEmissionValue(
|
|||||||
): Promise<BigNumber | null> {
|
): Promise<BigNumber | null> {
|
||||||
try {
|
try {
|
||||||
const client = await getIncentivesQueryClient()
|
const client = await getIncentivesQueryClient()
|
||||||
const activeEmissions = await client.activeEmissions({
|
const activeEmissions = await cacheFn(
|
||||||
collateralDenom: denom,
|
() =>
|
||||||
})
|
client.activeEmissions({
|
||||||
|
collateralDenom: denom,
|
||||||
|
}),
|
||||||
|
emissionsCache,
|
||||||
|
`emission/${denom}`,
|
||||||
|
60,
|
||||||
|
)
|
||||||
|
|
||||||
if (activeEmissions.length === 0) {
|
if (activeEmissions.length === 0) {
|
||||||
throw 'Asset has no active incentive emission.'
|
throw 'Asset has no active incentive emission.'
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
import { cacheFn, unclaimedRewardsCache } from 'api/cache'
|
||||||
import { getIncentivesQueryClient } from 'api/cosmwasm-client'
|
import { getIncentivesQueryClient } from 'api/cosmwasm-client'
|
||||||
import { BNCoin } from 'types/classes/BNCoin'
|
import { BNCoin } from 'types/classes/BNCoin'
|
||||||
|
|
||||||
@ -7,11 +8,17 @@ export default async function getUnclaimedRewards(
|
|||||||
): Promise<BNCoin[]> {
|
): Promise<BNCoin[]> {
|
||||||
try {
|
try {
|
||||||
const client = await getIncentivesQueryClient()
|
const client = await getIncentivesQueryClient()
|
||||||
const unclaimedRewards = await client.userUnclaimedRewards({
|
const unclaimedRewards = await cacheFn(
|
||||||
user,
|
() =>
|
||||||
accountId,
|
client.userUnclaimedRewards({
|
||||||
limit: 100,
|
user,
|
||||||
})
|
accountId,
|
||||||
|
limit: 100,
|
||||||
|
}),
|
||||||
|
unclaimedRewardsCache,
|
||||||
|
`incentives/${accountId}`,
|
||||||
|
60,
|
||||||
|
)
|
||||||
|
|
||||||
if (unclaimedRewards.length === 0) return []
|
if (unclaimedRewards.length === 0) return []
|
||||||
|
|
||||||
|
@ -1,7 +1,12 @@
|
|||||||
import { resolveMarketResponse } from 'utils/resolvers'
|
import { cacheFn, marketCache } from 'api/cache'
|
||||||
import { getParamsQueryClient, getRedBankQueryClient } from 'api/cosmwasm-client'
|
import { getParamsQueryClient, getRedBankQueryClient } from 'api/cosmwasm-client'
|
||||||
|
import { resolveMarketResponse } from 'utils/resolvers'
|
||||||
|
|
||||||
export default async function getMarket(denom: string): Promise<Market> {
|
export default async function getMarket(denom: string): Promise<Market> {
|
||||||
|
return cacheFn(() => fetchMarket(denom), marketCache, denom, 60)
|
||||||
|
}
|
||||||
|
|
||||||
|
async function fetchMarket(denom: string) {
|
||||||
try {
|
try {
|
||||||
const redBankClient = await getRedBankQueryClient()
|
const redBankClient = await getRedBankQueryClient()
|
||||||
const paramsClient = await getParamsQueryClient()
|
const paramsClient = await getParamsQueryClient()
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
import getMarkets from 'api/markets/getMarkets'
|
import { cacheFn, underlyingDebtCache } from 'api/cache'
|
||||||
import { getRedBankQueryClient } from 'api/cosmwasm-client'
|
import { getRedBankQueryClient } from 'api/cosmwasm-client'
|
||||||
|
import getMarkets from 'api/markets/getMarkets'
|
||||||
import { BNCoin } from 'types/classes/BNCoin'
|
import { BNCoin } from 'types/classes/BNCoin'
|
||||||
|
|
||||||
export default async function getMarketDebts(): Promise<BNCoin[]> {
|
export default async function getMarketDebts(): Promise<BNCoin[]> {
|
||||||
@ -8,10 +9,16 @@ export default async function getMarketDebts(): Promise<BNCoin[]> {
|
|||||||
const redBankQueryClient = await getRedBankQueryClient()
|
const redBankQueryClient = await getRedBankQueryClient()
|
||||||
|
|
||||||
const debtQueries = markets.map((asset) =>
|
const debtQueries = markets.map((asset) =>
|
||||||
redBankQueryClient.underlyingDebtAmount({
|
cacheFn(
|
||||||
denom: asset.denom,
|
() =>
|
||||||
amountScaled: asset.debtTotalScaled,
|
redBankQueryClient.underlyingDebtAmount({
|
||||||
}),
|
denom: asset.denom,
|
||||||
|
amountScaled: asset.debtTotalScaled,
|
||||||
|
}),
|
||||||
|
underlyingDebtCache,
|
||||||
|
`marketDebts/${asset.denom}/amount/${asset.debtTotalScaled}`,
|
||||||
|
60,
|
||||||
|
),
|
||||||
)
|
)
|
||||||
const debtsResults = await Promise.all(debtQueries)
|
const debtsResults = await Promise.all(debtQueries)
|
||||||
|
|
||||||
|
@ -1,6 +1,16 @@
|
|||||||
|
import { cacheFn, underlyingLiquidityAmountCache } from 'api/cache'
|
||||||
import { getRedBankQueryClient } from 'api/cosmwasm-client'
|
import { getRedBankQueryClient } from 'api/cosmwasm-client'
|
||||||
|
|
||||||
export default async function getUnderlyingLiquidityAmount(market: Market): Promise<string> {
|
export default async function getUnderlyingLiquidityAmount(market: Market): Promise<string> {
|
||||||
|
return cacheFn(
|
||||||
|
() => fetchUnderlyingLiquidityAmount(market),
|
||||||
|
underlyingLiquidityAmountCache,
|
||||||
|
`underlyingLiquidity/${market.denom}/amount/${market.collateralTotalScaled}`,
|
||||||
|
60,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
async function fetchUnderlyingLiquidityAmount(market: Market) {
|
||||||
try {
|
try {
|
||||||
const client = await getRedBankQueryClient()
|
const client = await getRedBankQueryClient()
|
||||||
return await client.underlyingLiquidityAmount({
|
return await client.underlyingLiquidityAmount({
|
||||||
|
@ -1,13 +1,14 @@
|
|||||||
import { getEnabledMarketAssets } from 'utils/assets'
|
import { allParamsCache, cacheFn, marketsCache, totalDepositCache } from 'api/cache'
|
||||||
import { getParamsQueryClient, getRedBankQueryClient } from 'api/cosmwasm-client'
|
import { getParamsQueryClient, getRedBankQueryClient } from 'api/cosmwasm-client'
|
||||||
import iterateContractQuery from 'utils/iterateContractQuery'
|
|
||||||
import { byDenom } from 'utils/array'
|
|
||||||
import { resolveMarketResponse } from 'utils/resolvers'
|
|
||||||
import { Market as RedBankMarket } from 'types/generated/mars-red-bank/MarsRedBank.types'
|
|
||||||
import {
|
import {
|
||||||
AssetParamsBaseForAddr as AssetParams,
|
AssetParamsBaseForAddr as AssetParams,
|
||||||
TotalDepositResponse,
|
TotalDepositResponse,
|
||||||
} from 'types/generated/mars-params/MarsParams.types'
|
} from 'types/generated/mars-params/MarsParams.types'
|
||||||
|
import { Market as RedBankMarket } from 'types/generated/mars-red-bank/MarsRedBank.types'
|
||||||
|
import { byDenom } from 'utils/array'
|
||||||
|
import { getEnabledMarketAssets } from 'utils/assets'
|
||||||
|
import iterateContractQuery from 'utils/iterateContractQuery'
|
||||||
|
import { resolveMarketResponse } from 'utils/resolvers'
|
||||||
|
|
||||||
export default async function getMarkets(): Promise<Market[]> {
|
export default async function getMarkets(): Promise<Market[]> {
|
||||||
try {
|
try {
|
||||||
@ -16,11 +17,21 @@ export default async function getMarkets(): Promise<Market[]> {
|
|||||||
|
|
||||||
const enabledAssets = getEnabledMarketAssets()
|
const enabledAssets = getEnabledMarketAssets()
|
||||||
const capQueries = enabledAssets.map((asset) =>
|
const capQueries = enabledAssets.map((asset) =>
|
||||||
paramsClient.totalDeposit({ denom: asset.denom }),
|
cacheFn(
|
||||||
|
() => paramsClient.totalDeposit({ denom: asset.denom }),
|
||||||
|
totalDepositCache,
|
||||||
|
`enabledMarkets/${asset.denom}`,
|
||||||
|
60,
|
||||||
|
),
|
||||||
)
|
)
|
||||||
const [markets, assetParams, assetCaps] = await Promise.all([
|
const [markets, assetParams, assetCaps] = await Promise.all([
|
||||||
iterateContractQuery(redBankClient.markets),
|
cacheFn(() => iterateContractQuery(redBankClient.markets), marketsCache, 'markets', 60),
|
||||||
iterateContractQuery(paramsClient.allAssetParams),
|
cacheFn(
|
||||||
|
async () => await iterateContractQuery(paramsClient.allAssetParams),
|
||||||
|
allParamsCache,
|
||||||
|
'params',
|
||||||
|
60,
|
||||||
|
),
|
||||||
Promise.all(capQueries),
|
Promise.all(capQueries),
|
||||||
])
|
])
|
||||||
|
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
import { cacheFn, oraclePriceCache } from 'api/cache'
|
||||||
import { getOracleQueryClient } from 'api/cosmwasm-client'
|
import { getOracleQueryClient } from 'api/cosmwasm-client'
|
||||||
import { PRICE_ORACLE_DECIMALS } from 'constants/query'
|
import { PRICE_ORACLE_DECIMALS } from 'constants/query'
|
||||||
import { BNCoin } from 'types/classes/BNCoin'
|
import { BNCoin } from 'types/classes/BNCoin'
|
||||||
@ -11,7 +12,12 @@ export default async function getOraclePrices(...assets: Asset[]): Promise<BNCoi
|
|||||||
if (!assets.length) return []
|
if (!assets.length) return []
|
||||||
|
|
||||||
const oracleQueryClient = await getOracleQueryClient()
|
const oracleQueryClient = await getOracleQueryClient()
|
||||||
const priceResults = await iterateContractQuery(oracleQueryClient.prices)
|
const priceResults = await cacheFn(
|
||||||
|
() => iterateContractQuery(oracleQueryClient.prices),
|
||||||
|
oraclePriceCache,
|
||||||
|
'oraclePrices',
|
||||||
|
60,
|
||||||
|
)
|
||||||
|
|
||||||
return assets.map((asset) => {
|
return assets.map((asset) => {
|
||||||
const priceResponse = priceResults.find(byDenom(asset.denom)) as PriceResponse
|
const priceResponse = priceResults.find(byDenom(asset.denom)) as PriceResponse
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
import { cacheFn, poolPriceCache } from 'api/cache'
|
||||||
import getPrice from 'api/prices/getPrice'
|
import getPrice from 'api/prices/getPrice'
|
||||||
import { ENV } from 'constants/env'
|
import { ENV } from 'constants/env'
|
||||||
import { BN_ONE } from 'constants/math'
|
import { BN_ONE } from 'constants/math'
|
||||||
@ -34,7 +35,12 @@ export default async function getPoolPrice(
|
|||||||
|
|
||||||
const getAssetRate = async (asset: Asset) => {
|
const getAssetRate = async (asset: Asset) => {
|
||||||
const url = `${ENV.URL_REST}osmosis/gamm/v1beta1/pools/${asset.poolId}`
|
const url = `${ENV.URL_REST}osmosis/gamm/v1beta1/pools/${asset.poolId}`
|
||||||
const response = await fetch(url).then((res) => res.json())
|
const response = await cacheFn(
|
||||||
|
() => fetch(url).then((res) => res.json()),
|
||||||
|
poolPriceCache,
|
||||||
|
`poolPrices/${(asset.poolId || 0).toString()}`,
|
||||||
|
60,
|
||||||
|
)
|
||||||
return calculateSpotPrice(response.pool.pool_assets, asset)
|
return calculateSpotPrice(response.pool.pool_assets, asset)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,12 +1,17 @@
|
|||||||
|
import { cacheFn, priceCache } from 'api/cache'
|
||||||
import { getOracleQueryClient } from 'api/cosmwasm-client'
|
import { getOracleQueryClient } from 'api/cosmwasm-client'
|
||||||
import { ASSETS } from 'constants/assets'
|
|
||||||
import { byDenom } from 'utils/array'
|
|
||||||
import getPythPrice from 'api/prices/getPythPrices'
|
|
||||||
import getPoolPrice from 'api/prices/getPoolPrice'
|
import getPoolPrice from 'api/prices/getPoolPrice'
|
||||||
import { BN } from 'utils/helpers'
|
import getPythPrice from 'api/prices/getPythPrices'
|
||||||
|
import { ASSETS } from 'constants/assets'
|
||||||
import { PRICE_ORACLE_DECIMALS } from 'constants/query'
|
import { PRICE_ORACLE_DECIMALS } from 'constants/query'
|
||||||
|
import { byDenom } from 'utils/array'
|
||||||
|
import { BN } from 'utils/helpers'
|
||||||
|
|
||||||
export default async function getPrice(denom: string): Promise<BigNumber> {
|
export default async function getPrice(denom: string): Promise<BigNumber> {
|
||||||
|
return cacheFn(() => fetchPrice(denom), priceCache, `price/${denom}`, 60)
|
||||||
|
}
|
||||||
|
|
||||||
|
async function fetchPrice(denom: string) {
|
||||||
try {
|
try {
|
||||||
const asset = ASSETS.find(byDenom(denom)) as Asset
|
const asset = ASSETS.find(byDenom(denom)) as Asset
|
||||||
|
|
||||||
|
@ -1,12 +1,19 @@
|
|||||||
import { ENV } from 'constants/env'
|
import { ENV } from 'constants/env'
|
||||||
import { BN } from 'utils/helpers'
|
import { BN } from 'utils/helpers'
|
||||||
|
|
||||||
|
import { cacheFn, pythPriceCache } from '../cache'
|
||||||
|
|
||||||
export default async function fetchPythPrices(...priceFeedIds: string[]) {
|
export default async function fetchPythPrices(...priceFeedIds: string[]) {
|
||||||
try {
|
try {
|
||||||
const pricesUrl = new URL(`${ENV.PYTH_ENDPOINT}/latest_price_feeds`)
|
const pricesUrl = new URL(`${ENV.PYTH_ENDPOINT}/latest_price_feeds`)
|
||||||
priceFeedIds.forEach((id) => pricesUrl.searchParams.append('ids[]', id))
|
priceFeedIds.forEach((id) => pricesUrl.searchParams.append('ids[]', id))
|
||||||
|
|
||||||
const pythResponse: PythPriceData[] = await fetch(pricesUrl).then((res) => res.json())
|
const pythResponse: PythPriceData[] = await cacheFn(
|
||||||
|
() => fetch(pricesUrl).then((res) => res.json()),
|
||||||
|
pythPriceCache,
|
||||||
|
`pythPrices/${priceFeedIds.flat().join('-')}`,
|
||||||
|
30,
|
||||||
|
)
|
||||||
|
|
||||||
return pythResponse.map(({ price }) => BN(price.price).shiftedBy(price.expo))
|
return pythResponse.map(({ price }) => BN(price.price).shiftedBy(price.expo))
|
||||||
} catch (ex) {
|
} catch (ex) {
|
||||||
|
@ -1,5 +1,12 @@
|
|||||||
import moment from 'moment'
|
import moment from 'moment'
|
||||||
|
|
||||||
|
import {
|
||||||
|
cacheFn,
|
||||||
|
estimateWithdrawCache,
|
||||||
|
positionsCache,
|
||||||
|
previewRedeemCache,
|
||||||
|
unlockPositionsCache,
|
||||||
|
} from 'api/cache'
|
||||||
import { getClient, getCreditManagerQueryClient, getVaultQueryClient } from 'api/cosmwasm-client'
|
import { getClient, getCreditManagerQueryClient, getVaultQueryClient } from 'api/cosmwasm-client'
|
||||||
import getPrice from 'api/prices/getPrice'
|
import getPrice from 'api/prices/getPrice'
|
||||||
import getVaults from 'api/vaults/getVaults'
|
import getVaults from 'api/vaults/getVaults'
|
||||||
@ -7,6 +14,7 @@ import { BN_ZERO } from 'constants/math'
|
|||||||
import { BNCoin } from 'types/classes/BNCoin'
|
import { BNCoin } from 'types/classes/BNCoin'
|
||||||
import { VaultStatus } from 'types/enums/vault'
|
import { VaultStatus } from 'types/enums/vault'
|
||||||
import {
|
import {
|
||||||
|
Positions,
|
||||||
VaultPosition,
|
VaultPosition,
|
||||||
VaultPositionAmount,
|
VaultPositionAmount,
|
||||||
} from 'types/generated/mars-credit-manager/MarsCreditManager.types'
|
} from 'types/generated/mars-credit-manager/MarsCreditManager.types'
|
||||||
@ -17,9 +25,15 @@ async function getUnlocksAtTimestamp(unlockingId: number, vaultAddress: string)
|
|||||||
try {
|
try {
|
||||||
const client = await getClient()
|
const client = await getClient()
|
||||||
|
|
||||||
const vaultExtension = (await client.queryContractSmart(vaultAddress, {
|
const vaultExtension = (await cacheFn(
|
||||||
vault_extension: { lockup: { unlocking_position: { lockup_id: unlockingId } } },
|
() =>
|
||||||
})) as VaultExtensionResponse
|
client.queryContractSmart(vaultAddress, {
|
||||||
|
vault_extension: { lockup: { unlocking_position: { lockup_id: unlockingId } } },
|
||||||
|
}),
|
||||||
|
unlockPositionsCache,
|
||||||
|
`unlockPositions/${vaultAddress}.id/${unlockingId}`,
|
||||||
|
60,
|
||||||
|
)) as VaultExtensionResponse
|
||||||
|
|
||||||
return Number(vaultExtension.release_at.at_time) / 1e6
|
return Number(vaultExtension.release_at.at_time) / 1e6
|
||||||
} catch (ex) {
|
} catch (ex) {
|
||||||
@ -78,16 +92,28 @@ async function getLpTokensForVaultPosition(
|
|||||||
const amounts = flatVaultPositionAmount(vaultPosition.amount)
|
const amounts = flatVaultPositionAmount(vaultPosition.amount)
|
||||||
const totalAmount = amounts.locked.plus(amounts.unlocked).plus(amounts.unlocking).toString()
|
const totalAmount = amounts.locked.plus(amounts.unlocked).plus(amounts.unlocking).toString()
|
||||||
|
|
||||||
const lpAmount = await vaultQueryClient.previewRedeem({
|
const lpAmount = await cacheFn(
|
||||||
amount: totalAmount,
|
() =>
|
||||||
})
|
vaultQueryClient.previewRedeem({
|
||||||
|
amount: totalAmount,
|
||||||
|
}),
|
||||||
|
previewRedeemCache,
|
||||||
|
`previewRedeem/vaults/${vault.address}/amount/${totalAmount}`,
|
||||||
|
60,
|
||||||
|
)
|
||||||
|
|
||||||
const lpTokens = await creditManagerQueryClient.estimateWithdrawLiquidity({
|
const lpTokens = await cacheFn(
|
||||||
lpToken: {
|
() =>
|
||||||
amount: lpAmount,
|
creditManagerQueryClient.estimateWithdrawLiquidity({
|
||||||
denom: vault.denoms.lp,
|
lpToken: {
|
||||||
},
|
amount: lpAmount,
|
||||||
})
|
denom: vault.denoms.lp,
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
estimateWithdrawCache,
|
||||||
|
`lpToken/${vault.denoms.lp}/amount/${lpAmount}`,
|
||||||
|
60,
|
||||||
|
)
|
||||||
|
|
||||||
const primaryLpToken = lpTokens.find((t) => t.denom === vault.denoms.primary) ?? {
|
const primaryLpToken = lpTokens.find((t) => t.denom === vault.denoms.primary) ?? {
|
||||||
amount: '0',
|
amount: '0',
|
||||||
@ -147,12 +173,23 @@ async function getVaultValuesAndAmounts(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async function getDepositedVaults(accountId: string): Promise<DepositedVault[]> {
|
async function getDepositedVaults(
|
||||||
|
accountId: string,
|
||||||
|
positions?: Positions,
|
||||||
|
): Promise<DepositedVault[]> {
|
||||||
try {
|
try {
|
||||||
const creditManagerQueryClient = await getCreditManagerQueryClient()
|
const creditManagerQueryClient = await getCreditManagerQueryClient()
|
||||||
const positionsQuery = creditManagerQueryClient.positions({ accountId })
|
|
||||||
|
|
||||||
const [positions, allVaults] = await Promise.all([positionsQuery, getVaults()])
|
if (!positions)
|
||||||
|
positions = await cacheFn(
|
||||||
|
() => creditManagerQueryClient.positions({ accountId }),
|
||||||
|
positionsCache,
|
||||||
|
`depositedVaults/${accountId}`,
|
||||||
|
)
|
||||||
|
|
||||||
|
if (!positions.vaults.length) return []
|
||||||
|
|
||||||
|
const [allVaults] = await Promise.all([getVaults()])
|
||||||
|
|
||||||
const depositedVaults = positions.vaults.map(async (vaultPosition) => {
|
const depositedVaults = positions.vaults.map(async (vaultPosition) => {
|
||||||
const vault = allVaults.find((v) => v.address === vaultPosition.vault.address)
|
const vault = allVaults.find((v) => v.address === vaultPosition.vault.address)
|
||||||
|
@ -1,19 +1,22 @@
|
|||||||
|
import { aprsCache, aprsCacheResponse, cacheFn } from 'api/cache'
|
||||||
import { ENV } from 'constants/env'
|
import { ENV } from 'constants/env'
|
||||||
|
|
||||||
export default async function getAprs() {
|
export default async function getAprs() {
|
||||||
try {
|
try {
|
||||||
const response = await fetch(ENV.URL_VAULT_APR)
|
const response = await cacheFn(
|
||||||
|
() => fetch(ENV.URL_VAULT_APR),
|
||||||
|
aprsCacheResponse,
|
||||||
|
'aprsResponse',
|
||||||
|
60,
|
||||||
|
)
|
||||||
|
|
||||||
if (response.ok) {
|
if (response.ok) {
|
||||||
const data: AprResponse = await response.json()
|
const data: AprResponse = await cacheFn(() => response.json(), aprsCache, 'aprs', 60)
|
||||||
|
|
||||||
const newAprs = data.vaults.map((aprData) => {
|
return data.vaults.map((aprData) => {
|
||||||
const finalApr = aprData.apr.projected_apr * 100
|
const finalApr = aprData.apr.projected_apr * 100
|
||||||
|
return { address: aprData.address, apr: finalApr } as Apr
|
||||||
return { address: aprData.address, apr: finalApr }
|
|
||||||
})
|
})
|
||||||
|
|
||||||
return newAprs
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return []
|
return []
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
import { cacheFn, vaultConfigsCache } from 'api/cache'
|
||||||
import { getParamsQueryClient } from 'api/cosmwasm-client'
|
import { getParamsQueryClient } from 'api/cosmwasm-client'
|
||||||
import { VaultConfigBaseForAddr } from 'types/generated/mars-params/MarsParams.types'
|
import { VaultConfigBaseForAddr } from 'types/generated/mars-params/MarsParams.types'
|
||||||
import iterateContractQuery from 'utils/iterateContractQuery'
|
import iterateContractQuery from 'utils/iterateContractQuery'
|
||||||
@ -5,7 +6,12 @@ import iterateContractQuery from 'utils/iterateContractQuery'
|
|||||||
export const getVaultConfigs = async (): Promise<VaultConfigBaseForAddr[]> => {
|
export const getVaultConfigs = async (): Promise<VaultConfigBaseForAddr[]> => {
|
||||||
try {
|
try {
|
||||||
const paramsQueryClient = await getParamsQueryClient()
|
const paramsQueryClient = await getParamsQueryClient()
|
||||||
return await iterateContractQuery(paramsQueryClient.allVaultConfigs, 'addr')
|
return await cacheFn(
|
||||||
|
() => iterateContractQuery(paramsQueryClient.allVaultConfigs, 'addr'),
|
||||||
|
vaultConfigsCache,
|
||||||
|
'vaultConfigs',
|
||||||
|
600,
|
||||||
|
)
|
||||||
} catch (ex) {
|
} catch (ex) {
|
||||||
console.error(ex)
|
console.error(ex)
|
||||||
throw ex
|
throw ex
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
import { cacheFn, previewDepositCache } from 'api/cache'
|
||||||
import { getVaultQueryClient } from 'api/cosmwasm-client'
|
import { getVaultQueryClient } from 'api/cosmwasm-client'
|
||||||
|
|
||||||
export async function getVaultTokenFromLp(
|
export async function getVaultTokenFromLp(
|
||||||
@ -7,7 +8,13 @@ export async function getVaultTokenFromLp(
|
|||||||
try {
|
try {
|
||||||
const client = await getVaultQueryClient(vaultAddress)
|
const client = await getVaultQueryClient(vaultAddress)
|
||||||
|
|
||||||
return client.previewDeposit({ amount: lpAmount }).then((amount) => ({ vaultAddress, amount }))
|
return cacheFn(
|
||||||
|
() =>
|
||||||
|
client.previewDeposit({ amount: lpAmount }).then((amount) => ({ vaultAddress, amount })),
|
||||||
|
previewDepositCache,
|
||||||
|
`vaults/${vaultAddress}/amounts/${lpAmount}`,
|
||||||
|
30,
|
||||||
|
)
|
||||||
} catch (ex) {
|
} catch (ex) {
|
||||||
throw ex
|
throw ex
|
||||||
}
|
}
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
import { cacheFn, vaultUtilizationCache } from 'api/cache'
|
||||||
import { getCreditManagerQueryClient } from 'api/cosmwasm-client'
|
import { getCreditManagerQueryClient } from 'api/cosmwasm-client'
|
||||||
import { ENV } from 'constants/env'
|
import { ENV } from 'constants/env'
|
||||||
import { VaultUtilizationResponse } from 'types/generated/mars-credit-manager/MarsCreditManager.types'
|
import { VaultUtilizationResponse } from 'types/generated/mars-credit-manager/MarsCreditManager.types'
|
||||||
@ -10,7 +11,12 @@ export const getVaultUtilizations = async (
|
|||||||
const creditManagerQueryClient = await getCreditManagerQueryClient()
|
const creditManagerQueryClient = await getCreditManagerQueryClient()
|
||||||
try {
|
try {
|
||||||
const vaultUtilizations$ = vaultConfigs.map((vaultConfig) => {
|
const vaultUtilizations$ = vaultConfigs.map((vaultConfig) => {
|
||||||
return creditManagerQueryClient.vaultUtilization({ vault: { address: vaultConfig.addr } })
|
return cacheFn(
|
||||||
|
() => creditManagerQueryClient.vaultUtilization({ vault: { address: vaultConfig.addr } }),
|
||||||
|
vaultUtilizationCache,
|
||||||
|
`vaultUtilization/${vaultConfig.addr}`,
|
||||||
|
60,
|
||||||
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
return await Promise.all(vaultUtilizations$).then((vaultUtilizations) => vaultUtilizations)
|
return await Promise.all(vaultUtilizations$).then((vaultUtilizations) => vaultUtilizations)
|
||||||
|
@ -131,7 +131,7 @@ export default function Index(props: Props) {
|
|||||||
header: 'APY',
|
header: 'APY',
|
||||||
cell: ({ row }) => {
|
cell: ({ row }) => {
|
||||||
if (row.original.type === 'deposits')
|
if (row.original.type === 'deposits')
|
||||||
return <span className='w-full text-xs text-center'>–</span>
|
return <p className='w-full text-xs text-right number'>–</p>
|
||||||
const isEnabled = markets.find(byDenom(row.original.denom))?.borrowEnabled ?? false
|
const isEnabled = markets.find(byDenom(row.original.denom))?.borrowEnabled ?? false
|
||||||
return (
|
return (
|
||||||
<AssetRate
|
<AssetRate
|
||||||
|
@ -3,6 +3,7 @@ import useSWR from 'swr'
|
|||||||
import getAccounts from 'api/wallets/getAccounts'
|
import getAccounts from 'api/wallets/getAccounts'
|
||||||
import useStore from 'store'
|
import useStore from 'store'
|
||||||
|
|
||||||
|
// TODO: Remove this hook
|
||||||
export default function useAccounts(address?: string) {
|
export default function useAccounts(address?: string) {
|
||||||
return useSWR(`accounts${address}`, () => getAccounts(address), {
|
return useSWR(`accounts${address}`, () => getAccounts(address), {
|
||||||
suspense: true,
|
suspense: true,
|
||||||
|
5
src/types/interfaces/vaults.d.ts
vendored
5
src/types/interfaces/vaults.d.ts
vendored
@ -111,3 +111,8 @@ interface AprBreakdown {
|
|||||||
period_daily_return: number
|
period_daily_return: number
|
||||||
projected_apr: number
|
projected_apr: number
|
||||||
}
|
}
|
||||||
|
|
||||||
|
interface Apr {
|
||||||
|
address: string
|
||||||
|
apr: number
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user