- Add .catch() so failed background fetches don't silently break the interval
- Add refreshing state with a spinning ↻ on the live badge during background updates
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Cesium+ stores geoPoint in multiple Elasticsearch formats (object,
string "lat,lon", array [lon,lat]). Using z.object() caused a ZodError
that silently swallowed the entire Cesium+ response, leaving geoMap
empty and displaying 0 geolocalized transactions.
Replace the strict Zod schema with z.unknown() and a parseGeoPoint()
helper that normalizes all three formats. Also add [GéoFlux] debug
logs to DataService to trace keyMap/duniterKeys/geoMap pipeline steps.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Au lieu de chercher par nom (title), on résout maintenant par clé :
1. buildIdentityKeyMap() : charge toutes les identités Ğ1v2 depuis Subsquid
avec leur ownerKeyChange → currentSS58 → genesisKey → duniterKey
2. ss58ToDuniterKey() : conversion SS58 v2 (préfixe 2 octets) → base58 Ed25519
= _id Cesium+ (même matériau cryptographique, encodage différent)
3. resolveGeoByKeys() : query Cesium+ par ids{} → résultat exact, pas d'ambiguïté
4. Cache keyMap 10 min : 1 requête Subsquid pour ~8000 identités, pas par refresh
Résultat : les membres migrés v1→v2 avec un profil Cesium+ sont correctement
géolocalisés même si leur nom v2 diffère de leur nom v1.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- CesiumAdapter : terms query en minuscules (champ title analysé par ES)
- CesiumAdapter : z.coerce.number() pour geoPoint.lat/lon (37% des profils
stockent les coordonnées en string → ZodError silencieux → 0 géolocalisées)
- CesiumAdapter : clé de la Map en toLowerCase() pour cohérence
- DataService : lookup geoMap par fromName.toLowerCase()
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- CesiumAdapter : utilise le champ `title` (analysé ES) au lieu de `title.keyword`
qui retournait 0 résultats ; coerce lat/lon en number (certains profils stockent des strings)
- DataService : sépare totalVolume (all tx blockchain) de geoCount (tx heatmap)
- StatsPanel : barre de couverture géo uniquement en mode live
- App : badge source "● live Ğ1v2" ou "○ mock"
- DataService.test.ts : mock SubsquidAdapter + CesiumAdapter directement (vi.mock hoistés)
pour que les tests soient déterministes quel que soit VITE_USE_LIVE_API dans .env.local
- tsconfig.app.json : exclude src/test pour éviter les erreurs de build prod
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>