gnunet-svn
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[taler-merchant] 01/02: Factor out 16 new functions (shit job)


From: gnunet
Subject: [taler-merchant] 01/02: Factor out 16 new functions (shit job)
Date: Thu, 19 Oct 2023 05:26:19 +0200

This is an automated email from the git hooks/post-receive script.

ivan-avalos pushed a commit to branch master
in repository merchant.

commit 36bbe89f13b18938d7b9cb05ce6e3399052aa24e
Author: Iván Ávalos <avalos@disroot.org>
AuthorDate: Wed Oct 18 20:54:48 2023 -0600

    Factor out 16 new functions (shit job)
---
 src/backenddb/Makefile.am                        |   16 +
 src/backenddb/pg_delete_pending_webhook.c        |   48 +
 src/backenddb/pg_delete_pending_webhook.h        |   40 +
 src/backenddb/pg_delete_reserve.c                |   57 +
 src/backenddb/pg_delete_reserve.h                |   42 +
 src/backenddb/pg_delete_webhook.c                |   54 +
 src/backenddb/pg_delete_webhook.h                |   42 +
 src/backenddb/pg_insert_pickup_blind_signature.c |   58 +
 src/backenddb/pg_insert_pickup_blind_signature.h |   46 +
 src/backenddb/pg_insert_webhook.c                |   70 +
 src/backenddb/pg_insert_webhook.h                |   43 +
 src/backenddb/pg_lookup_pending_reserves.c       |  146 ++
 src/backenddb/pg_lookup_pending_reserves.h       |   41 +
 src/backenddb/pg_lookup_pickup.c                 |  174 +++
 src/backenddb/pg_lookup_pickup.h                 |   52 +
 src/backenddb/pg_lookup_reserve.c                |  241 ++++
 src/backenddb/pg_lookup_reserve.h                |   47 +
 src/backenddb/pg_lookup_reward.c                 |   84 ++
 src/backenddb/pg_lookup_reward.h                 |   53 +
 src/backenddb/pg_lookup_reward_details.c         |  208 +++
 src/backenddb/pg_lookup_reward_details.h         |   57 +
 src/backenddb/pg_lookup_rewards.c                |  221 +++
 src/backenddb/pg_lookup_rewards.h                |   50 +
 src/backenddb/pg_lookup_webhook.c                |   92 ++
 src/backenddb/pg_lookup_webhook.h                |   44 +
 src/backenddb/pg_lookup_webhook_by_event.c       |  158 ++
 src/backenddb/pg_lookup_webhook_by_event.h       |   45 +
 src/backenddb/pg_lookup_webhooks.c               |  133 ++
 src/backenddb/pg_lookup_webhooks.h               |   43 +
 src/backenddb/pg_purge_reserve.c                 |   54 +
 src/backenddb/pg_purge_reserve.h                 |   42 +
 src/backenddb/pg_update_webhook.c                |   69 +
 src/backenddb/pg_update_webhook.h                |   45 +
 src/backenddb/plugin_merchantdb_postgres.c       | 1681 +---------------------
 34 files changed, 2663 insertions(+), 1633 deletions(-)

diff --git a/src/backenddb/Makefile.am b/src/backenddb/Makefile.am
index ddf24df7..daa14832 100644
--- a/src/backenddb/Makefile.am
+++ b/src/backenddb/Makefile.am
@@ -147,6 +147,22 @@ libtaler_plugin_merchantdb_postgres_la_SOURCES = \
   pg_lookup_transfer.h pg_lookup_transfer.c \
   pg_lookup_transfer_summary.h pg_lookup_transfer_summary.c \
   pg_lookup_transfer_details.h pg_lookup_transfer_details.c \
+  pg_lookup_pending_reserves.h pg_lookup_pending_reserves.c \
+  pg_lookup_reserve.h pg_lookup_reserve.c \
+  pg_delete_reserve.h pg_delete_reserve.c \
+  pg_purge_reserve.h pg_purge_reserve.c \
+  pg_lookup_pickup.h pg_lookup_pickup.c \
+  pg_lookup_reward.h pg_lookup_reward.c \
+  pg_lookup_rewards.h pg_lookup_rewards.c \
+  pg_lookup_reward_details.h pg_lookup_reward_details.c \
+  pg_insert_pickup_blind_signature.h pg_insert_pickup_blind_signature.c \
+  pg_lookup_webhooks.h pg_lookup_webhooks.c \
+  pg_lookup_webhook.h pg_lookup_webhook.c \
+  pg_delete_webhook.h pg_delete_webhook.c \
+  pg_insert_webhook.h pg_insert_webhook.c \
+  pg_update_webhook.h pg_update_webhook.c \
+  pg_lookup_webhook_by_event.h pg_lookup_webhook_by_event.c \
+  pg_delete_pending_webhook.h pg_delete_pending_webhook.c \
   plugin_merchantdb_postgres.c \
   pg_helper.h pg_helper.c
 libtaler_plugin_merchantdb_postgres_la_LIBADD = \
