gnunet-svn
[Top][All Lists]
Advanced

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

[taler-exchange] branch master updated: major refactoring, eliminating w


From: gnunet
Subject: [taler-exchange] branch master updated: major refactoring, eliminating wire-plugins and moving towards new bank API. main code compiles, testcases known to fail, code sure not to fully work yet
Date: Sat, 11 Jan 2020 15:20:20 +0100

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

grothoff pushed a commit to branch master
in repository exchange.

The following commit(s) were added to refs/heads/master by this push:
     new 9443c10d major refactoring, eliminating wire-plugins and moving 
towards new bank API. main code compiles, testcases known to fail, code sure 
not to fully work yet
9443c10d is described below

commit 9443c10d7feb0d91323869dd08ec61ca781564f4
Author: Christian Grothoff <address@hidden>
AuthorDate: Sat Jan 11 15:19:56 2020 +0100

    major refactoring, eliminating wire-plugins and moving towards new bank 
API. main code compiles, testcases known to fail, code sure not to fully work 
yet
---
 configure.ac                                       |    1 -
 src/Makefile.am                                    |    2 +-
 src/auditor/Makefile.am                            |    2 +
 src/auditor/taler-auditor.c                        |  110 +-
 src/auditor/taler-wire-auditor.c                   |  411 +++---
 src/auditordb/plugin_auditordb_postgres.c          |   72 +-
 src/bank-lib/Makefile.am                           |   13 +-
 src/bank-lib/bank_api_admin.c                      |   71 +-
 src/bank-lib/bank_api_common.c                     |   86 +-
 src/bank-lib/bank_api_common.h                     |   12 +
 .../{bank_api_history.c => bank_api_credit.c}      |  254 +---
 .../{bank_api_history.c => bank_api_debit.c}       |  256 +---
 src/bank-lib/bank_api_parse.c                      |   54 +-
 src/bank-lib/bank_api_reject.c                     |  242 ----
 src/bank-lib/bank_api_transaction.c                |  368 ++++++
 src/bank-lib/fakebank.c                            |  728 +++++++----
 src/bank-lib/fakebank.h                            |  283 +----
 src/bank-lib/fakebank_history.c                    |  204 +--
 src/bank-lib/taler-bank-transfer.c                 |   55 +-
 src/bank-lib/test_bank_api.c                       |    2 +-
 ..._history.c => testing_api_cmd_history_credit.c} |  484 ++------
 ...d_history.c => testing_api_cmd_history_debit.c} |  494 ++------
 src/bank-lib/testing_api_cmd_reject.c              |  223 ----
 src/benchmark/taler-exchange-benchmark.c           |   69 +-
 src/exchange-tools/Makefile.am                     |    4 +
 src/exchange-tools/taler-exchange-keyup.c          |   23 +-
 src/exchange-tools/taler-wire.c                    |  268 ++--
 src/exchange/Makefile.am                           |    5 +
 src/exchange/taler-exchange-aggregator.c           |  448 +++----
 src/exchange/taler-exchange-httpd_deposit.c        |   13 -
 src/exchange/taler-exchange-httpd_validation.c     |  142 +--
 src/exchange/taler-exchange-wirewatch.c            |  271 ++--
 src/exchangedb/exchangedb_accounts.c               |   12 +-
 src/exchangedb/exchangedb_fees.c                   |    8 +-
 src/exchangedb/plugin_exchangedb_postgres.c        |   31 +-
 src/exchangedb/test_exchangedb.c                   |   32 +-
 src/include/Makefile.am                            |    2 -
 src/include/taler_auditordb_plugin.h               |   18 +-
 src/include/taler_bank_service.h                   |  313 +++--
 src/include/taler_exchangedb_lib.h                 |    9 +-
 src/include/taler_exchangedb_plugin.h              |   18 +-
 src/include/taler_fakebank_lib.h                   |   25 +-
 src/include/taler_mhd_lib.h                        |    2 +-
 src/include/taler_testing_bank_lib.h               |   44 +-
 src/include/taler_testing_lib.h                    |  159 ++-
 src/include/taler_wire_lib.h                       |   59 +-
 src/include/taler_wire_plugin.h                    |  259 ++--
 src/lib/Makefile.am                                |    1 +
 src/lib/exchange_api_handle.c                      |    2 +-
 src/lib/testing_api_cmd_bank_check.c               |   69 +-
 src/lib/testing_api_cmd_fakebank_transfer.c        |  402 +++---
 src/lib/testing_api_cmd_status.c                   |   36 +-
 src/lib/testing_api_cmd_track.c                    |   21 +-
 src/lib/testing_api_trait_reserve_pub.c            |   77 ++
 src/lib/testing_api_trait_string.c                 |   29 +-
 src/wire-plugins/Makefile.am                       |   81 --
 src/wire-plugins/plugin_wire_taler-bank.c          | 1306 --------------------
 src/wire-plugins/plugin_wire_template.c            |  384 ------
 src/wire-plugins/test_wire_plugin.c                |  189 ---
 src/wire-plugins/test_wire_plugin.conf             |   25 -
 .../test_wire_plugin_transactions_taler-bank.c     |  365 ------
 .../test_wire_plugin_transactions_taler-bank.conf  |   12 -
 src/wire/Makefile.am                               |    1 -
 src/wire/payto.c                                   |  104 +-
 src/wire/wire.c                                    |  149 ---
 src/wire/wire_helper.c                             |   56 +-
 66 files changed, 2884 insertions(+), 7086 deletions(-)

diff --git a/configure.ac b/configure.ac
index 95e590bf..35813210 100644
--- a/configure.ac
+++ b/configure.ac
@@ -558,6 +558,5 @@ AC_CONFIG_FILES([Makefile
                  src/util/Makefile
                  src/util/taler-config
                  src/wire/Makefile
-                 src/wire-plugins/Makefile
                  ])
 AC_OUTPUT
diff --git a/src/Makefile.am b/src/Makefile.am
index 761b9c33..cc749e27 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -22,7 +22,7 @@ pkgcfg_DATA = \
 EXTRA_DIST = \
   taler.conf
 
-SUBDIRS = include util wire json curl $(PQ_DIR) mhd $(BANK_LIB) wire-plugins 
exchangedb exchange exchange-tools auditordb auditor
+SUBDIRS = include util wire json curl $(PQ_DIR) mhd $(BANK_LIB) exchangedb 
exchange exchange-tools auditordb auditor
 if HAVE_LIBCURL
  SUBDIRS += lib benchmark
 else
diff --git a/src/auditor/Makefile.am b/src/auditor/Makefile.am
index b942076f..d5d7669b 100644
--- a/src/auditor/Makefile.am
+++ b/src/auditor/Makefile.am
@@ -73,10 +73,12 @@ taler_wire_auditor_LDADD = \
   $(top_builddir)/src/util/libtalerutil.la \
   $(top_builddir)/src/json/libtalerjson.la \
   $(top_builddir)/src/wire/libtalerwire.la \
+  $(top_builddir)/src/bank-lib/libtalerbank.la \
   $(top_builddir)/src/exchangedb/libtalerexchangedb.la \
   $(top_builddir)/src/auditordb/libtalerauditordb.la \
   -ljansson \
   -lgnunetjson \
+  -lgnunetcurl \
   -lgnunetutil
 
 taler_auditor_sign_SOURCES = \
diff --git a/src/auditor/taler-auditor.c b/src/auditor/taler-auditor.c
index 0cc2868f..bb769fd6 100644
--- a/src/auditor/taler-auditor.c
+++ b/src/auditor/taler-auditor.c
@@ -1010,8 +1010,7 @@ struct ReserveContext
  * @param reserve_pub public key of the reserve (also the WTID)
  * @param credit amount that was received
  * @param sender_account_details information about the sender's bank account
- * @param wire_reference unique reference identifying the wire transfer 
(binary blob)
- * @param wire_reference_size number of bytes in @a wire_reference
+ * @param wire_reference unique reference identifying the wire transfer
  * @param execution_date when did we receive the funds
  * @return #GNUNET_OK to continue to iterate, #GNUNET_SYSERR to stop
  */
@@ -1021,8 +1020,7 @@ handle_reserve_in (void *cls,
                    const struct TALER_ReservePublicKeyP *reserve_pub,
                    const struct TALER_Amount *credit,
                    const char *sender_account_details,
-                   const void *wire_reference,
-                   size_t wire_reference_size,
+                   uint64_t wire_reference,
                    struct GNUNET_TIME_Absolute execution_date)
 {
   struct ReserveContext *rc = cls;
@@ -2031,35 +2029,6 @@ analyze_reserves (void *cls)
    paying each merchant what they were due (and on time). */
 
 
-/**
- * Information we keep per loaded wire plugin.
- */
-struct WirePlugin
-{
-
-  /**
-   * Kept in a DLL.
-   */
-  struct WirePlugin *next;
-
-  /**
-   * Kept in a DLL.
-   */
-  struct WirePlugin *prev;
-
-  /**
-   * Name of the wire method.
-   */
-  char *type;
-
-  /**
-   * Handle to the wire plugin.
-   */
-  struct TALER_WIRE_Plugin *plugin;
-
-};
-
-
 /**
  * Information about wire fees charged by the exchange.
  */
@@ -2105,16 +2074,6 @@ struct WireFeeInfo
 struct AggregationContext
 {
 
-  /**
-   * DLL of wire plugins encountered.
-   */
-  struct WirePlugin *wire_head;
-
-  /**
-   * DLL of wire plugins encountered.
-   */
-  struct WirePlugin *wire_tail;
-
   /**
    * DLL of wire fees charged by the exchange.
    */
@@ -2132,46 +2091,6 @@ struct AggregationContext
 };
 
 
-/**
- * Find the relevant wire plugin.
- *
- * @param ac context to search
- * @param type type of the wire plugin to load; it
- *  will be used _as is_ from the dynamic loader.
- * @return NULL on error
- */
-static struct TALER_WIRE_Plugin *
-get_wire_plugin (struct AggregationContext *ac,
-                 const char *type)
-{
-  struct WirePlugin *wp;
-  struct TALER_WIRE_Plugin *plugin;
-
-  for (wp = ac->wire_head; NULL != wp; wp = wp->next)
-    if (0 == strcmp (type,
-                     wp->type))
-      return wp->plugin;
-
-  /* Wants the exact *plugin name* (!= method)  */
-  plugin = TALER_WIRE_plugin_load (cfg,
-                                   type);
-  if (NULL == plugin)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                "Failed to locate wire plugin for `%s'\n",
-                type);
-    return NULL;
-  }
-  wp = GNUNET_new (struct WirePlugin);
-  wp->type = GNUNET_strdup (type);
-  wp->plugin = plugin;
-  GNUNET_CONTAINER_DLL_insert (ac->wire_head,
-                               ac->wire_tail,
-                               wp);
-  return plugin;
-}
-
-
 /**
  * Closure for #wire_transfer_information_cb.
  */
@@ -2884,7 +2803,6 @@ check_wire_out_cb
 {
   struct AggregationContext *ac = cls;
   struct WireCheckContext wcc;
-  struct TALER_WIRE_Plugin *plugin;
   struct TALER_Amount final_amount;
   struct TALER_Amount exchange_gain;
   enum GNUNET_DB_QueryStatus qs;
@@ -2976,19 +2894,7 @@ check_wire_out_cb
   }
 
   /* Round down to amount supported by wire method */
-  plugin = get_wire_plugin
-             (ac,
-             TALER_WIRE_get_plugin_from_method (method));
-  if (NULL == plugin)
-  {
-    GNUNET_break (0);
-    GNUNET_free (method);
-    return GNUNET_SYSERR;
-  }
-  GNUNET_free (method);
-  GNUNET_break (GNUNET_SYSERR !=
-                plugin->amount_round (plugin->cls,
-                                      &final_amount));
+  GNUNET_break (TALER_WIRE_amount_round (&final_amount));
 
   /* Calculate the exchange's gain as the fees plus rounding differences! */
   if (GNUNET_OK !=
@@ -3071,7 +2977,6 @@ static enum GNUNET_DB_QueryStatus
 analyze_aggregations (void *cls)
 {
   struct AggregationContext ac;
-  struct WirePlugin *wc;
   struct WireFeeInfo *wfi;
   enum GNUNET_DB_QueryStatus qsx;
   enum GNUNET_DB_QueryStatus qs;
@@ -3125,15 +3030,6 @@ analyze_aggregations (void *cls)
     GNUNET_break (GNUNET_DB_STATUS_SOFT_ERROR == qs);
     ac.qs = qs;
   }
-  while (NULL != (wc = ac.wire_head))
-  {
-    GNUNET_CONTAINER_DLL_remove (ac.wire_head,
-                                 ac.wire_tail,
-                                 wc);
-    TALER_WIRE_plugin_unload (wc->plugin);
-    GNUNET_free (wc->type);
-    GNUNET_free (wc);
-  }
   while (NULL != (wfi = ac.fee_head))
   {
     GNUNET_CONTAINER_DLL_remove (ac.fee_head,
diff --git a/src/auditor/taler-wire-auditor.c b/src/auditor/taler-wire-auditor.c
index e66834a1..bd961746 100644
--- a/src/auditor/taler-wire-auditor.c
+++ b/src/auditor/taler-wire-auditor.c
@@ -1,6 +1,6 @@
 /*
   This file is part of TALER
-  Copyright (C) 2017-2019 Taler Systems SA
+  Copyright (C) 2017-2020 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
@@ -27,9 +27,11 @@
  */
 #include "platform.h"
 #include <gnunet/gnunet_util_lib.h>
+#include <gnunet/gnunet_curl_lib.h>
 #include "taler_auditordb_plugin.h"
 #include "taler_exchangedb_plugin.h"
 #include "taler_json_lib.h"
+#include "taler_bank_service.h"
 #include "taler_wire_lib.h"
 #include "taler_signatures.h"
 
@@ -65,9 +67,14 @@ struct WireAccount
   struct WireAccount *prev;
 
   /**
-   * Handle to the plugin.
+   * Authentication data for the account.
    */
-  struct TALER_WIRE_Plugin *wire_plugin;
+  struct TALER_BANK_AuthenticationData auth;
+
+  /**
+   * Our bank account number.
+   */
+  struct TALER_Account account;
 
   /**
    * Name of the section that configures this account.
@@ -77,7 +84,12 @@ struct WireAccount
   /**
    * Active wire request for the transaction history.
    */
-  struct TALER_WIRE_HistoryHandle *hh;
+  struct TALER_BANK_CreditHistoryHandle *chh;
+
+  /**
+   * Active wire request for the transaction history.
+   */
+  struct TALER_BANK_DebitHistoryHandle *dhh;
 
   /**
    * Progress point for this account.
@@ -92,17 +104,12 @@ struct WireAccount
   /**
    * Where we are in the inbound (CREDIT) transaction history.
    */
-  void *in_wire_off;
+  uint64_t in_wire_off;
 
   /**
    * Where we are in the inbound (DEBIT) transaction history.
    */
-  void *out_wire_off;
-
-  /**
-   * Number of bytes in #in_wire_off and #out_wire_off.
-   */
-  size_t wire_off_size;
+  uint64_t out_wire_off;
 
   /**
    * We should check for inbound transactions to this account.
@@ -341,6 +348,16 @@ static struct TALER_Amount total_wire_format_amount;
  */
 static struct TALER_Amount zero;
 
+/**
+ * Handle to the context for interacting with the bank.
+ */
+static struct GNUNET_CURL_Context *ctx;
+
+/**
+ * Scheduler context for running the @e ctx.
+ */
+static struct GNUNET_CURL_RescheduleContext *rc;
+
 
 /* *****************************   Shutdown   **************************** */
 
@@ -356,15 +373,12 @@ struct ReserveInInfo
    */
   struct GNUNET_HashCode row_off_hash;
 
-  /**
-   * Number of bytes in @e row_off.
-   */
-  size_t row_off_size;
-
   /**
    * Expected details about the wire transfer.
+   * The member "account_url" is to be allocated
+   * at the end of this struct!
    */
-  struct TALER_WIRE_TransferDetails details;
+  struct TALER_BANK_CreditDetails details;
 
   /**
    * RowID in reserves_in table.
@@ -389,7 +403,7 @@ struct ReserveOutInfo
   /**
    * Expected details about the wire transfer.
    */
-  struct TALER_WIRE_TransferDetails details;
+  struct TALER_BANK_DebitDetails details;
 
 };
 
@@ -427,8 +441,6 @@ free_rii (void *cls,
                  GNUNET_CONTAINER_multihashmap_remove (in_map,
                                                        key,
                                                        rii));
-  GNUNET_free (rii->details.account_url);
-  GNUNET_free_non_null (rii->details.wtid_s); /* field not used (yet) */
   GNUNET_free (rii);
   return GNUNET_OK;
 }
@@ -453,8 +465,6 @@ free_roi (void *cls,
                  GNUNET_CONTAINER_multihashmap_remove (out_map,
                                                        key,
                                                        roi));
-  GNUNET_free (roi->details.account_url);
-  GNUNET_free_non_null (roi->details.wtid_s); /* field not used (yet) */
   GNUNET_free (roi);
   return GNUNET_OK;
 }
@@ -495,6 +505,17 @@ do_shutdown (void *cls)
 {
   struct WireAccount *wa;
 
+  if (NULL != ctx)
+  {
+    GNUNET_CURL_fini (ctx);
+    ctx = NULL;
+  }
+  if (NULL != rc)
+  {
+    GNUNET_CURL_gnunet_rc_destroy (rc);
+    rc = NULL;
+  }
+
   if (NULL != report_row_inconsistencies)
   {
     json_t *report;
@@ -617,21 +638,22 @@ do_shutdown (void *cls)
   }
   while (NULL != (wa = wa_head))
   {
-    if (NULL != wa->hh)
+    if (NULL != wa->dhh)
     {
-      struct TALER_WIRE_Plugin *wp = wa->wire_plugin;
-
-      wp->get_history_cancel (wp->cls,
-                              wa->hh);
-      wa->hh = NULL;
+      TALER_BANK_debit_history_cancel (wa->dhh);
+      wa->dhh = NULL;
+    }
+    if (NULL != wa->chh)
+    {
+      TALER_BANK_credit_history_cancel (wa->chh);
+      wa->chh = NULL;
     }
     GNUNET_CONTAINER_DLL_remove (wa_head,
                                  wa_tail,
                                  wa);
-    TALER_WIRE_plugin_unload (wa->wire_plugin);
+    TALER_BANK_auth_free (&wa->auth);
+    TALER_WIRE_account_free (&wa->account);
     GNUNET_free (wa->section_name);
-    GNUNET_free_non_null (wa->in_wire_off);
-    GNUNET_free_non_null (wa->out_wire_off);
     GNUNET_free (wa);
   }
   if (NULL != adb)
@@ -787,8 +809,7 @@ commit (enum GNUNET_DB_QueryStatus qs)
                                                       wa->section_name,
                                                       &wa->pp,
                                                       wa->in_wire_off,
-                                                      wa->out_wire_off,
-                                                      wa->wire_off_size);
+                                                      wa->out_wire_off);
     else
       qs = adb->insert_wire_auditor_account_progress (adb->cls,
                                                       asession,
@@ -796,8 +817,7 @@ commit (enum GNUNET_DB_QueryStatus qs)
                                                       wa->section_name,
                                                       &wa->pp,
                                                       wa->in_wire_off,
-                                                      wa->out_wire_off,
-                                                      wa->wire_off_size);
+                                                      wa->out_wire_off);
     if (0 >= qs)
     {
       GNUNET_log (GNUNET_ERROR_TYPE_INFO,
@@ -1250,9 +1270,7 @@ complain_out_not_found (void *cls,
                      "amount_wired", TALER_JSON_from_amount (
                        &roi->details.amount),
                      "amount_justified", TALER_JSON_from_amount (&zero),
-                     "wtid", (NULL == roi->details.wtid_s)
-                     ? GNUNET_JSON_from_data_auto (&roi->details.wtid)
-                     : json_string (roi->details.wtid_s),
+                     "wtid", GNUNET_JSON_from_data_auto (&roi->details.wtid),
                      "timestamp", json_from_time_abs (
                        roi->details.execution_date),
                      "diagnostic",
@@ -1317,29 +1335,28 @@ check_exchange_wire_out (struct WireAccount *wa)
 
 /**
  * This function is called for all transactions that
- * are credited to the exchange's account (incoming
+ * are debited from the exchange's account (outgoing
  * transactions).
  *
  * @param cls `struct WireAccount` with current wire account to process
+ * @param http_status_code http status of the request
  * @param ec error code in case something went wrong
- * @param dir direction of the transfer
  * @param row_off identification of the position at which we are querying
- * @param row_off_size number of bytes in @a row_off
  * @param details details about the wire transfer
  * @return #GNUNET_OK to continue, #GNUNET_SYSERR to abort iteration
  */
 static int
 history_debit_cb (void *cls,
+                  unsigned int http_status_code,
                   enum TALER_ErrorCode ec,
-                  enum TALER_BANK_Direction dir,
-                  const void *row_off,
-                  size_t row_off_size,
-                  const struct TALER_WIRE_TransferDetails *details)
+                  uint64_t row_off,
+                  const struct TALER_BANK_DebitDetails *details,
+                  const json_t *json)
 {
   struct WireAccount *wa = cls;
   struct ReserveOutInfo *roi;
 
-  if (TALER_BANK_DIRECTION_NONE == dir)
+  if (NULL == details)
   {
     if (TALER_EC_NONE != ec)
     {
@@ -1348,7 +1365,7 @@ history_debit_cb (void *cls,
                   "Error fetching history: %u!\n",
                   (unsigned int) ec);
     }
-    wa->hh = NULL;
+    wa->dhh = NULL;
     check_exchange_wire_out (wa);
     return GNUNET_OK;
   }
@@ -1357,45 +1374,8 @@ history_debit_cb (void *cls,
               GNUNET_STRINGS_absolute_time_to_string (details->execution_date),
               TALER_amount2s (&details->amount),
               TALER_B2S (&details->wtid));
-  if (NULL != details->wtid_s)
-  {
-    char *diagnostic;
-
-    GNUNET_asprintf (&diagnostic,
-                     "malformed subject `%s'",
-                     details->wtid_s);
-    GNUNET_break (GNUNET_OK ==
-                  TALER_amount_add (&total_wire_format_amount,
-                                    &total_wire_format_amount,
-                                    &details->amount));
-    report (report_wire_format_inconsistencies,
-            json_pack ("{s:o, s:o, s:s}",
-                       "amount", TALER_JSON_from_amount (&details->amount),
-                       "wire_offset", GNUNET_JSON_from_data (row_off,
-                                                             row_off_size),
-                       "diagnostic", diagnostic));
-    GNUNET_free (diagnostic);
-    return GNUNET_OK;
-  }
-
   /* Update offset */
-  if (NULL == wa->out_wire_off)
-  {
-    wa->wire_off_size = row_off_size;
-    wa->out_wire_off = GNUNET_malloc (row_off_size);
-  }
-  if (wa->wire_off_size != row_off_size)
-  {
-    GNUNET_break (0);
-    commit (GNUNET_DB_STATUS_HARD_ERROR);
-    wa->hh = NULL;
-    GNUNET_SCHEDULER_shutdown ();
-    return GNUNET_SYSERR;
-  }
-  memcpy (wa->out_wire_off,
-          row_off,
-          row_off_size);
-
+  wa->out_wire_off = row_off;
   roi = GNUNET_new (struct ReserveOutInfo);
   GNUNET_CRYPTO_hash (&details->wtid,
                       sizeof (details->wtid),
@@ -1420,10 +1400,9 @@ history_debit_cb (void *cls,
                                     &total_wire_format_amount,
                                     &details->amount));
     report (report_wire_format_inconsistencies,
-            json_pack ("{s:o, s:o, s:s}",
+            json_pack ("{s:o, s:I, s:s}",
                        "amount", TALER_JSON_from_amount (&details->amount),
-                       "wire_offset", GNUNET_JSON_from_data (row_off,
-                                                             row_off_size),
+                       "wire_offset", (json_int_t) row_off,
                        "diagnostic", diagnostic));
     GNUNET_free (diagnostic);
     return GNUNET_OK;
@@ -1443,7 +1422,6 @@ static void
 process_debits (void *cls)
 {
   struct WireAccount *wa = cls;
-  struct TALER_WIRE_Plugin *wp;
 
   /* skip accounts where DEBIT is not enabled */
   while ( (NULL != wa) &&
@@ -1459,17 +1437,16 @@ process_debits (void *cls)
   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
               "Checking bank DEBIT records of account `%s'\n",
               wa->section_name);
-  GNUNET_assert (NULL == wa->hh);
-  wp = wa->wire_plugin;
-  wa->hh = wp->get_history (wp->cls,
-                            wa->section_name,
-                            TALER_BANK_DIRECTION_DEBIT,
-                            wa->out_wire_off,
-                            wa->wire_off_size,
-                            INT64_MAX,
-                            &history_debit_cb,
-                            wa);
-  if (NULL == wa->hh)
+  GNUNET_assert (NULL == wa->dhh);
+  wa->dhh = TALER_BANK_debit_history (ctx,
+                                      wa->account.details.x_taler_bank.
+                                      account_base_url,
+                                      &wa->auth,
+                                      wa->out_wire_off,
+                                      INT64_MAX,
+                                      &history_debit_cb,
+                                      wa);
+  if (NULL == wa->dhh)
   {
     fprintf (stderr,
              "Failed to obtain bank transaction history for `%s'\n",
@@ -1519,24 +1496,25 @@ conclude_credit_history ()
  * @param rowid unique serial ID for the entry in our DB
  * @param reserve_pub public key of the reserve (also the WTID)
  * @param credit amount that was received
- * @param sender_url payto://-URL of the sender's bank account
- * @param wire_reference unique identifier for the wire transfer 
(plugin-specific format)
- * @param wire_reference_size number of bytes in @a wire_reference
+ * @param sender_account_details payto://-URL of the sender's bank account
+ * @param wire_reference unique identifier for the wire transfer
  * @param execution_date when did we receive the funds
  * @return #GNUNET_OK to continue to iterate, #GNUNET_SYSERR to stop
  */
 static int
 reserve_in_cb (void *cls,
                uint64_t rowid,
-               const struct TALER_ReservePublicKeyP *reserve_pub,
+               const struct
+               TALER_ReservePublicKeyP *reserve_pub,
                const struct TALER_Amount *credit,
-               const char *sender_url,
-               const void *wire_reference,
-               size_t wire_reference_size,
-               struct GNUNET_TIME_Absolute execution_date)
+               const char *sender_account_details,
+               uint64_t wire_reference,
+               struct GNUNET_TIME_Absolute
+               execution_date)
 {
   struct WireAccount *wa = cls;
   struct ReserveInInfo *rii;
+  size_t slen;
 
   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
               "Analyzing exchange wire IN (%llu) at %s of %s with reserve_pub 
%s\n",
@@ -1544,21 +1522,20 @@ reserve_in_cb (void *cls,
               GNUNET_STRINGS_absolute_time_to_string (execution_date),
               TALER_amount2s (credit),
               TALER_B2S (reserve_pub));
-  rii = GNUNET_new (struct ReserveInInfo);
-  GNUNET_CRYPTO_hash (wire_reference,
-                      wire_reference_size,
-                      &rii->row_off_hash);
-  rii->row_off_size = wire_reference_size;
+  slen = strlen (sender_account_details) + 1;
+  rii = GNUNET_malloc (sizeof (struct ReserveInInfo)
+                       + slen);
+  rii->rowid = rowid;
   rii->details.amount = *credit;
   rii->details.execution_date = execution_date;
-  /* reserve public key should be the WTID */
-  GNUNET_assert (sizeof (rii->details.wtid) ==
-                 sizeof (*reserve_pub));
-  memcpy (&rii->details.wtid,
-          reserve_pub,
-          sizeof (*reserve_pub));
-  rii->details.account_url = GNUNET_strdup (sender_url);
-  rii->rowid = rowid;
+  rii->details.reserve_pub = *reserve_pub;
+  rii->details.account_url = (const char *) &rii[1];
+  memcpy (&rii[1],
+          sender_account_details,
+          slen);
+  GNUNET_CRYPTO_hash (&wire_reference,
+                      sizeof (uint64_t),
+                      &rii->row_off_hash);
   if (GNUNET_OK !=
       GNUNET_CONTAINER_multihashmap_put (in_map,
                                          &rii->row_off_hash,
@@ -1572,8 +1549,6 @@ reserve_in_cb (void *cls,
                        "wire_offset_hash", GNUNET_JSON_from_data_auto (
                          &rii->row_off_hash),
                        "diagnostic", "duplicate wire offset"));
-    GNUNET_free (rii->details.account_url);
-    GNUNET_free_non_null (rii->details.wtid_s); /* field not used (yet) */
     GNUNET_free (rii);
     return GNUNET_OK;
   }
@@ -1604,7 +1579,8 @@ complain_in_not_found (void *cls,
                      "amount_exchange_expected", TALER_JSON_from_amount (
                        &rii->details.amount),
                      "amount_wired", TALER_JSON_from_amount (&zero),
-                     "wtid", GNUNET_JSON_from_data_auto (&rii->details.wtid),
+                     "reserve_pub", GNUNET_JSON_from_data_auto (
+                       &rii->details.reserve_pub),
                      "timestamp", json_from_time_abs (
                        rii->details.execution_date),
                      "account", wa->section_name,
@@ -1635,25 +1611,24 @@ process_credits (void *cls);
  *
  * @param cls `struct WireAccount` we are processing
  * @param ec error code in case something went wrong
- * @param dir direction of the transfer
  * @param row_off identification of the position at which we are querying
- * @param row_off_size number of bytes in @a row_off
  * @param details details about the wire transfer
+ * @param json raw response
  * @return #GNUNET_OK to continue, #GNUNET_SYSERR to abort iteration
  */
 static int
 history_credit_cb (void *cls,
+                   unsigned int http_status,
                    enum TALER_ErrorCode ec,
-                   enum TALER_BANK_Direction dir,
-                   const void *row_off,
-                   size_t row_off_size,
-                   const struct TALER_WIRE_TransferDetails *details)
+                   uint64_t row_off,
+                   const struct TALER_BANK_CreditDetails *details,
+                   const json_t *json)
 {
   struct WireAccount *wa = cls;
   struct ReserveInInfo *rii;
   struct GNUNET_HashCode key;
 
-  if (TALER_BANK_DIRECTION_NONE == dir)
+  if (NULL == details)
   {
     if (TALER_EC_NONE != ec)
     {
@@ -1663,7 +1638,7 @@ history_credit_cb (void *cls,
                   (unsigned int) ec);
     }
     /* end of operation */
-    wa->hh = NULL;
+    wa->chh = NULL;
     GNUNET_log (GNUNET_ERROR_TYPE_INFO,
                 "Reconciling CREDIT processing of account `%s'\n",
                 wa->section_name);
@@ -1678,12 +1653,12 @@ history_credit_cb (void *cls,
     return GNUNET_OK;
   }
   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
-              "Analyzing bank CREDIT at %s of %s with WTID %s\n",
+              "Analyzing bank CREDIT at %s of %s with Reserve-pub %s\n",
               GNUNET_STRINGS_absolute_time_to_string (details->execution_date),
               TALER_amount2s (&details->amount),
-              TALER_B2S (&details->wtid));
-  GNUNET_CRYPTO_hash (row_off,
-                      row_off_size,
+              TALER_B2S (&details->reserve_pub));
+  GNUNET_CRYPTO_hash (&row_off,
+                      sizeof (row_off),
                       &key);
   rii = GNUNET_CONTAINER_multihashmap_get (in_map,
                                            &key);
@@ -1693,55 +1668,26 @@ history_credit_cb (void *cls,
                 "Failed to find wire transfer at `%s' in exchange database. 
Audit ends at this point in time.\n",
                 GNUNET_STRINGS_absolute_time_to_string (
                   details->execution_date));
-    wa->hh = NULL;
+    wa->chh = NULL;
     process_credits (wa->next);
     return GNUNET_SYSERR; /* not an error, just end of processing */
   }
 
   /* Update offset */
-  if (NULL == wa->in_wire_off)
-  {
-    wa->wire_off_size = row_off_size;
-    wa->in_wire_off = GNUNET_malloc (row_off_size);
-  }
-  if (wa->wire_off_size != row_off_size)
-  {
-    GNUNET_break (0);
-    commit (GNUNET_DB_STATUS_HARD_ERROR);
-    GNUNET_SCHEDULER_shutdown ();
-    return GNUNET_SYSERR;
-  }
-  memcpy (wa->in_wire_off,
-          row_off,
-          row_off_size);
-
-
+  wa->in_wire_off = row_off;
   /* compare records with expected data */
-  if (row_off_size != rii->row_off_size)
-  {
-    GNUNET_break (0);
-    report (report_row_inconsistencies,
-            json_pack ("{s:s, s:I, s:o, s:o, s:s}",
-                       "table", "reserves_in",
-                       "row", (json_int_t) rii->rowid,
-                       "raw_bank_row", GNUNET_JSON_from_data (row_off,
-                                                              row_off_size),
-                       "wire_offset_hash", GNUNET_JSON_from_data_auto (&key),
-                       "diagnostic", "wire reference size missmatch"));
-    return GNUNET_OK;
-  }
-  if (0 != GNUNET_memcmp (&details->wtid,
-                          &rii->details.wtid))
+  if (0 != GNUNET_memcmp (&details->reserve_pub,
+                          &rii->details.reserve_pub))
   {
     report (report_reserve_in_inconsistencies,
-            json_pack ("{s:I, s:o, s:o, s:o, s:o, s:o, s:s}",
+            json_pack ("{s:I, s:I, s:o, s:o, s:o, s:o, s:s}",
                        "row", (json_int_t) rii->rowid,
-                       "raw_bank_row", GNUNET_JSON_from_data (row_off,
-                                                              row_off_size),
+                       "bank_row", (json_int_t) row_off,
                        "amount_exchange_expected", TALER_JSON_from_amount (
                          &rii->details.amount),
                        "amount_wired", TALER_JSON_from_amount (&zero),
-                       "wtid", GNUNET_JSON_from_data_auto (&rii->details.wtid),
+                       "reserve_pub", GNUNET_JSON_from_data_auto (
+                         &rii->details.reserve_pub),
                        "timestamp", json_from_time_abs (
                          rii->details.execution_date),
                        "diagnostic", "wire subject does not match"));
@@ -1750,15 +1696,15 @@ history_credit_cb (void *cls,
                                     &total_bad_amount_in_minus,
                                     &rii->details.amount));
     report (report_reserve_in_inconsistencies,
-            json_pack ("{s:I, s:o, s:o, s:o, s:o, s:o, s:s}",
+            json_pack ("{s:I, s:I, s:o, s:o, s:o, s:o, s:s}",
                        "row", (json_int_t) rii->rowid,
-                       "raw_bank_row", GNUNET_JSON_from_data (row_off,
-                                                              row_off_size),
+                       "bank_row", (json_int_t) row_off,
                        "amount_exchange_expected", TALER_JSON_from_amount (
                          &zero),
                        "amount_wired", TALER_JSON_from_amount (
                          &details->amount),
-                       "wtid", GNUNET_JSON_from_data_auto (&details->wtid),
+                       "reserve_pub", GNUNET_JSON_from_data_auto (
+                         &details->reserve_pub),
                        "timestamp", json_from_time_abs (
                          details->execution_date),
                        "diagnostic", "wire subject does not match"));
@@ -1773,15 +1719,15 @@ history_credit_cb (void *cls,
                              &details->amount))
   {
     report (report_reserve_in_inconsistencies,
-            json_pack ("{s:I, s:o, s:o, s:o, s:o, s:o, s:s}",
+            json_pack ("{s:I, s:I, s:o, s:o, s:o, s:o, s:s}",
                        "row", (json_int_t) rii->rowid,
-                       "raw_bank_row", GNUNET_JSON_from_data (row_off,
-                                                              row_off_size),
+                       "bank_row", (json_int_t) row_off,
                        "amount_exchange_expected", TALER_JSON_from_amount (
                          &rii->details.amount),
                        "amount_wired", TALER_JSON_from_amount (
                          &details->amount),
-                       "wtid", GNUNET_JSON_from_data_auto (&details->wtid),
+                       "reserve_pub", GNUNET_JSON_from_data_auto (
+                         &details->reserve_pub),
                        "timestamp", json_from_time_abs (
                          details->execution_date),
                        "diagnostic", "wire amount does not match"));
@@ -1820,13 +1766,12 @@ history_credit_cb (void *cls,
                        rii->details.account_url))
   {
     report (report_missattribution_in_inconsistencies,
-            json_pack ("{s:o, s:I, s:o, s:o}",
+            json_pack ("{s:o, s:I, s:I, s:o}",
                        "amount", TALER_JSON_from_amount (&rii->details.amount),
                        "row", (json_int_t) rii->rowid,
-                       "raw_bank_row", GNUNET_JSON_from_data (row_off,
-                                                              row_off_size),
-                       "wtid", GNUNET_JSON_from_data_auto (
-                         &rii->details.wtid)));
+                       "bank_row", (json_int_t) row_off,
+                       "reserve_pub", GNUNET_JSON_from_data_auto (
+                         &rii->details.reserve_pub)));
     GNUNET_break (GNUNET_OK ==
                   TALER_amount_add (&total_missattribution_in,
                                     &total_missattribution_in,
@@ -1836,11 +1781,10 @@ history_credit_cb (void *cls,
       rii->details.execution_date.abs_value_us)
   {
     report (report_row_minor_inconsistencies,
-            json_pack ("{s:s, s:I, s:o, s:s}",
+            json_pack ("{s:s, s:I, s:I, s:s}",
                        "table", "reserves_in",
                        "row", (json_int_t) rii->rowid,
-                       "raw_bank_row", GNUNET_JSON_from_data (row_off,
-                                                              row_off_size),
+                       "bank_row", (json_int_t) row_off,
                        "diagnostic", "execution date missmatch"));
   }
 cleanup:
@@ -1865,7 +1809,6 @@ static void
 process_credits (void *cls)
 {
   struct WireAccount *wa = cls;
-  struct TALER_WIRE_Plugin *wp;
   enum GNUNET_DB_QueryStatus qs;
 
   /* skip accounts where CREDIT is not enabled */
@@ -1899,16 +1842,15 @@ process_credits (void *cls)
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
               "Starting bank CREDIT history of account `%s'\n",
               wa->section_name);
-  wp = wa->wire_plugin;
-  wa->hh = wp->get_history (wp->cls,
-                            wa->section_name,
-                            TALER_BANK_DIRECTION_CREDIT,
-                            wa->in_wire_off,
-                            wa->wire_off_size,
-                            INT64_MAX,
-                            &history_credit_cb,
-                            wa);
-  if (NULL == wa->hh)
+  wa->chh = TALER_BANK_credit_history (ctx,
+                                       wa->account.details.x_taler_bank.
+                                       account_base_url,
+                                       &wa->auth,
+                                       wa->in_wire_off,
+                                       INT64_MAX,
+                                       &history_credit_cb,
+                                       wa);
+  if (NULL == wa->chh)
   {
     fprintf (stderr,
              "Failed to obtain bank transaction history\n");
@@ -2037,8 +1979,7 @@ begin_transaction ()
                                                   wa->section_name,
                                                   &wa->pp,
                                                   &wa->in_wire_off,
-                                                  &wa->out_wire_off,
-                                                  &wa->wire_off_size);
+                                                  &wa->out_wire_off);
     if (0 > qsx)
     {
       GNUNET_break (GNUNET_DB_STATUS_SOFT_ERROR == qsx);
@@ -2096,30 +2037,62 @@ process_account_cb (void *cls,
                     const struct TALER_EXCHANGEDB_AccountInfo *ai)
 {
   struct WireAccount *wa;
-  struct TALER_WIRE_Plugin *wp;
 
   if ( (GNUNET_NO == ai->debit_enabled) &&
        (GNUNET_NO == ai->credit_enabled) )
     return; /* not an active exchange account */
-  wp = TALER_WIRE_plugin_load (cfg,
-                               ai->plugin_name);
-  if (NULL == wp)
-  {
-    fprintf (stderr,
-             "Failed to load wire plugin `%s'\n",
-             ai->plugin_name);
-    global_ret = 1;
-    GNUNET_SCHEDULER_shutdown ();
-    return;
-  }
   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
               "Found exchange account `%s'\n",
               ai->section_name);
   wa = GNUNET_new (struct WireAccount);
-  wa->wire_plugin = wp;
   wa->section_name = GNUNET_strdup (ai->section_name);
   wa->watch_debit = ai->debit_enabled;
   wa->watch_credit = ai->credit_enabled;
+  if (GNUNET_OK !=
+      TALER_BANK_auth_parse_cfg (cfg,
+                                 ai->section_name,
+                                 &wa->auth))
+  {
+    GNUNET_break (0);
+    GNUNET_free (wa->section_name);
+    GNUNET_free (wa);
+    fprintf (stderr,
+             "Failed to access bank account `%s'\n",
+             wa->section_name);
+    global_ret = 1;
+    GNUNET_SCHEDULER_shutdown ();
+    return;
+  }
+  if (GNUNET_OK !=
+      TALER_BANK_account_parse_cfg (cfg,
+                                    wa->section_name,
+                                    &wa->account))
+  {
+    GNUNET_break (0);
+    TALER_BANK_auth_free (&wa->auth);
+    GNUNET_free (wa->section_name);
+    GNUNET_free (wa);
+    fprintf (stderr,
+             "Failed to access bank account `%s'\n",
+             wa->section_name);
+    global_ret = 1;
+    GNUNET_SCHEDULER_shutdown ();
+    return;
+  }
+  if (TALER_PAC_X_TALER_BANK != wa->account.type)
+  {
+    GNUNET_break (0);
+    TALER_WIRE_account_free (&wa->account);
+    TALER_BANK_auth_free (&wa->auth);
+    GNUNET_free (wa->section_name);
+    GNUNET_free (wa);
+    fprintf (stderr,
+             "Need x-taler-bank account URL in `%s'\n",
+             wa->section_name);
+    global_ret = 1;
+    GNUNET_SCHEDULER_shutdown ();
+    return;
+  }
   GNUNET_CONTAINER_DLL_insert (wa_head,
                                wa_tail,
                                wa);
@@ -2258,6 +2231,14 @@ run (void *cls,
   }
   GNUNET_SCHEDULER_add_shutdown (&do_shutdown,
                                  NULL);
+  ctx = GNUNET_CURL_init (&GNUNET_CURL_gnunet_scheduler_reschedule,
+                          &rc);
+  rc = GNUNET_CURL_gnunet_rc_create (ctx);
+  if (NULL == ctx)
+  {
+    GNUNET_break (0);
+    return;
+  }
   esession = edb->get_session (edb->cls);
   if (NULL == esession)
   {
diff --git a/src/auditordb/plugin_auditordb_postgres.c 
b/src/auditordb/plugin_auditordb_postgres.c
index 060e745d..7360258a 100644
--- a/src/auditordb/plugin_auditordb_postgres.c
+++ b/src/auditordb/plugin_auditordb_postgres.c
@@ -1,6 +1,6 @@
 /*
   This file is part of TALER
-  Copyright (C) 2014-2018 GNUnet e.V.
+  Copyright (C) 2014-2020 GNUnet e.V.
 
   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
@@ -241,8 +241,8 @@ postgres_create_tables (void *cls)
       ",account_name TEXT NOT NULL"
       ",last_wire_reserve_in_serial_id INT8 NOT NULL DEFAULT 0"
       ",last_wire_wire_out_serial_id INT8 NOT NULL DEFAULT 0"
-      ",wire_in_off BYTEA"
-      ",wire_out_off BYTEA"
+      ",wire_in_off INT8"
+      ",wire_out_off INT8"
       ")"),
     GNUNET_PQ_make_execute ("CREATE TABLE IF NOT EXISTS wire_auditor_progress"
                             "(master_pub BYTEA CONSTRAINT master_pub_ref 
REFERENCES auditor_exchanges(master_pub) ON DELETE CASCADE"
@@ -2135,23 +2135,16 @@ postgres_insert_wire_auditor_account_progress (void 
*cls,
                                                const struct
                                                
TALER_AUDITORDB_WireAccountProgressPoint
                                                *pp,
-                                               const void *in_wire_off,
-                                               const void *out_wire_off,
-                                               size_t wire_off_size)
+                                               uint64_t in_wire_off,
+                                               uint64_t out_wire_off)
 {
   struct GNUNET_PQ_QueryParam params[] = {
     GNUNET_PQ_query_param_auto_from_type (master_pub),
     GNUNET_PQ_query_param_string (account_name),
     GNUNET_PQ_query_param_uint64 (&pp->last_reserve_in_serial_id),
     GNUNET_PQ_query_param_uint64 (&pp->last_wire_out_serial_id),
-    GNUNET_PQ_query_param_fixed_size (in_wire_off,
-                                      NULL == in_wire_off
-                                      ? 0
-                                      : wire_off_size),
-    GNUNET_PQ_query_param_fixed_size (out_wire_off,
-                                      NULL == out_wire_off
-                                      ? 0
-                                      : wire_off_size),
+    GNUNET_PQ_query_param_uint64 (&in_wire_off),
+    GNUNET_PQ_query_param_uint64 (&out_wire_off),
     GNUNET_PQ_query_param_end
   };
 
@@ -2182,21 +2175,14 @@ postgres_update_wire_auditor_account_progress (void 
*cls,
                                                const struct
                                                
TALER_AUDITORDB_WireAccountProgressPoint
                                                *pp,
-                                               const void *in_wire_off,
-                                               const void *out_wire_off,
-                                               size_t wire_off_size)
+                                               uint64_t in_wire_off,
+                                               uint64_t out_wire_off)
 {
   struct GNUNET_PQ_QueryParam params[] = {
     GNUNET_PQ_query_param_uint64 (&pp->last_reserve_in_serial_id),
     GNUNET_PQ_query_param_uint64 (&pp->last_wire_out_serial_id),
-    GNUNET_PQ_query_param_fixed_size (in_wire_off,
-                                      NULL == in_wire_off
-                                      ? 0
-                                      : wire_off_size),
-    GNUNET_PQ_query_param_fixed_size (out_wire_off,
-                                      NULL == out_wire_off
-                                      ? 0
-                                      : wire_off_size),
+    GNUNET_PQ_query_param_uint64 (&in_wire_off),
+    GNUNET_PQ_query_param_uint64 (&out_wire_off),
     GNUNET_PQ_query_param_auto_from_type (master_pub),
     GNUNET_PQ_query_param_string (account_name),
     GNUNET_PQ_query_param_end
@@ -2231,12 +2217,9 @@ postgres_get_wire_auditor_account_progress (void *cls,
                                             struct
                                             
TALER_AUDITORDB_WireAccountProgressPoint
                                             *pp,
-                                            void **in_wire_off,
-                                            void **out_wire_off,
-                                            size_t *wire_off_size)
+                                            uint64_t *in_wire_off,
+                                            uint64_t *out_wire_off)
 {
-  size_t xsize;
-  enum GNUNET_DB_QueryStatus qs;
   struct GNUNET_PQ_QueryParam params[] = {
     GNUNET_PQ_query_param_auto_from_type (master_pub),
     GNUNET_PQ_query_param_string (account_name),
@@ -2247,30 +2230,17 @@ postgres_get_wire_auditor_account_progress (void *cls,
                                   &pp->last_reserve_in_serial_id),
     GNUNET_PQ_result_spec_uint64 ("last_wire_wire_out_serial_id",
                                   &pp->last_wire_out_serial_id),
-    GNUNET_PQ_result_spec_variable_size ("wire_in_off",
-                                         in_wire_off,
-                                         wire_off_size),
-    GNUNET_PQ_result_spec_variable_size ("wire_out_off",
-                                         out_wire_off,
-                                         &xsize),
+    GNUNET_PQ_result_spec_uint64 ("wire_in_off",
+                                  in_wire_off),
+    GNUNET_PQ_result_spec_uint64 ("wire_out_off",
+                                  out_wire_off),
     GNUNET_PQ_result_spec_end
   };
 
-  qs = GNUNET_PQ_eval_prepared_singleton_select (session->conn,
-                                                 
"wire_auditor_account_progress_select",
-                                                 params,
-                                                 rs);
-  if (qs <= 0)
-  {
-    *wire_off_size = 0;
-    xsize = 0;
-  }
-  if ( (0 != xsize) &&
-       (0 != *wire_off_size) )
-  {
-    GNUNET_assert (xsize == *wire_off_size);
-  }
-  return qs;
+  return GNUNET_PQ_eval_prepared_singleton_select (session->conn,
+                                                   
"wire_auditor_account_progress_select",
+                                                   params,
+                                                   rs);
 }
 
 
diff --git a/src/bank-lib/Makefile.am b/src/bank-lib/Makefile.am
index 3bb86323..371f5e6d 100644
--- a/src/bank-lib/Makefile.am
+++ b/src/bank-lib/Makefile.am
@@ -39,8 +39,9 @@ libtalerbank_la_LDFLAGS = \
 libtalerbank_la_SOURCES = \
   bank_api_admin.c \
   bank_api_common.c bank_api_common.h \
-  bank_api_history.c \
-  bank_api_reject.c \
+  bank_api_credit.c \
+  bank_api_debit.c \
+  bank_api_transaction.c \
   bank_api_parse.c
 libtalerbank_la_LIBADD = \
   $(top_builddir)/src/json/libtalerjson.la \
@@ -55,10 +56,10 @@ libtalerfakebank_la_LDFLAGS = \
   -version-info 0:0:0 \
   -no-undefined
 libtalerfakebank_la_SOURCES = \
-  fakebank_history.c \
-  fakebank.c fakebank.h
+  fakebank.c
 libtalerfakebank_la_LIBADD = \
   $(top_builddir)/src/json/libtalerjson.la \
+  $(top_builddir)/src/mhd/libtalermhd.la \
   -lgnunetjson \
   -lgnunetutil \
   -ljansson \
@@ -69,8 +70,8 @@ libtalerbanktesting_la_LDFLAGS = \
   -version-info 0:0:0 \
   -no-undefined
 libtalerbanktesting_la_SOURCES = \
-  testing_api_cmd_history.c \
-  testing_api_cmd_reject.c \
+  testing_api_cmd_history_credit.c \
+  testing_api_cmd_history_debit.c \
   testing_api_helpers.c
 libtalerbanktesting_la_LIBADD = \
   $(top_builddir)/src/json/libtalerjson.la \
diff --git a/src/bank-lib/bank_api_admin.c b/src/bank-lib/bank_api_admin.c
index 5240a372..068fd0e0 100644
--- a/src/bank-lib/bank_api_admin.c
+++ b/src/bank-lib/bank_api_admin.c
@@ -1,6 +1,6 @@
 /*
   This file is part of TALER
-  Copyright (C) 2015, 2016, 2017 Taler Systems SA
+  Copyright (C) 2015--2020 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
@@ -166,13 +166,11 @@ handle_admin_add_incoming_finished (void *cls,
  * to the operators of the bank.
  *
  * @param ctx curl context for the event loop
- * @param bank_base_url URL of the bank (used to execute this request)
+ * @param account_base_url URL of the bank (used to execute this request)
  * @param auth authentication data to send to the bank
- * @param exchange_base_url base URL of the exchange (for tracking)
- * @param subject wire transfer subject for the transfer
+ * @param reserve_pub wire transfer subject for the transfer
  * @param amount amount that was deposited
- * @param debit_account_no account number to withdraw from (53 bits at most)
- * @param credit_account_no account number to deposit into (53 bits at most)
+ * @param credit_account account to deposit into (payto)
  * @param res_cb the callback to call when the final result for this request 
is available
  * @param res_cb_cls closure for the above callback
  * @return NULL
@@ -181,13 +179,12 @@ handle_admin_add_incoming_finished (void *cls,
  */
 struct TALER_BANK_AdminAddIncomingHandle *
 TALER_BANK_admin_add_incoming (struct GNUNET_CURL_Context *ctx,
-                               const char *bank_base_url,
+                               const char *account_base_url,
                                const struct TALER_BANK_AuthenticationData 
*auth,
-                               const char *exchange_base_url,
-                               const char *subject,
+                               const struct
+                               TALER_ReservePublicKeyP *reserve_pub,
                                const struct TALER_Amount *amount,
-                               uint64_t debit_account_no,
-                               uint64_t credit_account_no,
+                               const char *credit_account,
                                TALER_BANK_AdminAddIncomingResultCallback 
res_cb,
                                void *res_cb_cls)
 {
@@ -195,18 +192,10 @@ TALER_BANK_admin_add_incoming (struct GNUNET_CURL_Context 
*ctx,
   json_t *admin_obj;
   CURL *eh;
 
-  if (NULL == exchange_base_url)
-  {
-    GNUNET_break (0);
-    return NULL;
-  }
-  admin_obj = json_pack ("{s:{s:s}, s:s, s:s, s:o, s:I, s:I}",
-                         "auth", "type", "basic",
-                         "exchange_url", exchange_base_url,
-                         "subject", subject,
+  admin_obj = json_pack ("{s:o, s:o, s:s}",
+                         "subject", GNUNET_JSON_from_data_auto (reserve_pub),
                          "amount", TALER_JSON_from_amount (amount),
-                         "debit_account", (json_int_t) debit_account_no,
-                         "credit_account", (json_int_t) credit_account_no);
+                         "credit_account", credit_account);
   if (NULL == admin_obj)
   {
     GNUNET_break (0);
@@ -215,27 +204,33 @@ TALER_BANK_admin_add_incoming (struct GNUNET_CURL_Context 
*ctx,
   aai = GNUNET_new (struct TALER_BANK_AdminAddIncomingHandle);
   aai->cb = res_cb;
   aai->cb_cls = res_cb_cls;
-  aai->request_url = TALER_BANK_path_to_url_ (bank_base_url,
+  aai->request_url = TALER_BANK_path_to_url_ (account_base_url,
                                               "/admin/add/incoming");
-  aai->post_ctx.headers = TALER_BANK_make_auth_header_ (auth);
-
-  GNUNET_assert
-    (NULL != (aai->post_ctx.headers = curl_slist_append
-                                        (aai->post_ctx.headers,
-                                        "Content-Type: application/json")));
+  aai->post_ctx.headers = curl_slist_append
+                            (aai->post_ctx.headers,
+                            "Content-Type: application/json");
 
   eh = curl_easy_init ();
-
-  GNUNET_assert (GNUNET_OK ==
-                 TALER_curl_easy_post (&aai->post_ctx, eh, admin_obj));
-
+  if ( (GNUNET_OK !=
+        TALER_BANK_setup_auth_ (eh,
+                                auth)) ||
+       (CURLE_OK !=
+        curl_easy_setopt (eh,
+                          CURLOPT_URL,
+                          aai->request_url)) ||
+       (GNUNET_OK !=
+        TALER_curl_easy_post (&aai->post_ctx,
+                              eh,
+                              admin_obj)) )
+  {
+    GNUNET_break (0);
+    TALER_BANK_admin_add_incoming_cancel (aai);
+    curl_easy_cleanup (eh);
+    json_decref (admin_obj);
+    return NULL;
+  }
   json_decref (admin_obj);
 
-  GNUNET_assert (CURLE_OK ==
-                 curl_easy_setopt (eh,
-                                   CURLOPT_URL,
-                                   aai->request_url));
-
   aai->job = GNUNET_CURL_job_add2 (ctx,
                                    eh,
                                    aai->post_ctx.headers,
diff --git a/src/bank-lib/bank_api_common.c b/src/bank-lib/bank_api_common.c
index 50769dae..8a8f4289 100644
--- a/src/bank-lib/bank_api_common.c
+++ b/src/bank-lib/bank_api_common.c
@@ -1,6 +1,6 @@
 /*
   This file is part of TALER
-  Copyright (C) 2015, 2016, 2017 GNUnet e.V.
+  Copyright (C) 2015-2020 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
@@ -24,67 +24,47 @@
 
 
 /**
- * Append HTTP key-value pair to curl header list.
+ * Set authentication data in @a easy from @a auth.
+ * The API currently specifies the use of HTTP basic
+ * authentication.
  *
- * @param hdr list to append to, can be NULL
- * @param key key to append
- * @param value value to append
- * @return new list, NULL on error
+ * @param easy curl handle to setup for authentication
+ * @param auth authentication data to use
+ * @return #GNUNET_OK in success
  */
-static struct curl_slist *
-append (struct curl_slist *hdr,
-        const char *key,
-        const char *value)
+int
+TALER_BANK_setup_auth_ (CURL *easy,
+                        const struct TALER_BANK_AuthenticationData *auth)
 {
-  char *str;
-  struct curl_slist *ret;
-
-  GNUNET_asprintf (&str,
-                   "%s: %s",
-                   key,
-                   value);
-  ret = curl_slist_append (hdr,
-                           str);
-  GNUNET_free (str);
-  if (NULL == ret)
-  {
-    GNUNET_break (0);
-    curl_slist_free_all (hdr);
-    return NULL;
-  }
-  return ret;
-}
-
-
-/**
- * Build authentication header from @a auth.
- *
- * @param auth authentication data to use.
- *
- * @return NULL on error, otherwise curl headers to use.
- */
-struct curl_slist *
-TALER_BANK_make_auth_header_
-  (const struct TALER_BANK_AuthenticationData *auth)
-{
-  struct curl_slist *authh;
+  int ret;
 
+  ret = GNUNET_OK;
   switch (auth->method)
   {
   case TALER_BANK_AUTH_NONE:
-    return NULL;
+    return GNUNET_OK;
   case TALER_BANK_AUTH_BASIC:
-    authh = append (NULL,
-                    "X-Taler-Bank-Username",
-                    auth->details.basic.username);
-    if (NULL == authh)
-      return NULL;
-    authh = append (authh,
-                    "X-Taler-Bank-Password",
-                    auth->details.basic.password);
-    return authh;
+    {
+      char *up;
+
+      GNUNET_asprintf (&up,
+                       "%s:%s",
+                       auth->details.basic.username,
+                       auth->details.basic.password);
+      if ( (CURLE_OK !=
+            curl_easy_setopt (easy,
+                              CURLOPT_HTTPAUTH,
+                              CURLAUTH_BASIC)) ||
+           (CURLE_OK !=
+            curl_easy_setopt (easy,
+                              CURLOPT_USERPWD,
+                              up)) )
+        ret = GNUNET_SYSERR;
+      GNUNET_free (up);
+      break;
+    }
   }
-  return NULL;
+  return ret;
 }
 
 
diff --git a/src/bank-lib/bank_api_common.h b/src/bank-lib/bank_api_common.h
index fcf2029d..1120ed94 100644
--- a/src/bank-lib/bank_api_common.h
+++ b/src/bank-lib/bank_api_common.h
@@ -39,6 +39,18 @@ struct curl_slist *
 TALER_BANK_make_auth_header_ (const struct TALER_BANK_AuthenticationData 
*auth);
 
 
+/**
+ * Set authentication data in @a easy from @a auth.
+ *
+ * @param easy curl handle to setup for authentication
+ * @param auth authentication data to use
+ * @return #GNUNET_OK in success
+ */
+int
+TALER_BANK_setup_auth_ (CURL *easy,
+                        const struct TALER_BANK_AuthenticationData *auth);
+
+
 /**
  * Obtain the URL to use for an API request.
  *
diff --git a/src/bank-lib/bank_api_history.c b/src/bank-lib/bank_api_credit.c
similarity index 50%
copy from src/bank-lib/bank_api_history.c
copy to src/bank-lib/bank_api_credit.c
index f5013b85..ed0a1e2a 100644
--- a/src/bank-lib/bank_api_history.c
+++ b/src/bank-lib/bank_api_credit.c
@@ -1,6 +1,6 @@
 /*
   This file is part of TALER
-  Copyright (C) 2017 GNUnet e.V. & Inria
+  Copyright (C) 2017--2020 Taler Systems SA
 
   TALER is free software; you can redistribute it and/or
   modify it under the terms of the GNU General Public License
@@ -32,7 +32,7 @@
 /**
  * @brief A /history Handle
  */
-struct TALER_BANK_HistoryHandle
+struct TALER_BANK_CreditHistoryHandle
 {
 
   /**
@@ -50,15 +50,10 @@ struct TALER_BANK_HistoryHandle
    */
   struct GNUNET_CURL_Job *job;
 
-  /**
-   * HTTP authentication-related headers for the request.
-   */
-  struct curl_slist *authh;
-
   /**
    * Function to call with the result.
    */
-  TALER_BANK_HistoryResultCallback hcb;
+  TALER_BANK_CreditResultCallback hcb;
 
   /**
    * Closure for @a cb.
@@ -77,37 +72,37 @@ struct TALER_BANK_HistoryHandle
  *         #GNUNET_SYSERR if there was a protocol violation in @a history
  */
 static int
-parse_account_history (struct TALER_BANK_HistoryHandle *hh,
+parse_account_history (struct TALER_BANK_CreditHistoryHandle *hh,
                        const json_t *history)
 {
   json_t *history_array;
-  char *bank_hostname;
 
-  if (NULL == (history_array = json_object_get (history, "data")))
+  if (NULL == (history_array = json_object_get (history,
+                                                "data")))
+  {
+    GNUNET_break_op (0);
+    return GNUNET_SYSERR;
+  }
+  if (! json_is_array (history_array))
   {
     GNUNET_break_op (0);
     return GNUNET_SYSERR;
   }
   for (unsigned int i = 0; i<json_array_size (history_array); i++)
   {
-    struct TALER_BANK_TransferDetails td;
-    const char *sign;
-    uint64_t other_account;
+    struct TALER_BANK_CreditDetails td;
     uint64_t row_id;
-    enum TALER_BANK_Direction direction;
     struct GNUNET_JSON_Specification hist_spec[] = {
-      GNUNET_JSON_spec_string ("sign",
-                               &sign),
       TALER_JSON_spec_amount ("amount",
                               &td.amount),
       GNUNET_JSON_spec_absolute_time ("date",
                                       &td.execution_date),
       GNUNET_JSON_spec_uint64 ("row_id",
                                &row_id),
-      GNUNET_JSON_spec_string ("wt_subject",
-                               (const char **) &td.wire_transfer_subject),
-      GNUNET_JSON_spec_uint64 ("counterpart",
-                               &other_account),
+      GNUNET_JSON_spec_fixed_auto ("reserve_pub",
+                                   &td.reserve_pub),
+      GNUNET_JSON_spec_string ("counterpart",
+                               &td.account_url),
       GNUNET_JSON_spec_end ()
     };
     json_t *transaction = json_array_get (history_array,
@@ -121,45 +116,12 @@ parse_account_history (struct TALER_BANK_HistoryHandle 
*hh,
       GNUNET_break_op (0);
       return GNUNET_SYSERR;
     }
-
-    if (0 == strcasecmp (sign,
-                         "+"))
-      direction = TALER_BANK_DIRECTION_CREDIT;
-    else if (0 == strcasecmp (sign,
-                              "-"))
-      direction = TALER_BANK_DIRECTION_DEBIT;
-    else if (0 == strcasecmp (sign,
-                              "cancel+"))
-      direction = TALER_BANK_DIRECTION_CREDIT | TALER_BANK_DIRECTION_CANCEL;
-    else if (0 == strcasecmp (sign,
-                              "cancel-"))
-      direction = TALER_BANK_DIRECTION_DEBIT | TALER_BANK_DIRECTION_CANCEL;
-    else
-    {
-      GNUNET_break_op (0);
-      GNUNET_JSON_parse_free (hist_spec);
-      return GNUNET_SYSERR;
-    }
-    /* Note, bank_base_url has _always_ the protocol scheme
-     * and it proved to be good at this point.  */
-    bank_hostname = strchr (hh->bank_base_url, ':');
-    GNUNET_assert (NULL != bank_hostname);
-    bank_hostname += 3;
-
-    GNUNET_asprintf (&td.account_url,
-                     ('/' == bank_hostname[strlen (bank_hostname) - 1])
-                     ? "payto://x-taler-bank/%s%llu"
-                     : "payto://x-taler-bank/%s/%llu",
-                     bank_hostname,
-                     (unsigned long long) other_account);
     hh->hcb (hh->hcb_cls,
              MHD_HTTP_OK,
              TALER_EC_NONE,
-             direction,
              row_id,
              &td,
              transaction);
-    GNUNET_free (td.account_url);
     GNUNET_JSON_parse_free (hist_spec);
   }
   return GNUNET_OK;
@@ -170,7 +132,7 @@ parse_account_history (struct TALER_BANK_HistoryHandle *hh,
  * Function called when we're done processing the
  * HTTP /history request.
  *
- * @param cls the `struct TALER_BANK_HistoryHandle`
+ * @param cls the `struct TALER_BANK_CreditHistoryHandle`
  * @param response_code HTTP response code, 0 on error
  * @param response parsed JSON result, NULL on error
  */
@@ -179,7 +141,7 @@ handle_history_finished (void *cls,
                          long response_code,
                          const void *response)
 {
-  struct TALER_BANK_HistoryHandle *hh = cls;
+  struct TALER_BANK_CreditHistoryHandle *hh = cls;
   enum TALER_ErrorCode ec;
   const json_t *j = response;
 
@@ -243,120 +205,19 @@ handle_history_finished (void *cls,
   hh->hcb (hh->hcb_cls,
            response_code,
            ec,
-           TALER_BANK_DIRECTION_NONE,
            0LLU,
            NULL,
            j);
-  TALER_BANK_history_cancel (hh);
-}
-
-
-/**
- * Backend of both the /history[-range] requests.
- *
- * @param ctx curl context for the event loop
- * @param bank_base_url base URL of the bank.
- * @param urlargs path + URL arguments.
- * @param auth authentication data to use
- * @param hres_cb the callback to call with the transaction
- *        history
- * @param hres_cb_cls closure for the above callback
- * @return NULL if the inputs are invalid (i.e. zero value for
- *         @e num_results). In this case, the callback is not
- *         called.
- */
-static struct TALER_BANK_HistoryHandle *
-put_history_job (struct GNUNET_CURL_Context *ctx,
-                 const char *bank_base_url,
-                 const char *urlargs,
-                 const struct TALER_BANK_AuthenticationData *auth,
-                 TALER_BANK_HistoryResultCallback hres_cb,
-                 void *hres_cb_cls)
-{
-  struct TALER_BANK_HistoryHandle *hh;
-  CURL *eh;
-
-  hh = GNUNET_new (struct TALER_BANK_HistoryHandle);
-  hh->hcb = hres_cb;
-  hh->hcb_cls = hres_cb_cls;
-  hh->bank_base_url = GNUNET_strdup (bank_base_url);
-  hh->request_url = TALER_BANK_path_to_url_ (bank_base_url,
-                                             urlargs);
-
-  hh->authh = TALER_BANK_make_auth_header_ (auth);
-  eh = curl_easy_init ();
-  GNUNET_assert (CURLE_OK ==
-                 curl_easy_setopt (eh,
-                                   CURLOPT_URL,
-                                   hh->request_url));
-  hh->job = GNUNET_CURL_job_add2 (ctx,
-                                  eh,
-                                  hh->authh,
-                                  &handle_history_finished,
-                                  hh);
-  return hh;
+  TALER_BANK_credit_history_cancel (hh);
 }
 
 
 /**
- * Convert fixed value 'direction' into string.
- *
- * @param direction the value to convert.
- * @return string representation of @a direction.  NULL on error
- */
-static const char *
-conv_direction (enum TALER_BANK_Direction direction)
-{
-  if (TALER_BANK_DIRECTION_NONE == direction)
-  {
-    /* Should just never happen.  */
-    GNUNET_break (0);
-    return NULL;
-  }
-  if (TALER_BANK_DIRECTION_BOTH ==
-      (TALER_BANK_DIRECTION_BOTH & direction))
-    return "both";
-  else if (TALER_BANK_DIRECTION_CREDIT ==
-           (TALER_BANK_DIRECTION_CREDIT & direction))
-    return "credit";
-  else if (TALER_BANK_DIRECTION_DEBIT ==
-           (TALER_BANK_DIRECTION_BOTH & direction)) /*why use 'both' flag?*/
-    return "debit";
-  /* Should just never happen.  */
-  GNUNET_break (0);
-  return NULL;
-}
-
-
-/**
- * Convert fixed value 'direction' into string representation
- * of the "cancel" argument.
- *
- * @param direction the value to convert.
- * @return string representation of @a direction
- */
-static const char *
-conv_cancel (enum TALER_BANK_Direction direction)
-{
-  if (TALER_BANK_DIRECTION_CANCEL ==
-      (TALER_BANK_DIRECTION_CANCEL & direction))
-    return "show";
-  return "omit";
-}
-
-
-/**
- * Request the wire transfer history of a bank account.
+ * Request the credit history of the exchange's bank account.
  *
  * @param ctx curl context for the event loop
- * @param bank_base_url URL of the bank (used to execute this
- *        request)
+ * @param bank_base_url URL of the base INCLUDING account number
  * @param auth authentication data to use
- * @param account_number which account number should we query
- * @param direction what kinds of wire transfers should be
- *        returned
- * @param ascending if GNUNET_YES, history elements will
- *        be returned in chronological order.
  * @param start_row from which row on do we want to get results,
  *        use UINT64_MAX for the latest; exclusive
  * @param num_results how many results do we want;
@@ -370,20 +231,18 @@ conv_cancel (enum TALER_BANK_Direction direction)
  *         @e num_results). In this case, the callback is not
  *         called.
  */
-struct TALER_BANK_HistoryHandle *
-TALER_BANK_history (struct GNUNET_CURL_Context *ctx,
-                    const char *bank_base_url,
-                    const struct TALER_BANK_AuthenticationData *auth,
-                    uint64_t account_number,
-                    enum TALER_BANK_Direction direction,
-                    unsigned int ascending,
-                    uint64_t start_row,
-                    int64_t num_results,
-                    TALER_BANK_HistoryResultCallback hres_cb,
-                    void *hres_cb_cls)
+struct TALER_BANK_CreditHistoryHandle *
+TALER_BANK_credit_history (struct GNUNET_CURL_Context *ctx,
+                           const char *bank_base_url,
+                           const struct TALER_BANK_AuthenticationData *auth,
+                           uint64_t start_row,
+                           int64_t num_results,
+                           TALER_BANK_CreditResultCallback hres_cb,
+                           void *hres_cb_cls)
 {
-  struct TALER_BANK_HistoryHandle *hh;
   char *url;
+  struct TALER_BANK_CreditHistoryHandle *hh;
+  CURL *eh;
 
   if (0 == num_results)
   {
@@ -393,28 +252,40 @@ TALER_BANK_history (struct GNUNET_CURL_Context *ctx,
 
   if (UINT64_MAX == start_row)
     GNUNET_asprintf (&url,
-                     
"/history?auth=basic&account_number=%llu&delta=%lld&direction=%s&cancelled=%s&ordering=%s",
-                     (unsigned long long) account_number,
-                     (long long) num_results,
-                     conv_direction (direction),
-                     conv_cancel (direction),
-                     (GNUNET_YES == ascending) ? "ascending" : "descending");
+                     "/history&delta=%lld",
+                     (long long) num_results);
   else
     GNUNET_asprintf (&url,
-                     
"/history?auth=basic&account_number=%llu&delta=%lld&direction=%s&cancelled=%s&ordering=%s&start=%llu",
-                     (unsigned long long) account_number,
+                     "/history&delta=%lld&start=%llu",
                      (long long) num_results,
-                     conv_direction (direction),
-                     conv_cancel (direction),
-                     (GNUNET_YES == ascending) ? "ascending" : "descending",
                      start_row);
-  hh = put_history_job (ctx,
-                        bank_base_url,
-                        url,
-                        auth,
-                        hres_cb,
-                        hres_cb_cls);
+  hh = GNUNET_new (struct TALER_BANK_CreditHistoryHandle);
+  hh->hcb = hres_cb;
+  hh->hcb_cls = hres_cb_cls;
+  hh->bank_base_url = GNUNET_strdup (bank_base_url);
+  hh->request_url = TALER_BANK_path_to_url_ (bank_base_url,
+                                             url);
 
+  eh = curl_easy_init ();
+  if ( (GNUNET_OK !=
+        TALER_BANK_setup_auth_ (eh,
+                                auth)) ||
+       (CURLE_OK !=
+        curl_easy_setopt (eh,
+                          CURLOPT_URL,
+                          hh->request_url)) )
+  {
+    GNUNET_break (0);
+    TALER_BANK_credit_history_cancel (hh);
+    curl_easy_cleanup (eh);
+    GNUNET_free (url);
+    return NULL;
+  }
+  hh->job = GNUNET_CURL_job_add2 (ctx,
+                                  eh,
+                                  NULL,
+                                  &handle_history_finished,
+                                  hh);
   GNUNET_free (url);
   return hh;
 }
@@ -428,18 +299,17 @@ TALER_BANK_history (struct GNUNET_CURL_Context *ctx,
  * @param hh the history request handle
  */
 void
-TALER_BANK_history_cancel (struct TALER_BANK_HistoryHandle *hh)
+TALER_BANK_credit_history_cancel (struct TALER_BANK_CreditHistoryHandle *hh)
 {
   if (NULL != hh->job)
   {
     GNUNET_CURL_job_cancel (hh->job);
     hh->job = NULL;
   }
-  curl_slist_free_all (hh->authh);
   GNUNET_free (hh->request_url);
   GNUNET_free (hh->bank_base_url);
   GNUNET_free (hh);
 }
 
 
-/* end of bank_api_history.c */
+/* end of bank_api_credit.c */
diff --git a/src/bank-lib/bank_api_history.c b/src/bank-lib/bank_api_debit.c
similarity index 50%
rename from src/bank-lib/bank_api_history.c
rename to src/bank-lib/bank_api_debit.c
index f5013b85..84836243 100644
--- a/src/bank-lib/bank_api_history.c
+++ b/src/bank-lib/bank_api_debit.c
@@ -1,6 +1,6 @@
 /*
   This file is part of TALER
-  Copyright (C) 2017 GNUnet e.V. & Inria
+  Copyright (C) 2017--2020 Taler Systems SA
 
   TALER is free software; you can redistribute it and/or
   modify it under the terms of the GNU General Public License
@@ -32,7 +32,7 @@
 /**
  * @brief A /history Handle
  */
-struct TALER_BANK_HistoryHandle
+struct TALER_BANK_DebitHistoryHandle
 {
 
   /**
@@ -50,15 +50,10 @@ struct TALER_BANK_HistoryHandle
    */
   struct GNUNET_CURL_Job *job;
 
-  /**
-   * HTTP authentication-related headers for the request.
-   */
-  struct curl_slist *authh;
-
   /**
    * Function to call with the result.
    */
-  TALER_BANK_HistoryResultCallback hcb;
+  TALER_BANK_DebitResultCallback hcb;
 
   /**
    * Closure for @a cb.
@@ -77,37 +72,39 @@ struct TALER_BANK_HistoryHandle
  *         #GNUNET_SYSERR if there was a protocol violation in @a history
  */
 static int
-parse_account_history (struct TALER_BANK_HistoryHandle *hh,
+parse_account_history (struct TALER_BANK_DebitHistoryHandle *hh,
                        const json_t *history)
 {
   json_t *history_array;
-  char *bank_hostname;
 
-  if (NULL == (history_array = json_object_get (history, "data")))
+  if (NULL == (history_array = json_object_get (history,
+                                                "data")))
+  {
+    GNUNET_break_op (0);
+    return GNUNET_SYSERR;
+  }
+  if (! json_is_array (history_array))
   {
     GNUNET_break_op (0);
     return GNUNET_SYSERR;
   }
   for (unsigned int i = 0; i<json_array_size (history_array); i++)
   {
-    struct TALER_BANK_TransferDetails td;
-    const char *sign;
-    uint64_t other_account;
+    struct TALER_BANK_DebitDetails td;
     uint64_t row_id;
-    enum TALER_BANK_Direction direction;
     struct GNUNET_JSON_Specification hist_spec[] = {
-      GNUNET_JSON_spec_string ("sign",
-                               &sign),
       TALER_JSON_spec_amount ("amount",
                               &td.amount),
       GNUNET_JSON_spec_absolute_time ("date",
                                       &td.execution_date),
       GNUNET_JSON_spec_uint64 ("row_id",
                                &row_id),
-      GNUNET_JSON_spec_string ("wt_subject",
-                               (const char **) &td.wire_transfer_subject),
-      GNUNET_JSON_spec_uint64 ("counterpart",
-                               &other_account),
+      GNUNET_JSON_spec_fixed_auto ("wtid",
+                                   &td.wtid),
+      GNUNET_JSON_spec_string ("counterpart",
+                               &td.account_url),
+      GNUNET_JSON_spec_string ("exchange_base_url",
+                               &td.exchange_base_url),
       GNUNET_JSON_spec_end ()
     };
     json_t *transaction = json_array_get (history_array,
@@ -121,45 +118,12 @@ parse_account_history (struct TALER_BANK_HistoryHandle 
*hh,
       GNUNET_break_op (0);
       return GNUNET_SYSERR;
     }
-
-    if (0 == strcasecmp (sign,
-                         "+"))
-      direction = TALER_BANK_DIRECTION_CREDIT;
-    else if (0 == strcasecmp (sign,
-                              "-"))
-      direction = TALER_BANK_DIRECTION_DEBIT;
-    else if (0 == strcasecmp (sign,
-                              "cancel+"))
-      direction = TALER_BANK_DIRECTION_CREDIT | TALER_BANK_DIRECTION_CANCEL;
-    else if (0 == strcasecmp (sign,
-                              "cancel-"))
-      direction = TALER_BANK_DIRECTION_DEBIT | TALER_BANK_DIRECTION_CANCEL;
-    else
-    {
-      GNUNET_break_op (0);
-      GNUNET_JSON_parse_free (hist_spec);
-      return GNUNET_SYSERR;
-    }
-    /* Note, bank_base_url has _always_ the protocol scheme
-     * and it proved to be good at this point.  */
-    bank_hostname = strchr (hh->bank_base_url, ':');
-    GNUNET_assert (NULL != bank_hostname);
-    bank_hostname += 3;
-
-    GNUNET_asprintf (&td.account_url,
-                     ('/' == bank_hostname[strlen (bank_hostname) - 1])
-                     ? "payto://x-taler-bank/%s%llu"
-                     : "payto://x-taler-bank/%s/%llu",
-                     bank_hostname,
-                     (unsigned long long) other_account);
     hh->hcb (hh->hcb_cls,
              MHD_HTTP_OK,
              TALER_EC_NONE,
-             direction,
              row_id,
              &td,
              transaction);
-    GNUNET_free (td.account_url);
     GNUNET_JSON_parse_free (hist_spec);
   }
   return GNUNET_OK;
@@ -170,7 +134,7 @@ parse_account_history (struct TALER_BANK_HistoryHandle *hh,
  * Function called when we're done processing the
  * HTTP /history request.
  *
- * @param cls the `struct TALER_BANK_HistoryHandle`
+ * @param cls the `struct TALER_BANK_DebitHistoryHandle`
  * @param response_code HTTP response code, 0 on error
  * @param response parsed JSON result, NULL on error
  */
@@ -179,7 +143,7 @@ handle_history_finished (void *cls,
                          long response_code,
                          const void *response)
 {
-  struct TALER_BANK_HistoryHandle *hh = cls;
+  struct TALER_BANK_DebitHistoryHandle *hh = cls;
   enum TALER_ErrorCode ec;
   const json_t *j = response;
 
@@ -243,120 +207,19 @@ handle_history_finished (void *cls,
   hh->hcb (hh->hcb_cls,
            response_code,
            ec,
-           TALER_BANK_DIRECTION_NONE,
            0LLU,
            NULL,
            j);
-  TALER_BANK_history_cancel (hh);
-}
-
-
-/**
- * Backend of both the /history[-range] requests.
- *
- * @param ctx curl context for the event loop
- * @param bank_base_url base URL of the bank.
- * @param urlargs path + URL arguments.
- * @param auth authentication data to use
- * @param hres_cb the callback to call with the transaction
- *        history
- * @param hres_cb_cls closure for the above callback
- * @return NULL if the inputs are invalid (i.e. zero value for
- *         @e num_results). In this case, the callback is not
- *         called.
- */
-static struct TALER_BANK_HistoryHandle *
-put_history_job (struct GNUNET_CURL_Context *ctx,
-                 const char *bank_base_url,
-                 const char *urlargs,
-                 const struct TALER_BANK_AuthenticationData *auth,
-                 TALER_BANK_HistoryResultCallback hres_cb,
-                 void *hres_cb_cls)
-{
-  struct TALER_BANK_HistoryHandle *hh;
-  CURL *eh;
-
-  hh = GNUNET_new (struct TALER_BANK_HistoryHandle);
-  hh->hcb = hres_cb;
-  hh->hcb_cls = hres_cb_cls;
-  hh->bank_base_url = GNUNET_strdup (bank_base_url);
-  hh->request_url = TALER_BANK_path_to_url_ (bank_base_url,
-                                             urlargs);
-
-  hh->authh = TALER_BANK_make_auth_header_ (auth);
-  eh = curl_easy_init ();
-  GNUNET_assert (CURLE_OK ==
-                 curl_easy_setopt (eh,
-                                   CURLOPT_URL,
-                                   hh->request_url));
-  hh->job = GNUNET_CURL_job_add2 (ctx,
-                                  eh,
-                                  hh->authh,
-                                  &handle_history_finished,
-                                  hh);
-  return hh;
+  TALER_BANK_debit_history_cancel (hh);
 }
 
 
 /**
- * Convert fixed value 'direction' into string.
- *
- * @param direction the value to convert.
- * @return string representation of @a direction.  NULL on error
- */
-static const char *
-conv_direction (enum TALER_BANK_Direction direction)
-{
-  if (TALER_BANK_DIRECTION_NONE == direction)
-  {
-    /* Should just never happen.  */
-    GNUNET_break (0);
-    return NULL;
-  }
-  if (TALER_BANK_DIRECTION_BOTH ==
-      (TALER_BANK_DIRECTION_BOTH & direction))
-    return "both";
-  else if (TALER_BANK_DIRECTION_CREDIT ==
-           (TALER_BANK_DIRECTION_CREDIT & direction))
-    return "credit";
-  else if (TALER_BANK_DIRECTION_DEBIT ==
-           (TALER_BANK_DIRECTION_BOTH & direction)) /*why use 'both' flag?*/
-    return "debit";
-  /* Should just never happen.  */
-  GNUNET_break (0);
-  return NULL;
-}
-
-
-/**
- * Convert fixed value 'direction' into string representation
- * of the "cancel" argument.
- *
- * @param direction the value to convert.
- * @return string representation of @a direction
- */
-static const char *
-conv_cancel (enum TALER_BANK_Direction direction)
-{
-  if (TALER_BANK_DIRECTION_CANCEL ==
-      (TALER_BANK_DIRECTION_CANCEL & direction))
-    return "show";
-  return "omit";
-}
-
-
-/**
- * Request the wire transfer history of a bank account.
+ * Request the debit history of the exchange's bank account.
  *
  * @param ctx curl context for the event loop
- * @param bank_base_url URL of the bank (used to execute this
- *        request)
+ * @param bank_base_url URL of the base INCLUDING account number
  * @param auth authentication data to use
- * @param account_number which account number should we query
- * @param direction what kinds of wire transfers should be
- *        returned
- * @param ascending if GNUNET_YES, history elements will
- *        be returned in chronological order.
  * @param start_row from which row on do we want to get results,
  *        use UINT64_MAX for the latest; exclusive
  * @param num_results how many results do we want;
@@ -370,20 +233,18 @@ conv_cancel (enum TALER_BANK_Direction direction)
  *         @e num_results). In this case, the callback is not
  *         called.
  */
-struct TALER_BANK_HistoryHandle *
-TALER_BANK_history (struct GNUNET_CURL_Context *ctx,
-                    const char *bank_base_url,
-                    const struct TALER_BANK_AuthenticationData *auth,
-                    uint64_t account_number,
-                    enum TALER_BANK_Direction direction,
-                    unsigned int ascending,
-                    uint64_t start_row,
-                    int64_t num_results,
-                    TALER_BANK_HistoryResultCallback hres_cb,
-                    void *hres_cb_cls)
+struct TALER_BANK_DebitHistoryHandle *
+TALER_BANK_debit_history (struct GNUNET_CURL_Context *ctx,
+                          const char *bank_base_url,
+                          const struct TALER_BANK_AuthenticationData *auth,
+                          uint64_t start_row,
+                          int64_t num_results,
+                          TALER_BANK_DebitResultCallback hres_cb,
+                          void *hres_cb_cls)
 {
-  struct TALER_BANK_HistoryHandle *hh;
   char *url;
+  struct TALER_BANK_DebitHistoryHandle *hh;
+  CURL *eh;
 
   if (0 == num_results)
   {
@@ -393,28 +254,40 @@ TALER_BANK_history (struct GNUNET_CURL_Context *ctx,
 
   if (UINT64_MAX == start_row)
     GNUNET_asprintf (&url,
-                     
"/history?auth=basic&account_number=%llu&delta=%lld&direction=%s&cancelled=%s&ordering=%s",
-                     (unsigned long long) account_number,
-                     (long long) num_results,
-                     conv_direction (direction),
-                     conv_cancel (direction),
-                     (GNUNET_YES == ascending) ? "ascending" : "descending");
+                     "/history&delta=%lld",
+                     (long long) num_results);
   else
     GNUNET_asprintf (&url,
-                     
"/history?auth=basic&account_number=%llu&delta=%lld&direction=%s&cancelled=%s&ordering=%s&start=%llu",
-                     (unsigned long long) account_number,
+                     "/history&delta=%lld&start=%llu",
                      (long long) num_results,
-                     conv_direction (direction),
-                     conv_cancel (direction),
-                     (GNUNET_YES == ascending) ? "ascending" : "descending",
                      start_row);
-  hh = put_history_job (ctx,
-                        bank_base_url,
-                        url,
-                        auth,
-                        hres_cb,
-                        hres_cb_cls);
+  hh = GNUNET_new (struct TALER_BANK_DebitHistoryHandle);
+  hh->hcb = hres_cb;
+  hh->hcb_cls = hres_cb_cls;
+  hh->bank_base_url = GNUNET_strdup (bank_base_url);
+  hh->request_url = TALER_BANK_path_to_url_ (bank_base_url,
+                                             url);
 
+  eh = curl_easy_init ();
+  if ( (GNUNET_OK !=
+        TALER_BANK_setup_auth_ (eh,
+                                auth)) ||
+       (CURLE_OK !=
+        curl_easy_setopt (eh,
+                          CURLOPT_URL,
+                          hh->request_url)) )
+  {
+    GNUNET_break (0);
+    TALER_BANK_debit_history_cancel (hh);
+    curl_easy_cleanup (eh);
+    GNUNET_free (url);
+    return NULL;
+  }
+  hh->job = GNUNET_CURL_job_add2 (ctx,
+                                  eh,
+                                  NULL,
+                                  &handle_history_finished,
+                                  hh);
   GNUNET_free (url);
   return hh;
 }
@@ -428,18 +301,17 @@ TALER_BANK_history (struct GNUNET_CURL_Context *ctx,
  * @param hh the history request handle
  */
 void
-TALER_BANK_history_cancel (struct TALER_BANK_HistoryHandle *hh)
+TALER_BANK_debit_history_cancel (struct TALER_BANK_DebitHistoryHandle *hh)
 {
   if (NULL != hh->job)
   {
     GNUNET_CURL_job_cancel (hh->job);
     hh->job = NULL;
   }
-  curl_slist_free_all (hh->authh);
   GNUNET_free (hh->request_url);
   GNUNET_free (hh->bank_base_url);
   GNUNET_free (hh);
 }
 
 
-/* end of bank_api_history.c */
+/* end of bank_api_debit.c */
diff --git a/src/bank-lib/bank_api_parse.c b/src/bank-lib/bank_api_parse.c
index 582e2a7d..86288802 100644
--- a/src/bank-lib/bank_api_parse.c
+++ b/src/bank-lib/bank_api_parse.c
@@ -1,6 +1,6 @@
 /*
   This file is part of TALER
-  Copyright (C) 2018 Taler Systems SA
+  Copyright (C) 2018-2020 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
@@ -23,6 +23,58 @@
 #include "taler_bank_service.h"
 
 
+/**
+ * Convenience method for parsing configuration section with bank account data.
+ *
+ * @param cfg configuration to parse
+ * @param section the section with the configuration data
+ * @param acc[out] set to the account details
+ * @return #GNUNET_OK on success
+ */
+int
+TALER_BANK_account_parse_cfg (const struct GNUNET_CONFIGURATION_Handle *cfg,
+                              const char *section,
+                              struct TALER_Account *acc)
+{
+  char *account_url;
+
+  if (GNUNET_OK !=
+      GNUNET_CONFIGURATION_get_value_string (cfg,
+                                             section,
+                                             "URL",
+                                             &account_url))
+  {
+    GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
+                               section,
+                               "URL");
+    return GNUNET_SYSERR;
+  }
+  if (TALER_EC_NONE !=
+      TALER_WIRE_payto_to_account (account_url,
+                                   acc))
+  {
+    GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR,
+                               section,
+                               "URL",
+                               "Malformed payto:// URL for x-taler-bank 
method");
+    GNUNET_free (account_url);
+    return GNUNET_SYSERR;
+  }
+  if (TALER_PAC_X_TALER_BANK != acc->type)
+  {
+    GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR,
+                               section,
+                               "URL",
+                               "Malformed payto:// URL for x-taler-bank 
method");
+    GNUNET_free (account_url);
+    TALER_WIRE_account_free (acc);
+    return GNUNET_SYSERR;
+  }
+  GNUNET_free (account_url);
+  return GNUNET_OK;
+}
+
+
 /**
  * Parse configuration section with bank authentication data.
  *
diff --git a/src/bank-lib/bank_api_reject.c b/src/bank-lib/bank_api_reject.c
deleted file mode 100644
index 3f181bc3..00000000
--- a/src/bank-lib/bank_api_reject.c
+++ /dev/null
@@ -1,242 +0,0 @@
-/*
-  This file is part of TALER
-  Copyright (C) 2015, 2016, 2017 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 bank-lib/bank_api_reject.c
- * @brief Implementation of the /reject request of the bank's HTTP API
- * @author Christian Grothoff
- */
-#include "platform.h"
-#include "bank_api_common.h"
-#include <microhttpd.h> /* just for HTTP status codes */
-#include "taler_signatures.h"
-
-
-/**
- * @brief A /reject Handle
- */
-struct TALER_BANK_RejectHandle
-{
-
-  /**
-   * The url for this request.
-   */
-  char *request_url;
-
-  /**
-   * JSON encoding of the request to POST.
-   */
-  char *json_enc;
-
-  /**
-   * Handle for the request.
-   */
-  struct GNUNET_CURL_Job *job;
-
-  /**
-   * HTTP authentication-related headers for the request.
-   */
-  struct curl_slist *authh;
-
-  /**
-   * Function to call with the result.
-   */
-  TALER_BANK_RejectResultCallback cb;
-
-  /**
-   * Closure for @a cb.
-   */
-  void *cb_cls;
-
-};
-
-
-/**
- * Function called when we're done processing the
- * HTTP /reject request.
- *
- * @param cls the `struct TALER_BANK_RejectHandle`
- * @param response_code HTTP response code, 0 on error
- * @param response parsed JSON result, NULL on error
- */
-static void
-handle_reject_finished (void *cls,
-                        long response_code,
-                        const void *response)
-{
-  struct TALER_BANK_RejectHandle *rh = cls;
-  enum TALER_ErrorCode ec;
-  const json_t *j = response;
-
-  rh->job = NULL;
-  switch (response_code)
-  {
-  case 0:
-    ec = TALER_EC_INVALID_RESPONSE;
-    break;
-  case MHD_HTTP_OK:
-    GNUNET_break_op (0);
-    response_code = 0;
-    ec = TALER_EC_INVALID_RESPONSE;
-    break;
-  case MHD_HTTP_NO_CONTENT:
-    ec = TALER_EC_NONE;
-    break;
-  case MHD_HTTP_BAD_REQUEST:
-    /* This should never happen, either us or the bank is buggy
-       (or API version conflict); just pass JSON reply to the application */
-    ec = TALER_BANK_parse_ec_ (j);
-    break;
-  case MHD_HTTP_FORBIDDEN:
-    /* Access denied */
-    ec = TALER_BANK_parse_ec_ (j);
-    break;
-  case MHD_HTTP_UNAUTHORIZED:
-    /* Nothing really to verify, bank says one of the signatures is
-       invalid; as we checked them, this should never happen, we
-       should pass the JSON reply to the application */
-    ec = TALER_BANK_parse_ec_ (j);
-    break;
-  case MHD_HTTP_NOT_FOUND:
-    /* Nothing really to verify, this should never
-       happen, we should pass the JSON reply to the application */
-    ec = TALER_BANK_parse_ec_ (j);
-    break;
-  case MHD_HTTP_INTERNAL_SERVER_ERROR:
-    /* Server had an internal issue; we should retry, but this API
-       leaves this to the application */
-    ec = TALER_BANK_parse_ec_ (j);
-    break;
-  default:
-    /* unexpected response code */
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                "Unexpected response code %u\n",
-                (unsigned int) response_code);
-    GNUNET_break (0);
-    ec = TALER_BANK_parse_ec_ (j);
-    response_code = 0;
-    break;
-  }
-  rh->cb (rh->cb_cls,
-          response_code,
-          ec);
-  TALER_BANK_reject_cancel (rh);
-}
-
-
-/**
- * Request rejection of a wire transfer, marking it as cancelled and voiding
- * its effects.
- *
- * @param ctx curl context for the event loop
- * @param bank_base_url URL of the bank (used to execute this request)
- * @param auth authentication data to use
- * @param account_number which account number should we query
- * @param rowid transfer to reject
- * @param rcb the callback to call with the operation result
- * @param rcb_cls closure for @a rcb
- * @return NULL
- *         if the inputs are invalid.
- *         In this case, the callback is not called.
- */
-struct TALER_BANK_RejectHandle *
-TALER_BANK_reject (struct GNUNET_CURL_Context *ctx,
-                   const char *bank_base_url,
-                   const struct TALER_BANK_AuthenticationData *auth,
-                   uint64_t account_number,
-                   uint64_t rowid,
-                   TALER_BANK_RejectResultCallback rcb,
-                   void *rcb_cls)
-{
-  struct TALER_BANK_RejectHandle *rh;
-  json_t *reject_obj;
-  CURL *eh;
-
-  reject_obj = json_pack ("{s:{s:s}, s:I, s:I}",
-                          "auth", "type", "basic",
-                          "row_id", (json_int_t) rowid,
-                          "account_number", (json_int_t) account_number);
-  if (NULL == reject_obj)
-  {
-    GNUNET_break (0);
-    return NULL;
-  }
-  rh = GNUNET_new (struct TALER_BANK_RejectHandle);
-  rh->cb = rcb;
-  rh->cb_cls = rcb_cls;
-  rh->request_url = TALER_BANK_path_to_url_ (bank_base_url,
-                                             "/reject");
-  rh->authh = TALER_BANK_make_auth_header_ (auth);
-  /* Append content type header here, can't do it in GNUNET_CURL_job_add
-     as that would override the CURLOPT_HTTPHEADER instead of appending. */
-  {
-    struct curl_slist *ext;
-
-    ext = curl_slist_append (rh->authh,
-                             "Content-Type: application/json");
-    if (NULL == ext)
-      GNUNET_break (0);
-    else
-      rh->authh = ext;
-  }
-  eh = curl_easy_init ();
-  GNUNET_assert (NULL != (rh->json_enc =
-                            json_dumps (reject_obj,
-                                        JSON_COMPACT)));
-  json_decref (reject_obj);
-  GNUNET_assert (CURLE_OK ==
-                 curl_easy_setopt (eh,
-                                   CURLOPT_URL,
-                                   rh->request_url));
-  GNUNET_assert (CURLE_OK ==
-                 curl_easy_setopt (eh,
-                                   CURLOPT_POSTFIELDS,
-                                   rh->json_enc));
-  GNUNET_assert (CURLE_OK ==
-                 curl_easy_setopt (eh,
-                                   CURLOPT_POSTFIELDSIZE,
-                                   strlen (rh->json_enc)));
-  rh->job = GNUNET_CURL_job_add2 (ctx,
-                                  eh,
-                                  rh->authh,
-                                  &handle_reject_finished,
-                                  rh);
-  return rh;
-}
-
-
-/**
- * Cancel an reject request.  This function cannot be used on a request
- * handle if the response was is already served for it.
- *
- * @param rh the reject request handle
- */
-void
-TALER_BANK_reject_cancel (struct TALER_BANK_RejectHandle *rh)
-{
-  if (NULL != rh->job)
-  {
-    GNUNET_CURL_job_cancel (rh->job);
-    rh->job = NULL;
-  }
-  curl_slist_free_all (rh->authh);
-  GNUNET_free (rh->request_url);
-  GNUNET_free (rh->json_enc);
-  GNUNET_free (rh);
-}
-
-
-/* end of bank_api_reject.c */
diff --git a/src/bank-lib/bank_api_transaction.c 
b/src/bank-lib/bank_api_transaction.c
new file mode 100644
index 00000000..17732848
--- /dev/null
+++ b/src/bank-lib/bank_api_transaction.c
@@ -0,0 +1,368 @@
+/*
+  This file is part of TALER
+  Copyright (C) 2015--2020 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 bank-lib/bank_api_transaction.c
+ * @brief Implementation of the /transaction/ requests of the bank's HTTP API
+ * @author Christian Grothoff
+ */
+#include "platform.h"
+#include "bank_api_common.h"
+#include <microhttpd.h> /* just for HTTP status codes */
+#include "taler_signatures.h"
+#include "taler_curl_lib.h"
+#include "taler_bank_service.h"
+
+
+GNUNET_NETWORK_STRUCT_BEGIN
+
+/**
+ * Data structure serialized in the prepare stage.
+ */
+struct WirePackP
+{
+  /**
+   * Random unique identifier for the request.
+   */
+  struct GNUNET_HashCode request_uid;
+
+  /**
+   * Amount to be transferred.
+   */
+  struct TALER_AmountNBO amount;
+
+  /**
+   * Wire transfer identifier to use.
+   */
+  struct TALER_WireTransferIdentifierRawP wtid;
+
+  /**
+   * Length of the payto:// URL of the target account,
+   * including 0-terminator, in network byte order.
+   */
+  uint32_t account_len GNUNET_PACKED;
+
+  /**
+   * Length of the exchange's base URL,
+   * including 0-terminator, in network byte order.
+   */
+  uint32_t exchange_url_len GNUNET_PACKED;
+
+};
+
+GNUNET_NETWORK_STRUCT_END
+
+/**
+ * Prepare for exeuction of a wire transfer.
+ *
+ * @param destination_account_url payto:// URL identifying where to send the 
money
+ * @param amount amount to transfer, already rounded
+ * @param exchange_base_url base URL of this exchange (included in subject
+ *        to facilitate use of tracking API by merchant backend)
+ * @param wtid wire transfer identifier to use
+ * @param buf[out] set to transaction data to persist, NULL on error
+ * @param buf_size[out] set to number of bytes in @a buf, 0 on error
+ */
+void
+TALER_BANK_prepare_wire_transfer (const char *destination_account_url,
+                                  const struct TALER_Amount *amount,
+                                  const char *exchange_base_url,
+                                  const struct
+                                  TALER_WireTransferIdentifierRawP *wtid,
+                                  void **buf,
+                                  size_t *buf_size)
+{
+  struct WirePackP *wp;
+  size_t d_len = strlen (destination_account_url) + 1;
+  size_t u_len = strlen (exchange_base_url) + 1;
+  char *end;
+
+  *buf_size = sizeof (*wp) + d_len + u_len;
+  wp = GNUNET_malloc (*buf_size);
+  GNUNET_CRYPTO_hash_create_random (GNUNET_CRYPTO_QUALITY_NONCE,
+                                    &wp->request_uid);
+  TALER_amount_hton (&wp->amount,
+                     amount);
+  wp->wtid = *wtid;
+  wp->account_len = htonl ((uint32_t) d_len);
+  wp->exchange_url_len = htonl ((uint32_t) u_len);
+  end = (char *) &wp[1];
+  memcpy (end,
+          destination_account_url,
+          d_len);
+  memcpy (end + d_len,
+          exchange_base_url,
+          u_len);
+  *buf = (char *) wp;
+}
+
+
+/**
+ * @brief An transaction Handle
+ */
+struct TALER_BANK_WireExecuteHandle
+{
+
+  /**
+   * The url for this request.
+   */
+  char *request_url;
+
+  /**
+   * POST context.
+   */
+  struct TEAH_PostContext post_ctx;
+
+  /**
+   * Handle for the request.
+   */
+  struct GNUNET_CURL_Job *job;
+
+  /**
+   * Function to call with the result.
+   */
+  TALER_BANK_ConfirmationCallback cb;
+
+  /**
+   * Closure for @a cb.
+   */
+  void *cb_cls;
+
+};
+
+
+/**
+ * Function called when we're done processing the
+ * HTTP /transaction request.
+ *
+ * @param cls the `struct TALER_BANK_WireExecuteHandle`
+ * @param response_code HTTP response code, 0 on error
+ * @param response parsed JSON result, NULL on error
+ */
+static void
+handle_transaction_finished (void *cls,
+                             long response_code,
+                             const void *response)
+{
+  struct TALER_BANK_WireExecuteHandle *weh = cls;
+  uint64_t row_id = UINT64_MAX;
+  struct GNUNET_TIME_Absolute timestamp;
+  enum TALER_ErrorCode ec;
+  const json_t *j = response;
+
+  weh->job = NULL;
+  timestamp = GNUNET_TIME_UNIT_FOREVER_ABS;
+  switch (response_code)
+  {
+  case 0:
+    ec = TALER_EC_INVALID_RESPONSE;
+    break;
+  case MHD_HTTP_OK:
+    {
+      struct GNUNET_JSON_Specification spec[] = {
+        GNUNET_JSON_spec_uint64 ("row_id",
+                                 &row_id),
+        GNUNET_JSON_spec_absolute_time ("timestamp",
+                                        &timestamp),
+        GNUNET_JSON_spec_end ()
+      };
+
+      if (GNUNET_OK !=
+          GNUNET_JSON_parse (j,
+                             spec,
+                             NULL, NULL))
+      {
+        GNUNET_break_op (0);
+        response_code = 0;
+        ec = TALER_EC_INVALID_RESPONSE;
+        break;
+      }
+      ec = TALER_EC_NONE;
+    }
+    break;
+  case MHD_HTTP_BAD_REQUEST:
+    /* This should never happen, either us or the bank is buggy
+       (or API version conflict); just pass JSON reply to the application */
+    ec = TALER_BANK_parse_ec_ (j);
+    break;
+  case MHD_HTTP_FORBIDDEN:
+    /* Access denied */
+    ec = TALER_BANK_parse_ec_ (j);
+    break;
+  case MHD_HTTP_UNAUTHORIZED:
+    /* Nothing really to verify, bank says one of the signatures is
+       invalid; as we checked them, this should never happen, we
+       should pass the JSON reply to the application */
+    ec = TALER_BANK_parse_ec_ (j);
+    break;
+  case MHD_HTTP_NOT_FOUND:
+    /* Nothing really to verify, this should never
+       happen, we should pass the JSON reply to the application */
+    ec = TALER_BANK_parse_ec_ (j);
+    break;
+  case MHD_HTTP_NOT_ACCEPTABLE:
+    /* Nothing really to verify, this should never
+       happen, we should pass the JSON reply to the application */
+    ec = TALER_BANK_parse_ec_ (j);
+    break;
+  case MHD_HTTP_INTERNAL_SERVER_ERROR:
+    /* Server had an internal issue; we should retry, but this API
+       leaves this to the application */
+    ec = TALER_BANK_parse_ec_ (j);
+    break;
+  default:
+    /* unexpected response code */
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                "Unexpected response code %u\n",
+                (unsigned int) response_code);
+    GNUNET_break (0);
+    ec = TALER_BANK_parse_ec_ (j);
+    response_code = 0;
+    break;
+  }
+  weh->cb (weh->cb_cls,
+           response_code,
+           ec,
+           row_id,
+           timestamp);
+  TALER_BANK_execute_wire_transfer_cancel (weh);
+}
+
+
+/**
+ * Execute a wire transfer.
+ *
+ * @param cls the @e cls of this struct with the plugin-specific state
+ * @param buf buffer with the prepared execution details
+ * @param buf_size number of bytes in @a buf
+ * @param cc function to call upon success
+ * @param cc_cls closure for @a cc
+ * @return NULL on error
+ */
+struct TALER_BANK_WireExecuteHandle *
+TALER_BANK_execute_wire_transfer (struct GNUNET_CURL_Context *ctx,
+                                  const char *bank_base_url,
+                                  const struct
+                                  TALER_BANK_AuthenticationData *auth,
+                                  const void *buf,
+                                  size_t buf_size,
+                                  TALER_BANK_ConfirmationCallback cc,
+                                  void *cc_cls)
+{
+  struct TALER_BANK_WireExecuteHandle *weh;
+  json_t *transaction_obj;
+  CURL *eh;
+  const struct WirePackP *wp = buf;
+  uint32_t d_len;
+  uint32_t u_len;
+  const char *destination_account_url;
+  const char *exchange_base_url;
+  struct TALER_Amount amount;
+
+  if (sizeof (*wp) > buf_size)
+  {
+    GNUNET_break (0);
+    return NULL;
+  }
+  d_len = ntohl (wp->account_len);
+  u_len = ntohl (wp->exchange_url_len);
+  if (sizeof (*wp) + d_len + u_len != buf_size)
+  {
+    GNUNET_break (0);
+    return NULL;
+  }
+  destination_account_url = (const char *) &wp[1];
+  exchange_base_url = destination_account_url + d_len;
+  if (NULL == bank_base_url)
+  {
+    GNUNET_break (0);
+    return NULL;
+  }
+  TALER_amount_ntoh (&amount,
+                     &wp->amount);
+  transaction_obj = json_pack ("{s:o, s:o, s:s, s:o, s:o, s:s}",
+                               "request_uid", GNUNET_JSON_from_data_auto (
+                                 &wp->request_uid),
+                               "amount", TALER_JSON_from_amount (&amount),
+                               "exchange_url", exchange_base_url,
+                               "wtid", GNUNET_JSON_from_data_auto (&wp->wtid),
+                               "credit_account", destination_account_url);
+  if (NULL == transaction_obj)
+  {
+    GNUNET_break (0);
+    return NULL;
+  }
+  weh = GNUNET_new (struct TALER_BANK_WireExecuteHandle);
+  weh->cb = cc;
+  weh->cb_cls = cc_cls;
+  weh->request_url = TALER_BANK_path_to_url_ (bank_base_url,
+                                              "/transaction");
+  weh->post_ctx.headers = curl_slist_append
+                            (weh->post_ctx.headers,
+                            "Content-Type: application/json");
+
+  eh = curl_easy_init ();
+  if ( (GNUNET_OK !=
+        TALER_BANK_setup_auth_ (eh,
+                                auth)) ||
+       (CURLE_OK !=
+        curl_easy_setopt (eh,
+                          CURLOPT_URL,
+                          weh->request_url)) ||
+       (GNUNET_OK !=
+        TALER_curl_easy_post (&weh->post_ctx,
+                              eh,
+                              transaction_obj)) )
+  {
+    GNUNET_break (0);
+    TALER_BANK_execute_wire_transfer_cancel (weh);
+    curl_easy_cleanup (eh);
+    json_decref (transaction_obj);
+    return NULL;
+  }
+  json_decref (transaction_obj);
+
+  weh->job = GNUNET_CURL_job_add2 (ctx,
+                                   eh,
+                                   weh->post_ctx.headers,
+                                   &handle_transaction_finished,
+                                   weh);
+  return weh;
+}
+
+
+/**
+ * Cancel a wire transfer.  This function cannot be used on a request handle
+ * if a response is already served for it.
+ *
+ * @param weh the wire transfer request handle
+ */
+void
+TALER_BANK_execute_wire_transfer_cancel (struct
+                                         TALER_BANK_WireExecuteHandle *weh)
+{
+  if (NULL != weh->job)
+  {
+    GNUNET_CURL_job_cancel (weh->job);
+    weh->job = NULL;
+  }
+  TALER_curl_easy_post_finished (&weh->post_ctx);
+  GNUNET_free (weh->request_url);
+  GNUNET_free (weh);
+}
+
+
+/* end of bank_api_transaction.c */
diff --git a/src/bank-lib/fakebank.c b/src/bank-lib/fakebank.c
index d8ea392b..1706ca8f 100644
--- a/src/bank-lib/fakebank.c
+++ b/src/bank-lib/fakebank.c
@@ -1,6 +1,6 @@
 /*
   This file is part of TALER
-  (C) 2016, 2017, 2018 Inria and GNUnet e.V.
+  (C) 2016-2020 Taler Systems SA
 
   TALER is free software; you can redistribute it and/or
   modify it under the terms of the GNU General Public License
@@ -25,7 +25,7 @@
 #include "platform.h"
 #include "taler_fakebank_lib.h"
 #include "taler_bank_service.h"
-#include "fakebank.h"
+#include "taler_mhd_lib.h"
 
 /**
  * Maximum POST request size (for /admin/add/incoming)
@@ -33,6 +33,65 @@
 #define REQUEST_BUFFER_MAX (4 * 1024)
 
 
+/**
+ * Details about a transcation we (as the simulated bank) received.
+ */
+struct Transaction
+{
+  /**
+   * We store transactions in a DLL.
+   */
+  struct Transaction *next;
+
+  /**
+   * We store transactions in a DLL.
+   */
+  struct Transaction *prev;
+
+  /**
+   * Amount to be transferred.
+   */
+  struct TALER_Amount amount;
+
+  /**
+   * Account to debit.
+   */
+  char *debit_account;
+
+  /**
+   * Account to credit.
+   */
+  char *credit_account;
+
+  /**
+   * Subject of the transfer.
+   */
+  char *subject;
+
+  /**
+   * Base URL of the exchange.
+   */
+  char *exchange_base_url;
+
+  /**
+   * When did the transaction happen?
+   */
+  struct GNUNET_TIME_Absolute date;
+
+  /**
+   * Number of this transaction.
+   */
+  uint64_t row_id;
+
+  /**
+   * Has this transaction been subjected to #TALER_FAKEBANK_check()
+   * and should thus no longer be counted in
+   * #TALER_FAKEBANK_check_empty()?
+   */
+  int checked;
+};
+
+
 /**
  * Handle for the fake bank.
  */
@@ -63,6 +122,11 @@ struct TALER_FAKEBANK_Handle
    */
   uint64_t serial_counter;
 
+  /**
+   * Our port number.
+   */
+  uint16_t port;
+
 #if EPOLL_SUPPORT
   /**
    * Boxed @e mhd_fd.
@@ -95,8 +159,8 @@ struct TALER_FAKEBANK_Handle
 int
 TALER_FAKEBANK_check (struct TALER_FAKEBANK_Handle *h,
                       const struct TALER_Amount *want_amount,
-                      uint64_t want_debit,
-                      uint64_t want_credit,
+                      const char *want_debit,
+                      const char *want_credit,
                       const char *exchange_base_url,
                       char **subject)
 {
@@ -151,8 +215,8 @@ TALER_FAKEBANK_check (struct TALER_FAKEBANK_Handle *h,
  */
 uint64_t
 TALER_FAKEBANK_make_transfer (struct TALER_FAKEBANK_Handle *h,
-                              uint64_t debit_account,
-                              uint64_t credit_account,
+                              const char *debit_account,
+                              const char *credit_account,
                               const struct TALER_Amount *amount,
                               const char *subject,
                               const char *exchange_base_url)
@@ -160,15 +224,15 @@ TALER_FAKEBANK_make_transfer (struct 
TALER_FAKEBANK_Handle *h,
   struct Transaction *t;
 
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "Making transfer from %llu to %llu over %s and subject %s; for 
exchange: %s\n",
-              (unsigned long long) debit_account,
-              (unsigned long long) credit_account,
+              "Making transfer from %s to %s over %s and subject %s; for 
exchange: %s\n",
+              debit_account,
+              credit_account,
               TALER_amount2s (amount),
               subject,
               exchange_base_url);
   t = GNUNET_new (struct Transaction);
-  t->debit_account = debit_account;
-  t->credit_account = credit_account;
+  t->debit_account = GNUNET_strdup (debit_account);
+  t->credit_account = GNUNET_strdup (credit_account);
   t->amount = *amount;
   t->exchange_base_url = GNUNET_strdup (exchange_base_url);
   t->row_id = ++h->serial_counter;
@@ -182,31 +246,6 @@ TALER_FAKEBANK_make_transfer (struct TALER_FAKEBANK_Handle 
*h,
 }
 
 
-/**
- * Reject incoming wire transfer to account @a credit_account
- * as identified by @a rowid.
- *
- * @param h fake bank handle
- * @param rowid identifies transfer to reject
- * @param credit_account account number of owner of credited account
- * @return #GNUNET_YES on success, #GNUNET_NO if the wire transfer was not 
found
- */
-int
-TALER_FAKEBANK_reject_transfer (struct TALER_FAKEBANK_Handle *h,
-                                uint64_t rowid,
-                                uint64_t credit_account)
-{
-  for (struct Transaction *t = h->transactions_head; NULL != t; t = t->next)
-    if ( (t->row_id == rowid) &&
-         (t->credit_account == credit_account) )
-    {
-      t->rejected = GNUNET_YES;
-      return GNUNET_YES;
-    }
-  return GNUNET_NO;
-}
-
-
 /**
  * Check that no wire transfers were ordered (or at least none
  * that have not been taken care of via #TALER_FAKEBANK_check()).
@@ -223,8 +262,7 @@ TALER_FAKEBANK_check_empty (struct TALER_FAKEBANK_Handle *h)
   t = h->transactions_head;
   while (NULL != t)
   {
-    if ( (GNUNET_YES != t->checked) &&
-         (GNUNET_YES != t->rejected) )
+    if (GNUNET_YES != t->checked)
       break;
     t = t->next;
   }
@@ -234,16 +272,15 @@ TALER_FAKEBANK_check_empty (struct TALER_FAKEBANK_Handle 
*h)
            "Expected empty transaction set, but I have:\n");
   while (NULL != t)
   {
-    if ( (GNUNET_YES != t->checked) &&
-         (GNUNET_YES != t->rejected) )
+    if (GNUNET_YES != t->checked)
     {
       char *s;
 
       s = TALER_amount_to_string (&t->amount);
       fprintf (stderr,
-               "%llu -> %llu (%s) from %s\n",
-               (unsigned long long) t->debit_account,
-               (unsigned long long) t->credit_account,
+               "%s -> %s (%s) from %s\n",
+               t->debit_account,
+               t->credit_account,
                s,
                t->exchange_base_url);
       GNUNET_free (s);
@@ -270,6 +307,8 @@ TALER_FAKEBANK_stop (struct TALER_FAKEBANK_Handle *h)
                                  h->transactions_tail,
                                  t);
     GNUNET_free (t->subject);
+    GNUNET_free (t->debit_account);
+    GNUNET_free (t->credit_account);
     GNUNET_free (t->exchange_base_url);
     GNUNET_free (t);
   }
@@ -290,62 +329,6 @@ TALER_FAKEBANK_stop (struct TALER_FAKEBANK_Handle *h)
 }
 
 
-/**
- * Create and queue a bank error message with the HTTP response
- * code @a response_code on connection @a connection.
- *
- * @param connection where to queue the reply
- * @param response_code http status code to use
- * @param ec taler error code to use
- * @param message human readable error message
- * @return MHD status code
- */
-static int
-create_bank_error (struct MHD_Connection *connection,
-                   unsigned int response_code,
-                   enum TALER_ErrorCode ec,
-                   const char *message)
-{
-  json_t *json;
-  struct MHD_Response *resp;
-  void *json_str;
-  size_t json_len;
-  int ret;
-
-  json = json_pack ("{s:s, s:I}",
-                    "error",
-                    message,
-                    "ec",
-                    (json_int_t) ec);
-  json_str = json_dumps (json,
-                         JSON_INDENT (2));
-  json_decref (json);
-  if (NULL == json_str)
-  {
-    GNUNET_break (0);
-    return MHD_NO;
-  }
-  json_len = strlen (json_str);
-  resp = MHD_create_response_from_buffer (json_len,
-                                          json_str,
-                                          MHD_RESPMEM_MUST_FREE);
-  if (NULL == resp)
-  {
-    GNUNET_break (0);
-    free (json_str);
-    return MHD_NO;
-  }
-  (void) MHD_add_response_header (resp,
-                                  MHD_HTTP_HEADER_CONTENT_TYPE,
-                                  "application/json");
-  ret = MHD_queue_response (connection,
-                            response_code,
-                            resp);
-  MHD_destroy_response (resp);
-  return ret;
-}
-
-
 /**
  * Function called whenever MHD is done with a request.  If the
  * request was a POST, we may have stored a `struct Buffer *` in the
@@ -394,8 +377,6 @@ handle_admin_add_incoming (struct TALER_FAKEBANK_Handle *h,
 {
   enum GNUNET_JSON_PostResult pr;
   json_t *json;
-  struct MHD_Response *resp;
-  int ret;
   uint64_t row_id;
 
   pr = GNUNET_JSON_post_parser (REQUEST_BUFFER_MAX,
@@ -422,15 +403,14 @@ handle_admin_add_incoming (struct TALER_FAKEBANK_Handle 
*h,
   }
   {
     const char *subject;
-    uint64_t debit_account;
-    uint64_t credit_account;
+    const char *debit_account;
+    const char *credit_account;
     const char *base_url;
     struct TALER_Amount amount;
-    char *amount_s;
     struct GNUNET_JSON_Specification spec[] = {
       GNUNET_JSON_spec_string ("subject", &subject),
-      GNUNET_JSON_spec_uint64 ("debit_account", &debit_account),
-      GNUNET_JSON_spec_uint64 ("credit_account", &credit_account),
+      GNUNET_JSON_spec_string ("debit_account", &debit_account),
+      GNUNET_JSON_spec_string ("credit_account", &credit_account),
       TALER_JSON_spec_amount ("amount", &amount),
       GNUNET_JSON_spec_string ("exchange_url", &base_url),
       GNUNET_JSON_spec_end ()
@@ -450,80 +430,49 @@ handle_admin_add_incoming (struct TALER_FAKEBANK_Handle 
*h,
                                            &amount,
                                            subject,
                                            base_url);
-    amount_s = TALER_amount_to_string (&amount);
     GNUNET_log (GNUNET_ERROR_TYPE_INFO,
-                "Receiving incoming wire transfer: %llu->%llu, subject: %s, 
amount: %s, from %s\n",
-                (unsigned long long) debit_account,
-                (unsigned long long) credit_account,
+                "Receiving incoming wire transfer: %s->%s, subject: %s, 
amount: %s, from %s\n",
+                debit_account,
+                credit_account,
                 subject,
-                amount_s,
+                TALER_amount2s (&amount),
                 base_url);
-    GNUNET_free (amount_s);
   }
   json_decref (json);
 
   /* Finally build response object */
-  {
-    void *json_str;
-    size_t json_len;
-
-    json = json_pack ("{s:I, s:o}",
-                      "row_id",
-                      (json_int_t) row_id,
-                      "timestamp", GNUNET_JSON_from_time_abs 
(GNUNET_TIME_UNIT_ZERO_ABS)); /*dummy tmp */
-
-    json_str = json_dumps (json,
-                           JSON_INDENT (2));
-    json_decref (json);
-    if (NULL == json_str)
-    {
-      GNUNET_break (0);
-      return MHD_NO;
-    }
-    json_len = strlen (json_str);
-    resp = MHD_create_response_from_buffer (json_len,
-                                            json_str,
-                                            MHD_RESPMEM_MUST_FREE);
-    if (NULL == resp)
-    {
-      GNUNET_break (0);
-      free (json_str);
-      return MHD_NO;
-    }
-    (void) MHD_add_response_header (resp,
-                                    MHD_HTTP_HEADER_CONTENT_TYPE,
-                                    "application/json");
-  }
-  ret = MHD_queue_response (connection,
-                            MHD_HTTP_OK,
-                            resp);
-  MHD_destroy_response (resp);
-  return ret;
+  return TALER_MHD_reply_json_pack (connection,
+                                    MHD_HTTP_OK,
+                                    "{s:I, s:o}",
+                                    "row_id",
+                                    (json_int_t) row_id,
+                                    "timestamp", GNUNET_JSON_from_time_abs (
+                                      GNUNET_TIME_UNIT_ZERO_ABS));             
                          /*dummy tmp */
 }
 
 
 /**
- * Handle incoming HTTP request for /reject.
+ * Handle incoming HTTP request for /transaction.
  *
  * @param h the fakebank handle
  * @param connection the connection
+ * @param account account making the transaction
  * @param upload_data request data
  * @param upload_data_size size of @a upload_data in bytes
  * @param con_cls closure for request (a `struct Buffer *`)
  * @return MHD result code
  */
 static int
-handle_reject (struct TALER_FAKEBANK_Handle *h,
-               struct MHD_Connection *connection,
-               const char *upload_data,
-               size_t *upload_data_size,
-               void **con_cls)
+handle_transaction (struct TALER_FAKEBANK_Handle *h,
+                    struct MHD_Connection *connection,
+                    const char *account,
+                    const char *upload_data,
+                    size_t *upload_data_size,
+                    void **con_cls)
 {
   enum GNUNET_JSON_PostResult pr;
   json_t *json;
-  struct MHD_Response *resp;
-  int ret;
-  int found;
+  uint64_t row_id;
 
   pr = GNUNET_JSON_post_parser (REQUEST_BUFFER_MAX,
                                 connection,
@@ -548,13 +497,25 @@ handle_reject (struct TALER_FAKEBANK_Handle *h,
     break;
   }
   {
-    uint64_t row_id;
-    uint64_t credit_account;
+    struct GNUNET_HashCode uuid;
+    struct TALER_WireTransferIdentifierRawP wtid;
+    const char *credit_account;
+    const char *base_url;
+    struct TALER_Amount amount;
     struct GNUNET_JSON_Specification spec[] = {
-      GNUNET_JSON_spec_uint64 ("row_id", &row_id),
-      GNUNET_JSON_spec_uint64 ("account_number", &credit_account),
+      GNUNET_JSON_spec_fixed_auto ("request_uid",
+                                   &uuid),
+      TALER_JSON_spec_amount ("amount",
+                              &amount),
+      GNUNET_JSON_spec_string ("exchange_base_url",
+                               &base_url),
+      GNUNET_JSON_spec_fixed_auto ("wtid",
+                                   &wtid),
+      GNUNET_JSON_spec_string ("credit_account",
+                               &credit_account),
       GNUNET_JSON_spec_end ()
     };
+
     if (GNUNET_OK !=
         GNUNET_JSON_parse (json,
                            spec,
@@ -564,31 +525,38 @@ handle_reject (struct TALER_FAKEBANK_Handle *h,
       json_decref (json);
       return MHD_NO;
     }
-    found = TALER_FAKEBANK_reject_transfer (h,
-                                            row_id,
-                                            credit_account);
-    GNUNET_log (GNUNET_ERROR_TYPE_INFO,
-                "Rejected wire transfer #%llu (to %llu)\n",
-                (unsigned long long) row_id,
-                (unsigned long long) credit_account);
+    {
+      char *subject;
+
+      subject = GNUNET_STRINGS_data_to_string_alloc (&wtid,
+                                                     sizeof (wtid));
+      // FIXME: use uuid here!!!
+      row_id = TALER_FAKEBANK_make_transfer (h,
+                                             account,
+                                             credit_account,
+                                             &amount,
+                                             subject,
+                                             base_url);
+      GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+                  "Receiving incoming wire transfer: %s->%s, subject: %s, 
amount: %s, from %s\n",
+                  account,
+                  credit_account,
+                  subject,
+                  TALER_amount2s (&amount),
+                  base_url);
+      GNUNET_free (subject);
+    }
   }
   json_decref (json);
 
-  if (GNUNET_OK != found)
-    return create_bank_error
-             (connection,
-             MHD_HTTP_NOT_FOUND,
-             TALER_EC_BANK_TRANSACTION_NOT_FOUND,
-             "transaction unknown");
-  /* finally build regular response */
-  resp = MHD_create_response_from_buffer (0,
-                                          NULL,
-                                          MHD_RESPMEM_PERSISTENT);
-  ret = MHD_queue_response (connection,
-                            MHD_HTTP_NO_CONTENT,
-                            resp);
-  MHD_destroy_response (resp);
-  return ret;
+  /* Finally build response object */
+  return TALER_MHD_reply_json_pack (connection,
+                                    MHD_HTTP_OK,
+                                    "{s:I, s:o}",
+                                    "row_id",
+                                    (json_int_t) row_id,
+                                    "timestamp", GNUNET_JSON_from_time_abs (
+                                      GNUNET_TIME_UNIT_ZERO_ABS));             
                          /*dummy tmp */
 }
 
 
@@ -626,75 +594,245 @@ handle_home_page (struct TALER_FAKEBANK_Handle *h,
 
 
 /**
- * Handle incoming HTTP request for /history
+ * This is the "base" structure for both the /history and the
+ * /history-range API calls.
+ */
+struct HistoryArgs
+{
+
+  /**
+   * Bank account number of the requesting client.
+   */
+  uint64_t account_number;
+
+  /**
+   * Index of the starting transaction.
+   */
+  uint64_t start_idx;
+
+  /**
+   * Requested number of results and order
+   * (positive: ascending, negative: descending)
+   */
+  int64_t delta;
+
+  /**
+   * Timeout for long polling.
+   */
+  struct GNUNET_TIME_Relative lp_timeout;
+
+  /**
+   * #GNUNET_YES if starting point was given.
+   */
+  int have_start;
+
+};
+
+
+/**
+ * Parse URL history arguments, of _both_ APIs:
+ * /history/incoming and /history/outgoing.
+ *
+ * @param connection MHD connection.
+ * @param function_name name of the caller.
+ * @param ha[out] will contain the parsed values.
+ * @return GNUNET_OK only if the parsing succeedes.
+ */
+static int
+parse_history_common_args (struct MHD_Connection *connection,
+                           struct HistoryArgs *ha)
+{
+  const char *start;
+  const char *delta;
+  const char *long_poll_ms;
+  unsigned long long lp_timeout;
+  unsigned long long sval;
+  long long d;
+
+  start = MHD_lookup_connection_value (connection,
+                                       MHD_GET_ARGUMENT_KIND,
+                                       "start");
+  ha->have_start = (NULL != start);
+  delta = MHD_lookup_connection_value (connection,
+                                       MHD_GET_ARGUMENT_KIND,
+                                       "delta");
+  long_poll_ms = MHD_lookup_connection_value (connection,
+                                              MHD_GET_ARGUMENT_KIND,
+                                              "long_poll_ms");
+  lp_timeout = 0;
+  if ( (NULL == delta) ||
+       (1 != sscanf (delta,
+                     "%lld",
+                     &d)) ||
+       ( (NULL != long_poll_ms) &&
+         (1 != sscanf (long_poll_ms,
+                       "%llu",
+                       &lp_timeout)) ) ||
+       ( (NULL != start) &&
+         (1 != sscanf (start,
+                       "%llu",
+                       &sval)) ) )
+  {
+    /* Fail if one of the above failed.  */
+    /* Invalid request, given that this is fakebank we impolitely
+     * just kill the connection instead of returning a nice error.
+     */
+    GNUNET_break (0);
+    return GNUNET_NO;
+  }
+  if (NULL == start)
+    ha->start_idx = (d > 0) ? 0 : UINT64_MAX;
+  else
+    ha->start_idx = (uint64_t) sval;
+  ha->delta = (int64_t) d;
+  ha->lp_timeout
+    = GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MILLISECONDS,
+                                     lp_timeout);
+  return GNUNET_OK;
+}
+
+
+/**
+ * Handle incoming HTTP request for /history/incoming
  *
  * @param h the fakebank handle
  * @param connection the connection
- * @param con_cls place to store state, not used
+ * @param account which account the request is about
  * @return MHD result code
  */
 static int
-handle_history (struct TALER_FAKEBANK_Handle *h,
-                struct MHD_Connection *connection,
-                void **con_cls)
+handle_credit_history (struct TALER_FAKEBANK_Handle *h,
+                       struct MHD_Connection *connection,
+                       const char *account)
 {
   struct HistoryArgs ha;
-  struct HistoryRangeIds hri;
-  const char *start;
-  const char *delta;
   struct Transaction *pos;
+  json_t *history;
 
-  (void) con_cls;
   if (GNUNET_OK !=
-      TFH_parse_history_common_args (connection,
-                                     &ha))
+      parse_history_common_args (connection,
+                                 &ha))
   {
     GNUNET_break (0);
     return MHD_NO;
   }
 
-  start = MHD_lookup_connection_value (connection,
-                                       MHD_GET_ARGUMENT_KIND,
-                                       "start");
-  delta = MHD_lookup_connection_value (connection,
-                                       MHD_GET_ARGUMENT_KIND,
-                                       "delta");
-  if ( ((NULL != start) && (1 != sscanf (start,
-                                         "%llu",
-                                         &hri.start))) ||
-       (NULL == delta) || (1 != sscanf (delta,
-                                        "%lld",
-                                        &hri.count)) )
+  if (! ha.have_start)
+  {
+    pos = (0 > ha.delta)
+          ? h->transactions_tail
+          : h->transactions_head;
+  }
+  else if (NULL != h->transactions_head)
+  {
+    for (pos = h->transactions_head;
+         NULL != pos;
+         pos = pos->next)
+      if (pos->row_id  == ha.start_idx)
+        break;
+    if (NULL == pos)
+    {
+      GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                  "Invalid start specified, transaction %llu not known!\n",
+                  (unsigned long long) ha.start_idx);
+      return MHD_NO;
+    }
+    /* range is exclusive, skip the matching entry */
+    if (ha.delta > 0)
+      pos = pos->next;
+    if (ha.delta < 0)
+      pos = pos->prev;
+  }
+  else
+  {
+    /* list is empty */
+    pos = NULL;
+  }
+  history = json_array ();
+  while ( (0 != ha.delta) &&
+          (NULL != pos) )
+  {
+    if (0 == strcasecmp (pos->credit_account,
+                         account))
+    {
+      json_t *trans;
+
+      trans = json_pack
+                ("{s:I, s:o, s:o, s:s, s:s, s:s}",
+                "row_id", (json_int_t) pos->row_id,
+                "date", GNUNET_JSON_from_time_abs (pos->date),
+                "amount", TALER_JSON_from_amount (&pos->amount),
+                "credit_account", account,
+                "debit_account", pos->debit_account,
+                "wtid", pos->subject /* we "know" it is OK */);
+      GNUNET_assert (0 ==
+                     json_array_append_new (history,
+                                            trans));
+      if (ha.delta > 0)
+        ha.delta--;
+      else
+        ha.delta++;
+    }
+    if (ha.delta > 0)
+      pos = pos->prev;
+    else
+      pos = pos->next;
+  }
+  return TALER_MHD_reply_json (connection,
+                               history,
+                               MHD_HTTP_OK);
+}
+
+
+/**
+ * Handle incoming HTTP request for /history/incoming
+ *
+ * @param h the fakebank handle
+ * @param connection the connection
+ * @param account which account the request is about
+ * @return MHD result code
+ */
+static int
+handle_debit_history (struct TALER_FAKEBANK_Handle *h,
+                      struct MHD_Connection *connection,
+                      const char *account)
+{
+  struct HistoryArgs ha;
+  struct Transaction *pos;
+  json_t *history;
+
+  if (GNUNET_OK !=
+      parse_history_common_args (connection,
+                                 &ha))
   {
     GNUNET_break (0);
     return MHD_NO;
   }
-  ha.range = &hri;
 
-  if (NULL == start)
+  if (! ha.have_start)
   {
-    pos = 0 > hri.count ?
-          h->transactions_tail : h->transactions_head;
+    pos = (0 > ha.delta)
+          ? h->transactions_tail
+          : h->transactions_head;
   }
   else if (NULL != h->transactions_head)
   {
     for (pos = h->transactions_head;
          NULL != pos;
          pos = pos->next)
-      if (pos->row_id  == hri.start)
+      if (pos->row_id  == ha.start_idx)
         break;
     if (NULL == pos)
     {
       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                  "Invalid range specified,"
-                  " transaction %llu not known!\n",
-                  (unsigned long long) hri.start);
+                  "Invalid start specified, transaction %llu not known!\n",
+                  (unsigned long long) ha.start_idx);
       return MHD_NO;
     }
     /* range is exclusive, skip the matching entry */
-    if (hri.count > 0)
+    if (ha.delta > 0)
       pos = pos->next;
-    if (hri.count < 0)
+    if (ha.delta < 0)
       pos = pos->prev;
   }
   else
@@ -702,56 +840,77 @@ handle_history (struct TALER_FAKEBANK_Handle *h,
     /* list is empty */
     pos = NULL;
   }
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "/history, start row (0 == no transactions exist): %llu\n",
-              NULL != pos ? pos->row_id : 0LL);
-  return TFH_build_history_response (connection,
-                                     pos,
-                                     &ha,
-                                     &TFH_handle_history_skip,
-                                     &TFH_handle_history_step,
-                                     &TFH_handle_history_advance);
+  history = json_array ();
+  while ( (0 != ha.delta) &&
+          (NULL != pos) )
+  {
+    if (0 == strcasecmp (pos->debit_account,
+                         account))
+    {
+      json_t *trans;
+
+      trans = json_pack
+                ("{s:I, s:o, s:o, s:s, s:s, s:s}",
+                "row_id", (json_int_t) pos->row_id,
+                "date", GNUNET_JSON_from_time_abs (pos->date),
+                "amount", TALER_JSON_from_amount (&pos->amount),
+                "credit_account", pos->credit_account,
+                "debit_account", account,
+                "reserve_pub", pos->subject /* we "know" it is OK */);
+      GNUNET_assert (0 ==
+                     json_array_append_new (history,
+                                            trans));
+      if (ha.delta > 0)
+        ha.delta--;
+      else
+        ha.delta++;
+    }
+    if (ha.delta > 0)
+      pos = pos->prev;
+    else
+      pos = pos->next;
+  }
+  return TALER_MHD_reply_json (connection,
+                               history,
+                               MHD_HTTP_OK);
 }
 
 
 /**
  * Handle incoming HTTP request.
  *
- * @param cls a `struct TALER_FAKEBANK_Handle`
+ * @param h our handle
  * @param connection the connection
  * @param url the requested url
  * @param method the method (POST, GET, ...)
- * @param version HTTP version (ignored)
+ * @param account which account should process the request
  * @param upload_data request data
  * @param upload_data_size size of @a upload_data in bytes
  * @param con_cls closure for request (a `struct Buffer *`)
  * @return MHD result code
  */
 static int
-handle_mhd_request (void *cls,
-                    struct MHD_Connection *connection,
-                    const char *url,
-                    const char *method,
-                    const char *version,
-                    const char *upload_data,
-                    size_t *upload_data_size,
-                    void **con_cls)
+serve (struct TALER_FAKEBANK_Handle *h,
+       struct MHD_Connection *connection,
+       const char *account,
+       const char *url,
+       const char *method,
+       const char *upload_data,
+       size_t *upload_data_size,
+       void **con_cls)
 {
-  struct TALER_FAKEBANK_Handle *h = cls;
-
-  (void) version;
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
               "Fakebank, serving: %s\n",
               url);
-  if ( (0 == strcasecmp (url,
-                         "/")) &&
+  if ( (0 == strcmp (url,
+                     "/")) &&
        (0 == strcasecmp (method,
                          MHD_HTTP_METHOD_GET)) )
     return handle_home_page (h,
                              connection,
                              con_cls);
-  if ( (0 == strcasecmp (url,
-                         "/admin/add/incoming")) &&
+  if ( (0 == strcmp (url,
+                     "/admin/add/incoming")) &&
        (0 == strcasecmp (method,
                          MHD_HTTP_METHOD_POST)) )
     return handle_admin_add_incoming (h,
@@ -759,22 +918,33 @@ handle_mhd_request (void *cls,
                                       upload_data,
                                       upload_data_size,
                                       con_cls);
-  if ( (0 == strcasecmp (url,
-                         "/reject")) &&
+  if ( (0 == strcmp (url,
+                     "/transaction")) &&
+       (NULL != account) &&
        (0 == strcasecmp (method,
                          MHD_HTTP_METHOD_POST)) )
-    return handle_reject (h,
-                          connection,
-                          upload_data,
-                          upload_data_size,
-                          con_cls);
-  if ( (0 == strcasecmp (url,
-                         "/history")) &&
+    return handle_transaction (h,
+                               connection,
+                               account,
+                               upload_data,
+                               upload_data_size,
+                               con_cls);
+  if ( (0 == strcmp (url,
+                     "/history/incoming")) &&
+       (NULL != account) &&
+       (0 == strcasecmp (method,
+                         MHD_HTTP_METHOD_GET)) )
+    return handle_credit_history (h,
+                                  connection,
+                                  account);
+  if ( (0 == strcmp (url,
+                     "/history/outgoing")) &&
+       (NULL != account) &&
        (0 == strcasecmp (method,
                          MHD_HTTP_METHOD_GET)) )
-    return handle_history (h,
-                           connection,
-                           con_cls);
+    return handle_debit_history (h,
+                                 connection,
+                                 account);
 
   /* Unexpected URL path, just close the connection. */
   /* we're rather impolite here, but it's a testcase. */
@@ -785,6 +955,55 @@ handle_mhd_request (void *cls,
 }
 
 
+/**
+ * Handle incoming HTTP request.
+ *
+ * @param cls a `struct TALER_FAKEBANK_Handle`
+ * @param connection the connection
+ * @param url the requested url
+ * @param method the method (POST, GET, ...)
+ * @param version HTTP version (ignored)
+ * @param upload_data request data
+ * @param upload_data_size size of @a upload_data in bytes
+ * @param con_cls closure for request (a `struct Buffer *`)
+ * @return MHD result code
+ */
+static int
+handle_mhd_request (void *cls,
+                    struct MHD_Connection *connection,
+                    const char *url,
+                    const char *method,
+                    const char *version,
+                    const char *upload_data,
+                    size_t *upload_data_size,
+                    void **con_cls)
+{
+  struct TALER_FAKEBANK_Handle *h = cls;
+  char *account = NULL;
+  char *end;
+  int ret;
+
+  (void) version;
+  if ( (strlen (url) > 1) &&
+       (NULL != (end = strchr (url + 1, '/'))) )
+  {
+    account = GNUNET_strndup (url + 1,
+                              end - url - 1);
+    url = end;
+  }
+  ret = serve (h,
+               connection,
+               account,
+               url,
+               method,
+               upload_data,
+               upload_data_size,
+               con_cls);
+  GNUNET_free_non_null (account);
+  return ret;
+}
+
+
 /**
  * Task run whenever HTTP server operations are pending.
  *
@@ -918,6 +1137,7 @@ TALER_FAKEBANK_start (uint16_t port)
   struct TALER_FAKEBANK_Handle *h;
 
   h = GNUNET_new (struct TALER_FAKEBANK_Handle);
+  h->port = port;
   h->mhd_bank = MHD_start_daemon (MHD_USE_DEBUG
 #if EPOLL_SUPPORT
                                   | MHD_USE_EPOLL_INTERNAL_THREAD
diff --git a/src/bank-lib/fakebank.h b/src/bank-lib/fakebank.h
index cc235901..c52902f1 100644
--- a/src/bank-lib/fakebank.h
+++ b/src/bank-lib/fakebank.h
@@ -1,6 +1,6 @@
 /*
   This file is part of TALER
-  (C) 2016, 2017, 2018 Inria and GNUnet e.V.
+  (C) 2016-2020 Taler Systems SA
 
   TALER is free software; you can redistribute it and/or
   modify it under the terms of the GNU General Public License
@@ -19,7 +19,7 @@
 
 /**
  * @file bank-lib/fakebank.h
- * @brief definitions for the "/history[-range]" layer.
+ * @brief definitions for the "/history" layer.
  * @author Marcello Stanisci <address@hidden>
  */
 
@@ -29,283 +29,4 @@
 #include <gnunet/gnunet_util_lib.h>
 #include "taler_bank_service.h"
 
-/**
- * Details about a transcation we (as the simulated bank) received.
- */
-struct Transaction
-{
-  /**
-   * We store transactions in a DLL.
-   */
-  struct Transaction *next;
-
-  /**
-   * We store transactions in a DLL.
-   */
-  struct Transaction *prev;
-
-  /**
-   * Amount to be transferred.
-   */
-  struct TALER_Amount amount;
-
-  /**
-   * Account to debit.
-   */
-  uint64_t debit_account;
-
-  /**
-   * Account to credit.
-   */
-  uint64_t credit_account;
-
-  /**
-   * Subject of the transfer.
-   */
-  char *subject;
-
-  /**
-   * Base URL of the exchange.
-   */
-  char *exchange_base_url;
-
-  /**
-   * When did the transaction happen?
-   */
-  struct GNUNET_TIME_Absolute date;
-
-  /**
-   * Number of this transaction.
-   */
-  long long unsigned int row_id;
-
-  /**
-   * Flag set if the transfer was rejected.
-   */
-  int rejected;
-
-  /**
-   * Has this transaction been subjected to #TALER_FAKEBANK_check()
-   * and should thus no longer be counted in
-   * #TALER_FAKEBANK_check_empty()?
-   */
-  int checked;
-};
-
-
-/******************************************
- * Definitions for "/history" start here. *
- ******************************************/
-
-/**
- * Needed to implement ascending/descending ordering
- * of /history results.
- */
-struct HistoryElement
-{
-
-  /**
-   * History JSON element.
-   */
-  json_t *element;
-
-  /**
-   * Previous element.
-   */
-  struct HistoryElement *prev;
-
-  /**
-   * Next element.
-   */
-  struct HistoryElement *next;
-};
-
-
-/**
- * Values to implement the "/history-range" range.
- */
-struct HistoryRangeDates
-{
-  /**
-   * Oldest row in the results.
-   */
-  struct GNUNET_TIME_Absolute start;
-
-  /**
-   * Youngest row in the results.
-   */
-  struct GNUNET_TIME_Absolute end;
-};
-
-/**
- * Values to implement the "/history" range.
- */
-struct HistoryRangeIds
-{
-
-  /**
-   * (Exclusive) row ID for the result set.
-   */
-  unsigned long long start;
-
-  /**
-   * How many transactions we want in the result set.  If
-   * negative/positive, @a start will be strictly younger/older
-   * of any element in the result set.
-   */
-  long long count;
-};
-
-
-/**
- * This is the "base" structure for both the /history and the
- * /history-range API calls.
- */
-struct HistoryArgs
-{
-
-  /**
-   * Direction asked by the client: CREDIT / DEBIT / BOTH / CANCEL.
-   */
-  enum TALER_BANK_Direction direction;
-
-  /**
-   * Bank account number of the requesting client.
-   */
-  unsigned long long account_number;
-
-  /**
-   * Ordering of the results.
-   */
-  unsigned int ascending;
-
-  /**
-   * Overloaded type that indicates the "range" to be returned
-   * in the results; this can be either a date range, or a
-   * starting row id + the count.
-   */
-  void *range;
-};
-
-
-/**
- * Type for a function that decides whether or not
- * the history-building loop should iterate once again.
- * Typically called from inside the 'while' condition.
- *
- * @param ha history argument.
- * @param pos current position.
- * @return GNUNET_YES if the iteration shuold go on.
- */
-typedef int (*CheckAdvance)(const struct HistoryArgs *ha,
-                            const struct Transaction *pos);
-
-/**
- * Type for a function that steps over the next element
- * in the list of all transactions, after the current @a pos
- * _got_ included in the result.
- */
-typedef struct Transaction * (*Step)(const struct HistoryArgs *ha,
-                                     const struct Transaction *pos);
-
-/*
- * Type for a function that steps over the next element
- * in the list of all transactions, after the current @a pos
- * did _not_ get included in the result.
- */
-typedef struct Transaction * (*Skip)(const struct HistoryArgs *ha,
-                                     const struct Transaction *pos);
-
-/**
- * Actual history response builder.
- *
- * @param pos first (included) element in the result set.
- * @param ha history arguments.
- * @param caller_name which function is building the history.
- * @return MHD_YES / MHD_NO, after having enqueued the response
- *         object into MHD.
- */
-int
-TFH_build_history_response (struct MHD_Connection *connection,
-                            struct Transaction *pos,
-                            struct HistoryArgs *ha,
-                            Skip skip,
-                            Step step,
-                            CheckAdvance advance);
-
-
-/**
- * Parse URL history arguments, of _both_ APIs:
- * /history and /history-range.
- *
- * @param connection MHD connection.
- * @param function_name name of the caller.
- * @param ha[out] will contain the parsed values.
- * @return GNUNET_OK only if the parsing succeedes.
- */
-int
-TFH_parse_history_common_args (struct MHD_Connection *connection,
-                               struct HistoryArgs *ha);
-
-
-/**
- * Decides whether the history builder will advance or not
- * to the next element.
- *
- * @param ha history args
- * @return GNUNET_YES/NO to advance/not-advance.
- */
-int
-TFH_handle_history_advance (const struct HistoryArgs *ha,
-                            const struct Transaction *pos);
-
-/**
- * Iterates on the "next" element to be processed.  To
- * be used when the current element does not get inserted in
- * the result.
- *
- * @param ha history arguments.
- * @param pos current element being processed.
- * @return the next element to be processed.
- */
-struct Transaction *
-TFH_handle_history_skip (const struct HistoryArgs *ha,
-                         const struct Transaction *pos);
-
-/**
- * Iterates on the "next" element to be processed.  To
- * be used when the current element _gets_ inserted in the result.
- *
- * @param ha history arguments.
- * @param pos current element being processed.
- * @return the next element to be processed.
- */
-struct Transaction *
-TFH_handle_history_step (const struct HistoryArgs *ha,
-                         const struct Transaction *pos);
-
-/**
- * Decides whether the history builder will advance or not
- * to the next element.
- *
- * @param ha history args
- * @return GNUNET_YES/NO to advance/not-advance.
- */
-int
-TFH_handle_history_range_advance (const struct HistoryArgs *ha,
-                                  const struct Transaction *pos);
-
-/**
- * Iterates towards the "next" element to be processed.  To
- * be used when the current element does not get inserted in
- * the result.
- *
- * @param ha history arguments.
- * @param pos current element being processed.
- * @return the next element to be processed.
- */
-struct Transaction *
-TFH_handle_history_range_skip (const struct HistoryArgs *ha,
-                               const struct Transaction *pos);
-
 #endif
diff --git a/src/bank-lib/fakebank_history.c b/src/bank-lib/fakebank_history.c
index f4c615c5..2781cdca 100644
--- a/src/bank-lib/fakebank_history.c
+++ b/src/bank-lib/fakebank_history.c
@@ -1,6 +1,6 @@
 /*
   This file is part of TALER
-  (C) 2016, 2017, 2018 Inria and GNUnet e.V.
+  (C) 2016-2020 Taler Systems SA
 
   TALER is free software; you can redistribute it and/or
   modify it under the terms of the GNU General Public License
@@ -19,92 +19,15 @@
 
 /**
  * @file bank-lib/fakebank_history.c
- * @brief definitions for the "/history[-range]" layer.
+ * @brief definitions for the "/history" layer.
  * @author Marcello Stanisci <address@hidden>
  */
-
 #include "platform.h"
 #include <gnunet/gnunet_util_lib.h>
 #include "taler_json_lib.h"
 #include "fakebank.h"
 
-/**
- * Decides whether the history builder will advance or not
- * to the next element.
- *
- * @param ha history args
- * @return GNUNET_YES/NO to advance/not-advance.
- */
-int
-TFH_handle_history_advance (const struct HistoryArgs *ha,
-                            const struct Transaction *pos)
-{
-  const struct HistoryRangeIds *hri = ha->range;
-
-  return (NULL != pos) && (0 != hri->count);
-}
-
-
-/**
- * Iterates on the "next" element to be processed.  To
- * be used when the current element does not get inserted in
- * the result.
- *
- * @param ha history arguments.
- * @param pos current element being processed.
- * @return the next element to be processed.
- */
-struct Transaction *
-TFH_handle_history_skip (const struct HistoryArgs *ha,
-                         const struct Transaction *pos)
-{
-  const struct HistoryRangeIds *hri = ha->range;
-
-  if (hri->count > 0)
-    return pos->next;
-  if (hri->count < 0)
-    return pos->prev;
-  return NULL;
-}
-
-
-/**
- * Iterates on the "next" element to be processed.  To
- * be used when the current element _gets_ inserted in the result.
- *
- * @param ha history arguments.
- * @param pos current element being processed.
- * @return the next element to be processed.
- */
-struct Transaction *
-TFH_handle_history_step (const struct HistoryArgs *ha,
-                         const struct Transaction *pos)
-{
-  struct HistoryRangeIds *hri = ha->range;
-
-  if (hri->count > 0)
-  {
-    hri->count--;
-    return pos->next;
-  }
-  if (hri->count < 0)
-  {
-    hri->count++;
-    return pos->prev;
-  }
-  return NULL;
-}
-
 
-/**
- * Actual history response builder.
- *
- * @param pos first (included) element in the result set, NULL if history is 
empty
- * @param ha history arguments.
- * @param caller_name which function is building the history.
- * @return MHD_YES / MHD_NO, after having enqueued the response
- *         object into MHD.
- */
 int
 TFH_build_history_response (struct MHD_Connection *connection,
                             struct Transaction *pos,
@@ -257,126 +180,3 @@ TFH_build_history_response (struct MHD_Connection 
*connection,
   }
   return ret;
 }
-
-
-/**
- * Parse URL history arguments, of _both_ APIs:
- * /history and /history-range.
- *
- * @param connection MHD connection.
- * @param function_name name of the caller.
- * @param ha[out] will contain the parsed values.
- * @return GNUNET_OK only if the parsing succeedes.
- */
-int
-TFH_parse_history_common_args (struct MHD_Connection *connection,
-                               struct HistoryArgs *ha)
-{
-  /**
-   * @variable
-   * Just check if given and == "basic", no need to keep around.
-   */
-  const char *auth;
-
-  /**
-   * All those will go into the structure, after parsing.
-   */
-  const char *direction;
-  const char *cancelled;
-  const char *ordering;
-  const char *account_number;
-
-
-  auth = MHD_lookup_connection_value (connection,
-                                      MHD_GET_ARGUMENT_KIND,
-                                      "auth");
-  direction = MHD_lookup_connection_value (connection,
-                                           MHD_GET_ARGUMENT_KIND,
-                                           "direction");
-  cancelled = MHD_lookup_connection_value (connection,
-                                           MHD_GET_ARGUMENT_KIND,
-                                           "cancelled");
-  ordering = MHD_lookup_connection_value (connection,
-                                          MHD_GET_ARGUMENT_KIND,
-                                          "ordering");
-  account_number = MHD_lookup_connection_value
-                     (connection,
-                     MHD_GET_ARGUMENT_KIND,
-                     "account_number");
-
-  /* Fail if one of the above failed.  */
-  if ( (NULL == direction) ||
-       (NULL == cancelled) ||
-       ( (0 != strcasecmp (cancelled,
-                           "OMIT")) &&
-         (0 != strcasecmp (cancelled,
-                           "SHOW")) ) ||
-       ( (0 != strcasecmp (direction,
-                           "BOTH")) &&
-         (0 != strcasecmp (direction,
-                           "CREDIT")) &&
-         (0 != strcasecmp (direction,
-                           "DEBIT")) ) ||
-       (1 != sscanf (account_number,
-                     "%llu",
-                     &ha->account_number)) ||
-       ( (NULL == auth) || (0 != strcasecmp (auth,
-                                             "basic")) ) )
-  {
-    /* Invalid request, given that this is fakebank we impolitely
-     * just kill the connection instead of returning a nice error.
-     */
-    GNUNET_break (0);
-    return GNUNET_NO;
-  }
-
-  if (0 == strcasecmp (direction,
-                       "CREDIT"))
-  {
-    ha->direction = TALER_BANK_DIRECTION_CREDIT;
-  }
-  else if (0 == strcasecmp (direction,
-                            "DEBIT"))
-  {
-    ha->direction = TALER_BANK_DIRECTION_DEBIT;
-  }
-  else if (0 == strcasecmp (direction,
-                            "BOTH"))
-  {
-    ha->direction = TALER_BANK_DIRECTION_BOTH;
-  }
-
-  /* Direction is invalid.  */
-  else
-  {
-    GNUNET_break (0);
-    return GNUNET_NO;
-  }
-
-  if (0 == strcasecmp (cancelled,
-                       "OMIT"))
-  {
-    /* nothing */
-  }
-  else if (0 == strcasecmp (cancelled,
-                            "SHOW"))
-  {
-    ha->direction |= TALER_BANK_DIRECTION_CANCEL;
-  }
-
-  /* Cancel-showing policy is invalid.  */
-  else
-  {
-    GNUNET_break (0);
-    return GNUNET_NO;
-  }
-
-  if ((NULL != ordering)
-      && (0 == strcmp ("ascending",
-                       ordering)))
-    ha->ascending = GNUNET_YES;
-  else
-    ha->ascending = GNUNET_NO;
-
-  return GNUNET_OK;
-}
diff --git a/src/bank-lib/taler-bank-transfer.c 
b/src/bank-lib/taler-bank-transfer.c
index 625545b6..c52c4b38 100644
--- a/src/bank-lib/taler-bank-transfer.c
+++ b/src/bank-lib/taler-bank-transfer.c
@@ -25,9 +25,9 @@
 #include "taler_bank_service.h"
 
 /**
- * Bank URL.
+ * Account base URL.
  */
-static char *bank_url;
+static char *account_base_url;
 
 /**
  * Amount to transfer.
@@ -35,14 +35,9 @@ static char *bank_url;
 static struct TALER_Amount amount;
 
 /**
- * Debit account number.
+ * Credit account payto://-URI.
  */
-static unsigned long long debit_account_no;
-
-/**
- * Credit account number.
- */
-static unsigned long long credit_account_no;
+static char *credit_account;
 
 /**
  * Wire transfer subject.
@@ -168,11 +163,23 @@ run (void *cls,
      const struct GNUNET_CONFIGURATION_Handle *cfg)
 {
   struct TALER_BANK_AuthenticationData auth;
+  struct TALER_ReservePublicKeyP reserve_pub;
 
   (void) cls;
   (void) args;
   (void) cfgfile;
   (void) cfg;
+  if (GNUNET_OK !=
+      GNUNET_STRINGS_string_to_data (subject,
+                                     strlen (subject),
+                                     &reserve_pub,
+                                     sizeof (reserve_pub)))
+  {
+    fprintf (stderr,
+             "Error: wire transfer subject must be a reserve public key\n");
+    return;
+  }
+
   ctx = GNUNET_CURL_init (&GNUNET_CURL_gnunet_scheduler_reschedule,
                           &rc);
   GNUNET_assert (NULL != ctx);
@@ -182,13 +189,11 @@ run (void *cls,
   auth.details.basic.username = username;
   auth.details.basic.password = password;
   op = TALER_BANK_admin_add_incoming (ctx,
-                                      bank_url,
+                                      account_base_url,
                                       &auth,
-                                      "https://exchange.com/legacy";,
-                                      subject,
+                                      &reserve_pub,
                                       &amount,
-                                      debit_account_no,
-                                      credit_account_no,
+                                      credit_account,
                                       &res_cb,
                                       NULL);
   GNUNET_SCHEDULER_add_shutdown (&do_shutdown,
@@ -219,26 +224,20 @@ main (int argc, char *const *argv)
       (GNUNET_GETOPT_option_string ('b',
                                     "bank",
                                     "URL",
-                                    "base URL of the bank",
-                                    &bank_url)),
+                                    "base URL of the account at the bank",
+                                    &account_base_url)),
     GNUNET_GETOPT_option_help ("Deposit funds into a Taler reserve"),
     GNUNET_GETOPT_option_mandatory
-      (GNUNET_GETOPT_option_ulong ('C',
-                                   "credit",
-                                   "ACCOUNT",
-                                   "number of the bank account to credit",
-                                   &credit_account_no)),
-    GNUNET_GETOPT_option_mandatory
-      (GNUNET_GETOPT_option_ulong ('D',
-                                   "debit",
-                                   "ACCOUNT",
-                                   "number of the bank account to debit",
-                                   &debit_account_no)),
+      (GNUNET_GETOPT_option_string ('C',
+                                    "credit",
+                                    "ACCOUNT",
+                                    "payto URL of the bank account to credit",
+                                    &credit_account)),
     GNUNET_GETOPT_option_mandatory
       (GNUNET_GETOPT_option_string ('s',
                                     "subject",
                                     "STRING",
-                                    "specifies the wire transfer subject",
+                                    "specifies the wire transfer subject (must 
be a reserve public key)",
                                     &subject)),
     GNUNET_GETOPT_option_mandatory
       (GNUNET_GETOPT_option_string ('u',
diff --git a/src/bank-lib/test_bank_api.c b/src/bank-lib/test_bank_api.c
index d15984a9..087e4484 100644
--- a/src/bank-lib/test_bank_api.c
+++ b/src/bank-lib/test_bank_api.c
@@ -1,6 +1,6 @@
 /*
   This file is part of TALER
-  Copyright (C) 2016, 2017 GNUnet e.V.
+  Copyright (C) 2016-2020 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
diff --git a/src/bank-lib/testing_api_cmd_history.c 
b/src/bank-lib/testing_api_cmd_history_credit.c
similarity index 56%
copy from src/bank-lib/testing_api_cmd_history.c
copy to src/bank-lib/testing_api_cmd_history_credit.c
index dc5cd2d9..5c2b34d0 100644
--- a/src/bank-lib/testing_api_cmd_history.c
+++ b/src/bank-lib/testing_api_cmd_history_credit.c
@@ -1,6 +1,6 @@
 /*
   This file is part of TALER
-  Copyright (C) 2018 Taler Systems SA
+  Copyright (C) 2018-2020 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
@@ -16,13 +16,11 @@
   License along with TALER; see the file COPYING.  If not, see
   <http://www.gnu.org/licenses/>
 */
-
 /**
  * @file bank-lib/testing_api_cmd_history.c
  * @brief command to check the /history API from the bank.
  * @author Marcello Stanisci
  */
-
 #include "platform.h"
 #include "taler_json_lib.h"
 #include <gnunet/gnunet_curl_lib.h>
@@ -40,35 +38,26 @@
 struct HistoryState
 {
   /**
-   * Base URL of the bank offering the "history" operation.
-   */
-  const char *bank_url;
-
-  /**
-   * Account number to ask the history for.
-   */
-  uint64_t account_no;
-
-  /**
-   * Which type of records we are interested: in-transfers
-   * / out-transfers / rejected transfers.
+   * Base URL of the account offering the "history" operation.
    */
-  enum TALER_BANK_Direction direction;
+  char *account_url;
 
   /**
-   * First row number we want in the result.
+   * Reference to command defining the
+   * first row number we want in the result.
    */
   const char *start_row_reference;
 
   /**
-   * How many rows we want in the result, _at most_.
+   * How many rows we want in the result, _at most_,
+   * and ascending/descending.
    */
-  unsigned long long num_results;
+  long long num_results;
 
   /**
    * Handle to a pending "history" operation.
    */
-  struct TALER_BANK_HistoryHandle *hh;
+  struct TALER_BANK_CreditHistoryHandle *hh;
 
   /**
    * Expected number of results (= rows).
@@ -81,34 +70,9 @@ struct HistoryState
    */
   int failed;
 
-  /**
-   * If GNUNET_YES, this parameter will ask for results in
-   * chronological order.
-   */
-  unsigned int ascending;
-
-  /**********************************
-   * Following defs are specific to *
-   * the "/history-range" version.  *
-   **********************************/
-
-  /**
-   * Last row number we want in the result.  Only used
-   * as a trait source when using the /history-range API.
-   */
-  const char *end_row_reference;
-
-  /**
-   * Start date for /history-range.
-   */
-  struct GNUNET_TIME_Absolute start_date;
-
-  /**
-   * End date for /history-range.
-   */
-  struct GNUNET_TIME_Absolute end_date;
 };
 
+
 /**
  * Item in the transaction history, as reconstructed from the
  * command history.
@@ -119,7 +83,7 @@ struct History
   /**
    * Wire details.
    */
-  struct TALER_BANK_TransferDetails details;
+  struct TALER_BANK_CreditDetails details;
 
   /**
    * Serial ID of the wire transfer.
@@ -127,19 +91,12 @@ struct History
   uint64_t row_id;
 
   /**
-   * Direction of the transfer.
+   * URL to free.
    */
-  enum TALER_BANK_Direction direction;
-
+  char *url;
 };
 
 
-/**
- * Array mapping bank account numbers to login credentials.
- */
-extern struct TALER_BANK_AuthenticationData AUTHS[];
-
-
 /**
  * Offer internal data to other commands.
  *
@@ -166,51 +123,6 @@ history_traits (void *cls,
 }
 
 
-/**
- * Test if the CMD at offset @a off has been /rejected, and
- * is indeed a wire transfer CMD.
- *
- * @param is interpreter state (where we are right now)
- * @param off offset of the command to test for rejection.
- *
- * @return GNUNET_YES if the command at @a off was cancelled.
- */
-static int
-test_cancelled (struct TALER_TESTING_Interpreter *is,
-                unsigned int off)
-{
-  const char *rejected_reference;
-  const struct TALER_TESTING_Command *current_cmd;
-
-  current_cmd = &is->commands[off];
-  TALER_LOG_INFO ("Is `%s' rejected?\n",
-                  current_cmd->label);
-  for (int i = 0; i<is->ip; i++)
-  {
-    const struct TALER_TESTING_Command *c = &is->commands[i];
-
-
-    /* XXX: Errors reported here are NOT fatal */
-
-    /* Rejected wire transfers have a non-NULL reference to a
-     * reject command to mark them as rejected. So errors
-     * about "reject traits" not found are NOT fatal here */
-    if (GNUNET_OK != TALER_TESTING_get_trait_rejected
-          (c, 0, &rejected_reference))
-      continue;
-
-    TALER_LOG_INFO ("Command `%s' was rejected by `%s'.\n",
-                    current_cmd->label,
-                    c->label);
-
-    if (0 == strcmp (rejected_reference,
-                     current_cmd->label))
-      return GNUNET_YES;
-  }
-  return GNUNET_NO;
-}
-
-
 /**
  * Free history @a h of length @a h_len.
  *
@@ -222,10 +134,7 @@ free_history (struct History *h,
               uint64_t h_len)
 {
   for (uint64_t off = 0; off<h_len; off++)
-  {
-    GNUNET_free (h[off].details.wire_transfer_subject);
-    GNUNET_free (h[off].details.account_url);
-  }
+    GNUNET_free (h[off].url);
   GNUNET_free_non_null (h);
 }
 
@@ -251,14 +160,12 @@ print_expected (struct History *h,
   for (uint64_t i = 0; i<h_len; i++)
   {
     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                "H(%llu): %s%s (serial: %llu, subject: %s,"
+                "H(%llu): %s (serial: %llu, subject: %s,"
                 " counterpart: %s)\n",
                 (unsigned long long) i,
-                (TALER_BANK_DIRECTION_CREDIT == h[i].direction) ?
-                "+" : "-",
                 TALER_amount2s (&h[i].details.amount),
                 (unsigned long long) h[i].row_id,
-                h[i].details.wire_transfer_subject,
+                TALER_B2S (&h[i].details.reserve_pub),
                 h[i].details.account_url);
   }
 }
@@ -280,20 +187,6 @@ build_history_hit_limit (uint64_t total,
                          const struct HistoryState *hs,
                          const struct TALER_TESTING_Command *pos)
 {
-  /* "/history-range" case.  */
-  if (GNUNET_TIME_UNIT_FOREVER_ABS.abs_value_us !=
-      hs->start_date.abs_value_us)
-  {
-    const struct GNUNET_TIME_Absolute *timestamp;
-
-    GNUNET_assert (GNUNET_OK ==
-                   TALER_TESTING_get_trait_absolute_time (pos,
-                                                          0,
-                                                          &timestamp));
-    GNUNET_assert (GNUNET_TIME_UNIT_FOREVER_ABS.abs_value_us !=
-                   hs->end_date.abs_value_us);
-    return timestamp->abs_value_us >= hs->end_date.abs_value_us;
-  }
   return total >= hs->num_results;
 }
 
@@ -305,13 +198,6 @@ build_history_hit_limit (uint64_t total,
  * to be allocated, and the second to actually populate every
  * element.
  *
- * This command has a limitation currently: it orders the history
- * list with descending elements if and only if the 'delta' was
- * given negative; and will order the list with ascending elements
- * if and only if the 'delta' was given positive.  Therefore,
- * for now it is NOT possible to test such a "/history" request:
- * "/history?auth=basic&direction=both&delta=10&ordering=descending"
- *
  * @param is interpreter state (supposedly having the
  *        current CMD pointing at a "history" CMD).
  * @param[out] rh history array to initialize.
@@ -350,10 +236,7 @@ build_history (struct TALER_TESTING_Interpreter *is,
                      (add_incoming_cmd, 0, &row_id_start));
   }
 
-  GNUNET_assert ((0 != hs->num_results) || /* "/history" */
-                 (GNUNET_TIME_UNIT_FOREVER_ABS.abs_value_us != /* 
"/history-range" */
-                  hs->start_date.abs_value_us));
-
+  GNUNET_assert (0 != hs->num_results);
   if (0 == is->ip)
   {
     TALER_LOG_DEBUG ("Checking history at first CMD..\n");
@@ -387,8 +270,9 @@ build_history (struct TALER_TESTING_Interpreter *is,
   for (unsigned int off = start; off != end + inc; off += inc)
   {
     const struct TALER_TESTING_Command *pos = &is->commands[off];
-    int cancelled;
     const uint64_t *row_id;
+    const char *credit_account;
+    const char *debit_account;
 
     /**
      * The following command allows us to skip over those CMDs
@@ -411,28 +295,6 @@ build_history (struct TALER_TESTING_Interpreter *is,
       }
     }
 
-    /* Seek "/history-range" starting row, _if_ that's the case */
-    if ((GNUNET_TIME_UNIT_FOREVER_ABS.abs_value_us !=
-         hs->start_date.abs_value_us) && (GNUNET_YES != ok))
-    {
-      const struct GNUNET_TIME_Absolute *timestamp;
-
-      TALER_TESTING_get_trait_absolute_time (pos,
-                                             0,
-                                             &timestamp);
-      TALER_LOG_DEBUG
-        ("Seeking first row, start vs timestamp: %llu vs %llu\n",
-        (long long unsigned int) hs->start_date.abs_value_us,
-        (long long unsigned int) timestamp->abs_value_us);
-
-      if (hs->start_date.abs_value_us <= timestamp->abs_value_us)
-      {
-        total = 0;
-        ok = GNUNET_YES;
-        continue;
-      }
-    }
-
     /* when 'start' was _not_ given, then ok == GNUNET_YES */
     if (GNUNET_NO == ok)
       continue; /* skip until we find the marker */
@@ -447,37 +309,23 @@ build_history (struct TALER_TESTING_Interpreter *is,
       break;
     }
 
-    cancelled = test_cancelled (is, off);
-
-    if ( (GNUNET_YES == cancelled) &&
-         (0 == (hs->direction & TALER_BANK_DIRECTION_CANCEL)) )
-    {
-      TALER_LOG_INFO ("Ignoring canceled wire"
-                      " transfer from history\n");
-      continue;
-    }
-
-    const uint64_t *credit_account_no;
-    const uint64_t *debit_account_no;
 
     GNUNET_assert
       (GNUNET_OK == TALER_TESTING_GET_TRAIT_CREDIT_ACCOUNT
-        (pos, &credit_account_no));
+        (pos, &credit_account));
 
     GNUNET_assert
       (GNUNET_OK == TALER_TESTING_GET_TRAIT_DEBIT_ACCOUNT
-        (pos, &debit_account_no));
+        (pos, &debit_account));
 
     TALER_LOG_INFO ("Potential history element:"
-                    " %llu->%llu; my account: %llu\n",
-                    (unsigned long long) *debit_account_no,
-                    (unsigned long long) *credit_account_no,
-                    (unsigned long long) hs->account_no);
-
-    if ( ( (0 != (hs->direction & TALER_BANK_DIRECTION_CREDIT)) &&
-           (hs->account_no == *credit_account_no)) ||
-         ( (0 != (hs->direction & TALER_BANK_DIRECTION_DEBIT)) &&
-           (hs->account_no == *debit_account_no)) )
+                    " %s->%s; my account: %s\n",
+                    debit_account,
+                    credit_account,
+                    hs->account_url);
+
+    if (0 == strcasecmp (hs->account_url,
+                         credit_account))
     {
       TALER_LOG_INFO ("+1 my history\n");
       total++; /* found matching record */
@@ -508,11 +356,10 @@ build_history (struct TALER_TESTING_Interpreter *is,
   for (unsigned int off = start; off != end + inc; off += inc)
   {
     const struct TALER_TESTING_Command *pos = &is->commands[off];
-    int cancelled;
     const uint64_t *row_id;
     char *bank_hostname;
-    const uint64_t *credit_account_no;
-    const uint64_t *debit_account_no;
+    const char *credit_account;
+    const char *debit_account;
 
     if (GNUNET_OK != TALER_TESTING_GET_TRAIT_ROW_ID
           (pos, &row_id))
@@ -533,28 +380,6 @@ build_history (struct TALER_TESTING_Interpreter *is,
       }
     }
 
-    /* Seek "/history-range" starting row, _if_ that's the case */
-    if ((GNUNET_TIME_UNIT_FOREVER_ABS.abs_value_us !=
-         hs->start_date.abs_value_us) && (GNUNET_YES != ok))
-    {
-      const struct GNUNET_TIME_Absolute *timestamp;
-
-      TALER_TESTING_get_trait_absolute_time (pos,
-                                             0,
-                                             &timestamp);
-      TALER_LOG_DEBUG
-        ("Seeking first row, start vs timestamp (2): %llu vs %llu\n",
-        (long long unsigned int) hs->start_date.abs_value_us,
-        (long long unsigned int) timestamp->abs_value_us);
-
-      if (hs->start_date.abs_value_us <= timestamp->abs_value_us)
-      {
-        total = 0;
-        ok = GNUNET_YES;
-        continue;
-      }
-    }
-
     TALER_LOG_INFO ("Found first row (2)\n");
 
     if (GNUNET_NO == ok)
@@ -574,43 +399,31 @@ build_history (struct TALER_TESTING_Interpreter *is,
 
     GNUNET_assert
       (GNUNET_OK == TALER_TESTING_GET_TRAIT_CREDIT_ACCOUNT
-        (pos, &credit_account_no));
+        (pos, &credit_account));
 
     GNUNET_assert
       (GNUNET_OK == TALER_TESTING_GET_TRAIT_DEBIT_ACCOUNT
-        (pos, &debit_account_no));
+        (pos, &debit_account));
 
     TALER_LOG_INFO ("Potential history bit:"
-                    " %llu->%llu; my account: %llu\n",
-                    (unsigned long long) *debit_account_no,
-                    (unsigned long long) *credit_account_no,
-                    (unsigned long long) hs->account_no);
+                    " %s->%s; my account: %s\n",
+                    debit_account,
+                    credit_account,
+                    hs->account_url);
 
     /**
      * Discard transactions where the audited account played
      * _both_ the credit and the debit roles, but _only if_
      * the audit goes on both directions..  This needs more
      * explaination!
-     */if ( ( (0 != (hs->direction & TALER_BANK_DIRECTION_CREDIT)) &&
-           (hs->account_no == *credit_account_no)) &&
-         ( (0 != (hs->direction & TALER_BANK_DIRECTION_DEBIT)) &&
-           (hs->account_no == *debit_account_no)) )
+     */if (0 == strcasecmp (hs->account_url,
+                         credit_account))
     {
       GNUNET_break (0);
       continue;
     }
 
-    cancelled = test_cancelled (is, off);
-    if ( (GNUNET_YES == cancelled) &&
-         (0 == (hs->direction & TALER_BANK_DIRECTION_CANCEL)) )
-    {
-      TALER_LOG_WARNING ("`%s' was cancelled\n",
-                         TALER_TESTING_interpreter_get_current_label
-                           (is));
-      continue;
-    }
-
-    bank_hostname = strchr (hs->bank_url, ':');
+    bank_hostname = strchr (hs->account_url, ':');
     GNUNET_assert (NULL != bank_hostname);
     bank_hostname += 3;
 
@@ -618,68 +431,36 @@ build_history (struct TALER_TESTING_Interpreter *is,
      * information.  */
 
     /* Asked for credit, and account got the credit.  */
-    if ( (0 != (hs->direction & TALER_BANK_DIRECTION_CREDIT)) &&
-         (hs->account_no == *credit_account_no))
-    {
-      h[total].direction = TALER_BANK_DIRECTION_CREDIT;
-      if (GNUNET_YES == cancelled)
-        h[total].direction |= TALER_BANK_DIRECTION_CANCEL;
-
-      GNUNET_asprintf
-        (&h[total].details.account_url,
-        ('/' == bank_hostname[strlen (bank_hostname) - 1])
-        ? "payto://x-taler-bank/%s%llu"
-        : "payto://x-taler-bank/%s/%llu",
-        bank_hostname,
-        (unsigned long long) *debit_account_no);
-    }
-
-    /* Asked for debit, and account got the debit.  */
-    if ( (0 != (hs->direction & TALER_BANK_DIRECTION_DEBIT)) &&
-         (hs->account_no == *debit_account_no))
+    if (0 == strcasecmp (hs->account_url,
+                         credit_account))
     {
-      h[total].direction = TALER_BANK_DIRECTION_DEBIT;
-      if (GNUNET_YES == cancelled)
-        h[total].direction |= TALER_BANK_DIRECTION_CANCEL;
-
-      GNUNET_asprintf
-        (&h[total].details.account_url,
-        ('/' == bank_hostname[strlen (bank_hostname) - 1])
-        ? "payto://x-taler-bank/%s%llu"
-        : "payto://x-taler-bank/%s/%llu",
-        bank_hostname,
-        (unsigned long long) *credit_account_no);
+      h[total].url = GNUNET_strdup (debit_account);
+      h[total].details.account_url = h[total].url;
     }
 
     /* This block _completes_ the information of the current item,
      * with amount / subject / exchange URL.  */
-    if ( ( (0 != (hs->direction & TALER_BANK_DIRECTION_CREDIT)) &&
-           (hs->account_no == *credit_account_no)) ||
-         ( (0 != (hs->direction & TALER_BANK_DIRECTION_DEBIT)) &&
-           (hs->account_no == *debit_account_no)) )
+    if (0 == strcasecmp (hs->account_url,
+                         credit_account))
     {
       const struct TALER_Amount *amount;
-      const char *subject;
-      const char *exchange_url;
-
-      GNUNET_assert
-        (GNUNET_OK == TALER_TESTING_get_trait_amount_obj
-          (pos, 0, &amount));
-
-      GNUNET_assert
-        (GNUNET_OK == TALER_TESTING_get_trait_transfer_subject
-          (pos, 0, &subject));
-
-      GNUNET_assert (GNUNET_OK == TALER_TESTING_get_trait_url
-                       (pos, 0, &exchange_url));
-
+      const struct TALER_ReservePublicKeyP *reserve_pub;
+      const char *account_url;
+
+      GNUNET_assert (GNUNET_OK ==
+                     TALER_TESTING_get_trait_amount_obj
+                       (pos, 0, &amount));
+      GNUNET_assert (GNUNET_OK ==
+                     TALER_TESTING_get_trait_reserve_pub
+                       (pos, 0, &reserve_pub));
+      GNUNET_assert (GNUNET_OK ==
+                     TALER_TESTING_get_trait_url
+                       (pos, 1,
+                       &account_url));
       h[total].details.amount = *amount;
-
       h[total].row_id = *row_id;
-      GNUNET_asprintf (&h[total].details.wire_transfer_subject,
-                       "%s %s",
-                       subject,
-                       exchange_url);
+      h[total].details.reserve_pub = *reserve_pub;
+      h[total].details.account_url = account_url;
       TALER_LOG_INFO ("+1-bit of my history\n");
       total++;
     }
@@ -723,8 +504,7 @@ compute_result_count (struct TALER_TESTING_Interpreter *is)
 static int
 check_result (struct TALER_TESTING_Interpreter *is,
               unsigned int off,
-              enum TALER_BANK_Direction dir,
-              const struct TALER_BANK_TransferDetails *details)
+              const struct TALER_BANK_CreditDetails *details)
 {
   uint64_t total;
   struct History *h;
@@ -737,27 +517,22 @@ check_result (struct TALER_TESTING_Interpreter *is,
                 " results, but got result #%u to check\n",
                 (unsigned int) total,
                 off);
-    print_expected (h, total, off);
-    return GNUNET_SYSERR;
-  }
-  if (h[off].direction != dir)
-  {
-    GNUNET_break (0);
-    print_expected (h, total, off);
-    free_history (h,
-                  total);
+    print_expected (h,
+                    total,
+                    off);
     return GNUNET_SYSERR;
   }
-
-  if ( (0 != strcmp (h[off].details.wire_transfer_subject,
-                     details->wire_transfer_subject)) ||
+  if ( (0 != GNUNET_memcmp (&h[off].details.reserve_pub,
+                            &details->reserve_pub)) ||
        (0 != TALER_amount_cmp (&h[off].details.amount,
                                &details->amount)) ||
        (0 != strcasecmp (h[off].details.account_url,
                          details->account_url)) )
   {
     GNUNET_break (0);
-    print_expected (h, total, off);
+    print_expected (h,
+                    total,
+                    off);
     free_history (h,
                   total);
     return GNUNET_SYSERR;
@@ -789,22 +564,30 @@ check_result (struct TALER_TESTING_Interpreter *is,
  * @param details details about the wire transfer.
  * @param json detailed response from the HTTPD, or NULL if
  *        reply was not in JSON.
+ * @return #GNUNET_OK to continue, #GNUNET_SYSERR to abort iteration
  */
-static void
+static int
 history_cb (void *cls,
             unsigned int http_status,
             enum TALER_ErrorCode ec,
-            enum TALER_BANK_Direction dir,
             uint64_t row_id,
-            const struct TALER_BANK_TransferDetails *details,
+            const struct TALER_BANK_CreditDetails *details,
             const json_t *json)
 {
   struct TALER_TESTING_Interpreter *is = cls;
   struct HistoryState *hs = is->commands[is->ip].cls;
 
   (void) row_id;
-  /*NOTE: "204 No Content" is used to signal the end of results.*/
-  if (MHD_HTTP_NO_CONTENT == http_status)
+  if (MHD_HTTP_OK != http_status)
+  {
+    hs->hh = NULL;
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                "Unwanted response code from /history: %u\n",
+                http_status);
+    TALER_TESTING_interpreter_fail (is);
+    return GNUNET_SYSERR;
+  }
+  if (NULL == details)
   {
     hs->hh = NULL;
     if ( (hs->results_obtained != compute_result_count (is)) ||
@@ -829,47 +612,33 @@ history_cb (void *cls,
       free_history (h,
                     total);
       TALER_TESTING_interpreter_fail (is);
-      return;
+      return GNUNET_SYSERR;
     }
     TALER_TESTING_interpreter_next (is);
-    return;
-  }
-
-  if (MHD_HTTP_OK != http_status)
-  {
-    hs->hh = NULL;
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                "Unwanted response code from /history[-range]: %u\n",
-                http_status);
-    TALER_TESTING_interpreter_fail (is);
-    return;
+    return GNUNET_OK;
   }
 
   /* check current element */
   if (GNUNET_OK != check_result (is,
                                  hs->results_obtained,
-                                 dir,
                                  details))
   {
-    GNUNET_break (0);
-
-    {
-      char *acc;
-
-      acc = json_dumps (json,
-                        JSON_COMPACT);
-      GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                  "Result %u was `%s'\n",
-                  (unsigned int) hs->results_obtained++,
-                  acc);
-      if (NULL != acc)
-        free (acc);
-    }
+    char *acc;
 
+    GNUNET_break (0);
+    acc = json_dumps (json,
+                      JSON_COMPACT);
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                "Result %u was `%s'\n",
+                (unsigned int) hs->results_obtained++,
+                acc);
+    if (NULL != acc)
+      free (acc);
     hs->failed = GNUNET_YES;
-    return;
+    return GNUNET_SYSERR;
   }
   hs->results_obtained++;
+  return GNUNET_OK;
 }
 
 
@@ -886,9 +655,8 @@ history_run (void *cls,
              struct TALER_TESTING_Interpreter *is)
 {
   struct HistoryState *hs = cls;
-  uint64_t row_id = UINT64_MAX;
-  const uint64_t *row_id_ptr = &row_id;
-  struct TALER_BANK_AuthenticationData *auth;
+  uint64_t row_id = (hs->num_results > 0) ? 0 : UINT64_MAX;
+  const uint64_t *row_ptr;
 
   (void) cmd;
   /* Get row_id from trait. */
@@ -902,27 +670,24 @@ history_run (void *cls,
     if (NULL == history_cmd)
       TALER_TESTING_FAIL (is);
 
-    if (GNUNET_OK != TALER_TESTING_get_trait_uint64 (history_cmd,
-                                                     0,
-                                                     &row_id_ptr))
+    if (GNUNET_OK !=
+        TALER_TESTING_get_trait_uint64 (history_cmd,
+                                        0,
+                                        &row_ptr))
       TALER_TESTING_FAIL (is);
-    row_id = *row_id_ptr;
-
+    else
+      row_id = *row_ptr;
     TALER_LOG_DEBUG ("row id (from trait) is %llu\n",
                      (unsigned long long) row_id);
   }
 
-  auth = &AUTHS[hs->account_no - 1];
-  hs->hh = TALER_BANK_history (is->ctx,
-                               hs->bank_url,
-                               auth,
-                               hs->account_no,
-                               hs->direction,
-                               hs->ascending,
-                               row_id,
-                               hs->num_results,
-                               &history_cb,
-                               is);
+  hs->hh = TALER_BANK_credit_history (is->ctx,
+                                      hs->account_url,
+                                      NULL,
+                                      row_id,
+                                      hs->num_results,
+                                      &history_cb,
+                                      is);
   GNUNET_assert (NULL != hs->hh);
 }
 
@@ -944,8 +709,9 @@ history_cleanup (void *cls,
   if (NULL != hs->hh)
   {
     TALER_LOG_WARNING ("/history did not complete\n");
-    TALER_BANK_history_cancel (hs->hh);
+    TALER_BANK_credit_history_cancel (hs->hh);
   }
+  GNUNET_free (hs->account_url);
   GNUNET_free (hs);
 }
 
@@ -954,12 +720,8 @@ history_cleanup (void *cls,
  * Make a "history" CMD.
  *
  * @param label command label.
- * @param bank_url base URL of the bank offering the "history"
+ * @param account_url base URL of the account offering the "history"
  *        operation.
- * @param account_no bank account number to ask the history for.
- * @param direction which direction this operation is interested.
- * @param ascending if #GNUNET_YES, the bank will return the rows
- *        in ascending (= chronological) order.
  * @param start_row_reference reference to a command that can
  *        offer a row identifier, to be used as the starting row
  *        to accept in the result.
@@ -967,25 +729,17 @@ history_cleanup (void *cls,
  * @return the command.
  */
 struct TALER_TESTING_Command
-TALER_TESTING_cmd_bank_history (const char *label,
-                                const char *bank_url,
-                                uint64_t account_no,
-                                enum TALER_BANK_Direction direction,
-                                unsigned int ascending,
+TALER_TESTING_cmd_bank_credits (const char *label,
+                                const char *account_url,
                                 const char *start_row_reference,
-                                unsigned long long num_results)
+                                long long num_results)
 {
   struct HistoryState *hs;
 
   hs = GNUNET_new (struct HistoryState);
-  hs->bank_url = bank_url;
-  hs->account_no = account_no;
-  hs->direction = direction;
+  hs->account_url = GNUNET_strdup (account_url);
   hs->start_row_reference = start_row_reference;
   hs->num_results = num_results;
-  hs->ascending = ascending;
-  hs->start_date = GNUNET_TIME_UNIT_FOREVER_ABS;
-  hs->end_date = GNUNET_TIME_UNIT_FOREVER_ABS;
 
   {
     struct TALER_TESTING_Command cmd = {
@@ -1001,4 +755,4 @@ TALER_TESTING_cmd_bank_history (const char *label,
 }
 
 
-/* end of testing_api_cmd_history.c */
+/* end of testing_api_cmd_credit_history.c */
diff --git a/src/bank-lib/testing_api_cmd_history.c 
b/src/bank-lib/testing_api_cmd_history_debit.c
similarity index 56%
rename from src/bank-lib/testing_api_cmd_history.c
rename to src/bank-lib/testing_api_cmd_history_debit.c
index dc5cd2d9..93f84da0 100644
--- a/src/bank-lib/testing_api_cmd_history.c
+++ b/src/bank-lib/testing_api_cmd_history_debit.c
@@ -1,6 +1,6 @@
 /*
   This file is part of TALER
-  Copyright (C) 2018 Taler Systems SA
+  Copyright (C) 2018-2020 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
@@ -40,35 +40,26 @@
 struct HistoryState
 {
   /**
-   * Base URL of the bank offering the "history" operation.
+   * Base URL of the account offering the "history" operation.
    */
-  const char *bank_url;
+  const char *account_url;
 
   /**
-   * Account number to ask the history for.
-   */
-  uint64_t account_no;
-
-  /**
-   * Which type of records we are interested: in-transfers
-   * / out-transfers / rejected transfers.
-   */
-  enum TALER_BANK_Direction direction;
-
-  /**
-   * First row number we want in the result.
+   * Reference to command defining the
+   * first row number we want in the result.
    */
   const char *start_row_reference;
 
   /**
-   * How many rows we want in the result, _at most_.
+   * How many rows we want in the result, _at most_,
+   * and ascending/descending.
    */
-  unsigned long long num_results;
+  long long num_results;
 
   /**
    * Handle to a pending "history" operation.
    */
-  struct TALER_BANK_HistoryHandle *hh;
+  struct TALER_BANK_DebitHistoryHandle *hh;
 
   /**
    * Expected number of results (= rows).
@@ -81,34 +72,9 @@ struct HistoryState
    */
   int failed;
 
-  /**
-   * If GNUNET_YES, this parameter will ask for results in
-   * chronological order.
-   */
-  unsigned int ascending;
-
-  /**********************************
-   * Following defs are specific to *
-   * the "/history-range" version.  *
-   **********************************/
-
-  /**
-   * Last row number we want in the result.  Only used
-   * as a trait source when using the /history-range API.
-   */
-  const char *end_row_reference;
-
-  /**
-   * Start date for /history-range.
-   */
-  struct GNUNET_TIME_Absolute start_date;
-
-  /**
-   * End date for /history-range.
-   */
-  struct GNUNET_TIME_Absolute end_date;
 };
 
+
 /**
  * Item in the transaction history, as reconstructed from the
  * command history.
@@ -119,7 +85,7 @@ struct History
   /**
    * Wire details.
    */
-  struct TALER_BANK_TransferDetails details;
+  struct TALER_BANK_DebitDetails details;
 
   /**
    * Serial ID of the wire transfer.
@@ -127,19 +93,12 @@ struct History
   uint64_t row_id;
 
   /**
-   * Direction of the transfer.
+   * URL to free.
    */
-  enum TALER_BANK_Direction direction;
-
+  char *url;
 };
 
 
-/**
- * Array mapping bank account numbers to login credentials.
- */
-extern struct TALER_BANK_AuthenticationData AUTHS[];
-
-
 /**
  * Offer internal data to other commands.
  *
@@ -166,51 +125,6 @@ history_traits (void *cls,
 }
 
 
-/**
- * Test if the CMD at offset @a off has been /rejected, and
- * is indeed a wire transfer CMD.
- *
- * @param is interpreter state (where we are right now)
- * @param off offset of the command to test for rejection.
- *
- * @return GNUNET_YES if the command at @a off was cancelled.
- */
-static int
-test_cancelled (struct TALER_TESTING_Interpreter *is,
-                unsigned int off)
-{
-  const char *rejected_reference;
-  const struct TALER_TESTING_Command *current_cmd;
-
-  current_cmd = &is->commands[off];
-  TALER_LOG_INFO ("Is `%s' rejected?\n",
-                  current_cmd->label);
-  for (int i = 0; i<is->ip; i++)
-  {
-    const struct TALER_TESTING_Command *c = &is->commands[i];
-
-
-    /* XXX: Errors reported here are NOT fatal */
-
-    /* Rejected wire transfers have a non-NULL reference to a
-     * reject command to mark them as rejected. So errors
-     * about "reject traits" not found are NOT fatal here */
-    if (GNUNET_OK != TALER_TESTING_get_trait_rejected
-          (c, 0, &rejected_reference))
-      continue;
-
-    TALER_LOG_INFO ("Command `%s' was rejected by `%s'.\n",
-                    current_cmd->label,
-                    c->label);
-
-    if (0 == strcmp (rejected_reference,
-                     current_cmd->label))
-      return GNUNET_YES;
-  }
-  return GNUNET_NO;
-}
-
-
 /**
  * Free history @a h of length @a h_len.
  *
@@ -222,10 +136,7 @@ free_history (struct History *h,
               uint64_t h_len)
 {
   for (uint64_t off = 0; off<h_len; off++)
-  {
-    GNUNET_free (h[off].details.wire_transfer_subject);
-    GNUNET_free (h[off].details.account_url);
-  }
+    GNUNET_free (h[off].url);
   GNUNET_free_non_null (h);
 }
 
@@ -251,14 +162,12 @@ print_expected (struct History *h,
   for (uint64_t i = 0; i<h_len; i++)
   {
     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                "H(%llu): %s%s (serial: %llu, subject: %s,"
+                "H(%llu): %s (serial: %llu, subject: %s,"
                 " counterpart: %s)\n",
                 (unsigned long long) i,
-                (TALER_BANK_DIRECTION_CREDIT == h[i].direction) ?
-                "+" : "-",
                 TALER_amount2s (&h[i].details.amount),
                 (unsigned long long) h[i].row_id,
-                h[i].details.wire_transfer_subject,
+                TALER_B2S (&h[i].details.wtid),
                 h[i].details.account_url);
   }
 }
@@ -280,20 +189,6 @@ build_history_hit_limit (uint64_t total,
                          const struct HistoryState *hs,
                          const struct TALER_TESTING_Command *pos)
 {
-  /* "/history-range" case.  */
-  if (GNUNET_TIME_UNIT_FOREVER_ABS.abs_value_us !=
-      hs->start_date.abs_value_us)
-  {
-    const struct GNUNET_TIME_Absolute *timestamp;
-
-    GNUNET_assert (GNUNET_OK ==
-                   TALER_TESTING_get_trait_absolute_time (pos,
-                                                          0,
-                                                          &timestamp));
-    GNUNET_assert (GNUNET_TIME_UNIT_FOREVER_ABS.abs_value_us !=
-                   hs->end_date.abs_value_us);
-    return timestamp->abs_value_us >= hs->end_date.abs_value_us;
-  }
   return total >= hs->num_results;
 }
 
@@ -305,13 +200,6 @@ build_history_hit_limit (uint64_t total,
  * to be allocated, and the second to actually populate every
  * element.
  *
- * This command has a limitation currently: it orders the history
- * list with descending elements if and only if the 'delta' was
- * given negative; and will order the list with ascending elements
- * if and only if the 'delta' was given positive.  Therefore,
- * for now it is NOT possible to test such a "/history" request:
- * "/history?auth=basic&direction=both&delta=10&ordering=descending"
- *
  * @param is interpreter state (supposedly having the
  *        current CMD pointing at a "history" CMD).
  * @param[out] rh history array to initialize.
@@ -350,10 +238,7 @@ build_history (struct TALER_TESTING_Interpreter *is,
                      (add_incoming_cmd, 0, &row_id_start));
   }
 
-  GNUNET_assert ((0 != hs->num_results) || /* "/history" */
-                 (GNUNET_TIME_UNIT_FOREVER_ABS.abs_value_us != /* 
"/history-range" */
-                  hs->start_date.abs_value_us));
-
+  GNUNET_assert (0 != hs->num_results);
   if (0 == is->ip)
   {
     TALER_LOG_DEBUG ("Checking history at first CMD..\n");
@@ -387,8 +272,9 @@ build_history (struct TALER_TESTING_Interpreter *is,
   for (unsigned int off = start; off != end + inc; off += inc)
   {
     const struct TALER_TESTING_Command *pos = &is->commands[off];
-    int cancelled;
     const uint64_t *row_id;
+    const char *debit_account;
+    const char *credit_account;
 
     /**
      * The following command allows us to skip over those CMDs
@@ -411,28 +297,6 @@ build_history (struct TALER_TESTING_Interpreter *is,
       }
     }
 
-    /* Seek "/history-range" starting row, _if_ that's the case */
-    if ((GNUNET_TIME_UNIT_FOREVER_ABS.abs_value_us !=
-         hs->start_date.abs_value_us) && (GNUNET_YES != ok))
-    {
-      const struct GNUNET_TIME_Absolute *timestamp;
-
-      TALER_TESTING_get_trait_absolute_time (pos,
-                                             0,
-                                             &timestamp);
-      TALER_LOG_DEBUG
-        ("Seeking first row, start vs timestamp: %llu vs %llu\n",
-        (long long unsigned int) hs->start_date.abs_value_us,
-        (long long unsigned int) timestamp->abs_value_us);
-
-      if (hs->start_date.abs_value_us <= timestamp->abs_value_us)
-      {
-        total = 0;
-        ok = GNUNET_YES;
-        continue;
-      }
-    }
-
     /* when 'start' was _not_ given, then ok == GNUNET_YES */
     if (GNUNET_NO == ok)
       continue; /* skip until we find the marker */
@@ -447,37 +311,22 @@ build_history (struct TALER_TESTING_Interpreter *is,
       break;
     }
 
-    cancelled = test_cancelled (is, off);
-
-    if ( (GNUNET_YES == cancelled) &&
-         (0 == (hs->direction & TALER_BANK_DIRECTION_CANCEL)) )
-    {
-      TALER_LOG_INFO ("Ignoring canceled wire"
-                      " transfer from history\n");
-      continue;
-    }
-
-    const uint64_t *credit_account_no;
-    const uint64_t *debit_account_no;
-
     GNUNET_assert
-      (GNUNET_OK == TALER_TESTING_GET_TRAIT_CREDIT_ACCOUNT
-        (pos, &credit_account_no));
+      (GNUNET_OK == TALER_TESTING_GET_TRAIT_DEBIT_ACCOUNT
+        (pos, &debit_account));
 
     GNUNET_assert
-      (GNUNET_OK == TALER_TESTING_GET_TRAIT_DEBIT_ACCOUNT
-        (pos, &debit_account_no));
+      (GNUNET_OK == TALER_TESTING_GET_TRAIT_CREDIT_ACCOUNT
+        (pos, &credit_account));
 
     TALER_LOG_INFO ("Potential history element:"
-                    " %llu->%llu; my account: %llu\n",
-                    (unsigned long long) *debit_account_no,
-                    (unsigned long long) *credit_account_no,
-                    (unsigned long long) hs->account_no);
-
-    if ( ( (0 != (hs->direction & TALER_BANK_DIRECTION_CREDIT)) &&
-           (hs->account_no == *credit_account_no)) ||
-         ( (0 != (hs->direction & TALER_BANK_DIRECTION_DEBIT)) &&
-           (hs->account_no == *debit_account_no)) )
+                    " %s->%s; my account: %s\n",
+                    debit_account,
+                    credit_account,
+                    hs->account_url);
+
+    if (0 == strcasecmp (hs->account_url,
+                         debit_account))
     {
       TALER_LOG_INFO ("+1 my history\n");
       total++; /* found matching record */
@@ -508,11 +357,10 @@ build_history (struct TALER_TESTING_Interpreter *is,
   for (unsigned int off = start; off != end + inc; off += inc)
   {
     const struct TALER_TESTING_Command *pos = &is->commands[off];
-    int cancelled;
     const uint64_t *row_id;
     char *bank_hostname;
-    const uint64_t *credit_account_no;
-    const uint64_t *debit_account_no;
+    const char *credit_account;
+    const char *debit_account;
 
     if (GNUNET_OK != TALER_TESTING_GET_TRAIT_ROW_ID
           (pos, &row_id))
@@ -533,28 +381,6 @@ build_history (struct TALER_TESTING_Interpreter *is,
       }
     }
 
-    /* Seek "/history-range" starting row, _if_ that's the case */
-    if ((GNUNET_TIME_UNIT_FOREVER_ABS.abs_value_us !=
-         hs->start_date.abs_value_us) && (GNUNET_YES != ok))
-    {
-      const struct GNUNET_TIME_Absolute *timestamp;
-
-      TALER_TESTING_get_trait_absolute_time (pos,
-                                             0,
-                                             &timestamp);
-      TALER_LOG_DEBUG
-        ("Seeking first row, start vs timestamp (2): %llu vs %llu\n",
-        (long long unsigned int) hs->start_date.abs_value_us,
-        (long long unsigned int) timestamp->abs_value_us);
-
-      if (hs->start_date.abs_value_us <= timestamp->abs_value_us)
-      {
-        total = 0;
-        ok = GNUNET_YES;
-        continue;
-      }
-    }
-
     TALER_LOG_INFO ("Found first row (2)\n");
 
     if (GNUNET_NO == ok)
@@ -573,113 +399,69 @@ build_history (struct TALER_TESTING_Interpreter *is,
     }
 
     GNUNET_assert
-      (GNUNET_OK == TALER_TESTING_GET_TRAIT_CREDIT_ACCOUNT
-        (pos, &credit_account_no));
+      (GNUNET_OK == TALER_TESTING_GET_TRAIT_DEBIT_ACCOUNT
+        (pos, &debit_account));
 
     GNUNET_assert
-      (GNUNET_OK == TALER_TESTING_GET_TRAIT_DEBIT_ACCOUNT
-        (pos, &debit_account_no));
+      (GNUNET_OK == TALER_TESTING_GET_TRAIT_CREDIT_ACCOUNT
+        (pos, &credit_account));
 
     TALER_LOG_INFO ("Potential history bit:"
-                    " %llu->%llu; my account: %llu\n",
-                    (unsigned long long) *debit_account_no,
-                    (unsigned long long) *credit_account_no,
-                    (unsigned long long) hs->account_no);
+                    " %s->%s; my account: %s\n",
+                    debit_account,
+                    credit_account,
+                    hs->account_url);
 
     /**
      * Discard transactions where the audited account played
-     * _both_ the credit and the debit roles, but _only if_
+     * _both_ the debit and the debit roles, but _only if_
      * the audit goes on both directions..  This needs more
      * explaination!
-     */if ( ( (0 != (hs->direction & TALER_BANK_DIRECTION_CREDIT)) &&
-           (hs->account_no == *credit_account_no)) &&
-         ( (0 != (hs->direction & TALER_BANK_DIRECTION_DEBIT)) &&
-           (hs->account_no == *debit_account_no)) )
+     */if (0 == strcasecmp (hs->account_url,
+                         debit_account))
     {
       GNUNET_break (0);
       continue;
     }
 
-    cancelled = test_cancelled (is, off);
-    if ( (GNUNET_YES == cancelled) &&
-         (0 == (hs->direction & TALER_BANK_DIRECTION_CANCEL)) )
-    {
-      TALER_LOG_WARNING ("`%s' was cancelled\n",
-                         TALER_TESTING_interpreter_get_current_label
-                           (is));
-      continue;
-    }
-
-    bank_hostname = strchr (hs->bank_url, ':');
+    bank_hostname = strchr (hs->account_url, ':');
     GNUNET_assert (NULL != bank_hostname);
     bank_hostname += 3;
 
     /* Next two blocks only put the 'direction' and 'banking'
      * information.  */
 
-    /* Asked for credit, and account got the credit.  */
-    if ( (0 != (hs->direction & TALER_BANK_DIRECTION_CREDIT)) &&
-         (hs->account_no == *credit_account_no))
-    {
-      h[total].direction = TALER_BANK_DIRECTION_CREDIT;
-      if (GNUNET_YES == cancelled)
-        h[total].direction |= TALER_BANK_DIRECTION_CANCEL;
-
-      GNUNET_asprintf
-        (&h[total].details.account_url,
-        ('/' == bank_hostname[strlen (bank_hostname) - 1])
-        ? "payto://x-taler-bank/%s%llu"
-        : "payto://x-taler-bank/%s/%llu",
-        bank_hostname,
-        (unsigned long long) *debit_account_no);
-    }
-
     /* Asked for debit, and account got the debit.  */
-    if ( (0 != (hs->direction & TALER_BANK_DIRECTION_DEBIT)) &&
-         (hs->account_no == *debit_account_no))
+    if (0 == strcasecmp (hs->account_url,
+                         debit_account))
     {
-      h[total].direction = TALER_BANK_DIRECTION_DEBIT;
-      if (GNUNET_YES == cancelled)
-        h[total].direction |= TALER_BANK_DIRECTION_CANCEL;
-
-      GNUNET_asprintf
-        (&h[total].details.account_url,
-        ('/' == bank_hostname[strlen (bank_hostname) - 1])
-        ? "payto://x-taler-bank/%s%llu"
-        : "payto://x-taler-bank/%s/%llu",
-        bank_hostname,
-        (unsigned long long) *credit_account_no);
+      h[total].url = GNUNET_strdup (credit_account);
+      h[total].details.account_url = h[total].url;
     }
 
     /* This block _completes_ the information of the current item,
      * with amount / subject / exchange URL.  */
-    if ( ( (0 != (hs->direction & TALER_BANK_DIRECTION_CREDIT)) &&
-           (hs->account_no == *credit_account_no)) ||
-         ( (0 != (hs->direction & TALER_BANK_DIRECTION_DEBIT)) &&
-           (hs->account_no == *debit_account_no)) )
+    if (0 == strcasecmp (hs->account_url,
+                         debit_account))
     {
       const struct TALER_Amount *amount;
-      const char *subject;
-      const char *exchange_url;
-
-      GNUNET_assert
-        (GNUNET_OK == TALER_TESTING_get_trait_amount_obj
-          (pos, 0, &amount));
-
-      GNUNET_assert
-        (GNUNET_OK == TALER_TESTING_get_trait_transfer_subject
-          (pos, 0, &subject));
-
-      GNUNET_assert (GNUNET_OK == TALER_TESTING_get_trait_url
-                       (pos, 0, &exchange_url));
-
+      const struct TALER_WireTransferIdentifierRawP *wtid;
+      const char *account_url;
+
+      GNUNET_assert (GNUNET_OK ==
+                     TALER_TESTING_get_trait_amount_obj
+                       (pos, 0, &amount));
+      GNUNET_assert (GNUNET_OK ==
+                     TALER_TESTING_get_trait_wtid
+                       (pos, 0, &wtid));
+      GNUNET_assert (GNUNET_OK ==
+                     TALER_TESTING_get_trait_url
+                       (pos, 1,
+                       &account_url));
       h[total].details.amount = *amount;
-
       h[total].row_id = *row_id;
-      GNUNET_asprintf (&h[total].details.wire_transfer_subject,
-                       "%s %s",
-                       subject,
-                       exchange_url);
+      h[total].details.wtid = *wtid;
+      h[total].details.account_url = account_url;
       TALER_LOG_INFO ("+1-bit of my history\n");
       total++;
     }
@@ -723,8 +505,7 @@ compute_result_count (struct TALER_TESTING_Interpreter *is)
 static int
 check_result (struct TALER_TESTING_Interpreter *is,
               unsigned int off,
-              enum TALER_BANK_Direction dir,
-              const struct TALER_BANK_TransferDetails *details)
+              const struct TALER_BANK_DebitDetails *details)
 {
   uint64_t total;
   struct History *h;
@@ -737,27 +518,22 @@ check_result (struct TALER_TESTING_Interpreter *is,
                 " results, but got result #%u to check\n",
                 (unsigned int) total,
                 off);
-    print_expected (h, total, off);
-    return GNUNET_SYSERR;
-  }
-  if (h[off].direction != dir)
-  {
-    GNUNET_break (0);
-    print_expected (h, total, off);
-    free_history (h,
-                  total);
+    print_expected (h,
+                    total,
+                    off);
     return GNUNET_SYSERR;
   }
-
-  if ( (0 != strcmp (h[off].details.wire_transfer_subject,
-                     details->wire_transfer_subject)) ||
+  if ( (0 != GNUNET_memcmp (&h[off].details.wtid,
+                            &details->wtid)) ||
        (0 != TALER_amount_cmp (&h[off].details.amount,
                                &details->amount)) ||
        (0 != strcasecmp (h[off].details.account_url,
                          details->account_url)) )
   {
     GNUNET_break (0);
-    print_expected (h, total, off);
+    print_expected (h,
+                    total,
+                    off);
     free_history (h,
                   total);
     return GNUNET_SYSERR;
@@ -789,22 +565,30 @@ check_result (struct TALER_TESTING_Interpreter *is,
  * @param details details about the wire transfer.
  * @param json detailed response from the HTTPD, or NULL if
  *        reply was not in JSON.
+ * @return #GNUNET_OK to continue, #GNUNET_SYSERR to abort iteration
  */
-static void
+static int
 history_cb (void *cls,
             unsigned int http_status,
             enum TALER_ErrorCode ec,
-            enum TALER_BANK_Direction dir,
             uint64_t row_id,
-            const struct TALER_BANK_TransferDetails *details,
+            const struct TALER_BANK_DebitDetails *details,
             const json_t *json)
 {
   struct TALER_TESTING_Interpreter *is = cls;
   struct HistoryState *hs = is->commands[is->ip].cls;
 
   (void) row_id;
-  /*NOTE: "204 No Content" is used to signal the end of results.*/
-  if (MHD_HTTP_NO_CONTENT == http_status)
+  if (MHD_HTTP_OK != http_status)
+  {
+    hs->hh = NULL;
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                "Unwanted response code from /history: %u\n",
+                http_status);
+    TALER_TESTING_interpreter_fail (is);
+    return GNUNET_SYSERR;
+  }
+  if (NULL == details)
   {
     hs->hh = NULL;
     if ( (hs->results_obtained != compute_result_count (is)) ||
@@ -829,47 +613,33 @@ history_cb (void *cls,
       free_history (h,
                     total);
       TALER_TESTING_interpreter_fail (is);
-      return;
+      return GNUNET_SYSERR;
     }
     TALER_TESTING_interpreter_next (is);
-    return;
-  }
-
-  if (MHD_HTTP_OK != http_status)
-  {
-    hs->hh = NULL;
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                "Unwanted response code from /history[-range]: %u\n",
-                http_status);
-    TALER_TESTING_interpreter_fail (is);
-    return;
+    return GNUNET_OK;
   }
 
   /* check current element */
   if (GNUNET_OK != check_result (is,
                                  hs->results_obtained,
-                                 dir,
                                  details))
   {
-    GNUNET_break (0);
-
-    {
-      char *acc;
-
-      acc = json_dumps (json,
-                        JSON_COMPACT);
-      GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                  "Result %u was `%s'\n",
-                  (unsigned int) hs->results_obtained++,
-                  acc);
-      if (NULL != acc)
-        free (acc);
-    }
+    char *acc;
 
+    GNUNET_break (0);
+    acc = json_dumps (json,
+                      JSON_COMPACT);
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                "Result %u was `%s'\n",
+                (unsigned int) hs->results_obtained++,
+                acc);
+    if (NULL != acc)
+      free (acc);
     hs->failed = GNUNET_YES;
-    return;
+    return GNUNET_SYSERR;
   }
   hs->results_obtained++;
+  return GNUNET_OK;
 }
 
 
@@ -886,9 +656,8 @@ history_run (void *cls,
              struct TALER_TESTING_Interpreter *is)
 {
   struct HistoryState *hs = cls;
-  uint64_t row_id = UINT64_MAX;
-  const uint64_t *row_id_ptr = &row_id;
-  struct TALER_BANK_AuthenticationData *auth;
+  uint64_t row_id = (hs->num_results > 0) ? 0 : UINT64_MAX;
+  const uint64_t *row_ptr;
 
   (void) cmd;
   /* Get row_id from trait. */
@@ -902,27 +671,24 @@ history_run (void *cls,
     if (NULL == history_cmd)
       TALER_TESTING_FAIL (is);
 
-    if (GNUNET_OK != TALER_TESTING_get_trait_uint64 (history_cmd,
-                                                     0,
-                                                     &row_id_ptr))
+    if (GNUNET_OK !=
+        TALER_TESTING_get_trait_uint64 (history_cmd,
+                                        0,
+                                        &row_ptr))
       TALER_TESTING_FAIL (is);
-    row_id = *row_id_ptr;
-
+    else
+      row_id = *row_ptr;
     TALER_LOG_DEBUG ("row id (from trait) is %llu\n",
                      (unsigned long long) row_id);
   }
 
-  auth = &AUTHS[hs->account_no - 1];
-  hs->hh = TALER_BANK_history (is->ctx,
-                               hs->bank_url,
-                               auth,
-                               hs->account_no,
-                               hs->direction,
-                               hs->ascending,
-                               row_id,
-                               hs->num_results,
-                               &history_cb,
-                               is);
+  hs->hh = TALER_BANK_debit_history (is->ctx,
+                                     hs->account_url,
+                                     NULL,
+                                     row_id,
+                                     hs->num_results,
+                                     &history_cb,
+                                     is);
   GNUNET_assert (NULL != hs->hh);
 }
 
@@ -944,7 +710,7 @@ history_cleanup (void *cls,
   if (NULL != hs->hh)
   {
     TALER_LOG_WARNING ("/history did not complete\n");
-    TALER_BANK_history_cancel (hs->hh);
+    TALER_BANK_debit_history_cancel (hs->hh);
   }
   GNUNET_free (hs);
 }
@@ -954,12 +720,8 @@ history_cleanup (void *cls,
  * Make a "history" CMD.
  *
  * @param label command label.
- * @param bank_url base URL of the bank offering the "history"
+ * @param account_url base URL of the account offering the "history"
  *        operation.
- * @param account_no bank account number to ask the history for.
- * @param direction which direction this operation is interested.
- * @param ascending if #GNUNET_YES, the bank will return the rows
- *        in ascending (= chronological) order.
  * @param start_row_reference reference to a command that can
  *        offer a row identifier, to be used as the starting row
  *        to accept in the result.
@@ -967,25 +729,17 @@ history_cleanup (void *cls,
  * @return the command.
  */
 struct TALER_TESTING_Command
-TALER_TESTING_cmd_bank_history (const char *label,
-                                const char *bank_url,
-                                uint64_t account_no,
-                                enum TALER_BANK_Direction direction,
-                                unsigned int ascending,
-                                const char *start_row_reference,
-                                unsigned long long num_results)
+TALER_TESTING_cmd_bank_debits (const char *label,
+                               const char *account_url,
+                               const char *start_row_reference,
+                               long long num_results)
 {
   struct HistoryState *hs;
 
   hs = GNUNET_new (struct HistoryState);
-  hs->bank_url = bank_url;
-  hs->account_no = account_no;
-  hs->direction = direction;
+  hs->account_url = account_url;
   hs->start_row_reference = start_row_reference;
   hs->num_results = num_results;
-  hs->ascending = ascending;
-  hs->start_date = GNUNET_TIME_UNIT_FOREVER_ABS;
-  hs->end_date = GNUNET_TIME_UNIT_FOREVER_ABS;
 
   {
     struct TALER_TESTING_Command cmd = {
@@ -1001,4 +755,4 @@ TALER_TESTING_cmd_bank_history (const char *label,
 }
 
 
-/* end of testing_api_cmd_history.c */
+/* end of testing_api_cmd_history_debit.c */
diff --git a/src/bank-lib/testing_api_cmd_reject.c 
b/src/bank-lib/testing_api_cmd_reject.c
deleted file mode 100644
index 01c189f1..00000000
--- a/src/bank-lib/testing_api_cmd_reject.c
+++ /dev/null
@@ -1,223 +0,0 @@
-/*
-  This file is part of TALER
-  Copyright (C) 2018 Taler Systems SA
-
-  TALER is free software; you can redistribute it and/or modify
-  it under the terms of the GNU General Public License as
-  published by the Free Software Foundation; either version 3, or
-  (at your option) any later version.
-
-  TALER is distributed in the hope that it will be useful, but
-  WITHOUT ANY WARRANTY; without even the implied warranty of
-  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-  GNU General Public License for more details.
-
-  You should have received a copy of the GNU General Public
-  License along with TALER; see the file COPYING.  If not, see
-  <http://www.gnu.org/licenses/>
-*/
-
-/**
- * @file bank-lib/testing_api_cmd_reject.c
- * @brief command to check the /reject API from the bank.
- * @author Marcello Stanisci
- */
-
-#include "platform.h"
-#include "taler_json_lib.h"
-#include <gnunet/gnunet_curl_lib.h>
-#include "taler_exchange_service.h"
-#include "taler_testing_lib.h"
-#include "taler_fakebank_lib.h"
-#include "taler_bank_service.h"
-#include "taler_fakebank_lib.h"
-
-
-/**
- * State for a "reject" CMD.
- */
-struct RejectState
-{
-
-  /**
-   * Handle of a ongoing "reject" operation.
-   */
-  struct TALER_BANK_RejectHandle *rh;
-
-  /**
-   * Reference to any command that can offer a wire
-   * transfer "row id" and its credit account so as
-   * to give input data to the "reject" operation.
-   */
-  const char *deposit_reference;
-
-  /**
-   * Base URL of the bank implementing the "reject"
-   * operation.
-   */
-  const char *bank_url;
-};
-
-/**
- * Check that the response code from the "reject" opetation
- * is acceptable, namely it equals "204 No Content".
- *
- * @param cls closure.
- * @param http_status HTTP response code.
- * @param ec taler-specific error code.
- */
-static void
-reject_cb (void *cls,
-           unsigned int http_status,
-           enum TALER_ErrorCode ec)
-{
-  struct TALER_TESTING_Interpreter *is = cls;
-  struct RejectState *rs = is->commands[is->ip].cls;
-
-  rs->rh = NULL;
-  if (MHD_HTTP_NO_CONTENT != http_status)
-  {
-    GNUNET_break (0);
-    fprintf (stderr,
-             "Unexpected response code %u/%d\n",
-             http_status,
-             (int) ec);
-    TALER_TESTING_interpreter_fail (is);
-    return;
-  }
-  TALER_TESTING_interpreter_next (is);
-}
-
-
-/**
- * Cleanup the state of a "reject" CMD, and possibly
- * cancel a pending operation thereof.
- *
- * @param cls closure.
- * @param cmd the command.
- */
-static void
-reject_cleanup (void *cls,
-                const struct TALER_TESTING_Command *cmd)
-{
-  struct RejectState *rs = cls;
-
-  (void) cmd;
-  if (NULL != rs->rh)
-  {
-    TALER_LOG_WARNING ("/reject did not complete\n");
-    TALER_BANK_reject_cancel (rs->rh);
-  }
-  GNUNET_free (rs);
-}
-
-
-/**
- * Run the command.
- *
- * @param cls closure.
- * @param cmd the command to execute.
- * @param is the interpreter state.
- */
-static void
-reject_run (void *cls,
-            const struct TALER_TESTING_Command *cmd,
-            struct TALER_TESTING_Interpreter *is)
-{
-  struct RejectState *rs = cls;
-  const struct TALER_TESTING_Command *deposit_cmd;
-  const uint64_t *credit_account;
-  const uint64_t *row_id;
-  extern struct TALER_BANK_AuthenticationData AUTHS[];
-
-  (void) cmd;
-  deposit_cmd
-    = TALER_TESTING_interpreter_lookup_command (is,
-                                                rs->deposit_reference);
-  if (NULL == deposit_cmd)
-    TALER_TESTING_FAIL (is);
-  GNUNET_assert (GNUNET_OK ==
-                 TALER_TESTING_GET_TRAIT_CREDIT_ACCOUNT (deposit_cmd,
-                                                         &credit_account));
-  GNUNET_assert (GNUNET_OK ==
-                 TALER_TESTING_GET_TRAIT_ROW_ID (deposit_cmd,
-                                                 &row_id));
-  TALER_LOG_INFO ("Account %llu rejects deposit\n",
-                  (unsigned long long) *credit_account);
-  rs->rh = TALER_BANK_reject (is->ctx,
-                              rs->bank_url,
-                              &AUTHS[*credit_account - 1],
-                              *credit_account,
-                              *row_id,
-                              &reject_cb,
-                              is);
-  GNUNET_assert (NULL != rs->rh);
-}
-
-
-/**
- * Offer internal data from a "reject" CMD to other commands.
- *
- * @param cls closure.
- * @param ret[out] result.
- * @param trait name of the trait.
- * @param index index number of the trait to return.
- *
- * @return #GNUNET_OK on success.
- */
-static int
-reject_traits (void *cls,
-               const void **ret,
-               const char *trait,
-               unsigned int index)
-{
-  struct RejectState *rs = cls;
-  struct TALER_TESTING_Trait traits[] = {
-    TALER_TESTING_make_trait_rejected (0, rs->deposit_reference),
-    TALER_TESTING_trait_end ()
-  };
-
-  return TALER_TESTING_get_trait (traits,
-                                  ret,
-                                  trait,
-                                  index);
-}
-
-
-/**
- * Create a "reject" CMD.
- *
- * @param label command label.
- * @param bank_url base URL of the bank implementing the
- *        "reject" operation.
- * @param deposit_reference reference to a command that will
- *        provide a "row id" and credit (bank) account to craft
- *        the "reject" request.
- * @return the command.
- */
-struct TALER_TESTING_Command
-TALER_TESTING_cmd_bank_reject (const char *label,
-                               const char *bank_url,
-                               const char *deposit_reference)
-{
-  struct RejectState *rs;
-
-  rs = GNUNET_new (struct RejectState);
-  rs->bank_url = bank_url;
-  rs->deposit_reference = deposit_reference;
-
-  {
-    struct TALER_TESTING_Command cmd = {
-      .cls = rs,
-      .run = &reject_run,
-      .cleanup = &reject_cleanup,
-      .label = label,
-      .traits = &reject_traits
-    };
-
-    return cmd;
-  }
-}
-
-
-/* end of testing_api_cmd_reject.c */
diff --git a/src/benchmark/taler-exchange-benchmark.c 
b/src/benchmark/taler-exchange-benchmark.c
index 31dbdf15..b931c3c9 100644
--- a/src/benchmark/taler-exchange-benchmark.c
+++ b/src/benchmark/taler-exchange-benchmark.c
@@ -1,6 +1,6 @@
 /*
   This file is part of TALER
-  (C) 2014-2019 Taler Systems SA
+  (C) 2014-2020 Taler Systems SA
 
   TALER is free software; you can redistribute it and/or modify it
   under the terms of the GNU Affero General Public License as
@@ -16,15 +16,13 @@
   along with TALER; see the file COPYING.  If not,
   see <http://www.gnu.org/licenses/>
 */
-
 /**
- * @file merchant/backend/taler-merchant-httpd.c
+ * @file benchmark/taler-exchange-benchmark.c
  * @brief HTTP serving layer intended to perform crypto-work and
  * communication with the exchange
  * @author Marcello Stanisci
  * @author Christian Grothoff
  */
-
 #include "platform.h"
 #include <gnunet/gnunet_util_lib.h>
 #include <microhttpd.h>
@@ -58,23 +56,14 @@ enum BenchmarkError
  */
 #define UNITY_SIZE 6
 
-/**
- * Account number of the merchant.  Fakebank likes any number,
- * the only requirement is that this number then matches the
- * number given when building payto URLs at deposit time.
- */
-#define TALER_TESTING_USER_ACCOUNT_NUMBER 3
-
 #define FIRST_INSTRUCTION -1
 
 #define CMD_TRANSFER_TO_EXCHANGE(label, amount) \
   TALER_TESTING_cmd_fakebank_transfer_retry \
     (TALER_TESTING_cmd_fakebank_transfer (label, amount, \
-                                          exchange_bank_account.details. \
-                                          x_taler_bank.bank_base_url, \
-                                          TALER_TESTING_USER_ACCOUNT_NUMBER, \
-                                          exchange_bank_account.details. \
-                                          x_taler_bank.no, \
+                                          user_bank_account.details.           
                           \
+                                          x_taler_bank.account_base_url, \
+                                          exchange_payto_url, \
                                           "dummy_user", \
                                           "dummy_password", \
                                           "http://example.com/";))
@@ -107,6 +96,11 @@ enum BenchmarkMode
  */
 static struct TALER_Account exchange_bank_account;
 
+/**
+ * Hold information about a user at the bank.
+ */
+static struct TALER_Account user_bank_account;
+
 /**
  * Time snapshot taken right before executing the CMDs.
  */
@@ -168,6 +162,11 @@ static enum BenchmarkMode mode;
  */
 static char *cfg_filename;
 
+/**
+ * payto://-URL of the exchange's bank account.
+ */
+static char *exchange_payto_url;
+
 /**
  * Currency used.
  */
@@ -405,12 +404,12 @@ stop_fakebank (void *cls)
 static void
 launch_fakebank (void *cls)
 {
-  const char *bank_base_url = cls;
+  const char *hostname = cls;
   const char *port;
   long pnum;
   struct TALER_FAKEBANK_Handle *fakebank;
 
-  port = strrchr (bank_base_url,
+  port = strrchr (hostname,
                   (unsigned char) ':');
   if (NULL == port)
     pnum = 80;
@@ -419,7 +418,7 @@ launch_fakebank (void *cls)
   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
               "Starting Fakebank on port %u (%s)\n",
               (unsigned int) pnum,
-              bank_base_url);
+              hostname);
   fakebank = TALER_FAKEBANK_start ((uint16_t) pnum);
   if (NULL == fakebank)
   {
@@ -466,8 +465,7 @@ parallel_benchmark (TALER_TESTING_Main main_cb,
                         NULL == loglev ? "INFO" : loglev,
                         logfile);
       GNUNET_SCHEDULER_run (&launch_fakebank,
-                            exchange_bank_account.details.x_taler_bank.
-                            bank_base_url);
+                            
exchange_bank_account.details.x_taler_bank.hostname);
       exit (0);
     }
     if (-1 == fakebank)
@@ -824,10 +822,36 @@ main (int argc,
     return BAD_CLI_ARG;
   }
 
+  {
+    char *user_payto_url;
+
+    if (GNUNET_OK !=
+        GNUNET_CONFIGURATION_get_value_string
+          (cfg,
+          "benchmark",
+          "user-url",
+          &user_payto_url))
+    {
+      GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
+                                 "benchmark",
+                                 "user-url");
+      return BAD_CONFIG_FILE;
+    }
+    if (TALER_EC_NONE !=
+        TALER_WIRE_payto_to_account (user_payto_url,
+                                     &user_bank_account))
+    {
+      GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                  _ ("Malformed payto:// URL `%s' in configuration\n"),
+                  user_payto_url);
+      GNUNET_free (user_payto_url);
+      return BAD_CONFIG_FILE;
+    }
+    GNUNET_free (user_payto_url);
+  }
 
   {
     const char *bank_details_section;
-    char *exchange_payto_url;
 
     GNUNET_CONFIGURATION_iterate_sections
       (cfg,
@@ -873,7 +897,6 @@ main (int argc,
       GNUNET_free (exchange_payto_url);
       return BAD_CONFIG_FILE;
     }
-    GNUNET_free (exchange_payto_url);
   }
   if ( (MODE_EXCHANGE == mode) || (MODE_BOTH == mode) )
   {
diff --git a/src/exchange-tools/Makefile.am b/src/exchange-tools/Makefile.am
index 64b4cee8..0b9a2d52 100644
--- a/src/exchange-tools/Makefile.am
+++ b/src/exchange-tools/Makefile.am
@@ -23,7 +23,9 @@ taler_wire_SOURCES = \
   taler-wire.c
 taler_wire_LDADD = \
   $(top_builddir)/src/util/libtalerutil.la \
+  $(top_builddir)/src/bank-lib/libtalerbank.la \
   $(top_builddir)/src/wire/libtalerwire.la \
+  -lgnunetcurl \
   -lgnunetutil
 
 taler_exchange_keyup_SOURCES = \
@@ -32,6 +34,7 @@ taler_exchange_keyup_LDADD = \
   $(LIBGCRYPT_LIBS) \
   $(top_builddir)/src/util/libtalerutil.la \
   $(top_builddir)/src/pq/libtalerpq.la \
+  $(top_builddir)/src/bank-lib/libtalerbank.la \
   $(top_builddir)/src/wire/libtalerwire.la \
   $(top_builddir)/src/exchangedb/libtalerexchangedb.la \
   -lgnunetutil $(XLIB)
@@ -44,6 +47,7 @@ taler_exchange_wire_LDADD = \
   $(LIBGCRYPT_LIBS) \
   $(top_builddir)/src/json/libtalerjson.la \
   $(top_builddir)/src/exchangedb/libtalerexchangedb.la \
+  $(top_builddir)/src/bank-lib/libtalerbank.la \
   $(top_builddir)/src/wire/libtalerwire.la \
   $(top_builddir)/src/util/libtalerutil.la \
   -lgnunetjson \
diff --git a/src/exchange-tools/taler-exchange-keyup.c 
b/src/exchange-tools/taler-exchange-keyup.c
index e6e3db0d..f2ec3ca8 100644
--- a/src/exchange-tools/taler-exchange-keyup.c
+++ b/src/exchange-tools/taler-exchange-keyup.c
@@ -1,6 +1,6 @@
 /*
   This file is part of TALER
-  Copyright (C) 2014-2018 Taler Systems SA
+  Copyright (C) 2014-2020 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
@@ -923,17 +923,17 @@ exchange_keys_update_denomkeys ()
  * Sign @a af with @a priv
  *
  * @param[in,out] af fee structure to sign
- * @param wireplugin name of the plugin for which we sign
+ * @param method name of the wire method for which we sign
  * @param priv private key to use for signing
  */
 static void
 sign_af (struct TALER_EXCHANGEDB_AggregateFees *af,
-         const char *wireplugin,
+         const char *method,
          const struct GNUNET_CRYPTO_EddsaPrivateKey *priv)
 {
   struct TALER_MasterWireFeePS wf;
 
-  TALER_EXCHANGEDB_fees_2_wf (wireplugin,
+  TALER_EXCHANGEDB_fees_2_wf (method,
                               af,
                               &wf);
   GNUNET_assert (GNUNET_OK ==
@@ -1101,28 +1101,15 @@ create_wire_fee_by_account (void *cls,
                             const struct TALER_EXCHANGEDB_AccountInfo *ai)
 {
   int *ret = cls;
-  struct TALER_WIRE_Plugin *plugin;
 
   if (GNUNET_NO == ai->credit_enabled)
     return;
-  plugin = TALER_WIRE_plugin_load (kcfg,
-                                   ai->plugin_name);
-  if (NULL == plugin)
-  {
-    fprintf (stderr,
-             "Failed to load wire plugin `%s' configured for account `%s'\n",
-             ai->plugin_name,
-             ai->section_name);
-    *ret = GNUNET_SYSERR;
-    return;
-  }
   /* We may call this function repeatedly for the same method
      if there are multiple accounts with plugins using the
      same method, but except for some minor performance loss,
      this is harmless. */
   create_wire_fee_for_method (ret,
-                              plugin->method);
-  TALER_WIRE_plugin_unload (plugin);
+                              ai->method);
 }
 
 
diff --git a/src/exchange-tools/taler-wire.c b/src/exchange-tools/taler-wire.c
index 12963324..5e3c18a6 100644
--- a/src/exchange-tools/taler-wire.c
+++ b/src/exchange-tools/taler-wire.c
@@ -22,11 +22,10 @@
  * @author Marcello Stanisci
  * @author Christian Grothoff
  */
-
 #include <platform.h>
 #include <gnunet/gnunet_util_lib.h>
 #include "taler_util.h"
-#include "taler_wire_lib.h"
+#include "taler_bank_service.h"
 
 /**
  * If set to #GNUNET_YES, then we'll ask the bank for a list
@@ -36,16 +35,11 @@
 static int history;
 
 /**
- * If set to GNUNET_YES, then we'll ask the bank to execute a
+ * If set to #GNUNET_YES, then we'll ask the bank to execute a
  * wire transfer.
  */
 static int transfer;
 
-/**
- * Name of the wire plugin to use with the bank.
- */
-static char *plugin_name;
-
 /**
  * Global return code.
  */
@@ -59,11 +53,9 @@ static unsigned int global_ret = 1;
 static char *amount;
 
 /**
- * Base32 encoding of a transaction ID.  When asking the
- * bank for a transaction history, all the results will
- * have a transaction ID settled *after* this one.
+ * Starting row.
  */
-static char *since_when;
+static unsigned long long start_row;
 
 /**
  * Which config section has the credentials to access the bank.
@@ -77,19 +69,29 @@ static char *account_section;
 static char *destination_account_url;
 
 /**
- * Handle for the wire transfer preparation task.
+ * Handle for executing the wire transfer.
  */
-static struct TALER_WIRE_PrepareHandle *ph;
+static struct TALER_BANK_WireExecuteHandle *eh;
 
 /**
- * Wire plugin handle.
+ * Handle to ongoing history operation.
  */
-static struct TALER_WIRE_Plugin *plugin_handle;
+static struct TALER_BANK_CreditHistoryHandle *hh;
 
 /**
- * Handle to ongoing history operation.
+ * For authentication.
+ */
+static struct TALER_BANK_AuthenticationData auth;
+
+/**
+ * Handle to the context for interacting with the bank.
  */
-static struct TALER_WIRE_HistoryHandle *hh;
+static struct GNUNET_CURL_Context *ctx;
+
+/**
+ * Scheduler context for running the @e ctx.
+ */
+static struct GNUNET_CURL_RescheduleContext *rc;
 
 
 /**
@@ -108,16 +110,16 @@ static struct TALER_WIRE_HistoryHandle *hh;
  */
 static int
 history_cb (void *cls,
+            unsigned int http_status,
             enum TALER_ErrorCode ec,
-            enum TALER_BANK_Direction dir,
-            const void *row_off,
-            size_t row_off_size,
-            const struct TALER_WIRE_TransferDetails *details)
+            uint64_t serial_id,
+            const struct TALER_BANK_CreditDetails *details,
+            const json_t *json)
 {
-  char *row_off_enc;
-
   (void) cls;
-  if (TALER_BANK_DIRECTION_NONE == dir)
+  (void) ec;
+  (void) http_status;
+  if (NULL == details)
   {
     fprintf (stdout,
              "End of transactions list.\n");
@@ -126,15 +128,9 @@ history_cb (void *cls,
     return GNUNET_NO;
   }
 
-  row_off_enc = GNUNET_STRINGS_data_to_string_alloc (row_off,
-                                                     row_off_size);
-  /* Give more details on screen (??) */
   fprintf (stdout,
-           "%s\n",
-           row_off_enc);
-
-  GNUNET_free (row_off_enc);
-
+           "%llu\n",
+           (unsigned long long) serial_id);
   return GNUNET_OK;
 }
 
@@ -142,71 +138,36 @@ history_cb (void *cls,
 /**
  * Callback that processes the outcome of a wire transfer
  * execution.
+ *
+ * @param cls closure
+ * @param response_code HTTP status code
+ * @param ec taler error code
+ * @param row_id unique ID of the wire transfer in the bank's records
+ * @param timestamp when did the transaction go into effect
  */
 static void
 confirmation_cb (void *cls,
-                 int success,
-                 const void *row_id,
-                 size_t row_id_size,
-                 const char *emsg)
+                 unsigned int response_code,
+                 enum TALER_ErrorCode ec,
+                 uint64_t row_id,
+                 struct GNUNET_TIME_Absolute timestamp)
 {
-  if (GNUNET_YES != success)
+  if (MHD_HTTP_OK != response_code)
   {
     fprintf (stderr,
-             "The wire transfer didn't execute correctly.\n");
-    GNUNET_assert (NULL != emsg);
-    fprintf (stderr,
-             "%s",
-             emsg);
+             "The wire transfer didn't execute correctly (%d).\n",
+             ec);
     GNUNET_SCHEDULER_shutdown ();
     return;
   }
 
   fprintf (stdout,
            "Wire transfer executed successfully.\n");
-
   global_ret = 0;
   GNUNET_SCHEDULER_shutdown ();
 }
 
 
-/**
- * Takes prepared blob and executes the wire-transfer.
- *
- * @param cls NULL.
- * @param buf prepared wire transfer data.
- * @param buf_size size of the prepared wire transfer data.
- */
-static void
-prepare_cb (void *cls,
-            const char *buf,
-            size_t buf_size)
-{
-  struct TALER_WIRE_ExecuteHandle *eh;
-
-  if (NULL == (eh = plugin_handle->execute_wire_transfer
-                      (plugin_handle->cls,
-                      buf,
-                      buf_size,
-                      confirmation_cb,
-                      NULL)))
-  {
-    fprintf (stderr,
-             "Could not execute the wire transfer\n");
-
-    plugin_handle->prepare_wire_transfer_cancel
-      (plugin_handle->cls,
-      ph);
-
-    plugin_handle->execute_wire_transfer_cancel
-      (plugin_handle->cls,
-      eh);
-
-    GNUNET_SCHEDULER_shutdown ();
-  }
-}
-
-
 /**
  * Ask the bank to execute a wire transfer.
  */
@@ -215,6 +176,8 @@ execute_wire_transfer ()
 {
   struct TALER_Amount a;
   struct TALER_WireTransferIdentifierRawP wtid;
+  void *buf;
+  size_t buf_size;
 
   if (NULL == amount)
   {
@@ -223,7 +186,6 @@ execute_wire_transfer ()
     GNUNET_SCHEDULER_shutdown ();
     return;
   }
-
   if (GNUNET_OK != TALER_string_to_amount (amount,
                                            &a))
   {
@@ -240,19 +202,25 @@ execute_wire_transfer ()
     GNUNET_SCHEDULER_shutdown ();
     return;
   }
-  if (NULL == (ph = plugin_handle->prepare_wire_transfer
-                      (plugin_handle->cls,
-                      account_section,
-                      destination_account_url,
-                      &a,
-                      "http://exchange.example.com/";,
-                      &wtid, /* Any value will do.  */
-                      prepare_cb,
-                      NULL)))
+  TALER_BANK_prepare_wire_transfer (destination_account_url,
+                                    &a,
+                                    "http://exchange.example.com/";,
+                                    &wtid,
+                                    &buf,
+                                    &buf_size);
+  eh = TALER_BANK_execute_wire_transfer (ctx,
+                                         destination_account_url,
+                                         &auth,
+                                         buf,
+                                         buf_size,
+                                         &confirmation_cb,
+                                         NULL);
+  if (NULL == eh)
   {
     fprintf (stderr,
-             "Could not prepare the wire transfer\n");
+             "Could not execute the wire transfer\n");
     GNUNET_SCHEDULER_shutdown ();
+    return;
   }
 }
 
@@ -264,30 +232,14 @@ execute_wire_transfer ()
 static void
 execute_history ()
 {
-  size_t bin_len = 0;
-  void *since_when_bin = NULL;
-
-  if (NULL != since_when)
-  {
-    bin_len = (strlen (since_when) * 5) / 8;
-
-    since_when_bin = GNUNET_malloc (bin_len);
-    GNUNET_assert
-      (GNUNET_OK == GNUNET_STRINGS_string_to_data
-        (since_when,
-        strlen (since_when),
-        since_when_bin,
-        bin_len));
-  }
-
-  if (NULL == (hh = plugin_handle->get_history (plugin_handle->cls,
-                                                account_section,
-                                                TALER_BANK_DIRECTION_BOTH,
-                                                since_when_bin,
-                                                bin_len,
-                                                -10,
-                                                &history_cb,
-                                                NULL)))
+  hh = TALER_BANK_credit_history (ctx,
+                                  destination_account_url,
+                                  &auth,
+                                  start_row,
+                                  -10,
+                                  &history_cb,
+                                  NULL);
+  if (NULL == hh)
   {
     fprintf (stderr,
              "Could not request the transaction history.\n");
@@ -305,19 +257,27 @@ execute_history ()
 static void
 do_shutdown (void *cls)
 {
+  if (NULL != ctx)
+  {
+    GNUNET_CURL_fini (ctx);
+    ctx = NULL;
+  }
+  if (NULL != rc)
+  {
+    GNUNET_CURL_gnunet_rc_destroy (rc);
+    rc = NULL;
+  }
   if (NULL != hh)
   {
-    plugin_handle->get_history_cancel (plugin_handle->cls,
-                                       hh);
+    TALER_BANK_credit_history_cancel (hh);
     hh = NULL;
   }
-  if (NULL != ph)
+  if (NULL != eh)
   {
-    plugin_handle->prepare_wire_transfer_cancel (plugin_handle->cls,
-                                                 ph);
-    ph = NULL;
+    TALER_BANK_execute_wire_transfer_cancel (eh);
+    eh = NULL;
   }
-  TALER_WIRE_plugin_unload (plugin_handle);
+  TALER_BANK_auth_free (&auth);
 }
 
 
@@ -342,27 +302,18 @@ run (void *cls,
              "The option: -s ACCOUNT-SECTION, is mandatory.\n");
     return;
   }
-
-  if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_string
-        (cfg,
-        account_section,
-        "plugin",
-        &plugin_name))
+  if (GNUNET_OK !=
+      TALER_BANK_auth_parse_cfg (cfg,
+                                 account_section,
+                                 &auth))
   {
     fprintf (stderr,
-             "Could not find the 'plugin' value under %s\n",
+             "Authentication information not found in configuration section 
`%s'\n",
              account_section);
+    GNUNET_SCHEDULER_shutdown ();
     return;
   }
 
-  plugin_handle = TALER_WIRE_plugin_load (cfg,
-                                          plugin_name);
-  if (NULL == plugin_handle)
-  {
-    fprintf (stderr,
-             "Could not load the wire plugin\n");
-    return;
-  }
 
   if (GNUNET_YES == history)
     execute_history ();
@@ -372,6 +323,14 @@ run (void *cls,
     fprintf (stderr,
              "Please give either --history/-H or --transfer/t\n");
 
+  ctx = GNUNET_CURL_init (&GNUNET_CURL_gnunet_scheduler_reschedule,
+                          &rc);
+  rc = GNUNET_CURL_gnunet_rc_create (ctx);
+  if (NULL == ctx)
+  {
+    GNUNET_break (0);
+    return;
+  }
   GNUNET_SCHEDULER_add_shutdown (&do_shutdown,
                                  NULL);
 }
@@ -400,22 +359,23 @@ main (int argc,
                                "transfer",
                                "Execute a wire transfer.",
                                &transfer),
-    GNUNET_GETOPT_option_string ('w',
-                                 "since-when",
-                                 "SW",
-                                 "When asking the bank for"
-                                 " transactions history, this"
-                                 " option commands that all the"
-                                 " results should have IDs settled"
-                                 " after SW.  If not given, then"
-                                 " the 10 youngest transactions"
-                                 " are returned.",
-                                 &since_when),
-    GNUNET_GETOPT_option_string ('s',
-                                 "section",
-                                 "ACCOUNT-SECTION",
-                                 "Which config section has the credentials to 
access the bank.  Mandatory.\n",
-                                 &account_section),
+    GNUNET_GETOPT_option_ulong ('w',
+                                "since-when",
+                                "SW",
+                                "When asking the bank for"
+                                " transactions history, this"
+                                " option commands that all the"
+                                " results should have IDs settled"
+                                " after SW.  If not given, then"
+                                " the 10 youngest transactions"
+                                " are returned.",
+                                &start_row),
+    GNUNET_GETOPT_option_mandatory
+      (GNUNET_GETOPT_option_string ('s',
+                                    "section",
+                                    "ACCOUNT-SECTION",
+                                    "Which config section has the credentials 
to access the bank.  Mandatory.\n",
+                                    &account_section)),
     GNUNET_GETOPT_option_string ('a',
                                  "amount",
                                  "AMOUNT",
diff --git a/src/exchange/Makefile.am b/src/exchange/Makefile.am
index 3453683a..b08c85c6 100644
--- a/src/exchange/Makefile.am
+++ b/src/exchange/Makefile.am
@@ -29,9 +29,11 @@ taler_exchange_aggregator_LDADD = \
   $(LIBGCRYPT_LIBS) \
   $(top_builddir)/src/json/libtalerjson.la \
   $(top_builddir)/src/util/libtalerutil.la \
+  $(top_builddir)/src/bank-lib/libtalerbank.la \
   $(top_builddir)/src/wire/libtalerwire.la \
   $(top_builddir)/src/exchangedb/libtalerexchangedb.la \
   -ljansson \
+  -lgnunetcurl \
   -lgnunetutil
 
 taler_exchange_wirewatch_SOURCES = \
@@ -40,9 +42,11 @@ taler_exchange_wirewatch_LDADD = \
   $(LIBGCRYPT_LIBS) \
   $(top_builddir)/src/json/libtalerjson.la \
   $(top_builddir)/src/util/libtalerutil.la \
+  $(top_builddir)/src/bank-lib/libtalerbank.la \
   $(top_builddir)/src/wire/libtalerwire.la \
   $(top_builddir)/src/exchangedb/libtalerexchangedb.la \
   -ljansson \
+  -lgnunetcurl \
   -lgnunetutil
 
 taler_exchange_httpd_SOURCES = \
@@ -66,6 +70,7 @@ taler_exchange_httpd_SOURCES = \
   taler-exchange-httpd_validation.c taler-exchange-httpd_validation.h
 taler_exchange_httpd_LDADD = \
   $(LIBGCRYPT_LIBS) \
+  $(top_builddir)/src/bank-lib/libtalerbank.la \
   $(top_builddir)/src/wire/libtalerwire.la \
   $(top_builddir)/src/mhd/libtalermhd.la \
   $(top_builddir)/src/json/libtalerjson.la \
diff --git a/src/exchange/taler-exchange-aggregator.c 
b/src/exchange/taler-exchange-aggregator.c
index 71a3efd7..2704f591 100644
--- a/src/exchange/taler-exchange-aggregator.c
+++ b/src/exchange/taler-exchange-aggregator.c
@@ -1,6 +1,6 @@
 /*
   This file is part of TALER
-  Copyright (C) 2016-2018 Taler Systems SA
+  Copyright (C) 2016-2020 Taler Systems SA
 
   TALER is free software; you can redistribute it and/or modify it under the
   terms of the GNU Affero General Public License as published by the Free 
Software
@@ -26,6 +26,7 @@
 #include "taler_exchangedb_lib.h"
 #include "taler_exchangedb_plugin.h"
 #include "taler_json_lib.h"
+#include "taler_bank_service.h"
 #include "taler_wire_lib.h"
 
 
@@ -45,9 +46,14 @@ struct WireAccount
   struct WireAccount *prev;
 
   /**
-   * Handle to the plugin.
+   * Account information.
    */
-  struct TALER_WIRE_Plugin *wire_plugin;
+  struct TALER_Account account;
+
+  /**
+   * Authentication data.
+   */
+  struct TALER_BANK_AuthenticationData auth;
 
   /**
    * Wire transfer fee structure.
@@ -59,6 +65,11 @@ struct WireAccount
    */
   char *section_name;
 
+  /**
+   * Name of the wire method underlying the account.
+   */
+  char *method;
+
 };
 
 
@@ -77,7 +88,7 @@ struct WirePrepareData
   /**
    * Wire execution handle.
    */
-  struct TALER_WIRE_ExecuteHandle *eh;
+  struct TALER_BANK_WireExecuteHandle *eh;
 
   /**
    * Wire plugin used for this preparation.
@@ -187,10 +198,6 @@ struct AggregationUnit
  */
 struct CloseTransferContext
 {
-  /**
-   * Handle for preparing the wire transfer.
-   */
-  struct TALER_WIRE_PrepareHandle *ph;
 
   /**
    * Our database session.
@@ -262,6 +269,16 @@ static struct WirePrepareData *wpd;
  */
 static struct AggregationUnit *au;
 
+/**
+ * Handle to the context for interacting with the bank.
+ */
+static struct GNUNET_CURL_Context *ctx;
+
+/**
+ * Scheduler context for running the @e ctx.
+ */
+static struct GNUNET_CURL_RescheduleContext *rc;
+
 /**
  * Value to return from main(). #GNUNET_OK on success, #GNUNET_SYSERR
  * on serious errors.
@@ -339,7 +356,7 @@ update_fees (struct WireAccount *wa,
     return GNUNET_DB_STATUS_SUCCESS_ONE_RESULT;
   /* Let's try to load it from disk... */
   wa->af = TALER_EXCHANGEDB_fees_read (cfg,
-                                       wa->wire_plugin->method);
+                                       wa->method);
   advance_fees (wa,
                 now);
   for (struct TALER_EXCHANGEDB_AggregateFees *p = wa->af;
@@ -348,7 +365,7 @@ update_fees (struct WireAccount *wa,
   {
     qs = db_plugin->insert_wire_fee (db_plugin->cls,
                                      session,
-                                     wa->wire_plugin->method,
+                                     wa->method,
                                      p->start_date,
                                      p->end_date,
                                      &p->wire_fee,
@@ -365,7 +382,7 @@ update_fees (struct WireAccount *wa,
     return GNUNET_DB_STATUS_SUCCESS_ONE_RESULT;
   GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
               "Failed to find current wire transfer fees for `%s'\n",
-              wa->wire_plugin->method);
+              wa->method);
   return GNUNET_DB_STATUS_SUCCESS_NO_RESULTS;
 }
 
@@ -381,7 +398,7 @@ find_account_by_method (const char *method)
 {
   for (struct WireAccount *wa = wa_head; NULL != wa; wa = wa->next)
     if (0 == strcmp (method,
-                     wa->wire_plugin->method))
+                     wa->method))
       return wa;
   return NULL;
 }
@@ -431,13 +448,40 @@ add_account_cb (void *cls,
   if (GNUNET_YES != ai->debit_enabled)
     return; /* not enabled for us, skip */
   wa = GNUNET_new (struct WireAccount);
-  wa->wire_plugin = TALER_WIRE_plugin_load (cfg,
-                                            ai->plugin_name);
-  if (NULL == wa->wire_plugin)
+  if (GNUNET_OK !=
+      GNUNET_CONFIGURATION_get_value_string (cfg,
+                                             ai->section_name,
+                                             "METHOD",
+                                             &wa->method))
   {
-    fprintf (stderr,
-             "Failed to load wire plugin for `%s'\n",
-             ai->plugin_name);
+    GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
+                               ai->section_name,
+                               "METHOD");
+    GNUNET_free (wa);
+    return;
+  }
+  if (GNUNET_OK !=
+      TALER_BANK_auth_parse_cfg (cfg,
+                                 ai->section_name,
+                                 &wa->auth))
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
+                "Failed to load account `%s'\n",
+                ai->section_name);
+    GNUNET_free (wa->method);
+    GNUNET_free (wa);
+    return;
+  }
+  if (GNUNET_OK !=
+      TALER_BANK_account_parse_cfg (cfg,
+                                    ai->section_name,
+                                    &wa->account))
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
+                "Failed to load account `%s'\n",
+                ai->section_name);
+    TALER_BANK_auth_free (&wa->auth);
+    GNUNET_free (wa->method);
     GNUNET_free (wa);
     return;
   }
@@ -476,6 +520,16 @@ static void
 shutdown_task (void *cls)
 {
   (void) cls;
+  if (NULL != ctx)
+  {
+    GNUNET_CURL_fini (ctx);
+    ctx = NULL;
+  }
+  if (NULL != rc)
+  {
+    GNUNET_CURL_gnunet_rc_destroy (rc);
+    rc = NULL;
+  }
   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
               "Running shutdown\n");
   if (NULL != task)
@@ -487,9 +541,7 @@ shutdown_task (void *cls)
   {
     if (NULL != wpd->eh)
     {
-      wpd->wa->wire_plugin->execute_wire_transfer_cancel (
-        wpd->wa->wire_plugin->cls,
-        wpd->eh);
+      TALER_BANK_execute_wire_transfer_cancel (wpd->eh);
       wpd->eh = NULL;
     }
     db_plugin->rollback (db_plugin->cls,
@@ -499,23 +551,12 @@ shutdown_task (void *cls)
   }
   if (NULL != au)
   {
-    if (NULL != au->ph)
-    {
-      au->wa->wire_plugin->prepare_wire_transfer_cancel (
-        au->wa->wire_plugin->cls,
-        au->ph);
-      au->ph = NULL;
-    }
     db_plugin->rollback (db_plugin->cls,
                          au->session);
     cleanup_au ();
   }
   if (NULL != ctc)
   {
-    ctc->wa->wire_plugin->prepare_wire_transfer_cancel (
-      ctc->wa->wire_plugin->cls,
-      ctc->ph);
-    ctc->ph = NULL;
     db_plugin->rollback (db_plugin->cls,
                          ctc->session);
     GNUNET_free (ctc->method);
@@ -532,9 +573,11 @@ shutdown_task (void *cls)
       GNUNET_CONTAINER_DLL_remove (wa_head,
                                    wa_tail,
                                    wa);
-      TALER_WIRE_plugin_unload (wa->wire_plugin);
+      TALER_WIRE_account_free (&wa->account);
+      TALER_BANK_auth_free (&wa->auth);
       TALER_EXCHANGEDB_fees_free (wa->af);
       GNUNET_free (wa->section_name);
+      GNUNET_free (wa->method);
       GNUNET_free (wa);
     }
   }
@@ -921,20 +964,6 @@ aggregate_cb (void *cls,
 }
 
 
-/**
- * Function to be called with the prepared transfer data
- * when running an aggregation on a merchant.
- *
- * @param cls closure with the `struct AggregationUnit`
- * @param buf transaction data to persist, NULL on error
- * @param buf_size number of bytes in @a buf, 0 on error
- */
-static void
-prepare_cb (void *cls,
-            const char *buf,
-            size_t buf_size);
-
-
 /**
  * Main work function that finds and triggers transfers for reserves
  * closures.
@@ -988,83 +1017,6 @@ commit_or_warn (struct TALER_EXCHANGEDB_Session *session)
 }
 
 
-/**
- * Function to be called with the prepared transfer data
- * when closing a reserve.
- *
- * @param cls closure with a `struct CloseTransferContext`
- * @param buf transaction data to persist, NULL on error
- * @param buf_size number of bytes in @a buf, 0 on error
- */
-static void
-prepare_close_cb (void *cls,
-                  const char *buf,
-                  size_t buf_size)
-{
-  enum GNUNET_DB_QueryStatus qs;
-
-  GNUNET_assert (cls == ctc);
-
-  GNUNET_log (GNUNET_ERROR_TYPE_INFO,
-              "Prepared for reserve closing\n");
-  ctc->ph = NULL;
-  if (NULL == buf)
-  {
-    GNUNET_break (0); /* why? how to best recover? */
-    db_plugin->rollback (db_plugin->cls,
-                         ctc->session);
-    /* start again */
-    GNUNET_free (ctc->method);
-    GNUNET_free (ctc);
-    ctc = NULL;
-    task = GNUNET_SCHEDULER_add_now (&run_aggregation,
-                                     NULL);
-    return;
-  }
-
-  /* Commit our intention to execute the wire transfer! */
-  qs = db_plugin->wire_prepare_data_insert (db_plugin->cls,
-                                            ctc->session,
-                                            ctc->method,
-                                            buf,
-                                            buf_size);
-  if (GNUNET_DB_STATUS_HARD_ERROR == qs)
-  {
-    GNUNET_break (0);
-    db_plugin->rollback (db_plugin->cls,
-                         ctc->session);
-    global_ret = GNUNET_SYSERR;
-    GNUNET_SCHEDULER_shutdown ();
-    GNUNET_free (ctc->method);
-    GNUNET_free (ctc);
-    ctc = NULL;
-    return;
-  }
-  if (GNUNET_DB_STATUS_SOFT_ERROR == qs)
-  {
-    db_plugin->rollback (db_plugin->cls,
-                         ctc->session);
-    /* start again */
-    task = GNUNET_SCHEDULER_add_now (&run_aggregation,
-                                     NULL);
-    GNUNET_free (ctc->method);
-    GNUNET_free (ctc);
-    ctc = NULL;
-    return;
-  }
-
-  /* finally commit */
-  (void) commit_or_warn (ctc->session);
-  GNUNET_free (ctc->method);
-  GNUNET_free (ctc);
-  ctc = NULL;
-  GNUNET_log (GNUNET_ERROR_TYPE_INFO,
-              "Reserve closure committed, running transfer\n");
-  task = GNUNET_SCHEDULER_add_now (&run_transfers,
-                                   NULL);
-}
-
-
 /**
  * Closure for #expired_reserve_cb().
  */
@@ -1113,6 +1065,8 @@ expired_reserve_cb (void *cls,
   int ret;
   enum GNUNET_DB_QueryStatus qs;
   struct WireAccount *wa;
+  void *buf;
+  size_t buf_size;
 
   /* NOTE: potential optimization: use custom SQL API to not
      fetch this: */
@@ -1121,7 +1075,7 @@ expired_reserve_cb (void *cls,
   now = GNUNET_TIME_absolute_get ();
   (void) GNUNET_TIME_round_abs (&now);
 
-  /* lookup wire plugin */
+  /* lookup account we should use */
   wa = find_account_by_url (account_details);
   if (NULL == wa)
   {
@@ -1161,6 +1115,18 @@ expired_reserve_cb (void *cls,
                    TALER_amount_get_zero (left->currency,
                                           &amount_without_fee));
   }
+  /* round down to enable transfer */
+  if (GNUNET_SYSERR ==
+      TALER_WIRE_amount_round (&amount_without_fee))
+  {
+    GNUNET_break (0);
+    global_ret = GNUNET_SYSERR;
+    GNUNET_SCHEDULER_shutdown ();
+    return GNUNET_DB_STATUS_HARD_ERROR;
+  }
+  if ( (0 == amount_without_fee.value) &&
+       (0 == amount_without_fee.fraction) )
+    ret = GNUNET_NO;
 
   /* NOTE: sizeof (*reserve_pub) == sizeof (wtid) right now, but to
      be future-compatible, we use the memset + min construction */
@@ -1171,61 +1137,23 @@ expired_reserve_cb (void *cls,
           reserve_pub,
           GNUNET_MIN (sizeof (wtid),
                       sizeof (*reserve_pub)));
-
-  qs = db_plugin->insert_reserve_closed (db_plugin->cls,
-                                         session,
-                                         reserve_pub,
-                                         now,
-                                         account_details,
-                                         &wtid,
-                                         left,
-                                         closing_fee);
-
+  if (GNUNET_SYSERR != ret)
+    qs = db_plugin->insert_reserve_closed (db_plugin->cls,
+                                           session,
+                                           reserve_pub,
+                                           now,
+                                           account_details,
+                                           &wtid,
+                                           left,
+                                           closing_fee);
+  else
+    ret = GNUNET_DB_STATUS_HARD_ERROR;
   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
               "Closing reserve %s over %s (%d, %d)\n",
               TALER_B2S (reserve_pub),
               TALER_amount2s (left),
               ret,
               qs);
-  if ( (GNUNET_OK == ret) &&
-       (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT == qs) )
-  {
-    /* success, perform wire transfer */
-    if (GNUNET_SYSERR ==
-        wa->wire_plugin->amount_round (wa->wire_plugin->cls,
-                                       &amount_without_fee))
-    {
-      GNUNET_break (0);
-      global_ret = GNUNET_SYSERR;
-      GNUNET_SCHEDULER_shutdown ();
-      return GNUNET_DB_STATUS_HARD_ERROR;
-    }
-    ctc = GNUNET_new (struct CloseTransferContext);
-    ctc->wa = wa;
-    ctc->session = session;
-    ctc->method = TALER_WIRE_payto_get_method (account_details);
-    ctc->ph
-      = wa->wire_plugin->prepare_wire_transfer (wa->wire_plugin->cls,
-                                                wa->section_name,
-                                                account_details,
-                                                &amount_without_fee,
-                                                exchange_base_url,
-                                                &wtid,
-                                                &prepare_close_cb,
-                                                ctc);
-    if (NULL == ctc->ph)
-    {
-      GNUNET_break (0);
-      global_ret = GNUNET_SYSERR;
-      GNUNET_SCHEDULER_shutdown ();
-      GNUNET_free (ctc->method);
-      GNUNET_free (ctc);
-      ctc = NULL;
-      return GNUNET_DB_STATUS_HARD_ERROR;
-    }
-    erc->async_cont = GNUNET_YES;
-    return GNUNET_DB_STATUS_SUCCESS_ONE_RESULT;
-  }
   /* Check for hard failure */
   if ( (GNUNET_SYSERR == ret) ||
        (GNUNET_DB_STATUS_HARD_ERROR == qs) )
@@ -1235,10 +1163,59 @@ expired_reserve_cb (void *cls,
     GNUNET_SCHEDULER_shutdown ();
     return GNUNET_DB_STATUS_HARD_ERROR;
   }
-  /* Reserve balance was almost zero OR soft error */
-  GNUNET_log (GNUNET_ERROR_TYPE_INFO,
-              "Reserve was virtually empty, moving on\n");
-  return qs;
+  if ( (GNUNET_OK != ret) ||
+       (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != qs) )
+  {
+    /* Reserve balance was almost zero OR soft error */
+    GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+                "Reserve was virtually empty, moving on\n");
+    (void) commit_or_warn (ctc->session);
+    GNUNET_free (ctc->method);
+    GNUNET_free (ctc);
+    ctc = NULL;
+    task = GNUNET_SCHEDULER_add_now (&run_transfers,
+                                     NULL);
+    return qs;
+  }
+
+  /* success, perform wire transfer */
+  ctc = GNUNET_new (struct CloseTransferContext);
+  ctc->wa = wa;
+  ctc->session = session;
+  ctc->method = TALER_WIRE_payto_get_method (account_details);
+  TALER_BANK_prepare_wire_transfer (account_details,
+                                    &amount_without_fee,
+                                    exchange_base_url,
+                                    &wtid,
+                                    &buf,
+                                    &buf_size);
+  /* Commit our intention to execute the wire transfer! */
+  qs = db_plugin->wire_prepare_data_insert (db_plugin->cls,
+                                            ctc->session,
+                                            ctc->method,
+                                            buf,
+                                            buf_size);
+  GNUNET_free (buf);
+  if (GNUNET_DB_STATUS_HARD_ERROR == qs)
+  {
+    GNUNET_break (0);
+    GNUNET_free (ctc->method);
+    GNUNET_free (ctc);
+    ctc = NULL;
+    return GNUNET_DB_STATUS_HARD_ERROR;
+  }
+  if (GNUNET_DB_STATUS_SOFT_ERROR == qs)
+  {
+    /* start again */
+    GNUNET_free (ctc->method);
+    GNUNET_free (ctc);
+    ctc = NULL;
+    return GNUNET_DB_STATUS_SUCCESS_NO_RESULTS;
+  }
+  erc->async_cont = GNUNET_YES;
+  task = GNUNET_SCHEDULER_add_now (&run_transfers,
+                                   NULL);
+  return GNUNET_DB_STATUS_SUCCESS_ONE_RESULT;
 }
 
 
@@ -1344,6 +1321,8 @@ run_aggregation (void *cls)
   struct TALER_EXCHANGEDB_Session *session;
   enum GNUNET_DB_QueryStatus qs;
   const struct GNUNET_SCHEDULER_TaskContext *tc;
+  void *buf;
+  size_t buf_size;
 
   (void) cls;
   task = NULL;
@@ -1470,8 +1449,7 @@ run_aggregation (void *cls)
                                &au->total_amount,
                                &au->wire_fee)) ||
        (GNUNET_SYSERR ==
-        au->wa->wire_plugin->amount_round (au->wa->wire_plugin->cls,
-                                           &au->final_amount)) ||
+        TALER_WIRE_amount_round (&au->final_amount)) ||
        ( (0 == au->final_amount.value) &&
          (0 == au->final_amount.fraction) ) )
   {
@@ -1555,70 +1533,26 @@ run_aggregation (void *cls)
     char *url;
 
     url = TALER_JSON_wire_to_payto (au->wire);
-    au->ph = au->wa->wire_plugin->prepare_wire_transfer (
-      au->wa->wire_plugin->cls,
-      au->wa->section_name,
-      url,
-      &au->final_amount,
-      exchange_base_url,
-      &au->wtid,
-      &prepare_cb,
-      au);
+    TALER_BANK_prepare_wire_transfer (url,
+                                      &au->final_amount,
+                                      exchange_base_url,
+                                      &au->wtid,
+                                      &buf,
+                                      &buf_size);
     GNUNET_free (url);
   }
-  if (NULL == au->ph)
-  {
-    /* something went very wrong, likely bad configuration,
-       abort */
-    db_plugin->rollback (db_plugin->cls,
-                         session);
-    cleanup_au ();
-    GNUNET_SCHEDULER_shutdown ();
-    return;
-  }
-  /* otherwise we continue with #prepare_cb(), see below */
-}
-
-
-/**
- * Function to be called with the prepared transfer data.
- *
- * @param cls NULL
- * @param buf transaction data to persist, NULL on error
- * @param buf_size number of bytes in @a buf, 0 on error
- */
-static void
-prepare_cb (void *cls,
-            const char *buf,
-            size_t buf_size)
-{
-  struct TALER_EXCHANGEDB_Session *session = au->session;
-  enum GNUNET_DB_QueryStatus qs;
-
-  (void) cls;
   GNUNET_free_non_null (au->additional_rows);
   au->additional_rows = NULL;
-  if (NULL == buf)
-  {
-    GNUNET_break (0); /* why? how to best recover? */
-    db_plugin->rollback (db_plugin->cls,
-                         session);
-    /* start again */
-    task = GNUNET_SCHEDULER_add_now (&run_aggregation,
-                                     NULL);
-    cleanup_au ();
-    return;
-  }
-
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
               "Storing %u bytes of wire prepare data\n",
               (unsigned int) buf_size);
   /* Commit our intention to execute the wire transfer! */
   qs = db_plugin->wire_prepare_data_insert (db_plugin->cls,
                                             session,
-                                            au->wa->wire_plugin->method,
+                                            au->wa->method,
                                             buf,
                                             buf_size);
+  GNUNET_free (buf);
   /* Commit the WTID data to 'wire_out' to finally satisfy aggregation
      table constraints */
   if (qs >= 0)
@@ -1691,29 +1625,30 @@ prepare_cb (void *cls,
  * Function called with the result from the execute step.
  *
  * @param cls NULL
- * @param success #GNUNET_OK on success, #GNUNET_SYSERR on failure
- * @param serial_id unique ID of the wire transfer in the bank's records; 
UINT64_MAX on error
- * @param emsg NULL on success, otherwise an error message
+ * @param http_status_code #MHD_HTTP_OK on success
+ * @param ec taler error code
+ * @param row_id unique ID of the wire transfer in the bank's records
+ * @param wire_timestamp when did the transfer happen
  */
 static void
 wire_confirm_cb (void *cls,
-                 int success,
-                 const void *row_id,
-                 size_t row_id_size,
-                 const char *emsg)
+                 unsigned int http_status_code,
+                 enum TALER_ErrorCode ec,
+                 uint64_t row_id,
+                 struct GNUNET_TIME_Absolute wire_timestamp)
 {
   struct TALER_EXCHANGEDB_Session *session = wpd->session;
   enum GNUNET_DB_QueryStatus qs;
 
   (void) cls;
   (void) row_id;
-  (void) row_id_size;
   wpd->eh = NULL;
-  if (GNUNET_SYSERR == success)
+  if (MHD_HTTP_OK != http_status_code)
   {
     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                "Wire transaction failed: %s\n",
-                emsg);
+                "Wire transaction failed: %u/%d\n",
+                http_status_code,
+                ec);
     db_plugin->rollback (db_plugin->cls,
                          session);
     global_ret = GNUNET_SYSERR;
@@ -1792,6 +1727,8 @@ wire_prepare_cb (void *cls,
                  const char *buf,
                  size_t buf_size)
 {
+  struct WireAccount *wa;
+
   (void) cls;
   wpd->row_id = rowid;
   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
@@ -1811,12 +1748,15 @@ wire_prepare_cb (void *cls,
     wpd = NULL;
     return;
   }
-  wpd->eh = wpd->wa->wire_plugin->execute_wire_transfer (
-    wpd->wa->wire_plugin->cls,
-    buf,
-    buf_size,
-    &wire_confirm_cb,
-    NULL);
+  wa = wpd->wa;
+  wpd->eh = TALER_BANK_execute_wire_transfer (ctx,
+                                              wa->account.details.x_taler_bank.
+                                              account_base_url,
+                                              &wa->auth,
+                                              buf,
+                                              buf_size,
+                                              &wire_confirm_cb,
+                                              NULL);
   if (NULL == wpd->eh)
   {
     GNUNET_break (0); /* why? how to best recover? */
@@ -1927,6 +1867,7 @@ run (void *cls,
   (void) cls;
   (void) args;
   (void) cfgfile;
+
   if (GNUNET_OK !=
       GNUNET_CONFIGURATION_get_value_string (c,
                                              "exchange",
@@ -1947,6 +1888,15 @@ run (void *cls,
     global_ret = 1;
     return;
   }
+  ctx = GNUNET_CURL_init (&GNUNET_CURL_gnunet_scheduler_reschedule,
+                          &rc);
+  rc = GNUNET_CURL_gnunet_rc_create (ctx);
+  if (NULL == ctx)
+  {
+    GNUNET_break (0);
+    return;
+  }
+
   task = GNUNET_SCHEDULER_add_now (&run_transfers,
                                    NULL);
   GNUNET_SCHEDULER_add_shutdown (&shutdown_task,
diff --git a/src/exchange/taler-exchange-httpd_deposit.c 
b/src/exchange/taler-exchange-httpd_deposit.c
index 02448238..96e30e43 100644
--- a/src/exchange/taler-exchange-httpd_deposit.c
+++ b/src/exchange/taler-exchange-httpd_deposit.c
@@ -400,7 +400,6 @@ TEH_DEPOSIT_handler_deposit (struct TEH_RequestHandler *rh,
   json_t *json;
   int res;
   json_t *wire;
-  char *emsg;
   enum TALER_ErrorCode ec;
   unsigned int hc;
   struct TALER_EXCHANGEDB_Deposit deposit;
@@ -460,18 +459,6 @@ TEH_DEPOSIT_handler_deposit (struct TEH_RequestHandler *rh,
                                        "refund_deadline");
   }
 
-  if (TALER_EC_NONE !=
-      (ec = TEH_json_validate_wireformat (wire,
-                                          &emsg)))
-  {
-    GNUNET_JSON_parse_free (spec);
-    res = TALER_MHD_reply_with_error (connection,
-                                      MHD_HTTP_BAD_REQUEST,
-                                      ec,
-                                      emsg);
-    GNUNET_free (emsg);
-    return res;
-  }
   if (GNUNET_OK !=
       check_timestamp_current (deposit.timestamp))
   {
diff --git a/src/exchange/taler-exchange-httpd_validation.c 
b/src/exchange/taler-exchange-httpd_validation.c
index 23dbbf24..d0371e93 100644
--- a/src/exchange/taler-exchange-httpd_validation.c
+++ b/src/exchange/taler-exchange-httpd_validation.c
@@ -1,6 +1,6 @@
 /*
   This file is part of TALER
-  Copyright (C) 2016, 2017, 2018 Taler Systems SA
+  Copyright (C) 2016-2020 Taler Systems SA
 
   TALER is free software; you can redistribute it and/or modify it under the
   terms of the GNU Affero General Public License as published by the Free 
Software
@@ -29,40 +29,6 @@
 #include "taler_wire_lib.h"
 
 
-/**
- * Information we keep for each plugin.
- */
-struct Plugin
-{
-
-  /**
-   * We keep plugins in a DLL.
-   */
-  struct Plugin *next;
-
-  /**
-   * We keep plugins in a DLL.
-   */
-  struct Plugin *prev;
-
-  /**
-   * Pointer to the plugin.
-   */
-  struct TALER_WIRE_Plugin *plugin;
-
-};
-
-
-/**
- * Head of DLL of wire plugins.
- */
-static struct Plugin *wire_head;
-
-/**
- * Tail of DLL of wire plugins.
- */
-static struct Plugin *wire_tail;
-
 /**
  * Array of wire methods supported by this exchange.
  */
@@ -191,9 +157,8 @@ load_account (void *cls,
     else
     {
       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                  "Wire fees not specified for `%s', ignoring plugin %s\n",
-                  method,
-                  ai->plugin_name);
+                  "Wire fees not specified for `%s'\n",
+                  method);
       *ret = GNUNET_SYSERR;
     }
     GNUNET_free (method);
@@ -201,35 +166,15 @@ load_account (void *cls,
 
   if (GNUNET_YES == ai->debit_enabled)
   {
-    struct Plugin *p;
-
-    p = GNUNET_new (struct Plugin);
-    p->plugin = TALER_WIRE_plugin_load (cfg,
-                                        ai->plugin_name);
-    if (NULL == p->plugin)
-    {
-      GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                  "Failed to load plugin %s\n",
-                  ai->plugin_name);
-      GNUNET_free (p);
-      *ret = GNUNET_SYSERR;
-      return;
-    }
     if (GNUNET_OK !=
-        load_fee (p->plugin->method))
+        load_fee (ai->method))
     {
       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                  "Disabling plugin `%s' as wire transfer fees for `%s' are 
not given correctly\n",
-                  ai->plugin_name,
-                  p->plugin->method);
-      TALER_WIRE_plugin_unload (p->plugin);
-      GNUNET_free (p);
+                  "Wire transfer fees for `%s' are not given correctly\n",
+                  ai->method);
       *ret = GNUNET_SYSERR;
       return;
     }
-    GNUNET_CONTAINER_DLL_insert (wire_head,
-                                 wire_tail,
-                                 p);
   }
 }
 
@@ -251,12 +196,6 @@ TEH_VALIDATION_init (const struct 
GNUNET_CONFIGURATION_Handle *cfg)
   TALER_EXCHANGEDB_find_accounts (cfg,
                                   &load_account,
                                   &ret);
-  if (NULL == wire_head)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                "Failed to find properly configured wire transfer method\n");
-    ret = GNUNET_SYSERR;
-  }
   if (GNUNET_OK != ret)
     TEH_VALIDATION_done ();
   return ret;
@@ -269,16 +208,6 @@ TEH_VALIDATION_init (const struct 
GNUNET_CONFIGURATION_Handle *cfg)
 void
 TEH_VALIDATION_done ()
 {
-  struct Plugin *p;
-
-  while (NULL != (p = wire_head))
-  {
-    GNUNET_CONTAINER_DLL_remove (wire_head,
-                                 wire_tail,
-                                 p);
-    TALER_WIRE_plugin_unload (p->plugin);
-    GNUNET_free (p);
-  }
   json_decref (wire_fee_object);
   wire_fee_object = NULL;
   json_decref (wire_accounts_array);
@@ -286,65 +215,6 @@ TEH_VALIDATION_done ()
 }
 
 
-/**
- * Check if the given wire format JSON object is correctly formatted as
- * a wire address.
- *
- * @param wire the JSON wire format object
- * @param[out] emsg set to error message if we return an error code
- * @return #TALER_EC_NONE if correctly formatted; otherwise error code
- */
-enum TALER_ErrorCode
-TEH_json_validate_wireformat (const json_t *wire,
-                              char **emsg)
-{
-  const char *payto_url;
-  json_error_t error;
-  char *method;
-
-  *emsg = NULL;
-  if (0 != json_unpack_ex ((json_t *) wire,
-                           &error, 0,
-                           "{s:s}",
-                           "url", &payto_url))
-  {
-    GNUNET_asprintf (emsg,
-                     "No `url' specified in the wire details\n");
-    return TALER_EC_DEPOSIT_INVALID_WIRE_FORMAT_TYPE_MISSING;
-  }
-  method = TALER_WIRE_payto_get_method (payto_url);
-  if (NULL == method)
-  {
-    GNUNET_asprintf (emsg,
-                     "Malformed payto URL `%s'\n",
-                     payto_url);
-    return TALER_EC_PAYTO_MALFORMED;
-  }
-  for (struct Plugin *p = wire_head; NULL != p; p = p->next)
-  {
-    if (0 == strcasecmp (p->plugin->method,
-                         method))
-    {
-      enum TALER_ErrorCode ec;
-
-      GNUNET_free (method);
-      ec = p->plugin->wire_validate (p->plugin->cls,
-                                     payto_url);
-      if (TALER_EC_NONE != ec)
-        GNUNET_asprintf (emsg,
-                         "Payto URL `%s' rejected by plugin\n",
-                         payto_url);
-      return ec;
-    }
-  }
-  GNUNET_asprintf (emsg,
-                   "Wire format type `%s' is not supported by this exchange\n",
-                   method);
-  GNUNET_free (method);
-  return TALER_EC_DEPOSIT_INVALID_WIRE_FORMAT_TYPE_UNSUPPORTED;
-}
-
-
 /**
  * Obtain JSON response for /wire
  *
diff --git a/src/exchange/taler-exchange-wirewatch.c 
b/src/exchange/taler-exchange-wirewatch.c
index 21f62cd8..091f4ba2 100644
--- a/src/exchange/taler-exchange-wirewatch.c
+++ b/src/exchange/taler-exchange-wirewatch.c
@@ -27,6 +27,7 @@
 #include "taler_exchangedb_lib.h"
 #include "taler_exchangedb_plugin.h"
 #include "taler_json_lib.h"
+#include "taler_bank_service.h"
 #include "taler_wire_lib.h"
 
 /**
@@ -36,23 +37,6 @@
 #define DELAY GNUNET_TIME_UNIT_SECONDS
 
 
-/**
- * Closure for #reject_cb().
- */
-struct RejectContext
-{
-  /**
-   * Wire transfer subject that was illformed.
-   */
-  char *wtid_s;
-
-  /**
-   * Database session that encountered the problem.
-   */
-  struct TALER_EXCHANGEDB_Session *session;
-};
-
-
 /**
  * Information we keep for each supported account.
  */
@@ -69,14 +53,19 @@ struct WireAccount
   struct WireAccount *prev;
 
   /**
-   * Handle to the plugin.
+   * Name of the section that configures this account.
    */
-  struct TALER_WIRE_Plugin *wire_plugin;
+  char *section_name;
 
   /**
-   * Name of the section that configures this account.
+   * Account information.
    */
-  char *section_name;
+  struct TALER_Account account;
+
+  /**
+   * Authentication data.
+   */
+  struct TALER_BANK_AuthenticationData auth;
 
   /**
    * Are we running from scratch and should re-process all transactions
@@ -107,6 +96,16 @@ static struct WireAccount *wa_tail;
  */
 static struct WireAccount *wa_pos;
 
+/**
+ * Handle to the context for interacting with the bank.
+ */
+static struct GNUNET_CURL_Context *ctx;
+
+/**
+ * Scheduler context for running the @e ctx.
+ */
+static struct GNUNET_CURL_RescheduleContext *rc;
+
 /**
  * Which currency is used by this exchange?
  */
@@ -132,23 +131,13 @@ static int global_ret;
  * Encoded offset in the wire transfer list from where
  * to start the next query with the bank.
  */
-static void *last_row_off;
-
-/**
- * Number of bytes in #last_row_off.
- */
-static size_t last_row_off_size;
+static uint64_t last_row_off;
 
 /**
  * Latest row offset seen in this transaction, becomes
  * the new #last_row_off upon commit.
  */
-static void *latest_row_off;
-
-/**
- * Number of bytes in #latest_row_off.
- */
-static size_t latest_row_off_size;
+static uint64_t latest_row_off;
 
 /**
  * Should we delay the next request to the wire plugin a bit?
@@ -183,12 +172,7 @@ static struct GNUNET_SCHEDULER_Task *task;
 /**
  * Active request for history.
  */
-static struct TALER_WIRE_HistoryHandle *hh;
-
-/**
- * Active request to reject a wire transfer.
- */
-static struct TALER_WIRE_RejectHandle *rt;
+static struct TALER_BANK_CreditHistoryHandle *hh;
 
 
 /**
@@ -202,6 +186,16 @@ shutdown_task (void *cls)
   struct WireAccount *wa;
 
   (void) cls;
+  if (NULL != ctx)
+  {
+    GNUNET_CURL_fini (ctx);
+    ctx = NULL;
+  }
+  if (NULL != rc)
+  {
+    GNUNET_CURL_gnunet_rc_destroy (rc);
+    rc = NULL;
+  }
   if (NULL != task)
   {
     GNUNET_SCHEDULER_cancel (task);
@@ -209,20 +203,9 @@ shutdown_task (void *cls)
   }
   if (NULL != hh)
   {
-    wa_pos->wire_plugin->get_history_cancel (wa_pos->wire_plugin->cls,
-                                             hh);
+    TALER_BANK_credit_history_cancel (hh);
     hh = NULL;
   }
-  if (NULL != rt)
-  {
-    char *wtid_s;
-
-    wtid_s = wa_pos->wire_plugin->reject_transfer_cancel (
-      wa_pos->wire_plugin->cls,
-      rt);
-    rt = NULL;
-    GNUNET_free (wtid_s);
-  }
   TALER_EXCHANGEDB_plugin_unload (db_plugin);
   db_plugin = NULL;
   while (NULL != (wa = wa_head))
@@ -230,14 +213,13 @@ shutdown_task (void *cls)
     GNUNET_CONTAINER_DLL_remove (wa_head,
                                  wa_tail,
                                  wa);
-    TALER_WIRE_plugin_unload (wa->wire_plugin);
+    TALER_WIRE_account_free (&wa->account);
+    TALER_BANK_auth_free (&wa->auth);
     GNUNET_free (wa->section_name);
     GNUNET_free (wa);
   }
   wa_pos = NULL;
-  GNUNET_free_non_null (last_row_off);
-  last_row_off = NULL;
-  last_row_off_size = 0;
+  last_row_off = 0;
 }
 
 
@@ -259,13 +241,26 @@ add_account_cb (void *cls,
     return; /* not enabled for us, skip */
   wa = GNUNET_new (struct WireAccount);
   wa->reset_mode = reset_mode;
-  wa->wire_plugin = TALER_WIRE_plugin_load (cfg,
-                                            ai->plugin_name);
-  if (NULL == wa->wire_plugin)
+  if (GNUNET_OK !=
+      TALER_BANK_auth_parse_cfg (cfg,
+                                 ai->section_name,
+                                 &wa->auth))
   {
     GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
-                "Failed to load wire plugin for `%s'\n",
-                ai->plugin_name);
+                "Failed to load account `%s'\n",
+                ai->section_name);
+    GNUNET_free (wa);
+    return;
+  }
+  if (GNUNET_OK !=
+      TALER_BANK_account_parse_cfg (cfg,
+                                    ai->section_name,
+                                    &wa->account))
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
+                "Failed to load account `%s'\n",
+                ai->section_name);
+    TALER_BANK_auth_free (&wa->auth);
     GNUNET_free (wa);
     return;
   }
@@ -335,71 +330,29 @@ static void
 find_transfers (void *cls);
 
 
-/**
- * Function called upon completion of the rejection of a wire transfer.
- *
- * @param cls closure with the `struct RejectContext`
- * @param ec error code for the operation
- */
-static void
-reject_cb (void *cls,
-           enum TALER_ErrorCode ec)
-{
-  struct RejectContext *rtc = cls;
-  enum GNUNET_DB_QueryStatus qs;
-
-  rt = NULL;
-  if (TALER_EC_NONE != ec)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                "Failed to wire back transfer `%s': %d\n",
-                rtc->wtid_s,
-                ec);
-    GNUNET_free (rtc->wtid_s);
-    db_plugin->rollback (db_plugin->cls,
-                         rtc->session);
-    GNUNET_free (rtc);
-    GNUNET_SCHEDULER_shutdown ();
-    return;
-  }
-  GNUNET_free (rtc->wtid_s);
-  qs = db_plugin->commit (db_plugin->cls,
-                          rtc->session);
-  GNUNET_break (0 <= qs);
-  GNUNET_free (rtc);
-  task = GNUNET_SCHEDULER_add_now (&find_transfers,
-                                   NULL);
-}
-
-
 /**
  * Callbacks of this type are used to serve the result of asking
  * the bank for the transaction history.
  *
  * @param cls closure with the `struct TALER_EXCHANGEDB_Session *`
  * @param ec taler error code
- * @param dir direction of the transfer
- * @param row_off identification of the position at which we are querying
- * @param row_off_size number of bytes in @a row_off
+ * @param serial_id identification of the position at which we are querying
  * @param details details about the wire transfer
+ * @param json raw JSON response
  * @return #GNUNET_OK to continue, #GNUNET_SYSERR to abort iteration
  */
 static int
 history_cb (void *cls,
+            unsigned int http_status,
             enum TALER_ErrorCode ec,
-            enum TALER_BANK_Direction dir,
-            const void *row_off,
-            size_t row_off_size,
-            const struct TALER_WIRE_TransferDetails *details)
+            uint64_t serial_id,
+            const struct TALER_BANK_CreditDetails *details,
+            const json_t *json)
 {
   struct TALER_EXCHANGEDB_Session *session = cls;
   enum GNUNET_DB_QueryStatus qs;
-  struct TALER_ReservePublicKeyP reserve_pub;
 
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "Got history callback, direction %u!\n",
-              (unsigned int) dir);
-  if (TALER_BANK_DIRECTION_NONE == dir)
+  if (NULL == details)
   {
     hh = NULL;
     if (TALER_EC_NONE != ec)
@@ -428,11 +381,8 @@ history_cb (void *cls,
     if (0 < qs)
     {
       /* transaction success, update #last_row_off */
-      GNUNET_free_non_null (last_row_off);
       last_row_off = latest_row_off;
-      last_row_off_size = latest_row_off_size;
-      latest_row_off = NULL;
-      latest_row_off_size = 0;
+      latest_row_off = 0;
 
       /* if successful at limit, try increasing transaction batch size (AIMD) 
*/
       if (current_batch_size == batch_size)
@@ -462,49 +412,10 @@ history_cb (void *cls,
                                     NULL);
     return GNUNET_OK; /* will be ignored anyway */
   }
-  if (NULL != details->wtid_s)
-  {
-    struct RejectContext *rtc;
-
-    GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
-                "Wire transfer over %s has invalid subject `%s', sending it 
back!\n",
-                TALER_amount2s (&details->amount),
-                details->wtid_s);
-    GNUNET_break (0 != row_off_size);
-    if (latest_row_off_size != row_off_size)
-    {
-      GNUNET_free_non_null (latest_row_off);
-      latest_row_off = GNUNET_malloc (row_off_size);
-      latest_row_off_size = row_off_size;
-    }
-    memcpy (latest_row_off,
-            row_off,
-            row_off_size);
-    rtc = GNUNET_new (struct RejectContext);
-    rtc->session = session;
-    rtc->wtid_s = GNUNET_strdup (details->wtid_s);
-    rt = wa_pos->wire_plugin->reject_transfer (wa_pos->wire_plugin->cls,
-                                               wa_pos->section_name,
-                                               row_off,
-                                               row_off_size,
-                                               &reject_cb,
-                                               rtc);
-    if (NULL == rt)
-    {
-      GNUNET_break (0);
-      db_plugin->rollback (db_plugin->cls,
-                           session);
-      GNUNET_assert (NULL == task);
-      task = GNUNET_SCHEDULER_add_now (&find_transfers,
-                                       NULL);
-    }
-    return GNUNET_SYSERR; /* will continue later... */
-  }
-
   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
               "Adding wire transfer over %s with (hashed) subject `%s'\n",
               TALER_amount2s (&details->amount),
-              TALER_B2S (&details->wtid));
+              TALER_B2S (&details->reserve_pub));
 
   /**
    * Debug block.
@@ -515,8 +426,8 @@ history_cb (void *cls,
     char wtid_s[PUBSIZE];
 
     GNUNET_break
-      (NULL != GNUNET_STRINGS_data_to_string (&details->wtid,
-                                              sizeof (details->wtid),
+      (NULL != GNUNET_STRINGS_data_to_string (&details->reserve_pub,
+                                              sizeof (details->reserve_pub),
                                               &wtid_s[0],
                                               PUBSIZE));
     GNUNET_log (GNUNET_ERROR_TYPE_INFO,
@@ -525,20 +436,14 @@ history_cb (void *cls,
   }
 
   current_batch_size++;
-  /* Wire transfer identifier == reserve public key */
-  GNUNET_assert (sizeof (reserve_pub) == sizeof (details->wtid));
-  memcpy (&reserve_pub,
-          &details->wtid,
-          sizeof (reserve_pub));
   qs = db_plugin->reserves_in_insert (db_plugin->cls,
                                       session,
-                                      &reserve_pub,
+                                      &details->reserve_pub,
                                       &details->amount,
                                       details->execution_date,
                                       details->account_url,
                                       wa_pos->section_name,
-                                      row_off,
-                                      row_off_size);
+                                      serial_id);
   if (GNUNET_DB_STATUS_HARD_ERROR == qs)
   {
     GNUNET_break (0);
@@ -560,15 +465,7 @@ history_cb (void *cls,
     return GNUNET_SYSERR;
   }
 
-  if (latest_row_off_size != row_off_size)
-  {
-    GNUNET_free_non_null (latest_row_off);
-    latest_row_off = GNUNET_malloc (row_off_size);
-    latest_row_off_size = row_off_size;
-  }
-  memcpy (latest_row_off,
-          row_off,
-          row_off_size);
+  latest_row_off = serial_id;
   return GNUNET_OK;
 }
 
@@ -615,8 +512,7 @@ find_transfers (void *cls)
     qs = db_plugin->get_latest_reserve_in_reference (db_plugin->cls,
                                                      session,
                                                      wa_pos->section_name,
-                                                     &last_row_off,
-                                                     &last_row_off_size);
+                                                     &last_row_off);
     if (GNUNET_DB_STATUS_HARD_ERROR == qs)
     {
       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
@@ -638,20 +534,17 @@ find_transfers (void *cls)
     }
   }
   wa_pos->reset_mode = GNUNET_NO;
-  GNUNET_assert ( (NULL == last_row_off) ||
-                  ( (NULL != last_row_off) &&
-                    (0 != last_row_off_size) ) );
   delay = GNUNET_YES;
   current_batch_size = 0;
 
-  hh = wa_pos->wire_plugin->get_history (wa_pos->wire_plugin->cls,
-                                         wa_pos->section_name,
-                                         TALER_BANK_DIRECTION_CREDIT,
-                                         last_row_off,
-                                         last_row_off_size,
-                                         batch_size,
-                                         &history_cb,
-                                         session);
+  hh = TALER_BANK_credit_history (ctx,
+                                  wa_pos->account.details.x_taler_bank.
+                                  account_base_url,
+                                  &wa_pos->auth,
+                                  last_row_off,
+                                  batch_size,
+                                  &history_cb,
+                                  session);
   if (NULL == hh)
   {
     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
@@ -695,6 +588,14 @@ run (void *cls,
                                    NULL);
   GNUNET_SCHEDULER_add_shutdown (&shutdown_task,
                                  cls);
+  ctx = GNUNET_CURL_init (&GNUNET_CURL_gnunet_scheduler_reschedule,
+                          &rc);
+  rc = GNUNET_CURL_gnunet_rc_create (ctx);
+  if (NULL == ctx)
+  {
+    GNUNET_break (0);
+    return;
+  }
 }
 
 
diff --git a/src/exchangedb/exchangedb_accounts.c 
b/src/exchangedb/exchangedb_accounts.c
index e3150902..03779395 100644
--- a/src/exchangedb/exchangedb_accounts.c
+++ b/src/exchangedb/exchangedb_accounts.c
@@ -58,7 +58,7 @@ check_for_account (void *cls,
                    const char *section)
 {
   struct FindAccountContext *ctx = cls;
-  char *plugin_name;
+  char *method;
   char *payto_url;
   char *wire_response_filename;
   struct TALER_EXCHANGEDB_AccountInfo ai;
@@ -81,12 +81,12 @@ check_for_account (void *cls,
   if (GNUNET_OK !=
       GNUNET_CONFIGURATION_get_value_string (ctx->cfg,
                                              section,
-                                             "PLUGIN",
-                                             &plugin_name))
+                                             "METHOD",
+                                             &method))
   {
     GNUNET_log_config_missing (GNUNET_ERROR_TYPE_WARNING,
                                section,
-                               "PLUGIN");
+                               "METHOD");
     GNUNET_free (payto_url);
     return;
   }
@@ -97,7 +97,7 @@ check_for_account (void *cls,
                                                &wire_response_filename))
     wire_response_filename = NULL;
   ai.section_name = section;
-  ai.plugin_name = plugin_name;
+  ai.method = method;
   ai.payto_url = payto_url;
   ai.wire_response_filename = wire_response_filename;
 
@@ -112,7 +112,7 @@ check_for_account (void *cls,
   ctx->cb (ctx->cb_cls,
            &ai);
   GNUNET_free (payto_url);
-  GNUNET_free (plugin_name);
+  GNUNET_free (method);
   GNUNET_free_non_null (wire_response_filename);
 }
 
diff --git a/src/exchangedb/exchangedb_fees.c b/src/exchangedb/exchangedb_fees.c
index f06be73a..386c5de9 100644
--- a/src/exchangedb/exchangedb_fees.c
+++ b/src/exchangedb/exchangedb_fees.c
@@ -144,12 +144,12 @@ TALER_EXCHANGEDB_fees_read (const struct 
GNUNET_CONFIGURATION_Handle *cfg,
 /**
  * Convert @a af to @a wf.
  *
- * @param wireplugin name of the wire plugin the fees are for
+ * @param method name of the wire method the fees are for
  * @param[in,out] af aggregate fees, host format (updated to round time)
  * @param[out] wf aggregate fees, disk / signature format
  */
 void
-TALER_EXCHANGEDB_fees_2_wf (const char *wireplugin,
+TALER_EXCHANGEDB_fees_2_wf (const char *method,
                             struct TALER_EXCHANGEDB_AggregateFees *af,
                             struct TALER_MasterWireFeePS *wf)
 {
@@ -157,8 +157,8 @@ TALER_EXCHANGEDB_fees_2_wf (const char *wireplugin,
   (void) GNUNET_TIME_round_abs (&af->end_date);
   wf->purpose.size = htonl (sizeof (*wf));
   wf->purpose.purpose = htonl (TALER_SIGNATURE_MASTER_WIRE_FEES);
-  GNUNET_CRYPTO_hash (wireplugin,
-                      strlen (wireplugin) + 1,
+  GNUNET_CRYPTO_hash (method,
+                      strlen (method) + 1,
                       &wf->h_wire_method);
   wf->start_date = GNUNET_TIME_absolute_hton (af->start_date);
   wf->end_date = GNUNET_TIME_absolute_hton (af->end_date);
diff --git a/src/exchangedb/plugin_exchangedb_postgres.c 
b/src/exchangedb/plugin_exchangedb_postgres.c
index 6ddbead9..5f2c6716 100644
--- a/src/exchangedb/plugin_exchangedb_postgres.c
+++ b/src/exchangedb/plugin_exchangedb_postgres.c
@@ -253,7 +253,7 @@ postgres_create_tables (void *cls)
     GNUNET_PQ_make_execute ("CREATE TABLE IF NOT EXISTS reserves_in"
                             "(reserve_in_serial_id BIGSERIAL UNIQUE"
                             ",reserve_pub BYTEA NOT NULL REFERENCES reserves 
(reserve_pub) ON DELETE CASCADE"
-                            ",wire_reference BYTEA NOT NULL"
+                            ",wire_reference INT8 NOT NULL"
                             ",credit_val INT8 NOT NULL"
                             ",credit_frac INT4 NOT NULL"
                             ",sender_account_details TEXT NOT NULL"
@@ -2158,8 +2158,7 @@ reserves_update (void *cls,
  * @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_reference unique reference identifying the wire transfer 
(binary blob)
- * @param wire_reference_size number of bytes in @a wire_reference
+ * @param wire_ref unique reference identifying the wire transfer
  * @return transaction status code
  */
 static enum GNUNET_DB_QueryStatus
@@ -2170,8 +2169,7 @@ postgres_reserves_in_insert (void *cls,
                              struct GNUNET_TIME_Absolute execution_time,
                              const char *sender_account_details,
                              const char *exchange_account_section,
-                             const void *wire_reference,
-                             size_t wire_reference_size)
+                             uint64_t wire_ref)
 {
   struct PostgresClosure *pg = cls;
   enum GNUNET_DB_QueryStatus reserve_exists;
@@ -2252,8 +2250,7 @@ postgres_reserves_in_insert (void *cls,
   {
     struct GNUNET_PQ_QueryParam params[] = {
       GNUNET_PQ_query_param_auto_from_type (&reserve.pub),
-      GNUNET_PQ_query_param_fixed_size (wire_reference,
-                                        wire_reference_size),
+      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_string (sender_account_details),
@@ -2311,8 +2308,7 @@ postgres_reserves_in_insert (void *cls,
  * @param session the database session handle
  * @param exchange_account_name name of the section in the exchange's 
configuration
  *                       for the account that we are tracking here
- * @param[out] wire_reference set to unique reference identifying the wire 
transfer (binary blob)
- * @param[out] wire_reference_size set to number of bytes in @a wire_reference
+ * @param[out] wire_ref set to unique reference identifying the wire transfer
  * @return transaction status code
  */
 static enum GNUNET_DB_QueryStatus
@@ -2320,17 +2316,15 @@ postgres_get_latest_reserve_in_reference (void *cls,
                                           struct TALER_EXCHANGEDB_Session *
                                           session,
                                           const char *exchange_account_name,
-                                          void **wire_reference,
-                                          size_t *wire_reference_size)
+                                          uint64_t *wire_reference)
 {
   struct GNUNET_PQ_QueryParam params[] = {
     GNUNET_PQ_query_param_string (exchange_account_name),
     GNUNET_PQ_query_param_end
   };
   struct GNUNET_PQ_ResultSpec rs[] = {
-    GNUNET_PQ_result_spec_variable_size ("wire_reference",
-                                         wire_reference,
-                                         wire_reference_size),
+    GNUNET_PQ_result_spec_uint64 ("wire_reference",
+                                  wire_reference),
     GNUNET_PQ_result_spec_end
   };
 
@@ -6192,14 +6186,12 @@ reserves_in_serial_helper_cb (void *cls,
     char *sender_account_details;
     struct GNUNET_TIME_Absolute execution_date;
     uint64_t rowid;
-    void *wire_reference;
-    size_t wire_reference_size;
+    uint64_t wire_reference;
     struct GNUNET_PQ_ResultSpec rs[] = {
       GNUNET_PQ_result_spec_auto_from_type ("reserve_pub",
                                             &reserve_pub),
-      GNUNET_PQ_result_spec_variable_size ("wire_reference",
-                                           &wire_reference,
-                                           &wire_reference_size),
+      GNUNET_PQ_result_spec_uint64 ("wire_reference",
+                                    &wire_reference),
       TALER_PQ_RESULT_SPEC_AMOUNT ("credit",
                                    &credit),
       TALER_PQ_result_spec_absolute_time ("execution_date",
@@ -6227,7 +6219,6 @@ reserves_in_serial_helper_cb (void *cls,
                     &credit,
                     sender_account_details,
                     wire_reference,
-                    wire_reference_size,
                     execution_date);
     GNUNET_PQ_cleanup_result (rs);
     if (GNUNET_OK != ret)
diff --git a/src/exchangedb/test_exchangedb.c b/src/exchangedb/test_exchangedb.c
index a1e20e83..583e3c17 100644
--- a/src/exchangedb/test_exchangedb.c
+++ b/src/exchangedb/test_exchangedb.c
@@ -944,8 +944,7 @@ audit_refund_cb (void *cls,
  * @param reserve_pub public key of the reserve (also the WTID)
  * @param credit amount that was received
  * @param sender_account_details information about the sender's bank account
- * @param wire_reference unique reference identifying the wire transfer 
(binary blob)
- * @param wire_reference_size number of bytes in @a wire_reference
+ * @param wire_reference unique reference identifying the wire transfer
  * @param execution_date when did we receive the funds
  * @return #GNUNET_OK to continue to iterate, #GNUNET_SYSERR to stop
  */
@@ -955,8 +954,7 @@ audit_reserve_in_cb (void *cls,
                      const struct TALER_ReservePublicKeyP *reserve_pub,
                      const struct TALER_Amount *credit,
                      const char *sender_account_details,
-                     const void *wire_reference,
-                     size_t wire_reference_size,
+                     uint64_t wire_reference,
                      struct GNUNET_TIME_Absolute execution_date)
 {
   auditor_row_cnt++;
@@ -1507,8 +1505,7 @@ run (void *cls)
   const char *sndr = "payto://x-taler-bank/localhost:8080/1";
   unsigned int matched;
   unsigned int cnt;
-  void *rr;
-  size_t rr_size;
+  uint64_t rr;
   enum GNUNET_DB_QueryStatus qs;
   struct GNUNET_TIME_Absolute now;
 
@@ -1578,8 +1575,7 @@ run (void *cls)
           plugin->get_latest_reserve_in_reference (plugin->cls,
                                                    session,
                                                    "account-1",
-                                                   &rr,
-                                                   &rr_size));
+                                                   &rr));
   now = GNUNET_TIME_absolute_get ();
   (void) GNUNET_TIME_round_abs (&now);
   FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
@@ -1590,17 +1586,13 @@ run (void *cls)
                                       now,
                                       sndr,
                                       "account-1",
-                                      "TEST",
                                       4));
   FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
           plugin->get_latest_reserve_in_reference (plugin->cls,
                                                    session,
                                                    "account-1",
-                                                   &rr,
-                                                   &rr_size));
-  FAILIF (4 != rr_size);
-  FAILIF (0 != memcmp ("TEST", rr, 4));
-  GNUNET_free (rr);
+                                                   &rr));
+  FAILIF (4 != rr);
   FAILIF (GNUNET_OK !=
           check_reserve (session,
                          &reserve_pub,
@@ -1617,24 +1609,18 @@ run (void *cls)
                                       now,
                                       sndr,
                                       "account-1",
-                                      "TEST2",
                                       5));
   FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
           plugin->get_latest_reserve_in_reference (plugin->cls,
                                                    session,
                                                    "account-1",
-                                                   &rr,
-                                                   &rr_size));
-  GNUNET_free (rr);
+                                                   &rr));
   FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
           plugin->get_latest_reserve_in_reference (plugin->cls,
                                                    session,
                                                    "account-1",
-                                                   &rr,
-                                                   &rr_size));
-  FAILIF (5 != rr_size);
-  FAILIF (0 != memcmp ("TEST2", rr, 5));
-  GNUNET_free (rr);
+                                                   &rr));
+  FAILIF (5 != rr);
   FAILIF (GNUNET_OK !=
           check_reserve (session,
                          &reserve_pub,
diff --git a/src/include/Makefile.am b/src/include/Makefile.am
index af91f117..25bc67b2 100644
--- a/src/include/Makefile.am
+++ b/src/include/Makefile.am
@@ -31,8 +31,6 @@ talerinclude_HEADERS = \
   taler_mhd_lib.h \
   taler_pq_lib.h \
   taler_signatures.h \
-  taler_wire_lib.h \
-  taler_wire_plugin.h \
   taler_testing_bank_lib.h 
 
 endif
diff --git a/src/include/taler_auditordb_plugin.h 
b/src/include/taler_auditordb_plugin.h
index 03a1c6d4..14d477d3 100644
--- a/src/include/taler_auditordb_plugin.h
+++ b/src/include/taler_auditordb_plugin.h
@@ -870,7 +870,6 @@ struct TALER_AUDITORDB_Plugin
    * @param pp where is the auditor in processing
    * @param in_wire_off how far are we in the incoming wire transaction history
    * @param out_wire_off how far are we in the outgoing wire transaction 
history
-   * @param wire_off_size how many bytes do @a in_wire_off and @a out_wire_off 
take?
    * @return transaction status code
    */
   enum GNUNET_DB_QueryStatus
@@ -883,9 +882,8 @@ struct TALER_AUDITORDB_Plugin
                                           const struct
                                           
TALER_AUDITORDB_WireAccountProgressPoint
                                           *pp,
-                                          const void *in_wire_off,
-                                          const void *out_wire_off,
-                                          size_t wire_off_size);
+                                          uint64_t in_wire_off,
+                                          uint64_t out_wire_off);
 
 
   /**
@@ -899,7 +897,6 @@ struct TALER_AUDITORDB_Plugin
    * @param pp where is the auditor in processing
    * @param in_wire_off how far are we in the incoming wire transaction history
    * @param out_wire_off how far are we in the outgoing wire transaction 
history
-   * @param wire_off_size how many bytes do @a in_wire_off and @a out_wire_off 
take?
    * @return transaction status code
    */
   enum GNUNET_DB_QueryStatus
@@ -912,9 +909,8 @@ struct TALER_AUDITORDB_Plugin
                                           const struct
                                           
TALER_AUDITORDB_WireAccountProgressPoint
                                           *pp,
-                                          const void *in_wire_off,
-                                          const void *out_wire_off,
-                                          size_t wire_off_size);
+                                          uint64_t in_wire_off,
+                                          uint64_t out_wire_off);
 
 
   /**
@@ -927,7 +923,6 @@ struct TALER_AUDITORDB_Plugin
    * @param[out] pp where is the auditor in processing
    * @param[out] in_wire_off how far are we in the incoming wire transaction 
history
    * @param[out] out_wire_off how far are we in the outgoing wire transaction 
history
-   * @param[out] wire_off_size how many bytes do @a in_wire_off and @a 
out_wire_off take?
    * @return transaction status code
    */
   enum GNUNET_DB_QueryStatus
@@ -939,9 +934,8 @@ struct TALER_AUDITORDB_Plugin
                                        struct
                                        TALER_AUDITORDB_WireAccountProgressPoint
                                        *pp,
-                                       void **in_wire_off,
-                                       void **out_wire_off,
-                                       size_t *wire_off_size);
+                                       uint64_t *in_wire_off,
+                                       uint64_t *out_wire_off);
 
 
   /**
diff --git a/src/include/taler_bank_service.h b/src/include/taler_bank_service.h
index a7246ad2..a2eec49a 100644
--- a/src/include/taler_bank_service.h
+++ b/src/include/taler_bank_service.h
@@ -1,6 +1,6 @@
 /*
   This file is part of TALER
-  Copyright (C) 2015, 2016, 2017 Taler Systems SA
+  Copyright (C) 2015-2020 Taler Systems SA
 
   TALER is free software; you can redistribute it and/or modify it under the
   terms of the GNU Affero General Public License as published by the Free 
Software
@@ -25,6 +25,7 @@
 #include <jansson.h>
 #include <gnunet/gnunet_curl_lib.h>
 #include "taler_util.h"
+#include "taler_wire_lib.h"
 #include "taler_error_codes.h"
 
 
@@ -122,13 +123,11 @@ typedef void
  * to the operators of the bank.
  *
  * @param ctx curl context for the event loop
- * @param bank_base_url URL of the bank (used to execute this request)
+ * @param account_base_url URL of the account (used to execute this request)
  * @param auth authentication data to use
- * @param exchange_base_url base URL of the exchange (for tracking)
- * @param subject wire transfer subject for the transfer
+ * @param reserve_pub wire transfer subject for the transfer
  * @param amount amount that was deposited
- * @param debit_account_no account number to withdraw from (53 bits at most)
- * @param credit_account_no account number to deposit into (53 bits at most)
+ * @param credit_account account to deposit into
  * @param res_cb the callback to call when the final result for this request 
is available
  * @param res_cb_cls closure for the above callback
  * @return NULL
@@ -137,13 +136,12 @@ typedef void
  */
 struct TALER_BANK_AdminAddIncomingHandle *
 TALER_BANK_admin_add_incoming (struct GNUNET_CURL_Context *ctx,
-                               const char *bank_base_url,
+                               const char *account_base_url,
                                const struct TALER_BANK_AuthenticationData 
*auth,
-                               const char *exchange_base_url,
-                               const char *subject,
+                               const struct
+                               TALER_ReservePublicKeyP *reserve_pub,
                                const struct TALER_Amount *amount,
-                               uint64_t debit_account_no,
-                               uint64_t credit_account_no,
+                               const char *credit_account,
                                TALER_BANK_AdminAddIncomingResultCallback 
res_cb,
                                void *res_cb_cls);
 
@@ -159,53 +157,103 @@ TALER_BANK_admin_add_incoming_cancel (struct
                                       TALER_BANK_AdminAddIncomingHandle *aai);
 
 
+/* ********************* /taler/transfer *********************** */
+
 /**
- * Which types of transactions should be (or is being) returned?
+ * Prepare for exeuction of a wire transfer.
+ *
+ * @param destination_account_url payto:// URL identifying where to send the 
money
+ * @param amount amount to transfer, already rounded
+ * @param exchange_base_url base URL of this exchange (included in subject
+ *        to facilitate use of tracking API by merchant backend)
+ * @param wtid wire transfer identifier to use
+ * @param buf[out] set to transaction data to persist, NULL on error
+ * @param buf_size[out] set to number of bytes in @a buf, 0 on error
  */
-enum TALER_BANK_Direction
-{
+void
+TALER_BANK_prepare_wire_transfer (const char *destination_account_url,
+                                  const struct TALER_Amount *amount,
+                                  const char *exchange_base_url,
+                                  const struct
+                                  TALER_WireTransferIdentifierRawP *wtid,
+                                  void **buf,
+                                  size_t *buf_size);
 
-  /**
-   * Base case, used to indicate errors or end of list.
-   */
-  TALER_BANK_DIRECTION_NONE = 0,
 
-  /**
-   * Transactions where the bank account receives money.
-   */
-  TALER_BANK_DIRECTION_CREDIT = 1,
+/**
+ * Handle for active wire transfer.
+ */
+struct TALER_BANK_WireExecuteHandle;
 
-  /**
-   * Transactions where the bank account looses money.
-   */
-  TALER_BANK_DIRECTION_DEBIT = 2,
 
-  /**
-   * Return both types of transactions.
-   */
-  TALER_BANK_DIRECTION_BOTH = (TALER_BANK_DIRECTION_CREDIT
-                               | TALER_BANK_DIRECTION_DEBIT),
+/**
+ * Function called with the result from the execute step.
+ *
+ * @param cls closure
+ * @param response_code HTTP status code
+ * @param ec taler error code
+ * @param row_id unique ID of the wire transfer in the bank's records
+ * @param timestamp when did the transaction go into effect
+ */
+typedef void
+(*TALER_BANK_ConfirmationCallback)(void *cls,
+                                   unsigned int response_code,
+                                   enum TALER_ErrorCode ec,
+                                   uint64_t row_id,
+                                   struct GNUNET_TIME_Absolute timestamp);
 
-  /**
-   * Bit mask that is applied to view transactions that have been
-   * cancelled. The bit is set for cancelled transactions that are
-   * returned from /history, and must also be set in order for
-   * cancelled transactions to show up in the /history.
-   */
-  TALER_BANK_DIRECTION_CANCEL = 4
 
-};
+/**
+
+ * Execute a wire transfer.
+ *
+ * @param ctx context for HTTP interaction
+ * @param bank_base_url URL of the base INCLUDING account number
+ * @param buf buffer with the prepared execution details
+ * @param buf_size number of bytes in @a buf
+ * @param cc function to call upon success
+ * @param cc_cls closure for @a cc
+ * @return NULL on error
+ */
+struct TALER_BANK_WireExecuteHandle *
+TALER_BANK_execute_wire_transfer (struct GNUNET_CURL_Context *ctx,
+                                  const char *bank_base_url,
+                                  const struct
+                                  TALER_BANK_AuthenticationData *auth,
+                                  const void *buf,
+                                  size_t buf_size,
+                                  TALER_BANK_ConfirmationCallback cc,
+                                  void *cc_cls);
 
 
 /**
- * Handle for querying the bank's transaction history.
+ * Abort execution of a wire transfer. For example, because we are
+ * shutting down.  Note that if an execution is aborted, it may or
+ * may not still succeed. The caller MUST run @e
+ * execute_wire_transfer again for the same request as soon as
+ * possilbe, to ensure that the request either ultimately succeeds
+ * or ultimately fails. Until this has been done, the transaction is
+ * in limbo (i.e. may or may not have been committed).
+ *
+ * @param eh execution to cancel
  */
-struct TALER_BANK_HistoryHandle;
+void
+TALER_BANK_execute_wire_transfer_cancel (struct
+                                         TALER_BANK_WireExecuteHandle *eh);
+
+
+/* ********************* /taler/credits *********************** */
 
 /**
- * Details about a wire transfer.
+ * Handle for querying the bank for transactions
+ * made to the exchange.
  */
-struct TALER_BANK_TransferDetails
+struct TALER_BANK_CreditHistoryHandle;
+
+/**
+ * Details about a wire transfer to the exchange.
+ */
+struct TALER_BANK_CreditDetails
 {
   /**
    * Amount that was transferred
@@ -218,21 +266,22 @@ struct TALER_BANK_TransferDetails
   struct GNUNET_TIME_Absolute execution_date;
 
   /**
-   * Wire transfer subject.  Usually a reserve public key
-   * followed by the base URL of the exchange.
+   * Reserve public key encoded in the wire
+   * transfer subject.
    */
-  char *wire_transfer_subject;
+  struct TALER_ReservePublicKeyP reserve_pub;
 
   /**
-   * payto://-URL of the other account that was involved
+   * payto://-URL of the source account that
+   * send the funds.
    */
-  char *account_url;
+  const char *account_url;
 };
 
 
 /**
  * Callbacks of this type are used to serve the result of asking
- * the bank for the transaction history.
+ * the bank for the credit transaction history.
  *
  * @param cls closure
  * @param http_status HTTP response code, #MHD_HTTP_OK (200) for successful 
status request
@@ -241,31 +290,27 @@ struct TALER_BANK_TransferDetails
  *                    last callback is always of this status (even if 
`abs(num_results)` were
  *                    already returned).
  * @param ec detailed error code
- * @param dir direction of the transfer
  * @param serial_id monotonically increasing counter corresponding to the 
transaction
  * @param details details about the wire transfer
  * @param json detailed response from the HTTPD, or NULL if reply was not in 
JSON
+ * @return #GNUNET_OK to continue, #GNUNET_SYSERR to abort iteration
  */
-typedef void
-(*TALER_BANK_HistoryResultCallback) (void *cls,
-                                     unsigned int http_status,
-                                     enum TALER_ErrorCode ec,
-                                     enum TALER_BANK_Direction dir,
-                                     uint64_t serial_id,
-                                     const struct
-                                     TALER_BANK_TransferDetails *details,
-                                     const json_t *json);
+typedef int
+(*TALER_BANK_CreditResultCallback) (void *cls,
+                                    unsigned int http_status,
+                                    enum TALER_ErrorCode ec,
+                                    uint64_t serial_id,
+                                    const struct
+                                    TALER_BANK_CreditDetails *details,
+                                    const json_t *json);
 
 
 /**
- * Request the wire transfer history of a bank account.
+ * Request the wire credit history of an exchange's bank account.
  *
  * @param ctx curl context for the event loop
- * @param bank_base_url URL of the bank (used to execute this request)
+ * @param account_base_url URL of the base INCLUDING account number
  * @param auth authentication data to use
- * @param account_number which account number should we query
- * @param direction what kinds of wire transfers should be returned
- * @param ascending if GNUNET_YES, history elements will be returned in 
chronological order.
  * @param start_row from which row on do we want to get results, use 
UINT64_MAX for the latest; exclusive
  * @param num_results how many results do we want; negative numbers to go into 
the past,
  *                    positive numbers to go into the future starting at @a 
start_row;
@@ -276,17 +321,14 @@ typedef void
  *         if the inputs are invalid (i.e. zero value for @e num_results).
  *         In this case, the callback is not called.
  */
-struct TALER_BANK_HistoryHandle *
-TALER_BANK_history (struct GNUNET_CURL_Context *ctx,
-                    const char *bank_base_url,
-                    const struct TALER_BANK_AuthenticationData *auth,
-                    uint64_t account_number,
-                    enum TALER_BANK_Direction direction,
-                    unsigned int ascending,
-                    uint64_t start_row,
-                    int64_t num_results,
-                    TALER_BANK_HistoryResultCallback hres_cb,
-                    void *hres_cb_cls);
+struct TALER_BANK_CreditHistoryHandle *
+TALER_BANK_credit_history (struct GNUNET_CURL_Context *ctx,
+                           const char *account_base_url,
+                           const struct TALER_BANK_AuthenticationData *auth,
+                           uint64_t start_row,
+                           int64_t num_results,
+                           TALER_BANK_CreditResultCallback hres_cb,
+                           void *hres_cb_cls);
 
 
 /**
@@ -297,64 +339,127 @@ TALER_BANK_history (struct GNUNET_CURL_Context *ctx,
  * @param hh the history request handle
  */
 void
-TALER_BANK_history_cancel (struct TALER_BANK_HistoryHandle *hh);
+TALER_BANK_credit_history_cancel (struct TALER_BANK_CreditHistoryHandle *hh);
+
 
+/* ********************* /taler/debits *********************** */
 
 /**
- * Handle for #TALER_BANK_reject() operation.
+ * Handle for querying the bank for transactions
+ * made from the exchange to merchants.
  */
-struct TALER_BANK_RejectHandle;
+struct TALER_BANK_DebitHistoryHandle;
+
+/**
+ * Details about a wire transfer made by the exchange
+ * to a merchant.
+ */
+struct TALER_BANK_DebitDetails
+{
+  /**
+   * Amount that was transferred
+   */
+  struct TALER_Amount amount;
+
+  /**
+   * Time of the the transfer
+   */
+  struct GNUNET_TIME_Absolute execution_date;
+
+  /**
+   * Wire transfer identifier used by the exchange.
+   */
+  struct TALER_WireTransferIdentifierRawP wtid;
+
+  /**
+   * Exchange's base URL as given in the wire transfer.
+   */
+  const char *exchange_base_url;
+
+  /**
+   * payto://-URL of the source account that
+   * send the funds.
+   */
+  const char *account_url;
+};
 
 
 /**
  * Callbacks of this type are used to serve the result of asking
- * the bank to reject an incoming wire transfer.
+ * the bank for the debit transaction history.
  *
  * @param cls closure
- * @param http_status HTTP response code, #MHD_HTTP_NO_CONTENT (204) for 
successful status request;
- *                    #MHD_HTTP_NOT_FOUND if the rowid is unknown;
+ * @param http_status HTTP response code, #MHD_HTTP_OK (200) for successful 
status request
  *                    0 if the bank's reply is bogus (fails to follow the 
protocol),
+ *                    #MHD_HTTP_NO_CONTENT if there are no more results; on 
success the
+ *                    last callback is always of this status (even if 
`abs(num_results)` were
+ *                    already returned).
  * @param ec detailed error code
+ * @param serial_id monotonically increasing counter corresponding to the 
transaction
+ * @param details details about the wire transfer
+ * @param json detailed response from the HTTPD, or NULL if reply was not in 
JSON
+ * @return #GNUNET_OK to continue, #GNUNET_SYSERR to abort iteration
  */
-typedef void
-(*TALER_BANK_RejectResultCallback) (void *cls,
-                                    unsigned int http_status,
-                                    enum TALER_ErrorCode ec);
+typedef int
+(*TALER_BANK_DebitResultCallback) (void *cls,
+                                   unsigned int http_status,
+                                   enum TALER_ErrorCode ec,
+                                   uint64_t serial_id,
+                                   const struct
+                                   TALER_BANK_DebitDetails *details,
+                                   const json_t *json);
 
 
 /**
- * Request rejection of a wire transfer, marking it as cancelled and voiding
- * its effects.
+ * Request the wire credit history of an exchange's bank account.
  *
  * @param ctx curl context for the event loop
- * @param bank_base_url URL of the bank (used to execute this request)
+ * @param bank_base_url URL of the base INCLUDING account number
  * @param auth authentication data to use
  * @param account_number which account number should we query
- * @param rowid transfer to reject
- * @param rcb the callback to call with the operation result
- * @param rcb_cls closure for @a rcb
+ * @param start_row from which row on do we want to get results, use 
UINT64_MAX for the latest; exclusive
+ * @param num_results how many results do we want; negative numbers to go into 
the past,
+ *                    positive numbers to go into the future starting at @a 
start_row;
+ *                    must not be zero.
+ * @param hres_cb the callback to call with the transaction history
+ * @param hres_cb_cls closure for the above callback
  * @return NULL
- *         if the inputs are invalid.
+ *         if the inputs are invalid (i.e. zero value for @e num_results).
  *         In this case, the callback is not called.
  */
-struct TALER_BANK_RejectHandle *
-TALER_BANK_reject (struct GNUNET_CURL_Context *ctx,
-                   const char *bank_base_url,
-                   const struct TALER_BANK_AuthenticationData *auth,
-                   uint64_t account_number,
-                   uint64_t rowid,
-                   TALER_BANK_RejectResultCallback rcb,
-                   void *rcb_cls);
+struct TALER_BANK_DebitHistoryHandle *
+TALER_BANK_debit_history (struct GNUNET_CURL_Context *ctx,
+                          const char *bank_base_url,
+                          const struct TALER_BANK_AuthenticationData *auth,
+                          uint64_t start_row,
+                          int64_t num_results,
+                          TALER_BANK_DebitResultCallback hres_cb,
+                          void *hres_cb_cls);
 
 
 /**
- * Cancel an reject request.  This function cannot be used on a request
- * handle if the response was is already served for it.
+ * Cancel an history request.  This function cannot be used on a request
+ * handle if the last response (anything with a status code other than
+ * 200) is already served for it.
  *
- * @param rh the reject request handle
+ * @param hh the history request handle
  */
 void
-TALER_BANK_reject_cancel (struct TALER_BANK_RejectHandle *rh);
+TALER_BANK_debit_history_cancel (struct TALER_BANK_DebitHistoryHandle *hh);
+
+
+/**
+ * Convenience method for parsing configuration section with bank account data.
+ *
+ * @param cfg configuration to parse
+ * @param section the section with the configuration data
+ * @param acc[out] set to the account details
+ * @return #GNUNET_OK on success
+ */
+int
+TALER_BANK_account_parse_cfg (const struct GNUNET_CONFIGURATION_Handle *cfg,
+                              const char *section,
+                              struct TALER_Account *acc);
 
 
 /**
diff --git a/src/include/taler_exchangedb_lib.h 
b/src/include/taler_exchangedb_lib.h
index e6364062..1681c45a 100644
--- a/src/include/taler_exchangedb_lib.h
+++ b/src/include/taler_exchangedb_lib.h
@@ -425,12 +425,12 @@ TALER_EXCHANGEDB_fees_read (const struct 
GNUNET_CONFIGURATION_Handle *cfg,
 /**
  * Convert @a af to @a wf.
  *
- * @param wireplugin name of the wire plugin the fees are for
+ * @param wiremethod name of the wire method the fees are for
  * @param[in,out] af aggregate fees, host format (updated to round time)
  * @param[out] wf aggregate fees, disk / signature format
  */
 void
-TALER_EXCHANGEDB_fees_2_wf (const char *wireplugin,
+TALER_EXCHANGEDB_fees_2_wf (const char *wiremethod,
                             struct TALER_EXCHANGEDB_AggregateFees *af,
                             struct TALER_MasterWireFeePS *wf);
 
@@ -470,10 +470,9 @@ struct TALER_EXCHANGEDB_AccountInfo
   const char *section_name;
 
   /**
-   * Name of the wire plugin that should be used to access
-   * the account.
+   * Name of the wire method used by this account.
    */
-  const char *plugin_name;
+  const char *method;
 
   /**
    * payto://-URL of the account.
diff --git a/src/include/taler_exchangedb_plugin.h 
b/src/include/taler_exchangedb_plugin.h
index 0dcf4b84..09e3b180 100644
--- a/src/include/taler_exchangedb_plugin.h
+++ b/src/include/taler_exchangedb_plugin.h
@@ -960,8 +960,7 @@ typedef int
  * @param reserve_pub public key of the reserve (also the WTID)
  * @param credit amount that was received
  * @param sender_account_details information about the sender's bank account, 
in payto://-format
- * @param wire_reference unique identifier for the wire transfer 
(plugin-specific format)
- * @param wire_reference_size number of bytes in @a wire_reference
+ * @param wire_reference unique identifier for the wire transfer
  * @param execution_date when did we receive the funds
  * @return #GNUNET_OK to continue to iterate, #GNUNET_SYSERR to stop
  */
@@ -972,8 +971,7 @@ typedef int
                                       TALER_ReservePublicKeyP *reserve_pub,
                                       const struct TALER_Amount *credit,
                                       const char *sender_account_details,
-                                      const void *wire_reference,
-                                      size_t wire_reference_size,
+                                      uint64_t wire_reference,
                                       struct GNUNET_TIME_Absolute
                                       execution_date);
 
@@ -1500,8 +1498,7 @@ struct TALER_EXCHANGEDB_Plugin
    * @param balance the amount that has to be added to the reserve
    * @param execution_time when was the amount added
    * @param sender_account_details information about the sender's bank 
account, in payto://-format
-   * @param wire_reference unique reference identifying the wire transfer 
(binary blob)
-   * @param wire_reference_size number of bytes in @a wire_reference
+   * @param wire_reference unique reference identifying the wire transfer
    * @return transaction status code
    */
   enum GNUNET_DB_QueryStatus
@@ -1512,8 +1509,7 @@ struct TALER_EXCHANGEDB_Plugin
                         struct GNUNET_TIME_Absolute execution_time,
                         const char *sender_account_details,
                         const char *exchange_account_name,
-                        const void *wire_reference,
-                        size_t wire_reference_size);
+                        uint64_t wire_reference);
 
 
   /**
@@ -1521,16 +1517,14 @@ struct TALER_EXCHANGEDB_Plugin
    *
    * @param cls the @e cls of this struct with the plugin-specific state
    * @param db the database connection handle
-   * @param[out] wire_reference set to unique reference identifying the wire 
transfer (binary blob)
-   * @param[out] wire_reference_size set to number of bytes in @a 
wire_reference
+   * @param[out] wire_ref set to unique reference identifying the wire transfer
    * @return transaction status code
    */
   enum GNUNET_DB_QueryStatus
   (*get_latest_reserve_in_reference)(void *cls,
                                      struct TALER_EXCHANGEDB_Session *db,
                                      const char *exchange_account_name,
-                                     void **wire_reference,
-                                     size_t *wire_reference_size);
+                                     uint64_t *wire_ref);
 
 
   /**
diff --git a/src/include/taler_fakebank_lib.h b/src/include/taler_fakebank_lib.h
index f3f92534..474c6627 100644
--- a/src/include/taler_fakebank_lib.h
+++ b/src/include/taler_fakebank_lib.h
@@ -1,6 +1,6 @@
 /*
   This file is part of TALER
-  (C) 2016 Inria and GNUnet e.V.
+  (C) 2016-2020 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
@@ -74,8 +74,8 @@ TALER_FAKEBANK_check_empty (struct TALER_FAKEBANK_Handle *h);
  */
 uint64_t
 TALER_FAKEBANK_make_transfer (struct TALER_FAKEBANK_Handle *h,
-                              uint64_t debit_account,
-                              uint64_t credit_account,
+                              const char *debit_account,
+                              const char *credit_account,
                               const struct TALER_Amount *amount,
                               const char *subject,
                               const char *exchange_base_url);
@@ -101,27 +101,12 @@ TALER_FAKEBANK_make_transfer (struct 
TALER_FAKEBANK_Handle *h,
 int
 TALER_FAKEBANK_check (struct TALER_FAKEBANK_Handle *h,
                       const struct TALER_Amount *want_amount,
-                      uint64_t want_debit,
-                      uint64_t want_credit,
+                      const char *want_debit,
+                      const char *want_credit,
                       const char *exchange_base_url,
                       char **subject);
 
 
-/**
- * Reject incoming wire transfer to account @a credit_account
- * as identified by @a rowid.
- *
- * @param h fake bank handle
- * @param rowid identifies transfer to reject
- * @param credit_account account number of owner of credited account
- * @return #GNUNET_YES on success, #GNUNET_NO if the wire transfer was not 
found
- */
-int
-TALER_FAKEBANK_reject_transfer (struct TALER_FAKEBANK_Handle *h,
-                                uint64_t rowid,
-                                uint64_t credit_account);
-
-
 /**
  * Stop running the fake bank.
  *
diff --git a/src/include/taler_mhd_lib.h b/src/include/taler_mhd_lib.h
index 6aefbd77..c836e446 100644
--- a/src/include/taler_mhd_lib.h
+++ b/src/include/taler_mhd_lib.h
@@ -1,6 +1,6 @@
 /*
   This file is part of TALER
-  Copyright (C) 2014 GNUnet e.V.
+  Copyright (C) 2014-2020 Taler Systems SA
 
   TALER is free software; you can redistribute it and/or modify it under the
   terms of the GNU Affero General Public License as published by the Free 
Software
diff --git a/src/include/taler_testing_bank_lib.h 
b/src/include/taler_testing_bank_lib.h
index 350aca3b..43d12d33 100644
--- a/src/include/taler_testing_bank_lib.h
+++ b/src/include/taler_testing_bank_lib.h
@@ -1,6 +1,6 @@
 /*
   This file is part of TALER
-  (C) 2018 Taler Systems SA
+  (C) 2018-2020 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
@@ -103,46 +103,42 @@ TALER_TESTING_has_in_name (const char *prog,
 /* ************** Specific interpreter commands ************ */
 
 /**
- * Make a "history" CMD.
+ * Make a credit "history" CMD.
  *
  * @param label command label.
- * @param bank_url base URL of the bank offering the "history"
+ * @param account_url base URL of the account offering the "history"
  *        operation.
- * @param account_no bank account number to ask the history for.
- * @param direction which direction this operation is interested
- * @param ascending if #GNUNET_YES, it ask the bank to return results
- *        in chronological order.
  * @param start_row_reference reference to a command that can
  *        offer a row identifier, to be used as the starting row
  *        to accept in the result.
- * @param num_results how many rows we want in the result.
+ * @param num_results how many rows we want in the result,
+ *        and ascending/descending call
  * @return the command.
  */
 struct TALER_TESTING_Command
-TALER_TESTING_cmd_bank_history (const char *label,
-                                const char *bank_url,
-                                uint64_t account_no,
-                                enum TALER_BANK_Direction direction,
-                                unsigned int ascending,
+TALER_TESTING_cmd_bank_credits (const char *label,
+                                const char *account_url,
                                 const char *start_row_reference,
-                                unsigned long long num_results);
+                                long long num_results);
 
 
 /**
- * Create a "reject" CMD.
+ * Make a debit "history" CMD.
  *
  * @param label command label.
- * @param bank_url base URL of the bank implementing the
- *        "reject" operation.
- * @param deposit_reference reference to a command that will
- *        provide a "row id" and credit (bank) account to craft
- *        the "reject" request.
- *
+ * @param account_url base URL of the account offering the "history"
+ *        operation.
+ * @param start_row_reference reference to a command that can
+ *        offer a row identifier, to be used as the starting row
+ *        to accept in the result.
+ * @param num_results how many rows we want in the result.
  * @return the command.
  */
 struct TALER_TESTING_Command
-TALER_TESTING_cmd_bank_reject (const char *label,
-                               const char *bank_url,
-                               const char *deposit_reference);
+TALER_TESTING_cmd_bank_debits (const char *label,
+                               const char *account_url,
+                               const char *start_row_reference,
+                               long long num_results);
+
 
 #endif
diff --git a/src/include/taler_testing_lib.h b/src/include/taler_testing_lib.h
index a039f0ec..33f07070 100644
--- a/src/include/taler_testing_lib.h
+++ b/src/include/taler_testing_lib.h
@@ -48,23 +48,24 @@
   } while (0)
 
 
+#define TALER_TESTING_GET_TRAIT_ROW_ID(cmd,out) \
+  TALER_TESTING_get_trait_uint64 (cmd, 3, out)
+
+#define TALER_TESTING_MAKE_TRAIT_ROW_ID(data) \
+  TALER_TESTING_make_trait_uint64 (3, data)
+
+
 #define TALER_TESTING_GET_TRAIT_CREDIT_ACCOUNT(cmd,out) \
-  TALER_TESTING_get_trait_uint64 (cmd, 0, out)
+  TALER_TESTING_get_trait_string (cmd, 4, out)
 
 #define TALER_TESTING_MAKE_TRAIT_CREDIT_ACCOUNT(data) \
-  TALER_TESTING_make_trait_uint64 (0, data)
+  TALER_TESTING_make_trait_string (4, data)
 
 #define TALER_TESTING_GET_TRAIT_DEBIT_ACCOUNT(cmd,out) \
-  TALER_TESTING_get_trait_uint64 (cmd, 1, out)
+  TALER_TESTING_get_trait_string (cmd, 5, out)
 
 #define TALER_TESTING_MAKE_TRAIT_DEBIT_ACCOUNT(data) \
-  TALER_TESTING_make_trait_uint64 (1, data)
-
-#define TALER_TESTING_GET_TRAIT_ROW_ID(cmd,out) \
-  TALER_TESTING_get_trait_uint64 (cmd, 3, out)
-
-#define TALER_TESTING_MAKE_TRAIT_ROW_ID(data) \
-  TALER_TESTING_make_trait_uint64 (3, data)
+  TALER_TESTING_make_trait_string (5, data)
 
 
 /**
@@ -715,13 +716,9 @@ TALER_TESTING_setup_with_auditor_and_exchange 
(TALER_TESTING_Main main_cb,
  *
  * @param label command label.
  * @param amount amount to transfer.
- * @param bank_url base URL of the bank that implements this
- *        wire transer.  For simplicity, both credit and debit
- *        bank account exist at the same bank.
- * @param debit_account_no which account (expressed as a number)
- *        gives money.
- * @param credit_account_no which account (expressed as a number)
- *        receives money.
+ * @param account_base_url base URL of the account that implements this
+ *        wire transer (which account gives money).
+ * @param payto_credit_account which account receives money.
  * @param auth_username username identifying the @a
  *        debit_account_no at the bank.
  * @param auth_password password for @a auth_username.
@@ -734,50 +731,13 @@ TALER_TESTING_setup_with_auditor_and_exchange 
(TALER_TESTING_Main main_cb,
 struct TALER_TESTING_Command
 TALER_TESTING_cmd_fakebank_transfer (const char *label,
                                      const char *amount,
-                                     const char *bank_url,
-                                     uint64_t debit_account_no,
-                                     uint64_t credit_account_no,
+                                     const char *account_base_url,
+                                     const char *payto_credit_account,
                                      const char *auth_username,
                                      const char *auth_password,
                                      const char *exchange_url);
 
 
-/**
- * Create "fakebank transfer" CMD, letting the caller specifying
- * the subject line.
- *
- * @param label command label.
- * @param amount amount to transfer.
- * @param bank_url base URL of the bank that implements this
- *        wire transer.  For simplicity, both credit and debit
- *        bank account exist at the same bank.
- * @param debit_account_no which account (expressed as a number)
- *        gives money.
- * @param credit_account_no which account (expressed as a number)
- *        receives money.
- *
- * @param auth_username username identifying the @a
- *        debit_account_no at the bank.
- * @param auth_password password for @a auth_username.
- * @param subject wire transfer's subject line.
- * @param exchange_url which exchange is involved in this transfer.
- *        This data is used for tracking purposes (FIXME: explain
- *        _how_).
- *
- * @return the command.
- */
-struct TALER_TESTING_Command
-TALER_TESTING_cmd_fakebank_transfer_with_subject (const char *label,
-                                                  const char *amount,
-                                                  const char *bank_url,
-                                                  uint64_t debit_account_no,
-                                                  uint64_t credit_account_no,
-                                                  const char *auth_username,
-                                                  const char *auth_password,
-                                                  const char *subject,
-                                                  const char *exchange_url);
-
-
 /**
  * Create "fakebank transfer" CMD, letting the caller specify
  * a reference to a command that can offer a reserve private key.
@@ -786,11 +746,9 @@ TALER_TESTING_cmd_fakebank_transfer_with_subject (const 
char *label,
  *
  * @param label command label.
  * @param amount the amount to transfer.
- * @param bank_url base URL of the bank running the transfer.
- * @param debit_account_no which account (expressed as a number)
- *        gives money.
- * @param credit_account_no which account (expressed as a number)
- *        receives money.
+ * @param account_base_url base URL of the account that implements this
+ *        wire transer (which account gives money).
+ * @param payto_credit_account which account receives money.
  * @param auth_username username identifying the @a
  *        debit_account_no at the bank.
  * @param auth_password password for @a auth_username.
@@ -804,9 +762,9 @@ TALER_TESTING_cmd_fakebank_transfer_with_subject (const 
char *label,
 struct TALER_TESTING_Command
 TALER_TESTING_cmd_fakebank_transfer_with_ref (const char *label,
                                               const char *amount,
-                                              const char *bank_url,
-                                              uint64_t debit_account_no,
-                                              uint64_t credit_account_no,
+                                              const char *account_base_url,
+                                              const char *payto_credit_account,
+
                                               const char *auth_username,
                                               const char *auth_password,
                                               const char *ref,
@@ -822,14 +780,9 @@ TALER_TESTING_cmd_fakebank_transfer_with_ref (const char 
*label,
  *
  * @param label command label.
  * @param amount amount to transfer.
- * @param bank_url base URL of the bank that implements this
- *        wire transer.  For simplicity, both credit and debit
- *        bank account exist at the same bank.
- * @param debit_account_no which account (expressed as a number)
- *        gives money.
- * @param credit_account_no which account (expressed as a number)
- *        receives money.
- *
+ * @param account_base_url base URL of the account that implements this
+ *        wire transer (which account gives money).
+ * @param payto_credit_account which account receives money.
  * @param auth_username username identifying the @a
  *        debit_account_no at the bank.
  * @param auth_password password for @a auth_username.
@@ -847,9 +800,9 @@ TALER_TESTING_cmd_fakebank_transfer_with_ref (const char 
*label,
 struct TALER_TESTING_Command
 TALER_TESTING_cmd_fakebank_transfer_with_instance (const char *label,
                                                    const char *amount,
-                                                   const char *bank_url,
-                                                   uint64_t debit_account_no,
-                                                   uint64_t credit_account_no,
+                                                   const char 
*account_base_url,
+                                                   const char *
+                                                   payto_credit_account,
                                                    const char *auth_username,
                                                    const char *auth_password,
                                                    const char *instance,
@@ -1268,8 +1221,8 @@ struct TALER_TESTING_Command
 TALER_TESTING_cmd_check_bank_transfer (const char *label,
                                        const char *exchange_base_url,
                                        const char *amount,
-                                       uint64_t debit_account,
-                                       uint64_t credit_account);
+                                       const char *debit_account,
+                                       const char *credit_account);
 
 
 /**
@@ -1617,7 +1570,6 @@ TALER_TESTING_get_trait (const struct TALER_TESTING_Trait 
*traits,
  *
  * @return the trait.
  */
-
 struct TALER_TESTING_Trait
 TALER_TESTING_make_trait_reserve_priv (unsigned int index,
                                        const struct
@@ -1640,6 +1592,34 @@ TALER_TESTING_get_trait_reserve_priv (const struct 
TALER_TESTING_Command *cmd,
                                       TALER_ReservePrivateKeyP **reserve_priv);
 
 
+/**
+ * Offer a reserve public key.
+ *
+ * @param index reserve pubs's index number.
+ * @param reserve_priv reserve public key to offer.
+ * @return the trait.
+ */
+struct TALER_TESTING_Trait
+TALER_TESTING_make_trait_reserve_pub (unsigned int index,
+                                      const struct
+                                      TALER_ReservePublicKeyP *reserve_pub);
+
+
+/**
+ * Obtain a reserve public key from a @a cmd.
+ *
+ * @param cmd command to extract the reserve pub from.
+ * @param index reserve pub's index number.
+ * @param reserve_pub[out] set to the reserve pub.
+ * @return #GNUNET_OK on success.
+ */
+int
+TALER_TESTING_get_trait_reserve_pub (const struct TALER_TESTING_Command *cmd,
+                                     unsigned int index,
+                                     const struct
+                                     TALER_ReservePublicKeyP **reserve_pub);
+
+
 /**
  * Make a trait for a exchange signature.
  *
@@ -2129,34 +2109,34 @@ TALER_TESTING_make_trait_peer_key_pub (unsigned int 
index,
 
 
 /**
- * Obtain a transfer subject from @a cmd.
+ * Obtain a string from @a cmd.
  *
  * @param cmd command to extract the subject from.
  * @param index index number associated with the transfer
  *        subject to offer.
- * @param transfer_subject[out] where to write the offered
- *        transfer subject.
+ * @param s[out] where to write the offered
+ *        string.
  *
  * @return #GNUNET_OK on success.
  */
 int
-TALER_TESTING_get_trait_transfer_subject (const struct
-                                          TALER_TESTING_Command *cmd,
-                                          unsigned int index,
-                                          const char **transfer_subject);
+TALER_TESTING_get_trait_string (const struct
+                                TALER_TESTING_Command *cmd,
+                                unsigned int index,
+                                const char **s);
 
 
 /**
- * Offer transfer subject.
+ * Offer string subject.
  *
  * @param index index number associated with the transfer
  *        subject being offered.
- * @param transfer_subject transfer subject to offer.
+ * @param s string to offer.
  * @return the trait.
  */
 struct TALER_TESTING_Trait
-TALER_TESTING_make_trait_transfer_subject (unsigned int index,
-                                           const char *transfer_subject);
+TALER_TESTING_make_trait_string (unsigned int index,
+                                 const char *s);
 
 
 /**
@@ -2223,7 +2203,6 @@ TALER_TESTING_get_trait_amount (const struct 
TALER_TESTING_Command *cmd,
  * @param index which url is to be picked,
  *        in case multiple are offered.
  * @param url the url to offer.
- *
  * @return the trait.
  */
 struct TALER_TESTING_Trait
diff --git a/src/include/taler_wire_lib.h b/src/include/taler_wire_lib.h
index 3c851091..c7d9f78d 100644
--- a/src/include/taler_wire_lib.h
+++ b/src/include/taler_wire_lib.h
@@ -22,7 +22,7 @@
 #define TALER_WIRE_H
 
 #include <gnunet/gnunet_util_lib.h>
-#include "taler_wire_plugin.h"
+
 
 /**
  * Different account types supported by payto://.
@@ -46,6 +46,7 @@ enum TALER_PaytoAccountType
   TALER_PAC_IBAN
 };
 
+
 /**
  * Information about an account extracted from a payto://-URL.
  */
@@ -71,19 +72,15 @@ struct TALER_Account
     {
 
       /**
-       * Hostname of the bank (possibly including port).
+       * Bank account base URL.
        */
-      char *hostname;
+      char *account_base_url;
 
       /**
-       * Bank account number.
+       * Only the hostname of the bank.
        */
-      unsigned long long no;
+      char *hostname;
 
-      /**
-       * Base URL of the bank hosting the account above.
-       */
-      char *bank_base_url;
     } x_taler_bank;
 
     /**
@@ -113,6 +110,18 @@ void
 TALER_WIRE_account_free (struct TALER_Account *acc);
 
 
+/**
+ * Round the amount to something that can be
+ * transferred on the wire.
+ *
+ * @param[in,out] amount amount to round down
+ * @return #GNUNET_OK on success, #GNUNET_NO if rounding was unnecessary,
+ *         #GNUNET_SYSERR if the amount or currency was invalid
+ */
+int
+TALER_WIRE_amount_round (struct TALER_Amount *amount);
+
+
 /**
  * Parse @a payto_url and store the result in @a acc
  *
@@ -135,36 +144,4 @@ char *
 TALER_WIRE_payto_get_method (const char *payto_url);
 
 
-/**
- * Get the plugin name from the payment method.
- *
- * @param method the method implemented by the plugin (for
- *  simplicity, we assume 1 method is implemented by 1 plugin).
- * @return the plugin name, NULL if not found.
- */
-const char *
-TALER_WIRE_get_plugin_from_method (const char *method);
-
-
-/**
- * Load a WIRE plugin.
- *
- * @param cfg configuration to use
- * @param plugin_name name of the plugin to load
- * @return #GNUNET_OK on success
- */
-struct TALER_WIRE_Plugin *
-TALER_WIRE_plugin_load (const struct GNUNET_CONFIGURATION_Handle *cfg,
-                        const char *plugin_name);
-
-
-/**
- * Unload a WIRE plugin.
- *
- * @param plugin the plugin to unload
- */
-void
-TALER_WIRE_plugin_unload (struct TALER_WIRE_Plugin *plugin);
-
-
 #endif
diff --git a/src/include/taler_wire_plugin.h b/src/include/taler_wire_plugin.h
index ffc7adf5..b5621e68 100644
--- a/src/include/taler_wire_plugin.h
+++ b/src/include/taler_wire_plugin.h
@@ -1,6 +1,6 @@
 /*
   This file is part of TALER
-  Copyright (C) 2016, 2017 GNUnet e.V. & Inria
+  Copyright (C) 2016-2020 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
@@ -40,23 +40,10 @@ typedef void
                                           size_t buf_size);
 
 
-/**
- * Callback to process a merchant registration outcome.
- *
- * @param cls closure
- * @param status GNUNET_OK if the registration succeeded,
- *        GNUNET_NO otherwise.
- */
-typedef void
-(*TALER_WIRE_MerchantRegisterCallback) (void *cls,
-                                        unsigned int status);
-
 /**
  * Details about a valid wire transfer to the exchange.
- * It is the plugin's responsibility to filter and undo
- * invalid transfers.
  */
-struct TALER_WIRE_TransferDetails
+struct TALER_WIRE_CreditDetails
 {
   /**
    * Amount that was transferred
@@ -69,22 +56,44 @@ struct TALER_WIRE_TransferDetails
   struct GNUNET_TIME_Absolute execution_date;
 
   /**
-   * Binary data that was encoded in the wire transfer subject, if
-   * it decoded properly.  Otherwise all-zeros and @e wtid_s is set.
+   * Binary data that was encoded in the wire transfer subject.
    */
-  struct TALER_WireTransferIdentifierRawP wtid;
+  struct TALER_ReservePublicKeyP reserve_pub;
+
+  /**
+   * payto://-URL of the source's account (used
+   * when the reserve is closed or for debugging).
+   */
+  const char *source_account_url;
+};
+
+
+/**
+ * Details about a valid wire transfer made by the
+ * exchange's aggregator to a merchant.
+ */
+struct TALER_WIRE_DebitDetails
+{
+  /**
+   * Amount that was transferred
+   */
+  struct TALER_Amount amount;
 
   /**
-   * Wire transfer identifer as a string.  Set to NULL if the
-   * identifier was properly Base32 encoded and this @e wtid could be
-   * set instead.
+   * Time of the the transfer
+   */
+  struct GNUNET_TIME_Absolute execution_date;
+
+  /**
+   * Binary data that was encoded in the wire transfer subject.
    */
-  char *wtid_s;
+  struct TALER_WireTransferIdentifierRawP wtid;
 
   /**
-   * payto://-URL of the other account that was involved
+   * payto://-URL of the target account which received
+   * the funds.
    */
-  char *account_url;
+  const char *target_account_url;
 };
 
 
@@ -96,33 +105,40 @@ struct TALER_WIRE_TransferDetails
  *
  * @param cls closure
  * @param ec taler error code
- * @param dir direction of the transfer, #TALER_BANK_DIRECTION_NONE when
- *            the iteration is complete
  * @param row_off identification of the position at which we are querying
  * @param row_off_size number of bytes in @a row_off
  * @param details details about the wire transfer
  * @return #GNUNET_OK to continue, #GNUNET_SYSERR to abort iteration
  */
 typedef int
-(*TALER_WIRE_HistoryResultCallback) (void *cls,
-                                     enum TALER_ErrorCode ec,
-                                     enum TALER_BANK_Direction dir,
-                                     const void *row_off,
-                                     size_t row_off_size,
-                                     const struct
-                                     TALER_WIRE_TransferDetails *details);
+(*TALER_WIRE_CreditResultCallback) (void *cls,
+                                    enum TALER_ErrorCode ec,
+                                    const void *row_off,
+                                    size_t row_off_size,
+                                    const struct
+                                    TALER_WIRE_CreditDetails *details);
 
 
 /**
  * Callbacks of this type are used to serve the result of asking
- * the bank to reject a wire transfer.
+ * the bank for the transaction history.  NOTE: this function will
+ * NOT get the list of history elements, but rather get (iteratively)
+ * called for each (parsed) history element.
  *
  * @param cls closure
- * @param ec status of the operation, #TALER_EC_NONE on success
+ * @param ec taler error code
+ * @param row_off identification of the position at which we are querying
+ * @param row_off_size number of bytes in @a row_off
+ * @param details details about the wire transfer
+ * @return #GNUNET_OK to continue, #GNUNET_SYSERR to abort iteration
  */
-typedef void
-(*TALER_WIRE_RejectTransferCallback) (void *cls,
-                                      enum TALER_ErrorCode ec);
+typedef int
+(*TALER_WIRE_DebitResultCallback) (void *cls,
+                                   enum TALER_ErrorCode ec,
+                                   const void *row_off,
+                                   size_t row_off_size,
+                                   const struct
+                                   TALER_WIRE_DebitDetails *details);
 
 
 /**
@@ -136,9 +152,14 @@ struct TALER_WIRE_PrepareHandle;
 struct TALER_WIRE_ExecuteHandle;
 
 /**
- * Handle returned for querying the transaction history.
+ * Handle returned for querying the credit transaction history.
  */
-struct TALER_WIRE_HistoryHandle;
+struct TALER_WIRE_CreditHistoryHandle;
+
+/**
+ * Handle returned for querying the debit transaction history.
+ */
+struct TALER_WIRE_DebitHistoryHandle;
 
 
 /**
@@ -146,7 +167,8 @@ struct TALER_WIRE_HistoryHandle;
  *
  * @param cls closure
  * @param success #GNUNET_OK on success, #GNUNET_SYSERR on failure
- * @param serial_id unique ID of the wire transfer in the bank's records; 
UINT64_MAX on error
+ * @param row_id unique ID of the wire transfer in the bank's records; NULL on 
error
+ * @param row_id_size number of bytes in @e row_id
  * @param emsg NULL on success, otherwise an error message
  */
 typedef void
@@ -156,6 +178,7 @@ typedef void
                                    size_t row_id_size,
                                    const char *emsg);
 
+
 /**
  * @brief The plugin API, returned from the plugin's "init" function.
  * The argument given to "init" is simply a configuration handle.
@@ -176,11 +199,10 @@ struct TALER_WIRE_Plugin
 
   /**
    * Which wire method (payto://METHOD/") is supported by this plugin?
-   * For example, "iban" or "x-taler-bank".
+   * For example, "x-taler-bank" or "iban".
    */
   const char *method;
 
-
   /**
    * Round amount DOWN to the amount that can be transferred via the wire
    * method.  For example, Taler may support 0.000001 EUR as a unit of
@@ -210,80 +232,7 @@ struct TALER_WIRE_Plugin
 
 
   /**
-   * Prepare for exeuction of a wire transfer.
-   *
-   * @param cls the @e cls of this struct with the plugin-specific state
-   * @param origin_account_section configuration section specifying the origin
-   *        account of the exchange to use
-   * @param destination_account_url payto:// URL identifying where to send the 
money
-   * @param amount amount to transfer, already rounded
-   * @param exchange_base_url base URL of this exchange (included in subject
-   *        to facilitate use of tracking API by merchant backend)
-   * @param wtid wire transfer identifier to use
-   * @param ptc function to call with the prepared data to persist
-   * @param ptc_cls closure for @a ptc
-   * @return NULL on failure
-   */
-  struct TALER_WIRE_PrepareHandle *
-  (*prepare_wire_transfer) (void *cls,
-                            const char *origin_account_section,
-                            const char *destination_account_url,
-                            const struct TALER_Amount *amount,
-                            const char *exchange_base_url,
-                            const struct TALER_WireTransferIdentifierRawP 
*wtid,
-                            TALER_WIRE_PrepareTransactionCallback ptc,
-                            void *ptc_cls);
-
-
-  /**
-   * Abort preparation of a wire transfer. For example,
-   * because we are shutting down.
-   *
-   * @param cls the @e cls of this struct with the plugin-specific state
-   * @param pth preparation to cancel
-   */
-  void
-  (*prepare_wire_transfer_cancel) (void *cls,
-                                   struct TALER_WIRE_PrepareHandle *pth);
-
-
-  /**
-   * Execute a wire transfer.
-   *
-   * @param cls the @e cls of this struct with the plugin-specific state
-   * @param buf buffer with the prepared execution details
-   * @param buf_size number of bytes in @a buf
-   * @param cc function to call upon success
-   * @param cc_cls closure for @a cc
-   * @return NULL on error
-   */
-  struct TALER_WIRE_ExecuteHandle *
-  (*execute_wire_transfer) (void *cls,
-                            const char *buf,
-                            size_t buf_size,
-                            TALER_WIRE_ConfirmationCallback cc,
-                            void *cc_cls);
-
-
-  /**
-   * Abort execution of a wire transfer. For example, because we are
-   * shutting down.  Note that if an execution is aborted, it may or
-   * may not still succeed. The caller MUST run @e
-   * execute_wire_transfer again for the same request as soon as
-   * possilbe, to ensure that the request either ultimately succeeds
-   * or ultimately fails. Until this has been done, the transaction is
-   * in limbo (i.e. may or may not have been committed).
-   *
-   * @param cls the @e cls of this struct with the plugin-specific state
-   * @param eh execution to cancel
-   */
-  void
-  (*execute_wire_transfer_cancel) (void *cls,
-                                   struct TALER_WIRE_ExecuteHandle *eh);
-
-
-  /**
-   * Query transfer history of an account.  We use the variable-size
+   * Query credits made to exchange account.  We use the variable-size
    * @a start_off to indicate which transfers we are interested in as
    * different banking systems may have different ways to identify
    * transfers.  The @a start_off value must thus match the value of
@@ -295,7 +244,6 @@ struct TALER_WIRE_Plugin
    * @param cls the @e cls of this struct with the plugin-specific state
    * @param account_section specifies the configuration section which
    *        identifies the account for which we should get the history
-   * @param direction what kinds of wire transfers should be returned
    * @param start_off from which row on do we want to get results, use NULL 
for the latest; exclusive
    * @param start_off_len number of bytes in @a start_off
    * @param num_results how many results do we want; negative numbers to go 
into the past,
@@ -304,70 +252,65 @@ struct TALER_WIRE_Plugin
    * @param hres_cb the callback to call with the transaction history
    * @param hres_cb_cls closure for the above callback
    */
-  struct TALER_WIRE_HistoryHandle *
-  (*get_history) (void *cls,
+  struct TALER_WIRE_CreditHistoryHandle *
+  (*get_credits) (void *cls,
                   const char *account_section,
-                  enum TALER_BANK_Direction direction,
                   const void *start_off,
                   size_t start_off_len,
                   int64_t num_results,
-                  TALER_WIRE_HistoryResultCallback hres_cb,
+                  TALER_WIRE_CreditResultCallback hres_cb,
                   void *hres_cb_cls);
 
   /**
    * Cancel going over the account's history.
    *
    * @param cls plugins' closure
-   * @param whh operation to cancel
+   * @param chh operation to cancel
    */
   void
-  (*get_history_cancel) (void *cls,
-                         struct TALER_WIRE_HistoryHandle *whh);
+  (*get_credits_cancel) (void *cls,
+                         struct TALER_WIRE_CreditHistoryHandle *chh);
 
 
   /**
-   * Reject an incoming wire transfer that was obtained from the
-   * history. This function can be used to transfer funds back to
-   * the sender if the WTID was malformed (i.e. due to a typo).
-   *
-   * Calling `reject_transfer` twice on the same wire transfer should
-   * be idempotent, i.e. not cause the funds to be wired back twice.
-   * Furthermore, the transfer should henceforth be removed from the
-   * results returned by @e get_history.
+   * Query debits (transfers to merchants) made by an exchange.  We use the
+   * variable-size @a start_off to indicate which transfers we are interested
+   * in as different banking systems may have different ways to identify
+   * transfers.  The @a start_off value must thus match the value of a
+   * `row_off` argument previously given to the @a hres_cb.  Use NULL to query
+   * transfers from the beginning of time (with positive @a num_results) or
+   * from the latest committed transfers (with negative @a num_results).
    *
-   * @param cls plugin's closure
+   * @param cls the @e cls of this struct with the plugin-specific state
    * @param account_section specifies the configuration section which
-   *        identifies the account to use to reject the transfer
-   * @param start_off offset of the wire transfer in plugin-specific format
+   *        identifies the account for which we should get the history
+   * @param start_off from which row on do we want to get results, use NULL 
for the latest; exclusive
    * @param start_off_len number of bytes in @a start_off
-   * @param rej_cb function to call with the result of the operation
-   * @param rej_cb_cls closure for @a rej_cb
-   * @return handle to cancel the operation
+   * @param num_results how many results do we want; negative numbers to go 
into the past,
+   *                    positive numbers to go into the future starting at @a 
start_row;
+   *                    must not be zero.
+   * @param hres_cb the callback to call with the transaction history
+   * @param hres_cb_cls closure for the above callback
    */
-  struct TALER_WIRE_RejectHandle *
-  (*reject_transfer)(void *cls,
-                     const char *account_section,
-                     const void *start_off,
-                     size_t start_off_len,
-                     TALER_WIRE_RejectTransferCallback rej_cb,
-                     void *rej_cb_cls);
-
+  struct TALER_WIRE_DebitHistoryHandle *
+  (*get_debits) (void *cls,
+                 const char *account_section,
+                 const void *start_off,
+                 size_t start_off_len,
+                 int64_t num_results,
+                 TALER_WIRE_DebitResultCallback hres_cb,
+                 void *hres_cb_cls);
 
   /**
-   * Cancel ongoing reject operation.  Note that the rejection may still
-   * proceed. Basically, if this function is called, the rejection may
-   * have happened or not.  This function is usually used during shutdown
-   * or system upgrades.  At a later point, the application must call
-   * @e reject_transfer again for this wire transfer, unless the
-   * @e get_history shows that the wire transfer no longer exists.
+   * Cancel going over the account's history.
    *
    * @param cls plugins' closure
-   * @param rh operation to cancel
-   * @return closure of the callback of the operation
+   * @param dhh operation to cancel
    */
-  void *
-  (*reject_transfer_cancel)(void *cls,
-                            struct TALER_WIRE_RejectHandle *rh);
+  void
+  (*get_debits_cancel) (void *cls,
+                        struct TALER_WIRE_DebitHistoryHandle *dhh);
+
 
 };
 
diff --git a/src/lib/Makefile.am b/src/lib/Makefile.am
index de0c8935..ee8389f6 100644
--- a/src/lib/Makefile.am
+++ b/src/lib/Makefile.am
@@ -103,6 +103,7 @@ libtalertesting_la_SOURCES = \
   testing_api_trait_exchange_sig.c \
   testing_api_trait_json.c \
   testing_api_trait_process.c \
+  testing_api_trait_reserve_pub.c \
   testing_api_trait_reserve_priv.c \
   testing_api_trait_number.c \
   testing_api_trait_fresh_coin.c \
diff --git a/src/lib/exchange_api_handle.c b/src/lib/exchange_api_handle.c
index abb95816..6b51519f 100644
--- a/src/lib/exchange_api_handle.c
+++ b/src/lib/exchange_api_handle.c
@@ -1262,7 +1262,7 @@ keys_completed_cb (void *cls,
     for (unsigned int i = 0; i<kd_old.num_denom_keys; i++)
       kd.denom_keys[i].key.rsa_public_key
         = GNUNET_CRYPTO_rsa_public_key_dup (
-            kd_old.denom_keys[i].key.rsa_public_key);
+        kd_old.denom_keys[i].key.rsa_public_key);
 
     kd.num_auditors = kd_old.num_auditors;
     kd.auditors = GNUNET_new_array (kd.num_auditors,
diff --git a/src/lib/testing_api_cmd_bank_check.c 
b/src/lib/testing_api_cmd_bank_check.c
index f51c535a..f74f7afe 100644
--- a/src/lib/testing_api_cmd_bank_check.c
+++ b/src/lib/testing_api_cmd_bank_check.c
@@ -52,12 +52,12 @@ struct BankCheckState
   /**
    * Expected debit bank account.
    */
-  uint64_t debit_account;
+  const char *debit_account;
 
   /**
    * Expected credit bank account.
    */
-  uint64_t credit_account;
+  const char *credit_account;
 
   /**
    * Wire transfer subject (set by fakebank-lib).
@@ -95,18 +95,16 @@ check_bank_transfer_run (void *cls,
                          struct TALER_TESTING_Interpreter *is)
 {
   struct BankCheckState *bcs = cls;
-
   struct TALER_Amount amount;
-  const uint64_t *debit_account;
-  const uint64_t *credit_account;
+  const char *debit_account;
+  const char *credit_account;
   const char *exchange_base_url;
 
-
   if (NULL == bcs->deposit_reference)
   {
     TALER_LOG_INFO ("Deposit reference NOT given\n");
-    debit_account = &bcs->debit_account;
-    credit_account = &bcs->credit_account;
+    debit_account = bcs->debit_account;
+    credit_account = bcs->credit_account;
     exchange_base_url = bcs->exchange_base_url;
 
     if (GNUNET_OK !=
@@ -154,14 +152,13 @@ check_bank_transfer_run (void *cls,
     GNUNET_assert
       (GNUNET_OK == TALER_TESTING_get_trait_url
         (deposit_cmd, 0, &exchange_base_url)); // check 0 works!
-
   }
 
   if (GNUNET_OK !=
       TALER_FAKEBANK_check (is->fakebank,
                             &amount,
-                            *debit_account,
-                            *credit_account,
+                            debit_account,
+                            credit_account,
                             exchange_base_url,
                             &bcs->subject))
   {
@@ -217,18 +214,18 @@ check_bank_transfer_traits (void *cls,
     wtid_ptr = NULL;
   else
     wtid_ptr = &bcs->wtid;
-
-  struct TALER_TESTING_Trait traits[] = {
-    TALER_TESTING_make_trait_transfer_subject (0, bcs->subject),
-    TALER_TESTING_make_trait_wtid (0, wtid_ptr),
-    TALER_TESTING_make_trait_url (0, bcs->exchange_base_url),
-    TALER_TESTING_trait_end ()
-  };
-
-  return TALER_TESTING_get_trait (traits,
-                                  ret,
-                                  trait,
-                                  index);
+  {
+    struct TALER_TESTING_Trait traits[] = {
+      TALER_TESTING_make_trait_wtid (0, wtid_ptr),
+      TALER_TESTING_make_trait_url (0, bcs->exchange_base_url),
+      TALER_TESTING_trait_end ()
+    };
+
+    return TALER_TESTING_get_trait (traits,
+                                    ret,
+                                    trait,
+                                    index);
+  }
 }
 
 
@@ -250,8 +247,8 @@ TALER_TESTING_cmd_check_bank_transfer
   (const char *label,
   const char *exchange_base_url,
   const char *amount,
-  uint64_t debit_account,
-  uint64_t credit_account)
+  const char *debit_account,
+  const char *credit_account)
 {
   struct BankCheckState *bcs;
 
@@ -260,18 +257,18 @@ TALER_TESTING_cmd_check_bank_transfer
   bcs->amount = amount;
   bcs->debit_account = debit_account;
   bcs->credit_account = credit_account;
-
   bcs->deposit_reference = NULL;
-
-  struct TALER_TESTING_Command cmd = {
-    .label = label,
-    .cls = bcs,
-    .run = &check_bank_transfer_run,
-    .cleanup = &check_bank_transfer_cleanup,
-    .traits = &check_bank_transfer_traits
-  };
-
-  return cmd;
+  {
+    struct TALER_TESTING_Command cmd = {
+      .label = label,
+      .cls = bcs,
+      .run = &check_bank_transfer_run,
+      .cleanup = &check_bank_transfer_cleanup,
+      .traits = &check_bank_transfer_traits
+    };
+
+    return cmd;
+  }
 }
 
 
diff --git a/src/lib/testing_api_cmd_fakebank_transfer.c 
b/src/lib/testing_api_cmd_fakebank_transfer.c
index 81378238..e212fd31 100644
--- a/src/lib/testing_api_cmd_fakebank_transfer.c
+++ b/src/lib/testing_api_cmd_fakebank_transfer.c
@@ -1,6 +1,6 @@
 /*
   This file is part of TALER
-  Copyright (C) 2018 Taler Systems SA
+  Copyright (C) 2018-2020 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
@@ -51,24 +51,14 @@ struct FakebankTransferState
   struct TALER_Amount amount;
 
   /**
-   * Wire transfer subject.
+   * Base URL of the debit account.
    */
-  const char *subject;
+  const char *debit_url;
 
   /**
-   * Base URL of the bank serving the request.
+   * Money receiver account URL.
    */
-  const char *bank_url;
-
-  /**
-   * Money sender account number.
-   */
-  uint64_t debit_account_no;
-
-  /**
-   * Money receiver account number.
-   */
-  uint64_t credit_account_no;
+  const char *payto_credit_account;
 
   /**
    * Username to use for authentication.
@@ -86,6 +76,11 @@ struct FakebankTransferState
    */
   struct TALER_ReservePrivateKeyP reserve_priv;
 
+  /**
+   * Reserve public key matching @e reserve_priv.
+   */
+  struct TALER_ReservePublicKeyP reserve_pub;
+
   /**
    * Handle to the pending request at the fakebank.
    */
@@ -188,16 +183,15 @@ do_retry (void *cls)
  * @param ec taler-specific error code, #TALER_EC_NONE on success
  * @param serial_id unique ID of the wire transfer
  * @param timestamp time stamp of the transaction made.
- * @param full_response full response from the exchange (for
- *        logging, in case of errors)
+ * @param json raw response
  */
 static void
-add_incoming_cb (void *cls,
+confirmation_cb (void *cls,
                  unsigned int http_status,
                  enum TALER_ErrorCode ec,
                  uint64_t serial_id,
                  struct GNUNET_TIME_Absolute timestamp,
-                 const json_t *full_response)
+                 const json_t *json)
 {
   struct FakebankTransferState *fts = cls;
   struct TALER_TESTING_Interpreter *is = fts->is;
@@ -256,130 +250,115 @@ fakebank_transfer_run (void *cls,
                        struct TALER_TESTING_Interpreter *is)
 {
   struct FakebankTransferState *fts = cls;
-  char *subject;
   struct TALER_BANK_AuthenticationData auth;
-  struct TALER_ReservePublicKeyP reserve_pub;
 
-  if (NULL != fts->subject)
+  /* Use reserve public key as subject */
+  if (NULL != fts->reserve_reference)
   {
-    subject = GNUNET_strdup (fts->subject);
+    const struct TALER_TESTING_Command *ref;
+    const struct TALER_ReservePrivateKeyP *reserve_priv;
+
+    ref = TALER_TESTING_interpreter_lookup_command
+            (is, fts->reserve_reference);
+    if (NULL == ref)
+    {
+      GNUNET_break (0);
+      TALER_TESTING_interpreter_fail (is);
+      return;
+    }
+    if (GNUNET_OK !=
+        TALER_TESTING_get_trait_reserve_priv (ref,
+                                              0,
+                                              &reserve_priv))
+    {
+      GNUNET_break (0);
+      TALER_TESTING_interpreter_fail (is);
+      return;
+    }
+    fts->reserve_priv.eddsa_priv = reserve_priv->eddsa_priv;
   }
   else
   {
-    /* Use reserve public key as subject */
-    if (NULL != fts->reserve_reference)
+    if (NULL != fts->instance)
     {
-      const struct TALER_TESTING_Command *ref;
-      const struct TALER_ReservePrivateKeyP *reserve_priv;
+      char *section;
+      char *keys;
+      struct GNUNET_CRYPTO_EddsaPrivateKey *priv;
+      struct GNUNET_CONFIGURATION_Handle *cfg;
 
-      ref = TALER_TESTING_interpreter_lookup_command
-              (is, fts->reserve_reference);
-      if (NULL == ref)
+      GNUNET_assert (NULL != fts->config_filename);
+      cfg = GNUNET_CONFIGURATION_create ();
+      if (GNUNET_OK !=
+          GNUNET_CONFIGURATION_load (cfg,
+                                     fts->config_filename))
       {
         GNUNET_break (0);
         TALER_TESTING_interpreter_fail (is);
         return;
       }
+
+      GNUNET_asprintf (&section,
+                       "instance-%s",
+                       fts->instance);
       if (GNUNET_OK !=
-          TALER_TESTING_get_trait_reserve_priv (ref,
-                                                0,
-                                                &reserve_priv))
+          GNUNET_CONFIGURATION_get_value_filename
+            (cfg,
+            section,
+            "TIP_RESERVE_PRIV_FILENAME",
+            &keys))
       {
-        GNUNET_break (0);
+        GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                    "Configuration fails to specify reserve"
+                    " private key filename in section %s\n",
+                    section);
+        GNUNET_free (section);
         TALER_TESTING_interpreter_fail (is);
         return;
       }
-      fts->reserve_priv.eddsa_priv = reserve_priv->eddsa_priv;
-    }
-    else
-    {
-      if (NULL != fts->instance)
+      priv = GNUNET_CRYPTO_eddsa_key_create_from_file (keys);
+      GNUNET_free (keys);
+      if (NULL == priv)
       {
-        char *section;
-        char *keys;
-        struct GNUNET_CRYPTO_EddsaPrivateKey *priv;
-        struct GNUNET_CONFIGURATION_Handle *cfg;
-
-        GNUNET_assert (NULL != fts->config_filename);
-        cfg = GNUNET_CONFIGURATION_create ();
-        if (GNUNET_OK !=
-            GNUNET_CONFIGURATION_load (cfg,
-                                       fts->config_filename))
-        {
-          GNUNET_break (0);
-          TALER_TESTING_interpreter_fail (is);
-          return;
-        }
-
-        GNUNET_asprintf (&section,
-                         "instance-%s",
-                         fts->instance);
-        if (GNUNET_OK !=
-            GNUNET_CONFIGURATION_get_value_filename
-              (cfg,
-              section,
-              "TIP_RESERVE_PRIV_FILENAME",
-              &keys))
-        {
-          GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                      "Configuration fails to specify reserve"
-                      " private key filename in section %s\n",
-                      section);
-          GNUNET_free (section);
-          TALER_TESTING_interpreter_fail (is);
-          return;
-        }
-        priv = GNUNET_CRYPTO_eddsa_key_create_from_file (keys);
-        GNUNET_free (keys);
-        if (NULL == priv)
-        {
-          GNUNET_log_config_invalid
-            (GNUNET_ERROR_TYPE_ERROR,
-            section,
-            "TIP_RESERVE_PRIV_FILENAME",
-            "Failed to read private key");
-          GNUNET_free (section);
-          TALER_TESTING_interpreter_fail (is);
-          return;
-        }
-        fts->reserve_priv.eddsa_priv = *priv;
+        GNUNET_log_config_invalid
+          (GNUNET_ERROR_TYPE_ERROR,
+          section,
+          "TIP_RESERVE_PRIV_FILENAME",
+          "Failed to read private key");
         GNUNET_free (section);
-        GNUNET_free (priv);
-        GNUNET_CONFIGURATION_destroy (cfg);
+        TALER_TESTING_interpreter_fail (is);
+        return;
       }
-      else
-      {
-        /* No referenced reserve, no instance to take priv
-         * from, no explicit subject given: create new key! */
-        struct GNUNET_CRYPTO_EddsaPrivateKey *priv;
+      fts->reserve_priv.eddsa_priv = *priv;
+      GNUNET_free (section);
+      GNUNET_free (priv);
+      GNUNET_CONFIGURATION_destroy (cfg);
+    }
+    else
+    {
+      /* No referenced reserve, no instance to take priv
+       * from, no explicit subject given: create new key! */
+      struct GNUNET_CRYPTO_EddsaPrivateKey *priv;
 
-        priv = GNUNET_CRYPTO_eddsa_key_create ();
-        fts->reserve_priv.eddsa_priv = *priv;
-        GNUNET_free (priv);
-      }
+      priv = GNUNET_CRYPTO_eddsa_key_create ();
+      fts->reserve_priv.eddsa_priv = *priv;
+      GNUNET_free (priv);
     }
-    GNUNET_CRYPTO_eddsa_key_get_public
-      (&fts->reserve_priv.eddsa_priv, &reserve_pub.eddsa_pub);
-    subject = GNUNET_STRINGS_data_to_string_alloc
-                (&reserve_pub, sizeof (reserve_pub));
   }
-
+  GNUNET_CRYPTO_eddsa_key_get_public (&fts->reserve_priv.eddsa_priv,
+                                      &fts->reserve_pub.eddsa_pub);
   auth.method = TALER_BANK_AUTH_BASIC;
   auth.details.basic.username = (char *) fts->auth_username;
   auth.details.basic.password = (char *) fts->auth_password;
   fts->is = is;
   fts->aih = TALER_BANK_admin_add_incoming
                (TALER_TESTING_interpreter_get_context (is),
-               fts->bank_url,
+               fts->debit_url,
                &auth,
-               fts->exchange_url,
-               subject,
+               &fts->reserve_pub,
                &fts->amount,
-               fts->debit_account_no,
-               fts->credit_account_no,
-               &add_incoming_cb,
+               fts->payto_credit_account,
+               &confirmation_cb,
                fts);
-  GNUNET_free (subject);
   if (NULL == fts->aih)
   {
     GNUNET_break (0);
@@ -408,6 +387,7 @@ fakebank_transfer_cleanup (void *cls,
                 "Command %s did not complete\n",
                 cmd->label);
     TALER_BANK_admin_add_incoming_cancel (fts->aih);
+    fts->aih = NULL;
   }
   if (NULL != fts->retry_task)
   {
@@ -435,32 +415,21 @@ fakebank_transfer_traits (void *cls,
                           unsigned int index)
 {
   struct FakebankTransferState *fts = cls;
-  #define MANDATORY 7
-  struct TALER_TESTING_Trait traits[MANDATORY + 1] = {
-    TALER_TESTING_MAKE_TRAIT_DEBIT_ACCOUNT
-      (&fts->debit_account_no),
-    TALER_TESTING_MAKE_TRAIT_CREDIT_ACCOUNT
-      (&fts->credit_account_no),
+  struct TALER_TESTING_Trait traits[] = {
     TALER_TESTING_make_trait_url (0, fts->exchange_url),
+    TALER_TESTING_make_trait_url (1, fts->debit_url),
     TALER_TESTING_MAKE_TRAIT_ROW_ID (&fts->serial_id),
+    TALER_TESTING_MAKE_TRAIT_CREDIT_ACCOUNT (fts->payto_credit_account),
+    TALER_TESTING_MAKE_TRAIT_DEBIT_ACCOUNT (fts->debit_url),
     TALER_TESTING_make_trait_amount_obj (0, &fts->amount),
-    TALER_TESTING_make_trait_absolute_time (0, &fts->timestamp)
+    TALER_TESTING_make_trait_absolute_time (0, &fts->timestamp),
+    TALER_TESTING_make_trait_reserve_priv (0,
+                                           &fts->reserve_priv),
+    TALER_TESTING_make_trait_reserve_pub (0,
+                                          &fts->reserve_pub),
+    TALER_TESTING_trait_end ()
   };
 
-  /**
-   * The user gave explicit subject,
-   * there must be NO reserve priv.  */
-  if (NULL != fts->subject)
-    traits[MANDATORY - 1] =
-      TALER_TESTING_make_trait_transfer_subject (0,
-                                                 fts->subject);
-  /* A reserve priv must exist if no subject was given.  */
-  else
-    traits[MANDATORY - 1] = TALER_TESTING_make_trait_reserve_priv
-                              (0, &fts->reserve_priv),
-
-    traits[MANDATORY] = TALER_TESTING_trait_end ();
-
   return TALER_TESTING_get_trait (traits,
                                   ret,
                                   trait,
@@ -475,27 +444,21 @@ fakebank_transfer_traits (void *cls,
  *
  * @param label command label.
  * @param amount amount to transfer.
- * @param bank_url base URL of the bank that implements this
- *        wire transer.  For simplicity, both credit and debit
- *        bank account exist at the same bank.
- * @param debit_account_no which account (expressed as a number)
- *        gives money.
- * @param credit_account_no which account (expressed as a number)
- *        receives money.
+ * @param account_base_url base URL of the account that implements this
+ *        wire transer (which account gives money).
+ * @param payto_credit_account which account receives money.
  * @param auth_username username identifying the @a
  *        debit_account_no at the bank.
  * @param auth_password password for @a auth_username.
  * @param exchange_url which exchange is involved in this transfer.
- *
  * @return the command.
  */
 struct TALER_TESTING_Command
 TALER_TESTING_cmd_fakebank_transfer
   (const char *label,
   const char *amount,
-  const char *bank_url,
-  uint64_t debit_account_no,
-  uint64_t credit_account_no,
+  const char *account_base_url,
+  const char *payto_credit_account,
   const char *auth_username,
   const char *auth_password,
   const char *exchange_url)
@@ -503,9 +466,8 @@ TALER_TESTING_cmd_fakebank_transfer
   struct FakebankTransferState *fts;
 
   fts = GNUNET_new (struct FakebankTransferState);
-  fts->bank_url = bank_url;
-  fts->credit_account_no = credit_account_no;
-  fts->debit_account_no = debit_account_no;
+  fts->debit_url = account_base_url;
+  fts->payto_credit_account = payto_credit_account;
   fts->auth_username = auth_username;
   fts->auth_password = auth_password;
   fts->exchange_url = exchange_url;
@@ -520,87 +482,17 @@ TALER_TESTING_cmd_fakebank_transfer
     GNUNET_assert (0);
   }
 
-  struct TALER_TESTING_Command cmd = {
-    .cls = fts,
-    .label = label,
-    .run = &fakebank_transfer_run,
-    .cleanup = &fakebank_transfer_cleanup,
-    .traits = &fakebank_transfer_traits
-  };
-
-  return cmd;
-}
-
-
-/**
- * Create "fakebank transfer" CMD, letting the caller specifying
- * the subject line.
- *
- * @param label command label.
- * @param amount amount to transfer.
- * @param bank_url base URL of the bank that implements this
- *        wire transer.  For simplicity, both credit and debit
- *        bank account exist at the same bank.
- * @param debit_account_no which account (expressed as a number)
- *        gives money.
- * @param credit_account_no which account (expressed as a number)
- *        receives money.
- *
- * @param auth_username username identifying the @a
- *        debit_account_no at the bank.
- * @param auth_password password for @a auth_username.
- * @param subject wire transfer's subject line.
- * @param exchange_url which exchange is involved in this transfer.
- *
- * @return the command.
- */
-struct TALER_TESTING_Command
-TALER_TESTING_cmd_fakebank_transfer_with_subject
-  (const char *label,
-  const char *amount,
-  const char *bank_url,
-  uint64_t debit_account_no,
-  uint64_t credit_account_no,
-  const char *auth_username,
-  const char *auth_password,
-  const char *subject,
-  const char *exchange_url)
-{
-  struct FakebankTransferState *fts;
-
-  fts = GNUNET_new (struct FakebankTransferState);
-
-  TALER_LOG_DEBUG ("%s:FTS@%p\n",
-                   label,
-                   fts);
-
-  fts->bank_url = bank_url;
-  fts->credit_account_no = credit_account_no;
-  fts->debit_account_no = debit_account_no;
-  fts->auth_username = auth_username;
-  fts->auth_password = auth_password;
-  fts->subject = subject;
-  fts->exchange_url = exchange_url;
-  if (GNUNET_OK !=
-      TALER_string_to_amount (amount,
-                              &fts->amount))
   {
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                "Failed to parse amount `%s' at %s\n",
-                amount,
-                label);
-    GNUNET_assert (0);
+    struct TALER_TESTING_Command cmd = {
+      .cls = fts,
+      .label = label,
+      .run = &fakebank_transfer_run,
+      .cleanup = &fakebank_transfer_cleanup,
+      .traits = &fakebank_transfer_traits
+    };
+
+    return cmd;
   }
-
-  struct TALER_TESTING_Command cmd = {
-    .cls = fts,
-    .label = label,
-    .run = &fakebank_transfer_run,
-    .cleanup = &fakebank_transfer_cleanup,
-    .traits = &fakebank_transfer_traits
-  };
-
-  return cmd;
 }
 
 
@@ -631,9 +523,8 @@ struct TALER_TESTING_Command
 TALER_TESTING_cmd_fakebank_transfer_with_ref
   (const char *label,
   const char *amount,
-  const char *bank_url,
-  uint64_t debit_account_no,
-  uint64_t credit_account_no,
+  const char *account_base_url,
+  const char *payto_credit_account,
   const char *auth_username,
   const char *auth_password,
   const char *ref,
@@ -642,9 +533,8 @@ TALER_TESTING_cmd_fakebank_transfer_with_ref
   struct FakebankTransferState *fts;
 
   fts = GNUNET_new (struct FakebankTransferState);
-  fts->bank_url = bank_url;
-  fts->credit_account_no = credit_account_no;
-  fts->debit_account_no = debit_account_no;
+  fts->debit_url = account_base_url;
+  fts->payto_credit_account = payto_credit_account;
   fts->auth_username = auth_username;
   fts->auth_password = auth_password;
   fts->reserve_reference = ref;
@@ -659,16 +549,17 @@ TALER_TESTING_cmd_fakebank_transfer_with_ref
                 label);
     GNUNET_assert (0);
   }
-
-  struct TALER_TESTING_Command cmd = {
-    .cls = fts,
-    .label = label,
-    .run = &fakebank_transfer_run,
-    .cleanup = &fakebank_transfer_cleanup,
-    .traits = &fakebank_transfer_traits
-  };
-
-  return cmd;
+  {
+    struct TALER_TESTING_Command cmd = {
+      .cls = fts,
+      .label = label,
+      .run = &fakebank_transfer_run,
+      .cleanup = &fakebank_transfer_cleanup,
+      .traits = &fakebank_transfer_traits
+    };
+
+    return cmd;
+  }
 }
 
 
@@ -705,9 +596,8 @@ struct TALER_TESTING_Command
 TALER_TESTING_cmd_fakebank_transfer_with_instance
   (const char *label,
   const char *amount,
-  const char *bank_url,
-  uint64_t debit_account_no,
-  uint64_t credit_account_no,
+  const char *account_base_url,
+  const char *payto_credit_account,
   const char *auth_username,
   const char *auth_password,
   const char *instance,
@@ -717,9 +607,8 @@ TALER_TESTING_cmd_fakebank_transfer_with_instance
   struct FakebankTransferState *fts;
 
   fts = GNUNET_new (struct FakebankTransferState);
-  fts->bank_url = bank_url;
-  fts->credit_account_no = credit_account_no;
-  fts->debit_account_no = debit_account_no;
+  fts->debit_url = account_base_url;
+  fts->payto_credit_account = payto_credit_account;
   fts->auth_username = auth_username;
   fts->auth_password = auth_password;
   fts->instance = instance;
@@ -735,16 +624,17 @@ TALER_TESTING_cmd_fakebank_transfer_with_instance
                 label);
     GNUNET_assert (0);
   }
-
-  struct TALER_TESTING_Command cmd = {
-    .cls = fts,
-    .label = label,
-    .run = &fakebank_transfer_run,
-    .cleanup = &fakebank_transfer_cleanup,
-    .traits = &fakebank_transfer_traits
-  };
-
-  return cmd;
+  {
+    struct TALER_TESTING_Command cmd = {
+      .cls = fts,
+      .label = label,
+      .run = &fakebank_transfer_run,
+      .cleanup = &fakebank_transfer_cleanup,
+      .traits = &fakebank_transfer_traits
+    };
+
+    return cmd;
+  }
 }
 
 
diff --git a/src/lib/testing_api_cmd_status.c b/src/lib/testing_api_cmd_status.c
index 398221a1..2da404fb 100644
--- a/src/lib/testing_api_cmd_status.c
+++ b/src/lib/testing_api_cmd_status.c
@@ -1,6 +1,6 @@
 /*
   This file is part of TALER
-  Copyright (C) 2014-2018 Taler Systems SA
+  Copyright (C) 2014-2020 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
@@ -146,6 +146,7 @@ status_run (void *cls,
   const struct TALER_TESTING_Command *create_reserve;
   const struct TALER_ReservePrivateKeyP *reserve_priv;
   struct TALER_ReservePublicKeyP reserve_pub;
+  const struct TALER_ReservePublicKeyP *reserve_pubp;
 
   ss->is = is;
   GNUNET_assert (NULL != ss->reserve_reference);
@@ -163,44 +164,31 @@ status_run (void *cls,
 
   /* NOTE: the following line might generate a ERROR log
    * statements, but it can be ignored.  */
-  if (GNUNET_OK == TALER_TESTING_get_trait_reserve_priv
-        (create_reserve,
-        0,
-        &reserve_priv))
+  if (GNUNET_OK ==
+      TALER_TESTING_get_trait_reserve_priv (create_reserve,
+                                            0,
+                                            &reserve_priv))
   {
     GNUNET_CRYPTO_eddsa_key_get_public (&reserve_priv->eddsa_priv,
                                         &reserve_pub.eddsa_pub);
+    reserve_pubp = &reserve_pub;
   }
   else
   {
-    const char *transfer_subject;
-
-    if (GNUNET_OK != TALER_TESTING_get_trait_transfer_subject
-          (create_reserve,
-          0,
-          &transfer_subject))
-    {
-      GNUNET_break (0);
-      TALER_LOG_ERROR ("The reserve has neither a priv nor a subject line.\n");
-      TALER_TESTING_interpreter_fail (is);
-      return;
-    }
-
     if (GNUNET_OK !=
-        GNUNET_STRINGS_string_to_data (transfer_subject,
-                                       strlen (transfer_subject),
-                                       &reserve_pub.eddsa_pub,
-                                       sizeof (struct 
TALER_ReservePublicKeyP)))
+        TALER_TESTING_get_trait_reserve_pub (create_reserve,
+                                             0,
+                                             &reserve_pubp))
     {
       GNUNET_break (0);
-      TALER_LOG_ERROR ("Transfer subject is not a public key.\n");
+      TALER_LOG_ERROR ("The reserve has neither a priv nor a pub.\n");
       TALER_TESTING_interpreter_fail (is);
       return;
     }
   }
 
   ss->rsh = TALER_EXCHANGE_reserve_status (is->exchange,
-                                           &reserve_pub,
+                                           reserve_pubp,
                                            &reserve_status_cb,
                                            ss);
 }
diff --git a/src/lib/testing_api_cmd_track.c b/src/lib/testing_api_cmd_track.c
index 41c6be17..070218cf 100644
--- a/src/lib/testing_api_cmd_track.c
+++ b/src/lib/testing_api_cmd_track.c
@@ -1,6 +1,6 @@
 /*
   This file is part of TALER
-  Copyright (C) 2014-2018 Taler Systems SA
+  Copyright (C) 2014-2020 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
@@ -190,15 +190,11 @@ deposit_wtid_cb
     if (NULL != tts->bank_transfer_reference)
     {
       const struct TALER_TESTING_Command *bank_transfer_cmd;
-      char *ws;
+      const struct TALER_WireTransferIdentifierRawP *wtid_want;
 
       /* _this_ wire transfer subject line.  */
-      ws = GNUNET_STRINGS_data_to_string_alloc (wtid,
-                                                sizeof (*wtid));
-
       bank_transfer_cmd = TALER_TESTING_interpreter_lookup_command
                             (is, tts->bank_transfer_reference);
-
       if (NULL == bank_transfer_cmd)
       {
         GNUNET_break (0);
@@ -206,12 +202,9 @@ deposit_wtid_cb
         return;
       }
 
-      /* expected wire transfer subject line.  */
-      const char *transfer_subject;
-
       if (GNUNET_OK !=
-          TALER_TESTING_get_trait_transfer_subject
-            (bank_transfer_cmd, 0, &transfer_subject))
+          TALER_TESTING_get_trait_wtid
+            (bank_transfer_cmd, 0, &wtid_want))
       {
         GNUNET_break (0);
         TALER_TESTING_interpreter_fail (is);
@@ -219,15 +212,13 @@ deposit_wtid_cb
       }
 
       /* Compare that expected and gotten subjects match.  */
-      if (0 != strcmp (ws, transfer_subject))
+      if (0 != GNUNET_memcmp (wtid,
+                              wtid_want))
       {
         GNUNET_break (0);
-        GNUNET_free (ws);
         TALER_TESTING_interpreter_fail (tts->is);
         return;
       }
-
-      GNUNET_free (ws);
     }
     break;
   case MHD_HTTP_ACCEPTED:
diff --git a/src/lib/testing_api_trait_reserve_pub.c 
b/src/lib/testing_api_trait_reserve_pub.c
new file mode 100644
index 00000000..b9cd070d
--- /dev/null
+++ b/src/lib/testing_api_trait_reserve_pub.c
@@ -0,0 +1,77 @@
+/*
+  This file is part of TALER
+  Copyright (C) 2018-2020 Taler Systems SA
+
+  TALER is free software; you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as
+  published by the Free Software Foundation; either version 3, or
+  (at your option) any later version.
+
+  TALER is distributed in the hope that it will be useful, but
+  WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public
+  License along with TALER; see the file COPYING.  If not, see
+  <http://www.gnu.org/licenses/>
+*/
+/**
+ * @file exchange-lib/testing_api_trait_reserve_pub.c
+ * @brief implements reserve public key trait
+ * @author Christian Grothoff
+ * @author Marcello Stanisci
+ */
+#include "platform.h"
+#include "taler_json_lib.h"
+#include <gnunet/gnunet_curl_lib.h>
+#include "exchange_api_handle.h"
+#include "taler_signatures.h"
+#include "taler_testing_lib.h"
+
+#define TALER_TESTING_TRAIT_RESERVE_PUBLIC_KEY \
+  "reserve-public-key"
+
+/**
+ * Obtain a reserve public key from a @a cmd.
+ *
+ * @param cmd command to extract the reserve pub from.
+ * @param index reserve pub's index number.
+ * @param reserve_pub[out] set to the reserve pub.
+ * @return #GNUNET_OK on success.
+ */
+int
+TALER_TESTING_get_trait_reserve_pub
+  (const struct TALER_TESTING_Command *cmd,
+  unsigned int index,
+  const struct TALER_ReservePublicKeyP **reserve_pub)
+{
+  return cmd->traits (cmd->cls,
+                      (const void **) reserve_pub,
+                      TALER_TESTING_TRAIT_RESERVE_PUBLIC_KEY,
+                      index);
+}
+
+
+/**
+ * Offer a reserve public key.
+ *
+ * @param index reserve pub's index number.
+ * @param reserve_pub reserve public key to offer.
+ * @return the trait.
+ */
+struct TALER_TESTING_Trait
+TALER_TESTING_make_trait_reserve_pub
+  (unsigned int index,
+  const struct TALER_ReservePublicKeyP *reserve_pub)
+{
+  struct TALER_TESTING_Trait ret = {
+    .index = index,
+    .trait_name = TALER_TESTING_TRAIT_RESERVE_PUBLIC_KEY,
+    .ptr = (const void *) reserve_pub
+  };
+  return ret;
+}
+
+
+/* end of testing_api_trait_reserve_pub.c */
diff --git a/src/lib/testing_api_trait_string.c 
b/src/lib/testing_api_trait_string.c
index 8d3d5df0..b9f57ab7 100644
--- a/src/lib/testing_api_trait_string.c
+++ b/src/lib/testing_api_trait_string.c
@@ -30,7 +30,7 @@
 #include "taler_testing_lib.h"
 
 #define TALER_TESTING_TRAIT_CONTRACT_TERMS "contract-terms"
-#define TALER_TESTING_TRAIT_TRANSFER_SUBJECT "transfer-subject"
+#define TALER_TESTING_TRAIT_STRING "string"
 #define TALER_TESTING_TRAIT_AMOUNT "amount"
 #define TALER_TESTING_TRAIT_URL "url"
 #define TALER_TESTING_TRAIT_ORDER_ID "order-id"
@@ -80,46 +80,45 @@ TALER_TESTING_make_trait_contract_terms
 
 
 /**
- * Obtain a transfer subject from @a cmd.
+ * Obtain a string from @a cmd.
  *
  * @param cmd command to extract the subject from.
  * @param index index number associated with the transfer
  *        subject to offer.
- * @param transfer_subject[out] where to write the offered
- *        transfer subject.
+ * @param s[out] where to write the offered
+ *        string
  * @return #GNUNET_OK on success.
  */
 int
-TALER_TESTING_get_trait_transfer_subject
+TALER_TESTING_get_trait_string
   (const struct TALER_TESTING_Command *cmd,
   unsigned int index,
-  const char **transfer_subject)
+  const char **s)
 {
   return cmd->traits (cmd->cls,
-                      (const void **) transfer_subject,
-                      TALER_TESTING_TRAIT_TRANSFER_SUBJECT,
+                      (const void **) s,
+                      TALER_TESTING_TRAIT_STRING,
                       index);
 }
 
 
 /**
- * Offer transfer subject.
+ * Offer string.
  *
  * @param index index number associated with the transfer
  *        subject being offered.
- * @param transfer_subject transfer subject to offer.
- *
+ * @param s transfer subject to offer.
  * @return the trait.
  */
 struct TALER_TESTING_Trait
-TALER_TESTING_make_trait_transfer_subject
+TALER_TESTING_make_trait_string
   (unsigned int index,
-  const char *transfer_subject)
+  const char *s)
 {
   struct TALER_TESTING_Trait ret = {
     .index = index,
-    .trait_name = TALER_TESTING_TRAIT_TRANSFER_SUBJECT,
-    .ptr = (const void *) transfer_subject
+    .trait_name = TALER_TESTING_TRAIT_STRING,
+    .ptr = (const void *) s
   };
   return ret;
 }
diff --git a/src/wire-plugins/Makefile.am b/src/wire-plugins/Makefile.am
deleted file mode 100644
index 6d5b3e8b..00000000
--- a/src/wire-plugins/Makefile.am
+++ /dev/null
@@ -1,81 +0,0 @@
-# This Makefile.am is in the public domain
-AM_CPPFLAGS = -I$(top_srcdir)/src/include
-
-if USE_COVERAGE
-  AM_CFLAGS = --coverage -O0
-  XLIB = -lgcov
-endif
-
-pkgcfgdir = $(prefix)/share/taler/config.d/
-
-EXTRA_DIST = \
-  test_wire_plugin.conf \
-  test_wire_plugin_transactions_taler-bank.conf
-
-plugindir = $(libdir)/taler
-
-if HAVE_LIBCURL
-plugin_LTLIBRARIES = \
- libtaler_plugin_wire_taler_bank.la
-else
-if HAVE_LIBGNURL
-plugin_LTLIBRARIES = \
- libtaler_plugin_wire_taler_bank.la
-endif
-endif
-
-noinst_LTLIBRARIES = \
-  libtaler_plugin_wire_template.la
-
-
-libtaler_plugin_wire_taler_bank_la_SOURCES = \
-  plugin_wire_taler-bank.c
-libtaler_plugin_wire_taler_bank_la_LIBADD = \
-  $(LTLIBINTL)
-libtaler_plugin_wire_taler_bank_la_LDFLAGS = \
-  $(TALER_PLUGIN_LDFLAGS) \
-  $(top_builddir)/src/bank-lib/libtalerbank.la \
-  $(top_builddir)/src/json/libtalerjson.la \
-  $(top_builddir)/src/wire/libtalerwire.la \
-  $(top_builddir)/src/util/libtalerutil.la \
-  -lgnunetcurl \
-  -lgnunetutil $(XLIB)
-
-
-libtaler_plugin_wire_template_la_SOURCES = \
-  plugin_wire_template.c
-libtaler_plugin_wire_template_la_LIBADD = \
-  $(LTLIBINTL)
-libtaler_plugin_wire_template_la_LDFLAGS = \
-  $(TALER_PLUGIN_LDFLAGS) \
-  $(top_builddir)/src/util/libtalerutil.la \
-  -lgnunetutil $(XLIB)
-
-
-AM_TESTS_ENVIRONMENT=export TALER_PREFIX=$${TALER_PREFIX:-@libdir@};export 
PATH=$${TALER_PREFIX:-@prefix@}/bin:$$PATH;
-
-TESTS = \
- test_wire_plugin \
- test_wire_plugin_transactions_taler_bank
-
-check_PROGRAMS= $(TESTS)
-
-
-test_wire_plugin_SOURCES = \
-  test_wire_plugin.c
-test_wire_plugin_LDADD = \
-  -lgnunetutil \
-  $(top_builddir)/src/wire/libtalerwire.la \
-  $(top_builddir)/src/util/libtalerutil.la
-
-
-test_wire_plugin_transactions_taler_bank_SOURCES = \
-  test_wire_plugin_transactions_taler-bank.c
-test_wire_plugin_transactions_taler_bank_LDADD = \
-  -lgnunetjson \
-  -lgnunetutil \
-  -ljansson \
-  $(top_builddir)/src/wire/libtalerwire.la \
-  $(top_builddir)/src/bank-lib/libtalerbank.la \
-  $(top_builddir)/src/bank-lib/libtalerfakebank.la \
-  $(top_builddir)/src/util/libtalerutil.la
diff --git a/src/wire-plugins/plugin_wire_taler-bank.c 
b/src/wire-plugins/plugin_wire_taler-bank.c
deleted file mode 100644
index ad8daa4e..00000000
--- a/src/wire-plugins/plugin_wire_taler-bank.c
+++ /dev/null
@@ -1,1306 +0,0 @@
-/*
-  This file is part of TALER
-  Copyright (C) 2017, 2018 Taler Systems SA
-
-  TALER is free software; you can redistribute it and/or modify it under the
-  terms of the GNU General Public License as published by the Free Software
-  Foundation; either version 3, or (at your option) any later version.
-
-  TALER is distributed in the hope that it will be useful, but WITHOUT ANY
-  WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
-  A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
-
-  You should have received a copy of the GNU General Public License along with
-  TALER; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
-*/
-
-/**
- * @file plugin_wire_taler_bank.c
- * @brief plugin for the "x-taler-bank" wire method
- * @author Christian Grothoff
- */
-#include "platform.h"
-#include "taler_wire_plugin.h"
-#include "taler_json_lib.h"
-#include "taler_wire_lib.h"
-#include "taler_bank_service.h"
-#include "taler_signatures.h"
-#include <gnunet/gnunet_curl_lib.h>
-
-/* only for HTTP status codes */
-#include <microhttpd.h>
-
-/**
- * Type of the "cls" argument given to each of the functions in
- * our API.
- */
-struct TalerBankClosure
-{
-
-  /**
-   * Which currency do we support?
-   */
-  char *currency;
-
-  /**
-   * Handle to the context for sending funds to the bank.
-   */
-  struct GNUNET_CURL_Context *ctx;
-
-  /**
-   * Scheduler context for running the @e ctx.
-   */
-  struct GNUNET_CURL_RescheduleContext *rc;
-
-  /**
-   * Configuration we use to lookup account information.
-   */
-  struct GNUNET_CONFIGURATION_Handle *cfg;
-
-};
-
-
-/**
- * Handle returned by #taler_bank_prepare_wire_transfer.
- */
-struct TALER_WIRE_PrepareHandle
-{
-
-  /**
-   * Task we use for async execution.
-   */
-  struct GNUNET_SCHEDULER_Task *task;
-
-  /**
-   * TalerBank closure we run in.
-   */
-  struct TalerBankClosure *tc;
-
-  /**
-   * Authentication information.
-   */
-  struct TALER_BANK_AuthenticationData auth;
-
-  /**
-   * Which account should be debited? Given as the respective
-   * section in the configuration file.
-   */
-  char *origin_account_url;
-
-  /**
-   * Which account should be credited?
-   */
-  char *destination_account_url;
-
-  /**
-   * Base URL to use for the exchange.
-   */
-  char *exchange_base_url;
-
-  /**
-   * Function to call with the serialized data.
-   */
-  TALER_WIRE_PrepareTransactionCallback ptc;
-
-  /**
-   * Closure for @e ptc.
-   */
-  void *ptc_cls;
-
-  /**
-   * Amount to transfer.
-   */
-  struct TALER_Amount amount;
-
-  /**
-   * Subject of the wire transfer.
-   */
-  struct TALER_WireTransferIdentifierRawP wtid;
-
-
-};
-
-
-/**
- * Handle returned by #taler_bank_execute_wire_transfer.
- */
-struct TALER_WIRE_ExecuteHandle
-{
-
-  /**
-   * Handle to the HTTP request to the bank.
-   */
-  struct TALER_BANK_AdminAddIncomingHandle *aaih;
-
-  /**
-   * Function to call with the result.
-   */
-  TALER_WIRE_ConfirmationCallback cc;
-
-  /**
-   * Closure for @e cc.
-   */
-  void *cc_cls;
-};
-
-
-/**
- * Round amount DOWN to the amount that can be transferred via the wire
- * method.  For example, Taler may support 0.000001 EUR as a unit of
- * payment, but SEPA only supports 0.01 EUR.  This function would
- * round 0.125 EUR to 0.12 EUR in this case.
- *
- * @param cls the @e cls of this struct with the plugin-specific state
- * @param[in,out] amount amount to round down
- * @return #GNUNET_OK on success, #GNUNET_NO if rounding was unnecessary,
- *         #GNUNET_SYSERR if the amount or currency was invalid
- */
-static int
-taler_bank_amount_round (void *cls,
-                         struct TALER_Amount *amount)
-{
-  struct TalerBankClosure *tc = cls;
-  uint32_t delta;
-
-  if (NULL == tc->currency)
-  {
-    GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
-                               "taler",
-                               "CURRENCY");
-    return GNUNET_SYSERR; /* not configured with currency */
-  }
-  if (0 != strcasecmp (amount->currency,
-                       tc->currency))
-  {
-    GNUNET_break (0);
-    return GNUNET_SYSERR;
-  }
-  /* 'taler_bank' method supports 1/100 of the unit currency, i.e. 0.01 CUR */
-  delta = amount->fraction % (TALER_AMOUNT_FRAC_BASE / 100);
-  if (0 == delta)
-    return GNUNET_NO;
-  amount->fraction -= delta;
-  return GNUNET_OK;
-}
-
-
-/**
- * Check if the given payto:// URL is correctly formatted.
- *
- * @param cls the @e cls of this struct with the plugin-specific state
- * @param account_url an account URL
- * @return #TALER_EC_NONE if correctly formatted
- */
-static enum TALER_ErrorCode
-taler_bank_wire_validate (void *cls,
-                          const char *account_url)
-{
-  (void) cls;
-  struct TALER_Account acc;
-  enum TALER_ErrorCode ec;
-
-  ec = TALER_WIRE_payto_to_account (account_url,
-                                    &acc);
-  if (TALER_EC_NONE == ec)
-  {
-    if (TALER_PAC_X_TALER_BANK != acc.type)
-      ec = TALER_EC_PAYTO_WRONG_METHOD;
-    TALER_WIRE_account_free (&acc);
-  }
-  return ec;
-}
-
-
-GNUNET_NETWORK_STRUCT_BEGIN
-/**
- * Format we used for serialized transaction data.
- */
-struct BufFormatP
-{
-
-  /**
-   * The wire transfer identifier.
-   */
-  struct TALER_WireTransferIdentifierRawP wtid;
-
-  /**
-   * The amount.
-   */
-  struct TALER_AmountNBO amount;
-
-  /* followed by 0-terminated origin account URL */
-
-  /* followed by 0-terminated destination account URL */
-
-  /* followed by 0-terminated exchange base URL */
-
-  /* optionally followed by 0-terminated origin username URL */
-
-  /* optionally followed by 0-terminated origin password URL */
-
-};
-GNUNET_NETWORK_STRUCT_END
-
-
-/**
- * Abort preparation of a wire transfer. For example,
- * because we are shutting down.
- *
- * @param cls the @e cls of this struct with the plugin-specific state
- * @param pth preparation to cancel
- */
-static void
-taler_bank_prepare_wire_transfer_cancel (void *cls,
-                                         struct TALER_WIRE_PrepareHandle *pth)
-{
-  (void) cls;
-  if (NULL != pth->task)
-    GNUNET_SCHEDULER_cancel (pth->task);
-  TALER_BANK_auth_free (&pth->auth);
-  GNUNET_free (pth->origin_account_url);
-  GNUNET_free (pth->destination_account_url);
-  GNUNET_free (pth->exchange_base_url);
-  GNUNET_free (pth);
-}
-
-
-/**
- * Prepare for exeuction of a wire transfer.  Calls the
- * callback with the serialized state.
- *
- * @param cls the `struct TALER_WIRE_PrepareHandle`
- */
-static void
-do_prepare (void *cls)
-{
-  struct TALER_WIRE_PrepareHandle *pth = cls;
-  size_t len_i;
-  size_t len_o;
-  size_t len_au;
-  size_t len_ap;
-  size_t len_b;
-  struct BufFormatP bf;
-
-  pth->task = NULL;
-  /* serialize the state into a 'buf' */
-  len_o = strlen (pth->origin_account_url) + 1;
-  len_i = strlen (pth->destination_account_url) + 1;
-  len_b = strlen (pth->exchange_base_url) + 1;
-  len_au = 0;
-  len_ap = 0;
-  switch (pth->auth.method)
-  {
-  case TALER_BANK_AUTH_NONE:
-    break;
-  case TALER_BANK_AUTH_BASIC:
-    len_au = strlen (pth->auth.details.basic.username) + 1;
-    len_ap = strlen (pth->auth.details.basic.password) + 1;
-    break;
-  }
-  bf.wtid = pth->wtid;
-  TALER_amount_hton (&bf.amount,
-                     &pth->amount);
-  {
-    char buf[sizeof (struct BufFormatP) + len_o + len_i + len_b + len_au
-             + len_ap];
-
-    memcpy (buf,
-            &bf,
-            sizeof (struct BufFormatP));
-    memcpy (&buf[sizeof (struct BufFormatP)],
-            pth->origin_account_url,
-            len_o);
-    memcpy (&buf[sizeof (struct BufFormatP) + len_o],
-            pth->destination_account_url,
-            len_i);
-    memcpy (&buf[sizeof (struct BufFormatP) + len_o + len_i],
-            pth->exchange_base_url,
-            len_b);
-    switch (pth->auth.method)
-    {
-    case TALER_BANK_AUTH_NONE:
-      break;
-    case TALER_BANK_AUTH_BASIC:
-      memcpy (&buf[sizeof (struct BufFormatP) + len_o + len_i + len_b],
-              pth->auth.details.basic.username,
-              len_au);
-      memcpy (&buf[sizeof (struct BufFormatP) + len_o + len_i + len_b + 
len_au],
-              pth->auth.details.basic.password,
-              len_ap);
-      break;
-    }
-    /* finally give the state back */
-    pth->ptc (pth->ptc_cls,
-              buf,
-              sizeof (buf));
-  }
-  taler_bank_prepare_wire_transfer_cancel (NULL,
-                                           pth);
-}
-
-
-/**
- * Parse account configuration from @a cfg in @a section into @a account.
- * Obtains the URL option and initializes @a account from it.
- *
- * @param cfg configuration to parse
- * @param section section with the account configuration
- * @param account[out] account information to initialize
- * @return #GNUNET_OK on success
- */
-static int
-parse_account_cfg (const struct GNUNET_CONFIGURATION_Handle *cfg,
-                   const char *section,
-                   struct TALER_Account *account)
-{
-  char *account_url;
-
-  if (GNUNET_OK !=
-      GNUNET_CONFIGURATION_get_value_string (cfg,
-                                             section,
-                                             "URL",
-                                             &account_url))
-  {
-    GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
-                               section,
-                               "URL");
-    return GNUNET_SYSERR;
-  }
-
-  if (TALER_EC_NONE !=
-      TALER_WIRE_payto_to_account (account_url,
-                                   account))
-  {
-    GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR,
-                               section,
-                               "URL",
-                               "Malformed payto:// URL for x-taler-bank 
method");
-    GNUNET_free (account_url);
-    return GNUNET_SYSERR;
-  }
-  if (TALER_PAC_X_TALER_BANK != account->type)
-  {
-    GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR,
-                               section,
-                               "URL",
-                               "Malformed payto:// URL for x-taler-bank 
method");
-    GNUNET_free (account_url);
-    TALER_WIRE_account_free (account);
-    return GNUNET_SYSERR;
-  }
-  GNUNET_free (account_url);
-  return GNUNET_OK;
-}
-
-
-/**
- * Prepare for exeuction of a wire transfer.  Note that we should call
- * @a ptc asynchronously (as that is what the API requires, because
- * some transfer methods need it).  So while we could immediately call
- * @a ptc, we first bundle up all the data and schedule a task to do
- * the work.
- *
- * @param cls the @e cls of this struct with the plugin-specific state
- * @param origin_account_section configuration section specifying the origin
- *        account of the exchange to use
- * @param destination_account_url payto:// URL identifying where to send the 
money
- * @param amount amount to transfer, already rounded
- * @param exchange_base_url base URL of this exchange
- * @param wtid wire transfer identifier to use
- * @param ptc function to call with the prepared data to persist
- * @param ptc_cls closure for @a ptc
- * @return NULL on failure
- */
-static struct TALER_WIRE_PrepareHandle *
-taler_bank_prepare_wire_transfer (void *cls,
-                                  const char *origin_account_section,
-                                  const char *destination_account_url,
-                                  const struct TALER_Amount *amount,
-                                  const char *exchange_base_url,
-                                  const struct
-                                  TALER_WireTransferIdentifierRawP *wtid,
-                                  TALER_WIRE_PrepareTransactionCallback ptc,
-                                  void *ptc_cls)
-{
-  struct TalerBankClosure *tc = cls;
-  struct TALER_WIRE_PrepareHandle *pth;
-  char *origin_account_url;
-  struct TALER_Account a_in;
-  struct TALER_Account a_out;
-
-  /* Check that payto:// URLs are valid */
-  if (TALER_EC_NONE !=
-      TALER_WIRE_payto_to_account (destination_account_url,
-                                   &a_out))
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                "payto://-URL `%s' is invalid!\n",
-                destination_account_url);
-    return NULL;
-  }
-  if (TALER_PAC_X_TALER_BANK != a_out.type)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                "payto://-URL `%s' is invalid!\n",
-                destination_account_url);
-    TALER_WIRE_account_free (&a_out);
-    return NULL;
-  }
-  if (GNUNET_OK !=
-      GNUNET_CONFIGURATION_get_value_string (tc->cfg,
-                                             origin_account_section,
-                                             "URL",
-                                             &origin_account_url))
-  {
-    GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
-                               origin_account_section,
-                               "URL");
-    TALER_WIRE_account_free (&a_out);
-    return NULL;
-  }
-  if (TALER_EC_NONE !=
-      TALER_WIRE_payto_to_account (origin_account_url,
-                                   &a_in))
-  {
-    GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR,
-                               origin_account_section,
-                               "URL",
-                               "Malformed payto:// URL for x-taler-bank 
method");
-    GNUNET_free (origin_account_url);
-    TALER_WIRE_account_free (&a_out);
-    return NULL;
-  }
-  if (TALER_PAC_X_TALER_BANK != a_in.type)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                "payto://-URL `%s' is invalid!\n",
-                origin_account_url);
-    GNUNET_free (origin_account_url);
-    TALER_WIRE_account_free (&a_in);
-    TALER_WIRE_account_free (&a_out);
-    return NULL;
-  }
-
-  /* Make sure the bank is the same! */
-  if (0 != strcasecmp (a_in.details.x_taler_bank.hostname,
-                       a_out.details.x_taler_bank.hostname))
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
-                "x-taler-bank hostname missmatch: `%s' != `%s'\n",
-                a_in.details.x_taler_bank.hostname,
-                a_out.details.x_taler_bank.hostname);
-    TALER_WIRE_account_free (&a_in);
-    TALER_WIRE_account_free (&a_out);
-    GNUNET_free (origin_account_url);
-    return NULL;
-  }
-  TALER_WIRE_account_free (&a_in);
-  TALER_WIRE_account_free (&a_out);
-
-  pth = GNUNET_new (struct TALER_WIRE_PrepareHandle);
-  if (GNUNET_OK !=
-      TALER_BANK_auth_parse_cfg (tc->cfg,
-                                 origin_account_section,
-                                 &pth->auth))
-  {
-    GNUNET_free (pth);
-    GNUNET_free (origin_account_url);
-    return NULL;
-  }
-
-  pth->tc = tc;
-  pth->origin_account_url = origin_account_url;
-  pth->destination_account_url = GNUNET_strdup (destination_account_url);
-  pth->exchange_base_url = GNUNET_strdup (exchange_base_url);
-  pth->wtid = *wtid;
-  pth->ptc = ptc;
-  pth->ptc_cls = ptc_cls;
-  pth->amount = *amount;
-  pth->task = GNUNET_SCHEDULER_add_now (&do_prepare,
-                                        pth);
-  return pth;
-}
-
-
-/**
- * Called with the result of submitting information about an incoming
- * transaction to a bank.
- *
- * @param cls closure with the `struct TALER_WIRE_ExecuteHandle`
- * @param http_status HTTP response code, #MHD_HTTP_OK (200) for successful 
status request
- *                    0 if the bank's reply is bogus (fails to follow the 
protocol)
- * @param ec error code from the bank
- * @param serial_id unique ID of the wire transfer in the bank's records; 
UINT64_MAX on error
- * @param timestamp time when the transfer was settled by the bank.
- * @param json detailed response from the HTTPD, or NULL if reply was not JSON
- */
-static void
-execute_cb (void *cls,
-            unsigned int http_status,
-            enum TALER_ErrorCode ec,
-            uint64_t serial_id,
-            struct GNUNET_TIME_Absolute timestamp,
-            const json_t *json)
-{
-  struct TALER_WIRE_ExecuteHandle *eh = cls;
-  json_t *reason;
-  const char *emsg;
-  char *s;
-  uint64_t serial_id_nbo;
-
-  (void) timestamp;
-  eh->aaih = NULL;
-  emsg = NULL;
-  if (NULL != json)
-  {
-    reason = json_object_get (json,
-                              "reason");
-    if (NULL != reason)
-      emsg = json_string_value (reason);
-  }
-  if (NULL != emsg)
-    GNUNET_asprintf (&s,
-                     "%u/%u (%s)",
-                     http_status,
-                     (unsigned int) ec,
-                     emsg);
-  else
-    GNUNET_asprintf (&s,
-                     "%u/%u",
-                     http_status,
-                     (unsigned int) ec);
-  serial_id_nbo = GNUNET_htonll (serial_id);
-  eh->cc (eh->cc_cls,
-          (MHD_HTTP_OK == http_status) ? GNUNET_OK : GNUNET_SYSERR,
-          &serial_id_nbo,
-          sizeof (uint64_t),
-          (MHD_HTTP_OK == http_status) ? NULL : s);
-  GNUNET_free (s);
-  GNUNET_free (eh);
-}
-
-
-/**
- * Execute a wire transfer.
- *
- * @param cls the @e cls of this struct with the plugin-specific state
- * @param buf buffer with the prepared execution details
- * @param buf_size number of bytes in @a buf
- * @param cc function to call upon success
- * @param cc_cls closure for @a cc
- * @return NULL on error
- */
-static struct TALER_WIRE_ExecuteHandle *
-taler_bank_execute_wire_transfer (void *cls,
-                                  const char *buf,
-                                  size_t buf_size,
-                                  TALER_WIRE_ConfirmationCallback cc,
-                                  void *cc_cls)
-{
-  struct TalerBankClosure *tc = cls;
-  struct TALER_WIRE_ExecuteHandle *eh;
-  struct TALER_Amount amount;
-  struct TALER_Account origin_account;
-  struct TALER_Account destination_account;
-  struct BufFormatP bf;
-  const char *exchange_base_url;
-  const char *origin_account_url;
-  const char *destination_account_url;
-  struct TALER_BANK_AuthenticationData auth;
-  size_t left;
-  size_t slen;
-  char *wire_s;
-
-  if (NULL == tc->ctx)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                "Bank not initialized, cannot do transfers!\n");
-    return NULL; /* not initialized with configuration, cannot do transfers */
-  }
-  if ( (buf_size <= sizeof (struct BufFormatP)) ||
-       ('\0' != buf[buf_size - 1]) )
-  {
-    GNUNET_break (0);
-    return NULL;
-  }
-  memcpy (&bf,
-          buf,
-          sizeof (bf));
-  TALER_amount_ntoh (&amount,
-                     &bf.amount);
-  origin_account_url = &buf[sizeof (struct BufFormatP)];
-  left = buf_size - sizeof (struct BufFormatP);
-  slen = strlen (origin_account_url) + 1;
-  /* make sure there's enough space to accomodate what's been taken now */
-  GNUNET_assert (left >= slen);
-  left -= slen;
-  if (0 == left)
-  {
-    GNUNET_break (0);
-    return NULL;
-  }
-  destination_account_url = &origin_account_url[slen];
-  slen = strlen (destination_account_url) + 1;
-  GNUNET_assert (left >= slen);
-  left -= slen;
-  if (0 == left)
-  {
-    GNUNET_break (0);
-    return NULL;
-  }
-  exchange_base_url = &destination_account_url[slen];
-  slen = strlen (exchange_base_url) + 1;
-  GNUNET_assert (left >= slen);
-  left -= slen;
-  if (0 == left)
-  {
-    auth.method = TALER_BANK_AUTH_NONE;
-  }
-  else
-  {
-    auth.method = TALER_BANK_AUTH_BASIC;
-    auth.details.basic.username = (char *) &exchange_base_url[slen];
-    slen = strlen (auth.details.basic.username) + 1;
-    GNUNET_assert (left >= slen);
-    left -= slen;
-    if (0 == left)
-    {
-      GNUNET_break (0);
-      return NULL;
-    }
-    auth.details.basic.password = &auth.details.basic.username[slen];
-    slen = strlen (auth.details.basic.password) + 1;
-    GNUNET_assert (left >= slen);
-    left -= slen;
-    if (0 != left)
-    {
-      GNUNET_break (0);
-      return NULL;
-    }
-  }
-
-  if (TALER_EC_NONE !=
-      TALER_WIRE_payto_to_account (origin_account_url,
-                                   &origin_account))
-  {
-    GNUNET_break (0);
-    return NULL;
-  }
-  if (TALER_EC_NONE !=
-      TALER_WIRE_payto_to_account (destination_account_url,
-                                   &destination_account))
-  {
-    TALER_WIRE_account_free (&origin_account);
-    GNUNET_break (0);
-    return NULL;
-  }
-  if ( (TALER_PAC_X_TALER_BANK != origin_account.type) ||
-       (TALER_PAC_X_TALER_BANK != destination_account.type) ||
-       (0 != strcasecmp (origin_account.details.x_taler_bank.hostname,
-                         destination_account.details.x_taler_bank.hostname)) )
-  {
-    GNUNET_break (0);
-    TALER_WIRE_account_free (&origin_account);
-    TALER_WIRE_account_free (&destination_account);
-    return NULL;
-  }
-
-  eh = GNUNET_new (struct TALER_WIRE_ExecuteHandle);
-  eh->cc = cc;
-  eh->cc_cls = cc_cls;
-  wire_s = GNUNET_STRINGS_data_to_string_alloc (&bf.wtid,
-                                                sizeof (bf.wtid));
-  eh->aaih = TALER_BANK_admin_add_incoming (tc->ctx,
-                                            
origin_account.details.x_taler_bank.
-                                            bank_base_url,
-                                            &auth,
-                                            exchange_base_url,
-                                            wire_s,
-                                            &amount,
-                                            (uint64_t) origin_account.details.
-                                            x_taler_bank.no,
-                                            (uint64_t) destination_account.
-                                            details.x_taler_bank.no,
-                                            &execute_cb,
-                                            eh);
-  TALER_WIRE_account_free (&origin_account);
-  TALER_WIRE_account_free (&destination_account);
-  GNUNET_free (wire_s);
-  if (NULL == eh->aaih)
-  {
-    GNUNET_break (0);
-    GNUNET_free (eh);
-    return NULL;
-  }
-  return eh;
-}
-
-
-/**
- * Abort execution of a wire transfer. For example, because we are
- * shutting down.  Note that if an execution is aborted, it may or
- * may not still succeed. The caller MUST run @e
- * execute_wire_transfer again for the same request as soon as
- * possilbe, to ensure that the request either ultimately succeeds
- * or ultimately fails. Until this has been done, the transaction is
- * in limbo (i.e. may or may not have been committed).
- *
- * @param cls the @e cls of this struct with the plugin-specific state
- * @param eh execution to cancel
- */
-static void
-taler_bank_execute_wire_transfer_cancel (void *cls,
-                                         struct TALER_WIRE_ExecuteHandle *eh)
-{
-  (void) cls;
-  TALER_BANK_admin_add_incoming_cancel (eh->aaih);
-  GNUNET_free (eh);
-}
-
-
-/**
- * Handle for a #taler_bank_get_history() request.
- */
-struct TALER_WIRE_HistoryHandle
-{
-
-  /**
-   * Function to call with results, can become NULL if the
-   * application cancels the iteration.
-   */
-  TALER_WIRE_HistoryResultCallback hres_cb;
-
-  /**
-   * Closure for @e hres_cb.
-   */
-  void *hres_cb_cls;
-
-  /**
-   * Request to the bank.
-   */
-  struct TALER_BANK_HistoryHandle *hh;
-
-  /**
-   * Authentication to use for access.
-   */
-  struct TALER_BANK_AuthenticationData auth;
-
-};
-
-
-/**
- * Cancel going over the account's history.
- *
- * @param cls the @e cls of this struct with the plugin-specific state
- * @param whh operation to cancel
- */
-static void
-taler_bank_get_history_cancel (void *cls,
-                               struct TALER_WIRE_HistoryHandle *whh)
-{
-  (void) cls;
-  if (NULL != whh->hh)
-  {
-    TALER_BANK_history_cancel (whh->hh);
-    whh->hh = NULL;
-  }
-  TALER_BANK_auth_free (&whh->auth);
-  GNUNET_free (whh);
-}
-
-
-/**
- * Function called with results from the bank
- * about the transaction history.
- *
- * @param cls the `struct TALER_WIRE_HistoryHandle`
- * @param http_status HTTP response code, #MHD_HTTP_OK (200)
- *        for successful status request 0 if the bank's reply
- *        is bogus (fails to follow the protocol),
- *        #MHD_HTTP_NO_CONTENT if there are no more results; on
- *        success the last callback is always of this status
- *        (even if `abs(num_results)` were already returned).
- * @param ec taler error code
- * @param dir direction of the transfer
- * @param serial_id monotonically increasing
- *        counter corresponding to the transaction
- * @param details details about the wire transfer
- * @param json detailed response from the HTTPD,
- *        or NULL if reply was not in JSON
- */
-static void
-bhist_cb (void *cls,
-          unsigned int http_status,
-          enum TALER_ErrorCode ec,
-          enum TALER_BANK_Direction dir,
-          uint64_t serial_id,
-          const struct TALER_BANK_TransferDetails *details,
-          const json_t *json)
-{
-  struct TALER_WIRE_HistoryHandle *whh = cls;
-  uint64_t bserial_id = GNUNET_htonll (serial_id);
-  struct TALER_WIRE_TransferDetails wd;
-
-  (void) json;
-  switch (http_status)
-  {
-  case MHD_HTTP_OK:
-    {
-      char *subject;
-      char *space;
-
-      wd.amount = details->amount;
-      wd.execution_date = details->execution_date;
-      subject = GNUNET_strdup (details->wire_transfer_subject);
-      space = strchr (subject,
-                      (unsigned char) ' ');
-      if (NULL != space)
-      {
-        /* Space separates the actual wire transfer subject
-           from the exchange base URL (if present, expected
-           only for outgoing transactions).  So we cut the
-           string off at the space. */
-        *space = '\0';
-      }
-      /* NOTE: For a real bank, the subject should include a
-         checksum! */
-      if (GNUNET_OK !=
-          GNUNET_STRINGS_string_to_data (subject,
-                                         strlen (subject),
-                                         &wd.wtid,
-                                         sizeof (wd.wtid)))
-      {
-        /* Ill-formed wire subject, set binary version to all zeros
-           and pass as a string, this time including the part after
-           the space. */
-        memset (&wd.wtid,
-                0,
-                sizeof (wd.wtid));
-        wd.wtid_s = details->wire_transfer_subject;
-      }
-      else
-      {
-        wd.wtid_s = NULL;
-      }
-      GNUNET_free (subject);
-      wd.account_url = details->account_url;
-      if ( (NULL != whh->hres_cb) &&
-           (GNUNET_OK !=
-            whh->hres_cb (whh->hres_cb_cls,
-                          TALER_EC_NONE,
-                          dir,
-                          &bserial_id,
-                          sizeof (bserial_id),
-                          &wd)) )
-        whh->hres_cb = NULL;
-      GNUNET_break (NULL != whh->hh);
-      /* Once we get the sentinel element, the handle becomes invalid. */
-      if (TALER_BANK_DIRECTION_NONE == dir)
-      {
-        whh->hh = NULL;
-        taler_bank_get_history_cancel (NULL,
-                                       whh);
-      }
-      return;
-    }
-  case MHD_HTTP_NO_CONTENT:
-    if (NULL != whh->hres_cb)
-      (void) whh->hres_cb (whh->hres_cb_cls,
-                           ec,
-                           TALER_BANK_DIRECTION_NONE,
-                           NULL,
-                           0,
-                           NULL);
-    whh->hh = NULL;
-    taler_bank_get_history_cancel (NULL,
-                                   whh);
-    return;
-  default:
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                "Bank failed with HTTP status %u (EC: %u)\n",
-                http_status,
-                ec);
-    if (NULL != whh->hres_cb)
-      (void) whh->hres_cb (whh->hres_cb_cls,
-                           ec,
-                           TALER_BANK_DIRECTION_NONE,
-                           NULL,
-                           0,
-                           NULL);
-    whh->hh = NULL;
-    taler_bank_get_history_cancel (NULL,
-                                   whh);
-    return;
-  }
-}
-
-
-/**
- * Query transfer history of an account.  We use the variable-size
- * @a start_off to indicate which transfers we are interested in as
- * different banking systems may have different ways to identify
- * transfers.  The @a start_off value must thus match the value of
- * a `row_off` argument previously given to the @a hres_cb.  Use
- * NULL to query transfers from the beginning of time (with
- * positive @a num_results) or from the lataler_bank committed
- * transfers (with negative @a num_results).
- *
- * @param cls the @e cls of this struct with the plugin-specific
- *        state
- * @param account_section specifies the configuration section which
- *        identifies the account for which we should get the history
- * @param direction what kinds of wire transfers should be returned
- * @param start_off from which row on do we want to get results, use NULL for 
the latest; exclusive
- * @param start_off_len number of bytes in @a start_off; must be 
`sizeof(uint64_t)`.
- * @param num_results how many results do we want; negative numbers to go into 
the past,
- *                    positive numbers to go into the future starting at @a 
start_row;
- *                    must not be zero.
- * @param hres_cb the callback to call with the transaction history
- * @param hres_cb_cls closure for the above callback
- */
-static struct TALER_WIRE_HistoryHandle *
-taler_bank_get_history (void *cls,
-                        const char *account_section,
-                        enum TALER_BANK_Direction direction,
-                        const void *start_off,
-                        size_t start_off_len,
-                        int64_t num_results,
-                        TALER_WIRE_HistoryResultCallback hres_cb,
-                        void *hres_cb_cls)
-{
-  struct TalerBankClosure *tc = cls;
-  struct TALER_WIRE_HistoryHandle *whh;
-  const uint64_t *start_off_b64;
-  uint64_t start_row;
-  struct TALER_Account account;
-
-  GNUNET_assert (NULL != hres_cb);
-  if (0 == num_results)
-  {
-    GNUNET_break (0);
-    return NULL;
-  }
-  if (TALER_BANK_DIRECTION_NONE == direction)
-  {
-    GNUNET_break (0);
-    return NULL;
-  }
-  if ( (NULL != start_off) &&
-       (sizeof (uint64_t) != start_off_len) )
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                "Wire plugin 'taler_bank' got"
-                " start offset of wrong size (%llu"
-                " instead of %llu)\n",
-                (unsigned long long) start_off_len,
-                (unsigned long long) sizeof (uint64_t));
-    GNUNET_break (0);
-
-    /**
-     * Probably something is wrong with the DB, some
-     * other component wrote a wrong value to it.  Instead
-     * of completely stopping to work, we just scan from the
-     * beginning. */start_off = NULL;
-  }
-  if (NULL == start_off)
-  {
-    start_row = UINT64_MAX; /* no start row */
-  }
-  else
-  {
-    start_off_b64 = start_off;
-    start_row = GNUNET_ntohll (*start_off_b64);
-  }
-  if (GNUNET_OK !=
-      parse_account_cfg (tc->cfg,
-                         account_section,
-                         &account))
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                "Could not parse the config section '%s'\n",
-                account_section);
-    return NULL;
-  }
-
-  whh = GNUNET_new (struct TALER_WIRE_HistoryHandle);
-  if (GNUNET_OK !=
-      TALER_BANK_auth_parse_cfg (tc->cfg,
-                                 account_section,
-                                 &whh->auth))
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                "Could not parse the auth values from '%s'\n",
-                account_section);
-    TALER_WIRE_account_free (&account);
-    GNUNET_free (whh);
-    return NULL;
-  }
-  whh->hres_cb = hres_cb;
-  whh->hres_cb_cls = hres_cb_cls;
-  whh->hh = TALER_BANK_history (tc->ctx,
-                                account.details.x_taler_bank.bank_base_url,
-                                &whh->auth,
-                                (uint64_t) account.details.x_taler_bank.no,
-                                direction,
-                                /* Defaults to descending ordering always. */
-                                GNUNET_NO,
-                                start_row,
-                                num_results,
-                                &bhist_cb,
-                                whh);
-  if (NULL == whh->hh)
-  {
-    GNUNET_break (0);
-    taler_bank_get_history_cancel (tc,
-                                   whh);
-    TALER_WIRE_account_free (&account);
-    return NULL;
-  }
-  TALER_WIRE_account_free (&account);
-  return whh;
-}
-
-
-/**
- * Context for a rejection operation.
- */
-struct TALER_WIRE_RejectHandle
-{
-  /**
-   * Function to call with the result.
-   */
-  TALER_WIRE_RejectTransferCallback rej_cb;
-
-  /**
-   * Closure for @e rej_cb.
-   */
-  void *rej_cb_cls;
-
-  /**
-   * Handle for the reject operation.
-   */
-  struct TALER_BANK_RejectHandle *brh;
-
-  /**
-   * Authentication information to use.
-   */
-  struct TALER_BANK_AuthenticationData auth;
-};
-
-
-/**
- * Callbacks of this type are used to serve the result of asking
- * the bank to reject an incoming wire transfer.
- *
- * @param cls closure
- * @param http_status HTTP response code, #MHD_HTTP_NO_CONTENT (204) for 
successful status request;
- *                    #MHD_HTTP_NOT_FOUND if the rowid is unknown;
- *                    0 if the bank's reply is bogus (fails to follow the 
protocol),
- * @param ec detailed error code
- */
-static void
-reject_cb (void *cls,
-           unsigned int http_status,
-           enum TALER_ErrorCode ec)
-{
-  struct TALER_WIRE_RejectHandle *rh = cls;
-
-  (void) http_status;
-  rh->brh = NULL;
-  rh->rej_cb (rh->rej_cb_cls,
-              ec);
-  GNUNET_free (rh);
-}
-
-
-/**
- * Cancel ongoing reject operation.  Note that the rejection may still
- * proceed. Basically, if this function is called, the rejection may
- * have happened or not.  This function is usually used during shutdown
- * or system upgrades.  At a later point, the application must call
- * @e reject_transfer again for this wire transfer, unless the
- * @e get_history shows that the wire transfer no longer exists.
- *
- * @param cls plugins' closure
- * @param rh operation to cancel
- * @return closure of the callback of the operation
- */
-static void *
-taler_bank_reject_transfer_cancel (void *cls,
-                                   struct TALER_WIRE_RejectHandle *rh)
-{
-  void *ret = rh->rej_cb_cls;
-
-  (void) cls;
-  if (NULL != rh->brh)
-    TALER_BANK_reject_cancel (rh->brh);
-  TALER_BANK_auth_free (&rh->auth);
-  GNUNET_free (rh);
-  return ret;
-}
-
-
-/**
- * Reject an incoming wire transfer that was obtained from the
- * history. This function can be used to transfer funds back to
- * the sender if the WTID was malformed (i.e. due to a typo).
- *
- * Calling `reject_transfer` twice on the same wire transfer should
- * be idempotent, i.e. not cause the funds to be wired back twice.
- * Furthermore, the transfer should henceforth be removed from the
- * results returned by @e get_history.
- *
- * @param cls plugin's closure
- * @param account_section specifies the configuration section which
- *        identifies the account to use to reject the transfer
- * @param start_off offset of the wire transfer in plugin-specific format
- * @param start_off_len number of bytes in @a start_off
- * @param rej_cb function to call with the result of the operation
- * @param rej_cb_cls closure for @a rej_cb
- * @return handle to cancel the operation
- */
-static struct TALER_WIRE_RejectHandle *
-taler_bank_reject_transfer (void *cls,
-                            const char *account_section,
-                            const void *start_off,
-                            size_t start_off_len,
-                            TALER_WIRE_RejectTransferCallback rej_cb,
-                            void *rej_cb_cls)
-{
-  struct TalerBankClosure *tc = cls;
-  const uint64_t *rowid_b64 = start_off;
-  struct TALER_WIRE_RejectHandle *rh;
-  struct TALER_Account account;
-
-  if (sizeof (uint64_t) != start_off_len)
-  {
-    GNUNET_break (0);
-    return NULL;
-  }
-  rh = GNUNET_new (struct TALER_WIRE_RejectHandle);
-  if (GNUNET_OK !=
-      TALER_BANK_auth_parse_cfg (tc->cfg,
-                                 account_section,
-                                 &rh->auth))
-  {
-    GNUNET_free (rh);
-    return NULL;
-  }
-  if (GNUNET_OK !=
-      parse_account_cfg (tc->cfg,
-                         account_section,
-                         &account))
-  {
-    (void) taler_bank_reject_transfer_cancel (tc,
-                                              rh);
-    return NULL;
-  }
-  rh->rej_cb = rej_cb;
-  rh->rej_cb_cls = rej_cb_cls;
-  TALER_LOG_INFO ("Rejecting over %s bank URL\n",
-                  account.details.x_taler_bank.hostname);
-  rh->brh = TALER_BANK_reject (tc->ctx,
-                               account.details.x_taler_bank.bank_base_url,
-                               &rh->auth,
-                               (uint64_t) account.details.x_taler_bank.no,
-                               GNUNET_ntohll (*rowid_b64),
-                               &reject_cb,
-                               rh);
-  if (NULL == rh->brh)
-  {
-    (void) taler_bank_reject_transfer_cancel (tc,
-                                              rh);
-    TALER_WIRE_account_free (&account);
-    return NULL;
-  }
-  TALER_WIRE_account_free (&account);
-  return rh;
-}
-
-
-/**
- * Initialize taler_bank-wire subsystem.
- *
- * @param cls a configuration instance
- * @return NULL on error, otherwise a `struct TALER_WIRE_Plugin`
- */
-void *
-libtaler_plugin_wire_taler_bank_init (void *cls)
-{
-  struct GNUNET_CONFIGURATION_Handle *cfg = cls;
-  struct TalerBankClosure *tc;
-  struct TALER_WIRE_Plugin *plugin;
-
-  tc = GNUNET_new (struct TalerBankClosure);
-  tc->cfg = cfg;
-  if (GNUNET_OK !=
-      GNUNET_CONFIGURATION_get_value_string (cfg,
-                                             "taler",
-                                             "CURRENCY",
-                                             &tc->currency))
-  {
-    GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
-                               "taler",
-                               "CURRENCY");
-    GNUNET_free (tc);
-    return NULL;
-  }
-  tc->ctx = GNUNET_CURL_init (&GNUNET_CURL_gnunet_scheduler_reschedule,
-                              &tc->rc);
-  tc->rc = GNUNET_CURL_gnunet_rc_create (tc->ctx);
-  if (NULL == tc->ctx)
-  {
-    GNUNET_break (0);
-    GNUNET_free (tc->currency);
-    GNUNET_free (tc);
-    return NULL;
-  }
-  plugin = GNUNET_new (struct TALER_WIRE_Plugin);
-  plugin->cls = tc;
-  plugin->method = "x-taler-bank";
-  plugin->amount_round = &taler_bank_amount_round;
-  plugin->wire_validate = &taler_bank_wire_validate;
-  plugin->prepare_wire_transfer = &taler_bank_prepare_wire_transfer;
-  plugin->prepare_wire_transfer_cancel =
-    &taler_bank_prepare_wire_transfer_cancel;
-  plugin->execute_wire_transfer = &taler_bank_execute_wire_transfer;
-  plugin->execute_wire_transfer_cancel =
-    &taler_bank_execute_wire_transfer_cancel;
-  plugin->get_history = &taler_bank_get_history;
-  plugin->get_history_cancel = &taler_bank_get_history_cancel;
-  plugin->reject_transfer = &taler_bank_reject_transfer;
-  plugin->reject_transfer_cancel = &taler_bank_reject_transfer_cancel;
-  return plugin;
-}
-
-
-/**
- * Shutdown taler-bank wire subsystem.
- *
- * @param cls a `struct TALER_WIRE_Plugin`
- * @return NULL (always)
- */
-void *
-libtaler_plugin_wire_taler_bank_done (void *cls)
-{
-  struct TALER_WIRE_Plugin *plugin = cls;
-  struct TalerBankClosure *tc = plugin->cls;
-
-  if (NULL != tc->ctx)
-  {
-    GNUNET_CURL_fini (tc->ctx);
-    tc->ctx = NULL;
-  }
-  if (NULL != tc->rc)
-  {
-    GNUNET_CURL_gnunet_rc_destroy (tc->rc);
-    tc->rc = NULL;
-  }
-  GNUNET_free_non_null (tc->currency);
-  GNUNET_free (tc);
-  GNUNET_free (plugin);
-  return NULL;
-}
-
-
-/* end of plugin_wire_taler-bank.c */
diff --git a/src/wire-plugins/plugin_wire_template.c 
b/src/wire-plugins/plugin_wire_template.c
deleted file mode 100644
index 731885ac..00000000
--- a/src/wire-plugins/plugin_wire_template.c
+++ /dev/null
@@ -1,384 +0,0 @@
-/*
-  This file is part of TALER
-  Copyright (C) 2016, 2018 GNUnet e.V.
-
-  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 plugin_wire_template.c
- * @brief template for wire plugins; replace "template" with real plugin name!
- * @author Florian Dold
- * @author Christian Grothoff
- * @author Sree Harsha Totakura
- */
-#include "platform.h"
-#include "taler_wire_plugin.h"
-
-
-/**
- * Type of the "cls" argument given to each of the functions in
- * our API.
- */
-struct TemplateClosure
-{
-
-  /**
-   * Which currency do we support?
-   */
-  char *currency;
-
-  /**
-   * Which configuration do we use to lookup accounts?
-   */
-  struct GNUNET_CONFIGURATION_Handle *cfg;
-
-};
-
-
-/**
- * Round amount DOWN to the amount that can be transferred via the wire
- * method.  For example, Taler may support 0.000001 EUR as a unit of
- * payment, but SEPA only supports 0.01 EUR.  This function would
- * round 0.125 EUR to 0.12 EUR in this case.
- *
- * @param cls the @e cls of this struct with the plugin-specific state
- * @param[in,out] amount amount to round down
- * @return #GNUNET_OK on success, #GNUNET_NO if rounding was unnecessary,
- *         #GNUNET_SYSERR if the amount or currency was invalid
- */
-static int
-template_amount_round (void *cls,
-                       struct TALER_Amount *amount)
-{
-  struct TemplateClosure *tc = cls;
-
-  if (0 != strcasecmp (amount->currency,
-                       tc->currency))
-  {
-    GNUNET_break (0);
-    return GNUNET_SYSERR;
-  }
-  GNUNET_break (0); // not implemented
-  return GNUNET_SYSERR;
-}
-
-
-/**
- * Check if the given payto:// URL is correctly formatted for this plugin
- *
- * @param cls the @e cls of this struct with the plugin-specific state
- * @param account_url the payto:// URL
- * @return #TALER_EC_NONE if correctly formatted
- */
-static enum TALER_ErrorCode
-template_wire_validate (void *cls,
-                        const char *account_url)
-{
-  (void) cls;
-  (void) account_url;
-  GNUNET_break (0);
-  return TALER_EC_NOT_IMPLEMENTED;
-}
-
-
-/**
- * Prepare for exeuction of a wire transfer.
- *
- * @param cls the @e cls of this struct with the plugin-specific state
- * @param origin_account_section configuration section specifying the origin
- *        account of the exchange to use
- * @param destination_account_url payto:// URL identifying where to send the 
money
- * @param amount amount to transfer, already rounded
- * @param exchange_base_url base URL of the exchange (for tracking)
- * @param wtid wire transfer identifier to use
- * @param ptc function to call with the prepared data to persist
- * @param ptc_cls closure for @a ptc
- * @return NULL on failure
- */
-static struct TALER_WIRE_PrepareHandle *
-template_prepare_wire_transfer (void *cls,
-                                const char *origin_account_section,
-                                const char *destination_account_url,
-                                const struct TALER_Amount *amount,
-                                const char *exchange_base_url,
-                                const struct
-                                TALER_WireTransferIdentifierRawP *wtid,
-                                TALER_WIRE_PrepareTransactionCallback ptc,
-                                void *ptc_cls)
-{
-  (void) cls;
-  (void) origin_account_section;
-  (void) destination_account_url;
-  (void) amount;
-  (void) exchange_base_url;
-  (void) wtid;
-  (void) ptc;
-  (void) ptc_cls;
-  GNUNET_break (0);
-  return NULL;
-}
-
-
-/**
- * Abort preparation of a wire transfer. For example,
- * because we are shutting down.
- *
- * @param cls the @e cls of this struct with the plugin-specific state
- * @param pth preparation to cancel
- */
-static void
-template_prepare_wire_transfer_cancel (void *cls,
-                                       struct TALER_WIRE_PrepareHandle *pth)
-{
-  (void) cls;
-  (void) pth;
-  GNUNET_break (0);
-}
-
-
-/**
- * Execute a wire transfer.
- *
- * @param cls the @e cls of this struct with the plugin-specific state
- * @param buf buffer with the prepared execution details
- * @param buf_size number of bytes in @a buf
- * @param cc function to call upon success
- * @param cc_cls closure for @a cc
- * @return NULL on error
- */
-static struct TALER_WIRE_ExecuteHandle *
-template_execute_wire_transfer (void *cls,
-                                const char *buf,
-                                size_t buf_size,
-                                TALER_WIRE_ConfirmationCallback cc,
-                                void *cc_cls)
-{
-  (void) cls;
-  (void) buf;
-  (void) buf_size;
-  (void) cc;
-  (void) cc_cls;
-  GNUNET_break (0);
-  return NULL;
-}
-
-
-/**
- * Abort execution of a wire transfer. For example, because we are
- * shutting down.  Note that if an execution is aborted, it may or
- * may not still succeed. The caller MUST run @e
- * execute_wire_transfer again for the same request as soon as
- * possilbe, to ensure that the request either ultimately succeeds
- * or ultimately fails. Until this has been done, the transaction is
- * in limbo (i.e. may or may not have been committed).
- *
- * @param cls the @e cls of this struct with the plugin-specific state
- * @param eh execution to cancel
- */
-static void
-template_execute_wire_transfer_cancel (void *cls,
-                                       struct TALER_WIRE_ExecuteHandle *eh)
-{
-  (void) cls;
-  (void) eh;
-  GNUNET_break (0);
-}
-
-
-/**
- * Query transfer history of an account.  We use the variable-size
- * @a start_off to indicate which transfers we are interested in as
- * different banking systems may have different ways to identify
- * transfers.  The @a start_off value must thus match the value of
- * a `row_off` argument previously given to the @a hres_cb.  Use
- * NULL to query transfers from the beginning of time (with
- * positive @a num_results) or from the latest committed transfers
- * (with negative @a num_results).
- *
- * @param cls the @e cls of this struct with the plugin-specific state
- * @param account_section specifies the configuration section which
- *        identifies the account for which we should get the history
- * @param direction what kinds of wire transfers should be returned
- * @param start_off from which row on do we want to get results, use NULL for 
the latest; exclusive
- * @param start_off_len number of bytes in @a start_off; must be 
`sizeof(uint64_t)`.
- * @param num_results how many results do we want; negative numbers to go into 
the past,
- *                    positive numbers to go into the future starting at @a 
start_row;
- *                    must not be zero.
- * @param hres_cb the callback to call with the transaction history
- * @param hres_cb_cls closure for the above callback
- */
-static struct TALER_WIRE_HistoryHandle *
-template_get_history (void *cls,
-                      const char *account_section,
-                      enum TALER_BANK_Direction direction,
-                      const void *start_off,
-                      size_t start_off_len,
-                      int64_t num_results,
-                      TALER_WIRE_HistoryResultCallback hres_cb,
-                      void *hres_cb_cls)
-{
-  (void) cls;
-  (void) account_section;
-  (void) direction;
-  (void) start_off;
-  (void) start_off_len;
-  (void) num_results;
-  (void) hres_cb;
-  (void) hres_cb_cls;
-  GNUNET_break (0);
-  return NULL;
-}
-
-
-/**
- * Cancel going over the account's history.
- *
- * @param cls the @e cls of this struct with the plugin-specific state
- * @param whh operation to cancel
- */
-static void
-template_get_history_cancel (void *cls,
-                             struct TALER_WIRE_HistoryHandle *whh)
-{
-  (void) cls;
-  (void) whh;
-  GNUNET_break (0);
-}
-
-
-/**
- * Reject an incoming wire transfer that was obtained from the
- * history. This function can be used to transfer funds back to
- * the sender if the WTID was malformed (i.e. due to a typo).
- *
- * Calling `reject_transfer` twice on the same wire transfer should
- * be idempotent, i.e. not cause the funds to be wired back twice.
- * Furthermore, the transfer should henceforth be removed from the
- * results returned by @e get_history.
- *
- * @param cls plugin's closure
- * @param account_section specifies the configuration section which
- *        identifies the account to use to reject the transfer
- * @param start_off offset of the wire transfer in plugin-specific format
- * @param start_off_len number of bytes in @a start_off
- * @param rej_cb function to call with the result of the operation
- * @param rej_cb_cls closure for @a rej_cb
- * @return handle to cancel the operation
- */
-static struct TALER_WIRE_RejectHandle *
-template_reject_transfer (void *cls,
-                          const char *account_section,
-                          const void *start_off,
-                          size_t start_off_len,
-                          TALER_WIRE_RejectTransferCallback rej_cb,
-                          void *rej_cb_cls)
-{
-  (void) cls;
-  (void) account_section;
-  (void) start_off;
-  (void) start_off_len;
-  (void) rej_cb;
-  (void) rej_cb_cls;
-  GNUNET_break (0);
-  return NULL;
-}
-
-
-/**
- * Cancel ongoing reject operation.  Note that the rejection may still
- * proceed. Basically, if this function is called, the rejection may
- * have happened or not.  This function is usually used during shutdown
- * or system upgrades.  At a later point, the application must call
- * @e reject_transfer again for this wire transfer, unless the
- * @e get_history shows that the wire transfer no longer exists.
- *
- * @param cls plugins' closure
- * @param rh operation to cancel
- * @return closure of the callback of the operation
- */
-static void *
-template_reject_transfer_cancel (void *cls,
-                                 struct TALER_WIRE_RejectHandle *rh)
-{
-  (void) cls;
-  (void) rh;
-  GNUNET_break (0);
-  return NULL;
-}
-
-
-/**
- * Initialize template-wire subsystem.
- *
- * @param cls a configuration instance
- * @return NULL on error, otherwise a `struct TALER_WIRE_Plugin`
- */
-void *
-libtaler_plugin_wire_template_init (void *cls)
-{
-  struct GNUNET_CONFIGURATION_Handle *cfg = cls;
-  struct TemplateClosure *tc;
-  struct TALER_WIRE_Plugin *plugin;
-
-  tc = GNUNET_new (struct TemplateClosure);
-  tc->cfg = cfg;
-  if (GNUNET_OK !=
-      GNUNET_CONFIGURATION_get_value_string (cfg,
-                                             "taler",
-                                             "CURRENCY",
-                                             &tc->currency))
-  {
-    GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
-                               "taler",
-                               "CURRENCY");
-    GNUNET_free (tc);
-    return NULL;
-  }
-
-  plugin = GNUNET_new (struct TALER_WIRE_Plugin);
-  plugin->cls = tc;
-  plugin->method = "FIXME-REPLACE-BY-METHOD";
-  plugin->amount_round = &template_amount_round;
-  plugin->wire_validate = &template_wire_validate;
-  plugin->prepare_wire_transfer = &template_prepare_wire_transfer;
-  plugin->prepare_wire_transfer_cancel = 
&template_prepare_wire_transfer_cancel;
-  plugin->execute_wire_transfer = &template_execute_wire_transfer;
-  plugin->execute_wire_transfer_cancel = 
&template_execute_wire_transfer_cancel;
-  plugin->get_history = &template_get_history;
-  plugin->get_history_cancel = &template_get_history_cancel;
-  plugin->reject_transfer = &template_reject_transfer;
-  plugin->reject_transfer_cancel = &template_reject_transfer_cancel;
-  return plugin;
-}
-
-
-/**
- * Shutdown Template wire subsystem.
- *
- * @param cls a `struct TALER_WIRE_Plugin`
- * @return NULL (always)
- */
-void *
-libtaler_plugin_wire_template_done (void *cls)
-{
-  struct TALER_WIRE_Plugin *plugin = cls;
-  struct TemplateClosure *tc = plugin->cls;
-
-  GNUNET_free (tc->currency);
-  GNUNET_free (tc);
-  GNUNET_free (plugin);
-  return NULL;
-}
-
-
-/* end of plugin_wire_template.c */
diff --git a/src/wire-plugins/test_wire_plugin.c 
b/src/wire-plugins/test_wire_plugin.c
deleted file mode 100644
index 65867113..00000000
--- a/src/wire-plugins/test_wire_plugin.c
+++ /dev/null
@@ -1,189 +0,0 @@
-/*
-  This file is part of TALER
-  (C) 2015, 2016, 2017 GNUnet e.V. and Inria
-
-  TALER is free software; you can redistribute it and/or modify it under the
-  terms of the GNU General Public License as published by the Free Software
-  Foundation; either version 3, or (at your option) any later version.
-
-  TALER is distributed in the hope that it will be useful, but WITHOUT ANY
-  WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
-  A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
-
-  You should have received a copy of the GNU General Public License along with
-  TALER; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
-*/
-/**
- * @file wire/test_wire_plugin.c
- * @brief Tests for wire plugins
- * @author Christian Grothoff
- * @author Sree Harsha Totakura <address@hidden>
- */
-#include "platform.h"
-#include "taler_util.h"
-#include "taler_wire_lib.h"
-#include "taler_wire_plugin.h"
-#include <gnunet/gnunet_json_lib.h>
-
-
-/**
- * Definitions for a test with a plugin.
- */
-struct TestBlock
-{
-
-  /**
-   * Name of the plugin to test.
-   */
-  const char *plugin_name;
-
-  /**
-   * Amount to give to the rounding function.
-   */
-  const char *round_in;
-
-  /**
-   * Expected result from rounding.
-   */
-  const char *round_out;
-
-  /**
-   * Currency to give to the plugin.
-   */
-  const char *currency;
-};
-
-
-/**
- * List of plugins and (unsigned) JSON account definitions
- * to use for the tests.
- */
-static struct TestBlock tests[] = {
-#if HAVE_LIBCURL
-  {
-    .plugin_name = "taler_bank",
-    .round_in = "KUDOS:0.123456",
-    .round_out = "KUDOS:0.12",
-    .currency = "KUDOS"
-  },
-#endif
-  {
-    NULL, NULL, NULL, NULL
-  }
-};
-
-
-/**
- * Our configuration.
- */
-static struct GNUNET_CONFIGURATION_Handle *cfg;
-
-
-/**
- * Run the test.
- *
- * @param test details of the test
- * @param plugin plugin to test
- * @return #GNUNET_OK on success
- */
-static int
-run_test (const struct TestBlock *test,
-          struct TALER_WIRE_Plugin *plugin)
-{
-  struct GNUNET_HashCode salt;
-  struct TALER_Amount in;
-  struct TALER_Amount expect;
-
-  GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_NONCE,
-                              &salt,
-                              sizeof (salt));
-  GNUNET_assert (GNUNET_OK ==
-                 TALER_string_to_amount (test->round_in,
-                                         &in));
-  GNUNET_assert (GNUNET_OK ==
-                 TALER_string_to_amount (test->round_out,
-                                         &expect));
-  if (GNUNET_OK !=
-      plugin->amount_round (plugin->cls,
-                            &in))
-  {
-    GNUNET_break (0);
-    return GNUNET_SYSERR;
-  }
-  if (0 != TALER_amount_cmp (&in, &expect))
-  {
-    GNUNET_break (0);
-    return GNUNET_SYSERR;
-  }
-  if (GNUNET_NO !=
-      plugin->amount_round (plugin->cls,
-                            &in))
-  {
-    GNUNET_break (0);
-    return GNUNET_SYSERR;
-  }
-  memset (&in, 0, sizeof (in));
-  GNUNET_log_skip (GNUNET_ERROR_TYPE_ERROR, 1);
-  if (GNUNET_SYSERR !=
-      plugin->amount_round (plugin->cls,
-                            &in))
-  {
-    GNUNET_break (0);
-    return GNUNET_SYSERR;
-  }
-  return GNUNET_OK;
-}
-
-
-int
-main (int argc,
-      const char *const argv[])
-{
-  int ret;
-  struct TALER_WIRE_Plugin *plugin;
-  const struct TestBlock *test;
-
-  GNUNET_log_setup ("test-wire-plugin",
-                    "WARNING",
-                    NULL);
-  cfg = GNUNET_CONFIGURATION_create ();
-  GNUNET_assert (GNUNET_OK ==
-                 GNUNET_CONFIGURATION_load (cfg,
-                                            "test_wire_plugin.conf"));
-  ret = GNUNET_OK;
-  for (unsigned int i = 0; NULL != (test = &tests[i])->plugin_name; i++)
-  {
-    GNUNET_CONFIGURATION_set_value_string (cfg,
-                                           "taler",
-                                           "CURRENCY",
-                                           test->currency);
-    plugin = TALER_WIRE_plugin_load (cfg,
-                                     test->plugin_name);
-    if (NULL == plugin)
-    {
-      TALER_LOG_ERROR ("Could not load plugin `%s'\n",
-                       test->plugin_name);
-      return 77;
-    }
-
-    ret = run_test (test, plugin);
-    TALER_WIRE_plugin_unload (plugin);
-    if (GNUNET_OK != ret)
-    {
-      GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                  "%s FAILED\n",
-                  test->plugin_name);
-      break;
-    }
-    else
-    {
-      GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
-                  "%s PASS\n",
-                  test->plugin_name);
-    }
-  }
-  GNUNET_CONFIGURATION_destroy (cfg);
-  if (GNUNET_OK != ret)
-    return 1;
-  return 0;
-}
diff --git a/src/wire-plugins/test_wire_plugin.conf 
b/src/wire-plugins/test_wire_plugin.conf
deleted file mode 100644
index d1d699b0..00000000
--- a/src/wire-plugins/test_wire_plugin.conf
+++ /dev/null
@@ -1,25 +0,0 @@
-# This file is in the public domain.
-#
-[account-taler-bank]
-# This is the response we give out for the /wire request.  It provides
-# wallets with the bank information for transfers to the exchange.
-WIRE_JSON = test_wire_plugin_test.json
-
-# Our bank account URL
-URL = payto://x-taler-bank/2
-
-# Which wire plugin should we used to access the account?
-PLUGIN = taler_bank
-
-
-[account-sepa]
-# This is the response we give out for the /wire request.  It provides
-# wallets with the bank information for transfers to the exchange.
-WIRE_JSON = test_wire_plugin_sepa.json
-
-# Which wire plugin should we used to access the account?
-PLUGIN = ebics
-
-
-[taler]
-CURRENCY = "EUR"
diff --git a/src/wire-plugins/test_wire_plugin_transactions_taler-bank.c 
b/src/wire-plugins/test_wire_plugin_transactions_taler-bank.c
deleted file mode 100644
index 79700818..00000000
--- a/src/wire-plugins/test_wire_plugin_transactions_taler-bank.c
+++ /dev/null
@@ -1,365 +0,0 @@
-/*
-  This file is part of TALER
-  (C) 2015-2018 Taler Systems SA
-
-  TALER is free software; you can redistribute it and/or modify it under the
-  terms of the GNU General Public License as published by the Free Software
-  Foundation; either version 3, or (at your option) any later version.
-
-  TALER is distributed in the hope that it will be useful, but WITHOUT ANY
-  WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
-  A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
-
-  You should have received a copy of the GNU General Public License along with
-  TALER; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
-*/
-/**
- * @file wire/test_wire_plugin_transactions_taler-bank.c
- * @brief Tests performing actual transactions with the taler-bank wire plugin 
against FAKEBANK
- * @author Christian Grothoff
- */
-#include "platform.h"
-#include "taler_util.h"
-#include "taler_wire_lib.h"
-#include "taler_wire_plugin.h"
-#include "taler_fakebank_lib.h"
-#include <gnunet/gnunet_json_lib.h>
-
-
-/**
- * When does the test timeout? Right now, we expect this to be very
- * fast.
- */
-#define TIMEOUT GNUNET_TIME_UNIT_SECONDS
-
-
-/**
- * Destination account to use.
- */
-static const char *dest_account = "payto://x-taler-bank/localhost:8088/42";
-
-/**
- * Origin account, section in the configuration file.
- */
-static const char *my_account = "account-test";
-
-/**
- * Our configuration.
- */
-static struct GNUNET_CONFIGURATION_Handle *cfg;
-
-/**
- * Set to #GNUNET_SYSERR if the test failed.
- */
-static int global_ret;
-
-/**
- * The 'test' plugin that we are using for the test.
- */
-static struct TALER_WIRE_Plugin *plugin;
-
-/**
- * Active preparation handle, or NULL if not active.
- */
-static struct TALER_WIRE_PrepareHandle *ph;
-
-/**
- * Active execution handle, or NULL if not active.
- */
-static struct TALER_WIRE_ExecuteHandle *eh;
-
-/**
- * Handle to the bank.
- */
-static struct TALER_FAKEBANK_Handle *fb;
-
-/**
- * Handle to the history request.
- */
-static struct TALER_WIRE_HistoryHandle *hh;
-
-/**
- * Handle to the history-range request (the "legacy" bank API).
- */
-static struct TALER_WIRE_HistoryHandle *hhr;
-
-/**
- * Handle for the timeout task.
- */
-static struct GNUNET_SCHEDULER_Task *tt;
-
-/**
- * Which serial ID do we expect to get from /history?
- */
-static uint64_t serial_target;
-
-/**
- * Wire transfer identifier we are using.
- */
-static struct TALER_WireTransferIdentifierRawP wtid;
-
-
-/**
- * Function called on shutdown (regular, error or CTRL-C).
- *
- * @param cls NULL
- */
-static void
-do_shutdown (void *cls)
-{
-  (void) cls;
-  TALER_FAKEBANK_stop (fb);
-  fb = NULL;
-  if (NULL != eh)
-  {
-    plugin->execute_wire_transfer_cancel (plugin->cls,
-                                          eh);
-    eh = NULL;
-  }
-  if (NULL != ph)
-  {
-    plugin->prepare_wire_transfer_cancel (plugin->cls,
-                                          ph);
-    ph = NULL;
-  }
-  if (NULL != hh)
-  {
-    plugin->get_history_cancel (plugin->cls,
-                                hh);
-    hh = NULL;
-  }
-
-  if (NULL != hhr)
-  {
-    plugin->get_history_cancel (plugin->cls,
-                                hhr);
-    hhr = NULL;
-  }
-
-  if (NULL != tt)
-  {
-    GNUNET_SCHEDULER_cancel (tt);
-    tt = NULL;
-  }
-  TALER_WIRE_plugin_unload (plugin);
-}
-
-
-/**
- * Function called on timeout.
- *
- * @param cls NULL
- */
-static void
-timeout_cb (void *cls)
-{
-  tt = NULL;
-  GNUNET_break (0);
-  global_ret = GNUNET_SYSERR;
-  GNUNET_SCHEDULER_shutdown ();
-}
-
-
-/**
- * Callbacks of this type are used to serve the result of asking
- * the bank for the transaction history.
- *
- * @param cls closure
- * @param ec taler status code
- * @param dir direction of the transfer
- * @param row_off identification of the position at
- *        which we are querying
- * @param row_off_size number of bytes in @a row_off
- * @param details details about the wire transfer
- * @return #GNUNET_OK to continue, #GNUNET_SYSERR to
- *         abort iteration
- */
-static int
-history_result_cb
-  (void *cls,
-  enum TALER_ErrorCode ec,
-  enum TALER_BANK_Direction dir,
-  const void *row_off,
-  size_t row_off_size,
-  const struct TALER_WIRE_TransferDetails *details)
-{
-  uint64_t *serialp;
-  uint64_t serialh;
-  struct TALER_Amount amount;
-
-  if ( (TALER_BANK_DIRECTION_NONE == dir) &&
-       (GNUNET_OK == global_ret) )
-  {
-    GNUNET_SCHEDULER_shutdown ();
-    hh = NULL;
-    return GNUNET_OK;
-  }
-  if (sizeof (uint64_t) != row_off_size)
-  {
-    GNUNET_break (0);
-    global_ret = GNUNET_SYSERR;
-    GNUNET_SCHEDULER_shutdown ();
-    return GNUNET_SYSERR;
-  }
-  serialp = (uint64_t *) row_off;
-  serialh = GNUNET_ntohll (*serialp);
-  if (serialh != serial_target)
-  {
-    GNUNET_break (0);
-    global_ret = GNUNET_SYSERR;
-    GNUNET_SCHEDULER_shutdown ();
-    return GNUNET_SYSERR;
-  }
-  GNUNET_assert (GNUNET_OK ==
-                 TALER_string_to_amount ("KUDOS:5.01",
-                                         &amount));
-  if (0 != TALER_amount_cmp (&amount,
-                             &details->amount))
-  {
-    GNUNET_break (0);
-    global_ret = GNUNET_SYSERR;
-    GNUNET_SCHEDULER_shutdown ();
-    return GNUNET_SYSERR;
-  }
-  if (0 != GNUNET_memcmp (&wtid,
-                          &details->wtid))
-  {
-    GNUNET_break (0);
-    global_ret = GNUNET_SYSERR;
-    GNUNET_SCHEDULER_shutdown ();
-    return GNUNET_SYSERR;
-  }
-  global_ret = GNUNET_OK;
-  return GNUNET_OK;
-}
-
-
-/**
- * Function called with the result from the execute step.
- *
- * @param cls closure
- * @param success #GNUNET_OK on success,
- *        #GNUNET_SYSERR on failure
- * @param row_id ID of the fresh transaction,
- *        in _network_ byte order.
- * @param emsg NULL on success, otherwise an error message
- */
-static void
-confirmation_cb (void *cls,
-                 int success,
-                 const void *row_id,
-                 size_t row_id_size,
-                 const char *emsg)
-{
-  uint64_t tmp;
-
-  eh = NULL;
-  if (GNUNET_OK != success)
-  {
-    GNUNET_break (0);
-    global_ret = GNUNET_SYSERR;
-    GNUNET_SCHEDULER_shutdown ();
-    return;
-  }
-  memcpy (&tmp,
-          row_id,
-          row_id_size);
-  serial_target = GNUNET_ntohll (tmp);
-  hh = plugin->get_history (plugin->cls,
-                            my_account,
-                            TALER_BANK_DIRECTION_BOTH,
-                            NULL,
-                            0,
-                            5,
-                            &history_result_cb,
-                            NULL);
-}
-
-
-/**
- * Callback with prepared transaction.
- *
- * @param cls closure
- * @param buf transaction data to persist, NULL on error
- * @param buf_size number of bytes in @a buf, 0 on error
- */
-static void
-prepare_cb (void *cls,
-            const char *buf,
-            size_t buf_size)
-{
-  ph = NULL;
-  if (NULL == buf)
-  {
-    GNUNET_break (0);
-    global_ret = GNUNET_SYSERR;
-    GNUNET_SCHEDULER_shutdown ();
-    return;
-  }
-  plugin->execute_wire_transfer (plugin->cls,
-                                 buf,
-                                 buf_size,
-                                 &confirmation_cb,
-                                 NULL);
-}
-
-
-/**
- * Run the test.
- *
- * @param cls NULL
- */
-static void
-run (void *cls)
-{
-  struct TALER_Amount amount;
-
-  GNUNET_SCHEDULER_add_shutdown (&do_shutdown,
-                                 NULL);
-  tt = GNUNET_SCHEDULER_add_delayed (TIMEOUT,
-                                     &timeout_cb,
-                                     NULL);
-  GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_WEAK,
-                              &wtid,
-                              sizeof (wtid));
-  GNUNET_assert (GNUNET_OK ==
-                 TALER_string_to_amount ("KUDOS:5.01",
-                                         &amount));
-  fb = TALER_FAKEBANK_start (8088);
-  ph = plugin->prepare_wire_transfer (plugin->cls,
-                                      my_account,
-                                      dest_account,
-                                      &amount,
-                                      "https://exchange.net/";,
-                                      &wtid,
-                                      &prepare_cb,
-                                      NULL);
-}
-
-
-int
-main (int argc,
-      const char *const argv[])
-{
-
-  GNUNET_log_setup ("test-wire-plugin-transactions-test",
-                    "WARNING",
-                    NULL);
-  cfg = GNUNET_CONFIGURATION_create ();
-  GNUNET_assert (GNUNET_OK ==
-                 GNUNET_CONFIGURATION_load (cfg,
-                                            
"test_wire_plugin_transactions_taler-bank.conf"));
-  global_ret = GNUNET_OK;
-  plugin = TALER_WIRE_plugin_load (cfg,
-                                   "taler_bank");
-  GNUNET_assert (NULL != plugin);
-  GNUNET_SCHEDULER_run (&run,
-                        NULL);
-  GNUNET_CONFIGURATION_destroy (cfg);
-  if (GNUNET_OK != global_ret)
-    return 1;
-  return 0;
-}
-
-
-/* end of test_wire_plugin_transactions_taler-bank.c */
diff --git a/src/wire-plugins/test_wire_plugin_transactions_taler-bank.conf 
b/src/wire-plugins/test_wire_plugin_transactions_taler-bank.conf
deleted file mode 100644
index d6d2e834..00000000
--- a/src/wire-plugins/test_wire_plugin_transactions_taler-bank.conf
+++ /dev/null
@@ -1,12 +0,0 @@
-# This file is in the public domain.
-#
-[account-test]
-# This is the response we give out for the /wire request.  It provides
-# wallets with the bank information for transfers to the exchange.
-
-TALER_BANK_AUTH_METHOD = NONE
-
-URL = payto://x-taler-bank/localhost:8088/2
-
-[taler]
-CURRENCY = "KUDOS"
diff --git a/src/wire/Makefile.am b/src/wire/Makefile.am
index 6bf38aa2..2a82282a 100644
--- a/src/wire/Makefile.am
+++ b/src/wire/Makefile.am
@@ -13,7 +13,6 @@ lib_LTLIBRARIES = \
 
 libtalerwire_la_SOURCES = \
   payto.c \
-  wire.c \
   wire_helper.c
 libtalerwire_la_LIBADD = \
   -lgnunetutil \
diff --git a/src/wire/payto.c b/src/wire/payto.c
index 74154977..0c3fce95 100644
--- a/src/wire/payto.c
+++ b/src/wire/payto.c
@@ -20,6 +20,7 @@
  */
 #include "platform.h"
 #include "taler_util.h"
+#include "taler_bank_service.h"
 #include "taler_wire_lib.h"
 
 /**
@@ -43,8 +44,8 @@ TALER_WIRE_account_free (struct TALER_Account *acc)
   case TALER_PAC_X_TALER_BANK:
     GNUNET_free (acc->details.x_taler_bank.hostname);
     acc->details.x_taler_bank.hostname = NULL;
-    GNUNET_free (acc->details.x_taler_bank.bank_base_url);
-    acc->details.x_taler_bank.bank_base_url = NULL;
+    GNUNET_free (acc->details.x_taler_bank.account_base_url);
+    acc->details.x_taler_bank.account_base_url = NULL;
     break;
   case TALER_PAC_IBAN:
     GNUNET_free (acc->details.iban.number);
@@ -410,7 +411,8 @@ parse_payto_x_taler_bank (const char *account_url,
   const char *hostname;
   const char *account;
   const char *q;
-  unsigned long long no;
+  unsigned int port;
+  char *p;
 
 #define PREFIX "payto://x-taler-bank/"
   if (0 != strncasecmp (account_url,
@@ -422,74 +424,52 @@ parse_payto_x_taler_bank (const char *account_url,
                                  (unsigned char) '/')))
     return TALER_EC_PAYTO_MALFORMED;
   account++;
-  if (NULL != (q = strchr (account,
-                           (unsigned char) '?')))
+  if (NULL == r_account)
+    return TALER_EC_NONE;
+  q = strchr (account,
+              (unsigned char) '?');
+  if (0 == q)
+    q = account + strlen (account);
+  r_account->details.x_taler_bank.hostname
+    = GNUNET_strndup (hostname,
+                      account - hostname);
+  port = 443; /* if non given, equals 443.  */
+  if (NULL != (p = strchr (r_account->details.x_taler_bank.hostname,
+                           (unsigned char) ':')))
   {
-    char *s;
-
-    s = GNUNET_strndup (account,
-                        q - account);
-    if (1 != sscanf (s,
-                     "%llu",
-                     &no))
+    p++;
+    if (1 != sscanf (p,
+                     "%u",
+                     &port))
     {
-      GNUNET_free (s);
+      GNUNET_break (0);
+      TALER_LOG_ERROR ("Malformed host from payto:// URI\n");
+      GNUNET_free (r_account->details.x_taler_bank.hostname);
+      r_account->details.x_taler_bank.hostname = NULL;
       return TALER_EC_PAYTO_MALFORMED;
     }
-    GNUNET_free (s);
   }
-  else if (1 != sscanf (account,
-                        "%llu",
-                        &no))
+  if (443 != port)
   {
-    return TALER_EC_PAYTO_MALFORMED;
+    GNUNET_assert
+      (GNUNET_SYSERR != GNUNET_asprintf
+        (&r_account->details.x_taler_bank.account_base_url,
+        "http://%s/%.*s";,
+        r_account->details.x_taler_bank.hostname,
+        (int) (q - account),
+        account));
   }
-  if (no > MAX_ACCOUNT_NO)
-    return TALER_EC_PAYTO_MALFORMED;
-
-  if (NULL != r_account)
+  else
   {
-    long long unsigned port;
-    char *p;
-
-    r_account->details.x_taler_bank.hostname
-      = GNUNET_strndup (hostname,
-                        account - hostname);
-    r_account->details.x_taler_bank.no = no;
-    port = 443; /* if non given, equals 443.  */
-    if (NULL != (p = strchr (r_account->details.x_taler_bank.hostname,
-                             (unsigned char) ':')))
-    {
-      p++;
-      if (1 != sscanf (p,
-                       "%llu",
-                       &port))
-      {
-        GNUNET_break (0);
-        TALER_LOG_ERROR ("Malformed host from payto:// URI\n");
-        GNUNET_free (r_account->details.x_taler_bank.hostname);
-        r_account->details.x_taler_bank.hostname = NULL;
-        return TALER_EC_PAYTO_MALFORMED;
-      }
-    }
-    if (443 != port)
-    {
-      GNUNET_assert
-        (GNUNET_SYSERR != GNUNET_asprintf
-          (&r_account->details.x_taler_bank.bank_base_url,
-          "http://%s";,
-          r_account->details.x_taler_bank.hostname));
-    }
-    else
-    {
-      GNUNET_assert
-        (GNUNET_SYSERR != GNUNET_asprintf
-          (&r_account->details.x_taler_bank.bank_base_url,
-          "https://%s";,
-          r_account->details.x_taler_bank.hostname));
-    }
-    r_account->type = TALER_PAC_X_TALER_BANK;
+    GNUNET_assert
+      (GNUNET_SYSERR != GNUNET_asprintf
+        (&r_account->details.x_taler_bank.account_base_url,
+        "https://%s/%.*s";,
+        r_account->details.x_taler_bank.hostname,
+        (int) (q - account),
+        account));
   }
+  r_account->type = TALER_PAC_X_TALER_BANK;
   return TALER_EC_NONE;
 }
 
diff --git a/src/wire/wire.c b/src/wire/wire.c
deleted file mode 100644
index 60ae9e6e..00000000
--- a/src/wire/wire.c
+++ /dev/null
@@ -1,149 +0,0 @@
-/*
-  This file is part of TALER
-  (C) 2015, 2016, 2017, 2018 GNUnet e.V.
-
-  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 wire/wire.c
- * @brief Functions for loading wire plugins
- * @author Christian Grothoff <address@hidden>
- */
-#include "platform.h"
-#include "taler_util.h"
-#include "taler_wire_lib.h"
-
-
-/**
- * A wire plugin that we have loaded.
- */
-struct WirePlugin
-{
-  /**
-   * We keep these in a DLL.
-   */
-  struct WirePlugin *next;
-
-  /**
-   * We keep these in a DLL.
-   */
-  struct WirePlugin *prev;
-
-  /**
-   * Type of this wire plugin.
-   */
-  char *type;
-
-  /**
-   * Wire plugin
-   */
-  struct TALER_WIRE_Plugin *plugin;
-
-  /**
-   * Reference counter for the plugin.
-   */
-  unsigned int rc;
-};
-
-
-/**
- * Head of the DLL of loaded wire plugins.
- */
-static struct WirePlugin *wp_head;
-
-/**
- * Tail of the DLL of loaded wire plugins.
- */
-static struct WirePlugin *wp_tail;
-
-
-/**
- * Load a WIRE plugin.
- *
- * @param cfg configuration to use
- * @param plugin_name name of the plugin to load
- * @return the plugin object pointer, or NULL upon errors.
- */
-struct TALER_WIRE_Plugin *
-TALER_WIRE_plugin_load (const struct GNUNET_CONFIGURATION_Handle *cfg,
-                        const char *plugin_name)
-{
-  char *lib_name;
-  struct TALER_WIRE_Plugin *plugin;
-  struct WirePlugin *wp;
-
-  for (wp = wp_head; NULL != wp; wp = wp->next)
-    if (0 == strcasecmp (plugin_name,
-                         wp->type))
-    {
-      wp->rc++;
-      return wp->plugin;
-    }
-  (void) GNUNET_asprintf (&lib_name,
-                          "libtaler_plugin_wire_%s",
-                          plugin_name);
-  plugin = GNUNET_PLUGIN_load (lib_name,
-                               (void *) cfg);
-  if (NULL != plugin)
-    plugin->library_name = lib_name;
-  else
-    GNUNET_free (lib_name);
-  if (NULL == plugin)
-    return NULL;
-  wp = GNUNET_new (struct WirePlugin);
-  wp->plugin = plugin;
-  wp->type = GNUNET_strdup (plugin_name);
-  GNUNET_CONTAINER_DLL_insert (wp_head,
-                               wp_tail,
-                               wp);
-  wp->rc = 1;
-  return plugin;
-}
-
-
-/**
- * Unload a WIRE plugin.
- *
- * @param plugin the plugin to unload
- */
-void
-TALER_WIRE_plugin_unload (struct TALER_WIRE_Plugin *plugin)
-{
-  struct WirePlugin *wp;
-  char *lib_name;
-
-  if (NULL == plugin)
-    return;
-  for (wp = wp_head; NULL != wp; wp = wp->next)
-  {
-    if (plugin == wp->plugin)
-    {
-      wp->rc--;
-      if (0 < wp->rc)
-        return;
-      GNUNET_CONTAINER_DLL_remove (wp_head,
-                                   wp_tail,
-                                   wp);
-      GNUNET_free (wp->type);
-      GNUNET_free (wp);
-      break;
-    }
-  }
-  lib_name = plugin->library_name;
-  GNUNET_assert (NULL == GNUNET_PLUGIN_unload (lib_name,
-                                               plugin));
-  GNUNET_free (lib_name);
-}
-
-
-/* end of wire.c */
diff --git a/src/wire/wire_helper.c b/src/wire/wire_helper.c
index e6253983..4b7f092a 100644
--- a/src/wire/wire_helper.c
+++ b/src/wire/wire_helper.c
@@ -20,6 +20,7 @@
 /**
  * @file wire/wire_helper.c
  * @brief Helper functions for dealing with wire formats
+
  * @author Christian Grothoff <address@hidden>
  */
 #include "platform.h"
@@ -32,23 +33,6 @@
 #define PAYTO "payto://"
 
 
-/**
- * Maps wire methods to plugin names.
- */
-struct ConversionTable
-{
-
-  /**
-   * Wire method (e.g. 'iban', 'x-taler-bank', ..)
-   */
-  const char *method;
-
-  /**
-   * Plugin name, e.g. 'taler_bank', ..
-   */
-  const char *plugin_name;
-};
-
 /**
  * Obtain the payment method from a @a payto_url
  *
@@ -76,35 +60,23 @@ TALER_WIRE_payto_get_method (const char *payto_url)
 
 
 /**
- * Get the plugin name from the payment method.
+ * Round the amount to something that can be
+ * transferred on the wire.
  *
- * FIXME: this is ugly, would be better to have
- * a way to iterate over all plugins and interrogate
- * them as to what wire method(s) they support!
- *
- * @param method the method implemented by the plugin (for
- *  simplicity, we assume 1 method is implemented by 1 plugin).
- * @return the plugin name, NULL if not found.
+ * @param[in,out] amount amount to round down
+ * @return #GNUNET_OK on success, #GNUNET_NO if rounding was unnecessary,
+ *         #GNUNET_SYSERR if the amount or currency was invalid
  */
-const char *
-TALER_WIRE_get_plugin_from_method (const char *method)
+int
+TALER_WIRE_amount_round (struct TALER_Amount *amount)
 {
-  static const struct ConversionTable ct[] = {
-    {"x-taler-bank", "taler_bank"},
-    {"iban", "taler_bank"},
-    {NULL, NULL}
-  };
-
-  for (unsigned int i = 0;
-       NULL != ct[i].method;
-       i++)
-  {
-    if (0 == strcmp (method,
-                     ct[i].method))
-      return ct[i].plugin_name;
-  }
+  uint32_t delta;
 
-  return NULL;
+  delta = amount->fraction % (TALER_AMOUNT_FRAC_BASE / 100);
+  if (0 == delta)
+    return GNUNET_NO;
+  amount->fraction -= delta;
+  return GNUNET_OK;
 }
 
 

-- 
To stop receiving notification emails like this one, please contact
address@hidden.



reply via email to

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