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[]> {
|
export default async function getAccounts(address: string): Promise<Account[]> {
|
||||||
const accountIds: string[] = await getWalletAccountIds(address)
|
const accountIds: string[] = await getWalletAccountIds(address)
|
||||||
|
|
||||||
const client = await getClient()
|
const client = await getClient()
|
||||||
|
|
||||||
const $accounts: Promise<AccountResponse>[] = accountIds.map((accountId) =>
|
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 {
|
interface VaultMetaData {
|
||||||
address: string
|
address: string
|
||||||
name: string
|
name: string
|
||||||
@ -37,15 +38,34 @@ interface Vault extends VaultConfig {
|
|||||||
apy: number | null
|
apy: number | null
|
||||||
}
|
}
|
||||||
|
|
||||||
interface ActiveVault extends Vault {
|
interface VaultValuesAndAmounts {
|
||||||
status: 'active' | 'unlocking' | 'unlocked'
|
|
||||||
amounts: {
|
amounts: {
|
||||||
primary: number
|
primary: BigNumber
|
||||||
secondary: number
|
secondary: BigNumber
|
||||||
}
|
}
|
||||||
values: {
|
values: {
|
||||||
primary: number
|
primary: BigNumber
|
||||||
secondary: number
|
secondary: BigNumber
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type VaultStatus = 'active' | 'unlocking' | 'unlocked'
|
||||||
|
interface DepositedVault extends Vault, VaultValuesAndAmounts {
|
||||||
|
status: VaultStatus
|
||||||
unlocksAt?: number
|
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'
|
import BigNumber from 'bignumber.js'
|
||||||
|
|
||||||
|
BigNumber.config({ EXPONENTIAL_AT: 1e9 })
|
||||||
export function BN(n: BigNumber.Value) {
|
export function BN(n: BigNumber.Value) {
|
||||||
return new BigNumber(n)
|
return new BigNumber(n)
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user