You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
- Manual fromJson for DTO models (no json_serializable), intl as explicit dependency
@@ -71,7 +80,7 @@ All decisions logged in PROJECT.md Key Decisions table.
71
80
72
81
### Known Risks
73
82
74
-
-Phase 27: VNDirect finfo API JSON schema unconfirmed (endpoint timed out during research). Needs live request verification at Phase 27 planning start. Use `/gsd:research-phase` before planning Phase 27.
83
+
- VNDirect dchart-api is undocumented/unofficial — could change without notice (research valid until 2026-03-20)
Created the shared price feed infrastructure and CoinGecko crypto price provider:
9
+
10
+
1.**PriceFeedEntry** — MessagePack-serializable positional record with `Price`, `FetchedAtUnixSeconds`, `Currency`. Uses `long` for timestamp to avoid DateTimeOffset resolver issues. Computed `FetchedAt` property via `[IgnoreMember]`.
11
+
12
+
2.**PriceFeedResult** — Return type record with `Price`, `FetchedAt`, `IsStale`, `Currency`. Static factories `Fresh()` and `Stale()` for clarity.
13
+
14
+
3.**ICryptoPriceProvider** — Interface with `GetPriceAsync(string coinGeckoId)` and batch `GetPricesAsync(IEnumerable<string> coinGeckoIds)`.
15
+
16
+
4.**IEtfPriceProvider** — Interface with `GetPriceAsync(string vnDirectTicker)`.
17
+
18
+
5.**IExchangeRateProvider** — Interface with `GetUsdToVndRateAsync()`.
19
+
20
+
6.**CoinGeckoPriceProvider** — Full implementation with:
- All MessagePack attributes correctly applied (MsgPack017 warning resolved with positional record)
42
+
- No new NuGet packages required
43
+
44
+
## Decisions Made
45
+
46
+
- Used positional record syntax for PriceFeedEntry to avoid MessagePack init accessor warnings
47
+
- CoinGecko API key sent per-request via HttpRequestMessage header (not default header on HttpClient — that's handled in ServiceCollectionExtensions in Plan 02)
48
+
- Batch method returns stale results for cached IDs and throws only if uncached IDs fail to fetch
- VNDirect uses stale-while-revalidate (returns stale immediately, refreshes in background) per research recommendation — 48h TTL means staleness only during VN market hours
56
+
- OpenErApiProvider uses wait-for-fetch (not stale-while-revalidate) — exchange rate accuracy matters more for currency conversion
57
+
- Shared `ConfigureResilience` method avoids repeating resilience options 3 times
58
+
- CoinGecko API key added as DefaultRequestHeader on HttpClient at registration time (ServiceCollectionExtensions), not per-request
0 commit comments