commit 9c672c08f021c4a58b10b42e931742e45f21cbad
parent b3c40059d72a690653ecffbd64370e66bf2fd5e7
Author: Christian Grothoff <christian@grothoff.org>
Date: Tue, 17 Jun 2025 23:20:21 +0200
first version of exchange API to do GET on /aml//legitimizations (towards fixing #9027), plus some renames for consistency
Diffstat:
16 files changed, 2375 insertions(+), 738 deletions(-)
diff --git a/src/exchange/Makefile.am b/src/exchange/Makefile.am
@@ -148,6 +148,7 @@ taler_exchange_httpd_SOURCES = \
taler-exchange-httpd_aml-attributes-get.c taler-exchange-httpd_aml-attributes-get.h \
taler-exchange-httpd_aml-decision.c taler-exchange-httpd_aml-decision.h \
taler-exchange-httpd_aml-decisions-get.c \
+ taler-exchange-httpd_aml-legitimization-measures-get.c taler-exchange-httpd_aml-legitimization-measures-get.h \
taler-exchange-httpd_aml-statistics-get.c taler-exchange-httpd_aml-statistics-get.h \
taler-exchange-httpd_aml-measures-get.c taler-exchange-httpd_aml-measures-get.h \
taler-exchange-httpd_aml-transfer-get.c taler-exchange-httpd_aml-transfer-get.h \
@@ -170,7 +171,6 @@ taler_exchange_httpd_SOURCES = \
taler-exchange-httpd_kyc-upload.c taler-exchange-httpd_kyc-upload.h \
taler-exchange-httpd_kyc-wallet.c taler-exchange-httpd_kyc-wallet.h \
taler-exchange-httpd_kyc-webhook.c taler-exchange-httpd_kyc-webhook.h \
- taler-exchange-httpd_legitimization-measures-get.c taler-exchange-httpd_legitimization-measures-get.h \
taler-exchange-httpd_management.h \
taler-exchange-httpd_management_aml-officers.c \
taler-exchange-httpd_management_auditors.c \
diff --git a/src/exchange/taler-exchange-httpd.c b/src/exchange/taler-exchange-httpd.c
@@ -34,6 +34,7 @@
#include "taler-exchange-httpd_withdraw.h"
#include "taler-exchange-httpd_aml-attributes-get.h"
#include "taler-exchange-httpd_aml-decision.h"
+#include "taler-exchange-httpd_aml-legitimization-measures-get.h"
#include "taler-exchange-httpd_aml-statistics-get.h"
#include "taler-exchange-httpd_aml-transfer-get.h"
#include "taler-exchange-httpd_aml-measures-get.h"
@@ -54,7 +55,6 @@
#include "taler-exchange-httpd_kyc-wallet.h"
#include "taler-exchange-httpd_kyc-webhook.h"
#include "taler-exchange-httpd_aml-decision.h"
-#include "taler-exchange-httpd_legitimization-measures-get.h"
#include "taler-exchange-httpd_management.h"
#include "taler-exchange-httpd_melt_v27.h"
#include "taler-exchange-httpd_metrics.h"
@@ -589,7 +589,7 @@ handle_get_aml (struct TEH_RequestContext *rc,
},
{
.op = "legitimizations",
- .handler = &TEH_handler_legitimization_measures_get
+ .handler = &TEH_handler_aml_legitimization_measures_get
},
{
.op = "kyc-statistics",
diff --git a/src/exchange/taler-exchange-httpd_aml-legitimization-measures-get.c b/src/exchange/taler-exchange-httpd_aml-legitimization-measures-get.c
@@ -0,0 +1,175 @@
+/*
+ This file is part of TALER
+ Copyright (C) 2024 Taler Systems SA
+
+ TALER is free software; you can redistribute it and/or modify it under the
+ terms of the GNU Affero General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ TALER is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License along with
+ TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
+*/
+/**
+ * @file taler-exchange-httpd_aml-legitimization-measures-get.c
+ * @brief Return information about legitimization measures
+ * @author Christian Grothoff
+ */
+#include "platform.h"
+#include <gnunet/gnunet_util_lib.h>
+#include <jansson.h>
+#include <microhttpd.h>
+#include <pthread.h>
+#include "taler_json_lib.h"
+#include "taler_mhd_lib.h"
+#include "taler_signatures.h"
+#include "taler-exchange-httpd.h"
+#include "taler_exchangedb_plugin.h"
+#include "taler-exchange-httpd_aml-legitimization-measures-get.h"
+#include "taler-exchange-httpd_metrics.h"
+
+/**
+ * Maximum number of measures we return in one request.
+ */
+#define MAX_MEASURES 1024
+
+/**
+ * Return LEGITIMIZATION measure.
+ *
+ * @param cls closure
+ * @param h_payto hash of account the measure applies to
+ * @param start_time when was the process started
+ * @param jmeasures object of type ``LegitimizationMeasures``
+ * @param is_finished true if the measure was finished
+ * @param measure_serial_id row ID of the measure in the exchange table
+ */
+static void
+record_cb (
+ void *cls,
+ struct TALER_NormalizedPaytoHashP *h_payto,
+ struct GNUNET_TIME_Timestamp start_time,
+ const json_t *jmeasures,
+ bool is_finished,
+ uint64_t measure_serial_id)
+{
+ json_t *measures = cls;
+
+ GNUNET_assert (
+ 0 ==
+ json_array_append_new (
+ measures,
+ GNUNET_JSON_PACK (
+ GNUNET_JSON_pack_data_auto ("h_payto",
+ h_payto),
+ GNUNET_JSON_pack_uint64 ("rowid",
+ measure_serial_id),
+ GNUNET_JSON_pack_timestamp ("start_time",
+ start_time),
+ GNUNET_JSON_pack_allow_null (
+ GNUNET_JSON_pack_object_incref ("measures",
+ (json_t *) jmeasures)),
+ GNUNET_JSON_pack_bool ("is_finished",
+ is_finished)
+ )));
+}
+
+
+MHD_RESULT
+TEH_handler_aml_legitimization_measures_get (
+ struct TEH_RequestContext *rc,
+ const struct TALER_AmlOfficerPublicKeyP *officer_pub,
+ const char *const args[])
+{
+ int64_t limit = -20;
+ uint64_t offset;
+ struct TALER_NormalizedPaytoHashP h_payto;
+ bool have_payto = false;
+ enum TALER_EXCHANGE_YesNoAll active_filter;
+
+ if (NULL != args[0])
+ {
+ GNUNET_break_op (0);
+ return TALER_MHD_reply_with_error (
+ rc->connection,
+ MHD_HTTP_NOT_FOUND,
+ TALER_EC_GENERIC_ENDPOINT_UNKNOWN,
+ args[0]);
+ }
+ TALER_MHD_parse_request_snumber (rc->connection,
+ "limit",
+ &limit);
+ if (limit > 0)
+ offset = 0;
+ else
+ offset = INT64_MAX;
+ TALER_MHD_parse_request_number (rc->connection,
+ "offset",
+ &offset);
+ if (offset > INT64_MAX)
+ {
+ GNUNET_break_op (0); /* broken client */
+ offset = INT64_MAX;
+ }
+ TALER_MHD_parse_request_arg_auto (rc->connection,
+ "h_payto",
+ &h_payto,
+ have_payto);
+ TALER_MHD_parse_request_yna (rc->connection,
+ "active",
+ TALER_EXCHANGE_YNA_ALL,
+ &active_filter);
+ {
+ json_t *measures;
+ enum GNUNET_DB_QueryStatus qs;
+
+ measures = json_array ();
+ GNUNET_assert (NULL != measures);
+ if (limit > MAX_MEASURES)
+ limit = MAX_MEASURES;
+ if (limit < -MAX_MEASURES)
+ limit = -MAX_MEASURES;
+ qs = TEH_plugin->select_aml_measures (
+ TEH_plugin->cls,
+ have_payto
+ ? &h_payto
+ : NULL,
+ active_filter,
+ offset,
+ limit,
+ &record_cb,
+ measures);
+ switch (qs)
+ {
+ case GNUNET_DB_STATUS_HARD_ERROR:
+ case GNUNET_DB_STATUS_SOFT_ERROR:
+ json_decref (measures);
+ GNUNET_break (0);
+ return TALER_MHD_reply_with_error (
+ rc->connection,
+ MHD_HTTP_INTERNAL_SERVER_ERROR,
+ TALER_EC_GENERIC_DB_FETCH_FAILED,
+ "select_aml_measures");
+ case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS:
+ json_decref (measures);
+ return TALER_MHD_reply_static (
+ rc->connection,
+ MHD_HTTP_NO_CONTENT,
+ NULL,
+ NULL,
+ 0);
+ case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT:
+ break;
+ }
+ return TALER_MHD_REPLY_JSON_PACK (
+ rc->connection,
+ MHD_HTTP_OK,
+ GNUNET_JSON_pack_array_steal ("measures",
+ measures));
+ }
+}
+
+
+/* end of taler-exchange-httpd_legitimization-measures_get.c */
diff --git a/src/exchange/taler-exchange-httpd_aml-legitimization-measures-get.h b/src/exchange/taler-exchange-httpd_aml-legitimization-measures-get.h
@@ -0,0 +1,43 @@
+/*
+ This file is part of TALER
+ Copyright (C) 2023 Taler Systems SA
+
+ TALER is free software; you can redistribute it and/or modify it under the
+ terms of the GNU Affero General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ TALER is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License along with
+ TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
+*/
+/**
+ * @file taler-exchange-httpd_aml-legitimization-measures-get.h
+ * @brief Handle /aml/$OFFICER_PUB/legitimizations requests
+ * @author Christian Grothoff
+ */
+#ifndef TALER_EXCHANGE_HTTPD_AML_LEGITIMIZATION_MEASURES_GET_H
+#define TALER_EXCHANGE_HTTPD_AML_LEGITIMIZATION_MEASURES_GET_H
+
+#include <microhttpd.h>
+#include "taler-exchange-httpd.h"
+
+/**
+ * Handle a GET "/aml/$OFFICER_PUB/legitimizations" request. Parses the request
+ * details, checks the signatures and if appropriately authorized returns
+ * the matching measuress.
+ *
+ * @param rc request context
+ * @param officer_pub public key of the AML officer who made the request
+ * @param args GET arguments (should be the state)
+ * @return MHD result code
+ */
+MHD_RESULT
+TEH_handler_aml_legitimization_measures_get (
+ struct TEH_RequestContext *rc,
+ const struct TALER_AmlOfficerPublicKeyP *officer_pub,
+ const char *const args[]);
+
+#endif
diff --git a/src/exchange/taler-exchange-httpd_legitimization-measures-get.c b/src/exchange/taler-exchange-httpd_legitimization-measures-get.c
@@ -1,175 +0,0 @@
-/*
- This file is part of TALER
- Copyright (C) 2024 Taler Systems SA
-
- TALER is free software; you can redistribute it and/or modify it under the
- terms of the GNU Affero General Public License as published by the Free Software
- Foundation; either version 3, or (at your option) any later version.
-
- TALER is distributed in the hope that it will be useful, but WITHOUT ANY
- WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
- A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details.
-
- You should have received a copy of the GNU Affero General Public License along with
- TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
-*/
-/**
- * @file taler-exchange-httpd_legitimization-measures-get.c
- * @brief Return information about legitimization measures
- * @author Christian Grothoff
- */
-#include "platform.h"
-#include <gnunet/gnunet_util_lib.h>
-#include <jansson.h>
-#include <microhttpd.h>
-#include <pthread.h>
-#include "taler_json_lib.h"
-#include "taler_mhd_lib.h"
-#include "taler_signatures.h"
-#include "taler-exchange-httpd.h"
-#include "taler_exchangedb_plugin.h"
-#include "taler-exchange-httpd_legitimization-measures-get.h"
-#include "taler-exchange-httpd_metrics.h"
-
-/**
- * Maximum number of measures we return in one request.
- */
-#define MAX_MEASURES 1024
-
-/**
- * Return LEGITIMIZATION measure.
- *
- * @param cls closure
- * @param h_payto hash of account the measure applies to
- * @param start_time when was the process started
- * @param jmeasures object of type ``LegitimizationMeasures``
- * @param is_finished true if the measure was finished
- * @param measure_serial_id row ID of the measure in the exchange table
- */
-static void
-record_cb (
- void *cls,
- struct TALER_NormalizedPaytoHashP *h_payto,
- struct GNUNET_TIME_Timestamp start_time,
- const json_t *jmeasures,
- bool is_finished,
- uint64_t measure_serial_id)
-{
- json_t *measures = cls;
-
- GNUNET_assert (
- 0 ==
- json_array_append_new (
- measures,
- GNUNET_JSON_PACK (
- GNUNET_JSON_pack_data_auto ("h_payto",
- h_payto),
- GNUNET_JSON_pack_uint64 ("rowid",
- measure_serial_id),
- GNUNET_JSON_pack_timestamp ("start_time",
- start_time),
- GNUNET_JSON_pack_allow_null (
- GNUNET_JSON_pack_object_incref ("measures",
- (json_t *) jmeasures)),
- GNUNET_JSON_pack_bool ("is_finished",
- is_finished)
- )));
-}
-
-
-MHD_RESULT
-TEH_handler_legitimization_measures_get (
- struct TEH_RequestContext *rc,
- const struct TALER_AmlOfficerPublicKeyP *officer_pub,
- const char *const args[])
-{
- int64_t limit = -20;
- uint64_t offset;
- struct TALER_NormalizedPaytoHashP h_payto;
- bool have_payto = false;
- enum TALER_EXCHANGE_YesNoAll active_filter;
-
- if (NULL != args[0])
- {
- GNUNET_break_op (0);
- return TALER_MHD_reply_with_error (
- rc->connection,
- MHD_HTTP_NOT_FOUND,
- TALER_EC_GENERIC_ENDPOINT_UNKNOWN,
- args[0]);
- }
- TALER_MHD_parse_request_snumber (rc->connection,
- "limit",
- &limit);
- if (limit > 0)
- offset = 0;
- else
- offset = INT64_MAX;
- TALER_MHD_parse_request_number (rc->connection,
- "offset",
- &offset);
- if (offset > INT64_MAX)
- {
- GNUNET_break_op (0); /* broken client */
- offset = INT64_MAX;
- }
- TALER_MHD_parse_request_arg_auto (rc->connection,
- "h_payto",
- &h_payto,
- have_payto);
- TALER_MHD_parse_request_yna (rc->connection,
- "active",
- TALER_EXCHANGE_YNA_ALL,
- &active_filter);
- {
- json_t *measures;
- enum GNUNET_DB_QueryStatus qs;
-
- measures = json_array ();
- GNUNET_assert (NULL != measures);
- if (limit > MAX_MEASURES)
- limit = MAX_MEASURES;
- if (limit < -MAX_MEASURES)
- limit = -MAX_MEASURES;
- qs = TEH_plugin->select_aml_measures (
- TEH_plugin->cls,
- have_payto
- ? &h_payto
- : NULL,
- active_filter,
- offset,
- limit,
- &record_cb,
- measures);
- switch (qs)
- {
- case GNUNET_DB_STATUS_HARD_ERROR:
- case GNUNET_DB_STATUS_SOFT_ERROR:
- json_decref (measures);
- GNUNET_break (0);
- return TALER_MHD_reply_with_error (
- rc->connection,
- MHD_HTTP_INTERNAL_SERVER_ERROR,
- TALER_EC_GENERIC_DB_FETCH_FAILED,
- "select_aml_measures");
- case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS:
- json_decref (measures);
- return TALER_MHD_reply_static (
- rc->connection,
- MHD_HTTP_NO_CONTENT,
- NULL,
- NULL,
- 0);
- case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT:
- break;
- }
- return TALER_MHD_REPLY_JSON_PACK (
- rc->connection,
- MHD_HTTP_OK,
- GNUNET_JSON_pack_array_steal ("measures",
- measures));
- }
-}
-
-
-/* end of taler-exchange-httpd_legitimization-measures_get.c */
diff --git a/src/exchange/taler-exchange-httpd_legitimization-measures-get.h b/src/exchange/taler-exchange-httpd_legitimization-measures-get.h
@@ -1,43 +0,0 @@
-/*
- This file is part of TALER
- Copyright (C) 2023 Taler Systems SA
-
- TALER is free software; you can redistribute it and/or modify it under the
- terms of the GNU Affero General Public License as published by the Free Software
- Foundation; either version 3, or (at your option) any later version.
-
- TALER is distributed in the hope that it will be useful, but WITHOUT ANY
- WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
- A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details.
-
- You should have received a copy of the GNU Affero General Public License along with
- TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
-*/
-/**
- * @file taler-exchange-httpd_legitimization-measures-get.h
- * @brief Handle /aml/$OFFICER_PUB/legitimizations requests
- * @author Christian Grothoff
- */
-#ifndef TALER_EXCHANGE_HTTPD_LEGITIMIZATION_MEASURES_GET_H
-#define TALER_EXCHANGE_HTTPD_LEGITIMIZATION_MEASURES_GET_H
-
-#include <microhttpd.h>
-#include "taler-exchange-httpd.h"
-
-/**
- * Handle a GET "/aml/$OFFICER_PUB/legitimizations" request. Parses the request
- * details, checks the signatures and if appropriately authorized returns
- * the matching measuress.
- *
- * @param rc request context
- * @param officer_pub public key of the AML officer who made the request
- * @param args GET arguments (should be the state)
- * @return MHD result code
- */
-MHD_RESULT
-TEH_handler_legitimization_measures_get (
- struct TEH_RequestContext *rc,
- const struct TALER_AmlOfficerPublicKeyP *officer_pub,
- const char *const args[]);
-
-#endif
diff --git a/src/include/taler-exchange/Makefile.am b/src/include/taler-exchange/Makefile.am
@@ -3,4 +3,5 @@ talerincludedir = $(includedir)/taler/taler-exchange
talerinclude_HEADERS = \
aml_legitimizations_get.h \
+ reserves_get.h \
common.h
diff --git a/src/include/taler-exchange/aml_attributes_get.h b/src/include/taler-exchange/aml_attributes_get.h
@@ -0,0 +1,292 @@
+/*
+ This file is part of TALER
+ Copyright (C) 2025 Taler Systems SA
+
+ TALER is free software; you can redistribute it and/or modify it under the
+ terms of the GNU Affero General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ TALER is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License along with
+ TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
+ */
+/**
+ * @file include/taler-exchange/aml_attributes_get.h
+ * @brief C interface for the GET /aml/$OFFICER_PUB/attributes/$H_NORMALIZED_PAYTO endpoint
+ * @author Christian Grothoff
+ */
+#ifndef _TALER_EXCHANGE__AML_ATTRIBUTES_GET_H
+#define _TALER_EXCHANGE__AML_ATTRIBUTES_GET_H
+
+#include <taler-exchange/common.h>
+
+/**
+ * Possible options we can set for the GET attributes request.
+ */
+enum TALER_EXCHANGE_AmlAttributesGetOption
+{
+ /**
+ * End of list of options.
+ */
+ TALER_EXCHANGE_AML_ATTRIBUTES_GET_OPTION_END = 0,
+
+ /**
+ * Return at most N values, default is -20 to return
+ * the last 20 entries before start. Negative values
+ * to return before limit, positive to return after limit.
+ */
+ TALER_EXCHANGE_AML_ATTRIBUTES_GET_OPTION_LIMIT,
+
+ /**
+ * Row number threshold, defaults to INT64_MAX, namely
+ * the biggest row id possible in the database.
+ */
+ TALER_EXCHANGE_AML_ATTRIBUTES_GET_OPTION_OFFSET
+
+};
+
+
+/**
+ * Possible options we can set for the GET attributes request.
+ */
+struct TALER_EXCHANGE_AmlAttributesGetOptionValue
+{
+
+ /**
+ * Type of the option being set.
+ */
+ enum TALER_EXCHANGE_AmlAttributesGetOption option;
+
+ /**
+ * Specific option value.
+ */
+ union
+ {
+
+ /**
+ * Value of if @e option is TALER_EXCHANGE_AML_ATTRIBUTES_GET_OPTION_LIMIT.
+ */
+ int64_t limit;
+
+ /**
+ * Value of if @e option is TALER_EXCHANGE_AML_ATTRIBUTES_GET_OPTION_OFFSET.
+ * Note that in practice the maximum value is INT64_MAX, even though
+ * this value is unsigned.
+ */
+ uint64_t offset;
+
+ } details;
+
+};
+
+
+/**
+ * Handle for an operation to GET /aml/$OFFICER_PUB/attributes/$H_NORMALIZED_PAYTO.
+ */
+struct TALER_EXCHANGE_AmlAttributesGetHandle;
+
+
+/**
+ * Set up GET /aml/$OPUB/attributes/$H_NORMALIZED_PAYTO operation.
+ * Note that you must explicitly start the operation after
+ * possibly setting options.
+ *
+ * @param ctx the context
+ * @param url base URL of the exchange
+ * @param officer_priv private key of the officer
+ * @param h_payto normalized payto URI hash of the account to get attributes for
+ * @return handle to operation
+ */
+struct TALER_EXCHANGE_AmlAttributesGetHandle *
+TALER_EXCHANGE_aml_attributes_get_create (
+ struct GNUNET_CURL_Context *ctx,
+ const char *url,
+ const struct TALER_AmlOfficerPrivateKeyP *officer_priv,
+ const struct TALER_NormalizedPaytoHashP *h_payto);
+
+
+/**
+ * Terminate the list of the options.
+ *
+ * @return the terminating object of struct TALER_EXCHANGE_AmlAttributesGetOptionValue
+ */
+#define TALER_EXCHANGE_aml_attributes_get_option_end_() \
+ (const struct TALER_EXCHANGE_AmlAttributesGetOptionValue) \
+ { \
+ .option = TALER_EXCHANGE_AML_ATTRIBUTES_GET_OPTION_END \
+ }
+
+/**
+ * Set limit @a l on the number of results to return.
+ *
+ * @param l limit on the number of results to return
+ * @return representation of the option as a struct TALER_EXCHANGE_AmlAttributesGetOptionValue
+ */
+#define TALER_EXCHANGE_aml_attributes_get_option_limit_(l) \
+ (const struct TALER_EXCHANGE_AmlAttributesGetOptionValue) \
+ { \
+ .option = TALER_EXCHANGE_AML_ATTRIBUTES_GET_OPTION_LIMIT, \
+ .details.limit = (l) \
+ }
+
+
+/**
+ * Set row offset from which to return results.
+ *
+ * @param o offset to use
+ * @return representation of the option as a struct TALER_EXCHANGE_AmlAttributesGetOptionValue
+ */
+#define TALER_EXCHANGE_aml_attributes_get_option_offset_(o) \
+ (const struct TALER_EXCHANGE_AmlAttributesGetOptionValue) \
+ { \
+ .option = TALER_EXCHANGE_AML_ATTRIBUTES_GET_OPTION_OFFSET, \
+ .details.offset = (o) \
+ }
+
+
+enum TALER_ErrorCode
+TALER_EXCHANGE_aml_attributes_get_set_options_ (
+ struct TALER_EXCHANGE_AmlAttributesGetHandle *aagh,
+ unsigned int num_options,
+ struct TALER_EXCHANGE_AmlAttributesGetOptionValue options[
+ static num_options]);
+
+
+/**
+ * Set the requested options for the operation.
+ *
+ * If any option fail other options may be or may be not applied.
+ *
+ * It should be used with helpers that creates required options, for example:
+ *
+ * TALER_EXCHANGE_aml_attributes_get_set_options (
+ * aagh,
+ * TALER_EXCHANGE_aml_attributes_get_option_limit_(10));
+ *
+ * @param aagh the request to set the options for
+ * @param ... the list of the options, each option must be created
+ * by helpers TALER_EXCHANGE_aml_attributes_get_option_NAME(VALUE)
+ * @return ::TALER_EC_NONE on success,
+ * error code otherwise
+ */
+#define TALER_EXCHANGE_aml_attributes_get_set_options(aagh,...) \
+ TALER_EXCHANGE_aml_attributes_get_set_options_ ( \
+ aagh, \
+ ((const struct TALER_EXCHANGE_AmlAttributesGetOptionValue[]) \
+ {__VA_ARGS__, TALER_EXCHANGE_aml_attributes_get_option_end_ () } \
+ ), \
+ TALER_EXCHANGE_COMMON_OPTIONS_ARRAY_MAX_SIZE)
+
+
+/**
+ * Entry in the set of KYC attribute collection events that are returned
+ * by the server in a single request.
+ */
+struct TALER_EXCHANGE_AmlAttributesGetCollectionEvent
+{
+ /**
+ * Row ID of the record. Used to filter by offset.
+ */
+ uint64_t rowid;
+
+ /**
+ * The collected KYC data. NULL if the attribute data could not
+ * be decrypted (internal error of the exchange, likely the
+ * attribute key was changed).
+ */
+ const json_t *attributes;
+
+ /**
+ * Time when the KYC data was collected.
+ */
+ struct GNUNET_TIME_Timestamp collection_time;
+};
+
+/**
+ * Information returned from the exchange for a
+ * GET /aml/$OFFICER_PUB/attributes/$H_NORMALIZED_PAYTO request.
+ */
+struct TALER_EXCHANGE_AmlAttributesGetResult
+{
+ /**
+ * HTTP response data
+ */
+ struct TALER_EXCHANGE_HttpResponse hr;
+
+ /**
+ * Details depending on the HTTP status code.
+ */
+ union
+ {
+
+ /**
+ * Details on #MHD_HTTP_OK.
+ */
+ struct
+ {
+ /**
+ * Length of the @e details array.
+ */
+ size_t details_length;
+
+ /**
+ * Matching KYC attribute history of the account.
+ */
+ const struct TALER_EXCHANGE_AmlAttributesGetCollectionEvent *details;
+
+ } ok;
+
+ } details;
+};
+
+
+#ifndef TALER_EXCHANGE__AML_ATTRIBUTES_GET_RESULT_CLOSURE
+/**
+ * Type of the closure used by
+ * the #TALER_EXCHANGE_AmlAttributesGetCallback.
+ */
+#define TALER_EXCHANGE__AML_ATTRIBUTES_GET_RESULT_CLOSURE void
+#endif
+
+/**
+ * Type of the function that receives the result of a
+ * GET /aml/$OFFICER_PUB/attributes/$H_NORMALIZED_PAYTO request.
+ *
+ * @param cls closure
+ * @param result result returned by the HTTP server
+ */
+typedef void
+(*TALER_EXCHANGE_AmlAttributesGetCallback)(
+ TALER_EXCHANGE__AML_ATTRIBUTES_GET_RESULT_CLOSURE *cls,
+ const struct TALER_EXCHANGE_AmlAttributesGetResult *result);
+
+
+/**
+ * Start GET /aml/$OPUB/attributes/$H_NORMALIZED_PAYTO operation.
+ *
+ * @param[in,out] aagh operation to start
+ * @param cb function to call with the exchange's result
+ * @param cb_cls closure for @a cb
+ * @return status code
+ */
+enum TALER_ErrorCode
+TALER_EXCHANGE_aml_attributes_get_start (
+ struct TALER_EXCHANGE_AmlAttributesGetHandle *aagh,
+ TALER_EXCHANGE_AmlAttributesGetCallback cb,
+ TALER_EXCHANGE__AML_ATTRIBUTES_GET_RESULT_CLOSURE *cb_cls);
+
+
+/**
+ * Cancel GET /aml/$OPUB/attributes/$H_NORMALIZED_PAYTO operation.
+ *
+ * @param[in] aagh operation to cancel
+ */
+void
+TALER_EXCHANGE_aml_attributes_get_cancel (
+ struct TALER_EXCHANGE_AmlAttributesGetHandle *aagh);
+
+
+#endif
diff --git a/src/include/taler-exchange/aml_decisions_get.h b/src/include/taler-exchange/aml_decisions_get.h
@@ -0,0 +1,483 @@
+/*
+ This file is part of TALER
+ Copyright (C) 2025 Taler Systems SA
+
+ TALER is free software; you can redistribute it and/or modify it under the
+ terms of the GNU Affero General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ TALER is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License along with
+ TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
+ */
+/**
+ * @file include/taler-exchange/aml_decisions_get.h
+ * @brief C interface for the GET /aml/$OFFICER_PUB/decisions endpoint
+ * @author Christian Grothoff
+ */
+#ifndef _TALER_EXCHANGE__AML_DECISIONS_GET_H
+#define _TALER_EXCHANGE__AML_DECISIONS_GET_H
+
+#include <taler-exchange/common.h>
+
+/**
+ * Possible options we can set for the GET decisions request.
+ */
+enum TALER_EXCHANGE_AmlDecisionsGetOption
+{
+ /**
+ * End of list of options.
+ */
+ TALER_EXCHANGE_AML_DECISIONS_GET_OPTION_END = 0,
+
+ /**
+ * Return at most N values, default is -20 to return
+ * the last 20 entries before start. Negative values
+ * to return before limit, positive to return after limit.
+ */
+ TALER_EXCHANGE_AML_DECISIONS_GET_OPTION_LIMIT,
+
+ /**
+ * Row number threshold, defaults to INT64_MAX, namely
+ * the biggest row id possible in the database.
+ */
+ TALER_EXCHANGE_AML_DECISIONS_GET_OPTION_OFFSET,
+
+ /**
+ * Filter by account using a normalized payto URI hash.
+ */
+ TALER_EXCHANGE_AML_DECISIONS_GET_OPTION_H_PAYTO,
+
+ /**
+ * If set to #TALER_EXCHANGE_YNA_YES, only return active
+ * results, #TALER_EXCHANGE_YNA_NO, only return inactive
+ * results, #TALER_EXCHANGE_YNA_ALL, to return all
+ * decisions. Default is all.
+ */
+ TALER_EXCHANGE_AML_DECISIONS_GET_OPTION_ACTIVE,
+
+ /**
+ * If set to #TALER_EXCHANGE_YNA_YES, only return accounts
+ * under investigation, #TALER_EXCHANGE_YNA_NO, only return
+ * accounts not under investigation, #TALER_EXCHANGE_YNA_ALL,
+ * to return all accounts. Default is all.
+ */
+ TALER_EXCHANGE_AML_DECISIONS_GET_OPTION_INVESTIGATION
+
+};
+
+
+/**
+ * Possible options we can set for the GET decisions request.
+ */
+struct TALER_EXCHANGE_AmlDecisionsGetOptionValue
+{
+
+ /**
+ * Type of the option being set.
+ */
+ enum TALER_EXCHANGE_AmlDecisionsGetOption option;
+
+ /**
+ * Specific option value.
+ */
+ union
+ {
+
+ /**
+ * Value of if @e option is TALER_EXCHANGE_AML_DECISIONS_GET_OPTION_LIMIT.
+ */
+ int64_t limit;
+
+ /**
+ * Value of if @e option is TALER_EXCHANGE_AML_DECISIONS_GET_OPTION_OFFSET.
+ * Note that in practice the maximum value is INT64_MAX, even though
+ * this value is unsigned.
+ */
+ uint64_t offset;
+
+ /**
+ * Value of if @e option is TALER_EXCHANGE_AML_DECISIONS_GET_OPTION_H_PAYTO.
+ */
+ const struct TALER_NormalizedPaytoHashP *h_payto;
+
+ /**
+ * Value of if @e option is TALER_EXCHANGE_AML_DECISIONS_GET_OPTION_ACTIVE.
+ */
+ enum TALER_EXCHANGE_YesNoAll active;
+
+ /**
+ * Value of if @e option is TALER_EXCHANGE_AML_DECISIONS_GET_OPTION_INVESTIGATION.
+ */
+ enum TALER_EXCHANGE_YesNoAll investigation;
+
+ } details;
+
+};
+
+
+/**
+ * Handle for an operation to GET /aml/$OFFICER_PUB/decisions.
+ */
+struct TALER_EXCHANGE_AmlDecisionsGetHandle;
+
+
+/**
+ * Information about a KYC rule.
+ */
+struct TALER_EXCHANGE_AmlDecisionsGetKycRule
+{
+ /**
+ * Type of operation to which the rule applies.
+ */
+ enum TALER_KYCLOGIC_KycTriggerEvent operation_type;
+
+ /**
+ * Name of the configuration section this rule originates from.
+ * Can be NULL.
+ */
+ const char *rule_name;
+
+ /**
+ * The threshold amount that triggers the measures.
+ */
+ struct TALER_Amount threshold;
+
+ /**
+ * Over which duration should the threshold be computed.
+ */
+ struct GNUNET_TIME_Relative timeframe;
+
+ /**
+ * Length of the @e measures array.
+ */
+ size_t measures_length;
+
+ /**
+ * Array of names of measures to apply.
+ */
+ const char **measures;
+
+ /**
+ * Display priority for this rule.
+ */
+ int64_t display_priority;
+
+ /**
+ * True if the rule should be exposed to the client.
+ */
+ bool exposed;
+
+ /**
+ * True if all measures need to be satisfied (AND combinator),
+ * false if any measure is sufficient (OR combinator).
+ */
+ bool is_and_combinator;
+};
+
+
+/**
+ * Legitimization rule set associated with an AML decision.
+ */
+struct TALER_EXCHANGE_AmlDecisionsGetLegitimizationRuleSet
+{
+ /**
+ * When does this set of rules expire?
+ */
+ struct GNUNET_TIME_Timestamp expiration_time;
+
+ /**
+ * Name of the successor measure to apply when expiration time is reached.
+ * Can be NULL.
+ */
+ const char *successor_measure;
+
+ /**
+ * Length of the @e rules array.
+ */
+ size_t rules_length;
+
+ /**
+ * Array of KYC rules.
+ */
+ struct TALER_EXCHANGE_AmlDecisionsGetKycRule *rules;
+
+ /**
+ * Custom measures.
+ */
+ const json_t *custom_measures;
+};
+
+
+/**
+ * Entry in the set of AML decisions that are returned
+ * by the server in a single request.
+ */
+struct TALER_EXCHANGE_AmlDecisionsGetDecision
+{
+ /**
+ * Hash of the normalized payto:// URI of the account the
+ * decision applies to.
+ */
+ struct TALER_NormalizedPaytoHashP h_payto;
+
+ /**
+ * True if the underlying payto://-URI is for a wallet.
+ */
+ bool is_wallet;
+
+ /**
+ * Row ID of the decision in the exchange database.
+ */
+ uint64_t rowid;
+
+ /**
+ * Justification for the decision. Can be NULL.
+ */
+ const char *justification;
+
+ /**
+ * When was the decision made?
+ */
+ struct GNUNET_TIME_Timestamp decision_time;
+
+ /**
+ * Account properties. Can be NULL if no properties are set.
+ */
+ const json_t *properties;
+
+ /**
+ * Legitimization rules that apply to this account.
+ */
+ struct TALER_EXCHANGE_AmlDecisionsGetLegitimizationRuleSet limits;
+
+ /**
+ * True if the account is under investigation by AML staff.
+ */
+ bool to_investigate;
+
+ /**
+ * True if this is the active decision for the account.
+ */
+ bool is_active;
+};
+
+
+/**
+ * Information returned from the exchange for a
+ * GET /aml/$OFFICER_PUB/decisions request.
+ */
+struct TALER_EXCHANGE_AmlDecisionsGetResult
+{
+ /**
+ * HTTP response data
+ */
+ struct TALER_EXCHANGE_HttpResponse hr;
+
+ /**
+ * Details depending on the HTTP status code.
+ */
+ union
+ {
+
+ /**
+ * Details on #MHD_HTTP_OK.
+ */
+ struct
+ {
+ /**
+ * Length of the @e records array.
+ */
+ size_t records_length;
+
+ /**
+ * AML decisions.
+ */
+ const struct TALER_EXCHANGE_AmlDecisionsGetDecision *records;
+
+ } ok;
+
+ } details;
+};
+
+
+/**
+ * Set up GET /aml/$OPUB/decisions operation.
+ * Note that you must explicitly start the operation after
+ * possibly setting options.
+ *
+ * @param ctx the context
+ * @param url base URL of the exchange
+ * @param officer_priv private key of the officer
+ * @return handle to operation
+ */
+struct TALER_EXCHANGE_AmlDecisionsGetHandle *
+TALER_EXCHANGE_aml_decisions_get_create (
+ struct GNUNET_CURL_Context *ctx,
+ const char *url,
+ const struct TALER_AmlOfficerPrivateKeyP *officer_priv);
+
+
+/**
+ * Terminate the list of the options.
+ *
+ * @return the terminating object of struct TALER_EXCHANGE_AmlDecisionsGetOptionValue
+ */
+#define TALER_EXCHANGE_aml_decisions_get_option_end_() \
+ (const struct TALER_EXCHANGE_AmlDecisionsGetOptionValue) \
+ { \
+ .option = TALER_EXCHANGE_AML_DECISIONS_GET_OPTION_END \
+ }
+
+/**
+ * Set limit @a l on the number of results to return.
+ *
+ * @param l limit on the number of results to return
+ * @return representation of the option as a struct TALER_EXCHANGE_AmlDecisionsGetOptionValue
+ */
+#define TALER_EXCHANGE_aml_decisions_get_option_limit_(l) \
+ (const struct TALER_EXCHANGE_AmlDecisionsGetOptionValue) \
+ { \
+ .option = TALER_EXCHANGE_AML_DECISIONS_GET_OPTION_LIMIT, \
+ .details.limit = (l) \
+ }
+
+
+/**
+ * Set row offset from which to return results.
+ *
+ * @param o offset to use
+ * @return representation of the option as a struct TALER_EXCHANGE_AmlDecisionsGetOptionValue
+ */
+#define TALER_EXCHANGE_aml_decisions_get_option_offset_(o) \
+ (const struct TALER_EXCHANGE_AmlDecisionsGetOptionValue) \
+ { \
+ .option = TALER_EXCHANGE_AML_DECISIONS_GET_OPTION_OFFSET, \
+ .details.offset = (o) \
+ }
+
+
+/**
+ * Set filter on which account to filter AML decisions by.
+ *
+ * @param p normalized payto URI hash of the account to filter by
+ * @return representation of the option as a struct TALER_EXCHANGE_AmlDecisionsGetOptionValue
+ */
+#define TALER_EXCHANGE_aml_decisions_get_option_h_payto_(p) \
+ (const struct TALER_EXCHANGE_AmlDecisionsGetOptionValue) \
+ { \
+ .option = TALER_EXCHANGE_AML_DECISIONS_GET_OPTION_H_PAYTO, \
+ .details.h_payto = (p) \
+ }
+
+/**
+ * Set filter on active (or inactive) results.
+ *
+ * @param a activity filter to use
+ * @return representation of the option as a struct TALER_EXCHANGE_AmlDecisionsGetOptionValue
+ */
+#define TALER_EXCHANGE_aml_decisions_get_option_active_(a) \
+ (const struct TALER_EXCHANGE_AmlDecisionsGetOptionValue) \
+ { \
+ .option = TALER_EXCHANGE_AML_DECISIONS_GET_OPTION_ACTIVE, \
+ .details.active = (a) \
+ }
+
+/**
+ * Set filter on investigation status.
+ *
+ * @param i investigation filter to use
+ * @return representation of the option as a struct TALER_EXCHANGE_AmlDecisionsGetOptionValue
+ */
+#define TALER_EXCHANGE_aml_decisions_get_option_investigation_(i) \
+ (const struct TALER_EXCHANGE_AmlDecisionsGetOptionValue) \
+ { \
+ .option = TALER_EXCHANGE_AML_DECISIONS_GET_OPTION_INVESTIGATION, \
+ .details.investigation = (i) \
+ }
+
+
+enum TALER_ErrorCode
+TALER_EXCHANGE_aml_decisions_get_set_options_ (
+ struct TALER_EXCHANGE_AmlDecisionsGetHandle *adgh,
+ unsigned int num_options,
+ struct TALER_EXCHANGE_AmlDecisionsGetOptionValue options[
+ static num_options]);
+
+
+/**
+ * Set the requested options for the operation.
+ *
+ * If any option fail other options may be or may be not applied.
+ *
+ * It should be used with helpers that creates required options, for example:
+ *
+ * TALER_EXCHANGE_aml_decisions_get_set_options (
+ * adgh,
+ * TALER_EXCHANGE_aml_decisions_get_option_h_payto_(&h_payto));
+ *
+ * @param adgh the request to set the options for
+ * @param ... the list of the options, each option must be created
+ * by helpers TALER_EXCHANGE_aml_decisions_get_option_NAME(VALUE)
+ * @return ::TALER_EC_NONE on success,
+ * error code otherwise
+ */
+#define TALER_EXCHANGE_aml_decisions_get_set_options(adgh,...) \
+ TALER_EXCHANGE_aml_decisions_get_set_options_ ( \
+ adgh, \
+ ((const struct TALER_EXCHANGE_AmlDecisionsGetOptionValue[]) \
+ {__VA_ARGS__, TALER_EXCHANGE_aml_decisions_get_option_end_ () } \
+ ), \
+ TALER_EXCHANGE_COMMON_OPTIONS_ARRAY_MAX_SIZE)
+
+
+#ifndef TALER_EXCHANGE__AML_DECISIONS_GET_RESULT_CLOSURE
+/**
+ * Type of the closure used by
+ * the #TALER_EXCHANGE_AmlDecisionsGetCallback.
+ */
+#define TALER_EXCHANGE__AML_DECISIONS_GET_RESULT_CLOSURE void
+#endif
+
+/**
+ * Type of the function that receives the result of a
+ * GET /aml/$OFFICER_PUB/decisions request.
+ *
+ * @param cls closure
+ * @param result result returned by the HTTP server
+ */
+typedef void
+(*TALER_EXCHANGE_AmlDecisionsGetCallback)(
+ TALER_EXCHANGE__AML_DECISIONS_GET_RESULT_CLOSURE *cls,
+ const struct TALER_EXCHANGE_AmlDecisionsGetResult *result);
+
+
+/**
+ * Start GET /aml/$OPUB/decisions operation.
+ *
+ * @param[in,out] adgh operation to start
+ * @param cb function to call with the exchange's result
+ * @param cb_cls closure for @a cb
+ * @return status code
+ */
+enum TALER_ErrorCode
+TALER_EXCHANGE_aml_decisions_get_start (
+ struct TALER_EXCHANGE_AmlDecisionsGetHandle *adgh,
+ TALER_EXCHANGE_AmlDecisionsGetCallback cb,
+ TALER_EXCHANGE__AML_DECISIONS_GET_RESULT_CLOSURE *cb_cls);
+
+
+/**
+ * Cancel GET /aml/$OPUB/decisions operation.
+ *
+ * @param[in] adgh operation to cancel
+ */
+void
+TALER_EXCHANGE_aml_decisions_get_cancel (
+ struct TALER_EXCHANGE_AmlDecisionsGetHandle *adgh);
+
+
+#endif
diff --git a/src/include/taler-exchange/aml_legitimizations_get.h b/src/include/taler-exchange/aml_legitimizations_get.h
@@ -191,11 +191,30 @@ TALER_EXCHANGE_aml_legitimizations_get_create (
(const struct TALER_EXCHANGE_AmlLegitimizationsGetOptionValue) \
{ \
.option = TALER_EXCHANGE_AML_LEGITIMIZATIONS_GET_OPTION_ACTIVE, \
- .details.active = (o) \
+ .details.active = (a) \
}
-enum TALER_ErrorCode
+/**
+ * Set the requested options for the operation.
+ *
+ * If any option fail other options may be or may be not applied.
+ *
+ * It should be used with helpers that creates required options, for example:
+ *
+ * TALER_EXCHANGE_aml_legitimizations_get_set_options (
+ * algh,
+ * TALER_EXCHANGE_aml_legitimizations_get_option_h_payto_(&h_payto));
+ *
+ * @param algh the request to set the options for
+ * @param num_options length of the @a options array
+ * @param options array of options, each option must be created
+ * by helpers TALER_EXCHANGE_aml_legitimizations_get_option_NAME(VALUE)
+ * @return #GNUNET_OK on success,
+ * #GNUNET_NO on failure,
+ * #GNUNET_SYSERR on internal error
+ */
+enum GNUNET_GenericReturnValue
TALER_EXCHANGE_aml_legitimizations_get_set_options_ (
struct TALER_EXCHANGE_AmlLegitimizationsGetHandle *algh,
unsigned int num_options,
@@ -217,8 +236,9 @@ TALER_EXCHANGE_aml_legitimizations_get_set_options_ (
* @param algh the request to set the options for
* @param ... the list of the options, each option must be created
* by helpers TALER_EXCHANGE_aml_legitimizations_get_option_NAME(VALUE)
- * @return ::TALER_EC_NONE on success,
- * error code otherwise
+ * @return #GNUNET_OK on success,
+ * #GNUNET_NO on failure,
+ * #GNUNET_SYSERR on internal error
*/
#define TALER_EXCHANGE_aml_legitimizations_get_set_options(algh,...) \
TALER_EXCHANGE_aml_legitimizations_get_set_options_ ( \
@@ -230,86 +250,34 @@ TALER_EXCHANGE_aml_legitimizations_get_set_options_ (
/**
- * Information about legitimization measures that apply to the
- * customer at a particular point in time.
- */
-struct TALER_EXCHANGE_AmlLegitimizationsGetMeasureInformation
-{
- /**
- * Name of the KYC check.
- */
- const char *check_name;
-
- /**
- * Name of the AML program to run on the KYC check's result.
- */
- const char *prog_name;
-
- /**
- * Context for the check and AML program. Can be NULL!
- */
- const json_t *context;
-
- /**
- * Type of operation that triggered this measure,
- * #TALER_KYCLOGIC_KYC_TRIGGER_NONE if unknown / not applicable.
- */
- enum TALER_KYCLOGIC_KycTriggerEvent operation_type;
-
- /**
- * True if the customer can voluntarily do this measure.
- */
- bool voluntary;
-};
-
-
-/**
* Entry in the set of legitimization measures that are returned
* by the server in a single request.
*/
struct TALER_EXCHANGE_AmlLegitimizationsGetMeasureDetails
{
/**
- * Account the measure applies to.
+ * Hash of the normalized payto:// URI of the account the
+ * measure applies to.
*/
struct TALER_NormalizedPaytoHashP h_payto;
/**
- * Row ID of the measure in the exchange.
+ * Row ID of the measure in the exchange database.
*/
uint64_t rowid;
/**
- * When was the measure started/triggered?
+ * When was the measure started / triggered?
*/
struct GNUNET_TIME_Timestamp start_time;
/**
- * Length of the @e mi array.
- */
- size_t mi_length;
-
- /**
- * Array of legitimization measures that are to be applied.
+ * Object with the legitimization measures that are to be applied.
*/
- struct TALER_EXCHANGE_AmlLegitimizationsGetMeasureInformation *mi;
+ const json_t *measures;
/**
- * True if the entries in the
- * the @e mi are expected to be all satisfied,
- * false if the customer has to chose one of them.
- */
- bool is_and_combinator;
-
- /**
- * Was some operation categorically forbidden and hence
- * the customer cannot even do something here? If true,
- * then the @e mi array will be empty.
- */
- bool verboten;
-
- /**
- * Was this measure finished by the customer (or obsoleted
+ * Was this measure finished by the customer? (or obsoleted
* by a subsequent other measure taken)?
*/
bool is_finished;
@@ -343,7 +311,7 @@ struct TALER_EXCHANGE_AmlLegitimizationsGetResult
size_t measures_length;
/**
- * Legitimization measures that apply to the account(s).
+ * Legitimization measures.
*/
const struct TALER_EXCHANGE_AmlLegitimizationsGetMeasureDetails *measures;
@@ -380,12 +348,27 @@ typedef void
* @param[in,out] algh operation to start
* @param cb function to call with the exchange's result
* @param cb_cls closure for @a cb
+ * @return status code
*/
-void
+enum TALER_EXCHANGE_AmlLegitimizationsGetStartError
+{
+ /**
+ * Success.
+ */
+ TALER_EXCHANGE_AML_LEGITIMIZATIONS_GET_START_OK = 0,
+ /**
+ * Only allowed to be started once.
+ */
+ TALER_EXCHANGE_AML_LEGITIMIZATIONS_GET_START_E_AGAIN = 1,
+ /**
+ * Internal logic failure.
+ */
+ TALER_EXCHANGE_AML_LEGITIMIZATIONS_GET_START_E_INTERNAL = 2,
+}
TALER_EXCHANGE_aml_legitimizations_get_start (
struct TALER_EXCHANGE_AmlLegitimizationsGetHandle *algh,
TALER_EXCHANGE_AmlLegitimizationsGetCallback cb,
- TALER_EXCHANGE__AML_LEGITIMIZATIONS_GET_RESULT_CLOSURE *cb_cls);
+ TALER_EXCHANGE__AML_LEGITIMIZATIONS_GET_RESULT_CLOSURE * cb_cls);
/**
diff --git a/src/include/taler-exchange/aml_transfers_kycauth_get.h b/src/include/taler-exchange/aml_transfers_kycauth_get.h
@@ -0,0 +1,342 @@
+/*
+ This file is part of TALER
+ Copyright (C) 2025 Taler Systems SA
+
+ TALER is free software; you can redistribute it and/or modify it under the
+ terms of the GNU Affero General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ TALER is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License along with
+ TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
+ */
+/**
+ * @file include/taler-exchange/aml_transfers_kycauth_get.h
+ * @brief C interface for the GET /aml/$OFFICER_PUB/transfers-kycauth endpoint
+ * @author Christian Grothoff
+ */
+#ifndef _TALER_EXCHANGE__AML_TRANSFERS_KYCAUTH_GET_H
+#define _TALER_EXCHANGE__AML_TRANSFERS_KYCAUTH_GET_H
+
+#include <taler-exchange/common.h>
+
+/**
+ * Possible options we can set for the GET transfers-kycauth request.
+ */
+enum TALER_EXCHANGE_AmlTransfersKycauthGetOption
+{
+ /**
+ * End of list of options.
+ */
+ TALER_EXCHANGE_AML_TRANSFERS_KYCAUTH_GET_OPTION_END = 0,
+
+ /**
+ * Minimum amount threshold to return. All amounts below
+ * the given threshold will be filtered.
+ */
+ TALER_EXCHANGE_AML_TRANSFERS_KYCAUTH_GET_OPTION_THRESHOLD,
+
+ /**
+ * Return at most N values, default is -20 to return
+ * the last 20 entries before start. Negative values
+ * to return before limit, positive to return after limit.
+ */
+ TALER_EXCHANGE_AML_TRANSFERS_KYCAUTH_GET_OPTION_LIMIT,
+
+ /**
+ * Row number threshold, defaults to INT64_MAX, namely
+ * the biggest row id possible in the database.
+ */
+ TALER_EXCHANGE_AML_TRANSFERS_KYCAUTH_GET_OPTION_OFFSET,
+
+ /**
+ * Filter by account using a normalized payto URI hash.
+ */
+ TALER_EXCHANGE_AML_TRANSFERS_KYCAUTH_GET_OPTION_H_PAYTO
+
+};
+
+
+/**
+ * Possible options we can set for the GET transfers-kycauth request.
+ */
+struct TALER_EXCHANGE_AmlTransfersKycauthGetOptionValue
+{
+
+ /**
+ * Type of the option being set.
+ */
+ enum TALER_EXCHANGE_AmlTransfersKycauthGetOption option;
+
+ /**
+ * Specific option value.
+ */
+ union
+ {
+
+ /**
+ * Value of if @e option is TALER_EXCHANGE_AML_TRANSFERS_KYCAUTH_GET_OPTION_THRESHOLD.
+ */
+ const struct TALER_Amount *threshold;
+
+ /**
+ * Value of if @e option is TALER_EXCHANGE_AML_TRANSFERS_KYCAUTH_GET_OPTION_LIMIT.
+ */
+ int64_t limit;
+
+ /**
+ * Value of if @e option is TALER_EXCHANGE_AML_TRANSFERS_KYCAUTH_GET_OPTION_OFFSET.
+ * Note that in practice the maximum value is INT64_MAX, even though
+ * this value is unsigned.
+ */
+ uint64_t offset;
+
+ /**
+ * Value of if @e option is TALER_EXCHANGE_AML_TRANSFERS_KYCAUTH_GET_OPTION_H_PAYTO.
+ */
+ const struct TALER_NormalizedPaytoHashP *h_payto;
+
+ } details;
+
+};
+
+
+/**
+ * Handle for an operation to GET /aml/$OFFICER_PUB/transfers-kycauth.
+ */
+struct TALER_EXCHANGE_AmlTransfersKycauthGetHandle;
+
+
+/**
+ * Set up GET /aml/$OPUB/transfers-kycauth operation.
+ * Note that you must explicitly start the operation after
+ * possibly setting options.
+ *
+ * @param ctx the context
+ * @param url base URL of the exchange
+ * @param officer_priv private key of the officer
+ * @return handle to operation
+ */
+struct TALER_EXCHANGE_AmlTransfersKycauthGetHandle *
+TALER_EXCHANGE_aml_transfers_kycauth_get_create (
+ struct GNUNET_CURL_Context *ctx,
+ const char *url,
+ const struct TALER_AmlOfficerPrivateKeyP *officer_priv);
+
+
+/**
+ * Terminate the list of the options.
+ *
+ * @return the terminating object of struct TALER_EXCHANGE_AmlTransfersKycauthGetOptionValue
+ */
+#define TALER_EXCHANGE_aml_transfers_kycauth_get_option_end_() \
+ (const struct TALER_EXCHANGE_AmlTransfersKycauthGetOptionValue) \
+ { \
+ .option = TALER_EXCHANGE_AML_TRANSFERS_KYCAUTH_GET_OPTION_END \
+ }
+
+/**
+ * Set minimum amount threshold @a t for transfers to return.
+ *
+ * @param t minimum amount threshold
+ * @return representation of the option as a struct TALER_EXCHANGE_AmlTransfersKycauthGetOptionValue
+ */
+#define TALER_EXCHANGE_aml_transfers_kycauth_get_option_threshold_(t) \
+ (const struct TALER_EXCHANGE_AmlTransfersKycauthGetOptionValue) \
+ { \
+ .option = TALER_EXCHANGE_AML_TRANSFERS_KYCAUTH_GET_OPTION_THRESHOLD, \
+ .details.threshold = (t) \
+ }
+
+/**
+ * Set limit @a l on the number of results to return.
+ *
+ * @param l limit on the number of results to return
+ * @return representation of the option as a struct TALER_EXCHANGE_AmlTransfersKycauthGetOptionValue
+ */
+#define TALER_EXCHANGE_aml_transfers_kycauth_get_option_limit_(l) \
+ (const struct TALER_EXCHANGE_AmlTransfersKycauthGetOptionValue) \
+ { \
+ .option = TALER_EXCHANGE_AML_TRANSFERS_KYCAUTH_GET_OPTION_LIMIT, \
+ .details.limit = (l) \
+ }
+
+
+/**
+ * Set row offset from which to return results.
+ *
+ * @param o offset to use
+ * @return representation of the option as a struct TALER_EXCHANGE_AmlTransfersKycauthGetOptionValue
+ */
+#define TALER_EXCHANGE_aml_transfers_kycauth_get_option_offset_(o) \
+ (const struct TALER_EXCHANGE_AmlTransfersKycauthGetOptionValue) \
+ { \
+ .option = TALER_EXCHANGE_AML_TRANSFERS_KYCAUTH_GET_OPTION_OFFSET, \
+ .details.offset = (o) \
+ }
+
+
+/**
+ * Set filter on which account to filter transfers by.
+ *
+ * @param p normalized payto URI hash of the account to filter by
+ * @return representation of the option as a struct TALER_EXCHANGE_AmlTransfersKycauthGetOptionValue
+ */
+#define TALER_EXCHANGE_aml_transfers_kycauth_get_option_h_payto_(p) \
+ (const struct TALER_EXCHANGE_AmlTransfersKycauthGetOptionValue) \
+ { \
+ .option = TALER_EXCHANGE_AML_TRANSFERS_KYCAUTH_GET_OPTION_H_PAYTO, \
+ .details.h_payto = (p) \
+ }
+
+
+enum TALER_ErrorCode
+TALER_EXCHANGE_aml_transfers_kycauth_get_set_options_ (
+ struct TALER_EXCHANGE_AmlTransfersKycauthGetHandle *atkgh,
+ unsigned int num_options,
+ struct TALER_EXCHANGE_AmlTransfersKycauthGetOptionValue options[
+ static num_options]);
+
+
+/**
+ * Set the requested options for the operation.
+ *
+ * If any option fail other options may be or may be not applied.
+ *
+ * It should be used with helpers that creates required options, for example:
+ *
+ * TALER_EXCHANGE_aml_transfers_kycauth_get_set_options (
+ * atkgh,
+ * TALER_EXCHANGE_aml_transfers_kycauth_get_option_h_payto_(&h_payto));
+ *
+ * @param atkgh the request to set the options for
+ * @param ... the list of the options, each option must be created
+ * by helpers TALER_EXCHANGE_aml_transfers_kycauth_get_option_NAME(VALUE)
+ * @return ::TALER_EC_NONE on success,
+ * error code otherwise
+ */
+#define TALER_EXCHANGE_aml_transfers_kycauth_get_set_options(atkgh,...) \
+ TALER_EXCHANGE_aml_transfers_kycauth_get_set_options_ ( \
+ atkgh, \
+ ((const struct TALER_EXCHANGE_AmlTransfersKycauthGetOptionValue[]) \
+ {__VA_ARGS__, TALER_EXCHANGE_aml_transfers_kycauth_get_option_end_ () \
+ } \
+ ), \
+ TALER_EXCHANGE_COMMON_OPTIONS_ARRAY_MAX_SIZE)
+
+
+/**
+ * Entry in the set of transfers that are returned
+ * by the server in a single request.
+ */
+struct TALER_EXCHANGE_AmlTransfersKycauthGetTransferEntry
+{
+ /**
+ * Row ID of the record. Used to filter by offset.
+ */
+ uint64_t rowid;
+
+ /**
+ * payto://-URI of the other account.
+ */
+ const char *payto_uri;
+
+ /**
+ * The amount involved.
+ */
+ struct TALER_Amount amount;
+
+ /**
+ * Time when the transfer was made.
+ */
+ struct GNUNET_TIME_Timestamp execution_time;
+};
+
+/**
+ * Information returned from the exchange for a
+ * GET /aml/$OFFICER_PUB/transfers-kycauth request.
+ */
+struct TALER_EXCHANGE_AmlTransfersKycauthGetResult
+{
+ /**
+ * HTTP response data
+ */
+ struct TALER_EXCHANGE_HttpResponse hr;
+
+ /**
+ * Details depending on the HTTP status code.
+ */
+ union
+ {
+
+ /**
+ * Details on #MHD_HTTP_OK.
+ */
+ struct
+ {
+ /**
+ * Length of the @e transfers array.
+ */
+ size_t transfers_length;
+
+ /**
+ * Matching transactions of the exchange.
+ */
+ const struct TALER_EXCHANGE_AmlTransfersKycauthGetTransferEntry *
+ transfers;
+
+ } ok;
+
+ } details;
+};
+
+
+#ifndef TALER_EXCHANGE__AML_TRANSFERS_KYCAUTH_GET_RESULT_CLOSURE
+/**
+ * Type of the closure used by
+ * the #TALER_EXCHANGE_AmlTransfersKycauthGetCallback.
+ */
+#define TALER_EXCHANGE__AML_TRANSFERS_KYCAUTH_GET_RESULT_CLOSURE void
+#endif
+
+/**
+ * Type of the function that receives the result of a
+ * GET /aml/$OFFICER_PUB/transfers-kycauth request.
+ *
+ * @param cls closure
+ * @param result result returned by the HTTP server
+ */
+typedef void
+(*TALER_EXCHANGE_AmlTransfersKycauthGetCallback)(
+ TALER_EXCHANGE__AML_TRANSFERS_KYCAUTH_GET_RESULT_CLOSURE *cls,
+ const struct TALER_EXCHANGE_AmlTransfersKycauthGetResult *result);
+
+
+/**
+ * Start GET /aml/$OPUB/transfers-kycauth operation.
+ *
+ * @param[in,out] atkgh operation to start
+ * @param cb function to call with the exchange's result
+ * @param cb_cls closure for @a cb
+ */
+void
+TALER_EXCHANGE_aml_transfers_kycauth_get_start (
+ struct TALER_EXCHANGE_AmlTransfersKycauthGetHandle *atkgh,
+ TALER_EXCHANGE_AmlTransfersKycauthGetCallback cb,
+ TALER_EXCHANGE__AML_TRANSFERS_KYCAUTH_GET_RESULT_CLOSURE *cb_cls);
+
+
+/**
+ * Cancel GET /aml/$OPUB/transfers-kycauth operation.
+ *
+ * @param[in] atkgh operation to cancel
+ */
+void
+TALER_EXCHANGE_aml_transfers_kycauth_get_cancel (
+ struct TALER_EXCHANGE_AmlTransfersKycauthGetHandle *atkgh);
+
+
+#endif
diff --git a/src/include/taler-exchange/common.h b/src/include/taler-exchange/common.h
@@ -32,6 +32,13 @@
/**
+ * Maximum number of options that can be set in one set_options
+ * call. Used as a dummy for "infinite" in the varargs case.
+ */
+#define TALER_EXCHANGE_COMMON_OPTIONS_ARRAY_MAX_SIZE SIZE_MAX
+
+
+/**
* General information about the HTTP response we obtained
* from the exchange for a request.
*/
diff --git a/src/include/taler-exchange/reserves_get.h b/src/include/taler-exchange/reserves_get.h
@@ -0,0 +1,476 @@
+/*
+ This file is part of TALER
+ Copyright (C) 2025 Taler Systems SA
+
+ TALER is free software; you can redistribute it and/or modify it under the
+ terms of the GNU Affero General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ TALER is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License along with
+ TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
+ */
+/**
+ * @file include/taler-exchange/reserves_get.h
+ * @brief C interface for the GET /reserves/$RESERVE_PUB endpoint
+ * @author Christian Grothoff
+ */
+#ifndef _TALER_EXCHANGE__RESERVES_GET_H
+#define _TALER_EXCHANGE__RESERVES_GET_H
+
+#include <taler-exchange/common.h>
+
+
+/**
+ * Ways how a reserve's balance may change.
+ */
+enum TALER_EXCHANGE_ReserveTransactionType
+{
+
+ /**
+ * Deposit into the reserve.
+ */
+ TALER_EXCHANGE_RTT_CREDIT,
+
+ /**
+ * Withdrawal from the reserve.
+ */
+ TALER_EXCHANGE_RTT_WITHDRAWAL,
+
+ /**
+ * /recoup operation.
+ */
+ TALER_EXCHANGE_RTT_RECOUP,
+
+ /**
+ * Reserve closed operation.
+ */
+ TALER_EXCHANGE_RTT_CLOSING,
+
+ /**
+ * Reserve purse merge operation.
+ */
+ TALER_EXCHANGE_RTT_MERGE,
+
+ /**
+ * Reserve open request operation.
+ */
+ TALER_EXCHANGE_RTT_OPEN,
+
+ /**
+ * Reserve close request operation.
+ */
+ TALER_EXCHANGE_RTT_CLOSE
+
+};
+
+
+/**
+ * @brief Entry in the reserve's transaction history.
+ */
+struct TALER_EXCHANGE_ReserveHistoryEntry
+{
+
+ /**
+ * Type of the transaction.
+ */
+ enum TALER_EXCHANGE_ReserveTransactionType type;
+
+ /**
+ * Amount transferred (in or out).
+ */
+ struct TALER_Amount amount;
+
+ /**
+ * Details depending on @e type.
+ */
+ union
+ {
+
+ /**
+ * Information about a deposit that filled this reserve.
+ * @e type is #TALER_EXCHANGE_RTT_CREDIT.
+ */
+ struct
+ {
+ /**
+ * Sender account payto://-URL of the incoming transfer.
+ */
+ struct TALER_FullPayto sender_url;
+
+ /**
+ * Information that uniquely identifies the wire transfer.
+ */
+ uint64_t wire_reference;
+
+ /**
+ * When did the wire transfer happen?
+ */
+ struct GNUNET_TIME_Timestamp timestamp;
+
+ } in_details;
+
+ /**
+ * Information about withdraw operation with age-restriction.
+ * @e type is #TALER_EXCHANGE_RTT_WITHDRAWAL.
+ */
+ struct
+ {
+ /**
+ * Signature authorizing the withdrawal for outgoing transaction.
+ */
+ json_t *out_authorization_sig;
+
+ /**
+ * The running hash over all hashes of blinded planchets of the withrdawal
+ */
+ struct TALER_HashBlindedPlanchetsP planchets_h;
+
+ /**
+ * If age restriction was required during the protocol
+ */
+ bool age_restricted;
+
+ /**
+ * Maximum age committed, if age_restricted is true
+ */
+ uint8_t max_age;
+
+ /**
+ * If @e age_restricted is true, the index that is not to be revealed
+ * after the initial commitment in /withdraw
+ */
+ uint8_t noreveal_index;
+
+ /**
+ * If @e age_restricted is true, the hash of the selected blinded planchets
+ */
+ struct TALER_HashBlindedPlanchetsP selected_h;
+
+ /**
+ * True, if no blinding_seed was provided. The value of
+ * @e blinding_seed is then zero.
+ */
+ bool no_blinding_seed;
+
+ /**
+ * In case of denominations of cipher type Clause-Schnorr, the
+ * seed for the prior call to /blinding-prepare
+ */
+ struct TALER_BlindingMasterSeedP blinding_seed;
+
+ /**
+ * Fee that was charged for the withdrawal.
+ */
+ struct TALER_Amount fee;
+
+ /**
+ * Number of coins withdrawn
+ */
+ uint16_t num_coins;
+
+ } withdraw;
+
+ /**
+ * Information provided if the reserve was filled via /recoup.
+ * @e type is #TALER_EXCHANGE_RTT_RECOUP.
+ */
+ struct
+ {
+
+ /**
+ * Public key of the coin that was paid back.
+ */
+ struct TALER_CoinSpendPublicKeyP coin_pub;
+
+ /**
+ * Signature of the coin of type
+ * #TALER_SIGNATURE_EXCHANGE_CONFIRM_RECOUP.
+ */
+ struct TALER_ExchangeSignatureP exchange_sig;
+
+ /**
+ * Public key of the exchange that was used for @e exchange_sig.
+ */
+ struct TALER_ExchangePublicKeyP exchange_pub;
+
+ /**
+ * When did the /recoup operation happen?
+ */
+ struct GNUNET_TIME_Timestamp timestamp;
+
+ } recoup_details;
+
+ /**
+ * Information about a close operation of the reserve.
+ * @e type is #TALER_EXCHANGE_RTT_CLOSE.
+ */
+ struct
+ {
+ /**
+ * Receiver account information for the outgoing wire transfer as a payto://-URI.
+ */
+ struct TALER_FullPayto receiver_account_details;
+
+ /**
+ * Wire transfer details for the outgoing wire transfer.
+ */
+ struct TALER_WireTransferIdentifierRawP wtid;
+
+ /**
+ * Signature of the coin of type
+ * #TALER_SIGNATURE_EXCHANGE_RESERVE_CLOSED.
+ */
+ struct TALER_ExchangeSignatureP exchange_sig;
+
+ /**
+ * Public key of the exchange that was used for @e exchange_sig.
+ */
+ struct TALER_ExchangePublicKeyP exchange_pub;
+
+ /**
+ * When did the wire transfer happen?
+ */
+ struct GNUNET_TIME_Timestamp timestamp;
+
+ /**
+ * Fee that was charged for the closing.
+ */
+ struct TALER_Amount fee;
+
+ } close_details;
+
+ /**
+ * Information about a merge operation on the reserve.
+ * @e type is #TALER_EXCHANGE_RTT_MERGE.
+ */
+ struct
+ {
+
+ /**
+ * Fee paid for the purse.
+ */
+ struct TALER_Amount purse_fee;
+
+ /**
+ * Hash over the contract.
+ */
+ struct TALER_PrivateContractHashP h_contract_terms;
+
+ /**
+ * Merge capability key.
+ */
+ struct TALER_PurseMergePublicKeyP merge_pub;
+
+ /**
+ * Purse public key.
+ */
+ struct TALER_PurseContractPublicKeyP purse_pub;
+
+ /**
+ * Signature by the reserve approving the merge.
+ */
+ struct TALER_ReserveSignatureP reserve_sig;
+
+ /**
+ * When was the merge made.
+ */
+ struct GNUNET_TIME_Timestamp merge_timestamp;
+
+ /**
+ * When was the purse set to expire.
+ */
+ struct GNUNET_TIME_Timestamp purse_expiration;
+
+ /**
+ * Minimum age required for depositing into the purse.
+ */
+ uint32_t min_age;
+
+ /**
+ * Flags of the purse.
+ */
+ enum TALER_WalletAccountMergeFlags flags;
+
+ /**
+ * True if the purse was actually merged, false
+ * if only the @e purse_fee was charged.
+ */
+ bool merged;
+
+ } merge_details;
+
+ /**
+ * Information about an open request operation on the reserve.
+ * @e type is #TALER_EXCHANGE_RTT_OPEN.
+ */
+ struct
+ {
+
+ /**
+ * Signature by the reserve approving the open.
+ */
+ struct TALER_ReserveSignatureP reserve_sig;
+
+ /**
+ * Amount to be paid from the reserve balance to open
+ * the reserve.
+ */
+ struct TALER_Amount reserve_payment;
+
+ /**
+ * When was the request created.
+ */
+ struct GNUNET_TIME_Timestamp request_timestamp;
+
+ /**
+ * For how long should the reserve be kept open.
+ * (Determines amount to be paid.)
+ */
+ struct GNUNET_TIME_Timestamp reserve_expiration;
+
+ /**
+ * How many open purses should be included with the
+ * open reserve?
+ * (Determines amount to be paid.)
+ */
+ uint32_t purse_limit;
+
+ } open_request;
+
+ /**
+ * Information about an close request operation on the reserve.
+ * @e type is #TALER_EXCHANGE_RTT_CLOSE.
+ */
+ struct
+ {
+
+ /**
+ * Signature by the reserve approving the close.
+ */
+ struct TALER_ReserveSignatureP reserve_sig;
+
+ /**
+ * When was the request created.
+ */
+ struct GNUNET_TIME_Timestamp request_timestamp;
+
+ /**
+ * Hash of the payto://-URI of the target account
+ * for the closure, or all zeros for the reserve
+ * origin account.
+ */
+ struct TALER_FullPaytoHashP target_account_h_payto;
+
+ } close_request;
+
+
+ } details;
+
+};
+
+
+/**
+ * @brief A /reserves/ GET Handle
+ */
+struct TALER_EXCHANGE_ReservesGetHandle;
+
+
+/**
+ * @brief Reserve summary.
+ */
+struct TALER_EXCHANGE_ReserveSummary
+{
+
+ /**
+ * High-level HTTP response details.
+ */
+ struct TALER_EXCHANGE_HttpResponse hr;
+
+ /**
+ * Details depending on @e hr.http_status.
+ */
+ union
+ {
+
+ /**
+ * Information returned on success, if
+ * @e hr.http_status is #MHD_HTTP_OK
+ */
+ struct
+ {
+
+ /**
+ * Reserve balance.
+ */
+ struct TALER_Amount balance;
+
+ /**
+ * payto://-URI of the last bank account that wired funds
+ * to the reserve, NULL for none (can happen if reserve
+ * was funded via P2P merge).
+ */
+ struct TALER_FullPayto last_origin;
+ } ok;
+
+ } details;
+
+};
+
+
+/**
+ * Callbacks of this type are used to serve the result of submitting a
+ * reserve status request to a exchange.
+ *
+ * @param cls closure
+ * @param rs HTTP response data
+ */
+typedef void
+(*TALER_EXCHANGE_ReservesGetCallback) (
+ void *cls,
+ const struct TALER_EXCHANGE_ReserveSummary *rs);
+
+
+/**
+ * Submit a request to obtain the transaction history of a reserve
+ * from the exchange. Note that while we return the full response to the
+ * caller for further processing, we do already verify that the
+ * response is well-formed (i.e. that signatures included in the
+ * response are all valid and add up to the balance). If the exchange's
+ * reply is not well-formed, we return an HTTP status code of zero to
+ * @a cb.
+ *
+ * @param ctx curl context
+ * @param url exchange base URL
+ * @param reserve_pub public key of the reserve to inspect
+ * @param timeout how long to wait for an affirmative reply
+ * (enables long polling if the reserve does not yet exist)
+ * @param cb the callback to call when a reply for this request is available
+ * @param cb_cls closure for the above callback
+ * @return a handle for this request; NULL if the inputs are invalid (i.e.
+ * signatures fail to verify). In this case, the callback is not called.
+ */
+struct TALER_EXCHANGE_ReservesGetHandle *
+TALER_EXCHANGE_reserves_get (
+ struct GNUNET_CURL_Context *ctx,
+ const char *url,
+ const struct TALER_ReservePublicKeyP *reserve_pub,
+ struct GNUNET_TIME_Relative timeout,
+ TALER_EXCHANGE_ReservesGetCallback cb,
+ void *cb_cls);
+
+
+/**
+ * Cancel a reserve GET request. This function cannot be used
+ * on a request handle if a response is already served for it.
+ *
+ * @param rgh the reserve request handle
+ */
+void
+TALER_EXCHANGE_reserves_get_cancel (
+ struct TALER_EXCHANGE_ReservesGetHandle *rgh);
+
+#endif
diff --git a/src/include/taler_exchange_service.h b/src/include/taler_exchange_service.h
@@ -27,6 +27,7 @@
#include <taler-exchange/common.h>
#include <taler-exchange/aml_legitimizations_get.h>
+#include <taler-exchange/reserves_get.h>
/**
* Version of the Taler Exchange API, in hex.
@@ -1896,457 +1897,7 @@ TALER_EXCHANGE_coins_history_cancel (
struct TALER_EXCHANGE_CoinsHistoryHandle *rsh);
-/* ********************* GET /reserves/$RESERVE_PUB *********************** */
-
-/**
- * Ways how a reserve's balance may change.
- */
-enum TALER_EXCHANGE_ReserveTransactionType
-{
-
- /**
- * Deposit into the reserve.
- */
- TALER_EXCHANGE_RTT_CREDIT,
-
- /**
- * Withdrawal from the reserve.
- */
- TALER_EXCHANGE_RTT_WITHDRAWAL,
-
- /**
- * /recoup operation.
- */
- TALER_EXCHANGE_RTT_RECOUP,
-
- /**
- * Reserve closed operation.
- */
- TALER_EXCHANGE_RTT_CLOSING,
-
- /**
- * Reserve purse merge operation.
- */
- TALER_EXCHANGE_RTT_MERGE,
-
- /**
- * Reserve open request operation.
- */
- TALER_EXCHANGE_RTT_OPEN,
-
- /**
- * Reserve close request operation.
- */
- TALER_EXCHANGE_RTT_CLOSE
-
-};
-
-
-/**
- * @brief Entry in the reserve's transaction history.
- */
-struct TALER_EXCHANGE_ReserveHistoryEntry
-{
-
- /**
- * Type of the transaction.
- */
- enum TALER_EXCHANGE_ReserveTransactionType type;
-
- /**
- * Amount transferred (in or out).
- */
- struct TALER_Amount amount;
-
- /**
- * Details depending on @e type.
- */
- union
- {
-
- /**
- * Information about a deposit that filled this reserve.
- * @e type is #TALER_EXCHANGE_RTT_CREDIT.
- */
- struct
- {
- /**
- * Sender account payto://-URL of the incoming transfer.
- */
- struct TALER_FullPayto sender_url;
-
- /**
- * Information that uniquely identifies the wire transfer.
- */
- uint64_t wire_reference;
-
- /**
- * When did the wire transfer happen?
- */
- struct GNUNET_TIME_Timestamp timestamp;
-
- } in_details;
-
- /**
- * Information about withdraw operation with age-restriction.
- * @e type is #TALER_EXCHANGE_RTT_WITHDRAWAL.
- */
- struct
- {
- /**
- * Signature authorizing the withdrawal for outgoing transaction.
- */
- json_t *out_authorization_sig;
-
- /**
- * The running hash over all hashes of blinded planchets of the withrdawal
- */
- struct TALER_HashBlindedPlanchetsP planchets_h;
-
- /**
- * If age restriction was required during the protocol
- */
- bool age_restricted;
-
- /**
- * Maximum age committed, if age_restricted is true
- */
- uint8_t max_age;
-
- /**
- * If @e age_restricted is true, the index that is not to be revealed
- * after the initial commitment in /withdraw
- */
- uint8_t noreveal_index;
-
- /**
- * If @e age_restricted is true, the hash of the selected blinded planchets
- */
- struct TALER_HashBlindedPlanchetsP selected_h;
-
- /**
- * True, if no blinding_seed was provided. The value of
- * @e blinding_seed is then zero.
- */
- bool no_blinding_seed;
-
- /**
- * In case of denominations of cipher type Clause-Schnorr, the
- * seed for the prior call to /blinding-prepare
- */
- struct TALER_BlindingMasterSeedP blinding_seed;
-
- /**
- * Fee that was charged for the withdrawal.
- */
- struct TALER_Amount fee;
-
- /**
- * Number of coins withdrawn
- */
- uint16_t num_coins;
-
- } withdraw;
-
- /**
- * Information provided if the reserve was filled via /recoup.
- * @e type is #TALER_EXCHANGE_RTT_RECOUP.
- */
- struct
- {
-
- /**
- * Public key of the coin that was paid back.
- */
- struct TALER_CoinSpendPublicKeyP coin_pub;
-
- /**
- * Signature of the coin of type
- * #TALER_SIGNATURE_EXCHANGE_CONFIRM_RECOUP.
- */
- struct TALER_ExchangeSignatureP exchange_sig;
-
- /**
- * Public key of the exchange that was used for @e exchange_sig.
- */
- struct TALER_ExchangePublicKeyP exchange_pub;
-
- /**
- * When did the /recoup operation happen?
- */
- struct GNUNET_TIME_Timestamp timestamp;
-
- } recoup_details;
-
- /**
- * Information about a close operation of the reserve.
- * @e type is #TALER_EXCHANGE_RTT_CLOSE.
- */
- struct
- {
- /**
- * Receiver account information for the outgoing wire transfer as a payto://-URI.
- */
- struct TALER_FullPayto receiver_account_details;
-
- /**
- * Wire transfer details for the outgoing wire transfer.
- */
- struct TALER_WireTransferIdentifierRawP wtid;
-
- /**
- * Signature of the coin of type
- * #TALER_SIGNATURE_EXCHANGE_RESERVE_CLOSED.
- */
- struct TALER_ExchangeSignatureP exchange_sig;
-
- /**
- * Public key of the exchange that was used for @e exchange_sig.
- */
- struct TALER_ExchangePublicKeyP exchange_pub;
-
- /**
- * When did the wire transfer happen?
- */
- struct GNUNET_TIME_Timestamp timestamp;
-
- /**
- * Fee that was charged for the closing.
- */
- struct TALER_Amount fee;
-
- } close_details;
-
- /**
- * Information about a merge operation on the reserve.
- * @e type is #TALER_EXCHANGE_RTT_MERGE.
- */
- struct
- {
-
- /**
- * Fee paid for the purse.
- */
- struct TALER_Amount purse_fee;
-
- /**
- * Hash over the contract.
- */
- struct TALER_PrivateContractHashP h_contract_terms;
-
- /**
- * Merge capability key.
- */
- struct TALER_PurseMergePublicKeyP merge_pub;
-
- /**
- * Purse public key.
- */
- struct TALER_PurseContractPublicKeyP purse_pub;
-
- /**
- * Signature by the reserve approving the merge.
- */
- struct TALER_ReserveSignatureP reserve_sig;
-
- /**
- * When was the merge made.
- */
- struct GNUNET_TIME_Timestamp merge_timestamp;
-
- /**
- * When was the purse set to expire.
- */
- struct GNUNET_TIME_Timestamp purse_expiration;
-
- /**
- * Minimum age required for depositing into the purse.
- */
- uint32_t min_age;
-
- /**
- * Flags of the purse.
- */
- enum TALER_WalletAccountMergeFlags flags;
-
- /**
- * True if the purse was actually merged, false
- * if only the @e purse_fee was charged.
- */
- bool merged;
-
- } merge_details;
-
- /**
- * Information about an open request operation on the reserve.
- * @e type is #TALER_EXCHANGE_RTT_OPEN.
- */
- struct
- {
-
- /**
- * Signature by the reserve approving the open.
- */
- struct TALER_ReserveSignatureP reserve_sig;
-
- /**
- * Amount to be paid from the reserve balance to open
- * the reserve.
- */
- struct TALER_Amount reserve_payment;
-
- /**
- * When was the request created.
- */
- struct GNUNET_TIME_Timestamp request_timestamp;
-
- /**
- * For how long should the reserve be kept open.
- * (Determines amount to be paid.)
- */
- struct GNUNET_TIME_Timestamp reserve_expiration;
-
- /**
- * How many open purses should be included with the
- * open reserve?
- * (Determines amount to be paid.)
- */
- uint32_t purse_limit;
-
- } open_request;
-
- /**
- * Information about an close request operation on the reserve.
- * @e type is #TALER_EXCHANGE_RTT_CLOSE.
- */
- struct
- {
-
- /**
- * Signature by the reserve approving the close.
- */
- struct TALER_ReserveSignatureP reserve_sig;
-
- /**
- * When was the request created.
- */
- struct GNUNET_TIME_Timestamp request_timestamp;
-
- /**
- * Hash of the payto://-URI of the target account
- * for the closure, or all zeros for the reserve
- * origin account.
- */
- struct TALER_FullPaytoHashP target_account_h_payto;
-
- } close_request;
-
-
- } details;
-
-};
-
-
-/**
- * @brief A /reserves/ GET Handle
- */
-struct TALER_EXCHANGE_ReservesGetHandle;
-
-
-/**
- * @brief Reserve summary.
- */
-struct TALER_EXCHANGE_ReserveSummary
-{
-
- /**
- * High-level HTTP response details.
- */
- struct TALER_EXCHANGE_HttpResponse hr;
-
- /**
- * Details depending on @e hr.http_status.
- */
- union
- {
-
- /**
- * Information returned on success, if
- * @e hr.http_status is #MHD_HTTP_OK
- */
- struct
- {
-
- /**
- * Reserve balance.
- */
- struct TALER_Amount balance;
-
- /**
- * payto://-URI of the last bank account that wired funds
- * to the reserve, NULL for none (can happen if reserve
- * was funded via P2P merge).
- */
- struct TALER_FullPayto last_origin;
- } ok;
-
- } details;
-
-};
-
-
-/**
- * Callbacks of this type are used to serve the result of submitting a
- * reserve status request to a exchange.
- *
- * @param cls closure
- * @param rs HTTP response data
- */
-typedef void
-(*TALER_EXCHANGE_ReservesGetCallback) (
- void *cls,
- const struct TALER_EXCHANGE_ReserveSummary *rs);
-
-
-/**
- * Submit a request to obtain the transaction history of a reserve
- * from the exchange. Note that while we return the full response to the
- * caller for further processing, we do already verify that the
- * response is well-formed (i.e. that signatures included in the
- * response are all valid and add up to the balance). If the exchange's
- * reply is not well-formed, we return an HTTP status code of zero to
- * @a cb.
- *
- * @param ctx curl context
- * @param url exchange base URL
- * @param reserve_pub public key of the reserve to inspect
- * @param timeout how long to wait for an affirmative reply
- * (enables long polling if the reserve does not yet exist)
- * @param cb the callback to call when a reply for this request is available
- * @param cb_cls closure for the above callback
- * @return a handle for this request; NULL if the inputs are invalid (i.e.
- * signatures fail to verify). In this case, the callback is not called.
- */
-struct TALER_EXCHANGE_ReservesGetHandle *
-TALER_EXCHANGE_reserves_get (
- struct GNUNET_CURL_Context *ctx,
- const char *url,
- const struct TALER_ReservePublicKeyP *reserve_pub,
- struct GNUNET_TIME_Relative timeout,
- TALER_EXCHANGE_ReservesGetCallback cb,
- void *cb_cls);
-
-
-/**
- * Cancel a reserve GET request. This function cannot be used
- * on a request handle if a response is already served for it.
- *
- * @param rgh the reserve request handle
- */
-void
-TALER_EXCHANGE_reserves_get_cancel (
- struct TALER_EXCHANGE_ReservesGetHandle *rgh);
-
+/* ********************* GET /reserves/$RESERVE_PUB/history *********************** */
/**
* @brief A /reserves/$RID/history Handle
diff --git a/src/lib/Makefile.am b/src/lib/Makefile.am
@@ -22,6 +22,7 @@ libtalerexchange_la_LDFLAGS = \
-no-undefined
libtalerexchange_la_SOURCES = \
exchange_api_add_aml_decision.c \
+ exchange_api_aml_legitimizations_get.c \
exchange_api_auditor_add_denomination.c \
exchange_api_batch_deposit.c \
exchange_api_blinding_prepare.c \
diff --git a/src/lib/exchange_api_aml_legitimizations_get.c b/src/lib/exchange_api_aml_legitimizations_get.c
@@ -0,0 +1,501 @@
+/*
+ This file is part of TALER
+ Copyright (C) 2025 Taler Systems SA
+
+ TALER is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ TALER is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ TALER; see the file COPYING. If not, see
+ <http://www.gnu.org/licenses/>
+*/
+/**
+ * @file lib/exchange_api_aml_legitimizations_get.c
+ * @brief Implementation of the GET /aml/$OFFICER_PUB/legitimizations requests
+ * @author Christian Grothoff
+ */
+#include "platform.h"
+#include <jansson.h>
+#include <microhttpd.h> /* just for HTTP status codes */
+#include <gnunet/gnunet_util_lib.h>
+#include <gnunet/gnunet_json_lib.h>
+#include <gnunet/gnunet_curl_lib.h>
+#include "taler_exchange_service.h"
+#include "taler_json_lib.h"
+#include "exchange_api_handle.h"
+#include "taler_signatures.h"
+#include "exchange_api_curl_defaults.h"
+
+
+/**
+ * Handle for an operation to GET /aml/$OFFICER_PUB/legitimizations.
+ */
+struct TALER_EXCHANGE_AmlLegitimizationsGetHandle
+{
+
+ /**
+ * The exchange base URL for this request.
+ */
+ char *exchange_base_url;
+
+ /**
+ * Our execution context.
+ */
+ struct GNUNET_CURL_Context *ctx;
+
+ /**
+ * Handle for the request.
+ */
+ struct GNUNET_CURL_Job *job;
+
+ /**
+ * Signature of the AML officer.
+ */
+ struct TALER_AmlOfficerSignatureP officer_sig;
+
+ /**
+ * Public key of the AML officer.
+ */
+ struct TALER_AmlOfficerPublicKeyP officer_pub;
+
+ /**
+ * Function to call with the result.
+ */
+ TALER_EXCHANGE_AmlLegitimizationsGetCallback cb;
+
+ /**
+ * Closure for @a cb.
+ */
+ TALER_EXCHANGE__AML_LEGITIMIZATIONS_GET_RESULT_CLOSURE *cb_cls;
+
+ /**
+ * The url for this request.
+ */
+ char *url;
+
+ /**
+ * HTTP headers for the job.
+ */
+ struct curl_slist *job_headers;
+
+ /**
+ * Request options.
+ */
+ struct
+ {
+ /**
+ * Limit on number of results.
+ */
+ int64_t limit;
+
+ /**
+ * Row offset from which to return results.
+ */
+ uint64_t offset;
+
+ /**
+ * Hash of payto URI to filter by, NULL for no filter.
+ */
+ const struct TALER_NormalizedPaytoHashP *h_payto;
+
+ /**
+ * Activity filter.
+ */
+ enum TALER_EXCHANGE_YesNoAll active;
+
+ } options;
+
+};
+
+
+/**
+ * Parse a single measure details entry from JSON.
+ *
+ * @param md_json JSON object to parse
+ * @param[out] md where to store the result
+ * @return #GNUNET_OK on success
+ */
+static enum GNUNET_GenericReturnValue
+parse_measure_details (
+ const json_t *md_json,
+ struct TALER_EXCHANGE_AmlLegitimizationsGetMeasureDetails *md)
+{
+ struct GNUNET_JSON_Specification spec[] = {
+ GNUNET_JSON_spec_fixed_auto ("h_payto",
+ &md->h_payto),
+ GNUNET_JSON_spec_uint64 ("rowid",
+ &md->rowid),
+ GNUNET_JSON_spec_timestamp ("start_time",
+ &md->start_time),
+ GNUNET_JSON_spec_object_const ("measures",
+ &md->measures),
+ GNUNET_JSON_spec_bool ("is_finished",
+ &md->is_finished),
+ GNUNET_JSON_spec_end ()
+ };
+
+ if (GNUNET_OK !=
+ GNUNET_JSON_parse (md_json,
+ spec,
+ NULL,
+ NULL))
+ {
+ GNUNET_break_op (0);
+ return GNUNET_SYSERR;
+ }
+ return GNUNET_OK;
+}
+
+
+/**
+ * We received an #MHD_HTTP_OK status code. Handle the JSON
+ * response.
+ *
+ * @param algh handle of the request
+ * @param j JSON response
+ * @return #GNUNET_OK on success
+ */
+static enum GNUNET_GenericReturnValue
+handle_aml_legitimizations_get_ok (
+ struct TALER_EXCHANGE_AmlLegitimizationsGetHandle *algh,
+ const json_t *j)
+{
+ struct TALER_EXCHANGE_AmlLegitimizationsGetResult result = {
+ .hr.reply = j,
+ .hr.http_status = MHD_HTTP_OK
+ };
+ const json_t *measures_array;
+ struct GNUNET_JSON_Specification spec[] = {
+ GNUNET_JSON_spec_array_const ("measures",
+ &measures_array),
+ GNUNET_JSON_spec_end ()
+ };
+ struct TALER_EXCHANGE_AmlLegitimizationsGetMeasureDetails *measures;
+
+ if (GNUNET_OK !=
+ GNUNET_JSON_parse (j,
+ spec,
+ NULL,
+ NULL))
+ {
+ GNUNET_break_op (0);
+ return GNUNET_SYSERR;
+ }
+
+ result.details.ok.measures_length = json_array_size (measures_array);
+ if (0 == result.details.ok.measures_length)
+ {
+ measures = NULL;
+ }
+ else
+ {
+ measures
+ = GNUNET_new_array (
+ result.details.ok.measures_length,
+ struct TALER_EXCHANGE_AmlLegitimizationsGetMeasureDetails);
+ }
+ for (size_t i = 0; i < result.details.ok.measures_length; i++)
+ {
+ const json_t *measure_json = json_array_get (measures_array,
+ i);
+
+ if (GNUNET_OK !=
+ parse_measure_details (measure_json,
+ &measures[i]))
+ {
+ GNUNET_free (measures);
+ return GNUNET_SYSERR;
+ }
+ }
+ result.details.ok.measures = measures;
+ algh->cb (algh->cb_cls,
+ &result);
+ algh->cb = NULL;
+ GNUNET_free (measures);
+ return GNUNET_OK;
+}
+
+
+/**
+ * Function called when we're done processing the
+ * HTTP /aml/$OFFICER_PUB/legitimizations GET request.
+ *
+ * @param cls the `struct TALER_EXCHANGE_AmlLegitimizationsGetHandle`
+ * @param response_code HTTP response code, 0 on error
+ * @param response parsed JSON result, NULL on error
+ */
+static void
+handle_aml_legitimizations_get_finished (void *cls,
+ long response_code,
+ const void *response)
+{
+ struct TALER_EXCHANGE_AmlLegitimizationsGetHandle *algh = cls;
+ const json_t *j = response;
+ struct TALER_EXCHANGE_AmlLegitimizationsGetResult result = {
+ .hr.reply = j,
+ .hr.http_status = (unsigned int) response_code
+ };
+
+ algh->job = NULL;
+ switch (response_code)
+ {
+ case 0:
+ result.hr.ec = TALER_EC_GENERIC_INVALID_RESPONSE;
+ break;
+ case MHD_HTTP_OK:
+ if (GNUNET_OK !=
+ handle_aml_legitimizations_get_ok (algh,
+ j))
+ {
+ result.hr.http_status = 0;
+ result.hr.ec = TALER_EC_GENERIC_REPLY_MALFORMED;
+ }
+ break;
+ case MHD_HTTP_BAD_REQUEST:
+ /* This should never happen, either us or the exchange is buggy
+ (or API version conflict); just pass JSON reply to the application */
+ result.hr.ec = TALER_JSON_get_error_code (j);
+ result.hr.hint = TALER_JSON_get_error_hint (j);
+ break;
+ case MHD_HTTP_UNAUTHORIZED:
+ /* Invalid officer credentials */
+ result.hr.ec = TALER_JSON_get_error_code (j);
+ result.hr.hint = TALER_JSON_get_error_hint (j);
+ break;
+ case MHD_HTTP_FORBIDDEN:
+ /* Officer not authorized for this operation */
+ result.hr.ec = TALER_JSON_get_error_code (j);
+ result.hr.hint = TALER_JSON_get_error_hint (j);
+ break;
+ case MHD_HTTP_NOT_FOUND:
+ /* Officer not found */
+ result.hr.ec = TALER_JSON_get_error_code (j);
+ result.hr.hint = TALER_JSON_get_error_hint (j);
+ break;
+ case MHD_HTTP_INTERNAL_SERVER_ERROR:
+ /* Server had an internal issue; we should retry, but this API
+ leaves this to the application */
+ result.hr.ec = TALER_JSON_get_error_code (j);
+ result.hr.hint = TALER_JSON_get_error_hint (j);
+ break;
+ default:
+ /* unexpected response code */
+ GNUNET_break_op (0);
+ result.hr.ec = TALER_JSON_get_error_code (j);
+ result.hr.hint = TALER_JSON_get_error_hint (j);
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Unexpected response code %u/%d for GET %s\n",
+ (unsigned int) response_code,
+ (int) result.hr.ec,
+ algh->url);
+ break;
+ }
+ if (NULL != algh->cb)
+ {
+ algh->cb (algh->cb_cls,
+ &result);
+ algh->cb = NULL;
+ }
+ TALER_EXCHANGE_aml_legitimizations_get_cancel (algh);
+}
+
+
+struct TALER_EXCHANGE_AmlLegitimizationsGetHandle *
+TALER_EXCHANGE_aml_legitimizations_get_create (
+ struct GNUNET_CURL_Context *ctx,
+ const char *exchange_base_url,
+ const struct TALER_AmlOfficerPrivateKeyP *officer_priv)
+{
+ struct TALER_EXCHANGE_AmlLegitimizationsGetHandle *algh;
+
+ algh = GNUNET_new (struct TALER_EXCHANGE_AmlLegitimizationsGetHandle);
+ algh->ctx = ctx;
+ algh->exchange_base_url = GNUNET_strdup (exchange_base_url);
+ GNUNET_CRYPTO_eddsa_key_get_public (&officer_priv->eddsa_priv,
+ &algh->officer_pub.eddsa_pub);
+ TALER_officer_aml_query_sign (officer_priv,
+ &algh->officer_sig);
+ algh->options.limit = -20; /* Default to last 20 entries */
+ algh->options.offset = UINT64_MAX; /* Default to maximum row id */
+ algh->options.active = TALER_EXCHANGE_YNA_ALL; /* Default to all */
+ return algh;
+}
+
+
+enum GNUNET_GenericReturnValue
+TALER_EXCHANGE_aml_legitimizations_get_set_options_ (
+ struct TALER_EXCHANGE_AmlLegitimizationsGetHandle *algh,
+ unsigned int num_options,
+ struct TALER_EXCHANGE_AmlLegitimizationsGetOptionValue options[
+ static num_options])
+{
+ for (unsigned int i = 0; i < num_options; i++)
+ {
+ switch (options[i].option)
+ {
+ case TALER_EXCHANGE_AML_LEGITIMIZATIONS_GET_OPTION_END:
+ return GNUNET_OK;
+ case TALER_EXCHANGE_AML_LEGITIMIZATIONS_GET_OPTION_LIMIT:
+ algh->options.limit = options[i].details.limit;
+ break;
+ case TALER_EXCHANGE_AML_LEGITIMIZATIONS_GET_OPTION_OFFSET:
+ algh->options.offset = options[i].details.offset;
+ break;
+ case TALER_EXCHANGE_AML_LEGITIMIZATIONS_GET_OPTION_H_PAYTO:
+ algh->options.h_payto = options[i].details.h_payto;
+ break;
+ case TALER_EXCHANGE_AML_LEGITIMIZATIONS_GET_OPTION_ACTIVE:
+ algh->options.active = options[i].details.active;
+ break;
+ default:
+ GNUNET_break (0);
+ return GNUNET_NO;
+ }
+ }
+ return GNUNET_OK;
+}
+
+
+enum TALER_EXCHANGE_AmlLegitimizationsGetStartError
+TALER_EXCHANGE_aml_legitimizations_get_start (
+ struct TALER_EXCHANGE_AmlLegitimizationsGetHandle *algh,
+ TALER_EXCHANGE_AmlLegitimizationsGetCallback cb,
+ TALER_EXCHANGE__AML_LEGITIMIZATIONS_GET_RESULT_CLOSURE *cb_cls)
+{
+ char officer_pub_str[sizeof (struct TALER_AmlOfficerPublicKeyP) * 2];
+ char arg_str[sizeof (officer_pub_str) + 64];
+ char limit_str[24];
+ char offset_str[24];
+ char paytoh_str[sizeof (struct TALER_NormalizedPaytoHashP) * 2];
+
+ if (NULL != algh->job)
+ {
+ GNUNET_break (0);
+ return TALER_EXCHANGE_AML_LEGITIMIZATIONS_GET_START_E_AGAIN;
+ }
+ algh->cb = cb;
+ algh->cb_cls = cb_cls;
+ {
+ char *end;
+
+ end = GNUNET_STRINGS_data_to_string (
+ &algh->officer_pub,
+ sizeof (algh->officer_pub),
+ officer_pub_str,
+ sizeof (officer_pub_str));
+ *end = '\0';
+ }
+ if (NULL != algh->options.h_payto)
+ {
+ char *end;
+
+ end = GNUNET_STRINGS_data_to_string (
+ algh->options.h_payto,
+ sizeof (struct TALER_NormalizedPaytoHashP),
+ paytoh_str,
+ sizeof (paytoh_str));
+ *end = '\0';
+ }
+ /* Build query parameters */
+ GNUNET_snprintf (offset_str,
+ sizeof (offset_str),
+ "%llu",
+ (unsigned long long) algh->options.offset);
+ GNUNET_snprintf (limit_str,
+ sizeof (limit_str),
+ "%lld",
+ (long long) algh->options.limit);
+ GNUNET_snprintf (arg_str,
+ sizeof (arg_str),
+ "aml/%s/legitimizations",
+ officer_pub_str);
+ algh->url = TALER_url_join (algh->exchange_base_url,
+ arg_str,
+ "limit",
+ limit_str,
+ "offset",
+ offset_str,
+ "h_payto",
+ NULL == algh->options.h_payto
+ ? NULL
+ : offset_str,
+ "active",
+ TALER_EXCHANGE_YNA_ALL == algh->options.active
+ ? NULL
+ : TALER_yna_to_string (algh->options.active),
+ NULL);
+ if (NULL == algh->url)
+ {
+ GNUNET_break (0);
+ return TALER_EXCHANGE_AML_LEGITIMIZATIONS_GET_START_E_INTERNAL;
+ }
+
+ {
+ CURL *eh;
+
+ eh = TALER_EXCHANGE_curl_easy_get_ (algh->url);
+ if (NULL == eh)
+ {
+ GNUNET_break (0);
+ GNUNET_free (algh->url);
+ algh->url = NULL;
+ return TALER_EXCHANGE_AML_LEGITIMIZATIONS_GET_START_E_INTERNAL;
+ }
+
+ /* Add authentication header for AML officer */
+ {
+ char *hdr;
+ char sig_str[sizeof (algh->officer_sig) * 2];
+ char *end;
+
+ end = GNUNET_STRINGS_data_to_string (
+ &algh->officer_sig,
+ sizeof (algh->officer_sig),
+ sig_str,
+ sizeof (sig_str));
+ *end = '\0';
+ GNUNET_asprintf (&hdr,
+ "%s: %s",
+ TALER_AML_OFFICER_SIGNATURE_HEADER,
+ sig_str);
+ algh->job_headers = curl_slist_append (NULL,
+ hdr);
+ GNUNET_free (hdr);
+ GNUNET_break (CURLE_OK ==
+ curl_easy_setopt (eh,
+ CURLOPT_HTTPHEADER,
+ algh->job_headers));
+ }
+ algh->job
+ = GNUNET_CURL_job_add (
+ algh->ctx,
+ eh,
+ &handle_aml_legitimizations_get_finished,
+ algh);
+ }
+ return TALER_EXCHANGE_AML_LEGITIMIZATIONS_GET_START_OK;
+}
+
+
+void
+TALER_EXCHANGE_aml_legitimizations_get_cancel (
+ struct TALER_EXCHANGE_AmlLegitimizationsGetHandle *algh)
+{
+ if (NULL != algh->job)
+ {
+ GNUNET_CURL_job_cancel (algh->job);
+ algh->job = NULL;
+ }
+ curl_slist_free_all (algh->job_headers);
+ GNUNET_free (algh->exchange_base_url);
+ GNUNET_free (algh->url);
+ GNUNET_free (algh);
+}
+
+
+/* end of exchange_api_aml_legitimizations_get.c */