feat: nature des échanges — catégorisation et détail des commentaires de transactions
ci/woodpecker/push/woodpecker Pipeline was successful

- Nouveau commentParser.ts : ~80 règles regex multilingues, 11 catégories
- SubsquidAdapter : fetch du champ comment.remark depuis SubSquid
- Transaction et TransactionArc : champs comment et category
- StatsPanel : section Nature des échanges avec barres cliquables (détail inline)
- FlowMap : tooltip au survol des arcs avec répartition catégories + commentaires
- InfoPanel mis à jour

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
syoul
2026-04-21 21:29:59 +02:00
parent 6b7591db32
commit 8e396cd331
10 changed files with 562 additions and 27 deletions
+9
View File
@@ -14,6 +14,7 @@
import { fetchTransfers, buildIdentityKeyMap, fetchCurrentUD, ss58ToDuniterKey, fetchActiveMemberKeys } from './adapters/SubsquidAdapter';
import { resolveGeoByKeys, resolveGeoByKeysBatched, cleanCityName } from './adapters/CesiumAdapter';
import { parseComment } from '../data/commentParser';
import {
getTransactionsForPeriod,
computeStats,
@@ -112,6 +113,8 @@ async function fetchLiveTransactions(periodDays: number): Promise<{
countryCode: fromGeo.countryCode,
fromKey: t.fromId,
toKey: t.toId,
comment: t.comment,
category: parseComment(t.comment),
});
// Arc : les deux extrémités géolocalisées + villes différentes
@@ -133,6 +136,8 @@ async function fetchLiveTransactions(periodDays: number): Promise<{
toLat: toGeo.lat, toLng: toGeo.lng,
toCity, toCountry: toGeo.countryCode,
toKey: t.toId,
comment: t.comment,
category: parseComment(t.comment),
});
}
@@ -192,6 +197,8 @@ export interface PeriodStats {
transactionCount: number; // total blockchain (y compris non-géolocalisés)
geoCount: number; // transactions visibles sur la carte
topCities: { name: string; volume: number; count: number; countryCode: string }[];
categoryBreakdown: { category: import('../data/commentParser').TxCategory; count: number; volume: number }[];
commentedCount: number; // nb de transactions avec un commentaire
}
export interface DataResult {
@@ -233,6 +240,8 @@ export async function fetchData(periodDays: number): Promise<DataResult> {
transactionCount: totalCount,
geoCount: geolocated.length,
topCities: base.topCities,
categoryBreakdown: base.categoryBreakdown,
commentedCount: base.commentedCount,
},
source: 'live',
currentUD,
+6
View File
@@ -29,6 +29,7 @@ const SubsquidTransferNodeSchema = z.object({
from: z.object({
linkedIdentity: z.object({ name: z.string() }).nullable(),
}).nullable(),
comment: z.object({ remark: z.string() }).nullable().optional(),
});
const SubsquidResponseSchema = z.object({
@@ -52,6 +53,7 @@ export interface RawTransfer {
fromId: string;
toId: string;
fromName: string; // nom d'identité Ğ1 de l'émetteur (peut être vide)
comment: string | null;
}
// ---------------------------------------------------------------------------
@@ -77,6 +79,9 @@ const TRANSFERS_QUERY = `
name
}
}
comment {
remark
}
}
}
}
@@ -253,6 +258,7 @@ export async function fetchTransfers(
fromId: node.fromId ?? '',
toId: node.toId ?? '',
fromName: node.from?.linkedIdentity?.name ?? '',
comment: node.comment?.remark ?? null,
})),
};
}