Mp 2565 api for active vaults (#239)
* feat: get deposited vaults functions * feat: functional improvements * cleanup: logging * cleanup: remove unused import * update: naming conventions
This commit is contained in:
parent
9d09ebdf77
commit
2156431355
16
src/api/prices/getPrice.ts
Normal file
16
src/api/prices/getPrice.ts
Normal file
@ -0,0 +1,16 @@
|
||||
import { getClient } from 'api/cosmwasm-client'
|
||||
import { ENV } from 'constants/env'
|
||||
|
||||
export default async function getPrice(denom: string): Promise<PriceResult> {
|
||||
try {
|
||||
const client = await getClient()
|
||||
|
||||
return await client.queryContractSmart(ENV.ADDRESS_ORACLE, {
|
||||
price: {
|
||||
denom,
|
||||
},
|
||||
})
|
||||
} catch (ex) {
|
||||
throw ex
|
||||
}
|
||||
}
|
183
src/api/vaults/getDepositedVaults.ts
Normal file
183
src/api/vaults/getDepositedVaults.ts
Normal file
@ -0,0 +1,183 @@
|
||||
import moment from 'moment'
|
||||
|
||||
import { getClient } from 'api/cosmwasm-client'
|
||||
import { ENV } from 'constants/env'
|
||||
import getVaults from 'api/vaults/getVaults'
|
||||
import {
|
||||
Positions,
|
||||
VaultPosition,
|
||||
VaultPositionAmount,
|
||||
} from 'types/generated/mars-credit-manager/MarsCreditManager.types'
|
||||
import { BN } from 'utils/helpers'
|
||||
import getPrice from 'api/prices/getPrice'
|
||||
|
||||
async function getUnlocksAtTimestamp(unlockingId: number, vaultAddress: string) {
|
||||
try {
|
||||
const client = await getClient()
|
||||
|
||||
const vaultExtension = (await client.queryContractSmart(vaultAddress, {
|
||||
vault_extension: { lockup: { unlocking_position: { lockup_id: unlockingId } } },
|
||||
})) as VaultExtensionResponse
|
||||
|
||||
return Number(vaultExtension.release_at.at_time) / 1e6
|
||||
} catch (ex) {
|
||||
throw ex
|
||||
}
|
||||
}
|
||||
|
||||
async function getVaultPositionStatusAndUnlockTime(
|
||||
vaultPosition: VaultPosition,
|
||||
): Promise<[VaultStatus, number | undefined]> {
|
||||
const amount = vaultPosition.amount
|
||||
|
||||
if ('unlocked' in amount) return ['unlocked', undefined]
|
||||
|
||||
if (amount.locking.unlocking.length) {
|
||||
const unlocksAtTimestamp = await getUnlocksAtTimestamp(
|
||||
amount.locking.unlocking[0].id,
|
||||
vaultPosition.vault.address,
|
||||
)
|
||||
|
||||
if (moment(unlocksAtTimestamp).isBefore(new Date())) {
|
||||
return ['unlocked', unlocksAtTimestamp]
|
||||
}
|
||||
|
||||
return ['unlocking', unlocksAtTimestamp]
|
||||
} else {
|
||||
return ['active', undefined]
|
||||
}
|
||||
}
|
||||
|
||||
function flatVaultPositionAmount(
|
||||
vaultPositionAmount: VaultPositionAmount,
|
||||
): VaultPositionFlatAmounts {
|
||||
const amounts = {
|
||||
locked: '0',
|
||||
unlocking: '0',
|
||||
unlocked: '0',
|
||||
}
|
||||
|
||||
if ('locking' in vaultPositionAmount) {
|
||||
const { locked, unlocking } = vaultPositionAmount.locking
|
||||
amounts.locked = locked
|
||||
amounts.unlocking = unlocking[0]?.coin.amount ?? '0'
|
||||
} else if ('unlocked' in vaultPositionAmount) {
|
||||
amounts.unlocked = vaultPositionAmount.unlocked
|
||||
}
|
||||
|
||||
return amounts
|
||||
}
|
||||
|
||||
async function getLpTokensForVaultPosition(
|
||||
vault: Vault,
|
||||
vaultPosition: VaultPosition,
|
||||
): Promise<Coin[]> {
|
||||
try {
|
||||
const client = await getClient()
|
||||
const amounts = flatVaultPositionAmount(vaultPosition.amount)
|
||||
const totalAmount = BN(amounts.locked)
|
||||
.plus(BN(amounts.unlocked))
|
||||
.plus(BN(amounts.unlocking))
|
||||
.toString()
|
||||
|
||||
const lpAmount = await client.queryContractSmart(vault.address, {
|
||||
preview_redeem: {
|
||||
amount: totalAmount,
|
||||
},
|
||||
})
|
||||
|
||||
const lpTokens: Coin[] = await client.queryContractSmart(ENV.ADDRESS_CREDIT_MANAGER, {
|
||||
estimate_withdraw_liquidity: {
|
||||
lp_token: {
|
||||
amount: lpAmount,
|
||||
denom: vault.denoms.lp,
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
const primaryLpToken = lpTokens.find((t) => t.denom === vault.denoms.primary) ?? {
|
||||
amount: '0',
|
||||
denom: vault.denoms.primary,
|
||||
}
|
||||
const secondaryLpToken = lpTokens.find((t) => t.denom === vault.denoms.secondary) ?? {
|
||||
amount: '0',
|
||||
denom: vault.denoms.secondary,
|
||||
}
|
||||
|
||||
return [primaryLpToken, secondaryLpToken]
|
||||
} catch (ex) {
|
||||
throw ex
|
||||
}
|
||||
}
|
||||
|
||||
async function getVaultValuesAndAmounts(
|
||||
vault: Vault,
|
||||
vaultPosition: VaultPosition,
|
||||
): Promise<VaultValuesAndAmounts> {
|
||||
try {
|
||||
const pricesQueries = Promise.all([
|
||||
getPrice(vault.denoms.primary),
|
||||
getPrice(vault.denoms.secondary),
|
||||
])
|
||||
|
||||
const lpTokensQuery = getLpTokensForVaultPosition(vault, vaultPosition)
|
||||
|
||||
const [[primaryLpToken, secondaryLpToken], [primaryAsset, secondaryAsset]] = await Promise.all([
|
||||
lpTokensQuery,
|
||||
pricesQueries,
|
||||
])
|
||||
|
||||
return {
|
||||
amounts: {
|
||||
primary: BN(primaryLpToken.amount),
|
||||
secondary: BN(secondaryLpToken.amount),
|
||||
},
|
||||
values: {
|
||||
primary: BN(primaryLpToken.amount).multipliedBy(BN(primaryAsset.price)),
|
||||
secondary: BN(secondaryLpToken.amount).multipliedBy(BN(secondaryAsset.price)),
|
||||
},
|
||||
}
|
||||
} catch (ex) {
|
||||
throw ex
|
||||
}
|
||||
}
|
||||
|
||||
async function getDepositedVaults(accountId: string): Promise<DepositedVault[]> {
|
||||
try {
|
||||
const client = await getClient()
|
||||
|
||||
const positionsQuery = client.queryContractSmart(ENV.ADDRESS_CREDIT_MANAGER, {
|
||||
positions: {
|
||||
account_id: accountId,
|
||||
},
|
||||
}) as Promise<Positions>
|
||||
|
||||
const [positions, allVaults] = await Promise.all([positionsQuery, getVaults()])
|
||||
|
||||
const depositedVaults = positions.vaults.map(async (vaultPosition) => {
|
||||
const vault = allVaults.find((v) => v.address === vaultPosition.vault.address)
|
||||
|
||||
if (!vault) {
|
||||
throw 'Could not find the deposited vault among all vaults'
|
||||
}
|
||||
|
||||
const [[status, unlocksAt], valuesAndAmounts] = await Promise.all([
|
||||
getVaultPositionStatusAndUnlockTime(vaultPosition),
|
||||
getVaultValuesAndAmounts(vault, vaultPosition),
|
||||
])
|
||||
|
||||
return {
|
||||
...vault,
|
||||
status,
|
||||
unlocksAt,
|
||||
...valuesAndAmounts,
|
||||
}
|
||||
})
|
||||
|
||||
return await Promise.all(depositedVaults)
|
||||
} catch (ex) {
|
||||
throw ex
|
||||
}
|
||||
}
|
||||
|
||||
export default getDepositedVaults
|
@ -5,7 +5,6 @@ import { getClient } from 'api/cosmwasm-client'
|
||||
|
||||
export default async function getAccounts(address: string): Promise<Account[]> {
|
||||
const accountIds: string[] = await getWalletAccountIds(address)
|
||||
|
||||
const client = await getClient()
|
||||
|
||||
const $accounts: Promise<AccountResponse>[] = accountIds.map((accountId) =>
|
||||
|
9
src/hooks/useDepositedVaults.ts
Normal file
9
src/hooks/useDepositedVaults.ts
Normal file
@ -0,0 +1,9 @@
|
||||
import useSWR from 'swr'
|
||||
|
||||
import getDepositedVaults from 'api/vaults/getDepositedVaults'
|
||||
|
||||
export default function useDepositedVaults(accountId: string) {
|
||||
return useSWR(`depositedVaultsByAccount-${accountId}`, () => getDepositedVaults(accountId), {
|
||||
suspense: true,
|
||||
})
|
||||
}
|
32
src/types/interfaces/vaults.d.ts
vendored
32
src/types/interfaces/vaults.d.ts
vendored
@ -1,3 +1,4 @@
|
||||
type BigNumber = import('bignumber.js').BigNumber
|
||||
interface VaultMetaData {
|
||||
address: string
|
||||
name: string
|
||||
@ -37,15 +38,34 @@ interface Vault extends VaultConfig {
|
||||
apy: number | null
|
||||
}
|
||||
|
||||
interface ActiveVault extends Vault {
|
||||
status: 'active' | 'unlocking' | 'unlocked'
|
||||
interface VaultValuesAndAmounts {
|
||||
amounts: {
|
||||
primary: number
|
||||
secondary: number
|
||||
primary: BigNumber
|
||||
secondary: BigNumber
|
||||
}
|
||||
values: {
|
||||
primary: number
|
||||
secondary: number
|
||||
primary: BigNumber
|
||||
secondary: BigNumber
|
||||
}
|
||||
}
|
||||
|
||||
type VaultStatus = 'active' | 'unlocking' | 'unlocked'
|
||||
interface DepositedVault extends Vault, VaultValuesAndAmounts {
|
||||
status: VaultStatus
|
||||
unlocksAt?: number
|
||||
}
|
||||
|
||||
interface VaultExtensionResponse {
|
||||
base_token_amount: string
|
||||
id: number
|
||||
owner: string
|
||||
release_at: {
|
||||
at_time: string
|
||||
}
|
||||
}
|
||||
|
||||
interface VaultPositionFlatAmounts {
|
||||
locked: string
|
||||
unlocking: string
|
||||
unlocked: string
|
||||
}
|
||||
|
@ -1,5 +1,6 @@
|
||||
import BigNumber from 'bignumber.js'
|
||||
|
||||
BigNumber.config({ EXPONENTIAL_AT: 1e9 })
|
||||
export function BN(n: BigNumber.Value) {
|
||||
return new BigNumber(n)
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user