Skip to content

Commit a2cfc9f

Browse files
authored
fix(beefy): add fallbackPriceUsd to CLM positions (#527)
This also adds fallbackPriceUsd for CLM positions. So Beefy CLM positions don't miss part of the value. | Before | After | |-|-| | ![IMG_7091](https://github.com/user-attachments/assets/dc0e0b1c-9cd6-4897-aea7-b359c981ca7d) | ![IMG_7092](https://github.com/user-attachments/assets/561af152-57dd-4ddc-8c2e-4c018db26e20) | Before the change, because we don't have a $ price for MIGGLES, the MIGGLES-WETH position $ value was only showing the WETH part.
1 parent 50d113c commit a2cfc9f

File tree

2 files changed

+98
-48
lines changed

2 files changed

+98
-48
lines changed

src/apps/beefy/api.ts

+39-5
Original file line numberDiff line numberDiff line change
@@ -78,9 +78,43 @@ export async function getBeefyVaults(
7878
}
7979
}
8080

81-
export async function getBeefyLpsPrices(): Promise<Record<string, number>> {
82-
const prices = await got
83-
.get(`https://api.beefy.finance/lps`)
84-
.json<Record<string, number>>()
85-
return prices
81+
export async function getBeefyPrices(
82+
networkId: NetworkId,
83+
): Promise<Record<string, number | undefined>> {
84+
const [lpsPrices, tokenPrices, tokens] = await Promise.all([
85+
got
86+
.get(`https://api.beefy.finance/lps`)
87+
.json<Record<string, number | undefined>>(),
88+
got
89+
.get(`https://api.beefy.finance/prices`)
90+
.json<Record<string, number | undefined>>(),
91+
got
92+
.get(
93+
`https://api.beefy.finance/tokens/${NETWORK_ID_TO_BEEFY_BLOCKCHAIN_ID[networkId]}`,
94+
)
95+
.json<
96+
Record<
97+
string, // oracleId
98+
{
99+
// These are the fields we need, but there are more
100+
address: string
101+
oracle: string // examples: 'lps', 'tokens'
102+
oracleId: string
103+
}
104+
>
105+
>(),
106+
])
107+
108+
// Combine lps prices with token prices
109+
return {
110+
...lpsPrices,
111+
...Object.fromEntries(
112+
Object.entries(tokens)
113+
.filter(([, { oracle }]) => oracle === 'tokens')
114+
.map(([, { address, oracleId }]) => [
115+
address.toLowerCase(),
116+
tokenPrices[oracleId],
117+
]),
118+
),
119+
}
86120
}

src/apps/beefy/positions.ts

+59-43
Original file line numberDiff line numberDiff line change
@@ -17,12 +17,9 @@ import {
1717
beefyClmVaultsMulticallBytecode,
1818
} from './abis/beefy-clm-vaults-multicall'
1919
import { beefyV2AppMulticallAbi } from './abis/beefy-v2-app-multicall'
20-
import {
21-
BaseBeefyVault,
22-
GovVault,
23-
getBeefyLpsPrices,
24-
getBeefyVaults,
25-
} from './api'
20+
import { BaseBeefyVault, GovVault, getBeefyPrices, getBeefyVaults } from './api'
21+
22+
type BeefyPrices = Awaited<ReturnType<typeof getBeefyPrices>>
2623

2724
// Fetched addresses from https://github.com/beefyfinance/beefy-v2/blob/main/src/config/config.tsx
2825
const BEEFY_MULTICALL_ADDRESS: {
@@ -46,37 +43,40 @@ const BEEFY_MULTICALL_ADDRESS: {
4643
const beefyAppTokenDefinition = (
4744
networkId: NetworkId,
4845
vault: BaseBeefyVault,
49-
prices: Record<string, number>,
50-
): AppTokenPositionDefinition => ({
51-
type: 'app-token-definition',
52-
networkId,
53-
address: vault.earnedTokenAddress.toLowerCase(),
54-
tokens: [
55-
{
56-
address: vault.tokenAddress.toLowerCase(),
57-
networkId,
58-
fallbackPriceUsd: prices[vault.id]
59-
? toSerializedDecimalNumber(prices[vault.id])
60-
: undefined,
46+
prices: BeefyPrices,
47+
): AppTokenPositionDefinition => {
48+
const priceUsd = prices[vault.id]
49+
return {
50+
type: 'app-token-definition',
51+
networkId,
52+
address: vault.earnedTokenAddress.toLowerCase(),
53+
tokens: [
54+
{
55+
address: vault.tokenAddress.toLowerCase(),
56+
networkId,
57+
fallbackPriceUsd: priceUsd
58+
? toSerializedDecimalNumber(priceUsd)
59+
: undefined,
60+
},
61+
],
62+
displayProps: () => {
63+
return {
64+
title: vault.name + (vault.status === 'eol' ? ' (Retired)' : ''),
65+
description: 'Vault',
66+
imageUrl:
67+
'https://raw.githubusercontent.com/valora-inc/dapp-list/main/assets/beefy.png',
68+
}
6169
},
62-
],
63-
displayProps: () => {
64-
return {
65-
title: vault.name + (vault.status === 'eol' ? ' (Retired)' : ''),
66-
description: 'Vault',
67-
imageUrl:
68-
'https://raw.githubusercontent.com/valora-inc/dapp-list/main/assets/beefy.png',
69-
}
70-
},
71-
pricePerShare: async ({ tokensByTokenId }) => {
72-
const tokenId = getTokenId({
73-
address: vault.tokenAddress,
74-
networkId,
75-
})
76-
const { decimals } = tokensByTokenId[tokenId]
77-
return [toDecimalNumber(BigInt(vault.pricePerFullShare), decimals)]
78-
},
79-
})
70+
pricePerShare: async ({ tokensByTokenId }) => {
71+
const tokenId = getTokenId({
72+
address: vault.tokenAddress,
73+
networkId,
74+
})
75+
const { decimals } = tokensByTokenId[tokenId]
76+
return [toDecimalNumber(BigInt(vault.pricePerFullShare), decimals)]
77+
},
78+
}
79+
}
8080

8181
// CLM = Cowcentrated Liquidity Manager: https://docs.beefy.finance/beefy-products/clm
8282
interface ClmVaultBalanceInfo {
@@ -91,6 +91,7 @@ const beefyConcentratedContractDefinition = (
9191
vault: BaseBeefyVault,
9292
balanceInfo: ClmVaultBalanceInfo | undefined,
9393
description: string,
94+
prices: BeefyPrices,
9495
): ContractPositionDefinition | null => {
9596
if (!balanceInfo) {
9697
return null
@@ -100,10 +101,17 @@ const beefyConcentratedContractDefinition = (
100101
type: 'contract-position-definition',
101102
networkId,
102103
address: vault.earnedTokenAddress.toLowerCase(),
103-
tokens: vault.depositTokenAddresses.map((address) => ({
104-
address: address.toLowerCase(),
105-
networkId,
106-
})),
104+
tokens: vault.depositTokenAddresses.map((address) => {
105+
const addressLower = address.toLowerCase()
106+
const priceUsd = prices[addressLower]
107+
return {
108+
address: addressLower,
109+
networkId,
110+
fallbackPriceUsd: priceUsd
111+
? toSerializedDecimalNumber(priceUsd)
112+
: undefined,
113+
}
114+
}),
107115
displayProps: () => {
108116
return {
109117
title: vault.name + (vault.status === 'eol' ? ' (Retired)' : ''),
@@ -140,6 +148,7 @@ const beefyBaseVaultsPositions = async (
140148
address: Address,
141149
vaults: BaseBeefyVault[],
142150
multicallAddress: Address,
151+
prices: BeefyPrices,
143152
) => {
144153
const client = getClient(networkId)
145154

@@ -171,8 +180,6 @@ const beefyBaseVaultsPositions = async (
171180
return []
172181
}
173182

174-
const prices = await getBeefyLpsPrices()
175-
176183
const clmVaults = userVaults.filter((vault) => vault.type === 'cowcentrated')
177184
const info =
178185
clmVaults.length === 0
@@ -195,6 +202,7 @@ const beefyBaseVaultsPositions = async (
195202
i.token1 === vault.depositTokenAddresses[1],
196203
),
197204
'CLM Vault',
205+
prices,
198206
)
199207
: beefyAppTokenDefinition(networkId, vault, prices),
200208
)
@@ -207,6 +215,7 @@ const beefyGovVaultsPositions = async (
207215
vaults: BaseBeefyVault[],
208216
govVaults: GovVault[],
209217
multicallAddress: Address,
218+
prices: BeefyPrices,
210219
) => {
211220
const client = getClient(networkId)
212221

@@ -278,6 +287,7 @@ const beefyGovVaultsPositions = async (
278287
i.token1 === vault!.depositTokenAddresses[1],
279288
),
280289
'CLM Pool',
290+
prices,
281291
),
282292
)
283293
.filter((position): position is ContractPositionDefinition => !!position)
@@ -297,20 +307,26 @@ const hook: PositionsHook = {
297307
return []
298308
}
299309

300-
const { vaults, govVaults } = await getBeefyVaults(networkId)
310+
const [{ vaults, govVaults }, prices] = await Promise.all([
311+
getBeefyVaults(networkId),
312+
getBeefyPrices(networkId),
313+
])
314+
301315
return [
302316
...(await beefyBaseVaultsPositions(
303317
networkId,
304318
address as Address,
305319
vaults,
306320
multicallAddress,
321+
prices,
307322
)),
308323
...(await beefyGovVaultsPositions(
309324
networkId,
310325
address as Address,
311326
vaults,
312327
govVaults,
313328
multicallAddress,
329+
prices,
314330
)),
315331
]
316332
},

0 commit comments

Comments
 (0)