From fdf2a429f5c078913c344ddf5183b4197d9b0408 Mon Sep 17 00:00:00 2001 From: Jeff Emmett Date: Sun, 15 Mar 2026 12:41:11 -0700 Subject: [PATCH] fix(rwallet): populate yield APY stats, hide top tabs on yield view - Fix DeFi Llama field mapping: use apyMean30d + apyPct7D (apyMean7d doesn't exist in their API) - Add apyBase, apy30d fields to YieldOpportunity type - Deduplicate rates table (best APY per protocol+chain+asset) - Hide "My Wallets / Wallet Visualizer" top tab bar on yield page - Color-code APY values, better TVL formatting (B/M) - Bump JS cache to v=11 Co-Authored-By: Claude Opus 4.6 --- .../rwallet/components/folk-wallet-viewer.ts | 31 +++++++++++++------ modules/rwallet/lib/yield-protocols.ts | 2 ++ modules/rwallet/lib/yield-rates.ts | 9 ++++-- modules/rwallet/mod.ts | 2 +- 4 files changed, 32 insertions(+), 12 deletions(-) diff --git a/modules/rwallet/components/folk-wallet-viewer.ts b/modules/rwallet/components/folk-wallet-viewer.ts index 84904c9..bd3a2e9 100644 --- a/modules/rwallet/components/folk-wallet-viewer.ts +++ b/modules/rwallet/components/folk-wallet-viewer.ts @@ -90,7 +90,9 @@ interface YieldRate { assetAddress: string; vaultAddress: string; apy: number; + apyBase?: number; apy7d?: number; + apy30d?: number; tvl?: number; vaultName?: string; } @@ -2043,6 +2045,15 @@ class FolkWalletViewer extends HTMLElement { // ── Rates table ── if (this.yieldRates.length > 0) { + // Deduplicate: keep highest-APY entry per protocol+chain+asset + const deduped = new Map(); + const sorted = [...this.yieldRates].sort((a, b) => b.apy - a.apy); + for (const r of sorted) { + const key = `${r.protocol}:${r.chainId}:${r.asset}`; + if (!deduped.has(key)) deduped.set(key, r); + } + const rates = [...deduped.values()]; + html += `

Available Rates

@@ -2051,20 +2062,21 @@ class FolkWalletViewer extends HTMLElement { - + `; - const sorted = [...this.yieldRates].sort((a, b) => b.apy - a.apy); - for (const r of sorted) { + for (const r of rates) { const protocolLabel = r.protocol === "aave-v3" ? "Aave V3" : (r.vaultName || "Morpho"); + const chainColor = r.chainId === "1" ? "#627eea" : "#0052ff"; + const apyColor = r.apy >= 3 ? "var(--rs-success)" : r.apy >= 1.5 ? "#ffa726" : "var(--rs-text-secondary)"; html += ` - + - - - + + + `; } html += `
Chain Asset APY7d Avg30d Avg TVL
${protocolLabel}${chainNames[r.chainId] || r.chainId}${chainNames[r.chainId] || r.chainId} ${this.esc(r.asset)}${r.apy.toFixed(2)}%${r.apy7d ? r.apy7d.toFixed(2) + "%" : "-"}${r.tvl ? "$" + (r.tvl / 1e6).toFixed(1) + "M" : "-"}${r.apy.toFixed(2)}%${r.apy30d != null ? r.apy30d.toFixed(2) + "%" : "-"}${r.tvl ? "$" + (r.tvl >= 1e9 ? (r.tvl / 1e9).toFixed(1) + "B" : (r.tvl / 1e6).toFixed(0) + "M") : "-"}
`; @@ -2329,11 +2341,12 @@ class FolkWalletViewer extends HTMLElement { private render() { const isMyWallets = this.topTab === "my-wallets" && this.isAuthenticated; + const isYield = this.activeView === "yield"; this.shadow.innerHTML = ` ${this.renderStyles()} - ${this.isAuthenticated ? this.renderTopTabBar() : ''} - ${isMyWallets ? this.renderMyWalletsTab() : this.renderVisualizerTab()} + ${this.isAuthenticated && !isYield ? this.renderTopTabBar() : ''} + ${isMyWallets && !isYield ? this.renderMyWalletsTab() : this.renderVisualizerTab()} `; // Top tab listeners diff --git a/modules/rwallet/lib/yield-protocols.ts b/modules/rwallet/lib/yield-protocols.ts index 1fe5e57..3ee0fe3 100644 --- a/modules/rwallet/lib/yield-protocols.ts +++ b/modules/rwallet/lib/yield-protocols.ts @@ -16,6 +16,8 @@ export interface YieldOpportunity { vaultAddress: string; // aToken for Aave, vault for Morpho apy: number; apy7d?: number; + apy30d?: number; + apyBase?: number; tvl?: number; poolId?: string; // DeFi Llama pool ID vaultName?: string; diff --git a/modules/rwallet/lib/yield-rates.ts b/modules/rwallet/lib/yield-rates.ts index d7b98a7..a8d5be3 100644 --- a/modules/rwallet/lib/yield-rates.ts +++ b/modules/rwallet/lib/yield-rates.ts @@ -63,7 +63,10 @@ interface LlamaPool { symbol: string; tvlUsd: number; apy: number; - apyMean7d?: number; + apyBase?: number; + apyReward?: number | null; + apyPct7D?: number; + apyMean30d?: number; underlyingTokens?: string[]; } @@ -119,7 +122,9 @@ async function fetchDefiLlamaRates(): Promise { assetAddress, vaultAddress, apy: pool.apy || 0, - apy7d: pool.apyMean7d, + apyBase: pool.apyBase ?? undefined, + apy7d: pool.apyPct7D != null ? pool.apy + pool.apyPct7D : undefined, + apy30d: pool.apyMean30d ?? undefined, tvl: pool.tvlUsd, poolId: pool.pool, vaultName: protocol === "morpho-blue" diff --git a/modules/rwallet/mod.ts b/modules/rwallet/mod.ts index 6e1be9a..6546c68 100644 --- a/modules/rwallet/mod.ts +++ b/modules/rwallet/mod.ts @@ -1014,7 +1014,7 @@ function renderWallet(spaceSlug: string, initialView?: string) { modules: getModuleInfoList(), theme: "dark", body: ``, - scripts: ``, + scripts: ``, styles: ``, }); }