gnunet-svn
[Top][All Lists]
Advanced

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

[taler-exchange] branch master updated: remove more functions


From: gnunet
Subject: [taler-exchange] branch master updated: remove more functions
Date: Mon, 14 Nov 2022 13:36:40 +0100

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

joseph-xu pushed a commit to branch master
in repository exchange.

The following commit(s) were added to refs/heads/master by this push:
     new 6991ca01 remove more functions
6991ca01 is described below

commit 6991ca011b4f97d24066f82ccd09adde8a692f6a
Author: Joseph <Joseph.xu@efrei.net>
AuthorDate: Mon Nov 14 07:35:56 2022 -0500

    remove more functions
---
 contrib/gana                                       |     2 +-
 src/exchangedb/Makefile.am                         |   103 +
 src/exchangedb/pg_abort_shard.c                    |    54 +
 src/exchangedb/pg_abort_shard.h                    |    42 +
 src/exchangedb/pg_add_denomination_key.c           |    89 +
 src/exchangedb/pg_add_denomination_key.h           |    46 +
 src/exchangedb/pg_add_policy_fulfillment_proof.c   |   132 +
 src/exchangedb/pg_add_policy_fulfillment_proof.h   |    39 +
 src/exchangedb/pg_aggregate.c                      |   205 +
 src/exchangedb/pg_aggregate.h                      |    46 +
 src/exchangedb/pg_begin_shard.c                    |   258 +
 src/exchangedb/pg_begin_shard.h                    |    47 +
 src/exchangedb/pg_complete_shard.c                 |    59 +
 src/exchangedb/pg_complete_shard.h                 |    42 +
 src/exchangedb/pg_compute_shard.c                  |    49 +
 src/exchangedb/pg_compute_shard.h                  |    39 +
 src/exchangedb/pg_count_known_coins.c              |    63 +
 src/exchangedb/pg_count_known_coins.h              |    39 +
 src/exchangedb/pg_create_aggregation_transient.c   |    64 +
 src/exchangedb/pg_create_aggregation_transient.h   |    49 +
 src/exchangedb/pg_create_tables.c                  |    47 +
 src/exchangedb/pg_create_tables.h                  |    37 +
 src/exchangedb/pg_delete_shard_locks.c             |    42 +
 src/exchangedb/pg_delete_shard_locks.h             |    38 +
 src/exchangedb/pg_do_batch_withdraw.c              |    78 +
 src/exchangedb/pg_do_batch_withdraw.h              |    51 +
 src/exchangedb/pg_do_deposit.c                     |    86 +
 src/exchangedb/pg_do_deposit.h                     |    52 +
 src/exchangedb/pg_do_melt.c                        |    82 +
 src/exchangedb/pg_do_melt.h                        |    49 +
 src/exchangedb/pg_do_recoup.c                      |    86 +
 src/exchangedb/pg_do_recoup.h                      |    56 +
 src/exchangedb/pg_do_recoup_refresh.c              |    79 +
 src/exchangedb/pg_do_recoup_refresh.h              |    56 +
 src/exchangedb/pg_do_refund.c                      |    90 +
 src/exchangedb/pg_do_refund.h                      |    52 +
 src/exchangedb/pg_drain_kyc_alert.c                |    59 +
 src/exchangedb/pg_drain_kyc_alert.h                |    40 +
 src/exchangedb/pg_ensure_coin_known.c              |   159 +
 src/exchangedb/pg_ensure_coin_known.h              |    45 +
 src/exchangedb/pg_event_listen.c                   |    53 +
 src/exchangedb/pg_event_listen.h                   |    45 +
 src/exchangedb/pg_event_listen_cancel.c            |    37 +
 src/exchangedb/pg_event_listen_cancel.h            |    38 +
 src/exchangedb/pg_event_notify.c                   |    41 +
 src/exchangedb/pg_event_notify.h                   |    42 +
 src/exchangedb/pg_expire_purse.c                   |    69 +
 src/exchangedb/pg_expire_purse.h                   |    41 +
 src/exchangedb/pg_find_aggregation_transient.c     |   151 +
 src/exchangedb/pg_find_aggregation_transient.h     |    43 +
 src/exchangedb/pg_gc.c                             |    80 +
 src/exchangedb/pg_gc.h                             |    38 +
 src/exchangedb/pg_get_coin_denomination.c          |    71 +
 src/exchangedb/pg_get_coin_denomination.h          |    43 +
 src/exchangedb/pg_get_denomination_info.c          |    99 +
 src/exchangedb/pg_get_denomination_info.h          |    41 +
 src/exchangedb/pg_get_denomination_revocation.c    |    63 +
 src/exchangedb/pg_get_denomination_revocation.h    |    44 +
 src/exchangedb/pg_get_global_fee.c                 |    91 +
 src/exchangedb/pg_get_global_fee.h                 |    52 +
 src/exchangedb/pg_get_global_fees.c                |   175 +
 src/exchangedb/pg_get_global_fees.h                |    40 +
 src/exchangedb/pg_get_known_coin.c                 |    71 +
 src/exchangedb/pg_get_known_coin.h                 |    40 +
 src/exchangedb/pg_get_melt.c                       |   128 +
 src/exchangedb/pg_get_melt.h                       |    44 +
 src/exchangedb/pg_get_old_coin_by_h_blind.c        |    65 +
 src/exchangedb/pg_get_old_coin_by_h_blind.h        |    44 +
 src/exchangedb/pg_get_policy_details.c             |    65 +
 src/exchangedb/pg_get_policy_details.h             |    40 +
 src/exchangedb/pg_get_ready_deposit.c              |    94 +
 src/exchangedb/pg_get_ready_deposit.h              |    46 +
 src/exchangedb/pg_get_refresh_reveal.c             |   214 +
 src/exchangedb/pg_get_refresh_reveal.h             |    44 +
 src/exchangedb/pg_get_reserve_balance.c            |    55 +
 src/exchangedb/pg_get_reserve_balance.h            |    40 +
 src/exchangedb/pg_get_reserve_by_h_blind.c         |    63 +
 src/exchangedb/pg_get_reserve_by_h_blind.h         |    44 +
 src/exchangedb/pg_get_wire_accounts.c              |   129 +
 src/exchangedb/pg_get_wire_accounts.h              |    42 +
 src/exchangedb/pg_get_wire_fee.c                   |    78 +
 src/exchangedb/pg_get_wire_fee.h                   |    49 +
 src/exchangedb/pg_get_wire_fees.c                  |   150 +
 src/exchangedb/pg_get_wire_fees.h                  |    44 +
 src/exchangedb/pg_get_withdraw_info.c              |    85 +
 src/exchangedb/pg_get_withdraw_info.h              |    43 +
 src/exchangedb/pg_have_deposit2.c                  |   120 +
 src/exchangedb/pg_have_deposit2.h                  |    53 +
 src/exchangedb/pg_insert_auditor.c                 |    58 +
 src/exchangedb/pg_insert_auditor.h                 |    45 +
 src/exchangedb/pg_insert_auditor_denom_sig.c       |    61 +
 src/exchangedb/pg_insert_auditor_denom_sig.h       |    43 +
 src/exchangedb/pg_insert_denomination_revocation.c |    54 +
 src/exchangedb/pg_insert_denomination_revocation.h |    42 +
 src/exchangedb/pg_insert_deposit.c                 |   104 +
 src/exchangedb/pg_insert_deposit.h                 |    40 +
 src/exchangedb/pg_insert_global_fee.c              |   137 +
 src/exchangedb/pg_insert_global_fee.h              |    50 +
 src/exchangedb/pg_insert_partner.c                 |    70 +
 src/exchangedb/pg_insert_partner.h                 |    51 +
 src/exchangedb/pg_insert_refresh_reveal.c          |    94 +
 src/exchangedb/pg_insert_refresh_reveal.h          |    51 +
 src/exchangedb/pg_insert_refund.c                  |    66 +
 src/exchangedb/pg_insert_refund.h                  |    38 +
 src/exchangedb/pg_insert_reserve_closed.c          |   114 +
 src/exchangedb/pg_insert_reserve_closed.h          |    51 +
 src/exchangedb/pg_insert_signkey_revocation.c      |    53 +
 src/exchangedb/pg_insert_signkey_revocation.h      |    41 +
 src/exchangedb/pg_insert_wire.c                    |    56 +
 src/exchangedb/pg_insert_wire.h                    |    44 +
 src/exchangedb/pg_insert_wire_fee.c                |   108 +
 src/exchangedb/pg_insert_wire_fee.h                |    46 +
 src/exchangedb/pg_iterate_active_auditors.c        |   124 +
 src/exchangedb/pg_iterate_active_auditors.h        |    41 +
 src/exchangedb/pg_iterate_auditor_denominations.c  |   121 +
 src/exchangedb/pg_iterate_auditor_denominations.h  |    44 +
 src/exchangedb/pg_iterate_denomination_info.c      |   194 +
 src/exchangedb/pg_iterate_denomination_info.h      |    41 +
 src/exchangedb/pg_iterate_denominations.c          |   179 +
 src/exchangedb/pg_iterate_denominations.h          |    44 +
 src/exchangedb/pg_lookup_auditor_status.c          |    61 +
 src/exchangedb/pg_lookup_auditor_status.h          |    44 +
 src/exchangedb/pg_lookup_auditor_timestamp.c       |    57 +
 src/exchangedb/pg_lookup_auditor_timestamp.h       |    41 +
 src/exchangedb/pg_lookup_denomination_key.c        |    88 +
 src/exchangedb/pg_lookup_denomination_key.h        |    41 +
 src/exchangedb/pg_lookup_signing_key.c             |    65 +
 src/exchangedb/pg_lookup_signing_key.h             |    42 +
 src/exchangedb/pg_lookup_signkey_revocation.c      |    61 +
 src/exchangedb/pg_lookup_signkey_revocation.h      |    42 +
 src/exchangedb/pg_lookup_transfer_by_deposit.c     |   203 +
 src/exchangedb/pg_lookup_transfer_by_deposit.h     |    61 +
 src/exchangedb/pg_lookup_wire_timestamp.c          |    56 +
 src/exchangedb/pg_lookup_wire_timestamp.h          |    40 +
 src/exchangedb/pg_lookup_wire_transfer.c           |   187 +
 src/exchangedb/pg_lookup_wire_transfer.h           |    45 +
 src/exchangedb/pg_persist_policy_details.c         |    67 +
 src/exchangedb/pg_persist_policy_details.h         |    45 +
 src/exchangedb/pg_release_revolving_shard.c        |    59 +
 src/exchangedb/pg_release_revolving_shard.h        |    44 +
 src/exchangedb/pg_reserves_get.c                   |    61 +
 src/exchangedb/pg_reserves_get.h                   |    40 +
 src/exchangedb/pg_reserves_get_origin.c            |    57 +
 src/exchangedb/pg_reserves_get_origin.h            |    41 +
 src/exchangedb/pg_reserves_in_insert.c             |   297 +
 src/exchangedb/pg_reserves_in_insert.h             |    51 +
 src/exchangedb/pg_reserves_update.c                |    53 +
 src/exchangedb/pg_reserves_update.h                |    40 +
 src/exchangedb/pg_select_aggregation_transient.c   |    67 +
 src/exchangedb/pg_select_aggregation_transient.h   |    47 +
 src/exchangedb/pg_select_auditor_denom_sig.c       |    67 +
 src/exchangedb/pg_select_auditor_denom_sig.h       |    43 +
 .../pg_select_deposits_above_serial_id.c           |   197 +
 .../pg_select_deposits_above_serial_id.h           |    44 +
 src/exchangedb/pg_select_deposits_missing_wire.c   |   176 +
 src/exchangedb/pg_select_deposits_missing_wire.h   |    46 +
 .../pg_select_history_requests_above_serial_id.c   |   159 +
 .../pg_select_history_requests_above_serial_id.h   |    44 +
 src/exchangedb/pg_select_purse_by_merge_pub.c      |    83 +
 src/exchangedb/pg_select_purse_by_merge_pub.h      |    54 +
 .../pg_select_purse_decisions_above_serial_id.c    |   164 +
 .../pg_select_purse_decisions_above_serial_id.h    |    46 +
 src/exchangedb/pg_select_purse_deposits_by_purse.c |   153 +
 src/exchangedb/pg_select_purse_deposits_by_purse.h |    44 +
 src/exchangedb/pg_select_recoup_above_serial_id.c  |   196 +
 src/exchangedb/pg_select_recoup_above_serial_id.h  |    44 +
 .../pg_select_recoup_refresh_above_serial_id.c     |   207 +
 .../pg_select_recoup_refresh_above_serial_id.h     |    45 +
 .../pg_select_refreshes_above_serial_id.c          |   185 +
 .../pg_select_refreshes_above_serial_id.h          |    45 +
 src/exchangedb/pg_select_refunds_above_serial_id.c |   211 +
 src/exchangedb/pg_select_refunds_above_serial_id.h |    45 +
 src/exchangedb/pg_select_refunds_by_coin.c         |   143 +
 src/exchangedb/pg_select_refunds_by_coin.h         |    47 +
 .../pg_select_reserves_in_above_serial_id.c        |   167 +
 .../pg_select_reserves_in_above_serial_id.h        |    44 +
 ...select_reserves_in_above_serial_id_by_account.c |   169 +
 ...select_reserves_in_above_serial_id_by_account.h |    46 +
 .../pg_select_wire_out_above_serial_id.c           |   159 +
 .../pg_select_wire_out_above_serial_id.h           |    45 +
 ...pg_select_wire_out_above_serial_id_by_account.c |   162 +
 ...pg_select_wire_out_above_serial_id_by_account.h |    46 +
 .../pg_select_withdrawals_above_serial_id.c        |   175 +
 .../pg_select_withdrawals_above_serial_id.h        |    44 +
 src/exchangedb/pg_set_extension_manifest.c         |    56 +
 src/exchangedb/pg_set_extension_manifest.h         |    43 +
 src/exchangedb/pg_set_purse_balance.c              |    55 +
 src/exchangedb/pg_set_purse_balance.h              |    43 +
 src/exchangedb/pg_setup_foreign_servers.c          |   118 +
 src/exchangedb/pg_setup_foreign_servers.h          |    39 +
 src/exchangedb/pg_setup_wire_target.c              |    54 +
 src/exchangedb/pg_setup_wire_target.h              |    43 +
 src/exchangedb/pg_start_deferred_wire_out.c        |    59 +
 src/exchangedb/pg_start_deferred_wire_out.h        |    39 +
 src/exchangedb/pg_store_wire_transfer_out.c        |    63 +
 src/exchangedb/pg_store_wire_transfer_out.h        |    48 +
 src/exchangedb/pg_update_aggregation_transient.c   |    60 +
 src/exchangedb/pg_update_aggregation_transient.h   |    46 +
 src/exchangedb/pg_update_wire.c                    |    54 +
 src/exchangedb/pg_update_wire.h                    |    43 +
 src/exchangedb/pg_wire_prepare_data_get.c          |   142 +
 src/exchangedb/pg_wire_prepare_data_get.h          |    45 +
 src/exchangedb/pg_wire_prepare_data_insert.c       |    54 +
 src/exchangedb/pg_wire_prepare_data_insert.h       |    42 +
 src/exchangedb/pg_wire_prepare_data_mark_failed.c  |    50 +
 src/exchangedb/pg_wire_prepare_data_mark_failed.h  |    39 +
 .../pg_wire_prepare_data_mark_finished.c           |    49 +
 .../pg_wire_prepare_data_mark_finished.h           |    39 +
 src/exchangedb/plugin_exchangedb_postgres.c        | 10667 ++++++-------------
 209 files changed, 18645 insertions(+), 7336 deletions(-)

diff --git a/contrib/gana b/contrib/gana
index a4a6b9ba..d83d2584 160000
--- a/contrib/gana
+++ b/contrib/gana
@@ -1 +1 @@
-Subproject commit a4a6b9ba4b2634c56194d53e36344686d7052cef
+Subproject commit d83d2584fd4698719b8eb78a4e0e9c8dad698aca
diff --git a/src/exchangedb/Makefile.am b/src/exchangedb/Makefile.am
index bae4eba0..ac300a9c 100644
--- a/src/exchangedb/Makefile.am
+++ b/src/exchangedb/Makefile.am
@@ -68,7 +68,10 @@ endif
 
 libtaler_plugin_exchangedb_postgres_la_SOURCES = \
   plugin_exchangedb_common.c plugin_exchangedb_common.h \
+  pg_setup_wire_target.h pg_setup_wire_target.c \
+  pg_compute_shard.h pg_compute_shard.c \
   plugin_exchangedb_postgres.c pg_helper.h \
+  pg_reserves_update.h pg_reserves_update.c \
   pg_insert_aggregation_tracking.h pg_insert_aggregation_tracking.c \
   pg_select_aggregation_amounts_for_kyc_check.h 
pg_select_aggregation_amounts_for_kyc_check.c \
   pg_lookup_wire_fee_by_time.h pg_lookup_wire_fee_by_time.c \
@@ -90,6 +93,106 @@ libtaler_plugin_exchangedb_postgres_la_SOURCES = \
   pg_select_purse_merge.h pg_select_purse_merge.c \
   pg_select_contract_by_purse.h pg_select_contract_by_purse.c \
   pg_insert_drain_profit.h pg_insert_drain_profit.c \
+  pg_create_tables.h pg_create_tables.c \
+  pg_setup_foreign_servers.h pg_setup_foreign_servers.c \
+  pg_event_listen.h pg_event_listen.c \
+  pg_event_listen_cancel.h pg_event_listen_cancel.c \
+  pg_event_notify.h pg_event_notify.c \
+  pg_get_denomination_info.h pg_get_denomination_info.c \
+  pg_iterate_denomination_info.h pg_iterate_denomination_info.c \
+  pg_iterate_denominations.h pg_iterate_denominations.c \
+  pg_iterate_active_auditors.h pg_iterate_active_auditors.c \
+  pg_iterate_auditor_denominations.h pg_iterate_auditor_denominations.c \
+  pg_reserves_get.h pg_reserves_get.c \
+  pg_reserves_get_origin.h pg_reserves_get_origin.c \
+  pg_drain_kyc_alert.h pg_drain_kyc_alert.c \
+  pg_reserves_in_insert.h pg_reserves_in_insert.c \
+  pg_get_withdraw_info.h pg_get_withdraw_info.c \
+  pg_do_batch_withdraw.h pg_do_batch_withdraw.c \
+  pg_get_policy_details.h pg_get_policy_details.c \
+  pg_persist_policy_details.h pg_persist_policy_details.c \
+  pg_do_deposit.h pg_do_deposit.c \
+  pg_add_policy_fulfillment_proof.h pg_add_policy_fulfillment_proof.c \
+  pg_do_melt.h pg_do_melt.c \
+  pg_do_refund.h pg_do_refund.c \
+  pg_do_recoup.h pg_do_recoup.c \
+  pg_do_recoup_refresh.h pg_do_recoup_refresh.c \
+  pg_get_reserve_balance.h pg_get_reserve_balance.c \
+  pg_count_known_coins.h pg_count_known_coins.c \
+  pg_ensure_coin_known.h pg_ensure_coin_known.c \
+  pg_get_known_coin.h pg_get_known_coin.c \
+  pg_get_coin_denomination.h pg_get_coin_denomination.c \
+  pg_have_deposit2.h pg_have_deposit2.c \
+  pg_aggregate.h pg_aggregate.c \
+  pg_create_aggregation_transient.h pg_create_aggregation_transient.c \
+  pg_select_aggregation_transient.h pg_select_aggregation_transient.c \
+  pg_find_aggregation_transient.h pg_find_aggregation_transient.c \
+  pg_update_aggregation_transient.h pg_update_aggregation_transient.c \
+  pg_get_ready_deposit.h pg_get_ready_deposit.c \
+  pg_insert_deposit.h pg_insert_deposit.c \
+  pg_insert_refund.h pg_insert_refund.c \
+  pg_select_refunds_by_coin.h pg_select_refunds_by_coin.c \
+  pg_get_melt.h pg_get_melt.c \
+  pg_insert_refresh_reveal.h pg_insert_refresh_reveal.c \
+  pg_get_refresh_reveal.h pg_get_refresh_reveal.c \
+  pg_lookup_wire_transfer.h pg_lookup_wire_transfer.c \
+  pg_lookup_transfer_by_deposit.h pg_lookup_transfer_by_deposit.c \
+  pg_insert_wire_fee.h pg_insert_wire_fee.c \
+  pg_insert_global_fee.h pg_insert_global_fee.c \
+  pg_get_wire_fee.h pg_get_wire_fee.c \
+  pg_get_global_fee.h pg_get_global_fee.c \
+  pg_get_global_fees.h pg_get_global_fees.c \
+  pg_insert_reserve_closed.h pg_insert_reserve_closed.c \
+  pg_wire_prepare_data_insert.h pg_wire_prepare_data_insert.c \
+  pg_wire_prepare_data_mark_finished.h pg_wire_prepare_data_mark_finished.c \
+  pg_wire_prepare_data_mark_failed.h pg_wire_prepare_data_mark_failed.c \
+  pg_wire_prepare_data_get.h pg_wire_prepare_data_get.c \
+  pg_start_deferred_wire_out.h pg_start_deferred_wire_out.c \
+  pg_store_wire_transfer_out.h pg_store_wire_transfer_out.c \
+  pg_gc.h pg_gc.c \
+  pg_select_deposits_above_serial_id.h pg_select_deposits_above_serial_id.c \
+  pg_select_history_requests_above_serial_id.h 
pg_select_history_requests_above_serial_id.c \
+  pg_select_purse_decisions_above_serial_id.h 
pg_select_purse_decisions_above_serial_id.c \
+  pg_select_purse_deposits_by_purse.h pg_select_purse_deposits_by_purse.c \
+  pg_select_refreshes_above_serial_id.h pg_select_refreshes_above_serial_id.c \
+  pg_select_refunds_above_serial_id.h pg_select_refunds_above_serial_id.c \
+  pg_select_reserves_in_above_serial_id.h 
pg_select_reserves_in_above_serial_id.c \
+  pg_select_reserves_in_above_serial_id_by_account.h 
pg_select_reserves_in_above_serial_id_by_account.c \
+  pg_select_withdrawals_above_serial_id.h 
pg_select_withdrawals_above_serial_id.c \
+  pg_select_wire_out_above_serial_id.h pg_select_wire_out_above_serial_id.c \
+  pg_select_wire_out_above_serial_id_by_account.h 
pg_select_wire_out_above_serial_id_by_account.c \
+  pg_select_recoup_above_serial_id.h pg_select_recoup_above_serial_id.c \
+  pg_select_recoup_refresh_above_serial_id.h 
pg_select_recoup_refresh_above_serial_id.c \
+  pg_get_reserve_by_h_blind.h pg_get_reserve_by_h_blind.c \
+  pg_get_old_coin_by_h_blind.h pg_get_old_coin_by_h_blind.c \
+  pg_insert_denomination_revocation.h pg_insert_denomination_revocation.c \
+  pg_get_denomination_revocation.h pg_get_denomination_revocation.c \
+  pg_select_deposits_missing_wire.h pg_select_deposits_missing_wire.c \
+  pg_lookup_auditor_timestamp.h pg_lookup_auditor_timestamp.c \
+  pg_lookup_auditor_status.h pg_lookup_auditor_status.c \
+  pg_insert_auditor.h pg_insert_auditor.c \
+  pg_lookup_wire_timestamp.h pg_lookup_wire_timestamp.c \
+  pg_insert_wire.h pg_insert_wire.c \
+  pg_update_wire.h pg_update_wire.c \
+  pg_get_wire_accounts.h pg_get_wire_accounts.c \
+  pg_get_wire_fees.h pg_get_wire_fees.c \
+  pg_insert_signkey_revocation.h pg_insert_signkey_revocation.c \
+  pg_lookup_signkey_revocation.h pg_lookup_signkey_revocation.c \
+  pg_lookup_denomination_key.h pg_lookup_denomination_key.c \
+  pg_insert_auditor_denom_sig.h pg_insert_auditor_denom_sig.c \
+  pg_select_auditor_denom_sig.h pg_select_auditor_denom_sig.c \
+  pg_add_denomination_key.h pg_add_denomination_key.c \
+  pg_lookup_signing_key.h pg_lookup_signing_key.c \
+  pg_begin_shard.h pg_begin_shard.c \
+  pg_abort_shard.h pg_abort_shard.c \
+  pg_complete_shard.h pg_complete_shard.c \
+  pg_release_revolving_shard.h pg_release_revolving_shard.c \
+  pg_delete_shard_locks.h pg_delete_shard_locks.c \
+  pg_set_extension_manifest.h pg_set_extension_manifest.c \
+  pg_insert_partner.h pg_insert_partner.c \
+  pg_expire_purse.h pg_expire_purse.c \
+  pg_select_purse_by_merge_pub.h pg_select_purse_by_merge_pub.c \
+  pg_set_purse_balance.h pg_set_purse_balance.c \
   pg_do_reserve_purse.h pg_do_reserve_purse.c \
   pg_lookup_global_fee_by_time.h pg_lookup_global_fee_by_time.c \
   pg_do_purse_deposit.h pg_do_purse_deposit.c \
diff --git a/src/exchangedb/pg_abort_shard.c b/src/exchangedb/pg_abort_shard.c
new file mode 100644
index 00000000..de10f7d3
--- /dev/null
+++ b/src/exchangedb/pg_abort_shard.c
@@ -0,0 +1,54 @@
+/*
+   This file is part of TALER
+   Copyright (C) 2022 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 exchangedb/pg_abort_shard.c
+ * @brief Implementation of the abort_shard function for Postgres
+ * @author Christian Grothoff
+ */
+#include "platform.h"
+#include "taler_error_codes.h"
+#include "taler_dbevents.h"
+#include "taler_pq_lib.h"
+#include "pg_abort_shard.h"
+#include "pg_helper.h"
+
+
+enum GNUNET_DB_QueryStatus
+TEH_PG_abort_shard (void *cls,
+                      const char *job_name,
+                      uint64_t start_row,
+                      uint64_t end_row)
+{
+  struct PostgresClosure *pg = cls;
+  struct GNUNET_PQ_QueryParam params[] = {
+    GNUNET_PQ_query_param_string (job_name),
+    GNUNET_PQ_query_param_uint64 (&start_row),
+    GNUNET_PQ_query_param_uint64 (&end_row),
+    GNUNET_PQ_query_param_end
+  };
+
+
+  PREPARE (pg,
+           "abort_shard",
+           "UPDATE work_shards"
+           "   SET last_attempt=0"
+           " WHERE job_name = $1 "
+           "    AND start_row = $2 "
+           "    AND end_row = $3;");
+  return GNUNET_PQ_eval_prepared_non_select (pg->conn,
+                                             "abort_shard",
+                                             params);
+}
diff --git a/src/exchangedb/pg_abort_shard.h b/src/exchangedb/pg_abort_shard.h
new file mode 100644
index 00000000..070b48da
--- /dev/null
+++ b/src/exchangedb/pg_abort_shard.h
@@ -0,0 +1,42 @@
+/*
+   This file is part of TALER
+   Copyright (C) 2022 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 exchangedb/pg_abort_shard.h
+ * @brief implementation of the abort_shard function for Postgres
+ * @author Christian Grothoff
+ */
+#ifndef PG_ABORT_SHARD_H
+#define PG_ABORT_SHARD_H
+
+#include "taler_util.h"
+#include "taler_json_lib.h"
+#include "taler_exchangedb_plugin.h"
+
+/**
+ * Function called to abort work on a shard.
+ *
+ * @param cls the @e cls of this struct with the plugin-specific state
+ * @param job_name name of the operation to abort a word shard for
+ * @param start_row inclusive start row of the shard
+ * @param end_row exclusive end row of the shard
+ * @return transaction status code
+ */
+enum GNUNET_DB_QueryStatus
+TEH_PG_abort_shard (void *cls,
+                      const char *job_name,
+                      uint64_t start_row,
+                    uint64_t end_row);
+#endif
diff --git a/src/exchangedb/pg_add_denomination_key.c 
b/src/exchangedb/pg_add_denomination_key.c
new file mode 100644
index 00000000..e115a44e
--- /dev/null
+++ b/src/exchangedb/pg_add_denomination_key.c
@@ -0,0 +1,89 @@
+/*
+   This file is part of TALER
+   Copyright (C) 2022 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 exchangedb/pg_add_denomination_key.c
+ * @brief Implementation of the add_denomination_key function for Postgres
+ * @author Christian Grothoff
+ */
+#include "platform.h"
+#include "taler_error_codes.h"
+#include "taler_dbevents.h"
+#include "taler_pq_lib.h"
+#include "pg_add_denomination_key.h"
+#include "pg_helper.h"
+
+
+enum GNUNET_DB_QueryStatus
+TEH_PG_add_denomination_key (
+  void *cls,
+  const struct TALER_DenominationHashP *h_denom_pub,
+  const struct TALER_DenominationPublicKey *denom_pub,
+  const struct TALER_EXCHANGEDB_DenominationKeyMetaData *meta,
+  const struct TALER_MasterSignatureP *master_sig)
+{
+  struct PostgresClosure *pg = cls;
+  struct GNUNET_PQ_QueryParam iparams[] = {
+    GNUNET_PQ_query_param_auto_from_type (h_denom_pub),
+    TALER_PQ_query_param_denom_pub (denom_pub),
+    GNUNET_PQ_query_param_auto_from_type (master_sig),
+    GNUNET_PQ_query_param_timestamp (&meta->start),
+    GNUNET_PQ_query_param_timestamp (&meta->expire_withdraw),
+    GNUNET_PQ_query_param_timestamp (&meta->expire_deposit),
+    GNUNET_PQ_query_param_timestamp (&meta->expire_legal),
+    TALER_PQ_query_param_amount (&meta->value),
+    TALER_PQ_query_param_amount (&meta->fees.withdraw),
+    TALER_PQ_query_param_amount (&meta->fees.deposit),
+    TALER_PQ_query_param_amount (&meta->fees.refresh),
+    TALER_PQ_query_param_amount (&meta->fees.refund),
+    GNUNET_PQ_query_param_uint32 (&meta->age_mask.bits),
+    GNUNET_PQ_query_param_end
+  };
+
+  /* Sanity check: ensure fees match coin currency */
+  GNUNET_assert (GNUNET_YES ==
+                 TALER_denom_fee_check_currency (meta->value.currency,
+                                                 &meta->fees));
+    /* Used in #postgres_insert_denomination_info() and
+     #postgres_add_denomination_key() */
+  PREPARE (pg,
+           "denomination_insert",
+           "INSERT INTO denominations "
+           "(denom_pub_hash"
+           ",denom_pub"
+           ",master_sig"
+           ",valid_from"
+           ",expire_withdraw"
+           ",expire_deposit"
+           ",expire_legal"
+           ",coin_val"                                                /* value 
of this denom */
+           ",coin_frac"                                                /* 
fractional value of this denom */
+           ",fee_withdraw_val"
+           ",fee_withdraw_frac"
+           ",fee_deposit_val"
+           ",fee_deposit_frac"
+           ",fee_refresh_val"
+           ",fee_refresh_frac"
+           ",fee_refund_val"
+           ",fee_refund_frac"
+           ",age_mask"
+           ") VALUES "
+           "($1, $2, $3, $4, $5, $6, $7, $8, $9, $10,"
+           " $11, $12, $13, $14, $15, $16, $17, $18);");
+  return GNUNET_PQ_eval_prepared_non_select (pg->conn,
+                                             "denomination_insert",
+                                             iparams);
+}
+
diff --git a/src/exchangedb/pg_add_denomination_key.h 
b/src/exchangedb/pg_add_denomination_key.h
new file mode 100644
index 00000000..d131679e
--- /dev/null
+++ b/src/exchangedb/pg_add_denomination_key.h
@@ -0,0 +1,46 @@
+/*
+   This file is part of TALER
+   Copyright (C) 2022 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 exchangedb/pg_add_denomination_key.h
+ * @brief implementation of the add_denomination_key function for Postgres
+ * @author Christian Grothoff
+ */
+#ifndef PG_ADD_DENOMINATION_KEY_H
+#define PG_ADD_DENOMINATION_KEY_H
+
+#include "taler_util.h"
+#include "taler_json_lib.h"
+#include "taler_exchangedb_plugin.h"
+
+/**
+ * Activate denomination key, turning it into a "current" or "valid"
+ * denomination key by adding the master signature.
+ *
+ * @param cls closure
+ * @param h_denom_pub hash of the denomination public key
+ * @param denom_pub the actual denomination key
+ * @param meta meta data about the denomination
+ * @param master_sig master signature to add
+ * @return transaction status code
+ */
+enum GNUNET_DB_QueryStatus
+TEH_PG_add_denomination_key (
+  void *cls,
+  const struct TALER_DenominationHashP *h_denom_pub,
+  const struct TALER_DenominationPublicKey *denom_pub,
+  const struct TALER_EXCHANGEDB_DenominationKeyMetaData *meta,
+  const struct TALER_MasterSignatureP *master_sig);
+#endif
diff --git a/src/exchangedb/pg_add_policy_fulfillment_proof.c 
b/src/exchangedb/pg_add_policy_fulfillment_proof.c
new file mode 100644
index 00000000..bb06206a
--- /dev/null
+++ b/src/exchangedb/pg_add_policy_fulfillment_proof.c
@@ -0,0 +1,132 @@
+/*
+   This file is part of TALER
+   Copyright (C) 2022 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 exchangedb/pg_add_policy_fulfillment_proof.c
+ * @brief Implementation of the add_policy_fulfillment_proof function for 
Postgres
+ * @author Christian Grothoff
+ */
+#include "platform.h"
+#include "taler_error_codes.h"
+#include "taler_dbevents.h"
+#include "taler_pq_lib.h"
+#include "pg_add_policy_fulfillment_proof.h"
+#include "pg_helper.h"
+
+
+/**
+ * Compares two indices into an array of hash codes according to
+ * GNUNET_CRYPTO_hash_cmp of the content at those index positions.
+ *
+ * Used in a call qsort_t in order to generate sorted policy_hash_codes.
+ */
+static int
+hash_code_cmp (
+  const void *hc1,
+  const void *hc2,
+  void *arg)
+{
+  size_t i1 = *(size_t *) hc1;
+  size_t i2 = *(size_t *) hc2;
+  const struct TALER_PolicyDetails *d = arg;
+
+  return GNUNET_CRYPTO_hash_cmp (&d[i1].hash_code,
+                                 &d[i2].hash_code);
+}
+
+
+enum GNUNET_DB_QueryStatus
+TEH_PG_add_policy_fulfillment_proof (
+  void *cls,
+  struct TALER_PolicyFulfillmentTransactionData *fulfillment)
+{
+  enum GNUNET_DB_QueryStatus qs;
+  struct PostgresClosure *pg = cls;
+  size_t count = fulfillment->details_count;
+  struct GNUNET_HashCode hcs[count];
+
+  /* Create the sorted policy_hash_codes */
+  {
+    size_t idx[count];
+    for (size_t i = 0; i < count; i++)
+      idx[i] = i;
+
+    /* Sort the indices according to the hash codes of the corresponding
+     * details. */
+    qsort_r (idx,
+             count,
+             sizeof(size_t),
+             hash_code_cmp,
+             fulfillment->details);
+
+    /* Finally, concatenate all hash_codes in sorted order */
+    for (size_t i = 0; i < count; i++)
+      hcs[i] = fulfillment->details[idx[i]].hash_code;
+  }
+
+
+  /* Now, add the proof to the policy_fulfillments table, retrieve the
+   * record_id */
+  {
+    struct GNUNET_PQ_QueryParam params[] = {
+      GNUNET_PQ_query_param_timestamp (&fulfillment->timestamp),
+      TALER_PQ_query_param_json (fulfillment->proof),
+      GNUNET_PQ_query_param_auto_from_type (&fulfillment->h_proof),
+      GNUNET_PQ_query_param_fixed_size (hcs,
+                                        count * sizeof(struct 
GNUNET_HashCode)),
+      GNUNET_PQ_query_param_end
+    };
+    struct GNUNET_PQ_ResultSpec rs[] = {
+      GNUNET_PQ_result_spec_uint64 ("fulfillment_id",
+                                    &fulfillment->fulfillment_id),
+      GNUNET_PQ_result_spec_end
+    };
+
+    
+    qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
+                                                   
"insert_proof_into_policy_fulfillments",
+                                                   params,
+                                                   rs);
+    if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != qs)
+      return qs;
+  }
+
+  /* Now, set the states of each entry corresponding to the hash_codes in
+   * policy_details accordingly */
+  for (size_t i = 0; i < count; i++)
+  {
+    struct TALER_PolicyDetails *pos = &fulfillment->details[i];
+    {
+      struct GNUNET_PQ_QueryParam params[] = {
+        GNUNET_PQ_query_param_auto_from_type (&pos->hash_code),
+        GNUNET_PQ_query_param_timestamp (&pos->deadline),
+        TALER_PQ_query_param_amount (&pos->commitment),
+        TALER_PQ_query_param_amount (&pos->accumulated_total),
+        TALER_PQ_query_param_amount (&pos->policy_fee),
+        TALER_PQ_query_param_amount (&pos->transferable_amount),
+        GNUNET_PQ_query_param_auto_from_type (&pos->fulfillment_state),
+        GNUNET_PQ_query_param_end
+      };
+
+      qs = GNUNET_PQ_eval_prepared_non_select (pg->conn,
+                                               "update_policy_details",
+                                               params);
+      if (qs < 0)
+        return qs;
+    }
+  }
+
+  return qs;
+}
diff --git a/src/exchangedb/pg_add_policy_fulfillment_proof.h 
b/src/exchangedb/pg_add_policy_fulfillment_proof.h
new file mode 100644
index 00000000..77bddaf0
--- /dev/null
+++ b/src/exchangedb/pg_add_policy_fulfillment_proof.h
@@ -0,0 +1,39 @@
+/*
+   This file is part of TALER
+   Copyright (C) 2022 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 exchangedb/pg_add_policy_fulfillment_proof.h
+ * @brief implementation of the add_policy_fulfillment_proof function for 
Postgres
+ * @author Christian Grothoff
+ */
+#ifndef PG_ADD_POLICY_FULFILLMENT_PROOF_H
+#define PG_ADD_POLICY_FULFILLMENT_PROOF_H
+
+#include "taler_util.h"
+#include "taler_json_lib.h"
+#include "taler_exchangedb_plugin.h"
+/**
+ * Add a proof of fulfillment into the policy_fulfillments table
+ *
+ * @param cls the `struct PostgresClosure` with the plugin-specific state
+ * @param fulfillment fullfilment transaction data to be added
+ * @return query execution status
+ */
+enum GNUNET_DB_QueryStatus
+TEH_PG_add_policy_fulfillment_proof (
+  void *cls,
+  struct TALER_PolicyFulfillmentTransactionData *fulfillment);
+
+#endif
diff --git a/src/exchangedb/pg_aggregate.c b/src/exchangedb/pg_aggregate.c
new file mode 100644
index 00000000..f1c4d677
--- /dev/null
+++ b/src/exchangedb/pg_aggregate.c
@@ -0,0 +1,205 @@
+/*
+   This file is part of TALER
+   Copyright (C) 2022 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 exchangedb/pg_aggregate.c
+ * @brief Implementation of the aggregate function for Postgres
+ * @author Christian Grothoff
+ */
+#include "platform.h"
+#include "taler_error_codes.h"
+#include "taler_dbevents.h"
+#include "taler_pq_lib.h"
+#include "pg_aggregate.h"
+#include "pg_helper.h"
+
+enum GNUNET_DB_QueryStatus
+TEH_PG_aggregate (
+  void *cls,
+  const struct TALER_PaytoHashP *h_payto,
+  const struct TALER_MerchantPublicKeyP *merchant_pub,
+  const struct TALER_WireTransferIdentifierRawP *wtid,
+  struct TALER_Amount *total)
+{
+  struct PostgresClosure *pg = cls;
+  struct GNUNET_TIME_Absolute now = {0};
+  struct GNUNET_PQ_QueryParam params[] = {
+    GNUNET_PQ_query_param_absolute_time (&now),
+    GNUNET_PQ_query_param_auto_from_type (merchant_pub),
+    GNUNET_PQ_query_param_auto_from_type (h_payto),
+    GNUNET_PQ_query_param_auto_from_type (wtid),
+    GNUNET_PQ_query_param_end
+  };
+  uint64_t sum_deposit_value;
+  uint64_t sum_deposit_frac;
+  uint64_t sum_refund_value;
+  uint64_t sum_refund_frac;
+  uint64_t sum_fee_value;
+  uint64_t sum_fee_frac;
+  struct GNUNET_PQ_ResultSpec rs[] = {
+    GNUNET_PQ_result_spec_uint64 ("sum_deposit_value",
+                                  &sum_deposit_value),
+    GNUNET_PQ_result_spec_uint64 ("sum_deposit_fraction",
+                                  &sum_deposit_frac),
+    GNUNET_PQ_result_spec_uint64 ("sum_refund_value",
+                                  &sum_refund_value),
+    GNUNET_PQ_result_spec_uint64 ("sum_refund_fraction",
+                                  &sum_refund_frac),
+    GNUNET_PQ_result_spec_uint64 ("sum_fee_value",
+                                  &sum_fee_value),
+    GNUNET_PQ_result_spec_uint64 ("sum_fee_fraction",
+                                  &sum_fee_frac),
+    GNUNET_PQ_result_spec_end
+  };
+  enum GNUNET_DB_QueryStatus qs;
+  struct TALER_Amount sum_deposit;
+  struct TALER_Amount sum_refund;
+  struct TALER_Amount sum_fee;
+  struct TALER_Amount delta;
+
+  now = GNUNET_TIME_absolute_round_down (GNUNET_TIME_absolute_get (),
+                                         pg->aggregator_shift);
+
+    /* Used in #postgres_aggregate() */
+  PREPARE (pg,
+           "aggregate",
+           "WITH rdy AS (" /* find deposits ready by merchant */
+           "  SELECT"
+           "    coin_pub"
+           "    FROM deposits_for_matching"
+           "    WHERE refund_deadline<$1" /* filter by shard, only actually 
executable deposits */
+           "      AND merchant_pub=$2" /* filter by target merchant */
+           "    ORDER BY refund_deadline ASC" /* ordering is not critical */
+           "    LIMIT "
+           TALER_QUOTE (TALER_EXCHANGEDB_MATCHING_DEPOSITS_LIMIT) /* limits 
transaction size */
+           " )"
+           " ,dep AS (" /* restrict to our merchant and account and mark as 
done */
+           "  UPDATE deposits"
+           "     SET done=TRUE"
+           "   WHERE coin_pub IN (SELECT coin_pub FROM rdy)"
+           "     AND merchant_pub=$2" /* theoretically, same coin could be 
spent at another merchant */
+           "     AND wire_target_h_payto=$3" /* merchant could have a 2nd bank 
account */
+           "     AND done=FALSE" /* theoretically, same coin could be spend at 
the same merchant a 2nd time */
+           "   RETURNING"
+           "     deposit_serial_id"
+           "    ,coin_pub"
+           "    ,amount_with_fee_val AS amount_val"
+           "    ,amount_with_fee_frac AS amount_frac)"
+           " ,ref AS (" /* find applicable refunds -- NOTE: may do a full join 
on the master, maybe find a left-join way to integrate with query above to push 
it to the shards? */
+           "  SELECT"
+           "    amount_with_fee_val AS refund_val"
+           "   ,amount_with_fee_frac AS refund_frac"
+           "   ,coin_pub"
+           "   ,deposit_serial_id" /* theoretically, coin could be in multiple 
refunded transactions */
+           "    FROM refunds"
+           "   WHERE coin_pub IN (SELECT coin_pub FROM dep)"
+           "     AND deposit_serial_id IN (SELECT deposit_serial_id FROM dep))"
+           " ,ref_by_coin AS (" /* total up refunds by coin */
+           "  SELECT"
+           "    SUM(refund_val) AS sum_refund_val"
+           "   ,SUM(refund_frac) AS sum_refund_frac"
+           "   ,coin_pub"
+           "   ,deposit_serial_id" /* theoretically, coin could be in multiple 
refunded transactions */
+           "    FROM ref"
+           "   GROUP BY coin_pub, deposit_serial_id)"
+           " ,norm_ref_by_coin AS (" /* normalize */
+           "  SELECT"
+           "    sum_refund_val + sum_refund_frac / 100000000 AS 
norm_refund_val"
+           "   ,sum_refund_frac % 100000000 AS norm_refund_frac"
+           "   ,coin_pub"
+           "   ,deposit_serial_id" /* theoretically, coin could be in multiple 
refunded transactions */
+           "    FROM ref_by_coin)"
+           " ,fully_refunded_coins AS (" /* find applicable refunds -- NOTE: 
may do a full join on the master, maybe find a left-join way to integrate with 
query above to push it to the shards? */
+           "  SELECT"
+           "    dep.coin_pub"
+           "    FROM norm_ref_by_coin norm"
+           "    JOIN dep"
+           "      ON (norm.coin_pub = dep.coin_pub"
+           "      AND norm.deposit_serial_id = dep.deposit_Serial_id"
+           "      AND norm.norm_refund_val = dep.amount_val"
+           "      AND norm.norm_refund_frac = dep.amount_frac))"
+           " ,fees AS (" /* find deposit fees for not fully refunded deposits 
*/
+           "  SELECT"
+           "    denom.fee_deposit_val AS fee_val"
+           "   ,denom.fee_deposit_frac AS fee_frac"
+           "   ,cs.deposit_serial_id" /* ensures we get the fee for each coin, 
not once per denomination */
+           "    FROM dep cs"
+           "    JOIN known_coins kc" /* NOTE: may do a full join on the 
master, maybe find a left-join way to integrate with query above to push it to 
the shards? */
+           "      USING (coin_pub)"
+           "    JOIN denominations denom"
+           "      USING (denominations_serial)"
+           "    WHERE coin_pub NOT IN (SELECT coin_pub FROM 
fully_refunded_coins))"
+           " ,dummy AS (" /* add deposits to aggregation_tracking */
+           "    INSERT INTO aggregation_tracking"
+           "    (deposit_serial_id"
+           "    ,wtid_raw)"
+           "    SELECT deposit_serial_id,$4"
+           "      FROM dep)"
+           "SELECT" /* calculate totals (deposits, refunds and fees) */
+           "  CAST(COALESCE(SUM(dep.amount_val),0) AS INT8) AS 
sum_deposit_value" /* cast needed, otherwise we get NUMBER */
+           " ,COALESCE(SUM(dep.amount_frac),0) AS sum_deposit_fraction" /* SUM 
over INT returns INT8 */
+           " ,CAST(COALESCE(SUM(ref.refund_val),0) AS INT8) AS 
sum_refund_value"
+           " ,COALESCE(SUM(ref.refund_frac),0) AS sum_refund_fraction"
+           " ,CAST(COALESCE(SUM(fees.fee_val),0) AS INT8) AS sum_fee_value"
+           " ,COALESCE(SUM(fees.fee_frac),0) AS sum_fee_fraction"
+           " FROM dep "
+           "   FULL OUTER JOIN ref ON (FALSE)"    /* We just want all sums */
+           "   FULL OUTER JOIN fees ON (FALSE);");
+
+
+  qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
+                                                 "aggregate",
+                                                 params,
+                                                 rs);
+  if (qs < 0)
+  {
+    GNUNET_break (GNUNET_DB_STATUS_SOFT_ERROR == qs);
+    return qs;
+  }
+  if (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS == qs)
+  {
+    GNUNET_assert (GNUNET_OK ==
+                   TALER_amount_set_zero (pg->currency,
+                                          total));
+    return qs;
+  }
+  GNUNET_assert (GNUNET_OK ==
+                 TALER_amount_set_zero (pg->currency,
+                                        &sum_deposit));
+  GNUNET_assert (GNUNET_OK ==
+                 TALER_amount_set_zero (pg->currency,
+                                        &sum_refund));
+  GNUNET_assert (GNUNET_OK ==
+                 TALER_amount_set_zero (pg->currency,
+                                        &sum_fee));
+  sum_deposit.value    = sum_deposit_frac / TALER_AMOUNT_FRAC_BASE
+                         + sum_deposit_value;
+  sum_deposit.fraction = sum_deposit_frac % TALER_AMOUNT_FRAC_BASE;
+  sum_refund.value     = sum_refund_frac  / TALER_AMOUNT_FRAC_BASE
+                         + sum_refund_value;
+  sum_refund.fraction  = sum_refund_frac  % TALER_AMOUNT_FRAC_BASE;
+  sum_fee.value        = sum_fee_frac     / TALER_AMOUNT_FRAC_BASE
+                         + sum_fee_value;
+  sum_fee.fraction     = sum_fee_frac     % TALER_AMOUNT_FRAC_BASE; \
+  GNUNET_assert (0 <=
+                 TALER_amount_subtract (&delta,
+                                        &sum_deposit,
+                                        &sum_refund));
+  GNUNET_assert (0 <=
+                 TALER_amount_subtract (total,
+                                        &delta,
+                                        &sum_fee));
+  return qs;
+}
diff --git a/src/exchangedb/pg_aggregate.h b/src/exchangedb/pg_aggregate.h
new file mode 100644
index 00000000..1f986ef9
--- /dev/null
+++ b/src/exchangedb/pg_aggregate.h
@@ -0,0 +1,46 @@
+/*
+   This file is part of TALER
+   Copyright (C) 2022 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 exchangedb/pg_aggregate.h
+ * @brief implementation of the aggregate function for Postgres
+ * @author Christian Grothoff
+ */
+#ifndef PG_AGGREGATE_H
+#define PG_AGGREGATE_H
+
+#include "taler_util.h"
+#include "taler_json_lib.h"
+#include "taler_exchangedb_plugin.h"
+/**
+ * Aggregate all matching deposits for @a h_payto and
+ * @a merchant_pub, returning the total amounts.
+ *
+ * @param cls the @e cls of this struct with the plugin-specific state
+ * @param h_payto destination of the wire transfer
+ * @param merchant_pub public key of the merchant
+ * @param wtid wire transfer ID to set for the aggregate
+ * @param[out] total set to the sum of the total deposits minus applicable 
deposit fees and refunds
+ * @return transaction status
+ */
+enum GNUNET_DB_QueryStatus
+TEH_PG_aggregate (
+  void *cls,
+  const struct TALER_PaytoHashP *h_payto,
+  const struct TALER_MerchantPublicKeyP *merchant_pub,
+  const struct TALER_WireTransferIdentifierRawP *wtid,
+  struct TALER_Amount *total);
+
+#endif
diff --git a/src/exchangedb/pg_begin_shard.c b/src/exchangedb/pg_begin_shard.c
new file mode 100644
index 00000000..2d4a33af
--- /dev/null
+++ b/src/exchangedb/pg_begin_shard.c
@@ -0,0 +1,258 @@
+/*
+   This file is part of TALER
+   Copyright (C) 2022 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 exchangedb/pg_begin_shard.c
+ * @brief Implementation of the begin_shard function for Postgres
+ * @author Christian Grothoff
+ */
+#include "platform.h"
+#include "taler_error_codes.h"
+#include "taler_dbevents.h"
+#include "taler_pq_lib.h"
+#include "pg_begin_shard.h"
+#include "pg_helper.h"
+#include "pg_start.h"
+#include "pg_rollback.h"
+#include "pg_commit.h"
+
+enum GNUNET_DB_QueryStatus
+TEH_PG_begin_shard (void *cls,
+                      const char *job_name,
+                      struct GNUNET_TIME_Relative delay,
+                      uint64_t shard_size,
+                      uint64_t *start_row,
+                      uint64_t *end_row)
+{
+  struct PostgresClosure *pg = cls;
+
+  for (unsigned int retries = 0; retries<10; retries++)
+  {
+    if (GNUNET_OK !=
+        TEH_PG_start (pg,
+                        "begin_shard"))
+    {
+      GNUNET_break (0);
+      return GNUNET_DB_STATUS_HARD_ERROR;
+    }
+
+    {
+      struct GNUNET_TIME_Absolute past;
+      enum GNUNET_DB_QueryStatus qs;
+      struct GNUNET_PQ_QueryParam params[] = {
+        GNUNET_PQ_query_param_string (job_name),
+        GNUNET_PQ_query_param_absolute_time (&past),
+        GNUNET_PQ_query_param_end
+      };
+      struct GNUNET_PQ_ResultSpec rs[] = {
+        GNUNET_PQ_result_spec_uint64 ("start_row",
+                                      start_row),
+        GNUNET_PQ_result_spec_uint64 ("end_row",
+                                      end_row),
+        GNUNET_PQ_result_spec_end
+      };
+
+      past = GNUNET_TIME_absolute_get ();
+
+      PREPARE (pg,
+               "get_open_shard",
+               "SELECT"
+               " start_row"
+               ",end_row"
+               " FROM work_shards"
+               " WHERE job_name=$1"
+               "   AND completed=FALSE"
+               "   AND last_attempt<$2"
+               " ORDER BY last_attempt ASC"
+               " LIMIT 1;");
+
+      qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
+                                                     "get_open_shard",
+                                                     params,
+                                                     rs);
+      switch (qs)
+      {
+      case GNUNET_DB_STATUS_HARD_ERROR:
+        GNUNET_break (0);
+        TEH_PG_rollback (pg);
+        return qs;
+      case GNUNET_DB_STATUS_SOFT_ERROR:
+        TEH_PG_rollback (pg);
+        continue;
+      case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT:
+        {
+          enum GNUNET_DB_QueryStatus qs;
+          struct GNUNET_TIME_Absolute now;
+          struct GNUNET_PQ_QueryParam params[] = {
+            GNUNET_PQ_query_param_string (job_name),
+            GNUNET_PQ_query_param_absolute_time (&now),
+            GNUNET_PQ_query_param_uint64 (start_row),
+            GNUNET_PQ_query_param_uint64 (end_row),
+            GNUNET_PQ_query_param_end
+          };
+
+          now = GNUNET_TIME_relative_to_absolute (delay);
+
+
+          PREPARE (pg,
+                   "reclaim_shard",
+                   "UPDATE work_shards"
+                   " SET last_attempt=$2"
+                   " WHERE job_name=$1"
+                   "   AND start_row=$3"
+                   "   AND end_row=$4");
+
+          qs = GNUNET_PQ_eval_prepared_non_select (pg->conn,
+                                                   "reclaim_shard",
+                                                   params);
+          switch (qs)
+          {
+          case GNUNET_DB_STATUS_HARD_ERROR:
+            GNUNET_break (0);
+            TEH_PG_rollback (pg);
+            return qs;
+          case GNUNET_DB_STATUS_SOFT_ERROR:
+            TEH_PG_rollback (pg);
+            continue;
+          case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT:
+            goto commit;
+          case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS:
+            GNUNET_break (0); /* logic error, should be impossible */
+            TEH_PG_rollback (pg);
+            return GNUNET_DB_STATUS_HARD_ERROR;
+          }
+        }
+        break; /* actually unreachable */
+      case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS:
+        break; /* continued below */
+      }
+    } /* get_open_shard */
+
+    /* No open shard, find last 'end_row' */
+    {
+      enum GNUNET_DB_QueryStatus qs;
+      struct GNUNET_PQ_QueryParam params[] = {
+        GNUNET_PQ_query_param_string (job_name),
+        GNUNET_PQ_query_param_end
+      };
+      struct GNUNET_PQ_ResultSpec rs[] = {
+        GNUNET_PQ_result_spec_uint64 ("end_row",
+                                      start_row),
+        GNUNET_PQ_result_spec_end
+      };
+
+      PREPARE (pg,
+               "get_last_shard",
+               "SELECT"
+               " end_row"
+               " FROM work_shards"
+               " WHERE job_name=$1"
+               " ORDER BY end_row DESC"
+               " LIMIT 1;");
+      qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
+                                                     "get_last_shard",
+                                                     params,
+                                                     rs);
+      switch (qs)
+      {
+      case GNUNET_DB_STATUS_HARD_ERROR:
+        GNUNET_break (0);
+        TEH_PG_rollback (pg);
+        return qs;
+      case GNUNET_DB_STATUS_SOFT_ERROR:
+        TEH_PG_rollback (pg);
+        continue;
+      case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT:
+        break;
+      case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS:
+        *start_row = 0; /* base-case: no shards yet */
+        break; /* continued below */
+      }
+      *end_row = *start_row + shard_size;
+    } /* get_last_shard */
+
+    /* Claim fresh shard */
+    {
+      enum GNUNET_DB_QueryStatus qs;
+      struct GNUNET_TIME_Absolute now;
+      struct GNUNET_PQ_QueryParam params[] = {
+        GNUNET_PQ_query_param_string (job_name),
+        GNUNET_PQ_query_param_absolute_time (&now),
+        GNUNET_PQ_query_param_uint64 (start_row),
+        GNUNET_PQ_query_param_uint64 (end_row),
+        GNUNET_PQ_query_param_end
+      };
+
+      now = GNUNET_TIME_relative_to_absolute (delay);
+      GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+                  "Trying to claim shard (%llu-%llu]\n",
+                  (unsigned long long) *start_row,
+                  (unsigned long long) *end_row);
+
+      PREPARE (pg,
+               "claim_next_shard",
+               "INSERT INTO work_shards"
+               "(job_name"
+               ",last_attempt"
+               ",start_row"
+               ",end_row"
+               ") VALUES "
+               "($1, $2, $3, $4);");
+      qs = GNUNET_PQ_eval_prepared_non_select (pg->conn,
+                                               "claim_next_shard",
+                                               params);
+      switch (qs)
+      {
+      case GNUNET_DB_STATUS_HARD_ERROR:
+        GNUNET_break (0);
+        TEH_PG_rollback (pg);
+        return qs;
+      case GNUNET_DB_STATUS_SOFT_ERROR:
+        TEH_PG_rollback (pg);
+        continue;
+      case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT:
+        /* continued below */
+        break;
+      case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS:
+        /* someone else got this shard already,
+           try again */
+        TEH_PG_rollback (pg);
+        continue;
+      }
+    } /* claim_next_shard */
+
+    /* commit */
+commit:
+    {
+      enum GNUNET_DB_QueryStatus qs;
+
+      qs = TEH_PG_commit (pg);
+      switch (qs)
+      {
+      case GNUNET_DB_STATUS_HARD_ERROR:
+        GNUNET_break (0);
+        TEH_PG_rollback (pg);
+        return qs;
+      case GNUNET_DB_STATUS_SOFT_ERROR:
+        TEH_PG_rollback (pg);
+        continue;
+      case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS:
+      case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT:
+        return GNUNET_DB_STATUS_SUCCESS_ONE_RESULT;
+      }
+    }
+  } /* retry 'for' loop */
+  return GNUNET_DB_STATUS_SOFT_ERROR;
+}
diff --git a/src/exchangedb/pg_begin_shard.h b/src/exchangedb/pg_begin_shard.h
new file mode 100644
index 00000000..39bd834e
--- /dev/null
+++ b/src/exchangedb/pg_begin_shard.h
@@ -0,0 +1,47 @@
+/*
+   This file is part of TALER
+   Copyright (C) 2022 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 exchangedb/pg_begin_shard.h
+ * @brief implementation of the begin_shard function for Postgres
+ * @author Christian Grothoff
+ */
+#ifndef PG_BEGIN_SHARD_H
+#define PG_BEGIN_SHARD_H
+
+#include "taler_util.h"
+#include "taler_json_lib.h"
+#include "taler_exchangedb_plugin.h"
+/**
+ * Function called to grab a work shard on an operation @a op. Runs in its
+ * own transaction.
+ *
+ * @param cls the @e cls of this struct with the plugin-specific state
+ * @param job_name name of the operation to grab a word shard for
+ * @param delay minimum age of a shard to grab
+ * @param shard_size desired shard size
+ * @param[out] start_row inclusive start row of the shard (returned)
+ * @param[out] end_row exclusive end row of the shard (returned)
+ * @return transaction status code
+ */
+enum GNUNET_DB_QueryStatus
+TEH_PG_begin_shard (void *cls,
+                      const char *job_name,
+                      struct GNUNET_TIME_Relative delay,
+                      uint64_t shard_size,
+                      uint64_t *start_row,
+                    uint64_t *end_row);
+
+#endif
diff --git a/src/exchangedb/pg_complete_shard.c 
b/src/exchangedb/pg_complete_shard.c
new file mode 100644
index 00000000..5efea7c0
--- /dev/null
+++ b/src/exchangedb/pg_complete_shard.c
@@ -0,0 +1,59 @@
+/*
+   This file is part of TALER
+   Copyright (C) 2022 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 exchangedb/pg_complete_shard.c
+ * @brief Implementation of the complete_shard function for Postgres
+ * @author Christian Grothoff
+ */
+#include "platform.h"
+#include "taler_error_codes.h"
+#include "taler_dbevents.h"
+#include "taler_pq_lib.h"
+#include "pg_complete_shard.h"
+#include "pg_helper.h"
+
+enum GNUNET_DB_QueryStatus
+TEH_PG_complete_shard (void *cls,
+                         const char *job_name,
+                         uint64_t start_row,
+                         uint64_t end_row)
+{
+  struct PostgresClosure *pg = cls;
+
+  struct GNUNET_PQ_QueryParam params[] = {
+    GNUNET_PQ_query_param_string (job_name),
+    GNUNET_PQ_query_param_uint64 (&start_row),
+    GNUNET_PQ_query_param_uint64 (&end_row),
+    GNUNET_PQ_query_param_end
+  };
+
+  GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+              "Completing shard %llu-%llu\n",
+              (unsigned long long) start_row,
+              (unsigned long long) end_row);
+
+
+  PREPARE (pg,
+           "complete_shard",
+           "UPDATE work_shards"
+           " SET completed=TRUE"
+           " WHERE job_name=$1"
+           "   AND start_row=$2"
+           "   AND end_row=$3");
+  return GNUNET_PQ_eval_prepared_non_select (pg->conn,
+                                             "complete_shard",
+                                             params);
+}
diff --git a/src/exchangedb/pg_complete_shard.h 
b/src/exchangedb/pg_complete_shard.h
new file mode 100644
index 00000000..8693f402
--- /dev/null
+++ b/src/exchangedb/pg_complete_shard.h
@@ -0,0 +1,42 @@
+/*
+   This file is part of TALER
+   Copyright (C) 2022 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 exchangedb/pg_complete_shard.h
+ * @brief implementation of the complete_shard function for Postgres
+ * @author Christian Grothoff
+ */
+#ifndef PG_COMPLETE_SHARD_H
+#define PG_COMPLETE_SHARD_H
+
+#include "taler_util.h"
+#include "taler_json_lib.h"
+#include "taler_exchangedb_plugin.h"
+
+/**
+ * Function called to persist that work on a shard was completed.
+ *
+ * @param cls the @e cls of this struct with the plugin-specific state
+ * @param job_name name of the operation to grab a word shard for
+ * @param start_row inclusive start row of the shard
+ * @param end_row exclusive end row of the shard
+ * @return transaction status code
+ */
+enum GNUNET_DB_QueryStatus
+TEH_PG_complete_shard (void *cls,
+                         const char *job_name,
+                         uint64_t start_row,
+                       uint64_t end_row);
+#endif
diff --git a/src/exchangedb/pg_compute_shard.c 
b/src/exchangedb/pg_compute_shard.c
new file mode 100644
index 00000000..1dea591f
--- /dev/null
+++ b/src/exchangedb/pg_compute_shard.c
@@ -0,0 +1,49 @@
+/*
+   This file is part of TALER
+   Copyright (C) 2022 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 exchangedb/pg_compute_shard.c
+ * @brief Implementation of the compute_shard function for Postgres
+ * @author Christian Grothoff
+ */
+#include "platform.h"
+#include "taler_error_codes.h"
+#include "taler_dbevents.h"
+#include "taler_pq_lib.h"
+#include "pg_compute_shard.h"
+#include "pg_helper.h"
+
+
+uint64_t
+TEH_PG_compute_shard (const struct TALER_MerchantPublicKeyP *merchant_pub)
+{
+  uint32_t res;
+
+  GNUNET_assert (GNUNET_YES ==
+                 GNUNET_CRYPTO_kdf (&res,
+                                    sizeof (res),
+                                    merchant_pub,
+                                    sizeof (*merchant_pub),
+                                    "VOID",
+                                    4,
+                                    NULL, 0));
+  /* interpret hash result as NBO for platform independence,
+     convert to HBO and map to [0..2^31-1] range */
+  res = ntohl (res);
+  if (res > INT32_MAX)
+    res += INT32_MIN;
+  GNUNET_assert (res <= INT32_MAX);
+  return (uint64_t) res;
+}
diff --git a/src/exchangedb/pg_compute_shard.h 
b/src/exchangedb/pg_compute_shard.h
new file mode 100644
index 00000000..d9bde2d3
--- /dev/null
+++ b/src/exchangedb/pg_compute_shard.h
@@ -0,0 +1,39 @@
+/*
+   This file is part of TALER
+   Copyright (C) 2022 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 exchangedb/pg_compute_shard.h
+ * @brief implementation of the compute_shard function for Postgres
+ * @author Christian Grothoff
+ */
+#ifndef PG_COMPUTE_SHARD_H
+#define PG_COMPUTE_SHARD_H
+
+#include "taler_util.h"
+#include "taler_json_lib.h"
+#include "taler_exchangedb_plugin.h"
+
+
+/**
+ * Compute the shard number of a given @a merchant_pub.
+ *
+ * @param merchant_pub merchant public key to compute shard for
+ * @return shard number
+ */
+uint64_t
+TEH_PG_compute_shard (const struct TALER_MerchantPublicKeyP *merchant_pub);
+
+
+#endif
diff --git a/src/exchangedb/pg_count_known_coins.c 
b/src/exchangedb/pg_count_known_coins.c
new file mode 100644
index 00000000..28c4612f
--- /dev/null
+++ b/src/exchangedb/pg_count_known_coins.c
@@ -0,0 +1,63 @@
+/*
+   This file is part of TALER
+   Copyright (C) 2022 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 exchangedb/pg_count_known_coins.c
+ * @brief Implementation of the count_known_coins function for Postgres
+ * @author Christian Grothoff
+ */
+#include "platform.h"
+#include "taler_error_codes.h"
+#include "taler_dbevents.h"
+#include "taler_pq_lib.h"
+#include "pg_count_known_coins.h"
+#include "pg_helper.h"
+
+long long
+TEH_PG_count_known_coins (void *cls,
+                            const struct
+                            TALER_DenominationHashP *denom_pub_hash)
+{
+  struct PostgresClosure *pg = cls;
+  uint64_t count;
+  struct GNUNET_PQ_QueryParam params[] = {
+    GNUNET_PQ_query_param_auto_from_type (denom_pub_hash),
+    GNUNET_PQ_query_param_end
+  };
+  struct GNUNET_PQ_ResultSpec rs[] = {
+    GNUNET_PQ_result_spec_uint64 ("count",
+                                  &count),
+    GNUNET_PQ_result_spec_end
+  };
+  enum GNUNET_DB_QueryStatus qs;
+
+
+  PREPARE (pg,
+           "count_known_coins",
+           "SELECT"
+           " COUNT(*) AS count"
+           " FROM known_coins"
+           " WHERE denominations_serial="
+           "  (SELECT denominations_serial"
+           "    FROM denominations"
+           "    WHERE denom_pub_hash=$1);");
+  qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
+                                                 "count_known_coins",
+                                                 params,
+                                                 rs);
+  if (0 > qs)
+    return (long long) qs;
+  return (long long) count;
+}
diff --git a/src/exchangedb/pg_count_known_coins.h 
b/src/exchangedb/pg_count_known_coins.h
new file mode 100644
index 00000000..f5dd4f27
--- /dev/null
+++ b/src/exchangedb/pg_count_known_coins.h
@@ -0,0 +1,39 @@
+/*
+   This file is part of TALER
+   Copyright (C) 2022 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 exchangedb/pg_count_known_coins.h
+ * @brief implementation of the count_known_coins function for Postgres
+ * @author Christian Grothoff
+ */
+#ifndef PG_COUNT_KNOWN_COINS_H
+#define PG_COUNT_KNOWN_COINS_H
+
+#include "taler_util.h"
+#include "taler_json_lib.h"
+#include "taler_exchangedb_plugin.h"
+/**
+ * Count the number of known coins by denomination.
+ *
+ * @param cls database connection plugin state
+ * @param denom_pub_hash denomination to count by
+ * @return number of coins if non-negative, otherwise an `enum 
GNUNET_DB_QueryStatus`
+ */
+long long
+TEH_PG_count_known_coins (void *cls,
+                            const struct
+                          TALER_DenominationHashP *denom_pub_hash);
+
+#endif
diff --git a/src/exchangedb/pg_create_aggregation_transient.c 
b/src/exchangedb/pg_create_aggregation_transient.c
new file mode 100644
index 00000000..4ced9da0
--- /dev/null
+++ b/src/exchangedb/pg_create_aggregation_transient.c
@@ -0,0 +1,64 @@
+/*
+   This file is part of TALER
+   Copyright (C) 2022 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 exchangedb/pg_create_aggregation_transient.c
+ * @brief Implementation of the create_aggregation_transient function for 
Postgres
+ * @author Christian Grothoff
+ */
+#include "platform.h"
+#include "taler_error_codes.h"
+#include "taler_dbevents.h"
+#include "taler_pq_lib.h"
+#include "pg_create_aggregation_transient.h"
+#include "pg_helper.h"
+
+
+enum GNUNET_DB_QueryStatus
+TEH_PG_create_aggregation_transient (
+  void *cls,
+  const struct TALER_PaytoHashP *h_payto,
+  const char *exchange_account_section,
+  const struct TALER_MerchantPublicKeyP *merchant_pub,
+  const struct TALER_WireTransferIdentifierRawP *wtid,
+  uint64_t kyc_requirement_row,
+  const struct TALER_Amount *total)
+{
+  struct PostgresClosure *pg = cls;
+  struct GNUNET_PQ_QueryParam params[] = {
+    TALER_PQ_query_param_amount (total),
+    GNUNET_PQ_query_param_auto_from_type (merchant_pub),
+    GNUNET_PQ_query_param_auto_from_type (h_payto),
+    GNUNET_PQ_query_param_uint64 (&kyc_requirement_row),
+    GNUNET_PQ_query_param_string (exchange_account_section),
+    GNUNET_PQ_query_param_auto_from_type (wtid),
+    GNUNET_PQ_query_param_end
+  };
+    /* Used in #postgres_create_aggregation_transient() */
+  PREPARE (pg,
+      "create_aggregation_transient",
+      "INSERT INTO aggregation_transient"
+      " (amount_val"
+      " ,amount_frac"
+      " ,merchant_pub"
+      " ,wire_target_h_payto"
+      " ,legitimization_requirement_serial_id"
+      " ,exchange_account_section"
+      " ,wtid_raw)"
+      " VALUES ($1, $2, $3, $4, $5, $6, $7);");
+  return GNUNET_PQ_eval_prepared_non_select (pg->conn,
+                                             "create_aggregation_transient",
+                                             params);
+}
diff --git a/src/exchangedb/pg_create_aggregation_transient.h 
b/src/exchangedb/pg_create_aggregation_transient.h
new file mode 100644
index 00000000..2f0a348b
--- /dev/null
+++ b/src/exchangedb/pg_create_aggregation_transient.h
@@ -0,0 +1,49 @@
+/*
+   This file is part of TALER
+   Copyright (C) 2022 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 exchangedb/pg_create_aggregation_transient.h
+ * @brief implementation of the create_aggregation_transient function for 
Postgres
+ * @author Christian Grothoff
+ */
+#ifndef PG_CREATE_AGGREGATION_TRANSIENT_H
+#define PG_CREATE_AGGREGATION_TRANSIENT_H
+
+#include "taler_util.h"
+#include "taler_json_lib.h"
+#include "taler_exchangedb_plugin.h"
+/**
+ * Create a new entry in the transient aggregation table.
+ *
+ * @param cls the @e cls of this struct with the plugin-specific state
+ * @param h_payto destination of the wire transfer
+ * @param exchange_account_section exchange account to use
+ * @param merchant_pub public key of the merchant receiving the transfer
+ * @param wtid the raw wire transfer identifier to be used
+ * @param kyc_requirement_row row in legitimization_requirements that need to 
be satisfied to continue, or 0 for none
+ * @param total amount to be wired in the future
+ * @return transaction status
+ */
+enum GNUNET_DB_QueryStatus
+TEH_PG_create_aggregation_transient (
+  void *cls,
+  const struct TALER_PaytoHashP *h_payto,
+  const char *exchange_account_section,
+  const struct TALER_MerchantPublicKeyP *merchant_pub,
+  const struct TALER_WireTransferIdentifierRawP *wtid,
+  uint64_t kyc_requirement_row,
+  const struct TALER_Amount *total);
+
+#endif
diff --git a/src/exchangedb/pg_create_tables.c 
b/src/exchangedb/pg_create_tables.c
new file mode 100644
index 00000000..63211cf5
--- /dev/null
+++ b/src/exchangedb/pg_create_tables.c
@@ -0,0 +1,47 @@
+/*
+   This file is part of TALER
+   Copyright (C) 2022 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 exchangedb/pg_create_tables.c
+ * @brief Implementation of the create_tables function for Postgres
+ * @author Christian Grothoff
+ */
+#include "platform.h"
+#include "taler_error_codes.h"
+#include "taler_dbevents.h"
+#include "taler_pq_lib.h"
+#include "pg_create_tables.h"
+#include "pg_helper.h"
+
+
+enum GNUNET_GenericReturnValue
+TEH_PG_create_tables (void *cls)
+{
+  struct PostgresClosure *pg = cls;
+  struct GNUNET_PQ_Context *conn;
+  enum GNUNET_GenericReturnValue ret;
+
+  conn = GNUNET_PQ_connect_with_cfg (pg->cfg,
+                                     "exchangedb-postgres",
+                                     "exchange-",
+                                     NULL,
+                                     NULL);
+  if (NULL == conn)
+    return GNUNET_SYSERR;
+  ret = GNUNET_PQ_exec_sql (conn,
+                            "procedures");
+  GNUNET_PQ_disconnect (conn);
+  return ret;
+}
diff --git a/src/exchangedb/pg_create_tables.h 
b/src/exchangedb/pg_create_tables.h
new file mode 100644
index 00000000..7fb7a56f
--- /dev/null
+++ b/src/exchangedb/pg_create_tables.h
@@ -0,0 +1,37 @@
+/*
+   This file is part of TALER
+   Copyright (C) 2022 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 exchangedb/pg_create_tables.h
+ * @brief implementation of the create_tables function for Postgres
+ * @author Christian Grothoff
+ */
+#ifndef PG_CREATE_TABLES_H
+#define PG_CREATE_TABLES_H
+
+#include "taler_util.h"
+#include "taler_json_lib.h"
+#include "taler_exchangedb_plugin.h"
+
+/**
+ * Create the necessary tables if they are not present
+ *
+ * @param cls the `struct PostgresClosure` with the plugin-specific state
+ * @return #GNUNET_OK upon success; #GNUNET_SYSERR upon failure
+ */
+enum GNUNET_GenericReturnValue
+TEH_PG_create_tables (void *cls);
+
+#endif
diff --git a/src/exchangedb/pg_delete_shard_locks.c 
b/src/exchangedb/pg_delete_shard_locks.c
new file mode 100644
index 00000000..e55cf25f
--- /dev/null
+++ b/src/exchangedb/pg_delete_shard_locks.c
@@ -0,0 +1,42 @@
+/*
+   This file is part of TALER
+   Copyright (C) 2022 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 exchangedb/pg_delete_shard_locks.c
+ * @brief Implementation of the delete_shard_locks function for Postgres
+ * @author Christian Grothoff
+ */
+#include "platform.h"
+#include "taler_error_codes.h"
+#include "taler_dbevents.h"
+#include "taler_pq_lib.h"
+#include "pg_delete_shard_locks.h"
+#include "pg_helper.h"
+
+
+enum GNUNET_GenericReturnValue
+TEH_PG_delete_shard_locks (void *cls)
+{
+  struct PostgresClosure *pg = cls;
+  struct GNUNET_PQ_ExecuteStatement es[] = {
+    GNUNET_PQ_make_execute ("DELETE FROM work_shards;"),
+    GNUNET_PQ_make_execute ("DELETE FROM revolving_work_shards;"),
+    GNUNET_PQ_EXECUTE_STATEMENT_END
+  };
+
+  return GNUNET_PQ_exec_statements (pg->conn,
+                                    es);
+}
+
diff --git a/src/exchangedb/pg_delete_shard_locks.h 
b/src/exchangedb/pg_delete_shard_locks.h
new file mode 100644
index 00000000..e8df2d67
--- /dev/null
+++ b/src/exchangedb/pg_delete_shard_locks.h
@@ -0,0 +1,38 @@
+/*
+   This file is part of TALER
+   Copyright (C) 2022 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 exchangedb/pg_delete_shard_locks.h
+ * @brief implementation of the delete_shard_locks function for Postgres
+ * @author Christian Grothoff
+ */
+#ifndef PG_DELETE_SHARD_LOCKS_H
+#define PG_DELETE_SHARD_LOCKS_H
+
+#include "taler_util.h"
+#include "taler_json_lib.h"
+#include "taler_exchangedb_plugin.h"
+/**
+ * Function called to delete all revolving shards.
+ * To be used after a crash or when the shard size is
+ * changed.
+ *
+ * @param cls the @e cls of this struct with the plugin-specific state
+ * @return transaction status code
+ */
+enum GNUNET_GenericReturnValue
+TEH_PG_delete_shard_locks (void *cls);
+
+#endif
diff --git a/src/exchangedb/pg_do_batch_withdraw.c 
b/src/exchangedb/pg_do_batch_withdraw.c
new file mode 100644
index 00000000..8ef1be26
--- /dev/null
+++ b/src/exchangedb/pg_do_batch_withdraw.c
@@ -0,0 +1,78 @@
+/*
+   This file is part of TALER
+   Copyright (C) 2022 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 exchangedb/pg_do_batch_withdraw.c
+ * @brief Implementation of the do_batch_withdraw function for Postgres
+ * @author Christian Grothoff
+ */
+#include "platform.h"
+#include "taler_error_codes.h"
+#include "taler_dbevents.h"
+#include "taler_pq_lib.h"
+#include "pg_do_batch_withdraw.h"
+#include "pg_helper.h"
+
+
+enum GNUNET_DB_QueryStatus
+TEH_PG_do_batch_withdraw (
+  void *cls,
+  struct GNUNET_TIME_Timestamp now,
+  const struct TALER_ReservePublicKeyP *reserve_pub,
+  const struct TALER_Amount *amount,
+  bool *found,
+  bool *balance_ok,
+  uint64_t *ruuid)
+{
+  struct PostgresClosure *pg = cls;
+  struct GNUNET_TIME_Timestamp gc;
+  struct GNUNET_PQ_QueryParam params[] = {
+    TALER_PQ_query_param_amount (amount),
+    GNUNET_PQ_query_param_auto_from_type (reserve_pub),
+    GNUNET_PQ_query_param_timestamp (&now),
+    GNUNET_PQ_query_param_timestamp (&gc),
+    GNUNET_PQ_query_param_end
+  };
+  struct GNUNET_PQ_ResultSpec rs[] = {
+    GNUNET_PQ_result_spec_bool ("reserve_found",
+                                found),
+    GNUNET_PQ_result_spec_bool ("balance_ok",
+                                balance_ok),
+    GNUNET_PQ_result_spec_uint64 ("ruuid",
+                                  ruuid),
+    GNUNET_PQ_result_spec_end
+  };
+
+  gc = GNUNET_TIME_absolute_to_timestamp (
+    GNUNET_TIME_absolute_add (now.abs_time,
+                              pg->legal_reserve_expiration_time));
+
+
+ /* Used in #postgres_do_batch_withdraw() to
+       update the reserve balance and check its status */
+  PREPARE (pg,
+           "call_batch_withdraw",
+           "SELECT "
+           " reserve_found"
+           ",balance_ok"
+           ",ruuid"
+           " FROM exchange_do_batch_withdraw"
+           " ($1,$2,$3,$4,$5);");
+  return GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
+                                                   "call_batch_withdraw",
+                                                   params,
+                                                   rs);
+}
+
diff --git a/src/exchangedb/pg_do_batch_withdraw.h 
b/src/exchangedb/pg_do_batch_withdraw.h
new file mode 100644
index 00000000..ee4bf293
--- /dev/null
+++ b/src/exchangedb/pg_do_batch_withdraw.h
@@ -0,0 +1,51 @@
+/*
+   This file is part of TALER
+   Copyright (C) 2022 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 exchangedb/pg_do_batch_withdraw.h
+ * @brief implementation of the do_batch_withdraw function for Postgres
+ * @author Christian Grothoff
+ */
+#ifndef PG_DO_BATCH_WITHDRAW_H
+#define PG_DO_BATCH_WITHDRAW_H
+
+#include "taler_util.h"
+#include "taler_json_lib.h"
+#include "taler_exchangedb_plugin.h"
+/**
+ * Perform reserve update as part of a batch withdraw operation, checking
+ * for sufficient balance. Persisting the withdrawal details is done
+ * separately!
+ *
+ * @param cls the `struct PostgresClosure` with the plugin-specific state
+ * @param now current time (rounded)
+ * @param reserve_pub public key of the reserve to debit
+ * @param amount total amount to withdraw
+ * @param[out] found set to true if the reserve was found
+ * @param[out] balance_ok set to true if the balance was sufficient
+ * @param[out] ruuid set to the reserve's UUID (reserves table row)
+ * @return query execution status
+ */
+enum GNUNET_DB_QueryStatus
+TEH_PG_do_batch_withdraw (
+  void *cls,
+  struct GNUNET_TIME_Timestamp now,
+  const struct TALER_ReservePublicKeyP *reserve_pub,
+  const struct TALER_Amount *amount,
+  bool *found,
+  bool *balance_ok,
+  uint64_t *ruuid);
+
+#endif
diff --git a/src/exchangedb/pg_do_deposit.c b/src/exchangedb/pg_do_deposit.c
new file mode 100644
index 00000000..c8f25e5b
--- /dev/null
+++ b/src/exchangedb/pg_do_deposit.c
@@ -0,0 +1,86 @@
+/*
+   This file is part of TALER
+   Copyright (C) 2022 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 exchangedb/pg_do_deposit.c
+ * @brief Implementation of the do_deposit function for Postgres
+ * @author Christian Grothoff
+ */
+#include "platform.h"
+#include "taler_error_codes.h"
+#include "taler_dbevents.h"
+#include "taler_pq_lib.h"
+#include "pg_do_deposit.h"
+#include "pg_helper.h"
+#include "pg_compute_shard.h"
+enum GNUNET_DB_QueryStatus
+TEH_PG_do_deposit (
+  void *cls,
+  const struct TALER_EXCHANGEDB_Deposit *deposit,
+  uint64_t known_coin_id,
+  const struct TALER_PaytoHashP *h_payto,
+  uint64_t *policy_details_serial_id,
+  struct GNUNET_TIME_Timestamp *exchange_timestamp,
+  bool *balance_ok,
+  bool *in_conflict)
+{
+  struct PostgresClosure *pg = cls;
+  uint64_t deposit_shard = TEH_PG_compute_shard (&deposit->merchant_pub);
+  struct GNUNET_PQ_QueryParam params[] = {
+    TALER_PQ_query_param_amount (&deposit->amount_with_fee),
+    GNUNET_PQ_query_param_auto_from_type (&deposit->h_contract_terms),
+    GNUNET_PQ_query_param_auto_from_type (&deposit->wire_salt),
+    GNUNET_PQ_query_param_timestamp (&deposit->timestamp),
+    GNUNET_PQ_query_param_timestamp (exchange_timestamp),
+    GNUNET_PQ_query_param_timestamp (&deposit->refund_deadline),
+    GNUNET_PQ_query_param_timestamp (&deposit->wire_deadline),
+    GNUNET_PQ_query_param_auto_from_type (&deposit->merchant_pub),
+    GNUNET_PQ_query_param_string (deposit->receiver_wire_account),
+    GNUNET_PQ_query_param_auto_from_type (h_payto),
+    GNUNET_PQ_query_param_uint64 (&known_coin_id),
+    GNUNET_PQ_query_param_auto_from_type (&deposit->coin.coin_pub),
+    GNUNET_PQ_query_param_auto_from_type (&deposit->csig),
+    GNUNET_PQ_query_param_uint64 (&deposit_shard),
+    GNUNET_PQ_query_param_bool (deposit->has_policy),
+    (NULL == policy_details_serial_id)
+    ? GNUNET_PQ_query_param_null ()
+    : GNUNET_PQ_query_param_uint64 (policy_details_serial_id),
+    GNUNET_PQ_query_param_end
+  };
+  struct GNUNET_PQ_ResultSpec rs[] = {
+    GNUNET_PQ_result_spec_bool ("balance_ok",
+                                balance_ok),
+    GNUNET_PQ_result_spec_bool ("conflicted",
+                                in_conflict),
+    GNUNET_PQ_result_spec_timestamp ("exchange_timestamp",
+                                     exchange_timestamp),
+    GNUNET_PQ_result_spec_end
+  };
+
+      /* Used in #postgres_do_deposit() to execute a deposit,
+       checking the coin's balance in the process as needed. */
+  PREPARE (pg,
+           "call_deposit",
+           "SELECT "
+           " out_exchange_timestamp AS exchange_timestamp"
+           ",out_balance_ok AS balance_ok"
+           ",out_conflict AS conflicted"
+           " FROM exchange_do_deposit"
+           " ($1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11,$12,$13,$14,$15,$16,$17);");
+  return GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
+                                                   "call_deposit",
+                                                   params,
+                                                   rs);
+}
diff --git a/src/exchangedb/pg_do_deposit.h b/src/exchangedb/pg_do_deposit.h
new file mode 100644
index 00000000..e71cf0e4
--- /dev/null
+++ b/src/exchangedb/pg_do_deposit.h
@@ -0,0 +1,52 @@
+/*
+   This file is part of TALER
+   Copyright (C) 2022 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 exchangedb/pg_do_deposit.h
+ * @brief implementation of the do_deposit function for Postgres
+ * @author Christian Grothoff
+ */
+#ifndef PG_DO_DEPOSIT_H
+#define PG_DO_DEPOSIT_H
+
+#include "taler_util.h"
+#include "taler_json_lib.h"
+#include "taler_exchangedb_plugin.h"
+/**
+ * Perform deposit operation, checking for sufficient balance
+ * of the coin and possibly persisting the deposit details.
+ *
+ * @param cls the `struct PostgresClosure` with the plugin-specific state
+ * @param deposit deposit operation details
+ * @param known_coin_id row of the coin in the known_coins table
+ * @param h_payto hash of the merchant's bank account details
+ * @param policy_details_serial_id pointer to the ID of the entry in 
policy_details, maybe NULL
+ * @param[in,out] exchange_timestamp time to use for the deposit (possibly 
updated)
+ * @param[out] balance_ok set to true if the balance was sufficient
+ * @param[out] in_conflict set to true if the deposit conflicted
+ * @return query execution status
+ */
+enum GNUNET_DB_QueryStatus
+TEH_PG_do_deposit (
+  void *cls,
+  const struct TALER_EXCHANGEDB_Deposit *deposit,
+  uint64_t known_coin_id,
+  const struct TALER_PaytoHashP *h_payto,
+  uint64_t *policy_details_serial_id,
+  struct GNUNET_TIME_Timestamp *exchange_timestamp,
+  bool *balance_ok,
+  bool *in_conflict);
+
+#endif
diff --git a/src/exchangedb/pg_do_melt.c b/src/exchangedb/pg_do_melt.c
new file mode 100644
index 00000000..6f81ff38
--- /dev/null
+++ b/src/exchangedb/pg_do_melt.c
@@ -0,0 +1,82 @@
+/*
+   This file is part of TALER
+   Copyright (C) 2022 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 exchangedb/pg_do_melt.c
+ * @brief Implementation of the do_melt function for Postgres
+ * @author Christian Grothoff
+ */
+#include "platform.h"
+#include "taler_error_codes.h"
+#include "taler_dbevents.h"
+#include "taler_pq_lib.h"
+#include "pg_do_melt.h"
+#include "pg_helper.h"
+
+
+enum GNUNET_DB_QueryStatus
+TEH_PG_do_melt (
+  void *cls,
+  const struct TALER_RefreshMasterSecretP *rms,
+  struct TALER_EXCHANGEDB_Refresh *refresh,
+  uint64_t known_coin_id,
+  bool *zombie_required,
+  bool *balance_ok)
+{
+  struct PostgresClosure *pg = cls;
+  struct GNUNET_PQ_QueryParam params[] = {
+    NULL == rms
+    ? GNUNET_PQ_query_param_null ()
+    : GNUNET_PQ_query_param_auto_from_type (rms),
+    TALER_PQ_query_param_amount (&refresh->amount_with_fee),
+    GNUNET_PQ_query_param_auto_from_type (&refresh->rc),
+    GNUNET_PQ_query_param_auto_from_type (&refresh->coin.coin_pub),
+    GNUNET_PQ_query_param_auto_from_type (&refresh->coin_sig),
+    GNUNET_PQ_query_param_uint64 (&known_coin_id),
+    GNUNET_PQ_query_param_uint32 (&refresh->noreveal_index),
+    GNUNET_PQ_query_param_bool (*zombie_required),
+    GNUNET_PQ_query_param_end
+  };
+  bool is_null;
+  struct GNUNET_PQ_ResultSpec rs[] = {
+    GNUNET_PQ_result_spec_bool ("balance_ok",
+                                balance_ok),
+    GNUNET_PQ_result_spec_bool ("zombie_required",
+                                zombie_required),
+    GNUNET_PQ_result_spec_allow_null (
+      GNUNET_PQ_result_spec_uint32 ("noreveal_index",
+                                    &refresh->noreveal_index),
+      &is_null),
+    GNUNET_PQ_result_spec_end
+  };
+  enum GNUNET_DB_QueryStatus qs;
+
+      /* Used in #postgres_do_melt() to melt a coin. */
+  PREPARE (pg,
+           "call_melt",
+           "SELECT "
+           " out_balance_ok AS balance_ok"
+           ",out_zombie_bad AS zombie_required"
+           ",out_noreveal_index AS noreveal_index"
+           " FROM exchange_do_melt"
+           " ($1,$2,$3,$4,$5,$6,$7,$8,$9);");
+  qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
+                                                 "call_melt",
+                                                 params,
+                                                 rs);
+  if (is_null)
+    refresh->noreveal_index = UINT32_MAX; /* set to very invalid value */
+  return qs;
+}
diff --git a/src/exchangedb/pg_do_melt.h b/src/exchangedb/pg_do_melt.h
new file mode 100644
index 00000000..554ce08b
--- /dev/null
+++ b/src/exchangedb/pg_do_melt.h
@@ -0,0 +1,49 @@
+/*
+   This file is part of TALER
+   Copyright (C) 2022 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 exchangedb/pg_do_melt.h
+ * @brief implementation of the do_melt function for Postgres
+ * @author Christian Grothoff
+ */
+#ifndef PG_DO_MELT_H
+#define PG_DO_MELT_H
+
+#include "taler_util.h"
+#include "taler_json_lib.h"
+#include "taler_exchangedb_plugin.h"
+/**
+ * Perform melt operation, checking for sufficient balance
+ * of the coin and possibly persisting the melt details.
+ *
+ * @param cls the `struct PostgresClosure` with the plugin-specific state
+ * @param rms client-contributed input for CS denominations that must be 
checked for idempotency, or NULL for non-CS withdrawals
+ * @param[in,out] refresh refresh operation details; the noreveal_index
+ *                is set in case the coin was already melted before
+ * @param known_coin_id row of the coin in the known_coins table
+ * @param[in,out] zombie_required true if the melt must only succeed if the 
coin is a zombie, set to false if the requirement was satisfied
+ * @param[out] balance_ok set to true if the balance was sufficient
+ * @return query execution status
+ */
+enum GNUNET_DB_QueryStatus
+TEH_PG_do_melt (
+  void *cls,
+  const struct TALER_RefreshMasterSecretP *rms,
+  struct TALER_EXCHANGEDB_Refresh *refresh,
+  uint64_t known_coin_id,
+  bool *zombie_required,
+  bool *balance_ok);
+
+#endif
diff --git a/src/exchangedb/pg_do_recoup.c b/src/exchangedb/pg_do_recoup.c
new file mode 100644
index 00000000..00f7bdd8
--- /dev/null
+++ b/src/exchangedb/pg_do_recoup.c
@@ -0,0 +1,86 @@
+/*
+   This file is part of TALER
+   Copyright (C) 2022 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 exchangedb/pg_do_recoup.c
+ * @brief Implementation of the do_recoup function for Postgres
+ * @author Christian Grothoff
+ */
+#include "platform.h"
+#include "taler_error_codes.h"
+#include "taler_dbevents.h"
+#include "taler_pq_lib.h"
+#include "pg_do_recoup.h"
+#include "pg_helper.h"
+
+
+enum GNUNET_DB_QueryStatus
+TEH_PG_do_recoup (
+  void *cls,
+  const struct TALER_ReservePublicKeyP *reserve_pub,
+  uint64_t reserve_out_serial_id,
+  const union TALER_DenominationBlindingKeyP *coin_bks,
+  const struct TALER_CoinSpendPublicKeyP *coin_pub,
+  uint64_t known_coin_id,
+  const struct TALER_CoinSpendSignatureP *coin_sig,
+  struct GNUNET_TIME_Timestamp *recoup_timestamp,
+  bool *recoup_ok,
+  bool *internal_failure)
+{
+  struct PostgresClosure *pg = cls;
+  struct GNUNET_TIME_Timestamp reserve_gc
+    = GNUNET_TIME_relative_to_timestamp (pg->legal_reserve_expiration_time);
+  struct GNUNET_TIME_Timestamp reserve_expiration
+    = GNUNET_TIME_relative_to_timestamp (pg->idle_reserve_expiration_time);
+  struct GNUNET_PQ_QueryParam params[] = {
+    GNUNET_PQ_query_param_auto_from_type (reserve_pub),
+    GNUNET_PQ_query_param_uint64 (&reserve_out_serial_id),
+    GNUNET_PQ_query_param_auto_from_type (coin_bks),
+    GNUNET_PQ_query_param_auto_from_type (coin_pub),
+    GNUNET_PQ_query_param_uint64 (&known_coin_id),
+    GNUNET_PQ_query_param_auto_from_type (coin_sig),
+    GNUNET_PQ_query_param_timestamp (&reserve_gc),
+    GNUNET_PQ_query_param_timestamp (&reserve_expiration),
+    GNUNET_PQ_query_param_timestamp (recoup_timestamp),
+    GNUNET_PQ_query_param_end
+  };
+  bool is_null;
+  struct GNUNET_PQ_ResultSpec rs[] = {
+    GNUNET_PQ_result_spec_allow_null (
+      GNUNET_PQ_result_spec_timestamp ("recoup_timestamp",
+                                       recoup_timestamp),
+      &is_null),
+    GNUNET_PQ_result_spec_bool ("recoup_ok",
+                                recoup_ok),
+    GNUNET_PQ_result_spec_bool ("internal_failure",
+                                internal_failure),
+    GNUNET_PQ_result_spec_end
+  };
+
+
+
+  PREPARE (pg,
+           "call_recoup",
+           "SELECT "
+           " out_recoup_timestamp AS recoup_timestamp"
+           ",out_recoup_ok AS recoup_ok"
+           ",out_internal_failure AS internal_failure"
+           " FROM exchange_do_recoup_to_reserve"
+           " ($1,$2,$3,$4,$5,$6,$7,$8,$9);");
+  return GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
+                                                   "call_recoup",
+                                                   params,
+                                                   rs);
+}
diff --git a/src/exchangedb/pg_do_recoup.h b/src/exchangedb/pg_do_recoup.h
new file mode 100644
index 00000000..07a35078
--- /dev/null
+++ b/src/exchangedb/pg_do_recoup.h
@@ -0,0 +1,56 @@
+/*
+   This file is part of TALER
+   Copyright (C) 2022 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 exchangedb/pg_do_recoup.h
+ * @brief implementation of the do_recoup function for Postgres
+ * @author Christian Grothoff
+ */
+#ifndef PG_DO_RECOUP_H
+#define PG_DO_RECOUP_H
+
+#include "taler_util.h"
+#include "taler_json_lib.h"
+#include "taler_exchangedb_plugin.h"
+/**
+ * Perform recoup operation, checking for sufficient deposits
+ * of the coin and possibly persisting the recoup details.
+ *
+ * @param cls the `struct PostgresClosure` with the plugin-specific state
+ * @param reserve_pub public key of the reserve to credit
+ * @param reserve_out_serial_id row in the reserves_out table justifying the 
recoup
+ * @param coin_bks coin blinding key secret to persist
+ * @param coin_pub public key of the coin being recouped
+ * @param known_coin_id row of the @a coin_pub in the known_coins table
+ * @param coin_sig signature of the coin requesting the recoup
+ * @param[in,out] recoup_timestamp recoup timestamp, set if recoup existed
+ * @param[out] recoup_ok  set if the recoup succeeded (balance ok)
+ * @param[out] internal_failure set on internal failures
+ * @return query execution status
+ */
+enum GNUNET_DB_QueryStatus
+TEH_PG_do_recoup (
+  void *cls,
+  const struct TALER_ReservePublicKeyP *reserve_pub,
+  uint64_t reserve_out_serial_id,
+  const union TALER_DenominationBlindingKeyP *coin_bks,
+  const struct TALER_CoinSpendPublicKeyP *coin_pub,
+  uint64_t known_coin_id,
+  const struct TALER_CoinSpendSignatureP *coin_sig,
+  struct GNUNET_TIME_Timestamp *recoup_timestamp,
+  bool *recoup_ok,
+  bool *internal_failure);
+
+#endif
diff --git a/src/exchangedb/pg_do_recoup_refresh.c 
b/src/exchangedb/pg_do_recoup_refresh.c
new file mode 100644
index 00000000..be5e4705
--- /dev/null
+++ b/src/exchangedb/pg_do_recoup_refresh.c
@@ -0,0 +1,79 @@
+/*
+   This file is part of TALER
+   Copyright (C) 2022 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 exchangedb/pg_do_recoup_refresh.c
+ * @brief Implementation of the do_recoup_refresh function for Postgres
+ * @author Christian Grothoff
+ */
+#include "platform.h"
+#include "taler_error_codes.h"
+#include "taler_dbevents.h"
+#include "taler_pq_lib.h"
+#include "pg_do_recoup_refresh.h"
+#include "pg_helper.h"
+
+enum GNUNET_DB_QueryStatus
+TEH_PG_do_recoup_refresh (
+  void *cls,
+  const struct TALER_CoinSpendPublicKeyP *old_coin_pub,
+  uint64_t rrc_serial,
+  const union TALER_DenominationBlindingKeyP *coin_bks,
+  const struct TALER_CoinSpendPublicKeyP *coin_pub,
+  uint64_t known_coin_id,
+  const struct TALER_CoinSpendSignatureP *coin_sig,
+  struct GNUNET_TIME_Timestamp *recoup_timestamp,
+  bool *recoup_ok,
+  bool *internal_failure)
+{
+  struct PostgresClosure *pg = cls;
+  struct GNUNET_PQ_QueryParam params[] = {
+    GNUNET_PQ_query_param_auto_from_type (old_coin_pub),
+    GNUNET_PQ_query_param_uint64 (&rrc_serial),
+    GNUNET_PQ_query_param_auto_from_type (coin_bks),
+    GNUNET_PQ_query_param_auto_from_type (coin_pub),
+    GNUNET_PQ_query_param_uint64 (&known_coin_id),
+    GNUNET_PQ_query_param_auto_from_type (coin_sig),
+    GNUNET_PQ_query_param_timestamp (recoup_timestamp),
+    GNUNET_PQ_query_param_end
+  };
+  bool is_null;
+  struct GNUNET_PQ_ResultSpec rs[] = {
+    GNUNET_PQ_result_spec_allow_null (
+      GNUNET_PQ_result_spec_timestamp ("recoup_timestamp",
+                                       recoup_timestamp),
+      &is_null),
+    GNUNET_PQ_result_spec_bool ("recoup_ok",
+                                recoup_ok),
+    GNUNET_PQ_result_spec_bool ("internal_failure",
+                                internal_failure),
+    GNUNET_PQ_result_spec_end
+  };
+
+
+  PREPARE (pg,
+           "call_recoup_refresh",
+           "SELECT "
+           " out_recoup_timestamp AS recoup_timestamp"
+           ",out_recoup_ok AS recoup_ok"
+           ",out_internal_failure AS internal_failure"
+           " FROM exchange_do_recoup_to_coin"
+           " ($1,$2,$3,$4,$5,$6,$7);");
+
+  return GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
+                                                   "call_recoup_refresh",
+                                                   params,
+                                                   rs);
+}
diff --git a/src/exchangedb/pg_do_recoup_refresh.h 
b/src/exchangedb/pg_do_recoup_refresh.h
new file mode 100644
index 00000000..3ac0f0a0
--- /dev/null
+++ b/src/exchangedb/pg_do_recoup_refresh.h
@@ -0,0 +1,56 @@
+/*
+   This file is part of TALER
+   Copyright (C) 2022 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 exchangedb/pg_do_recoup_refresh.h
+ * @brief implementation of the do_recoup_refresh function for Postgres
+ * @author Christian Grothoff
+ */
+#ifndef PG_DO_RECOUP_REFRESH_H
+#define PG_DO_RECOUP_REFRESH_H
+
+#include "taler_util.h"
+#include "taler_json_lib.h"
+#include "taler_exchangedb_plugin.h"
+
+/**
+ * Perform recoup-refresh operation, checking for sufficient deposits of the
+ * coin and possibly persisting the recoup-refresh details.
+ *
+ * @param cls the `struct PostgresClosure` with the plugin-specific state
+ * @param old_coin_pub public key of the old coin to credit
+ * @param rrc_serial row in the refresh_revealed_coins table justifying the 
recoup-refresh
+ * @param coin_bks coin blinding key secret to persist
+ * @param coin_pub public key of the coin being recouped
+ * @param known_coin_id row of the @a coin_pub in the known_coins table
+ * @param coin_sig signature of the coin requesting the recoup
+ * @param[in,out] recoup_timestamp recoup timestamp, set if recoup existed
+ * @param[out] recoup_ok  set if the recoup-refresh succeeded (balance ok)
+ * @param[out] internal_failure set on internal failures
+ * @return query execution status
+ */
+enum GNUNET_DB_QueryStatus
+TEH_PG_do_recoup_refresh (
+  void *cls,
+  const struct TALER_CoinSpendPublicKeyP *old_coin_pub,
+  uint64_t rrc_serial,
+  const union TALER_DenominationBlindingKeyP *coin_bks,
+  const struct TALER_CoinSpendPublicKeyP *coin_pub,
+  uint64_t known_coin_id,
+  const struct TALER_CoinSpendSignatureP *coin_sig,
+  struct GNUNET_TIME_Timestamp *recoup_timestamp,
+  bool *recoup_ok,
+  bool *internal_failure);
+#endif
diff --git a/src/exchangedb/pg_do_refund.c b/src/exchangedb/pg_do_refund.c
new file mode 100644
index 00000000..1059f9cb
--- /dev/null
+++ b/src/exchangedb/pg_do_refund.c
@@ -0,0 +1,90 @@
+/*
+   This file is part of TALER
+   Copyright (C) 2022 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 exchangedb/pg_do_refund.c
+ * @brief Implementation of the do_refund function for Postgres
+ * @author Christian Grothoff
+ */
+#include "platform.h"
+#include "taler_error_codes.h"
+#include "taler_dbevents.h"
+#include "taler_pq_lib.h"
+#include "pg_do_refund.h"
+#include "pg_helper.h"
+#include "pg_compute_shard.h"
+enum GNUNET_DB_QueryStatus
+TEH_PG_do_refund (
+  void *cls,
+  const struct TALER_EXCHANGEDB_Refund *refund,
+  const struct TALER_Amount *deposit_fee,
+  uint64_t known_coin_id,
+  bool *not_found,
+  bool *refund_ok,
+  bool *gone,
+  bool *conflict)
+{
+  struct PostgresClosure *pg = cls;
+  uint64_t deposit_shard = TEH_PG_compute_shard 
(&refund->details.merchant_pub);
+  struct TALER_Amount amount_without_fee;
+  struct GNUNET_PQ_QueryParam params[] = {
+    TALER_PQ_query_param_amount (&refund->details.refund_amount),
+    TALER_PQ_query_param_amount (&amount_without_fee),
+    TALER_PQ_query_param_amount (deposit_fee),
+    GNUNET_PQ_query_param_auto_from_type (&refund->details.h_contract_terms),
+    GNUNET_PQ_query_param_uint64 (&refund->details.rtransaction_id),
+    GNUNET_PQ_query_param_uint64 (&deposit_shard),
+    GNUNET_PQ_query_param_uint64 (&known_coin_id),
+    GNUNET_PQ_query_param_auto_from_type (&refund->coin.coin_pub),
+    GNUNET_PQ_query_param_auto_from_type (&refund->details.merchant_pub),
+    GNUNET_PQ_query_param_auto_from_type (&refund->details.merchant_sig),
+    GNUNET_PQ_query_param_end
+  };
+  struct GNUNET_PQ_ResultSpec rs[] = {
+    GNUNET_PQ_result_spec_bool ("not_found",
+                                not_found),
+    GNUNET_PQ_result_spec_bool ("refund_ok",
+                                refund_ok),
+    GNUNET_PQ_result_spec_bool ("gone",
+                                gone),
+    GNUNET_PQ_result_spec_bool ("conflict",
+                                conflict),
+    GNUNET_PQ_result_spec_end
+  };
+
+  if (0 >
+      TALER_amount_subtract (&amount_without_fee,
+                             &refund->details.refund_amount,
+                             &refund->details.refund_fee))
+  {
+    GNUNET_break (0);
+    return GNUNET_DB_STATUS_HARD_ERROR;
+  }
+    /* Used in #postgres_do_refund() to refund a deposit. */
+  PREPARE (pg,
+           "call_refund",
+           "SELECT "
+           " out_not_found AS not_found"
+           ",out_refund_ok AS refund_ok"
+           ",out_gone AS gone"
+           ",out_conflict AS conflict"
+           " FROM exchange_do_refund"
+           " ($1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11,$12,$13);");
+
+  return GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
+                                                   "call_refund",
+                                                   params,
+                                                   rs);
+}
diff --git a/src/exchangedb/pg_do_refund.h b/src/exchangedb/pg_do_refund.h
new file mode 100644
index 00000000..7118858d
--- /dev/null
+++ b/src/exchangedb/pg_do_refund.h
@@ -0,0 +1,52 @@
+/*
+   This file is part of TALER
+   Copyright (C) 2022 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 exchangedb/pg_do_refund.h
+ * @brief implementation of the do_refund function for Postgres
+ * @author Christian Grothoff
+ */
+#ifndef PG_DO_REFUND_H
+#define PG_DO_REFUND_H
+
+#include "taler_util.h"
+#include "taler_json_lib.h"
+#include "taler_exchangedb_plugin.h"
+/**
+ * Perform refund operation, checking for sufficient deposits
+ * of the coin and possibly persisting the refund details.
+ *
+ * @param cls the `struct PostgresClosure` with the plugin-specific state
+ * @param refund refund operation details
+ * @param deposit_fee deposit fee applicable for the coin, possibly refunded
+ * @param known_coin_id row of the coin in the known_coins table
+ * @param[out] not_found set if the deposit was not found
+ * @param[out] refund_ok  set if the refund succeeded (below deposit amount)
+ * @param[out] gone if the merchant was already paid
+ * @param[out] conflict set if the refund ID was re-used
+ * @return query execution status
+ */
+enum GNUNET_DB_QueryStatus
+TEH_PG_do_refund (
+  void *cls,
+  const struct TALER_EXCHANGEDB_Refund *refund,
+  const struct TALER_Amount *deposit_fee,
+  uint64_t known_coin_id,
+  bool *not_found,
+  bool *refund_ok,
+  bool *gone,
+  bool *conflict);
+
+#endif
diff --git a/src/exchangedb/pg_drain_kyc_alert.c 
b/src/exchangedb/pg_drain_kyc_alert.c
new file mode 100644
index 00000000..d635d95e
--- /dev/null
+++ b/src/exchangedb/pg_drain_kyc_alert.c
@@ -0,0 +1,59 @@
+/*
+   This file is part of TALER
+   Copyright (C) 2022 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 exchangedb/pg_drain_kyc_alert.c
+ * @brief Implementation of the drain_kyc_alert function for Postgres
+ * @author Christian Grothoff
+ */
+#include "platform.h"
+#include "taler_error_codes.h"
+#include "taler_dbevents.h"
+#include "taler_pq_lib.h"
+#include "pg_drain_kyc_alert.h"
+#include "pg_helper.h"
+
+
+enum GNUNET_DB_QueryStatus
+TEH_PG_drain_kyc_alert (void *cls,
+                          uint32_t trigger_type,
+                          struct TALER_PaytoHashP *h_payto)
+{
+  struct PostgresClosure *pg = cls;
+  struct GNUNET_PQ_QueryParam params[] = {
+    GNUNET_PQ_query_param_uint32 (&trigger_type),
+    GNUNET_PQ_query_param_end
+  };
+  struct GNUNET_PQ_ResultSpec rs[] = {
+    GNUNET_PQ_result_spec_auto_from_type ("h_payto",
+                                          h_payto),
+    GNUNET_PQ_result_spec_end
+  };
+
+  PREPARE (pg,
+           "drain_kyc_alert",
+           "DELETE FROM kyc_alerts"
+           " WHERE trigger_type=$1"
+           "   AND h_payto = "
+           "   (SELECT h_payto "
+           "      FROM kyc_alerts"
+           "     WHERE trigger_type=$1"
+           "     LIMIT 1)"
+           " RETURNING h_payto;");
+  return GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
+                                                   "drain_kyc_alert",
+                                                   params,
+                                                   rs);
+}
diff --git a/src/exchangedb/pg_drain_kyc_alert.h 
b/src/exchangedb/pg_drain_kyc_alert.h
new file mode 100644
index 00000000..bfaf0489
--- /dev/null
+++ b/src/exchangedb/pg_drain_kyc_alert.h
@@ -0,0 +1,40 @@
+/*
+   This file is part of TALER
+   Copyright (C) 2022 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 exchangedb/pg_drain_kyc_alert.h
+ * @brief implementation of the drain_kyc_alert function for Postgres
+ * @author Christian Grothoff
+ */
+#ifndef PG_DRAIN_KYC_ALERT_H
+#define PG_DRAIN_KYC_ALERT_H
+
+#include "taler_util.h"
+#include "taler_json_lib.h"
+#include "taler_exchangedb_plugin.h"
+/**
+ * Extract next KYC alert.  Deletes the alert.
+ *
+ * @param cls the @e cls of this struct with the plugin-specific state
+ * @param trigger_type which type of alert to drain
+ * @param[out] h_payto set to hash of payto-URI where KYC status changed
+ * @return transaction status
+ */
+enum GNUNET_DB_QueryStatus
+TEH_PG_drain_kyc_alert (void *cls,
+                          uint32_t trigger_type,
+                        struct TALER_PaytoHashP *h_payto);
+
+#endif
diff --git a/src/exchangedb/pg_ensure_coin_known.c 
b/src/exchangedb/pg_ensure_coin_known.c
new file mode 100644
index 00000000..6b2385ad
--- /dev/null
+++ b/src/exchangedb/pg_ensure_coin_known.c
@@ -0,0 +1,159 @@
+/*
+   This file is part of TALER
+   Copyright (C) 2022 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 exchangedb/pg_ensure_coin_known.c
+ * @brief Implementation of the ensure_coin_known function for Postgres
+ * @author Christian Grothoff
+ */
+#include "platform.h"
+#include "taler_error_codes.h"
+#include "taler_dbevents.h"
+#include "taler_pq_lib.h"
+#include "pg_ensure_coin_known.h"
+#include "pg_helper.h"
+
+
+enum TALER_EXCHANGEDB_CoinKnownStatus
+TEH_PG_ensure_coin_known (void *cls,
+                            const struct TALER_CoinPublicInfo *coin,
+                            uint64_t *known_coin_id,
+                            struct TALER_DenominationHashP *denom_hash,
+                            struct TALER_AgeCommitmentHash *h_age_commitment)
+{
+  struct PostgresClosure *pg = cls;
+  enum GNUNET_DB_QueryStatus qs;
+  bool existed;
+  bool is_denom_pub_hash_null = false;
+  bool is_age_hash_null = false;
+  struct GNUNET_PQ_QueryParam params[] = {
+    GNUNET_PQ_query_param_auto_from_type (&coin->coin_pub),
+    GNUNET_PQ_query_param_auto_from_type (&coin->denom_pub_hash),
+    GNUNET_PQ_query_param_auto_from_type (&coin->h_age_commitment),
+    TALER_PQ_query_param_denom_sig (&coin->denom_sig),
+    GNUNET_PQ_query_param_end
+  };
+  struct GNUNET_PQ_ResultSpec rs[] = {
+    GNUNET_PQ_result_spec_bool ("existed",
+                                &existed),
+    GNUNET_PQ_result_spec_uint64 ("known_coin_id",
+                                  known_coin_id),
+    GNUNET_PQ_result_spec_allow_null (
+      GNUNET_PQ_result_spec_auto_from_type ("denom_pub_hash",
+                                            denom_hash),
+      &is_denom_pub_hash_null),
+    GNUNET_PQ_result_spec_allow_null (
+      GNUNET_PQ_result_spec_auto_from_type ("age_commitment_hash",
+                                            h_age_commitment),
+      &is_age_hash_null),
+    GNUNET_PQ_result_spec_end
+  };
+    /* Used in #postgres_insert_known_coin() to store the denomination public
+       key and signature for a coin known to the exchange.
+
+       See also:
+       
https://stackoverflow.com/questions/34708509/how-to-use-returning-with-on-conflict-in-postgresql/37543015#37543015
+     */
+  PREPARE (pg,
+           "insert_known_coin",
+           "WITH dd"
+           "  (denominations_serial"
+           "  ,coin_val"
+           "  ,coin_frac"
+           "  ) AS ("
+           "    SELECT "
+           "       denominations_serial"
+           "      ,coin_val"
+           "      ,coin_frac"
+           "        FROM denominations"
+           "        WHERE denom_pub_hash=$2"
+           "  ), input_rows"
+           "    (coin_pub) AS ("
+           "      VALUES ($1::BYTEA)"
+           "  ), ins AS ("
+           "  INSERT INTO known_coins "
+           "  (coin_pub"
+           "  ,denominations_serial"
+           "  ,age_commitment_hash"
+           "  ,denom_sig"
+           "  ,remaining_val"
+           "  ,remaining_frac"
+           "  ) SELECT "
+           "     $1"
+           "    ,denominations_serial"
+           "    ,$3"
+           "    ,$4"
+           "    ,coin_val"
+           "    ,coin_frac"
+           "  FROM dd"
+           "  ON CONFLICT DO NOTHING" /* CONFLICT on (coin_pub) */
+           "  RETURNING "
+           "     known_coin_id"
+           "  ) "
+           "SELECT "
+           "   FALSE AS existed"
+           "  ,known_coin_id"
+           "  ,NULL AS denom_pub_hash"
+           "  ,NULL AS age_commitment_hash"
+           "  FROM ins "
+           "UNION ALL "
+           "SELECT "
+           "   TRUE AS existed"
+           "  ,known_coin_id"
+           "  ,denom_pub_hash"
+           "  ,kc.age_commitment_hash"
+           "  FROM input_rows"
+           "  JOIN known_coins kc USING (coin_pub)"
+           "  JOIN denominations USING (denominations_serial)"
+           "  LIMIT 1");
+  qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
+                                                 "insert_known_coin",
+                                                 params,
+                                                 rs);
+  switch (qs)
+  {
+  case GNUNET_DB_STATUS_HARD_ERROR:
+    GNUNET_break (0);
+    return TALER_EXCHANGEDB_CKS_HARD_FAIL;
+  case GNUNET_DB_STATUS_SOFT_ERROR:
+    return TALER_EXCHANGEDB_CKS_SOFT_FAIL;
+  case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS:
+    GNUNET_break (0); /* should be impossible */
+    return TALER_EXCHANGEDB_CKS_HARD_FAIL;
+  case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT:
+    if (! existed)
+      return TALER_EXCHANGEDB_CKS_ADDED;
+    break; /* continued below */
+  }
+
+  if ( (! is_denom_pub_hash_null) &&
+       (0 != GNUNET_memcmp (&denom_hash->hash,
+                            &coin->denom_pub_hash.hash)) )
+  {
+    GNUNET_break_op (0);
+    return TALER_EXCHANGEDB_CKS_DENOM_CONFLICT;
+  }
+
+  if ( (! is_age_hash_null) &&
+       (0 != GNUNET_memcmp (h_age_commitment,
+                            &coin->h_age_commitment)) )
+  {
+    GNUNET_break (GNUNET_is_zero (h_age_commitment));
+    GNUNET_break_op (0);
+    return TALER_EXCHANGEDB_CKS_AGE_CONFLICT;
+  }
+
+  return TALER_EXCHANGEDB_CKS_PRESENT;
+}
diff --git a/src/exchangedb/pg_ensure_coin_known.h 
b/src/exchangedb/pg_ensure_coin_known.h
new file mode 100644
index 00000000..76581d4b
--- /dev/null
+++ b/src/exchangedb/pg_ensure_coin_known.h
@@ -0,0 +1,45 @@
+/*
+   This file is part of TALER
+   Copyright (C) 2022 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 exchangedb/pg_ensure_coin_known.h
+ * @brief implementation of the ensure_coin_known function for Postgres
+ * @author Christian Grothoff
+ */
+#ifndef PG_ENSURE_COIN_KNOWN_H
+#define PG_ENSURE_COIN_KNOWN_H
+
+#include "taler_util.h"
+#include "taler_json_lib.h"
+#include "taler_exchangedb_plugin.h"
+/**
+ * Make sure the given @a coin is known to the database.
+ *
+ * @param cls database connection plugin state
+ * @param coin the coin that must be made known
+ * @param[out] known_coin_id set to the unique row of the coin
+ * @param[out] denom_hash set to the denomination hash of the existing
+ *             coin (for conflict error reporting)
+ * @param[out] h_age_commitment  set to the conflicting age commitment hash on 
conflict
+ * @return database transaction status, non-negative on success
+ */
+enum TALER_EXCHANGEDB_CoinKnownStatus
+TEH_PG_ensure_coin_known (void *cls,
+                            const struct TALER_CoinPublicInfo *coin,
+                            uint64_t *known_coin_id,
+                            struct TALER_DenominationHashP *denom_hash,
+                          struct TALER_AgeCommitmentHash *h_age_commitment);
+
+#endif
diff --git a/src/exchangedb/pg_event_listen.c b/src/exchangedb/pg_event_listen.c
new file mode 100644
index 00000000..c557ed3c
--- /dev/null
+++ b/src/exchangedb/pg_event_listen.c
@@ -0,0 +1,53 @@
+/*
+   This file is part of TALER
+   Copyright (C) 2022 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 exchangedb/pg_event_listen.c
+ * @brief Implementation of the event_listen function for Postgres
+ * @author Christian Grothoff
+ */
+#include "platform.h"
+#include "taler_error_codes.h"
+#include "taler_dbevents.h"
+#include "taler_pq_lib.h"
+#include "pg_event_listen.h"
+#include "pg_helper.h"
+
+/**
+ * Register callback to be invoked on events of type @a es.
+ *
+ * @param cls database context to use
+ * @param timeout how long until to generate a timeout event
+ * @param es specification of the event to listen for
+ * @param cb function to call when the event happens, possibly
+ *         multiple times (until cancel is invoked)
+ * @param cb_cls closure for @a cb
+ * @return handle useful to cancel the listener
+ */
+struct GNUNET_DB_EventHandler *
+TEH_PG_event_listen (void *cls,
+                       struct GNUNET_TIME_Relative timeout,
+                       const struct GNUNET_DB_EventHeaderP *es,
+                       GNUNET_DB_EventCallback cb,
+                       void *cb_cls)
+{
+  struct PostgresClosure *pg = cls;
+
+  return GNUNET_PQ_event_listen (pg->conn,
+                                 es,
+                                 timeout,
+                                 cb,
+                                 cb_cls);
+}
diff --git a/src/exchangedb/pg_event_listen.h b/src/exchangedb/pg_event_listen.h
new file mode 100644
index 00000000..1be14077
--- /dev/null
+++ b/src/exchangedb/pg_event_listen.h
@@ -0,0 +1,45 @@
+/*
+   This file is part of TALER
+   Copyright (C) 2022 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 exchangedb/pg_event_listen.h
+ * @brief implementation of the event_listen function for Postgres
+ * @author Christian Grothoff
+ */
+#ifndef PG_EVENT_LISTEN_H
+#define PG_EVENT_LISTEN_H
+
+#include "taler_util.h"
+#include "taler_json_lib.h"
+#include "taler_exchangedb_plugin.h"
+/**
+ * Register callback to be invoked on events of type @a es.
+ *
+ * @param cls database context to use
+ * @param timeout how long until to generate a timeout event
+ * @param es specification of the event to listen for
+ * @param cb function to call when the event happens, possibly
+ *         multiple times (until cancel is invoked)
+ * @param cb_cls closure for @a cb
+ * @return handle useful to cancel the listener
+ */
+struct GNUNET_DB_EventHandler *
+TEH_PG_event_listen (void *cls,
+                       struct GNUNET_TIME_Relative timeout,
+                       const struct GNUNET_DB_EventHeaderP *es,
+                       GNUNET_DB_EventCallback cb,
+                     void *cb_cls);
+
+#endif
diff --git a/src/exchangedb/pg_event_listen_cancel.c 
b/src/exchangedb/pg_event_listen_cancel.c
new file mode 100644
index 00000000..5d65827c
--- /dev/null
+++ b/src/exchangedb/pg_event_listen_cancel.c
@@ -0,0 +1,37 @@
+/*
+   This file is part of TALER
+   Copyright (C) 2022 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 exchangedb/pg_event_listen_cancel.c
+ * @brief Implementation of the event_listen_cancel function for Postgres
+ * @author Christian Grothoff
+ */
+#include "platform.h"
+#include "taler_error_codes.h"
+#include "taler_dbevents.h"
+#include "taler_pq_lib.h"
+#include "pg_event_listen_cancel.h"
+#include "pg_helper.h"
+
+
+
+void
+TEH_PG_event_listen_cancel (void *cls,
+                              struct GNUNET_DB_EventHandler *eh)
+
+{
+  (void) cls;
+  GNUNET_PQ_event_listen_cancel (eh);
+}
diff --git a/src/exchangedb/pg_event_listen_cancel.h 
b/src/exchangedb/pg_event_listen_cancel.h
new file mode 100644
index 00000000..258d7a58
--- /dev/null
+++ b/src/exchangedb/pg_event_listen_cancel.h
@@ -0,0 +1,38 @@
+/*
+   This file is part of TALER
+   Copyright (C) 2022 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 exchangedb/pg_event_listen_cancel.h
+ * @brief implementation of the event_listen_cancel function for Postgres
+ * @author Christian Grothoff
+ */
+#ifndef PG_EVENT_LISTEN_CANCEL_H
+#define PG_EVENT_LISTEN_CANCEL_H
+
+#include "taler_util.h"
+#include "taler_json_lib.h"
+#include "taler_exchangedb_plugin.h"
+
+
+/**
+ * Stop notifications.
+ *
+ * @param cls the plugin's `struct PostgresClosure`
+ * @param eh handle to unregister.
+ */
+void
+TEH_PG_event_listen_cancel (void *cls,
+                            struct GNUNET_DB_EventHandler *eh);
+#endif
diff --git a/src/exchangedb/pg_event_notify.c b/src/exchangedb/pg_event_notify.c
new file mode 100644
index 00000000..577f4acb
--- /dev/null
+++ b/src/exchangedb/pg_event_notify.c
@@ -0,0 +1,41 @@
+/*
+   This file is part of TALER
+   Copyright (C) 2022 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 exchangedb/pg_event_notify.c
+ * @brief Implementation of the event_notify function for Postgres
+ * @author Christian Grothoff
+ */
+#include "platform.h"
+#include "taler_error_codes.h"
+#include "taler_dbevents.h"
+#include "taler_pq_lib.h"
+#include "pg_event_notify.h"
+#include "pg_helper.h"
+
+
+void
+TEH_PG_event_notify (void *cls,
+                       const struct GNUNET_DB_EventHeaderP *es,
+                       const void *extra,
+                       size_t extra_size)
+{
+  struct PostgresClosure *pg = cls;
+
+  GNUNET_PQ_event_notify (pg->conn,
+                          es,
+                          extra,
+                          extra_size);
+}
diff --git a/src/exchangedb/pg_event_notify.h b/src/exchangedb/pg_event_notify.h
new file mode 100644
index 00000000..3b937cba
--- /dev/null
+++ b/src/exchangedb/pg_event_notify.h
@@ -0,0 +1,42 @@
+/*
+   This file is part of TALER
+   Copyright (C) 2022 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 exchangedb/pg_event_notify.h
+ * @brief implementation of the event_notify function for Postgres
+ * @author Christian Grothoff
+ */
+#ifndef PG_EVENT_NOTIFY_H
+#define PG_EVENT_NOTIFY_H
+
+#include "taler_util.h"
+#include "taler_json_lib.h"
+#include "taler_exchangedb_plugin.h"
+
+/**
+ * Notify all that listen on @a es of an event.
+ *
+ * @param cls database context to use
+ * @param es specification of the event to generate
+ * @param extra additional event data provided
+ * @param extra_size number of bytes in @a extra
+ */
+void
+TEH_PG_event_notify (void *cls,
+                       const struct GNUNET_DB_EventHeaderP *es,
+                       const void *extra,
+                     size_t extra_size);
+
+#endif
diff --git a/src/exchangedb/pg_expire_purse.c b/src/exchangedb/pg_expire_purse.c
new file mode 100644
index 00000000..6ef7a277
--- /dev/null
+++ b/src/exchangedb/pg_expire_purse.c
@@ -0,0 +1,69 @@
+/*
+   This file is part of TALER
+   Copyright (C) 2022 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 exchangedb/pg_expire_purse.c
+ * @brief Implementation of the expire_purse function for Postgres
+ * @author Christian Grothoff
+ */
+#include "platform.h"
+#include "taler_error_codes.h"
+#include "taler_dbevents.h"
+#include "taler_pq_lib.h"
+#include "pg_expire_purse.h"
+#include "pg_helper.h"
+
+
+enum GNUNET_DB_QueryStatus
+TEH_PG_expire_purse (
+  void *cls,
+  struct GNUNET_TIME_Absolute start_time,
+  struct GNUNET_TIME_Absolute end_time)
+{
+  struct PostgresClosure *pg = cls;
+  struct GNUNET_TIME_Absolute now = GNUNET_TIME_absolute_get ();
+  struct GNUNET_PQ_QueryParam params[] = {
+    GNUNET_PQ_query_param_absolute_time (&start_time),
+    GNUNET_PQ_query_param_absolute_time (&end_time),
+    GNUNET_PQ_query_param_absolute_time (&now),
+    GNUNET_PQ_query_param_end
+  };
+  bool found = false;
+  struct GNUNET_PQ_ResultSpec rs[] = {
+    GNUNET_PQ_result_spec_bool ("found",
+                                &found),
+    GNUNET_PQ_result_spec_end
+  };
+  enum GNUNET_DB_QueryStatus qs;
+
+
+  PREPARE (pg,
+           "call_expire_purse",
+           "SELECT "
+           " out_found AS found"
+           " FROM exchange_do_expire_purse"
+           " ($1,$2,$3);");
+
+  qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
+                                                 "call_expire_purse",
+                                                 params,
+                                                 rs);
+  if (qs < 0)
+    return qs;
+  GNUNET_assert (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT == qs);
+  return found
+         ? GNUNET_DB_STATUS_SUCCESS_ONE_RESULT
+         : GNUNET_DB_STATUS_SUCCESS_NO_RESULTS;
+}
diff --git a/src/exchangedb/pg_expire_purse.h b/src/exchangedb/pg_expire_purse.h
new file mode 100644
index 00000000..fe05fd52
--- /dev/null
+++ b/src/exchangedb/pg_expire_purse.h
@@ -0,0 +1,41 @@
+/*
+   This file is part of TALER
+   Copyright (C) 2022 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 exchangedb/pg_expire_purse.h
+ * @brief implementation of the expire_purse function for Postgres
+ * @author Christian Grothoff
+ */
+#ifndef PG_EXPIRE_PURSE_H
+#define PG_EXPIRE_PURSE_H
+
+#include "taler_util.h"
+#include "taler_json_lib.h"
+#include "taler_exchangedb_plugin.h"
+/**
+ * Function called to clean up one expired purse.
+ *
+ * @param cls the @e cls of this struct with the plugin-specific state
+ * @param start_time select purse expired after this time
+ * @param end_time select purse expired before this time
+ * @return transaction status code (#GNUNET_DB_STATUS_SUCCESS_NO_RESULTS if no 
purse expired in the given time interval).
+ */
+enum GNUNET_DB_QueryStatus
+TEH_PG_expire_purse (
+  void *cls,
+  struct GNUNET_TIME_Absolute start_time,
+  struct GNUNET_TIME_Absolute end_time);
+
+#endif
diff --git a/src/exchangedb/pg_find_aggregation_transient.c 
b/src/exchangedb/pg_find_aggregation_transient.c
new file mode 100644
index 00000000..a5f367b5
--- /dev/null
+++ b/src/exchangedb/pg_find_aggregation_transient.c
@@ -0,0 +1,151 @@
+/*
+   This file is part of TALER
+   Copyright (C) 2022 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 exchangedb/pg_find_aggregation_transient.c
+ * @brief Implementation of the find_aggregation_transient function for 
Postgres
+ * @author Christian Grothoff
+ */
+#include "platform.h"
+#include "taler_error_codes.h"
+#include "taler_dbevents.h"
+#include "taler_pq_lib.h"
+#include "pg_find_aggregation_transient.h"
+#include "pg_helper.h"
+
+
+/**
+ * Closure for #get_refunds_cb().
+ */
+struct FindAggregationTransientContext
+{
+  /**
+   * Function to call on each result.
+   */
+  TALER_EXCHANGEDB_TransientAggregationCallback cb;
+
+  /**
+   * Closure for @a cb.
+   */
+  void *cb_cls;
+
+  /**
+   * Plugin context.
+   */
+  struct PostgresClosure *pg;
+
+  /**
+   * Set to #GNUNET_SYSERR on error.
+   */
+  enum GNUNET_GenericReturnValue status;
+};
+
+
+/**
+ * Function to be called with the results of a SELECT statement
+ * that has returned @a num_results results.
+ *
+ * @param cls closure of type `struct SelectRefundContext *`
+ * @param result the postgres result
+ * @param num_results the number of results in @a result
+ */
+static void
+get_transients_cb (void *cls,
+                   PGresult *result,
+                   unsigned int num_results)
+{
+  struct FindAggregationTransientContext *srctx = cls;
+  struct PostgresClosure *pg = srctx->pg;
+
+  for (unsigned int i = 0; i<num_results; i++)
+  {
+    struct TALER_Amount amount;
+    char *payto_uri;
+    struct TALER_WireTransferIdentifierRawP wtid;
+    struct TALER_MerchantPublicKeyP merchant_pub;
+    struct GNUNET_PQ_ResultSpec rs[] = {
+      GNUNET_PQ_result_spec_auto_from_type ("merchant_pub",
+                                            &merchant_pub),
+      GNUNET_PQ_result_spec_auto_from_type ("wtid_raw",
+                                            &wtid),
+      GNUNET_PQ_result_spec_string ("payto_uri",
+                                    &payto_uri),
+      TALER_PQ_RESULT_SPEC_AMOUNT ("amount",
+                                   &amount),
+      GNUNET_PQ_result_spec_end
+    };
+    bool cont;
+
+    if (GNUNET_OK !=
+        GNUNET_PQ_extract_result (result,
+                                  rs,
+                                  i))
+    {
+      GNUNET_break (0);
+      srctx->status = GNUNET_SYSERR;
+      return;
+    }
+    cont = srctx->cb (srctx->cb_cls,
+                      payto_uri,
+                      &wtid,
+                      &merchant_pub,
+                      &amount);
+    GNUNET_free (payto_uri);
+    if (! cont)
+      break;
+  }
+}
+
+
+enum GNUNET_DB_QueryStatus
+TEH_PG_find_aggregation_transient (
+  void *cls,
+  const struct TALER_PaytoHashP *h_payto,
+  TALER_EXCHANGEDB_TransientAggregationCallback cb,
+  void *cb_cls)
+{
+  struct PostgresClosure *pg = cls;
+  enum GNUNET_DB_QueryStatus qs;
+  struct GNUNET_PQ_QueryParam params[] = {
+    GNUNET_PQ_query_param_auto_from_type (h_payto),
+    GNUNET_PQ_query_param_end
+  };
+  struct FindAggregationTransientContext srctx = {
+    .cb = cb,
+    .cb_cls = cb_cls,
+    .pg = pg,
+    .status = GNUNET_OK
+  };
+    /* Used in #postgres_find_aggregation_transient() */
+  PREPARE (pg,
+           "find_transient_aggregations",
+           "SELECT"
+           "  amount_val"
+           " ,amount_frac"
+           " ,wtid_raw"
+           " ,merchant_pub"
+           " ,payto_uri"
+           " FROM aggregation_transient atr"
+           " JOIN wire_targets wt USING (wire_target_h_payto)"
+           " WHERE atr.wire_target_h_payto=$1;");
+  qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn,
+                                             "find_transient_aggregations",
+                                             params,
+                                             &get_transients_cb,
+                                             &srctx);
+  if (GNUNET_SYSERR == srctx.status)
+    return GNUNET_DB_STATUS_HARD_ERROR;
+  return qs;
+}
diff --git a/src/exchangedb/pg_find_aggregation_transient.h 
b/src/exchangedb/pg_find_aggregation_transient.h
new file mode 100644
index 00000000..c7ba4ea3
--- /dev/null
+++ b/src/exchangedb/pg_find_aggregation_transient.h
@@ -0,0 +1,43 @@
+/*
+   This file is part of TALER
+   Copyright (C) 2022 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 exchangedb/pg_find_aggregation_transient.h
+ * @brief implementation of the find_aggregation_transient function for 
Postgres
+ * @author Christian Grothoff
+ */
+#ifndef PG_FIND_AGGREGATION_TRANSIENT_H
+#define PG_FIND_AGGREGATION_TRANSIENT_H
+
+#include "taler_util.h"
+#include "taler_json_lib.h"
+#include "taler_exchangedb_plugin.h"
+/**
+ * Find existing entry in the transient aggregation table.
+ *
+ * @param cls the @e cls of this struct with the plugin-specific state
+ * @param h_payto destination of the wire transfer
+ * @param cb function to call on each matching entry
+ * @param cb_cls closure for @a cb
+ * @return transaction status
+ */
+enum GNUNET_DB_QueryStatus
+TEH_PG_find_aggregation_transient (
+  void *cls,
+  const struct TALER_PaytoHashP *h_payto,
+  TALER_EXCHANGEDB_TransientAggregationCallback cb,
+  void *cb_cls);
+
+#endif
diff --git a/src/exchangedb/pg_gc.c b/src/exchangedb/pg_gc.c
new file mode 100644
index 00000000..e01c1e10
--- /dev/null
+++ b/src/exchangedb/pg_gc.c
@@ -0,0 +1,80 @@
+/*
+   This file is part of TALER
+   Copyright (C) 2022 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 exchangedb/pg_gc.c
+ * @brief Implementation of the gc function for Postgres
+ * @author Christian Grothoff
+ */
+#include "platform.h"
+#include "taler_error_codes.h"
+#include "taler_dbevents.h"
+#include "taler_pq_lib.h"
+#include "pg_gc.h"
+#include "pg_helper.h"
+
+
+enum GNUNET_GenericReturnValue
+TEH_PG_gc (void *cls)
+{
+  struct PostgresClosure *pg = cls;
+  struct GNUNET_TIME_Absolute now = GNUNET_TIME_absolute_get ();
+  struct GNUNET_TIME_Absolute long_ago;
+  struct GNUNET_PQ_QueryParam params[] = {
+    GNUNET_PQ_query_param_absolute_time (&long_ago),
+    GNUNET_PQ_query_param_absolute_time (&now),
+    GNUNET_PQ_query_param_end
+  };
+  struct GNUNET_PQ_Context *conn;
+  enum GNUNET_GenericReturnValue ret;
+
+  /* Keep wire fees for 10 years, that should always
+     be enough _and_ they are tiny so it does not
+     matter to make this tight */
+  long_ago = GNUNET_TIME_absolute_subtract (
+    now,
+    GNUNET_TIME_relative_multiply (
+      GNUNET_TIME_UNIT_YEARS,
+      10));
+  {
+    struct GNUNET_PQ_ExecuteStatement es[] = {
+      GNUNET_PQ_make_try_execute ("SET search_path TO exchange;"),
+      GNUNET_PQ_EXECUTE_STATEMENT_END
+    };
+    struct GNUNET_PQ_PreparedStatement ps[] = {
+      /* Used in #postgres_gc() */
+      GNUNET_PQ_make_prepare ("run_gc",
+                              "CALL"
+                              " exchange_do_gc"
+                              " ($1,$2);"),
+      GNUNET_PQ_PREPARED_STATEMENT_END
+    };
+
+    conn = GNUNET_PQ_connect_with_cfg (pg->cfg,
+                                       "exchangedb-postgres",
+                                       NULL,
+                                       es,
+                                       ps);
+  }
+  if (NULL == conn)
+    return GNUNET_SYSERR;
+  ret = GNUNET_OK;
+  if (0 > GNUNET_PQ_eval_prepared_non_select (conn,
+                                              "run_gc",
+                                              params))
+    ret = GNUNET_SYSERR;
+  GNUNET_PQ_disconnect (conn);
+  return ret;
+}
diff --git a/src/exchangedb/pg_gc.h b/src/exchangedb/pg_gc.h
new file mode 100644
index 00000000..9e6ffbc3
--- /dev/null
+++ b/src/exchangedb/pg_gc.h
@@ -0,0 +1,38 @@
+/*
+   This file is part of TALER
+   Copyright (C) 2022 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 exchangedb/pg_gc.h
+ * @brief implementation of the gc function for Postgres
+ * @author Christian Grothoff
+ */
+#ifndef PG_GC_H
+#define PG_GC_H
+
+#include "taler_util.h"
+#include "taler_json_lib.h"
+#include "taler_exchangedb_plugin.h"
+
+/**
+ * Function called to perform "garbage collection" on the
+ * database, expiring records we no longer require.
+ *
+ * @param cls closure
+ * @return #GNUNET_OK on success,
+ *         #GNUNET_SYSERR on DB errors
+ */
+enum GNUNET_GenericReturnValue
+TEH_PG_gc (void *cls);
+#endif
diff --git a/src/exchangedb/pg_get_coin_denomination.c 
b/src/exchangedb/pg_get_coin_denomination.c
new file mode 100644
index 00000000..e82b86aa
--- /dev/null
+++ b/src/exchangedb/pg_get_coin_denomination.c
@@ -0,0 +1,71 @@
+/*
+   This file is part of TALER
+   Copyright (C) 2022 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 exchangedb/pg_get_coin_denomination.c
+ * @brief Implementation of the get_coin_denomination function for Postgres
+ * @author Christian Grothoff
+ */
+#include "platform.h"
+#include "taler_error_codes.h"
+#include "taler_dbevents.h"
+#include "taler_pq_lib.h"
+#include "pg_get_coin_denomination.h"
+#include "pg_helper.h"
+
+enum GNUNET_DB_QueryStatus
+TEH_PG_get_coin_denomination (
+  void *cls,
+  const struct TALER_CoinSpendPublicKeyP *coin_pub,
+  uint64_t *known_coin_id,
+  struct TALER_DenominationHashP *denom_hash)
+{
+  struct PostgresClosure *pg = cls;
+  struct GNUNET_PQ_QueryParam params[] = {
+    GNUNET_PQ_query_param_auto_from_type (coin_pub),
+    GNUNET_PQ_query_param_end
+  };
+  struct GNUNET_PQ_ResultSpec rs[] = {
+    GNUNET_PQ_result_spec_auto_from_type ("denom_pub_hash",
+                                          denom_hash),
+    GNUNET_PQ_result_spec_uint64 ("known_coin_id",
+                                  known_coin_id),
+    GNUNET_PQ_result_spec_end
+  };
+
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Getting coin denomination of coin %s\n",
+              TALER_B2S (coin_pub));
+
+    /* Used in #postgres_get_coin_denomination() to fetch
+       the denomination public key hash for
+       a coin known to the exchange. */
+  PREPARE (pg,
+           "get_coin_denomination",
+           "SELECT"
+           " denominations.denom_pub_hash"
+           ",known_coin_id"
+           " FROM known_coins"
+           " JOIN denominations USING (denominations_serial)"
+           " WHERE coin_pub=$1"
+           " FOR SHARE;");
+
+  return GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
+                                                   "get_coin_denomination",
+                                                   params,
+                                                   rs);
+}
+
+
diff --git a/src/exchangedb/pg_get_coin_denomination.h 
b/src/exchangedb/pg_get_coin_denomination.h
new file mode 100644
index 00000000..3b9f03f3
--- /dev/null
+++ b/src/exchangedb/pg_get_coin_denomination.h
@@ -0,0 +1,43 @@
+/*
+   This file is part of TALER
+   Copyright (C) 2022 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 exchangedb/pg_get_coin_denomination.h
+ * @brief implementation of the get_coin_denomination function for Postgres
+ * @author Christian Grothoff
+ */
+#ifndef PG_GET_COIN_DENOMINATION_H
+#define PG_GET_COIN_DENOMINATION_H
+
+#include "taler_util.h"
+#include "taler_json_lib.h"
+#include "taler_exchangedb_plugin.h"
+/**
+ * Retrieve the denomination of a known coin.
+ *
+ * @param cls the plugin closure
+ * @param coin_pub the public key of the coin to search for
+ * @param[out] known_coin_id set to the ID of the coin in the known_coins table
+ * @param[out] denom_hash where to store the hash of the coins denomination
+ * @return transaction status code
+ */
+enum GNUNET_DB_QueryStatus
+TEH_PG_get_coin_denomination (
+  void *cls,
+  const struct TALER_CoinSpendPublicKeyP *coin_pub,
+  uint64_t *known_coin_id,
+  struct TALER_DenominationHashP *denom_hash);
+
+#endif
diff --git a/src/exchangedb/pg_get_denomination_info.c 
b/src/exchangedb/pg_get_denomination_info.c
new file mode 100644
index 00000000..97250b62
--- /dev/null
+++ b/src/exchangedb/pg_get_denomination_info.c
@@ -0,0 +1,99 @@
+/*
+   This file is part of TALER
+   Copyright (C) 2022 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 exchangedb/pg_get_denomination_info.c
+ * @brief Implementation of the get_denomination_info function for Postgres
+ * @author Christian Grothoff
+ */
+#include "platform.h"
+#include "taler_error_codes.h"
+#include "taler_dbevents.h"
+#include "taler_pq_lib.h"
+#include "pg_get_denomination_info.h"
+#include "pg_helper.h"
+
+
+enum GNUNET_DB_QueryStatus
+TEH_PG_get_denomination_info (
+  void *cls,
+  const struct TALER_DenominationHashP *denom_pub_hash,
+  struct TALER_EXCHANGEDB_DenominationKeyInformation *issue)
+{
+  struct PostgresClosure *pg = cls;
+  enum GNUNET_DB_QueryStatus qs;
+  struct GNUNET_PQ_QueryParam params[] = {
+    GNUNET_PQ_query_param_auto_from_type (denom_pub_hash),
+    GNUNET_PQ_query_param_end
+  };
+  struct GNUNET_PQ_ResultSpec rs[] = {
+    GNUNET_PQ_result_spec_auto_from_type ("master_sig",
+                                          &issue->signature),
+    GNUNET_PQ_result_spec_timestamp ("valid_from",
+                                     &issue->start),
+    GNUNET_PQ_result_spec_timestamp ("expire_withdraw",
+                                     &issue->expire_withdraw),
+    GNUNET_PQ_result_spec_timestamp ("expire_deposit",
+                                     &issue->expire_deposit),
+    GNUNET_PQ_result_spec_timestamp ("expire_legal",
+                                     &issue->expire_legal),
+    TALER_PQ_RESULT_SPEC_AMOUNT ("coin",
+                                 &issue->value),
+    TALER_PQ_RESULT_SPEC_AMOUNT ("fee_withdraw",
+                                 &issue->fees.withdraw),
+    TALER_PQ_RESULT_SPEC_AMOUNT ("fee_deposit",
+                                 &issue->fees.deposit),
+    TALER_PQ_RESULT_SPEC_AMOUNT ("fee_refresh",
+                                 &issue->fees.refresh),
+    TALER_PQ_RESULT_SPEC_AMOUNT ("fee_refund",
+                                 &issue->fees.refund),
+    GNUNET_PQ_result_spec_uint32 ("age_mask",
+                                  &issue->age_mask.bits),
+    GNUNET_PQ_result_spec_end
+  };
+
+
+    /* Used in #postgres_get_denomination_info() */
+  PREPARE (pg,
+           "denomination_get",
+           "SELECT"
+           " master_sig"
+           ",valid_from"
+           ",expire_withdraw"
+           ",expire_deposit"
+           ",expire_legal"
+           ",coin_val"                                                /* value 
of this denom */
+           ",coin_frac"                                                /* 
fractional value of this denom */
+           ",fee_withdraw_val"
+           ",fee_withdraw_frac"
+           ",fee_deposit_val"
+           ",fee_deposit_frac"
+           ",fee_refresh_val"
+           ",fee_refresh_frac"
+           ",fee_refund_val"
+           ",fee_refund_frac"
+           ",age_mask"
+           " FROM denominations"
+           " WHERE denom_pub_hash=$1;"); 
+  qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
+                                                 "denomination_get",
+                                                 params,
+                                                 rs);
+  if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != qs)
+    return qs;
+  issue->denom_hash = *denom_pub_hash;
+  return qs;
+}
+
diff --git a/src/exchangedb/pg_get_denomination_info.h 
b/src/exchangedb/pg_get_denomination_info.h
new file mode 100644
index 00000000..84322775
--- /dev/null
+++ b/src/exchangedb/pg_get_denomination_info.h
@@ -0,0 +1,41 @@
+/*
+   This file is part of TALER
+   Copyright (C) 2022 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 exchangedb/pg_get_denomination_info.h
+ * @brief implementation of the get_denomination_info function for Postgres
+ * @author Christian Grothoff
+ */
+#ifndef PG_GET_DENOMINATION_INFO_H
+#define PG_GET_DENOMINATION_INFO_H
+
+#include "taler_util.h"
+#include "taler_json_lib.h"
+#include "taler_exchangedb_plugin.h"
+/**
+ * Fetch information about a denomination key.
+ *
+ * @param cls the @e cls of this struct with the plugin-specific state
+ * @param denom_pub_hash hash of the public key used for signing coins of this 
denomination
+ * @param[out] issue set to issue information with value, fees and other info 
about the coin
+ * @return transaction status code
+ */
+enum GNUNET_DB_QueryStatus
+TEH_PG_get_denomination_info (
+  void *cls,
+  const struct TALER_DenominationHashP *denom_pub_hash,
+  struct TALER_EXCHANGEDB_DenominationKeyInformation *issue);
+
+#endif
diff --git a/src/exchangedb/pg_get_denomination_revocation.c 
b/src/exchangedb/pg_get_denomination_revocation.c
new file mode 100644
index 00000000..4d29d88c
--- /dev/null
+++ b/src/exchangedb/pg_get_denomination_revocation.c
@@ -0,0 +1,63 @@
+/*
+   This file is part of TALER
+   Copyright (C) 2022 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 exchangedb/pg_get_denomination_revocation.c
+ * @brief Implementation of the get_denomination_revocation function for 
Postgres
+ * @author Christian Grothoff
+ */
+#include "platform.h"
+#include "taler_error_codes.h"
+#include "taler_dbevents.h"
+#include "taler_pq_lib.h"
+#include "pg_get_denomination_revocation.h"
+#include "pg_helper.h"
+
+enum GNUNET_DB_QueryStatus
+TEH_PG_get_denomination_revocation (
+  void *cls,
+  const struct TALER_DenominationHashP *denom_pub_hash,
+  struct TALER_MasterSignatureP *master_sig,
+  uint64_t *rowid)
+{
+  struct PostgresClosure *pg = cls;
+  struct GNUNET_PQ_QueryParam params[] = {
+    GNUNET_PQ_query_param_auto_from_type (denom_pub_hash),
+    GNUNET_PQ_query_param_end
+  };
+  struct GNUNET_PQ_ResultSpec rs[] = {
+    GNUNET_PQ_result_spec_auto_from_type ("master_sig",
+                                          master_sig),
+    GNUNET_PQ_result_spec_uint64 ("denom_revocations_serial_id",
+                                  rowid),
+    GNUNET_PQ_result_spec_end
+  };
+
+  PREPARE (pg,
+      "denomination_revocation_get",
+      "SELECT"
+      " master_sig"
+      ",denom_revocations_serial_id"
+      " FROM denomination_revocations"
+      " WHERE denominations_serial="
+      "  (SELECT denominations_serial"
+      "    FROM denominations"
+      "    WHERE denom_pub_hash=$1);");
+
+  return GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
+                                                   
"denomination_revocation_get",
+                                                   params,
+                                                   rs);
+}
diff --git a/src/exchangedb/pg_get_denomination_revocation.h 
b/src/exchangedb/pg_get_denomination_revocation.h
new file mode 100644
index 00000000..d022c822
--- /dev/null
+++ b/src/exchangedb/pg_get_denomination_revocation.h
@@ -0,0 +1,44 @@
+/*
+   This file is part of TALER
+   Copyright (C) 2022 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 exchangedb/pg_get_denomination_revocation.h
+ * @brief implementation of the get_denomination_revocation function for 
Postgres
+ * @author Christian Grothoff
+ */
+#ifndef PG_GET_DENOMINATION_REVOCATION_H
+#define PG_GET_DENOMINATION_REVOCATION_H
+
+#include "taler_util.h"
+#include "taler_json_lib.h"
+#include "taler_exchangedb_plugin.h"
+
+/**
+ * Obtain information about a denomination key's revocation from
+ * the database.
+ *
+ * @param cls closure
+ * @param denom_pub_hash hash of the revoked denomination key
+ * @param[out] master_sig signature affirming the revocation
+ * @param[out] rowid row where the information is stored
+ * @return transaction status code
+ */
+enum GNUNET_DB_QueryStatus
+TEH_PG_get_denomination_revocation (
+  void *cls,
+  const struct TALER_DenominationHashP *denom_pub_hash,
+  struct TALER_MasterSignatureP *master_sig,
+  uint64_t *rowid);
+#endif
diff --git a/src/exchangedb/pg_get_global_fee.c 
b/src/exchangedb/pg_get_global_fee.c
new file mode 100644
index 00000000..6f6bbafe
--- /dev/null
+++ b/src/exchangedb/pg_get_global_fee.c
@@ -0,0 +1,91 @@
+/*
+   This file is part of TALER
+   Copyright (C) 2022 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 exchangedb/pg_get_global_fee.c
+ * @brief Implementation of the get_global_fee function for Postgres
+ * @author Christian Grothoff
+ */
+#include "platform.h"
+#include "taler_error_codes.h"
+#include "taler_dbevents.h"
+#include "taler_pq_lib.h"
+#include "pg_get_global_fee.h"
+#include "pg_helper.h"
+
+
+enum GNUNET_DB_QueryStatus
+TEH_PG_get_global_fee (void *cls,
+                         struct GNUNET_TIME_Timestamp date,
+                         struct GNUNET_TIME_Timestamp *start_date,
+                         struct GNUNET_TIME_Timestamp *end_date,
+                         struct TALER_GlobalFeeSet *fees,
+                         struct GNUNET_TIME_Relative *purse_timeout,
+                         struct GNUNET_TIME_Relative *history_expiration,
+                         uint32_t *purse_account_limit,
+                         struct TALER_MasterSignatureP *master_sig)
+{
+  struct PostgresClosure *pg = cls;
+  struct GNUNET_PQ_QueryParam params[] = {
+    GNUNET_PQ_query_param_timestamp (&date),
+    GNUNET_PQ_query_param_end
+  };
+  struct GNUNET_PQ_ResultSpec rs[] = {
+    GNUNET_PQ_result_spec_timestamp ("start_date",
+                                     start_date),
+    GNUNET_PQ_result_spec_timestamp ("end_date",
+                                     end_date),
+    TALER_PQ_RESULT_SPEC_AMOUNT ("history_fee",
+                                 &fees->history),
+    TALER_PQ_RESULT_SPEC_AMOUNT ("account_fee",
+                                 &fees->account),
+    TALER_PQ_RESULT_SPEC_AMOUNT ("purse_fee",
+                                 &fees->purse),
+    GNUNET_PQ_result_spec_relative_time ("purse_timeout",
+                                         purse_timeout),
+    GNUNET_PQ_result_spec_relative_time ("history_expiration",
+                                         history_expiration),
+    GNUNET_PQ_result_spec_uint32 ("purse_account_limit",
+                                  purse_account_limit),
+    GNUNET_PQ_result_spec_auto_from_type ("master_sig",
+                                          master_sig),
+    GNUNET_PQ_result_spec_end
+  };
+
+
+      /* Used in #postgres_get_global_fee() */
+  PREPARE(pg,
+          "get_global_fee",
+          "SELECT "
+          " start_date"
+          ",end_date"
+          ",history_fee_val"
+          ",history_fee_frac"
+          ",account_fee_val"
+          ",account_fee_frac"
+          ",purse_fee_val"
+          ",purse_fee_frac"
+          ",purse_timeout"
+          ",history_expiration"
+          ",purse_account_limit"
+          ",master_sig"
+          " FROM global_fee"
+          " WHERE start_date <= $1"
+          "   AND end_date > $1;");
+  return GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
+                                                   "get_global_fee",
+                                                   params,
+                                                   rs);
+}
diff --git a/src/exchangedb/pg_get_global_fee.h 
b/src/exchangedb/pg_get_global_fee.h
new file mode 100644
index 00000000..0887d54d
--- /dev/null
+++ b/src/exchangedb/pg_get_global_fee.h
@@ -0,0 +1,52 @@
+/*
+   This file is part of TALER
+   Copyright (C) 2022 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 exchangedb/pg_get_global_fee.h
+ * @brief implementation of the get_global_fee function for Postgres
+ * @author Christian Grothoff
+ */
+#ifndef PG_GET_GLOBAL_FEE_H
+#define PG_GET_GLOBAL_FEE_H
+
+#include "taler_util.h"
+#include "taler_json_lib.h"
+#include "taler_exchangedb_plugin.h"
+/**
+ * Obtain global fees from database.
+ *
+ * @param cls closure
+ * @param date for which date do we want the fee?
+ * @param[out] start_date when does the fee go into effect
+ * @param[out] end_date when does the fee end being valid
+ * @param[out] fees how high are the wire fees
+ * @param[out] purse_timeout set to how long we keep unmerged purses
+ * @param[out] history_expiration set to how long we keep account histories
+ * @param[out] purse_account_limit set to the number of free purses per account
+ * @param[out] master_sig signature over the above by the exchange master key
+ * @return status of the transaction
+ */
+enum GNUNET_DB_QueryStatus
+TEH_PG_get_global_fee (void *cls,
+                         struct GNUNET_TIME_Timestamp date,
+                         struct GNUNET_TIME_Timestamp *start_date,
+                         struct GNUNET_TIME_Timestamp *end_date,
+                         struct TALER_GlobalFeeSet *fees,
+                         struct GNUNET_TIME_Relative *purse_timeout,
+                         struct GNUNET_TIME_Relative *history_expiration,
+                         uint32_t *purse_account_limit,
+                       struct TALER_MasterSignatureP *master_sig);
+
+#endif
diff --git a/src/exchangedb/pg_get_global_fees.c 
b/src/exchangedb/pg_get_global_fees.c
new file mode 100644
index 00000000..0e1736bd
--- /dev/null
+++ b/src/exchangedb/pg_get_global_fees.c
@@ -0,0 +1,175 @@
+/*
+   This file is part of TALER
+   Copyright (C) 2022 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 exchangedb/pg_get_global_fees.c
+ * @brief Implementation of the get_global_fees function for Postgres
+ * @author Christian Grothoff
+ */
+#include "platform.h"
+#include "taler_error_codes.h"
+#include "taler_dbevents.h"
+#include "taler_pq_lib.h"
+#include "pg_get_global_fees.h"
+#include "pg_helper.h"
+
+
+/**
+ * Closure for #global_fees_cb().
+ */
+struct GlobalFeeContext
+{
+  /**
+   * Function to call for each global fee block.
+   */
+  TALER_EXCHANGEDB_GlobalFeeCallback cb;
+
+  /**
+   * Closure to give to @e rec.
+   */
+  void *cb_cls;
+
+  /**
+   * Plugin context.
+   */
+  struct PostgresClosure *pg;
+
+  /**
+   * Set to #GNUNET_SYSERR on error.
+   */
+  enum GNUNET_GenericReturnValue status;
+};
+
+
+/**
+ * Function to be called with the results of a SELECT statement
+ * that has returned @a num_results results.
+ *
+ * @param cls closure
+ * @param result the postgres result
+ * @param num_results the number of results in @a result
+ */
+static void
+global_fees_cb (void *cls,
+                PGresult *result,
+                unsigned int num_results)
+{
+  struct GlobalFeeContext *gctx = cls;
+  struct PostgresClosure *pg = gctx->pg;
+
+  for (unsigned int i = 0; i<num_results; i++)
+  {
+    struct TALER_GlobalFeeSet fees;
+    struct GNUNET_TIME_Relative purse_timeout;
+    struct GNUNET_TIME_Relative history_expiration;
+    uint32_t purse_account_limit;
+    struct GNUNET_TIME_Timestamp start_date;
+    struct GNUNET_TIME_Timestamp end_date;
+    struct TALER_MasterSignatureP master_sig;
+    struct GNUNET_PQ_ResultSpec rs[] = {
+      GNUNET_PQ_result_spec_timestamp ("start_date",
+                                       &start_date),
+      GNUNET_PQ_result_spec_timestamp ("end_date",
+                                       &end_date),
+      TALER_PQ_RESULT_SPEC_AMOUNT ("history_fee",
+                                   &fees.history),
+      TALER_PQ_RESULT_SPEC_AMOUNT ("account_fee",
+                                   &fees.account),
+      TALER_PQ_RESULT_SPEC_AMOUNT ("purse_fee",
+                                   &fees.purse),
+      GNUNET_PQ_result_spec_relative_time ("purse_timeout",
+                                           &purse_timeout),
+      GNUNET_PQ_result_spec_relative_time ("history_expiration",
+                                           &history_expiration),
+      GNUNET_PQ_result_spec_uint32 ("purse_account_limit",
+                                    &purse_account_limit),
+      GNUNET_PQ_result_spec_auto_from_type ("master_sig",
+                                            &master_sig),
+      GNUNET_PQ_result_spec_end
+    };
+    if (GNUNET_OK !=
+        GNUNET_PQ_extract_result (result,
+                                  rs,
+                                  i))
+    {
+      GNUNET_break (0);
+      gctx->status = GNUNET_SYSERR;
+      break;
+    }
+    gctx->cb (gctx->cb_cls,
+              &fees,
+              purse_timeout,
+              history_expiration,
+              purse_account_limit,
+              start_date,
+              end_date,
+              &master_sig);
+    GNUNET_PQ_cleanup_result (rs);
+  }
+}
+
+
+
+enum GNUNET_DB_QueryStatus
+TEH_PG_get_global_fees (void *cls,
+                          TALER_EXCHANGEDB_GlobalFeeCallback cb,
+                          void *cb_cls)
+{
+  struct PostgresClosure *pg = cls;
+  struct GNUNET_TIME_Timestamp date
+    = GNUNET_TIME_absolute_to_timestamp (
+        GNUNET_TIME_absolute_subtract (
+          GNUNET_TIME_absolute_get (),
+          GNUNET_TIME_UNIT_YEARS));
+  struct GNUNET_PQ_QueryParam params[] = {
+    GNUNET_PQ_query_param_timestamp (&date),
+    GNUNET_PQ_query_param_end
+  };
+  struct GlobalFeeContext gctx = {
+    .cb = cb,
+    .cb_cls = cb_cls,
+    .pg = pg,
+    .status = GNUNET_OK
+  };
+
+      /* Used in #postgres_get_global_fees() */
+  PREPARE (pg,
+           "get_global_fees",
+           "SELECT "
+           " start_date"
+           ",end_date"
+           ",history_fee_val"
+           ",history_fee_frac"
+           ",account_fee_val"
+           ",account_fee_frac"
+           ",purse_fee_val"
+           ",purse_fee_frac"
+           ",purse_timeout"
+           ",history_expiration"
+           ",purse_account_limit"
+           ",master_sig"
+           " FROM global_fee"
+           " WHERE start_date >= $1");
+
+  return GNUNET_PQ_eval_prepared_multi_select (pg->conn,
+                                               "get_global_fees",
+                                               params,
+                                               &global_fees_cb,
+                                               &gctx);
+}
+
+
+
+
diff --git a/src/exchangedb/pg_get_global_fees.h 
b/src/exchangedb/pg_get_global_fees.h
new file mode 100644
index 00000000..c8f6f02c
--- /dev/null
+++ b/src/exchangedb/pg_get_global_fees.h
@@ -0,0 +1,40 @@
+/*
+   This file is part of TALER
+   Copyright (C) 2022 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 exchangedb/pg_get_global_fees.h
+ * @brief implementation of the get_global_fees function for Postgres
+ * @author Christian Grothoff
+ */
+#ifndef PG_GET_GLOBAL_FEES_H
+#define PG_GET_GLOBAL_FEES_H
+
+#include "taler_util.h"
+#include "taler_json_lib.h"
+#include "taler_exchangedb_plugin.h"
+
+/**
+ * Obtain global fees from database.
+ *
+ * @param cls closure
+ * @param cb function to call on each fee entry
+ * @param cb_cls closure for @a cb
+ * @return status of the transaction
+ */
+enum GNUNET_DB_QueryStatus
+TEH_PG_get_global_fees (void *cls,
+                          TALER_EXCHANGEDB_GlobalFeeCallback cb,
+                        void *cb_cls);
+#endif
diff --git a/src/exchangedb/pg_get_known_coin.c 
b/src/exchangedb/pg_get_known_coin.c
new file mode 100644
index 00000000..fe5c683b
--- /dev/null
+++ b/src/exchangedb/pg_get_known_coin.c
@@ -0,0 +1,71 @@
+/*
+   This file is part of TALER
+   Copyright (C) 2022 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 exchangedb/pg_get_known_coin.c
+ * @brief Implementation of the get_known_coin function for Postgres
+ * @author Christian Grothoff
+ */
+#include "platform.h"
+#include "taler_error_codes.h"
+#include "taler_dbevents.h"
+#include "taler_pq_lib.h"
+#include "pg_get_known_coin.h"
+#include "pg_helper.h"
+
+enum GNUNET_DB_QueryStatus
+TEH_PG_get_known_coin (void *cls,
+                         const struct TALER_CoinSpendPublicKeyP *coin_pub,
+                         struct TALER_CoinPublicInfo *coin_info)
+{
+  struct PostgresClosure *pg = cls;
+  struct GNUNET_PQ_QueryParam params[] = {
+    GNUNET_PQ_query_param_auto_from_type (coin_pub),
+    GNUNET_PQ_query_param_end
+  };
+  struct GNUNET_PQ_ResultSpec rs[] = {
+    GNUNET_PQ_result_spec_auto_from_type ("denom_pub_hash",
+                                          &coin_info->denom_pub_hash),
+    GNUNET_PQ_result_spec_allow_null (
+      GNUNET_PQ_result_spec_auto_from_type ("age_commitment_hash",
+                                            &coin_info->h_age_commitment),
+      &coin_info->no_age_commitment),
+    TALER_PQ_result_spec_denom_sig ("denom_sig",
+                                    &coin_info->denom_sig),
+    GNUNET_PQ_result_spec_end
+  };
+
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Getting known coin data for coin %s\n",
+              TALER_B2S (coin_pub));
+  coin_info->coin_pub = *coin_pub;
+    /* Used in #postgres_get_known_coin() to fetch
+       the denomination public key and signature for
+       a coin known to the exchange. */
+  PREPARE (pg,
+           "get_known_coin",
+           "SELECT"
+           " denominations.denom_pub_hash"
+           ",age_commitment_hash"
+           ",denom_sig"
+           " FROM known_coins"
+           " JOIN denominations USING (denominations_serial)"
+           " WHERE coin_pub=$1;");
+
+  return GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
+                                                   "get_known_coin",
+                                                   params,
+                                                   rs);
+}
diff --git a/src/exchangedb/pg_get_known_coin.h 
b/src/exchangedb/pg_get_known_coin.h
new file mode 100644
index 00000000..d7f55b33
--- /dev/null
+++ b/src/exchangedb/pg_get_known_coin.h
@@ -0,0 +1,40 @@
+/*
+   This file is part of TALER
+   Copyright (C) 2022 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 exchangedb/pg_get_known_coin.h
+ * @brief implementation of the get_known_coin function for Postgres
+ * @author Christian Grothoff
+ */
+#ifndef PG_GET_KNOWN_COIN_H
+#define PG_GET_KNOWN_COIN_H
+
+#include "taler_util.h"
+#include "taler_json_lib.h"
+#include "taler_exchangedb_plugin.h"
+/**
+ * Retrieve the record for a known coin.
+ *
+ * @param cls the plugin closure
+ * @param coin_pub the public key of the coin to search for
+ * @param coin_info place holder for the returned coin information object
+ * @return transaction status code
+ */
+enum GNUNET_DB_QueryStatus
+TEH_PG_get_known_coin (void *cls,
+                         const struct TALER_CoinSpendPublicKeyP *coin_pub,
+                       struct TALER_CoinPublicInfo *coin_info);
+
+#endif
diff --git a/src/exchangedb/pg_get_melt.c b/src/exchangedb/pg_get_melt.c
new file mode 100644
index 00000000..f239c605
--- /dev/null
+++ b/src/exchangedb/pg_get_melt.c
@@ -0,0 +1,128 @@
+/*
+   This file is part of TALER
+   Copyright (C) 2022 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 exchangedb/pg_get_melt.c
+ * @brief Implementation of the get_melt function for Postgres
+ * @author Christian Grothoff
+ */
+#include "platform.h"
+#include "taler_error_codes.h"
+#include "taler_dbevents.h"
+#include "taler_pq_lib.h"
+#include "pg_get_melt.h"
+#include "pg_helper.h"
+
+
+enum GNUNET_DB_QueryStatus
+TEH_PG_get_melt (void *cls,
+                   const struct TALER_RefreshCommitmentP *rc,
+                   struct TALER_EXCHANGEDB_Melt *melt,
+                   uint64_t *melt_serial_id)
+{
+  struct PostgresClosure *pg = cls;
+  bool h_age_commitment_is_null;
+  struct GNUNET_PQ_QueryParam params[] = {
+    GNUNET_PQ_query_param_auto_from_type (rc),
+    GNUNET_PQ_query_param_end
+  };
+  struct GNUNET_PQ_ResultSpec rs[] = {
+    GNUNET_PQ_result_spec_auto_from_type ("denom_pub_hash",
+                                          &melt->session.coin.
+                                          denom_pub_hash),
+    TALER_PQ_RESULT_SPEC_AMOUNT ("fee_refresh",
+                                 &melt->melt_fee),
+    GNUNET_PQ_result_spec_uint32 ("noreveal_index",
+                                  &melt->session.noreveal_index),
+    GNUNET_PQ_result_spec_auto_from_type ("old_coin_pub",
+                                          &melt->session.coin.coin_pub),
+    GNUNET_PQ_result_spec_auto_from_type ("old_coin_sig",
+                                          &melt->session.coin_sig),
+    GNUNET_PQ_result_spec_allow_null (
+      GNUNET_PQ_result_spec_auto_from_type ("age_commitment_hash",
+                                            
&melt->session.coin.h_age_commitment),
+      &h_age_commitment_is_null),
+    TALER_PQ_RESULT_SPEC_AMOUNT ("amount_with_fee",
+                                 &melt->session.amount_with_fee),
+    GNUNET_PQ_result_spec_uint64 ("melt_serial_id",
+                                  melt_serial_id),
+    GNUNET_PQ_result_spec_end
+  };
+  enum GNUNET_DB_QueryStatus qs;
+
+  memset (&melt->session.coin.denom_sig,
+          0,
+          sizeof (melt->session.coin.denom_sig));
+
+    /* Used in #postgres_get_melt() to fetch
+       high-level information about a melt operation */
+  PREPARE (pg,
+           "get_melt",
+           /* "SELECT"
+              " denoms.denom_pub_hash"
+              ",denoms.fee_refresh_val"
+              ",denoms.fee_refresh_frac"
+              ",old_coin_pub"
+              ",old_coin_sig"
+              ",kc.age_commitment_hash"
+              ",amount_with_fee_val"
+              ",amount_with_fee_frac"
+              ",noreveal_index"
+              ",melt_serial_id"
+              " FROM refresh_commitments"
+              "   JOIN known_coins kc"
+              "     ON (old_coin_pub = kc.coin_pub)"
+              "   JOIN denominations denoms"
+              "     ON (kc.denominations_serial = denoms.denominations_serial)"
+              " WHERE rc=$1;", */
+           "WITH rc AS MATERIALIZED ( "
+           " SELECT"
+           "  * FROM refresh_commitments"
+           " WHERE rc=$1"
+           ")"
+           "SELECT"
+           " denoms.denom_pub_hash"
+           ",denoms.fee_refresh_val"
+           ",denoms.fee_refresh_frac"
+           ",rc.old_coin_pub"
+           ",rc.old_coin_sig"
+           ",kc.age_commitment_hash"
+           ",amount_with_fee_val"
+           ",amount_with_fee_frac"
+           ",noreveal_index"
+           ",melt_serial_id "
+           "FROM ("
+           " SELECT"
+           "  * "
+           " FROM known_coins"
+           " WHERE coin_pub=(SELECT old_coin_pub from rc)"
+           ") kc "
+           "JOIN rc"
+           "  ON (kc.coin_pub=rc.old_coin_pub) "
+           "JOIN denominations denoms"
+           "  USING (denominations_serial);");
+
+  qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
+                                                 "get_melt",
+                                                 params,
+                                                 rs);
+  if (h_age_commitment_is_null)
+    memset (&melt->session.coin.h_age_commitment,
+            0,
+            sizeof(melt->session.coin.h_age_commitment));
+
+  melt->session.rc = *rc;
+  return qs;
+}
diff --git a/src/exchangedb/pg_get_melt.h b/src/exchangedb/pg_get_melt.h
new file mode 100644
index 00000000..73d757a0
--- /dev/null
+++ b/src/exchangedb/pg_get_melt.h
@@ -0,0 +1,44 @@
+/*
+   This file is part of TALER
+   Copyright (C) 2022 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 exchangedb/pg_get_melt.h
+ * @brief implementation of the get_melt function for Postgres
+ * @author Christian Grothoff
+ */
+#ifndef PG_GET_MELT_H
+#define PG_GET_MELT_H
+
+#include "taler_util.h"
+#include "taler_json_lib.h"
+#include "taler_exchangedb_plugin.h"
+/**
+ * Lookup refresh melt commitment data under the given @a rc.
+ *
+ * @param cls the `struct PostgresClosure` with the plugin-specific state
+ * @param rc commitment hash to use to locate the operation
+ * @param[out] melt where to store the result; note that
+ *             melt->session.coin.denom_sig will be set to NULL
+ *             and is not fetched by this routine (as it is not needed by the 
client)
+ * @param[out] melt_serial_id set to the row ID of @a rc in the 
refresh_commitments table
+ * @return transaction status
+ */
+enum GNUNET_DB_QueryStatus
+TEH_PG_get_melt (void *cls,
+                   const struct TALER_RefreshCommitmentP *rc,
+                   struct TALER_EXCHANGEDB_Melt *melt,
+                 uint64_t *melt_serial_id);
+
+#endif
diff --git a/src/exchangedb/pg_get_old_coin_by_h_blind.c 
b/src/exchangedb/pg_get_old_coin_by_h_blind.c
new file mode 100644
index 00000000..385c3f1d
--- /dev/null
+++ b/src/exchangedb/pg_get_old_coin_by_h_blind.c
@@ -0,0 +1,65 @@
+/*
+   This file is part of TALER
+   Copyright (C) 2022 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 exchangedb/pg_get_old_coin_by_h_blind.c
+ * @brief Implementation of the get_old_coin_by_h_blind function for Postgres
+ * @author Christian Grothoff
+ */
+#include "platform.h"
+#include "taler_error_codes.h"
+#include "taler_dbevents.h"
+#include "taler_pq_lib.h"
+#include "pg_get_old_coin_by_h_blind.h"
+#include "pg_helper.h"
+
+
+
+enum GNUNET_DB_QueryStatus
+TEH_PG_get_old_coin_by_h_blind (
+  void *cls,
+  const struct TALER_BlindedCoinHashP *h_blind_ev,
+  struct TALER_CoinSpendPublicKeyP *old_coin_pub,
+  uint64_t *rrc_serial)
+{
+  struct PostgresClosure *pg = cls;
+  struct GNUNET_PQ_QueryParam params[] = {
+    GNUNET_PQ_query_param_auto_from_type (h_blind_ev),
+    GNUNET_PQ_query_param_end
+  };
+  struct GNUNET_PQ_ResultSpec rs[] = {
+    GNUNET_PQ_result_spec_auto_from_type ("old_coin_pub",
+                                          old_coin_pub),
+    GNUNET_PQ_result_spec_uint64 ("rrc_serial",
+                                  rrc_serial),
+    GNUNET_PQ_result_spec_end
+  };
+
+      /* Used in #postgres_get_old_coin_by_h_blind() */
+  PREPARE (pg,
+           "old_coin_by_h_blind",
+           "SELECT"
+           " okc.coin_pub AS old_coin_pub"
+           ",rrc_serial"
+           " FROM refresh_revealed_coins rrc"
+           " JOIN refresh_commitments rcom USING (melt_serial_id)"
+           " JOIN known_coins okc ON (rcom.old_coin_pub = okc.coin_pub)"
+           " WHERE h_coin_ev=$1"
+           " LIMIT 1;");
+  return GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
+                                                   "old_coin_by_h_blind",
+                                                   params,
+                                                   rs);
+}
diff --git a/src/exchangedb/pg_get_old_coin_by_h_blind.h 
b/src/exchangedb/pg_get_old_coin_by_h_blind.h
new file mode 100644
index 00000000..1404990d
--- /dev/null
+++ b/src/exchangedb/pg_get_old_coin_by_h_blind.h
@@ -0,0 +1,44 @@
+/*
+   This file is part of TALER
+   Copyright (C) 2022 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 exchangedb/pg_get_old_coin_by_h_blind.h
+ * @brief implementation of the get_old_coin_by_h_blind function for Postgres
+ * @author Christian Grothoff
+ */
+#ifndef PG_GET_OLD_COIN_BY_H_BLIND_H
+#define PG_GET_OLD_COIN_BY_H_BLIND_H
+
+#include "taler_util.h"
+#include "taler_json_lib.h"
+#include "taler_exchangedb_plugin.h"
+
+/**
+ * Obtain information about which old coin a coin was refreshed
+ * given the hash of the blinded (fresh) coin.
+ *
+ * @param cls closure
+ * @param h_blind_ev hash of the blinded coin
+ * @param[out] old_coin_pub set to information about the old coin (on success 
only)
+ * @param[out] rrc_serial set to serial number of the entry in the database
+ * @return transaction status code
+ */
+enum GNUNET_DB_QueryStatus
+TEH_PG_get_old_coin_by_h_blind (
+  void *cls,
+  const struct TALER_BlindedCoinHashP *h_blind_ev,
+  struct TALER_CoinSpendPublicKeyP *old_coin_pub,
+  uint64_t *rrc_serial);
+#endif
diff --git a/src/exchangedb/pg_get_policy_details.c 
b/src/exchangedb/pg_get_policy_details.c
new file mode 100644
index 00000000..5dacb600
--- /dev/null
+++ b/src/exchangedb/pg_get_policy_details.c
@@ -0,0 +1,65 @@
+/*
+   This file is part of TALER
+   Copyright (C) 2022 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 exchangedb/pg_get_policy_details.c
+ * @brief Implementation of the get_policy_details function for Postgres
+ * @author Christian Grothoff
+ */
+#include "platform.h"
+#include "taler_error_codes.h"
+#include "taler_dbevents.h"
+#include "taler_pq_lib.h"
+#include "pg_get_policy_details.h"
+#include "pg_helper.h"
+
+enum GNUNET_DB_QueryStatus
+TEH_PG_get_policy_details (
+  void *cls,
+  const struct GNUNET_HashCode *hc,
+  struct TALER_PolicyDetails *details)
+{
+  struct PostgresClosure *pg = cls;
+  struct GNUNET_PQ_QueryParam params[] = {
+    GNUNET_PQ_query_param_auto_from_type (hc),
+    GNUNET_PQ_query_param_end
+  };
+  struct GNUNET_PQ_ResultSpec rs[] = {
+    GNUNET_PQ_result_spec_timestamp ("deadline",
+                                     &details->deadline),
+    TALER_PQ_RESULT_SPEC_AMOUNT ("commitment",
+                                 &details->commitment),
+    TALER_PQ_RESULT_SPEC_AMOUNT ("accumulated_total",
+                                 &details->accumulated_total),
+    TALER_PQ_RESULT_SPEC_AMOUNT ("policy_fee",
+                                 &details->policy_fee),
+    TALER_PQ_RESULT_SPEC_AMOUNT ("transferable_amount",
+                                 &details->transferable_amount),
+    GNUNET_PQ_result_spec_auto_from_type ("state",
+                                          &details->fulfillment_state),
+    GNUNET_PQ_result_spec_allow_null (
+      GNUNET_PQ_result_spec_uint64 ("policy_fulfillment_id",
+                                    &details->policy_fulfillment_id),
+      &details->no_policy_fulfillment_id),
+    GNUNET_PQ_result_spec_end
+  };
+
+
+  
+  return GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
+                                                   "get_policy_details",
+                                                   params,
+                                                   rs);
+}
diff --git a/src/exchangedb/pg_get_policy_details.h 
b/src/exchangedb/pg_get_policy_details.h
new file mode 100644
index 00000000..e3d2b0a2
--- /dev/null
+++ b/src/exchangedb/pg_get_policy_details.h
@@ -0,0 +1,40 @@
+/*
+   This file is part of TALER
+   Copyright (C) 2022 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 exchangedb/pg_get_policy_details.h
+ * @brief implementation of the get_policy_details function for Postgres
+ * @author Christian Grothoff
+ */
+#ifndef PG_GET_POLICY_DETAILS_H
+#define PG_GET_POLICY_DETAILS_H
+
+#include "taler_util.h"
+#include "taler_json_lib.h"
+#include "taler_exchangedb_plugin.h"
+/* Get the details of a policy, referenced by its hash code
+ *
+ * @param cls the `struct PostgresClosure` with the plugin-specific state
+ * @param hc The hash code under which the details to a particular policy 
should be found
+ * @param[out] details The found details
+ * @return query execution status
+ * */
+enum GNUNET_DB_QueryStatus
+TEH_PG_get_policy_details (
+  void *cls,
+  const struct GNUNET_HashCode *hc,
+  struct TALER_PolicyDetails *details);
+
+#endif
diff --git a/src/exchangedb/pg_get_ready_deposit.c 
b/src/exchangedb/pg_get_ready_deposit.c
new file mode 100644
index 00000000..741a480d
--- /dev/null
+++ b/src/exchangedb/pg_get_ready_deposit.c
@@ -0,0 +1,94 @@
+/*
+   This file is part of TALER
+   Copyright (C) 2022 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 exchangedb/pg_get_ready_deposit.c
+ * @brief Implementation of the get_ready_deposit function for Postgres
+ * @author Christian Grothoff
+ */
+#include "platform.h"
+#include "taler_error_codes.h"
+#include "taler_dbevents.h"
+#include "taler_pq_lib.h"
+#include "pg_get_ready_deposit.h"
+#include "pg_helper.h"
+
+
+enum GNUNET_DB_QueryStatus
+TEH_PG_get_ready_deposit (void *cls,
+                            uint64_t start_shard_row,
+                            uint64_t end_shard_row,
+                            struct TALER_MerchantPublicKeyP *merchant_pub,
+                            char **payto_uri)
+{
+  struct PostgresClosure *pg = cls;
+  struct GNUNET_TIME_Absolute now = {0};
+  struct GNUNET_PQ_QueryParam params[] = {
+    GNUNET_PQ_query_param_absolute_time (&now),
+    GNUNET_PQ_query_param_uint64 (&start_shard_row),
+    GNUNET_PQ_query_param_uint64 (&end_shard_row),
+    GNUNET_PQ_query_param_end
+  };
+  struct GNUNET_PQ_ResultSpec rs[] = {
+    GNUNET_PQ_result_spec_auto_from_type ("merchant_pub",
+                                          merchant_pub),
+    GNUNET_PQ_result_spec_string ("payto_uri",
+                                  payto_uri),
+    GNUNET_PQ_result_spec_end
+  };
+
+  now = GNUNET_TIME_absolute_round_down (GNUNET_TIME_absolute_get (),
+                                         pg->aggregator_shift);
+  GNUNET_assert (start_shard_row < end_shard_row);
+  GNUNET_assert (end_shard_row <= INT32_MAX);
+  GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+              "Finding ready deposits by deadline %s (%llu)\n",
+              GNUNET_TIME_absolute2s (now),
+              (unsigned long long) now.abs_value_us);
+
+
+    /* Used in #postgres_get_ready_deposit() */
+  PREPARE (pg,
+           "deposits_get_ready",
+           "SELECT"
+           " payto_uri"
+           ",merchant_pub"
+           " FROM deposits_by_ready dbr"
+           "  JOIN deposits dep"
+           "    ON (dbr.coin_pub = dep.coin_pub AND"
+           "        dbr.deposit_serial_id = dep.deposit_serial_id)"
+           "  JOIN wire_targets wt"
+           "    USING (wire_target_h_payto)"
+           " WHERE dbr.wire_deadline<=$1"
+           "   AND dbr.shard >= $2"
+           "   AND dbr.shard <= $3"
+           " ORDER BY "
+           "   dbr.wire_deadline ASC"
+           "  ,dbr.shard ASC"
+           " LIMIT 1;");
+
+
+
+  return GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
+                                                   "deposits_get_ready",
+                                                   params,
+                                                   rs);
+}
+
+
+
+
+
+
diff --git a/src/exchangedb/pg_get_ready_deposit.h 
b/src/exchangedb/pg_get_ready_deposit.h
new file mode 100644
index 00000000..19b6dafe
--- /dev/null
+++ b/src/exchangedb/pg_get_ready_deposit.h
@@ -0,0 +1,46 @@
+/*
+   This file is part of TALER
+   Copyright (C) 2022 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 exchangedb/pg_get_ready_deposit.h
+ * @brief implementation of the get_ready_deposit function for Postgres
+ * @author Christian Grothoff
+ */
+#ifndef PG_GET_READY_DEPOSIT_H
+#define PG_GET_READY_DEPOSIT_H
+
+#include "taler_util.h"
+#include "taler_json_lib.h"
+#include "taler_exchangedb_plugin.h"
+/**
+ * Obtain information about deposits that are ready to be executed.  Such
+ * deposits must not be marked as "done", the execution time must be
+ * in the past, and the KYC status must be 'ok'.
+ *
+ * @param cls the @e cls of this struct with the plugin-specific state
+ * @param start_shard_row minimum shard row to select
+ * @param end_shard_row maximum shard row to select (inclusive)
+ * @param[out] merchant_pub set to the public key of a merchant with a ready 
deposit
+ * @param[out] payto_uri set to the account of the merchant, to be freed by 
caller
+ * @return transaction status code
+ */
+enum GNUNET_DB_QueryStatus
+TEH_PG_get_ready_deposit (void *cls,
+                            uint64_t start_shard_row,
+                            uint64_t end_shard_row,
+                            struct TALER_MerchantPublicKeyP *merchant_pub,
+                          char **payto_uri);
+
+#endif
diff --git a/src/exchangedb/pg_get_refresh_reveal.c 
b/src/exchangedb/pg_get_refresh_reveal.c
new file mode 100644
index 00000000..e2db082b
--- /dev/null
+++ b/src/exchangedb/pg_get_refresh_reveal.c
@@ -0,0 +1,214 @@
+/*
+   This file is part of TALER
+   Copyright (C) 2022 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 exchangedb/pg_get_refresh_reveal.c
+ * @brief Implementation of the get_refresh_reveal function for Postgres
+ * @author Christian Grothoff
+ */
+#include "platform.h"
+#include "taler_error_codes.h"
+#include "taler_dbevents.h"
+#include "taler_pq_lib.h"
+#include "pg_get_refresh_reveal.h"
+#include "pg_helper.h"
+
+
+/**
+ * Context where we aggregate data from the database.
+ * Closure for #add_revealed_coins().
+ */
+struct GetRevealContext
+{
+  /**
+   * Array of revealed coins we obtained from the DB.
+   */
+  struct TALER_EXCHANGEDB_RefreshRevealedCoin *rrcs;
+
+  /**
+   * Length of the @a rrcs array.
+   */
+  unsigned int rrcs_len;
+
+  /**
+   * Set to an error code if we ran into trouble.
+   */
+  enum GNUNET_DB_QueryStatus qs;
+};
+
+
+/**
+ * Function to be called with the results of a SELECT statement
+ * that has returned @a num_results results.
+ *
+ * @param cls closure of type `struct GetRevealContext`
+ * @param result the postgres result
+ * @param num_results the number of results in @a result
+ */
+static void
+add_revealed_coins (void *cls,
+                    PGresult *result,
+                    unsigned int num_results)
+{
+  struct GetRevealContext *grctx = cls;
+
+  if (0 == num_results)
+    return;
+  grctx->rrcs = GNUNET_new_array (num_results,
+                                  struct TALER_EXCHANGEDB_RefreshRevealedCoin);
+  grctx->rrcs_len = num_results;
+  for (unsigned int i = 0; i < num_results; i++)
+  {
+    uint32_t off;
+    struct GNUNET_PQ_ResultSpec rso[] = {
+      GNUNET_PQ_result_spec_uint32 ("freshcoin_index",
+                                    &off),
+      GNUNET_PQ_result_spec_end
+    };
+
+    if (GNUNET_OK !=
+        GNUNET_PQ_extract_result (result,
+                                  rso,
+                                  i))
+    {
+      GNUNET_break (0);
+      grctx->qs = GNUNET_DB_STATUS_HARD_ERROR;
+      return;
+    }
+    if (off >= num_results)
+    {
+      GNUNET_break (0);
+      grctx->qs = GNUNET_DB_STATUS_HARD_ERROR;
+      return;
+    }
+    {
+      struct TALER_EXCHANGEDB_RefreshRevealedCoin *rrc = &grctx->rrcs[off];
+      struct GNUNET_PQ_ResultSpec rsi[] = {
+        /* NOTE: freshcoin_index selected and discarded here... */
+        GNUNET_PQ_result_spec_auto_from_type ("denom_pub_hash",
+                                              &rrc->h_denom_pub),
+        GNUNET_PQ_result_spec_auto_from_type ("link_sig",
+                                              &rrc->orig_coin_link_sig),
+        GNUNET_PQ_result_spec_auto_from_type ("h_coin_ev",
+                                              &rrc->coin_envelope_hash),
+        TALER_PQ_result_spec_blinded_planchet ("coin_ev",
+                                               &rrc->blinded_planchet),
+        TALER_PQ_result_spec_exchange_withdraw_values ("ewv",
+                                                       &rrc->exchange_vals),
+        TALER_PQ_result_spec_blinded_denom_sig ("ev_sig",
+                                                &rrc->coin_sig),
+        GNUNET_PQ_result_spec_end
+      };
+
+      if (TALER_DENOMINATION_INVALID != rrc->blinded_planchet.cipher)
+      {
+        /* duplicate offset, not allowed */
+        GNUNET_break (0);
+        grctx->qs = GNUNET_DB_STATUS_HARD_ERROR;
+        return;
+      }
+      if (GNUNET_OK !=
+          GNUNET_PQ_extract_result (result,
+                                    rsi,
+                                    i))
+      {
+        GNUNET_break (0);
+        grctx->qs = GNUNET_DB_STATUS_HARD_ERROR;
+        return;
+      }
+    }
+  }
+}
+
+
+
+
+
+enum GNUNET_DB_QueryStatus
+TEH_PG_get_refresh_reveal (void *cls,
+                             const struct TALER_RefreshCommitmentP *rc,
+                             TALER_EXCHANGEDB_RefreshCallback cb,
+                             void *cb_cls)
+{
+  struct PostgresClosure *pg = cls;
+  struct GetRevealContext grctx;
+  enum GNUNET_DB_QueryStatus qs;
+  struct GNUNET_PQ_QueryParam params[] = {
+    GNUNET_PQ_query_param_auto_from_type (rc),
+    GNUNET_PQ_query_param_end
+  };
+
+  memset (&grctx,
+          0,
+          sizeof (grctx));
+
+    /* Obtain information about the coins created in a refresh
+       operation, used in #postgres_get_refresh_reveal() */
+  PREPARE (pg,
+           "get_refresh_revealed_coins",
+           "SELECT "
+           " rrc.freshcoin_index"
+           ",denom.denom_pub_hash"
+           ",rrc.h_coin_ev"
+           ",rrc.link_sig"
+           ",rrc.coin_ev"
+           ",rrc.ewv"
+           ",rrc.ev_sig"
+           " FROM refresh_commitments"
+           "    JOIN refresh_revealed_coins rrc"
+           "      USING (melt_serial_id)"
+           "    JOIN denominations denom "
+           "      USING (denominations_serial)"
+           " WHERE rc=$1;");
+  qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn,
+                                             "get_refresh_revealed_coins",
+                                             params,
+                                             &add_revealed_coins,
+                                             &grctx);
+  switch (qs)
+  {
+  case GNUNET_DB_STATUS_HARD_ERROR:
+  case GNUNET_DB_STATUS_SOFT_ERROR:
+  case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS:
+    goto cleanup;
+  case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT:
+  default: /* can have more than one result */
+    break;
+  }
+  switch (grctx.qs)
+  {
+  case GNUNET_DB_STATUS_HARD_ERROR:
+  case GNUNET_DB_STATUS_SOFT_ERROR:
+    goto cleanup;
+  case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS:
+  case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT: /* should be impossible */
+    break;
+  }
+
+  /* Pass result back to application */
+  cb (cb_cls,
+      grctx.rrcs_len,
+      grctx.rrcs);
+cleanup:
+  for (unsigned int i = 0; i < grctx.rrcs_len; i++)
+  {
+    struct TALER_EXCHANGEDB_RefreshRevealedCoin *rrc = &grctx.rrcs[i];
+
+    TALER_blinded_denom_sig_free (&rrc->coin_sig);
+    TALER_blinded_planchet_free (&rrc->blinded_planchet);
+  }
+  GNUNET_free (grctx.rrcs);
+  return qs;
+}
diff --git a/src/exchangedb/pg_get_refresh_reveal.h 
b/src/exchangedb/pg_get_refresh_reveal.h
new file mode 100644
index 00000000..0fcea26c
--- /dev/null
+++ b/src/exchangedb/pg_get_refresh_reveal.h
@@ -0,0 +1,44 @@
+/*
+   This file is part of TALER
+   Copyright (C) 2022 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 exchangedb/pg_get_refresh_reveal.h
+ * @brief implementation of the get_refresh_reveal function for Postgres
+ * @author Christian Grothoff
+ */
+#ifndef PG_GET_REFRESH_REVEAL_H
+#define PG_GET_REFRESH_REVEAL_H
+
+#include "taler_util.h"
+#include "taler_json_lib.h"
+#include "taler_exchangedb_plugin.h"
+
+/**
+ * Lookup in the database the coins that we want to
+ * create in the given refresh operation.
+ *
+ * @param cls the `struct PostgresClosure` with the plugin-specific state
+ * @param rc identify commitment and thus refresh operation
+ * @param cb function to call with the results
+ * @param cb_cls closure for @a cb
+ * @return transaction status
+ */
+enum GNUNET_DB_QueryStatus
+TEH_PG_get_refresh_reveal (void *cls,
+                             const struct TALER_RefreshCommitmentP *rc,
+                             TALER_EXCHANGEDB_RefreshCallback cb,
+                           void *cb_cls);
+
+#endif
diff --git a/src/exchangedb/pg_get_reserve_balance.c 
b/src/exchangedb/pg_get_reserve_balance.c
new file mode 100644
index 00000000..e08261fc
--- /dev/null
+++ b/src/exchangedb/pg_get_reserve_balance.c
@@ -0,0 +1,55 @@
+/*
+   This file is part of TALER
+   Copyright (C) 2022 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 exchangedb/pg_get_reserve_balance.c
+ * @brief Implementation of the get_reserve_balance function for Postgres
+ * @author Christian Grothoff
+ */
+#include "platform.h"
+#include "taler_error_codes.h"
+#include "taler_dbevents.h"
+#include "taler_pq_lib.h"
+#include "pg_get_reserve_balance.h"
+#include "pg_helper.h"
+
+enum GNUNET_DB_QueryStatus
+TEH_PG_get_reserve_balance (void *cls,
+                              const struct TALER_ReservePublicKeyP 
*reserve_pub,
+                              struct TALER_Amount *balance)
+{
+  struct PostgresClosure *pg = cls;
+  struct GNUNET_PQ_QueryParam params[] = {
+    GNUNET_PQ_query_param_auto_from_type (reserve_pub),
+    GNUNET_PQ_query_param_end
+  };
+  struct GNUNET_PQ_ResultSpec rs[] = {
+    TALER_PQ_RESULT_SPEC_AMOUNT ("current_balance",
+                                 balance),
+    GNUNET_PQ_result_spec_end
+  };
+
+  PREPARE (pg,
+           "get_reserve_balance",
+           "SELECT"
+           " current_balance_val"
+           ",current_balance_frac"
+           " FROM reserves"
+           " WHERE reserve_pub=$1;");
+  return GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
+                                                   "get_reserve_balance",
+                                                   params,
+                                                   rs);
+}
diff --git a/src/exchangedb/pg_get_reserve_balance.h 
b/src/exchangedb/pg_get_reserve_balance.h
new file mode 100644
index 00000000..fd15f0d8
--- /dev/null
+++ b/src/exchangedb/pg_get_reserve_balance.h
@@ -0,0 +1,40 @@
+/*
+   This file is part of TALER
+   Copyright (C) 2022 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 exchangedb/pg_get_reserve_balance.h
+ * @brief implementation of the get_reserve_balance function for Postgres
+ * @author Christian Grothoff
+ */
+#ifndef PG_GET_RESERVE_BALANCE_H
+#define PG_GET_RESERVE_BALANCE_H
+
+#include "taler_util.h"
+#include "taler_json_lib.h"
+#include "taler_exchangedb_plugin.h"
+/**
+ * Get the balance of the specified reserve.
+ *
+ * @param cls the `struct PostgresClosure` with the plugin-specific state
+ * @param reserve_pub public key of the reserve
+ * @param[out] balance set to the reserve balance
+ * @return transaction status
+ */
+enum GNUNET_DB_QueryStatus
+TEH_PG_get_reserve_balance (void *cls,
+                              const struct TALER_ReservePublicKeyP 
*reserve_pub,
+                            struct TALER_Amount *balance);
+
+#endif
diff --git a/src/exchangedb/pg_get_reserve_by_h_blind.c 
b/src/exchangedb/pg_get_reserve_by_h_blind.c
new file mode 100644
index 00000000..2105b476
--- /dev/null
+++ b/src/exchangedb/pg_get_reserve_by_h_blind.c
@@ -0,0 +1,63 @@
+/*
+   This file is part of TALER
+   Copyright (C) 2022 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 exchangedb/pg_get_reserve_by_h_blind.c
+ * @brief Implementation of the get_reserve_by_h_blind function for Postgres
+ * @author Christian Grothoff
+ */
+#include "platform.h"
+#include "taler_error_codes.h"
+#include "taler_dbevents.h"
+#include "taler_pq_lib.h"
+#include "pg_get_reserve_by_h_blind.h"
+#include "pg_helper.h"
+
+
+enum GNUNET_DB_QueryStatus
+TEH_PG_get_reserve_by_h_blind (
+  void *cls,
+  const struct TALER_BlindedCoinHashP *bch,
+  struct TALER_ReservePublicKeyP *reserve_pub,
+  uint64_t *reserve_out_serial_id)
+{
+  struct PostgresClosure *pg = cls;
+  struct GNUNET_PQ_QueryParam params[] = {
+    GNUNET_PQ_query_param_auto_from_type (bch),
+    GNUNET_PQ_query_param_end
+  };
+  struct GNUNET_PQ_ResultSpec rs[] = {
+    GNUNET_PQ_result_spec_auto_from_type ("reserve_pub",
+                                          reserve_pub),
+    GNUNET_PQ_result_spec_uint64 ("reserve_out_serial_id",
+                                  reserve_out_serial_id),
+    GNUNET_PQ_result_spec_end
+  };
+    /* Used in #postgres_get_reserve_by_h_blind() */
+  PREPARE (pg,
+           "reserve_by_h_blind",
+           "SELECT"
+           " reserves.reserve_pub"
+           ",reserve_out_serial_id"
+           " FROM reserves_out"
+           " JOIN reserves"
+           "   USING (reserve_uuid)"
+           " WHERE h_blind_ev=$1"
+           " LIMIT 1;");
+  return GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
+                                                   "reserve_by_h_blind",
+                                                   params,
+                                                   rs);
+}
diff --git a/src/exchangedb/pg_get_reserve_by_h_blind.h 
b/src/exchangedb/pg_get_reserve_by_h_blind.h
new file mode 100644
index 00000000..49c1c840
--- /dev/null
+++ b/src/exchangedb/pg_get_reserve_by_h_blind.h
@@ -0,0 +1,44 @@
+/*
+   This file is part of TALER
+   Copyright (C) 2022 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 exchangedb/pg_get_reserve_by_h_blind.h
+ * @brief implementation of the get_reserve_by_h_blind function for Postgres
+ * @author Christian Grothoff
+ */
+#ifndef PG_GET_RESERVE_BY_H_BLIND_H
+#define PG_GET_RESERVE_BY_H_BLIND_H
+
+#include "taler_util.h"
+#include "taler_json_lib.h"
+#include "taler_exchangedb_plugin.h"
+/**
+ * Obtain information about which reserve a coin was generated
+ * from given the hash of the blinded coin.
+ *
+ * @param cls closure
+ * @param bch hash that uniquely identifies the withdraw request
+ * @param[out] reserve_pub set to information about the reserve (on success 
only)
+ * @param[out] reserve_out_serial_id set to row of the @a h_blind_ev in 
reserves_out
+ * @return transaction status code
+ */
+enum GNUNET_DB_QueryStatus
+TEH_PG_get_reserve_by_h_blind (
+  void *cls,
+  const struct TALER_BlindedCoinHashP *bch,
+  struct TALER_ReservePublicKeyP *reserve_pub,
+  uint64_t *reserve_out_serial_id);
+
+#endif
diff --git a/src/exchangedb/pg_get_wire_accounts.c 
b/src/exchangedb/pg_get_wire_accounts.c
new file mode 100644
index 00000000..6986eaef
--- /dev/null
+++ b/src/exchangedb/pg_get_wire_accounts.c
@@ -0,0 +1,129 @@
+/*
+   This file is part of TALER
+   Copyright (C) 2022 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 exchangedb/pg_get_wire_accounts.c
+ * @brief Implementation of the get_wire_accounts function for Postgres
+ * @author Christian Grothoff
+ */
+#include "platform.h"
+#include "taler_error_codes.h"
+#include "taler_dbevents.h"
+#include "taler_pq_lib.h"
+#include "pg_get_wire_accounts.h"
+#include "pg_helper.h"
+
+
+/**
+ * Closure for #get_wire_accounts_cb().
+ */
+struct GetWireAccountsContext
+{
+  /**
+   * Function to call per result.
+   */
+  TALER_EXCHANGEDB_WireAccountCallback cb;
+
+  /**
+   * Closure for @e cb.
+   */
+  void *cb_cls;
+
+  /**
+   * Flag set to #GNUNET_OK as long as everything is fine.
+   */
+  enum GNUNET_GenericReturnValue status;
+
+};
+
+
+/**
+ * Invoke the callback for each result.
+ *
+ * @param cls a `struct MissingWireContext *`
+ * @param result SQL result
+ * @param num_results number of rows in @a result
+ */
+static void
+get_wire_accounts_cb (void *cls,
+                      PGresult *result,
+                      unsigned int num_results)
+{
+  struct GetWireAccountsContext *ctx = cls;
+
+  for (unsigned int i = 0; i < num_results; i++)
+  {
+    char *payto_uri;
+    struct TALER_MasterSignatureP master_sig;
+    struct GNUNET_PQ_ResultSpec rs[] = {
+      GNUNET_PQ_result_spec_string ("payto_uri",
+                                    &payto_uri),
+      GNUNET_PQ_result_spec_auto_from_type ("master_sig",
+                                            &master_sig),
+      GNUNET_PQ_result_spec_end
+    };
+
+    if (GNUNET_OK !=
+        GNUNET_PQ_extract_result (result,
+                                  rs,
+                                  i))
+    {
+      GNUNET_break (0);
+      ctx->status = GNUNET_SYSERR;
+      return;
+    }
+    ctx->cb (ctx->cb_cls,
+             payto_uri,
+             &master_sig);
+    GNUNET_PQ_cleanup_result (rs);
+  }
+}
+
+
+
+
+enum GNUNET_DB_QueryStatus
+TEH_PG_get_wire_accounts (void *cls,
+                            TALER_EXCHANGEDB_WireAccountCallback cb,
+                            void *cb_cls)
+{
+  struct PostgresClosure *pg = cls;
+  struct GetWireAccountsContext ctx = {
+    .cb = cb,
+    .cb_cls = cb_cls,
+    .status = GNUNET_OK
+  };
+  struct GNUNET_PQ_QueryParam params[] = {
+    GNUNET_PQ_query_param_end
+  };
+  enum GNUNET_DB_QueryStatus qs;
+
+  PREPARE (pg,
+      "get_wire_accounts",
+      "SELECT"
+      " payto_uri"
+      ",master_sig"
+      " FROM wire_accounts"
+      " WHERE is_active");
+  qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn,
+                                             "get_wire_accounts",
+                                             params,
+                                             &get_wire_accounts_cb,
+                                             &ctx);
+  if (GNUNET_OK != ctx.status)
+    return GNUNET_DB_STATUS_HARD_ERROR;
+  return qs;
+
+}
diff --git a/src/exchangedb/pg_get_wire_accounts.h 
b/src/exchangedb/pg_get_wire_accounts.h
new file mode 100644
index 00000000..4ddda0ed
--- /dev/null
+++ b/src/exchangedb/pg_get_wire_accounts.h
@@ -0,0 +1,42 @@
+/*
+   This file is part of TALER
+   Copyright (C) 2022 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 exchangedb/pg_get_wire_accounts.h
+ * @brief implementation of the get_wire_accounts function for Postgres
+ * @author Christian Grothoff
+ */
+#ifndef PG_GET_WIRE_ACCOUNTS_H
+#define PG_GET_WIRE_ACCOUNTS_H
+
+#include "taler_util.h"
+#include "taler_json_lib.h"
+#include "taler_exchangedb_plugin.h"
+
+
+/**
+ * Obtain information about the enabled wire accounts of the exchange.
+ *
+ * @param cls closure
+ * @param cb function to call on each account
+ * @param cb_cls closure for @a cb
+ * @return transaction status code
+ */
+enum GNUNET_DB_QueryStatus
+TEH_PG_get_wire_accounts (void *cls,
+                            TALER_EXCHANGEDB_WireAccountCallback cb,
+                          void *cb_cls);
+
+#endif
diff --git a/src/exchangedb/pg_get_wire_fee.c b/src/exchangedb/pg_get_wire_fee.c
new file mode 100644
index 00000000..4b432476
--- /dev/null
+++ b/src/exchangedb/pg_get_wire_fee.c
@@ -0,0 +1,78 @@
+/*
+   This file is part of TALER
+   Copyright (C) 2022 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 exchangedb/pg_get_wire_fee.c
+ * @brief Implementation of the get_wire_fee function for Postgres
+ * @author Christian Grothoff
+ */
+#include "platform.h"
+#include "taler_error_codes.h"
+#include "taler_dbevents.h"
+#include "taler_pq_lib.h"
+#include "pg_get_wire_fee.h"
+#include "pg_helper.h"
+
+enum GNUNET_DB_QueryStatus
+TEH_PG_get_wire_fee (void *cls,
+                       const char *type,
+                       struct GNUNET_TIME_Timestamp date,
+                       struct GNUNET_TIME_Timestamp *start_date,
+                       struct GNUNET_TIME_Timestamp *end_date,
+                       struct TALER_WireFeeSet *fees,
+                       struct TALER_MasterSignatureP *master_sig)
+{
+  struct PostgresClosure *pg = cls;
+  struct GNUNET_PQ_QueryParam params[] = {
+    GNUNET_PQ_query_param_string (type),
+    GNUNET_PQ_query_param_timestamp (&date),
+    GNUNET_PQ_query_param_end
+  };
+  struct GNUNET_PQ_ResultSpec rs[] = {
+    GNUNET_PQ_result_spec_timestamp ("start_date",
+                                     start_date),
+    GNUNET_PQ_result_spec_timestamp ("end_date",
+                                     end_date),
+    TALER_PQ_RESULT_SPEC_AMOUNT ("wire_fee",
+                                 &fees->wire),
+    TALER_PQ_RESULT_SPEC_AMOUNT ("closing_fee",
+                                 &fees->closing),
+    GNUNET_PQ_result_spec_auto_from_type ("master_sig",
+                                          master_sig),
+    GNUNET_PQ_result_spec_end
+  };
+
+
+
+      /* Used in #postgres_get_wire_fee() */
+  PREPARE(pg,
+          "get_wire_fee",
+          "SELECT "
+          " start_date"
+          ",end_date"
+          ",wire_fee_val"
+          ",wire_fee_frac"
+          ",closing_fee_val"
+          ",closing_fee_frac"
+          ",master_sig"
+          " FROM wire_fee"
+          " WHERE wire_method=$1"
+          "   AND start_date <= $2"
+          "   AND end_date > $2;");
+  return GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
+                                                   "get_wire_fee",
+                                                   params,
+                                                   rs);
+}
diff --git a/src/exchangedb/pg_get_wire_fee.h b/src/exchangedb/pg_get_wire_fee.h
new file mode 100644
index 00000000..92107fe3
--- /dev/null
+++ b/src/exchangedb/pg_get_wire_fee.h
@@ -0,0 +1,49 @@
+/*
+   This file is part of TALER
+   Copyright (C) 2022 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 exchangedb/pg_get_wire_fee.h
+ * @brief implementation of the get_wire_fee function for Postgres
+ * @author Christian Grothoff
+ */
+#ifndef PG_GET_WIRE_FEE_H
+#define PG_GET_WIRE_FEE_H
+
+#include "taler_util.h"
+#include "taler_json_lib.h"
+#include "taler_exchangedb_plugin.h"
+
+/**
+ * Obtain wire fee from database.
+ *
+ * @param cls closure
+ * @param type type of wire transfer the fee applies for
+ * @param date for which date do we want the fee?
+ * @param[out] start_date when does the fee go into effect
+ * @param[out] end_date when does the fee end being valid
+ * @param[out] fees how high are the wire fees
+ * @param[out] master_sig signature over the above by the exchange master key
+ * @return status of the transaction
+ */
+enum GNUNET_DB_QueryStatus
+TEH_PG_get_wire_fee (void *cls,
+                       const char *type,
+                       struct GNUNET_TIME_Timestamp date,
+                       struct GNUNET_TIME_Timestamp *start_date,
+                       struct GNUNET_TIME_Timestamp *end_date,
+                       struct TALER_WireFeeSet *fees,
+                     struct TALER_MasterSignatureP *master_sig);
+
+#endif
diff --git a/src/exchangedb/pg_get_wire_fees.c 
b/src/exchangedb/pg_get_wire_fees.c
new file mode 100644
index 00000000..a83db151
--- /dev/null
+++ b/src/exchangedb/pg_get_wire_fees.c
@@ -0,0 +1,150 @@
+/*
+   This file is part of TALER
+   Copyright (C) 2022 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 exchangedb/pg_get_wire_fees.c
+ * @brief Implementation of the get_wire_fees function for Postgres
+ * @author Christian Grothoff
+ */
+#include "platform.h"
+#include "taler_error_codes.h"
+#include "taler_dbevents.h"
+#include "taler_pq_lib.h"
+#include "pg_get_wire_fees.h"
+#include "pg_helper.h"
+
+/**
+ * Closure for #get_wire_fees_cb().
+ */
+struct GetWireFeesContext
+{
+  /**
+   * Function to call per result.
+   */
+  TALER_EXCHANGEDB_WireFeeCallback cb;
+
+  /**
+   * Closure for @e cb.
+   */
+  void *cb_cls;
+
+  /**
+   * Plugin context.
+   */
+  struct PostgresClosure *pg;
+
+  /**
+   * Flag set to #GNUNET_OK as long as everything is fine.
+   */
+  enum GNUNET_GenericReturnValue status;
+
+};
+
+
+/**
+ * Invoke the callback for each result.
+ *
+ * @param cls a `struct GetWireFeesContext *`
+ * @param result SQL result
+ * @param num_results number of rows in @a result
+ */
+static void
+get_wire_fees_cb (void *cls,
+                  PGresult *result,
+                  unsigned int num_results)
+{
+  struct GetWireFeesContext *ctx = cls;
+  struct PostgresClosure *pg = ctx->pg;
+
+  for (unsigned int i = 0; i < num_results; i++)
+  {
+    struct TALER_MasterSignatureP master_sig;
+    struct TALER_WireFeeSet fees;
+    struct GNUNET_TIME_Timestamp start_date;
+    struct GNUNET_TIME_Timestamp end_date;
+    struct GNUNET_PQ_ResultSpec rs[] = {
+      TALER_PQ_RESULT_SPEC_AMOUNT ("wire_fee",
+                                   &fees.wire),
+      TALER_PQ_RESULT_SPEC_AMOUNT ("closing_fee",
+                                   &fees.closing),
+      GNUNET_PQ_result_spec_timestamp ("start_date",
+                                       &start_date),
+      GNUNET_PQ_result_spec_timestamp ("end_date",
+                                       &end_date),
+      GNUNET_PQ_result_spec_auto_from_type ("master_sig",
+                                            &master_sig),
+      GNUNET_PQ_result_spec_end
+    };
+
+    if (GNUNET_OK !=
+        GNUNET_PQ_extract_result (result,
+                                  rs,
+                                  i))
+    {
+      GNUNET_break (0);
+      ctx->status = GNUNET_SYSERR;
+      return;
+    }
+    ctx->cb (ctx->cb_cls,
+             &fees,
+             start_date,
+             end_date,
+             &master_sig);
+    GNUNET_PQ_cleanup_result (rs);
+  }
+}
+
+
+enum GNUNET_DB_QueryStatus
+TEH_PG_get_wire_fees (void *cls,
+                        const char *wire_method,
+                        TALER_EXCHANGEDB_WireFeeCallback cb,
+                        void *cb_cls)
+{
+  struct PostgresClosure *pg = cls;
+  struct GNUNET_PQ_QueryParam params[] = {
+    GNUNET_PQ_query_param_string (wire_method),
+    GNUNET_PQ_query_param_end
+  };
+  struct GetWireFeesContext ctx = {
+    .cb = cb,
+    .cb_cls = cb_cls,
+    .pg = pg,
+    .status = GNUNET_OK
+  };
+  enum GNUNET_DB_QueryStatus qs;
+
+
+  PREPARE (pg,
+           "get_wire_fees",
+           "SELECT"
+           " wire_fee_val"
+           ",wire_fee_frac"
+           ",closing_fee_val"
+           ",closing_fee_frac"
+           ",start_date"
+           ",end_date"
+           ",master_sig"
+           " FROM wire_fee"
+           " WHERE wire_method=$1");
+  qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn,
+                                             "get_wire_fees",
+                                             params,
+                                             &get_wire_fees_cb,
+                                             &ctx);
+  if (GNUNET_OK != ctx.status)
+    return GNUNET_DB_STATUS_HARD_ERROR;
+  return qs;
+}
diff --git a/src/exchangedb/pg_get_wire_fees.h 
b/src/exchangedb/pg_get_wire_fees.h
new file mode 100644
index 00000000..83bacd67
--- /dev/null
+++ b/src/exchangedb/pg_get_wire_fees.h
@@ -0,0 +1,44 @@
+/*
+   This file is part of TALER
+   Copyright (C) 2022 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 exchangedb/pg_get_wire_fees.h
+ * @brief implementation of the get_wire_fees function for Postgres
+ * @author Christian Grothoff
+ */
+#ifndef PG_GET_WIRE_FEES_H
+#define PG_GET_WIRE_FEES_H
+
+#include "taler_util.h"
+#include "taler_json_lib.h"
+#include "taler_exchangedb_plugin.h"
+
+/**
+ * Obtain information about the fee structure of the exchange for
+ * a given @a wire_method
+ *
+ * @param cls closure
+ * @param wire_method which wire method to obtain fees for
+ * @param cb function to call on each account
+ * @param cb_cls closure for @a cb
+ * @return transaction status code
+ */
+enum GNUNET_DB_QueryStatus
+TEH_PG_get_wire_fees (void *cls,
+                        const char *wire_method,
+                        TALER_EXCHANGEDB_WireFeeCallback cb,
+                      void *cb_cls);
+
+#endif
diff --git a/src/exchangedb/pg_get_withdraw_info.c 
b/src/exchangedb/pg_get_withdraw_info.c
new file mode 100644
index 00000000..ef393626
--- /dev/null
+++ b/src/exchangedb/pg_get_withdraw_info.c
@@ -0,0 +1,85 @@
+/*
+   This file is part of TALER
+   Copyright (C) 2022 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 exchangedb/pg_get_withdraw_info.c
+ * @brief Implementation of the get_withdraw_info function for Postgres
+ * @author Christian Grothoff
+ */
+#include "platform.h"
+#include "taler_error_codes.h"
+#include "taler_dbevents.h"
+#include "taler_pq_lib.h"
+#include "pg_get_withdraw_info.h"
+#include "pg_helper.h"
+
+
+enum GNUNET_DB_QueryStatus
+TEH_PG_get_withdraw_info (
+  void *cls,
+  const struct TALER_BlindedCoinHashP *bch,
+  struct TALER_EXCHANGEDB_CollectableBlindcoin *collectable)
+{
+  struct PostgresClosure *pg = cls;
+  struct GNUNET_PQ_QueryParam params[] = {
+    GNUNET_PQ_query_param_auto_from_type (bch),
+    GNUNET_PQ_query_param_end
+  };
+  struct GNUNET_PQ_ResultSpec rs[] = {
+    GNUNET_PQ_result_spec_auto_from_type ("denom_pub_hash",
+                                          &collectable->denom_pub_hash),
+    TALER_PQ_result_spec_blinded_denom_sig ("denom_sig",
+                                            &collectable->sig),
+    GNUNET_PQ_result_spec_auto_from_type ("reserve_sig",
+                                          &collectable->reserve_sig),
+    GNUNET_PQ_result_spec_auto_from_type ("reserve_pub",
+                                          &collectable->reserve_pub),
+    GNUNET_PQ_result_spec_auto_from_type ("h_blind_ev",
+                                          &collectable->h_coin_envelope),
+    TALER_PQ_RESULT_SPEC_AMOUNT ("amount_with_fee",
+                                 &collectable->amount_with_fee),
+    TALER_PQ_RESULT_SPEC_AMOUNT ("fee_withdraw",
+                                 &collectable->withdraw_fee),
+    GNUNET_PQ_result_spec_end
+  };
+
+   /* Used in #postgres_get_withdraw_info() to
+       locate the response for a /reserve/withdraw request
+       using the hash of the blinded message.  Used to
+       make sure /reserve/withdraw requests are idempotent. */
+  PREPARE (pg,
+           "get_withdraw_info",
+           "SELECT"
+           " denom.denom_pub_hash"
+           ",denom_sig"
+           ",reserve_sig"
+           ",reserves.reserve_pub"
+           ",execution_date"
+           ",h_blind_ev"
+           ",amount_with_fee_val"
+           ",amount_with_fee_frac"
+           ",denom.fee_withdraw_val"
+           ",denom.fee_withdraw_frac"
+           " FROM reserves_out"
+           "    JOIN reserves"
+           "      USING (reserve_uuid)"
+           "    JOIN denominations denom"
+           "      USING (denominations_serial)"
+           " WHERE h_blind_ev=$1;");
+  return GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
+                                                   "get_withdraw_info",
+                                                   params,
+                                                   rs);
+}
diff --git a/src/exchangedb/pg_get_withdraw_info.h 
b/src/exchangedb/pg_get_withdraw_info.h
new file mode 100644
index 00000000..7c3e06a0
--- /dev/null
+++ b/src/exchangedb/pg_get_withdraw_info.h
@@ -0,0 +1,43 @@
+/*
+   This file is part of TALER
+   Copyright (C) 2022 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 exchangedb/pg_get_withdraw_info.h
+ * @brief implementation of the get_withdraw_info function for Postgres
+ * @author Christian Grothoff
+ */
+#ifndef PG_GET_WITHDRAW_INFO_H
+#define PG_GET_WITHDRAW_INFO_H
+
+#include "taler_util.h"
+#include "taler_json_lib.h"
+#include "taler_exchangedb_plugin.h"
+/**
+ * Locate the response for a /reserve/withdraw request under the
+ * key of the hash of the blinded message.
+ *
+ * @param cls the `struct PostgresClosure` with the plugin-specific state
+ * @param bch hash that uniquely identifies the withdraw operation
+ * @param collectable corresponding collectable coin (blind signature)
+ *                    if a coin is found
+ * @return statement execution status
+ */
+enum GNUNET_DB_QueryStatus
+TEH_PG_get_withdraw_info (
+  void *cls,
+  const struct TALER_BlindedCoinHashP *bch,
+  struct TALER_EXCHANGEDB_CollectableBlindcoin *collectable);
+
+#endif
diff --git a/src/exchangedb/pg_have_deposit2.c 
b/src/exchangedb/pg_have_deposit2.c
new file mode 100644
index 00000000..1616858c
--- /dev/null
+++ b/src/exchangedb/pg_have_deposit2.c
@@ -0,0 +1,120 @@
+/*
+   This file is part of TALER
+   Copyright (C) 2022 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 exchangedb/pg_have_deposit2.c
+ * @brief Implementation of the have_deposit2 function for Postgres
+ * @author Christian Grothoff
+ */
+#include "platform.h"
+#include "taler_error_codes.h"
+#include "taler_dbevents.h"
+#include "taler_pq_lib.h"
+#include "pg_have_deposit2.h"
+#include "pg_helper.h"
+
+
+enum GNUNET_DB_QueryStatus
+TEH_PG_have_deposit2 (
+  void *cls,
+  const struct TALER_PrivateContractHashP *h_contract_terms,
+  const struct TALER_MerchantWireHashP *h_wire,
+  const struct TALER_CoinSpendPublicKeyP *coin_pub,
+  const struct TALER_MerchantPublicKeyP *merchant,
+  struct GNUNET_TIME_Timestamp refund_deadline,
+  struct TALER_Amount *deposit_fee,
+  struct GNUNET_TIME_Timestamp *exchange_timestamp)
+{
+  struct PostgresClosure *pg = cls;
+  struct GNUNET_PQ_QueryParam params[] = {
+    GNUNET_PQ_query_param_auto_from_type (coin_pub),
+    GNUNET_PQ_query_param_auto_from_type (h_contract_terms),
+    GNUNET_PQ_query_param_auto_from_type (merchant),
+    GNUNET_PQ_query_param_end
+  };
+  struct TALER_EXCHANGEDB_Deposit deposit2;
+  struct GNUNET_PQ_ResultSpec rs[] = {
+    TALER_PQ_RESULT_SPEC_AMOUNT ("amount_with_fee",
+                                 &deposit2.amount_with_fee),
+    GNUNET_PQ_result_spec_timestamp ("wallet_timestamp",
+                                     &deposit2.timestamp),
+    GNUNET_PQ_result_spec_timestamp ("exchange_timestamp",
+                                     exchange_timestamp),
+    GNUNET_PQ_result_spec_timestamp ("refund_deadline",
+                                     &deposit2.refund_deadline),
+    GNUNET_PQ_result_spec_timestamp ("wire_deadline",
+                                     &deposit2.wire_deadline),
+    TALER_PQ_RESULT_SPEC_AMOUNT ("fee_deposit",
+                                 deposit_fee),
+    GNUNET_PQ_result_spec_auto_from_type ("wire_salt",
+                                          &deposit2.wire_salt),
+    GNUNET_PQ_result_spec_string ("receiver_wire_account",
+                                  &deposit2.receiver_wire_account),
+    GNUNET_PQ_result_spec_end
+  };
+  enum GNUNET_DB_QueryStatus qs;
+  struct TALER_MerchantWireHashP h_wire2;
+
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Getting deposits for coin %s\n",
+              TALER_B2S (coin_pub));
+
+    /* Fetch an existing deposit request, used to ensure idempotency
+       during /deposit processing. Used in #postgres_have_deposit(). */
+  PREPARE (pg,
+      "get_deposit",
+      "SELECT"
+      " dep.amount_with_fee_val"
+      ",dep.amount_with_fee_frac"
+      ",denominations.fee_deposit_val"
+      ",denominations.fee_deposit_frac"
+      ",dep.wallet_timestamp"
+      ",dep.exchange_timestamp"
+      ",dep.refund_deadline"
+      ",dep.wire_deadline"
+      ",dep.h_contract_terms"
+      ",dep.wire_salt"
+      ",wt.payto_uri AS receiver_wire_account"
+      " FROM deposits dep"
+      " JOIN known_coins kc ON (kc.coin_pub = dep.coin_pub)"
+      " JOIN denominations USING (denominations_serial)"
+      " JOIN wire_targets wt USING (wire_target_h_payto)"
+      " WHERE dep.coin_pub=$1"
+      "   AND dep.merchant_pub=$3"
+      "   AND dep.h_contract_terms=$2;");
+
+  qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
+                                                 "get_deposit",
+                                                 params,
+                                                 rs);
+  if (0 >= qs)
+    return qs;
+  TALER_merchant_wire_signature_hash (deposit2.receiver_wire_account,
+                                      &deposit2.wire_salt,
+                                      &h_wire2);
+  GNUNET_free (deposit2.receiver_wire_account);
+  /* Now we check that the other information in @a deposit
+     also matches, and if not report inconsistencies. */
+  if ( (GNUNET_TIME_timestamp_cmp (refund_deadline,
+                                   !=,
+                                   deposit2.refund_deadline)) ||
+       (0 != GNUNET_memcmp (h_wire,
+                            &h_wire2) ) )
+  {
+    /* Inconsistencies detected! Does not match! */
+    return GNUNET_DB_STATUS_SUCCESS_NO_RESULTS;
+  }
+  return GNUNET_DB_STATUS_SUCCESS_ONE_RESULT;
+}
diff --git a/src/exchangedb/pg_have_deposit2.h 
b/src/exchangedb/pg_have_deposit2.h
new file mode 100644
index 00000000..0e8119c2
--- /dev/null
+++ b/src/exchangedb/pg_have_deposit2.h
@@ -0,0 +1,53 @@
+/*
+   This file is part of TALER
+   Copyright (C) 2022 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 exchangedb/pg_have_deposit2.h
+ * @brief implementation of the have_deposit2 function for Postgres
+ * @author Christian Grothoff
+ */
+#ifndef PG_HAVE_DEPOSIT2_H
+#define PG_HAVE_DEPOSIT2_H
+
+#include "taler_util.h"
+#include "taler_json_lib.h"
+#include "taler_exchangedb_plugin.h"
+
+/**
+ * Check if we have the specified deposit already in the database.
+ *
+ * @param cls the `struct PostgresClosure` with the plugin-specific state
+ * @param h_contract_terms contract to check for
+ * @param h_wire wire hash to check for
+ * @param coin_pub public key of the coin to check for
+ * @param merchant merchant public key to check for
+ * @param refund_deadline expected refund deadline
+ * @param[out] deposit_fee set to the deposit fee the exchange charged
+ * @param[out] exchange_timestamp set to the time when the exchange received 
the deposit
+ * @return 1 if we know this operation,
+ *         0 if this exact deposit is unknown to us,
+ *         otherwise transaction error status
+ */
+enum GNUNET_DB_QueryStatus
+TEH_PG_have_deposit2 (
+  void *cls,
+  const struct TALER_PrivateContractHashP *h_contract_terms,
+  const struct TALER_MerchantWireHashP *h_wire,
+  const struct TALER_CoinSpendPublicKeyP *coin_pub,
+  const struct TALER_MerchantPublicKeyP *merchant,
+  struct GNUNET_TIME_Timestamp refund_deadline,
+  struct TALER_Amount *deposit_fee,
+  struct GNUNET_TIME_Timestamp *exchange_timestamp);
+#endif
diff --git a/src/exchangedb/pg_insert_auditor.c 
b/src/exchangedb/pg_insert_auditor.c
new file mode 100644
index 00000000..757dfa62
--- /dev/null
+++ b/src/exchangedb/pg_insert_auditor.c
@@ -0,0 +1,58 @@
+/*
+   This file is part of TALER
+   Copyright (C) 2022 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 exchangedb/pg_insert_auditor.c
+ * @brief Implementation of the insert_auditor function for Postgres
+ * @author Christian Grothoff
+ */
+#include "platform.h"
+#include "taler_error_codes.h"
+#include "taler_dbevents.h"
+#include "taler_pq_lib.h"
+#include "pg_insert_auditor.h"
+#include "pg_helper.h"
+
+enum GNUNET_DB_QueryStatus
+TEH_PG_insert_auditor (void *cls,
+                         const struct TALER_AuditorPublicKeyP *auditor_pub,
+                         const char *auditor_url,
+                         const char *auditor_name,
+                         struct GNUNET_TIME_Timestamp start_date)
+{
+  struct PostgresClosure *pg = cls;
+  struct GNUNET_PQ_QueryParam params[] = {
+    GNUNET_PQ_query_param_auto_from_type (auditor_pub),
+    GNUNET_PQ_query_param_string (auditor_name),
+    GNUNET_PQ_query_param_string (auditor_url),
+    GNUNET_PQ_query_param_timestamp (&start_date),
+    GNUNET_PQ_query_param_end
+  };
+
+      /* used in #postgres_insert_auditor() */
+  PREPARE (pg,
+           "insert_auditor",
+           "INSERT INTO auditors "
+           "(auditor_pub"
+           ",auditor_name"
+           ",auditor_url"
+           ",is_active"
+           ",last_change"
+           ") VALUES "
+           "($1, $2, $3, true, $4);");
+  return GNUNET_PQ_eval_prepared_non_select (pg->conn,
+                                             "insert_auditor",
+                                             params);
+}
diff --git a/src/exchangedb/pg_insert_auditor.h 
b/src/exchangedb/pg_insert_auditor.h
new file mode 100644
index 00000000..7523282e
--- /dev/null
+++ b/src/exchangedb/pg_insert_auditor.h
@@ -0,0 +1,45 @@
+/*
+   This file is part of TALER
+   Copyright (C) 2022 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 exchangedb/pg_insert_auditor.h
+ * @brief implementation of the insert_auditor function for Postgres
+ * @author Christian Grothoff
+ */
+#ifndef PG_INSERT_AUDITOR_H
+#define PG_INSERT_AUDITOR_H
+
+#include "taler_util.h"
+#include "taler_json_lib.h"
+#include "taler_exchangedb_plugin.h"
+
+/**
+ * Insert information about an auditor that will audit this exchange.
+ *
+ * @param cls closure
+ * @param auditor_pub key of the auditor
+ * @param auditor_url base URL of the auditor's REST service
+ * @param auditor_name name of the auditor (for humans)
+ * @param start_date date when the auditor was added by the offline system
+ *                      (only to be used for replay detection)
+ * @return transaction status code
+ */
+enum GNUNET_DB_QueryStatus
+TEH_PG_insert_auditor (void *cls,
+                         const struct TALER_AuditorPublicKeyP *auditor_pub,
+                         const char *auditor_url,
+                         const char *auditor_name,
+                       struct GNUNET_TIME_Timestamp start_date);
+#endif
diff --git a/src/exchangedb/pg_insert_auditor_denom_sig.c 
b/src/exchangedb/pg_insert_auditor_denom_sig.c
new file mode 100644
index 00000000..3643a87f
--- /dev/null
+++ b/src/exchangedb/pg_insert_auditor_denom_sig.c
@@ -0,0 +1,61 @@
+/*
+   This file is part of TALER
+   Copyright (C) 2022 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 exchangedb/pg_insert_auditor_denom_sig.c
+ * @brief Implementation of the insert_auditor_denom_sig function for Postgres
+ * @author Christian Grothoff
+ */
+#include "platform.h"
+#include "taler_error_codes.h"
+#include "taler_dbevents.h"
+#include "taler_pq_lib.h"
+#include "pg_insert_auditor_denom_sig.h"
+#include "pg_helper.h"
+
+
+enum GNUNET_DB_QueryStatus
+TEH_PG_insert_auditor_denom_sig (
+  void *cls,
+  const struct TALER_DenominationHashP *h_denom_pub,
+  const struct TALER_AuditorPublicKeyP *auditor_pub,
+  const struct TALER_AuditorSignatureP *auditor_sig)
+{
+  struct PostgresClosure *pg = cls;
+  struct GNUNET_PQ_QueryParam params[] = {
+    GNUNET_PQ_query_param_auto_from_type (auditor_pub),
+    GNUNET_PQ_query_param_auto_from_type (h_denom_pub),
+    GNUNET_PQ_query_param_auto_from_type (auditor_sig),
+    GNUNET_PQ_query_param_end
+  };
+
+  PREPARE (pg,
+           "insert_auditor_denom_sig",
+           "WITH ax AS"
+           " (SELECT auditor_uuid"
+           "    FROM auditors"
+           "   WHERE auditor_pub=$1)"
+           "INSERT INTO auditor_denom_sigs "
+           "(auditor_uuid"
+           ",denominations_serial"
+           ",auditor_sig"
+           ") SELECT ax.auditor_uuid, denominations_serial, $3 "
+           "    FROM denominations"
+           "   CROSS JOIN ax"
+           "   WHERE denom_pub_hash=$2;");
+  return GNUNET_PQ_eval_prepared_non_select (pg->conn,
+                                             "insert_auditor_denom_sig",
+                                             params);
+}
diff --git a/src/exchangedb/pg_insert_auditor_denom_sig.h 
b/src/exchangedb/pg_insert_auditor_denom_sig.h
new file mode 100644
index 00000000..baa67cfe
--- /dev/null
+++ b/src/exchangedb/pg_insert_auditor_denom_sig.h
@@ -0,0 +1,43 @@
+/*
+   This file is part of TALER
+   Copyright (C) 2022 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 exchangedb/pg_insert_auditor_denom_sig.h
+ * @brief implementation of the insert_auditor_denom_sig function for Postgres
+ * @author Christian Grothoff
+ */
+#ifndef PG_INSERT_AUDITOR_DENOM_SIG_H
+#define PG_INSERT_AUDITOR_DENOM_SIG_H
+
+#include "taler_util.h"
+#include "taler_json_lib.h"
+#include "taler_exchangedb_plugin.h"
+
+/**
+ * Insert information about an auditor auditing a denomination key.
+ *
+ * @param cls closure
+ * @param h_denom_pub the audited denomination
+ * @param auditor_pub the auditor's key
+ * @param auditor_sig signature affirming the auditor's audit activity
+ * @return transaction status code
+ */
+enum GNUNET_DB_QueryStatus
+TEH_PG_insert_auditor_denom_sig (
+  void *cls,
+  const struct TALER_DenominationHashP *h_denom_pub,
+  const struct TALER_AuditorPublicKeyP *auditor_pub,
+  const struct TALER_AuditorSignatureP *auditor_sig);
+#endif
diff --git a/src/exchangedb/pg_insert_denomination_revocation.c 
b/src/exchangedb/pg_insert_denomination_revocation.c
new file mode 100644
index 00000000..061d7adc
--- /dev/null
+++ b/src/exchangedb/pg_insert_denomination_revocation.c
@@ -0,0 +1,54 @@
+/*
+   This file is part of TALER
+   Copyright (C) 2022 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 exchangedb/pg_insert_denomination_revocation.c
+ * @brief Implementation of the insert_denomination_revocation function for 
Postgres
+ * @author Christian Grothoff
+ */
+#include "platform.h"
+#include "taler_error_codes.h"
+#include "taler_dbevents.h"
+#include "taler_pq_lib.h"
+#include "pg_insert_denomination_revocation.h"
+#include "pg_helper.h"
+
+
+enum GNUNET_DB_QueryStatus
+TEH_PG_insert_denomination_revocation (
+  void *cls,
+  const struct TALER_DenominationHashP *denom_pub_hash,
+  const struct TALER_MasterSignatureP *master_sig)
+{
+  struct PostgresClosure *pg = cls;
+  struct GNUNET_PQ_QueryParam params[] = {
+    GNUNET_PQ_query_param_auto_from_type (denom_pub_hash),
+    GNUNET_PQ_query_param_auto_from_type (master_sig),
+    GNUNET_PQ_query_param_end
+  };
+
+      /* Used in #postgres_insert_denomination_revocation() */
+  PREPARE (pg,
+           "denomination_revocation_insert",
+           "INSERT INTO denomination_revocations "
+           "(denominations_serial"
+           ",master_sig"
+           ") SELECT denominations_serial,$2"
+           "    FROM denominations"
+           "   WHERE denom_pub_hash=$1;");
+  return GNUNET_PQ_eval_prepared_non_select (pg->conn,
+                                             "denomination_revocation_insert",
+                                             params);
+}
diff --git a/src/exchangedb/pg_insert_denomination_revocation.h 
b/src/exchangedb/pg_insert_denomination_revocation.h
new file mode 100644
index 00000000..e3da8766
--- /dev/null
+++ b/src/exchangedb/pg_insert_denomination_revocation.h
@@ -0,0 +1,42 @@
+/*
+   This file is part of TALER
+   Copyright (C) 2022 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 exchangedb/pg_insert_denomination_revocation.h
+ * @brief implementation of the insert_denomination_revocation function for 
Postgres
+ * @author Christian Grothoff
+ */
+#ifndef PG_INSERT_DENOMINATION_REVOCATION_H
+#define PG_INSERT_DENOMINATION_REVOCATION_H
+
+#include "taler_util.h"
+#include "taler_json_lib.h"
+#include "taler_exchangedb_plugin.h"
+
+/**
+ * Store information that a denomination key was revoked
+ * in the database.
+ *
+ * @param cls closure
+ * @param denom_pub_hash hash of the revoked denomination key
+ * @param master_sig signature affirming the revocation
+ * @return transaction status code
+ */
+enum GNUNET_DB_QueryStatus
+TEH_PG_insert_denomination_revocation (
+  void *cls,
+  const struct TALER_DenominationHashP *denom_pub_hash,
+  const struct TALER_MasterSignatureP *master_sig);
+#endif
diff --git a/src/exchangedb/pg_insert_deposit.c 
b/src/exchangedb/pg_insert_deposit.c
new file mode 100644
index 00000000..09247e28
--- /dev/null
+++ b/src/exchangedb/pg_insert_deposit.c
@@ -0,0 +1,104 @@
+/*
+   This file is part of TALER
+   Copyright (C) 2022 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 exchangedb/pg_insert_deposit.c
+ * @brief Implementation of the insert_deposit function for Postgres
+ * @author Christian Grothoff
+ */
+#include "platform.h"
+#include "taler_error_codes.h"
+#include "taler_dbevents.h"
+#include "taler_pq_lib.h"
+#include "pg_insert_deposit.h"
+#include "pg_helper.h"
+#include "pg_setup_wire_target.h"
+#include "pg_compute_shard.h"
+enum GNUNET_DB_QueryStatus
+TEH_PG_insert_deposit (void *cls,
+                         struct GNUNET_TIME_Timestamp exchange_timestamp,
+                         const struct TALER_EXCHANGEDB_Deposit *deposit)
+{
+  struct PostgresClosure *pg = cls;
+  struct TALER_PaytoHashP h_payto;
+  enum GNUNET_DB_QueryStatus qs;
+
+  qs = TEH_PG_setup_wire_target (pg,
+                          deposit->receiver_wire_account,
+                          &h_payto);
+  if (qs < 0)
+    return qs;
+  if (GNUNET_TIME_timestamp_cmp (deposit->wire_deadline,
+                                 <,
+                                 deposit->refund_deadline))
+  {
+    GNUNET_break (0);
+  }
+  {
+    uint64_t shard = TEH_PG_compute_shard (&deposit->merchant_pub);
+    struct GNUNET_PQ_QueryParam params[] = {
+      GNUNET_PQ_query_param_auto_from_type (&deposit->coin.coin_pub),
+      TALER_PQ_query_param_amount (&deposit->amount_with_fee),
+      GNUNET_PQ_query_param_timestamp (&deposit->timestamp),
+      GNUNET_PQ_query_param_timestamp (&deposit->refund_deadline),
+      GNUNET_PQ_query_param_timestamp (&deposit->wire_deadline),
+      GNUNET_PQ_query_param_auto_from_type (&deposit->merchant_pub),
+      GNUNET_PQ_query_param_auto_from_type (&deposit->h_contract_terms),
+      GNUNET_PQ_query_param_auto_from_type (&deposit->wire_salt),
+      GNUNET_PQ_query_param_auto_from_type (&h_payto),
+      GNUNET_PQ_query_param_auto_from_type (&deposit->csig),
+      GNUNET_PQ_query_param_timestamp (&exchange_timestamp),
+      GNUNET_PQ_query_param_uint64 (&shard),
+      GNUNET_PQ_query_param_end
+    };
+
+    GNUNET_assert (shard <= INT32_MAX);
+    GNUNET_log (
+      GNUNET_ERROR_TYPE_INFO,
+      "Inserting deposit to be executed at %s (%llu/%llu)\n",
+      GNUNET_TIME_timestamp2s (deposit->wire_deadline),
+      (unsigned long long) deposit->wire_deadline.abs_time.abs_value_us,
+      (unsigned long long) deposit->refund_deadline.abs_time.abs_value_us);
+    /* Store information about a /deposit the exchange is to execute.
+       Used in #postgres_insert_deposit().  Only used in test cases. */
+    PREPARE (pg,
+             "insert_deposit",
+             "INSERT INTO deposits "
+             "(known_coin_id"
+             ",coin_pub"
+             ",amount_with_fee_val"
+             ",amount_with_fee_frac"
+             ",wallet_timestamp"
+             ",refund_deadline"
+             ",wire_deadline"
+             ",merchant_pub"
+             ",h_contract_terms"
+             ",wire_salt"
+             ",wire_target_h_payto"
+             ",coin_sig"
+             ",exchange_timestamp"
+             ",shard"
+             ") SELECT known_coin_id, $1, $2, $3, $4, $5, $6, "
+             " $7, $8, $9, $10, $11, $12, $13"
+             "    FROM known_coins"
+             "   WHERE coin_pub=$1"
+             " ON CONFLICT DO NOTHING;");
+
+
+    return GNUNET_PQ_eval_prepared_non_select (pg->conn,
+                                               "insert_deposit",
+                                               params);
+  }
+}
diff --git a/src/exchangedb/pg_insert_deposit.h 
b/src/exchangedb/pg_insert_deposit.h
new file mode 100644
index 00000000..15de39ef
--- /dev/null
+++ b/src/exchangedb/pg_insert_deposit.h
@@ -0,0 +1,40 @@
+/*
+   This file is part of TALER
+   Copyright (C) 2022 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 exchangedb/pg_insert_deposit.h
+ * @brief implementation of the insert_deposit function for Postgres
+ * @author Christian Grothoff
+ */
+#ifndef PG_INSERT_DEPOSIT_H
+#define PG_INSERT_DEPOSIT_H
+
+#include "taler_util.h"
+#include "taler_json_lib.h"
+#include "taler_exchangedb_plugin.h"
+/**
+ * Insert information about deposited coin into the database.
+ *
+ * @param cls the `struct PostgresClosure` with the plugin-specific state
+ * @param exchange_timestamp time the exchange received the deposit request
+ * @param deposit deposit information to store
+ * @return query result status
+ */
+enum GNUNET_DB_QueryStatus
+TEH_PG_insert_deposit (void *cls,
+                         struct GNUNET_TIME_Timestamp exchange_timestamp,
+                       const struct TALER_EXCHANGEDB_Deposit *deposit);
+
+#endif
diff --git a/src/exchangedb/pg_insert_global_fee.c 
b/src/exchangedb/pg_insert_global_fee.c
new file mode 100644
index 00000000..c08fc23b
--- /dev/null
+++ b/src/exchangedb/pg_insert_global_fee.c
@@ -0,0 +1,137 @@
+/*
+   This file is part of TALER
+   Copyright (C) 2022 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 exchangedb/pg_insert_global_fee.c
+ * @brief Implementation of the insert_global_fee function for Postgres
+ * @author Christian Grothoff
+ */
+#include "platform.h"
+#include "taler_error_codes.h"
+#include "taler_dbevents.h"
+#include "taler_pq_lib.h"
+#include "pg_insert_global_fee.h"
+#include "pg_helper.h"
+#include "pg_get_global_fee.h"
+
+enum GNUNET_DB_QueryStatus
+TEH_PG_insert_global_fee (void *cls,
+                            struct GNUNET_TIME_Timestamp start_date,
+                            struct GNUNET_TIME_Timestamp end_date,
+                            const struct TALER_GlobalFeeSet *fees,
+                            struct GNUNET_TIME_Relative purse_timeout,
+                            struct GNUNET_TIME_Relative history_expiration,
+                            uint32_t purse_account_limit,
+                            const struct TALER_MasterSignatureP *master_sig)
+{
+  struct PostgresClosure *pg = cls;
+  struct GNUNET_PQ_QueryParam params[] = {
+    GNUNET_PQ_query_param_timestamp (&start_date),
+    GNUNET_PQ_query_param_timestamp (&end_date),
+    TALER_PQ_query_param_amount (&fees->history),
+    TALER_PQ_query_param_amount (&fees->account),
+    TALER_PQ_query_param_amount (&fees->purse),
+    GNUNET_PQ_query_param_relative_time (&purse_timeout),
+    GNUNET_PQ_query_param_relative_time (&history_expiration),
+    GNUNET_PQ_query_param_uint32 (&purse_account_limit),
+    GNUNET_PQ_query_param_auto_from_type (master_sig),
+    GNUNET_PQ_query_param_end
+  };
+  struct TALER_GlobalFeeSet wx;
+  struct TALER_MasterSignatureP sig;
+  struct GNUNET_TIME_Timestamp sd;
+  struct GNUNET_TIME_Timestamp ed;
+  enum GNUNET_DB_QueryStatus qs;
+  struct GNUNET_TIME_Relative pt;
+  struct GNUNET_TIME_Relative he;
+  uint32_t pal;
+
+  qs = TEH_PG_get_global_fee (pg,
+                                start_date,
+                                &sd,
+                                &ed,
+                                &wx,
+                                &pt,
+                                &he,
+                                &pal,
+                                &sig);
+  if (qs < 0)
+    return qs;
+  if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT == qs)
+  {
+    if (0 != GNUNET_memcmp (&sig,
+                            master_sig))
+    {
+      GNUNET_break (0);
+      return GNUNET_DB_STATUS_HARD_ERROR;
+    }
+    if (0 !=
+        TALER_global_fee_set_cmp (fees,
+                                  &wx))
+    {
+      GNUNET_break (0);
+      return GNUNET_DB_STATUS_HARD_ERROR;
+    }
+    if ( (GNUNET_TIME_timestamp_cmp (sd,
+                                     !=,
+                                     start_date)) ||
+         (GNUNET_TIME_timestamp_cmp (ed,
+                                     !=,
+                                     end_date)) )
+    {
+      GNUNET_break (0);
+      return GNUNET_DB_STATUS_HARD_ERROR;
+    }
+    if ( (GNUNET_TIME_relative_cmp (purse_timeout,
+                                    !=,
+                                    pt)) ||
+         (GNUNET_TIME_relative_cmp (history_expiration,
+                                    !=,
+                                    he)) )
+    {
+      GNUNET_break (0);
+      return GNUNET_DB_STATUS_HARD_ERROR;
+    }
+    if (purse_account_limit != pal)
+    {
+      GNUNET_break (0);
+      return GNUNET_DB_STATUS_HARD_ERROR;
+    }
+    /* equal record already exists */
+    return GNUNET_DB_STATUS_SUCCESS_NO_RESULTS;
+  }
+
+      /* Used in #postgres_insert_global_fee */
+  PREPARE (pg,
+           "insert_global_fee",
+           "INSERT INTO global_fee "
+           "(start_date"
+           ",end_date"
+           ",history_fee_val"
+           ",history_fee_frac"
+           ",account_fee_val"
+           ",account_fee_frac"
+           ",purse_fee_val"
+           ",purse_fee_frac"
+           ",purse_timeout"
+           ",history_expiration"
+           ",purse_account_limit"
+           ",master_sig"
+           ") VALUES "
+           "($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12);");
+  return GNUNET_PQ_eval_prepared_non_select (pg->conn,
+                                             "insert_global_fee",
+                                             params);
+}
diff --git a/src/exchangedb/pg_insert_global_fee.h 
b/src/exchangedb/pg_insert_global_fee.h
new file mode 100644
index 00000000..9780d532
--- /dev/null
+++ b/src/exchangedb/pg_insert_global_fee.h
@@ -0,0 +1,50 @@
+/*
+   This file is part of TALER
+   Copyright (C) 2022 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 exchangedb/pg_insert_global_fee.h
+ * @brief implementation of the insert_global_fee function for Postgres
+ * @author Christian Grothoff
+ */
+#ifndef PG_INSERT_GLOBAL_FEE_H
+#define PG_INSERT_GLOBAL_FEE_H
+
+#include "taler_util.h"
+#include "taler_json_lib.h"
+#include "taler_exchangedb_plugin.h"
+
+/**
+ * Insert global fee data into database.
+ *
+ * @param cls closure
+ * @param start_date when does the fees go into effect
+ * @param end_date when does the fees end being valid
+ * @param fees how high is are the global fees
+ * @param purse_timeout when do purses time out
+ * @param history_expiration how long are account histories preserved
+ * @param purse_account_limit how many purses are free per account
+ * @param master_sig signature over the above by the exchange master key
+ * @return transaction status code
+ */
+enum GNUNET_DB_QueryStatus
+TEH_PG_insert_global_fee (void *cls,
+                            struct GNUNET_TIME_Timestamp start_date,
+                            struct GNUNET_TIME_Timestamp end_date,
+                            const struct TALER_GlobalFeeSet *fees,
+                            struct GNUNET_TIME_Relative purse_timeout,
+                            struct GNUNET_TIME_Relative history_expiration,
+                            uint32_t purse_account_limit,
+                          const struct TALER_MasterSignatureP *master_sig);
+#endif
diff --git a/src/exchangedb/pg_insert_partner.c 
b/src/exchangedb/pg_insert_partner.c
new file mode 100644
index 00000000..567f3776
--- /dev/null
+++ b/src/exchangedb/pg_insert_partner.c
@@ -0,0 +1,70 @@
+/*
+   This file is part of TALER
+   Copyright (C) 2022 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 exchangedb/pg_insert_partner.c
+ * @brief Implementation of the insert_partner function for Postgres
+ * @author Christian Grothoff
+ */
+#include "platform.h"
+#include "taler_error_codes.h"
+#include "taler_dbevents.h"
+#include "taler_pq_lib.h"
+#include "pg_insert_partner.h"
+#include "pg_helper.h"
+
+
+enum GNUNET_DB_QueryStatus
+TEH_PG_insert_partner (void *cls,
+                         const struct TALER_MasterPublicKeyP *master_pub,
+                         struct GNUNET_TIME_Timestamp start_date,
+                         struct GNUNET_TIME_Timestamp end_date,
+                         struct GNUNET_TIME_Relative wad_frequency,
+                         const struct TALER_Amount *wad_fee,
+                         const char *partner_base_url,
+                         const struct TALER_MasterSignatureP *master_sig)
+{
+  struct PostgresClosure *pg = cls;
+  struct GNUNET_PQ_QueryParam params[] = {
+    GNUNET_PQ_query_param_auto_from_type (master_pub),
+    GNUNET_PQ_query_param_timestamp (&start_date),
+    GNUNET_PQ_query_param_timestamp (&end_date),
+    GNUNET_PQ_query_param_relative_time (&wad_frequency),
+    TALER_PQ_query_param_amount (wad_fee),
+    GNUNET_PQ_query_param_auto_from_type (master_sig),
+    GNUNET_PQ_query_param_string (partner_base_url),
+    GNUNET_PQ_query_param_end
+  };
+
+
+  PREPARE (pg,
+           "insert_partner",
+           "INSERT INTO partners"
+           "  (partner_master_pub"
+           "  ,start_date"
+           "  ,end_date"
+           "  ,wad_frequency"
+           "  ,wad_fee_val"
+           "  ,wad_fee_frac"
+           "  ,master_sig"
+           "  ,partner_base_url"
+           "  ) VALUES "
+           "  ($1, $2, $3, $4, $5, $6, $7, $8);");
+  return GNUNET_PQ_eval_prepared_non_select (pg->conn,
+                                             "insert_partner",
+                                             params);
+}
+
+
diff --git a/src/exchangedb/pg_insert_partner.h 
b/src/exchangedb/pg_insert_partner.h
new file mode 100644
index 00000000..eed40a80
--- /dev/null
+++ b/src/exchangedb/pg_insert_partner.h
@@ -0,0 +1,51 @@
+/*
+   This file is part of TALER
+   Copyright (C) 2022 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 exchangedb/pg_insert_partner.h
+ * @brief implementation of the insert_partner function for Postgres
+ * @author Christian Grothoff
+ */
+#ifndef PG_INSERT_PARTNER_H
+#define PG_INSERT_PARTNER_H
+
+#include "taler_util.h"
+#include "taler_json_lib.h"
+#include "taler_exchangedb_plugin.h"
+/**
+ * Function called to store configuration data about a partner
+ * exchange that we are federated with.
+ *
+ * @param cls the @e cls of this struct with the plugin-specific state
+ * @param master_pub public offline signing key of the partner exchange
+ * @param start_date when does the following data start to be valid
+ * @param end_date when does the validity end (exclusive)
+ * @param wad_frequency how often do we do exchange-to-exchange settlements?
+ * @param wad_fee how much do we charge for transfers to the partner
+ * @param partner_base_url base URL of the partner exchange
+ * @param master_sig signature with our offline signing key affirming the above
+ * @return transaction status code
+ */
+enum GNUNET_DB_QueryStatus
+TEH_PG_insert_partner (void *cls,
+                         const struct TALER_MasterPublicKeyP *master_pub,
+                         struct GNUNET_TIME_Timestamp start_date,
+                         struct GNUNET_TIME_Timestamp end_date,
+                         struct GNUNET_TIME_Relative wad_frequency,
+                         const struct TALER_Amount *wad_fee,
+                         const char *partner_base_url,
+                       const struct TALER_MasterSignatureP *master_sig);
+
+#endif
diff --git a/src/exchangedb/pg_insert_refresh_reveal.c 
b/src/exchangedb/pg_insert_refresh_reveal.c
new file mode 100644
index 00000000..098a3aed
--- /dev/null
+++ b/src/exchangedb/pg_insert_refresh_reveal.c
@@ -0,0 +1,94 @@
+/*
+   This file is part of TALER
+   Copyright (C) 2022 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 exchangedb/pg_insert_refresh_reveal.c
+ * @brief Implementation of the insert_refresh_reveal function for Postgres
+ * @author Christian Grothoff
+ */
+#include "platform.h"
+#include "taler_error_codes.h"
+#include "taler_dbevents.h"
+#include "taler_pq_lib.h"
+#include "pg_insert_refresh_reveal.h"
+#include "pg_helper.h"
+
+
+enum GNUNET_DB_QueryStatus
+TEH_PG_insert_refresh_reveal (
+  void *cls,
+  uint64_t melt_serial_id,
+  uint32_t num_rrcs,
+  const struct TALER_EXCHANGEDB_RefreshRevealedCoin *rrcs,
+  unsigned int num_tprivs,
+  const struct TALER_TransferPrivateKeyP *tprivs,
+  const struct TALER_TransferPublicKeyP *tp)
+{
+  struct PostgresClosure *pg = cls;
+
+  if (TALER_CNC_KAPPA != num_tprivs + 1)
+  {
+    GNUNET_break (0);
+    return GNUNET_DB_STATUS_HARD_ERROR;
+  }
+  for (uint32_t i = 0; i<num_rrcs; i++)
+  {
+    const struct TALER_EXCHANGEDB_RefreshRevealedCoin *rrc = &rrcs[i];
+    struct GNUNET_PQ_QueryParam params[] = {
+      GNUNET_PQ_query_param_uint64 (&melt_serial_id),
+      GNUNET_PQ_query_param_uint32 (&i),
+      GNUNET_PQ_query_param_auto_from_type (&rrc->orig_coin_link_sig),
+      GNUNET_PQ_query_param_auto_from_type (&rrc->h_denom_pub),
+      TALER_PQ_query_param_blinded_planchet (&rrc->blinded_planchet),
+      TALER_PQ_query_param_exchange_withdraw_values (&rrc->exchange_vals),
+      GNUNET_PQ_query_param_auto_from_type (&rrc->coin_envelope_hash),
+      TALER_PQ_query_param_blinded_denom_sig (&rrc->coin_sig),
+      GNUNET_PQ_query_param_end
+    };
+    enum GNUNET_DB_QueryStatus qs;
+
+    qs = GNUNET_PQ_eval_prepared_non_select (pg->conn,
+                                             "insert_refresh_revealed_coin",
+                                             params);
+    if (0 > qs)
+      return qs;
+  }
+
+  {
+    struct GNUNET_PQ_QueryParam params[] = {
+      GNUNET_PQ_query_param_uint64 (&melt_serial_id),
+      GNUNET_PQ_query_param_auto_from_type (tp),
+      GNUNET_PQ_query_param_fixed_size (
+        tprivs,
+        num_tprivs * sizeof (struct TALER_TransferPrivateKeyP)),
+      GNUNET_PQ_query_param_end
+    };
+
+        /* Used in #postgres_insert_refresh_reveal() to store the transfer
+       keys we learned */
+    PREPARE (pg,
+      "insert_refresh_transfer_keys",
+      "INSERT INTO refresh_transfer_keys "
+      "(melt_serial_id"
+      ",transfer_pub"
+      ",transfer_privs"
+      ") VALUES ($1, $2, $3)"
+      " ON CONFLICT DO NOTHING;");
+
+    return GNUNET_PQ_eval_prepared_non_select (pg->conn,
+                                               "insert_refresh_transfer_keys",
+                                               params);
+  }
+}
diff --git a/src/exchangedb/pg_insert_refresh_reveal.h 
b/src/exchangedb/pg_insert_refresh_reveal.h
new file mode 100644
index 00000000..ad53ab19
--- /dev/null
+++ b/src/exchangedb/pg_insert_refresh_reveal.h
@@ -0,0 +1,51 @@
+/*
+   This file is part of TALER
+   Copyright (C) 2022 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 exchangedb/pg_insert_refresh_reveal.h
+ * @brief implementation of the insert_refresh_reveal function for Postgres
+ * @author Christian Grothoff
+ */
+#ifndef PG_INSERT_REFRESH_REVEAL_H
+#define PG_INSERT_REFRESH_REVEAL_H
+
+#include "taler_util.h"
+#include "taler_json_lib.h"
+#include "taler_exchangedb_plugin.h"
+/**
+ * Store in the database which coin(s) the wallet wanted to create
+ * in a given refresh operation and all of the other information
+ * we learned or created in the /refresh/reveal step.
+ *
+ * @param cls the @e cls of this struct with the plugin-specific state
+ * @param melt_serial_id row ID of the commitment / melt operation in 
refresh_commitments
+ * @param num_rrcs number of coins to generate, size of the @a rrcs array
+ * @param rrcs information about the new coins
+ * @param num_tprivs number of entries in @a tprivs, should be 
#TALER_CNC_KAPPA - 1
+ * @param tprivs transfer private keys to store
+ * @param tp public key to store
+ * @return query status for the transaction
+ */
+enum GNUNET_DB_QueryStatus
+TEH_PG_insert_refresh_reveal (
+  void *cls,
+  uint64_t melt_serial_id,
+  uint32_t num_rrcs,
+  const struct TALER_EXCHANGEDB_RefreshRevealedCoin *rrcs,
+  unsigned int num_tprivs,
+  const struct TALER_TransferPrivateKeyP *tprivs,
+  const struct TALER_TransferPublicKeyP *tp);
+
+#endif
diff --git a/src/exchangedb/pg_insert_refund.c 
b/src/exchangedb/pg_insert_refund.c
new file mode 100644
index 00000000..047df033
--- /dev/null
+++ b/src/exchangedb/pg_insert_refund.c
@@ -0,0 +1,66 @@
+/*
+   This file is part of TALER
+   Copyright (C) 2022 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 exchangedb/pg_insert_refund.c
+ * @brief Implementation of the insert_refund function for Postgres
+ * @author Christian Grothoff
+ */
+#include "platform.h"
+#include "taler_error_codes.h"
+#include "taler_dbevents.h"
+#include "taler_pq_lib.h"
+#include "pg_insert_refund.h"
+#include "pg_helper.h"
+
+
+enum GNUNET_DB_QueryStatus
+TEH_PG_insert_refund (void *cls,
+                        const struct TALER_EXCHANGEDB_Refund *refund)
+{
+  struct PostgresClosure *pg = cls;
+  struct GNUNET_PQ_QueryParam params[] = {
+    GNUNET_PQ_query_param_auto_from_type (&refund->coin.coin_pub),
+    GNUNET_PQ_query_param_auto_from_type (&refund->details.merchant_pub),
+    GNUNET_PQ_query_param_auto_from_type (&refund->details.merchant_sig),
+    GNUNET_PQ_query_param_auto_from_type (&refund->details.h_contract_terms),
+    GNUNET_PQ_query_param_uint64 (&refund->details.rtransaction_id),
+    TALER_PQ_query_param_amount (&refund->details.refund_amount),
+    GNUNET_PQ_query_param_end
+  };
+
+  GNUNET_assert (GNUNET_YES ==
+                 TALER_amount_cmp_currency (&refund->details.refund_amount,
+                                            &refund->details.refund_fee));
+
+    /* Used in #postgres_insert_refund() to store refund information */
+  PREPARE (pg,
+           "insert_refund",
+           "INSERT INTO refunds "
+           "(coin_pub "
+           ",deposit_serial_id"
+           ",merchant_sig "
+           ",rtransaction_id "
+           ",amount_with_fee_val "
+           ",amount_with_fee_frac "
+           ") SELECT $1, deposit_serial_id, $3, $5, $6, $7"
+           "    FROM deposits"
+           "   WHERE coin_pub=$1"
+           "     AND h_contract_terms=$4"
+           "     AND merchant_pub=$2");
+  return GNUNET_PQ_eval_prepared_non_select (pg->conn,
+                                             "insert_refund",
+                                             params);
+}
diff --git a/src/exchangedb/pg_insert_refund.h 
b/src/exchangedb/pg_insert_refund.h
new file mode 100644
index 00000000..02190bcc
--- /dev/null
+++ b/src/exchangedb/pg_insert_refund.h
@@ -0,0 +1,38 @@
+/*
+   This file is part of TALER
+   Copyright (C) 2022 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 exchangedb/pg_insert_refund.h
+ * @brief implementation of the insert_refund function for Postgres
+ * @author Christian Grothoff
+ */
+#ifndef PG_INSERT_REFUND_H
+#define PG_INSERT_REFUND_H
+
+#include "taler_util.h"
+#include "taler_json_lib.h"
+#include "taler_exchangedb_plugin.h"
+/**
+ * Insert information about refunded coin into the database.
+ *
+ * @param cls the @e cls of this struct with the plugin-specific state
+ * @param refund refund information to store
+ * @return query result status
+ */
+enum GNUNET_DB_QueryStatus
+TEH_PG_insert_refund (void *cls,
+                      const struct TALER_EXCHANGEDB_Refund *refund);
+
+#endif
diff --git a/src/exchangedb/pg_insert_reserve_closed.c 
b/src/exchangedb/pg_insert_reserve_closed.c
new file mode 100644
index 00000000..d17c37ed
--- /dev/null
+++ b/src/exchangedb/pg_insert_reserve_closed.c
@@ -0,0 +1,114 @@
+/*
+   This file is part of TALER
+   Copyright (C) 2022 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 exchangedb/pg_insert_reserve_closed.c
+ * @brief Implementation of the insert_reserve_closed function for Postgres
+ * @author Christian Grothoff
+ */
+#include "platform.h"
+#include "taler_error_codes.h"
+#include "taler_dbevents.h"
+#include "taler_pq_lib.h"
+#include "pg_insert_reserve_closed.h"
+#include "pg_helper.h"
+#include "pg_reserves_get.h"
+#include "pg_reserves_update.h"
+
+enum GNUNET_DB_QueryStatus
+TEH_PG_insert_reserve_closed (
+  void *cls,
+  const struct TALER_ReservePublicKeyP *reserve_pub,
+  struct GNUNET_TIME_Timestamp execution_date,
+  const char *receiver_account,
+  const struct TALER_WireTransferIdentifierRawP *wtid,
+  const struct TALER_Amount *amount_with_fee,
+  const struct TALER_Amount *closing_fee,
+  uint64_t close_request_row)
+{
+  struct PostgresClosure *pg = cls;
+  struct TALER_EXCHANGEDB_Reserve reserve;
+  enum GNUNET_DB_QueryStatus qs;
+  struct TALER_PaytoHashP h_payto;
+
+  TALER_payto_hash (receiver_account,
+                    &h_payto);
+  {
+    struct GNUNET_PQ_QueryParam params[] = {
+      GNUNET_PQ_query_param_auto_from_type (reserve_pub),
+      GNUNET_PQ_query_param_timestamp (&execution_date),
+      GNUNET_PQ_query_param_auto_from_type (wtid),
+      GNUNET_PQ_query_param_auto_from_type (&h_payto),
+      TALER_PQ_query_param_amount (amount_with_fee),
+      TALER_PQ_query_param_amount (closing_fee),
+      GNUNET_PQ_query_param_uint64 (&close_request_row),
+      GNUNET_PQ_query_param_end
+    };
+
+        /* Used in #postgres_insert_reserve_closed() */
+    PREPARE (pg,
+      "reserves_close_insert",
+      "INSERT INTO reserves_close "
+      "(reserve_pub"
+      ",execution_date"
+      ",wtid"
+      ",wire_target_h_payto"
+      ",amount_val"
+      ",amount_frac"
+      ",closing_fee_val"
+      ",closing_fee_frac"
+      ",close_request_row"
+      ") VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9);");
+
+    qs = GNUNET_PQ_eval_prepared_non_select (pg->conn,
+                                             "reserves_close_insert",
+                                             params);
+  }
+  if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != qs)
+    return qs;
+
+  /* update reserve balance */
+  reserve.pub = *reserve_pub;
+  if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
+      (qs = TEH_PG_reserves_get (cls,
+                                   &reserve)))
+  {
+    /* Existence should have been checked before we got here... */
+    GNUNET_break (GNUNET_DB_STATUS_SOFT_ERROR == qs);
+    if (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS == qs)
+      qs = GNUNET_DB_STATUS_HARD_ERROR;
+    return qs;
+  }
+  {
+    enum TALER_AmountArithmeticResult ret;
+
+    ret = TALER_amount_subtract (&reserve.balance,
+                                 &reserve.balance,
+                                 amount_with_fee);
+    if (ret < 0)
+    {
+      /* The reserve history was checked to make sure there is enough of a 
balance
+         left before we tried this; however, concurrent operations may have 
changed
+         the situation by now.  We should re-try the transaction.  */
+      GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                  "Closing of reserve `%s' refused due to balance mismatch. 
Retrying.\n",
+                  TALER_B2S (reserve_pub));
+      return GNUNET_DB_STATUS_HARD_ERROR;
+    }
+    GNUNET_break (TALER_AAR_RESULT_ZERO == ret);
+  }
+  return TEH_PG_reserves_update (cls,
+                          &reserve);
+}
diff --git a/src/exchangedb/pg_insert_reserve_closed.h 
b/src/exchangedb/pg_insert_reserve_closed.h
new file mode 100644
index 00000000..2ac1a6e3
--- /dev/null
+++ b/src/exchangedb/pg_insert_reserve_closed.h
@@ -0,0 +1,51 @@
+/*
+   This file is part of TALER
+   Copyright (C) 2022 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 exchangedb/pg_insert_reserve_closed.h
+ * @brief implementation of the insert_reserve_closed function for Postgres
+ * @author Christian Grothoff
+ */
+#ifndef PG_INSERT_RESERVE_CLOSED_H
+#define PG_INSERT_RESERVE_CLOSED_H
+
+#include "taler_util.h"
+#include "taler_json_lib.h"
+#include "taler_exchangedb_plugin.h"
+/**
+ * Insert reserve close operation into database.
+ *
+ * @param cls closure
+ * @param reserve_pub which reserve is this about?
+ * @param execution_date when did we perform the transfer?
+ * @param receiver_account to which account do we transfer?
+ * @param wtid wire transfer details
+ * @param amount_with_fee amount we charged to the reserve
+ * @param closing_fee how high is the closing fee
+ * @param close_request_row identifies explicit close request, 0 for none
+ * @return transaction status code
+ */
+enum GNUNET_DB_QueryStatus
+TEH_PG_insert_reserve_closed (
+  void *cls,
+  const struct TALER_ReservePublicKeyP *reserve_pub,
+  struct GNUNET_TIME_Timestamp execution_date,
+  const char *receiver_account,
+  const struct TALER_WireTransferIdentifierRawP *wtid,
+  const struct TALER_Amount *amount_with_fee,
+  const struct TALER_Amount *closing_fee,
+  uint64_t close_request_row);
+
+#endif
diff --git a/src/exchangedb/pg_insert_signkey_revocation.c 
b/src/exchangedb/pg_insert_signkey_revocation.c
new file mode 100644
index 00000000..9197be6a
--- /dev/null
+++ b/src/exchangedb/pg_insert_signkey_revocation.c
@@ -0,0 +1,53 @@
+/*
+   This file is part of TALER
+   Copyright (C) 2022 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 exchangedb/pg_insert_signkey_revocation.c
+ * @brief Implementation of the insert_signkey_revocation function for Postgres
+ * @author Christian Grothoff
+ */
+#include "platform.h"
+#include "taler_error_codes.h"
+#include "taler_dbevents.h"
+#include "taler_pq_lib.h"
+#include "pg_insert_signkey_revocation.h"
+#include "pg_helper.h"
+
+enum GNUNET_DB_QueryStatus
+TEH_PG_insert_signkey_revocation (
+  void *cls,
+  const struct TALER_ExchangePublicKeyP *exchange_pub,
+  const struct TALER_MasterSignatureP *master_sig)
+{
+  struct PostgresClosure *pg = cls;
+  struct GNUNET_PQ_QueryParam params[] = {
+    GNUNET_PQ_query_param_auto_from_type (exchange_pub),
+    GNUNET_PQ_query_param_auto_from_type (master_sig),
+    GNUNET_PQ_query_param_end
+  };
+
+
+  PREPARE (pg,
+           "insert_signkey_revocation",
+           "INSERT INTO signkey_revocations "
+           "(esk_serial"
+           ",master_sig"
+           ") SELECT esk_serial, $2 "
+           "    FROM exchange_sign_keys"
+           "   WHERE exchange_pub=$1;");
+  return GNUNET_PQ_eval_prepared_non_select (pg->conn,
+                                             "insert_signkey_revocation",
+                                             params);
+}
diff --git a/src/exchangedb/pg_insert_signkey_revocation.h 
b/src/exchangedb/pg_insert_signkey_revocation.h
new file mode 100644
index 00000000..534e6d45
--- /dev/null
+++ b/src/exchangedb/pg_insert_signkey_revocation.h
@@ -0,0 +1,41 @@
+/*
+   This file is part of TALER
+   Copyright (C) 2022 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 exchangedb/pg_insert_signkey_revocation.h
+ * @brief implementation of the insert_signkey_revocation function for Postgres
+ * @author Christian Grothoff
+ */
+#ifndef PG_INSERT_SIGNKEY_REVOCATION_H
+#define PG_INSERT_SIGNKEY_REVOCATION_H
+
+#include "taler_util.h"
+#include "taler_json_lib.h"
+#include "taler_exchangedb_plugin.h"
+
+/**
+ * Store information about a revoked online signing key.
+ *
+ * @param cls closure
+ * @param exchange_pub exchange online signing key that was revoked
+ * @param master_sig signature affirming the revocation
+ * @return transaction status code
+ */
+enum GNUNET_DB_QueryStatus
+TEH_PG_insert_signkey_revocation (
+  void *cls,
+  const struct TALER_ExchangePublicKeyP *exchange_pub,
+  const struct TALER_MasterSignatureP *master_sig);
+#endif
diff --git a/src/exchangedb/pg_insert_wire.c b/src/exchangedb/pg_insert_wire.c
new file mode 100644
index 00000000..646bce94
--- /dev/null
+++ b/src/exchangedb/pg_insert_wire.c
@@ -0,0 +1,56 @@
+/*
+   This file is part of TALER
+   Copyright (C) 2022 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 exchangedb/pg_insert_wire.c
+ * @brief Implementation of the insert_wire function for Postgres
+ * @author Christian Grothoff
+ */
+#include "platform.h"
+#include "taler_error_codes.h"
+#include "taler_dbevents.h"
+#include "taler_pq_lib.h"
+#include "pg_insert_wire.h"
+#include "pg_helper.h"
+
+
+enum GNUNET_DB_QueryStatus
+TEH_PG_insert_wire (void *cls,
+                      const char *payto_uri,
+                      struct GNUNET_TIME_Timestamp start_date,
+                      const struct TALER_MasterSignatureP *master_sig)
+{
+  struct PostgresClosure *pg = cls;
+  struct GNUNET_PQ_QueryParam params[] = {
+    GNUNET_PQ_query_param_string (payto_uri),
+    GNUNET_PQ_query_param_auto_from_type (master_sig),
+    GNUNET_PQ_query_param_timestamp (&start_date),
+    GNUNET_PQ_query_param_end
+  };
+
+      /* used in #postgres_insert_wire() */
+  PREPARE (pg,
+           "insert_wire",
+           "INSERT INTO wire_accounts "
+           "(payto_uri"
+           ",master_sig"
+           ",is_active"
+           ",last_change"
+           ") VALUES "
+           "($1, $2, true, $3);");
+  return GNUNET_PQ_eval_prepared_non_select (pg->conn,
+                                             "insert_wire",
+                                             params);
+}
diff --git a/src/exchangedb/pg_insert_wire.h b/src/exchangedb/pg_insert_wire.h
new file mode 100644
index 00000000..15ce0867
--- /dev/null
+++ b/src/exchangedb/pg_insert_wire.h
@@ -0,0 +1,44 @@
+/*
+   This file is part of TALER
+   Copyright (C) 2022 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 exchangedb/pg_insert_wire.h
+ * @brief implementation of the insert_wire function for Postgres
+ * @author Christian Grothoff
+ */
+#ifndef PG_INSERT_WIRE_H
+#define PG_INSERT_WIRE_H
+
+#include "taler_util.h"
+#include "taler_json_lib.h"
+#include "taler_exchangedb_plugin.h"
+/**
+ * Insert information about an wire account used by this exchange.
+ *
+ * @param cls closure
+ * @param payto_uri wire account of the exchange
+ * @param start_date date when the account was added by the offline system
+ *                      (only to be used for replay detection)
+ * @param master_sig public signature affirming the existence of the account,
+ *         must be of purpose #TALER_SIGNATURE_MASTER_WIRE_DETAILS
+ * @return transaction status code
+ */
+enum GNUNET_DB_QueryStatus
+TEH_PG_insert_wire (void *cls,
+                      const char *payto_uri,
+                      struct GNUNET_TIME_Timestamp start_date,
+                    const struct TALER_MasterSignatureP *master_sig);
+
+#endif
diff --git a/src/exchangedb/pg_insert_wire_fee.c 
b/src/exchangedb/pg_insert_wire_fee.c
new file mode 100644
index 00000000..278ec2bc
--- /dev/null
+++ b/src/exchangedb/pg_insert_wire_fee.c
@@ -0,0 +1,108 @@
+/*
+   This file is part of TALER
+   Copyright (C) 2022 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 exchangedb/pg_insert_wire_fee.c
+ * @brief Implementation of the insert_wire_fee function for Postgres
+ * @author Christian Grothoff
+ */
+#include "platform.h"
+#include "taler_error_codes.h"
+#include "taler_dbevents.h"
+#include "taler_pq_lib.h"
+#include "pg_insert_wire_fee.h"
+#include "pg_helper.h"
+#include "pg_get_wire_fee.h"
+
+enum GNUNET_DB_QueryStatus
+TEH_PG_insert_wire_fee (void *cls,
+                          const char *type,
+                          struct GNUNET_TIME_Timestamp start_date,
+                          struct GNUNET_TIME_Timestamp end_date,
+                          const struct TALER_WireFeeSet *fees,
+                          const struct TALER_MasterSignatureP *master_sig)
+{
+  struct PostgresClosure *pg = cls;
+  struct GNUNET_PQ_QueryParam params[] = {
+    GNUNET_PQ_query_param_string (type),
+    GNUNET_PQ_query_param_timestamp (&start_date),
+    GNUNET_PQ_query_param_timestamp (&end_date),
+    TALER_PQ_query_param_amount (&fees->wire),
+    TALER_PQ_query_param_amount (&fees->closing),
+    GNUNET_PQ_query_param_auto_from_type (master_sig),
+    GNUNET_PQ_query_param_end
+  };
+  struct TALER_WireFeeSet wx;
+  struct TALER_MasterSignatureP sig;
+  struct GNUNET_TIME_Timestamp sd;
+  struct GNUNET_TIME_Timestamp ed;
+  enum GNUNET_DB_QueryStatus qs;
+
+  qs = TEH_PG_get_wire_fee (pg,
+                              type,
+                              start_date,
+                              &sd,
+                              &ed,
+                              &wx,
+                              &sig);
+  if (qs < 0)
+    return qs;
+  if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT == qs)
+  {
+    if (0 != GNUNET_memcmp (&sig,
+                            master_sig))
+    {
+      GNUNET_break (0);
+      return GNUNET_DB_STATUS_HARD_ERROR;
+    }
+    if (0 !=
+        TALER_wire_fee_set_cmp (fees,
+                                &wx))
+    {
+      GNUNET_break (0);
+      return GNUNET_DB_STATUS_HARD_ERROR;
+    }
+    if ( (GNUNET_TIME_timestamp_cmp (sd,
+                                     !=,
+                                     start_date)) ||
+         (GNUNET_TIME_timestamp_cmp (ed,
+                                     !=,
+                                     end_date)) )
+    {
+      GNUNET_break (0);
+      return GNUNET_DB_STATUS_HARD_ERROR;
+    }
+    /* equal record already exists */
+    return GNUNET_DB_STATUS_SUCCESS_NO_RESULTS;
+  }
+
+      /* Used in #postgres_insert_wire_fee */
+  PREPARE (pg,
+           "insert_wire_fee",
+           "INSERT INTO wire_fee "
+           "(wire_method"
+           ",start_date"
+           ",end_date"
+           ",wire_fee_val"
+           ",wire_fee_frac"
+           ",closing_fee_val"
+           ",closing_fee_frac"
+           ",master_sig"
+           ") VALUES "
+           "($1, $2, $3, $4, $5, $6, $7, $8);");
+  return GNUNET_PQ_eval_prepared_non_select (pg->conn,
+                                             "insert_wire_fee",
+                                             params);
+}
diff --git a/src/exchangedb/pg_insert_wire_fee.h 
b/src/exchangedb/pg_insert_wire_fee.h
new file mode 100644
index 00000000..e53faf5a
--- /dev/null
+++ b/src/exchangedb/pg_insert_wire_fee.h
@@ -0,0 +1,46 @@
+/*
+   This file is part of TALER
+   Copyright (C) 2022 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 exchangedb/pg_insert_wire_fee.h
+ * @brief implementation of the insert_wire_fee function for Postgres
+ * @author Christian Grothoff
+ */
+#ifndef PG_INSERT_WIRE_FEE_H
+#define PG_INSERT_WIRE_FEE_H
+
+#include "taler_util.h"
+#include "taler_json_lib.h"
+#include "taler_exchangedb_plugin.h"
+
+/**
+ * Insert wire transfer fee into database.
+ *
+ * @param cls closure
+ * @param type type of wire transfer this fee applies for
+ * @param start_date when does the fee go into effect
+ * @param end_date when does the fee end being valid
+ * @param fees how high are the wire fees
+ * @param master_sig signature over the above by the exchange master key
+ * @return transaction status code
+ */
+enum GNUNET_DB_QueryStatus
+TEH_PG_insert_wire_fee (void *cls,
+                          const char *type,
+                          struct GNUNET_TIME_Timestamp start_date,
+                          struct GNUNET_TIME_Timestamp end_date,
+                          const struct TALER_WireFeeSet *fees,
+                        const struct TALER_MasterSignatureP *master_sig);
+#endif
diff --git a/src/exchangedb/pg_iterate_active_auditors.c 
b/src/exchangedb/pg_iterate_active_auditors.c
new file mode 100644
index 00000000..11b10cb4
--- /dev/null
+++ b/src/exchangedb/pg_iterate_active_auditors.c
@@ -0,0 +1,124 @@
+/*
+   This file is part of TALER
+   Copyright (C) 2022 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 exchangedb/pg_iterate_active_auditors.c
+ * @brief Implementation of the iterate_active_auditors function for Postgres
+ * @author Christian Grothoff
+ */
+#include "platform.h"
+#include "taler_error_codes.h"
+#include "taler_dbevents.h"
+#include "taler_pq_lib.h"
+#include "pg_iterate_active_auditors.h"
+#include "pg_helper.h"
+
+
+/**
+ * Closure for #auditors_cb_helper()
+ */
+struct AuditorsIteratorContext
+{
+  /**
+   * Function to call with the results.
+   */
+  TALER_EXCHANGEDB_AuditorsCallback cb;
+
+  /**
+   * Closure to pass to @e cb
+   */
+  void *cb_cls;
+
+};
+
+
+/**
+ * Helper function for #postgres_iterate_active_auditors().
+ * Calls the callback with each auditor.
+ *
+ * @param cls a `struct SignkeysIteratorContext`
+ * @param result db results
+ * @param num_results number of results in @a result
+ */
+static void
+auditors_cb_helper (void *cls,
+                    PGresult *result,
+                    unsigned int num_results)
+{
+  struct AuditorsIteratorContext *dic = cls;
+
+  for (unsigned int i = 0; i<num_results; i++)
+  {
+    struct TALER_AuditorPublicKeyP auditor_pub;
+    char *auditor_url;
+    char *auditor_name;
+    struct GNUNET_PQ_ResultSpec rs[] = {
+      GNUNET_PQ_result_spec_auto_from_type ("auditor_pub",
+                                            &auditor_pub),
+      GNUNET_PQ_result_spec_string ("auditor_url",
+                                    &auditor_url),
+      GNUNET_PQ_result_spec_string ("auditor_name",
+                                    &auditor_name),
+      GNUNET_PQ_result_spec_end
+    };
+
+    if (GNUNET_OK !=
+        GNUNET_PQ_extract_result (result,
+                                  rs,
+                                  i))
+    {
+      GNUNET_break (0);
+      return;
+    }
+    dic->cb (dic->cb_cls,
+             &auditor_pub,
+             auditor_url,
+             auditor_name);
+    GNUNET_PQ_cleanup_result (rs);
+  }
+}
+
+
+
+enum GNUNET_DB_QueryStatus
+TEH_PG_iterate_active_auditors (void *cls,
+                                  TALER_EXCHANGEDB_AuditorsCallback cb,
+                                  void *cb_cls)
+{
+  struct PostgresClosure *pg = cls;
+  struct GNUNET_PQ_QueryParam params[] = {
+    GNUNET_PQ_query_param_end
+  };
+  struct AuditorsIteratorContext dic = {
+    .cb = cb,
+    .cb_cls = cb_cls,
+  };
+    /* Used in #postgres_iterate_active_auditors() */
+  PREPARE (pg,
+           "select_auditors",
+           "SELECT"
+           " auditor_pub"
+           ",auditor_url"
+           ",auditor_name"
+           " FROM auditors"
+           " WHERE"
+           "   is_active;");
+
+  return GNUNET_PQ_eval_prepared_multi_select (pg->conn,
+                                               "select_auditors",
+                                               params,
+                                               &auditors_cb_helper,
+                                               &dic);
+}
diff --git a/src/exchangedb/pg_iterate_active_auditors.h 
b/src/exchangedb/pg_iterate_active_auditors.h
new file mode 100644
index 00000000..1247d2d3
--- /dev/null
+++ b/src/exchangedb/pg_iterate_active_auditors.h
@@ -0,0 +1,41 @@
+/*
+   This file is part of TALER
+   Copyright (C) 2022 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 exchangedb/pg_iterate_active_auditors.h
+ * @brief implementation of the iterate_active_auditors function for Postgres
+ * @author Christian Grothoff
+ */
+#ifndef PG_ITERATE_ACTIVE_AUDITORS_H
+#define PG_ITERATE_ACTIVE_AUDITORS_H
+
+#include "taler_util.h"
+#include "taler_json_lib.h"
+#include "taler_exchangedb_plugin.h"
+
+/**
+ * Function called to invoke @a cb on every active auditor. Disabled
+ * auditors are skipped. Runs in its own read-only transaction.
+ *
+ * @param cls the @e cls of this struct with the plugin-specific state
+ * @param cb function to call on each active auditor
+ * @param cb_cls closure for @a cb
+ * @return transaction status code
+ */
+enum GNUNET_DB_QueryStatus
+TEH_PG_iterate_active_auditors (void *cls,
+                                  TALER_EXCHANGEDB_AuditorsCallback cb,
+                                void *cb_cls);
+#endif
diff --git a/src/exchangedb/pg_iterate_auditor_denominations.c 
b/src/exchangedb/pg_iterate_auditor_denominations.c
new file mode 100644
index 00000000..6456ed1d
--- /dev/null
+++ b/src/exchangedb/pg_iterate_auditor_denominations.c
@@ -0,0 +1,121 @@
+/*
+   This file is part of TALER
+   Copyright (C) 2022 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 exchangedb/pg_iterate_auditor_denominations.c
+ * @brief Implementation of the iterate_auditor_denominations function for 
Postgres
+ * @author Christian Grothoff
+ */
+#include "platform.h"
+#include "taler_error_codes.h"
+#include "taler_dbevents.h"
+#include "taler_pq_lib.h"
+#include "pg_iterate_auditor_denominations.h"
+#include "pg_helper.h"
+
+/**
+ * Closure for #auditor_denoms_cb_helper()
+ */
+struct AuditorDenomsIteratorContext
+{
+  /**
+   * Function to call with the results.
+   */
+  TALER_EXCHANGEDB_AuditorDenominationsCallback cb;
+
+  /**
+   * Closure to pass to @e cb
+   */
+  void *cb_cls;
+};
+
+
+/**
+ * Helper function for #postgres_iterate_auditor_denominations().
+ * Calls the callback with each auditor and denomination pair.
+ *
+ * @param cls a `struct AuditorDenomsIteratorContext`
+ * @param result db results
+ * @param num_results number of results in @a result
+ */
+static void
+auditor_denoms_cb_helper (void *cls,
+                          PGresult *result,
+                          unsigned int num_results)
+{
+  struct AuditorDenomsIteratorContext *dic = cls;
+
+  for (unsigned int i = 0; i<num_results; i++)
+  {
+    struct TALER_AuditorPublicKeyP auditor_pub;
+    struct TALER_DenominationHashP h_denom_pub;
+    struct TALER_AuditorSignatureP auditor_sig;
+    struct GNUNET_PQ_ResultSpec rs[] = {
+      GNUNET_PQ_result_spec_auto_from_type ("auditor_pub",
+                                            &auditor_pub),
+      GNUNET_PQ_result_spec_auto_from_type ("denom_pub_hash",
+                                            &h_denom_pub),
+      GNUNET_PQ_result_spec_auto_from_type ("auditor_sig",
+                                            &auditor_sig),
+      GNUNET_PQ_result_spec_end
+    };
+
+    if (GNUNET_OK !=
+        GNUNET_PQ_extract_result (result,
+                                  rs,
+                                  i))
+    {
+      GNUNET_break (0);
+      return;
+    }
+    dic->cb (dic->cb_cls,
+             &auditor_pub,
+             &h_denom_pub,
+             &auditor_sig);
+  }
+}
+
+
+enum GNUNET_DB_QueryStatus
+TEH_PG_iterate_auditor_denominations (
+  void *cls,
+  TALER_EXCHANGEDB_AuditorDenominationsCallback cb,
+  void *cb_cls)
+{
+  struct PostgresClosure *pg = cls;
+  struct GNUNET_PQ_QueryParam params[] = {
+    GNUNET_PQ_query_param_end
+  };
+  struct AuditorDenomsIteratorContext dic = {
+    .cb = cb,
+    .cb_cls = cb_cls,
+  };
+    /* Used in #postgres_iterate_auditor_denominations() */
+  PREPARE (pg,
+           "select_auditor_denoms",
+           "SELECT"
+           " auditors.auditor_pub"
+           ",denominations.denom_pub_hash"
+           ",auditor_denom_sigs.auditor_sig"
+           " FROM auditor_denom_sigs"
+           " JOIN auditors USING (auditor_uuid)"
+           " JOIN denominations USING (denominations_serial)"
+           " WHERE auditors.is_active;");
+    return GNUNET_PQ_eval_prepared_multi_select (pg->conn,
+                                               "select_auditor_denoms",
+                                               params,
+                                               &auditor_denoms_cb_helper,
+                                               &dic);
+}
diff --git a/src/exchangedb/pg_iterate_auditor_denominations.h 
b/src/exchangedb/pg_iterate_auditor_denominations.h
new file mode 100644
index 00000000..da1f3670
--- /dev/null
+++ b/src/exchangedb/pg_iterate_auditor_denominations.h
@@ -0,0 +1,44 @@
+/*
+   This file is part of TALER
+   Copyright (C) 2022 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 exchangedb/pg_iterate_auditor_denominations.h
+ * @brief implementation of the iterate_auditor_denominations function for 
Postgres
+ * @author Christian Grothoff
+ */
+#ifndef PG_ITERATE_AUDITOR_DENOMINATIONS_H
+#define PG_ITERATE_AUDITOR_DENOMINATIONS_H
+
+#include "taler_util.h"
+#include "taler_json_lib.h"
+#include "taler_exchangedb_plugin.h"
+
+
+/**
+ * Function called to invoke @a cb on every denomination with an active
+ * auditor. Disabled auditors and denominations without auditor are
+ * skipped. Runs in its own read-only transaction.
+ *
+ * @param cls the @e cls of this struct with the plugin-specific state
+ * @param cb function to call on each active auditor
+ * @param cb_cls closure for @a cb
+ * @return transaction status code
+ */
+enum GNUNET_DB_QueryStatus
+TEH_PG_iterate_auditor_denominations (
+  void *cls,
+  TALER_EXCHANGEDB_AuditorDenominationsCallback cb,
+  void *cb_cls);
+#endif
diff --git a/src/exchangedb/pg_iterate_denomination_info.c 
b/src/exchangedb/pg_iterate_denomination_info.c
new file mode 100644
index 00000000..bf39a65a
--- /dev/null
+++ b/src/exchangedb/pg_iterate_denomination_info.c
@@ -0,0 +1,194 @@
+/*
+   This file is part of TALER
+   Copyright (C) 2022 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 exchangedb/pg_iterate_denomination_info.c
+ * @brief Implementation of the iterate_denomination_info function for Postgres
+ * @author Christian Grothoff
+ */
+#include "platform.h"
+#include "taler_error_codes.h"
+#include "taler_dbevents.h"
+#include "taler_pq_lib.h"
+#include "pg_iterate_denomination_info.h"
+#include "pg_helper.h"
+
+
+/**
+ * Closure for #domination_cb_helper()
+ */
+struct DenomIteratorContext
+{
+  /**
+   * Function to call with the results.
+   */
+  TALER_EXCHANGEDB_DenominationCallback cb;
+
+  /**
+   * Closure to pass to @e cb
+   */
+  void *cb_cls;
+
+  /**
+   * Plugin context.
+   */
+  struct PostgresClosure *pg;
+};
+
+
+/**
+ * Helper function for #postgres_iterate_denomination_info().
+ * Calls the callback with each denomination key.
+ *
+ * @param cls a `struct DenomIteratorContext`
+ * @param result db results
+ * @param num_results number of results in @a result
+ */
+static void
+domination_cb_helper (void *cls,
+                      PGresult *result,
+                      unsigned int num_results)
+{
+  struct DenomIteratorContext *dic = cls;
+  struct PostgresClosure *pg = dic->pg;
+
+  for (unsigned int i = 0; i<num_results; i++)
+  {
+    struct TALER_EXCHANGEDB_DenominationKeyInformation issue;
+    struct TALER_DenominationPublicKey denom_pub;
+    struct TALER_DenominationHashP denom_hash;
+    struct GNUNET_PQ_ResultSpec rs[] = {
+      GNUNET_PQ_result_spec_auto_from_type ("master_sig",
+                                            &issue.signature),
+      GNUNET_PQ_result_spec_auto_from_type ("denom_pub_hash",
+                                            &denom_hash),
+      GNUNET_PQ_result_spec_timestamp ("valid_from",
+                                       &issue.start),
+      GNUNET_PQ_result_spec_timestamp ("expire_withdraw",
+                                       &issue.expire_withdraw),
+      GNUNET_PQ_result_spec_timestamp ("expire_deposit",
+                                       &issue.expire_deposit),
+      GNUNET_PQ_result_spec_timestamp ("expire_legal",
+                                       &issue.expire_legal),
+      TALER_PQ_RESULT_SPEC_AMOUNT ("coin",
+                                   &issue.value),
+      TALER_PQ_RESULT_SPEC_AMOUNT ("fee_withdraw",
+                                   &issue.fees.withdraw),
+      TALER_PQ_RESULT_SPEC_AMOUNT ("fee_deposit",
+                                   &issue.fees.deposit),
+      TALER_PQ_RESULT_SPEC_AMOUNT ("fee_refresh",
+                                   &issue.fees.refresh),
+      TALER_PQ_RESULT_SPEC_AMOUNT ("fee_refund",
+                                   &issue.fees.refund),
+      TALER_PQ_result_spec_denom_pub ("denom_pub",
+                                      &denom_pub),
+      GNUNET_PQ_result_spec_uint32 ("age_mask",
+                                    &issue.age_mask.bits),
+      GNUNET_PQ_result_spec_end
+    };
+
+    if (GNUNET_OK !=
+        GNUNET_PQ_extract_result (result,
+                                  rs,
+                                  i))
+    {
+      GNUNET_break (0);
+      return;
+    }
+
+    /* Unfortunately we have to carry the age mask in both, the
+     * TALER_DenominationPublicKey and
+     * TALER_EXCHANGEDB_DenominationKeyInformation at different times.
+     * Here we use _both_ so let's make sure the values are the same. */
+    denom_pub.age_mask = issue.age_mask;
+    TALER_denom_pub_hash (&denom_pub,
+                          &issue.denom_hash);
+    if (0 !=
+        GNUNET_memcmp (&issue.denom_hash,
+                       &denom_hash))
+    {
+      GNUNET_break (0);
+    }
+    else
+    {
+      dic->cb (dic->cb_cls,
+               &denom_pub,
+               &issue);
+    }
+    TALER_denom_pub_free (&denom_pub);
+  }
+}
+
+
+
+
+
+
+
+
+
+
+/**
+ * Fetch information about all known denomination keys.
+ *
+ * @param cls the @e cls of this struct with the plugin-specific state
+ * @param cb function to call on each denomination key
+ * @param cb_cls closure for @a cb
+ * @return transaction status code
+ */
+enum GNUNET_DB_QueryStatus
+TEH_PG_iterate_denomination_info (void *cls,
+                                    TALER_EXCHANGEDB_DenominationCallback cb,
+                                    void *cb_cls)
+{
+  struct PostgresClosure *pg = cls;
+  struct GNUNET_PQ_QueryParam params[] = {
+    GNUNET_PQ_query_param_end
+  };
+  struct DenomIteratorContext dic = {
+    .cb = cb,
+    .cb_cls = cb_cls,
+    .pg = pg
+  };
+
+   /* Used in #postgres_iterate_denomination_info() */
+  PREPARE (pg,
+           "denomination_iterate",
+           "SELECT"
+           " master_sig"
+           ",denom_pub_hash"
+           ",valid_from"
+           ",expire_withdraw"
+           ",expire_deposit"
+           ",expire_legal"
+           ",coin_val"                                                /* value 
of this denom */
+           ",coin_frac"                                                /* 
fractional value of this denom */
+           ",fee_withdraw_val"
+           ",fee_withdraw_frac"
+           ",fee_deposit_val"
+           ",fee_deposit_frac"
+           ",fee_refresh_val"
+           ",fee_refresh_frac"
+           ",fee_refund_val"
+           ",fee_refund_frac"
+           ",denom_pub"
+           ",age_mask"
+           " FROM denominations;");
+  return GNUNET_PQ_eval_prepared_multi_select (pg->conn,
+                                               "denomination_iterate",
+                                               params,
+                                               &domination_cb_helper,
+                                               &dic);
+}
diff --git a/src/exchangedb/pg_iterate_denomination_info.h 
b/src/exchangedb/pg_iterate_denomination_info.h
new file mode 100644
index 00000000..57847a51
--- /dev/null
+++ b/src/exchangedb/pg_iterate_denomination_info.h
@@ -0,0 +1,41 @@
+/*
+   This file is part of TALER
+   Copyright (C) 2022 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 exchangedb/pg_iterate_denomination_info.h
+ * @brief implementation of the iterate_denomination_info function for Postgres
+ * @author Christian Grothoff
+ */
+#ifndef PG_ITERATE_DENOMINATION_INFO_H
+#define PG_ITERATE_DENOMINATION_INFO_H
+
+#include "taler_util.h"
+#include "taler_json_lib.h"
+#include "taler_exchangedb_plugin.h"
+
+/**
+ * Fetch information about all known denomination keys.
+ *
+ * @param cls the @e cls of this struct with the plugin-specific state
+ * @param cb function to call on each denomination key
+ * @param cb_cls closure for @a cb
+ * @return transaction status code
+ */
+enum GNUNET_DB_QueryStatus
+TEH_PG_iterate_denomination_info (void *cls,
+                                    TALER_EXCHANGEDB_DenominationCallback cb,
+                                  void *cb_cls);
+
+#endif
diff --git a/src/exchangedb/pg_iterate_denominations.c 
b/src/exchangedb/pg_iterate_denominations.c
new file mode 100644
index 00000000..d8a91f55
--- /dev/null
+++ b/src/exchangedb/pg_iterate_denominations.c
@@ -0,0 +1,179 @@
+/*
+   This file is part of TALER
+   Copyright (C) 2022 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 exchangedb/pg_iterate_denominations.c
+ * @brief Implementation of the iterate_denominations function for Postgres
+ * @author Christian Grothoff
+ */
+#include "platform.h"
+#include "taler_error_codes.h"
+#include "taler_dbevents.h"
+#include "taler_pq_lib.h"
+#include "pg_iterate_denominations.h"
+#include "pg_helper.h"
+
+
+
+
+/**
+ * Closure for #dominations_cb_helper()
+ */
+struct DenomsIteratorContext
+{
+  /**
+   * Function to call with the results.
+   */
+  TALER_EXCHANGEDB_DenominationsCallback cb;
+
+  /**
+   * Closure to pass to @e cb
+   */
+  void *cb_cls;
+
+  /**
+   * Plugin context.
+   */
+  struct PostgresClosure *pg;
+};
+
+
+/**
+ * Helper function for #postgres_iterate_denominations().
+ * Calls the callback with each denomination key.
+ *
+ * @param cls a `struct DenomsIteratorContext`
+ * @param result db results
+ * @param num_results number of results in @a result
+ */
+static void
+dominations_cb_helper (void *cls,
+                       PGresult *result,
+                       unsigned int num_results)
+{
+  struct DenomsIteratorContext *dic = cls;
+  struct PostgresClosure *pg = dic->pg;
+
+  for (unsigned int i = 0; i<num_results; i++)
+  {
+    struct TALER_EXCHANGEDB_DenominationKeyMetaData meta = {0};
+    struct TALER_DenominationPublicKey denom_pub = {0};
+    struct TALER_MasterSignatureP master_sig = {0};
+    struct TALER_DenominationHashP h_denom_pub = {0};
+    bool revoked;
+    struct GNUNET_PQ_ResultSpec rs[] = {
+      GNUNET_PQ_result_spec_auto_from_type ("master_sig",
+                                            &master_sig),
+      GNUNET_PQ_result_spec_bool ("revoked",
+                                  &revoked),
+      GNUNET_PQ_result_spec_timestamp ("valid_from",
+                                       &meta.start),
+      GNUNET_PQ_result_spec_timestamp ("expire_withdraw",
+                                       &meta.expire_withdraw),
+      GNUNET_PQ_result_spec_timestamp ("expire_deposit",
+                                       &meta.expire_deposit),
+      GNUNET_PQ_result_spec_timestamp ("expire_legal",
+                                       &meta.expire_legal),
+      TALER_PQ_RESULT_SPEC_AMOUNT ("coin",
+                                   &meta.value),
+      TALER_PQ_RESULT_SPEC_AMOUNT ("fee_withdraw",
+                                   &meta.fees.withdraw),
+      TALER_PQ_RESULT_SPEC_AMOUNT ("fee_deposit",
+                                   &meta.fees.deposit),
+      TALER_PQ_RESULT_SPEC_AMOUNT ("fee_refresh",
+                                   &meta.fees.refresh),
+      TALER_PQ_RESULT_SPEC_AMOUNT ("fee_refund",
+                                   &meta.fees.refund),
+      TALER_PQ_result_spec_denom_pub ("denom_pub",
+                                      &denom_pub),
+      GNUNET_PQ_result_spec_uint32 ("age_mask",
+                                    &meta.age_mask.bits),
+      GNUNET_PQ_result_spec_end
+    };
+
+    if (GNUNET_OK !=
+        GNUNET_PQ_extract_result (result,
+                                  rs,
+                                  i))
+    {
+      GNUNET_break (0);
+      return;
+    }
+
+    /* make sure the mask information is the same */
+    denom_pub.age_mask = meta.age_mask;
+
+    TALER_denom_pub_hash (&denom_pub,
+                          &h_denom_pub);
+    dic->cb (dic->cb_cls,
+             &denom_pub,
+             &h_denom_pub,
+             &meta,
+             &master_sig,
+             revoked);
+    GNUNET_PQ_cleanup_result (rs);
+  }
+}
+
+
+enum GNUNET_DB_QueryStatus
+TEH_PG_iterate_denominations (void *cls,
+                                TALER_EXCHANGEDB_DenominationsCallback cb,
+                                void *cb_cls)
+{
+  struct PostgresClosure *pg = cls;
+  struct GNUNET_PQ_QueryParam params[] = {
+    GNUNET_PQ_query_param_end
+  };
+  struct DenomsIteratorContext dic = {
+    .cb = cb,
+    .cb_cls = cb_cls,
+    .pg = pg
+  };
+
+    /* Used in #postgres_iterate_denominations() */
+  PREPARE (pg,
+           "select_denominations",
+           "SELECT"
+           " denominations.master_sig"
+           ",denom_revocations_serial_id IS NOT NULL AS revoked"
+           ",valid_from"
+           ",expire_withdraw"
+           ",expire_deposit"
+           ",expire_legal"
+           ",coin_val"                                                /* value 
of this denom */
+           ",coin_frac"                                                /* 
fractional value of this denom */
+           ",fee_withdraw_val"
+           ",fee_withdraw_frac"
+           ",fee_deposit_val"
+           ",fee_deposit_frac"
+           ",fee_refresh_val"
+           ",fee_refresh_frac"
+           ",fee_refund_val"
+           ",fee_refund_frac"
+           ",denom_type"
+           ",age_mask"
+           ",denom_pub"
+           " FROM denominations"
+           " LEFT JOIN "
+           "   denomination_revocations USING (denominations_serial);");
+
+
+  return GNUNET_PQ_eval_prepared_multi_select (pg->conn,
+                                               "select_denominations",
+                                               params,
+                                               &dominations_cb_helper,
+                                               &dic);
+}
diff --git a/src/exchangedb/pg_iterate_denominations.h 
b/src/exchangedb/pg_iterate_denominations.h
new file mode 100644
index 00000000..a205fc6b
--- /dev/null
+++ b/src/exchangedb/pg_iterate_denominations.h
@@ -0,0 +1,44 @@
+/*
+   This file is part of TALER
+   Copyright (C) 2022 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 exchangedb/pg_iterate_denominations.h
+ * @brief implementation of the iterate_denominations function for Postgres
+ * @author Christian Grothoff
+ */
+#ifndef PG_ITERATE_DENOMINATIONS_H
+#define PG_ITERATE_DENOMINATIONS_H
+
+#include "taler_util.h"
+#include "taler_json_lib.h"
+#include "taler_exchangedb_plugin.h"
+
+/**
+ * Function called to invoke @a cb on every known denomination key (revoked
+ * and non-revoked) that has been signed by the master key. Runs in its own
+ * read-only transaction.
+ *
+ *
+ * @param cls the @e cls of this struct with the plugin-specific state
+ * @param cb function to call on each denomination key
+ * @param cb_cls closure for @a cb
+ * @return transaction status code
+ */
+enum GNUNET_DB_QueryStatus
+TEH_PG_iterate_denominations (void *cls,
+                                TALER_EXCHANGEDB_DenominationsCallback cb,
+                              void *cb_cls);
+
+#endif
diff --git a/src/exchangedb/pg_lookup_auditor_status.c 
b/src/exchangedb/pg_lookup_auditor_status.c
new file mode 100644
index 00000000..5e62bfa9
--- /dev/null
+++ b/src/exchangedb/pg_lookup_auditor_status.c
@@ -0,0 +1,61 @@
+/*
+   This file is part of TALER
+   Copyright (C) 2022 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 exchangedb/pg_lookup_auditor_status.c
+ * @brief Implementation of the lookup_auditor_status function for Postgres
+ * @author Christian Grothoff
+ */
+#include "platform.h"
+#include "taler_error_codes.h"
+#include "taler_dbevents.h"
+#include "taler_pq_lib.h"
+#include "pg_lookup_auditor_status.h"
+#include "pg_helper.h"
+
+
+enum GNUNET_DB_QueryStatus
+TEH_PG_lookup_auditor_status (
+  void *cls,
+  const struct TALER_AuditorPublicKeyP *auditor_pub,
+  char **auditor_url,
+  bool *enabled)
+{
+  struct PostgresClosure *pg = cls;
+  struct GNUNET_PQ_QueryParam params[] = {
+    GNUNET_PQ_query_param_auto_from_type (auditor_pub),
+    GNUNET_PQ_query_param_end
+  };
+  struct GNUNET_PQ_ResultSpec rs[] = {
+    GNUNET_PQ_result_spec_string ("auditor_url",
+                                  auditor_url),
+    GNUNET_PQ_result_spec_bool ("is_active",
+                                enabled),
+    GNUNET_PQ_result_spec_end
+  };
+
+      /* Used in #postgres_lookup_auditor_status() */
+  PREPARE (pg,
+           "lookup_auditor_status",
+           "SELECT"
+           " auditor_url"
+           ",is_active"
+           " FROM auditors"
+           " WHERE auditor_pub=$1;");
+  return GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
+                                                   "lookup_auditor_status",
+                                                   params,
+                                                   rs);
+}
diff --git a/src/exchangedb/pg_lookup_auditor_status.h 
b/src/exchangedb/pg_lookup_auditor_status.h
new file mode 100644
index 00000000..b75788e1
--- /dev/null
+++ b/src/exchangedb/pg_lookup_auditor_status.h
@@ -0,0 +1,44 @@
+/*
+   This file is part of TALER
+   Copyright (C) 2022 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 exchangedb/pg_lookup_auditor_status.h
+ * @brief implementation of the lookup_auditor_status function for Postgres
+ * @author Christian Grothoff
+ */
+#ifndef PG_LOOKUP_AUDITOR_STATUS_H
+#define PG_LOOKUP_AUDITOR_STATUS_H
+
+#include "taler_util.h"
+#include "taler_json_lib.h"
+#include "taler_exchangedb_plugin.h"
+/**
+ * Lookup current state of an auditor.
+ *
+ * @param cls closure
+ * @param auditor_pub key to look up information for
+ * @param[out] auditor_url set to the base URL of the auditor's REST API; 
memory to be
+ *            released by the caller!
+ * @param[out] enabled set if the auditor is currently in use
+ * @return transaction status code
+ */
+enum GNUNET_DB_QueryStatus
+TEH_PG_lookup_auditor_status (
+  void *cls,
+  const struct TALER_AuditorPublicKeyP *auditor_pub,
+  char **auditor_url,
+  bool *enabled);
+
+#endif
diff --git a/src/exchangedb/pg_lookup_auditor_timestamp.c 
b/src/exchangedb/pg_lookup_auditor_timestamp.c
new file mode 100644
index 00000000..3a4bd6be
--- /dev/null
+++ b/src/exchangedb/pg_lookup_auditor_timestamp.c
@@ -0,0 +1,57 @@
+/*
+   This file is part of TALER
+   Copyright (C) 2022 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 exchangedb/pg_lookup_auditor_timestamp.c
+ * @brief Implementation of the lookup_auditor_timestamp function for Postgres
+ * @author Christian Grothoff
+ */
+#include "platform.h"
+#include "taler_error_codes.h"
+#include "taler_dbevents.h"
+#include "taler_pq_lib.h"
+#include "pg_lookup_auditor_timestamp.h"
+#include "pg_helper.h"
+
+
+enum GNUNET_DB_QueryStatus
+TEH_PG_lookup_auditor_timestamp (
+  void *cls,
+  const struct TALER_AuditorPublicKeyP *auditor_pub,
+  struct GNUNET_TIME_Timestamp *last_date)
+{
+  struct PostgresClosure *pg = cls;
+  struct GNUNET_PQ_QueryParam params[] = {
+    GNUNET_PQ_query_param_auto_from_type (auditor_pub),
+    GNUNET_PQ_query_param_end
+  };
+  struct GNUNET_PQ_ResultSpec rs[] = {
+    GNUNET_PQ_result_spec_timestamp ("last_change",
+                                     last_date),
+    GNUNET_PQ_result_spec_end
+  };
+
+      /* Used in #postgres_lookup_auditor_timestamp() */
+  PREPARE (pg,
+           "lookup_auditor_timestamp",
+           "SELECT"
+           " last_change"
+           " FROM auditors"
+           " WHERE auditor_pub=$1;");
+  return GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
+                                                   "lookup_auditor_timestamp",
+                                                   params,
+                                                   rs);
+}
diff --git a/src/exchangedb/pg_lookup_auditor_timestamp.h 
b/src/exchangedb/pg_lookup_auditor_timestamp.h
new file mode 100644
index 00000000..5674ba22
--- /dev/null
+++ b/src/exchangedb/pg_lookup_auditor_timestamp.h
@@ -0,0 +1,41 @@
+/*
+   This file is part of TALER
+   Copyright (C) 2022 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 exchangedb/pg_lookup_auditor_timestamp.h
+ * @brief implementation of the lookup_auditor_timestamp function for Postgres
+ * @author Christian Grothoff
+ */
+#ifndef PG_LOOKUP_AUDITOR_TIMESTAMP_H
+#define PG_LOOKUP_AUDITOR_TIMESTAMP_H
+
+#include "taler_util.h"
+#include "taler_json_lib.h"
+#include "taler_exchangedb_plugin.h"
+
+/**
+ * Check the last date an auditor was modified.
+ *
+ * @param cls closure
+ * @param auditor_pub key to look up information for
+ * @param[out] last_date last modification date to auditor status
+ * @return transaction status code
+ */
+enum GNUNET_DB_QueryStatus
+TEH_PG_lookup_auditor_timestamp (
+  void *cls,
+  const struct TALER_AuditorPublicKeyP *auditor_pub,
+  struct GNUNET_TIME_Timestamp *last_date);
+#endif
diff --git a/src/exchangedb/pg_lookup_denomination_key.c 
b/src/exchangedb/pg_lookup_denomination_key.c
new file mode 100644
index 00000000..36ada96e
--- /dev/null
+++ b/src/exchangedb/pg_lookup_denomination_key.c
@@ -0,0 +1,88 @@
+/*
+   This file is part of TALER
+   Copyright (C) 2022 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 exchangedb/pg_lookup_denomination_key.c
+ * @brief Implementation of the lookup_denomination_key function for Postgres
+ * @author Christian Grothoff
+ */
+#include "platform.h"
+#include "taler_error_codes.h"
+#include "taler_dbevents.h"
+#include "taler_pq_lib.h"
+#include "pg_lookup_denomination_key.h"
+#include "pg_helper.h"
+
+enum GNUNET_DB_QueryStatus
+TEH_PG_lookup_denomination_key (
+  void *cls,
+  const struct TALER_DenominationHashP *h_denom_pub,
+  struct TALER_EXCHANGEDB_DenominationKeyMetaData *meta)
+{
+  struct PostgresClosure *pg = cls;
+  struct GNUNET_PQ_QueryParam params[] = {
+    GNUNET_PQ_query_param_auto_from_type (h_denom_pub),
+    GNUNET_PQ_query_param_end
+  };
+  struct GNUNET_PQ_ResultSpec rs[] = {
+    GNUNET_PQ_result_spec_timestamp ("valid_from",
+                                     &meta->start),
+    GNUNET_PQ_result_spec_timestamp ("expire_withdraw",
+                                     &meta->expire_withdraw),
+    GNUNET_PQ_result_spec_timestamp ("expire_deposit",
+                                     &meta->expire_deposit),
+    GNUNET_PQ_result_spec_timestamp ("expire_legal",
+                                     &meta->expire_legal),
+    TALER_PQ_RESULT_SPEC_AMOUNT ("coin",
+                                 &meta->value),
+    TALER_PQ_RESULT_SPEC_AMOUNT ("fee_withdraw",
+                                 &meta->fees.withdraw),
+    TALER_PQ_RESULT_SPEC_AMOUNT ("fee_deposit",
+                                 &meta->fees.deposit),
+    TALER_PQ_RESULT_SPEC_AMOUNT ("fee_refresh",
+                                 &meta->fees.refresh),
+    TALER_PQ_RESULT_SPEC_AMOUNT ("fee_refund",
+                                 &meta->fees.refund),
+    GNUNET_PQ_result_spec_uint32 ("age_mask",
+                                  &meta->age_mask.bits),
+    GNUNET_PQ_result_spec_end
+  };
+
+      /* used in #postgres_lookup_denomination_key() */
+  PREPARE (pg,
+           "lookup_denomination_key",
+           "SELECT"
+           " valid_from"
+           ",expire_withdraw"
+           ",expire_deposit"
+           ",expire_legal"
+           ",coin_val"
+           ",coin_frac"
+           ",fee_withdraw_val"
+           ",fee_withdraw_frac"
+           ",fee_deposit_val"
+           ",fee_deposit_frac"
+           ",fee_refresh_val"
+           ",fee_refresh_frac"
+           ",fee_refund_val"
+           ",fee_refund_frac"
+           ",age_mask"
+           " FROM denominations"
+           " WHERE denom_pub_hash=$1;");
+  return GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
+                                                   "lookup_denomination_key",
+                                                   params,
+                                                   rs);
+}
diff --git a/src/exchangedb/pg_lookup_denomination_key.h 
b/src/exchangedb/pg_lookup_denomination_key.h
new file mode 100644
index 00000000..b7317ac4
--- /dev/null
+++ b/src/exchangedb/pg_lookup_denomination_key.h
@@ -0,0 +1,41 @@
+/*
+   This file is part of TALER
+   Copyright (C) 2022 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 exchangedb/pg_lookup_denomination_key.h
+ * @brief implementation of the lookup_denomination_key function for Postgres
+ * @author Christian Grothoff
+ */
+#ifndef PG_LOOKUP_DENOMINATION_KEY_H
+#define PG_LOOKUP_DENOMINATION_KEY_H
+
+#include "taler_util.h"
+#include "taler_json_lib.h"
+#include "taler_exchangedb_plugin.h"
+/**
+ * Lookup information about current denomination key.
+ *
+ * @param cls closure
+ * @param h_denom_pub hash of the denomination public key
+ * @param[out] meta set to various meta data about the key
+ * @return transaction status code
+ */
+enum GNUNET_DB_QueryStatus
+TEH_PG_lookup_denomination_key (
+  void *cls,
+  const struct TALER_DenominationHashP *h_denom_pub,
+  struct TALER_EXCHANGEDB_DenominationKeyMetaData *meta);
+
+#endif
diff --git a/src/exchangedb/pg_lookup_signing_key.c 
b/src/exchangedb/pg_lookup_signing_key.c
new file mode 100644
index 00000000..3f31a6f4
--- /dev/null
+++ b/src/exchangedb/pg_lookup_signing_key.c
@@ -0,0 +1,65 @@
+/*
+   This file is part of TALER
+   Copyright (C) 2022 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 exchangedb/pg_lookup_signing_key.c
+ * @brief Implementation of the lookup_signing_key function for Postgres
+ * @author Christian Grothoff
+ */
+#include "platform.h"
+#include "taler_error_codes.h"
+#include "taler_dbevents.h"
+#include "taler_pq_lib.h"
+#include "pg_lookup_signing_key.h"
+#include "pg_helper.h"
+
+
+enum GNUNET_DB_QueryStatus
+TEH_PG_lookup_signing_key (
+  void *cls,
+  const struct TALER_ExchangePublicKeyP *exchange_pub,
+  struct TALER_EXCHANGEDB_SignkeyMetaData *meta)
+{
+  struct PostgresClosure *pg = cls;
+  struct GNUNET_PQ_QueryParam params[] = {
+    GNUNET_PQ_query_param_auto_from_type (exchange_pub),
+    GNUNET_PQ_query_param_end
+  };
+  struct GNUNET_PQ_ResultSpec rs[] = {
+    GNUNET_PQ_result_spec_timestamp ("valid_from",
+                                     &meta->start),
+    GNUNET_PQ_result_spec_timestamp ("expire_sign",
+                                     &meta->expire_sign),
+    GNUNET_PQ_result_spec_timestamp ("expire_legal",
+                                     &meta->expire_legal),
+    GNUNET_PQ_result_spec_end
+  };
+
+
+  PREPARE (pg,
+           "lookup_signing_key",
+           "SELECT"
+           " valid_from"
+           ",expire_sign"
+           ",expire_legal"
+           " FROM exchange_sign_keys"
+           " WHERE exchange_pub=$1");
+
+  return GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
+                                                   "lookup_signing_key",
+                                                   params,
+                                                   rs);
+}
+
diff --git a/src/exchangedb/pg_lookup_signing_key.h 
b/src/exchangedb/pg_lookup_signing_key.h
new file mode 100644
index 00000000..487d60d2
--- /dev/null
+++ b/src/exchangedb/pg_lookup_signing_key.h
@@ -0,0 +1,42 @@
+/*
+   This file is part of TALER
+   Copyright (C) 2022 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 exchangedb/pg_lookup_signing_key.h
+ * @brief implementation of the lookup_signing_key function for Postgres
+ * @author Christian Grothoff
+ */
+#ifndef PG_LOOKUP_SIGNING_KEY_H
+#define PG_LOOKUP_SIGNING_KEY_H
+
+#include "taler_util.h"
+#include "taler_json_lib.h"
+#include "taler_exchangedb_plugin.h"
+
+
+/**
+ * Lookup signing key meta data.
+ *
+ * @param cls closure
+ * @param exchange_pub the exchange online signing public key
+ * @param[out] meta meta data about @a exchange_pub
+ * @return transaction status code
+ */
+enum GNUNET_DB_QueryStatus
+TEH_PG_lookup_signing_key (
+  void *cls,
+  const struct TALER_ExchangePublicKeyP *exchange_pub,
+  struct TALER_EXCHANGEDB_SignkeyMetaData *meta);
+#endif
diff --git a/src/exchangedb/pg_lookup_signkey_revocation.c 
b/src/exchangedb/pg_lookup_signkey_revocation.c
new file mode 100644
index 00000000..374aa7d5
--- /dev/null
+++ b/src/exchangedb/pg_lookup_signkey_revocation.c
@@ -0,0 +1,61 @@
+/*
+   This file is part of TALER
+   Copyright (C) 2022 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 exchangedb/pg_lookup_signkey_revocation.c
+ * @brief Implementation of the lookup_signkey_revocation function for Postgres
+ * @author Christian Grothoff
+ */
+#include "platform.h"
+#include "taler_error_codes.h"
+#include "taler_dbevents.h"
+#include "taler_pq_lib.h"
+#include "pg_lookup_signkey_revocation.h"
+#include "pg_helper.h"
+
+
+
+enum GNUNET_DB_QueryStatus
+TEH_PG_lookup_signkey_revocation (
+  void *cls,
+  const struct TALER_ExchangePublicKeyP *exchange_pub,
+  struct TALER_MasterSignatureP *master_sig)
+{
+  struct PostgresClosure *pg = cls;
+  struct GNUNET_PQ_QueryParam params[] = {
+    GNUNET_PQ_query_param_auto_from_type (exchange_pub),
+    GNUNET_PQ_query_param_end
+  };
+  struct GNUNET_PQ_ResultSpec rs[] = {
+    GNUNET_PQ_result_spec_auto_from_type ("master_sig",
+                                          master_sig),
+    GNUNET_PQ_result_spec_end
+  };
+
+
+  PREPARE (pg,
+           "lookup_signkey_revocation",
+           "SELECT "
+           " master_sig"
+           " FROM signkey_revocations"
+           " WHERE esk_serial="
+           "   (SELECT esk_serial"
+           "      FROM exchange_sign_keys"
+           "     WHERE exchange_pub=$1);");
+  return GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
+                                                   "lookup_signkey_revocation",
+                                                   params,
+                                                   rs);
+}
diff --git a/src/exchangedb/pg_lookup_signkey_revocation.h 
b/src/exchangedb/pg_lookup_signkey_revocation.h
new file mode 100644
index 00000000..de0fb1d7
--- /dev/null
+++ b/src/exchangedb/pg_lookup_signkey_revocation.h
@@ -0,0 +1,42 @@
+/*
+   This file is part of TALER
+   Copyright (C) 2022 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 exchangedb/pg_lookup_signkey_revocation.h
+ * @brief implementation of the lookup_signkey_revocation function for Postgres
+ * @author Christian Grothoff
+ */
+#ifndef PG_LOOKUP_SIGNKEY_REVOCATION_H
+#define PG_LOOKUP_SIGNKEY_REVOCATION_H
+
+#include "taler_util.h"
+#include "taler_json_lib.h"
+#include "taler_exchangedb_plugin.h"
+
+/**
+ * Obtain information about a revoked online signing key.
+ *
+ * @param cls closure
+ * @param exchange_pub exchange online signing key
+ * @param[out] master_sig set to signature affirming the revocation (if 
revoked)
+ * @return transaction status code
+ */
+enum GNUNET_DB_QueryStatus
+TEH_PG_lookup_signkey_revocation (
+  void *cls,
+  const struct TALER_ExchangePublicKeyP *exchange_pub,
+  struct TALER_MasterSignatureP *master_sig);
+
+#endif
diff --git a/src/exchangedb/pg_lookup_transfer_by_deposit.c 
b/src/exchangedb/pg_lookup_transfer_by_deposit.c
new file mode 100644
index 00000000..686b67cc
--- /dev/null
+++ b/src/exchangedb/pg_lookup_transfer_by_deposit.c
@@ -0,0 +1,203 @@
+/*
+   This file is part of TALER
+   Copyright (C) 2022 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 exchangedb/pg_lookup_transfer_by_deposit.c
+ * @brief Implementation of the lookup_transfer_by_deposit function for 
Postgres
+ * @author Christian Grothoff
+ */
+#include "platform.h"
+#include "taler_error_codes.h"
+#include "taler_dbevents.h"
+#include "taler_pq_lib.h"
+#include "pg_lookup_transfer_by_deposit.h"
+#include "pg_helper.h"
+
+
+
+enum GNUNET_DB_QueryStatus
+TEH_PG_lookup_transfer_by_deposit (
+  void *cls,
+  const struct TALER_PrivateContractHashP *h_contract_terms,
+  const struct TALER_MerchantWireHashP *h_wire,
+  const struct TALER_CoinSpendPublicKeyP *coin_pub,
+  const struct TALER_MerchantPublicKeyP *merchant_pub,
+  bool *pending,
+  struct TALER_WireTransferIdentifierRawP *wtid,
+  struct GNUNET_TIME_Timestamp *exec_time,
+  struct TALER_Amount *amount_with_fee,
+  struct TALER_Amount *deposit_fee,
+  struct TALER_EXCHANGEDB_KycStatus *kyc)
+{
+  struct PostgresClosure *pg = cls;
+  enum GNUNET_DB_QueryStatus qs;
+  struct GNUNET_PQ_QueryParam params[] = {
+    GNUNET_PQ_query_param_auto_from_type (coin_pub),
+    GNUNET_PQ_query_param_auto_from_type (h_contract_terms),
+    GNUNET_PQ_query_param_auto_from_type (merchant_pub),
+    GNUNET_PQ_query_param_end
+  };
+  char *payto_uri;
+  struct TALER_WireSaltP wire_salt;
+  struct GNUNET_PQ_ResultSpec rs[] = {
+    GNUNET_PQ_result_spec_auto_from_type ("wtid_raw",
+                                          wtid),
+    GNUNET_PQ_result_spec_auto_from_type ("wire_salt",
+                                          &wire_salt),
+    GNUNET_PQ_result_spec_string ("payto_uri",
+                                  &payto_uri),
+    GNUNET_PQ_result_spec_timestamp ("execution_date",
+                                     exec_time),
+    TALER_PQ_RESULT_SPEC_AMOUNT ("amount_with_fee",
+                                 amount_with_fee),
+    TALER_PQ_RESULT_SPEC_AMOUNT ("fee_deposit",
+                                 deposit_fee),
+    GNUNET_PQ_result_spec_end
+  };
+
+  memset (kyc,
+          0,
+          sizeof (*kyc));
+  /* check if the aggregation record exists and get it */
+
+    /* Used in #postgres_lookup_transfer_by_deposit */
+  PREPARE (pg,
+           "lookup_deposit_wtid",
+           "SELECT"
+           " aggregation_tracking.wtid_raw"
+           ",wire_out.execution_date"
+           ",dep.amount_with_fee_val"
+           ",dep.amount_with_fee_frac"
+           ",dep.wire_salt"
+           ",wt.payto_uri"
+           ",denom.fee_deposit_val"
+           ",denom.fee_deposit_frac"
+           " FROM deposits dep"
+           "    JOIN wire_targets wt"
+           "      USING (wire_target_h_payto)"
+           "    JOIN aggregation_tracking"
+           "      USING (deposit_serial_id)"
+           "    JOIN known_coins kc"
+           "      ON (kc.coin_pub = dep.coin_pub)"
+           "    JOIN denominations denom"
+           "      USING (denominations_serial)"
+           "    JOIN wire_out"
+           "      USING (wtid_raw)"
+           " WHERE dep.coin_pub=$1"
+           "   AND dep.merchant_pub=$3"
+           "   AND dep.h_contract_terms=$2");
+
+  qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
+                                                 "lookup_deposit_wtid",
+                                                 params,
+                                                 rs);
+  if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT == qs)
+  {
+    struct TALER_MerchantWireHashP wh;
+
+    TALER_merchant_wire_signature_hash (payto_uri,
+                                        &wire_salt,
+                                        &wh);
+    GNUNET_PQ_cleanup_result (rs);
+    if (0 ==
+        GNUNET_memcmp (&wh,
+                       h_wire))
+    {
+      *pending = false;
+      kyc->ok = true;
+      return qs;
+    }
+    qs = GNUNET_DB_STATUS_SUCCESS_NO_RESULTS;
+  }
+  if (0 > qs)
+    return qs;
+  *pending = true;
+  memset (wtid,
+          0,
+          sizeof (*wtid));
+  GNUNET_assert (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS == qs);
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "lookup_deposit_wtid returned 0 matching rows\n");
+  {
+    /* Check if transaction exists in deposits, so that we just
+       do not have a WTID yet. In that case, return without wtid
+       (by setting 'pending' true). */
+    struct GNUNET_PQ_ResultSpec rs2[] = {
+      GNUNET_PQ_result_spec_auto_from_type ("wire_salt",
+                                            &wire_salt),
+      GNUNET_PQ_result_spec_string ("payto_uri",
+                                    &payto_uri),
+      GNUNET_PQ_result_spec_allow_null (
+        GNUNET_PQ_result_spec_uint64 ("legitimization_requirement_serial_id",
+                                      &kyc->requirement_row),
+        NULL),
+      TALER_PQ_RESULT_SPEC_AMOUNT ("amount_with_fee",
+                                   amount_with_fee),
+      TALER_PQ_RESULT_SPEC_AMOUNT ("fee_deposit",
+                                   deposit_fee),
+      GNUNET_PQ_result_spec_timestamp ("wire_deadline",
+                                       exec_time),
+      GNUNET_PQ_result_spec_end
+    };
+
+        /* Fetch an existing deposit request.
+       Used in #postgres_lookup_transfer_by_deposit(). */
+    PREPARE (pg,
+             "get_deposit_without_wtid",
+             "SELECT"
+             " agt.legitimization_requirement_serial_id"
+             ",dep.wire_salt"
+             ",wt.payto_uri"
+             ",dep.amount_with_fee_val"
+             ",dep.amount_with_fee_frac"
+             ",denom.fee_deposit_val"
+             ",denom.fee_deposit_frac"
+             ",dep.wire_deadline"
+             " FROM deposits dep"
+             " JOIN wire_targets wt"
+             "   USING (wire_target_h_payto)"
+             " JOIN known_coins kc"
+             "   ON (kc.coin_pub = dep.coin_pub)"
+             " JOIN denominations denom"
+             "   USING (denominations_serial)"
+             " LEFT JOIN aggregation_transient agt "
+             "   ON ( (dep.wire_target_h_payto = agt.wire_target_h_payto) AND"
+             "        (dep.merchant_pub = agt.merchant_pub) )"
+             " WHERE dep.coin_pub=$1"
+             "   AND dep.merchant_pub=$3"
+             "   AND dep.h_contract_terms=$2"
+             " LIMIT 1;");
+    qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
+                                                   "get_deposit_without_wtid",
+                                                   params,
+                                                   rs2);
+    if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT == qs)
+    {
+      struct TALER_MerchantWireHashP wh;
+
+      if (0 == kyc->requirement_row)
+        kyc->ok = true; /* technically: unknown */
+      TALER_merchant_wire_signature_hash (payto_uri,
+                                          &wire_salt,
+                                          &wh);
+      GNUNET_PQ_cleanup_result (rs);
+      if (0 !=
+          GNUNET_memcmp (&wh,
+                         h_wire))
+        return GNUNET_DB_STATUS_SUCCESS_NO_RESULTS;
+    }
+    return qs;
+  }
+}
diff --git a/src/exchangedb/pg_lookup_transfer_by_deposit.h 
b/src/exchangedb/pg_lookup_transfer_by_deposit.h
new file mode 100644
index 00000000..ff5554dc
--- /dev/null
+++ b/src/exchangedb/pg_lookup_transfer_by_deposit.h
@@ -0,0 +1,61 @@
+/*
+   This file is part of TALER
+   Copyright (C) 2022 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 exchangedb/pg_lookup_transfer_by_deposit.h
+ * @brief implementation of the lookup_transfer_by_deposit function for 
Postgres
+ * @author Christian Grothoff
+ */
+#ifndef PG_LOOKUP_TRANSFER_BY_DEPOSIT_H
+#define PG_LOOKUP_TRANSFER_BY_DEPOSIT_H
+
+#include "taler_util.h"
+#include "taler_json_lib.h"
+#include "taler_exchangedb_plugin.h"
+
+/**
+ * Try to find the wire transfer details for a deposit operation.
+ * If we did not execute the deposit yet, return when it is supposed
+ * to be executed.
+ *
+ * @param cls closure
+ * @param h_contract_terms hash of the proposal data
+ * @param h_wire hash of merchant wire details
+ * @param coin_pub public key of deposited coin
+ * @param merchant_pub merchant public key
+ * @param[out] pending set to true if the transaction is still pending
+ * @param[out] wtid wire transfer identifier, only set if @a pending is false
+ * @param[out] exec_time when was the transaction done, or
+ *         when we expect it to be done (if @a pending is false)
+ * @param[out] amount_with_fee set to the total deposited amount
+ * @param[out] deposit_fee set to how much the exchange did charge for the 
deposit
+ * @param[out] kyc set to the kyc status of the receiver (if @a pending)
+ * @return transaction status code
+ */
+enum GNUNET_DB_QueryStatus
+TEH_PG_lookup_transfer_by_deposit (
+  void *cls,
+  const struct TALER_PrivateContractHashP *h_contract_terms,
+  const struct TALER_MerchantWireHashP *h_wire,
+  const struct TALER_CoinSpendPublicKeyP *coin_pub,
+  const struct TALER_MerchantPublicKeyP *merchant_pub,
+  bool *pending,
+  struct TALER_WireTransferIdentifierRawP *wtid,
+  struct GNUNET_TIME_Timestamp *exec_time,
+  struct TALER_Amount *amount_with_fee,
+  struct TALER_Amount *deposit_fee,
+  struct TALER_EXCHANGEDB_KycStatus *kyc);
+
+#endif
diff --git a/src/exchangedb/pg_lookup_wire_timestamp.c 
b/src/exchangedb/pg_lookup_wire_timestamp.c
new file mode 100644
index 00000000..19e915d4
--- /dev/null
+++ b/src/exchangedb/pg_lookup_wire_timestamp.c
@@ -0,0 +1,56 @@
+/*
+   This file is part of TALER
+   Copyright (C) 2022 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 exchangedb/pg_lookup_wire_timestamp.c
+ * @brief Implementation of the lookup_wire_timestamp function for Postgres
+ * @author Christian Grothoff
+ */
+#include "platform.h"
+#include "taler_error_codes.h"
+#include "taler_dbevents.h"
+#include "taler_pq_lib.h"
+#include "pg_lookup_wire_timestamp.h"
+#include "pg_helper.h"
+
+
+enum GNUNET_DB_QueryStatus
+TEH_PG_lookup_wire_timestamp (void *cls,
+                                const char *payto_uri,
+                                struct GNUNET_TIME_Timestamp *last_date)
+{
+  struct PostgresClosure *pg = cls;
+  struct GNUNET_PQ_QueryParam params[] = {
+    GNUNET_PQ_query_param_string (payto_uri),
+    GNUNET_PQ_query_param_end
+  };
+  struct GNUNET_PQ_ResultSpec rs[] = {
+    GNUNET_PQ_result_spec_timestamp ("last_change",
+                                     last_date),
+    GNUNET_PQ_result_spec_end
+  };
+
+
+  PREPARE (pg,
+           "lookup_wire_timestamp",
+           "SELECT"
+           " last_change"
+           " FROM wire_accounts"
+           " WHERE payto_uri=$1;");
+  return GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
+                                                   "lookup_wire_timestamp",
+                                                   params,
+                                                   rs);
+}
diff --git a/src/exchangedb/pg_lookup_wire_timestamp.h 
b/src/exchangedb/pg_lookup_wire_timestamp.h
new file mode 100644
index 00000000..069dd940
--- /dev/null
+++ b/src/exchangedb/pg_lookup_wire_timestamp.h
@@ -0,0 +1,40 @@
+/*
+   This file is part of TALER
+   Copyright (C) 2022 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 exchangedb/pg_lookup_wire_timestamp.h
+ * @brief implementation of the lookup_wire_timestamp function for Postgres
+ * @author Christian Grothoff
+ */
+#ifndef PG_LOOKUP_WIRE_TIMESTAMP_H
+#define PG_LOOKUP_WIRE_TIMESTAMP_H
+
+#include "taler_util.h"
+#include "taler_json_lib.h"
+#include "taler_exchangedb_plugin.h"
+/**
+ * Check the last date an exchange wire account was modified.
+ *
+ * @param cls closure
+ * @param payto_uri key to look up information for
+ * @param[out] last_date last modification date to auditor status
+ * @return transaction status code
+ */
+enum GNUNET_DB_QueryStatus
+TEH_PG_lookup_wire_timestamp (void *cls,
+                                const char *payto_uri,
+                              struct GNUNET_TIME_Timestamp *last_date);
+
+#endif
diff --git a/src/exchangedb/pg_lookup_wire_transfer.c 
b/src/exchangedb/pg_lookup_wire_transfer.c
new file mode 100644
index 00000000..39425170
--- /dev/null
+++ b/src/exchangedb/pg_lookup_wire_transfer.c
@@ -0,0 +1,187 @@
+/*
+   This file is part of TALER
+   Copyright (C) 2022 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 exchangedb/pg_lookup_wire_tranfer.c
+ * @brief Implementation of the lookup_wire_tranfer function for Postgres
+ * @author Christian Grothoff
+ */
+#include "platform.h"
+#include "taler_error_codes.h"
+#include "taler_dbevents.h"
+#include "taler_pq_lib.h"
+#include "pg_lookup_wire_transfer.h"
+#include "pg_helper.h"
+
+/**
+ * Closure for #handle_wt_result.
+ */
+struct WireTransferResultContext
+{
+  /**
+   * Function to call on each result.
+   */
+  TALER_EXCHANGEDB_AggregationDataCallback cb;
+
+  /**
+   * Closure for @e cb.
+   */
+  void *cb_cls;
+
+  /**
+   * Plugin context.
+   */
+  struct PostgresClosure *pg;
+
+  /**
+   * Set to #GNUNET_SYSERR on serious errors.
+   */
+  int status;
+};
+
+
+/**
+ * Function to be called with the results of a SELECT statement
+ * that has returned @a num_results results.  Helper function
+ * for #postgres_lookup_wire_transfer().
+ *
+ * @param cls closure of type `struct WireTransferResultContext *`
+ * @param result the postgres result
+ * @param num_results the number of results in @a result
+ */
+static void
+handle_wt_result (void *cls,
+                  PGresult *result,
+                  unsigned int num_results)
+{
+  struct WireTransferResultContext *ctx = cls;
+  struct PostgresClosure *pg = ctx->pg;
+
+  for (unsigned int i = 0; i<num_results; i++)
+  {
+    uint64_t rowid;
+    struct TALER_PrivateContractHashP h_contract_terms;
+    struct TALER_CoinSpendPublicKeyP coin_pub;
+    struct TALER_PaytoHashP h_payto;
+    struct TALER_MerchantPublicKeyP merchant_pub;
+    struct GNUNET_TIME_Timestamp exec_time;
+    struct TALER_Amount amount_with_fee;
+    struct TALER_Amount deposit_fee;
+    struct TALER_DenominationPublicKey denom_pub;
+    char *payto_uri;
+    struct GNUNET_PQ_ResultSpec rs[] = {
+      GNUNET_PQ_result_spec_uint64 ("aggregation_serial_id", &rowid),
+      GNUNET_PQ_result_spec_auto_from_type ("h_contract_terms",
+                                            &h_contract_terms),
+      GNUNET_PQ_result_spec_string ("payto_uri",
+                                    &payto_uri),
+      GNUNET_PQ_result_spec_auto_from_type ("wire_target_h_payto",
+                                            &h_payto),
+      TALER_PQ_result_spec_denom_pub ("denom_pub",
+                                      &denom_pub),
+      GNUNET_PQ_result_spec_auto_from_type ("coin_pub",
+                                            &coin_pub),
+      GNUNET_PQ_result_spec_auto_from_type ("merchant_pub",
+                                            &merchant_pub),
+      GNUNET_PQ_result_spec_timestamp ("execution_date",
+                                       &exec_time),
+      TALER_PQ_RESULT_SPEC_AMOUNT ("amount_with_fee",
+                                   &amount_with_fee),
+      TALER_PQ_RESULT_SPEC_AMOUNT ("fee_deposit",
+                                   &deposit_fee),
+      GNUNET_PQ_result_spec_end
+    };
+
+    if (GNUNET_OK !=
+        GNUNET_PQ_extract_result (result,
+                                  rs,
+                                  i))
+    {
+      GNUNET_break (0);
+      ctx->status = GNUNET_SYSERR;
+      return;
+    }
+    ctx->cb (ctx->cb_cls,
+             rowid,
+             &merchant_pub,
+             payto_uri,
+             &h_payto,
+             exec_time,
+             &h_contract_terms,
+             &denom_pub,
+             &coin_pub,
+             &amount_with_fee,
+             &deposit_fee);
+    GNUNET_PQ_cleanup_result (rs);
+  }
+}
+
+enum GNUNET_DB_QueryStatus
+TEH_PG_lookup_wire_transfer (
+  void *cls,
+  const struct TALER_WireTransferIdentifierRawP *wtid,
+  TALER_EXCHANGEDB_AggregationDataCallback cb,
+  void *cb_cls)
+{
+  struct PostgresClosure *pg = cls;
+  struct GNUNET_PQ_QueryParam params[] = {
+    GNUNET_PQ_query_param_auto_from_type (wtid),
+    GNUNET_PQ_query_param_end
+  };
+  struct WireTransferResultContext ctx;
+  enum GNUNET_DB_QueryStatus qs;
+
+  ctx.cb = cb;
+  ctx.cb_cls = cb_cls;
+  ctx.pg = pg;
+  ctx.status = GNUNET_OK;
+  /* check if the melt record exists and get it */
+    /* Used in #postgres_lookup_wire_transfer */
+  PREPARE (pg,
+           "lookup_transactions",
+           "SELECT"
+           " aggregation_serial_id"
+           ",deposits.h_contract_terms"
+           ",payto_uri"
+           ",wire_targets.wire_target_h_payto"
+           ",kc.coin_pub"
+           ",deposits.merchant_pub"
+           ",wire_out.execution_date"
+           ",deposits.amount_with_fee_val"
+           ",deposits.amount_with_fee_frac"
+           ",denom.fee_deposit_val"
+           ",denom.fee_deposit_frac"
+           ",denom.denom_pub"
+           " FROM aggregation_tracking"
+           "    JOIN deposits"
+           "      USING (deposit_serial_id)"
+           "    JOIN wire_targets"
+           "      USING (wire_target_h_payto)"
+           "    JOIN known_coins kc"
+           "      USING (coin_pub)"
+           "    JOIN denominations denom"
+           "      USING (denominations_serial)"
+           "    JOIN wire_out"
+           "      USING (wtid_raw)"
+           " WHERE wtid_raw=$1;");
+  qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn,
+                                             "lookup_transactions",
+                                             params,
+                                             &handle_wt_result,
+                                             &ctx);
+  if (GNUNET_OK != ctx.status)
+    return GNUNET_DB_STATUS_HARD_ERROR;
+  return qs;
+}
diff --git a/src/exchangedb/pg_lookup_wire_transfer.h 
b/src/exchangedb/pg_lookup_wire_transfer.h
new file mode 100644
index 00000000..1d66a211
--- /dev/null
+++ b/src/exchangedb/pg_lookup_wire_transfer.h
@@ -0,0 +1,45 @@
+/*
+   This file is part of TALER
+   Copyright (C) 2022 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 exchangedb/pg_lookup_wire_tranfer.h
+ * @brief implementation of the lookup_wire_tranfer function for Postgres
+ * @author Christian Grothoff
+ */
+#ifndef PG_LOOKUP_WIRE_TRANSFER_H
+#define PG_LOOKUP_WIRE_TRANSFER_H
+
+#include "taler_util.h"
+#include "taler_json_lib.h"
+#include "taler_exchangedb_plugin.h"
+
+/**
+ * Lookup the list of Taler transactions that were aggregated
+ * into a wire transfer by the respective @a wtid.
+ *
+ * @param cls closure
+ * @param wtid the raw wire transfer identifier we used
+ * @param cb function to call on each transaction found
+ * @param cb_cls closure for @a cb
+ * @return query status of the transaction
+ */
+enum GNUNET_DB_QueryStatus
+TEH_PG_lookup_wire_transfer (
+  void *cls,
+  const struct TALER_WireTransferIdentifierRawP *wtid,
+  TALER_EXCHANGEDB_AggregationDataCallback cb,
+  void *cb_cls);
+
+#endif
diff --git a/src/exchangedb/pg_persist_policy_details.c 
b/src/exchangedb/pg_persist_policy_details.c
new file mode 100644
index 00000000..28e2e4c5
--- /dev/null
+++ b/src/exchangedb/pg_persist_policy_details.c
@@ -0,0 +1,67 @@
+/*
+   This file is part of TALER
+   Copyright (C) 2022 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 exchangedb/pg_persist_policy_details.c
+ * @brief Implementation of the persist_policy_details function for Postgres
+ * @author Christian Grothoff
+ */
+#include "platform.h"
+#include "taler_error_codes.h"
+#include "taler_dbevents.h"
+#include "taler_pq_lib.h"
+#include "pg_persist_policy_details.h"
+#include "pg_helper.h"
+
+
+enum GNUNET_DB_QueryStatus
+TEH_PG_persist_policy_details (
+  void *cls,
+  const struct TALER_PolicyDetails *details,
+  uint64_t *policy_details_serial_id,
+  struct TALER_Amount *accumulated_total,
+  enum TALER_PolicyFulfillmentState *fulfillment_state)
+{
+  struct PostgresClosure *pg = cls;
+  struct GNUNET_PQ_QueryParam params[] = {
+    GNUNET_PQ_query_param_auto_from_type (&details->hash_code),
+    TALER_PQ_query_param_json (details->policy_json),
+    GNUNET_PQ_query_param_timestamp (&details->deadline),
+    TALER_PQ_query_param_amount (&details->commitment),
+    TALER_PQ_query_param_amount (&details->accumulated_total),
+    TALER_PQ_query_param_amount (&details->policy_fee),
+    TALER_PQ_query_param_amount (&details->transferable_amount),
+    GNUNET_PQ_query_param_auto_from_type (&details->fulfillment_state),
+    (details->no_policy_fulfillment_id)
+     ?  GNUNET_PQ_query_param_null ()
+     : GNUNET_PQ_query_param_uint64 (&details->policy_fulfillment_id),
+    GNUNET_PQ_query_param_end
+  };
+  struct GNUNET_PQ_ResultSpec rs[] = {
+    GNUNET_PQ_result_spec_uint64 ("policy_details_serial_id",
+                                  policy_details_serial_id),
+    TALER_PQ_RESULT_SPEC_AMOUNT ("accumulated_total",
+                                 accumulated_total),
+    GNUNET_PQ_result_spec_uint32 ("fulfillment_state",
+                                  fulfillment_state),
+    GNUNET_PQ_result_spec_end
+  };
+
+  
+  return GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
+                                                   
"call_insert_or_update_policy_details",
+                                                   params,
+                                                   rs);
+}
diff --git a/src/exchangedb/pg_persist_policy_details.h 
b/src/exchangedb/pg_persist_policy_details.h
new file mode 100644
index 00000000..ed9fd95d
--- /dev/null
+++ b/src/exchangedb/pg_persist_policy_details.h
@@ -0,0 +1,45 @@
+/*
+   This file is part of TALER
+   Copyright (C) 2022 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 exchangedb/pg_persist_policy_details.h
+ * @brief implementation of the persist_policy_details function for Postgres
+ * @author Christian Grothoff
+ */
+#ifndef PG_PERSIST_POLICY_DETAILS_H
+#define PG_PERSIST_POLICY_DETAILS_H
+
+#include "taler_util.h"
+#include "taler_json_lib.h"
+#include "taler_exchangedb_plugin.h"
+/* Persist the details to a policy in the policy_details table.  If there
+ * already exists a policy, update the fields accordingly.
+ *
+ * @param details The policy details that should be persisted.  If an entry for
+ *        the given details->hash_code exists, the values will be updated.
+ * @param[out] policy_details_serial_id The row ID of the policy details
+ * @param[out] accumulated_total The total amount accumulated in that policy
+ * @param[out] fulfillment_state The state of policy.  If the state was 
Insufficient prior to the call and the provided deposit raises the 
accumulated_total above the commitment, it will be set to Ready.
+ * @return query execution status
+ */
+enum GNUNET_DB_QueryStatus
+TEH_PG_persist_policy_details (
+  void *cls,
+  const struct TALER_PolicyDetails *details,
+  uint64_t *policy_details_serial_id,
+  struct TALER_Amount *accumulated_total,
+  enum TALER_PolicyFulfillmentState *fulfillment_state);
+
+#endif
diff --git a/src/exchangedb/pg_release_revolving_shard.c 
b/src/exchangedb/pg_release_revolving_shard.c
new file mode 100644
index 00000000..f176972b
--- /dev/null
+++ b/src/exchangedb/pg_release_revolving_shard.c
@@ -0,0 +1,59 @@
+/*
+   This file is part of TALER
+   Copyright (C) 2022 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 exchangedb/pg_release_revolving_shard.c
+ * @brief Implementation of the release_revolving_shard function for Postgres
+ * @author Christian Grothoff
+ */
+#include "platform.h"
+#include "taler_error_codes.h"
+#include "taler_dbevents.h"
+#include "taler_pq_lib.h"
+#include "pg_release_revolving_shard.h"
+#include "pg_helper.h"
+
+enum GNUNET_DB_QueryStatus
+TEH_PG_release_revolving_shard (void *cls,
+                                  const char *job_name,
+                                  uint32_t start_row,
+                                  uint32_t end_row)
+{
+  struct PostgresClosure *pg = cls;
+  struct GNUNET_PQ_QueryParam params[] = {
+    GNUNET_PQ_query_param_string (job_name),
+    GNUNET_PQ_query_param_uint32 (&start_row),
+    GNUNET_PQ_query_param_uint32 (&end_row),
+    GNUNET_PQ_query_param_end
+  };
+
+  GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+              "Releasing revolving shard %s %u-%u\n",
+              job_name,
+              (unsigned int) start_row,
+              (unsigned int) end_row);
+
+
+  PREPARE (pg,
+           "release_revolving_shard",
+           "UPDATE revolving_work_shards"
+           " SET active=FALSE"
+           " WHERE job_name=$1"
+           "   AND start_row=$2"
+           "   AND end_row=$3");
+  return GNUNET_PQ_eval_prepared_non_select (pg->conn,
+                                             "release_revolving_shard",
+                                             params);
+}
diff --git a/src/exchangedb/pg_release_revolving_shard.h 
b/src/exchangedb/pg_release_revolving_shard.h
new file mode 100644
index 00000000..f1712f53
--- /dev/null
+++ b/src/exchangedb/pg_release_revolving_shard.h
@@ -0,0 +1,44 @@
+/*
+   This file is part of TALER
+   Copyright (C) 2022 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 exchangedb/pg_release_revolving_shard.h
+ * @brief implementation of the release_revolving_shard function for Postgres
+ * @author Christian Grothoff
+ */
+#ifndef PG_RELEASE_REVOLVING_SHARD_H
+#define PG_RELEASE_REVOLVING_SHARD_H
+
+#include "taler_util.h"
+#include "taler_json_lib.h"
+#include "taler_exchangedb_plugin.h"
+/**
+ * Function called to release a revolving shard
+ * back into the work pool.  Clears the
+ * "completed" flag.
+ *
+ * @param cls the @e cls of this struct with the plugin-specific state
+ * @param job_name name of the operation to grab a word shard for
+ * @param start_row inclusive start row of the shard
+ * @param end_row exclusive end row of the shard
+ * @return transaction status code
+ */
+enum GNUNET_DB_QueryStatus
+TEH_PG_release_revolving_shard (void *cls,
+                                  const char *job_name,
+                                  uint32_t start_row,
+                                uint32_t end_row);
+
+#endif
diff --git a/src/exchangedb/pg_reserves_get.c b/src/exchangedb/pg_reserves_get.c
new file mode 100644
index 00000000..bea0022d
--- /dev/null
+++ b/src/exchangedb/pg_reserves_get.c
@@ -0,0 +1,61 @@
+/*
+   This file is part of TALER
+   Copyright (C) 2022 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 exchangedb/pg_reserves_get.c
+ * @brief Implementation of the reserves_get function for Postgres
+ * @author Christian Grothoff
+ */
+#include "platform.h"
+#include "taler_error_codes.h"
+#include "taler_dbevents.h"
+#include "taler_pq_lib.h"
+#include "pg_reserves_get.h"
+#include "pg_helper.h"
+
+enum GNUNET_DB_QueryStatus
+TEH_PG_reserves_get (void *cls,
+                       struct TALER_EXCHANGEDB_Reserve *reserve)
+{
+  struct PostgresClosure *pg = cls;
+  struct GNUNET_PQ_QueryParam params[] = {
+    GNUNET_PQ_query_param_auto_from_type (&reserve->pub),
+    GNUNET_PQ_query_param_end
+  };
+  struct GNUNET_PQ_ResultSpec rs[] = {
+    TALER_PQ_RESULT_SPEC_AMOUNT ("current_balance",
+                                 &reserve->balance),
+    GNUNET_PQ_result_spec_timestamp ("expiration_date",
+                                     &reserve->expiry),
+    GNUNET_PQ_result_spec_timestamp ("gc_date",
+                                     &reserve->gc),
+    GNUNET_PQ_result_spec_end
+  };
+    /* Used in #postgres_reserves_get() */
+  PREPARE (pg,
+           "reserves_get",
+           "SELECT"
+           " current_balance_val"
+           ",current_balance_frac"
+           ",expiration_date"
+           ",gc_date"
+           " FROM reserves"
+           " WHERE reserve_pub=$1"
+           " LIMIT 1;");
+  return GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
+                                                   "reserves_get",
+                                                   params,
+                                                   rs);
+}
diff --git a/src/exchangedb/pg_reserves_get.h b/src/exchangedb/pg_reserves_get.h
new file mode 100644
index 00000000..8a96d53e
--- /dev/null
+++ b/src/exchangedb/pg_reserves_get.h
@@ -0,0 +1,40 @@
+/*
+   This file is part of TALER
+   Copyright (C) 2022 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 exchangedb/pg_reserves_get.h
+ * @brief implementation of the reserves_get function for Postgres
+ * @author Christian Grothoff
+ */
+#ifndef PG_RESERVES_GET_H
+#define PG_RESERVES_GET_H
+
+#include "taler_util.h"
+#include "taler_json_lib.h"
+#include "taler_exchangedb_plugin.h"
+/**
+ * Get the summary of a reserve.
+ *
+ * @param cls the `struct PostgresClosure` with the plugin-specific state
+ * @param[in,out] reserve the reserve data.  The public key of the reserve 
should be
+ *          set in this structure; it is used to query the database.  The 
balance
+ *          and expiration are then filled accordingly.
+ * @return transaction status
+ */
+enum GNUNET_DB_QueryStatus
+TEH_PG_reserves_get (void *cls,
+                     struct TALER_EXCHANGEDB_Reserve *reserve);
+
+#endif
diff --git a/src/exchangedb/pg_reserves_get_origin.c 
b/src/exchangedb/pg_reserves_get_origin.c
new file mode 100644
index 00000000..fd6c5658
--- /dev/null
+++ b/src/exchangedb/pg_reserves_get_origin.c
@@ -0,0 +1,57 @@
+/*
+   This file is part of TALER
+   Copyright (C) 2022 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 exchangedb/pg_reserves_get_origin.c
+ * @brief Implementation of the reserves_get_origin function for Postgres
+ * @author Christian Grothoff
+ */
+#include "platform.h"
+#include "taler_error_codes.h"
+#include "taler_dbevents.h"
+#include "taler_pq_lib.h"
+#include "pg_reserves_get_origin.h"
+#include "pg_helper.h"
+
+
+enum GNUNET_DB_QueryStatus
+TEH_PG_reserves_get_origin (
+  void *cls,
+  const struct TALER_ReservePublicKeyP *reserve_pub,
+  struct TALER_PaytoHashP *h_payto)
+{
+  struct PostgresClosure *pg = cls;
+  struct GNUNET_PQ_QueryParam params[] = {
+    GNUNET_PQ_query_param_auto_from_type (reserve_pub),
+    GNUNET_PQ_query_param_end
+  };
+  struct GNUNET_PQ_ResultSpec rs[] = {
+    GNUNET_PQ_result_spec_auto_from_type ("wire_source_h_payto",
+                                          h_payto),
+    GNUNET_PQ_result_spec_end
+  };
+
+
+  PREPARE (pg,
+           "get_h_wire_source_of_reserve",
+           "SELECT"
+           " wire_source_h_payto"
+           " FROM reserves_in"
+           " WHERE reserve_pub=$1");
+    return GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
+                                                   
"get_h_wire_source_of_reserve",
+                                                   params,
+                                                   rs);
+}
diff --git a/src/exchangedb/pg_reserves_get_origin.h 
b/src/exchangedb/pg_reserves_get_origin.h
new file mode 100644
index 00000000..22085d8f
--- /dev/null
+++ b/src/exchangedb/pg_reserves_get_origin.h
@@ -0,0 +1,41 @@
+/*
+   This file is part of TALER
+   Copyright (C) 2022 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 exchangedb/pg_reserves_get_origin.h
+ * @brief implementation of the reserves_get_origin function for Postgres
+ * @author Christian Grothoff
+ */
+#ifndef PG_RESERVES_GET_ORIGIN_H
+#define PG_RESERVES_GET_ORIGIN_H
+
+#include "taler_util.h"
+#include "taler_json_lib.h"
+#include "taler_exchangedb_plugin.h"
+/**
+ * Get the origin of funds of a reserve.
+ *
+ * @param cls the `struct PostgresClosure` with the plugin-specific state
+ * @param reserve_pub public key of the reserve
+ * @param[out] h_payto set to hash of the wire source payto://-URI
+ * @return transaction status
+ */
+enum GNUNET_DB_QueryStatus
+TEH_PG_reserves_get_origin (
+  void *cls,
+  const struct TALER_ReservePublicKeyP *reserve_pub,
+  struct TALER_PaytoHashP *h_payto);
+
+#endif
diff --git a/src/exchangedb/pg_reserves_in_insert.c 
b/src/exchangedb/pg_reserves_in_insert.c
new file mode 100644
index 00000000..38524bd6
--- /dev/null
+++ b/src/exchangedb/pg_reserves_in_insert.c
@@ -0,0 +1,297 @@
+/*
+   This file is part of TALER
+   Copyright (C) 2022 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 exchangedb/pg_reserves_in_insert.c
+ * @brief Implementation of the reserves_in_insert function for Postgres
+ * @author Christian Grothoff
+ */
+#include "platform.h"
+#include "taler_error_codes.h"
+#include "taler_dbevents.h"
+#include "taler_pq_lib.h"
+#include "pg_reserves_in_insert.h"
+#include "pg_helper.h"
+#include "pg_start.h"
+#include "pg_start_read_committed.h"
+#include "pg_commit.h"
+#include "pg_reserves_get.h"
+#include "pg_reserves_update.h"
+#include "pg_setup_wire_target.h"
+#include "pg_event_notify.h"
+/**
+ * Generate event notification for the reserve
+ * change.
+ *
+ * @param pg plugin state
+ * @param reserve_pub reserve to notfiy on
+ */
+
+static void
+notify_on_reserve (struct PostgresClosure *pg,
+                   const struct TALER_ReservePublicKeyP *reserve_pub)
+{
+  struct TALER_ReserveEventP rep = {
+    .header.size = htons (sizeof (rep)),
+    .header.type = htons (TALER_DBEVENT_EXCHANGE_RESERVE_INCOMING),
+    .reserve_pub = *reserve_pub
+  };
+
+  GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+              "Notifying on reserve!\n");
+  TEH_PG_event_notify (pg,
+                         &rep.header,
+                         NULL,
+                         0);
+}
+
+enum GNUNET_DB_QueryStatus
+TEH_PG_reserves_in_insert (void *cls,
+                             const struct TALER_ReservePublicKeyP *reserve_pub,
+                             const struct TALER_Amount *balance,
+                             struct GNUNET_TIME_Timestamp execution_time,
+                             const char *sender_account_details,
+                             const char *exchange_account_section,
+                             uint64_t wire_ref)
+{
+  struct PostgresClosure *pg = cls;
+  enum GNUNET_DB_QueryStatus qs1;
+  struct TALER_EXCHANGEDB_Reserve reserve;
+  struct GNUNET_TIME_Timestamp expiry;
+  struct GNUNET_TIME_Timestamp gc;
+  uint64_t reserve_uuid;
+
+  reserve.pub = *reserve_pub;
+  expiry = GNUNET_TIME_absolute_to_timestamp (
+    GNUNET_TIME_absolute_add (execution_time.abs_time,
+                              pg->idle_reserve_expiration_time));
+  gc = GNUNET_TIME_absolute_to_timestamp (
+    GNUNET_TIME_absolute_add (GNUNET_TIME_absolute_get (),
+                              pg->legal_reserve_expiration_time));
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Creating reserve %s with expiration in %s\n",
+              TALER_B2S (reserve_pub),
+              GNUNET_STRINGS_relative_time_to_string (
+                pg->idle_reserve_expiration_time,
+                GNUNET_NO));
+  /* Optimistically assume this is a new reserve, create balance for the first
+     time; we do this before adding the actual transaction to "reserves_in",
+     as for a new reserve it can't be a duplicate 'add' operation, and as
+     the 'add' operation needs the reserve entry as a foreign key. */
+  {
+    struct GNUNET_PQ_QueryParam params[] = {
+      GNUNET_PQ_query_param_auto_from_type (reserve_pub),
+      TALER_PQ_query_param_amount (balance),
+      GNUNET_PQ_query_param_timestamp (&expiry),
+      GNUNET_PQ_query_param_timestamp (&gc),
+      GNUNET_PQ_query_param_end
+    };
+    struct GNUNET_PQ_ResultSpec rs[] = {
+      GNUNET_PQ_result_spec_uint64 ("reserve_uuid",
+                                    &reserve_uuid),
+      GNUNET_PQ_result_spec_end
+    };
+
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "Reserve does not exist; creating a new one\n");
+    /* Note: query uses 'on conflict do nothing' */
+
+
+
+    PREPARE (pg,
+             "reserve_create",
+             "INSERT INTO reserves "
+             "(reserve_pub"
+             ",current_balance_val"
+             ",current_balance_frac"
+             ",expiration_date"
+             ",gc_date"
+             ") VALUES "
+             "($1, $2, $3, $4, $5)"
+             " ON CONFLICT DO NOTHING"
+             " RETURNING reserve_uuid;");
+
+    qs1 = GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
+                                                    "reserve_create",
+                                                    params,
+                                                    rs);
+    if (qs1 < 0)
+      return qs1;
+  }
+
+  /* Create new incoming transaction, "ON CONFLICT DO NOTHING"
+     is again used to guard against duplicates. */
+  {
+    enum GNUNET_DB_QueryStatus qs2;
+    enum GNUNET_DB_QueryStatus qs3;
+    struct TALER_PaytoHashP h_payto;
+
+    qs3 = TEH_PG_setup_wire_target (pg,
+                             sender_account_details,
+                             &h_payto);
+    if (qs3 < 0)
+      return qs3;
+    /* We do not have the UUID, so insert by public key */
+    struct GNUNET_PQ_QueryParam params[] = {
+      GNUNET_PQ_query_param_auto_from_type (&reserve.pub),
+      GNUNET_PQ_query_param_uint64 (&wire_ref),
+      TALER_PQ_query_param_amount (balance),
+      GNUNET_PQ_query_param_string (exchange_account_section),
+      GNUNET_PQ_query_param_auto_from_type (&h_payto),
+      GNUNET_PQ_query_param_timestamp (&execution_time),
+      GNUNET_PQ_query_param_end
+    };
+
+
+    PREPARE (pg,
+             "reserves_in_add_transaction",
+             "INSERT INTO reserves_in "
+             "(reserve_pub"
+             ",wire_reference"
+             ",credit_val"
+             ",credit_frac"
+             ",exchange_account_section"
+             ",wire_source_h_payto"
+             ",execution_date"
+             ") VALUES ($1, $2, $3, $4, $5, $6, $7)"
+             " ON CONFLICT DO NOTHING;");
+    qs2 = GNUNET_PQ_eval_prepared_non_select (pg->conn,
+                                              "reserves_in_add_transaction",
+                                              params);
+    /* qs2 could be 0 as statement used 'ON CONFLICT DO NOTHING' */
+    if (0 >= qs2)
+    {
+      if ( (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS == qs2) &&
+           (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS != qs1) )
+      {
+        /* Conflict for the transaction, but the reserve was
+           just now created, that should be impossible. */
+        GNUNET_break (0); /* should be impossible: reserve was fresh,
+                             but transaction already known */
+        return GNUNET_DB_STATUS_HARD_ERROR;
+      }
+      /* Transaction was already known or error. We are finished. */
+      return qs2;
+    }
+  }
+  if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT == qs1)
+  {
+    /* New reserve, we are finished */
+    notify_on_reserve (pg,
+                       reserve_pub);
+    return GNUNET_DB_STATUS_SUCCESS_ONE_RESULT;
+  }
+
+  /* we were wrong with our optimistic assumption:
+     reserve did already exist, need to do an update instead */
+  {
+    /* We need to move away from 'read committed' to serializable.
+       Also, we know that it should be safe to commit at this point.
+       (We are only run in a larger transaction for performance.) */
+    enum GNUNET_DB_QueryStatus cs;
+
+    cs = TEH_PG_commit(pg);
+    if (cs < 0)
+      return cs;
+    if (GNUNET_OK !=
+        TEH_PG_start (pg,
+                        "reserve-update-serializable"))
+    {
+      GNUNET_break (0);
+      return GNUNET_DB_STATUS_HARD_ERROR;
+    }
+  }
+  {
+    enum GNUNET_DB_QueryStatus reserve_exists;
+
+    reserve_exists = TEH_PG_reserves_get (pg,
+                                            &reserve);
+    switch (reserve_exists)
+    {
+    case GNUNET_DB_STATUS_HARD_ERROR:
+      GNUNET_break (0);
+      return reserve_exists;
+    case GNUNET_DB_STATUS_SOFT_ERROR:
+      return reserve_exists;
+    case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS:
+      /* First we got a conflict, but then we cannot select? Very strange. */
+      GNUNET_break (0);
+      return GNUNET_DB_STATUS_SOFT_ERROR;
+    case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT:
+      /* continued below */
+      break;
+    }
+  }
+
+  {
+    struct TALER_EXCHANGEDB_Reserve updated_reserve;
+    enum GNUNET_DB_QueryStatus qs3;
+
+    /* If the reserve already existed, we need to still update the
+       balance; we do this after checking for duplication, as
+       otherwise we might have to actually pay the cost to roll this
+       back for duplicate transactions; like this, we should virtually
+       never actually have to rollback anything. */
+    updated_reserve.pub = reserve.pub;
+    if (0 >
+        TALER_amount_add (&updated_reserve.balance,
+                          &reserve.balance,
+                          balance))
+    {
+      /* currency overflow or incompatible currency */
+      GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                  "Attempt to deposit incompatible amount into reserve\n");
+      return GNUNET_DB_STATUS_HARD_ERROR;
+    }
+    updated_reserve.expiry = GNUNET_TIME_timestamp_max (expiry,
+                                                        reserve.expiry);
+    updated_reserve.gc = GNUNET_TIME_timestamp_max (gc,
+                                                    reserve.gc);
+    qs3 = TEH_PG_reserves_update (pg,
+                           &updated_reserve);
+    switch (qs3)
+    {
+    case GNUNET_DB_STATUS_HARD_ERROR:
+      GNUNET_break (0);
+      return qs3;
+    case GNUNET_DB_STATUS_SOFT_ERROR:
+      return qs3;
+    case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS:
+      /* How can the UPDATE not work here? Very strange. */
+      GNUNET_break (0);
+      return GNUNET_DB_STATUS_HARD_ERROR;
+    case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT:
+      /* continued below */
+      break;
+    }
+  }
+  notify_on_reserve (pg,
+                     reserve_pub);
+  /* Go back to original transaction mode */
+  {
+    enum GNUNET_DB_QueryStatus cs;
+
+    cs = TEH_PG_commit (pg);
+    if (cs < 0)
+      return cs;
+    if (GNUNET_OK !=
+       TEH_PG_start_read_committed (pg, "reserve-insert-continued"))
+    {
+      GNUNET_break (0);
+      return GNUNET_DB_STATUS_HARD_ERROR;
+    }
+  }
+  return GNUNET_DB_STATUS_SUCCESS_ONE_RESULT;
+}
diff --git a/src/exchangedb/pg_reserves_in_insert.h 
b/src/exchangedb/pg_reserves_in_insert.h
new file mode 100644
index 00000000..85401938
--- /dev/null
+++ b/src/exchangedb/pg_reserves_in_insert.h
@@ -0,0 +1,51 @@
+/*
+   This file is part of TALER
+   Copyright (C) 2022 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 exchangedb/pg_reserves_in_insert.h
+ * @brief implementation of the reserves_in_insert function for Postgres
+ * @author Christian Grothoff
+ */
+#ifndef PG_RESERVES_IN_INSERT_H
+#define PG_RESERVES_IN_INSERT_H
+
+#include "taler_util.h"
+#include "taler_json_lib.h"
+#include "taler_exchangedb_plugin.h"
+/**
+ * Insert an incoming transaction into reserves.  New reserves are also
+ * created through this function. Started within the scope of an ongoing
+ * transaction.
+ *
+ * @param cls the `struct PostgresClosure` with the plugin-specific state
+ * @param reserve_pub public key of the reserve
+ * @param balance the amount that has to be added to the reserve
+ * @param execution_time when was the amount added
+ * @param sender_account_details account information for the sender 
(payto://-URL)
+ * @param exchange_account_section name of the section in the configuration 
for the exchange's
+ *                       account into which the deposit was made
+ * @param wire_ref unique reference identifying the wire transfer
+ * @return transaction status code
+ */
+enum GNUNET_DB_QueryStatus
+TEH_PG_reserves_in_insert (void *cls,
+                             const struct TALER_ReservePublicKeyP *reserve_pub,
+                             const struct TALER_Amount *balance,
+                             struct GNUNET_TIME_Timestamp execution_time,
+                             const char *sender_account_details,
+                             const char *exchange_account_section,
+                           uint64_t wire_ref);
+
+#endif
diff --git a/src/exchangedb/pg_reserves_update.c 
b/src/exchangedb/pg_reserves_update.c
new file mode 100644
index 00000000..4a886102
--- /dev/null
+++ b/src/exchangedb/pg_reserves_update.c
@@ -0,0 +1,53 @@
+/*
+   This file is part of TALER
+   Copyright (C) 2022 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 exchangedb/pg_reserves_update.c
+ * @brief Implementation of the reserves_update function for Postgres
+ * @author Christian Grothoff
+ */
+#include "platform.h"
+#include "taler_error_codes.h"
+#include "taler_dbevents.h"
+#include "taler_pq_lib.h"
+#include "pg_reserves_update.h"
+#include "pg_helper.h"
+
+enum GNUNET_DB_QueryStatus
+TEH_PG_reserves_update (void *cls,
+                 const struct TALER_EXCHANGEDB_Reserve *reserve)
+{
+  struct PostgresClosure *pg = cls;
+  struct GNUNET_PQ_QueryParam params[] = {
+    GNUNET_PQ_query_param_timestamp (&reserve->expiry),
+    GNUNET_PQ_query_param_timestamp (&reserve->gc),
+    TALER_PQ_query_param_amount (&reserve->balance),
+    GNUNET_PQ_query_param_auto_from_type (&reserve->pub),
+    GNUNET_PQ_query_param_end
+  };
+
+  PREPARE (pg,
+           "reserve_update",
+           "UPDATE reserves"
+           " SET"
+           " expiration_date=$1"
+           ",gc_date=$2"
+           ",current_balance_val=$3"
+           ",current_balance_frac=$4"
+           " WHERE reserve_pub=$5;");
+  return GNUNET_PQ_eval_prepared_non_select (pg->conn,
+                                             "reserve_update",
+                                             params);
+}
diff --git a/src/exchangedb/pg_reserves_update.h 
b/src/exchangedb/pg_reserves_update.h
new file mode 100644
index 00000000..24cf671d
--- /dev/null
+++ b/src/exchangedb/pg_reserves_update.h
@@ -0,0 +1,40 @@
+/*
+   This file is part of TALER
+   Copyright (C) 2022 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 exchangedb/pg_reserves_update.h
+ * @brief implementation of the reserves_update function for Postgres
+ * @author Christian Grothoff
+ */
+#ifndef PG_RESERVES_UPDATE_H
+#define PG_RESERVES_UPDATE_H
+
+#include "taler_util.h"
+#include "taler_json_lib.h"
+#include "taler_exchangedb_plugin.h"
+
+/**
+ * Updates a reserve with the data from the given reserve structure.
+ *
+ * @param cls the `struct PostgresClosure` with the plugin-specific state
+ * @param reserve the reserve structure whose data will be used to update the
+ *          corresponding record in the database.
+ * @return transaction status
+ */
+enum GNUNET_DB_QueryStatus
+TEH_PG_reserves_update (void *cls,
+                        const struct TALER_EXCHANGEDB_Reserve *reserve);
+
+#endif
diff --git a/src/exchangedb/pg_select_aggregation_transient.c 
b/src/exchangedb/pg_select_aggregation_transient.c
new file mode 100644
index 00000000..f3e39c53
--- /dev/null
+++ b/src/exchangedb/pg_select_aggregation_transient.c
@@ -0,0 +1,67 @@
+/*
+   This file is part of TALER
+   Copyright (C) 2022 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 exchangedb/pg_select_aggregation_transient.c
+ * @brief Implementation of the select_aggregation_transient function for 
Postgres
+ * @author Christian Grothoff
+ */
+#include "platform.h"
+#include "taler_error_codes.h"
+#include "taler_dbevents.h"
+#include "taler_pq_lib.h"
+#include "pg_select_aggregation_transient.h"
+#include "pg_helper.h"
+
+
+enum GNUNET_DB_QueryStatus
+TEH_PG_select_aggregation_transient (
+  void *cls,
+  const struct TALER_PaytoHashP *h_payto,
+  const struct TALER_MerchantPublicKeyP *merchant_pub,
+  const char *exchange_account_section,
+  struct TALER_WireTransferIdentifierRawP *wtid,
+  struct TALER_Amount *total)
+{
+  struct PostgresClosure *pg = cls;
+  struct GNUNET_PQ_QueryParam params[] = {
+    GNUNET_PQ_query_param_auto_from_type (h_payto),
+    GNUNET_PQ_query_param_auto_from_type (merchant_pub),
+    GNUNET_PQ_query_param_string (exchange_account_section),
+    GNUNET_PQ_query_param_end
+  };
+  struct GNUNET_PQ_ResultSpec rs[] = {
+    TALER_PQ_RESULT_SPEC_AMOUNT ("amount",
+                                 total),
+    GNUNET_PQ_result_spec_auto_from_type ("wtid_raw",
+                                          wtid),
+    GNUNET_PQ_result_spec_end
+  };
+    /* Used in #postgres_select_aggregation_transient() */
+  PREPARE (pg,
+           "select_aggregation_transient",
+           "SELECT"
+           "  amount_val"
+           " ,amount_frac"
+           " ,wtid_raw"
+           " FROM aggregation_transient"
+           " WHERE wire_target_h_payto=$1"
+           "   AND merchant_pub=$2"
+           "   AND exchange_account_section=$3;");
+  return GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
+                                                   
"select_aggregation_transient",
+                                                   params,
+                                                   rs);
+}
diff --git a/src/exchangedb/pg_select_aggregation_transient.h 
b/src/exchangedb/pg_select_aggregation_transient.h
new file mode 100644
index 00000000..fd82a97a
--- /dev/null
+++ b/src/exchangedb/pg_select_aggregation_transient.h
@@ -0,0 +1,47 @@
+/*
+   This file is part of TALER
+   Copyright (C) 2022 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 exchangedb/pg_select_aggregation_transient.h
+ * @brief implementation of the select_aggregation_transient function for 
Postgres
+ * @author Christian Grothoff
+ */
+#ifndef PG_SELECT_AGGREGATION_TRANSIENT_H
+#define PG_SELECT_AGGREGATION_TRANSIENT_H
+
+#include "taler_util.h"
+#include "taler_json_lib.h"
+#include "taler_exchangedb_plugin.h"
+
+/**
+ * Find existing entry in the transient aggregation table.
+ *
+ * @param cls the @e cls of this struct with the plugin-specific state
+ * @param h_payto destination of the wire transfer
+ * @param merchant_pub public key of the merchant receiving the transfer
+ * @param exchange_account_section exchange account to use
+ * @param[out] wtid set to the raw wire transfer identifier to be used
+ * @param[out] total existing amount to be wired in the future
+ * @return transaction status
+ */
+enum GNUNET_DB_QueryStatus
+TEH_PG_select_aggregation_transient (
+  void *cls,
+  const struct TALER_PaytoHashP *h_payto,
+  const struct TALER_MerchantPublicKeyP *merchant_pub,
+  const char *exchange_account_section,
+  struct TALER_WireTransferIdentifierRawP *wtid,
+  struct TALER_Amount *total);
+#endif
diff --git a/src/exchangedb/pg_select_auditor_denom_sig.c 
b/src/exchangedb/pg_select_auditor_denom_sig.c
new file mode 100644
index 00000000..90e0c509
--- /dev/null
+++ b/src/exchangedb/pg_select_auditor_denom_sig.c
@@ -0,0 +1,67 @@
+/*
+   This file is part of TALER
+   Copyright (C) 2022 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 exchangedb/pg_select_auditor_denom_sig.c
+ * @brief Implementation of the select_auditor_denom_sig function for Postgres
+ * @author Christian Grothoff
+ */
+#include "platform.h"
+#include "taler_error_codes.h"
+#include "taler_dbevents.h"
+#include "taler_pq_lib.h"
+#include "pg_select_auditor_denom_sig.h"
+#include "pg_helper.h"
+
+
+enum GNUNET_DB_QueryStatus
+TEH_PG_select_auditor_denom_sig (
+  void *cls,
+  const struct TALER_DenominationHashP *h_denom_pub,
+  const struct TALER_AuditorPublicKeyP *auditor_pub,
+  struct TALER_AuditorSignatureP *auditor_sig)
+{
+  struct PostgresClosure *pg = cls;
+  struct GNUNET_PQ_QueryParam params[] = {
+    GNUNET_PQ_query_param_auto_from_type (auditor_pub),
+    GNUNET_PQ_query_param_auto_from_type (h_denom_pub),
+    GNUNET_PQ_query_param_end
+  };
+  struct GNUNET_PQ_ResultSpec rs[] = {
+    GNUNET_PQ_result_spec_auto_from_type ("auditor_sig",
+                                          auditor_sig),
+    GNUNET_PQ_result_spec_end
+  };
+
+  PREPARE (pg,
+           "select_auditor_denom_sig",
+           "SELECT"
+           " auditor_sig"
+           " FROM auditor_denom_sigs"
+           " WHERE auditor_uuid="
+           "  (SELECT auditor_uuid"
+           "    FROM auditors"
+           "    WHERE auditor_pub=$1)"
+           " AND denominations_serial="
+           "  (SELECT denominations_serial"
+           "    FROM denominations"
+           "    WHERE denom_pub_hash=$2);");
+
+  return GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
+                                                   "select_auditor_denom_sig",
+                                                   params,
+                                                   rs);
+}
+
diff --git a/src/exchangedb/pg_select_auditor_denom_sig.h 
b/src/exchangedb/pg_select_auditor_denom_sig.h
new file mode 100644
index 00000000..0f635cf4
--- /dev/null
+++ b/src/exchangedb/pg_select_auditor_denom_sig.h
@@ -0,0 +1,43 @@
+/*
+   This file is part of TALER
+   Copyright (C) 2022 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 exchangedb/pg_select_auditor_denom_sig.h
+ * @brief implementation of the select_auditor_denom_sig function for Postgres
+ * @author Christian Grothoff
+ */
+#ifndef PG_SELECT_AUDITOR_DENOM_SIG_H
+#define PG_SELECT_AUDITOR_DENOM_SIG_H
+
+#include "taler_util.h"
+#include "taler_json_lib.h"
+#include "taler_exchangedb_plugin.h"
+/**
+ * Select information about an auditor auditing a denomination key.
+ *
+ * @param cls closure
+ * @param h_denom_pub the audited denomination
+ * @param auditor_pub the auditor's key
+ * @param[out] auditor_sig set to signature affirming the auditor's audit 
activity
+ * @return transaction status code
+ */
+enum GNUNET_DB_QueryStatus
+TEH_PG_select_auditor_denom_sig (
+  void *cls,
+  const struct TALER_DenominationHashP *h_denom_pub,
+  const struct TALER_AuditorPublicKeyP *auditor_pub,
+  struct TALER_AuditorSignatureP *auditor_sig);
+
+#endif
diff --git a/src/exchangedb/pg_select_deposits_above_serial_id.c 
b/src/exchangedb/pg_select_deposits_above_serial_id.c
new file mode 100644
index 00000000..52f96e5f
--- /dev/null
+++ b/src/exchangedb/pg_select_deposits_above_serial_id.c
@@ -0,0 +1,197 @@
+/*
+   This file is part of TALER
+   Copyright (C) 2022 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 exchangedb/pg_select_deposits_above_serial_id.c
+ * @brief Implementation of the select_deposits_above_serial_id function for 
Postgres
+ * @author Christian Grothoff
+ */
+#include "platform.h"
+#include "taler_error_codes.h"
+#include "taler_dbevents.h"
+#include "taler_pq_lib.h"
+#include "pg_select_deposits_above_serial_id.h"
+#include "pg_helper.h"
+
+/**
+ * Closure for #deposit_serial_helper_cb().
+ */
+struct DepositSerialContext
+{
+
+  /**
+   * Callback to call.
+   */
+  TALER_EXCHANGEDB_DepositCallback cb;
+
+  /**
+   * Closure for @e cb.
+   */
+  void *cb_cls;
+
+  /**
+   * Plugin context.
+   */
+  struct PostgresClosure *pg;
+
+  /**
+   * Status code, set to #GNUNET_SYSERR on hard errors.
+   */
+  enum GNUNET_GenericReturnValue status;
+};
+
+
+/**
+ * Helper function to be called with the results of a SELECT statement
+ * that has returned @a num_results results.
+ *
+ * @param cls closure of type `struct DepositSerialContext`
+ * @param result the postgres result
+ * @param num_results the number of results in @a result
+ */
+static void
+deposit_serial_helper_cb (void *cls,
+                          PGresult *result,
+                          unsigned int num_results)
+{
+  struct DepositSerialContext *dsc = cls;
+  struct PostgresClosure *pg = dsc->pg;
+
+  for (unsigned int i = 0; i<num_results; i++)
+  {
+    struct TALER_EXCHANGEDB_Deposit deposit;
+    struct GNUNET_TIME_Timestamp exchange_timestamp;
+    struct TALER_DenominationPublicKey denom_pub;
+    bool done;
+    uint64_t rowid;
+    struct GNUNET_PQ_ResultSpec rs[] = {
+      TALER_PQ_RESULT_SPEC_AMOUNT ("amount_with_fee",
+                                   &deposit.amount_with_fee),
+      GNUNET_PQ_result_spec_timestamp ("wallet_timestamp",
+                                       &deposit.timestamp),
+      GNUNET_PQ_result_spec_timestamp ("exchange_timestamp",
+                                       &exchange_timestamp),
+      GNUNET_PQ_result_spec_auto_from_type ("merchant_pub",
+                                            &deposit.merchant_pub),
+      TALER_PQ_result_spec_denom_pub ("denom_pub",
+                                      &denom_pub),
+      GNUNET_PQ_result_spec_auto_from_type ("coin_pub",
+                                            &deposit.coin.coin_pub),
+      GNUNET_PQ_result_spec_allow_null (
+        GNUNET_PQ_result_spec_auto_from_type ("age_commitment_hash",
+                                              &deposit.coin.h_age_commitment),
+        &deposit.coin.no_age_commitment),
+      GNUNET_PQ_result_spec_auto_from_type ("coin_sig",
+                                            &deposit.csig),
+      GNUNET_PQ_result_spec_timestamp ("refund_deadline",
+                                       &deposit.refund_deadline),
+      GNUNET_PQ_result_spec_timestamp ("wire_deadline",
+                                       &deposit.wire_deadline),
+      GNUNET_PQ_result_spec_auto_from_type ("h_contract_terms",
+                                            &deposit.h_contract_terms),
+      GNUNET_PQ_result_spec_auto_from_type ("wire_salt",
+                                            &deposit.wire_salt),
+      GNUNET_PQ_result_spec_string ("receiver_wire_account",
+                                    &deposit.receiver_wire_account),
+      GNUNET_PQ_result_spec_bool ("done",
+                                  &done),
+      GNUNET_PQ_result_spec_uint64 ("deposit_serial_id",
+                                    &rowid),
+      GNUNET_PQ_result_spec_end
+    };
+    enum GNUNET_GenericReturnValue ret;
+
+    memset (&deposit,
+            0,
+            sizeof (deposit));
+    if (GNUNET_OK !=
+        GNUNET_PQ_extract_result (result,
+                                  rs,
+                                  i))
+    {
+      GNUNET_break (0);
+      dsc->status = GNUNET_SYSERR;
+      return;
+    }
+    ret = dsc->cb (dsc->cb_cls,
+                   rowid,
+                   exchange_timestamp,
+                   &deposit,
+                   &denom_pub,
+                   done);
+    GNUNET_PQ_cleanup_result (rs);
+    if (GNUNET_OK != ret)
+      break;
+  }
+}
+
+enum GNUNET_DB_QueryStatus
+TEH_PG_select_deposits_above_serial_id (
+  void *cls,
+  uint64_t serial_id,
+  TALER_EXCHANGEDB_DepositCallback cb,
+  void *cb_cls)
+{
+  struct PostgresClosure *pg = cls;
+  struct GNUNET_PQ_QueryParam params[] = {
+    GNUNET_PQ_query_param_uint64 (&serial_id),
+    GNUNET_PQ_query_param_end
+  };
+  struct DepositSerialContext dsc = {
+    .cb = cb,
+    .cb_cls = cb_cls,
+    .pg = pg,
+    .status = GNUNET_OK
+  };
+  enum GNUNET_DB_QueryStatus qs;
+
+      /* Fetch deposits with rowid '\geq' the given parameter */
+  PREPARE (pg,
+           "audit_get_deposits_incr",
+           "SELECT"
+           " amount_with_fee_val"
+           ",amount_with_fee_frac"
+           ",wallet_timestamp"
+           ",exchange_timestamp"
+           ",merchant_pub"
+           ",denom.denom_pub"
+           ",kc.coin_pub"
+           ",kc.age_commitment_hash"
+           ",coin_sig"
+           ",refund_deadline"
+           ",wire_deadline"
+           ",h_contract_terms"
+           ",wire_salt"
+           ",payto_uri AS receiver_wire_account"
+           ",done"
+           ",deposit_serial_id"
+           " FROM deposits"
+           "    JOIN wire_targets USING (wire_target_h_payto)"
+           "    JOIN known_coins kc USING (coin_pub)"
+           "    JOIN denominations denom USING (denominations_serial)"
+           " WHERE ("
+           "  (deposit_serial_id>=$1)"
+           " )"
+           " ORDER BY deposit_serial_id ASC;");
+
+  qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn,
+                                             "audit_get_deposits_incr",
+                                             params,
+                                             &deposit_serial_helper_cb,
+                                             &dsc);
+  if (GNUNET_OK != dsc.status)
+    return GNUNET_DB_STATUS_HARD_ERROR;
+  return qs;
+}
diff --git a/src/exchangedb/pg_select_deposits_above_serial_id.h 
b/src/exchangedb/pg_select_deposits_above_serial_id.h
new file mode 100644
index 00000000..e29937e0
--- /dev/null
+++ b/src/exchangedb/pg_select_deposits_above_serial_id.h
@@ -0,0 +1,44 @@
+/*
+   This file is part of TALER
+   Copyright (C) 2022 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 exchangedb/pg_select_deposits_above_serial_id.h
+ * @brief implementation of the select_deposits_above_serial_id function for 
Postgres
+ * @author Christian Grothoff
+ */
+#ifndef PG_SELECT_DEPOSITS_ABOVE_SERIAL_ID_H
+#define PG_SELECT_DEPOSITS_ABOVE_SERIAL_ID_H
+
+#include "taler_util.h"
+#include "taler_json_lib.h"
+#include "taler_exchangedb_plugin.h"
+/**
+ * Select deposits above @a serial_id in monotonically increasing
+ * order.
+ *
+ * @param cls closure
+ * @param serial_id highest serial ID to exclude (select strictly larger)
+ * @param cb function to call on each result
+ * @param cb_cls closure for @a cb
+ * @return transaction status code
+ */
+enum GNUNET_DB_QueryStatus
+TEH_PG_select_deposits_above_serial_id (
+  void *cls,
+  uint64_t serial_id,
+  TALER_EXCHANGEDB_DepositCallback cb,
+  void *cb_cls);
+
+#endif
diff --git a/src/exchangedb/pg_select_deposits_missing_wire.c 
b/src/exchangedb/pg_select_deposits_missing_wire.c
new file mode 100644
index 00000000..2a260a36
--- /dev/null
+++ b/src/exchangedb/pg_select_deposits_missing_wire.c
@@ -0,0 +1,176 @@
+/*
+   This file is part of TALER
+   Copyright (C) 2022 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 exchangedb/pg_select_deposits_missing_wire.c
+ * @brief Implementation of the select_deposits_missing_wire function for 
Postgres
+ * @author Christian Grothoff
+ */
+#include "platform.h"
+#include "taler_error_codes.h"
+#include "taler_dbevents.h"
+#include "taler_pq_lib.h"
+#include "pg_select_deposits_missing_wire.h"
+#include "pg_helper.h"
+
+/**
+ * Closure for #missing_wire_cb().
+ */
+struct MissingWireContext
+{
+  /**
+   * Function to call per result.
+   */
+  TALER_EXCHANGEDB_WireMissingCallback cb;
+
+  /**
+   * Closure for @e cb.
+   */
+  void *cb_cls;
+
+  /**
+   * Plugin context.
+   */
+  struct PostgresClosure *pg;
+
+  /**
+   * Set to #GNUNET_SYSERR on error.
+   */
+  enum GNUNET_GenericReturnValue status;
+};
+
+
+/**
+ * Invoke the callback for each result.
+ *
+ * @param cls a `struct MissingWireContext *`
+ * @param result SQL result
+ * @param num_results number of rows in @a result
+ */
+static void
+missing_wire_cb (void *cls,
+                 PGresult *result,
+                 unsigned int num_results)
+{
+  struct MissingWireContext *mwc = cls;
+  struct PostgresClosure *pg = mwc->pg;
+
+  while (0 < num_results)
+  {
+    uint64_t rowid;
+    struct TALER_CoinSpendPublicKeyP coin_pub;
+    struct TALER_Amount amount;
+    char *payto_uri;
+    struct GNUNET_TIME_Timestamp deadline;
+    bool done;
+    struct GNUNET_PQ_ResultSpec rs[] = {
+      GNUNET_PQ_result_spec_uint64 ("deposit_serial_id",
+                                    &rowid),
+      GNUNET_PQ_result_spec_auto_from_type ("coin_pub",
+                                            &coin_pub),
+      TALER_PQ_RESULT_SPEC_AMOUNT ("amount_with_fee",
+                                   &amount),
+      GNUNET_PQ_result_spec_string ("payto_uri",
+                                    &payto_uri),
+      GNUNET_PQ_result_spec_timestamp ("wire_deadline",
+                                       &deadline),
+      GNUNET_PQ_result_spec_bool ("done",
+                                  &done),
+      GNUNET_PQ_result_spec_end
+    };
+
+    if (GNUNET_OK !=
+        GNUNET_PQ_extract_result (result,
+                                  rs,
+                                  --num_results))
+    {
+      GNUNET_break (0);
+      mwc->status = GNUNET_SYSERR;
+      return;
+    }
+    mwc->cb (mwc->cb_cls,
+             rowid,
+             &coin_pub,
+             &amount,
+             payto_uri,
+             deadline,
+             done);
+    GNUNET_PQ_cleanup_result (rs);
+  }
+}
+
+
+enum GNUNET_DB_QueryStatus
+TEH_PG_select_deposits_missing_wire (void *cls,
+                                       struct GNUNET_TIME_Timestamp start_date,
+                                       struct GNUNET_TIME_Timestamp end_date,
+                                       TALER_EXCHANGEDB_WireMissingCallback cb,
+                                       void *cb_cls)
+{
+  struct PostgresClosure *pg = cls;
+  struct GNUNET_PQ_QueryParam params[] = {
+    GNUNET_PQ_query_param_timestamp (&start_date),
+    GNUNET_PQ_query_param_timestamp (&end_date),
+    GNUNET_PQ_query_param_end
+  };
+  struct MissingWireContext mwc = {
+    .cb = cb,
+    .cb_cls = cb_cls,
+    .pg = pg,
+    .status = GNUNET_OK
+  };
+  enum GNUNET_DB_QueryStatus qs;
+
+      /* Used in #postgres_select_deposits_missing_wire */
+    // FIXME: used by the auditor; can probably be done
+    // smarter by checking if 'done' or 'blocked'
+    // are set correctly when going over deposits, instead
+    // of JOINing with refunds.
+  PREPARE (pg,
+           "deposits_get_overdue",
+           "SELECT"
+           " deposit_serial_id"
+           ",coin_pub"
+           ",amount_with_fee_val"
+           ",amount_with_fee_frac"
+           ",payto_uri"
+           ",wire_deadline"
+           ",done"
+           " FROM deposits d"
+           "   JOIN known_coins"
+           "     USING (coin_pub)"
+           "   JOIN wire_targets"
+           "     USING (wire_target_h_payto)"
+           " WHERE wire_deadline >= $1"
+           " AND wire_deadline < $2"
+           " AND NOT (EXISTS (SELECT 1"
+           "            FROM refunds r"
+           "            WHERE (r.coin_pub = d.coin_pub) AND 
(r.deposit_serial_id = d.deposit_serial_id))"
+           "       OR EXISTS (SELECT 1"
+           "            FROM aggregation_tracking"
+           "            WHERE (aggregation_tracking.deposit_serial_id = 
d.deposit_serial_id)))"
+           " ORDER BY wire_deadline ASC");
+
+
+
+  qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn,
+                                             "deposits_get_overdue",
+                                             params,
+                                             &missing_wire_cb,
+                                             &mwc);
+  if (GNUNET_OK != mwc.status)
+    return GNUNET_DB_STATUS_HARD_ERROR;
+  return qs;
+}
diff --git a/src/exchangedb/pg_select_deposits_missing_wire.h 
b/src/exchangedb/pg_select_deposits_missing_wire.h
new file mode 100644
index 00000000..f702c241
--- /dev/null
+++ b/src/exchangedb/pg_select_deposits_missing_wire.h
@@ -0,0 +1,46 @@
+/*
+   This file is part of TALER
+   Copyright (C) 2022 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 exchangedb/pg_select_deposits_missing_wire.h
+ * @brief implementation of the select_deposits_missing_wire function for 
Postgres
+ * @author Christian Grothoff
+ */
+#ifndef PG_SELECT_DEPOSITS_MISSING_WIRE_H
+#define PG_SELECT_DEPOSITS_MISSING_WIRE_H
+
+#include "taler_util.h"
+#include "taler_json_lib.h"
+#include "taler_exchangedb_plugin.h"
+/**
+ * Select all of those deposits in the database for which we do
+ * not have a wire transfer (or a refund) and which should have
+ * been deposited between @a start_date and @a end_date.
+ *
+ * @param cls closure
+ * @param start_date lower bound on the requested wire execution date
+ * @param end_date upper bound on the requested wire execution date
+ * @param cb function to call on all such deposits
+ * @param cb_cls closure for @a cb
+ * @return transaction status code
+ */
+enum GNUNET_DB_QueryStatus
+TEH_PG_select_deposits_missing_wire (void *cls,
+                                       struct GNUNET_TIME_Timestamp start_date,
+                                       struct GNUNET_TIME_Timestamp end_date,
+                                       TALER_EXCHANGEDB_WireMissingCallback cb,
+                                     void *cb_cls);
+
+#endif
diff --git a/src/exchangedb/pg_select_history_requests_above_serial_id.c 
b/src/exchangedb/pg_select_history_requests_above_serial_id.c
new file mode 100644
index 00000000..81e03811
--- /dev/null
+++ b/src/exchangedb/pg_select_history_requests_above_serial_id.c
@@ -0,0 +1,159 @@
+/*
+   This file is part of TALER
+   Copyright (C) 2022 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 exchangedb/pg_select_history_requests_above_serial_id.c
+ * @brief Implementation of the select_history_requests_above_serial_id 
function for Postgres
+ * @author Christian Grothoff
+ */
+#include "platform.h"
+#include "taler_error_codes.h"
+#include "taler_dbevents.h"
+#include "taler_pq_lib.h"
+#include "pg_select_history_requests_above_serial_id.h"
+#include "pg_helper.h"
+
+/**
+ * Closure for #purse_deposit_serial_helper_cb().
+ */
+struct HistoryRequestSerialContext
+{
+
+  /**
+   * Callback to call.
+   */
+  TALER_EXCHANGEDB_HistoryRequestCallback cb;
+
+  /**
+   * Closure for @e cb.
+   */
+  void *cb_cls;
+
+  /**
+   * Plugin context.
+   */
+  struct PostgresClosure *pg;
+
+  /**
+   * Status code, set to #GNUNET_SYSERR on hard errors.
+   */
+  enum GNUNET_GenericReturnValue status;
+};
+
+
+/**
+ * Helper function to be called with the results of a SELECT statement
+ * that has returned @a num_results results.
+ *
+ * @param cls closure of type `struct HistoryRequestSerialContext`
+ * @param result the postgres result
+ * @param num_results the number of results in @a result
+ */
+static void
+history_request_serial_helper_cb (void *cls,
+                                  PGresult *result,
+                                  unsigned int num_results)
+{
+  struct HistoryRequestSerialContext *dsc = cls;
+  struct PostgresClosure *pg = dsc->pg;
+
+  for (unsigned int i = 0; i<num_results; i++)
+  {
+    uint64_t rowid;
+    struct TALER_Amount history_fee;
+    struct GNUNET_TIME_Timestamp ts;
+    struct TALER_ReservePublicKeyP reserve_pub;
+    struct TALER_ReserveSignatureP reserve_sig;
+    struct GNUNET_PQ_ResultSpec rs[] = {
+      TALER_PQ_RESULT_SPEC_AMOUNT ("history_fee",
+                                   &history_fee),
+      GNUNET_PQ_result_spec_auto_from_type ("reserve_pub",
+                                            &reserve_pub),
+      GNUNET_PQ_result_spec_auto_from_type ("reserve_sig",
+                                            &reserve_sig),
+      GNUNET_PQ_result_spec_uint64 ("history_request_serial_id",
+                                    &rowid),
+      GNUNET_PQ_result_spec_timestamp ("request_timestamp",
+                                       &ts),
+      GNUNET_PQ_result_spec_end
+    };
+    enum GNUNET_GenericReturnValue ret;
+
+    if (GNUNET_OK !=
+        GNUNET_PQ_extract_result (result,
+                                  rs,
+                                  i))
+    {
+      GNUNET_break (0);
+      dsc->status = GNUNET_SYSERR;
+      return;
+    }
+    ret = dsc->cb (dsc->cb_cls,
+                   rowid,
+                   &history_fee,
+                   ts,
+                   &reserve_pub,
+                   &reserve_sig);
+    GNUNET_PQ_cleanup_result (rs);
+    if (GNUNET_OK != ret)
+      break;
+  }
+}
+
+
+
+
+enum GNUNET_DB_QueryStatus
+TEH_PG_select_history_requests_above_serial_id (
+  void *cls,
+  uint64_t serial_id,
+  TALER_EXCHANGEDB_HistoryRequestCallback cb,
+  void *cb_cls)
+{
+  struct PostgresClosure *pg = cls;
+  struct GNUNET_PQ_QueryParam params[] = {
+    GNUNET_PQ_query_param_uint64 (&serial_id),
+    GNUNET_PQ_query_param_end
+  };
+  struct HistoryRequestSerialContext dsc = {
+    .cb = cb,
+    .cb_cls = cb_cls,
+    .pg = pg,
+    .status = GNUNET_OK
+  };
+  enum GNUNET_DB_QueryStatus qs;
+  PREPARE (pg,
+           "audit_get_history_requests_incr",
+           "SELECT"
+           " history_request_serial_id"
+           ",history_fee_val"
+           ",history_fee_frac"
+           ",request_timestamp"
+           ",reserve_pub"
+           ",reserve_sig"
+           " FROM history_requests"
+           " WHERE ("
+           "  (history_request_serial_id>=$1)"
+           " )"
+           " ORDER BY history_request_serial_id ASC;");
+  qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn,
+                                             "audit_get_history_requests_incr",
+                                             params,
+                                             &history_request_serial_helper_cb,
+                                             &dsc);
+  if (GNUNET_OK != dsc.status)
+    return GNUNET_DB_STATUS_HARD_ERROR;
+  return qs;
+}
diff --git a/src/exchangedb/pg_select_history_requests_above_serial_id.h 
b/src/exchangedb/pg_select_history_requests_above_serial_id.h
new file mode 100644
index 00000000..b16efdce
--- /dev/null
+++ b/src/exchangedb/pg_select_history_requests_above_serial_id.h
@@ -0,0 +1,44 @@
+/*
+   This file is part of TALER
+   Copyright (C) 2022 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 exchangedb/pg_select_history_requests_above_serial_id.h
+ * @brief implementation of the select_history_requests_above_serial_id 
function for Postgres
+ * @author Christian Grothoff
+ */
+#ifndef PG_SELECT_HISTORY_REQUESTS_ABOVE_SERIAL_ID_H
+#define PG_SELECT_HISTORY_REQUESTS_ABOVE_SERIAL_ID_H
+
+#include "taler_util.h"
+#include "taler_json_lib.h"
+#include "taler_exchangedb_plugin.h"
+/**
+ * Select history requests above @a serial_id in monotonically increasing
+ * order.
+ *
+ * @param cls closure
+ * @param serial_id highest serial ID to exclude (select strictly larger)
+ * @param cb function to call on each result
+ * @param cb_cls closure for @a cb
+ * @return transaction status code
+ */
+enum GNUNET_DB_QueryStatus
+TEH_PG_select_history_requests_above_serial_id (
+  void *cls,
+  uint64_t serial_id,
+  TALER_EXCHANGEDB_HistoryRequestCallback cb,
+  void *cb_cls);
+
+#endif
diff --git a/src/exchangedb/pg_select_purse_by_merge_pub.c 
b/src/exchangedb/pg_select_purse_by_merge_pub.c
new file mode 100644
index 00000000..965b27ba
--- /dev/null
+++ b/src/exchangedb/pg_select_purse_by_merge_pub.c
@@ -0,0 +1,83 @@
+/*
+   This file is part of TALER
+   Copyright (C) 2022 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 exchangedb/pg_select_purse_by_merge_pub.c
+ * @brief Implementation of the select_purse_by_merge_pub function for Postgres
+ * @author Christian Grothoff
+ */
+#include "platform.h"
+#include "taler_error_codes.h"
+#include "taler_dbevents.h"
+#include "taler_pq_lib.h"
+#include "pg_select_purse_by_merge_pub.h"
+#include "pg_helper.h"
+
+enum GNUNET_DB_QueryStatus
+TEH_PG_select_purse_by_merge_pub (
+  void *cls,
+  const struct TALER_PurseMergePublicKeyP *merge_pub,
+  struct TALER_PurseContractPublicKeyP *purse_pub,
+  struct GNUNET_TIME_Timestamp *purse_expiration,
+  struct TALER_PrivateContractHashP *h_contract_terms,
+  uint32_t *age_limit,
+  struct TALER_Amount *target_amount,
+  struct TALER_Amount *balance,
+  struct TALER_PurseContractSignatureP *purse_sig)
+{
+  struct PostgresClosure *pg = cls;
+  struct GNUNET_PQ_QueryParam params[] = {
+    GNUNET_PQ_query_param_auto_from_type (merge_pub),
+    GNUNET_PQ_query_param_end
+  };
+  struct GNUNET_PQ_ResultSpec rs[] = {
+    GNUNET_PQ_result_spec_auto_from_type ("purse_pub",
+                                          purse_pub),
+    GNUNET_PQ_result_spec_timestamp ("purse_expiration",
+                                     purse_expiration),
+    GNUNET_PQ_result_spec_auto_from_type ("h_contract_terms",
+                                          h_contract_terms),
+    GNUNET_PQ_result_spec_uint32 ("age_limit",
+                                  age_limit),
+    TALER_PQ_RESULT_SPEC_AMOUNT ("amount_with_fee",
+                                 target_amount),
+    TALER_PQ_RESULT_SPEC_AMOUNT ("balance",
+                                 balance),
+    GNUNET_PQ_result_spec_auto_from_type ("purse_sig",
+                                          purse_sig),
+    GNUNET_PQ_result_spec_end
+  };
+
+
+  PREPARE (pg,
+           "select_purse_by_merge_pub",
+           "SELECT "
+           " purse_pub"
+           ",purse_expiration"
+           ",h_contract_terms"
+           ",age_limit"
+           ",amount_with_fee_val"
+           ",amount_with_fee_frac"
+           ",balance_val"
+           ",balance_frac"
+           ",purse_sig"
+           " FROM purse_requests"
+           " WHERE merge_pub=$1;");
+
+  return GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
+                                                   "select_purse_by_merge_pub",
+                                                   params,
+                                                   rs);
+}
diff --git a/src/exchangedb/pg_select_purse_by_merge_pub.h 
b/src/exchangedb/pg_select_purse_by_merge_pub.h
new file mode 100644
index 00000000..2a766713
--- /dev/null
+++ b/src/exchangedb/pg_select_purse_by_merge_pub.h
@@ -0,0 +1,54 @@
+/*
+   This file is part of TALER
+   Copyright (C) 2022 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 exchangedb/pg_select_purse_by_merge_pub.h
+ * @brief implementation of the select_purse_by_merge_pub function for Postgres
+ * @author Christian Grothoff
+ */
+#ifndef PG_SELECT_PURSE_BY_MERGE_PUB_H
+#define PG_SELECT_PURSE_BY_MERGE_PUB_H
+
+#include "taler_util.h"
+#include "taler_json_lib.h"
+#include "taler_exchangedb_plugin.h"
+
+/**
+ * Function called to return meta data about a purse by the
+ * merge capability key.
+ *
+ * @param cls the @e cls of this struct with the plugin-specific state
+ * @param merge_pub public key representing the merge capability
+ * @param[out] purse_pub public key of the purse
+ * @param[out] purse_expiration when would an unmerged purse expire
+ * @param[out] h_contract_terms contract associated with the purse
+ * @param[out] age_limit the age limit for deposits into the purse
+ * @param[out] target_amount amount to be put into the purse
+ * @param[out] balance amount put so far into the purse
+ * @param[out] purse_sig signature of the purse over the initialization data
+ * @return transaction status code
+ */
+enum GNUNET_DB_QueryStatus
+TEH_PG_select_purse_by_merge_pub (
+  void *cls,
+  const struct TALER_PurseMergePublicKeyP *merge_pub,
+  struct TALER_PurseContractPublicKeyP *purse_pub,
+  struct GNUNET_TIME_Timestamp *purse_expiration,
+  struct TALER_PrivateContractHashP *h_contract_terms,
+  uint32_t *age_limit,
+  struct TALER_Amount *target_amount,
+  struct TALER_Amount *balance,
+  struct TALER_PurseContractSignatureP *purse_sig);
+#endif
diff --git a/src/exchangedb/pg_select_purse_decisions_above_serial_id.c 
b/src/exchangedb/pg_select_purse_decisions_above_serial_id.c
new file mode 100644
index 00000000..2368f2d3
--- /dev/null
+++ b/src/exchangedb/pg_select_purse_decisions_above_serial_id.c
@@ -0,0 +1,164 @@
+/*
+   This file is part of TALER
+   Copyright (C) 2022 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 exchangedb/pg_select_purse_decisions_above_serial_id.c
+ * @brief Implementation of the select_purse_decisions_above_serial_id 
function for Postgres
+ * @author Christian Grothoff
+ */
+#include "platform.h"
+#include "taler_error_codes.h"
+#include "taler_dbevents.h"
+#include "taler_pq_lib.h"
+#include "pg_select_purse_decisions_above_serial_id.h"
+#include "pg_helper.h"
+
+/**
+ * Closure for #purse_decision_serial_helper_cb().
+ */
+struct PurseDecisionSerialContext
+{
+
+  /**
+   * Callback to call.
+   */
+  TALER_EXCHANGEDB_PurseDecisionCallback cb;
+
+  /**
+   * Closure for @e cb.
+   */
+  void *cb_cls;
+
+  /**
+   * Plugin context.
+   */
+  struct PostgresClosure *pg;
+
+  /**
+   * Status code, set to #GNUNET_SYSERR on hard errors.
+   */
+  enum GNUNET_GenericReturnValue status;
+};
+
+
+/**
+ * Helper function to be called with the results of a SELECT statement
+ * that has returned @a num_results results.
+ *
+ * @param cls closure of type `struct PurseRefundSerialContext`
+ * @param result the postgres result
+ * @param num_results the number of results in @a result
+ */
+static void
+purse_decision_serial_helper_cb (void *cls,
+                                 PGresult *result,
+                                 unsigned int num_results)
+{
+  struct PurseDecisionSerialContext *dsc = cls;
+  struct PostgresClosure *pg = dsc->pg;
+
+  for (unsigned int i = 0; i<num_results; i++)
+  {
+    struct TALER_PurseContractPublicKeyP purse_pub;
+    struct TALER_ReservePublicKeyP reserve_pub;
+    bool no_reserve = true;
+    uint64_t rowid;
+    struct TALER_Amount val;
+    struct GNUNET_PQ_ResultSpec rs[] = {
+      GNUNET_PQ_result_spec_auto_from_type ("purse_pub",
+                                            &purse_pub),
+      GNUNET_PQ_result_spec_allow_null (
+        GNUNET_PQ_result_spec_auto_from_type ("reserve_pub",
+                                              &reserve_pub),
+        &no_reserve),
+      TALER_PQ_RESULT_SPEC_AMOUNT ("amount_with_fee",
+                                   &val),
+      GNUNET_PQ_result_spec_uint64 ("purse_deposit_serial_id",
+                                    &rowid),
+      GNUNET_PQ_result_spec_end
+    };
+    enum GNUNET_GenericReturnValue ret;
+
+    if (GNUNET_OK !=
+        GNUNET_PQ_extract_result (result,
+                                  rs,
+                                  i))
+    {
+      GNUNET_break (0);
+      dsc->status = GNUNET_SYSERR;
+      return;
+    }
+    ret = dsc->cb (dsc->cb_cls,
+                   rowid,
+                   &purse_pub,
+                   no_reserve ? NULL : &reserve_pub,
+                   &val);
+    GNUNET_PQ_cleanup_result (rs);
+    if (GNUNET_OK != ret)
+      break;
+  }
+}
+
+
+
+enum GNUNET_DB_QueryStatus
+TEH_PG_select_purse_decisions_above_serial_id (
+  void *cls,
+  uint64_t serial_id,
+  bool refunded,
+  TALER_EXCHANGEDB_PurseDecisionCallback cb,
+  void *cb_cls)
+{
+  struct PostgresClosure *pg = cls;
+  struct GNUNET_PQ_QueryParam params[] = {
+    GNUNET_PQ_query_param_uint64 (&serial_id),
+    GNUNET_PQ_query_param_bool (refunded),
+    GNUNET_PQ_query_param_end
+  };
+  struct PurseDecisionSerialContext dsc = {
+    .cb = cb,
+    .cb_cls = cb_cls,
+    .pg = pg,
+    .status = GNUNET_OK
+  };
+  enum GNUNET_DB_QueryStatus qs;
+
+  PREPARE (pg,
+           "audit_get_purse_decisions_incr",
+           "SELECT"
+           " pd.purse_pub"
+           ",pm.reserve_pub"
+           ",pd.purse_decision_serial_id"
+           ",pr.amount_with_fee_val"
+           ",pr.amount_with_fee_frac"
+           " FROM purse_decision pd"
+           " JOIN purse_requests pr ON (pd.purse_pub = pr.purse_pub)"
+           " LEFT JOIN purse_merges pm ON (pm.purse_pub = pd.purse_pub)"
+           " WHERE ("
+           "  (purse_decision_serial_id>=$1) AND "
+           "  (refunded=$2)"
+           " )"
+           " ORDER BY purse_decision_serial_id ASC;");
+
+
+  qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn,
+                                             "audit_get_purse_decisions_incr",
+                                             params,
+                                             &purse_decision_serial_helper_cb,
+                                             &dsc);
+  if (GNUNET_OK != dsc.status)
+    return GNUNET_DB_STATUS_HARD_ERROR;
+  return qs;
+}
diff --git a/src/exchangedb/pg_select_purse_decisions_above_serial_id.h 
b/src/exchangedb/pg_select_purse_decisions_above_serial_id.h
new file mode 100644
index 00000000..53ab31c8
--- /dev/null
+++ b/src/exchangedb/pg_select_purse_decisions_above_serial_id.h
@@ -0,0 +1,46 @@
+/*
+   This file is part of TALER
+   Copyright (C) 2022 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 exchangedb/pg_select_purse_decisions_above_serial_id.h
+ * @brief implementation of the select_purse_decisions_above_serial_id 
function for Postgres
+ * @author Christian Grothoff
+ */
+#ifndef PG_SELECT_PURSE_DECISIONS_ABOVE_SERIAL_ID_H
+#define PG_SELECT_PURSE_DECISIONS_ABOVE_SERIAL_ID_H
+
+#include "taler_util.h"
+#include "taler_json_lib.h"
+#include "taler_exchangedb_plugin.h"
+
+/**
+ * Select purse decisions above @a serial_id in monotonically increasing
+ * order.
+ *
+ * @param cls closure
+ * @param serial_id highest serial ID to exclude (select strictly larger)
+ * @param refunded which refund status to select for
+ * @param cb function to call on each result
+ * @param cb_cls closure for @a cb
+ * @return transaction status code
+ */
+enum GNUNET_DB_QueryStatus
+TEH_PG_select_purse_decisions_above_serial_id (
+  void *cls,
+  uint64_t serial_id,
+  bool refunded,
+  TALER_EXCHANGEDB_PurseDecisionCallback cb,
+  void *cb_cls);
+#endif
diff --git a/src/exchangedb/pg_select_purse_deposits_by_purse.c 
b/src/exchangedb/pg_select_purse_deposits_by_purse.c
new file mode 100644
index 00000000..5fe7e014
--- /dev/null
+++ b/src/exchangedb/pg_select_purse_deposits_by_purse.c
@@ -0,0 +1,153 @@
+/*
+   This file is part of TALER
+   Copyright (C) 2022 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 exchangedb/pg_select_purse_deposits_by_purse.c
+ * @brief Implementation of the select_purse_deposits_by_purse function for 
Postgres
+ * @author Christian Grothoff
+ */
+#include "platform.h"
+#include "taler_error_codes.h"
+#include "taler_dbevents.h"
+#include "taler_pq_lib.h"
+#include "pg_select_purse_deposits_by_purse.h"
+#include "pg_helper.h"
+
+/**
+ * Closure for #purse_refund_coin_helper_cb().
+ */
+struct PurseRefundCoinContext
+{
+
+  /**
+   * Callback to call.
+   */
+  TALER_EXCHANGEDB_PurseRefundCoinCallback cb;
+
+  /**
+   * Closure for @e cb.
+   */
+  void *cb_cls;
+
+  /**
+   * Plugin context.
+   */
+  struct PostgresClosure *pg;
+
+  /**
+   * Status code, set to #GNUNET_SYSERR on hard errors.
+   */
+  enum GNUNET_GenericReturnValue status;
+};
+
+
+/**
+ * Helper function to be called with the results of a SELECT statement
+ * that has returned @a num_results results.
+ *
+ * @param cls closure of type `struct PurseRefundCoinContext`
+ * @param result the postgres result
+ * @param num_results the number of results in @a result
+ */
+static void
+purse_refund_coin_helper_cb (void *cls,
+                             PGresult *result,
+                             unsigned int num_results)
+{
+  struct PurseRefundCoinContext *dsc = cls;
+  struct PostgresClosure *pg = dsc->pg;
+
+  for (unsigned int i = 0; i<num_results; i++)
+  {
+    struct TALER_Amount amount_with_fee;
+    struct TALER_CoinSpendPublicKeyP coin_pub;
+    struct TALER_DenominationPublicKey denom_pub;
+    uint64_t rowid;
+    struct GNUNET_PQ_ResultSpec rs[] = {
+      TALER_PQ_result_spec_denom_pub ("denom_pub",
+                                      &denom_pub),
+      TALER_PQ_RESULT_SPEC_AMOUNT ("amount_with_fee",
+                                   &amount_with_fee),
+      GNUNET_PQ_result_spec_auto_from_type ("coin_pub",
+                                            &coin_pub),
+      GNUNET_PQ_result_spec_uint64 ("purse_deposit_serial_id",
+                                    &rowid),
+      GNUNET_PQ_result_spec_end
+    };
+    enum GNUNET_GenericReturnValue ret;
+
+    if (GNUNET_OK !=
+        GNUNET_PQ_extract_result (result,
+                                  rs,
+                                  i))
+    {
+      GNUNET_break (0);
+      dsc->status = GNUNET_SYSERR;
+      return;
+    }
+    ret = dsc->cb (dsc->cb_cls,
+                   rowid,
+                   &amount_with_fee,
+                   &coin_pub,
+                   &denom_pub);
+    GNUNET_PQ_cleanup_result (rs);
+    if (GNUNET_OK != ret)
+      break;
+  }
+}
+
+
+enum GNUNET_DB_QueryStatus
+TEH_PG_select_purse_deposits_by_purse (
+  void *cls,
+  const struct TALER_PurseContractPublicKeyP *purse_pub,
+  TALER_EXCHANGEDB_PurseRefundCoinCallback cb,
+  void *cb_cls)
+{
+  struct PostgresClosure *pg = cls;
+  struct GNUNET_PQ_QueryParam params[] = {
+    GNUNET_PQ_query_param_auto_from_type (purse_pub),
+    GNUNET_PQ_query_param_end
+  };
+  struct PurseRefundCoinContext dsc = {
+    .cb = cb,
+    .cb_cls = cb_cls,
+    .pg = pg,
+    .status = GNUNET_OK
+  };
+  enum GNUNET_DB_QueryStatus qs;
+
+  PREPARE (pg,
+           "audit_get_purse_deposits_by_purse",
+           "SELECT"
+           " pd.purse_deposit_serial_id"
+           ",pd.amount_with_fee_val"
+           ",pd.amount_with_fee_frac"
+           ",pd.coin_pub"
+           ",denom.denom_pub"
+           " FROM purse_deposits pd"
+           " JOIN known_coins kc USING (coin_pub)"
+           " JOIN denominations denom USING (denominations_serial)"
+           " WHERE purse_pub=$1;");
+
+  qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn,
+                                             
"audit_get_purse_deposits_by_purse",
+                                             params,
+                                             &purse_refund_coin_helper_cb,
+                                             &dsc);
+  if (GNUNET_OK != dsc.status)
+    return GNUNET_DB_STATUS_HARD_ERROR;
+  return qs;
+}
diff --git a/src/exchangedb/pg_select_purse_deposits_by_purse.h 
b/src/exchangedb/pg_select_purse_deposits_by_purse.h
new file mode 100644
index 00000000..203f9a15
--- /dev/null
+++ b/src/exchangedb/pg_select_purse_deposits_by_purse.h
@@ -0,0 +1,44 @@
+/*
+   This file is part of TALER
+   Copyright (C) 2022 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 exchangedb/pg_select_purse_deposits_by_purse.h
+ * @brief implementation of the select_purse_deposits_by_purse function for 
Postgres
+ * @author Christian Grothoff
+ */
+#ifndef PG_SELECT_PURSE_DEPOSITS_BY_PURSE_H
+#define PG_SELECT_PURSE_DEPOSITS_BY_PURSE_H
+
+#include "taler_util.h"
+#include "taler_json_lib.h"
+#include "taler_exchangedb_plugin.h"
+
+/**
+ * Select coin affected by purse refund.
+ *
+ * @param cls closure
+ * @param purse_pub purse that was refunded
+ * @param cb function to call on each result
+ * @param cb_cls closure for @a cb
+ * @return transaction status code
+ */
+enum GNUNET_DB_QueryStatus
+TEH_PG_select_purse_deposits_by_purse (
+  void *cls,
+  const struct TALER_PurseContractPublicKeyP *purse_pub,
+  TALER_EXCHANGEDB_PurseRefundCoinCallback cb,
+  void *cb_cls);
+
+#endif
diff --git a/src/exchangedb/pg_select_recoup_above_serial_id.c 
b/src/exchangedb/pg_select_recoup_above_serial_id.c
new file mode 100644
index 00000000..9047a86f
--- /dev/null
+++ b/src/exchangedb/pg_select_recoup_above_serial_id.c
@@ -0,0 +1,196 @@
+/*
+   This file is part of TALER
+   Copyright (C) 2022 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 exchangedb/pg_select_recoup_above_serial_id.c
+ * @brief Implementation of the select_recoup_above_serial_id function for 
Postgres
+ * @author Christian Grothoff
+ */
+#include "platform.h"
+#include "taler_error_codes.h"
+#include "taler_dbevents.h"
+#include "taler_pq_lib.h"
+#include "pg_select_recoup_above_serial_id.h"
+#include "pg_helper.h"
+
+
+
+/**
+ * Closure for #recoup_serial_helper_cb().
+ */
+struct RecoupSerialContext
+{
+
+  /**
+   * Callback to call.
+   */
+  TALER_EXCHANGEDB_RecoupCallback cb;
+
+  /**
+   * Closure for @e cb.
+   */
+  void *cb_cls;
+
+  /**
+   * Plugin context.
+   */
+  struct PostgresClosure *pg;
+
+  /**
+   * Status code, set to #GNUNET_SYSERR on hard errors.
+   */
+  enum GNUNET_GenericReturnValue status;
+};
+
+
+/**
+ * Helper function to be called with the results of a SELECT statement
+ * that has returned @a num_results results.
+ *
+ * @param cls closure of type `struct RecoupSerialContext`
+ * @param result the postgres result
+ * @param num_results the number of results in @a result
+ */
+static void
+recoup_serial_helper_cb (void *cls,
+                         PGresult *result,
+                         unsigned int num_results)
+{
+  struct RecoupSerialContext *psc = cls;
+  struct PostgresClosure *pg = psc->pg;
+
+  for (unsigned int i = 0; i<num_results; i++)
+  {
+    uint64_t rowid;
+    struct TALER_ReservePublicKeyP reserve_pub;
+    struct TALER_CoinPublicInfo coin;
+    struct TALER_CoinSpendSignatureP coin_sig;
+    union TALER_DenominationBlindingKeyP coin_blind;
+    struct TALER_Amount amount;
+    struct TALER_DenominationPublicKey denom_pub;
+    struct TALER_BlindedCoinHashP h_blind_ev;
+    struct GNUNET_TIME_Timestamp timestamp;
+    struct GNUNET_PQ_ResultSpec rs[] = {
+      GNUNET_PQ_result_spec_uint64 ("recoup_uuid",
+                                    &rowid),
+      GNUNET_PQ_result_spec_timestamp ("recoup_timestamp",
+                                       &timestamp),
+      GNUNET_PQ_result_spec_auto_from_type ("reserve_pub",
+                                            &reserve_pub),
+      GNUNET_PQ_result_spec_auto_from_type ("coin_pub",
+                                            &coin.coin_pub),
+      TALER_PQ_result_spec_denom_pub ("denom_pub",
+                                      &denom_pub),
+      GNUNET_PQ_result_spec_auto_from_type ("coin_sig",
+                                            &coin_sig),
+      GNUNET_PQ_result_spec_auto_from_type ("coin_blind",
+                                            &coin_blind),
+      GNUNET_PQ_result_spec_auto_from_type ("h_blind_ev",
+                                            &h_blind_ev),
+      GNUNET_PQ_result_spec_auto_from_type ("denom_pub_hash",
+                                            &coin.denom_pub_hash),
+      GNUNET_PQ_result_spec_allow_null (
+        GNUNET_PQ_result_spec_auto_from_type ("age_commitment_hash",
+                                              &coin.h_age_commitment),
+        &coin.no_age_commitment),
+      TALER_PQ_result_spec_denom_sig ("denom_sig",
+                                      &coin.denom_sig),
+      TALER_PQ_RESULT_SPEC_AMOUNT ("amount",
+                                   &amount),
+      GNUNET_PQ_result_spec_end
+    };
+    int ret;
+
+    if (GNUNET_OK !=
+        GNUNET_PQ_extract_result (result,
+                                  rs,
+                                  i))
+    {
+      GNUNET_break (0);
+      psc->status = GNUNET_SYSERR;
+      return;
+    }
+    ret = psc->cb (psc->cb_cls,
+                   rowid,
+                   timestamp,
+                   &amount,
+                   &reserve_pub,
+                   &coin,
+                   &denom_pub,
+                   &coin_sig,
+                   &coin_blind);
+    GNUNET_PQ_cleanup_result (rs);
+    if (GNUNET_OK != ret)
+      break;
+  }
+}
+
+enum GNUNET_DB_QueryStatus
+TEH_PG_select_recoup_above_serial_id (
+  void *cls,
+  uint64_t serial_id,
+  TALER_EXCHANGEDB_RecoupCallback cb,
+  void *cb_cls)
+{
+  struct PostgresClosure *pg = cls;
+  struct GNUNET_PQ_QueryParam params[] = {
+    GNUNET_PQ_query_param_uint64 (&serial_id),
+    GNUNET_PQ_query_param_end
+  };
+  struct RecoupSerialContext psc = {
+    .cb = cb,
+    .cb_cls = cb_cls,
+    .pg = pg,
+    .status = GNUNET_OK
+  };
+  enum GNUNET_DB_QueryStatus qs;
+
+      /* Used in #postgres_select_recoup_above_serial_id() to obtain recoup 
transactions */
+  PREPARE (pg,
+           "recoup_get_incr",
+           "SELECT"
+           " recoup_uuid"
+           ",recoup_timestamp"
+           ",reserves.reserve_pub"
+           ",coins.coin_pub"
+           ",coin_sig"
+           ",coin_blind"
+           ",ro.h_blind_ev"
+           ",denoms.denom_pub_hash"
+           ",coins.denom_sig"
+           ",coins.age_commitment_hash"
+           ",denoms.denom_pub"
+           ",amount_val"
+           ",amount_frac"
+           " FROM recoup"
+           "    JOIN known_coins coins"
+           "      USING (coin_pub)"
+           "    JOIN reserves_out ro"
+           "      USING (reserve_out_serial_id)"
+           "    JOIN reserves"
+           "      USING (reserve_uuid)"
+           "    JOIN denominations denoms"
+           "      ON (coins.denominations_serial = 
denoms.denominations_serial)"
+           " WHERE recoup_uuid>=$1"
+           " ORDER BY recoup_uuid ASC;");
+  qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn,
+                                             "recoup_get_incr",
+                                             params,
+                                             &recoup_serial_helper_cb,
+                                             &psc);
+  if (GNUNET_OK != psc.status)
+    return GNUNET_DB_STATUS_HARD_ERROR;
+  return qs;
+}
diff --git a/src/exchangedb/pg_select_recoup_above_serial_id.h 
b/src/exchangedb/pg_select_recoup_above_serial_id.h
new file mode 100644
index 00000000..9be0b5c3
--- /dev/null
+++ b/src/exchangedb/pg_select_recoup_above_serial_id.h
@@ -0,0 +1,44 @@
+/*
+   This file is part of TALER
+   Copyright (C) 2022 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 exchangedb/pg_select_recoup_above_serial_id.h
+ * @brief implementation of the select_recoup_above_serial_id function for 
Postgres
+ * @author Christian Grothoff
+ */
+#ifndef PG_SELECT_RECOUP_ABOVE_SERIAL_ID_H
+#define PG_SELECT_RECOUP_ABOVE_SERIAL_ID_H
+
+#include "taler_util.h"
+#include "taler_json_lib.h"
+#include "taler_exchangedb_plugin.h"
+/**
+ * Function called to select recoup requests the exchange
+ * received, ordered by serial ID (monotonically increasing).
+ *
+ * @param cls closure
+ * @param serial_id lowest serial ID to include (select larger or equal)
+ * @param cb function to call for ONE unfinished item
+ * @param cb_cls closure for @a cb
+ * @return transaction status code
+ */
+enum GNUNET_DB_QueryStatus
+TEH_PG_select_recoup_above_serial_id (
+  void *cls,
+  uint64_t serial_id,
+  TALER_EXCHANGEDB_RecoupCallback cb,
+  void *cb_cls);
+
+#endif
diff --git a/src/exchangedb/pg_select_recoup_refresh_above_serial_id.c 
b/src/exchangedb/pg_select_recoup_refresh_above_serial_id.c
new file mode 100644
index 00000000..a3f6bc93
--- /dev/null
+++ b/src/exchangedb/pg_select_recoup_refresh_above_serial_id.c
@@ -0,0 +1,207 @@
+/*
+   This file is part of TALER
+   Copyright (C) 2022 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 exchangedb/pg_select_recoup_refresh_above_serial_id.c
+ * @brief Implementation of the select_recoup_refresh_above_serial_id function 
for Postgres
+ * @author Christian Grothoff
+ */
+#include "platform.h"
+#include "taler_error_codes.h"
+#include "taler_dbevents.h"
+#include "taler_pq_lib.h"
+#include "pg_select_recoup_refresh_above_serial_id.h"
+#include "pg_helper.h"
+
+
+/**
+ * Closure for #recoup_refresh_serial_helper_cb().
+ */
+struct RecoupRefreshSerialContext
+{
+
+  /**
+   * Callback to call.
+   */
+  TALER_EXCHANGEDB_RecoupRefreshCallback cb;
+
+  /**
+   * Closure for @e cb.
+   */
+  void *cb_cls;
+
+  /**
+   * Plugin context.
+   */
+  struct PostgresClosure *pg;
+
+  /**
+   * Status code, set to #GNUNET_SYSERR on hard errors.
+   */
+  enum GNUNET_GenericReturnValue status;
+};
+
+
+/**
+ * Helper function to be called with the results of a SELECT statement
+ * that has returned @a num_results results.
+ *
+ * @param cls closure of type `struct RecoupRefreshSerialContext`
+ * @param result the postgres result
+ * @param num_results the number of results in @a result
+ */
+static void
+recoup_refresh_serial_helper_cb (void *cls,
+                                 PGresult *result,
+                                 unsigned int num_results)
+{
+  struct RecoupRefreshSerialContext *psc = cls;
+  struct PostgresClosure *pg = psc->pg;
+
+  for (unsigned int i = 0; i<num_results; i++)
+  {
+    uint64_t rowid;
+    struct TALER_CoinSpendPublicKeyP old_coin_pub;
+    struct TALER_CoinPublicInfo coin;
+    struct TALER_CoinSpendSignatureP coin_sig;
+    union TALER_DenominationBlindingKeyP coin_blind;
+    struct TALER_DenominationPublicKey denom_pub;
+    struct TALER_DenominationHashP old_denom_pub_hash;
+    struct TALER_Amount amount;
+    struct TALER_BlindedCoinHashP h_blind_ev;
+    struct GNUNET_TIME_Timestamp timestamp;
+    struct GNUNET_PQ_ResultSpec rs[] = {
+      GNUNET_PQ_result_spec_uint64 ("recoup_refresh_uuid",
+                                    &rowid),
+      GNUNET_PQ_result_spec_timestamp ("recoup_timestamp",
+                                       &timestamp),
+      GNUNET_PQ_result_spec_auto_from_type ("old_coin_pub",
+                                            &old_coin_pub),
+      GNUNET_PQ_result_spec_auto_from_type ("old_denom_pub_hash",
+                                            &old_denom_pub_hash),
+      GNUNET_PQ_result_spec_auto_from_type ("coin_pub",
+                                            &coin.coin_pub),
+      GNUNET_PQ_result_spec_auto_from_type ("coin_sig",
+                                            &coin_sig),
+      GNUNET_PQ_result_spec_auto_from_type ("coin_blind",
+                                            &coin_blind),
+      TALER_PQ_result_spec_denom_pub ("denom_pub",
+                                      &denom_pub),
+      GNUNET_PQ_result_spec_auto_from_type ("h_blind_ev",
+                                            &h_blind_ev),
+      GNUNET_PQ_result_spec_auto_from_type ("denom_pub_hash",
+                                            &coin.denom_pub_hash),
+      GNUNET_PQ_result_spec_allow_null (
+        GNUNET_PQ_result_spec_auto_from_type ("age_commitment_hash",
+                                              &coin.h_age_commitment),
+        &coin.no_age_commitment),
+      TALER_PQ_result_spec_denom_sig ("denom_sig",
+                                      &coin.denom_sig),
+      TALER_PQ_RESULT_SPEC_AMOUNT ("amount",
+                                   &amount),
+      GNUNET_PQ_result_spec_end
+    };
+    enum GNUNET_GenericReturnValue ret;
+
+    if (GNUNET_OK !=
+        GNUNET_PQ_extract_result (result,
+                                  rs,
+                                  i))
+    {
+      GNUNET_break (0);
+      psc->status = GNUNET_SYSERR;
+      return;
+    }
+    ret = psc->cb (psc->cb_cls,
+                   rowid,
+                   timestamp,
+                   &amount,
+                   &old_coin_pub,
+                   &old_denom_pub_hash,
+                   &coin,
+                   &denom_pub,
+                   &coin_sig,
+                   &coin_blind);
+    GNUNET_PQ_cleanup_result (rs);
+    if (GNUNET_OK != ret)
+      break;
+  }
+}
+
+
+
+enum GNUNET_DB_QueryStatus
+TEH_PG_select_recoup_refresh_above_serial_id (
+  void *cls,
+  uint64_t serial_id,
+  TALER_EXCHANGEDB_RecoupRefreshCallback cb,
+  void *cb_cls)
+{
+  struct PostgresClosure *pg = cls;
+  struct GNUNET_PQ_QueryParam params[] = {
+    GNUNET_PQ_query_param_uint64 (&serial_id),
+    GNUNET_PQ_query_param_end
+  };
+  struct RecoupRefreshSerialContext psc = {
+    .cb = cb,
+    .cb_cls = cb_cls,
+    .pg = pg,
+    .status = GNUNET_OK
+  };
+  enum GNUNET_DB_QueryStatus qs;
+
+      /* Used in #postgres_select_recoup_refresh_above_serial_id() to obtain
+       recoup-refresh transactions */
+  PREPARE (pg,
+           "recoup_refresh_get_incr",
+           "SELECT"
+           " recoup_refresh_uuid"
+           ",recoup_timestamp"
+           ",old_coins.coin_pub AS old_coin_pub"
+           ",new_coins.age_commitment_hash"
+           ",old_denoms.denom_pub_hash AS old_denom_pub_hash"
+           ",new_coins.coin_pub As coin_pub"
+           ",coin_sig"
+           ",coin_blind"
+           ",new_denoms.denom_pub AS denom_pub"
+           ",rrc.h_coin_ev AS h_blind_ev"
+           ",new_denoms.denom_pub_hash"
+           ",new_coins.denom_sig AS denom_sig"
+           ",amount_val"
+           ",amount_frac"
+           " FROM recoup_refresh"
+           "    INNER JOIN refresh_revealed_coins rrc"
+           "      USING (rrc_serial)"
+           "    INNER JOIN refresh_commitments rfc"
+           "      ON (rrc.melt_serial_id = rfc.melt_serial_id)"
+           "    INNER JOIN known_coins old_coins"
+           "      ON (rfc.old_coin_pub = old_coins.coin_pub)"
+           "    INNER JOIN known_coins new_coins"
+           "      ON (new_coins.coin_pub = recoup_refresh.coin_pub)"
+           "    INNER JOIN denominations new_denoms"
+           "      ON (new_coins.denominations_serial = 
new_denoms.denominations_serial)"
+           "    INNER JOIN denominations old_denoms"
+           "      ON (old_coins.denominations_serial = 
old_denoms.denominations_serial)"
+           " WHERE recoup_refresh_uuid>=$1"
+           " ORDER BY recoup_refresh_uuid ASC;");
+  qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn,
+                                             "recoup_refresh_get_incr",
+                                             params,
+                                             &recoup_refresh_serial_helper_cb,
+                                             &psc);
+  if (GNUNET_OK != psc.status)
+    return GNUNET_DB_STATUS_HARD_ERROR;
+  return qs;
+}
diff --git a/src/exchangedb/pg_select_recoup_refresh_above_serial_id.h 
b/src/exchangedb/pg_select_recoup_refresh_above_serial_id.h
new file mode 100644
index 00000000..0d7b72fc
--- /dev/null
+++ b/src/exchangedb/pg_select_recoup_refresh_above_serial_id.h
@@ -0,0 +1,45 @@
+/*
+   This file is part of TALER
+   Copyright (C) 2022 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 exchangedb/pg_select_recoup_refresh_above_serial_id.h
+ * @brief implementation of the select_recoup_refresh_above_serial_id function 
for Postgres
+ * @author Christian Grothoff
+ */
+#ifndef PG_SELECT_RECOUP_REFRESH_ABOVE_SERIAL_ID_H
+#define PG_SELECT_RECOUP_REFRESH_ABOVE_SERIAL_ID_H
+
+#include "taler_util.h"
+#include "taler_json_lib.h"
+#include "taler_exchangedb_plugin.h"
+
+/**
+ * Function called to select recoup requests the exchange received for
+ * refreshed coins, ordered by serial ID (monotonically increasing).
+ *
+ * @param cls closure
+ * @param serial_id lowest serial ID to include (select larger or equal)
+ * @param cb function to call for ONE unfinished item
+ * @param cb_cls closure for @a cb
+ * @return transaction status code
+ */
+enum GNUNET_DB_QueryStatus
+TEH_PG_select_recoup_refresh_above_serial_id (
+  void *cls,
+  uint64_t serial_id,
+  TALER_EXCHANGEDB_RecoupRefreshCallback cb,
+  void *cb_cls);
+
+#endif
diff --git a/src/exchangedb/pg_select_refreshes_above_serial_id.c 
b/src/exchangedb/pg_select_refreshes_above_serial_id.c
new file mode 100644
index 00000000..d2b4a7fa
--- /dev/null
+++ b/src/exchangedb/pg_select_refreshes_above_serial_id.c
@@ -0,0 +1,185 @@
+/*
+   This file is part of TALER
+   Copyright (C) 2022 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 exchangedb/pg_select_refreshes_above_serial_id.c
+ * @brief Implementation of the select_refreshes_above_serial_id function for 
Postgres
+ * @author Christian Grothoff
+ */
+#include "platform.h"
+#include "taler_error_codes.h"
+#include "taler_dbevents.h"
+#include "taler_pq_lib.h"
+#include "pg_select_refreshes_above_serial_id.h"
+#include "pg_helper.h"
+
+
+/**
+ * Closure for #refreshs_serial_helper_cb().
+ */
+struct RefreshsSerialContext
+{
+
+  /**
+   * Callback to call.
+   */
+  TALER_EXCHANGEDB_RefreshesCallback cb;
+
+  /**
+   * Closure for @e cb.
+   */
+  void *cb_cls;
+
+  /**
+   * Plugin context.
+   */
+  struct PostgresClosure *pg;
+
+  /**
+   * Status code, set to #GNUNET_SYSERR on hard errors.
+   */
+  enum GNUNET_GenericReturnValue status;
+};
+
+
+/**
+ * Helper function to be called with the results of a SELECT statement
+ * that has returned @a num_results results.
+ *
+ * @param cls closure of type `struct RefreshsSerialContext`
+ * @param result the postgres result
+ * @param num_results the number of results in @a result
+ */
+static void
+refreshs_serial_helper_cb (void *cls,
+                           PGresult *result,
+                           unsigned int num_results)
+{
+  struct RefreshsSerialContext *rsc = cls;
+  struct PostgresClosure *pg = rsc->pg;
+
+  for (unsigned int i = 0; i<num_results; i++)
+  {
+    struct TALER_DenominationPublicKey denom_pub;
+    struct TALER_CoinSpendPublicKeyP coin_pub;
+    struct TALER_CoinSpendSignatureP coin_sig;
+    struct TALER_AgeCommitmentHash h_age_commitment;
+    bool ac_isnull;
+    struct TALER_Amount amount_with_fee;
+    uint32_t noreveal_index;
+    uint64_t rowid;
+    struct TALER_RefreshCommitmentP rc;
+    struct GNUNET_PQ_ResultSpec rs[] = {
+      TALER_PQ_result_spec_denom_pub ("denom_pub",
+                                      &denom_pub),
+      GNUNET_PQ_result_spec_allow_null (
+        GNUNET_PQ_result_spec_auto_from_type ("age_commitment_hash",
+                                              &h_age_commitment),
+        &ac_isnull),
+      GNUNET_PQ_result_spec_auto_from_type ("old_coin_pub",
+                                            &coin_pub),
+      GNUNET_PQ_result_spec_auto_from_type ("old_coin_sig",
+                                            &coin_sig),
+      TALER_PQ_RESULT_SPEC_AMOUNT ("amount_with_fee",
+                                   &amount_with_fee),
+      GNUNET_PQ_result_spec_uint32 ("noreveal_index",
+                                    &noreveal_index),
+      GNUNET_PQ_result_spec_uint64 ("melt_serial_id",
+                                    &rowid),
+      GNUNET_PQ_result_spec_auto_from_type ("rc",
+                                            &rc),
+      GNUNET_PQ_result_spec_end
+    };
+    enum GNUNET_GenericReturnValue ret;
+
+    if (GNUNET_OK !=
+        GNUNET_PQ_extract_result (result,
+                                  rs,
+                                  i))
+    {
+      GNUNET_break (0);
+      rsc->status = GNUNET_SYSERR;
+      return;
+    }
+
+    ret = rsc->cb (rsc->cb_cls,
+                   rowid,
+                   &denom_pub,
+                   ac_isnull ? NULL : &h_age_commitment,
+                   &coin_pub,
+                   &coin_sig,
+                   &amount_with_fee,
+                   noreveal_index,
+                   &rc);
+    GNUNET_PQ_cleanup_result (rs);
+    if (GNUNET_OK != ret)
+      break;
+  }
+}
+
+
+
+
+
+
+enum GNUNET_DB_QueryStatus
+TEH_PG_select_refreshes_above_serial_id (
+  void *cls,
+  uint64_t serial_id,
+  TALER_EXCHANGEDB_RefreshesCallback cb,
+  void *cb_cls)
+{
+  struct PostgresClosure *pg = cls;
+  struct GNUNET_PQ_QueryParam params[] = {
+    GNUNET_PQ_query_param_uint64 (&serial_id),
+    GNUNET_PQ_query_param_end
+  };
+  struct RefreshsSerialContext rsc = {
+    .cb = cb,
+    .cb_cls = cb_cls,
+    .pg = pg,
+    .status = GNUNET_OK
+  };
+  enum GNUNET_DB_QueryStatus qs;
+    /* Used in #postgres_select_refreshes_above_serial_id() to fetch
+       refresh session with id '\geq' the given parameter */
+  PREPARE (pg,
+           "audit_get_refresh_commitments_incr",
+           "SELECT"
+           " denom.denom_pub"
+           ",kc.coin_pub AS old_coin_pub"
+           ",kc.age_commitment_hash"
+           ",old_coin_sig"
+           ",amount_with_fee_val"
+           ",amount_with_fee_frac"
+           ",noreveal_index"
+           ",melt_serial_id"
+           ",rc"
+           " FROM refresh_commitments"
+           "   JOIN known_coins kc"
+           "     ON (refresh_commitments.old_coin_pub = kc.coin_pub)"
+           "   JOIN denominations denom"
+           "     ON (kc.denominations_serial = denom.denominations_serial)"
+           " WHERE melt_serial_id>=$1"
+           " ORDER BY melt_serial_id ASC;");
+  qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn,
+                                             
"audit_get_refresh_commitments_incr",
+                                             params,
+                                             &refreshs_serial_helper_cb,
+                                             &rsc);
+  if (GNUNET_OK != rsc.status)
+    return GNUNET_DB_STATUS_HARD_ERROR;
+  return qs;
+}
diff --git a/src/exchangedb/pg_select_refreshes_above_serial_id.h 
b/src/exchangedb/pg_select_refreshes_above_serial_id.h
new file mode 100644
index 00000000..2d1db275
--- /dev/null
+++ b/src/exchangedb/pg_select_refreshes_above_serial_id.h
@@ -0,0 +1,45 @@
+/*
+   This file is part of TALER
+   Copyright (C) 2022 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 exchangedb/pg_select_refreshes_above_serial_id.h
+ * @brief implementation of the select_refreshes_above_serial_id function for 
Postgres
+ * @author Christian Grothoff
+ */
+#ifndef PG_SELECT_REFRESHES_ABOVE_SERIAL_ID_H
+#define PG_SELECT_REFRESHES_ABOVE_SERIAL_ID_H
+
+#include "taler_util.h"
+#include "taler_json_lib.h"
+#include "taler_exchangedb_plugin.h"
+
+/**
+ * Select refresh sessions above @a serial_id in monotonically increasing
+ * order.
+ *
+ * @param cls closure
+ * @param serial_id highest serial ID to exclude (select strictly larger)
+ * @param cb function to call on each result
+ * @param cb_cls closure for @a cb
+ * @return transaction status code
+ */
+enum GNUNET_DB_QueryStatus
+TEH_PG_select_refreshes_above_serial_id (
+  void *cls,
+  uint64_t serial_id,
+  TALER_EXCHANGEDB_RefreshesCallback cb,
+  void *cb_cls);
+
+#endif
diff --git a/src/exchangedb/pg_select_refunds_above_serial_id.c 
b/src/exchangedb/pg_select_refunds_above_serial_id.c
new file mode 100644
index 00000000..a5f7d3df
--- /dev/null
+++ b/src/exchangedb/pg_select_refunds_above_serial_id.c
@@ -0,0 +1,211 @@
+/*
+   This file is part of TALER
+   Copyright (C) 2022 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 exchangedb/pg_select_refunds_above_serial_id.c
+ * @brief Implementation of the select_refunds_above_serial_id function for 
Postgres
+ * @author Christian Grothoff
+ */
+#include "platform.h"
+#include "taler_error_codes.h"
+#include "taler_dbevents.h"
+#include "taler_pq_lib.h"
+#include "pg_select_refunds_above_serial_id.h"
+#include "pg_helper.h"
+
+/**
+ * Closure for #refunds_serial_helper_cb().
+ */
+struct RefundsSerialContext
+{
+
+  /**
+   * Callback to call.
+   */
+  TALER_EXCHANGEDB_RefundCallback cb;
+
+  /**
+   * Closure for @e cb.
+   */
+  void *cb_cls;
+
+  /**
+   * Plugin context.
+   */
+  struct PostgresClosure *pg;
+
+  /**
+   * Status code, set to #GNUNET_SYSERR on hard errors.
+   */
+  enum GNUNET_GenericReturnValue status;
+};
+
+
+/**
+ * Helper function to be called with the results of a SELECT statement
+ * that has returned @a num_results results.
+ *
+ * @param cls closure of type `struct RefundsSerialContext`
+ * @param result the postgres result
+ * @param num_results the number of results in @a result
+ */
+static void
+refunds_serial_helper_cb (void *cls,
+                          PGresult *result,
+                          unsigned int num_results)
+{
+  struct RefundsSerialContext *rsc = cls;
+  struct PostgresClosure *pg = rsc->pg;
+
+  for (unsigned int i = 0; i<num_results; i++)
+  {
+    struct TALER_EXCHANGEDB_Refund refund;
+    struct TALER_DenominationPublicKey denom_pub;
+    uint64_t rowid;
+    bool full_refund;
+    struct GNUNET_PQ_ResultSpec rs[] = {
+      GNUNET_PQ_result_spec_auto_from_type ("merchant_pub",
+                                            &refund.details.merchant_pub),
+      GNUNET_PQ_result_spec_auto_from_type ("merchant_sig",
+                                            &refund.details.merchant_sig),
+      GNUNET_PQ_result_spec_auto_from_type ("h_contract_terms",
+                                            &refund.details.h_contract_terms),
+      GNUNET_PQ_result_spec_uint64 ("rtransaction_id",
+                                    &refund.details.rtransaction_id),
+      TALER_PQ_result_spec_denom_pub ("denom_pub",
+                                      &denom_pub),
+      GNUNET_PQ_result_spec_auto_from_type ("coin_pub",
+                                            &refund.coin.coin_pub),
+      TALER_PQ_RESULT_SPEC_AMOUNT ("amount_with_fee",
+                                   &refund.details.refund_amount),
+      GNUNET_PQ_result_spec_uint64 ("refund_serial_id",
+                                    &rowid),
+      GNUNET_PQ_result_spec_end
+    };
+    enum GNUNET_GenericReturnValue ret;
+
+    if (GNUNET_OK !=
+        GNUNET_PQ_extract_result (result,
+                                  rs,
+                                  i))
+    {
+      GNUNET_break (0);
+      rsc->status = GNUNET_SYSERR;
+      return;
+    }
+    {
+      struct GNUNET_PQ_QueryParam params[] = {
+        GNUNET_PQ_query_param_uint64 (&rowid),
+        GNUNET_PQ_query_param_end
+      };
+      struct TALER_Amount amount_with_fee;
+      uint64_t s_f;
+      uint64_t s_v;
+      struct GNUNET_PQ_ResultSpec rs2[] = {
+        GNUNET_PQ_result_spec_uint64 ("s_v",
+                                      &s_v),
+        GNUNET_PQ_result_spec_uint64 ("s_f",
+                                      &s_f),
+        TALER_PQ_RESULT_SPEC_AMOUNT ("amount_with_fee",
+                                     &amount_with_fee),
+        GNUNET_PQ_result_spec_end
+      };
+      enum GNUNET_DB_QueryStatus qs;
+
+      qs = GNUNET_PQ_eval_prepared_singleton_select (
+        pg->conn,
+        "test_refund_full",
+        params,
+        rs2);
+      if (qs <= 0)
+      {
+        GNUNET_break (0);
+        rsc->status = GNUNET_SYSERR;
+        return;
+      }
+      /* normalize */
+      s_v += s_f / TALER_AMOUNT_FRAC_BASE;
+      s_f %= TALER_AMOUNT_FRAC_BASE;
+      full_refund = (s_v >= amount_with_fee.value) &&
+                    (s_f >= amount_with_fee.fraction);
+    }
+    ret = rsc->cb (rsc->cb_cls,
+                   rowid,
+                   &denom_pub,
+                   &refund.coin.coin_pub,
+                   &refund.details.merchant_pub,
+                   &refund.details.merchant_sig,
+                   &refund.details.h_contract_terms,
+                   refund.details.rtransaction_id,
+                   full_refund,
+                   &refund.details.refund_amount);
+    GNUNET_PQ_cleanup_result (rs);
+    if (GNUNET_OK != ret)
+      break;
+  }
+}
+
+
+enum GNUNET_DB_QueryStatus
+TEH_PG_select_refunds_above_serial_id (
+  void *cls,
+  uint64_t serial_id,
+  TALER_EXCHANGEDB_RefundCallback cb,
+  void *cb_cls)
+{
+  struct PostgresClosure *pg = cls;
+  struct GNUNET_PQ_QueryParam params[] = {
+    GNUNET_PQ_query_param_uint64 (&serial_id),
+    GNUNET_PQ_query_param_end
+  };
+  struct RefundsSerialContext rsc = {
+    .cb = cb,
+    .cb_cls = cb_cls,
+    .pg = pg,
+    .status = GNUNET_OK
+  };
+  enum GNUNET_DB_QueryStatus qs;
+
+      /* Fetch refunds with rowid '\geq' the given parameter */
+  PREPARE (pg,
+           "audit_get_refunds_incr",
+           "SELECT"
+           " dep.merchant_pub"
+           ",ref.merchant_sig"
+           ",dep.h_contract_terms"
+           ",ref.rtransaction_id"
+           ",denom.denom_pub"
+           ",kc.coin_pub"
+           ",ref.amount_with_fee_val"
+           ",ref.amount_with_fee_frac"
+           ",ref.refund_serial_id"
+           " FROM refunds ref"
+           "   JOIN deposits dep"
+           "     ON (ref.coin_pub=dep.coin_pub AND 
ref.deposit_serial_id=dep.deposit_serial_id)"
+           "   JOIN known_coins kc"
+           "     ON (dep.coin_pub=kc.coin_pub)"
+           "   JOIN denominations denom"
+           "     ON (kc.denominations_serial=denom.denominations_serial)"
+           " WHERE ref.refund_serial_id>=$1"
+           " ORDER BY ref.refund_serial_id ASC;");
+  qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn,
+                                             "audit_get_refunds_incr",
+                                             params,
+                                             &refunds_serial_helper_cb,
+                                             &rsc);
+  if (GNUNET_OK != rsc.status)
+    return GNUNET_DB_STATUS_HARD_ERROR;
+  return qs;
+}
diff --git a/src/exchangedb/pg_select_refunds_above_serial_id.h 
b/src/exchangedb/pg_select_refunds_above_serial_id.h
new file mode 100644
index 00000000..b33816a9
--- /dev/null
+++ b/src/exchangedb/pg_select_refunds_above_serial_id.h
@@ -0,0 +1,45 @@
+/*
+   This file is part of TALER
+   Copyright (C) 2022 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 exchangedb/pg_select_refunds_above_serial_id.h
+ * @brief implementation of the select_refunds_above_serial_id function for 
Postgres
+ * @author Christian Grothoff
+ */
+#ifndef PG_SELECT_REFUNDS_ABOVE_SERIAL_ID_H
+#define PG_SELECT_REFUNDS_ABOVE_SERIAL_ID_H
+
+#include "taler_util.h"
+#include "taler_json_lib.h"
+#include "taler_exchangedb_plugin.h"
+
+/**
+ * Select refunds above @a serial_id in monotonically increasing
+ * order.
+ *
+ * @param cls closure
+ * @param serial_id highest serial ID to exclude (select strictly larger)
+ * @param cb function to call on each result
+ * @param cb_cls closure for @a cb
+ * @return transaction status code
+ */
+enum GNUNET_DB_QueryStatus
+TEH_PG_select_refunds_above_serial_id (
+  void *cls,
+  uint64_t serial_id,
+  TALER_EXCHANGEDB_RefundCallback cb,
+  void *cb_cls);
+
+#endif
diff --git a/src/exchangedb/pg_select_refunds_by_coin.c 
b/src/exchangedb/pg_select_refunds_by_coin.c
new file mode 100644
index 00000000..17885a47
--- /dev/null
+++ b/src/exchangedb/pg_select_refunds_by_coin.c
@@ -0,0 +1,143 @@
+/*
+   This file is part of TALER
+   Copyright (C) 2022 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 exchangedb/pg_select_refunds_by_coin.c
+ * @brief Implementation of the select_refunds_by_coin function for Postgres
+ * @author Christian Grothoff
+ */
+#include "platform.h"
+#include "taler_error_codes.h"
+#include "taler_dbevents.h"
+#include "taler_pq_lib.h"
+#include "pg_select_refunds_by_coin.h"
+#include "pg_helper.h"
+
+
+/**
+ * Closure for #get_refunds_cb().
+ */
+struct SelectRefundContext
+{
+  /**
+   * Function to call on each result.
+   */
+  TALER_EXCHANGEDB_RefundCoinCallback cb;
+
+  /**
+   * Closure for @a cb.
+   */
+  void *cb_cls;
+
+  /**
+   * Plugin context.
+   */
+  struct PostgresClosure *pg;
+
+  /**
+   * Set to #GNUNET_SYSERR on error.
+   */
+  int status;
+};
+
+
+/**
+ * Function to be called with the results of a SELECT statement
+ * that has returned @a num_results results.
+ *
+ * @param cls closure of type `struct SelectRefundContext *`
+ * @param result the postgres result
+ * @param num_results the number of results in @a result
+ */
+static void
+get_refunds_cb (void *cls,
+                PGresult *result,
+                unsigned int num_results)
+{
+  struct SelectRefundContext *srctx = cls;
+  struct PostgresClosure *pg = srctx->pg;
+
+  for (unsigned int i = 0; i<num_results; i++)
+  {
+    struct TALER_Amount amount_with_fee;
+    struct GNUNET_PQ_ResultSpec rs[] = {
+      TALER_PQ_RESULT_SPEC_AMOUNT ("amount_with_fee",
+                                   &amount_with_fee),
+      GNUNET_PQ_result_spec_end
+    };
+
+    if (GNUNET_OK !=
+        GNUNET_PQ_extract_result (result,
+                                  rs,
+                                  i))
+    {
+      GNUNET_break (0);
+      srctx->status = GNUNET_SYSERR;
+      return;
+    }
+    if (GNUNET_OK !=
+        srctx->cb (srctx->cb_cls,
+                   &amount_with_fee))
+      return;
+  }
+}
+
+
+enum GNUNET_DB_QueryStatus
+TEH_PG_select_refunds_by_coin (
+  void *cls,
+  const struct TALER_CoinSpendPublicKeyP *coin_pub,
+  const struct TALER_MerchantPublicKeyP *merchant_pub,
+  const struct TALER_PrivateContractHashP *h_contract,
+  TALER_EXCHANGEDB_RefundCoinCallback cb,
+  void *cb_cls)
+{
+  struct PostgresClosure *pg = cls;
+  enum GNUNET_DB_QueryStatus qs;
+  struct GNUNET_PQ_QueryParam params[] = {
+    GNUNET_PQ_query_param_auto_from_type (coin_pub),
+    GNUNET_PQ_query_param_auto_from_type (merchant_pub),
+    GNUNET_PQ_query_param_auto_from_type (h_contract),
+    GNUNET_PQ_query_param_end
+  };
+  struct SelectRefundContext srctx = {
+    .cb = cb,
+    .cb_cls = cb_cls,
+    .pg = pg,
+    .status = GNUNET_OK
+  };
+
+      /* Query the 'refunds' by coin public key */
+    /* Query the 'refunds' by coin public key, merchant_pub and contract hash 
*/
+  PREPARE (pg,
+           "get_refunds_by_coin_and_contract",
+           "SELECT"
+           " ref.amount_with_fee_val"
+           ",ref.amount_with_fee_frac"
+           " FROM refunds ref"
+           " JOIN deposits dep"
+           "   USING (coin_pub,deposit_serial_id)"
+           " WHERE ref.coin_pub=$1"
+           "   AND dep.merchant_pub=$2"
+           "   AND dep.h_contract_terms=$3;");
+  qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn,
+                                             
"get_refunds_by_coin_and_contract",
+                                             params,
+                                             &get_refunds_cb,
+                                             &srctx);
+  if (GNUNET_SYSERR == srctx.status)
+    return GNUNET_DB_STATUS_HARD_ERROR;
+  return qs;
+}
diff --git a/src/exchangedb/pg_select_refunds_by_coin.h 
b/src/exchangedb/pg_select_refunds_by_coin.h
new file mode 100644
index 00000000..e1838b23
--- /dev/null
+++ b/src/exchangedb/pg_select_refunds_by_coin.h
@@ -0,0 +1,47 @@
+/*
+   This file is part of TALER
+   Copyright (C) 2022 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 exchangedb/pg_select_refunds_by_coin.h
+ * @brief implementation of the select_refunds_by_coin function for Postgres
+ * @author Christian Grothoff
+ */
+#ifndef PG_SELECT_REFUNDS_BY_COIN_H
+#define PG_SELECT_REFUNDS_BY_COIN_H
+
+#include "taler_util.h"
+#include "taler_json_lib.h"
+#include "taler_exchangedb_plugin.h"
+
+/**
+ * Select refunds by @a coin_pub, @a merchant_pub and @a h_contract.
+ *
+ * @param cls closure of plugin
+ * @param coin_pub coin to get refunds for
+ * @param merchant_pub merchant to get refunds for
+ * @param h_contract contract (hash) to get refunds for
+ * @param cb function to call for each refund found
+ * @param cb_cls closure for @a cb
+ * @return query result status
+ */
+enum GNUNET_DB_QueryStatus
+TEH_PG_select_refunds_by_coin (
+  void *cls,
+  const struct TALER_CoinSpendPublicKeyP *coin_pub,
+  const struct TALER_MerchantPublicKeyP *merchant_pub,
+  const struct TALER_PrivateContractHashP *h_contract,
+  TALER_EXCHANGEDB_RefundCoinCallback cb,
+  void *cb_cls);
+#endif
diff --git a/src/exchangedb/pg_select_reserves_in_above_serial_id.c 
b/src/exchangedb/pg_select_reserves_in_above_serial_id.c
new file mode 100644
index 00000000..1a6efc66
--- /dev/null
+++ b/src/exchangedb/pg_select_reserves_in_above_serial_id.c
@@ -0,0 +1,167 @@
+/*
+   This file is part of TALER
+   Copyright (C) 2022 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 exchangedb/pg_select_reserves_in_above_serial_id.c
+ * @brief Implementation of the select_reserves_in_above_serial_id function 
for Postgres
+ * @author Christian Grothoff
+ */
+#include "platform.h"
+#include "taler_error_codes.h"
+#include "taler_dbevents.h"
+#include "taler_pq_lib.h"
+#include "pg_select_reserves_in_above_serial_id.h"
+#include "pg_helper.h"
+
+/**
+ * Closure for #reserves_in_serial_helper_cb().
+ */
+struct ReservesInSerialContext
+{
+
+  /**
+   * Callback to call.
+   */
+  TALER_EXCHANGEDB_ReserveInCallback cb;
+
+  /**
+   * Closure for @e cb.
+   */
+  void *cb_cls;
+
+  /**
+   * Plugin context.
+   */
+  struct PostgresClosure *pg;
+
+  /**
+   * Status code, set to #GNUNET_SYSERR on hard errors.
+   */
+  enum GNUNET_GenericReturnValue status;
+};
+
+
+/**
+ * Helper function to be called with the results of a SELECT statement
+ * that has returned @a num_results results.
+ *
+ * @param cls closure of type `struct ReservesInSerialContext`
+ * @param result the postgres result
+ * @param num_results the number of results in @a result
+ */
+static void
+reserves_in_serial_helper_cb (void *cls,
+                              PGresult *result,
+                              unsigned int num_results)
+{
+  struct ReservesInSerialContext *risc = cls;
+  struct PostgresClosure *pg = risc->pg;
+
+  for (unsigned int i = 0; i<num_results; i++)
+  {
+    struct TALER_ReservePublicKeyP reserve_pub;
+    struct TALER_Amount credit;
+    char *sender_account_details;
+    struct GNUNET_TIME_Timestamp execution_date;
+    uint64_t rowid;
+    uint64_t wire_reference;
+    struct GNUNET_PQ_ResultSpec rs[] = {
+      GNUNET_PQ_result_spec_auto_from_type ("reserve_pub",
+                                            &reserve_pub),
+      GNUNET_PQ_result_spec_uint64 ("wire_reference",
+                                    &wire_reference),
+      TALER_PQ_RESULT_SPEC_AMOUNT ("credit",
+                                   &credit),
+      GNUNET_PQ_result_spec_timestamp ("execution_date",
+                                       &execution_date),
+      GNUNET_PQ_result_spec_string ("sender_account_details",
+                                    &sender_account_details),
+      GNUNET_PQ_result_spec_uint64 ("reserve_in_serial_id",
+                                    &rowid),
+      GNUNET_PQ_result_spec_end
+    };
+    enum GNUNET_GenericReturnValue ret;
+
+    if (GNUNET_OK !=
+        GNUNET_PQ_extract_result (result,
+                                  rs,
+                                  i))
+    {
+      GNUNET_break (0);
+      risc->status = GNUNET_SYSERR;
+      return;
+    }
+    ret = risc->cb (risc->cb_cls,
+                    rowid,
+                    &reserve_pub,
+                    &credit,
+                    sender_account_details,
+                    wire_reference,
+                    execution_date);
+    GNUNET_PQ_cleanup_result (rs);
+    if (GNUNET_OK != ret)
+      break;
+  }
+}
+
+
+enum GNUNET_DB_QueryStatus
+TEH_PG_select_reserves_in_above_serial_id (
+  void *cls,
+  uint64_t serial_id,
+  TALER_EXCHANGEDB_ReserveInCallback cb,
+  void *cb_cls)
+{
+  struct PostgresClosure *pg = cls;
+  struct GNUNET_PQ_QueryParam params[] = {
+    GNUNET_PQ_query_param_uint64 (&serial_id),
+    GNUNET_PQ_query_param_end
+  };
+  struct ReservesInSerialContext risc = {
+    .cb = cb,
+    .cb_cls = cb_cls,
+    .pg = pg,
+    .status = GNUNET_OK
+  };
+  enum GNUNET_DB_QueryStatus qs;
+
+      /* Used in postgres_select_reserves_in_above_serial_id() to obtain 
inbound
+       transactions for reserves with serial id '\geq' the given parameter */
+  PREPARE (pg,
+           "audit_reserves_in_get_transactions_incr",
+           "SELECT"
+           " reserves.reserve_pub"
+           ",wire_reference"
+           ",credit_val"
+           ",credit_frac"
+           ",execution_date"
+           ",payto_uri AS sender_account_details"
+           ",reserve_in_serial_id"
+           " FROM reserves_in"
+           " JOIN reserves"
+           "   USING (reserve_pub)"
+           " JOIN wire_targets"
+           "   ON (wire_source_h_payto = wire_target_h_payto)"
+           " WHERE reserve_in_serial_id>=$1"
+           " ORDER BY reserve_in_serial_id;");
+  qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn,
+                                             
"audit_reserves_in_get_transactions_incr",
+                                             params,
+                                             &reserves_in_serial_helper_cb,
+                                             &risc);
+  if (GNUNET_OK != risc.status)
+    return GNUNET_DB_STATUS_HARD_ERROR;
+  return qs;
+}
diff --git a/src/exchangedb/pg_select_reserves_in_above_serial_id.h 
b/src/exchangedb/pg_select_reserves_in_above_serial_id.h
new file mode 100644
index 00000000..5f5dd2ec
--- /dev/null
+++ b/src/exchangedb/pg_select_reserves_in_above_serial_id.h
@@ -0,0 +1,44 @@
+/*
+   This file is part of TALER
+   Copyright (C) 2022 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 exchangedb/pg_select_reserves_in_above_serial_id.h
+ * @brief implementation of the select_reserves_in_above_serial_id function 
for Postgres
+ * @author Christian Grothoff
+ */
+#ifndef PG_SELECT_RESERVES_IN_ABOVE_SERIAL_ID_H
+#define PG_SELECT_RESERVES_IN_ABOVE_SERIAL_ID_H
+
+#include "taler_util.h"
+#include "taler_json_lib.h"
+#include "taler_exchangedb_plugin.h"
+/**
+ * Select inbound wire transfers into reserves_in above @a serial_id
+ * in monotonically increasing order.
+ *
+ * @param cls closure
+ * @param serial_id highest serial ID to exclude (select strictly larger)
+ * @param cb function to call on each result
+ * @param cb_cls closure for @a cb
+ * @return transaction status code
+ */
+enum GNUNET_DB_QueryStatus
+TEH_PG_select_reserves_in_above_serial_id (
+  void *cls,
+  uint64_t serial_id,
+  TALER_EXCHANGEDB_ReserveInCallback cb,
+  void *cb_cls);
+
+#endif
diff --git a/src/exchangedb/pg_select_reserves_in_above_serial_id_by_account.c 
b/src/exchangedb/pg_select_reserves_in_above_serial_id_by_account.c
new file mode 100644
index 00000000..ba73994f
--- /dev/null
+++ b/src/exchangedb/pg_select_reserves_in_above_serial_id_by_account.c
@@ -0,0 +1,169 @@
+/*
+   This file is part of TALER
+   Copyright (C) 2022 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 exchangedb/pg_select_reserves_in_above_serial_id_by_account.c
+ * @brief Implementation of the select_reserves_in_above_serial_id_by_account 
function for Postgres
+ * @author Christian Grothoff
+ */
+#include "platform.h"
+#include "taler_error_codes.h"
+#include "taler_dbevents.h"
+#include "taler_pq_lib.h"
+#include "pg_select_reserves_in_above_serial_id_by_account.h"
+#include "pg_helper.h"
+/**
+ * Closure for #reserves_in_serial_helper_cb().
+ */
+struct ReservesInSerialContext
+{
+
+  /**
+   * Callback to call.
+   */
+  TALER_EXCHANGEDB_ReserveInCallback cb;
+
+  /**
+   * Closure for @e cb.
+   */
+  void *cb_cls;
+
+  /**
+   * Plugin context.
+   */
+  struct PostgresClosure *pg;
+
+  /**
+   * Status code, set to #GNUNET_SYSERR on hard errors.
+   */
+  enum GNUNET_GenericReturnValue status;
+};
+
+
+/**
+ * Helper function to be called with the results of a SELECT statement
+ * that has returned @a num_results results.
+ *
+ * @param cls closure of type `struct ReservesInSerialContext`
+ * @param result the postgres result
+ * @param num_results the number of results in @a result
+ */
+static void
+reserves_in_serial_helper_cb (void *cls,
+                              PGresult *result,
+                              unsigned int num_results)
+{
+  struct ReservesInSerialContext *risc = cls;
+  struct PostgresClosure *pg = risc->pg;
+
+  for (unsigned int i = 0; i<num_results; i++)
+  {
+    struct TALER_ReservePublicKeyP reserve_pub;
+    struct TALER_Amount credit;
+    char *sender_account_details;
+    struct GNUNET_TIME_Timestamp execution_date;
+    uint64_t rowid;
+    uint64_t wire_reference;
+    struct GNUNET_PQ_ResultSpec rs[] = {
+      GNUNET_PQ_result_spec_auto_from_type ("reserve_pub",
+                                            &reserve_pub),
+      GNUNET_PQ_result_spec_uint64 ("wire_reference",
+                                    &wire_reference),
+      TALER_PQ_RESULT_SPEC_AMOUNT ("credit",
+                                   &credit),
+      GNUNET_PQ_result_spec_timestamp ("execution_date",
+                                       &execution_date),
+      GNUNET_PQ_result_spec_string ("sender_account_details",
+                                    &sender_account_details),
+      GNUNET_PQ_result_spec_uint64 ("reserve_in_serial_id",
+                                    &rowid),
+      GNUNET_PQ_result_spec_end
+    };
+    enum GNUNET_GenericReturnValue ret;
+
+    if (GNUNET_OK !=
+        GNUNET_PQ_extract_result (result,
+                                  rs,
+                                  i))
+    {
+      GNUNET_break (0);
+      risc->status = GNUNET_SYSERR;
+      return;
+    }
+    ret = risc->cb (risc->cb_cls,
+                    rowid,
+                    &reserve_pub,
+                    &credit,
+                    sender_account_details,
+                    wire_reference,
+                    execution_date);
+    GNUNET_PQ_cleanup_result (rs);
+    if (GNUNET_OK != ret)
+      break;
+  }
+}
+
+
+enum GNUNET_DB_QueryStatus
+TEH_PG_select_reserves_in_above_serial_id_by_account (
+  void *cls,
+  const char *account_name,
+  uint64_t serial_id,
+  TALER_EXCHANGEDB_ReserveInCallback cb,
+  void *cb_cls)
+{
+  struct PostgresClosure *pg = cls;
+  struct GNUNET_PQ_QueryParam params[] = {
+    GNUNET_PQ_query_param_uint64 (&serial_id),
+    GNUNET_PQ_query_param_string (account_name),
+    GNUNET_PQ_query_param_end
+  };
+  struct ReservesInSerialContext risc = {
+    .cb = cb,
+    .cb_cls = cb_cls,
+    .pg = pg,
+    .status = GNUNET_OK
+  };
+  enum GNUNET_DB_QueryStatus qs;
+
+      /* Used in postgres_select_reserves_in_above_serial_id() to obtain 
inbound
+       transactions for reserves with serial id '\geq' the given parameter */
+  PREPARE (pg,
+           "audit_reserves_in_get_transactions_incr_by_account",
+           "SELECT"
+           " reserves.reserve_pub"
+           ",wire_reference"
+           ",credit_val"
+           ",credit_frac"
+           ",execution_date"
+           ",payto_uri AS sender_account_details"
+           ",reserve_in_serial_id"
+           " FROM reserves_in"
+           " JOIN reserves "
+           "   USING (reserve_pub)"
+           " JOIN wire_targets"
+           "   ON (wire_source_h_payto = wire_target_h_payto)"
+           " WHERE reserve_in_serial_id>=$1 AND exchange_account_section=$2"
+           " ORDER BY reserve_in_serial_id;");
+
+  qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn,
+                                             
"audit_reserves_in_get_transactions_incr_by_account",
+                                             params,
+                                             &reserves_in_serial_helper_cb,
+                                             &risc);
+  if (GNUNET_OK != risc.status)
+    return GNUNET_DB_STATUS_HARD_ERROR;
+  return qs;
+}
diff --git a/src/exchangedb/pg_select_reserves_in_above_serial_id_by_account.h 
b/src/exchangedb/pg_select_reserves_in_above_serial_id_by_account.h
new file mode 100644
index 00000000..81855ede
--- /dev/null
+++ b/src/exchangedb/pg_select_reserves_in_above_serial_id_by_account.h
@@ -0,0 +1,46 @@
+/*
+   This file is part of TALER
+   Copyright (C) 2022 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 exchangedb/pg_select_reserves_in_above_serial_id_by_account.h
+ * @brief implementation of the select_reserves_in_above_serial_id_by_account 
function for Postgres
+ * @author Christian Grothoff
+ */
+#ifndef PG_SELECT_RESERVES_IN_ABOVE_SERIAL_ID_BY_ACCOUNT_H
+#define PG_SELECT_RESERVES_IN_ABOVE_SERIAL_ID_BY_ACCOUNT_H
+
+#include "taler_util.h"
+#include "taler_json_lib.h"
+#include "taler_exchangedb_plugin.h"
+/**
+ * Select inbound wire transfers into reserves_in above @a serial_id
+ * in monotonically increasing order by account.
+ *
+ * @param cls closure
+ * @param account_name name of the account to select by
+ * @param serial_id highest serial ID to exclude (select strictly larger)
+ * @param cb function to call on each result
+ * @param cb_cls closure for @a cb
+ * @return transaction status code
+ */
+enum GNUNET_DB_QueryStatus
+TEH_PG_select_reserves_in_above_serial_id_by_account (
+  void *cls,
+  const char *account_name,
+  uint64_t serial_id,
+  TALER_EXCHANGEDB_ReserveInCallback cb,
+  void *cb_cls);
+
+#endif
diff --git a/src/exchangedb/pg_select_wire_out_above_serial_id.c 
b/src/exchangedb/pg_select_wire_out_above_serial_id.c
new file mode 100644
index 00000000..e219f5d4
--- /dev/null
+++ b/src/exchangedb/pg_select_wire_out_above_serial_id.c
@@ -0,0 +1,159 @@
+/*
+   This file is part of TALER
+   Copyright (C) 2022 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 exchangedb/pg_select_wire_out_above_serial_id.c
+ * @brief Implementation of the select_wire_out_above_serial_id function for 
Postgres
+ * @author Christian Grothoff
+ */
+#include "platform.h"
+#include "taler_error_codes.h"
+#include "taler_dbevents.h"
+#include "taler_pq_lib.h"
+#include "pg_select_wire_out_above_serial_id.h"
+#include "pg_helper.h"
+
+/**
+ * Closure for #wire_out_serial_helper_cb().
+ */
+struct WireOutSerialContext
+{
+
+  /**
+   * Callback to call.
+   */
+  TALER_EXCHANGEDB_WireTransferOutCallback cb;
+
+  /**
+   * Closure for @e cb.
+   */
+  void *cb_cls;
+
+  /**
+   * Plugin context.
+   */
+  struct PostgresClosure *pg;
+
+  /**
+   * Status code, set to #GNUNET_SYSERR on hard errors.
+   */
+  int status;
+};
+
+
+/**
+ * Helper function to be called with the results of a SELECT statement
+ * that has returned @a num_results results.
+ *
+ * @param cls closure of type `struct WireOutSerialContext`
+ * @param result the postgres result
+ * @param num_results the number of results in @a result
+ */
+static void
+wire_out_serial_helper_cb (void *cls,
+                           PGresult *result,
+                           unsigned int num_results)
+{
+  struct WireOutSerialContext *wosc = cls;
+  struct PostgresClosure *pg = wosc->pg;
+
+  for (unsigned int i = 0; i<num_results; i++)
+  {
+    uint64_t rowid;
+    struct GNUNET_TIME_Timestamp date;
+    struct TALER_WireTransferIdentifierRawP wtid;
+    char *payto_uri;
+    struct TALER_Amount amount;
+    struct GNUNET_PQ_ResultSpec rs[] = {
+      GNUNET_PQ_result_spec_uint64 ("wireout_uuid",
+                                    &rowid),
+      GNUNET_PQ_result_spec_timestamp ("execution_date",
+                                       &date),
+      GNUNET_PQ_result_spec_auto_from_type ("wtid_raw",
+                                            &wtid),
+      GNUNET_PQ_result_spec_string ("payto_uri",
+                                    &payto_uri),
+      TALER_PQ_RESULT_SPEC_AMOUNT ("amount",
+                                   &amount),
+      GNUNET_PQ_result_spec_end
+    };
+    int ret;
+
+    if (GNUNET_OK !=
+        GNUNET_PQ_extract_result (result,
+                                  rs,
+                                  i))
+    {
+      GNUNET_break (0);
+      wosc->status = GNUNET_SYSERR;
+      return;
+    }
+    ret = wosc->cb (wosc->cb_cls,
+                    rowid,
+                    date,
+                    &wtid,
+                    payto_uri,
+                    &amount);
+    GNUNET_PQ_cleanup_result (rs);
+    if (GNUNET_OK != ret)
+      break;
+  }
+}
+
+
+
+enum GNUNET_DB_QueryStatus
+TEH_PG_select_wire_out_above_serial_id (
+  void *cls,
+  uint64_t serial_id,
+  TALER_EXCHANGEDB_WireTransferOutCallback cb,
+  void *cb_cls)
+{
+  struct PostgresClosure *pg = cls;
+  struct GNUNET_PQ_QueryParam params[] = {
+    GNUNET_PQ_query_param_uint64 (&serial_id),
+    GNUNET_PQ_query_param_end
+  };
+  struct WireOutSerialContext wosc = {
+    .cb = cb,
+    .cb_cls = cb_cls,
+    .pg = pg,
+    .status = GNUNET_OK
+  };
+  enum GNUNET_DB_QueryStatus qs;
+    /* Used in #postgres_select_wire_out_above_serial_id() */
+  PREPARE (pg,
+           "audit_get_wire_incr",
+           "SELECT"
+           " wireout_uuid"
+           ",execution_date"
+           ",wtid_raw"
+           ",payto_uri"
+           ",amount_val"
+           ",amount_frac"
+           " FROM wire_out"
+           "   JOIN wire_targets"
+           "     USING (wire_target_h_payto)"
+           " WHERE wireout_uuid>=$1"
+           " ORDER BY wireout_uuid ASC;");
+  qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn,
+                                             "audit_get_wire_incr",
+                                             params,
+                                             &wire_out_serial_helper_cb,
+                                             &wosc);
+  if (GNUNET_OK != wosc.status)
+    return GNUNET_DB_STATUS_HARD_ERROR;
+  return qs;
+}
diff --git a/src/exchangedb/pg_select_wire_out_above_serial_id.h 
b/src/exchangedb/pg_select_wire_out_above_serial_id.h
new file mode 100644
index 00000000..e42cb9b0
--- /dev/null
+++ b/src/exchangedb/pg_select_wire_out_above_serial_id.h
@@ -0,0 +1,45 @@
+/*
+   This file is part of TALER
+   Copyright (C) 2022 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 exchangedb/pg_select_wire_out_above_serial_id.h
+ * @brief implementation of the select_wire_out_above_serial_id function for 
Postgres
+ * @author Christian Grothoff
+ */
+#ifndef PG_SELECT_WIRE_OUT_ABOVE_SERIAL_ID_H
+#define PG_SELECT_WIRE_OUT_ABOVE_SERIAL_ID_H
+
+#include "taler_util.h"
+#include "taler_json_lib.h"
+#include "taler_exchangedb_plugin.h"
+
+/**
+ * Function called to select all wire transfers the exchange
+ * executed.
+ *
+ * @param cls closure
+ * @param serial_id highest serial ID to exclude (select strictly larger)
+ * @param cb function to call for ONE unfinished item
+ * @param cb_cls closure for @a cb
+ * @return transaction status code
+ */
+enum GNUNET_DB_QueryStatus
+TEH_PG_select_wire_out_above_serial_id (
+  void *cls,
+  uint64_t serial_id,
+  TALER_EXCHANGEDB_WireTransferOutCallback cb,
+  void *cb_cls);
+
+#endif
diff --git a/src/exchangedb/pg_select_wire_out_above_serial_id_by_account.c 
b/src/exchangedb/pg_select_wire_out_above_serial_id_by_account.c
new file mode 100644
index 00000000..08883c9a
--- /dev/null
+++ b/src/exchangedb/pg_select_wire_out_above_serial_id_by_account.c
@@ -0,0 +1,162 @@
+/*
+   This file is part of TALER
+   Copyright (C) 2022 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 exchangedb/pg_select_wire_out_above_serial_id_by_account.c
+ * @brief Implementation of the select_wire_out_above_serial_id_by_account 
function for Postgres
+ * @author Christian Grothoff
+ */
+#include "platform.h"
+#include "taler_error_codes.h"
+#include "taler_dbevents.h"
+#include "taler_pq_lib.h"
+#include "pg_select_wire_out_above_serial_id_by_account.h"
+#include "pg_helper.h"
+
+/**
+ * Closure for #wire_out_serial_helper_cb().
+ */
+struct WireOutSerialContext
+{
+
+  /**
+   * Callback to call.
+   */
+  TALER_EXCHANGEDB_WireTransferOutCallback cb;
+
+  /**
+   * Closure for @e cb.
+   */
+  void *cb_cls;
+
+  /**
+   * Plugin context.
+   */
+  struct PostgresClosure *pg;
+
+  /**
+   * Status code, set to #GNUNET_SYSERR on hard errors.
+   */
+  int status;
+};
+
+
+/**
+ * Helper function to be called with the results of a SELECT statement
+ * that has returned @a num_results results.
+ *
+ * @param cls closure of type `struct WireOutSerialContext`
+ * @param result the postgres result
+ * @param num_results the number of results in @a result
+ */
+static void
+wire_out_serial_helper_cb (void *cls,
+                           PGresult *result,
+                           unsigned int num_results)
+{
+  struct WireOutSerialContext *wosc = cls;
+  struct PostgresClosure *pg = wosc->pg;
+
+  for (unsigned int i = 0; i<num_results; i++)
+  {
+    uint64_t rowid;
+    struct GNUNET_TIME_Timestamp date;
+    struct TALER_WireTransferIdentifierRawP wtid;
+    char *payto_uri;
+    struct TALER_Amount amount;
+    struct GNUNET_PQ_ResultSpec rs[] = {
+      GNUNET_PQ_result_spec_uint64 ("wireout_uuid",
+                                    &rowid),
+      GNUNET_PQ_result_spec_timestamp ("execution_date",
+                                       &date),
+      GNUNET_PQ_result_spec_auto_from_type ("wtid_raw",
+                                            &wtid),
+      GNUNET_PQ_result_spec_string ("payto_uri",
+                                    &payto_uri),
+      TALER_PQ_RESULT_SPEC_AMOUNT ("amount",
+                                   &amount),
+      GNUNET_PQ_result_spec_end
+    };
+    int ret;
+
+    if (GNUNET_OK !=
+        GNUNET_PQ_extract_result (result,
+                                  rs,
+                                  i))
+    {
+      GNUNET_break (0);
+      wosc->status = GNUNET_SYSERR;
+      return;
+    }
+    ret = wosc->cb (wosc->cb_cls,
+                    rowid,
+                    date,
+                    &wtid,
+                    payto_uri,
+                    &amount);
+    GNUNET_PQ_cleanup_result (rs);
+    if (GNUNET_OK != ret)
+      break;
+  }
+}
+
+enum GNUNET_DB_QueryStatus
+TEH_PG_select_wire_out_above_serial_id_by_account (
+  void *cls,
+  const char *account_name,
+  uint64_t serial_id,
+  TALER_EXCHANGEDB_WireTransferOutCallback cb,
+  void *cb_cls)
+{
+  struct PostgresClosure *pg = cls;
+  struct GNUNET_PQ_QueryParam params[] = {
+    GNUNET_PQ_query_param_uint64 (&serial_id),
+    GNUNET_PQ_query_param_string (account_name),
+    GNUNET_PQ_query_param_end
+  };
+  struct WireOutSerialContext wosc = {
+    .cb = cb,
+    .cb_cls = cb_cls,
+    .pg = pg,
+    .status = GNUNET_OK
+  };
+  enum GNUNET_DB_QueryStatus qs;
+
+    /* Used in #postgres_select_wire_out_above_serial_id_by_account() */
+  PREPARE (pg,
+           "audit_get_wire_incr_by_account",
+           "SELECT"
+           " wireout_uuid"
+           ",execution_date"
+           ",wtid_raw"
+           ",payto_uri"
+           ",amount_val"
+           ",amount_frac"
+           " FROM wire_out"
+           "   JOIN wire_targets"
+           "     USING (wire_target_h_payto)"
+           " WHERE "
+           "      wireout_uuid>=$1 "
+           "  AND exchange_account_section=$2"
+           " ORDER BY wireout_uuid ASC;");
+  qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn,
+                                             "audit_get_wire_incr_by_account",
+                                             params,
+                                             &wire_out_serial_helper_cb,
+                                             &wosc);
+  if (GNUNET_OK != wosc.status)
+    return GNUNET_DB_STATUS_HARD_ERROR;
+  return qs;
+}
diff --git a/src/exchangedb/pg_select_wire_out_above_serial_id_by_account.h 
b/src/exchangedb/pg_select_wire_out_above_serial_id_by_account.h
new file mode 100644
index 00000000..98315cac
--- /dev/null
+++ b/src/exchangedb/pg_select_wire_out_above_serial_id_by_account.h
@@ -0,0 +1,46 @@
+/*
+   This file is part of TALER
+   Copyright (C) 2022 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 exchangedb/pg_select_wire_out_above_serial_id_by_account.h
+ * @brief implementation of the select_wire_out_above_serial_id_by_account 
function for Postgres
+ * @author Christian Grothoff
+ */
+#ifndef PG_SELECT_WIRE_OUT_ABOVE_SERIAL_ID_BY_ACCOUNT_H
+#define PG_SELECT_WIRE_OUT_ABOVE_SERIAL_ID_BY_ACCOUNT_H
+
+#include "taler_util.h"
+#include "taler_json_lib.h"
+#include "taler_exchangedb_plugin.h"
+
+/**
+ * Function called to select all wire transfers the exchange
+ * executed by account.
+ *
+ * @param cls closure
+ * @param account_name account to select
+ * @param serial_id highest serial ID to exclude (select strictly larger)
+ * @param cb function to call for ONE unfinished item
+ * @param cb_cls closure for @a cb
+ * @return transaction status code
+ */
+enum GNUNET_DB_QueryStatus
+TEH_PG_select_wire_out_above_serial_id_by_account (
+  void *cls,
+  const char *account_name,
+  uint64_t serial_id,
+  TALER_EXCHANGEDB_WireTransferOutCallback cb,
+  void *cb_cls);
+#endif
diff --git a/src/exchangedb/pg_select_withdrawals_above_serial_id.c 
b/src/exchangedb/pg_select_withdrawals_above_serial_id.c
new file mode 100644
index 00000000..4718a62a
--- /dev/null
+++ b/src/exchangedb/pg_select_withdrawals_above_serial_id.c
@@ -0,0 +1,175 @@
+/*
+   This file is part of TALER
+   Copyright (C) 2022 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 exchangedb/pg_select_withdrawals_above_serial_id.c
+ * @brief Implementation of the select_withdrawals_above_serial_id function 
for Postgres
+ * @author Christian Grothoff
+ */
+#include "platform.h"
+#include "taler_error_codes.h"
+#include "taler_dbevents.h"
+#include "taler_pq_lib.h"
+#include "pg_select_withdrawals_above_serial_id.h"
+#include "pg_helper.h"
+
+/**
+ * Closure for #reserves_out_serial_helper_cb().
+ */
+struct ReservesOutSerialContext
+{
+
+  /**
+   * Callback to call.
+   */
+  TALER_EXCHANGEDB_WithdrawCallback cb;
+
+  /**
+   * Closure for @e cb.
+   */
+  void *cb_cls;
+
+  /**
+   * Plugin context.
+   */
+  struct PostgresClosure *pg;
+
+  /**
+   * Status code, set to #GNUNET_SYSERR on hard errors.
+   */
+  enum GNUNET_GenericReturnValue status;
+};
+
+
+/**
+ * Helper function to be called with the results of a SELECT statement
+ * that has returned @a num_results results.
+ *
+ * @param cls closure of type `struct ReservesOutSerialContext`
+ * @param result the postgres result
+ * @param num_results the number of results in @a result
+ */
+static void
+reserves_out_serial_helper_cb (void *cls,
+                               PGresult *result,
+                               unsigned int num_results)
+{
+  struct ReservesOutSerialContext *rosc = cls;
+  struct PostgresClosure *pg = rosc->pg;
+
+  for (unsigned int i = 0; i<num_results; i++)
+  {
+    struct TALER_BlindedCoinHashP h_blind_ev;
+    struct TALER_DenominationPublicKey denom_pub;
+    struct TALER_ReservePublicKeyP reserve_pub;
+    struct TALER_ReserveSignatureP reserve_sig;
+    struct GNUNET_TIME_Timestamp execution_date;
+    struct TALER_Amount amount_with_fee;
+    uint64_t rowid;
+    struct GNUNET_PQ_ResultSpec rs[] = {
+      GNUNET_PQ_result_spec_auto_from_type ("h_blind_ev",
+                                            &h_blind_ev),
+      TALER_PQ_result_spec_denom_pub ("denom_pub",
+                                      &denom_pub),
+      GNUNET_PQ_result_spec_auto_from_type ("reserve_pub",
+                                            &reserve_pub),
+      GNUNET_PQ_result_spec_auto_from_type ("reserve_sig",
+                                            &reserve_sig),
+      GNUNET_PQ_result_spec_timestamp ("execution_date",
+                                       &execution_date),
+      TALER_PQ_RESULT_SPEC_AMOUNT ("amount_with_fee",
+                                   &amount_with_fee),
+      GNUNET_PQ_result_spec_uint64 ("reserve_out_serial_id",
+                                    &rowid),
+      GNUNET_PQ_result_spec_end
+    };
+    enum GNUNET_GenericReturnValue ret;
+
+    if (GNUNET_OK !=
+        GNUNET_PQ_extract_result (result,
+                                  rs,
+                                  i))
+    {
+      GNUNET_break (0);
+      rosc->status = GNUNET_SYSERR;
+      return;
+    }
+    ret = rosc->cb (rosc->cb_cls,
+                    rowid,
+                    &h_blind_ev,
+                    &denom_pub,
+                    &reserve_pub,
+                    &reserve_sig,
+                    execution_date,
+                    &amount_with_fee);
+    GNUNET_PQ_cleanup_result (rs);
+    if (GNUNET_OK != ret)
+      break;
+  }
+}
+
+
+
+enum GNUNET_DB_QueryStatus
+TEH_PG_select_withdrawals_above_serial_id (
+  void *cls,
+  uint64_t serial_id,
+  TALER_EXCHANGEDB_WithdrawCallback cb,
+  void *cb_cls)
+{
+  struct PostgresClosure *pg = cls;
+  struct GNUNET_PQ_QueryParam params[] = {
+    GNUNET_PQ_query_param_uint64 (&serial_id),
+    GNUNET_PQ_query_param_end
+  };
+  struct ReservesOutSerialContext rosc = {
+    .cb = cb,
+    .cb_cls = cb_cls,
+    .pg = pg,
+    .status = GNUNET_OK
+  };
+  enum GNUNET_DB_QueryStatus qs;
+
+      /* Fetch deposits with rowid '\geq' the given parameter */
+
+  PREPARE (pg,
+           "audit_get_reserves_out_incr",
+           "SELECT"
+           " h_blind_ev"
+           ",denom.denom_pub"
+           ",reserve_sig"
+           ",reserves.reserve_pub"
+           ",execution_date"
+           ",amount_with_fee_val"
+           ",amount_with_fee_frac"
+           ",reserve_out_serial_id"
+           " FROM reserves_out"
+           "    JOIN reserves"
+           "      USING (reserve_uuid)"
+           "    JOIN denominations denom"
+           "      USING (denominations_serial)"
+           " WHERE reserve_out_serial_id>=$1"
+           " ORDER BY reserve_out_serial_id ASC;");
+
+
+  qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn,
+                                             "audit_get_reserves_out_incr",
+                                             params,
+                                             &reserves_out_serial_helper_cb,
+                                             &rosc);
+  if (GNUNET_OK != rosc.status)
+    return GNUNET_DB_STATUS_HARD_ERROR;
+  return qs;
+}
diff --git a/src/exchangedb/pg_select_withdrawals_above_serial_id.h 
b/src/exchangedb/pg_select_withdrawals_above_serial_id.h
new file mode 100644
index 00000000..adc23fb3
--- /dev/null
+++ b/src/exchangedb/pg_select_withdrawals_above_serial_id.h
@@ -0,0 +1,44 @@
+/*
+   This file is part of TALER
+   Copyright (C) 2022 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 exchangedb/pg_select_withdrawals_above_serial_id.h
+ * @brief implementation of the select_withdrawals_above_serial_id function 
for Postgres
+ * @author Christian Grothoff
+ */
+#ifndef PG_SELECT_WITHDRAWALS_ABOVE_SERIAL_ID_H
+#define PG_SELECT_WITHDRAWALS_ABOVE_SERIAL_ID_H
+
+#include "taler_util.h"
+#include "taler_json_lib.h"
+#include "taler_exchangedb_plugin.h"
+
+/**
+ * Select withdraw operations from reserves_out above @a serial_id
+ * in monotonically increasing order.
+ *
+ * @param cls closure
+ * @param serial_id highest serial ID to exclude (select strictly larger)
+ * @param cb function to call on each result
+ * @param cb_cls closure for @a cb
+ * @return transaction status code
+ */
+enum GNUNET_DB_QueryStatus
+TEH_PG_select_withdrawals_above_serial_id (
+  void *cls,
+  uint64_t serial_id,
+  TALER_EXCHANGEDB_WithdrawCallback cb,
+  void *cb_cls);
+#endif
diff --git a/src/exchangedb/pg_set_extension_manifest.c 
b/src/exchangedb/pg_set_extension_manifest.c
new file mode 100644
index 00000000..86e9d3f0
--- /dev/null
+++ b/src/exchangedb/pg_set_extension_manifest.c
@@ -0,0 +1,56 @@
+/*
+   This file is part of TALER
+   Copyright (C) 2022 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 exchangedb/pg_set_extension_manifest.c
+ * @brief Implementation of the set_extension_manifest function for Postgres
+ * @author Christian Grothoff
+ */
+#include "platform.h"
+#include "taler_error_codes.h"
+#include "taler_dbevents.h"
+#include "taler_pq_lib.h"
+#include "pg_set_extension_manifest.h"
+#include "pg_helper.h"
+
+
+enum GNUNET_DB_QueryStatus
+TEH_PG_set_extension_manifest (void *cls,
+                                 const char *extension_name,
+                                 const char *manifest)
+{
+  struct PostgresClosure *pg = cls;
+  struct GNUNET_PQ_QueryParam pcfg =
+    (NULL == manifest || 0 == *manifest)
+    ? GNUNET_PQ_query_param_null ()
+    : GNUNET_PQ_query_param_string (manifest);
+  struct GNUNET_PQ_QueryParam params[] = {
+    GNUNET_PQ_query_param_string (extension_name),
+    pcfg,
+    GNUNET_PQ_query_param_end
+  };
+
+
+  PREPARE (pg,
+           "set_extension_manifest",
+           "INSERT INTO extensions (name, manifest) VALUES ($1, $2) "
+           "ON CONFLICT (name) "
+           "DO UPDATE SET manifest=$2");
+
+
+  return GNUNET_PQ_eval_prepared_non_select (pg->conn,
+                                             "set_extension_manifest",
+                                             params);
+}
diff --git a/src/exchangedb/pg_set_extension_manifest.h 
b/src/exchangedb/pg_set_extension_manifest.h
new file mode 100644
index 00000000..ead3abd2
--- /dev/null
+++ b/src/exchangedb/pg_set_extension_manifest.h
@@ -0,0 +1,43 @@
+/*
+   This file is part of TALER
+   Copyright (C) 2022 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 exchangedb/pg_set_extension_manifest.h
+ * @brief implementation of the set_extension_manifest function for Postgres
+ * @author Christian Grothoff
+ */
+#ifndef PG_SET_EXTENSION_MANIFEST_H
+#define PG_SET_EXTENSION_MANIFEST_H
+
+#include "taler_util.h"
+#include "taler_json_lib.h"
+#include "taler_exchangedb_plugin.h"
+
+/**
+ * Function called to save the manifest of an extension
+ * (age-restriction, policy_extension_...) After successful storage of the
+ * configuration it triggers the corresponding event.
+ *
+ * @param cls the @e cls of this struct with the plugin-specific state
+ * @param extension_name the name of the extension
+ * @param manifest JSON object of the configuration as string
+ * @return transaction status code
+ */
+enum GNUNET_DB_QueryStatus
+TEH_PG_set_extension_manifest (void *cls,
+                                 const char *extension_name,
+                               const char *manifest);
+
+#endif
diff --git a/src/exchangedb/pg_set_purse_balance.c 
b/src/exchangedb/pg_set_purse_balance.c
new file mode 100644
index 00000000..a996104b
--- /dev/null
+++ b/src/exchangedb/pg_set_purse_balance.c
@@ -0,0 +1,55 @@
+/*
+   This file is part of TALER
+   Copyright (C) 2022 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 exchangedb/pg_set_purse_balance.c
+ * @brief Implementation of the set_purse_balance function for Postgres
+ * @author Christian Grothoff
+ */
+#include "platform.h"
+#include "taler_error_codes.h"
+#include "taler_dbevents.h"
+#include "taler_pq_lib.h"
+#include "pg_set_purse_balance.h"
+#include "pg_helper.h"
+
+
+enum GNUNET_DB_QueryStatus
+TEH_PG_set_purse_balance (
+  void *cls,
+  const struct TALER_PurseContractPublicKeyP *purse_pub,
+  const struct TALER_Amount *balance)
+{
+  struct PostgresClosure *pg = cls;
+  struct GNUNET_PQ_QueryParam params[] = {
+    GNUNET_PQ_query_param_auto_from_type (purse_pub),
+    TALER_PQ_query_param_amount (balance),
+    GNUNET_PQ_query_param_end
+  };
+
+  PREPARE (pg,
+           "set_purse_balance",
+           "UPDATE purse_requests"
+           " SET balance_val=$2"
+           "    ,balance_frac=$3"
+           " WHERE purse_pub=$1;");
+
+  return GNUNET_PQ_eval_prepared_non_select (pg->conn,
+                                             "set_purse_balance",
+                                             params);
+}
+
+
+
diff --git a/src/exchangedb/pg_set_purse_balance.h 
b/src/exchangedb/pg_set_purse_balance.h
new file mode 100644
index 00000000..44b76556
--- /dev/null
+++ b/src/exchangedb/pg_set_purse_balance.h
@@ -0,0 +1,43 @@
+/*
+   This file is part of TALER
+   Copyright (C) 2022 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 exchangedb/pg_set_purse_balance.h
+ * @brief implementation of the set_purse_balance function for Postgres
+ * @author Christian Grothoff
+ */
+#ifndef PG_SET_PURSE_BALANCE_H
+#define PG_SET_PURSE_BALANCE_H
+
+#include "taler_util.h"
+#include "taler_json_lib.h"
+#include "taler_exchangedb_plugin.h"
+/**
+ * Set the current @a balance in the purse
+ * identified by @a purse_pub. Used by the auditor
+ * to update the balance as calculated by the auditor.
+ *
+ * @param cls closure
+ * @param purse_pub public key of a purse
+ * @param balance new balance to store under the purse
+ * @return transaction status
+ */
+enum GNUNET_DB_QueryStatus
+TEH_PG_set_purse_balance (
+  void *cls,
+  const struct TALER_PurseContractPublicKeyP *purse_pub,
+  const struct TALER_Amount *balance);
+
+#endif
diff --git a/src/exchangedb/pg_setup_foreign_servers.c 
b/src/exchangedb/pg_setup_foreign_servers.c
new file mode 100644
index 00000000..490ae4c2
--- /dev/null
+++ b/src/exchangedb/pg_setup_foreign_servers.c
@@ -0,0 +1,118 @@
+/*
+   This file is part of TALER
+   Copyright (C) 2022 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 exchangedb/pg_setup_foreign_servers.c
+ * @brief Implementation of the setup_foreign_servers function for Postgres
+ * @author Christian Grothoff
+ */
+#include "platform.h"
+#include "taler_error_codes.h"
+#include "taler_dbevents.h"
+#include "taler_pq_lib.h"
+#include "pg_setup_foreign_servers.h"
+#include "pg_helper.h"
+
+
+
+enum GNUNET_GenericReturnValue
+TEH_PG_setup_foreign_servers (void *cls,
+                                uint32_t num)
+{
+  struct PostgresClosure *pg = cls;
+  struct GNUNET_PQ_Context *conn;
+  enum GNUNET_GenericReturnValue ret = GNUNET_OK;
+  char *shard_domain = NULL;
+  char *remote_user = NULL;
+  char *remote_user_pw = NULL;
+
+  if (GNUNET_OK !=
+      GNUNET_CONFIGURATION_get_value_string (pg->cfg,
+                                             "exchange",
+                                             "SHARD_DOMAIN",
+                                             &shard_domain))
+  {
+    GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
+                               "exchange",
+                               "SHARD_DOMAIN");
+    return GNUNET_SYSERR;
+  }
+  if (GNUNET_OK !=
+      GNUNET_CONFIGURATION_get_value_string (pg->cfg,
+                                             "exchangedb-postgres",
+                                             "SHARD_REMOTE_USER",
+                                             &remote_user))
+  {
+    GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
+                               "exchangedb-postgres",
+                               "SHARD_REMOTE_USER");
+    GNUNET_free (shard_domain);
+    return GNUNET_SYSERR;
+  }
+  if (GNUNET_OK !=
+      GNUNET_CONFIGURATION_get_value_string (pg->cfg,
+                                             "exchangedb-postgres",
+                                             "SHARD_REMOTE_USER_PW",
+                                             &remote_user_pw))
+  {
+    GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
+                               "exchangedb-postgres",
+                               "SHARD_REMOTE_USER_PW");
+    GNUNET_free (shard_domain);
+    GNUNET_free (remote_user);
+    return GNUNET_SYSERR;
+  }
+
+  struct GNUNET_PQ_QueryParam params[] = {
+    GNUNET_PQ_query_param_uint32 (&num),
+    GNUNET_PQ_query_param_string (shard_domain),
+    GNUNET_PQ_query_param_string (remote_user),
+    GNUNET_PQ_query_param_string (remote_user_pw),
+    GNUNET_PQ_query_param_end
+  };
+  struct GNUNET_PQ_ExecuteStatement es[] = {
+    GNUNET_PQ_make_try_execute ("SET search_path TO exchange;"),
+    GNUNET_PQ_EXECUTE_STATEMENT_END
+  };
+  struct GNUNET_PQ_PreparedStatement ps[] = {
+    GNUNET_PQ_make_prepare ("create_foreign_servers",
+                            "SELECT"
+                            " create_foreign_servers"
+                            " ($1, $2, $3, $4);"),
+    GNUNET_PQ_PREPARED_STATEMENT_END
+  };
+
+  conn = GNUNET_PQ_connect_with_cfg (pg->cfg,
+                                     "exchangedb-postgres",
+                                     NULL,
+                                     es,
+                                     ps);
+  if (NULL == conn)
+  {
+    ret = GNUNET_SYSERR;
+  }
+  else if (0 > GNUNET_PQ_eval_prepared_non_select (conn,
+                                                   "create_foreign_servers",
+                                                   params))
+  {
+    ret = GNUNET_SYSERR;
+  }
+  GNUNET_free (shard_domain);
+  GNUNET_free (remote_user);
+  GNUNET_free (remote_user_pw);
+  GNUNET_PQ_disconnect (conn);
+  return ret;
+}
+
diff --git a/src/exchangedb/pg_setup_foreign_servers.h 
b/src/exchangedb/pg_setup_foreign_servers.h
new file mode 100644
index 00000000..65ba0343
--- /dev/null
+++ b/src/exchangedb/pg_setup_foreign_servers.h
@@ -0,0 +1,39 @@
+/*
+   This file is part of TALER
+   Copyright (C) 2022 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 exchangedb/pg_setup_foreign_servers.h
+ * @brief implementation of the setup_foreign_servers function for Postgres
+ * @author Christian Grothoff
+ */
+#ifndef PG_SETUP_FOREIGN_SERVERS_H
+#define PG_SETUP_FOREIGN_SERVERS_H
+
+#include "taler_util.h"
+#include "taler_json_lib.h"
+#include "taler_exchangedb_plugin.h"
+
+
+/**
+ * Setup foreign servers (shards) for already existing tables
+ *
+ * @param cls the `struct PostgresClosure` with the plugin-specific state
+ * @param num the number of foreign servers (shards) to create for each 
partitioned table
+ * @return #GNUNET_OK upon success; #GNUNET_SYSERR upon failure
+ */
+enum GNUNET_GenericReturnValue
+TEH_PG_setup_foreign_servers (void *cls,
+                              uint32_t num);
+#endif
diff --git a/src/exchangedb/pg_setup_wire_target.c 
b/src/exchangedb/pg_setup_wire_target.c
new file mode 100644
index 00000000..a2d890c5
--- /dev/null
+++ b/src/exchangedb/pg_setup_wire_target.c
@@ -0,0 +1,54 @@
+/*
+   This file is part of TALER
+   Copyright (C) 2022 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 exchangedb/pg_setup_wire_target.c
+ * @brief Implementation of the setup_wire_target function for Postgres
+ * @author Christian Grothoff
+ */
+#include "platform.h"
+#include "taler_error_codes.h"
+#include "taler_dbevents.h"
+#include "taler_pq_lib.h"
+#include "pg_setup_wire_target.h"
+
+
+enum GNUNET_DB_QueryStatus
+TEH_PG_setup_wire_target(
+  struct PostgresClosure *pg,
+  const char *payto_uri,
+  struct TALER_PaytoHashP *h_payto)
+{
+  struct GNUNET_PQ_QueryParam iparams[] = {
+    GNUNET_PQ_query_param_auto_from_type (h_payto),
+    GNUNET_PQ_query_param_string (payto_uri),
+    GNUNET_PQ_query_param_end
+  };
+
+  TALER_payto_hash (payto_uri,
+                    h_payto);
+
+  PREPARE (pg,
+           "insert_kyc_status",
+           "INSERT INTO wire_targets"
+           "  (wire_target_h_payto"
+           "  ,payto_uri"
+           "  ) VALUES "
+           "  ($1, $2)"
+           " ON CONFLICT DO NOTHING");
+  return GNUNET_PQ_eval_prepared_non_select (pg->conn,
+                                             "insert_kyc_status",
+                                             iparams);
+}
diff --git a/src/exchangedb/pg_setup_wire_target.h 
b/src/exchangedb/pg_setup_wire_target.h
new file mode 100644
index 00000000..12c0e59b
--- /dev/null
+++ b/src/exchangedb/pg_setup_wire_target.h
@@ -0,0 +1,43 @@
+/*
+   This file is part of TALER
+   Copyright (C) 2022 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 exchangedb/pg_setup_wire_target.h
+ * @brief implementation of the setup_wire_target function for Postgres
+ * @author Christian Grothoff
+ */
+#ifndef PG_SETUP_WIRE_TARGET_H
+#define PG_SETUP_WIRE_TARGET_H
+
+#include "taler_util.h"
+#include "taler_json_lib.h"
+#include "pg_helper.h"
+#include "taler_exchangedb_plugin.h"
+
+/**
+ * Setup new wire target for @a payto_uri.
+ *
+ * @param pg the plugin-specific state
+ * @param payto_uri the payto URI to check
+ * @param[out] h_payto set to the hash of @a payto_uri
+ * @return transaction status
+ */
+enum GNUNET_DB_QueryStatus
+TEH_PG_setup_wire_target(
+  struct PostgresClosure *pg,
+  const char *payto_uri,
+  struct TALER_PaytoHashP *h_payto);
+
+#endif
diff --git a/src/exchangedb/pg_start_deferred_wire_out.c 
b/src/exchangedb/pg_start_deferred_wire_out.c
new file mode 100644
index 00000000..abdc1602
--- /dev/null
+++ b/src/exchangedb/pg_start_deferred_wire_out.c
@@ -0,0 +1,59 @@
+/*
+   This file is part of TALER
+   Copyright (C) 2022 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 exchangedb/pg_start_deferred_wire_out.c
+ * @brief Implementation of the start_deferred_wire_out function for Postgres
+ * @author Christian Grothoff
+ */
+#include "platform.h"
+#include "taler_error_codes.h"
+#include "taler_dbevents.h"
+#include "taler_pq_lib.h"
+#include "pg_start_deferred_wire_out.h"
+#include "pg_helper.h"
+#include "pg_preflight.h"
+#include "pg_rollback.h"
+
+enum GNUNET_GenericReturnValue
+TEH_PG_start_deferred_wire_out (void *cls)
+{
+  struct PostgresClosure *pg = cls;
+  struct GNUNET_PQ_ExecuteStatement es[] = {
+    GNUNET_PQ_make_execute (
+      "START TRANSACTION ISOLATION LEVEL READ COMMITTED;"),
+    GNUNET_PQ_make_execute ("SET CONSTRAINTS ALL DEFERRED;"),
+    GNUNET_PQ_EXECUTE_STATEMENT_END
+  };
+
+  if (GNUNET_SYSERR ==
+      TEH_PG_preflight (pg))
+    return GNUNET_SYSERR;
+  if (GNUNET_OK !=
+      GNUNET_PQ_exec_statements (pg->conn,
+                                 es))
+  {
+    TALER_LOG_ERROR (
+      "Failed to defer wire_out_ref constraint on transaction\n");
+    GNUNET_break (0);
+    TEH_PG_rollback (pg);
+    return GNUNET_SYSERR;
+  }
+  pg->transaction_name = "deferred wire out";
+  GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+              "Starting READ COMMITTED DEFERRED transaction `%s'\n",
+              pg->transaction_name);
+  return GNUNET_OK;
+}
diff --git a/src/exchangedb/pg_start_deferred_wire_out.h 
b/src/exchangedb/pg_start_deferred_wire_out.h
new file mode 100644
index 00000000..ed444ef7
--- /dev/null
+++ b/src/exchangedb/pg_start_deferred_wire_out.h
@@ -0,0 +1,39 @@
+/*
+   This file is part of TALER
+   Copyright (C) 2022 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 exchangedb/pg_start_deferred_wire_out.h
+ * @brief implementation of the start_deferred_wire_out function for Postgres
+ * @author Christian Grothoff
+ */
+#ifndef PG_START_DEFERRED_WIRE_OUT_H
+#define PG_START_DEFERRED_WIRE_OUT_H
+
+#include "taler_util.h"
+#include "taler_json_lib.h"
+#include "taler_exchangedb_plugin.h"
+
+/**
+ * Starts a READ COMMITTED transaction where we transiently violate the foreign
+ * constraints on the "wire_out" table as we insert aggregations
+ * and only add the wire transfer out at the end.
+ *
+ * @param cls the @e cls of this struct with the plugin-specific state
+ * @return #GNUNET_OK on success
+ */
+enum GNUNET_GenericReturnValue
+TEH_PG_start_deferred_wire_out (void *cls);
+
+#endif
diff --git a/src/exchangedb/pg_store_wire_transfer_out.c 
b/src/exchangedb/pg_store_wire_transfer_out.c
new file mode 100644
index 00000000..8bc0147d
--- /dev/null
+++ b/src/exchangedb/pg_store_wire_transfer_out.c
@@ -0,0 +1,63 @@
+/*
+   This file is part of TALER
+   Copyright (C) 2022 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 exchangedb/pg_store_wire_transfer_out.c
+ * @brief Implementation of the store_wire_transfer_out function for Postgres
+ * @author Christian Grothoff
+ */
+#include "platform.h"
+#include "taler_error_codes.h"
+#include "taler_dbevents.h"
+#include "taler_pq_lib.h"
+#include "pg_store_wire_transfer_out.h"
+#include "pg_helper.h"
+
+enum GNUNET_DB_QueryStatus
+TEH_PG_store_wire_transfer_out (
+  void *cls,
+  struct GNUNET_TIME_Timestamp date,
+  const struct TALER_WireTransferIdentifierRawP *wtid,
+  const struct TALER_PaytoHashP *h_payto,
+  const char *exchange_account_section,
+  const struct TALER_Amount *amount)
+{
+  struct PostgresClosure *pg = cls;
+  struct GNUNET_PQ_QueryParam params[] = {
+    GNUNET_PQ_query_param_timestamp (&date),
+    GNUNET_PQ_query_param_auto_from_type (wtid),
+    GNUNET_PQ_query_param_auto_from_type (h_payto),
+    GNUNET_PQ_query_param_string (exchange_account_section),
+    TALER_PQ_query_param_amount (amount),
+    GNUNET_PQ_query_param_end
+  };
+
+      /* Used in #postgres_store_wire_transfer_out */
+  PREPARE (pg,
+           "insert_wire_out",
+           "INSERT INTO wire_out "
+           "(execution_date"
+           ",wtid_raw"
+           ",wire_target_h_payto"
+           ",exchange_account_section"
+           ",amount_val"
+           ",amount_frac"
+           ") VALUES "
+           "($1, $2, $3, $4, $5, $6);");
+
+  return GNUNET_PQ_eval_prepared_non_select (pg->conn,
+                                             "insert_wire_out",
+                                             params);
+}
diff --git a/src/exchangedb/pg_store_wire_transfer_out.h 
b/src/exchangedb/pg_store_wire_transfer_out.h
new file mode 100644
index 00000000..79950e65
--- /dev/null
+++ b/src/exchangedb/pg_store_wire_transfer_out.h
@@ -0,0 +1,48 @@
+/*
+   This file is part of TALER
+   Copyright (C) 2022 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 exchangedb/pg_store_wire_transfer_out.h
+ * @brief implementation of the store_wire_transfer_out function for Postgres
+ * @author Christian Grothoff
+ */
+#ifndef PG_STORE_WIRE_TRANSFER_OUT_H
+#define PG_STORE_WIRE_TRANSFER_OUT_H
+
+#include "taler_util.h"
+#include "taler_json_lib.h"
+#include "taler_exchangedb_plugin.h"
+/**
+ * Store information about an outgoing wire transfer that was executed.
+ *
+ * @param cls closure
+ * @param date time of the wire transfer
+ * @param wtid subject of the wire transfer
+ * @param h_payto identifies the receiver account of the wire transfer
+ * @param exchange_account_section configuration section of the exchange 
specifying the
+ *        exchange's bank account being used
+ * @param amount amount that was transmitted
+ * @return transaction status code
+ */
+enum GNUNET_DB_QueryStatus
+TEH_PG_store_wire_transfer_out (
+  void *cls,
+  struct GNUNET_TIME_Timestamp date,
+  const struct TALER_WireTransferIdentifierRawP *wtid,
+  const struct TALER_PaytoHashP *h_payto,
+  const char *exchange_account_section,
+  const struct TALER_Amount *amount);
+
+#endif
diff --git a/src/exchangedb/pg_update_aggregation_transient.c 
b/src/exchangedb/pg_update_aggregation_transient.c
new file mode 100644
index 00000000..1d91301c
--- /dev/null
+++ b/src/exchangedb/pg_update_aggregation_transient.c
@@ -0,0 +1,60 @@
+/*
+   This file is part of TALER
+   Copyright (C) 2022 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 exchangedb/pg_update_aggregation_transient.c
+ * @brief Implementation of the update_aggregation_transient function for 
Postgres
+ * @author Christian Grothoff
+ */
+#include "platform.h"
+#include "taler_error_codes.h"
+#include "taler_dbevents.h"
+#include "taler_pq_lib.h"
+#include "pg_update_aggregation_transient.h"
+#include "pg_helper.h"
+
+
+
+enum GNUNET_DB_QueryStatus
+TEH_PG_update_aggregation_transient (
+  void *cls,
+  const struct TALER_PaytoHashP *h_payto,
+  const struct TALER_WireTransferIdentifierRawP *wtid,
+  uint64_t kyc_requirement_row,
+  const struct TALER_Amount *total)
+{
+  struct PostgresClosure *pg = cls;
+  struct GNUNET_PQ_QueryParam params[] = {
+    TALER_PQ_query_param_amount (total),
+    GNUNET_PQ_query_param_auto_from_type (h_payto),
+    GNUNET_PQ_query_param_auto_from_type (wtid),
+    GNUNET_PQ_query_param_uint64 (&kyc_requirement_row),
+    GNUNET_PQ_query_param_end
+  };
+
+
+    /* Used in #postgres_update_aggregation_transient() */
+  PREPARE (pg,
+           "update_aggregation_transient",
+           "UPDATE aggregation_transient"
+           " SET amount_val=$1"
+           "    ,amount_frac=$2"
+           "    ,legitimization_requirement_serial_id=$5"
+           " WHERE wire_target_h_payto=$3"
+           "   AND wtid_raw=$4");
+  return GNUNET_PQ_eval_prepared_non_select (pg->conn,
+                                             "update_aggregation_transient",
+                                             params);
+}
diff --git a/src/exchangedb/pg_update_aggregation_transient.h 
b/src/exchangedb/pg_update_aggregation_transient.h
new file mode 100644
index 00000000..c444e85b
--- /dev/null
+++ b/src/exchangedb/pg_update_aggregation_transient.h
@@ -0,0 +1,46 @@
+/*
+   This file is part of TALER
+   Copyright (C) 2022 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 exchangedb/pg_update_aggregation_transient.h
+ * @brief implementation of the update_aggregation_transient function for 
Postgres
+ * @author Christian Grothoff
+ */
+#ifndef PG_UPDATE_AGGREGATION_TRANSIENT_H
+#define PG_UPDATE_AGGREGATION_TRANSIENT_H
+
+#include "taler_util.h"
+#include "taler_json_lib.h"
+#include "taler_exchangedb_plugin.h"
+/**
+ * Update existing entry in the transient aggregation table.
+ * @a h_payto is only needed for query performance.
+ *
+ * @param cls the @e cls of this struct with the plugin-specific state
+ * @param h_payto destination of the wire transfer
+ * @param wtid the raw wire transfer identifier to update
+ * @param kyc_requirement_row row in legitimization_requirements that need to 
be satisfied to continue, or 0 for none
+ * @param total new total amount to be wired in the future
+ * @return transaction status
+ */
+enum GNUNET_DB_QueryStatus
+TEH_PG_update_aggregation_transient (
+  void *cls,
+  const struct TALER_PaytoHashP *h_payto,
+  const struct TALER_WireTransferIdentifierRawP *wtid,
+  uint64_t kyc_requirement_row,
+  const struct TALER_Amount *total);
+
+#endif
diff --git a/src/exchangedb/pg_update_wire.c b/src/exchangedb/pg_update_wire.c
new file mode 100644
index 00000000..f5f5672c
--- /dev/null
+++ b/src/exchangedb/pg_update_wire.c
@@ -0,0 +1,54 @@
+/*
+   This file is part of TALER
+   Copyright (C) 2022 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 exchangedb/pg_update_wire.c
+ * @brief Implementation of the update_wire function for Postgres
+ * @author Christian Grothoff
+ */
+#include "platform.h"
+#include "taler_error_codes.h"
+#include "taler_dbevents.h"
+#include "taler_pq_lib.h"
+#include "pg_update_wire.h"
+#include "pg_helper.h"
+
+
+enum GNUNET_DB_QueryStatus
+TEH_PG_update_wire (void *cls,
+                      const char *payto_uri,
+                      struct GNUNET_TIME_Timestamp change_date,
+                      bool enabled)
+{
+  struct PostgresClosure *pg = cls;
+  struct GNUNET_PQ_QueryParam params[] = {
+    GNUNET_PQ_query_param_string (payto_uri),
+    GNUNET_PQ_query_param_bool (enabled),
+    GNUNET_PQ_query_param_timestamp (&change_date),
+    GNUNET_PQ_query_param_end
+  };
+
+      /* used in #postgres_update_wire() */
+  PREPARE (pg,
+           "update_wire",
+           "UPDATE wire_accounts"
+           " SET"
+           "  is_active=$2"
+           " ,last_change=$3"
+           " WHERE payto_uri=$1");
+  return GNUNET_PQ_eval_prepared_non_select (pg->conn,
+                                             "update_wire",
+                                             params);
+}
diff --git a/src/exchangedb/pg_update_wire.h b/src/exchangedb/pg_update_wire.h
new file mode 100644
index 00000000..c01d68a4
--- /dev/null
+++ b/src/exchangedb/pg_update_wire.h
@@ -0,0 +1,43 @@
+/*
+   This file is part of TALER
+   Copyright (C) 2022 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 exchangedb/pg_update_wire.h
+ * @brief implementation of the update_wire function for Postgres
+ * @author Christian Grothoff
+ */
+#ifndef PG_UPDATE_WIRE_H
+#define PG_UPDATE_WIRE_H
+
+#include "taler_util.h"
+#include "taler_json_lib.h"
+#include "taler_exchangedb_plugin.h"
+/**
+ * Update information about a wire account of the exchange.
+ *
+ * @param cls closure
+ * @param payto_uri account the update is about
+ * @param change_date date when the account status was last changed
+ *                      (only to be used for replay detection)
+ * @param enabled true to enable, false to disable (the actual change)
+ * @return transaction status code
+ */
+enum GNUNET_DB_QueryStatus
+TEH_PG_update_wire (void *cls,
+                      const char *payto_uri,
+                      struct GNUNET_TIME_Timestamp change_date,
+                    bool enabled);
+
+#endif
diff --git a/src/exchangedb/pg_wire_prepare_data_get.c 
b/src/exchangedb/pg_wire_prepare_data_get.c
new file mode 100644
index 00000000..d4541301
--- /dev/null
+++ b/src/exchangedb/pg_wire_prepare_data_get.c
@@ -0,0 +1,142 @@
+/*
+   This file is part of TALER
+   Copyright (C) 2022 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 exchangedb/pg_wire_prepare_data_get.c
+ * @brief Implementation of the wire_prepare_data_get function for Postgres
+ * @author Christian Grothoff
+ */
+#include "platform.h"
+#include "taler_error_codes.h"
+#include "taler_dbevents.h"
+#include "taler_pq_lib.h"
+#include "pg_wire_prepare_data_get.h"
+#include "pg_helper.h"
+
+/**
+ * Closure for #prewire_cb().
+ */
+struct PrewireContext
+{
+  /**
+   * Function to call on each result.
+   */
+  TALER_EXCHANGEDB_WirePreparationIterator cb;
+
+  /**
+   * Closure for @a cb.
+   */
+  void *cb_cls;
+
+  /**
+   * #GNUNET_OK if everything went fine.
+   */
+  enum GNUNET_GenericReturnValue status;
+};
+
+
+/**
+ * Invoke the callback for each result.
+ *
+ * @param cls a `struct MissingWireContext *`
+ * @param result SQL result
+ * @param num_results number of rows in @a result
+ */
+static void
+prewire_cb (void *cls,
+            PGresult *result,
+            unsigned int num_results)
+{
+  struct PrewireContext *pc = cls;
+
+  for (unsigned int i = 0; i < num_results; i++)
+  {
+    uint64_t prewire_uuid;
+    char *wire_method;
+    void *buf = NULL;
+    size_t buf_size;
+    struct GNUNET_PQ_ResultSpec rs[] = {
+      GNUNET_PQ_result_spec_uint64 ("prewire_uuid",
+                                    &prewire_uuid),
+      GNUNET_PQ_result_spec_string ("wire_method",
+                                    &wire_method),
+      GNUNET_PQ_result_spec_variable_size ("buf",
+                                           &buf,
+                                           &buf_size),
+      GNUNET_PQ_result_spec_end
+    };
+
+    if (GNUNET_OK !=
+        GNUNET_PQ_extract_result (result,
+                                  rs,
+                                  i))
+    {
+      GNUNET_break (0);
+      pc->status = GNUNET_SYSERR;
+      return;
+    }
+    pc->cb (pc->cb_cls,
+            prewire_uuid,
+            wire_method,
+            buf,
+            buf_size);
+    GNUNET_PQ_cleanup_result (rs);
+  }
+}
+
+
+enum GNUNET_DB_QueryStatus
+TEH_PG_wire_prepare_data_get (void *cls,
+                                uint64_t start_row,
+                                uint64_t limit,
+                                TALER_EXCHANGEDB_WirePreparationIterator cb,
+                                void *cb_cls)
+{
+  struct PostgresClosure *pg = cls;
+  struct GNUNET_PQ_QueryParam params[] = {
+    GNUNET_PQ_query_param_uint64 (&start_row),
+    GNUNET_PQ_query_param_uint64 (&limit),
+    GNUNET_PQ_query_param_end
+  };
+  struct PrewireContext pc = {
+    .cb = cb,
+    .cb_cls = cb_cls,
+    .status = GNUNET_OK
+  };
+  enum GNUNET_DB_QueryStatus qs;
+
+
+      /* Used in #postgres_wire_prepare_data_get() */
+  PREPARE (pg,
+           "wire_prepare_data_get",
+           "SELECT"
+           " prewire_uuid"
+           ",wire_method"
+           ",buf"
+           " FROM prewire"
+           " WHERE prewire_uuid >= $1"
+           "   AND finished=FALSE"
+           "   AND failed=FALSE"
+           " ORDER BY prewire_uuid ASC"
+           " LIMIT $2;");
+  qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn,
+                                             "wire_prepare_data_get",
+                                             params,
+                                             &prewire_cb,
+                                             &pc);
+  if (GNUNET_OK != pc.status)
+    return GNUNET_DB_STATUS_HARD_ERROR;
+  return qs;
+}
diff --git a/src/exchangedb/pg_wire_prepare_data_get.h 
b/src/exchangedb/pg_wire_prepare_data_get.h
new file mode 100644
index 00000000..91e21d27
--- /dev/null
+++ b/src/exchangedb/pg_wire_prepare_data_get.h
@@ -0,0 +1,45 @@
+/*
+   This file is part of TALER
+   Copyright (C) 2022 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 exchangedb/pg_wire_prepare_data_get.h
+ * @brief implementation of the wire_prepare_data_get function for Postgres
+ * @author Christian Grothoff
+ */
+#ifndef PG_WIRE_PREPARE_DATA_GET_H
+#define PG_WIRE_PREPARE_DATA_GET_H
+
+#include "taler_util.h"
+#include "taler_json_lib.h"
+#include "taler_exchangedb_plugin.h"
+
+/**
+ * Function called to get an unfinished wire transfer
+ * preparation data. Fetches at most one item.
+ *
+ * @param cls closure
+ * @param start_row offset to query table at
+ * @param limit maximum number of results to return
+ * @param cb function to call for ONE unfinished item
+ * @param cb_cls closure for @a cb
+ * @return transaction status code
+ */
+enum GNUNET_DB_QueryStatus
+TEH_PG_wire_prepare_data_get (void *cls,
+                                uint64_t start_row,
+                                uint64_t limit,
+                                TALER_EXCHANGEDB_WirePreparationIterator cb,
+                              void *cb_cls);
+#endif
diff --git a/src/exchangedb/pg_wire_prepare_data_insert.c 
b/src/exchangedb/pg_wire_prepare_data_insert.c
new file mode 100644
index 00000000..903f22a5
--- /dev/null
+++ b/src/exchangedb/pg_wire_prepare_data_insert.c
@@ -0,0 +1,54 @@
+/*
+   This file is part of TALER
+   Copyright (C) 2022 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 exchangedb/pg_wire_prepare_data_insert.c
+ * @brief Implementation of the wire_prepare_data_insert function for Postgres
+ * @author Christian Grothoff
+ */
+#include "platform.h"
+#include "taler_error_codes.h"
+#include "taler_dbevents.h"
+#include "taler_pq_lib.h"
+#include "pg_wire_prepare_data_insert.h"
+#include "pg_helper.h"
+
+enum GNUNET_DB_QueryStatus
+TEH_PG_wire_prepare_data_insert (void *cls,
+                                   const char *type,
+                                   const char *buf,
+                                   size_t buf_size)
+{
+  struct PostgresClosure *pg = cls;
+  struct GNUNET_PQ_QueryParam params[] = {
+    GNUNET_PQ_query_param_string (type),
+    GNUNET_PQ_query_param_fixed_size (buf, buf_size),
+    GNUNET_PQ_query_param_end
+  };
+
+
+      /* Used in #postgres_wire_prepare_data_insert() to store
+       wire transfer information before actually committing it with the bank */
+  PREPARE (pg,
+      "wire_prepare_data_insert",
+      "INSERT INTO prewire "
+      "(wire_method"
+      ",buf"
+      ") VALUES "
+      "($1, $2);");
+  return GNUNET_PQ_eval_prepared_non_select (pg->conn,
+                                             "wire_prepare_data_insert",
+                                             params);
+}
diff --git a/src/exchangedb/pg_wire_prepare_data_insert.h 
b/src/exchangedb/pg_wire_prepare_data_insert.h
new file mode 100644
index 00000000..2b6050d0
--- /dev/null
+++ b/src/exchangedb/pg_wire_prepare_data_insert.h
@@ -0,0 +1,42 @@
+/*
+   This file is part of TALER
+   Copyright (C) 2022 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 exchangedb/pg_wire_prepare_data_insert.h
+ * @brief implementation of the wire_prepare_data_insert function for Postgres
+ * @author Christian Grothoff
+ */
+#ifndef PG_WIRE_PREPARE_DATA_INSERT_H
+#define PG_WIRE_PREPARE_DATA_INSERT_H
+
+#include "taler_util.h"
+#include "taler_json_lib.h"
+#include "taler_exchangedb_plugin.h"
+
+/**
+ * Function called to insert wire transfer commit data into the DB.
+ *
+ * @param cls closure
+ * @param type type of the wire transfer (i.e. "iban")
+ * @param buf buffer with wire transfer preparation data
+ * @param buf_size number of bytes in @a buf
+ * @return query status code
+ */
+enum GNUNET_DB_QueryStatus
+TEH_PG_wire_prepare_data_insert (void *cls,
+                                   const char *type,
+                                   const char *buf,
+                                 size_t buf_size);
+#endif
diff --git a/src/exchangedb/pg_wire_prepare_data_mark_failed.c 
b/src/exchangedb/pg_wire_prepare_data_mark_failed.c
new file mode 100644
index 00000000..fe2236b8
--- /dev/null
+++ b/src/exchangedb/pg_wire_prepare_data_mark_failed.c
@@ -0,0 +1,50 @@
+/*
+   This file is part of TALER
+   Copyright (C) 2022 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 exchangedb/pg_wire_prepare_data_mark_failed.c
+ * @brief Implementation of the wire_prepare_data_mark_failed function for 
Postgres
+ * @author Christian Grothoff
+ */
+#include "platform.h"
+#include "taler_error_codes.h"
+#include "taler_dbevents.h"
+#include "taler_pq_lib.h"
+#include "pg_wire_prepare_data_mark_failed.h"
+#include "pg_helper.h"
+
+
+enum GNUNET_DB_QueryStatus
+TEH_PG_wire_prepare_data_mark_failed (
+  void *cls,
+  uint64_t rowid)
+{
+  struct PostgresClosure *pg = cls;
+  struct GNUNET_PQ_QueryParam params[] = {
+    GNUNET_PQ_query_param_uint64 (&rowid),
+    GNUNET_PQ_query_param_end
+  };
+
+      /* Used in #postgres_wire_prepare_data_mark_failed() */
+
+  PREPARE (pg,
+           "wire_prepare_data_mark_failed",
+           "UPDATE prewire"
+           " SET failed=TRUE"
+           " WHERE prewire_uuid=$1;");
+  return GNUNET_PQ_eval_prepared_non_select (pg->conn,
+                                             "wire_prepare_data_mark_failed",
+                                             params);
+}
diff --git a/src/exchangedb/pg_wire_prepare_data_mark_failed.h 
b/src/exchangedb/pg_wire_prepare_data_mark_failed.h
new file mode 100644
index 00000000..cae1523d
--- /dev/null
+++ b/src/exchangedb/pg_wire_prepare_data_mark_failed.h
@@ -0,0 +1,39 @@
+/*
+   This file is part of TALER
+   Copyright (C) 2022 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 exchangedb/pg_wire_prepare_data_mark_failed.h
+ * @brief implementation of the wire_prepare_data_mark_failed function for 
Postgres
+ * @author Christian Grothoff
+ */
+#ifndef PG_WIRE_PREPARE_DATA_MARK_FAILED_H
+#define PG_WIRE_PREPARE_DATA_MARK_FAILED_H
+
+#include "taler_util.h"
+#include "taler_json_lib.h"
+#include "taler_exchangedb_plugin.h"
+
+/**
+ * Function called to mark wire transfer commit data as failed.
+ *
+ * @param cls closure
+ * @param rowid which entry to mark as failed
+ * @return transaction status code
+ */
+enum GNUNET_DB_QueryStatus
+TEH_PG_wire_prepare_data_mark_failed (
+  void *cls,
+  uint64_t rowid);
+#endif
diff --git a/src/exchangedb/pg_wire_prepare_data_mark_finished.c 
b/src/exchangedb/pg_wire_prepare_data_mark_finished.c
new file mode 100644
index 00000000..de8738e4
--- /dev/null
+++ b/src/exchangedb/pg_wire_prepare_data_mark_finished.c
@@ -0,0 +1,49 @@
+/*
+   This file is part of TALER
+   Copyright (C) 2022 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 exchangedb/pg_wire_prepare_data_mark_finished.c
+ * @brief Implementation of the wire_prepare_data_mark_finished function for 
Postgres
+ * @author Christian Grothoff
+ */
+#include "platform.h"
+#include "taler_error_codes.h"
+#include "taler_dbevents.h"
+#include "taler_pq_lib.h"
+#include "pg_wire_prepare_data_mark_finished.h"
+#include "pg_helper.h"
+
+enum GNUNET_DB_QueryStatus
+TEH_PG_wire_prepare_data_mark_finished (
+  void *cls,
+  uint64_t rowid)
+{
+  struct PostgresClosure *pg = cls;
+  struct GNUNET_PQ_QueryParam params[] = {
+    GNUNET_PQ_query_param_uint64 (&rowid),
+    GNUNET_PQ_query_param_end
+  };
+
+      /* Used in #postgres_wire_prepare_data_mark_finished() */
+  PREPARE (pg,
+      "wire_prepare_data_mark_done",
+      "UPDATE prewire"
+      " SET finished=TRUE"
+      " WHERE prewire_uuid=$1;");
+
+  return GNUNET_PQ_eval_prepared_non_select (pg->conn,
+                                             "wire_prepare_data_mark_done",
+                                             params);
+}
diff --git a/src/exchangedb/pg_wire_prepare_data_mark_finished.h 
b/src/exchangedb/pg_wire_prepare_data_mark_finished.h
new file mode 100644
index 00000000..19db2ca9
--- /dev/null
+++ b/src/exchangedb/pg_wire_prepare_data_mark_finished.h
@@ -0,0 +1,39 @@
+/*
+   This file is part of TALER
+   Copyright (C) 2022 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 exchangedb/pg_wire_prepare_data_mark_finished.h
+ * @brief implementation of the wire_prepare_data_mark_finished function for 
Postgres
+ * @author Christian Grothoff
+ */
+#ifndef PG_WIRE_PREPARE_DATA_MARK_FINISHED_H
+#define PG_WIRE_PREPARE_DATA_MARK_FINISHED_H
+
+#include "taler_util.h"
+#include "taler_json_lib.h"
+#include "taler_exchangedb_plugin.h"
+
+/**
+ * Function called to mark wire transfer commit data as finished.
+ *
+ * @param cls closure
+ * @param rowid which entry to mark as finished
+ * @return transaction status code
+ */
+enum GNUNET_DB_QueryStatus
+TEH_PG_wire_prepare_data_mark_finished (
+  void *cls,
+  uint64_t rowid);
+#endif
diff --git a/src/exchangedb/plugin_exchangedb_postgres.c 
b/src/exchangedb/plugin_exchangedb_postgres.c
index aa16e7ff..6a2a473c 100644
--- a/src/exchangedb/plugin_exchangedb_postgres.c
+++ b/src/exchangedb/plugin_exchangedb_postgres.c
@@ -104,6 +104,110 @@
 #include "pg_lookup_wire_fee_by_time.h"
 #include "pg_start.h"
 #include "pg_rollback.h"
+#include "pg_create_tables.h"
+#include "pg_setup_foreign_servers.h"
+#include "pg_event_listen.h"
+#include "pg_event_listen_cancel.h"
+#include "pg_event_notify.h"
+#include "pg_get_denomination_info.h"
+#include "pg_iterate_denomination_info.h"
+#include "pg_iterate_denominations.h"
+#include "pg_iterate_active_auditors.h"
+#include "pg_iterate_auditor_denominations.h"
+#include "pg_reserves_get.h"
+#include "pg_reserves_get_origin.h"
+#include "pg_drain_kyc_alert.h"
+#include "pg_reserves_in_insert.h"
+#include "pg_get_withdraw_info.h"
+#include "pg_do_batch_withdraw.h"
+#include "pg_get_policy_details.h"
+#include "pg_persist_policy_details.h"
+#include "pg_do_deposit.h"
+#include "pg_add_policy_fulfillment_proof.h"
+#include "pg_do_melt.h"
+#include "pg_do_refund.h"
+#include "pg_do_recoup.h"
+#include "pg_do_recoup_refresh.h"
+#include "pg_get_reserve_balance.h"
+#include "pg_count_known_coins.h"
+#include "pg_ensure_coin_known.h"
+#include "pg_get_known_coin.h"
+#include "pg_get_coin_denomination.h"
+#include "pg_have_deposit2.h"
+#include "pg_aggregate.h"
+#include "pg_create_aggregation_transient.h"
+#include "pg_select_aggregation_transient.h"
+#include "pg_find_aggregation_transient.h"
+#include "pg_update_aggregation_transient.h"
+#include "pg_get_ready_deposit.h"
+#include "pg_insert_deposit.h"
+#include "pg_insert_refund.h"
+#include "pg_select_refunds_by_coin.h"
+#include "pg_get_melt.h"
+#include "pg_insert_refresh_reveal.h"
+#include "pg_get_refresh_reveal.h"
+#include "pg_lookup_wire_transfer.h"
+#include "pg_lookup_transfer_by_deposit.h"
+#include "pg_insert_wire_fee.h"
+#include "pg_insert_global_fee.h"
+#include "pg_get_wire_fee.h"
+#include "pg_get_global_fee.h"
+#include "pg_get_global_fees.h"
+#include "pg_insert_reserve_closed.h"
+#include "pg_wire_prepare_data_insert.h"
+#include "pg_wire_prepare_data_mark_finished.h"
+#include "pg_wire_prepare_data_mark_failed.h"
+#include "pg_wire_prepare_data_get.h"
+#include "pg_start_deferred_wire_out.h"
+#include "pg_store_wire_transfer_out.h"
+#include "pg_gc.h"
+#include "pg_select_deposits_above_serial_id.h"
+#include "pg_select_history_requests_above_serial_id.h"
+#include "pg_select_purse_decisions_above_serial_id.h"
+#include "pg_select_purse_deposits_by_purse.h"
+#include "pg_select_refreshes_above_serial_id.h"
+#include "pg_select_refunds_above_serial_id.h"
+#include "pg_select_reserves_in_above_serial_id.h"
+#include "pg_select_reserves_in_above_serial_id_by_account.h"
+#include "pg_select_withdrawals_above_serial_id.h"
+#include "pg_select_wire_out_above_serial_id.h"
+#include "pg_select_wire_out_above_serial_id_by_account.h"
+#include "pg_select_recoup_above_serial_id.h"
+#include "pg_select_recoup_refresh_above_serial_id.h"
+#include "pg_get_reserve_by_h_blind.h"
+#include "pg_get_old_coin_by_h_blind.h"
+#include "pg_insert_denomination_revocation.h"
+#include "pg_get_denomination_revocation.h"
+#include "pg_select_deposits_missing_wire.h"
+#include "pg_lookup_auditor_timestamp.h"
+#include "pg_lookup_auditor_status.h"
+#include "pg_insert_auditor.h"
+#include "pg_lookup_wire_timestamp.h"
+#include "pg_insert_wire.h"
+#include "pg_update_wire.h"
+#include "pg_get_wire_accounts.h"
+#include "pg_get_wire_fees.h"
+#include "pg_insert_signkey_revocation.h"
+#include "pg_lookup_signkey_revocation.h"
+#include "pg_lookup_denomination_key.h"
+#include "pg_insert_auditor_denom_sig.h"
+#include "pg_select_auditor_denom_sig.h"
+#include "pg_add_denomination_key.h"
+#include "pg_lookup_signing_key.h"
+#include "pg_begin_shard.h"
+#include "pg_abort_shard.h"
+#include "pg_complete_shard.h"
+#include "pg_release_revolving_shard.h"
+#include "pg_delete_shard_locks.h"
+#include "pg_set_extension_manifest.h"
+#include "pg_insert_partner.h"
+#include "pg_expire_purse.h"
+#include "pg_select_purse_by_merge_pub.h"
+#include "pg_set_purse_balance.h"
+#include "pg_reserves_update.h"
+#include "pg_setup_wire_target.h"
+#include "pg_compute_shard.h"
+
 /**
  * Set to 1 to enable Postgres auto_explain module. This will
  * slow down things a _lot_, but also provide extensive logging
@@ -130,130 +234,6 @@
 } while (0)
 
 
-/**
- * Create the necessary tables if they are not present
- *
- * @param cls the `struct PostgresClosure` with the plugin-specific state
- * @return #GNUNET_OK upon success; #GNUNET_SYSERR upon failure
- */
-static enum GNUNET_GenericReturnValue
-postgres_create_tables (void *cls)
-{
-  struct PostgresClosure *pg = cls;
-  struct GNUNET_PQ_Context *conn;
-  enum GNUNET_GenericReturnValue ret;
-
-  conn = GNUNET_PQ_connect_with_cfg (pg->cfg,
-                                     "exchangedb-postgres",
-                                     "exchange-",
-                                     NULL,
-                                     NULL);
-  if (NULL == conn)
-    return GNUNET_SYSERR;
-  ret = GNUNET_PQ_exec_sql (conn,
-                            "procedures");
-  GNUNET_PQ_disconnect (conn);
-  return ret;
-}
-
-
-/**
- * Setup foreign servers (shards) for already existing tables
- *
- * @param cls the `struct PostgresClosure` with the plugin-specific state
- * @param num the number of foreign servers (shards) to create for each 
partitioned table
- * @return #GNUNET_OK upon success; #GNUNET_SYSERR upon failure
- */
-static enum GNUNET_GenericReturnValue
-postgres_setup_foreign_servers (void *cls,
-                                uint32_t num)
-{
-  struct PostgresClosure *pg = cls;
-  struct GNUNET_PQ_Context *conn;
-  enum GNUNET_GenericReturnValue ret = GNUNET_OK;
-  char *shard_domain = NULL;
-  char *remote_user = NULL;
-  char *remote_user_pw = NULL;
-
-  if (GNUNET_OK !=
-      GNUNET_CONFIGURATION_get_value_string (pg->cfg,
-                                             "exchange",
-                                             "SHARD_DOMAIN",
-                                             &shard_domain))
-  {
-    GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
-                               "exchange",
-                               "SHARD_DOMAIN");
-    return GNUNET_SYSERR;
-  }
-  if (GNUNET_OK !=
-      GNUNET_CONFIGURATION_get_value_string (pg->cfg,
-                                             "exchangedb-postgres",
-                                             "SHARD_REMOTE_USER",
-                                             &remote_user))
-  {
-    GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
-                               "exchangedb-postgres",
-                               "SHARD_REMOTE_USER");
-    GNUNET_free (shard_domain);
-    return GNUNET_SYSERR;
-  }
-  if (GNUNET_OK !=
-      GNUNET_CONFIGURATION_get_value_string (pg->cfg,
-                                             "exchangedb-postgres",
-                                             "SHARD_REMOTE_USER_PW",
-                                             &remote_user_pw))
-  {
-    GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
-                               "exchangedb-postgres",
-                               "SHARD_REMOTE_USER_PW");
-    GNUNET_free (shard_domain);
-    GNUNET_free (remote_user);
-    return GNUNET_SYSERR;
-  }
-
-  struct GNUNET_PQ_QueryParam params[] = {
-    GNUNET_PQ_query_param_uint32 (&num),
-    GNUNET_PQ_query_param_string (shard_domain),
-    GNUNET_PQ_query_param_string (remote_user),
-    GNUNET_PQ_query_param_string (remote_user_pw),
-    GNUNET_PQ_query_param_end
-  };
-  struct GNUNET_PQ_ExecuteStatement es[] = {
-    GNUNET_PQ_make_try_execute ("SET search_path TO exchange;"),
-    GNUNET_PQ_EXECUTE_STATEMENT_END
-  };
-  struct GNUNET_PQ_PreparedStatement ps[] = {
-    GNUNET_PQ_make_prepare ("create_foreign_servers",
-                            "SELECT"
-                            " create_foreign_servers"
-                            " ($1, $2, $3, $4);"),
-    GNUNET_PQ_PREPARED_STATEMENT_END
-  };
-
-  conn = GNUNET_PQ_connect_with_cfg (pg->cfg,
-                                     "exchangedb-postgres",
-                                     NULL,
-                                     es,
-                                     ps);
-  if (NULL == conn)
-  {
-    ret = GNUNET_SYSERR;
-  }
-  else if (0 > GNUNET_PQ_eval_prepared_non_select (conn,
-                                                   "create_foreign_servers",
-                                                   params))
-  {
-    ret = GNUNET_SYSERR;
-  }
-  GNUNET_free (shard_domain);
-  GNUNET_free (remote_user);
-  GNUNET_free (remote_user_pw);
-  GNUNET_PQ_disconnect (conn);
-  return ret;
-}
-
-
 /**
  * Initialize prepared statements for @a pg.
  *
@@ -265,151 +245,6 @@ prepare_statements (struct PostgresClosure *pg)
 {
   enum GNUNET_GenericReturnValue ret;
   struct GNUNET_PQ_PreparedStatement ps[] = {
-    /* Used in #postgres_add_denomination_key() */
-    GNUNET_PQ_make_prepare (
-      "add_denomination_key",
-      "INSERT INTO denominations "
-      "(denom_pub_hash"
-      ",denom_pub"
-      ",master_sig"
-      ",valid_from"
-      ",expire_withdraw"
-      ",expire_deposit"
-      ",expire_legal"
-      ",coin_val"                                                /* value of 
this denom */
-      ",coin_frac"                                                /* 
fractional value of this denom */
-      ",fee_withdraw_val"
-      ",fee_withdraw_frac"
-      ",fee_deposit_val"
-      ",fee_deposit_frac"
-      ",fee_refresh_val"
-      ",fee_refresh_frac"
-      ",fee_refund_val"
-      ",fee_refund_frac"
-      ",age_mask"
-      ") VALUES "
-      "($1, $2, $3, $4, $5, $6, $7, $8, $9, $10,"
-      " $11, $12, $13, $14, $15, $16, $17, $18);"),
-    /* Used in #postgres_iterate_denomination_info() */
-    GNUNET_PQ_make_prepare (
-      "denomination_iterate",
-      "SELECT"
-      " master_sig"
-      ",denom_pub_hash"
-      ",valid_from"
-      ",expire_withdraw"
-      ",expire_deposit"
-      ",expire_legal"
-      ",coin_val"                                                /* value of 
this denom */
-      ",coin_frac"                                                /* 
fractional value of this denom */
-      ",fee_withdraw_val"
-      ",fee_withdraw_frac"
-      ",fee_deposit_val"
-      ",fee_deposit_frac"
-      ",fee_refresh_val"
-      ",fee_refresh_frac"
-      ",fee_refund_val"
-      ",fee_refund_frac"
-      ",denom_pub"
-      ",age_mask"
-      " FROM denominations;"),
-    /* Used in #postgres_iterate_denominations() */
-    GNUNET_PQ_make_prepare (
-      "select_denominations",
-      "SELECT"
-      " denominations.master_sig"
-      ",denom_revocations_serial_id IS NOT NULL AS revoked"
-      ",valid_from"
-      ",expire_withdraw"
-      ",expire_deposit"
-      ",expire_legal"
-      ",coin_val"                                                /* value of 
this denom */
-      ",coin_frac"                                                /* 
fractional value of this denom */
-      ",fee_withdraw_val"
-      ",fee_withdraw_frac"
-      ",fee_deposit_val"
-      ",fee_deposit_frac"
-      ",fee_refresh_val"
-      ",fee_refresh_frac"
-      ",fee_refund_val"
-      ",fee_refund_frac"
-      ",denom_type"
-      ",age_mask"
-      ",denom_pub"
-      " FROM denominations"
-      " LEFT JOIN "
-      "   denomination_revocations USING (denominations_serial);"),
-
-    /* Used in #postgres_iterate_auditor_denominations() */
-    GNUNET_PQ_make_prepare (
-      "select_auditor_denoms",
-      "SELECT"
-      " auditors.auditor_pub"
-      ",denominations.denom_pub_hash"
-      ",auditor_denom_sigs.auditor_sig"
-      " FROM auditor_denom_sigs"
-      " JOIN auditors USING (auditor_uuid)"
-      " JOIN denominations USING (denominations_serial)"
-      " WHERE auditors.is_active;"),
-    /* Used in #postgres_iterate_active_auditors() */
-    GNUNET_PQ_make_prepare (
-      "select_auditors",
-      "SELECT"
-      " auditor_pub"
-      ",auditor_url"
-      ",auditor_name"
-      " FROM auditors"
-      " WHERE"
-      "   is_active;"),
-    /* Used in #postgres_get_denomination_info() */
-    GNUNET_PQ_make_prepare (
-      "denomination_get",
-      "SELECT"
-      " master_sig"
-      ",valid_from"
-      ",expire_withdraw"
-      ",expire_deposit"
-      ",expire_legal"
-      ",coin_val"                                                /* value of 
this denom */
-      ",coin_frac"                                                /* 
fractional value of this denom */
-      ",fee_withdraw_val"
-      ",fee_withdraw_frac"
-      ",fee_deposit_val"
-      ",fee_deposit_frac"
-      ",fee_refresh_val"
-      ",fee_refresh_frac"
-      ",fee_refund_val"
-      ",fee_refund_frac"
-      ",age_mask"
-      " FROM denominations"
-      " WHERE denom_pub_hash=$1;"),
-    /* Used in #postgres_insert_denomination_revocation() */
-    GNUNET_PQ_make_prepare (
-      "denomination_revocation_insert",
-      "INSERT INTO denomination_revocations "
-      "(denominations_serial"
-      ",master_sig"
-      ") SELECT denominations_serial,$2"
-      "    FROM denominations"
-      "   WHERE denom_pub_hash=$1;"),
-    /* Used in #postgres_get_denomination_revocation() */
-    GNUNET_PQ_make_prepare (
-      "denomination_revocation_get",
-      "SELECT"
-      " master_sig"
-      ",denom_revocations_serial_id"
-      " FROM denomination_revocations"
-      " WHERE denominations_serial="
-      "  (SELECT denominations_serial"
-      "    FROM denominations"
-      "    WHERE denom_pub_hash=$1);"),
-    /* Used in #postgres_reserves_get_origin() */
-    GNUNET_PQ_make_prepare (
-      "get_h_wire_source_of_reserve",
-      "SELECT"
-      " wire_source_h_payto"
-      " FROM reserves_in"
-      " WHERE reserve_pub=$1"),
     GNUNET_PQ_make_prepare (
       "get_kyc_h_payto",
       "SELECT"
@@ -417,287 +252,8 @@ prepare_statements (struct PostgresClosure *pg)
       " FROM wire_targets"
       " WHERE wire_target_h_payto=$1"
       " LIMIT 1;"),
-    /* Used in #postgres_insert_partner() */
-    GNUNET_PQ_make_prepare (
-      "insert_partner",
-      "INSERT INTO partners"
-      "  (partner_master_pub"
-      "  ,start_date"
-      "  ,end_date"
-      "  ,wad_frequency"
-      "  ,wad_fee_val"
-      "  ,wad_fee_frac"
-      "  ,master_sig"
-      "  ,partner_base_url"
-      "  ) VALUES "
-      "  ($1, $2, $3, $4, $5, $6, $7, $8);"),
-    /* Used in #setup_wire_target() */
-    GNUNET_PQ_make_prepare (
-      "insert_kyc_status",
-      "INSERT INTO wire_targets"
-      "  (wire_target_h_payto"
-      "  ,payto_uri"
-      "  ) VALUES "
-      "  ($1, $2)"
-      " ON CONFLICT DO NOTHING"),
-    /* Used in #postgres_drain_kyc_alert() */
-    GNUNET_PQ_make_prepare (
-      "drain_kyc_alert",
-      "DELETE FROM kyc_alerts"
-      " WHERE trigger_type=$1"
-      "   AND h_payto = "
-      "   (SELECT h_payto "
-      "      FROM kyc_alerts"
-      "     WHERE trigger_type=$1"
-      "     LIMIT 1)"
-      " RETURNING h_payto;"),
-    /* Used in #postgres_reserves_get() */
-    GNUNET_PQ_make_prepare (
-      "reserves_get",
-      "SELECT"
-      " current_balance_val"
-      ",current_balance_frac"
-      ",expiration_date"
-      ",gc_date"
-      " FROM reserves"
-      " WHERE reserve_pub=$1"
-      " LIMIT 1;"),
-    GNUNET_PQ_make_prepare (
-      "reserve_create",
-      "INSERT INTO reserves "
-      "(reserve_pub"
-      ",current_balance_val"
-      ",current_balance_frac"
-      ",expiration_date"
-      ",gc_date"
-      ") VALUES "
-      "($1, $2, $3, $4, $5)"
-      " ON CONFLICT DO NOTHING"
-      " RETURNING reserve_uuid;"),
-    /* Used in #postgres_insert_reserve_closed() */
-    GNUNET_PQ_make_prepare (
-      "reserves_close_insert",
-      "INSERT INTO reserves_close "
-      "(reserve_pub"
-      ",execution_date"
-      ",wtid"
-      ",wire_target_h_payto"
-      ",amount_val"
-      ",amount_frac"
-      ",closing_fee_val"
-      ",closing_fee_frac"
-      ",close_request_row"
-      ") VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9);"),
-
-
-    /* Used in #postgres_reserves_update() when the reserve is updated */
-    GNUNET_PQ_make_prepare (
-      "reserve_update",
-      "UPDATE reserves"
-      " SET"
-      " expiration_date=$1"
-      ",gc_date=$2"
-      ",current_balance_val=$3"
-      ",current_balance_frac=$4"
-      " WHERE reserve_pub=$5;"),
-    /* Used in #postgres_reserves_in_insert() to store transaction details */
-    GNUNET_PQ_make_prepare (
-      "reserves_in_add_transaction",
-      "INSERT INTO reserves_in "
-      "(reserve_pub"
-      ",wire_reference"
-      ",credit_val"
-      ",credit_frac"
-      ",exchange_account_section"
-      ",wire_source_h_payto"
-      ",execution_date"
-      ") VALUES ($1, $2, $3, $4, $5, $6, $7)"
-      " ON CONFLICT DO NOTHING;"),
-    /* Used in postgres_select_reserves_in_above_serial_id() to obtain inbound
-       transactions for reserves with serial id '\geq' the given parameter */
-    GNUNET_PQ_make_prepare (
-      "audit_reserves_in_get_transactions_incr",
-      "SELECT"
-      " reserves.reserve_pub"
-      ",wire_reference"
-      ",credit_val"
-      ",credit_frac"
-      ",execution_date"
-      ",payto_uri AS sender_account_details"
-      ",reserve_in_serial_id"
-      " FROM reserves_in"
-      " JOIN reserves"
-      "   USING (reserve_pub)"
-      " JOIN wire_targets"
-      "   ON (wire_source_h_payto = wire_target_h_payto)"
-      " WHERE reserve_in_serial_id>=$1"
-      " ORDER BY reserve_in_serial_id;"),
-    /* Used in postgres_select_reserves_in_above_serial_id() to obtain inbound
-       transactions for reserves with serial id '\geq' the given parameter */
-    GNUNET_PQ_make_prepare (
-      "audit_reserves_in_get_transactions_incr_by_account",
-      "SELECT"
-      " reserves.reserve_pub"
-      ",wire_reference"
-      ",credit_val"
-      ",credit_frac"
-      ",execution_date"
-      ",payto_uri AS sender_account_details"
-      ",reserve_in_serial_id"
-      " FROM reserves_in"
-      " JOIN reserves "
-      "   USING (reserve_pub)"
-      " JOIN wire_targets"
-      "   ON (wire_source_h_payto = wire_target_h_payto)"
-      " WHERE reserve_in_serial_id>=$1 AND exchange_account_section=$2"
-      " ORDER BY reserve_in_serial_id;"),
-    /* Used in #postgres_do_batch_withdraw() to
-       update the reserve balance and check its status */
-    GNUNET_PQ_make_prepare (
-      "call_batch_withdraw",
-      "SELECT "
-      " reserve_found"
-      ",balance_ok"
-      ",ruuid"
-      " FROM exchange_do_batch_withdraw"
-      " ($1,$2,$3,$4,$5);"),
-
-    /* Used in #postgres_do_deposit() to execute a deposit,
-       checking the coin's balance in the process as needed. */
-    GNUNET_PQ_make_prepare (
-      "call_deposit",
-      "SELECT "
-      " out_exchange_timestamp AS exchange_timestamp"
-      ",out_balance_ok AS balance_ok"
-      ",out_conflict AS conflicted"
-      " FROM exchange_do_deposit"
-      " ($1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11,$12,$13,$14,$15,$16,$17);"),
-
-    /* Used in #postgres_update_aggregation_transient() */
-    GNUNET_PQ_make_prepare (
-      "set_purse_balance",
-      "UPDATE purse_requests"
-      " SET balance_val=$2"
-      "    ,balance_frac=$3"
-      " WHERE purse_pub=$1;"),
-    /* used in #postgres_expire_purse() */
-    GNUNET_PQ_make_prepare (
-      "call_expire_purse",
-      "SELECT "
-      " out_found AS found"
-      " FROM exchange_do_expire_purse"
-      " ($1,$2,$3);"),
-    /* Used in #postgres_do_melt() to melt a coin. */
-    GNUNET_PQ_make_prepare (
-      "call_melt",
-      "SELECT "
-      " out_balance_ok AS balance_ok"
-      ",out_zombie_bad AS zombie_required"
-      ",out_noreveal_index AS noreveal_index"
-      " FROM exchange_do_melt"
-      " ($1,$2,$3,$4,$5,$6,$7,$8,$9);"),
-    /* Used in #postgres_do_refund() to refund a deposit. */
-    GNUNET_PQ_make_prepare (
-      "call_refund",
-      "SELECT "
-      " out_not_found AS not_found"
-      ",out_refund_ok AS refund_ok"
-      ",out_gone AS gone"
-      ",out_conflict AS conflict"
-      " FROM exchange_do_refund"
-      " ($1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11,$12,$13);"),
-    /* Used in #postgres_do_recoup() to recoup a coin to a reserve. */
-    GNUNET_PQ_make_prepare (
-      "call_recoup",
-      "SELECT "
-      " out_recoup_timestamp AS recoup_timestamp"
-      ",out_recoup_ok AS recoup_ok"
-      ",out_internal_failure AS internal_failure"
-      " FROM exchange_do_recoup_to_reserve"
-      " ($1,$2,$3,$4,$5,$6,$7,$8,$9);"),
-    /* Used in #postgres_do_recoup_refresh() to recoup a coin to a zombie 
coin. */
-    GNUNET_PQ_make_prepare (
-      "call_recoup_refresh",
-      "SELECT "
-      " out_recoup_timestamp AS recoup_timestamp"
-      ",out_recoup_ok AS recoup_ok"
-      ",out_internal_failure AS internal_failure"
-      " FROM exchange_do_recoup_to_coin"
-      " ($1,$2,$3,$4,$5,$6,$7);"),
-    /* Used in #postgres_get_withdraw_info() to
-       locate the response for a /reserve/withdraw request
-       using the hash of the blinded message.  Used to
-       make sure /reserve/withdraw requests are idempotent. */
-    GNUNET_PQ_make_prepare (
-      "get_withdraw_info",
-      "SELECT"
-      " denom.denom_pub_hash"
-      ",denom_sig"
-      ",reserve_sig"
-      ",reserves.reserve_pub"
-      ",execution_date"
-      ",h_blind_ev"
-      ",amount_with_fee_val"
-      ",amount_with_fee_frac"
-      ",denom.fee_withdraw_val"
-      ",denom.fee_withdraw_frac"
-      " FROM reserves_out"
-      "    JOIN reserves"
-      "      USING (reserve_uuid)"
-      "    JOIN denominations denom"
-      "      USING (denominations_serial)"
-      " WHERE h_blind_ev=$1;"),
-    /* Used in #postgres_select_withdrawals_above_serial_id() */
-    GNUNET_PQ_make_prepare (
-      "get_reserve_balance",
-      "SELECT"
-      " current_balance_val"
-      ",current_balance_frac"
-      " FROM reserves"
-      " WHERE reserve_pub=$1;"),
-    /* Fetch deposits with rowid '\geq' the given parameter */
 
-    GNUNET_PQ_make_prepare (
-      "audit_get_reserves_out_incr",
-      "SELECT"
-      " h_blind_ev"
-      ",denom.denom_pub"
-      ",reserve_sig"
-      ",reserves.reserve_pub"
-      ",execution_date"
-      ",amount_with_fee_val"
-      ",amount_with_fee_frac"
-      ",reserve_out_serial_id"
-      " FROM reserves_out"
-      "    JOIN reserves"
-      "      USING (reserve_uuid)"
-      "    JOIN denominations denom"
-      "      USING (denominations_serial)"
-      " WHERE reserve_out_serial_id>=$1"
-      " ORDER BY reserve_out_serial_id ASC;"),
-
-    /* Used in #postgres_count_known_coins() */
-    GNUNET_PQ_make_prepare (
-      "count_known_coins",
-      "SELECT"
-      " COUNT(*) AS count"
-      " FROM known_coins"
-      " WHERE denominations_serial="
-      "  (SELECT denominations_serial"
-      "    FROM denominations"
-      "    WHERE denom_pub_hash=$1);"),
-    /* Used in #postgres_get_known_coin() to fetch
-       the denomination public key and signature for
-       a coin known to the exchange. */
-    GNUNET_PQ_make_prepare (
-      "get_known_coin",
-      "SELECT"
-      " denominations.denom_pub_hash"
-      ",age_commitment_hash"
-      ",denom_sig"
-      " FROM known_coins"
-      " JOIN denominations USING (denominations_serial)"
-      " WHERE coin_pub=$1;"),
+
     /* Used in #postgres_ensure_coin_known() */
     GNUNET_PQ_make_prepare (
       "get_known_coin_dh",
@@ -706,145 +262,6 @@ prepare_statements (struct PostgresClosure *pg)
       " FROM known_coins"
       " JOIN denominations USING (denominations_serial)"
       " WHERE coin_pub=$1;"),
-    /* Used in #postgres_get_coin_denomination() to fetch
-       the denomination public key hash for
-       a coin known to the exchange. */
-    GNUNET_PQ_make_prepare (
-      "get_coin_denomination",
-      "SELECT"
-      " denominations.denom_pub_hash"
-      ",known_coin_id"
-      " FROM known_coins"
-      " JOIN denominations USING (denominations_serial)"
-      " WHERE coin_pub=$1"
-      " FOR SHARE;"),
-    /* Used in #postgres_insert_known_coin() to store the denomination public
-       key and signature for a coin known to the exchange.
-
-       See also:
-       
https://stackoverflow.com/questions/34708509/how-to-use-returning-with-on-conflict-in-postgresql/37543015#37543015
-     */
-    GNUNET_PQ_make_prepare (
-      "insert_known_coin",
-      "WITH dd"
-      "  (denominations_serial"
-      "  ,coin_val"
-      "  ,coin_frac"
-      "  ) AS ("
-      "    SELECT "
-      "       denominations_serial"
-      "      ,coin_val"
-      "      ,coin_frac"
-      "        FROM denominations"
-      "        WHERE denom_pub_hash=$2"
-      "  ), input_rows"
-      "    (coin_pub) AS ("
-      "      VALUES ($1::BYTEA)"
-      "  ), ins AS ("
-      "  INSERT INTO known_coins "
-      "  (coin_pub"
-      "  ,denominations_serial"
-      "  ,age_commitment_hash"
-      "  ,denom_sig"
-      "  ,remaining_val"
-      "  ,remaining_frac"
-      "  ) SELECT "
-      "     $1"
-      "    ,denominations_serial"
-      "    ,$3"
-      "    ,$4"
-      "    ,coin_val"
-      "    ,coin_frac"
-      "  FROM dd"
-      "  ON CONFLICT DO NOTHING" /* CONFLICT on (coin_pub) */
-      "  RETURNING "
-      "     known_coin_id"
-      "  ) "
-      "SELECT "
-      "   FALSE AS existed"
-      "  ,known_coin_id"
-      "  ,NULL AS denom_pub_hash"
-      "  ,NULL AS age_commitment_hash"
-      "  FROM ins "
-      "UNION ALL "
-      "SELECT "
-      "   TRUE AS existed"
-      "  ,known_coin_id"
-      "  ,denom_pub_hash"
-      "  ,kc.age_commitment_hash"
-      "  FROM input_rows"
-      "  JOIN known_coins kc USING (coin_pub)"
-      "  JOIN denominations USING (denominations_serial)"
-      "  LIMIT 1"),
-
-    /* Used in #postgres_get_melt() to fetch
-       high-level information about a melt operation */
-    GNUNET_PQ_make_prepare (
-      "get_melt",
-      /* "SELECT"
-      " denoms.denom_pub_hash"
-      ",denoms.fee_refresh_val"
-      ",denoms.fee_refresh_frac"
-      ",old_coin_pub"
-      ",old_coin_sig"
-      ",kc.age_commitment_hash"
-      ",amount_with_fee_val"
-      ",amount_with_fee_frac"
-      ",noreveal_index"
-      ",melt_serial_id"
-      " FROM refresh_commitments"
-      "   JOIN known_coins kc"
-      "     ON (old_coin_pub = kc.coin_pub)"
-      "   JOIN denominations denoms"
-      "     ON (kc.denominations_serial = denoms.denominations_serial)"
-      " WHERE rc=$1;", */
-      "WITH rc AS MATERIALIZED ( "
-      " SELECT"
-      "  * FROM refresh_commitments"
-      " WHERE rc=$1"
-      ")"
-      "SELECT"
-      " denoms.denom_pub_hash"
-      ",denoms.fee_refresh_val"
-      ",denoms.fee_refresh_frac"
-      ",rc.old_coin_pub"
-      ",rc.old_coin_sig"
-      ",kc.age_commitment_hash"
-      ",amount_with_fee_val"
-      ",amount_with_fee_frac"
-      ",noreveal_index"
-      ",melt_serial_id "
-      "FROM ("
-      " SELECT"
-      "  * "
-      " FROM known_coins"
-      " WHERE coin_pub=(SELECT old_coin_pub from rc)"
-      ") kc "
-      "JOIN rc"
-      "  ON (kc.coin_pub=rc.old_coin_pub) "
-      "JOIN denominations denoms"
-      "  USING (denominations_serial);"),
-    /* Used in #postgres_select_refreshes_above_serial_id() to fetch
-       refresh session with id '\geq' the given parameter */
-    GNUNET_PQ_make_prepare (
-      "audit_get_refresh_commitments_incr",
-      "SELECT"
-      " denom.denom_pub"
-      ",kc.coin_pub AS old_coin_pub"
-      ",kc.age_commitment_hash"
-      ",old_coin_sig"
-      ",amount_with_fee_val"
-      ",amount_with_fee_frac"
-      ",noreveal_index"
-      ",melt_serial_id"
-      ",rc"
-      " FROM refresh_commitments"
-      "   JOIN known_coins kc"
-      "     ON (refresh_commitments.old_coin_pub = kc.coin_pub)"
-      "   JOIN denominations denom"
-      "     ON (kc.denominations_serial = denom.denominations_serial)"
-      " WHERE melt_serial_id>=$1"
-      " ORDER BY melt_serial_id ASC;"),
     /* Store information about the desired denominations for a
        refresh operation, used in #postgres_insert_refresh_reveal() */
     GNUNET_PQ_make_prepare (
@@ -863,85 +280,6 @@ prepare_statements (struct PostgresClosure *pg)
       "    FROM denominations"
       "   WHERE denom_pub_hash=$4"
       " ON CONFLICT DO NOTHING;"),
-    /* Obtain information about the coins created in a refresh
-       operation, used in #postgres_get_refresh_reveal() */
-    GNUNET_PQ_make_prepare (
-      "get_refresh_revealed_coins",
-      "SELECT "
-      " rrc.freshcoin_index"
-      ",denom.denom_pub_hash"
-      ",rrc.h_coin_ev"
-      ",rrc.link_sig"
-      ",rrc.coin_ev"
-      ",rrc.ewv"
-      ",rrc.ev_sig"
-      " FROM refresh_commitments"
-      "    JOIN refresh_revealed_coins rrc"
-      "      USING (melt_serial_id)"
-      "    JOIN denominations denom "
-      "      USING (denominations_serial)"
-      " WHERE rc=$1;"),
-
-    /* Used in #postgres_insert_refresh_reveal() to store the transfer
-       keys we learned */
-    GNUNET_PQ_make_prepare (
-      "insert_refresh_transfer_keys",
-      "INSERT INTO refresh_transfer_keys "
-      "(melt_serial_id"
-      ",transfer_pub"
-      ",transfer_privs"
-      ") VALUES ($1, $2, $3)"
-      " ON CONFLICT DO NOTHING;"),
-    /* Used in #postgres_insert_refund() to store refund information */
-    GNUNET_PQ_make_prepare (
-      "insert_refund",
-      "INSERT INTO refunds "
-      "(coin_pub "
-      ",deposit_serial_id"
-      ",merchant_sig "
-      ",rtransaction_id "
-      ",amount_with_fee_val "
-      ",amount_with_fee_frac "
-      ") SELECT $1, deposit_serial_id, $3, $5, $6, $7"
-      "    FROM deposits"
-      "   WHERE coin_pub=$1"
-      "     AND h_contract_terms=$4"
-      "     AND merchant_pub=$2"),
-    /* Query the 'refunds' by coin public key */
-    /* Query the 'refunds' by coin public key, merchant_pub and contract hash 
*/
-    GNUNET_PQ_make_prepare (
-      "get_refunds_by_coin_and_contract",
-      "SELECT"
-      " ref.amount_with_fee_val"
-      ",ref.amount_with_fee_frac"
-      " FROM refunds ref"
-      " JOIN deposits dep"
-      "   USING (coin_pub,deposit_serial_id)"
-      " WHERE ref.coin_pub=$1"
-      "   AND dep.merchant_pub=$2"
-      "   AND dep.h_contract_terms=$3;"),
-    /* Fetch refunds with rowid '\geq' the given parameter */
-    GNUNET_PQ_make_prepare (
-      "audit_get_refunds_incr",
-      "SELECT"
-      " dep.merchant_pub"
-      ",ref.merchant_sig"
-      ",dep.h_contract_terms"
-      ",ref.rtransaction_id"
-      ",denom.denom_pub"
-      ",kc.coin_pub"
-      ",ref.amount_with_fee_val"
-      ",ref.amount_with_fee_frac"
-      ",ref.refund_serial_id"
-      " FROM refunds ref"
-      "   JOIN deposits dep"
-      "     ON (ref.coin_pub=dep.coin_pub AND 
ref.deposit_serial_id=dep.deposit_serial_id)"
-      "   JOIN known_coins kc"
-      "     ON (dep.coin_pub=kc.coin_pub)"
-      "   JOIN denominations denom"
-      "     ON (kc.denominations_serial=denom.denominations_serial)"
-      " WHERE ref.refund_serial_id>=$1"
-      " ORDER BY ref.refund_serial_id ASC;"),
     GNUNET_PQ_make_prepare (
       "test_refund_full",
       "SELECT"
@@ -954,910 +292,33 @@ prepare_statements (struct PostgresClosure *pg)
       "     ON (ref.coin_pub=dep.coin_pub AND 
ref.deposit_serial_id=dep.deposit_serial_id)"
       " WHERE ref.refund_serial_id=$1"
       " GROUP BY (dep.amount_with_fee_val, dep.amount_with_fee_frac);"),
-
-    /* Store information about a /deposit the exchange is to execute.
-       Used in #postgres_insert_deposit().  Only used in test cases. */
-    GNUNET_PQ_make_prepare (
-      "insert_deposit",
-      "INSERT INTO deposits "
-      "(known_coin_id"
-      ",coin_pub"
-      ",amount_with_fee_val"
-      ",amount_with_fee_frac"
-      ",wallet_timestamp"
-      ",refund_deadline"
-      ",wire_deadline"
-      ",merchant_pub"
-      ",h_contract_terms"
-      ",wire_salt"
-      ",wire_target_h_payto"
-      ",coin_sig"
-      ",exchange_timestamp"
-      ",shard"
-      ") SELECT known_coin_id, $1, $2, $3, $4, $5, $6, "
-      " $7, $8, $9, $10, $11, $12, $13"
-      "    FROM known_coins"
-      "   WHERE coin_pub=$1"
-      " ON CONFLICT DO NOTHING;"),
-    /* Fetch an existing deposit request, used to ensure idempotency
-       during /deposit processing. Used in #postgres_have_deposit(). */
+    /* Used in #postgres_do_account_merge() */
     GNUNET_PQ_make_prepare (
-      "get_deposit",
-      "SELECT"
-      " dep.amount_with_fee_val"
-      ",dep.amount_with_fee_frac"
-      ",denominations.fee_deposit_val"
-      ",denominations.fee_deposit_frac"
-      ",dep.wallet_timestamp"
-      ",dep.exchange_timestamp"
-      ",dep.refund_deadline"
-      ",dep.wire_deadline"
-      ",dep.h_contract_terms"
-      ",dep.wire_salt"
-      ",wt.payto_uri AS receiver_wire_account"
-      " FROM deposits dep"
-      " JOIN known_coins kc ON (kc.coin_pub = dep.coin_pub)"
-      " JOIN denominations USING (denominations_serial)"
-      " JOIN wire_targets wt USING (wire_target_h_payto)"
-      " WHERE dep.coin_pub=$1"
-      "   AND dep.merchant_pub=$3"
-      "   AND dep.h_contract_terms=$2;"),
-    /* Fetch deposits with rowid '\geq' the given parameter */
+      "call_account_merge",
+      "SELECT 1"
+      " FROM exchange_do_account_merge"
+      "  ($1, $2, $3);"),
+    /* Used in #postgres_update_kyc_requirement_by_row() */
     GNUNET_PQ_make_prepare (
-      "audit_get_deposits_incr",
-      "SELECT"
-      " amount_with_fee_val"
-      ",amount_with_fee_frac"
-      ",wallet_timestamp"
-      ",exchange_timestamp"
-      ",merchant_pub"
-      ",denom.denom_pub"
-      ",kc.coin_pub"
-      ",kc.age_commitment_hash"
-      ",coin_sig"
-      ",refund_deadline"
-      ",wire_deadline"
-      ",h_contract_terms"
-      ",wire_salt"
-      ",payto_uri AS receiver_wire_account"
-      ",done"
-      ",deposit_serial_id"
-      " FROM deposits"
-      "    JOIN wire_targets USING (wire_target_h_payto)"
-      "    JOIN known_coins kc USING (coin_pub)"
-      "    JOIN denominations denom USING (denominations_serial)"
-      " WHERE ("
-      "  (deposit_serial_id>=$1)"
-      " )"
-      " ORDER BY deposit_serial_id ASC;"),
+      "update_legitimization_process",
+      "UPDATE legitimization_processes"
+      " SET provider_user_id=$4"
+      "    ,provider_legitimization_id=$5"
+      "    ,expiration_time=GREATEST(expiration_time,$6)"
+      " WHERE"
+      "      h_payto=$3"
+      "  AND legitimization_process_serial_id=$1"
+      "  AND provider_section=$2;"),
+    GNUNET_PQ_PREPARED_STATEMENT_END
+  };
 
-    GNUNET_PQ_make_prepare (
-      "audit_get_history_requests_incr",
-      "SELECT"
-      " history_request_serial_id"
-      ",history_fee_val"
-      ",history_fee_frac"
-      ",request_timestamp"
-      ",reserve_pub"
-      ",reserve_sig"
-      " FROM history_requests"
-      " WHERE ("
-      "  (history_request_serial_id>=$1)"
-      " )"
-      " ORDER BY history_request_serial_id ASC;"),
-
-    GNUNET_PQ_make_prepare (
-      "audit_get_purse_deposits_by_purse",
-      "SELECT"
-      " pd.purse_deposit_serial_id"
-      ",pd.amount_with_fee_val"
-      ",pd.amount_with_fee_frac"
-      ",pd.coin_pub"
-      ",denom.denom_pub"
-      " FROM purse_deposits pd"
-      " JOIN known_coins kc USING (coin_pub)"
-      " JOIN denominations denom USING (denominations_serial)"
-      " WHERE purse_pub=$1;"),
-    GNUNET_PQ_make_prepare (
-      "audit_get_purse_decisions_incr",
-      "SELECT"
-      " pd.purse_pub"
-      ",pm.reserve_pub"
-      ",pd.purse_decision_serial_id"
-      ",pr.amount_with_fee_val"
-      ",pr.amount_with_fee_frac"
-      " FROM purse_decision pd"
-      " JOIN purse_requests pr ON (pd.purse_pub = pr.purse_pub)"
-      " LEFT JOIN purse_merges pm ON (pm.purse_pub = pd.purse_pub)"
-      " WHERE ("
-      "  (purse_decision_serial_id>=$1) AND "
-      "  (refunded=$2)"
-      " )"
-      " ORDER BY purse_decision_serial_id ASC;"),
-    /* Fetch an existing deposit request.
-       Used in #postgres_lookup_transfer_by_deposit(). */
-    GNUNET_PQ_make_prepare (
-      "get_deposit_without_wtid",
-      "SELECT"
-      " agt.legitimization_requirement_serial_id"
-      ",dep.wire_salt"
-      ",wt.payto_uri"
-      ",dep.amount_with_fee_val"
-      ",dep.amount_with_fee_frac"
-      ",denom.fee_deposit_val"
-      ",denom.fee_deposit_frac"
-      ",dep.wire_deadline"
-      " FROM deposits dep"
-      " JOIN wire_targets wt"
-      "   USING (wire_target_h_payto)"
-      " JOIN known_coins kc"
-      "   ON (kc.coin_pub = dep.coin_pub)"
-      " JOIN denominations denom"
-      "   USING (denominations_serial)"
-      " LEFT JOIN aggregation_transient agt "
-      "   ON ( (dep.wire_target_h_payto = agt.wire_target_h_payto) AND"
-      "        (dep.merchant_pub = agt.merchant_pub) )"
-      " WHERE dep.coin_pub=$1"
-      "   AND dep.merchant_pub=$3"
-      "   AND dep.h_contract_terms=$2"
-      " LIMIT 1;"),
-    /* Used in #postgres_get_ready_deposit() */
-    GNUNET_PQ_make_prepare (
-      "deposits_get_ready",
-      "SELECT"
-      " payto_uri"
-      ",merchant_pub"
-      " FROM deposits_by_ready dbr"
-      "  JOIN deposits dep"
-      "    ON (dbr.coin_pub = dep.coin_pub AND"
-      "        dbr.deposit_serial_id = dep.deposit_serial_id)"
-      "  JOIN wire_targets wt"
-      "    USING (wire_target_h_payto)"
-      " WHERE dbr.wire_deadline<=$1"
-      "   AND dbr.shard >= $2"
-      "   AND dbr.shard <= $3"
-      " ORDER BY "
-      "   dbr.wire_deadline ASC"
-      "  ,dbr.shard ASC"
-      " LIMIT 1;"),
-    /* Used in #postgres_aggregate() */
-    GNUNET_PQ_make_prepare (
-      "aggregate",
-      "WITH rdy AS (" /* find deposits ready by merchant */
-      "  SELECT"
-      "    coin_pub"
-      "    FROM deposits_for_matching"
-      "    WHERE refund_deadline<$1" /* filter by shard, only actually 
executable deposits */
-      "      AND merchant_pub=$2" /* filter by target merchant */
-      "    ORDER BY refund_deadline ASC" /* ordering is not critical */
-      "    LIMIT "
-      TALER_QUOTE (TALER_EXCHANGEDB_MATCHING_DEPOSITS_LIMIT) /* limits 
transaction size */
-      " )"
-      " ,dep AS (" /* restrict to our merchant and account and mark as done */
-      "  UPDATE deposits"
-      "     SET done=TRUE"
-      "   WHERE coin_pub IN (SELECT coin_pub FROM rdy)"
-      "     AND merchant_pub=$2" /* theoretically, same coin could be spent at 
another merchant */
-      "     AND wire_target_h_payto=$3" /* merchant could have a 2nd bank 
account */
-      "     AND done=FALSE" /* theoretically, same coin could be spend at the 
same merchant a 2nd time */
-      "   RETURNING"
-      "     deposit_serial_id"
-      "    ,coin_pub"
-      "    ,amount_with_fee_val AS amount_val"
-      "    ,amount_with_fee_frac AS amount_frac)"
-      " ,ref AS (" /* find applicable refunds -- NOTE: may do a full join on 
the master, maybe find a left-join way to integrate with query above to push it 
to the shards? */
-      "  SELECT"
-      "    amount_with_fee_val AS refund_val"
-      "   ,amount_with_fee_frac AS refund_frac"
-      "   ,coin_pub"
-      "   ,deposit_serial_id" /* theoretically, coin could be in multiple 
refunded transactions */
-      "    FROM refunds"
-      "   WHERE coin_pub IN (SELECT coin_pub FROM dep)"
-      "     AND deposit_serial_id IN (SELECT deposit_serial_id FROM dep))"
-      " ,ref_by_coin AS (" /* total up refunds by coin */
-      "  SELECT"
-      "    SUM(refund_val) AS sum_refund_val"
-      "   ,SUM(refund_frac) AS sum_refund_frac"
-      "   ,coin_pub"
-      "   ,deposit_serial_id" /* theoretically, coin could be in multiple 
refunded transactions */
-      "    FROM ref"
-      "   GROUP BY coin_pub, deposit_serial_id)"
-      " ,norm_ref_by_coin AS (" /* normalize */
-      "  SELECT"
-      "    sum_refund_val + sum_refund_frac / 100000000 AS norm_refund_val"
-      "   ,sum_refund_frac % 100000000 AS norm_refund_frac"
-      "   ,coin_pub"
-      "   ,deposit_serial_id" /* theoretically, coin could be in multiple 
refunded transactions */
-      "    FROM ref_by_coin)"
-      " ,fully_refunded_coins AS (" /* find applicable refunds -- NOTE: may do 
a full join on the master, maybe find a left-join way to integrate with query 
above to push it to the shards? */
-      "  SELECT"
-      "    dep.coin_pub"
-      "    FROM norm_ref_by_coin norm"
-      "    JOIN dep"
-      "      ON (norm.coin_pub = dep.coin_pub"
-      "      AND norm.deposit_serial_id = dep.deposit_Serial_id"
-      "      AND norm.norm_refund_val = dep.amount_val"
-      "      AND norm.norm_refund_frac = dep.amount_frac))"
-      " ,fees AS (" /* find deposit fees for not fully refunded deposits */
-      "  SELECT"
-      "    denom.fee_deposit_val AS fee_val"
-      "   ,denom.fee_deposit_frac AS fee_frac"
-      "   ,cs.deposit_serial_id" /* ensures we get the fee for each coin, not 
once per denomination */
-      "    FROM dep cs"
-      "    JOIN known_coins kc" /* NOTE: may do a full join on the master, 
maybe find a left-join way to integrate with query above to push it to the 
shards? */
-      "      USING (coin_pub)"
-      "    JOIN denominations denom"
-      "      USING (denominations_serial)"
-      "    WHERE coin_pub NOT IN (SELECT coin_pub FROM fully_refunded_coins))"
-      " ,dummy AS (" /* add deposits to aggregation_tracking */
-      "    INSERT INTO aggregation_tracking"
-      "    (deposit_serial_id"
-      "    ,wtid_raw)"
-      "    SELECT deposit_serial_id,$4"
-      "      FROM dep)"
-      "SELECT" /* calculate totals (deposits, refunds and fees) */
-      "  CAST(COALESCE(SUM(dep.amount_val),0) AS INT8) AS sum_deposit_value" 
/* cast needed, otherwise we get NUMBER */
-      " ,COALESCE(SUM(dep.amount_frac),0) AS sum_deposit_fraction" /* SUM over 
INT returns INT8 */
-      " ,CAST(COALESCE(SUM(ref.refund_val),0) AS INT8) AS sum_refund_value"
-      " ,COALESCE(SUM(ref.refund_frac),0) AS sum_refund_fraction"
-      " ,CAST(COALESCE(SUM(fees.fee_val),0) AS INT8) AS sum_fee_value"
-      " ,COALESCE(SUM(fees.fee_frac),0) AS sum_fee_fraction"
-      " FROM dep "
-      "   FULL OUTER JOIN ref ON (FALSE)"    /* We just want all sums */
-      "   FULL OUTER JOIN fees ON (FALSE);"),
-
-
-    /* Used in #postgres_create_aggregation_transient() */
-    GNUNET_PQ_make_prepare (
-      "create_aggregation_transient",
-      "INSERT INTO aggregation_transient"
-      " (amount_val"
-      " ,amount_frac"
-      " ,merchant_pub"
-      " ,wire_target_h_payto"
-      " ,legitimization_requirement_serial_id"
-      " ,exchange_account_section"
-      " ,wtid_raw)"
-      " VALUES ($1, $2, $3, $4, $5, $6, $7);"),
-    /* Used in #postgres_select_aggregation_transient() */
-    GNUNET_PQ_make_prepare (
-      "select_aggregation_transient",
-      "SELECT"
-      "  amount_val"
-      " ,amount_frac"
-      " ,wtid_raw"
-      " FROM aggregation_transient"
-      " WHERE wire_target_h_payto=$1"
-      "   AND merchant_pub=$2"
-      "   AND exchange_account_section=$3;"),
-    /* Used in #postgres_find_aggregation_transient() */
-    GNUNET_PQ_make_prepare (
-      "find_transient_aggregations",
-      "SELECT"
-      "  amount_val"
-      " ,amount_frac"
-      " ,wtid_raw"
-      " ,merchant_pub"
-      " ,payto_uri"
-      " FROM aggregation_transient atr"
-      " JOIN wire_targets wt USING (wire_target_h_payto)"
-      " WHERE atr.wire_target_h_payto=$1;"),
-    /* Used in #postgres_update_aggregation_transient() */
-    GNUNET_PQ_make_prepare (
-      "update_aggregation_transient",
-      "UPDATE aggregation_transient"
-      " SET amount_val=$1"
-      "    ,amount_frac=$2"
-      "    ,legitimization_requirement_serial_id=$5"
-      " WHERE wire_target_h_payto=$3"
-      "   AND wtid_raw=$4"),
-    /* Used in #postgres_lookup_wire_transfer */
-    GNUNET_PQ_make_prepare (
-      "lookup_transactions",
-      "SELECT"
-      " aggregation_serial_id"
-      ",deposits.h_contract_terms"
-      ",payto_uri"
-      ",wire_targets.wire_target_h_payto"
-      ",kc.coin_pub"
-      ",deposits.merchant_pub"
-      ",wire_out.execution_date"
-      ",deposits.amount_with_fee_val"
-      ",deposits.amount_with_fee_frac"
-      ",denom.fee_deposit_val"
-      ",denom.fee_deposit_frac"
-      ",denom.denom_pub"
-      " FROM aggregation_tracking"
-      "    JOIN deposits"
-      "      USING (deposit_serial_id)"
-      "    JOIN wire_targets"
-      "      USING (wire_target_h_payto)"
-      "    JOIN known_coins kc"
-      "      USING (coin_pub)"
-      "    JOIN denominations denom"
-      "      USING (denominations_serial)"
-      "    JOIN wire_out"
-      "      USING (wtid_raw)"
-      " WHERE wtid_raw=$1;"),
-    /* Used in #postgres_lookup_transfer_by_deposit */
-    GNUNET_PQ_make_prepare (
-      "lookup_deposit_wtid",
-      "SELECT"
-      " aggregation_tracking.wtid_raw"
-      ",wire_out.execution_date"
-      ",dep.amount_with_fee_val"
-      ",dep.amount_with_fee_frac"
-      ",dep.wire_salt"
-      ",wt.payto_uri"
-      ",denom.fee_deposit_val"
-      ",denom.fee_deposit_frac"
-      " FROM deposits dep"
-      "    JOIN wire_targets wt"
-      "      USING (wire_target_h_payto)"
-      "    JOIN aggregation_tracking"
-      "      USING (deposit_serial_id)"
-      "    JOIN known_coins kc"
-      "      ON (kc.coin_pub = dep.coin_pub)"
-      "    JOIN denominations denom"
-      "      USING (denominations_serial)"
-      "    JOIN wire_out"
-      "      USING (wtid_raw)"
-      " WHERE dep.coin_pub=$1"
-      "   AND dep.merchant_pub=$3"
-      "   AND dep.h_contract_terms=$2"),
-
-    /* Used in #postgres_get_wire_fee() */
-    GNUNET_PQ_make_prepare (
-      "get_wire_fee",
-      "SELECT "
-      " start_date"
-      ",end_date"
-      ",wire_fee_val"
-      ",wire_fee_frac"
-      ",closing_fee_val"
-      ",closing_fee_frac"
-      ",master_sig"
-      " FROM wire_fee"
-      " WHERE wire_method=$1"
-      "   AND start_date <= $2"
-      "   AND end_date > $2;"),
-    /* Used in #postgres_get_global_fee() */
-    GNUNET_PQ_make_prepare (
-      "get_global_fee",
-      "SELECT "
-      " start_date"
-      ",end_date"
-      ",history_fee_val"
-      ",history_fee_frac"
-      ",account_fee_val"
-      ",account_fee_frac"
-      ",purse_fee_val"
-      ",purse_fee_frac"
-      ",purse_timeout"
-      ",history_expiration"
-      ",purse_account_limit"
-      ",master_sig"
-      " FROM global_fee"
-      " WHERE start_date <= $1"
-      "   AND end_date > $1;"),
-    /* Used in #postgres_get_global_fees() */
-    GNUNET_PQ_make_prepare (
-      "get_global_fees",
-      "SELECT "
-      " start_date"
-      ",end_date"
-      ",history_fee_val"
-      ",history_fee_frac"
-      ",account_fee_val"
-      ",account_fee_frac"
-      ",purse_fee_val"
-      ",purse_fee_frac"
-      ",purse_timeout"
-      ",history_expiration"
-      ",purse_account_limit"
-      ",master_sig"
-      " FROM global_fee"
-      " WHERE start_date >= $1"),
-    /* Used in #postgres_insert_wire_fee */
-    GNUNET_PQ_make_prepare (
-      "insert_wire_fee",
-      "INSERT INTO wire_fee "
-      "(wire_method"
-      ",start_date"
-      ",end_date"
-      ",wire_fee_val"
-      ",wire_fee_frac"
-      ",closing_fee_val"
-      ",closing_fee_frac"
-      ",master_sig"
-      ") VALUES "
-      "($1, $2, $3, $4, $5, $6, $7, $8);"),
-    /* Used in #postgres_insert_global_fee */
-    GNUNET_PQ_make_prepare (
-      "insert_global_fee",
-      "INSERT INTO global_fee "
-      "(start_date"
-      ",end_date"
-      ",history_fee_val"
-      ",history_fee_frac"
-      ",account_fee_val"
-      ",account_fee_frac"
-      ",purse_fee_val"
-      ",purse_fee_frac"
-      ",purse_timeout"
-      ",history_expiration"
-      ",purse_account_limit"
-      ",master_sig"
-      ") VALUES "
-      "($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12);"),
-    /* Used in #postgres_store_wire_transfer_out */
-    GNUNET_PQ_make_prepare (
-      "insert_wire_out",
-      "INSERT INTO wire_out "
-      "(execution_date"
-      ",wtid_raw"
-      ",wire_target_h_payto"
-      ",exchange_account_section"
-      ",amount_val"
-      ",amount_frac"
-      ") VALUES "
-      "($1, $2, $3, $4, $5, $6);"),
-    /* Used in #postgres_wire_prepare_data_insert() to store
-       wire transfer information before actually committing it with the bank */
-    GNUNET_PQ_make_prepare (
-      "wire_prepare_data_insert",
-      "INSERT INTO prewire "
-      "(wire_method"
-      ",buf"
-      ") VALUES "
-      "($1, $2);"),
-    /* Used in #postgres_wire_prepare_data_mark_finished() */
-    GNUNET_PQ_make_prepare (
-      "wire_prepare_data_mark_done",
-      "UPDATE prewire"
-      " SET finished=TRUE"
-      " WHERE prewire_uuid=$1;"),
-    /* Used in #postgres_wire_prepare_data_mark_failed() */
-    GNUNET_PQ_make_prepare (
-      "wire_prepare_data_mark_failed",
-      "UPDATE prewire"
-      " SET failed=TRUE"
-      " WHERE prewire_uuid=$1;"),
-    /* Used in #postgres_wire_prepare_data_get() */
-    GNUNET_PQ_make_prepare (
-      "wire_prepare_data_get",
-      "SELECT"
-      " prewire_uuid"
-      ",wire_method"
-      ",buf"
-      " FROM prewire"
-      " WHERE prewire_uuid >= $1"
-      "   AND finished=FALSE"
-      "   AND failed=FALSE"
-      " ORDER BY prewire_uuid ASC"
-      " LIMIT $2;"),
-    /* Used in #postgres_select_deposits_missing_wire */
-    // FIXME: used by the auditor; can probably be done
-    // smarter by checking if 'done' or 'blocked'
-    // are set correctly when going over deposits, instead
-    // of JOINing with refunds.
-    GNUNET_PQ_make_prepare (
-      "deposits_get_overdue",
-      "SELECT"
-      " deposit_serial_id"
-      ",coin_pub"
-      ",amount_with_fee_val"
-      ",amount_with_fee_frac"
-      ",payto_uri"
-      ",wire_deadline"
-      ",done"
-      " FROM deposits d"
-      "   JOIN known_coins"
-      "     USING (coin_pub)"
-      "   JOIN wire_targets"
-      "     USING (wire_target_h_payto)"
-      " WHERE wire_deadline >= $1"
-      " AND wire_deadline < $2"
-      " AND NOT (EXISTS (SELECT 1"
-      "            FROM refunds r"
-      "            WHERE (r.coin_pub = d.coin_pub) AND (r.deposit_serial_id = 
d.deposit_serial_id))"
-      "       OR EXISTS (SELECT 1"
-      "            FROM aggregation_tracking"
-      "            WHERE (aggregation_tracking.deposit_serial_id = 
d.deposit_serial_id)))"
-      " ORDER BY wire_deadline ASC"),
-    /* Used in #postgres_select_wire_out_above_serial_id() */
-    GNUNET_PQ_make_prepare (
-      "audit_get_wire_incr",
-      "SELECT"
-      " wireout_uuid"
-      ",execution_date"
-      ",wtid_raw"
-      ",payto_uri"
-      ",amount_val"
-      ",amount_frac"
-      " FROM wire_out"
-      "   JOIN wire_targets"
-      "     USING (wire_target_h_payto)"
-      " WHERE wireout_uuid>=$1"
-      " ORDER BY wireout_uuid ASC;"),
-    /* Used in #postgres_select_wire_out_above_serial_id_by_account() */
-    GNUNET_PQ_make_prepare (
-      "audit_get_wire_incr_by_account",
-      "SELECT"
-      " wireout_uuid"
-      ",execution_date"
-      ",wtid_raw"
-      ",payto_uri"
-      ",amount_val"
-      ",amount_frac"
-      " FROM wire_out"
-      "   JOIN wire_targets"
-      "     USING (wire_target_h_payto)"
-      " WHERE "
-      "      wireout_uuid>=$1 "
-      "  AND exchange_account_section=$2"
-      " ORDER BY wireout_uuid ASC;"),
-    /* Used in #postgres_select_recoup_above_serial_id() to obtain recoup 
transactions */
-    GNUNET_PQ_make_prepare (
-      "recoup_get_incr",
-      "SELECT"
-      " recoup_uuid"
-      ",recoup_timestamp"
-      ",reserves.reserve_pub"
-      ",coins.coin_pub"
-      ",coin_sig"
-      ",coin_blind"
-      ",ro.h_blind_ev"
-      ",denoms.denom_pub_hash"
-      ",coins.denom_sig"
-      ",coins.age_commitment_hash"
-      ",denoms.denom_pub"
-      ",amount_val"
-      ",amount_frac"
-      " FROM recoup"
-      "    JOIN known_coins coins"
-      "      USING (coin_pub)"
-      "    JOIN reserves_out ro"
-      "      USING (reserve_out_serial_id)"
-      "    JOIN reserves"
-      "      USING (reserve_uuid)"
-      "    JOIN denominations denoms"
-      "      ON (coins.denominations_serial = denoms.denominations_serial)"
-      " WHERE recoup_uuid>=$1"
-      " ORDER BY recoup_uuid ASC;"),
-    /* Used in #postgres_select_recoup_refresh_above_serial_id() to obtain
-       recoup-refresh transactions */
-    GNUNET_PQ_make_prepare (
-      "recoup_refresh_get_incr",
-      "SELECT"
-      " recoup_refresh_uuid"
-      ",recoup_timestamp"
-      ",old_coins.coin_pub AS old_coin_pub"
-      ",new_coins.age_commitment_hash"
-      ",old_denoms.denom_pub_hash AS old_denom_pub_hash"
-      ",new_coins.coin_pub As coin_pub"
-      ",coin_sig"
-      ",coin_blind"
-      ",new_denoms.denom_pub AS denom_pub"
-      ",rrc.h_coin_ev AS h_blind_ev"
-      ",new_denoms.denom_pub_hash"
-      ",new_coins.denom_sig AS denom_sig"
-      ",amount_val"
-      ",amount_frac"
-      " FROM recoup_refresh"
-      "    INNER JOIN refresh_revealed_coins rrc"
-      "      USING (rrc_serial)"
-      "    INNER JOIN refresh_commitments rfc"
-      "      ON (rrc.melt_serial_id = rfc.melt_serial_id)"
-      "    INNER JOIN known_coins old_coins"
-      "      ON (rfc.old_coin_pub = old_coins.coin_pub)"
-      "    INNER JOIN known_coins new_coins"
-      "      ON (new_coins.coin_pub = recoup_refresh.coin_pub)"
-      "    INNER JOIN denominations new_denoms"
-      "      ON (new_coins.denominations_serial = 
new_denoms.denominations_serial)"
-      "    INNER JOIN denominations old_denoms"
-      "      ON (old_coins.denominations_serial = 
old_denoms.denominations_serial)"
-      " WHERE recoup_refresh_uuid>=$1"
-      " ORDER BY recoup_refresh_uuid ASC;"),
-    /* Used in #postgres_get_reserve_by_h_blind() */
-    GNUNET_PQ_make_prepare (
-      "reserve_by_h_blind",
-      "SELECT"
-      " reserves.reserve_pub"
-      ",reserve_out_serial_id"
-      " FROM reserves_out"
-      " JOIN reserves"
-      "   USING (reserve_uuid)"
-      " WHERE h_blind_ev=$1"
-      " LIMIT 1;"),
-    /* Used in #postgres_get_old_coin_by_h_blind() */
-    GNUNET_PQ_make_prepare (
-      "old_coin_by_h_blind",
-      "SELECT"
-      " okc.coin_pub AS old_coin_pub"
-      ",rrc_serial"
-      " FROM refresh_revealed_coins rrc"
-      " JOIN refresh_commitments rcom USING (melt_serial_id)"
-      " JOIN known_coins okc ON (rcom.old_coin_pub = okc.coin_pub)"
-      " WHERE h_coin_ev=$1"
-      " LIMIT 1;"),
-    /* Used in #postgres_lookup_auditor_timestamp() */
-    GNUNET_PQ_make_prepare (
-      "lookup_auditor_timestamp",
-      "SELECT"
-      " last_change"
-      " FROM auditors"
-      " WHERE auditor_pub=$1;"),
-    /* Used in #postgres_lookup_auditor_status() */
-    GNUNET_PQ_make_prepare (
-      "lookup_auditor_status",
-      "SELECT"
-      " auditor_url"
-      ",is_active"
-      " FROM auditors"
-      " WHERE auditor_pub=$1;"),
-    /* Used in #postgres_lookup_wire_timestamp() */
-    GNUNET_PQ_make_prepare (
-      "lookup_wire_timestamp",
-      "SELECT"
-      " last_change"
-      " FROM wire_accounts"
-      " WHERE payto_uri=$1;"),
-    /* used in #postgres_insert_auditor() */
-    GNUNET_PQ_make_prepare (
-      "insert_auditor",
-      "INSERT INTO auditors "
-      "(auditor_pub"
-      ",auditor_name"
-      ",auditor_url"
-      ",is_active"
-      ",last_change"
-      ") VALUES "
-      "($1, $2, $3, true, $4);"),
-
-    /* used in #postgres_insert_wire() */
-    GNUNET_PQ_make_prepare (
-      "insert_wire",
-      "INSERT INTO wire_accounts "
-      "(payto_uri"
-      ",master_sig"
-      ",is_active"
-      ",last_change"
-      ") VALUES "
-      "($1, $2, true, $3);"),
-    /* used in #postgres_update_wire() */
-    GNUNET_PQ_make_prepare (
-      "update_wire",
-      "UPDATE wire_accounts"
-      " SET"
-      "  is_active=$2"
-      " ,last_change=$3"
-      " WHERE payto_uri=$1"),
-    /* used in #postgres_update_wire() */
-    GNUNET_PQ_make_prepare (
-      "get_wire_accounts",
-      "SELECT"
-      " payto_uri"
-      ",master_sig"
-      " FROM wire_accounts"
-      " WHERE is_active"),
-    /* used in #postgres_update_wire() */
-    GNUNET_PQ_make_prepare (
-      "get_wire_fees",
-      "SELECT"
-      " wire_fee_val"
-      ",wire_fee_frac"
-      ",closing_fee_val"
-      ",closing_fee_frac"
-      ",start_date"
-      ",end_date"
-      ",master_sig"
-      " FROM wire_fee"
-      " WHERE wire_method=$1"),
-    /* used in #postgres_insert_signkey_revocation() */
-    GNUNET_PQ_make_prepare (
-      "insert_signkey_revocation",
-      "INSERT INTO signkey_revocations "
-      "(esk_serial"
-      ",master_sig"
-      ") SELECT esk_serial, $2 "
-      "    FROM exchange_sign_keys"
-      "   WHERE exchange_pub=$1;"),
-    /* used in #postgres_insert_signkey_revocation() */
-    GNUNET_PQ_make_prepare (
-      "lookup_signkey_revocation",
-      "SELECT "
-      " master_sig"
-      " FROM signkey_revocations"
-      " WHERE esk_serial="
-      "   (SELECT esk_serial"
-      "      FROM exchange_sign_keys"
-      "     WHERE exchange_pub=$1);"),
-
-    /* used in #postgres_lookup_signing_key() */
-    GNUNET_PQ_make_prepare (
-      "lookup_signing_key",
-      "SELECT"
-      " valid_from"
-      ",expire_sign"
-      ",expire_legal"
-      " FROM exchange_sign_keys"
-      " WHERE exchange_pub=$1"),
-    /* used in #postgres_lookup_denomination_key() */
-    GNUNET_PQ_make_prepare (
-      "lookup_denomination_key",
-      "SELECT"
-      " valid_from"
-      ",expire_withdraw"
-      ",expire_deposit"
-      ",expire_legal"
-      ",coin_val"
-      ",coin_frac"
-      ",fee_withdraw_val"
-      ",fee_withdraw_frac"
-      ",fee_deposit_val"
-      ",fee_deposit_frac"
-      ",fee_refresh_val"
-      ",fee_refresh_frac"
-      ",fee_refund_val"
-      ",fee_refund_frac"
-      ",age_mask"
-      " FROM denominations"
-      " WHERE denom_pub_hash=$1;"),
-    /* used in #postgres_insert_auditor_denom_sig() */
-    GNUNET_PQ_make_prepare (
-      "insert_auditor_denom_sig",
-      "WITH ax AS"
-      " (SELECT auditor_uuid"
-      "    FROM auditors"
-      "   WHERE auditor_pub=$1)"
-      "INSERT INTO auditor_denom_sigs "
-      "(auditor_uuid"
-      ",denominations_serial"
-      ",auditor_sig"
-      ") SELECT ax.auditor_uuid, denominations_serial, $3 "
-      "    FROM denominations"
-      "   CROSS JOIN ax"
-      "   WHERE denom_pub_hash=$2;"),
-    /* used in #postgres_select_auditor_denom_sig() */
-    GNUNET_PQ_make_prepare (
-      "select_auditor_denom_sig",
-      "SELECT"
-      " auditor_sig"
-      " FROM auditor_denom_sigs"
-      " WHERE auditor_uuid="
-      "  (SELECT auditor_uuid"
-      "    FROM auditors"
-      "    WHERE auditor_pub=$1)"
-      " AND denominations_serial="
-      "  (SELECT denominations_serial"
-      "    FROM denominations"
-      "    WHERE denom_pub_hash=$2);"),
-
-
-    /* Used in #postgres_begin_shard() */
-    GNUNET_PQ_make_prepare (
-      "get_open_shard",
-      "SELECT"
-      " start_row"
-      ",end_row"
-      " FROM work_shards"
-      " WHERE job_name=$1"
-      "   AND completed=FALSE"
-      "   AND last_attempt<$2"
-      " ORDER BY last_attempt ASC"
-      " LIMIT 1;"),
-
-    /* Used in #postgres_begin_shard() */
-    GNUNET_PQ_make_prepare (
-      "reclaim_shard",
-      "UPDATE work_shards"
-      " SET last_attempt=$2"
-      " WHERE job_name=$1"
-      "   AND start_row=$3"
-      "   AND end_row=$4"),
-
-    /* Used in #postgres_begin_shard() */
-    GNUNET_PQ_make_prepare (
-      "get_last_shard",
-      "SELECT"
-      " end_row"
-      " FROM work_shards"
-      " WHERE job_name=$1"
-      " ORDER BY end_row DESC"
-      " LIMIT 1;"),
-
-    /* Used in #postgres_abort_shard() */
-    GNUNET_PQ_make_prepare (
-      "abort_shard",
-      "UPDATE work_shards"
-      "   SET last_attempt=0"
-      " WHERE job_name = $1 "
-      "    AND start_row = $2 "
-      "    AND end_row = $3;"),
-    /* Used in #postgres_begin_shard() */
-    GNUNET_PQ_make_prepare (
-      "claim_next_shard",
-      "INSERT INTO work_shards"
-      "(job_name"
-      ",last_attempt"
-      ",start_row"
-      ",end_row"
-      ") VALUES "
-      "($1, $2, $3, $4);"),
-
-    /* Used in #postgres_complete_shard() */
-    GNUNET_PQ_make_prepare (
-      "complete_shard",
-      "UPDATE work_shards"
-      " SET completed=TRUE"
-      " WHERE job_name=$1"
-      "   AND start_row=$2"
-      "   AND end_row=$3"),
-    /* Used in #postgres_complete_shard() */
-    GNUNET_PQ_make_prepare (
-      "release_revolving_shard",
-      "UPDATE revolving_work_shards"
-      " SET active=FALSE"
-      " WHERE job_name=$1"
-      "   AND start_row=$2"
-      "   AND end_row=$3"),
-    /* Used in #postgres_set_extension_manifest */
-    GNUNET_PQ_make_prepare (
-      "set_extension_manifest",
-      "INSERT INTO extensions (name, manifest) VALUES ($1, $2) "
-      "ON CONFLICT (name) "
-      "DO UPDATE SET manifest=$2"),
-
-
-    /* Used in #postgres_select_purse_by_merge_pub */
-    GNUNET_PQ_make_prepare (
-      "select_purse_by_merge_pub",
-      "SELECT "
-      " purse_pub"
-      ",purse_expiration"
-      ",h_contract_terms"
-      ",age_limit"
-      ",amount_with_fee_val"
-      ",amount_with_fee_frac"
-      ",balance_val"
-      ",balance_frac"
-      ",purse_sig"
-      " FROM purse_requests"
-      " WHERE merge_pub=$1;"),
-
-
-    /* Used in #postgres_do_account_merge() */
-    GNUNET_PQ_make_prepare (
-      "call_account_merge",
-      "SELECT 1"
-      " FROM exchange_do_account_merge"
-      "  ($1, $2, $3);"),
-
-
-    /* Used in #postgres_update_kyc_requirement_by_row() */
-    GNUNET_PQ_make_prepare (
-      "update_legitimization_process",
-      "UPDATE legitimization_processes"
-      " SET provider_user_id=$4"
-      "    ,provider_legitimization_id=$5"
-      "    ,expiration_time=GREATEST(expiration_time,$6)"
-      " WHERE"
-      "      h_payto=$3"
-      "  AND legitimization_process_serial_id=$1"
-      "  AND provider_section=$2;"),
-
-
-    GNUNET_PQ_PREPARED_STATEMENT_END
-  };
-
-  ret = GNUNET_PQ_prepare_statements (pg->conn,
-                                      ps);
-  if (GNUNET_OK != ret)
-    return ret;
-  pg->init = true;
-  return GNUNET_OK;
-}
+  ret = GNUNET_PQ_prepare_statements (pg->conn,
+                                      ps);
+  if (GNUNET_OK != ret)
+    return ret;
+  pg->init = true;
+  return GNUNET_OK;
+}
 
 
 /**
@@ -1923,141 +384,21 @@ TEH_PG_internal_setup (struct PostgresClosure *pg,
 }
 
 
-/**
- * Register callback to be invoked on events of type @a es.
- *
- * @param cls database context to use
- * @param timeout how long until to generate a timeout event
- * @param es specification of the event to listen for
- * @param cb function to call when the event happens, possibly
- *         multiple times (until cancel is invoked)
- * @param cb_cls closure for @a cb
- * @return handle useful to cancel the listener
- */
-static struct GNUNET_DB_EventHandler *
-postgres_event_listen (void *cls,
-                       struct GNUNET_TIME_Relative timeout,
-                       const struct GNUNET_DB_EventHeaderP *es,
-                       GNUNET_DB_EventCallback cb,
-                       void *cb_cls)
-{
-  struct PostgresClosure *pg = cls;
-
-  return GNUNET_PQ_event_listen (pg->conn,
-                                 es,
-                                 timeout,
-                                 cb,
-                                 cb_cls);
-}
-
-
-/**
- * Stop notifications.
- *
- * @param cls the plugin's `struct PostgresClosure`
- * @param eh handle to unregister.
- */
-static void
-postgres_event_listen_cancel (void *cls,
-                              struct GNUNET_DB_EventHandler *eh)
-{
-  (void) cls;
-  GNUNET_PQ_event_listen_cancel (eh);
-}
-
-
-/**
- * Notify all that listen on @a es of an event.
- *
- * @param cls database context to use
- * @param es specification of the event to generate
- * @param extra additional event data provided
- * @param extra_size number of bytes in @a extra
- */
-static void
-postgres_event_notify (void *cls,
-                       const struct GNUNET_DB_EventHeaderP *es,
-                       const void *extra,
-                       size_t extra_size)
-{
-  struct PostgresClosure *pg = cls;
-
-  GNUNET_PQ_event_notify (pg->conn,
-                          es,
-                          extra,
-                          extra_size);
-}
-
-
-/**
- * Fetch information about a denomination key.
- *
- * @param cls the @e cls of this struct with the plugin-specific state
- * @param denom_pub_hash hash of the public key used for signing coins of this 
denomination
- * @param[out] issue set to issue information with value, fees and other info 
about the coin
- * @return transaction status code
- */
-static enum GNUNET_DB_QueryStatus
-postgres_get_denomination_info (
-  void *cls,
-  const struct TALER_DenominationHashP *denom_pub_hash,
-  struct TALER_EXCHANGEDB_DenominationKeyInformation *issue)
-{
-  struct PostgresClosure *pg = cls;
-  enum GNUNET_DB_QueryStatus qs;
-  struct GNUNET_PQ_QueryParam params[] = {
-    GNUNET_PQ_query_param_auto_from_type (denom_pub_hash),
-    GNUNET_PQ_query_param_end
-  };
-  struct GNUNET_PQ_ResultSpec rs[] = {
-    GNUNET_PQ_result_spec_auto_from_type ("master_sig",
-                                          &issue->signature),
-    GNUNET_PQ_result_spec_timestamp ("valid_from",
-                                     &issue->start),
-    GNUNET_PQ_result_spec_timestamp ("expire_withdraw",
-                                     &issue->expire_withdraw),
-    GNUNET_PQ_result_spec_timestamp ("expire_deposit",
-                                     &issue->expire_deposit),
-    GNUNET_PQ_result_spec_timestamp ("expire_legal",
-                                     &issue->expire_legal),
-    TALER_PQ_RESULT_SPEC_AMOUNT ("coin",
-                                 &issue->value),
-    TALER_PQ_RESULT_SPEC_AMOUNT ("fee_withdraw",
-                                 &issue->fees.withdraw),
-    TALER_PQ_RESULT_SPEC_AMOUNT ("fee_deposit",
-                                 &issue->fees.deposit),
-    TALER_PQ_RESULT_SPEC_AMOUNT ("fee_refresh",
-                                 &issue->fees.refresh),
-    TALER_PQ_RESULT_SPEC_AMOUNT ("fee_refund",
-                                 &issue->fees.refund),
-    GNUNET_PQ_result_spec_uint32 ("age_mask",
-                                  &issue->age_mask.bits),
-    GNUNET_PQ_result_spec_end
-  };
 
-  qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
-                                                 "denomination_get",
-                                                 params,
-                                                 rs);
-  if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != qs)
-    return qs;
-  issue->denom_hash = *denom_pub_hash;
-  return qs;
-}
 
 
 /**
- * Closure for #domination_cb_helper()
+ * Closure for #get_refunds_cb().
  */
-struct DenomIteratorContext
+struct SelectRefundContext
 {
   /**
-   * Function to call with the results.
+   * Function to call on each result.
    */
-  TALER_EXCHANGEDB_DenominationCallback cb;
+  TALER_EXCHANGEDB_RefundCoinCallback cb;
 
   /**
-   * Closure to pass to @e cb
+   * Closure for @a cb.
    */
   void *cb_cls;
 
@@ -2065,57 +406,36 @@ struct DenomIteratorContext
    * Plugin context.
    */
   struct PostgresClosure *pg;
+
+  /**
+   * Set to #GNUNET_SYSERR on error.
+   */
+  int status;
 };
 
 
 /**
- * Helper function for #postgres_iterate_denomination_info().
- * Calls the callback with each denomination key.
+ * Function to be called with the results of a SELECT statement
+ * that has returned @a num_results results.
  *
- * @param cls a `struct DenomIteratorContext`
- * @param result db results
- * @param num_results number of results in @a result
+ * @param cls closure of type `struct SelectRefundContext *`
+ * @param result the postgres result
+ * @param num_results the number of results in @a result
  */
 static void
-domination_cb_helper (void *cls,
-                      PGresult *result,
-                      unsigned int num_results)
+get_refunds_cb (void *cls,
+                PGresult *result,
+                unsigned int num_results)
 {
-  struct DenomIteratorContext *dic = cls;
-  struct PostgresClosure *pg = dic->pg;
+  struct SelectRefundContext *srctx = cls;
+  struct PostgresClosure *pg = srctx->pg;
 
   for (unsigned int i = 0; i<num_results; i++)
   {
-    struct TALER_EXCHANGEDB_DenominationKeyInformation issue;
-    struct TALER_DenominationPublicKey denom_pub;
-    struct TALER_DenominationHashP denom_hash;
+    struct TALER_Amount amount_with_fee;
     struct GNUNET_PQ_ResultSpec rs[] = {
-      GNUNET_PQ_result_spec_auto_from_type ("master_sig",
-                                            &issue.signature),
-      GNUNET_PQ_result_spec_auto_from_type ("denom_pub_hash",
-                                            &denom_hash),
-      GNUNET_PQ_result_spec_timestamp ("valid_from",
-                                       &issue.start),
-      GNUNET_PQ_result_spec_timestamp ("expire_withdraw",
-                                       &issue.expire_withdraw),
-      GNUNET_PQ_result_spec_timestamp ("expire_deposit",
-                                       &issue.expire_deposit),
-      GNUNET_PQ_result_spec_timestamp ("expire_legal",
-                                       &issue.expire_legal),
-      TALER_PQ_RESULT_SPEC_AMOUNT ("coin",
-                                   &issue.value),
-      TALER_PQ_RESULT_SPEC_AMOUNT ("fee_withdraw",
-                                   &issue.fees.withdraw),
-      TALER_PQ_RESULT_SPEC_AMOUNT ("fee_deposit",
-                                   &issue.fees.deposit),
-      TALER_PQ_RESULT_SPEC_AMOUNT ("fee_refresh",
-                                   &issue.fees.refresh),
-      TALER_PQ_RESULT_SPEC_AMOUNT ("fee_refund",
-                                   &issue.fees.refund),
-      TALER_PQ_result_spec_denom_pub ("denom_pub",
-                                      &denom_pub),
-      GNUNET_PQ_result_spec_uint32 ("age_mask",
-                                    &issue.age_mask.bits),
+      TALER_PQ_RESULT_SPEC_AMOUNT ("amount_with_fee",
+                                   &amount_with_fee),
       GNUNET_PQ_result_spec_end
     };
 
@@ -2125,1772 +445,1507 @@ domination_cb_helper (void *cls,
                                   i))
     {
       GNUNET_break (0);
+      srctx->status = GNUNET_SYSERR;
       return;
     }
-
-    /* Unfortunately we have to carry the age mask in both, the
-     * TALER_DenominationPublicKey and
-     * TALER_EXCHANGEDB_DenominationKeyInformation at different times.
-     * Here we use _both_ so let's make sure the values are the same. */
-    denom_pub.age_mask = issue.age_mask;
-    TALER_denom_pub_hash (&denom_pub,
-                          &issue.denom_hash);
-    if (0 !=
-        GNUNET_memcmp (&issue.denom_hash,
-                       &denom_hash))
-    {
-      GNUNET_break (0);
-    }
-    else
-    {
-      dic->cb (dic->cb_cls,
-               &denom_pub,
-               &issue);
-    }
-    TALER_denom_pub_free (&denom_pub);
+    if (GNUNET_OK !=
+        srctx->cb (srctx->cb_cls,
+                   &amount_with_fee))
+      return;
   }
 }
 
 
-/**
- * Fetch information about all known denomination keys.
+
+
+
+/* Get the details of a policy, referenced by its hash code
  *
- * @param cls the @e cls of this struct with the plugin-specific state
- * @param cb function to call on each denomination key
- * @param cb_cls closure for @a cb
- * @return transaction status code
- */
+ * @param cls the `struct PostgresClosure` with the plugin-specific state
+ * @param hc The hash code under which the details to a particular policy 
should be found
+ * @param[out] details The found details
+ * @return query execution status
+ * */
 static enum GNUNET_DB_QueryStatus
-postgres_iterate_denomination_info (void *cls,
-                                    TALER_EXCHANGEDB_DenominationCallback cb,
-                                    void *cb_cls)
+postgres_get_policy_details (
+  void *cls,
+  const struct GNUNET_HashCode *hc,
+  struct TALER_PolicyDetails *details)
 {
   struct PostgresClosure *pg = cls;
   struct GNUNET_PQ_QueryParam params[] = {
+    GNUNET_PQ_query_param_auto_from_type (hc),
     GNUNET_PQ_query_param_end
   };
-  struct DenomIteratorContext dic = {
-    .cb = cb,
-    .cb_cls = cb_cls,
-    .pg = pg
+  struct GNUNET_PQ_ResultSpec rs[] = {
+    GNUNET_PQ_result_spec_timestamp ("deadline",
+                                     &details->deadline),
+    TALER_PQ_RESULT_SPEC_AMOUNT ("commitment",
+                                 &details->commitment),
+    TALER_PQ_RESULT_SPEC_AMOUNT ("accumulated_total",
+                                 &details->accumulated_total),
+    TALER_PQ_RESULT_SPEC_AMOUNT ("policy_fee",
+                                 &details->policy_fee),
+    TALER_PQ_RESULT_SPEC_AMOUNT ("transferable_amount",
+                                 &details->transferable_amount),
+    GNUNET_PQ_result_spec_auto_from_type ("state",
+                                          &details->fulfillment_state),
+    GNUNET_PQ_result_spec_allow_null (
+      GNUNET_PQ_result_spec_uint64 ("policy_fulfillment_id",
+                                    &details->policy_fulfillment_id),
+      &details->no_policy_fulfillment_id),
+    GNUNET_PQ_result_spec_end
   };
 
-  return GNUNET_PQ_eval_prepared_multi_select (pg->conn,
-                                               "denomination_iterate",
-                                               params,
-                                               &domination_cb_helper,
-                                               &dic);
+  return GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
+                                                   "get_policy_details",
+                                                   params,
+                                                   rs);
 }
 
 
-/**
- * Closure for #dominations_cb_helper()
+/* Persist the details to a policy in the policy_details table.  If there
+ * already exists a policy, update the fields accordingly.
+ *
+ * @param details The policy details that should be persisted.  If an entry for
+ *        the given details->hash_code exists, the values will be updated.
+ * @param[out] policy_details_serial_id The row ID of the policy details
+ * @param[out] accumulated_total The total amount accumulated in that policy
+ * @param[out] fulfillment_state The state of policy.  If the state was 
Insufficient prior to the call and the provided deposit raises the 
accumulated_total above the commitment, it will be set to Ready.
+ * @return query execution status
  */
-struct DenomsIteratorContext
+static enum GNUNET_DB_QueryStatus
+postgres_persist_policy_details (
+  void *cls,
+  const struct TALER_PolicyDetails *details,
+  uint64_t *policy_details_serial_id,
+  struct TALER_Amount *accumulated_total,
+  enum TALER_PolicyFulfillmentState *fulfillment_state)
 {
-  /**
-   * Function to call with the results.
-   */
-  TALER_EXCHANGEDB_DenominationsCallback cb;
+  struct PostgresClosure *pg = cls;
+  struct GNUNET_PQ_QueryParam params[] = {
+    GNUNET_PQ_query_param_auto_from_type (&details->hash_code),
+    TALER_PQ_query_param_json (details->policy_json),
+    GNUNET_PQ_query_param_timestamp (&details->deadline),
+    TALER_PQ_query_param_amount (&details->commitment),
+    TALER_PQ_query_param_amount (&details->accumulated_total),
+    TALER_PQ_query_param_amount (&details->policy_fee),
+    TALER_PQ_query_param_amount (&details->transferable_amount),
+    GNUNET_PQ_query_param_auto_from_type (&details->fulfillment_state),
+    (details->no_policy_fulfillment_id)
+     ?  GNUNET_PQ_query_param_null ()
+     : GNUNET_PQ_query_param_uint64 (&details->policy_fulfillment_id),
+    GNUNET_PQ_query_param_end
+  };
+  struct GNUNET_PQ_ResultSpec rs[] = {
+    GNUNET_PQ_result_spec_uint64 ("policy_details_serial_id",
+                                  policy_details_serial_id),
+    TALER_PQ_RESULT_SPEC_AMOUNT ("accumulated_total",
+                                 accumulated_total),
+    GNUNET_PQ_result_spec_uint32 ("fulfillment_state",
+                                  fulfillment_state),
+    GNUNET_PQ_result_spec_end
+  };
 
-  /**
-   * Closure to pass to @e cb
-   */
-  void *cb_cls;
-
-  /**
-   * Plugin context.
-   */
-  struct PostgresClosure *pg;
-};
-
-
-/**
- * Helper function for #postgres_iterate_denominations().
- * Calls the callback with each denomination key.
- *
- * @param cls a `struct DenomsIteratorContext`
- * @param result db results
- * @param num_results number of results in @a result
- */
-static void
-dominations_cb_helper (void *cls,
-                       PGresult *result,
-                       unsigned int num_results)
-{
-  struct DenomsIteratorContext *dic = cls;
-  struct PostgresClosure *pg = dic->pg;
-
-  for (unsigned int i = 0; i<num_results; i++)
-  {
-    struct TALER_EXCHANGEDB_DenominationKeyMetaData meta = {0};
-    struct TALER_DenominationPublicKey denom_pub = {0};
-    struct TALER_MasterSignatureP master_sig = {0};
-    struct TALER_DenominationHashP h_denom_pub = {0};
-    bool revoked;
-    struct GNUNET_PQ_ResultSpec rs[] = {
-      GNUNET_PQ_result_spec_auto_from_type ("master_sig",
-                                            &master_sig),
-      GNUNET_PQ_result_spec_bool ("revoked",
-                                  &revoked),
-      GNUNET_PQ_result_spec_timestamp ("valid_from",
-                                       &meta.start),
-      GNUNET_PQ_result_spec_timestamp ("expire_withdraw",
-                                       &meta.expire_withdraw),
-      GNUNET_PQ_result_spec_timestamp ("expire_deposit",
-                                       &meta.expire_deposit),
-      GNUNET_PQ_result_spec_timestamp ("expire_legal",
-                                       &meta.expire_legal),
-      TALER_PQ_RESULT_SPEC_AMOUNT ("coin",
-                                   &meta.value),
-      TALER_PQ_RESULT_SPEC_AMOUNT ("fee_withdraw",
-                                   &meta.fees.withdraw),
-      TALER_PQ_RESULT_SPEC_AMOUNT ("fee_deposit",
-                                   &meta.fees.deposit),
-      TALER_PQ_RESULT_SPEC_AMOUNT ("fee_refresh",
-                                   &meta.fees.refresh),
-      TALER_PQ_RESULT_SPEC_AMOUNT ("fee_refund",
-                                   &meta.fees.refund),
-      TALER_PQ_result_spec_denom_pub ("denom_pub",
-                                      &denom_pub),
-      GNUNET_PQ_result_spec_uint32 ("age_mask",
-                                    &meta.age_mask.bits),
-      GNUNET_PQ_result_spec_end
-    };
-
-    if (GNUNET_OK !=
-        GNUNET_PQ_extract_result (result,
-                                  rs,
-                                  i))
-    {
-      GNUNET_break (0);
-      return;
-    }
-
-    /* make sure the mask information is the same */
-    denom_pub.age_mask = meta.age_mask;
-
-    TALER_denom_pub_hash (&denom_pub,
-                          &h_denom_pub);
-    dic->cb (dic->cb_cls,
-             &denom_pub,
-             &h_denom_pub,
-             &meta,
-             &master_sig,
-             revoked);
-    GNUNET_PQ_cleanup_result (rs);
-  }
-}
+  return GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
+                                                   
"call_insert_or_update_policy_details",
+                                                   params,
+                                                   rs);
+}
 
 
 /**
- * Function called to invoke @a cb on every known denomination key (revoked
- * and non-revoked) that has been signed by the master key. Runs in its own
- * read-only transaction.
- *
+ * Perform melt operation, checking for sufficient balance
+ * of the coin and possibly persisting the melt details.
  *
- * @param cls the @e cls of this struct with the plugin-specific state
- * @param cb function to call on each denomination key
- * @param cb_cls closure for @a cb
- * @return transaction status code
+ * @param cls the `struct PostgresClosure` with the plugin-specific state
+ * @param rms client-contributed input for CS denominations that must be 
checked for idempotency, or NULL for non-CS withdrawals
+ * @param[in,out] refresh refresh operation details; the noreveal_index
+ *                is set in case the coin was already melted before
+ * @param known_coin_id row of the coin in the known_coins table
+ * @param[in,out] zombie_required true if the melt must only succeed if the 
coin is a zombie, set to false if the requirement was satisfied
+ * @param[out] balance_ok set to true if the balance was sufficient
+ * @return query execution status
  */
 static enum GNUNET_DB_QueryStatus
-postgres_iterate_denominations (void *cls,
-                                TALER_EXCHANGEDB_DenominationsCallback cb,
-                                void *cb_cls)
+postgres_do_melt (
+  void *cls,
+  const struct TALER_RefreshMasterSecretP *rms,
+  struct TALER_EXCHANGEDB_Refresh *refresh,
+  uint64_t known_coin_id,
+  bool *zombie_required,
+  bool *balance_ok)
 {
   struct PostgresClosure *pg = cls;
   struct GNUNET_PQ_QueryParam params[] = {
+    NULL == rms
+    ? GNUNET_PQ_query_param_null ()
+    : GNUNET_PQ_query_param_auto_from_type (rms),
+    TALER_PQ_query_param_amount (&refresh->amount_with_fee),
+    GNUNET_PQ_query_param_auto_from_type (&refresh->rc),
+    GNUNET_PQ_query_param_auto_from_type (&refresh->coin.coin_pub),
+    GNUNET_PQ_query_param_auto_from_type (&refresh->coin_sig),
+    GNUNET_PQ_query_param_uint64 (&known_coin_id),
+    GNUNET_PQ_query_param_uint32 (&refresh->noreveal_index),
+    GNUNET_PQ_query_param_bool (*zombie_required),
     GNUNET_PQ_query_param_end
   };
-  struct DenomsIteratorContext dic = {
-    .cb = cb,
-    .cb_cls = cb_cls,
-    .pg = pg
+  bool is_null;
+  struct GNUNET_PQ_ResultSpec rs[] = {
+    GNUNET_PQ_result_spec_bool ("balance_ok",
+                                balance_ok),
+    GNUNET_PQ_result_spec_bool ("zombie_required",
+                                zombie_required),
+    GNUNET_PQ_result_spec_allow_null (
+      GNUNET_PQ_result_spec_uint32 ("noreveal_index",
+                                    &refresh->noreveal_index),
+      &is_null),
+    GNUNET_PQ_result_spec_end
   };
+  enum GNUNET_DB_QueryStatus qs;
 
-  return GNUNET_PQ_eval_prepared_multi_select (pg->conn,
-                                               "select_denominations",
-                                               params,
-                                               &dominations_cb_helper,
-                                               &dic);
+  qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
+                                                 "call_melt",
+                                                 params,
+                                                 rs);
+  if (is_null)
+    refresh->noreveal_index = UINT32_MAX; /* set to very invalid value */
+  return qs;
 }
 
 
 /**
- * Closure for #auditors_cb_helper()
- */
-struct AuditorsIteratorContext
-{
-  /**
-   * Function to call with the results.
-   */
-  TALER_EXCHANGEDB_AuditorsCallback cb;
-
-  /**
-   * Closure to pass to @e cb
-   */
-  void *cb_cls;
-
-};
-
-
-/**
- * Helper function for #postgres_iterate_active_auditors().
- * Calls the callback with each auditor.
+ * Perform refund operation, checking for sufficient deposits
+ * of the coin and possibly persisting the refund details.
  *
- * @param cls a `struct SignkeysIteratorContext`
- * @param result db results
- * @param num_results number of results in @a result
+ * @param cls the `struct PostgresClosure` with the plugin-specific state
+ * @param refund refund operation details
+ * @param deposit_fee deposit fee applicable for the coin, possibly refunded
+ * @param known_coin_id row of the coin in the known_coins table
+ * @param[out] not_found set if the deposit was not found
+ * @param[out] refund_ok  set if the refund succeeded (below deposit amount)
+ * @param[out] gone if the merchant was already paid
+ * @param[out] conflict set if the refund ID was re-used
+ * @return query execution status
  */
-static void
-auditors_cb_helper (void *cls,
-                    PGresult *result,
-                    unsigned int num_results)
+static enum GNUNET_DB_QueryStatus
+postgres_do_refund (
+  void *cls,
+  const struct TALER_EXCHANGEDB_Refund *refund,
+  const struct TALER_Amount *deposit_fee,
+  uint64_t known_coin_id,
+  bool *not_found,
+  bool *refund_ok,
+  bool *gone,
+  bool *conflict)
 {
-  struct AuditorsIteratorContext *dic = cls;
+  struct PostgresClosure *pg = cls;
+  uint64_t deposit_shard = TEH_PG_compute_shard 
(&refund->details.merchant_pub);
+  struct TALER_Amount amount_without_fee;
+  struct GNUNET_PQ_QueryParam params[] = {
+    TALER_PQ_query_param_amount (&refund->details.refund_amount),
+    TALER_PQ_query_param_amount (&amount_without_fee),
+    TALER_PQ_query_param_amount (deposit_fee),
+    GNUNET_PQ_query_param_auto_from_type (&refund->details.h_contract_terms),
+    GNUNET_PQ_query_param_uint64 (&refund->details.rtransaction_id),
+    GNUNET_PQ_query_param_uint64 (&deposit_shard),
+    GNUNET_PQ_query_param_uint64 (&known_coin_id),
+    GNUNET_PQ_query_param_auto_from_type (&refund->coin.coin_pub),
+    GNUNET_PQ_query_param_auto_from_type (&refund->details.merchant_pub),
+    GNUNET_PQ_query_param_auto_from_type (&refund->details.merchant_sig),
+    GNUNET_PQ_query_param_end
+  };
+  struct GNUNET_PQ_ResultSpec rs[] = {
+    GNUNET_PQ_result_spec_bool ("not_found",
+                                not_found),
+    GNUNET_PQ_result_spec_bool ("refund_ok",
+                                refund_ok),
+    GNUNET_PQ_result_spec_bool ("gone",
+                                gone),
+    GNUNET_PQ_result_spec_bool ("conflict",
+                                conflict),
+    GNUNET_PQ_result_spec_end
+  };
 
-  for (unsigned int i = 0; i<num_results; i++)
+  if (0 >
+      TALER_amount_subtract (&amount_without_fee,
+                             &refund->details.refund_amount,
+                             &refund->details.refund_fee))
   {
-    struct TALER_AuditorPublicKeyP auditor_pub;
-    char *auditor_url;
-    char *auditor_name;
-    struct GNUNET_PQ_ResultSpec rs[] = {
-      GNUNET_PQ_result_spec_auto_from_type ("auditor_pub",
-                                            &auditor_pub),
-      GNUNET_PQ_result_spec_string ("auditor_url",
-                                    &auditor_url),
-      GNUNET_PQ_result_spec_string ("auditor_name",
-                                    &auditor_name),
-      GNUNET_PQ_result_spec_end
-    };
-
-    if (GNUNET_OK !=
-        GNUNET_PQ_extract_result (result,
-                                  rs,
-                                  i))
-    {
-      GNUNET_break (0);
-      return;
-    }
-    dic->cb (dic->cb_cls,
-             &auditor_pub,
-             auditor_url,
-             auditor_name);
-    GNUNET_PQ_cleanup_result (rs);
+    GNUNET_break (0);
+    return GNUNET_DB_STATUS_HARD_ERROR;
   }
+  return GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
+                                                   "call_refund",
+                                                   params,
+                                                   rs);
 }
 
 
 /**
- * Function called to invoke @a cb on every active auditor. Disabled
- * auditors are skipped. Runs in its own read-only transaction.
+ * Perform recoup operation, checking for sufficient deposits
+ * of the coin and possibly persisting the recoup details.
  *
- * @param cls the @e cls of this struct with the plugin-specific state
- * @param cb function to call on each active auditor
- * @param cb_cls closure for @a cb
- * @return transaction status code
+ * @param cls the `struct PostgresClosure` with the plugin-specific state
+ * @param reserve_pub public key of the reserve to credit
+ * @param reserve_out_serial_id row in the reserves_out table justifying the 
recoup
+ * @param coin_bks coin blinding key secret to persist
+ * @param coin_pub public key of the coin being recouped
+ * @param known_coin_id row of the @a coin_pub in the known_coins table
+ * @param coin_sig signature of the coin requesting the recoup
+ * @param[in,out] recoup_timestamp recoup timestamp, set if recoup existed
+ * @param[out] recoup_ok  set if the recoup succeeded (balance ok)
+ * @param[out] internal_failure set on internal failures
+ * @return query execution status
  */
 static enum GNUNET_DB_QueryStatus
-postgres_iterate_active_auditors (void *cls,
-                                  TALER_EXCHANGEDB_AuditorsCallback cb,
-                                  void *cb_cls)
+postgres_do_recoup (
+  void *cls,
+  const struct TALER_ReservePublicKeyP *reserve_pub,
+  uint64_t reserve_out_serial_id,
+  const union TALER_DenominationBlindingKeyP *coin_bks,
+  const struct TALER_CoinSpendPublicKeyP *coin_pub,
+  uint64_t known_coin_id,
+  const struct TALER_CoinSpendSignatureP *coin_sig,
+  struct GNUNET_TIME_Timestamp *recoup_timestamp,
+  bool *recoup_ok,
+  bool *internal_failure)
 {
   struct PostgresClosure *pg = cls;
+  struct GNUNET_TIME_Timestamp reserve_gc
+    = GNUNET_TIME_relative_to_timestamp (pg->legal_reserve_expiration_time);
+  struct GNUNET_TIME_Timestamp reserve_expiration
+    = GNUNET_TIME_relative_to_timestamp (pg->idle_reserve_expiration_time);
   struct GNUNET_PQ_QueryParam params[] = {
+    GNUNET_PQ_query_param_auto_from_type (reserve_pub),
+    GNUNET_PQ_query_param_uint64 (&reserve_out_serial_id),
+    GNUNET_PQ_query_param_auto_from_type (coin_bks),
+    GNUNET_PQ_query_param_auto_from_type (coin_pub),
+    GNUNET_PQ_query_param_uint64 (&known_coin_id),
+    GNUNET_PQ_query_param_auto_from_type (coin_sig),
+    GNUNET_PQ_query_param_timestamp (&reserve_gc),
+    GNUNET_PQ_query_param_timestamp (&reserve_expiration),
+    GNUNET_PQ_query_param_timestamp (recoup_timestamp),
     GNUNET_PQ_query_param_end
   };
-  struct AuditorsIteratorContext dic = {
-    .cb = cb,
-    .cb_cls = cb_cls,
+  bool is_null;
+  struct GNUNET_PQ_ResultSpec rs[] = {
+    GNUNET_PQ_result_spec_allow_null (
+      GNUNET_PQ_result_spec_timestamp ("recoup_timestamp",
+                                       recoup_timestamp),
+      &is_null),
+    GNUNET_PQ_result_spec_bool ("recoup_ok",
+                                recoup_ok),
+    GNUNET_PQ_result_spec_bool ("internal_failure",
+                                internal_failure),
+    GNUNET_PQ_result_spec_end
   };
 
-  return GNUNET_PQ_eval_prepared_multi_select (pg->conn,
-                                               "select_auditors",
-                                               params,
-                                               &auditors_cb_helper,
-                                               &dic);
+  return GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
+                                                   "call_recoup",
+                                                   params,
+                                                   rs);
 }
 
 
 /**
- * Closure for #auditor_denoms_cb_helper()
- */
-struct AuditorDenomsIteratorContext
-{
-  /**
-   * Function to call with the results.
-   */
-  TALER_EXCHANGEDB_AuditorDenominationsCallback cb;
-
-  /**
-   * Closure to pass to @e cb
-   */
-  void *cb_cls;
-};
-
-
-/**
- * Helper function for #postgres_iterate_auditor_denominations().
- * Calls the callback with each auditor and denomination pair.
+ * Perform recoup-refresh operation, checking for sufficient deposits of the
+ * coin and possibly persisting the recoup-refresh details.
  *
- * @param cls a `struct AuditorDenomsIteratorContext`
- * @param result db results
- * @param num_results number of results in @a result
- */
-static void
-auditor_denoms_cb_helper (void *cls,
-                          PGresult *result,
-                          unsigned int num_results)
-{
-  struct AuditorDenomsIteratorContext *dic = cls;
-
-  for (unsigned int i = 0; i<num_results; i++)
-  {
-    struct TALER_AuditorPublicKeyP auditor_pub;
-    struct TALER_DenominationHashP h_denom_pub;
-    struct TALER_AuditorSignatureP auditor_sig;
-    struct GNUNET_PQ_ResultSpec rs[] = {
-      GNUNET_PQ_result_spec_auto_from_type ("auditor_pub",
-                                            &auditor_pub),
-      GNUNET_PQ_result_spec_auto_from_type ("denom_pub_hash",
-                                            &h_denom_pub),
-      GNUNET_PQ_result_spec_auto_from_type ("auditor_sig",
-                                            &auditor_sig),
-      GNUNET_PQ_result_spec_end
-    };
-
-    if (GNUNET_OK !=
-        GNUNET_PQ_extract_result (result,
-                                  rs,
-                                  i))
-    {
-      GNUNET_break (0);
-      return;
-    }
-    dic->cb (dic->cb_cls,
-             &auditor_pub,
-             &h_denom_pub,
-             &auditor_sig);
-  }
-}
-
-
-/**
- * Function called to invoke @a cb on every denomination with an active
- * auditor. Disabled auditors and denominations without auditor are
- * skipped. Runs in its own read-only transaction.
- *
- * @param cls the @e cls of this struct with the plugin-specific state
- * @param cb function to call on each active auditor
- * @param cb_cls closure for @a cb
- * @return transaction status code
+ * @param cls the `struct PostgresClosure` with the plugin-specific state
+ * @param old_coin_pub public key of the old coin to credit
+ * @param rrc_serial row in the refresh_revealed_coins table justifying the 
recoup-refresh
+ * @param coin_bks coin blinding key secret to persist
+ * @param coin_pub public key of the coin being recouped
+ * @param known_coin_id row of the @a coin_pub in the known_coins table
+ * @param coin_sig signature of the coin requesting the recoup
+ * @param[in,out] recoup_timestamp recoup timestamp, set if recoup existed
+ * @param[out] recoup_ok  set if the recoup-refresh succeeded (balance ok)
+ * @param[out] internal_failure set on internal failures
+ * @return query execution status
  */
 static enum GNUNET_DB_QueryStatus
-postgres_iterate_auditor_denominations (
+postgres_do_recoup_refresh (
   void *cls,
-  TALER_EXCHANGEDB_AuditorDenominationsCallback cb,
-  void *cb_cls)
+  const struct TALER_CoinSpendPublicKeyP *old_coin_pub,
+  uint64_t rrc_serial,
+  const union TALER_DenominationBlindingKeyP *coin_bks,
+  const struct TALER_CoinSpendPublicKeyP *coin_pub,
+  uint64_t known_coin_id,
+  const struct TALER_CoinSpendSignatureP *coin_sig,
+  struct GNUNET_TIME_Timestamp *recoup_timestamp,
+  bool *recoup_ok,
+  bool *internal_failure)
 {
   struct PostgresClosure *pg = cls;
   struct GNUNET_PQ_QueryParam params[] = {
+    GNUNET_PQ_query_param_auto_from_type (old_coin_pub),
+    GNUNET_PQ_query_param_uint64 (&rrc_serial),
+    GNUNET_PQ_query_param_auto_from_type (coin_bks),
+    GNUNET_PQ_query_param_auto_from_type (coin_pub),
+    GNUNET_PQ_query_param_uint64 (&known_coin_id),
+    GNUNET_PQ_query_param_auto_from_type (coin_sig),
+    GNUNET_PQ_query_param_timestamp (recoup_timestamp),
     GNUNET_PQ_query_param_end
   };
-  struct AuditorDenomsIteratorContext dic = {
-    .cb = cb,
-    .cb_cls = cb_cls,
+  bool is_null;
+  struct GNUNET_PQ_ResultSpec rs[] = {
+    GNUNET_PQ_result_spec_allow_null (
+      GNUNET_PQ_result_spec_timestamp ("recoup_timestamp",
+                                       recoup_timestamp),
+      &is_null),
+    GNUNET_PQ_result_spec_bool ("recoup_ok",
+                                recoup_ok),
+    GNUNET_PQ_result_spec_bool ("internal_failure",
+                                internal_failure),
+    GNUNET_PQ_result_spec_end
   };
 
-  return GNUNET_PQ_eval_prepared_multi_select (pg->conn,
-                                               "select_auditor_denoms",
-                                               params,
-                                               &auditor_denoms_cb_helper,
-                                               &dic);
+  return GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
+                                                   "call_recoup_refresh",
+                                                   params,
+                                                   rs);
 }
 
 
 /**
- * Get the summary of a reserve.
+ * Compares two indices into an array of hash codes according to
+ * GNUNET_CRYPTO_hash_cmp of the content at those index positions.
  *
- * @param cls the `struct PostgresClosure` with the plugin-specific state
- * @param[in,out] reserve the reserve data.  The public key of the reserve 
should be
- *          set in this structure; it is used to query the database.  The 
balance
- *          and expiration are then filled accordingly.
- * @return transaction status
+ * Used in a call qsort_t in order to generate sorted policy_hash_codes.
  */
-static enum GNUNET_DB_QueryStatus
-postgres_reserves_get (void *cls,
-                       struct TALER_EXCHANGEDB_Reserve *reserve)
+static int
+hash_code_cmp (
+  const void *hc1,
+  const void *hc2,
+  void *arg)
 {
-  struct PostgresClosure *pg = cls;
-  struct GNUNET_PQ_QueryParam params[] = {
-    GNUNET_PQ_query_param_auto_from_type (&reserve->pub),
-    GNUNET_PQ_query_param_end
-  };
-  struct GNUNET_PQ_ResultSpec rs[] = {
-    TALER_PQ_RESULT_SPEC_AMOUNT ("current_balance",
-                                 &reserve->balance),
-    GNUNET_PQ_result_spec_timestamp ("expiration_date",
-                                     &reserve->expiry),
-    GNUNET_PQ_result_spec_timestamp ("gc_date",
-                                     &reserve->gc),
-    GNUNET_PQ_result_spec_end
-  };
+  size_t i1 = *(size_t *) hc1;
+  size_t i2 = *(size_t *) hc2;
+  const struct TALER_PolicyDetails *d = arg;
 
-  return GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
-                                                   "reserves_get",
-                                                   params,
-                                                   rs);
+  return GNUNET_CRYPTO_hash_cmp (&d[i1].hash_code,
+                                 &d[i2].hash_code);
 }
 
 
 /**
- * Get the origin of funds of a reserve.
+ * Add a proof of fulfillment into the policy_fulfillments table
  *
  * @param cls the `struct PostgresClosure` with the plugin-specific state
- * @param reserve_pub public key of the reserve
- * @param[out] h_payto set to hash of the wire source payto://-URI
- * @return transaction status
+ * @param fulfillment fullfilment transaction data to be added
+ * @return query execution status
  */
 static enum GNUNET_DB_QueryStatus
-postgres_reserves_get_origin (
+postgres_add_policy_fulfillment_proof (
   void *cls,
-  const struct TALER_ReservePublicKeyP *reserve_pub,
-  struct TALER_PaytoHashP *h_payto)
+  struct TALER_PolicyFulfillmentTransactionData *fulfillment)
 {
+  enum GNUNET_DB_QueryStatus qs;
   struct PostgresClosure *pg = cls;
-  struct GNUNET_PQ_QueryParam params[] = {
-    GNUNET_PQ_query_param_auto_from_type (reserve_pub),
-    GNUNET_PQ_query_param_end
-  };
-  struct GNUNET_PQ_ResultSpec rs[] = {
-    GNUNET_PQ_result_spec_auto_from_type ("wire_source_h_payto",
-                                          h_payto),
-    GNUNET_PQ_result_spec_end
-  };
+  size_t count = fulfillment->details_count;
+  struct GNUNET_HashCode hcs[count];
 
-  return GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
-                                                   
"get_h_wire_source_of_reserve",
+  /* Create the sorted policy_hash_codes */
+  {
+    size_t idx[count];
+    for (size_t i = 0; i < count; i++)
+      idx[i] = i;
+
+    /* Sort the indices according to the hash codes of the corresponding
+     * details. */
+    qsort_r (idx,
+             count,
+             sizeof(size_t),
+             hash_code_cmp,
+             fulfillment->details);
+
+    /* Finally, concatenate all hash_codes in sorted order */
+    for (size_t i = 0; i < count; i++)
+      hcs[i] = fulfillment->details[idx[i]].hash_code;
+  }
+
+
+  /* Now, add the proof to the policy_fulfillments table, retrieve the
+   * record_id */
+  {
+    struct GNUNET_PQ_QueryParam params[] = {
+      GNUNET_PQ_query_param_timestamp (&fulfillment->timestamp),
+      TALER_PQ_query_param_json (fulfillment->proof),
+      GNUNET_PQ_query_param_auto_from_type (&fulfillment->h_proof),
+      GNUNET_PQ_query_param_fixed_size (hcs,
+                                        count * sizeof(struct 
GNUNET_HashCode)),
+      GNUNET_PQ_query_param_end
+    };
+    struct GNUNET_PQ_ResultSpec rs[] = {
+      GNUNET_PQ_result_spec_uint64 ("fulfillment_id",
+                                    &fulfillment->fulfillment_id),
+      GNUNET_PQ_result_spec_end
+    };
+
+    qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
+                                                   
"insert_proof_into_policy_fulfillments",
                                                    params,
                                                    rs);
+    if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != qs)
+      return qs;
+  }
+
+  /* Now, set the states of each entry corresponding to the hash_codes in
+   * policy_details accordingly */
+  for (size_t i = 0; i < count; i++)
+  {
+    struct TALER_PolicyDetails *pos = &fulfillment->details[i];
+    {
+      struct GNUNET_PQ_QueryParam params[] = {
+        GNUNET_PQ_query_param_auto_from_type (&pos->hash_code),
+        GNUNET_PQ_query_param_timestamp (&pos->deadline),
+        TALER_PQ_query_param_amount (&pos->commitment),
+        TALER_PQ_query_param_amount (&pos->accumulated_total),
+        TALER_PQ_query_param_amount (&pos->policy_fee),
+        TALER_PQ_query_param_amount (&pos->transferable_amount),
+        GNUNET_PQ_query_param_auto_from_type (&pos->fulfillment_state),
+        GNUNET_PQ_query_param_end
+      };
+
+      qs = GNUNET_PQ_eval_prepared_non_select (pg->conn,
+                                               "update_policy_details",
+                                               params);
+      if (qs < 0)
+        return qs;
+    }
+  }
+
+  return qs;
 }
 
 
 /**
- * Extract next KYC alert.  Deletes the alert.
+ * Get the balance of the specified reserve.
  *
- * @param cls the @e cls of this struct with the plugin-specific state
- * @param trigger_type which type of alert to drain
- * @param[out] h_payto set to hash of payto-URI where KYC status changed
+ * @param cls the `struct PostgresClosure` with the plugin-specific state
+ * @param reserve_pub public key of the reserve
+ * @param[out] balance set to the reserve balance
  * @return transaction status
  */
 static enum GNUNET_DB_QueryStatus
-postgres_drain_kyc_alert (void *cls,
-                          uint32_t trigger_type,
-                          struct TALER_PaytoHashP *h_payto)
+postgres_get_reserve_balance (void *cls,
+                              const struct TALER_ReservePublicKeyP 
*reserve_pub,
+                              struct TALER_Amount *balance)
 {
   struct PostgresClosure *pg = cls;
   struct GNUNET_PQ_QueryParam params[] = {
-    GNUNET_PQ_query_param_uint32 (&trigger_type),
+    GNUNET_PQ_query_param_auto_from_type (reserve_pub),
     GNUNET_PQ_query_param_end
   };
   struct GNUNET_PQ_ResultSpec rs[] = {
-    GNUNET_PQ_result_spec_auto_from_type ("h_payto",
-                                          h_payto),
+    TALER_PQ_RESULT_SPEC_AMOUNT ("current_balance",
+                                 balance),
     GNUNET_PQ_result_spec_end
   };
 
   return GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
-                                                   "drain_kyc_alert",
+                                                   "get_reserve_balance",
                                                    params,
                                                    rs);
 }
 
 
 /**
- * Updates a reserve with the data from the given reserve structure.
+ * Check if we have the specified deposit already in the database.
  *
  * @param cls the `struct PostgresClosure` with the plugin-specific state
- * @param reserve the reserve structure whose data will be used to update the
- *          corresponding record in the database.
- * @return transaction status
+ * @param h_contract_terms contract to check for
+ * @param h_wire wire hash to check for
+ * @param coin_pub public key of the coin to check for
+ * @param merchant merchant public key to check for
+ * @param refund_deadline expected refund deadline
+ * @param[out] deposit_fee set to the deposit fee the exchange charged
+ * @param[out] exchange_timestamp set to the time when the exchange received 
the deposit
+ * @return 1 if we know this operation,
+ *         0 if this exact deposit is unknown to us,
+ *         otherwise transaction error status
  */
 static enum GNUNET_DB_QueryStatus
-reserves_update (void *cls,
-                 const struct TALER_EXCHANGEDB_Reserve *reserve)
+postgres_have_deposit2 (
+  void *cls,
+  const struct TALER_PrivateContractHashP *h_contract_terms,
+  const struct TALER_MerchantWireHashP *h_wire,
+  const struct TALER_CoinSpendPublicKeyP *coin_pub,
+  const struct TALER_MerchantPublicKeyP *merchant,
+  struct GNUNET_TIME_Timestamp refund_deadline,
+  struct TALER_Amount *deposit_fee,
+  struct GNUNET_TIME_Timestamp *exchange_timestamp)
 {
   struct PostgresClosure *pg = cls;
   struct GNUNET_PQ_QueryParam params[] = {
-    GNUNET_PQ_query_param_timestamp (&reserve->expiry),
-    GNUNET_PQ_query_param_timestamp (&reserve->gc),
-    TALER_PQ_query_param_amount (&reserve->balance),
-    GNUNET_PQ_query_param_auto_from_type (&reserve->pub),
+    GNUNET_PQ_query_param_auto_from_type (coin_pub),
+    GNUNET_PQ_query_param_auto_from_type (h_contract_terms),
+    GNUNET_PQ_query_param_auto_from_type (merchant),
     GNUNET_PQ_query_param_end
   };
+  struct TALER_EXCHANGEDB_Deposit deposit2;
+  struct GNUNET_PQ_ResultSpec rs[] = {
+    TALER_PQ_RESULT_SPEC_AMOUNT ("amount_with_fee",
+                                 &deposit2.amount_with_fee),
+    GNUNET_PQ_result_spec_timestamp ("wallet_timestamp",
+                                     &deposit2.timestamp),
+    GNUNET_PQ_result_spec_timestamp ("exchange_timestamp",
+                                     exchange_timestamp),
+    GNUNET_PQ_result_spec_timestamp ("refund_deadline",
+                                     &deposit2.refund_deadline),
+    GNUNET_PQ_result_spec_timestamp ("wire_deadline",
+                                     &deposit2.wire_deadline),
+    TALER_PQ_RESULT_SPEC_AMOUNT ("fee_deposit",
+                                 deposit_fee),
+    GNUNET_PQ_result_spec_auto_from_type ("wire_salt",
+                                          &deposit2.wire_salt),
+    GNUNET_PQ_result_spec_string ("receiver_wire_account",
+                                  &deposit2.receiver_wire_account),
+    GNUNET_PQ_result_spec_end
+  };
+  enum GNUNET_DB_QueryStatus qs;
+  struct TALER_MerchantWireHashP h_wire2;
 
-  return GNUNET_PQ_eval_prepared_non_select (pg->conn,
-                                             "reserve_update",
-                                             params);
-}
-
-
-/**
- * Setup new wire target for @a payto_uri.
- *
- * @param pg the plugin-specific state
- * @param payto_uri the payto URI to check
- * @param[out] h_payto set to the hash of @a payto_uri
- * @return transaction status
- */
-static enum GNUNET_DB_QueryStatus
-setup_wire_target (
-  struct PostgresClosure *pg,
-  const char *payto_uri,
-  struct TALER_PaytoHashP *h_payto)
-{
-  struct GNUNET_PQ_QueryParam iparams[] = {
-    GNUNET_PQ_query_param_auto_from_type (h_payto),
-    GNUNET_PQ_query_param_string (payto_uri),
-    GNUNET_PQ_query_param_end
-  };
-
-  TALER_payto_hash (payto_uri,
-                    h_payto);
-  return GNUNET_PQ_eval_prepared_non_select (pg->conn,
-                                             "insert_kyc_status",
-                                             iparams);
-}
-
-
-/**
- * Generate event notification for the reserve
- * change.
- *
- * @param pg plugin state
- * @param reserve_pub reserve to notfiy on
- */
-static void
-notify_on_reserve (struct PostgresClosure *pg,
-                   const struct TALER_ReservePublicKeyP *reserve_pub)
-{
-  struct TALER_ReserveEventP rep = {
-    .header.size = htons (sizeof (rep)),
-    .header.type = htons (TALER_DBEVENT_EXCHANGE_RESERVE_INCOMING),
-    .reserve_pub = *reserve_pub
-  };
-
-  GNUNET_log (GNUNET_ERROR_TYPE_INFO,
-              "Notifying on reserve!\n");
-  postgres_event_notify (pg,
-                         &rep.header,
-                         NULL,
-                         0);
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Getting deposits for coin %s\n",
+              TALER_B2S (coin_pub));
+  qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
+                                                 "get_deposit",
+                                                 params,
+                                                 rs);
+  if (0 >= qs)
+    return qs;
+  TALER_merchant_wire_signature_hash (deposit2.receiver_wire_account,
+                                      &deposit2.wire_salt,
+                                      &h_wire2);
+  GNUNET_free (deposit2.receiver_wire_account);
+  /* Now we check that the other information in @a deposit
+     also matches, and if not report inconsistencies. */
+  if ( (GNUNET_TIME_timestamp_cmp (refund_deadline,
+                                   !=,
+                                   deposit2.refund_deadline)) ||
+       (0 != GNUNET_memcmp (h_wire,
+                            &h_wire2) ) )
+  {
+    /* Inconsistencies detected! Does not match! */
+    return GNUNET_DB_STATUS_SUCCESS_NO_RESULTS;
+  }
+  return GNUNET_DB_STATUS_SUCCESS_ONE_RESULT;
 }
 
 
 /**
- * Insert an incoming transaction into reserves.  New reserves are also
- * created through this function. Started within the scope of an ongoing
- * transaction.
+ * Aggregate all matching deposits for @a h_payto and
+ * @a merchant_pub, returning the total amounts.
  *
- * @param cls the `struct PostgresClosure` with the plugin-specific state
- * @param reserve_pub public key of the reserve
- * @param balance the amount that has to be added to the reserve
- * @param execution_time when was the amount added
- * @param sender_account_details account information for the sender 
(payto://-URL)
- * @param exchange_account_section name of the section in the configuration 
for the exchange's
- *                       account into which the deposit was made
- * @param wire_ref unique reference identifying the wire transfer
- * @return transaction status code
+ * @param cls the @e cls of this struct with the plugin-specific state
+ * @param h_payto destination of the wire transfer
+ * @param merchant_pub public key of the merchant
+ * @param wtid wire transfer ID to set for the aggregate
+ * @param[out] total set to the sum of the total deposits minus applicable 
deposit fees and refunds
+ * @return transaction status
  */
 static enum GNUNET_DB_QueryStatus
-postgres_reserves_in_insert (void *cls,
-                             const struct TALER_ReservePublicKeyP *reserve_pub,
-                             const struct TALER_Amount *balance,
-                             struct GNUNET_TIME_Timestamp execution_time,
-                             const char *sender_account_details,
-                             const char *exchange_account_section,
-                             uint64_t wire_ref)
+postgres_aggregate (
+  void *cls,
+  const struct TALER_PaytoHashP *h_payto,
+  const struct TALER_MerchantPublicKeyP *merchant_pub,
+  const struct TALER_WireTransferIdentifierRawP *wtid,
+  struct TALER_Amount *total)
 {
   struct PostgresClosure *pg = cls;
-  enum GNUNET_DB_QueryStatus qs1;
-  struct TALER_EXCHANGEDB_Reserve reserve;
-  struct GNUNET_TIME_Timestamp expiry;
-  struct GNUNET_TIME_Timestamp gc;
-  uint64_t reserve_uuid;
-
-  reserve.pub = *reserve_pub;
-  expiry = GNUNET_TIME_absolute_to_timestamp (
-    GNUNET_TIME_absolute_add (execution_time.abs_time,
-                              pg->idle_reserve_expiration_time));
-  gc = GNUNET_TIME_absolute_to_timestamp (
-    GNUNET_TIME_absolute_add (GNUNET_TIME_absolute_get (),
-                              pg->legal_reserve_expiration_time));
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "Creating reserve %s with expiration in %s\n",
-              TALER_B2S (reserve_pub),
-              GNUNET_STRINGS_relative_time_to_string (
-                pg->idle_reserve_expiration_time,
-                GNUNET_NO));
-  /* Optimistically assume this is a new reserve, create balance for the first
-     time; we do this before adding the actual transaction to "reserves_in",
-     as for a new reserve it can't be a duplicate 'add' operation, and as
-     the 'add' operation needs the reserve entry as a foreign key. */
-  {
-    struct GNUNET_PQ_QueryParam params[] = {
-      GNUNET_PQ_query_param_auto_from_type (reserve_pub),
-      TALER_PQ_query_param_amount (balance),
-      GNUNET_PQ_query_param_timestamp (&expiry),
-      GNUNET_PQ_query_param_timestamp (&gc),
-      GNUNET_PQ_query_param_end
-    };
-    struct GNUNET_PQ_ResultSpec rs[] = {
-      GNUNET_PQ_result_spec_uint64 ("reserve_uuid",
-                                    &reserve_uuid),
-      GNUNET_PQ_result_spec_end
-    };
-
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "Reserve does not exist; creating a new one\n");
-    /* Note: query uses 'on conflict do nothing' */
-    qs1 = GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
-                                                    "reserve_create",
-                                                    params,
-                                                    rs);
-    if (qs1 < 0)
-      return qs1;
-  }
-
-  /* Create new incoming transaction, "ON CONFLICT DO NOTHING"
-     is again used to guard against duplicates. */
-  {
-    enum GNUNET_DB_QueryStatus qs2;
-    enum GNUNET_DB_QueryStatus qs3;
-    struct TALER_PaytoHashP h_payto;
-
-    qs3 = setup_wire_target (pg,
-                             sender_account_details,
-                             &h_payto);
-    if (qs3 < 0)
-      return qs3;
-    /* We do not have the UUID, so insert by public key */
-    struct GNUNET_PQ_QueryParam params[] = {
-      GNUNET_PQ_query_param_auto_from_type (&reserve.pub),
-      GNUNET_PQ_query_param_uint64 (&wire_ref),
-      TALER_PQ_query_param_amount (balance),
-      GNUNET_PQ_query_param_string (exchange_account_section),
-      GNUNET_PQ_query_param_auto_from_type (&h_payto),
-      GNUNET_PQ_query_param_timestamp (&execution_time),
-      GNUNET_PQ_query_param_end
-    };
-
-    qs2 = GNUNET_PQ_eval_prepared_non_select (pg->conn,
-                                              "reserves_in_add_transaction",
-                                              params);
-    /* qs2 could be 0 as statement used 'ON CONFLICT DO NOTHING' */
-    if (0 >= qs2)
-    {
-      if ( (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS == qs2) &&
-           (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS != qs1) )
-      {
-        /* Conflict for the transaction, but the reserve was
-           just now created, that should be impossible. */
-        GNUNET_break (0); /* should be impossible: reserve was fresh,
-                             but transaction already known */
-        return GNUNET_DB_STATUS_HARD_ERROR;
-      }
-      /* Transaction was already known or error. We are finished. */
-      return qs2;
-    }
-  }
-  if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT == qs1)
-  {
-    /* New reserve, we are finished */
-    notify_on_reserve (pg,
-                       reserve_pub);
-    return GNUNET_DB_STATUS_SUCCESS_ONE_RESULT;
-  }
-
-  /* we were wrong with our optimistic assumption:
-     reserve did already exist, need to do an update instead */
-  {
-    /* We need to move away from 'read committed' to serializable.
-       Also, we know that it should be safe to commit at this point.
-       (We are only run in a larger transaction for performance.) */
-    enum GNUNET_DB_QueryStatus cs;
-
-    cs = TEH_PG_commit (pg);
-    if (cs < 0)
-      return cs;
-    if (GNUNET_OK !=
-        TEH_PG_start (pg,
-                      "reserve-update-serializable"))
-    {
-      GNUNET_break (0);
-      return GNUNET_DB_STATUS_HARD_ERROR;
-    }
-  }
-  {
-    enum GNUNET_DB_QueryStatus reserve_exists;
-
-    reserve_exists = postgres_reserves_get (pg,
-                                            &reserve);
-    switch (reserve_exists)
-    {
-    case GNUNET_DB_STATUS_HARD_ERROR:
-      GNUNET_break (0);
-      return reserve_exists;
-    case GNUNET_DB_STATUS_SOFT_ERROR:
-      return reserve_exists;
-    case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS:
-      /* First we got a conflict, but then we cannot select? Very strange. */
-      GNUNET_break (0);
-      return GNUNET_DB_STATUS_SOFT_ERROR;
-    case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT:
-      /* continued below */
-      break;
-    }
-  }
+  struct GNUNET_TIME_Absolute now = {0};
+  struct GNUNET_PQ_QueryParam params[] = {
+    GNUNET_PQ_query_param_absolute_time (&now),
+    GNUNET_PQ_query_param_auto_from_type (merchant_pub),
+    GNUNET_PQ_query_param_auto_from_type (h_payto),
+    GNUNET_PQ_query_param_auto_from_type (wtid),
+    GNUNET_PQ_query_param_end
+  };
+  uint64_t sum_deposit_value;
+  uint64_t sum_deposit_frac;
+  uint64_t sum_refund_value;
+  uint64_t sum_refund_frac;
+  uint64_t sum_fee_value;
+  uint64_t sum_fee_frac;
+  struct GNUNET_PQ_ResultSpec rs[] = {
+    GNUNET_PQ_result_spec_uint64 ("sum_deposit_value",
+                                  &sum_deposit_value),
+    GNUNET_PQ_result_spec_uint64 ("sum_deposit_fraction",
+                                  &sum_deposit_frac),
+    GNUNET_PQ_result_spec_uint64 ("sum_refund_value",
+                                  &sum_refund_value),
+    GNUNET_PQ_result_spec_uint64 ("sum_refund_fraction",
+                                  &sum_refund_frac),
+    GNUNET_PQ_result_spec_uint64 ("sum_fee_value",
+                                  &sum_fee_value),
+    GNUNET_PQ_result_spec_uint64 ("sum_fee_fraction",
+                                  &sum_fee_frac),
+    GNUNET_PQ_result_spec_end
+  };
+  enum GNUNET_DB_QueryStatus qs;
+  struct TALER_Amount sum_deposit;
+  struct TALER_Amount sum_refund;
+  struct TALER_Amount sum_fee;
+  struct TALER_Amount delta;
 
+  now = GNUNET_TIME_absolute_round_down (GNUNET_TIME_absolute_get (),
+                                         pg->aggregator_shift);
+  qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
+                                                 "aggregate",
+                                                 params,
+                                                 rs);
+  if (qs < 0)
   {
-    struct TALER_EXCHANGEDB_Reserve updated_reserve;
-    enum GNUNET_DB_QueryStatus qs3;
-
-    /* If the reserve already existed, we need to still update the
-       balance; we do this after checking for duplication, as
-       otherwise we might have to actually pay the cost to roll this
-       back for duplicate transactions; like this, we should virtually
-       never actually have to rollback anything. */
-    updated_reserve.pub = reserve.pub;
-    if (0 >
-        TALER_amount_add (&updated_reserve.balance,
-                          &reserve.balance,
-                          balance))
-    {
-      /* currency overflow or incompatible currency */
-      GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                  "Attempt to deposit incompatible amount into reserve\n");
-      return GNUNET_DB_STATUS_HARD_ERROR;
-    }
-    updated_reserve.expiry = GNUNET_TIME_timestamp_max (expiry,
-                                                        reserve.expiry);
-    updated_reserve.gc = GNUNET_TIME_timestamp_max (gc,
-                                                    reserve.gc);
-    qs3 = reserves_update (pg,
-                           &updated_reserve);
-    switch (qs3)
-    {
-    case GNUNET_DB_STATUS_HARD_ERROR:
-      GNUNET_break (0);
-      return qs3;
-    case GNUNET_DB_STATUS_SOFT_ERROR:
-      return qs3;
-    case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS:
-      /* How can the UPDATE not work here? Very strange. */
-      GNUNET_break (0);
-      return GNUNET_DB_STATUS_HARD_ERROR;
-    case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT:
-      /* continued below */
-      break;
-    }
+    GNUNET_break (GNUNET_DB_STATUS_SOFT_ERROR == qs);
+    return qs;
   }
-  notify_on_reserve (pg,
-                     reserve_pub);
-  /* Go back to original transaction mode */
+  if (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS == qs)
   {
-    enum GNUNET_DB_QueryStatus cs;
-
-    cs = TEH_PG_commit (pg);
-    if (cs < 0)
-      return cs;
-    if (GNUNET_OK !=
-        TEH_PG_start_read_committed (pg, "reserve-insert-continued"))
-    {
-      GNUNET_break (0);
-      return GNUNET_DB_STATUS_HARD_ERROR;
-    }
+    GNUNET_assert (GNUNET_OK ==
+                   TALER_amount_set_zero (pg->currency,
+                                          total));
+    return qs;
   }
-  return GNUNET_DB_STATUS_SUCCESS_ONE_RESULT;
+  GNUNET_assert (GNUNET_OK ==
+                 TALER_amount_set_zero (pg->currency,
+                                        &sum_deposit));
+  GNUNET_assert (GNUNET_OK ==
+                 TALER_amount_set_zero (pg->currency,
+                                        &sum_refund));
+  GNUNET_assert (GNUNET_OK ==
+                 TALER_amount_set_zero (pg->currency,
+                                        &sum_fee));
+  sum_deposit.value    = sum_deposit_frac / TALER_AMOUNT_FRAC_BASE
+                         + sum_deposit_value;
+  sum_deposit.fraction = sum_deposit_frac % TALER_AMOUNT_FRAC_BASE;
+  sum_refund.value     = sum_refund_frac  / TALER_AMOUNT_FRAC_BASE
+                         + sum_refund_value;
+  sum_refund.fraction  = sum_refund_frac  % TALER_AMOUNT_FRAC_BASE;
+  sum_fee.value        = sum_fee_frac     / TALER_AMOUNT_FRAC_BASE
+                         + sum_fee_value;
+  sum_fee.fraction     = sum_fee_frac     % TALER_AMOUNT_FRAC_BASE; \
+  GNUNET_assert (0 <=
+                 TALER_amount_subtract (&delta,
+                                        &sum_deposit,
+                                        &sum_refund));
+  GNUNET_assert (0 <=
+                 TALER_amount_subtract (total,
+                                        &delta,
+                                        &sum_fee));
+  return qs;
 }
 
 
 /**
- * Locate the response for a /reserve/withdraw request under the
- * key of the hash of the blinded message.
+ * Create a new entry in the transient aggregation table.
  *
- * @param cls the `struct PostgresClosure` with the plugin-specific state
- * @param bch hash that uniquely identifies the withdraw operation
- * @param collectable corresponding collectable coin (blind signature)
- *                    if a coin is found
- * @return statement execution status
+ * @param cls the @e cls of this struct with the plugin-specific state
+ * @param h_payto destination of the wire transfer
+ * @param exchange_account_section exchange account to use
+ * @param merchant_pub public key of the merchant receiving the transfer
+ * @param wtid the raw wire transfer identifier to be used
+ * @param kyc_requirement_row row in legitimization_requirements that need to 
be satisfied to continue, or 0 for none
+ * @param total amount to be wired in the future
+ * @return transaction status
  */
 static enum GNUNET_DB_QueryStatus
-postgres_get_withdraw_info (
+postgres_create_aggregation_transient (
   void *cls,
-  const struct TALER_BlindedCoinHashP *bch,
-  struct TALER_EXCHANGEDB_CollectableBlindcoin *collectable)
+  const struct TALER_PaytoHashP *h_payto,
+  const char *exchange_account_section,
+  const struct TALER_MerchantPublicKeyP *merchant_pub,
+  const struct TALER_WireTransferIdentifierRawP *wtid,
+  uint64_t kyc_requirement_row,
+  const struct TALER_Amount *total)
 {
   struct PostgresClosure *pg = cls;
   struct GNUNET_PQ_QueryParam params[] = {
-    GNUNET_PQ_query_param_auto_from_type (bch),
+    TALER_PQ_query_param_amount (total),
+    GNUNET_PQ_query_param_auto_from_type (merchant_pub),
+    GNUNET_PQ_query_param_auto_from_type (h_payto),
+    GNUNET_PQ_query_param_uint64 (&kyc_requirement_row),
+    GNUNET_PQ_query_param_string (exchange_account_section),
+    GNUNET_PQ_query_param_auto_from_type (wtid),
     GNUNET_PQ_query_param_end
   };
-  struct GNUNET_PQ_ResultSpec rs[] = {
-    GNUNET_PQ_result_spec_auto_from_type ("denom_pub_hash",
-                                          &collectable->denom_pub_hash),
-    TALER_PQ_result_spec_blinded_denom_sig ("denom_sig",
-                                            &collectable->sig),
-    GNUNET_PQ_result_spec_auto_from_type ("reserve_sig",
-                                          &collectable->reserve_sig),
-    GNUNET_PQ_result_spec_auto_from_type ("reserve_pub",
-                                          &collectable->reserve_pub),
-    GNUNET_PQ_result_spec_auto_from_type ("h_blind_ev",
-                                          &collectable->h_coin_envelope),
-    TALER_PQ_RESULT_SPEC_AMOUNT ("amount_with_fee",
-                                 &collectable->amount_with_fee),
-    TALER_PQ_RESULT_SPEC_AMOUNT ("fee_withdraw",
-                                 &collectable->withdraw_fee),
-    GNUNET_PQ_result_spec_end
-  };
 
-  return GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
-                                                   "get_withdraw_info",
-                                                   params,
-                                                   rs);
+  return GNUNET_PQ_eval_prepared_non_select (pg->conn,
+                                             "create_aggregation_transient",
+                                             params);
 }
 
 
 /**
- * Perform reserve update as part of a batch withdraw operation, checking
- * for sufficient balance. Persisting the withdrawal details is done
- * separately!
+ * Find existing entry in the transient aggregation table.
  *
- * @param cls the `struct PostgresClosure` with the plugin-specific state
- * @param now current time (rounded)
- * @param reserve_pub public key of the reserve to debit
- * @param amount total amount to withdraw
- * @param[out] found set to true if the reserve was found
- * @param[out] balance_ok set to true if the balance was sufficient
- * @param[out] ruuid set to the reserve's UUID (reserves table row)
- * @return query execution status
+ * @param cls the @e cls of this struct with the plugin-specific state
+ * @param h_payto destination of the wire transfer
+ * @param merchant_pub public key of the merchant receiving the transfer
+ * @param exchange_account_section exchange account to use
+ * @param[out] wtid set to the raw wire transfer identifier to be used
+ * @param[out] total existing amount to be wired in the future
+ * @return transaction status
  */
 static enum GNUNET_DB_QueryStatus
-postgres_do_batch_withdraw (
+postgres_select_aggregation_transient (
   void *cls,
-  struct GNUNET_TIME_Timestamp now,
-  const struct TALER_ReservePublicKeyP *reserve_pub,
-  const struct TALER_Amount *amount,
-  bool *found,
-  bool *balance_ok,
-  uint64_t *ruuid)
+  const struct TALER_PaytoHashP *h_payto,
+  const struct TALER_MerchantPublicKeyP *merchant_pub,
+  const char *exchange_account_section,
+  struct TALER_WireTransferIdentifierRawP *wtid,
+  struct TALER_Amount *total)
 {
   struct PostgresClosure *pg = cls;
-  struct GNUNET_TIME_Timestamp gc;
   struct GNUNET_PQ_QueryParam params[] = {
-    TALER_PQ_query_param_amount (amount),
-    GNUNET_PQ_query_param_auto_from_type (reserve_pub),
-    GNUNET_PQ_query_param_timestamp (&now),
-    GNUNET_PQ_query_param_timestamp (&gc),
+    GNUNET_PQ_query_param_auto_from_type (h_payto),
+    GNUNET_PQ_query_param_auto_from_type (merchant_pub),
+    GNUNET_PQ_query_param_string (exchange_account_section),
     GNUNET_PQ_query_param_end
   };
   struct GNUNET_PQ_ResultSpec rs[] = {
-    GNUNET_PQ_result_spec_bool ("reserve_found",
-                                found),
-    GNUNET_PQ_result_spec_bool ("balance_ok",
-                                balance_ok),
-    GNUNET_PQ_result_spec_uint64 ("ruuid",
-                                  ruuid),
+    TALER_PQ_RESULT_SPEC_AMOUNT ("amount",
+                                 total),
+    GNUNET_PQ_result_spec_auto_from_type ("wtid_raw",
+                                          wtid),
     GNUNET_PQ_result_spec_end
   };
 
-  gc = GNUNET_TIME_absolute_to_timestamp (
-    GNUNET_TIME_absolute_add (now.abs_time,
-                              pg->legal_reserve_expiration_time));
   return GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
-                                                   "call_batch_withdraw",
+                                                   
"select_aggregation_transient",
                                                    params,
                                                    rs);
 }
 
 
 /**
- * Compute the shard number of a given @a merchant_pub.
+ * Closure for #get_refunds_cb().
+ */
+struct FindAggregationTransientContext
+{
+  /**
+   * Function to call on each result.
+   */
+  TALER_EXCHANGEDB_TransientAggregationCallback cb;
+
+  /**
+   * Closure for @a cb.
+   */
+  void *cb_cls;
+
+  /**
+   * Plugin context.
+   */
+  struct PostgresClosure *pg;
+
+  /**
+   * Set to #GNUNET_SYSERR on error.
+   */
+  enum GNUNET_GenericReturnValue status;
+};
+
+
+/**
+ * Function to be called with the results of a SELECT statement
+ * that has returned @a num_results results.
  *
- * @param merchant_pub merchant public key to compute shard for
- * @return shard number
+ * @param cls closure of type `struct SelectRefundContext *`
+ * @param result the postgres result
+ * @param num_results the number of results in @a result
  */
-static uint64_t
-compute_shard (const struct TALER_MerchantPublicKeyP *merchant_pub)
+static void
+get_transients_cb (void *cls,
+                   PGresult *result,
+                   unsigned int num_results)
 {
-  uint32_t res;
+  struct FindAggregationTransientContext *srctx = cls;
+  struct PostgresClosure *pg = srctx->pg;
 
-  GNUNET_assert (GNUNET_YES ==
-                 GNUNET_CRYPTO_kdf (&res,
-                                    sizeof (res),
-                                    merchant_pub,
-                                    sizeof (*merchant_pub),
-                                    "VOID",
-                                    4,
-                                    NULL, 0));
-  /* interpret hash result as NBO for platform independence,
-     convert to HBO and map to [0..2^31-1] range */
-  res = ntohl (res);
-  if (res > INT32_MAX)
-    res += INT32_MIN;
-  GNUNET_assert (res <= INT32_MAX);
-  return (uint64_t) res;
+  for (unsigned int i = 0; i<num_results; i++)
+  {
+    struct TALER_Amount amount;
+    char *payto_uri;
+    struct TALER_WireTransferIdentifierRawP wtid;
+    struct TALER_MerchantPublicKeyP merchant_pub;
+    struct GNUNET_PQ_ResultSpec rs[] = {
+      GNUNET_PQ_result_spec_auto_from_type ("merchant_pub",
+                                            &merchant_pub),
+      GNUNET_PQ_result_spec_auto_from_type ("wtid_raw",
+                                            &wtid),
+      GNUNET_PQ_result_spec_string ("payto_uri",
+                                    &payto_uri),
+      TALER_PQ_RESULT_SPEC_AMOUNT ("amount",
+                                   &amount),
+      GNUNET_PQ_result_spec_end
+    };
+    bool cont;
+
+    if (GNUNET_OK !=
+        GNUNET_PQ_extract_result (result,
+                                  rs,
+                                  i))
+    {
+      GNUNET_break (0);
+      srctx->status = GNUNET_SYSERR;
+      return;
+    }
+    cont = srctx->cb (srctx->cb_cls,
+                      payto_uri,
+                      &wtid,
+                      &merchant_pub,
+                      &amount);
+    GNUNET_free (payto_uri);
+    if (! cont)
+      break;
+  }
 }
 
 
 /**
- * Perform deposit operation, checking for sufficient balance
- * of the coin and possibly persisting the deposit details.
+ * Find existing entry in the transient aggregation table.
  *
- * @param cls the `struct PostgresClosure` with the plugin-specific state
- * @param deposit deposit operation details
- * @param known_coin_id row of the coin in the known_coins table
- * @param h_payto hash of the merchant's bank account details
- * @param policy_details_serial_id pointer to the ID of the entry in 
policy_details, maybe NULL
- * @param[in,out] exchange_timestamp time to use for the deposit (possibly 
updated)
- * @param[out] balance_ok set to true if the balance was sufficient
- * @param[out] in_conflict set to true if the deposit conflicted
- * @return query execution status
+ * @param cls the @e cls of this struct with the plugin-specific state
+ * @param h_payto destination of the wire transfer
+ * @param cb function to call on each matching entry
+ * @param cb_cls closure for @a cb
+ * @return transaction status
  */
 static enum GNUNET_DB_QueryStatus
-postgres_do_deposit (
+postgres_find_aggregation_transient (
   void *cls,
-  const struct TALER_EXCHANGEDB_Deposit *deposit,
-  uint64_t known_coin_id,
   const struct TALER_PaytoHashP *h_payto,
-  uint64_t *policy_details_serial_id,
-  struct GNUNET_TIME_Timestamp *exchange_timestamp,
-  bool *balance_ok,
-  bool *in_conflict)
+  TALER_EXCHANGEDB_TransientAggregationCallback cb,
+  void *cb_cls)
 {
   struct PostgresClosure *pg = cls;
-  uint64_t deposit_shard = compute_shard (&deposit->merchant_pub);
+  enum GNUNET_DB_QueryStatus qs;
   struct GNUNET_PQ_QueryParam params[] = {
-    TALER_PQ_query_param_amount (&deposit->amount_with_fee),
-    GNUNET_PQ_query_param_auto_from_type (&deposit->h_contract_terms),
-    GNUNET_PQ_query_param_auto_from_type (&deposit->wire_salt),
-    GNUNET_PQ_query_param_timestamp (&deposit->timestamp),
-    GNUNET_PQ_query_param_timestamp (exchange_timestamp),
-    GNUNET_PQ_query_param_timestamp (&deposit->refund_deadline),
-    GNUNET_PQ_query_param_timestamp (&deposit->wire_deadline),
-    GNUNET_PQ_query_param_auto_from_type (&deposit->merchant_pub),
-    GNUNET_PQ_query_param_string (deposit->receiver_wire_account),
     GNUNET_PQ_query_param_auto_from_type (h_payto),
-    GNUNET_PQ_query_param_uint64 (&known_coin_id),
-    GNUNET_PQ_query_param_auto_from_type (&deposit->coin.coin_pub),
-    GNUNET_PQ_query_param_auto_from_type (&deposit->csig),
-    GNUNET_PQ_query_param_uint64 (&deposit_shard),
-    GNUNET_PQ_query_param_bool (deposit->has_policy),
-    (NULL == policy_details_serial_id)
-    ? GNUNET_PQ_query_param_null ()
-    : GNUNET_PQ_query_param_uint64 (policy_details_serial_id),
     GNUNET_PQ_query_param_end
   };
-  struct GNUNET_PQ_ResultSpec rs[] = {
-    GNUNET_PQ_result_spec_bool ("balance_ok",
-                                balance_ok),
-    GNUNET_PQ_result_spec_bool ("conflicted",
-                                in_conflict),
-    GNUNET_PQ_result_spec_timestamp ("exchange_timestamp",
-                                     exchange_timestamp),
-    GNUNET_PQ_result_spec_end
+  struct FindAggregationTransientContext srctx = {
+    .cb = cb,
+    .cb_cls = cb_cls,
+    .pg = pg,
+    .status = GNUNET_OK
   };
 
-  return GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
-                                                   "call_deposit",
-                                                   params,
-                                                   rs);
+  qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn,
+                                             "find_transient_aggregations",
+                                             params,
+                                             &get_transients_cb,
+                                             &srctx);
+  if (GNUNET_SYSERR == srctx.status)
+    return GNUNET_DB_STATUS_HARD_ERROR;
+  return qs;
 }
 
 
-/* Get the details of a policy, referenced by its hash code
+/**
+ * Update existing entry in the transient aggregation table.
+ * @a h_payto is only needed for query performance.
  *
- * @param cls the `struct PostgresClosure` with the plugin-specific state
- * @param hc The hash code under which the details to a particular policy 
should be found
- * @param[out] details The found details
- * @return query execution status
- * */
+ * @param cls the @e cls of this struct with the plugin-specific state
+ * @param h_payto destination of the wire transfer
+ * @param wtid the raw wire transfer identifier to update
+ * @param kyc_requirement_row row in legitimization_requirements that need to 
be satisfied to continue, or 0 for none
+ * @param total new total amount to be wired in the future
+ * @return transaction status
+ */
 static enum GNUNET_DB_QueryStatus
-postgres_get_policy_details (
+postgres_update_aggregation_transient (
   void *cls,
-  const struct GNUNET_HashCode *hc,
-  struct TALER_PolicyDetails *details)
+  const struct TALER_PaytoHashP *h_payto,
+  const struct TALER_WireTransferIdentifierRawP *wtid,
+  uint64_t kyc_requirement_row,
+  const struct TALER_Amount *total)
 {
   struct PostgresClosure *pg = cls;
   struct GNUNET_PQ_QueryParam params[] = {
-    GNUNET_PQ_query_param_auto_from_type (hc),
+    TALER_PQ_query_param_amount (total),
+    GNUNET_PQ_query_param_auto_from_type (h_payto),
+    GNUNET_PQ_query_param_auto_from_type (wtid),
+    GNUNET_PQ_query_param_uint64 (&kyc_requirement_row),
     GNUNET_PQ_query_param_end
   };
-  struct GNUNET_PQ_ResultSpec rs[] = {
-    GNUNET_PQ_result_spec_timestamp ("deadline",
-                                     &details->deadline),
-    TALER_PQ_RESULT_SPEC_AMOUNT ("commitment",
-                                 &details->commitment),
-    TALER_PQ_RESULT_SPEC_AMOUNT ("accumulated_total",
-                                 &details->accumulated_total),
-    TALER_PQ_RESULT_SPEC_AMOUNT ("policy_fee",
-                                 &details->policy_fee),
-    TALER_PQ_RESULT_SPEC_AMOUNT ("transferable_amount",
-                                 &details->transferable_amount),
-    GNUNET_PQ_result_spec_auto_from_type ("state",
-                                          &details->fulfillment_state),
-    GNUNET_PQ_result_spec_allow_null (
-      GNUNET_PQ_result_spec_uint64 ("policy_fulfillment_id",
-                                    &details->policy_fulfillment_id),
-      &details->no_policy_fulfillment_id),
-    GNUNET_PQ_result_spec_end
-  };
 
-  return GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
-                                                   "get_policy_details",
-                                                   params,
-                                                   rs);
+  return GNUNET_PQ_eval_prepared_non_select (pg->conn,
+                                             "update_aggregation_transient",
+                                             params);
 }
 
 
-/* Persist the details to a policy in the policy_details table.  If there
- * already exists a policy, update the fields accordingly.
+/**
+ * Obtain information about deposits that are ready to be executed.  Such
+ * deposits must not be marked as "done", the execution time must be
+ * in the past, and the KYC status must be 'ok'.
  *
- * @param details The policy details that should be persisted.  If an entry for
- *        the given details->hash_code exists, the values will be updated.
- * @param[out] policy_details_serial_id The row ID of the policy details
- * @param[out] accumulated_total The total amount accumulated in that policy
- * @param[out] fulfillment_state The state of policy.  If the state was 
Insufficient prior to the call and the provided deposit raises the 
accumulated_total above the commitment, it will be set to Ready.
- * @return query execution status
+ * @param cls the @e cls of this struct with the plugin-specific state
+ * @param start_shard_row minimum shard row to select
+ * @param end_shard_row maximum shard row to select (inclusive)
+ * @param[out] merchant_pub set to the public key of a merchant with a ready 
deposit
+ * @param[out] payto_uri set to the account of the merchant, to be freed by 
caller
+ * @return transaction status code
  */
 static enum GNUNET_DB_QueryStatus
-postgres_persist_policy_details (
-  void *cls,
-  const struct TALER_PolicyDetails *details,
-  uint64_t *policy_details_serial_id,
-  struct TALER_Amount *accumulated_total,
-  enum TALER_PolicyFulfillmentState *fulfillment_state)
+postgres_get_ready_deposit (void *cls,
+                            uint64_t start_shard_row,
+                            uint64_t end_shard_row,
+                            struct TALER_MerchantPublicKeyP *merchant_pub,
+                            char **payto_uri)
 {
   struct PostgresClosure *pg = cls;
+  struct GNUNET_TIME_Absolute now = {0};
   struct GNUNET_PQ_QueryParam params[] = {
-    GNUNET_PQ_query_param_auto_from_type (&details->hash_code),
-    TALER_PQ_query_param_json (details->policy_json),
-    GNUNET_PQ_query_param_timestamp (&details->deadline),
-    TALER_PQ_query_param_amount (&details->commitment),
-    TALER_PQ_query_param_amount (&details->accumulated_total),
-    TALER_PQ_query_param_amount (&details->policy_fee),
-    TALER_PQ_query_param_amount (&details->transferable_amount),
-    GNUNET_PQ_query_param_auto_from_type (&details->fulfillment_state),
-    (details->no_policy_fulfillment_id)
-     ?  GNUNET_PQ_query_param_null ()
-     : GNUNET_PQ_query_param_uint64 (&details->policy_fulfillment_id),
+    GNUNET_PQ_query_param_absolute_time (&now),
+    GNUNET_PQ_query_param_uint64 (&start_shard_row),
+    GNUNET_PQ_query_param_uint64 (&end_shard_row),
     GNUNET_PQ_query_param_end
   };
   struct GNUNET_PQ_ResultSpec rs[] = {
-    GNUNET_PQ_result_spec_uint64 ("policy_details_serial_id",
-                                  policy_details_serial_id),
-    TALER_PQ_RESULT_SPEC_AMOUNT ("accumulated_total",
-                                 accumulated_total),
-    GNUNET_PQ_result_spec_uint32 ("fulfillment_state",
-                                  fulfillment_state),
+    GNUNET_PQ_result_spec_auto_from_type ("merchant_pub",
+                                          merchant_pub),
+    GNUNET_PQ_result_spec_string ("payto_uri",
+                                  payto_uri),
     GNUNET_PQ_result_spec_end
   };
 
+  now = GNUNET_TIME_absolute_round_down (GNUNET_TIME_absolute_get (),
+                                         pg->aggregator_shift);
+  GNUNET_assert (start_shard_row < end_shard_row);
+  GNUNET_assert (end_shard_row <= INT32_MAX);
+  GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+              "Finding ready deposits by deadline %s (%llu)\n",
+              GNUNET_TIME_absolute2s (now),
+              (unsigned long long) now.abs_value_us);
   return GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
-                                                   
"call_insert_or_update_policy_details",
+                                                   "deposits_get_ready",
                                                    params,
                                                    rs);
 }
 
 
 /**
- * Perform melt operation, checking for sufficient balance
- * of the coin and possibly persisting the melt details.
+ * Retrieve the record for a known coin.
  *
- * @param cls the `struct PostgresClosure` with the plugin-specific state
- * @param rms client-contributed input for CS denominations that must be 
checked for idempotency, or NULL for non-CS withdrawals
- * @param[in,out] refresh refresh operation details; the noreveal_index
- *                is set in case the coin was already melted before
- * @param known_coin_id row of the coin in the known_coins table
- * @param[in,out] zombie_required true if the melt must only succeed if the 
coin is a zombie, set to false if the requirement was satisfied
- * @param[out] balance_ok set to true if the balance was sufficient
- * @return query execution status
+ * @param cls the plugin closure
+ * @param coin_pub the public key of the coin to search for
+ * @param coin_info place holder for the returned coin information object
+ * @return transaction status code
  */
 static enum GNUNET_DB_QueryStatus
-postgres_do_melt (
-  void *cls,
-  const struct TALER_RefreshMasterSecretP *rms,
-  struct TALER_EXCHANGEDB_Refresh *refresh,
-  uint64_t known_coin_id,
-  bool *zombie_required,
-  bool *balance_ok)
+postgres_get_known_coin (void *cls,
+                         const struct TALER_CoinSpendPublicKeyP *coin_pub,
+                         struct TALER_CoinPublicInfo *coin_info)
 {
   struct PostgresClosure *pg = cls;
   struct GNUNET_PQ_QueryParam params[] = {
-    NULL == rms
-    ? GNUNET_PQ_query_param_null ()
-    : GNUNET_PQ_query_param_auto_from_type (rms),
-    TALER_PQ_query_param_amount (&refresh->amount_with_fee),
-    GNUNET_PQ_query_param_auto_from_type (&refresh->rc),
-    GNUNET_PQ_query_param_auto_from_type (&refresh->coin.coin_pub),
-    GNUNET_PQ_query_param_auto_from_type (&refresh->coin_sig),
-    GNUNET_PQ_query_param_uint64 (&known_coin_id),
-    GNUNET_PQ_query_param_uint32 (&refresh->noreveal_index),
-    GNUNET_PQ_query_param_bool (*zombie_required),
+    GNUNET_PQ_query_param_auto_from_type (coin_pub),
     GNUNET_PQ_query_param_end
   };
-  bool is_null;
   struct GNUNET_PQ_ResultSpec rs[] = {
-    GNUNET_PQ_result_spec_bool ("balance_ok",
-                                balance_ok),
-    GNUNET_PQ_result_spec_bool ("zombie_required",
-                                zombie_required),
+    GNUNET_PQ_result_spec_auto_from_type ("denom_pub_hash",
+                                          &coin_info->denom_pub_hash),
     GNUNET_PQ_result_spec_allow_null (
-      GNUNET_PQ_result_spec_uint32 ("noreveal_index",
-                                    &refresh->noreveal_index),
-      &is_null),
+      GNUNET_PQ_result_spec_auto_from_type ("age_commitment_hash",
+                                            &coin_info->h_age_commitment),
+      &coin_info->no_age_commitment),
+    TALER_PQ_result_spec_denom_sig ("denom_sig",
+                                    &coin_info->denom_sig),
     GNUNET_PQ_result_spec_end
   };
-  enum GNUNET_DB_QueryStatus qs;
 
-  qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
-                                                 "call_melt",
-                                                 params,
-                                                 rs);
-  if (is_null)
-    refresh->noreveal_index = UINT32_MAX; /* set to very invalid value */
-  return qs;
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Getting known coin data for coin %s\n",
+              TALER_B2S (coin_pub));
+  coin_info->coin_pub = *coin_pub;
+  return GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
+                                                   "get_known_coin",
+                                                   params,
+                                                   rs);
 }
 
 
 /**
- * Perform refund operation, checking for sufficient deposits
- * of the coin and possibly persisting the refund details.
+ * Retrieve the denomination of a known coin.
  *
- * @param cls the `struct PostgresClosure` with the plugin-specific state
- * @param refund refund operation details
- * @param deposit_fee deposit fee applicable for the coin, possibly refunded
- * @param known_coin_id row of the coin in the known_coins table
- * @param[out] not_found set if the deposit was not found
- * @param[out] refund_ok  set if the refund succeeded (below deposit amount)
- * @param[out] gone if the merchant was already paid
- * @param[out] conflict set if the refund ID was re-used
- * @return query execution status
+ * @param cls the plugin closure
+ * @param coin_pub the public key of the coin to search for
+ * @param[out] known_coin_id set to the ID of the coin in the known_coins table
+ * @param[out] denom_hash where to store the hash of the coins denomination
+ * @return transaction status code
  */
 static enum GNUNET_DB_QueryStatus
-postgres_do_refund (
+postgres_get_coin_denomination (
   void *cls,
-  const struct TALER_EXCHANGEDB_Refund *refund,
-  const struct TALER_Amount *deposit_fee,
-  uint64_t known_coin_id,
-  bool *not_found,
-  bool *refund_ok,
-  bool *gone,
-  bool *conflict)
+  const struct TALER_CoinSpendPublicKeyP *coin_pub,
+  uint64_t *known_coin_id,
+  struct TALER_DenominationHashP *denom_hash)
 {
   struct PostgresClosure *pg = cls;
-  uint64_t deposit_shard = compute_shard (&refund->details.merchant_pub);
-  struct TALER_Amount amount_without_fee;
   struct GNUNET_PQ_QueryParam params[] = {
-    TALER_PQ_query_param_amount (&refund->details.refund_amount),
-    TALER_PQ_query_param_amount (&amount_without_fee),
-    TALER_PQ_query_param_amount (deposit_fee),
-    GNUNET_PQ_query_param_auto_from_type (&refund->details.h_contract_terms),
-    GNUNET_PQ_query_param_uint64 (&refund->details.rtransaction_id),
-    GNUNET_PQ_query_param_uint64 (&deposit_shard),
-    GNUNET_PQ_query_param_uint64 (&known_coin_id),
-    GNUNET_PQ_query_param_auto_from_type (&refund->coin.coin_pub),
-    GNUNET_PQ_query_param_auto_from_type (&refund->details.merchant_pub),
-    GNUNET_PQ_query_param_auto_from_type (&refund->details.merchant_sig),
+    GNUNET_PQ_query_param_auto_from_type (coin_pub),
     GNUNET_PQ_query_param_end
   };
   struct GNUNET_PQ_ResultSpec rs[] = {
-    GNUNET_PQ_result_spec_bool ("not_found",
-                                not_found),
-    GNUNET_PQ_result_spec_bool ("refund_ok",
-                                refund_ok),
-    GNUNET_PQ_result_spec_bool ("gone",
-                                gone),
-    GNUNET_PQ_result_spec_bool ("conflict",
-                                conflict),
+    GNUNET_PQ_result_spec_auto_from_type ("denom_pub_hash",
+                                          denom_hash),
+    GNUNET_PQ_result_spec_uint64 ("known_coin_id",
+                                  known_coin_id),
     GNUNET_PQ_result_spec_end
   };
 
-  if (0 >
-      TALER_amount_subtract (&amount_without_fee,
-                             &refund->details.refund_amount,
-                             &refund->details.refund_fee))
-  {
-    GNUNET_break (0);
-    return GNUNET_DB_STATUS_HARD_ERROR;
-  }
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Getting coin denomination of coin %s\n",
+              TALER_B2S (coin_pub));
   return GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
-                                                   "call_refund",
+                                                   "get_coin_denomination",
                                                    params,
                                                    rs);
 }
 
 
 /**
- * Perform recoup operation, checking for sufficient deposits
- * of the coin and possibly persisting the recoup details.
+ * Count the number of known coins by denomination.
  *
- * @param cls the `struct PostgresClosure` with the plugin-specific state
- * @param reserve_pub public key of the reserve to credit
- * @param reserve_out_serial_id row in the reserves_out table justifying the 
recoup
- * @param coin_bks coin blinding key secret to persist
- * @param coin_pub public key of the coin being recouped
- * @param known_coin_id row of the @a coin_pub in the known_coins table
- * @param coin_sig signature of the coin requesting the recoup
- * @param[in,out] recoup_timestamp recoup timestamp, set if recoup existed
- * @param[out] recoup_ok  set if the recoup succeeded (balance ok)
- * @param[out] internal_failure set on internal failures
- * @return query execution status
+ * @param cls database connection plugin state
+ * @param denom_pub_hash denomination to count by
+ * @return number of coins if non-negative, otherwise an `enum 
GNUNET_DB_QueryStatus`
  */
-static enum GNUNET_DB_QueryStatus
-postgres_do_recoup (
-  void *cls,
-  const struct TALER_ReservePublicKeyP *reserve_pub,
-  uint64_t reserve_out_serial_id,
-  const union TALER_DenominationBlindingKeyP *coin_bks,
-  const struct TALER_CoinSpendPublicKeyP *coin_pub,
-  uint64_t known_coin_id,
-  const struct TALER_CoinSpendSignatureP *coin_sig,
-  struct GNUNET_TIME_Timestamp *recoup_timestamp,
-  bool *recoup_ok,
-  bool *internal_failure)
+static long long
+postgres_count_known_coins (void *cls,
+                            const struct
+                            TALER_DenominationHashP *denom_pub_hash)
 {
   struct PostgresClosure *pg = cls;
-  struct GNUNET_TIME_Timestamp reserve_gc
-    = GNUNET_TIME_relative_to_timestamp (pg->legal_reserve_expiration_time);
-  struct GNUNET_TIME_Timestamp reserve_expiration
-    = GNUNET_TIME_relative_to_timestamp (pg->idle_reserve_expiration_time);
+  uint64_t count;
   struct GNUNET_PQ_QueryParam params[] = {
-    GNUNET_PQ_query_param_auto_from_type (reserve_pub),
-    GNUNET_PQ_query_param_uint64 (&reserve_out_serial_id),
-    GNUNET_PQ_query_param_auto_from_type (coin_bks),
-    GNUNET_PQ_query_param_auto_from_type (coin_pub),
-    GNUNET_PQ_query_param_uint64 (&known_coin_id),
-    GNUNET_PQ_query_param_auto_from_type (coin_sig),
-    GNUNET_PQ_query_param_timestamp (&reserve_gc),
-    GNUNET_PQ_query_param_timestamp (&reserve_expiration),
-    GNUNET_PQ_query_param_timestamp (recoup_timestamp),
+    GNUNET_PQ_query_param_auto_from_type (denom_pub_hash),
     GNUNET_PQ_query_param_end
   };
-  bool is_null;
   struct GNUNET_PQ_ResultSpec rs[] = {
-    GNUNET_PQ_result_spec_allow_null (
-      GNUNET_PQ_result_spec_timestamp ("recoup_timestamp",
-                                       recoup_timestamp),
-      &is_null),
-    GNUNET_PQ_result_spec_bool ("recoup_ok",
-                                recoup_ok),
-    GNUNET_PQ_result_spec_bool ("internal_failure",
-                                internal_failure),
+    GNUNET_PQ_result_spec_uint64 ("count",
+                                  &count),
     GNUNET_PQ_result_spec_end
   };
+  enum GNUNET_DB_QueryStatus qs;
 
-  return GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
-                                                   "call_recoup",
-                                                   params,
-                                                   rs);
+  qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
+                                                 "count_known_coins",
+                                                 params,
+                                                 rs);
+  if (0 > qs)
+    return (long long) qs;
+  return (long long) count;
 }
 
 
 /**
- * Perform recoup-refresh operation, checking for sufficient deposits of the
- * coin and possibly persisting the recoup-refresh details.
+ * Make sure the given @a coin is known to the database.
  *
- * @param cls the `struct PostgresClosure` with the plugin-specific state
- * @param old_coin_pub public key of the old coin to credit
- * @param rrc_serial row in the refresh_revealed_coins table justifying the 
recoup-refresh
- * @param coin_bks coin blinding key secret to persist
- * @param coin_pub public key of the coin being recouped
- * @param known_coin_id row of the @a coin_pub in the known_coins table
- * @param coin_sig signature of the coin requesting the recoup
- * @param[in,out] recoup_timestamp recoup timestamp, set if recoup existed
- * @param[out] recoup_ok  set if the recoup-refresh succeeded (balance ok)
- * @param[out] internal_failure set on internal failures
- * @return query execution status
+ * @param cls database connection plugin state
+ * @param coin the coin that must be made known
+ * @param[out] known_coin_id set to the unique row of the coin
+ * @param[out] denom_hash set to the denomination hash of the existing
+ *             coin (for conflict error reporting)
+ * @param[out] h_age_commitment  set to the conflicting age commitment hash on 
conflict
+ * @return database transaction status, non-negative on success
  */
-static enum GNUNET_DB_QueryStatus
-postgres_do_recoup_refresh (
-  void *cls,
-  const struct TALER_CoinSpendPublicKeyP *old_coin_pub,
-  uint64_t rrc_serial,
-  const union TALER_DenominationBlindingKeyP *coin_bks,
-  const struct TALER_CoinSpendPublicKeyP *coin_pub,
-  uint64_t known_coin_id,
-  const struct TALER_CoinSpendSignatureP *coin_sig,
-  struct GNUNET_TIME_Timestamp *recoup_timestamp,
-  bool *recoup_ok,
-  bool *internal_failure)
+static enum TALER_EXCHANGEDB_CoinKnownStatus
+postgres_ensure_coin_known (void *cls,
+                            const struct TALER_CoinPublicInfo *coin,
+                            uint64_t *known_coin_id,
+                            struct TALER_DenominationHashP *denom_hash,
+                            struct TALER_AgeCommitmentHash *h_age_commitment)
 {
   struct PostgresClosure *pg = cls;
+  enum GNUNET_DB_QueryStatus qs;
+  bool existed;
+  bool is_denom_pub_hash_null = false;
+  bool is_age_hash_null = false;
   struct GNUNET_PQ_QueryParam params[] = {
-    GNUNET_PQ_query_param_auto_from_type (old_coin_pub),
-    GNUNET_PQ_query_param_uint64 (&rrc_serial),
-    GNUNET_PQ_query_param_auto_from_type (coin_bks),
-    GNUNET_PQ_query_param_auto_from_type (coin_pub),
-    GNUNET_PQ_query_param_uint64 (&known_coin_id),
-    GNUNET_PQ_query_param_auto_from_type (coin_sig),
-    GNUNET_PQ_query_param_timestamp (recoup_timestamp),
+    GNUNET_PQ_query_param_auto_from_type (&coin->coin_pub),
+    GNUNET_PQ_query_param_auto_from_type (&coin->denom_pub_hash),
+    GNUNET_PQ_query_param_auto_from_type (&coin->h_age_commitment),
+    TALER_PQ_query_param_denom_sig (&coin->denom_sig),
     GNUNET_PQ_query_param_end
   };
-  bool is_null;
   struct GNUNET_PQ_ResultSpec rs[] = {
+    GNUNET_PQ_result_spec_bool ("existed",
+                                &existed),
+    GNUNET_PQ_result_spec_uint64 ("known_coin_id",
+                                  known_coin_id),
     GNUNET_PQ_result_spec_allow_null (
-      GNUNET_PQ_result_spec_timestamp ("recoup_timestamp",
-                                       recoup_timestamp),
-      &is_null),
-    GNUNET_PQ_result_spec_bool ("recoup_ok",
-                                recoup_ok),
-    GNUNET_PQ_result_spec_bool ("internal_failure",
-                                internal_failure),
+      GNUNET_PQ_result_spec_auto_from_type ("denom_pub_hash",
+                                            denom_hash),
+      &is_denom_pub_hash_null),
+    GNUNET_PQ_result_spec_allow_null (
+      GNUNET_PQ_result_spec_auto_from_type ("age_commitment_hash",
+                                            h_age_commitment),
+      &is_age_hash_null),
     GNUNET_PQ_result_spec_end
   };
 
-  return GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
-                                                   "call_recoup_refresh",
-                                                   params,
-                                                   rs);
-}
+  qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
+                                                 "insert_known_coin",
+                                                 params,
+                                                 rs);
+  switch (qs)
+  {
+  case GNUNET_DB_STATUS_HARD_ERROR:
+    GNUNET_break (0);
+    return TALER_EXCHANGEDB_CKS_HARD_FAIL;
+  case GNUNET_DB_STATUS_SOFT_ERROR:
+    return TALER_EXCHANGEDB_CKS_SOFT_FAIL;
+  case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS:
+    GNUNET_break (0); /* should be impossible */
+    return TALER_EXCHANGEDB_CKS_HARD_FAIL;
+  case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT:
+    if (! existed)
+      return TALER_EXCHANGEDB_CKS_ADDED;
+    break; /* continued below */
+  }
 
+  if ( (! is_denom_pub_hash_null) &&
+       (0 != GNUNET_memcmp (&denom_hash->hash,
+                            &coin->denom_pub_hash.hash)) )
+  {
+    GNUNET_break_op (0);
+    return TALER_EXCHANGEDB_CKS_DENOM_CONFLICT;
+  }
 
-/*
- * Compares two indices into an array of hash codes according to
- * GNUNET_CRYPTO_hash_cmp of the content at those index positions.
- *
- * Used in a call qsort_t in order to generate sorted policy_hash_codes.
- */
-static int
-hash_code_cmp (
-  const void *hc1,
-  const void *hc2,
-  void *arg)
-{
-  size_t i1 = *(size_t *) hc1;
-  size_t i2 = *(size_t *) hc2;
-  const struct TALER_PolicyDetails *d = arg;
+  if ( (! is_age_hash_null) &&
+       (0 != GNUNET_memcmp (h_age_commitment,
+                            &coin->h_age_commitment)) )
+  {
+    GNUNET_break (GNUNET_is_zero (h_age_commitment));
+    GNUNET_break_op (0);
+    return TALER_EXCHANGEDB_CKS_AGE_CONFLICT;
+  }
 
-  return GNUNET_CRYPTO_hash_cmp (&d[i1].hash_code,
-                                 &d[i2].hash_code);
+  return TALER_EXCHANGEDB_CKS_PRESENT;
 }
 
+enum GNUNET_DB_QueryStatus
+setup_wire_target(
+  struct PostgresClosure *pg,
+  const char *payto_uri,
+  struct TALER_PaytoHashP *h_payto)
+{
+  struct GNUNET_PQ_QueryParam iparams[] = {
+    GNUNET_PQ_query_param_auto_from_type (h_payto),
+    GNUNET_PQ_query_param_string (payto_uri),
+    GNUNET_PQ_query_param_end
+  };
+
+  TALER_payto_hash (payto_uri,
+                    h_payto);
 
+  PREPARE (pg,
+           "insert_kyc_status",
+           "INSERT INTO wire_targets"
+           "  (wire_target_h_payto"
+           "  ,payto_uri"
+           "  ) VALUES "
+           "  ($1, $2)"
+           " ON CONFLICT DO NOTHING");
+  return GNUNET_PQ_eval_prepared_non_select (pg->conn,
+                                             "insert_kyc_status",
+                                             iparams);
+}
 /**
- * Add a proof of fulfillment into the policy_fulfillments table
+ * Insert information about deposited coin into the database.
  *
  * @param cls the `struct PostgresClosure` with the plugin-specific state
- * @param fulfillment fullfilment transaction data to be added
- * @return query execution status
+ * @param exchange_timestamp time the exchange received the deposit request
+ * @param deposit deposit information to store
+ * @return query result status
  */
 static enum GNUNET_DB_QueryStatus
-postgres_add_policy_fulfillment_proof (
-  void *cls,
-  struct TALER_PolicyFulfillmentTransactionData *fulfillment)
+postgres_insert_deposit (void *cls,
+                         struct GNUNET_TIME_Timestamp exchange_timestamp,
+                         const struct TALER_EXCHANGEDB_Deposit *deposit)
 {
-  enum GNUNET_DB_QueryStatus qs;
   struct PostgresClosure *pg = cls;
-  size_t count = fulfillment->details_count;
-  struct GNUNET_HashCode hcs[count];
+  struct TALER_PaytoHashP h_payto;
+  enum GNUNET_DB_QueryStatus qs;
 
-  /* Create the sorted policy_hash_codes */
+  qs = setup_wire_target (pg,
+                          deposit->receiver_wire_account,
+                          &h_payto);
+  if (qs < 0)
+    return qs;
+  if (GNUNET_TIME_timestamp_cmp (deposit->wire_deadline,
+                                 <,
+                                 deposit->refund_deadline))
   {
-    size_t idx[count];
-    for (size_t i = 0; i < count; i++)
-      idx[i] = i;
-
-    /* Sort the indices according to the hash codes of the corresponding
-     * details. */
-    qsort_r (idx,
-             count,
-             sizeof(size_t),
-             hash_code_cmp,
-             fulfillment->details);
-
-    /* Finally, concatenate all hash_codes in sorted order */
-    for (size_t i = 0; i < count; i++)
-      hcs[i] = fulfillment->details[idx[i]].hash_code;
+    GNUNET_break (0);
   }
-
-
-  /* Now, add the proof to the policy_fulfillments table, retrieve the
-   * record_id */
   {
+    uint64_t shard = TEH_PG_compute_shard (&deposit->merchant_pub);
     struct GNUNET_PQ_QueryParam params[] = {
-      GNUNET_PQ_query_param_timestamp (&fulfillment->timestamp),
-      TALER_PQ_query_param_json (fulfillment->proof),
-      GNUNET_PQ_query_param_auto_from_type (&fulfillment->h_proof),
-      GNUNET_PQ_query_param_fixed_size (hcs,
-                                        count * sizeof(struct 
GNUNET_HashCode)),
+      GNUNET_PQ_query_param_auto_from_type (&deposit->coin.coin_pub),
+      TALER_PQ_query_param_amount (&deposit->amount_with_fee),
+      GNUNET_PQ_query_param_timestamp (&deposit->timestamp),
+      GNUNET_PQ_query_param_timestamp (&deposit->refund_deadline),
+      GNUNET_PQ_query_param_timestamp (&deposit->wire_deadline),
+      GNUNET_PQ_query_param_auto_from_type (&deposit->merchant_pub),
+      GNUNET_PQ_query_param_auto_from_type (&deposit->h_contract_terms),
+      GNUNET_PQ_query_param_auto_from_type (&deposit->wire_salt),
+      GNUNET_PQ_query_param_auto_from_type (&h_payto),
+      GNUNET_PQ_query_param_auto_from_type (&deposit->csig),
+      GNUNET_PQ_query_param_timestamp (&exchange_timestamp),
+      GNUNET_PQ_query_param_uint64 (&shard),
       GNUNET_PQ_query_param_end
     };
-    struct GNUNET_PQ_ResultSpec rs[] = {
-      GNUNET_PQ_result_spec_uint64 ("fulfillment_id",
-                                    &fulfillment->fulfillment_id),
-      GNUNET_PQ_result_spec_end
-    };
-
-    qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
-                                                   
"insert_proof_into_policy_fulfillments",
-                                                   params,
-                                                   rs);
-    if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != qs)
-      return qs;
-  }
-
-  /* Now, set the states of each entry corresponding to the hash_codes in
-   * policy_details accordingly */
-  for (size_t i = 0; i < count; i++)
-  {
-    struct TALER_PolicyDetails *pos = &fulfillment->details[i];
-    {
-      struct GNUNET_PQ_QueryParam params[] = {
-        GNUNET_PQ_query_param_auto_from_type (&pos->hash_code),
-        GNUNET_PQ_query_param_timestamp (&pos->deadline),
-        TALER_PQ_query_param_amount (&pos->commitment),
-        TALER_PQ_query_param_amount (&pos->accumulated_total),
-        TALER_PQ_query_param_amount (&pos->policy_fee),
-        TALER_PQ_query_param_amount (&pos->transferable_amount),
-        GNUNET_PQ_query_param_auto_from_type (&pos->fulfillment_state),
-        GNUNET_PQ_query_param_end
-      };
 
-      qs = GNUNET_PQ_eval_prepared_non_select (pg->conn,
-                                               "update_policy_details",
+    GNUNET_assert (shard <= INT32_MAX);
+    GNUNET_log (
+      GNUNET_ERROR_TYPE_INFO,
+      "Inserting deposit to be executed at %s (%llu/%llu)\n",
+      GNUNET_TIME_timestamp2s (deposit->wire_deadline),
+      (unsigned long long) deposit->wire_deadline.abs_time.abs_value_us,
+      (unsigned long long) deposit->refund_deadline.abs_time.abs_value_us);
+    return GNUNET_PQ_eval_prepared_non_select (pg->conn,
+                                               "insert_deposit",
                                                params);
-      if (qs < 0)
-        return qs;
-    }
   }
-
-  return qs;
 }
 
 
 /**
- * Get the balance of the specified reserve.
+ * Insert information about refunded coin into the database.
  *
- * @param cls the `struct PostgresClosure` with the plugin-specific state
- * @param reserve_pub public key of the reserve
- * @param[out] balance set to the reserve balance
- * @return transaction status
+ * @param cls the @e cls of this struct with the plugin-specific state
+ * @param refund refund information to store
+ * @return query result status
  */
 static enum GNUNET_DB_QueryStatus
-postgres_get_reserve_balance (void *cls,
-                              const struct TALER_ReservePublicKeyP 
*reserve_pub,
-                              struct TALER_Amount *balance)
+postgres_insert_refund (void *cls,
+                        const struct TALER_EXCHANGEDB_Refund *refund)
 {
   struct PostgresClosure *pg = cls;
   struct GNUNET_PQ_QueryParam params[] = {
-    GNUNET_PQ_query_param_auto_from_type (reserve_pub),
+    GNUNET_PQ_query_param_auto_from_type (&refund->coin.coin_pub),
+    GNUNET_PQ_query_param_auto_from_type (&refund->details.merchant_pub),
+    GNUNET_PQ_query_param_auto_from_type (&refund->details.merchant_sig),
+    GNUNET_PQ_query_param_auto_from_type (&refund->details.h_contract_terms),
+    GNUNET_PQ_query_param_uint64 (&refund->details.rtransaction_id),
+    TALER_PQ_query_param_amount (&refund->details.refund_amount),
     GNUNET_PQ_query_param_end
   };
-  struct GNUNET_PQ_ResultSpec rs[] = {
-    TALER_PQ_RESULT_SPEC_AMOUNT ("current_balance",
-                                 balance),
-    GNUNET_PQ_result_spec_end
-  };
 
-  return GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
-                                                   "get_reserve_balance",
-                                                   params,
-                                                   rs);
+  GNUNET_assert (GNUNET_YES ==
+                 TALER_amount_cmp_currency (&refund->details.refund_amount,
+                                            &refund->details.refund_fee));
+  return GNUNET_PQ_eval_prepared_non_select (pg->conn,
+                                             "insert_refund",
+                                             params);
 }
 
 
 /**
- * Check if we have the specified deposit already in the database.
+ * Select refunds by @a coin_pub, @a merchant_pub and @a h_contract.
  *
- * @param cls the `struct PostgresClosure` with the plugin-specific state
- * @param h_contract_terms contract to check for
- * @param h_wire wire hash to check for
- * @param coin_pub public key of the coin to check for
- * @param merchant merchant public key to check for
- * @param refund_deadline expected refund deadline
- * @param[out] deposit_fee set to the deposit fee the exchange charged
- * @param[out] exchange_timestamp set to the time when the exchange received 
the deposit
- * @return 1 if we know this operation,
- *         0 if this exact deposit is unknown to us,
- *         otherwise transaction error status
- */
-static enum GNUNET_DB_QueryStatus
-postgres_have_deposit2 (
-  void *cls,
-  const struct TALER_PrivateContractHashP *h_contract_terms,
-  const struct TALER_MerchantWireHashP *h_wire,
+ * @param cls closure of plugin
+ * @param coin_pub coin to get refunds for
+ * @param merchant_pub merchant to get refunds for
+ * @param h_contract contract (hash) to get refunds for
+ * @param cb function to call for each refund found
+ * @param cb_cls closure for @a cb
+ * @return query result status
+ */
+static enum GNUNET_DB_QueryStatus
+postgres_select_refunds_by_coin (
+  void *cls,
   const struct TALER_CoinSpendPublicKeyP *coin_pub,
-  const struct TALER_MerchantPublicKeyP *merchant,
-  struct GNUNET_TIME_Timestamp refund_deadline,
-  struct TALER_Amount *deposit_fee,
-  struct GNUNET_TIME_Timestamp *exchange_timestamp)
+  const struct TALER_MerchantPublicKeyP *merchant_pub,
+  const struct TALER_PrivateContractHashP *h_contract,
+  TALER_EXCHANGEDB_RefundCoinCallback cb,
+  void *cb_cls)
 {
   struct PostgresClosure *pg = cls;
+  enum GNUNET_DB_QueryStatus qs;
   struct GNUNET_PQ_QueryParam params[] = {
     GNUNET_PQ_query_param_auto_from_type (coin_pub),
-    GNUNET_PQ_query_param_auto_from_type (h_contract_terms),
-    GNUNET_PQ_query_param_auto_from_type (merchant),
+    GNUNET_PQ_query_param_auto_from_type (merchant_pub),
+    GNUNET_PQ_query_param_auto_from_type (h_contract),
     GNUNET_PQ_query_param_end
   };
-  struct TALER_EXCHANGEDB_Deposit deposit2;
-  struct GNUNET_PQ_ResultSpec rs[] = {
-    TALER_PQ_RESULT_SPEC_AMOUNT ("amount_with_fee",
-                                 &deposit2.amount_with_fee),
-    GNUNET_PQ_result_spec_timestamp ("wallet_timestamp",
-                                     &deposit2.timestamp),
-    GNUNET_PQ_result_spec_timestamp ("exchange_timestamp",
-                                     exchange_timestamp),
-    GNUNET_PQ_result_spec_timestamp ("refund_deadline",
-                                     &deposit2.refund_deadline),
-    GNUNET_PQ_result_spec_timestamp ("wire_deadline",
-                                     &deposit2.wire_deadline),
-    TALER_PQ_RESULT_SPEC_AMOUNT ("fee_deposit",
-                                 deposit_fee),
-    GNUNET_PQ_result_spec_auto_from_type ("wire_salt",
-                                          &deposit2.wire_salt),
-    GNUNET_PQ_result_spec_string ("receiver_wire_account",
-                                  &deposit2.receiver_wire_account),
-    GNUNET_PQ_result_spec_end
+  struct SelectRefundContext srctx = {
+    .cb = cb,
+    .cb_cls = cb_cls,
+    .pg = pg,
+    .status = GNUNET_OK
   };
-  enum GNUNET_DB_QueryStatus qs;
-  struct TALER_MerchantWireHashP h_wire2;
 
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "Getting deposits for coin %s\n",
-              TALER_B2S (coin_pub));
-  qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
-                                                 "get_deposit",
-                                                 params,
-                                                 rs);
-  if (0 >= qs)
-    return qs;
-  TALER_merchant_wire_signature_hash (deposit2.receiver_wire_account,
-                                      &deposit2.wire_salt,
-                                      &h_wire2);
-  GNUNET_free (deposit2.receiver_wire_account);
-  /* Now we check that the other information in @a deposit
-     also matches, and if not report inconsistencies. */
-  if ( (GNUNET_TIME_timestamp_cmp (refund_deadline,
-                                   !=,
-                                   deposit2.refund_deadline)) ||
-       (0 != GNUNET_memcmp (h_wire,
-                            &h_wire2) ) )
-  {
-    /* Inconsistencies detected! Does not match! */
-    return GNUNET_DB_STATUS_SUCCESS_NO_RESULTS;
-  }
-  return GNUNET_DB_STATUS_SUCCESS_ONE_RESULT;
+  qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn,
+                                             
"get_refunds_by_coin_and_contract",
+                                             params,
+                                             &get_refunds_cb,
+                                             &srctx);
+  if (GNUNET_SYSERR == srctx.status)
+    return GNUNET_DB_STATUS_HARD_ERROR;
+  return qs;
 }
 
 
 /**
- * Aggregate all matching deposits for @a h_payto and
- * @a merchant_pub, returning the total amounts.
+ * Lookup refresh melt commitment data under the given @a rc.
  *
- * @param cls the @e cls of this struct with the plugin-specific state
- * @param h_payto destination of the wire transfer
- * @param merchant_pub public key of the merchant
- * @param wtid wire transfer ID to set for the aggregate
- * @param[out] total set to the sum of the total deposits minus applicable 
deposit fees and refunds
+ * @param cls the `struct PostgresClosure` with the plugin-specific state
+ * @param rc commitment hash to use to locate the operation
+ * @param[out] melt where to store the result; note that
+ *             melt->session.coin.denom_sig will be set to NULL
+ *             and is not fetched by this routine (as it is not needed by the 
client)
+ * @param[out] melt_serial_id set to the row ID of @a rc in the 
refresh_commitments table
  * @return transaction status
  */
 static enum GNUNET_DB_QueryStatus
-postgres_aggregate (
-  void *cls,
-  const struct TALER_PaytoHashP *h_payto,
-  const struct TALER_MerchantPublicKeyP *merchant_pub,
-  const struct TALER_WireTransferIdentifierRawP *wtid,
-  struct TALER_Amount *total)
+postgres_get_melt (void *cls,
+                   const struct TALER_RefreshCommitmentP *rc,
+                   struct TALER_EXCHANGEDB_Melt *melt,
+                   uint64_t *melt_serial_id)
 {
   struct PostgresClosure *pg = cls;
-  struct GNUNET_TIME_Absolute now = {0};
+  bool h_age_commitment_is_null;
   struct GNUNET_PQ_QueryParam params[] = {
-    GNUNET_PQ_query_param_absolute_time (&now),
-    GNUNET_PQ_query_param_auto_from_type (merchant_pub),
-    GNUNET_PQ_query_param_auto_from_type (h_payto),
-    GNUNET_PQ_query_param_auto_from_type (wtid),
+    GNUNET_PQ_query_param_auto_from_type (rc),
     GNUNET_PQ_query_param_end
   };
-  uint64_t sum_deposit_value;
-  uint64_t sum_deposit_frac;
-  uint64_t sum_refund_value;
-  uint64_t sum_refund_frac;
-  uint64_t sum_fee_value;
-  uint64_t sum_fee_frac;
   struct GNUNET_PQ_ResultSpec rs[] = {
-    GNUNET_PQ_result_spec_uint64 ("sum_deposit_value",
-                                  &sum_deposit_value),
-    GNUNET_PQ_result_spec_uint64 ("sum_deposit_fraction",
-                                  &sum_deposit_frac),
-    GNUNET_PQ_result_spec_uint64 ("sum_refund_value",
-                                  &sum_refund_value),
-    GNUNET_PQ_result_spec_uint64 ("sum_refund_fraction",
-                                  &sum_refund_frac),
-    GNUNET_PQ_result_spec_uint64 ("sum_fee_value",
-                                  &sum_fee_value),
-    GNUNET_PQ_result_spec_uint64 ("sum_fee_fraction",
-                                  &sum_fee_frac),
+    GNUNET_PQ_result_spec_auto_from_type ("denom_pub_hash",
+                                          &melt->session.coin.
+                                          denom_pub_hash),
+    TALER_PQ_RESULT_SPEC_AMOUNT ("fee_refresh",
+                                 &melt->melt_fee),
+    GNUNET_PQ_result_spec_uint32 ("noreveal_index",
+                                  &melt->session.noreveal_index),
+    GNUNET_PQ_result_spec_auto_from_type ("old_coin_pub",
+                                          &melt->session.coin.coin_pub),
+    GNUNET_PQ_result_spec_auto_from_type ("old_coin_sig",
+                                          &melt->session.coin_sig),
+    GNUNET_PQ_result_spec_allow_null (
+      GNUNET_PQ_result_spec_auto_from_type ("age_commitment_hash",
+                                            
&melt->session.coin.h_age_commitment),
+      &h_age_commitment_is_null),
+    TALER_PQ_RESULT_SPEC_AMOUNT ("amount_with_fee",
+                                 &melt->session.amount_with_fee),
+    GNUNET_PQ_result_spec_uint64 ("melt_serial_id",
+                                  melt_serial_id),
     GNUNET_PQ_result_spec_end
   };
   enum GNUNET_DB_QueryStatus qs;
-  struct TALER_Amount sum_deposit;
-  struct TALER_Amount sum_refund;
-  struct TALER_Amount sum_fee;
-  struct TALER_Amount delta;
 
-  now = GNUNET_TIME_absolute_round_down (GNUNET_TIME_absolute_get (),
-                                         pg->aggregator_shift);
+  memset (&melt->session.coin.denom_sig,
+          0,
+          sizeof (melt->session.coin.denom_sig));
   qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
-                                                 "aggregate",
+                                                 "get_melt",
                                                  params,
                                                  rs);
-  if (qs < 0)
-  {
-    GNUNET_break (GNUNET_DB_STATUS_SOFT_ERROR == qs);
-    return qs;
-  }
-  if (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS == qs)
-  {
-    GNUNET_assert (GNUNET_OK ==
-                   TALER_amount_set_zero (pg->currency,
-                                          total));
-    return qs;
-  }
-  GNUNET_assert (GNUNET_OK ==
-                 TALER_amount_set_zero (pg->currency,
-                                        &sum_deposit));
-  GNUNET_assert (GNUNET_OK ==
-                 TALER_amount_set_zero (pg->currency,
-                                        &sum_refund));
-  GNUNET_assert (GNUNET_OK ==
-                 TALER_amount_set_zero (pg->currency,
-                                        &sum_fee));
-  sum_deposit.value    = sum_deposit_frac / TALER_AMOUNT_FRAC_BASE
-                         + sum_deposit_value;
-  sum_deposit.fraction = sum_deposit_frac % TALER_AMOUNT_FRAC_BASE;
-  sum_refund.value     = sum_refund_frac  / TALER_AMOUNT_FRAC_BASE
-                         + sum_refund_value;
-  sum_refund.fraction  = sum_refund_frac  % TALER_AMOUNT_FRAC_BASE;
-  sum_fee.value        = sum_fee_frac     / TALER_AMOUNT_FRAC_BASE
-                         + sum_fee_value;
-  sum_fee.fraction     = sum_fee_frac     % TALER_AMOUNT_FRAC_BASE; \
-  GNUNET_assert (0 <=
-                 TALER_amount_subtract (&delta,
-                                        &sum_deposit,
-                                        &sum_refund));
-  GNUNET_assert (0 <=
-                 TALER_amount_subtract (total,
-                                        &delta,
-                                        &sum_fee));
+  if (h_age_commitment_is_null)
+    memset (&melt->session.coin.h_age_commitment,
+            0,
+            sizeof(melt->session.coin.h_age_commitment));
+
+  melt->session.rc = *rc;
   return qs;
 }
 
 
 /**
- * Create a new entry in the transient aggregation table.
+ * Store in the database which coin(s) the wallet wanted to create
+ * in a given refresh operation and all of the other information
+ * we learned or created in the /refresh/reveal step.
  *
  * @param cls the @e cls of this struct with the plugin-specific state
- * @param h_payto destination of the wire transfer
- * @param exchange_account_section exchange account to use
- * @param merchant_pub public key of the merchant receiving the transfer
- * @param wtid the raw wire transfer identifier to be used
- * @param kyc_requirement_row row in legitimization_requirements that need to 
be satisfied to continue, or 0 for none
- * @param total amount to be wired in the future
- * @return transaction status
+ * @param melt_serial_id row ID of the commitment / melt operation in 
refresh_commitments
+ * @param num_rrcs number of coins to generate, size of the @a rrcs array
+ * @param rrcs information about the new coins
+ * @param num_tprivs number of entries in @a tprivs, should be 
#TALER_CNC_KAPPA - 1
+ * @param tprivs transfer private keys to store
+ * @param tp public key to store
+ * @return query status for the transaction
  */
 static enum GNUNET_DB_QueryStatus
-postgres_create_aggregation_transient (
+postgres_insert_refresh_reveal (
   void *cls,
-  const struct TALER_PaytoHashP *h_payto,
-  const char *exchange_account_section,
-  const struct TALER_MerchantPublicKeyP *merchant_pub,
-  const struct TALER_WireTransferIdentifierRawP *wtid,
-  uint64_t kyc_requirement_row,
-  const struct TALER_Amount *total)
+  uint64_t melt_serial_id,
+  uint32_t num_rrcs,
+  const struct TALER_EXCHANGEDB_RefreshRevealedCoin *rrcs,
+  unsigned int num_tprivs,
+  const struct TALER_TransferPrivateKeyP *tprivs,
+  const struct TALER_TransferPublicKeyP *tp)
 {
   struct PostgresClosure *pg = cls;
-  struct GNUNET_PQ_QueryParam params[] = {
-    TALER_PQ_query_param_amount (total),
-    GNUNET_PQ_query_param_auto_from_type (merchant_pub),
-    GNUNET_PQ_query_param_auto_from_type (h_payto),
-    GNUNET_PQ_query_param_uint64 (&kyc_requirement_row),
-    GNUNET_PQ_query_param_string (exchange_account_section),
-    GNUNET_PQ_query_param_auto_from_type (wtid),
-    GNUNET_PQ_query_param_end
-  };
 
-  return GNUNET_PQ_eval_prepared_non_select (pg->conn,
-                                             "create_aggregation_transient",
-                                             params);
-}
-
-
-/**
- * Find existing entry in the transient aggregation table.
- *
- * @param cls the @e cls of this struct with the plugin-specific state
- * @param h_payto destination of the wire transfer
- * @param merchant_pub public key of the merchant receiving the transfer
- * @param exchange_account_section exchange account to use
- * @param[out] wtid set to the raw wire transfer identifier to be used
- * @param[out] total existing amount to be wired in the future
- * @return transaction status
- */
-static enum GNUNET_DB_QueryStatus
-postgres_select_aggregation_transient (
-  void *cls,
-  const struct TALER_PaytoHashP *h_payto,
-  const struct TALER_MerchantPublicKeyP *merchant_pub,
-  const char *exchange_account_section,
-  struct TALER_WireTransferIdentifierRawP *wtid,
-  struct TALER_Amount *total)
-{
-  struct PostgresClosure *pg = cls;
-  struct GNUNET_PQ_QueryParam params[] = {
-    GNUNET_PQ_query_param_auto_from_type (h_payto),
-    GNUNET_PQ_query_param_auto_from_type (merchant_pub),
-    GNUNET_PQ_query_param_string (exchange_account_section),
-    GNUNET_PQ_query_param_end
-  };
-  struct GNUNET_PQ_ResultSpec rs[] = {
-    TALER_PQ_RESULT_SPEC_AMOUNT ("amount",
-                                 total),
-    GNUNET_PQ_result_spec_auto_from_type ("wtid_raw",
-                                          wtid),
-    GNUNET_PQ_result_spec_end
-  };
+  if (TALER_CNC_KAPPA != num_tprivs + 1)
+  {
+    GNUNET_break (0);
+    return GNUNET_DB_STATUS_HARD_ERROR;
+  }
+  for (uint32_t i = 0; i<num_rrcs; i++)
+  {
+    const struct TALER_EXCHANGEDB_RefreshRevealedCoin *rrc = &rrcs[i];
+    struct GNUNET_PQ_QueryParam params[] = {
+      GNUNET_PQ_query_param_uint64 (&melt_serial_id),
+      GNUNET_PQ_query_param_uint32 (&i),
+      GNUNET_PQ_query_param_auto_from_type (&rrc->orig_coin_link_sig),
+      GNUNET_PQ_query_param_auto_from_type (&rrc->h_denom_pub),
+      TALER_PQ_query_param_blinded_planchet (&rrc->blinded_planchet),
+      TALER_PQ_query_param_exchange_withdraw_values (&rrc->exchange_vals),
+      GNUNET_PQ_query_param_auto_from_type (&rrc->coin_envelope_hash),
+      TALER_PQ_query_param_blinded_denom_sig (&rrc->coin_sig),
+      GNUNET_PQ_query_param_end
+    };
+    enum GNUNET_DB_QueryStatus qs;
 
-  return GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
-                                                   
"select_aggregation_transient",
-                                                   params,
-                                                   rs);
+    qs = GNUNET_PQ_eval_prepared_non_select (pg->conn,
+                                             "insert_refresh_revealed_coin",
+                                             params);
+    if (0 > qs)
+      return qs;
+  }
+
+  {
+    struct GNUNET_PQ_QueryParam params[] = {
+      GNUNET_PQ_query_param_uint64 (&melt_serial_id),
+      GNUNET_PQ_query_param_auto_from_type (tp),
+      GNUNET_PQ_query_param_fixed_size (
+        tprivs,
+        num_tprivs * sizeof (struct TALER_TransferPrivateKeyP)),
+      GNUNET_PQ_query_param_end
+    };
+
+    return GNUNET_PQ_eval_prepared_non_select (pg->conn,
+                                               "insert_refresh_transfer_keys",
+                                               params);
+  }
 }
 
 
 /**
- * Closure for #get_refunds_cb().
+ * Context where we aggregate data from the database.
+ * Closure for #add_revealed_coins().
  */
-struct FindAggregationTransientContext
+struct GetRevealContext
 {
   /**
-   * Function to call on each result.
-   */
-  TALER_EXCHANGEDB_TransientAggregationCallback cb;
-
-  /**
-   * Closure for @a cb.
+   * Array of revealed coins we obtained from the DB.
    */
-  void *cb_cls;
+  struct TALER_EXCHANGEDB_RefreshRevealedCoin *rrcs;
 
   /**
-   * Plugin context.
+   * Length of the @a rrcs array.
    */
-  struct PostgresClosure *pg;
+  unsigned int rrcs_len;
 
   /**
-   * Set to #GNUNET_SYSERR on error.
+   * Set to an error code if we ran into trouble.
    */
-  enum GNUNET_GenericReturnValue status;
+  enum GNUNET_DB_QueryStatus qs;
 };
 
 
@@ -3898,487 +1953,559 @@ struct FindAggregationTransientContext
  * Function to be called with the results of a SELECT statement
  * that has returned @a num_results results.
  *
- * @param cls closure of type `struct SelectRefundContext *`
+ * @param cls closure of type `struct GetRevealContext`
  * @param result the postgres result
  * @param num_results the number of results in @a result
  */
 static void
-get_transients_cb (void *cls,
-                   PGresult *result,
-                   unsigned int num_results)
+add_revealed_coins (void *cls,
+                    PGresult *result,
+                    unsigned int num_results)
 {
-  struct FindAggregationTransientContext *srctx = cls;
-  struct PostgresClosure *pg = srctx->pg;
+  struct GetRevealContext *grctx = cls;
 
-  for (unsigned int i = 0; i<num_results; i++)
+  if (0 == num_results)
+    return;
+  grctx->rrcs = GNUNET_new_array (num_results,
+                                  struct TALER_EXCHANGEDB_RefreshRevealedCoin);
+  grctx->rrcs_len = num_results;
+  for (unsigned int i = 0; i < num_results; i++)
   {
-    struct TALER_Amount amount;
-    char *payto_uri;
-    struct TALER_WireTransferIdentifierRawP wtid;
-    struct TALER_MerchantPublicKeyP merchant_pub;
-    struct GNUNET_PQ_ResultSpec rs[] = {
-      GNUNET_PQ_result_spec_auto_from_type ("merchant_pub",
-                                            &merchant_pub),
-      GNUNET_PQ_result_spec_auto_from_type ("wtid_raw",
-                                            &wtid),
-      GNUNET_PQ_result_spec_string ("payto_uri",
-                                    &payto_uri),
-      TALER_PQ_RESULT_SPEC_AMOUNT ("amount",
-                                   &amount),
+    uint32_t off;
+    struct GNUNET_PQ_ResultSpec rso[] = {
+      GNUNET_PQ_result_spec_uint32 ("freshcoin_index",
+                                    &off),
       GNUNET_PQ_result_spec_end
     };
-    bool cont;
 
     if (GNUNET_OK !=
         GNUNET_PQ_extract_result (result,
-                                  rs,
+                                  rso,
                                   i))
     {
       GNUNET_break (0);
-      srctx->status = GNUNET_SYSERR;
+      grctx->qs = GNUNET_DB_STATUS_HARD_ERROR;
       return;
     }
-    cont = srctx->cb (srctx->cb_cls,
-                      payto_uri,
-                      &wtid,
-                      &merchant_pub,
-                      &amount);
-    GNUNET_free (payto_uri);
-    if (! cont)
-      break;
+    if (off >= num_results)
+    {
+      GNUNET_break (0);
+      grctx->qs = GNUNET_DB_STATUS_HARD_ERROR;
+      return;
+    }
+    {
+      struct TALER_EXCHANGEDB_RefreshRevealedCoin *rrc = &grctx->rrcs[off];
+      struct GNUNET_PQ_ResultSpec rsi[] = {
+        /* NOTE: freshcoin_index selected and discarded here... */
+        GNUNET_PQ_result_spec_auto_from_type ("denom_pub_hash",
+                                              &rrc->h_denom_pub),
+        GNUNET_PQ_result_spec_auto_from_type ("link_sig",
+                                              &rrc->orig_coin_link_sig),
+        GNUNET_PQ_result_spec_auto_from_type ("h_coin_ev",
+                                              &rrc->coin_envelope_hash),
+        TALER_PQ_result_spec_blinded_planchet ("coin_ev",
+                                               &rrc->blinded_planchet),
+        TALER_PQ_result_spec_exchange_withdraw_values ("ewv",
+                                                       &rrc->exchange_vals),
+        TALER_PQ_result_spec_blinded_denom_sig ("ev_sig",
+                                                &rrc->coin_sig),
+        GNUNET_PQ_result_spec_end
+      };
+
+      if (TALER_DENOMINATION_INVALID != rrc->blinded_planchet.cipher)
+      {
+        /* duplicate offset, not allowed */
+        GNUNET_break (0);
+        grctx->qs = GNUNET_DB_STATUS_HARD_ERROR;
+        return;
+      }
+      if (GNUNET_OK !=
+          GNUNET_PQ_extract_result (result,
+                                    rsi,
+                                    i))
+      {
+        GNUNET_break (0);
+        grctx->qs = GNUNET_DB_STATUS_HARD_ERROR;
+        return;
+      }
+    }
   }
 }
 
 
 /**
- * Find existing entry in the transient aggregation table.
+ * Lookup in the database the coins that we want to
+ * create in the given refresh operation.
  *
- * @param cls the @e cls of this struct with the plugin-specific state
- * @param h_payto destination of the wire transfer
- * @param cb function to call on each matching entry
+ * @param cls the `struct PostgresClosure` with the plugin-specific state
+ * @param rc identify commitment and thus refresh operation
+ * @param cb function to call with the results
  * @param cb_cls closure for @a cb
  * @return transaction status
  */
 static enum GNUNET_DB_QueryStatus
-postgres_find_aggregation_transient (
-  void *cls,
-  const struct TALER_PaytoHashP *h_payto,
-  TALER_EXCHANGEDB_TransientAggregationCallback cb,
-  void *cb_cls)
+postgres_get_refresh_reveal (void *cls,
+                             const struct TALER_RefreshCommitmentP *rc,
+                             TALER_EXCHANGEDB_RefreshCallback cb,
+                             void *cb_cls)
 {
   struct PostgresClosure *pg = cls;
+  struct GetRevealContext grctx;
   enum GNUNET_DB_QueryStatus qs;
   struct GNUNET_PQ_QueryParam params[] = {
-    GNUNET_PQ_query_param_auto_from_type (h_payto),
+    GNUNET_PQ_query_param_auto_from_type (rc),
     GNUNET_PQ_query_param_end
   };
-  struct FindAggregationTransientContext srctx = {
-    .cb = cb,
-    .cb_cls = cb_cls,
-    .pg = pg,
-    .status = GNUNET_OK
-  };
 
+  memset (&grctx,
+          0,
+          sizeof (grctx));
   qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn,
-                                             "find_transient_aggregations",
+                                             "get_refresh_revealed_coins",
                                              params,
-                                             &get_transients_cb,
-                                             &srctx);
-  if (GNUNET_SYSERR == srctx.status)
-    return GNUNET_DB_STATUS_HARD_ERROR;
-  return qs;
-}
+                                             &add_revealed_coins,
+                                             &grctx);
+  switch (qs)
+  {
+  case GNUNET_DB_STATUS_HARD_ERROR:
+  case GNUNET_DB_STATUS_SOFT_ERROR:
+  case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS:
+    goto cleanup;
+  case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT:
+  default: /* can have more than one result */
+    break;
+  }
+  switch (grctx.qs)
+  {
+  case GNUNET_DB_STATUS_HARD_ERROR:
+  case GNUNET_DB_STATUS_SOFT_ERROR:
+    goto cleanup;
+  case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS:
+  case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT: /* should be impossible */
+    break;
+  }
+
+  /* Pass result back to application */
+  cb (cb_cls,
+      grctx.rrcs_len,
+      grctx.rrcs);
+cleanup:
+  for (unsigned int i = 0; i < grctx.rrcs_len; i++)
+  {
+    struct TALER_EXCHANGEDB_RefreshRevealedCoin *rrc = &grctx.rrcs[i];
+
+    TALER_blinded_denom_sig_free (&rrc->coin_sig);
+    TALER_blinded_planchet_free (&rrc->blinded_planchet);
+  }
+  GNUNET_free (grctx.rrcs);
+  return qs;
+}
 
 
 /**
- * Update existing entry in the transient aggregation table.
- * @a h_payto is only needed for query performance.
+ * Closure for #handle_wt_result.
+ */
+struct WireTransferResultContext
+{
+  /**
+   * Function to call on each result.
+   */
+  TALER_EXCHANGEDB_AggregationDataCallback cb;
+
+  /**
+   * Closure for @e cb.
+   */
+  void *cb_cls;
+
+  /**
+   * Plugin context.
+   */
+  struct PostgresClosure *pg;
+
+  /**
+   * Set to #GNUNET_SYSERR on serious errors.
+   */
+  int status;
+};
+
+
+/**
+ * Function to be called with the results of a SELECT statement
+ * that has returned @a num_results results.  Helper function
+ * for #postgres_lookup_wire_transfer().
  *
- * @param cls the @e cls of this struct with the plugin-specific state
- * @param h_payto destination of the wire transfer
- * @param wtid the raw wire transfer identifier to update
- * @param kyc_requirement_row row in legitimization_requirements that need to 
be satisfied to continue, or 0 for none
- * @param total new total amount to be wired in the future
- * @return transaction status
+ * @param cls closure of type `struct WireTransferResultContext *`
+ * @param result the postgres result
+ * @param num_results the number of results in @a result
  */
-static enum GNUNET_DB_QueryStatus
-postgres_update_aggregation_transient (
-  void *cls,
-  const struct TALER_PaytoHashP *h_payto,
-  const struct TALER_WireTransferIdentifierRawP *wtid,
-  uint64_t kyc_requirement_row,
-  const struct TALER_Amount *total)
+static void
+handle_wt_result (void *cls,
+                  PGresult *result,
+                  unsigned int num_results)
 {
-  struct PostgresClosure *pg = cls;
-  struct GNUNET_PQ_QueryParam params[] = {
-    TALER_PQ_query_param_amount (total),
-    GNUNET_PQ_query_param_auto_from_type (h_payto),
-    GNUNET_PQ_query_param_auto_from_type (wtid),
-    GNUNET_PQ_query_param_uint64 (&kyc_requirement_row),
-    GNUNET_PQ_query_param_end
-  };
+  struct WireTransferResultContext *ctx = cls;
+  struct PostgresClosure *pg = ctx->pg;
 
-  return GNUNET_PQ_eval_prepared_non_select (pg->conn,
-                                             "update_aggregation_transient",
-                                             params);
+  for (unsigned int i = 0; i<num_results; i++)
+  {
+    uint64_t rowid;
+    struct TALER_PrivateContractHashP h_contract_terms;
+    struct TALER_CoinSpendPublicKeyP coin_pub;
+    struct TALER_PaytoHashP h_payto;
+    struct TALER_MerchantPublicKeyP merchant_pub;
+    struct GNUNET_TIME_Timestamp exec_time;
+    struct TALER_Amount amount_with_fee;
+    struct TALER_Amount deposit_fee;
+    struct TALER_DenominationPublicKey denom_pub;
+    char *payto_uri;
+    struct GNUNET_PQ_ResultSpec rs[] = {
+      GNUNET_PQ_result_spec_uint64 ("aggregation_serial_id", &rowid),
+      GNUNET_PQ_result_spec_auto_from_type ("h_contract_terms",
+                                            &h_contract_terms),
+      GNUNET_PQ_result_spec_string ("payto_uri",
+                                    &payto_uri),
+      GNUNET_PQ_result_spec_auto_from_type ("wire_target_h_payto",
+                                            &h_payto),
+      TALER_PQ_result_spec_denom_pub ("denom_pub",
+                                      &denom_pub),
+      GNUNET_PQ_result_spec_auto_from_type ("coin_pub",
+                                            &coin_pub),
+      GNUNET_PQ_result_spec_auto_from_type ("merchant_pub",
+                                            &merchant_pub),
+      GNUNET_PQ_result_spec_timestamp ("execution_date",
+                                       &exec_time),
+      TALER_PQ_RESULT_SPEC_AMOUNT ("amount_with_fee",
+                                   &amount_with_fee),
+      TALER_PQ_RESULT_SPEC_AMOUNT ("fee_deposit",
+                                   &deposit_fee),
+      GNUNET_PQ_result_spec_end
+    };
+
+    if (GNUNET_OK !=
+        GNUNET_PQ_extract_result (result,
+                                  rs,
+                                  i))
+    {
+      GNUNET_break (0);
+      ctx->status = GNUNET_SYSERR;
+      return;
+    }
+    ctx->cb (ctx->cb_cls,
+             rowid,
+             &merchant_pub,
+             payto_uri,
+             &h_payto,
+             exec_time,
+             &h_contract_terms,
+             &denom_pub,
+             &coin_pub,
+             &amount_with_fee,
+             &deposit_fee);
+    GNUNET_PQ_cleanup_result (rs);
+  }
 }
 
 
 /**
- * Obtain information about deposits that are ready to be executed.  Such
- * deposits must not be marked as "done", the execution time must be
- * in the past, and the KYC status must be 'ok'.
+ * Lookup the list of Taler transactions that were aggregated
+ * into a wire transfer by the respective @a wtid.
  *
- * @param cls the @e cls of this struct with the plugin-specific state
- * @param start_shard_row minimum shard row to select
- * @param end_shard_row maximum shard row to select (inclusive)
- * @param[out] merchant_pub set to the public key of a merchant with a ready 
deposit
- * @param[out] payto_uri set to the account of the merchant, to be freed by 
caller
- * @return transaction status code
+ * @param cls closure
+ * @param wtid the raw wire transfer identifier we used
+ * @param cb function to call on each transaction found
+ * @param cb_cls closure for @a cb
+ * @return query status of the transaction
  */
 static enum GNUNET_DB_QueryStatus
-postgres_get_ready_deposit (void *cls,
-                            uint64_t start_shard_row,
-                            uint64_t end_shard_row,
-                            struct TALER_MerchantPublicKeyP *merchant_pub,
-                            char **payto_uri)
+postgres_lookup_wire_transfer (
+  void *cls,
+  const struct TALER_WireTransferIdentifierRawP *wtid,
+  TALER_EXCHANGEDB_AggregationDataCallback cb,
+  void *cb_cls)
 {
   struct PostgresClosure *pg = cls;
-  struct GNUNET_TIME_Absolute now = {0};
   struct GNUNET_PQ_QueryParam params[] = {
-    GNUNET_PQ_query_param_absolute_time (&now),
-    GNUNET_PQ_query_param_uint64 (&start_shard_row),
-    GNUNET_PQ_query_param_uint64 (&end_shard_row),
+    GNUNET_PQ_query_param_auto_from_type (wtid),
     GNUNET_PQ_query_param_end
   };
-  struct GNUNET_PQ_ResultSpec rs[] = {
-    GNUNET_PQ_result_spec_auto_from_type ("merchant_pub",
-                                          merchant_pub),
-    GNUNET_PQ_result_spec_string ("payto_uri",
-                                  payto_uri),
-    GNUNET_PQ_result_spec_end
-  };
+  struct WireTransferResultContext ctx;
+  enum GNUNET_DB_QueryStatus qs;
 
-  now = GNUNET_TIME_absolute_round_down (GNUNET_TIME_absolute_get (),
-                                         pg->aggregator_shift);
-  GNUNET_assert (start_shard_row < end_shard_row);
-  GNUNET_assert (end_shard_row <= INT32_MAX);
-  GNUNET_log (GNUNET_ERROR_TYPE_INFO,
-              "Finding ready deposits by deadline %s (%llu)\n",
-              GNUNET_TIME_absolute2s (now),
-              (unsigned long long) now.abs_value_us);
-  return GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
-                                                   "deposits_get_ready",
-                                                   params,
-                                                   rs);
+  ctx.cb = cb;
+  ctx.cb_cls = cb_cls;
+  ctx.pg = pg;
+  ctx.status = GNUNET_OK;
+  /* check if the melt record exists and get it */
+  qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn,
+                                             "lookup_transactions",
+                                             params,
+                                             &handle_wt_result,
+                                             &ctx);
+  if (GNUNET_OK != ctx.status)
+    return GNUNET_DB_STATUS_HARD_ERROR;
+  return qs;
 }
 
 
 /**
- * Retrieve the record for a known coin.
+ * Try to find the wire transfer details for a deposit operation.
+ * If we did not execute the deposit yet, return when it is supposed
+ * to be executed.
  *
- * @param cls the plugin closure
- * @param coin_pub the public key of the coin to search for
- * @param coin_info place holder for the returned coin information object
+ * @param cls closure
+ * @param h_contract_terms hash of the proposal data
+ * @param h_wire hash of merchant wire details
+ * @param coin_pub public key of deposited coin
+ * @param merchant_pub merchant public key
+ * @param[out] pending set to true if the transaction is still pending
+ * @param[out] wtid wire transfer identifier, only set if @a pending is false
+ * @param[out] exec_time when was the transaction done, or
+ *         when we expect it to be done (if @a pending is false)
+ * @param[out] amount_with_fee set to the total deposited amount
+ * @param[out] deposit_fee set to how much the exchange did charge for the 
deposit
+ * @param[out] kyc set to the kyc status of the receiver (if @a pending)
  * @return transaction status code
  */
 static enum GNUNET_DB_QueryStatus
-postgres_get_known_coin (void *cls,
-                         const struct TALER_CoinSpendPublicKeyP *coin_pub,
-                         struct TALER_CoinPublicInfo *coin_info)
+postgres_lookup_transfer_by_deposit (
+  void *cls,
+  const struct TALER_PrivateContractHashP *h_contract_terms,
+  const struct TALER_MerchantWireHashP *h_wire,
+  const struct TALER_CoinSpendPublicKeyP *coin_pub,
+  const struct TALER_MerchantPublicKeyP *merchant_pub,
+  bool *pending,
+  struct TALER_WireTransferIdentifierRawP *wtid,
+  struct GNUNET_TIME_Timestamp *exec_time,
+  struct TALER_Amount *amount_with_fee,
+  struct TALER_Amount *deposit_fee,
+  struct TALER_EXCHANGEDB_KycStatus *kyc)
 {
   struct PostgresClosure *pg = cls;
+  enum GNUNET_DB_QueryStatus qs;
   struct GNUNET_PQ_QueryParam params[] = {
     GNUNET_PQ_query_param_auto_from_type (coin_pub),
+    GNUNET_PQ_query_param_auto_from_type (h_contract_terms),
+    GNUNET_PQ_query_param_auto_from_type (merchant_pub),
     GNUNET_PQ_query_param_end
   };
+  char *payto_uri;
+  struct TALER_WireSaltP wire_salt;
   struct GNUNET_PQ_ResultSpec rs[] = {
-    GNUNET_PQ_result_spec_auto_from_type ("denom_pub_hash",
-                                          &coin_info->denom_pub_hash),
-    GNUNET_PQ_result_spec_allow_null (
-      GNUNET_PQ_result_spec_auto_from_type ("age_commitment_hash",
-                                            &coin_info->h_age_commitment),
-      &coin_info->no_age_commitment),
-    TALER_PQ_result_spec_denom_sig ("denom_sig",
-                                    &coin_info->denom_sig),
+    GNUNET_PQ_result_spec_auto_from_type ("wtid_raw",
+                                          wtid),
+    GNUNET_PQ_result_spec_auto_from_type ("wire_salt",
+                                          &wire_salt),
+    GNUNET_PQ_result_spec_string ("payto_uri",
+                                  &payto_uri),
+    GNUNET_PQ_result_spec_timestamp ("execution_date",
+                                     exec_time),
+    TALER_PQ_RESULT_SPEC_AMOUNT ("amount_with_fee",
+                                 amount_with_fee),
+    TALER_PQ_RESULT_SPEC_AMOUNT ("fee_deposit",
+                                 deposit_fee),
     GNUNET_PQ_result_spec_end
   };
 
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "Getting known coin data for coin %s\n",
-              TALER_B2S (coin_pub));
-  coin_info->coin_pub = *coin_pub;
-  return GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
-                                                   "get_known_coin",
+  memset (kyc,
+          0,
+          sizeof (*kyc));
+  /* check if the aggregation record exists and get it */
+  qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
+                                                 "lookup_deposit_wtid",
+                                                 params,
+                                                 rs);
+  if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT == qs)
+  {
+    struct TALER_MerchantWireHashP wh;
+
+    TALER_merchant_wire_signature_hash (payto_uri,
+                                        &wire_salt,
+                                        &wh);
+    GNUNET_PQ_cleanup_result (rs);
+    if (0 ==
+        GNUNET_memcmp (&wh,
+                       h_wire))
+    {
+      *pending = false;
+      kyc->ok = true;
+      return qs;
+    }
+    qs = GNUNET_DB_STATUS_SUCCESS_NO_RESULTS;
+  }
+  if (0 > qs)
+    return qs;
+  *pending = true;
+  memset (wtid,
+          0,
+          sizeof (*wtid));
+  GNUNET_assert (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS == qs);
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "lookup_deposit_wtid returned 0 matching rows\n");
+  {
+    /* Check if transaction exists in deposits, so that we just
+       do not have a WTID yet. In that case, return without wtid
+       (by setting 'pending' true). */
+    struct GNUNET_PQ_ResultSpec rs2[] = {
+      GNUNET_PQ_result_spec_auto_from_type ("wire_salt",
+                                            &wire_salt),
+      GNUNET_PQ_result_spec_string ("payto_uri",
+                                    &payto_uri),
+      GNUNET_PQ_result_spec_allow_null (
+        GNUNET_PQ_result_spec_uint64 ("legitimization_requirement_serial_id",
+                                      &kyc->requirement_row),
+        NULL),
+      TALER_PQ_RESULT_SPEC_AMOUNT ("amount_with_fee",
+                                   amount_with_fee),
+      TALER_PQ_RESULT_SPEC_AMOUNT ("fee_deposit",
+                                   deposit_fee),
+      GNUNET_PQ_result_spec_timestamp ("wire_deadline",
+                                       exec_time),
+      GNUNET_PQ_result_spec_end
+    };
+
+    qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
+                                                   "get_deposit_without_wtid",
                                                    params,
-                                                   rs);
+                                                   rs2);
+    if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT == qs)
+    {
+      struct TALER_MerchantWireHashP wh;
+
+      if (0 == kyc->requirement_row)
+        kyc->ok = true; /* technically: unknown */
+      TALER_merchant_wire_signature_hash (payto_uri,
+                                          &wire_salt,
+                                          &wh);
+      GNUNET_PQ_cleanup_result (rs);
+      if (0 !=
+          GNUNET_memcmp (&wh,
+                         h_wire))
+        return GNUNET_DB_STATUS_SUCCESS_NO_RESULTS;
+    }
+    return qs;
+  }
 }
 
 
 /**
- * Retrieve the denomination of a known coin.
+ * Obtain wire fee from database.
  *
- * @param cls the plugin closure
- * @param coin_pub the public key of the coin to search for
- * @param[out] known_coin_id set to the ID of the coin in the known_coins table
- * @param[out] denom_hash where to store the hash of the coins denomination
- * @return transaction status code
+ * @param cls closure
+ * @param type type of wire transfer the fee applies for
+ * @param date for which date do we want the fee?
+ * @param[out] start_date when does the fee go into effect
+ * @param[out] end_date when does the fee end being valid
+ * @param[out] fees how high are the wire fees
+ * @param[out] master_sig signature over the above by the exchange master key
+ * @return status of the transaction
  */
 static enum GNUNET_DB_QueryStatus
-postgres_get_coin_denomination (
-  void *cls,
-  const struct TALER_CoinSpendPublicKeyP *coin_pub,
-  uint64_t *known_coin_id,
-  struct TALER_DenominationHashP *denom_hash)
+postgres_get_wire_fee (void *cls,
+                       const char *type,
+                       struct GNUNET_TIME_Timestamp date,
+                       struct GNUNET_TIME_Timestamp *start_date,
+                       struct GNUNET_TIME_Timestamp *end_date,
+                       struct TALER_WireFeeSet *fees,
+                       struct TALER_MasterSignatureP *master_sig)
 {
   struct PostgresClosure *pg = cls;
   struct GNUNET_PQ_QueryParam params[] = {
-    GNUNET_PQ_query_param_auto_from_type (coin_pub),
+    GNUNET_PQ_query_param_string (type),
+    GNUNET_PQ_query_param_timestamp (&date),
     GNUNET_PQ_query_param_end
   };
   struct GNUNET_PQ_ResultSpec rs[] = {
-    GNUNET_PQ_result_spec_auto_from_type ("denom_pub_hash",
-                                          denom_hash),
-    GNUNET_PQ_result_spec_uint64 ("known_coin_id",
-                                  known_coin_id),
+    GNUNET_PQ_result_spec_timestamp ("start_date",
+                                     start_date),
+    GNUNET_PQ_result_spec_timestamp ("end_date",
+                                     end_date),
+    TALER_PQ_RESULT_SPEC_AMOUNT ("wire_fee",
+                                 &fees->wire),
+    TALER_PQ_RESULT_SPEC_AMOUNT ("closing_fee",
+                                 &fees->closing),
+    GNUNET_PQ_result_spec_auto_from_type ("master_sig",
+                                          master_sig),
     GNUNET_PQ_result_spec_end
   };
 
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "Getting coin denomination of coin %s\n",
-              TALER_B2S (coin_pub));
   return GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
-                                                   "get_coin_denomination",
+                                                   "get_wire_fee",
                                                    params,
                                                    rs);
 }
 
 
 /**
- * Count the number of known coins by denomination.
+ * Obtain global fees from database.
  *
- * @param cls database connection plugin state
- * @param denom_pub_hash denomination to count by
- * @return number of coins if non-negative, otherwise an `enum 
GNUNET_DB_QueryStatus`
+ * @param cls closure
+ * @param date for which date do we want the fee?
+ * @param[out] start_date when does the fee go into effect
+ * @param[out] end_date when does the fee end being valid
+ * @param[out] fees how high are the wire fees
+ * @param[out] purse_timeout set to how long we keep unmerged purses
+ * @param[out] history_expiration set to how long we keep account histories
+ * @param[out] purse_account_limit set to the number of free purses per account
+ * @param[out] master_sig signature over the above by the exchange master key
+ * @return status of the transaction
  */
-static long long
-postgres_count_known_coins (void *cls,
-                            const struct
-                            TALER_DenominationHashP *denom_pub_hash)
+static enum GNUNET_DB_QueryStatus
+postgres_get_global_fee (void *cls,
+                         struct GNUNET_TIME_Timestamp date,
+                         struct GNUNET_TIME_Timestamp *start_date,
+                         struct GNUNET_TIME_Timestamp *end_date,
+                         struct TALER_GlobalFeeSet *fees,
+                         struct GNUNET_TIME_Relative *purse_timeout,
+                         struct GNUNET_TIME_Relative *history_expiration,
+                         uint32_t *purse_account_limit,
+                         struct TALER_MasterSignatureP *master_sig)
 {
   struct PostgresClosure *pg = cls;
-  uint64_t count;
   struct GNUNET_PQ_QueryParam params[] = {
-    GNUNET_PQ_query_param_auto_from_type (denom_pub_hash),
+    GNUNET_PQ_query_param_timestamp (&date),
     GNUNET_PQ_query_param_end
   };
   struct GNUNET_PQ_ResultSpec rs[] = {
-    GNUNET_PQ_result_spec_uint64 ("count",
-                                  &count),
+    GNUNET_PQ_result_spec_timestamp ("start_date",
+                                     start_date),
+    GNUNET_PQ_result_spec_timestamp ("end_date",
+                                     end_date),
+    TALER_PQ_RESULT_SPEC_AMOUNT ("history_fee",
+                                 &fees->history),
+    TALER_PQ_RESULT_SPEC_AMOUNT ("account_fee",
+                                 &fees->account),
+    TALER_PQ_RESULT_SPEC_AMOUNT ("purse_fee",
+                                 &fees->purse),
+    GNUNET_PQ_result_spec_relative_time ("purse_timeout",
+                                         purse_timeout),
+    GNUNET_PQ_result_spec_relative_time ("history_expiration",
+                                         history_expiration),
+    GNUNET_PQ_result_spec_uint32 ("purse_account_limit",
+                                  purse_account_limit),
+    GNUNET_PQ_result_spec_auto_from_type ("master_sig",
+                                          master_sig),
     GNUNET_PQ_result_spec_end
   };
-  enum GNUNET_DB_QueryStatus qs;
 
-  qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
-                                                 "count_known_coins",
-                                                 params,
-                                                 rs);
-  if (0 > qs)
-    return (long long) qs;
-  return (long long) count;
+  return GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
+                                                   "get_global_fee",
+                                                   params,
+                                                   rs);
 }
 
 
 /**
- * Make sure the given @a coin is known to the database.
- *
- * @param cls database connection plugin state
- * @param coin the coin that must be made known
- * @param[out] known_coin_id set to the unique row of the coin
- * @param[out] denom_hash set to the denomination hash of the existing
- *             coin (for conflict error reporting)
- * @param[out] h_age_commitment  set to the conflicting age commitment hash on 
conflict
- * @return database transaction status, non-negative on success
+ * Closure for #global_fees_cb().
  */
-static enum TALER_EXCHANGEDB_CoinKnownStatus
-postgres_ensure_coin_known (void *cls,
-                            const struct TALER_CoinPublicInfo *coin,
-                            uint64_t *known_coin_id,
-                            struct TALER_DenominationHashP *denom_hash,
-                            struct TALER_AgeCommitmentHash *h_age_commitment)
+struct GlobalFeeContext
 {
-  struct PostgresClosure *pg = cls;
-  enum GNUNET_DB_QueryStatus qs;
-  bool existed;
-  bool is_denom_pub_hash_null = false;
-  bool is_age_hash_null = false;
-  struct GNUNET_PQ_QueryParam params[] = {
-    GNUNET_PQ_query_param_auto_from_type (&coin->coin_pub),
-    GNUNET_PQ_query_param_auto_from_type (&coin->denom_pub_hash),
-    GNUNET_PQ_query_param_auto_from_type (&coin->h_age_commitment),
-    TALER_PQ_query_param_denom_sig (&coin->denom_sig),
-    GNUNET_PQ_query_param_end
-  };
-  struct GNUNET_PQ_ResultSpec rs[] = {
-    GNUNET_PQ_result_spec_bool ("existed",
-                                &existed),
-    GNUNET_PQ_result_spec_uint64 ("known_coin_id",
-                                  known_coin_id),
-    GNUNET_PQ_result_spec_allow_null (
-      GNUNET_PQ_result_spec_auto_from_type ("denom_pub_hash",
-                                            denom_hash),
-      &is_denom_pub_hash_null),
-    GNUNET_PQ_result_spec_allow_null (
-      GNUNET_PQ_result_spec_auto_from_type ("age_commitment_hash",
-                                            h_age_commitment),
-      &is_age_hash_null),
-    GNUNET_PQ_result_spec_end
-  };
-
-  qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
-                                                 "insert_known_coin",
-                                                 params,
-                                                 rs);
-  switch (qs)
-  {
-  case GNUNET_DB_STATUS_HARD_ERROR:
-    GNUNET_break (0);
-    return TALER_EXCHANGEDB_CKS_HARD_FAIL;
-  case GNUNET_DB_STATUS_SOFT_ERROR:
-    return TALER_EXCHANGEDB_CKS_SOFT_FAIL;
-  case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS:
-    GNUNET_break (0); /* should be impossible */
-    return TALER_EXCHANGEDB_CKS_HARD_FAIL;
-  case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT:
-    if (! existed)
-      return TALER_EXCHANGEDB_CKS_ADDED;
-    break; /* continued below */
-  }
-
-  if ( (! is_denom_pub_hash_null) &&
-       (0 != GNUNET_memcmp (&denom_hash->hash,
-                            &coin->denom_pub_hash.hash)) )
-  {
-    GNUNET_break_op (0);
-    return TALER_EXCHANGEDB_CKS_DENOM_CONFLICT;
-  }
-
-  if ( (! is_age_hash_null) &&
-       (0 != GNUNET_memcmp (h_age_commitment,
-                            &coin->h_age_commitment)) )
-  {
-    GNUNET_break (GNUNET_is_zero (h_age_commitment));
-    GNUNET_break_op (0);
-    return TALER_EXCHANGEDB_CKS_AGE_CONFLICT;
-  }
-
-  return TALER_EXCHANGEDB_CKS_PRESENT;
-}
-
-
-/**
- * Insert information about deposited coin into the database.
- *
- * @param cls the `struct PostgresClosure` with the plugin-specific state
- * @param exchange_timestamp time the exchange received the deposit request
- * @param deposit deposit information to store
- * @return query result status
- */
-static enum GNUNET_DB_QueryStatus
-postgres_insert_deposit (void *cls,
-                         struct GNUNET_TIME_Timestamp exchange_timestamp,
-                         const struct TALER_EXCHANGEDB_Deposit *deposit)
-{
-  struct PostgresClosure *pg = cls;
-  struct TALER_PaytoHashP h_payto;
-  enum GNUNET_DB_QueryStatus qs;
-
-  qs = setup_wire_target (pg,
-                          deposit->receiver_wire_account,
-                          &h_payto);
-  if (qs < 0)
-    return qs;
-  if (GNUNET_TIME_timestamp_cmp (deposit->wire_deadline,
-                                 <,
-                                 deposit->refund_deadline))
-  {
-    GNUNET_break (0);
-  }
-  {
-    uint64_t shard = compute_shard (&deposit->merchant_pub);
-    struct GNUNET_PQ_QueryParam params[] = {
-      GNUNET_PQ_query_param_auto_from_type (&deposit->coin.coin_pub),
-      TALER_PQ_query_param_amount (&deposit->amount_with_fee),
-      GNUNET_PQ_query_param_timestamp (&deposit->timestamp),
-      GNUNET_PQ_query_param_timestamp (&deposit->refund_deadline),
-      GNUNET_PQ_query_param_timestamp (&deposit->wire_deadline),
-      GNUNET_PQ_query_param_auto_from_type (&deposit->merchant_pub),
-      GNUNET_PQ_query_param_auto_from_type (&deposit->h_contract_terms),
-      GNUNET_PQ_query_param_auto_from_type (&deposit->wire_salt),
-      GNUNET_PQ_query_param_auto_from_type (&h_payto),
-      GNUNET_PQ_query_param_auto_from_type (&deposit->csig),
-      GNUNET_PQ_query_param_timestamp (&exchange_timestamp),
-      GNUNET_PQ_query_param_uint64 (&shard),
-      GNUNET_PQ_query_param_end
-    };
-
-    GNUNET_assert (shard <= INT32_MAX);
-    GNUNET_log (
-      GNUNET_ERROR_TYPE_INFO,
-      "Inserting deposit to be executed at %s (%llu/%llu)\n",
-      GNUNET_TIME_timestamp2s (deposit->wire_deadline),
-      (unsigned long long) deposit->wire_deadline.abs_time.abs_value_us,
-      (unsigned long long) deposit->refund_deadline.abs_time.abs_value_us);
-    return GNUNET_PQ_eval_prepared_non_select (pg->conn,
-                                               "insert_deposit",
-                                               params);
-  }
-}
-
-
-/**
- * Insert information about refunded coin into the database.
- *
- * @param cls the @e cls of this struct with the plugin-specific state
- * @param refund refund information to store
- * @return query result status
- */
-static enum GNUNET_DB_QueryStatus
-postgres_insert_refund (void *cls,
-                        const struct TALER_EXCHANGEDB_Refund *refund)
-{
-  struct PostgresClosure *pg = cls;
-  struct GNUNET_PQ_QueryParam params[] = {
-    GNUNET_PQ_query_param_auto_from_type (&refund->coin.coin_pub),
-    GNUNET_PQ_query_param_auto_from_type (&refund->details.merchant_pub),
-    GNUNET_PQ_query_param_auto_from_type (&refund->details.merchant_sig),
-    GNUNET_PQ_query_param_auto_from_type (&refund->details.h_contract_terms),
-    GNUNET_PQ_query_param_uint64 (&refund->details.rtransaction_id),
-    TALER_PQ_query_param_amount (&refund->details.refund_amount),
-    GNUNET_PQ_query_param_end
-  };
-
-  GNUNET_assert (GNUNET_YES ==
-                 TALER_amount_cmp_currency (&refund->details.refund_amount,
-                                            &refund->details.refund_fee));
-  return GNUNET_PQ_eval_prepared_non_select (pg->conn,
-                                             "insert_refund",
-                                             params);
-}
-
-
-/**
- * Closure for #get_refunds_cb().
- */
-struct SelectRefundContext
-{
-  /**
-   * Function to call on each result.
-   */
-  TALER_EXCHANGEDB_RefundCoinCallback cb;
+  /**
+   * Function to call for each global fee block.
+   */
+  TALER_EXCHANGEDB_GlobalFeeCallback cb;
 
   /**
-   * Closure for @a cb.
+   * Closure to give to @e rec.
    */
   void *cb_cls;
 
@@ -4390,7 +2517,7 @@ struct SelectRefundContext
   /**
    * Set to #GNUNET_SYSERR on error.
    */
-  int status;
+  enum GNUNET_GenericReturnValue status;
 };
 
 
@@ -4398,2450 +2525,506 @@ struct SelectRefundContext
  * Function to be called with the results of a SELECT statement
  * that has returned @a num_results results.
  *
- * @param cls closure of type `struct SelectRefundContext *`
+ * @param cls closure
  * @param result the postgres result
  * @param num_results the number of results in @a result
  */
 static void
-get_refunds_cb (void *cls,
+global_fees_cb (void *cls,
                 PGresult *result,
                 unsigned int num_results)
 {
-  struct SelectRefundContext *srctx = cls;
-  struct PostgresClosure *pg = srctx->pg;
+  struct GlobalFeeContext *gctx = cls;
+  struct PostgresClosure *pg = gctx->pg;
 
   for (unsigned int i = 0; i<num_results; i++)
   {
-    struct TALER_Amount amount_with_fee;
+    struct TALER_GlobalFeeSet fees;
+    struct GNUNET_TIME_Relative purse_timeout;
+    struct GNUNET_TIME_Relative history_expiration;
+    uint32_t purse_account_limit;
+    struct GNUNET_TIME_Timestamp start_date;
+    struct GNUNET_TIME_Timestamp end_date;
+    struct TALER_MasterSignatureP master_sig;
     struct GNUNET_PQ_ResultSpec rs[] = {
-      TALER_PQ_RESULT_SPEC_AMOUNT ("amount_with_fee",
-                                   &amount_with_fee),
+      GNUNET_PQ_result_spec_timestamp ("start_date",
+                                       &start_date),
+      GNUNET_PQ_result_spec_timestamp ("end_date",
+                                       &end_date),
+      TALER_PQ_RESULT_SPEC_AMOUNT ("history_fee",
+                                   &fees.history),
+      TALER_PQ_RESULT_SPEC_AMOUNT ("account_fee",
+                                   &fees.account),
+      TALER_PQ_RESULT_SPEC_AMOUNT ("purse_fee",
+                                   &fees.purse),
+      GNUNET_PQ_result_spec_relative_time ("purse_timeout",
+                                           &purse_timeout),
+      GNUNET_PQ_result_spec_relative_time ("history_expiration",
+                                           &history_expiration),
+      GNUNET_PQ_result_spec_uint32 ("purse_account_limit",
+                                    &purse_account_limit),
+      GNUNET_PQ_result_spec_auto_from_type ("master_sig",
+                                            &master_sig),
       GNUNET_PQ_result_spec_end
     };
-
     if (GNUNET_OK !=
         GNUNET_PQ_extract_result (result,
                                   rs,
                                   i))
     {
       GNUNET_break (0);
-      srctx->status = GNUNET_SYSERR;
-      return;
+      gctx->status = GNUNET_SYSERR;
+      break;
     }
-    if (GNUNET_OK !=
-        srctx->cb (srctx->cb_cls,
-                   &amount_with_fee))
-      return;
+    gctx->cb (gctx->cb_cls,
+              &fees,
+              purse_timeout,
+              history_expiration,
+              purse_account_limit,
+              start_date,
+              end_date,
+              &master_sig);
+    GNUNET_PQ_cleanup_result (rs);
   }
 }
 
 
 /**
- * Select refunds by @a coin_pub, @a merchant_pub and @a h_contract.
+ * Obtain global fees from database.
  *
- * @param cls closure of plugin
- * @param coin_pub coin to get refunds for
- * @param merchant_pub merchant to get refunds for
- * @param h_contract contract (hash) to get refunds for
- * @param cb function to call for each refund found
+ * @param cls closure
+ * @param cb function to call on each fee entry
  * @param cb_cls closure for @a cb
- * @return query result status
+ * @return status of the transaction
  */
 static enum GNUNET_DB_QueryStatus
-postgres_select_refunds_by_coin (
-  void *cls,
-  const struct TALER_CoinSpendPublicKeyP *coin_pub,
-  const struct TALER_MerchantPublicKeyP *merchant_pub,
-  const struct TALER_PrivateContractHashP *h_contract,
-  TALER_EXCHANGEDB_RefundCoinCallback cb,
-  void *cb_cls)
+postgres_get_global_fees (void *cls,
+                          TALER_EXCHANGEDB_GlobalFeeCallback cb,
+                          void *cb_cls)
 {
   struct PostgresClosure *pg = cls;
-  enum GNUNET_DB_QueryStatus qs;
+  struct GNUNET_TIME_Timestamp date
+    = GNUNET_TIME_absolute_to_timestamp (
+        GNUNET_TIME_absolute_subtract (
+          GNUNET_TIME_absolute_get (),
+          GNUNET_TIME_UNIT_YEARS));
   struct GNUNET_PQ_QueryParam params[] = {
-    GNUNET_PQ_query_param_auto_from_type (coin_pub),
-    GNUNET_PQ_query_param_auto_from_type (merchant_pub),
-    GNUNET_PQ_query_param_auto_from_type (h_contract),
+    GNUNET_PQ_query_param_timestamp (&date),
     GNUNET_PQ_query_param_end
   };
-  struct SelectRefundContext srctx = {
+  struct GlobalFeeContext gctx = {
     .cb = cb,
     .cb_cls = cb_cls,
     .pg = pg,
     .status = GNUNET_OK
   };
 
-  qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn,
-                                             
"get_refunds_by_coin_and_contract",
-                                             params,
-                                             &get_refunds_cb,
-                                             &srctx);
-  if (GNUNET_SYSERR == srctx.status)
-    return GNUNET_DB_STATUS_HARD_ERROR;
-  return qs;
+  return GNUNET_PQ_eval_prepared_multi_select (pg->conn,
+                                               "get_global_fees",
+                                               params,
+                                               &global_fees_cb,
+                                               &gctx);
 }
 
 
 /**
- * Lookup refresh melt commitment data under the given @a rc.
+ * Insert wire transfer fee into database.
  *
- * @param cls the `struct PostgresClosure` with the plugin-specific state
- * @param rc commitment hash to use to locate the operation
- * @param[out] melt where to store the result; note that
- *             melt->session.coin.denom_sig will be set to NULL
- *             and is not fetched by this routine (as it is not needed by the 
client)
- * @param[out] melt_serial_id set to the row ID of @a rc in the 
refresh_commitments table
- * @return transaction status
+ * @param cls closure
+ * @param type type of wire transfer this fee applies for
+ * @param start_date when does the fee go into effect
+ * @param end_date when does the fee end being valid
+ * @param fees how high are the wire fees
+ * @param master_sig signature over the above by the exchange master key
+ * @return transaction status code
  */
 static enum GNUNET_DB_QueryStatus
-postgres_get_melt (void *cls,
-                   const struct TALER_RefreshCommitmentP *rc,
-                   struct TALER_EXCHANGEDB_Melt *melt,
-                   uint64_t *melt_serial_id)
-{
-  struct PostgresClosure *pg = cls;
-  bool h_age_commitment_is_null;
-  struct GNUNET_PQ_QueryParam params[] = {
-    GNUNET_PQ_query_param_auto_from_type (rc),
-    GNUNET_PQ_query_param_end
-  };
-  struct GNUNET_PQ_ResultSpec rs[] = {
-    GNUNET_PQ_result_spec_auto_from_type ("denom_pub_hash",
-                                          &melt->session.coin.
-                                          denom_pub_hash),
-    TALER_PQ_RESULT_SPEC_AMOUNT ("fee_refresh",
-                                 &melt->melt_fee),
-    GNUNET_PQ_result_spec_uint32 ("noreveal_index",
-                                  &melt->session.noreveal_index),
-    GNUNET_PQ_result_spec_auto_from_type ("old_coin_pub",
-                                          &melt->session.coin.coin_pub),
-    GNUNET_PQ_result_spec_auto_from_type ("old_coin_sig",
-                                          &melt->session.coin_sig),
-    GNUNET_PQ_result_spec_allow_null (
-      GNUNET_PQ_result_spec_auto_from_type ("age_commitment_hash",
-                                            
&melt->session.coin.h_age_commitment),
-      &h_age_commitment_is_null),
-    TALER_PQ_RESULT_SPEC_AMOUNT ("amount_with_fee",
-                                 &melt->session.amount_with_fee),
-    GNUNET_PQ_result_spec_uint64 ("melt_serial_id",
-                                  melt_serial_id),
-    GNUNET_PQ_result_spec_end
-  };
-  enum GNUNET_DB_QueryStatus qs;
-
-  memset (&melt->session.coin.denom_sig,
-          0,
-          sizeof (melt->session.coin.denom_sig));
-  qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
-                                                 "get_melt",
-                                                 params,
-                                                 rs);
-  if (h_age_commitment_is_null)
-    memset (&melt->session.coin.h_age_commitment,
-            0,
-            sizeof(melt->session.coin.h_age_commitment));
-
-  melt->session.rc = *rc;
-  return qs;
-}
-
-
-/**
- * Store in the database which coin(s) the wallet wanted to create
- * in a given refresh operation and all of the other information
- * we learned or created in the /refresh/reveal step.
- *
- * @param cls the @e cls of this struct with the plugin-specific state
- * @param melt_serial_id row ID of the commitment / melt operation in 
refresh_commitments
- * @param num_rrcs number of coins to generate, size of the @a rrcs array
- * @param rrcs information about the new coins
- * @param num_tprivs number of entries in @a tprivs, should be 
#TALER_CNC_KAPPA - 1
- * @param tprivs transfer private keys to store
- * @param tp public key to store
- * @return query status for the transaction
- */
-static enum GNUNET_DB_QueryStatus
-postgres_insert_refresh_reveal (
-  void *cls,
-  uint64_t melt_serial_id,
-  uint32_t num_rrcs,
-  const struct TALER_EXCHANGEDB_RefreshRevealedCoin *rrcs,
-  unsigned int num_tprivs,
-  const struct TALER_TransferPrivateKeyP *tprivs,
-  const struct TALER_TransferPublicKeyP *tp)
-{
-  struct PostgresClosure *pg = cls;
-
-  if (TALER_CNC_KAPPA != num_tprivs + 1)
-  {
-    GNUNET_break (0);
-    return GNUNET_DB_STATUS_HARD_ERROR;
-  }
-  for (uint32_t i = 0; i<num_rrcs; i++)
-  {
-    const struct TALER_EXCHANGEDB_RefreshRevealedCoin *rrc = &rrcs[i];
-    struct GNUNET_PQ_QueryParam params[] = {
-      GNUNET_PQ_query_param_uint64 (&melt_serial_id),
-      GNUNET_PQ_query_param_uint32 (&i),
-      GNUNET_PQ_query_param_auto_from_type (&rrc->orig_coin_link_sig),
-      GNUNET_PQ_query_param_auto_from_type (&rrc->h_denom_pub),
-      TALER_PQ_query_param_blinded_planchet (&rrc->blinded_planchet),
-      TALER_PQ_query_param_exchange_withdraw_values (&rrc->exchange_vals),
-      GNUNET_PQ_query_param_auto_from_type (&rrc->coin_envelope_hash),
-      TALER_PQ_query_param_blinded_denom_sig (&rrc->coin_sig),
-      GNUNET_PQ_query_param_end
-    };
-    enum GNUNET_DB_QueryStatus qs;
-
-    qs = GNUNET_PQ_eval_prepared_non_select (pg->conn,
-                                             "insert_refresh_revealed_coin",
-                                             params);
-    if (0 > qs)
-      return qs;
-  }
-
-  {
-    struct GNUNET_PQ_QueryParam params[] = {
-      GNUNET_PQ_query_param_uint64 (&melt_serial_id),
-      GNUNET_PQ_query_param_auto_from_type (tp),
-      GNUNET_PQ_query_param_fixed_size (
-        tprivs,
-        num_tprivs * sizeof (struct TALER_TransferPrivateKeyP)),
-      GNUNET_PQ_query_param_end
-    };
-
-    return GNUNET_PQ_eval_prepared_non_select (pg->conn,
-                                               "insert_refresh_transfer_keys",
-                                               params);
-  }
-}
-
-
-/**
- * Context where we aggregate data from the database.
- * Closure for #add_revealed_coins().
- */
-struct GetRevealContext
-{
-  /**
-   * Array of revealed coins we obtained from the DB.
-   */
-  struct TALER_EXCHANGEDB_RefreshRevealedCoin *rrcs;
-
-  /**
-   * Length of the @a rrcs array.
-   */
-  unsigned int rrcs_len;
-
-  /**
-   * Set to an error code if we ran into trouble.
-   */
-  enum GNUNET_DB_QueryStatus qs;
-};
-
-
-/**
- * Function to be called with the results of a SELECT statement
- * that has returned @a num_results results.
- *
- * @param cls closure of type `struct GetRevealContext`
- * @param result the postgres result
- * @param num_results the number of results in @a result
- */
-static void
-add_revealed_coins (void *cls,
-                    PGresult *result,
-                    unsigned int num_results)
-{
-  struct GetRevealContext *grctx = cls;
-
-  if (0 == num_results)
-    return;
-  grctx->rrcs = GNUNET_new_array (num_results,
-                                  struct TALER_EXCHANGEDB_RefreshRevealedCoin);
-  grctx->rrcs_len = num_results;
-  for (unsigned int i = 0; i < num_results; i++)
-  {
-    uint32_t off;
-    struct GNUNET_PQ_ResultSpec rso[] = {
-      GNUNET_PQ_result_spec_uint32 ("freshcoin_index",
-                                    &off),
-      GNUNET_PQ_result_spec_end
-    };
-
-    if (GNUNET_OK !=
-        GNUNET_PQ_extract_result (result,
-                                  rso,
-                                  i))
-    {
-      GNUNET_break (0);
-      grctx->qs = GNUNET_DB_STATUS_HARD_ERROR;
-      return;
-    }
-    if (off >= num_results)
-    {
-      GNUNET_break (0);
-      grctx->qs = GNUNET_DB_STATUS_HARD_ERROR;
-      return;
-    }
-    {
-      struct TALER_EXCHANGEDB_RefreshRevealedCoin *rrc = &grctx->rrcs[off];
-      struct GNUNET_PQ_ResultSpec rsi[] = {
-        /* NOTE: freshcoin_index selected and discarded here... */
-        GNUNET_PQ_result_spec_auto_from_type ("denom_pub_hash",
-                                              &rrc->h_denom_pub),
-        GNUNET_PQ_result_spec_auto_from_type ("link_sig",
-                                              &rrc->orig_coin_link_sig),
-        GNUNET_PQ_result_spec_auto_from_type ("h_coin_ev",
-                                              &rrc->coin_envelope_hash),
-        TALER_PQ_result_spec_blinded_planchet ("coin_ev",
-                                               &rrc->blinded_planchet),
-        TALER_PQ_result_spec_exchange_withdraw_values ("ewv",
-                                                       &rrc->exchange_vals),
-        TALER_PQ_result_spec_blinded_denom_sig ("ev_sig",
-                                                &rrc->coin_sig),
-        GNUNET_PQ_result_spec_end
-      };
-
-      if (TALER_DENOMINATION_INVALID != rrc->blinded_planchet.cipher)
-      {
-        /* duplicate offset, not allowed */
-        GNUNET_break (0);
-        grctx->qs = GNUNET_DB_STATUS_HARD_ERROR;
-        return;
-      }
-      if (GNUNET_OK !=
-          GNUNET_PQ_extract_result (result,
-                                    rsi,
-                                    i))
-      {
-        GNUNET_break (0);
-        grctx->qs = GNUNET_DB_STATUS_HARD_ERROR;
-        return;
-      }
-    }
-  }
-}
-
-
-/**
- * Lookup in the database the coins that we want to
- * create in the given refresh operation.
- *
- * @param cls the `struct PostgresClosure` with the plugin-specific state
- * @param rc identify commitment and thus refresh operation
- * @param cb function to call with the results
- * @param cb_cls closure for @a cb
- * @return transaction status
- */
-static enum GNUNET_DB_QueryStatus
-postgres_get_refresh_reveal (void *cls,
-                             const struct TALER_RefreshCommitmentP *rc,
-                             TALER_EXCHANGEDB_RefreshCallback cb,
-                             void *cb_cls)
-{
-  struct PostgresClosure *pg = cls;
-  struct GetRevealContext grctx;
-  enum GNUNET_DB_QueryStatus qs;
-  struct GNUNET_PQ_QueryParam params[] = {
-    GNUNET_PQ_query_param_auto_from_type (rc),
-    GNUNET_PQ_query_param_end
-  };
-
-  memset (&grctx,
-          0,
-          sizeof (grctx));
-  qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn,
-                                             "get_refresh_revealed_coins",
-                                             params,
-                                             &add_revealed_coins,
-                                             &grctx);
-  switch (qs)
-  {
-  case GNUNET_DB_STATUS_HARD_ERROR:
-  case GNUNET_DB_STATUS_SOFT_ERROR:
-  case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS:
-    goto cleanup;
-  case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT:
-  default: /* can have more than one result */
-    break;
-  }
-  switch (grctx.qs)
-  {
-  case GNUNET_DB_STATUS_HARD_ERROR:
-  case GNUNET_DB_STATUS_SOFT_ERROR:
-    goto cleanup;
-  case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS:
-  case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT: /* should be impossible */
-    break;
-  }
-
-  /* Pass result back to application */
-  cb (cb_cls,
-      grctx.rrcs_len,
-      grctx.rrcs);
-cleanup:
-  for (unsigned int i = 0; i < grctx.rrcs_len; i++)
-  {
-    struct TALER_EXCHANGEDB_RefreshRevealedCoin *rrc = &grctx.rrcs[i];
-
-    TALER_blinded_denom_sig_free (&rrc->coin_sig);
-    TALER_blinded_planchet_free (&rrc->blinded_planchet);
-  }
-  GNUNET_free (grctx.rrcs);
-  return qs;
-}
-
-
-/**
- * Closure for #handle_wt_result.
- */
-struct WireTransferResultContext
-{
-  /**
-   * Function to call on each result.
-   */
-  TALER_EXCHANGEDB_AggregationDataCallback cb;
-
-  /**
-   * Closure for @e cb.
-   */
-  void *cb_cls;
-
-  /**
-   * Plugin context.
-   */
-  struct PostgresClosure *pg;
-
-  /**
-   * Set to #GNUNET_SYSERR on serious errors.
-   */
-  int status;
-};
-
-
-/**
- * Function to be called with the results of a SELECT statement
- * that has returned @a num_results results.  Helper function
- * for #postgres_lookup_wire_transfer().
- *
- * @param cls closure of type `struct WireTransferResultContext *`
- * @param result the postgres result
- * @param num_results the number of results in @a result
- */
-static void
-handle_wt_result (void *cls,
-                  PGresult *result,
-                  unsigned int num_results)
-{
-  struct WireTransferResultContext *ctx = cls;
-  struct PostgresClosure *pg = ctx->pg;
-
-  for (unsigned int i = 0; i<num_results; i++)
-  {
-    uint64_t rowid;
-    struct TALER_PrivateContractHashP h_contract_terms;
-    struct TALER_CoinSpendPublicKeyP coin_pub;
-    struct TALER_PaytoHashP h_payto;
-    struct TALER_MerchantPublicKeyP merchant_pub;
-    struct GNUNET_TIME_Timestamp exec_time;
-    struct TALER_Amount amount_with_fee;
-    struct TALER_Amount deposit_fee;
-    struct TALER_DenominationPublicKey denom_pub;
-    char *payto_uri;
-    struct GNUNET_PQ_ResultSpec rs[] = {
-      GNUNET_PQ_result_spec_uint64 ("aggregation_serial_id", &rowid),
-      GNUNET_PQ_result_spec_auto_from_type ("h_contract_terms",
-                                            &h_contract_terms),
-      GNUNET_PQ_result_spec_string ("payto_uri",
-                                    &payto_uri),
-      GNUNET_PQ_result_spec_auto_from_type ("wire_target_h_payto",
-                                            &h_payto),
-      TALER_PQ_result_spec_denom_pub ("denom_pub",
-                                      &denom_pub),
-      GNUNET_PQ_result_spec_auto_from_type ("coin_pub",
-                                            &coin_pub),
-      GNUNET_PQ_result_spec_auto_from_type ("merchant_pub",
-                                            &merchant_pub),
-      GNUNET_PQ_result_spec_timestamp ("execution_date",
-                                       &exec_time),
-      TALER_PQ_RESULT_SPEC_AMOUNT ("amount_with_fee",
-                                   &amount_with_fee),
-      TALER_PQ_RESULT_SPEC_AMOUNT ("fee_deposit",
-                                   &deposit_fee),
-      GNUNET_PQ_result_spec_end
-    };
-
-    if (GNUNET_OK !=
-        GNUNET_PQ_extract_result (result,
-                                  rs,
-                                  i))
-    {
-      GNUNET_break (0);
-      ctx->status = GNUNET_SYSERR;
-      return;
-    }
-    ctx->cb (ctx->cb_cls,
-             rowid,
-             &merchant_pub,
-             payto_uri,
-             &h_payto,
-             exec_time,
-             &h_contract_terms,
-             &denom_pub,
-             &coin_pub,
-             &amount_with_fee,
-             &deposit_fee);
-    GNUNET_PQ_cleanup_result (rs);
-  }
-}
-
-
-/**
- * Lookup the list of Taler transactions that were aggregated
- * into a wire transfer by the respective @a wtid.
- *
- * @param cls closure
- * @param wtid the raw wire transfer identifier we used
- * @param cb function to call on each transaction found
- * @param cb_cls closure for @a cb
- * @return query status of the transaction
- */
-static enum GNUNET_DB_QueryStatus
-postgres_lookup_wire_transfer (
-  void *cls,
-  const struct TALER_WireTransferIdentifierRawP *wtid,
-  TALER_EXCHANGEDB_AggregationDataCallback cb,
-  void *cb_cls)
-{
-  struct PostgresClosure *pg = cls;
-  struct GNUNET_PQ_QueryParam params[] = {
-    GNUNET_PQ_query_param_auto_from_type (wtid),
-    GNUNET_PQ_query_param_end
-  };
-  struct WireTransferResultContext ctx;
-  enum GNUNET_DB_QueryStatus qs;
-
-  ctx.cb = cb;
-  ctx.cb_cls = cb_cls;
-  ctx.pg = pg;
-  ctx.status = GNUNET_OK;
-  /* check if the melt record exists and get it */
-  qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn,
-                                             "lookup_transactions",
-                                             params,
-                                             &handle_wt_result,
-                                             &ctx);
-  if (GNUNET_OK != ctx.status)
-    return GNUNET_DB_STATUS_HARD_ERROR;
-  return qs;
-}
-
-
-/**
- * Try to find the wire transfer details for a deposit operation.
- * If we did not execute the deposit yet, return when it is supposed
- * to be executed.
- *
- * @param cls closure
- * @param h_contract_terms hash of the proposal data
- * @param h_wire hash of merchant wire details
- * @param coin_pub public key of deposited coin
- * @param merchant_pub merchant public key
- * @param[out] pending set to true if the transaction is still pending
- * @param[out] wtid wire transfer identifier, only set if @a pending is false
- * @param[out] exec_time when was the transaction done, or
- *         when we expect it to be done (if @a pending is false)
- * @param[out] amount_with_fee set to the total deposited amount
- * @param[out] deposit_fee set to how much the exchange did charge for the 
deposit
- * @param[out] kyc set to the kyc status of the receiver (if @a pending)
- * @return transaction status code
- */
-static enum GNUNET_DB_QueryStatus
-postgres_lookup_transfer_by_deposit (
-  void *cls,
-  const struct TALER_PrivateContractHashP *h_contract_terms,
-  const struct TALER_MerchantWireHashP *h_wire,
-  const struct TALER_CoinSpendPublicKeyP *coin_pub,
-  const struct TALER_MerchantPublicKeyP *merchant_pub,
-  bool *pending,
-  struct TALER_WireTransferIdentifierRawP *wtid,
-  struct GNUNET_TIME_Timestamp *exec_time,
-  struct TALER_Amount *amount_with_fee,
-  struct TALER_Amount *deposit_fee,
-  struct TALER_EXCHANGEDB_KycStatus *kyc)
-{
-  struct PostgresClosure *pg = cls;
-  enum GNUNET_DB_QueryStatus qs;
-  struct GNUNET_PQ_QueryParam params[] = {
-    GNUNET_PQ_query_param_auto_from_type (coin_pub),
-    GNUNET_PQ_query_param_auto_from_type (h_contract_terms),
-    GNUNET_PQ_query_param_auto_from_type (merchant_pub),
-    GNUNET_PQ_query_param_end
-  };
-  char *payto_uri;
-  struct TALER_WireSaltP wire_salt;
-  struct GNUNET_PQ_ResultSpec rs[] = {
-    GNUNET_PQ_result_spec_auto_from_type ("wtid_raw",
-                                          wtid),
-    GNUNET_PQ_result_spec_auto_from_type ("wire_salt",
-                                          &wire_salt),
-    GNUNET_PQ_result_spec_string ("payto_uri",
-                                  &payto_uri),
-    GNUNET_PQ_result_spec_timestamp ("execution_date",
-                                     exec_time),
-    TALER_PQ_RESULT_SPEC_AMOUNT ("amount_with_fee",
-                                 amount_with_fee),
-    TALER_PQ_RESULT_SPEC_AMOUNT ("fee_deposit",
-                                 deposit_fee),
-    GNUNET_PQ_result_spec_end
-  };
-
-  memset (kyc,
-          0,
-          sizeof (*kyc));
-  /* check if the aggregation record exists and get it */
-  qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
-                                                 "lookup_deposit_wtid",
-                                                 params,
-                                                 rs);
-  if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT == qs)
-  {
-    struct TALER_MerchantWireHashP wh;
-
-    TALER_merchant_wire_signature_hash (payto_uri,
-                                        &wire_salt,
-                                        &wh);
-    GNUNET_PQ_cleanup_result (rs);
-    if (0 ==
-        GNUNET_memcmp (&wh,
-                       h_wire))
-    {
-      *pending = false;
-      kyc->ok = true;
-      return qs;
-    }
-    qs = GNUNET_DB_STATUS_SUCCESS_NO_RESULTS;
-  }
-  if (0 > qs)
-    return qs;
-  *pending = true;
-  memset (wtid,
-          0,
-          sizeof (*wtid));
-  GNUNET_assert (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS == qs);
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "lookup_deposit_wtid returned 0 matching rows\n");
-  {
-    /* Check if transaction exists in deposits, so that we just
-       do not have a WTID yet. In that case, return without wtid
-       (by setting 'pending' true). */
-    struct GNUNET_PQ_ResultSpec rs2[] = {
-      GNUNET_PQ_result_spec_auto_from_type ("wire_salt",
-                                            &wire_salt),
-      GNUNET_PQ_result_spec_string ("payto_uri",
-                                    &payto_uri),
-      GNUNET_PQ_result_spec_allow_null (
-        GNUNET_PQ_result_spec_uint64 ("legitimization_requirement_serial_id",
-                                      &kyc->requirement_row),
-        NULL),
-      TALER_PQ_RESULT_SPEC_AMOUNT ("amount_with_fee",
-                                   amount_with_fee),
-      TALER_PQ_RESULT_SPEC_AMOUNT ("fee_deposit",
-                                   deposit_fee),
-      GNUNET_PQ_result_spec_timestamp ("wire_deadline",
-                                       exec_time),
-      GNUNET_PQ_result_spec_end
-    };
-
-    qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
-                                                   "get_deposit_without_wtid",
-                                                   params,
-                                                   rs2);
-    if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT == qs)
-    {
-      struct TALER_MerchantWireHashP wh;
-
-      if (0 == kyc->requirement_row)
-        kyc->ok = true; /* technically: unknown */
-      TALER_merchant_wire_signature_hash (payto_uri,
-                                          &wire_salt,
-                                          &wh);
-      GNUNET_PQ_cleanup_result (rs);
-      if (0 !=
-          GNUNET_memcmp (&wh,
-                         h_wire))
-        return GNUNET_DB_STATUS_SUCCESS_NO_RESULTS;
-    }
-    return qs;
-  }
-}
-
-
-/**
- * Obtain wire fee from database.
- *
- * @param cls closure
- * @param type type of wire transfer the fee applies for
- * @param date for which date do we want the fee?
- * @param[out] start_date when does the fee go into effect
- * @param[out] end_date when does the fee end being valid
- * @param[out] fees how high are the wire fees
- * @param[out] master_sig signature over the above by the exchange master key
- * @return status of the transaction
- */
-static enum GNUNET_DB_QueryStatus
-postgres_get_wire_fee (void *cls,
-                       const char *type,
-                       struct GNUNET_TIME_Timestamp date,
-                       struct GNUNET_TIME_Timestamp *start_date,
-                       struct GNUNET_TIME_Timestamp *end_date,
-                       struct TALER_WireFeeSet *fees,
-                       struct TALER_MasterSignatureP *master_sig)
-{
-  struct PostgresClosure *pg = cls;
-  struct GNUNET_PQ_QueryParam params[] = {
-    GNUNET_PQ_query_param_string (type),
-    GNUNET_PQ_query_param_timestamp (&date),
-    GNUNET_PQ_query_param_end
-  };
-  struct GNUNET_PQ_ResultSpec rs[] = {
-    GNUNET_PQ_result_spec_timestamp ("start_date",
-                                     start_date),
-    GNUNET_PQ_result_spec_timestamp ("end_date",
-                                     end_date),
-    TALER_PQ_RESULT_SPEC_AMOUNT ("wire_fee",
-                                 &fees->wire),
-    TALER_PQ_RESULT_SPEC_AMOUNT ("closing_fee",
-                                 &fees->closing),
-    GNUNET_PQ_result_spec_auto_from_type ("master_sig",
-                                          master_sig),
-    GNUNET_PQ_result_spec_end
-  };
-
-  return GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
-                                                   "get_wire_fee",
-                                                   params,
-                                                   rs);
-}
-
-
-/**
- * Obtain global fees from database.
- *
- * @param cls closure
- * @param date for which date do we want the fee?
- * @param[out] start_date when does the fee go into effect
- * @param[out] end_date when does the fee end being valid
- * @param[out] fees how high are the wire fees
- * @param[out] purse_timeout set to how long we keep unmerged purses
- * @param[out] history_expiration set to how long we keep account histories
- * @param[out] purse_account_limit set to the number of free purses per account
- * @param[out] master_sig signature over the above by the exchange master key
- * @return status of the transaction
- */
-static enum GNUNET_DB_QueryStatus
-postgres_get_global_fee (void *cls,
-                         struct GNUNET_TIME_Timestamp date,
-                         struct GNUNET_TIME_Timestamp *start_date,
-                         struct GNUNET_TIME_Timestamp *end_date,
-                         struct TALER_GlobalFeeSet *fees,
-                         struct GNUNET_TIME_Relative *purse_timeout,
-                         struct GNUNET_TIME_Relative *history_expiration,
-                         uint32_t *purse_account_limit,
-                         struct TALER_MasterSignatureP *master_sig)
-{
-  struct PostgresClosure *pg = cls;
-  struct GNUNET_PQ_QueryParam params[] = {
-    GNUNET_PQ_query_param_timestamp (&date),
-    GNUNET_PQ_query_param_end
-  };
-  struct GNUNET_PQ_ResultSpec rs[] = {
-    GNUNET_PQ_result_spec_timestamp ("start_date",
-                                     start_date),
-    GNUNET_PQ_result_spec_timestamp ("end_date",
-                                     end_date),
-    TALER_PQ_RESULT_SPEC_AMOUNT ("history_fee",
-                                 &fees->history),
-    TALER_PQ_RESULT_SPEC_AMOUNT ("account_fee",
-                                 &fees->account),
-    TALER_PQ_RESULT_SPEC_AMOUNT ("purse_fee",
-                                 &fees->purse),
-    GNUNET_PQ_result_spec_relative_time ("purse_timeout",
-                                         purse_timeout),
-    GNUNET_PQ_result_spec_relative_time ("history_expiration",
-                                         history_expiration),
-    GNUNET_PQ_result_spec_uint32 ("purse_account_limit",
-                                  purse_account_limit),
-    GNUNET_PQ_result_spec_auto_from_type ("master_sig",
-                                          master_sig),
-    GNUNET_PQ_result_spec_end
-  };
-
-  return GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
-                                                   "get_global_fee",
-                                                   params,
-                                                   rs);
-}
-
-
-/**
- * Closure for #global_fees_cb().
- */
-struct GlobalFeeContext
-{
-  /**
-   * Function to call for each global fee block.
-   */
-  TALER_EXCHANGEDB_GlobalFeeCallback cb;
-
-  /**
-   * Closure to give to @e rec.
-   */
-  void *cb_cls;
-
-  /**
-   * Plugin context.
-   */
-  struct PostgresClosure *pg;
-
-  /**
-   * Set to #GNUNET_SYSERR on error.
-   */
-  enum GNUNET_GenericReturnValue status;
-};
-
-
-/**
- * Function to be called with the results of a SELECT statement
- * that has returned @a num_results results.
- *
- * @param cls closure
- * @param result the postgres result
- * @param num_results the number of results in @a result
- */
-static void
-global_fees_cb (void *cls,
-                PGresult *result,
-                unsigned int num_results)
-{
-  struct GlobalFeeContext *gctx = cls;
-  struct PostgresClosure *pg = gctx->pg;
-
-  for (unsigned int i = 0; i<num_results; i++)
-  {
-    struct TALER_GlobalFeeSet fees;
-    struct GNUNET_TIME_Relative purse_timeout;
-    struct GNUNET_TIME_Relative history_expiration;
-    uint32_t purse_account_limit;
-    struct GNUNET_TIME_Timestamp start_date;
-    struct GNUNET_TIME_Timestamp end_date;
-    struct TALER_MasterSignatureP master_sig;
-    struct GNUNET_PQ_ResultSpec rs[] = {
-      GNUNET_PQ_result_spec_timestamp ("start_date",
-                                       &start_date),
-      GNUNET_PQ_result_spec_timestamp ("end_date",
-                                       &end_date),
-      TALER_PQ_RESULT_SPEC_AMOUNT ("history_fee",
-                                   &fees.history),
-      TALER_PQ_RESULT_SPEC_AMOUNT ("account_fee",
-                                   &fees.account),
-      TALER_PQ_RESULT_SPEC_AMOUNT ("purse_fee",
-                                   &fees.purse),
-      GNUNET_PQ_result_spec_relative_time ("purse_timeout",
-                                           &purse_timeout),
-      GNUNET_PQ_result_spec_relative_time ("history_expiration",
-                                           &history_expiration),
-      GNUNET_PQ_result_spec_uint32 ("purse_account_limit",
-                                    &purse_account_limit),
-      GNUNET_PQ_result_spec_auto_from_type ("master_sig",
-                                            &master_sig),
-      GNUNET_PQ_result_spec_end
-    };
-    if (GNUNET_OK !=
-        GNUNET_PQ_extract_result (result,
-                                  rs,
-                                  i))
-    {
-      GNUNET_break (0);
-      gctx->status = GNUNET_SYSERR;
-      break;
-    }
-    gctx->cb (gctx->cb_cls,
-              &fees,
-              purse_timeout,
-              history_expiration,
-              purse_account_limit,
-              start_date,
-              end_date,
-              &master_sig);
-    GNUNET_PQ_cleanup_result (rs);
-  }
-}
-
-
-/**
- * Obtain global fees from database.
- *
- * @param cls closure
- * @param cb function to call on each fee entry
- * @param cb_cls closure for @a cb
- * @return status of the transaction
- */
-static enum GNUNET_DB_QueryStatus
-postgres_get_global_fees (void *cls,
-                          TALER_EXCHANGEDB_GlobalFeeCallback cb,
-                          void *cb_cls)
-{
-  struct PostgresClosure *pg = cls;
-  struct GNUNET_TIME_Timestamp date
-    = GNUNET_TIME_absolute_to_timestamp (
-        GNUNET_TIME_absolute_subtract (
-          GNUNET_TIME_absolute_get (),
-          GNUNET_TIME_UNIT_YEARS));
-  struct GNUNET_PQ_QueryParam params[] = {
-    GNUNET_PQ_query_param_timestamp (&date),
-    GNUNET_PQ_query_param_end
-  };
-  struct GlobalFeeContext gctx = {
-    .cb = cb,
-    .cb_cls = cb_cls,
-    .pg = pg,
-    .status = GNUNET_OK
-  };
-
-  return GNUNET_PQ_eval_prepared_multi_select (pg->conn,
-                                               "get_global_fees",
-                                               params,
-                                               &global_fees_cb,
-                                               &gctx);
-}
-
-
-/**
- * Insert wire transfer fee into database.
- *
- * @param cls closure
- * @param type type of wire transfer this fee applies for
- * @param start_date when does the fee go into effect
- * @param end_date when does the fee end being valid
- * @param fees how high are the wire fees
- * @param master_sig signature over the above by the exchange master key
- * @return transaction status code
- */
-static enum GNUNET_DB_QueryStatus
-postgres_insert_wire_fee (void *cls,
-                          const char *type,
-                          struct GNUNET_TIME_Timestamp start_date,
-                          struct GNUNET_TIME_Timestamp end_date,
-                          const struct TALER_WireFeeSet *fees,
-                          const struct TALER_MasterSignatureP *master_sig)
-{
-  struct PostgresClosure *pg = cls;
-  struct GNUNET_PQ_QueryParam params[] = {
-    GNUNET_PQ_query_param_string (type),
-    GNUNET_PQ_query_param_timestamp (&start_date),
-    GNUNET_PQ_query_param_timestamp (&end_date),
-    TALER_PQ_query_param_amount (&fees->wire),
-    TALER_PQ_query_param_amount (&fees->closing),
-    GNUNET_PQ_query_param_auto_from_type (master_sig),
-    GNUNET_PQ_query_param_end
-  };
-  struct TALER_WireFeeSet wx;
-  struct TALER_MasterSignatureP sig;
-  struct GNUNET_TIME_Timestamp sd;
-  struct GNUNET_TIME_Timestamp ed;
-  enum GNUNET_DB_QueryStatus qs;
-
-  qs = postgres_get_wire_fee (pg,
-                              type,
-                              start_date,
-                              &sd,
-                              &ed,
-                              &wx,
-                              &sig);
-  if (qs < 0)
-    return qs;
-  if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT == qs)
-  {
-    if (0 != GNUNET_memcmp (&sig,
-                            master_sig))
-    {
-      GNUNET_break (0);
-      return GNUNET_DB_STATUS_HARD_ERROR;
-    }
-    if (0 !=
-        TALER_wire_fee_set_cmp (fees,
-                                &wx))
-    {
-      GNUNET_break (0);
-      return GNUNET_DB_STATUS_HARD_ERROR;
-    }
-    if ( (GNUNET_TIME_timestamp_cmp (sd,
-                                     !=,
-                                     start_date)) ||
-         (GNUNET_TIME_timestamp_cmp (ed,
-                                     !=,
-                                     end_date)) )
-    {
-      GNUNET_break (0);
-      return GNUNET_DB_STATUS_HARD_ERROR;
-    }
-    /* equal record already exists */
-    return GNUNET_DB_STATUS_SUCCESS_NO_RESULTS;
-  }
-
-  return GNUNET_PQ_eval_prepared_non_select (pg->conn,
-                                             "insert_wire_fee",
-                                             params);
-}
-
-
-/**
- * Insert global fee data into database.
- *
- * @param cls closure
- * @param start_date when does the fees go into effect
- * @param end_date when does the fees end being valid
- * @param fees how high is are the global fees
- * @param purse_timeout when do purses time out
- * @param history_expiration how long are account histories preserved
- * @param purse_account_limit how many purses are free per account
- * @param master_sig signature over the above by the exchange master key
- * @return transaction status code
- */
-static enum GNUNET_DB_QueryStatus
-postgres_insert_global_fee (void *cls,
-                            struct GNUNET_TIME_Timestamp start_date,
-                            struct GNUNET_TIME_Timestamp end_date,
-                            const struct TALER_GlobalFeeSet *fees,
-                            struct GNUNET_TIME_Relative purse_timeout,
-                            struct GNUNET_TIME_Relative history_expiration,
-                            uint32_t purse_account_limit,
-                            const struct TALER_MasterSignatureP *master_sig)
-{
-  struct PostgresClosure *pg = cls;
-  struct GNUNET_PQ_QueryParam params[] = {
-    GNUNET_PQ_query_param_timestamp (&start_date),
-    GNUNET_PQ_query_param_timestamp (&end_date),
-    TALER_PQ_query_param_amount (&fees->history),
-    TALER_PQ_query_param_amount (&fees->account),
-    TALER_PQ_query_param_amount (&fees->purse),
-    GNUNET_PQ_query_param_relative_time (&purse_timeout),
-    GNUNET_PQ_query_param_relative_time (&history_expiration),
-    GNUNET_PQ_query_param_uint32 (&purse_account_limit),
-    GNUNET_PQ_query_param_auto_from_type (master_sig),
-    GNUNET_PQ_query_param_end
-  };
-  struct TALER_GlobalFeeSet wx;
-  struct TALER_MasterSignatureP sig;
-  struct GNUNET_TIME_Timestamp sd;
-  struct GNUNET_TIME_Timestamp ed;
-  enum GNUNET_DB_QueryStatus qs;
-  struct GNUNET_TIME_Relative pt;
-  struct GNUNET_TIME_Relative he;
-  uint32_t pal;
-
-  qs = postgres_get_global_fee (pg,
-                                start_date,
-                                &sd,
-                                &ed,
-                                &wx,
-                                &pt,
-                                &he,
-                                &pal,
-                                &sig);
-  if (qs < 0)
-    return qs;
-  if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT == qs)
-  {
-    if (0 != GNUNET_memcmp (&sig,
-                            master_sig))
-    {
-      GNUNET_break (0);
-      return GNUNET_DB_STATUS_HARD_ERROR;
-    }
-    if (0 !=
-        TALER_global_fee_set_cmp (fees,
-                                  &wx))
-    {
-      GNUNET_break (0);
-      return GNUNET_DB_STATUS_HARD_ERROR;
-    }
-    if ( (GNUNET_TIME_timestamp_cmp (sd,
-                                     !=,
-                                     start_date)) ||
-         (GNUNET_TIME_timestamp_cmp (ed,
-                                     !=,
-                                     end_date)) )
-    {
-      GNUNET_break (0);
-      return GNUNET_DB_STATUS_HARD_ERROR;
-    }
-    if ( (GNUNET_TIME_relative_cmp (purse_timeout,
-                                    !=,
-                                    pt)) ||
-         (GNUNET_TIME_relative_cmp (history_expiration,
-                                    !=,
-                                    he)) )
-    {
-      GNUNET_break (0);
-      return GNUNET_DB_STATUS_HARD_ERROR;
-    }
-    if (purse_account_limit != pal)
-    {
-      GNUNET_break (0);
-      return GNUNET_DB_STATUS_HARD_ERROR;
-    }
-    /* equal record already exists */
-    return GNUNET_DB_STATUS_SUCCESS_NO_RESULTS;
-  }
-
-  return GNUNET_PQ_eval_prepared_non_select (pg->conn,
-                                             "insert_global_fee",
-                                             params);
-}
-
-
-/**
- * Insert reserve close operation into database.
- *
- * @param cls closure
- * @param reserve_pub which reserve is this about?
- * @param execution_date when did we perform the transfer?
- * @param receiver_account to which account do we transfer?
- * @param wtid wire transfer details
- * @param amount_with_fee amount we charged to the reserve
- * @param closing_fee how high is the closing fee
- * @param close_request_row identifies explicit close request, 0 for none
- * @return transaction status code
- */
-static enum GNUNET_DB_QueryStatus
-postgres_insert_reserve_closed (
-  void *cls,
-  const struct TALER_ReservePublicKeyP *reserve_pub,
-  struct GNUNET_TIME_Timestamp execution_date,
-  const char *receiver_account,
-  const struct TALER_WireTransferIdentifierRawP *wtid,
-  const struct TALER_Amount *amount_with_fee,
-  const struct TALER_Amount *closing_fee,
-  uint64_t close_request_row)
-{
-  struct PostgresClosure *pg = cls;
-  struct TALER_EXCHANGEDB_Reserve reserve;
-  enum GNUNET_DB_QueryStatus qs;
-  struct TALER_PaytoHashP h_payto;
-
-  TALER_payto_hash (receiver_account,
-                    &h_payto);
-  {
-    struct GNUNET_PQ_QueryParam params[] = {
-      GNUNET_PQ_query_param_auto_from_type (reserve_pub),
-      GNUNET_PQ_query_param_timestamp (&execution_date),
-      GNUNET_PQ_query_param_auto_from_type (wtid),
-      GNUNET_PQ_query_param_auto_from_type (&h_payto),
-      TALER_PQ_query_param_amount (amount_with_fee),
-      TALER_PQ_query_param_amount (closing_fee),
-      GNUNET_PQ_query_param_uint64 (&close_request_row),
-      GNUNET_PQ_query_param_end
-    };
-
-    qs = GNUNET_PQ_eval_prepared_non_select (pg->conn,
-                                             "reserves_close_insert",
-                                             params);
-  }
-  if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != qs)
-    return qs;
-
-  /* update reserve balance */
-  reserve.pub = *reserve_pub;
-  if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
-      (qs = postgres_reserves_get (cls,
-                                   &reserve)))
-  {
-    /* Existence should have been checked before we got here... */
-    GNUNET_break (GNUNET_DB_STATUS_SOFT_ERROR == qs);
-    if (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS == qs)
-      qs = GNUNET_DB_STATUS_HARD_ERROR;
-    return qs;
-  }
-  {
-    enum TALER_AmountArithmeticResult ret;
-
-    ret = TALER_amount_subtract (&reserve.balance,
-                                 &reserve.balance,
-                                 amount_with_fee);
-    if (ret < 0)
-    {
-      /* The reserve history was checked to make sure there is enough of a 
balance
-         left before we tried this; however, concurrent operations may have 
changed
-         the situation by now.  We should re-try the transaction.  */
-      GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                  "Closing of reserve `%s' refused due to balance mismatch. 
Retrying.\n",
-                  TALER_B2S (reserve_pub));
-      return GNUNET_DB_STATUS_HARD_ERROR;
-    }
-    GNUNET_break (TALER_AAR_RESULT_ZERO == ret);
-  }
-  return reserves_update (cls,
-                          &reserve);
-}
-
-
-/**
- * Function called to insert wire transfer commit data into the DB.
- *
- * @param cls closure
- * @param type type of the wire transfer (i.e. "iban")
- * @param buf buffer with wire transfer preparation data
- * @param buf_size number of bytes in @a buf
- * @return query status code
- */
-static enum GNUNET_DB_QueryStatus
-postgres_wire_prepare_data_insert (void *cls,
-                                   const char *type,
-                                   const char *buf,
-                                   size_t buf_size)
-{
-  struct PostgresClosure *pg = cls;
-  struct GNUNET_PQ_QueryParam params[] = {
-    GNUNET_PQ_query_param_string (type),
-    GNUNET_PQ_query_param_fixed_size (buf, buf_size),
-    GNUNET_PQ_query_param_end
-  };
-
-  return GNUNET_PQ_eval_prepared_non_select (pg->conn,
-                                             "wire_prepare_data_insert",
-                                             params);
-}
-
-
-/**
- * Function called to mark wire transfer commit data as finished.
- *
- * @param cls closure
- * @param rowid which entry to mark as finished
- * @return transaction status code
- */
-static enum GNUNET_DB_QueryStatus
-postgres_wire_prepare_data_mark_finished (
-  void *cls,
-  uint64_t rowid)
-{
-  struct PostgresClosure *pg = cls;
-  struct GNUNET_PQ_QueryParam params[] = {
-    GNUNET_PQ_query_param_uint64 (&rowid),
-    GNUNET_PQ_query_param_end
-  };
-
-  return GNUNET_PQ_eval_prepared_non_select (pg->conn,
-                                             "wire_prepare_data_mark_done",
-                                             params);
-}
-
-
-/**
- * Function called to mark wire transfer commit data as failed.
- *
- * @param cls closure
- * @param rowid which entry to mark as failed
- * @return transaction status code
- */
-static enum GNUNET_DB_QueryStatus
-postgres_wire_prepare_data_mark_failed (
-  void *cls,
-  uint64_t rowid)
-{
-  struct PostgresClosure *pg = cls;
-  struct GNUNET_PQ_QueryParam params[] = {
-    GNUNET_PQ_query_param_uint64 (&rowid),
-    GNUNET_PQ_query_param_end
-  };
-
-  return GNUNET_PQ_eval_prepared_non_select (pg->conn,
-                                             "wire_prepare_data_mark_failed",
-                                             params);
-}
-
-
-/**
- * Closure for #prewire_cb().
- */
-struct PrewireContext
-{
-  /**
-   * Function to call on each result.
-   */
-  TALER_EXCHANGEDB_WirePreparationIterator cb;
-
-  /**
-   * Closure for @a cb.
-   */
-  void *cb_cls;
-
-  /**
-   * #GNUNET_OK if everything went fine.
-   */
-  enum GNUNET_GenericReturnValue status;
-};
-
-
-/**
- * Invoke the callback for each result.
- *
- * @param cls a `struct MissingWireContext *`
- * @param result SQL result
- * @param num_results number of rows in @a result
- */
-static void
-prewire_cb (void *cls,
-            PGresult *result,
-            unsigned int num_results)
-{
-  struct PrewireContext *pc = cls;
-
-  for (unsigned int i = 0; i < num_results; i++)
-  {
-    uint64_t prewire_uuid;
-    char *wire_method;
-    void *buf = NULL;
-    size_t buf_size;
-    struct GNUNET_PQ_ResultSpec rs[] = {
-      GNUNET_PQ_result_spec_uint64 ("prewire_uuid",
-                                    &prewire_uuid),
-      GNUNET_PQ_result_spec_string ("wire_method",
-                                    &wire_method),
-      GNUNET_PQ_result_spec_variable_size ("buf",
-                                           &buf,
-                                           &buf_size),
-      GNUNET_PQ_result_spec_end
-    };
-
-    if (GNUNET_OK !=
-        GNUNET_PQ_extract_result (result,
-                                  rs,
-                                  i))
-    {
-      GNUNET_break (0);
-      pc->status = GNUNET_SYSERR;
-      return;
-    }
-    pc->cb (pc->cb_cls,
-            prewire_uuid,
-            wire_method,
-            buf,
-            buf_size);
-    GNUNET_PQ_cleanup_result (rs);
-  }
-}
-
-
-/**
- * Function called to get an unfinished wire transfer
- * preparation data. Fetches at most one item.
- *
- * @param cls closure
- * @param start_row offset to query table at
- * @param limit maximum number of results to return
- * @param cb function to call for ONE unfinished item
- * @param cb_cls closure for @a cb
- * @return transaction status code
- */
-static enum GNUNET_DB_QueryStatus
-postgres_wire_prepare_data_get (void *cls,
-                                uint64_t start_row,
-                                uint64_t limit,
-                                TALER_EXCHANGEDB_WirePreparationIterator cb,
-                                void *cb_cls)
-{
-  struct PostgresClosure *pg = cls;
-  struct GNUNET_PQ_QueryParam params[] = {
-    GNUNET_PQ_query_param_uint64 (&start_row),
-    GNUNET_PQ_query_param_uint64 (&limit),
-    GNUNET_PQ_query_param_end
-  };
-  struct PrewireContext pc = {
-    .cb = cb,
-    .cb_cls = cb_cls,
-    .status = GNUNET_OK
-  };
-  enum GNUNET_DB_QueryStatus qs;
-
-  qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn,
-                                             "wire_prepare_data_get",
-                                             params,
-                                             &prewire_cb,
-                                             &pc);
-  if (GNUNET_OK != pc.status)
-    return GNUNET_DB_STATUS_HARD_ERROR;
-  return qs;
-}
-
-
-/**
- * Starts a READ COMMITTED transaction where we transiently violate the foreign
- * constraints on the "wire_out" table as we insert aggregations
- * and only add the wire transfer out at the end.
- *
- * @param cls the @e cls of this struct with the plugin-specific state
- * @return #GNUNET_OK on success
- */
-static enum GNUNET_GenericReturnValue
-postgres_start_deferred_wire_out (void *cls)
-{
-  struct PostgresClosure *pg = cls;
-  struct GNUNET_PQ_ExecuteStatement es[] = {
-    GNUNET_PQ_make_execute (
-      "START TRANSACTION ISOLATION LEVEL READ COMMITTED;"),
-    GNUNET_PQ_make_execute ("SET CONSTRAINTS ALL DEFERRED;"),
-    GNUNET_PQ_EXECUTE_STATEMENT_END
-  };
-
-  if (GNUNET_SYSERR ==
-      TEH_PG_preflight (pg))
-    return GNUNET_SYSERR;
-  if (GNUNET_OK !=
-      GNUNET_PQ_exec_statements (pg->conn,
-                                 es))
-  {
-    TALER_LOG_ERROR (
-      "Failed to defer wire_out_ref constraint on transaction\n");
-    GNUNET_break (0);
-    TEH_PG_rollback (pg);
-    return GNUNET_SYSERR;
-  }
-  pg->transaction_name = "deferred wire out";
-  GNUNET_log (GNUNET_ERROR_TYPE_INFO,
-              "Starting READ COMMITTED DEFERRED transaction `%s'\n",
-              pg->transaction_name);
-  return GNUNET_OK;
-}
-
-
-/**
- * Store information about an outgoing wire transfer that was executed.
- *
- * @param cls closure
- * @param date time of the wire transfer
- * @param wtid subject of the wire transfer
- * @param h_payto identifies the receiver account of the wire transfer
- * @param exchange_account_section configuration section of the exchange 
specifying the
- *        exchange's bank account being used
- * @param amount amount that was transmitted
- * @return transaction status code
- */
-static enum GNUNET_DB_QueryStatus
-postgres_store_wire_transfer_out (
-  void *cls,
-  struct GNUNET_TIME_Timestamp date,
-  const struct TALER_WireTransferIdentifierRawP *wtid,
-  const struct TALER_PaytoHashP *h_payto,
-  const char *exchange_account_section,
-  const struct TALER_Amount *amount)
-{
-  struct PostgresClosure *pg = cls;
-  struct GNUNET_PQ_QueryParam params[] = {
-    GNUNET_PQ_query_param_timestamp (&date),
-    GNUNET_PQ_query_param_auto_from_type (wtid),
-    GNUNET_PQ_query_param_auto_from_type (h_payto),
-    GNUNET_PQ_query_param_string (exchange_account_section),
-    TALER_PQ_query_param_amount (amount),
-    GNUNET_PQ_query_param_end
-  };
-
-  return GNUNET_PQ_eval_prepared_non_select (pg->conn,
-                                             "insert_wire_out",
-                                             params);
-}
-
-
-/**
- * Function called to perform "garbage collection" on the
- * database, expiring records we no longer require.
- *
- * @param cls closure
- * @return #GNUNET_OK on success,
- *         #GNUNET_SYSERR on DB errors
- */
-static enum GNUNET_GenericReturnValue
-postgres_gc (void *cls)
-{
-  struct PostgresClosure *pg = cls;
-  struct GNUNET_TIME_Absolute now = GNUNET_TIME_absolute_get ();
-  struct GNUNET_TIME_Absolute long_ago;
-  struct GNUNET_PQ_QueryParam params[] = {
-    GNUNET_PQ_query_param_absolute_time (&long_ago),
-    GNUNET_PQ_query_param_absolute_time (&now),
-    GNUNET_PQ_query_param_end
-  };
-  struct GNUNET_PQ_Context *conn;
-  enum GNUNET_GenericReturnValue ret;
-
-  /* Keep wire fees for 10 years, that should always
-     be enough _and_ they are tiny so it does not
-     matter to make this tight */
-  long_ago = GNUNET_TIME_absolute_subtract (
-    now,
-    GNUNET_TIME_relative_multiply (
-      GNUNET_TIME_UNIT_YEARS,
-      10));
-  {
-    struct GNUNET_PQ_ExecuteStatement es[] = {
-      GNUNET_PQ_make_try_execute ("SET search_path TO exchange;"),
-      GNUNET_PQ_EXECUTE_STATEMENT_END
-    };
-    struct GNUNET_PQ_PreparedStatement ps[] = {
-      /* Used in #postgres_gc() */
-      GNUNET_PQ_make_prepare ("run_gc",
-                              "CALL"
-                              " exchange_do_gc"
-                              " ($1,$2);"),
-      GNUNET_PQ_PREPARED_STATEMENT_END
-    };
-
-    conn = GNUNET_PQ_connect_with_cfg (pg->cfg,
-                                       "exchangedb-postgres",
-                                       NULL,
-                                       es,
-                                       ps);
-  }
-  if (NULL == conn)
-    return GNUNET_SYSERR;
-  ret = GNUNET_OK;
-  if (0 > GNUNET_PQ_eval_prepared_non_select (conn,
-                                              "run_gc",
-                                              params))
-    ret = GNUNET_SYSERR;
-  GNUNET_PQ_disconnect (conn);
-  return ret;
-}
-
-
-/**
- * Closure for #deposit_serial_helper_cb().
- */
-struct DepositSerialContext
-{
-
-  /**
-   * Callback to call.
-   */
-  TALER_EXCHANGEDB_DepositCallback cb;
-
-  /**
-   * Closure for @e cb.
-   */
-  void *cb_cls;
-
-  /**
-   * Plugin context.
-   */
-  struct PostgresClosure *pg;
-
-  /**
-   * Status code, set to #GNUNET_SYSERR on hard errors.
-   */
-  enum GNUNET_GenericReturnValue status;
-};
-
-
-/**
- * Helper function to be called with the results of a SELECT statement
- * that has returned @a num_results results.
- *
- * @param cls closure of type `struct DepositSerialContext`
- * @param result the postgres result
- * @param num_results the number of results in @a result
- */
-static void
-deposit_serial_helper_cb (void *cls,
-                          PGresult *result,
-                          unsigned int num_results)
-{
-  struct DepositSerialContext *dsc = cls;
-  struct PostgresClosure *pg = dsc->pg;
-
-  for (unsigned int i = 0; i<num_results; i++)
-  {
-    struct TALER_EXCHANGEDB_Deposit deposit;
-    struct GNUNET_TIME_Timestamp exchange_timestamp;
-    struct TALER_DenominationPublicKey denom_pub;
-    bool done;
-    uint64_t rowid;
-    struct GNUNET_PQ_ResultSpec rs[] = {
-      TALER_PQ_RESULT_SPEC_AMOUNT ("amount_with_fee",
-                                   &deposit.amount_with_fee),
-      GNUNET_PQ_result_spec_timestamp ("wallet_timestamp",
-                                       &deposit.timestamp),
-      GNUNET_PQ_result_spec_timestamp ("exchange_timestamp",
-                                       &exchange_timestamp),
-      GNUNET_PQ_result_spec_auto_from_type ("merchant_pub",
-                                            &deposit.merchant_pub),
-      TALER_PQ_result_spec_denom_pub ("denom_pub",
-                                      &denom_pub),
-      GNUNET_PQ_result_spec_auto_from_type ("coin_pub",
-                                            &deposit.coin.coin_pub),
-      GNUNET_PQ_result_spec_allow_null (
-        GNUNET_PQ_result_spec_auto_from_type ("age_commitment_hash",
-                                              &deposit.coin.h_age_commitment),
-        &deposit.coin.no_age_commitment),
-      GNUNET_PQ_result_spec_auto_from_type ("coin_sig",
-                                            &deposit.csig),
-      GNUNET_PQ_result_spec_timestamp ("refund_deadline",
-                                       &deposit.refund_deadline),
-      GNUNET_PQ_result_spec_timestamp ("wire_deadline",
-                                       &deposit.wire_deadline),
-      GNUNET_PQ_result_spec_auto_from_type ("h_contract_terms",
-                                            &deposit.h_contract_terms),
-      GNUNET_PQ_result_spec_auto_from_type ("wire_salt",
-                                            &deposit.wire_salt),
-      GNUNET_PQ_result_spec_string ("receiver_wire_account",
-                                    &deposit.receiver_wire_account),
-      GNUNET_PQ_result_spec_bool ("done",
-                                  &done),
-      GNUNET_PQ_result_spec_uint64 ("deposit_serial_id",
-                                    &rowid),
-      GNUNET_PQ_result_spec_end
-    };
-    enum GNUNET_GenericReturnValue ret;
-
-    memset (&deposit,
-            0,
-            sizeof (deposit));
-    if (GNUNET_OK !=
-        GNUNET_PQ_extract_result (result,
-                                  rs,
-                                  i))
-    {
-      GNUNET_break (0);
-      dsc->status = GNUNET_SYSERR;
-      return;
-    }
-    ret = dsc->cb (dsc->cb_cls,
-                   rowid,
-                   exchange_timestamp,
-                   &deposit,
-                   &denom_pub,
-                   done);
-    GNUNET_PQ_cleanup_result (rs);
-    if (GNUNET_OK != ret)
-      break;
-  }
-}
-
-
-/**
- * Select deposits above @a serial_id in monotonically increasing
- * order.
- *
- * @param cls closure
- * @param serial_id highest serial ID to exclude (select strictly larger)
- * @param cb function to call on each result
- * @param cb_cls closure for @a cb
- * @return transaction status code
- */
-static enum GNUNET_DB_QueryStatus
-postgres_select_deposits_above_serial_id (
-  void *cls,
-  uint64_t serial_id,
-  TALER_EXCHANGEDB_DepositCallback cb,
-  void *cb_cls)
-{
-  struct PostgresClosure *pg = cls;
-  struct GNUNET_PQ_QueryParam params[] = {
-    GNUNET_PQ_query_param_uint64 (&serial_id),
-    GNUNET_PQ_query_param_end
-  };
-  struct DepositSerialContext dsc = {
-    .cb = cb,
-    .cb_cls = cb_cls,
-    .pg = pg,
-    .status = GNUNET_OK
-  };
-  enum GNUNET_DB_QueryStatus qs;
-
-  qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn,
-                                             "audit_get_deposits_incr",
-                                             params,
-                                             &deposit_serial_helper_cb,
-                                             &dsc);
-  if (GNUNET_OK != dsc.status)
-    return GNUNET_DB_STATUS_HARD_ERROR;
-  return qs;
-}
-
-
-/**
- * Closure for #purse_deposit_serial_helper_cb().
- */
-struct HistoryRequestSerialContext
-{
-
-  /**
-   * Callback to call.
-   */
-  TALER_EXCHANGEDB_HistoryRequestCallback cb;
-
-  /**
-   * Closure for @e cb.
-   */
-  void *cb_cls;
-
-  /**
-   * Plugin context.
-   */
-  struct PostgresClosure *pg;
-
-  /**
-   * Status code, set to #GNUNET_SYSERR on hard errors.
-   */
-  enum GNUNET_GenericReturnValue status;
-};
-
-
-/**
- * Helper function to be called with the results of a SELECT statement
- * that has returned @a num_results results.
- *
- * @param cls closure of type `struct HistoryRequestSerialContext`
- * @param result the postgres result
- * @param num_results the number of results in @a result
- */
-static void
-history_request_serial_helper_cb (void *cls,
-                                  PGresult *result,
-                                  unsigned int num_results)
-{
-  struct HistoryRequestSerialContext *dsc = cls;
-  struct PostgresClosure *pg = dsc->pg;
-
-  for (unsigned int i = 0; i<num_results; i++)
-  {
-    uint64_t rowid;
-    struct TALER_Amount history_fee;
-    struct GNUNET_TIME_Timestamp ts;
-    struct TALER_ReservePublicKeyP reserve_pub;
-    struct TALER_ReserveSignatureP reserve_sig;
-    struct GNUNET_PQ_ResultSpec rs[] = {
-      TALER_PQ_RESULT_SPEC_AMOUNT ("history_fee",
-                                   &history_fee),
-      GNUNET_PQ_result_spec_auto_from_type ("reserve_pub",
-                                            &reserve_pub),
-      GNUNET_PQ_result_spec_auto_from_type ("reserve_sig",
-                                            &reserve_sig),
-      GNUNET_PQ_result_spec_uint64 ("history_request_serial_id",
-                                    &rowid),
-      GNUNET_PQ_result_spec_timestamp ("request_timestamp",
-                                       &ts),
-      GNUNET_PQ_result_spec_end
-    };
-    enum GNUNET_GenericReturnValue ret;
-
-    if (GNUNET_OK !=
-        GNUNET_PQ_extract_result (result,
-                                  rs,
-                                  i))
-    {
-      GNUNET_break (0);
-      dsc->status = GNUNET_SYSERR;
-      return;
-    }
-    ret = dsc->cb (dsc->cb_cls,
-                   rowid,
-                   &history_fee,
-                   ts,
-                   &reserve_pub,
-                   &reserve_sig);
-    GNUNET_PQ_cleanup_result (rs);
-    if (GNUNET_OK != ret)
-      break;
-  }
-}
-
-
-/**
- * Select history requests above @a serial_id in monotonically increasing
- * order.
- *
- * @param cls closure
- * @param serial_id highest serial ID to exclude (select strictly larger)
- * @param cb function to call on each result
- * @param cb_cls closure for @a cb
- * @return transaction status code
- */
-static enum GNUNET_DB_QueryStatus
-postgres_select_history_requests_above_serial_id (
-  void *cls,
-  uint64_t serial_id,
-  TALER_EXCHANGEDB_HistoryRequestCallback cb,
-  void *cb_cls)
+postgres_insert_wire_fee (void *cls,
+                          const char *type,
+                          struct GNUNET_TIME_Timestamp start_date,
+                          struct GNUNET_TIME_Timestamp end_date,
+                          const struct TALER_WireFeeSet *fees,
+                          const struct TALER_MasterSignatureP *master_sig)
 {
   struct PostgresClosure *pg = cls;
   struct GNUNET_PQ_QueryParam params[] = {
-    GNUNET_PQ_query_param_uint64 (&serial_id),
+    GNUNET_PQ_query_param_string (type),
+    GNUNET_PQ_query_param_timestamp (&start_date),
+    GNUNET_PQ_query_param_timestamp (&end_date),
+    TALER_PQ_query_param_amount (&fees->wire),
+    TALER_PQ_query_param_amount (&fees->closing),
+    GNUNET_PQ_query_param_auto_from_type (master_sig),
     GNUNET_PQ_query_param_end
   };
-  struct HistoryRequestSerialContext dsc = {
-    .cb = cb,
-    .cb_cls = cb_cls,
-    .pg = pg,
-    .status = GNUNET_OK
-  };
+  struct TALER_WireFeeSet wx;
+  struct TALER_MasterSignatureP sig;
+  struct GNUNET_TIME_Timestamp sd;
+  struct GNUNET_TIME_Timestamp ed;
   enum GNUNET_DB_QueryStatus qs;
 
-  qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn,
-                                             "audit_get_history_requests_incr",
-                                             params,
-                                             &history_request_serial_helper_cb,
-                                             &dsc);
-  if (GNUNET_OK != dsc.status)
-    return GNUNET_DB_STATUS_HARD_ERROR;
-  return qs;
-}
-
-
-/**
- * Closure for #purse_decision_serial_helper_cb().
- */
-struct PurseDecisionSerialContext
-{
-
-  /**
-   * Callback to call.
-   */
-  TALER_EXCHANGEDB_PurseDecisionCallback cb;
-
-  /**
-   * Closure for @e cb.
-   */
-  void *cb_cls;
-
-  /**
-   * Plugin context.
-   */
-  struct PostgresClosure *pg;
-
-  /**
-   * Status code, set to #GNUNET_SYSERR on hard errors.
-   */
-  enum GNUNET_GenericReturnValue status;
-};
-
-
-/**
- * Helper function to be called with the results of a SELECT statement
- * that has returned @a num_results results.
- *
- * @param cls closure of type `struct PurseRefundSerialContext`
- * @param result the postgres result
- * @param num_results the number of results in @a result
- */
-static void
-purse_decision_serial_helper_cb (void *cls,
-                                 PGresult *result,
-                                 unsigned int num_results)
-{
-  struct PurseDecisionSerialContext *dsc = cls;
-  struct PostgresClosure *pg = dsc->pg;
-
-  for (unsigned int i = 0; i<num_results; i++)
+  qs = postgres_get_wire_fee (pg,
+                              type,
+                              start_date,
+                              &sd,
+                              &ed,
+                              &wx,
+                              &sig);
+  if (qs < 0)
+    return qs;
+  if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT == qs)
   {
-    struct TALER_PurseContractPublicKeyP purse_pub;
-    struct TALER_ReservePublicKeyP reserve_pub;
-    bool no_reserve = true;
-    uint64_t rowid;
-    struct TALER_Amount val;
-    struct GNUNET_PQ_ResultSpec rs[] = {
-      GNUNET_PQ_result_spec_auto_from_type ("purse_pub",
-                                            &purse_pub),
-      GNUNET_PQ_result_spec_allow_null (
-        GNUNET_PQ_result_spec_auto_from_type ("reserve_pub",
-                                              &reserve_pub),
-        &no_reserve),
-      TALER_PQ_RESULT_SPEC_AMOUNT ("amount_with_fee",
-                                   &val),
-      GNUNET_PQ_result_spec_uint64 ("purse_deposit_serial_id",
-                                    &rowid),
-      GNUNET_PQ_result_spec_end
-    };
-    enum GNUNET_GenericReturnValue ret;
-
-    if (GNUNET_OK !=
-        GNUNET_PQ_extract_result (result,
-                                  rs,
-                                  i))
+    if (0 != GNUNET_memcmp (&sig,
+                            master_sig))
     {
       GNUNET_break (0);
-      dsc->status = GNUNET_SYSERR;
-      return;
+      return GNUNET_DB_STATUS_HARD_ERROR;
     }
-    ret = dsc->cb (dsc->cb_cls,
-                   rowid,
-                   &purse_pub,
-                   no_reserve ? NULL : &reserve_pub,
-                   &val);
-    GNUNET_PQ_cleanup_result (rs);
-    if (GNUNET_OK != ret)
-      break;
+    if (0 !=
+        TALER_wire_fee_set_cmp (fees,
+                                &wx))
+    {
+      GNUNET_break (0);
+      return GNUNET_DB_STATUS_HARD_ERROR;
+    }
+    if ( (GNUNET_TIME_timestamp_cmp (sd,
+                                     !=,
+                                     start_date)) ||
+         (GNUNET_TIME_timestamp_cmp (ed,
+                                     !=,
+                                     end_date)) )
+    {
+      GNUNET_break (0);
+      return GNUNET_DB_STATUS_HARD_ERROR;
+    }
+    /* equal record already exists */
+    return GNUNET_DB_STATUS_SUCCESS_NO_RESULTS;
   }
+
+  return GNUNET_PQ_eval_prepared_non_select (pg->conn,
+                                             "insert_wire_fee",
+                                             params);
 }
 
 
 /**
- * Select purse decisions above @a serial_id in monotonically increasing
- * order.
+ * Insert global fee data into database.
  *
  * @param cls closure
- * @param serial_id highest serial ID to exclude (select strictly larger)
- * @param refunded which refund status to select for
- * @param cb function to call on each result
- * @param cb_cls closure for @a cb
+ * @param start_date when does the fees go into effect
+ * @param end_date when does the fees end being valid
+ * @param fees how high is are the global fees
+ * @param purse_timeout when do purses time out
+ * @param history_expiration how long are account histories preserved
+ * @param purse_account_limit how many purses are free per account
+ * @param master_sig signature over the above by the exchange master key
  * @return transaction status code
  */
 static enum GNUNET_DB_QueryStatus
-postgres_select_purse_decisions_above_serial_id (
-  void *cls,
-  uint64_t serial_id,
-  bool refunded,
-  TALER_EXCHANGEDB_PurseDecisionCallback cb,
-  void *cb_cls)
+postgres_insert_global_fee (void *cls,
+                            struct GNUNET_TIME_Timestamp start_date,
+                            struct GNUNET_TIME_Timestamp end_date,
+                            const struct TALER_GlobalFeeSet *fees,
+                            struct GNUNET_TIME_Relative purse_timeout,
+                            struct GNUNET_TIME_Relative history_expiration,
+                            uint32_t purse_account_limit,
+                            const struct TALER_MasterSignatureP *master_sig)
 {
   struct PostgresClosure *pg = cls;
   struct GNUNET_PQ_QueryParam params[] = {
-    GNUNET_PQ_query_param_uint64 (&serial_id),
-    GNUNET_PQ_query_param_bool (refunded),
+    GNUNET_PQ_query_param_timestamp (&start_date),
+    GNUNET_PQ_query_param_timestamp (&end_date),
+    TALER_PQ_query_param_amount (&fees->history),
+    TALER_PQ_query_param_amount (&fees->account),
+    TALER_PQ_query_param_amount (&fees->purse),
+    GNUNET_PQ_query_param_relative_time (&purse_timeout),
+    GNUNET_PQ_query_param_relative_time (&history_expiration),
+    GNUNET_PQ_query_param_uint32 (&purse_account_limit),
+    GNUNET_PQ_query_param_auto_from_type (master_sig),
     GNUNET_PQ_query_param_end
   };
-  struct PurseDecisionSerialContext dsc = {
-    .cb = cb,
-    .cb_cls = cb_cls,
-    .pg = pg,
-    .status = GNUNET_OK
-  };
+  struct TALER_GlobalFeeSet wx;
+  struct TALER_MasterSignatureP sig;
+  struct GNUNET_TIME_Timestamp sd;
+  struct GNUNET_TIME_Timestamp ed;
   enum GNUNET_DB_QueryStatus qs;
+  struct GNUNET_TIME_Relative pt;
+  struct GNUNET_TIME_Relative he;
+  uint32_t pal;
 
-  qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn,
-                                             "audit_get_purse_decisions_incr",
-                                             params,
-                                             &purse_decision_serial_helper_cb,
-                                             &dsc);
-  if (GNUNET_OK != dsc.status)
-    return GNUNET_DB_STATUS_HARD_ERROR;
-  return qs;
-}
-
-
-/**
- * Closure for #purse_refund_coin_helper_cb().
- */
-struct PurseRefundCoinContext
-{
-
-  /**
-   * Callback to call.
-   */
-  TALER_EXCHANGEDB_PurseRefundCoinCallback cb;
-
-  /**
-   * Closure for @e cb.
-   */
-  void *cb_cls;
-
-  /**
-   * Plugin context.
-   */
-  struct PostgresClosure *pg;
-
-  /**
-   * Status code, set to #GNUNET_SYSERR on hard errors.
-   */
-  enum GNUNET_GenericReturnValue status;
-};
-
-
-/**
- * Helper function to be called with the results of a SELECT statement
- * that has returned @a num_results results.
- *
- * @param cls closure of type `struct PurseRefundCoinContext`
- * @param result the postgres result
- * @param num_results the number of results in @a result
- */
-static void
-purse_refund_coin_helper_cb (void *cls,
-                             PGresult *result,
-                             unsigned int num_results)
-{
-  struct PurseRefundCoinContext *dsc = cls;
-  struct PostgresClosure *pg = dsc->pg;
-
-  for (unsigned int i = 0; i<num_results; i++)
-  {
-    struct TALER_Amount amount_with_fee;
-    struct TALER_CoinSpendPublicKeyP coin_pub;
-    struct TALER_DenominationPublicKey denom_pub;
-    uint64_t rowid;
-    struct GNUNET_PQ_ResultSpec rs[] = {
-      TALER_PQ_result_spec_denom_pub ("denom_pub",
-                                      &denom_pub),
-      TALER_PQ_RESULT_SPEC_AMOUNT ("amount_with_fee",
-                                   &amount_with_fee),
-      GNUNET_PQ_result_spec_auto_from_type ("coin_pub",
-                                            &coin_pub),
-      GNUNET_PQ_result_spec_uint64 ("purse_deposit_serial_id",
-                                    &rowid),
-      GNUNET_PQ_result_spec_end
-    };
-    enum GNUNET_GenericReturnValue ret;
-
-    if (GNUNET_OK !=
-        GNUNET_PQ_extract_result (result,
-                                  rs,
-                                  i))
+  qs = postgres_get_global_fee (pg,
+                                start_date,
+                                &sd,
+                                &ed,
+                                &wx,
+                                &pt,
+                                &he,
+                                &pal,
+                                &sig);
+  if (qs < 0)
+    return qs;
+  if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT == qs)
+  {
+    if (0 != GNUNET_memcmp (&sig,
+                            master_sig))
     {
       GNUNET_break (0);
-      dsc->status = GNUNET_SYSERR;
-      return;
+      return GNUNET_DB_STATUS_HARD_ERROR;
     }
-    ret = dsc->cb (dsc->cb_cls,
-                   rowid,
-                   &amount_with_fee,
-                   &coin_pub,
-                   &denom_pub);
-    GNUNET_PQ_cleanup_result (rs);
-    if (GNUNET_OK != ret)
-      break;
+    if (0 !=
+        TALER_global_fee_set_cmp (fees,
+                                  &wx))
+    {
+      GNUNET_break (0);
+      return GNUNET_DB_STATUS_HARD_ERROR;
+    }
+    if ( (GNUNET_TIME_timestamp_cmp (sd,
+                                     !=,
+                                     start_date)) ||
+         (GNUNET_TIME_timestamp_cmp (ed,
+                                     !=,
+                                     end_date)) )
+    {
+      GNUNET_break (0);
+      return GNUNET_DB_STATUS_HARD_ERROR;
+    }
+    if ( (GNUNET_TIME_relative_cmp (purse_timeout,
+                                    !=,
+                                    pt)) ||
+         (GNUNET_TIME_relative_cmp (history_expiration,
+                                    !=,
+                                    he)) )
+    {
+      GNUNET_break (0);
+      return GNUNET_DB_STATUS_HARD_ERROR;
+    }
+    if (purse_account_limit != pal)
+    {
+      GNUNET_break (0);
+      return GNUNET_DB_STATUS_HARD_ERROR;
+    }
+    /* equal record already exists */
+    return GNUNET_DB_STATUS_SUCCESS_NO_RESULTS;
   }
+
+  return GNUNET_PQ_eval_prepared_non_select (pg->conn,
+                                             "insert_global_fee",
+                                             params);
 }
 
 
 /**
- * Select coin affected by purse refund.
+ * Insert reserve close operation into database.
  *
  * @param cls closure
- * @param purse_pub purse that was refunded
- * @param cb function to call on each result
- * @param cb_cls closure for @a cb
+ * @param reserve_pub which reserve is this about?
+ * @param execution_date when did we perform the transfer?
+ * @param receiver_account to which account do we transfer?
+ * @param wtid wire transfer details
+ * @param amount_with_fee amount we charged to the reserve
+ * @param closing_fee how high is the closing fee
+ * @param close_request_row identifies explicit close request, 0 for none
  * @return transaction status code
  */
 static enum GNUNET_DB_QueryStatus
-postgres_select_purse_deposits_by_purse (
+postgres_insert_reserve_closed (
   void *cls,
-  const struct TALER_PurseContractPublicKeyP *purse_pub,
-  TALER_EXCHANGEDB_PurseRefundCoinCallback cb,
-  void *cb_cls)
+  const struct TALER_ReservePublicKeyP *reserve_pub,
+  struct GNUNET_TIME_Timestamp execution_date,
+  const char *receiver_account,
+  const struct TALER_WireTransferIdentifierRawP *wtid,
+  const struct TALER_Amount *amount_with_fee,
+  const struct TALER_Amount *closing_fee,
+  uint64_t close_request_row)
 {
   struct PostgresClosure *pg = cls;
-  struct GNUNET_PQ_QueryParam params[] = {
-    GNUNET_PQ_query_param_auto_from_type (purse_pub),
-    GNUNET_PQ_query_param_end
-  };
-  struct PurseRefundCoinContext dsc = {
-    .cb = cb,
-    .cb_cls = cb_cls,
-    .pg = pg,
-    .status = GNUNET_OK
-  };
+  struct TALER_EXCHANGEDB_Reserve reserve;
   enum GNUNET_DB_QueryStatus qs;
+  struct TALER_PaytoHashP h_payto;
 
-  qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn,
-                                             
"audit_get_purse_deposits_by_purse",
-                                             params,
-                                             &purse_refund_coin_helper_cb,
-                                             &dsc);
-  if (GNUNET_OK != dsc.status)
-    return GNUNET_DB_STATUS_HARD_ERROR;
-  return qs;
-}
-
-
-/**
- * Closure for #refreshs_serial_helper_cb().
- */
-struct RefreshsSerialContext
-{
-
-  /**
-   * Callback to call.
-   */
-  TALER_EXCHANGEDB_RefreshesCallback cb;
-
-  /**
-   * Closure for @e cb.
-   */
-  void *cb_cls;
-
-  /**
-   * Plugin context.
-   */
-  struct PostgresClosure *pg;
-
-  /**
-   * Status code, set to #GNUNET_SYSERR on hard errors.
-   */
-  enum GNUNET_GenericReturnValue status;
-};
-
+  TALER_payto_hash (receiver_account,
+                    &h_payto);
+  {
+    struct GNUNET_PQ_QueryParam params[] = {
+      GNUNET_PQ_query_param_auto_from_type (reserve_pub),
+      GNUNET_PQ_query_param_timestamp (&execution_date),
+      GNUNET_PQ_query_param_auto_from_type (wtid),
+      GNUNET_PQ_query_param_auto_from_type (&h_payto),
+      TALER_PQ_query_param_amount (amount_with_fee),
+      TALER_PQ_query_param_amount (closing_fee),
+      GNUNET_PQ_query_param_uint64 (&close_request_row),
+      GNUNET_PQ_query_param_end
+    };
 
-/**
- * Helper function to be called with the results of a SELECT statement
- * that has returned @a num_results results.
- *
- * @param cls closure of type `struct RefreshsSerialContext`
- * @param result the postgres result
- * @param num_results the number of results in @a result
- */
-static void
-refreshs_serial_helper_cb (void *cls,
-                           PGresult *result,
-                           unsigned int num_results)
-{
-  struct RefreshsSerialContext *rsc = cls;
-  struct PostgresClosure *pg = rsc->pg;
+    qs = GNUNET_PQ_eval_prepared_non_select (pg->conn,
+                                             "reserves_close_insert",
+                                             params);
+  }
+  if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != qs)
+    return qs;
 
-  for (unsigned int i = 0; i<num_results; i++)
+  /* update reserve balance */
+  reserve.pub = *reserve_pub;
+  if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
+      (qs = TEH_PG_reserves_get (cls,
+                                   &reserve)))
   {
-    struct TALER_DenominationPublicKey denom_pub;
-    struct TALER_CoinSpendPublicKeyP coin_pub;
-    struct TALER_CoinSpendSignatureP coin_sig;
-    struct TALER_AgeCommitmentHash h_age_commitment;
-    bool ac_isnull;
-    struct TALER_Amount amount_with_fee;
-    uint32_t noreveal_index;
-    uint64_t rowid;
-    struct TALER_RefreshCommitmentP rc;
-    struct GNUNET_PQ_ResultSpec rs[] = {
-      TALER_PQ_result_spec_denom_pub ("denom_pub",
-                                      &denom_pub),
-      GNUNET_PQ_result_spec_allow_null (
-        GNUNET_PQ_result_spec_auto_from_type ("age_commitment_hash",
-                                              &h_age_commitment),
-        &ac_isnull),
-      GNUNET_PQ_result_spec_auto_from_type ("old_coin_pub",
-                                            &coin_pub),
-      GNUNET_PQ_result_spec_auto_from_type ("old_coin_sig",
-                                            &coin_sig),
-      TALER_PQ_RESULT_SPEC_AMOUNT ("amount_with_fee",
-                                   &amount_with_fee),
-      GNUNET_PQ_result_spec_uint32 ("noreveal_index",
-                                    &noreveal_index),
-      GNUNET_PQ_result_spec_uint64 ("melt_serial_id",
-                                    &rowid),
-      GNUNET_PQ_result_spec_auto_from_type ("rc",
-                                            &rc),
-      GNUNET_PQ_result_spec_end
-    };
-    enum GNUNET_GenericReturnValue ret;
+    /* Existence should have been checked before we got here... */
+    GNUNET_break (GNUNET_DB_STATUS_SOFT_ERROR == qs);
+    if (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS == qs)
+      qs = GNUNET_DB_STATUS_HARD_ERROR;
+    return qs;
+  }
+  {
+    enum TALER_AmountArithmeticResult ret;
 
-    if (GNUNET_OK !=
-        GNUNET_PQ_extract_result (result,
-                                  rs,
-                                  i))
+    ret = TALER_amount_subtract (&reserve.balance,
+                                 &reserve.balance,
+                                 amount_with_fee);
+    if (ret < 0)
     {
-      GNUNET_break (0);
-      rsc->status = GNUNET_SYSERR;
-      return;
+      /* The reserve history was checked to make sure there is enough of a 
balance
+         left before we tried this; however, concurrent operations may have 
changed
+         the situation by now.  We should re-try the transaction.  */
+      GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                  "Closing of reserve `%s' refused due to balance mismatch. 
Retrying.\n",
+                  TALER_B2S (reserve_pub));
+      return GNUNET_DB_STATUS_HARD_ERROR;
     }
-
-    ret = rsc->cb (rsc->cb_cls,
-                   rowid,
-                   &denom_pub,
-                   ac_isnull ? NULL : &h_age_commitment,
-                   &coin_pub,
-                   &coin_sig,
-                   &amount_with_fee,
-                   noreveal_index,
-                   &rc);
-    GNUNET_PQ_cleanup_result (rs);
-    if (GNUNET_OK != ret)
-      break;
+    GNUNET_break (TALER_AAR_RESULT_ZERO == ret);
   }
+  return TEH_PG_reserves_update (cls,
+                          &reserve);
 }
 
 
 /**
- * Select refresh sessions above @a serial_id in monotonically increasing
- * order.
+ * Function called to insert wire transfer commit data into the DB.
  *
  * @param cls closure
- * @param serial_id highest serial ID to exclude (select strictly larger)
- * @param cb function to call on each result
- * @param cb_cls closure for @a cb
- * @return transaction status code
+ * @param type type of the wire transfer (i.e. "iban")
+ * @param buf buffer with wire transfer preparation data
+ * @param buf_size number of bytes in @a buf
+ * @return query status code
  */
 static enum GNUNET_DB_QueryStatus
-postgres_select_refreshes_above_serial_id (
-  void *cls,
-  uint64_t serial_id,
-  TALER_EXCHANGEDB_RefreshesCallback cb,
-  void *cb_cls)
+postgres_wire_prepare_data_insert (void *cls,
+                                   const char *type,
+                                   const char *buf,
+                                   size_t buf_size)
 {
   struct PostgresClosure *pg = cls;
   struct GNUNET_PQ_QueryParam params[] = {
-    GNUNET_PQ_query_param_uint64 (&serial_id),
+    GNUNET_PQ_query_param_string (type),
+    GNUNET_PQ_query_param_fixed_size (buf, buf_size),
     GNUNET_PQ_query_param_end
   };
-  struct RefreshsSerialContext rsc = {
-    .cb = cb,
-    .cb_cls = cb_cls,
-    .pg = pg,
-    .status = GNUNET_OK
-  };
-  enum GNUNET_DB_QueryStatus qs;
 
-  qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn,
-                                             
"audit_get_refresh_commitments_incr",
-                                             params,
-                                             &refreshs_serial_helper_cb,
-                                             &rsc);
-  if (GNUNET_OK != rsc.status)
-    return GNUNET_DB_STATUS_HARD_ERROR;
-  return qs;
+  return GNUNET_PQ_eval_prepared_non_select (pg->conn,
+                                             "wire_prepare_data_insert",
+                                             params);
 }
 
 
 /**
- * Closure for #refunds_serial_helper_cb().
- */
-struct RefundsSerialContext
-{
-
-  /**
-   * Callback to call.
-   */
-  TALER_EXCHANGEDB_RefundCallback cb;
-
-  /**
-   * Closure for @e cb.
-   */
-  void *cb_cls;
-
-  /**
-   * Plugin context.
-   */
-  struct PostgresClosure *pg;
-
-  /**
-   * Status code, set to #GNUNET_SYSERR on hard errors.
-   */
-  enum GNUNET_GenericReturnValue status;
-};
-
-
-/**
- * Helper function to be called with the results of a SELECT statement
- * that has returned @a num_results results.
+ * Function called to mark wire transfer commit data as finished.
  *
- * @param cls closure of type `struct RefundsSerialContext`
- * @param result the postgres result
- * @param num_results the number of results in @a result
+ * @param cls closure
+ * @param rowid which entry to mark as finished
+ * @return transaction status code
  */
-static void
-refunds_serial_helper_cb (void *cls,
-                          PGresult *result,
-                          unsigned int num_results)
+static enum GNUNET_DB_QueryStatus
+postgres_wire_prepare_data_mark_finished (
+  void *cls,
+  uint64_t rowid)
 {
-  struct RefundsSerialContext *rsc = cls;
-  struct PostgresClosure *pg = rsc->pg;
-
-  for (unsigned int i = 0; i<num_results; i++)
-  {
-    struct TALER_EXCHANGEDB_Refund refund;
-    struct TALER_DenominationPublicKey denom_pub;
-    uint64_t rowid;
-    bool full_refund;
-    struct GNUNET_PQ_ResultSpec rs[] = {
-      GNUNET_PQ_result_spec_auto_from_type ("merchant_pub",
-                                            &refund.details.merchant_pub),
-      GNUNET_PQ_result_spec_auto_from_type ("merchant_sig",
-                                            &refund.details.merchant_sig),
-      GNUNET_PQ_result_spec_auto_from_type ("h_contract_terms",
-                                            &refund.details.h_contract_terms),
-      GNUNET_PQ_result_spec_uint64 ("rtransaction_id",
-                                    &refund.details.rtransaction_id),
-      TALER_PQ_result_spec_denom_pub ("denom_pub",
-                                      &denom_pub),
-      GNUNET_PQ_result_spec_auto_from_type ("coin_pub",
-                                            &refund.coin.coin_pub),
-      TALER_PQ_RESULT_SPEC_AMOUNT ("amount_with_fee",
-                                   &refund.details.refund_amount),
-      GNUNET_PQ_result_spec_uint64 ("refund_serial_id",
-                                    &rowid),
-      GNUNET_PQ_result_spec_end
-    };
-    enum GNUNET_GenericReturnValue ret;
-
-    if (GNUNET_OK !=
-        GNUNET_PQ_extract_result (result,
-                                  rs,
-                                  i))
-    {
-      GNUNET_break (0);
-      rsc->status = GNUNET_SYSERR;
-      return;
-    }
-    {
-      struct GNUNET_PQ_QueryParam params[] = {
-        GNUNET_PQ_query_param_uint64 (&rowid),
-        GNUNET_PQ_query_param_end
-      };
-      struct TALER_Amount amount_with_fee;
-      uint64_t s_f;
-      uint64_t s_v;
-      struct GNUNET_PQ_ResultSpec rs2[] = {
-        GNUNET_PQ_result_spec_uint64 ("s_v",
-                                      &s_v),
-        GNUNET_PQ_result_spec_uint64 ("s_f",
-                                      &s_f),
-        TALER_PQ_RESULT_SPEC_AMOUNT ("amount_with_fee",
-                                     &amount_with_fee),
-        GNUNET_PQ_result_spec_end
-      };
-      enum GNUNET_DB_QueryStatus qs;
+  struct PostgresClosure *pg = cls;
+  struct GNUNET_PQ_QueryParam params[] = {
+    GNUNET_PQ_query_param_uint64 (&rowid),
+    GNUNET_PQ_query_param_end
+  };
 
-      qs = GNUNET_PQ_eval_prepared_singleton_select (
-        pg->conn,
-        "test_refund_full",
-        params,
-        rs2);
-      if (qs <= 0)
-      {
-        GNUNET_break (0);
-        rsc->status = GNUNET_SYSERR;
-        return;
-      }
-      /* normalize */
-      s_v += s_f / TALER_AMOUNT_FRAC_BASE;
-      s_f %= TALER_AMOUNT_FRAC_BASE;
-      full_refund = (s_v >= amount_with_fee.value) &&
-                    (s_f >= amount_with_fee.fraction);
-    }
-    ret = rsc->cb (rsc->cb_cls,
-                   rowid,
-                   &denom_pub,
-                   &refund.coin.coin_pub,
-                   &refund.details.merchant_pub,
-                   &refund.details.merchant_sig,
-                   &refund.details.h_contract_terms,
-                   refund.details.rtransaction_id,
-                   full_refund,
-                   &refund.details.refund_amount);
-    GNUNET_PQ_cleanup_result (rs);
-    if (GNUNET_OK != ret)
-      break;
-  }
+  return GNUNET_PQ_eval_prepared_non_select (pg->conn,
+                                             "wire_prepare_data_mark_done",
+                                             params);
 }
 
 
 /**
- * Select refunds above @a serial_id in monotonically increasing
- * order.
+ * Function called to mark wire transfer commit data as failed.
  *
  * @param cls closure
- * @param serial_id highest serial ID to exclude (select strictly larger)
- * @param cb function to call on each result
- * @param cb_cls closure for @a cb
+ * @param rowid which entry to mark as failed
  * @return transaction status code
  */
 static enum GNUNET_DB_QueryStatus
-postgres_select_refunds_above_serial_id (
+postgres_wire_prepare_data_mark_failed (
   void *cls,
-  uint64_t serial_id,
-  TALER_EXCHANGEDB_RefundCallback cb,
-  void *cb_cls)
+  uint64_t rowid)
 {
   struct PostgresClosure *pg = cls;
   struct GNUNET_PQ_QueryParam params[] = {
-    GNUNET_PQ_query_param_uint64 (&serial_id),
+    GNUNET_PQ_query_param_uint64 (&rowid),
     GNUNET_PQ_query_param_end
   };
-  struct RefundsSerialContext rsc = {
-    .cb = cb,
-    .cb_cls = cb_cls,
-    .pg = pg,
-    .status = GNUNET_OK
-  };
-  enum GNUNET_DB_QueryStatus qs;
 
-  qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn,
-                                             "audit_get_refunds_incr",
-                                             params,
-                                             &refunds_serial_helper_cb,
-                                             &rsc);
-  if (GNUNET_OK != rsc.status)
-    return GNUNET_DB_STATUS_HARD_ERROR;
-  return qs;
+  return GNUNET_PQ_eval_prepared_non_select (pg->conn,
+                                             "wire_prepare_data_mark_failed",
+                                             params);
 }
 
 
 /**
- * Closure for #reserves_in_serial_helper_cb().
+ * Closure for #prewire_cb().
  */
-struct ReservesInSerialContext
+struct PrewireContext
 {
-
   /**
-   * Callback to call.
+   * Function to call on each result.
    */
-  TALER_EXCHANGEDB_ReserveInCallback cb;
+  TALER_EXCHANGEDB_WirePreparationIterator cb;
 
   /**
-   * Closure for @e cb.
+   * Closure for @a cb.
    */
   void *cb_cls;
 
   /**
-   * Plugin context.
-   */
-  struct PostgresClosure *pg;
-
-  /**
-   * Status code, set to #GNUNET_SYSERR on hard errors.
+   * #GNUNET_OK if everything went fine.
    */
   enum GNUNET_GenericReturnValue status;
 };
 
 
 /**
- * Helper function to be called with the results of a SELECT statement
- * that has returned @a num_results results.
+ * Invoke the callback for each result.
  *
- * @param cls closure of type `struct ReservesInSerialContext`
- * @param result the postgres result
- * @param num_results the number of results in @a result
+ * @param cls a `struct MissingWireContext *`
+ * @param result SQL result
+ * @param num_results number of rows in @a result
  */
 static void
-reserves_in_serial_helper_cb (void *cls,
-                              PGresult *result,
-                              unsigned int num_results)
+prewire_cb (void *cls,
+            PGresult *result,
+            unsigned int num_results)
 {
-  struct ReservesInSerialContext *risc = cls;
-  struct PostgresClosure *pg = risc->pg;
-
-  for (unsigned int i = 0; i<num_results; i++)
-  {
-    struct TALER_ReservePublicKeyP reserve_pub;
-    struct TALER_Amount credit;
-    char *sender_account_details;
-    struct GNUNET_TIME_Timestamp execution_date;
-    uint64_t rowid;
-    uint64_t wire_reference;
+  struct PrewireContext *pc = cls;
+
+  for (unsigned int i = 0; i < num_results; i++)
+  {
+    uint64_t prewire_uuid;
+    char *wire_method;
+    void *buf = NULL;
+    size_t buf_size;
     struct GNUNET_PQ_ResultSpec rs[] = {
-      GNUNET_PQ_result_spec_auto_from_type ("reserve_pub",
-                                            &reserve_pub),
-      GNUNET_PQ_result_spec_uint64 ("wire_reference",
-                                    &wire_reference),
-      TALER_PQ_RESULT_SPEC_AMOUNT ("credit",
-                                   &credit),
-      GNUNET_PQ_result_spec_timestamp ("execution_date",
-                                       &execution_date),
-      GNUNET_PQ_result_spec_string ("sender_account_details",
-                                    &sender_account_details),
-      GNUNET_PQ_result_spec_uint64 ("reserve_in_serial_id",
-                                    &rowid),
+      GNUNET_PQ_result_spec_uint64 ("prewire_uuid",
+                                    &prewire_uuid),
+      GNUNET_PQ_result_spec_string ("wire_method",
+                                    &wire_method),
+      GNUNET_PQ_result_spec_variable_size ("buf",
+                                           &buf,
+                                           &buf_size),
       GNUNET_PQ_result_spec_end
     };
-    enum GNUNET_GenericReturnValue ret;
 
     if (GNUNET_OK !=
         GNUNET_PQ_extract_result (result,
@@ -6849,118 +3032,210 @@ reserves_in_serial_helper_cb (void *cls,
                                   i))
     {
       GNUNET_break (0);
-      risc->status = GNUNET_SYSERR;
+      pc->status = GNUNET_SYSERR;
       return;
     }
-    ret = risc->cb (risc->cb_cls,
-                    rowid,
-                    &reserve_pub,
-                    &credit,
-                    sender_account_details,
-                    wire_reference,
-                    execution_date);
+    pc->cb (pc->cb_cls,
+            prewire_uuid,
+            wire_method,
+            buf,
+            buf_size);
     GNUNET_PQ_cleanup_result (rs);
-    if (GNUNET_OK != ret)
-      break;
   }
 }
 
 
 /**
- * Select inbound wire transfers into reserves_in above @a serial_id
- * in monotonically increasing order.
+ * Function called to get an unfinished wire transfer
+ * preparation data. Fetches at most one item.
  *
  * @param cls closure
- * @param serial_id highest serial ID to exclude (select strictly larger)
- * @param cb function to call on each result
+ * @param start_row offset to query table at
+ * @param limit maximum number of results to return
+ * @param cb function to call for ONE unfinished item
  * @param cb_cls closure for @a cb
  * @return transaction status code
  */
 static enum GNUNET_DB_QueryStatus
-postgres_select_reserves_in_above_serial_id (
-  void *cls,
-  uint64_t serial_id,
-  TALER_EXCHANGEDB_ReserveInCallback cb,
-  void *cb_cls)
+postgres_wire_prepare_data_get (void *cls,
+                                uint64_t start_row,
+                                uint64_t limit,
+                                TALER_EXCHANGEDB_WirePreparationIterator cb,
+                                void *cb_cls)
 {
   struct PostgresClosure *pg = cls;
   struct GNUNET_PQ_QueryParam params[] = {
-    GNUNET_PQ_query_param_uint64 (&serial_id),
+    GNUNET_PQ_query_param_uint64 (&start_row),
+    GNUNET_PQ_query_param_uint64 (&limit),
     GNUNET_PQ_query_param_end
   };
-  struct ReservesInSerialContext risc = {
+  struct PrewireContext pc = {
     .cb = cb,
     .cb_cls = cb_cls,
-    .pg = pg,
     .status = GNUNET_OK
   };
   enum GNUNET_DB_QueryStatus qs;
 
   qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn,
-                                             
"audit_reserves_in_get_transactions_incr",
+                                             "wire_prepare_data_get",
                                              params,
-                                             &reserves_in_serial_helper_cb,
-                                             &risc);
-  if (GNUNET_OK != risc.status)
+                                             &prewire_cb,
+                                             &pc);
+  if (GNUNET_OK != pc.status)
     return GNUNET_DB_STATUS_HARD_ERROR;
   return qs;
 }
 
 
 /**
- * Select inbound wire transfers into reserves_in above @a serial_id
- * in monotonically increasing order by account.
+ * Starts a READ COMMITTED transaction where we transiently violate the foreign
+ * constraints on the "wire_out" table as we insert aggregations
+ * and only add the wire transfer out at the end.
+ *
+ * @param cls the @e cls of this struct with the plugin-specific state
+ * @return #GNUNET_OK on success
+ */
+static enum GNUNET_GenericReturnValue
+postgres_start_deferred_wire_out (void *cls)
+{
+  struct PostgresClosure *pg = cls;
+  struct GNUNET_PQ_ExecuteStatement es[] = {
+    GNUNET_PQ_make_execute (
+      "START TRANSACTION ISOLATION LEVEL READ COMMITTED;"),
+    GNUNET_PQ_make_execute ("SET CONSTRAINTS ALL DEFERRED;"),
+    GNUNET_PQ_EXECUTE_STATEMENT_END
+  };
+
+  if (GNUNET_SYSERR ==
+      TEH_PG_preflight (pg))
+    return GNUNET_SYSERR;
+  if (GNUNET_OK !=
+      GNUNET_PQ_exec_statements (pg->conn,
+                                 es))
+  {
+    TALER_LOG_ERROR (
+      "Failed to defer wire_out_ref constraint on transaction\n");
+    GNUNET_break (0);
+    TEH_PG_rollback (pg);
+    return GNUNET_SYSERR;
+  }
+  pg->transaction_name = "deferred wire out";
+  GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+              "Starting READ COMMITTED DEFERRED transaction `%s'\n",
+              pg->transaction_name);
+  return GNUNET_OK;
+}
+
+
+/**
+ * Store information about an outgoing wire transfer that was executed.
  *
  * @param cls closure
- * @param account_name name of the account to select by
- * @param serial_id highest serial ID to exclude (select strictly larger)
- * @param cb function to call on each result
- * @param cb_cls closure for @a cb
+ * @param date time of the wire transfer
+ * @param wtid subject of the wire transfer
+ * @param h_payto identifies the receiver account of the wire transfer
+ * @param exchange_account_section configuration section of the exchange 
specifying the
+ *        exchange's bank account being used
+ * @param amount amount that was transmitted
  * @return transaction status code
  */
 static enum GNUNET_DB_QueryStatus
-postgres_select_reserves_in_above_serial_id_by_account (
+postgres_store_wire_transfer_out (
   void *cls,
-  const char *account_name,
-  uint64_t serial_id,
-  TALER_EXCHANGEDB_ReserveInCallback cb,
-  void *cb_cls)
+  struct GNUNET_TIME_Timestamp date,
+  const struct TALER_WireTransferIdentifierRawP *wtid,
+  const struct TALER_PaytoHashP *h_payto,
+  const char *exchange_account_section,
+  const struct TALER_Amount *amount)
 {
   struct PostgresClosure *pg = cls;
   struct GNUNET_PQ_QueryParam params[] = {
-    GNUNET_PQ_query_param_uint64 (&serial_id),
-    GNUNET_PQ_query_param_string (account_name),
+    GNUNET_PQ_query_param_timestamp (&date),
+    GNUNET_PQ_query_param_auto_from_type (wtid),
+    GNUNET_PQ_query_param_auto_from_type (h_payto),
+    GNUNET_PQ_query_param_string (exchange_account_section),
+    TALER_PQ_query_param_amount (amount),
     GNUNET_PQ_query_param_end
   };
-  struct ReservesInSerialContext risc = {
-    .cb = cb,
-    .cb_cls = cb_cls,
-    .pg = pg,
-    .status = GNUNET_OK
+
+  return GNUNET_PQ_eval_prepared_non_select (pg->conn,
+                                             "insert_wire_out",
+                                             params);
+}
+
+
+/**
+ * Function called to perform "garbage collection" on the
+ * database, expiring records we no longer require.
+ *
+ * @param cls closure
+ * @return #GNUNET_OK on success,
+ *         #GNUNET_SYSERR on DB errors
+ */
+static enum GNUNET_GenericReturnValue
+postgres_gc (void *cls)
+{
+  struct PostgresClosure *pg = cls;
+  struct GNUNET_TIME_Absolute now = GNUNET_TIME_absolute_get ();
+  struct GNUNET_TIME_Absolute long_ago;
+  struct GNUNET_PQ_QueryParam params[] = {
+    GNUNET_PQ_query_param_absolute_time (&long_ago),
+    GNUNET_PQ_query_param_absolute_time (&now),
+    GNUNET_PQ_query_param_end
   };
-  enum GNUNET_DB_QueryStatus qs;
+  struct GNUNET_PQ_Context *conn;
+  enum GNUNET_GenericReturnValue ret;
 
-  qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn,
-                                             
"audit_reserves_in_get_transactions_incr_by_account",
-                                             params,
-                                             &reserves_in_serial_helper_cb,
-                                             &risc);
-  if (GNUNET_OK != risc.status)
-    return GNUNET_DB_STATUS_HARD_ERROR;
-  return qs;
+  /* Keep wire fees for 10 years, that should always
+     be enough _and_ they are tiny so it does not
+     matter to make this tight */
+  long_ago = GNUNET_TIME_absolute_subtract (
+    now,
+    GNUNET_TIME_relative_multiply (
+      GNUNET_TIME_UNIT_YEARS,
+      10));
+  {
+    struct GNUNET_PQ_ExecuteStatement es[] = {
+      GNUNET_PQ_make_try_execute ("SET search_path TO exchange;"),
+      GNUNET_PQ_EXECUTE_STATEMENT_END
+    };
+    struct GNUNET_PQ_PreparedStatement ps[] = {
+      /* Used in #postgres_gc() */
+      GNUNET_PQ_make_prepare ("run_gc",
+                              "CALL"
+                              " exchange_do_gc"
+                              " ($1,$2);"),
+      GNUNET_PQ_PREPARED_STATEMENT_END
+    };
+
+    conn = GNUNET_PQ_connect_with_cfg (pg->cfg,
+                                       "exchangedb-postgres",
+                                       NULL,
+                                       es,
+                                       ps);
+  }
+  if (NULL == conn)
+    return GNUNET_SYSERR;
+  ret = GNUNET_OK;
+  if (0 > GNUNET_PQ_eval_prepared_non_select (conn,
+                                              "run_gc",
+                                              params))
+    ret = GNUNET_SYSERR;
+  GNUNET_PQ_disconnect (conn);
+  return ret;
 }
 
 
 /**
- * Closure for #reserves_out_serial_helper_cb().
+ * Closure for #deposit_serial_helper_cb().
  */
-struct ReservesOutSerialContext
+struct DepositSerialContext
 {
 
   /**
    * Callback to call.
    */
-  TALER_EXCHANGEDB_WithdrawCallback cb;
+  TALER_EXCHANGEDB_DepositCallback cb;
 
   /**
    * Closure for @e cb.
@@ -6983,63 +3258,80 @@ struct ReservesOutSerialContext
  * Helper function to be called with the results of a SELECT statement
  * that has returned @a num_results results.
  *
- * @param cls closure of type `struct ReservesOutSerialContext`
+ * @param cls closure of type `struct DepositSerialContext`
  * @param result the postgres result
  * @param num_results the number of results in @a result
  */
 static void
-reserves_out_serial_helper_cb (void *cls,
-                               PGresult *result,
-                               unsigned int num_results)
+deposit_serial_helper_cb (void *cls,
+                          PGresult *result,
+                          unsigned int num_results)
 {
-  struct ReservesOutSerialContext *rosc = cls;
-  struct PostgresClosure *pg = rosc->pg;
+  struct DepositSerialContext *dsc = cls;
+  struct PostgresClosure *pg = dsc->pg;
 
   for (unsigned int i = 0; i<num_results; i++)
   {
-    struct TALER_BlindedCoinHashP h_blind_ev;
+    struct TALER_EXCHANGEDB_Deposit deposit;
+    struct GNUNET_TIME_Timestamp exchange_timestamp;
     struct TALER_DenominationPublicKey denom_pub;
-    struct TALER_ReservePublicKeyP reserve_pub;
-    struct TALER_ReserveSignatureP reserve_sig;
-    struct GNUNET_TIME_Timestamp execution_date;
-    struct TALER_Amount amount_with_fee;
+    bool done;
     uint64_t rowid;
     struct GNUNET_PQ_ResultSpec rs[] = {
-      GNUNET_PQ_result_spec_auto_from_type ("h_blind_ev",
-                                            &h_blind_ev),
+      TALER_PQ_RESULT_SPEC_AMOUNT ("amount_with_fee",
+                                   &deposit.amount_with_fee),
+      GNUNET_PQ_result_spec_timestamp ("wallet_timestamp",
+                                       &deposit.timestamp),
+      GNUNET_PQ_result_spec_timestamp ("exchange_timestamp",
+                                       &exchange_timestamp),
+      GNUNET_PQ_result_spec_auto_from_type ("merchant_pub",
+                                            &deposit.merchant_pub),
       TALER_PQ_result_spec_denom_pub ("denom_pub",
                                       &denom_pub),
-      GNUNET_PQ_result_spec_auto_from_type ("reserve_pub",
-                                            &reserve_pub),
-      GNUNET_PQ_result_spec_auto_from_type ("reserve_sig",
-                                            &reserve_sig),
-      GNUNET_PQ_result_spec_timestamp ("execution_date",
-                                       &execution_date),
-      TALER_PQ_RESULT_SPEC_AMOUNT ("amount_with_fee",
-                                   &amount_with_fee),
-      GNUNET_PQ_result_spec_uint64 ("reserve_out_serial_id",
+      GNUNET_PQ_result_spec_auto_from_type ("coin_pub",
+                                            &deposit.coin.coin_pub),
+      GNUNET_PQ_result_spec_allow_null (
+        GNUNET_PQ_result_spec_auto_from_type ("age_commitment_hash",
+                                              &deposit.coin.h_age_commitment),
+        &deposit.coin.no_age_commitment),
+      GNUNET_PQ_result_spec_auto_from_type ("coin_sig",
+                                            &deposit.csig),
+      GNUNET_PQ_result_spec_timestamp ("refund_deadline",
+                                       &deposit.refund_deadline),
+      GNUNET_PQ_result_spec_timestamp ("wire_deadline",
+                                       &deposit.wire_deadline),
+      GNUNET_PQ_result_spec_auto_from_type ("h_contract_terms",
+                                            &deposit.h_contract_terms),
+      GNUNET_PQ_result_spec_auto_from_type ("wire_salt",
+                                            &deposit.wire_salt),
+      GNUNET_PQ_result_spec_string ("receiver_wire_account",
+                                    &deposit.receiver_wire_account),
+      GNUNET_PQ_result_spec_bool ("done",
+                                  &done),
+      GNUNET_PQ_result_spec_uint64 ("deposit_serial_id",
                                     &rowid),
       GNUNET_PQ_result_spec_end
     };
     enum GNUNET_GenericReturnValue ret;
 
+    memset (&deposit,
+            0,
+            sizeof (deposit));
     if (GNUNET_OK !=
         GNUNET_PQ_extract_result (result,
                                   rs,
                                   i))
     {
       GNUNET_break (0);
-      rosc->status = GNUNET_SYSERR;
+      dsc->status = GNUNET_SYSERR;
       return;
     }
-    ret = rosc->cb (rosc->cb_cls,
-                    rowid,
-                    &h_blind_ev,
-                    &denom_pub,
-                    &reserve_pub,
-                    &reserve_sig,
-                    execution_date,
-                    &amount_with_fee);
+    ret = dsc->cb (dsc->cb_cls,
+                   rowid,
+                   exchange_timestamp,
+                   &deposit,
+                   &denom_pub,
+                   done);
     GNUNET_PQ_cleanup_result (rs);
     if (GNUNET_OK != ret)
       break;
@@ -7048,8 +3340,8 @@ reserves_out_serial_helper_cb (void *cls,
 
 
 /**
- * Select withdraw operations from reserves_out above @a serial_id
- * in monotonically increasing order.
+ * Select deposits above @a serial_id in monotonically increasing
+ * order.
  *
  * @param cls closure
  * @param serial_id highest serial ID to exclude (select strictly larger)
@@ -7058,10 +3350,10 @@ reserves_out_serial_helper_cb (void *cls,
  * @return transaction status code
  */
 static enum GNUNET_DB_QueryStatus
-postgres_select_withdrawals_above_serial_id (
+postgres_select_deposits_above_serial_id (
   void *cls,
   uint64_t serial_id,
-  TALER_EXCHANGEDB_WithdrawCallback cb,
+  TALER_EXCHANGEDB_DepositCallback cb,
   void *cb_cls)
 {
   struct PostgresClosure *pg = cls;
@@ -7069,7 +3361,7 @@ postgres_select_withdrawals_above_serial_id (
     GNUNET_PQ_query_param_uint64 (&serial_id),
     GNUNET_PQ_query_param_end
   };
-  struct ReservesOutSerialContext rosc = {
+  struct DepositSerialContext dsc = {
     .cb = cb,
     .cb_cls = cb_cls,
     .pg = pg,
@@ -7078,26 +3370,26 @@ postgres_select_withdrawals_above_serial_id (
   enum GNUNET_DB_QueryStatus qs;
 
   qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn,
-                                             "audit_get_reserves_out_incr",
+                                             "audit_get_deposits_incr",
                                              params,
-                                             &reserves_out_serial_helper_cb,
-                                             &rosc);
-  if (GNUNET_OK != rosc.status)
+                                             &deposit_serial_helper_cb,
+                                             &dsc);
+  if (GNUNET_OK != dsc.status)
     return GNUNET_DB_STATUS_HARD_ERROR;
   return qs;
 }
 
 
 /**
- * Closure for #wire_out_serial_helper_cb().
+ * Closure for #purse_deposit_serial_helper_cb().
  */
-struct WireOutSerialContext
+struct HistoryRequestSerialContext
 {
 
   /**
    * Callback to call.
    */
-  TALER_EXCHANGEDB_WireTransferOutCallback cb;
+  TALER_EXCHANGEDB_HistoryRequestCallback cb;
 
   /**
    * Closure for @e cb.
@@ -7112,7 +3404,7 @@ struct WireOutSerialContext
   /**
    * Status code, set to #GNUNET_SYSERR on hard errors.
    */
-  int status;
+  enum GNUNET_GenericReturnValue status;
 };
 
 
@@ -7120,39 +3412,39 @@ struct WireOutSerialContext
  * Helper function to be called with the results of a SELECT statement
  * that has returned @a num_results results.
  *
- * @param cls closure of type `struct WireOutSerialContext`
+ * @param cls closure of type `struct HistoryRequestSerialContext`
  * @param result the postgres result
  * @param num_results the number of results in @a result
  */
 static void
-wire_out_serial_helper_cb (void *cls,
-                           PGresult *result,
-                           unsigned int num_results)
+history_request_serial_helper_cb (void *cls,
+                                  PGresult *result,
+                                  unsigned int num_results)
 {
-  struct WireOutSerialContext *wosc = cls;
-  struct PostgresClosure *pg = wosc->pg;
+  struct HistoryRequestSerialContext *dsc = cls;
+  struct PostgresClosure *pg = dsc->pg;
 
   for (unsigned int i = 0; i<num_results; i++)
   {
     uint64_t rowid;
-    struct GNUNET_TIME_Timestamp date;
-    struct TALER_WireTransferIdentifierRawP wtid;
-    char *payto_uri;
-    struct TALER_Amount amount;
+    struct TALER_Amount history_fee;
+    struct GNUNET_TIME_Timestamp ts;
+    struct TALER_ReservePublicKeyP reserve_pub;
+    struct TALER_ReserveSignatureP reserve_sig;
     struct GNUNET_PQ_ResultSpec rs[] = {
-      GNUNET_PQ_result_spec_uint64 ("wireout_uuid",
+      TALER_PQ_RESULT_SPEC_AMOUNT ("history_fee",
+                                   &history_fee),
+      GNUNET_PQ_result_spec_auto_from_type ("reserve_pub",
+                                            &reserve_pub),
+      GNUNET_PQ_result_spec_auto_from_type ("reserve_sig",
+                                            &reserve_sig),
+      GNUNET_PQ_result_spec_uint64 ("history_request_serial_id",
                                     &rowid),
-      GNUNET_PQ_result_spec_timestamp ("execution_date",
-                                       &date),
-      GNUNET_PQ_result_spec_auto_from_type ("wtid_raw",
-                                            &wtid),
-      GNUNET_PQ_result_spec_string ("payto_uri",
-                                    &payto_uri),
-      TALER_PQ_RESULT_SPEC_AMOUNT ("amount",
-                                   &amount),
+      GNUNET_PQ_result_spec_timestamp ("request_timestamp",
+                                       &ts),
       GNUNET_PQ_result_spec_end
     };
-    int ret;
+    enum GNUNET_GenericReturnValue ret;
 
     if (GNUNET_OK !=
         GNUNET_PQ_extract_result (result,
@@ -7160,15 +3452,15 @@ wire_out_serial_helper_cb (void *cls,
                                   i))
     {
       GNUNET_break (0);
-      wosc->status = GNUNET_SYSERR;
+      dsc->status = GNUNET_SYSERR;
       return;
     }
-    ret = wosc->cb (wosc->cb_cls,
-                    rowid,
-                    date,
-                    &wtid,
-                    payto_uri,
-                    &amount);
+    ret = dsc->cb (dsc->cb_cls,
+                   rowid,
+                   &history_fee,
+                   ts,
+                   &reserve_pub,
+                   &reserve_sig);
     GNUNET_PQ_cleanup_result (rs);
     if (GNUNET_OK != ret)
       break;
@@ -7177,72 +3469,28 @@ wire_out_serial_helper_cb (void *cls,
 
 
 /**
- * Function called to select all wire transfers the exchange
- * executed.
- *
- * @param cls closure
- * @param serial_id highest serial ID to exclude (select strictly larger)
- * @param cb function to call for ONE unfinished item
- * @param cb_cls closure for @a cb
- * @return transaction status code
- */
-static enum GNUNET_DB_QueryStatus
-postgres_select_wire_out_above_serial_id (
-  void *cls,
-  uint64_t serial_id,
-  TALER_EXCHANGEDB_WireTransferOutCallback cb,
-  void *cb_cls)
-{
-  struct PostgresClosure *pg = cls;
-  struct GNUNET_PQ_QueryParam params[] = {
-    GNUNET_PQ_query_param_uint64 (&serial_id),
-    GNUNET_PQ_query_param_end
-  };
-  struct WireOutSerialContext wosc = {
-    .cb = cb,
-    .cb_cls = cb_cls,
-    .pg = pg,
-    .status = GNUNET_OK
-  };
-  enum GNUNET_DB_QueryStatus qs;
-
-  qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn,
-                                             "audit_get_wire_incr",
-                                             params,
-                                             &wire_out_serial_helper_cb,
-                                             &wosc);
-  if (GNUNET_OK != wosc.status)
-    return GNUNET_DB_STATUS_HARD_ERROR;
-  return qs;
-}
-
-
-/**
- * Function called to select all wire transfers the exchange
- * executed by account.
+ * Select history requests above @a serial_id in monotonically increasing
+ * order.
  *
  * @param cls closure
- * @param account_name account to select
  * @param serial_id highest serial ID to exclude (select strictly larger)
- * @param cb function to call for ONE unfinished item
+ * @param cb function to call on each result
  * @param cb_cls closure for @a cb
  * @return transaction status code
  */
 static enum GNUNET_DB_QueryStatus
-postgres_select_wire_out_above_serial_id_by_account (
+postgres_select_history_requests_above_serial_id (
   void *cls,
-  const char *account_name,
   uint64_t serial_id,
-  TALER_EXCHANGEDB_WireTransferOutCallback cb,
+  TALER_EXCHANGEDB_HistoryRequestCallback cb,
   void *cb_cls)
 {
   struct PostgresClosure *pg = cls;
   struct GNUNET_PQ_QueryParam params[] = {
     GNUNET_PQ_query_param_uint64 (&serial_id),
-    GNUNET_PQ_query_param_string (account_name),
     GNUNET_PQ_query_param_end
   };
-  struct WireOutSerialContext wosc = {
+  struct HistoryRequestSerialContext dsc = {
     .cb = cb,
     .cb_cls = cb_cls,
     .pg = pg,
@@ -7251,26 +3499,26 @@ postgres_select_wire_out_above_serial_id_by_account (
   enum GNUNET_DB_QueryStatus qs;
 
   qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn,
-                                             "audit_get_wire_incr_by_account",
+                                             "audit_get_history_requests_incr",
                                              params,
-                                             &wire_out_serial_helper_cb,
-                                             &wosc);
-  if (GNUNET_OK != wosc.status)
+                                             &history_request_serial_helper_cb,
+                                             &dsc);
+  if (GNUNET_OK != dsc.status)
     return GNUNET_DB_STATUS_HARD_ERROR;
   return qs;
 }
 
 
 /**
- * Closure for #recoup_serial_helper_cb().
+ * Closure for #purse_decision_serial_helper_cb().
  */
-struct RecoupSerialContext
+struct PurseDecisionSerialContext
 {
 
   /**
    * Callback to call.
    */
-  TALER_EXCHANGEDB_RecoupCallback cb;
+  TALER_EXCHANGEDB_PurseDecisionCallback cb;
 
   /**
    * Closure for @e cb.
@@ -7293,59 +3541,39 @@ struct RecoupSerialContext
  * Helper function to be called with the results of a SELECT statement
  * that has returned @a num_results results.
  *
- * @param cls closure of type `struct RecoupSerialContext`
+ * @param cls closure of type `struct PurseRefundSerialContext`
  * @param result the postgres result
  * @param num_results the number of results in @a result
  */
 static void
-recoup_serial_helper_cb (void *cls,
-                         PGresult *result,
-                         unsigned int num_results)
+purse_decision_serial_helper_cb (void *cls,
+                                 PGresult *result,
+                                 unsigned int num_results)
 {
-  struct RecoupSerialContext *psc = cls;
-  struct PostgresClosure *pg = psc->pg;
+  struct PurseDecisionSerialContext *dsc = cls;
+  struct PostgresClosure *pg = dsc->pg;
 
   for (unsigned int i = 0; i<num_results; i++)
   {
-    uint64_t rowid;
+    struct TALER_PurseContractPublicKeyP purse_pub;
     struct TALER_ReservePublicKeyP reserve_pub;
-    struct TALER_CoinPublicInfo coin;
-    struct TALER_CoinSpendSignatureP coin_sig;
-    union TALER_DenominationBlindingKeyP coin_blind;
-    struct TALER_Amount amount;
-    struct TALER_DenominationPublicKey denom_pub;
-    struct TALER_BlindedCoinHashP h_blind_ev;
-    struct GNUNET_TIME_Timestamp timestamp;
+    bool no_reserve = true;
+    uint64_t rowid;
+    struct TALER_Amount val;
     struct GNUNET_PQ_ResultSpec rs[] = {
-      GNUNET_PQ_result_spec_uint64 ("recoup_uuid",
-                                    &rowid),
-      GNUNET_PQ_result_spec_timestamp ("recoup_timestamp",
-                                       &timestamp),
-      GNUNET_PQ_result_spec_auto_from_type ("reserve_pub",
-                                            &reserve_pub),
-      GNUNET_PQ_result_spec_auto_from_type ("coin_pub",
-                                            &coin.coin_pub),
-      TALER_PQ_result_spec_denom_pub ("denom_pub",
-                                      &denom_pub),
-      GNUNET_PQ_result_spec_auto_from_type ("coin_sig",
-                                            &coin_sig),
-      GNUNET_PQ_result_spec_auto_from_type ("coin_blind",
-                                            &coin_blind),
-      GNUNET_PQ_result_spec_auto_from_type ("h_blind_ev",
-                                            &h_blind_ev),
-      GNUNET_PQ_result_spec_auto_from_type ("denom_pub_hash",
-                                            &coin.denom_pub_hash),
+      GNUNET_PQ_result_spec_auto_from_type ("purse_pub",
+                                            &purse_pub),
       GNUNET_PQ_result_spec_allow_null (
-        GNUNET_PQ_result_spec_auto_from_type ("age_commitment_hash",
-                                              &coin.h_age_commitment),
-        &coin.no_age_commitment),
-      TALER_PQ_result_spec_denom_sig ("denom_sig",
-                                      &coin.denom_sig),
-      TALER_PQ_RESULT_SPEC_AMOUNT ("amount",
-                                   &amount),
+        GNUNET_PQ_result_spec_auto_from_type ("reserve_pub",
+                                              &reserve_pub),
+        &no_reserve),
+      TALER_PQ_RESULT_SPEC_AMOUNT ("amount_with_fee",
+                                   &val),
+      GNUNET_PQ_result_spec_uint64 ("purse_deposit_serial_id",
+                                    &rowid),
       GNUNET_PQ_result_spec_end
     };
-    int ret;
+    enum GNUNET_GenericReturnValue ret;
 
     if (GNUNET_OK !=
         GNUNET_PQ_extract_result (result,
@@ -7353,18 +3581,14 @@ recoup_serial_helper_cb (void *cls,
                                   i))
     {
       GNUNET_break (0);
-      psc->status = GNUNET_SYSERR;
+      dsc->status = GNUNET_SYSERR;
       return;
     }
-    ret = psc->cb (psc->cb_cls,
+    ret = dsc->cb (dsc->cb_cls,
                    rowid,
-                   timestamp,
-                   &amount,
-                   &reserve_pub,
-                   &coin,
-                   &denom_pub,
-                   &coin_sig,
-                   &coin_blind);
+                   &purse_pub,
+                   no_reserve ? NULL : &reserve_pub,
+                   &val);
     GNUNET_PQ_cleanup_result (rs);
     if (GNUNET_OK != ret)
       break;
@@ -7373,28 +3597,31 @@ recoup_serial_helper_cb (void *cls,
 
 
 /**
- * Function called to select recoup requests the exchange
- * received, ordered by serial ID (monotonically increasing).
+ * Select purse decisions above @a serial_id in monotonically increasing
+ * order.
  *
  * @param cls closure
- * @param serial_id lowest serial ID to include (select larger or equal)
- * @param cb function to call for ONE unfinished item
+ * @param serial_id highest serial ID to exclude (select strictly larger)
+ * @param refunded which refund status to select for
+ * @param cb function to call on each result
  * @param cb_cls closure for @a cb
  * @return transaction status code
  */
 static enum GNUNET_DB_QueryStatus
-postgres_select_recoup_above_serial_id (
+postgres_select_purse_decisions_above_serial_id (
   void *cls,
   uint64_t serial_id,
-  TALER_EXCHANGEDB_RecoupCallback cb,
+  bool refunded,
+  TALER_EXCHANGEDB_PurseDecisionCallback cb,
   void *cb_cls)
 {
   struct PostgresClosure *pg = cls;
   struct GNUNET_PQ_QueryParam params[] = {
     GNUNET_PQ_query_param_uint64 (&serial_id),
+    GNUNET_PQ_query_param_bool (refunded),
     GNUNET_PQ_query_param_end
   };
-  struct RecoupSerialContext psc = {
+  struct PurseDecisionSerialContext dsc = {
     .cb = cb,
     .cb_cls = cb_cls,
     .pg = pg,
@@ -7403,26 +3630,26 @@ postgres_select_recoup_above_serial_id (
   enum GNUNET_DB_QueryStatus qs;
 
   qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn,
-                                             "recoup_get_incr",
+                                             "audit_get_purse_decisions_incr",
                                              params,
-                                             &recoup_serial_helper_cb,
-                                             &psc);
-  if (GNUNET_OK != psc.status)
+                                             &purse_decision_serial_helper_cb,
+                                             &dsc);
+  if (GNUNET_OK != dsc.status)
     return GNUNET_DB_STATUS_HARD_ERROR;
   return qs;
 }
 
 
 /**
- * Closure for #recoup_refresh_serial_helper_cb().
+ * Closure for #purse_refund_coin_helper_cb().
  */
-struct RecoupRefreshSerialContext
+struct PurseRefundCoinContext
 {
 
   /**
    * Callback to call.
    */
-  TALER_EXCHANGEDB_RecoupRefreshCallback cb;
+  TALER_EXCHANGEDB_PurseRefundCoinCallback cb;
 
   /**
    * Closure for @e cb.
@@ -7445,59 +3672,33 @@ struct RecoupRefreshSerialContext
  * Helper function to be called with the results of a SELECT statement
  * that has returned @a num_results results.
  *
- * @param cls closure of type `struct RecoupRefreshSerialContext`
+ * @param cls closure of type `struct PurseRefundCoinContext`
  * @param result the postgres result
  * @param num_results the number of results in @a result
  */
 static void
-recoup_refresh_serial_helper_cb (void *cls,
-                                 PGresult *result,
-                                 unsigned int num_results)
+purse_refund_coin_helper_cb (void *cls,
+                             PGresult *result,
+                             unsigned int num_results)
 {
-  struct RecoupRefreshSerialContext *psc = cls;
-  struct PostgresClosure *pg = psc->pg;
+  struct PurseRefundCoinContext *dsc = cls;
+  struct PostgresClosure *pg = dsc->pg;
 
   for (unsigned int i = 0; i<num_results; i++)
   {
-    uint64_t rowid;
-    struct TALER_CoinSpendPublicKeyP old_coin_pub;
-    struct TALER_CoinPublicInfo coin;
-    struct TALER_CoinSpendSignatureP coin_sig;
-    union TALER_DenominationBlindingKeyP coin_blind;
+    struct TALER_Amount amount_with_fee;
+    struct TALER_CoinSpendPublicKeyP coin_pub;
     struct TALER_DenominationPublicKey denom_pub;
-    struct TALER_DenominationHashP old_denom_pub_hash;
-    struct TALER_Amount amount;
-    struct TALER_BlindedCoinHashP h_blind_ev;
-    struct GNUNET_TIME_Timestamp timestamp;
+    uint64_t rowid;
     struct GNUNET_PQ_ResultSpec rs[] = {
-      GNUNET_PQ_result_spec_uint64 ("recoup_refresh_uuid",
-                                    &rowid),
-      GNUNET_PQ_result_spec_timestamp ("recoup_timestamp",
-                                       &timestamp),
-      GNUNET_PQ_result_spec_auto_from_type ("old_coin_pub",
-                                            &old_coin_pub),
-      GNUNET_PQ_result_spec_auto_from_type ("old_denom_pub_hash",
-                                            &old_denom_pub_hash),
-      GNUNET_PQ_result_spec_auto_from_type ("coin_pub",
-                                            &coin.coin_pub),
-      GNUNET_PQ_result_spec_auto_from_type ("coin_sig",
-                                            &coin_sig),
-      GNUNET_PQ_result_spec_auto_from_type ("coin_blind",
-                                            &coin_blind),
       TALER_PQ_result_spec_denom_pub ("denom_pub",
                                       &denom_pub),
-      GNUNET_PQ_result_spec_auto_from_type ("h_blind_ev",
-                                            &h_blind_ev),
-      GNUNET_PQ_result_spec_auto_from_type ("denom_pub_hash",
-                                            &coin.denom_pub_hash),
-      GNUNET_PQ_result_spec_allow_null (
-        GNUNET_PQ_result_spec_auto_from_type ("age_commitment_hash",
-                                              &coin.h_age_commitment),
-        &coin.no_age_commitment),
-      TALER_PQ_result_spec_denom_sig ("denom_sig",
-                                      &coin.denom_sig),
-      TALER_PQ_RESULT_SPEC_AMOUNT ("amount",
-                                   &amount),
+      TALER_PQ_RESULT_SPEC_AMOUNT ("amount_with_fee",
+                                   &amount_with_fee),
+      GNUNET_PQ_result_spec_auto_from_type ("coin_pub",
+                                            &coin_pub),
+      GNUNET_PQ_result_spec_uint64 ("purse_deposit_serial_id",
+                                    &rowid),
       GNUNET_PQ_result_spec_end
     };
     enum GNUNET_GenericReturnValue ret;
@@ -7508,19 +3709,14 @@ recoup_refresh_serial_helper_cb (void *cls,
                                   i))
     {
       GNUNET_break (0);
-      psc->status = GNUNET_SYSERR;
+      dsc->status = GNUNET_SYSERR;
       return;
     }
-    ret = psc->cb (psc->cb_cls,
+    ret = dsc->cb (dsc->cb_cls,
                    rowid,
-                   timestamp,
-                   &amount,
-                   &old_coin_pub,
-                   &old_denom_pub_hash,
-                   &coin,
-                   &denom_pub,
-                   &coin_sig,
-                   &coin_blind);
+                   &amount_with_fee,
+                   &coin_pub,
+                   &denom_pub);
     GNUNET_PQ_cleanup_result (rs);
     if (GNUNET_OK != ret)
       break;
@@ -7529,28 +3725,27 @@ recoup_refresh_serial_helper_cb (void *cls,
 
 
 /**
- * Function called to select recoup requests the exchange received for
- * refreshed coins, ordered by serial ID (monotonically increasing).
+ * Select coin affected by purse refund.
  *
  * @param cls closure
- * @param serial_id lowest serial ID to include (select larger or equal)
- * @param cb function to call for ONE unfinished item
+ * @param purse_pub purse that was refunded
+ * @param cb function to call on each result
  * @param cb_cls closure for @a cb
  * @return transaction status code
  */
 static enum GNUNET_DB_QueryStatus
-postgres_select_recoup_refresh_above_serial_id (
+postgres_select_purse_deposits_by_purse (
   void *cls,
-  uint64_t serial_id,
-  TALER_EXCHANGEDB_RecoupRefreshCallback cb,
+  const struct TALER_PurseContractPublicKeyP *purse_pub,
+  TALER_EXCHANGEDB_PurseRefundCoinCallback cb,
   void *cb_cls)
 {
   struct PostgresClosure *pg = cls;
   struct GNUNET_PQ_QueryParam params[] = {
-    GNUNET_PQ_query_param_uint64 (&serial_id),
+    GNUNET_PQ_query_param_auto_from_type (purse_pub),
     GNUNET_PQ_query_param_end
   };
-  struct RecoupRefreshSerialContext psc = {
+  struct PurseRefundCoinContext dsc = {
     .cb = cb,
     .cb_cls = cb_cls,
     .pg = pg,
@@ -7559,164 +3754,26 @@ postgres_select_recoup_refresh_above_serial_id (
   enum GNUNET_DB_QueryStatus qs;
 
   qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn,
-                                             "recoup_refresh_get_incr",
+                                             
"audit_get_purse_deposits_by_purse",
                                              params,
-                                             &recoup_refresh_serial_helper_cb,
-                                             &psc);
-  if (GNUNET_OK != psc.status)
+                                             &purse_refund_coin_helper_cb,
+                                             &dsc);
+  if (GNUNET_OK != dsc.status)
     return GNUNET_DB_STATUS_HARD_ERROR;
   return qs;
 }
 
 
 /**
- * Obtain information about which reserve a coin was generated
- * from given the hash of the blinded coin.
- *
- * @param cls closure
- * @param bch hash that uniquely identifies the withdraw request
- * @param[out] reserve_pub set to information about the reserve (on success 
only)
- * @param[out] reserve_out_serial_id set to row of the @a h_blind_ev in 
reserves_out
- * @return transaction status code
- */
-static enum GNUNET_DB_QueryStatus
-postgres_get_reserve_by_h_blind (
-  void *cls,
-  const struct TALER_BlindedCoinHashP *bch,
-  struct TALER_ReservePublicKeyP *reserve_pub,
-  uint64_t *reserve_out_serial_id)
-{
-  struct PostgresClosure *pg = cls;
-  struct GNUNET_PQ_QueryParam params[] = {
-    GNUNET_PQ_query_param_auto_from_type (bch),
-    GNUNET_PQ_query_param_end
-  };
-  struct GNUNET_PQ_ResultSpec rs[] = {
-    GNUNET_PQ_result_spec_auto_from_type ("reserve_pub",
-                                          reserve_pub),
-    GNUNET_PQ_result_spec_uint64 ("reserve_out_serial_id",
-                                  reserve_out_serial_id),
-    GNUNET_PQ_result_spec_end
-  };
-
-  return GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
-                                                   "reserve_by_h_blind",
-                                                   params,
-                                                   rs);
-}
-
-
-/**
- * Obtain information about which old coin a coin was refreshed
- * given the hash of the blinded (fresh) coin.
- *
- * @param cls closure
- * @param h_blind_ev hash of the blinded coin
- * @param[out] old_coin_pub set to information about the old coin (on success 
only)
- * @param[out] rrc_serial set to serial number of the entry in the database
- * @return transaction status code
- */
-static enum GNUNET_DB_QueryStatus
-postgres_get_old_coin_by_h_blind (
-  void *cls,
-  const struct TALER_BlindedCoinHashP *h_blind_ev,
-  struct TALER_CoinSpendPublicKeyP *old_coin_pub,
-  uint64_t *rrc_serial)
-{
-  struct PostgresClosure *pg = cls;
-  struct GNUNET_PQ_QueryParam params[] = {
-    GNUNET_PQ_query_param_auto_from_type (h_blind_ev),
-    GNUNET_PQ_query_param_end
-  };
-  struct GNUNET_PQ_ResultSpec rs[] = {
-    GNUNET_PQ_result_spec_auto_from_type ("old_coin_pub",
-                                          old_coin_pub),
-    GNUNET_PQ_result_spec_uint64 ("rrc_serial",
-                                  rrc_serial),
-    GNUNET_PQ_result_spec_end
-  };
-
-  return GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
-                                                   "old_coin_by_h_blind",
-                                                   params,
-                                                   rs);
-}
-
-
-/**
- * Store information that a denomination key was revoked
- * in the database.
- *
- * @param cls closure
- * @param denom_pub_hash hash of the revoked denomination key
- * @param master_sig signature affirming the revocation
- * @return transaction status code
- */
-static enum GNUNET_DB_QueryStatus
-postgres_insert_denomination_revocation (
-  void *cls,
-  const struct TALER_DenominationHashP *denom_pub_hash,
-  const struct TALER_MasterSignatureP *master_sig)
-{
-  struct PostgresClosure *pg = cls;
-  struct GNUNET_PQ_QueryParam params[] = {
-    GNUNET_PQ_query_param_auto_from_type (denom_pub_hash),
-    GNUNET_PQ_query_param_auto_from_type (master_sig),
-    GNUNET_PQ_query_param_end
-  };
-
-  return GNUNET_PQ_eval_prepared_non_select (pg->conn,
-                                             "denomination_revocation_insert",
-                                             params);
-}
-
-
-/**
- * Obtain information about a denomination key's revocation from
- * the database.
- *
- * @param cls closure
- * @param denom_pub_hash hash of the revoked denomination key
- * @param[out] master_sig signature affirming the revocation
- * @param[out] rowid row where the information is stored
- * @return transaction status code
- */
-static enum GNUNET_DB_QueryStatus
-postgres_get_denomination_revocation (
-  void *cls,
-  const struct TALER_DenominationHashP *denom_pub_hash,
-  struct TALER_MasterSignatureP *master_sig,
-  uint64_t *rowid)
-{
-  struct PostgresClosure *pg = cls;
-  struct GNUNET_PQ_QueryParam params[] = {
-    GNUNET_PQ_query_param_auto_from_type (denom_pub_hash),
-    GNUNET_PQ_query_param_end
-  };
-  struct GNUNET_PQ_ResultSpec rs[] = {
-    GNUNET_PQ_result_spec_auto_from_type ("master_sig",
-                                          master_sig),
-    GNUNET_PQ_result_spec_uint64 ("denom_revocations_serial_id",
-                                  rowid),
-    GNUNET_PQ_result_spec_end
-  };
-
-  return GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
-                                                   
"denomination_revocation_get",
-                                                   params,
-                                                   rs);
-}
-
-
-/**
- * Closure for #missing_wire_cb().
+ * Closure for #refreshs_serial_helper_cb().
  */
-struct MissingWireContext
+struct RefreshsSerialContext
 {
+
   /**
-   * Function to call per result.
+   * Callback to call.
    */
-  TALER_EXCHANGEDB_WireMissingCallback cb;
+  TALER_EXCHANGEDB_RefreshesCallback cb;
 
   /**
    * Closure for @e cb.
@@ -7729,98 +3786,111 @@ struct MissingWireContext
   struct PostgresClosure *pg;
 
   /**
-   * Set to #GNUNET_SYSERR on error.
+   * Status code, set to #GNUNET_SYSERR on hard errors.
    */
   enum GNUNET_GenericReturnValue status;
 };
 
 
 /**
- * Invoke the callback for each result.
+ * Helper function to be called with the results of a SELECT statement
+ * that has returned @a num_results results.
  *
- * @param cls a `struct MissingWireContext *`
- * @param result SQL result
- * @param num_results number of rows in @a result
+ * @param cls closure of type `struct RefreshsSerialContext`
+ * @param result the postgres result
+ * @param num_results the number of results in @a result
  */
 static void
-missing_wire_cb (void *cls,
-                 PGresult *result,
-                 unsigned int num_results)
+refreshs_serial_helper_cb (void *cls,
+                           PGresult *result,
+                           unsigned int num_results)
 {
-  struct MissingWireContext *mwc = cls;
-  struct PostgresClosure *pg = mwc->pg;
+  struct RefreshsSerialContext *rsc = cls;
+  struct PostgresClosure *pg = rsc->pg;
 
-  while (0 < num_results)
+  for (unsigned int i = 0; i<num_results; i++)
   {
-    uint64_t rowid;
+    struct TALER_DenominationPublicKey denom_pub;
     struct TALER_CoinSpendPublicKeyP coin_pub;
-    struct TALER_Amount amount;
-    char *payto_uri;
-    struct GNUNET_TIME_Timestamp deadline;
-    bool done;
+    struct TALER_CoinSpendSignatureP coin_sig;
+    struct TALER_AgeCommitmentHash h_age_commitment;
+    bool ac_isnull;
+    struct TALER_Amount amount_with_fee;
+    uint32_t noreveal_index;
+    uint64_t rowid;
+    struct TALER_RefreshCommitmentP rc;
     struct GNUNET_PQ_ResultSpec rs[] = {
-      GNUNET_PQ_result_spec_uint64 ("deposit_serial_id",
-                                    &rowid),
-      GNUNET_PQ_result_spec_auto_from_type ("coin_pub",
+      TALER_PQ_result_spec_denom_pub ("denom_pub",
+                                      &denom_pub),
+      GNUNET_PQ_result_spec_allow_null (
+        GNUNET_PQ_result_spec_auto_from_type ("age_commitment_hash",
+                                              &h_age_commitment),
+        &ac_isnull),
+      GNUNET_PQ_result_spec_auto_from_type ("old_coin_pub",
                                             &coin_pub),
+      GNUNET_PQ_result_spec_auto_from_type ("old_coin_sig",
+                                            &coin_sig),
       TALER_PQ_RESULT_SPEC_AMOUNT ("amount_with_fee",
-                                   &amount),
-      GNUNET_PQ_result_spec_string ("payto_uri",
-                                    &payto_uri),
-      GNUNET_PQ_result_spec_timestamp ("wire_deadline",
-                                       &deadline),
-      GNUNET_PQ_result_spec_bool ("done",
-                                  &done),
+                                   &amount_with_fee),
+      GNUNET_PQ_result_spec_uint32 ("noreveal_index",
+                                    &noreveal_index),
+      GNUNET_PQ_result_spec_uint64 ("melt_serial_id",
+                                    &rowid),
+      GNUNET_PQ_result_spec_auto_from_type ("rc",
+                                            &rc),
       GNUNET_PQ_result_spec_end
     };
+    enum GNUNET_GenericReturnValue ret;
 
     if (GNUNET_OK !=
         GNUNET_PQ_extract_result (result,
                                   rs,
-                                  --num_results))
+                                  i))
     {
       GNUNET_break (0);
-      mwc->status = GNUNET_SYSERR;
+      rsc->status = GNUNET_SYSERR;
       return;
     }
-    mwc->cb (mwc->cb_cls,
-             rowid,
-             &coin_pub,
-             &amount,
-             payto_uri,
-             deadline,
-             done);
+
+    ret = rsc->cb (rsc->cb_cls,
+                   rowid,
+                   &denom_pub,
+                   ac_isnull ? NULL : &h_age_commitment,
+                   &coin_pub,
+                   &coin_sig,
+                   &amount_with_fee,
+                   noreveal_index,
+                   &rc);
     GNUNET_PQ_cleanup_result (rs);
+    if (GNUNET_OK != ret)
+      break;
   }
 }
 
 
 /**
- * Select all of those deposits in the database for which we do
- * not have a wire transfer (or a refund) and which should have
- * been deposited between @a start_date and @a end_date.
+ * Select refresh sessions above @a serial_id in monotonically increasing
+ * order.
  *
  * @param cls closure
- * @param start_date lower bound on the requested wire execution date
- * @param end_date upper bound on the requested wire execution date
- * @param cb function to call on all such deposits
+ * @param serial_id highest serial ID to exclude (select strictly larger)
+ * @param cb function to call on each result
  * @param cb_cls closure for @a cb
  * @return transaction status code
  */
 static enum GNUNET_DB_QueryStatus
-postgres_select_deposits_missing_wire (void *cls,
-                                       struct GNUNET_TIME_Timestamp start_date,
-                                       struct GNUNET_TIME_Timestamp end_date,
-                                       TALER_EXCHANGEDB_WireMissingCallback cb,
-                                       void *cb_cls)
+postgres_select_refreshes_above_serial_id (
+  void *cls,
+  uint64_t serial_id,
+  TALER_EXCHANGEDB_RefreshesCallback cb,
+  void *cb_cls)
 {
   struct PostgresClosure *pg = cls;
   struct GNUNET_PQ_QueryParam params[] = {
-    GNUNET_PQ_query_param_timestamp (&start_date),
-    GNUNET_PQ_query_param_timestamp (&end_date),
+    GNUNET_PQ_query_param_uint64 (&serial_id),
     GNUNET_PQ_query_param_end
   };
-  struct MissingWireContext mwc = {
+  struct RefreshsSerialContext rsc = {
     .cb = cb,
     .cb_cls = cb_cls,
     .pg = pg,
@@ -7829,219 +3899,26 @@ postgres_select_deposits_missing_wire (void *cls,
   enum GNUNET_DB_QueryStatus qs;
 
   qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn,
-                                             "deposits_get_overdue",
+                                             
"audit_get_refresh_commitments_incr",
                                              params,
-                                             &missing_wire_cb,
-                                             &mwc);
-  if (GNUNET_OK != mwc.status)
+                                             &refreshs_serial_helper_cb,
+                                             &rsc);
+  if (GNUNET_OK != rsc.status)
     return GNUNET_DB_STATUS_HARD_ERROR;
   return qs;
 }
 
 
 /**
- * Check the last date an auditor was modified.
- *
- * @param cls closure
- * @param auditor_pub key to look up information for
- * @param[out] last_date last modification date to auditor status
- * @return transaction status code
- */
-static enum GNUNET_DB_QueryStatus
-postgres_lookup_auditor_timestamp (
-  void *cls,
-  const struct TALER_AuditorPublicKeyP *auditor_pub,
-  struct GNUNET_TIME_Timestamp *last_date)
-{
-  struct PostgresClosure *pg = cls;
-  struct GNUNET_PQ_QueryParam params[] = {
-    GNUNET_PQ_query_param_auto_from_type (auditor_pub),
-    GNUNET_PQ_query_param_end
-  };
-  struct GNUNET_PQ_ResultSpec rs[] = {
-    GNUNET_PQ_result_spec_timestamp ("last_change",
-                                     last_date),
-    GNUNET_PQ_result_spec_end
-  };
-
-  return GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
-                                                   "lookup_auditor_timestamp",
-                                                   params,
-                                                   rs);
-}
-
-
-/**
- * Lookup current state of an auditor.
- *
- * @param cls closure
- * @param auditor_pub key to look up information for
- * @param[out] auditor_url set to the base URL of the auditor's REST API; 
memory to be
- *            released by the caller!
- * @param[out] enabled set if the auditor is currently in use
- * @return transaction status code
- */
-static enum GNUNET_DB_QueryStatus
-postgres_lookup_auditor_status (
-  void *cls,
-  const struct TALER_AuditorPublicKeyP *auditor_pub,
-  char **auditor_url,
-  bool *enabled)
-{
-  struct PostgresClosure *pg = cls;
-  struct GNUNET_PQ_QueryParam params[] = {
-    GNUNET_PQ_query_param_auto_from_type (auditor_pub),
-    GNUNET_PQ_query_param_end
-  };
-  struct GNUNET_PQ_ResultSpec rs[] = {
-    GNUNET_PQ_result_spec_string ("auditor_url",
-                                  auditor_url),
-    GNUNET_PQ_result_spec_bool ("is_active",
-                                enabled),
-    GNUNET_PQ_result_spec_end
-  };
-
-  return GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
-                                                   "lookup_auditor_status",
-                                                   params,
-                                                   rs);
-}
-
-
-/**
- * Insert information about an auditor that will audit this exchange.
- *
- * @param cls closure
- * @param auditor_pub key of the auditor
- * @param auditor_url base URL of the auditor's REST service
- * @param auditor_name name of the auditor (for humans)
- * @param start_date date when the auditor was added by the offline system
- *                      (only to be used for replay detection)
- * @return transaction status code
- */
-static enum GNUNET_DB_QueryStatus
-postgres_insert_auditor (void *cls,
-                         const struct TALER_AuditorPublicKeyP *auditor_pub,
-                         const char *auditor_url,
-                         const char *auditor_name,
-                         struct GNUNET_TIME_Timestamp start_date)
-{
-  struct PostgresClosure *pg = cls;
-  struct GNUNET_PQ_QueryParam params[] = {
-    GNUNET_PQ_query_param_auto_from_type (auditor_pub),
-    GNUNET_PQ_query_param_string (auditor_name),
-    GNUNET_PQ_query_param_string (auditor_url),
-    GNUNET_PQ_query_param_timestamp (&start_date),
-    GNUNET_PQ_query_param_end
-  };
-
-  return GNUNET_PQ_eval_prepared_non_select (pg->conn,
-                                             "insert_auditor",
-                                             params);
-}
-
-
-/**
- * Check the last date an exchange wire account was modified.
- *
- * @param cls closure
- * @param payto_uri key to look up information for
- * @param[out] last_date last modification date to auditor status
- * @return transaction status code
- */
-static enum GNUNET_DB_QueryStatus
-postgres_lookup_wire_timestamp (void *cls,
-                                const char *payto_uri,
-                                struct GNUNET_TIME_Timestamp *last_date)
-{
-  struct PostgresClosure *pg = cls;
-  struct GNUNET_PQ_QueryParam params[] = {
-    GNUNET_PQ_query_param_string (payto_uri),
-    GNUNET_PQ_query_param_end
-  };
-  struct GNUNET_PQ_ResultSpec rs[] = {
-    GNUNET_PQ_result_spec_timestamp ("last_change",
-                                     last_date),
-    GNUNET_PQ_result_spec_end
-  };
-
-  return GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
-                                                   "lookup_wire_timestamp",
-                                                   params,
-                                                   rs);
-}
-
-
-/**
- * Insert information about an wire account used by this exchange.
- *
- * @param cls closure
- * @param payto_uri wire account of the exchange
- * @param start_date date when the account was added by the offline system
- *                      (only to be used for replay detection)
- * @param master_sig public signature affirming the existence of the account,
- *         must be of purpose #TALER_SIGNATURE_MASTER_WIRE_DETAILS
- * @return transaction status code
- */
-static enum GNUNET_DB_QueryStatus
-postgres_insert_wire (void *cls,
-                      const char *payto_uri,
-                      struct GNUNET_TIME_Timestamp start_date,
-                      const struct TALER_MasterSignatureP *master_sig)
-{
-  struct PostgresClosure *pg = cls;
-  struct GNUNET_PQ_QueryParam params[] = {
-    GNUNET_PQ_query_param_string (payto_uri),
-    GNUNET_PQ_query_param_auto_from_type (master_sig),
-    GNUNET_PQ_query_param_timestamp (&start_date),
-    GNUNET_PQ_query_param_end
-  };
-
-  return GNUNET_PQ_eval_prepared_non_select (pg->conn,
-                                             "insert_wire",
-                                             params);
-}
-
-
-/**
- * Update information about a wire account of the exchange.
- *
- * @param cls closure
- * @param payto_uri account the update is about
- * @param change_date date when the account status was last changed
- *                      (only to be used for replay detection)
- * @param enabled true to enable, false to disable (the actual change)
- * @return transaction status code
+ * Closure for #refunds_serial_helper_cb().
  */
-static enum GNUNET_DB_QueryStatus
-postgres_update_wire (void *cls,
-                      const char *payto_uri,
-                      struct GNUNET_TIME_Timestamp change_date,
-                      bool enabled)
+struct RefundsSerialContext
 {
-  struct PostgresClosure *pg = cls;
-  struct GNUNET_PQ_QueryParam params[] = {
-    GNUNET_PQ_query_param_string (payto_uri),
-    GNUNET_PQ_query_param_bool (enabled),
-    GNUNET_PQ_query_param_timestamp (&change_date),
-    GNUNET_PQ_query_param_end
-  };
 
-  return GNUNET_PQ_eval_prepared_non_select (pg->conn,
-                                             "update_wire",
-                                             params);
-}
-
-
-/**
- * Closure for #get_wire_accounts_cb().
- */
-struct GetWireAccountsContext
-{
   /**
-   * Function to call per result.
+   * Callback to call.
    */
-  TALER_EXCHANGEDB_WireAccountCallback cb;
+  TALER_EXCHANGEDB_RefundCallback cb;
 
   /**
    * Closure for @e cb.
@@ -8049,38 +3926,59 @@ struct GetWireAccountsContext
   void *cb_cls;
 
   /**
-   * Flag set to #GNUNET_OK as long as everything is fine.
+   * Plugin context.
    */
-  enum GNUNET_GenericReturnValue status;
+  struct PostgresClosure *pg;
 
+  /**
+   * Status code, set to #GNUNET_SYSERR on hard errors.
+   */
+  enum GNUNET_GenericReturnValue status;
 };
 
 
 /**
- * Invoke the callback for each result.
+ * Helper function to be called with the results of a SELECT statement
+ * that has returned @a num_results results.
  *
- * @param cls a `struct MissingWireContext *`
- * @param result SQL result
- * @param num_results number of rows in @a result
+ * @param cls closure of type `struct RefundsSerialContext`
+ * @param result the postgres result
+ * @param num_results the number of results in @a result
  */
 static void
-get_wire_accounts_cb (void *cls,
-                      PGresult *result,
-                      unsigned int num_results)
+refunds_serial_helper_cb (void *cls,
+                          PGresult *result,
+                          unsigned int num_results)
 {
-  struct GetWireAccountsContext *ctx = cls;
+  struct RefundsSerialContext *rsc = cls;
+  struct PostgresClosure *pg = rsc->pg;
 
-  for (unsigned int i = 0; i < num_results; i++)
+  for (unsigned int i = 0; i<num_results; i++)
   {
-    char *payto_uri;
-    struct TALER_MasterSignatureP master_sig;
+    struct TALER_EXCHANGEDB_Refund refund;
+    struct TALER_DenominationPublicKey denom_pub;
+    uint64_t rowid;
+    bool full_refund;
     struct GNUNET_PQ_ResultSpec rs[] = {
-      GNUNET_PQ_result_spec_string ("payto_uri",
-                                    &payto_uri),
-      GNUNET_PQ_result_spec_auto_from_type ("master_sig",
-                                            &master_sig),
+      GNUNET_PQ_result_spec_auto_from_type ("merchant_pub",
+                                            &refund.details.merchant_pub),
+      GNUNET_PQ_result_spec_auto_from_type ("merchant_sig",
+                                            &refund.details.merchant_sig),
+      GNUNET_PQ_result_spec_auto_from_type ("h_contract_terms",
+                                            &refund.details.h_contract_terms),
+      GNUNET_PQ_result_spec_uint64 ("rtransaction_id",
+                                    &refund.details.rtransaction_id),
+      TALER_PQ_result_spec_denom_pub ("denom_pub",
+                                      &denom_pub),
+      GNUNET_PQ_result_spec_auto_from_type ("coin_pub",
+                                            &refund.coin.coin_pub),
+      TALER_PQ_RESULT_SPEC_AMOUNT ("amount_with_fee",
+                                   &refund.details.refund_amount),
+      GNUNET_PQ_result_spec_uint64 ("refund_serial_id",
+                                    &rowid),
       GNUNET_PQ_result_spec_end
     };
+    enum GNUNET_GenericReturnValue ret;
 
     if (GNUNET_OK !=
         GNUNET_PQ_extract_result (result,
@@ -8088,62 +3986,113 @@ get_wire_accounts_cb (void *cls,
                                   i))
     {
       GNUNET_break (0);
-      ctx->status = GNUNET_SYSERR;
+      rsc->status = GNUNET_SYSERR;
       return;
     }
-    ctx->cb (ctx->cb_cls,
-             payto_uri,
-             &master_sig);
+    {
+      struct GNUNET_PQ_QueryParam params[] = {
+        GNUNET_PQ_query_param_uint64 (&rowid),
+        GNUNET_PQ_query_param_end
+      };
+      struct TALER_Amount amount_with_fee;
+      uint64_t s_f;
+      uint64_t s_v;
+      struct GNUNET_PQ_ResultSpec rs2[] = {
+        GNUNET_PQ_result_spec_uint64 ("s_v",
+                                      &s_v),
+        GNUNET_PQ_result_spec_uint64 ("s_f",
+                                      &s_f),
+        TALER_PQ_RESULT_SPEC_AMOUNT ("amount_with_fee",
+                                     &amount_with_fee),
+        GNUNET_PQ_result_spec_end
+      };
+      enum GNUNET_DB_QueryStatus qs;
+
+      qs = GNUNET_PQ_eval_prepared_singleton_select (
+        pg->conn,
+        "test_refund_full",
+        params,
+        rs2);
+      if (qs <= 0)
+      {
+        GNUNET_break (0);
+        rsc->status = GNUNET_SYSERR;
+        return;
+      }
+      /* normalize */
+      s_v += s_f / TALER_AMOUNT_FRAC_BASE;
+      s_f %= TALER_AMOUNT_FRAC_BASE;
+      full_refund = (s_v >= amount_with_fee.value) &&
+                    (s_f >= amount_with_fee.fraction);
+    }
+    ret = rsc->cb (rsc->cb_cls,
+                   rowid,
+                   &denom_pub,
+                   &refund.coin.coin_pub,
+                   &refund.details.merchant_pub,
+                   &refund.details.merchant_sig,
+                   &refund.details.h_contract_terms,
+                   refund.details.rtransaction_id,
+                   full_refund,
+                   &refund.details.refund_amount);
     GNUNET_PQ_cleanup_result (rs);
+    if (GNUNET_OK != ret)
+      break;
   }
 }
 
 
 /**
- * Obtain information about the enabled wire accounts of the exchange.
+ * Select refunds above @a serial_id in monotonically increasing
+ * order.
  *
  * @param cls closure
- * @param cb function to call on each account
+ * @param serial_id highest serial ID to exclude (select strictly larger)
+ * @param cb function to call on each result
  * @param cb_cls closure for @a cb
  * @return transaction status code
  */
 static enum GNUNET_DB_QueryStatus
-postgres_get_wire_accounts (void *cls,
-                            TALER_EXCHANGEDB_WireAccountCallback cb,
-                            void *cb_cls)
+postgres_select_refunds_above_serial_id (
+  void *cls,
+  uint64_t serial_id,
+  TALER_EXCHANGEDB_RefundCallback cb,
+  void *cb_cls)
 {
   struct PostgresClosure *pg = cls;
-  struct GetWireAccountsContext ctx = {
+  struct GNUNET_PQ_QueryParam params[] = {
+    GNUNET_PQ_query_param_uint64 (&serial_id),
+    GNUNET_PQ_query_param_end
+  };
+  struct RefundsSerialContext rsc = {
     .cb = cb,
     .cb_cls = cb_cls,
+    .pg = pg,
     .status = GNUNET_OK
   };
-  struct GNUNET_PQ_QueryParam params[] = {
-    GNUNET_PQ_query_param_end
-  };
   enum GNUNET_DB_QueryStatus qs;
 
   qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn,
-                                             "get_wire_accounts",
+                                             "audit_get_refunds_incr",
                                              params,
-                                             &get_wire_accounts_cb,
-                                             &ctx);
-  if (GNUNET_OK != ctx.status)
+                                             &refunds_serial_helper_cb,
+                                             &rsc);
+  if (GNUNET_OK != rsc.status)
     return GNUNET_DB_STATUS_HARD_ERROR;
   return qs;
-
 }
 
 
 /**
- * Closure for #get_wire_fees_cb().
+ * Closure for #reserves_in_serial_helper_cb().
  */
-struct GetWireFeesContext
+struct ReservesInSerialContext
 {
+
   /**
-   * Function to call per result.
+   * Callback to call.
    */
-  TALER_EXCHANGEDB_WireFeeCallback cb;
+  TALER_EXCHANGEDB_ReserveInCallback cb;
 
   /**
    * Closure for @e cb.
@@ -8156,47 +4105,52 @@ struct GetWireFeesContext
   struct PostgresClosure *pg;
 
   /**
-   * Flag set to #GNUNET_OK as long as everything is fine.
+   * Status code, set to #GNUNET_SYSERR on hard errors.
    */
   enum GNUNET_GenericReturnValue status;
-
 };
 
 
 /**
- * Invoke the callback for each result.
+ * Helper function to be called with the results of a SELECT statement
+ * that has returned @a num_results results.
  *
- * @param cls a `struct GetWireFeesContext *`
- * @param result SQL result
- * @param num_results number of rows in @a result
+ * @param cls closure of type `struct ReservesInSerialContext`
+ * @param result the postgres result
+ * @param num_results the number of results in @a result
  */
 static void
-get_wire_fees_cb (void *cls,
-                  PGresult *result,
-                  unsigned int num_results)
+reserves_in_serial_helper_cb (void *cls,
+                              PGresult *result,
+                              unsigned int num_results)
 {
-  struct GetWireFeesContext *ctx = cls;
-  struct PostgresClosure *pg = ctx->pg;
+  struct ReservesInSerialContext *risc = cls;
+  struct PostgresClosure *pg = risc->pg;
 
-  for (unsigned int i = 0; i < num_results; i++)
+  for (unsigned int i = 0; i<num_results; i++)
   {
-    struct TALER_MasterSignatureP master_sig;
-    struct TALER_WireFeeSet fees;
-    struct GNUNET_TIME_Timestamp start_date;
-    struct GNUNET_TIME_Timestamp end_date;
+    struct TALER_ReservePublicKeyP reserve_pub;
+    struct TALER_Amount credit;
+    char *sender_account_details;
+    struct GNUNET_TIME_Timestamp execution_date;
+    uint64_t rowid;
+    uint64_t wire_reference;
     struct GNUNET_PQ_ResultSpec rs[] = {
-      TALER_PQ_RESULT_SPEC_AMOUNT ("wire_fee",
-                                   &fees.wire),
-      TALER_PQ_RESULT_SPEC_AMOUNT ("closing_fee",
-                                   &fees.closing),
-      GNUNET_PQ_result_spec_timestamp ("start_date",
-                                       &start_date),
-      GNUNET_PQ_result_spec_timestamp ("end_date",
-                                       &end_date),
-      GNUNET_PQ_result_spec_auto_from_type ("master_sig",
-                                            &master_sig),
+      GNUNET_PQ_result_spec_auto_from_type ("reserve_pub",
+                                            &reserve_pub),
+      GNUNET_PQ_result_spec_uint64 ("wire_reference",
+                                    &wire_reference),
+      TALER_PQ_RESULT_SPEC_AMOUNT ("credit",
+                                   &credit),
+      GNUNET_PQ_result_spec_timestamp ("execution_date",
+                                       &execution_date),
+      GNUNET_PQ_result_spec_string ("sender_account_details",
+                                    &sender_account_details),
+      GNUNET_PQ_result_spec_uint64 ("reserve_in_serial_id",
+                                    &rowid),
       GNUNET_PQ_result_spec_end
     };
+    enum GNUNET_GenericReturnValue ret;
 
     if (GNUNET_OK !=
         GNUNET_PQ_extract_result (result,
@@ -8204,41 +4158,46 @@ get_wire_fees_cb (void *cls,
                                   i))
     {
       GNUNET_break (0);
-      ctx->status = GNUNET_SYSERR;
+      risc->status = GNUNET_SYSERR;
       return;
     }
-    ctx->cb (ctx->cb_cls,
-             &fees,
-             start_date,
-             end_date,
-             &master_sig);
+    ret = risc->cb (risc->cb_cls,
+                    rowid,
+                    &reserve_pub,
+                    &credit,
+                    sender_account_details,
+                    wire_reference,
+                    execution_date);
     GNUNET_PQ_cleanup_result (rs);
+    if (GNUNET_OK != ret)
+      break;
   }
 }
 
 
 /**
- * Obtain information about the fee structure of the exchange for
- * a given @a wire_method
+ * Select inbound wire transfers into reserves_in above @a serial_id
+ * in monotonically increasing order.
  *
  * @param cls closure
- * @param wire_method which wire method to obtain fees for
- * @param cb function to call on each account
+ * @param serial_id highest serial ID to exclude (select strictly larger)
+ * @param cb function to call on each result
  * @param cb_cls closure for @a cb
  * @return transaction status code
  */
 static enum GNUNET_DB_QueryStatus
-postgres_get_wire_fees (void *cls,
-                        const char *wire_method,
-                        TALER_EXCHANGEDB_WireFeeCallback cb,
-                        void *cb_cls)
+postgres_select_reserves_in_above_serial_id (
+  void *cls,
+  uint64_t serial_id,
+  TALER_EXCHANGEDB_ReserveInCallback cb,
+  void *cb_cls)
 {
   struct PostgresClosure *pg = cls;
   struct GNUNET_PQ_QueryParam params[] = {
-    GNUNET_PQ_query_param_string (wire_method),
+    GNUNET_PQ_query_param_uint64 (&serial_id),
     GNUNET_PQ_query_param_end
   };
-  struct GetWireFeesContext ctx = {
+  struct ReservesInSerialContext risc = {
     .cb = cb,
     .cb_cls = cb_cls,
     .pg = pg,
@@ -8247,798 +4206,715 @@ postgres_get_wire_fees (void *cls,
   enum GNUNET_DB_QueryStatus qs;
 
   qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn,
-                                             "get_wire_fees",
+                                             
"audit_reserves_in_get_transactions_incr",
                                              params,
-                                             &get_wire_fees_cb,
-                                             &ctx);
-  if (GNUNET_OK != ctx.status)
+                                             &reserves_in_serial_helper_cb,
+                                             &risc);
+  if (GNUNET_OK != risc.status)
     return GNUNET_DB_STATUS_HARD_ERROR;
   return qs;
 }
 
 
 /**
- * Store information about a revoked online signing key.
- *
- * @param cls closure
- * @param exchange_pub exchange online signing key that was revoked
- * @param master_sig signature affirming the revocation
- * @return transaction status code
- */
-static enum GNUNET_DB_QueryStatus
-postgres_insert_signkey_revocation (
-  void *cls,
-  const struct TALER_ExchangePublicKeyP *exchange_pub,
-  const struct TALER_MasterSignatureP *master_sig)
-{
-  struct PostgresClosure *pg = cls;
-  struct GNUNET_PQ_QueryParam params[] = {
-    GNUNET_PQ_query_param_auto_from_type (exchange_pub),
-    GNUNET_PQ_query_param_auto_from_type (master_sig),
-    GNUNET_PQ_query_param_end
-  };
-
-  return GNUNET_PQ_eval_prepared_non_select (pg->conn,
-                                             "insert_signkey_revocation",
-                                             params);
-}
-
-
-/**
- * Obtain information about a revoked online signing key.
- *
- * @param cls closure
- * @param exchange_pub exchange online signing key
- * @param[out] master_sig set to signature affirming the revocation (if 
revoked)
- * @return transaction status code
- */
-static enum GNUNET_DB_QueryStatus
-postgres_lookup_signkey_revocation (
-  void *cls,
-  const struct TALER_ExchangePublicKeyP *exchange_pub,
-  struct TALER_MasterSignatureP *master_sig)
-{
-  struct PostgresClosure *pg = cls;
-  struct GNUNET_PQ_QueryParam params[] = {
-    GNUNET_PQ_query_param_auto_from_type (exchange_pub),
-    GNUNET_PQ_query_param_end
-  };
-  struct GNUNET_PQ_ResultSpec rs[] = {
-    GNUNET_PQ_result_spec_auto_from_type ("master_sig",
-                                          master_sig),
-    GNUNET_PQ_result_spec_end
-  };
-
-  return GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
-                                                   "lookup_signkey_revocation",
-                                                   params,
-                                                   rs);
-}
-
-
-/**
- * Lookup information about current denomination key.
+ * Select inbound wire transfers into reserves_in above @a serial_id
+ * in monotonically increasing order by account.
  *
  * @param cls closure
- * @param h_denom_pub hash of the denomination public key
- * @param[out] meta set to various meta data about the key
+ * @param account_name name of the account to select by
+ * @param serial_id highest serial ID to exclude (select strictly larger)
+ * @param cb function to call on each result
+ * @param cb_cls closure for @a cb
  * @return transaction status code
  */
 static enum GNUNET_DB_QueryStatus
-postgres_lookup_denomination_key (
+postgres_select_reserves_in_above_serial_id_by_account (
   void *cls,
-  const struct TALER_DenominationHashP *h_denom_pub,
-  struct TALER_EXCHANGEDB_DenominationKeyMetaData *meta)
+  const char *account_name,
+  uint64_t serial_id,
+  TALER_EXCHANGEDB_ReserveInCallback cb,
+  void *cb_cls)
 {
   struct PostgresClosure *pg = cls;
   struct GNUNET_PQ_QueryParam params[] = {
-    GNUNET_PQ_query_param_auto_from_type (h_denom_pub),
+    GNUNET_PQ_query_param_uint64 (&serial_id),
+    GNUNET_PQ_query_param_string (account_name),
     GNUNET_PQ_query_param_end
   };
-  struct GNUNET_PQ_ResultSpec rs[] = {
-    GNUNET_PQ_result_spec_timestamp ("valid_from",
-                                     &meta->start),
-    GNUNET_PQ_result_spec_timestamp ("expire_withdraw",
-                                     &meta->expire_withdraw),
-    GNUNET_PQ_result_spec_timestamp ("expire_deposit",
-                                     &meta->expire_deposit),
-    GNUNET_PQ_result_spec_timestamp ("expire_legal",
-                                     &meta->expire_legal),
-    TALER_PQ_RESULT_SPEC_AMOUNT ("coin",
-                                 &meta->value),
-    TALER_PQ_RESULT_SPEC_AMOUNT ("fee_withdraw",
-                                 &meta->fees.withdraw),
-    TALER_PQ_RESULT_SPEC_AMOUNT ("fee_deposit",
-                                 &meta->fees.deposit),
-    TALER_PQ_RESULT_SPEC_AMOUNT ("fee_refresh",
-                                 &meta->fees.refresh),
-    TALER_PQ_RESULT_SPEC_AMOUNT ("fee_refund",
-                                 &meta->fees.refund),
-    GNUNET_PQ_result_spec_uint32 ("age_mask",
-                                  &meta->age_mask.bits),
-    GNUNET_PQ_result_spec_end
-  };
-
-  return GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
-                                                   "lookup_denomination_key",
-                                                   params,
-                                                   rs);
-}
-
-
-/**
- * Activate denomination key, turning it into a "current" or "valid"
- * denomination key by adding the master signature.
- *
- * @param cls closure
- * @param h_denom_pub hash of the denomination public key
- * @param denom_pub the actual denomination key
- * @param meta meta data about the denomination
- * @param master_sig master signature to add
- * @return transaction status code
- */
-static enum GNUNET_DB_QueryStatus
-postgres_add_denomination_key (
-  void *cls,
-  const struct TALER_DenominationHashP *h_denom_pub,
-  const struct TALER_DenominationPublicKey *denom_pub,
-  const struct TALER_EXCHANGEDB_DenominationKeyMetaData *meta,
-  const struct TALER_MasterSignatureP *master_sig)
-{
-  struct PostgresClosure *pg = cls;
-  struct GNUNET_PQ_QueryParam iparams[] = {
-    GNUNET_PQ_query_param_auto_from_type (h_denom_pub),
-    TALER_PQ_query_param_denom_pub (denom_pub),
-    GNUNET_PQ_query_param_auto_from_type (master_sig),
-    GNUNET_PQ_query_param_timestamp (&meta->start),
-    GNUNET_PQ_query_param_timestamp (&meta->expire_withdraw),
-    GNUNET_PQ_query_param_timestamp (&meta->expire_deposit),
-    GNUNET_PQ_query_param_timestamp (&meta->expire_legal),
-    TALER_PQ_query_param_amount (&meta->value),
-    TALER_PQ_query_param_amount (&meta->fees.withdraw),
-    TALER_PQ_query_param_amount (&meta->fees.deposit),
-    TALER_PQ_query_param_amount (&meta->fees.refresh),
-    TALER_PQ_query_param_amount (&meta->fees.refund),
-    GNUNET_PQ_query_param_uint32 (&meta->age_mask.bits),
-    GNUNET_PQ_query_param_end
+  struct ReservesInSerialContext risc = {
+    .cb = cb,
+    .cb_cls = cb_cls,
+    .pg = pg,
+    .status = GNUNET_OK
   };
+  enum GNUNET_DB_QueryStatus qs;
 
-  /* Sanity check: ensure fees match coin currency */
-  GNUNET_assert (GNUNET_YES ==
-                 TALER_denom_fee_check_currency (meta->value.currency,
-                                                 &meta->fees));
-  return GNUNET_PQ_eval_prepared_non_select (pg->conn,
-                                             "add_denomination_key",
-                                             iparams);
+  qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn,
+                                             
"audit_reserves_in_get_transactions_incr_by_account",
+                                             params,
+                                             &reserves_in_serial_helper_cb,
+                                             &risc);
+  if (GNUNET_OK != risc.status)
+    return GNUNET_DB_STATUS_HARD_ERROR;
+  return qs;
 }
 
 
 /**
- * Lookup signing key meta data.
- *
- * @param cls closure
- * @param exchange_pub the exchange online signing public key
- * @param[out] meta meta data about @a exchange_pub
- * @return transaction status code
+ * Closure for #reserves_out_serial_helper_cb().
  */
-static enum GNUNET_DB_QueryStatus
-postgres_lookup_signing_key (
-  void *cls,
-  const struct TALER_ExchangePublicKeyP *exchange_pub,
-  struct TALER_EXCHANGEDB_SignkeyMetaData *meta)
+struct ReservesOutSerialContext
 {
-  struct PostgresClosure *pg = cls;
-  struct GNUNET_PQ_QueryParam params[] = {
-    GNUNET_PQ_query_param_auto_from_type (exchange_pub),
-    GNUNET_PQ_query_param_end
-  };
-  struct GNUNET_PQ_ResultSpec rs[] = {
-    GNUNET_PQ_result_spec_timestamp ("valid_from",
-                                     &meta->start),
-    GNUNET_PQ_result_spec_timestamp ("expire_sign",
-                                     &meta->expire_sign),
-    GNUNET_PQ_result_spec_timestamp ("expire_legal",
-                                     &meta->expire_legal),
-    GNUNET_PQ_result_spec_end
-  };
 
-  return GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
-                                                   "lookup_signing_key",
-                                                   params,
-                                                   rs);
-}
+  /**
+   * Callback to call.
+   */
+  TALER_EXCHANGEDB_WithdrawCallback cb;
+
+  /**
+   * Closure for @e cb.
+   */
+  void *cb_cls;
+
+  /**
+   * Plugin context.
+   */
+  struct PostgresClosure *pg;
+
+  /**
+   * Status code, set to #GNUNET_SYSERR on hard errors.
+   */
+  enum GNUNET_GenericReturnValue status;
+};
 
 
 /**
- * Insert information about an auditor auditing a denomination key.
+ * Helper function to be called with the results of a SELECT statement
+ * that has returned @a num_results results.
  *
- * @param cls closure
- * @param h_denom_pub the audited denomination
- * @param auditor_pub the auditor's key
- * @param auditor_sig signature affirming the auditor's audit activity
- * @return transaction status code
+ * @param cls closure of type `struct ReservesOutSerialContext`
+ * @param result the postgres result
+ * @param num_results the number of results in @a result
  */
-static enum GNUNET_DB_QueryStatus
-postgres_insert_auditor_denom_sig (
-  void *cls,
-  const struct TALER_DenominationHashP *h_denom_pub,
-  const struct TALER_AuditorPublicKeyP *auditor_pub,
-  const struct TALER_AuditorSignatureP *auditor_sig)
+static void
+reserves_out_serial_helper_cb (void *cls,
+                               PGresult *result,
+                               unsigned int num_results)
 {
-  struct PostgresClosure *pg = cls;
-  struct GNUNET_PQ_QueryParam params[] = {
-    GNUNET_PQ_query_param_auto_from_type (auditor_pub),
-    GNUNET_PQ_query_param_auto_from_type (h_denom_pub),
-    GNUNET_PQ_query_param_auto_from_type (auditor_sig),
-    GNUNET_PQ_query_param_end
-  };
+  struct ReservesOutSerialContext *rosc = cls;
+  struct PostgresClosure *pg = rosc->pg;
 
-  return GNUNET_PQ_eval_prepared_non_select (pg->conn,
-                                             "insert_auditor_denom_sig",
-                                             params);
+  for (unsigned int i = 0; i<num_results; i++)
+  {
+    struct TALER_BlindedCoinHashP h_blind_ev;
+    struct TALER_DenominationPublicKey denom_pub;
+    struct TALER_ReservePublicKeyP reserve_pub;
+    struct TALER_ReserveSignatureP reserve_sig;
+    struct GNUNET_TIME_Timestamp execution_date;
+    struct TALER_Amount amount_with_fee;
+    uint64_t rowid;
+    struct GNUNET_PQ_ResultSpec rs[] = {
+      GNUNET_PQ_result_spec_auto_from_type ("h_blind_ev",
+                                            &h_blind_ev),
+      TALER_PQ_result_spec_denom_pub ("denom_pub",
+                                      &denom_pub),
+      GNUNET_PQ_result_spec_auto_from_type ("reserve_pub",
+                                            &reserve_pub),
+      GNUNET_PQ_result_spec_auto_from_type ("reserve_sig",
+                                            &reserve_sig),
+      GNUNET_PQ_result_spec_timestamp ("execution_date",
+                                       &execution_date),
+      TALER_PQ_RESULT_SPEC_AMOUNT ("amount_with_fee",
+                                   &amount_with_fee),
+      GNUNET_PQ_result_spec_uint64 ("reserve_out_serial_id",
+                                    &rowid),
+      GNUNET_PQ_result_spec_end
+    };
+    enum GNUNET_GenericReturnValue ret;
+
+    if (GNUNET_OK !=
+        GNUNET_PQ_extract_result (result,
+                                  rs,
+                                  i))
+    {
+      GNUNET_break (0);
+      rosc->status = GNUNET_SYSERR;
+      return;
+    }
+    ret = rosc->cb (rosc->cb_cls,
+                    rowid,
+                    &h_blind_ev,
+                    &denom_pub,
+                    &reserve_pub,
+                    &reserve_sig,
+                    execution_date,
+                    &amount_with_fee);
+    GNUNET_PQ_cleanup_result (rs);
+    if (GNUNET_OK != ret)
+      break;
+  }
 }
 
 
 /**
- * Select information about an auditor auditing a denomination key.
+ * Select withdraw operations from reserves_out above @a serial_id
+ * in monotonically increasing order.
  *
  * @param cls closure
- * @param h_denom_pub the audited denomination
- * @param auditor_pub the auditor's key
- * @param[out] auditor_sig set to signature affirming the auditor's audit 
activity
+ * @param serial_id highest serial ID to exclude (select strictly larger)
+ * @param cb function to call on each result
+ * @param cb_cls closure for @a cb
  * @return transaction status code
  */
 static enum GNUNET_DB_QueryStatus
-postgres_select_auditor_denom_sig (
+postgres_select_withdrawals_above_serial_id (
   void *cls,
-  const struct TALER_DenominationHashP *h_denom_pub,
-  const struct TALER_AuditorPublicKeyP *auditor_pub,
-  struct TALER_AuditorSignatureP *auditor_sig)
+  uint64_t serial_id,
+  TALER_EXCHANGEDB_WithdrawCallback cb,
+  void *cb_cls)
 {
   struct PostgresClosure *pg = cls;
   struct GNUNET_PQ_QueryParam params[] = {
-    GNUNET_PQ_query_param_auto_from_type (auditor_pub),
-    GNUNET_PQ_query_param_auto_from_type (h_denom_pub),
+    GNUNET_PQ_query_param_uint64 (&serial_id),
     GNUNET_PQ_query_param_end
   };
-  struct GNUNET_PQ_ResultSpec rs[] = {
-    GNUNET_PQ_result_spec_auto_from_type ("auditor_sig",
-                                          auditor_sig),
-    GNUNET_PQ_result_spec_end
+  struct ReservesOutSerialContext rosc = {
+    .cb = cb,
+    .cb_cls = cb_cls,
+    .pg = pg,
+    .status = GNUNET_OK
   };
+  enum GNUNET_DB_QueryStatus qs;
 
-  return GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
-                                                   "select_auditor_denom_sig",
-                                                   params,
-                                                   rs);
+  qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn,
+                                             "audit_get_reserves_out_incr",
+                                             params,
+                                             &reserves_out_serial_helper_cb,
+                                             &rosc);
+  if (GNUNET_OK != rosc.status)
+    return GNUNET_DB_STATUS_HARD_ERROR;
+  return qs;
 }
 
 
 /**
- * Function called to grab a work shard on an operation @a op. Runs in its
- * own transaction.
- *
- * @param cls the @e cls of this struct with the plugin-specific state
- * @param job_name name of the operation to grab a word shard for
- * @param delay minimum age of a shard to grab
- * @param shard_size desired shard size
- * @param[out] start_row inclusive start row of the shard (returned)
- * @param[out] end_row exclusive end row of the shard (returned)
- * @return transaction status code
+ * Closure for #wire_out_serial_helper_cb().
  */
-static enum GNUNET_DB_QueryStatus
-postgres_begin_shard (void *cls,
-                      const char *job_name,
-                      struct GNUNET_TIME_Relative delay,
-                      uint64_t shard_size,
-                      uint64_t *start_row,
-                      uint64_t *end_row)
+struct WireOutSerialContext
 {
-  struct PostgresClosure *pg = cls;
-
-  for (unsigned int retries = 0; retries<10; retries++)
-  {
-    if (GNUNET_OK !=
-        TEH_PG_start (pg,
-                      "begin_shard"))
-    {
-      GNUNET_break (0);
-      return GNUNET_DB_STATUS_HARD_ERROR;
-    }
 
-    {
-      struct GNUNET_TIME_Absolute past;
-      enum GNUNET_DB_QueryStatus qs;
-      struct GNUNET_PQ_QueryParam params[] = {
-        GNUNET_PQ_query_param_string (job_name),
-        GNUNET_PQ_query_param_absolute_time (&past),
-        GNUNET_PQ_query_param_end
-      };
-      struct GNUNET_PQ_ResultSpec rs[] = {
-        GNUNET_PQ_result_spec_uint64 ("start_row",
-                                      start_row),
-        GNUNET_PQ_result_spec_uint64 ("end_row",
-                                      end_row),
-        GNUNET_PQ_result_spec_end
-      };
+  /**
+   * Callback to call.
+   */
+  TALER_EXCHANGEDB_WireTransferOutCallback cb;
 
-      past = GNUNET_TIME_absolute_get ();
-      qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
-                                                     "get_open_shard",
-                                                     params,
-                                                     rs);
-      switch (qs)
-      {
-      case GNUNET_DB_STATUS_HARD_ERROR:
-        GNUNET_break (0);
-        TEH_PG_rollback (pg);
-        return qs;
-      case GNUNET_DB_STATUS_SOFT_ERROR:
-        TEH_PG_rollback (pg);
-        continue;
-      case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT:
-        {
-          enum GNUNET_DB_QueryStatus qs;
-          struct GNUNET_TIME_Absolute now;
-          struct GNUNET_PQ_QueryParam params[] = {
-            GNUNET_PQ_query_param_string (job_name),
-            GNUNET_PQ_query_param_absolute_time (&now),
-            GNUNET_PQ_query_param_uint64 (start_row),
-            GNUNET_PQ_query_param_uint64 (end_row),
-            GNUNET_PQ_query_param_end
-          };
-
-          now = GNUNET_TIME_relative_to_absolute (delay);
-          qs = GNUNET_PQ_eval_prepared_non_select (pg->conn,
-                                                   "reclaim_shard",
-                                                   params);
-          switch (qs)
-          {
-          case GNUNET_DB_STATUS_HARD_ERROR:
-            GNUNET_break (0);
-            TEH_PG_rollback (pg);
-            return qs;
-          case GNUNET_DB_STATUS_SOFT_ERROR:
-            TEH_PG_rollback (pg);
-            continue;
-          case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT:
-            goto commit;
-          case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS:
-            GNUNET_break (0); /* logic error, should be impossible */
-            TEH_PG_rollback (pg);
-            return GNUNET_DB_STATUS_HARD_ERROR;
-          }
-        }
-        break; /* actually unreachable */
-      case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS:
-        break; /* continued below */
-      }
-    } /* get_open_shard */
+  /**
+   * Closure for @e cb.
+   */
+  void *cb_cls;
 
-    /* No open shard, find last 'end_row' */
-    {
-      enum GNUNET_DB_QueryStatus qs;
-      struct GNUNET_PQ_QueryParam params[] = {
-        GNUNET_PQ_query_param_string (job_name),
-        GNUNET_PQ_query_param_end
-      };
-      struct GNUNET_PQ_ResultSpec rs[] = {
-        GNUNET_PQ_result_spec_uint64 ("end_row",
-                                      start_row),
-        GNUNET_PQ_result_spec_end
-      };
+  /**
+   * Plugin context.
+   */
+  struct PostgresClosure *pg;
 
-      qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
-                                                     "get_last_shard",
-                                                     params,
-                                                     rs);
-      switch (qs)
-      {
-      case GNUNET_DB_STATUS_HARD_ERROR:
-        GNUNET_break (0);
-        TEH_PG_rollback (pg);
-        return qs;
-      case GNUNET_DB_STATUS_SOFT_ERROR:
-        TEH_PG_rollback (pg);
-        continue;
-      case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT:
-        break;
-      case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS:
-        *start_row = 0; /* base-case: no shards yet */
-        break; /* continued below */
-      }
-      *end_row = *start_row + shard_size;
-    } /* get_last_shard */
+  /**
+   * Status code, set to #GNUNET_SYSERR on hard errors.
+   */
+  int status;
+};
 
-    /* Claim fresh shard */
-    {
-      enum GNUNET_DB_QueryStatus qs;
-      struct GNUNET_TIME_Absolute now;
-      struct GNUNET_PQ_QueryParam params[] = {
-        GNUNET_PQ_query_param_string (job_name),
-        GNUNET_PQ_query_param_absolute_time (&now),
-        GNUNET_PQ_query_param_uint64 (start_row),
-        GNUNET_PQ_query_param_uint64 (end_row),
-        GNUNET_PQ_query_param_end
-      };
 
-      now = GNUNET_TIME_relative_to_absolute (delay);
-      GNUNET_log (GNUNET_ERROR_TYPE_INFO,
-                  "Trying to claim shard (%llu-%llu]\n",
-                  (unsigned long long) *start_row,
-                  (unsigned long long) *end_row);
-      qs = GNUNET_PQ_eval_prepared_non_select (pg->conn,
-                                               "claim_next_shard",
-                                               params);
-      switch (qs)
-      {
-      case GNUNET_DB_STATUS_HARD_ERROR:
-        GNUNET_break (0);
-        TEH_PG_rollback (pg);
-        return qs;
-      case GNUNET_DB_STATUS_SOFT_ERROR:
-        TEH_PG_rollback (pg);
-        continue;
-      case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT:
-        /* continued below */
-        break;
-      case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS:
-        /* someone else got this shard already,
-           try again */
-        TEH_PG_rollback (pg);
-        continue;
-      }
-    } /* claim_next_shard */
+/**
+ * Helper function to be called with the results of a SELECT statement
+ * that has returned @a num_results results.
+ *
+ * @param cls closure of type `struct WireOutSerialContext`
+ * @param result the postgres result
+ * @param num_results the number of results in @a result
+ */
+static void
+wire_out_serial_helper_cb (void *cls,
+                           PGresult *result,
+                           unsigned int num_results)
+{
+  struct WireOutSerialContext *wosc = cls;
+  struct PostgresClosure *pg = wosc->pg;
 
-    /* commit */
-commit:
-    {
-      enum GNUNET_DB_QueryStatus qs;
+  for (unsigned int i = 0; i<num_results; i++)
+  {
+    uint64_t rowid;
+    struct GNUNET_TIME_Timestamp date;
+    struct TALER_WireTransferIdentifierRawP wtid;
+    char *payto_uri;
+    struct TALER_Amount amount;
+    struct GNUNET_PQ_ResultSpec rs[] = {
+      GNUNET_PQ_result_spec_uint64 ("wireout_uuid",
+                                    &rowid),
+      GNUNET_PQ_result_spec_timestamp ("execution_date",
+                                       &date),
+      GNUNET_PQ_result_spec_auto_from_type ("wtid_raw",
+                                            &wtid),
+      GNUNET_PQ_result_spec_string ("payto_uri",
+                                    &payto_uri),
+      TALER_PQ_RESULT_SPEC_AMOUNT ("amount",
+                                   &amount),
+      GNUNET_PQ_result_spec_end
+    };
+    int ret;
 
-      qs = TEH_PG_commit (pg);
-      switch (qs)
-      {
-      case GNUNET_DB_STATUS_HARD_ERROR:
-        GNUNET_break (0);
-        TEH_PG_rollback (pg);
-        return qs;
-      case GNUNET_DB_STATUS_SOFT_ERROR:
-        TEH_PG_rollback (pg);
-        continue;
-      case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS:
-      case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT:
-        return GNUNET_DB_STATUS_SUCCESS_ONE_RESULT;
-      }
+    if (GNUNET_OK !=
+        GNUNET_PQ_extract_result (result,
+                                  rs,
+                                  i))
+    {
+      GNUNET_break (0);
+      wosc->status = GNUNET_SYSERR;
+      return;
     }
-  } /* retry 'for' loop */
-  return GNUNET_DB_STATUS_SOFT_ERROR;
+    ret = wosc->cb (wosc->cb_cls,
+                    rowid,
+                    date,
+                    &wtid,
+                    payto_uri,
+                    &amount);
+    GNUNET_PQ_cleanup_result (rs);
+    if (GNUNET_OK != ret)
+      break;
+  }
 }
 
 
 /**
- * Function called to abort work on a shard.
+ * Function called to select all wire transfers the exchange
+ * executed.
  *
- * @param cls the @e cls of this struct with the plugin-specific state
- * @param job_name name of the operation to abort a word shard for
- * @param start_row inclusive start row of the shard
- * @param end_row exclusive end row of the shard
+ * @param cls closure
+ * @param serial_id highest serial ID to exclude (select strictly larger)
+ * @param cb function to call for ONE unfinished item
+ * @param cb_cls closure for @a cb
  * @return transaction status code
  */
 static enum GNUNET_DB_QueryStatus
-postgres_abort_shard (void *cls,
-                      const char *job_name,
-                      uint64_t start_row,
-                      uint64_t end_row)
+postgres_select_wire_out_above_serial_id (
+  void *cls,
+  uint64_t serial_id,
+  TALER_EXCHANGEDB_WireTransferOutCallback cb,
+  void *cb_cls)
 {
   struct PostgresClosure *pg = cls;
   struct GNUNET_PQ_QueryParam params[] = {
-    GNUNET_PQ_query_param_string (job_name),
-    GNUNET_PQ_query_param_uint64 (&start_row),
-    GNUNET_PQ_query_param_uint64 (&end_row),
+    GNUNET_PQ_query_param_uint64 (&serial_id),
     GNUNET_PQ_query_param_end
   };
+  struct WireOutSerialContext wosc = {
+    .cb = cb,
+    .cb_cls = cb_cls,
+    .pg = pg,
+    .status = GNUNET_OK
+  };
+  enum GNUNET_DB_QueryStatus qs;
 
-  return GNUNET_PQ_eval_prepared_non_select (pg->conn,
-                                             "abort_shard",
-                                             params);
+  qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn,
+                                             "audit_get_wire_incr",
+                                             params,
+                                             &wire_out_serial_helper_cb,
+                                             &wosc);
+  if (GNUNET_OK != wosc.status)
+    return GNUNET_DB_STATUS_HARD_ERROR;
+  return qs;
 }
 
 
 /**
- * Function called to persist that work on a shard was completed.
+ * Function called to select all wire transfers the exchange
+ * executed by account.
  *
- * @param cls the @e cls of this struct with the plugin-specific state
- * @param job_name name of the operation to grab a word shard for
- * @param start_row inclusive start row of the shard
- * @param end_row exclusive end row of the shard
+ * @param cls closure
+ * @param account_name account to select
+ * @param serial_id highest serial ID to exclude (select strictly larger)
+ * @param cb function to call for ONE unfinished item
+ * @param cb_cls closure for @a cb
  * @return transaction status code
  */
-enum GNUNET_DB_QueryStatus
-postgres_complete_shard (void *cls,
-                         const char *job_name,
-                         uint64_t start_row,
-                         uint64_t end_row)
+static enum GNUNET_DB_QueryStatus
+postgres_select_wire_out_above_serial_id_by_account (
+  void *cls,
+  const char *account_name,
+  uint64_t serial_id,
+  TALER_EXCHANGEDB_WireTransferOutCallback cb,
+  void *cb_cls)
 {
   struct PostgresClosure *pg = cls;
-
   struct GNUNET_PQ_QueryParam params[] = {
-    GNUNET_PQ_query_param_string (job_name),
-    GNUNET_PQ_query_param_uint64 (&start_row),
-    GNUNET_PQ_query_param_uint64 (&end_row),
+    GNUNET_PQ_query_param_uint64 (&serial_id),
+    GNUNET_PQ_query_param_string (account_name),
     GNUNET_PQ_query_param_end
   };
+  struct WireOutSerialContext wosc = {
+    .cb = cb,
+    .cb_cls = cb_cls,
+    .pg = pg,
+    .status = GNUNET_OK
+  };
+  enum GNUNET_DB_QueryStatus qs;
 
-  GNUNET_log (GNUNET_ERROR_TYPE_INFO,
-              "Completing shard %llu-%llu\n",
-              (unsigned long long) start_row,
-              (unsigned long long) end_row);
-  return GNUNET_PQ_eval_prepared_non_select (pg->conn,
-                                             "complete_shard",
-                                             params);
+  qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn,
+                                             "audit_get_wire_incr_by_account",
+                                             params,
+                                             &wire_out_serial_helper_cb,
+                                             &wosc);
+  if (GNUNET_OK != wosc.status)
+    return GNUNET_DB_STATUS_HARD_ERROR;
+  return qs;
 }
 
 
 /**
- * Function called to release a revolving shard
- * back into the work pool.  Clears the
- * "completed" flag.
- *
- * @param cls the @e cls of this struct with the plugin-specific state
- * @param job_name name of the operation to grab a word shard for
- * @param start_row inclusive start row of the shard
- * @param end_row exclusive end row of the shard
- * @return transaction status code
+ * Closure for #recoup_serial_helper_cb().
  */
-enum GNUNET_DB_QueryStatus
-postgres_release_revolving_shard (void *cls,
-                                  const char *job_name,
-                                  uint32_t start_row,
-                                  uint32_t end_row)
+struct RecoupSerialContext
 {
-  struct PostgresClosure *pg = cls;
-  struct GNUNET_PQ_QueryParam params[] = {
-    GNUNET_PQ_query_param_string (job_name),
-    GNUNET_PQ_query_param_uint32 (&start_row),
-    GNUNET_PQ_query_param_uint32 (&end_row),
-    GNUNET_PQ_query_param_end
-  };
 
-  GNUNET_log (GNUNET_ERROR_TYPE_INFO,
-              "Releasing revolving shard %s %u-%u\n",
-              job_name,
-              (unsigned int) start_row,
-              (unsigned int) end_row);
-  return GNUNET_PQ_eval_prepared_non_select (pg->conn,
-                                             "release_revolving_shard",
-                                             params);
-}
+  /**
+   * Callback to call.
+   */
+  TALER_EXCHANGEDB_RecoupCallback cb;
+
+  /**
+   * Closure for @e cb.
+   */
+  void *cb_cls;
+
+  /**
+   * Plugin context.
+   */
+  struct PostgresClosure *pg;
+
+  /**
+   * Status code, set to #GNUNET_SYSERR on hard errors.
+   */
+  enum GNUNET_GenericReturnValue status;
+};
 
 
 /**
- * Function called to delete all revolving shards.
- * To be used after a crash or when the shard size is
- * changed.
+ * Helper function to be called with the results of a SELECT statement
+ * that has returned @a num_results results.
  *
- * @param cls the @e cls of this struct with the plugin-specific state
- * @return transaction status code
+ * @param cls closure of type `struct RecoupSerialContext`
+ * @param result the postgres result
+ * @param num_results the number of results in @a result
  */
-enum GNUNET_GenericReturnValue
-postgres_delete_shard_locks (void *cls)
+static void
+recoup_serial_helper_cb (void *cls,
+                         PGresult *result,
+                         unsigned int num_results)
 {
-  struct PostgresClosure *pg = cls;
-  struct GNUNET_PQ_ExecuteStatement es[] = {
-    GNUNET_PQ_make_execute ("DELETE FROM work_shards;"),
-    GNUNET_PQ_make_execute ("DELETE FROM revolving_work_shards;"),
-    GNUNET_PQ_EXECUTE_STATEMENT_END
-  };
+  struct RecoupSerialContext *psc = cls;
+  struct PostgresClosure *pg = psc->pg;
+
+  for (unsigned int i = 0; i<num_results; i++)
+  {
+    uint64_t rowid;
+    struct TALER_ReservePublicKeyP reserve_pub;
+    struct TALER_CoinPublicInfo coin;
+    struct TALER_CoinSpendSignatureP coin_sig;
+    union TALER_DenominationBlindingKeyP coin_blind;
+    struct TALER_Amount amount;
+    struct TALER_DenominationPublicKey denom_pub;
+    struct TALER_BlindedCoinHashP h_blind_ev;
+    struct GNUNET_TIME_Timestamp timestamp;
+    struct GNUNET_PQ_ResultSpec rs[] = {
+      GNUNET_PQ_result_spec_uint64 ("recoup_uuid",
+                                    &rowid),
+      GNUNET_PQ_result_spec_timestamp ("recoup_timestamp",
+                                       &timestamp),
+      GNUNET_PQ_result_spec_auto_from_type ("reserve_pub",
+                                            &reserve_pub),
+      GNUNET_PQ_result_spec_auto_from_type ("coin_pub",
+                                            &coin.coin_pub),
+      TALER_PQ_result_spec_denom_pub ("denom_pub",
+                                      &denom_pub),
+      GNUNET_PQ_result_spec_auto_from_type ("coin_sig",
+                                            &coin_sig),
+      GNUNET_PQ_result_spec_auto_from_type ("coin_blind",
+                                            &coin_blind),
+      GNUNET_PQ_result_spec_auto_from_type ("h_blind_ev",
+                                            &h_blind_ev),
+      GNUNET_PQ_result_spec_auto_from_type ("denom_pub_hash",
+                                            &coin.denom_pub_hash),
+      GNUNET_PQ_result_spec_allow_null (
+        GNUNET_PQ_result_spec_auto_from_type ("age_commitment_hash",
+                                              &coin.h_age_commitment),
+        &coin.no_age_commitment),
+      TALER_PQ_result_spec_denom_sig ("denom_sig",
+                                      &coin.denom_sig),
+      TALER_PQ_RESULT_SPEC_AMOUNT ("amount",
+                                   &amount),
+      GNUNET_PQ_result_spec_end
+    };
+    int ret;
 
-  return GNUNET_PQ_exec_statements (pg->conn,
-                                    es);
+    if (GNUNET_OK !=
+        GNUNET_PQ_extract_result (result,
+                                  rs,
+                                  i))
+    {
+      GNUNET_break (0);
+      psc->status = GNUNET_SYSERR;
+      return;
+    }
+    ret = psc->cb (psc->cb_cls,
+                   rowid,
+                   timestamp,
+                   &amount,
+                   &reserve_pub,
+                   &coin,
+                   &denom_pub,
+                   &coin_sig,
+                   &coin_blind);
+    GNUNET_PQ_cleanup_result (rs);
+    if (GNUNET_OK != ret)
+      break;
+  }
 }
 
 
 /**
- * Function called to save the manifest of an extension
- * (age-restriction, policy_extension_...) After successful storage of the
- * configuration it triggers the corresponding event.
+ * Function called to select recoup requests the exchange
+ * received, ordered by serial ID (monotonically increasing).
  *
- * @param cls the @e cls of this struct with the plugin-specific state
- * @param extension_name the name of the extension
- * @param manifest JSON object of the configuration as string
+ * @param cls closure
+ * @param serial_id lowest serial ID to include (select larger or equal)
+ * @param cb function to call for ONE unfinished item
+ * @param cb_cls closure for @a cb
  * @return transaction status code
  */
-enum GNUNET_DB_QueryStatus
-postgres_set_extension_manifest (void *cls,
-                                 const char *extension_name,
-                                 const char *manifest)
+static enum GNUNET_DB_QueryStatus
+postgres_select_recoup_above_serial_id (
+  void *cls,
+  uint64_t serial_id,
+  TALER_EXCHANGEDB_RecoupCallback cb,
+  void *cb_cls)
 {
   struct PostgresClosure *pg = cls;
-  struct GNUNET_PQ_QueryParam pcfg =
-    (NULL == manifest || 0 == *manifest)
-    ? GNUNET_PQ_query_param_null ()
-    : GNUNET_PQ_query_param_string (manifest);
   struct GNUNET_PQ_QueryParam params[] = {
-    GNUNET_PQ_query_param_string (extension_name),
-    pcfg,
+    GNUNET_PQ_query_param_uint64 (&serial_id),
     GNUNET_PQ_query_param_end
   };
+  struct RecoupSerialContext psc = {
+    .cb = cb,
+    .cb_cls = cb_cls,
+    .pg = pg,
+    .status = GNUNET_OK
+  };
+  enum GNUNET_DB_QueryStatus qs;
+
+  qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn,
+                                             "recoup_get_incr",
+                                             params,
+                                             &recoup_serial_helper_cb,
+                                             &psc);
+  if (GNUNET_OK != psc.status)
+    return GNUNET_DB_STATUS_HARD_ERROR;
+  return qs;
+}
+
+
+/**
+ * Closure for #recoup_refresh_serial_helper_cb().
+ */
+struct RecoupRefreshSerialContext
+{
+
+  /**
+   * Callback to call.
+   */
+  TALER_EXCHANGEDB_RecoupRefreshCallback cb;
+
+  /**
+   * Closure for @e cb.
+   */
+  void *cb_cls;
+
+  /**
+   * Plugin context.
+   */
+  struct PostgresClosure *pg;
 
-  return GNUNET_PQ_eval_prepared_non_select (pg->conn,
-                                             "set_extension_manifest",
-                                             params);
-}
+  /**
+   * Status code, set to #GNUNET_SYSERR on hard errors.
+   */
+  enum GNUNET_GenericReturnValue status;
+};
 
 
 /**
- * Function called to store configuration data about a partner
- * exchange that we are federated with.
+ * Helper function to be called with the results of a SELECT statement
+ * that has returned @a num_results results.
  *
- * @param cls the @e cls of this struct with the plugin-specific state
- * @param master_pub public offline signing key of the partner exchange
- * @param start_date when does the following data start to be valid
- * @param end_date when does the validity end (exclusive)
- * @param wad_frequency how often do we do exchange-to-exchange settlements?
- * @param wad_fee how much do we charge for transfers to the partner
- * @param partner_base_url base URL of the partner exchange
- * @param master_sig signature with our offline signing key affirming the above
- * @return transaction status code
+ * @param cls closure of type `struct RecoupRefreshSerialContext`
+ * @param result the postgres result
+ * @param num_results the number of results in @a result
  */
-static enum GNUNET_DB_QueryStatus
-postgres_insert_partner (void *cls,
-                         const struct TALER_MasterPublicKeyP *master_pub,
-                         struct GNUNET_TIME_Timestamp start_date,
-                         struct GNUNET_TIME_Timestamp end_date,
-                         struct GNUNET_TIME_Relative wad_frequency,
-                         const struct TALER_Amount *wad_fee,
-                         const char *partner_base_url,
-                         const struct TALER_MasterSignatureP *master_sig)
+static void
+recoup_refresh_serial_helper_cb (void *cls,
+                                 PGresult *result,
+                                 unsigned int num_results)
 {
-  struct PostgresClosure *pg = cls;
-  struct GNUNET_PQ_QueryParam params[] = {
-    GNUNET_PQ_query_param_auto_from_type (master_pub),
-    GNUNET_PQ_query_param_timestamp (&start_date),
-    GNUNET_PQ_query_param_timestamp (&end_date),
-    GNUNET_PQ_query_param_relative_time (&wad_frequency),
-    TALER_PQ_query_param_amount (wad_fee),
-    GNUNET_PQ_query_param_auto_from_type (master_sig),
-    GNUNET_PQ_query_param_string (partner_base_url),
-    GNUNET_PQ_query_param_end
-  };
+  struct RecoupRefreshSerialContext *psc = cls;
+  struct PostgresClosure *pg = psc->pg;
 
-  return GNUNET_PQ_eval_prepared_non_select (pg->conn,
-                                             "insert_partner",
-                                             params);
+  for (unsigned int i = 0; i<num_results; i++)
+  {
+    uint64_t rowid;
+    struct TALER_CoinSpendPublicKeyP old_coin_pub;
+    struct TALER_CoinPublicInfo coin;
+    struct TALER_CoinSpendSignatureP coin_sig;
+    union TALER_DenominationBlindingKeyP coin_blind;
+    struct TALER_DenominationPublicKey denom_pub;
+    struct TALER_DenominationHashP old_denom_pub_hash;
+    struct TALER_Amount amount;
+    struct TALER_BlindedCoinHashP h_blind_ev;
+    struct GNUNET_TIME_Timestamp timestamp;
+    struct GNUNET_PQ_ResultSpec rs[] = {
+      GNUNET_PQ_result_spec_uint64 ("recoup_refresh_uuid",
+                                    &rowid),
+      GNUNET_PQ_result_spec_timestamp ("recoup_timestamp",
+                                       &timestamp),
+      GNUNET_PQ_result_spec_auto_from_type ("old_coin_pub",
+                                            &old_coin_pub),
+      GNUNET_PQ_result_spec_auto_from_type ("old_denom_pub_hash",
+                                            &old_denom_pub_hash),
+      GNUNET_PQ_result_spec_auto_from_type ("coin_pub",
+                                            &coin.coin_pub),
+      GNUNET_PQ_result_spec_auto_from_type ("coin_sig",
+                                            &coin_sig),
+      GNUNET_PQ_result_spec_auto_from_type ("coin_blind",
+                                            &coin_blind),
+      TALER_PQ_result_spec_denom_pub ("denom_pub",
+                                      &denom_pub),
+      GNUNET_PQ_result_spec_auto_from_type ("h_blind_ev",
+                                            &h_blind_ev),
+      GNUNET_PQ_result_spec_auto_from_type ("denom_pub_hash",
+                                            &coin.denom_pub_hash),
+      GNUNET_PQ_result_spec_allow_null (
+        GNUNET_PQ_result_spec_auto_from_type ("age_commitment_hash",
+                                              &coin.h_age_commitment),
+        &coin.no_age_commitment),
+      TALER_PQ_result_spec_denom_sig ("denom_sig",
+                                      &coin.denom_sig),
+      TALER_PQ_RESULT_SPEC_AMOUNT ("amount",
+                                   &amount),
+      GNUNET_PQ_result_spec_end
+    };
+    enum GNUNET_GenericReturnValue ret;
+
+    if (GNUNET_OK !=
+        GNUNET_PQ_extract_result (result,
+                                  rs,
+                                  i))
+    {
+      GNUNET_break (0);
+      psc->status = GNUNET_SYSERR;
+      return;
+    }
+    ret = psc->cb (psc->cb_cls,
+                   rowid,
+                   timestamp,
+                   &amount,
+                   &old_coin_pub,
+                   &old_denom_pub_hash,
+                   &coin,
+                   &denom_pub,
+                   &coin_sig,
+                   &coin_blind);
+    GNUNET_PQ_cleanup_result (rs);
+    if (GNUNET_OK != ret)
+      break;
+  }
 }
 
 
 /**
- * Function called to clean up one expired purse.
+ * Function called to select recoup requests the exchange received for
+ * refreshed coins, ordered by serial ID (monotonically increasing).
  *
- * @param cls the @e cls of this struct with the plugin-specific state
- * @param start_time select purse expired after this time
- * @param end_time select purse expired before this time
- * @return transaction status code (#GNUNET_DB_STATUS_SUCCESS_NO_RESULTS if no 
purse expired in the given time interval).
+ * @param cls closure
+ * @param serial_id lowest serial ID to include (select larger or equal)
+ * @param cb function to call for ONE unfinished item
+ * @param cb_cls closure for @a cb
+ * @return transaction status code
  */
 static enum GNUNET_DB_QueryStatus
-postgres_expire_purse (
+postgres_select_recoup_refresh_above_serial_id (
   void *cls,
-  struct GNUNET_TIME_Absolute start_time,
-  struct GNUNET_TIME_Absolute end_time)
+  uint64_t serial_id,
+  TALER_EXCHANGEDB_RecoupRefreshCallback cb,
+  void *cb_cls)
 {
   struct PostgresClosure *pg = cls;
-  struct GNUNET_TIME_Absolute now = GNUNET_TIME_absolute_get ();
   struct GNUNET_PQ_QueryParam params[] = {
-    GNUNET_PQ_query_param_absolute_time (&start_time),
-    GNUNET_PQ_query_param_absolute_time (&end_time),
-    GNUNET_PQ_query_param_absolute_time (&now),
+    GNUNET_PQ_query_param_uint64 (&serial_id),
     GNUNET_PQ_query_param_end
   };
-  bool found = false;
-  struct GNUNET_PQ_ResultSpec rs[] = {
-    GNUNET_PQ_result_spec_bool ("found",
-                                &found),
-    GNUNET_PQ_result_spec_end
+  struct RecoupRefreshSerialContext psc = {
+    .cb = cb,
+    .cb_cls = cb_cls,
+    .pg = pg,
+    .status = GNUNET_OK
   };
   enum GNUNET_DB_QueryStatus qs;
 
-  qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
-                                                 "call_expire_purse",
-                                                 params,
-                                                 rs);
-  if (qs < 0)
-    return qs;
-  GNUNET_assert (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT == qs);
-  return found
-         ? GNUNET_DB_STATUS_SUCCESS_ONE_RESULT
-         : GNUNET_DB_STATUS_SUCCESS_NO_RESULTS;
+  qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn,
+                                             "recoup_refresh_get_incr",
+                                             params,
+                                             &recoup_refresh_serial_helper_cb,
+                                             &psc);
+  if (GNUNET_OK != psc.status)
+    return GNUNET_DB_STATUS_HARD_ERROR;
+  return qs;
 }
 
 
 /**
- * Function called to return meta data about a purse by the
- * merge capability key.
+ * Obtain information about which reserve a coin was generated
+ * from given the hash of the blinded coin.
  *
- * @param cls the @e cls of this struct with the plugin-specific state
- * @param merge_pub public key representing the merge capability
- * @param[out] purse_pub public key of the purse
- * @param[out] purse_expiration when would an unmerged purse expire
- * @param[out] h_contract_terms contract associated with the purse
- * @param[out] age_limit the age limit for deposits into the purse
- * @param[out] target_amount amount to be put into the purse
- * @param[out] balance amount put so far into the purse
- * @param[out] purse_sig signature of the purse over the initialization data
+ * @param cls closure
+ * @param bch hash that uniquely identifies the withdraw request
+ * @param[out] reserve_pub set to information about the reserve (on success 
only)
+ * @param[out] reserve_out_serial_id set to row of the @a h_blind_ev in 
reserves_out
  * @return transaction status code
  */
 static enum GNUNET_DB_QueryStatus
-postgres_select_purse_by_merge_pub (
+postgres_get_reserve_by_h_blind (
   void *cls,
-  const struct TALER_PurseMergePublicKeyP *merge_pub,
-  struct TALER_PurseContractPublicKeyP *purse_pub,
-  struct GNUNET_TIME_Timestamp *purse_expiration,
-  struct TALER_PrivateContractHashP *h_contract_terms,
-  uint32_t *age_limit,
-  struct TALER_Amount *target_amount,
-  struct TALER_Amount *balance,
-  struct TALER_PurseContractSignatureP *purse_sig)
+  const struct TALER_BlindedCoinHashP *bch,
+  struct TALER_ReservePublicKeyP *reserve_pub,
+  uint64_t *reserve_out_serial_id)
 {
   struct PostgresClosure *pg = cls;
   struct GNUNET_PQ_QueryParam params[] = {
-    GNUNET_PQ_query_param_auto_from_type (merge_pub),
+    GNUNET_PQ_query_param_auto_from_type (bch),
     GNUNET_PQ_query_param_end
   };
   struct GNUNET_PQ_ResultSpec rs[] = {
-    GNUNET_PQ_result_spec_auto_from_type ("purse_pub",
-                                          purse_pub),
-    GNUNET_PQ_result_spec_timestamp ("purse_expiration",
-                                     purse_expiration),
-    GNUNET_PQ_result_spec_auto_from_type ("h_contract_terms",
-                                          h_contract_terms),
-    GNUNET_PQ_result_spec_uint32 ("age_limit",
-                                  age_limit),
-    TALER_PQ_RESULT_SPEC_AMOUNT ("amount_with_fee",
-                                 target_amount),
-    TALER_PQ_RESULT_SPEC_AMOUNT ("balance",
-                                 balance),
-    GNUNET_PQ_result_spec_auto_from_type ("purse_sig",
-                                          purse_sig),
+    GNUNET_PQ_result_spec_auto_from_type ("reserve_pub",
+                                          reserve_pub),
+    GNUNET_PQ_result_spec_uint64 ("reserve_out_serial_id",
+                                  reserve_out_serial_id),
     GNUNET_PQ_result_spec_end
   };
+
   return GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
-                                                   "select_purse_by_merge_pub",
+                                                   "reserve_by_h_blind",
                                                    params,
                                                    rs);
 }
 
 
-/**
- * Set the current @a balance in the purse
- * identified by @a purse_pub. Used by the auditor
- * to update the balance as calculated by the auditor.
- *
- * @param cls closure
- * @param purse_pub public key of a purse
- * @param balance new balance to store under the purse
- * @return transaction status
- */
-static enum GNUNET_DB_QueryStatus
-postgres_set_purse_balance (
-  void *cls,
-  const struct TALER_PurseContractPublicKeyP *purse_pub,
-  const struct TALER_Amount *balance)
-{
-  struct PostgresClosure *pg = cls;
-  struct GNUNET_PQ_QueryParam params[] = {
-    GNUNET_PQ_query_param_auto_from_type (purse_pub),
-    TALER_PQ_query_param_amount (balance),
-    GNUNET_PQ_query_param_end
-  };
-
-  return GNUNET_PQ_eval_prepared_non_select (pg->conn,
-                                             "set_purse_balance",
-                                             params);
-}
-
-
 /**
  * Initialize Postgres database subsystem.
  *
@@ -9146,29 +5022,10 @@ libtaler_plugin_exchangedb_postgres_init (void *cls)
     GNUNET_free (pg);
     return NULL;
   }
-
   plugin = GNUNET_new (struct TALER_EXCHANGEDB_Plugin);
   plugin->cls = pg;
-  plugin->create_tables = &postgres_create_tables;
-  plugin->setup_foreign_servers = &postgres_setup_foreign_servers;
-  plugin->event_listen = &postgres_event_listen;
-  plugin->event_listen_cancel = &postgres_event_listen_cancel;
-  plugin->event_notify = &postgres_event_notify;
-  plugin->get_denomination_info = &postgres_get_denomination_info;
-  plugin->iterate_denomination_info = &postgres_iterate_denomination_info;
-  plugin->iterate_denominations = &postgres_iterate_denominations;
-  plugin->iterate_active_auditors = &postgres_iterate_active_auditors;
-  plugin->iterate_auditor_denominations =
-    &postgres_iterate_auditor_denominations;
-  plugin->reserves_get = &postgres_reserves_get;
-  plugin->reserves_get_origin = &postgres_reserves_get_origin;
-  plugin->drain_kyc_alert = &postgres_drain_kyc_alert;
-  plugin->reserves_in_insert = &postgres_reserves_in_insert;
-  plugin->get_withdraw_info = &postgres_get_withdraw_info;
-  plugin->do_batch_withdraw = &postgres_do_batch_withdraw;
   plugin->get_policy_details = &postgres_get_policy_details;
   plugin->persist_policy_details = &postgres_persist_policy_details;
-  plugin->do_deposit = &postgres_do_deposit;
   plugin->add_policy_fulfillment_proof = 
&postgres_add_policy_fulfillment_proof;
   plugin->do_melt = &postgres_do_melt;
   plugin->do_refund = &postgres_do_refund;
@@ -9213,6 +5070,7 @@ libtaler_plugin_exchangedb_postgres_init (void *cls)
   plugin->start_deferred_wire_out = &postgres_start_deferred_wire_out;
   plugin->store_wire_transfer_out = &postgres_store_wire_transfer_out;
   plugin->gc = &postgres_gc;
+
   plugin->select_deposits_above_serial_id
     = &postgres_select_deposits_above_serial_id;
   plugin->select_history_requests_above_serial_id
@@ -9241,67 +5099,8 @@ libtaler_plugin_exchangedb_postgres_init (void *cls)
     = &postgres_select_recoup_refresh_above_serial_id;
   plugin->get_reserve_by_h_blind
     = &postgres_get_reserve_by_h_blind;
-  plugin->get_old_coin_by_h_blind
-    = &postgres_get_old_coin_by_h_blind;
-  plugin->insert_denomination_revocation
-    = &postgres_insert_denomination_revocation;
-  plugin->get_denomination_revocation
-    = &postgres_get_denomination_revocation;
-  plugin->select_deposits_missing_wire
-    = &postgres_select_deposits_missing_wire;
-  plugin->lookup_auditor_timestamp
-    = &postgres_lookup_auditor_timestamp;
-  plugin->lookup_auditor_status
-    = &postgres_lookup_auditor_status;
-  plugin->insert_auditor
-    = &postgres_insert_auditor;
-
-  plugin->lookup_wire_timestamp
-    = &postgres_lookup_wire_timestamp;
-  plugin->insert_wire
-    = &postgres_insert_wire;
-  plugin->update_wire
-    = &postgres_update_wire;
-  plugin->get_wire_accounts
-    = &postgres_get_wire_accounts;
-  plugin->get_wire_fees
-    = &postgres_get_wire_fees;
-  plugin->insert_signkey_revocation
-    = &postgres_insert_signkey_revocation;
-  plugin->lookup_signkey_revocation
-    = &postgres_lookup_signkey_revocation;
-  plugin->lookup_denomination_key
-    = &postgres_lookup_denomination_key;
-  plugin->insert_auditor_denom_sig
-    = &postgres_insert_auditor_denom_sig;
-  plugin->select_auditor_denom_sig
-    = &postgres_select_auditor_denom_sig;
-  plugin->add_denomination_key
-    = &postgres_add_denomination_key;
-  plugin->lookup_signing_key
-    = &postgres_lookup_signing_key;
-  plugin->begin_shard
-    = &postgres_begin_shard;
-  plugin->abort_shard
-    = &postgres_abort_shard;
-  plugin->complete_shard
-    = &postgres_complete_shard;
-  plugin->release_revolving_shard
-    = &postgres_release_revolving_shard;
-  plugin->delete_shard_locks
-    = &postgres_delete_shard_locks;
-  plugin->set_extension_manifest
-    = &postgres_set_extension_manifest;
-  plugin->insert_partner
-    = &postgres_insert_partner;
-  plugin->expire_purse
-    = &postgres_expire_purse;
-  plugin->select_purse_by_merge_pub
-    = &postgres_select_purse_by_merge_pub;
-  plugin->set_purse_balance
-    = &postgres_set_purse_balance;
 
-  /* NEW style, sort alphabetically! */
+  /* New style, sort alphabetically! */
   plugin->do_reserve_open
     = &TEH_PG_do_reserve_open;
   plugin->drop_tables
@@ -9386,8 +5185,6 @@ libtaler_plugin_exchangedb_postgres_init (void *cls)
     = &TEH_PG_lookup_kyc_requirement_by_row;
   plugin->insert_kyc_requirement_for_account
     = &TEH_PG_insert_kyc_requirement_for_account;
-
-
   plugin->lookup_kyc_process_by_account
     = &TEH_PG_lookup_kyc_process_by_account;
   plugin->update_kyc_process_by_row
@@ -9449,6 +5246,206 @@ libtaler_plugin_exchangedb_postgres_init (void *cls)
   plugin->rollback
     = &TEH_PG_rollback;
 
+ plugin->create_tables
+    = &TEH_PG_create_tables;
+  plugin->setup_foreign_servers
+    = &TEH_PG_setup_foreign_servers;
+  plugin->event_listen
+    = &TEH_PG_event_listen;
+  plugin->event_listen_cancel
+    = &TEH_PG_event_listen_cancel;
+  plugin->event_notify
+    = &TEH_PG_event_notify;
+  plugin->get_denomination_info
+    = &TEH_PG_get_denomination_info;
+  plugin->iterate_denomination_info
+    = &TEH_PG_iterate_denomination_info;
+  plugin->iterate_denominations
+    = &TEH_PG_iterate_denominations;
+  plugin->iterate_active_auditors
+    = &TEH_PG_iterate_active_auditors;
+  plugin->iterate_auditor_denominations
+    = &TEH_PG_iterate_auditor_denominations;
+  plugin->reserves_get
+    = &TEH_PG_reserves_get;
+  plugin->reserves_get_origin
+    = &TEH_PG_reserves_get_origin;
+  plugin->drain_kyc_alert
+    = &TEH_PG_drain_kyc_alert;
+  plugin->reserves_in_insert
+    = &TEH_PG_reserves_in_insert;
+  plugin->get_withdraw_info
+    = &TEH_PG_get_withdraw_info;
+  plugin->do_batch_withdraw
+    = &TEH_PG_do_batch_withdraw;
+  plugin->get_policy_details
+    = &TEH_PG_get_policy_details;
+  plugin->persist_policy_details
+    = &TEH_PG_persist_policy_details;
+  plugin->do_deposit
+    = &TEH_PG_do_deposit;
+  plugin->add_policy_fulfillment_proof
+    = &TEH_PG_add_policy_fulfillment_proof;
+  plugin->do_melt
+    = &TEH_PG_do_melt;
+  plugin->do_refund
+    = &TEH_PG_do_refund;
+  plugin->do_recoup
+    = &TEH_PG_do_recoup;
+  plugin->do_recoup_refresh
+    = &TEH_PG_do_recoup_refresh;
+  plugin->get_reserve_balance
+    = &TEH_PG_get_reserve_balance;
+  plugin->count_known_coins
+    = &TEH_PG_count_known_coins;
+  plugin->ensure_coin_known
+    = &TEH_PG_ensure_coin_known;
+  plugin->get_known_coin
+    = &TEH_PG_get_known_coin;
+  plugin->get_coin_denomination
+    = &TEH_PG_get_coin_denomination;
+  plugin->have_deposit2
+    = &TEH_PG_have_deposit2;
+  plugin->aggregate
+    = &TEH_PG_aggregate;
+  plugin->create_aggregation_transient
+    = &TEH_PG_create_aggregation_transient;
+  plugin->select_aggregation_transient
+    = &TEH_PG_select_aggregation_transient;
+  plugin->find_aggregation_transient
+    = &TEH_PG_find_aggregation_transient;
+  plugin->update_aggregation_transient
+    = &TEH_PG_update_aggregation_transient;
+  plugin->get_ready_deposit
+    = &TEH_PG_get_ready_deposit;
+  plugin->insert_deposit
+    = &TEH_PG_insert_deposit;
+  plugin->insert_refund
+    = &TEH_PG_insert_refund;
+  plugin->select_refunds_by_coin
+    = &TEH_PG_select_refunds_by_coin;
+  plugin->get_melt
+    = &TEH_PG_get_melt;
+  plugin->insert_refresh_reveal
+    = &TEH_PG_insert_refresh_reveal;
+  plugin->get_refresh_reveal
+    = &TEH_PG_get_refresh_reveal;
+  plugin->lookup_wire_transfer
+    = &TEH_PG_lookup_wire_transfer;
+  plugin->lookup_transfer_by_deposit
+    = &TEH_PG_lookup_transfer_by_deposit;
+  plugin->insert_wire_fee
+    = &TEH_PG_insert_wire_fee;
+  plugin->insert_global_fee
+    = &TEH_PG_insert_global_fee;
+  plugin->get_wire_fee
+    = &TEH_PG_get_wire_fee;
+  plugin->get_global_fee
+    = &TEH_PG_get_global_fee;
+  plugin->get_global_fees
+    = &TEH_PG_get_global_fees;
+  plugin->insert_reserve_closed
+    = &TEH_PG_insert_reserve_closed;
+  plugin->wire_prepare_data_insert
+    = &TEH_PG_wire_prepare_data_insert;
+  plugin->wire_prepare_data_mark_finished
+    = &TEH_PG_wire_prepare_data_mark_finished;
+  plugin->wire_prepare_data_mark_failed
+    = &TEH_PG_wire_prepare_data_mark_failed;
+  plugin->wire_prepare_data_get
+    = &TEH_PG_wire_prepare_data_get;
+  plugin->start_deferred_wire_out
+    = &TEH_PG_start_deferred_wire_out;
+  plugin->store_wire_transfer_out
+    = &TEH_PG_store_wire_transfer_out;
+  plugin->gc
+    = &TEH_PG_gc;
+  plugin->select_deposits_above_serial_id
+    = &TEH_PG_select_deposits_above_serial_id;
+  plugin->select_history_requests_above_serial_id
+    = &TEH_PG_select_history_requests_above_serial_id;
+  plugin->select_purse_decisions_above_serial_id
+    = &TEH_PG_select_purse_decisions_above_serial_id;
+  plugin->select_purse_deposits_by_purse
+    = &TEH_PG_select_purse_deposits_by_purse;
+  plugin->select_refreshes_above_serial_id
+    = &TEH_PG_select_refreshes_above_serial_id;
+  plugin->select_refunds_above_serial_id
+    = &TEH_PG_select_refunds_above_serial_id;
+  plugin->select_reserves_in_above_serial_id
+    = &TEH_PG_select_reserves_in_above_serial_id;
+  plugin->select_reserves_in_above_serial_id_by_account
+    = &TEH_PG_select_reserves_in_above_serial_id_by_account;
+  plugin->select_withdrawals_above_serial_id
+    = &TEH_PG_select_withdrawals_above_serial_id;
+  plugin->select_wire_out_above_serial_id
+    = &TEH_PG_select_wire_out_above_serial_id;
+  plugin->select_wire_out_above_serial_id_by_account
+    = &TEH_PG_select_wire_out_above_serial_id_by_account;
+  plugin->select_recoup_above_serial_id
+    = &TEH_PG_select_recoup_above_serial_id;
+  plugin->select_recoup_refresh_above_serial_id
+    = &TEH_PG_select_recoup_refresh_above_serial_id;
+  plugin->get_reserve_by_h_blind
+    = &TEH_PG_get_reserve_by_h_blind;
+  plugin->get_old_coin_by_h_blind
+    = &TEH_PG_get_old_coin_by_h_blind;
+  plugin->insert_denomination_revocation
+    = &TEH_PG_insert_denomination_revocation;
+  plugin->get_denomination_revocation
+    = &TEH_PG_get_denomination_revocation;
+  plugin->select_deposits_missing_wire
+    = &TEH_PG_select_deposits_missing_wire;
+  plugin->lookup_auditor_timestamp
+    = &TEH_PG_lookup_auditor_timestamp;
+  plugin->lookup_auditor_status
+    = &TEH_PG_lookup_auditor_status;
+  plugin->insert_auditor
+    = &TEH_PG_insert_auditor;
+  plugin->lookup_wire_timestamp
+    = &TEH_PG_lookup_wire_timestamp;
+  plugin->insert_wire
+    = &TEH_PG_insert_wire;
+  plugin->update_wire
+    = &TEH_PG_update_wire;
+  plugin->get_wire_accounts
+    = &TEH_PG_get_wire_accounts;
+  plugin->get_wire_fees
+    = &TEH_PG_get_wire_fees;
+  plugin->insert_signkey_revocation
+    = &TEH_PG_insert_signkey_revocation;
+  plugin->lookup_signkey_revocation
+    = &TEH_PG_lookup_signkey_revocation;
+  plugin->lookup_denomination_key
+    = &TEH_PG_lookup_denomination_key;
+  plugin->insert_auditor_denom_sig
+    = &TEH_PG_insert_auditor_denom_sig;
+  plugin->select_auditor_denom_sig
+    = &TEH_PG_select_auditor_denom_sig;
+  plugin->add_denomination_key
+    = &TEH_PG_add_denomination_key;
+  plugin->lookup_signing_key
+    = &TEH_PG_lookup_signing_key;
+  plugin->begin_shard
+    = &TEH_PG_begin_shard;
+  plugin->abort_shard
+    = &TEH_PG_abort_shard;
+  plugin->complete_shard
+    = &TEH_PG_complete_shard;
+  plugin->release_revolving_shard
+    = &TEH_PG_release_revolving_shard;
+  plugin->delete_shard_locks
+    = &TEH_PG_delete_shard_locks;
+  plugin->set_extension_manifest
+    = &TEH_PG_set_extension_manifest;
+  plugin->insert_partner
+    = &TEH_PG_insert_partner;
+  plugin->expire_purse
+    = &TEH_PG_expire_purse;
+  plugin->select_purse_by_merge_pub
+    = &TEH_PG_select_purse_by_merge_pub;
+  plugin->set_purse_balance
+    = &TEH_PG_set_purse_balance;
 
   return plugin;
 }

-- 
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]