gnunet-svn
[Top][All Lists]
Advanced

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

[GNUnet-SVN] [taler-exchange] branch master updated (1b3bf1a -> 202827e)


From: gnunet
Subject: [GNUnet-SVN] [taler-exchange] branch master updated (1b3bf1a -> 202827e)
Date: Sun, 15 Apr 2018 12:20:44 +0200

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

grothoff pushed a change to branch master
in repository exchange.

    from 1b3bf1a  disable /keys cherrypicking until #5315 is addressed
     new 7a20062  modify wire plugin load logic to use reference counting
     new cb55c1a  Changing configuration structure to enable multiple accounts.
     new 40a64e8  fix post-merge FTBFS
     new 8ebb4cd  fix NULL termination of fee list
     new e098dbf  get filename instead of get_string, nicify some strings
     new 2b0f98d  report which command failed
     new aea82d3  allow auditor to operate per-account
     new 202827e  merging Florian's changes with my wire changes

The 8 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 .gitignore                                         |    7 +-
 configure.ac                                       |    1 +
 .../exchange-template/config/exchange-common.conf  |  103 +-
 doc/taler-exchange-wire.1                          |   12 +-
 doc/taler-exchange.texi                            |  220 ++--
 doc/taler.conf.5                                   |  191 +++-
 src/Makefile.am                                    |    2 +-
 src/auditor/taler-auditor.c                        |   73 +-
 src/auditor/taler-wire-auditor.c                   |  467 ++++++---
 src/auditordb/auditordb-postgres.conf              |    2 +-
 src/auditordb/plugin_auditordb_postgres.c          |   27 +-
 src/auditordb/test-auditor-db-postgres.conf        |    2 +-
 src/bank-lib/Makefile.am                           |    4 +-
 src/bank-lib/bank.conf                             |    5 +-
 src/bank-lib/bank_api_history.c                    |   12 +-
 src/bank-lib/bank_api_parse.c                      |  133 +++
 src/bank-lib/bank_twisted.conf                     |    3 +
 src/bank-lib/test_bank_api_with_fakebank_new.c     |    5 +-
 src/bank-lib/test_bank_api_with_fakebank_twisted.c |    8 +-
 src/bank-lib/test_bank_interpreter.c               |   40 +-
 src/bank-lib/testing_api_cmd_history.c             |   47 +-
 src/bank-lib/testing_api_cmd_reject.c              |    2 +-
 src/benchmark/taler-exchange-benchmark.c           |    4 +-
 src/benchmark/taler-exchange-benchmark.conf        |   14 +-
 src/exchange-lib/Makefile.am                       |    3 +-
 src/exchange-lib/exchange_api_deposit.c            |    4 +-
 src/exchange-lib/exchange_api_reserve.c            |   15 +-
 src/exchange-lib/exchange_api_wire.c               |  477 +++++----
 src/exchange-lib/test_exchange_api.c               |   80 +-
 src/exchange-lib/test_exchange_api.conf            |   78 +-
 .../.config/taler/account-1.json                   |    5 +
 .../.config/taler/account-2.json                   |    5 +
 .../.config/taler/x-taler-bank.json                |    5 +
 .../test_exchange_api_keys_cherry_picking.conf     |   64 +-
 ..._exchange_api_keys_cherry_picking_extended.conf |    2 +-
 src/exchange-lib/test_exchange_api_new.c           |   99 +-
 src/exchange-lib/test_exchange_api_twisted.c       |    3 +-
 src/exchange-lib/testing_api_cmd_deposit.c         |   52 +-
 .../testing_api_cmd_exec_auditor-sign.c            |   20 +-
 src/exchange-lib/testing_api_cmd_exec_wirewatch.c  |    1 -
 .../testing_api_cmd_fakebank_transfer.c            |   14 +-
 src/exchange-lib/testing_api_cmd_payback.c         |   41 +-
 src/exchange-lib/testing_api_cmd_refund.c          |   11 +-
 src/exchange-lib/testing_api_cmd_track.c           |   64 +-
 src/exchange-lib/testing_api_cmd_wire.c            |  129 +--
 src/exchange-lib/testing_api_helpers.c             |   82 +-
 src/exchange-lib/testing_api_loop.c                |   10 +-
 ...trait_fresh_coin.c => testing_api_trait_json.c} |   38 +-
 src/exchange-lib/testing_api_trait_string.c        |   48 +-
 src/exchange-tools/Makefile.am                     |    3 +-
 src/exchange-tools/exchange-signkeys.conf          |   16 -
 src/exchange-tools/taler-exchange-keyup.c          |   66 +-
 src/exchange-tools/taler-exchange-wire.c           |  193 ++--
 src/exchange/.gitignore                            |    1 +
 src/exchange/exchange.conf                         |   15 +
 src/exchange/taler-exchange-aggregator.c           |  323 +++---
 src/exchange/taler-exchange-httpd.c                |   15 +-
 src/exchange/taler-exchange-httpd_deposit.c        |   12 +-
 src/exchange/taler-exchange-httpd_responses.c      |   17 +-
 src/exchange/taler-exchange-httpd_track_transfer.c |   18 +-
 src/exchange/taler-exchange-httpd_validation.c     |  310 +++---
 src/exchange/taler-exchange-httpd_validation.h     |    9 +-
 src/exchange/taler-exchange-httpd_wire.c           |   17 +-
 src/exchange/taler-exchange-httpd_wire.h           |    4 +-
 src/exchange/taler-exchange-wirewatch.c            |  203 +++-
 .../test-taler-exchange-aggregator-postgres.conf   |   34 +-
 .../test-taler-exchange-wirewatch-postgres.conf    |   30 +-
 src/exchange/test_taler_exchange_aggregator.c      |   26 +-
 src/exchange/test_taler_exchange_httpd.conf        |   49 +-
 src/exchange/test_taler_exchange_httpd.data        |   17 +-
 src/exchange/test_taler_exchange_httpd.sh          |    4 +-
 src/exchange/test_taler_exchange_wirewatch.c       |    3 +-
 src/exchangedb/Makefile.am                         |   12 +-
 src/exchangedb/exchangedb-postgres.conf            |    2 +-
 src/exchangedb/exchangedb_accounts.c               |  141 +++
 src/exchangedb/perf_taler_exchangedb.c             |    2 +-
 src/exchangedb/perf_taler_exchangedb_init.c        |   22 +-
 src/exchangedb/perf_taler_exchangedb_interpreter.c |   14 +-
 src/exchangedb/plugin_exchangedb_common.c          |    8 +-
 src/exchangedb/plugin_exchangedb_postgres.c        |  258 +++--
 src/exchangedb/test-exchange-db-postgres.conf      |    2 +-
 src/exchangedb/test_exchangedb.c                   |  100 +-
 src/include/taler_auditordb_plugin.h               |    8 +-
 src/include/taler_bank_service.h                   |   29 +-
 src/include/taler_crypto_lib.h                     |   49 +-
 src/include/taler_error_codes.h                    |   22 +
 src/include/taler_exchange_service.h               |   68 +-
 src/include/taler_exchangedb_lib.h                 |   68 ++
 src/include/taler_exchangedb_plugin.h              |   96 +-
 src/include/taler_json_lib.h                       |   59 ++
 src/include/taler_signatures.h                     |   27 +-
 src/include/taler_testing_lib.h                    |   38 +-
 src/include/taler_wire_lib.h                       |   36 +-
 src/include/taler_wire_plugin.h                    |   75 +-
 src/json/Makefile.am                               |    4 +-
 src/json/json_wire.c                               |  193 ++++
 src/util/Makefile.am                               |    1 +
 src/util/crypto_wire.c                             |  108 ++
 src/{wire => wire-plugins}/Makefile.am             |   76 +-
 .../plugin_wire_ebics.c}                           |  493 +++------
 .../plugin_wire_taler-bank.c}                      | 1084 ++++++++++----------
 src/{wire => wire-plugins}/plugin_wire_template.c  |  149 ++-
 src/wire-plugins/test_ebics_wireformat.c           |   80 ++
 src/{wire => wire-plugins}/test_wire_plugin.c      |   97 +-
 src/{wire => wire-plugins}/test_wire_plugin.conf   |   22 +-
 .../test_wire_plugin_transactions_taler-bank.c}    |   44 +-
 .../test_wire_plugin_transactions_taler-bank.conf  |   12 +
 src/wire/Makefile.am                               |  103 +-
 src/wire/test_sepa_wireformat.c                    |  120 ---
 src/wire/test_wire_plugin_key.priv                 |    1 -
 src/wire/test_wire_plugin_sepa.json                |    8 -
 src/wire/test_wire_plugin_test.json                |    7 -
 src/wire/test_wire_plugin_transactions_test.conf   |   15 -
 src/wire/wire-sepa.conf                            |   15 -
 src/wire/wire-test.conf                            |   22 -
 src/wire/wire.c                                    |  157 +--
 src/wire/wire_helper.c                             |   57 +
 117 files changed, 4609 insertions(+), 3514 deletions(-)
 create mode 100644 src/bank-lib/bank_api_parse.c
 create mode 100644 
src/exchange-lib/test_exchange_api_home/.config/taler/account-1.json
 create mode 100644 
src/exchange-lib/test_exchange_api_home/.config/taler/account-2.json
 create mode 100644 
src/exchange-lib/test_exchange_api_home/.config/taler/x-taler-bank.json
 copy src/exchange-lib/{testing_api_trait_fresh_coin.c => 
testing_api_trait_json.c} (61%)
 delete mode 100644 src/exchange-tools/exchange-signkeys.conf
 create mode 100644 src/exchangedb/exchangedb_accounts.c
 create mode 100644 src/json/json_wire.c
 create mode 100644 src/util/crypto_wire.c
 copy src/{wire => wire-plugins}/Makefile.am (57%)
 rename src/{wire/plugin_wire_sepa.c => wire-plugins/plugin_wire_ebics.c} (56%)
 rename src/{wire/plugin_wire_test.c => wire-plugins/plugin_wire_taler-bank.c} 
(55%)
 rename src/{wire => wire-plugins}/plugin_wire_template.c (74%)
 create mode 100644 src/wire-plugins/test_ebics_wireformat.c
 rename src/{wire => wire-plugins}/test_wire_plugin.c (59%)
 rename src/{wire => wire-plugins}/test_wire_plugin.conf (51%)
 rename src/{wire/test_wire_plugin_transactions_test.c => 
wire-plugins/test_wire_plugin_transactions_taler-bank.c} (87%)
 create mode 100644 
src/wire-plugins/test_wire_plugin_transactions_taler-bank.conf
 delete mode 100644 src/wire/test_sepa_wireformat.c
 delete mode 100644 src/wire/test_wire_plugin_key.priv
 delete mode 100644 src/wire/test_wire_plugin_sepa.json
 delete mode 100644 src/wire/test_wire_plugin_test.json
 delete mode 100644 src/wire/test_wire_plugin_transactions_test.conf
 delete mode 100644 src/wire/wire-sepa.conf
 delete mode 100644 src/wire/wire-test.conf
 create mode 100644 src/wire/wire_helper.c

diff --git a/.gitignore b/.gitignore
index daf8589..7acf2dc 100644
--- a/.gitignore
+++ b/.gitignore
@@ -59,10 +59,11 @@ src/exchange-tools/taler-exchange-wire
 src/exchangedb/perf-exchangedb
 src/benchmark/taler-exchange-benchmark
 src/benchmark/test_benchmark_home/.local/share/taler/exchange/live-keys/
+src/benchmark/test_benchmark_home/.local/share/taler/exchange/wirefees/
 src/json/test_json
-src/wire/test_sepa_wireformat
-src/wire/test_wire_plugin
-src/wire/test_wire_plugin_transactions_test
+src/wire-plugins/test_ebics_wireformat
+src/wire-plugins/test_wire_plugin
+src/wire-plugins/test_wire_plugin_transactions_taler_bank
 src/pq/test_pq
 src/util/test_amount
 src/util/test_crypto
diff --git a/configure.ac b/configure.ac
index d2254b3..d28aca8 100644
--- a/configure.ac
+++ b/configure.ac
@@ -536,5 +536,6 @@ AC_CONFIG_FILES([Makefile
                  src/util/Makefile
                  src/util/taler-config
                  src/wire/Makefile
+                 src/wire-plugins/Makefile
                  ])
 AC_OUTPUT
diff --git a/contrib/exchange-template/config/exchange-common.conf 
b/contrib/exchange-template/config/exchange-common.conf
index 4778265..425bb92 100644
--- a/contrib/exchange-template/config/exchange-common.conf
+++ b/contrib/exchange-template/config/exchange-common.conf
@@ -17,27 +17,98 @@ TESTRUN = YES
 [exchangedb-postgres]
 DB_CONN_STR = "postgres:///talercheck"
 
+[auditordb-postgres]
+DB_CONN_STR = "postgres:///talercheck"
 
-[exchange-wire-sepa]
-# Change here to enable SEPA wire transfers.
-ENABLE = NO
 
-# Response for /wire
-SEPA_RESPONSE_FILE = "sepa.json"
+# Provide account information
+[account-1]
+# Accounts must have a payto:// URL
+URL = payto://METHOD/DETAILS
+
+# To be included in /wire, accounts must have a signed wire file
+# Must match URL.
+WIRE_RESPONSE = ${TALER_CONFIG_HOME}/account-1.json
+
+# For access to the account, we need to know the plugin.
+PLUGIN = "ebics"
 
-[exchange-wire-outgoing-sepa]
-# TBD
+# TBD: authentication data.
 
+# Accounts need to be enabled for the aggregator to debit them.
+ENABLE_DEBIT = NO
 
-[exchange-wire-test]
-# Change here to disable TEST wire transfers.
-ENABLE = YES
+# Accounts need to be enabled for the wirewatcher to look for credits into 
them.
+ENABLE_CREDIT = YES
+
+[account-2]
+URL = payto://x-taler-wire/bank/2
 
 # Response for /wire
-TEST_RESPONSE_FILE = "test.json"
+# Must match URL.
+WIRE_RESPONSE = ${TALER_CONFIG_HOME}/account-2.json
+
+PLUGIN = taler_bank
+
+# We also may need authentication data.
+TALER_BANK_AUTH_METHOD = "none" # or basic
+# TALER_BANK_USERNAME = user
+# TALER_BANK_PASSWORD = pass
+
+# Accounts need to be enabled for the aggregator to debit them.
+ENABLE_DEBIT = YES
+
+# Accounts need to be enabled for the wirewatcher to look for credits into 
them.
+ENABLE_CREDIT = YES
+
+
+# Wire fees are specified by wire method, NOT by wire plugin.
+[fees-x-taler-bank]
+# Fees for the forseeable future...
+# If you see this after 2018, update to match the next 10 years...
+WIRE-FEE-2018 = EUR:0.01
+WIRE-FEE-2019 = EUR:0.01
+WIRE-FEE-2020 = EUR:0.01
+WIRE-FEE-2021 = EUR:0.01
+WIRE-FEE-2022 = EUR:0.01
+WIRE-FEE-2023 = EUR:0.01
+WIRE-FEE-2024 = EUR:0.01
+WIRE-FEE-2025 = EUR:0.01
+WIRE-FEE-2026 = EUR:0.01
+WIRE-FEE-2027 = EUR:0.01
+
+CLOSING-FEE-2018 = EUR:0.01
+CLOSING-FEE-2019 = EUR:0.01
+CLOSING-FEE-2020 = EUR:0.01
+CLOSING-FEE-2021 = EUR:0.01
+CLOSING-FEE-2022 = EUR:0.01
+CLOSING-FEE-2023 = EUR:0.01
+CLOSING-FEE-2024 = EUR:0.01
+CLOSING-FEE-2025 = EUR:0.01
+CLOSING-FEE-2026 = EUR:0.01
+CLOSING-FEE-2027 = EUR:0.01
+
+[fees-sepa]
+# Fees for the forseeable future...
+# If you see this after 2018, update to match the next 10 years...
+WIRE-FEE-2018 = EUR:0.01
+WIRE-FEE-2019 = EUR:0.01
+WIRE-FEE-2020 = EUR:0.01
+WIRE-FEE-2021 = EUR:0.01
+WIRE-FEE-2022 = EUR:0.01
+WIRE-FEE-2023 = EUR:0.01
+WIRE-FEE-2024 = EUR:0.01
+WIRE-FEE-2025 = EUR:0.01
+WIRE-FEE-2026 = EUR:0.01
+WIRE-FEE-2027 = EUR:0.01
 
-# What is the main website of the bank?
-BANK_URL = "https://bank/";
-# Into which account at the 'bank' should incoming
-# wire transfers be made?
-BANK_ACCOUNT_NUMBER = 2
+CLOSING-FEE-2018 = EUR:0.01
+CLOSING-FEE-2019 = EUR:0.01
+CLOSING-FEE-2020 = EUR:0.01
+CLOSING-FEE-2021 = EUR:0.01
+CLOSING-FEE-2022 = EUR:0.01
+CLOSING-FEE-2023 = EUR:0.01
+CLOSING-FEE-2024 = EUR:0.01
+CLOSING-FEE-2025 = EUR:0.01
+CLOSING-FEE-2026 = EUR:0.01
+CLOSING-FEE-2027 = EUR:0.01
diff --git a/doc/taler-exchange-wire.1 b/doc/taler-exchange-wire.1
index 546d8eb..256daab 100644
--- a/doc/taler-exchange-wire.1
+++ b/doc/taler-exchange-wire.1
@@ -1,4 +1,4 @@
-.TH TALER\-EXCHANGE\-WIRE 1 "Apr 2, 2016" "GNU Taler"
+.TH TALER\-EXCHANGE\-WIRE 1 "Mar 18, 2018" "GNU Taler"
 
 .SH NAME
 taler\-exchange\-wire \- Create the master-key signed responses to /wire.
@@ -13,18 +13,8 @@ taler\-exchange\-wire \- Create the master-key signed 
responses to /wire.
 
 .SH OPTIONS
 .B
-.IP "\-j JSON,  \-\-json=JSON"
-Gives JSON with all of the relevant account details in a method-specific 
format.
-.B
-.IP "\-t METHOD,  \-\-type=METHOD"
-Specifies the wire transfer method to use. Common are 'test' and 'sepa'.
-.B
 .IP "\-m MASTERKEYFILE,  \-\-master=MASTERKEYFILE"
 Specifies the name of the file containing the exchange's master key.
-.B
-.IP "\-o FILENAME,  \-\-output=FILENAME"
-Where to write the SEPA_RESPONSE_FILE.
-.B
 .IP "\-h, \-\-help"
 Print short help on options.
 .B
diff --git a/doc/taler-exchange.texi b/doc/taler-exchange.texi
index 9f5fd10..72efe39 100644
--- a/doc/taler-exchange.texi
+++ b/doc/taler-exchange.texi
@@ -13,7 +13,7 @@ This manual is for the GNU Taler Exchange
 (version @value{VERSION}, @value{UPDATED}),
 a payment service provider for GNU Taler.
 
-Copyright @copyright{} 2014-2017 GNUnet e.V. and INRIA
+Copyright @copyright{} 2014-2018 Taler Systems SA
 
 @quotation
 Permission is granted to copy, distribute and/or modify this document
@@ -260,7 +260,7 @@ GNU libunistring @geq{} 0.9.3
 libcurl @geq{} 7.26 (or libgnurl @geq{} 7.26)
 
 @item
-GNU libmicrohttpd @geq{} 0.9.52
+GNU libmicrohttpd @geq{} 0.9.59
 
 @item
 GNU libgcrypt @geq{} 1.6
@@ -354,6 +354,8 @@ description of some of the options.
 
 The exchange works with three types of keys:
 
address@hidden FIXME: explain better!
+
 @itemize
 
 @item
@@ -366,34 +368,18 @@ The exchange works with three types of keys:
 @cite{denomination keys} (see section @cite{Coins})
 @end itemize
 
address@hidden key}: in section @cite{[exchange]}, edit the two following 
values:
-
address@hidden FIXME: text here.
 
 @itemize
-
 @item
address@hidden: Path to the exchange's master private file.
address@hidden: Path to the exchange's master private file.
 
 @item
address@hidden: Must specify the exchange's master public key.
address@hidden: Must specify the exchange's master public key.
 @end itemize
 
address@hidden keys}: the following two options under
address@hidden section control @cite{sign keys}:
-
 
address@hidden
-
address@hidden
address@hidden: How long should one signing key be used?
 
address@hidden
address@hidden: How much time we want to cover with our
address@hidden Note that if @cite{signkey_duration} is bigger than
address@hidden, @cite{taler-exchange-keyup} will generate a
-quantity of @cite{signkeys} which is sufficient to cover all the
-gap. See keys-duration.
address@hidden itemize
 
 
 @node Serving
@@ -436,99 +422,148 @@ option @cite{currency} in section @cite{[taler]}.
 @node Bank account
 @section Bank account
 
address@hidden
-* Wiremethod-test::
-* Wiremethod-sepa::
address@hidden menu
+To configure a bank account in Taler, we need to furnish four
+pieces of information:
address@hidden
address@hidden
+  The @code{payto://} URL of the bank account, which uniquely idenfies
+  the account. Examples for such URLs include
+  @code{payto://sepa/CH9300762011623852957} for a bank account
+  in the single European payment area (SEPA) or
+  @code{payto://x-taler-bank/localhost:8080/2} for the 2nd bank
+  account a the Taler bank demonstrator running at @code{localhost}
+  on port 8080.  The first part of the URL following @code{payto://}
+  (``sepa'' or ``x-taler-bank'') is called the wire method.
address@hidden
+  A matching wire plugin that implements a protocol to interact
+  with the banking system.  For example, the EBICS plugin can
+  be used for SEPA transfers, or the ``taler-bank'' plugin can
+  interact with the Taler bank demonstrator.  A wire plugin
+  only supports one particular wire method. Thus, you must make
+  sure to pick a plugin that supports the wire method used in the
+  URL.
address@hidden
+  A file containing the signed JSON-encoded bank account details
+  for the /wire API.  This is necessary as Taler supports offline
+  signing for bank accounts for additional security.
address@hidden
+  Finally, the plugin needs to be provided resources for
+  authentication to the respective banking service.  The format
+  in which the authentication information must be provided
+  depends on the wire plugin.
address@hidden itemize
 
address@hidden Wiremethod-test
address@hidden Wiremethod-test
+You can configure multiple accounts for an exchange by creating
+sections starting with ``account-'' for the section name.  You can
+ENABLE for each account whether it should be used, and for what
+(incoming or outgoing wire transfers):
 
-To enable the wire transfer method ``test'', you need to set
-``ENABLE=YES'' in section @cite{[exchange-wire-test]}.
address@hidden ini
address@hidden
+
+[account-1]
+URL = "payto://sepa/CH9300762011623852957"
+WIRE_RESPONSE = address@hidden@}/account-1.json
+PLUGIN = ebics
 
-The bank account where the exchange gets money from customers is
-configured under the section @cite{[exchange-wire-test]}.  It must
-contain the options ``EXCHANGE_ACCOUNT_NO'' and ``BANK_URL''.
-For basic authentication, it must additionally contain the
-``USERNAME'' and ``PASSWORD'' of the exchange's account at the bank.
+# Use for exchange-aggregator (outgoing transfers)
+ENABLE_DEBIT = YES
+# Use for exchange-wirewatch (and listed in /wire)
+ENABLE_CREDIT = YES
 
-For incoming transfers, the section must additional contain the
-option: @cite{test_response_file}, which takes
-the path to a text file containing the exchange's bank account details
-in JSON format.
+# ... add authentication options here
address@hidden example
 
-The command line tool @cite{taler-exchange-wire} is used to create such a file.
-For example, the utility may be invoked as follows:
+The command line tool @cite{taler-exchange-wire} is used to create
+the @code{account-1.json} file.
+For example, the utility may be invoked as follows to create
+all of the WIRE_RESPONSE files (in the locations specified by the 
configuration):
 
 @example
-$ taler-exchange-wire -j '@{"name": "The Exchange", "account_number":
-10, "bank_url": "https://bank.demo.taler.net";, "type": "test"@}' -t
-test -o exchange.json
+$ taler-exchange-wire
 @end example
 
-Note that the value given to option @cite{-t} must match the value in
-the JSON's field @code{"type"}.
-
 The generated file will be echoed by the exchange when serving
 /address@hidden://api.taler.net/api-exchange.html#wire-req}
 requests.
 
 
address@hidden Wiremethod-sepa
address@hidden Wiremethod-sepa
address@hidden
+* Wire plugin ``taler_bank''::
+* Wire plugin ``ebics''::
+* Wire fee structure::
address@hidden menu
 
-To enable the wire transfer method ``sepa'', you need to set
-``ENABLE=YES'' in section @cite{[exchange-wire-sepa]}.
address@hidden Wire plugin ``taler_bank''
address@hidden Wire plugin ``taler_bank''
address@hidden x-taler-bank
address@hidden taler_bank plugin
 
+The @code{taler_bank} plugin implements the wire method ``x-taler-bank''.
 
-This section contains only one option: @cite{sepa_response_file},
-which takes the path to a text file containing the exchange's bank
-account details in JSON format.
+The format of the @code{payto://} URL is 
@code{payto://x-taler-bank/HOSTNAME:PORT},
+possibly followed by other parameters like the amount and wire transfer subject
+as per the @code{payto://} standard.
 
-The command line tool @cite{taler-exchange-wire} is used to create such a file.
-For example, the utility may be invoked as follows:
+For basic authentication, the @code{taler_bank} plugin only supports
+simple password-based authentication.  For this, the configuration
+must contain the ``USERNAME'' and ``PASSWORD'' of the respective
+account at the bank.
 
address@hidden ini
 @example
-$ taler-exchange-wire -j '@{"name": "The Exchange", "account_number":
-10, "bank_url": "https://bank.demo.taler.net";, "type": "sepa"@}' -t
-sepa -o exchange.json
+[account-2]
+URL = "payto://test/localhost:8080"
+USERNAME = exchange
+PASSWORD = super-secure
 @end example
 
-Note that the value given to option @cite{-t} must match the value in the 
JSON's field @code{"type"}.
-
-The generated file will be echoed by the exchange when serving
-/address@hidden://api.taler.net/api-exchange.html#wire-req}
-requests.
-
-This exchange's outgoing bank account is used to give money to merchants, after
-successful
address@hidden://api.taler.net/api-exchange.html#deposit-par}
-operations. The outgoing bank account is configured by the following
-options under @cite{[exchange-wire-outgoing-sepa]}: (NOT YET SUPPORTED).
 
address@hidden
-
-
address@hidden
address@hidden Wire plugin ``ebics''
address@hidden Wire plugin ``ebics''
 
address@hidden
address@hidden: which bank account number has the exchange
+The ``ebics'' wire plugin is not fully implemented and today
+does not support actual wire transfers.
 
address@hidden
address@hidden: base URL of the bank hosting the exchange bank account
address@hidden itemize
address@hidden quotation
 
 @cartouche
 @quotation Note
-The rationale behind having two bank accounts is that the exchange operator, 
as a security
+The rationale behind having multiple bank accounts is that the exchange 
operator, as a security
 measure, may want to instruct the bank that the incoming bank account is only 
supposed to
 @emph{receive} money.
 @end quotation
 @end cartouche
 
 
address@hidden Wire fee structure
address@hidden Wire fee structure
address@hidden wire fee
address@hidden fee
+
+For each wire method (``sepa'' or ``x-taler-wire'', but not per plugin!) the
+exchange configuration must specify applicable wire fees.  This is done
+in configuration sections of the format @code{fee-METHOD}.  There are two
+types of fees, simple wire fees and closing fees.  Wire fees apply whenever
+the aggregator transfers funds to a merchant.  Closing fees apply whenever
+the exchange closes a reserve (sending back funds to the customer).  The
+fees must be constant for a full year, which is specified as part of the name
+of the option.
+
address@hidden ini
address@hidden
+[fee-iban]
+WIRE-FEE-2018 = EUR:0.01
+WIRE-FEE-2019 = EUR:0.01
+CLOSING-FEE-2018 = EUR:0.01
+CLOSING-FEE-2019 = EUR:0.01
+
+[fee-x-taler-bank]
+WIRE-FEE-2018 = KUDOS:0.01
+WIRE-FEE-2019 = KUDOS:0.01
+CLOSING-FEE-2018 = KUDOS:0.01
+CLOSING-FEE-2019 = KUDOS:0.01
address@hidden example
+
 
 @node Database
 @section Database
@@ -546,18 +581,18 @@ possible in two ways:
 via an environment variable: @cite{TALER_EXCHANGEDB_POSTGRES_CONFIG}.
 
 @item
-via configuration option @cite{db_conn_str}, under section 
@cite{[exchangedb-BACKEND]}. For example, the demo exchange is configured as 
follows:
+via configuration option @cite{CONFIG}, under section 
@cite{[exchangedb-BACKEND]}. For example, the demo exchange is configured as 
follows:
 @end itemize
 
 @setsyntax ini
 @example
 [exchange]
 ...
-db = postgres
+DB = postgres
 ...
 
 [exchangedb-postgres]
-db_conn_str = postgres:///talerdemo
+CONFIG = postgres:///talerdemo
 @end example
 
 @node Coins denomination keys
@@ -639,6 +674,25 @@ key will get a starting time of @cite{t}, and the 
@cite{j}-th key will
 get a starting time of @cite{x + duration_withdraw}, where @cite{x} is
 the starting time of the @cite{(j-1)}-th key.
 
+To change these settings, edit the following
+values in section @cite{[exchange]}:
+
address@hidden
address@hidden
address@hidden: How long should one signing key be used?
+
address@hidden
address@hidden: How much time we want to cover with our
+signing keys? Note that if @cite{SIGNKEY_DURATION} is bigger than
address@hidden, @code{taler-exchange-keyup} will generate a
+quantity of signing keys which is sufficient to cover all the
+gap.
address@hidden itemize
+
address@hidden FIXME: LEGAL_DURATION not covered!
address@hidden FIXME: LOOKAHEAD_PROVIDE not covered!
+
+
 @node Deployment
 @chapter Deployment
 
diff --git a/doc/taler.conf.5 b/doc/taler.conf.5
index 40a9506..07d13f1 100644
--- a/doc/taler.conf.5
+++ b/doc/taler.conf.5
@@ -1,4 +1,4 @@
-.TH TALER.CONF 5 "Apr 11, 2016" "GNU Taler"
+.TH TALER.CONF 5 "Mar 20, 2018" "GNU Taler"
 
 .SH NAME
 taler.conf \- Taler configuration file.
@@ -10,46 +10,174 @@ taler.conf \- Taler configuration file.
 
 The basic structure of the configuration file is the following.  The file is 
split into sections.  Every section begins with "[SECTIONNAME]" and contains a 
number of options of the form "OPTION=VALUE".  Empty lines and lines beginning 
with a "#" are treated as comments.  Files containing default values for many 
of the options described below are installed under 
$TALER\_PREFIX/share/taler/config.d/. The configuration file given with \-c to 
Taler binaries overrides these defaults.
 
-.SH EXCHANGE OPTIONS
+.SH GLOBAL OPTIONS
 
-The following options are from the "[exchange]" section and used by most 
exchange tools:
+The following options are from the "[taler]" section and used by virtually all 
Taler components.
 
 .IP CURRENCY
     Name of the currency, i.e. "EUR" for Euro.
+
+The "[PATHS]" section is special in that it contains paths that can be 
referenced using "$" in other configuration values that specify filenames.  For 
Taler, it commonly contains the following paths:
+
+.IP TALER_HOME
+    Home directory of the user, usually "${HOME}". Can be overwritten by 
testcases by setting ${TALER_TEST_HOME}.
+.IP TALER_DATA_HOME
+    Where should Taler store its long-term data.  Usually 
"${TALER_HOME}/.local/share/taler/"
+.IP TALER_CONFIG_HOME
+    Where is the Taler configuration kept.  Usually 
"${TALER_HOME}/.config/taler/"
+.IP TALER_CACHE_HOME
+    Where should Taler store cached data. Usually "${TALER_HOME}/.cache/taler/"
+.IP TALER_RUNTIME_DIR
+    Where should Taler store system runtime data (like UNIX domain sockets).  
Usually "${TMP}/taler-system-runtime".
+
+.SH EXCHANGE OPTIONS
+
+The following options are from the "[exchange]" section and used by most 
exchange tools:
+
 .IP DB
     Plugin to use for the database, i.e. "postgres"
 .IP PORT
     Port on which the HTTP server listens, i.e. 8080.
 .IP MASTER_PUBLIC_KEY
     Crockford Base32-encoded master public key, public version of the 
exchange\'s long\-time offline signing key.
+.IP MASTER_PRIV_FILE
+    Location of the master private key on disk. Only used by tools that can be 
run offline (as the master key is for offline signing).
+.IP BASE_URL
+    Specifies the base URL under which the exchange can be reached. Added to 
wire transfers to enable tracking by merchants.
+.IP SIGNKEY_DURATION
+    For how long is a signing key valid?
+.IP LEGAL_DURATION
+    For how long are signatures with signing keys legally valid?
+.IP LOOKAHEAD_SIGN
+    How long do we generate denomination and signing keys ahead of time?
+.IP LOOKAHEAD_PROVIDE
+    How long into the future do we provide signing and denomination keys to 
clients?
+
 
 
-.SH WIRE transfer details
+.SH EXCHANGE POSTGRES BACKEND DATABASE OPTIONS
 
-To enable the "test" wire transfer method, you must set "ENABLE = YES" in 
"[exchange\-wire\-test]".
-Then, the following options must be in section 
"[exchange\-wire\-incoming\-test]" and "[exchange\-wire\-outgoing\-test]":
+The following options must be in section "[exchangedb\-postgres]" if the 
"postgres" plugin was selected for the database:
 
-.IP BANK_URI
-    URL of the Taler bank.
+.IP CONFIG
+    How to access the database, i.e. "postgres:///taler" to use the "taler" 
database. Testcases use "talercheck".
 
-.IP BANK_ACCOUNT_NUMBER
-    Number of the bank account of the exchange.
 
-To enable the "sepa" wire transfer method, you must set "ENABLE = YES" in 
"[exchange\-wire\-sepa]".
-Then, the following options must be in section 
"[exchange\-wire\-incoming\-sepa]" and "[exchange\-wire\-outgoing\-sepa]":
+.SH MERCHANT OPTIONS
 
-.IP SEPA_RESPONSE_FILE
-    Filename with the JSON body for the /wire response, signed using the 
exchange\'s long-term offline master key.  Use taler\-exchange\-sepa to create 
the SEPA_RESPONSE_FILE.
+The following options are from the "[merchant]" section and used by the 
merchant backend:
 
+.IP DB
+    Plugin to use for the database, i.e. "postgres"
+.IP PORT
+    Port on which the HTTP server listens, i.e. 8080.
+.IP WIRE_TRANSFER_DELAY
+    How quickly do we want the exchange to send us money? Note that wire 
transfer fees will be higher if we ask for money to be wired often.  Given as a 
relative time, i.e. "5 s"
+.IP DEFAULT_MAX_WIRE_FEE
+    Maximum wire fee we are willing to accept from exchanges.  Given as a 
Taler amount, i.e. "EUR:0.1"
+.IP DEFAULT_MAX_DEPOSIT_FEE
+    Maximum deposit fee we are willing to cover.  Given as a Taler amount, 
i.e. "EUR:0.1"
 
-.SH Postgres database options
 
-The following options must be in section "[exchangedb\-postgres]":
+.SH MERCHANT POSTGRES BACKEND DATABASE OPTIONS
 
-.IP DB_CONN_STR
+The following options must be in section "[merchantdb\-postgres]" if the 
"postgres" plugin was selected for the database:
+
+.IP CONFIG
     How to access the database, i.e. "postgres:///taler" to use the "taler" 
database. Testcases use "talercheck".
 
-.SH COIN OPTIONS
+.SH MERCHANT INSTANCES
+
+The merchant configuration must specify a set of instances, containing at 
least the "default" instance.  The following options must be given in each 
"[instance-NAME]" section:
+
+.IP KEYFILE
+    Name of the file where the instance\'s private key is to be stored, i.e. 
"${TALER_CONFIG_HOME}/merchant/instance/name.priv"
+.IP NAME
+    Human-readable name of the instance, i.e. "Kudos Inc."
+
+Additionally, for instances that support tipping, the following options are 
required:
+
+.IP TIP_EXCHANGE
+    Base-URL of the exchange that holds the reserve for tipping, i.e. 
"https://exchange.demo.taler.net/";
+.IP TIP_EXCHANGE_PRIV_FILENAME
+    Filename with the private key granting access to the reserve, i.e. 
"${TALER_CONFIG_HOME}/merchant/reserve/tip.priv"
+
+
+.SH KNOWN EXCHANGES (for merchants and wallets)
+
+The merchant configuration can include a list of known exchanges if the 
merchant wants to specify that certain exchanges are explicitly trusted.  For 
each trusted exchange, a section [exchange-NAME] must exist, where NAME is a 
merchant-given name for the exchange.  The following options must be given in 
each "[exchange-NAME]" section:
+
+.IP BASE_URL
+    Base URL of the exchange, i.e. "https://exchange.demo.taler.net/";
+.IP MASTER_KEY
+    Crockford Base32 encoded master public key, public version of the 
exchange\'s long\-time offline signing key
+.IP CURRENCY
+    Name of the currency for which this exchange is trusted, i.e. "KUDOS"
+
+
+.SH KNOWN AUDITORS (for merchants and wallets)
+
+The merchant configuration can include a list of known exchanges if the 
merchant wants to specify that certain auditors are explicitly trusted.  For 
each trusted exchange, a section [auditor-NAME] must exist, where NAME is a 
merchant-given name for the exchange.  The following options must be given in 
each "[auditor-NAME]" section:
+
+.IP BASE_URL
+    Base URL of the auditor, i.e. "https://auditor.demo.taler.net/";
+.IP AUDITOR_KEY
+    Crockford Base32 encoded auditor public key.
+.IP CURRENCY
+    Name of the currency for which this auditor is trusted, i.e. "KUDOS"
+
+
+
+.SH ACCOUNT OPTIONS (for exchanges and merchants)
+
+An exchange (or merchant) can have multiple bank accounts. The following 
options are for sections named "[account-SOMETHING]".  The SOMETHING is 
arbitrary and should be chosen to uniquely identify the bank account for the 
operator.  Additional authentication options may need to be specified in the 
account section depending on the PLUGIN used.
+
+.IP URL
+    Specifies the payto://-URL of the account.  The general format is 
payto://METHOD/DETAILS.  This option is used for exchanges and merchants.
+.IP WIRE_RESPONSE
+    Specifies the name of the file in which the /wire response for this 
account should be located. Used by the Taler exchange service and the 
taler\-exchange\-wire tool and the taler\-merchant\-httpd (to generate the 
files).
+.IP PLUGIN
+    Name of the plugin can be used to access the account (i.e. "taler-bank" or 
"ebics"). Used by the merchant backend for back office operations (i.e. to 
identify incoming wire transfers) and by the exchange.
+.IP ENABLE_DEBIT
+    Must be set to YES for the accounts that the taler\-exchange\-aggregator 
should debit. Not used by merchants.
+.IP ENABLE_CREDIT
+    Must be set to YES for the accounts that the taler\-exchange\-wirewatch 
should check for credits. (It is yet uncertain if the merchant implementation 
may check this flag as well.)
+.IP HONOR_instance
+    Must be set to YES for the instances (where "instance" is the section name 
of the instance) of the merchant backend that should allow incoming wire 
transfers for this bank account.
+.IP ACTIVE_instance
+    Must be set to YES for the instances (where "instance" is the section name 
of the instance) of the merchant backend that should use this bank account in 
new offers/contracts.  Setting ACTIVE_instance to YES requires also setting 
ENABLE_instance to YES.
+
+
+.SH TALER-BANK AUTHENTICATION OPTIONS (for accounts)
+
+The following authentication options are supported by the "taler-bank" wire 
plugin. They must be specified in the "[account-]" section that uses the 
"taler-bank" plugin.
+
+.IP TALER_BANK_AUTH_METHOD
+    Authentication method to use. "none" or "basic" are currently supported.
+.IP USERNAME
+    Username to use for authentication. Used with the "basic" authentication 
method.
+.IP PASSWORD
+    Password to use for authentication. Used with the "basic" authentication 
method.
+
+.SH EBICS AUTHENTICATION OPTIONS
+
+The following authentication options are supported by the "ebics" wire plugin. 
They must be specified in the "[account-]" section that uses the "ebics" plugin.
+
+.IP NONE
+    Currently the "ebics" implementation is incomplete and does not support 
authentication.
+
+
+.SH EXCHANGE WIRE FEE OPTIONS
+
+For each supported wire method (i.e. "x-taler-bank" or "sepa"), sections named 
"[fees-METHOD]" state the (aggregate) wire transfer fee and the reserve closing 
fees charged by the exchange.  Note that fees are specified using the name of 
the wire method, not by the plugin name.  You need to replace "YEAR" in the 
option name by the calendar year for which the fee should apply.  Usually, fees 
should be given for serveral years in advance.
+
+.IP WIRE-FEE-YEAR
+    Aggregate wire transfer fee merchants are charged in YEAR.  Specified as a 
Taler amount using the usual amount syntax (CURRENCY:VALUE.FRACTION).
+.IP CLOSING-FEE-YEAR
+    Reserve closing fee customers are charged in YEAR.  Specified as a Taler 
amount using the usual amount syntax (CURRENCY:VALUE.FRACTION).
+
+
+.SH EXCHANGE COIN OPTIONS
 
 The following options must be in sections starting with "[coin_]" and are used 
by taler\-exchange\-keyup to create denomination keys:
 
@@ -72,22 +200,27 @@ The following options must be in sections starting with 
"[coin_]" and are used b
 .IP RSA_KEYSIZE
     What is the RSA keysize modulos (in bits)?
 
-.SH KEY OPTIONS
 
-The following options are from the "[exchange_keys]" section and used by most 
taler\-exchange\-keyup to create keys:
+.SH AUDITOR OPTIONS
 
-.IP SIGNKEY_DURATION
-    For how long is a signing key valid?
-.IP LEGAL_DURATION
-    For how long are signatures with signing keys legally valid?
-.IP LOOKAHEAD_SIGN
-    How long do we generate denomination and signing keys ahead of time?
-.IP LOOKAHEAD_PROVIDE
-    How long into the future do we provide signing and denomination keys to 
clients?
+The following options must be in section "[auditor]" for the Taler auditor:
+
+.IP DB
+    Plugin to use for the database, i.e. "postgres"
+.IP AUDITOR_PRIV_FILE
+    Name of the file containing the auditor's private key
+
+
+.SH AUDITOR POSTGRES BACKEND DATABASE OPTIONS
+
+The following options must be in section "[auditordb\-postgres]" if the 
"postgres" plugin was selected for the database:
+
+.IP CONFIG
+    How to access the database, i.e. "postgres:///taler" to use the "taler" 
database. Testcases use "talercheck".
 
 
 .SH BUGS
 Report bugs by using Mantis <https://gnunet.org/bugs/> or by sending 
electronic mail to <address@hidden>
 
 .SH "SEE ALSO"
-\fBtaler\-exchange\-httpd\fP(1), \fBtaler\-exchange\-keyup\fP(1), 
\fBtaler\-exchange\-reservemod\fP(1), \fBtaler\-exchange\-dbinit\fP(1), 
\fBtaler\-exchange\-sepa(1)
+\fBtaler\-exchange\-httpd\fP(1), \fBtaler\-exchange\-keyup\fP(1), 
\fBtaler\-exchange\-dbinit\fP(1), \fBtaler\-exchange\-wire(1)
diff --git a/src/Makefile.am b/src/Makefile.am
index 2f158a1..d2c9255 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -22,7 +22,7 @@ pkgcfg_DATA = \
 EXTRA_DIST = \
   taler.conf
 
-SUBDIRS = include util json $(PQ_DIR) $(BANK_LIB) wire exchangedb exchange 
exchange-tools auditordb auditor
+SUBDIRS = include util wire json $(PQ_DIR) $(BANK_LIB) wire-plugins exchangedb 
exchange exchange-tools auditordb auditor
 if HAVE_LIBCURL
  SUBDIRS += exchange-lib benchmark
 else
diff --git a/src/auditor/taler-auditor.c b/src/auditor/taler-auditor.c
index b8f6c62..f5d185c 100644
--- a/src/auditor/taler-auditor.c
+++ b/src/auditor/taler-auditor.c
@@ -761,7 +761,7 @@ handle_reserve_in (void *cls,
                    uint64_t rowid,
                    const struct TALER_ReservePublicKeyP *reserve_pub,
                    const struct TALER_Amount *credit,
-                   const json_t *sender_account_details,
+                   const char *sender_account_details,
                    const void *wire_reference,
                    size_t wire_reference_size,
                    struct GNUNET_TIME_Absolute execution_date)
@@ -1193,7 +1193,7 @@ handle_reserve_closed (void *cls,
                       const struct TALER_Amount *amount_with_fee,
                       const struct TALER_Amount *closing_fee,
                       const struct TALER_ReservePublicKeyP *reserve_pub,
-                      const json_t *receiver_account,
+                      const char *receiver_account,
                       const struct TALER_WireTransferIdentifierRawP 
*transfer_details)
 {
   struct ReserveContext *rc = cls;
@@ -1774,11 +1774,6 @@ struct WireCheckContext
   struct GNUNET_TIME_Absolute date;
 
   /**
-   * Wire method used for the transfer.
-   */
-  const char *method;
-
-  /**
    * Database transaction status.
    */
   enum GNUNET_DB_QueryStatus qs;
@@ -2069,8 +2064,8 @@ check_transaction_history (const struct 
TALER_CoinSpendPublicKeyP *coin_pub,
  * @param cls a `struct WireCheckContext`
  * @param rowid which row in the table is the information from (for 
diagnostics)
  * @param merchant_pub public key of the merchant (should be same for all 
callbacks with the same @e cls)
- * @param wire_method which wire plugin was used for the transfer?
  * @param h_wire hash of wire transfer details of the merchant (should be same 
for all callbacks with the same @e cls)
+ * @param account_details where did we transfer the funds?
  * @param exec_time execution time of the wire transfer (should be same for 
all callbacks with the same @e cls)
  * @param h_contract_terms which proposal was this payment about
  * @param coin_pub which public key was this payment about
@@ -2082,8 +2077,8 @@ static void
 wire_transfer_information_cb (void *cls,
                               uint64_t rowid,
                               const struct TALER_MerchantPublicKeyP 
*merchant_pub,
-                              const char *wire_method,
                               const struct GNUNET_HashCode *h_wire,
+                              const json_t *account_details,
                               struct GNUNET_TIME_Absolute exec_time,
                               const struct GNUNET_HashCode *h_contract_terms,
                               const struct TALER_CoinSpendPublicKeyP *coin_pub,
@@ -2097,6 +2092,29 @@ wire_transfer_information_cb (void *cls,
   struct TALER_EXCHANGEDB_TransactionList *tl;
   const struct TALER_CoinPublicInfo *coin;
   enum GNUNET_DB_QueryStatus qs;
+  struct GNUNET_HashCode hw;
+
+  if (GNUNET_OK !=
+      TALER_JSON_wire_signature_hash (account_details,
+                                      &hw))
+  {
+    wcc->qs = GNUNET_DB_STATUS_HARD_ERROR;
+    report_row_inconsistency ("aggregation",
+                              rowid,
+                              "failed to compute hash of given wire data");
+    return;
+  }
+  if (0 !=
+      memcmp (&hw,
+              h_wire,
+              sizeof (struct GNUNET_HashCode)))
+  {
+    wcc->qs = GNUNET_DB_STATUS_HARD_ERROR;
+    report_row_inconsistency ("aggregation",
+                              rowid,
+                              "database contains wrong hash code for wire 
details");
+    return;
+  }
 
   /* Obtain coin's transaction history */
   qs = edb->get_coin_transactions (edb->cls,
@@ -2183,8 +2201,9 @@ wire_transfer_information_cb (void *cls,
                                    tl);
 
   /* Check other details of wire transfer match */
-  if (0 != strcmp (wire_method,
-                   wcc->method))
+  if (0 != memcmp (h_wire,
+                   &wcc->h_wire,
+                   sizeof (struct GNUNET_HashCode)))
   {
     wcc->qs = GNUNET_DB_STATUS_HARD_ERROR;
     report_row_inconsistency ("aggregation",
@@ -2360,12 +2379,12 @@ check_wire_out_cb (void *cls,
 {
   struct AggregationContext *ac = cls;
   struct WireCheckContext wcc;
-  json_t *method;
   struct TALER_WIRE_Plugin *plugin;
   const struct TALER_Amount *wire_fee;
   struct TALER_Amount final_amount;
   struct TALER_Amount exchange_gain;
   enum GNUNET_DB_QueryStatus qs;
+  char *method;
 
   /* should be monotonically increasing */
   GNUNET_assert (rowid >= pp.last_wire_out_serial_id);
@@ -2376,26 +2395,23 @@ check_wire_out_cb (void *cls,
               TALER_B2S (wtid),
               TALER_amount2s (amount),
               GNUNET_STRINGS_absolute_time_to_string (date));
-  wcc.ac = ac;
-  method = json_object_get (wire,
-                            "type");
-  if ( (NULL == method) ||
-       (! json_is_string (method)) )
+  if (NULL == (method = TALER_JSON_wire_to_method (wire)))
   {
     report_row_inconsistency ("wire_out",
                               rowid,
-                              "specified wire address lacks type");
+                              "specified wire address lacks method");
     return GNUNET_OK;
   }
-  wcc.method = json_string_value (method);
+
+  wcc.ac = ac;
   wcc.qs = GNUNET_DB_STATUS_SUCCESS_ONE_RESULT;
   wcc.date = date;
   GNUNET_assert (GNUNET_OK ==
                  TALER_amount_get_zero (amount->currency,
                                         &wcc.total_deposits));
   if (GNUNET_OK !=
-      TALER_JSON_hash (wire,
-                       &wcc.h_wire))
+      TALER_JSON_wire_signature_hash (wire,
+                                      &wcc.h_wire))
   {
     GNUNET_break (0);
     return GNUNET_SYSERR;
@@ -2409,6 +2425,7 @@ check_wire_out_cb (void *cls,
   {
     GNUNET_break (GNUNET_DB_STATUS_SOFT_ERROR == qs);
     ac->qs = qs;
+    GNUNET_free (method);
     return GNUNET_SYSERR;
   }
   if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != wcc.qs)
@@ -2417,17 +2434,19 @@ check_wire_out_cb (void *cls,
     report_row_inconsistency ("wire_out",
                               rowid,
                               "audit of associated transactions failed");
+    GNUNET_free (method);
     return GNUNET_OK;
   }
 
   /* Subtract aggregation fee from total */
   wire_fee = get_wire_fee (ac,
-                           wcc.method,
+                           method,
                            date);
   if (NULL == wire_fee)
   {
     GNUNET_break (0);
     ac->qs = GNUNET_DB_STATUS_HARD_ERROR;
+    GNUNET_free (method);
     return GNUNET_SYSERR;
   }
   if (GNUNET_SYSERR ==
@@ -2440,18 +2459,20 @@ check_wire_out_cb (void *cls,
                                             &wcc.total_deposits,
                                             wire_fee,
                                             -1);
+    GNUNET_free (method);
     return GNUNET_OK;
   }
 
   /* Round down to amount supported by wire method */
   plugin = get_wire_plugin (ac,
-                            wcc.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));
@@ -3408,8 +3429,8 @@ deposit_cb (void *cls,
   dr.purpose.size = htonl (sizeof (dr));
   dr.h_contract_terms = *h_contract_terms;
   if (GNUNET_OK !=
-      TALER_JSON_hash (receiver_wire_account,
-                       &dr.h_wire))
+      TALER_JSON_wire_signature_hash (receiver_wire_account,
+                                      &dr.h_wire))
   {
     GNUNET_break (0);
     cc->qs = GNUNET_DB_STATUS_HARD_ERROR;
diff --git a/src/auditor/taler-wire-auditor.c b/src/auditor/taler-wire-auditor.c
index 55a2a05..6e66ea9 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 Taler Systems SA
+  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
@@ -40,6 +40,45 @@
  */
 #define GRACE_PERIOD GNUNET_TIME_UNIT_HOURS
 
+
+/**
+ * Information we keep for each supported account.
+ */
+struct WireAccount
+{
+  /**
+   * Accounts are kept in a DLL.
+   */
+  struct WireAccount *next;
+
+  /**
+   * Plugins are kept in a DLL.
+   */
+  struct WireAccount *prev;
+
+  /**
+   * Handle to the plugin.
+   */
+  struct TALER_WIRE_Plugin *wire_plugin;
+
+  /**
+   * Name of the section that configures this account.
+   */
+  char *section_name;
+
+  /**
+   * We should check for inbound transactions to this account.
+   */
+  int watch_credit;
+
+  /**
+   * We should check for outbound transactions from this account.
+   */
+  int watch_debit;
+
+};
+
+
 /**
  * Return value from main().
  */
@@ -51,11 +90,6 @@ static int global_ret;
 static int restart;
 
 /**
- * Name of the wire plugin to load to access the exchange's bank account.
- */
-static char *wire_plugin;
-
-/**
  * Handle to access the exchange's database.
  */
 static struct TALER_EXCHANGEDB_Plugin *edb;
@@ -104,11 +138,27 @@ static struct TALER_AUDITORDB_Session *asession;
 static struct TALER_MasterPublicKeyP master_pub;
 
 /**
+ * Head of list of wire accounts we still need to look at.
+ */
+static struct WireAccount *wa_head;
+
+/**
+ * Tail of list of wire accounts we still need to look at.
+ */
+static struct WireAccount *wa_tail;
+
+/**
  * Handle to the wire plugin for wire operations.
  */
 static struct TALER_WIRE_Plugin *wp;
 
 /**
+ * Name of the section that configures the account
+ * we are currently processing (matches #wp).
+ */
+static char *wp_section_name;
+
+/**
  * Active wire request for the transaction history.
  */
 static struct TALER_WIRE_HistoryHandle *hh;
@@ -289,7 +339,8 @@ free_rii (void *cls,
                 GNUNET_CONTAINER_multihashmap_remove (in_map,
                                                       key,
                                                       rii));
-  json_decref (rii->details.account_details);
+  GNUNET_free (rii->details.account_url);
+  GNUNET_free_non_null (rii->details.wtid_s); /* field not used (yet) */
   GNUNET_free (rii);
   return GNUNET_OK;
 }
@@ -314,7 +365,8 @@ free_roi (void *cls,
                 GNUNET_CONTAINER_multihashmap_remove (out_map,
                                                       key,
                                                       roi));
-  json_decref (roi->details.account_details);
+  GNUNET_free (roi->details.account_url);
+  GNUNET_free_non_null (roi->details.wtid_s); /* field not used (yet) */
   GNUNET_free (roi);
   return GNUNET_OK;
 }
@@ -328,6 +380,8 @@ free_roi (void *cls,
 static void
 do_shutdown (void *cls)
 {
+  struct WireAccount *wa;
+
   if (NULL != report_row_inconsistencies)
   {
     json_t *report;
@@ -407,6 +461,20 @@ do_shutdown (void *cls)
     TALER_WIRE_plugin_unload (wp);
     wp = NULL;
   }
+  if (NULL != wp_section_name)
+  {
+    GNUNET_free (wp_section_name);
+    wp_section_name = NULL;
+  }
+  while (NULL != (wa = wa_head))
+  {
+    GNUNET_CONTAINER_DLL_remove (wa_head,
+                                 wa_tail,
+                                 wa);
+    TALER_WIRE_plugin_unload (wa->wire_plugin);
+    GNUNET_free (wa->section_name);
+    GNUNET_free (wa);
+  }
   if (NULL != adb)
   {
     TALER_AUDITORDB_plugin_unload (adb);
@@ -470,6 +538,7 @@ commit (enum GNUNET_DB_QueryStatus qs)
     qs = adb->update_wire_auditor_progress (adb->cls,
                                             asession,
                                             &master_pub,
+                                            wp_section_name,
                                             &pp,
                                             in_wire_off,
                                             out_wire_off,
@@ -478,6 +547,7 @@ commit (enum GNUNET_DB_QueryStatus qs)
     qs = adb->insert_wire_auditor_progress (adb->cls,
                                             asession,
                                             &master_pub,
+                                            wp_section_name,
                                             &pp,
                                             in_wire_off,
                                             out_wire_off,
@@ -583,37 +653,44 @@ wire_out_cb (void *cls,
                                     amount));
     return GNUNET_OK;
   }
-  if (! json_equal ((json_t *) wire,
-                   roi->details.account_details))
   {
-    /* Destination bank account is wrong in actual wire transfer, so
-       we should count the wire transfer as entirely spurious, and
-       additionally consider the justified wire transfer as missing. */
-    report (report_wire_out_inconsistencies,
-            json_pack ("{s:I, s:o, s:o, s:o, s:s, s:s}",
-                       "row", (json_int_t) rowid,
-                       "amount_wired", TALER_JSON_from_amount 
(&roi->details.amount),
-                       "amount_justified", TALER_JSON_from_amount (&zero),
-                       "wtid", GNUNET_JSON_from_data_auto (wtid),
-                       "timestamp", GNUNET_STRINGS_absolute_time_to_string 
(date),
-                       "diagnostic", "recevier account missmatch"));
-    GNUNET_break (GNUNET_OK ==
-                  TALER_amount_add (&total_bad_amount_out_plus,
-                                    &total_bad_amount_out_plus,
-                                    &roi->details.amount));
-    report (report_wire_out_inconsistencies,
-            json_pack ("{s:I, s:o, s:o, s:o, s:s, s:s}",
-                       "row", (json_int_t) rowid,
-                       "amount_wired", TALER_JSON_from_amount (&zero),
-                       "amount_justified", TALER_JSON_from_amount (amount),
-                       "wtid", GNUNET_JSON_from_data_auto (wtid),
-                       "timestamp", GNUNET_STRINGS_absolute_time_to_string 
(date),
-                       "diagnostic", "receiver account missmatch"));
-    GNUNET_break (GNUNET_OK ==
-                  TALER_amount_add (&total_bad_amount_out_minus,
-                                    &total_bad_amount_out_minus,
-                                    amount));
-    goto cleanup;
+    char *payto_url;
+
+    payto_url = TALER_JSON_wire_to_payto (wire);
+    if (0 != strcasecmp (payto_url,
+                         roi->details.account_url))
+    {
+      /* Destination bank account is wrong in actual wire transfer, so
+         we should count the wire transfer as entirely spurious, and
+         additionally consider the justified wire transfer as missing. */
+      report (report_wire_out_inconsistencies,
+              json_pack ("{s:I, s:o, s:o, s:o, s:s, s:s}",
+                         "row", (json_int_t) rowid,
+                         "amount_wired", TALER_JSON_from_amount 
(&roi->details.amount),
+                         "amount_justified", TALER_JSON_from_amount (&zero),
+                         "wtid", GNUNET_JSON_from_data_auto (wtid),
+                         "timestamp", GNUNET_STRINGS_absolute_time_to_string 
(date),
+                         "diagnostic", "recevier account missmatch"));
+      GNUNET_break (GNUNET_OK ==
+                    TALER_amount_add (&total_bad_amount_out_plus,
+                                      &total_bad_amount_out_plus,
+                                      &roi->details.amount));
+      report (report_wire_out_inconsistencies,
+              json_pack ("{s:I, s:o, s:o, s:o, s:s, s:s}",
+                         "row", (json_int_t) rowid,
+                         "amount_wired", TALER_JSON_from_amount (&zero),
+                         "amount_justified", TALER_JSON_from_amount (amount),
+                         "wtid", GNUNET_JSON_from_data_auto (wtid),
+                         "timestamp", GNUNET_STRINGS_absolute_time_to_string 
(date),
+                         "diagnostic", "receiver account missmatch"));
+      GNUNET_break (GNUNET_OK ==
+                    TALER_amount_add (&total_bad_amount_out_minus,
+                                      &total_bad_amount_out_minus,
+                                      amount));
+      GNUNET_free (payto_url);
+      goto cleanup;
+    }
+    GNUNET_free (payto_url);
   }
   if (0 != TALER_amount_cmp (&roi->details.amount,
                             amount))
@@ -765,6 +842,16 @@ wire_missing_cb (void *cls,
 
 
 /**
+ * Start processing the next wire account.
+ * Shuts down if we are done.
+ *
+ * @param cls NULL
+ */
+static void
+process_next_account (void *cls);
+
+
+/**
  * Go over the "wire_out" table of the exchange and
  * verify that all wire outs are in that table.
  */
@@ -774,11 +861,12 @@ check_exchange_wire_out ()
   enum GNUNET_DB_QueryStatus qs;
   struct GNUNET_TIME_Absolute next_timestamp;
 
-  qs = edb->select_wire_out_above_serial_id (edb->cls,
-                                            esession,
-                                            pp.last_wire_out_serial_id,
-                                            &wire_out_cb,
-                                            NULL);
+  qs = edb->select_wire_out_above_serial_id_by_account (edb->cls,
+                                                        esession,
+                                                        wp_section_name,
+                                                        
pp.last_wire_out_serial_id,
+                                                        &wire_out_cb,
+                                                        NULL);
   if (0 > qs)
   {
     GNUNET_break (GNUNET_DB_STATUS_SOFT_ERROR == qs);
@@ -818,9 +906,8 @@ check_exchange_wire_out ()
   }
   pp.last_timestamp = next_timestamp;
 
-  /* conclude with: */
-  commit (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT);
-  GNUNET_SCHEDULER_shutdown ();
+  /* continue with next account: */
+  process_next_account (NULL);
 }
 
 
@@ -892,7 +979,7 @@ history_debit_cb (void *cls,
   roi->details.amount = details->amount;
   roi->details.execution_date = details->execution_date;
   roi->details.wtid = details->wtid;
-  roi->details.account_details = json_incref ((json_t *) 
details->account_details);
+  roi->details.account_url = GNUNET_strdup (details->account_url);
   if (GNUNET_OK !=
       GNUNET_CONTAINER_multihashmap_put (out_map,
                                         &roi->subject_hash,
@@ -936,6 +1023,7 @@ process_debits ()
   out_map = GNUNET_CONTAINER_multihashmap_create (1024,
                                                  GNUNET_YES);
   hh = wp->get_history (wp->cls,
+                        wp_section_name,
                         TALER_BANK_DIRECTION_DEBIT,
                         out_wire_off,
                         wire_off_size,
@@ -965,7 +1053,7 @@ process_debits ()
  * @param rowid unique serial ID for the refresh session in our DB
  * @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 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 execution_date when did we receive the funds
@@ -976,7 +1064,7 @@ reserve_in_cb (void *cls,
               uint64_t rowid,
               const struct TALER_ReservePublicKeyP *reserve_pub,
               const struct TALER_Amount *credit,
-              const json_t *sender_account_details,
+              const char *sender_url,
               const void *wire_reference,
               size_t wire_reference_size,
               struct GNUNET_TIME_Absolute execution_date)
@@ -997,7 +1085,7 @@ reserve_in_cb (void *cls,
   memcpy (&rii->details.wtid,
           reserve_pub,
           sizeof (*reserve_pub));
-  rii->details.account_details = json_incref ((json_t *) 
sender_account_details);
+  rii->details.account_url = GNUNET_strdup (sender_url);
   rii->rowid = rowid;
   if (GNUNET_OK !=
       GNUNET_CONTAINER_multihashmap_put (in_map,
@@ -1011,7 +1099,8 @@ reserve_in_cb (void *cls,
                        "row", (json_int_t) rowid,
                        "wire_offset_hash", GNUNET_JSON_from_data_auto 
(&rii->row_off_hash),
                        "diagnostic", "duplicate wire offset"));
-    json_decref (rii->details.account_details);
+    GNUNET_free (rii->details.account_url);
+    GNUNET_free_non_null (rii->details.wtid_s); /* field not used (yet) */
     GNUNET_free (rii);
     return GNUNET_OK;
   }
@@ -1228,8 +1317,8 @@ history_credit_cb (void *cls,
     }
     goto cleanup;
   }
-  if (! json_equal (details->account_details,
-                   rii->details.account_details))
+  if (0 != strcasecmp (details->account_url,
+                       rii->details.account_url))
   {
     report (report_missattribution_in_inconsistencies,
             json_pack ("{s:s, s:o, s:o}",
@@ -1267,6 +1356,168 @@ history_credit_cb (void *cls,
 
 
 /**
+ * Start processing the next wire account.
+ * Shuts down if we are done.
+ *
+ * @param cls NULL
+ */
+static void
+process_next_account (void *cls)
+{
+  struct WireAccount *wa;
+  enum GNUNET_DB_QueryStatus qs;
+  int ret;
+
+  (void) cls;
+  if (NULL == (wa = wa_head))
+  {
+    commit (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT);
+    GNUNET_SCHEDULER_shutdown ();
+    return;
+  }
+  GNUNET_CONTAINER_DLL_remove (wa_head,
+                               wa_tail,
+                               wa);
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Starting audit of account `%s'\n",
+              wa->section_name);
+  /* setup globals */
+  if (NULL != wp)
+    TALER_WIRE_plugin_unload (wp);
+  wp = wa->wire_plugin;
+  GNUNET_free_non_null (wp_section_name);
+  wp_section_name = wa->section_name;
+  GNUNET_free (wa);
+
+  ret = adb->start (adb->cls,
+                    asession);
+  if (GNUNET_OK != ret)
+  {
+    GNUNET_break (0);
+    global_ret = 1;
+    GNUNET_SCHEDULER_shutdown ();
+    return;
+  }
+  edb->preflight (edb->cls,
+                  esession);
+  ret = edb->start (edb->cls,
+                    esession,
+                    "wire auditor");
+  if (GNUNET_OK != ret)
+  {
+    GNUNET_break (0);
+    global_ret = 1;
+    GNUNET_SCHEDULER_shutdown ();
+    return;
+  }
+  qsx = adb->get_wire_auditor_progress (adb->cls,
+                                        asession,
+                                        &master_pub,
+                                        wp_section_name,
+                                        &pp,
+                                        &in_wire_off,
+                                        &out_wire_off,
+                                        &wire_off_size);
+  if (0 > qsx)
+  {
+    GNUNET_break (GNUNET_DB_STATUS_SOFT_ERROR == qsx);
+    global_ret = 1;
+    GNUNET_SCHEDULER_shutdown ();
+    return;
+  }
+  if (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS == qsx)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
+                _("First analysis using this auditor, starting audit from 
scratch\n"));
+  }
+  else
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+                _("Resuming audit at %llu/%llu\n"),
+                (unsigned long long) pp.last_reserve_in_serial_id,
+                (unsigned long long) pp.last_wire_out_serial_id);
+  }
+
+  in_map = GNUNET_CONTAINER_multihashmap_create (1024,
+                                                GNUNET_YES);
+  qs = edb->select_reserves_in_above_serial_id_by_account (edb->cls,
+                                                           esession,
+                                                           wp_section_name,
+                                                           
pp.last_reserve_in_serial_id,
+                                                           &reserve_in_cb,
+                                                           NULL);
+  if (0 > qs)
+  {
+    GNUNET_break (GNUNET_DB_STATUS_SOFT_ERROR == qs);
+    global_ret = 1;
+    GNUNET_SCHEDULER_shutdown ();
+    return;
+  }
+  if (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS == qs)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
+                "No new incoming transactions available, skipping CREDIT 
phase\n");
+    process_debits ();
+    return;
+  }
+  hh = wp->get_history (wp->cls,
+                        wp_section_name,
+                        TALER_BANK_DIRECTION_CREDIT,
+                        in_wire_off,
+                        wire_off_size,
+                        INT64_MAX,
+                        &history_credit_cb,
+                        NULL);
+  if (NULL == hh)
+  {
+    fprintf (stderr,
+             "Failed to obtain bank transaction history\n");
+    commit (GNUNET_DB_STATUS_HARD_ERROR);
+    global_ret = 1;
+    GNUNET_SCHEDULER_shutdown ();
+    return;
+  }
+}
+
+
+/**
+ * Function called with information about a wire account.  Adds the
+ * account to our list for processing (if it is enabled and we can
+ * load the plugin).
+ *
+ * @param cls closure, NULL
+ * @param ai account information
+ */
+static void
+process_account_cb (void *cls,
+                    const struct TALER_EXCHANGEDB_AccountInfo *ai)
+{
+  struct WireAccount *wa;
+  struct TALER_WIRE_Plugin *wp;
+
+  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;
+  }
+  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;
+  GNUNET_CONTAINER_DLL_insert (wa_head,
+                               wa_tail,
+                               wa);
+}
+
+
+/**
  * Main function that will be run.
  *
  * @param cls closure
@@ -1281,8 +1532,6 @@ run (void *cls,
      const struct GNUNET_CONFIGURATION_Handle *c)
 {
   static const struct TALER_MasterPublicKeyP zeromp;
-  enum GNUNET_DB_QueryStatus qs;
-  int ret;
 
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
               "Launching auditor\n");
@@ -1390,40 +1639,6 @@ run (void *cls,
     GNUNET_SCHEDULER_shutdown ();
     return;
   }
-  wp = TALER_WIRE_plugin_load (cfg,
-                               wire_plugin);
-  if (NULL == wp)
-  {
-    fprintf (stderr,
-             "Failed to load wire plugin `%s'\n",
-             wire_plugin);
-    global_ret = 1;
-    GNUNET_SCHEDULER_shutdown ();
-    return;
-  }
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "Starting audit\n");
-  ret = adb->start (adb->cls,
-                    asession);
-  if (GNUNET_OK != ret)
-  {
-    GNUNET_break (0);
-    global_ret = 1;
-    GNUNET_SCHEDULER_shutdown ();
-    return;
-  }
-  edb->preflight (edb->cls,
-                  esession);
-  ret = edb->start (edb->cls,
-                    esession,
-                    "wire auditor");
-  if (GNUNET_OK != ret)
-  {
-    GNUNET_break (0);
-    global_ret = 1;
-    GNUNET_SCHEDULER_shutdown ();
-    return;
-  }
   GNUNET_assert (NULL !=
                 (report_wire_out_inconsistencies = json_array ()));
   GNUNET_assert (NULL !=
@@ -1462,71 +1677,9 @@ run (void *cls,
   GNUNET_assert (GNUNET_OK ==
                  TALER_amount_get_zero (currency,
                                         &zero));
-
-  qsx = adb->get_wire_auditor_progress (adb->cls,
-                                        asession,
-                                        &master_pub,
-                                        &pp,
-                                        &in_wire_off,
-                                        &out_wire_off,
-                                        &wire_off_size);
-  if (0 > qsx)
-  {
-    GNUNET_break (GNUNET_DB_STATUS_SOFT_ERROR == qsx);
-    global_ret = 1;
-    GNUNET_SCHEDULER_shutdown ();
-    return;
-  }
-  if (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS == qsx)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
-                _("First analysis using this auditor, starting audit from 
scratch\n"));
-  }
-  else
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_INFO,
-                _("Resuming audit at %llu/%llu\n"),
-                (unsigned long long) pp.last_reserve_in_serial_id,
-                (unsigned long long) pp.last_wire_out_serial_id);
-  }
-
-  in_map = GNUNET_CONTAINER_multihashmap_create (1024,
-                                                GNUNET_YES);
-  qs = edb->select_reserves_in_above_serial_id (edb->cls,
-                                               esession,
-                                               pp.last_reserve_in_serial_id,
-                                               &reserve_in_cb,
-                                               NULL);
-  if (0 > qs)
-  {
-    GNUNET_break (GNUNET_DB_STATUS_SOFT_ERROR == qs);
-    global_ret = 1;
-    GNUNET_SCHEDULER_shutdown ();
-    return;
-  }
-  if (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS == qs)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
-                "No new incoming transactions available, skipping CREDIT 
phase\n");
-    process_debits ();
-    return;
-  }
-  hh = wp->get_history (wp->cls,
-                        TALER_BANK_DIRECTION_CREDIT,
-                        in_wire_off,
-                        wire_off_size,
-                        INT64_MAX,
-                        &history_credit_cb,
-                        NULL);
-  if (NULL == hh)
-  {
-    fprintf (stderr,
-             "Failed to obtain bank transaction history\n");
-    commit (GNUNET_DB_STATUS_HARD_ERROR);
-    global_ret = 1;
-    GNUNET_SCHEDULER_shutdown ();
-    return;
-  }
+  TALER_EXCHANGEDB_find_accounts (cfg,
+                                  &process_account_cb,
+                                  NULL);
 }
 
 
@@ -1552,12 +1705,6 @@ main (int argc,
                                "restart",
                                "restart audit from the beginning (required on 
first run)",
                                &restart),
-    GNUNET_GETOPT_option_mandatory
-    (GNUNET_GETOPT_option_string ('w',
-                                 "wire",
-                                 "PLUGINNAME",
-                                 "name of the wire plugin to use",
-                                 &wire_plugin)),
     GNUNET_GETOPT_OPTION_END
   };
 
diff --git a/src/auditordb/auditordb-postgres.conf 
b/src/auditordb/auditordb-postgres.conf
index 4fe2064..9a6d398 100644
--- a/src/auditordb/auditordb-postgres.conf
+++ b/src/auditordb/auditordb-postgres.conf
@@ -1,3 +1,3 @@
 [auditordb-postgres]
 # Argument for Postgres for how to connect to the database.
-DB_CONN_STR = "postgres:///taler"
+CONFIG = "postgres:///taler"
diff --git a/src/auditordb/plugin_auditordb_postgres.c 
b/src/auditordb/plugin_auditordb_postgres.c
index 2f881ae..13fbbc2 100644
--- a/src/auditordb/plugin_auditordb_postgres.c
+++ b/src/auditordb/plugin_auditordb_postgres.c
@@ -231,6 +231,7 @@ postgres_create_tables (void *cls)
                            ")"),
     GNUNET_PQ_make_execute ("CREATE TABLE IF NOT EXISTS wire_auditor_progress"
                            "(master_pub BYTEA PRIMARY KEY CHECK 
(LENGTH(master_pub)=32)"
+                            ",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"
                            ",last_timestamp INT8 NOT NULL"
@@ -521,13 +522,14 @@ postgres_prepare (PGconn *db_conn)
     GNUNET_PQ_make_prepare ("wire_auditor_progress_insert",
                            "INSERT INTO wire_auditor_progress "
                            "(master_pub"
+                            ",account_name"
                            ",last_wire_reserve_in_serial_id"
                            ",last_wire_wire_out_serial_id"
                             ",last_timestamp"
                             ",wire_in_off"
                             ",wire_out_off"
-                           ") VALUES ($1,$2,$3,$4,$5,$6);",
-                           6),
+                           ") VALUES ($1,$2,$3,$4,$5,$6,$7);",
+                           7),
     /* Used in #postgres_update_wire_auditor_progress() */
     GNUNET_PQ_make_prepare ("wire_auditor_progress_update",
                            "UPDATE wire_auditor_progress SET "
@@ -536,8 +538,8 @@ postgres_prepare (PGconn *db_conn)
                             ",last_timestamp=$3"
                             ",wire_in_off=$4"
                             ",wire_out_off=$5"
-                           " WHERE master_pub=$6",
-                           6),
+                           " WHERE master_pub=$6 AND account_name=$7",
+                           7),
     /* Used in #postgres_get_wire_auditor_progress() */
     GNUNET_PQ_make_prepare ("wire_auditor_progress_select",
                            "SELECT"
@@ -547,8 +549,8 @@ postgres_prepare (PGconn *db_conn)
                             ",wire_in_off"
                             ",wire_out_off"
                            " FROM wire_auditor_progress"
-                           " WHERE master_pub=$1;",
-                           1),
+                           " WHERE master_pub=$1 AND account_name=$2;",
+                           2),
     /* Used in #postgres_insert_reserve_info() */
     GNUNET_PQ_make_prepare ("auditor_reserves_insert",
                            "INSERT INTO auditor_reserves "
@@ -1342,6 +1344,7 @@ postgres_get_auditor_progress (void *cls,
  * @param cls the @e cls of this struct with the plugin-specific state
  * @param session connection to use
  * @param master_pub master key of the exchange
+ * @param account_name name of the wire account we are auditing
  * @param pp where is the auditor in processing
  * @return transaction status code
  */
@@ -1349,6 +1352,7 @@ static enum GNUNET_DB_QueryStatus
 postgres_insert_wire_auditor_progress (void *cls,
                                        struct TALER_AUDITORDB_Session *session,
                                        const struct TALER_MasterPublicKeyP 
*master_pub,
+                                       const char *account_name,
                                        const struct 
TALER_AUDITORDB_WireProgressPoint *pp,
                                        const void *in_wire_off,
                                        const void *out_wire_off,
@@ -1356,6 +1360,7 @@ postgres_insert_wire_auditor_progress (void *cls,
 {
   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),
     TALER_PQ_query_param_absolute_time (&pp->last_timestamp),
@@ -1379,6 +1384,7 @@ postgres_insert_wire_auditor_progress (void *cls,
  * @param cls the @e cls of this struct with the plugin-specific state
  * @param session connection to use
  * @param master_pub master key of the exchange
+ * @param account_name name of the wire account we are auditing
  * @param pp where is the auditor in processing
  * @return transaction status code
  */
@@ -1386,6 +1392,7 @@ static enum GNUNET_DB_QueryStatus
 postgres_update_wire_auditor_progress (void *cls,
                                        struct TALER_AUDITORDB_Session *session,
                                        const struct TALER_MasterPublicKeyP 
*master_pub,
+                                       const char *account_name,
                                        const struct 
TALER_AUDITORDB_WireProgressPoint *pp,
                                        const void *in_wire_off,
                                        const void *out_wire_off,
@@ -1400,6 +1407,7 @@ postgres_update_wire_auditor_progress (void *cls,
     GNUNET_PQ_query_param_fixed_size (out_wire_off,
                                       wire_off_size),
     GNUNET_PQ_query_param_auto_from_type (master_pub),
+    GNUNET_PQ_query_param_string (account_name),
     GNUNET_PQ_query_param_end
   };
 
@@ -1415,6 +1423,7 @@ postgres_update_wire_auditor_progress (void *cls,
  * @param cls the @e cls of this struct with the plugin-specific state
  * @param session connection to use
  * @param master_pub master key of the exchange
+ * @param account_name name of the wire account we are auditing
  * @param[out] pp set to where the auditor is in processing
  * @return transaction status code
  */
@@ -1422,6 +1431,7 @@ static enum GNUNET_DB_QueryStatus
 postgres_get_wire_auditor_progress (void *cls,
                                     struct TALER_AUDITORDB_Session *session,
                                     const struct TALER_MasterPublicKeyP 
*master_pub,
+                                    const char *account_name,
                                     struct TALER_AUDITORDB_WireProgressPoint 
*pp,
                                     void **in_wire_off,
                                     void **out_wire_off,
@@ -1431,6 +1441,7 @@ postgres_get_wire_auditor_progress (void *cls,
   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),
     GNUNET_PQ_query_param_end
   };
   struct GNUNET_PQ_ResultSpec rs[] = {
@@ -2594,12 +2605,12 @@ libtaler_plugin_auditordb_postgres_init (void *cls)
     if (GNUNET_OK !=
         GNUNET_CONFIGURATION_get_value_string (cfg,
                                                "auditordb-postgres",
-                                               "db_conn_str",
+                                               "CONFIG",
                                                &pg->connection_cfg_str))
     {
       GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
                                  "auditordb-postgres",
-                                 "db_conn_str");
+                                 "CONFIG");
       GNUNET_free (pg);
       return NULL;
     }
diff --git a/src/auditordb/test-auditor-db-postgres.conf 
b/src/auditordb/test-auditor-db-postgres.conf
index 5c1e7fb..fd8ffbf 100644
--- a/src/auditordb/test-auditor-db-postgres.conf
+++ b/src/auditordb/test-auditor-db-postgres.conf
@@ -4,4 +4,4 @@ DB = postgres
 
 [auditordb-postgres]
 # Argument for Postgres for how to connect to the database.
-DB_CONN_STR = "postgres:///talercheck"
+CONFIG = "postgres:///talercheck"
diff --git a/src/bank-lib/Makefile.am b/src/bank-lib/Makefile.am
index abe820a..9f2740b 100644
--- a/src/bank-lib/Makefile.am
+++ b/src/bank-lib/Makefile.am
@@ -32,7 +32,8 @@ 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_reject.c \
+  bank_api_parse.c
 
 libtalerbank_la_LIBADD = \
   $(top_builddir)/src/json/libtalerjson.la \
@@ -148,6 +149,7 @@ test_bank_api_new_SOURCES = \
 
 test_bank_api_new_LDADD = \
   $(top_builddir)/src/exchange-lib/libtalertesting.la \
+  $(top_builddir)/src/json/libtalerjson.la \
   libtalerbanktesting.la \
   -ltalerexchange \
   -lgnunetutil \
diff --git a/src/bank-lib/bank.conf b/src/bank-lib/bank.conf
index f6e4e7f..9befeba 100644
--- a/src/bank-lib/bank.conf
+++ b/src/bank-lib/bank.conf
@@ -1,8 +1,11 @@
 [taler]
 currency = KUDOS
 
+[account-1]
+URL = payto://x-taler-bank/localhost:8081/1
+
 [bank]
-http_port = 8081
+HTTP_PORT = 8081
 
 [exchange-wire-test]
 bank_url = http://localhost:8081/
diff --git a/src/bank-lib/bank_api_history.c b/src/bank-lib/bank_api_history.c
index 14a206a..902165d 100644
--- a/src/bank-lib/bank_api_history.c
+++ b/src/bank-lib/bank_api_history.c
@@ -136,10 +136,12 @@ parse_account_history (struct TALER_BANK_HistoryHandle 
*hh,
       GNUNET_JSON_parse_free (hist_spec);
       return GNUNET_SYSERR;
     }
-    td.account_details = json_pack ("{s:s, s:s, s:I}",
-                                    "type", "test",
-                                    "bank_url", hh->bank_base_url,
-                                    "account_number", (json_int_t) 
other_account);
+    GNUNET_asprintf (&td.account_url,
+                     ('/' == hh->bank_base_url[strlen(hh->bank_base_url)-1])
+                     ? "payto://x-taler-bank/%s%llu"
+                     : "payto://x-taler-bank/%s/%llu",
+                     hh->bank_base_url,
+                     (unsigned long long) other_account);
     hh->hcb (hh->hcb_cls,
              MHD_HTTP_OK,
              TALER_EC_NONE,
@@ -147,7 +149,7 @@ parse_account_history (struct TALER_BANK_HistoryHandle *hh,
              row_id,
              &td,
              transaction);
-    json_decref (td.account_details);
+    GNUNET_free (td.account_url);
     GNUNET_JSON_parse_free (hist_spec);
   }
   return GNUNET_OK;
diff --git a/src/bank-lib/bank_api_parse.c b/src/bank-lib/bank_api_parse.c
new file mode 100644
index 0000000..04cf7b8
--- /dev/null
+++ b/src/bank-lib/bank_api_parse.c
@@ -0,0 +1,133 @@
+/*
+  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/bank_api_parse.c
+ * @brief Convenience function to parse authentication configuration
+ * @author Christian Grothoff
+ */
+#include "platform.h"
+#include "taler_bank_service.h"
+
+
+/**
+ * Parse configuration section with bank authentication data.
+ *
+ * @param cfg configuration to parse
+ * @param section the section with the configuration data
+ * @param auth[out] set to the configuration data found
+ * @return #GNUNET_OK on success
+ */
+int
+TALER_BANK_auth_parse_cfg (const struct GNUNET_CONFIGURATION_Handle *cfg,
+                           const char *section,
+                           struct TALER_BANK_AuthenticationData *auth)
+{
+  const struct {
+    const char *m;
+    enum TALER_BANK_AuthenticationMethod e;
+  } methods[] = {
+    { "NONE",  TALER_BANK_AUTH_NONE  },
+    { "BASIC", TALER_BANK_AUTH_BASIC },
+    { NULL, TALER_BANK_AUTH_NONE     }
+  };
+  char *method;
+
+  if (GNUNET_OK !=
+      GNUNET_CONFIGURATION_get_value_string (cfg,
+                                             section,
+                                             "TALER_BANK_AUTH_METHOD",
+                                             &method))
+  {
+    GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
+                               section,
+                               "TALER_BANK_AUTH_METHOD");
+    return GNUNET_SYSERR;
+  }
+  for (unsigned int i=0; NULL != methods[i].m;i++)
+  {
+    if (0 == strcasecmp (method,
+                         methods[i].m))
+    {
+      switch (methods[i].e)
+      {
+      case TALER_BANK_AUTH_NONE:
+        auth->method = TALER_BANK_AUTH_NONE;
+        return GNUNET_OK;
+      case TALER_BANK_AUTH_BASIC:
+        if (GNUNET_OK !=
+            GNUNET_CONFIGURATION_get_value_string (cfg,
+                                                   section,
+                                                   "USERNAME",
+                                                   
&auth->details.basic.username))
+        {
+          GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
+                                     section,
+                                     "USERNAME");
+          return GNUNET_SYSERR;
+        }
+        if (GNUNET_OK !=
+            GNUNET_CONFIGURATION_get_value_string (cfg,
+                                                   section,
+                                                   "PASSWORD",
+                                                   
&auth->details.basic.password))
+        {
+          GNUNET_free (auth->details.basic.username);
+          auth->details.basic.username = NULL;
+          GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
+                                     section,
+                                     "USERNAME");
+          return GNUNET_SYSERR;
+        }
+        auth->method = TALER_BANK_AUTH_BASIC;
+        return GNUNET_OK;
+      }
+    }
+  }
+  return GNUNET_SYSERR;
+}
+
+
+/**
+ * Free memory inside of @a auth (but not auth itself).
+ * Dual to #TALER_BANK_auth_parse_cfg().
+ *
+ * @param auth authentication data to free
+ */
+void
+TALER_BANK_auth_free (struct TALER_BANK_AuthenticationData *auth)
+{
+  switch (auth->method)
+  {
+  case TALER_BANK_AUTH_NONE:
+    break;
+  case TALER_BANK_AUTH_BASIC:
+    if (NULL != auth->details.basic.username)
+    {
+      GNUNET_free (auth->details.basic.username);
+      auth->details.basic.username = NULL;
+    }
+    if (NULL != auth->details.basic.password)
+    {
+      GNUNET_free (auth->details.basic.password);
+      auth->details.basic.password = NULL;
+    }
+    break;
+  }
+}
+
+
+/* end of bank_api_parse.c */
diff --git a/src/bank-lib/bank_twisted.conf b/src/bank-lib/bank_twisted.conf
index 54e8c80..d20e109 100644
--- a/src/bank-lib/bank_twisted.conf
+++ b/src/bank-lib/bank_twisted.conf
@@ -29,5 +29,8 @@ currency = KUDOS
 [bank]
 http_port = 8081
 
+[account-1]
+URL = payto://x-taler-bank/localhost:8081/1
+
 [exchange-wire-test]
 bank_url = http://localhost:8081/
diff --git a/src/bank-lib/test_bank_api_with_fakebank_new.c 
b/src/bank-lib/test_bank_api_with_fakebank_new.c
index 1a70f57..002010b 100644
--- a/src/bank-lib/test_bank_api_with_fakebank_new.c
+++ b/src/bank-lib/test_bank_api_with_fakebank_new.c
@@ -210,9 +210,10 @@ main (int argc,
                     "DEBUG",
                     NULL);
   if (NULL ==
-    (fakebank_url = TALER_TESTING_prepare_fakebank (CONFIG_FILE)))
+      (fakebank_url = TALER_TESTING_prepare_fakebank (CONFIG_FILE,
+                                                      "account-1")))
     return 77;
-  
+
   return (GNUNET_OK == TALER_TESTING_setup (&run,
                                             NULL,
                                             CONFIG_FILE,
diff --git a/src/bank-lib/test_bank_api_with_fakebank_twisted.c 
b/src/bank-lib/test_bank_api_with_fakebank_twisted.c
index 6465c03..4e49110 100644
--- a/src/bank-lib/test_bank_api_with_fakebank_twisted.c
+++ b/src/bank-lib/test_bank_api_with_fakebank_twisted.c
@@ -75,9 +75,7 @@ static void
 run (void *cls,
      struct TALER_TESTING_Interpreter *is)
 {
-
   struct TALER_TESTING_Command commands[] = {
-
     TALER_TESTING_cmd_bank_history ("history-0",
                                     fakebank_url,
                                     EXCHANGE_ACCOUNT_NUMBER,
@@ -110,6 +108,7 @@ purge_process (struct GNUNET_OS_Process *process)
   GNUNET_OS_process_destroy (process);
 }
 
+
 int
 main (int argc,
       char * const *argv)
@@ -122,13 +121,14 @@ main (int argc,
                     "DEBUG", NULL);
 
   if (NULL == (fakebank_url = TALER_TESTING_prepare_fakebank
-      (CONFIG_FILE)))
+               (CONFIG_FILE,
+                "account-1")))
     return 77;
 
   if (NULL == (twister_url = TALER_TESTING_prepare_twister
       (CONFIG_FILE)))
     return 77;
-  
+
   if (NULL == (twisterd = TALER_TESTING_run_twister (CONFIG_FILE)))
     return 77;
 
diff --git a/src/bank-lib/test_bank_interpreter.c 
b/src/bank-lib/test_bank_interpreter.c
index 40adea5..e503bd8 100644
--- a/src/bank-lib/test_bank_interpreter.c
+++ b/src/bank-lib/test_bank_interpreter.c
@@ -326,15 +326,10 @@ build_history (struct InterpreterState *is,
       h[total].direction = TALER_BANK_DIRECTION_CREDIT;
       if (GNUNET_YES == cancelled)
         h[total].direction |= TALER_BANK_DIRECTION_CANCEL;
-      h[total].details.account_details
-        = json_pack ("{s:s, s:s, s:I}",
-                     "type",
-                     "test",
-                     "bank_url",
-                     "http://localhost:8080";,
-                     "account_number",
-                     (json_int_t) 
pos->details.admin_add_incoming.debit_account_no);
-      GNUNET_assert (NULL != h[total].details.account_details);
+      GNUNET_asprintf (&h[total].details.account_url,
+                       "payto://x-taler-bank/%s/%llu",
+                       "http://localhost:8080";,
+                       (unsigned long long) 
pos->details.admin_add_incoming.debit_account_no);
     }
     if ( (0 != (cmd->details.history.direction & TALER_BANK_DIRECTION_DEBIT)) 
&&
            (cmd->details.history.account_number ==
@@ -343,15 +338,10 @@ build_history (struct InterpreterState *is,
       h[total].direction = TALER_BANK_DIRECTION_DEBIT;
       if (GNUNET_YES == cancelled)
         h[total].direction |= TALER_BANK_DIRECTION_CANCEL;
-      h[total].details.account_details
-        = json_pack ("{s:s, s:s, s:I}",
-                     "type",
-                     "test",
-                     "bank_url",
-                     "http://localhost:8080";,
-                     "account_number",
-                     (json_int_t) 
pos->details.admin_add_incoming.credit_account_no);
-      GNUNET_assert (NULL != h[total].details.account_details);
+      GNUNET_asprintf (&h[total].details.account_url,
+                       "payto://x-taler-bank/%s/%llu",
+                       "http://localhost:8080";,
+                       (unsigned long long) 
pos->details.admin_add_incoming.credit_account_no);
     }
     if ( ( (0 != (cmd->details.history.direction & 
TALER_BANK_DIRECTION_CREDIT)) &&
            (cmd->details.history.account_number ==
@@ -398,10 +388,6 @@ print_expected (struct History *h,
               "Expected history:\n");
   for (uint64_t i=0;i<h_len;i++)
   {
-    char *acc;
-
-    acc = json_dumps (h[i].details.account_details,
-                      JSON_COMPACT);
     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
                 "H(%llu): %s%s (serial: %llu, subject: %s, to: %s)\n",
                 (unsigned long long) i,
@@ -409,9 +395,7 @@ print_expected (struct History *h,
                 TALER_amount2s (&h[i].details.amount),
                 (unsigned long long) h[i].row_id,
                 h[i].details.wire_transfer_subject,
-                acc);
-    if (NULL != acc)
-      free (acc);
+                h[i].details.account_url);
   }
 }
 
@@ -429,7 +413,7 @@ free_history (struct History *h,
   for (uint64_t off = 0;off<h_len;off++)
   {
     GNUNET_free (h[off].details.wire_transfer_subject);
-    json_decref (h[off].details.account_details);
+    GNUNET_free (h[off].details.account_url);
   }
   GNUNET_free_non_null (h);
 }
@@ -500,8 +484,8 @@ check_result (struct InterpreterState *is,
                      details->wire_transfer_subject)) ||
        (0 != TALER_amount_cmp (&h[off].details.amount,
                                &details->amount)) ||
-       (1 != json_equal (h[off].details.account_details,
-                         details->account_details)) )
+       (0 != strcasecmp (h[off].details.account_url,
+                         details->account_url)) )
   {
     GNUNET_break (0);
     print_expected (h, total, off);
diff --git a/src/bank-lib/testing_api_cmd_history.c 
b/src/bank-lib/testing_api_cmd_history.c
index d033e67..6f00536 100644
--- a/src/bank-lib/testing_api_cmd_history.c
+++ b/src/bank-lib/testing_api_cmd_history.c
@@ -99,6 +99,7 @@ history_traits (void *cls,
   return GNUNET_SYSERR;
 }
 
+
 /**
  * Test if the /admin/add/incoming transaction at offset @a off
  * has been /rejected.
@@ -115,7 +116,8 @@ test_cancelled (struct TALER_TESTING_Interpreter *is,
   const struct TALER_TESTING_Command *current_cmd;
 
   current_cmd = &is->commands[off];
-  TALER_LOG_INFO ("Is `%s' rejected?\n", current_cmd->label);
+  TALER_LOG_INFO ("Is `%s' rejected?\n",
+                  current_cmd->label);
   for (unsigned int i=0;i<is->ip;i++)
   {
     const struct TALER_TESTING_Command *c = &is->commands[i];
@@ -141,6 +143,7 @@ test_cancelled (struct TALER_TESTING_Interpreter *is,
   return GNUNET_NO;
 }
 
+
 /**
  * Free history @a h of length @a h_len.
  *
@@ -154,11 +157,12 @@ free_history (struct History *h,
   for (uint64_t off = 0;off<h_len;off++)
   {
     GNUNET_free (h[off].details.wire_transfer_subject);
-    json_decref (h[off].details.account_details);
+    GNUNET_free (h[off].details.account_url);
   }
   GNUNET_free_non_null (h);
 }
 
+
 /**
  * Log which history we expected.
  *
@@ -179,10 +183,6 @@ print_expected (struct History *h,
               "Expected history:\n");
   for (uint64_t i=0;i<h_len;i++)
   {
-    char *acc;
-
-    acc = json_dumps (h[i].details.account_details,
-                      JSON_COMPACT);
     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
                 "H(%llu): %s%s (serial: %llu, subject: %s, to: %s)\n",
                 (unsigned long long) i,
@@ -190,12 +190,11 @@ print_expected (struct History *h,
                 TALER_amount2s (&h[i].details.amount),
                 (unsigned long long) h[i].row_id,
                 h[i].details.wire_transfer_subject,
-                acc);
-    if (NULL != acc)
-      free (acc);
+                h[i].details.account_url);
   }
 }
 
+
 /**
  * Build history of transactions matching the current
  * command in @a is.
@@ -410,15 +409,10 @@ build_history (struct TALER_TESTING_Interpreter *is,
       h[total].direction = TALER_BANK_DIRECTION_CREDIT;
       if (GNUNET_YES == cancelled)
         h[total].direction |= TALER_BANK_DIRECTION_CANCEL;
-      h[total].details.account_details
-        = json_pack ("{s:s, s:s, s:I}",
-                     "type",
-                     "test",
-                     "bank_url",
-                     hs->bank_url,
-                     "account_number",
-                     (json_int_t) *debit_account_no);
-      GNUNET_assert (NULL != h[total].details.account_details);
+      GNUNET_asprintf (&h[total].details.account_url,
+                       "payto://x-taler-bank/%s/%llu",
+                       hs->bank_url,
+                       (unsigned long long) *debit_account_no);
     }
     if ( (0 != (hs->direction & TALER_BANK_DIRECTION_DEBIT)) &&
            (hs->account_no == *debit_account_no))
@@ -426,15 +420,10 @@ build_history (struct TALER_TESTING_Interpreter *is,
       h[total].direction = TALER_BANK_DIRECTION_DEBIT;
       if (GNUNET_YES == cancelled)
         h[total].direction |= TALER_BANK_DIRECTION_CANCEL;
-      h[total].details.account_details
-        = json_pack ("{s:s, s:s, s:I}",
-                     "type",
-                     "test",
-                     "bank_url",
-                     hs->bank_url,
-                     "account_number",
-                     (json_int_t) *credit_account_no);
-      GNUNET_assert (NULL != h[total].details.account_details);
+      GNUNET_asprintf (&h[total].details.account_url,
+                       "payto://x-taler-bank/%s/%llu",
+                       hs->bank_url,
+                       (unsigned long long) *credit_account_no);
     }
     if ( ( (0 != (hs->direction & TALER_BANK_DIRECTION_CREDIT)) &&
            (hs->account_no == *credit_account_no)) ||
@@ -534,8 +523,8 @@ check_result (struct TALER_TESTING_Interpreter *is,
                      details->wire_transfer_subject)) ||
        (0 != TALER_amount_cmp (&h[off].details.amount,
                                &details->amount)) ||
-       (1 != json_equal (h[off].details.account_details,
-                         details->account_details)) )
+       (0 != strcasecmp (h[off].details.account_url,
+                         details->account_url)) )
   {
     GNUNET_break (0);
     print_expected (h, total, off);
diff --git a/src/bank-lib/testing_api_cmd_reject.c 
b/src/bank-lib/testing_api_cmd_reject.c
index 24d7414..2eb6d4f 100644
--- a/src/bank-lib/testing_api_cmd_reject.c
+++ b/src/bank-lib/testing_api_cmd_reject.c
@@ -180,7 +180,7 @@ TALER_TESTING_cmd_bank_reject (const char *label,
   rs = GNUNET_new (struct RejectState);
   rs->bank_url = bank_url;
   rs->deposit_reference = deposit_reference;
-  
+
   cmd.cls = rs;
   cmd.run = &reject_run;
   cmd.cleanup = &reject_cleanup;
diff --git a/src/benchmark/taler-exchange-benchmark.c 
b/src/benchmark/taler-exchange-benchmark.c
index fbdfe82..3fd31ed 100644
--- a/src/benchmark/taler-exchange-benchmark.c
+++ b/src/benchmark/taler-exchange-benchmark.c
@@ -895,8 +895,8 @@ spend_coin (struct Coin *coin,
   dr.purpose.purpose = htonl (TALER_SIGNATURE_WALLET_COIN_DEPOSIT);
   dr.h_contract_terms = h_contract_terms;
   GNUNET_assert (GNUNET_OK ==
-                 TALER_JSON_hash (merchant_details,
-                                  &dr.h_wire));
+                 TALER_JSON_wire_signature_hash (merchant_details,
+                                                 &dr.h_wire));
 
   dr.timestamp = GNUNET_TIME_absolute_hton (timestamp);
   dr.refund_deadline = GNUNET_TIME_absolute_hton (refund_deadline);
diff --git a/src/benchmark/taler-exchange-benchmark.conf 
b/src/benchmark/taler-exchange-benchmark.conf
index 453782c..8876738 100644
--- a/src/benchmark/taler-exchange-benchmark.conf
+++ b/src/benchmark/taler-exchange-benchmark.conf
@@ -20,22 +20,20 @@ DB = postgres
 MASTER_PUBLIC_KEY = 98NJW3CQHZQGQXTY3K85K531XKPAPAVV4Q5V8PYYRR00NJGZWNVG
 
 [exchangedb-postgres]
-DB_CONN_STR = "postgres:///talercheck"
+CONFIG = "postgres:///talercheck"
 
-[exchange-wire-test]
-# Enable 'test' for testing of the actual coin operations.
-ENABLE = YES
+[account-exchange]
 
 # What is the main website of the bank?
 # (Not used unless the aggregator is run.)
-BANK_URL = "http://localhost:8082/";
-# From which account at the 'bank' should outgoing wire transfers be made?
-BANK_ACCOUNT_NUMBER = 2
+URL = "payto://x-taler-bank/localhost:8082/2"
 
 # This is the response we give out for the /wire request.  It provides
 # wallets with the bank information for transfers to the exchange.
-TEST_RESPONSE_FILE = ${TALER_CONFIG_HOME}/test.json
+WIRE_RESPONSE = ${TALER_CONFIG_HOME}/account.json
 
+
+[fees-x-taler-bank]
 WIRE-FEE-2017 = KUDOS:0.01
 WIRE-FEE-2018 = KUDOS:0.01
 WIRE-FEE-2019 = KUDOS:0.01
diff --git a/src/exchange-lib/Makefile.am b/src/exchange-lib/Makefile.am
index 5e0833b..57c9350 100644
--- a/src/exchange-lib/Makefile.am
+++ b/src/exchange-lib/Makefile.am
@@ -61,6 +61,7 @@ libtalertesting_la_SOURCES = \
   testing_api_trait_coin_priv.c \
   testing_api_trait_denom_pub.c \
   testing_api_trait_denom_sig.c \
+  testing_api_trait_json.c \
   testing_api_trait_process.c \
   testing_api_trait_reserve_priv.c \
   testing_api_trait_number.c \
@@ -69,8 +70,8 @@ libtalertesting_la_SOURCES = \
   testing_api_trait_key_peer.c \
   testing_api_trait_wtid.c \
   testing_api_trait_amount.c
-
 libtalertesting_la_LIBADD = \
+  $(top_builddir)/src/wire/libtalerwire.la \
   $(top_builddir)/src/json/libtalerjson.la \
   $(top_builddir)/src/util/libtalerutil.la \
   $(top_builddir)/src/bank-lib/libtalerfakebank.la \
diff --git a/src/exchange-lib/exchange_api_deposit.c 
b/src/exchange-lib/exchange_api_deposit.c
index 76e3e4d..7e499a4 100644
--- a/src/exchange-lib/exchange_api_deposit.c
+++ b/src/exchange-lib/exchange_api_deposit.c
@@ -416,8 +416,8 @@ TALER_EXCHANGE_deposit (struct TALER_EXCHANGE_Handle 
*exchange,
                 MAH_handle_is_ready (exchange));
   /* initialize h_wire */
   if (GNUNET_OK !=
-      TALER_JSON_hash (wire_details,
-                       &h_wire))
+      TALER_JSON_wire_signature_hash (wire_details,
+                                      &h_wire))
   {
     GNUNET_break (0);
     return NULL;
diff --git a/src/exchange-lib/exchange_api_reserve.c 
b/src/exchange-lib/exchange_api_reserve.c
index 72429d4..86a83fd 100644
--- a/src/exchange-lib/exchange_api_reserve.c
+++ b/src/exchange-lib/exchange_api_reserve.c
@@ -139,7 +139,7 @@ parse_reserve_history (struct TALER_EXCHANGE_Handle 
*exchange,
     if (0 == strcasecmp (type,
                          "DEPOSIT"))
     {
-      json_t *wire_account;
+      const char *wire_url;
       void *wire_reference;
       size_t wire_reference_size;
       struct GNUNET_TIME_Absolute timestamp;
@@ -150,8 +150,8 @@ parse_reserve_history (struct TALER_EXCHANGE_Handle 
*exchange,
                                   &wire_reference_size),
         GNUNET_JSON_spec_absolute_time ("timestamp",
                                         &timestamp),
-        GNUNET_JSON_spec_json ("sender_account_details",
-                               &wire_account),
+        GNUNET_JSON_spec_string ("sender_account_url",
+                                 &wire_url),
         GNUNET_JSON_spec_end()
       };
 
@@ -173,7 +173,7 @@ parse_reserve_history (struct TALER_EXCHANGE_Handle 
*exchange,
         GNUNET_break_op (0);
         return GNUNET_SYSERR;
       }
-      rhistory[off].details.in_details.sender_account_details = wire_account;
+      rhistory[off].details.in_details.sender_url = GNUNET_strdup (wire_url);
       rhistory[off].details.in_details.wire_reference = wire_reference;
       rhistory[off].details.in_details.wire_reference_size = 
wire_reference_size;
       rhistory[off].details.in_details.timestamp = timestamp;
@@ -361,8 +361,8 @@ parse_reserve_history (struct TALER_EXCHANGE_Handle 
*exchange,
       TALER_amount_hton (&rcc.closing_amount,
                         &amount);
       if (GNUNET_OK !=
-          TALER_JSON_hash 
(rhistory[off].details.close_details.receiver_account_details,
-                           &rcc.h_wire))
+          TALER_JSON_wire_signature_hash 
(rhistory[off].details.close_details.receiver_account_details,
+                                          &rcc.h_wire))
       {
         GNUNET_break (0);
         return GNUNET_SYSERR;
@@ -440,8 +440,7 @@ free_rhistory (struct TALER_EXCHANGE_ReserveHistory 
*rhistory,
     {
     case TALER_EXCHANGE_RTT_DEPOSIT:
       GNUNET_free_non_null (rhistory[i].details.in_details.wire_reference);
-      if (NULL != rhistory[i].details.in_details.sender_account_details)
-        json_decref (rhistory[i].details.in_details.sender_account_details);
+      GNUNET_free_non_null (rhistory[i].details.in_details.sender_url);
       break;
     case TALER_EXCHANGE_RTT_WITHDRAWAL:
       break;
diff --git a/src/exchange-lib/exchange_api_wire.c 
b/src/exchange-lib/exchange_api_wire.c
index f1056fd..6537e6c 100644
--- a/src/exchange-lib/exchange_api_wire.c
+++ b/src/exchange-lib/exchange_api_wire.c
@@ -1,6 +1,6 @@
 /*
   This file is part of TALER
-  Copyright (C) 2014, 2015, 2016 Inria and GNUnet e.V.
+  Copyright (C) 2014-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
@@ -27,6 +27,7 @@
 #include <gnunet/gnunet_curl_lib.h>
 #include "taler_exchange_service.h"
 #include "taler_json_lib.h"
+#include "taler_wire_lib.h"
 #include "taler_signatures.h"
 #include "taler_wire_plugin.h"
 #include "exchange_api_handle.h"
@@ -63,66 +64,135 @@ struct TALER_EXCHANGE_WireHandle
    */
   void *cb_cls;
 
+};
+
+
+/**
+ * List of wire fees by method.
+ */
+struct FeeMap
+{
   /**
-   * Set to the "methods" JSON array returned by the
-   * /wire request.
+   * Next entry in list.
    */
-  json_t *methods;
+  struct FeeMap *next;
 
   /**
-   * Current iteration offset in the @e methods array.
+   * Wire method this fee structure is for.
    */
-  unsigned int methods_off;
+  char *method;
 
+  /**
+   * Array of wire fees, also linked list, but allocated
+   * only once.
+   */
+  struct TALER_EXCHANGE_WireAggregateFees *fee_list;
 };
 
 
 /**
- * Verify that the signature on the "200 OK" response
- * for /wire/METHOD from the exchange is valid.
+ * Frees @a fm.
  *
- * @param wh wire handle with key material
- * @param method method to verify the reply for
- * @param json json reply with the signature
- * @return #GNUNET_SYSERR if @a json is invalid,
- *         #GNUNET_NO if the method is unknown,
- *         #GNUNET_OK if the json is valid
+ * @param fm memory to release
  */
-static int
-verify_wire_method_signature_ok (const struct TALER_EXCHANGE_WireHandle *wh,
-                                 const char *method,
-                                 const json_t *json)
+static void
+free_fees (struct FeeMap *fm)
 {
-  const struct TALER_EXCHANGE_Keys *key_state;
-  struct TALER_WIRE_Plugin *plugin;
-  char *lib_name;
-  char *emsg;
-  enum TALER_ErrorCode ec;
-
-  key_state = TALER_EXCHANGE_get_keys (wh->exchange);
-  (void) GNUNET_asprintf (&lib_name,
-                          "libtaler_plugin_wire_%s",
-                          method);
-  plugin = GNUNET_PLUGIN_load (lib_name,
-                               NULL);
-  if (NULL == plugin)
+  while (NULL != fm)
   {
-    GNUNET_free (lib_name);
-    GNUNET_log (GNUNET_ERROR_TYPE_INFO,
-                "Wire transfer method `%s' not supported\n",
-                method);
-    return GNUNET_NO;
+    struct FeeMap *fe = fm->next;
+
+    GNUNET_free (fm->fee_list);
+    GNUNET_free (fm->method);
+    GNUNET_free (fm);
+    fm = fe;
   }
-  plugin->library_name = lib_name;
-  ec = plugin->wire_validate (plugin->cls,
-                              json,
-                              &key_state->master_pub,
-                              &emsg);
-  GNUNET_free_non_null (emsg);
-  GNUNET_PLUGIN_unload (lib_name,
-                        plugin);
-  GNUNET_free (lib_name);
-  return (TALER_EC_NONE == ec) ? GNUNET_OK : GNUNET_SYSERR;
+}
+
+
+/**
+ * Parse wire @a fees and return map.
+ *
+ * @param fees json AggregateTransferFee to parse
+ * @return NULL on error
+ */
+static struct FeeMap *
+parse_fees (json_t *fees)
+{
+  struct FeeMap *fm = NULL;
+  const char *key;
+  json_t *fee_array;
+
+  json_object_foreach (fees, key, fee_array) {
+    struct FeeMap *fe = GNUNET_new (struct FeeMap);
+    int len;
+    unsigned int idx;
+    json_t *fee;
+
+    if (0 == (len = json_array_size (fee_array)))
+    {
+      GNUNET_break_op (0);
+      GNUNET_free (fe);
+      continue; /* skip */
+    }
+    fe->method = GNUNET_strdup (key);
+    fe->next = fm;
+    fe->fee_list = GNUNET_new_array (len,
+                                     struct TALER_EXCHANGE_WireAggregateFees);
+    fm = fe;
+    json_array_foreach (fee_array, idx, fee)
+    {
+      struct TALER_EXCHANGE_WireAggregateFees *wa = &fe->fee_list[idx];
+      struct GNUNET_JSON_Specification spec[] = {
+        GNUNET_JSON_spec_fixed_auto ("sig",
+                                     &wa->master_sig),
+        TALER_JSON_spec_amount ("wire_fee",
+                                &wa->wire_fee),
+        TALER_JSON_spec_amount ("closing_fee",
+                              &wa->closing_fee),
+        GNUNET_JSON_spec_absolute_time ("start_date",
+                                        &wa->start_date),
+        GNUNET_JSON_spec_absolute_time ("end_date",
+                                        &wa->end_date),
+        GNUNET_JSON_spec_end()
+      };
+
+      if (GNUNET_OK !=
+          GNUNET_JSON_parse (fee,
+                             spec,
+                             NULL,
+                             NULL))
+      {
+        GNUNET_break_op (0);
+        free_fees (fm);
+        return NULL;
+      }
+      if (idx + 1 < len)
+        wa->next = &fe->fee_list[idx + 1];
+      else
+        wa->next = NULL;
+    }
+  }
+  return fm;
+}
+
+
+/**
+ * Find fee by @a method.
+ *
+ * @param fm map to look in
+ * @param method key to look for
+ * @return NULL if fee is not specified in @a fm
+ */
+static const struct TALER_EXCHANGE_WireAggregateFees *
+lookup_fee (const struct FeeMap *fm,
+            const char *method)
+{
+  for (;NULL != fm; fm = fm->next)
+    if (0 == strcasecmp (fm->method,
+                         method))
+      return fm->fee_list;
+  return NULL;
 }
 
 
@@ -140,70 +210,131 @@ handle_wire_finished (void *cls,
                       const json_t *json)
 {
   struct TALER_EXCHANGE_WireHandle *wh = cls;
-  json_t *keep = NULL;
+  enum TALER_ErrorCode ec;
 
   wh->job = NULL;
+  ec = TALER_EC_NONE;
   switch (response_code)
   {
   case 0:
     break;
   case MHD_HTTP_OK:
     {
-      const struct TALER_EXCHANGE_Keys *keys;
-      const struct TALER_MasterPublicKeyP *master_pub;
-      const char *key;
-      json_t *method;
-      int ret;
-
-      /* We 'keep' methods that we support and that are well-formed;
-         we fail (by setting response_code=0) if any method that we do
-         support fails to verify. */
-      keep = json_object ();
-      json_object_foreach ((json_t *) json, key, method) {
-        ret = verify_wire_method_signature_ok (wh,
-                                               key,
-                                               method);
-        if (GNUNET_SYSERR == ret)
-        {
-          /* bogus reply */
-          GNUNET_break_op (0);
-          response_code = 0;
-        }
-        /* GNUNET_NO: not understood by us, simply skip! */
-        if (GNUNET_OK == ret)
-        {
-          /* supported and valid, keep! */
-          json_object_set (keep,
-                           key,
-                           method);
-        }
-      }
-      /* check fees */
-      keys = TALER_EXCHANGE_get_keys (wh->exchange);
-      if (NULL == keys)
-        master_pub = NULL;
-      else
-        master_pub = &keys->master_pub;
+      json_t *accounts;
+      json_t *fees;
+      int num_accounts;
+      struct FeeMap *fm;
+      const struct TALER_EXCHANGE_Keys *key_state;
+      struct GNUNET_JSON_Specification spec[] = {
+        GNUNET_JSON_spec_json ("accounts", &accounts),
+        GNUNET_JSON_spec_json ("fees", &fees),
+        GNUNET_JSON_spec_end()
+      };
+
       if (GNUNET_OK !=
-          TALER_EXCHANGE_wire_get_fees (master_pub,
-                                        keep,
-                                        NULL,
-                                        NULL))
+          GNUNET_JSON_parse (json,
+                             spec,
+                             NULL, NULL))
       {
         /* bogus reply */
         GNUNET_break_op (0);
         response_code = 0;
+        ec = TALER_EC_SERVER_JSON_INVALID;
+        break;
       }
-      if (0 != response_code)
+      if (0 == (num_accounts = json_array_size (accounts)))
       {
-        /* all supported methods were valid, use 'keep' for 'json' */
+        /* bogus reply */
+        GNUNET_break_op (0);
+        GNUNET_JSON_parse_free (spec);
+        response_code = 0;
+        ec = TALER_EC_SERVER_JSON_INVALID;
         break;
       }
-      /* some supported methods were invalid, release 'keep', preserve
-         full 'json' for application-level error handling. */
-      json_decref (keep);
-      keep = NULL;
-    }
+      if (NULL == (fm = parse_fees (fees)))
+      {
+        /* bogus reply */
+        GNUNET_break_op (0);
+        GNUNET_JSON_parse_free (spec);
+        response_code = 0;
+        ec = TALER_EC_SERVER_JSON_INVALID;
+        break;
+      }
+
+      key_state = TALER_EXCHANGE_get_keys (wh->exchange);
+      /* parse accounts */
+      {
+        struct TALER_EXCHANGE_WireAccount was[num_accounts];
+
+        for (unsigned int i=0;i<num_accounts;i++)
+        {
+          struct TALER_EXCHANGE_WireAccount *wa = &was[i];
+          json_t *account;
+          struct GNUNET_JSON_Specification spec_account[] = {
+            GNUNET_JSON_spec_string ("url", &wa->url),
+            GNUNET_JSON_spec_string ("salt", &wa->salt),
+            GNUNET_JSON_spec_fixed_auto ("master_sig", &wa->master_sig),
+            GNUNET_JSON_spec_end()
+          };
+          char *method;
+
+          account = json_array_get (accounts,
+                                    i);
+          if (GNUNET_OK !=
+              TALER_JSON_wire_signature_check (account,
+                                               &key_state->master_pub))
+          {
+            /* bogus reply */
+            GNUNET_break_op (0);
+            response_code = 0;
+            ec = TALER_EC_SERVER_SIGNATURE_INVALID;
+            break;
+          }
+          if (GNUNET_OK !=
+              GNUNET_JSON_parse (account,
+                                 spec_account,
+                                 NULL, NULL))
+          {
+            /* bogus reply */
+            GNUNET_break_op (0);
+            response_code = 0;
+            ec = TALER_EC_SERVER_JSON_INVALID;
+            break;
+          }
+          if (NULL == (method = TALER_WIRE_payto_get_method (wa->url)))
+          {
+            /* bogus reply */
+            GNUNET_break_op (0);
+            response_code = 0;
+            ec = TALER_EC_SERVER_JSON_INVALID;
+            break;
+          }
+          if (NULL == (wa->fees = lookup_fee (fm,
+                                              method)))
+          {
+            /* bogus reply */
+            GNUNET_break_op (0);
+            response_code = 0;
+            ec = TALER_EC_SERVER_JSON_INVALID;
+            GNUNET_free (method);
+            break;
+          }
+          GNUNET_free (method);
+        } /* end 'for all accounts */
+        if ( (0 != response_code) &&
+             (NULL != wh->cb) )
+        {
+          wh->cb (wh->cb_cls,
+                  response_code,
+                  TALER_EC_NONE,
+                  num_accounts,
+                  was);
+          wh->cb = NULL;
+        }
+      } /* end of 'parse accounts */
+      free_fees (fm);
+      GNUNET_JSON_parse_free (spec);
+    } /* end of MHD_HTTP_OK */
     break;
   case MHD_HTTP_BAD_REQUEST:
     /* This should never happen, either us or the exchange is buggy
@@ -226,12 +357,12 @@ handle_wire_finished (void *cls,
     response_code = 0;
     break;
   }
-  wh->cb (wh->cb_cls,
-          response_code,
-         TALER_JSON_get_error_code (json),
-          (NULL != keep) ? keep : json);
-  if (NULL != keep)
-    json_decref (keep);
+  if (NULL != wh->cb)
+    wh->cb (wh->cb_cls,
+            response_code,
+            (0 == response_code) ? ec : TALER_JSON_get_error_code (json),
+            0,
+            NULL);
   TALER_EXCHANGE_wire_cancel (wh);
 }
 
@@ -306,157 +437,9 @@ TALER_EXCHANGE_wire_cancel (struct 
TALER_EXCHANGE_WireHandle *wh)
     GNUNET_CURL_job_cancel (wh->job);
     wh->job = NULL;
   }
-  if (NULL != wh->methods)
-  {
-    json_decref (wh->methods);
-    wh->methods = NULL;
-  }
   GNUNET_free (wh->url);
   GNUNET_free (wh);
 }
 
 
-/**
- * Parse wire @a fee and store the result in @a af.
- *
- * @param[out] af where to write the result
- * @param fee json AggregateTransferFee to parse
- * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
- */
-static int
-parse_json_fees (struct TALER_EXCHANGE_WireAggregateFees *af,
-                 json_t *fee)
-{
-  struct GNUNET_JSON_Specification spec[] = {
-    GNUNET_JSON_spec_fixed_auto ("sig",
-                                 &af->master_sig),
-    TALER_JSON_spec_amount ("wire_fee",
-                            &af->wire_fee),
-    TALER_JSON_spec_amount ("closing_fee",
-                            &af->closing_fee),
-    GNUNET_JSON_spec_absolute_time ("start_date",
-                                    &af->start_date),
-    GNUNET_JSON_spec_absolute_time ("end_date",
-                                    &af->end_date),
-    GNUNET_JSON_spec_end()
-  };
-
-  if (GNUNET_OK !=
-      GNUNET_JSON_parse (fee,
-                         spec,
-                         NULL,
-                         NULL))
-  {
-    GNUNET_break_op (0);
-    return GNUNET_SYSERR;
-  }
-  return GNUNET_OK;
-}
-
-
-/**
- * Check the #TALER_SIGNATURE_MASTER_WIRE_FEES signature.
- *
- * @param af record to check
- * @param wire_method wire method to check against
- * @param master_pub expected signing key
- * @return #GNUNET_OK on success, #GNUNET_SYSERR on failure
- */
-static int
-check_sig (const struct TALER_EXCHANGE_WireAggregateFees *af,
-           const char *wire_method,
-           const struct TALER_MasterPublicKeyP *master_pub)
-{
-  struct TALER_MasterWireFeePS wp;
-
-  wp.purpose.purpose = htonl (TALER_SIGNATURE_MASTER_WIRE_FEES);
-  wp.purpose.size = htonl (sizeof (wp));
-  GNUNET_CRYPTO_hash (wire_method,
-                      strlen (wire_method) + 1,
-                      &wp.h_wire_method);
-  wp.start_date = GNUNET_TIME_absolute_hton (af->start_date);
-  wp.end_date = GNUNET_TIME_absolute_hton (af->end_date);
-  TALER_amount_hton (&wp.wire_fee,
-                     &af->wire_fee);
-  TALER_amount_hton (&wp.closing_fee,
-                     &af->closing_fee);
-  return GNUNET_CRYPTO_eddsa_verify (TALER_SIGNATURE_MASTER_WIRE_FEES,
-                                     &wp.purpose,
-                                     &af->master_sig.eddsa_signature,
-                                     &master_pub->eddsa_pub);
-}
-
-
-/**
- * Obtain information about wire fees encoded in @a obj
- * by wire method.
- *
- * @param master_pub public key to use to verify signatures, NULL to not verify
- * @param obj wire information as encoded in the 
#TALER_EXCHANGE_WireResultCallback
- * @param cb callback to invoke for the fees
- * @param cb_cls closure for @a cb
- * @return #GNUNET_OK in success, #GNUNET_SYSERR if @a obj is ill-formed
- */
-int
-TALER_EXCHANGE_wire_get_fees (const struct TALER_MasterPublicKeyP *master_pub,
-                              const json_t *obj,
-                              TALER_EXCHANGE_WireFeeCallback cb,
-                              void *cb_cls)
-{
-  const char *wire_method;
-  json_t *value;
-
-  json_object_foreach (((json_t *) obj), wire_method, value)
-  {
-    json_t *fees;
-    size_t num_fees;
-
-    fees = json_object_get (value, "fees");
-    if ( (NULL == fees) ||
-         (! json_is_array (fees)) )
-    {
-      GNUNET_break_op (0);
-      return GNUNET_SYSERR;
-    }
-    num_fees = json_array_size (fees);
-    if (num_fees > 1024)
-    {
-      GNUNET_break_op (0);
-      return GNUNET_SYSERR;
-    }
-    {
-      struct TALER_EXCHANGE_WireAggregateFees af[num_fees + 1];
-
-      for (size_t i=0;i<num_fees;i++)
-      {
-        af[i].next = &af[i+1];
-        if (GNUNET_OK !=
-            parse_json_fees (&af[i],
-                             json_array_get (fees,
-                                             i)))
-        {
-          GNUNET_break_op (0);
-          return GNUNET_SYSERR;
-        }
-        if ( (NULL != master_pub) &&
-             (GNUNET_OK !=
-              check_sig (&af[i],
-                         wire_method,
-                         master_pub)) )
-        {
-          GNUNET_break_op (0);
-          return GNUNET_SYSERR;
-        }
-      }
-      af[num_fees - 1].next = NULL;
-      if (NULL != cb)
-        cb (cb_cls,
-            wire_method,
-            &af[0]);
-    }
-  }
-  return GNUNET_OK;
-}
-
-
 /* end of exchange_api_wire.c */
diff --git a/src/exchange-lib/test_exchange_api.c 
b/src/exchange-lib/test_exchange_api.c
index fe38777..7ca74a2 100644
--- a/src/exchange-lib/test_exchange_api.c
+++ b/src/exchange-lib/test_exchange_api.c
@@ -36,9 +36,12 @@
 #define WIRE_TEST 1
 
 /**
- * Is the configuration file is set to include wire format 'sepa'?
+ * Is the configuration file is set to include wire format 'ebics'?
+ * Requires that EBICS /history function is implemented, which it
+ * is currently not.  Once it is, set ENABLE_CREDIT to YES in the
+ * configuration and then set this option to 1.
  */
-#define WIRE_SEPA 1
+#define WIRE_EBICS 0
 
 /**
  * Account number of the exchange at the bank.
@@ -1539,12 +1542,15 @@ find_pk (const struct TALER_EXCHANGE_Keys *keys,
 }
 
 
+#if LEGACY
+/* Tests the *old* /wire API, the _modern_ testcase was adapted,
+   but little point in right now adapting the old testcase */
 /**
  * Function called with information about the wire fees
  * for each wire method.
  *
  * @param cls closure
- * @param wire_method name of the wire method (i.e. "sepa")
+ * @param wire_method name of the wire method (i.e. "ebics")
  * @param fees fee structure for this method
  */
 static void
@@ -1556,9 +1562,9 @@ check_fee_cb (void *cls,
   struct Command *cmd = &is->commands[is->ip];
   struct TALER_Amount expected_amount;
 
-  GNUNET_break ( (0 == strcasecmp ("test",
+  GNUNET_break ( (0 == strcasecmp ("x-taler-bank",
                                    wire_method)) ||
-                 (0 == strcasecmp ("sepa",
+                 (0 == strcasecmp ("ebics",
                                    wire_method)) );
   if (GNUNET_OK !=
       TALER_string_to_amount (cmd->details.wire.expected_fee,
@@ -1582,6 +1588,7 @@ check_fee_cb (void *cls,
     fees = fees->next;
   }
 }
+#endif
 
 
 /**
@@ -1592,14 +1599,15 @@ check_fee_cb (void *cls,
  * @param http_status HTTP response code, #MHD_HTTP_OK (200) for successful 
request;
  *                    0 if the exchange's reply is bogus (fails to follow the 
protocol)
  * @param ec taler-specific error code, #TALER_EC_NONE on success
- * @param obj the received JSON reply, if successful this should be the wire
- *            format details as provided by /wire.
+ * @param accounts_len length of the @a accounts array
+ * @param accounts list of wire accounts of the exchange, NULL on error
  */
 static void
 wire_cb (void *cls,
          unsigned int http_status,
         enum TALER_ErrorCode ec,
-         const json_t *obj)
+         unsigned int accounts_len,
+         const struct TALER_EXCHANGE_WireAccount *accounts)
 {
   struct InterpreterState *is = cls;
   struct Command *cmd = &is->commands[is->ip];
@@ -1611,7 +1619,9 @@ wire_cb (void *cls,
                 "Unexpected response code %u to command %s\n",
                 http_status,
                 cmd->label);
+#if LEGACY
     json_dumpf (obj, stderr, 0);
+#endif
     fail (is);
     return;
   }
@@ -1619,6 +1629,7 @@ wire_cb (void *cls,
   {
   case MHD_HTTP_OK:
     {
+#if LEGACY
       json_t *method;
 
       method = json_object_get (obj,
@@ -1646,6 +1657,7 @@ wire_cb (void *cls,
         fail (is);
         return;
       }
+#endif
     }
     break;
   default:
@@ -1760,8 +1772,8 @@ wire_deposits_cb (void *cls,
                            JSON_REJECT_DUPLICATES,
                            NULL);
         GNUNET_assert (GNUNET_OK ==
-                       TALER_JSON_hash (wire,
-                                        &hw));
+                       TALER_JSON_wire_signature_hash (wire,
+                                                       &hw));
         json_decref (wire);
         if (0 != memcmp (&hw,
                          h_wire,
@@ -2331,13 +2343,15 @@ interpreter_run (void *cls)
       {
         struct TALER_DepositRequestPS dr;
 
-        memset (&dr, 0, sizeof (dr));
+        memset (&dr,
+                0,
+                sizeof (dr));
         dr.purpose.size = htonl (sizeof (struct TALER_DepositRequestPS));
         dr.purpose.purpose = htonl (TALER_SIGNATURE_WALLET_COIN_DEPOSIT);
         dr.h_contract_terms = h_contract_terms;
         GNUNET_assert (GNUNET_OK ==
-                       TALER_JSON_hash (wire,
-                                        &dr.h_wire));
+                       TALER_JSON_wire_signature_hash (wire,
+                                                       &dr.h_wire));
         dr.timestamp = GNUNET_TIME_absolute_hton (timestamp);
         dr.refund_deadline = GNUNET_TIME_absolute_hton (refund_deadline);
         TALER_amount_hton (&dr.amount_with_fee,
@@ -2581,8 +2595,8 @@ interpreter_run (void *cls)
                          NULL);
       GNUNET_assert (NULL != wire);
       GNUNET_assert (GNUNET_OK ==
-                     TALER_JSON_hash (wire,
-                                      &h_wire));
+                     TALER_JSON_wire_signature_hash (wire,
+                                                     &h_wire));
       json_decref (wire);
       contract_terms = json_loads (ref->details.deposit.contract_terms,
                              JSON_REJECT_DUPLICATES,
@@ -2640,7 +2654,6 @@ interpreter_run (void *cls)
                                    "taler-exchange-wirewatch",
                                    "taler-exchange-wirewatch",
                                    "-c", "test_exchange_api.conf",
-                                   "-t", "test", /* use Taler's bank/fakebank 
*/
                                    "-T", /* exit when done */
                                    NULL);
       if (NULL == cmd->details.run_wirewatch.wirewatch_proc)
@@ -3204,15 +3217,15 @@ run (void *cls)
       .label = "wire-test",
       /* expecting 'test' method in response */
       .expected_response_code = MHD_HTTP_OK,
-      .details.wire.format = "test",
+      .details.wire.format = "x-taler-bank",
       .details.wire.expected_fee = "EUR:0.01" },
 #endif
-#if WIRE_SEPA
+#if WIRE_EBICS
     { .oc = OC_WIRE,
       .label = "wire-sepa",
-      /* expecting 'sepa' method in response */
+      /* expecting 'ebics' method in response */
       .expected_response_code = MHD_HTTP_OK,
-      .details.wire.format = "sepa",
+      .details.wire.format = "ebics",
       .details.wire.expected_fee = "EUR:0.01" },
 #endif
     /* *************** end of /wire testing ************** */
@@ -3252,7 +3265,7 @@ run (void *cls)
       .expected_response_code = MHD_HTTP_OK,
       .details.deposit.amount = "EUR:5",
       .details.deposit.coin_ref = "withdraw-coin-1",
-      .details.deposit.wire_details = "{ \"type\":\"test\", 
\"bank_url\":\"http://localhost:8082/\";, \"account_number\":42  }",
+      .details.deposit.wire_details = "{ 
\"url\":\"payto://x-taler-bank/localhost:8082/42\", \"salt\":\"my salt\"  }",
       .details.deposit.contract_terms = "{ \"items\": [ { \"name\":\"ice 
cream\", \"value\":1 } ] }" },
 
     /* Try to overdraw funds ... */
@@ -3268,7 +3281,7 @@ run (void *cls)
       .expected_response_code = MHD_HTTP_FORBIDDEN,
       .details.deposit.amount = "EUR:5",
       .details.deposit.coin_ref = "withdraw-coin-1",
-      .details.deposit.wire_details = "{ \"type\":\"test\", 
\"bank_url\":\"http://localhost:8082/\";, \"account_number\":43  }",
+      .details.deposit.wire_details = "{ 
\"url\":\"payto://x-taler-bank/localhost:8082/43\", \"salt\":\"my salt\"  }",
       .details.deposit.contract_terms = "{ \"items\": [ { \"name\":\"ice 
cream\", \"value\":1 } ] }" },
     /* Try to double-spend the 5 EUR coin at the same merchant (but different
        transaction ID) */
@@ -3277,7 +3290,7 @@ run (void *cls)
       .expected_response_code = MHD_HTTP_FORBIDDEN,
       .details.deposit.amount = "EUR:5",
       .details.deposit.coin_ref = "withdraw-coin-1",
-      .details.deposit.wire_details = "{ \"type\":\"test\", 
\"bank_url\":\"http://localhost:8082/\";, \"account_number\":42  }",
+      .details.deposit.wire_details = "{ 
\"url\":\"payto://x-taler-bank/localhost:8082/42\", \"salt\":\"my salt\"  }",
       .details.deposit.contract_terms = "{ \"items\": [ { \"name\":\"ice 
cream\", \"value\":1 } ] }" },
     /* Try to double-spend the 5 EUR coin at the same merchant (but different
        proposal) */
@@ -3286,7 +3299,7 @@ run (void *cls)
       .expected_response_code = MHD_HTTP_FORBIDDEN,
       .details.deposit.amount = "EUR:5",
       .details.deposit.coin_ref = "withdraw-coin-1",
-      .details.deposit.wire_details = "{ \"type\":\"test\", 
\"bank_url\":\"http://localhost:8082/\";, \"account_number\":42  }",
+      .details.deposit.wire_details = "{ 
\"url\":\"payto://x-taler-bank/localhost:8082/42\", \"salt\":\"my salt\"  }",
       .details.deposit.contract_terms = "{ \"items\":[{ \"name\":\"ice 
cream\", \"value\":2 } ] }" },
 
     /* ***************** /refresh testing ******************** */
@@ -3316,7 +3329,7 @@ run (void *cls)
       .expected_response_code = MHD_HTTP_OK,
       .details.deposit.amount = "EUR:1",
       .details.deposit.coin_ref = "refresh-withdraw-coin-1",
-      .details.deposit.wire_details = "{ \"type\":\"test\", 
\"bank_url\":\"http://localhost:8082/\";, \"account_number\":42  }",
+      .details.deposit.wire_details = "{ 
\"url\":\"payto://x-taler-bank/localhost:8082/42\", \"salt\":\"my salt\"  }",
       .details.deposit.contract_terms = "{ \"items\" : [ { \"name\":\"ice 
cream\", \"value\":\"EUR:1\" } ] }" },
 
     /* Melt the rest of the coin's value (EUR:4.00 = 3x EUR:1.03 + 7x 
EUR:0.13) */
@@ -3357,7 +3370,7 @@ run (void *cls)
       .details.deposit.amount = "EUR:1",
       .details.deposit.coin_ref = "refresh-reveal-1-idempotency",
       .details.deposit.coin_idx = 0,
-      .details.deposit.wire_details = "{ \"type\":\"test\", 
\"bank_url\":\"http://localhost:8082/\";, \"account_number\":42  }",
+      .details.deposit.wire_details = "{ 
\"url\":\"payto://x-taler-bank/localhost:8082/42\", \"salt\":\"my salt\"  }",
       .details.deposit.contract_terms = "{ \"items\": [ { \"name\":\"ice 
cream\", \"value\":3 } ] }" },
 
     /* Test successfully spending coins from the refresh operation:
@@ -3368,7 +3381,7 @@ run (void *cls)
       .details.deposit.amount = "EUR:0.1",
       .details.deposit.coin_ref = "refresh-reveal-1",
       .details.deposit.coin_idx = 4,
-      .details.deposit.wire_details = "{ \"type\":\"test\", 
\"bank_url\":\"http://localhost:8082/\";, \"account_number\":43  }",
+      .details.deposit.wire_details = "{ 
\"url\":\"payto://x-taler-bank/localhost:8082/43\", \"salt\":\"my salt\"  }",
       .details.deposit.contract_terms = "{ \"items\": [ { \"name\":\"ice 
cream\", \"value\":3 } ] }" },
 
     /* Test running a failing melt operation (same operation again must fail) 
*/
@@ -3507,7 +3520,7 @@ run (void *cls)
       .expected_response_code = MHD_HTTP_OK,
       .details.deposit.amount = "EUR:5",
       .details.deposit.coin_ref = "withdraw-coin-r1",
-      .details.deposit.wire_details = "{ \"type\":\"test\", 
\"bank_url\":\"http://localhost:8082/\";, \"account_number\":42  }",
+      .details.deposit.wire_details = "{ 
\"url\":\"payto://x-taler-bank/localhost:8082/42\", \"salt\":\"my salt\"  }",
       .details.deposit.contract_terms = "{ \"items\" : [ { \"name\":\"ice 
cream\", \"value\":\"EUR:5\" } ] }",
       .details.deposit.refund_deadline = { 60LL * 1000 * 1000 } /* 60 s */,
     },
@@ -3539,7 +3552,7 @@ run (void *cls)
       .expected_response_code = MHD_HTTP_OK,
       .details.deposit.amount = "EUR:4.99",
       .details.deposit.coin_ref = "withdraw-coin-r1",
-      .details.deposit.wire_details = "{ \"type\":\"test\", 
\"bank_url\":\"http://localhost:8082/\";, \"account_number\":42  }",
+      .details.deposit.wire_details = "{ 
\"url\":\"payto://x-taler-bank/localhost:8082/42\", \"salt\":\"my salt\"  }",
       .details.deposit.contract_terms = "{ \"items\" : [ { \"name\":\"more ice 
cream\", \"value\":\"EUR:5\" } ] }",
     },
     /* Run transfers. This will do the transfer as refund deadline was 0 */
@@ -3591,9 +3604,9 @@ run (void *cls)
       .expected_response_code = MHD_HTTP_OK,
       .details.deposit.amount = "EUR:5",
       .details.deposit.coin_ref = "withdraw-coin-rb",
-      .details.deposit.wire_details = "{ \"type\":\"test\", 
\"bank_url\":\"http://localhost:8082/\";, \"account_number\":42  }",
       .details.deposit.contract_terms = "{ \"items\" : [ { \"name\":\"ice 
cream\", \"value\":\"EUR:5\" } ] }",
       .details.deposit.refund_deadline = { 0 },
+      .details.deposit.wire_details = "{ 
\"url\":\"payto://x-taler-bank/localhost:8082/42\", \"salt\":\"my salt\"  }"
     },
     { .oc = OC_CHECK_BANK_TRANSFER,
       .label = "check_bank_transfer-aai-3b",
@@ -3695,7 +3708,7 @@ run (void *cls)
       .expected_response_code = MHD_HTTP_OK,
       .details.deposit.amount = "EUR:0.5",
       .details.deposit.coin_ref = "payback-withdraw-coin-2a",
-      .details.deposit.wire_details = "{ \"type\":\"test\", 
\"bank_url\":\"http://localhost:8082/\";, \"account_number\":42  }",
+      .details.deposit.wire_details = "{ 
\"url\":\"payto://x-taler-bank/localhost:8082/42\", \"salt\":\"my salt\"    }",
       .details.deposit.contract_terms = "{ \"items\": [ { \"name\":\"more ice 
cream\", \"value\":1 } ] }" },
     { .oc = OC_REVOKE,
       .label = "revoke-2",
@@ -3716,7 +3729,7 @@ run (void *cls)
       .expected_response_code = MHD_HTTP_NOT_FOUND,
       .details.deposit.amount = "EUR:1",
       .details.deposit.coin_ref = "payback-withdraw-coin-2b",
-      .details.deposit.wire_details = "{ \"type\":\"test\", 
\"bank_url\":\"http://localhost:8082/\";, \"account_number\":42  }",
+      .details.deposit.wire_details = "{ 
\"url\":\"payto://x-taler-bank/localhost:8082/42\",   \"salt\":\"my salt\"  }",
       .details.deposit.contract_terms = "{ \"items\": [ { \"name\":\"more ice 
cream\", \"value\":1 } ] }" },
 
     /* Test deposit fails after payback, with proof in payback */
@@ -3727,7 +3740,7 @@ run (void *cls)
       .expected_response_code = MHD_HTTP_NOT_FOUND,
       .details.deposit.amount = "EUR:0.5",
       .details.deposit.coin_ref = "payback-withdraw-coin-2a",
-      .details.deposit.wire_details = "{ \"type\":\"test\", 
\"bank_url\":\"http://localhost:8082/\";, \"account_number\":42  }",
+      .details.deposit.wire_details = "{ 
\"url\":\"payto://x-taler-bank/localhost:8082/42\", \"salt\":\"my salt\"  }",
       .details.deposit.contract_terms = "{ \"items\": [ { \"name\":\"extra ice 
cream\", \"value\":1 } ] }" },
 
 
@@ -3999,6 +4012,7 @@ main (int argc,
     }
   while (0 != system ("wget -q -t 1 -T 1 http://127.0.0.1:8081/keys -o 
/dev/null -O /dev/null"));
   fprintf (stderr, "\n");
+
   result = GNUNET_NO;
   sigpipe = GNUNET_DISK_pipe (GNUNET_NO, GNUNET_NO, GNUNET_NO, GNUNET_NO);
   GNUNET_assert (NULL != sigpipe);
diff --git a/src/exchange-lib/test_exchange_api.conf 
b/src/exchange-lib/test_exchange_api.conf
index 7d8761f..8c8bd7e 100644
--- a/src/exchange-lib/test_exchange_api.conf
+++ b/src/exchange-lib/test_exchange_api.conf
@@ -9,7 +9,6 @@ TALER_TEST_HOME = test_exchange_api_home/
 CURRENCY = EUR
 
 [exchange]
-
 # HTTP port the exchange listens to
 PORT = 8081
 
@@ -23,23 +22,58 @@ DB = postgres
 # exchange (or the twister) is actually listening.
 BASE_URL = "http://localhost:8081/";
 
+# Keep it short so the test runs fast.
+LOOKAHEAD_SIGN = 12 h
+
 [exchangedb-postgres]
-DB_CONN_STR = "postgres:///talercheck"
+CONFIG = "postgres:///talercheck"
 
 [auditordb-postgres]
-DB_CONN_STR = "postgres:///talercheck"
+CONFIG = "postgres:///talercheck"
+
+# Sections starting with "account-" configure the bank accounts
+# of the exchange.  The "URL" specifies the account in
+# payto://-format, while the WIRE_JSON specifies the
+# (possibly offline) signed version to be returned in /wire.
+# WIRE_JSON is optional, as not all accounts must be
+# advertised in /wire.
+[account-1]
+# What is the URL of our account?
+URL = "payto://sepa/CH9300762011623852957"
+# This is the response we give out for the /wire request.  It provides
+# wallets with the bank information for transfers to the exchange.
+WIRE_RESPONSE = ${TALER_CONFIG_HOME}/account-1.json
+# Which wire plugin should we used to access the account?
+PLUGIN = ebics
 
-[exchange-wire-sepa]
-# Enable 'sepa' to test SEPA-specific routines.
-ENABLE = YES
+# ENABLE_CREDIT = YES
+
+[account-2]
+# What is the bank account (with the "Taler Bank" demo system)?
+URL = "payto://x-taler-bank/localhost:8082/2"
 
 # This is the response we give out for the /wire request.  It provides
 # wallets with the bank information for transfers to the exchange.
-SEPA_RESPONSE_FILE = ${TALER_CONFIG_HOME}/sepa.json
+WIRE_RESPONSE = ${TALER_CONFIG_HOME}/account-2.json
+
+# Which wire plugin should we used to access the account?
+PLUGIN = taler_bank
+
+# Authentication information for basic authentication
+TALER_BANK_AUTH_METHOD = "basic"
+USERNAME = user
+PASSWORD = pass
+
+ENABLE_DEBIT = YES
+
+ENABLE_CREDIT = YES
 
+
+# Sections starting with "fee-" configure the wire fee for the
+# respective wire method.
+[fees-sepa]
 # Fees for the forseeable future...
 # If you see this after 2017, update to match the next 10 years...
-WIRE-FEE-2017 = EUR:0.01
 WIRE-FEE-2018 = EUR:0.01
 WIRE-FEE-2019 = EUR:0.01
 WIRE-FEE-2020 = EUR:0.01
@@ -49,8 +83,8 @@ WIRE-FEE-2023 = EUR:0.01
 WIRE-FEE-2024 = EUR:0.01
 WIRE-FEE-2025 = EUR:0.01
 WIRE-FEE-2026 = EUR:0.01
+WIRE-FEE-2027 = EUR:0.01
 
-CLOSING-FEE-2017 = EUR:0.01
 CLOSING-FEE-2018 = EUR:0.01
 CLOSING-FEE-2019 = EUR:0.01
 CLOSING-FEE-2020 = EUR:0.01
@@ -60,18 +94,11 @@ CLOSING-FEE-2023 = EUR:0.01
 CLOSING-FEE-2024 = EUR:0.01
 CLOSING-FEE-2025 = EUR:0.01
 CLOSING-FEE-2026 = EUR:0.01
+CLOSING-FEE-2027 = EUR:0.01
 
-[exchange_keys]
-# Keep it short so the test runs fast.
-LOOKAHEAD_SIGN = 12 h
-
-[exchange-wire-test]
-# Enable 'test' for testing of the actual coin operations.
-ENABLE = YES
-
+[fees-x-taler-bank]
 # Fees for the forseeable future...
 # If you see this after 2017, update to match the next 10 years...
-WIRE-FEE-2017 = EUR:0.01
 WIRE-FEE-2018 = EUR:0.01
 WIRE-FEE-2019 = EUR:0.01
 WIRE-FEE-2020 = EUR:0.01
@@ -81,8 +108,8 @@ WIRE-FEE-2023 = EUR:0.01
 WIRE-FEE-2024 = EUR:0.01
 WIRE-FEE-2025 = EUR:0.01
 WIRE-FEE-2026 = EUR:0.01
+WIRE-FEE-2027 = EUR:0.01
 
-CLOSING-FEE-2017 = EUR:0.01
 CLOSING-FEE-2018 = EUR:0.01
 CLOSING-FEE-2019 = EUR:0.01
 CLOSING-FEE-2020 = EUR:0.01
@@ -92,17 +119,10 @@ CLOSING-FEE-2023 = EUR:0.01
 CLOSING-FEE-2024 = EUR:0.01
 CLOSING-FEE-2025 = EUR:0.01
 CLOSING-FEE-2026 = EUR:0.01
+CLOSING-FEE-2027 = EUR:0.01
 
-# This is the response we give out for the /wire request.  It provides
-# wallets with the bank information for transfers to the exchange.
-TEST_RESPONSE_FILE = ${TALER_CONFIG_HOME}/test.json
-
-# What is the main website of the bank?
-BANK_URL = "http://localhost:8082/";
-# From which account at the 'bank' should outgoing wire transfers be made?
-BANK_ACCOUNT_NUMBER = 2
-
-
+# Sections starting with "coin_" specify which denominations
+# the exchange should support (and their respective fee structure)
 [coin_eur_ct_1]
 value = EUR:0.01
 duration_overlap = 5 minutes
diff --git 
a/src/exchange-lib/test_exchange_api_home/.config/taler/account-1.json 
b/src/exchange-lib/test_exchange_api_home/.config/taler/account-1.json
new file mode 100644
index 0000000..48093f2
--- /dev/null
+++ b/src/exchange-lib/test_exchange_api_home/.config/taler/account-1.json
@@ -0,0 +1,5 @@
+{
+  "url": "payto://sepa/CH9300762011623852957",
+  "salt": 
"N83T9J9202WCC8TQFDMJDWEGZNBEKA33C1ZM241VNYH88RZNTHPW509Y1M2YF7Y098R8VRESWQ05H03BK1SPAZCWE54KARDCKT5N8AG",
+  "master_sig": 
"D4V5GJ998YK7D6N0N56AD0J6MZNFEW6MRZT2CFPVQ5ME3NMQ59AA2007CXYESSFGRN70CNCFM06858QSSENCWTZM8VHEJ93YQ20ZJ1R"
+}
\ No newline at end of file
diff --git 
a/src/exchange-lib/test_exchange_api_home/.config/taler/account-2.json 
b/src/exchange-lib/test_exchange_api_home/.config/taler/account-2.json
new file mode 100644
index 0000000..85d80de
--- /dev/null
+++ b/src/exchange-lib/test_exchange_api_home/.config/taler/account-2.json
@@ -0,0 +1,5 @@
+{
+  "url": "payto://x-taler-bank/localhost:8082/2",
+  "salt": 
"TMXB995ZZVKA02AG4074X3C6XX0BFTHY8XK76EF4BSG5XVDF069FEBN4TCKW9GS7NKZH409GKAVHMQPA3T361MC6VM7J268V3GBH42R",
+  "master_sig": 
"CK7BGHKYVAT7DMVCN00DQ0761NCTJVESZT69049BCF3SKNJKVHXXEQ5X6FH2HFGHCJ18YA1MGHBD8RRG4W3G4KJWQJDY2CGPGTHDJ2G"
+}
\ No newline at end of file
diff --git 
a/src/exchange-lib/test_exchange_api_home/.config/taler/x-taler-bank.json 
b/src/exchange-lib/test_exchange_api_home/.config/taler/x-taler-bank.json
new file mode 100644
index 0000000..9445f04
--- /dev/null
+++ b/src/exchange-lib/test_exchange_api_home/.config/taler/x-taler-bank.json
@@ -0,0 +1,5 @@
+{
+  "url": "payto://x-taler-bank/http://localhost:8082/2";,
+  "salt": 
"WGRD0W7YKD8ZAN960B0JBRARRY0K5FQ4920Q3DJBTYH4GY7W0XNAX1F04R5B1E0RWH1NFG08TM8K1517WNCXTJM9KMH4913Q5XPK0N8",
+  "master_sig": 
"J4N0KP64MGNEQX9HST9TDWK67152MSHHM9CTZH8GSMKD607BXSAF209AQYDKYT6QJP0NQXYXC1JMM9Z405DJHGV75JFMWP4G6WB6A00"
+}
\ No newline at end of file
diff --git a/src/exchange-lib/test_exchange_api_keys_cherry_picking.conf 
b/src/exchange-lib/test_exchange_api_keys_cherry_picking.conf
index 38b9528..7193bf1 100644
--- a/src/exchange-lib/test_exchange_api_keys_cherry_picking.conf
+++ b/src/exchange-lib/test_exchange_api_keys_cherry_picking.conf
@@ -23,20 +23,53 @@ DB = postgres
 # exchange (or the twister) is actually listening.
 BASE_URL = "http://localhost:8081/";
 
+# Keep it short so we can prolong later!
+LOOKAHEAD_SIGN = 60 s
+
+
 [exchangedb-postgres]
-DB_CONN_STR = "postgres:///talercheck"
+CONFIG = "postgres:///talercheck"
 
 [auditordb-postgres]
-DB_CONN_STR = "postgres:///talercheck"
+CONFIG = "postgres:///talercheck"
+
+
+[account-1]
+# This is the response we give out for the /wire request.  It provides
+# wallets with the bank information for transfers to the exchange.
+WIRE_RESPONSE = ${TALER_CONFIG_HOME}/iban.json
+
+# What is the URL of our bank account? Must match WIRE_RESPONSE above!
+URL = payto://sepa/FIXME
 
-[exchange-wire-sepa]
-# Enable 'sepa' to test SEPA-specific routines.
-ENABLE = YES
+# Which plugin implements access for this account?
+PLUGIN = "ebics"
 
+
+[account-2]
 # This is the response we give out for the /wire request.  It provides
 # wallets with the bank information for transfers to the exchange.
-SEPA_RESPONSE_FILE = ${TALER_CONFIG_HOME}/sepa.json
+WIRE_RESPONSE = ${TALER_CONFIG_HOME}/x-taler-bank.json
+
+# What is the URL of our bank account? Must match WIRE_RESPONSE above!
+URL = payto://x-taler-bank/http://localhost:8082/2
+
+# Which plugin implements access for this account?
+PLUGIN = "taler_bank"
+
+# Authentication information for basic authentication
+TALER_BANK_AUTH_METHOD = "basic"
+USERNAME = user
+PASSWORD = pass
+
+ENABLE_DEBIT = YES
 
+ENABLE_CREDIT = YES
+
+
+
+
+[fees-x-taler-bank]
 # Fees for the forseeable future...
 # If you see this after 2017, update to match the next 10 years...
 WIRE-FEE-2017 = EUR:0.01
@@ -61,14 +94,7 @@ CLOSING-FEE-2024 = EUR:0.01
 CLOSING-FEE-2025 = EUR:0.01
 CLOSING-FEE-2026 = EUR:0.01
 
-[exchange_keys]
-# Keep it short so we can prolong later!
-LOOKAHEAD_SIGN = 60 s
-
-[exchange-wire-test]
-# Enable 'test' for testing of the actual coin operations.
-ENABLE = YES
-
+[fees-sepa]
 # Fees for the forseeable future...
 # If you see this after 2017, update to match the next 10 years...
 WIRE-FEE-2017 = EUR:0.01
@@ -93,16 +119,6 @@ CLOSING-FEE-2024 = EUR:0.01
 CLOSING-FEE-2025 = EUR:0.01
 CLOSING-FEE-2026 = EUR:0.01
 
-# This is the response we give out for the /wire request.  It provides
-# wallets with the bank information for transfers to the exchange.
-TEST_RESPONSE_FILE = ${TALER_CONFIG_HOME}/test.json
-
-# What is the main website of the bank?
-BANK_URL = "http://localhost:8082/";
-# From which account at the 'bank' should outgoing wire transfers be made?
-BANK_ACCOUNT_NUMBER = 2
-
-
 [coin_eur_ct_1]
 value = EUR:0.01
 duration_overlap = 5 s
diff --git 
a/src/exchange-lib/test_exchange_api_keys_cherry_picking_extended.conf 
b/src/exchange-lib/test_exchange_api_keys_cherry_picking_extended.conf
index 3becf3d..29290c9 100644
--- a/src/exchange-lib/test_exchange_api_keys_cherry_picking_extended.conf
+++ b/src/exchange-lib/test_exchange_api_keys_cherry_picking_extended.conf
@@ -1,5 +1,5 @@
 @INLINE@ test_exchange_api_keys_cherry_picking.conf
 
-[exchange_keys]
+[exchange]
 # Lengthen over original value (60 s)
 LOOKAHEAD_SIGN = 100 s
diff --git a/src/exchange-lib/test_exchange_api_new.c 
b/src/exchange-lib/test_exchange_api_new.c
index c3e1ce8..a33f8d0 100644
--- a/src/exchange-lib/test_exchange_api_new.c
+++ b/src/exchange-lib/test_exchange_api_new.c
@@ -43,6 +43,14 @@
 #define CONFIG_FILE "test_exchange_api.conf"
 
 /**
+ * Is the configuration file is set to include wire format 'ebics'?
+ * Requires that EBICS /history function is implemented, which it
+ * is currently not.  Once it is, set ENABLE_CREDIT to YES in the
+ * configuration and then set this option to 1.
+ */
+#define WIRE_EBICS 0
+
+/**
  * URL of the fakebank.  Obtained from CONFIG_FILE's
  * "exchange-wire-test:BANK_URI" option.
  */
@@ -145,23 +153,23 @@ run (void *cls,
     CMD_EXEC_WIREWATCH ("wirewatch-1"),
 
     /**
-     * Check if 'test' wire method is offered by the exchange.
+     * Check if 'x-taler-bank' wire method is offered by the exchange.
      */
-    TALER_TESTING_cmd_wire ("wire-test-1",
+    TALER_TESTING_cmd_wire ("wire-taler-bank-1",
                             is->exchange,
-                            "test",
+                            "x-taler-bank",
                             NULL,
                             MHD_HTTP_OK),
-
+#if WIRE_EBICS
     /**
-     * Check if 'sepa' wire method is offered by the exchange.
+     * Check if 'ebics' wire method is offered by the exchange.
      */
     TALER_TESTING_cmd_wire ("wire-sepa-1",
                             is->exchange,
-                            "sepa",
+                            "ebics",
                             NULL,
                             MHD_HTTP_OK),
-
+#endif
     /****** End of "wire" testing ******/
 
     /******  Start of withdraw and spend testing ******/
@@ -188,9 +196,8 @@ run (void *cls,
      */
     TALER_TESTING_cmd_deposit
       ("deposit-simple", is->exchange, "withdraw-coin-1", 0,
-       TALER_TESTING_make_wire_details
-         ("{ \"type\":\"test\",\"account_number\":42}",
-          fakebank_url),
+       TALER_TESTING_make_wire_details (42,
+                                        fakebank_url),
        "{\"items\":[{\"name\":\"ice cream\",\"value\":1}]}",
        GNUNET_TIME_UNIT_ZERO, "EUR:5", MHD_HTTP_OK),
 
@@ -208,9 +215,8 @@ run (void *cls,
      */
     TALER_TESTING_cmd_deposit
       ("deposit-double-1", is->exchange, "withdraw-coin-1", 0,
-       TALER_TESTING_make_wire_details
-         ("{\"type\":\"test\",\"account_number\":43}",
-          fakebank_url),
+       TALER_TESTING_make_wire_details (43,
+                                        fakebank_url),
        "{\"items\":[{\"name\":\"ice cream\",\"value\":1}]}",
        GNUNET_TIME_UNIT_ZERO, "EUR:5", MHD_HTTP_FORBIDDEN),
 
@@ -225,9 +231,8 @@ run (void *cls,
      */
     TALER_TESTING_cmd_deposit
       ("deposit-double-1", is->exchange, "withdraw-coin-1", 0,
-       TALER_TESTING_make_wire_details
-         ("{ \"type\":\"test\", \"account_number\":43}",
-          fakebank_url),
+       TALER_TESTING_make_wire_details (43,
+                                        fakebank_url),
        "{\"items\":[{\"name\":\"ice cream\",\"value\":1}]}",
        GNUNET_TIME_UNIT_ZERO, "EUR:5", MHD_HTTP_FORBIDDEN),
 
@@ -236,12 +241,11 @@ run (void *cls,
      */
     TALER_TESTING_cmd_deposit
       ("deposit-double-2", is->exchange, "withdraw-coin-1", 0,
-       TALER_TESTING_make_wire_details
-         ("{ \"type\":\"test\", \"account_number\":43}",
-          fakebank_url),
+       TALER_TESTING_make_wire_details (43,
+                                        fakebank_url),
        "{\"items\":[{\"name\":\"ice cream\",\"value\":2}]}",
        GNUNET_TIME_UNIT_ZERO, "EUR:5", MHD_HTTP_FORBIDDEN),
-    
+
     /******  End of withdraw and spend testing ******/
 
     /******  Start of refresh testing ******/
@@ -254,7 +258,7 @@ run (void *cls,
      */
     CMD_TRANSFER_TO_EXCHANGE ("refresh-create-reserve-1",
                               "EUR:5.01"),
- 
+
     /**
      * Make previous command effective.
      */
@@ -277,9 +281,8 @@ run (void *cls,
     TALER_TESTING_cmd_deposit
       ("refresh-deposit-partial", is->exchange,
        "refresh-withdraw-coin-1", 0,
-       TALER_TESTING_make_wire_details
-         ("{ \"type\":\"test\",\"account_number\":42}",
-          fakebank_url),
+       TALER_TESTING_make_wire_details (42,
+                                        fakebank_url),
        "{\"items\":[{\"name\":\"ice cream\",\
                      \"value\":\"EUR:1\"}]}",
        GNUNET_TIME_UNIT_ZERO, "EUR:1", MHD_HTTP_OK),
@@ -297,7 +300,7 @@ run (void *cls,
     TALER_TESTING_cmd_refresh_reveal
       ("refresh-reveal-1", is->exchange,
        "refresh-melt-1", MHD_HTTP_OK),
-    
+
     /**
      * Do it again to check idempotency
      */
@@ -318,9 +321,8 @@ run (void *cls,
     TALER_TESTING_cmd_deposit
       ("refresh-deposit-refreshed-1a", is->exchange,
        "refresh-reveal-1-idempotency", 0,
-       TALER_TESTING_make_wire_details
-         ("{ \"type\":\"test\",\"account_number\":42}",
-          fakebank_url),
+       TALER_TESTING_make_wire_details (42,
+                                        fakebank_url),
        "{\"items\":[{\"name\":\"ice cream\",\
                      \"value\":3}]}",
        GNUNET_TIME_UNIT_ZERO, "EUR:1", MHD_HTTP_OK),
@@ -331,9 +333,8 @@ run (void *cls,
     TALER_TESTING_cmd_deposit
       ("refresh-deposit-refreshed-1b", is->exchange,
        "refresh-reveal-1", 4,
-       TALER_TESTING_make_wire_details
-         ("{ \"type\":\"test\",\"account_number\":43}",
-          fakebank_url),
+       TALER_TESTING_make_wire_details (43,
+                                        fakebank_url),
        "{\"items\":[{\"name\":\"ice cream\",\
                      \"value\":3}]}",
        GNUNET_TIME_UNIT_ZERO, "EUR:0.1", MHD_HTTP_OK),
@@ -463,9 +464,8 @@ run (void *cls,
      */
     TALER_TESTING_cmd_deposit
       ("deposit-refund-1", is->exchange, "withdraw-coin-r1", 0,
-       TALER_TESTING_make_wire_details
-         ("{ \"type\":\"test\", \"account_number\":42}",
-          fakebank_url),
+       TALER_TESTING_make_wire_details (42,
+                                        fakebank_url),
        "{\"items\":[{\"name\":\"ice cream\","
                     "\"value\":\"EUR:5\"}]}",
        GNUNET_TIME_UNIT_MINUTES, "EUR:5", MHD_HTTP_OK),
@@ -502,9 +502,8 @@ run (void *cls,
      * 1 ct deposit fee) */
     TALER_TESTING_cmd_deposit
       ("deposit-refund-2", is->exchange, "withdraw-coin-r1", 0,
-       TALER_TESTING_make_wire_details
-         ("{ \"type\":\"test\", \"account_number\":42}",
-          fakebank_url),
+       TALER_TESTING_make_wire_details (42,
+                                        fakebank_url),
        "{\"items\":[{\"name\":\"more ice cream\","
                     "\"value\":\"EUR:5\"}]}",
        GNUNET_TIME_UNIT_ZERO, "EUR:4.99", MHD_HTTP_OK),
@@ -555,9 +554,8 @@ run (void *cls,
 
     TALER_TESTING_cmd_deposit
       ("deposit-refund-1b", is->exchange, "withdraw-coin-rb", 0,
-       TALER_TESTING_make_wire_details
-         ("{ \"type\":\"test\", \"account_number\":42}",
-          fakebank_url),
+       TALER_TESTING_make_wire_details (42,
+                                        fakebank_url),
        "{\"items\":[{\"name\":\"ice cream\","
                     "\"value\":\"EUR:5\"}]}",
        GNUNET_TIME_UNIT_ZERO, "EUR:5", MHD_HTTP_OK),
@@ -602,7 +600,7 @@ run (void *cls,
                                        is->exchange,
                                        "payback-create-reserve-1",
                                        "EUR:5",
-                                       MHD_HTTP_OK), 
+                                       MHD_HTTP_OK),
 
     TALER_TESTING_cmd_revoke ("revoke-1", MHD_HTTP_OK,
                               "payback-withdraw-coin-1",
@@ -648,9 +646,8 @@ run (void *cls,
     TALER_TESTING_cmd_deposit
       ("payback-deposit-partial", is->exchange,
        "payback-withdraw-coin-2a", 0,
-       TALER_TESTING_make_wire_details
-         ("{ \"type\":\"test\",\"account_number\":42}",
-          fakebank_url),
+       TALER_TESTING_make_wire_details (42,
+                                        fakebank_url),
        "{\"items\":[{\"name\":\"more ice cream\",\"value\":1}]}",
        GNUNET_TIME_UNIT_ZERO, "EUR:0.5", MHD_HTTP_OK),
 
@@ -670,9 +667,8 @@ run (void *cls,
     TALER_TESTING_cmd_deposit
       ("payback-deposit-revoked", is->exchange,
        "payback-withdraw-coin-2b", 0,
-       TALER_TESTING_make_wire_details
-         ("{ \"type\":\"test\",\"account_number\":42}",
-          fakebank_url),
+       TALER_TESTING_make_wire_details (42,
+                                        fakebank_url),
        "{\"items\":[{\"name\":\"more ice cream\",\"value\":1}]}",
        GNUNET_TIME_UNIT_ZERO, "EUR:1", MHD_HTTP_NOT_FOUND),
 
@@ -685,9 +681,8 @@ run (void *cls,
     TALER_TESTING_cmd_deposit
       ("payback-deposit-partial-after-payback", is->exchange,
        "payback-withdraw-coin-2a", 0,
-       TALER_TESTING_make_wire_details
-         ("{ \"type\":\"test\",\"account_number\":42}",
-          fakebank_url),
+       TALER_TESTING_make_wire_details (42,
+                                        fakebank_url),
        "{\"items\":[{\"name\":\"extra ice cream\",\"value\":1}]}",
        GNUNET_TIME_UNIT_ZERO, "EUR:0.5", MHD_HTTP_NOT_FOUND),
 
@@ -740,6 +735,7 @@ run (void *cls,
                                    fakebank_url);
 }
 
+
 int
 main (int argc,
       char * const *argv)
@@ -753,7 +749,8 @@ main (int argc,
   if (NULL == (fakebank_url
        /* Check fakebank port is available and config cares
         * about bank url. */
-       = TALER_TESTING_prepare_fakebank (CONFIG_FILE)))
+               = TALER_TESTING_prepare_fakebank (CONFIG_FILE,
+                                                 "account-2")))
     return 77;
   TALER_TESTING_cleanup_files (CONFIG_FILE);
   /* @helpers.  Run keyup, create tables, ... Note: it
diff --git a/src/exchange-lib/test_exchange_api_twisted.c 
b/src/exchange-lib/test_exchange_api_twisted.c
index 6032417..1e3aa34 100644
--- a/src/exchange-lib/test_exchange_api_twisted.c
+++ b/src/exchange-lib/test_exchange_api_twisted.c
@@ -179,7 +179,8 @@ main (int argc,
                     "DEBUG", NULL);
 
   if (NULL == (fakebank_url = TALER_TESTING_prepare_fakebank
-      (CONFIG_FILE)))
+               (CONFIG_FILE,
+                "account-2")))
     return 77;
 
   if (NULL == (twister_url = TALER_TESTING_prepare_twister
diff --git a/src/exchange-lib/testing_api_cmd_deposit.c 
b/src/exchange-lib/testing_api_cmd_deposit.c
index 6f66e8a..5854bf8 100644
--- a/src/exchange-lib/testing_api_cmd_deposit.c
+++ b/src/exchange-lib/testing_api_cmd_deposit.c
@@ -50,9 +50,9 @@ struct DepositState
   unsigned int coin_index;
 
   /**
-   * JSON string describing the merchant's "wire details".
+   * payto://-URL of the merchant's bank account.
    */
-  char *wire_details;
+  json_t *wire_details;
 
   /**
    * JSON string describing what a proposal is about.
@@ -126,6 +126,7 @@ deposit_cb (void *cls,
   TALER_TESTING_interpreter_next (ds->is);
 }
 
+
 /**
  * Run the command.
  *
@@ -133,7 +134,7 @@ deposit_cb (void *cls,
  * @param cmd the command to execute, a /wire one.
  * @param i the interpreter state.
  */
-void
+static void
 deposit_run (void *cls,
              const struct TALER_TESTING_Command *cmd,
              struct TALER_TESTING_Interpreter *is)
@@ -153,7 +154,6 @@ deposit_run (void *cls,
   struct TALER_MerchantPublicKeyP merchant_pub;
   struct GNUNET_HashCode h_contract_terms;
   json_t *contract_terms;
-  json_t *wire;
   struct TALER_Amount amount;
 
   ds->is = is;
@@ -166,7 +166,7 @@ deposit_run (void *cls,
   if (NULL == coin_cmd)
   {
     GNUNET_break (0);
-    TALER_TESTING_interpreter_fail (is);  
+    TALER_TESTING_interpreter_fail (is);
     return;
   }
 
@@ -213,21 +213,6 @@ deposit_run (void *cls,
                  TALER_JSON_hash (contract_terms,
                                   &h_contract_terms));
   json_decref (contract_terms);
-
-  wire = json_loads (ds->wire_details,
-                     JSON_REJECT_DUPLICATES,
-                     NULL);
-  if (NULL == wire)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                "Failed to parse wire details `%s' at %u/%s\n",
-                ds->wire_details,
-                is->ip,
-                this_cmd->label);
-    TALER_TESTING_interpreter_fail (is);
-    return;
-  }
-  
   GNUNET_CRYPTO_eddsa_key_get_public (&coin_priv->eddsa_priv,
                                       &coin_pub.eddsa_pub);
 
@@ -267,8 +252,9 @@ deposit_run (void *cls,
     dr.purpose.purpose = htonl
       (TALER_SIGNATURE_WALLET_COIN_DEPOSIT);
     dr.h_contract_terms = h_contract_terms;
-    GNUNET_assert (GNUNET_OK == TALER_JSON_hash
-      (wire, &dr.h_wire));
+    GNUNET_assert (GNUNET_OK ==
+                   TALER_JSON_wire_signature_hash (ds->wire_details,
+                                                   &dr.h_wire));
     dr.timestamp = GNUNET_TIME_absolute_hton (timestamp);
     dr.refund_deadline = GNUNET_TIME_absolute_hton
       (refund_deadline);
@@ -286,7 +272,7 @@ deposit_run (void *cls,
     (ds->exchange,
      &amount,
      wire_deadline,
-     wire,
+     ds->wire_details,
      &h_contract_terms,
      &coin_pub,
      denom_pub_sig,
@@ -301,21 +287,20 @@ deposit_run (void *cls,
   if (NULL == ds->dh)
   {
     GNUNET_break (0);
-    json_decref (wire);
     TALER_TESTING_interpreter_fail (is);
     return;
   }
-  json_decref (wire);
   return;
 }
 
+
 /**
  * Cleanup the state.
  *
  * @param cls closure, typically a #struct WireState.
  * @param cmd the command which is being cleaned up.
  */
-void
+static void
 deposit_cleanup (void *cls,
                  const struct TALER_TESTING_Command *cmd)
 {
@@ -331,10 +316,11 @@ deposit_cleanup (void *cls,
     ds->dh = NULL;
   }
 
-  GNUNET_free (ds->wire_details);
+  json_decref (ds->wire_details);
   GNUNET_free (ds);
 }
 
+
 /**
  * Extract information from a command that is useful for other
  * commands.
@@ -354,7 +340,7 @@ deposit_traits (void *cls,
                 unsigned int index)
 {
   struct DepositState *ds = cls;
-  const struct TALER_TESTING_Command *coin_cmd; 
+  const struct TALER_TESTING_Command *coin_cmd;
   /* Will point to coin cmd internals. */
   struct TALER_CoinSpendPrivateKeyP *coin_spent_priv;
 
@@ -382,7 +368,7 @@ deposit_traits (void *cls,
     TALER_TESTING_make_trait_contract_terms (0, ds->contract_terms),
     TALER_TESTING_make_trait_peer_key
       (0, &ds->merchant_priv.eddsa_priv),
-    TALER_TESTING_trait_end ()  
+    TALER_TESTING_trait_end ()
   };
 
   return TALER_TESTING_get_trait (traits,
@@ -402,8 +388,8 @@ deposit_traits (void *cls,
  *        coins, this parameter selects which one in that array.
  *        This value is currently ignored, as only one-coin
  *        withdrawals are implemented.
- * @param wire_details bank details of the merchant performing the
- *        deposit
+ * @param wire_details JSON details of the wire account of the merchant 
performing the
+ *        deposit, reference is captured by this command
  * @param contract_terms contract terms to be signed over by the
  *        coin
  * @param refund_deadline refund deadline, zero means 'no refunds'
@@ -419,7 +405,7 @@ TALER_TESTING_cmd_deposit
    struct TALER_EXCHANGE_Handle *exchange,
    const char *coin_reference,
    unsigned int coin_index,
-   char *wire_details,
+   json_t *wire_details,
    const char *contract_terms,
    struct GNUNET_TIME_Relative refund_deadline,
    const char *amount,
@@ -427,7 +413,7 @@ TALER_TESTING_cmd_deposit
 {
   struct TALER_TESTING_Command cmd;
   struct DepositState *ds;
-  
+
   ds = GNUNET_new (struct DepositState);
   ds->exchange = exchange;
   ds->coin_reference = coin_reference;
diff --git a/src/exchange-lib/testing_api_cmd_exec_auditor-sign.c 
b/src/exchange-lib/testing_api_cmd_exec_auditor-sign.c
index bae0c07..98ce116 100644
--- a/src/exchange-lib/testing_api_cmd_exec_auditor-sign.c
+++ b/src/exchange-lib/testing_api_cmd_exec_auditor-sign.c
@@ -72,23 +72,23 @@ auditor_sign_run (void *cls,
   if (GNUNET_OK != GNUNET_CONFIGURATION_load
     (cfg, ass->config_filename))
   {
-    GNUNET_break (0); 
-    TALER_TESTING_interpreter_fail (is); 
+    GNUNET_break (0);
+    TALER_TESTING_interpreter_fail (is);
     return;
   }
 
   if (GNUNET_OK !=
-      GNUNET_CONFIGURATION_get_value_string (cfg,
-                                             "paths",
-                                             "TALER_TEST_HOME",
-                                             &test_home_dir))
+      GNUNET_CONFIGURATION_get_value_filename (cfg,
+                                               "paths",
+                                               "TALER_TEST_HOME",
+                                               &test_home_dir))
   {
     GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
                                "paths",
                                "TALER_TEST_HOME");
     GNUNET_CONFIGURATION_destroy (cfg);
-    GNUNET_break (0); 
-    TALER_TESTING_interpreter_fail (is); 
+    GNUNET_break (0);
+    TALER_TESTING_interpreter_fail (is);
     return;
   }
 
@@ -108,8 +108,8 @@ auditor_sign_run (void *cls,
                                "MASTER_PUBLIC_KEY");
     GNUNET_CONFIGURATION_destroy (cfg);
 
-    GNUNET_break (0); 
-    TALER_TESTING_interpreter_fail (is); 
+    GNUNET_break (0);
+    TALER_TESTING_interpreter_fail (is);
     return;
   }
 
diff --git a/src/exchange-lib/testing_api_cmd_exec_wirewatch.c 
b/src/exchange-lib/testing_api_cmd_exec_wirewatch.c
index 1ff466f..fd8404b 100644
--- a/src/exchange-lib/testing_api_cmd_exec_wirewatch.c
+++ b/src/exchange-lib/testing_api_cmd_exec_wirewatch.c
@@ -68,7 +68,6 @@ wirewatch_run (void *cls,
                                "taler-exchange-wirewatch",
                                "taler-exchange-wirewatch",
                                "-c", ws->config_filename,
-                               "-t", "test", /* use Taler's bank/fakebank */
                                "-T", /* exit when done */
                                NULL);
   if (NULL == ws->wirewatch_proc)
diff --git a/src/exchange-lib/testing_api_cmd_fakebank_transfer.c 
b/src/exchange-lib/testing_api_cmd_fakebank_transfer.c
index a8bad86..733ceb4 100644
--- a/src/exchange-lib/testing_api_cmd_fakebank_transfer.c
+++ b/src/exchange-lib/testing_api_cmd_fakebank_transfer.c
@@ -231,18 +231,16 @@ fakebank_transfer_run (void *cls,
         }
 
         GNUNET_asprintf (&section,
-                         "merchant-instance-%s",
+                         "instance-%s",
                          fts->instance);
         if (GNUNET_OK !=
-            GNUNET_CONFIGURATION_get_value_string
-              (cfg,
-               section,
-               "TIP_RESERVE_PRIV_FILENAME",
-               &keys))
+            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",
+                      "Configuration fails to specify reserve private key 
filename in section %s\n",
                       section);
           GNUNET_free (section);
           TALER_TESTING_interpreter_fail (is);
diff --git a/src/exchange-lib/testing_api_cmd_payback.c 
b/src/exchange-lib/testing_api_cmd_payback.c
index 3a750e7..65665c9 100644
--- a/src/exchange-lib/testing_api_cmd_payback.c
+++ b/src/exchange-lib/testing_api_cmd_payback.c
@@ -31,7 +31,7 @@
 
 struct RevokeState
 {
-  /** 
+  /**
    * Expected HTTP status code.
    */
   unsigned int expected_response_code;
@@ -65,7 +65,7 @@ struct RevokeState
 
 struct PaybackState
 {
-  /** 
+  /**
    * Expected HTTP status code.
    */
   unsigned int expected_response_code;
@@ -154,7 +154,7 @@ payback_cb (void *cls,
     TALER_TESTING_interpreter_fail (is);
     return;
   }
-  
+
   if (GNUNET_OK != TALER_TESTING_get_trait_reserve_priv
     (reserve_cmd, 0, &reserve_priv))
   {
@@ -201,6 +201,7 @@ payback_cb (void *cls,
   TALER_TESTING_interpreter_next (is);
 }
 
+
 /**
  * Run the command.
  *
@@ -208,7 +209,7 @@ payback_cb (void *cls,
  * @param cmd the command to execute, a /wire one.
  * @param is the interpreter state.
  */
-void
+static void
 payback_run (void *cls,
              const struct TALER_TESTING_Command *cmd,
              struct TALER_TESTING_Interpreter *is)
@@ -230,7 +231,7 @@ payback_run (void *cls,
   {
     GNUNET_break (0);
     TALER_TESTING_interpreter_fail (is);
-    return;  
+    return;
   }
 
   if (GNUNET_OK != TALER_TESTING_get_trait_coin_priv
@@ -238,7 +239,7 @@ payback_run (void *cls,
   {
     GNUNET_break (0);
     TALER_TESTING_interpreter_fail (is);
-    return; 
+    return;
   }
 
   if (GNUNET_OK != TALER_TESTING_get_trait_blinding_key
@@ -246,7 +247,7 @@ payback_run (void *cls,
   {
     GNUNET_break (0);
     TALER_TESTING_interpreter_fail (is);
-    return; 
+    return;
   }
   planchet.coin_priv = *coin_priv;
   planchet.blinding_key = *blinding_key;
@@ -256,7 +257,7 @@ payback_run (void *cls,
   {
     GNUNET_break (0);
     TALER_TESTING_interpreter_fail (is);
-    return; 
+    return;
   }
 
   if (GNUNET_OK != TALER_TESTING_get_trait_denom_sig
@@ -264,13 +265,13 @@ payback_run (void *cls,
   {
     GNUNET_break (0);
     TALER_TESTING_interpreter_fail (is);
-    return; 
+    return;
   }
 
   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
               "Trying to get '%s..' paid back\n",
               TALER_B2S (&denom_pub->h_key));
-  
+
   ps->ph = TALER_EXCHANGE_payback (ps->exchange,
                                    denom_pub,
                                    coin_sig,
@@ -280,13 +281,14 @@ payback_run (void *cls,
   GNUNET_assert (NULL != ps->ph);
 }
 
+
 /**
  * Cleanup the state.
  *
  * @param cls closure, typically a #struct WireState.
  * @param cmd the command which is being cleaned up.
  */
-void
+static void
 revoke_cleanup (void *cls,
                 const struct TALER_TESTING_Command *cmd)
 {
@@ -302,17 +304,18 @@ revoke_cleanup (void *cls,
     rs->revoke_proc = NULL;
   }
 
-  GNUNET_free (rs->dhks);
+  GNUNET_free_non_null (rs->dhks);
   GNUNET_free (rs);
 }
 
+
 /**
  * Cleanup the state.
  *
  * @param cls closure, typically a #struct WireState.
  * @param cmd the command which is being cleaned up.
  */
-void
+static void
 payback_cleanup (void *cls,
                  const struct TALER_TESTING_Command *cmd)
 {
@@ -325,6 +328,7 @@ payback_cleanup (void *cls,
   GNUNET_free (ps);
 }
 
+
 /**
  * Extract information from a command that is useful for other
  * commands.
@@ -366,7 +370,7 @@ revoke_traits (void *cls,
  * @param cmd the command to execute, a /wire one.
  * @param is the interpreter state.
  */
-void
+static void
 revoke_run (void *cls,
             const struct TALER_TESTING_Command *cmd,
             struct TALER_TESTING_Interpreter *is)
@@ -384,7 +388,7 @@ revoke_run (void *cls,
   {
     GNUNET_break (0);
     TALER_TESTING_interpreter_fail (is);
-    return;  
+    return;
   }
 
   GNUNET_assert (GNUNET_OK == TALER_TESTING_get_trait_denom_pub
@@ -395,8 +399,8 @@ revoke_run (void *cls,
               TALER_B2S (&denom_pub->h_key));
 
   rs->dhks = GNUNET_STRINGS_data_to_string_alloc
-    (&denom_pub->h_key, sizeof (struct GNUNET_HashCode)); 
-  
+    (&denom_pub->h_key, sizeof (struct GNUNET_HashCode));
+
   rs->revoke_proc = GNUNET_OS_start_process
     (GNUNET_NO,
      GNUNET_OS_INHERIT_STD_ALL,
@@ -441,7 +445,7 @@ TALER_TESTING_cmd_payback (const char *label,
 {
   struct PaybackState *ps;
   struct TALER_TESTING_Command cmd;
-  
+
   ps = GNUNET_new (struct PaybackState);
   ps->expected_response_code = expected_response_code;
   ps->coin_reference = coin_reference;
@@ -455,6 +459,7 @@ TALER_TESTING_cmd_payback (const char *label,
   return cmd;
 }
 
+
 /**
  * Make a /revoke command.
  *
diff --git a/src/exchange-lib/testing_api_cmd_refund.c 
b/src/exchange-lib/testing_api_cmd_refund.c
index a092ee2..35cb20d 100644
--- a/src/exchange-lib/testing_api_cmd_refund.c
+++ b/src/exchange-lib/testing_api_cmd_refund.c
@@ -139,7 +139,7 @@ refund_run (void *cls,
             const struct TALER_TESTING_Command *cmd,
             struct TALER_TESTING_Interpreter *is)
 {
-  struct RefundState *rs = cls; 
+  struct RefundState *rs = cls;
   struct TALER_CoinSpendPrivateKeyP *coin_priv;
   struct TALER_CoinSpendPublicKeyP coin;
   const char *contract_terms;
@@ -193,7 +193,7 @@ refund_run (void *cls,
   {
     GNUNET_break (0);
     TALER_TESTING_interpreter_fail (is);
-    return; 
+    return;
   }
 
   j_contract_terms = json_loads
@@ -201,8 +201,9 @@ refund_run (void *cls,
 
   /* Very unlikely to fail */
   GNUNET_assert (NULL != j_contract_terms);
-  GNUNET_assert (GNUNET_OK == TALER_JSON_hash
-    (j_contract_terms, &h_contract_terms));
+  GNUNET_assert (GNUNET_OK ==
+                 TALER_JSON_hash (j_contract_terms,
+                                  &h_contract_terms));
 
   json_decref (j_contract_terms);
 
@@ -222,7 +223,7 @@ refund_run (void *cls,
   {
     GNUNET_break (0);
     TALER_TESTING_interpreter_fail (is);
-    return; 
+    return;
   }
 
   rs->rh = TALER_EXCHANGE_refund
diff --git a/src/exchange-lib/testing_api_cmd_track.c 
b/src/exchange-lib/testing_api_cmd_track.c
index bbad7b7..d4f9805 100644
--- a/src/exchange-lib/testing_api_cmd_track.c
+++ b/src/exchange-lib/testing_api_cmd_track.c
@@ -183,7 +183,7 @@ deposit_wtid_cb
     tts->wtid = *wtid;
     if (NULL != tts->bank_transfer_reference)
     {
-      const struct TALER_TESTING_Command *bank_transfer_cmd; 
+      const struct TALER_TESTING_Command *bank_transfer_cmd;
       char *ws;
 
       ws = GNUNET_STRINGS_data_to_string_alloc (wtid,
@@ -205,7 +205,7 @@ deposit_wtid_cb
       {
         GNUNET_break (0);
         TALER_TESTING_interpreter_fail (is);
-        return;       
+        return;
       }
 
       if (0 != strcmp (ws, transfer_subject))
@@ -248,14 +248,13 @@ track_transaction_run (void *cls,
   const struct TALER_TESTING_Command *transaction_cmd;
   struct TALER_CoinSpendPrivateKeyP *coin_priv;
   struct TALER_CoinSpendPublicKeyP coin_pub;
-  const char *wire_details;
   const char *contract_terms;
-  json_t *j_wire_details;
+  const json_t *wire_details;
   json_t *j_contract_terms;
   struct GNUNET_HashCode h_wire_details;
   struct GNUNET_HashCode h_contract_terms;
   const struct GNUNET_CRYPTO_EddsaPrivateKey *merchant_priv;
-  
+
   tts->is = is;
   transaction_cmd = TALER_TESTING_interpreter_lookup_command
     (tts->is, tts->transaction_reference);
@@ -264,7 +263,7 @@ track_transaction_run (void *cls,
   {
     GNUNET_break (0);
     TALER_TESTING_interpreter_fail (tts->is);
-    return;  
+    return;
   }
 
   if (GNUNET_OK != TALER_TESTING_get_trait_coin_priv
@@ -272,7 +271,7 @@ track_transaction_run (void *cls,
   {
     GNUNET_break (0);
     TALER_TESTING_interpreter_fail (tts->is);
-    return;  
+    return;
   }
 
   GNUNET_CRYPTO_eddsa_key_get_public (&coin_priv->eddsa_priv,
@@ -296,31 +295,31 @@ track_transaction_run (void *cls,
   }
 
   /* Parse them.. */
-  j_wire_details = json_loads
-    (wire_details, JSON_REJECT_DUPLICATES, NULL);
   j_contract_terms = json_loads
     (contract_terms, JSON_REJECT_DUPLICATES, NULL);
-  
-  if ((NULL == j_wire_details) || (NULL == j_contract_terms))
+
+  if ((NULL == wire_details) || (NULL == j_contract_terms))
   {
     GNUNET_break (0);
     TALER_TESTING_interpreter_fail (tts->is);
-    return;  
+    return;
   }
 
   /* Should not fail here, json has been parsed already */
   GNUNET_assert
-    ( (GNUNET_OK == TALER_JSON_hash (j_wire_details,
-                                      &h_wire_details)) &&
-      (GNUNET_OK == TALER_JSON_hash (j_contract_terms,
-                                      &h_contract_terms)) );
+    ( (GNUNET_OK ==
+       TALER_JSON_wire_signature_hash (wire_details,
+                                       &h_wire_details)) &&
+      (GNUNET_OK ==
+       TALER_JSON_hash (j_contract_terms,
+                        &h_contract_terms)) );
 
   if (GNUNET_OK != TALER_TESTING_get_trait_peer_key
     (transaction_cmd, 0, &merchant_priv))
   {
     GNUNET_break (0);
     TALER_TESTING_interpreter_fail (tts->is);
-    return; 
+    return;
   }
 
   tts->tth = TALER_EXCHANGE_track_transaction
@@ -579,7 +578,7 @@ track_transfer_cb
     {
       GNUNET_break (0);
       TALER_TESTING_interpreter_fail (is);
-      return;    
+      return;
     }
 
     /**
@@ -593,8 +592,7 @@ track_transfer_cb
     if (NULL != tts->wire_details_reference)
     {
       const struct TALER_TESTING_Command *wire_details_cmd;
-      const char *wire_details;
-      json_t *j_wire_details;
+      const json_t *wire_details;
       struct GNUNET_HashCode h_wire_details;
 
       if (NULL == (wire_details_cmd
@@ -614,13 +612,9 @@ track_transfer_cb
         return;
       }
 
-      j_wire_details = json_loads
-        (wire_details, JSON_REJECT_DUPLICATES, NULL);
-
-      GNUNET_assert (NULL != j_wire_details);
-
-      GNUNET_assert (GNUNET_OK == TALER_JSON_hash
-        (j_wire_details, &h_wire_details));
+      GNUNET_assert (GNUNET_OK ==
+                     TALER_JSON_wire_signature_hash (wire_details,
+                                                     &h_wire_details));
 
       if (0 != memcmp (&h_wire_details,
                        h_wire,
@@ -646,7 +640,7 @@ track_transfer_cb
       {
         GNUNET_break (0);
         TALER_TESTING_interpreter_fail (is);
-        return;      
+        return;
       }
 
       if (GNUNET_OK != TALER_TESTING_get_trait_amount
@@ -656,7 +650,7 @@ track_transfer_cb
         TALER_TESTING_interpreter_fail (is);
         return;
       }
-      
+
       GNUNET_assert (GNUNET_OK == TALER_string_to_amount
         (total_amount_from_reference_str,
          &total_amount_from_reference));
@@ -698,7 +692,7 @@ track_transfer_run (void *cls,
    * WTID */
   memset (&wtid, 0, sizeof (wtid));
   wtid_ptr = &wtid;
-  
+
   tts->is = is;
   if (NULL != tts->wtid_reference)
   {
@@ -719,7 +713,7 @@ track_transfer_run (void *cls,
     {
       GNUNET_break (0);
       TALER_TESTING_interpreter_fail (tts->is);
-      return;     
+      return;
     }
     GNUNET_assert (NULL != wtid_ptr);
   }
@@ -755,7 +749,7 @@ TALER_TESTING_cmd_track_transfer_empty
 {
   struct TrackTransferState *tts;
   struct TALER_TESTING_Command cmd;
-  
+
   tts = GNUNET_new (struct TrackTransferState);
 
   tts->wtid_reference = wtid_reference;
@@ -768,7 +762,7 @@ TALER_TESTING_cmd_track_transfer_empty
   cmd.run = &track_transfer_run;
   cmd.cleanup = &track_transfer_cleanup;
 
-  return cmd; 
+  return cmd;
 }
 
 /**
@@ -800,7 +794,7 @@ TALER_TESTING_cmd_track_transfer
 {
   struct TrackTransferState *tts;
   struct TALER_TESTING_Command cmd;
-  
+
   tts = GNUNET_new (struct TrackTransferState);
 
   tts->wtid_reference = wtid_reference;
@@ -815,5 +809,5 @@ TALER_TESTING_cmd_track_transfer
   cmd.run = &track_transfer_run;
   cmd.cleanup = &track_transfer_cleanup;
 
-  return cmd; 
+  return cmd;
 }
diff --git a/src/exchange-lib/testing_api_cmd_wire.c 
b/src/exchange-lib/testing_api_cmd_wire.c
index f65daec..cf8304e 100644
--- a/src/exchange-lib/testing_api_cmd_wire.c
+++ b/src/exchange-lib/testing_api_cmd_wire.c
@@ -27,6 +27,7 @@
 #include "taler_json_lib.h"
 #include <gnunet/gnunet_curl_lib.h>
 #include "exchange_api_handle.h"
+#include "taler_wire_lib.h"
 #include "taler_testing_lib.h"
 
 struct WireState
@@ -71,19 +72,6 @@ struct WireState
 
 
 /**
- * Check all the expected values have been returned by /wire.
- *
- * @param cls closure
- * @param wire_method name of the wire method (i.e. "sepa")
- * @param fees fee structure for this method
- */
-static void
-check_method_and_fee_cb
-  (void *cls,
-   const char *wire_method,
-   const struct TALER_EXCHANGE_WireAggregateFees *fees);
-
-/**
  * Callbacks called with the result(s) of a wire format inquiry
  * request to the exchange.
  *
@@ -92,23 +80,20 @@ check_method_and_fee_cb
  *                    for successful request; 0 if the exchange's
  *                    reply is bogus (fails to follow the protocol)
  * @param ec taler-specific error code, #TALER_EC_NONE on success
- * @param obj the received JSON reply, if successful this should
- *            be the wire format details as provided by /wire.
+ * @param accounts_len length of the @a accounts array
+ * @param accounts list of wire accounts of the exchange, NULL on error
  */
 static void
 wire_cb (void *cls,
          unsigned int http_status,
         enum TALER_ErrorCode ec,
-         const json_t *obj)
+         unsigned int accounts_len,
+         const struct TALER_EXCHANGE_WireAccount *accounts)
 {
   struct WireState *ws = cls;
-  struct TALER_TESTING_Command *cmd
-    = &ws->is->commands[ws->is->ip];
+  struct TALER_TESTING_Command *cmd = &ws->is->commands[ws->is->ip];
+  struct TALER_Amount expected_fee;
 
-  /**
-   * The handle has been free'd by GNUnet curl-lib. FIXME:
-   * shouldn't GNUnet nullify it once it frees it?
-   */
   ws->wh = NULL;
   if (ws->expected_response_code != http_status)
   {
@@ -117,74 +102,54 @@ wire_cb (void *cls,
     return;
   }
 
-  if (GNUNET_OK != TALER_EXCHANGE_wire_get_fees
-       (&TALER_EXCHANGE_get_keys (ws->exchange)->master_pub,
-        obj,
-        // will check synchronously.
-        &check_method_and_fee_cb,
-        ws))
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                "Wire fee extraction in command %s failed\n",
-                cmd->label);
-    json_dumpf (obj, stderr, 0);
-    TALER_TESTING_interpreter_fail (ws->is);
-    return;
-  }
-
-  if (ws->method_found != GNUNET_OK)
+  if (MHD_HTTP_OK == http_status)
   {
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                "/wire does not offer method '%s'\n",
-                ws->expected_method);
-    TALER_TESTING_interpreter_fail (ws->is);
-    return;
-  }
-  TALER_TESTING_interpreter_next (ws->is);
-}
-
-/**
- * Check all the expected values have been returned by /wire.
- *
- * @param cls closure
- * @param wire_method name of the wire method (i.e. "sepa")
- * @param fees fee structure for this method
- */
-static void
-check_method_and_fee_cb
-  (void *cls,
-   const char *wire_method,
-   const struct TALER_EXCHANGE_WireAggregateFees *fees)
-{
-  struct WireState *ws = cls;
-  struct TALER_TESTING_Command *cmd
-    = &ws->is->commands[ws->is->ip]; // ugly?
-  struct TALER_Amount expected_fee;
-
-  if (0 == strcmp (ws->expected_method, wire_method))
-    ws->method_found = GNUNET_OK;
-
-  if ( ws->expected_fee && (ws->method_found == GNUNET_OK) )
-  {
-    GNUNET_assert (GNUNET_OK == TALER_string_to_amount
-                     (ws->expected_fee,
-                      &expected_fee));
-    while (NULL != fees)
+    for (unsigned int i=0;i<accounts_len;i++)
     {
-      if (0 != TALER_amount_cmp (&fees->wire_fee,
-                                 &expected_fee))
+      char *method;
+
+      method = TALER_WIRE_payto_get_method (accounts[i].url);
+      if (0 == strcmp (ws->expected_method,
+                       method))
       {
-        GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                    "Wire fee missmatch to command %s\n",
-                    cmd->label);
-        TALER_TESTING_interpreter_fail (ws->is);
-        return;
+        ws->method_found = GNUNET_OK;
+        if (NULL != ws->expected_fee)
+        {
+          GNUNET_assert (GNUNET_OK ==
+                         TALER_string_to_amount (ws->expected_fee,
+                                                 &expected_fee));
+          for (const struct TALER_EXCHANGE_WireAggregateFees *waf = 
accounts[i].fees;
+               NULL != waf;
+               waf = waf->next)
+          {
+            if (0 != TALER_amount_cmp (&waf->wire_fee,
+                                       &expected_fee))
+              {
+                GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                            "Wire fee missmatch to command %s\n",
+                            cmd->label);
+                TALER_TESTING_interpreter_fail (ws->is);
+                GNUNET_free (method);
+                return;
+              }
+          }
+        }
       }
-      fees = fees->next;
+      GNUNET_free (method);
+    }
+    if (GNUNET_OK != ws->method_found)
+    {
+      GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                  "/wire does not offer method '%s'\n",
+                  ws->expected_method);
+      TALER_TESTING_interpreter_fail (ws->is);
+      return;
     }
   }
+  TALER_TESTING_interpreter_next (ws->is);
 }
 
+
 /**
  * Run the command.
  *
diff --git a/src/exchange-lib/testing_api_helpers.c 
b/src/exchange-lib/testing_api_helpers.c
index a942b65..8bf66ef 100644
--- a/src/exchange-lib/testing_api_helpers.c
+++ b/src/exchange-lib/testing_api_helpers.c
@@ -127,10 +127,10 @@ TALER_TESTING_prepare_exchange (const char 
*config_filename,
   }
 
   if (GNUNET_OK !=
-      GNUNET_CONFIGURATION_get_value_string (cfg,
-                                             "paths",
-                                             "TALER_TEST_HOME",
-                                             &test_home_dir))
+      GNUNET_CONFIGURATION_get_value_filename (cfg,
+                                               "paths",
+                                               "TALER_TEST_HOME",
+                                               &test_home_dir))
   {
     GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
                                "paths",
@@ -416,42 +416,54 @@ TALER_TESTING_url_port_free (const char *url)
   return GNUNET_OK;
 }
 
+
 /**
- * Allocate and return a piece of wire-details.  Mostly, it adds
- * the bank_url to the JSON.
+ * Allocate and return a piece of wire-details.  Combines
+ * the @a account_no and the @a bank_url to a
+ * @a payto://-URL and adds some salt to create the JSON.
  *
- * @param template the wire-details template.
+ * @param account_no account number
  * @param bank_url the bank_url
- *
- * @return the filled out and stringified wire-details.  To
- *         be manually free'd.
+ * @return JSON describing the account, including the
+ *         payto://-URL of the account, must be manually decref'd
  */
-char *
-TALER_TESTING_make_wire_details (const char *template,
+json_t *
+TALER_TESTING_make_wire_details (unsigned long long account_no,
                                  const char *bank_url)
 {
-  json_t *jtemplate;
-
-  GNUNET_assert (NULL != (jtemplate = json_loads
-    (template, JSON_REJECT_DUPLICATES, NULL)));
-  GNUNET_assert (0 == json_object_set
-    (jtemplate, "bank_url", json_string (bank_url)));
-  return json_dumps (jtemplate, JSON_COMPACT);
+  char *payto;
+  json_t *ret;
+
+  GNUNET_asprintf (&payto,
+                   "payto://x-taler-bank/%s/%llu",
+                   bank_url,
+                   account_no);
+  ret = json_pack ("{s:s, s:s}",
+                   "url", payto,
+                   "salt", "test-salt (must be constant for aggregation 
tests)");
+  GNUNET_free (payto);
+  return ret;
 }
 
+
 /**
  * Prepare launching a fakebank.  Check that the configuration
  * file has the right option, and that the port is available.
  * If everything is OK, return the configured URL of the fakebank.
  *
  * @param config_filename configuration file to use
+ * @param config_section which account to use (must match x-taler-bank)
  * @return NULL on error, fakebank URL otherwise
  */
 char *
-TALER_TESTING_prepare_fakebank (const char *config_filename)
+TALER_TESTING_prepare_fakebank (const char *config_filename,
+                                const char *config_section)
 {
   struct GNUNET_CONFIGURATION_Handle *cfg;
+  char *payto_url;
   char *fakebank_url;
+  const char *start;
+  const char *end;
 
   cfg = GNUNET_CONFIGURATION_create ();
   if (GNUNET_OK != GNUNET_CONFIGURATION_load (cfg,
@@ -459,17 +471,37 @@ TALER_TESTING_prepare_fakebank (const char 
*config_filename)
     return NULL;
   if (GNUNET_OK !=
       GNUNET_CONFIGURATION_get_value_string (cfg,
-                                             "exchange-wire-test",
-                                             "BANK_URL",
-                                             &fakebank_url))
+                                             config_section,
+                                             "URL",
+                                             &payto_url))
   {
     GNUNET_log_config_missing (GNUNET_ERROR_TYPE_WARNING,
-                               "exchange-wire-test",
-                               "BANK_URL");
+                               config_section,
+                               "URL");
     GNUNET_CONFIGURATION_destroy (cfg);
     return NULL;
   }
   GNUNET_CONFIGURATION_destroy (cfg);
+  if (0 != strncasecmp (payto_url,
+                        "payto://x-taler-bank/",
+                        strlen ("payto://x-taler-bank/")))
+  {
+    GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_WARNING,
+                               config_section,
+                               "URL",
+                               "expected `x-taler-bank' payto://-URL");
+    GNUNET_CONFIGURATION_destroy (cfg);
+    GNUNET_free (payto_url);
+    return NULL;
+  }
+  start = &payto_url [strlen ("payto://x-taler-bank/")];
+  end = strchr (start,
+                (unsigned char) '/');
+  if (NULL == end)
+    end = &start[strlen (start)];
+  fakebank_url = GNUNET_strndup (start,
+                                 end - start);
+  GNUNET_free (payto_url);
   if (GNUNET_OK !=
       TALER_TESTING_url_port_free (fakebank_url))
   {
diff --git a/src/exchange-lib/testing_api_loop.c 
b/src/exchange-lib/testing_api_loop.c
index 592843b..7efadb3 100644
--- a/src/exchange-lib/testing_api_loop.c
+++ b/src/exchange-lib/testing_api_loop.c
@@ -158,7 +158,13 @@ void
 TALER_TESTING_interpreter_fail
   (struct TALER_TESTING_Interpreter *is)
 {
+  struct TALER_TESTING_Command *cmd = &is->commands[is->ip];
+
   // FIXME: disconnect from the exchange.
+  GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+              "Failed at command `%s'\n",
+              cmd->label);
+
   is->result = GNUNET_SYSERR;
   // this cleans up too.
   GNUNET_SCHEDULER_shutdown ();
@@ -473,7 +479,7 @@ cert_cb (void *cls,
   {
     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
                 "Got NULL response for /keys\n");
-  
+
   }
   else
     GNUNET_log (GNUNET_ERROR_TYPE_INFO,
@@ -482,7 +488,7 @@ cert_cb (void *cls,
 
   main_ctx->is->key_generation++;
   main_ctx->is->keys = keys;
-  
+
   /* /keys has been called for some reason and
    * the interpreter is already running. */
   if (GNUNET_YES == main_ctx->is->working)
diff --git a/src/exchange-lib/testing_api_trait_fresh_coin.c 
b/src/exchange-lib/testing_api_trait_json.c
similarity index 61%
copy from src/exchange-lib/testing_api_trait_fresh_coin.c
copy to src/exchange-lib/testing_api_trait_json.c
index 985591b..40dddbf 100644
--- a/src/exchange-lib/testing_api_trait_fresh_coin.c
+++ b/src/exchange-lib/testing_api_trait_json.c
@@ -18,8 +18,8 @@
 */
 
 /**
- * @file exchange-lib/testing_api_fresh_coin.c
- * @brief traits to offer fresh conins (after "melt" operations)
+ * @file exchange-lib/testing_api_trait_json.c
+ * @brief offers JSON traits.
  * @author Marcello Stanisci
  */
 #include "platform.h"
@@ -29,46 +29,48 @@
 #include "taler_signatures.h"
 #include "taler_testing_lib.h"
 
-#define TALER_TESTING_TRAIT_FRESH_COINS "fresh-coins"
+#define TALER_TESTING_TRAIT_WIRE_DETAILS "wire-details"
 
 /**
- * Obtain a "number" value from @a cmd.
+ * Obtain wire details from @a cmd.
  *
  * @param cmd command to extract trait from
- * @param selector which coin to pick if @a cmd has multiple on
- * offer
- * @param fresh_coins[out] will point to array of fresh coins
+ * @param index always (?) zero, as one command sticks
+ *        to one bank account
+ * @param wire_details[out] where to write the wire details.
  * @return #GNUNET_OK on success
  */
 int
-TALER_TESTING_get_trait_fresh_coins
+TALER_TESTING_get_trait_wire_details
   (const struct TALER_TESTING_Command *cmd,
    unsigned int index,
-   struct FreshCoin **fresh_coins)
+   const json_t **wire_details)
 {
   return cmd->traits (cmd->cls,
-                      (void **) fresh_coins,
-                      TALER_TESTING_TRAIT_FRESH_COINS,
+                      (void **) wire_details,
+                      TALER_TESTING_TRAIT_WIRE_DETAILS,
                       index);
 }
 
 /**
- * @param selector associate the object with this "tag"
- * @param fresh_coins the array of fresh coins to offer
+ * Offer wire details in a trait.
  *
+ * @param index always (?) zero, as one command sticks
+ *        to one bank account
+ * @param wire_details wire details to offer
  * @return the trait, to be put in the traits array of the command
  */
 struct TALER_TESTING_Trait
-TALER_TESTING_make_trait_fresh_coins
+TALER_TESTING_make_trait_wire_details
   (unsigned int index,
-   struct FreshCoin *fresh_coins)
+   const json_t *wire_details)
 {
   struct TALER_TESTING_Trait ret = {
     .index = index,
-    .trait_name = TALER_TESTING_TRAIT_FRESH_COINS,
-    .ptr = (const void *) fresh_coins
+    .trait_name = TALER_TESTING_TRAIT_WIRE_DETAILS,
+    .ptr = (const json_t *) wire_details
   };
   return ret;
 }
 
-/* end of testing_api_trait_fresh_coin.c */
+/* end of testing_api_trait_json.c */
diff --git a/src/exchange-lib/testing_api_trait_string.c 
b/src/exchange-lib/testing_api_trait_string.c
index 1b1b422..fb5af93 100644
--- a/src/exchange-lib/testing_api_trait_string.c
+++ b/src/exchange-lib/testing_api_trait_string.c
@@ -30,7 +30,6 @@
 #include "taler_signatures.h"
 #include "taler_testing_lib.h"
 
-#define TALER_TESTING_TRAIT_WIRE_DETAILS "wire-details"
 #define TALER_TESTING_TRAIT_CONTRACT_TERMS "contract-terms"
 #define TALER_TESTING_TRAIT_TRANSFER_SUBJECT "transfer-subject"
 #define TALER_TESTING_TRAIT_AMOUNT "amount"
@@ -81,49 +80,6 @@ TALER_TESTING_make_trait_contract_terms
 
 
 /**
- * Obtain wire details from @a cmd.
- *
- * @param cmd command to extract trait from
- * @param index always (?) zero, as one command sticks
- *        to one bank account
- * @param wire_details[out] where to write the wire details.
- * @return #GNUNET_OK on success
- */
-int
-TALER_TESTING_get_trait_wire_details
-  (const struct TALER_TESTING_Command *cmd,
-   unsigned int index,
-   const char **wire_details)
-{
-  return cmd->traits (cmd->cls,
-                      (void **) wire_details,
-                      TALER_TESTING_TRAIT_WIRE_DETAILS,
-                      index);
-}
-
-/**
- * Offer wire details in a trait.
- *
- * @param index always (?) zero, as one command sticks
- *        to one bank account
- * @param wire_details wire details to offer
- * @return the trait, to be put in the traits array of the command
- */
-struct TALER_TESTING_Trait
-TALER_TESTING_make_trait_wire_details
-  (unsigned int index,
-   const char *wire_details)
-{
-  struct TALER_TESTING_Trait ret = {
-    .index = index,
-    .trait_name = TALER_TESTING_TRAIT_WIRE_DETAILS,
-    .ptr = (const void *) wire_details
-  };
-  return ret;
-}
-
-
-/**
  * Obtain a transfer subject from @a cmd.
  *
  * @param cmd command to extract trait from
@@ -289,7 +245,7 @@ TALER_TESTING_make_trait_order_id
   struct TALER_TESTING_Trait ret = {
     .index = index,
     .trait_name = TALER_TESTING_TRAIT_ORDER_ID,
-    .ptr = (const void *) order_id 
+    .ptr = (const void *) order_id
   };
   return ret;
 }
@@ -333,7 +289,7 @@ TALER_TESTING_make_trait_rejected
   struct TALER_TESTING_Trait ret = {
     .index = index,
     .trait_name = TALER_TESTING_TRAIT_REJECTED,
-    .ptr = (const void *) rejected 
+    .ptr = (const void *) rejected
   };
   return ret;
 }
diff --git a/src/exchange-tools/Makefile.am b/src/exchange-tools/Makefile.am
index 8d00415..2c1ff0f 100644
--- a/src/exchange-tools/Makefile.am
+++ b/src/exchange-tools/Makefile.am
@@ -4,7 +4,6 @@ AM_CPPFLAGS = -I$(top_srcdir)/src/include
 pkgcfgdir = $(prefix)/share/taler/config.d/
 
 pkgcfg_DATA = \
-  exchange-signkeys.conf \
   coins.conf
 
 if USE_COVERAGE
@@ -34,6 +33,8 @@ taler_exchange_wire_SOURCES = \
   taler-exchange-wire.c
 taler_exchange_wire_LDADD = \
   $(LIBGCRYPT_LIBS) \
+  $(top_builddir)/src/json/libtalerjson.la \
+  $(top_builddir)/src/exchangedb/libtalerexchangedb.la \
   $(top_builddir)/src/wire/libtalerwire.la \
   $(top_builddir)/src/util/libtalerutil.la \
   -lgnunetjson \
diff --git a/src/exchange-tools/exchange-signkeys.conf 
b/src/exchange-tools/exchange-signkeys.conf
deleted file mode 100644
index 3146f09..0000000
--- a/src/exchange-tools/exchange-signkeys.conf
+++ /dev/null
@@ -1,16 +0,0 @@
-# General data for signing keys.
-[exchange_keys]
-
-# how long is one signkey valid?
-signkey_duration = 4 weeks
-
-# how long are the signatures with the signkey valid?
-legal_duration = 2 years
-
-# how long do we generate denomination and signing keys
-# ahead of time?
-lookahead_sign = 32 weeks 1 day
-
-# how long do we provide to clients denomination and signing keys
-# ahead of time?
-lookahead_provide = 4 weeks 1 day
diff --git a/src/exchange-tools/taler-exchange-keyup.c 
b/src/exchange-tools/taler-exchange-keyup.c
index 5e069af..9842a37 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-2017 GNUnet e.V.
+  Copyright (C) 2014-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
@@ -499,23 +499,23 @@ exchange_keys_update_signkeys ()
 
   if (GNUNET_OK !=
       GNUNET_CONFIGURATION_get_value_time (kcfg,
-                                           "exchange_keys",
+                                           "exchange",
                                            "signkey_duration",
                                            &signkey_duration))
   {
     GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
-                               "exchange_keys",
+                               "exchange",
                                "signkey_duration");
     return GNUNET_SYSERR;
   }
   if (GNUNET_OK !=
       GNUNET_CONFIGURATION_get_value_time (kcfg,
-                                           "exchange_keys",
+                                           "exchange",
                                            "legal_duration",
                                            &legal_duration))
   {
     GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR,
-                               "exchange_keys",
+                               "exchange",
                                "legal_duration",
                                "fails to specify valid timeframe");
     return GNUNET_SYSERR;
@@ -523,7 +523,7 @@ exchange_keys_update_signkeys ()
   if (signkey_duration.rel_value_us > legal_duration.rel_value_us)
   {
     GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR,
-                               "exchange_keys",
+                               "exchange",
                                "legal_duration",
                                "must be longer than signkey_duration");
     return GNUNET_SYSERR;
@@ -926,10 +926,13 @@ create_wire_fee_for_method (void *cls,
 
   if (GNUNET_OK != *ret)
     return;
+  GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+              "Setting up wire fees for `%s'\n",
+              wiremethod);
   last_date = GNUNET_TIME_absolute_add (lookahead_sign_stamp,
                                         max_duration_spend);
   GNUNET_asprintf (&section,
-                   "exchange-wire-%s",
+                   "fees-%s",
                    wiremethod);
   GNUNET_asprintf (&fn,
                    "%s%s.fee",
@@ -1049,6 +1052,43 @@ create_wire_fee_for_method (void *cls,
  * Output the wire fee structure.  Must be run after #max_duration_spend
  * was initialized.
  *
+ * @param cls pointer to `int`, set to #GNUNET_SYSERR on error
+ * @param ai information about enabled accounts
+ */
+static void
+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);
+}
+
+
+/**
+ * Output the wire fee structure.  Must be run after #max_duration_spend
+ * was initialized.
+ *
  * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
  */
 static int
@@ -1057,9 +1097,9 @@ create_wire_fees ()
   int ret;
 
   ret = GNUNET_OK;
-  TALER_WIRE_find_enabled (kcfg,
-                           &create_wire_fee_for_method,
-                           &ret);
+  TALER_EXCHANGEDB_find_accounts (kcfg,
+                                  &create_wire_fee_by_account,
+                                  &ret);
   return ret;
 }
 
@@ -1305,12 +1345,12 @@ run (void *cls,
 
   if (GNUNET_OK !=
       GNUNET_CONFIGURATION_get_value_time (kcfg,
-                                           "exchange_keys",
+                                           "exchange",
                                            "lookahead_sign",
                                            &lookahead_sign))
   {
     GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
-                               "exchange_keys",
+                               "exchange",
                                "lookahead_sign");
     global_ret = 1;
     return;
@@ -1318,7 +1358,7 @@ run (void *cls,
   if (0 == lookahead_sign.rel_value_us)
   {
     GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR,
-                               "exchange_keys",
+                               "exchange",
                                "lookahead_sign",
                                _("must not be zero"));
     global_ret = 1;
diff --git a/src/exchange-tools/taler-exchange-wire.c 
b/src/exchange-tools/taler-exchange-wire.c
index 60244f1..6daf3de 100644
--- a/src/exchange-tools/taler-exchange-wire.c
+++ b/src/exchange-tools/taler-exchange-wire.c
@@ -1,6 +1,6 @@
 /*
   This file is part of TALER
-  Copyright (C) 2015, 2016, 2017 Inria
+  Copyright (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
@@ -24,6 +24,8 @@
 #include "taler_crypto_lib.h"
 #include "taler_util.h"
 #include "taler_wire_lib.h"
+#include "taler_json_lib.h"
+#include "taler_exchangedb_lib.h"
 #include "taler_signatures.h"
 
 
@@ -33,24 +35,75 @@
 static char *masterkeyfile;
 
 /**
- * Account holder information in JSON format.
+ * Private key for signing.
  */
-static json_t *account_holder;
+static struct TALER_MasterPrivateKeyP master_priv;
 
 /**
- * Which wire method is this for?
+ * Return value from main().
  */
-static char *method;
+static int global_ret;
 
-/**
- * Where to write the result.
- */
-static char *output_filename;
 
 /**
- * Return value from main().
+ * Function called with information about a wire account.  Signs
+ * the account's wire details and writes out the JSON file to disk.
+ *
+ * @param cls closure
+ * @param ai account information
  */
-static int global_ret;
+static void
+sign_account_data (void *cls,
+                   const struct TALER_EXCHANGEDB_AccountInfo *ai)
+{
+  json_t *wire;
+  char *json_out;
+  FILE *out;
+
+  if (GNUNET_NO == ai->credit_enabled)
+    return;
+  if (NULL == ai->wire_response_filename)
+  {
+    GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
+                               ai->section_name,
+                               "WIRE_RESPONSE");
+    global_ret = 1;
+    return;
+  }
+  wire = TALER_JSON_wire_signature_make (ai->payto_url,
+                                         &master_priv);
+  json_out = json_dumps (wire,
+                         JSON_INDENT(2));
+  json_decref (wire);
+  GNUNET_assert (NULL != json_out);
+  if (GNUNET_OK !=
+      GNUNET_DISK_directory_create_for_file (ai->wire_response_filename))
+  {
+    GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR,
+                              "mkdir",
+                              ai->wire_response_filename);
+    global_ret = 1;
+    free (json_out);
+    return;
+  }
+
+  out = fopen (ai->wire_response_filename,
+               "w+");
+  if (NULL == out)
+  {
+    GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR,
+                              "fopen",
+                              ai->wire_response_filename);
+    global_ret = 1;
+    free (json_out);
+    return;
+  }
+  fprintf (out,
+          "%s",
+          json_out);
+  fclose (out);
+  free (json_out);
+}
 
 
 /**
@@ -68,11 +121,6 @@ run (void *cls,
      const struct GNUNET_CONFIGURATION_Handle *cfg)
 {
   struct GNUNET_CRYPTO_EddsaPrivateKey *eddsa_priv;
-  struct TALER_MasterPrivateKeyP key;
-  struct TALER_MasterSignatureP sig;
-  char *json_out;
-  struct GNUNET_HashCode salt;
-  struct TALER_WIRE_Plugin *plugin;
 
   if ( (NULL == masterkeyfile) &&
        (GNUNET_OK !=
@@ -86,7 +134,8 @@ run (void *cls,
     global_ret = 1;
     return;
   }
-  if (GNUNET_YES != GNUNET_DISK_file_test (masterkeyfile))
+  if (GNUNET_YES !=
+      GNUNET_DISK_file_test (masterkeyfile))
     GNUNET_log (GNUNET_ERROR_TYPE_INFO,
                 "Exchange master private key `%s' does not exist yet, creating 
it!\n",
                 masterkeyfile);
@@ -99,97 +148,11 @@ run (void *cls,
     global_ret = 1;
     return;
   }
-  if (NULL == method)
-  {
-    json_t *test;
-    const char *m;
-
-    test = json_object_get(account_holder,
-                           "type");
-    if ( (NULL == test) ||
-         (NULL == (m = json_string_value (test))))
-    {
-      fprintf (stderr,
-               "Required -t argument missing\n");
-      global_ret = 1;
-      return;
-    }
-    method = GNUNET_strdup (m);
-  }
-  else
-  {
-    json_object_set_new (account_holder,
-                         "type",
-                         json_string (method));
-  }
-  key.eddsa_priv = *eddsa_priv;
-  GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_NONCE,
-                              &salt,
-                              sizeof (salt));
-  plugin = TALER_WIRE_plugin_load (cfg,
-                                   method);
-  if (NULL == plugin)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_INFO,
-                "Wire transfer method `%s' not supported\n",
-                method);
-    GNUNET_free (method);
-    global_ret = 1;
-    return;
-  }
-  GNUNET_free (method);
-  if (GNUNET_OK !=
-      plugin->sign_wire_details (plugin->cls,
-                                 account_holder,
-                                 &key,
-                                 &salt,
-                                 &sig))
-  {
-    /* sign function should have logged applicable errors */
-    json_decref (account_holder);
-    TALER_WIRE_plugin_unload (plugin);
-    global_ret = 1;
-    return;
-  }
-  TALER_WIRE_plugin_unload (plugin);
+  master_priv.eddsa_priv = *eddsa_priv;
+  TALER_EXCHANGEDB_find_accounts (cfg,
+                                  &sign_account_data,
+                                  NULL);
   GNUNET_free (eddsa_priv);
-
-  /* add signature and salt to JSON message */
-  json_object_set_new (account_holder,
-                       "salt",
-                       GNUNET_JSON_from_data (&salt,
-                                              sizeof (salt)));
-  json_object_set_new (account_holder,
-                       "sig",
-                       GNUNET_JSON_from_data (&sig,
-                                              sizeof (sig)));
-
-  /* dump result to stdout */
-  json_out = json_dumps (account_holder,
-                         JSON_INDENT(2));
-  json_decref (account_holder);
-  GNUNET_assert (NULL != json_out);
-
-  if (NULL != output_filename)
-  {
-    if (NULL != stdout)
-      fclose (stdout);
-    stdout = fopen (output_filename,
-                   "w+");
-    if (NULL == stdout)
-    {
-      fprintf (stderr,
-               "Failed to open `%s': %s\n",
-               output_filename,
-               STRERROR (errno));
-      return;
-    }
-  }
-  fprintf (stdout,
-          "%s",
-          json_out);
-  fflush (stdout);
-  free (json_out);
 }
 
 
@@ -206,27 +169,11 @@ main (int argc,
       char *const *argv)
 {
   const struct GNUNET_GETOPT_CommandLineOption options[] = {
-    GNUNET_GETOPT_option_mandatory
-    (GNUNET_JSON_getopt ('j',
-                         "json",
-                         "JSON",
-                         "account information in JSON format",
-                         &account_holder)),
     GNUNET_GETOPT_option_filename ('m',
                                    "master-key",
                                    "FILENAME",
                                    "master key file (private key)",
                                    &masterkeyfile),
-    GNUNET_GETOPT_option_string ('t',
-                                 "type",
-                                 "METHOD",
-                                 "which wire transfer method (i.e. 'test' or 
'sepa') is this for?",
-                                 &method),
-    GNUNET_GETOPT_option_filename ('o',
-                                   "output",
-                                   "FILENAME",
-                                   "where to write the result",
-                                   &output_filename),
     GNUNET_GETOPT_OPTION_END
   };
 
diff --git a/src/exchange/.gitignore b/src/exchange/.gitignore
index e54fe49..b0fe0a0 100644
--- a/src/exchange/.gitignore
+++ b/src/exchange/.gitignore
@@ -6,3 +6,4 @@ taler-exchange-reservemod
 taler-exchange-httpd
 taler-exchange-wirewatch
 test_taler_exchange_wirewatch-postgres
+test_taler_exchange_httpd_home/.config/taler/account-1.json
diff --git a/src/exchange/exchange.conf b/src/exchange/exchange.conf
index 39c496e..5b9ff9b 100644
--- a/src/exchange/exchange.conf
+++ b/src/exchange/exchange.conf
@@ -36,3 +36,18 @@ PORT = 8081
 # Required for wire transfers as we need to include it in the wire
 # transfers to enable tracking.
 BASE_URL = http://localhost:8081/
+
+
+# how long is one signkey valid?
+SIGNKEY_DURATION = 4 weeks
+
+# how long are the signatures with the signkey valid?
+LEGAL_DURATION = 2 years
+
+# how long do we generate denomination and signing keys
+# ahead of time?
+LOOKAHEAD_SIGN = 32 weeks 1 day
+
+# how long do we provide to clients denomination and signing keys
+# ahead of time?
+LOOKAHEAD_PROVIDE = 4 weeks 1 day
diff --git a/src/exchange/taler-exchange-aggregator.c 
b/src/exchange/taler-exchange-aggregator.c
index 49cbb2b..805577a 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, 2017 GNUnet e.V.
+  Copyright (C) 2016-2018 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
@@ -30,19 +30,19 @@
 
 
 /**
- * Information we keep for each loaded wire plugin.
+ * Information we keep for each supported account.
  */
-struct WirePlugin
+struct WireAccount
 {
   /**
-   * Plugins are kept in a DLL.
+   * Accounts are kept in a DLL.
    */
-  struct WirePlugin *next;
+  struct WireAccount *next;
 
   /**
    * Plugins are kept in a DLL.
    */
-  struct WirePlugin *prev;
+  struct WireAccount *prev;
 
   /**
    * Handle to the plugin.
@@ -50,14 +50,14 @@ struct WirePlugin
   struct TALER_WIRE_Plugin *wire_plugin;
 
   /**
-   * Name of the plugin.
+   * Wire transfer fee structure.
    */
-  char *type;
+  struct TALER_EXCHANGEDB_AggregateFees *af;
 
   /**
-   * Wire transfer fee structure.
+   * Name of the section that configures this account.
    */
-  struct TALER_EXCHANGEDB_AggregateFees *af;
+  char *section_name;
 
 };
 
@@ -82,7 +82,7 @@ struct WirePrepareData
   /**
    * Wire plugin used for this preparation.
    */
-  struct WirePlugin *wp;
+  struct WireAccount *wa;
 
   /**
    * Row ID of the transfer.
@@ -149,9 +149,9 @@ struct AggregationUnit
   json_t *wire;
 
   /**
-   * Wire plugin to be used for the preparation.
+   * Wire account to be used for the preparation.
    */
-  struct WirePlugin *wp;
+  struct WireAccount *wa;
 
   /**
    * Database session for all of our transactions.
@@ -200,12 +200,12 @@ struct CloseTransferContext
   /**
    * Wire transfer method.
    */
-  char *type;
+  char *method;
 
   /**
-   * Wire plugin used for closing the reserve.
+   * Wire account used for closing the reserve.
    */
-  struct WirePlugin *wp;
+  struct WireAccount *wa;
 };
 
 
@@ -238,12 +238,12 @@ static struct TALER_EXCHANGEDB_Plugin *db_plugin;
 /**
  * Head of list of loaded wire plugins.
  */
-static struct WirePlugin *wp_head;
+static struct WireAccount *wa_head;
 
 /**
  * Tail of list of loaded wire plugins.
  */
-static struct WirePlugin *wp_tail;
+static struct WireAccount *wa_tail;
 
 /**
  * Next task to run, if any.
@@ -290,49 +290,22 @@ static int reserves_idle;
 static unsigned int aggregation_limit = 
TALER_EXCHANGEDB_MATCHING_DEPOSITS_LIMIT;
 
 
-/**
- * Extract wire plugin type from @a wire address
- *
- * @param wire a wire address
- * @return NULL if @a wire is ill-formed
- */
-const char *
-extract_type (const json_t *wire)
-{
-  const char *type;
-  json_t *t;
-
-  t = json_object_get (wire, "type");
-  if (NULL == t)
-  {
-    GNUNET_break (0);
-    return NULL;
-  }
-  type = json_string_value (t);
-  if (NULL == type)
-  {
-    GNUNET_break (0);
-    return NULL;
-  }
-  return type;
-}
-
 
 /**
  * Advance the "af" pointer in @a wp to point to the
  * currently valid record.
  *
- * @param wp wire transfer fee data structure to update
+ * @param wa wire transfer fee data structure to update
  * @param now timestamp to update fees to
  */
 static void
-advance_fees (struct WirePlugin *wp,
+advance_fees (struct WireAccount *wa,
               struct GNUNET_TIME_Absolute now)
 {
   struct TALER_EXCHANGEDB_AggregateFees *af;
 
   /* First, try to see if we have current fee information in memory */
-  af = wp->af;
+  af = wa->af;
   while ( (NULL != af) &&
           (af->end_date.abs_value_us < now.abs_value_us) )
   {
@@ -341,7 +314,7 @@ advance_fees (struct WirePlugin *wp,
     GNUNET_free (af);
     af = n;
   }
-  wp->af = af;
+  wa->af = af;
 }
 
 
@@ -354,28 +327,28 @@ advance_fees (struct WirePlugin *wp,
  * @return transaction status
  */
 static enum GNUNET_DB_QueryStatus
-update_fees (struct WirePlugin *wp,
+update_fees (struct WireAccount *wa,
              struct GNUNET_TIME_Absolute now,
              struct TALER_EXCHANGEDB_Session *session)
 {
   enum GNUNET_DB_QueryStatus qs;
 
-  advance_fees (wp,
+  advance_fees (wa,
                 now);
-  if (NULL != wp->af)
+  if (NULL != wa->af)
     return GNUNET_DB_STATUS_SUCCESS_ONE_RESULT;
   /* Let's try to load it from disk... */
-  wp->af = TALER_EXCHANGEDB_fees_read (cfg,
-                                       wp->type);
-  advance_fees (wp,
+  wa->af = TALER_EXCHANGEDB_fees_read (cfg,
+                                       wa->wire_plugin->method);
+  advance_fees (wa,
                 now);
-  for (struct TALER_EXCHANGEDB_AggregateFees *p = wp->af;
+  for (struct TALER_EXCHANGEDB_AggregateFees *p = wa->af;
        NULL != p;
        p = p->next)
   {
     qs = db_plugin->insert_wire_fee (db_plugin->cls,
                                     session,
-                                    wp->type,
+                                    wa->wire_plugin->method,
                                     p->start_date,
                                     p->end_date,
                                     &p->wire_fee,
@@ -383,53 +356,94 @@ update_fees (struct WirePlugin *wp,
                                     &p->master_sig);
     if (qs < 0)
     {
-      TALER_EXCHANGEDB_fees_free (wp->af);
-      wp->af = NULL;
+      TALER_EXCHANGEDB_fees_free (wa->af);
+      wa->af = NULL;
       return qs;
     }
   }
-  if (NULL != wp->af)
+  if (NULL != wa->af)
     return GNUNET_DB_STATUS_SUCCESS_ONE_RESULT;
   GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
               "Failed to find current wire transfer fees for `%s'\n",
-              wp->type);
+              wa->wire_plugin->method);
   return GNUNET_DB_STATUS_SUCCESS_NO_RESULTS;
 }
 
 
 /**
- * Find the wire plugin for the given wire address.
+ * Find the wire plugin for the given payto:// URL
+ *
+ * @param method wire method we need an account for
+ * @return NULL on error
+ */
+static struct WireAccount *
+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))
+      return wa;
+  return NULL;
+}
+
+
+/**
+ * Find the wire plugin for the given payto:// URL
  *
- * @param type wire plugin type we need a plugin for
+ * @param url wire address we need an account for
  * @return NULL on error
  */
-static struct WirePlugin *
-find_plugin (const char *type)
+static struct WireAccount *
+find_account_by_url (const char *url)
 {
-  struct WirePlugin *wp;
+  char *method;
+  struct WireAccount *wa;
 
-  if (NULL == type)
+  method = TALER_WIRE_payto_get_method (url);
+  if (NULL == method)
+  {
+    fprintf (stderr,
+             "Invalid payto:// URL `%s'\n",
+             url);
     return NULL;
-  for (wp = wp_head; NULL != wp; wp = wp->next)
-    if (0 == strcmp (type,
-                     wp->type))
-      return wp;
-  wp = GNUNET_new (struct WirePlugin);
-  wp->wire_plugin = TALER_WIRE_plugin_load (cfg,
-                                            type);
-  if (NULL == wp->wire_plugin)
+  }
+  wa = find_account_by_method (method);
+  GNUNET_free (method);
+  return wa;
+}
+
+
+/**
+ * Function called with information about a wire account.  Adds the
+ * account to our list (if it is enabled and we can load the plugin).
+ *
+ * @param cls closure, NULL
+ * @param ai account information
+ */
+static void
+add_account_cb (void *cls,
+                const struct TALER_EXCHANGEDB_AccountInfo *ai)
+{
+  struct WireAccount *wa;
+
+  (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)
   {
     fprintf (stderr,
              "Failed to load wire plugin for `%s'\n",
-             type);
-    GNUNET_free (wp);
-    return NULL;
+             ai->plugin_name);
+    GNUNET_free (wa);
+    return;
   }
-  wp->type = GNUNET_strdup (type);
-  GNUNET_CONTAINER_DLL_insert (wp_head,
-                               wp_tail,
-                               wp);
-  return wp;
+  wa->section_name = GNUNET_strdup (ai->section_name);
+  GNUNET_CONTAINER_DLL_insert (wa_head,
+                               wa_tail,
+                               wa);
 }
 
 
@@ -471,7 +485,7 @@ shutdown_task (void *cls)
   {
     if (NULL != wpd->eh)
     {
-      wpd->wp->wire_plugin->execute_wire_transfer_cancel 
(wpd->wp->wire_plugin->cls,
+      wpd->wa->wire_plugin->execute_wire_transfer_cancel 
(wpd->wa->wire_plugin->cls,
                                                           wpd->eh);
       wpd->eh = NULL;
     }
@@ -484,7 +498,7 @@ shutdown_task (void *cls)
   {
     if (NULL != au->ph)
     {
-      au->wp->wire_plugin->prepare_wire_transfer_cancel 
(au->wp->wire_plugin->cls,
+      au->wa->wire_plugin->prepare_wire_transfer_cancel 
(au->wa->wire_plugin->cls,
                                                          au->ph);
       au->ph = NULL;
     }
@@ -494,29 +508,29 @@ shutdown_task (void *cls)
   }
   if (NULL != ctc)
   {
-    ctc->wp->wire_plugin->prepare_wire_transfer_cancel 
(ctc->wp->wire_plugin->cls,
+    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->type);
+    GNUNET_free (ctc->method);
     GNUNET_free (ctc);
     ctc = NULL;
   }
   TALER_EXCHANGEDB_plugin_unload (db_plugin);
 
   {
-    struct WirePlugin *wp;
+    struct WireAccount *wa;
 
-    while (NULL != (wp = wp_head))
+    while (NULL != (wa = wa_head))
     {
-      GNUNET_CONTAINER_DLL_remove (wp_head,
-                                   wp_tail,
-                                   wp);
-      TALER_WIRE_plugin_unload (wp->wire_plugin);
-      TALER_EXCHANGEDB_fees_free (wp->af);
-      GNUNET_free (wp->type);
-      GNUNET_free (wp);
+      GNUNET_CONTAINER_DLL_remove (wa_head,
+                                   wa_tail,
+                                   wa);
+      TALER_WIRE_plugin_unload (wa->wire_plugin);
+      TALER_EXCHANGEDB_fees_free (wa->af);
+      GNUNET_free (wa->section_name);
+      GNUNET_free (wa);
     }
   }
   GNUNET_CONFIGURATION_destroy (cfg);
@@ -568,7 +582,16 @@ exchange_serve_process_config ()
     TALER_EXCHANGEDB_plugin_unload (db_plugin);
     return GNUNET_SYSERR;
   }
-
+  TALER_EXCHANGEDB_find_accounts (cfg,
+                                  &add_account_cb,
+                                  NULL);
+  if (NULL == wa_head)
+  {
+    fprintf (stderr,
+             "No wire accounts configured for debit!\n");
+    TALER_EXCHANGEDB_plugin_unload (db_plugin);
+    return GNUNET_SYSERR;
+  }
   return GNUNET_OK;
 }
 
@@ -677,16 +700,13 @@ deposit_cb (void *cls,
   }
 
   GNUNET_assert (NULL == au->wire);
-  au->wire = json_incref ((json_t *) wire);
-  if (GNUNET_OK !=
-      TALER_JSON_hash (au->wire,
-                       &au->h_wire))
+  if (NULL == (au->wire = json_incref ((json_t *) wire)))
   {
     GNUNET_break (0);
-    json_decref (au->wire);
-    au->wire = NULL;
     return GNUNET_DB_STATUS_HARD_ERROR;
   }
+  TALER_JSON_wire_signature_hash (wire,
+                                  &au->h_wire);
   GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_NONCE,
                               &au->wtid,
                               sizeof (au->wtid));
@@ -695,15 +715,23 @@ deposit_cb (void *cls,
               TALER_B2S (&au->wtid),
               TALER_amount2s (amount_with_fee),
               (unsigned long long) row_id);
+  {
+    char *url;
 
-  au->wp = find_plugin (extract_type (au->wire));
-  if (NULL == au->wp)
+    url = TALER_JSON_wire_to_payto (au->wire);
+    au->wa = find_account_by_url (url);
+    GNUNET_free (url);
+  }
+  if (NULL == au->wa)
+  {
+    GNUNET_break (0);
     return GNUNET_DB_STATUS_HARD_ERROR;
+  }
 
   /* make sure we have current fees */
   au->execution_time = GNUNET_TIME_absolute_get ();
   (void) GNUNET_TIME_round_abs (&au->execution_time);
-  qs = update_fees (au->wp,
+  qs = update_fees (au->wa,
                    au->execution_time,
                    au->session);
   if (qs <= 0)
@@ -713,7 +741,7 @@ deposit_cb (void *cls,
     GNUNET_break (GNUNET_DB_STATUS_SOFT_ERROR == qs);
     return qs;
   }
-  au->wire_fee = au->wp->af->wire_fee;
+  au->wire_fee = au->wa->af->wire_fee;
 
   qs = db_plugin->insert_aggregation_tracking (db_plugin->cls,
                                               au->session,
@@ -942,7 +970,7 @@ prepare_close_cb (void *cls,
     db_plugin->rollback (db_plugin->cls,
                          ctc->session);
     /* start again */
-    GNUNET_free (ctc->type);
+    GNUNET_free (ctc->method);
     GNUNET_free (ctc);
     ctc = NULL;
     task = GNUNET_SCHEDULER_add_now (&run_aggregation,
@@ -953,7 +981,7 @@ prepare_close_cb (void *cls,
   /* Commit our intention to execute the wire transfer! */
   qs = db_plugin->wire_prepare_data_insert (db_plugin->cls,
                                            ctc->session,
-                                           ctc->type,
+                                           ctc->method,
                                            buf,
                                            buf_size);
   if (GNUNET_DB_STATUS_HARD_ERROR == qs)
@@ -963,7 +991,7 @@ prepare_close_cb (void *cls,
                          ctc->session);
     global_ret = GNUNET_SYSERR;
     GNUNET_SCHEDULER_shutdown ();
-    GNUNET_free (ctc->type);
+    GNUNET_free (ctc->method);
     GNUNET_free (ctc);
     ctc = NULL;
     return;
@@ -975,7 +1003,7 @@ prepare_close_cb (void *cls,
     /* start again */
     task = GNUNET_SCHEDULER_add_now (&run_aggregation,
                                      NULL);
-    GNUNET_free (ctc->type);
+    GNUNET_free (ctc->method);
     GNUNET_free (ctc);
     ctc = NULL;
     return;
@@ -983,7 +1011,7 @@ prepare_close_cb (void *cls,
 
   /* finally commit */
   (void) commit_or_warn (ctc->session);
-  GNUNET_free (ctc->type);
+  GNUNET_free (ctc->method);
   GNUNET_free (ctc);
   ctc = NULL;
   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
@@ -1029,7 +1057,7 @@ static enum GNUNET_DB_QueryStatus
 expired_reserve_cb (void *cls,
                    const struct TALER_ReservePublicKeyP *reserve_pub,
                    const struct TALER_Amount *left,
-                   const json_t *account_details,
+                   const char *account_details,
                    struct GNUNET_TIME_Absolute expiration_date)
 {
   struct ExpiredReserveContext *erc = cls;
@@ -1040,24 +1068,15 @@ expired_reserve_cb (void *cls,
   const struct TALER_Amount *closing_fee;
   int ret;
   enum GNUNET_DB_QueryStatus qs;
-  const char *type;
-  struct WirePlugin *wp;
+  struct WireAccount *wa;
 
   GNUNET_assert (NULL == ctc);
   now = GNUNET_TIME_absolute_get ();
   (void) GNUNET_TIME_round_abs (&now);
 
   /* lookup wire plugin */
-  type = extract_type (account_details);
-  if (NULL == type)
-  {
-    GNUNET_break (0);
-    global_ret = GNUNET_SYSERR;
-    GNUNET_SCHEDULER_shutdown ();
-    return GNUNET_DB_STATUS_HARD_ERROR;
-  }
-  wp = find_plugin (type);
-  if (NULL == wp)
+  wa = find_account_by_url (account_details);
+  if (NULL == wa)
   {
     GNUNET_break (0);
     global_ret = GNUNET_SYSERR;
@@ -1066,7 +1085,7 @@ expired_reserve_cb (void *cls,
   }
 
   /* lookup `closing_fee` */
-  qs = update_fees (wp,
+  qs = update_fees (wa,
                    now,
                    session);
   if (qs <= 0)
@@ -1079,7 +1098,7 @@ expired_reserve_cb (void *cls,
       GNUNET_SCHEDULER_shutdown ();
     return qs;
   }
-  closing_fee = &wp->af->closing_fee;
+  closing_fee = &wa->af->closing_fee;
 
   /* calculate transfer amount */
   ret = TALER_amount_subtract (&amount_without_fee,
@@ -1124,7 +1143,7 @@ expired_reserve_cb (void *cls,
   {
     /* success, perform wire transfer */
     if (GNUNET_SYSERR ==
-       wp->wire_plugin->amount_round (wp->wire_plugin->cls,
+       wa->wire_plugin->amount_round (wa->wire_plugin->cls,
                                       &amount_without_fee))
     {
       GNUNET_break (0);
@@ -1133,11 +1152,12 @@ expired_reserve_cb (void *cls,
       return GNUNET_DB_STATUS_HARD_ERROR;
     }
     ctc = GNUNET_new (struct CloseTransferContext);
-    ctc->wp = wp;
+    ctc->wa = wa;
     ctc->session = session;
-    ctc->type = GNUNET_strdup (type);
+    ctc->method = TALER_WIRE_payto_get_method (account_details);
     ctc->ph
-      = wp->wire_plugin->prepare_wire_transfer (wp->wire_plugin->cls,
+      = wa->wire_plugin->prepare_wire_transfer (wa->wire_plugin->cls,
+                                                wa->section_name,
                                                account_details,
                                                &amount_without_fee,
                                                exchange_base_url,
@@ -1149,7 +1169,7 @@ expired_reserve_cb (void *cls,
       GNUNET_break (0);
       global_ret = GNUNET_SYSERR;
       GNUNET_SCHEDULER_shutdown ();
-      GNUNET_free (ctc->type);
+      GNUNET_free (ctc->method);
       GNUNET_free (ctc);
       ctc = NULL;
       return GNUNET_DB_STATUS_HARD_ERROR;
@@ -1398,7 +1418,7 @@ run_aggregation (void *cls)
                                &au->total_amount,
                                &au->wire_fee)) ||
        (GNUNET_SYSERR ==
-        au->wp->wire_plugin->amount_round (au->wp->wire_plugin->cls,
+        au->wa->wire_plugin->amount_round (au->wa->wire_plugin->cls,
                                            &au->final_amount)) ||
        ( (0 == au->final_amount.value) &&
          (0 == au->final_amount.fraction) ) )
@@ -1479,22 +1499,28 @@ run_aggregation (void *cls)
                 TALER_B2S (&au->merchant_pub));
     GNUNET_free (amount_s);
   }
-  au->ph = au->wp->wire_plugin->prepare_wire_transfer 
(au->wp->wire_plugin->cls,
-                                                       au->wire,
-                                                       &au->final_amount,
-                                                       exchange_base_url,
-                                                       &au->wtid,
-                                                       &prepare_cb,
-                                                       au);
+  {
+    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);
+    GNUNET_free (url);
+  }
   if (NULL == au->ph)
   {
-    GNUNET_break (0); /* why? how to best recover? */
+    /* something went very wrong, likely bad configuration,
+       abort */
     db_plugin->rollback (db_plugin->cls,
                          session);
     cleanup_au ();
-    /* start again */
-    task = GNUNET_SCHEDULER_add_now (&run_aggregation,
-                                     NULL);
+    GNUNET_SCHEDULER_shutdown ();
     return;
   }
   /* otherwise we continue with #prepare_cb(), see below */
@@ -1536,7 +1562,7 @@ prepare_cb (void *cls,
   /* Commit our intention to execute the wire transfer! */
   qs = db_plugin->wire_prepare_data_insert (db_plugin->cls,
                                            session,
-                                           au->wp->type,
+                                           au->wa->wire_plugin->method,
                                            buf,
                                            buf_size);
   /* Commit the WTID data to 'wire_out' to finally satisfy aggregation
@@ -1547,6 +1573,7 @@ prepare_cb (void *cls,
                                             au->execution_time,
                                             &au->wtid,
                                             au->wire,
+                                             au->wa->section_name,
                                             &au->final_amount);
   cleanup_au ();
   if (GNUNET_DB_STATUS_SOFT_ERROR == qs)
@@ -1711,8 +1738,8 @@ wire_prepare_cb (void *cls,
   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
               "Starting wire transfer %llu\n",
               (unsigned long long) rowid);
-  wpd->wp = find_plugin (wire_method);
-  if (NULL == wpd->wp)
+  wpd->wa = find_account_by_method (wire_method);
+  if (NULL == wpd->wa)
   {
     /* Should really never happen here, as when we get
        here the plugin should be in the cache. */
@@ -1725,7 +1752,7 @@ wire_prepare_cb (void *cls,
     wpd = NULL;
     return;
   }
-  wpd->eh = wpd->wp->wire_plugin->execute_wire_transfer 
(wpd->wp->wire_plugin->cls,
+  wpd->eh = wpd->wa->wire_plugin->execute_wire_transfer 
(wpd->wa->wire_plugin->cls,
                                                          buf,
                                                          buf_size,
                                                          &wire_confirm_cb,
diff --git a/src/exchange/taler-exchange-httpd.c 
b/src/exchange/taler-exchange-httpd.c
index 823f124..cb8ba28 100644
--- a/src/exchange/taler-exchange-httpd.c
+++ b/src/exchange/taler-exchange-httpd.c
@@ -472,13 +472,12 @@ parse_port_config (const char *section,
     if (GNUNET_OK !=
         GNUNET_CONFIGURATION_get_value_string (cfg,
                                                section,
-                                               "unixpath_mode",
+                                               "UNIXPATH_MODE",
                                                &modestring))
     {
-      GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR,
+      GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
                                  section,
-                                 "unixpath_mode",
-                                 "unixpath_mode required");
+                                 "UNIXPATH_MODE");
       return GNUNET_SYSERR;
     }
     errno = 0;
@@ -487,8 +486,8 @@ parse_port_config (const char *section,
     {
       GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR,
                                  section,
-                                 "unixpath_mode",
-                                 "unixpath_mode required");
+                                 "UNIXPATH_MODE",
+                                 "must be octal number");
       GNUNET_free (modestring);
       return GNUNET_SYSERR;
     }
@@ -526,7 +525,7 @@ exchange_serve_process_config ()
   if (GNUNET_OK !=
       GNUNET_CONFIGURATION_get_value_string (cfg,
                                              "taler",
-                                             "currency",
+                                             "CURRENCY",
                                              &TEH_exchange_currency_string))
   {
     GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
@@ -545,7 +544,7 @@ exchange_serve_process_config ()
   if (GNUNET_OK !=
       GNUNET_CONFIGURATION_get_value_string (cfg,
                                              "exchange",
-                                             "master_public_key",
+                                             "MASTER_PUBLIC_KEY",
                                              &TEH_master_public_key_str))
   {
     GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
diff --git a/src/exchange/taler-exchange-httpd_deposit.c 
b/src/exchange/taler-exchange-httpd_deposit.c
index 277430b..8bf4771 100644
--- a/src/exchange/taler-exchange-httpd_deposit.c
+++ b/src/exchange/taler-exchange-httpd_deposit.c
@@ -402,9 +402,12 @@ TEH_DEPOSIT_handler_deposit (struct TEH_RequestHandler *rh,
                              &json);
   if (GNUNET_SYSERR == res)
     return MHD_NO;
-  if ( (GNUNET_NO == res) || (NULL == json) )
+  if ( (GNUNET_NO == res) ||
+       (NULL == json) )
     return MHD_YES;
-  memset (&deposit, 0, sizeof (deposit));
+  memset (&deposit,
+          0,
+          sizeof (deposit));
   res = TEH_PARSE_json_data (connection,
                              json,
                              spec);
@@ -426,7 +429,6 @@ TEH_DEPOSIT_handler_deposit (struct TEH_RequestHandler *rh,
 
   if (TALER_EC_NONE !=
       (ec = TEH_json_validate_wireformat (wire,
-                                          GNUNET_NO,
                                           &emsg)))
   {
     GNUNET_JSON_parse_free (spec);
@@ -446,8 +448,8 @@ TEH_DEPOSIT_handler_deposit (struct TEH_RequestHandler *rh,
                                            "timestamp");
   }
   if (GNUNET_OK !=
-      TALER_JSON_hash (wire,
-                       &my_h_wire))
+      TALER_JSON_wire_signature_hash (wire,
+                                      &my_h_wire))
   {
     TALER_LOG_WARNING ("Failed to parse JSON wire format specification for 
/deposit request\n");
     GNUNET_JSON_parse_free (spec);
diff --git a/src/exchange/taler-exchange-httpd_responses.c 
b/src/exchange/taler-exchange-httpd_responses.c
index c7874ed..99ee08a 100644
--- a/src/exchange/taler-exchange-httpd_responses.c
+++ b/src/exchange/taler-exchange-httpd_responses.c
@@ -148,7 +148,7 @@ TEH_RESPONSE_reply_json (struct MHD_Connection *connection,
                         JSON_INDENT(2));
   if (NULL == json_str)
   {
-    GNUNET_break (0);
+    GNUNET_assert (0);
     return MHD_NO;
   }
   json_len = strlen (json_str);
@@ -733,10 +733,10 @@ TEH_RESPONSE_compile_reserve_history (const struct 
TALER_EXCHANGEDB_ReserveHisto
       ret |= 1;
       GNUNET_assert (0 ==
                      json_array_append_new (json_history,
-                                            json_pack ("{s:s, s:o, s:O, s:o, 
s:o}",
+                                            json_pack ("{s:s, s:o, s:s, s:o, 
s:o}",
                                                        "type", "DEPOSIT",
                                                        "timestamp", 
GNUNET_JSON_from_time_abs (pos->details.bank->execution_date),
-                                                       
"sender_account_details", pos->details.bank->sender_account_details,
+                                                       "sender_account_url", 
pos->details.bank->sender_account_details,
                                                        "wire_reference", 
GNUNET_JSON_from_data (pos->details.bank->wire_reference,
                                                                                
                 pos->details.bank->wire_reference_size),
                                                        "amount", 
TALER_JSON_from_amount (&pos->details.bank->amount))));
@@ -858,14 +858,9 @@ TEH_RESPONSE_compile_reserve_history (const struct 
TALER_EXCHANGEDB_ReserveHisto
        TALER_amount_hton (&rcc.closing_fee,
                           &pos->details.closing->closing_fee);
        rcc.reserve_pub = pos->details.closing->reserve_pub;
-       if (GNUNET_OK !=
-            TALER_JSON_hash (pos->details.closing->receiver_account_details,
-                             &rcc.h_wire))
-        {
-          GNUNET_break (0);
-          json_decref (json_history);
-          return NULL;
-        }
+        GNUNET_CRYPTO_hash (pos->details.closing->receiver_account_details,
+                            strlen 
(pos->details.closing->receiver_account_details) + 1,
+                            &rcc.h_wire);
        rcc.wtid = pos->details.closing->wtid;
        if (GNUNET_OK !=
            TEH_KS_sign (&rcc.purpose,
diff --git a/src/exchange/taler-exchange-httpd_track_transfer.c 
b/src/exchange/taler-exchange-httpd_track_transfer.c
index 493febc..429c86f 100644
--- a/src/exchange/taler-exchange-httpd_track_transfer.c
+++ b/src/exchange/taler-exchange-httpd_track_transfer.c
@@ -1,6 +1,6 @@
 /*
   This file is part of TALER
-  Copyright (C) 2014-2017 GNUnet e.V.
+  Copyright (C) 2014-2018 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
@@ -28,6 +28,7 @@
 #include "taler-exchange-httpd_keystate.h"
 #include "taler-exchange-httpd_track_transfer.h"
 #include "taler-exchange-httpd_responses.h"
+#include "taler_wire_lib.h"
 
 
 /**
@@ -236,8 +237,8 @@ struct WtidTransactionContext
  * @param cls our context for transmission
  * @param rowid which row in the DB is the information from (for diagnostics)
  * @param merchant_pub public key of the merchant (should be same for all 
callbacks with the same @e cls)
- * @param wire_method which wire plugin was used
  * @param h_wire hash of wire transfer details of the merchant (should be same 
for all callbacks with the same @e cls)
+ * @param wire where the funds were sent
  * @param exec_time execution time of the wire transfer (should be same for 
all callbacks with the same @e cls)
  * @param h_contract_terms which proposal was this payment about
  * @param coin_pub which public key was this payment about
@@ -248,8 +249,8 @@ static void
 handle_transaction_data (void *cls,
                          uint64_t rowid,
                          const struct TALER_MerchantPublicKeyP *merchant_pub,
-                         const char *wire_method,
                          const struct GNUNET_HashCode *h_wire,
+                         const json_t *wire,
                          struct GNUNET_TIME_Absolute exec_time,
                          const struct GNUNET_HashCode *h_contract_terms,
                          const struct TALER_CoinSpendPublicKeyP *coin_pub,
@@ -259,15 +260,22 @@ handle_transaction_data (void *cls,
   struct WtidTransactionContext *ctx = cls;
   struct TALER_Amount delta;
   struct TEH_TrackTransferDetail *wdd;
+  char *wire_method;
 
   if (GNUNET_SYSERR == ctx->is_valid)
     return;
+  if (NULL == (wire_method = TALER_JSON_wire_to_method (wire)))
+  {
+    GNUNET_break (0);
+    ctx->is_valid = GNUNET_SYSERR;
+    return;
+  }
   if (GNUNET_NO == ctx->is_valid)
   {
     ctx->merchant_pub = *merchant_pub;
     ctx->h_wire = *h_wire;
     ctx->exec_time = exec_time;
-    ctx->wire_method = GNUNET_strdup (wire_method);
+    ctx->wire_method = wire_method;
     ctx->is_valid = GNUNET_YES;
     if (GNUNET_OK !=
         TALER_amount_subtract (&ctx->total,
@@ -292,8 +300,10 @@ handle_transaction_data (void *cls,
     {
       GNUNET_break (0);
       ctx->is_valid = GNUNET_SYSERR;
+      GNUNET_free (wire_method);
       return;
     }
+    GNUNET_free (wire_method);
     if (GNUNET_OK !=
         TALER_amount_subtract (&delta,
                                deposit_value,
diff --git a/src/exchange/taler-exchange-httpd_validation.c 
b/src/exchange/taler-exchange-httpd_validation.c
index bef6aec..7daa18a 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 GNUnet e.V.
+  Copyright (C) 2016, 2017, 2018 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
@@ -24,6 +24,8 @@
 #include "taler-exchange-httpd.h"
 #include "taler-exchange-httpd_validation.h"
 #include "taler-exchange-httpd_wire.h"
+#include "taler_exchangedb_lib.h"
+#include "taler_json_lib.h"
 #include "taler_wire_lib.h"
 
 
@@ -44,17 +46,13 @@ struct Plugin
   struct Plugin *prev;
 
   /**
-   * Type of the wireformat.
-   */
-  char *type;
-
-  /**
    * Pointer to the plugin.
    */
   struct TALER_WIRE_Plugin *plugin;
 
 };
 
+
 /**
  * Head of DLL of wire plugins.
  */
@@ -65,50 +63,162 @@ static struct Plugin *wire_head;
  */
 static struct Plugin *wire_tail;
 
+/**
+ * Array of wire methods supported by this exchange.
+ */
+static json_t *wire_accounts_array;
+
+/**
+ * Object mapping wire methods to the respective fee structure.
+ */
+static json_t *wire_fee_object;
+
 
 /**
- * Load plugin @a name.
+ * Load wire fees for @a method.
+ *
+ * @param method wire method to load fee structure for
+ * @return #GNUNET_OK on success
+ */
+static int
+load_fee (const char *method)
+{
+  json_t *fees;
+
+  if (NULL != json_object_get (wire_fee_object,
+                               method))
+    return GNUNET_OK; /* already have them */
+  fees = TEH_WIRE_get_fees (method);
+  if (NULL == fees)
+    return GNUNET_SYSERR;
+  /* Add fees to #wire_fee_object */
+  GNUNET_assert (-1 !=
+                 json_object_set_new (wire_fee_object,
+                                      method,
+                                      fees));
+  return GNUNET_OK;
+}
+
+
+/**
+ * Initialize account; checks if @ai has /wire information, and if so,
+ * adds the /wire information (if included) to our responses. Also, if
+ * the account is debitable, we try to load the plugin.
  *
  * @param cls pointer to `int` to set to #GNUNET_SYSERR on errors
  * @param name name of the plugin to load
  */
 static void
-load_plugin (void *cls,
-             const char *name)
+load_account (void *cls,
+              const struct TALER_EXCHANGEDB_AccountInfo *ai)
 {
   int *ret = cls;
-  struct Plugin *p;
-  json_t *fees;
 
-  p = GNUNET_new (struct Plugin);
-  p->type = GNUNET_strdup (name);
-  p->plugin = TALER_WIRE_plugin_load (cfg,
-                                      name);
-  if (NULL == p->plugin)
+  if ( (NULL != ai->wire_response_filename) &&
+       (GNUNET_YES == ai->credit_enabled) )
   {
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                "Failed to load plugin %s\n",
-                name);
-    GNUNET_free (p->type);
-    GNUNET_free (p);
-    *ret = GNUNET_SYSERR;
-    return;
+    json_t *wire_s;
+    json_error_t error;
+    char *url;
+    char *method;
+
+    if (NULL == (wire_s = json_load_file (ai->wire_response_filename,
+                                          JSON_REJECT_DUPLICATES,
+                                          &error)))
+    {
+      GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                  "Failed to parse `%s': %s at %d:%d (%d)\n",
+                  ai->wire_response_filename,
+                  error.text,
+                  error.line,
+                  error.column,
+                  error.position);
+      *ret = GNUNET_SYSERR;
+      return;
+    }
+    if (NULL == (url = TALER_JSON_wire_to_payto (wire_s)))
+    {
+      GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                  "Wire response file `%s' lacks `url' entry\n",
+                  ai->wire_response_filename);
+      json_decref (wire_s);
+      *ret = GNUNET_SYSERR;
+      return;
+    }
+    if (0 != strcasecmp (url,
+                         ai->payto_url))
+    {
+      GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                  "URL in Wire response file `%s' does not match URL in 
configuration!\n",
+                  ai->wire_response_filename);
+      json_decref (wire_s);
+      GNUNET_free (url);
+      *ret = GNUNET_SYSERR;
+      return;
+    }
+    GNUNET_free (url);
+    if (GNUNET_OK !=
+        TALER_JSON_wire_signature_check (wire_s,
+                                         &TEH_master_public_key))
+    {
+      GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                  "Invalid signature in `%s'\n",
+                  ai->wire_response_filename);
+      json_decref (wire_s);
+      *ret = GNUNET_SYSERR;
+      return;
+    }
+    method = TALER_WIRE_payto_get_method (ai->payto_url);
+    if (GNUNET_OK ==
+        load_fee (method))
+    {
+      GNUNET_assert (-1 !=
+                     json_array_append_new (wire_accounts_array,
+                                            wire_s));
+    }
+    else
+    {
+      GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                  "Wire fees not specified for `%s', ignoring plugin %s\n",
+                  method,
+                  ai->plugin_name);
+      *ret = GNUNET_SYSERR;
+    }
+    GNUNET_free (method);
   }
-  fees = TEH_WIRE_get_fees (name);
-  if (NULL == fees)
+
+  if (GNUNET_YES == ai->debit_enabled)
   {
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                "Disabling method `%s' as wire transfer fees are not given 
correctly\n",
-                name);
-    GNUNET_free (p->type);
-    GNUNET_free (p);
-    *ret = GNUNET_SYSERR;
-    return;
+    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))
+    {
+      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);
+      *ret = GNUNET_SYSERR;
+      return;
+    }
+    GNUNET_CONTAINER_DLL_insert (wire_head,
+                                 wire_tail,
+                                 p);
   }
-  json_decref (fees);
-  GNUNET_CONTAINER_DLL_insert (wire_head,
-                               wire_tail,
-                               p);
 }
 
 
@@ -124,9 +234,11 @@ TEH_VALIDATION_init (const struct 
GNUNET_CONFIGURATION_Handle *cfg)
   int ret;
 
   ret = GNUNET_OK;
-  TALER_WIRE_find_enabled (cfg,
-                           &load_plugin,
-                           &ret);
+  wire_accounts_array = json_array ();
+  wire_fee_object = json_object ();
+  TALER_EXCHANGEDB_find_accounts (cfg,
+                                  &load_account,
+                                  &ret);
   if (NULL == wire_head)
   {
     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
@@ -153,9 +265,12 @@ TEH_VALIDATION_done ()
                                  wire_tail,
                                  p);
     TALER_WIRE_plugin_unload (p->plugin);
-    GNUNET_free (p->type);
     GNUNET_free (p);
   }
+  json_decref (wire_fee_object);
+  wire_fee_object = NULL;
+  json_decref (wire_accounts_array);
+  wire_accounts_array = NULL;
 }
 
 
@@ -164,109 +279,74 @@ TEH_VALIDATION_done ()
  * a wire address.
  *
  * @param wire the JSON wire format object
- * @param ours #GNUNET_YES if the signature should match our master key
  * @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,
-                              int ours,
                               char **emsg)
 {
-  const char *stype;
+  const char *payto_url;
   json_error_t error;
-  struct Plugin *p;
+  char *method;
 
   *emsg = NULL;
   if (0 != json_unpack_ex ((json_t *) wire,
                            &error, 0,
                            "{s:s}",
-                           "type", &stype))
+                           "url", &payto_url))
   {
     GNUNET_asprintf (emsg,
-                     "No `type' specified in the wire details\n");
+                     "No `url' specified in the wire details\n");
     return TALER_EC_DEPOSIT_INVALID_WIRE_FORMAT_TYPE_MISSING;
   }
-  for (p=wire_head; NULL != p; p = p->next)
-    if (0 == strcasecmp (p->type,
-                         stype))
-      return p->plugin->wire_validate (p->plugin->cls,
-                                       wire,
-                                       (GNUNET_YES == ours)
-                                       ? &TEH_master_public_key
-                                       : NULL,
-                                       emsg);
+  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",
-                   stype);
+                   method);
+  GNUNET_free (method);
   return TALER_EC_DEPOSIT_INVALID_WIRE_FORMAT_TYPE_UNSUPPORTED;
 }
 
 
 /**
- * Obtain JSON of the supported wire methods for a given
- * account name prefix.
+ * Obtain JSON response for /wire
  *
- * @return JSON array with the supported validation methods
+ * @return JSON array with the supported validation methods, NULL on error
  */
 json_t *
-TEH_VALIDATION_get_wire_methods ()
+TEH_VALIDATION_get_wire_response ()
 {
-  json_t *methods;
-  char *account_name;
-  char *emsg;
-  enum TALER_ErrorCode ec;
-
-  methods = json_object ();
-  for (struct Plugin *p=wire_head;NULL != p;p = p->next)
-  {
-    struct TALER_WIRE_Plugin *plugin = p->plugin;
-    json_t *method;
-    json_t *fees;
-
-    GNUNET_asprintf (&account_name,
-                     "exchange-wire-%s",
-                     p->type);
-    method = plugin->get_wire_details (plugin->cls,
-                                       cfg,
-                                       account_name);
-    if (TALER_EC_NONE !=
-        (ec = TEH_json_validate_wireformat (method,
-                                            GNUNET_YES,
-                                            &emsg)))
-    {
-      GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                  "Disabling method `%s' as details are ill-formed: %s (%d)\n",
-                  p->type,
-                  emsg,
-                  ec);
-      GNUNET_free (emsg);
-      json_decref (method);
-      method = NULL;
-    }
-    fees = TEH_WIRE_get_fees (p->type);
-    if (NULL == fees)
-    {
-      GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                  "Disabling method `%s' as wire transfer fees are not given 
correctly\n",
-                  p->type);
-      json_decref (method);
-      method = NULL;
-    }
-    else
-    {
-      json_object_set_new (method,
-                           "fees",
-                           fees);
-    }
-
-    if (NULL != method)
-      json_object_set_new (methods,
-                           p->type,
-                           method);
-    GNUNET_free (account_name);
-  }
-  return methods;
+  if ( (0 == json_array_size (wire_accounts_array)) ||
+       (0 == json_object_size (wire_fee_object)) )
+    return NULL;
+  return json_pack ("{s:O, s:O}",
+                    "accounts", wire_accounts_array,
+                    "fees", wire_fee_object);
 }
 
 
diff --git a/src/exchange/taler-exchange-httpd_validation.h 
b/src/exchange/taler-exchange-httpd_validation.h
index d910da7..a0d0795 100644
--- a/src/exchange/taler-exchange-httpd_validation.h
+++ b/src/exchange/taler-exchange-httpd_validation.h
@@ -47,24 +47,21 @@ TEH_VALIDATION_done (void);
  * a wire address.
  *
  * @param wire the JSON wire format object
- * @param ours #GNUNET_YES if the signature should match our master key
  * @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,
-                              int ours,
                               char **emsg);
 
 
 /**
- * Obtain JSON of the supported wire methods for a given
- * account name prefix.
+ * Obtain JSON response for /wire
  *
- * @return JSON array with the supported validation methods
+ * @return JSON object with the supported wire transfer options, NULL on error
  */
 json_t *
-TEH_VALIDATION_get_wire_methods (void);
+TEH_VALIDATION_get_wire_response (void);
 
 
 #endif
diff --git a/src/exchange/taler-exchange-httpd_wire.c 
b/src/exchange/taler-exchange-httpd_wire.c
index 69b800f..bbbf3fb 100644
--- a/src/exchange/taler-exchange-httpd_wire.c
+++ b/src/exchange/taler-exchange-httpd_wire.c
@@ -74,20 +74,20 @@ fees_to_json (struct TALER_EXCHANGEDB_AggregateFees *af)
 
 
 /**
- * Obtain fee structure for @a wire_plugin_name wire transfers.
+ * Obtain fee structure for @a method wire transfers.
  *
- * @param wire_plugin_name name of the plugin to load fees for
+ * @param method method to load fees for
  * @return JSON object (to be freed by caller) with fee structure
  */
 json_t *
-TEH_WIRE_get_fees (const char *wire_plugin_name)
+TEH_WIRE_get_fees (const char *method)
 {
   struct TALER_EXCHANGEDB_AggregateFees *af;
   json_t *j;
   struct GNUNET_TIME_Absolute now;
 
   af = TALER_EXCHANGEDB_fees_read (cfg,
-                                   wire_plugin_name);
+                                   method);
   now = GNUNET_TIME_absolute_get ();
   while ( (NULL != af) &&
           (af->end_date.abs_value_us < now.abs_value_us) )
@@ -101,7 +101,7 @@ TEH_WIRE_get_fees (const char *wire_plugin_name)
   {
     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
                 "Failed to find current wire transfer fees for `%s'\n",
-                wire_plugin_name);
+                method);
     return NULL;
   }
   j = fees_to_json (af);
@@ -143,9 +143,8 @@ TEH_WIRE_handler_wire (struct TEH_RequestHandler *rh,
 int
 TEH_WIRE_init ()
 {
-  wire_methods = TEH_VALIDATION_get_wire_methods ();
-  if ( (NULL == wire_methods) ||
-       (0 == json_object_size (wire_methods)) )
+  wire_methods = TEH_VALIDATION_get_wire_response ();
+  if (NULL == wire_methods)
   {
     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
                 "Failed to find properly configured wire transfer method\n");
@@ -156,7 +155,7 @@ TEH_WIRE_init ()
 
 
 /**
- * Initialize libgcrypt.
+ * Clean up wire subsystem.
  */
 void  __attribute__ ((destructor))
 TEH_wire_cleanup ()
diff --git a/src/exchange/taler-exchange-httpd_wire.h 
b/src/exchange/taler-exchange-httpd_wire.h
index 72dd219..48f82be 100644
--- a/src/exchange/taler-exchange-httpd_wire.h
+++ b/src/exchange/taler-exchange-httpd_wire.h
@@ -39,11 +39,11 @@ TEH_WIRE_init (void);
 /**
  * Obtain fee structure for @a wire_plugin_name wire transfers.
  *
- * @param wire_plugin_name name of the plugin to load fees for
+ * @param method method to load fees for
  * @return JSON object (to be freed by caller) with fee structure
  */
 json_t *
-TEH_WIRE_get_fees (const char *wire_plugin_name);
+TEH_WIRE_get_fees (const char *method);
 
 
 /**
diff --git a/src/exchange/taler-exchange-wirewatch.c 
b/src/exchange/taler-exchange-wirewatch.c
index 508f8c3..a48634e 100644
--- a/src/exchange/taler-exchange-wirewatch.c
+++ b/src/exchange/taler-exchange-wirewatch.c
@@ -1,6 +1,6 @@
 /*
   This file is part of TALER
-  Copyright (C) 2016, 2017 GNUnet e.V.
+  Copyright (C) 2016, 2017, 2018 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
@@ -54,9 +54,58 @@ struct RejectContext
 
 
 /**
- * Handle to the plugin.
+ * Information we keep for each supported account.
  */
-static struct TALER_WIRE_Plugin *wire_plugin;
+struct WireAccount
+{
+  /**
+   * Accounts are kept in a DLL.
+   */
+  struct WireAccount *next;
+
+  /**
+   * Plugins are kept in a DLL.
+   */
+  struct WireAccount *prev;
+
+  /**
+   * Handle to the plugin.
+   */
+  struct TALER_WIRE_Plugin *wire_plugin;
+
+  /**
+   * Name of the section that configures this account.
+   */
+  char *section_name;
+
+  /**
+   * Are we running from scratch and should re-process all transactions
+   * for this account?
+   */
+  int reset_mode;
+
+  /**
+   * Until when is processing this wire plugin delayed?
+   */
+  struct GNUNET_TIME_Absolute delayed_until;
+
+};
+
+
+/**
+ * Head of list of loaded wire plugins.
+ */
+static struct WireAccount *wa_head;
+
+/**
+ * Tail of list of loaded wire plugins.
+ */
+static struct WireAccount *wa_tail;
+
+/**
+ * Wire plugin we are currently using.
+ */
+static struct WireAccount *wa_pos;
 
 /**
  * Which currency is used by this exchange?
@@ -91,11 +140,6 @@ static void *last_row_off;
 static size_t last_row_off_size;
 
 /**
- * Which wire plugin are we watching?
- */
-static char *type;
-
-/**
  * Should we delay the next request to the wire plugin a bit?
  */
 static int delay;
@@ -134,6 +178,8 @@ static struct TALER_WIRE_RejectHandle *rt;
 static void
 shutdown_task (void *cls)
 {
+  struct WireAccount *wa;
+
   if (NULL != task)
   {
     GNUNET_SCHEDULER_cancel (task);
@@ -141,23 +187,31 @@ shutdown_task (void *cls)
   }
   if (NULL != hh)
   {
-    wire_plugin->get_history_cancel (wire_plugin->cls,
-                                    hh);
+    wa_pos->wire_plugin->get_history_cancel (wa_pos->wire_plugin->cls,
+                                             hh);
     hh = NULL;
   }
   if (NULL != rt)
   {
     char *wtid_s;
 
-    wtid_s = wire_plugin->reject_transfer_cancel (wire_plugin->cls,
-                                                  rt);
+    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;
-  TALER_WIRE_plugin_unload (wire_plugin);
-  wire_plugin = NULL;
+  while (NULL != (wa = wa_head))
+  {
+    GNUNET_CONTAINER_DLL_remove (wa_head,
+                                 wa_tail,
+                                 wa);
+    TALER_WIRE_plugin_unload (wa->wire_plugin);
+    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;
@@ -165,6 +219,41 @@ shutdown_task (void *cls)
 
 
 /**
+ * Function called with information about a wire account.  Adds the
+ * account to our list (if it is enabled and we can load the plugin).
+ *
+ * @param cls closure, NULL
+ * @param ai account information
+ */
+static void
+add_account_cb (void *cls,
+                const struct TALER_EXCHANGEDB_AccountInfo *ai)
+{
+  struct WireAccount *wa;
+
+  (void) cls;
+  if (GNUNET_YES != ai->credit_enabled)
+    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)
+  {
+    fprintf (stderr,
+             "Failed to load wire plugin for `%s'\n",
+             ai->plugin_name);
+    GNUNET_free (wa);
+    return;
+  }
+  wa->section_name = GNUNET_strdup (ai->section_name);
+  GNUNET_CONTAINER_DLL_insert (wa_head,
+                               wa_tail,
+                               wa);
+}
+
+
+/**
  * Parse configuration parameters for the exchange server into the
  * corresponding global variables.
  *
@@ -173,21 +262,15 @@ shutdown_task (void *cls)
 static int
 exchange_serve_process_config ()
 {
-  if (NULL == type)
-  {
-    fprintf (stderr,
-             "Option `-t' to specify wire plugin is mandatory.\n");
-    return GNUNET_SYSERR;
-  }
   if (GNUNET_OK !=
       GNUNET_CONFIGURATION_get_value_string (cfg,
                                              "taler",
-                                             "currency",
+                                             "CURRENCY",
                                              &exchange_currency_string))
   {
     GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
                                "taler",
-                               "currency");
+                               "CURRENCY");
     return GNUNET_SYSERR;
   }
   if (strlen (exchange_currency_string) >= TALER_CURRENCY_LEN)
@@ -206,17 +289,16 @@ exchange_serve_process_config ()
              "Failed to initialize DB subsystem\n");
     return GNUNET_SYSERR;
   }
-  if (NULL ==
-      (wire_plugin = TALER_WIRE_plugin_load (cfg,
-                                            type)))
+  TALER_EXCHANGEDB_find_accounts (cfg,
+                                  &add_account_cb,
+                                  NULL);
+  if (NULL == wa_head)
   {
     fprintf (stderr,
-             "Failed to load wire plugin for `%s'\n",
-             type);
+             "No wire accounts configured for credit!\n");
     TALER_EXCHANGEDB_plugin_unload (db_plugin);
     return GNUNET_SYSERR;
   }
-
   return GNUNET_OK;
 }
 
@@ -297,7 +379,6 @@ history_cb (void *cls,
   if (TALER_BANK_DIRECTION_NONE == dir)
   {
     hh = NULL;
-
     if (TALER_EC_NONE != ec)
     {
       GNUNET_log (GNUNET_ERROR_TYPE_INFO,
@@ -310,7 +391,8 @@ history_cb (void *cls,
                            session);
     GNUNET_break (0 <= qs);
     if ( (GNUNET_YES == delay) &&
-         (test_mode) )
+         (test_mode) &&
+         (NULL == wa_pos->next) )
     {
       GNUNET_log (GNUNET_ERROR_TYPE_INFO,
                   "Shutdown due to test mode!\n");
@@ -318,12 +400,20 @@ history_cb (void *cls,
       return GNUNET_OK;
     }
     if (GNUNET_YES == delay)
-      task = GNUNET_SCHEDULER_add_delayed (DELAY,
-                                          &find_transfers,
-                                          NULL);
-    else
-      task = GNUNET_SCHEDULER_add_now (&find_transfers,
-                                      NULL);
+    {
+      wa_pos->delayed_until
+        = GNUNET_TIME_relative_to_absolute (DELAY);
+      GNUNET_free_non_null (last_row_off);
+      last_row_off = NULL;
+      last_row_off_size = 0;
+      wa_pos = wa_pos->next;
+      if (NULL == wa_pos)
+        wa_pos = wa_head;
+      GNUNET_assert (NULL != wa_pos);
+    }
+    task = GNUNET_SCHEDULER_add_at (wa_pos->delayed_until,
+                                    &find_transfers,
+                                    NULL);
     return GNUNET_OK; /* will be ignored anyway */
   }
   if (NULL != details->wtid_s)
@@ -347,11 +437,12 @@ history_cb (void *cls,
     rtc = GNUNET_new (struct RejectContext);
     rtc->session = session;
     rtc->wtid_s = GNUNET_strdup (details->wtid_s);
-    rt = wire_plugin->reject_transfer (wire_plugin->cls,
-                                       row_off,
-                                       row_off_size,
-                                       &reject_cb,
-                                       rtc);
+    rt = wa_pos->wire_plugin->reject_transfer (wa_pos->wire_plugin->cls,
+                                               wa_pos->section_name,
+                                               row_off,
+                                               row_off_size,
+                                               &reject_cb,
+                                               rtc);
     return GNUNET_SYSERR; /* will continue later... */
   }
 
@@ -369,7 +460,8 @@ history_cb (void *cls,
                                      &reserve_pub,
                                      &details->amount,
                                      details->execution_date,
-                                     details->account_details,
+                                     details->account_url,
+                                      wa_pos->section_name,
                                      row_off,
                                      row_off_size);
   if (GNUNET_DB_STATUS_HARD_ERROR == qs)
@@ -437,10 +529,11 @@ find_transfers (void *cls)
     GNUNET_SCHEDULER_shutdown ();
     return;
   }
-  if (! reset_mode)
+  if (! wa_pos->reset_mode)
   {
     qs = db_plugin->get_latest_reserve_in_reference (db_plugin->cls,
                                                      session,
+                                                     wa_pos->section_name,
                                                      &last_row_off,
                                                      &last_row_off_size);
     if (GNUNET_DB_STATUS_HARD_ERROR == qs)
@@ -459,17 +552,19 @@ find_transfers (void *cls)
       return;
     }
   }
+  wa_pos->reset_mode = GNUNET_NO;
   GNUNET_assert ( (NULL == last_row_off) ||
                   ( (NULL != last_row_off) &&
                     (0 != last_row_off_size) ) );
   delay = GNUNET_YES;
-  hh = wire_plugin->get_history (wire_plugin->cls,
-                                TALER_BANK_DIRECTION_CREDIT,
-                                last_row_off,
-                                last_row_off_size,
-                                1024,
-                                &history_cb,
-                                session);
+  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,
+                                         1024,
+                                         &history_cb,
+                                         session);
   if (NULL == hh)
   {
     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
@@ -504,7 +599,8 @@ run (void *cls,
     global_ret = 1;
     return;
   }
-
+  wa_pos = wa_head;
+  GNUNET_assert (NULL != wa_pos);
   task = GNUNET_SCHEDULER_add_now (&find_transfers,
                                    NULL);
   GNUNET_SCHEDULER_add_shutdown (&shutdown_task,
@@ -524,11 +620,6 @@ main (int argc,
       char *const *argv)
 {
   struct GNUNET_GETOPT_CommandLineOption options[] = {
-    GNUNET_GETOPT_option_string ('t',
-                                "type",
-                                "PLUGINNAME",
-                                "which wire plugin to use",
-                                &type),
     GNUNET_GETOPT_option_flag ('T',
                               "test",
                               "run in test mode and exit when idle",
diff --git a/src/exchange/test-taler-exchange-aggregator-postgres.conf 
b/src/exchange/test-taler-exchange-aggregator-postgres.conf
index a5f3519..c2c8aef 100644
--- a/src/exchange/test-taler-exchange-aggregator-postgres.conf
+++ b/src/exchange/test-taler-exchange-aggregator-postgres.conf
@@ -16,7 +16,8 @@ PORT = 8081
 # Master public key used to sign the exchange's various keys
 MASTER_PUBLIC_KEY = 98NJW3CQHZQGQXTY3K85K531XKPAPAVV4Q5V8PYYRR00NJGZWNVG
 
-# Expected base URL of the exchange.
+# Expected base URL of the exchange.  Used in wire transfers for
+# the tracking API.
 BASE_URL = "https://exchange.taler.net/";
 
 [exchangedb]
@@ -31,16 +32,24 @@ IDLE_RESERVE_EXPIRATION_TIME = 4 weeks
 [exchangedb-postgres]
 
 #The connection string the plugin has to use for connecting to the database
-DB_CONN_STR = postgres:///talercheck
+CONFIG = postgres:///talercheck
 
 
-[exchange-wire-test]
-# Enable 'test' for testing of the actual coin operations.
-ENABLE = YES
+[account-1]
+
+# What is the account URL?
+URL = "payto://x-taler-bank/localhost:8082/3"
+
+WIRE_RESPONSE = ${TALER_CONFIG_HOME}/account-1.json
+PLUGIN = "taler_bank"
+ENABLE_DEBIT = YES
+ENABLE_CREDIT = YES
+TALER_BANK_AUTH_METHOD = NONE
+
+[fees-x-taler-bank]
 
 # Fees for the forseeable future...
-# If you see this after 2017, update to match the next 10 years...
-WIRE-FEE-2017 = EUR:0.01
+# If you see this after 2018, update to match the next 10 years...
 WIRE-FEE-2018 = EUR:0.01
 WIRE-FEE-2019 = EUR:0.01
 WIRE-FEE-2020 = EUR:0.01
@@ -50,8 +59,8 @@ WIRE-FEE-2023 = EUR:0.01
 WIRE-FEE-2024 = EUR:0.01
 WIRE-FEE-2025 = EUR:0.01
 WIRE-FEE-2026 = EUR:0.01
+WIRE-FEE-2027 = EUR:0.01
 
-CLOSING-FEE-2017 = EUR:0.01
 CLOSING-FEE-2018 = EUR:0.01
 CLOSING-FEE-2019 = EUR:0.01
 CLOSING-FEE-2020 = EUR:0.01
@@ -61,11 +70,4 @@ CLOSING-FEE-2023 = EUR:0.01
 CLOSING-FEE-2024 = EUR:0.01
 CLOSING-FEE-2025 = EUR:0.01
 CLOSING-FEE-2026 = EUR:0.01
-
-
-# What is the main website of the bank?
-BANK_URL = "http://localhost:8082/";
-
-# From which account at the 'bank' should outgoing
-# wire transfers be made?
-EXCHANGE_ACCOUNT_NUMBER = 3
+CLOSING-FEE-2027 = EUR:0.01
diff --git a/src/exchange/test-taler-exchange-wirewatch-postgres.conf 
b/src/exchange/test-taler-exchange-wirewatch-postgres.conf
index cc614fc..7f8cc47 100644
--- a/src/exchange/test-taler-exchange-wirewatch-postgres.conf
+++ b/src/exchange/test-taler-exchange-wirewatch-postgres.conf
@@ -33,16 +33,23 @@ IDLE_RESERVE_EXPIRATION_TIME = 5 s
 [exchangedb-postgres]
 
 #The connection string the plugin has to use for connecting to the database
-DB_CONN_STR = postgres:///talercheck
+CONFIG = postgres:///talercheck
 
+[account-1]
 
-[exchange-wire-test]
-# Enable 'test' for testing of the actual coin operations.
-ENABLE = YES
+# What is the account URL?
+URL = "payto://x-taler-bank/localhost:8082/3"
+
+WIRE_RESPONSE = ${TALER_CONFIG_HOME}/account-1.json
+PLUGIN = "taler_bank"
+ENABLE_DEBIT = YES
+ENABLE_CREDIT = YES
+TALER_BANK_AUTH_METHOD = NONE
+
+[fees-x-taler-bank]
 
 # Fees for the forseeable future...
-# If you see this after 2017, update to match the next 10 years...
-WIRE-FEE-2017 = EUR:0.01
+# If you see this after 2018, update to match the next 10 years...
 WIRE-FEE-2018 = EUR:0.01
 WIRE-FEE-2019 = EUR:0.01
 WIRE-FEE-2020 = EUR:0.01
@@ -52,8 +59,8 @@ WIRE-FEE-2023 = EUR:0.01
 WIRE-FEE-2024 = EUR:0.01
 WIRE-FEE-2025 = EUR:0.01
 WIRE-FEE-2026 = EUR:0.01
+WIRE-FEE-2027 = EUR:0.01
 
-CLOSING-FEE-2017 = EUR:0.01
 CLOSING-FEE-2018 = EUR:0.01
 CLOSING-FEE-2019 = EUR:0.01
 CLOSING-FEE-2020 = EUR:0.01
@@ -63,11 +70,4 @@ CLOSING-FEE-2023 = EUR:0.01
 CLOSING-FEE-2024 = EUR:0.01
 CLOSING-FEE-2025 = EUR:0.01
 CLOSING-FEE-2026 = EUR:0.01
-
-
-# What is the main website of the bank?
-BANK_URL = "http://localhost:8082/";
-
-# From which account at the 'bank' should outgoing
-# wire transfers be made?
-EXCHANGE_ACCOUNT_NUMBER = 3
+CLOSING-FEE-2027 = EUR:0.01
diff --git a/src/exchange/test_taler_exchange_aggregator.c 
b/src/exchange/test_taler_exchange_aggregator.c
index 0335bcd..f22e638 100644
--- a/src/exchange/test_taler_exchange_aggregator.c
+++ b/src/exchange/test_taler_exchange_aggregator.c
@@ -1,6 +1,6 @@
 /*
   This file is part of TALER
-  (C) 2016, 2017 Inria and GNUnet e.V.
+  (C) 2016, 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
@@ -403,7 +403,9 @@ do_deposit (struct Command *cmd)
   struct TALER_MerchantPrivateKeyP merchant_priv;
   int ret;
 
-  memset (&deposit, 0, sizeof (deposit));
+  memset (&deposit,
+          0,
+          sizeof (deposit));
   /* we derive the merchant's private key from the
      name, to ensure that the same name always
      results in the same key pair. */
@@ -432,13 +434,21 @@ do_deposit (struct Command *cmd)
   }
   fake_coin (&deposit.coin);
   /* Build JSON for wire details */
-  deposit.receiver_wire_account = json_pack ("{s:s, s:s, s:I}",
-                                             "type", "test",
-                                             "bank_url", 
"http://localhost:8082/";,
-                                             "account_number", (json_int_t) 
cmd->details.deposit.merchant_account);
+  {
+    char *str;
+
+    GNUNET_asprintf (&str,
+                     "payto://x-taler-bank/localhost:8082/%llu",
+                     (unsigned long long) 
cmd->details.deposit.merchant_account);
+    deposit.receiver_wire_account
+      = json_pack ("{s:s, s:s}",
+                   "salt", "this-is-a-salt-value",
+                   "url", str);
+    GNUNET_free (str);
+  }
   GNUNET_assert (GNUNET_OK ==
-                 TALER_JSON_hash (deposit.receiver_wire_account,
-                                  &deposit.h_wire));
+                 TALER_JSON_wire_signature_hash (deposit.receiver_wire_account,
+                                                 &deposit.h_wire));
   deposit.timestamp = GNUNET_TIME_absolute_get ();
   GNUNET_TIME_round_abs (&deposit.timestamp);
   deposit.wire_deadline = GNUNET_TIME_relative_to_absolute 
(cmd->details.deposit.wire_deadline);
diff --git a/src/exchange/test_taler_exchange_httpd.conf 
b/src/exchange/test_taler_exchange_httpd.conf
index 7df8d9b..743dbfe 100644
--- a/src/exchange/test_taler_exchange_httpd.conf
+++ b/src/exchange/test_taler_exchange_httpd.conf
@@ -30,18 +30,49 @@ IDLE_RESERVE_EXPIRATION_TIME = 4 weeks
 
 
 [exchangedb-postgres]
-DB_CONN_STR = "postgres:///talercheck"
+CONFIG = "postgres:///talercheck"
 
-[exchange-wire-test]
-# Enable 'test' for testing of the actual coin operations.
-ENABLE = YES
+[account-1]
 
 # What is the main website of the bank?
-BANK_URL = "http://localhost:8082/";
-
-# From which account at the 'bank' should outgoing
-# wire transfers be made?
-EXCHANGE_ACCOUNT_NUMBER = 3
+URL = "payto://x-taler-bank/localhost:8082/3"
+
+WIRE_RESPONSE = ${TALER_CONFIG_HOME}/account-1.json
+
+PLUGIN = "taler_bank"
+
+ENABLE_DEBIT = YES
+
+ENABLE_CREDIT = YES
+
+TALER_BANK_AUTH_METHOD = NONE
+
+
+# Wire fees are specified by wire method, NOT by wire plugin.
+[fees-x-taler-bank]
+# Fees for the forseeable future...
+# If you see this after 2018, update to match the next 10 years...
+WIRE-FEE-2018 = EUR:0.01
+WIRE-FEE-2019 = EUR:0.01
+WIRE-FEE-2020 = EUR:0.01
+WIRE-FEE-2021 = EUR:0.01
+WIRE-FEE-2022 = EUR:0.01
+WIRE-FEE-2023 = EUR:0.01
+WIRE-FEE-2024 = EUR:0.01
+WIRE-FEE-2025 = EUR:0.01
+WIRE-FEE-2026 = EUR:0.01
+WIRE-FEE-2027 = EUR:0.01
+
+CLOSING-FEE-2018 = EUR:0.01
+CLOSING-FEE-2019 = EUR:0.01
+CLOSING-FEE-2020 = EUR:0.01
+CLOSING-FEE-2021 = EUR:0.01
+CLOSING-FEE-2022 = EUR:0.01
+CLOSING-FEE-2023 = EUR:0.01
+CLOSING-FEE-2024 = EUR:0.01
+CLOSING-FEE-2025 = EUR:0.01
+CLOSING-FEE-2026 = EUR:0.01
+CLOSING-FEE-2027 = EUR:0.01
 
 
 # Coins for the tests.
diff --git a/src/exchange/test_taler_exchange_httpd.data 
b/src/exchange/test_taler_exchange_httpd.data
index f88f420..48fd8ee 100644
--- a/src/exchange/test_taler_exchange_httpd.data
+++ b/src/exchange/test_taler_exchange_httpd.data
@@ -1,5 +1,5 @@
 # This file is part of TALER
-# Copyright (C) 2015 GNUnet e.V.
+# Copyright (C) 2015, 2018 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
@@ -23,21 +23,6 @@
 # Note that neither element may contain any spaces!
 #
 #
-# Bad amount:
-/admin/add/incoming 
{"reserve_pub":"7RZBZ86677QMASD2KAYGEPD246C7B7RC6P101FNTG6ZK8X61A620","amount":"1","execution_date":"\/Date(1435934428788)\/","wire":{"empty":"empty"}}
-#
-# Bad wire format:
-/admin/add/incoming 
{"reserve_pub":"6VRFYZRVHJ434BV3J018MS6H7Q1V5Q6YECNMEF9G4WKB8QJQCAX0","amount":{"currency":"EUR","value":10,"fraction":3},"execution_date":"\/Date(1436258333286)\/","wire":{"empty":"empty"}}
-#
-# Malformed JSON (ill-balanced quotes around 'amount')
-/admin/add/incoming 
{"reserve_pub":"BSEFVVNZ4C3724BPVKTJMQMD73HQREA5FWSS1C1BZ36ZFF2WBTK0",amount":{"currency":"EUR","value":5,"fraction":3},"execution_date":"\/Date(1436271156447)\/","wire":{"type":"test","IBAN":0,"name":"Jack","BIC":999,"edate":"\/Date(1436271156447)\/","r":50}}
-#
-# Bad amount (value not a string)
-/admin/add/incoming 
{"reserve_pub":"BSEFVVNZ4C3724BPVKTJMQMD73HQREA5FWSS1C1BZ36ZFF2WBTK0","amount":{"currency":"EUR","value":"5","fraction":3},"execution_date":"\/Date(1436271156447)\/","wire":{"type":"test","IBAN":0,"name":"Jack","BIC":999,"edate":"\/Date(1436271156447)\/","r":50}}
-#
-# Bad amount (overall amount is a string)
-/admin/add/incoming 
{"reserve_pub":"BSEFVVNZ4C3724BPVKTJMQMD73HQREA5FWSS1C1BZ36ZFF2WBTK0","amount":"{\"currency\":\"EUR\",\"value\":5,\"fraction\":3}","execution_date":"\/Date(1436271156447)\/","wire":{"type":"test"}}
-#
 # Bogus denomination key
 /deposit 
{"f":{"currency":"EUR","value":5,"fraction":0},"h_contract_terms":"NRT9E07FYT147V4VCDG0102P0YX0FZ11ZRG90F4X1HDV95M0J64ZVE4XQGNN9MJ3B5K3JX6TJ181KNGRYSZSTYZ5PQHBM1F9QKQ5B50","wire":{"bank":"dest
 
bank","type":"TEST","account":42},"timestamp":"/Date(1436823947)/","coin_pub":"2KCPBGZ77VGJT4DG99EZAY0GQ5TJ89DF53FWYR5RFRTK0CCXRMFG","denom_pub":"51B7ARKCD5HJTTV5F4G0M818E9SP280A40G2GVH04CR30E9S6GVK2DHM8S234C236CR32C9N8RW44E9M712KAH1R60VM2CJ16RT3GGA18RR36CA575144DJ58CTK0E9M8D2M2E9S8GTKGH1Q
 [...]
 #
diff --git a/src/exchange/test_taler_exchange_httpd.sh 
b/src/exchange/test_taler_exchange_httpd.sh
index 7cd2e27..9c9ef40 100755
--- a/src/exchange/test_taler_exchange_httpd.sh
+++ b/src/exchange/test_taler_exchange_httpd.sh
@@ -25,7 +25,9 @@ unset XDG_DATA_HOME
 unset XDG_CONFIG_HOME
 #
 # Setup keys.
-taler-exchange-keyup -c test_taler_exchange_httpd.conf
+taler-exchange-keyup -c test_taler_exchange_httpd.conf || exit 1
+# Setup wire accounts.
+taler-exchange-wire -c test_taler_exchange_httpd.conf || exit 1
 # Run Exchange HTTPD (in background)
 taler-exchange-httpd -c test_taler_exchange_httpd.conf -i &
 # Give HTTP time to start
diff --git a/src/exchange/test_taler_exchange_wirewatch.c 
b/src/exchange/test_taler_exchange_wirewatch.c
index 69502d9..8c1210d 100644
--- a/src/exchange/test_taler_exchange_wirewatch.c
+++ b/src/exchange/test_taler_exchange_wirewatch.c
@@ -1,6 +1,6 @@
 /*
   This file is part of TALER
-  (C) 2016, 2017 Inria and GNUnet e.V.
+  (C) 2016, 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
@@ -499,7 +499,6 @@ interpreter (void *cls)
                                  "taler-exchange-wirewatch",
                                  "taler-exchange-wirewatch",
                                  "-c", config_filename,
-                                 "-t", "test",
                                  "-T", /* run in test mode, exit instead of 
looping */
                                  NULL);
     if (NULL == cmd->details.wirewatch.wirewatch_proc)
diff --git a/src/exchangedb/Makefile.am b/src/exchangedb/Makefile.am
index 66299d7..03322f8 100644
--- a/src/exchangedb/Makefile.am
+++ b/src/exchangedb/Makefile.am
@@ -42,6 +42,7 @@ lib_LTLIBRARIES = \
   libtalerexchangedb.la
 
 libtalerexchangedb_la_SOURCES = \
+  exchangedb_accounts.c \
   exchangedb_auditorkeys.c \
   exchangedb_denomkeys.c \
   exchangedb_fees.c \
@@ -111,7 +112,8 @@ test_exchangedb_postgres_LDADD = \
   $(top_builddir)/src/json/libtalerjson.la \
   $(top_srcdir)/src/util/libtalerutil.la \
   $(top_srcdir)/src/pq/libtalerpq.la \
-  -lgnunetutil -ljansson
+  -ljansson \
+  -lgnunetutil
 
 test_perf_taler_exchangedb_SOURCES = \
   test_perf_taler_exchangedb.c \
@@ -121,8 +123,8 @@ test_perf_taler_exchangedb_LDADD = \
   libtalerexchangedb.la \
   $(top_srcdir)/src/util/libtalerutil.la \
   $(top_srcdir)/src/pq/libtalerpq.la \
-  -ljansson \
-  -lgnunetutil
+  -lgnunetutil \
+  -ljansson
 
 perf_exchangedb_SOURCES = \
   perf_taler_exchangedb.c \
@@ -132,8 +134,8 @@ perf_exchangedb_LDADD = \
   libtalerexchangedb.la \
   $(top_srcdir)/src/util/libtalerutil.la \
   $(top_srcdir)/src/pq/libtalerpq.la \
-  -ljansson \
-  -lgnunetutil
+  -lgnunetutil \
+  -ljansson
 
 
 EXTRA_test_exchangedb_postgres_DEPENDENCIES = \
diff --git a/src/exchangedb/exchangedb-postgres.conf 
b/src/exchangedb/exchangedb-postgres.conf
index 3de7474..5ebd656 100644
--- a/src/exchangedb/exchangedb-postgres.conf
+++ b/src/exchangedb/exchangedb-postgres.conf
@@ -1,2 +1,2 @@
 [exchangedb-postgres]
-DB_CONN_STR = "postgres:///taler"
+CONFIG = "postgres:///taler"
diff --git a/src/exchangedb/exchangedb_accounts.c 
b/src/exchangedb/exchangedb_accounts.c
new file mode 100644
index 0000000..275e926
--- /dev/null
+++ b/src/exchangedb/exchangedb_accounts.c
@@ -0,0 +1,141 @@
+/*
+  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 exchangedb/exchangedb_accounts.c
+ * @brief Logic to parse account information from the configuration
+ * @author Christian Grothoff
+ */
+#include "platform.h"
+#include "taler_exchangedb_lib.h"
+
+
+/**
+ * Closure of #check_for_account.
+ */
+struct FindAccountContext
+{
+  /**
+   * Configuration we are usign.
+   */
+  const struct GNUNET_CONFIGURATION_Handle *cfg;
+
+  /**
+   * Callback to invoke.
+   */
+  TALER_EXCHANGEDB_AccountCallback cb;
+
+  /**
+   * Closure for @e cb.
+   */
+  void *cb_cls;
+};
+
+
+/**
+ * Check if @a section begins with "exchange-wire-", and if
+ * so if the "ENABLE" option is set to "YES".  If both are
+ * true, call the callback from the context with the
+ * rest of the section name.
+ *
+ * @param cls our `struct FindEnabledWireContext`
+ * @param section name of a section in the configuration
+ */
+static void
+check_for_account (void *cls,
+                   const char *section)
+{
+  struct FindAccountContext *ctx = cls;
+  char *plugin_name;
+  char *payto_url;
+  char *wire_response_filename;
+  struct TALER_EXCHANGEDB_AccountInfo ai;
+
+  if (0 != strncasecmp (section,
+                        "account-",
+                        strlen ("account-")))
+    return;
+  if (GNUNET_OK !=
+      GNUNET_CONFIGURATION_get_value_string (ctx->cfg,
+                                             section,
+                                             "URL",
+                                             &payto_url))
+  {
+    GNUNET_log_config_missing (GNUNET_ERROR_TYPE_WARNING,
+                               section,
+                               "URL");
+    return;
+  }
+  if (GNUNET_OK !=
+      GNUNET_CONFIGURATION_get_value_string (ctx->cfg,
+                                             section,
+                                             "PLUGIN",
+                                             &plugin_name))
+  {
+    GNUNET_log_config_missing (GNUNET_ERROR_TYPE_WARNING,
+                               section,
+                               "PLUGIN");
+    GNUNET_free (payto_url);
+    return;
+  }
+  if (GNUNET_OK !=
+      GNUNET_CONFIGURATION_get_value_filename (ctx->cfg,
+                                               section,
+                                               "WIRE_RESPONSE",
+                                               &wire_response_filename))
+    wire_response_filename = NULL;
+  ai.section_name = section;
+  ai.plugin_name = plugin_name;
+  ai.payto_url = payto_url;
+  ai.wire_response_filename = wire_response_filename;
+  ai.debit_enabled = (GNUNET_YES ==
+                      GNUNET_CONFIGURATION_get_value_yesno (ctx->cfg,
+                                                            section,
+                                                            "ENABLE_DEBIT"));
+  ai.credit_enabled = (GNUNET_YES ==
+                       GNUNET_CONFIGURATION_get_value_yesno (ctx->cfg,
+                                                             section,
+                                                             "ENABLE_CREDIT"));
+  ctx->cb (ctx->cb_cls,
+           &ai);
+  GNUNET_free (payto_url);
+  GNUNET_free (plugin_name);
+  GNUNET_free_non_null (wire_response_filename);
+}
+
+
+/**
+ * Parse the configuration to find account information.
+ *
+ * @param cfg configuration to use
+ * @param cb callback to invoke
+ * @param cb_cls closure for @a cb
+ */
+void
+TALER_EXCHANGEDB_find_accounts (const struct GNUNET_CONFIGURATION_Handle *cfg,
+                                TALER_EXCHANGEDB_AccountCallback cb,
+                                void *cb_cls)
+{
+  struct FindAccountContext ctx;
+
+  ctx.cfg = cfg;
+  ctx.cb = cb;
+  ctx.cb_cls = cb_cls;
+  GNUNET_CONFIGURATION_iterate_sections (cfg,
+                                         &check_for_account,
+                                         &ctx);
+}
+
+/* end of exchangedb_accounts.c */
diff --git a/src/exchangedb/perf_taler_exchangedb.c 
b/src/exchangedb/perf_taler_exchangedb.c
index e2591c8..5cde719 100644
--- a/src/exchangedb/perf_taler_exchangedb.c
+++ b/src/exchangedb/perf_taler_exchangedb.c
@@ -1,6 +1,6 @@
 /*
    This file is part of TALER
-   Copyright (C) 2014, 2015, 2016 Inria and GNUnet e.V.
+   Copyright (C) 2014-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
diff --git a/src/exchangedb/perf_taler_exchangedb_init.c 
b/src/exchangedb/perf_taler_exchangedb_init.c
index 4efec39..789aaea 100644
--- a/src/exchangedb/perf_taler_exchangedb_init.c
+++ b/src/exchangedb/perf_taler_exchangedb_init.c
@@ -204,6 +204,7 @@ PERF_TALER_EXCHANGEDB_reserve_free (struct 
PERF_TALER_EXCHANGEDB_Reserve *reserv
 
 /**
  * Generate a dummy deposit for testing purposes
+ *
  * @param dki the denomination key used to sign the key
  */
 struct TALER_EXCHANGEDB_Deposit *
@@ -214,19 +215,12 @@ PERF_TALER_EXCHANGEDB_deposit_init (const struct 
PERF_TALER_EXCHANGEDB_Coin *coi
   struct TALER_MerchantPublicKeyP merchant_pub;
   struct GNUNET_HashCode h_contract_terms;
   struct GNUNET_HashCode h_wire;
-  const char wire[] = "{"
-    "\"type\":\"SEPA\","
-    "\"IBAN\":\"DE67830654080004822650\","
-    "\"NAME\":\"GNUNET E.\","
-    "\"BIC\":\"GENODEF1SRL\""
-    "}";
   struct GNUNET_TIME_Absolute timestamp;
   struct GNUNET_TIME_Absolute refund_deadline;
   struct TALER_Amount amount_with_fee;
   struct TALER_Amount deposit_fee;
 
-  GNUNET_assert (NULL !=
-                 (deposit = GNUNET_malloc (sizeof (struct 
TALER_EXCHANGEDB_Deposit) + sizeof (wire))));
+  deposit = GNUNET_new (struct TALER_EXCHANGEDB_Deposit);
   GNUNET_CRYPTO_hash_create_random (GNUNET_CRYPTO_QUALITY_WEAK,
                                     &h_contract_terms);
   GNUNET_CRYPTO_hash_create_random (GNUNET_CRYPTO_QUALITY_WEAK,
@@ -253,9 +247,8 @@ PERF_TALER_EXCHANGEDB_deposit_init (const struct 
PERF_TALER_EXCHANGEDB_Coin *coi
 
     eddsa_prv = GNUNET_CRYPTO_eddsa_key_create ();
     GNUNET_assert(NULL != eddsa_prv);
-    GNUNET_CRYPTO_eddsa_key_get_public (
-      eddsa_prv,
-      &merchant_pub.eddsa_pub);
+    GNUNET_CRYPTO_eddsa_key_get_public (eddsa_prv,
+                                        &merchant_pub.eddsa_pub);
     GNUNET_free (eddsa_prv);
   }
   timestamp = GNUNET_TIME_absolute_get ();
@@ -280,7 +273,10 @@ PERF_TALER_EXCHANGEDB_deposit_init (const struct 
PERF_TALER_EXCHANGEDB_Coin *coi
   deposit->csig = csig;
   deposit->h_contract_terms = h_contract_terms;
   deposit->h_wire = h_wire;
-  deposit->receiver_wire_account = json_loads (wire, 0, NULL);
+  deposit->receiver_wire_account
+    = json_pack ("{s:s, s:s}",
+                 "url", "payto://sepa/DE67830654080004822650",
+                 "salt", "this-is-a-salt-value");
   deposit->timestamp = timestamp;
   deposit->refund_deadline = refund_deadline;
   deposit->amount_with_fee = amount_with_fee;
@@ -301,7 +297,7 @@ PERF_TALER_EXCHANGEDB_deposit_copy (const struct 
TALER_EXCHANGEDB_Deposit *depos
 
   copy = GNUNET_new (struct TALER_EXCHANGEDB_Deposit);
   *copy = *deposit;
-  json_incref (copy->receiver_wire_account);
+  copy->receiver_wire_account = json_incref (deposit->receiver_wire_account);
   copy->coin.denom_pub.rsa_public_key =
     GNUNET_CRYPTO_rsa_public_key_dup (deposit->coin.denom_pub.rsa_public_key);
   copy->coin.denom_sig.rsa_signature =
diff --git a/src/exchangedb/perf_taler_exchangedb_interpreter.c 
b/src/exchangedb/perf_taler_exchangedb_interpreter.c
index 8a81bef..43891e5 100644
--- a/src/exchangedb/perf_taler_exchangedb_interpreter.c
+++ b/src/exchangedb/perf_taler_exchangedb_interpreter.c
@@ -1243,19 +1243,18 @@ interpret (struct 
PERF_TALER_EXCHANGEDB_interpreter_state *state)
           unsigned int reserve_index;
           int ret;
           struct PERF_TALER_EXCHANGEDB_Reserve *reserve;
-          json_t *sndr;
+          char *sndr;
           uint32_t uid;
           struct GNUNET_TIME_Absolute now;
 
           reserve_index = 
state->cmd[state->i].details.insert_reserve.index_reserve;
           reserve = state->cmd[reserve_index].exposed.data.reserve;
-          sndr = json_pack ("{s:i}",
-                            "account",
-                            (int) GNUNET_CRYPTO_random_u32 
(GNUNET_CRYPTO_QUALITY_WEAK,
-                                                            UINT32_MAX));
+          GNUNET_asprintf (&sndr,
+                           "payto://x-taler-test/localhost:8080/%u",
+                           (unsigned int) GNUNET_CRYPTO_random_u32 
(GNUNET_CRYPTO_QUALITY_WEAK,
+                                                                    
UINT32_MAX));
           uid = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK,
                                           UINT32_MAX);
-          GNUNET_assert (NULL != sndr);
           now = GNUNET_TIME_absolute_get ();
           (void) GNUNET_TIME_round_abs (&now);
           ret = state->plugin->reserves_in_insert (state->plugin->cls,
@@ -1264,10 +1263,11 @@ interpret (struct 
PERF_TALER_EXCHANGEDB_interpreter_state *state)
                                                    &reserve->reserve.balance,
                                                    now,
                                                    sndr,
+                                                   "account-1",
                                                    &uid,
                                                    sizeof (uid));
           GNUNET_assert (GNUNET_SYSERR != ret);
-          json_decref (sndr);
+          GNUNET_free (sndr);
         }
         break;
 
diff --git a/src/exchangedb/plugin_exchangedb_common.c 
b/src/exchangedb/plugin_exchangedb_common.c
index e4b8324..8344974 100644
--- a/src/exchangedb/plugin_exchangedb_common.c
+++ b/src/exchangedb/plugin_exchangedb_common.c
@@ -42,8 +42,7 @@ common_free_reserve_history (void *cls,
     {
     case TALER_EXCHANGEDB_RO_BANK_TO_EXCHANGE:
       bt = rh->details.bank;
-      if (NULL != bt->sender_account_details)
-        json_decref (bt->sender_account_details);
+      GNUNET_free_non_null (bt->sender_account_details);
       GNUNET_free_non_null (bt->wire_reference);
       GNUNET_free (bt);
       break;
@@ -61,8 +60,7 @@ common_free_reserve_history (void *cls,
       break;
     case TALER_EXCHANGEDB_RO_EXCHANGE_TO_BANK:
       closing = rh->details.closing;
-      if (NULL != closing->receiver_account_details)
-        json_decref (closing->receiver_account_details);
+      GNUNET_free_non_null (closing->receiver_account_details);
       GNUNET_free (closing);
       break;
     }
@@ -92,7 +90,7 @@ common_free_coin_transaction_list (void *cls,
     switch (list->type)
     {
     case TALER_EXCHANGEDB_TT_DEPOSIT:
-      json_decref (list->details.deposit->receiver_wire_account);
+      GNUNET_free_non_null (list->details.deposit->receiver_wire_account);
       if (NULL != list->details.deposit->coin.denom_pub.rsa_public_key)
         GNUNET_CRYPTO_rsa_public_key_free 
(list->details.deposit->coin.denom_pub.rsa_public_key);
       if (NULL != list->details.deposit->coin.denom_sig.rsa_signature)
diff --git a/src/exchangedb/plugin_exchangedb_postgres.c 
b/src/exchangedb/plugin_exchangedb_postgres.c
index 63ed887..e72e96c 100644
--- a/src/exchangedb/plugin_exchangedb_postgres.c
+++ b/src/exchangedb/plugin_exchangedb_postgres.c
@@ -127,6 +127,7 @@ postgres_drop_tables (void *cls)
   PGconn *conn;
   int ret;
 
+  /* FIXME: use GNUNET_PQ_connect_with_cfg instead? */
   conn = GNUNET_PQ_connect (pc->connection_cfg_str);
   if (NULL == conn)
     return GNUNET_SYSERR;
@@ -218,12 +219,13 @@ postgres_create_tables (void *cls)
                            ",credit_frac INT4 NOT NULL"
                            ",credit_curr VARCHAR("TALER_CURRENCY_LEN_STR") NOT 
NULL"
                            ",sender_account_details TEXT NOT NULL"
+                           ",exchange_account_section TEXT NOT NULL"
                            ",execution_date INT8 NOT NULL"
                            ",PRIMARY KEY (reserve_pub, wire_reference)"
                            ");"),
     /* Create indices on reserves_in */
     GNUNET_PQ_make_try_execute ("CREATE INDEX reserves_in_execution_index"
-                                " ON reserves_in (execution_date);"),
+                                " ON reserves_in 
(exchange_account_section,execution_date);"),
     /* This table contains the data for wire transfers the exchange has
        executed to close a reserve. */
     GNUNET_PQ_make_execute("CREATE TABLE IF NOT EXISTS reserves_close "
@@ -366,6 +368,7 @@ postgres_create_tables (void *cls)
                            ",execution_date INT8 NOT NULL"
                            ",wtid_raw BYTEA UNIQUE NOT NULL CHECK 
(LENGTH(wtid_raw)=" TALER_WIRE_TRANSFER_IDENTIFIER_LEN_STR ")"
                            ",wire_target TEXT NOT NULL"
+                           ",exchange_account_section TEXT NOT NULL"
                            ",amount_val INT8 NOT NULL"
                            ",amount_frac INT4 NOT NULL"
                            ",amount_curr VARCHAR("TALER_CURRENCY_LEN_STR") NOT 
NULL"
@@ -433,6 +436,7 @@ postgres_create_tables (void *cls)
   PGconn *conn;
   int ret;
 
+  /* FIXME: use GNUNET_PQ_connect_with_cfg instead? */
   conn = GNUNET_PQ_connect (pc->connection_cfg_str);
   if (NULL == conn)
     return GNUNET_SYSERR;
@@ -585,21 +589,23 @@ postgres_prepare (PGconn *db_conn)
                             ",credit_val"
                             ",credit_frac"
                             ",credit_curr"
+                            ",exchange_account_section"
                             ",sender_account_details"
                             ",execution_date"
                             ") VALUES "
-                            "($1, $2, $3, $4, $5, $6, $7) "
+                            "($1, $2, $3, $4, $5, $6, $7, $8) "
                             "ON CONFLICT DO NOTHING;",
-                            7),
+                            8),
     /* Used in postgres_select_reserves_in_above_serial_id() to obtain inbound
        transactions for reserves with serial id '\geq' the given parameter */
     GNUNET_PQ_make_prepare ("reserves_in_get_latest_wire_reference",
                             "SELECT"
                             " wire_reference"
                             " FROM reserves_in"
+                            " WHERE exchange_account_section=$1"
                             " ORDER BY reserve_in_serial_id DESC"
                             " LIMIT 1;",
-                            0),
+                            1),
     /* Used in postgres_select_reserves_in_above_serial_id() to obtain inbound
        transactions for reserves with serial id '\geq' the given parameter */
     GNUNET_PQ_make_prepare ("audit_reserves_in_get_transactions_incr",
@@ -616,6 +622,22 @@ postgres_prepare (PGconn *db_conn)
                             " WHERE reserve_in_serial_id>=$1"
                             " ORDER BY reserve_in_serial_id;",
                             1),
+    /* Used in postgres_select_reserves_in_above_serial_id() to obtain inbound
+       transactions for reserves with serial id '\geq' the given parameter */
+    GNUNET_PQ_make_prepare 
("audit_reserves_in_get_transactions_incr_by_account",
+                            "SELECT"
+                            " reserve_pub"
+                            ",wire_reference"
+                            ",credit_val"
+                            ",credit_frac"
+                            ",credit_curr"
+                            ",execution_date"
+                            ",sender_account_details"
+                            ",reserve_in_serial_id"
+                            " FROM reserves_in"
+                            " WHERE reserve_in_serial_id>=$1 AND 
exchange_account_section=$2"
+                            " ORDER BY reserve_in_serial_id;",
+                            2),
     /* Used in #postgres_get_reserve_history() to obtain inbound transactions
        for a reserve */
     GNUNET_PQ_make_prepare ("reserves_in_get_transactions",
@@ -1210,12 +1232,13 @@ postgres_prepare (PGconn *db_conn)
                             "(execution_date"
                             ",wtid_raw"
                             ",wire_target"
+                            ",exchange_account_section"
                             ",amount_val"
                             ",amount_frac"
                             ",amount_curr"
                             ") VALUES "
-                            "($1, $2, $3, $4, $5, $6);",
-                            6),
+                            "($1, $2, $3, $4, $5, $6, $7);",
+                            7),
     /* Used in #postgres_wire_prepare_data_insert() to store
        wire transfer information before actually committing it with the bank */
     GNUNET_PQ_make_prepare ("wire_prepare_data_insert",
@@ -1285,6 +1308,20 @@ postgres_prepare (PGconn *db_conn)
                             " WHERE wireout_uuid>=$1"
                             " ORDER BY wireout_uuid ASC;",
                             1),
+    /* Used in #postgres_select_wire_out_above_serial_id_by_account() */
+    GNUNET_PQ_make_prepare ("audit_get_wire_incr_by_account",
+                            "SELECT"
+                            " wireout_uuid"
+                            ",execution_date"
+                            ",wtid_raw"
+                            ",wire_target"
+                            ",amount_val"
+                            ",amount_frac"
+                            ",amount_curr"
+                            " FROM wire_out"
+                            " WHERE wireout_uuid>=$1 AND 
exchange_account_section=$2"
+                            " ORDER BY wireout_uuid ASC;",
+                            2),
     /* Used in #postgres_insert_payback_request() to store payback
        information */
     GNUNET_PQ_make_prepare ("payback_insert",
@@ -1509,6 +1546,7 @@ postgres_get_session (void *cls)
       return session;
     }
   }
+  /* FIXME: use GNUNET_PQ_connect_with_cfg instead? */
   db_conn = GNUNET_PQ_connect (pc->connection_cfg_str);
   if (NULL == db_conn)
     return NULL;
@@ -1836,7 +1874,9 @@ reserves_update (void *cls,
  * @param reserve_pub public key of the reserve
  * @param balance the amount that has to be added to the reserve
  * @param execution_time when was the amount added
- * @param sender_account_details account information for the sender
+ * @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
  * @return transaction status code
@@ -1847,7 +1887,8 @@ postgres_reserves_in_insert (void *cls,
                              const struct TALER_ReservePublicKeyP *reserve_pub,
                              const struct TALER_Amount *balance,
                              struct GNUNET_TIME_Absolute execution_time,
-                             const json_t *sender_account_details,
+                             const char *sender_account_details,
+                             const char *exchange_account_section,
                              const void *wire_reference,
                              size_t wire_reference_size)
 {
@@ -1900,7 +1941,7 @@ postgres_reserves_in_insert (void *cls,
        as a foreign key. */
     struct GNUNET_PQ_QueryParam params[] = {
       GNUNET_PQ_query_param_auto_from_type (reserve_pub),
-      TALER_PQ_query_param_json (sender_account_details),
+      GNUNET_PQ_query_param_string (sender_account_details),
       TALER_PQ_query_param_amount (balance),
       TALER_PQ_query_param_absolute_time (&expiry),
       GNUNET_PQ_query_param_end
@@ -1932,7 +1973,8 @@ postgres_reserves_in_insert (void *cls,
       GNUNET_PQ_query_param_fixed_size (wire_reference,
                                         wire_reference_size),
       TALER_PQ_query_param_amount (balance),
-      TALER_PQ_query_param_json (sender_account_details),
+      GNUNET_PQ_query_param_string (exchange_account_section),
+      GNUNET_PQ_query_param_string (sender_account_details),
       TALER_PQ_query_param_absolute_time (&execution_time),
       GNUNET_PQ_query_param_end
     };
@@ -1982,6 +2024,8 @@ postgres_reserves_in_insert (void *cls,
  *
  * @param cls the @e cls of this struct with the plugin-specific state
  * @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
  * @return transaction status code
@@ -1989,10 +2033,12 @@ postgres_reserves_in_insert (void *cls,
 static enum GNUNET_DB_QueryStatus
 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)
 {
   struct GNUNET_PQ_QueryParam params[] = {
+    GNUNET_PQ_query_param_string (exchange_account_name),
     GNUNET_PQ_query_param_end
   };
   struct GNUNET_PQ_ResultSpec rs[] = {
@@ -2228,8 +2274,8 @@ add_bank_to_exchange (void *cls,
                                     &bt->amount),
        TALER_PQ_result_spec_absolute_time ("execution_date",
                                             &bt->execution_date),
-       TALER_PQ_result_spec_json ("sender_account_details",
-                                  &bt->sender_account_details),
+       GNUNET_PQ_result_spec_string ("sender_account_details",
+                                      &bt->sender_account_details),
        GNUNET_PQ_result_spec_end
       };
 
@@ -2395,8 +2441,8 @@ add_exchange_to_bank (void *cls,
                                     &closing->closing_fee),
        TALER_PQ_result_spec_absolute_time ("execution_date",
                                             &closing->execution_date),
-       TALER_PQ_result_spec_json ("receiver_account",
-                                  &closing->receiver_account_details),
+       GNUNET_PQ_result_spec_string ("receiver_account",
+                                      &closing->receiver_account_details),
        GNUNET_PQ_result_spec_auto_from_type ("wtid",
                                              &closing->wtid),
        GNUNET_PQ_result_spec_end
@@ -2716,7 +2762,7 @@ postgres_get_ready_deposit (void *cls,
     GNUNET_PQ_result_spec_auto_from_type ("coin_pub",
                                          &coin_pub),
     TALER_PQ_result_spec_json ("wire",
-                              &wire),
+                               &wire),
     GNUNET_PQ_result_spec_end
   };
   enum GNUNET_DB_QueryStatus qs;
@@ -3817,7 +3863,7 @@ add_coin_deposit (void *cls,
        GNUNET_PQ_result_spec_auto_from_type ("h_wire",
                                              &deposit->h_wire),
        TALER_PQ_result_spec_json ("wire",
-                                  &deposit->receiver_wire_account),
+                                   &deposit->receiver_wire_account),
        GNUNET_PQ_result_spec_auto_from_type ("coin_sig",
                                              &deposit->csig),
        GNUNET_PQ_result_spec_end
@@ -4184,8 +4230,6 @@ handle_wt_result (void *cls,
     struct TALER_Amount amount_with_fee;
     struct TALER_Amount deposit_fee;
     json_t *wire;
-    json_t *t;
-    const char *wire_method;
     struct GNUNET_PQ_ResultSpec rs[] = {
       GNUNET_PQ_result_spec_uint64 ("aggregation_serial_id", &rowid),
       GNUNET_PQ_result_spec_auto_from_type ("h_contract_terms", 
&h_contract_terms),
@@ -4208,25 +4252,11 @@ handle_wt_result (void *cls,
       ctx->status = GNUNET_SYSERR;
       return;
     }
-    t = json_object_get (wire, "type");
-    if (NULL == t)
-    {
-      GNUNET_break (0);
-      ctx->status = GNUNET_SYSERR;
-      return;
-    }
-    wire_method = json_string_value (t);
-    if (NULL == wire_method)
-    {
-      GNUNET_break (0);
-      ctx->status = GNUNET_SYSERR;
-      return;
-    }
     ctx->cb (ctx->cb_cls,
             rowid,
             &merchant_pub,
-            wire_method,
             &h_wire,
+             wire,
             exec_time,
             &h_contract_terms,
             &coin_pub,
@@ -4586,14 +4616,14 @@ reserve_expired_cb (void *cls,
   for (unsigned int i=0;i<num_results;i++)
   {
     struct GNUNET_TIME_Absolute exp_date;
-    json_t *account_details;
+    char *account_details;
     struct TALER_ReservePublicKeyP reserve_pub;
     struct TALER_Amount remaining_balance;
     struct GNUNET_PQ_ResultSpec rs[] = {
       TALER_PQ_result_spec_absolute_time ("expiration_date",
                                           &exp_date),
-      TALER_PQ_result_spec_json ("account_details",
-                                &account_details),
+      GNUNET_PQ_result_spec_string ("account_details",
+                                    &account_details),
       GNUNET_PQ_result_spec_auto_from_type ("reserve_pub",
                                            &reserve_pub),
       TALER_PQ_result_spec_amount ("current_balance",
@@ -4680,7 +4710,7 @@ postgres_insert_reserve_closed (void *cls,
                                struct TALER_EXCHANGEDB_Session *session,
                                const struct TALER_ReservePublicKeyP 
*reserve_pub,
                                struct GNUNET_TIME_Absolute execution_date,
-                               const json_t *receiver_account,
+                               const char *receiver_account,
                                const struct TALER_WireTransferIdentifierRawP 
*wtid,
                                const struct TALER_Amount *amount_with_fee,
                                const struct TALER_Amount *closing_fee)
@@ -4690,7 +4720,7 @@ postgres_insert_reserve_closed (void *cls,
     GNUNET_PQ_query_param_auto_from_type (reserve_pub),
     TALER_PQ_query_param_absolute_time (&execution_date),
     GNUNET_PQ_query_param_auto_from_type (wtid),
-    TALER_PQ_query_param_json (receiver_account),
+    GNUNET_PQ_query_param_string (receiver_account),
     TALER_PQ_query_param_amount (amount_with_fee),
     TALER_PQ_query_param_amount (closing_fee),
     GNUNET_PQ_query_param_end
@@ -4891,6 +4921,8 @@ postgres_start_deferred_wire_out (void *cls,
  * @param date time of the wire transfer
  * @param wtid subject of the wire transfer
  * @param wire_account details about the receiver account of the wire transfer
+ * @param exchange_account_section configuration section of the exchange 
specifying the
+ *        exchange's bank account being used
  * @param amount amount that was transmitted
  * @return transaction status code
  */
@@ -4900,12 +4932,14 @@ postgres_store_wire_transfer_out (void *cls,
                                   struct GNUNET_TIME_Absolute date,
                                   const struct 
TALER_WireTransferIdentifierRawP *wtid,
                                   const json_t *wire_account,
+                                  const char *exchange_account_section,
                                   const struct TALER_Amount *amount)
 {
   struct GNUNET_PQ_QueryParam params[] = {
     TALER_PQ_query_param_absolute_time (&date),
     GNUNET_PQ_query_param_auto_from_type (wtid),
     TALER_PQ_query_param_json (wire_account),
+    GNUNET_PQ_query_param_string (exchange_account_section),
     TALER_PQ_query_param_amount (amount),
     GNUNET_PQ_query_param_end
   };
@@ -4952,6 +4986,7 @@ postgres_gc (void *cls)
   long_ago = GNUNET_TIME_absolute_subtract (now,
                                            GNUNET_TIME_relative_multiply 
(GNUNET_TIME_UNIT_YEARS,
                                                                           10));
+  /* FIXME: use GNUNET_PQ_connect_with_cfg instead? */
   conn = GNUNET_PQ_connect (pc->connection_cfg_str);
   if (NULL == conn)
     return GNUNET_SYSERR;
@@ -5427,7 +5462,7 @@ reserves_in_serial_helper_cb (void *cls,
   {
     struct TALER_ReservePublicKeyP reserve_pub;
     struct TALER_Amount credit;
-    json_t *sender_account_details;
+    char *sender_account_details;
     struct GNUNET_TIME_Absolute execution_date;
     uint64_t rowid;
     void *wire_reference;
@@ -5442,8 +5477,8 @@ reserves_in_serial_helper_cb (void *cls,
                                    &credit),
       TALER_PQ_result_spec_absolute_time("execution_date",
                                           &execution_date),
-      TALER_PQ_result_spec_json ("sender_account_details",
-                                 &sender_account_details),
+      GNUNET_PQ_result_spec_string ("sender_account_details",
+                                    &sender_account_details),
       GNUNET_PQ_result_spec_uint64 ("reserve_in_serial_id",
                                     &rowid),
       GNUNET_PQ_result_spec_end
@@ -5515,6 +5550,49 @@ postgres_select_reserves_in_above_serial_id (void *cls,
 
 
 /**
+ * Select inbound wire transfers into reserves_in above @a serial_id
+ * in monotonically increasing order by account.
+ *
+ * @param cls closure
+ * @param session database connection
+ * @param account_name name of the account to select by
+ * @param serial_id highest serial ID to exclude (select strictly larger)
+ * @param cb function to call on each result
+ * @param cb_cls closure for @a cb
+ * @return transaction status code
+ */
+static enum GNUNET_DB_QueryStatus
+postgres_select_reserves_in_above_serial_id_by_account (void *cls,
+                                                        struct 
TALER_EXCHANGEDB_Session *session,
+                                                        const char 
*account_name,
+                                                        uint64_t serial_id,
+                                                        
TALER_EXCHANGEDB_ReserveInCallback cb,
+                                                        void *cb_cls)
+{
+  struct GNUNET_PQ_QueryParam params[] = {
+    GNUNET_PQ_query_param_uint64 (&serial_id),
+    GNUNET_PQ_query_param_string (account_name),
+    GNUNET_PQ_query_param_end
+  };
+  struct ReservesInSerialContext risc = {
+    .cb = cb,
+    .cb_cls = cb_cls,
+    .status = GNUNET_OK
+  };
+  enum GNUNET_DB_QueryStatus qs;
+
+  qs = GNUNET_PQ_eval_prepared_multi_select (session->conn,
+                                            
"audit_reserves_in_get_transactions_incr_by_account",
+                                            params,
+                                            &reserves_in_serial_helper_cb,
+                                            &risc);
+  if (GNUNET_OK != risc.status)
+    return GNUNET_DB_STATUS_HARD_ERROR;
+  return qs;
+}
+
+
+/**
  * Closure for #reserves_out_serial_helper_cb().
  */
 struct ReservesOutSerialContext
@@ -5771,6 +5849,49 @@ postgres_select_wire_out_above_serial_id (void *cls,
 
 
 /**
+ * Function called to select all wire transfers the exchange
+ * executed by account.
+ *
+ * @param cls closure
+ * @param session database connection
+ * @param account_name account to select
+ * @param serial_id highest serial ID to exclude (select strictly larger)
+ * @param cb function to call for ONE unfinished item
+ * @param cb_cls closure for @a cb
+ * @return transaction status code
+ */
+static enum GNUNET_DB_QueryStatus
+postgres_select_wire_out_above_serial_id_by_account (void *cls,
+                                                     struct 
TALER_EXCHANGEDB_Session *session,
+                                                     const char *account_name,
+                                                     uint64_t serial_id,
+                                                     
TALER_EXCHANGEDB_WireTransferOutCallback cb,
+                                                     void *cb_cls)
+{
+  struct GNUNET_PQ_QueryParam params[] = {
+    GNUNET_PQ_query_param_uint64 (&serial_id),
+    GNUNET_PQ_query_param_string (account_name),
+    GNUNET_PQ_query_param_end
+  };
+  struct WireOutSerialContext wosc = {
+    .cb = cb,
+    .cb_cls = cb_cls,
+    .status = GNUNET_OK
+  };
+  enum GNUNET_DB_QueryStatus qs;
+
+  qs = GNUNET_PQ_eval_prepared_multi_select (session->conn,
+                                            "audit_get_wire_incr_by_account",
+                                            params,
+                                            &wire_out_serial_helper_cb,
+                                            &wosc);
+  if (GNUNET_OK != wosc.status)
+    return GNUNET_DB_STATUS_HARD_ERROR;
+  return qs;
+}
+
+
+/**
  * Closure for #payback_serial_helper_cb().
  */
 struct PaybackSerialContext
@@ -5949,7 +6070,7 @@ reserve_closed_serial_helper_cb (void *cls,
   {
     uint64_t rowid;
     struct TALER_ReservePublicKeyP reserve_pub;
-    json_t *receiver_account;
+    char *receiver_account;
     struct TALER_WireTransferIdentifierRawP wtid;
     struct TALER_Amount amount_with_fee;
     struct TALER_Amount closing_fee;
@@ -5963,8 +6084,8 @@ reserve_closed_serial_helper_cb (void *cls,
                                            &execution_date),
       GNUNET_PQ_result_spec_auto_from_type ("wtid",
                                            &wtid),
-      TALER_PQ_result_spec_json ("receiver_account",
-                                &receiver_account),
+      GNUNET_PQ_result_spec_string ("receiver_account",
+                                    &receiver_account),
       TALER_PQ_result_spec_amount ("amount",
                                    &amount_with_fee),
       TALER_PQ_result_spec_amount ("closing_fee",
@@ -6277,7 +6398,7 @@ missing_wire_cb (void *cls,
       TALER_PQ_result_spec_amount ("amount_with_fee",
                                   &amount),
       TALER_PQ_result_spec_json ("wire",
-                                &wire),
+                                 &wire),
       TALER_PQ_result_spec_absolute_time ("wire_deadline",
                                           &deadline),
       GNUNET_PQ_result_spec_auto_from_type ("tiny",
@@ -6386,12 +6507,12 @@ libtaler_plugin_exchangedb_postgres_init (void *cls)
     if (GNUNET_OK !=
         GNUNET_CONFIGURATION_get_value_string (cfg,
                                                "exchangedb-postgres",
-                                               "db_conn_str",
+                                               "CONFIG",
                                                &pg->connection_cfg_str))
     {
       GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
                                  "exchangedb-postgres",
-                                 "db_conn_str");
+                                 "CONFIG");
       GNUNET_free (pg);
       return NULL;
     }
@@ -6455,19 +6576,36 @@ libtaler_plugin_exchangedb_postgres_init (void *cls)
   plugin->start_deferred_wire_out = &postgres_start_deferred_wire_out;
   plugin->store_wire_transfer_out = &postgres_store_wire_transfer_out;
   plugin->gc = &postgres_gc;
-  plugin->select_deposits_above_serial_id = 
&postgres_select_deposits_above_serial_id;
-  plugin->select_refreshs_above_serial_id = 
&postgres_select_refreshs_above_serial_id;
-  plugin->select_refunds_above_serial_id = 
&postgres_select_refunds_above_serial_id;
-  plugin->select_reserves_in_above_serial_id = 
&postgres_select_reserves_in_above_serial_id;
-  plugin->select_reserves_out_above_serial_id = 
&postgres_select_reserves_out_above_serial_id;
-  plugin->select_wire_out_above_serial_id = 
&postgres_select_wire_out_above_serial_id;
-  plugin->select_payback_above_serial_id = 
&postgres_select_payback_above_serial_id;
-  plugin->select_reserve_closed_above_serial_id = 
&postgres_select_reserve_closed_above_serial_id;
-  plugin->insert_payback_request = &postgres_insert_payback_request;
-  plugin->get_reserve_by_h_blind = &postgres_get_reserve_by_h_blind;
-  plugin->insert_denomination_revocation = 
&postgres_insert_denomination_revocation;
-  plugin->get_denomination_revocation = &postgres_get_denomination_revocation;
-  plugin->select_deposits_missing_wire = 
&postgres_select_deposits_missing_wire;
+  plugin->select_deposits_above_serial_id
+    = &postgres_select_deposits_above_serial_id;
+  plugin->select_refreshs_above_serial_id
+    = &postgres_select_refreshs_above_serial_id;
+  plugin->select_refunds_above_serial_id
+    = &postgres_select_refunds_above_serial_id;
+  plugin->select_reserves_in_above_serial_id
+    = &postgres_select_reserves_in_above_serial_id;
+  plugin->select_reserves_in_above_serial_id_by_account
+    = &postgres_select_reserves_in_above_serial_id_by_account;
+  plugin->select_reserves_out_above_serial_id
+    = &postgres_select_reserves_out_above_serial_id;
+  plugin->select_wire_out_above_serial_id
+    = &postgres_select_wire_out_above_serial_id;
+  plugin->select_wire_out_above_serial_id_by_account
+    = &postgres_select_wire_out_above_serial_id_by_account;
+  plugin->select_payback_above_serial_id
+    = &postgres_select_payback_above_serial_id;
+  plugin->select_reserve_closed_above_serial_id
+    = &postgres_select_reserve_closed_above_serial_id;
+  plugin->insert_payback_request
+    = &postgres_insert_payback_request;
+  plugin->get_reserve_by_h_blind
+    = &postgres_get_reserve_by_h_blind;
+  plugin->insert_denomination_revocation
+    = &postgres_insert_denomination_revocation;
+  plugin->get_denomination_revocation
+    = &postgres_get_denomination_revocation;
+  plugin->select_deposits_missing_wire
+    = &postgres_select_deposits_missing_wire;
   return plugin;
 }
 
diff --git a/src/exchangedb/test-exchange-db-postgres.conf 
b/src/exchangedb/test-exchange-db-postgres.conf
index 926e299..d0afc53 100644
--- a/src/exchangedb/test-exchange-db-postgres.conf
+++ b/src/exchangedb/test-exchange-db-postgres.conf
@@ -5,7 +5,7 @@ DB = postgres
 [exchangedb-postgres]
 
 #The connection string the plugin has to use for connecting to the database
-DB_CONN_STR = postgres:///talercheck
+CONFIG = postgres:///talercheck
 
 
 [exchangedb]
diff --git a/src/exchangedb/test_exchangedb.c b/src/exchangedb/test_exchangedb.c
index 36f0cce..9191f60 100644
--- a/src/exchangedb/test_exchangedb.c
+++ b/src/exchangedb/test_exchangedb.c
@@ -1,6 +1,6 @@
 /*
   This file is part of TALER
-  Copyright (C) 2014, 2015, 2016, 2017 GNUnet e.V.
+  Copyright (C) 2014-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
@@ -703,8 +703,8 @@ static void
 cb_wt_never (void *cls,
              uint64_t serial_id,
              const struct TALER_MerchantPublicKeyP *merchant_pub,
-             const char *wire_method,
              const struct GNUNET_HashCode *h_wire,
+             const json_t *wire,
              struct GNUNET_TIME_Absolute exec_time,
              const struct GNUNET_HashCode *h_contract_terms,
              const struct TALER_CoinSpendPublicKeyP *coin_pub,
@@ -747,8 +747,8 @@ static void
 cb_wt_check (void *cls,
              uint64_t rowid,
              const struct TALER_MerchantPublicKeyP *merchant_pub,
-             const char *wire_method,
              const struct GNUNET_HashCode *h_wire,
+             const json_t *wire,
              struct GNUNET_TIME_Absolute exec_time,
              const struct GNUNET_HashCode *h_contract_terms,
              const struct TALER_CoinSpendPublicKeyP *coin_pub,
@@ -759,8 +759,9 @@ cb_wt_check (void *cls,
   GNUNET_assert (0 == memcmp (merchant_pub,
                               &merchant_pub_wt,
                               sizeof (struct TALER_MerchantPublicKeyP)));
-  GNUNET_assert (0 == strcmp (wire_method,
-                              "SEPA"));
+  GNUNET_assert (0 == strcmp (json_string_value (json_object_get (wire,
+                                                                  "url")),
+                              "payto://sepa/DE67830654080004822650"));
   GNUNET_assert (0 == memcmp (h_wire,
                               &h_wire_wt,
                               sizeof (struct GNUNET_HashCode)));
@@ -842,8 +843,8 @@ deposit_cb (void *cls,
   deposit_rowid = rowid;
   if (NULL != wire)
     GNUNET_assert (GNUNET_OK ==
-                   TALER_JSON_hash (wire,
-                                    &h_wire));
+                   TALER_JSON_wire_signature_hash (wire,
+                                                   &h_wire));
   if ( (0 != memcmp (merchant_pub,
                      &deposit->merchant_pub,
                      sizeof (struct TALER_MerchantPublicKeyP))) ||
@@ -960,7 +961,7 @@ audit_reserve_in_cb (void *cls,
                      uint64_t rowid,
                      const struct TALER_ReservePublicKeyP *reserve_pub,
                      const struct TALER_Amount *credit,
-                     const json_t *sender_account_details,
+                     const char *sender_account_details,
                      const void *wire_reference,
                      size_t wire_reference_size,
                      struct GNUNET_TIME_Absolute execution_date)
@@ -1156,8 +1157,6 @@ test_wire_fees (struct TALER_EXCHANGEDB_Session *session)
 }
 
 
-static json_t *wire_out_account;
-
 static  struct TALER_Amount wire_out_amount;
 
 
@@ -1204,11 +1203,11 @@ test_wire_out (struct TALER_EXCHANGEDB_Session *session,
                const struct TALER_EXCHANGEDB_Deposit *deposit)
 {
   auditor_row_cnt = 0;
-  memset (&wire_out_wtid, 42, sizeof (wire_out_wtid));
+  memset (&wire_out_wtid,
+          42,
+          sizeof (wire_out_wtid));
   wire_out_date = GNUNET_TIME_absolute_get ();
   (void) GNUNET_TIME_round_abs (&wire_out_date);
-  wire_out_account = json_loads ("{ \"account\":\"1\" }", 0, NULL);
-  GNUNET_assert (NULL != wire_out_account);
   GNUNET_assert (GNUNET_OK ==
                  TALER_string_to_amount (CURRENCY ":1",
                                          &wire_out_amount));
@@ -1262,13 +1261,26 @@ test_wire_out (struct TALER_EXCHANGEDB_Session *session,
 
   /* Now let's fix the transient constraint violation by
      putting in the WTID into the wire_out table */
-  FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
-          plugin->store_wire_transfer_out (plugin->cls,
-                                           session,
-                                           wire_out_date,
-                                           &wire_out_wtid,
-                                           wire_out_account,
-                                           &wire_out_amount));
+  {
+    json_t *wire_out_account;
+
+    wire_out_account = json_pack ("{s:s,s:s}",
+                                  "url", 
"payto://x-taler-bank/localhost:8080/1",
+                                  "salt", "this-is-my-salt");
+    if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
+        plugin->store_wire_transfer_out (plugin->cls,
+                                         session,
+                                         wire_out_date,
+                                         &wire_out_wtid,
+                                         wire_out_account,
+                                         "my-config-section",
+                                         &wire_out_amount))
+    {
+      json_decref (wire_out_account);
+      FAILIF (1);
+    }
+    json_decref (wire_out_account);
+  }
   /* And now the commit should still succeed! */
   FAILIF (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS !=
           plugin->commit (plugin->cls,
@@ -1365,8 +1377,8 @@ wire_missing_cb (void *cls,
 
   if (NULL != wire)
     GNUNET_assert (GNUNET_OK ==
-                   TALER_JSON_hash (wire,
-                                    &h_wire));
+                   TALER_JSON_wire_signature_hash (wire,
+                                                   &h_wire));
   else
     memset (&h_wire,
             0,
@@ -1500,16 +1512,8 @@ run (void *cls)
   struct TALER_EXCHANGEDB_TransactionList *tl;
   struct TALER_EXCHANGEDB_TransactionList *tlp;
   json_t *wire;
-  json_t *sndr;
+  const char *sndr = "payto://x-taler-bank/localhost:8080/1";
   unsigned int matched;
-  const char * const json_wire_str =
-      "{ \"type\":\"SEPA\", \
-\"IBAN\":\"DE67830654080004822650\",                    \
-\"name\":\"GNUnet e.V.\",                               \
-\"bic\":\"GENODEF1SLR\",                                 \
-\"wire_transfer_deadline\":\"1449930207000\",                                \
-\"r\":123456789,                                     \
-\"address\": \"foobar\"}";
   unsigned int cnt;
   void *rr;
   size_t rr_size;
@@ -1518,9 +1522,11 @@ run (void *cls)
 
   dkp = NULL;
   rh = NULL;
-  wire = NULL;
   session = NULL;
   deposit.coin.denom_sig.rsa_signature = NULL;
+  wire = json_pack ("{s:s, s:s}",
+                    "url", "payto://sepa/DE67830654080004822650",
+                    "salt", "this-is-a-salt-value");
   ZR_BLK (&cbc);
   ZR_BLK (&cbc2);
   if (NULL ==
@@ -1576,11 +1582,10 @@ run (void *cls)
                                          &amount_with_fee));
 
   result = 4;
-  sndr = json_loads ("{ \"account\":\"1\" }", 0, NULL);
-  GNUNET_assert (NULL != sndr);
   FAILIF (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS !=
           plugin->get_latest_reserve_in_reference (plugin->cls,
                                                    session,
+                                                   "account-1",
                                                    &rr,
                                                    &rr_size));
   now = GNUNET_TIME_absolute_get ();
@@ -1592,11 +1597,13 @@ run (void *cls)
                                       &value,
                                       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);
@@ -1617,23 +1624,25 @@ run (void *cls)
                                       &value,
                                       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);
   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);
-  json_decref (sndr);
   FAILIF (GNUNET_OK !=
           check_reserve (session,
                          &reserve_pub,
@@ -1731,7 +1740,6 @@ run (void *cls)
                 TALER_amount_add (&amount_with_fee,
                                   &value,
                                   &value));
-  sndr = json_loads ("{ \"account\":\"1\" }", 0, NULL);
   GNUNET_assert (GNUNET_OK ==
                  TALER_string_to_amount (CURRENCY ":0.000010",
                                          &fee_closing));
@@ -1753,7 +1761,6 @@ run (void *cls)
                         0,
                          value.currency));
 
-  json_decref (sndr);
   result = 7;
   qs = plugin->get_reserve_history (plugin->cls,
                                     session,
@@ -1840,17 +1847,18 @@ run (void *cls)
   FAILIF (3 != auditor_row_cnt);
 
   /* Tests for deposits */
-  memset (&deposit, 0, sizeof (deposit));
+  memset (&deposit,
+          0,
+          sizeof (deposit));
   RND_BLK (&deposit.coin.coin_pub);
   deposit.coin.denom_pub = dkp->pub;
   deposit.coin.denom_sig = cbc.sig;
   RND_BLK (&deposit.csig);
   RND_BLK (&deposit.merchant_pub);
   RND_BLK (&deposit.h_contract_terms);
-  wire = json_loads (json_wire_str, 0, NULL);
   GNUNET_assert (GNUNET_OK ==
-                 TALER_JSON_hash (wire,
-                                  &deposit.h_wire));
+                 TALER_JSON_wire_signature_hash (wire,
+                                                 &deposit.h_wire));
   deposit.receiver_wire_account = wire;
   deposit.amount_with_fee = value;
   deposit.deposit_fee = fee_deposit;
@@ -1897,7 +1905,8 @@ run (void *cls)
                                              session,
                                              &deposit.h_wire,
                                              &deposit.merchant_pub,
-                                             &deposit_cb, &deposit,
+                                             &deposit_cb,
+                                             &deposit,
                                              2));
   sleep (2); /* giv deposit time to be ready */
   FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
@@ -2179,8 +2188,10 @@ run (void *cls)
   result = 0;
 
  drop:
-  if (NULL != wire)
-    json_decref (wire);
+  if ( (0 != result) &&
+       (NULL != session) )
+    plugin->rollback (plugin->cls,
+                      session);
   if (NULL != rh)
     plugin->free_reserve_history (plugin->cls,
                                   rh);
@@ -2196,6 +2207,7 @@ run (void *cls)
   if (NULL != cbc2.sig.rsa_signature)
     GNUNET_CRYPTO_rsa_signature_free (cbc2.sig.rsa_signature);
   dkp = NULL;
+  json_decref (wire);
   TALER_EXCHANGEDB_plugin_unload (plugin);
   plugin = NULL;
 }
diff --git a/src/include/taler_auditordb_plugin.h 
b/src/include/taler_auditordb_plugin.h
index 80974cc..e84fa04 100644
--- a/src/include/taler_auditordb_plugin.h
+++ b/src/include/taler_auditordb_plugin.h
@@ -1,6 +1,6 @@
 /*
   This file is part of TALER
-  Copyright (C) 2014-2017 Inria and GNUnet e.V.
+  Copyright (C) 2014-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
@@ -382,6 +382,7 @@ struct TALER_AUDITORDB_Plugin
    * @param cls the @e cls of this struct with the plugin-specific state
    * @param session connection to use
    * @param master_pub master key of the exchange
+   * @param account_name name of the wire account we are auditing
    * @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
@@ -392,6 +393,7 @@ struct TALER_AUDITORDB_Plugin
   (*insert_wire_auditor_progress)(void *cls,
                                   struct TALER_AUDITORDB_Session *session,
                                   const struct TALER_MasterPublicKeyP 
*master_pub,
+                                  const char *account_name,
                                   const struct 
TALER_AUDITORDB_WireProgressPoint *pp,
                                   const void *in_wire_off,
                                   const void *out_wire_off,
@@ -405,6 +407,7 @@ struct TALER_AUDITORDB_Plugin
    * @param cls the @e cls of this struct with the plugin-specific state
    * @param session connection to use
    * @param master_pub master key of the exchange
+   * @param account_name name of the wire account we are auditing
    * @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
@@ -415,6 +418,7 @@ struct TALER_AUDITORDB_Plugin
   (*update_wire_auditor_progress)(void *cls,
                                   struct TALER_AUDITORDB_Session *session,
                                   const struct TALER_MasterPublicKeyP 
*master_pub,
+                                  const char *account_name,
                                   const struct 
TALER_AUDITORDB_WireProgressPoint *pp,
                                   const void *in_wire_off,
                                   const void *out_wire_off,
@@ -428,6 +432,7 @@ struct TALER_AUDITORDB_Plugin
    * @param cls the @e cls of this struct with the plugin-specific state
    * @param session connection to use
    * @param master_pub master key of the exchange
+   * @param account_name name of the wire account we are auditing
    * @param[out] pp set to where the auditor is 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
@@ -438,6 +443,7 @@ struct TALER_AUDITORDB_Plugin
   (*get_wire_auditor_progress)(void *cls,
                                struct TALER_AUDITORDB_Session *session,
                                const struct TALER_MasterPublicKeyP *master_pub,
+                               const char *account_name,
                                struct TALER_AUDITORDB_WireProgressPoint *pp,
                                void **in_wire_off,
                                void **out_wire_off,
diff --git a/src/include/taler_bank_service.h b/src/include/taler_bank_service.h
index bfa0503..1cad571 100644
--- a/src/include/taler_bank_service.h
+++ b/src/include/taler_bank_service.h
@@ -217,9 +217,9 @@ struct TALER_BANK_TransferDetails
   char *wire_transfer_subject;
 
   /**
-   * The other account that was involved
+   * payto://-URL of the other account that was involved
    */
-  json_t *account_details;
+  char *account_url;
 };
 
 
@@ -347,4 +347,29 @@ void
 TALER_BANK_reject_cancel (struct TALER_BANK_RejectHandle *rh);
 
 
+/**
+ * Convenience method for parsing configuration section with bank
+ * authentication data.  The section must contain an option
+ * "METHOD", plus other options that depend on the METHOD specified.
+ *
+ * @param cfg configuration to parse
+ * @param section the section with the configuration data
+ * @param auth[out] set to the configuration data found
+ * @return #GNUNET_OK on success
+ */
+int
+TALER_BANK_auth_parse_cfg (const struct GNUNET_CONFIGURATION_Handle *cfg,
+                           const char *section,
+                           struct TALER_BANK_AuthenticationData *auth);
+
+
+/**
+ * Free memory inside of @a auth (but not auth itself).
+ * Dual to #TALER_BANK_auth_parse_cfg().
+ *
+ * @param auth authentication data to free
+ */
+void
+TALER_BANK_auth_free (struct TALER_BANK_AuthenticationData *auth);
+
 #endif  /* _TALER_BANK_SERVICE_H */
diff --git a/src/include/taler_crypto_lib.h b/src/include/taler_crypto_lib.h
index d45e7bb..b22c55c 100644
--- a/src/include/taler_crypto_lib.h
+++ b/src/include/taler_crypto_lib.h
@@ -1,6 +1,6 @@
 /*
   This file is part of TALER
-  Copyright (C) 2014, 2015, 2016, 2017 Taler Systems SA
+  Copyright (C) 2014-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
@@ -730,4 +730,51 @@ TALER_refresh_get_commitment (struct 
TALER_RefreshCommitmentP *rc,
                               const struct TALER_Amount *amount_with_fee);
 
 
+/* **************** /wire account offline signing **************** */
+
+
+/**
+ * Compute the hash of the given wire details.   The resulting
+ * hash is what is put into the contract.
+ *
+ * @param payto_url bank account
+ * @param salt salt used to eliminate brute-force inversion
+ * @param hc[out] set to the hash
+ */
+void
+TALER_wire_signature_hash (const char *payto_url,
+                           const char *salt,
+                           struct GNUNET_HashCode *hc);
+
+/**
+ * Check the signature in @a wire_s.
+ *
+ * @param payto_url URL that is signed
+ * @param salt the salt used to salt the @a payto_url when hashing
+ * @param master_pub master public key of the exchange
+ * @param master_sig signature of the exchange
+ * @return #GNUNET_OK if signature is valid
+ */
+int
+TALER_wire_signature_check (const char *payto_url,
+                            const char *salt,
+                            const struct TALER_MasterPublicKeyP *master_pub,
+                            const struct TALER_MasterSignatureP *master_sig);
+
+
+/**
+ * Create a signed wire statement for the given account.
+ *
+ * @param payto_url account specification
+ * @param salt the salt used to salt the @a payto_url when hashing
+ * @param master_priv private key to sign with
+ * @param master_sig[out] where to write the signature
+ */
+void
+TALER_wire_signature_make (const char *payto_url,
+                           const char *salt,
+                           const struct TALER_MasterPrivateKeyP *master_priv,
+                           struct TALER_MasterSignatureP *master_sig);
+
+
 #endif
diff --git a/src/include/taler_error_codes.h b/src/include/taler_error_codes.h
index 1a20889..dbde04d 100644
--- a/src/include/taler_error_codes.h
+++ b/src/include/taler_error_codes.h
@@ -165,7 +165,15 @@ enum TALER_ErrorCode
    */
   TALER_EC_INTERNAL_LOGIC_ERROR = 1011,
 
+  /**
+   * The method specified in a payto:// URL is not one we expected.
+   */
+  TALER_EC_PAYTO_WRONG_METHOD = 1012,
 
+  /**
+   * The PAYTO URL is malformed.
+   */
+  TALER_EC_PAYTO_MALFORMED = 1013,
 
   /* ********** request-specific error codes ************* */
 
@@ -1535,6 +1543,20 @@ enum TALER_ErrorCode
    */
   TALER_EC_TEST_RSA_SIGN_ERROR = 4005,
 
+
+  /**
+   * The JSON in the server's response was malformed.  This response
+   * is provided with HTTP status code of 0.
+   */
+  TALER_EC_SERVER_JSON_INVALID = 5000,
+
+  /**
+   * A signature in the server's response was malformed.  This response
+   * is provided with HTTP status code of 0.
+   */
+  TALER_EC_SERVER_SIGNATURE_INVALID = 5001,
+
+
   /* *************** Taler BANK/FAKEBANK error codes *************** */
 
   /**
diff --git a/src/include/taler_exchange_service.h 
b/src/include/taler_exchange_service.h
index 54188e3..e5a26e2 100644
--- a/src/include/taler_exchange_service.h
+++ b/src/include/taler_exchange_service.h
@@ -479,40 +479,32 @@ struct TALER_EXCHANGE_WireAggregateFees
 
 
 /**
- * Function called with information about the wire fees
- * for each wire method.
- *
- * @param cls closure
- * @param wire_method name of the wire method (i.e. "sepa")
- * @param fees fee structure for this method
+ * Information about a wire account of the exchange.
  */
-typedef void
-(*TALER_EXCHANGE_WireFeeCallback)(void *cls,
-                                  const char *wire_method,
-                                  const struct 
TALER_EXCHANGE_WireAggregateFees *fees);
+struct TALER_EXCHANGE_WireAccount
+{
+  /**
+   * payto://-URL of the exchange.
+   */
+  const char *url;
 
+  /**
+   * Salt used to generate @e master_sig.
+   */
+  const char *salt;
 
-/**
- * Obtain information about wire fees encoded in @a obj
- * by wire method.
- *
- * @param master_pub public key to use to verify signatures, NULL to not verify
- * @param obj wire information as encoded in the 
#TALER_EXCHANGE_WireResultCallback
- * @param cb callback to invoke for the fees
- * @param cb_cls closure for @a cb
- * @return #GNUNET_OK in success, #GNUNET_SYSERR if @a obj is ill-formed
- */
-int
-TALER_EXCHANGE_wire_get_fees (const struct TALER_MasterPublicKeyP *master_pub,
-                              const json_t *obj,
-                              TALER_EXCHANGE_WireFeeCallback cb,
-                              void *cb_cls);
+  /**
+   * Signature of the exchange over the account (was checked by the API).
+   */
+  struct TALER_MasterSignatureP master_sig;
 
+  /**
+   * Linked list of wire fees the exchange charges for
+   * accounts of the wire method matching @e url.
+   */
+  const struct TALER_EXCHANGE_WireAggregateFees *fees;
 
-/**
- * @brief A Wire format inquiry handle
- */
-struct TALER_EXCHANGE_WireHandle;
+};
 
 
 /**
@@ -526,15 +518,21 @@ struct TALER_EXCHANGE_WireHandle;
  * @param http_status HTTP response code, #MHD_HTTP_OK (200) for successful 
request;
  *                    0 if the exchange's reply is bogus (fails to follow the 
protocol)
  * @param ec taler-specific error code, #TALER_EC_NONE on success
- * @param obj the received JSON reply, if successful this should be the wire
- *            format details as provided by /wire, or NULL if the
- *            reply was not in JSON format.
+ * @param accounts_len length of the @a accounts array
+ * @param accounts list of wire accounts of the exchange, NULL on error
  */
 typedef void
 (*TALER_EXCHANGE_WireResultCallback) (void *cls,
                                       unsigned int http_status,
                                      enum TALER_ErrorCode ec,
-                                      const json_t *obj);
+                                      unsigned int accounts_len,
+                                      const struct TALER_EXCHANGE_WireAccount 
*accounts);
+
+
+/**
+ * @brief A Wire format inquiry handle
+ */
+struct TALER_EXCHANGE_WireHandle;
 
 
 /**
@@ -850,9 +848,9 @@ struct TALER_EXCHANGE_ReserveHistory
      */
     struct {
       /**
-       * Sender account information for the incoming transfer.
+       * Sender account payto://-URL of the incoming transfer.
        */
-      json_t *sender_account_details;
+      char *sender_url;
 
       /**
        * Information that uniquely identifies the wire transfer.
diff --git a/src/include/taler_exchangedb_lib.h 
b/src/include/taler_exchangedb_lib.h
index e4284c2..b89dd08 100644
--- a/src/include/taler_exchangedb_lib.h
+++ b/src/include/taler_exchangedb_lib.h
@@ -406,4 +406,72 @@ TALER_EXCHANGEDB_fees_write (const char *filename,
 void
 TALER_EXCHANGEDB_fees_free (struct TALER_EXCHANGEDB_AggregateFees *af);
 
+
+/**
+ * Information about an account from the configuration.
+ */
+struct TALER_EXCHANGEDB_AccountInfo
+{
+  /**
+   * Section in the configuration file that specifies the
+   * account. Must start with "account-".
+   */
+  const char *section_name;
+
+  /**
+   * Name of the wire plugin that should be used to access
+   * the account.
+   */
+  const char *plugin_name;
+
+  /**
+   * payto://-URL of the account.
+   */
+  const char *payto_url;
+
+  /**
+   * Filename containing the signed /wire response, or NULL
+   * if not given.
+   */
+  const char *wire_response_filename;
+
+  /**
+   * #GNUNET_YES if this account is enabed to be debited
+   * by the taler-exchange-aggregator.
+   */
+  int debit_enabled;
+
+  /**
+   * #GNUNET_YES if this account is enabed to be credited by wallets
+   * and needs to be watched by the taler-exchange-wirewatch.
+   * Also, the account will only be included in /wire if credit
+   * is enabled.
+   */
+  int credit_enabled;
+};
+
+
+/**
+ * Function called with information about a wire account.
+ *
+ * @param cls closure
+ * @param ai account information
+ */
+typedef void
+(*TALER_EXCHANGEDB_AccountCallback)(void *cls,
+                                    const struct TALER_EXCHANGEDB_AccountInfo 
*ai);
+
+/**
+ * Parse the configuration to find account information.
+ *
+ * @param cfg configuration to use
+ * @param cb callback to invoke
+ * @param cb_cls closure for @a cb
+ */
+void
+TALER_EXCHANGEDB_find_accounts (const struct GNUNET_CONFIGURATION_Handle *cfg,
+                                TALER_EXCHANGEDB_AccountCallback cb,
+                                void *cb_cls);
+
+
 #endif
diff --git a/src/include/taler_exchangedb_plugin.h 
b/src/include/taler_exchangedb_plugin.h
index 3367755..fb5b47d 100644
--- a/src/include/taler_exchangedb_plugin.h
+++ b/src/include/taler_exchangedb_plugin.h
@@ -21,7 +21,6 @@
  */
 #ifndef TALER_EXCHANGEDB_PLUGIN_H
 #define TALER_EXCHANGEDB_PLUGIN_H
-
 #include <jansson.h>
 #include <gnunet/gnunet_util_lib.h>
 #include <gnunet/gnunet_db_lib.h>
@@ -52,9 +51,10 @@ struct TALER_EXCHANGEDB_BankTransfer
   struct GNUNET_TIME_Absolute execution_date;
 
   /**
-   * Detailed wire information about the sending account.
+   * Detailed wire information about the sending account
+   * in "payto://" format.
    */
-  json_t *sender_account_details;
+  char *sender_account_details;
 
   /**
    * Data uniquely identifying the wire transfer (wire transfer-type specific)
@@ -97,9 +97,10 @@ struct TALER_EXCHANGEDB_ClosingTransfer
   struct GNUNET_TIME_Absolute execution_date;
 
   /**
-   * Detailed wire information about the receiving account.
+   * Detailed wire information about the receiving account
+   * in payto://-format.
    */
-  json_t *receiver_account_details;
+  char *receiver_account_details;
 
   /**
    * Detailed wire transfer information that uniquely identifies the
@@ -361,6 +362,7 @@ struct TALER_EXCHANGEDB_Deposit
 
   /**
    * Detailed information about the receiver for executing the transaction.
+   * Includes URL in payto://-format and salt.
    */
   json_t *receiver_wire_account;
 
@@ -638,7 +640,8 @@ struct TALER_EXCHANGEDB_Session;
  * @param h_contract_terms hash of the proposal data known to merchant and 
customer
  * @param wire_deadline by which the merchant adviced that he would like the
  *        wire transfer to be executed
- * @param receiver_wire_account wire details for the merchant, NULL from 
iterate_matching_deposits()
+ * @param receiver_wire_account wire details for the merchant, includes
+ *        'url' in payto://-format; NULL from iterate_matching_deposits()
  * @return transaction status code, #GNUNET_DB_STATUS_SUCCESS_ONE_RESULT to 
continue to iterate
  */
 typedef enum GNUNET_DB_QueryStatus
@@ -687,7 +690,8 @@ typedef void
  *        to get a refund
  * @param wire_deadline by which the merchant adviced that he would like the
  *        wire transfer to be executed
- * @param receiver_wire_account wire details for the merchant, NULL from 
iterate_matching_deposits()
+ * @param receiver_wire_account wire details for the merchant including 'url' 
in payto://-format;
+ *        NULL from iterate_matching_deposits()
  * @param done flag set if the deposit was already executed (or not)
  * @return #GNUNET_OK to continue to iterate, #GNUNET_SYSERR to stop
  */
@@ -837,7 +841,7 @@ typedef int
  * @param rowid unique serial ID for the refresh session in our DB
  * @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 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 execution_date when did we receive the funds
@@ -848,7 +852,7 @@ typedef int
                                       uint64_t rowid,
                                       const struct TALER_ReservePublicKeyP 
*reserve_pub,
                                       const struct TALER_Amount *credit,
-                                      const json_t *sender_account_details,
+                                      const char *sender_account_details,
                                       const void *wire_reference,
                                       size_t wire_reference_size,
                                       struct GNUNET_TIME_Absolute 
execution_date);
@@ -923,8 +927,8 @@ typedef void
  * @param cls closure
  * @param rowid which row in the table is the information from (for 
diagnostics)
  * @param merchant_pub public key of the merchant (should be same for all 
callbacks with the same @e cls)
- * @param wire_method which wire plugin was used for the transfer?
  * @param h_wire hash of wire transfer details of the merchant (should be same 
for all callbacks with the same @e cls)
+ * @param account_details which account did the transfer go to?
  * @param exec_time execution time of the wire transfer (should be same for 
all callbacks with the same @e cls)
  * @param h_contract_terms which proposal was this payment about
  * @param coin_pub which public key was this payment about
@@ -935,8 +939,8 @@ typedef void
 (*TALER_EXCHANGEDB_WireTransferDataCallback)(void *cls,
                                              uint64_t rowid,
                                              const struct 
TALER_MerchantPublicKeyP *merchant_pub,
-                                             const char *wire_method,
                                              const struct GNUNET_HashCode 
*h_wire,
+                                             const json_t *account_details,
                                              struct GNUNET_TIME_Absolute 
exec_time,
                                              const struct GNUNET_HashCode 
*h_contract_terms,
                                              const struct 
TALER_CoinSpendPublicKeyP *coin_pub,
@@ -952,7 +956,7 @@ typedef void
  * @param rowid identifier of the respective row in the database
  * @param date timestamp of the wire transfer (roughly)
  * @param wtid wire transfer subject
- * @param wire wire transfer details of the receiver
+ * @param wire wire transfer details of the receiver, including "url" in 
payto://-format
  * @param amount amount that was wired
  * @return #GNUNET_OK to continue, #GNUNET_SYSERR to stop iteration
  */
@@ -1019,7 +1023,7 @@ typedef int
  * @param amount_with_fee how much did we debit the reserve
  * @param closing_fee how much did we charge for closing the reserve
  * @param reserve_pub public key of the reserve
- * @param receiver_account where did we send the funds
+ * @param receiver_account where did we send the funds, in payto://-format
  * @param wtid identifier used for the wire transfer
  * @return #GNUNET_OK to continue to iterate, #GNUNET_SYSERR to stop
  */
@@ -1030,7 +1034,7 @@ typedef int
                                          const struct TALER_Amount 
*amount_with_fee,
                                          const struct TALER_Amount 
*closing_fee,
                                          const struct TALER_ReservePublicKeyP 
*reserve_pub,
-                                         const json_t *receiver_account,
+                                         const char *receiver_account,
                                          const struct 
TALER_WireTransferIdentifierRawP *wtid);
 
 
@@ -1040,7 +1044,7 @@ typedef int
  * @param cls closure
  * @param reserve_pub public key of the reserve
  * @param left amount left in the reserve
- * @param account_details information about the reserve's bank account
+ * @param account_details information about the reserve's bank account, in 
payto://-format
  * @param expiration_date when did the reserve expire
  * @return transaction status code to pass on
  */
@@ -1048,7 +1052,7 @@ typedef enum GNUNET_DB_QueryStatus
 (*TALER_EXCHANGEDB_ReserveExpiredCallback)(void *cls,
                                           const struct TALER_ReservePublicKeyP 
*reserve_pub,
                                           const struct TALER_Amount *left,
-                                          const json_t *account_details,
+                                          const char *account_details,
                                           struct GNUNET_TIME_Absolute 
expiration_date);
 
 
@@ -1082,7 +1086,7 @@ typedef void
  * @param rowid deposit table row of the coin's deposit
  * @param coin_pub public key of the coin
  * @param amount value of the deposit, including fee
- * @param wire where should the funds be wired
+ * @param wire where should the funds be wired, including 'url' in 
payto://-format
  * @param deadline what was the requested wire transfer deadline
  * @param tiny did the exchange defer this transfer because it is too small?
  * @param done did the exchange claim that it made a transfer?
@@ -1259,7 +1263,7 @@ struct TALER_EXCHANGEDB_Plugin
    * @param reserve_pub public key of the reserve
    * @param balance the amount that has to be added to the reserve
    * @param execution_time when was the amount added
-   * @param sender_account_details information about the sender's bank account
+   * @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
    * @return transaction status code
@@ -1270,7 +1274,8 @@ struct TALER_EXCHANGEDB_Plugin
                          const struct TALER_ReservePublicKeyP *reserve_pub,
                          const struct TALER_Amount *balance,
                          struct GNUNET_TIME_Absolute execution_time,
-                         const json_t *sender_account_details,
+                         const char *sender_account_details,
+                         const char *exchange_account_name,
                          const void *wire_reference,
                          size_t wire_reference_size);
 
@@ -1287,6 +1292,7 @@ struct TALER_EXCHANGEDB_Plugin
   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);
 
@@ -1781,7 +1787,7 @@ struct TALER_EXCHANGEDB_Plugin
    * @param session database connection
    * @param reserve_pub which reserve is this about?
    * @param execution_date when did we perform the transfer?
-   * @param receiver_account to which account do we transfer?
+   * @param receiver_account to which account do we transfer, in 
payto://-format
    * @param wtid identifier for the wire transfer
    * @param amount_with_fee amount we charged to the reserve
    * @param closing_fee how high is the closing fee
@@ -1792,7 +1798,7 @@ struct TALER_EXCHANGEDB_Plugin
                           struct TALER_EXCHANGEDB_Session *session,
                           const struct TALER_ReservePublicKeyP *reserve_pub,
                           struct GNUNET_TIME_Absolute execution_date,
-                          const json_t *receiver_account,
+                          const char *receiver_account,
                           const struct TALER_WireTransferIdentifierRawP *wtid,
                           const struct TALER_Amount *amount_with_fee,
                           const struct TALER_Amount *closing_fee);
@@ -1869,8 +1875,11 @@ struct TALER_EXCHANGEDB_Plugin
    * @param session database connection
    * @param date time of the wire transfer
    * @param wtid subject of the wire transfer
-   * @param wire_account details about the receiver account of the wire 
transfer
+   * @param wire_account details about the receiver account of the wire 
transfer,
+   *        including 'url' in payto://-format
    * @param amount amount that was transmitted
+   * @param exchange_account_section configuration section of the exchange 
specifying the
+   *        exchange's bank account being used
    * @return transaction status code
    */
   enum GNUNET_DB_QueryStatus
@@ -1879,6 +1888,7 @@ struct TALER_EXCHANGEDB_Plugin
                              struct GNUNET_TIME_Absolute date,
                              const struct TALER_WireTransferIdentifierRawP 
*wtid,
                              const json_t *wire_account,
+                             const char *exchange_account_section,
                              const struct TALER_Amount *amount);
 
 
@@ -1977,11 +1987,32 @@ struct TALER_EXCHANGEDB_Plugin
                                         void *cb_cls);
 
   /**
+   * Select inbound wire transfers into reserves_in above @a serial_id
+   * in monotonically increasing order by @a account_name.
+   *
+   * @param cls closure
+   * @param session database connection
+   * @param account_name name of the account for which we do the selection
+   * @param serial_id highest serial ID to exclude (select strictly larger)
+   * @param cb function to call on each result
+   * @param cb_cls closure for @a cb
+   * @return transaction status code
+   */
+  enum GNUNET_DB_QueryStatus
+  (*select_reserves_in_above_serial_id_by_account)(void *cls,
+                                                   struct 
TALER_EXCHANGEDB_Session *session,
+                                                   const char *account_name,
+                                                   uint64_t serial_id,
+                                                   
TALER_EXCHANGEDB_ReserveInCallback cb,
+                                                   void *cb_cls);
+
+  /**
    * Select withdraw operations from reserves_out above @a serial_id
    * in monotonically increasing order.
    *
    * @param cls closure
    * @param session database connection
+   * @param account_name name of the account for which we do the selection
    * @param serial_id highest serial ID to exclude (select strictly larger)
    * @param cb function to call on each result
    * @param cb_cls closure for @a cb
@@ -1994,7 +2025,6 @@ struct TALER_EXCHANGEDB_Plugin
                                          TALER_EXCHANGEDB_WithdrawCallback cb,
                                          void *cb_cls);
 
-
   /**
    * Function called to select outgoing wire transfers the exchange
    * executed, ordered by serial ID (monotonically increasing).
@@ -2013,6 +2043,26 @@ struct TALER_EXCHANGEDB_Plugin
                                      TALER_EXCHANGEDB_WireTransferOutCallback 
cb,
                                      void *cb_cls);
 
+  /**
+   * Function called to select outgoing wire transfers the exchange
+   * executed, ordered by serial ID (monotonically increasing).
+   *
+   * @param cls closure
+   * @param session database connection
+   * @param account_name name to select by
+   * @param serial_id lowest serial ID to include (select larger or equal)
+   * @param cb function to call for ONE unfinished item
+   * @param cb_cls closure for @a cb
+   * @return transaction status code
+   */
+  enum GNUNET_DB_QueryStatus
+  (*select_wire_out_above_serial_id_by_account)(void *cls,
+                                                struct 
TALER_EXCHANGEDB_Session *session,
+                                                const char *account_name,
+                                                uint64_t serial_id,
+                                                
TALER_EXCHANGEDB_WireTransferOutCallback cb,
+                                                void *cb_cls);
+
 
   /**
    * Function called to select payback requests the exchange
diff --git a/src/include/taler_json_lib.h b/src/include/taler_json_lib.h
index 6d019ec..0504ddf 100644
--- a/src/include/taler_json_lib.h
+++ b/src/include/taler_json_lib.h
@@ -126,6 +126,65 @@ enum TALER_ErrorCode
 TALER_JSON_get_error_code (const json_t *json);
 
 
+/* **************** /wire account offline signing **************** */
+
+/**
+ * Compute the hash of the given wire details.   The resulting
+ * hash is what is put into the contract.
+ *
+ * @param wire_s wire details to hash
+ * @param hc[out] set to the hash
+ * @return #GNUNET_OK on success, #GNUNET_SYSERR if @a wire_s is malformed
+ */
+int
+TALER_JSON_wire_signature_hash (const json_t *wire_s,
+                                struct GNUNET_HashCode *hc);
+
+/**
+ * Check the signature in @a wire_s.
+ *
+ * @param wire_s signed wire information of an exchange
+ * @param master_pub master public key of the exchange
+ * @return #GNUNET_OK if signature is valid
+ */
+int
+TALER_JSON_wire_signature_check (const json_t *wire_s,
+                                 const struct TALER_MasterPublicKeyP 
*master_pub);
+
+
+/**
+ * Create a signed wire statement for the given account.
+ *
+ * @param payto_url account specification
+ * @param master_priv private key to sign with, NULL to not sign
+ */
+json_t *
+TALER_JSON_wire_signature_make (const char *payto_url,
+                                const struct TALER_MasterPrivateKeyP 
*master_priv);
+
+
+/**
+ * Obtain the wire method associated with the given
+ * wire account details.  @a wire_s must contain a payto://-URL
+ * under 'url'.
+ *
+ * @return NULL on error
+ */
+char *
+TALER_JSON_wire_to_method (const json_t *wire_s);
+
+
+/**
+ * Obtain the payto://-URL associated with the given
+ * wire account details.  @a wire_s must contain a payto://-URL
+ * under 'url'.
+ *
+ * @return NULL on error
+ */
+char *
+TALER_JSON_wire_to_payto (const json_t *wire_s);
+
+
 #endif /* TALER_JSON_LIB_H_ */
 
 /* End of taler_json_lib.h */
diff --git a/src/include/taler_signatures.h b/src/include/taler_signatures.h
index c281d21..f1148be 100644
--- a/src/include/taler_signatures.h
+++ b/src/include/taler_signatures.h
@@ -62,18 +62,6 @@
 #define TALER_SIGNATURE_MASTER_DENOMINATION_KEY_VALIDITY 1025
 
 /**
- * Signature where the Exchange confirms its SEPA details in
- * the /wire response.
- */
-#define TALER_SIGNATURE_MASTER_SEPA_DETAILS 1026
-
-/**
- * Signature where the Exchange confirms its TEST details in
- * the /wire response.
- */
-#define TALER_SIGNATURE_MASTER_TEST_DETAILS 1027
-
-/**
  * Fees charged per (aggregate) wire transfer to the merchant.
  */
 #define TALER_SIGNATURE_MASTER_WIRE_FEES 1028
@@ -83,6 +71,12 @@
  */
 #define TALER_SIGNATURE_MASTER_DENOMINATION_KEY_REVOKED 1029
 
+/**
+ * Signature where the Exchange confirms its SEPA details in
+ * the /wire response.
+ */
+#define TALER_SIGNATURE_MASTER_WIRE_DETAILS 1030
+
 /*********************************************/
 /* Exchange online signatures (with signing key) */
 /*********************************************/
@@ -891,16 +885,15 @@ struct TALER_MasterWireDetailsPS
 {
 
   /**
-   * Purpose is #TALER_SIGNATURE_MASTER_SEPA_DETAILS or
-   * #TALER_SIGNATURE_MASTER_TEST_DETAILS.
+   * Purpose is #TALER_SIGNATURE_MASTER_WIRE_DETAILS.
    */
   struct GNUNET_CRYPTO_EccSignaturePurpose purpose;
 
   /**
-   * Hash over the account holder's name, IBAN and BIC
-   * code (all as 0-terminated strings).
+   * Hash over the account holder's payto:// URL and
+   * the salt, as done by #TALER_wire_signature_hash().
    */
-  struct GNUNET_HashCode h_sepa_details GNUNET_PACKED;
+  struct GNUNET_HashCode h_wire_details GNUNET_PACKED;
 
 };
 
diff --git a/src/include/taler_testing_lib.h b/src/include/taler_testing_lib.h
index 3914208..dce92ce 100644
--- a/src/include/taler_testing_lib.h
+++ b/src/include/taler_testing_lib.h
@@ -66,20 +66,22 @@
 #define TALER_TESTING_MAKE_TRAIT_ROW_ID(data) \
   TALER_TESTING_make_trait_uint64 (3, data)
 
+
 /**
- * Allocate and return a piece of wire-details.  Mostly, it adds
- * the bank_url to the JSON.
+ * Allocate and return a piece of wire-details.  Combines
+ * the @a account_no and the @a bank_url to a
+ * @a payto://-URL and adds some salt to create the JSON.
  *
- * @param template the wire-details template.
+ * @param account_no account number
  * @param bank_url the bank_url
- *
- * @return the filled out and stringified wire-details.  To
- *         be manually free'd.
+ * @return JSON describing the account, including the
+ *         payto://-URL of the account, must be manually decref'd
  */
-char *
-TALER_TESTING_make_wire_details (const char *template,
+json_t *
+TALER_TESTING_make_wire_details (unsigned long long account_no,
                                  const char *bank_url);
 
+
 /**
  * Find denomination key matching the given amount.
  *
@@ -130,10 +132,12 @@ TALER_TESTING_url_port_free (const char *url);
  * If everything is OK, return the configured URL of the fakebank.
  *
  * @param config_filename configuration file to use
+ * @param config_section which account to use (must match x-taler-bank)
  * @return NULL on error, fakebank URL otherwise
  */
 char *
-TALER_TESTING_prepare_fakebank (const char *config_filename);
+TALER_TESTING_prepare_fakebank (const char *config_filename,
+                                const char *config_section);
 
 
 /* ******************* Generic interpreter logic ************ */
@@ -613,8 +617,8 @@ TALER_TESTING_cmd_status (const char *label,
  *        coins, this parameter selects which one in that array
  *        This value is currently ignored, as only one-coin
  *        withdrawals are implemented.
- * @param wire_details bank details of the merchant performing the
- *        deposit
+ * @param wire_details JSON including payto://-URL of the merchant performing 
the
+ *        deposit, reference is captured by this command
  * @param contract_terms contract terms to be signed over by the
  *        coin
  * @param refund_deadline refund deadline
@@ -625,12 +629,12 @@ TALER_TESTING_cmd_status (const char *label,
  * @return the deposit command to be run by the interpreter
  */
 struct TALER_TESTING_Command
-TALER_TESTING_cmd_deposit 
+TALER_TESTING_cmd_deposit
   (const char *label,
    struct TALER_EXCHANGE_Handle *exchange,
    const char *coin_reference,
    unsigned int coin_index,
-   char *wire_details,
+   json_t *wire_details,
    const char *contract_terms,
    struct GNUNET_TIME_Relative refund_deadline,
    const char *amount,
@@ -1209,7 +1213,7 @@ int
 TALER_TESTING_get_trait_wire_details
   (const struct TALER_TESTING_Command *cmd,
    unsigned int index,
-   const char **wire_details);
+   const json_t **wire_details);
 
 
 /**
@@ -1223,7 +1227,7 @@ TALER_TESTING_get_trait_wire_details
 struct TALER_TESTING_Trait
 TALER_TESTING_make_trait_wire_details
   (unsigned int index,
-   const char *wire_details);
+   const json_t *wire_details);
 
 /**
  * Obtain a private key from a "peer".  Used e.g. to obtain
@@ -1300,11 +1304,11 @@ TALER_TESTING_get_trait_transfer_subject
 
 
 /**
- * Offer wire details in a trait.
+ * Offer wire wire transfer subject in a trait.
  *
  * @param index always (?) zero, as one command sticks
  *        to one bank account
- * @param wire_details wire details to offer
+ * @param transfer_subject wire transfer subject to offer
  * @return the trait, to be put in the traits array of the command
  */
 struct TALER_TESTING_Trait
diff --git a/src/include/taler_wire_lib.h b/src/include/taler_wire_lib.h
index 68c36e8..0cf38d6 100644
--- a/src/include/taler_wire_lib.h
+++ b/src/include/taler_wire_lib.h
@@ -1,6 +1,6 @@
 /*
   This file is part of TALER
-  Copyright (C) 2016 GNUnet e.V.
+  Copyright (C) 2016,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
@@ -26,6 +26,16 @@
 
 
 /**
+ * Obtain the payment method from a @a payto_url
+ *
+ * @param payto_url the URL to parse
+ * @return NULL on error (malformed @a payto_url)
+ */
+char *
+TALER_WIRE_payto_get_method (const char *payto_url);
+
+
+/**
  * Load a WIRE plugin.
  *
  * @param cfg configuration to use
@@ -45,28 +55,4 @@ void
 TALER_WIRE_plugin_unload (struct TALER_WIRE_Plugin *plugin);
 
 
-/**
- * Signature of a function to be called on each enabled
- * wire plugin.
- *
- * @param cls closure
- * @param name name of the enabled plugin
- */
-typedef void
-(*TALER_WIRE_EnabledCallback)(void *cls,
-                              const char *name);
-
-
-/**
- * Check which wire plugins are enabled in @a cfg and call @a cb for each one.
- *
- * @param cfg configuration to use
- * @param cb callback to invoke
- * @param cb_cls closure for @a cb
- */
-void
-TALER_WIRE_find_enabled (const struct GNUNET_CONFIGURATION_Handle *cfg,
-                         TALER_WIRE_EnabledCallback cb,
-                         void *cb_cls);
-
 #endif
diff --git a/src/include/taler_wire_plugin.h b/src/include/taler_wire_plugin.h
index c0e2960..2758d2d 100644
--- a/src/include/taler_wire_plugin.h
+++ b/src/include/taler_wire_plugin.h
@@ -22,7 +22,6 @@
 #define TALER_WIRE_PLUGIN_H
 
 #include <gnunet/gnunet_util_lib.h>
-#include <jansson.h>
 #include "taler_util.h"
 #include "taler_error_codes.h"
 #include "taler_bank_service.h" /* for `enum TALER_BANK_Direction` and `struct 
TALER_BANK_TransferDetails` */
@@ -72,9 +71,9 @@ struct TALER_WIRE_TransferDetails
   char *wtid_s;
 
   /**
-   * The other account that was involved
+   * payto://-URL of the other account that was involved
    */
-  json_t *account_details;
+  char *account_url;
 };
 
 
@@ -161,6 +160,13 @@ struct TALER_WIRE_Plugin
   char *library_name;
 
   /**
+   * Which wire method (payto://METHOD/") is supported by this plugin?
+   * For example, "sepa" or "x-taler-bank".
+   */
+  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
    * payment, but SEPA only supports 0.01 EUR.  This function would
@@ -177,62 +183,27 @@ struct TALER_WIRE_Plugin
 
 
   /**
-   * Obtain wire transfer details in the plugin-specific format
-   * from the configuration.
-   *
-   * @param cls closure
-   * @param cfg configuration with details about wire accounts
-   * @param account_name which section in the configuration should we parse
-   * @return NULL if @a cfg fails to have valid wire details for @a 
account_name
-   */
-  json_t *
-  (*get_wire_details)(void *cls,
-                      const struct GNUNET_CONFIGURATION_Handle *cfg,
-                      const char *account_name);
-
-
-  /**
-   * Sign wire transfer details in the plugin-specific format.
-   *
-   * @param cls closure
-   * @param in wire transfer details in JSON format
-   * @param key private signing key to use
-   * @param salt salt to add
-   * @param[out] sig where to write the signature
-   * @return #GNUNET_OK on success
-   */
-  int
-  (*sign_wire_details)(void *cls,
-                       const json_t *in,
-                       const struct TALER_MasterPrivateKeyP *key,
-                       const struct GNUNET_HashCode *salt,
-                       struct TALER_MasterSignatureP *sig);
-
-
-  /**
-   * Check if the given wire format JSON object is correctly formatted
+   * 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 wire the JSON wire format object
-   * @param master_pub public key of the exchange to verify against
-   * @param[out] emsg set to an error message, unless we return #TALER_EC_NONE;
-   *             error message must be freed by the caller using GNUNET_free()
+   * @param account_url the payto:// URL
    * @return #TALER_EC_NONE if correctly formatted
    */
   enum TALER_ErrorCode
   (*wire_validate) (void *cls,
-                    const json_t *wire,
-                    const struct TALER_MasterPublicKeyP *master_pub,
-                    char **emsg);
+                    const char *account_url);
 
 
   /**
    * Prepare for exeuction of a wire transfer.
    *
    * @param cls the @e cls of this struct with the plugin-specific state
-   * @param wire valid wire account information
+   * @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 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
@@ -240,13 +211,15 @@ struct TALER_WIRE_Plugin
    */
   struct TALER_WIRE_PrepareHandle *
   (*prepare_wire_transfer) (void *cls,
-                            const json_t *wire,
+                            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.
@@ -305,6 +278,8 @@ struct TALER_WIRE_Plugin
    * (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
@@ -316,6 +291,7 @@ struct TALER_WIRE_Plugin
    */
   struct TALER_WIRE_HistoryHandle *
   (*get_history) (void *cls,
+                  const char *account_section,
                   enum TALER_BANK_Direction direction,
                   const void *start_off,
                   size_t start_off_len,
@@ -323,6 +299,7 @@ struct TALER_WIRE_Plugin
                   TALER_WIRE_HistoryResultCallback hres_cb,
                   void *hres_cb_cls);
 
+
   /**
    * Cancel going over the account's history.
    *
@@ -345,6 +322,8 @@ struct TALER_WIRE_Plugin
    * 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
@@ -353,11 +332,13 @@ struct TALER_WIRE_Plugin
    */
   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);
 
+
   /**
    * Cancel ongoing reject operation.  Note that the rejection may still
    * proceed. Basically, if this function is called, the rejection may
diff --git a/src/json/Makefile.am b/src/json/Makefile.am
index d26f731..4b40e94 100644
--- a/src/json/Makefile.am
+++ b/src/json/Makefile.am
@@ -11,12 +11,14 @@ lib_LTLIBRARIES = \
 
 libtalerjson_la_SOURCES = \
   json.c \
-  json_helper.c
+  json_helper.c \
+  json_wire.c
 libtalerjson_la_LDFLAGS = \
   -version-info 1:0:1 \
   -export-dynamic -no-undefined
 libtalerjson_la_LIBADD = \
   -lgnunetjson \
+  $(top_builddir)/src/wire/libtalerwire.la \
   $(top_builddir)/src/util/libtalerutil.la \
   -lgnunetutil \
   -ljansson \
diff --git a/src/json/json_wire.c b/src/json/json_wire.c
new file mode 100644
index 0000000..f0bd175
--- /dev/null
+++ b/src/json/json_wire.c
@@ -0,0 +1,193 @@
+/*
+  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 json/json_wire.c
+ * @brief helper functions to generate or check /wire replies
+ * @author Christian Grothoff
+ */
+#include "platform.h"
+#include <gnunet/gnunet_util_lib.h>
+#include "taler_util.h"
+#include "taler_json_lib.h"
+#include "taler_wire_lib.h"
+
+
+/**
+ * Compute the hash of the given wire details.   The resulting
+ * hash is what is put into the contract.
+ *
+ * @param wire_s wire details to hash
+ * @param hc[out] set to the hash
+ * @return #GNUNET_OK on success, #GNUNET_SYSERR if @a wire_s is malformed
+ */
+int
+TALER_JSON_wire_signature_hash (const json_t *wire_s,
+                                struct GNUNET_HashCode *hc)
+{
+  const char *payto_url;
+  const char *salt;
+  struct GNUNET_JSON_Specification spec[] = {
+    GNUNET_JSON_spec_string ("url", &payto_url),
+    GNUNET_JSON_spec_string ("salt", &salt),
+    GNUNET_JSON_spec_end ()
+  };
+
+  if (GNUNET_OK !=
+      GNUNET_JSON_parse (wire_s,
+                         spec,
+                         NULL, NULL))
+  {
+    GNUNET_break_op (0);
+    return GNUNET_SYSERR;
+  }
+  TALER_wire_signature_hash (payto_url,
+                             salt,
+                             hc);
+  return GNUNET_OK;
+}
+
+
+/**
+ * Check the signature in @a wire_s.
+ *
+ * @param wire_s signed wire information of an exchange
+ * @param master_pub master public key of the exchange
+ * @return #GNUNET_OK if signature is valid
+ */
+int
+TALER_JSON_wire_signature_check (const json_t *wire_s,
+                                 const struct TALER_MasterPublicKeyP 
*master_pub)
+{
+  const char *payto_url;
+  const char *salt;
+  struct TALER_MasterSignatureP master_sig;
+  struct GNUNET_JSON_Specification spec[] = {
+    GNUNET_JSON_spec_string ("url", &payto_url),
+    GNUNET_JSON_spec_string ("salt", &salt),
+    GNUNET_JSON_spec_fixed_auto ("master_sig", &master_sig),
+    GNUNET_JSON_spec_end ()
+  };
+
+  if (GNUNET_OK !=
+      GNUNET_JSON_parse (wire_s,
+                         spec,
+                         NULL, NULL))
+  {
+    GNUNET_break_op (0);
+    return GNUNET_SYSERR;
+  }
+  return TALER_wire_signature_check (payto_url,
+                                     salt,
+                                     master_pub,
+                                     &master_sig);
+}
+
+
+/**
+ * Create a signed wire statement for the given account.
+ *
+ * @param payto_url account specification
+ * @param master_priv private key to sign with, NULL to not sign
+ */
+json_t *
+TALER_JSON_wire_signature_make (const char *payto_url,
+                                const struct TALER_MasterPrivateKeyP 
*master_priv)
+{
+  struct TALER_MasterSignatureP master_sig;
+  struct GNUNET_HashCode salt;
+  char *salt_str;
+  json_t *ret;
+
+  GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_NONCE,
+                              &salt,
+                              sizeof (salt));
+  salt_str = GNUNET_STRINGS_data_to_string_alloc (&salt,
+                                                  sizeof (salt));
+  if (NULL != master_priv)
+  {
+    TALER_wire_signature_make (payto_url,
+                               salt_str,
+                               master_priv,
+                               &master_sig);
+    ret = json_pack ("{s:s, s:s, s:o}",
+                     "url", payto_url,
+                     "salt", salt_str,
+                     "master_sig", GNUNET_JSON_from_data_auto (&master_sig));
+  }
+  else
+  {
+    ret = json_pack ("{s:s, s:s}",
+                     "url", payto_url,
+                     "salt", salt_str);
+  }
+  GNUNET_free (salt_str);
+  return ret;
+}
+
+
+/**
+ * Obtain the wire method associated with the given
+ * wire account details.  @a wire_s must contain a payto://-URL
+ * under 'url'.
+ *
+ * @return NULL on error
+ */
+char *
+TALER_JSON_wire_to_payto (const json_t *wire_s)
+{
+  json_t *payto_o;
+  const char *payto_str;
+
+  payto_o = json_object_get (wire_s,
+                             "url");
+  if ( (NULL == payto_o) ||
+       (NULL == (payto_str = json_string_value (payto_o))) )
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                "Fatally malformed wire record encountered: lacks 
payto://-url\n");
+    return NULL;
+  }
+  return GNUNET_strdup (payto_str);
+}
+
+
+/**
+ * Obtain the wire method associated with the given
+ * wire account details.  @a wire_s must contain a payto://-URL
+ * under 'url'.
+ *
+ * @return NULL on error
+ */
+char *
+TALER_JSON_wire_to_method (const json_t *wire_s)
+{
+  json_t *payto_o;
+  const char *payto_str;
+
+  payto_o = json_object_get (wire_s,
+                             "url");
+  if ( (NULL == payto_o) ||
+       (NULL == (payto_str = json_string_value (payto_o))) )
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                "Fatally malformed wire record encountered: lacks 
payto://-url\n");
+    return NULL;
+  }
+  return TALER_WIRE_payto_get_method (payto_str);
+}
+
+
+/* end of json_wire.c */
diff --git a/src/util/Makefile.am b/src/util/Makefile.am
index 4f9a636..89b31eb 100644
--- a/src/util/Makefile.am
+++ b/src/util/Makefile.am
@@ -43,6 +43,7 @@ libtalerutil_wallet_la_LDFLAGS = \
 libtalerutil_la_SOURCES = \
   amount.c \
   crypto.c \
+  crypto_wire.c \
   util.c \
   os_installation.c
 
diff --git a/src/util/crypto_wire.c b/src/util/crypto_wire.c
new file mode 100644
index 0000000..494573f
--- /dev/null
+++ b/src/util/crypto_wire.c
@@ -0,0 +1,108 @@
+/*
+  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 util/crypto_wire.c
+ * @brief functions for making and verifying /wire account signatures
+ * @author Christian Grothoff <address@hidden>
+ */
+#include "platform.h"
+#include "taler_crypto_lib.h"
+#include "taler_signatures.h"
+
+/**
+ * Compute the hash of the given wire details.   The resulting
+ * hash is what is put into the contract.
+ *
+ * @param payto_url bank account
+ * @param salt salt used to eliminate brute-force inversion
+ * @param hc[out] set to the hash
+ */
+void
+TALER_wire_signature_hash (const char *payto_url,
+                           const char *salt,
+                           struct GNUNET_HashCode *hc)
+{
+  GNUNET_assert (GNUNET_YES ==
+                 GNUNET_CRYPTO_kdf (hc,
+                                    sizeof (*hc),
+                                    salt,
+                                    strlen (salt) + 1,
+                                    payto_url,
+                                    strlen (payto_url) + 1,
+                                    "wire-signature",
+                                    strlen ("wire-signature"),
+                                    NULL, 0));
+}
+
+
+/**
+ * Check the signature in @a wire_s.
+ *
+ * @param payto_url URL that is signed
+ * @param salt the salt used to salt the @a payto_url when hashing
+ * @param master_pub master public key of the exchange
+ * @param master_sig signature of the exchange
+ * @return #GNUNET_OK if signature is valid
+ */
+int
+TALER_wire_signature_check (const char *payto_url,
+                            const char *salt,
+                            const struct TALER_MasterPublicKeyP *master_pub,
+                            const struct TALER_MasterSignatureP *master_sig)
+{
+  struct TALER_MasterWireDetailsPS wd;
+
+  wd.purpose.purpose = htonl (TALER_SIGNATURE_MASTER_WIRE_DETAILS);
+  wd.purpose.size = htonl (sizeof (wd));
+  TALER_wire_signature_hash (payto_url,
+                             salt,
+                             &wd.h_wire_details);
+  return GNUNET_CRYPTO_eddsa_verify (TALER_SIGNATURE_MASTER_WIRE_DETAILS,
+                                     &wd.purpose,
+                                     &master_sig->eddsa_signature,
+                                     &master_pub->eddsa_pub);
+}
+
+
+/**
+ * Create a signed wire statement for the given account.
+ *
+ * @param payto_url account specification
+ * @param salt the salt used to salt the @a payto_url when hashing
+ * @param master_priv private key to sign with
+ * @param master_sig[out] where to write the signature
+ */
+void
+TALER_wire_signature_make (const char *payto_url,
+                           const char *salt,
+                           const struct TALER_MasterPrivateKeyP *master_priv,
+                           struct TALER_MasterSignatureP *master_sig)
+{
+  struct TALER_MasterWireDetailsPS wd;
+
+  wd.purpose.purpose = htonl (TALER_SIGNATURE_MASTER_WIRE_DETAILS);
+  wd.purpose.size = htonl (sizeof (wd));
+  TALER_wire_signature_hash (payto_url,
+                             salt,
+                             &wd.h_wire_details);
+  GNUNET_assert (GNUNET_OK ==
+                 GNUNET_CRYPTO_eddsa_sign (&master_priv->eddsa_priv,
+                                           &wd.purpose,
+                                           &master_sig->eddsa_signature));
+}
+
+
+/* end of crypto_wire.c */
diff --git a/src/wire/Makefile.am b/src/wire-plugins/Makefile.am
similarity index 57%
copy from src/wire/Makefile.am
copy to src/wire-plugins/Makefile.am
index 5f65146..9f6029d 100644
--- a/src/wire/Makefile.am
+++ b/src/wire-plugins/Makefile.am
@@ -8,50 +8,41 @@ endif
 
 pkgcfgdir = $(prefix)/share/taler/config.d/
 
-pkgcfg_DATA = \
-  wire-sepa.conf \
-  wire-test.conf
-
-
 EXTRA_DIST = \
-  wire-sepa.conf \
-  wire-test.conf \
   test_wire_plugin.conf \
-  test_wire_plugin_transactions_test.conf \
+  test_wire_plugin_transactions_taler-bank.conf \
   test_wire_plugin_key.priv \
   test_wire_plugin_test.json \
-  test_wire_plugin_sepa.json 
+  test_wire_plugin_sepa.json
 
 plugindir = $(libdir)/taler
 
 plugin_LTLIBRARIES = \
-  libtaler_plugin_wire_sepa.la \
-  libtaler_plugin_wire_test.la
+  libtaler_plugin_wire_ebics.la \
+  libtaler_plugin_wire_taler_bank.la
 
 noinst_LTLIBRARIES = \
   libtaler_plugin_wire_template.la
 
-lib_LTLIBRARIES = \
-  libtalerwire.la
-
 
-libtaler_plugin_wire_test_la_SOURCES = \
-  plugin_wire_test.c
-libtaler_plugin_wire_test_la_LIBADD = \
+libtaler_plugin_wire_taler_bank_la_SOURCES = \
+  plugin_wire_taler-bank.c
+libtaler_plugin_wire_taler_bank_la_LIBADD = \
   $(LTLIBINTL)
-libtaler_plugin_wire_test_la_LDFLAGS = \
+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/util/libtalerutil.la \
   -lgnunetcurl \
   -lgnunetutil $(XLIB)
 
 
-libtaler_plugin_wire_sepa_la_SOURCES = \
-  plugin_wire_sepa.c
-libtaler_plugin_wire_sepa_la_LIBADD = \
+libtaler_plugin_wire_ebics_la_SOURCES = \
+  plugin_wire_ebics.c
+libtaler_plugin_wire_ebics_la_LIBADD = \
   $(LTLIBINTL)
-libtaler_plugin_wire_sepa_la_LDFLAGS = \
+libtaler_plugin_wire_ebics_la_LDFLAGS = \
   $(TALER_PLUGIN_LDFLAGS) \
   $(top_builddir)/src/json/libtalerjson.la \
   $(top_builddir)/src/util/libtalerutil.la \
@@ -69,53 +60,42 @@ libtaler_plugin_wire_template_la_LDFLAGS = \
   -lgnunetutil $(XLIB)
 
 
-libtalerwire_la_SOURCES = \
-  wire.c
-libtalerwire_la_LIBADD = \
-  -lgnunetutil \
-  $(XLIB)
-libtalerwire_la_LDFLAGS = \
-  -version-info 1:0:0 \
-  -export-dynamic -no-undefined
-
-
 AM_TESTS_ENVIRONMENT=export 
TALER_PREFIX=$${TALER_PREFIX:address@hidden@};export 
PATH=$${TALER_PREFIX:address@hidden@}/bin:$$PATH;
 
 TESTS = \
- test_sepa_wireformat \
- test_wire_plugin
+ test_ebics_wireformat \
+ test_wire_plugin \
+ test_wire_plugin_transactions_taler_bank
 
 check_PROGRAMS= \
- test_sepa_wireformat \
+ test_ebics_wireformat \
  test_wire_plugin \
- test_wire_plugin_transactions_test
+ test_wire_plugin_transactions_taler_bank
 
 
-test_sepa_wireformat_SOURCES = \
-  test_sepa_wireformat.c
-test_sepa_wireformat_LDADD = \
+test_ebics_wireformat_SOURCES = \
+  test_ebics_wireformat.c
+test_ebics_wireformat_LDADD = \
   -lgnunetutil \
-  -ljansson \
-  libtalerwire.la \
+  $(top_builddir)/src/wire/libtalerwire.la \
   $(top_builddir)/src/util/libtalerutil.la
 
 
 test_wire_plugin_SOURCES = \
   test_wire_plugin.c
 test_wire_plugin_LDADD = \
-  -lgnunetjson \
   -lgnunetutil \
-  -ljansson \
-  libtalerwire.la \
+  $(top_builddir)/src/wire/libtalerwire.la \
   $(top_builddir)/src/util/libtalerutil.la
 
 
-test_wire_plugin_transactions_test_SOURCES = \
-  test_wire_plugin_transactions_test.c
-test_wire_plugin_transactions_test_LDADD = \
+test_wire_plugin_transactions_taler_bank_SOURCES = \
+  test_wire_plugin_transactions_taler-bank.c
+test_wire_plugin_transactions_taler_bank_LDADD = \
   -lgnunetjson \
   -lgnunetutil \
   -ljansson \
-  libtalerwire.la \
+  $(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/plugin_wire_sepa.c b/src/wire-plugins/plugin_wire_ebics.c
similarity index 56%
rename from src/wire/plugin_wire_sepa.c
rename to src/wire-plugins/plugin_wire_ebics.c
index 416acac..9aad9df 100644
--- a/src/wire/plugin_wire_sepa.c
+++ b/src/wire-plugins/plugin_wire_ebics.c
@@ -1,6 +1,6 @@
 /*
   This file is part of TALER
-  Copyright (C) 2016, 2017 GNUnet e.V. & Inria
+  Copyright (C) 2016, 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
@@ -15,7 +15,7 @@
 */
 
 /**
- * @file plugin_wire_sepa.c
+ * @file plugin_wire_ebics.c
  * @brief wire plugin for transfers using SEPA/EBICS
  * @author Florian Dold
  * @author Christian Grothoff
@@ -31,7 +31,7 @@
  * Type of the "cls" argument given to each of the functions in
  * our API.
  */
-struct SepaClosure
+struct EbicsClosure
 {
 
   /**
@@ -39,6 +39,11 @@ struct SepaClosure
    */
   char *currency;
 
+  /**
+   * Configuration we use to lookup account information.
+   */
+  struct GNUNET_CONFIGURATION_Handle *cfg;
+
 };
 
 
@@ -54,10 +59,10 @@ struct SepaClosure
  *         #GNUNET_SYSERR if the amount or currency was invalid
  */
 static int
-sepa_amount_round (void *cls,
-                   struct TALER_Amount *amount)
+ebics_amount_round (void *cls,
+                    struct TALER_Amount *amount)
 {
-  struct SepaClosure *sc = cls;
+  struct EbicsClosure *sc = cls;
   uint32_t delta;
 
   if (NULL == sc->currency)
@@ -81,7 +86,7 @@ sepa_amount_round (void *cls,
 /**
  * Entry in the country table.
  */
-struct table_entry
+struct CountryTableEntry
 {
   /**
    * 2-Character international country code.
@@ -100,7 +105,7 @@ struct table_entry
 /**
  * List of country codes.
  */
-static const struct table_entry country_table[] =
+static const struct CountryTableEntry country_table[] =
   {
     { "AE", "U.A.E." },
     { "AF", "Afghanistan" },
@@ -259,8 +264,8 @@ static int
 cmp_country_code (const void *ptr1,
                   const void *ptr2)
 {
-  const struct table_entry *cc1 = ptr1;
-  const struct table_entry *cc2 = ptr2;
+  const struct CountryTableEntry *cc1 = ptr1;
+  const struct CountryTableEntry *cc2 = ptr2;
 
   return strncmp (cc1->code,
                   cc2->code,
@@ -280,20 +285,21 @@ validate_iban (const char *iban)
 {
   char cc[2];
   char ibancpy[35];
-  struct table_entry cc_entry;
+  struct CountryTableEntry cc_entry;
   unsigned int len;
   char *nbuf;
-  unsigned int i;
-  unsigned int j;
   unsigned long long dividend;
   unsigned long long remainder;
   int nread;
   int ret;
+  unsigned int i;
+  unsigned int j;
 
   len = strlen (iban);
   if (len > 34)
   {
-    GNUNET_break_op (0);
+    GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+                "IBAN number too long to be valid\n");
     return GNUNET_NO;
   }
   strncpy (cc, iban, 2);
@@ -305,11 +311,14 @@ validate_iban (const char *iban)
   if (NULL ==
       bsearch (&cc_entry,
                country_table,
-               sizeof (country_table) / sizeof (struct table_entry),
-               sizeof (struct table_entry),
+               sizeof (country_table) / sizeof (struct CountryTableEntry),
+               sizeof (struct CountryTableEntry),
                &cmp_country_code))
   {
-    GNUNET_break_op (0);
+    GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+                "Country code `%c%c' not supported\n",
+                cc[0],
+                cc[1]);
     return GNUNET_NO;
   }
   nbuf = GNUNET_malloc ((len * 2) + 1);
@@ -354,309 +363,89 @@ validate_iban (const char *iban)
   GNUNET_free (nbuf);
   if (1 == remainder)
     return GNUNET_YES;
-  GNUNET_break_op (0); /* checksum wrong */
+  GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+              "IBAN checksum wrong\n");
   return GNUNET_NO;
 }
 
 
 /**
- * Compute purpose for signing.
- *
- * @param sepa_name name of the account holder
- * @param iban bank account number in IBAN format
- * @param bic bank identifier
- * @param[out] wsd purpose to be signed
+ * Information about an account extracted from a payto://-URL.
  */
-static void
-compute_purpose (const char *sepa_name,
-                 const char *iban,
-                 const char *bic,
-                 struct TALER_MasterWireDetailsPS *wsd)
+struct Account
 {
-  struct GNUNET_HashContext *hc;
-
-  wsd->purpose.size = htonl (sizeof (struct TALER_MasterWireDetailsPS));
-  wsd->purpose.purpose = htonl (TALER_SIGNATURE_MASTER_SEPA_DETAILS);
-  hc = GNUNET_CRYPTO_hash_context_start ();
-  GNUNET_CRYPTO_hash_context_read (hc,
-                                  "sepa",
-                                  strlen ("sepa") + 1);
-  GNUNET_CRYPTO_hash_context_read (hc,
-                                  sepa_name,
-                                  strlen (sepa_name) + 1);
-  GNUNET_CRYPTO_hash_context_read (hc,
-                                  iban,
-                                  strlen (iban) + 1);
-  GNUNET_CRYPTO_hash_context_read (hc,
-                                  bic,
-                                  strlen (bic) + 1);
-  GNUNET_CRYPTO_hash_context_finish (hc,
-                                    &wsd->h_sepa_details);
-}
-
-
-/**
- * Verify that the signature in the @a json for /wire/sepa is valid.
- *
- * @param json json reply with the signature
- * @param master_pub public key of the exchange to verify against
- * @return #GNUNET_SYSERR if @a json is invalid,
- *         #GNUNET_NO if the method is unknown,
- *         #GNUNET_OK if the json is valid
- */
-static int
-verify_wire_sepa_signature_ok (const json_t *json,
-                               const struct TALER_MasterPublicKeyP *master_pub)
-{
-  struct TALER_MasterSignatureP exchange_sig;
-  struct TALER_MasterWireDetailsPS mp;
-  const char *name;
-  const char *iban;
-  const char *bic;
-  struct GNUNET_JSON_Specification spec[] = {
-    GNUNET_JSON_spec_fixed_auto ("sig", &exchange_sig),
-    GNUNET_JSON_spec_string ("name", &name),
-    GNUNET_JSON_spec_string ("iban", &iban),
-    GNUNET_JSON_spec_string ("bic", &bic),
-    GNUNET_JSON_spec_end()
-  };
+  /**
+   * The IBAN number.
+   */
+  char *iban;
 
-  if (NULL == master_pub)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "Skipping signature check as master public key not given\n");
-    return GNUNET_OK;
-  }
-  if (GNUNET_OK !=
-      GNUNET_JSON_parse (json, spec,
-                         NULL, NULL))
-  {
-    GNUNET_break_op (0);
-    return GNUNET_SYSERR;
-  }
-  compute_purpose (name,
-                   iban,
-                   bic,
-                   &mp);
-  if (GNUNET_OK !=
-      GNUNET_CRYPTO_eddsa_verify (TALER_SIGNATURE_MASTER_SEPA_DETAILS,
-                                  &mp.purpose,
-                                  &exchange_sig.eddsa_signature,
-                                  &master_pub->eddsa_pub))
-  {
-    GNUNET_break_op (0);
-    GNUNET_JSON_parse_free (spec);
-    return GNUNET_SYSERR;
-  }
-  GNUNET_JSON_parse_free (spec);
-  return GNUNET_OK;
-}
+};
 
 
 /**
- * Check if the given wire format JSON object is correctly formatted
+ * Parse payto:// account URL (only account information,
+ * wire subject and amount are ignored).
  *
- * @param cls the @e cls of this struct with the plugin-specific state
- * @param wire the JSON wire format object
- * @param master_pub public key of the exchange to verify against
- * @param[out] emsg set to an error message, unless we return #TALER_EC_NONE;
- *             error message must be freed by the caller using GNUNET_free()
- * @return #TALER_EC_NONE if correctly formatted
+ * @param account_url URL to parse
+ * @param account[out] set to information, can be NULL
+ * @return #TALER_EC_NONE if @a account_url is well-formed
  */
 static enum TALER_ErrorCode
-sepa_wire_validate (void *cls,
-                    const json_t *wire,
-                    const struct TALER_MasterPublicKeyP *master_pub,
-                    char **emsg)
+parse_payto (const char *account_url,
+             struct Account *account)
 {
-  json_error_t error;
-  const char *type;
   const char *iban;
-  const char *name;
-  const char *bic;
-
-  *emsg = NULL;
-  if (0 != json_unpack_ex
-      ((json_t *) wire,
-       &error, 0,
-       "{"
-       "s:s," /* type: sepa */
-       "s:s," /* iban: IBAN */
-       "s:s," /* name: beneficiary name */
-       "s:s" /* bic: beneficiary bank's BIC */
-       "}",
-       "type", &type,
-       "iban", &iban,
-       "name", &name,
-       "bic", &bic))
-  {
-    char *dump;
-
-    dump = json_dumps (wire, 0);
-    GNUNET_asprintf (emsg,
-                     "JSON parsing failed at %s:%u: %s (%s): %s\n",
-                     __FILE__, __LINE__,
-                     error.text,
-                     error.source,
-                     dump);
-    free (dump);
-    return TALER_EC_DEPOSIT_INVALID_WIRE_FORMAT_JSON;
-  }
-  if (0 != strcasecmp (type,
-                       "sepa"))
+  const char *q;
+  char *result;
+
+#define PREFIX "payto://sepa/"
+  if (0 != strncasecmp (account_url,
+                        PREFIX,
+                        strlen (PREFIX)))
+    return TALER_EC_PAYTO_WRONG_METHOD;
+  iban = &account_url[strlen (PREFIX)];
+  q = strchr (iban,
+              '?');
+  if (NULL != q)
   {
-    GNUNET_asprintf (emsg,
-                     "Transfer type `%s' invalid for SEPA wire plugin\n",
-                     type);
-    return TALER_EC_DEPOSIT_INVALID_WIRE_FORMAT_TYPE;
+    result = GNUNET_strndup (iban,
+                             q - iban);
   }
-  if (1 != validate_iban (iban))
+  else
   {
-    GNUNET_asprintf (emsg,
-                     "IBAN `%s' invalid\n",
-                     iban);
-    return TALER_EC_DEPOSIT_INVALID_WIRE_FORMAT_ACCOUNT_NUMBER;
+    result = GNUNET_strdup (iban);
   }
-  /* FIXME: don't parse again, integrate properly... */
   if (GNUNET_OK !=
-      verify_wire_sepa_signature_ok (wire,
-                                     master_pub))
+      validate_iban (result))
   {
-    GNUNET_asprintf (emsg,
-                     "Signature using public key `%s' invalid\n",
-                     TALER_B2S (master_pub));
-    return TALER_EC_DEPOSIT_INVALID_WIRE_FORMAT_SIGNATURE;
+    GNUNET_free (result);
+    return TALER_EC_PAYTO_MALFORMED;
   }
-  return TALER_EC_NONE;
-}
-
-
-/**
- * Obtain wire transfer details in the plugin-specific format
- * from the configuration.
- *
- * @param cls closure
- * @param cfg configuration with details about wire accounts
- * @param account_name which section in the configuration should we parse
- * @return NULL if @a cfg fails to have valid wire details for @a account_name
- */
-static json_t *
-sepa_get_wire_details (void *cls,
-                       const struct GNUNET_CONFIGURATION_Handle *cfg,
-                       const char *account_name)
-{
-  char *sepa_wire_file;
-  json_error_t err;
-  json_t *ret;
-  char *emsg;
-
-  /* Fetch reply */
-  if (GNUNET_OK !=
-      GNUNET_CONFIGURATION_get_value_filename (cfg,
-                                               account_name,
-                                               "SEPA_RESPONSE_FILE",
-                                               &sepa_wire_file))
+  if (NULL != account)
   {
-    GNUNET_log_config_missing (GNUNET_ERROR_TYPE_WARNING,
-                               account_name,
-                               "SEPA_RESPONSE_FILE");
-    return NULL;
+    account->iban = result;
   }
-  ret = json_load_file (sepa_wire_file,
-                        JSON_REJECT_DUPLICATES,
-                        &err);
-  if (NULL == ret)
+  else
   {
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                "Failed to parse JSON in %s: %s (%s:%u)\n",
-                sepa_wire_file,
-                err.text,
-                err.source,
-                err.line);
-    GNUNET_free (sepa_wire_file);
-    return NULL;
+    GNUNET_free (result);
   }
-  if (TALER_EC_NONE !=
-      sepa_wire_validate (cls,
-                          ret,
-                          NULL,
-                          &emsg))
-    {
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                "Failed to validate SEPA data in %s: %s\n",
-                sepa_wire_file,
-                emsg);
-    GNUNET_free (emsg);
-    GNUNET_free (sepa_wire_file);
-    json_decref (ret);
-    return NULL;
-  }
-  GNUNET_free (sepa_wire_file);
-  return ret;
+  return TALER_EC_NONE;
 }
 
 
 /**
- * Sign wire transfer details in the plugin-specific format.
+ * Check if the given payto:// URL is correctly formatted for this plugin
  *
- * @param cls closure
- * @param in wire transfer details in JSON format
- * @param key private signing key to use
- * @param salt salt to add
- * @param[out] sig where to write the signature
- * @return #GNUNET_OK on success
+ * @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 int
-sepa_sign_wire_details (void *cls,
-                        const json_t *in,
-                        const struct TALER_MasterPrivateKeyP *key,
-                        const struct GNUNET_HashCode *salt,
-                        struct TALER_MasterSignatureP *sig)
+static enum TALER_ErrorCode
+ebics_wire_validate (void *cls,
+                     const char *account_url)
 {
-  struct TALER_MasterWireDetailsPS wsd;
-  const char *sepa_name;
-  const char *iban;
-  const char *bic;
-  const char *type;
-  json_error_t err;
-
-  if (0 !=
-      json_unpack_ex ((json_t *) in,
-                      &err,
-                      0 /* flags */,
-                      "{s:s, s:s, s:s, s:s}",
-                      "type", &type,
-                      "name", &sepa_name,
-                      "iban", &iban,
-                      "bic", &bic))
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
-                "Failed to unpack JSON: %s (at %u)\n",
-                err.text,
-                err.position);
-    return GNUNET_SYSERR;
-  }
-  if (0 != strcmp (type,
-                   "sepa"))
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
-                "`type' must be `sepa' for SEPA wire details\n");
-    return GNUNET_SYSERR;
-  }
-  if (1 != validate_iban (iban))
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
-                "IBAN invalid in SEPA wire details\n");
-    return GNUNET_SYSERR;
-  }
-  compute_purpose (sepa_name,
-                   iban,
-                   bic,
-                   &wsd);
-  GNUNET_CRYPTO_eddsa_sign (&key->eddsa_priv,
-                           &wsd.purpose,
-                           &sig->eddsa_signature);
-  return GNUNET_OK;
+  return parse_payto (account_url,
+                      NULL);
 }
 
 
@@ -673,13 +462,14 @@ sepa_sign_wire_details (void *cls,
  * @return NULL on failure
  */
 static struct TALER_WIRE_PrepareHandle *
-sepa_prepare_wire_transfer (void *cls,
-                            const json_t *wire,
-                            const struct TALER_Amount *amount,
-                            const char *exchange_base_url,
-                            const struct TALER_WireTransferIdentifierRawP 
*wtid,
-                            TALER_WIRE_PrepareTransactionCallback psc,
-                            void *psc_cls)
+ebics_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 psc,
+                             void *psc_cls)
 {
   GNUNET_break (0); // FIXME: not implemented
   return NULL;
@@ -694,7 +484,7 @@ sepa_prepare_wire_transfer (void *cls,
  * @param pth preparation to cancel
  */
 static void
-sepa_prepare_wire_transfer_cancel (void *cls,
+ebics_prepare_wire_transfer_cancel (void *cls,
                                    struct TALER_WIRE_PrepareHandle *pth)
 {
   GNUNET_break (0); // FIXME: not implemented
@@ -712,11 +502,11 @@ sepa_prepare_wire_transfer_cancel (void *cls,
  * @return NULL on error
  */
 static struct TALER_WIRE_ExecuteHandle *
-sepa_execute_wire_transfer (void *cls,
-                            const char *buf,
-                            size_t buf_size,
-                            TALER_WIRE_ConfirmationCallback cc,
-                            void *cc_cls)
+ebics_execute_wire_transfer (void *cls,
+                             const char *buf,
+                             size_t buf_size,
+                             TALER_WIRE_ConfirmationCallback cc,
+                             void *cc_cls)
 {
   GNUNET_break (0); // FIXME: not implemented
   return NULL;
@@ -736,8 +526,8 @@ sepa_execute_wire_transfer (void *cls,
  * @param eh execution to cancel
  */
 static void
-sepa_execute_wire_transfer_cancel (void *cls,
-                                   struct TALER_WIRE_ExecuteHandle *eh)
+ebics_execute_wire_transfer_cancel (void *cls,
+                                    struct TALER_WIRE_ExecuteHandle *eh)
 {
   GNUNET_break (0); // FIXME: not implemented
 }
@@ -754,6 +544,8 @@ sepa_execute_wire_transfer_cancel (void *cls,
  * (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)`.
@@ -764,13 +556,14 @@ sepa_execute_wire_transfer_cancel (void *cls,
  * @param hres_cb_cls closure for the above callback
  */
 static struct TALER_WIRE_HistoryHandle *
-sepa_get_history (void *cls,
-                  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)
+ebics_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)
 {
   GNUNET_break (0);
   return NULL;
@@ -784,8 +577,8 @@ sepa_get_history (void *cls,
  * @param whh operation to cancel
  */
 static void
-sepa_get_history_cancel (void *cls,
-                        struct TALER_WIRE_HistoryHandle *whh)
+ebics_get_history_cancel (void *cls,
+                          struct TALER_WIRE_HistoryHandle *whh)
 {
   GNUNET_break (0);
 }
@@ -843,6 +636,8 @@ timeout_reject (void *cls)
  * 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
@@ -850,11 +645,12 @@ timeout_reject (void *cls)
  * @return handle to cancel the operation
  */
 static struct TALER_WIRE_RejectHandle *
-sepa_reject_transfer (void *cls,
-                      const void *start_off,
-                      size_t start_off_len,
-                      TALER_WIRE_RejectTransferCallback rej_cb,
-                      void *rej_cb_cls)
+ebics_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_RejectHandle *rh;
 
@@ -881,8 +677,8 @@ sepa_reject_transfer (void *cls,
  * @return closure of the callback of the operation
  */
 static void *
-sepa_reject_transfer_cancel (void *cls,
-                             struct TALER_WIRE_RejectHandle *rh)
+ebics_reject_transfer_cancel (void *cls,
+                              struct TALER_WIRE_RejectHandle *rh)
 {
   void *ret = rh->rej_cb_cls;
 
@@ -893,63 +689,60 @@ sepa_reject_transfer_cancel (void *cls,
 
 
 /**
- * Initialize sepa-wire subsystem.
+ * Initialize ebics-wire subsystem.
  *
  * @param cls a configuration instance
  * @return NULL on error, otherwise a `struct TALER_WIRE_Plugin`
  */
 void *
-libtaler_plugin_wire_sepa_init (void *cls)
+libtaler_plugin_wire_ebics_init (void *cls)
 {
   struct GNUNET_CONFIGURATION_Handle *cfg = cls;
-  struct SepaClosure *sc;
+  struct EbicsClosure *sc;
   struct TALER_WIRE_Plugin *plugin;
 
-  sc = GNUNET_new (struct SepaClosure);
-  if (NULL != cfg)
+  sc = GNUNET_new (struct EbicsClosure);
+  sc->cfg = cfg;
+  if (GNUNET_OK !=
+      GNUNET_CONFIGURATION_get_value_string (cfg,
+                                             "taler",
+                                             "CURRENCY",
+                                             &sc->currency))
   {
-    if (GNUNET_OK !=
-        GNUNET_CONFIGURATION_get_value_string (cfg,
-                                               "taler",
-                                               "CURRENCY",
-                                               &sc->currency))
-    {
-      GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
-                                 "taler",
-                                 "CURRENCY");
-      GNUNET_free (sc);
-      return NULL;
-    }
+    GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
+                               "taler",
+                               "CURRENCY");
+    GNUNET_free (sc);
+    return NULL;
   }
   plugin = GNUNET_new (struct TALER_WIRE_Plugin);
   plugin->cls = sc;
-  plugin->amount_round = &sepa_amount_round;
-  plugin->get_wire_details = &sepa_get_wire_details;
-  plugin->sign_wire_details = &sepa_sign_wire_details;
-  plugin->wire_validate = &sepa_wire_validate;
-  plugin->prepare_wire_transfer = &sepa_prepare_wire_transfer;
-  plugin->prepare_wire_transfer_cancel = &sepa_prepare_wire_transfer_cancel;
-  plugin->execute_wire_transfer = &sepa_execute_wire_transfer;
-  plugin->execute_wire_transfer_cancel = &sepa_execute_wire_transfer_cancel;
-  plugin->get_history = &sepa_get_history;
-  plugin->get_history_cancel = &sepa_get_history_cancel;
-  plugin->reject_transfer = &sepa_reject_transfer;
-  plugin->reject_transfer_cancel = &sepa_reject_transfer_cancel;
+  plugin->method = "sepa";
+  plugin->amount_round = &ebics_amount_round;
+  plugin->wire_validate = &ebics_wire_validate;
+  plugin->prepare_wire_transfer = &ebics_prepare_wire_transfer;
+  plugin->prepare_wire_transfer_cancel = &ebics_prepare_wire_transfer_cancel;
+  plugin->execute_wire_transfer = &ebics_execute_wire_transfer;
+  plugin->execute_wire_transfer_cancel = &ebics_execute_wire_transfer_cancel;
+  plugin->get_history = &ebics_get_history;
+  plugin->get_history_cancel = &ebics_get_history_cancel;
+  plugin->reject_transfer = &ebics_reject_transfer;
+  plugin->reject_transfer_cancel = &ebics_reject_transfer_cancel;
   return plugin;
 }
 
 
 /**
- * Shutdown Sepa wire subsystem.
+ * Shutdown Ebics wire subsystem.
  *
  * @param cls a `struct TALER_WIRE_Plugin`
  * @return NULL (always)
  */
 void *
-libtaler_plugin_wire_sepa_done (void *cls)
+libtaler_plugin_wire_ebics_done (void *cls)
 {
   struct TALER_WIRE_Plugin *plugin = cls;
-  struct SepaClosure *sc = plugin->cls;
+  struct EbicsClosure *sc = plugin->cls;
 
   GNUNET_free_non_null (sc->currency);
   GNUNET_free (sc);
@@ -957,4 +750,4 @@ libtaler_plugin_wire_sepa_done (void *cls)
   return NULL;
 }
 
-/* end of plugin_wire_sepa.c */
+/* end of plugin_wire_ebics.c */
diff --git a/src/wire/plugin_wire_test.c 
b/src/wire-plugins/plugin_wire_taler-bank.c
similarity index 55%
rename from src/wire/plugin_wire_test.c
rename to src/wire-plugins/plugin_wire_taler-bank.c
index a81ccda..743d85b 100644
--- a/src/wire/plugin_wire_test.c
+++ b/src/wire-plugins/plugin_wire_taler-bank.c
@@ -1,6 +1,6 @@
 /*
   This file is part of TALER
-  Copyright (C) 2017 Taler Systems SA
+  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
@@ -15,12 +15,13 @@
 */
 
 /**
- * @file plugin_wire_test.c
- * @brief plugin for the "test" wire method
+ * @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_bank_service.h"
 #include "taler_signatures.h"
 #include <gnunet/gnunet_curl_lib.h>
@@ -29,10 +30,15 @@
 #include <microhttpd.h>
 
 /**
+ * Maximum legal 'value' for an account number, based on IEEE double (for 
JavaScript compatibility).
+ */
+#define MAX_ACCOUNT_NO (1LLU << 52)
+
+/**
  * Type of the "cls" argument given to each of the functions in
  * our API.
  */
-struct TestClosure
+struct TalerBankClosure
 {
 
   /**
@@ -41,16 +47,6 @@ struct TestClosure
   char *currency;
 
   /**
-   * URL of our bank.
-   */
-  char *bank_url;
-
-  /**
-   * Authentication information.
-   */
-  struct TALER_BANK_AuthenticationData auth;
-
-  /**
    * Handle to the context for sending funds to the bank.
    */
   struct GNUNET_CURL_Context *ctx;
@@ -61,16 +57,15 @@ struct TestClosure
   struct GNUNET_CURL_RescheduleContext *rc;
 
   /**
-   * Number of the account that the exchange has at the bank for
-   * transfers.
+   * Configuration we use to lookup account information.
    */
-  unsigned long long exchange_account_no;
+  struct GNUNET_CONFIGURATION_Handle *cfg;
 
 };
 
 
 /**
- * Handle returned by #test_prepare_wire_transfer.
+ * Handle returned by #taler_bank_prepare_wire_transfer.
  */
 struct TALER_WIRE_PrepareHandle
 {
@@ -81,14 +76,25 @@ struct TALER_WIRE_PrepareHandle
   struct GNUNET_SCHEDULER_Task *task;
 
   /**
-   * Test closure we run in.
+   * TalerBank closure we run in.
    */
-  struct TestClosure *tc;
+  struct TalerBankClosure *tc;
 
   /**
-   * Wire data for the transfer.
+   * Authentication information.
+   */
+  struct TALER_BANK_AuthenticationData auth;
+
+  /**
+   * Which account should be debited? Given as the respective
+   * section in the configuration file.
    */
-  json_t *wire;
+  char *origin_account_url;
+
+  /**
+   * Which account should be credited?
+   */
+  char *destination_account_url;
 
   /**
    * Base URL to use for the exchange.
@@ -120,7 +126,7 @@ struct TALER_WIRE_PrepareHandle
 
 
 /**
- * Handle returned by #test_execute_wire_transfer.
+ * Handle returned by #taler_bank_execute_wire_transfer.
  */
 struct TALER_WIRE_ExecuteHandle
 {
@@ -142,7 +148,6 @@ struct TALER_WIRE_ExecuteHandle
 };
 
 
-
 /**
  * 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
@@ -155,10 +160,10 @@ struct TALER_WIRE_ExecuteHandle
  *         #GNUNET_SYSERR if the amount or currency was invalid
  */
 static int
-test_amount_round (void *cls,
-                   struct TALER_Amount *amount)
+taler_bank_amount_round (void *cls,
+                         struct TALER_Amount *amount)
 {
-  struct TestClosure *tc = cls;
+  struct TalerBankClosure *tc = cls;
   uint32_t delta;
 
   if (NULL == tc->currency)
@@ -174,7 +179,7 @@ test_amount_round (void *cls,
     GNUNET_break (0);
     return GNUNET_SYSERR;
   }
-  /* 'test' method supports 1/100 of the unit currency, i.e. 0.01 CUR */
+  /* '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;
@@ -184,209 +189,99 @@ test_amount_round (void *cls,
 
 
 /**
- * Compute purpose for signing.
- *
- * @param account number of the account
- * @param bank_url URL of the bank
- * @param[out] wsd purpose to be signed
+ * Information about an account extracted from a payto://-URL.
  */
-static void
-compute_purpose (uint64_t account,
-                 const char *bank_url,
-                 struct TALER_MasterWireDetailsPS *wsd)
+struct Account
 {
-  struct GNUNET_HashContext *hc;
-  uint64_t n = GNUNET_htonll (account);
-
-  wsd->purpose.size = htonl (sizeof (struct TALER_MasterWireDetailsPS));
-  wsd->purpose.purpose = htonl (TALER_SIGNATURE_MASTER_TEST_DETAILS);
-  hc = GNUNET_CRYPTO_hash_context_start ();
-  GNUNET_CRYPTO_hash_context_read (hc,
-                                  "test",
-                                  strlen ("test") + 1);
-  GNUNET_CRYPTO_hash_context_read (hc,
-                                  &n,
-                                   sizeof (n));
-  GNUNET_CRYPTO_hash_context_read (hc,
-                                  bank_url,
-                                  strlen (bank_url) + 1);
-  GNUNET_CRYPTO_hash_context_finish (hc,
-                                    &wsd->h_sepa_details);
-}
+  /**
+   * Hostname of the bank (possibly including port).
+   */
+  char *hostname;
+
+  /**
+   * Bank account number.
+   */
+  unsigned long long no;
+};
 
 
 /**
- * Check if the given wire format JSON object is correctly formatted.
- * Right now, the only thing we require is a field
- * "account_number" which must contain a positive 53-bit integer.
+ * Parse payto:// account URL (only account information,
+ * wire subject and amount are ignored).
  *
- * @param cls the @e cls of this struct with the plugin-specific state
- * @param wire the JSON wire format object
- * @param master_pub public key of the exchange to verify against
- * @param[out] emsg set to an error message, unless we return #TALER_EC_NONE;
- *             error message must be freed by the caller using GNUNET_free()
- * @return #TALER_EC_NONE if correctly formatted
+ * @param account_url URL to parse
+ * @param account[out] set to information, can be NULL
+ * @return #TALER_EC_NONE if @a account_url is well-formed
  */
 static enum TALER_ErrorCode
-test_wire_validate (void *cls,
-                    const json_t *wire,
-                    const struct TALER_MasterPublicKeyP *master_pub,
-                    char **emsg)
+parse_payto (const char *account_url,
+             struct Account *r_account)
 {
-  struct TestClosure *tc = cls;
-  json_error_t error;
-  json_int_t account_no;
-  const char *bank_url;
-  const char *sig_s;
-  struct TALER_MasterWireDetailsPS wsd;
-  struct TALER_MasterSignatureP sig;
-
-  *emsg = NULL;
-  if (0 !=
-      json_unpack_ex ((json_t *) wire,
-                     &error,
-                     0,
-                     "{s:I, s:s}",
-                     "account_number", &account_no,
-                      "bank_url", &bank_url))
+  const char *hostname;
+  const char *account;
+  const char *q;
+  unsigned long long no;
+
+#define PREFIX "payto://x-taler-bank/"
+  if (0 != strncasecmp (account_url,
+                        PREFIX,
+                        strlen (PREFIX)))
+    return TALER_EC_PAYTO_WRONG_METHOD;
+  hostname = &account_url[strlen (PREFIX)];
+  if (NULL == (account = strchr (hostname,
+                                 (unsigned char) '/')))
+    return TALER_EC_PAYTO_MALFORMED;
+  account++;
+  if (NULL != (q = strchr (account,
+                           (unsigned char) '?')))
   {
-    char *dump;
-
-    dump = json_dumps (wire, 0);
-    GNUNET_asprintf (emsg,
-                     "JSON parsing failed at %s:%u: %s (%s): %s\n",
-                     __FILE__, __LINE__,
-                     error.text,
-                     error.source,
-                     dump);
-    free (dump);
-    return TALER_EC_DEPOSIT_INVALID_WIRE_FORMAT_JSON;
-  }
-  if ( (account_no < 0) ||
-       (account_no > (1LL << 53)) )
-  {
-    GNUNET_asprintf (emsg,
-                     "Account number %llu outside of permitted range\n",
-                     account_no);
-    return TALER_EC_DEPOSIT_INVALID_WIRE_FORMAT_ACCOUNT_NUMBER;
-  }
-  if ( (NULL != tc->bank_url) &&
-       (0 != strcmp (bank_url,
-                     tc->bank_url)) )
-  {
-    GNUNET_asprintf (emsg,
-                     "Wire specifies bank URL `%s', but this exchange only 
supports `%s'\n",
-                     bank_url,
-                     tc->bank_url);
-    return TALER_EC_DEPOSIT_INVALID_WIRE_FORMAT_BANK;
-  }
-  if (NULL == master_pub)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "Skipping signature check as master public key not given\n");
-    return TALER_EC_NONE;
-  }
-  if (0 !=
-      json_unpack_ex ((json_t *) wire,
-                     &error,
-                     0,
-                     "{s:s}",
-                      "sig", &sig_s))
-  {
-    GNUNET_asprintf (emsg,
-                     "Signature check required, but signature is missing\n");
-    return TALER_EC_DEPOSIT_INVALID_WIRE_FORMAT_SIGNATURE;
+    char *s;
+
+    s = GNUNET_strndup (account,
+                        q - account);
+    if (1 != sscanf (s,
+                     "%llu",
+                     &no))
+    {
+      GNUNET_free (s);
+      return TALER_EC_PAYTO_MALFORMED;
+    }
+    GNUNET_free (s);
   }
-  compute_purpose (account_no,
-                   bank_url,
-                   &wsd);
-  if (GNUNET_OK !=
-      GNUNET_STRINGS_string_to_data (sig_s,
-                                     strlen (sig_s),
-                                     &sig,
-                                     sizeof (sig)))
+  else
   {
-    GNUNET_break (0);
-    return TALER_EC_DEPOSIT_INVALID_WIRE_FORMAT_SIGNATURE;
+    if (1 != sscanf (account,
+                     "%llu",
+                     &no))
+      return TALER_EC_PAYTO_MALFORMED;
   }
-  if (GNUNET_OK !=
-      GNUNET_CRYPTO_eddsa_verify (TALER_SIGNATURE_MASTER_TEST_DETAILS,
-                                  &wsd.purpose,
-                                  &sig.eddsa_signature,
-                                  &master_pub->eddsa_pub))
+  if (no > MAX_ACCOUNT_NO)
+    return TALER_EC_PAYTO_MALFORMED;
+  if (NULL != r_account)
   {
-    GNUNET_asprintf (emsg,
-                     "Signature using public key `%s' invalid\n",
-                     TALER_B2S (master_pub));
-    return TALER_EC_DEPOSIT_INVALID_WIRE_FORMAT_SIGNATURE;
+    r_account->hostname = GNUNET_strndup (hostname,
+                                          account - hostname);
+    r_account->no = no;
   }
   return TALER_EC_NONE;
 }
 
 
 /**
- * Obtain wire transfer details in the plugin-specific format
- * from the configuration.
+ * Check if the given payto:// URL is correctly formatted.
  *
- * @param cls closure
- * @param cfg configuration with details about wire accounts
- * @param account_name which section in the configuration should we parse
- * @return NULL if @a cfg fails to have valid wire details for @a account_name
+ * @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 json_t *
-test_get_wire_details (void *cls,
-                       const struct GNUNET_CONFIGURATION_Handle *cfg,
-                       const char *account_name)
+static enum TALER_ErrorCode
+taler_bank_wire_validate (void *cls,
+                          const char *account_url)
 {
-  struct TestClosure *tc = cls;
-  char *test_wire_file;
-  json_error_t err;
-  json_t *ret;
-  char *emsg;
+  (void) cls;
 
-  /* Fetch reply */
-  if (GNUNET_OK !=
-      GNUNET_CONFIGURATION_get_value_filename (cfg,
-                                               account_name,
-                                               "TEST_RESPONSE_FILE",
-                                               &test_wire_file))
-  {
-    GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
-                               account_name,
-                               "TEST_RESPONSE_FILE");
-    return NULL;
-  }
-  ret = json_load_file (test_wire_file,
-                        JSON_REJECT_DUPLICATES,
-                        &err);
-  if (NULL == ret)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                "Failed to parse JSON in %s: %s (%s:%u)\n",
-                test_wire_file,
-                err.text,
-                err.source,
-                err.line);
-    GNUNET_free (test_wire_file);
-    return NULL;
-  }
-  if (TALER_EC_NONE !=
-      test_wire_validate (tc,
-                          ret,
-                          NULL,
-                          &emsg))
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                "Failed to validate TEST wire data in %s: %s\n",
-                test_wire_file,
-                emsg);
-    GNUNET_free (emsg);
-    GNUNET_free (test_wire_file);
-    json_decref (ret);
-    return NULL;
-  }
-  GNUNET_free (test_wire_file);
-  return ret;
+  return parse_payto (account_url,
+                      NULL);
 }
 
 
@@ -407,9 +302,15 @@ struct BufFormatP
    */
   struct TALER_AmountNBO amount;
 
-  /* followed by serialized 'wire' JSON data (0-terminated) */
+  /* followed by 0-terminated origin account URL */
+
+  /* followed by 0-terminated destination account URL */
 
-  /* followed by 0-terminated base 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
@@ -423,12 +324,14 @@ GNUNET_NETWORK_STRUCT_END
  * @param pth preparation to cancel
  */
 static void
-test_prepare_wire_transfer_cancel (void *cls,
-                                   struct TALER_WIRE_PrepareHandle *pth)
+taler_bank_prepare_wire_transfer_cancel (void *cls,
+                                         struct TALER_WIRE_PrepareHandle *pth)
 {
   if (NULL != pth->task)
     GNUNET_SCHEDULER_cancel (pth->task);
-  json_decref (pth->wire);
+  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);
 }
@@ -444,52 +347,111 @@ static void
 do_prepare (void *cls)
 {
   struct TALER_WIRE_PrepareHandle *pth = cls;
-  char *wire_enc;
-  size_t len_w;
+  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' */
-  wire_enc = json_dumps (pth->wire,
-                         JSON_COMPACT | JSON_SORT_KEYS);
-  if (NULL == wire_enc)
+  len_o = strlen (pth->origin_account_url) + 1;
+  len_i = strlen (pth->destination_account_url) + 1;
+  len_b = strlen (pth->exchange_base_url) + 1;
+  switch (pth->auth.method)
   {
-    GNUNET_break (0);
-    pth->ptc (pth->ptc_cls,
-              NULL,
-              0);
-    test_prepare_wire_transfer_cancel (NULL,
-                                       pth);
-    return;
+  case TALER_BANK_AUTH_NONE:
+    len_au = 0;
+    len_ap = 0;
+    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;
   }
-  len_w = strlen (wire_enc) + 1;
-  len_b = strlen (pth->exchange_base_url) + 1;
   bf.wtid = pth->wtid;
   TALER_amount_hton (&bf.amount,
                      &pth->amount);
   {
-    char buf[sizeof (struct BufFormatP) + len_w + len_b];
+    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)],
-            wire_enc,
-            len_w);
-    memcpy (&buf[sizeof (struct BufFormatP) + len_w],
+            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));
   }
-  free (wire_enc); /* not using GNUNET_free(),
-                      as this one is allocated by libjansson */
-  test_prepare_wire_transfer_cancel (NULL,
-                                     pth);
+  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 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 !=
+      parse_payto (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;
+  }
+  GNUNET_free (account_url);
+  return GNUNET_OK;
 }
 
 
@@ -501,7 +463,9 @@ do_prepare (void *cls)
  * the work.
  *
  * @param cls the @e cls of this struct with the plugin-specific state
- * @param wire valid wire account information
+ * @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
@@ -510,31 +474,84 @@ do_prepare (void *cls)
  * @return NULL on failure
  */
 static struct TALER_WIRE_PrepareHandle *
-test_prepare_wire_transfer (void *cls,
-                            const json_t *wire,
-                            const struct TALER_Amount *amount,
-                            const char *exchange_base_url,
-                            const struct TALER_WireTransferIdentifierRawP 
*wtid,
-                            TALER_WIRE_PrepareTransactionCallback ptc,
-                            void *ptc_cls)
+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 TestClosure *tc = cls;
+  struct TalerBankClosure *tc = cls;
   struct TALER_WIRE_PrepareHandle *pth;
-  char *emsg;
+  char *origin_account_url;
+  struct Account a_in;
+  struct Account a_out;
 
+  /* Check that payto:// URLs are valid */
+  if (TALER_EC_NONE !=
+      parse_payto (destination_account_url,
+                   &a_out))
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                "payto://-URL `%s' is invalid!\n",
+                destination_account_url);
+    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");
+    GNUNET_free (a_out.hostname);
+    return NULL;
+  }
   if (TALER_EC_NONE !=
-      test_wire_validate (tc,
-                          wire,
-                          NULL,
-                          &emsg))
+      parse_payto (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);
+    GNUNET_free (a_out.hostname);
+    return NULL;
+  }
+
+  /* Make sure the bank is the same! */
+  if (0 != strcasecmp (a_in.hostname,
+                       a_out.hostname))
   {
-    GNUNET_break_op (0);
-    GNUNET_free (emsg);
+    GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+                "x-taler-bank hostname missmatch: `%s' != `%s'\n",
+                a_in.hostname,
+                a_out.hostname);
+    GNUNET_free (a_in.hostname);
+    GNUNET_free (a_out.hostname);
     return NULL;
   }
+  GNUNET_free (a_in.hostname);
+  GNUNET_free (a_out.hostname);
+
   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);
+    return NULL;
+  }
+
   pth->tc = tc;
-  pth->wire = json_incref ((json_t *) wire);
+  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;
@@ -599,61 +616,6 @@ execute_cb (void *cls,
 
 
 /**
- * Sign wire transfer details in the plugin-specific format.
- *
- * @param cls closure
- * @param in wire transfer details in JSON format
- * @param key private signing key to use
- * @param salt salt to add
- * @param[out] sig where to write the signature
- * @return #GNUNET_OK on success
- */
-static int
-test_sign_wire_details (void *cls,
-                        const json_t *in,
-                        const struct TALER_MasterPrivateKeyP *key,
-                        const struct GNUNET_HashCode *salt,
-                        struct TALER_MasterSignatureP *sig)
-{
-  struct TALER_MasterWireDetailsPS wsd;
-  const char *bank_url;
-  const char *type;
-  json_int_t account;
-  json_error_t err;
-
-  if (0 !=
-      json_unpack_ex ((json_t *) in,
-                      &err,
-                      0 /* flags */,
-                      "{s:s, s:s, s:I}",
-                      "type", &type,
-                      "bank_url", &bank_url,
-                      "account_number", &account))
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
-                "Failed to unpack JSON: %s (at %u)\n",
-                err.text,
-                err.position);
-    return GNUNET_SYSERR;
-  }
-  if (0 != strcmp (type,
-                   "test"))
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
-                "`type' must be `test' for test wire details\n");
-    return GNUNET_SYSERR;
-  }
-  compute_purpose (account,
-                   bank_url,
-                   &wsd);
-  GNUNET_CRYPTO_eddsa_sign (&key->eddsa_priv,
-                           &wsd.purpose,
-                           &sig->eddsa_signature);
-  return GNUNET_OK;
-}
-
-
-/**
  * Execute a wire transfer.
  *
  * @param cls the @e cls of this struct with the plugin-specific state
@@ -664,22 +626,24 @@ test_sign_wire_details (void *cls,
  * @return NULL on error
  */
 static struct TALER_WIRE_ExecuteHandle *
-test_execute_wire_transfer (void *cls,
-                            const char *buf,
-                            size_t buf_size,
-                            TALER_WIRE_ConfirmationCallback cc,
-                            void *cc_cls)
+taler_bank_execute_wire_transfer (void *cls,
+                                  const char *buf,
+                                  size_t buf_size,
+                                  TALER_WIRE_ConfirmationCallback cc,
+                                  void *cc_cls)
 {
-  struct TestClosure *tc = cls;
+  struct TalerBankClosure *tc = cls;
   struct TALER_WIRE_ExecuteHandle *eh;
-  json_t *wire;
-  json_error_t error;
   struct TALER_Amount amount;
-  json_int_t account_no;
+  struct Account origin_account;
+  struct Account destination_account;
   struct BufFormatP bf;
-  char *emsg;
-  const char *json_s;
   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)
@@ -694,37 +658,76 @@ test_execute_wire_transfer (void *cls,
     GNUNET_break (0);
     return NULL;
   }
-  json_s = &buf[sizeof (struct BufFormatP)];
-  exchange_base_url = &json_s[strlen (json_s) + 1];
-  if (exchange_base_url > &buf[buf_size - 1])
-  {
-    GNUNET_break (0);
-    return NULL;
-  }
   memcpy (&bf,
           buf,
           sizeof (bf));
   TALER_amount_ntoh (&amount,
                      &bf.amount);
-  wire = json_loads (json_s,
-                     JSON_REJECT_DUPLICATES,
-                     NULL);
-  if (NULL == wire)
+  origin_account_url = &buf[sizeof (struct BufFormatP)];
+  left = buf_size - sizeof (struct BufFormatP);
+  slen = strlen (origin_account_url) + 1;
+  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.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.username) + 1;
+    GNUNET_assert (left >= slen);
+    left -= slen;
+    if (0 != left)
+    {
+      GNUNET_break (0);
+      return NULL;
+    }
+  }
+
+  if (TALER_EC_NONE !=
+      parse_payto (origin_account_url,
+                   &origin_account))
   {
     GNUNET_break (0);
     return NULL;
   }
-  GNUNET_assert (TALER_EC_NONE ==
-                 test_wire_validate (tc,
-                                     wire,
-                                     NULL,
-                                     &emsg));
-  if (0 !=
-      json_unpack_ex (wire,
-                     &error,
-                     0,
-                     "{s:I}",
-                     "account_number", &account_no))
+  if (TALER_EC_NONE !=
+      parse_payto (destination_account_url,
+                   &destination_account))
+  {
+    GNUNET_break (0);
+    return NULL;
+  }
+  if (0 != strcasecmp (origin_account.hostname,
+                       destination_account.hostname))
   {
     GNUNET_break (0);
     return NULL;
@@ -736,17 +739,16 @@ test_execute_wire_transfer (void *cls,
   wire_s = GNUNET_STRINGS_data_to_string_alloc (&bf.wtid,
                                                 sizeof (bf.wtid));
   eh->aaih = TALER_BANK_admin_add_incoming (tc->ctx,
-                                            tc->bank_url,
-                                            &tc->auth,
+                                            origin_account.hostname,
+                                            &auth,
                                             exchange_base_url,
                                             wire_s,
                                             &amount,
-                                            (uint64_t) tc->exchange_account_no,
-                                           (uint64_t) account_no,
+                                            (uint64_t) origin_account.no,
+                                           (uint64_t) destination_account.no,
                                             &execute_cb,
                                             eh);
   GNUNET_free (wire_s);
-  json_decref (wire);
   if (NULL == eh->aaih)
   {
     GNUNET_break (0);
@@ -770,8 +772,8 @@ test_execute_wire_transfer (void *cls,
  * @param eh execution to cancel
  */
 static void
-test_execute_wire_transfer_cancel (void *cls,
-                                   struct TALER_WIRE_ExecuteHandle *eh)
+taler_bank_execute_wire_transfer_cancel (void *cls,
+                                         struct TALER_WIRE_ExecuteHandle *eh)
 {
   TALER_BANK_admin_add_incoming_cancel (eh->aaih);
   GNUNET_free (eh);
@@ -779,7 +781,7 @@ test_execute_wire_transfer_cancel (void *cls,
 
 
 /**
- * Handle for a #test_get_history() request.
+ * Handle for a #taler_bank_get_history() request.
  */
 struct TALER_WIRE_HistoryHandle
 {
@@ -799,10 +801,35 @@ struct TALER_WIRE_HistoryHandle
    */
   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)
+{
+  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`
@@ -839,7 +866,8 @@ bhist_cb (void *cls,
       wd.amount = details->amount;
       wd.execution_date = details->execution_date;
       subject = GNUNET_strdup (details->wire_transfer_subject);
-      space = strchr (subject, (int) ' ');
+      space = strchr (subject,
+                      (unsigned char) ' ');
       if (NULL != space)
       {
         /* Space separates the actual wire transfer subject from the
@@ -867,14 +895,7 @@ bhist_cb (void *cls,
         wd.wtid_s = NULL;
       }
       GNUNET_free (subject);
-      wd.account_details = details->account_details;
-
-      GNUNET_break (NULL != whh->hh);
-
-      /* Once we get the sentinel element, the handle becomes invalid. */
-      if (TALER_BANK_DIRECTION_NONE == dir)
-        whh->hh = NULL;
-
+      wd.account_url = details->account_url;
       if ( (NULL != whh->hres_cb) &&
            (GNUNET_OK !=
             whh->hres_cb (whh->hres_cb_cls,
@@ -884,7 +905,11 @@ bhist_cb (void *cls,
                           sizeof (bserial_id),
                           &wd)) )
         whh->hres_cb = NULL;
-      break;
+      GNUNET_break (NULL != whh->hh);
+      /* Once we get the sentinel element, the handle becomes invalid. */
+      if (TALER_BANK_DIRECTION_NONE == dir)
+        whh->hh = NULL;
+      return;
     }
   case MHD_HTTP_NO_CONTENT:
     if (NULL != whh->hres_cb)
@@ -894,7 +919,6 @@ bhist_cb (void *cls,
                            NULL,
                            0,
                            NULL);
-    GNUNET_free (whh);
     break;
   default:
     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
@@ -908,9 +932,11 @@ bhist_cb (void *cls,
                            NULL,
                            0,
                            NULL);
-    GNUNET_free (whh);
     break;
   }
+  whh->hh = NULL;
+  taler_bank_get_history_cancel (NULL,
+                                 whh);
 }
 
 
@@ -921,12 +947,14 @@ bhist_cb (void *cls,
  * 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
+ * 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 from which row on do we want to get results, use NULL for 
the lataler_bank; 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;
@@ -935,18 +963,20 @@ bhist_cb (void *cls,
  * @param hres_cb_cls closure for the above callback
  */
 static struct TALER_WIRE_HistoryHandle *
-test_get_history (void *cls,
-                  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)
+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 TestClosure *tc = cls;
+  struct TalerBankClosure *tc = cls;
   struct TALER_WIRE_HistoryHandle *whh;
   const uint64_t *start_off_b64;
   uint64_t start_row;
+  struct Account account;
 
   if (0 == num_results)
   {
@@ -962,11 +992,12 @@ test_get_history (void *cls,
        (sizeof (uint64_t) != start_off_len) )
   {
     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                "Wire plugin 'test' got start offset of wrong size (%llu 
instead of %llu)\n",
-                (unsigned long long) start_off_len, (unsigned long long) 
sizeof (uint64_t));
+                "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, 
+     * wrote a wrong value to it.  Instead of completely stopping to work,
      * we just scan from the beginning. */
     start_off = NULL;
   }
@@ -979,14 +1010,28 @@ test_get_history (void *cls,
     start_off_b64 = start_off;
     start_row = GNUNET_ntohll (*start_off_b64);
   }
+  if (GNUNET_OK !=
+      parse_account_cfg (tc->cfg,
+                         account_section,
+                         &account))
+    return NULL;
 
   whh = GNUNET_new (struct TALER_WIRE_HistoryHandle);
+  if (GNUNET_OK !=
+      TALER_BANK_auth_parse_cfg (tc->cfg,
+                                 account_section,
+                                 &whh->auth))
+  {
+    GNUNET_free (whh);
+    return NULL;
+  }
+
   whh->hres_cb = hres_cb;
   whh->hres_cb_cls = hres_cb_cls;
   whh->hh = TALER_BANK_history (tc->ctx,
-                                tc->bank_url,
-                                &tc->auth,
-                                (uint64_t) tc->exchange_account_no,
+                                account.hostname,
+                                &whh->auth,
+                                (uint64_t) account.no,
                                 direction,
                                 start_row,
                                 num_results,
@@ -995,34 +1040,17 @@ test_get_history (void *cls,
   if (NULL == whh->hh)
   {
     GNUNET_break (0);
-    GNUNET_free (whh);
+    taler_bank_get_history_cancel (NULL,
+                                   whh);
+    GNUNET_free (account.hostname);
     return NULL;
   }
-
+  GNUNET_free (account.hostname);
   return whh;
 }
 
 
 /**
- * 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
-test_get_history_cancel (void *cls,
-                        struct TALER_WIRE_HistoryHandle *whh)
-{
-  if (NULL != whh->hh)
-  {
-    TALER_BANK_history_cancel (whh->hh);
-    whh->hh = NULL;
-  }
-  GNUNET_free (whh);
-}
-
-
-/**
  * Context for a rejection operation.
  */
 struct TALER_WIRE_RejectHandle
@@ -1041,6 +1069,11 @@ struct TALER_WIRE_RejectHandle
    * Handle for the reject operation.
    */
   struct TALER_BANK_RejectHandle *brh;
+
+  /**
+   * Authentication information to use.
+   */
+  struct TALER_BANK_AuthenticationData auth;
 };
 
 
@@ -1069,6 +1102,32 @@ reject_cb (void *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.
+ *
+ * @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;
+
+  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).
@@ -1079,6 +1138,8 @@ reject_cb (void *cls,
  * 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
@@ -1086,15 +1147,17 @@ reject_cb (void *cls,
  * @return handle to cancel the operation
  */
 static struct TALER_WIRE_RejectHandle *
-test_reject_transfer (void *cls,
-                      const void *start_off,
-                      size_t start_off_len,
-                      TALER_WIRE_RejectTransferCallback rej_cb,
-                      void *rej_cb_cls)
+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 TestClosure *tc = cls;
+  struct TalerBankClosure *tc = cls;
   const uint64_t *rowid_b64 = start_off;
   struct TALER_WIRE_RejectHandle *rh;
+  struct Account account;
 
   if (sizeof (uint64_t) != start_off_len)
   {
@@ -1102,178 +1165,109 @@ test_reject_transfer (void *cls,
     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;
   rh->brh = TALER_BANK_reject (tc->ctx,
-                               tc->bank_url,
-                               &tc->auth,
-                               (uint64_t) tc->exchange_account_no,
+                               account.hostname,
+                               &rh->auth,
+                               (uint64_t) account.no,
                                GNUNET_ntohll (*rowid_b64),
                                &reject_cb,
                                rh);
   if (NULL == rh->brh)
   {
-    GNUNET_free (rh);
+    (void) taler_bank_reject_transfer_cancel (tc,
+                                              rh);
+    GNUNET_free (account.hostname);
     return NULL;
   }
+  GNUNET_free (account.hostname);
   return 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 *
-test_reject_transfer_cancel (void *cls,
-                             struct TALER_WIRE_RejectHandle *rh)
-{
-  void *ret = rh->rej_cb_cls;
-
-  if (NULL != rh->brh)
-    TALER_BANK_reject_cancel (rh->brh);
-  GNUNET_free (rh);
-  return ret;
-}
-
-
-/**
- * Initialize test-wire subsystem.
+ * Initialize taler_bank-wire subsystem.
  *
  * @param cls a configuration instance
  * @return NULL on error, otherwise a `struct TALER_WIRE_Plugin`
  */
 void *
-libtaler_plugin_wire_test_init (void *cls)
+libtaler_plugin_wire_taler_bank_init (void *cls)
 {
   struct GNUNET_CONFIGURATION_Handle *cfg = cls;
-  struct TestClosure *tc;
+  struct TalerBankClosure *tc;
   struct TALER_WIRE_Plugin *plugin;
-  char *user;
-  char *pass;
 
-  tc = GNUNET_new (struct TestClosure);
-  if (NULL != cfg)
+  tc = GNUNET_new (struct TalerBankClosure);
+  tc->cfg = cfg;
+  if (GNUNET_OK !=
+      GNUNET_CONFIGURATION_get_value_string (cfg,
+                                             "taler",
+                                             "CURRENCY",
+                                             &tc->currency))
   {
-    if (GNUNET_OK !=
-        GNUNET_CONFIGURATION_get_value_string (cfg,
-                                               "exchange-wire-test",
-                                               "BANK_URL",
-                                               &tc->bank_url))
-    {
-      GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
-                                 "exchange-wire-test",
-                                 "BANK_URL");
-      GNUNET_free (tc);
-      return NULL;
-    }
-    if (GNUNET_OK !=
-        GNUNET_CONFIGURATION_get_value_number (cfg,
-                                               "exchange-wire-test",
-                                               "EXCHANGE_ACCOUNT_NUMBER",
-                                               &tc->exchange_account_no))
-    {
-      GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
-                                 "exchange-wire-test",
-                                 "EXCHANGE_ACCOUNT_NUMBER");
-      GNUNET_free (tc->bank_url);
-      GNUNET_free (tc);
-      return NULL;
-    }
-    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->bank_url);
-      GNUNET_free (tc);
-      return NULL;
-    }
-    if (GNUNET_OK !=
-        GNUNET_CONFIGURATION_get_value_string (cfg,
-                                               "exchange-wire-test",
-                                               "USERNAME",
-                                               &user))
-    {
-      GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
-                                 "exchange-wire-test",
-                                 "USERNAME");
-      GNUNET_free (tc->bank_url);
-      GNUNET_free (tc);
-      return NULL;
-    }
-    if (GNUNET_OK !=
-        GNUNET_CONFIGURATION_get_value_string (cfg,
-                                               "exchange-wire-test",
-                                               "PASSWORD",
-                                               &pass))
-    {
-      GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
-                                 "exchange-wire-test",
-                                 "PASSWORD");
-      GNUNET_free (tc->bank_url);
-      GNUNET_free (tc);
-      GNUNET_free (user);
-      return NULL;
-    }
-    tc->auth.method = TALER_BANK_AUTH_BASIC;
-    tc->auth.details.basic.username = user;
-    tc->auth.details.basic.password = pass;
-    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->bank_url);
-      GNUNET_free (tc->auth.details.basic.username);
-      GNUNET_free (tc->auth.details.basic.password);
-      GNUNET_free (tc);
-      return NULL;
-    }
+    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->amount_round = &test_amount_round;
-  plugin->get_wire_details = &test_get_wire_details;
-  plugin->sign_wire_details = &test_sign_wire_details;
-  plugin->wire_validate = &test_wire_validate;
-  plugin->prepare_wire_transfer = &test_prepare_wire_transfer;
-  plugin->prepare_wire_transfer_cancel = &test_prepare_wire_transfer_cancel;
-  plugin->execute_wire_transfer = &test_execute_wire_transfer;
-  plugin->execute_wire_transfer_cancel = &test_execute_wire_transfer_cancel;
-  plugin->get_history = &test_get_history;
-  plugin->get_history_cancel = &test_get_history_cancel;
-  plugin->reject_transfer = &test_reject_transfer;
-  plugin->reject_transfer_cancel = &test_reject_transfer_cancel;
+  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 Test wire subsystem.
+ * Shutdown taler-bank wire subsystem.
  *
  * @param cls a `struct TALER_WIRE_Plugin`
  * @return NULL (always)
  */
 void *
-libtaler_plugin_wire_test_done (void *cls)
+libtaler_plugin_wire_taler_bank_done (void *cls)
 {
   struct TALER_WIRE_Plugin *plugin = cls;
-  struct TestClosure *tc = plugin->cls;
+  struct TalerBankClosure *tc = plugin->cls;
 
   if (NULL != tc->ctx)
   {
@@ -1285,28 +1279,10 @@ libtaler_plugin_wire_test_done (void *cls)
     GNUNET_CURL_gnunet_rc_destroy (tc->rc);
     tc->rc = NULL;
   }
-  switch (tc->auth.method)
-  {
-  case TALER_BANK_AUTH_NONE:
-    break;
-  case TALER_BANK_AUTH_BASIC:
-    if (NULL != tc->auth.details.basic.username)
-    {
-      GNUNET_free (tc->auth.details.basic.username);
-      tc->auth.details.basic.username = NULL;
-    }
-    if (NULL != tc->auth.details.basic.password)
-    {
-      GNUNET_free (tc->auth.details.basic.password);
-      tc->auth.details.basic.password = NULL;
-    }
-    break;
-  }
   GNUNET_free_non_null (tc->currency);
-  GNUNET_free_non_null (tc->bank_url);
   GNUNET_free (tc);
   GNUNET_free (plugin);
   return NULL;
 }
 
-/* end of plugin_wire_test.c */
+/* end of plugin_wire_taler-bank.c */
diff --git a/src/wire/plugin_wire_template.c 
b/src/wire-plugins/plugin_wire_template.c
similarity index 74%
rename from src/wire/plugin_wire_template.c
rename to src/wire-plugins/plugin_wire_template.c
index 06e70c2..6fadb88 100644
--- a/src/wire/plugin_wire_template.c
+++ b/src/wire-plugins/plugin_wire_template.c
@@ -1,6 +1,6 @@
 /*
   This file is part of TALER
-  Copyright (C) 2016 GNUnet e.V.
+  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
@@ -33,14 +33,14 @@ struct TemplateClosure
 {
 
   /**
-   * URL of the bank for sending funds to the bank.
+   * Which currency do we support?
    */
-  char *bank_url;
+  char *currency;
 
   /**
-   * Which currency do we support?
+   * Which configuration do we use to lookup accounts?
    */
-  char *currency;
+  struct GNUNET_CONFIGURATION_Handle *cfg;
 
 };
 
@@ -74,42 +74,17 @@ template_amount_round (void *cls,
 
 
 /**
- * Obtain wire transfer details in the plugin-specific format
- * from the configuration.
- *
- * @param cls closure
- * @param cfg configuration with details about wire accounts
- * @param account_name which section in the configuration should we parse
- * @return NULL if @a cfg fails to have valid wire details for @a account_name
- */
-static json_t *
-template_get_wire_details (void *cls,
-                           const struct GNUNET_CONFIGURATION_Handle *cfg,
-                           const char *account_name)
-{
-  GNUNET_break (0);
-  return NULL;
-}
-
-
-/**
- * Check if the given wire format JSON object is correctly formatted
+ * 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 wire the JSON wire format object
- * @param master_pub public key of the exchange to verify against
- * @param[out] emsg set to an error message, unless we return #TALER_EC_NONE;
- *             error message must be freed by the caller using GNUNET_free()
+ * @param account_url the payto:// URL
  * @return #TALER_EC_NONE if correctly formatted
  */
 static enum TALER_ErrorCode
 template_wire_validate (void *cls,
-                        const json_t *wire,
-                        const struct TALER_MasterPublicKeyP *master_pub,
-                        char **emsg)
+                        const char *account_url)
 {
-  GNUNET_asprintf (emsg,
-                   "Not implemented");
+  GNUNET_break (0);
   return TALER_EC_NOT_IMPLEMENTED;
 }
 
@@ -118,7 +93,9 @@ template_wire_validate (void *cls,
  * Prepare for exeuction of a wire transfer.
  *
  * @param cls the @e cls of this struct with the plugin-specific state
- * @param wire valid wire account information
+ * @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
@@ -128,7 +105,8 @@ template_wire_validate (void *cls,
  */
 static struct TALER_WIRE_PrepareHandle *
 template_prepare_wire_transfer (void *cls,
-                                const json_t *wire,
+                                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,
@@ -178,28 +156,6 @@ template_execute_wire_transfer (void *cls,
 
 
 /**
- * Sign wire transfer details in the plugin-specific format.
- *
- * @param cls closure
- * @param in wire transfer details in JSON format
- * @param key private signing key to use
- * @param salt salt to add
- * @param[out] sig where to write the signature
- * @return #GNUNET_OK on success
- */
-static int
-template_sign_wire_details (void *cls,
-                            const json_t *in,
-                            const struct TALER_MasterPrivateKeyP *key,
-                            const struct GNUNET_HashCode *salt,
-                            struct TALER_MasterSignatureP *sig)
-{
-  GNUNET_break (0);
-  return GNUNET_SYSERR;
-}
-
-
-/**
  * 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
@@ -230,6 +186,8 @@ template_execute_wire_transfer_cancel (void *cls,
  * (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)`.
@@ -241,6 +199,7 @@ template_execute_wire_transfer_cancel (void *cls,
  */
 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,
@@ -268,6 +227,59 @@ template_get_history_cancel (void *cls,
 
 
 /**
+ * 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)
+{
+  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)
+{
+  GNUNET_break (0);
+  return NULL;
+}
+
+
+/**
  * Initialize template-wire subsystem.
  *
  * @param cls a configuration instance
@@ -281,19 +293,7 @@ libtaler_plugin_wire_template_init (void *cls)
   struct TALER_WIRE_Plugin *plugin;
 
   tc = GNUNET_new (struct TemplateClosure);
-
-  if (GNUNET_OK !=
-      GNUNET_CONFIGURATION_get_value_string (cfg,
-                                             "exchange-wire-template",
-                                             "bank_url",
-                                             &tc->bank_url))
-  {
-    GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
-                               "exchange-wire-template",
-                               "bank_url");
-    GNUNET_free (tc);
-    return NULL;
-  }
+  tc->cfg = cfg;
   if (GNUNET_OK !=
       GNUNET_CONFIGURATION_get_value_string (cfg,
                                              "taler",
@@ -303,16 +303,14 @@ libtaler_plugin_wire_template_init (void *cls)
     GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
                                "taler",
                                "CURRENCY");
-    GNUNET_free (tc->bank_url);
     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->get_wire_details = &template_get_wire_details;
-  plugin->sign_wire_details = &template_sign_wire_details;
   plugin->wire_validate = &template_wire_validate;
   plugin->prepare_wire_transfer = &template_prepare_wire_transfer;
   plugin->prepare_wire_transfer_cancel = 
&template_prepare_wire_transfer_cancel;
@@ -320,6 +318,8 @@ libtaler_plugin_wire_template_init (void *cls)
   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;
 }
 
@@ -336,7 +336,6 @@ libtaler_plugin_wire_template_done (void *cls)
   struct TALER_WIRE_Plugin *plugin = cls;
   struct TemplateClosure *tc = plugin->cls;
 
-  GNUNET_free (tc->bank_url);
   GNUNET_free (tc->currency);
   GNUNET_free (tc);
   GNUNET_free (plugin);
diff --git a/src/wire-plugins/test_ebics_wireformat.c 
b/src/wire-plugins/test_ebics_wireformat.c
new file mode 100644
index 0000000..46989d5
--- /dev/null
+++ b/src/wire-plugins/test_ebics_wireformat.c
@@ -0,0 +1,80 @@
+/*
+  This file is part of TALER
+  (C) 2015, 2016, 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_ebics_wireformat.c
+ * @brief Tests for SEPA format validation by the EBICS plugin
+ * @author Sree Harsha Totakura <address@hidden>
+ */
+#include "platform.h"
+#include "taler_util.h"
+#include "taler_wire_lib.h"
+
+
+/**
+ * Valid SEPA data
+ */
+static const char *valid_wire_str = "payto://sepa/DE67830654080004822650";
+
+/**
+ * IBAN has wrong country code
+ */
+static const char *invalid_wire_str = "payto://sepa/XX67830654080004822650";
+
+/**
+ * IBAN has wrong checksum
+ */
+static const char *invalid_wire_str2 = "payto://sepa/DE67830654080004822651";
+
+/**
+ * Unsupported wireformat type
+ */
+static const char *unsupported_wire_str = 
"payto://sega/DE67830654080004822650";
+
+
+int
+main (int argc,
+      const char *const argv[])
+{
+  struct GNUNET_CONFIGURATION_Handle *cfg;
+  struct TALER_WIRE_Plugin *plugin;
+
+  GNUNET_log_setup ("test-sepa-wireformats",
+                    "WARNING",
+                    NULL);
+  cfg = GNUNET_CONFIGURATION_create ();
+  GNUNET_CONFIGURATION_set_value_string (cfg,
+                                         "taler",
+                                         "currency",
+                                         "EUR");
+  plugin = TALER_WIRE_plugin_load (cfg,
+                                   "ebics");
+  GNUNET_assert (NULL != plugin);
+  GNUNET_assert (TALER_EC_NONE !=
+                 plugin->wire_validate (plugin->cls,
+                                        unsupported_wire_str));
+  GNUNET_assert (TALER_EC_NONE !=
+                 plugin->wire_validate (plugin->cls,
+                                        invalid_wire_str));
+  GNUNET_assert (TALER_EC_NONE !=
+                 plugin->wire_validate (plugin->cls,
+                                        invalid_wire_str2));
+  GNUNET_assert (TALER_EC_NONE ==
+                 plugin->wire_validate (plugin->cls,
+                                        valid_wire_str));
+  TALER_WIRE_plugin_unload (plugin);
+  GNUNET_CONFIGURATION_destroy (cfg);
+  return 0;
+}
diff --git a/src/wire/test_wire_plugin.c b/src/wire-plugins/test_wire_plugin.c
similarity index 59%
rename from src/wire/test_wire_plugin.c
rename to src/wire-plugins/test_wire_plugin.c
index f5dba01..0e149dd 100644
--- a/src/wire/test_wire_plugin.c
+++ b/src/wire-plugins/test_wire_plugin.c
@@ -24,7 +24,6 @@
 #include "taler_wire_lib.h"
 #include "taler_wire_plugin.h"
 #include <gnunet/gnunet_json_lib.h>
-#include <jansson.h>
 
 
 /**
@@ -38,11 +37,6 @@ struct TestBlock {
   const char *plugin_name;
 
   /**
-   * JSON template expected by the plugin for an account definition.
-   */
-  const char *json_proto;
-
-  /**
    * Amount to give to the rounding function.
    */
   const char *round_in;
@@ -54,7 +48,7 @@ struct TestBlock {
 
   /**
    * Currency to give to the plugin.
-   */ 
+   */
   const char *currency;
 };
 
@@ -65,36 +59,24 @@ struct TestBlock {
  */
 static struct TestBlock tests[] = {
   {
-    .plugin_name = "sepa",
-    .json_proto = "{  \"type\":\"sepa\", \"iban\":\"DE67830654080004822650\", 
\"name\":\"GNUnet e.V.\", \"bic\":\"GENODEF1SLR\" }",
+    .plugin_name = "ebics",
     .round_in = "EUR:0.123456",
     .round_out = "EUR:0.12",
     .currency = "EUR"
   },
   {
-    .plugin_name = "test",
-    .json_proto = "{  \"type\":\"test\", \"bank_url\":\"http://localhost/\";, 
\"account_number\":42 }",
+    .plugin_name = "taler_bank",
     .round_in = "KUDOS:0.123456",
     .round_out = "KUDOS:0.12",
     .currency = "KUDOS"
   },
   {
-    NULL, NULL, NULL, NULL, NULL
+    NULL, NULL, NULL, NULL
   }
 };
 
 
 /**
- * Private key used to sign wire details.
- */
-static struct TALER_MasterPrivateKeyP priv_key;
-
-/**
- * Public key matching #priv_key.
- */
-static struct TALER_MasterPublicKeyP pub_key;
-
-/**
  * Our configuration.
  */
 static struct GNUNET_CONFIGURATION_Handle *cfg;
@@ -105,73 +87,19 @@ static struct GNUNET_CONFIGURATION_Handle *cfg;
  *
  * @param test details of the test
  * @param plugin plugin to test
- * @param wire wire details for testing
  * @return #GNUNET_OK on success
  */
 static int
 run_test (const struct TestBlock *test,
-          struct TALER_WIRE_Plugin *plugin,
-          json_t *wire)
+          struct TALER_WIRE_Plugin *plugin)
 {
   struct GNUNET_HashCode salt;
-  struct TALER_MasterSignatureP sig;
-  json_t *lwire;
   struct TALER_Amount in;
   struct TALER_Amount expect;
-  char *emsg;
 
   GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_NONCE,
                               &salt,
                               sizeof (salt));
-  if (GNUNET_OK !=
-      plugin->sign_wire_details (plugin->cls,
-                                 wire,
-                                 &priv_key,
-                                 &salt,
-                                 &sig))
-  {
-    GNUNET_break (0);
-    return GNUNET_SYSERR;
-  }
-  json_object_set_new (wire,
-                       "salt",
-                       GNUNET_JSON_from_data (&salt,
-                                              sizeof (salt)));
-  json_object_set_new (wire,
-                       "sig",
-                       GNUNET_JSON_from_data (&sig,
-                                              sizeof (sig)));
-  if (TALER_EC_NONE !=
-      plugin->wire_validate (plugin->cls,
-                             wire,
-                             &pub_key,
-                             &emsg))
-  {
-    GNUNET_break (0);
-    GNUNET_free (emsg);
-    return GNUNET_SYSERR;
-  }
-  /* load wire details from file */
-  lwire = plugin->get_wire_details (plugin->cls,
-                                    cfg,
-                                    test->plugin_name);
-  if (NULL == lwire)
-  {
-    GNUNET_break (0);
-    return GNUNET_SYSERR;
-  }
-  if (TALER_EC_NONE !=
-      plugin->wire_validate (plugin->cls,
-                             lwire,
-                             &pub_key,
-                             &emsg))
-  {
-    GNUNET_break (0);
-    GNUNET_free (emsg);
-    json_decref (lwire);
-    return GNUNET_SYSERR;
-  }
-  json_decref (lwire);
   GNUNET_assert (GNUNET_OK ==
                  TALER_string_to_amount (test->round_in,
                                          &in));
@@ -214,12 +142,9 @@ int
 main (int argc,
       const char *const argv[])
 {
-  json_t *wire;
   int ret;
   struct TALER_WIRE_Plugin *plugin;
   const struct TestBlock *test;
-  unsigned int i;
-  struct GNUNET_CRYPTO_EddsaPrivateKey *pk;
 
   GNUNET_log_setup ("test-wire-plugin",
                     "WARNING",
@@ -228,13 +153,8 @@ main (int argc,
   GNUNET_assert (GNUNET_OK ==
                  GNUNET_CONFIGURATION_load (cfg,
                                             "test_wire_plugin.conf"));
-  pk = GNUNET_CRYPTO_eddsa_key_create_from_file ("test_wire_plugin_key.priv");
-  priv_key.eddsa_priv = *pk;
-  GNUNET_free (pk);
-  GNUNET_CRYPTO_eddsa_key_get_public (&priv_key.eddsa_priv,
-                                      &pub_key.eddsa_pub);
   ret = GNUNET_OK;
-  for (i=0;NULL != (test = &tests[i])->plugin_name;i++)
+  for (unsigned int i=0;NULL != (test = &tests[i])->plugin_name;i++)
   {
     GNUNET_CONFIGURATION_set_value_string (cfg,
                                           "taler",
@@ -243,10 +163,7 @@ main (int argc,
     plugin = TALER_WIRE_plugin_load (cfg,
                                      test->plugin_name);
     GNUNET_assert (NULL != plugin);
-    wire = json_loads (test->json_proto, 0, NULL);
-    GNUNET_assert (NULL != wire);
-    ret = run_test (test, plugin, wire);
-    json_decref (wire);
+    ret = run_test (test, plugin);
     TALER_WIRE_plugin_unload (plugin);
     if (GNUNET_OK != ret)
     {
diff --git a/src/wire/test_wire_plugin.conf 
b/src/wire-plugins/test_wire_plugin.conf
similarity index 51%
rename from src/wire/test_wire_plugin.conf
rename to src/wire-plugins/test_wire_plugin.conf
index 90b4f07..d1d699b 100644
--- a/src/wire/test_wire_plugin.conf
+++ b/src/wire-plugins/test_wire_plugin.conf
@@ -1,21 +1,25 @@
 # This file is in the public domain.
 #
-[test]
+[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.
-TEST_RESPONSE_FILE = test_wire_plugin_test.json
+WIRE_JSON = test_wire_plugin_test.json
 
-[sepa]
+# 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.
-SEPA_RESPONSE_FILE = test_wire_plugin_sepa.json
+WIRE_JSON = test_wire_plugin_sepa.json
 
+# Which wire plugin should we used to access the account?
+PLUGIN = ebics
 
-[exchange-wire-test]
-# For transfers made by the exchange, we need to know
-# the URL of the bank (where the /admin/add/incoming API
-# is avaialble).
-BANK_URL = http://localhost/
 
 [taler]
 CURRENCY = "EUR"
diff --git a/src/wire/test_wire_plugin_transactions_test.c 
b/src/wire-plugins/test_wire_plugin_transactions_taler-bank.c
similarity index 87%
rename from src/wire/test_wire_plugin_transactions_test.c
rename to src/wire-plugins/test_wire_plugin_transactions_taler-bank.c
index ccfde1b..06aef8a 100644
--- a/src/wire/test_wire_plugin_transactions_test.c
+++ b/src/wire-plugins/test_wire_plugin_transactions_taler-bank.c
@@ -1,6 +1,6 @@
 /*
   This file is part of TALER
-  (C) 2015, 2016, 2017 GNUnet e.V. and Inria
+  (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
@@ -14,8 +14,8 @@
   TALER; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
 */
 /**
- * @file wire/test_wire_plugin_transactions_test.c
- * @brief Tests performing actual transactions with the TEST wire plugin 
against FAKEBANK
+ * @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"
@@ -24,7 +24,6 @@
 #include "taler_wire_plugin.h"
 #include "taler_fakebank_lib.h"
 #include <gnunet/gnunet_json_lib.h>
-#include <jansson.h>
 
 
 /**
@@ -35,21 +34,14 @@
 
 
 /**
- * Input for the wire transfer details.
+ * Destination account to use.
  */
-static const char *json_proto =
-  "{  \"type\":\"test\", \"bank_url\":\"http://localhost:8088/\";, 
\"account_number\":42 }";
-
+static const char *dest_account = "payto://x-taler-bank/localhost:8088/42";
 
 /**
- * Private key used to sign wire details.
+ * Origin account, section in the configuration file.
  */
-static struct TALER_MasterPrivateKeyP priv_key;
-
-/**
- * Public key matching #priv_key.
- */
-static struct TALER_MasterPublicKeyP pub_key;
+static const char *my_account = "account-test";
 
 /**
  * Our configuration.
@@ -250,6 +242,7 @@ confirmation_cb (void *cls,
   }
   serial_target = serial_id;
   hh = plugin->get_history (plugin->cls,
+                            my_account,
                             TALER_BANK_DIRECTION_BOTH,
                             NULL, 0,
                             5,
@@ -294,7 +287,6 @@ prepare_cb (void *cls,
 static void
 run (void *cls)
 {
-  json_t *wire;
   struct TALER_Amount amount;
 
   GNUNET_SCHEDULER_add_shutdown (&do_shutdown,
@@ -308,18 +300,15 @@ run (void *cls)
   GNUNET_assert (GNUNET_OK ==
                  TALER_string_to_amount ("KUDOS:5.01",
                                          &amount));
-  wire = json_loads (json_proto,
-                     0,
-                     NULL);
   fb = TALER_FAKEBANK_start (8088);
   ph = plugin->prepare_wire_transfer (plugin->cls,
-                                      wire,
+                                      my_account,
+                                      dest_account,
                                       &amount,
                                       "https://exchange.net/";,
                                       &wtid,
                                       &prepare_cb,
                                       NULL);
-  json_decref (wire);
 }
 
 
@@ -327,23 +316,16 @@ int
 main (int argc,
       const char *const argv[])
 {
-  struct GNUNET_CRYPTO_EddsaPrivateKey *pk;
-
   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_test.conf"));
-  pk = GNUNET_CRYPTO_eddsa_key_create_from_file ("test_wire_plugin_key.priv");
-  priv_key.eddsa_priv = *pk;
-  GNUNET_free (pk);
-  GNUNET_CRYPTO_eddsa_key_get_public (&priv_key.eddsa_priv,
-                                      &pub_key.eddsa_pub);
+                                            
"test_wire_plugin_transactions_taler-bank.conf"));
   global_ret = GNUNET_OK;
   plugin = TALER_WIRE_plugin_load (cfg,
-                                   "test");
+                                   "taler_bank");
   GNUNET_assert (NULL != plugin);
   GNUNET_SCHEDULER_run (&run,
                         NULL);
@@ -353,4 +335,4 @@ main (int argc,
   return 0;
 }
 
-/* end of test_wire_plugin_transactions_test.c */
+/* 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
new file mode 100644
index 0000000..d6d2e83
--- /dev/null
+++ b/src/wire-plugins/test_wire_plugin_transactions_taler-bank.conf
@@ -0,0 +1,12 @@
+# 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 5f65146..9fcf877 100644
--- a/src/wire/Makefile.am
+++ b/src/wire/Makefile.am
@@ -8,114 +8,15 @@ endif
 
 pkgcfgdir = $(prefix)/share/taler/config.d/
 
-pkgcfg_DATA = \
-  wire-sepa.conf \
-  wire-test.conf
-
-
-EXTRA_DIST = \
-  wire-sepa.conf \
-  wire-test.conf \
-  test_wire_plugin.conf \
-  test_wire_plugin_transactions_test.conf \
-  test_wire_plugin_key.priv \
-  test_wire_plugin_test.json \
-  test_wire_plugin_sepa.json 
-
-plugindir = $(libdir)/taler
-
-plugin_LTLIBRARIES = \
-  libtaler_plugin_wire_sepa.la \
-  libtaler_plugin_wire_test.la
-
-noinst_LTLIBRARIES = \
-  libtaler_plugin_wire_template.la
-
 lib_LTLIBRARIES = \
   libtalerwire.la
 
-
-libtaler_plugin_wire_test_la_SOURCES = \
-  plugin_wire_test.c
-libtaler_plugin_wire_test_la_LIBADD = \
-  $(LTLIBINTL)
-libtaler_plugin_wire_test_la_LDFLAGS = \
-  $(TALER_PLUGIN_LDFLAGS) \
-  $(top_builddir)/src/bank-lib/libtalerbank.la \
-  $(top_builddir)/src/util/libtalerutil.la \
-  -lgnunetcurl \
-  -lgnunetutil $(XLIB)
-
-
-libtaler_plugin_wire_sepa_la_SOURCES = \
-  plugin_wire_sepa.c
-libtaler_plugin_wire_sepa_la_LIBADD = \
-  $(LTLIBINTL)
-libtaler_plugin_wire_sepa_la_LDFLAGS = \
-  $(TALER_PLUGIN_LDFLAGS) \
-  $(top_builddir)/src/json/libtalerjson.la \
-  $(top_builddir)/src/util/libtalerutil.la \
-  -lgnunetjson \
-  -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)
-
-
 libtalerwire_la_SOURCES = \
-  wire.c
+  wire.c \
+  wire_helper.c
 libtalerwire_la_LIBADD = \
   -lgnunetutil \
   $(XLIB)
 libtalerwire_la_LDFLAGS = \
   -version-info 1:0:0 \
   -export-dynamic -no-undefined
-
-
-AM_TESTS_ENVIRONMENT=export 
TALER_PREFIX=$${TALER_PREFIX:address@hidden@};export 
PATH=$${TALER_PREFIX:address@hidden@}/bin:$$PATH;
-
-TESTS = \
- test_sepa_wireformat \
- test_wire_plugin
-
-check_PROGRAMS= \
- test_sepa_wireformat \
- test_wire_plugin \
- test_wire_plugin_transactions_test
-
-
-test_sepa_wireformat_SOURCES = \
-  test_sepa_wireformat.c
-test_sepa_wireformat_LDADD = \
-  -lgnunetutil \
-  -ljansson \
-  libtalerwire.la \
-  $(top_builddir)/src/util/libtalerutil.la
-
-
-test_wire_plugin_SOURCES = \
-  test_wire_plugin.c
-test_wire_plugin_LDADD = \
-  -lgnunetjson \
-  -lgnunetutil \
-  -ljansson \
-  libtalerwire.la \
-  $(top_builddir)/src/util/libtalerutil.la
-
-
-test_wire_plugin_transactions_test_SOURCES = \
-  test_wire_plugin_transactions_test.c
-test_wire_plugin_transactions_test_LDADD = \
-  -lgnunetjson \
-  -lgnunetutil \
-  -ljansson \
-  libtalerwire.la \
-  $(top_builddir)/src/bank-lib/libtalerfakebank.la \
-  $(top_builddir)/src/util/libtalerutil.la
diff --git a/src/wire/test_sepa_wireformat.c b/src/wire/test_sepa_wireformat.c
deleted file mode 100644
index 07a3784..0000000
--- a/src/wire/test_sepa_wireformat.c
+++ /dev/null
@@ -1,120 +0,0 @@
-/*
-  This file is part of TALER
-  (C) 2015, 2016 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/test_sepa_wireformat.c
- * @brief Tests for JSON SEPA format validation
- * @author Sree Harsha Totakura <address@hidden>
- */
-
-#include "platform.h"
-#include "taler_util.h"
-#include "taler_wire_lib.h"
-
-
-/* Valid SEPA data */
-static const char * const valid_wire_str =
-    "{ \"type\":\"SEPA\", \
-\"iban\":\"DE67830654080004822650\",                 \
-\"name\":\"GNUnet e.V.\",                               \
-\"bic\":\"GENODEF1SLR\",                                 \
-\"salt\":\"123456789\",                                     \
-\"address\": \"foobar\"}";
-
-/* IBAN has wrong country code */
-static const char * const invalid_wire_str =
-    "{ \"type\":\"SEPA\", \
-\"iban\":\"XX67830654080004822650\",                 \
-\"name\":\"GNUnet e.V.\",                               \
-\"bic\":\"GENODEF1SLR\",                                 \
-\"salt\":\"123456789\",                                     \
-\"address\": \"foobar\"}";
-
-/* IBAN has wrong checksum */
-static const char * const invalid_wire_str2 =
-    "{ \"type\":\"SEPA\", \
-\"iban\":\"DE67830654080004822651\",                 \
-\"name\":\"GNUnet e.V.\",                               \
-\"bic\":\"GENODEF1SLR\",                                 \
-\"salt\":\"123456789\",                                     \
-\"address\": \"foobar\"}";
-
-/* Unsupported wireformat type */
-static const char * const unsupported_wire_str =
-    "{ \"type\":\"unsupported\", \
-\"iban\":\"DE67830654080004822650\",                 \
-\"name\":\"GNUnet e.V.\",                               \
-\"bic\":\"GENODEF1SLR\",                                 \
-\"salt\":\"123456789\",                                     \
-\"address\": \"foobar\"}";
-
-
-int
-main(int argc,
-     const char *const argv[])
-{
-  json_t *wire;
-  char *emsg;
-  json_error_t error;
-  int ret;
-  struct GNUNET_CONFIGURATION_Handle *cfg;
-  struct TALER_WIRE_Plugin *plugin;
-
-  GNUNET_log_setup ("test-sepa-wireformats",
-                    "WARNING",
-                    NULL);
-  cfg = GNUNET_CONFIGURATION_create ();
-  GNUNET_CONFIGURATION_set_value_string (cfg,
-                                         "taler",
-                                         "currency",
-                                         "EUR");
-  plugin = TALER_WIRE_plugin_load (cfg,
-                                   "sepa");
-  GNUNET_assert (NULL != plugin);
-  (void) memset(&error, 0, sizeof(error));
-  GNUNET_assert (NULL != (wire = json_loads (unsupported_wire_str, 0, NULL)));
-  GNUNET_assert (TALER_EC_NONE != plugin->wire_validate (NULL,
-                                                         wire,
-                                                         NULL,
-                                                         &emsg));
-  GNUNET_free (emsg);
-  json_decref (wire);
-  GNUNET_assert (NULL != (wire = json_loads (invalid_wire_str, 0, NULL)));
-  GNUNET_assert (TALER_EC_NONE != plugin->wire_validate (NULL,
-                                                         wire,
-                                                         NULL,
-                                                         &emsg));
-  GNUNET_free (emsg);
-  json_decref (wire);
-  GNUNET_assert (NULL != (wire = json_loads (invalid_wire_str2, 0, NULL)));
-  GNUNET_assert (TALER_EC_NONE != plugin->wire_validate (NULL,
-                                                         wire,
-                                                         NULL,
-                                                         &emsg));
-  GNUNET_free (emsg);
-  json_decref (wire);
-  GNUNET_assert (NULL != (wire = json_loads (valid_wire_str, 0, &error)));
-  ret = plugin->wire_validate (NULL,
-                               wire,
-                               NULL,
-                               &emsg);
-  json_decref (wire);
-  TALER_WIRE_plugin_unload (plugin);
-  GNUNET_CONFIGURATION_destroy (cfg);
-  if (TALER_EC_NONE != ret)
-    return 1;
-  return 0;
-}
diff --git a/src/wire/test_wire_plugin_key.priv 
b/src/wire/test_wire_plugin_key.priv
deleted file mode 100644
index 26b4f26..0000000
--- a/src/wire/test_wire_plugin_key.priv
+++ /dev/null
@@ -1 +0,0 @@
address@hidden;�%aK���ȉ�s_��Hў
\ No newline at end of file
diff --git a/src/wire/test_wire_plugin_sepa.json 
b/src/wire/test_wire_plugin_sepa.json
deleted file mode 100644
index 175345f..0000000
--- a/src/wire/test_wire_plugin_sepa.json
+++ /dev/null
@@ -1,8 +0,0 @@
-{
-  "salt": 
"32V01R7K4T02S74PZZMVXRQ1K7FR948RBNB9BJ5Z101HEQFH7CW7J82006GY3BPTGQ4FM775PSSRD3K9MY97HSNVVCGEVBPVSAQ2710",
-  "type": "sepa",
-  "iban": "DE67830654080004822650",
-  "sig": 
"K48GPPM715ZXX0DC597WESD5ECT3R0B3TAFQMB68SBF4K5CZ5KCE9NESN1JX412SPZ82PSV7JAPVJFXDDTZ63YV4295S5RC28E4221G",
-  "name": "GNUnet e.V.",
-  "bic": "GENODEF1SLR"
-}
\ No newline at end of file
diff --git a/src/wire/test_wire_plugin_test.json 
b/src/wire/test_wire_plugin_test.json
deleted file mode 100644
index e5a0c33..0000000
--- a/src/wire/test_wire_plugin_test.json
+++ /dev/null
@@ -1,7 +0,0 @@
-{
-  "type": "test",
-  "bank_url": "http://localhost/";,
-  "sig": 
"KX1CMHNFH1WE10244AEF07AXHJCF9PZDZVNZBC9P4EJEQ1MH1Y3C2TWF08VTQMK4N5TCV0V1VTGWSV0WB8TB9YQRZW87F5A6KCEZ81R",
-  "account_number": 42,
-  "salt": 
"EZV905MQPVAZEMGC6SEZQF2Z75P6ZKTN8TX00JHN11S7J81DQ78G8Z551K6TGR9WHPP0JW1X9J9X9CVRY48JTHBCP6Q4XKJ6R2G18G0"
-}
diff --git a/src/wire/test_wire_plugin_transactions_test.conf 
b/src/wire/test_wire_plugin_transactions_test.conf
deleted file mode 100644
index 42fb51b..0000000
--- a/src/wire/test_wire_plugin_transactions_test.conf
+++ /dev/null
@@ -1,15 +0,0 @@
-# This file is in the public domain.
-#
-[test]
-# This is the response we give out for the /wire request.  It provides
-# wallets with the bank information for transfers to the exchange.
-TEST_RESPONSE_FILE = test_wire_plugin_test.json
-
-[exchange-wire-test]
-# For transfers made by the exchange, we need to know
-# the URL of the bank (where the /admin/add/incoming API
-# is avaialble).
-BANK_URL= http://localhost:8088/
-
-[taler]
-CURRENCY = "KUDOS"
diff --git a/src/wire/wire-sepa.conf b/src/wire/wire-sepa.conf
deleted file mode 100644
index eb43d3d..0000000
--- a/src/wire/wire-sepa.conf
+++ /dev/null
@@ -1,15 +0,0 @@
-# This file is in the public domain.
-#
-# Configuration for SEPA wire plugin.
-
-[exchange-wire-sepa]
-# Set to "YES" to activate the 'sepa' plugin.
-ENABLE = NO
-
-# This is the response we give out for the /wire request.  It provides
-# wallets with the bank information for transfers to the exchange.
-SEPA_RESPONSE_FILE = ${TALER_CONFIG_HOME}/exchange/wire/sepa.json
-
-[exchange-wire-outgoing-sepa]
-# This section should contain the options required for making outgoing
-# SEPA transfers. Not yet supported (need libebics).
diff --git a/src/wire/wire-test.conf b/src/wire/wire-test.conf
deleted file mode 100644
index 7ee217e..0000000
--- a/src/wire/wire-test.conf
+++ /dev/null
@@ -1,22 +0,0 @@
-# This file is in the public domain.
-#
-# Configuration for TEST wire plugin.
-#
-[exchange-wire-test]
-# Set to "YES" to activate the 'test' plugin.
-ENABLE = NO
-
-# This is the response we give out for the /wire request.  It provides
-# wallets with the bank information for transfers to the exchange.
-TEST_RESPONSE_FILE = ${TALER_CONFIG_HOME}/exchange/wire/test.json
-
-# We need to know the exchange's account number at the bank.
-EXCHANGE_ACCOUNT_NUMBER = 2
-
-# For accessing transfers, we need to know
-# the URL of the bank (where the /history API is available).
-# BANK_URL = https://bank.demo.taler.net/
-
-# Authentication information for basic authentication
-USERNAME = user
-PASSWORD = pass
diff --git a/src/wire/wire.c b/src/wire/wire.c
index c799334..aeb8689 100644
--- a/src/wire/wire.c
+++ b/src/wire/wire.c
@@ -1,6 +1,6 @@
 /*
   This file is part of TALER
-  (C) 2015, 2016, 2017 GNUnet e.V.
+  (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
@@ -23,6 +23,50 @@
 #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.
  *
@@ -36,7 +80,15 @@ TALER_WIRE_plugin_load (const struct 
GNUNET_CONFIGURATION_Handle *cfg,
 {
   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);
@@ -46,6 +98,15 @@ TALER_WIRE_plugin_load (const struct 
GNUNET_CONFIGURATION_Handle *cfg,
     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;
 }
 
@@ -58,10 +119,26 @@ TALER_WIRE_plugin_load (const struct 
GNUNET_CONFIGURATION_Handle *cfg,
 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));
@@ -69,80 +146,4 @@ TALER_WIRE_plugin_unload (struct TALER_WIRE_Plugin *plugin)
 }
 
 
-/**
- * Closure of #check_for_wire.
- */
-struct FindEnabledWireContext
-{
-  /**
-   * Configuration we are usign.
-   */
-  const struct GNUNET_CONFIGURATION_Handle *cfg;
-
-  /**
-   * Callback to invoke.
-   */
-  TALER_WIRE_EnabledCallback cb;
-
-  /**
-   * Closure for @e cb.
-   */
-  void *cb_cls;
-};
-
-
-/**
- * Check if @a section begins with "exchange-wire-", and if
- * so if the "ENABLE" option is set to "YES".  If both are
- * true, call the callback from the context with the
- * rest of the section name.
- *
- * @param cls our `struct FindEnabledWireContext`
- * @param section name of a section in the configuration
- */
-static void
-check_for_wire (void *cls,
-                const char *section)
-{
-  struct FindEnabledWireContext *ctx = cls;
-  const char *name;
-
-  if (0 != strncasecmp (section,
-                        "exchange-wire-",
-                        strlen ("exchange-wire-")))
-    return;
-  if (GNUNET_YES !=
-      GNUNET_CONFIGURATION_get_value_yesno (ctx->cfg,
-                                            section,
-                                            "ENABLE"))
-    return;
-  name = &section[strlen ("exchange-wire-")];
-  ctx->cb (ctx->cb_cls,
-           name);
-}
-
-
-/**
- * Check which wire plugins are enabled in @a cfg and call @a cb for each one.
- *
- * @param cfg configuration to use
- * @param cb callback to invoke
- * @param cb_cls closure for @a cb
- */
-void
-TALER_WIRE_find_enabled (const struct GNUNET_CONFIGURATION_Handle *cfg,
-                         TALER_WIRE_EnabledCallback cb,
-                         void *cb_cls)
-{
-  struct FindEnabledWireContext ctx;
-
-  ctx.cfg = cfg;
-  ctx.cb = cb;
-  ctx.cb_cls = cb_cls;
-  GNUNET_CONFIGURATION_iterate_sections (cfg,
-                                         &check_for_wire,
-                                         &ctx);
-}
-
-
 /* end of wire.c */
diff --git a/src/wire/wire_helper.c b/src/wire/wire_helper.c
new file mode 100644
index 0000000..34d40e1
--- /dev/null
+++ b/src/wire/wire_helper.c
@@ -0,0 +1,57 @@
+/*
+  This file is part of TALER
+  (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 wire/wire_helper.c
+ * @brief Helper functions for dealing with wire formats
+ * @author Christian Grothoff <address@hidden>
+ */
+#include "platform.h"
+#include "taler_util.h"
+#include "taler_wire_lib.h"
+
+/**
+ * Prefix of PAYTO URLs.
+ */
+#define PAYTO "payto://"
+
+
+/**
+ * Obtain the payment method from a @a payto_url
+ *
+ * @param payto_url the URL to parse
+ * @return NULL on error (malformed @a payto_url)
+ */
+char *
+TALER_WIRE_payto_get_method (const char *payto_url)
+{
+  const char *start;
+  const char *end;
+
+  if (0 != strncmp (payto_url,
+                    PAYTO,
+                    strlen (PAYTO)))
+    return NULL;
+  start = &payto_url[strlen(PAYTO)];
+  end = strchr (start,
+                (unsigned char) '/');
+  if (NULL == end)
+    return NULL;
+  return GNUNET_strndup (start,
+                         end - start);
+}
+
+/* end of wire_helper.c */

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



reply via email to

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