diff --git a/src/backenddb/pg_delete_pending_webhook.c 
b/src/backenddb/pg_delete_pending_webhook.c
new file mode 100644
index 00000000..9121fe41
--- /dev/null
+++ b/src/backenddb/pg_delete_pending_webhook.c
@@ -0,0 +1,48 @@
+/*
+   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 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 backenddb/pg_delete_pending_webhook.c
+ * @brief Implementation of the delete_pending_webhook function for Postgres
+ * @author Iván Ávalos
+ */
+#include "platform.h"
+#include <taler/taler_error_codes.h>
+#include <taler/taler_dbevents.h>
+#include <taler/taler_pq_lib.h>
+#include "pg_delete_pending_webhook.h"
+#include "pg_helper.h"
+
+enum GNUNET_DB_QueryStatus
+TMH_PG_delete_pending_webhook (void *cls,
+                               uint64_t webhook_pending_serial)
+{
+  struct PostgresClosure *pg = cls;
+  struct GNUNET_PQ_QueryParam params[] = {
+    GNUNET_PQ_query_param_uint64 (&webhook_pending_serial),
+    GNUNET_PQ_query_param_end
+  };
+
+  check_connection (pg);
+  PREPARE (pg,
+           "delete_pending_webhook",
+           "DELETE"
+           " FROM merchant_pending_webhooks"
+           " WHERE webhook_pending_serial=$1");
+
+  return GNUNET_PQ_eval_prepared_non_select (pg->conn,
+                                             "delete_pending_webhook",
+                                             params);
+}
diff --git a/src/backenddb/pg_delete_pending_webhook.h 
b/src/backenddb/pg_delete_pending_webhook.h
new file mode 100644
index 00000000..1247cf4e
--- /dev/null
+++ b/src/backenddb/pg_delete_pending_webhook.h
@@ -0,0 +1,40 @@
+/*
+   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 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 backenddb/pg_delete_pending_webhook.h
+ * @brief implementation of the delete_pending_webhook function for Postgres
+ * @author Iván Ávalos
+ */
+#ifndef PG_DELETE_PENDING_WEBHOOK_H
+#define PG_DELETE_PENDING_WEBHOOK_H
+
+#include <taler/taler_util.h>
+#include <taler/taler_json_lib.h>
+#include "taler_merchantdb_plugin.h"
+
+/**
+ * Delete a webhook in the pending webhook after the
+ * webhook was completed successfully.
+ *
+ * @param cls closure
+ * @param webhook_pending_serial identifies the row that needs to be deleted 
in the pending webhook table
+ * @return database result code
+ */
+enum GNUNET_DB_QueryStatus
+TMH_PG_delete_pending_webhook (void *cls,
+                               uint64_t webhook_pending_serial);
+
+#endif
diff --git a/src/backenddb/pg_delete_reserve.c 
b/src/backenddb/pg_delete_reserve.c
new file mode 100644
index 00000000..f31e7c7a
--- /dev/null
+++ b/src/backenddb/pg_delete_reserve.c
@@ -0,0 +1,57 @@
+/*
+   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 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 backenddb/pg_delete_reserve.c
+ * @brief Implementation of the delete_reserve function for Postgres
+ * @author Iván Ávalos
+ */
+#include "platform.h"
+#include <taler/taler_error_codes.h>
+#include <taler/taler_dbevents.h>
+#include <taler/taler_pq_lib.h>
+#include "pg_delete_reserve.h"
+#include "pg_helper.h"
+
+enum GNUNET_DB_QueryStatus
+TMH_PG_delete_reserve (void *cls,
+                       const char *instance_id,
+                       const struct TALER_ReservePublicKeyP *reserve_pub)
+{
+  struct PostgresClosure *pg = cls;
+  struct GNUNET_PQ_QueryParam params[] = {
+    GNUNET_PQ_query_param_string (instance_id),
+    GNUNET_PQ_query_param_auto_from_type (reserve_pub),
+    GNUNET_PQ_query_param_end
+  };
+
+  check_connection (pg);
+  PREPARE (pg,
+           "delete_reserve",
+           "DELETE"
+           " FROM merchant_reward_reserve_keys"
+           " WHERE reserve_serial="
+           "   (SELECT reserve_serial"
+           "      FROM merchant_reward_reserves"
+           "       WHERE reserve_pub=$2"
+           "         AND merchant_serial="
+           "     (SELECT merchant_serial"
+           "        FROM merchant_instances"
+           "       WHERE merchant_id=$1))");
+
+  return GNUNET_PQ_eval_prepared_non_select (pg->conn,
+                                             "delete_reserve",
+                                             params);
+}
diff --git a/src/backenddb/pg_delete_reserve.h 
b/src/backenddb/pg_delete_reserve.h
new file mode 100644
index 00000000..f3aa2403
--- /dev/null
+++ b/src/backenddb/pg_delete_reserve.h
@@ -0,0 +1,42 @@
+/*
+   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 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 backenddb/pg_delete_reserve.h
+ * @brief implementation of the delete_reserve function for Postgres
+ * @author Iván Ávalos
+ */
+#ifndef PG_DELETE_RESERVE_H
+#define PG_DELETE_RESERVE_H
+
+#include <taler/taler_util.h>
+#include <taler/taler_json_lib.h>
+#include "taler_merchantdb_plugin.h"
+
+/**
+ * Delete a reserve's private key.
+ *
+ * @param cls closure, typically a connection to the db
+ * @param instance_id which instance is the reserve tied to
+ * @param reserve_pub which reserve is to be deleted
+ * @return transaction status, usually
+ *      #GNUNET_DB_STATUS_SUCCESS_ONE_RESULT for success
+ */
+enum GNUNET_DB_QueryStatus
+TMH_PG_delete_reserve (void *cls,
+                       const char *instance_id,
+                       const struct TALER_ReservePublicKeyP *reserve_pub);
+
+#endif
diff --git a/src/backenddb/pg_delete_webhook.c 
b/src/backenddb/pg_delete_webhook.c
new file mode 100644
index 00000000..ba2173cb
--- /dev/null
+++ b/src/backenddb/pg_delete_webhook.c
@@ -0,0 +1,54 @@
+/*
+   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 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 backenddb/pg_delete_webhook.c
+ * @brief Implementation of the delete_webhook function for Postgres
+ * @author Iván Ávalos
+ */
+#include "platform.h"
+#include <taler/taler_error_codes.h>
+#include <taler/taler_dbevents.h>
+#include <taler/taler_pq_lib.h>
+#include "pg_delete_webhook.h"
+#include "pg_helper.h"
+
+enum GNUNET_DB_QueryStatus
+TMH_PG_delete_webhook (void *cls,
+                       const char *instance_id,
+                       const char *webhook_id)
+{
+  struct PostgresClosure *pg = cls;
+  struct GNUNET_PQ_QueryParam params[] = {
+    GNUNET_PQ_query_param_string (instance_id),
+    GNUNET_PQ_query_param_string (webhook_id),
+    GNUNET_PQ_query_param_end
+  };
+
+  check_connection (pg);
+  PREPARE (pg,
+           "delete_webhook",
+           "DELETE"
+           " FROM merchant_webhook"
+           " WHERE merchant_webhook.merchant_serial="
+           "     (SELECT merchant_serial "
+           "        FROM merchant_instances"
+           "        WHERE merchant_id=$1)"
+           "   AND merchant_webhook.webhook_id=$2");
+
+  return GNUNET_PQ_eval_prepared_non_select (pg->conn,
+                                             "delete_webhook",
+                                             params);
+}
diff --git a/src/backenddb/pg_delete_webhook.h 
b/src/backenddb/pg_delete_webhook.h
new file mode 100644
index 00000000..02f021ab
--- /dev/null
+++ b/src/backenddb/pg_delete_webhook.h
@@ -0,0 +1,42 @@
+/*
+   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 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 backenddb/pg_delete_webhook.h
+ * @brief implementation of the delete_webhook function for Postgres
+ * @author Iván Ávalos
+ */
+#ifndef PG_DELETE_WEBHOOK_H
+#define PG_DELETE_WEBHOOK_H
+
+#include <taler/taler_util.h>
+#include <taler/taler_json_lib.h>
+#include "taler_merchantdb_plugin.h"
+
+/**
+ * Delete information about a webhook.
+ *
+ * @param cls closure
+ * @param instance_id instance to delete webhook of
+ * @param webhook_id webhook to delete
+ * @return DB status code, #GNUNET_DB_STATUS_SUCCESS_NO_RESULTS
+ *           if webhook unknown.
+ */
+enum GNUNET_DB_QueryStatus
+TMH_PG_delete_webhook (void *cls,
+                       const char *instance_id,
+                       const char *webhook_id);
+
+#endif
diff --git a/src/backenddb/pg_insert_pickup_blind_signature.c 
b/src/backenddb/pg_insert_pickup_blind_signature.c
new file mode 100644
index 00000000..89d51346
--- /dev/null
+++ b/src/backenddb/pg_insert_pickup_blind_signature.c
@@ -0,0 +1,58 @@
+/*
+   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 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 backenddb/pg_insert_pickup_blind_signature.c
+ * @brief Implementation of the insert_pickup_blind_signature function for 
Postgres
+ * @author Iván Ávalos
+ */
+#include "platform.h"
+#include <taler/taler_error_codes.h>
+#include <taler/taler_dbevents.h>
+#include <taler/taler_pq_lib.h>
+#include "pg_insert_pickup_blind_signature.h"
+#include "pg_helper.h"
+
+enum GNUNET_DB_QueryStatus
+TMH_PG_insert_pickup_blind_signature (void *cls,
+                                      const struct TALER_PickupIdentifierP 
*pickup_id,
+                                      uint32_t offset,
+                                      const struct 
TALER_BlindedDenominationSignature *blind_sig)
+{
+  struct PostgresClosure *pg = cls;
+  struct GNUNET_PQ_QueryParam params[] = {
+    GNUNET_PQ_query_param_auto_from_type (pickup_id),
+    GNUNET_PQ_query_param_uint32 (&offset),
+    TALER_PQ_query_param_blinded_denom_sig (blind_sig),
+    GNUNET_PQ_query_param_end
+  };
+
+  check_connection (pg);
+  PREPARE (pg,
+           "insert_pickup_blind_signature",
+           "INSERT INTO merchant_reward_pickup_signatures"
+           "(pickup_serial"
+           ",coin_offset"
+           ",blind_sig"
+           ") "
+           "SELECT"
+           " pickup_serial, $2, $3"
+           " FROM merchant_reward_pickups"
+           " WHERE pickup_id=$1");
+
+  return GNUNET_PQ_eval_prepared_non_select (pg->conn,
+                                             "insert_pickup_blind_signature",
+                                             params);
+}
diff --git a/src/backenddb/pg_insert_pickup_blind_signature.h 
b/src/backenddb/pg_insert_pickup_blind_signature.h
new file mode 100644
index 00000000..a4f98275
--- /dev/null
+++ b/src/backenddb/pg_insert_pickup_blind_signature.h
@@ -0,0 +1,46 @@
+/*
+   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 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 backenddb/pg_insert_pickup_blind_signature.h
+ * @brief implementation of the insert_pickup_blind_signature function for 
Postgres
+ * @author Iván Ávalos
+ */
+#ifndef PG_INSERT_PICKUP_BLIND_SIGNATURE_H
+#define PG_INSERT_PICKUP_BLIND_SIGNATURE_H
+
+#include <taler/taler_util.h>
+#include <taler/taler_json_lib.h>
+#include "taler_merchantdb_plugin.h"
+
+/**
+ * Insert blind signature obtained from the exchange during a
+ * reward pickup operation.
+ *
+ * @param cls closure, typically a connection to the db
+ * @param pickup_id unique ID for the operation
+ * @param offset offset of the blind signature for the pickup
+ * @param blind_sig the blind signature
+ * @return transaction status, usually
+ *      #GNUNET_DB_STATUS_SUCCESS_ONE_RESULT for success
+ *      #GNUNET_DB_STATUS_SUCCESS_NO_RESULTS if @a credit_uuid already known
+ */
+enum GNUNET_DB_QueryStatus
+TMH_PG_insert_pickup_blind_signature (void *cls,
+                                      const struct TALER_PickupIdentifierP 
*pickup_id,
+                                      uint32_t offset,
+                                      const struct 
TALER_BlindedDenominationSignature *blind_sig);
+
+#endif
diff --git a/src/backenddb/pg_insert_webhook.c 
b/src/backenddb/pg_insert_webhook.c
new file mode 100644
index 00000000..53049a43
--- /dev/null
+++ b/src/backenddb/pg_insert_webhook.c
@@ -0,0 +1,70 @@
+/*
+   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 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 backenddb/pg_insert_webhook.c
+ * @brief Implementation of the insert_webhook function for Postgres
+ * @author Iván Ávalos
+ */
+#include "platform.h"
+#include <taler/taler_error_codes.h>
+#include <taler/taler_dbevents.h>
+#include <taler/taler_pq_lib.h>
+#include "pg_insert_webhook.h"
+#include "pg_helper.h"
+
+enum GNUNET_DB_QueryStatus
+TMH_PG_insert_webhook (void *cls,
+                       const char *instance_id,
+                       const char *webhook_id,
+                       const struct TALER_MERCHANTDB_WebhookDetails *wb)
+{
+  struct PostgresClosure *pg = cls;
+  struct GNUNET_PQ_QueryParam params[] = {
+    GNUNET_PQ_query_param_string (instance_id),
+    GNUNET_PQ_query_param_string (webhook_id),
+    GNUNET_PQ_query_param_string (wb->event_type),
+    GNUNET_PQ_query_param_string (wb->url),
+    GNUNET_PQ_query_param_string (wb->http_method),
+    (NULL == wb->header_template)
+    ? GNUNET_PQ_query_param_null ()
+    : GNUNET_PQ_query_param_string (wb->header_template),
+    (NULL == wb->body_template)
+    ? GNUNET_PQ_query_param_null ()
+    : GNUNET_PQ_query_param_string (wb->body_template),
+    GNUNET_PQ_query_param_end
+  };
+
+  check_connection (pg);
+  PREPARE (pg,
+           "insert_webhook",
+           "INSERT INTO merchant_webhook"
+           "(merchant_serial"
+           ",webhook_id"
+           ",event_type"
+           ",url"
+           ",http_method"
+           ",header_template"
+           ",body_template"
+           ")"
+           " SELECT merchant_serial,"
+           " $2, $3, $4, $5, $6, $7"
+           " FROM merchant_instances"
+           " WHERE merchant_id=$1");
+
+  return GNUNET_PQ_eval_prepared_non_select (pg->conn,
+                                             "insert_webhook",
+                                             params);
+}
diff --git a/src/backenddb/pg_insert_webhook.h 
b/src/backenddb/pg_insert_webhook.h
new file mode 100644
index 00000000..fe89d113
--- /dev/null
+++ b/src/backenddb/pg_insert_webhook.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 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 backenddb/pg_insert_webhook.h
+ * @brief implementation of the insert_webhook function for Postgres
+ * @author Iván Ávalos
+ */
+#ifndef PG_INSERT_WEBHOOK_H
+#define PG_INSERT_WEBHOOK_H
+
+#include <taler/taler_util.h>
+#include <taler/taler_json_lib.h>
+#include "taler_merchantdb_plugin.h"
+
+/**
+ * Insert details about a particular webhook.
+ *
+ * @param cls closure
+ * @param instance_id instance to insert webhook for
+ * @param webhook_id webhook identifier of webhook to insert
+ * @param wb the webhook details to insert
+ * @return database result code
+ */
+enum GNUNET_DB_QueryStatus
+TMH_PG_insert_webhook (void *cls,
+                       const char *instance_id,
+                       const char *webhook_id,
+                       const struct TALER_MERCHANTDB_WebhookDetails *wb);
+
+#endif
diff --git a/src/backenddb/pg_lookup_pending_reserves.c 
b/src/backenddb/pg_lookup_pending_reserves.c
new file mode 100644
index 00000000..f35021c6
--- /dev/null
+++ b/src/backenddb/pg_lookup_pending_reserves.c
@@ -0,0 +1,146 @@
+/*
+   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 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 backenddb/pg_lookup_pending_reserves.c
+ * @brief Implementation of the lookup_pending_reserves function for Postgres
+ * @author Iván Ávalos
+ */
+#include "platform.h"
+#include <taler/taler_error_codes.h>
+#include <taler/taler_dbevents.h>
+#include <taler/taler_pq_lib.h>
+#include "pg_lookup_pending_reserves.h"
+#include "pg_helper.h"
+
+/**
+ * Closure for #lookup_pending_reserves_cb.
+ */
+struct LookupPendingReservesContext
+{
+  /**
+   * Postgres context.
+   */
+  struct PostgresClosure *pg;
+
+  /**
+   * Function to call with the results
+   */
+  TALER_MERCHANTDB_PendingReservesCallback cb;
+
+  /**
+   * Closure for @e cb
+   */
+  void *cb_cls;
+
+  /**
+   * Set in case of errors.
+   */
+  enum GNUNET_DB_QueryStatus qs;
+
+};
+
+
+/**
+ * Function to be called with the results of a SELECT statement
+ * that has returned @a num_results results about accounts.
+ *
+ * @param[in,out] cls of type `struct LookupReservesContext *`
+ * @param result the postgres result
+ * @param num_results the number of results in @a result
+ */
+static void
+lookup_pending_reserves_cb (void *cls,
+                            PGresult *result,
+                            unsigned int num_results)
+{
+  struct LookupPendingReservesContext *lrc = cls;
+
+  for (unsigned int i = 0; i < num_results; i++)
+  {
+    struct TALER_ReservePublicKeyP reserve_pub;
+    struct TALER_Amount merchant_initial_balance;
+    char *exchange_url;
+    char *instance_id;
+    struct GNUNET_PQ_ResultSpec rs[] = {
+      GNUNET_PQ_result_spec_auto_from_type ("reserve_pub",
+                                            &reserve_pub),
+      GNUNET_PQ_result_spec_string ("merchant_id",
+                                    &instance_id),
+      GNUNET_PQ_result_spec_string ("exchange_url",
+                                    &exchange_url),
+      TALER_PQ_result_spec_amount_with_currency ("merchant_initial_balance",
+                                                 &merchant_initial_balance),
+      GNUNET_PQ_result_spec_end
+    };
+
+    if (GNUNET_OK !=
+        GNUNET_PQ_extract_result (result,
+                                  rs,
+                                  i))
+    {
+      GNUNET_break (0);
+      lrc->qs = GNUNET_DB_STATUS_HARD_ERROR;
+      return;
+    }
+    lrc->cb (lrc->cb_cls,
+             instance_id,
+             exchange_url,
+             &reserve_pub,
+             &merchant_initial_balance);
+    GNUNET_PQ_cleanup_result (rs);
+  }
+}
+
+
+enum GNUNET_DB_QueryStatus
+TMH_PG_lookup_pending_reserves (void *cls,
+                                TALER_MERCHANTDB_PendingReservesCallback cb,
+                                void *cb_cls)
+{
+  struct PostgresClosure *pg = cls;
+  struct LookupPendingReservesContext lrc = {
+    .pg = pg,
+    .cb = cb,
+    .cb_cls = cb_cls
+  };
+  struct GNUNET_PQ_QueryParam params[] = {
+    GNUNET_PQ_query_param_end
+  };
+  enum GNUNET_DB_QueryStatus qs;
+
+  check_connection (pg);
+  PREPARE (pg,
+           "lookup_pending_reserves",
+           "SELECT"
+           " reserve_pub"
+           ",merchant_id"
+           ",exchange_url"
+           ",merchant_initial_balance"
+           " FROM merchant_reward_reserves mrr"
+           " JOIN merchant_instances USING (merchant_serial)"
+           " JOIN merchant_reward_reserve_keys USING (reserve_serial)"
+           " WHERE (mrr.exchange_initial_balance).val=0"
+           "   AND (mrr.exchange_initial_balance).frac=0");
+
+  qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn,
+                                             "lookup_pending_reserves",
+                                             params,
+                                             &lookup_pending_reserves_cb,
+                                             &lrc);
+  if (lrc.qs < 0)
+    return lrc.qs;
+  return qs;
+}
diff --git a/src/backenddb/pg_lookup_pending_reserves.h 
b/src/backenddb/pg_lookup_pending_reserves.h
new file mode 100644
index 00000000..4ffff78f
--- /dev/null
+++ b/src/backenddb/pg_lookup_pending_reserves.h
@@ -0,0 +1,41 @@
+/*
+   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 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 backenddb/pg_lookup_pending_reserves.h
+ * @brief implementation of the lookup_pending_reserves function for Postgres
+ * @author Iván Ávalos
+ */
+#ifndef PG_LOOKUP_PENDING_RESERVES_H
+#define PG_LOOKUP_PENDING_RESERVES_H
+
+#include <taler/taler_util.h>
+#include <taler/taler_json_lib.h>
+#include "taler_merchantdb_plugin.h"
+
+/**
+ * Lookup reserves pending activation across all instances.
+ *
+ * @param cls closure
+ * @param cb function to call with reserve summary data
+ * @param cb_cls closure for @a cb
+ * @return transaction status
+ */
+enum GNUNET_DB_QueryStatus
+TMH_PG_lookup_pending_reserves (void *cls,
+                                TALER_MERCHANTDB_PendingReservesCallback cb,
+                                void *cb_cls);
+
+#endif
diff --git a/src/backenddb/pg_lookup_pickup.c b/src/backenddb/pg_lookup_pickup.c
new file mode 100644
index 00000000..f10b948b
--- /dev/null
+++ b/src/backenddb/pg_lookup_pickup.c
@@ -0,0 +1,174 @@
+/*
+   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 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 backenddb/pg_lookup_pickup.c
+ * @brief Implementation of the lookup_pickup function for Postgres
+ * @author Iván Ávalos
+ */
+#include "platform.h"
+#include <taler/taler_error_codes.h>
+#include <taler/taler_dbevents.h>
+#include <taler/taler_pq_lib.h>
+#include "pg_lookup_pickup.h"
+#include "pg_helper.h"
+
+/**
+ * Closure for #lookup_signatures_cb().
+ */
+struct LookupSignaturesContext
+{
+  /**
+   * Length of the @e sigs array
+   */
+  unsigned int sigs_length;
+
+  /**
+   * Where to store the signatures.
+   */
+  struct TALER_BlindedDenominationSignature *sigs;
+};
+
+
+/**
+ * Function to be called with the results of a SELECT statement
+ * that has returned @a num_results results about accounts.
+ *
+ * @param[in,out] cls of type `struct LookupSignaturesContext *`
+ * @param result the postgres result
+ * @param num_results the number of results in @a result
+ */
+static void
+lookup_signatures_cb (void *cls,
+                      PGresult *result,
+                      unsigned int num_results)
+{
+  struct LookupSignaturesContext *lsc = cls;
+
+  for (unsigned int i = 0; i < num_results; i++)
+  {
+    uint32_t offset;
+    struct TALER_BlindedDenominationSignature bsig;
+    struct GNUNET_PQ_ResultSpec rs[] = {
+      GNUNET_PQ_result_spec_uint32 ("coin_offset",
+                                    &offset),
+      TALER_PQ_result_spec_blinded_denom_sig ("blind_sig",
+                                              &bsig),
+      GNUNET_PQ_result_spec_end
+    };
+
+    if (GNUNET_OK !=
+        GNUNET_PQ_extract_result (result,
+                                  rs,
+                                  i))
+    {
+      GNUNET_break (0);
+      return;
+    }
+    if (offset >= lsc->sigs_length)
+    {
+      GNUNET_break_op (0);
+      GNUNET_PQ_cleanup_result (rs);
+      continue;
+    }
+    /* Must be NULL due to UNIQUE constraint on offset and
+       requirement that client launched us with 'sigs'
+       pre-initialized to NULL. */
+    lsc->sigs[offset] = bsig;
+  }
+}
+
+
+enum GNUNET_DB_QueryStatus
+TMH_PG_lookup_pickup (void *cls,
+                      const char *instance_id,
+                      const struct TALER_RewardIdentifierP *reward_id,
+                      const struct TALER_PickupIdentifierP *pickup_id,
+                      char **exchange_url,
+                      struct TALER_ReservePrivateKeyP *reserve_priv,
+                      unsigned int sigs_length,
+                      struct TALER_BlindedDenominationSignature sigs[])
+{
+  struct PostgresClosure *pg = cls;
+  uint64_t pickup_serial;
+
+  {
+    struct GNUNET_PQ_QueryParam params[] = {
+      GNUNET_PQ_query_param_string (instance_id),
+      GNUNET_PQ_query_param_auto_from_type (reward_id),
+      GNUNET_PQ_query_param_auto_from_type (pickup_id),
+      GNUNET_PQ_query_param_end
+    };
+    struct GNUNET_PQ_ResultSpec rs[] = {
+      GNUNET_PQ_result_spec_string ("exchange_url",
+                                    exchange_url),
+      GNUNET_PQ_result_spec_auto_from_type ("reserve_priv",
+                                            reserve_priv),
+      GNUNET_PQ_result_spec_uint64 ("pickup_serial",
+                                    &pickup_serial),
+      GNUNET_PQ_result_spec_end
+    };
+    enum GNUNET_DB_QueryStatus qs;
+
+    check_connection (pg);
+    PREPARE (pg,
+             "lookup_pickup",
+             "SELECT"
+             " exchange_url"
+             ",reserve_priv"
+             ",pickup_serial"
+             " FROM merchant_reward_pickups"
+             " JOIN merchant_rewards USING (reward_serial)"
+             " JOIN merchant_reward_reserves USING (reserve_serial)"
+             " JOIN merchant_reward_reserve_keys USING (reserve_serial)"
+             " WHERE pickup_id = $3"
+             "   AND reward_id = $2"
+             "   AND merchant_serial ="
+             "     (SELECT merchant_serial"
+             "        FROM merchant_instances"
+             "       WHERE merchant_id=$1)");
+
+    qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
+                                                   "lookup_pickup",
+                                                   params,
+                                                   rs);
+    if (qs <= 0)
+      return qs;
+  }
+  {
+    struct GNUNET_PQ_QueryParam params[] = {
+      GNUNET_PQ_query_param_uint64 (&pickup_serial),
+      GNUNET_PQ_query_param_end
+    };
+    struct LookupSignaturesContext lsc = {
+      .sigs_length = sigs_length,
+      .sigs = sigs
+    };
+
+    PREPARE (pg,
+             "lookup_pickup_signatures",
+             "SELECT"
+             " coin_offset"
+             ",blind_sig"
+             " FROM merchant_reward_pickup_signatures"
+             " WHERE pickup_serial = $1");
+
+    return GNUNET_PQ_eval_prepared_multi_select (pg->conn,
+                                                 "lookup_pickup_signatures",
+                                                 params,
+                                                 &lookup_signatures_cb,
+                                                 &lsc);
+  }
+}
diff --git a/src/backenddb/pg_lookup_pickup.h b/src/backenddb/pg_lookup_pickup.h
new file mode 100644
index 00000000..b3814731
--- /dev/null
+++ b/src/backenddb/pg_lookup_pickup.h
@@ -0,0 +1,52 @@
+/*
+   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 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 backenddb/pg_lookup_pickup.h
+ * @brief implementation of the lookup_pickup function for Postgres
+ * @author Iván Ávalos
+ */
+#ifndef PG_LOOKUP_PICKUP_H
+#define PG_LOOKUP_PICKUP_H
+
+#include <taler/taler_util.h>
+#include <taler/taler_json_lib.h>
+#include "taler_merchantdb_plugin.h"
+
+/**
+ * Lookup pickup details for pickup @a pickup_id.
+ *
+ * @param cls closure, typically a connection to the db
+ * @param instance_id which instance should we lookup reward details for
+ * @param reward_id which reward should we lookup details on
+ * @param pickup_id which pickup should we lookup details on
+ * @param[out] exchange_url which exchange is the reward withdrawn from
+ * @param[out] reserve_priv private key the reward is withdrawn from (set if 
still available!)
+ * @param sigs_length length of the @a sigs array
+ * @param[out] sigs set to the (blind) signatures we have for this @a 
pickup_id,
+ *              those that are unavailable are left at NULL
+ * @return transaction status
+ */
+enum GNUNET_DB_QueryStatus
+TMH_PG_lookup_pickup (void *cls,
+                      const char *instance_id,
+                      const struct TALER_RewardIdentifierP *reward_id,
+                      const struct TALER_PickupIdentifierP *pickup_id,
+                      char **exchange_url,
+                      struct TALER_ReservePrivateKeyP *reserve_priv,
+                      unsigned int sigs_length,
+                      struct TALER_BlindedDenominationSignature sigs[]);
+
+#endif
diff --git a/src/backenddb/pg_lookup_reserve.c 
b/src/backenddb/pg_lookup_reserve.c
new file mode 100644
index 00000000..392db057
--- /dev/null
+++ b/src/backenddb/pg_lookup_reserve.c
@@ -0,0 +1,241 @@
+/*
+   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 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 backenddb/pg_lookup_reserve.c
+ * @brief Implementation of the lookup_reserve function for Postgres
+ * @author Iván Ávalos
+ */
+#include "platform.h"
+#include <taler/taler_error_codes.h>
+#include <taler/taler_dbevents.h>
+#include <taler/taler_pq_lib.h>
+#include "pg_lookup_reserve.h"
+#include "pg_helper.h"
+
+/**
+ * Closure for #lookup_reserve_rewards_cb().
+ */
+struct LookupRewardsContext
+{
+  /**
+   * Postgres context.
+   */
+  struct PostgresClosure *pg;
+
+  /**
+   * Array with information about rewards generated from this reserve.
+   */
+  struct TALER_MERCHANTDB_RewardDetails *rewards;
+
+  /**
+   * Length of the @e rewards array.
+   */
+  unsigned int rewards_length;
+
+  /**
+   * Set in case of errors.
+   */
+  enum GNUNET_DB_QueryStatus qs;
+};
+
+
+/**
+ * Function to be called with the results of a SELECT statement
+ * that has returned @a num_results results about accounts.
+ *
+ * @param[in,out] cls of type `struct LookupRewardsContext *`
+ * @param result the postgres result
+ * @param num_results the number of results in @a result
+ */
+static void
+lookup_reserve_rewards_cb (void *cls,
+                           PGresult *result,
+                           unsigned int num_results)
+{
+  struct LookupRewardsContext *ltc = cls;
+
+  GNUNET_array_grow (ltc->rewards,
+                     ltc->rewards_length,
+                     num_results);
+  for (unsigned int i = 0; i < num_results; i++)
+  {
+    struct TALER_MERCHANTDB_RewardDetails *td = &ltc->rewards[i];
+    struct GNUNET_PQ_ResultSpec rs[] = {
+      GNUNET_PQ_result_spec_string ("justification",
+                                    &td->reason),
+      GNUNET_PQ_result_spec_auto_from_type ("reward_id",
+                                            &td->reward_id),
+      TALER_PQ_result_spec_amount_with_currency ("amount",
+                                                 &td->total_amount),
+      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;
+    }
+  }
+}
+
+
+enum GNUNET_DB_QueryStatus
+TMH_PG_lookup_reserve (void *cls,
+                       const char *instance_id,
+                       const struct TALER_ReservePublicKeyP *reserve_pub,
+                       bool fetch_rewards,
+                       TALER_MERCHANTDB_ReserveDetailsCallback cb,
+                       void *cb_cls)
+{
+  struct PostgresClosure *pg = cls;
+  struct LookupRewardsContext ltc = {
+    .pg = pg,
+    .qs = GNUNET_DB_STATUS_SUCCESS_ONE_RESULT
+  };
+  struct GNUNET_PQ_QueryParam params[] = {
+    GNUNET_PQ_query_param_string (instance_id),
+    GNUNET_PQ_query_param_auto_from_type (reserve_pub),
+    GNUNET_PQ_query_param_end
+  };
+  struct GNUNET_TIME_Timestamp creation_time;
+  struct GNUNET_TIME_Timestamp expiration_time;
+  struct TALER_Amount merchant_initial_balance;
+  struct TALER_Amount exchange_initial_balance;
+  struct TALER_Amount pickup_amount;
+  struct TALER_Amount committed_amount;
+  struct TALER_MasterPublicKeyP master_pub;
+  bool active;
+  char *exchange_url = NULL;
+  struct GNUNET_PQ_ResultSpec rs[] = {
+    GNUNET_PQ_result_spec_timestamp ("creation_time",
+                                     &creation_time),
+    GNUNET_PQ_result_spec_timestamp ("expiration",
+                                     &expiration_time),
+    TALER_PQ_result_spec_amount_with_currency ("merchant_initial_balance",
+                                               &merchant_initial_balance),
+    TALER_PQ_result_spec_amount_with_currency ("exchange_initial_balance",
+                                               &exchange_initial_balance),
+    TALER_PQ_result_spec_amount_with_currency ("rewards_picked_up",
+                                               &pickup_amount),
+    TALER_PQ_result_spec_amount_with_currency ("rewards_committed",
+                                               &committed_amount),
+    GNUNET_PQ_result_spec_auto_from_type ("master_pub",
+                                          &master_pub),
+    GNUNET_PQ_result_spec_bool ("active",
+                                &active),
+    GNUNET_PQ_result_spec_allow_null (
+      GNUNET_PQ_result_spec_string ("exchange_url",
+                                    &exchange_url),
+      NULL),
+    GNUNET_PQ_result_spec_end
+  };
+  enum GNUNET_DB_QueryStatus qs;
+
+  check_connection (pg);
+  PREPARE (pg,
+           "lookup_reserve",
+           "SELECT"
+           " creation_time"
+           ",expiration"
+           ",merchant_initial_balance"
+           ",exchange_initial_balance"
+           ",rewards_committed"
+           ",rewards_picked_up"
+           ",reserve_priv IS NOT NULL AS active"
+           ",exchange_url"
+           ",master_pub"
+           " FROM merchant_reward_reserves"
+           " FULL OUTER JOIN merchant_reward_reserve_keys USING 
(reserve_serial)"
+           " WHERE reserve_pub = $2"
+           "   AND merchant_serial ="
+           "     (SELECT merchant_serial"
+           "        FROM merchant_instances"
+           "       WHERE merchant_id=$1)");
+
+  qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
+                                                 "lookup_reserve",
+                                                 params,
+                                                 rs);
+  if (qs < 0)
+    return qs;
+  if (! fetch_rewards)
+  {
+    cb (cb_cls,
+        creation_time,
+        expiration_time,
+        &merchant_initial_balance,
+        &exchange_initial_balance,
+        &pickup_amount,
+        &committed_amount,
+        active,
+        &master_pub,
+        exchange_url,
+        0,
+        NULL);
+    GNUNET_PQ_cleanup_result (rs);
+    return qs;
+  }
+
+  PREPARE (pg,
+           "lookup_reserve_rewards",
+           "SELECT"
+           " justification"
+           ",reward_id"
+           ",amount"
+           " FROM merchant_rewards"
+           " WHERE reserve_serial ="
+           "  (SELECT reserve_serial"
+           "     FROM merchant_reward_reserves"
+           "      WHERE reserve_pub=$2"
+           "        AND merchant_serial ="
+           "       (SELECT merchant_serial"
+           "          FROM merchant_instances"
+           "         WHERE merchant_id=$1))");
+
+  qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn,
+                                             "lookup_reserve_rewards",
+                                             params,
+                                             &lookup_reserve_rewards_cb,
+                                             &ltc);
+  if (qs < 0)
+    return qs;
+  if (ltc.qs >= 0)
+  {
+    cb (cb_cls,
+        creation_time,
+        expiration_time,
+        &merchant_initial_balance,
+        &exchange_initial_balance,
+        &pickup_amount,
+        &committed_amount,
+        active,
+        &master_pub,
+        exchange_url,
+        ltc.rewards_length,
+        ltc.rewards);
+  }
+  for (unsigned int i = 0; i<ltc.rewards_length; i++)
+    GNUNET_free (ltc.rewards[i].reason);
+  GNUNET_array_grow (ltc.rewards,
+                     ltc.rewards_length,
+                     0);
+  GNUNET_PQ_cleanup_result (rs);
+  return ltc.qs;
+}
diff --git a/src/backenddb/pg_lookup_reserve.h 
b/src/backenddb/pg_lookup_reserve.h
new file mode 100644
index 00000000..53bb05f8
--- /dev/null
+++ b/src/backenddb/pg_lookup_reserve.h
@@ -0,0 +1,47 @@
+/*
+   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 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 backenddb/pg_lookup_reserve.h
+ * @brief implementation of the lookup_reserve function for Postgres
+ * @author Iván Ávalos
+ */
+#ifndef PG_LOOKUP_RESERVE_H
+#define PG_LOOKUP_RESERVE_H
+
+#include <taler/taler_util.h>
+#include <taler/taler_json_lib.h>
+#include "taler_merchantdb_plugin.h"
+
+/**
+ * Lookup reserve details.
+ *
+ * @param cls closure
+ * @param instance_id instance to lookup payments for
+ * @param reserve_pub public key of the reserve to inspect
+ * @param fetch_rewards if true, also return information about rewards
+ * @param cb function to call with reserve summary data
+ * @param cb_cls closure for @a cb
+ * @return transaction status
+ */
+enum GNUNET_DB_QueryStatus
+TMH_PG_lookup_reserve (void *cls,
+                       const char *instance_id,
+                       const struct TALER_ReservePublicKeyP *reserve_pub,
+                       bool fetch_rewards,
+                       TALER_MERCHANTDB_ReserveDetailsCallback cb,
+                       void *cb_cls);
+
+#endif
diff --git a/src/backenddb/pg_lookup_reward.c b/src/backenddb/pg_lookup_reward.c
new file mode 100644
index 00000000..cb887586
--- /dev/null
+++ b/src/backenddb/pg_lookup_reward.c
@@ -0,0 +1,84 @@
+/*
+   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 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 backenddb/pg_lookup_reward.c
+ * @brief Implementation of the lookup_reward function for Postgres
+ * @author Iván Ávalos
+ */
+#include "platform.h"
+#include <taler/taler_error_codes.h>
+#include <taler/taler_dbevents.h>
+#include <taler/taler_pq_lib.h>
+#include "pg_lookup_reward.h"
+#include "pg_helper.h"
+
+enum GNUNET_DB_QueryStatus
+TMH_PG_lookup_reward (void *cls,
+                      const char *instance_id,
+                      const struct TALER_RewardIdentifierP *reward_id,
+                      struct TALER_Amount *total_authorized,
+                      struct TALER_Amount *total_picked_up,
+                      struct GNUNET_TIME_Timestamp *expiration,
+                      char **exchange_url,
+                      char **next_url,
+                      struct TALER_ReservePrivateKeyP *reserve_priv)
+{
+  struct PostgresClosure *pg = cls;
+  struct GNUNET_PQ_QueryParam params[] = {
+    GNUNET_PQ_query_param_string (instance_id),
+    GNUNET_PQ_query_param_auto_from_type (reward_id),
+    GNUNET_PQ_query_param_end
+  };
+  struct GNUNET_PQ_ResultSpec rs[] = {
+    TALER_PQ_result_spec_amount_with_currency ("amount",
+                                               total_authorized),
+    TALER_PQ_result_spec_amount_with_currency ("picked_up",
+                                               total_picked_up),
+    GNUNET_PQ_result_spec_timestamp ("expiration",
+                                     expiration),
+    GNUNET_PQ_result_spec_string ("exchange_url",
+                                  exchange_url),
+    GNUNET_PQ_result_spec_string ("next_url",
+                                  next_url),
+    GNUNET_PQ_result_spec_auto_from_type ("reserve_priv",
+                                          reserve_priv),
+    GNUNET_PQ_result_spec_end
+  };
+
+  check_connection (pg);
+  PREPARE (pg,
+           "lookup_reward",
+           "SELECT"
+           " amount"
+           ",picked_up"
+           ",merchant_rewards.expiration"
+           ",exchange_url"
+           ",next_url"
+           ",reserve_priv"
+           " FROM merchant_rewards"
+           " JOIN merchant_reward_reserves USING (reserve_serial)"
+           " JOIN merchant_reward_reserve_keys USING (reserve_serial)"
+           " WHERE reward_id = $2"
+           "   AND merchant_serial ="
+           "     (SELECT merchant_serial"
+           "        FROM merchant_instances"
+           "       WHERE merchant_id=$1)");
+
+  return GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
+                                                   "lookup_reward",
+                                                   params,
+                                                   rs);
+}
diff --git a/src/backenddb/pg_lookup_reward.h b/src/backenddb/pg_lookup_reward.h
new file mode 100644
index 00000000..fc23c9ea
--- /dev/null
+++ b/src/backenddb/pg_lookup_reward.h
@@ -0,0 +1,53 @@
+/*
+   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 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 backenddb/pg_lookup_reward.h
+ * @brief implementation of the lookup_reward function for Postgres
+ * @author Iván Ávalos
+ */
+#ifndef PG_LOOKUP_REWARD_H
+#define PG_LOOKUP_REWARD_H
+
+#include <taler/taler_util.h>
+#include <taler/taler_json_lib.h>
+#include "taler_merchantdb_plugin.h"
+
+/**
+ * Lookup reward details for reward @a reward_id.
+ *
+ * @param cls closure, typically a connection to the db
+ * @param instance_id which instance should we lookup reward details for
+ * @param reward_id which reward should we lookup details on
+ * @param[out] total_authorized amount how high is the reward (with fees)
+ * @param[out] total_picked_up how much of the reward was so far picked up 
(with fees)
+ * @param[out] expiration set to when the reward expires
+ * @param[out] exchange_url set to the exchange URL where the reserve is
+ * @param[out] next_url set to the URL where the wallet should navigate after 
getting the reward
+ * @param[out] reserve_priv set to private key of reserve to be debited
+ * @return transaction status
+ */
+enum GNUNET_DB_QueryStatus
+TMH_PG_lookup_reward (void *cls,
+                      const char *instance_id,
+                      const struct TALER_RewardIdentifierP *reward_id,
+                      struct TALER_Amount *total_authorized,
+                      struct TALER_Amount *total_picked_up,
+                      struct GNUNET_TIME_Timestamp *expiration,
+                      char **exchange_url,
+                      char **next_url,
+                      struct TALER_ReservePrivateKeyP *reserve_priv);
+
+#endif
diff --git a/src/backenddb/pg_lookup_reward_details.c 
b/src/backenddb/pg_lookup_reward_details.c
new file mode 100644
index 00000000..062fbdd4
--- /dev/null
+++ b/src/backenddb/pg_lookup_reward_details.c
@@ -0,0 +1,208 @@
+/*
+   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 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 backenddb/pg_lookup_reward_details.c
+ * @brief Implementation of the lookup_reward_details function for Postgres
+ * @author Iván Ávalos
+ */
+#include "platform.h"
+#include <taler/taler_error_codes.h>
+#include <taler/taler_dbevents.h>
+#include <taler/taler_pq_lib.h>
+#include "pg_lookup_reward_details.h"
+#include "pg_helper.h"
+
+/**
+ * Closure for #lookup_pickup_details_cb().
+ */
+struct LookupRewardDetailsContext
+{
+  /**
+   * Length of the @e sigs array
+   */
+  unsigned int *pickups_length;
+
+  /**
+   * Where to store the signatures.
+   */
+  struct TALER_MERCHANTDB_PickupDetails **pickups;
+
+  /**
+   * Database handle.
+   */
+  struct PostgresClosure *pg;
+
+  /**
+   * Transaction status.
+   */
+  enum GNUNET_DB_QueryStatus qs;
+
+};
+
+
+/**
+ * Function to be called with the results of a SELECT statement
+ * that has returned @a num_results results about pickups.
+ *
+ * @param[in,out] cls of type `struct LookupRewardDetailsContext *`
+ * @param result the postgres result
+ * @param num_results the number of results in @a result
+ */
+static void
+lookup_pickup_details_cb (void *cls,
+                          PGresult *result,
+                          unsigned int num_results)
+{
+  struct LookupRewardDetailsContext *ltdc = cls;
+
+  *ltdc->pickups_length = num_results;
+  *ltdc->pickups = GNUNET_new_array (num_results,
+                                     struct TALER_MERCHANTDB_PickupDetails);
+  for (unsigned int i = 0; i < num_results; i++)
+  {
+    struct TALER_MERCHANTDB_PickupDetails *pd = &((*ltdc->pickups)[i]);
+    uint64_t num_planchets = 0;
+    struct GNUNET_PQ_ResultSpec rs[] = {
+      GNUNET_PQ_result_spec_auto_from_type ("pickup_id",
+                                            &pd->pickup_id),
+      TALER_PQ_result_spec_amount_with_currency ("amount",
+                                                 &pd->requested_amount),
+      GNUNET_PQ_result_spec_uint64 ("num_planchets",
+                                    &num_planchets),
+      GNUNET_PQ_result_spec_end
+    };
+
+    if (GNUNET_OK !=
+        GNUNET_PQ_extract_result (result,
+                                  rs,
+                                  i))
+    {
+      GNUNET_break (0);
+      ltdc->qs = GNUNET_DB_STATUS_HARD_ERROR;
+      GNUNET_array_grow (*ltdc->pickups,
+                         *ltdc->pickups_length,
+                         0);
+      return;
+    }
+
+    pd->num_planchets = num_planchets;
+  }
+}
+
+
+enum GNUNET_DB_QueryStatus
+TMH_PG_lookup_reward_details (void *cls,
+                              const char *instance_id,
+                              const struct TALER_RewardIdentifierP *reward_id,
+                              bool fpu,
+                              struct TALER_Amount *total_authorized,
+                              struct TALER_Amount *total_picked_up,
+                              char **justification,
+                              struct GNUNET_TIME_Timestamp *expiration,
+                              struct TALER_ReservePublicKeyP *reserve_pub,
+                              unsigned int *pickups_length,
+                              struct TALER_MERCHANTDB_PickupDetails **pickups)
+{
+  struct PostgresClosure *pg = cls;
+  uint64_t reward_serial;
+  enum GNUNET_DB_QueryStatus qs;
+  {
+    struct GNUNET_PQ_QueryParam params[] = {
+      GNUNET_PQ_query_param_string (instance_id),
+      GNUNET_PQ_query_param_auto_from_type (reward_id),
+      GNUNET_PQ_query_param_end
+    };
+    struct GNUNET_PQ_ResultSpec rs[] = {
+      GNUNET_PQ_result_spec_uint64 ("reward_serial",
+                                    &reward_serial),
+      TALER_PQ_result_spec_amount_with_currency ("amount",
+                                                 total_authorized),
+      TALER_PQ_result_spec_amount_with_currency ("picked_up",
+                                                 total_picked_up),
+      GNUNET_PQ_result_spec_string ("justification",
+                                    justification),
+      GNUNET_PQ_result_spec_timestamp ("expiration",
+                                       expiration),
+      GNUNET_PQ_result_spec_auto_from_type ("reserve_pub",
+                                            reserve_pub),
+      GNUNET_PQ_result_spec_end
+    };
+
+    check_connection (pg);
+    PREPARE (pg,
+             "lookup_reward_details",
+             "SELECT"
+             " reward_serial"
+             ",amount"
+             ",picked_up"
+             ",justification"
+             ",merchant_rewards.expiration"
+             ",reserve_pub"
+             " FROM merchant_rewards"
+             " JOIN merchant_reward_reserves USING (reserve_serial)"
+             " WHERE reward_id = $2"
+             "   AND merchant_serial ="
+             "     (SELECT merchant_serial"
+             "        FROM merchant_instances"
+             "       WHERE merchant_id=$1)");
+
+    qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
+                                                   "lookup_reward_details",
+                                                   params,
+                                                   rs);
+    if (qs <= 0)
+      return qs;
+    if (! fpu)
+    {
+      *pickups_length = 0;
+      *pickups = NULL;
+      return qs;
+    }
+  }
+  {
+    struct GNUNET_PQ_QueryParam params[] = {
+      GNUNET_PQ_query_param_uint64 (&reward_serial),
+      GNUNET_PQ_query_param_end
+    };
+
+    struct LookupRewardDetailsContext ltdc = {
+      .pickups_length = pickups_length,
+      .pickups = pickups,
+      .pg = pg,
+      .qs = GNUNET_DB_STATUS_SUCCESS_ONE_RESULT
+    };
+
+    PREPARE (pg,
+             "lookup_pickup_details",
+             "SELECT"
+             " pickup_id"
+             ",amount"
+             ",COUNT(blind_sig) AS num_planchets"
+             " FROM merchant_reward_pickups"
+             " JOIN merchant_reward_pickup_signatures USING (pickup_serial)"
+             " WHERE reward_serial = $1"
+             " GROUP BY pickup_serial");
+
+    qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn,
+                                               "lookup_pickup_details",
+                                               params,
+                                               &lookup_pickup_details_cb,
+                                               &ltdc);
+    if (qs < 0)
+      return qs;
+    return ltdc.qs;
+  }
+}
diff --git a/src/backenddb/pg_lookup_reward_details.h 
b/src/backenddb/pg_lookup_reward_details.h
new file mode 100644
index 00000000..61ff301f
--- /dev/null
+++ b/src/backenddb/pg_lookup_reward_details.h
@@ -0,0 +1,57 @@
+/*
+   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 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 backenddb/pg_lookup_reward_details.h
+ * @brief implementation of the lookup_reward_details function for Postgres
+ * @author Iván Ávalos
+ */
+#ifndef PG_LOOKUP_REWARD_DETAILS_H
+#define PG_LOOKUP_REWARD_DETAILS_H
+
+#include <taler/taler_util.h>
+#include <taler/taler_json_lib.h>
+#include "taler_merchantdb_plugin.h"
+
+/**
+ * Lookup reward details for reward @a reward_id.
+ *
+ * @param cls closure, typically a connection to the db
+ * @param instance_id which instance should we lookup reward details for
+ * @param reward_id which reward should we lookup details on
+ * @param fpu should we fetch details about individual pickups
+ * @param[out] total_authorized amount how high is the reward (with fees)
+ * @param[out] total_picked_up how much of the reward was so far picked up 
(with fees)
+ * @param[out] justification why was the reward approved
+ * @param[out] expiration set to when the reward expires
+ * @param[out] reserve_pub set to which reserve is debited
+ * @param[out] pickups_length set to the length of @e pickups
+ * @param[out] pickups if @a fpu is true, set to details about the pickup 
operations
+ * @return transaction status,
+ */
+enum GNUNET_DB_QueryStatus
+TMH_PG_lookup_reward_details (void *cls,
+                              const char *instance_id,
+                              const struct TALER_RewardIdentifierP *reward_id,
+                              bool fpu,
+                              struct TALER_Amount *total_authorized,
+                              struct TALER_Amount *total_picked_up,
+                              char **justification,
+                              struct GNUNET_TIME_Timestamp *expiration,
+                              struct TALER_ReservePublicKeyP *reserve_pub,
+                              unsigned int *pickups_length,
+                              struct TALER_MERCHANTDB_PickupDetails **pickups);
+
+#endif
diff --git a/src/backenddb/pg_lookup_rewards.c 
b/src/backenddb/pg_lookup_rewards.c
new file mode 100644
index 00000000..4914ad58
--- /dev/null
+++ b/src/backenddb/pg_lookup_rewards.c
@@ -0,0 +1,221 @@
+/*
+   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 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 backenddb/pg_lookup_rewards.c
+ * @brief Implementation of the lookup_rewards function for Postgres
+ * @author Iván Ávalos
+ */
+#include "platform.h"
+#include <taler/taler_error_codes.h>
+#include <taler/taler_dbevents.h>
+#include <taler/taler_pq_lib.h>
+#include "pg_lookup_rewards.h"
+#include "pg_helper.h"
+
+/**
+ * Context used for postgres_lookup_rewards().
+ */
+struct LookupMerchantRewardsContext
+{
+  /**
+   * Postgres context.
+   */
+  struct PostgresClosure *pg;
+
+  /**
+   * Function to call with the results.
+   */
+  TALER_MERCHANTDB_RewardsCallback cb;
+
+  /**
+   * Closure for @a cb.
+   */
+  void *cb_cls;
+
+  /**
+   * Internal result.
+   */
+  enum GNUNET_DB_QueryStatus qs;
+};
+
+
+/**
+ * Function to be called with the results of a SELECT statement
+ * that has returned @a num_results results about rewards.
+ *
+ * @param[in,out] cls of type `struct LookupRewardsContext *`
+ * @param result the postgres result
+ * @param num_results the number of results in @a result
+ */
+static void
+lookup_rewards_cb (void *cls,
+                   PGresult *result,
+                   unsigned int num_results)
+{
+  struct LookupMerchantRewardsContext *plc = cls;
+
+  for (unsigned int i = 0; i < num_results; i++)
+  {
+    uint64_t row_id;
+    struct TALER_RewardIdentifierP reward_id;
+    struct TALER_Amount reward_amount;
+    struct GNUNET_PQ_ResultSpec rs[] = {
+      GNUNET_PQ_result_spec_uint64 ("reward_serial",
+                                    &row_id),
+      GNUNET_PQ_result_spec_auto_from_type ("reward_id",
+                                            &reward_id),
+      TALER_PQ_result_spec_amount_with_currency ("amount",
+                                                 &reward_amount),
+      GNUNET_PQ_result_spec_end
+    };
+
+    if (GNUNET_OK !=
+        GNUNET_PQ_extract_result (result,
+                                  rs,
+                                  i))
+    {
+      GNUNET_break (0);
+      plc->qs = GNUNET_DB_STATUS_HARD_ERROR;
+      return;
+    }
+    plc->cb (plc->cb_cls,
+             row_id,
+             reward_id,
+             reward_amount);
+    GNUNET_PQ_cleanup_result (rs);
+  }
+}
+
+
+enum GNUNET_DB_QueryStatus
+TMH_PG_lookup_rewards (void *cls,
+                       const char *instance_id,
+                       enum TALER_EXCHANGE_YesNoAll expired,
+                       int64_t limit,
+                       uint64_t offset,
+                       TALER_MERCHANTDB_RewardsCallback cb,
+                       void *cb_cls)
+{
+  struct PostgresClosure *pg = cls;
+  struct LookupMerchantRewardsContext plc = {
+    .pg = pg,
+    .cb = cb,
+    .cb_cls = cb_cls
+  };
+  uint64_t ulimit = (limit > 0) ? limit : -limit;
+  uint8_t bexpired;
+  struct GNUNET_TIME_Absolute now = GNUNET_TIME_absolute_get ();
+  struct GNUNET_PQ_QueryParam params[] = {
+    GNUNET_PQ_query_param_string (instance_id),
+    GNUNET_PQ_query_param_uint64 (&ulimit),
+    GNUNET_PQ_query_param_uint64 (&offset),
+    GNUNET_PQ_query_param_absolute_time (&now),
+    GNUNET_PQ_query_param_auto_from_type (&bexpired),
+    GNUNET_PQ_query_param_end
+  };
+  enum GNUNET_DB_QueryStatus qs;
+  char stmt[128];
+
+  bexpired = (TALER_EXCHANGE_YNA_YES == expired);
+  GNUNET_snprintf (stmt,
+                   sizeof (stmt),
+                   "lookup_rewards_%s%s",
+                   (limit > 0) ? "inc" : "dec",
+                   (TALER_EXCHANGE_YNA_ALL == expired) ? "" : "_expired");
+
+  check_connection (pg);
+  PREPARE (pg,
+           "lookup_rewards_inc",
+           "SELECT"
+           " reward_serial"
+           ",reward_id"
+           ",amount"
+           ",CAST($4 as BIGINT)" /* otherwise $4 is unused and Postgres 
unhappy */
+           ",CAST($5 as BOOL)" /* otherwise $5 is unused and Postgres unhappy 
*/
+           " FROM merchant_rewards"
+           " JOIN merchant_reward_reserves USING (reserve_serial)"
+           " WHERE merchant_serial ="
+           "     (SELECT merchant_serial"
+           "        FROM merchant_instances"
+           "       WHERE merchant_id=$1)"
+           "   AND"
+           "    reward_serial > $3"
+           " ORDER BY reward_serial ASC"
+           " LIMIT $2");
+  PREPARE (pg,
+           "lookup_rewards_dec",
+           "SELECT"
+           " reward_serial"
+           ",reward_id"
+           ",amount"
+           ",CAST($4 as BIGINT)" /* otherwise $4 is unused and Postgres 
unhappy */
+           ",CAST($5 as BOOL)" /* otherwise $5 is unused and Postgres unhappy 
*/
+           " FROM merchant_rewards"
+           " JOIN merchant_reward_reserves USING (reserve_serial)"
+           " WHERE merchant_serial ="
+           "     (SELECT merchant_serial"
+           "        FROM merchant_instances"
+           "       WHERE merchant_id=$1)"
+           "   AND"
+           "    reward_serial < $3"
+           " ORDER BY reward_serial DESC"
+           " LIMIT $2");
+  PREPARE (pg,
+           "lookup_rewards_inc_expired",
+           "SELECT"
+           " reward_serial"
+           ",reward_id"
+           ",amount"
+           " FROM merchant_rewards"
+           " JOIN merchant_reward_reserves USING (reserve_serial)"
+           " WHERE merchant_serial ="
+           "     (SELECT merchant_serial"
+           "        FROM merchant_instances"
+           "       WHERE merchant_id=$1)"
+           "   AND"
+           "    reward_serial > $3"
+           "   AND"
+           "    CAST($5 as BOOL) = (merchant_rewards.expiration < $4)"
+           " ORDER BY reward_serial ASC"
+           " LIMIT $2");
+  PREPARE (pg,
+           "lookup_rewards_dec_expired",
+           "SELECT"
+           " reward_serial"
+           ",reward_id"
+           ",amount"
+           " FROM merchant_rewards"
+           " JOIN merchant_reward_reserves USING (reserve_serial)"
+           " WHERE merchant_serial ="
+           "     (SELECT merchant_serial"
+           "        FROM merchant_instances"
+           "       WHERE merchant_id=$1)"
+           "   AND"
+           "    reward_serial < $3"
+           "   AND"
+           "    CAST($5 as BOOL) = (merchant_rewards.expiration < $4)"
+           " ORDER BY reward_serial DESC"
+           " LIMIT $2");
+
+  qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn,
+                                             stmt,
+                                             params,
+                                             &lookup_rewards_cb,
+                                             &plc);
+  if (0 != plc.qs)
+    return plc.qs;
+  return qs;
+}
diff --git a/src/backenddb/pg_lookup_rewards.h 
b/src/backenddb/pg_lookup_rewards.h
new file mode 100644
index 00000000..a4fc61ec
--- /dev/null
+++ b/src/backenddb/pg_lookup_rewards.h
@@ -0,0 +1,50 @@
+/*
+   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 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 backenddb/pg_lookup_rewards.h
+ * @brief implementation of the lookup_rewards function for Postgres
+ * @author Iván Ávalos
+ */
+#ifndef PG_LOOKUP_REWARDS_H
+#define PG_LOOKUP_REWARDS_H
+
+#include <taler/taler_util.h>
+#include <taler/taler_json_lib.h>
+#include "taler_merchantdb_plugin.h"
+
+/**
+ * Lookup rewards
+ *
+ * @param cls closure, typically a connection to the db
+ * @param instance_id which instance should we lookup rewards for
+ * @param expired should we include expired rewards?
+ * @param limit maximum number of results to return, positive for
+ *   ascending row id, negative for descending
+ * @param offset row id to start returning results from
+ * @param cb function to call with reward data
+ * @param cb_cls closure for @a cb
+ * @return transaction status
+ */
+enum GNUNET_DB_QueryStatus
+TMH_PG_lookup_rewards (void *cls,
+                       const char *instance_id,
+                       enum TALER_EXCHANGE_YesNoAll expired,
+                       int64_t limit,
+                       uint64_t offset,
+                       TALER_MERCHANTDB_RewardsCallback cb,
+                       void *cb_cls);
+
+#endif
diff --git a/src/backenddb/pg_lookup_webhook.c 
b/src/backenddb/pg_lookup_webhook.c
new file mode 100644
index 00000000..3dcf396c
--- /dev/null
+++ b/src/backenddb/pg_lookup_webhook.c
@@ -0,0 +1,92 @@
+/*
+   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 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 backenddb/pg_lookup_webhook.c
+ * @brief Implementation of the lookup_webhook function for Postgres
+ * @author Iván Ávalos
+ */
+#include "platform.h"
+#include <taler/taler_error_codes.h>
+#include <taler/taler_dbevents.h>
+#include <taler/taler_pq_lib.h>
+#include "pg_lookup_webhook.h"
+#include "pg_helper.h"
+
+enum GNUNET_DB_QueryStatus
+TMH_PG_lookup_webhook (void *cls,
+                       const char *instance_id,
+                       const char *webhook_id,
+                       struct TALER_MERCHANTDB_WebhookDetails *wb)
+{
+  struct PostgresClosure *pg = cls;
+  struct GNUNET_PQ_QueryParam params[] = {
+    GNUNET_PQ_query_param_string (instance_id),
+    GNUNET_PQ_query_param_string (webhook_id),
+    GNUNET_PQ_query_param_end
+  };
+
+  check_connection (pg);
+  PREPARE (pg,
+           "lookup_webhook",
+           "SELECT"
+           " event_type"
+           ",url"
+           ",http_method"
+           ",header_template"
+           ",body_template"
+           " FROM merchant_webhook"
+           " JOIN merchant_instances"
+           "   USING (merchant_serial)"
+           " WHERE merchant_instances.merchant_id=$1"
+           "   AND merchant_webhook.webhook_id=$2");
+
+  if (NULL == wb)
+  {
+    struct GNUNET_PQ_ResultSpec rs_null[] = {
+      GNUNET_PQ_result_spec_end
+    };
+
+    return GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
+                                                     "lookup_webhook",
+                                                     params,
+                                                     rs_null);
+  }
+  else
+  {
+    struct GNUNET_PQ_ResultSpec rs[] = {
+      GNUNET_PQ_result_spec_string ("event_type",
+                                    &wb->event_type),
+      GNUNET_PQ_result_spec_string ("url",
+                                    &wb->url),
+      GNUNET_PQ_result_spec_string ("http_method",
+                                    &wb->http_method),
+      GNUNET_PQ_result_spec_allow_null (
+        GNUNET_PQ_result_spec_string ("header_template",
+                                      &wb->header_template),
+        NULL),
+      GNUNET_PQ_result_spec_allow_null (
+        GNUNET_PQ_result_spec_string ("body_template",
+                                      &wb->body_template),
+        NULL),
+      GNUNET_PQ_result_spec_end
+    };
+
+    return GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
+                                                     "lookup_webhook",
+                                                     params,
+                                                     rs);
+  }
+}
diff --git a/src/backenddb/pg_lookup_webhook.h 
b/src/backenddb/pg_lookup_webhook.h
new file mode 100644
index 00000000..d39828f1
--- /dev/null
+++ b/src/backenddb/pg_lookup_webhook.h
@@ -0,0 +1,44 @@
+/*
+   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 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 backenddb/pg_lookup_webhook.h
+ * @brief implementation of the lookup_webhook function for Postgres
+ * @author Iván Ávalos
+ */
+#ifndef PG_LOOKUP_WEBHOOK_H
+#define PG_LOOKUP_WEBHOOK_H
+
+#include <taler/taler_util.h>
+#include <taler/taler_json_lib.h>
+#include "taler_merchantdb_plugin.h"
+
+/**
+ * Lookup details about a particular webhook.
+ *
+ * @param cls closure
+ * @param instance_id instance to lookup webhook for
+ * @param webhook_id webhook to lookup
+ * @param[out] wb set to the webhook details on success, can be NULL
+ *             (in that case we only want to check if the webhook exists)
+ * @return database result code
+ */
+enum GNUNET_DB_QueryStatus
+TMH_PG_lookup_webhook (void *cls,
+                       const char *instance_id,
+                       const char *webhook_id,
+                       struct TALER_MERCHANTDB_WebhookDetails *wb);
+
+#endif
diff --git a/src/backenddb/pg_lookup_webhook_by_event.c 
b/src/backenddb/pg_lookup_webhook_by_event.c
new file mode 100644
index 00000000..97960bbe
--- /dev/null
+++ b/src/backenddb/pg_lookup_webhook_by_event.c
@@ -0,0 +1,158 @@
+/*
+   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 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 backenddb/pg_lookup_webhook_by_event.c
+ * @brief Implementation of the lookup_webhook_by_event function for Postgres
+ * @author Iván Ávalos
+ */
+#include "platform.h"
+#include <taler/taler_error_codes.h>
+#include <taler/taler_dbevents.h>
+#include <taler/taler_pq_lib.h>
+#include "pg_lookup_webhook_by_event.h"
+#include "pg_helper.h"
+
+/**
+ * Context used for lookup_webhook_by_event_cb().
+ */
+struct LookupWebhookDetailContext
+{
+  /**
+   * Function to call with the results.
+   */
+  TALER_MERCHANTDB_WebhookDetailCallback cb;
+
+  /**
+   * Closure for @a cb.
+   */
+  void *cb_cls;
+
+  /**
+   * Did database result extraction fail?
+   */
+  bool extract_failed;
+};
+
+/**
+ * Function to be called with the results of a SELECT statement
+ * that has returned @a num_results results about webhook.
+ *
+ * @param[in,out] cls of type `struct LookupPendingWebhookContext *`
+ * @param result the postgres result
+ * @param num_results the number of results in @a result
+ */
+static void
+lookup_webhook_by_event_cb (void *cls,
+                            PGresult *result,
+                            unsigned int num_results)
+{
+  struct LookupWebhookDetailContext *wlc = cls;
+
+  for (unsigned int i = 0; i < num_results; i++)
+  {
+    uint64_t webhook_serial;
+    char *event_type;
+    char *url;
+    char *http_method;
+    char *header_template;
+    char *body_template;
+    struct GNUNET_PQ_ResultSpec rs[] = {
+      GNUNET_PQ_result_spec_uint64 ("webhook_serial",
+                                    &webhook_serial),
+      GNUNET_PQ_result_spec_string ("event_type",
+                                    &event_type),
+      GNUNET_PQ_result_spec_string ("url",
+                                    &url),
+      GNUNET_PQ_result_spec_string ("http_method",
+                                    &http_method),
+      GNUNET_PQ_result_spec_allow_null (
+        GNUNET_PQ_result_spec_string ("header_template",
+                                      &header_template),
+        NULL),
+      GNUNET_PQ_result_spec_allow_null (
+        GNUNET_PQ_result_spec_string ("body_template",
+                                      &body_template),
+        NULL),
+      GNUNET_PQ_result_spec_end
+    };
+
+    if (GNUNET_OK !=
+        GNUNET_PQ_extract_result (result,
+                                  rs,
+                                  i))
+    {
+      GNUNET_break (0);
+      wlc->extract_failed = true;
+      return;
+    }
+    wlc->cb (wlc->cb_cls,
+             webhook_serial,
+             event_type,
+             url,
+             http_method,
+             header_template,
+             body_template);
+    GNUNET_PQ_cleanup_result (rs);
+  }
+}
+
+enum GNUNET_DB_QueryStatus
+TMH_PG_lookup_webhook_by_event (void *cls,
+                                const char *instance_id,
+                                const char *event_type,
+                                TALER_MERCHANTDB_WebhookDetailCallback cb,
+                                void *cb_cls)
+{
+  struct PostgresClosure *pg = cls;
+  struct LookupWebhookDetailContext wlc = {
+    .cb = cb,
+    .cb_cls = cb_cls,
+    .extract_failed = false,
+  };
+
+  struct GNUNET_PQ_QueryParam params[] = {
+    GNUNET_PQ_query_param_string (instance_id),
+    GNUNET_PQ_query_param_string (event_type),
+    GNUNET_PQ_query_param_end
+  };
+  enum GNUNET_DB_QueryStatus qs;
+
+  check_connection (pg);
+  PREPARE (pg,
+           "lookup_webhook_by_event",
+           "SELECT"
+           " webhook_serial"
+           ",event_type"
+           ",url"
+           ",http_method"
+           ",header_template"
+           ",body_template"
+           " FROM merchant_webhook"
+           " JOIN merchant_instances"
+           "   USING (merchant_serial)"
+           " WHERE merchant_instances.merchant_id=$1"
+           "  AND event_type=$2");
+
+  qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn,
+                                             "lookup_webhook_by_event",
+                                             params,
+                                             &lookup_webhook_by_event_cb,
+                                             &wlc);
+
+  if (wlc.extract_failed)
+    return GNUNET_DB_STATUS_HARD_ERROR;
+  return qs;
+}
diff --git a/src/backenddb/pg_lookup_webhook_by_event.h 
b/src/backenddb/pg_lookup_webhook_by_event.h
new file mode 100644
index 00000000..ccabc1ec
--- /dev/null
+++ b/src/backenddb/pg_lookup_webhook_by_event.h
@@ -0,0 +1,45 @@
+/*
+   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 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 backenddb/pg_lookup_webhook_by_event.h
+ * @brief implementation of the lookup_webhook_by_event function for Postgres
+ * @author Iván Ávalos
+ */
+#ifndef PG_LOOKUP_WEBHOOK_BY_EVENT_H
+#define PG_LOOKUP_WEBHOOK_BY_EVENT_H
+
+#include <taler/taler_util.h>
+#include <taler/taler_json_lib.h>
+#include "taler_merchantdb_plugin.h"
+
+/**
+   * Lookup webhook by event
+   *
+   * @param cls closure
+   * @param instance_id instance to lookup webhook for
+   * @param event_type event that we need to put in the pending webhook
+   * @param[out] cb set to the webhook details on success
+   * @param cb_cls callback closure
+   * @return database result code
+   */
+enum GNUNET_DB_QueryStatus
+TMH_PG_lookup_webhook_by_event (void *cls,
+                                const char *instance_id,
+                                const char *event_type,
+                                TALER_MERCHANTDB_WebhookDetailCallback cb,
+                                void *cb_cls);
+
+#endif
diff --git a/src/backenddb/pg_lookup_webhooks.c 
b/src/backenddb/pg_lookup_webhooks.c
new file mode 100644
index 00000000..0a85d527
--- /dev/null
+++ b/src/backenddb/pg_lookup_webhooks.c
@@ -0,0 +1,133 @@
+/*
+   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 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 backenddb/pg_lookup_webhooks.c
+ * @brief Implementation of the lookup_webhooks function for Postgres
+ * @author Iván Ávalos
+ */
+#include "platform.h"
+#include <taler/taler_error_codes.h>
+#include <taler/taler_dbevents.h>
+#include <taler/taler_pq_lib.h>
+#include "pg_lookup_webhooks.h"
+#include "pg_helper.h"
+
+/**
+ * Context used for postgres_lookup_webhooks().
+ */
+struct LookupWebhookContext
+{
+  /**
+   * Function to call with the results.
+   */
+  TALER_MERCHANTDB_WebhooksCallback cb;
+
+  /**
+   * Closure for @a cb.
+   */
+  void *cb_cls;
+
+  /**
+   * Did database result extraction fail?
+   */
+  bool extract_failed;
+};
+
+
+/**
+ * Function to be called with the results of a SELECT statement
+ * that has returned @a num_results results about webhook.
+ *
+ * @param[in,out] cls of type `struct LookupWebhookContext *`
+ * @param result the postgres result
+ * @param num_results the number of results in @a result
+ */
+static void
+lookup_webhooks_cb (void *cls,
+                    PGresult *result,
+                    unsigned int num_results)
+{
+  struct LookupWebhookContext *wlc = cls;
+
+  for (unsigned int i = 0; i < num_results; i++)
+  {
+    char *webhook_id;
+    char *event_type;
+    struct GNUNET_PQ_ResultSpec rs[] = {
+      GNUNET_PQ_result_spec_string ("webhook_id",
+                                    &webhook_id),
+      GNUNET_PQ_result_spec_string ("event_type",
+                                    &event_type),
+      GNUNET_PQ_result_spec_end
+    };
+
+    if (GNUNET_OK !=
+        GNUNET_PQ_extract_result (result,
+                                  rs,
+                                  i))
+    {
+      GNUNET_break (0);
+      wlc->extract_failed = true;
+      return;
+    }
+    wlc->cb (wlc->cb_cls,
+             webhook_id,
+             event_type);
+    GNUNET_PQ_cleanup_result (rs);
+  }
+}
+
+
+enum GNUNET_DB_QueryStatus
+TMH_PG_lookup_webhooks (void *cls,
+                        const char *instance_id,
+                        TALER_MERCHANTDB_WebhooksCallback cb,
+                        void *cb_cls)
+{
+  struct PostgresClosure *pg = cls;
+  struct LookupWebhookContext wlc = {
+    .cb = cb,
+    .cb_cls = cb_cls,
+    /* Can be overwritten by the lookup_webhook_cb */
+    .extract_failed = false,
+  };
+  struct GNUNET_PQ_QueryParam params[] = {
+    GNUNET_PQ_query_param_string (instance_id),
+    GNUNET_PQ_query_param_end
+  };
+  enum GNUNET_DB_QueryStatus qs;
+
+  check_connection (pg);
+  PREPARE (pg,
+           "lookup_webhooks",
+           "SELECT"
+           " webhook_id"
+           ",event_type"
+           " FROM merchant_webhook"
+           " JOIN merchant_instances"
+           "   USING (merchant_serial)"
+           " WHERE merchant_instances.merchant_id=$1");
+
+  qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn,
+                                             "lookup_webhooks",
+                                             params,
+                                             &lookup_webhooks_cb,
+                                             &wlc);
+  /* If there was an error inside lookup_webhook_cb, return a hard error. */
+  if (wlc.extract_failed)
+    return GNUNET_DB_STATUS_HARD_ERROR;
+  return qs;
+}
diff --git a/src/backenddb/pg_lookup_webhooks.h 
b/src/backenddb/pg_lookup_webhooks.h
new file mode 100644
index 00000000..84509267
--- /dev/null
+++ b/src/backenddb/pg_lookup_webhooks.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 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 backenddb/pg_lookup_webhooks.h
+ * @brief implementation of the lookup_webhooks function for Postgres
+ * @author Iván Ávalos
+ */
+#ifndef PG_LOOKUP_WEBHOOKS_H
+#define PG_LOOKUP_WEBHOOKS_H
+
+#include <taler/taler_util.h>
+#include <taler/taler_json_lib.h>
+#include "taler_merchantdb_plugin.h"
+
+/**
+ * Lookup all of the webhooks the given instance has configured.
+ *
+ * @param cls closure
+ * @param instance_id instance to lookup webhook for
+ * @param cb function to call on all webhook found
+ * @param cb_cls closure for @a cb
+ * @return database result code
+ */
+enum GNUNET_DB_QueryStatus
+TMH_PG_lookup_webhooks (void *cls,
+                        const char *instance_id,
+                        TALER_MERCHANTDB_WebhooksCallback cb,
+                        void *cb_cls);
+
+#endif
diff --git a/src/backenddb/pg_purge_reserve.c b/src/backenddb/pg_purge_reserve.c
new file mode 100644
index 00000000..cb01069a
--- /dev/null
+++ b/src/backenddb/pg_purge_reserve.c
@@ -0,0 +1,54 @@
+/*
+   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 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 backenddb/pg_purge_reserve.c
+ * @brief Implementation of the purge_reserve function for Postgres
+ * @author Iván Ávalos
+ */
+#include "platform.h"
+#include <taler/taler_error_codes.h>
+#include <taler/taler_dbevents.h>
+#include <taler/taler_pq_lib.h>
+#include "pg_purge_reserve.h"
+#include "pg_helper.h"
+
+enum GNUNET_DB_QueryStatus
+TMH_PG_purge_reserve (void *cls,
+                      const char *instance_id,
+                      const struct TALER_ReservePublicKeyP *reserve_pub)
+{
+  struct PostgresClosure *pg = cls;
+  struct GNUNET_PQ_QueryParam params[] = {
+    GNUNET_PQ_query_param_string (instance_id),
+    GNUNET_PQ_query_param_auto_from_type (reserve_pub),
+    GNUNET_PQ_query_param_end
+  };
+
+  check_connection (pg);
+  PREPARE (pg,
+           "purge_reserve",
+           "DELETE"
+           "   FROM merchant_reward_reserves"
+           "  WHERE reserve_pub=$2"
+           "    AND merchant_serial="
+           "    (SELECT merchant_serial"
+           "       FROM merchant_instances"
+           "      WHERE merchant_id=$1)");
+
+  return GNUNET_PQ_eval_prepared_non_select (pg->conn,
+                                             "purge_reserve",
+                                             params);
+}
diff --git a/src/backenddb/pg_purge_reserve.h b/src/backenddb/pg_purge_reserve.h
new file mode 100644
index 00000000..83c1b44f
--- /dev/null
+++ b/src/backenddb/pg_purge_reserve.h
@@ -0,0 +1,42 @@
+/*
+   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 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 backenddb/pg_purge_reserve.h
+ * @brief implementation of the purge_reserve function for Postgres
+ * @author Iván Ávalos
+ */
+#ifndef PG_PURGE_RESERVE_H
+#define PG_PURGE_RESERVE_H
+
+#include <taler/taler_util.h>
+#include <taler/taler_json_lib.h>
+#include "taler_merchantdb_plugin.h"
+
+/**
+ * Purge all of the information about a reserve, including rewards.
+ *
+ * @param cls closure, typically a connection to the db
+ * @param instance_id which instance is the reserve tied to
+ * @param reserve_pub which reserve is to be purged
+ * @return transaction status, usually
+ *      #GNUNET_DB_STATUS_SUCCESS_ONE_RESULT for success
+ */
+enum GNUNET_DB_QueryStatus
+TMH_PG_purge_reserve (void *cls,
+                      const char *instance_id,
+                      const struct TALER_ReservePublicKeyP *reserve_pub);
+
+#endif
diff --git a/src/backenddb/pg_update_webhook.c 
b/src/backenddb/pg_update_webhook.c
new file mode 100644
index 00000000..c12ae9e3
--- /dev/null
+++ b/src/backenddb/pg_update_webhook.c
@@ -0,0 +1,69 @@
+/*
+   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 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 backenddb/pg_update_webhook.c
+ * @brief Implementation of the update_webhook function for Postgres
+ * @author Iván Ávalos
+ */
+#include "platform.h"
+#include <taler/taler_error_codes.h>
+#include <taler/taler_dbevents.h>
+#include <taler/taler_pq_lib.h>
+#include "pg_update_webhook.h"
+#include "pg_helper.h"
+
+enum GNUNET_DB_QueryStatus
+TMH_PG_update_webhook (void *cls,
+                       const char *instance_id,
+                       const char *webhook_id,
+                       const struct TALER_MERCHANTDB_WebhookDetails *wb)
+{
+  struct PostgresClosure *pg = cls;
+  struct GNUNET_PQ_QueryParam params[] = {
+    GNUNET_PQ_query_param_string (instance_id),
+    GNUNET_PQ_query_param_string (webhook_id),
+    GNUNET_PQ_query_param_string (wb->event_type),
+    GNUNET_PQ_query_param_string (wb->url),
+    GNUNET_PQ_query_param_string (wb->http_method),
+    (NULL == wb->header_template)
+    ? GNUNET_PQ_query_param_null ()
+    : GNUNET_PQ_query_param_string (wb->header_template),
+    (NULL == wb->body_template)
+    ? GNUNET_PQ_query_param_null ()
+    : GNUNET_PQ_query_param_string (wb->body_template),
+    GNUNET_PQ_query_param_end
+  };
+
+
+  check_connection (pg);
+  PREPARE (pg,
+           "update_webhook",
+           "UPDATE merchant_webhook SET"
+           " event_type=$3"
+           ",url=$4"
+           ",http_method=$5"
+           ",header_template=$6"
+           ",body_template=$7"
+           " WHERE merchant_serial="
+           "   (SELECT merchant_serial"
+           "      FROM merchant_instances"
+           "      WHERE merchant_id=$1)"
+           "   AND webhook_id=$2");
+
+  return GNUNET_PQ_eval_prepared_non_select (pg->conn,
+                                             "update_webhook",
+                                             params);
+}
diff --git a/src/backenddb/pg_update_webhook.h 
b/src/backenddb/pg_update_webhook.h
new file mode 100644
index 00000000..a34eb598
--- /dev/null
+++ b/src/backenddb/pg_update_webhook.h
@@ -0,0 +1,45 @@
+/*
+   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 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 backenddb/pg_update_webhook.h
+ * @brief implementation of the update_webhook function for Postgres
+ * @author Iván Ávalos
+ */
+#ifndef PG_UPDATE_WEBHOOK_H
+#define PG_UPDATE_WEBHOOK_H
+
+#include <taler/taler_util.h>
+#include <taler/taler_json_lib.h>
+#include "taler_merchantdb_plugin.h"
+
+/**
+ * Update details about a particular webhook.
+ *
+ * @param cls closure
+ * @param instance_id instance to update template for
+ * @param webhook_id webhook to update
+ * @param wb update to the webhook details on success, can be NULL
+ *             (in that case we only want to check if the webhook exists)
+ * @return database result code, #GNUNET_DB_STATUS_SUCCESS_NO_RESULTS if the 
webhook
+ *         does not yet exist.
+ */
+enum GNUNET_DB_QueryStatus
+TMH_PG_update_webhook (void *cls,
+                       const char *instance_id,
+                       const char *webhook_id,
+                       const struct TALER_MERCHANTDB_WebhookDetails *wb);
+
+#endif
diff --git a/src/backenddb/plugin_merchantdb_postgres.c 
b/src/backenddb/plugin_merchantdb_postgres.c
index 214902dd..35f2ecb9 100644
--- a/src/backenddb/plugin_merchantdb_postgres.c
+++ b/src/backenddb/plugin_merchantdb_postgres.c
@@ -112,6 +112,22 @@
 #include "pg_lookup_transfer.h"
 #include "pg_lookup_transfer_summary.h"
 #include "pg_lookup_transfer_details.h"
