summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2020-05-10 20:06:36 +0200
committerChristian Grothoff <christian@grothoff.org>2020-05-10 20:06:36 +0200
commita5da6d3cec3b090c5aa21255eed37fc7a3ca48ec (patch)
tree0f2a93abc26c9d53690864a47250035dbb167a14 /src
parent47811a60b692e575274305d4cac429220d27a328 (diff)
downloadmerchant-a5da6d3cec3b090c5aa21255eed37fc7a3ca48ec.tar.gz
merchant-a5da6d3cec3b090c5aa21255eed37fc7a3ca48ec.tar.bz2
merchant-a5da6d3cec3b090c5aa21255eed37fc7a3ca48ec.zip
GET /transfers implementation
Diffstat (limited to 'src')
-rw-r--r--src/backend/Makefile.am2
-rw-r--r--src/backend/taler-merchant-httpd.c7
-rw-r--r--src/backend/taler-merchant-httpd_private-get-instances-ID.c4
-rw-r--r--src/backend/taler-merchant-httpd_private-get-transfers.c47
-rw-r--r--src/backend/taler-merchant-httpd_private-get-transfers.h25
-rw-r--r--src/backenddb/plugin_merchantdb_postgres.c548
-rw-r--r--src/include/taler_merchantdb_plugin.h106
7 files changed, 531 insertions, 208 deletions
diff --git a/src/backend/Makefile.am b/src/backend/Makefile.am
index 2512143d..3127ab24 100644
--- a/src/backend/Makefile.am
+++ b/src/backend/Makefile.am
@@ -41,6 +41,8 @@ taler_merchant_httpd_SOURCES = \
taler-merchant-httpd_private-get-products-ID.h \
taler-merchant-httpd_private-get-orders.c \
taler-merchant-httpd_private-get-orders.h \
+ taler-merchant-httpd_private-get-transfers.c \
+ taler-merchant-httpd_private-get-transfers.h \
taler-merchant-httpd_private-patch-instances-ID.c \
taler-merchant-httpd_private-patch-instances-ID.h \
taler-merchant-httpd_private-patch-products-ID.c \
diff --git a/src/backend/taler-merchant-httpd.c b/src/backend/taler-merchant-httpd.c
index c5dbacd2..e3640112 100644
--- a/src/backend/taler-merchant-httpd.c
+++ b/src/backend/taler-merchant-httpd.c
@@ -38,6 +38,7 @@
#include "taler-merchant-httpd_private-get-products-ID.h"
#include "taler-merchant-httpd_private-get-orders.h"
// #include "taler-merchant-httpd_private-get-orders-ID.h"
+#include "taler-merchant-httpd_private-get-transfers.h"
#include "taler-merchant-httpd_private-patch-instances-ID.h"
#include "taler-merchant-httpd_private-patch-products-ID.h"
#include "taler-merchant-httpd_private-post-instances.h"
@@ -838,6 +839,12 @@ url_handler (void *cls,
.method = MHD_HTTP_METHOD_POST,
.handler = &TMH_private_post_transfers
},
+ /* GET /transfers: */
+ {
+ .url_prefix = "/transfers",
+ .method = MHD_HTTP_METHOD_GET,
+ .handler = &TMH_private_get_transfers
+ },
{
NULL
}
diff --git a/src/backend/taler-merchant-httpd_private-get-instances-ID.c b/src/backend/taler-merchant-httpd_private-get-instances-ID.c
index b6993791..bf248b15 100644
--- a/src/backend/taler-merchant-httpd_private-get-instances-ID.c
+++ b/src/backend/taler-merchant-httpd_private-get-instances-ID.c
@@ -51,7 +51,7 @@ TMH_private_get_instances_ID (const struct TMH_RequestHandler *rh,
json_array_append_new (
ja,
json_pack (
- "{s:O, s:o, s:O, s:o}",
+ "{s:O, s:o, s:O, s:b}",
"payto_uri",
json_object_get (wm->j_wire,
"payto_uri"),
@@ -61,7 +61,7 @@ TMH_private_get_instances_ID (const struct TMH_RequestHandler *rh,
json_object_get (wm->j_wire,
"salt"),
"active",
- (wm->active) ? json_true () : json_false ())));
+ (wm->active) ? 1 : 0)));
}
return TALER_MHD_reply_json_pack (
diff --git a/src/backend/taler-merchant-httpd_private-get-transfers.c b/src/backend/taler-merchant-httpd_private-get-transfers.c
index 23163129..0bf53f3d 100644
--- a/src/backend/taler-merchant-httpd_private-get-transfers.c
+++ b/src/backend/taler-merchant-httpd_private-get-transfers.c
@@ -21,13 +21,8 @@
*/
#include "platform.h"
#include <jansson.h>
-#include <taler/taler_signatures.h>
#include <taler/taler_json_lib.h>
-#include "taler-merchant-httpd.h"
-#include "taler-merchant-httpd_mhd.h"
-#include "taler-merchant-httpd_auditors.h"
-#include "taler-merchant-httpd_exchanges.h"
-#include "taler-merchant-httpd_track-transfer.h"
+#include "taler-merchant-httpd_private-get-transfers.h"
/**
@@ -54,11 +49,31 @@ transfer_cb (void *cls,
const char *exchange_url,
uint64_t transfer_serial_id,
struct GNUNET_TIME_Absolute execution_time,
- enum TALER_MERCHANTDB_YesNoAll verified)
+ bool verified,
+ bool confirmed)
{
json_t *ja = cls;
-
-
+ json_t *r;
+
+ r = json_pack ("{s:o, s:o, s:s, s:s, s:I, s:b, s:b}",
+ "credit_amount", TALER_JSON_from_amount (credit_amount),
+ "wtid", GNUNET_JSON_from_data_auto (wtid),
+ "payto_uri", payto_uri,
+ "exchange_url", exchange_url,
+ "transfer_serial_id", (json_int_t) transfer_serial_id,
+ "verified", verified ? 1 : 0,
+ "confirmed", confirmed ? 1 : 0);
+ GNUNET_assert (NULL != r);
+ if (GNUNET_TIME_UNIT_FOREVER_ABS.abs_value_us !=
+ execution_time.abs_value_us)
+ GNUNET_assert (0 ==
+ json_object_set_new (
+ r,
+ "execution_time",
+ GNUNET_JSON_from_time_abs (execution_time)));
+ GNUNET_assert (0 ==
+ json_array_append_new (ja,
+ r));
}
@@ -150,7 +165,7 @@ TMH_private_get_transfers (const struct TMH_RequestHandler *rh,
unsigned long long o;
if (1 !=
- sscanf (limit_s,
+ sscanf (offset_s,
"%llu%1s",
&o,
dummy))
@@ -200,7 +215,7 @@ TMH_private_get_transfers (const struct TMH_RequestHandler *rh,
"verified");
}
- db->preflight (db->cls);
+ TMH_db->preflight (TMH_db->cls);
{
json_t *ja;
enum GNUNET_DB_QueryStatus qs;
@@ -225,13 +240,13 @@ TMH_private_get_transfers (const struct TMH_RequestHandler *rh,
GNUNET_break (GNUNET_DB_STATUS_HARD_ERROR == qs);
return TALER_MHD_reply_with_error (connection,
MHD_HTTP_INTERNAL_SERVER_ERROR,
- TALER_EC_GET_TRANSFERS_DB_FETCH_DEPOSIT_ERROR,
+ TALER_EC_GET_TRANSFERS_DB_FETCH_ERROR,
"Fail to query database about transfers");
}
- return MHD_MHD_reply_json_pack (connection,
- MHD_HTTP_OK,
- "{s:o}",
- "transfers", ja);
+ return TALER_MHD_reply_json_pack (connection,
+ MHD_HTTP_OK,
+ "{s:o}",
+ "transfers", ja);
}
}
diff --git a/src/backend/taler-merchant-httpd_private-get-transfers.h b/src/backend/taler-merchant-httpd_private-get-transfers.h
index 0463295e..556e8558 100644
--- a/src/backend/taler-merchant-httpd_private-get-transfers.h
+++ b/src/backend/taler-merchant-httpd_private-get-transfers.h
@@ -14,36 +14,29 @@
TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
*/
/**
- * @file backend/taler-merchant-httpd_track-transfer.h
- * @brief headers for /track/transfer handler
+ * @file backend/taler-merchant-httpd_private-get-transfers.h
+ * @brief headers for GET /transfers handler
* @author Christian Grothoff
* @author Marcello Stanisci
*/
-#ifndef TALER_MERCHANT_HTTPD_TRACK_TRANSFER_H
-#define TALER_MERCHANT_HTTPD_TRACK_TRANSFER_H
+#ifndef TALER_MERCHANT_HTTPD_PRIVATE_GET_TRANSFERS_H
+#define TALER_MERCHANT_HTTPD_PRIVATE_GET_TRANSFERS_H
#include <microhttpd.h>
#include "taler-merchant-httpd.h"
+
/**
- * Manages a /track/transfer call, thus it calls the /wire/transfer
- * offered by the exchange in order to return the set of transfers
- * (of coins) associated with a given wire transfer
+ * Manages a GET /private/transfers call.
*
* @param rh context of the handler
* @param connection the MHD connection to handle
- * @param[in,out] connection_cls the connection's closure (can be updated)
- * @param upload_data upload data
- * @param[in,out] upload_data_size number of bytes (left) in @a upload_data
- * @param mi merchant backend instance, never NULL
+ * @param[in,out] hc context with further information about the request
* @return MHD result code
*/
MHD_RESULT
-MH_handler_track_transfer (struct TMH_RequestHandler *rh,
+TMH_private_get_transfers (const struct TMH_RequestHandler *rh,
struct MHD_Connection *connection,
- void **connection_cls,
- const char *upload_data,
- size_t *upload_data_size,
- struct MerchantInstance *mi);
+ struct TMH_HandlerContext *hc);
#endif
diff --git a/src/backenddb/plugin_merchantdb_postgres.c b/src/backenddb/plugin_merchantdb_postgres.c
index 8e402d31..8c1646a7 100644
--- a/src/backenddb/plugin_merchantdb_postgres.c
+++ b/src/backenddb/plugin_merchantdb_postgres.c
@@ -3457,6 +3457,219 @@ postgres_lookup_transfer_details (
}
+/**
+ * Closure for #lookup_transfers_cb().
+ */
+struct LookupTransfersContext
+{
+ /**
+ * Function to call on results.
+ */
+ TALER_MERCHANTDB_TransferCallback cb;
+
+ /**
+ * Closure for @e cb.
+ */
+ void *cb_cls;
+
+ /**
+ * Postgres context.
+ */
+ struct PostgresClosure *pg;
+
+ /**
+ * Transaction status (set).
+ */
+ enum GNUNET_DB_QueryStatus qs;
+
+ /**
+ * Filter to apply by verification status.
+ */
+ enum TALER_MERCHANTDB_YesNoAll verified;
+};
+
+
+/**
+ * Function to be called with the results of a SELECT statement
+ * that has returned @a num_results results.
+ *
+ * @param cls of type `struct LookupTransfersContext *`
+ * @param result the postgres result
+ * @param num_result the number of results in @a result
+ */
+static void
+lookup_transfers_cb (void *cls,
+ PGresult *result,
+ unsigned int num_results)
+{
+ struct LookupTransfersContext *ltc = cls;
+ struct PostgresClosure *pg = ltc->pg;
+
+ for (unsigned int i = 0; i<num_results; i++)
+ {
+ struct TALER_Amount credit_amount;
+ struct TALER_WireTransferIdentifierRawP wtid;
+ char *payto_uri;
+ char *exchange_url;
+ uint64_t transfer_serial_id;
+ struct GNUNET_TIME_Absolute execution_time;
+ enum TALER_MERCHANTDB_YesNoAll verified;
+ uint8_t verified8;
+ uint8_t confirmed8;
+ struct GNUNET_PQ_ResultSpec rs[] = {
+ TALER_PQ_RESULT_SPEC_AMOUNT ("credit_amount",
+ &credit_amount),
+ GNUNET_PQ_result_spec_auto_from_type ("wtid",
+ &wtid),
+ GNUNET_PQ_result_spec_string ("payto_uri",
+ &payto_uri),
+ GNUNET_PQ_result_spec_string ("exchange_url",
+ &exchange_url),
+ GNUNET_PQ_result_spec_uint64 ("credit_serial",
+ &transfer_serial_id),
+ GNUNET_PQ_result_spec_absolute_time ("execution_time",
+ &execution_time),
+ GNUNET_PQ_result_spec_auto_from_type ("verified",
+ &verified8),
+ GNUNET_PQ_result_spec_auto_from_type ("confirmed",
+ &confirmed8),
+ GNUNET_PQ_result_spec_end
+ };
+
+ if (GNUNET_OK !=
+ GNUNET_PQ_extract_result (result,
+ rs,
+ i))
+ {
+ GNUNET_break (0);
+ ltc->qs = GNUNET_DB_STATUS_HARD_ERROR;
+ return;
+ }
+ if (0 == verified8)
+ verified = TALER_MERCHANTDB_YNA_NO;
+ else
+ verified = TALER_MERCHANTDB_YNA_YES;
+ if ( (ltc->verified == TALER_MERCHANTDB_YNA_ALL) ||
+ (ltc->verified == verified) )
+ {
+ ltc->qs = i + 1;
+ ltc->cb (ltc->cb_cls,
+ &credit_amount,
+ &wtid,
+ payto_uri,
+ exchange_url,
+ transfer_serial_id,
+ execution_time,
+ TALER_MERCHANTDB_YNA_YES == verified,
+ 0 != confirmed8);
+ }
+ GNUNET_PQ_cleanup_result (rs);
+ }
+}
+
+
+/**
+ * Lookup transfers. Note that filtering by @a verified status is done
+ * outside of SQL, as we already have 8 prepared statements and adding
+ * a filter on verified would further double the number of statements for
+ * a likely rather ineffective filter. So we apply that filter in
+ * #lookup_transfers_cb().
+ *
+ * @param cls closure
+ * @param instance_id instance to lookup payments for
+ * @param payto_uri account that we are interested in transfers to
+ * @param before timestamp for the earliest transfer we care about
+ * @param after timestamp for the last transfer we care about
+ * @param limit number of entries to return, negative for descending in execution time,
+ * positive for ascending in execution time
+ * @param offset transfer_serial number of the transfer we want to offset from
+ * @param verified filter transfers by verification status
+ * @param cb function to call with detailed transfer data
+ * @param cb_cls closure for @a cb
+ * @return transaction status
+ */
+static enum GNUNET_DB_QueryStatus
+postgres_lookup_transfers (void *cls,
+ const char *instance_id,
+ const char *payto_uri,
+ struct GNUNET_TIME_Absolute before,
+ struct GNUNET_TIME_Absolute after,
+ int64_t limit,
+ uint64_t offset,
+ enum TALER_MERCHANTDB_YesNoAll verified,
+ TALER_MERCHANTDB_TransferCallback cb,
+ void *cb_cls)
+{
+ struct PostgresClosure *pg = cls;
+ uint64_t plimit = (uint64_t) ((limit < 0) ? -limit : limit);
+ struct GNUNET_PQ_QueryParam params_payto_et[] = {
+ GNUNET_PQ_query_param_string (instance_id),
+ GNUNET_PQ_query_param_absolute_time (&before),
+ GNUNET_PQ_query_param_absolute_time (&after),
+ GNUNET_PQ_query_param_uint64 (&offset),
+ GNUNET_PQ_query_param_uint64 (&plimit),
+ GNUNET_PQ_query_param_string (payto_uri),
+ GNUNET_PQ_query_param_end
+ };
+ struct GNUNET_PQ_QueryParam params_et[] = {
+ GNUNET_PQ_query_param_string (instance_id),
+ GNUNET_PQ_query_param_absolute_time (&before),
+ GNUNET_PQ_query_param_absolute_time (&after),
+ GNUNET_PQ_query_param_uint64 (&offset),
+ GNUNET_PQ_query_param_uint64 (&plimit),
+ GNUNET_PQ_query_param_end
+ };
+ struct GNUNET_PQ_QueryParam params_payto[] = {
+ GNUNET_PQ_query_param_string (instance_id),
+ GNUNET_PQ_query_param_uint64 (&offset),
+ GNUNET_PQ_query_param_uint64 (&plimit),
+ GNUNET_PQ_query_param_string (payto_uri),
+ GNUNET_PQ_query_param_end
+ };
+ struct GNUNET_PQ_QueryParam params_none[] = {
+ GNUNET_PQ_query_param_string (instance_id),
+ GNUNET_PQ_query_param_uint64 (&offset),
+ GNUNET_PQ_query_param_uint64 (&plimit),
+ GNUNET_PQ_query_param_end
+ };
+ struct GNUNET_PQ_QueryParam *params;
+ struct LookupTransfersContext ltc = {
+ .cb = cb,
+ .cb_cls = cb_cls,
+ .pg = pg,
+ .verified = verified
+ };
+ enum GNUNET_DB_QueryStatus qs;
+ char stmt[128];
+ bool by_time;
+
+ by_time = ( (before.abs_value_us !=
+ GNUNET_TIME_UNIT_FOREVER_ABS.abs_value_us) ||
+ (after.abs_value_us != GNUNET_TIME_UNIT_ZERO_ABS.abs_value_us) );
+
+ check_connection (pg);
+ GNUNET_snprintf (stmt,
+ sizeof (stmt),
+ "lookup_transfers%s%s%s",
+ (by_time) ? "_time" : "",
+ (NULL != payto_uri) ? "_payto" : "",
+ (limit > 0) ? "_asc" : "_desc");
+ params = (by_time)
+ ? ( (NULL != payto_uri) ? params_payto_et : params_et)
+ : ( (NULL != payto_uri) ? params_payto : params_none);
+
+ // FIXME: write SQL (_desc-variant!)
+ qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn,
+ stmt,
+ params,
+ &lookup_transfers_cb,
+ &ltc);
+ if (0 >= qs)
+ return qs;
+ return ltc.qs;
+}
+
+
/* ********************* OLD API ************************** */
/**
@@ -3672,131 +3885,6 @@ postgres_get_authorized_tip_amount (void *cls,
/**
- * Closure for #find_transfers_cb().
- */
-struct FindTransfersContext
-{
- /**
- * Function to call on results.
- */
- TALER_MERCHANTDB_TransferCallback cb;
-
- /**
- * Closure for @e cb.
- */
- void *cb_cls;
-
- /**
- * Hash of the contract we are looking under.
- */
- const struct GNUNET_HashCode *h_contract_terms;
-
- /**
- * Transaction status (set).
- */
- enum GNUNET_DB_QueryStatus qs;
-};
-
-
-/**
- * Function to be called with the results of a SELECT statement
- * that has returned @a num_results results.
- *
- * @param cls of type `struct FindTransfersContext *`
- * @param result the postgres result
- * @param num_result the number of results in @a result
- */
-static void
-find_transfers_cb (void *cls,
- PGresult *result,
- unsigned int num_results)
-{
- struct FindTransfersContext *ftc = cls;
-
- for (unsigned int i = 0; i<num_results; i++)
- {
- struct TALER_CoinSpendPublicKeyP coin_pub;
- struct TALER_WireTransferIdentifierRawP wtid;
- struct GNUNET_TIME_Absolute execution_time;
- json_t *proof;
-
- struct GNUNET_PQ_ResultSpec rs[] = {
- GNUNET_PQ_result_spec_auto_from_type ("coin_pub",
- &coin_pub),
- GNUNET_PQ_result_spec_auto_from_type ("wtid",
- &wtid),
- GNUNET_PQ_result_spec_absolute_time ("execution_time",
- &execution_time),
- TALER_PQ_result_spec_json ("proof",
- &proof),
- GNUNET_PQ_result_spec_end
- };
-
- if (GNUNET_OK !=
- GNUNET_PQ_extract_result (result,
- rs,
- i))
- {
- GNUNET_break (0);
- ftc->qs = GNUNET_DB_STATUS_HARD_ERROR;
- return;
- }
- ftc->qs = i + 1;
- ftc->cb (ftc->cb_cls,
- ftc->h_contract_terms,
- &coin_pub,
- &wtid,
- execution_time,
- proof);
- GNUNET_PQ_cleanup_result (rs);
- }
-}
-
-
-/**
- * Lookup information about a transfer by @a h_contract_terms. Note
- * that in theory there could be multiple wire transfers for a
- * single @a h_contract_terms, as the transaction may have involved
- * multiple coins and the coins may be spread over different wire
- * transfers.
- *
- * @param cls closure
- * @param h_contract_terms key for the search
- * @param cb function to call with transfer data
- * @param cb_cls closure for @a cb
- * @return transaction status
- */
-static enum GNUNET_DB_QueryStatus
-postgres_find_transfers_by_hash (void *cls,
- const struct GNUNET_HashCode *h_contract_terms,
- TALER_MERCHANTDB_TransferCallback cb,
- void *cb_cls)
-{
- struct PostgresClosure *pg = cls;
- struct GNUNET_PQ_QueryParam params[] = {
- GNUNET_PQ_query_param_auto_from_type (h_contract_terms),
- GNUNET_PQ_query_param_end
- };
- struct FindTransfersContext ftc = {
- .h_contract_terms = h_contract_terms,
- .cb = cb,
- .cb_cls = cb_cls
- };
- enum GNUNET_DB_QueryStatus qs;
-
- check_connection (pg);
- qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn,
- "find_transfers_by_hash",
- params,
- &find_transfers_cb,
- &ftc);
- if (0 >= qs)
- return qs;
- return ftc.qs;
-}
-
-
-/**
* Store information about wire fees charged by an exchange,
* including signature (so we have proof).
*
@@ -6007,6 +6095,214 @@ libtaler_plugin_merchantdb_postgres_init (void *cls)
" WHERE merchant_transfers.wtid=$2"
" AND merchant_transfers.exchange_url=$1",
2),
+ /* for postgres_lookup_transfers() */
+ GNUNET_PQ_make_prepare ("lookup_transfers_time_payto_asc",
+ "SELECT"
+ " credit_amount_val"
+ ",credit_amount_frac"
+ ",wtid"
+ ",merchant_accounts.payto_uri"
+ ",exchange_url"
+ ",credit_serial"
+ ",merchant_transfer_signatures.execution_time"
+ ",verified"
+ ",confirmed"
+ " FROM merchant_transfers"
+ " JOIN merchant_accounts USING (account_serial)"
+ " JOIN merchant_transfer_signatures USING (credit_serial)"
+ " WHERE execution_time < $2"
+ " AND execution_time >= $3"
+ " AND credit_serial > $4"
+ " AND payto_uri = $6"
+ " AND merchant_serial ="
+ " (SELECT merchant_serial"
+ " FROM merchant_instances"
+ " WHERE merchant_id=$1)"
+ " ORDER BY credit_serial ASC"
+ " LIMIT $5",
+ 6),
+ /* for postgres_lookup_transfers() */
+ GNUNET_PQ_make_prepare ("lookup_transfers_time_asc",
+ "SELECT"
+ " credit_amount_val"
+ ",credit_amount_frac"
+ ",wtid"
+ ",merchant_accounts.payto_uri"
+ ",exchange_url"
+ ",credit_serial"
+ ",merchant_transfer_signatures.execution_time"
+ ",verified"
+ ",confirmed"
+ " FROM merchant_transfers"
+ " JOIN merchant_accounts USING (account_serial)"
+ " JOIN merchant_transfer_signatures USING (credit_serial)"
+ " WHERE execution_time < $2"
+ " AND execution_time >= $3"
+ " AND credit_serial > $4"
+ " AND merchant_serial ="
+ " (SELECT merchant_serial"
+ " FROM merchant_instances"
+ " WHERE merchant_id=$1)"
+ " ORDER BY credit_serial ASC"
+ " LIMIT $5",
+ 5),
+ /* for postgres_lookup_transfers() */
+ GNUNET_PQ_make_prepare ("lookup_transfers_payto_asc",
+ "SELECT"
+ " credit_amount_val"
+ ",credit_amount_frac"
+ ",wtid"
+ ",merchant_accounts.payto_uri"
+ ",exchange_url"
+ ",credit_serial"
+ ",CASE WHEN (merchant_transfer_signatures.execution_time) IS NULL"
+ " THEN 9223372036854775807" /* largest BIGINT possible */
+ " ELSE merchant_transfer_signatures.execution_time"
+ " END AS execution_time"
+ ",verified"
+ ",confirmed"
+ " FROM merchant_transfers"
+ " JOIN merchant_accounts USING (account_serial)"
+ " LEFT JOIN merchant_transfer_signatures USING (credit_serial)"
+ " WHERE credit_serial > $2"
+ " AND payto_uri = $4"
+ " AND merchant_serial ="
+ " (SELECT merchant_serial"
+ " FROM merchant_instances"
+ " WHERE merchant_id=$1)"
+ " ORDER BY credit_serial ASC"
+ " LIMIT $3",
+ 4),
+ /* for postgres_lookup_transfers() */
+ GNUNET_PQ_make_prepare ("lookup_transfers_asc",
+ "SELECT"
+ " credit_amount_val"
+ ",credit_amount_frac"
+ ",wtid"
+ ",merchant_accounts.payto_uri"
+ ",exchange_url"
+ ",credit_serial"
+ ",CASE WHEN (merchant_transfer_signatures.execution_time) IS NULL"
+ " THEN 9223372036854775807" /* largest BIGINT possible */
+ " ELSE merchant_transfer_signatures.execution_time"
+ " END AS execution_time"
+ ",verified"
+ ",confirmed"
+ " FROM merchant_transfers"
+ " JOIN merchant_accounts USING (account_serial)"
+ " LEFT JOIN merchant_transfer_signatures USING (credit_serial)"
+ " WHERE credit_serial > $2"
+ " AND merchant_serial ="
+ " (SELECT merchant_serial"
+ " FROM merchant_instances"
+ " WHERE merchant_id=$1)"
+ " ORDER BY credit_serial ASC"
+ " LIMIT $3",
+ 3),
+ /* for postgres_lookup_transfers() */
+ GNUNET_PQ_make_prepare ("lookup_transfers_time_payto_desc",
+ "SELECT"
+ " credit_amount_val"
+ ",credit_amount_frac"
+ ",wtid"
+ ",merchant_accounts.payto_uri"
+ ",exchange_url"
+ ",credit_serial"
+ ",merchant_transfer_signatures.execution_time"
+ ",verified"
+ ",confirmed"
+ " FROM merchant_transfers"
+ " JOIN merchant_accounts USING (account_serial)"
+ " JOIN merchant_transfer_signatures USING (credit_serial)"
+ " WHERE execution_time < $2"
+ " AND execution_time >= $3"
+ " AND credit_serial < $4"
+ " AND payto_uri = $6"
+ " AND merchant_serial ="
+ " (SELECT merchant_serial"
+ " FROM merchant_instances"
+ " WHERE merchant_id=$1)"
+ " ORDER BY credit_serial DESC"
+ " LIMIT $5",
+ 6),
+ /* for postgres_lookup_transfers() */
+ GNUNET_PQ_make_prepare ("lookup_transfers_time_desc",
+ "SELECT"
+ " credit_amount_val"
+ ",credit_amount_frac"
+ ",wtid"
+ ",merchant_accounts.payto_uri"
+ ",exchange_url"
+ ",credit_serial"
+ ",merchant_transfer_signatures.execution_time"
+ ",verified"
+ ",confirmed"
+ " FROM merchant_transfers"
+ " JOIN merchant_accounts USING (account_serial)"
+ " JOIN merchant_transfer_signatures USING (credit_serial)"
+ " WHERE execution_time < $2"
+ " AND execution_time >= $3"
+ " AND credit_serial < $4"
+ " AND merchant_serial ="
+ " (SELECT merchant_serial"
+ " FROM merchant_instances"
+ " WHERE merchant_id=$1)"
+ " ORDER BY credit_serial DESC"
+ " LIMIT $5",
+ 5),
+ /* for postgres_lookup_transfers() */
+ GNUNET_PQ_make_prepare ("lookup_transfers_payto_desc",
+ "SELECT"
+ " credit_amount_val"
+ ",credit_amount_frac"
+ ",wtid"
+ ",merchant_accounts.payto_uri"
+ ",exchange_url"
+ ",credit_serial"
+ ",CASE WHEN (merchant_transfer_signatures.execution_time) IS NULL"
+ " THEN 9223372036854775807" /* largest BIGINT possible */
+ " ELSE merchant_transfer_signatures.execution_time"
+ " END AS execution_time"
+ ",verified"
+ ",confirmed"
+ " FROM merchant_transfers"
+ " JOIN merchant_accounts USING (account_serial)"
+ " LEFT JOIN merchant_transfer_signatures USING (credit_serial)"
+ " WHERE credit_serial < $2"
+ " AND payto_uri = $4"
+ " AND merchant_serial ="
+ " (SELECT merchant_serial"
+ " FROM merchant_instances"
+ " WHERE merchant_id=$1)"
+ " ORDER BY credit_serial DESC"
+ " LIMIT $3",
+ 4),
+ /* for postgres_lookup_transfers() */
+ GNUNET_PQ_make_prepare ("lookup_transfers_desc",
+ "SELECT"
+ " credit_amount_val"
+ ",credit_amount_frac"
+ ",wtid"
+ ",merchant_accounts.payto_uri"
+ ",exchange_url"
+ ",credit_serial"
+ ",CASE WHEN (merchant_transfer_signatures.execution_time) IS NULL"
+ " THEN 9223372036854775807" /* largest BIGINT possible */
+ " ELSE merchant_transfer_signatures.execution_time"
+ " END AS execution_time"
+ ",verified"
+ ",confirmed"
+ " FROM merchant_transfers"
+ " JOIN merchant_accounts USING (account_serial)"
+ " LEFT JOIN merchant_transfer_signatures USING (credit_serial)"
+ " WHERE credit_serial < $2"
+ " AND merchant_serial ="
+ " (SELECT merchant_serial"
+ " FROM merchant_instances"
+ " WHERE merchant_id=$1)"
+ " ORDER BY credit_serial DESC"
+ " LIMIT $3",
+ 3),
/* OLD API: */
#if 0
@@ -6333,12 +6629,12 @@ libtaler_plugin_merchantdb_postgres_init (void *cls)
&postgres_set_transfer_status_to_verified;
plugin->lookup_transfer_summary = &postgres_lookup_transfer_summary;
plugin->lookup_transfer_details = &postgres_lookup_transfer_details;
+ plugin->lookup_transfers = &postgres_lookup_transfers;
/* OLD API: */
plugin->store_coin_to_transfer = &postgres_store_coin_to_transfer;
plugin->store_transfer_to_proof = &postgres_store_transfer_to_proof;
plugin->store_wire_fee_by_exchange = &postgres_store_wire_fee_by_exchange;
- plugin->find_transfers_by_hash = &postgres_find_transfers_by_hash;
plugin->find_proof_by_wtid = &postgres_find_proof_by_wtid;
plugin->get_authorized_tip_amount = &postgres_get_authorized_tip_amount;
plugin->enable_tip_reserve_TR = &postgres_enable_tip_reserve_TR;
diff --git a/src/include/taler_merchantdb_plugin.h b/src/include/taler_merchantdb_plugin.h
index a9816a0f..5321b574 100644
--- a/src/include/taler_merchantdb_plugin.h
+++ b/src/include/taler_merchantdb_plugin.h
@@ -425,6 +425,35 @@ typedef void
const struct TALER_TrackTransferDetails *ttd);
+/**
+ * Function called with information about a wire transfer.
+ *
+ * @param cls closure with a `json_t *` array to build up the response
+ * @param credit_amount how much was wired to the merchant (minus fees)
+ * @param wtid wire transfer identifier
+ * @param payto_uri target account that received the wire transfer
+ * @param exchange_url base URL of the exchange that made the wire transfer
+ * @param transfer_serial_id serial number identifying the transfer in the backend
+ * @param execution_time when did the exchange make the transfer, #GNUNET_TIME_UNIT_FOREVER_ABS
+ * if it did not yet happen
+ * @param verified true if we checked the exchange's answer and liked it,
+ * false there is a problem (verification failed or did not yet happen)
+ * @param confirmed true if the merchant confirmed this wire transfer
+ * false if it is so far only claimed to have been made by the exchange
+ */
+typedef void
+(*TALER_MERCHANTDB_TransferCallback)(
+ void *cls,
+ const struct TALER_Amount *credit_amount,
+ const struct TALER_WireTransferIdentifierRawP *wtid,
+ const char *payto_uri,
+ const char *exchange_url,
+ uint64_t transfer_serial_id,
+ struct GNUNET_TIME_Absolute execution_time,
+ bool verified,
+ bool confirmed);
+
+
/* **************** OLD: ******************** */
/**
@@ -495,33 +524,6 @@ typedef void
/**
- * Information about the wire transfer corresponding to
- * a deposit operation. Note that it is in theory possible
- * that we have a @a h_contract_terms and @a coin_pub in the
- * result that do not match a deposit that we know about,
- * for example because someone else deposited funds into
- * our account.
- *
- * @param cls closure
- * @param h_contract_terms hashcode of the proposal data
- * @param coin_pub public key of the coin
- * @param wtid identifier of the wire transfer in which the exchange
- * send us the money for the coin deposit
- * @param execution_time when was the wire transfer executed?
- * @param exchange_proof proof from exchange about what the deposit was for
- * NULL if we have not asked for this signature
- */
-typedef void
-(*TALER_MERCHANTDB_TransferCallback)(
- void *cls,
- const struct GNUNET_HashCode *h_contract_terms,
- const struct TALER_CoinSpendPublicKeyP *coin_pub,
- const struct TALER_WireTransferIdentifierRawP *wtid,
- struct GNUNET_TIME_Absolute execution_time,
- const json_t *exchange_proof);
-
-
-/**
* Function called with information about a wire transfer identifier.
*
* @param cls closure
@@ -1346,7 +1348,6 @@ struct TALER_MERCHANTDB_Plugin
* Lookup transfer status.
*
* @param cls closure
- * @param instance_id instance to lookup payments for
* @param exchange_url the exchange that made the transfer
* @param payto_uri account that received the transfer
* @param wtid wire transfer subject
@@ -1426,6 +1427,35 @@ struct TALER_MERCHANTDB_Plugin
void *cb_cls);
+ /**
+ * Lookup transfers.
+ *
+ * @param cls closure
+ * @param instance_id instance to lookup payments for
+ * @param payto_uri account that we are interested in transfers to
+ * @param before timestamp for the earliest transfer we care about
+ * @param after timestamp for the last transfer we care about
+ * @param limit number of entries to return, negative for descending in execution time,
+ * positive for ascending in execution time
+ * @param offset transfer_serial number of the transfer we want to offset from
+ * @param verified filter transfers by verification status
+ * @param cb function to call with detailed transfer data
+ * @param cb_cls closure for @a cb
+ * @return transaction status
+ */
+ enum GNUNET_DB_QueryStatus
+ (*lookup_transfers)(void *cls,
+ const char *instance_id,
+ const char *payto_uri,
+ struct GNUNET_TIME_Absolute before,
+ struct GNUNET_TIME_Absolute after,
+ int64_t limit,
+ uint64_t offset,
+ enum TALER_MERCHANTDB_YesNoAll yna,
+ TALER_MERCHANTDB_TransferCallback cb,
+ void *cb_cls);
+
+
/* ****************** OLD API ******************** */
@@ -1605,26 +1635,6 @@ struct TALER_MERCHANTDB_Plugin
/**
- * Lookup information about a transfer by @a h_contract_terms. Note
- * that in theory there could be multiple wire transfers for a
- * single @a h_contract_terms, as the transaction may have involved
- * multiple coins and the coins may be spread over different wire
- * transfers.
- *
- * @param cls closure
- * @param h_contract_terms proposal data's hashcode
- * @param cb function to call with transfer data
- * @param cb_cls closure for @a cb
- * @return transaction status
- */
- enum GNUNET_DB_QueryStatus
- (*find_transfers_by_hash)(void *cls,
- const struct GNUNET_HashCode *h_contract_terms,
- TALER_MERCHANTDB_TransferCallback cb,
- void *cb_cls);
-
-
- /**
* Lookup proof information about a wire transfer.
*
* @param cls closure