commit 5dabf9f4103562b9315600667792459c0e7ed9c8
parent 71273a95e2b3b64bf40a414583a1ffac811dc611
Author: Sebastian <sebasjm@gmail.com>
Date: Fri, 4 Jul 2025 07:06:24 -0300
fix #10150
Diffstat:
3 files changed, 63 insertions(+), 16 deletions(-)
diff --git a/packages/taler-util/src/aml/reporting.ts b/packages/taler-util/src/aml/reporting.ts
@@ -356,7 +356,7 @@ export async function fetchTopsInfoFromServer(
const allQueries = eventList.map(async ([_key, value]) => {
const key = _key as keyof EventType;
- const response = await api.getAmlKycStatistics(officer, value.event, {
+ const response = await api.getAmlKycStatistics(officer, [value.event], {
since: value.start,
until: value.end,
});
@@ -367,7 +367,7 @@ export async function fetchTopsInfoFromServer(
const resultMap = allResponses.reduce((prev, event) => {
prev[event.key] =
- event.response.type === "ok" ? event.response.body.counter : undefined;
+ event.response.type === "ok" ? event.response.body.statistics[0].counter : undefined;
return prev;
}, {} as CounterResultByEventName<EventType>);
@@ -384,9 +384,50 @@ export async function fetchVqfInfoFromServer(
type EventType = typeof VQF_EVENTS_THIS_YEAR;
const eventList = Object.entries(VQF_EVENTS_THIS_YEAR);
+ // type QueryAndEvent = { query: string; eventName: string };
+ // type RawTime = AbsoluteTime["t_ms"];
+ // // group by start & end
+ // const groupedEvents = eventList.reduce(
+ // (prev, [query, metric]) => {
+ // if (!prev.has(metric.start.t_ms)) {
+ // prev.set(metric.start.t_ms, new Map<RawTime, QueryAndEvent[]>());
+ // }
+ // const st = prev.get(metric.start.t_ms)!;
+ // if (!st.has(metric.end.t_ms)) {
+ // st.set(metric.end.t_ms, []);
+ // }
+ // const ed = st.get(metric.end.t_ms)!;
+
+ // ed.push({
+ // query,
+ // eventName: metric.event,
+ // });
+ // return prev;
+ // },
+ // {} as Map<RawTime, Map<RawTime, QueryAndEvent[]>>,
+ // );
+
+ // groupedEvents.entries()
+ // const groupedEventsList = Object.entries(groupedEvents).flatMap(
+ // ([startStr, map]) => {
+ // return Object.entries(map).flatMap(([endStr, list]) => {
+ // const start =
+ // startStr === "never"
+ // ? AbsoluteTime.never()
+ // : AbsoluteTime.fromMilliseconds(Number.parseInt(startStr, 10));
+ // const end =
+ // endStr === "never"
+ // ? AbsoluteTime.never()
+ // : AbsoluteTime.fromMilliseconds(Number.parseInt(endStr, 10));
+
+ // return list;
+ // });
+ // },
+ // );
+
const allQueries = eventList.map(async ([_key, value]) => {
const key = _key as keyof EventType;
- const response = await api.getAmlKycStatistics(officer, value.event, {
+ const response = await api.getAmlKycStatistics(officer, [value.event], {
since: value.start,
until: value.end,
});
@@ -397,7 +438,7 @@ export async function fetchVqfInfoFromServer(
const resultMap = allResponses.reduce((prev, event) => {
prev[event.key] =
- event.response.type === "ok" ? event.response.body.counter : undefined;
+ event.response.type === "ok" ? event.response.body.statistics[0].counter : undefined;
return prev;
}, {} as CounterResultByEventName<EventType>);
diff --git a/packages/taler-util/src/http-client/exchange-client.ts b/packages/taler-util/src/http-client/exchange-client.ts
@@ -84,6 +84,7 @@ import {
codecForAccountKycStatus,
codecForAmlDecisionsResponse,
codecForAmlKycAttributes,
+ codecForAmlStatisticsResponse,
codecForAmlWalletKycCheckResponse,
codecForAvailableMeasureSummary,
codecForEventCounter,
@@ -927,25 +928,18 @@ export class TalerExchangeHttpClient {
}
/**
- * https://docs.taler.net/core/api-exchange.html#get--aml-$OFFICER_PUB-kyc-statistics-$NAME
+ * https://docs.taler.net/core/api-exchange.html#get--aml-$OFFICER_PUB-kyc-statistics-$NAMES
*
*/
async getAmlKycStatistics(
auth: OfficerAccount,
- name: string,
+ names: string[],
filter: {
since?: AbsoluteTime;
until?: AbsoluteTime;
} = {},
- ): Promise<
- | OperationFail<
- | HttpStatusCode.Forbidden
- | HttpStatusCode.NotFound
- | HttpStatusCode.Conflict
- >
- | OperationOk<EventCounter>
- > {
- const url = new URL(`aml/${auth.id}/kyc-statistics/${name}`, this.baseUrl);
+ ) {
+ const url = new URL(`aml/${auth.id}/kyc-statistics/${names.join(" ")}`, this.baseUrl);
if (filter.since !== undefined && filter.since.t_ms !== "never") {
url.searchParams.set("start_date", String(filter.since.t_ms));
@@ -964,7 +958,7 @@ export class TalerExchangeHttpClient {
});
switch (resp.status) {
case HttpStatusCode.Ok:
- return opSuccessFromHttp(resp, codecForEventCounter());
+ return opSuccessFromHttp(resp, codecForAmlStatisticsResponse());
case HttpStatusCode.Conflict:
case HttpStatusCode.NotFound:
case HttpStatusCode.Forbidden:
diff --git a/packages/taler-util/src/types-taler-exchange.ts b/packages/taler-util/src/types-taler-exchange.ts
@@ -2087,7 +2087,13 @@ export interface KycCheckPublicInformation {
// something more??!?
}
+export interface AmlStatisticsResponse {
+ statistics: EventCounter[];
+}
export interface EventCounter {
+ // Name of the statistic that is being returned.
+ name: string;
+
// Number of events of the specified type in
// the given range.
counter: Integer;
@@ -2607,8 +2613,14 @@ export const codecForExchangeKeysResponse = (): Codec<ExchangeKeysResponse> =>
.deprecatedProperty("rewards_allowed")
.build("TalerExchangeApi.ExchangeKeysResponse");
+export const codecForAmlStatisticsResponse = (): Codec<AmlStatisticsResponse> =>
+ buildCodecForObject<AmlStatisticsResponse>()
+ .property("statistics", codecForList(codecForEventCounter()))
+ .build("TalerExchangeApi.AmlStatisticsResponse");
+
export const codecForEventCounter = (): Codec<EventCounter> =>
buildCodecForObject<EventCounter>()
+ .property("name", codecForString())
.property("counter", codecForNumber())
.build("TalerExchangeApi.EventCounter");