fix(cache): restore per-chain isolation + validation to vault data pipeline#312
Open
Mischa0x wants to merge 1 commit into
Open
fix(cache): restore per-chain isolation + validation to vault data pipeline#312Mischa0x wants to merge 1 commit into
Mischa0x wants to merge 1 commit into
Conversation
…peline The vaultsData.json cache has been frozen at 2025-11-24 12:20 UTC because a latent TypeError in getSafeVaultApy crashes the whole pipeline via a brittle top-level Promise.all, which in turn skips the commit step. Changes: - lib/vault/prepareVaultData.ts: guard filteredLogs[0].blockNumber access in getSafeVaultApy when no oracle PriceUpdated events match the vault in the last 10k-block window. The guard at line 368 only checked the unfiltered logs; this adds the missing check on the filtered list. - lib/scripts/cacheVaultsData.ts: wrap each chain's fetch in try/catch inside Promise.allSettled so one chain cannot kill the others. Validate each chain's vault addresses/assets before inclusion; drop chains with malformed data rather than propagating corruption. Always emit every supported chain in the output (empty array for failures) so client vaultsData[chain.id] access remains shape-compatible. Add generatedAt, chains, failedChains, stakingTVLFromFallback manifest fields for observability. Log DefiLlama staking TVL fallback (previously silent). - .github/workflows/update-cache.yml: add Validate cache output step between run and commit (freshness <30min, mainnet required, >=6 chains, address hex format, vaultTVL numeric). Skip commit when no diff. Push to current ref instead of hardcoded main to make workflow_dispatch on feature branches safe. Add optional failure alert via CACHE_ALERT_WEBHOOK secret. Does not modify next.config.js env block. Secrets surface is unchanged from current main. No new process.env.* reads added.
Contributor
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
app.vaultcraft.io/vaultshas been serving cached data frozen at 2025-11-24 12:20 UTC for ~5 months. Root cause is a four-layer failure. This PR fixes the first three (code/CI); layer 4 (workflow re-enable) is a one-linegh apicall after merge.A fifth issue was surfaced by CI running on this branch — see Required before merge below.
Root cause
TypeErrorinlib/vault/prepareVaultData.ts:377—filteredLogs[0].blockNumberdereferenced without alength === 0guard. Existing guard at line 368 only checked the unfilteredlogsarray. When the oracle emitsPriceUpdatedwithin the 10k-block window but none match(base=vault.address, quote=vault.asset), the pipeline crashed.lib/scripts/cacheVaultsData.ts—Promise.allat the top level meant one chain's rejection killed the entire cache build.writeFileSynclived inside the per-chain.map()callback, so concurrent chain completions could interleave writes.totalAssets), it could be committed tocache/vaultsData.jsonand read by the deposit/withdraw modals (vaultsAtom,tokensAtom).disabled_inactivitybecause it had been failing every 4h for ~60+ days without commits or manual dispatches. Re-enable after merge.Changes
lib/vault/prepareVaultData.ts(+1 line)Added
if (filteredLogs.length === 0) return [];after the.filter(...)call, beforefilteredLogs[0].blockNumberis accessed.lib/scripts/cacheVaultsData.ts(rewrite)Promise.all→Promise.allSettled; per-chaintry/catchinside the mapwriteFileSyncmoved outside the map — writes once, after all chains settlevault.addressandvault.assetmust match/^0x[a-fA-F0-9]{40}$/;totalAssetsandtotalSupplymust be defined. Invalid chains are dropped, not written.SUPPORTED_NETWORKSchain is emitted (as[]/{}if failed) so the client'svaultsData[chain.id]access incomponents/common/Page.tsx:520never hitsundefined. Shape-compatible with the existing cache.generatedAt,chains(successful),failedChains(with error messages),stakingTVLFromFallback(bool flag when DefiLlama staking TVL hits the hardcoded2590000fallback).lockVaultTVL = 520000and thestakingTVLfallback are flagged with aTODO— not fixed here.1only when zero chains succeed. Partial success writes the file..github/workflows/update-cache.yml(rewrite)jq:generatedAtwithin last 30minvaultTVLis numericvault.addressandvault.assetmatches0x[a-fA-F0-9]{40}${{ secrets.CACHE_ALERT_WEBHOOK }}(Slack/Discord) with the run URL. No-ops gracefully if secret unset.success()so no partial/invalid cache ever lands on main.HEAD:${{ github.ref_name }}so workflow_dispatch from feature branches writes back to that branch, not main.Required before merge — DefiLlama API key exhausted
CI verification on this branch (run #24662013118) surfaced that `DEFILLAMA_API_KEY` is out of credits:
```
Chain 43111 failed: Request failed with status code 402
Chain 137 failed: Request failed with status code 402
Chain 43114 failed: Request failed with status code 402
Chain 8453 failed: Request failed with status code 402
Chain 196 failed: Request failed with status code 402
Chain 2818 failed: Request failed with status code 402
Chain 10 failed: Request failed with status code 402
Chain 42161 failed: Request failed with status code 402
```
Response body: `{ error: 'You ran out of API credits' }` from `pro-api.llama.fi/.../yields/chart/...`. This call is made inside the per-chain vault fetch (APY history), not just the staking-TVL step at the end.
This was the second reason the cache was stale (beyond the TypeError). The per-chain isolation in this PR is what made the real error visible — previously it was buried inside a bigger stack trace.
Please top up the DefiLlama subscription before merge so the first post-merge run produces real data. After merge, enable the workflow with:
```bash
gh api -X PUT repos/Popcorn-Limited/vaultcraft/actions/workflows/193517961/enable
gh workflow run update-cache.yml -R Popcorn-Limited/vaultcraft
```
Safety posture
This PR does not modify `next.config.js`. Secrets surface is unchanged from current main. No new `process.env.*` reads added. All changes are confined to the cache-build pipeline (GitHub Actions runtime) and one null-guard in a script imported only by the cache script — none of this ships to the client bundle.
Client-side behavior (deposits/withdrawals reading from the cache-hydrated Jotai atoms) is unchanged by this PR. A separate, later PR will add a staleness banner in `components/common/Page.tsx` with a >24h hard-fallback to the live data path, but that is intentionally scoped out here.
Out of scope (tracked separately):
Test plan