feat: migration Ğ1v2 — Subsquid + Cesium+ g1.data.e-is.pro

Sources de données réelles Ğ1v2 (vérifiées par introspection) :
- SubsquidAdapter : https://squidv2s.syoul.fr/v1/graphql
  transfers(filter: timestamp >= since, orderBy: TIMESTAMP_DESC)
  with from.linkedIdentity.name pour jointure géo
- CesiumAdapter : https://g1.data.e-is.pro (59 841 profils)
  recherche batch par nom d'identité (title.keyword)
  g1.data.duniter.fr hors ligne depuis arrêt Ğ1v1

Schémas Zod mis à jour pour Ğ1v2 :
- G1v2KeySchema : SS58 "g1" + 47 chars = 49 chars (mesuré sur données réelles)
- SubsquidTransferSchema : id, blockNumber, timestamp ISO, amount BigInt string
- parseSubsquidAmount : BigInt string centimes → Ğ1 flottant

Activation : VITE_USE_LIVE_API=true dans .env.local
Badge "● live Ğ1v2 / ○ mock" ajouté dans l'UI

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
syoul
2026-03-22 16:01:36 +01:00
parent d20d042bca
commit 2f813c5fdf
8 changed files with 392 additions and 259 deletions

View File

@@ -1,11 +1,11 @@
export interface Transaction {
id: string;
timestamp: number; // Unix ms
timestamp: number; // Unix ms (entier)
lat: number;
lng: number;
amount: number; // Ğ1
amount: number; // Ğ1 (pas en centimes)
city: string;
fromKey: string;
fromKey: string; // SS58 Ğ1v2 : préfixe "g1", ~50 chars
toKey: string;
}
@@ -51,9 +51,11 @@ function weightedRandom<T extends { weight: number }>(items: T[]): T {
return items[items.length - 1];
}
// Génère une clé SS58 Ğ1v2 simulée : préfixe "g1" + 48 chars base58
function generateKey(): string {
const chars = '123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz';
return Array.from({ length: 44 }, () => chars[Math.floor(Math.random() * chars.length)]).join('');
const suffix = Array.from({ length: 47 }, () => chars[Math.floor(Math.random() * chars.length)]).join('');
return 'g1' + suffix;
}
function generateTransactions(count: number, maxAgeMs: number): Transaction[] {
@@ -62,7 +64,6 @@ function generateTransactions(count: number, maxAgeMs: number): Transaction[] {
for (let i = 0; i < count; i++) {
const city = weightedRandom(CITIES);
// Add slight spatial noise around city center
const lat = city.lat + randomBetween(-0.08, 0.08);
const lng = city.lng + randomBetween(-0.12, 0.12);
const amount = Math.round(randomBetween(0.5, 150) * 100) / 100;
@@ -82,7 +83,6 @@ function generateTransactions(count: number, maxAgeMs: number): Transaction[] {
return transactions.sort((a, b) => b.timestamp - a.timestamp);
}
// Pre-generate a pool of 30 days worth of transactions
const TRANSACTION_POOL = generateTransactions(2400, 30 * 24 * 60 * 60 * 1000);
export function getTransactionsForPeriod(periodDays: number): Transaction[] {