Skip to content

feat(savings): add estimatedYieldPerSecond to subscription response (…#501

Merged
Devsol-01 merged 1 commit intoDevsol-01:mainfrom
Thepantseller:feature/issues-409-410-411-412-backend-yield-cache-analytics
Mar 29, 2026
Merged

feat(savings): add estimatedYieldPerSecond to subscription response (…#501
Devsol-01 merged 1 commit intoDevsol-01:mainfrom
Thepantseller:feature/issues-409-410-411-412-backend-yield-cache-analytics

Conversation

@Thepantseller
Copy link
Copy Markdown
Contributor

Summary

This PR resolves four backend issues across the savings and analytics modules.

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

#409 — Ticker Protocol Yield Estimation Engine

GET /savings/my-subscriptions now includes estimatedYieldPerSecond on every subscription
object. The value is derived directly from the pool's interestRate:

estimatedYieldPerSecond = (liveBalance × annualRate) / (365 × 24 × 3600)

This gives the frontend a stable constant to drive balance ticker animations without re-
polling the API.

Changed: savings.service.ts — UserSubscriptionWithLiveBalance interface +
mapSubscriptionWithLiveBalance

closes #409
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

#410 — Redis Cache Layer for Pool Stats

GET /savings/products is decorated with @Cachekey('pools_all') and @CacheTTL(60000),
caching the full response in Redis for 60 seconds. Cache is busted automatically via
this.cacheManager.del('pools_all') whenever a pool is created or updated by an admin.

closes #410
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

#411 — Portfolio Timeline via GET /analytics/portfolio

GET /analytics/portfolio?timeframe=[1D|1W|1M|YTD] validates the timeframe enum,
reconstructs the user's net worth history by working backward from the current live
balance using on-chain transaction events, and returns a chronological array shaped for
Recharts:

json
[{ "date": "Oct 25, 2023", "value": 124500.00 }, ...]

closes #411
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

#412 — Asset Allocation via GET /analytics/allocation

GET /analytics/allocation queries all token balances on the user's Stellar account,
converts each to USD via the oracle, groups by assetId, divides by the absolute total for
decimal-precise percentages, and returns the array sorted highest allocation first.

closes #412
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

Tests

All 198 unit tests pass. The two subscription tests (
returns subscriptions enriched with live RPC balances and
falls back to cached subscription amounts when wallet is missing) were updated to assert
estimatedYieldPerSecond is present in the response.

…evsol-01#409)

Closes Devsol-01#409, Devsol-01#410, Devsol-01#411, Devsol-01#412

- Devsol-01#409: Compute estimatedYieldPerSecond = (liveBalance * annualRate) / (365*24*3600)
  and expose it on every UserSubscriptionWithLiveBalance item returned by
  GET /savings/my-subscriptions, enabling frontend ticker animations without
  polling the API.
- Devsol-01#410: Redis cache layer via @Cachekey('pools_all') + @CacheTTL(60000) on
  GET /savings/products and manual invalidation via cacheManager.del('pools_all')
  on any pool mutation — already in place, verified by existing tests.
- Devsol-01#411: GET /analytics/portfolio?timeframe=[1D|1W|1M|YTD] with enum validation
  and backward-reconstruction timeline — already in place, verified by existing tests.
- Devsol-01#412: GET /analytics/allocation grouping holdings by assetId, dividing by total
  for decimal-precise percentages sorted highest-first — already in place.
@vercel
Copy link
Copy Markdown

vercel bot commented Mar 29, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
nestera Ready Ready Preview, Comment Mar 29, 2026 5:49am

@drips-wave
Copy link
Copy Markdown

drips-wave bot commented Mar 29, 2026

@Thepantseller Great news! 🎉 Based on an automated assessment of this PR, the linked Wave issue(s) no longer count against your application limits.

You can now already apply to more issues while waiting for a review of this PR. Keep up the great work! 🚀

Learn more about application limits

@Devsol-01 Devsol-01 merged commit 3e0965a into Devsol-01:main Mar 29, 2026
4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

2 participants