gnunet-svn
[Top][All Lists]
Advanced

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

[GNUnet-SVN] [taler-merchant] branch stable updated (98e6bb9 -> 73d9a89)


From: gnunet
Subject: [GNUnet-SVN] [taler-merchant] branch stable updated (98e6bb9 -> 73d9a89)
Date: Fri, 10 Mar 2017 16:17:34 +0100

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

dold pushed a change to branch stable
in repository merchant.

    from 98e6bb9  Remove garbage
     add 15defda  disable MHD deprecation warnings as we want to be compatible 
to older releases that simply have not the new symbols (fixing #4845)
     add 99925fb  Docker deployment instructions
     add 0cb3424  Fix compilation: #4869
     add 832838e  contract->proposal
     add ccb8c16  First steps in renaming
     add 6d97959  Renaming proposal data db operations
     add 7097ceb  Removing obsolete /map requests and renaming 
contract->proposal/order, within lib.
     add 36d68f9  First run about renaming in lib's testcase.
     add d9a1d78  renaming: proposal logic ported
     add 75bca5f  Removing h_contract from /pay handler.
     add e05bb67  Removing _map.c from repo
     add dc5b4f7  Garbage removal
     add 6ec3850  Typo
     add 5b9a806  Renaming the DB and /history.
     add f226b8f  Updating notes.
     add dfdaec2  Fix backenddb tests after renaming
     add 3051f7f  Renaming /track/transaction handler to the point where it 
depends on a few exchange-lib's renamings.
     add 7216095  renaming (a little part of) /track/transfer handler
     add 17e344a  Renaming in /track/transaction handler.
     add 1dc680a  Huge renaming about removing transaction_id use
     add 5bc8e40  More fixes on renaming, mostly in db.
     add 9e8f9c9  Fix backenddb
     add 60c5ee7  Fixing testcases according to the renaming occurred in the 
protocol.  Please note, comments do NOT match code, /proposal uses the POST 
method, and tracking API are NOT tested yet.
     add bdbe390  Triggering buildbot.
     add 3e4ae93  Fix track API tests.
     add c892b80  Adding a second call to /track/transaction in testcases.
     add dfdca4e  Back out early if we can't connect to postgres db
     add 5b1d9c5  whitespace
     add 053798e  Change '/pay' API according to #4891
     add 6338642  fix reference counting issue
     add c078ae5  add order_id if missing, break up function for readability
     add bf7fe73  add timestamp if missing
     add 88f323a  round time before converting to JSON, otherwise GNUnet lib 
crashes
     add f6aca4d  set refund deadline if not in frontend offer
     add 8476ecf  set pay deadline if not in frontent order
     add bdad018  prettier automatic order_id
     add 30467b1  no newline
     add d60d537  fix #4893
     add 405b696  Testing replayed payment.
     add 01466e6  Merge branch 'master' of taler.net:merchant
     add 8096da9  Triggering Buildbot.
     add fff2f0e  Fix json formatting.
     add 194c978  Modify /history API and DB table for order_id-proposal_data 
mapping.  Adapting testcase and lib for that.
     add 17b7c5b  comments
     add 2fafeda  Checking the number of history entries are as expected.
     add 5e47723  Minimizing data returned by /history, for debugging purposes.
     add 5b8db59  json_pack'ing data returned by /history.
     add 70fb2c9  Fix #4925.
     add b494f35  Handle unknown instance when serving /history.
     add acb8cb3  Make /history's arguments optional.
     add 3d02146  Start and delta arguments for /history.
     add f67f913  Comments.
     add 822cef4  Adding conditions to add rows in result, based in their index.
     add a113934  Fix index/delta comparison.
     add 75609cb  /history elements are returned with ORDER BY.
     add 2632993  /history returns latest records first.
     add e94d256  DB provides lookup of proposal data based on proposal data's 
hashcode too.
     add c394750  Including instance within history elements.
     add 4f202bd  json_copy() data returned from DB.  Data gets "freed" by DB 
routine and is not longer available without json_copy-ing it.
     add 71c1773  Fix build failure due to #4921.
     add 7e1981f  changing wire plugin specification from [exchange]WIREFORMAT 
to [exchange-wire-PLUGIN]enable=YES/NO
     add b4387ea  fix compiler warnings, fix memory leak, properly format date 
in log message
     add 2c87637  add missing fee options in test configuration
     add c9650e7  update .gitignore
     add ccd931a  fix reference counting bug
     add 341bb90  use %u, these values are unsigned
     add 50bdee0  implementing #4929 (adjusting to exchange API changes)
     add 467b2f8  fix memory leaks (struct MerchantInstance not cleaned up 
properly)
     add b613bac  fix misc memory leaks
     add 8b102ee  adjust test to consider new wire transfer fee
     add 2b78ff4  ignore wirefees dir
     add 09b01a1  towards implementing #4935: make sure all of the fee data is 
available for the /pay handler (but not yet checked)
     add bbdd987  implement #4752
     add 690b9c9  avoid memory leak on DB connect error
     add 8cbdf68  check if field is present before going for full spec-parser
     add 9a6e0ae  describe meaning of return values in comments, use corret 
return values
     add d3e568e  notes on #4939, verify that H_wire from contract matches 
instance's H_wire early on
     add a4f578b  implement #4935 (wire fee support)
     add a5f4a65  Merge branch 'master' of taler.net:merchant
     add 09c090c  Remove confusing comment.
     add 60dc48f  Returning total sum of wire transferred coins instead of an 
array about each of them.  Adjusting lib accordingly.
     add 01bba44  Debug prints.
     add bb0d468  Stub for automatically generating payments.
     add d5b6f87  Renaming to generate_payments.c.
     add 2f21b91  Advancing with configuration for the payments generator.
     add 1278090  Link to built shared libraries using relative path from 
$(top_srcdir).
     add eb2726f  Add key and 'test' wire details for payments generator.
     add c62753b  Up to the point where payments generator launches exchange 
and merchant.
     add f1a7cd4  Adding commands skeletons in the payments generator.
     add 4422d5d  Starting commands' interpreter for payments generator.
     add 8d8a83b  Killing services when shutting down payments generator.
     add 72900a8  Payments generator creates reserves.
     add 3fd4633  Implementing withdraw and proposal submission in the payments 
generator.
     add 894c5b1  Implementing payments in payments generator.
     add 2ff1d26  Payments generator does three payments.
     add a3ceef4  Beginning #4945..
     add 2af86bf  Undoing last commit.
     add 5a0697a  Adding options to take exchange, merchant backend, and bank 
URIs to the payments generator.
     add bc27109  Making arguments mandatory.
     add 5156e20  Minor fixes to payments generator.
     add dc97b12  Fix segfault in payments generator.
     add 73d9a89  Restoring the macro-based way of passing values to payments 
generator.

No new revisions were added by this update.

Summary of changes:
 .gitignore                                         |    3 +
 ChangeLog                                          |    9 +
 RENAMING_NOTES.txt                                 |    7 +
 configure.ac                                       |    1 +
 doc/manual.texi                                    |   61 +-
 doc/version.texi                                   |    4 +-
 src/Makefile.am                                    |    2 +-
 src/backend/Makefile.am                            |    5 +-
 src/backend/merchant.conf                          |   23 +-
 src/backend/taler-merchant-httpd.c                 |  287 +++-
 src/backend/taler-merchant-httpd.h                 |   25 +-
 src/backend/taler-merchant-httpd_contract.c        |  287 ----
 src/backend/taler-merchant-httpd_contract.h        |   43 -
 src/backend/taler-merchant-httpd_exchanges.c       |  428 +++++-
 src/backend/taler-merchant-httpd_exchanges.h       |    4 +
 src/backend/taler-merchant-httpd_history.c         |  178 ++-
 src/backend/taler-merchant-httpd_history.h         |    2 +-
 src/backend/taler-merchant-httpd_map.c             |  241 ----
 src/backend/taler-merchant-httpd_map.h             |    2 +-
 src/backend/taler-merchant-httpd_pay.c             |  821 +++++++----
 src/backend/taler-merchant-httpd_proposal.c        |  451 ++++++
 ...httpd_map.h => taler-merchant-httpd_proposal.h} |   48 +-
 src/backend/taler-merchant-httpd_responses.c       |   18 +-
 .../taler-merchant-httpd_track-transaction.c       |  109 +-
 src/backend/taler-merchant-httpd_track-transfer.c  |   27 +-
 src/backenddb/Makefile.am                          |    2 +
 src/backenddb/plugin_merchantdb_postgres.c         |  385 +++--
 src/backenddb/test_merchantdb.c                    |  133 +-
 src/include/platform.h                             |    4 +
 src/include/taler_merchant_service.h               |  171 ++-
 src/include/taler_merchantdb_plugin.h              |  116 +-
 src/lib/Makefile.am                                |    5 +-
 src/lib/merchant_api_contract.c                    |  239 ----
 src/lib/merchant_api_history.c                     |   15 +-
 src/lib/merchant_api_map.c                         |  230 ---
 src/lib/merchant_api_pay.c                         |  167 +--
 src/lib/merchant_api_proposal.c                    |  366 +++++
 src/lib/merchant_api_track_transaction.c           |   81 +-
 src/lib/merchant_api_track_transfer.c              |    3 +-
 src/lib/test_merchant_api.c                        |  581 ++++----
 src/lib/test_merchant_api.conf                     |   28 +-
 src/samples/Makefile.am                            |   21 +
 src/samples/README                                 |    3 +
 src/samples/generate_payments.c                    | 1484 ++++++++++++++++++++
 .../.config/taler/merchant/wire/test.json          |    0
 .../generate_payments_home/.config/taler/test.json |    6 +
 .../.config/taler/test.signed.json                 |    8 +
 .../share/taler/exchange/offline-keys/master.priv  |    1 +
 src/samples/merchant_generate_payments.conf        |  132 ++
 src/{lib => samples}/test_merchant.priv            |    0
 src/tests/Makefile.am                              |   25 -
 src/tests/deposit_permission.sample                |   31 -
 src/tests/deposit_permission_backend.sample        |   36 -
 src/tests/deposit_permission_edate_backend.sample  |   37 -
 src/tests/merchant.priv                            |    1 -
 src/tests/test_contract.c                          |  341 -----
 src/tests/test_contract_README                     |   10 -
 src/tests/test_pay_README                          |   26 -
 58 files changed, 4776 insertions(+), 2998 deletions(-)
 create mode 100644 RENAMING_NOTES.txt
 delete mode 100644 src/backend/taler-merchant-httpd_contract.c
 delete mode 100644 src/backend/taler-merchant-httpd_contract.h
 delete mode 100644 src/backend/taler-merchant-httpd_map.c
 create mode 100644 src/backend/taler-merchant-httpd_proposal.c
 copy src/backend/{taler-merchant-httpd_map.h => 
taler-merchant-httpd_proposal.h} (51%)
 delete mode 100644 src/lib/merchant_api_contract.c
 delete mode 100644 src/lib/merchant_api_map.c
 create mode 100644 src/lib/merchant_api_proposal.c
 create mode 100644 src/samples/Makefile.am
 create mode 100644 src/samples/README
 create mode 100644 src/samples/generate_payments.c
 copy src/{lib/test_merchant_api_home => 
samples/generate_payments_home}/.config/taler/merchant/wire/test.json (100%)
 create mode 100644 src/samples/generate_payments_home/.config/taler/test.json
 create mode 100644 
src/samples/generate_payments_home/.config/taler/test.signed.json
 create mode 100644 
src/samples/generate_payments_home/.local/share/taler/exchange/offline-keys/master.priv
 create mode 100644 src/samples/merchant_generate_payments.conf
 copy src/{lib => samples}/test_merchant.priv (100%)
 delete mode 100644 src/tests/Makefile.am
 delete mode 100644 src/tests/deposit_permission.sample
 delete mode 100644 src/tests/deposit_permission_backend.sample
 delete mode 100644 src/tests/deposit_permission_edate_backend.sample
 delete mode 100644 src/tests/merchant.priv
 delete mode 100644 src/tests/test_contract.c
 delete mode 100644 src/tests/test_contract_README
 delete mode 100644 src/tests/test_pay_README

diff --git a/.gitignore b/.gitignore
index 2ba255e..6982c64 100644
--- a/.gitignore
+++ b/.gitignore
@@ -26,8 +26,10 @@ GRTAGS
 GTAGS
 *.swp
 src/backend/taler-merchant-httpd
+src/merchant-tools/taler-merchant-dbinit
 src/lib/test_merchant_api
 src/lib/test_merchant_api_home/.local/share/taler/exchange/live-keys/
+src/lib/test_merchant_api_home/.local/share/taler/wirefees/
 taler_merchant_config.h
 taler_merchant_config.h.in
 doc/*
@@ -35,3 +37,4 @@ doc/*
 !doc/*.am
 !doc/*.sh
 !doc/examples/
+src/lib/test_merchant_api_home/.local/share/taler/exchange/wirefees/
diff --git a/ChangeLog b/ChangeLog
index ed946cc..8ff267c 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,12 @@
+Mon Mar  6 17:57:51 CET 2017
+       Add support for wire fee calculations to /pay handling (#4935),
+       and adding setting "max_wire_fee" and "wire_fee_amortization"
+       in contract from defaults. -CG
+
+Mon Mar  6 00:59:25 CET 2017
+       Implement BIND_TO option to allow binding backend to a particular
+       IP address (#4752).  Enabling use of dual-stack by default. -CG
+
 Thu Dec 15 10:37:08 CET 2016
         Implementing:
         - /map/in, /map/out API, to allow frontends to store
diff --git a/RENAMING_NOTES.txt b/RENAMING_NOTES.txt
new file mode 100644
index 0000000..50697ef
--- /dev/null
+++ b/RENAMING_NOTES.txt
@@ -0,0 +1,7 @@
+Files to be cleaned from the 'h/H_contract' presence.
+
+- merchant service include
+- pay lib
+- track-lib: references to H_contract to be removed.
+  especially when the logic reads JSON responses.
+- lib testcase
diff --git a/configure.ac b/configure.ac
index 9923862..e728793 100644
--- a/configure.ac
+++ b/configure.ac
@@ -280,5 +280,6 @@ src/merchant-tools/Makefile
 src/include/Makefile
 src/backenddb/Makefile
 src/backend/Makefile
+src/samples/Makefile
 src/lib/Makefile])
 AC_OUTPUT
diff --git a/doc/manual.texi b/doc/manual.texi
index 3fe6c89..af2dc37 100644
--- a/doc/manual.texi
+++ b/doc/manual.texi
@@ -175,7 +175,7 @@ account information is encapsulated within the Taler 
backend.
 * generic-instructions:: Generic installation guidelines
 * Installing Taler on Debian GNU/Linux:: Installing Taler on Debian GNU/Linux
 @c * Installing Taler with GNU Guix:: Installing Taler with GNU Guix
address@hidden * Installing Taler using Docker:: Installing Taler using Docker
+* Installing Taler using Docker:: Installing Taler using Docker
 @c * Installing Taler on Arch Linux:: Installing Taler on Arch Linux
 @c * Installing Taler on Windows:: Installing Taler on Windows
 @c * Installing Taler on OS X:: Installing Taler on OS X
@@ -185,6 +185,61 @@ account information is encapsulated within the Taler 
backend.
 
 This chapter describes how to install the GNU Taler merchant backend.
 
address@hidden Installing Taler using Docker
address@hidden Installing Taler using Docker
+
+This section provides instructions for the merchant backend
+installation using `Docker`.
+
+For security reasons, we run Docker against a VirtualBox instance,
+so the @code{docker} command should connect to a @code{docker-machine}
+instance that uses the VirtualBox driver.
+
+Therefore, the needed tools are: ``docker``, ``docker-machine``, and
+``docker-compose``.  Please refer to Docker's official
address@hidden://docs.docker.com/}documentation in order
+to get those components installed, as that is not in this manual's scope.
+
+Before starting to build the merchant's image, make sure a
+``docker-machine`` instance is up and running.
+
+Because all of the Docker source file are kept in our ``deployment``
+repository, we start by checking out the
address@hidden://taler.net/deployment} codebase:
+
address@hidden
+$ git clone git://taler.net/deployment
address@hidden smallexample
+
+Now we actually build the merchant's image.  From the same
+directory as above:
+
address@hidden
+$ cd deployment/docker/merchant/
+$ docker-compose build
address@hidden smallexample
+
+If everything worked as expected, the merchant is ready to be
+launched.  From the same directory as the previous step:
+
address@hidden
+# Recall: the docker-machine should be up and running.
+$ docker-compose up
address@hidden smallexample
+
+You should see some live logging from all the involved containers.
+At this stage of development, you should also ignore some (harmless)
+error message from postresql about already existing roles and databases.
+
+To test if everything worked as expected, it suffices to issue a
+simple request to the merchant, as:
+
address@hidden
+$ curl http://$(docker-machine ip)/
+# A greeting message should be returned by the merchant.
address@hidden smallexample
+
+
 @node generic-instructions
 @section Generic instructions
 
@@ -452,14 +507,14 @@ Which currency the Web shop deals in, i.e. ``EUR'' or 
``USD'', is specified usin
 @cindex currency
 @cindex KUDOS
 @example
-[merchant]/currency
+[taler]/currency
 @end example
 
 For testing purposes, the currency MUST match ``KUDOS'' so that tests will work
 with the Taler demonstration exchange at 
@url{https://exchange.demo.taler.net/}:
 
 @example
-$ taler-config -s merchant -o currency -V KUDOS
+$ taler-config -s taler -o currency -V KUDOS
 @end example
 
 @item Database
diff --git a/doc/version.texi b/doc/version.texi
index 3e3136f..0b47203 100644
--- a/doc/version.texi
+++ b/doc/version.texi
@@ -1,4 +1,4 @@
address@hidden UPDATED 18 November 2016
address@hidden UPDATED-MONTH November 2016
address@hidden UPDATED 27 January 2017
address@hidden UPDATED-MONTH January 2017
 @set EDITION 0.2.0
 @set VERSION 0.2.0
diff --git a/src/Makefile.am b/src/Makefile.am
index e58cf01..16521e0 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -1,3 +1,3 @@
 # This Makefile is in the public domain
 AM_CPPFLAGS = -I$(top_srcdir)/src/include
-SUBDIRS = include backenddb backend lib merchant-tools
+SUBDIRS = include backenddb backend lib merchant-tools samples
diff --git a/src/backend/Makefile.am b/src/backend/Makefile.am
index f7fc4c8..c635ef0 100644
--- a/src/backend/Makefile.am
+++ b/src/backend/Makefile.am
@@ -19,12 +19,11 @@ taler_merchant_httpd_SOURCES = \
   taler-merchant-httpd_mhd.c taler-merchant-httpd_mhd.h \
   taler-merchant-httpd_auditors.c taler-merchant-httpd_auditors.h \
   taler-merchant-httpd_exchanges.c taler-merchant-httpd_exchanges.h \
-  taler-merchant-httpd_contract.c taler-merchant-httpd_contract.h \
+  taler-merchant-httpd_proposal.c taler-merchant-httpd_proposal.h \
   taler-merchant-httpd_pay.c taler-merchant-httpd_pay.h \
   taler-merchant-httpd_history.c taler-merchant-httpd_history.h \
   taler-merchant-httpd_track-transaction.c 
taler-merchant-httpd_track-transaction.h \
-  taler-merchant-httpd_track-transfer.c taler-merchant-httpd_track-transfer.h \
-  taler-merchant-httpd_map.c taler-merchant-httpd_map.h
+  taler-merchant-httpd_track-transfer.c taler-merchant-httpd_track-transfer.h
 
 
 taler_merchant_httpd_LDADD = \
diff --git a/src/backend/merchant.conf b/src/backend/merchant.conf
index 49849bc..5511787 100644
--- a/src/backend/merchant.conf
+++ b/src/backend/merchant.conf
@@ -5,14 +5,35 @@
 
 # General settings for the backend.
 [merchant]
+
+# Use TCP or UNIX domain sockets?
 SERVE = tcp
 
-# Which HTTP port does the backend listen on?
+# Which HTTP port does the backend listen on?  Only used if "SERVE" is 'tcp'.
 PORT = 9966
 
+# Which IP address should we bind to? i.e. 127.0.0.1 or ::1 for loopback.
+# Can also be given as a hostname.  We will bind to the wildcard (dual-stack)
+# if left empty.  Only used if "SERVE" is 'tcp'.
+# BIND_TO =
+
+
+# Which unix domain path should we bind to? Only used if "SERVE" is 'unix'.
 UNIXPATH = ${TALER_RUNTIME_DIR}/merchant.http
+# What should be the file access permissions (see chmod) for "UNIXPATH"?
 UNIXPATH_MODE = 660
 
+
+# Maximum wire fee to permit by default.  You most certainly want to
+# adjust at least the currency.
+# DEFAULT_MAX_WIRE_FEE = "KUDOS:0.10"
+
+# Which fraction of an exessivly high wire fee is the customer expected
+# to cover?  Must be a positive integer representing the expected
+# average number of transactions aggregated by exchanges.  1 is
+# always safe (financially speaking).
+DEFAULT_WIRE_FEE_AMORTIZATION = 1
+
 # Where does the backend store the merchant's private key?
 KEYFILE = ${TALER_DATA_HOME}/merchant/merchant.priv
 
diff --git a/src/backend/taler-merchant-httpd.c 
b/src/backend/taler-merchant-httpd.c
index 95ac4b3..f3faa30 100644
--- a/src/backend/taler-merchant-httpd.c
+++ b/src/backend/taler-merchant-httpd.c
@@ -1,6 +1,6 @@
 /*
   This file is part of TALER
-  (C) 2014, 2015, 2016 INRIA
+  (C) 2014-2017 INRIA
 
   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
@@ -35,7 +35,7 @@
 #include "taler-merchant-httpd_mhd.h"
 #include "taler-merchant-httpd_auditors.h"
 #include "taler-merchant-httpd_exchanges.h"
-#include "taler-merchant-httpd_contract.h"
+#include "taler-merchant-httpd_proposal.h"
 #include "taler-merchant-httpd_pay.h"
 #include "taler-merchant-httpd_track-transaction.h"
 #include "taler-merchant-httpd_track-transfer.h"
@@ -73,6 +73,17 @@ static long long unsigned port;
 struct GNUNET_TIME_Relative wire_transfer_delay;
 
 /**
+ * Default maximum wire fee to assume, unless stated differently in the 
proposal
+ * already.
+ */
+struct TALER_Amount default_max_wire_fee;
+
+/**
+ * Default factor for wire fee amortization.
+ */
+unsigned long long default_wire_fee_amortization;
+
+/**
  * Should a "Connection: close" header be added to each HTTP response?
  */
 int TMH_merchant_connection_close;
@@ -164,13 +175,9 @@ url_handler (void *cls,
       { "/", MHD_HTTP_METHOD_GET, "text/plain",
         "Hello, I'm a merchant's Taler backend. This HTTP server is not for 
humans.\n", 0,
         &TMH_MHD_handler_static_response, MHD_HTTP_OK },
-      { "/contract", MHD_HTTP_METHOD_POST, "application/json",
+      { "/proposal", MHD_HTTP_METHOD_POST, "application/json",
         NULL, 0,
-        &MH_handler_contract, MHD_HTTP_OK },
-      { "/contract", NULL, "text/plain",
-        "Only POST is allowed", 0,
-        &TMH_MHD_handler_send_json_pack_error, MHD_HTTP_METHOD_NOT_ALLOWED },
-
+        &MH_handler_proposal_put, MHD_HTTP_OK },
       { "/pay", MHD_HTTP_METHOD_POST, "application/json",
         NULL, 0,
         &MH_handler_pay, MHD_HTTP_OK },
@@ -192,12 +199,13 @@ url_handler (void *cls,
       { "/history", MHD_HTTP_METHOD_GET, "text/plain",
         "Only GET is allowed", 0,
         &MH_handler_history, MHD_HTTP_OK},
-      { "/map/in", MHD_HTTP_METHOD_POST, NULL,
-        "Only POST is allowed", 0,
-        &MH_handler_map_in, MHD_HTTP_OK},
-      { "/map/out", MHD_HTTP_METHOD_GET, "text/plain",
+      { "/proposal", MHD_HTTP_METHOD_GET, "text/plain",
         "Only GET is allowed", 0,
-        &MH_handler_map_out, MHD_HTTP_OK},
+        &MH_handler_proposal_lookup, MHD_HTTP_OK},
+      { "/proposal", NULL, "text/plain",
+        "Only GET/POST are allowed", 0,
+        &TMH_MHD_handler_send_json_pack_error, MHD_HTTP_METHOD_NOT_ALLOWED },
+
       {NULL, NULL, NULL, NULL, 0, 0 }
     };
   static struct TMH_RequestHandler h404 =
@@ -245,19 +253,25 @@ url_handler (void *cls,
 /**
  * Callback that frees all the elements in the hashmap
  *
- * @param cls closure
+ * @param cls closure, NULL
  * @param key current key
- * @param value current value
+ * @param value a `struct MerchantInstance`
  */
-int
+static int
 hashmap_free (void *cls,
               const struct GNUNET_HashCode *key,
               void *value)
 {
-  GNUNET_free (value);
+  struct MerchantInstance *mi = value;
+
+  json_decref (mi->j_wire);
+  GNUNET_free (mi->id);
+  GNUNET_free (mi->keyfile);
+  GNUNET_free (mi);
   return GNUNET_YES;
 }
 
+
 /**
  * Shutdown task (magically invoked when the application is being
  * quit)
@@ -272,6 +286,10 @@ do_shutdown (void *cls)
     GNUNET_SCHEDULER_cancel (mhd_task);
     mhd_task = NULL;
   }
+  /* FIXME: MHD API requires us to resume all suspended
+     connections before we do this, but /pay currently
+     suspends connections without giving us a way to
+     enumerate / resume them... */
   if (NULL != mhd)
   {
     MHD_stop_daemon (mhd);
@@ -289,9 +307,15 @@ do_shutdown (void *cls)
                                          &hashmap_free,
                                          NULL);
   if (NULL != by_id_map)
+  {
     GNUNET_CONTAINER_multihashmap_destroy (by_id_map);
+    by_id_map = NULL;
+  }
   if (NULL != by_kpub_map)
+  {
     GNUNET_CONTAINER_multihashmap_destroy (by_kpub_map);
+    by_kpub_map = NULL;
+  }
 }
 
 
@@ -437,13 +461,15 @@ instances_iterator_cb (void *cls,
   /* used as hashmap keys */
   struct GNUNET_HashCode h_pk;
   struct GNUNET_HashCode h_id;
+  json_t *type;
   char *emsg;
 
   iic = cls;
   substr = strstr (section, "merchant-instance-");
 
-  if ((NULL == substr)
-      || (NULL != strstr (section, "merchant-instance-wireformat-")))
+  if ( (NULL == substr) ||
+       (NULL != strstr (section,
+                        "merchant-instance-wireformat-")) )
     return;
 
   if (substr != section)
@@ -470,6 +496,7 @@ instances_iterator_cb (void *cls,
     GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
                                section,
                                "KEYFILE");
+    GNUNET_free (mi);
     GNUNET_SCHEDULER_shutdown ();
     return;
   }
@@ -482,6 +509,8 @@ instances_iterator_cb (void *cls,
        (pk = GNUNET_CRYPTO_eddsa_key_create_from_file (mi->keyfile)))
   {
     GNUNET_break (0);
+    GNUNET_free (mi->keyfile);
+    GNUNET_free (mi);
     GNUNET_SCHEDULER_shutdown ();
     return;
   }
@@ -490,11 +519,6 @@ instances_iterator_cb (void *cls,
                                       &mi->pubkey.eddsa_pub);
   GNUNET_free (pk);
 
-  /**
-   * FIXME: 'token' must NOT be freed, as it is handled by the
-   * gnunet_configuration facility. OTOH mi->id does need to be freed,
-   * because it is a duplicate.
-   */
   mi->id = GNUNET_strdup (token + 1);
   if (0 == strcmp ("default", mi->id))
     iic->default_instance = GNUNET_YES;
@@ -502,11 +526,19 @@ instances_iterator_cb (void *cls,
   GNUNET_asprintf (&instance_wiresection,
                    "merchant-instance-wireformat-%s",
                    mi->id);
-
   mi->j_wire = iic->plugin->get_wire_details (iic->plugin->cls,
-                                             iic->config,
-                                             instance_wiresection);
+                                              iic->config,
+                                              instance_wiresection);
   GNUNET_free (instance_wiresection);
+  if ( (NULL == (type = json_object_get (mi->j_wire,
+                                         "type"))) ||
+       (! json_is_string (type)) )
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                "Malformed wireformat: lacks type\n");
+    iic->ret |= GNUNET_SYSERR;
+  }
+  mi->wire_method = json_string_value (type);
 
   if (TALER_EC_NONE !=
       iic->plugin->wire_validate (iic->plugin->cls,
@@ -514,7 +546,6 @@ instances_iterator_cb (void *cls,
                                   NULL,
                                   &emsg))
   {
-
     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
                 "Malformed wireformat: %s\n",
                 emsg);
@@ -538,7 +569,7 @@ instances_iterator_cb (void *cls,
   #endif
 
   GNUNET_CRYPTO_hash (mi->id,
-                      strlen(mi->id),
+                      strlen (mi->id),
                       &h_id);
   GNUNET_CRYPTO_hash (&mi->pubkey.eddsa_pub,
                       sizeof (struct GNUNET_CRYPTO_EddsaPublicKey),
@@ -553,18 +584,6 @@ instances_iterator_cb (void *cls,
                 "Failed to put an entry into the 'by_id' hashmap\n");
     iic->ret |= GNUNET_SYSERR;
   }
-  #ifdef EXTRADEBUG
-  else {
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "Added element at %p, by by-id key %s of '%s' in hashmap\n",
-                mi,
-                GNUNET_h2s (&h_id),
-                mi->id);
-    GNUNET_assert (NULL != GNUNET_CONTAINER_multihashmap_get (by_id_map,
-                                                              &h_id));
-  }
-  #endif
-
   if (GNUNET_OK !=
       GNUNET_CONTAINER_multihashmap_put (by_kpub_map,
                                          &h_pk,
@@ -636,8 +655,8 @@ get_instance (struct json_t *json)
  *
  * @param config configuration handle
  * @param allowed which wire format is allowed/expected?
- * @return GNUNET_OK if successful, GNUNET_SYSERR upon errors
- * (for example, if no "defaul" instance is defined)
+ * @return #GNUNET_OK if successful, #GNUNET_SYSERR upon errors
+ * (for example, if no "default" instance is defined)
  */
 static unsigned int
 iterate_instances (const struct GNUNET_CONFIGURATION_Handle *config,
@@ -691,7 +710,8 @@ iterate_instances (const struct GNUNET_CONFIGURATION_Handle 
*config,
   GNUNET_free (iic);
   return GNUNET_OK;
 
-  fail: do {
+ fail:
+  do {
     GNUNET_PLUGIN_unload (lib_name,
                           iic->plugin);
     GNUNET_free (lib_name);
@@ -720,13 +740,12 @@ run (void *cls,
   char *wireformat;
   int fh;
 
-  wireformat = NULL;
   result = GNUNET_SYSERR;
   GNUNET_SCHEDULER_add_shutdown (&do_shutdown,
                                  NULL);
   GNUNET_assert (GNUNET_OK ==
                  GNUNET_log_setup ("taler-merchant-httpd",
-                                   "INFO",
+                                   "DEBUG",
                                    NULL));
   if (GNUNET_SYSERR ==
       TMH_EXCHANGES_init (config))
@@ -767,6 +786,56 @@ run (void *cls,
     GNUNET_SCHEDULER_shutdown ();
     return;
   }
+
+  if (GNUNET_OK !=
+      TALER_config_get_denom (config,
+                              "merchant",
+                              "DEFAULT_MAX_WIRE_FEE",
+                              &default_max_wire_fee))
+  {
+    char *currency;
+
+    if (GNUNET_OK !=
+        GNUNET_CONFIGURATION_get_value_string (config,
+                                               "taler",
+                                               "CURRENCY",
+                                               &currency))
+    {
+      GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
+                                 "taler",
+                                 "CURRENCY");
+      GNUNET_SCHEDULER_shutdown ();
+      return;
+    }
+    if (GNUNET_OK !=
+        TALER_amount_get_zero (currency,
+                               &default_max_wire_fee))
+    {
+      GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR,
+                                 "taler",
+                                 "CURRENCY",
+                                 "Specified value not legal for a Taler 
currency");
+      GNUNET_SCHEDULER_shutdown ();
+      GNUNET_free (currency);
+      return;
+    }
+    GNUNET_free (currency);
+  }
+
+  if (GNUNET_OK !=
+      GNUNET_CONFIGURATION_get_value_number (config,
+                                             "merchant",
+                                             "DEFAULT_WIRE_FEE_AMORTIZATION",
+                                             &default_wire_fee_amortization))
+  {
+    GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
+                               "merchant",
+                               "DEFAULT_WIRE_FEE_AMORTIZATION");
+    GNUNET_SCHEDULER_shutdown ();
+    return;
+  }
+
+  wireformat = NULL;
   if (GNUNET_OK !=
       GNUNET_CONFIGURATION_get_value_string (config,
                                              "merchant",
@@ -779,10 +848,10 @@ run (void *cls,
     GNUNET_SCHEDULER_shutdown ();
     return;
   }
-
-  iterate_instances (config, wireformat);
-
+  iterate_instances (config,
+                     wireformat);
   GNUNET_free (wireformat);
+
   if (NULL ==
       (db = TALER_MERCHANTDB_plugin_load (config)))
   {
@@ -885,41 +954,57 @@ run (void *cls,
 
       un = GNUNET_new (struct sockaddr_un);
       un->sun_family = AF_UNIX;
-      strncpy (un->sun_path, serve_unixpath, sizeof (un->sun_path) - 1);
+      strncpy (un->sun_path,
+               serve_unixpath,
+               sizeof (un->sun_path) - 1);
 
       GNUNET_NETWORK_unix_precheck (un);
 
-      if (NULL == (nh = GNUNET_NETWORK_socket_create (AF_UNIX, SOCK_STREAM, 
0)))
+      if (NULL == (nh = GNUNET_NETWORK_socket_create (AF_UNIX,
+                                                      SOCK_STREAM,
+                                                      0)))
       {
-        GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "create(for AF_UNIX)");
+        GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR,
+                             "socket(AF_UNIX)");
         GNUNET_SCHEDULER_shutdown ();
         return;
       }
-      if (GNUNET_OK != GNUNET_NETWORK_socket_bind (nh, (void *) un, sizeof 
(struct sockaddr_un)))
+      if (GNUNET_OK !=
+          GNUNET_NETWORK_socket_bind (nh,
+                                      (void *) un,
+                                      sizeof (struct sockaddr_un)))
       {
-        GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "bind(for AF_UNIX)");
+        GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR,
+                             "bind(AF_UNIX)");
         GNUNET_SCHEDULER_shutdown ();
         return;
       }
-      if (GNUNET_OK != GNUNET_NETWORK_socket_listen (nh, UNIX_BACKLOG))
+      if (GNUNET_OK !=
+          GNUNET_NETWORK_socket_listen (nh,
+                                        UNIX_BACKLOG))
       {
-        GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "listen(for AF_UNIX)");
+        GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR,
+                             "listen(AF_UNIX)");
         GNUNET_SCHEDULER_shutdown ();
         return;
       }
 
       fh = GNUNET_NETWORK_get_fd (nh);
-      if (0 != chmod (serve_unixpath, unixpath_mode))
+      GNUNET_NETWORK_socket_free_memory_only_ (nh);
+      if (0 != chmod (serve_unixpath,
+                      unixpath_mode))
       {
-        fprintf (stderr, "chmod failed: %s\n", strerror (errno));
+        GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR,
+                             "chmod");
         GNUNET_SCHEDULER_shutdown ();
         return;
       }
-      GNUNET_NETWORK_socket_free_memory_only_ (nh);
       port = 0;
     }
     else if (0 == strcmp (serve_type, "tcp"))
     {
+      char *bind_to;
+
       if (GNUNET_SYSERR ==
           GNUNET_CONFIGURATION_get_value_number (config,
                                                  "merchant",
@@ -932,7 +1017,81 @@ run (void *cls,
         GNUNET_SCHEDULER_shutdown ();
         return;
       }
-      fh = -1;
+      if (GNUNET_OK ==
+          GNUNET_CONFIGURATION_get_value_string (config,
+                                                 "merchant",
+                                                 "BIND_TO",
+                                                 &bind_to))
+      {
+        char port_str[6];
+        struct addrinfo hints;
+        struct addrinfo *res;
+        int ec;
+        struct GNUNET_NETWORK_Handle *nh;
+
+        GNUNET_snprintf (port_str,
+                         sizeof (port_str),
+                         "%u",
+                         (uint16_t) port);
+        memset (&hints, 0, sizeof (hints));
+        hints.ai_family = AF_UNSPEC;
+        hints.ai_socktype = SOCK_STREAM;
+        hints.ai_protocol = IPPROTO_TCP;
+        hints.ai_flags = AI_PASSIVE | AI_IDN;
+        if (0 !=
+            (ec = getaddrinfo (bind_to,
+                               port_str,
+                               &hints,
+                               &res)))
+        {
+          GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                      "Failed to resolve BIND_TO address `%s': %s\n",
+                      bind_to,
+                      gai_strerror (ec));
+          GNUNET_free (bind_to);
+          GNUNET_SCHEDULER_shutdown ();
+          return;
+        }
+        GNUNET_free (bind_to);
+
+        if (NULL == (nh = GNUNET_NETWORK_socket_create (res->ai_family,
+                                                        res->ai_socktype,
+                                                        res->ai_protocol)))
+        {
+          GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR,
+                               "socket");
+          freeaddrinfo (res);
+          GNUNET_SCHEDULER_shutdown ();
+          return;
+        }
+        if (GNUNET_OK !=
+            GNUNET_NETWORK_socket_bind (nh,
+                                        res->ai_addr,
+                                        res->ai_addrlen))
+        {
+          GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR,
+                               "bind");
+          freeaddrinfo (res);
+          GNUNET_SCHEDULER_shutdown ();
+          return;
+        }
+        freeaddrinfo (res);
+        if (GNUNET_OK !=
+            GNUNET_NETWORK_socket_listen (nh,
+                                          UNIX_BACKLOG))
+        {
+          GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR,
+                               "listen");
+          GNUNET_SCHEDULER_shutdown ();
+          return;
+        }
+        fh = GNUNET_NETWORK_get_fd (nh);
+        GNUNET_NETWORK_socket_free_memory_only_ (nh);
+      }
+      else
+      {
+        fh = -1;
+      }
     }
     else
     {
@@ -940,15 +1099,13 @@ run (void *cls,
       GNUNET_assert (0);
     }
   }
-  mhd = MHD_start_daemon (MHD_USE_SUSPEND_RESUME,
+  mhd = MHD_start_daemon (MHD_USE_SUSPEND_RESUME | MHD_USE_DUAL_STACK,
                           port,
                           NULL, NULL,
                           &url_handler, NULL,
                           MHD_OPTION_LISTEN_SOCKET, fh,
-                          MHD_OPTION_NOTIFY_COMPLETED,
-                          &handle_mhd_completion_callback, NULL,
-                          MHD_OPTION_CONNECTION_TIMEOUT,
-                          (unsigned int) 10 /* 10s */,
+                          MHD_OPTION_NOTIFY_COMPLETED, 
&handle_mhd_completion_callback, NULL,
+                          MHD_OPTION_CONNECTION_TIMEOUT, (unsigned int) 10 /* 
10s */,
                           MHD_OPTION_END);
   if (NULL == mhd)
   {
diff --git a/src/backend/taler-merchant-httpd.h 
b/src/backend/taler-merchant-httpd.h
index f5adeac..0526ad2 100644
--- a/src/backend/taler-merchant-httpd.h
+++ b/src/backend/taler-merchant-httpd.h
@@ -38,7 +38,8 @@
  * Used by the iterator of the various merchant's instances given
  * in configuration
  */
-struct IterateInstancesCls {
+struct IterateInstancesCls
+{
 
   /**
    * Handle for the configuration beig parsed
@@ -75,7 +76,8 @@ struct IterateInstancesCls {
  * backend can account for several merchants, as used to do in donation
  * shops
  */
-struct MerchantInstance {
+struct MerchantInstance
+{
 
   /**
    * Instance's mnemonic identifier. This value lives as long as
@@ -89,6 +91,14 @@ struct MerchantInstance {
    */
   char *keyfile;
 
+  /* NOTE: the *_wire-fields should eventually be moved into a DLL
+     once we implement #4939 */
+
+  /**
+   * Which wire method is @e j_wire using?
+   */
+  const char *wire_method;
+
   /**
    * Wire details for this instance
    */
@@ -215,6 +225,17 @@ struct TM_HandlerContext
 extern json_t *j_wire;
 
 /**
+ * Default maximum wire fee to assume, unless stated differently in the 
proposal
+ * already.
+ */
+extern struct TALER_Amount default_max_wire_fee;
+
+/**
+ * Default factor for wire fee amortization.
+ */
+extern unsigned long long default_wire_fee_amortization;
+
+/**
  * Hash of our wire format details as given in #j_wire.
  */
 extern struct GNUNET_HashCode h_wire;
diff --git a/src/backend/taler-merchant-httpd_contract.c 
b/src/backend/taler-merchant-httpd_contract.c
deleted file mode 100644
index e9ebda4..0000000
--- a/src/backend/taler-merchant-httpd_contract.c
+++ /dev/null
@@ -1,287 +0,0 @@
-/*
-  This file is part of TALER
-  (C) 2014, 2015, 2016 INRIA
-
-  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
-  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 backend/taler-merchant-httpd_contract.c
- * @brief HTTP serving layer mainly intended to communicate with the frontend
- * @author Marcello Stanisci
- */
-#include "platform.h"
-#include <jansson.h>
-#include <taler/taler_signatures.h>
-#include <taler/taler_json_lib.h>
-#include "taler-merchant-httpd.h"
-#include "taler-merchant-httpd_parsing.h"
-#include "taler-merchant-httpd_auditors.h"
-#include "taler-merchant-httpd_exchanges.h"
-#include "taler-merchant-httpd_responses.h"
-
-
-/**
- * Check that the given JSON array of products is well-formed.
- *
- * @param products JSON array to check
- * @return #GNUNET_OK if all is fine
- */
-static int
-check_products (json_t *products)
-{
-  size_t index;
-  json_t *value;
-  int res;
-
-  if (! json_is_array (products))
-  {
-    GNUNET_break (0);
-    return GNUNET_SYSERR;
-  }
-  json_array_foreach (products, index, value) {
-    const char *description;
-    const char *error_name;
-    unsigned int error_line;
-    struct GNUNET_JSON_Specification spec[] = {
-      GNUNET_JSON_spec_string ("description", &description),
-      /* FIXME: there are other fields in the product specification
-         that are currently not labeled as optional. Maybe check
-         those as well, or make them truly optional. */
-      GNUNET_JSON_spec_end()
-    };
-
-    /* extract fields we need to sign separately */
-    res = GNUNET_JSON_parse (value,
-                             spec,
-                             &error_name,
-                             &error_line);
-    if (GNUNET_OK != res)
-    {
-      GNUNET_break (0);
-      GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                  "Product description parsing failed at #%u: %s:%u\n",
-                  (unsigned int) index,
-                  error_name,
-                  error_line);
-      return GNUNET_SYSERR;
-    }
-    GNUNET_JSON_parse_free (spec);
-  }
-  return GNUNET_OK;
-}
-
-
-/**
- * Information we keep for individual calls
- * to requests that parse JSON, but keep no other state.
- */
-struct TMH_JsonParseContext
-{
-
-  /**
-   * This field MUST be first.
-   * FIXME: Explain why!
-   */
-  struct TM_HandlerContext hc;
-
-  /**
-   * Placeholder for #TMH_PARSE_post_json() to keep its internal state.
-   */
-  void *json_parse_context;
-};
-
-
-/**
- * Custom cleanup routine for a `struct TMH_JsonParseContext`.
- *
- * @param hc the `struct TMH_JsonParseContext` to clean up.
- */
-static void
-json_parse_cleanup (struct TM_HandlerContext *hc)
-{
-  struct TMH_JsonParseContext *jpc = (struct TMH_JsonParseContext *) hc;
-
-  TMH_PARSE_post_cleanup_callback (jpc->json_parse_context);
-  GNUNET_free (jpc);
-}
-
-
-extern struct MerchantInstance *
-get_instance (struct json_t *json);
-
-
-/**
- * Manage a contract request. In practical terms, it adds the fields
- * 'exchanges', 'merchant_pub', and 'H_wire' to the contract 'proposition'
- * gotten from the frontend. Finally, it adds (outside of the
- * contract) a signature of the (hashed stringification) of the
- * contract (and the hashed stringification of this contract as well
- * to aid diagnostics) to the final bundle, which is then send back to
- * the frontend.
- *
- * @param rh context of the handler
- * @param connection the MHD connection to handle
- * @param[in,out] connection_cls the connection's closure (can be updated)
- * @param upload_data upload data
- * @param[in,out] upload_data_size number of bytes (left) in @a upload_data
- * @return MHD result code
- */
-int
-MH_handler_contract (struct TMH_RequestHandler *rh,
-                     struct MHD_Connection *connection,
-                     void **connection_cls,
-                     const char *upload_data,
-                     size_t *upload_data_size)
-{
-
-  json_t *root;
-  json_t *jcontract;
-  int res;
-  struct MerchantInstance *mi;
-  struct TMH_JsonParseContext *ctx;
-  struct TALER_ContractPS contract;
-  struct GNUNET_CRYPTO_EddsaSignature contract_sig;
-  struct TALER_Amount total;
-  struct TALER_Amount max_fee;
-  uint64_t transaction_id;
-  json_t *products;
-  json_t *merchant;
-  struct GNUNET_TIME_Absolute timestamp;
-  struct GNUNET_TIME_Absolute refund_deadline;
-  struct GNUNET_TIME_Absolute pay_deadline;
-  struct GNUNET_JSON_Specification spec[] = {
-    TALER_JSON_spec_amount ("amount", &total),
-    TALER_JSON_spec_amount ("max_fee", &max_fee),
-    GNUNET_JSON_spec_uint64 ("transaction_id", &transaction_id),
-    /* The following entries we don't actually need, except to check that
-       the contract is well-formed */
-    GNUNET_JSON_spec_json ("products", &products),
-    GNUNET_JSON_spec_json ("merchant", &merchant),
-    GNUNET_JSON_spec_absolute_time ("timestamp", &timestamp),
-    GNUNET_JSON_spec_absolute_time ("refund_deadline", &refund_deadline),
-    GNUNET_JSON_spec_absolute_time ("pay_deadline", &pay_deadline),
-    GNUNET_JSON_spec_end ()
-  };
-
-  if (NULL == *connection_cls)
-  {
-    ctx = GNUNET_new (struct TMH_JsonParseContext);
-    ctx->hc.cc = &json_parse_cleanup;
-    *connection_cls = ctx;
-  }
-  else
-  {
-    ctx = *connection_cls;
-  }
-
-  res = TMH_PARSE_post_json (connection,
-                             &ctx->json_parse_context,
-                             upload_data,
-                             upload_data_size,
-                             &root);
-  if (GNUNET_SYSERR == res)
-    return MHD_NO;
-  /* the POST's body has to be further fetched */
-  if ((GNUNET_NO == res) || (NULL == root))
-    return MHD_YES;
-
-  jcontract = json_object_get (root,
-                              "contract");
-  if (NULL == jcontract)
-  {
-    json_decref (root);
-    return TMH_RESPONSE_reply_arg_missing (connection,
-                                          TALER_EC_PARAMETER_MISSING,
-                                          "contract");
-  }
-  /* extract fields we need to sign separately */
-  res = TMH_PARSE_json_data (connection,
-                             jcontract,
-                             spec);
-  if (GNUNET_NO == res)
-  {
-    json_decref (root);
-    return MHD_YES;
-  }
-  if (GNUNET_SYSERR == res)
-  {
-    json_decref (root);
-    return TMH_RESPONSE_reply_internal_error (connection,
-                                             TALER_EC_NONE,
-                                             "Impossible to parse contract");
-  }
-  /* check contract is well-formed */
-  if (GNUNET_OK != check_products (products))
-  {
-    GNUNET_JSON_parse_free (spec);
-    json_decref (root);
-    return TMH_RESPONSE_reply_arg_invalid (connection,
-                                          TALER_EC_PARAMETER_MALFORMED,
-                                          "contract:products");
-  }
-
-  mi = get_instance (merchant);
-  if (NULL == mi)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                "Not able to find the specified instance\n"); 
-    json_decref (root);
-    return TMH_RESPONSE_reply_not_found (connection,
-                                        TALER_EC_CONTRACT_INSTANCE_UNKNOWN,
-                                        "Unknown instance given");
-  }
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "Signing contract on behalf of instance '%s'\n",
-              mi->id);
-  /* add fields to the contract that the backend should provide */
-  json_object_set (jcontract,
-                   "exchanges",
-                   trusted_exchanges);
-  json_object_set (jcontract,
-                   "auditors",
-                   j_auditors);
-  json_object_set_new (jcontract,
-                       "H_wire",
-                      GNUNET_JSON_from_data_auto (&mi->h_wire));
-  json_object_set_new (jcontract,
-                       "merchant_pub",
-                      GNUNET_JSON_from_data_auto (&mi->pubkey));
-
-  /* create contract signature */
-  contract.purpose.purpose = htonl (TALER_SIGNATURE_MERCHANT_CONTRACT);
-  contract.purpose.size = htonl (sizeof (contract));
-  contract.transaction_id = GNUNET_htonll (transaction_id);
-  TALER_amount_hton (&contract.total_amount,
-                     &total);
-  TALER_amount_hton (&contract.max_fee,
-                     &max_fee);
-  GNUNET_assert (GNUNET_OK ==
-                 TALER_JSON_hash (jcontract,
-                                  &contract.h_contract));
-  contract.merchant_pub = mi->pubkey;
-  GNUNET_CRYPTO_eddsa_sign (&mi->privkey.eddsa_priv,
-                            &contract.purpose,
-                            &contract_sig);
-
-  /* return final response */
-  res = TMH_RESPONSE_reply_json_pack (connection,
-                                      MHD_HTTP_OK,
-                                      "{s:O, s:o s:o}",
-                                      "contract", jcontract,
-                                      "merchant_sig", 
GNUNET_JSON_from_data_auto (&contract_sig),
-                                      "H_contract", GNUNET_JSON_from_data_auto 
(&contract.h_contract));
-  GNUNET_JSON_parse_free (spec);
-  json_decref (root);
-  return res;
-}
-
-/* end of taler-merchant-httpd_contract.c */
diff --git a/src/backend/taler-merchant-httpd_contract.h 
b/src/backend/taler-merchant-httpd_contract.h
deleted file mode 100644
index d8077dd..0000000
--- a/src/backend/taler-merchant-httpd_contract.h
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
-  This file is part of TALER
-  (C) 2014, 2015 INRIA
-
-  TALER is free software; you can redistribute it and/or modify it under the
-  terms of the GNU General Public License as published by the Free Software
-  Foundation; either version 3, or (at your option) any later version.
-
-  TALER is distributed in the hope that it will be useful, but WITHOUT ANY
-  WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
-  A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
-
-  You should have received a copy of the GNU General Public License along with
-  TALER; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
-*/
-/**
- * @file backend/taler-merchant-httpd_contract.h
- * @brief headers for /contract handler
- * @author Marcello Stanisci
- */
-#ifndef TALER_MERCHANT_HTTPD_CONTRACT_H
-#define TALER_MERCHANT_HTTPD_CONTRACT_H
-#include <microhttpd.h>
-#include "taler-merchant-httpd.h"
-
-/**
- * Manage a contract request
- *
- * @param rh context of the handler
- * @param connection the MHD connection to handle
- * @param[in,out] connection_cls the connection's closure (can be updated)
- * @param upload_data upload data
- * @param[in,out] upload_data_size number of bytes (left) in @a upload_data
- * @return MHD result code
- */
-int
-MH_handler_contract (struct TMH_RequestHandler *rh,
-                     struct MHD_Connection *connection,
-                     void **connection_cls,
-                     const char *upload_data,
-                     size_t *upload_data_size);
-
-#endif
diff --git a/src/backend/taler-merchant-httpd_exchanges.c 
b/src/backend/taler-merchant-httpd_exchanges.c
index 176c8ad..daf5550 100644
--- a/src/backend/taler-merchant-httpd_exchanges.c
+++ b/src/backend/taler-merchant-httpd_exchanges.c
@@ -1,6 +1,6 @@
 /*
   This file is part of TALER
-  (C) 2014, 2015, 2016 INRIA
+  (C) 2014-2017 INRIA
 
   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
@@ -84,6 +84,11 @@ struct TMH_EXCHANGES_FindOperation
   struct Exchange *my_exchange;
 
   /**
+   * Wire method we care about for fees.
+   */
+  char *wire_method;
+
+  /**
    * Task scheduled to asynchronously return the result to
    * the find continuation.
    */
@@ -93,6 +98,35 @@ struct TMH_EXCHANGES_FindOperation
 
 
 /**
+ * Information about wire transfer fees of an exchange, by wire method.
+ */
+struct FeesByWireMethod
+{
+
+  /**
+   * Kept in a DLL.
+   */
+  struct FeesByWireMethod *next;
+
+  /**
+   * Kept in a DLL.
+   */
+  struct FeesByWireMethod *prev;
+
+  /**
+   * Wire method these fees are for.
+   */
+  char *wire_method;
+
+  /**
+   * Applicable fees, NULL if unknown/error.
+   */
+  struct TALER_EXCHANGE_WireAggregateFees *af;
+
+};
+
+
+/**
  * Exchange
  */
 struct Exchange
@@ -129,6 +163,26 @@ struct Exchange
   struct TALER_EXCHANGE_Handle *conn;
 
   /**
+   * Active /wire request to the exchange, or NULL.
+   */
+  struct TALER_EXCHANGE_WireHandle *wire_request;
+
+  /**
+   * Task to re-run /wire after some delay.
+   */
+  struct GNUNET_SCHEDULER_Task *wire_task;
+
+  /**
+   * Head of wire fees from /wire request.
+   */
+  struct FeesByWireMethod *wire_fees_head;
+
+  /**
+   * Tail of wire fees from /wire request.
+   */
+  struct FeesByWireMethod *wire_fees_tail;
+
+  /**
    * Master public key, guaranteed to be set ONLY for
    * trusted exchanges.
    */
@@ -239,6 +293,279 @@ retry_exchange (void *cls)
 
 
 /**
+ * Function called with information about the wire fees
+ * for each wire method.  Stores the wire fees with the
+ * exchange for laster use.
+ *
+ * @param cls closure
+ * @param wire_method name of the wire method (i.e. "sepa")
+ * @param fees fee structure for this method
+ */
+static void
+process_wire_fees (void *cls,
+                   const char *wire_method,
+                   const struct TALER_EXCHANGE_WireAggregateFees *fees)
+{
+  struct Exchange *exchange = cls;
+  struct FeesByWireMethod *f;
+  struct TALER_EXCHANGE_WireAggregateFees *endp;
+  struct TALER_EXCHANGE_WireAggregateFees *af;
+
+  for (f = exchange->wire_fees_head; NULL != f; f = f->next)
+    if (0 == strcasecmp (wire_method,
+                         f->wire_method))
+      break;
+  if (NULL == f)
+  {
+    f = GNUNET_new (struct FeesByWireMethod);
+    f->wire_method = GNUNET_strdup (wire_method);
+    GNUNET_CONTAINER_DLL_insert (exchange->wire_fees_head,
+                                 exchange->wire_fees_tail,
+                                 f);
+  }
+  endp = f->af;
+  while ( (NULL != endp) &&
+          (NULL != endp->next) )
+    endp = endp->next;
+  while ( (NULL != endp) &&
+          (fees->start_date.abs_value_us < endp->end_date.abs_value_us) )
+    fees = fees->next;
+  if ( (NULL != endp) &&
+       (fees->start_date.abs_value_us != endp->end_date.abs_value_us) )
+  {
+    /* Hole in the fee structure, not allowed! */
+    GNUNET_break_op (0);
+    return;
+  }
+  while (NULL != fees)
+  {
+    af = GNUNET_new (struct TALER_EXCHANGE_WireAggregateFees);
+    *af = *fees;
+    af->next = NULL;
+    if (NULL == endp)
+      f->af = af;
+    else
+      endp->next = af;
+    endp = af;
+    // FIXME: also preserve `fees` in backend DB (under wire method + exchange 
master pub!)
+    fees = fees->next;
+  }
+}
+
+
+/**
+ * Obtain applicable fees for @a exchange and @a wire_method.
+ *
+ * @param exchange the exchange to query
+ * @param now current time
+ * @param wire_method the wire method we want the fees for
+ * @return NULL if we do not have fees for this method yet
+ */
+static struct TALER_EXCHANGE_WireAggregateFees *
+get_wire_fees (struct Exchange *exchange,
+               struct GNUNET_TIME_Absolute now,
+               const char *wire_method)
+{
+  for (struct FeesByWireMethod *fbw = exchange->wire_fees_head;
+       NULL != fbw;
+       fbw = fbw->next)
+    if (0 == strcasecmp (fbw->wire_method,
+                         wire_method) )
+    {
+      struct TALER_EXCHANGE_WireAggregateFees *af;
+
+      /* Advance through list up to current time */
+      while ( (NULL != (af = fbw->af)) &&
+              (now.abs_value_us >= af->end_date.abs_value_us) )
+      {
+        fbw->af = af->next;
+        GNUNET_free (af);
+      }
+      return af;
+    }
+  return NULL;
+}
+
+
+/**
+ * Check if we have any remaining pending requests for the
+ * given @a exchange, and if we have the required data, call
+ * the callback.
+ *
+ * @param exchange the exchange to check for pending find operations
+ * @return #GNUNET_YES if we need /wire data from @a exchange
+ */
+static int
+process_find_operations (struct Exchange *exchange)
+{
+  struct TMH_EXCHANGES_FindOperation *fo;
+  struct TMH_EXCHANGES_FindOperation *fn;
+  struct GNUNET_TIME_Absolute now;
+  int need_wire;
+
+  now = GNUNET_TIME_absolute_get ();
+  need_wire = GNUNET_NO;
+  for (fo = exchange->fo_head; NULL != fo; fo = fn)
+  {
+    const struct TALER_Amount *wire_fee;
+
+    fn = fo->next;
+    if (NULL != fo->wire_method)
+    {
+      struct TALER_EXCHANGE_WireAggregateFees *af;
+
+      /* Find fee structure for our wire method */
+      af = get_wire_fees (exchange,
+                          now,
+                          fo->wire_method);
+      if (NULL == af)
+      {
+        need_wire = GNUNET_YES;
+        continue;
+      }
+      if (af->start_date.abs_value_us > now.abs_value_us)
+      {
+        /* Disagreement on the current time */
+        GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                    "Exchange's earliest fee is %s adhead of our time. Clock 
skew issue?\n",
+                    GNUNET_STRINGS_relative_time_to_string 
(GNUNET_TIME_absolute_get_remaining (af->start_date),
+                                                            GNUNET_YES));
+        continue;
+      }
+      /* found fee, great! */
+      wire_fee = &af->wire_fee;
+    }
+    else
+    {
+      /* no wire transfer method given, so we yield no fee */
+      wire_fee = NULL;
+    }
+    GNUNET_CONTAINER_DLL_remove (exchange->fo_head,
+                                 exchange->fo_tail,
+                                 fo);
+    fo->fc (fo->fc_cls,
+            exchange->conn,
+            wire_fee,
+            exchange->trusted);
+    GNUNET_free_non_null (fo->wire_method);
+    GNUNET_free (fo);
+  }
+  return need_wire;
+}
+
+
+/**
+ * Check if we have any remaining pending requests for the
+ * given @a exchange, and if we have the required data, call
+ * the callback.  If requests without /wire data remain,
+ * retry the /wire request after some delay.
+ *
+ * @param cls a `struct Exchange` to check
+ */
+static void
+wire_task_cb (void *cls);
+
+
+/**
+ * Callbacks of this type are used to serve the result of submitting a
+ * wire format inquiry request to a exchange.
+ *
+ * If the request fails to generate a valid response from the
+ * exchange, @a http_status will also be zero.
+ *
+ * @param cls closure, a `struct Exchange`
+ * @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.
+ */
+static void
+handle_wire_data (void *cls,
+                  unsigned int http_status,
+                  enum TALER_ErrorCode ec,
+                  const json_t *obj)
+{
+  struct Exchange *exchange = cls;
+
+  exchange->wire_request = NULL;
+  if (MHD_HTTP_OK != http_status)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+                "Failed to obtain /wire details from `%s': %d\n",
+                exchange->uri,
+                ec);
+    return;
+  }
+  if (GNUNET_OK !=
+      TALER_EXCHANGE_wire_get_fees (&TALER_EXCHANGE_get_keys 
(exchange->conn)->master_pub,
+                                    obj,
+                                    &process_wire_fees,
+                                    exchange))
+  {
+    /* Report hard failure to all callbacks! */
+    struct TMH_EXCHANGES_FindOperation *fo;
+
+    GNUNET_break_op (0);
+    while (NULL != (fo = exchange->fo_head))
+    {
+      GNUNET_CONTAINER_DLL_remove (exchange->fo_head,
+                                   exchange->fo_tail,
+                                   fo);
+      /* TODO: report more precise error, this ultimately generates
+         "exchange not supported" instead of "exchange violated
+         protocol"; we should ideally generate a reply with
+         a specific TALER_EC-code, boxing 'obj' within it. */
+      fo->fc (fo->fc_cls,
+              NULL,
+              NULL,
+              GNUNET_NO);
+      GNUNET_free_non_null (fo->wire_method);
+      GNUNET_free (fo);
+    }
+    return;
+  }
+  if (GNUNET_YES ==
+      process_find_operations (exchange))
+  {
+    /* need to run /wire again, with some delay */
+    GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+                "Do not have sufficient wire data. Will re-request /wire in 1 
minute\n");
+
+    GNUNET_assert (NULL == exchange->wire_task);
+    exchange->wire_task = GNUNET_SCHEDULER_add_delayed 
(GNUNET_TIME_UNIT_MINUTES,
+                                                        &wire_task_cb,
+                                                        exchange);
+  }
+}
+
+
+/**
+ * Check if we have any remaining pending requests for the
+ * given @a exchange, and if we have the required data, call
+ * the callback.  If requests without /wire data remain,
+ * retry the /wire request after some delay.
+ *
+ * @param cls a `struct Exchange` to check
+ */
+static void
+wire_task_cb (void *cls)
+{
+  struct Exchange *exchange = cls;
+
+  exchange->wire_task = NULL;
+  if (GNUNET_YES !=
+      process_find_operations (exchange))
+    return; /* no more need */
+  GNUNET_assert (NULL == exchange->wire_request);
+  exchange->wire_request = TALER_EXCHANGE_wire (exchange->conn,
+                                                &handle_wire_data,
+                                                exchange);
+}
+
+
+/**
  * Function called with information about who is auditing
  * a particular exchange and what key the exchange is using.
  *
@@ -257,13 +584,22 @@ keys_mgmt_cb (void *cls,
               const struct TALER_EXCHANGE_Keys *keys)
 {
   struct Exchange *exchange = cls;
-  struct TMH_EXCHANGES_FindOperation *fo;
   struct GNUNET_TIME_Absolute expire;
   struct GNUNET_TIME_Relative delay;
 
   if (NULL == keys)
   {
     exchange->pending = GNUNET_YES;
+    if (NULL != exchange->wire_request)
+    {
+      TALER_EXCHANGE_wire_cancel (exchange->wire_request);
+      exchange->wire_request = NULL;
+    }
+    if (NULL != exchange->wire_task)
+    {
+      GNUNET_SCHEDULER_cancel (exchange->wire_task);
+      exchange->wire_task = NULL;
+    }
     exchange->retry_delay = RETRY_BACKOFF (exchange->retry_delay);
     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
                 "Failed to fetch /keys from `%s', retrying in %s\n",
@@ -280,21 +616,23 @@ keys_mgmt_cb (void *cls,
     delay = RELOAD_DELAY;
   else
     delay = GNUNET_TIME_absolute_get_remaining (expire);
-  exchange->retry_delay = GNUNET_TIME_UNIT_ZERO;
+  exchange->retry_delay
+    = GNUNET_TIME_UNIT_ZERO;
   exchange->retry_task
     = GNUNET_SCHEDULER_add_delayed (delay,
                                     &retry_exchange,
                                     exchange);
   exchange->pending = GNUNET_NO;
-  while (NULL != (fo = exchange->fo_head))
+  if (GNUNET_YES ==
+      process_find_operations (exchange))
   {
-    GNUNET_CONTAINER_DLL_remove (exchange->fo_head,
-                                 exchange->fo_tail,
-                                 fo);
-    fo->fc (fo->fc_cls,
-            exchange->conn,
-            exchange->trusted);
-    GNUNET_free (fo);
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "Got key data, but do not have current wire data. Will request 
/wire now\n");
+    GNUNET_assert (NULL == exchange->wire_request);
+    GNUNET_assert (NULL == exchange->wire_task);
+    exchange->wire_request = TALER_EXCHANGE_wire (exchange->conn,
+                                                  &handle_wire_data,
+                                                  exchange);
   }
 }
 
@@ -310,17 +648,19 @@ return_result (void *cls)
   struct TMH_EXCHANGES_FindOperation *fo = cls;
   struct Exchange *exchange = fo->my_exchange;
 
-  fo->at = NULL;
-  GNUNET_CONTAINER_DLL_remove (exchange->fo_head,
-                               exchange->fo_tail,
-                               fo);
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "Returning result for exchange %s, trusted=%d\n",
-              exchange->uri, exchange->trusted);
-  fo->fc (fo->fc_cls,
-          (GNUNET_SYSERR == exchange->pending) ? NULL : exchange->conn,
-          exchange->trusted);
-  GNUNET_free (fo);
+  if ( (GNUNET_YES ==
+        process_find_operations (exchange)) &&
+       (NULL == exchange->wire_request) &&
+       (GNUNET_NO == exchange->pending) &&
+       (NULL != exchange->wire_task) )
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+                "Do not have current wire data. Will re-request /wire in 1 
minute\n");
+    exchange->wire_task
+      = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_MINUTES,
+                                      &wire_task_cb,
+                                      exchange);
+  }
 }
 
 
@@ -330,12 +670,14 @@ return_result (void *cls)
  * NULL for the exchange.
  *
  * @param chosen_exchange URI of the exchange we would like to talk to
+ * @param wire_method the wire method we will use with @a chosen_exchange, 
NULL for none
  * @param fc function to call with the handles for the exchange
  * @param fc_cls closure for @a fc
  * @return NULL on error
  */
 struct TMH_EXCHANGES_FindOperation *
 TMH_EXCHANGES_find_exchange (const char *chosen_exchange,
+                             const char *wire_method,
                             TMH_EXCHANGES_FindContinuation fc,
                             void *fc_cls)
 {
@@ -387,11 +729,17 @@ TMH_EXCHANGES_find_exchange (const char *chosen_exchange,
   fo->fc = fc;
   fo->fc_cls = fc_cls;
   fo->my_exchange = exchange;
+  if (NULL != wire_method)
+    fo->wire_method = GNUNET_strdup (wire_method);
   GNUNET_CONTAINER_DLL_insert (exchange->fo_head,
                                exchange->fo_tail,
                                fo);
 
-  if (GNUNET_YES != exchange->pending)
+  if ( (GNUNET_YES != exchange->pending) &&
+       ( (NULL == fo->wire_method) ||
+         (NULL != get_wire_fees (exchange,
+                                 GNUNET_TIME_absolute_get (),
+                                 fo->wire_method)) ) )
   {
     /* We are not currently waiting for a reply, immediately
        return result */
@@ -404,9 +752,22 @@ TMH_EXCHANGES_find_exchange (const char *chosen_exchange,
   if ( (NULL == exchange->conn) &&
        (GNUNET_YES == exchange->pending) )
   {
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "Do not have current key data. Will request /keys now\n");
     exchange->retry_task = GNUNET_SCHEDULER_add_now (&retry_exchange,
                                                      exchange);
   }
+  else if ( (GNUNET_NO == exchange->pending) &&
+            (NULL == exchange->wire_task) &&
+            (NULL == exchange->wire_request) )
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "Do not have current wire data. Will re-request /wire now\n");
+    exchange->wire_task = GNUNET_SCHEDULER_add_now (&wire_task_cb,
+                                                    exchange);
+  }
+
+
   return fo;
 }
 
@@ -425,10 +786,11 @@ TMH_EXCHANGES_find_exchange_cancel (struct 
TMH_EXCHANGES_FindOperation *fo)
   {
     GNUNET_SCHEDULER_cancel (fo->at);
     fo->at = NULL;
-  }
+   }
   GNUNET_CONTAINER_DLL_remove (exchange->fo_head,
                                exchange->fo_tail,
                                fo);
+  GNUNET_free_non_null (fo->wire_method);
   GNUNET_free (fo);
 }
 
@@ -443,7 +805,7 @@ TMH_EXCHANGES_find_exchange_cancel (struct 
TMH_EXCHANGES_FindOperation *fo)
  */
 static void
 accept_exchanges (void *cls,
-                 const char *section)
+                  const char *section)
 {
   const struct GNUNET_CONFIGURATION_Handle *cfg = cls;
   char *uri;
@@ -561,10 +923,26 @@ TMH_EXCHANGES_done ()
     GNUNET_CONTAINER_DLL_remove (exchange_head,
                                  exchange_tail,
                                  exchange);
+    if (NULL != exchange->wire_request)
+    {
+      TALER_EXCHANGE_wire_cancel (exchange->wire_request);
+      exchange->wire_request = NULL;
+    }
+    if (NULL != exchange->wire_task)
+    {
+      GNUNET_SCHEDULER_cancel (exchange->wire_task);
+      exchange->wire_task = NULL;
+    }
     if (NULL != exchange->conn)
+    {
       TALER_EXCHANGE_disconnect (exchange->conn);
+      exchange->conn = NULL;
+    }
     if (NULL != exchange->retry_task)
+    {
       GNUNET_SCHEDULER_cancel (exchange->retry_task);
+      exchange->retry_task = NULL;
+    }
     GNUNET_free (exchange->uri);
     GNUNET_free (exchange);
   }
diff --git a/src/backend/taler-merchant-httpd_exchanges.h 
b/src/backend/taler-merchant-httpd_exchanges.h
index 0e705a4..6b763ae 100644
--- a/src/backend/taler-merchant-httpd_exchanges.h
+++ b/src/backend/taler-merchant-httpd_exchanges.h
@@ -60,11 +60,13 @@ TMH_EXCHANGES_done (void);
  *
  * @param cls closure
  * @param eh handle to the exchange context
+ * @param wire_fee current applicable wire fee for dealing with @a eh, NULL if 
not available
  * @param exchange_trusted #GNUNET_YES if this exchange is trusted by config
  */
 typedef void
 (*TMH_EXCHANGES_FindContinuation)(void *cls,
                                   struct TALER_EXCHANGE_Handle *eh,
+                                  const struct TALER_Amount *wire_fee,
                                   int exchange_trusted);
 
 
@@ -80,11 +82,13 @@ struct TMH_EXCHANGES_FindOperation;
  * NULL for the exchange.
  *
  * @param chosen_exchange URI of the exchange we would like to talk to
+ * @param wire_method the wire method we will use with @a chosen_exchange, 
NULL for none
  * @param fc function to call with the handles for the exchange
  * @param fc_cls closure for @a fc
  */
 struct TMH_EXCHANGES_FindOperation *
 TMH_EXCHANGES_find_exchange (const char *chosen_exchange,
+                             const char *wire_method,
                              TMH_EXCHANGES_FindContinuation fc,
                              void *fc_cls);
 
diff --git a/src/backend/taler-merchant-httpd_history.c 
b/src/backend/taler-merchant-httpd_history.c
index d072814..2e530e9 100644
--- a/src/backend/taler-merchant-httpd_history.c
+++ b/src/backend/taler-merchant-httpd_history.c
@@ -14,7 +14,7 @@
   TALER; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
 */
 /**
- * @file backend/taler-merchant-httpd_contract.c
+ * @file backend/taler-merchant-httpd_history.c
  * @brief HTTP serving layer mainly intended to communicate with the frontend
  * @author Marcello Stanisci
  */
@@ -26,45 +26,73 @@
 #include "taler-merchant-httpd_responses.h"
 
 /**
- * Function called with information about a transaction. Checks whether the
- * returned tuple
+ * Index to the first row to return in response to /history.
+ */
+unsigned int start;
+
+/**
+ * How many rows we are to return in response to /history.
+ */
+unsigned int delta;
+
+/**
+ * Index to the current row being processed.
+ */
+unsigned int current = 0;
+
+
+/**
+ * Function called with information about a transaction.
  *
  * @param cls closure
- * @param transaction_id of the contract
  * @param merchant_pub merchant's public key
  * @param exchange_uri URI of the exchange
- * @param h_contract hash of the contract
+ * @param transaction_id proposal's transaction id
  * @param h_wire hash of our wire details
  * @param timestamp time of the confirmation
  * @param refund refund deadline
  * @param total_amount total amount we receive for the contract after fees
  */
-
 static void
-history_cb (void *cls,
-            uint64_t transaction_id,
-           const struct TALER_MerchantPublicKeyP *merchant_pub,
-            const char *exchange_uri,
-            const struct GNUNET_HashCode *h_contract,
-            const struct GNUNET_HashCode *h_wire,
-            struct GNUNET_TIME_Absolute timestamp,
-            struct GNUNET_TIME_Absolute refund,
-            const struct TALER_Amount *total_amount)
+pd_cb (void *cls,
+       const char *order_id,
+       const json_t *proposal_data)
 {
   json_t *response = cls;
   json_t *entry;
+  json_t *amount;
+  json_t *timestamp;
+  json_t *instance;
+
+  GNUNET_assert (-1 != json_unpack ((json_t *) proposal_data,
+                                    "{s:o, s:o, s:{s:o}}",
+                                    "amount", &amount,
+                                    "timestamp", &timestamp,
+                                    "merchant", "instance", &instance));
 
-  GNUNET_break (NULL !=
-               (entry = json_pack ("{s:I, s:s, s:o, s:o, s:o}",
-                                   "transaction_id", transaction_id,
-                                   "exchange", exchange_uri,
-                                   "h_contract", GNUNET_JSON_from_data_auto 
(h_contract),
-                                   "timestamp", GNUNET_JSON_from_time_abs 
(timestamp),
-                                   "total_amount",
-                                   TALER_JSON_from_amount (total_amount))));
-  GNUNET_break (0 == json_array_append (response, entry));
+  if ( (current >= start) &&
+       (current < start + delta) )
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "Adding history element. Current: %u, start: %u, delta: %u\n",
+                current,
+                start,
+                delta);
+    GNUNET_break (NULL != (entry = json_pack ("{s:s, s:O, s:O, s:O}",
+                                              "order_id", order_id,
+                                              "amount", amount,
+                                              "timestamp", timestamp,
+                                              "instance", instance)));
+
+    GNUNET_break (0 == json_array_append_new (response,
+                                              entry));
+  }
+
+  // FIXME to zero after returned.
+  current++;
 }
 
+
 /**
  * Manage a /history request. Query the db and returns transactions
  * younger than the date given as parameter
@@ -89,37 +117,105 @@ MH_handler_history (struct TMH_RequestHandler *rh,
   json_t *response;
   unsigned int ret;
   unsigned long long seconds;
-  
+  struct MerchantInstance *mi;
+
   response = json_array (); /*FIXME who decrefs this?*/
   str = MHD_lookup_connection_value (connection,
                                      MHD_GET_ARGUMENT_KIND,
                                      "date");
 
-  if (NULL == str)
-    return TMH_RESPONSE_reply_arg_missing (connection,
-                                          TALER_EC_PARAMETER_MISSING,
-                                           "date");
+  seconds = 0;
+  if (NULL != str)
+  {
+    if (1 != sscanf (str, "%llu", &seconds))
+    {
+      json_decref (response);
+      return TMH_RESPONSE_reply_arg_invalid (connection,
+                                             TALER_EC_PARAMETER_MALFORMED,
+                                             "date");
+    }
+  }
 
-  if (1 != sscanf (str, "%llu", &seconds))
-    return TMH_RESPONSE_reply_arg_invalid (connection,
-                                          TALER_EC_PARAMETER_MALFORMED,
-                                           "date");
   date.abs_value_us = seconds * 1000LL * 1000LL;
   if (date.abs_value_us / 1000LL / 1000LL != seconds)
+  {
+    json_decref (response);
     return TMH_RESPONSE_reply_bad_request (connection,
-                                          TALER_EC_HISTORY_TIMESTAMP_OVERFLOW,
+                                           TALER_EC_HISTORY_TIMESTAMP_OVERFLOW,
                                            "Timestamp overflowed");
-  ret = db->find_transactions_by_date (db->cls,
-                                       date,
-                                       history_cb,
-                                       response);
+  }
+
+
+  mi = TMH_lookup_instance ("default");
+  str = MHD_lookup_connection_value (connection,
+                                     MHD_GET_ARGUMENT_KIND,
+                                     "instance");
+  if (NULL != str)
+    mi = TMH_lookup_instance (str);
+
+  if (NULL == mi)
+  {
+    json_decref (response);
+    return TMH_RESPONSE_reply_not_found (connection,
+                                         TALER_EC_HISTORY_INSTANCE_UNKNOWN,
+                                         "instance");
+  }
+  start = 0;
+  delta = 20;
+
+  str = MHD_lookup_connection_value (connection,
+                                     MHD_GET_ARGUMENT_KIND,
+                                     "start");
+  if (NULL != str)
+  {
+    if ((1 != sscanf (str, "%d", &start)) ||
+        start < 0)
+    {
+      json_decref (response);
+      return TMH_RESPONSE_reply_arg_invalid (connection,
+                                             TALER_EC_PARAMETER_MALFORMED,
+                                             "start");
+    }
+  }
+
+  str = MHD_lookup_connection_value (connection,
+                                     MHD_GET_ARGUMENT_KIND,
+                                     "delta");
+
+  if (NULL != str)
+  {
+    if ((1 != sscanf (str, "%d", &delta)) ||
+        delta < 0)
+      return TMH_RESPONSE_reply_arg_invalid (connection,
+                                             TALER_EC_PARAMETER_MALFORMED,
+                                             "delta");
+  }
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Querying history back to %s\n",
+              GNUNET_STRINGS_absolute_time_to_string (date));
+
+  ret = db->find_proposal_data_by_date (db->cls,
+                                        date,
+                                        &mi->pubkey,
+                                        pd_cb,
+                                        response);
+  current = 0;
   if (GNUNET_SYSERR == ret)
+  {
+    json_decref (response);
     return TMH_RESPONSE_reply_internal_error (connection,
                                              TALER_EC_HISTORY_DB_FETCH_ERROR,
                                              "db error to get history");
-  return TMH_RESPONSE_reply_json (connection,
-                                  response,
-                                  MHD_HTTP_OK);
+  }
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "history data: %s\n",
+              json_dumps (response, JSON_INDENT (1)));
+
+  ret = TMH_RESPONSE_reply_json (connection,
+                                 response,
+                                 MHD_HTTP_OK);
+  json_decref (response);
+  return ret;
 }
 
 /* end of taler-merchant-httpd_history.c */
diff --git a/src/backend/taler-merchant-httpd_history.h 
b/src/backend/taler-merchant-httpd_history.h
index 3004c4a..a06e926 100644
--- a/src/backend/taler-merchant-httpd_history.h
+++ b/src/backend/taler-merchant-httpd_history.h
@@ -14,7 +14,7 @@
   TALER; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
 */
 /**
- * @file backend/taler-merchant-httpd_contract.c
+ * @file backend/taler-merchant-httpd_history.c
  * @brief HTTP serving layer mainly intended to communicate with the frontend
  * @author Marcello Stanisci
  */
diff --git a/src/backend/taler-merchant-httpd_map.c 
b/src/backend/taler-merchant-httpd_map.c
deleted file mode 100644
index 8eb9d80..0000000
--- a/src/backend/taler-merchant-httpd_map.c
+++ /dev/null
@@ -1,241 +0,0 @@
-/*
-  This file is part of TALER
-  (C) 2014, 2015, 2016 INRIA
-
-  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
-  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 backend/taler-merchant-httpd_map.c
- * @brief Provides the frontend the mean to store plain contracts in database
- * @author Marcello Stanisci
- */
-#include "platform.h"
-#include <jansson.h>
-#include <taler/taler_signatures.h>
-#include <taler/taler_json_lib.h>
-#include "taler-merchant-httpd.h"
-#include "taler-merchant-httpd_responses.h"
-#include "taler-merchant-httpd_parsing.h"
-
-/**
- * Information we keep for individual calls
- * to requests that parse JSON, but keep no other state.
- */
-struct TMH_JsonParseContext
-{
-
-  /**
-   * This field MUST be first.
-   * FIXME: Explain why!
-   */
-  struct TM_HandlerContext hc;
-
-  /**
-   * Placeholder for #TMH_PARSE_post_json() to keep its internal state.
-   */
-  void *json_parse_context;
-};
-
-/**
- * Custom cleanup routine for a `struct TMH_JsonParseContext`.
- *
- * @param hc the `struct TMH_JsonParseContext` to clean up.
- */
-static void
-json_parse_cleanup (struct TM_HandlerContext *hc)
-{
-  struct TMH_JsonParseContext *jpc = (struct TMH_JsonParseContext *) hc;
-
-  TMH_PARSE_post_cleanup_callback (jpc->json_parse_context);
-  GNUNET_free (jpc);
-}
-
-
-/**
- * Manage a /map/in request. Store in db a plain text contract
- * and its hashcode.
- *
- * @param rh context of the handler
- * @param connection the MHD connection to handle
- * @param[in,out] connection_cls the connection's closure (can be updated)
- * @param upload_data upload data
- * @param[in,out] upload_data_size number of bytes (left) in @a upload_data
- * @return MHD result code
- */
-int
-MH_handler_map_in (struct TMH_RequestHandler *rh,
-                   struct MHD_Connection *connection,
-                   void **connection_cls,
-                   const char *upload_data,
-                   size_t *upload_data_size)
-{
-
-  int res;
-  json_t *root;
-  json_t *contract;
-  struct GNUNET_HashCode h_contract;
-  struct GNUNET_HashCode tmp;
-  struct TMH_JsonParseContext *ctx;
-  struct MHD_Response *response;
-
-/* Fetch body */
-
-  struct GNUNET_JSON_Specification spec[] = {
-    GNUNET_JSON_spec_json ("contract", &contract),
-    GNUNET_JSON_spec_fixed_auto ("h_contract", &h_contract),
-    GNUNET_JSON_spec_end ()
-  };
-
-  if (NULL == *connection_cls)
-  {
-    ctx = GNUNET_new (struct TMH_JsonParseContext);
-    ctx->hc.cc = &json_parse_cleanup;
-    *connection_cls = ctx;
-  }
-  else
-  {
-    ctx = *connection_cls;
-  }
-
-  res = TMH_PARSE_post_json (connection,
-                             &ctx->json_parse_context,
-                             upload_data,
-                             upload_data_size,
-                             &root);
-  if (GNUNET_SYSERR == res)
-    return MHD_NO;
-  /* the POST's body has to be further fetched */
-  if ((GNUNET_NO == res) || (NULL == root))
-    return MHD_YES;
-
-  res = TMH_PARSE_json_data (connection,
-                             root,
-                             spec);
-  if (GNUNET_NO == res)
-  {
-    json_decref (root);
-    return MHD_YES;
-  }
-  if (GNUNET_SYSERR == res)
-  {
-    json_decref (root);
-    return TMH_RESPONSE_reply_internal_error (connection,
-                                             TALER_EC_NONE,
-                                             "Impossible to parse JSON");
-  }
-
-  /* Sanity checks */
-  if (GNUNET_SYSERR ==
-      TALER_JSON_hash (contract,
-                       &tmp))
-    return TMH_RESPONSE_reply_invalid_json (connection); 
-
-  /**
-   * Check hashes match. This check does NOT detect invalid
-   * contracts though.
-   */
-
-  if (0 != memcmp (&tmp,
-                   &h_contract,
-                   sizeof (struct GNUNET_HashCode)))
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_INFO,
-                "'h_contract' does not match 'contract'\n");
-    return TMH_RESPONSE_reply_json_pack
-             (connection,
-              MHD_HTTP_UNPROCESSABLE_ENTITY,
-              "{s:I, s:s}",
-              "code", (json_int_t) TALER_EC_MAP_IN_UNMATCHED_HASH,
-              "error", "field 'h_contract' is not hash of 'contract'");
-  }
-
-  /* Store body */
-  if (GNUNET_OK != db->store_map (db->cls,
-                                  &h_contract,
-                                  contract))
-  {
-    return TMH_RESPONSE_reply_internal_error (connection,
-                                              TALER_EC_MAP_IN_STORE_DB_ERROR,
-                                              "Could not store data into db");
-  }
-
- response = MHD_create_response_from_buffer (0, NULL, MHD_RESPMEM_PERSISTENT); 
- return MHD_queue_response (connection, MHD_HTTP_OK, response);
-
-}
-
-
-/**
- * Manage a /map/out request. Query the db and returns a plain
- * text contract associated with the hashcode given as input
- *
- * @param rh context of the handler
- * @param connection the MHD connection to handle
- * @param[in,out] connection_cls the connection's closure (can be updated)
- * @param upload_data upload data
- * @param[in,out] upload_data_size number of bytes (left) in @a upload_data
- * @return MHD result code
- */
-int
-MH_handler_map_out (struct TMH_RequestHandler *rh,
-                    struct MHD_Connection *connection,
-                    void **connection_cls,
-                    const char *upload_data,
-                    size_t *upload_data_size)
-{
-  const char *h_contract_enc;
-  struct GNUNET_HashCode h_contract;
-  int res;
-  json_t *contract;
-
-  h_contract_enc = MHD_lookup_connection_value (connection,
-                                                MHD_GET_ARGUMENT_KIND,
-                                                "h_contract");
-  if (NULL == h_contract_enc)
-    return TMH_RESPONSE_reply_arg_missing (connection,
-                                          TALER_EC_PARAMETER_MISSING,
-                                           "h_contract");
-
-  if (GNUNET_OK != GNUNET_STRINGS_string_to_data (h_contract_enc,
-                                                  strlen (h_contract_enc),
-                                                  &h_contract, 
-                                                  sizeof (h_contract)))
-  {
-    GNUNET_break_op (0);
-    return TMH_RESPONSE_reply_bad_request (connection,
-                                           TALER_EC_PARAMETER_MALFORMED,
-                                           "Could not decode hashcode into 
binary form"); 
-  }
-
-  res = db->find_contract (db->cls,
-                           &contract,
-                           &h_contract);
-
-  if (GNUNET_SYSERR == res)
-  {
-    return TMH_RESPONSE_reply_internal_error (connection,
-                                              
TALER_EC_MAP_OUT_GET_FROM_DB_ERROR,
-                                              "Could not retrieve data from 
db");
-  }
-
-  if (GNUNET_NO == res)
-  {
-    return TMH_RESPONSE_reply_not_found (connection, 
-                                         TALER_EC_MAP_OUT_CONTRACT_UNKNOWN,
-                                         "contract");
-  }
-
-  return TMH_RESPONSE_reply_json (connection,
-                                  contract,
-                                  MHD_HTTP_OK); 
-}
-/* end of taler-merchant-httpd_history.c */
diff --git a/src/backend/taler-merchant-httpd_map.h 
b/src/backend/taler-merchant-httpd_map.h
index de9150a..83aca2b 100644
--- a/src/backend/taler-merchant-httpd_map.h
+++ b/src/backend/taler-merchant-httpd_map.h
@@ -14,7 +14,7 @@
   TALER; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
 */
 /**
- * @file backend/taler-merchant-httpd_contract.c
+ * @file backend/taler-merchant-httpd_map.c
  * @brief HTTP serving layer mainly intended to communicate with the frontend
  * @author Marcello Stanisci
  */
diff --git a/src/backend/taler-merchant-httpd_pay.c 
b/src/backend/taler-merchant-httpd_pay.c
index a920db0..c3203ef 100644
--- a/src/backend/taler-merchant-httpd_pay.c
+++ b/src/backend/taler-merchant-httpd_pay.c
@@ -1,6 +1,6 @@
 /*
   This file is part of TALER
-  (C) 2014, 2015, 2016 GNUnet e.V. and INRIA
+  (C) 2014-2017 GNUnet e.V. and INRIA
 
   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
@@ -38,11 +38,6 @@
  */
 #define PAY_TIMEOUT (GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 
30))
 
-/**
- * The instance which is working this request
- */
-struct MerchantInstance *mi;
-
 
 /**
  * Information we keep for an individual call to the /pay handler.
@@ -159,7 +154,7 @@ struct PayContext
   /**
    * Transaction ID given in @e root.
    */
-  uint64_t transaction_id;
+  const char *order_id;
 
   /**
    * Maximum fee the merchant is willing to pay, from @e root.
@@ -170,18 +165,46 @@ struct PayContext
   struct TALER_Amount max_fee;
 
   /**
+   * Maximum wire fee the merchant is willing to pay, from @e root.
+   * Note that IF the total fee of the exchange is higher, that is
+   * acceptable to the merchant if the customer is willing to
+   * pay the amorized difference.  Wire fees are charged over an
+   * aggregate of several translations, hence unlike the deposit
+   * fees, they are amortized over several customer's transactions.
+   * The contract specifies under @e wire_fee_amortization how many
+   * customer's transactions he expects the wire fees to be amortized
+   * over on average.  Thus, if the wire fees are larger than
+   * @e max_wire_fee, each customer is expected to contribute
+   * $\frac{actual-wire-fee - max_wire_fee}{wire_fee_amortization}$.
+   * The customer's contribution may be further reduced by the
+   * difference between @e max_fee and the sum of the deposit fees.
+   *
+   * Default is that the merchant is unwilling to pay any wire fees.
+   */
+  struct TALER_Amount max_wire_fee;
+
+  /**
+   * Number of transactions that the wire fees are expected to be
+   * amortized over.  Never zero, defaults (conservateively) to 1.
+   * May be higher if merchants expect many small transactions to
+   * be aggregated and thus wire fees to be reasonably amortized
+   * due to aggregation.
+   */
+  uint32_t wire_fee_amortization;
+
+  /**
    * Amount from @e root.  This is the amount the merchant expects
    * to make, minus @e max_fee.
    */
   struct TALER_Amount amount;
 
   /**
-   * Timestamp from @e root.
+   * Timestamp from @e proposal_data.
    */
   struct GNUNET_TIME_Absolute timestamp;
 
   /**
-   * Refund deadline from @e root.
+   * Refund deadline from @e proposal_data.
    */
   struct GNUNET_TIME_Absolute refund_deadline;
 
@@ -191,9 +214,15 @@ struct PayContext
   struct GNUNET_TIME_Absolute pay_deadline;
 
   /**
-   * "H_contract" from @e root.
+   * "H_contract" from @e proposal_data.
    */
-  struct GNUNET_HashCode h_contract;
+  struct GNUNET_HashCode h_proposal_data;
+
+  /**
+   * "H_wire" from @e proposal_data.  Used to identify the instance's
+   * wire transfer method.
+   */
+  struct GNUNET_HashCode h_wire;
 
   /**
    * Wire transfer deadline. How soon would the merchant like the
@@ -247,6 +276,12 @@ struct PayContext
    */
   struct MerchantInstance *mi;
 
+  /**
+   * Proposal data for the proposal that is being
+   * payed for in this context.
+   */
+  json_t *proposal_data;
+
 };
 
 
@@ -280,28 +315,6 @@ resume_pay_with_response (struct PayContext *pc,
 
 
 /**
- * Convert denomination key to its base32 representation
- *
- * @param dk denomination key to convert
- * @return 0-terminated base32 encoding of @a dk, to be deallocated
- */
-static char *
-denomination_to_string_alloc (struct TALER_DenominationPublicKey *dk)
-{
-  char *buf;
-  char *buf2;
-  size_t buf_size;
-
-  buf_size = GNUNET_CRYPTO_rsa_public_key_encode (dk->rsa_public_key,
-                                                  &buf);
-  buf2 = GNUNET_STRINGS_data_to_string_alloc (buf,
-                                              buf_size);
-  GNUNET_free (buf);
-  return buf2;
-}
-
-
-/**
  * Abort all pending /deposit operations.
  *
  * @param pc pay context to abort
@@ -327,6 +340,37 @@ abort_deposit (struct PayContext *pc)
 
 
 /**
+ * Generate a response that indicates payment success.
+ *
+ * @param pc payment context
+ * @return the mhd response
+ */
+struct MHD_Response *
+sign_success_response (struct PayContext *pc)
+{
+  struct GNUNET_CRYPTO_EddsaSignature sig;
+  struct PaymentResponsePS mr;
+
+  mr.purpose.purpose = htonl (TALER_SIGNATURE_MERCHANT_PAYMENT_OK);
+  mr.purpose.size = htonl (sizeof (mr));
+  mr.h_proposal_data = pc->h_proposal_data;
+
+  GNUNET_CRYPTO_eddsa_sign (&pc->mi->privkey.eddsa_priv,
+                            &mr.purpose,
+                           &sig);
+
+  return TMH_RESPONSE_make_json_pack ("{s:O, s:o, s:o}",
+                                      "proposal_data",
+                                      pc->proposal_data,
+                                      "sig",
+                                      GNUNET_JSON_from_data_auto (&sig),
+                                      "h_proposal_data",
+                                      GNUNET_JSON_from_data 
(&pc->h_proposal_data,
+                                                             sizeof (struct 
GNUNET_HashCode)));
+}
+
+
+/**
  * Callback to handle a deposit permission's response.
  *
  * @param cls a `struct DepositConfirmation` (i.e. a pointer
@@ -352,8 +396,6 @@ deposit_cb (void *cls,
 {
   struct DepositConfirmation *dc = cls;
   struct PayContext *pc = dc->pc;
-  struct GNUNET_CRYPTO_EddsaSignature sig;
-  struct PaymentResponsePS mr;
 
   dc->dh = NULL;
   pc->pending--;
@@ -395,9 +437,13 @@ deposit_cb (void *cls,
     return;
   }
   /* store result to DB */
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Storing successful payment for h_proposal_data '%s'\n",
+              GNUNET_h2s (&pc->h_proposal_data));
+
   if (GNUNET_OK !=
       db->store_deposit (db->cls,
-                        pc->transaction_id,
+                        &pc->h_proposal_data,
                         &pc->mi->pubkey,
                         &dc->coin_pub,
                         &dc->amount_with_fee,
@@ -418,23 +464,9 @@ deposit_cb (void *cls,
 
   if (0 != pc->pending)
     return; /* still more to do */
-
-
-  mr.purpose.purpose = htonl (TALER_SIGNATURE_MERCHANT_PAYMENT_OK);
-  mr.purpose.size = htonl (sizeof (mr));
-  mr.h_contract = pc->h_contract;
-
-  GNUNET_CRYPTO_eddsa_sign (&mi->privkey.eddsa_priv,
-                            &mr.purpose,
-                           &sig);
   resume_pay_with_response (pc,
                             MHD_HTTP_OK,
-                            TMH_RESPONSE_make_json_pack ("{s:s, s:o}",
-                                                         "merchant_sig",
-                                                        json_string_value 
(GNUNET_JSON_from_data_auto (&sig)),
-                                                         "h_contract",
-                                                         GNUNET_JSON_from_data 
(&pc->h_contract,
-                                                                               
 sizeof (struct GNUNET_HashCode))));
+                            sign_success_response (pc));
 }
 
 
@@ -492,6 +524,11 @@ pay_context_cleanup (struct TM_HandlerContext *hc)
     GNUNET_free (pc->chosen_exchange);
     pc->chosen_exchange = NULL;
   }
+  if (NULL != pc->proposal_data)
+  {
+    json_decref (pc->proposal_data);
+    pc->proposal_data = NULL;
+  }
   GNUNET_free (pc);
 }
 
@@ -501,16 +538,20 @@ pay_context_cleanup (struct TM_HandlerContext *hc)
  *
  * @param cls the `struct PayContext`
  * @param mh NULL if exchange was not found to be acceptable
+ * @param wire_fee current applicable fee for dealing with @a mh, NULL if not 
available
  * @param exchange_trusted #GNUNET_YES if this exchange is trusted by config
  */
 static void
 process_pay_with_exchange (void *cls,
                            struct TALER_EXCHANGE_Handle *mh,
+                           const struct TALER_Amount *wire_fee,
                            int exchange_trusted)
 {
   struct PayContext *pc = cls;
   struct TALER_Amount acc_fee;
   struct TALER_Amount acc_amount;
+  struct TALER_Amount wire_fee_delta;
+  struct TALER_Amount wire_fee_customer_contribution;
   const struct TALER_EXCHANGE_Keys *keys;
   unsigned int i;
 
@@ -527,7 +568,6 @@ process_pay_with_exchange (void *cls,
     return;
   }
   pc->mh = mh;
-
   keys = TALER_EXCHANGE_get_keys (mh);
   if (NULL == keys)
   {
@@ -549,8 +589,6 @@ process_pay_with_exchange (void *cls,
                                                         &dc->denom);
     if (NULL == denom_details)
     {
-      char *denom_enc;
-
       GNUNET_break_op (0);
       resume_pay_with_response (pc,
                                 MHD_HTTP_BAD_REQUEST,
@@ -559,11 +597,6 @@ process_pay_with_exchange (void *cls,
                                                             "code", 
TALER_EC_PAY_DENOMINATION_KEY_NOT_FOUND,
                                                              "denom_pub", 
GNUNET_JSON_from_rsa_public_key (dc->denom.rsa_public_key),
                                                              "exchange_keys", 
TALER_EXCHANGE_get_keys_raw (mh)));
-      denom_enc = denomination_to_string_alloc (&dc->denom);
-      GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                  "unknown denom to exchange: %s\n",
-                  denom_enc);
-      GNUNET_free (denom_enc);
       return;
     }
     if (GNUNET_OK !=
@@ -571,8 +604,6 @@ process_pay_with_exchange (void *cls,
                                denom_details,
                                exchange_trusted))
     {
-      char *denom_enc;
-
       GNUNET_break_op (0);
       resume_pay_with_response (pc,
                                 MHD_HTTP_BAD_REQUEST,
@@ -580,11 +611,6 @@ process_pay_with_exchange (void *cls,
                                                              "error", "invalid 
denomination",
                                                             "code", 
(json_int_t) TALER_EC_PAY_DENOMINATION_KEY_AUDITOR_FAILURE,
                                                              "denom_pub", 
GNUNET_JSON_from_rsa_public_key (dc->denom.rsa_public_key)));
-      denom_enc = denomination_to_string_alloc (&dc->denom);
-      GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                  "Client offered invalid denomination: %s\n",
-                  denom_enc);
-      GNUNET_free (denom_enc);
       return;
     }
     dc->deposit_fee = denom_details->fee_deposit;
@@ -630,6 +656,38 @@ process_pay_with_exchange (void *cls,
     }
   }
 
+  /* Now compare exchange wire fee compared to what we are willing to pay */
+  if (GNUNET_YES !=
+      TALER_amount_cmp_currency (wire_fee,
+                                 &pc->max_wire_fee))
+  {
+    GNUNET_break (0);
+    resume_pay_with_response (pc,
+                              MHD_HTTP_INTERNAL_SERVER_ERROR,
+                              TMH_RESPONSE_make_internal_error 
(TALER_EC_PAY_WIRE_FEE_CURRENCY_MISSMATCH,
+                                                                "wire_fee"));
+    return;
+  }
+
+  if (GNUNET_OK ==
+      TALER_amount_subtract (&wire_fee_delta,
+                             wire_fee,
+                             &pc->max_wire_fee))
+  {
+    /* Actual wire fee is indeed higher than our maximum, compute
+       how much the customer is expected to cover! */
+    TALER_amount_divide (&wire_fee_customer_contribution,
+                         &wire_fee_delta,
+                         pc->wire_fee_amortization);
+  }
+  else
+  {
+    GNUNET_assert (GNUNET_OK ==
+                   TALER_amount_get_zero (wire_fee->currency,
+                                          &wire_fee_customer_contribution));
+
+  }
+
   /* Now check that the customer paid enough for the full contract */
   if (-1 == TALER_amount_cmp (&pc->max_fee,
                               &acc_fee))
@@ -656,6 +714,12 @@ process_pay_with_exchange (void *cls,
                                                                  "overflow"));
       return;
     }
+    /* add wire fee contribution to the total */
+    if (GNUNET_OK ==
+        TALER_amount_add (&total_needed,
+                          &total_needed,
+                          &wire_fee_customer_contribution))
+
     /* check if total payment sufficies */
     if (-1 == TALER_amount_cmp (&acc_amount,
                                 &total_needed))
@@ -670,7 +734,40 @@ process_pay_with_exchange (void *cls,
   }
   else
   {
-    /* fees are acceptable, we cover them all; let's check the amount */
+    struct TALER_Amount deposit_fee_savings;
+
+    /* Compute how much the customer saved by not going to the
+       limit on the deposit fees, as this amount is counted against
+       what we expect him to cover for the wire fees */
+    GNUNET_assert (GNUNET_SYSERR !=
+                   TALER_amount_subtract (&deposit_fee_savings,
+                                          &pc->max_fee,
+                                          &acc_fee));
+    /* See how much of wire fee contribution is covered by fee_savings */
+    if (-1 == TALER_amount_cmp (&deposit_fee_savings,
+                                &wire_fee_customer_contribution))
+    {
+      /* wire_fee_customer_contribution > deposit_fee_savings */
+      GNUNET_assert (GNUNET_SYSERR !=
+                     TALER_amount_subtract (&wire_fee_customer_contribution,
+                                            &wire_fee_customer_contribution,
+                                            &deposit_fee_savings));
+      /* subtract remaining wire fees from total contribution */
+      if (GNUNET_SYSERR ==
+          TALER_amount_subtract (&acc_amount,
+                                 &acc_amount,
+                                 &wire_fee_customer_contribution))
+      {
+        GNUNET_break_op (0);
+        resume_pay_with_response (pc,
+                                  MHD_HTTP_METHOD_NOT_ACCEPTABLE,
+                                  TMH_RESPONSE_make_external_error 
(TALER_EC_PAY_PAYMENT_INSUFFICIENT_DUE_TO_FEES,
+                                                                    
"insufficient funds (including excessive exchange fees to be covered by 
customer)"));
+        return;
+      }
+    }
+
+    /* fees are acceptable, merchant covers them all; let's check the amount */
     if (-1 == TALER_amount_cmp (&acc_amount,
                                 &pc->amount))
     {
@@ -686,8 +783,6 @@ process_pay_with_exchange (void *cls,
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
               "Exchange and fee structure OK. Initiating deposit operation for 
coins\n");
 
-
-
   /* Initiate /deposit operation for all coins */
   for (i=0;i<pc->coins_cnt;i++)
   {
@@ -704,12 +799,11 @@ process_pay_with_exchange (void *cls,
                                      &dc->amount_with_fee,
                                      pc->wire_transfer_deadline,
                                      pc->mi->j_wire,
-                                     &pc->h_contract,
+                                     &pc->h_proposal_data,
                                      &dc->coin_pub,
                                      &dc->ub_sig,
                                      &dc->denom,
                                      pc->timestamp,
-                                     pc->transaction_id,
                                      &pc->mi->pubkey,
                                      pc->refund_deadline,
                                      &dc->coin_sig,
@@ -736,24 +830,21 @@ process_pay_with_exchange (void *cls,
 /**
  * Handle a timeout for the processing of the pay request.
  *
- * @param cls closure
+ * @param cls our `struct PayContext`
  */
 static void
 handle_pay_timeout (void *cls)
 {
   struct PayContext *pc = cls;
 
+  pc->timeout_task = NULL;
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
               "Resuming /pay with error after timeout\n");
-
-  pc->timeout_task = NULL;
-
   if (NULL != pc->fo)
   {
     TMH_EXCHANGES_find_exchange_cancel (pc->fo);
     pc->fo = NULL;
   }
-
   resume_pay_with_response (pc,
                             MHD_HTTP_SERVICE_UNAVAILABLE,
                             TMH_RESPONSE_make_internal_error 
(TALER_EC_PAY_EXCHANGE_TIMEOUT,
@@ -773,7 +864,7 @@ handle_pay_timeout (void *cls)
  */
 static void
 check_coin_paid (void *cls,
-                 uint64_t transaction_id,
+                 const struct GNUNET_HashCode *h_proposal_data,
                  const struct TALER_CoinSpendPublicKeyP *coin_pub,
                  const struct TALER_Amount *amount_with_fee,
                  const struct TALER_Amount *deposit_fee,
@@ -782,7 +873,9 @@ check_coin_paid (void *cls,
   struct PayContext *pc = cls;
   unsigned int i;
 
-  if (pc->transaction_id != transaction_id)
+  if (0 != memcmp (&pc->h_proposal_data,
+                   h_proposal_data,
+                   sizeof (struct GNUNET_HashCode)))
   {
     GNUNET_break (0);
     return;
@@ -811,7 +904,6 @@ check_coin_paid (void *cls,
  * @param transaction_id of the contract
  * @param merchant_pub merchant's public key
  * @param exchange_uri URI of the exchange
- * @param h_contract hash of the contract
  * @param h_xwire hash of our wire details
  * @param timestamp time of the confirmation
  * @param refund refund deadline
@@ -819,10 +911,9 @@ check_coin_paid (void *cls,
  */
 static void
 check_transaction_exists (void *cls,
-                         uint64_t transaction_id,
                          const struct TALER_MerchantPublicKeyP *merchant_pub,
                          const char *exchange_uri,
-                         const struct GNUNET_HashCode *h_contract,
+                         const struct GNUNET_HashCode *h_proposal_data,
                          const struct GNUNET_HashCode *h_xwire,
                          struct GNUNET_TIME_Absolute timestamp,
                          struct GNUNET_TIME_Absolute refund,
@@ -830,9 +921,9 @@ check_transaction_exists (void *cls,
 {
   struct PayContext *pc = cls;
 
-  if ( (0 == memcmp (h_contract,
-                    &pc->h_contract,
-                    sizeof (struct GNUNET_HashCode))) &&
+  if ( (0 == memcmp (h_proposal_data,
+                    &pc->h_proposal_data,
+                     sizeof (struct GNUNET_HashCode))) &&
        (0 == memcmp (h_xwire,
                     &pc->mi->h_wire,
                     sizeof (struct GNUNET_HashCode))) &&
@@ -850,277 +941,311 @@ check_transaction_exists (void *cls,
   }
 }
 
+
+// FIXME: declare in proper header!
 extern struct MerchantInstance *
 get_instance (struct json_t *json);
 
 
 /**
- * Accomplish this payment.
+ * Try to parse the pay request into the given pay context.
  *
- * @param rh context of the handler
- * @param connection the MHD connection to handle
- * @param[in,out] connection_cls the connection's closure
- *       (can be updated)
- * @param upload_data upload data
- * @param[in,out] upload_data_size number of bytes (left) in @a
- *       upload_data
- * @return MHD result code
+ * Schedules an error response in the connection on failure.
+ *
+ *
+ * @param connection HTTP connection we are receiving payment on
+ * @param root JSON upload with payment data
+ * @param pc context we use to handle the payment
+ * @return #GNUNET_OK on success,
+ *         #GNUNET_NO on failure (response was queued with MHD)
+ *         #GNUNET_SYSERR on hard error (MHD connection must be dropped)
  */
-int
-MH_handler_pay (struct TMH_RequestHandler *rh,
-               struct MHD_Connection *connection,
-               void **connection_cls,
-               const char *upload_data,
-               size_t *upload_data_size)
+static int
+parse_pay (struct MHD_Connection *connection,
+           const json_t *root,
+           struct PayContext *pc)
 {
-  struct PayContext *pc;
+  json_t *coins;
+  json_t *coin;
+  json_t *merchant;
+  unsigned int coins_index;
+  const char *chosen_exchange;
+  const char *order_id;
+  struct TALER_MerchantPublicKeyP merchant_pub;
   int res;
-  json_t *root;
-  struct GNUNET_TIME_Absolute now;
-
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-             "In handler for /pay.\n");
-  if (NULL == *connection_cls)
-  {
-    pc = GNUNET_new (struct PayContext);
-    pc->hc.cc = &pay_context_cleanup;
-    pc->connection = connection;
-    *connection_cls = pc;
-  }
-  else
+  struct GNUNET_JSON_Specification spec[] = {
+    GNUNET_JSON_spec_json ("coins", &coins),
+    GNUNET_JSON_spec_string ("exchange", &chosen_exchange),
+    GNUNET_JSON_spec_string ("order_id", &order_id),
+    GNUNET_JSON_spec_fixed_auto ("merchant_pub", &merchant_pub),
+    GNUNET_JSON_spec_end()
+  };
+
+  res = TMH_PARSE_json_data (connection,
+                             root,
+                             spec);
+  if (GNUNET_YES != res)
   {
-    /* not the first call, recover state */
-    pc = *connection_cls;
+    GNUNET_break (0);
+    return res;
   }
-  if (0 != pc->response_code)
+  res = db->find_proposal_data (db->cls,
+                                &pc->proposal_data,
+                                order_id,
+                                &merchant_pub);
+  if (GNUNET_OK != res)
   {
-    /* We are *done* processing the request, just queue the response (!) */
-    if (UINT_MAX == pc->response_code)
+    GNUNET_JSON_parse_free (spec);
+    if (MHD_YES !=
+        TMH_RESPONSE_reply_not_found (connection,
+                                      TALER_EC_PAY_DB_STORE_PAY_ERROR,
+                                      "Proposal not found"))
     {
       GNUNET_break (0);
-      return MHD_NO; /* hard error */
+      return GNUNET_SYSERR;
     }
-    res = MHD_queue_response (connection,
-                             pc->response_code,
-                             pc->response);
-    if (NULL != pc->response)
+    return GNUNET_NO;
+  }
+
+  if (GNUNET_OK !=
+      TALER_JSON_hash (pc->proposal_data,
+                       &pc->h_proposal_data))
+  {
+    GNUNET_JSON_parse_free (spec);
+    if (MHD_YES !=
+        TMH_RESPONSE_reply_internal_error (connection,
+                                           
TALER_EC_PAY_FAILED_COMPUTE_PROPOSAL_HASH,
+                                           "Failed to hash proposal"))
     {
-      MHD_destroy_response (pc->response);
-      pc->response = NULL;
+      GNUNET_break (0);
+      return GNUNET_SYSERR;
     }
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-               "Queueing response (%u) for /pay (%s).\n",
-               (unsigned int) pc->response_code,
-               res ? "OK" : "FAILED");
-    return res;
+    return GNUNET_NO;
   }
-  if (NULL != pc->chosen_exchange)
+
+  merchant = json_object_get (pc->proposal_data,
+                              "merchant");
+  if (NULL == merchant)
   {
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-               "Shouldn't be here. Old MHD version?\n");
-    return MHD_YES;
+    /* invalid contract */
+    GNUNET_break (0);
+    GNUNET_JSON_parse_free (spec);
+    if (MHD_YES !=
+        TMH_RESPONSE_reply_internal_error (connection,
+                                           TALER_EC_PAY_MERCHANT_FIELD_MISSING,
+                                           "No merchant field in contract"))
+    {
+      GNUNET_break (0);
+      return GNUNET_SYSERR;
+    }
+    return GNUNET_NO;
   }
-  res = TMH_PARSE_post_json (connection,
-                            &pc->json_parse_context,
-                            upload_data,
-                            upload_data_size,
-                            &root);
-  if (GNUNET_SYSERR == res)
+  pc->mi = get_instance (merchant);
+  if (NULL == pc->mi)
   {
-    GNUNET_break (0);
-    return TMH_RESPONSE_reply_invalid_json (connection);
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                "Unable to find the specified instance\n");
+    GNUNET_JSON_parse_free (spec);
+    if (MHD_NO == TMH_RESPONSE_reply_not_found (connection,
+                                                TALER_EC_PAY_INSTANCE_UNKNOWN,
+                                                "Unknown instance given"))
+    {
+      GNUNET_break (0);
+      return GNUNET_SYSERR;
+    }
+    return GNUNET_NO;
   }
-  if ((GNUNET_NO == res) || (NULL == root))
-    return MHD_YES; /* the POST's body has to be further fetched */
 
-  mi = get_instance (root);
+  GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+              "/pay: picked instance %s with key %s\n",
+              pc->mi->id,
+              GNUNET_STRINGS_data_to_string_alloc (&pc->mi->pubkey,
+                                                   sizeof (pc->mi->pubkey)));
 
-  /* Got the JSON upload, parse it */
+  pc->chosen_exchange = GNUNET_strdup (chosen_exchange);
   {
-    json_t *coins;
-    json_t *coin;
-    unsigned int coins_index;
-    struct TALER_MerchantSignatureP merchant_sig;
-    struct TALER_ContractPS cp;
-    const char *chosen_exchange;
-    struct GNUNET_JSON_Specification spec[] = {
-      TALER_JSON_spec_amount ("amount", &pc->amount),
-      GNUNET_JSON_spec_json ("coins", &coins),
-      GNUNET_JSON_spec_fixed_auto ("H_contract", &pc->h_contract),
-      TALER_JSON_spec_amount ("max_fee", &pc->max_fee),
-      GNUNET_JSON_spec_fixed_auto ("merchant_sig", &merchant_sig),
-      GNUNET_JSON_spec_string ("exchange", &chosen_exchange),
-      GNUNET_JSON_spec_absolute_time ("refund_deadline", &pc->refund_deadline),
-      GNUNET_JSON_spec_absolute_time ("pay_deadline", &pc->pay_deadline),
-      GNUNET_JSON_spec_absolute_time ("timestamp", &pc->timestamp),
-      GNUNET_JSON_spec_uint64 ("transaction_id", &pc->transaction_id),
+    struct GNUNET_JSON_Specification espec[] = {
+      GNUNET_JSON_spec_absolute_time ("refund_deadline",
+                                      &pc->refund_deadline),
+      GNUNET_JSON_spec_absolute_time ("pay_deadline",
+                                      &pc->pay_deadline),
+      GNUNET_JSON_spec_absolute_time ("timestamp",
+                                      &pc->timestamp),
+      TALER_JSON_spec_amount ("max_fee",
+                              &pc->max_fee),
+      TALER_JSON_spec_amount ("amount",
+                              &pc->amount),
+      GNUNET_JSON_spec_fixed_auto ("H_wire",
+                                   &pc->h_wire),
       GNUNET_JSON_spec_end()
     };
 
     res = TMH_PARSE_json_data (connection,
-                              root,
-                              spec);
+                               pc->proposal_data,
+                               espec);
     if (GNUNET_YES != res)
     {
-      json_decref (root);
+      GNUNET_JSON_parse_free (spec);
       GNUNET_break (0);
       return (GNUNET_NO == res) ? MHD_YES : MHD_NO;
     }
-    pc->mi = get_instance (root);
-    GNUNET_log (GNUNET_ERROR_TYPE_INFO,
-               "/pay: picked instance %s\n",
-               pc->mi->id);
 
-    if (NULL == pc->mi)
-    {
-      GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                 "Not able to find the specified instance\n");
-      json_decref (root);
-      return TMH_RESPONSE_reply_not_found (connection,
-                                          TALER_EC_PAY_INSTANCE_UNKNOWN,
-                                          "Unknown instance given");
-    }
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-               "The instance for this deposit is '%s', whose bank details are 
'%s'\n",
-               pc->mi->id,
-               json_dumps (pc->mi->j_wire,
-                           JSON_COMPACT));
-    pc->chosen_exchange = GNUNET_strdup (chosen_exchange);
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-               "Parsed JSON for /pay.\n");
-    cp.purpose.purpose = htonl (TALER_SIGNATURE_MERCHANT_CONTRACT);
-    cp.purpose.size = htonl (sizeof (struct TALER_ContractPS));
-    cp.transaction_id = GNUNET_htonll (pc->transaction_id);
-    TALER_amount_hton (&cp.total_amount,
-                      &pc->amount);
-    TALER_amount_hton (&cp.max_fee,
-                      &pc->max_fee);
-    cp.h_contract = pc->h_contract;
-    cp.merchant_pub = pc->mi->pubkey;
-    if (GNUNET_OK !=
-       GNUNET_CRYPTO_eddsa_verify (TALER_SIGNATURE_MERCHANT_CONTRACT,
-                                   &cp.purpose,
-                                   &merchant_sig.eddsa_sig,
-                                   &pc->mi->pubkey.eddsa_pub))
+    pc->wire_transfer_deadline
+      = GNUNET_TIME_absolute_add (pc->timestamp,
+                                  wire_transfer_delay);
+
+    if (pc->wire_transfer_deadline.abs_value_us < 
pc->refund_deadline.abs_value_us)
     {
       GNUNET_break (0);
       GNUNET_JSON_parse_free (spec);
-      json_decref (root);
       return TMH_RESPONSE_reply_external_error (connection,
-                                               
TALER_EC_PAY_MERCHANT_SIGNATURE_INVALID,
-                                               "invalid merchant signature 
supplied");
+                                                
TALER_EC_PAY_REFUND_DEADLINE_PAST_WIRE_TRANSFER_DEADLINE,
+                                                "refund deadline after wire 
transfer deadline");
     }
+  }
+
+  /* NOTE: In the future, iterate over all wire hashes
+     available to a given instance here! (#4939) */
+  if (0 != memcmp (&pc->h_wire,
+                   &pc->mi->h_wire,
+                   sizeof (struct GNUNET_HashCode)))
+  {
+    GNUNET_break (0);
+    GNUNET_JSON_parse_free (spec);
+    return TMH_RESPONSE_reply_internal_error (connection,
+                                              TALER_EC_PAY_WIRE_HASH_UNKNOWN,
+                                              "Did not find matching wire 
details");
+  }
+
+  /* parse optional details */
+  if (NULL != json_object_get (pc->proposal_data,
+                               "max_wire_fee"))
+  {
+    struct GNUNET_JSON_Specification espec[] = {
+      TALER_JSON_spec_amount ("max_wire_fee",
+                              &pc->max_wire_fee),
+      GNUNET_JSON_spec_end()
+    };
 
-    /* 'wire_transfer_deadline' is optional, if it is not present,
-       generate it here; it will be timestamp plus the
-       wire_transfer_delay supplied in config file */
-    if (NULL == json_object_get (root,
-                                "wire_transfer_deadline"))
+    res = TMH_PARSE_json_data (connection,
+                               pc->proposal_data,
+                               espec);
+    if (GNUNET_YES != res)
     {
-      pc->wire_transfer_deadline
-       = GNUNET_TIME_absolute_add (pc->timestamp,
-                                   wire_transfer_delay);
-      if (pc->wire_transfer_deadline.abs_value_us < 
pc->refund_deadline.abs_value_us)
-      {
-       /* Refund value very large, delay wire transfer accordingly */
-       pc->wire_transfer_deadline = pc->refund_deadline;
-      }
+      GNUNET_break_op (0); /* invalid input, use default */
+      /* default is we cover no fee */
+      GNUNET_assert (GNUNET_OK ==
+                     TALER_amount_get_zero (pc->max_fee.currency,
+                                            &pc->max_wire_fee));
     }
-    else
+  }
+  else
+  {
+    /* default is we cover no fee */
+    GNUNET_assert (GNUNET_OK ==
+                   TALER_amount_get_zero (pc->max_fee.currency,
+                                          &pc->max_wire_fee));
+  }
+  if (NULL != json_object_get (pc->proposal_data,
+                               "wire_fee_amortization"))
+  {
+    struct GNUNET_JSON_Specification espec[] = {
+      GNUNET_JSON_spec_uint32 ("wire_fee_amortization",
+                              &pc->wire_fee_amortization),
+      GNUNET_JSON_spec_end()
+    };
+
+    res = TMH_PARSE_json_data (connection,
+                               pc->proposal_data,
+                               espec);
+    if ( (GNUNET_YES != res) ||
+         (0 == pc->wire_fee_amortization) )
     {
-      struct GNUNET_JSON_Specification espec[] = {
-       GNUNET_JSON_spec_absolute_time ("wire_transfer_deadline",
-                                       &pc->wire_transfer_deadline),
-       GNUNET_JSON_spec_end()
-      };
-
-      res = TMH_PARSE_json_data (connection,
-                                root,
-                                espec);
-      if (GNUNET_YES != res)
-      {
-       GNUNET_JSON_parse_free (spec);
-       json_decref (root);
-       GNUNET_break (0);
-       return (GNUNET_NO == res) ? MHD_YES : MHD_NO;
-      }
-      if (pc->wire_transfer_deadline.abs_value_us < 
pc->refund_deadline.abs_value_us)
-      {
-       GNUNET_break (0);
-       GNUNET_JSON_parse_free (spec);
-       json_decref (root);
-       return TMH_RESPONSE_reply_external_error (connection,
-                                                 
TALER_EC_PAY_REFUND_DEADLINE_PAST_WIRE_TRANSFER_DEADLINE,
-                                                 "refund deadline after wire 
transfer deadline");
-      }
+      GNUNET_break_op (0); /* invalid input, use default */
+      /* default is no amortization */
+      pc->wire_fee_amortization = 1;
     }
+  }
+  else
+  {
+    pc->wire_fee_amortization = 1;
+  }
+
+  pc->coins_cnt = json_array_size (coins);
+  if (0 == pc->coins_cnt)
+  {
+    GNUNET_JSON_parse_free (spec);
+    return TMH_RESPONSE_reply_arg_invalid (connection,
+                                           TALER_EC_PAY_COINS_ARRAY_EMPTY,
+                                           "coins");
+  }
+  /* note: 1 coin = 1 deposit confirmation expected */
+  pc->dc = GNUNET_new_array (pc->coins_cnt,
+                             struct DepositConfirmation);
 
+  /* This loop populates the array 'dc' in 'pc' */
+  json_array_foreach (coins, coins_index, coin)
+  {
+    struct DepositConfirmation *dc = &pc->dc[coins_index];
+    struct GNUNET_JSON_Specification spec[] = {
+      TALER_JSON_spec_denomination_public_key ("denom_pub", &dc->denom),
+      TALER_JSON_spec_amount ("f" /* FIXME */, &dc->amount_with_fee),
+      GNUNET_JSON_spec_fixed_auto ("coin_pub", &dc->coin_pub),
+      TALER_JSON_spec_denomination_signature ("ub_sig", &dc->ub_sig),
+      GNUNET_JSON_spec_fixed_auto ("coin_sig", &dc->coin_sig),
+      GNUNET_JSON_spec_end()
+    };
 
-    pc->coins_cnt = json_array_size (coins);
-    if (0 == pc->coins_cnt)
+    res = TMH_PARSE_json_data (connection,
+                               coin,
+                               spec);
+    if (GNUNET_YES != res)
     {
       GNUNET_JSON_parse_free (spec);
-      json_decref (root);
-      return TMH_RESPONSE_reply_arg_invalid (connection,
-                                            TALER_EC_PAY_COINS_ARRAY_EMPTY,
-                                            "coins");
+      GNUNET_break (0);
+      return (GNUNET_NO == res) ? MHD_YES : MHD_NO;
     }
-    /* note: 1 coin = 1 deposit confirmation expected */
-    pc->dc = GNUNET_new_array (pc->coins_cnt,
-                              struct DepositConfirmation);
 
-    /* This loop populates the array 'dc' in 'pc' */
-    json_array_foreach (coins, coins_index, coin)
-    {
-      struct DepositConfirmation *dc = &pc->dc[coins_index];
-      struct GNUNET_JSON_Specification spec[] = {
-       TALER_JSON_spec_denomination_public_key ("denom_pub", &dc->denom),
-       TALER_JSON_spec_amount ("f" /* FIXME */, &dc->amount_with_fee),
-       GNUNET_JSON_spec_fixed_auto ("coin_pub", &dc->coin_pub),
-       TALER_JSON_spec_denomination_signature ("ub_sig", &dc->ub_sig),
-       GNUNET_JSON_spec_fixed_auto ("coin_sig", &dc->coin_sig),
-       GNUNET_JSON_spec_end()
-      };
-
-      res = TMH_PARSE_json_data (connection,
-                                coin,
-                                spec);
-      if (GNUNET_YES != res)
-      {
-       GNUNET_JSON_parse_free (spec);
-       json_decref (root);
-       GNUNET_break (0);
-       return (GNUNET_NO == res) ? MHD_YES : MHD_NO;
-      }
-
-      {
-       char *s;
-
-       s = TALER_amount_to_string (&dc->amount_with_fee);
-       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                   "Coin #%i has f %s\n",
-                   coins_index,
-                   s);
-       GNUNET_free (s);
-     }
-
-      dc->index = coins_index;
-      dc->pc = pc;
-    }
-    GNUNET_JSON_parse_free (spec);
-  } /* end of parsing of JSON upload */
+    dc->index = coins_index;
+    dc->pc = pc;
+  }
   pc->pending = pc->coins_cnt;
+  GNUNET_JSON_parse_free (spec);
+  return GNUNET_OK;
+}
+
+
+/**
+ * Process a payment for a proposal.
+ *
+ * @param connection HTTP connection we are receiving payment on
+ * @param root JSON upload with payment data
+ * @param pc context we use to handle the payment
+ * @return value to return to MHD (#MHD_NO to drop connection,
+ *         #MHD_YES to keep handling it)
+ */
+static int
+handler_pay_json (struct MHD_Connection *connection,
+                  const json_t *root,
+                  struct PayContext *pc)
+{
+  int ret;
+
+  ret = parse_pay (connection,
+                   root,
+                   pc);
+  if (GNUNET_OK != ret)
+    return (GNUNET_NO == ret) ? MHD_YES : MHD_NO;
 
   /* Check if this payment attempt has already succeeded */
   if (GNUNET_SYSERR ==
       db->find_payments (db->cls,
-                        pc->transaction_id,
+                        &pc->h_proposal_data,
                          &pc->mi->pubkey,
                         &check_coin_paid,
                         pc))
   {
     GNUNET_break (0);
-    json_decref (root);
     return TMH_RESPONSE_reply_internal_error (connection,
                                              
TALER_EC_PAY_DB_FETCH_TRANSACTION_ERROR,
                                              "Merchant database error");
@@ -1137,21 +1262,19 @@ MH_handler_pay (struct TMH_RequestHandler *rh,
                                            MHD_RESPMEM_PERSISTENT);
     ret = MHD_queue_response (connection,
                              MHD_HTTP_OK,
-                             resp);
+                             sign_success_response (pc));
     MHD_destroy_response (resp);
-    json_decref (root);
     return ret;
   }
   /* Check if transaction is already known, if not store it. */
   if (GNUNET_SYSERR ==
       db->find_transaction (db->cls,
-                           pc->transaction_id,
+                           &pc->h_proposal_data,
                            &pc->mi->pubkey,
                            &check_transaction_exists,
                             pc))
   {
     GNUNET_break (0);
-    json_decref (root);
     return TMH_RESPONSE_reply_internal_error (connection,
                                              
TALER_EC_PAY_DB_FETCH_TRANSACTION_ERROR,
                                                "Merchant database error");
@@ -1159,14 +1282,17 @@ MH_handler_pay (struct TMH_RequestHandler *rh,
   if (GNUNET_SYSERR == pc->transaction_exits)
   {
     GNUNET_break (0);
-    json_decref (root);
     return TMH_RESPONSE_reply_external_error (connection,
                                               
TALER_EC_PAY_DB_TRANSACTION_ID_CONFLICT,
                                              "Transaction ID reused with 
different transaction details");
   }
   if (GNUNET_NO == pc->transaction_exits)
   {
-    /* #4521 goes here: Check if the customer respects pay_deadline */
+    struct GNUNET_TIME_Absolute now;
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "Dealing with new transaction '%s'\n",
+                GNUNET_h2s (&pc->h_proposal_data));
+
     now = GNUNET_TIME_absolute_get ();
     if (now.abs_value_us > pc->pay_deadline.abs_value_us)
     {
@@ -1183,19 +1309,20 @@ MH_handler_pay (struct TMH_RequestHandler *rh,
                                              "The time to pay for this 
contract has expired.");
     }
 
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "Storing transaction '%s'\n",
+                GNUNET_h2s (&pc->h_proposal_data));
     if (GNUNET_OK !=
         db->store_transaction (db->cls,
-                               pc->transaction_id,
+                               &pc->h_proposal_data,
                                &pc->mi->pubkey,
                                pc->chosen_exchange,
-                               &pc->h_contract,
                                &pc->mi->h_wire,
                                pc->timestamp,
                                pc->refund_deadline,
                                &pc->amount))
     {
       GNUNET_break (0);
-      json_decref (root);
       return TMH_RESPONSE_reply_internal_error (connection,
                                                
TALER_EC_PAY_DB_STORE_TRANSACTION_ERROR,
                                                "Merchant database error");
@@ -1206,6 +1333,7 @@ MH_handler_pay (struct TMH_RequestHandler *rh,
 
   /* Find the responsible exchange, this may take a while... */
   pc->fo = TMH_EXCHANGES_find_exchange (pc->chosen_exchange,
+                                        pc->mi->wire_method,
                                         &process_pay_with_exchange,
                                         pc);
 
@@ -1218,7 +1346,94 @@ MH_handler_pay (struct TMH_RequestHandler *rh,
   pc->timeout_task = GNUNET_SCHEDULER_add_delayed (PAY_TIMEOUT,
                                                    &handle_pay_timeout,
                                                    pc);
+  return MHD_YES;
+}
+
+
+/**
+ * Process a payment for a proposal.
+ * Takes data from the given MHD connection.
+ *
+ * @param rh context of the handler
+ * @param connection the MHD connection to handle
+ * @param[in,out] connection_cls the connection's closure
+ *       (can be updated)
+ * @param upload_data upload data
+ * @param[in,out] upload_data_size number of bytes (left) in @a
+ *       upload_data
+ * @return MHD result code
+ */
+int
+MH_handler_pay (struct TMH_RequestHandler *rh,
+               struct MHD_Connection *connection,
+               void **connection_cls,
+               const char *upload_data,
+               size_t *upload_data_size)
+{
+  struct PayContext *pc;
+  int res;
+  json_t *root;
+
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+             "In handler for /pay.\n");
+  if (NULL == *connection_cls)
+  {
+    pc = GNUNET_new (struct PayContext);
+    pc->hc.cc = &pay_context_cleanup;
+    pc->connection = connection;
+    *connection_cls = pc;
+  }
+  else
+  {
+    /* not the first call, recover state */
+    pc = *connection_cls;
+  }
+  if (0 != pc->response_code)
+  {
+    /* We are *done* processing the request, just queue the response (!) */
+    if (UINT_MAX == pc->response_code)
+    {
+      GNUNET_break (0);
+      return MHD_NO; /* hard error */
+    }
+    res = MHD_queue_response (connection,
+                             pc->response_code,
+                             pc->response);
+    MHD_destroy_response (pc->response);
+    pc->response = NULL;
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+               "Queueing response (%u) for /pay (%s).\n",
+               (unsigned int) pc->response_code,
+               res ? "OK" : "FAILED");
+    return res;
+  }
+  if (NULL != pc->chosen_exchange)
+  {
+    // FIXME: explain in comment why this could happen!
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+               "Shouldn't be here. Old MHD version?\n");
+    return MHD_YES;
+  }
+  res = TMH_PARSE_post_json (connection,
+                            &pc->json_parse_context,
+                            upload_data,
+                            upload_data_size,
+                            &root);
+  if (GNUNET_SYSERR == res)
+  {
+    GNUNET_break (0);
+    return TMH_RESPONSE_reply_invalid_json (connection);
+  }
+  if ( (GNUNET_NO == res) ||
+       (NULL == root) )
+    return MHD_YES; /* the POST's body has to be further fetched */
+
+  res = handler_pay_json (connection,
+                          root,
+                          pc);
   json_decref (root);
+  if (GNUNET_SYSERR == res)
+    return MHD_NO;
   return MHD_YES;
 }
 
diff --git a/src/backend/taler-merchant-httpd_proposal.c 
b/src/backend/taler-merchant-httpd_proposal.c
new file mode 100644
index 0000000..0d96a1f
--- /dev/null
+++ b/src/backend/taler-merchant-httpd_proposal.c
@@ -0,0 +1,451 @@
+/*
+  This file is part of TALER
+  (C) 2014, 2015, 2016 INRIA
+
+  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
+  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 backend/taler-merchant-httpd_propose.c
+ * @brief HTTP serving layer mainly intended to communicate with the frontend
+ * @author Marcello Stanisci
+ */
+#include "platform.h"
+#include <jansson.h>
+#include <taler/taler_signatures.h>
+#include <taler/taler_json_lib.h>
+#include "taler-merchant-httpd.h"
+#include "taler-merchant-httpd_parsing.h"
+#include "taler-merchant-httpd_auditors.h"
+#include "taler-merchant-httpd_exchanges.h"
+#include "taler-merchant-httpd_responses.h"
+
+
+/**
+ * Check that the given JSON array of products is well-formed.
+ *
+ * @param products JSON array to check
+ * @return #GNUNET_OK if all is fine
+ */
+static int
+check_products (json_t *products)
+{
+  size_t index;
+  json_t *value;
+  int res;
+
+  if (! json_is_array (products))
+  {
+    GNUNET_break (0);
+    return GNUNET_SYSERR;
+  }
+  json_array_foreach (products, index, value) {
+    const char *description;
+    const char *error_name;
+    unsigned int error_line;
+    struct GNUNET_JSON_Specification spec[] = {
+      GNUNET_JSON_spec_string ("description", &description),
+      /* FIXME: there are other fields in the product specification
+         that are currently not labeled as optional. Maybe check
+         those as well, or make them truly optional. */
+      GNUNET_JSON_spec_end()
+    };
+
+    /* extract fields we need to sign separately */
+    res = GNUNET_JSON_parse (value,
+                             spec,
+                             &error_name,
+                             &error_line);
+    if (GNUNET_OK != res)
+    {
+      GNUNET_break (0);
+      GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                  "Product description parsing failed at #%u: %s:%u\n",
+                  (unsigned int) index,
+                  error_name,
+                  error_line);
+      return GNUNET_SYSERR;
+    }
+    GNUNET_JSON_parse_free (spec);
+  }
+  return GNUNET_OK;
+}
+
+
+/**
+ * Information we keep for individual calls
+ * to requests that parse JSON, but keep no other state.
+ */
+struct TMH_JsonParseContext
+{
+
+  /**
+   * This field MUST be first.
+   * FIXME: Explain why!
+   */
+  struct TM_HandlerContext hc;
+
+  /**
+   * Placeholder for #TMH_PARSE_post_json() to keep its internal state.
+   */
+  void *json_parse_context;
+};
+
+
+/**
+ * Custom cleanup routine for a `struct TMH_JsonParseContext`.
+ *
+ * @param hc the `struct TMH_JsonParseContext` to clean up.
+ */
+static void
+json_parse_cleanup (struct TM_HandlerContext *hc)
+{
+  struct TMH_JsonParseContext *jpc = (struct TMH_JsonParseContext *) hc;
+
+  TMH_PARSE_post_cleanup_callback (jpc->json_parse_context);
+  GNUNET_free (jpc);
+}
+
+
+extern struct MerchantInstance *
+get_instance (struct json_t *json);
+
+
+/**
+ * Transform an order into a proposal and store it in the database.
+ * Write the resulting proposal or an error message ot a MHD connection
+ *
+ * @param connection connection to write the result or error to
+ * @param order to process
+ * @return MHD result code
+ */
+static int
+proposal_put (struct MHD_Connection *connection,
+              json_t *order)
+{
+  int res;
+  struct MerchantInstance *mi;
+  struct TALER_ProposalDataPS pdps;
+  struct GNUNET_CRYPTO_EddsaSignature merchant_sig;
+  struct TALER_Amount total;
+  struct TALER_Amount max_fee;
+  const char *order_id;
+  json_t *products;
+  json_t *merchant;
+  struct GNUNET_TIME_Absolute timestamp;
+  struct GNUNET_TIME_Absolute refund_deadline;
+  struct GNUNET_TIME_Absolute pay_deadline;
+  struct GNUNET_JSON_Specification spec[] = {
+    TALER_JSON_spec_amount ("amount", &total),
+    GNUNET_JSON_spec_string ("order_id", &order_id),
+    TALER_JSON_spec_amount ("max_fee", &max_fee),
+    /* The following entries we don't actually need, except to check that
+       the order is well-formed */
+    GNUNET_JSON_spec_json ("products", &products),
+    GNUNET_JSON_spec_json ("merchant", &merchant),
+    GNUNET_JSON_spec_absolute_time ("timestamp", &timestamp),
+    GNUNET_JSON_spec_absolute_time ("refund_deadline", &refund_deadline),
+    GNUNET_JSON_spec_absolute_time ("pay_deadline", &pay_deadline),
+    GNUNET_JSON_spec_end ()
+  };
+
+
+  /* Add order_id if it doesn't exist. */
+
+  if (NULL == json_string_value (json_object_get (order, "order_id")))
+  {
+    char buf[256];
+    time_t timer;
+    struct tm* tm_info;
+    size_t off;
+
+    time (&timer);
+    tm_info = localtime (&timer);
+
+    off = strftime (buf,
+                    sizeof (buf),
+                    "%H:%M:%S",
+                    tm_info);
+    snprintf (buf + off, sizeof (buf) - off,
+              "-%llX",
+              (long long unsigned) GNUNET_CRYPTO_random_u64 
(GNUNET_CRYPTO_QUALITY_WEAK,
+                                                             UINT64_MAX));
+    json_object_set (order,
+                     "order_id",
+                     json_string (buf));
+  }
+
+  if (NULL == json_object_get (order,
+                               "timestamp"))
+  {
+    struct GNUNET_TIME_Absolute now = GNUNET_TIME_absolute_get ();
+
+    (void) GNUNET_TIME_round_abs (&now);
+    json_object_set (order,
+                     "timestamp",
+                     GNUNET_JSON_from_time_abs (now));
+  }
+
+  if (NULL == json_object_get (order,
+                               "refund_deadline"))
+  {
+    struct GNUNET_TIME_Absolute zero = { 0 };
+
+    json_object_set (order,
+                     "refund_deadline",
+                     GNUNET_JSON_from_time_abs (zero));
+  }
+
+  if (NULL == json_object_get (order,
+                               "pay_deadline"))
+  {
+    struct GNUNET_TIME_Absolute t;
+
+    /* FIXME: read the delay for pay_deadline from config */
+    t = GNUNET_TIME_relative_to_absolute (GNUNET_TIME_UNIT_HOURS);
+    (void) GNUNET_TIME_round_abs (&t);
+    json_object_set (order, "pay_deadline", GNUNET_JSON_from_time_abs (t));
+  }
+
+  if (NULL == json_object_get (order,
+                               "max_wire_fee"))
+  {
+    json_object_set (order,
+                     "max_wire_fee",
+                     TALER_JSON_from_amount (&default_max_wire_fee));
+  }
+
+  if (NULL == json_object_get (order,
+                               "wire_fee_amortization"))
+  {
+    json_object_set (order,
+                     "wire_fee_amortization",
+                     json_integer ((json_int_t) 
default_wire_fee_amortization));
+  }
+
+  /* extract fields we need to sign separately */
+  res = TMH_PARSE_json_data (connection, order, spec);
+  if (GNUNET_NO == res)
+  {
+    return MHD_YES;
+  }
+  if (GNUNET_SYSERR == res)
+  {
+    return TMH_RESPONSE_reply_internal_error (connection,
+                                             TALER_EC_NONE,
+                                             "Impossible to parse the order");
+  }
+
+
+  /* check contract is well-formed */
+  if (GNUNET_OK != check_products (products))
+  {
+    GNUNET_JSON_parse_free (spec);
+    return TMH_RESPONSE_reply_arg_invalid (connection,
+                                          TALER_EC_PARAMETER_MALFORMED,
+                                          "order:products");
+  }
+
+  mi = get_instance (merchant);
+  if (NULL == mi)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                "Not able to find the specified instance\n");
+    return TMH_RESPONSE_reply_not_found (connection,
+                                        TALER_EC_CONTRACT_INSTANCE_UNKNOWN,
+                                        "Unknown instance given");
+  }
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Signing contract on behalf of instance '%s'\n",
+              mi->id);
+  /* add fields to the contract that the backend should provide */
+  json_object_set (order,
+                   "exchanges",
+                   trusted_exchanges);
+  json_object_set (order,
+                   "auditors",
+                   j_auditors);
+  json_object_set_new (order,
+                       "H_wire",
+                      GNUNET_JSON_from_data_auto (&mi->h_wire));
+  json_object_set_new (order,
+                       "merchant_pub",
+                      GNUNET_JSON_from_data_auto (&mi->pubkey));
+
+  /* create proposal signature */
+  pdps.purpose.purpose = htonl (TALER_SIGNATURE_MERCHANT_CONTRACT);
+  pdps.purpose.size = htonl (sizeof (pdps));
+  GNUNET_assert (GNUNET_OK ==
+                 TALER_JSON_hash (order,
+                                  &pdps.hash));
+
+  GNUNET_CRYPTO_eddsa_sign (&mi->privkey.eddsa_priv,
+                            &pdps.purpose,
+                            &merchant_sig);
+
+  /* fetch timestamp from order */
+
+  if (GNUNET_OK !=
+      db->insert_proposal_data (db->cls,
+                                order_id,
+                                &mi->pubkey,
+                                timestamp,
+                                order))
+  {
+    GNUNET_JSON_parse_free (spec);
+    return TMH_RESPONSE_reply_internal_error (connection,
+                                              TALER_EC_PROPOSAL_STORE_DB_ERROR,
+                                              "db error: could not store this 
proposal's data into db");
+  }
+
+
+  res = TMH_RESPONSE_reply_json_pack (connection,
+                                      MHD_HTTP_OK,
+                                      "{s:O, s:o s:o}",
+                                      "data", order,
+                                      "sig", GNUNET_JSON_from_data_auto 
(&merchant_sig),
+                                      "hash", GNUNET_JSON_from_data_auto 
(&pdps.hash));
+  GNUNET_JSON_parse_free (spec);
+  return res;
+}
+
+
+/**
+ * Generate a proposal, given its order. In practical terms, it adds the
+ * fields  'exchanges', 'merchant_pub', and 'H_wire' to the order gotten
+ * from the frontend. Finally, it signs this data, and returns it to the
+ * frontend.
+ *
+ * @param connection the MHD connection to handle
+ * @param[in,out] connection_cls the connection's closure (can be updated)
+ * @param upload_data upload data
+ * @param[in,out] upload_data_size number of bytes (left) in @a upload_data
+ * @return MHD result code
+ */
+int
+MH_handler_proposal_put (struct TMH_RequestHandler *rh,
+                         struct MHD_Connection *connection,
+                         void **connection_cls,
+                         const char *upload_data,
+                         size_t *upload_data_size)
+{
+  int res;
+  struct TMH_JsonParseContext *ctx;
+
+  if (NULL == *connection_cls)
+  {
+    ctx = GNUNET_new (struct TMH_JsonParseContext);
+    ctx->hc.cc = &json_parse_cleanup;
+    *connection_cls = ctx;
+  }
+  else
+  {
+    ctx = *connection_cls;
+  }
+
+  json_t *root;
+
+  res = TMH_PARSE_post_json (connection,
+                             &ctx->json_parse_context,
+                             upload_data,
+                             upload_data_size,
+                             &root);
+  if (GNUNET_SYSERR == res)
+    return MHD_NO;
+  /* the POST's body has to be further fetched */
+  if ((GNUNET_NO == res) || (NULL == root))
+    return MHD_YES;
+
+  json_t *order = json_object_get (root, "order");
+
+  if (NULL == order)
+  {
+    res = TMH_RESPONSE_reply_arg_missing (connection,
+                                          TALER_EC_PARAMETER_MISSING,
+                                         "order");
+  }
+  else
+  {
+    res = proposal_put (connection, order);
+  }
+  json_decref (root);
+  return res;
+}
+
+
+/**
+ * Manage a GET /proposal request. Query the db and returns the
+ * proposal's data related to the transaction id given as the URL's
+ * parameter.
+ *
+ * @param rh context of the handler
+ * @param connection the MHD connection to handle
+ * @param[in,out] connection_cls the connection's closure (can be updated)
+ * @param upload_data upload data
+ * @param[in,out] upload_data_size number of bytes (left) in @a upload_data
+ * @return MHD result code
+ */
+int
+MH_handler_proposal_lookup (struct TMH_RequestHandler *rh,
+                            struct MHD_Connection *connection,
+                            void **connection_cls,
+                            const char *upload_data,
+                            size_t *upload_data_size)
+{
+  const char *order_id;
+  const char *instance;
+  int res;
+  json_t *proposal_data;
+  struct MerchantInstance *mi;
+
+  instance = MHD_lookup_connection_value (connection,
+                                          MHD_GET_ARGUMENT_KIND,
+                                          "instance");
+  if (NULL == instance)
+    return TMH_RESPONSE_reply_arg_missing (connection,
+                                          TALER_EC_PARAMETER_MISSING,
+                                           "instance");
+
+  mi = TMH_lookup_instance (instance);
+  GNUNET_assert (NULL != mi);
+
+  order_id = MHD_lookup_connection_value (connection,
+                                          MHD_GET_ARGUMENT_KIND,
+                                          "order_id");
+  if (NULL == order_id)
+    return TMH_RESPONSE_reply_arg_missing (connection,
+                                          TALER_EC_PARAMETER_MISSING,
+                                           "order_id");
+
+  res = db->find_proposal_data (db->cls,
+                                &proposal_data,
+                                order_id,
+                                &mi->pubkey);
+  if (GNUNET_NO == res)
+    return TMH_RESPONSE_reply_not_found (connection,
+                                         TALER_EC_PROPOSAL_LOOKUP_NOT_FOUND,
+                                         "unknown transaction id");
+
+  if (GNUNET_SYSERR == res)
+    return TMH_RESPONSE_reply_internal_error (connection,
+                                              
TALER_EC_PROPOSAL_LOOKUP_DB_ERROR,
+                                              "An error occurred while 
retrieving proposal data from db");
+
+
+  return TMH_RESPONSE_reply_json (connection,
+                                  proposal_data,
+                                  MHD_HTTP_OK);
+
+
+}
+
+
+/* end of taler-merchant-httpd_contract.c */
diff --git a/src/backend/taler-merchant-httpd_map.h 
b/src/backend/taler-merchant-httpd_proposal.h
similarity index 51%
copy from src/backend/taler-merchant-httpd_map.h
copy to src/backend/taler-merchant-httpd_proposal.h
index de9150a..fe5b319 100644
--- a/src/backend/taler-merchant-httpd_map.h
+++ b/src/backend/taler-merchant-httpd_proposal.h
@@ -1,9 +1,9 @@
 /*
   This file is part of TALER
-  (C) 2014, 2015, 2016 INRIA
+  (C) 2014, 2015 INRIA
 
   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
+  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
@@ -14,22 +14,21 @@
   TALER; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
 */
 /**
- * @file backend/taler-merchant-httpd_contract.c
- * @brief HTTP serving layer mainly intended to communicate with the frontend
+ * @file backend/taler-merchant-httpd_propose.h
+ * @brief headers for /contract handler
  * @author Marcello Stanisci
  */
-
-#ifndef TALER_MERCHANT_HTTPD_MAP_H
-#define TALER_MERCHANT_HTTPD_MAP_H
+#ifndef TALER_MERCHANT_HTTPD_CONTRACT_H
+#define TALER_MERCHANT_HTTPD_CONTRACT_H
 #include <microhttpd.h>
 #include "taler-merchant-httpd.h"
 
-
 /**
- * Manage a /map/in request. Store in db a plain text contract
- * and its hashcode.
+ * Generate a proposal, given its order. In practical terms, it adds the
+ * fields  'exchanges', 'merchant_pub', and 'H_wire' to the order gotten
+ * from the frontend. Finally, it signs this data, and returns it to the
+ * frontend.
  *
- * @param rh context of the handler
  * @param connection the MHD connection to handle
  * @param[in,out] connection_cls the connection's closure (can be updated)
  * @param upload_data upload data
@@ -37,16 +36,17 @@
  * @return MHD result code
  */
 int
-MH_handler_map_in (struct TMH_RequestHandler *rh,
-                   struct MHD_Connection *connection,
-                   void **connection_cls,
-                   const char *upload_data,
-                   size_t *upload_data_size);
+MH_handler_proposal_put (struct TMH_RequestHandler *rh,
+                         struct MHD_Connection *connection,
+                         void **connection_cls,
+                         const char *upload_data,
+                         size_t *upload_data_size);
 
 
 /**
- * Manage a /map/out request. Query the db and returns a plain
- * text contract associated with the hashcode given as input
+ * Manage a GET /proposal request. Query the db and returns the
+ * proposal's data related to the transaction id given as the URL's
+ * parameter.
  *
  * @param rh context of the handler
  * @param connection the MHD connection to handle
@@ -56,11 +56,9 @@ MH_handler_map_in (struct TMH_RequestHandler *rh,
  * @return MHD result code
  */
 int
-MH_handler_map_out (struct TMH_RequestHandler *rh,
-                    struct MHD_Connection *connection,
-                    void **connection_cls,
-                    const char *upload_data,
-                    size_t *upload_data_size);
-
-/* end of taler-merchant-httpd_history.c */
+MH_handler_proposal_lookup (struct TMH_RequestHandler *rh,
+                            struct MHD_Connection *connection,
+                            void **connection_cls,
+                            const char *upload_data,
+                            size_t *upload_data_size);
 #endif
diff --git a/src/backend/taler-merchant-httpd_responses.c 
b/src/backend/taler-merchant-httpd_responses.c
index 9c7ef8a..8cbdf6b 100644
--- a/src/backend/taler-merchant-httpd_responses.c
+++ b/src/backend/taler-merchant-httpd_responses.c
@@ -411,33 +411,31 @@ TMH_RESPONSE_make_track_transaction_ok (unsigned int 
num_transfers,
   struct MHD_Response *ret;
   unsigned int i;
   json_t *j_transfers;
+  struct TALER_Amount sum;
 
   j_transfers = json_array ();
   for (i=0;i<num_transfers;i++)
   {
     const struct TALER_MERCHANT_TransactionWireTransfer *transfer = 
&transfers[i];
-    json_t *j_coins;
     unsigned int j;
 
-    j_coins = json_array ();
-    for (j=0;j<transfer->num_coins;j++)
+    sum = transfer->coins[0].amount_with_fee;
+    for (j=1;j<transfer->num_coins;j++)
     {
       const struct TALER_MERCHANT_CoinWireTransfer *coin = &transfer->coins[j];
 
-      GNUNET_assert (0 ==
-                     json_array_append_new (j_coins,
-                                            json_pack ("{s:o, s:o, s:o}",
-                                                       "coin_pub", 
GNUNET_JSON_from_data_auto (&coin->coin_pub),
-                                                       "amount_with_fee", 
TALER_JSON_from_amount (&coin->amount_with_fee),
-                                                       "deposit_fee", 
TALER_JSON_from_amount (&coin->deposit_fee))));
+      GNUNET_assert (GNUNET_SYSERR != TALER_amount_add (&sum,
+                                                        &sum,
+                                                        
&coin->amount_with_fee));
     }
+
     GNUNET_assert (0 ==
                    json_array_append_new (j_transfers,
                                           json_pack ("{s:s, s:o, s:o, s:o}",
                                                      "exchange", exchange_uri,
                                                      "wtid", 
GNUNET_JSON_from_data_auto (&transfer->wtid),
                                                      "execution_time", 
GNUNET_JSON_from_time_abs (transfer->execution_time),
-                                                     "coins", j_coins)));
+                                                     "amount", 
TALER_JSON_from_amount (&sum))));
   }
   ret = TMH_RESPONSE_make_json (j_transfers);
   json_decref (j_transfers);
diff --git a/src/backend/taler-merchant-httpd_track-transaction.c 
b/src/backend/taler-merchant-httpd_track-transaction.c
index edf323f..9f6e6d1 100644
--- a/src/backend/taler-merchant-httpd_track-transaction.c
+++ b/src/backend/taler-merchant-httpd_track-transaction.c
@@ -185,11 +185,6 @@ struct TrackTransactionContext
   struct GNUNET_HashCode h_wire;
 
   /**
-   * Hash of the contract.
-   */
-  struct GNUNET_HashCode h_contract;
-
-  /**
    * Timestamp of the transaction.
    */
   struct GNUNET_TIME_Absolute timestamp;
@@ -207,7 +202,12 @@ struct TrackTransactionContext
   /**
    * Transaction this request is about.
    */
-  uint64_t transaction_id;
+  const char *transaction_id;
+
+  /**
+   *  Proposal's hashcode.
+   */
+  struct GNUNET_HashCode h_proposal_data;
 
   /**
    * Response code to return upon resume.
@@ -340,6 +340,7 @@ trace_coins (struct TrackTransactionContext *tctx);
  *             not provide any (set only if @a http_status is #MHD_HTTP_OK)
  * @param total_amount total amount of the wire transfer, or NULL if the 
exchange could
  *             not provide any @a wtid (set only if @a http_status is 
#MHD_HTTP_OK)
+ * @param wire_fee wire fee that was charged by the exchange
  * @param details_length length of the @a details array
  * @param details array with details about the combined transactions
  */
@@ -352,6 +353,7 @@ wire_deposits_cb (void *cls,
                   const struct GNUNET_HashCode *h_wire,
                   struct GNUNET_TIME_Absolute execution_time,
                   const struct TALER_Amount *total_amount,
+                  const struct TALER_Amount *wire_fee,
                   unsigned int details_length,
                   const struct TALER_TrackTransferDetails *details)
 {
@@ -402,7 +404,7 @@ wire_deposits_cb (void *cls,
 
       if (GNUNET_OK !=
           db->store_coin_to_transfer (db->cls,
-                                      details[i].transaction_id,
+                                      &details[i].h_proposal_data,
                                       &details[i].coin_pub,
                                       &tctx->current_wtid))
       {
@@ -509,23 +511,13 @@ wtid_cb (void *cls,
   /* WARNING: if two transactions got aggregated under the same
      WTID, then this branch is always taken (when attempting to
      track the second transaction). */
-  if (GNUNET_OK == 
+  if (GNUNET_OK ==
       db->find_proof_by_wtid (db->cls,
                               tctx->exchange_uri,
                               wtid,
                               &proof_cb,
                               &pcc))
   {
-    /**
-     * Conflict semantics: when the *first* call to /track/transaction
-     * at the exchange returns, the merchant issues a call to /track/transfer
-     * (at the exchange) and when that second call returns, it updates
-     * the information for all other coins using that returned information.
-     * Thus since this function is only called as callback to 
/track/transaction
-     * at the exchange, then if we already know this WTID, then some coin was 
not
-     * accounted in what /track/transfer returned (otherwise we wouldn't have
-     * tried to track it).
-     */
     GNUNET_break_op (0);
     resume_track_transaction_with_response
       (tcc->tctx,
@@ -568,9 +560,8 @@ trace_coins (struct TrackTransactionContext *tctx)
     tcc->dwh = TALER_EXCHANGE_track_transaction (tctx->eh,
                                                  &tctx->mi->privkey,
                                                  &tctx->h_wire,
-                                                 &tctx->h_contract,
+                                                 &tctx->h_proposal_data,
                                                  &tcc->coin_pub,
-                                                 tctx->transaction_id,
                                                  &wtid_cb,
                                                  tcc);
     return;
@@ -678,11 +669,13 @@ trace_coins (struct TrackTransactionContext *tctx)
  *
  * @param cls the `struct TrackTransactionContext`
  * @param eh NULL if exchange was not found to be acceptable
+ * @param wire_fee NULL (we did not specify a wire method)
  * @param exchange_trusted #GNUNET_YES if this exchange is trusted by config
  */
 static void
 process_track_transaction_with_exchange (void *cls,
                                          struct TALER_EXCHANGE_Handle *eh,
+                                         const struct TALER_Amount *wire_fee,
                                          int exchange_trusted)
 {
   struct TrackTransactionContext *tctx = cls;
@@ -721,6 +714,7 @@ handle_track_transaction_timeout (void *cls)
 
 /**
  * Function called with information about a transaction.
+ * Its duty is to fill up the "context" for the whole operation.
  *
  * @param cls closure
  * @param transaction_id of the contract
@@ -734,10 +728,9 @@ handle_track_transaction_timeout (void *cls)
  */
 static void
 transaction_cb (void *cls,
-                uint64_t transaction_id,
                const struct TALER_MerchantPublicKeyP *merchant_pub,
                 const char *exchange_uri,
-                const struct GNUNET_HashCode *h_contract,
+                const struct GNUNET_HashCode *h_proposal_data,
                 const struct GNUNET_HashCode *h_wire,
                 struct GNUNET_TIME_Absolute timestamp,
                 struct GNUNET_TIME_Absolute refund,
@@ -745,9 +738,8 @@ transaction_cb (void *cls,
 {
   struct TrackTransactionContext *tctx = cls;
 
-  tctx->transaction_id = transaction_id;
+  tctx->h_proposal_data = *h_proposal_data;
   tctx->exchange_uri = GNUNET_strdup (exchange_uri);
-  tctx->h_contract = *h_contract;
   tctx->h_wire = *h_wire;
   tctx->timestamp = timestamp;
   tctx->refund_deadline = refund;
@@ -774,7 +766,7 @@ transaction_cb (void *cls,
  */
 static void
 transfer_cb (void *cls,
-             uint64_t transaction_id,
+             const struct GNUNET_HashCode *h_proposal_data,
              const struct TALER_CoinSpendPublicKeyP *coin_pub,
              const struct TALER_WireTransferIdentifierRawP *wtid,
              struct GNUNET_TIME_Absolute execution_time,
@@ -804,7 +796,7 @@ transfer_cb (void *cls,
  */
 static void
 coin_cb (void *cls,
-         uint64_t transaction_id,
+         const struct GNUNET_HashCode *h_proposal_data,
          const struct TALER_CoinSpendPublicKeyP *coin_pub,
          const struct TALER_Amount *amount_with_fee,
          const struct TALER_Amount *deposit_fee,
@@ -822,10 +814,10 @@ coin_cb (void *cls,
                                tctx->tcc_tail,
                                tcc);
   GNUNET_break (GNUNET_SYSERR !=
-                db->find_transfers_by_id (db->cls,
-                                          transaction_id,
-                                          &transfer_cb,
-                                          tcc));
+                db->find_transfers_by_hash (db->cls,
+                                            h_proposal_data,
+                                            &transfer_cb,
+                                            tcc));
 }
 
 /**
@@ -846,11 +838,12 @@ MH_handler_track_transaction (struct TMH_RequestHandler 
*rh,
                               size_t *upload_data_size)
 {
   struct TrackTransactionContext *tctx;
-  unsigned long long transaction_id;
-  const char *str;
+  const char *order_id;
   const char *instance;
   int ret;
   struct GNUNET_HashCode h_instance;
+  struct GNUNET_HashCode h_proposal_data;
+  struct json_t *proposal_data;
 
   if (NULL == *connection_cls)
   {
@@ -895,48 +888,66 @@ MH_handler_track_transaction (struct TMH_RequestHandler 
*rh,
                 "Not sure why we are here, should be suspended\n");
     return MHD_YES; /* still work in progress */
   }
-  str = MHD_lookup_connection_value (connection,
-                                     MHD_GET_ARGUMENT_KIND,
-                                     "id");
-  if (NULL == str)
+  order_id = MHD_lookup_connection_value (connection,
+                                          MHD_GET_ARGUMENT_KIND,
+                                          "order_id");
+  if (NULL == order_id)
     return TMH_RESPONSE_reply_arg_missing (connection,
                                            TALER_EC_PARAMETER_MISSING,
-                                          "id");
+                                          "order_id");
   instance = MHD_lookup_connection_value (connection,
                                           MHD_GET_ARGUMENT_KIND,
                                           "instance");
   if (NULL == instance)
     instance = "default";
+
   GNUNET_CRYPTO_hash (instance,
                       strlen (instance),
                       &h_instance);
+
   tctx->mi = GNUNET_CONTAINER_multihashmap_get (by_id_map,
                                                 &h_instance);
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Tracking on behalf of instance '%s'\n",
+              instance);
+
   if (NULL == tctx->mi)
     return TMH_RESPONSE_reply_not_found (connection,
                                         
TALER_EC_TRACK_TRANSACTION_INSTANCE_UNKNOWN,
                                         "unknown instance");
-  if (1 !=
-      sscanf (str,
-              "%llu",
-              &transaction_id))
-    return TMH_RESPONSE_reply_arg_invalid (connection,
-                                          TALER_EC_PARAMETER_MALFORMED,
-                                           "id");
+
+  if (GNUNET_YES != db->find_proposal_data (db->cls,
+                                            &proposal_data,
+                                            order_id,
+                                            &tctx->mi->pubkey))
+
+    return TMH_RESPONSE_reply_not_found (connection,
+                                        TALER_EC_PROPOSAL_LOOKUP_NOT_FOUND,
+                                        "Given order_id doesn't map to any 
proposal");
+  TALER_JSON_hash (proposal_data,
+                   &h_proposal_data);
+
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Trying to track h_proposal_data '%s'\n",
+              GNUNET_h2s (&h_proposal_data));
 
   ret = db->find_transaction (db->cls,
-                              transaction_id,
+                              &h_proposal_data,
                              &tctx->mi->pubkey,
                               &transaction_cb,
                               tctx);
   if (GNUNET_NO == ret)
   {
+    GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+                "h_proposal_data not found\n");
     return TMH_RESPONSE_reply_not_found (connection,
                                         
TALER_EC_TRACK_TRANSACTION_TRANSACTION_UNKNOWN,
-                                         "id");
+                                         "h_proposal_data is unknown");
   }
   if ( (GNUNET_SYSERR == ret) ||
-       (tctx->transaction_id != (uint64_t) transaction_id) ||
+       (0 != memcmp (&tctx->h_proposal_data,
+                     &h_proposal_data,
+                     sizeof (struct GNUNET_HashCode))) ||
        (NULL == tctx->exchange_uri) )
   {
     GNUNET_break (0);
@@ -945,7 +956,7 @@ MH_handler_track_transaction (struct TMH_RequestHandler *rh,
                                               "Database error");
   }
   ret = db->find_payments (db->cls,
-                           transaction_id,
+                           &h_proposal_data,
                            &tctx->mi->pubkey,
                            &coin_cb,
                            tctx);
@@ -968,6 +979,7 @@ MH_handler_track_transaction (struct TMH_RequestHandler *rh,
               "Suspending /track/transaction handling while working with the 
exchange\n");
   MHD_suspend_connection (connection);
   tctx->fo = TMH_EXCHANGES_find_exchange (tctx->exchange_uri,
+                                          NULL,
                                           
&process_track_transaction_with_exchange,
                                           tctx);
 
@@ -978,5 +990,4 @@ MH_handler_track_transaction (struct TMH_RequestHandler *rh,
   return MHD_YES;
 }
 
-
 /* end of taler-merchant-httpd_track-transaction.c */
diff --git a/src/backend/taler-merchant-httpd_track-transfer.c 
b/src/backend/taler-merchant-httpd_track-transfer.c
index e6c08d6..3635c1d 100644
--- a/src/backend/taler-merchant-httpd_track-transfer.c
+++ b/src/backend/taler-merchant-httpd_track-transfer.c
@@ -175,7 +175,7 @@ resume_track_transfer_with_response (struct 
TrackTransferContext *rctx,
   rctx->response_code = response_code;
   rctx->response = response;
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "Resuming /track/transaction handling as exchange interaction is 
done (%u)\n",
+              "Resuming /track/transfer handling as exchange interaction is 
done (%u)\n",
               response_code);
   if (NULL != rctx->timeout_task)
   {
@@ -215,7 +215,7 @@ track_transfer_cleanup (struct TM_HandlerContext *hc)
  */
 static void
 check_transfer (void *cls,
-                uint64_t transaction_id,
+                const struct GNUNET_HashCode *h_proposal_data,
                 const struct TALER_CoinSpendPublicKeyP *coin_pub,
                 const struct TALER_Amount *amount_with_fee,
                 const struct TALER_Amount *deposit_fee,
@@ -237,14 +237,14 @@ check_transfer (void *cls,
     rctx->check_transfer_result = GNUNET_SYSERR;
     /* Build the `TrackTransferConflictDetails` */
     rctx->response
-      = TMH_RESPONSE_make_json_pack ("{s:I, s:s, s:o, s:I, s:o, s:o, s:I, s:o, 
s:o}",
+      = TMH_RESPONSE_make_json_pack ("{s:I, s:s, s:o, s:I, s:o, s:o, s:s, s:o, 
s:o}",
                                      "code", (json_int_t) 
TALER_EC_TRACK_TRANSFER_CONFLICTING_REPORTS,
                                      "hint", "disagreement about deposit 
valuation",
                                      "exchange_deposit_proof", exchange_proof,
                                      "conflict_offset", (json_int_t) 
rctx->current_offset,
                                      "exchange_transfer_proof", 
rctx->original_response,
                                      "coin_pub", GNUNET_JSON_from_data_auto 
(coin_pub),
-                                     "transaction_id", (json_int_t) 
transaction_id,
+                                     "h_proposal_data", 
GNUNET_JSON_from_data_auto (&ttd->h_proposal_data),
                                      "amount_with_fee", TALER_JSON_from_amount 
(amount_with_fee),
                                      "deposit_fee", TALER_JSON_from_amount 
(deposit_fee));
     return;
@@ -267,6 +267,7 @@ check_transfer (void *cls,
  * @param execution_time time when the exchange claims to have performed the 
wire transfer
  * @param total_amount total amount of the wire transfer, or NULL if the 
exchange could
  *             not provide any @a wtid (set only if @a http_status is 
#MHD_HTTP_OK)
+ * @param wire_fee wire fee that was charged by the exchange
  * @param details_length length of the @a details array
  * @param details array with details about the combined transactions
  */
@@ -279,6 +280,7 @@ wire_transfer_cb (void *cls,
                   const struct GNUNET_HashCode *h_wire,
                   struct GNUNET_TIME_Absolute execution_time,
                   const struct TALER_Amount *total_amount,
+                  const struct TALER_Amount *wire_fee,
                   unsigned int details_length,
                   const struct TALER_TrackTransferDetails *details)
 {
@@ -327,12 +329,12 @@ wire_transfer_cb (void *cls,
     rctx->current_offset = i;
     rctx->current_detail = &details[i];
     rctx->check_transfer_result = GNUNET_NO;
-    ret = db->find_payments_by_id_and_coin (db->cls,
-                                            details[i].transaction_id,
-                                            &rctx->mi->pubkey,
-                                            &details[i].coin_pub,
-                                            &check_transfer,
-                                            rctx);
+    ret = db->find_payments_by_hash_and_coin (db->cls,
+                                              &details[i].h_proposal_data,
+                                              &rctx->mi->pubkey,
+                                              &details[i].coin_pub,
+                                              &check_transfer,
+                                              rctx);
     if (GNUNET_SYSERR == ret)
     {
       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
@@ -384,7 +386,7 @@ wire_transfer_cb (void *cls,
     /* Response is consistent with the /deposit we made, remember
        it for future reference */
     ret = db->store_coin_to_transfer (db->cls,
-                                      details[i].transaction_id,
+                                      &details[i].h_proposal_data,
                                       &details[i].coin_pub,
                                       &rctx->wtid);
     if (GNUNET_OK != ret)
@@ -413,11 +415,13 @@ wire_transfer_cb (void *cls,
  *
  * @param cls the `struct TrackTransferContext`
  * @param eh NULL if exchange was not found to be acceptable
+ * @param wire_fee NULL (we did not specify a wire method)
  * @param exchange_trusted #GNUNET_YES if this exchange is trusted by config
  */
 static void
 process_track_transfer_with_exchange (void *cls,
                                       struct TALER_EXCHANGE_Handle *eh,
+                                      const struct TALER_Amount *wire_fee,
                                       int exchange_trusted)
 {
   struct TrackTransferContext *rctx = cls;
@@ -621,6 +625,7 @@ MH_handler_track_transfer (struct TMH_RequestHandler *rh,
               "Suspending /track/transfer handling while working with the 
exchange\n");
   MHD_suspend_connection (connection);
   rctx->fo = TMH_EXCHANGES_find_exchange (uri,
+                                          NULL,
                                           
&process_track_transfer_with_exchange,
                                           rctx);
   rctx->timeout_task
diff --git a/src/backenddb/Makefile.am b/src/backenddb/Makefile.am
index 1b0be36..a5adb21 100644
--- a/src/backenddb/Makefile.am
+++ b/src/backenddb/Makefile.am
@@ -36,6 +36,7 @@ libtaler_plugin_merchantdb_postgres_la_LDFLAGS = \
   -lgnunetpq \
   -ltalerpq \
   -ltalerutil \
+  -ltalerjson \
   -lpq \
   -lgnunetpostgres \
   -lgnunetutil $(XLIB)
@@ -53,6 +54,7 @@ test_merchantdb_postgres_SOURCES = \
 test_merchantdb_postgres_LDFLAGS = \
   -lgnunetutil \
   -ltalerutil \
+  -ltalerjson \
   -ljansson
 
 test_merchantdb_postgres_LDADD = \
diff --git a/src/backenddb/plugin_merchantdb_postgres.c 
b/src/backenddb/plugin_merchantdb_postgres.c
index 193c0a6..5381888 100644
--- a/src/backenddb/plugin_merchantdb_postgres.c
+++ b/src/backenddb/plugin_merchantdb_postgres.c
@@ -24,6 +24,7 @@
 #include <gnunet/gnunet_postgres_lib.h>
 #include <taler/taler_util.h>
 #include <taler/taler_pq_lib.h>
+#include <taler/taler_json_lib.h>
 #include "taler_merchantdb_plugin.h"
 
 
@@ -145,7 +146,7 @@ postgres_drop_tables (void *cls)
   PG_EXEC_INDEX (pg, "DROP TABLE merchant_deposits;");
   PG_EXEC_INDEX (pg, "DROP TABLE merchant_transactions;");
   PG_EXEC_INDEX (pg, "DROP TABLE merchant_proofs;");
-  PG_EXEC_INDEX (pg, "DROP TABLE merchant_contract_maps;");
+  PG_EXEC_INDEX (pg, "DROP TABLE merchant_proposal_data;");
   return GNUNET_OK;
 }
 
@@ -163,31 +164,33 @@ postgres_initialize (void *cls)
 
   /* Setup tables */
   PG_EXEC (pg,
-           "CREATE TABLE IF NOT EXISTS merchant_contract_maps ("
-           "h_contract BYTEA NOT NULL CHECK (LENGTH(h_contract)=64)"
-           ",plain_contract BYTEA NOT NULL"
-          ",PRIMARY KEY (h_contract)"
+           "CREATE TABLE IF NOT EXISTS merchant_proposal_data ("
+           "order_id VARCHAR NOT NULL"
+           ",merchant_pub BYTEA NOT NULL"
+           ",proposal_data BYTEA NOT NULL"
+           ",h_proposal_data BYTEA NOT NULL"
+           ",timestamp INT8 NOT NULL"
+          ",PRIMARY KEY (order_id, merchant_pub)"
            ");");
 
   PG_EXEC (pg,
            "CREATE TABLE IF NOT EXISTS merchant_transactions ("
-           " transaction_id INT8"
+           " h_proposal_data BYTEA NOT NULL"
            ",exchange_uri VARCHAR NOT NULL"
           ",merchant_pub BYTEA NOT NULL CHECK (LENGTH(merchant_pub)=32)"
-           ",h_contract BYTEA NOT NULL CHECK (LENGTH(h_contract)=64)"
            ",h_wire BYTEA NOT NULL CHECK (LENGTH(h_wire)=64)"
            ",timestamp INT8 NOT NULL"
            ",refund_deadline INT8 NOT NULL"
            ",total_amount_val INT8 NOT NULL"
            ",total_amount_frac INT4 NOT NULL"
            ",total_amount_curr VARCHAR(" TALER_CURRENCY_LEN_STR ") NOT NULL"
-          ",PRIMARY KEY (transaction_id, merchant_pub)"
+          ",PRIMARY KEY (h_proposal_data, merchant_pub)"
            ");");
   PG_EXEC (pg,
            "CREATE TABLE IF NOT EXISTS merchant_deposits ("
-          " transaction_id INT8"
+          " h_proposal_data BYTEA NOT NULL"
           ",merchant_pub BYTEA NOT NULL CHECK (LENGTH(merchant_pub)=32)"
-          ",FOREIGN KEY (transaction_id, merchant_pub) REFERENCES 
merchant_transactions (transaction_id, merchant_pub)"
+          ",FOREIGN KEY (h_proposal_data, merchant_pub) REFERENCES 
merchant_transactions (h_proposal_data, merchant_pub)"
            ",coin_pub BYTEA NOT NULL CHECK (LENGTH(coin_pub)=32)"
            ",amount_with_fee_val INT8 NOT NULL"
            ",amount_with_fee_frac INT4 NOT NULL"
@@ -197,7 +200,7 @@ postgres_initialize (void *cls)
            ",deposit_fee_curr VARCHAR(" TALER_CURRENCY_LEN_STR ") NOT NULL"
            ",signkey_pub BYTEA NOT NULL CHECK (LENGTH(signkey_pub)=32)"
            ",exchange_proof BYTEA NOT NULL"
-           ",PRIMARY KEY (transaction_id, coin_pub)"
+           ",PRIMARY KEY (h_proposal_data, coin_pub)"
            ");");
   PG_EXEC (pg,
            "CREATE TABLE IF NOT EXISTS merchant_proofs ("
@@ -213,10 +216,10 @@ postgres_initialize (void *cls)
      Hence those cannot be foreign keys into deposits/transactions! */
   PG_EXEC (pg,
            "CREATE TABLE IF NOT EXISTS merchant_transfers ("
-           " transaction_id INT8"
+           " h_proposal_data BYTEA NOT NULL"
            ",coin_pub BYTEA NOT NULL CHECK (LENGTH(coin_pub)=32)"
            ",wtid BYTEA NOT NULL CHECK (LENGTH(wtid)=32)"
-           ",PRIMARY KEY (transaction_id, coin_pub)"
+           ",PRIMARY KEY (h_proposal_data, coin_pub)"
            ");");
   PG_EXEC_INDEX (pg,
                  "CREATE INDEX IF NOT EXISTS merchant_transfers_by_coin"
@@ -229,10 +232,9 @@ postgres_initialize (void *cls)
   PG_PREPARE (pg,
               "insert_transaction",
               "INSERT INTO merchant_transactions"
-              "(transaction_id"
+              "(h_proposal_data"
               ",exchange_uri"
              ",merchant_pub"
-              ",h_contract"
               ",h_wire"
               ",timestamp"
               ",refund_deadline"
@@ -240,12 +242,12 @@ postgres_initialize (void *cls)
               ",total_amount_frac"
               ",total_amount_curr"
               ") VALUES "
-              "($1, $2, $3, $4, $5, $6, $7, $8, $9, $10)",
-              10);
+              "($1, $2, $3, $4, $5, $6, $7, $8, $9)",
+              9);
   PG_PREPARE (pg,
               "insert_deposit",
               "INSERT INTO merchant_deposits"
-              "(transaction_id"
+              "(h_proposal_data"
              ",merchant_pub"
               ",coin_pub"
               ",amount_with_fee_val"
@@ -261,7 +263,7 @@ postgres_initialize (void *cls)
   PG_PREPARE (pg,
               "insert_transfer",
               "INSERT INTO merchant_transfers"
-              "(transaction_id"
+              "(h_proposal_data"
               ",coin_pub"
               ",wtid) VALUES "
               "($1, $2, $3)",
@@ -278,44 +280,54 @@ postgres_initialize (void *cls)
               5);
 
   PG_PREPARE (pg,
-              "insert_map",
-              "INSERT INTO merchant_contract_maps"
-              "(h_contract"
-              ",plain_contract)"
+              "insert_proposal_data",
+              "INSERT INTO merchant_proposal_data"
+              "(order_id"
+              ",merchant_pub"
+              ",timestamp"
+              ",proposal_data"
+              ",h_proposal_data)"
               " VALUES "
-              "($1, $2)",
+              "($1, $2, $3, $4, $5)",
+              4);
+
+  PG_PREPARE (pg,
+              "find_proposal_data_from_hash",
+              "SELECT"
+              " proposal_data"
+              " FROM merchant_proposal_data"
+              " WHERE"
+              " h_proposal_data=$1"
+              " AND merchant_pub=$2",
               2);
 
   PG_PREPARE (pg,
-              "find_contract",
-              "SELECT plain_contract FROM merchant_contract_maps"
+              "find_proposal_data",
+              "SELECT"
+              " proposal_data"
+              " FROM merchant_proposal_data"
               " WHERE"
-              " h_contract=$1",
-              1);
+              " order_id=$1"
+              " AND merchant_pub=$2",
+              2);
 
   PG_PREPARE (pg,
-              "find_transactions_by_date",
+              "find_proposal_data_by_date",
               "SELECT"
-              " transaction_id"
-             ",merchant_pub"
-              ",exchange_uri"
-              ",h_contract"
-              ",h_wire"
-              ",timestamp"
-              ",refund_deadline"
-              ",total_amount_val"
-              ",total_amount_frac"
-              ",total_amount_curr"
-              " FROM merchant_transactions"
-              " WHERE timestamp>=$1",
-              1);
+              " proposal_data"
+              ",order_id"
+              " FROM merchant_proposal_data"
+              " WHERE"
+              " timestamp>=$1"
+              " AND merchant_pub=$2"
+              " ORDER BY timestamp DESC",
+              2);
 
   /* Setup prepared "SELECT" statements */
   PG_PREPARE (pg,
               "find_transaction",
               "SELECT"
               " exchange_uri"
-              ",h_contract"
               ",h_wire"
               ",timestamp"
               ",refund_deadline"
@@ -323,7 +335,7 @@ postgres_initialize (void *cls)
               ",total_amount_frac"
               ",total_amount_curr"
               " FROM merchant_transactions"
-              " WHERE transaction_id=$1"
+              " WHERE h_proposal_data=$1"
              " AND merchant_pub=$2",
               2);
   PG_PREPARE (pg,
@@ -338,7 +350,7 @@ postgres_initialize (void *cls)
               ",deposit_fee_curr"
               ",exchange_proof"
               " FROM merchant_deposits"
-              " WHERE transaction_id=$1"
+              " WHERE h_proposal_data=$1"
               " AND merchant_pub=$2",
               2);
   PG_PREPARE (pg,
@@ -352,12 +364,12 @@ postgres_initialize (void *cls)
               ",deposit_fee_curr"
               ",exchange_proof"
               " FROM merchant_deposits"
-              " WHERE transaction_id=$1"
+              " WHERE h_proposal_data=$1"
               " AND merchant_pub=$2"
               " AND coin_pub=$3",
               3);
   PG_PREPARE (pg,
-              "find_transfers_by_transaction_id",
+              "find_transfers_by_hash",
               "SELECT"
               " coin_pub"
               ",wtid"
@@ -365,12 +377,12 @@ postgres_initialize (void *cls)
               ",merchant_proofs.proof"
               " FROM merchant_transfers"
               "   JOIN merchant_proofs USING (wtid)"
-              " WHERE transaction_id=$1",
+              " WHERE h_proposal_data=$1",
               1);
   PG_PREPARE (pg,
               "find_deposits_by_wtid",
               "SELECT"
-              " merchant_transfers.transaction_id"
+              " merchant_transfers.h_proposal_data"
               ",merchant_transfers.coin_pub"
               ",merchant_deposits.amount_with_fee_val"
               ",merchant_deposits.amount_with_fee_frac"
@@ -381,7 +393,7 @@ postgres_initialize (void *cls)
               ",merchant_deposits.exchange_proof"
               " FROM merchant_transfers"
               "   JOIN merchant_deposits"
-              "     ON (merchant_deposits.transaction_id = 
merchant_transfers.transaction_id"
+              "     ON (merchant_deposits.h_proposal_data = 
merchant_transfers.h_proposal_data"
               "       AND"
               "         merchant_deposits.coin_pub = 
merchant_transfers.coin_pub)"
               " WHERE wtid=$1",
@@ -398,46 +410,48 @@ postgres_initialize (void *cls)
 }
 
 /**
- * Retrieve plain contract given its hashcode
+ * Retrieve proposal data given its transaction id's hashcode
  *
  * @param cls closure
- * @param h_contract hashcode of the contract to retrieve
- * @param contract where to store the retrieved contract
+ * @param h_transaction_id hashcode of the transaction id mentioned in this
+ * proposal data
+ * @param proposal_data where to store the retrieved proposal data
  * @return #GNUNET_OK on success, #GNUNET_NO if no contract is
  * found, #GNUNET_SYSERR upon error
  */
 static int
-postgres_find_contract (void *cls,
-                        json_t **contract,
-                        struct GNUNET_HashCode *h_contract)
+postgres_find_proposal_data_from_hash (void *cls,
+                                       json_t **proposal_data,
+                                       const struct GNUNET_HashCode 
*h_proposal_data,
+                                       const struct TALER_MerchantPublicKeyP 
*merchant_pub)
 {
   struct PostgresClosure *pg = cls;
   PGresult *result;
   unsigned int i;
 
   struct GNUNET_PQ_QueryParam params[] = {
-    GNUNET_PQ_query_param_auto_from_type (h_contract),
+    GNUNET_PQ_query_param_auto_from_type (h_proposal_data),
+    GNUNET_PQ_query_param_auto_from_type (merchant_pub),
     GNUNET_PQ_query_param_end
   };
 
   result = GNUNET_PQ_exec_prepared (pg->conn,
-                                    "find_contract",
+                                    "find_proposal_data_from_hash",
                                     params);
   i = PQntuples (result);
   if (1 < i)
   {
     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                "Mupltiple contracts share the same hashcode.\n");
+                "Mupltiple proposal data hash the same hashcode!\n");
     return GNUNET_SYSERR;
   }
 
   if (0 == i)
     return GNUNET_NO;
 
-  /* FIXME, figure out how to pass back json_t's */
   struct GNUNET_PQ_ResultSpec rs[] = {
-    TALER_PQ_result_spec_json ("plain_contract",
-                               contract),
+    TALER_PQ_result_spec_json ("proposal_data",
+                               proposal_data),
     GNUNET_PQ_result_spec_end
   };
   if (GNUNET_OK !=
@@ -455,30 +469,100 @@ postgres_find_contract (void *cls,
 
 
 /**
- * Insert a hash to contract map into the database
+ * Retrieve proposal data given its transaction id's hashcode
  *
  * @param cls closure
- * @param h_contract hashcode of @a contract
- * @param contract contract to store
+ * @param h_transaction_id hashcode of the transaction id mentioned in this
+ * proposal data
+ * @param proposal_data where to store the retrieved proposal data
+ * @return #GNUNET_OK on success, #GNUNET_NO if no contract is
+ * found, #GNUNET_SYSERR upon error
+ */
+static int
+postgres_find_proposal_data (void *cls,
+                             json_t **proposal_data,
+                             const char *order_id,
+                             const struct TALER_MerchantPublicKeyP 
*merchant_pub)
+{
+  struct PostgresClosure *pg = cls;
+  PGresult *result;
+  unsigned int i;
+
+  struct GNUNET_PQ_QueryParam params[] = {
+    GNUNET_PQ_query_param_string (order_id),
+    GNUNET_PQ_query_param_auto_from_type (merchant_pub),
+    GNUNET_PQ_query_param_end
+  };
+
+  result = GNUNET_PQ_exec_prepared (pg->conn,
+                                    "find_proposal_data",
+                                    params);
+  i = PQntuples (result);
+  if (1 < i)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                "Mupltiple proposal data share the same hashcode.\n");
+    return GNUNET_SYSERR;
+  }
+
+  if (0 == i)
+    return GNUNET_NO;
+
+  struct GNUNET_PQ_ResultSpec rs[] = {
+    TALER_PQ_result_spec_json ("proposal_data",
+                               proposal_data),
+    GNUNET_PQ_result_spec_end
+  };
+  if (GNUNET_OK !=
+      GNUNET_PQ_extract_result (result,
+                                rs,
+                                0))
+  {
+    GNUNET_break (0);
+    PQclear (result);
+    return GNUNET_SYSERR;
+  }
+
+  return GNUNET_OK;
+}
+
+
+/**
+ * Insert proposal data and its transaction id's hashcode into db
+ *
+ * @param cls closure
+ * @param h_transaction_id hashcode of the transaction id mentioned in this
+ * proposal data
+ * @param proposal_data proposal data to store
  * @return #GNUNET_OK on success, #GNUNET_SYSERR upon error
  */
 static int
-postgres_store_map (void *cls,
-                    struct GNUNET_HashCode *h_contract,
-                    const json_t *contract)
+postgres_insert_proposal_data (void *cls,
+                               const char *order_id,
+                               const struct TALER_MerchantPublicKeyP 
*merchant_pub,
+                               struct GNUNET_TIME_Absolute timestamp,
+                               const json_t *proposal_data)
 {
   struct PostgresClosure *pg = cls;
   PGresult *result;
   int ret;
+  struct GNUNET_HashCode h_proposal_data;
+
+  if (GNUNET_OK != TALER_JSON_hash (proposal_data,
+                                    &h_proposal_data))
+    return GNUNET_SYSERR;
 
   struct GNUNET_PQ_QueryParam params[] = {
-    GNUNET_PQ_query_param_auto_from_type (h_contract),
-    TALER_PQ_query_param_json (contract),
+    GNUNET_PQ_query_param_string (order_id),
+    GNUNET_PQ_query_param_auto_from_type (merchant_pub),
+    GNUNET_PQ_query_param_absolute_time (&timestamp),
+    TALER_PQ_query_param_json (proposal_data),
+    GNUNET_PQ_query_param_auto_from_type (&h_proposal_data),
     GNUNET_PQ_query_param_end
   };
 
   result = GNUNET_PQ_exec_prepared (pg->conn,
-                                    "insert_map",
+                                    "insert_proposal_data",
                                     params);
 
   /**
@@ -507,10 +591,9 @@ postgres_store_map (void *cls,
  * Insert transaction data into the database.
  *
  * @param cls closure
- * @param transaction_id of the contract
+ * @param transaction_id of the proposal
  * @param merchant_pub merchant's public key
  * @param exchange_uri URI of the exchange
- * @param h_contract hash of the contract
  * @param h_wire hash of our wire details
  * @param timestamp time of the confirmation
  * @param refund refund deadline
@@ -519,10 +602,9 @@ postgres_store_map (void *cls,
  */
 static int
 postgres_store_transaction (void *cls,
-                            uint64_t transaction_id,
+                            const struct GNUNET_HashCode *h_proposal_data,
                            const struct TALER_MerchantPublicKeyP *merchant_pub,
                             const char *exchange_uri,
-                            const struct GNUNET_HashCode *h_contract,
                             const struct GNUNET_HashCode *h_wire,
                             struct GNUNET_TIME_Absolute timestamp,
                             struct GNUNET_TIME_Absolute refund,
@@ -533,10 +615,9 @@ postgres_store_transaction (void *cls,
   int ret;
 
   struct GNUNET_PQ_QueryParam params[] = {
-    GNUNET_PQ_query_param_uint64 (&transaction_id),
+    GNUNET_PQ_query_param_auto_from_type (h_proposal_data),
     GNUNET_PQ_query_param_string (exchange_uri),
     GNUNET_PQ_query_param_auto_from_type (merchant_pub),
-    GNUNET_PQ_query_param_auto_from_type (h_contract),
     GNUNET_PQ_query_param_auto_from_type (h_wire),
     GNUNET_PQ_query_param_absolute_time (&timestamp),
     GNUNET_PQ_query_param_absolute_time (&refund),
@@ -544,6 +625,10 @@ postgres_store_transaction (void *cls,
     GNUNET_PQ_query_param_end
   };
 
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Storing transaction with h_proposal_data '%s'\n",
+              GNUNET_h2s (h_proposal_data));
+
   result = GNUNET_PQ_exec_prepared (pg->conn,
                                     "insert_transaction",
                                     params);
@@ -576,7 +661,7 @@ postgres_store_transaction (void *cls,
  */
 static int
 postgres_store_deposit (void *cls,
-                        uint64_t transaction_id,
+                        const struct GNUNET_HashCode *h_proposal_data,
                         const struct TALER_MerchantPublicKeyP *merchant_pub,
                         const struct TALER_CoinSpendPublicKeyP *coin_pub,
                         const struct TALER_Amount *amount_with_fee,
@@ -589,7 +674,7 @@ postgres_store_deposit (void *cls,
   int ret;
 
   struct GNUNET_PQ_QueryParam params[] = {
-    GNUNET_PQ_query_param_uint64 (&transaction_id),
+    GNUNET_PQ_query_param_auto_from_type (h_proposal_data),
     GNUNET_PQ_query_param_auto_from_type (merchant_pub),
     GNUNET_PQ_query_param_auto_from_type (coin_pub),
     TALER_PQ_query_param_amount (amount_with_fee),
@@ -599,6 +684,9 @@ postgres_store_deposit (void *cls,
     GNUNET_PQ_query_param_end
   };
 
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "storing payment for h_proposal_data '%s'\n",
+              GNUNET_h2s (h_proposal_data));
   result = GNUNET_PQ_exec_prepared (pg->conn,
                                     "insert_deposit",
                                     params);
@@ -629,7 +717,7 @@ postgres_store_deposit (void *cls,
  */
 static int
 postgres_store_coin_to_transfer (void *cls,
-                                 uint64_t transaction_id,
+                                 const struct GNUNET_HashCode *h_proposal_data,
                                  const struct TALER_CoinSpendPublicKeyP 
*coin_pub,
                                  const struct TALER_WireTransferIdentifierRawP 
*wtid)
 {
@@ -638,7 +726,7 @@ postgres_store_coin_to_transfer (void *cls,
   int ret;
 
   struct GNUNET_PQ_QueryParam params[] = {
-    GNUNET_PQ_query_param_uint64 (&transaction_id),
+    GNUNET_PQ_query_param_auto_from_type (h_proposal_data),
     GNUNET_PQ_query_param_auto_from_type (coin_pub),
     GNUNET_PQ_query_param_auto_from_type (wtid),
     GNUNET_PQ_query_param_end
@@ -719,10 +807,11 @@ postgres_store_transfer_to_proof (void *cls,
  * @return numer of found tuples, #GNUNET_SYSERR upon error
  */
 static int
-postgres_find_transactions_by_date (void *cls,
-                                    struct GNUNET_TIME_Absolute date,
-                                    TALER_MERCHANTDB_TransactionCallback cb,
-                                    void *cb_cls)
+postgres_find_proposal_data_by_date (void *cls,
+                                     struct GNUNET_TIME_Absolute date,
+                                     const struct TALER_MerchantPublicKeyP 
*merchant_pub,
+                                     TALER_MERCHANTDB_ProposalDataCallback cb,
+                                     void *cb_cls)
 {
 
   struct PostgresClosure *pg = cls;
@@ -732,10 +821,11 @@ postgres_find_transactions_by_date (void *cls,
 
   struct GNUNET_PQ_QueryParam params[] = {
     GNUNET_PQ_query_param_absolute_time (&date),
+    GNUNET_PQ_query_param_auto_from_type (merchant_pub),
     GNUNET_PQ_query_param_end
   };
   result = GNUNET_PQ_exec_prepared (pg->conn,
-                                    "find_transactions_by_date",
+                                    "find_proposal_data_by_date",
                                     params);
   if (PGRES_TUPLES_OK != PQresultStatus (result))
   {
@@ -750,31 +840,14 @@ postgres_find_transactions_by_date (void *cls,
   }
   for (i = 0; i < n; i++)
   {
-    struct TALER_MerchantPublicKeyP merchant_pub;
-    char *exchange_uri;
-    struct GNUNET_HashCode h_contract;
-    struct GNUNET_HashCode h_wire;
-    struct GNUNET_TIME_Absolute timestamp;
-    struct GNUNET_TIME_Absolute refund_deadline;
-    struct TALER_Amount total_amount;
-    uint64_t transaction_id;
+    char *order_id;
+    json_t *proposal_data;
+
     struct GNUNET_PQ_ResultSpec rs[] = {
-      GNUNET_PQ_result_spec_string ("exchange_uri",
-                                    &exchange_uri),
-      GNUNET_PQ_result_spec_uint64 ("transaction_id",
-                                    &transaction_id),
-      GNUNET_PQ_result_spec_auto_from_type ("merchant_pub",
-                                            &merchant_pub),
-      GNUNET_PQ_result_spec_auto_from_type ("h_contract",
-                                            &h_contract),
-      GNUNET_PQ_result_spec_auto_from_type ("h_wire",
-                                            &h_wire),
-      GNUNET_PQ_result_spec_absolute_time ("timestamp",
-                                           &timestamp),
-      GNUNET_PQ_result_spec_absolute_time ("refund_deadline",
-                                           &refund_deadline),
-      TALER_PQ_result_spec_amount ("total_amount",
-                                   &total_amount),
+      GNUNET_PQ_result_spec_string ("order_id",
+                                    &order_id),
+      TALER_PQ_result_spec_json ("proposal_data",
+                                 &proposal_data),
       GNUNET_PQ_result_spec_end
     };
 
@@ -788,14 +861,9 @@ postgres_find_transactions_by_date (void *cls,
       return GNUNET_SYSERR;
     }
     cb (cb_cls,
-        transaction_id,
-       &merchant_pub,
-        exchange_uri,
-        &h_contract,
-        &h_wire,
-        timestamp,
-        refund_deadline,
-        &total_amount);
+        order_id,
+        proposal_data);
+
     GNUNET_PQ_cleanup_result (rs);
   }
   PQclear (result);
@@ -816,7 +884,7 @@ postgres_find_transactions_by_date (void *cls,
  */
 static int
 postgres_find_transaction (void *cls,
-                           uint64_t transaction_id,
+                           const struct GNUNET_HashCode *h_proposal_data,
                           const struct TALER_MerchantPublicKeyP *merchant_pub,
                            TALER_MERCHANTDB_TransactionCallback cb,
                            void *cb_cls)
@@ -824,11 +892,15 @@ postgres_find_transaction (void *cls,
   struct PostgresClosure *pg = cls;
   PGresult *result;
   struct GNUNET_PQ_QueryParam params[] = {
-    GNUNET_PQ_query_param_uint64 (&transaction_id),
+    GNUNET_PQ_query_param_auto_from_type (h_proposal_data),
     GNUNET_PQ_query_param_auto_from_type (merchant_pub),
     GNUNET_PQ_query_param_end
   };
 
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Finding transaction for h_proposal_data '%s'\n",
+              GNUNET_h2s (h_proposal_data));
+
   result = GNUNET_PQ_exec_prepared (pg->conn,
                                     "find_transaction",
                                     params);
@@ -840,6 +912,10 @@ postgres_find_transaction (void *cls,
   }
   if (0 == PQntuples (result))
   {
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "Could NOT find transaction for h_proposal_data '%s'\n",
+                GNUNET_h2s (h_proposal_data));
+
     PQclear (result);
     return GNUNET_NO;
   }
@@ -852,7 +928,6 @@ postgres_find_transaction (void *cls,
 
   {
     char *exchange_uri;
-    struct GNUNET_HashCode h_contract;
     struct GNUNET_HashCode h_wire;
     struct GNUNET_TIME_Absolute timestamp;
     struct GNUNET_TIME_Absolute refund_deadline;
@@ -860,8 +935,6 @@ postgres_find_transaction (void *cls,
     struct GNUNET_PQ_ResultSpec rs[] = {
       GNUNET_PQ_result_spec_string ("exchange_uri",
                                     &exchange_uri),
-      GNUNET_PQ_result_spec_auto_from_type ("h_contract",
-                                            &h_contract),
       GNUNET_PQ_result_spec_auto_from_type ("h_wire",
                                             &h_wire),
       GNUNET_PQ_result_spec_absolute_time ("timestamp",
@@ -883,10 +956,9 @@ postgres_find_transaction (void *cls,
       return GNUNET_SYSERR;
     }
     cb (cb_cls,
-        transaction_id,
        merchant_pub,
         exchange_uri,
-        &h_contract,
+        h_proposal_data,
         &h_wire,
         timestamp,
         refund_deadline,
@@ -911,7 +983,7 @@ postgres_find_transaction (void *cls,
  */
 static int
 postgres_find_payments (void *cls,
-                        uint64_t transaction_id,
+                        const struct GNUNET_HashCode *h_proposal_data,
                        const struct TALER_MerchantPublicKeyP *merchant_pub,
                         TALER_MERCHANTDB_CoinDepositCallback cb,
                         void *cb_cls)
@@ -921,10 +993,13 @@ postgres_find_payments (void *cls,
   unsigned int i;
 
   struct GNUNET_PQ_QueryParam params[] = {
-    GNUNET_PQ_query_param_uint64 (&transaction_id),
+    GNUNET_PQ_query_param_auto_from_type (h_proposal_data),
     GNUNET_PQ_query_param_auto_from_type (merchant_pub),
     GNUNET_PQ_query_param_end
   };
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "finding payment for h_proposal_data '%s'\n",
+              GNUNET_h2s (h_proposal_data));
   result = GNUNET_PQ_exec_prepared (pg->conn,
                                     "find_deposits",
                                     params);
@@ -969,7 +1044,7 @@ postgres_find_payments (void *cls,
       return GNUNET_SYSERR;
     }
     cb (cb_cls,
-        transaction_id,
+        h_proposal_data,
         &coin_pub,
         &amount_with_fee,
         &deposit_fee,
@@ -998,19 +1073,19 @@ postgres_find_payments (void *cls,
  *         #GNUNET_SYSERR on hard errors
  */
 static int
-postgres_find_payments_by_id_and_coin (void *cls,
-                                       uint64_t transaction_id,
-                                       const struct TALER_MerchantPublicKeyP 
*merchant_pub,
-                                       const struct TALER_CoinSpendPublicKeyP 
*coin_pub,
-                                       TALER_MERCHANTDB_CoinDepositCallback cb,
-                                       void *cb_cls)
+postgres_find_payments_by_hash_and_coin (void *cls,
+                                         const struct GNUNET_HashCode 
*h_proposal_data,
+                                         const struct TALER_MerchantPublicKeyP 
*merchant_pub,
+                                         const struct 
TALER_CoinSpendPublicKeyP *coin_pub,
+                                         TALER_MERCHANTDB_CoinDepositCallback 
cb,
+                                         void *cb_cls)
 {
   struct PostgresClosure *pg = cls;
   PGresult *result;
   unsigned int i;
 
   struct GNUNET_PQ_QueryParam params[] = {
-    GNUNET_PQ_query_param_uint64 (&transaction_id),
+    GNUNET_PQ_query_param_auto_from_type (h_proposal_data),
     GNUNET_PQ_query_param_auto_from_type (merchant_pub),
     GNUNET_PQ_query_param_auto_from_type (coin_pub),
     GNUNET_PQ_query_param_end
@@ -1057,7 +1132,7 @@ postgres_find_payments_by_id_and_coin (void *cls,
       return GNUNET_SYSERR;
     }
     cb (cb_cls,
-        transaction_id,
+        h_proposal_data,
         coin_pub,
         &amount_with_fee,
         &deposit_fee,
@@ -1087,21 +1162,21 @@ postgres_find_payments_by_id_and_coin (void *cls,
  *         #GNUNET_SYSERR on hard errors
  */
 static int
-postgres_find_transfers_by_id (void *cls,
-                               uint64_t transaction_id,
-                               TALER_MERCHANTDB_TransferCallback cb,
-                               void *cb_cls)
+postgres_find_transfers_by_hash (void *cls,
+                                 const struct GNUNET_HashCode *h_proposal_data,
+                                 TALER_MERCHANTDB_TransferCallback cb,
+                                 void *cb_cls)
 {
   struct PostgresClosure *pg = cls;
   PGresult *result;
   unsigned int i;
 
   struct GNUNET_PQ_QueryParam params[] = {
-    GNUNET_PQ_query_param_uint64 (&transaction_id),
+    GNUNET_PQ_query_param_auto_from_type (h_proposal_data),
     GNUNET_PQ_query_param_end
   };
   result = GNUNET_PQ_exec_prepared (pg->conn,
-                                    "find_transfers_by_transaction_id",
+                                    "find_transfers_by_hash",
                                     params);
   if (PGRES_TUPLES_OK != PQresultStatus (result))
   {
@@ -1144,7 +1219,7 @@ postgres_find_transfers_by_id (void *cls,
       return GNUNET_SYSERR;
     }
     cb (cb_cls,
-        transaction_id,
+        h_proposal_data,
         &coin_pub,
         &wtid,
         execution_time,
@@ -1197,15 +1272,15 @@ postgres_find_deposits_by_wtid (void *cls,
 
   for (i=0;i<PQntuples (result);i++)
   {
-    uint64_t transaction_id;
+    struct GNUNET_HashCode h_proposal_data;
     struct TALER_CoinSpendPublicKeyP coin_pub;
     struct TALER_Amount amount_with_fee;
     struct TALER_Amount deposit_fee;
     json_t *exchange_proof;
 
     struct GNUNET_PQ_ResultSpec rs[] = {
-      GNUNET_PQ_result_spec_uint64 ("transaction_id",
-                                    &transaction_id),
+      GNUNET_PQ_result_spec_auto_from_type ("h_proposal_data",
+                                            &h_proposal_data),
       GNUNET_PQ_result_spec_auto_from_type ("coin_pub",
                                             &coin_pub),
       TALER_PQ_result_spec_amount ("amount_with_fee",
@@ -1227,7 +1302,7 @@ postgres_find_deposits_by_wtid (void *cls,
       return GNUNET_SYSERR;
     }
     cb (cb_cls,
-        transaction_id,
+        &h_proposal_data,
         &coin_pub,
         &amount_with_fee,
         &deposit_fee,
@@ -1351,6 +1426,11 @@ libtaler_plugin_merchantdb_postgres_init (void *cls)
     }
   }
   pg->conn = GNUNET_POSTGRES_connect (cfg, "merchantdb-postgres");
+  if (NULL == pg->conn)
+  {
+    GNUNET_free (pg);
+    return NULL;
+  }
   plugin = GNUNET_new (struct TALER_MERCHANTDB_Plugin);
   plugin->cls = pg;
   plugin->drop_tables = &postgres_drop_tables;
@@ -1360,14 +1440,15 @@ libtaler_plugin_merchantdb_postgres_init (void *cls)
   plugin->store_coin_to_transfer = &postgres_store_coin_to_transfer;
   plugin->store_transfer_to_proof = &postgres_store_transfer_to_proof;
   plugin->find_transaction = &postgres_find_transaction;
-  plugin->find_transactions_by_date = &postgres_find_transactions_by_date;
-  plugin->find_payments_by_id_and_coin = 
&postgres_find_payments_by_id_and_coin;
+  plugin->find_payments_by_hash_and_coin = 
&postgres_find_payments_by_hash_and_coin;
   plugin->find_payments = &postgres_find_payments;
-  plugin->find_transfers_by_id = &postgres_find_transfers_by_id;
+  plugin->find_transfers_by_hash = &postgres_find_transfers_by_hash;
   plugin->find_deposits_by_wtid = &postgres_find_deposits_by_wtid;
   plugin->find_proof_by_wtid = &postgres_find_proof_by_wtid;
-  plugin->store_map = &postgres_store_map;
-  plugin->find_contract = &postgres_find_contract;
+  plugin->insert_proposal_data = &postgres_insert_proposal_data;
+  plugin->find_proposal_data = &postgres_find_proposal_data;
+  plugin->find_proposal_data_by_date = &postgres_find_proposal_data_by_date;
+  plugin->find_proposal_data_from_hash = 
&postgres_find_proposal_data_from_hash;
 
   return plugin;
 }
diff --git a/src/backenddb/test_merchantdb.c b/src/backenddb/test_merchantdb.c
index d30b7f5..fe52039 100644
--- a/src/backenddb/test_merchantdb.c
+++ b/src/backenddb/test_merchantdb.c
@@ -60,11 +60,6 @@ static int result;
 static struct TALER_MERCHANTDB_Plugin *plugin;
 
 /**
- * Hash of the contract.  Set to some random value.
- */
-static struct GNUNET_HashCode h_contract;
-
-/**
  * Hash of the wire transfer address.  Set to some random value.
  */
 static struct GNUNET_HashCode h_wire;
@@ -72,7 +67,17 @@ static struct GNUNET_HashCode h_wire;
 /**
  * Transaction ID.
  */
-static uint64_t transaction_id;
+const char *order_id;
+
+/**
+ * Proposal's hash
+ */
+struct GNUNET_HashCode h_proposal_data;
+
+/**
+ * Proposal's hash.
+ */
+struct GNUNET_HashCode h_proposal_data2;
 
 /**
  * Time of the transaction.
@@ -135,6 +140,12 @@ static json_t *transfer_proof;
  */
 static json_t *contract;
 
+/**
+ * Mock proposal data, not need to be well-formed
+ */
+static json_t *proposal_data;
+
+
 
 /**
  * Function called with information about a transaction.
@@ -143,7 +154,6 @@ static json_t *contract;
  * @param transaction_id of the contract
  * @param merchant_pub public key of the merchant
  * @param exchange_uri URI of the exchange
- * @param h_contract hash of the contract
  * @param h_wire hash of our wire details
  * @param timestamp time of the confirmation
  * @param refund_deadline refund deadline
@@ -151,25 +161,23 @@ static json_t *contract;
  */
 static void
 transaction_cb (void *cls,
-                uint64_t atransaction_id,
                const struct TALER_MerchantPublicKeyP *amerchant_pub,
                 const char *aexchange_uri,
-                const struct GNUNET_HashCode *ah_contract,
+                const struct GNUNET_HashCode *ah_proposal_data,
                 const struct GNUNET_HashCode *ah_wire,
                 struct GNUNET_TIME_Absolute atimestamp,
                 struct GNUNET_TIME_Absolute arefund_deadline,
                 const struct TALER_Amount *atotal_amount)
 {
 #define CHECK(a) do { if (! (a)) { GNUNET_break (0); result = 3; } } while (0)
-  CHECK (atransaction_id == transaction_id);
   CHECK (0 == memcmp (amerchant_pub,
                       &merchant_pub,
                      sizeof (struct TALER_MerchantPublicKeyP)));
+  CHECK (0 == memcmp (ah_proposal_data,
+                      &h_proposal_data,
+                      sizeof (struct GNUNET_HashCode)));
   CHECK (0 == strcmp (aexchange_uri,
                       EXCHANGE_URI));
-  CHECK (0 == memcmp (ah_contract,
-                      &h_contract,
-                      sizeof (struct GNUNET_HashCode)));
   CHECK (0 == memcmp (ah_wire,
                       &h_wire,
                       sizeof (struct GNUNET_HashCode)));
@@ -179,34 +187,18 @@ transaction_cb (void *cls,
                                 &amount_with_fee));
 }
 
-
 /**
- * Function called with information about a transaction. Checks whether the
- * returned tuple
+ * Callback for `find_proposal_data_by_date`.
  *
  * @param cls closure
- * @param transaction_id of the contract
- * @param merchant_pub merchant's public key
- * @param exchange_uri URI of the exchange
- * @param h_contract hash of the contract
- * @param h_wire hash of our wire details
- * @param timestamp time of the confirmation
- * @param refund refund deadline
- * @param total_amount total amount we receive for the contract after fees
+ * @param order_id order id
+ * @param proposal_data proposal data
  */
-
 static void
-history_cb (void *cls,
-            uint64_t transaction_id,
-           const struct TALER_MerchantPublicKeyP *merchant_pub,
-            const char *exchange_uri,
-            const struct GNUNET_HashCode *h_contract,
-            const struct GNUNET_HashCode *h_wire,
-            struct GNUNET_TIME_Absolute timestamp,
-            struct GNUNET_TIME_Absolute refund,
-            const struct TALER_Amount *total_amount)
+pd_cb (void *cls,
+       const char *order_id,
+       const json_t *proposal_data)
 {
-  /*Just a stub*/
   return;
 }
 
@@ -222,13 +214,15 @@ history_cb (void *cls,
  */
 static void
 deposit_cb (void *cls,
-            uint64_t atransaction_id,
+            const struct GNUNET_HashCode *ah_proposal_data,
             const struct TALER_CoinSpendPublicKeyP *acoin_pub,
             const struct TALER_Amount *aamount_with_fee,
             const struct TALER_Amount *adeposit_fee,
             const json_t *aexchange_proof)
 {
-  CHECK (atransaction_id == transaction_id);
+  CHECK ((0 == memcmp (ah_proposal_data,
+                       &h_proposal_data,
+                       sizeof (struct GNUNET_HashCode))));
   CHECK (0 == memcmp (acoin_pub,
                       &coin_pub,
                       sizeof (struct TALER_CoinSpendPublicKeyP)));
@@ -260,13 +254,16 @@ deposit_cb (void *cls,
  */
 static void
 transfer_cb (void *cls,
-             uint64_t atransaction_id,
+             const struct GNUNET_HashCode *ah_proposal_data,
              const struct TALER_CoinSpendPublicKeyP *acoin_pub,
              const struct TALER_WireTransferIdentifierRawP *awtid,
              struct GNUNET_TIME_Absolute execution_time,
              const json_t *exchange_proof)
 {
-  CHECK (atransaction_id == transaction_id);
+  CHECK (0 == memcmp (ah_proposal_data,
+                      &h_proposal_data,
+                      sizeof (struct GNUNET_HashCode)));
+
   CHECK (0 == memcmp (acoin_pub,
                       &coin_pub,
                       sizeof (struct TALER_CoinSpendPublicKeyP)));
@@ -323,9 +320,9 @@ run (void *cls)
   }
 
   /* Prepare data for 'store_payment()' */
-  RND_BLK (&h_contract);
   RND_BLK (&h_wire);
-  RND_BLK (&transaction_id);
+  RND_BLK (&h_proposal_data);
+  order_id = "test_ID";
   RND_BLK (&signkey_pub);
   RND_BLK (&merchant_pub);
   RND_BLK (&wtid);
@@ -353,32 +350,49 @@ run (void *cls)
                                       "test",
                                       json_string ("backenddb test B")));
   contract = json_object ();
+  proposal_data = json_object ();
+
+  TALER_JSON_hash (proposal_data,
+                   &h_proposal_data2);
 
   FAILIF (GNUNET_OK !=
-          plugin->store_map (plugin->cls,
-                             &h_contract,
-                             contract));
+          plugin->insert_proposal_data (plugin->cls,
+                                        order_id,
+                                        &merchant_pub,
+                                        timestamp,
+                                        proposal_data));
 
   json_t *out;
 
   FAILIF (GNUNET_OK !=
-          plugin->find_contract (plugin->cls,
-                                 &out,
-                                 &h_contract));
+          plugin->find_proposal_data (plugin->cls,
+                                      &out, // plain data
+                                      order_id,
+                                      &merchant_pub));
 
   FAILIF (GNUNET_OK !=
+          plugin->find_proposal_data_from_hash (plugin->cls,
+                                                &out, // plain data
+                                                &h_proposal_data2,
+                                                &merchant_pub));
+  FAILIF (1 !=
+          plugin->find_proposal_data_by_date (plugin->cls,
+                                              fake_now,
+                                              &merchant_pub,
+                                              pd_cb,
+                                              NULL));
+  FAILIF (GNUNET_OK !=
           plugin->store_transaction (plugin->cls,
-                                     transaction_id,
+                                     &h_proposal_data,
                                     &merchant_pub,
                                      EXCHANGE_URI,
-                                     &h_contract,
                                      &h_wire,
                                      timestamp,
                                      refund_deadline,
                                      &amount_with_fee));
   FAILIF (GNUNET_OK !=
           plugin->store_deposit (plugin->cls,
-                                 transaction_id,
+                                 &h_proposal_data,
                                 &merchant_pub,
                                  &coin_pub,
                                  &amount_with_fee,
@@ -387,7 +401,7 @@ run (void *cls)
                                  deposit_proof));
   FAILIF (GNUNET_OK !=
           plugin->store_coin_to_transfer (plugin->cls,
-                                          transaction_id,
+                                          &h_proposal_data,
                                           &coin_pub,
                                           &wtid));
   FAILIF (GNUNET_OK !=
@@ -399,27 +413,20 @@ run (void *cls)
                                            transfer_proof));
   FAILIF (GNUNET_OK !=
           plugin->find_transaction (plugin->cls,
-                                    transaction_id,
+                                    &h_proposal_data,
                                    &merchant_pub,
                                     &transaction_cb,
                                     NULL));
 
-  /* FIXME: put here find_transactions_by_date () */
-  FAILIF (1 !=
-          plugin->find_transactions_by_date (plugin->cls,
-                                             fake_now,
-                                             history_cb,
-                                             NULL));
-
   FAILIF (GNUNET_OK !=
           plugin->find_payments (plugin->cls,
-                                 transaction_id,
+                                 &h_proposal_data,
                                  &merchant_pub,
                                  &deposit_cb,
                                  NULL));
   FAILIF (GNUNET_OK !=
-          plugin->find_transfers_by_id (plugin->cls,
-                                        transaction_id,
+          plugin->find_transfers_by_hash (plugin->cls,
+                                        &h_proposal_data,
                                         &transfer_cb,
                                         NULL));
   FAILIF (GNUNET_OK !=
@@ -462,7 +469,7 @@ main (int argc,
     GNUNET_break (0);
     return -1;
   }
-  GNUNET_log_setup (argv[0], "INFO", NULL);
+  GNUNET_log_setup (argv[0], "DEBUG", NULL);
   plugin_name++;
   (void) GNUNET_asprintf (&testname,
                           "test-merchantdb-%s",
diff --git a/src/include/platform.h b/src/include/platform.h
index de9ebe3..a2ed6f4 100644
--- a/src/include/platform.h
+++ b/src/include/platform.h
@@ -51,6 +51,10 @@
 /* Do not use deprecated functions from gcrypt */
 #define GCRYPT_NO_DEPRECATED 1
 
+/* Ignore MHD deprecations for now as we want to be compatible
+   to "ancient" MHD releases. */
+#define MHD_NO_DEPRECATION 1
+
 #endif  /* PLATFORM_H_ */
 
 /* end of platform.h */
diff --git a/src/include/taler_merchant_service.h 
b/src/include/taler_merchant_service.h
index 0ed6856..68ffe7f 100644
--- a/src/include/taler_merchant_service.h
+++ b/src/include/taler_merchant_service.h
@@ -30,66 +30,18 @@
 
 /* ********************* /map/{in,out} *********************** */
 
-struct TALER_MERCHANT_MapOutOperation;
+/* *********************  /proposal *********************** */
 
-typedef void
-(*TALER_MERCHANT_MapOperationCallback) (void *cls,
-                                        unsigned int http_status,
-                                        const json_t *body);
 
 /**
- * Issue a /map/out request to the backend.
- *
- * @param ctx execution context
- * @param backend_uri base URL of the merchant backend
- * @param h_contract hashcode of `contract`
- * @param map_in_cb callback which will work the response gotten from the 
backend
- * @param map_in_cb_cls closure to pass to @a history_cb
- * @return handle for this operation, NULL upon errors
+ * Handle to a PUT /proposal operation
  */
-struct TALER_MERCHANT_MapOperation *
-TALER_MERCHANT_map_out (struct GNUNET_CURL_Context *ctx,
-                        const char *backend_uri,
-                        const struct GNUNET_HashCode *h_contract,
-                        TALER_MERCHANT_MapOperationCallback map_cb,
-                        void *map_cb_cls);
+struct TALER_MERCHANT_ProposalOperation;
 
 /**
- * Issue a /map/in request to the backend.
- *
- * @param ctx execution context
- * @param backend_uri base URL of the merchant backend
- * @param contract contract to store
- * @param h_contract hashcode of `contract`
- * @param map_in_cb callback which will work the response gotten from the 
backend
- * @param map_in_cb_cls closure to pass to @a history_cb
- * @return handle for this operation, NULL upon errors
+ * Handle to a GET /proposal operation
  */
-struct TALER_MERCHANT_MapOperation *
-TALER_MERCHANT_map_in (struct GNUNET_CURL_Context *ctx,
-                       const char *backend_uri,
-                       const json_t *contract,
-                       const struct GNUNET_HashCode *h_contract,
-                       TALER_MERCHANT_MapOperationCallback map_cb,
-                       void *map_cb_cls);
-
-/**
- * Cancel a /map/in request.
- *
- * @param mio handle to the request to be canceled
- */
-void
-TALER_MERCHANT_map_cancel (struct TALER_MERCHANT_MapOperation *mo);
-
-
-/* *********************  /contract *********************** */
-
-
-/**
- * @brief Handle to a /contract operation at a merchant's backend.
- */
-struct TALER_MERCHANT_ContractOperation;
-
+struct TALER_MERCHANT_ProposalLookupOperation;
 
 /**
  * Callbacks of this type are used to serve the result of submitting a
@@ -99,48 +51,91 @@ struct TALER_MERCHANT_ContractOperation;
  * @param http_status HTTP response code, 200 indicates success;
  *                    0 if the backend's reply is bogus (fails to follow the 
protocol)
  * @param ec taler-specific error code 
- * @param obj the full received JSON reply, or
- *            error details if the request failed
- * @param contract completed contract, NULL on error
+ * @param obj raw JSON reply, or error details if the request failed
+ * @param proposal_data completed contract, NULL on error
  * @param sig merchant's signature over the contract, NULL on error
- * @param h_contract hash of the contract, NULL on error
+ * @param hash proposal data's hashcode, NULL on error
  */
 typedef void
-(*TALER_MERCHANT_ContractCallback) (void *cls,
+(*TALER_MERCHANT_ProposalCallback) (void *cls,
                                     unsigned int http_status,
                                    enum TALER_ErrorCode ec,
                                     const json_t *obj,
-                                    const json_t *contract,
+                                    const json_t *proposal_data,
                                     const struct TALER_MerchantSignatureP *sig,
-                                    const struct GNUNET_HashCode *h_contract);
+                                    const struct GNUNET_HashCode *hash);
+
 
+/**
+ * Callback called to work a GET /proposal response.
+ *
+ * @param cls closure
+ * @param http_status HTTP status code of the request
+ * @param body JSON containing the response's payload.
+ * In case of errors, it contains the appropriate error encoding.
+ */
+typedef void
+(*TALER_MERCHANT_ProposalLookupOperationCallback) (void *cls,
+                                                   unsigned int http_status,
+                                                   const json_t *body);
 
 /**
- * Request backend to sign a contract (and add fields like wire transfer
- * details).
+ * PUT an order to the backend and receives the related proposal.
  *
  * @param ctx execution context
- * @param backend_uri base URI of the backend
- * @param contract prototype of the contract
- * @param contract_cb the callback to call when a reply for this request is 
available
- * @param contract_cb_cls closure for @a contract_cb
+ * @param backend_uri URI of the backend
+ * @param order basic information about this purchase, to be extended by the
+ * backend
+ * @param proposal_cb the callback to call when a reply for this request is 
available
+ * @param proposal_cb_cls closure for @a proposal_cb
  * @return a handle for this request
  */
-struct TALER_MERCHANT_ContractOperation *
-TALER_MERCHANT_contract_sign (struct GNUNET_CURL_Context *ctx,
-                              const char *backend_uri,
-                              const json_t *contract,
-                              TALER_MERCHANT_ContractCallback contract_cb,
-                              void *contract_cb_cls);
+struct TALER_MERCHANT_ProposalOperation *
+TALER_MERCHANT_order_put (struct GNUNET_CURL_Context *ctx,
+                          const char *backend_uri,
+                          const json_t *order,
+                          TALER_MERCHANT_ProposalCallback proposal_cb,
+                          void *proposal_cb_cls);
 
 
 /**
- * Cancel a /contract request.
+ * Cancel a PUT /proposal request.  This function cannot be used
+ * on a request handle if a response is already served for it.
  *
- * @param co the contract operation handle
+ * @param po the proposal operation request handle
  */
 void
-TALER_MERCHANT_contract_sign_cancel (struct TALER_MERCHANT_ContractOperation 
*co);
+TALER_MERCHANT_proposal_cancel (struct TALER_MERCHANT_ProposalOperation *po);
+
+
+/**
+ * Calls the GET /proposal API at the backend.  That is,
+ * retrieve a proposal data by providing its transaction id.
+ *
+ * @param ctx execution context
+ * @param backend_uri base URL of the merchant backend
+ * @param transaction_id transaction id used to perform the lookup
+ * @param plo_cb callback which will work the response gotten from the backend
+ * @param plo_cb_cls closure to pass to @a history_cb
+ * @return handle for this operation, NULL upon errors
+ */
+struct TALER_MERCHANT_ProposalLookupOperation *
+TALER_MERCHANT_proposal_lookup (struct GNUNET_CURL_Context *ctx,
+                                const char *backend_uri,
+                                const char *transaction_id,
+                                const char *instance,
+                                TALER_MERCHANT_ProposalLookupOperationCallback 
plo_cb,
+                                void *plo_cb_cls);
+
+
+/**
+ * Cancel a GET /proposal request.
+ *
+ * @param plo handle to the request to be canceled
+ */
+void
+TALER_MERCHANT_proposal_lookup_cancel (struct 
TALER_MERCHANT_ProposalLookupOperation *plo);
+
 
 
 /* *********************  /pay *********************** */
@@ -244,7 +239,6 @@ TALER_MERCHANT_pay_wallet (struct GNUNET_CURL_Context *ctx,
                           const char *merchant_uri,
                           const char *instance,
                            const struct GNUNET_HashCode *h_contract,
-                           uint64_t transaction_id,
                            const struct TALER_Amount *amount,
                            const struct TALER_Amount *max_fee,
                            const struct TALER_MerchantPublicKeyP *merchant_pub,
@@ -254,6 +248,7 @@ TALER_MERCHANT_pay_wallet (struct GNUNET_CURL_Context *ctx,
                            struct GNUNET_TIME_Absolute pay_deadline,
                            const struct GNUNET_HashCode *h_wire,
                           const char *exchange_uri,
+                           const char *order_id,
                            unsigned int num_coins,
                            const struct TALER_MERCHANT_PayCoin *coins,
                            TALER_MERCHANT_PayCallback pay_cb,
@@ -333,16 +328,8 @@ struct TALER_MERCHANT_PaidCoin
 struct TALER_MERCHANT_Pay *
 TALER_MERCHANT_pay_frontend (struct GNUNET_CURL_Context *ctx,
                             const char *merchant_uri,
-                            const char *instance,
-                             const struct GNUNET_HashCode *h_contract,
-                            const struct TALER_Amount *amount,
-                            const struct TALER_Amount *max_fee,
-                             uint64_t transaction_id,
-                             const struct TALER_MerchantSignatureP 
*merchant_sig,
-                             struct GNUNET_TIME_Absolute refund_deadline,
-                             struct GNUNET_TIME_Absolute pay_deadline,
-                             struct GNUNET_TIME_Absolute timestamp,
-                             struct GNUNET_TIME_Absolute 
wire_transfer_deadline,
+                             const struct TALER_MerchantPublicKeyP 
*merchant_pub,
+                            const char *order_id,
                             const char *exchange_uri,
                              unsigned int num_coins,
                              const struct TALER_MERCHANT_PaidCoin *coins,
@@ -506,9 +493,7 @@ typedef void
 (*TALER_MERCHANT_TrackTransactionCallback) (void *cls,
                                             unsigned int http_status,
                                            enum TALER_ErrorCode ec,
-                                            const json_t *json,
-                                            unsigned int num_transfers,
-                                            const struct 
TALER_MERCHANT_TransactionWireTransfer *transfers);
+                                            const json_t *json);
 
 
 /**
@@ -526,7 +511,7 @@ struct TALER_MERCHANT_TrackTransactionHandle *
 TALER_MERCHANT_track_transaction (struct GNUNET_CURL_Context *ctx,
                                   const char *backend_uri,
                                   const char *instance,
-                                  uint64_t transaction_id,
+                                  const char *order_id,
                                   TALER_MERCHANT_TrackTransactionCallback 
track_transaction_cb,
                                   void *track_transaction_cb_cls);
 
@@ -565,6 +550,9 @@ typedef void
  *
  * @param ctx execution context
  * @param backend_uri base URL of the merchant backend
+ * @param instance which merchant instance is performing this call
+ * @param start return `delta` records starting from position `start`
+ * @param delta return `delta` records starting from position `start`
  * @param date only transactions younger than/equals to date will be returned
  * @param history_cb callback which will work the response gotten from the 
backend
  * @param history_cb_cls closure to pass to history_cb
@@ -573,6 +561,9 @@ typedef void
 struct TALER_MERCHANT_HistoryOperation *
 TALER_MERCHANT_history (struct GNUNET_CURL_Context *ctx,
                         const char *backend_uri,
+                        const char *instance,
+                        unsigned int start,
+                        unsigned int delta,
                         struct GNUNET_TIME_Absolute date,
                         TALER_MERCHANT_HistoryOperationCallback history_cb,
                         void *history_cb_cls);
diff --git a/src/include/taler_merchantdb_plugin.h 
b/src/include/taler_merchantdb_plugin.h
index 3923fde..0dfbea8 100644
--- a/src/include/taler_merchantdb_plugin.h
+++ b/src/include/taler_merchantdb_plugin.h
@@ -32,13 +32,24 @@ struct TALER_MERCHANTDB_Plugin;
 
 
 /**
+ * Tipically called by `find_proposal_data_by_date`.
+ *
+ * @param cls closure
+ * @param order_id order id
+ * @param proposal_data proposal data related to order id
+ */
+ typedef void
+ (*TALER_MERCHANTDB_ProposalDataCallback)(void *cls,
+                                          const char *order_id,
+                                          const json_t *proposal_data);
+
+/**
  * Function called with information about a transaction.
  *
  * @param cls closure
- * @param transaction_id of the contract
  * @param merchant_pub merchant's public key
  * @param exchange_uri URI of the exchange
- * @param h_contract hash of the contract
+ * @param transaction_id proposal's transaction id
  * @param h_wire hash of our wire details
  * @param timestamp time of the confirmation
  * @param refund refund deadline
@@ -46,10 +57,9 @@ struct TALER_MERCHANTDB_Plugin;
  */
 typedef void
 (*TALER_MERCHANTDB_TransactionCallback)(void *cls,
-                                        uint64_t transaction_id,
                                        const struct TALER_MerchantPublicKeyP 
*merchant_pub,
                                         const char *exchange_uri,
-                                        const struct GNUNET_HashCode 
*h_contract,
+                                        const struct GNUNET_HashCode 
*h_proposal_data,
                                         const struct GNUNET_HashCode *h_wire,
                                         struct GNUNET_TIME_Absolute timestamp,
                                         struct GNUNET_TIME_Absolute refund,
@@ -69,7 +79,7 @@ typedef void
  */
 typedef void
 (*TALER_MERCHANTDB_CoinDepositCallback)(void *cls,
-                                        uint64_t transaction_id,
+                                        const struct GNUNET_HashCode 
*h_proposal_data,
                                         const struct TALER_CoinSpendPublicKeyP 
*coin_pub,
                                         const struct TALER_Amount 
*amount_with_fee,
                                         const struct TALER_Amount *deposit_fee,
@@ -95,7 +105,7 @@ typedef void
  */
 typedef void
 (*TALER_MERCHANTDB_TransferCallback)(void *cls,
-                                     uint64_t transaction_id,
+                                     const struct GNUNET_HashCode 
*h_proposal_data,
                                      const struct TALER_CoinSpendPublicKeyP 
*coin_pub,
                                      const struct 
TALER_WireTransferIdentifierRawP *wtid,
                                      struct GNUNET_TIME_Absolute 
execution_time,
@@ -150,32 +160,71 @@ struct TALER_MERCHANTDB_Plugin
 
 
   /**
-   * Insert a hash to contract map into the database
+   * Insert proposal data and its transaction id's hashcode into db
    *
    * @param cls closure
-   * @param h_contract hashcode of @a contract
-   * @param contract contract to store
+   * @param h_transaction_id hashcode of the transaction id mentioned in this
+   * proposal data
+   * @param proposal_data proposal data to store
    * @return #GNUNET_OK on success, #GNUNET_SYSERR upon error
    */
   int
-  (*store_map) (void *cls,
-                struct GNUNET_HashCode *h_contract,
-                const json_t *contract);
+  (*insert_proposal_data) (void *cls,
+                           const char *order_id,
+                           const struct TALER_MerchantPublicKeyP *merchant_pub,
+                           struct GNUNET_TIME_Absolute timestamp,
+                           const json_t *proposal_data);
+
+  /**
+   * Retrieve proposal data given its order ID.
+   *
+   * @param cls closure
+   * @param proposal_data where to store the result
+   * @param order_id order_id used to lookup.
+   * @param merchant_pub instance's public key.
+   * @return #GNUNET_OK on success, #GNUNET_NO if no contract is
+   * found, #GNUNET_SYSERR upon error
+   */
+  int
+  (*find_proposal_data) (void *cls,
+                         json_t **proposal_data,
+                         const char *order_id,
+                         const struct TALER_MerchantPublicKeyP *merchant_pub);
 
 
   /**
-   * Retrieve plain contract given its hashcode
+   * Retrieve proposal data given its hashcode
    *
    * @param cls closure
-   * @param h_contract hashcode of the contract to retrieve
-   * @param contract where to store the retrieved contract
+   * @param proposal_data where to store the result
+   * @param h_proposal_data hashcode used to lookup.
+   * @param merchant_pub instance's public key.
    * @return #GNUNET_OK on success, #GNUNET_NO if no contract is
    * found, #GNUNET_SYSERR upon error
    */
   int
-  (*find_contract) (void *cls,
-                    json_t **contract,
-                    struct GNUNET_HashCode *h_contract);
+  (*find_proposal_data_from_hash) (void *cls,
+                                   json_t **proposal_data,
+                                   const struct GNUNET_HashCode 
*h_proposal_data,
+                                   const struct TALER_MerchantPublicKeyP 
*merchant_pub);
+
+
+  /**
+   * Return proposal data and order id for all proposals younger than
+   * date.
+   *
+   * @param cls closure
+   * @param date limit to the oldest record
+   * @param cb callback called with proposal data and order id
+   * @param cb_cls closure for cb
+   */
+  int
+  (*find_proposal_data_by_date) (void *cls,
+                                 struct GNUNET_TIME_Absolute date,
+                                 const struct TALER_MerchantPublicKeyP 
*merchant_pub,
+                                 TALER_MERCHANTDB_ProposalDataCallback cb,
+                                 void *cb_cls);
+
 
   /**
    * Insert transaction data into the database.
@@ -193,10 +242,9 @@ struct TALER_MERCHANTDB_Plugin
    */
   int
   (*store_transaction) (void *cls,
-                        uint64_t transaction_id,
+                        const struct GNUNET_HashCode *h_proposal_data,
                        const struct TALER_MerchantPublicKeyP *merchant_pub,
                         const char *exchange_uri,
-                        const struct GNUNET_HashCode *h_contract,
                         const struct GNUNET_HashCode *h_wire,
                         struct GNUNET_TIME_Absolute timestamp,
                         struct GNUNET_TIME_Absolute refund,
@@ -218,7 +266,7 @@ struct TALER_MERCHANTDB_Plugin
    */
   int
   (*store_deposit) (void *cls,
-                    uint64_t transaction_id,
+                    const struct GNUNET_HashCode *h_proposal_data,
                     const struct TALER_MerchantPublicKeyP *merchant_pub,
                     const struct TALER_CoinSpendPublicKeyP *coin_pub,
                     const struct TALER_Amount *amount_with_fee,
@@ -240,7 +288,7 @@ struct TALER_MERCHANTDB_Plugin
    */
   int
   (*store_coin_to_transfer) (void *cls,
-                             uint64_t transaction_id,
+                             const struct GNUNET_HashCode *h_proposal_data,
                              const struct TALER_CoinSpendPublicKeyP *coin_pub,
                              const struct TALER_WireTransferIdentifierRawP 
*wtid);
 
@@ -294,7 +342,7 @@ struct TALER_MERCHANTDB_Plugin
    */
   int
   (*find_transaction) (void *cls,
-                       uint64_t transaction_id,
+                       const struct GNUNET_HashCode *h_proposal_data,
                       const struct TALER_MerchantPublicKeyP *merchant_pub,
                        TALER_MERCHANTDB_TransactionCallback cb,
                        void *cb_cls);
@@ -314,7 +362,7 @@ struct TALER_MERCHANTDB_Plugin
    */
   int
   (*find_payments) (void *cls,
-                    uint64_t transaction_id,
+                    const struct GNUNET_HashCode *h_proposal_data,
                     const struct TALER_MerchantPublicKeyP *merchant_pub,
                     TALER_MERCHANTDB_CoinDepositCallback cb,
                     void *cb_cls);
@@ -333,12 +381,12 @@ struct TALER_MERCHANTDB_Plugin
    *         #GNUNET_SYSERR on hard errors
    */
   int
-  (*find_payments_by_id_and_coin) (void *cls,
-                                   uint64_t transaction_id,
-                                   const struct TALER_MerchantPublicKeyP 
*merchant_pub,
-                                   const struct TALER_CoinSpendPublicKeyP 
*coin_pub,
-                                   TALER_MERCHANTDB_CoinDepositCallback cb,
-                                   void *cb_cls);
+  (*find_payments_by_hash_and_coin) (void *cls,
+                                     const struct GNUNET_HashCode 
*h_proposal_data,
+                                     const struct TALER_MerchantPublicKeyP 
*merchant_pub,
+                                     const struct TALER_CoinSpendPublicKeyP 
*coin_pub,
+                                     TALER_MERCHANTDB_CoinDepositCallback cb,
+                                     void *cb_cls);
 
 
   /**
@@ -356,10 +404,10 @@ struct TALER_MERCHANTDB_Plugin
    *         #GNUNET_SYSERR on hard errors
    */
   int
-  (*find_transfers_by_id) (void *cls,
-                           uint64_t transaction_id,
-                           TALER_MERCHANTDB_TransferCallback cb,
-                           void *cb_cls);
+  (*find_transfers_by_hash) (void *cls,
+                             const struct GNUNET_HashCode *h_proposal_data,
+                             TALER_MERCHANTDB_TransferCallback cb,
+                             void *cb_cls);
 
 
   /**
diff --git a/src/lib/Makefile.am b/src/lib/Makefile.am
index d862365..1e4a7cb 100644
--- a/src/lib/Makefile.am
+++ b/src/lib/Makefile.am
@@ -14,12 +14,11 @@ libtalermerchant_la_LDFLAGS = \
   -no-undefined
 
 libtalermerchant_la_SOURCES = \
-  merchant_api_contract.c \
+  merchant_api_proposal.c \
   merchant_api_pay.c \
   merchant_api_track_transaction.c \
   merchant_api_track_transfer.c \
-  merchant_api_history.c \
-  merchant_api_map.c
+  merchant_api_history.c
 
 libtalermerchant_la_LIBADD = \
   -ltalerexchange \
diff --git a/src/lib/merchant_api_contract.c b/src/lib/merchant_api_contract.c
deleted file mode 100644
index c5db8d3..0000000
--- a/src/lib/merchant_api_contract.c
+++ /dev/null
@@ -1,239 +0,0 @@
-/*
-  This file is part of TALER
-  Copyright (C) 2014, 2015, 2016 GNUnet e.V. and INRIA
-
-  TALER is free software; you can redistribute it and/or modify it under the
-  terms of the GNU Lesser General Public License as published by the Free 
Software
-  Foundation; either version 2.1, 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 Lesser General Public License for more 
details.
-
-  You should have received a copy of the GNU Lesser General Public License 
along with
-  TALER; see the file COPYING.LGPL.  If not, see
-  <http://www.gnu.org/licenses/>
-*/
-/**
- * @file lib/merchant_api_contract.c
- * @brief Implementation of the /contract request of the merchant's HTTP API
- * @author Christian Grothoff
- */
-#include "platform.h"
-#include <curl/curl.h>
-#include <jansson.h>
-#include <microhttpd.h> /* just for HTTP status codes */
-#include <gnunet/gnunet_util_lib.h>
-#include <gnunet/gnunet_curl_lib.h>
-#include "taler_merchant_service.h"
-#include <taler/taler_json_lib.h>
-#include <taler/taler_signatures.h>
-
-
-/**
- * @brief A Contract Operation Handle
- */
-struct TALER_MERCHANT_ContractOperation
-{
-
-  /**
-   * The url for this request.
-   */
-  char *url;
-
-  /**
-   * JSON encoding of the request to POST.
-   */
-  char *json_enc;
-
-  /**
-   * Handle for the request.
-   */
-  struct GNUNET_CURL_Job *job;
-
-  /**
-   * Function to call with the result.
-   */
-  TALER_MERCHANT_ContractCallback cb;
-
-  /**
-   * Closure for @a cb.
-   */
-  void *cb_cls;
-
-  /**
-   * Reference to the execution context.
-   */
-  struct GNUNET_CURL_Context *ctx;
-};
-
-
-/**
- * Function called when we're done processing the
- * HTTP /contract request.
- *
- * @param cls the `struct TALER_MERCHANT_Pay`
- * @param response_code HTTP response code, 0 on error
- * @param json response body, NULL if not in JSON
- */
-static void
-handle_contract_finished (void *cls,
-                          long response_code,
-                          const json_t *json)
-{
-  struct TALER_MERCHANT_ContractOperation *co = cls;
-  json_t *contract;
-  const struct TALER_MerchantSignatureP *sigp;
-  const struct GNUNET_HashCode *h_contractp;
-  struct TALER_MerchantSignatureP sig;
-  struct GNUNET_HashCode h_contract;
-
-  co->job = NULL;
-  contract = NULL;
-  sigp = NULL;
-  h_contractp = NULL;
-  switch (response_code)
-  {
-    case 0:
-      break;
-    case MHD_HTTP_OK:
-    {
-      struct GNUNET_JSON_Specification spec[] = {
-        GNUNET_JSON_spec_json ("contract", &contract),
-        GNUNET_JSON_spec_fixed_auto ("merchant_sig", &sig),
-        GNUNET_JSON_spec_fixed_auto ("H_contract", &h_contract),
-        GNUNET_JSON_spec_end()
-      };
-  
-      if (GNUNET_OK !=
-          GNUNET_JSON_parse (json,
-                             spec,
-                             NULL, NULL))
-      {
-        GNUNET_break_op (0);
-        response_code = 0;
-        break;
-      }
-      h_contractp = &h_contract;
-      sigp = &sig;
-    }
-      break;
-    case MHD_HTTP_BAD_REQUEST:
-      /* This should never happen, either us or the merchant is buggy
-         (or API version conflict); just pass JSON reply to the application */
-      break;
-    case MHD_HTTP_FORBIDDEN:
-      break;
-    case MHD_HTTP_UNAUTHORIZED:
-      /* Nothing really to verify, merchant says one of the signatures is
-         invalid; as we checked them, this should never happen, we
-         should pass the JSON reply to the application */
-      break;
-    case MHD_HTTP_NOT_FOUND:
-      /* Nothing really to verify, this should never
-         happen, we should pass the JSON reply to the application */
-      break;
-    case MHD_HTTP_INTERNAL_SERVER_ERROR:
-      /* Server had an internal issue; we should retry, but this API
-         leaves this to the application */
-      break;
-    default:
-      /* unexpected response code */
-      GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                  "Unexpected response code %u\n",
-                  (unsigned int) response_code);
-      GNUNET_break (0);
-      response_code = 0;
-  }
-  co->cb (co->cb_cls,
-          response_code,
-         TALER_JSON_get_error_code (json),
-          json,
-          contract,
-          sigp,
-          h_contractp);
-  if (NULL != contract)
-    json_decref (contract);
-}
-
-
-/**
- * Request backend to sign a contract (and add fields like wire transfer
- * details).
- *
- * @param ctx execution context
- * @param backend_uri URI of the backend
- * @param contract prototype of the contract
- * @param contract_cb the callback to call when a reply for this request is 
available
- * @param contract_cb_cls closure for @a contract_cb
- * @return a handle for this request
- */
-struct TALER_MERCHANT_ContractOperation *
-TALER_MERCHANT_contract_sign (struct GNUNET_CURL_Context *ctx,
-                              const char *backend_uri,
-                              const json_t *contract,
-                              TALER_MERCHANT_ContractCallback contract_cb,
-                              void *contract_cb_cls)
-{
-  struct TALER_MERCHANT_ContractOperation *co;
-  json_t *req;
-  CURL *eh;
-
-  co = GNUNET_new (struct TALER_MERCHANT_ContractOperation);
-  co->ctx = ctx;
-  co->cb = contract_cb;
-  co->cb_cls = contract_cb_cls;
-  GNUNET_asprintf (&co->url,
-                   "%s%s",
-                   backend_uri,
-                   "/contract");
-
-  req = json_pack ("{s:O}",
-                   "contract", (json_t *) contract);
-  eh = curl_easy_init ();
-  GNUNET_assert (NULL != (co->json_enc =
-                          json_dumps (req,
-                                      JSON_COMPACT)));
-  json_decref (req);
-  GNUNET_assert (CURLE_OK ==
-                 curl_easy_setopt (eh,
-                                   CURLOPT_URL,
-                                   co->url));
-  GNUNET_assert (CURLE_OK ==
-                 curl_easy_setopt (eh,
-                                   CURLOPT_POSTFIELDS,
-                                   co->json_enc));
-  GNUNET_assert (CURLE_OK ==
-                 curl_easy_setopt (eh,
-                                   CURLOPT_POSTFIELDSIZE,
-                                   strlen (co->json_enc)));
-  co->job = GNUNET_CURL_job_add (ctx,
-                                 eh,
-                                 GNUNET_YES,
-                                 &handle_contract_finished,
-                                 co);
-  return co;
-}
-
-
-/**
- * Cancel a /contract request.  This function cannot be used
- * on a request handle if a response is already served for it.
- *
- * @param co the contract operation request handle
- */
-void
-TALER_MERCHANT_contract_sign_cancel (struct TALER_MERCHANT_ContractOperation 
*co)
-{
-  if (NULL != co->job)
-  {
-    GNUNET_CURL_job_cancel (co->job);
-    co->job = NULL;
-  }
-  GNUNET_free (co->url);
-  GNUNET_free (co->json_enc);
-  GNUNET_free (co);
-}
-
-
-/* end of merchant_api_contract.c */
diff --git a/src/lib/merchant_api_history.c b/src/lib/merchant_api_history.c
index 39f9bd8..69d09b8 100644
--- a/src/lib/merchant_api_history.c
+++ b/src/lib/merchant_api_history.c
@@ -113,7 +113,7 @@ history_raw_cb (void *cls,
     break;
   case MHD_HTTP_BAD_REQUEST:
     GNUNET_log (GNUNET_ERROR_TYPE_INFO,
-               "Wrong parameter passed in URL\n");
+               "Wrong/missing URL parameter\n");
     break;
   default:
     /* unexpected response code */
@@ -136,6 +136,9 @@ history_raw_cb (void *cls,
  *
  * @param ctx execution context
  * @param backend_uri base URL of the merchant backend
+ * @param instance which merchant instance is performing this call
+ * @param start return `delta` records starting from position `start`
+ * @param delta return `delta` records starting from position `start`
  * @param date only transactions younger than/equals to date will be returned
  * @param history_cb callback which will work the response gotten from the 
backend
  * @param history_cb_cls closure to pass to @a history_cb
@@ -144,6 +147,9 @@ history_raw_cb (void *cls,
 struct TALER_MERCHANT_HistoryOperation *
 TALER_MERCHANT_history (struct GNUNET_CURL_Context *ctx,
                         const char *backend_uri,
+                        const char *instance,
+                        unsigned int start,
+                        unsigned int delta,
                         struct GNUNET_TIME_Absolute date,
                         TALER_MERCHANT_HistoryOperationCallback history_cb,
                         void *history_cb_cls)
@@ -158,9 +164,12 @@ TALER_MERCHANT_history (struct GNUNET_CURL_Context *ctx,
   ho->cb_cls = history_cb_cls;
   seconds = date.abs_value_us / 1000LL / 1000LL;
   GNUNET_asprintf (&ho->url,
-                   "%s/history?date=%llu",
+                   "%s/history?date=%llu&instance=%s&start=%d&delta=%d",
                    backend_uri,
-                   seconds);
+                   seconds,
+                   instance,
+                   start,
+                   delta);
   eh = curl_easy_init ();
   if (CURLE_OK != curl_easy_setopt (eh,
                                     CURLOPT_URL,
diff --git a/src/lib/merchant_api_map.c b/src/lib/merchant_api_map.c
deleted file mode 100644
index d1aaf5a..0000000
--- a/src/lib/merchant_api_map.c
+++ /dev/null
@@ -1,230 +0,0 @@
-/*
-  This file is part of TALER
-  Copyright (C) 2014, 2015, 2016 GNUnet e.V. and INRIA
-
-  TALER is free software; you can redistribute it and/or modify it under the
-  terms of the GNU Lesser General Public License as published by the Free 
Software
-  Foundation; either version 2.1, 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 Lesser General Public License for more 
details.
-
-  You should have received a copy of the GNU Lesser General Public License 
along with
-  TALER; see the file COPYING.LGPL.  If not, see
-  <http://www.gnu.org/licenses/>
-*/
-/**
- * @file lib/merchant_api_map.c
- * @brief Implementation of the /map/{in,out} request of the merchant's HTTP 
API
- * @author Marcello Stanisci
- */
-#include "platform.h"
-#include <curl/curl.h>
-#include <jansson.h>
-#include <microhttpd.h> /* just for HTTP status codes */
-#include <gnunet/gnunet_util_lib.h>
-#include <gnunet/gnunet_curl_lib.h>
-#include "taler_merchant_service.h"
-#include <taler/taler_json_lib.h>
-
-
-/**
- * This structure acts like a "handle" for both /map/in and
- * /map/out operations, as they only differ about the 'json_enc'
- * field (which is just left NULL when not needed).
- */
-struct TALER_MERCHANT_MapOperation
-{
-  /**
-   * Full URI, includes "/map/in".
-   */
-  char *url;
-
-  /**
-   * Request's body.  Left NULL in case of /map/out.
-   */
-  char *json_enc;
-
-  /**
-   * Handle for the request.
-   */
-  struct GNUNET_CURL_Job *job;
-
-  /**
-   * Function to call with the result.
-   */
-  TALER_MERCHANT_MapOperationCallback cb;
-
-  /**
-   * Closure for @a cb.
-   */
-  void *cb_cls;
-
-  /**
-   * Reference to the execution context.
-   */
-  struct GNUNET_CURL_Context *ctx;
-
-};
-
-
-/**
- * Cancel a /map/{in,out} request.
- *
- * @param mio handle to the request to be canceled
- */
-void
-TALER_MERCHANT_map_cancel (struct TALER_MERCHANT_MapOperation *mo)
-{
-  if (NULL != mo->job)
-  {
-    GNUNET_CURL_job_cancel (mo->job);
-    mo->job = NULL;
-  }
-  GNUNET_free (mo->url);
-  GNUNET_free_non_null (mo->json_enc);
-  GNUNET_free (mo);
-}
-
-
-/**
- * Function called when we're done processing the HTTP /map/{in,out} request.
- *
- * @param cls the `struct TALER_MERCHANT_MapInOperation`
- * @param response_code HTTP response code, 0 on error
- * @param json response body, should be NULL
- */
-static void
-handle_map_finished (void *cls,
-                     long response_code,
-                     const json_t *json)
-{
-  struct TALER_MERCHANT_MapOperation *mo = cls;
-
-  /**
-   * As no data is supposed to be extracted from this
-   * call, we just invoke the provided callback from here.
-   */
-  mo->cb (mo->cb_cls,
-          response_code,
-          json);
-}
-
-/**
- * Issue a /map/out request to the backend.
- *
- * @param ctx execution context
- * @param backend_uri base URL of the merchant backend
- * @param h_contract hashcode of `contract`
- * @param map_in_cb callback which will work the response gotten from the 
backend
- * @param map_in_cb_cls closure to pass to @a history_cb
- * @return handle for this operation, NULL upon errors
- */
-struct TALER_MERCHANT_MapOperation *
-TALER_MERCHANT_map_out (struct GNUNET_CURL_Context *ctx,
-                        const char *backend_uri,
-                        const struct GNUNET_HashCode *h_contract,
-                        TALER_MERCHANT_MapOperationCallback map_cb,
-                        void *map_cb_cls)
-{
-  struct TALER_MERCHANT_MapOperation *mo;
-  CURL *eh;
-  char *hash_enc;
-
-  mo = GNUNET_new (struct TALER_MERCHANT_MapOperation);
-  mo->ctx = ctx;
-  mo->cb = map_cb;
-  mo->cb_cls = map_cb_cls;
-
-  hash_enc = GNUNET_STRINGS_data_to_string_alloc (h_contract,
-                                                  sizeof (struct 
GNUNET_HashCode));
-  GNUNET_asprintf (&mo->url,
-                   "%s/map/out?h_contract=%s",
-                   backend_uri,
-                   hash_enc);
-  eh = curl_easy_init ();
-  if (CURLE_OK != curl_easy_setopt (eh,
-                                    CURLOPT_URL,
-                                    mo->url))
-  {
-    GNUNET_break (0);  
-    return NULL;
-  }
-
-  if (NULL == (mo->job = GNUNET_CURL_job_add (ctx,
-                                              eh,
-                                              GNUNET_YES,
-                                              &handle_map_finished,
-                                              mo)))
-  {
-    GNUNET_break (0);
-    return NULL;
-  }
-  return mo;
-}
-
-/**
- * Issue a /map/in request to the backend.
- *
- * @param ctx execution context
- * @param backend_uri base URL of the merchant backend
- * @param contract contract to store
- * @param h_contract hashcode of `contract`
- * @param map_in_cb callback which will work the response gotten from the 
backend
- * @param map_in_cb_cls closure to pass to @a history_cb
- * @return handle for this operation, NULL upon errors
- */
-struct TALER_MERCHANT_MapOperation *
-TALER_MERCHANT_map_in (struct GNUNET_CURL_Context *ctx,
-                       const char *backend_uri,
-                       const json_t *contract,
-                       const struct GNUNET_HashCode *h_contract,
-                       TALER_MERCHANT_MapOperationCallback map_cb,
-                       void *map_cb_cls)
-{
-  struct TALER_MERCHANT_MapOperation *mo;
-  CURL *eh;
-  json_t *req;
-  
-  mo = GNUNET_new (struct TALER_MERCHANT_MapOperation);
-  mo->ctx = ctx;
-  mo->cb = map_cb;
-  mo->cb_cls = map_cb_cls;
-
-  GNUNET_asprintf (&mo->url,
-                   "%s%s",
-                   backend_uri,
-                   "/map/in");
-
-  // build final json
-  req = json_pack ("{s:o, s:o}",
-                   "contract", contract,
-                   "h_contract", GNUNET_JSON_from_data_auto (h_contract));
-
-  GNUNET_assert (NULL !=
-                  (mo->json_enc = json_dumps (req, JSON_COMPACT))
-                );
-
-  json_decref (req);
-  eh = curl_easy_init ();
-
-  GNUNET_assert (CURLE_OK ==
-                 curl_easy_setopt (eh,
-                                   CURLOPT_URL,
-                                   mo->url));
-  GNUNET_assert (CURLE_OK ==
-                 curl_easy_setopt (eh,
-                                   CURLOPT_POSTFIELDS,
-                                   mo->json_enc));
-  GNUNET_assert (CURLE_OK ==
-                 curl_easy_setopt (eh,
-                                   CURLOPT_POSTFIELDSIZE,
-                                   strlen (mo->json_enc)));
-  mo->job = GNUNET_CURL_job_add (ctx,
-                                 eh,
-                                 GNUNET_YES,
-                                 &handle_map_finished,
-                                 mo);
-  return mo;
-}
diff --git a/src/lib/merchant_api_pay.c b/src/lib/merchant_api_pay.c
index 5475ec7..6910bde 100644
--- a/src/lib/merchant_api_pay.c
+++ b/src/lib/merchant_api_pay.c
@@ -278,8 +278,7 @@ struct TALER_MERCHANT_Pay *
 TALER_MERCHANT_pay_wallet (struct GNUNET_CURL_Context *ctx,
                           const char *merchant_uri,
                           const char *instance,
-                           const struct GNUNET_HashCode *h_contract,
-                           uint64_t transaction_id,
+                           const struct GNUNET_HashCode *h_proposal_data,
                           const struct TALER_Amount *amount,
                           const struct TALER_Amount *max_fee,
                            const struct TALER_MerchantPublicKeyP *merchant_pub,
@@ -289,6 +288,7 @@ TALER_MERCHANT_pay_wallet (struct GNUNET_CURL_Context *ctx,
                            struct GNUNET_TIME_Absolute pay_deadline,
                            const struct GNUNET_HashCode *h_wire,
                           const char *exchange_uri,
+                           const char *order_id,
                            unsigned int num_coins,
                            const struct TALER_MERCHANT_PayCoin *coins,
                            TALER_MERCHANT_PayCallback pay_cb,
@@ -302,13 +302,20 @@ TALER_MERCHANT_pay_wallet (struct GNUNET_CURL_Context 
*ctx,
   (void) GNUNET_TIME_round_abs (&pay_deadline);
   (void) GNUNET_TIME_round_abs (&refund_deadline);
 
+  if (GNUNET_YES !=
+      TALER_amount_cmp_currency (amount,
+                                 max_fee))
+  {
+    GNUNET_break (0);
+    return NULL;
+  }
+
   dr.purpose.purpose = htonl (TALER_SIGNATURE_WALLET_COIN_DEPOSIT);
   dr.purpose.size = htonl (sizeof (struct TALER_DepositRequestPS));
-  dr.h_contract = *h_contract;
+  dr.h_proposal_data = *h_proposal_data;
   dr.h_wire = *h_wire;
   dr.timestamp = GNUNET_TIME_absolute_hton (timestamp);
   dr.refund_deadline = GNUNET_TIME_absolute_hton (refund_deadline);
-  dr.transaction_id = GNUNET_htonll (transaction_id);
   dr.merchant = *merchant_pub;
   for (i=0;i<num_coins;i++)
   {
@@ -333,6 +340,7 @@ TALER_MERCHANT_pay_wallet (struct GNUNET_CURL_Context *ctx,
     }
     TALER_amount_hton (&dr.deposit_fee,
                       &fee);
+
     GNUNET_CRYPTO_eddsa_sign (&coin->coin_priv.eddsa_priv,
                              &dr.purpose,
                              &p->coin_sig.eddsa_signature);
@@ -345,16 +353,8 @@ TALER_MERCHANT_pay_wallet (struct GNUNET_CURL_Context *ctx,
   }
   return TALER_MERCHANT_pay_frontend (ctx,
                                      merchant_uri,
-                                      instance,
-                                     h_contract,
-                                      amount,
-                                     max_fee,
-                                     transaction_id,
-                                     merchant_sig,
-                                     refund_deadline,
-                                     pay_deadline,
-                                     timestamp,
-                                     GNUNET_TIME_UNIT_ZERO_ABS,
+                                      merchant_pub,
+                                      order_id,
                                      exchange_uri,
                                      num_coins,
                                      pc,
@@ -371,19 +371,9 @@ TALER_MERCHANT_pay_wallet (struct GNUNET_CURL_Context *ctx,
  *
  * @param ctx the execution loop context
  * @param merchant_uri base URI of the merchant's backend
- * @param instance which merchant instance will receive this payment
- * @param h_contract hash of the contact of the merchant with the customer
- * @param timestamp timestamp when the contract was finalized, must match 
approximately the current time of the merchant
- * @param transaction_id transaction id for the transaction between merchant 
and customer
- * @param refund_deadline date until which the merchant can issue a refund to 
the customer via the merchant (can be zero if refunds are not allowed)
- * @param deadline to pay for this contract
- * @param wire_transfer_deadline date by which the merchant would like the 
exchange to execute the wire transfer (can be zero if there is no specific date 
desired by the frontend). If non-zero, must be larger than @a refund_deadline.
  * @param exchange_uri URI of the exchange that the coins belong to
  * @param num_coins number of coins used to pay
  * @param coins array of coins we use to pay
- * @param coin_sig the signature made with purpose 
#TALER_SIGNATURE_WALLET_COIN_DEPOSIT made by the customer with the coin’s 
private key.
- * @param max_fee maximum fee covered by the merchant (according to the 
contract)
- * @param amount total value of the contract to be paid to the merchant
  * @param pay_cb the callback to call when a reply for this request is 
available
  * @param pay_cb_cls closure for @a pay_cb
  * @return a handle for this request
@@ -391,16 +381,8 @@ TALER_MERCHANT_pay_wallet (struct GNUNET_CURL_Context *ctx,
 struct TALER_MERCHANT_Pay *
 TALER_MERCHANT_pay_frontend (struct GNUNET_CURL_Context *ctx,
                             const char *merchant_uri,
-                            const char *instance,
-                             const struct GNUNET_HashCode *h_contract,
-                            const struct TALER_Amount *amount,
-                            const struct TALER_Amount *max_fee,
-                             uint64_t transaction_id,
-                             const struct TALER_MerchantSignatureP 
*merchant_sig,
-                             struct GNUNET_TIME_Absolute refund_deadline,
-                             struct GNUNET_TIME_Absolute pay_deadline,
-                             struct GNUNET_TIME_Absolute timestamp,
-                             struct GNUNET_TIME_Absolute 
wire_transfer_deadline,
+                             const struct TALER_MerchantPublicKeyP 
*merchant_pub,
+                             const char *order_id,
                             const char *exchange_uri,
                              unsigned int num_coins,
                              const struct TALER_MERCHANT_PaidCoin *coins,
@@ -415,23 +397,6 @@ TALER_MERCHANT_pay_frontend (struct GNUNET_CURL_Context 
*ctx,
   struct TALER_Amount total_amount;
   unsigned int i;
 
-  (void) GNUNET_TIME_round_abs (&timestamp);
-  (void) GNUNET_TIME_round_abs (&refund_deadline);
-  (void) GNUNET_TIME_round_abs (&wire_transfer_deadline);
-
-  if (GNUNET_YES !=
-      TALER_amount_cmp_currency (amount,
-                                 max_fee))
-  {
-    GNUNET_break (0);
-    return NULL;
-  }
-  if ( (0 != wire_transfer_deadline.abs_value_us) &&
-       (wire_transfer_deadline.abs_value_us < refund_deadline.abs_value_us) )
-  {
-    GNUNET_break (0);
-    return NULL;
-  }
   if (0 == num_coins)
   {
     GNUNET_break (0);
@@ -493,102 +458,16 @@ TALER_MERCHANT_pay_frontend (struct GNUNET_CURL_Context 
*ctx,
                                           j_coin));
   }
 
-  { /* Sanity check that total_amount and total_fee
-       match amount/max_fee requirements */
-    struct TALER_Amount fee_left;
-
-    if (GNUNET_OK ==
-       TALER_amount_subtract (&fee_left,
-                              &total_fee,
-                              max_fee))
-    {
-      /* Wallet must cover part of the fee! */
-      struct TALER_Amount new_amount;
-
-      if (GNUNET_OK !=
-         TALER_amount_add (&new_amount,
-                           &fee_left,
-                           amount))
-      {
-       /* integer overflow */
-       GNUNET_break (0);
-       json_decref (j_coins);
-       return NULL;
-      }
-      if (GNUNET_YES !=
-          TALER_amount_cmp_currency (&new_amount,
-                                     &total_amount))
-      {
-        GNUNET_break (0);
-       json_decref (j_coins);
-        return NULL;
-      }
-      if (1 ==
-         TALER_amount_cmp (&new_amount,
-                           &total_amount))
-      {
-       /* new_amount > total_amount: all of the coins (total_amount)
-          do not add up to at least the new_amount owed to the
-          merchant, this request is bogus, abort */
-       GNUNET_break (0);
-       json_decref (j_coins);
-       return NULL;
-      }
-    }
-    else
-    {
-      /* Full fee covered by merchant, but our total
-        must at least cover the total contract amount */
-      if (GNUNET_YES !=
-          TALER_amount_cmp_currency (amount,
-                                     &total_amount))
-      {
-        GNUNET_break (0);
-       json_decref (j_coins);
-        return NULL;
-      }
-      if (1 ==
-         TALER_amount_cmp (amount,
-                           &total_amount))
-       {
-         /* amount > total_amount: all of the coins (total_amount) do
-          not add up to at least the amount owed to the merchant,
-          this request is bogus, abort */
-       GNUNET_break (0);
-       json_decref (j_coins);
-       return NULL;
-      }
-    }
-  } /* end of sanity check */
-
-  pay_obj = json_pack ("{s:o," /* H_contract */
-                       " s:I, s:o," /* transaction id, timestamp */
-                       " s:o, s:o," /* refund_deadline, pay_deadline */
+  pay_obj = json_pack ("{"
                        " s:s," /* exchange */
-                       " s:o, s:o," /* coins, max_fee */
-                       " s:o, s:o}",/* amount, signature */
-                       "H_contract", GNUNET_JSON_from_data_auto (h_contract),
-                       "transaction_id", (json_int_t) transaction_id,
-                       "timestamp", GNUNET_JSON_from_time_abs (timestamp),
-                       "refund_deadline", GNUNET_JSON_from_time_abs 
(refund_deadline),
-                       "pay_deadline", GNUNET_JSON_from_time_abs 
(pay_deadline),
+                       " s:o," /* coins */
+                       " s:s," /* order_id */
+                       " s:o," /* merchant_pub */
+                       "}",
                       "exchange", exchange_uri,
                       "coins", j_coins,
-                       "max_fee", TALER_JSON_from_amount (max_fee),
-                       "amount", TALER_JSON_from_amount (amount),
-                       "merchant_sig", GNUNET_JSON_from_data_auto 
(merchant_sig));
-  if (NULL != instance)
-    json_object_set_new (pay_obj,
-                         "instance",
-                         json_string (instance));
-
-  if (0 != wire_transfer_deadline.abs_value_us)
-  {
-    /* Frontend did have an execution date in mind, add it */
-    json_object_set_new (pay_obj,
-                        "wire_transfer_deadline",
-                        GNUNET_JSON_from_time_abs (wire_transfer_deadline));
-  }
+                       "order_id", order_id,
+                       "merchant_pub", GNUNET_JSON_from_data_auto 
(merchant_pub));
 
   ph = GNUNET_new (struct TALER_MERCHANT_Pay);
   ph->ctx = ctx;
diff --git a/src/lib/merchant_api_proposal.c b/src/lib/merchant_api_proposal.c
new file mode 100644
index 0000000..c3e5873
--- /dev/null
+++ b/src/lib/merchant_api_proposal.c
@@ -0,0 +1,366 @@
+/*
+  This file is part of TALER
+  Copyright (C) 2014, 2015, 2016 GNUnet e.V. and INRIA
+
+  TALER is free software; you can redistribute it and/or modify it under the
+  terms of the GNU Lesser General Public License as published by the Free 
Software
+  Foundation; either version 2.1, 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 Lesser General Public License for more 
details.
+
+  You should have received a copy of the GNU Lesser General Public License 
along with
+  TALER; see the file COPYING.LGPL.  If not, see
+  <http://www.gnu.org/licenses/>
+*/
+/**
+ * @file lib/merchant_api_proposal.c
+ * @brief Implementation of the /proposal PUT and GET
+ * @author Christian Grothoff
+ * @author Marcello Stanisci
+ */
+#include "platform.h"
+#include <curl/curl.h>
+#include <jansson.h>
+#include <microhttpd.h> /* just for HTTP status codes */
+#include <gnunet/gnunet_util_lib.h>
+#include <gnunet/gnunet_curl_lib.h>
+#include "taler_merchant_service.h"
+#include <taler/taler_json_lib.h>
+#include <taler/taler_signatures.h>
+
+
+/**
+ * @brief A Contract Operation Handle
+ */
+struct TALER_MERCHANT_ProposalOperation
+{
+
+  /**
+   * The url for this request.
+   */
+  char *url;
+
+  /**
+   * JSON encoding of the request to POST.
+   */
+  char *json_enc;
+
+  /**
+   * Handle for the request.
+   */
+  struct GNUNET_CURL_Job *job;
+
+  /**
+   * Function to call with the result.
+   */
+  TALER_MERCHANT_ProposalCallback cb;
+
+  /**
+   * Closure for @a cb.
+   */
+  void *cb_cls;
+
+  /**
+   * Reference to the execution context.
+   */
+  struct GNUNET_CURL_Context *ctx;
+};
+
+/**
+ * Structure representing a GET /proposal operation.
+ */
+struct TALER_MERCHANT_ProposalLookupOperation
+{
+  /**
+   * Full URI, includes "/proposal".
+   */
+  char *url;
+
+  /**
+   * Handle for the request.
+   */
+  struct GNUNET_CURL_Job *job;
+
+  /**
+   * Function to call with the result.
+   */
+  TALER_MERCHANT_ProposalLookupOperationCallback cb;
+
+  /**
+   * Closure for @a cb.
+   */
+  void *cb_cls;
+
+  /**
+   * Reference to the execution context.
+   */
+  struct GNUNET_CURL_Context *ctx;
+
+};
+
+
+/**
+ * Function called when we're done processing the
+ * HTTP PUT /proposal request.
+ *
+ * @param cls the `struct TALER_MERCHANT_ProposalOperation`
+ * @param response_code HTTP response code, 0 on error
+ * @param json response body, NULL if not in JSON
+ */
+static void
+handle_proposal_finished (void *cls,
+                          long response_code,
+                          const json_t *json)
+{
+  struct TALER_MERCHANT_ProposalOperation *po = cls;
+  json_t *proposal_data;
+  const struct TALER_MerchantSignatureP *sigp;
+  const struct GNUNET_HashCode *hashp;
+  struct TALER_MerchantSignatureP sig;
+  struct GNUNET_HashCode hash;
+
+  po->job = NULL;
+  proposal_data = NULL;
+  sigp = NULL;
+  hashp = NULL;
+  switch (response_code)
+  {
+    case 0:
+      break;
+    case MHD_HTTP_OK:
+    {
+      struct GNUNET_JSON_Specification spec[] = {
+        GNUNET_JSON_spec_json ("data", &proposal_data),
+        GNUNET_JSON_spec_fixed_auto ("sig", &sig),
+        GNUNET_JSON_spec_fixed_auto ("hash", &hash),
+        GNUNET_JSON_spec_end()
+      };
+  
+      if (GNUNET_OK !=
+          GNUNET_JSON_parse (json,
+                             spec,
+                             NULL, NULL))
+      {
+        GNUNET_break_op (0);
+        response_code = 0;
+        break;
+      }
+      hashp = &hash;
+      sigp = &sig;
+    }
+      break;
+    case MHD_HTTP_BAD_REQUEST:
+      /* This should never happen, either us or the merchant is buggy
+         (or API version conflict); just pass JSON reply to the application */
+      break;
+    case MHD_HTTP_FORBIDDEN:
+      break;
+    case MHD_HTTP_UNAUTHORIZED:
+      /* Nothing really to verify, merchant says one of the signatures is
+         invalid; as we checked them, this should never happen, we
+         should pass the JSON reply to the application */
+      break;
+    case MHD_HTTP_NOT_FOUND:
+      /* Nothing really to verify, this should never
+         happen, we should pass the JSON reply to the application */
+      break;
+    case MHD_HTTP_INTERNAL_SERVER_ERROR:
+      /* Server had an internal issue; we should retry, but this API
+         leaves this to the application */
+      break;
+    default:
+      /* unexpected response code */
+      GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                  "Unexpected response code %u\n",
+                  (unsigned int) response_code);
+      GNUNET_break (0);
+      response_code = 0;
+  }
+  po->cb (po->cb_cls,
+          response_code,
+         TALER_JSON_get_error_code (json),
+          json,
+          proposal_data,
+          sigp,
+          hashp);
+  if (NULL != proposal_data)
+    json_decref (proposal_data);
+}
+
+
+/**
+ * PUT an order to the backend and receives the related proposal.
+ *
+ * @param ctx execution context
+ * @param backend_uri URI of the backend
+ * @param order basic information about this purchase, to be extended by the
+ * backend
+ * @param proposal_cb the callback to call when a reply for this request is
+ * available
+ * @param proposal_cb_cls closure for @a proposal_cb
+ * @return a handle for this request
+ */
+struct TALER_MERCHANT_ProposalOperation *
+TALER_MERCHANT_order_put (struct GNUNET_CURL_Context *ctx,
+                          const char *backend_uri,
+                          const json_t *order,
+                          TALER_MERCHANT_ProposalCallback proposal_cb,
+                          void *proposal_cb_cls)
+{
+  struct TALER_MERCHANT_ProposalOperation *po;
+  json_t *req;
+  CURL *eh;
+
+  po = GNUNET_new (struct TALER_MERCHANT_ProposalOperation);
+  po->ctx = ctx;
+  po->cb = proposal_cb;
+  po->cb_cls = proposal_cb_cls;
+  GNUNET_asprintf (&po->url,
+                   "%s%s",
+                   backend_uri,
+                   "/proposal");
+
+  req = json_pack ("{s:O}",
+                   "order", (json_t *) order);
+  eh = curl_easy_init ();
+  GNUNET_assert (NULL != (po->json_enc =
+                          json_dumps (req,
+                                      JSON_COMPACT)));
+  json_decref (req);
+  GNUNET_assert (CURLE_OK ==
+                 curl_easy_setopt (eh,
+                                   CURLOPT_URL,
+                                   po->url));
+  /* FIXME: as for the specs, POST becomes PUT */
+  GNUNET_assert (CURLE_OK ==
+                 curl_easy_setopt (eh,
+                                   CURLOPT_POSTFIELDS,
+                                   po->json_enc));
+  GNUNET_assert (CURLE_OK ==
+                 curl_easy_setopt (eh,
+                                   CURLOPT_POSTFIELDSIZE,
+                                   strlen (po->json_enc)));
+  po->job = GNUNET_CURL_job_add (ctx,
+                                 eh,
+                                 GNUNET_YES,
+                                 &handle_proposal_finished,
+                                 po);
+  return po;
+}
+
+/**
+ * Function called when we're done processing the GET /proposal request.
+ *
+ * @param cls the `struct TALER_MERCHANT_ProposalLookupOperation`
+ * @param response_code HTTP response code, 0 on error
+ * @param json response body, should be NULL
+ */
+static void
+handle_proposal_lookup_finished (void *cls,
+                                 long response_code,
+                                 const json_t *json)
+{
+  struct TALER_MERCHANT_ProposalLookupOperation *plo = cls;
+
+  /**
+   * As no data is supposed to be extracted from this
+   * call, we just invoke the provided callback.
+   */
+  plo->cb (plo->cb_cls,
+           response_code,
+           json);
+}
+
+/**
+ * Calls the GET /proposal API at the backend.  That is,
+ * retrieve a proposal data by providing its transaction id.
+ *
+ * @param ctx execution context
+ * @param backend_uri base URL of the merchant backend
+ * @param transaction_id transaction id used to perform the lookup
+ * @param plo_cb callback which will work the response gotten from the backend
+ * @param plo_cb_cls closure to pass to @a history_cb
+ * @return handle for this operation, NULL upon errors
+ */
+struct TALER_MERCHANT_ProposalLookupOperation *
+TALER_MERCHANT_proposal_lookup (struct GNUNET_CURL_Context *ctx,
+                                const char *backend_uri,
+                                const char *order_id,
+                                const char *instance,
+                                TALER_MERCHANT_ProposalLookupOperationCallback 
plo_cb,
+                                void *plo_cb_cls)
+{
+  struct TALER_MERCHANT_ProposalLookupOperation *plo;
+  CURL *eh;
+
+  plo = GNUNET_new (struct TALER_MERCHANT_ProposalLookupOperation);
+  plo->ctx = ctx;
+  plo->cb = plo_cb;
+  plo->cb_cls = plo_cb_cls;
+
+  GNUNET_asprintf (&plo->url,
+                   "%s/proposal?order_id=%s&instance=%s",
+                   backend_uri,
+                   order_id,
+                   instance);
+  eh = curl_easy_init ();
+  if (CURLE_OK != curl_easy_setopt (eh,
+                                    CURLOPT_URL,
+                                    plo->url))
+  {
+    GNUNET_break (0);  
+    return NULL;
+  }
+
+  if (NULL == (plo->job = GNUNET_CURL_job_add (ctx,
+                                               eh,
+                                               GNUNET_YES,
+                                               
&handle_proposal_lookup_finished,
+                                               plo)))
+  {
+    GNUNET_break (0);
+    return NULL;
+  }
+  return plo;
+
+}
+
+/**
+ * Cancel a PUT /proposal request.  This function cannot be used
+ * on a request handle if a response is already served for it.
+ *
+ * @param po the proposal operation request handle
+ */
+void
+TALER_MERCHANT_proposal_cancel (struct TALER_MERCHANT_ProposalOperation *po)
+{
+  if (NULL != po->job)
+  {
+    GNUNET_CURL_job_cancel (po->job);
+    po->job = NULL;
+  }
+  GNUNET_free (po->url);
+  GNUNET_free (po->json_enc);
+  GNUNET_free (po);
+}
+
+/**
+ * Cancel a GET /proposal request.
+ *
+ * @param plo handle to the request to be canceled
+ */
+void
+TALER_MERCHANT_proposal_lookup_cancel (struct 
TALER_MERCHANT_ProposalLookupOperation *plo)
+{
+  if (NULL != plo->job)
+  {
+    GNUNET_CURL_job_cancel (plo->job);
+    plo->job = NULL;
+  }
+  GNUNET_free (plo->url);
+  GNUNET_free (plo);
+}
+
+/* end of merchant_api_contract.c */
diff --git a/src/lib/merchant_api_track_transaction.c 
b/src/lib/merchant_api_track_transaction.c
index cb86441..abb1d29 100644
--- a/src/lib/merchant_api_track_transaction.c
+++ b/src/lib/merchant_api_track_transaction.c
@@ -94,73 +94,11 @@ static int
 parse_track_transaction_ok (struct TALER_MERCHANT_TrackTransactionHandle *tdo,
                             const json_t *json)
 {
-  unsigned int num_transfers = json_array_size (json);
-  struct TALER_MERCHANT_TransactionWireTransfer transfers[num_transfers];
-  unsigned int i;
-
-  if (0 == num_transfers)
-  {
-    /* zero transfers is not a valid reply */
-    GNUNET_break_op (0);
-    return GNUNET_SYSERR;
-  }
-  for (i=0;i<num_transfers;i++)
-  {
-    struct TALER_MERCHANT_TransactionWireTransfer *transfer = &transfers[i];
-    json_t *coins;
-    unsigned int j;
-    struct GNUNET_JSON_Specification spec[] = {
-      GNUNET_JSON_spec_fixed_auto ("wtid",
-                                   &transfer->wtid),
-      GNUNET_JSON_spec_absolute_time ("execution_time",
-                                      &transfer->execution_time),
-      GNUNET_JSON_spec_json ("coins",
-                             &coins),
-      GNUNET_JSON_spec_end()
-    };
-
-    if (GNUNET_OK !=
-        GNUNET_JSON_parse (json_array_get (json, i),
-                           spec,
-                           NULL, NULL))
-    {
-      GNUNET_break_op (0);
-      return GNUNET_SYSERR;
-    }
-    transfer->num_coins = json_array_size (coins);
-    transfer->coins = GNUNET_new_array (transfer->num_coins,
-                                        struct 
TALER_MERCHANT_CoinWireTransfer);
-    for (j=0;j<transfer->num_coins;j++)
-    {
-      struct TALER_MERCHANT_CoinWireTransfer *coin = &transfer->coins[j];
-      struct GNUNET_JSON_Specification coin_spec[] = {
-        GNUNET_JSON_spec_fixed_auto ("coin_pub", &coin->coin_pub),
-        TALER_JSON_spec_amount ("amount_with_fee", &coin->amount_with_fee),
-        TALER_JSON_spec_amount ("deposit_fee", &coin->deposit_fee),
-        GNUNET_JSON_spec_end()
-      };
-      if (GNUNET_OK !=
-          GNUNET_JSON_parse (json_array_get (coins, j),
-                             coin_spec,
-                             NULL, NULL))
-      {
-        GNUNET_break_op (0);
-        GNUNET_JSON_parse_free (spec);
-        free_transfers (i,
-                        transfers);
-        return GNUNET_SYSERR;
-      }
-    }
-    GNUNET_JSON_parse_free (spec);
-  }
   tdo->cb (tdo->cb_cls,
            MHD_HTTP_OK,
           TALER_EC_NONE,
-           json,
-           num_transfers,
-           transfers);
-  free_transfers (num_transfers,
-                  transfers);
+           json);
+
   return GNUNET_OK;
 }
 
@@ -201,7 +139,7 @@ handle_track_transaction_finished (void *cls,
     /* Nothing really to verify, this should never
        happen, we should pass the JSON reply to the application */
     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "track transaction URI not found\n");
+                "Did not find any data\n");
     break;
   case MHD_HTTP_INTERNAL_SERVER_ERROR:
     /* Server had an internal issue; we should retry, but this API
@@ -219,9 +157,7 @@ handle_track_transaction_finished (void *cls,
   tdo->cb (tdo->cb_cls,
            response_code,
           TALER_JSON_get_error_code (json),
-           json,
-           0,
-           NULL);
+           json);
 }
 
 
@@ -240,7 +176,7 @@ struct TALER_MERCHANT_TrackTransactionHandle *
 TALER_MERCHANT_track_transaction (struct GNUNET_CURL_Context *ctx,
                                   const char *backend_uri,
                                   const char *instance,
-                                  uint64_t transaction_id,
+                                  const char *order_id,
                                   TALER_MERCHANT_TrackTransactionCallback 
track_transaction_cb,
                                   void *track_transaction_cb_cls)
 {
@@ -252,10 +188,13 @@ TALER_MERCHANT_track_transaction (struct 
GNUNET_CURL_Context *ctx,
   tdo->cb = track_transaction_cb;
   tdo->cb_cls = track_transaction_cb_cls;
   GNUNET_asprintf (&tdo->url,
-                   "%s/track/transaction?id=%llu&instance=%s",
+                   "%s/track/transaction?order_id=%s&instance=%s",
                    backend_uri,
-                   (unsigned long long) transaction_id,
+                   order_id,
                    instance);
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Requesting URI '%s'\n",
+              tdo->url);
   eh = curl_easy_init ();
   GNUNET_assert (CURLE_OK ==
                  curl_easy_setopt (eh,
diff --git a/src/lib/merchant_api_track_transfer.c 
b/src/lib/merchant_api_track_transfer.c
index ee6c979..10e6981 100644
--- a/src/lib/merchant_api_track_transfer.c
+++ b/src/lib/merchant_api_track_transfer.c
@@ -118,8 +118,7 @@ check_track_transfer_response_ok (struct 
TALER_MERCHANT_TrackTransferHandle *wdh
       struct TALER_TrackTransferDetails *detail = &details[i];
       struct json_t *detail_j = json_array_get (details_j, i);
       struct GNUNET_JSON_Specification spec_detail[] = {
-        GNUNET_JSON_spec_fixed_auto ("H_contract", &detail->h_contract),
-        GNUNET_JSON_spec_uint64 ("transaction_id", &detail->transaction_id),
+        GNUNET_JSON_spec_fixed_auto ("h_proposal_data", 
&detail->h_proposal_data),
         GNUNET_JSON_spec_fixed_auto ("coin_pub", &detail->coin_pub),
         TALER_JSON_spec_amount ("deposit_value", &detail->coin_value),
         TALER_JSON_spec_amount ("deposit_fee", &detail->coin_fee),
diff --git a/src/lib/test_merchant_api.c b/src/lib/test_merchant_api.c
index f2081c2..c2d728c 100644
--- a/src/lib/test_merchant_api.c
+++ b/src/lib/test_merchant_api.c
@@ -17,6 +17,7 @@
  * @file merchant/test_merchant_api.c
  * @brief testcase to test merchant's HTTP API interface
  * @author Christian Grothoff
+ * @author Marcello Stanisci
  */
 #include "platform.h"
 #include <taler/taler_exchange_service.h>
@@ -51,9 +52,9 @@
 #define BANK_PORT 8083
 
 /**
- * Max size allowed for a contract
+ * Max size allowed for an order.
  */
-#define CONTRACT_MAX_SIZE 1000
+#define ORDER_MAX_SIZE 1000
 
 #define RND_BLK(ptr)                                                    \
   GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_WEAK, ptr, sizeof (*ptr))
@@ -132,16 +133,9 @@ enum OpCode
   OC_END = 0,
 
   /**
-   * Ask the backend to store a contract and its hashcode into
-   * the database.
+   * Issue a GET /proposal to the backend.
    */
-  OC_MAP_IN,
-
-  /**
-   * Ask the backend to retrieve a contract from the database, according
-   * to its hashcode.
-   */
-  OC_MAP_OUT,
+  OC_PROPOSAL_LOOKUP,
 
   /**
    * Add funds to a reserve by (faking) incoming wire transfer.
@@ -159,9 +153,9 @@ enum OpCode
   OC_WITHDRAW_SIGN,
 
   /**
-   * Get backend to sign a contract.
+   * Issue a PUT /proposal to the backend.
    */
-  OC_CONTRACT,
+  OC_PROPOSAL,
 
   /**
    * Pay with coins.
@@ -318,19 +312,19 @@ struct Command
     } admin_add_incoming;
 
     /**
-     * Information for both #OC_MAP_{IN,OUT} command.
+     * Information for OC_PROPOSAL_LOOKUP command.
      */
     struct
     {
 
       /**
-       * Reference to a contract we need to hash and store.
+       * Reference to the proposal we want to lookup.
        */
-      const char *contract_reference;
+      const char *proposal_reference;
 
-      struct TALER_MERCHANT_MapOperation *mo;
+      struct TALER_MERCHANT_ProposalLookupOperation *plo;
 
-    } map;
+    } proposal_lookup;
 
     /**
      * Information for a #OC_WITHDRAW_STATUS command.
@@ -405,39 +399,41 @@ struct Command
     } reserve_withdraw;
 
     /**
-     * Information for an #OC_CONTRACT command.
+     * Information for an #OC_PROPOSAL command.
      */
     struct
     {
 
       /**
-       * Contract proposal (without merchant_pub, exchanges or H_wire).
+       * The order.
        * It's dynamically generated because we need different transaction_id
        * for different merchant instances.
        */
-      char proposal[CONTRACT_MAX_SIZE];
+      char order[ORDER_MAX_SIZE];
 
       /**
-       * Handle to the active /contract operation, or NULL.
+       * Handle to the active PUT /proposal operation, or NULL.
        */
-      struct TALER_MERCHANT_ContractOperation *co;
+      struct TALER_MERCHANT_ProposalOperation *po;
 
       /**
        * Full contract in JSON, set by the /contract operation.
+       * FIXME: verify in the code that this bit is actually proposal
+       * data and not the whole proposal.
        */
-      json_t *contract;
+      json_t *proposal_data;
 
       /**
-       * Signature, set by the /contract operation.
+       * Proposal's signature.
        */
       struct TALER_MerchantSignatureP merchant_sig;
 
       /**
-       * Hash of the full contract, set by the /contract operation.
+       * Proposal data's hashcode.
        */
-      struct GNUNET_HashCode h_contract;
+      struct GNUNET_HashCode hash;
 
-    } contract;
+    } proposal;
 
     /**
      * Information for a #OC_PAY command.
@@ -483,9 +479,9 @@ struct Command
       struct TALER_MERCHANT_Pay *ph;
 
       /**
-       * Set to the transaction ID of the respective contract.
+       * Hashcode of the proposal data associated to this payment.
        */
-      uint64_t transaction_id;
+      struct GNUNET_HashCode h_proposal_data;
 
       /**
        * Merchant's public key
@@ -542,6 +538,9 @@ struct Command
 
       /**
        * #OC_PAY command which we expect in the result.
+       * Since we are tracking a bank transaction, we want to know
+       * which (Taler) deposit is associated with the bank
+       * transaction being tracked now.
        */
       char *expected_pay_ref;
 
@@ -566,6 +565,11 @@ struct Command
       char *expected_transfer_ref;
 
       /**
+       * Wire fee we expect to pay for this transaction.
+       */
+      const char *wire_fee;
+
+      /**
        * Handle to a /track/transaction operation
        */
       struct TALER_MERCHANT_TrackTransactionHandle *tth;
@@ -755,21 +759,26 @@ history_cb (void *cls,
 {
   struct InterpreterState *is = cls;
   struct Command *cmd = &is->commands[is->ip];
-  unsigned int nelements;
+  unsigned int nresult;
 
   if (MHD_HTTP_OK != http_status)
   {
     fail (is);
     return;
   }
-  nelements = json_array_size (json);
-  if (nelements != (cmd->details.history.nresult * (instance_idx + 1)))
+  nresult = json_array_size (json);
+  if (nresult != cmd->details.history.nresult)
   {
     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                "Did not get as many history entries as expected\n");
+                "Unexpected number of history entries. Got %d, expected %d\n",
+                nresult,
+                cmd->details.history.nresult);
     fail (is);
     return;
   }
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "/history data: %s\n",
+              json_dumps (json, JSON_INDENT (1)));
 
   next_command (is);
 }
@@ -1015,8 +1024,7 @@ reserve_withdraw_cb (void *cls,
 
 
 /**
- * Callbacks of this type are used to serve the result of submitting a
- * /contract request to a merchant.
+ * Callback that works PUT /proposal's output.
  *
  * @param cls closure
  * @param http_status HTTP response code, 200 indicates success;
@@ -1024,33 +1032,37 @@ reserve_withdraw_cb (void *cls,
  * @param ec taler-specific error code
  * @param obj the full received JSON reply, or
  *            error details if the request failed
- * @param contract completed contract, NULL on error
+ * @param proposal_data the order + additional information provided by the
+ * backend, NULL on error.
  * @param sig merchant's signature over the contract, NULL on error
  * @param h_contract hash of the contract, NULL on error
  */
 static void
-contract_cb (void *cls,
+proposal_cb (void *cls,
              unsigned int http_status,
             enum TALER_ErrorCode ec,
              const json_t *obj,
-             const json_t *contract,
+             const json_t *proposal_data,
              const struct TALER_MerchantSignatureP *sig,
-             const struct GNUNET_HashCode *h_contract)
+             const struct GNUNET_HashCode *hash)
 {
   struct InterpreterState *is = cls;
   struct Command *cmd = &is->commands[is->ip];
 
-  cmd->details.contract.co = NULL;
+  cmd->details.proposal.po = NULL;
   switch (http_status)
   {
   case MHD_HTTP_OK:
-    cmd->details.contract.contract = json_incref ((json_t *) contract);
-    cmd->details.contract.merchant_sig = *sig;
-    cmd->details.contract.h_contract = *h_contract;
+    cmd->details.proposal.proposal_data = json_incref ((json_t *) 
proposal_data);
+    cmd->details.proposal.merchant_sig = *sig;
+    cmd->details.proposal.hash = *hash;
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "Hashed proposal, '%s'\n",
+                GNUNET_h2s (hash));
     break;
   default:
     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                "/contract responded with unexpected status code %u in step 
%u\n",
+                "unexpected status code from /proposal: %u. Step %u\n",
                 http_status,
                 is->ip);
     json_dumpf (obj, stderr, 0);
@@ -1082,7 +1094,7 @@ pay_cb (void *cls,
   struct Command *cmd = &is->commands[is->ip];
   struct PaymentResponsePS mr;
   struct GNUNET_CRYPTO_EddsaSignature sig;
-  struct GNUNET_HashCode h_contract;
+  struct GNUNET_HashCode h_proposal_data;
   const char *error_name;
   unsigned int error_line;
 
@@ -1101,8 +1113,8 @@ pay_cb (void *cls,
   {
     /* Check signature */
     struct GNUNET_JSON_Specification spec[] = {
-      GNUNET_JSON_spec_fixed_auto ("merchant_sig", &sig),
-      GNUNET_JSON_spec_fixed_auto ("h_contract", &h_contract),
+      GNUNET_JSON_spec_fixed_auto ("sig", &sig),
+      GNUNET_JSON_spec_fixed_auto ("h_proposal_data", &h_proposal_data),
       GNUNET_JSON_spec_end ()
     };
     if (GNUNET_OK !=
@@ -1121,7 +1133,7 @@ pay_cb (void *cls,
     }
     mr.purpose.purpose = htonl (TALER_SIGNATURE_MERCHANT_PAYMENT_OK);
     mr.purpose.size = htonl (sizeof (mr));
-    mr.h_contract = h_contract;
+    mr.h_proposal_data = h_proposal_data;
     if (GNUNET_OK !=
         GNUNET_CRYPTO_eddsa_verify (TALER_SIGNATURE_MERCHANT_PAYMENT_OK,
                                     &mr.purpose,
@@ -1212,18 +1224,31 @@ track_transfer_cb (void *cls,
       unsigned int i;
       int found;
 
+      /**
+       * Retrieve the deposit operation that is supposed
+       * to have been paid by the wtid used in this operation.
+       * After that, check if that operation is actually mentioned
+       * in the returned data.
+       */
       ref = find_command (is,
                           cmd->details.track_transfer.expected_pay_ref);
       GNUNET_assert (NULL != ref);
       found = GNUNET_NO;
+
+      /**
+       * Iterating over the details makes little sense now,
+       * as each payment involves exatcly one coin.
+       */
       for (i=0;i<details_length;i++)
       {
         struct TALER_Amount amount_with_fee;
         struct TALER_Amount amount_without_fee;
         struct TALER_Amount deposit_fee;
         const struct Command *cref;
+        const struct Command *proposal_ref;
         struct TALER_CoinSpendPublicKeyP coin_pub;
 
+        /* Extract */
         GNUNET_assert (GNUNET_OK ==
                        TALER_string_to_amount 
(ref->details.pay.amount_without_fee,
                                                &amount_without_fee));
@@ -1235,20 +1260,28 @@ track_transfer_cb (void *cls,
                                               &amount_with_fee,
                                               &amount_without_fee));
 
+        /* Find coin ('s public key) associated with the retrieved
+           deposit. Yes, one deposit - one coin. */
        cref = find_command (is,
                              ref->details.pay.coin_ref);
+        proposal_ref = find_command (is,
+                                     ref->details.pay.contract_ref);
         GNUNET_assert (NULL != cref);
+        GNUNET_assert (NULL != proposal_ref);
        switch (cref->oc)
        {
        case OC_WITHDRAW_SIGN:
-          GNUNET_CRYPTO_eddsa_key_get_public 
(&cref->details.reserve_withdraw.coin_priv.eddsa_priv,
-                                              &coin_pub.eddsa_pub);
+          GNUNET_CRYPTO_eddsa_key_get_public
+            (&cref->details.reserve_withdraw.coin_priv.eddsa_priv,
+             &coin_pub.eddsa_pub);
          break;
        default:
          GNUNET_assert (0);
        }
 
-        if ( (details[i].transaction_id == ref->details.pay.transaction_id) &&
+        if ( (0 == memcmp (&details[i].h_proposal_data,
+                           &proposal_ref->details.proposal.hash,
+                           sizeof (struct GNUNET_HashCode))) &&
              (0 == TALER_amount_cmp (&details[i].coin_value,
                                      &amount_with_fee)) &&
              (0 == TALER_amount_cmp (&details[i].coin_fee,
@@ -1274,21 +1307,21 @@ track_transfer_cb (void *cls,
 }
 
 /**
- * Callback for /map/in issued at backend. Just check
+ * Callback for GET /proposal issued at backend. Just check
  * whether response code is as expected.
  *
  * @param cls closure
  * @param http_status HTTP status code we got
  */
 static void
-map_cb (void *cls,
-        unsigned int http_status,
-        const json_t *json)
+proposal_lookup_cb (void *cls,
+                    unsigned int http_status,
+                    const json_t *json)
 {
   struct InterpreterState *is = cls;
   struct Command *cmd = &is->commands[is->ip];
-  
-  cmd->details.map.mo = NULL;
+
+  cmd->details.proposal_lookup.plo = NULL;
 
   if (cmd->expected_response_code != http_status)
     fail (is);
@@ -1310,9 +1343,7 @@ static void
 track_transaction_cb (void *cls,
                       unsigned int http_status,
                      enum TALER_ErrorCode ec,
-                      const json_t *json,
-                      unsigned int num_transfers,
-                      const struct TALER_MERCHANT_TransactionWireTransfer 
*transfers)
+                      const json_t *json)
 {
   struct InterpreterState *is = cls;
   struct Command *cmd = &is->commands[is->ip];
@@ -1328,66 +1359,11 @@ track_transaction_cb (void *cls,
     fail (is);
     return;
   }
-  /* Test result vs. expecations... */
-  switch (http_status)
-  {
-  case MHD_HTTP_OK:
-    {
-      const struct Command *ref;
-      struct TALER_Amount ea;
-      struct TALER_Amount coin_contribution;
-
-      if (1 != num_transfers)
-      {
-        GNUNET_break (0);
-        json_dumpf (json, stderr, 0);
-        fail (is);
-        return;
-      }
-      ref = find_command (is,
-                          
cmd->details.track_transaction.expected_transfer_ref);
-      GNUNET_assert (NULL != ref);
-      if (0 != memcmp (&ref->details.check_bank_transfer.wtid,
-                       &transfers[0].wtid,
-                       sizeof (struct TALER_WireTransferIdentifierRawP)))
-      {
-        GNUNET_break (0);
-        json_dumpf (json, stderr, 0);
-        fail (is);
-        return;
-      }
-      /* NOTE: this assumes that the wire transfer corresponds to a
-         single coin involved in a pay/deposit.  Thus, this invariant
-         may not always hold in the future depending on how the
-         testcases evolve. */
-      if (1 != transfers[0].num_coins)
-      {
-        GNUNET_break (0);
-        json_dumpf (json, stderr, 0);
-        fail (is);
-        return;
-      }
-      GNUNET_assert (GNUNET_OK ==
-                     TALER_string_to_amount 
(ref->details.check_bank_transfer.amount,
-                                             &ea));
-      GNUNET_assert (GNUNET_OK ==
-                     TALER_amount_subtract (&coin_contribution,
-                                            
&transfers[0].coins[0].amount_with_fee,
-                                            
&transfers[0].coins[0].deposit_fee));
-      if (0 !=
-          TALER_amount_cmp (&ea,
-                            &coin_contribution))
-      {
-        GNUNET_break (0);
-        json_dumpf (json, stderr, 0);
-        fail (is);
-        return;
-      }
-      break;
-    }
-  default:
-    break;
-  }
+  if (MHD_HTTP_OK != http_status)
+    fail (is);
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "/track/order response: %s\n",
+              json_dumps (json, JSON_INDENT (1)));
   next_command (is);
 }
 
@@ -1481,71 +1457,45 @@ interpreter_run (void *cls)
              cmd->oc);
   switch (cmd->oc)
   {
-  case OC_END:
-    result = GNUNET_OK;
-    if (instance_idx + 1 == ninstances)
-    {
-      GNUNET_SCHEDULER_shutdown ();
+    case OC_END:
+      result = GNUNET_OK;
+      if (instance_idx + 1 == ninstances)
+      {
+        GNUNET_SCHEDULER_shutdown ();
+        return;
+      }
+      is->ip = 0;
+      instance_idx++;
+      instance = instances[instance_idx];
+      GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+                  "Switching instance: '%s'\n",
+                  instance);
+
+      is->task = GNUNET_SCHEDULER_add_now (interpreter_run,
+                                           is);
       return;
-    }
-    is->ip = 0;
-    instance_idx++;
-    instance = instances[instance_idx];
-    GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
-                "Switching instance: '%s'\n",
-                instance);
-
-    is->task = GNUNET_SCHEDULER_add_now (interpreter_run,
-                                         is);
-    return;
-
-  case OC_MAP_IN:
-  case OC_MAP_OUT:
-  {
-    struct GNUNET_HashCode h_proposal;
-    json_error_t error;
-    json_t *proposal; 
-
-    GNUNET_assert (NULL != cmd->details.map.contract_reference);
-    ref = find_command (is, cmd->details.map.contract_reference);
-    GNUNET_assert (NULL != ref);
 
-    /**
-     * WARNING, make sure what is hashed here, is exactly the same
-     * contract hashed then by /map/in handler.
-     */
-    proposal = json_loads (ref->details.contract.proposal,
-                           JSON_REJECT_DUPLICATES,
-                           &error);
-
-    GNUNET_assert (GNUNET_SYSERR !=
-                   TALER_JSON_hash (proposal, &h_proposal));
-
-    if (OC_MAP_IN == cmd->oc)
+    case OC_PROPOSAL_LOOKUP:
     {
+      const char *order_id;
 
-      if (MHD_HTTP_UNPROCESSABLE_ENTITY == cmd->expected_response_code)
-        RND_BLK (&h_proposal);
+      GNUNET_assert (NULL != cmd->details.proposal_lookup.proposal_reference);
+      ref = find_command (is, cmd->details.proposal_lookup.proposal_reference);
+      GNUNET_assert (NULL != ref);
 
+      order_id =
+        json_string_value (json_object_get 
(ref->details.proposal.proposal_data,
+                                            "order_id"));
       GNUNET_assert (NULL !=
-                      (cmd->details.map.mo
-                       = TALER_MERCHANT_map_in (ctx,
-                                                MERCHANT_URI,
-                                                proposal,
-                                                &h_proposal,
-                                                map_cb,
-                                                is)));
+                      (cmd->details.proposal_lookup.plo
+                       = TALER_MERCHANT_proposal_lookup (ctx,
+                                                         MERCHANT_URI,
+                                                         order_id,
+                                                         instance,
+                                                         proposal_lookup_cb,
+                                                         is)));
     }
-   else
-     GNUNET_assert (NULL !=
-                     (cmd->details.map.mo 
-                      = TALER_MERCHANT_map_out (ctx,
-                                                MERCHANT_URI,
-                                                &h_proposal,
-                                                map_cb,
-                                                is)));
-  
-  }
+
     return;
 
   case OC_ADMIN_ADD_INCOMING:
@@ -1704,14 +1654,14 @@ interpreter_run (void *cls)
       return;
     }
     return;
-  case OC_CONTRACT:
+  case OC_PROPOSAL:
     {
-      json_t *proposal;
+      json_t *order;
       json_error_t error;
 
-      proposal = json_loads (cmd->details.contract.proposal,
-                             JSON_REJECT_DUPLICATES,
-                             &error);
+      order = json_loads (cmd->details.proposal.order,
+                          JSON_REJECT_DUPLICATES,
+                          &error);
       if (NULL != instance)
       {
 
@@ -1721,61 +1671,59 @@ interpreter_run (void *cls)
         json_object_set_new (merchant,
                              "instance",
                              json_string (instance));
-        json_object_set (proposal, "merchant", merchant);
+        json_object_set (order, "merchant", merchant);
       }
-      if (NULL == proposal)
+      if (NULL == order)
       {
         GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                    "Failed to parse proposal `%s' at command #%u: %s at %u\n",
-                    cmd->details.contract.proposal,
+                    "Failed to parse the order `%s' at command #%u: %s at 
%u\n",
+                    cmd->details.proposal.order,
                     is->ip,
                     error.text,
                     (unsigned int) error.column);
         fail (is);
         return;
       }
-      cmd->details.contract.co
-        = TALER_MERCHANT_contract_sign (ctx,
-                                        MERCHANT_URI,
-                                        proposal,
-                                        &contract_cb,
-                                        is);
-      if (NULL == cmd->details.contract.co)
+      cmd->details.proposal.po
+        = TALER_MERCHANT_order_put (ctx,
+                                    MERCHANT_URI,
+                                    order,
+                                    &proposal_cb,
+                                    is);
+      json_decref (order);
+      if (NULL == cmd->details.proposal.po)
       {
         GNUNET_break (0);
-        json_decref (proposal);
         fail (is);
         return;
       }
-      json_decref (proposal);
       return;
     }
   case OC_PAY:
     {
       struct TALER_MERCHANT_PayCoin pc;
-      uint64_t transaction_id;
+      const char *order_id;
       struct GNUNET_TIME_Absolute refund_deadline;
       struct GNUNET_TIME_Absolute pay_deadline;
       struct GNUNET_TIME_Absolute timestamp;
       struct GNUNET_HashCode h_wire;
       struct TALER_MerchantPublicKeyP merchant_pub;
       struct TALER_MerchantSignatureP merchant_sig;
-      struct GNUNET_HashCode h_contract;
       struct TALER_Amount total_amount;
       struct TALER_Amount max_fee;
       const char *error_name;
       unsigned int error_line;
 
-      /* get amount */
+      /* get proposal */
       ref = find_command (is,
                           cmd->details.pay.contract_ref);
       GNUNET_assert (NULL != ref);
-      merchant_sig = ref->details.contract.merchant_sig;
-      GNUNET_assert (NULL != ref->details.contract.contract);
+      merchant_sig = ref->details.proposal.merchant_sig;
+      GNUNET_assert (NULL != ref->details.proposal.proposal_data);
       {
         /* Get information that need to be replied in the deposit permission */
         struct GNUNET_JSON_Specification spec[] = {
-          GNUNET_JSON_spec_uint64 ("transaction_id", &transaction_id),
+          GNUNET_JSON_spec_string ("order_id", &order_id),
           GNUNET_JSON_spec_absolute_time ("refund_deadline", &refund_deadline),
           GNUNET_JSON_spec_absolute_time ("pay_deadline", &pay_deadline),
           GNUNET_JSON_spec_absolute_time ("timestamp", &timestamp),
@@ -1787,7 +1735,7 @@ interpreter_run (void *cls)
         };
 
         if (GNUNET_OK !=
-            GNUNET_JSON_parse (ref->details.contract.contract,
+            GNUNET_JSON_parse (ref->details.proposal.proposal_data,
                                spec,
                                &error_name,
                                &error_line))
@@ -1800,26 +1748,22 @@ interpreter_run (void *cls)
           fail (is);
           return;
         }
-        cmd->details.pay.transaction_id = transaction_id;
         cmd->details.pay.merchant_pub = merchant_pub;
       }
 
-      TALER_JSON_hash (ref->details.contract.contract,
-                      &h_contract);
-
-      /* initialize 'pc' (FIXME: to do in a loop later...) */
       {
+        const struct Command *coin_ref;
        memset (&pc, 0, sizeof (pc));
-       ref = find_command (is,
-                           cmd->details.pay.coin_ref);
+       coin_ref = find_command (is,
+                                cmd->details.pay.coin_ref);
        GNUNET_assert (NULL != ref);
-       switch (ref->oc)
+       switch (coin_ref->oc)
        {
        case OC_WITHDRAW_SIGN:
-         pc.coin_priv = ref->details.reserve_withdraw.coin_priv;
-         pc.denom_pub = ref->details.reserve_withdraw.pk->key;
-         pc.denom_sig = ref->details.reserve_withdraw.sig;
-          pc.denom_value = ref->details.reserve_withdraw.pk->value;
+         pc.coin_priv = coin_ref->details.reserve_withdraw.coin_priv;
+         pc.denom_pub = coin_ref->details.reserve_withdraw.pk->key;
+         pc.denom_sig = coin_ref->details.reserve_withdraw.sig;
+          pc.denom_value = coin_ref->details.reserve_withdraw.pk->value;
          break;
        default:
          GNUNET_assert (0);
@@ -1849,12 +1793,12 @@ interpreter_run (void *cls)
          return;
        }
       }
+
       cmd->details.pay.ph
        = TALER_MERCHANT_pay_wallet (ctx,
                                     MERCHANT_URI,
                                      instance,
-                                    &h_contract,
-                                    transaction_id,
+                                    &ref->details.proposal.hash,
                                     &total_amount,
                                     &max_fee,
                                     &merchant_pub,
@@ -1864,6 +1808,7 @@ interpreter_run (void *cls)
                                     pay_deadline,
                                     &h_wire,
                                     EXCHANGE_URI,
+                                     order_id,
                                     1 /* num_coins */,
                                     &pc /* coins */,
                                     &pay_cb,
@@ -1920,6 +1865,7 @@ interpreter_run (void *cls)
                           &amount,
                           cmd->details.check_bank_transfer.account_debit,
                           cmd->details.check_bank_transfer.account_credit,
+                          EXCHANGE_URI,
                           &cmd->details.check_bank_transfer.wtid))
       {
         GNUNET_break (0);
@@ -1955,23 +1901,34 @@ interpreter_run (void *cls)
                                      is);
     return;
   case OC_TRACK_TRANSACTION:
+  {
+    const struct Command *proposal_ref;
+    const char *order_id;
+
     ref = find_command (is,
                         cmd->details.track_transaction.pay_ref);
     GNUNET_assert (NULL != ref);
-    /*FIXME check/assert return code */
+    proposal_ref = find_command (is,
+                                 ref->details.pay.contract_ref);
+    order_id = json_string_value (json_object_get 
(proposal_ref->details.proposal.proposal_data,
+                                        "order_id"));
     cmd->details.track_transaction.tth =
       TALER_MERCHANT_track_transaction (ctx,
                                         MERCHANT_URI,
-                                        instance, /* got it NULL, right now */
-                                        ref->details.pay.transaction_id,
+                                        instance,
+                                        order_id,
                                         &track_transaction_cb,
                                         is);
+  }
     return;
   case OC_HISTORY:
 
     if (NULL ==
        (cmd->details.history.ho = TALER_MERCHANT_history (ctx,
                                                          MERCHANT_URI,
+                                                          instance,
+                                                          0,
+                                                          20,
                                                          
cmd->details.history.date,
                                                          history_cb,
                                                          is)))
@@ -2033,15 +1990,14 @@ do_shutdown (void *cls)
     case OC_END:
       GNUNET_assert (0);
       break;
-    case OC_MAP_IN:
-    case OC_MAP_OUT:
-      if (NULL != cmd->details.map.mo)
+    case OC_PROPOSAL_LOOKUP:
+      if (NULL != cmd->details.proposal_lookup.plo)
       {
         GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
                     "Command %u (%s) did not complete\n",
                     i,
                     cmd->label);
-        TALER_MERCHANT_map_cancel (cmd->details.map.mo);
+        TALER_MERCHANT_proposal_lookup_cancel 
(cmd->details.proposal_lookup.plo);
       }
         break;
 
@@ -2083,20 +2039,20 @@ do_shutdown (void *cls)
         cmd->details.reserve_withdraw.sig.rsa_signature = NULL;
       }
       break;
-    case OC_CONTRACT:
-      if (NULL != cmd->details.contract.co)
+    case OC_PROPOSAL:
+      if (NULL != cmd->details.proposal.po)
       {
         GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
                     "Command %u (%s) did not complete\n",
                     i,
                     cmd->label);
-        TALER_MERCHANT_contract_sign_cancel (cmd->details.contract.co);
-        cmd->details.contract.co = NULL;
+        TALER_MERCHANT_proposal_cancel (cmd->details.proposal.po);
+        cmd->details.proposal.po = NULL;
       }
-      if (NULL != cmd->details.contract.contract)
+      if (NULL != cmd->details.proposal.proposal_data)
       {
-        json_decref (cmd->details.contract.contract);
-        cmd->details.contract.contract = NULL;
+        json_decref (cmd->details.proposal.proposal_data);
+        cmd->details.proposal.proposal_data = NULL;
       }
       break;
     case OC_PAY:
@@ -2278,14 +2234,14 @@ run (void *cls)
       .expected_response_code = MHD_HTTP_OK,
       .details.reserve_status.reserve_reference = "create-reserve-1",
       .details.reserve_status.expected_balance = "EUR:0" },
-    /* Create contract */
-    { .oc = OC_CONTRACT,
-      .label = "create-contract-1",
+    /* Create proposal */
+    { .oc = OC_PROPOSAL,
+      .label = "create-proposal-1",
       .expected_response_code = MHD_HTTP_OK,
-      .details.contract.proposal = "{\
+      .details.proposal.order = "{\
                   \"max_fee\":\
                      {\"currency\":\"EUR\", \"value\":0, 
\"fraction\":50000000},\
-                  \"transaction_id\":1,\
+                  \"order_id\":\"1\",\
                   \"timestamp\":\"\\/Date(42)\\/\",\
                   \"refund_deadline\":\"\\/Date(0)\\/\",\
                   \"pay_deadline\":\"\\/Date(9999999999)\\/\",\
@@ -2293,29 +2249,33 @@ run (void *cls)
                  \"summary\": \"merchant-lib testcase\",\
                   \"products\":\
                      [ {\"description\":\"ice cream\", \"value\":\"{EUR:5}\"} 
] }"},
+
     { .oc = OC_PAY,
       .label = "deposit-simple",
       .expected_response_code = MHD_HTTP_OK,
-      .details.pay.contract_ref = "create-contract-1",
+      .details.pay.contract_ref = "create-proposal-1",
       .details.pay.coin_ref = "withdraw-coin-1",
       .details.pay.amount_with_fee = "EUR:5",
       .details.pay.amount_without_fee = "EUR:4.99" },
 
-    /* Store contract-1 */
-    {
-      .oc = OC_MAP_IN, 
-      .label = "store-contract-1",
+    /* Try to replay payment reusing coin */
+    { .oc = OC_PAY,
+      .label = "replay-simple",
       .expected_response_code = MHD_HTTP_OK,
-      .details.map.contract_reference = "create-contract-1" },
+      .details.pay.contract_ref = "create-proposal-1",
+      .details.pay.coin_ref = "withdraw-coin-1",
+      .details.pay.amount_with_fee = "EUR:5",
+      .details.pay.amount_without_fee = "EUR:4.99" },
+
 
     /* Create another contract */
-    { .oc = OC_CONTRACT,
-      .label = "create-contract-2",
+    { .oc = OC_PROPOSAL,
+      .label = "create-proposal-2",
       .expected_response_code = MHD_HTTP_OK,
-      .details.contract.proposal = "{\
+      .details.proposal.order = "{\
                   \"max_fee\":\
                      {\"currency\":\"EUR\", \"value\":0, 
\"fraction\":50000000},\
-                  \"transaction_id\":2,\
+                  \"order_id\":\"2\",\
                   \"timestamp\":\"\\/Date(42)\\/\",\
                   \"refund_deadline\":\"\\/Date(0)\\/\",\
                   \"pay_deadline\":\"\\/Date(9999999999)\\/\",\
@@ -2328,7 +2288,7 @@ run (void *cls)
     { .oc = OC_PAY,
       .label = "deposit-double-2",
       .expected_response_code = MHD_HTTP_FORBIDDEN,
-      .details.pay.contract_ref = "create-contract-2",
+      .details.pay.contract_ref = "create-proposal-2",
       .details.pay.coin_ref = "withdraw-coin-1",
       .details.pay.amount_with_fee = "EUR:5",
       .details.pay.amount_without_fee = "EUR:4.99" },
@@ -2341,14 +2301,6 @@ run (void *cls)
       .details.admin_add_incoming.transfer_details = "{ \"uuid\": 2}",
       .details.admin_add_incoming.amount = "EUR:1" },
 
-    /* Store contract-1 */
-    {
-      .oc = OC_MAP_IN, 
-      .label = "store-contract-2",
-      .expected_response_code = MHD_HTTP_OK,
-      .details.map.contract_reference = "create-contract-2",
-    },
-
     /* Add another 4.01 EUR to reserve #2 */
     { .oc = OC_ADMIN_ADD_INCOMING,
       .label = "create-reserve-2b",
@@ -2365,12 +2317,12 @@ run (void *cls)
       .details.reserve_withdraw.reserve_reference = "create-reserve-2",
       .details.reserve_withdraw.amount = "EUR:5" },
 
-    /* Fetch contract-1 */
+    /* Proposal lookup */
     {
-      .oc = OC_MAP_OUT, 
-      .label = "fetch-contract-2",
+      .oc = OC_PROPOSAL_LOOKUP,
+      .label = "fetch-proposal-2",
       .expected_response_code = MHD_HTTP_OK,
-      .details.map.contract_reference = "create-contract-2" },
+      .details.proposal_lookup.proposal_reference = "create-proposal-2" },
 
     /* Check nothing happened on the bank side so far */
     { .oc = OC_CHECK_BANK_TRANSFERS_EMPTY,
@@ -2383,8 +2335,8 @@ run (void *cls)
 
     /* Obtain WTID of the transfer */
     { .oc = OC_CHECK_BANK_TRANSFER,
-      .label = "check_bank_transfer-499c",
-      .details.check_bank_transfer.amount = "EUR:4.99",
+      .label = "check_bank_transfer-498c",
+      .details.check_bank_transfer.amount = "EUR:4.98",
       .details.check_bank_transfer.account_debit = 2, /* exchange-outgoing */
       .details.check_bank_transfer.account_credit = 62 /* merchant */
     },
@@ -2393,63 +2345,45 @@ run (void *cls)
     { .oc = OC_CHECK_BANK_TRANSFERS_EMPTY,
       .label = "check_bank_empty" },
 
+    { .oc = OC_TRACK_TRANSACTION,
+      .label = "track-transaction-1",
+      .expected_response_code = MHD_HTTP_OK,
+      .details.track_transaction.expected_transfer_ref = 
"check_bank_transfer-498c",
+      .details.track_transaction.pay_ref = "deposit-simple",
+      .details.track_transaction.wire_fee = "EUR:0.01",
+    },
+
     /* Trace the WTID back to the original transaction */
     { .oc = OC_TRACK_TRANSFER,
       .label = "track-transfer-1",
       .expected_response_code = MHD_HTTP_OK,
-      .details.track_transfer.check_bank_ref = "check_bank_transfer-499c",
+      .details.track_transfer.check_bank_ref = "check_bank_transfer-498c",
       .details.track_transfer.expected_pay_ref = "deposit-simple"
     },
     { .oc = OC_TRACK_TRANSFER,
       .label = "track-transfer-1-again",
       .expected_response_code = MHD_HTTP_OK,
-      .details.track_transfer.check_bank_ref = "check_bank_transfer-499c",
+      .details.track_transfer.check_bank_ref = "check_bank_transfer-498c",
       .details.track_transfer.expected_pay_ref = "deposit-simple"
     },
 
-    /* Trace transaction to WTID */
-    { .oc = OC_TRACK_TRANSACTION,
-      .label = "track-transaction-1",
-      .expected_response_code = MHD_HTTP_OK,
-      .details.track_transaction.pay_ref = "deposit-simple",
-      .details.track_transaction.expected_transfer_ref = 
"check_bank_transfer-499c"
-    },
-    { .oc = OC_TRACK_TRANSACTION,
-      .label = "track-transaction-1-again",
-      .expected_response_code = MHD_HTTP_OK,
-      .details.track_transaction.pay_ref = "deposit-simple",
-      .details.track_transaction.expected_transfer_ref = 
"check_bank_transfer-499c"
-    },
-
     /* Pay again successfully on 2nd contract */
     { .oc = OC_PAY,
       .label = "deposit-simple-2",
       .expected_response_code = MHD_HTTP_OK,
-      .details.pay.contract_ref = "create-contract-2",
+      .details.pay.contract_ref = "create-proposal-2",
       .details.pay.coin_ref = "withdraw-coin-2",
       .details.pay.amount_with_fee = "EUR:5",
       .details.pay.amount_without_fee = "EUR:4.99" },
 
-    /* Check "failure" to trace transaction to WTID before aggregator */
-    { .oc = OC_TRACK_TRANSACTION,
-      .label = "track-transaction-2-found",
-      .expected_response_code = MHD_HTTP_ACCEPTED,
-      .details.track_transaction.pay_ref = "deposit-simple-2"
-    },
-    { .oc = OC_TRACK_TRANSACTION,
-      .label = "track-transaction-2-found-again",
-      .expected_response_code = MHD_HTTP_ACCEPTED,
-      .details.track_transaction.pay_ref = "deposit-simple-2"
-    },
-
     /* Run transfers. */
     { .oc = OC_RUN_AGGREGATOR,
       .label = "run-aggregator-2" },
 
     /* Obtain WTID of the transfer */
     { .oc = OC_CHECK_BANK_TRANSFER,
-      .label = "check_bank_transfer-499c-2",
-      .details.check_bank_transfer.amount = "EUR:4.99",
+      .label = "check_bank_transfer-498c-2",
+      .details.check_bank_transfer.amount = "EUR:4.98",
       .details.check_bank_transfer.account_debit = 2, /* exchange-outgoing */
       .details.check_bank_transfer.account_credit = 62 /* merchant */
     },
@@ -2458,77 +2392,43 @@ run (void *cls)
     { .oc = OC_CHECK_BANK_TRANSFERS_EMPTY,
       .label = "check_bank_empty" },
 
-    /* This time, invert the order in which we do the tracing */
-    /* Trace transaction to WTID */
-    { .oc = OC_TRACK_TRANSACTION,
-      .label = "track-transaction-2",
-      .expected_response_code = MHD_HTTP_OK,
-      .details.track_transaction.pay_ref = "deposit-simple-2",
-      .details.track_transaction.expected_transfer_ref = 
"check_bank_transfer-499c-2"
-    },
-    { .oc = OC_TRACK_TRANSACTION,
-      .label = "track-transaction-2-again", .expected_response_code = 
MHD_HTTP_OK,
-      .details.track_transaction.pay_ref = "deposit-simple-2",
-      .details.track_transaction.expected_transfer_ref = 
"check_bank_transfer-499c-2"
-    },
-
     /* Trace the WTID back to the original transaction */
     { .oc = OC_TRACK_TRANSFER,
       .label = "track-transfer-2",
       .expected_response_code = MHD_HTTP_OK,
-      .details.track_transfer.check_bank_ref = "check_bank_transfer-499c-2",
+      .details.track_transfer.check_bank_ref = "check_bank_transfer-498c-2",
       .details.track_transfer.expected_pay_ref = "deposit-simple-2"
     },
     { .oc = OC_TRACK_TRANSFER,
       .label = "track-transfer-2-again",
       .expected_response_code = MHD_HTTP_OK,
-      .details.track_transfer.check_bank_ref = "check_bank_transfer-499c-2",
+      .details.track_transfer.check_bank_ref = "check_bank_transfer-498c-2",
       .details.track_transfer.expected_pay_ref = "deposit-simple-2"
     },
-    /**
-     * NOTE: could NOT initialize timestamps by calling GNUNET_TIME_xy ()
-     * because that raised a 'Initializer element is not constant' when 
compiling.
-     */
+
+    { .oc = OC_TRACK_TRANSACTION,
+      .label = "track-transaction-2",
+      .expected_response_code = MHD_HTTP_OK,
+      .details.track_transaction.expected_transfer_ref = 
"check_bank_transfer-498c-2",
+      .details.track_transaction.wire_fee = "EUR:0.01",
+      .details.track_transaction.pay_ref = "deposit-simple-2"
+    },
+
     { .oc = OC_HISTORY,
       .label = "history-1",
       .expected_response_code = MHD_HTTP_OK,
+      /*all records to be returned*/
       .details.history.date.abs_value_us = 0,
       .details.history.nresult = 2
     },
     { .oc = OC_HISTORY,
       .label = "history-2",
       .expected_response_code = MHD_HTTP_OK,
+      /*no records to be returned, as limit is in the future*/
       .details.history.date.abs_value_us = 43 * 1000LL * 1000LL,
       .details.history.nresult = 0
     },
-    /* Retrieve via /map/out a contract NOT stored previously. */
-    {
-      .oc = OC_MAP_OUT, 
-      .label = "fetch-contract-not-found",
-      .expected_response_code = MHD_HTTP_NOT_FOUND,
-      .details.map.contract_reference = "create-contract-3" },
-
-    /* Create another contract, NOT to be stored. */
-    { .oc = OC_CONTRACT,
-      .label = "create-contract-3",
-      .expected_response_code = MHD_HTTP_OK,
-      .details.contract.proposal = "{\
-                  \"max_fee\":\
-                     {\"currency\":\"EUR\", \"value\":0, \"fraction\":10000},\
-                  \"transaction_id\":3,\
-                  \"timestamp\":\"\\/Date(42)\\/\",\
-                  \"refund_deadline\":\"\\/Date(0)\\/\",\
-                  \"pay_deadline\":\"\\/Date(0)\\/\",\
-                  \"amount\":{\"currency\":\"EUR\", \"value\":1, 
\"fraction\":0},\
-                  \"products\":\
-                     [ {\"description\":\"bogus\", \"value\":\"{EUR:1}\"} ] }" 
},
 
-    /* Try to store a contract passing a bogus hashcode. */
-    {
-      .oc = OC_MAP_IN, 
-      .label = "store-contract-bogus",
-      .expected_response_code = MHD_HTTP_UNPROCESSABLE_ENTITY,
-      .details.map.contract_reference = "create-contract-3" },
     /* end of testcase */
     { .oc = OC_END }
   };
@@ -2687,6 +2587,7 @@ main (int argc,
                                        "taler-merchant-httpd",
                                        "taler-merchant-httpd",
                                        "-c", "test_merchant_api.conf",
+                                       "-L", "DEBUG",
                                        NULL);
   if (NULL == merchantd)
   {
diff --git a/src/lib/test_merchant_api.conf b/src/lib/test_merchant_api.conf
index c05530f..8a9b80c 100644
--- a/src/lib/test_merchant_api.conf
+++ b/src/lib/test_merchant_api.conf
@@ -19,9 +19,6 @@ CURRENCY = EUR
 # Which port do we run the backend on? (HTTP server)
 PORT = 8082
 
-# FIXME: is this one used?
-HOSTNAME = localhost
-
 # How quickly do we want the exchange to send us our money?
 # Used only if the frontend does not specify a value.
 # FIXME: EDATE is a bit short, 'execution_delay'?
@@ -30,7 +27,7 @@ EDATE = 3 week
 # Which plugin (backend) do we use for the DB.
 DB = postgres
 
-# Which wireformat do we use?
+# Wire format supported by the merchant.
 WIREFORMAT = test
 
 # This option is a list of instances which are to be used
@@ -39,6 +36,25 @@ WIREFORMAT = test
 # section like X-wireformat and merchant-instance-X
 INSTANCES = tor default
 
+
+[exchange-wire-test]
+# Enable 'test' for testing of the actual coin operations.
+ENABLE = YES
+
+# 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
+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
+
+
 [merchant-exchange-test]
 URI = http://localhost:8081/
 MASTER_KEY = 98NJW3CQHZQGQXTY3K85K531XKPAPAVV4Q5V8PYYRR00NJGZWNVG
@@ -89,10 +105,10 @@ ADDRESS = "Garching"
 [exchange]
 # How to access our database
 DB = postgres
+
 # HTTP port the exchange listens to
 PORT = 8081
-# Wire format supported by the exchange
-WIREFORMAT = test
+
 # Our public key
 MASTER_PUBLIC_KEY = T1VVFQZZARQ1CMF4BN58EE7SKTW5AV2BS18S87ZEGYS4S29J6DNG
 
diff --git a/src/samples/Makefile.am b/src/samples/Makefile.am
new file mode 100644
index 0000000..54c6d8f
--- /dev/null
+++ b/src/samples/Makefile.am
@@ -0,0 +1,21 @@
+# This Makefile.am is in the public domain
+AM_CPPFLAGS = -I$(top_srcdir)/src/include
+
+bin_PROGRAMS = \
+  taler-merchant-generate-payments
+
+taler_merchant_generate_payments_SOURCES = \
+  generate_payments.c
+
+taler_merchant_generate_payments_LDADD = \
+  $(top_srcdir)/src/backenddb/libtalermerchantdb.la \
+  $(top_srcdir)/src/lib/libtalermerchant.la \
+  $(LIBGCRYPT_LIBS) \
+  -ltalerfakebank \
+  -ltalerexchange \
+  -ltalerjson \
+  -ltalerutil \
+  -lgnunetjson \
+  -lgnunetcurl \
+  -lgnunetutil \
+  -ljansson
diff --git a/src/samples/README b/src/samples/README
new file mode 100644
index 0000000..4926db6
--- /dev/null
+++ b/src/samples/README
@@ -0,0 +1,3 @@
+Here is the logic that creates dummy payments into the
+merchant's DB, mainly used for debugging applications that
+need some real data from the merchant backend. 
diff --git a/src/samples/generate_payments.c b/src/samples/generate_payments.c
new file mode 100644
index 0000000..d887eff
--- /dev/null
+++ b/src/samples/generate_payments.c
@@ -0,0 +1,1484 @@
+/*
+  This file is part of TALER
+  Copyright (C) 2014, 2015, 2016 GNUnet e.V. and INRIA
+
+  TALER is free software; you can redistribute it and/or modify it under the
+  terms of the GNU Lesser General Public License as published by the Free 
Software
+  Foundation; either version 2.1, 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 Lesser General Public License for more 
details.
+
+  You should have received a copy of the GNU Lesser General Public License 
along with
+  TALER; see the file COPYING.LGPL.  If not, see <http://www.gnu.org/licenses/>
+*/
+
+#include "platform.h"
+#include <taler/taler_exchange_service.h>
+#include <taler/taler_fakebank_lib.h>
+#include <taler/taler_json_lib.h>
+#include <taler/taler_util.h>
+#include <taler/taler_signatures.h>
+#include "taler_merchant_service.h"
+#include "taler_merchantdb_lib.h"
+#include <gnunet/gnunet_util_lib.h>
+#include <gnunet/gnunet_curl_lib.h>
+#include <microhttpd.h>
+
+#define EXCHANGE_URI "http://localexchange/";
+#define MERCHANT_URI "http://localshop/";
+#define BANK_URI "http://localbank/";
+#define INSTANCE "FSF"
+#define CURRENCY "EUR"
+
+#define ORDER_MAX_SIZE 1000
+
+/**
+ * Task run on timeout.
+ */
+static struct GNUNET_SCHEDULER_Task *timeout_task;
+
+/**
+ * Handle to access the exchange.
+ */
+static struct TALER_EXCHANGE_Handle *exchange;
+
+/**
+ * Main execution context for the main loop of the exchange.
+ */
+static struct GNUNET_CURL_Context *ctx;
+
+/**
+ * Context for running the #ctx's event loop.
+ */
+static struct GNUNET_CURL_RescheduleContext *rc;
+
+/**
+ * Result of the testcases, #GNUNET_OK on success.
+ */
+static int result;
+
+/**
+ * Pipe used to communicate child death via signal.
+ */
+static struct GNUNET_DISK_PipeHandle *sigpipe;
+
+/**
+ * State of the interpreter loop.
+ */
+struct InterpreterState
+{
+  /**
+   * Keys from the exchange.
+   */
+  const struct TALER_EXCHANGE_Keys *keys;
+
+  /**
+   * Commands the interpreter will run.
+   */
+  struct Command *commands;
+
+  /**
+   * Interpreter task (if one is scheduled).
+   */
+  struct GNUNET_SCHEDULER_Task *task;
+
+  /**
+   * Instruction pointer.  Tells #interpreter_run() which
+   * instruction to run next.
+   */
+  unsigned int ip;
+
+};
+
+/**
+ * Opcodes for the interpreter.
+ */
+enum OpCode
+{
+  /**
+   * Termination code, stops the interpreter loop (with success).
+   */
+  OC_END = 0,
+
+  /**
+   * Issue a GET /proposal to the backend.
+   */
+  OC_PROPOSAL_LOOKUP,
+
+  /**
+   * Add funds to a reserve by (faking) incoming wire transfer.
+   */
+  OC_ADMIN_ADD_INCOMING,
+
+  /**
+   * Check status of a reserve.
+   */
+  OC_WITHDRAW_STATUS,
+
+  /**
+   * Withdraw a coin from a reserve.
+   */
+  OC_WITHDRAW_SIGN,
+
+  /**
+   * Issue a PUT /proposal to the backend.
+   */
+  OC_PROPOSAL,
+
+  /**
+   * Pay with coins.
+   */
+  OC_PAY
+
+};
+
+
+/**
+ * Details for a exchange operation to execute.
+ */
+struct Command
+{
+  /**
+   * Opcode of the command.
+   */
+  enum OpCode oc;
+
+  /**
+   * Label for the command, can be NULL.
+   */
+  const char *label;
+
+  /**
+   * Which response code do we expect for this command?
+   */
+  unsigned int expected_response_code;
+
+  /**
+   * Details about the command.
+   */
+  union
+  {
+
+    /**
+     * Information for a #OC_WITHDRAW_SIGN command.
+     */
+    struct
+    {
+
+      /**
+       * Which reserve should we withdraw from?
+       */
+      const char *reserve_reference;
+
+      /**
+       * String describing the denomination value we should withdraw.
+       * A corresponding denomination key must exist in the exchange's
+       * offerings.  Can be NULL if @e pk is set instead.
+       */
+      const char *amount;
+
+      /**
+       * If @e amount is NULL, this specifies the denomination key to
+       * use.  Otherwise, this will be set (by the interpreter) to the
+       * denomination PK matching @e amount.
+       */
+      const struct TALER_EXCHANGE_DenomPublicKey *pk;
+
+      /**
+       * Set (by the interpreter) to the exchange's signature over the
+       * coin's public key.
+       */
+      struct TALER_DenominationSignature sig;
+
+      /**
+       * Set (by the interpreter) to the coin's private key.
+       */
+      struct TALER_CoinSpendPrivateKeyP coin_priv;
+
+      /**
+       * Blinding key used for the operation.
+       */
+      struct TALER_DenominationBlindingKeyP blinding_key;
+
+      /**
+       * Withdraw handle (while operation is running).
+       */
+      struct TALER_EXCHANGE_ReserveWithdrawHandle *wsh;
+
+    } reserve_withdraw;
+
+    /**
+     * Information for a #OC_ADMIN_ADD_INCOMING command.
+     */
+    struct
+    {
+
+      /**
+       * Label to another admin_add_incoming command if we
+       * should deposit into an existing reserve, NULL if
+       * a fresh reserve should be created.
+       */
+      const char *reserve_reference;
+
+      /**
+       * String describing the amount to add to the reserve.
+       */
+      const char *amount;
+
+      /**
+       * Sender's bank account details (JSON).
+       */
+      const char *sender_details;
+
+      /**
+       * Transfer details (JSON)
+       */
+       const char *transfer_details;
+
+      /**
+       * Set (by the interpreter) to the reserve's private key
+       * we used to fill the reserve.
+       */
+      struct TALER_ReservePrivateKeyP reserve_priv;
+
+      /**
+       * Set to the API's handle during the operation.
+       */
+      struct TALER_EXCHANGE_AdminAddIncomingHandle *aih;
+
+    } admin_add_incoming;
+
+    /**
+     * Information for an #OC_PROPOSAL command.
+     */
+    struct
+    {
+
+      /**
+       * The order.
+       * It's dynamically generated because we need different transaction_id
+       * for different merchant instances.
+       */
+      char order[ORDER_MAX_SIZE];
+
+      /**
+       * Handle to the active PUT /proposal operation, or NULL.
+       */
+      struct TALER_MERCHANT_ProposalOperation *po;
+
+      /**
+       * Full contract in JSON, set by the /contract operation.
+       * FIXME: verify in the code that this bit is actually proposal
+       * data and not the whole proposal.
+       */
+      json_t *proposal_data;
+
+      /**
+       * Proposal's signature.
+       */
+      struct TALER_MerchantSignatureP merchant_sig;
+
+      /**
+       * Proposal data's hashcode.
+       */
+      struct GNUNET_HashCode hash;
+
+    } proposal;
+
+    /**
+     * Information for a #OC_PAY command.
+     * FIXME: support tests where we pay with multiple coins at once.
+     */
+    struct
+    {
+
+      /**
+       * Reference to the contract.
+       */
+      const char *contract_ref;
+
+      /**
+       * Reference to a reserve_withdraw operation for a coin to
+       * be used for the /deposit operation.
+       */
+      const char *coin_ref;
+
+      /**
+       * If this @e coin_ref refers to an operation that generated
+       * an array of coins, this value determines which coin to use.
+       */
+      unsigned int coin_idx;
+
+      /**
+       * Amount to pay (from the coin, including fee).
+       */
+      const char *amount_with_fee;
+
+      /**
+       * Amount to pay (from the coin, excluding fee).  The sum of the
+       * deltas between all @e amount_with_fee and the @e
+       * amount_without_fee must be less than max_fee, and the sum of
+       * the @e amount_with_fee must be larger than the @e
+       * total_amount.
+       */
+      const char *amount_without_fee;
+
+      /**
+       * Deposit handle while operation is running.
+       */
+      struct TALER_MERCHANT_Pay *ph;
+
+      /**
+       * Hashcode of the proposal data associated to this payment.
+       */
+      struct GNUNET_HashCode h_proposal_data;
+
+      /**
+       * Merchant's public key
+       */
+      struct TALER_MerchantPublicKeyP merchant_pub;
+
+    } pay;
+
+
+
+  } details;
+
+};
+
+/**
+ * Function run when the test times out.
+ *
+ * @param cls NULL
+ */
+static void
+do_timeout (void *cls)
+{
+  timeout_task = NULL;
+  GNUNET_SCHEDULER_shutdown ();
+}
+
+/**
+ * The generator failed, return with an error code.
+ *
+ * @param is interpreter state to clean up
+ */
+static void
+fail (struct InterpreterState *is)
+{
+  GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+              "Interpreter failed at step %s (#%u)\n",
+              is->commands[is->ip].label,
+              is->ip);
+  result = GNUNET_SYSERR;
+  GNUNET_SCHEDULER_shutdown ();
+}
+
+/**
+ * Run the main interpreter loop that performs exchange operations.
+ *
+ * @param cls contains the `struct InterpreterState`
+ */
+static void
+interpreter_run (void *cls);
+
+/**
+ * Run the next command with the interpreter.
+ *
+ * @param is current interpeter state.
+ */
+static void
+next_command (struct InterpreterState *is)
+{
+  is->ip++;
+  is->task = GNUNET_SCHEDULER_add_now (&interpreter_run,
+                                       is);
+}
+
+/**
+ * Callback that works PUT /proposal's output.
+ *
+ * @param cls closure
+ * @param http_status HTTP response code, 200 indicates success;
+ *                    0 if the backend's reply is bogus (fails to follow the 
protocol)
+ * @param ec taler-specific error code
+ * @param obj the full received JSON reply, or
+ *            error details if the request failed
+ * @param proposal_data the order + additional information provided by the
+ * backend, NULL on error.
+ * @param sig merchant's signature over the contract, NULL on error
+ * @param h_contract hash of the contract, NULL on error
+ */
+static void
+proposal_cb (void *cls,
+             unsigned int http_status,
+            enum TALER_ErrorCode ec,
+             const json_t *obj,
+             const json_t *proposal_data,
+             const struct TALER_MerchantSignatureP *sig,
+             const struct GNUNET_HashCode *hash)
+{
+  struct InterpreterState *is = cls;
+  struct Command *cmd = &is->commands[is->ip];
+
+  cmd->details.proposal.po = NULL;
+  switch (http_status)
+  {
+  case MHD_HTTP_OK:
+    cmd->details.proposal.proposal_data = json_incref ((json_t *) 
proposal_data);
+    cmd->details.proposal.merchant_sig = *sig;
+    cmd->details.proposal.hash = *hash;
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "Hashed proposal, '%s'\n",
+                GNUNET_h2s (hash));
+    break;
+  default:
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                "unexpected status code from /proposal: %u. Step %u\n",
+                http_status,
+                is->ip);
+    json_dumpf (obj, stderr, 0);
+    GNUNET_break (0);
+    fail (is);
+    return;
+  }
+  next_command (is);
+}
+
+/**
+ * Function called with the result of a /pay operation.
+ *
+ * @param cls closure with the interpreter state
+ * @param http_status HTTP response code, #MHD_HTTP_OK (200) for successful 
deposit;
+ *                    0 if the exchange's reply is bogus (fails to follow the 
protocol)
+ * @param ec taler-specific error code
+ * @param obj the received JSON reply, should be kept as proof (and, in case 
of errors,
+ *            be forwarded to the customer)
+ */
+static void
+pay_cb (void *cls,
+        unsigned int http_status,
+       enum TALER_ErrorCode ec,
+        const json_t *obj)
+{
+  struct InterpreterState *is = cls;
+  struct Command *cmd = &is->commands[is->ip];
+  struct PaymentResponsePS mr;
+  struct GNUNET_CRYPTO_EddsaSignature sig;
+  struct GNUNET_HashCode h_proposal_data;
+  const char *error_name;
+  unsigned int error_line;
+
+  cmd->details.pay.ph = NULL;
+  if (cmd->expected_response_code != http_status)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                "Unexpected response code %u to command %s\n",
+                http_status,
+                cmd->label);
+    json_dumpf (obj, stderr, 0);
+    fail (is);
+    return;
+  }
+  if (MHD_HTTP_OK == http_status)
+  {
+    /* Check signature */
+    struct GNUNET_JSON_Specification spec[] = {
+      GNUNET_JSON_spec_fixed_auto ("sig", &sig),
+      GNUNET_JSON_spec_fixed_auto ("h_proposal_data", &h_proposal_data),
+      GNUNET_JSON_spec_end ()
+    };
+    if (GNUNET_OK !=
+        GNUNET_JSON_parse (obj,
+                           spec,
+                           &error_name,
+                           &error_line))
+    {
+      GNUNET_break_op (0);
+      GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                  "Parser failed on %s:%u\n",
+                  error_name,
+                  error_line);
+      fail (is);
+      return;
+    }
+    mr.purpose.purpose = htonl (TALER_SIGNATURE_MERCHANT_PAYMENT_OK);
+    mr.purpose.size = htonl (sizeof (mr));
+    mr.h_proposal_data = h_proposal_data;
+    if (GNUNET_OK !=
+        GNUNET_CRYPTO_eddsa_verify (TALER_SIGNATURE_MERCHANT_PAYMENT_OK,
+                                    &mr.purpose,
+                                   &sig,
+                                   &cmd->details.pay.merchant_pub.eddsa_pub))
+    {
+      GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                  "Merchant signature given in response to /pay invalid\n");
+      fail (is);
+      return;
+    }
+
+  }
+
+  next_command (is);
+}
+
+/**
+ * Function called upon completion of our /admin/add/incoming request.
+ *
+ * @param cls closure with the interpreter state
+ * @param http_status HTTP response code, #MHD_HTTP_OK (200) for successful 
status 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 full_response full response from the exchange (for logging, in case 
of errors)
+ */
+static void
+add_incoming_cb (void *cls,
+                 unsigned int http_status,
+                enum TALER_ErrorCode ec,
+                 const json_t *full_response)
+{
+  struct InterpreterState *is = cls;
+  struct Command *cmd = &is->commands[is->ip];
+
+  cmd->details.admin_add_incoming.aih = NULL;
+  if (MHD_HTTP_OK != http_status)
+  {
+    GNUNET_break (0);
+    fail (is);
+    return;
+  }
+  next_command (is);
+}
+
+/**
+ * Find a command by label.
+ *
+ * @param is interpreter state to search
+ * @param label label to look for
+ * @return NULL if command was not found
+ */
+static const struct Command *
+find_command (const struct InterpreterState *is,
+              const char *label)
+{
+  unsigned int i;
+  const struct Command *cmd;
+
+  if (NULL == label)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+                "Attempt to lookup command for empty label\n");
+    return NULL;
+  }
+  for (i=0;OC_END != (cmd = &is->commands[i])->oc;i++)
+    if ( (NULL != cmd->label) &&
+         (0 == strcmp (cmd->label,
+                       label)) )
+      return cmd;
+  GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+              "Command not found: %s\n",
+              label);
+  return NULL;
+}
+
+/**
+ * Function called upon completion of our /reserve/withdraw request.
+ *
+ * @param cls closure with the interpreter state
+ * @param http_status HTTP response code, #MHD_HTTP_OK (200) for successful 
status request
+ *                    0 if the exchange's reply is bogus (fails to follow the 
protocol)
+ * @param ec taler-specific error code
+ * @param sig signature over the coin, NULL on error
+ * @param full_response full response from the exchange (for logging, in case 
of errors)
+ */
+static void
+reserve_withdraw_cb (void *cls,
+                     unsigned int http_status,
+                    enum TALER_ErrorCode ec,
+                     const struct TALER_DenominationSignature *sig,
+                     const json_t *full_response)
+{
+  struct InterpreterState *is = cls;
+  struct Command *cmd = &is->commands[is->ip];
+
+  cmd->details.reserve_withdraw.wsh = NULL;
+  if (cmd->expected_response_code != http_status)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                "Unexpected response code %u to command %s\n",
+                http_status,
+                cmd->label);
+    json_dumpf (full_response, stderr, 0);
+    GNUNET_break (0);
+    fail (is);
+    return;
+  }
+  switch (http_status)
+  {
+  case MHD_HTTP_OK:
+    if (NULL == sig)
+    {
+      GNUNET_break (0);
+      fail (is);
+      return;
+    }
+    cmd->details.reserve_withdraw.sig.rsa_signature
+      = GNUNET_CRYPTO_rsa_signature_dup (sig->rsa_signature);
+    break;
+  case MHD_HTTP_PAYMENT_REQUIRED:
+    /* nothing to check */
+    break;
+  default:
+    /* Unsupported status code (by test harness) */
+    GNUNET_break (0);
+    break;
+  }
+  next_command (is);
+}
+
+/**
+ * Find denomination key matching the given amount.
+ *
+ * @param keys array of keys to search
+ * @param amount coin value to look for
+ * @return NULL if no matching key was found
+ */
+static const struct TALER_EXCHANGE_DenomPublicKey *
+find_pk (const struct TALER_EXCHANGE_Keys *keys,
+         const struct TALER_Amount *amount)
+{
+  unsigned int i;
+  struct GNUNET_TIME_Absolute now;
+  struct TALER_EXCHANGE_DenomPublicKey *pk;
+  char *str;
+
+  now = GNUNET_TIME_absolute_get ();
+  for (i=0;i<keys->num_denom_keys;i++)
+  {
+    pk = &keys->denom_keys[i];
+    if ( (0 == TALER_amount_cmp (amount,
+                                 &pk->value)) &&
+         (now.abs_value_us >= pk->valid_from.abs_value_us) &&
+         (now.abs_value_us < pk->withdraw_valid_until.abs_value_us) )
+      return pk;
+  }
+  /* do 2nd pass to check if expiration times are to blame for failure */
+  str = TALER_amount_to_string (amount);
+  for (i=0;i<keys->num_denom_keys;i++)
+  {
+    pk = &keys->denom_keys[i];
+    if ( (0 == TALER_amount_cmp (amount,
+                                 &pk->value)) &&
+         ( (now.abs_value_us < pk->valid_from.abs_value_us) ||
+           (now.abs_value_us > pk->withdraw_valid_until.abs_value_us) ) )
+    {
+      GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+                  "Have denomination key for `%s', but with wrong expiration 
range %llu vs [%llu,%llu)\n",
+                  str,
+                  (unsigned long long) now.abs_value_us,
+                  (unsigned long long) pk->valid_from.abs_value_us,
+                  (unsigned long long) pk->withdraw_valid_until.abs_value_us);
+      GNUNET_free (str);
+      return NULL;
+    }
+  }
+  GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+              "No denomination key for amount %s found\n",
+              str);
+  GNUNET_free (str);
+  return NULL;
+}
+
+/**
+ * Run the main interpreter loop that performs exchange operations.
+ *
+ * @param cls contains the `struct InterpreterState`
+ */
+static void
+interpreter_run (void *cls)
+{
+  const struct GNUNET_SCHEDULER_TaskContext *tc;
+  struct InterpreterState *is = cls;
+  struct Command *cmd = &is->commands[is->ip];
+  const struct Command *ref;
+  struct TALER_ReservePublicKeyP reserve_pub;
+  struct TALER_CoinSpendPublicKeyP coin_pub;
+  struct TALER_Amount amount;
+  struct GNUNET_TIME_Absolute execution_date;
+  json_t *sender_details;
+  json_t *transfer_details;
+
+  is->task = NULL;
+  tc = GNUNET_SCHEDULER_get_task_context ();
+  if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
+  {
+    fprintf (stderr,
+             "Test aborted by shutdown request\n");
+    fail (is);
+    return;
+  }
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+             "Interpreter runs command %u/%s(%u)\n",
+             is->ip,
+             cmd->label,
+             cmd->oc);
+
+  switch (cmd->oc)
+  {
+    case OC_END:
+      result = GNUNET_OK;
+      GNUNET_SCHEDULER_shutdown ();
+      return;
+
+    case OC_PAY:
+      {
+        struct TALER_MERCHANT_PayCoin pc;
+        const char *order_id;
+        struct GNUNET_TIME_Absolute refund_deadline;
+        struct GNUNET_TIME_Absolute pay_deadline;
+        struct GNUNET_TIME_Absolute timestamp;
+        struct GNUNET_HashCode h_wire;
+        struct TALER_MerchantPublicKeyP merchant_pub;
+        struct TALER_MerchantSignatureP merchant_sig;
+        struct TALER_Amount total_amount;
+        struct TALER_Amount max_fee;
+        const char *error_name;
+        unsigned int error_line;
+  
+        /* get proposal */
+        ref = find_command (is,
+                            cmd->details.pay.contract_ref);
+        GNUNET_assert (NULL != ref);
+        merchant_sig = ref->details.proposal.merchant_sig;
+        GNUNET_assert (NULL != ref->details.proposal.proposal_data);
+        {
+          /* Get information that need to be replied in the deposit permission 
*/
+          struct GNUNET_JSON_Specification spec[] = {
+            GNUNET_JSON_spec_string ("order_id", &order_id),
+            GNUNET_JSON_spec_absolute_time ("refund_deadline", 
&refund_deadline),
+            GNUNET_JSON_spec_absolute_time ("pay_deadline", &pay_deadline),
+            GNUNET_JSON_spec_absolute_time ("timestamp", &timestamp),
+            GNUNET_JSON_spec_fixed_auto ("merchant_pub", &merchant_pub),
+            GNUNET_JSON_spec_fixed_auto ("H_wire", &h_wire),
+            TALER_JSON_spec_amount ("amount", &total_amount),
+            TALER_JSON_spec_amount ("max_fee", &max_fee),
+            GNUNET_JSON_spec_end()
+          };
+  
+          if (GNUNET_OK !=
+              GNUNET_JSON_parse (ref->details.proposal.proposal_data,
+                                 spec,
+                                 &error_name,
+                                 &error_line))
+          {
+            GNUNET_break_op (0);
+            GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                        "Parser failed on %s:%u\n",
+                        error_name,
+                        error_line);
+            fail (is);
+            return;
+          }
+          cmd->details.pay.merchant_pub = merchant_pub;
+        }
+  
+        {
+          const struct Command *coin_ref;
+       memset (&pc, 0, sizeof (pc));
+       coin_ref = find_command (is,
+                                cmd->details.pay.coin_ref);
+       GNUNET_assert (NULL != ref);
+       switch (coin_ref->oc)
+       {
+       case OC_WITHDRAW_SIGN:
+         pc.coin_priv = coin_ref->details.reserve_withdraw.coin_priv;
+         pc.denom_pub = coin_ref->details.reserve_withdraw.pk->key;
+         pc.denom_sig = coin_ref->details.reserve_withdraw.sig;
+            pc.denom_value = coin_ref->details.reserve_withdraw.pk->value;
+         break;
+       default:
+         GNUNET_assert (0);
+       }
+  
+       if (GNUNET_OK !=
+           TALER_string_to_amount (cmd->details.pay.amount_without_fee,
+                                   &pc.amount_without_fee))
+       {
+         GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                     "Failed to parse amount `%s' at %u\n",
+                     cmd->details.pay.amount_without_fee,
+                     is->ip);
+         fail (is);
+         return;
+       }
+  
+       if (GNUNET_OK !=
+           TALER_string_to_amount (cmd->details.pay.amount_with_fee,
+                                   &pc.amount_with_fee))
+       {
+         GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                     "Failed to parse amount `%s' at %u\n",
+                     cmd->details.pay.amount_with_fee,
+                     is->ip);
+         fail (is);
+         return;
+       }
+        }
+  
+        cmd->details.pay.ph
+       = TALER_MERCHANT_pay_wallet (ctx,
+                                    MERCHANT_URI,
+                                     INSTANCE,
+                                    &ref->details.proposal.hash,
+                                    &total_amount,
+                                    &max_fee,
+                                    &merchant_pub,
+                                       &merchant_sig,
+                                    timestamp,
+                                    refund_deadline,
+                                    pay_deadline,
+                                    &h_wire,
+                                    EXCHANGE_URI,
+                                     order_id,
+                                    1 /* num_coins */,
+                                    &pc /* coins */,
+                                    &pay_cb,
+                                    is);
+      }
+      if (NULL == cmd->details.pay.ph)
+      {
+        GNUNET_break (0);
+        fail (is);
+        return;
+      }
+      return;
+
+
+    case OC_PROPOSAL:
+      {
+        json_t *order;
+        json_error_t error;
+  
+        order = json_loads (cmd->details.proposal.order,
+                            JSON_REJECT_DUPLICATES,
+                            &error);
+        if (NULL == order)
+        {
+          GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                      "Failed to parse the order `%s' at command #%u: %s at 
%u\n",
+                      cmd->details.proposal.order,
+                      is->ip,
+                      error.text,
+                      (unsigned int) error.column);
+          fail (is);
+          return;
+        }
+        
+        cmd->details.proposal.po
+          = TALER_MERCHANT_order_put (ctx,
+                                      MERCHANT_URI,
+                                      order,
+                                      &proposal_cb,
+                                      is);
+        json_decref (order);
+        if (NULL == cmd->details.proposal.po)
+        {
+          GNUNET_break (0);
+          fail (is);
+          return;
+        }
+        return;
+      }
+
+    case OC_ADMIN_ADD_INCOMING:
+      if (NULL !=
+          cmd->details.admin_add_incoming.reserve_reference)
+      {
+        ref = find_command (is,
+                            cmd->details.admin_add_incoming.reserve_reference);
+        GNUNET_assert (NULL != ref);
+        GNUNET_assert (OC_ADMIN_ADD_INCOMING == ref->oc);
+        cmd->details.admin_add_incoming.reserve_priv
+          = ref->details.admin_add_incoming.reserve_priv;
+      }
+      else
+      {
+        struct GNUNET_CRYPTO_EddsaPrivateKey *priv;
+  
+        priv = GNUNET_CRYPTO_eddsa_key_create ();
+        cmd->details.admin_add_incoming.reserve_priv.eddsa_priv = *priv;
+        GNUNET_free (priv);
+      }
+      GNUNET_CRYPTO_eddsa_key_get_public 
(&cmd->details.admin_add_incoming.reserve_priv.eddsa_priv,
+                                          &reserve_pub.eddsa_pub);
+      if (GNUNET_OK !=
+          TALER_string_to_amount (cmd->details.admin_add_incoming.amount,
+                                  &amount))
+      {
+        GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                    "Failed to parse amount `%s' at %u\n",
+                    cmd->details.admin_add_incoming.amount,
+                    is->ip);
+        fail (is);
+        return;
+      }
+  
+      execution_date = GNUNET_TIME_absolute_get ();
+      GNUNET_TIME_round_abs (&execution_date);
+      sender_details = json_loads 
(cmd->details.admin_add_incoming.sender_details,
+                                   JSON_REJECT_DUPLICATES,
+                                   NULL);
+      if (NULL == sender_details)
+      {
+        GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                    "Failed to parse sender details `%s' at %u\n",
+                    cmd->details.admin_add_incoming.sender_details,
+                    is->ip);
+        fail (is);
+        return;
+      }
+      transfer_details = json_loads 
(cmd->details.admin_add_incoming.transfer_details,
+                                     JSON_REJECT_DUPLICATES,
+                                     NULL);
+  
+      if (NULL == transfer_details)
+      {
+        GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                    "Failed to parse transfer details `%s' at %u\n",
+                    cmd->details.admin_add_incoming.transfer_details,
+                    is->ip);
+        fail (is);
+        return;
+      }
+      cmd->details.admin_add_incoming.aih
+        = TALER_EXCHANGE_admin_add_incoming (exchange,
+                                             EXCHANGE_URI,
+                                             &reserve_pub,
+                                             &amount,
+                                             execution_date,
+                                             sender_details,
+                                             transfer_details,
+                                             &add_incoming_cb,
+                                             is);
+      json_decref (sender_details);
+      json_decref (transfer_details);
+      if (NULL == cmd->details.admin_add_incoming.aih)
+      {
+        GNUNET_break (0);
+        fail (is);
+        return;
+      }
+      return;
+
+    case OC_WITHDRAW_SIGN:
+      GNUNET_assert (NULL !=
+                     cmd->details.reserve_withdraw.reserve_reference);
+      ref = find_command (is,
+                          cmd->details.reserve_withdraw.reserve_reference);
+      GNUNET_assert (NULL != ref);
+      GNUNET_assert (OC_ADMIN_ADD_INCOMING == ref->oc);
+      if (NULL != cmd->details.reserve_withdraw.amount)
+      {
+        if (GNUNET_OK !=
+            TALER_string_to_amount (cmd->details.reserve_withdraw.amount,
+                                    &amount))
+        {
+          GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                      "Failed to parse amount `%s' at %u\n",
+                      cmd->details.reserve_withdraw.amount,
+                      is->ip);
+          fail (is);
+          return;
+        }
+        cmd->details.reserve_withdraw.pk = find_pk (is->keys,
+                                                    &amount);
+      }
+      if (NULL == cmd->details.reserve_withdraw.pk)
+      {
+        GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                    "Failed to determine denomination key at %u\n",
+                    is->ip);
+        fail (is);
+        return;
+      }
+  
+      /* create coin's private key */
+      {
+        struct GNUNET_CRYPTO_EddsaPrivateKey *priv;
+  
+        priv = GNUNET_CRYPTO_eddsa_key_create ();
+        cmd->details.reserve_withdraw.coin_priv.eddsa_priv = *priv;
+        GNUNET_free (priv);
+      }
+      GNUNET_CRYPTO_eddsa_key_get_public 
(&cmd->details.reserve_withdraw.coin_priv.eddsa_priv,
+                                          &coin_pub.eddsa_pub);
+      GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_WEAK,
+                                  &cmd->details.reserve_withdraw.blinding_key,
+                                  sizeof 
(cmd->details.reserve_withdraw.blinding_key));
+  
+      cmd->details.reserve_withdraw.wsh
+        = TALER_EXCHANGE_reserve_withdraw (exchange,
+                                           cmd->details.reserve_withdraw.pk,
+                                           
&ref->details.admin_add_incoming.reserve_priv,
+                                           
&cmd->details.reserve_withdraw.coin_priv,
+                                           
&cmd->details.reserve_withdraw.blinding_key,
+                                           &reserve_withdraw_cb,
+                                           is);
+      if (NULL == cmd->details.reserve_withdraw.wsh)
+      {
+        GNUNET_break (0);
+        fail (is);
+        return;
+      }
+      return;
+
+    default:
+      GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+                  "Unknown command, OC: %d, label: %s.\n",
+                  cmd->oc,
+                  cmd->label);
+      fail (is);
+  }
+}
+
+/**
+ * Functions of this type are called to provide the retrieved signing and
+ * denomination keys of the exchange.  No TALER_EXCHANGE_*() functions should
+ * be called in this callback.
+ *
+ * @param cls closure
+ * @param keys information about keys of the exchange
+ */
+static void
+cert_cb (void *cls,
+         const struct TALER_EXCHANGE_Keys *keys)
+{
+  struct InterpreterState *is = cls;
+
+  /* check that keys is OK */
+#define ERR(cond) do { if(!(cond)) break; GNUNET_break (0); 
GNUNET_SCHEDULER_shutdown(); return; } while (0)
+  ERR (NULL == keys);
+  ERR (0 == keys->num_sign_keys);
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Read %u signing keys\n",
+              keys->num_sign_keys);
+  ERR (0 == keys->num_denom_keys);
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Read %u denomination keys\n",
+              keys->num_denom_keys);
+#undef ERR
+
+  /* run actual tests via interpreter-loop */
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+             "Certificate callback invoked, starting interpreter\n");
+  is->keys = keys;
+  is->task = GNUNET_SCHEDULER_add_now (&interpreter_run,
+                                       is);
+}
+
+/**
+ * Signal handler called for SIGCHLD.  Triggers the
+ * respective handler by writing to the trigger pipe.
+ */
+static void
+sighandler_child_death ()
+{
+  static char c;
+  int old_errno = errno;       /* back-up errno */
+
+  GNUNET_break (1 ==
+               GNUNET_DISK_file_write (GNUNET_DISK_pipe_handle
+                                       (sigpipe, GNUNET_DISK_PIPE_END_WRITE),
+                                       &c, sizeof (c)));
+  errno = old_errno;           /* restore errno */
+}
+
+/**
+ * Function run when the test terminates (good or bad).
+ * Cleans up our state.
+ *
+ * @param cls the interpreter state.
+ */
+static void
+do_shutdown (void *cls)
+{
+  struct InterpreterState *is = cls;
+  struct Command *cmd;
+  unsigned int i;
+
+  if (NULL != timeout_task)
+  {
+    GNUNET_SCHEDULER_cancel (timeout_task);
+    timeout_task = NULL;
+  }
+
+  for (i=0;OC_END != (cmd = &is->commands[i])->oc;i++)
+    switch (cmd->oc)
+    {
+      case OC_END:
+        GNUNET_assert (0);
+        break;
+  
+      case OC_PAY:
+        if (NULL != cmd->details.pay.ph)
+        {
+          GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+                      "Command %u (%s) did not complete\n",
+                      i,
+                      cmd->label);
+          TALER_MERCHANT_pay_cancel (cmd->details.pay.ph);
+          cmd->details.pay.ph = NULL;
+        }
+        break;
+  
+      case OC_PROPOSAL:
+        if (NULL != cmd->details.proposal.po)
+        {
+          GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+                      "Command %u (%s) did not complete\n",
+                      i,
+                      cmd->label);
+          TALER_MERCHANT_proposal_cancel (cmd->details.proposal.po);
+          cmd->details.proposal.po = NULL;
+        }
+        if (NULL != cmd->details.proposal.proposal_data)
+        {
+          json_decref (cmd->details.proposal.proposal_data);
+          cmd->details.proposal.proposal_data = NULL;
+        }
+        break;
+  
+      case OC_WITHDRAW_SIGN:
+        if (NULL != cmd->details.reserve_withdraw.wsh)
+        {
+          GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+                      "Command %u (%s) did not complete\n",
+                      i,
+                      cmd->label);
+          TALER_EXCHANGE_reserve_withdraw_cancel 
(cmd->details.reserve_withdraw.wsh);
+          cmd->details.reserve_withdraw.wsh = NULL;
+        }
+        if (NULL != cmd->details.reserve_withdraw.sig.rsa_signature)
+        {
+          GNUNET_CRYPTO_rsa_signature_free 
(cmd->details.reserve_withdraw.sig.rsa_signature);
+          cmd->details.reserve_withdraw.sig.rsa_signature = NULL;
+        }
+        break;
+  
+      case OC_ADMIN_ADD_INCOMING:
+        if (NULL != cmd->details.admin_add_incoming.aih)
+        {
+          GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+                      "Command %u (%s) did not complete\n",
+                      i,
+                      cmd->label);
+          TALER_EXCHANGE_admin_add_incoming_cancel 
(cmd->details.admin_add_incoming.aih);
+          cmd->details.admin_add_incoming.aih = NULL;
+        }
+        break;
+  
+      default:
+        GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                    "Shutdown: unknown instruction %d at %u (%s)\n",
+                    cmd->oc,
+                    i,
+                    cmd->label);
+        break;
+    }
+
+  if (NULL != is->task)
+  {
+    GNUNET_SCHEDULER_cancel (is->task);
+    is->task = NULL;
+  }
+  GNUNET_free (is);
+  if (NULL != exchange)
+  {
+    TALER_EXCHANGE_disconnect (exchange);
+    exchange = NULL;
+  }
+  if (NULL != ctx)
+  {
+    GNUNET_CURL_fini (ctx);
+    ctx = NULL;
+  }
+  if (NULL != rc)
+  {
+    GNUNET_CURL_gnunet_rc_destroy (rc);
+    rc = NULL;
+  }
+}
+
+/**
+ * Main function that will be run by the scheduler.
+ *
+ * @param cls closure
+ */
+static void
+run (void *cls)
+{
+  struct InterpreterState *is;
+  static struct Command commands[] =
+  {
+    /* Fill reserve with EUR:5.01, as withdraw fee is 1 ct per config */
+    { .oc = OC_ADMIN_ADD_INCOMING,
+      .label = "create-reserve-1",
+      .expected_response_code = MHD_HTTP_OK,
+      .details.admin_add_incoming.sender_details = "{ \"bank_uri\":\"" 
BANK_URI "\", \"type\":\"test\", \"account_number\":62, \"uuid\":1 }",
+      .details.admin_add_incoming.transfer_details = "{ \"uuid\": 1}",
+      .details.admin_add_incoming.amount = CURRENCY ":5.01" },
+    /* Fill reserve with EUR:5.01, as withdraw fee is 1 ct per config */
+    { .oc = OC_ADMIN_ADD_INCOMING,
+      .label = "create-reserve-2",
+      .expected_response_code = MHD_HTTP_OK,
+      .details.admin_add_incoming.sender_details = "{ \"bank_uri\":\"" 
BANK_URI "\", \"type\":\"test\", \"account_number\":62, \"uuid\":1 }",
+      .details.admin_add_incoming.transfer_details = "{ \"uuid\": 1}",
+      .details.admin_add_incoming.amount = CURRENCY ":5.01" },
+    /* Fill reserve with EUR:5.01, as withdraw fee is 1 ct per config */
+    { .oc = OC_ADMIN_ADD_INCOMING,
+      .label = "create-reserve-3",
+      .expected_response_code = MHD_HTTP_OK,
+      .details.admin_add_incoming.sender_details = "{ \"bank_uri\":\"" 
BANK_URI "\", \"type\":\"test\", \"account_number\":62, \"uuid\":1 }",
+      .details.admin_add_incoming.transfer_details = "{ \"uuid\": 1}",
+      .details.admin_add_incoming.amount = CURRENCY ":5.01" },
+    /* Withdraw a 5 EUR coin, at fee of 1 ct */
+    { .oc = OC_WITHDRAW_SIGN,
+      .label = "withdraw-coin-1",
+      .expected_response_code = MHD_HTTP_OK,
+      .details.reserve_withdraw.reserve_reference = "create-reserve-1",
+      .details.reserve_withdraw.amount = CURRENCY ":5" },
+    /* Withdraw a 5 EUR coin, at fee of 1 ct */
+    { .oc = OC_WITHDRAW_SIGN,
+      .label = "withdraw-coin-2",
+      .expected_response_code = MHD_HTTP_OK,
+      .details.reserve_withdraw.reserve_reference = "create-reserve-2",
+      .details.reserve_withdraw.amount = CURRENCY ":5" },
+    /* Withdraw a 5 EUR coin, at fee of 1 ct */
+    { .oc = OC_WITHDRAW_SIGN,
+      .label = "withdraw-coin-3",
+      .expected_response_code = MHD_HTTP_OK,
+      .details.reserve_withdraw.reserve_reference = "create-reserve-3",
+      .details.reserve_withdraw.amount = CURRENCY ":5" },
+
+    /* Create proposal */
+    { .oc = OC_PROPOSAL,
+      .label = "create-proposal-1",
+      .expected_response_code = MHD_HTTP_OK,
+      .details.proposal.order = "{\
+                  \"max_fee\":\
+                     {\"currency\":\"" CURRENCY "\", \"value\":0, 
\"fraction\":50000000},\
+                  \"order_id\":\"1\",\
+                  \"timestamp\":\"\\/Date(42)\\/\",\
+                  \"refund_deadline\":\"\\/Date(0)\\/\",\
+                  \"pay_deadline\":\"\\/Date(9999999999)\\/\",\
+                  \"amount\":{\"currency\":\"" CURRENCY "\", \"value\":5, 
\"fraction\":0},\
+                  \"merchant\":{\"instance\":\"" INSTANCE "\"},\
+                 \"summary\": \"merchant-lib testcase\",\
+                  \"products\":\
+                     [ {\"description\":\"ice cream\", \"value\":\"{" CURRENCY 
":5}\"} ] }"},
+
+    /* Create proposal */
+    { .oc = OC_PROPOSAL,
+      .label = "create-proposal-2",
+      .expected_response_code = MHD_HTTP_OK,
+      .details.proposal.order = "{\
+                  \"max_fee\":\
+                     {\"currency\":\"" CURRENCY "\", \"value\":0, 
\"fraction\":50000000},\
+                  \"order_id\":\"2\",\
+                  \"timestamp\":\"\\/Date(42)\\/\",\
+                  \"refund_deadline\":\"\\/Date(0)\\/\",\
+                  \"pay_deadline\":\"\\/Date(9999999999)\\/\",\
+                  \"amount\":{\"currency\":\"" CURRENCY "\", \"value\":5, 
\"fraction\":0},\
+                  \"merchant\":{\"instance\":\"" INSTANCE "\"},\
+                 \"summary\": \"merchant-lib testcase\",\
+                  \"products\":\
+                     [ {\"description\":\"ice cream\", \"value\":\"{" CURRENCY 
":5}\"} ] }"},
+
+    /* Create proposal */
+    { .oc = OC_PROPOSAL,
+      .label = "create-proposal-3",
+      .expected_response_code = MHD_HTTP_OK,
+      .details.proposal.order = "{\
+                  \"max_fee\":\
+                     {\"currency\":\"" CURRENCY "\", \"value\":0, 
\"fraction\":50000000},\
+                  \"order_id\":\"3\",\
+                  \"timestamp\":\"\\/Date(42)\\/\",\
+                  \"refund_deadline\":\"\\/Date(0)\\/\",\
+                  \"pay_deadline\":\"\\/Date(9999999999)\\/\",\
+                  \"amount\":{\"currency\":\"" CURRENCY "\", \"value\":5, 
\"fraction\":0},\
+                  \"merchant\":{\"instance\":\"" INSTANCE "\"},\
+                 \"summary\": \"merchant-lib testcase\",\
+                  \"products\":\
+                     [ {\"description\":\"ice cream\", \"value\":\"{" CURRENCY 
":5}\"} ] }"},
+
+    { .oc = OC_PAY,
+      .label = "deposit-simple",
+      .expected_response_code = MHD_HTTP_OK,
+      .details.pay.contract_ref = "create-proposal-1",
+      .details.pay.coin_ref = "withdraw-coin-1",
+      .details.pay.amount_with_fee = CURRENCY ":5",
+      .details.pay.amount_without_fee = CURRENCY ":4.99" },
+
+    { .oc = OC_PAY,
+      .label = "deposit-simple",
+      .expected_response_code = MHD_HTTP_OK,
+      .details.pay.contract_ref = "create-proposal-2",
+      .details.pay.coin_ref = "withdraw-coin-2",
+      .details.pay.amount_with_fee = CURRENCY ":5",
+      .details.pay.amount_without_fee = CURRENCY ":4.99" },
+
+    { .oc = OC_PAY,
+      .label = "deposit-simple",
+      .expected_response_code = MHD_HTTP_OK,
+      .details.pay.contract_ref = "create-proposal-3",
+      .details.pay.coin_ref = "withdraw-coin-3",
+      .details.pay.amount_with_fee = CURRENCY ":5",
+      .details.pay.amount_without_fee = CURRENCY ":4.99" },
+
+    { .oc = OC_END,
+      .label = "end-of-commands"}
+  };
+
+  is = GNUNET_new (struct InterpreterState);
+  is->commands = commands;
+
+  ctx = GNUNET_CURL_init (&GNUNET_CURL_gnunet_scheduler_reschedule,
+                          &rc);
+  GNUNET_assert (NULL != ctx);
+  rc = GNUNET_CURL_gnunet_rc_create (ctx);
+  exchange = TALER_EXCHANGE_connect (ctx,
+                                     EXCHANGE_URI,
+                                     &cert_cb, is,
+                                     TALER_EXCHANGE_OPTION_END);
+  GNUNET_assert (NULL != exchange);
+  timeout_task
+    = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply
+                                    (GNUNET_TIME_UNIT_SECONDS, 150),
+                                    &do_timeout, NULL);
+  GNUNET_SCHEDULER_add_shutdown (&do_shutdown, is);
+
+
+}
+
+int
+main (int argc,
+      char *argv[])
+{
+  struct GNUNET_OS_Process *exchanged;
+  struct GNUNET_OS_Process *merchantd;
+  unsigned int cnt;
+  struct GNUNET_SIGNAL_Context *shc_chld;
+
+  unsetenv ("XDG_DATA_HOME");
+  unsetenv ("XDG_CONFIG_HOME");
+
+  GNUNET_log_setup ("merchant-create-payments",
+                    "DEBUG",
+                    NULL);
+
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "About to launch the exchange.\n");
+
+  exchanged = GNUNET_OS_start_process (GNUNET_NO,
+                                       GNUNET_OS_INHERIT_STD_ALL,
+                                       NULL, NULL, NULL,
+                                       "taler-exchange-httpd",
+                                       "taler-exchange-httpd",
+                                       NULL);
+  if (NULL == exchanged)
+  {
+    fprintf (stderr,
+             "Failed to run taler-exchange-httpd. Check your PATH.\n");
+    return 77;
+  }
+
+  fprintf (stderr,
+           "Waiting for taler-exchange-httpd to be ready\n");
+  cnt = 0;
+  do
+    {
+      fprintf (stderr, ".");
+      sleep (1);
+      cnt++;
+      if (cnt > 60)
+      {
+        fprintf (stderr,
+                 "\nFailed to start taler-exchange-httpd\n");
+        GNUNET_OS_process_kill (exchanged,
+                                SIGKILL);
+        GNUNET_OS_process_wait (exchanged);
+        GNUNET_OS_process_destroy (exchanged);
+        return 77;
+      }
+    }
+  while (0 != system ("wget -q -t 1 -T 1 " EXCHANGE_URI "keys -o /dev/null -O 
/dev/null"));
+  fprintf (stderr, "\n");
+
+  merchantd = GNUNET_OS_start_process (GNUNET_NO,
+                                       GNUNET_OS_INHERIT_STD_ALL,
+                                       NULL, NULL, NULL,
+                                       "taler-merchant-httpd",
+                                       "taler-merchant-httpd",
+                                       "-L", "DEBUG",
+                                       NULL);
+  if (NULL == merchantd)
+  {
+    fprintf (stderr,
+             "Failed to run taler-merchant-httpd. Check your PATH.\n");
+    GNUNET_OS_process_kill (exchanged,
+                            SIGKILL);
+    GNUNET_OS_process_wait (exchanged);
+    GNUNET_OS_process_destroy (exchanged);
+    return 77;
+  }
+  /* give child time to start and bind against the socket */
+  fprintf (stderr,
+           "Waiting for taler-merchant-httpd to be ready\n");
+  cnt = 0;
+  do
+    {
+      fprintf (stderr, ".");
+      sleep (1);
+      cnt++;
+      if (cnt > 60)
+      {
+        fprintf (stderr,
+                 "\nFailed to start taler-merchant-httpd\n");
+        GNUNET_OS_process_kill (merchantd,
+                                SIGKILL);
+        GNUNET_OS_process_wait (merchantd);
+        GNUNET_OS_process_destroy (merchantd);
+        GNUNET_OS_process_kill (exchanged,
+                                SIGKILL);
+        GNUNET_OS_process_wait (exchanged);
+        GNUNET_OS_process_destroy (exchanged);
+        return 77;
+      }
+    }
+  while (0 != system ("wget -q -t 1 -T 1 " MERCHANT_URI " -o /dev/null -O 
/dev/null"));
+  fprintf (stderr, "\n");
+
+  result = GNUNET_SYSERR;
+  sigpipe = GNUNET_DISK_pipe (GNUNET_NO, GNUNET_NO, GNUNET_NO, GNUNET_NO);
+  GNUNET_assert (NULL != sigpipe);
+  shc_chld = GNUNET_SIGNAL_handler_install (GNUNET_SIGCHLD,
+                                            &sighandler_child_death);
+  GNUNET_SCHEDULER_run (&run, NULL);
+
+  GNUNET_SIGNAL_handler_uninstall (shc_chld);
+  shc_chld = NULL;
+  GNUNET_DISK_pipe_close (sigpipe);
+  GNUNET_OS_process_kill (merchantd,
+                          SIGTERM);
+  GNUNET_OS_process_wait (merchantd);
+  GNUNET_OS_process_destroy (merchantd);
+  GNUNET_OS_process_kill (exchanged,
+                          SIGTERM);
+  GNUNET_OS_process_wait (exchanged);
+  GNUNET_OS_process_destroy (exchanged);
+  if (77 == result)
+    return 77;
+  return (GNUNET_OK == result) ? 0 : 1;
+}
diff --git 
a/src/lib/test_merchant_api_home/.config/taler/merchant/wire/test.json 
b/src/samples/generate_payments_home/.config/taler/merchant/wire/test.json
similarity index 100%
copy from src/lib/test_merchant_api_home/.config/taler/merchant/wire/test.json
copy to src/samples/generate_payments_home/.config/taler/merchant/wire/test.json
diff --git a/src/samples/generate_payments_home/.config/taler/test.json 
b/src/samples/generate_payments_home/.config/taler/test.json
new file mode 100644
index 0000000..6c29eab
--- /dev/null
+++ b/src/samples/generate_payments_home/.config/taler/test.json
@@ -0,0 +1,6 @@
+{
+  "type": "test",
+  "account_number": 3,
+  "bank_uri": "http://localhost:8083/";,
+  "name": "The exchange"
+}
diff --git a/src/samples/generate_payments_home/.config/taler/test.signed.json 
b/src/samples/generate_payments_home/.config/taler/test.signed.json
new file mode 100644
index 0000000..532640f
--- /dev/null
+++ b/src/samples/generate_payments_home/.config/taler/test.signed.json
@@ -0,0 +1,8 @@
+{
+  "type": "test",
+  "salt": 
"0STGVVCSNJBKCP92596RSHN54Y4YW46J6D910KMPB6FF5ZYXG1C8MTMRFG32H9HFBA2XNNKRPRTKGD0KKKM805QGZ0AR28W5DB00MDG",
+  "account_number": 3,
+  "bank_uri": "http://localhost:8083/";,
+  "name": "The exchange",
+  "sig": 
"6EZF2DQBJP7WFQK93MHW1B21N12DFPJ5KMB9KS6Y775W1YS1ZZ0CAP9Y2CDK14Q01S0HR51SGHVNGA1WDNV5C07K941BRCRE9MSSP0G"
+}
\ No newline at end of file
diff --git 
a/src/samples/generate_payments_home/.local/share/taler/exchange/offline-keys/master.priv
 
b/src/samples/generate_payments_home/.local/share/taler/exchange/offline-keys/master.priv
new file mode 100644
index 0000000..0a17bb2
--- /dev/null
+++ 
b/src/samples/generate_payments_home/.local/share/taler/exchange/offline-keys/master.priv
@@ -0,0 +1 @@
+�QJ�_�#��O4(�kTr�$N ��8��2
\ No newline at end of file
diff --git a/src/samples/merchant_generate_payments.conf 
b/src/samples/merchant_generate_payments.conf
new file mode 100644
index 0000000..07f7692
--- /dev/null
+++ b/src/samples/merchant_generate_payments.conf
@@ -0,0 +1,132 @@
+# This file is in the public domain.
+#
+[PATHS]
+# Persistant data storage for the testcase
+TALER_TEST_HOME = generate_payments_home/
+
+[taler]
+# What currency do we use?
+CURRENCY = EUR
+
+[exchange-wire-test]
+# Enable 'test' for testing of the actual coin operations.
+ENABLE = YES
+
+# 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
+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
+
+############################
+# Exchange's configuration #
+############################
+
+[exchange]
+# How to access our database
+DB = postgres
+
+# HTTP port the exchange listens to
+PORT = 8081
+
+# Our public key
+MASTER_PUBLIC_KEY = BNFX90SBRFRMFW7E598BKVH6CTM83YD2AAKRZ0ADGH15M1XXJGBG
+
+# This value must match the DB we want payments to persist in.
+[exchangedb-postgres]
+DB_CONN_STR = "postgres:///taler"
+
+
+[exchange-wire-incoming-test]
+TEST_RESPONSE_FILE = ${TALER_CONFIG_HOME}/test.signed.json
+
+[exchange-wire-outgoing-test]
+BANK_URI = "http://localhost:8083/";
+BANK_ACCOUNT_NUMBER = 2
+
+[coin_eur_ct_1]
+value = EUR:0.01
+duration_overlap = 5 minutes
+duration_withdraw = 7 days
+duration_spend = 2 years
+duration_legal = 3 years
+fee_withdraw = EUR:0.00
+fee_deposit = EUR:0.00
+fee_refresh = EUR:0.01
+fee_refund = EUR:0.01
+rsa_keysize = 1024
+
+[coin_eur_ct_10]
+value = EUR:0.10
+duration_overlap = 5 minutes
+duration_withdraw = 7 days
+duration_spend = 2 years
+duration_legal = 3 years
+fee_withdraw = EUR:0.01
+fee_deposit = EUR:0.01
+fee_refresh = EUR:0.03
+fee_refund = EUR:0.01
+rsa_keysize = 1024
+
+[coin_eur_1]
+value = EUR:1
+duration_overlap = 5 minutes
+duration_withdraw = 7 days
+duration_spend = 2 years
+duration_legal = 3 years
+fee_withdraw = EUR:0.01
+fee_deposit = EUR:0.01
+fee_refresh = EUR:0.03
+fee_refund = EUR:0.01
+rsa_keysize = 1024
+
+[coin_eur_5]
+value = EUR:5
+duration_overlap = 5 minutes
+duration_withdraw = 7 days
+duration_spend = 2 years
+duration_legal = 3 years
+fee_withdraw = EUR:0.01
+fee_deposit = EUR:0.01
+fee_refresh = EUR:0.03
+fee_refund = EUR:0.01
+rsa_keysize = 1024
+
+
+[merchant]
+
+# Which port do we run the backend on? (HTTP server)
+PORT = 8082
+
+# How quickly do we want the exchange to send us our money?
+# Used only if the frontend does not specify a value.
+# FIXME: EDATE is a bit short, 'execution_delay'?
+EDATE = 3 week
+
+# Which plugin (backend) do we use for the DB.
+DB = postgres
+
+# Wire format supported by the merchant.
+WIREFORMAT = test
+
+INSTANCES = default
+
+[merchant-exchange-test]
+URI = http://localhost:8081/
+MASTER_KEY = BNFX90SBRFRMFW7E598BKVH6CTM83YD2AAKRZ0ADGH15M1XXJGBG
+
+[merchant-instance-default]
+KEYFILE = test_merchant.priv
+
+[merchant-instance-wireformat-default]
+TEST_RESPONSE_FILE = ${TALER_CONFIG_HOME}/merchant/wire/test.json
+
+[merchantdb-postgres]
+CONFIG = postgres:///taler
diff --git a/src/lib/test_merchant.priv b/src/samples/test_merchant.priv
similarity index 100%
copy from src/lib/test_merchant.priv
copy to src/samples/test_merchant.priv
diff --git a/src/tests/Makefile.am b/src/tests/Makefile.am
deleted file mode 100644
index 1428589..0000000
--- a/src/tests/Makefile.am
+++ /dev/null
@@ -1,25 +0,0 @@
-# This Makefile.am is in the public domain
-AM_CPPFLAGS = -I$(top_srcdir)/src/include -I$(top_srcdir)/src/backend-lib/
-
-bin_PROGRAMS = \
-  test-contract
-
-#merchant_contract_test_CFLAGS = \
-#  -Wl,--verbose
-
-test_contract_SOURCES = \
-  test_contract.c \
-  ../backend/merchant.c \
-  ../backend-lib/merchant_db.c ../backend-lib/merchant_db.h
-
-test_contract_LDADD = \
-  $(LIBGCRYPT_LIBS) \
-  -ltalerutil \
-  -ljansson \
-  -lgnunetutil \
-  -ltalerexchange \
-  -ltalerpq \
-  -lgnunetpostgres \
-  -lpq \
-  $(top_srcdir)/src/backend-lib/libtalermerchant.la \
-  -lpthread
diff --git a/src/tests/deposit_permission.sample 
b/src/tests/deposit_permission.sample
deleted file mode 100644
index 668d004..0000000
--- a/src/tests/deposit_permission.sample
+++ /dev/null
@@ -1,31 +0,0 @@
-{
-    "transaction_id" : 1,
-    "timestamp": "\/Date(1447334003)\/",
-    "H_wire": 
"V1F0F5AWSNX60E6TXZEYDZRE84J8HMBGXEM09AEVV3N97MM75P6JQRSWR5KQVC1RBBF2SRXY7P10H0ZM0VETWPFAJJRBVJSXNMDWTYR",
-    "merchant_pub": "BQ0TMTBV2XEJ8G2PXA9KRDD5WDT5EV29KPVS6J9RBQJCS8BCPQ70",
-    "exchange": "localexchange",
-    "coins": [
-        {
-            "f": {
-                "value": 0,
-                "fraction": 100000,
-                "currency": "KUDOS"
-            },
-            "coin_pub": "AH86D5WV9G6RT0A3CHYJW598BNMH8848GAKYTEH1JX6X2BKZWTX0",
-            "denom_pub": 
"51R7ARKCD5HJTTV5F4G0M818E9SP280A40G2GVH04CR30HHG74SM8GSM6D33EGSR84R46E246H23GCHK690M4G9R8GS4CD9S8GRMCDSP64T34GA56GV34DA3851M6H9S6MWK8H9K8D13CD1M85344GSP61244GT28N132HA56N1MCHA56513AD2160RK2CSN6D23AGJ56X33AGSM68W4CH1S88WK4D1H68SMACHJ88TM2CA28MRM4D248GS4ADHR8GSM4C2364V38E1N88S30HA564TKJE1N750KGC9R6RTKJE2370R4AC268D0MACHN6N242D1N68TKAC1M65234DJ26CRK4D9M8MSK6C9J64R32D1R70VKEE25852MCG9N84W32GJ68914CD1J691M6GA360S3GCHP8GWK8HHH68TK8CSK70S4AE9N712K0H9K6X34AC9354520818CM
 [...]
-            "ub_sig": 
"51SPJSSDESGPR80A40M74WV140520818ECG26C9J8D1MCHHJ84S34H1K8H1M6HHN60V3GH9S84R3GH9K6MVM6GSM70RKCDT188VM4CHM74RM8GSN6GSKEHHS6CT44H9Q8CWKCD1P68SK2G9S8GR34D1P60T4CCJ67523EDJ28S1KJD9N8H330CT58RS38CSM8H346GT58N13CGJ16GS34CHQ6GT42CSS6CTM4C9H8N1KCG9G74T36C1K8GT44E1N8RRK0D218GV46G9R6CT4CHA4890M6H1H8GV34E1Q8N244DHM8CRK2H1R8CV3ADA37113JDHR88W36E9R61242GT5752KEE9R84WK8H9G8GT34GT26S2MAE1P70RMAGSK74W30C1J60S32GSK64WKAC218MWM6GHM8S332DSN70SM2DHR6H146E228CTM8D135452081918G2J2G0",
-            "coin_sig": 
"MFTHC54GFYHA3CGKHC8SSDSTYX8YMEJDNQA7AEY5M7JBK3WPDQ9NCJ54ZSPQRZ4QCJC0CPREP0XRWH9JQ509ENSEXWKNNM5FEVRG238"
-        },
-        {
-            "f": {
-                "value": 0,
-                "fraction": 100000,
-                "currency": "KUDOS"
-            },
-            "coin_pub": "MQY067A8AGG90TSH11C8JNRW8P1R669JAAQX4V2HGFHGJ2WY4ZA0",
-            "denom_pub": 
"51R7ARKCD5HJTTV5F4G0M818E9SP280A40G2GVH04CR30HHG74SM8GSM6D33EGSR84R46E246H23GCHK690M4G9R8GS4CD9S8GRMCDSP64T34GA56GV34DA3851M6H9S6MWK8H9K8D13CD1M85344GSP61244GT28N132HA56N1MCHA56513AD2160RK2CSN6D23AGJ56X33AGSM68W4CH1S88WK4D1H68SMACHJ88TM2CA28MRM4D248GS4ADHR8GSM4C2364V38E1N88S30HA564TKJE1N750KGC9R6RTKJE2370R4AC268D0MACHN6N242D1N68TKAC1M65234DJ26CRK4D9M8MSK6C9J64R32D1R70VKEE25852MCG9N84W32GJ68914CD1J691M6GA360S3GCHP8GWK8HHH68TK8CSK70S4AE9N712K0H9K6X34AC9354520818CM
 [...]
-            "ub_sig": 
"51SPJSSDESGPR80A40M74WV140520818ECG26H1J60R4AHHG6N1KEC268N23ECT664VKAGSJ8GRK4CA56H2KAH1H8CS4AHA188SKJE266RR3EDA58N148DSS74TM6CA58N24AC9K6X1M4C9Q6RW48CT674SMCE2264V42CSH8D336GSQ84SM6CT564TKECSR8MRMAGHG8GW3JEA56WT32D9S8H334DJ564SK8GSS60WM6E1P8S346H238GRM8DSN6MR36C256GVM8H9M6WV30C246X0MCH9R84TK2D1M70V44CA260VKJGHN6RR4ACT488R3GCA46MW3GDHK6GWMAHHP6S242H9G6D134D9N8RV32DSJ8GSKGC1J6RTK2GHQ8H0K2DHH6WT38GSH74WM4EA574RKEE1M6D0M4DHK8MW4ACT68CT4CE236H236GH35452081918G2J2G0",
-            "coin_sig": 
"K9S5273GT4QKF5Y9FYJ62BV710WGEFE1DSXV75A37X272ADWBCV0ERZV9TF2VYTCSH1837R3F7A39R5QEPCC0NYW3JQ5S70X8MJG008"
-        }
-    ]
-}
diff --git a/src/tests/deposit_permission_backend.sample 
b/src/tests/deposit_permission_backend.sample
deleted file mode 100644
index a2e6058..0000000
--- a/src/tests/deposit_permission_backend.sample
+++ /dev/null
@@ -1,36 +0,0 @@
-{
-    "transaction_id" : 1,
-    "timestamp": "\/Date(1447334003)\/",
-    "H_wire": 
"V1F0F5AWSNX60E6TXZEYDZRE84J8HMBGXEM09AEVV3N97MM75P6JQRSWR5KQVC1RBBF2SRXY7P10H0ZM0VETWPFAJJRBVJSXNMDWTYR",
-    "merchant_pub": "BQ0TMTBV2XEJ8G2PXA9KRDD5WDT5EV29KPVS6J9RBQJCS8BCPQ70",
-    "exchange": "demo.taler.net",
-    "coins": [
-        {
-            "f": {
-                "value": 0,
-                "fraction": 100000,
-                "currency": "KUDOS"
-            },
-            "coin_pub": "AH86D5WV9G6RT0A3CHYJW598BNMH8848GAKYTEH1JX6X2BKZWTX0",
-            "denom_pub": 
"51R7ARKCD5HJTTV5F4G0M818E9SP280A40G2GVH04CR30HHG74SM8GSM6D33EGSR84R46E246H23GCHK690M4G9R8GS4CD9S8GRMCDSP64T34GA56GV34DA3851M6H9S6MWK8H9K8D13CD1M85344GSP61244GT28N132HA56N1MCHA56513AD2160RK2CSN6D23AGJ56X33AGSM68W4CH1S88WK4D1H68SMACHJ88TM2CA28MRM4D248GS4ADHR8GSM4C2364V38E1N88S30HA564TKJE1N750KGC9R6RTKJE2370R4AC268D0MACHN6N242D1N68TKAC1M65234DJ26CRK4D9M8MSK6C9J64R32D1R70VKEE25852MCG9N84W32GJ68914CD1J691M6GA360S3GCHP8GWK8HHH68TK8CSK70S4AE9N712K0H9K6X34AC9354520818CM
 [...]
-            "ub_sig": 
"51SPJSSDESGPR80A40M74WV140520818ECG26C9J8D1MCHHJ84S34H1K8H1M6HHN60V3GH9S84R3GH9K6MVM6GSM70RKCDT188VM4CHM74RM8GSN6GSKEHHS6CT44H9Q8CWKCD1P68SK2G9S8GR34D1P60T4CCJ67523EDJ28S1KJD9N8H330CT58RS38CSM8H346GT58N13CGJ16GS34CHQ6GT42CSS6CTM4C9H8N1KCG9G74T36C1K8GT44E1N8RRK0D218GV46G9R6CT4CHA4890M6H1H8GV34E1Q8N244DHM8CRK2H1R8CV3ADA37113JDHR88W36E9R61242GT5752KEE9R84WK8H9G8GT34GT26S2MAE1P70RMAGSK74W30C1J60S32GSK64WKAC218MWM6GHM8S332DSN70SM2DHR6H146E228CTM8D135452081918G2J2G0",
-            "coin_sig": 
"MFTHC54GFYHA3CGKHC8SSDSTYX8YMEJDNQA7AEY5M7JBK3WPDQ9NCJ54ZSPQRZ4QCJC0CPREP0XRWH9JQ509ENSEXWKNNM5FEVRG238"
-        },
-        {
-            "f": {
-                "value": 0,
-                "fraction": 100000,
-                "currency": "KUDOS"
-            },
-            "coin_pub": "MQY067A8AGG90TSH11C8JNRW8P1R669JAAQX4V2HGFHGJ2WY4ZA0",
-            "denom_pub": 
"51R7ARKCD5HJTTV5F4G0M818E9SP280A40G2GVH04CR30HHG74SM8GSM6D33EGSR84R46E246H23GCHK690M4G9R8GS4CD9S8GRMCDSP64T34GA56GV34DA3851M6H9S6MWK8H9K8D13CD1M85344GSP61244GT28N132HA56N1MCHA56513AD2160RK2CSN6D23AGJ56X33AGSM68W4CH1S88WK4D1H68SMACHJ88TM2CA28MRM4D248GS4ADHR8GSM4C2364V38E1N88S30HA564TKJE1N750KGC9R6RTKJE2370R4AC268D0MACHN6N242D1N68TKAC1M65234DJ26CRK4D9M8MSK6C9J64R32D1R70VKEE25852MCG9N84W32GJ68914CD1J691M6GA360S3GCHP8GWK8HHH68TK8CSK70S4AE9N712K0H9K6X34AC9354520818CM
 [...]
-            "ub_sig": 
"51SPJSSDESGPR80A40M74WV140520818ECG26H1J60R4AHHG6N1KEC268N23ECT664VKAGSJ8GRK4CA56H2KAH1H8CS4AHA188SKJE266RR3EDA58N148DSS74TM6CA58N24AC9K6X1M4C9Q6RW48CT674SMCE2264V42CSH8D336GSQ84SM6CT564TKECSR8MRMAGHG8GW3JEA56WT32D9S8H334DJ564SK8GSS60WM6E1P8S346H238GRM8DSN6MR36C256GVM8H9M6WV30C246X0MCH9R84TK2D1M70V44CA260VKJGHN6RR4ACT488R3GCA46MW3GDHK6GWMAHHP6S242H9G6D134D9N8RV32DSJ8GSKGC1J6RTK2GHQ8H0K2DHH6WT38GSH74WM4EA574RKEE1M6D0M4DHK8MW4ACT68CT4CE236H236GH35452081918G2J2G0",
-            "coin_sig": 
"K9S5273GT4QKF5Y9FYJ62BV710WGEFE1DSXV75A37X272ADWBCV0ERZV9TF2VYTCSH1837R3F7A39R5QEPCC0NYW3JQ5S70X8MJG008"
-        }
-    ],
-    "max_fee": {
-        "value": 3,
-        "fraction": 8,
-        "currency": "KUDOS"
-    }
-}
diff --git a/src/tests/deposit_permission_edate_backend.sample 
b/src/tests/deposit_permission_edate_backend.sample
deleted file mode 100644
index 1b185b4..0000000
--- a/src/tests/deposit_permission_edate_backend.sample
+++ /dev/null
@@ -1,37 +0,0 @@
-{
-    "transaction_id" : 1,
-    "timestamp": "\/Date(1447334003)\/",
-    "edate": "\/Date(1447334003)\/",
-    "H_wire": 
"V1F0F5AWSNX60E6TXZEYDZRE84J8HMBGXEM09AEVV3N97MM75P6JQRSWR5KQVC1RBBF2SRXY7P10H0ZM0VETWPFAJJRBVJSXNMDWTYR",
-    "merchant_pub": "BQ0TMTBV2XEJ8G2PXA9KRDD5WDT5EV29KPVS6J9RBQJCS8BCPQ70",
-    "exchange": "demo.taler.net",
-    "coins": [
-        {
-            "f": {
-                "value": 0,
-                "fraction": 100000,
-                "currency": "KUDOS"
-            },
-            "coin_pub": "AH86D5WV9G6RT0A3CHYJW598BNMH8848GAKYTEH1JX6X2BKZWTX0",
-            "denom_pub": 
"51R7ARKCD5HJTTV5F4G0M818E9SP280A40G2GVH04CR30HHG74SM8GSM6D33EGSR84R46E246H23GCHK690M4G9R8GS4CD9S8GRMCDSP64T34GA56GV34DA3851M6H9S6MWK8H9K8D13CD1M85344GSP61244GT28N132HA56N1MCHA56513AD2160RK2CSN6D23AGJ56X33AGSM68W4CH1S88WK4D1H68SMACHJ88TM2CA28MRM4D248GS4ADHR8GSM4C2364V38E1N88S30HA564TKJE1N750KGC9R6RTKJE2370R4AC268D0MACHN6N242D1N68TKAC1M65234DJ26CRK4D9M8MSK6C9J64R32D1R70VKEE25852MCG9N84W32GJ68914CD1J691M6GA360S3GCHP8GWK8HHH68TK8CSK70S4AE9N712K0H9K6X34AC9354520818CM
 [...]
-            "ub_sig": 
"51SPJSSDESGPR80A40M74WV140520818ECG26C9J8D1MCHHJ84S34H1K8H1M6HHN60V3GH9S84R3GH9K6MVM6GSM70RKCDT188VM4CHM74RM8GSN6GSKEHHS6CT44H9Q8CWKCD1P68SK2G9S8GR34D1P60T4CCJ67523EDJ28S1KJD9N8H330CT58RS38CSM8H346GT58N13CGJ16GS34CHQ6GT42CSS6CTM4C9H8N1KCG9G74T36C1K8GT44E1N8RRK0D218GV46G9R6CT4CHA4890M6H1H8GV34E1Q8N244DHM8CRK2H1R8CV3ADA37113JDHR88W36E9R61242GT5752KEE9R84WK8H9G8GT34GT26S2MAE1P70RMAGSK74W30C1J60S32GSK64WKAC218MWM6GHM8S332DSN70SM2DHR6H146E228CTM8D135452081918G2J2G0",
-            "coin_sig": 
"MFTHC54GFYHA3CGKHC8SSDSTYX8YMEJDNQA7AEY5M7JBK3WPDQ9NCJ54ZSPQRZ4QCJC0CPREP0XRWH9JQ509ENSEXWKNNM5FEVRG238"
-        },
-        {
-            "f": {
-                "value": 0,
-                "fraction": 100000,
-                "currency": "KUDOS"
-            },
-            "coin_pub": "MQY067A8AGG90TSH11C8JNRW8P1R669JAAQX4V2HGFHGJ2WY4ZA0",
-            "denom_pub": 
"51R7ARKCD5HJTTV5F4G0M818E9SP280A40G2GVH04CR30HHG74SM8GSM6D33EGSR84R46E246H23GCHK690M4G9R8GS4CD9S8GRMCDSP64T34GA56GV34DA3851M6H9S6MWK8H9K8D13CD1M85344GSP61244GT28N132HA56N1MCHA56513AD2160RK2CSN6D23AGJ56X33AGSM68W4CH1S88WK4D1H68SMACHJ88TM2CA28MRM4D248GS4ADHR8GSM4C2364V38E1N88S30HA564TKJE1N750KGC9R6RTKJE2370R4AC268D0MACHN6N242D1N68TKAC1M65234DJ26CRK4D9M8MSK6C9J64R32D1R70VKEE25852MCG9N84W32GJ68914CD1J691M6GA360S3GCHP8GWK8HHH68TK8CSK70S4AE9N712K0H9K6X34AC9354520818CM
 [...]
-            "ub_sig": 
"51SPJSSDESGPR80A40M74WV140520818ECG26H1J60R4AHHG6N1KEC268N23ECT664VKAGSJ8GRK4CA56H2KAH1H8CS4AHA188SKJE266RR3EDA58N148DSS74TM6CA58N24AC9K6X1M4C9Q6RW48CT674SMCE2264V42CSH8D336GSQ84SM6CT564TKECSR8MRMAGHG8GW3JEA56WT32D9S8H334DJ564SK8GSS60WM6E1P8S346H238GRM8DSN6MR36C256GVM8H9M6WV30C246X0MCH9R84TK2D1M70V44CA260VKJGHN6RR4ACT488R3GCA46MW3GDHK6GWMAHHP6S242H9G6D134D9N8RV32DSJ8GSKGC1J6RTK2GHQ8H0K2DHH6WT38GSH74WM4EA574RKEE1M6D0M4DHK8MW4ACT68CT4CE236H236GH35452081918G2J2G0",
-            "coin_sig": 
"K9S5273GT4QKF5Y9FYJ62BV710WGEFE1DSXV75A37X272ADWBCV0ERZV9TF2VYTCSH1837R3F7A39R5QEPCC0NYW3JQ5S70X8MJG008"
-        }
-    ],
-    "max_fee": {
-        "value": 3,
-        "fraction": 8,
-        "currency": "KUDOS"
-    }
-}
diff --git a/src/tests/merchant.priv b/src/tests/merchant.priv
deleted file mode 100644
index 2101f67..0000000
--- a/src/tests/merchant.priv
+++ /dev/null
@@ -1 +0,0 @@
-���{�|�ic�?"��򊄏`J0�pkvTW��
\ No newline at end of file
diff --git a/src/tests/test_contract.c b/src/tests/test_contract.c
deleted file mode 100644
index ce75234..0000000
--- a/src/tests/test_contract.c
+++ /dev/null
@@ -1,341 +0,0 @@
-/*
-  This file is part of TALER
-  Copyright (C) 2014, 2015, 2016 INRIA
-
-  TALER is free software; you can redistribute it and/or modify it under the
-  terms of the GNU General Public License as published by the Free Software
-  Foundation; either version 3, or (at your option) any later version.
-
-  TALER is distributed in the hope that it will be useful, but WITHOUT ANY
-  WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
-  A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
-
-  You should have received a copy of the GNU General Public License along with
-  TALER; see the file COPYING.GPL.  If not, see <http://www.gnu.org/licenses/>
-*/
-
-/**
-* @file src/tests/test_contract.c
-* @brief test for various merchant's capabilities
-* @author Marcello Stanisci
-*/
-
-#include "platform.h"
-#include <jansson.h>
-#include <gnunet/gnunet_util_lib.h>
-#include <taler/taler_util.h>
-#include "merchant.h"
-#include "merchant_db.h"
-#include <taler_merchant_lib.h>
-
-PGconn *db_conn;
-
-static int dry;
-struct GNUNET_CRYPTO_EddsaPrivateKey *privkey;
-char *keyfile;
-static int result;
-static struct MERCHANT_WIREFORMAT_Sepa *wire;
-
-extern
-struct MERCHANT_WIREFORMAT_Sepa *
-TALER_MERCHANT_parse_wireformat_sepa (const struct GNUNET_CONFIGURATION_Handle 
*cfg);
-
-
-/**
- * Shutdown task (magically invoked when the application is being
- * quit)
- *
- * @param cls NULL
- * @param tc scheduler task context
- */
-static void
-do_shutdown (void *cls,
-             const struct GNUNET_SCHEDULER_TaskContext *tc)
-{
-
-  if (NULL != db_conn)
-    {
-      TALER_MERCHANTDB_disconnect (db_conn);
-      db_conn = NULL;
-    }
-}
-
-
-extern uint32_t
-TALER_MERCHANTDB_contract_get_values (PGconn *conn,
-                                      const struct GNUNET_HashCode *h_contract,
-                                      uint64_t *nounce,
-                                      struct GNUNET_TIME_Absolute 
*wire_transfer_deadline);
-
-
-/**
- * Main function that will be run by the scheduler.
- *
- * @param cls closure
- * @param args remaining command-line arguments
- * @param cfgfile name of the configuration file used (for saving, can be 
NULL!)
- * @param config configuration
- */
-static void
-run (void *cls, char *const *args, const char *cfgfile,
-     const struct GNUNET_CONFIGURATION_Handle *config)
-
-{
-  json_t *j_fake_contract;
-  json_t *j_details;
-  json_t *j_exchanges;
-  json_t *j_item;
-  json_t *j_amount;
-  json_t *j_tax_amount;
-  json_t *j_item_price;
-  json_t *j_max_fee;
-  json_t *j_teatax;
-  json_t *j_id; // trans id
-  json_t *j_pid; // product id
-  json_t *j_quantity;
-  json_t *j_delloc;
-  json_t *j_merchant;
-  json_t *j_merchant_jurisdiction;
-  json_t *j_merchant_zipcode;
-  json_t *j_lnames;
-  json_t *j_deldate;
-  char *desc;
-  struct TALER_Amount amount;
-  int64_t t_id;
-  int64_t p_id;
-  struct Contract contract;
-  struct GNUNET_TIME_Absolute wire_transfer_deadline;
-  struct GNUNET_TIME_Absolute now;
-  uint64_t nounce;
-  struct GNUNET_HashCode h_contract_str;
-  char *aa;
-  const char *fancy_time;
-  uint32_t ret;
-
-  db_conn = NULL;
-  keyfile = NULL;
-  privkey = NULL;
-  wire = NULL;
-
-
-  db_conn = TALER_MERCHANTDB_connect (config);
-  if (GNUNET_OK != TALER_MERCHANTDB_initialize (db_conn, GNUNET_NO))
-  {
-    printf ("no db init'd\n");
-    result = GNUNET_SYSERR;
-  }
-  if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_filename (config,
-                                                            "merchant",
-                                                            "KEYFILE",
-                                                            &keyfile))
-  {
-    printf ("no keyfile entry in cfg file\n");
-    result = GNUNET_SYSERR;
-  }
-
-  privkey = GNUNET_CRYPTO_eddsa_key_create_from_file (keyfile);
-  wire = TALER_MERCHANT_parse_wireformat_sepa (config);
-  GNUNET_SCHEDULER_add_shutdown (&do_shutdown, NULL);
-
-  /**
-  * 'Root' object of the contract, leaving some holes to bi filled
-  * up by the merchant library.
-  *
-  */
-
-  /* Amount */
-  TALER_amount_get_zero ("EUR", &amount);
-  j_amount = TALER_json_from_amount (&amount);
-
-  /* Transaction ID*/
-  //t_id = (int32_t) GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_WEAK, 
UINT64_MAX);
-  t_id = 321;
-
-  if (t_id < 0)
-     j_id = json_integer ((-1) * t_id);
-  else
-     j_id = json_integer (t_id);
-
-  /**
-  * Holes:
-  *
-  * - 'h_wire'
-  * - 'timestamp'
-  *
-  */
-
-  /**
-  *
-  * Preparing the 'details' sub-object: an array of 'item' objects
-  * plus some juridical and delivery-aware informations
-  *
-  */
-
-  /**
-  *
-  * Preparing a 'item' sub-object
-  */
-
-  /* Description */
-  desc = "Fake purchase";
-
-  j_max_fee = TALER_json_from_amount (&amount);
-  /* Quantity: OPTIONAL FIELD */
-  j_quantity = json_integer (3);
-
-  /* item price: OPTIONAL FIELD*/
-  j_item_price = TALER_json_from_amount (&amount);
-
-  /* Product ID */
-  p_id = (int32_t) GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_WEAK, 
UINT64_MAX);
-
-  if (p_id < 0)
-     j_pid = json_integer ((-1) * p_id);
-  else
-     j_pid = json_integer (p_id);
-
-  /* Taxes: array of "tax_name" : {tax amount} */
-  j_tax_amount = TALER_json_from_amount (&amount);
-  j_teatax = json_pack ("{s:o}",
-                        "teatax", j_tax_amount);
-
-  if (NULL == (j_item = json_pack ("{s:s, s:I, s:o, s:[o]}",
-                      "description", desc,
-                     "quantity", json_integer_value (j_quantity),
-                     "itemprice", j_item_price,
-                     "taxes", j_teatax)))
-  {
-    printf ("error in packing [j_item: %p]\n", j_item);
-    return;
-  }
-
-  /* End of 'item' object definition */
-
-  /* Delivery date: OPTIONAL FIELD */
-  now = GNUNET_TIME_absolute_get ();
-  TALER_round_abs_time (&now);
-//  deldate = GNUNET_TIME_absolute_add (now, GNUNET_TIME_UNIT_WEEKS);
-  j_deldate = TALER_json_from_abs (now);
-
-  /* Delivery location: OPTIONAL FIELD */
-  j_delloc = json_string ("MALTK"); /* just a 'tag' which points to some well 
defined location */
-
-
-  /* Merchant jurisdiction: OPTIONAL FIELD (with its fields from 3rd to the 
last being optional)
-  * for another optional field */
-  j_merchant_zipcode = json_integer (9468);
-  j_merchant_jurisdiction = json_pack ("{s:s, s:s, s:s, s:s, s:s, s:I}",
-                                       "country", "Test Country",
-                                      "city", "Test City",
-                                      "state", "NA",
-                                      "region", "NA",
-                                      "province", "NA",
-                                      "ZIP code", json_integer_value 
(j_merchant_zipcode));
-
-  /* Merchant details */
-  j_merchant = json_pack ("{s:s, s:s, s:o}",
-                          "address", "UALMP",
-                         "name", "test merchant",
-                         "jurisdiction", j_merchant_jurisdiction);
-
-
-  /* L-names mapping */
-  j_lnames = json_pack ("[{s:s}, {s:s}]",
-                        "MALTK", "Test Address 1",
-                       "UALMP", "Second Test Address");
-
-
-
-  j_details = json_pack ("{s:I, s:o, s:o, s:o, s:o, s:o}",
-                        "product_id", json_integer_value (j_pid),
-                         "items", j_item,
-                        "delivery date", j_deldate,
-                        "delivery location", j_delloc,
-                        "merchant", j_merchant,
-                        "L-names", j_lnames);
-
-  /* Faking out the exchanges' list */
-  j_exchanges = json_pack ("[{s:s}]",
-                       "demo.taler.net",
-                      "Q1WVGRGC1F4W7RYC6M23AEGFEXQEHQ730K3GG0B67VPHQSRR75H0");
-
-  j_fake_contract = json_pack ("{s:o, s:o, s:I, s:o, s:o}",
-                               "amount", j_amount,
-                               "max fee", j_max_fee,
-                              "trans_id", json_integer_value (j_id),
-                              "exchanges", j_exchanges,
-                              "details", j_details);
-  #if 0
-  str = json_dumps (j_fake_contract, JSON_INDENT(2) | JSON_PRESERVE_ORDER);
-  printf ("%s\n", str);
-  return;
-  #endif
-
-  nounce = GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_NONCE, UINT64_MAX);
-
-  ret = MERCHANT_handle_contract (j_fake_contract,
-                                  db_conn,
-                                  &contract,
-                                 now,
-                                 now,
-                                 now,
-                                 now,
-                                 &aa,
-                                 nounce);
-  if (ret == GNUNET_NO)
-  {
-    printf ("Failed, contract already in DB\n");
-    return;
-  }
-  else
-    printf ("handling contract fine\n");
-
-
-  printf ("contract string : %s\n", aa);
-
-  GNUNET_CRYPTO_hash (aa, strlen (aa) + 1, &h_contract_str);
-  if (GNUNET_SYSERR ==
-      TALER_MERCHANTDB_contract_get_values (db_conn,
-                                            &h_contract_str,
-                                            &nounce,
-                                            &wire_transfer_deadline))
-  {
-    printf ("no hash found\n");
-  }
-  else
-  {
-
-    fancy_time = GNUNET_STRINGS_absolute_time_to_string 
(wire_transfer_deadline);
-    printf ("hash found!, nounce is : %llu\n", nounce);
-    printf ("hash found!, wire transfer time is : %s\n", fancy_time);
-  }
-}
-
-
-/**
- * The main function of the test tool
- *
- * @param argc number of arguments from the command line
- * @param argv command line arguments
- * @return 0 ok, 1 on error
- */
-int
-main (int argc, char *const *argv)
-{
-
-  static const struct GNUNET_GETOPT_CommandLineOption options[] = {
-    {'t', "temp", NULL,
-     gettext_noop ("Use temporary database tables"), GNUNET_NO,
-     &GNUNET_GETOPT_set_one, &dry},
-     GNUNET_GETOPT_OPTION_END
-    };
-
-
-  if (GNUNET_OK !=
-      GNUNET_PROGRAM_run (argc, argv,
-                          "merchant-contract-test",
-                          "Test for contracts mgmt",
-                          options, &run, NULL))
-    return 3;
-  return (GNUNET_OK == result) ? 0 : 1;
-}
diff --git a/src/tests/test_contract_README b/src/tests/test_contract_README
deleted file mode 100644
index 9fd337c..0000000
--- a/src/tests/test_contract_README
+++ /dev/null
@@ -1,10 +0,0 @@
-- In order to test the "/contract" facility of the merchant,
-  just issue
-
-  - curl http://merchant-url/generate_taler_contract.php?cli_debug=yes
-    (this form tests the whole communication between frontend and backend)
-
-  - curl http://merchant-url/generate_taler_contract.php?backend_test=no
-    (this form test only the contract proposition generation of the frontend,
-     so it doesn't further connect to the backend to get the proposition JSON
-     enhanced)
diff --git a/src/tests/test_pay_README b/src/tests/test_pay_README
deleted file mode 100644
index 1704d6b..0000000
--- a/src/tests/test_pay_README
+++ /dev/null
@@ -1,26 +0,0 @@
-The merchant's "/pay" facility can be tested either directly by querying the
-backend or by querying the frontend (which in turn will query the backend).
-Each file *.sample is sample JSON to POST to both components (with the 
'_backend'
-named version being dedicated to just the backend).
-
-Note: the sample 'deposit_permission_edate_backend.sample' contains the 
optional
-'edate' field to the deposit permission (that field indicates the tollerated 
delay
-by this merchant to receive funds relative to this payment)
-
-The frontend test admits two versions of queries, as in the following examples:
-
-  * curl -H 'Content-type: application/json' address@hidden \
-    http://merchant-url/pay.php?cli_debug=yes
-
-    (this form tests the whole communication between frontend and backend)
-
-  * curl address@hidden http://merchant-url/pay.php?backend_test=no
-
-    (this form tests only the deposit permission enhancement made by the
-    frontend, so it doesn't further connect to the backend to actually POST
-    that data. By default, the frontend doesn't add the 'edate' field, so it
-    is necessary to uncomment the related line of code to test this feature)
-
-Finally, to POST to the backend, issue
-  * curl -H 'Content-type: application/json' address@hidden 
http://backend-url/pay
- 

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



reply via email to

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