aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/bank-lib/bank_api_admin.c4
-rw-r--r--src/bank-lib/bank_api_history.c333
-rw-r--r--src/bank-lib/fakebank.c11
-rw-r--r--src/bank-lib/test_bank_interpreter.c2
-rw-r--r--src/bank-lib/testing_api_cmd_history.c209
-rw-r--r--src/include/taler_bank_service.h37
-rw-r--r--src/include/taler_testing_lib.h72
-rw-r--r--src/lib/Makefile.am3
-rw-r--r--src/lib/testing_api_cmd_fakebank_transfer.c30
-rw-r--r--src/lib/testing_api_trait_time.c76
-rw-r--r--src/wire-plugins/plugin_wire_taler-bank.c2
11 files changed, 652 insertions, 127 deletions
diff --git a/src/bank-lib/bank_api_admin.c b/src/bank-lib/bank_api_admin.c
index 3a1ec4efa..8eff229f5 100644
--- a/src/bank-lib/bank_api_admin.c
+++ b/src/bank-lib/bank_api_admin.c
@@ -79,6 +79,7 @@ handle_admin_add_incoming_finished (void *cls,
{
struct TALER_BANK_AdminAddIncomingHandle *aai = cls;
uint64_t row_id = UINT64_MAX;
+ struct GNUNET_TIME_Absolute timestamp;
enum TALER_ErrorCode ec;
const json_t *j = response;
@@ -93,6 +94,8 @@ handle_admin_add_incoming_finished (void *cls,
struct GNUNET_JSON_Specification spec[] = {
GNUNET_JSON_spec_uint64 ("row_id",
&row_id),
+ GNUNET_JSON_spec_absolute_time ("timestamp",
+ &timestamp),
GNUNET_JSON_spec_end()
};
@@ -148,6 +151,7 @@ handle_admin_add_incoming_finished (void *cls,
response_code,
ec,
row_id,
+ timestamp,
j);
TALER_BANK_admin_add_incoming_cancel (aai);
}
diff --git a/src/bank-lib/bank_api_history.c b/src/bank-lib/bank_api_history.c
index ab757a2d2..4b9ea3c3c 100644
--- a/src/bank-lib/bank_api_history.c
+++ b/src/bank-lib/bank_api_history.c
@@ -2,22 +2,26 @@
This file is part of TALER
Copyright (C) 2017 GNUnet e.V. & Inria
- 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/>
+ 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 bank-lib/bank_api_history.c
- * @brief Implementation of the /history requests of the bank's HTTP API
+ * @brief Implementation of the /history[-range]
+ * requests of the bank's HTTP API.
* @author Christian Grothoff
+ * @author Marcello Stanisci
*/
#include "platform.h"
#include "bank_api_common.h"
@@ -60,7 +64,23 @@ struct TALER_BANK_HistoryHandle
* Closure for @a cb.
*/
void *hcb_cls;
+};
+
+
+/**
+ * Represent a URL argument+value pair.
+ */
+struct HistoryArgumentURL
+{
+ /**
+ * Name of the URL argument.
+ */
+ char argument[20];
+ /**
+ * Value of the URL argument.
+ */
+ char value[20];
};
@@ -248,24 +268,202 @@ handle_history_finished (void *cls,
}
+
+/**
+ * Backend of both the /history[-range] requests.
+ *
+ * @param ctx curl context for the event loop
+ * @param bank_base_url base URL of the bank.
+ * @param urlargs path + URL arguments.
+ * @param auth authentication data to use
+ * @param hres_cb the callback to call with the transaction
+ * history
+ * @param hres_cb_cls closure for the above callback
+ * @return NULL if the inputs are invalid (i.e. zero value for
+ * @e num_results). In this case, the callback is not
+ * called.
+ */
+static struct TALER_BANK_HistoryHandle *
+put_history_job (struct GNUNET_CURL_Context *ctx,
+ const char *bank_base_url,
+ const char *urlargs,
+ const struct TALER_BANK_AuthenticationData *auth,
+ TALER_BANK_HistoryResultCallback hres_cb,
+ void *hres_cb_cls)
+{
+ struct TALER_BANK_HistoryHandle *hh;
+ CURL *eh;
+
+ hh = GNUNET_new (struct TALER_BANK_HistoryHandle);
+ hh->hcb = hres_cb;
+ hh->hcb_cls = hres_cb_cls;
+ hh->bank_base_url = GNUNET_strdup (bank_base_url);
+ hh->request_url = TALER_BANK_path_to_url_ (bank_base_url,
+ urlargs);
+
+ hh->authh = TALER_BANK_make_auth_header_ (auth);
+ eh = curl_easy_init ();
+ GNUNET_assert (CURLE_OK ==
+ curl_easy_setopt (eh,
+ CURLOPT_HTTPHEADER,
+ hh->authh));
+ GNUNET_assert (CURLE_OK ==
+ curl_easy_setopt (eh,
+ CURLOPT_URL,
+ hh->request_url));
+ hh->job = GNUNET_CURL_job_add (ctx,
+ eh,
+ GNUNET_NO,
+ &handle_history_finished,
+ hh);
+ return hh;
+}
+
+
+/**
+ * Convert fixed value 'direction' into string.
+ *
+ * @param direction the value to convert.
+ * @return string representation of @a direction. When length
+ * is zero, an error occurred.
+ */
+static struct HistoryArgumentURL
+conv_direction (enum TALER_BANK_Direction direction)
+{
+ struct HistoryArgumentURL ret;
+
+ if (TALER_BANK_DIRECTION_NONE == direction)
+ {
+ /* Should just never happen. */
+ GNUNET_assert (0);
+ return ret;
+ }
+
+ if (TALER_BANK_DIRECTION_BOTH ==
+ (TALER_BANK_DIRECTION_BOTH & direction))
+ strcpy (&ret.value[0],
+ "both");
+ else if (TALER_BANK_DIRECTION_CREDIT ==
+ (TALER_BANK_DIRECTION_CREDIT & direction))
+ strcpy (&ret.value[0],
+ "credit");
+ else if (TALER_BANK_DIRECTION_DEBIT ==
+ (TALER_BANK_DIRECTION_BOTH & direction)) /*why use 'both' flag?*/
+ strcpy (&ret.value[0],
+ "debit");
+ return ret;
+}
+
+
+/**
+ * Convert fixed value 'direction' into string representation
+ * of the "cancel" argument.
+ *
+ * @param direction the value to convert.
+ * @return string representation of @a direction. When length
+ * is zero, an error occurred.
+ */
+static struct HistoryArgumentURL
+conv_cancel (enum TALER_BANK_Direction direction)
+{
+ struct HistoryArgumentURL ret;
+
+ if (TALER_BANK_DIRECTION_CANCEL ==
+ (TALER_BANK_DIRECTION_CANCEL & direction))
+ strcpy (&ret.value[0],
+ "show");
+ else
+ strcpy (&ret.value[0],
+ "omit");
+ return ret;
+}
+
+/**
+ * Request the wire transfer history of a bank account,
+ * using time stamps to narrow the results.
+ *
+ * @param ctx curl context for the event loop
+ * @param bank_base_url URL of the bank (used to execute this
+ * request)
+ * @param auth authentication data to use
+ * @param account_number which account number should we query
+ * @param direction what kinds of wire transfers should be
+ * returned
+ * @param ascending if GNUNET_YES, history elements will
+ * be returned in chronological order.
+ * @param start_date threshold for oldest result.
+ * @param end_date threshold for youngest result.
+ * @param hres_cb the callback to call with the transaction
+ * history
+ * @param hres_cb_cls closure for the above callback
+ * @return NULL if the inputs are invalid (i.e. zero value for
+ * @e num_results). In this case, the callback is not
+ * called.
+ */
+struct TALER_BANK_HistoryHandle *
+TALER_BANK_history_range (struct GNUNET_CURL_Context *ctx,
+ const char *bank_base_url,
+ const struct TALER_BANK_AuthenticationData *auth,
+ uint64_t account_number,
+ enum TALER_BANK_Direction direction,
+ unsigned int ascending,
+ struct GNUNET_TIME_Absolute start_date,
+ struct GNUNET_TIME_Absolute end_date,
+ TALER_BANK_HistoryResultCallback hres_cb,
+ void *hres_cb_cls)
+{
+ struct TALER_BANK_HistoryHandle *hh;
+ char *url;
+
+ GNUNET_TIME_round_abs (&start_date);
+ GNUNET_TIME_round_abs (&end_date);
+
+ GNUNET_asprintf (&url,
+ "/history?auth=basic&account_number=%llu&start=%llu&end=%llu&direction=%s&cancelled=%s&ordering=%s",
+ (unsigned long long) account_number,
+ start_date.abs_value_us / 1000LL / 1000LL,
+ end_date.abs_value_us / 1000LL / 1000LL,
+ conv_direction (direction).value,
+ conv_cancel (direction).value,
+ (GNUNET_YES == ascending) ? "ascending" : "descending");
+
+ hh = put_history_job (ctx,
+ bank_base_url,
+ url,
+ auth,
+ hres_cb,
+ hres_cb_cls);
+
+ GNUNET_free (url);
+ return hh;
+}
+
+
+
/**
* Request the wire transfer history of a bank account.
*
* @param ctx curl context for the event loop
- * @param bank_base_url URL of the bank (used to execute this request)
+ * @param bank_base_url URL of the bank (used to execute this
+ * request)
* @param auth authentication data to use
* @param account_number which account number should we query
- * @param direction what kinds of wire transfers should be returned
- * @param ascending if GNUNET_YES, history elements will be returned in chronological order.
- * @param start_row from which row on do we want to get results, use UINT64_MAX for the latest; exclusive
- * @param num_results how many results do we want; negative numbers to go into the past,
- * positive numbers to go into the future starting at @a start_row;
- * must not be zero.
- * @param hres_cb the callback to call with the transaction history
+ * @param direction what kinds of wire transfers should be
+ * returned
+ * @param ascending if GNUNET_YES, history elements will
+ * be returned in chronological order.
+ * @param start_row from which row on do we want to get results,
+ * use UINT64_MAX for the latest; exclusive
+ * @param num_results how many results do we want;
+ * negative numbers to go into the past, positive numbers
+ * to go into the future starting at @a start_row;
+ * must not be zero.
+ * @param hres_cb the callback to call with the transaction
+ * history
* @param hres_cb_cls closure for the above callback
- * @return NULL
- * if the inputs are invalid (i.e. zero value for @e num_results).
- * In this case, the callback is not called.
+ * @return NULL if the inputs are invalid (i.e. zero value for
+ * @e num_results). In this case, the callback is not
+ * called.
*/
struct TALER_BANK_HistoryHandle *
TALER_BANK_history (struct GNUNET_CURL_Context *ctx,
@@ -280,91 +478,44 @@ TALER_BANK_history (struct GNUNET_CURL_Context *ctx,
void *hres_cb_cls)
{
struct TALER_BANK_HistoryHandle *hh;
- CURL *eh;
char *url;
- const char *dir;
- const char *can;
if (0 == num_results)
{
GNUNET_break (0);
return NULL;
}
- if (TALER_BANK_DIRECTION_NONE == direction)
- {
- GNUNET_break (0);
- return NULL;
- }
-
- dir = NULL;
- if (TALER_BANK_DIRECTION_BOTH == (TALER_BANK_DIRECTION_BOTH & direction))
- dir = "both";
- else if (TALER_BANK_DIRECTION_CREDIT == (TALER_BANK_DIRECTION_CREDIT & direction))
- dir = "credit";
- else if (TALER_BANK_DIRECTION_DEBIT == (TALER_BANK_DIRECTION_BOTH & direction))
- dir = "debit";
- if (NULL == dir)
- {
- GNUNET_break (0);
- return NULL;
- }
- if (TALER_BANK_DIRECTION_CANCEL == (TALER_BANK_DIRECTION_CANCEL & direction))
- can = "show";
- else
- can = "omit";
+ GNUNET_asprintf (&url,
+ "/history?auth=basic&account_number=%llu&delta=%lld&direction=%s&cancelled=%s&ordering=%s&start=%llu",
+ (unsigned long long) account_number,
+ (long long) num_results,
+ conv_direction (direction).value,
+ conv_cancel (direction).value,
+ (GNUNET_YES == ascending) ? "ascending" : "descending",
+ start_row);
+
+ /* Locate and "cut" the 'start' argument,
+ * if the user didn't provide one. */
if (UINT64_MAX == start_row)
- {
- GNUNET_asprintf (&url,
- "/history?auth=basic&account_number=%llu&delta=%lld&direction=%s&cancelled=%s&ordering=%s",
- (unsigned long long) account_number,
- (long long) num_results,
- dir,
- can,
- (GNUNET_YES == ascending) ? "ascending" : "descending");
+ *strstr (url, "&start=") = '\0';
- }
- else
- {
- GNUNET_asprintf (&url,
- "/history?auth=basic&account_number=%llu&delta=%lld&start=%llu&direction=%s&cancelled=%s&ordering=%s",
- (unsigned long long) account_number,
- (long long) num_results,
- (unsigned long long) start_row,
- dir,
- can,
- (GNUNET_YES == ascending) ? "ascending" : "descending");
- }
+ hh = put_history_job (ctx,
+ bank_base_url,
+ url,
+ auth,
+ hres_cb,
+ hres_cb_cls);
- hh = GNUNET_new (struct TALER_BANK_HistoryHandle);
- hh->hcb = hres_cb;
- hh->hcb_cls = hres_cb_cls;
- hh->bank_base_url = GNUNET_strdup (bank_base_url);
- hh->request_url = TALER_BANK_path_to_url_ (bank_base_url,
- url);
GNUNET_free (url);
- hh->authh = TALER_BANK_make_auth_header_ (auth);
- eh = curl_easy_init ();
- GNUNET_assert (CURLE_OK ==
- curl_easy_setopt (eh,
- CURLOPT_HTTPHEADER,
- hh->authh));
- GNUNET_assert (CURLE_OK ==
- curl_easy_setopt (eh,
- CURLOPT_URL,
- hh->request_url));
- hh->job = GNUNET_CURL_job_add (ctx,
- eh,
- GNUNET_NO,
- &handle_history_finished,
- hh);
return hh;
}
/**
- * Cancel a history request. This function cannot be used on a request
- * handle if a response is already served for it.
+ * Cancel a history request. This function cannot be
+ * used on a request handle if a response is already
+ * served for it.
*
* @param hh the history request handle
*/
diff --git a/src/bank-lib/fakebank.c b/src/bank-lib/fakebank.c
index 37aae0423..9915516cd 100644
--- a/src/bank-lib/fakebank.c
+++ b/src/bank-lib/fakebank.c
@@ -160,11 +160,12 @@ TALER_FAKEBANK_make_transfer (struct TALER_FAKEBANK_Handle *h,
struct Transaction *t;
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Making transfer from %llu to %llu over %s and subject %s\n",
+ "Making transfer from %llu to %llu over %s and subject %s; for exchange: %s\n",
(unsigned long long) debit_account,
(unsigned long long) credit_account,
TALER_amount2s (amount),
- subject);
+ subject,
+ exchange_base_url);
t = GNUNET_new (struct Transaction);
t->debit_account = debit_account;
t->credit_account = credit_account;
@@ -463,9 +464,11 @@ handle_admin_add_incoming (struct TALER_FAKEBANK_Handle *h,
void *json_str;
size_t json_len;
- json = json_pack ("{s:I}",
+ json = json_pack ("{s:I, s:s}",
"row_id",
- (json_int_t) row_id);
+ (json_int_t) row_id,
+ "timestamp", "/Date(0)/"); /*dummy tmp */
+
json_str = json_dumps (json,
JSON_INDENT(2));
json_decref (json);
diff --git a/src/bank-lib/test_bank_interpreter.c b/src/bank-lib/test_bank_interpreter.c
index fc7657790..9430e84bb 100644
--- a/src/bank-lib/test_bank_interpreter.c
+++ b/src/bank-lib/test_bank_interpreter.c
@@ -530,6 +530,7 @@ next (struct InterpreterState *is)
* 0 if the bank's reply is bogus (fails to follow the protocol)
* @param ec taler status code
* @param row_id unique ID of the wire transfer in the bank's records; UINT64_MAX on error
+ * @param timestamp time stamp of when the transaction settled at the bank
* @param json detailed response from the HTTPD, or NULL if reply was not in JSON
*/
static void
@@ -537,6 +538,7 @@ add_incoming_cb (void *cls,
unsigned int http_status,
enum TALER_ErrorCode ec,
uint64_t row_id,
+ struct GNUNET_TIME_Absolute timestamp,
const json_t *json)
{
struct InterpreterState *is = cls;
diff --git a/src/bank-lib/testing_api_cmd_history.c b/src/bank-lib/testing_api_cmd_history.c
index e3b05c83a..37e15af82 100644
--- a/src/bank-lib/testing_api_cmd_history.c
+++ b/src/bank-lib/testing_api_cmd_history.c
@@ -90,6 +90,27 @@ struct HistoryState
* chronological order.
*/
unsigned int ascending;
+
+ /**********************************
+ * Following defs are specific to *
+ * the "/history-range" version. *
+ **********************************/
+
+ /**
+ * Last row number we want in the result. Only used
+ * as a trait source when using the /history-range API.
+ */
+ const char *end_row_reference;
+
+ /**
+ * Start date for /history-range.
+ */
+ struct GNUNET_TIME_Absolute start_date;
+
+ /**
+ * End date for /history-range.
+ */
+ struct GNUNET_TIME_Absolute end_date;
};
/**
@@ -669,6 +690,8 @@ history_cb (void *cls,
struct TALER_TESTING_Interpreter *is = cls;
struct HistoryState *hs = is->commands[is->ip].cls;
+ /* Possibly we got the 204 status code
+ * as a "end of list" marker. */
if (MHD_HTTP_OK != http_status)
{
hs->hh = NULL;
@@ -710,7 +733,7 @@ history_cb (void *cls,
JSON_COMPACT);
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"Result %u was `%s'\n",
- (unsigned int) hs->results_obtained,
+ (unsigned int) hs->results_obtained++,
acc);
if (NULL != acc)
free (acc);
@@ -758,7 +781,6 @@ history_run (void *cls,
TALER_LOG_DEBUG ("row id (from trait) is %llu\n",
(unsigned long long) row_id);
-
}
auth = &AUTHS[hs->account_no - 1];
@@ -777,6 +799,81 @@ history_run (void *cls,
/**
+ * Run the command.
+ *
+ * @param cls closure.
+ * @param cmd the command to execute.
+ * @param is the interpreter state.
+ */
+static void
+history_range_run (void *cls,
+ const struct TALER_TESTING_Command *cmd,
+ struct TALER_TESTING_Interpreter *is)
+{
+
+ struct HistoryState *hs = cls;
+ const struct GNUNET_TIME_Absolute *start_date;
+ const struct GNUNET_TIME_Absolute *end_date;
+ struct TALER_BANK_AuthenticationData *auth;
+
+ if (NULL != hs->start_row_reference)
+ {
+
+ const struct TALER_TESTING_Command *history_cmd;
+
+ history_cmd = TALER_TESTING_interpreter_lookup_command
+ (is, hs->start_row_reference);
+
+ if (NULL == history_cmd)
+ TALER_TESTING_FAIL (is);
+
+ if (GNUNET_OK != TALER_TESTING_get_trait_absolute_time
+ (history_cmd, 0, &start_date))
+ TALER_TESTING_FAIL (is);
+ }
+ else
+ {
+ GNUNET_assert (UINT64_MAX != hs->start_date.abs_value_us);
+ start_date = &hs->start_date;
+ }
+
+ if (NULL != hs->end_row_reference)
+ {
+
+ const struct TALER_TESTING_Command *history_cmd;
+
+ history_cmd = TALER_TESTING_interpreter_lookup_command
+ (is, hs->end_row_reference);
+
+ if (NULL == history_cmd)
+ TALER_TESTING_FAIL (is);
+
+ if (GNUNET_OK != TALER_TESTING_get_trait_absolute_time
+ (history_cmd, 0, &end_date))
+ TALER_TESTING_FAIL (is);
+ }
+ else
+ {
+ GNUNET_assert (UINT64_MAX != hs->end_date.abs_value_us);
+ end_date = &hs->end_date;
+ }
+
+ auth = &AUTHS[hs->account_no - 1];
+ hs->hh = TALER_BANK_history_range (is->ctx,
+ hs->bank_url,
+ auth,
+ hs->account_no,
+ hs->direction,
+ hs->ascending,
+ *start_date,
+ *end_date,
+ &history_cb,
+ is);
+ GNUNET_assert (NULL != hs->hh);
+}
+
+
+/**
* Free the state from a "history" CMD, and possibly cancel
* a pending operation thereof.
*
@@ -848,4 +945,112 @@ TALER_TESTING_cmd_bank_history
return cmd;
}
+
+/**
+ * Make a "history-range" CMD, picking dates from traits.
+ *
+ * @param label command label.
+ * @param bank_url base URL of the bank offering the "history"
+ * operation.
+ * @param account_no bank account number to ask the history for.
+ * @param direction which direction this operation is interested.
+ * @param ascending if GNUNET_YES, the bank will return the rows
+ * in ascending (= chronological) order.
+ * @param start_row_reference reference to a command that can
+ * offer a absolute time to use as the 'start' argument
+ * for "/history-range".
+ * @param end_row_reference reference to a command that can
+ * offer a absolute time to use as the 'end' argument
+ * for "/history-range".
+ * @param num_result how many rows we want in the result.
+ *
+ * @return the command.
+ */
+struct TALER_TESTING_Command
+TALER_TESTING_cmd_bank_history_range
+ (const char *label,
+ const char *bank_url,
+ uint64_t account_no,
+ enum TALER_BANK_Direction direction,
+ unsigned int ascending,
+ const char *start_row_reference,
+ const char *end_row_reference,
+ long long num_results)
+{
+ struct HistoryState *hs;
+
+ hs = GNUNET_new (struct HistoryState);
+ hs->bank_url = bank_url;
+ hs->account_no = account_no;
+ hs->direction = direction;
+ hs->start_row_reference = start_row_reference;
+ hs->end_row_reference = end_row_reference;
+ hs->num_results = num_results;
+ hs->ascending = ascending;
+ hs->start_date = GNUNET_TIME_UNIT_FOREVER_ABS;
+ hs->end_date = GNUNET_TIME_UNIT_FOREVER_ABS;
+
+ struct TALER_TESTING_Command cmd = {
+ .label = label,
+ .cls = hs,
+ .run = &history_range_run,
+ .cleanup = &history_cleanup,
+ .traits = &history_traits
+ };
+
+ return cmd;
+}
+
+
+/**
+ * Make a "history-range" CMD, picking dates from the arguments.
+ *
+ * @param label command label.
+ * @param bank_url base URL of the bank offering the "history"
+ * operation.
+ * @param account_no bank account number to ask the history for.
+ * @param direction which direction this operation is interested.
+ * @param ascending if GNUNET_YES, the bank will return the rows
+ * in ascending (= chronological) order.
+ * @param start_date value for the 'start' argument
+ * of "/history-range".
+ * @param end_date value for the 'end' argument
+ * of "/history-range".
+ * @param num_result how many rows we want in the result.
+ *
+ * @return the command.
+ */
+struct TALER_TESTING_Command
+TALER_TESTING_cmd_bank_history_range_with_dates
+ (const char *label,
+ const char *bank_url,
+ uint64_t account_no,
+ enum TALER_BANK_Direction direction,
+ unsigned int ascending,
+ struct GNUNET_TIME_Absolute start_date,
+ struct GNUNET_TIME_Absolute end_date,
+ long long num_results)
+{
+ struct HistoryState *hs;
+
+ hs = GNUNET_new (struct HistoryState);
+ hs->bank_url = bank_url;
+ hs->account_no = account_no;
+ hs->direction = direction;
+ hs->num_results = num_results;
+ hs->ascending = ascending;
+ hs->start_date = start_date;
+ hs->end_date = start_date;
+
+ struct TALER_TESTING_Command cmd = {
+ .label = label,
+ .cls = hs,
+ .run = &history_range_run,
+ .cleanup = &history_cleanup,
+ .traits = &history_traits
+ };
+
+ return cmd;
+}
+
/* end of testing_api_cmd_history.c */
diff --git a/src/include/taler_bank_service.h b/src/include/taler_bank_service.h
index 2f4a06023..2cebbe6e7 100644
--- a/src/include/taler_bank_service.h
+++ b/src/include/taler_bank_service.h
@@ -101,6 +101,7 @@ struct TALER_BANK_AdminAddIncomingHandle;
* 0 if the bank's reply is bogus (fails to follow the protocol)
* @param ec detailed error code
* @param serial_id unique ID of the wire transfer in the bank's records; UINT64_MAX on error
+ * @param timestamp time when the transaction was made.
* @param json detailed response from the HTTPD, or NULL if reply was not in JSON
*/
typedef void
@@ -108,6 +109,7 @@ typedef void
unsigned int http_status,
enum TALER_ErrorCode ec,
uint64_t serial_id,
+ struct GNUNET_TIME_Absolute timestamp,
const json_t *json);
@@ -282,6 +284,41 @@ TALER_BANK_history (struct GNUNET_CURL_Context *ctx,
/**
+ * Request the wire transfer history of a bank account,
+ * using time stamps to narrow the results.
+ *
+ * @param ctx curl context for the event loop
+ * @param bank_base_url URL of the bank (used to execute this
+ * request)
+ * @param auth authentication data to use
+ * @param account_number which account number should we query
+ * @param direction what kinds of wire transfers should be
+ * returned
+ * @param ascending if GNUNET_YES, history elements will
+ * be returned in chronological order.
+ * @param start_date threshold for oldest result.
+ * @param end_date threshold for youngest result.
+ * @param hres_cb the callback to call with the transaction
+ * history
+ * @param hres_cb_cls closure for the above callback
+ * @return NULL if the inputs are invalid (i.e. zero value for
+ * @e num_results). In this case, the callback is not
+ * called.
+ */
+struct TALER_BANK_HistoryHandle *
+TALER_BANK_history_range (struct GNUNET_CURL_Context *ctx,
+ const char *bank_base_url,
+ const struct TALER_BANK_AuthenticationData *auth,
+ uint64_t account_number,
+ enum TALER_BANK_Direction direction,
+ unsigned int ascending,
+ struct GNUNET_TIME_Absolute start_date,
+ struct GNUNET_TIME_Absolute end_date,
+ TALER_BANK_HistoryResultCallback hres_cb,
+ void *hres_cb_cls);
+
+
+/**
* Cancel an history request. This function cannot be used on a request
* handle if the last response (anything with a status code other than
* 200) is already served for it.
diff --git a/src/include/taler_testing_lib.h b/src/include/taler_testing_lib.h
index d0b5f2754..31180c308 100644
--- a/src/include/taler_testing_lib.h
+++ b/src/include/taler_testing_lib.h
@@ -654,8 +654,9 @@ struct TALER_TESTING_SetupContext
* @return #GNUNET_OK if no errors occurred.
*/
int
-TALER_TESTING_setup_with_exchange_cfg (void *cls,
- const struct GNUNET_CONFIGURATION_Handle *cfg);
+TALER_TESTING_setup_with_exchange_cfg
+ (void *cls,
+ const struct GNUNET_CONFIGURATION_Handle *cfg);
/**
@@ -681,22 +682,23 @@ TALER_TESTING_setup_with_exchange (TALER_TESTING_Main main_cb,
/**
* Initialize scheduler loop and curl context for the test case
- * including starting and stopping the auditor and exchange using the
- * given configuration file.
+ * including starting and stopping the auditor and exchange using
+ * the given configuration file.
*
* @param cls must be a `struct TALER_TESTING_SetupContext *`
* @param cfg configuration to use.
* @return #GNUNET_OK if no errors occurred.
*/
int
-TALER_TESTING_setup_with_auditor_and_exchange_cfg (void *cls,
- const struct GNUNET_CONFIGURATION_Handle *cfg);
+TALER_TESTING_setup_with_auditor_and_exchange_cfg
+ (void *cls,
+ const struct GNUNET_CONFIGURATION_Handle *cfg);
/**
* Initialize scheduler loop and curl context for the test case
- * including starting and stopping the auditor and exchange using the
- * given configuration file.
+ * including starting and stopping the auditor and exchange using
+ * the given configuration file.
*
* @param main_cb main method.
* @param main_cb_cls main method closure.
@@ -709,12 +711,10 @@ TALER_TESTING_setup_with_auditor_and_exchange_cfg (void *cls,
* @return #GNUNET_OK if no errors occurred.
*/
int
-TALER_TESTING_setup_with_auditor_and_exchange (TALER_TESTING_Main main_cb,
- void *main_cb_cls,
- const char *config_file);
-
-
-
+TALER_TESTING_setup_with_auditor_and_exchange
+ (TALER_TESTING_Main main_cb,
+ void *main_cb_cls,
+ const char *config_file);
/* ************** Specific interpreter commands ************ */
@@ -872,14 +872,15 @@ TALER_TESTING_cmd_fakebank_transfer_with_instance
/**
* Modify a fakebank transfer command to enable retries when the
- * reserve is not yet full or we get other transient errors from the
- * fakebank.
+ * reserve is not yet full or we get other transient errors from
+ * the fakebank.
*
* @param cmd a fakebank transfer command
* @return the command with retries enabled
*/
struct TALER_TESTING_Command
-TALER_TESTING_cmd_fakebank_transfer_retry (struct TALER_TESTING_Command cmd);
+TALER_TESTING_cmd_fakebank_transfer_retry
+ (struct TALER_TESTING_Command cmd);
/**
@@ -1020,7 +1021,8 @@ TALER_TESTING_cmd_withdraw_denomination
* @return the command with retries enabled
*/
struct TALER_TESTING_Command
-TALER_TESTING_cmd_withdraw_with_retry (struct TALER_TESTING_Command cmd);
+TALER_TESTING_cmd_withdraw_with_retry
+ (struct TALER_TESTING_Command cmd);
/**
@@ -1098,7 +1100,8 @@ TALER_TESTING_cmd_deposit
* @return the command with retries enabled
*/
struct TALER_TESTING_Command
-TALER_TESTING_cmd_deposit_with_retry (struct TALER_TESTING_Command cmd);
+TALER_TESTING_cmd_deposit_with_retry
+ (struct TALER_TESTING_Command cmd);
/**
@@ -1148,7 +1151,8 @@ TALER_TESTING_cmd_refresh_melt_double
* @return modified command.
*/
struct TALER_TESTING_Command
-TALER_TESTING_cmd_refresh_melt_with_retry (struct TALER_TESTING_Command cmd);
+TALER_TESTING_cmd_refresh_melt_with_retry
+ (struct TALER_TESTING_Command cmd);
/**
@@ -2407,4 +2411,32 @@ TALER_TESTING_get_trait_cmd
struct TALER_TESTING_Command **_cmd);
+/**
+ * Obtain a absolute time from @a cmd.
+ *
+ * @param cmd command to extract trait from
+ * @param index which time stamp to pick if
+ * @a cmd has multiple on offer.
+ * @param time[out] set to the wanted WTID.
+ * @return #GNUNET_OK on success
+ */
+int
+TALER_TESTING_get_trait_absolute_time
+ (const struct TALER_TESTING_Command *cmd,
+ unsigned int index,
+ const struct GNUNET_TIME_Absolute **time);
+
+
+/**
+ * Offer a absolute time.
+ *
+ * @param index associate the object with this index
+ * @param time which object should be returned
+ * @return the trait.
+ */
+struct TALER_TESTING_Trait
+TALER_TESTING_make_trait_absolute_time
+ (unsigned int index,
+ const struct GNUNET_TIME_Absolute *time);
+
#endif
diff --git a/src/lib/Makefile.am b/src/lib/Makefile.am
index adf075fa5..8b20860b7 100644
--- a/src/lib/Makefile.am
+++ b/src/lib/Makefile.am
@@ -107,7 +107,8 @@ libtalertesting_la_SOURCES = \
testing_api_trait_key_peer.c \
testing_api_trait_wtid.c \
testing_api_trait_amount.c \
- testing_api_trait_cmd.c
+ testing_api_trait_cmd.c \
+ testing_api_trait_time.c
libtalertesting_la_LIBADD = \
libtalerexchange.la \
$(top_builddir)/src/wire/libtalerwire.la \
diff --git a/src/lib/testing_api_cmd_fakebank_transfer.c b/src/lib/testing_api_cmd_fakebank_transfer.c
index 43f72573b..ce9ad8545 100644
--- a/src/lib/testing_api_cmd_fakebank_transfer.c
+++ b/src/lib/testing_api_cmd_fakebank_transfer.c
@@ -102,6 +102,11 @@ struct FakebankTransferState
uint64_t serial_id;
/**
+ * Timestamp of the transaction (as returned from the bank).
+ */
+ struct GNUNET_TIME_Absolute timestamp;
+
+ /**
* Exchange URL. This value is fed to the bank when requesting
* the wire transfer; note: the bank needs it because a merchant
* might want to know which exchange performed a wire transfer to
@@ -182,6 +187,7 @@ do_retry (void *cls)
* bogus (fails to follow the protocol)
* @param ec taler-specific error code, #TALER_EC_NONE on success
* @param serial_id unique ID of the wire transfer
+ * @param timestamp time stamp of the transaction made.
* @param full_response full response from the exchange (for
* logging, in case of errors)
*/
@@ -190,13 +196,13 @@ add_incoming_cb (void *cls,
unsigned int http_status,
enum TALER_ErrorCode ec,
uint64_t serial_id,
+ struct GNUNET_TIME_Absolute timestamp,
const json_t *full_response)
{
struct FakebankTransferState *fts = cls;
struct TALER_TESTING_Interpreter *is = fts->is;
fts->aih = NULL;
- fts->serial_id = serial_id;
if (MHD_HTTP_OK != http_status)
{
if (GNUNET_YES == fts->do_retry)
@@ -205,18 +211,20 @@ add_incoming_cb (void *cls,
(TALER_EC_DB_COMMIT_FAILED_ON_RETRY == ec) ||
(MHD_HTTP_INTERNAL_SERVER_ERROR == http_status) )
{
- GNUNET_log (GNUNET_ERROR_TYPE_INFO,
- "Retrying fakebank transfer failed with %u/%d\n",
- http_status,
- (int) ec);
+ GNUNET_log
+ (GNUNET_ERROR_TYPE_INFO,
+ "Retrying fakebank transfer failed with %u/%d\n",
+ http_status,
+ (int) ec);
/* on DB conflicts, do not use backoff */
if (TALER_EC_DB_COMMIT_FAILED_ON_RETRY == ec)
fts->backoff = GNUNET_TIME_UNIT_ZERO;
else
fts->backoff = EXCHANGE_LIB_BACKOFF (fts->backoff);
- fts->retry_task = GNUNET_SCHEDULER_add_delayed (fts->backoff,
- &do_retry,
- fts);
+ fts->retry_task = GNUNET_SCHEDULER_add_delayed
+ (fts->backoff,
+ &do_retry,
+ fts);
return;
}
}
@@ -228,6 +236,9 @@ add_incoming_cb (void *cls,
TALER_TESTING_interpreter_fail (is);
return;
}
+
+ fts->serial_id = serial_id;
+ fts->timestamp = timestamp;
TALER_TESTING_interpreter_next (is);
}
@@ -422,7 +433,7 @@ fakebank_transfer_traits (void *cls,
unsigned int index)
{
struct FakebankTransferState *fts = cls;
- #define MANDATORY 6
+ #define MANDATORY 7
struct TALER_TESTING_Trait traits[MANDATORY + 1] = {
TALER_TESTING_MAKE_TRAIT_DEBIT_ACCOUNT
(&fts->debit_account_no),
@@ -431,6 +442,7 @@ fakebank_transfer_traits (void *cls,
TALER_TESTING_make_trait_url (0, fts->exchange_url),
TALER_TESTING_MAKE_TRAIT_ROW_ID (&fts->serial_id),
TALER_TESTING_make_trait_amount_obj (0, &fts->amount),
+ TALER_TESTING_make_trait_absolute_time (0, &fts->timestamp)
};
/**
diff --git a/src/lib/testing_api_trait_time.c b/src/lib/testing_api_trait_time.c
new file mode 100644
index 000000000..3fd07bbba
--- /dev/null
+++ b/src/lib/testing_api_trait_time.c
@@ -0,0 +1,76 @@
+/*
+ This file is part of TALER
+ Copyright (C) 2018 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 exchange-lib/testing_api_trait_time.c
+ * @brief traits to offer time stamps.
+ * @author Marcello Stanisci
+ */
+#include "platform.h"
+#include "taler_json_lib.h"
+#include <gnunet/gnunet_curl_lib.h>
+#include "exchange_api_handle.h"
+#include "taler_signatures.h"
+#include "taler_testing_lib.h"
+
+#define TALER_TESTING_TRAIT_TIME_ABS "time-abs"
+
+/**
+ * Obtain a absolute time from @a cmd.
+ *
+ * @param cmd command to extract trait from
+ * @param index which time stamp to pick if
+ * @a cmd has multiple on offer.
+ * @param time[out] set to the wanted WTID.
+ * @return #GNUNET_OK on success
+ */
+int
+TALER_TESTING_get_trait_absolute_time
+ (const struct TALER_TESTING_Command *cmd,
+ unsigned int index,
+ const struct GNUNET_TIME_Absolute **time)
+{
+ return cmd->traits (cmd->cls,
+ (const void **) time,
+ TALER_TESTING_TRAIT_TIME_ABS,
+ index);
+}
+
+
+/**
+ * Offer a absolute time.
+ *
+ * @param index associate the object with this index
+ * @param time which object should be returned
+ * @return the trait.
+ */
+struct TALER_TESTING_Trait
+TALER_TESTING_make_trait_absolute_time
+ (unsigned int index,
+ const struct GNUNET_TIME_Absolute *time)
+{
+ struct TALER_TESTING_Trait ret = {
+ .index = index,
+ .trait_name = TALER_TESTING_TRAIT_TIME_ABS,
+ .ptr = (const void *) time
+ };
+ return ret;
+}
+
+/* end of testing_api_trait_time.c */
diff --git a/src/wire-plugins/plugin_wire_taler-bank.c b/src/wire-plugins/plugin_wire_taler-bank.c
index 096e81df8..a35fb5d2f 100644
--- a/src/wire-plugins/plugin_wire_taler-bank.c
+++ b/src/wire-plugins/plugin_wire_taler-bank.c
@@ -619,6 +619,7 @@ taler_bank_prepare_wire_transfer (void *cls,
* 0 if the bank's reply is bogus (fails to follow the protocol)
* @param ec error code from the bank
* @param serial_id unique ID of the wire transfer in the bank's records; UINT64_MAX on error
+ * @param timestamp time when the transfer was settled by the bank.
* @param json detailed response from the HTTPD, or NULL if reply was not JSON
*/
static void
@@ -626,6 +627,7 @@ execute_cb (void *cls,
unsigned int http_status,
enum TALER_ErrorCode ec,
uint64_t serial_id,
+ struct GNUNET_TIME_Absolute timestamp,
const json_t *json)
{
struct TALER_WIRE_ExecuteHandle *eh = cls;