From 3709ca28dcd43a6a458deca9ee191a8f6a7e24e7 Mon Sep 17 00:00:00 2001 From: matheus1lva Date: Mon, 26 Jan 2026 11:51:46 -0300 Subject: [PATCH 1/4] feat: consume Kong estimated APRs for V2 Curve/Convex/Velodrome/Aerodrome vaults Replace local RPC-based forward APR calculations with pre-computed estimated APRs from Kong's GraphQL API for V2 vaults. This integration reduces RPC call volume and improves performance while maintaining full backward compatibility. Changes: - Add TKongEstimatedApr and TKongEstimatedAprComponents types to Kong client and models - Update Kong GraphQL queries to fetch performance.estimated field with all components - Extract and store estimated APR data in Kong indexer - Add GetKongEstimatedAPY() storage accessor function - Modify forward APY calculation to prioritize Kong data with graceful fallback to local computation - Update apr-oracle-integration.md with V2 estimated APR integration documentation Supported chains: Ethereum (1), Optimism (10), Fantom (250), Arbitrum (42161), Base (8453) Supported strategies: Curve, Convex, Velodrome, Aerodrome Implements: https://github.com/yearn/ydaemon/issues/560 --- docs/apr-oracle-integration.md | 91 ++++++++++++++++++++++++++ internal/indexer/indexer.kong.go | 27 +++++++- internal/kong/client.go | 54 ++++++++++++++- internal/models/vaults.go | 22 ++++++- internal/storage/elem.vaults.go | 15 +++++ processes/apr/forward.curve.helpers.go | 56 ++++++++++++++++ processes/apr/main.go | 62 +++++++++++------- 7 files changed, 302 insertions(+), 25 deletions(-) diff --git a/docs/apr-oracle-integration.md b/docs/apr-oracle-integration.md index c0b96ffd0..2ffc505a0 100644 --- a/docs/apr-oracle-integration.md +++ b/docs/apr-oracle-integration.md @@ -32,3 +32,94 @@ The external API response structure for vaults remains unchanged to ensure backw } } ``` + +--- + +## V2 Vault Estimated APR Integration (Kong) + +As of the implementation of [issue #560](https://github.com/yearn/ydaemon/issues/560), V2 vaults with Curve, Convex, Velodrome, and Aerodrome strategies now prioritize pre-calculated estimated APRs from Kong over local RPC-based calculations. + +### Overview + +Previously, `yDaemon` computed forward-looking APRs for V2 Curve-like vaults (Curve, Convex, Velodrome, Aerodrome) by making multiple on-chain RPC calls to calculate: +- Gauge boost values +- Pool APY from Curve subgraph +- Reward rates and token prices +- Various fee components + +This approach was: +- **RPC-intensive**: Required multiple multicalls per vault +- **Computation-heavy**: Performed complex calculations locally +- **Slower**: Dependent on RPC response times + +### New Data Source + +The `performance.estimated` field from Kong's GraphQL API is now the **primary** source for V2 forward APR data: +- **Estimated APR**: Pre-computed annualized rate +- **Estimated APY**: Pre-computed annualized yield (compounded) +- **Type**: Strategy type identifier (e.g., `"crv"`, `"v2:velo"`) +- **Components**: Detailed breakdown including: + - `boost`: Gauge boost multiplier + - `poolAPY`: Pool swap fee APY + - `boostedAPR`: Boosted reward APR + - `baseAPR`: Base reward APR + - `rewardsAPR`: Additional rewards APR + - `rewardsAPY`: Additional rewards APY (compounded) + - `cvxAPR`: Convex-specific APR + - `keepCRV`: Percentage of CRV kept vs. swapped + - `keepVelo`: Percentage of VELO kept vs. swapped + +### Supported Chains + +The estimated APR integration applies to V2 vaults on: +- **Ethereum (chainId: 1)**: Curve, Convex +- **Optimism (chainId: 10)**: Velodrome +- **Fantom (chainId: 250)**: Curve +- **Arbitrum (chainId: 42161)**: Curve +- **Base (chainId: 8453)**: Aerodrome + +### Implementation Details + +#### Priority System +1. **Primary**: Check for Kong `performance.estimated` data +2. **Fallback**: If Kong data unavailable, perform local RPC-based calculation +3. **Graceful degradation**: System continues to function even if Kong is temporarily unavailable + +#### Internal Logic +- **Kong Indexer** (`internal/indexer/indexer.kong.go`): Fetches and stores estimated APR data from Kong GraphQL API +- **Storage Accessor** (`internal/storage/elem.vaults.go`): Provides `GetKongEstimatedAPY()` function to retrieve cached Kong data +- **APR Calculation** (`processes/apr/main.go`): Checks Kong data first before falling back to local computation +- **Helper Function** (`processes/apr/forward.curve.helpers.go`): `convertKongEstimatedAprToForwardAPY()` converts Kong format to internal `TForwardAPY` structure + +#### Benefits +- **Reduced RPC Calls**: Eliminates multiple multicalls for gauge data, prices, and boost calculations +- **Faster Response**: Pre-computed data from Kong cache vs. real-time RPC queries +- **Consistency**: Kong serves as single source of truth for APR calculations +- **Maintained Components**: All APR component breakdowns preserved in API responses + +### API Response + +The external API response structure remains **fully backward compatible**. The `apr.forwardAPR` object structure is unchanged: + +```json +"forwardAPR": { + "type": "crv", // From Kong estimated.type + "netAPY": 0.156, // From Kong estimated.apy + "composite": { + "boost": 2.5, // From Kong estimated.components.boost + "poolAPY": 0.023, // From Kong estimated.components.poolAPY + "boostedAPR": 0.187, // From Kong estimated.components.boostedAPR + "baseAPR": 0.075, // From Kong estimated.components.baseAPR + "cvxAPR": 0.045, // From Kong estimated.components.cvxAPR (Convex only) + "rewardsAPY": 0.034, // From Kong estimated.components.rewardsAPY + "keepCRV": 0.1 // From Kong estimated.components.keepCRV + } +} +``` + +### Migration Notes + +- **No Breaking Changes**: API consumers experience no differences in response structure +- **Automatic Fallback**: If Kong estimated data is unavailable, yDaemon seamlessly falls back to local computation +- **Strategy Support**: Works for all Curve, Convex, Velodrome, and Aerodrome V2 strategies + diff --git a/internal/indexer/indexer.kong.go b/internal/indexer/indexer.kong.go index 6e6522c78..2752f3cd5 100644 --- a/internal/indexer/indexer.kong.go +++ b/internal/indexer/indexer.kong.go @@ -67,13 +67,38 @@ func IndexNewVaults(chainID uint64) map[common.Address]models.TVaultsFromRegistr }) } - // Extract performance data from Kong response (oracle APR/APY) + // Extract performance data from Kong response (oracle APR/APY and estimated APR) performance := models.TKongPerformance{} if data.Vault.Performance != nil { performance.Oracle = models.TKongOracle{ Apr: data.Vault.Performance.Oracle.Apr, Apy: data.Vault.Performance.Oracle.Apy, } + + // Extract estimated APR if available + if data.Vault.Performance.Estimated != nil { + components := &models.TKongEstimatedAprComponents{} + if data.Vault.Performance.Estimated.Components != nil { + components = &models.TKongEstimatedAprComponents{ + Boost: data.Vault.Performance.Estimated.Components.Boost, + PoolAPY: data.Vault.Performance.Estimated.Components.PoolAPY, + BoostedAPR: data.Vault.Performance.Estimated.Components.BoostedAPR, + BaseAPR: data.Vault.Performance.Estimated.Components.BaseAPR, + RewardsAPR: data.Vault.Performance.Estimated.Components.RewardsAPR, + RewardsAPY: data.Vault.Performance.Estimated.Components.RewardsAPY, + CvxAPR: data.Vault.Performance.Estimated.Components.CvxAPR, + KeepCRV: data.Vault.Performance.Estimated.Components.KeepCRV, + KeepVelo: data.Vault.Performance.Estimated.Components.KeepVelo, + } + } + + performance.Estimated = &models.TKongEstimatedApr{ + Apr: data.Vault.Performance.Estimated.Apr, + Apy: data.Vault.Performance.Estimated.Apy, + Type: data.Vault.Performance.Estimated.Type, + Components: components, + } + } } kongSchema := models.TKongVaultSchema{ diff --git a/internal/kong/client.go b/internal/kong/client.go index 0702d3c70..83ed35911 100644 --- a/internal/kong/client.go +++ b/internal/kong/client.go @@ -77,8 +77,28 @@ type KongOracle struct { Apy *float64 `json:"apy"` // Float or null } +type KongEstimatedAprComponents struct { + Boost *float64 `json:"boost"` + PoolAPY *float64 `json:"poolAPY"` + BoostedAPR *float64 `json:"boostedAPR"` + BaseAPR *float64 `json:"baseAPR"` + RewardsAPR *float64 `json:"rewardsAPR"` + RewardsAPY *float64 `json:"rewardsAPY"` + CvxAPR *float64 `json:"cvxAPR"` + KeepCRV *float64 `json:"keepCRV"` + KeepVelo *float64 `json:"keepVelo"` +} + +type KongEstimatedApr struct { + Apr *float64 `json:"apr"` + Apy *float64 `json:"apy"` + Type string `json:"type"` + Components *KongEstimatedAprComponents `json:"components"` +} + type KongPerformance struct { - Oracle KongOracle `json:"oracle"` + Oracle KongOracle `json:"oracle"` + Estimated *KongEstimatedApr `json:"estimated"` // Estimated APR from Kong } type KongVault struct { @@ -215,6 +235,22 @@ func (c *Client) FetchVaultsForChain(ctx context.Context, chainID uint64) ([]Kon apr apy } + estimated { + apr + apy + type + components { + boost + poolAPY + boostedAPR + baseAPR + rewardsAPR + rewardsAPY + cvxAPR + keepCRV + keepVelo + } + } } apy { pricePerShare @@ -302,6 +338,22 @@ func (c *Client) FetchAllVaults(ctx context.Context) (map[uint64][]KongVault, er apr apy } + estimated { + apr + apy + type + components { + boost + poolAPY + boostedAPR + baseAPR + rewardsAPR + rewardsAPY + cvxAPR + keepCRV + keepVelo + } + } } apy { pricePerShare diff --git a/internal/models/vaults.go b/internal/models/vaults.go index 7b2e1d0a5..c604f1197 100644 --- a/internal/models/vaults.go +++ b/internal/models/vaults.go @@ -321,8 +321,28 @@ type TKongOracle struct { Apy *float64 `json:"apy"` // Float or null } +type TKongEstimatedAprComponents struct { + Boost *float64 `json:"boost"` + PoolAPY *float64 `json:"poolAPY"` + BoostedAPR *float64 `json:"boostedAPR"` + BaseAPR *float64 `json:"baseAPR"` + RewardsAPR *float64 `json:"rewardsAPR"` + RewardsAPY *float64 `json:"rewardsAPY"` + CvxAPR *float64 `json:"cvxAPR"` + KeepCRV *float64 `json:"keepCRV"` + KeepVelo *float64 `json:"keepVelo"` +} + +type TKongEstimatedApr struct { + Apr *float64 `json:"apr"` + Apy *float64 `json:"apy"` + Type string `json:"type"` + Components *TKongEstimatedAprComponents `json:"components"` +} + type TKongPerformance struct { - Oracle TKongOracle `json:"oracle"` + Oracle TKongOracle `json:"oracle"` + Estimated *TKongEstimatedApr `json:"estimated"` // Estimated APR from Kong } type TKongVaultSchema struct { diff --git a/internal/storage/elem.vaults.go b/internal/storage/elem.vaults.go index b6b75864e..27a4c5031 100644 --- a/internal/storage/elem.vaults.go +++ b/internal/storage/elem.vaults.go @@ -472,4 +472,19 @@ func GetKongOracleAPY(chainID uint64, vaultAddress common.Address) (*float64, *f return nil, nil, false } return data.Performance.Oracle.Apr, data.Performance.Oracle.Apy, true +} + +/************************************************************************************************** +** GetKongEstimatedAPY retrieves estimated APR data from Kong for a vault +** Returns the estimated APR struct and a boolean indicating if data was found +**************************************************************************************************/ +func GetKongEstimatedAPY(chainID uint64, vaultAddress common.Address) (*models.TKongEstimatedApr, bool) { + data, ok := GetKongVaultData(chainID, vaultAddress) + if !ok { + return nil, false + } + if data.Performance.Estimated == nil { + return nil, false + } + return data.Performance.Estimated, true } \ No newline at end of file diff --git a/processes/apr/forward.curve.helpers.go b/processes/apr/forward.curve.helpers.go index 2116c2485..a81b0b65b 100644 --- a/processes/apr/forward.curve.helpers.go +++ b/processes/apr/forward.curve.helpers.go @@ -375,3 +375,59 @@ func computeCurveLikeForwardAPY( }, } } + +/************************************************************************************************** +** convertKongEstimatedAprToForwardAPY converts Kong estimated APR data to TForwardAPY format +** Returns (forwardAPY, hasData) where hasData indicates if valid Kong data was found +**************************************************************************************************/ +func convertKongEstimatedAprToForwardAPY(chainID uint64, vaultAddress common.Address) (TForwardAPY, bool) { + estimatedApr, ok := storage.GetKongEstimatedAPY(chainID, vaultAddress) + if !ok || estimatedApr == nil || estimatedApr.Apy == nil { + return TForwardAPY{}, false + } + + // Convert to float64 values, defaulting to 0 if nil + var boost, poolAPY, boostedAPR, baseAPR, rewardsAPY, cvxAPR, keepCRV, keepVelo float64 + + if estimatedApr.Components != nil { + if estimatedApr.Components.Boost != nil { + boost = *estimatedApr.Components.Boost + } + if estimatedApr.Components.PoolAPY != nil { + poolAPY = *estimatedApr.Components.PoolAPY + } + if estimatedApr.Components.BoostedAPR != nil { + boostedAPR = *estimatedApr.Components.BoostedAPR + } + if estimatedApr.Components.BaseAPR != nil { + baseAPR = *estimatedApr.Components.BaseAPR + } + if estimatedApr.Components.RewardsAPY != nil { + rewardsAPY = *estimatedApr.Components.RewardsAPY + } + if estimatedApr.Components.CvxAPR != nil { + cvxAPR = *estimatedApr.Components.CvxAPR + } + if estimatedApr.Components.KeepCRV != nil { + keepCRV = *estimatedApr.Components.KeepCRV + } + if estimatedApr.Components.KeepVelo != nil { + keepVelo = *estimatedApr.Components.KeepVelo + } + } + + return TForwardAPY{ + Type: estimatedApr.Type, + NetAPY: bigNumber.NewFloat(*estimatedApr.Apy), + Composite: TCompositeData{ + Boost: bigNumber.NewFloat(boost), + PoolAPY: bigNumber.NewFloat(poolAPY), + BoostedAPR: bigNumber.NewFloat(boostedAPR), + BaseAPR: bigNumber.NewFloat(baseAPR), + CvxAPR: bigNumber.NewFloat(cvxAPR), + RewardsAPY: bigNumber.NewFloat(rewardsAPY), + KeepCRV: bigNumber.NewFloat(keepCRV), + KeepVelo: bigNumber.NewFloat(keepVelo), + }, + }, true +} diff --git a/processes/apr/main.go b/processes/apr/main.go index 3aa0ce42c..015e6a25f 100644 --- a/processes/apr/main.go +++ b/processes/apr/main.go @@ -126,40 +126,58 @@ func ComputeChainAPY(chainID uint64) { /********************************************************************************************** ** If it's a Curve Vault (has a Curve, Convex or Frax strategy), we can estimate the forward ** APY, aka the expected APY we will get for the upcoming period. - ** We need to compute it and store it in our ForwardAPY structure. + ** Priority: Use Kong estimated APR if available, otherwise compute locally. **********************************************************************************************/ if isCurveVault(allStrategiesForVault) { - forwardAPY := computeCurveLikeForwardAPY( - vault, - allStrategiesForVault, - gauges, - pools, - subgraphData, - fraxPools, - ) - if forwardAPY.NetAPY != nil { - vaultAPY.ForwardAPY = forwardAPY + // Try to get estimated APR from Kong first + if kongForwardAPY, hasKongData := convertKongEstimatedAprToForwardAPY(chainID, vault.Address); hasKongData { + vaultAPY.ForwardAPY = kongForwardAPY + } else { + // Fall back to local computation if Kong data not available + forwardAPY := computeCurveLikeForwardAPY( + vault, + allStrategiesForVault, + gauges, + pools, + subgraphData, + fraxPools, + ) + if forwardAPY.NetAPY != nil { + vaultAPY.ForwardAPY = forwardAPY + } } } /********************************************************************************************** ** If it's a Velo Vault (has a Velo or Aero strategy), we can estimate the forward APY, aka ** the expected APY we will get for the upcoming period. - ** We need to compute it and store it in our ForwardAPY structure. + ** Priority: Use Kong estimated APR if available, otherwise compute locally. **********************************************************************************************/ if veloPool, ok := isVeloVault(chainID, vault); ok { - vaultAPY.ForwardAPY = computeVeloLikeForwardAPY( - vault, - allStrategiesForVault, - veloPool, - ) + // Try to get estimated APR from Kong first + if kongForwardAPY, hasKongData := convertKongEstimatedAprToForwardAPY(chainID, vault.Address); hasKongData { + vaultAPY.ForwardAPY = kongForwardAPY + } else { + // Fall back to local computation if Kong data not available + vaultAPY.ForwardAPY = computeVeloLikeForwardAPY( + vault, + allStrategiesForVault, + veloPool, + ) + } } if aeroPool, ok := isAeroVault(chainID, vault); ok { - vaultAPY.ForwardAPY = computeVeloLikeForwardAPY( - vault, - allStrategiesForVault, - aeroPool, - ) + // Try to get estimated APR from Kong first + if kongForwardAPY, hasKongData := convertKongEstimatedAprToForwardAPY(chainID, vault.Address); hasKongData { + vaultAPY.ForwardAPY = kongForwardAPY + } else { + // Fall back to local computation if Kong data not available + vaultAPY.ForwardAPY = computeVeloLikeForwardAPY( + vault, + allStrategiesForVault, + aeroPool, + ) + } } /********************************************************************************************** From 3ff4778dac12f8ec8583f0d52de7c0af7d7e4224 Mon Sep 17 00:00:00 2001 From: matheus1lva Date: Wed, 28 Jan 2026 19:00:41 -0300 Subject: [PATCH 2/4] use kong when available --- processes/apr/main.go | 43 +++++++++++++++---------------------------- 1 file changed, 15 insertions(+), 28 deletions(-) diff --git a/processes/apr/main.go b/processes/apr/main.go index 015e6a25f..8d631360d 100644 --- a/processes/apr/main.go +++ b/processes/apr/main.go @@ -128,12 +128,19 @@ func ComputeChainAPY(chainID uint64) { ** APY, aka the expected APY we will get for the upcoming period. ** Priority: Use Kong estimated APR if available, otherwise compute locally. **********************************************************************************************/ - if isCurveVault(allStrategiesForVault) { - // Try to get estimated APR from Kong first - if kongForwardAPY, hasKongData := convertKongEstimatedAprToForwardAPY(chainID, vault.Address); hasKongData { - vaultAPY.ForwardAPY = kongForwardAPY - } else { - // Fall back to local computation if Kong data not available + /********************************************************************************************** + ** If it's a Curve Vault (has a Curve, Convex or Frax strategy), we can estimate the forward + ** APY, aka the expected APY we will get for the upcoming period. + ** Priority: Use Kong estimated APR if available, otherwise compute locally. + **********************************************************************************************/ + usedKongData := false + if kongForwardAPY, hasKongData := convertKongEstimatedAprToForwardAPY(chainID, vault.Address); hasKongData { + vaultAPY.ForwardAPY = kongForwardAPY + usedKongData = true + } + + if !usedKongData { + if isCurveVault(allStrategiesForVault) { forwardAPY := computeCurveLikeForwardAPY( vault, allStrategiesForVault, @@ -145,33 +152,13 @@ func ComputeChainAPY(chainID uint64) { if forwardAPY.NetAPY != nil { vaultAPY.ForwardAPY = forwardAPY } - } - } - - /********************************************************************************************** - ** If it's a Velo Vault (has a Velo or Aero strategy), we can estimate the forward APY, aka - ** the expected APY we will get for the upcoming period. - ** Priority: Use Kong estimated APR if available, otherwise compute locally. - **********************************************************************************************/ - if veloPool, ok := isVeloVault(chainID, vault); ok { - // Try to get estimated APR from Kong first - if kongForwardAPY, hasKongData := convertKongEstimatedAprToForwardAPY(chainID, vault.Address); hasKongData { - vaultAPY.ForwardAPY = kongForwardAPY - } else { - // Fall back to local computation if Kong data not available + } else if veloPool, ok := isVeloVault(chainID, vault); ok { vaultAPY.ForwardAPY = computeVeloLikeForwardAPY( vault, allStrategiesForVault, veloPool, ) - } - } - if aeroPool, ok := isAeroVault(chainID, vault); ok { - // Try to get estimated APR from Kong first - if kongForwardAPY, hasKongData := convertKongEstimatedAprToForwardAPY(chainID, vault.Address); hasKongData { - vaultAPY.ForwardAPY = kongForwardAPY - } else { - // Fall back to local computation if Kong data not available + } else if aeroPool, ok := isAeroVault(chainID, vault); ok { vaultAPY.ForwardAPY = computeVeloLikeForwardAPY( vault, allStrategiesForVault, From 7a39a918fa10b7b4e52866d3261debde0332f206 Mon Sep 17 00:00:00 2001 From: matheus1lva Date: Sat, 31 Jan 2026 19:54:10 -0300 Subject: [PATCH 3/4] update tests --- processes/apr/main.go | 46 +++---------------------------------------- 1 file changed, 3 insertions(+), 43 deletions(-) diff --git a/processes/apr/main.go b/processes/apr/main.go index 8d631360d..94ade0fad 100644 --- a/processes/apr/main.go +++ b/processes/apr/main.go @@ -54,10 +54,6 @@ func ComputeChainAPY(chainID uint64) { start := time.Now() logs.Warning("📈 [APY START]", "chain", chainID) allVaults, _ := storage.ListVaults(chainID) - gauges := storage.FetchCurveGauges(chainID) - pools := retrieveCurveGetPools(chainID) - subgraphData := retrieveCurveSubgraphData(chainID) - fraxPools := retrieveFraxPools() storage.RefreshGammaCalls(chainID) isOnGnosis := (chainID == 100) @@ -128,45 +124,9 @@ func ComputeChainAPY(chainID uint64) { ** APY, aka the expected APY we will get for the upcoming period. ** Priority: Use Kong estimated APR if available, otherwise compute locally. **********************************************************************************************/ - /********************************************************************************************** - ** If it's a Curve Vault (has a Curve, Convex or Frax strategy), we can estimate the forward - ** APY, aka the expected APY we will get for the upcoming period. - ** Priority: Use Kong estimated APR if available, otherwise compute locally. - **********************************************************************************************/ - usedKongData := false - if kongForwardAPY, hasKongData := convertKongEstimatedAprToForwardAPY(chainID, vault.Address); hasKongData { - vaultAPY.ForwardAPY = kongForwardAPY - usedKongData = true - } - - if !usedKongData { - if isCurveVault(allStrategiesForVault) { - forwardAPY := computeCurveLikeForwardAPY( - vault, - allStrategiesForVault, - gauges, - pools, - subgraphData, - fraxPools, - ) - if forwardAPY.NetAPY != nil { - vaultAPY.ForwardAPY = forwardAPY - } - } else if veloPool, ok := isVeloVault(chainID, vault); ok { - vaultAPY.ForwardAPY = computeVeloLikeForwardAPY( - vault, - allStrategiesForVault, - veloPool, - ) - } else if aeroPool, ok := isAeroVault(chainID, vault); ok { - vaultAPY.ForwardAPY = computeVeloLikeForwardAPY( - vault, - allStrategiesForVault, - aeroPool, - ) - } - } - + kongForwardAPY, _ := convertKongEstimatedAprToForwardAPY(chainID, vault.Address); + vaultAPY.ForwardAPY = kongForwardAPY + /********************************************************************************************** ** If it's a Gamma Vault, we can get the feeAPR as an estimate for the upcoming period, and we ** can retrieve the extraReward APRs. From e7b30076bcb8f406c615499cd4884253852ea9d5 Mon Sep 17 00:00:00 2001 From: matheus1lva Date: Sun, 1 Feb 2026 12:41:21 -0300 Subject: [PATCH 4/4] remove fallback --- internal/indexer/indexer.kong.go | 7 +++- processes/apr/main.go | 69 +++++++++++++++++++------------- 2 files changed, 48 insertions(+), 28 deletions(-) diff --git a/internal/indexer/indexer.kong.go b/internal/indexer/indexer.kong.go index 2752f3cd5..f0806bd51 100644 --- a/internal/indexer/indexer.kong.go +++ b/internal/indexer/indexer.kong.go @@ -44,6 +44,11 @@ func IndexNewVaults(chainID uint64) map[common.Address]models.TVaultsFromRegistr // Convert KongDebt to TKongDebt var debts []models.TKongDebt for _, debt := range data.Debts { + totalDebt := debt.TotalDebt + if totalDebt == nil { + zero := "0" + totalDebt = &zero + } debts = append(debts, models.TKongDebt{ Strategy: debt.Strategy, PerformanceFee: debt.PerformanceFee, @@ -52,7 +57,7 @@ func IndexNewVaults(chainID uint64) map[common.Address]models.TVaultsFromRegistr MinDebtPerHarvest: debt.MinDebtPerHarvest, MaxDebtPerHarvest: debt.MaxDebtPerHarvest, LastReport: debt.LastReport, - TotalDebt: debt.TotalDebt, + TotalDebt: totalDebt, TotalDebtUsd: debt.TotalDebtUsd, TotalGain: debt.TotalGain, TotalGainUsd: debt.TotalGainUsd, diff --git a/processes/apr/main.go b/processes/apr/main.go index 94ade0fad..bb6d16a66 100644 --- a/processes/apr/main.go +++ b/processes/apr/main.go @@ -11,6 +11,44 @@ import ( "github.com/yearn/ydaemon/internal/storage" ) +func isForwardAPYAllZeros(f TForwardAPY) bool { + if f.NetAPY != nil && !f.NetAPY.IsZero() { + return false + } + c := f.Composite + if c.Boost != nil && !c.Boost.IsZero() { + return false + } + if c.PoolAPY != nil && !c.PoolAPY.IsZero() { + return false + } + if c.BoostedAPR != nil && !c.BoostedAPR.IsZero() { + return false + } + if c.BaseAPR != nil && !c.BaseAPR.IsZero() { + return false + } + if c.CvxAPR != nil && !c.CvxAPR.IsZero() { + return false + } + if c.RewardsAPY != nil && !c.RewardsAPY.IsZero() { + return false + } + if c.V3OracleCurrentAPR != nil && !c.V3OracleCurrentAPR.IsZero() { + return false + } + if c.V3OracleStratRatioAPR != nil && !c.V3OracleStratRatioAPR.IsZero() { + return false + } + if c.KeepCRV != nil && !c.KeepCRV.IsZero() { + return false + } + if c.KeepVelo != nil && !c.KeepVelo.IsZero() { + return false + } + return true +} + var COMPUTED_APY = make(map[uint64]*sync.Map) func init() { @@ -119,35 +157,12 @@ func ComputeChainAPY(chainID uint64) { vaultAPY.Extra.StakingRewardsAPY = v3StakingAPY } - /********************************************************************************************** - ** If it's a Curve Vault (has a Curve, Convex or Frax strategy), we can estimate the forward - ** APY, aka the expected APY we will get for the upcoming period. - ** Priority: Use Kong estimated APR if available, otherwise compute locally. - **********************************************************************************************/ - kongForwardAPY, _ := convertKongEstimatedAprToForwardAPY(chainID, vault.Address); + kongForwardAPY, _ := convertKongEstimatedAprToForwardAPY(chainID, vault.Address) + if isForwardAPYAllZeros(kongForwardAPY) { + kongForwardAPY.Type = "" + } vaultAPY.ForwardAPY = kongForwardAPY - /********************************************************************************************** - ** If it's a Gamma Vault, we can get the feeAPR as an estimate for the upcoming period, and we - ** can retrieve the extraReward APRs. - **********************************************************************************************/ - if isGammaVault(chainID, vault) { - if _, extaRewardAPY, ok := calculateGammaExtraRewards(chainID, vault.AssetAddress); ok { - vaultAPY.Extra.GammaRewardAPY = extaRewardAPY - } - vaultAPY.ForwardAPY = computeGammaForwardAPY( - vault, - allStrategiesForVault, - ) - vaultAPY.ForwardAPY.Composite.RewardsAPY = vaultAPY.Extra.GammaRewardAPY - } - - if isPendleVault(chainID, vault) { - vaultAPY.ForwardAPY = computePendleForwardAPY( - vault, - allStrategiesForVault, - ) - } safeSyncMap(COMPUTED_APY, chainID).Store(vault.Address, vaultAPY) computedAPYData[vault.Address] = vaultAPY