+#include "pg_lookup_pending_reserves.h"
+#include "pg_lookup_reserve.h"
+#include "pg_delete_reserve.h"
+#include "pg_purge_reserve.h"
+#include "pg_lookup_pickup.h"
+#include "pg_lookup_reward.h"
+#include "pg_lookup_rewards.h"
+#include "pg_lookup_reward_details.h"
+#include "pg_insert_pickup_blind_signature.h"
+#include "pg_lookup_webhooks.h"
+#include "pg_lookup_webhook.h"
+#include "pg_delete_webhook.h"
+#include "pg_insert_webhook.h"
+#include "pg_update_webhook.h"
+#include "pg_lookup_webhook_by_event.h"
+#include "pg_delete_pending_webhook.h"
 #include "pg_set_transfer_status_to_confirmed.h"
 #include "pg_insert_exchange_keys.h"
 #include "pg_select_exchange_keys.h"
@@ -275,1306 +291,6 @@ check_connection (struct PostgresClosure *pg)
 }
 
 
-/**
- * Closure for #lookup_pending_reserves_cb.
- */
-struct LookupPendingReservesContext
-{
-  /**
-   * Postgres context.
-   */
-  struct PostgresClosure *pg;
-
-  /**
-   * Function to call with the results
-   */
-  TALER_MERCHANTDB_PendingReservesCallback cb;
-
-  /**
-   * Closure for @e cb
-   */
-  void *cb_cls;
-
-  /**
-   * Set in case of errors.
-   */
-  enum GNUNET_DB_QueryStatus qs;
-
-};
-
-
-/**
- * Function to be called with the results of a SELECT statement
- * that has returned @a num_results results about accounts.
- *
- * @param[in,out] cls of type `struct LookupReservesContext *`
- * @param result the postgres result
- * @param num_results the number of results in @a result
- */
-static void
-lookup_pending_reserves_cb (void *cls,
-                            PGresult *result,
-                            unsigned int num_results)
-{
-  struct LookupPendingReservesContext *lrc = cls;
-
-  for (unsigned int i = 0; i < num_results; i++)
-  {
-    struct TALER_ReservePublicKeyP reserve_pub;
-    struct TALER_Amount merchant_initial_balance;
-    char *exchange_url;
-    char *instance_id;
-    struct GNUNET_PQ_ResultSpec rs[] = {
-      GNUNET_PQ_result_spec_auto_from_type ("reserve_pub",
-                                            &reserve_pub),
-      GNUNET_PQ_result_spec_string ("merchant_id",
-                                    &instance_id),
-      GNUNET_PQ_result_spec_string ("exchange_url",
-                                    &exchange_url),
-      TALER_PQ_result_spec_amount_with_currency ("merchant_initial_balance",
-                                                 &merchant_initial_balance),
-      GNUNET_PQ_result_spec_end
-    };
-
-    if (GNUNET_OK !=
-        GNUNET_PQ_extract_result (result,
-                                  rs,
-                                  i))
-    {
-      GNUNET_break (0);
-      lrc->qs = GNUNET_DB_STATUS_HARD_ERROR;
-      return;
-    }
-    lrc->cb (lrc->cb_cls,
-             instance_id,
-             exchange_url,
-             &reserve_pub,
-             &merchant_initial_balance);
-    GNUNET_PQ_cleanup_result (rs);
-  }
-}
-
-
-/**
- * Lookup reserves pending activation across all instances.
- *
- * @param cls closure
- * @param cb function to call with reserve summary data
- * @param cb_cls closure for @a cb
- * @return transaction status
- */
-static enum GNUNET_DB_QueryStatus
-postgres_lookup_pending_reserves (void *cls,
-                                  TALER_MERCHANTDB_PendingReservesCallback cb,
-                                  void *cb_cls)
-{
-  struct PostgresClosure *pg = cls;
-  struct LookupPendingReservesContext lrc = {
-    .pg = pg,
-    .cb = cb,
-    .cb_cls = cb_cls
-  };
-  struct GNUNET_PQ_QueryParam params[] = {
-    GNUNET_PQ_query_param_end
-  };
-  enum GNUNET_DB_QueryStatus qs;
-
-  check_connection (pg);
-  qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn,
-                                             "lookup_pending_reserves",
-                                             params,
-                                             &lookup_pending_reserves_cb,
-                                             &lrc);
-  if (lrc.qs < 0)
-    return lrc.qs;
-  return qs;
-}
-
-
-/**
- * Closure for #lookup_reserve_rewards_cb().
- */
-struct LookupRewardsContext
-{
-  /**
-   * Postgres context.
-   */
-  struct PostgresClosure *pg;
-
-  /**
-   * Array with information about rewards generated from this reserve.
-   */
-  struct TALER_MERCHANTDB_RewardDetails *rewards;
-
-  /**
-   * Length of the @e rewards array.
-   */
-  unsigned int rewards_length;
-
-  /**
-   * Set in case of errors.
-   */
-  enum GNUNET_DB_QueryStatus qs;
-};
-
-
-/**
- * Function to be called with the results of a SELECT statement
- * that has returned @a num_results results about accounts.
- *
- * @param[in,out] cls of type `struct LookupRewardsContext *`
- * @param result the postgres result
- * @param num_results the number of results in @a result
- */
-static void
-lookup_reserve_rewards_cb (void *cls,
-                           PGresult *result,
-                           unsigned int num_results)
-{
-  struct LookupRewardsContext *ltc = cls;
-
-  GNUNET_array_grow (ltc->rewards,
-                     ltc->rewards_length,
-                     num_results);
-  for (unsigned int i = 0; i < num_results; i++)
-  {
-    struct TALER_MERCHANTDB_RewardDetails *td = &ltc->rewards[i];
-    struct GNUNET_PQ_ResultSpec rs[] = {
-      GNUNET_PQ_result_spec_string ("justification",
-                                    &td->reason),
-      GNUNET_PQ_result_spec_auto_from_type ("reward_id",
-                                            &td->reward_id),
-      TALER_PQ_result_spec_amount_with_currency ("amount",
-                                                 &td->total_amount),
-      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;
-    }
-  }
-}
-
-
-/**
- * Lookup reserve details.
- *
- * @param cls closure
- * @param instance_id instance to lookup payments for
- * @param reserve_pub public key of the reserve to inspect
- * @param fetch_rewards if true, also return information about rewards
- * @param cb function to call with reserve summary data
- * @param cb_cls closure for @a cb
- * @return transaction status
- */
-static enum GNUNET_DB_QueryStatus
-postgres_lookup_reserve (void *cls,
-                         const char *instance_id,
-                         const struct TALER_ReservePublicKeyP *reserve_pub,
-                         bool fetch_rewards,
-                         TALER_MERCHANTDB_ReserveDetailsCallback cb,
-                         void *cb_cls)
-{
-  struct PostgresClosure *pg = cls;
-  struct LookupRewardsContext ltc = {
-    .pg = pg,
-    .qs = GNUNET_DB_STATUS_SUCCESS_ONE_RESULT
-  };
-  struct GNUNET_PQ_QueryParam params[] = {
-    GNUNET_PQ_query_param_string (instance_id),
-    GNUNET_PQ_query_param_auto_from_type (reserve_pub),
-    GNUNET_PQ_query_param_end
-  };
-  struct GNUNET_TIME_Timestamp creation_time;
-  struct GNUNET_TIME_Timestamp expiration_time;
-  struct TALER_Amount merchant_initial_balance;
-  struct TALER_Amount exchange_initial_balance;
-  struct TALER_Amount pickup_amount;
-  struct TALER_Amount committed_amount;
-  struct TALER_MasterPublicKeyP master_pub;
-  bool active;
-  char *exchange_url = NULL;
-  struct GNUNET_PQ_ResultSpec rs[] = {
-    GNUNET_PQ_result_spec_timestamp ("creation_time",
-                                     &creation_time),
-    GNUNET_PQ_result_spec_timestamp ("expiration",
-                                     &expiration_time),
-    TALER_PQ_result_spec_amount_with_currency ("merchant_initial_balance",
-                                               &merchant_initial_balance),
-    TALER_PQ_result_spec_amount_with_currency ("exchange_initial_balance",
-                                               &exchange_initial_balance),
-    TALER_PQ_result_spec_amount_with_currency ("rewards_picked_up",
-                                               &pickup_amount),
-    TALER_PQ_result_spec_amount_with_currency ("rewards_committed",
-                                               &committed_amount),
-    GNUNET_PQ_result_spec_auto_from_type ("master_pub",
-                                          &master_pub),
-    GNUNET_PQ_result_spec_bool ("active",
-                                &active),
-    GNUNET_PQ_result_spec_allow_null (
-      GNUNET_PQ_result_spec_string ("exchange_url",
-                                    &exchange_url),
-      NULL),
-    GNUNET_PQ_result_spec_end
-  };
-  enum GNUNET_DB_QueryStatus qs;
-
-  check_connection (pg);
-  qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
-                                                 "lookup_reserve",
-                                                 params,
-                                                 rs);
-  if (qs < 0)
-    return qs;
-  if (! fetch_rewards)
-  {
-    cb (cb_cls,
-        creation_time,
-        expiration_time,
-        &merchant_initial_balance,
-        &exchange_initial_balance,
-        &pickup_amount,
-        &committed_amount,
-        active,
-        &master_pub,
-        exchange_url,
-        0,
-        NULL);
-    GNUNET_PQ_cleanup_result (rs);
-    return qs;
-  }
-
-  qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn,
-                                             "lookup_reserve_rewards",
-                                             params,
-                                             &lookup_reserve_rewards_cb,
-                                             &ltc);
-  if (qs < 0)
-    return qs;
-  if (ltc.qs >= 0)
-  {
-    cb (cb_cls,
-        creation_time,
-        expiration_time,
-        &merchant_initial_balance,
-        &exchange_initial_balance,
-        &pickup_amount,
-        &committed_amount,
-        active,
-        &master_pub,
-        exchange_url,
-        ltc.rewards_length,
-        ltc.rewards);
-  }
-  for (unsigned int i = 0; i<ltc.rewards_length; i++)
-    GNUNET_free (ltc.rewards[i].reason);
-  GNUNET_array_grow (ltc.rewards,
-                     ltc.rewards_length,
-                     0);
-  GNUNET_PQ_cleanup_result (rs);
-  return ltc.qs;
-}
-
-
-/**
- * Delete a reserve's private key.
- *
- * @param cls closure, typically a connection to the db
- * @param instance_id which instance is the reserve tied to
- * @param reserve_pub which reserve is to be deleted
- * @return transaction status, usually
- *      #GNUNET_DB_STATUS_SUCCESS_ONE_RESULT for success
- */
-static enum GNUNET_DB_QueryStatus
-postgres_delete_reserve (void *cls,
-                         const char *instance_id,
-                         const struct TALER_ReservePublicKeyP *reserve_pub)
-{
-  struct PostgresClosure *pg = cls;
-  struct GNUNET_PQ_QueryParam params[] = {
-    GNUNET_PQ_query_param_string (instance_id),
-    GNUNET_PQ_query_param_auto_from_type (reserve_pub),
-    GNUNET_PQ_query_param_end
-  };
-
-  check_connection (pg);
-  return GNUNET_PQ_eval_prepared_non_select (pg->conn,
-                                             "delete_reserve",
-                                             params);
-}
-
-
-/**
- * Purge all of the information about a reserve, including rewards.
- *
- * @param cls closure, typically a connection to the db
- * @param instance_id which instance is the reserve tied to
- * @param reserve_pub which reserve is to be purged
- * @return transaction status, usually
- *      #GNUNET_DB_STATUS_SUCCESS_ONE_RESULT for success
- */
-static enum GNUNET_DB_QueryStatus
-postgres_purge_reserve (void *cls,
-                        const char *instance_id,
-                        const struct TALER_ReservePublicKeyP *reserve_pub)
-{
-  struct PostgresClosure *pg = cls;
-  struct GNUNET_PQ_QueryParam params[] = {
-    GNUNET_PQ_query_param_string (instance_id),
-    GNUNET_PQ_query_param_auto_from_type (reserve_pub),
-    GNUNET_PQ_query_param_end
-  };
-
-  check_connection (pg);
-  return GNUNET_PQ_eval_prepared_non_select (pg->conn,
-                                             "purge_reserve",
-                                             params);
-}
-
-
-/**
- * Closure for #lookup_signatures_cb().
- */
-struct LookupSignaturesContext
-{
-  /**
-   * Length of the @e sigs array
-   */
-  unsigned int sigs_length;
-
-  /**
-   * Where to store the signatures.
-   */
-  struct TALER_BlindedDenominationSignature *sigs;
-};
-
-
-/**
- * Function to be called with the results of a SELECT statement
- * that has returned @a num_results results about accounts.
- *
- * @param[in,out] cls of type `struct LookupSignaturesContext *`
- * @param result the postgres result
- * @param num_results the number of results in @a result
- */
-static void
-lookup_signatures_cb (void *cls,
-                      PGresult *result,
-                      unsigned int num_results)
-{
-  struct LookupSignaturesContext *lsc = cls;
-
-  for (unsigned int i = 0; i < num_results; i++)
-  {
-    uint32_t offset;
-    struct TALER_BlindedDenominationSignature bsig;
-    struct GNUNET_PQ_ResultSpec rs[] = {
-      GNUNET_PQ_result_spec_uint32 ("coin_offset",
-                                    &offset),
-      TALER_PQ_result_spec_blinded_denom_sig ("blind_sig",
-                                              &bsig),
-      GNUNET_PQ_result_spec_end
-    };
-
-    if (GNUNET_OK !=
-        GNUNET_PQ_extract_result (result,
-                                  rs,
-                                  i))
-    {
-      GNUNET_break (0);
-      return;
-    }
-    if (offset >= lsc->sigs_length)
-    {
-      GNUNET_break_op (0);
-      GNUNET_PQ_cleanup_result (rs);
-      continue;
-    }
-    /* Must be NULL due to UNIQUE constraint on offset and
-       requirement that client launched us with 'sigs'
-       pre-initialized to NULL. */
-    lsc->sigs[offset] = bsig;
-  }
-}
-
-
-/**
- * Lookup pickup details for pickup @a pickup_id.
- *
- * @param cls closure, typically a connection to the db
- * @param instance_id which instance should we lookup reward details for
- * @param reward_id which reward should we lookup details on
- * @param pickup_id which pickup should we lookup details on
- * @param[out] exchange_url which exchange is the reward withdrawn from
- * @param[out] reserve_priv private key the reward is withdrawn from (set if 
still available!)
- * @param sigs_length length of the @a sigs array
- * @param[out] sigs set to the (blind) signatures we have for this @a 
pickup_id,
- *              those that are unavailable are left at NULL
- * @return transaction status
- */
-static enum GNUNET_DB_QueryStatus
-postgres_lookup_pickup (void *cls,
-                        const char *instance_id,
-                        const struct TALER_RewardIdentifierP *reward_id,
-                        const struct TALER_PickupIdentifierP *pickup_id,
-                        char **exchange_url,
-                        struct TALER_ReservePrivateKeyP *reserve_priv,
-                        unsigned int sigs_length,
-                        struct TALER_BlindedDenominationSignature sigs[])
-{
-  struct PostgresClosure *pg = cls;
-  uint64_t pickup_serial;
-
-  {
-    struct GNUNET_PQ_QueryParam params[] = {
-      GNUNET_PQ_query_param_string (instance_id),
-      GNUNET_PQ_query_param_auto_from_type (reward_id),
-      GNUNET_PQ_query_param_auto_from_type (pickup_id),
-      GNUNET_PQ_query_param_end
-    };
-    struct GNUNET_PQ_ResultSpec rs[] = {
-      GNUNET_PQ_result_spec_string ("exchange_url",
-                                    exchange_url),
-      GNUNET_PQ_result_spec_auto_from_type ("reserve_priv",
-                                            reserve_priv),
-      GNUNET_PQ_result_spec_uint64 ("pickup_serial",
-                                    &pickup_serial),
-      GNUNET_PQ_result_spec_end
-    };
-    enum GNUNET_DB_QueryStatus qs;
-
-    qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
-                                                   "lookup_pickup",
-                                                   params,
-                                                   rs);
-    if (qs <= 0)
-      return qs;
-  }
-  {
-    struct GNUNET_PQ_QueryParam params[] = {
-      GNUNET_PQ_query_param_uint64 (&pickup_serial),
-      GNUNET_PQ_query_param_end
-    };
-    struct LookupSignaturesContext lsc = {
-      .sigs_length = sigs_length,
-      .sigs = sigs
-    };
-
-    return GNUNET_PQ_eval_prepared_multi_select (pg->conn,
-                                                 "lookup_pickup_signatures",
-                                                 params,
-                                                 &lookup_signatures_cb,
-                                                 &lsc);
-  }
-}
-
-
-/**
- * Lookup reward details for reward @a reward_id.
- *
- * @param cls closure, typically a connection to the db
- * @param instance_id which instance should we lookup reward details for
- * @param reward_id which reward should we lookup details on
- * @param[out] total_authorized amount how high is the reward (with fees)
- * @param[out] total_picked_up how much of the reward was so far picked up 
(with fees)
- * @param[out] expiration set to when the reward expires
- * @param[out] exchange_url set to the exchange URL where the reserve is
- * @param[out] next_url set to the URL where the wallet should navigate after 
getting the reward
- * @param[out] reserve_priv set to private key of reserve to be debited
- * @return transaction status
- */
-static enum GNUNET_DB_QueryStatus
-postgres_lookup_reward (void *cls,
-                        const char *instance_id,
-                        const struct TALER_RewardIdentifierP *reward_id,
-                        struct TALER_Amount *total_authorized,
-                        struct TALER_Amount *total_picked_up,
-                        struct GNUNET_TIME_Timestamp *expiration,
-                        char **exchange_url,
-                        char **next_url,
-                        struct TALER_ReservePrivateKeyP *reserve_priv)
-{
-  struct PostgresClosure *pg = cls;
-  struct GNUNET_PQ_QueryParam params[] = {
-    GNUNET_PQ_query_param_string (instance_id),
-    GNUNET_PQ_query_param_auto_from_type (reward_id),
-    GNUNET_PQ_query_param_end
-  };
-  struct GNUNET_PQ_ResultSpec rs[] = {
-    TALER_PQ_result_spec_amount_with_currency ("amount",
-                                               total_authorized),
-    TALER_PQ_result_spec_amount_with_currency ("picked_up",
-                                               total_picked_up),
-    GNUNET_PQ_result_spec_timestamp ("expiration",
-                                     expiration),
-    GNUNET_PQ_result_spec_string ("exchange_url",
-                                  exchange_url),
-    GNUNET_PQ_result_spec_string ("next_url",
-                                  next_url),
-    GNUNET_PQ_result_spec_auto_from_type ("reserve_priv",
-                                          reserve_priv),
-    GNUNET_PQ_result_spec_end
-  };
-
-  return GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
-                                                   "lookup_reward",
-                                                   params,
-                                                   rs);
-}
-
-
-/**
- * Context used for postgres_lookup_rewards().
- */
-struct LookupMerchantRewardsContext
-{
-  /**
-   * Postgres context.
-   */
-  struct PostgresClosure *pg;
-
-  /**
-   * Function to call with the results.
-   */
-  TALER_MERCHANTDB_RewardsCallback cb;
-
-  /**
-   * Closure for @a cb.
-   */
-  void *cb_cls;
-
-  /**
-   * Internal result.
-   */
-  enum GNUNET_DB_QueryStatus qs;
-};
-
-
-/**
- * Function to be called with the results of a SELECT statement
- * that has returned @a num_results results about rewards.
- *
- * @param[in,out] cls of type `struct LookupRewardsContext *`
- * @param result the postgres result
- * @param num_results the number of results in @a result
- */
-static void
-lookup_rewards_cb (void *cls,
-                   PGresult *result,
-                   unsigned int num_results)
-{
-  struct LookupMerchantRewardsContext *plc = cls;
-
-  for (unsigned int i = 0; i < num_results; i++)
-  {
-    uint64_t row_id;
-    struct TALER_RewardIdentifierP reward_id;
-    struct TALER_Amount reward_amount;
-    struct GNUNET_PQ_ResultSpec rs[] = {
-      GNUNET_PQ_result_spec_uint64 ("reward_serial",
-                                    &row_id),
-      GNUNET_PQ_result_spec_auto_from_type ("reward_id",
-                                            &reward_id),
-      TALER_PQ_result_spec_amount_with_currency ("amount",
-                                                 &reward_amount),
-      GNUNET_PQ_result_spec_end
-    };
-
-    if (GNUNET_OK !=
-        GNUNET_PQ_extract_result (result,
-                                  rs,
-                                  i))
-    {
-      GNUNET_break (0);
-      plc->qs = GNUNET_DB_STATUS_HARD_ERROR;
-      return;
-    }
-    plc->cb (plc->cb_cls,
-             row_id,
-             reward_id,
-             reward_amount);
-    GNUNET_PQ_cleanup_result (rs);
-  }
-}
-
-
-/**
- * Lookup rewards
- *
- * @param cls closure, typically a connection to the db
- * @param instance_id which instance should we lookup rewards for
- * @param expired should we include expired rewards?
- * @param limit maximum number of results to return, positive for
- *   ascending row id, negative for descending
- * @param offset row id to start returning results from
- * @param cb function to call with reward data
- * @param cb_cls closure for @a cb
- * @return transaction status
- */
-static enum GNUNET_DB_QueryStatus
-postgres_lookup_rewards (void *cls,
-                         const char *instance_id,
-                         enum TALER_EXCHANGE_YesNoAll expired,
-                         int64_t limit,
-                         uint64_t offset,
-                         TALER_MERCHANTDB_RewardsCallback cb,
-                         void *cb_cls)
-{
-  struct PostgresClosure *pg = cls;
-  struct LookupMerchantRewardsContext plc = {
-    .pg = pg,
-    .cb = cb,
-    .cb_cls = cb_cls
-  };
-  uint64_t ulimit = (limit > 0) ? limit : -limit;
-  uint8_t bexpired;
-  struct GNUNET_TIME_Absolute now = GNUNET_TIME_absolute_get ();
-  struct GNUNET_PQ_QueryParam params[] = {
-    GNUNET_PQ_query_param_string (instance_id),
-    GNUNET_PQ_query_param_uint64 (&ulimit),
-    GNUNET_PQ_query_param_uint64 (&offset),
-    GNUNET_PQ_query_param_absolute_time (&now),
-    GNUNET_PQ_query_param_auto_from_type (&bexpired),
-    GNUNET_PQ_query_param_end
-  };
-  enum GNUNET_DB_QueryStatus qs;
-  char stmt[128];
-
-  bexpired = (TALER_EXCHANGE_YNA_YES == expired);
-  GNUNET_snprintf (stmt,
-                   sizeof (stmt),
-                   "lookup_rewards_%s%s",
-                   (limit > 0) ? "inc" : "dec",
-                   (TALER_EXCHANGE_YNA_ALL == expired) ? "" : "_expired");
-  qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn,
-                                             stmt,
-                                             params,
-                                             &lookup_rewards_cb,
-                                             &plc);
-  if (0 != plc.qs)
-    return plc.qs;
-  return qs;
-}
-
-
-/**
- * Closure for #lookup_pickup_details_cb().
- */
-struct LookupRewardDetailsContext
-{
-  /**
-   * Length of the @e sigs array
-   */
-  unsigned int *pickups_length;
-
-  /**
-   * Where to store the signatures.
-   */
-  struct TALER_MERCHANTDB_PickupDetails **pickups;
-
-  /**
-   * Database handle.
-   */
-  struct PostgresClosure *pg;
-
-  /**
-   * Transaction status.
-   */
-  enum GNUNET_DB_QueryStatus qs;
-
-};
-
-
-/**
- * Function to be called with the results of a SELECT statement
- * that has returned @a num_results results about pickups.
- *
- * @param[in,out] cls of type `struct LookupRewardDetailsContext *`
- * @param result the postgres result
- * @param num_results the number of results in @a result
- */
-static void
-lookup_pickup_details_cb (void *cls,
-                          PGresult *result,
-                          unsigned int num_results)
-{
-  struct LookupRewardDetailsContext *ltdc = cls;
-
-  *ltdc->pickups_length = num_results;
-  *ltdc->pickups = GNUNET_new_array (num_results,
-                                     struct TALER_MERCHANTDB_PickupDetails);
-  for (unsigned int i = 0; i < num_results; i++)
-  {
-    struct TALER_MERCHANTDB_PickupDetails *pd = &((*ltdc->pickups)[i]);
-    uint64_t num_planchets = 0;
-    struct GNUNET_PQ_ResultSpec rs[] = {
-      GNUNET_PQ_result_spec_auto_from_type ("pickup_id",
-                                            &pd->pickup_id),
-      TALER_PQ_result_spec_amount_with_currency ("amount",
-                                                 &pd->requested_amount),
-      GNUNET_PQ_result_spec_uint64 ("num_planchets",
-                                    &num_planchets),
-      GNUNET_PQ_result_spec_end
-    };
-
-    if (GNUNET_OK !=
-        GNUNET_PQ_extract_result (result,
-                                  rs,
-                                  i))
-    {
-      GNUNET_break (0);
-      ltdc->qs = GNUNET_DB_STATUS_HARD_ERROR;
-      GNUNET_array_grow (*ltdc->pickups,
-                         *ltdc->pickups_length,
-                         0);
-      return;
-    }
-
-    pd->num_planchets = num_planchets;
-  }
-}
-
-
-/**
- * Lookup reward details for reward @a reward_id.
- *
- * @param cls closure, typically a connection to the db
- * @param instance_id which instance should we lookup reward details for
- * @param reward_id which reward should we lookup details on
- * @param fpu should we fetch details about individual pickups
- * @param[out] total_authorized amount how high is the reward (with fees)
- * @param[out] total_picked_up how much of the reward was so far picked up 
(with fees)
- * @param[out] justification why was the reward approved
- * @param[out] expiration set to when the reward expires
- * @param[out] reserve_pub set to which reserve is debited
- * @param[out] pickups_length set to the length of @e pickups
- * @param[out] pickups if @a fpu is true, set to details about the pickup 
operations
- * @return transaction status,
- */
-static enum GNUNET_DB_QueryStatus
-postgres_lookup_reward_details (void *cls,
-                                const char *instance_id,
-                                const struct TALER_RewardIdentifierP 
*reward_id,
-                                bool fpu,
-                                struct TALER_Amount *total_authorized,
-                                struct TALER_Amount *total_picked_up,
-                                char **justification,
-                                struct GNUNET_TIME_Timestamp *expiration,
-                                struct TALER_ReservePublicKeyP *reserve_pub,
-                                unsigned int *pickups_length,
-                                struct TALER_MERCHANTDB_PickupDetails 
**pickups)
-{
-  struct PostgresClosure *pg = cls;
-  uint64_t reward_serial;
-  enum GNUNET_DB_QueryStatus qs;
-  {
-    struct GNUNET_PQ_QueryParam params[] = {
-      GNUNET_PQ_query_param_string (instance_id),
-      GNUNET_PQ_query_param_auto_from_type (reward_id),
-      GNUNET_PQ_query_param_end
-    };
-    struct GNUNET_PQ_ResultSpec rs[] = {
-      GNUNET_PQ_result_spec_uint64 ("reward_serial",
-                                    &reward_serial),
-      TALER_PQ_result_spec_amount_with_currency ("amount",
-                                                 total_authorized),
-      TALER_PQ_result_spec_amount_with_currency ("picked_up",
-                                                 total_picked_up),
-      GNUNET_PQ_result_spec_string ("justification",
-                                    justification),
-      GNUNET_PQ_result_spec_timestamp ("expiration",
-                                       expiration),
-      GNUNET_PQ_result_spec_auto_from_type ("reserve_pub",
-                                            reserve_pub),
-      GNUNET_PQ_result_spec_end
-    };
-
-    check_connection (pg);
-    qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
-                                                   "lookup_reward_details",
-                                                   params,
-                                                   rs);
-    if (qs <= 0)
-      return qs;
-    if (! fpu)
-    {
-      *pickups_length = 0;
-      *pickups = NULL;
-      return qs;
-    }
-  }
-  {
-    struct GNUNET_PQ_QueryParam params[] = {
-      GNUNET_PQ_query_param_uint64 (&reward_serial),
-      GNUNET_PQ_query_param_end
-    };
-
-    struct LookupRewardDetailsContext ltdc = {
-      .pickups_length = pickups_length,
-      .pickups = pickups,
-      .pg = pg,
-      .qs = GNUNET_DB_STATUS_SUCCESS_ONE_RESULT
-    };
-
-    qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn,
-                                               "lookup_pickup_details",
-                                               params,
-                                               &lookup_pickup_details_cb,
-                                               &ltdc);
-    if (qs < 0)
-      return qs;
-    return ltdc.qs;
-  }
-}
-
-
-/**
- * Insert blind signature obtained from the exchange during a
- * reward pickup operation.
- *
- * @param cls closure, typically a connection to the db
- * @param pickup_id unique ID for the operation
- * @param offset offset of the blind signature for the pickup
- * @param blind_sig the blind signature
- * @return transaction status, usually
- *      #GNUNET_DB_STATUS_SUCCESS_ONE_RESULT for success
- *      #GNUNET_DB_STATUS_SUCCESS_NO_RESULTS if @a credit_uuid already known
- */
-static enum GNUNET_DB_QueryStatus
-postgres_insert_pickup_blind_signature (
-  void *cls,
-  const struct TALER_PickupIdentifierP *pickup_id,
-  uint32_t offset,
-  const struct TALER_BlindedDenominationSignature *blind_sig)
-{
-  struct PostgresClosure *pg = cls;
-  struct GNUNET_PQ_QueryParam params[] = {
-    GNUNET_PQ_query_param_auto_from_type (pickup_id),
-    GNUNET_PQ_query_param_uint32 (&offset),
-    TALER_PQ_query_param_blinded_denom_sig (blind_sig),
-    GNUNET_PQ_query_param_end
-  };
-
-  check_connection (pg);
-  return GNUNET_PQ_eval_prepared_non_select (pg->conn,
-                                             "insert_pickup_blind_signature",
-                                             params);
-}
-
-
-/**
- * Delete information about a webhook.
- *
- * @param cls closure
- * @param instance_id instance to delete webhook of
- * @param webhook_id webhook to delete
- * @return DB status code, #GNUNET_DB_STATUS_SUCCESS_NO_RESULTS
- *           if webhook unknown.
- */
-static enum GNUNET_DB_QueryStatus
-postgres_delete_webhook (void *cls,
-                         const char *instance_id,
-                         const char *webhook_id)
-{
-  struct PostgresClosure *pg = cls;
-  struct GNUNET_PQ_QueryParam params[] = {
-    GNUNET_PQ_query_param_string (instance_id),
-    GNUNET_PQ_query_param_string (webhook_id),
-    GNUNET_PQ_query_param_end
-  };
-
-  check_connection (pg);
-  return GNUNET_PQ_eval_prepared_non_select (pg->conn,
-                                             "delete_webhook",
-                                             params);
-}
-
-
-/**
- * Insert details about a particular webhook.
- *
- * @param cls closure
- * @param instance_id instance to insert webhook for
- * @param webhook_id webhook identifier of webhook to insert
- * @param wb the webhook details to insert
- * @return database result code
- */
-static enum GNUNET_DB_QueryStatus
-postgres_insert_webhook (void *cls,
-                         const char *instance_id,
-                         const char *webhook_id,
-                         const struct TALER_MERCHANTDB_WebhookDetails *wb)
-{
-  struct PostgresClosure *pg = cls;
-  struct GNUNET_PQ_QueryParam params[] = {
-    GNUNET_PQ_query_param_string (instance_id),
-    GNUNET_PQ_query_param_string (webhook_id),
-    GNUNET_PQ_query_param_string (wb->event_type),
-    GNUNET_PQ_query_param_string (wb->url),
-    GNUNET_PQ_query_param_string (wb->http_method),
-    (NULL == wb->header_template)
-    ? GNUNET_PQ_query_param_null ()
-    : GNUNET_PQ_query_param_string (wb->header_template),
-    (NULL == wb->body_template)
-    ? GNUNET_PQ_query_param_null ()
-    : GNUNET_PQ_query_param_string (wb->body_template),
-    GNUNET_PQ_query_param_end
-  };
-
-  check_connection (pg);
-  return GNUNET_PQ_eval_prepared_non_select (pg->conn,
-                                             "insert_webhook",
-                                             params);
-}
-
-
-/**
- * Update details about a particular webhook.
- *
- * @param cls closure
- * @param instance_id instance to update template for
- * @param webhook_id webhook to update
- * @param wb update to the webhook details on success, can be NULL
- *             (in that case we only want to check if the webhook exists)
- * @return database result code, #GNUNET_DB_STATUS_SUCCESS_NO_RESULTS if the 
webhook
- *         does not yet exist.
- */
-static enum GNUNET_DB_QueryStatus
-postgres_update_webhook (void *cls,
-                         const char *instance_id,
-                         const char *webhook_id,
-                         const struct TALER_MERCHANTDB_WebhookDetails *wb)
-{
-  struct PostgresClosure *pg = cls;
-  struct GNUNET_PQ_QueryParam params[] = {
-    GNUNET_PQ_query_param_string (instance_id),
-    GNUNET_PQ_query_param_string (webhook_id),
-    GNUNET_PQ_query_param_string (wb->event_type),
-    GNUNET_PQ_query_param_string (wb->url),
-    GNUNET_PQ_query_param_string (wb->http_method),
-    (NULL == wb->header_template)
-    ? GNUNET_PQ_query_param_null ()
-    : GNUNET_PQ_query_param_string (wb->header_template),
-    (NULL == wb->body_template)
-    ? GNUNET_PQ_query_param_null ()
-    : GNUNET_PQ_query_param_string (wb->body_template),
-    GNUNET_PQ_query_param_end
-  };
-
-
-  check_connection (pg);
-  return GNUNET_PQ_eval_prepared_non_select (pg->conn,
-                                             "update_webhook",
-                                             params);
-}
-
-
-/**
- * Context used for postgres_lookup_webhook().
- */
-struct LookupWebhookContext
-{
-  /**
-   * Function to call with the results.
-   */
-  TALER_MERCHANTDB_WebhooksCallback cb;
-
-  /**
-   * Closure for @a cb.
-   */
-  void *cb_cls;
-
-  /**
-   * Did database result extraction fail?
-   */
-  bool extract_failed;
-};
-
-
-/**
- * Function to be called with the results of a SELECT statement
- * that has returned @a num_results results about webhook.
- *
- * @param[in,out] cls of type `struct LookupWebhookContext *`
- * @param result the postgres result
- * @param num_results the number of results in @a result
- */
-static void
-lookup_webhooks_cb (void *cls,
-                    PGresult *result,
-                    unsigned int num_results)
-{
-  struct LookupWebhookContext *wlc = cls;
-
-  for (unsigned int i = 0; i < num_results; i++)
-  {
-    char *webhook_id;
-    char *event_type;
-    struct GNUNET_PQ_ResultSpec rs[] = {
-      GNUNET_PQ_result_spec_string ("webhook_id",
-                                    &webhook_id),
-      GNUNET_PQ_result_spec_string ("event_type",
-                                    &event_type),
-      GNUNET_PQ_result_spec_end
-    };
-
-    if (GNUNET_OK !=
-        GNUNET_PQ_extract_result (result,
-                                  rs,
-                                  i))
-    {
-      GNUNET_break (0);
-      wlc->extract_failed = true;
-      return;
-    }
-    wlc->cb (wlc->cb_cls,
-             webhook_id,
-             event_type);
-    GNUNET_PQ_cleanup_result (rs);
-  }
-}
-
-
-/**
- * Lookup all of the webhooks the given instance has configured.
- *
- * @param cls closure
- * @param instance_id instance to lookup webhook for
- * @param cb function to call on all webhook found
- * @param cb_cls closure for @a cb
- * @return database result code
- */
-static enum GNUNET_DB_QueryStatus
-postgres_lookup_webhooks (void *cls,
-                          const char *instance_id,
-                          TALER_MERCHANTDB_WebhooksCallback cb,
-                          void *cb_cls)
-{
-  struct PostgresClosure *pg = cls;
-  struct LookupWebhookContext wlc = {
-    .cb = cb,
-    .cb_cls = cb_cls,
-    /* Can be overwritten by the lookup_webhook_cb */
-    .extract_failed = false,
-  };
-  struct GNUNET_PQ_QueryParam params[] = {
-    GNUNET_PQ_query_param_string (instance_id),
-    GNUNET_PQ_query_param_end
-  };
-  enum GNUNET_DB_QueryStatus qs;
-
-  check_connection (pg);
-  qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn,
-                                             "lookup_webhooks",
-                                             params,
-                                             &lookup_webhooks_cb,
-                                             &wlc);
-  /* If there was an error inside lookup_webhook_cb, return a hard error. */
-  if (wlc.extract_failed)
-    return GNUNET_DB_STATUS_HARD_ERROR;
-  return qs;
-}
-
-
-/**
- * Lookup details about a particular webhook.
- *
- * @param cls closure
- * @param instance_id instance to lookup webhook for
- * @param webhook_id webhook to lookup
- * @param[out] wb set to the webhook details on success, can be NULL
- *             (in that case we only want to check if the webhook exists)
- * @return database result code
- */
-static enum GNUNET_DB_QueryStatus
-postgres_lookup_webhook (void *cls,
-                         const char *instance_id,
-                         const char *webhook_id,
-                         struct TALER_MERCHANTDB_WebhookDetails *wb)
-{
-  struct PostgresClosure *pg = cls;
-  struct GNUNET_PQ_QueryParam params[] = {
-    GNUNET_PQ_query_param_string (instance_id),
-    GNUNET_PQ_query_param_string (webhook_id),
-    GNUNET_PQ_query_param_end
-  };
-
-  if (NULL == wb)
-  {
-    struct GNUNET_PQ_ResultSpec rs_null[] = {
-      GNUNET_PQ_result_spec_end
-    };
-
-    check_connection (pg);
-    return GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
-                                                     "lookup_webhook",
-                                                     params,
-                                                     rs_null);
-  }
-  else
-  {
-    struct GNUNET_PQ_ResultSpec rs[] = {
-      GNUNET_PQ_result_spec_string ("event_type",
-                                    &wb->event_type),
-      GNUNET_PQ_result_spec_string ("url",
-                                    &wb->url),
-      GNUNET_PQ_result_spec_string ("http_method",
-                                    &wb->http_method),
-      GNUNET_PQ_result_spec_allow_null (
-        GNUNET_PQ_result_spec_string ("header_template",
-                                      &wb->header_template),
-        NULL),
-      GNUNET_PQ_result_spec_allow_null (
-        GNUNET_PQ_result_spec_string ("body_template",
-                                      &wb->body_template),
-        NULL),
-      GNUNET_PQ_result_spec_end
-    };
-
-    check_connection (pg);
-    return GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
-                                                     "lookup_webhook",
-                                                     params,
-                                                     rs);
-  }
-}
-
-
-/**
- * Context used for postgres_lookup_webhook().
- */
-struct LookupWebhookDetailContext
-{
-  /**
-   * Function to call with the results.
-   */
-  TALER_MERCHANTDB_WebhookDetailCallback cb;
-
-  /**
-   * Closure for @a cb.
-   */
-  void *cb_cls;
-
-  /**
-   * Did database result extraction fail?
-   */
-  bool extract_failed;
-};
-
-/**
- * Function to be called with the results of a SELECT statement
- * that has returned @a num_results results about webhook.
- *
- * @param[in,out] cls of type `struct LookupPendingWebhookContext *`
- * @param result the postgres result
- * @param num_results the number of results in @a result
- */
-static void
-lookup_webhook_by_event_cb (void *cls,
-                            PGresult *result,
-                            unsigned int num_results)
-{
-  struct LookupWebhookDetailContext *wlc = cls;
-
-  for (unsigned int i = 0; i < num_results; i++)
-  {
-    uint64_t webhook_serial;
-    char *event_type;
-    char *url;
-    char *http_method;
-    char *header_template;
-    char *body_template;
-    struct GNUNET_PQ_ResultSpec rs[] = {
-      GNUNET_PQ_result_spec_uint64 ("webhook_serial",
-                                    &webhook_serial),
-      GNUNET_PQ_result_spec_string ("event_type",
-                                    &event_type),
-      GNUNET_PQ_result_spec_string ("url",
-                                    &url),
-      GNUNET_PQ_result_spec_string ("http_method",
-                                    &http_method),
-      GNUNET_PQ_result_spec_allow_null (
-        GNUNET_PQ_result_spec_string ("header_template",
-                                      &header_template),
-        NULL),
-      GNUNET_PQ_result_spec_allow_null (
-        GNUNET_PQ_result_spec_string ("body_template",
-                                      &body_template),
-        NULL),
-      GNUNET_PQ_result_spec_end
-    };
-
-    if (GNUNET_OK !=
-        GNUNET_PQ_extract_result (result,
-                                  rs,
-                                  i))
-    {
-      GNUNET_break (0);
-      wlc->extract_failed = true;
-      return;
-    }
-    wlc->cb (wlc->cb_cls,
-             webhook_serial,
-             event_type,
-             url,
-             http_method,
-             header_template,
-             body_template);
-    GNUNET_PQ_cleanup_result (rs);
-  }
-}
-
-
-/**
-   * Lookup webhook by event
-   *
-   * @param cls closure
-   * @param instance_id instance to lookup webhook for
-   * @param event_type event that we need to put in the pending webhook
-   * @param[out] cb set to the webhook details on success
-   * @param cb_cls callback closure
-   * @return database result code
-   */
-static enum GNUNET_DB_QueryStatus
-postgres_lookup_webhook_by_event (void *cls,
-                                  const char *instance_id,
-                                  const char *event_type,
-                                  TALER_MERCHANTDB_WebhookDetailCallback cb,
-                                  void *cb_cls)
-{
-  struct PostgresClosure *pg = cls;
-  struct LookupWebhookDetailContext wlc = {
-    .cb = cb,
-    .cb_cls = cb_cls,
-    .extract_failed = false,
-  };
-
-  struct GNUNET_PQ_QueryParam params[] = {
-    GNUNET_PQ_query_param_string (instance_id),
-    GNUNET_PQ_query_param_string (event_type),
-    GNUNET_PQ_query_param_end
-  };
-  enum GNUNET_DB_QueryStatus qs;
-
-  check_connection (pg);
-  qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn,
-                                             "lookup_webhook_by_event",
-                                             params,
-                                             &lookup_webhook_by_event_cb,
-                                             &wlc);
-
-  if (wlc.extract_failed)
-    return GNUNET_DB_STATUS_HARD_ERROR;
-  return qs;
-}
-
-
 /**
  * Insert webhook in the pending webhook.
  *
@@ -1863,30 +579,6 @@ postgres_update_pending_webhook (void *cls,
 }
 
 
-/**
- * Delete a webhook in the pending webhook after the
- * webhook was completed successfully.
- *
- * @param cls closure
- * @param webhook_pending_serial identifies the row that needs to be deleted 
in the pending webhook table
- * @return database result code
- */
-static enum GNUNET_DB_QueryStatus
-postgres_delete_pending_webhook (void *cls,
-                                 uint64_t webhook_pending_serial)
-{
-  struct PostgresClosure *pg = cls;
-  struct GNUNET_PQ_QueryParam params[] = {
-    GNUNET_PQ_query_param_uint64 (&webhook_pending_serial),
-    GNUNET_PQ_query_param_end
-  };
-  check_connection (pg);
-  return GNUNET_PQ_eval_prepared_non_select (pg->conn,
-                                             "delete_pending_webhook",
-                                             params);
-}
-
-
 /**
  * Establish connection to the database.
  *
@@ -1915,298 +607,6 @@ postgres_connect (void *cls)
                             "     (SELECT merchant_serial"
                             "        FROM merchant_instances"
                             "       WHERE merchant_id=$1)"),
-    /* For postgres_lookup_pending_reserves() */
-    GNUNET_PQ_make_prepare ("lookup_pending_reserves",
-                            "SELECT"
-                            " reserve_pub"
-                            ",merchant_id"
-                            ",exchange_url"
-                            ",merchant_initial_balance"
-                            " FROM merchant_reward_reserves mrr"
-                            " JOIN merchant_instances USING (merchant_serial)"
-                            " JOIN merchant_reward_reserve_keys USING 
(reserve_serial)"
-                            " WHERE (mrr.exchange_initial_balance).val=0"
-                            "   AND (mrr.exchange_initial_balance).frac=0"),
-    /* For postgres_lookup_reserve() */
-    GNUNET_PQ_make_prepare ("lookup_reserve",
-                            "SELECT"
-                            " creation_time"
-                            ",expiration"
-                            ",merchant_initial_balance"
-                            ",exchange_initial_balance"
-                            ",rewards_committed"
-                            ",rewards_picked_up"
-                            ",reserve_priv IS NOT NULL AS active"
-                            ",exchange_url"
-                            ",master_pub"
-                            " FROM merchant_reward_reserves"
-                            " FULL OUTER JOIN merchant_reward_reserve_keys 
USING (reserve_serial)"
-                            " WHERE reserve_pub = $2"
-                            "   AND merchant_serial ="
-                            "     (SELECT merchant_serial"
-                            "        FROM merchant_instances"
-                            "       WHERE merchant_id=$1)"),
-    /* For postgres_lookup_reserve() */
-    GNUNET_PQ_make_prepare ("lookup_reserve_rewards",
-                            "SELECT"
-                            " justification"
-                            ",reward_id"
-                            ",amount"
-                            " FROM merchant_rewards"
-                            " WHERE reserve_serial ="
-                            "  (SELECT reserve_serial"
-                            "     FROM merchant_reward_reserves"
-                            "      WHERE reserve_pub=$2"
-                            "        AND merchant_serial ="
-                            "       (SELECT merchant_serial"
-                            "          FROM merchant_instances"
-                            "         WHERE merchant_id=$1))"),
-    /* for postgres_delete_reserve() */
-    GNUNET_PQ_make_prepare ("delete_reserve",
-                            "DELETE"
-                            " FROM merchant_reward_reserve_keys"
-                            " WHERE reserve_serial="
-                            "   (SELECT reserve_serial"
-                            "      FROM merchant_reward_reserves"
-                            "       WHERE reserve_pub=$2"
-                            "         AND merchant_serial="
-                            "     (SELECT merchant_serial"
-                            "        FROM merchant_instances"
-                            "       WHERE merchant_id=$1))"),
-    /* for postgres_purge_reserve() */
-    GNUNET_PQ_make_prepare ("purge_reserve",
-                            "DELETE"
-                            "   FROM merchant_reward_reserves"
-                            "  WHERE reserve_pub=$2"
-                            "    AND merchant_serial="
-                            "    (SELECT merchant_serial"
-                            "       FROM merchant_instances"
-                            "      WHERE merchant_id=$1)"),
-    /* For postgres_lookup_pickup() */
-    GNUNET_PQ_make_prepare ("lookup_pickup",
-                            "SELECT"
-                            " exchange_url"
-                            ",reserve_priv"
-                            ",pickup_serial"
-                            " FROM merchant_reward_pickups"
-                            " JOIN merchant_rewards USING (reward_serial)"
-                            " JOIN merchant_reward_reserves USING 
(reserve_serial)"
-                            " JOIN merchant_reward_reserve_keys USING 
(reserve_serial)"
-                            " WHERE pickup_id = $3"
-                            "   AND reward_id = $2"
-                            "   AND merchant_serial ="
-                            "     (SELECT merchant_serial"
-                            "        FROM merchant_instances"
-                            "       WHERE merchant_id=$1)"),
-    /* For postgres_lookup_pickup() */
-    GNUNET_PQ_make_prepare ("lookup_pickup_signatures",
-                            "SELECT"
-                            " coin_offset"
-                            ",blind_sig"
-                            " FROM merchant_reward_pickup_signatures"
-                            " WHERE pickup_serial = $1"),
-
-    /* For postgres_lookup_reward() */
-    GNUNET_PQ_make_prepare ("lookup_reward",
-                            "SELECT"
-                            " amount"
-                            ",picked_up"
-                            ",merchant_rewards.expiration"
-                            ",exchange_url"
-                            ",next_url"
-                            ",reserve_priv"
-                            " FROM merchant_rewards"
-                            " JOIN merchant_reward_reserves USING 
(reserve_serial)"
-                            " JOIN merchant_reward_reserve_keys USING 
(reserve_serial)"
-                            " WHERE reward_id = $2"
-                            "   AND merchant_serial ="
-                            "     (SELECT merchant_serial"
-                            "        FROM merchant_instances"
-                            "       WHERE merchant_id=$1)"),
-    /* For postgres_lookup_reward() */
-    GNUNET_PQ_make_prepare ("lookup_rewards_inc",
-                            "SELECT"
-                            " reward_serial"
-                            ",reward_id"
-                            ",amount"
-                            ",CAST($4 as BIGINT)" /* otherwise $4 is unused 
and Postgres unhappy */
-                            ",CAST($5 as BOOL)" /* otherwise $5 is unused and 
Postgres unhappy */
-                            " FROM merchant_rewards"
-                            " JOIN merchant_reward_reserves USING 
(reserve_serial)"
-                            " WHERE merchant_serial ="
-                            "     (SELECT merchant_serial"
-                            "        FROM merchant_instances"
-                            "       WHERE merchant_id=$1)"
-                            "   AND"
-                            "    reward_serial > $3"
-                            " ORDER BY reward_serial ASC"
-                            " LIMIT $2"),
-    GNUNET_PQ_make_prepare ("lookup_rewards_dec",
-                            "SELECT"
-                            " reward_serial"
-                            ",reward_id"
-                            ",amount"
-                            ",CAST($4 as BIGINT)" /* otherwise $4 is unused 
and Postgres unhappy */
-                            ",CAST($5 as BOOL)" /* otherwise $5 is unused and 
Postgres unhappy */
-                            " FROM merchant_rewards"
-                            " JOIN merchant_reward_reserves USING 
(reserve_serial)"
-                            " WHERE merchant_serial ="
-                            "     (SELECT merchant_serial"
-                            "        FROM merchant_instances"
-                            "       WHERE merchant_id=$1)"
-                            "   AND"
-                            "    reward_serial < $3"
-                            " ORDER BY reward_serial DESC"
-                            " LIMIT $2"),
-    GNUNET_PQ_make_prepare ("lookup_rewards_inc_expired",
-                            "SELECT"
-                            " reward_serial"
-                            ",reward_id"
-                            ",amount"
-                            " FROM merchant_rewards"
-                            " JOIN merchant_reward_reserves USING 
(reserve_serial)"
-                            " WHERE merchant_serial ="
-                            "     (SELECT merchant_serial"
-                            "        FROM merchant_instances"
-                            "       WHERE merchant_id=$1)"
-                            "   AND"
-                            "    reward_serial > $3"
-                            "   AND"
-                            "    CAST($5 as BOOL) = 
(merchant_rewards.expiration < $4)"
-                            " ORDER BY reward_serial ASC"
-                            " LIMIT $2"),
-    GNUNET_PQ_make_prepare ("lookup_rewards_dec_expired",
-                            "SELECT"
-                            " reward_serial"
-                            ",reward_id"
-                            ",amount"
-                            " FROM merchant_rewards"
-                            " JOIN merchant_reward_reserves USING 
(reserve_serial)"
-                            " WHERE merchant_serial ="
-                            "     (SELECT merchant_serial"
-                            "        FROM merchant_instances"
-                            "       WHERE merchant_id=$1)"
-                            "   AND"
-                            "    reward_serial < $3"
-                            "   AND"
-                            "    CAST($5 as BOOL) = 
(merchant_rewards.expiration < $4)"
-                            " ORDER BY reward_serial DESC"
-                            " LIMIT $2"),
-    /* for postgres_lookup_reward_details() */
-    GNUNET_PQ_make_prepare ("lookup_reward_details",
-                            "SELECT"
-                            " reward_serial"
-                            ",amount"
-                            ",picked_up"
-                            ",justification"
-                            ",merchant_rewards.expiration"
-                            ",reserve_pub"
-                            " FROM merchant_rewards"
-                            " JOIN merchant_reward_reserves USING 
(reserve_serial)"
-                            " WHERE reward_id = $2"
-                            "   AND merchant_serial ="
-                            "     (SELECT merchant_serial"
-                            "        FROM merchant_instances"
-                            "       WHERE merchant_id=$1)"),
-    /* for postgres_lookup_reward_details() */
-    GNUNET_PQ_make_prepare ("lookup_pickup_details",
-                            "SELECT"
-                            " pickup_id"
-                            ",amount"
-                            ",COUNT(blind_sig) AS num_planchets"
-                            " FROM merchant_reward_pickups"
-                            " JOIN merchant_reward_pickup_signatures USING 
(pickup_serial)"
-                            " WHERE reward_serial = $1"
-                            " GROUP BY pickup_serial"),
-    /* for postgres_insert_pickup_blind_signature() */
-    GNUNET_PQ_make_prepare ("insert_pickup_blind_signature",
-                            "INSERT INTO merchant_reward_pickup_signatures"
-                            "(pickup_serial"
-                            ",coin_offset"
-                            ",blind_sig"
-                            ") "
-                            "SELECT"
-                            " pickup_serial, $2, $3"
-                            " FROM merchant_reward_pickups"
-                            " WHERE pickup_id=$1"),
-    /* for postgres_lookup_webhooks() */
-    GNUNET_PQ_make_prepare ("lookup_webhooks",
-                            "SELECT"
-                            " webhook_id"
-                            ",event_type"
-                            " FROM merchant_webhook"
-                            " JOIN merchant_instances"
-                            "   USING (merchant_serial)"
-                            " WHERE merchant_instances.merchant_id=$1"),
-    /* for postgres_lookup_webhook() */
-    GNUNET_PQ_make_prepare ("lookup_webhook",
-                            "SELECT"
-                            " event_type"
-                            ",url"
-                            ",http_method"
-                            ",header_template"
-                            ",body_template"
-                            " FROM merchant_webhook"
-                            " JOIN merchant_instances"
-                            "   USING (merchant_serial)"
-                            " WHERE merchant_instances.merchant_id=$1"
-                            "   AND merchant_webhook.webhook_id=$2"),
-    /* for postgres_delete_webhook() */
-    GNUNET_PQ_make_prepare ("delete_webhook",
-                            "DELETE"
-                            " FROM merchant_webhook"
-                            " WHERE merchant_webhook.merchant_serial="
-                            "     (SELECT merchant_serial "
-                            "        FROM merchant_instances"
-                            "        WHERE merchant_id=$1)"
-                            "   AND merchant_webhook.webhook_id=$2"),
-    /* for postgres_insert_webhook() */
-    GNUNET_PQ_make_prepare ("insert_webhook",
-                            "INSERT INTO merchant_webhook"
-                            "(merchant_serial"
-                            ",webhook_id"
-                            ",event_type"
-                            ",url"
-                            ",http_method"
-                            ",header_template"
-                            ",body_template"
-                            ")"
-                            " SELECT merchant_serial,"
-                            " $2, $3, $4, $5, $6, $7"
-                            " FROM merchant_instances"
-                            " WHERE merchant_id=$1"),
-    /* for postgres_update_webhook() */
-    GNUNET_PQ_make_prepare ("update_webhook",
-                            "UPDATE merchant_webhook SET"
-                            " event_type=$3"
-                            ",url=$4"
-                            ",http_method=$5"
-                            ",header_template=$6"
-                            ",body_template=$7"
-                            " WHERE merchant_serial="
-                            "   (SELECT merchant_serial"
-                            "      FROM merchant_instances"
-                            "      WHERE merchant_id=$1)"
-                            "   AND webhook_id=$2"),
-    /* for postgres_lookup_webhook_by_event() */
-    GNUNET_PQ_make_prepare ("lookup_webhook_by_event",
-                            "SELECT"
-                            " webhook_serial"
-                            ",event_type"
-                            ",url"
-                            ",http_method"
-                            ",header_template"
-                            ",body_template"
-                            " FROM merchant_webhook"
-                            " JOIN merchant_instances"
-                            "   USING (merchant_serial)"
-                            " WHERE merchant_instances.merchant_id=$1"
-                            "  AND event_type=$2"),
-    /* for postgres_delete_pending_webhook() */
-    GNUNET_PQ_make_prepare ("delete_pending_webhook",
-                            "DELETE"
-                            " FROM merchant_pending_webhooks"
-                            " WHERE webhook_pending_serial=$1"),
     /* for postgres_insert_pending_webhook() */
     GNUNET_PQ_make_prepare ("insert_pending_webhook",
                             "INSERT INTO merchant_pending_webhooks"
@@ -2494,16 +894,24 @@ libtaler_plugin_merchantdb_postgres_init (void *cls)
     = &TMH_PG_select_accounts;
   plugin->lookup_reserves
     = &TMH_PG_lookup_reserves;
-  plugin->lookup_pending_reserves = &postgres_lookup_pending_reserves;
-  plugin->lookup_reserve = &postgres_lookup_reserve;
-  plugin->delete_reserve = &postgres_delete_reserve;
-  plugin->purge_reserve = &postgres_purge_reserve;
-  plugin->lookup_pickup = &postgres_lookup_pickup;
-  plugin->lookup_reward = &postgres_lookup_reward;
-  plugin->lookup_rewards = &postgres_lookup_rewards;
-  plugin->lookup_reward_details = &postgres_lookup_reward_details;
-  plugin->insert_pickup_blind_signature =
-    &postgres_insert_pickup_blind_signature;
+  plugin->lookup_pending_reserves
+    = &TMH_PG_lookup_pending_reserves;
+  plugin->lookup_reserve
+    = &TMH_PG_lookup_reserve;
+  plugin->delete_reserve
+    = &TMH_PG_delete_reserve;
+  plugin->purge_reserve
+    = &TMH_PG_purge_reserve;
+  plugin->lookup_pickup
+    = &TMH_PG_lookup_pickup;
+  plugin->lookup_reward
+    = &TMH_PG_lookup_reward;
+  plugin->lookup_rewards
+    = &TMH_PG_lookup_rewards;
+  plugin->lookup_reward_details
+    = &TMH_PG_lookup_reward_details;
+  plugin->insert_pickup_blind_signature
+    = &TMH_PG_insert_pickup_blind_signature;
   plugin->select_open_transfers
     = &TMH_PG_select_open_transfers;
   plugin->insert_exchange_keys
@@ -2526,16 +934,23 @@ libtaler_plugin_merchantdb_postgres_init (void *cls)
     = &TMH_PG_authorize_reward;
   plugin->insert_pickup
     = &TMH_PG_insert_pickup;
-  plugin->lookup_webhooks = &postgres_lookup_webhooks;
-  plugin->lookup_webhook = &postgres_lookup_webhook;
-  plugin->delete_webhook = &postgres_delete_webhook;
-  plugin->insert_webhook = &postgres_insert_webhook;
-  plugin->update_webhook = &postgres_update_webhook;
-  plugin->lookup_webhook_by_event = &postgres_lookup_webhook_by_event;
+  plugin->lookup_webhooks
+    = &TMH_PG_lookup_webhooks;
+  plugin->lookup_webhook
+    = &TMH_PG_lookup_webhook;
+  plugin->delete_webhook
+    = &TMH_PG_delete_webhook;
+  plugin->insert_webhook
+    = &TMH_PG_insert_webhook;
+  plugin->update_webhook
+    = &TMH_PG_update_webhook;
+  plugin->lookup_webhook_by_event
+    = &TMH_PG_lookup_webhook_by_event;
   plugin->lookup_all_webhooks = &postgres_lookup_all_webhooks;
   plugin->lookup_future_webhook = &postgres_lookup_future_webhook;
   plugin->lookup_pending_webhooks = &postgres_lookup_pending_webhooks;
-  plugin->delete_pending_webhook = &postgres_delete_pending_webhook;
+  plugin->delete_pending_webhook
+    = &TMH_PG_delete_pending_webhook;
   plugin->insert_pending_webhook = &postgres_insert_pending_webhook;
   plugin->update_pending_webhook = &postgres_update_pending_webhook;
   plugin->delete_exchange_accounts

-- 
To stop receiving notification emails like this one, please contact
gnunet@gnunet.org.



reply via email to

[Prev in Thread] Current Thread [Next in Thread]