summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--_static/sample-pos-config.json2
-rw-r--r--checklist-demo-upgrade.rst56
-rw-r--r--checklist-release.rst176
-rw-r--r--conf.py638
-rw-r--r--core/api-bank-access.rst21
-rw-r--r--core/api-common.rst49
-rw-r--r--core/api-exchange.rst409
-rw-r--r--core/api-mailbox.rst47
-rw-r--r--core/api-merchant.rst447
-rw-r--r--core/api-sync.rst19
-rw-r--r--core/api-taldir.rst42
-rw-r--r--core/api-wire.rst2
-rw-r--r--core/taler-uri.rst13
-rw-r--r--core/tos.rst42
-rw-r--r--demo-deployment.rst46
-rw-r--r--design-documents/006-extensions.rst36
-rw-r--r--design-documents/024-age-restriction.rst2
-rw-r--r--design-documents/028-deposit-policies.rst188
-rw-r--r--design-documents/028-proof-of-escrow.rst128
-rw-r--r--design-documents/032-brandt-vickrey-auctions.rst (renamed from design-documents/032-auctions.rst)116
-rw-r--r--design-documents/033-database.rst152
-rw-r--r--design-documents/index.rst4
-rw-r--r--extract-tsdefs/.gitignore3
-rw-r--r--extract-tsdefs/README.md8
-rw-r--r--extract-tsdefs/extract.ts341
-rw-r--r--extract-tsdefs/myout.md2517
-rw-r--r--extract-tsdefs/package.json19
-rw-r--r--extract-tsdefs/pnpm-lock.yaml35
-rw-r--r--extract-tsdefs/tsconfig.json103
-rw-r--r--frags/using-taler-config.rst6
-rw-r--r--index.rst1
-rw-r--r--libeufin/api-sandbox-future.rst135
-rw-r--r--libeufin/api-sandbox.rst705
-rw-r--r--manpages/taler-exchange-offline.1.rst8
-rw-r--r--manpages/taler-helper-auditor-purses.1.rst75
-rw-r--r--manpages/taler-merchant-httpd.1.rst5
-rw-r--r--manpages/taler.conf.5.rst4
-rw-r--r--taler-developer-manual.rst235
-rw-r--r--taler-exchange-manual.rst5
-rw-r--r--taler-wallet.rst947
-rw-r--r--wallet/wallet-core.md3124
41 files changed, 8918 insertions, 1993 deletions
diff --git a/_static/sample-pos-config.json b/_static/sample-pos-config.json
index f078910..db4dca6 100644
--- a/_static/sample-pos-config.json
+++ b/_static/sample-pos-config.json
@@ -1,7 +1,7 @@
{
"config": {
"base_url": "https://backend.demo.taler.net/instances/pos",
- "api_key": "sandbox"
+ "api_key": "secret-token:sandbox"
},
"categories": [
{
diff --git a/checklist-demo-upgrade.rst b/checklist-demo-upgrade.rst
index 5eb0051..7ff892f 100644
--- a/checklist-demo-upgrade.rst
+++ b/checklist-demo-upgrade.rst
@@ -8,7 +8,6 @@ GNU Taler Demo Upgrade Checklist
Post-upgrade checks:
-- |check| Run ``taler-deployment-arm -I`` to verify that all services are running.
- |check| Run the headless wallet to check that services are actually working:
.. code-block:: console
@@ -23,15 +22,25 @@ Post-upgrade checks:
Basics:
- |check| Visit https://demo.taler.net/ to see if the landing page is displayed correctly
+- |check| landing language switcher
- |check| Visit the wallet installation page, install the wallet, and see if the presence
indicator is updated correctly.
-- |check| Visit https://bank.demo.taler.net/, register a new user and withdraw coins into the
- browser wallet.
+- |check| Visit https://bank.demo.taler.net/, register a new user
+- |check| bank language switcher
+- |check| bank logout
+- |check| bank login
+- |check| bank-integrated withdraw process, abort in bank
+- |check| transaction history: delete pending withdraw
+- |check| do bank-integrated withdraw process (5 KUDOS)
+- |check| do wallet-initiated withdraw process (5 KUDOS)
+- |check| withdraw process of large amount (20 KUDOS) runs into KYC check
Blog demo:
-- |check| Visit https://shop.demo.taler.net/ and purchase an article.
+- |check| Visit https://shop.demo.taler.net/
+- |check| blog page article list renders
+- |check| payment for blog article
- |check| Verify that the balance in the wallet was updated correctly.
- |check| Go back to https://shop.demo.taler.net/ and click on the same article
link. Verify that the article is shown and **no** repeated payment is
@@ -41,16 +50,53 @@ Blog demo:
- |check| Delete cookies on https://shop.demo.taler.net/ and click on the same article again.
Verify that the wallet detects that the article has already purchased and successfully
redirects to the article without spending more money.
+- |check| payment for other blog article
+- |check| refund of 2nd blog article (button at the end)
+- |check| wallet transaction history rendering
+- |check| delete history entry
Donation demo:
-- |check| Make a donation on https://donations.demo.taler.net
+- |check| Reset wallet
+- |check| Withdraw age-restricted coins (< 14)
+- |check| Try to make a donation on https://donations.demo.taler.net/, fail due to age-restriction
+- |check| Withdraw age-restricted coins (>= 14)
+- |check| Make a donation on https://donations.demo.taler.net/
- |check| Make another donation with the same parameters and verify
that the payment is requested again, instead of showing the previous
fulfillment page.
+Merchant SPA:
+
+- |check| test SPA loads
+- |check| try to login with wrong password
+- |check| try to login with correct password
+- |check| create instance
+- |check| modify instance
+- |check| add product
+- |check| add order with inventory product
+- |check| pay for order with wallet
+- |check| trigger refund
+- |check| accept refund with wallet
+- |check| TBD: tipping
+- |check| TBD: products with previews
+- |check| TBD: inventory management
+- |check| TBD: adding transactions
+- |check| TBD: test various settings
+- |check| TBD: ...
+
Survey/Tipping:
- |check| Visit https://survey.demo.taler.net/ and receive a tip.
- |check| Verify that the survey stats page (https://survey.demo.taler.net/survey-stats) is working,
and that the survey reserve has sufficient funds.
+
+P2P payments:
+
+- |check| generating push payment (to self is OK)
+- |check| accepting push payment (from self is OK)
+- |check| generating pull payment (to self is OK)
+- |check| accepting pull payment (from self is OK)
+- |check| sending money back from wallet to bank account
+- |check| wallet transaction history rendering
+- |check| delete history entry
diff --git a/checklist-release.rst b/checklist-release.rst
index 90ca6cb..33bfd61 100644
--- a/checklist-release.rst
+++ b/checklist-release.rst
@@ -1,70 +1,142 @@
-###########################
-GNU Taler Release Checklist
-###########################
+############################
+GNU Taler Release Checklists
+############################
+.. |check| raw:: html
-Release checklists for GNU Taler:
-
-Wallet:
-
-- [ ] build wallet
-- [ ] verify wallet works against 'test.taler.net'
-- [ ] tag repo.
-- [ ] upgrade 'demo.taler.net' to 'test.taler.net'
-- [ ] upload new wallet release to app store
-- [ ] Update bug tracker (mark release, resolved -> closed)
-- [ ] Send announcement to taler@gnu.org
-- [ ] Send announcement to info-gnu@gnu.org (major releases only)
-- [ ] Send announcement to coordinator@translationproject.org
+ <input type="checkbox">
For exchange:
-- [ ] check no compiler warnings at "-Wall"
-- [ ] ensure Coverity static analysis passes
-- [ ] make check.
-- [ ] upgrade 'demo.taler.net' to 'test.taler.net'
-- [ ] make dist, make check on result of 'make dist'.
-- [ ] Change version number in configure.ac.
-- [ ] make dist for release.
-- [ ] tag repo.
-- [ ] Upload triplet to ftp-upload.gnu.org/incoming/ftp or /incoming/alpha
-- [ ] Update bug tracker (mark release, resolved -> closed)
-- [ ] Send announcement to taler@gnu.org
-- [ ] Send announcement to info-gnu@gnu.org (major releases only)
-- [ ] Send announcement to coordinator@translationproject.org
+- |check| no compiler warnings at "-Wall" with gcc
+- |check| no compiler warnings at "-Wall" with clang
+- |check| ensure Coverity static analysis passes
+- |check| make check.
+- |check| make dist, make check on result of 'make dist'.
+- |check| Change version number in configure.ac.
+- |check| update man pages / info page documentation (prebuilt branch)
+- |check| make dist for release
+- |check| verify dist builds from source
+- |check| upgrade 'demo.taler.net'
+- |check| run :doc:`demo upgrade checklist <checklist-demo-upgrade>`
+- |check| tag repo.
+- |check| use deployment.git/packaging/*-docker/ to build Debian and Ubuntu packages
+- |check| upload packages to deb.taler.net/ (note: only Florian/Christian can sign)
+- |check| change 'demo.taler.net' deployment to use new tag.
+- |check| Upload triplet to ftp-upload.gnu.org/incoming/ftp or /incoming/alpha
For merchant (C backend):
-- [ ] check no compiler warnings at "-Wall"
-- [ ] ensure Coverity static analysis passes
-- [ ] make check.
-- [ ] upgrade 'demo.taler.net' to 'test.taler.net'
-- [ ] make dist, make check on result of 'make dist'.
-- [ ] Change version number in configure.ac.
-- [ ] make dist for release.
-- [ ] tag repo.
-- [ ] Upload triplet to ftp-upload.gnu.org/incoming/ftp or /incoming/alpha
-- [ ] Update bug tracker (mark release, resolved -> closed)
-- [ ] Send announcement to taler@gnu.org
-- [ ] Send announcement to info-gnu@gnu.org (major releases only)
-- [ ] Send announcement to coordinator@translationproject.org
+- |check| no compiler warnings at "-Wall" with gcc
+- |check| no compiler warnings at "-Wall" with clang
+- |check| ensure Coverity static analysis passes
+- |check| make check.
+- |check| make dist, make check on result of 'make dist'.
+- |check| update SPA (prebuilt branch)
+- |check| Change version number in configure.ac.
+- |check| make dist for release.
+- |check| verify dist builds from source
+- |check| upgrade 'demo.taler.net'
+- |check| run :doc:`demo upgrade checklist <checklist-demo-upgrade>`
+- |check| tag repo.
+- |check| use deployment.git/packaging/*-docker/ to build Debian and Ubuntu packages
+- |check| upload packages to deb.taler.net/ (note: only Florian/Christian can sign)
+- |check| change 'demo.taler.net' deployment to use new tag.
+- |check| Upload triplet to ftp-upload.gnu.org/incoming/ftp or /incoming/alpha
+
+For sync:
+
+- |check| no compiler warnings at "-Wall" with gcc
+- |check| no compiler warnings at "-Wall" with clang
+- |check| ensure Coverity static analysis passes
+- |check| make check.
+- |check| make dist, make check on result of 'make dist'.
+- |check| Change version number in configure.ac.
+- |check| make dist for release
+- |check| verify dist builds from source
+- |check| upgrade 'demo.taler.net'
+- |check| run :doc:`demo upgrade checklist <checklist-demo-upgrade>`
+- |check| tag repo.
+- |check| use deployment.git/packaging/*-docker/ to build Debian and Ubuntu packages
+- |check| upload packages to deb.taler.net/ (note: only Florian/Christian can sign)
+- |check| change 'demo.taler.net' deployment to use new tag.
+- |check| Upload triplet to ftp-upload.gnu.org/incoming/ftp or /incoming/alpha
+
+For taler-mdb:
+
+- |check| no compiler warnings at "-Wall" with gcc
+- |check| ensure Coverity static analysis passes
+- |check| Change version number in configure.ac.
+- |check| make dist for release.
+- |check| tag repo.
+- |check| use deployment.git/packaging/*-docker/ to build Debian and Ubuntu packages
+- |check| upload packages to deb.taler.net/ (note: only Florian/Christian can sign)
+- |check| Upload triplet to ftp-upload.gnu.org/incoming/ftp or /incoming/alpha
+
+For taler-twister:
+
+- |check| no compiler warnings at "-Wall" with gcc
+- |check| no compiler warnings at "-Wall" with clang
+- |check| ensure Coverity static analysis passes
+- |check| make check.
+- |check| make dist, make check on result of 'make dist'.
+- |check| Change version number in configure.ac.
+- |check| make dist for release.
+- |check| verify dist builds from source
+- |check| upgrade 'demo.taler.net'
+- |check| run :doc:`demo upgrade checklist <checklist-demo-upgrade>`
+- |check| tag repo.
+- |check| Upload triplet to ftp-upload.gnu.org/incoming/ftp or /incoming/alpha
+
+For libeufin:
+
+- |check| update SPA of bank
+- |check| build libeufin
+- |check| upgrade 'demo.taler.net'
+- |check| run :doc:`demo upgrade checklist <checklist-demo-upgrade>`
+- |check| make dist for release.
+- |check| verify dist builds from source
+- |check| tag repo.
+- |check| use deployment.git/packaging/*-docker/ to build Debian and Ubuntu packages
+- |check| upload packages to deb.taler.net/ (note: only Florian/Christian can sign)
+- |check| change 'demo.taler.net' deployment to use new tag.
+- |check| Upload triplet to ftp-upload.gnu.org/incoming/ftp or /incoming/alpha
-For bank:
+For Python merchant frontend:
-- TBD
+- |check| upgrade 'demo.taler.net'
+- |check| run :doc:`demo upgrade checklist <checklist-demo-upgrade>`
+- |check| change 'demo.taler.net' deployment to use new tag.
-For Python merchant frontend:
+Wallet-core:
-- TBD
+- |check| build wallet
+- |check| run integration test
+- |check| make dist for release.
+- |check| verify dist builds from source
+- |check| tag repo.
+- |check| use deployment.git/packaging/*-docker/ to build Debian and Ubuntu packages
+- |check| upload packages to deb.taler.net/ (note: only Florian/Christian can sign)
+- |check| change 'demo.taler.net' deployment to use new tag.
+- |check| Upload triplet to ftp-upload.gnu.org/incoming/ftp or /incoming/alpha
-For PHP merchant frontend:
+Android-Wallet:
-- TBD
+- |check| build wallet
+- |check| run :doc:`demo upgrade checklist <checklist-demo-upgrade>`
+- |check| tag repo.
+- |check| upload new wallet release to app store
-For auditor:
+Webextension-Wallet:
-- TBD
+- |check| build wallet
+- |check| run :doc:`demo upgrade checklist <checklist-demo-upgrade>`
+- |check| tag repo.
+- |check| upload new wallet release to app store
-For libebics:
+Release announcement:
-- TBD
+- |check| Update bug tracker (mark release, resolved -> closed)
+- |check| Send announcement to taler@gnu.org
+- |check| Send announcement to info-gnu@gnu.org (major releases only)
+- |check| Send announcement to coordinator@translationproject.org
diff --git a/conf.py b/conf.py
index a2fa348..b4e2927 100644
--- a/conf.py
+++ b/conf.py
@@ -35,61 +35,61 @@
import sys
import os
-sys.path.append(os.path.abspath('_exts'))
+sys.path.append(os.path.abspath("_exts"))
import taler_sphinx_theme
# If extensions (or modules to document with autodoc) are in another directory,
# add these directories to sys.path here. If the directory is relative to the
# documentation root, use os.path.abspath to make it absolute, like shown here.
-#sys.path.insert(0, os.path.abspath('.'))
+# sys.path.insert(0, os.path.abspath('.'))
# -- General configuration ------------------------------------------------
# If your documentation needs a minimal Sphinx version, state it here.
-needs_sphinx = '2.2.0'
+needs_sphinx = "2.2.0"
# Add any Sphinx extension module names here, as strings. They can be
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
# ones.
extensions = [
- 'ebicsdomain',
- 'typescriptdomain',
- 'taler_sphinx_theme',
- 'sphinx.ext.todo',
- 'sphinx.ext.imgmath',
- 'httpdomain.httpdomain',
- 'recommonmark',
- 'sphinx.ext.graphviz',
+ "ebicsdomain",
+ "typescriptdomain",
+ "taler_sphinx_theme",
+ "sphinx.ext.todo",
+ "sphinx.ext.imgmath",
+ "httpdomain.httpdomain",
+ "recommonmark",
+ "sphinx.ext.graphviz",
]
# Add any paths that contain templates here, relative to this directory.
-templates_path = ['_templates']
+templates_path = ["_templates"]
source_suffix = {
- '.rst': 'restructuredtext',
- '.txt': 'markdown',
- '.md': 'markdown',
+ ".rst": "restructuredtext",
+ ".txt": "markdown",
+ ".md": "markdown",
}
# The encoding of source files.
-#source_encoding = 'utf-8-sig'
+# source_encoding = 'utf-8-sig'
# The master toctree document.
-master_doc = 'index'
+master_doc = "index"
# General information about the project.
-project = u'GNU Taler'
-copyright = u'2014-2022 Taler Systems SA (GPLv3+ or GFDL 1.3+)'
+project = "GNU Taler"
+copyright = "2014-2022 Taler Systems SA (GPLv3+ or GFDL 1.3+)"
# The version info for the project you're documenting, acts as replacement for
# |version| and |release|, also used in various other places throughout the
# built documents.
#
# The short X.Y version.
-version = '0.9'
+version = "0.9"
# The full version, including alpha/beta/rc tags.
-release = '0.9.0'
+release = "0.9.0"
# The language for content autogenerated by Sphinx. Refer to documentation
# for a list of supported languages.
@@ -97,46 +97,53 @@ release = '0.9.0'
# There are two options for replacing |today|: either, you set today to some
# non-false value, then it is used:
-#today = ''
+# today = ''
# Else, today_fmt is used as the format for a strftime call.
-#today_fmt = '%B %d, %Y'
+# today_fmt = '%B %d, %Y'
# List of patterns, relative to source directory, that match files and
# directories to ignore when looking for source files.
-exclude_patterns = ['_build', '_exts', 'cf', 'prebuilt', '**/README.md']
+exclude_patterns = [
+ "_build",
+ "_exts",
+ "cf",
+ "prebuilt",
+ "**/README.md",
+ "extract-tsdefs",
+]
# The reST default role (used for this markup: `text`) to use for all
# documents.
default_role = "ts:type"
# If true, '()' will be appended to :func: etc. cross-reference text.
-#add_function_parentheses = True
+# add_function_parentheses = True
# If true, the current module name will be prepended to all description
# unit titles (such as .. function::).
-#add_module_names = True
+# add_module_names = True
# If true, sectionauthor and moduleauthor directives will be shown in the
# output. They are ignored by default.
-#show_authors = False
+# show_authors = False
# The name of the Pygments (syntax highlighting) style to use.
-pygments_style = 'sphinx'
+pygments_style = "sphinx"
# A list of ignored prefixes for module index sorting.
-#modindex_common_prefix = []
+# modindex_common_prefix = []
# If true, keep warnings as "system message" paragraphs in the built documents.
-#keep_warnings = False
+# keep_warnings = False
# -- Options for HTML output ----------------------------------------------
# The theme to use for HTML and HTML Help pages. See the documentation for
# a list of builtin themes.
-html_theme = 'taler_sphinx_theme'
+html_theme = "taler_sphinx_theme"
html_theme_path = taler_sphinx_theme.html_theme_path()
-html_sidebars = {'**': ['logo-text.html', 'globaltoc.html', 'searchbox.html']}
+html_sidebars = {"**": ["logo-text.html", "globaltoc.html", "searchbox.html"]}
html_theme_options = {
# Set the name of the project to appear in the sidebar
@@ -146,84 +153,82 @@ html_theme_options = {
}
# Add any paths that contain custom themes here, relative to this directory.
-#html_theme_path = []
+# html_theme_path = []
# The name for this set of Sphinx documents. If None, it defaults to
# "<project> v<release> documentation".
-#html_title = None
+# html_title = None
# A shorter title for the navigation bar. Default is the same as html_title.
-#html_short_title = None
+# html_short_title = None
# The name of an image file (relative to this directory) to place at the top
# of the sidebar.
-#html_logo = None
+# html_logo = None
# The name of an image file (within the static path) to use as favicon of the
# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32
# pixels large.
-#html_favicon = None
+# html_favicon = None
# Add any paths that contain custom static files (such as style sheets) here,
# relative to this directory. They are copied after the builtin static files,
# so a file named "default.css" will overwrite the builtin "default.css".
-html_static_path = ['_static']
+html_static_path = ["_static"]
# Add any extra paths that contain custom files (such as robots.txt or
# .htaccess) here, relative to this directory. These files are copied
# directly to the root of the documentation.
-#html_extra_path = []
+# html_extra_path = []
# If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
# using the given strftime format.
-#html_last_updated_fmt = '%b %d, %Y'
+# html_last_updated_fmt = '%b %d, %Y'
# If true, SmartyPants will be used to convert quotes and dashes to
# typographically correct entities.
-#html_use_smartypants = True
+# html_use_smartypants = True
# Custom sidebar templates, maps document names to template names.
-#html_sidebars = {}
+# html_sidebars = {}
# Additional templates that should be rendered to pages, maps page names to
# template names.
-#html_additional_pages = {}
+# html_additional_pages = {}
# If false, no module index is generated.
-#html_domain_indices = True
+# html_domain_indices = True
# If false, no index is generated.
-#html_use_index = True
+# html_use_index = True
# If true, the index is split into individual pages for each letter.
-#html_split_index = False
+# html_split_index = False
# If true, links to the reST sources are added to the pages.
-#html_show_sourcelink = True
+# html_show_sourcelink = True
# If true, "Created using Sphinx" is shown in the HTML footer. Default is True.
html_show_sphinx = False
# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True.
-#html_show_copyright = True
+# html_show_copyright = True
# If true, an OpenSearch description file will be output, and all pages will
# contain a <link> tag referring to it. The value of this option must be the
# base URL from which the finished HTML is served.
-#html_use_opensearch = ''
+# html_use_opensearch = ''
# This is the file name suffix for HTML files (e.g. ".xhtml").
-#html_file_suffix = None
+# html_file_suffix = None
# -- Options for LaTeX output ---------------------------------------------
latex_elements = {
# The paper size ('letterpaper' or 'a4paper').
#'papersize': 'letterpaper',
-
# The font size ('10pt', '11pt' or '12pt').
#'pointsize': '10pt',
-
# Additional stuff for the LaTeX preamble.
#'preamble': '',
}
@@ -232,148 +237,359 @@ latex_elements = {
# (source start file, target name, title,
# author, documentclass [howto, manual, or own class]).
latex_documents = [
- ('taler-auditor-manual', 'taler-auditor-manual.tex',
- 'GNU Taler Auditor Manual', 'GNU Taler team', 'manual'),
- ('taler-exchange-manual', 'taler-exchange-manual.tex',
- 'GNU Taler Exchange Manual', 'GNU Taler team', 'manual'),
- ('taler-merchant-manual', 'taler-merchant-manual.tex',
- 'GNU Taler Merchant Manual', 'GNU Taler team', 'manual'),
- ('taler-merchant-pos-terminal', 'taler-merchant-pos-terminal.tex',
- 'GNU Taler Merchant POS Terminal', 'GNU Taler team', 'manual'),
- ('taler-merchant-api-tutorial', 'taler-merchant-api-tutorial.tex',
- 'GNU Taler Merchant API Tutorial', 'GNU Taler team', 'manual'),
- ('taler-developer-manual', 'taler-developer-manual.tex', 'GNU Taler Developer Manual',
- 'GNU Taler team', 'manual'),
+ (
+ "taler-auditor-manual",
+ "taler-auditor-manual.tex",
+ "GNU Taler Auditor Manual",
+ "GNU Taler team",
+ "manual",
+ ),
+ (
+ "taler-exchange-manual",
+ "taler-exchange-manual.tex",
+ "GNU Taler Exchange Manual",
+ "GNU Taler team",
+ "manual",
+ ),
+ (
+ "taler-merchant-manual",
+ "taler-merchant-manual.tex",
+ "GNU Taler Merchant Manual",
+ "GNU Taler team",
+ "manual",
+ ),
+ (
+ "taler-merchant-pos-terminal",
+ "taler-merchant-pos-terminal.tex",
+ "GNU Taler Merchant POS Terminal",
+ "GNU Taler team",
+ "manual",
+ ),
+ (
+ "taler-merchant-api-tutorial",
+ "taler-merchant-api-tutorial.tex",
+ "GNU Taler Merchant API Tutorial",
+ "GNU Taler team",
+ "manual",
+ ),
+ (
+ "taler-developer-manual",
+ "taler-developer-manual.tex",
+ "GNU Taler Developer Manual",
+ "GNU Taler team",
+ "manual",
+ ),
]
# The name of an image file (relative to this directory) to place at the top of
# the title page.
-#latex_logo = None
+# latex_logo = None
# For "manual" documents, if this is true, then toplevel headings are parts,
# not chapters.
-#latex_use_parts = False
+# latex_use_parts = False
# If true, show page references after internal links.
-#latex_show_pagerefs = False
+# latex_show_pagerefs = False
# If true, show URL addresses after external links.
-#latex_show_urls = False
+# latex_show_urls = False
# Documents to append as an appendix to all manuals.
latex_appendices = ["fdl-1.3"]
# If false, no module index is generated.
-#latex_domain_indices = True
+# latex_domain_indices = True
# -- Options for manual page output ---------------------------------------
# One entry per manual page. List of tuples
# (source start file, name, description, authors, manual section).
man_pages = [
- ("manpages/sync-config.1", "sync-config",
- "manipulate Sync configuration files", "GNU Taler contributors", 1),
- ("manpages/sync-dbinit.1", "sync-dbinit",
- "initialize the Sync database", "GNU Taler contributors", 1),
- ("manpages/sync-httpd.1", "sync-httpd",
- "provide the Sync HTTP interface", "GNU Taler contributors", 1),
- ("manpages/sync.conf.5", "sync.conf",
- "Sync configuration file", "GNU Taler contributors", 5),
- ("manpages/taler-auditor-exchange.1", "taler-auditor-exchange",
- "add or remove exchange from auditor’s list", "GNU Taler contributors",
- 1),
- ("manpages/taler-auditor-dbinit.1", "taler-auditor-dbinit",
- "setup auditor database", "GNU Taler contributors", 1),
- ("manpages/taler-auditor-sync.1", "taler-auditor-sync",
- "tool to safely synchronize auditor database", "GNU Taler contributors", 1),
- ("manpages/taler-auditor-httpd.1", "taler-auditor-httpd",
- "HTTP server providing a RESTful API to access a Taler auditor",
- "GNU Taler contributors", 1),
- ("manpages/taler-auditor.1", "taler-auditor", "audit exchange",
- "GNU Taler contributors", 1),
- ("manpages/taler-exchange-aggregator.1", "taler-exchange-aggregator",
- "aggregate deposits into wire transfers", "GNU Taler contributors",
- 1),
- ("manpages/taler-exchange-closer.1", "taler-exchange-closer",
- "close idle reserves", "GNU Taler contributors",
- 1),
- ("manpages/taler-exchange-drain.1", "taler-exchange-drain",
- "drain profits from exchange", "GNU Taler contributors",
- 1),
- ("manpages/taler-exchange-kyc-tester.1", "taler-exchange-kyc-tester",
- "test KYC service integration", "GNU Taler contributors",
- 1),
- ("manpages/taler-exchange-expire.1", "taler-exchange-expire",
- "refund expired purses", "GNU Taler contributors",
- 1),
- ("manpages/taler-exchange-router.1", "taler-exchange-router",
- "route payments to partner exchanges", "GNU Taler contributors",
- 1),
- ("manpages/taler-exchange-transfer.1", "taler-exchange-transfer",
- "execute wire transfers", "GNU Taler contributors",
- 1),
- ("manpages/taler-exchange-benchmark.1", "taler-exchange-benchmark",
- "measure exchange performance", "GNU Taler contributors", 1),
- ("manpages/taler-exchange-dbinit.1", "taler-exchange-dbinit",
- "initialize Taler exchange database", "GNU Taler contributors", 1),
- ("manpages/taler-exchange-httpd.1", "taler-exchange-httpd",
- "run Taler exchange (with RESTful API)", "GNU Taler contributors", 1),
- ("manpages/taler-auditor-offline.1", "taler-auditor-offline",
- "Taler auditor certifies that it audits a Taler exchange",
- "GNU Taler contributors", 1),
- ("manpages/taler-exchange-offline.1", "taler-exchange-offline",
- "operations using the offline key of a Taler exchange",
- "GNU Taler contributors", 1),
- ("manpages/taler-exchange-wirewatch.1", "taler-exchange-wirewatch",
- "watch for incoming wire transfers", "GNU Taler contributors", 1),
- ("manpages/taler-merchant-benchmark.1", "taler-merchant-benchmark",
- "generate Taler-style benchmarking payments", "GNU Taler contributors",
- 1),
- ("manpages/taler-merchant-dbinit.1", "taler-merchant-dbinit",
- "initialize Taler merchant database", "GNU Taler contributors", 1),
- ("manpages/taler-merchant-httpd.1", "taler-merchant-httpd",
- "run Taler merchant backend (with RESTful API)", "GNU Taler contributors",
- 1),
- ("manpages/taler-merchant-setup-reserve.1", "taler-merchant-setup-reserve",
- "setup reserve for tipping at a Taler merchant backend", "GNU Taler contributors",
- 1),
- ("manpages/taler-exchange-wire-gateway-client.1", "taler-exchange-wire-gateway-client",
- "trigger a transfer at the bank", "GNU Taler contributors", 1),
- ("manpages/taler-config.1", "taler-config", "Taler configuration inspection and editing",
- "GNU Taler contributors", 1),
- ("manpages/taler.conf.5", "taler.conf", "Taler configuration file",
- "GNU Taler contributors", 5),
- ("manpages/taler-exchange-secmod-eddsa.1", "taler-exchange-secmod-eddsa",
- "handle private EDDSA key operations for a Taler exchange",
- "GNU Taler contributors", 1),
- ("manpages/taler-exchange-secmod-cs.1", "taler-exchange-secmod-cs",
- "handle private CS key operations for a Taler exchange",
- "GNU Taler contributors", 1),
- ("manpages/taler-exchange-secmod-rsa.1", "taler-exchange-secmod-rsa",
- "handle private RSA key operations for a Taler exchange",
- "GNU Taler contributors", 1),
- ("manpages/taler-helper-auditor-aggregation.1", "taler-helper-auditor-aggregation",
- "audit Taler exchange aggregation activity", "GNU Taler contributors", 1),
- ("manpages/taler-helper-auditor-coins.1", "taler-helper-auditor-coins",
- "audit Taler coin processing", "GNU Taler contributors", 1),
- ("manpages/taler-helper-auditor-deposits.1", "taler-helper-auditor-deposits",
- "audit Taler exchange database for deposit confirmation consistency",
- "GNU Taler contributors", 1),
- ("manpages/taler-helper-auditor-reserves.1", "taler-helper-auditor-reserves",
- "audit Taler exchange reserve handling", "GNU Taler contributors", 1),
- ("manpages/taler-helper-auditor-wire.1", "taler-helper-auditor-wire",
- "audit exchange database for consistency with the bank's wire transfers",
- "GNU Taler contributors", 1),
- ("manpages/libeufin-sandbox.1", "libeufin-sandbox",
- "simulate core banking system with EBICS access to bank accounts",
- "GNU Taler contributors", 1),
- ("manpages/libeufin-nexus.1", "libeufin-nexus",
- "service to interface to various bank access APIs",
- "GNU Taler contributors", 1),
+ (
+ "manpages/sync-config.1",
+ "sync-config",
+ "manipulate Sync configuration files",
+ "GNU Taler contributors",
+ 1,
+ ),
+ (
+ "manpages/sync-dbinit.1",
+ "sync-dbinit",
+ "initialize the Sync database",
+ "GNU Taler contributors",
+ 1,
+ ),
+ (
+ "manpages/sync-httpd.1",
+ "sync-httpd",
+ "provide the Sync HTTP interface",
+ "GNU Taler contributors",
+ 1,
+ ),
+ (
+ "manpages/sync.conf.5",
+ "sync.conf",
+ "Sync configuration file",
+ "GNU Taler contributors",
+ 5,
+ ),
+ (
+ "manpages/taler-auditor-exchange.1",
+ "taler-auditor-exchange",
+ "add or remove exchange from auditor’s list",
+ "GNU Taler contributors",
+ 1,
+ ),
+ (
+ "manpages/taler-auditor-dbinit.1",
+ "taler-auditor-dbinit",
+ "setup auditor database",
+ "GNU Taler contributors",
+ 1,
+ ),
+ (
+ "manpages/taler-auditor-sync.1",
+ "taler-auditor-sync",
+ "tool to safely synchronize auditor database",
+ "GNU Taler contributors",
+ 1,
+ ),
+ (
+ "manpages/taler-auditor-httpd.1",
+ "taler-auditor-httpd",
+ "HTTP server providing a RESTful API to access a Taler auditor",
+ "GNU Taler contributors",
+ 1,
+ ),
+ (
+ "manpages/taler-auditor.1",
+ "taler-auditor",
+ "audit exchange",
+ "GNU Taler contributors",
+ 1,
+ ),
+ (
+ "manpages/taler-exchange-aggregator.1",
+ "taler-exchange-aggregator",
+ "aggregate deposits into wire transfers",
+ "GNU Taler contributors",
+ 1,
+ ),
+ (
+ "manpages/taler-exchange-closer.1",
+ "taler-exchange-closer",
+ "close idle reserves",
+ "GNU Taler contributors",
+ 1,
+ ),
+ (
+ "manpages/taler-exchange-drain.1",
+ "taler-exchange-drain",
+ "drain profits from exchange",
+ "GNU Taler contributors",
+ 1,
+ ),
+ (
+ "manpages/taler-exchange-kyc-tester.1",
+ "taler-exchange-kyc-tester",
+ "test KYC service integration",
+ "GNU Taler contributors",
+ 1,
+ ),
+ (
+ "manpages/taler-exchange-expire.1",
+ "taler-exchange-expire",
+ "refund expired purses",
+ "GNU Taler contributors",
+ 1,
+ ),
+ (
+ "manpages/taler-exchange-router.1",
+ "taler-exchange-router",
+ "route payments to partner exchanges",
+ "GNU Taler contributors",
+ 1,
+ ),
+ (
+ "manpages/taler-exchange-transfer.1",
+ "taler-exchange-transfer",
+ "execute wire transfers",
+ "GNU Taler contributors",
+ 1,
+ ),
+ (
+ "manpages/taler-exchange-benchmark.1",
+ "taler-exchange-benchmark",
+ "measure exchange performance",
+ "GNU Taler contributors",
+ 1,
+ ),
+ (
+ "manpages/taler-exchange-dbinit.1",
+ "taler-exchange-dbinit",
+ "initialize Taler exchange database",
+ "GNU Taler contributors",
+ 1,
+ ),
+ (
+ "manpages/taler-exchange-httpd.1",
+ "taler-exchange-httpd",
+ "run Taler exchange (with RESTful API)",
+ "GNU Taler contributors",
+ 1,
+ ),
+ (
+ "manpages/taler-auditor-offline.1",
+ "taler-auditor-offline",
+ "Taler auditor certifies that it audits a Taler exchange",
+ "GNU Taler contributors",
+ 1,
+ ),
+ (
+ "manpages/taler-exchange-offline.1",
+ "taler-exchange-offline",
+ "operations using the offline key of a Taler exchange",
+ "GNU Taler contributors",
+ 1,
+ ),
+ (
+ "manpages/taler-exchange-wirewatch.1",
+ "taler-exchange-wirewatch",
+ "watch for incoming wire transfers",
+ "GNU Taler contributors",
+ 1,
+ ),
+ (
+ "manpages/taler-merchant-benchmark.1",
+ "taler-merchant-benchmark",
+ "generate Taler-style benchmarking payments",
+ "GNU Taler contributors",
+ 1,
+ ),
+ (
+ "manpages/taler-merchant-dbinit.1",
+ "taler-merchant-dbinit",
+ "initialize Taler merchant database",
+ "GNU Taler contributors",
+ 1,
+ ),
+ (
+ "manpages/taler-merchant-httpd.1",
+ "taler-merchant-httpd",
+ "run Taler merchant backend (with RESTful API)",
+ "GNU Taler contributors",
+ 1,
+ ),
+ (
+ "manpages/taler-merchant-setup-reserve.1",
+ "taler-merchant-setup-reserve",
+ "setup reserve for tipping at a Taler merchant backend",
+ "GNU Taler contributors",
+ 1,
+ ),
+ (
+ "manpages/taler-exchange-wire-gateway-client.1",
+ "taler-exchange-wire-gateway-client",
+ "trigger a transfer at the bank",
+ "GNU Taler contributors",
+ 1,
+ ),
+ (
+ "manpages/taler-config.1",
+ "taler-config",
+ "Taler configuration inspection and editing",
+ "GNU Taler contributors",
+ 1,
+ ),
+ (
+ "manpages/taler.conf.5",
+ "taler.conf",
+ "Taler configuration file",
+ "GNU Taler contributors",
+ 5,
+ ),
+ (
+ "manpages/taler-exchange-secmod-eddsa.1",
+ "taler-exchange-secmod-eddsa",
+ "handle private EDDSA key operations for a Taler exchange",
+ "GNU Taler contributors",
+ 1,
+ ),
+ (
+ "manpages/taler-exchange-secmod-cs.1",
+ "taler-exchange-secmod-cs",
+ "handle private CS key operations for a Taler exchange",
+ "GNU Taler contributors",
+ 1,
+ ),
+ (
+ "manpages/taler-exchange-secmod-rsa.1",
+ "taler-exchange-secmod-rsa",
+ "handle private RSA key operations for a Taler exchange",
+ "GNU Taler contributors",
+ 1,
+ ),
+ (
+ "manpages/taler-helper-auditor-aggregation.1",
+ "taler-helper-auditor-aggregation",
+ "audit Taler exchange aggregation activity",
+ "GNU Taler contributors",
+ 1,
+ ),
+ (
+ "manpages/taler-helper-auditor-coins.1",
+ "taler-helper-auditor-coins",
+ "audit Taler coin processing",
+ "GNU Taler contributors",
+ 1,
+ ),
+ (
+ "manpages/taler-helper-auditor-deposits.1",
+ "taler-helper-auditor-deposits",
+ "audit Taler exchange database for deposit confirmation consistency",
+ "GNU Taler contributors",
+ 1,
+ ),
+ (
+ "manpages/taler-helper-auditor-purses.1",
+ "taler-helper-auditor-purses",
+ "audit Taler exchange purse handling",
+ "GNU Taler contributors",
+ 1,
+ ),
+ (
+ "manpages/taler-helper-auditor-reserves.1",
+ "taler-helper-auditor-reserves",
+ "audit Taler exchange reserve handling",
+ "GNU Taler contributors",
+ 1,
+ ),
+ (
+ "manpages/taler-helper-auditor-wire.1",
+ "taler-helper-auditor-wire",
+ "audit exchange database for consistency with the bank's wire transfers",
+ "GNU Taler contributors",
+ 1,
+ ),
+ (
+ "manpages/libeufin-sandbox.1",
+ "libeufin-sandbox",
+ "simulate core banking system with EBICS access to bank accounts",
+ "GNU Taler contributors",
+ 1,
+ ),
+ (
+ "manpages/libeufin-nexus.1",
+ "libeufin-nexus",
+ "service to interface to various bank access APIs",
+ "GNU Taler contributors",
+ 1,
+ ),
]
# If true, show URL addresses after external links.
-#man_show_urls = False
+# man_show_urls = False
# -- Options for Texinfo output -------------------------------------------
@@ -381,31 +597,83 @@ man_pages = [
# (source start file, target name, title, author,
# dir menu entry, description, category)
texinfo_documents = [
- ("taler-auditor-manual", "taler-auditor", "Taler Auditor Manual",
- "GNU Taler team", "MENU ENTRY", "DESCRIPTION", "CATEGORY"),
- ("taler-exchange-manual", "taler-exchange", "Taler Exchange Manual",
- "GNU Taler team", "MENU ENTRY", "DESCRIPTION", "CATEGORY"),
- ("taler-merchant-manual", "taler-merchant", "Taler Merchant Manual",
- "GNU Taler team", "MENU ENTRY", "DESCRIPTION", "CATEGORY"),
- ("taler-merchant-api-tutorial", "taler-merchant-api-tutorial",
- "Taler Merchant API Tutorial", "GNU Taler team", "MENU ENTRY",
- "DESCRIPTION", "CATEGORY"),
- ("taler-developer-manual", "taler-developer-manual", "Taler Developer Manual", "GNU Taler team",
- "MENU ENTRY", "DESCRIPTION", "CATEGORY"),
+ (
+ "taler-auditor-manual",
+ "taler-auditor",
+ "Taler Auditor Manual",
+ "GNU Taler team",
+ "MENU ENTRY",
+ "DESCRIPTION",
+ "CATEGORY",
+ ),
+ (
+ "taler-exchange-manual",
+ "taler-exchange",
+ "Taler Exchange Manual",
+ "GNU Taler team",
+ "MENU ENTRY",
+ "DESCRIPTION",
+ "CATEGORY",
+ ),
+ (
+ "taler-merchant-manual",
+ "taler-merchant",
+ "Taler Merchant Manual",
+ "GNU Taler team",
+ "MENU ENTRY",
+ "DESCRIPTION",
+ "CATEGORY",
+ ),
+ (
+ "taler-merchant-api-tutorial",
+ "taler-merchant-api-tutorial",
+ "Taler Merchant API Tutorial",
+ "GNU Taler team",
+ "MENU ENTRY",
+ "DESCRIPTION",
+ "CATEGORY",
+ ),
+ (
+ "taler-developer-manual",
+ "taler-developer-manual",
+ "Taler Developer Manual",
+ "GNU Taler team",
+ "MENU ENTRY",
+ "DESCRIPTION",
+ "CATEGORY",
+ ),
]
# Documents to append as an appendix to all manuals.
-#texinfo_appendices = []
+# texinfo_appendices = []
# If false, no module index is generated.
-#texinfo_domain_indices = True
+# texinfo_domain_indices = True
# How to display URL addresses: 'footnote', 'no', or 'inline'.
-#texinfo_show_urls = 'footnote'
+# texinfo_show_urls = 'footnote'
# If true, do not generate a @detailmenu in the "Top" node's menu.
-#texinfo_no_detailmenu = False
+# texinfo_no_detailmenu = False
# The output format for Graphviz when building HTML files.
# This must be either 'png' or 'svg'; the default is 'png'.
-graphviz_output_format = 'svg'
+graphviz_output_format = "svg"
+
+myst_heading_anchors = 3
+
+myst_enable_extensions = [
+ "amsmath",
+ "colon_fence",
+ "deflist",
+ "dollarmath",
+ "fieldlist",
+ "html_admonition",
+ "html_image",
+ "linkify",
+ "replacements",
+ "smartquotes",
+ "strikethrough",
+ "substitution",
+ "tasklist",
+]
diff --git a/core/api-bank-access.rst b/core/api-bank-access.rst
index a33cbdb..8257839 100644
--- a/core/api-bank-access.rst
+++ b/core/api-bank-access.rst
@@ -81,7 +81,7 @@ name and account password, at least in the GNU Taler demo bank implementation.
}
-.. http:POST:: ${BANK_API_BASE_URL}/accounts/${account_name}/withdrawals
+.. http:post:: ${BANK_API_BASE_URL}/accounts/${account_name}/withdrawals
Create a withdrawal operation, resulting in a ``taler://withdraw`` URI.
@@ -107,7 +107,7 @@ name and account password, at least in the GNU Taler demo bank implementation.
}
-.. http:GET:: ${BANK_API_BASE_URL}/accounts/${account_name}/withdrawals/${withdrawal_id}
+.. http:get:: ${BANK_API_BASE_URL}/accounts/${account_name}/withdrawals/${withdrawal_id}
Query the status of a withdrawal operation.
@@ -143,7 +143,7 @@ name and account password, at least in the GNU Taler demo bank implementation.
}
-.. http:POST:: ${BANK_API_BASE_URL}/accounts/${account_name}/withdrawals/${withdrawal_id}/abort
+.. http:post:: ${BANK_API_BASE_URL}/accounts/${account_name}/withdrawals/${withdrawal_id}/abort
Abort a withdrawal operation. Has no effect on an already aborted withdrawal operation.
@@ -151,7 +151,7 @@ name and account password, at least in the GNU Taler demo bank implementation.
:http:statuscode:`409 Conflict`: The reserve operation has been confirmed previously and can't be aborted.
-.. http:POST:: ${BANK_API_BASE_URL}/accounts/${account_name}/withdrawals/${withdrawal_id}/confirm
+.. http:post:: ${BANK_API_BASE_URL}/accounts/${account_name}/withdrawals/${withdrawal_id}/confirm
Confirm a withdrawal operation. Has no effect on an already confirmed withdrawal operation.
This call is responsible of wiring the funds to the exchange.
@@ -169,7 +169,7 @@ name and account password, at least in the GNU Taler demo bank implementation.
Transactions
------------
-.. http:GET:: ${BANK_API_BASE_URL}/accounts/${account_name}/transactions
+.. http:get:: ${BANK_API_BASE_URL}/accounts/${account_name}/transactions
Retrieve a subset of transactions related to $account_name. Without
query parameters, it returns the last 5 transactions.
@@ -187,7 +187,7 @@ Transactions
transactions: BankAccountTransactionInfo[];
}
-.. http:GET:: ${BANK_API_BASE_URL}/accounts/${account_name}/transactions/${transaction_id}
+.. http:get:: ${BANK_API_BASE_URL}/accounts/${account_name}/transactions/${transaction_id}
**Response**
@@ -218,7 +218,7 @@ Transactions
}
-.. http:POST:: ${BANK_API_BASE_URL}/accounts/${account_name}/transactions
+.. http:post:: ${BANK_API_BASE_URL}/accounts/${account_name}/transactions
Create a new transaction where the bank account with the label ``account_name`` is **debited**.
@@ -247,11 +247,16 @@ Transactions
:http:statuscode:`400 Bad Request`:
the request was invalid or the payto://-URI used unacceptable features.
+.. http:delete:: ${BANK_API_BASE_URL}/accounts/${account_name}
+
+ Delete the bank account (and the customer entry) from the database.
+ Note, customer usernames and bank accounts have the same value.
+
----------------------
Registration (Testing)
----------------------
-.. http:POST:: ${BANK_API_BASE_URL}/testing/register
+.. http:post:: ${BANK_API_BASE_URL}/testing/register
Create a new bank account. This endpoint should be disabled for most deployments, but is useful
for automated testing / integration tests.
diff --git a/core/api-common.rst b/core/api-common.rst
index 848d580..b2913b4 100644
--- a/core/api-common.rst
+++ b/core/api-common.rst
@@ -117,7 +117,7 @@ handle the error as if an internal error (500) had been returned.
// Name of the object that was bogus (if applicable).
object?: string;
- // Name of the currency than was problematic (if applicable).
+ // Name of the currency that was problematic (if applicable).
currency?: string;
// Expected type (if applicable).
@@ -616,7 +616,7 @@ uses 512-bit hash codes (64 bytes).
.. sourcecode:: c
- struct TALER_ExtensionContractHash {
+ struct TALER_ExtensionsPolicyHash {
struct GNUNET_HashCode hash;
};
@@ -840,7 +840,7 @@ within the
struct GNUNET_CRYPTO_EccSignaturePurpose purpose;
struct TALER_PrivateContractHash h_contract_terms;
struct TALER_AgeCommitmentHash h_age_commitment;
- struct TALER_ExtensionContractHash h_extensions;
+ struct TALER_ExtensionsPolicyHash h_policy;
struct TALER_MerchantWireHash h_wire;
struct TALER_DenominationHash h_denom_pub;
struct GNUNET_TIME_AbsoluteNBO timestamp;
@@ -860,7 +860,7 @@ within the
struct GNUNET_CRYPTO_EccSignaturePurpose purpose;
struct TALER_PrivateContractHash h_contract_terms;
struct TALER_MerchantWireHash h_wire;
- struct TALER_ExtensionContractHash h_extensions;
+ struct TALER_ExtensionsPolicyHash h_policy;
struct GNUNET_TIME_AbsoluteNBO timestamp;
struct GNUNET_TIME_AbsoluteNBO refund_deadline;
struct TALER_AmountNBO amount_without_fee;
@@ -1365,6 +1365,19 @@ within the
};
+.. _TALER_ReserveOpenDepositSignaturePS:
+.. sourcecode:: c
+
+ struct TALER_PurseDepositSignaturePS {
+ /**
+ * purpose.purpose = TALER_SIGNATURE_WALLET_RESERVE_OPEN_DEPOSIT
+ */
+ struct GNUNET_CRYPTO_EccSignaturePurpose purpose;
+ struct TALER_ReserveSignatureP reserve_sig;
+ struct TALER_AmountNBO coin_contribution;
+ };
+
+
.. _TALER_PurseDepositConfirmedSignaturePS:
.. sourcecode:: c
@@ -1410,6 +1423,30 @@ within the
uint32_t min_age;
};
+.. _TALER_AccountSetupRequestSignaturePS:
+.. sourcecode:: c
+
+ struct TALER_AccountSetupRequestSignaturePS {
+ /**
+ * purpose.purpose = TALER_SIGNATURE_WALLET_ACCOUNT_SETUP
+ */
+ struct GNUNET_CRYPTO_EccSignaturePurpose purpose;
+ struct TALER_AmountNBO threshold;
+ };
+
+.. _TALER_AccountSetupSuccessSignaturePS:
+.. sourcecode:: c
+
+ struct TALER_AccountSetupSuccessSignaturePS {
+ /**
+ * purpose.purpose = TALER_SIGNATURE_WALLET_ACCOUNT_SETUP_SUCCESS
+ */
+ struct GNUNET_CRYPTO_EccSignaturePurpose purpose;
+ struct TALER_PaytoHash h_payto;
+ struct GNUNET_HashCode h_kyc;
+ struct GNUNET_TIME_AbsoluteNBO timestamp;
+ };
+
.. _TALER_PurseMergeSuccessSignaturePS:
.. sourcecode:: c
@@ -1490,9 +1527,7 @@ within the
struct GNUNET_CRYPTO_EccSignaturePurpose purpose;
struct TALER_PursePublicKey purse_pub;
union TALER_CoinSpendPublicKeyP coin_pub;
- struct TALER_MerchantPublicKeyP merchant;
- struct TALER_AmountNBO remaining_amount;
- struct TALER_AmountNBO purse_fee_share;
+ struct TALER_AmountNBO refunded_amount;
struct TALER_AmountNBO refund_fee;
};
diff --git a/core/api-exchange.rst b/core/api-exchange.rst
index 720d5a8..c5a6783 100644
--- a/core/api-exchange.rst
+++ b/core/api-exchange.rst
@@ -24,50 +24,9 @@ for all details not specified in the individual requests.
The `glossary <https://docs.taler.net/glossary.html#glossary>`_
defines all specific terms used in this section.
-.. _keys:
-
---------------------
-Terms of service API
---------------------
-
-These APIs allow merchants and wallets to obtain the terms of service
-and the privacy policy of an exchange.
-
-
-.. http:get:: /terms
-
- Get the terms of service of the exchange.
- The exchange will consider the "Accept" and "Accept-Language" and
- "Accept-Encoding" headers when generating a response. Specifically,
- it will try to find a response with an acceptable mime-type, then
- pick the version in the most preferred language of the user, and
- finally apply compression if that is allowed by the client and
- deemed beneficial.
-
- The exchange will set an "Etag", and subsequent requests of the
- same client should provide the tag in an "If-None-Match" header
- to detect if the terms of service have changed. If not, a
- "204 Not Modified" response will be returned.
-
- If the "Etag" is missing, the client should not cache the response and instead prompt the user again at the next opportunity. This is usually only the case if the terms of service were not configured correctly.
-
+.. include:: tos.rst
-.. http:get:: /privacy
-
- Get the privacy policy of the exchange.
- The exchange will consider the "Accept" and "Accept-Language" and
- "Accept-Encoding" headers when generating a response. Specifically,
- it will try to find a response with an acceptable mime-type, then
- pick the version in the most preferred language of the user, and
- finally apply compression if that is allowed by the client and
- deemed beneficial.
-
- The exchange will set an "Etag", and subsequent requests of the
- same client should provide the tag in an "If-None-Match" header
- to detect if the privacy policy has changed. If not, a
- "204 Not Modified" response will be returned.
-
- If the "Etag" is missing, the client should not cache the response and instead prompt the user again at the next opportunity. This is usually only the case if the privacy policy was not configured correctly.
+.. _keys:
---------------------------
Exchange status information
@@ -120,6 +79,9 @@ possibly by using HTTPS.
// The format is "current:revision:age".
version: string;
+ // The exchange's base URL.
+ base_url: string;
+
// The exchange's currency.
currency: string;
@@ -195,11 +157,6 @@ possibly by using HTTPS.
// What date (exclusive) does this fees stop going into effect?
end_date: Timestamp;
- // KYC fee, charged when a user wants to create an account.
- // The first year of the account_annual_fee after the KYC is
- // always included.
- kyc_fee: Amount;
-
// Account history fee, charged when a user wants to
// obtain a reserve/account history.
history_fee: Amount;
@@ -221,13 +178,6 @@ possibly by using HTTPS.
// retain the account history for legal reasons until this time.
history_expiration: RelativeTime;
- // How long does the exchange promise to keep funds
- // an account for which the KYC has never happened
- // after a purse was merged into an account? Basically,
- // after this time funds in an account without KYC are
- // forfeit.
- account_kyc_timeout: RelativeTime;
-
// Non-negative number of concurrent purses that any
// account holder is allowed to create without having
// to pay the purse_fee.
@@ -982,9 +932,6 @@ Management operations authorized by master key
// Wire fee to charge during that time period for this wire method.
wire_fee: Amount;
- // Wad fee to charge during that time period for this wire method.
- wad_fee: Amount;
-
}
.. http:post:: /management/global-fees
@@ -1348,6 +1295,8 @@ exchange.
| ReserveWithdrawTransaction
| ReserveCreditTransaction
| ReserveClosingTransaction
+ | ReserveOpenRequestTransaction
+ | ReserveCloseRequestTransaction
| PurseMergeTransaction;
.. ts:def:: PurseMergeTransaction
@@ -1556,27 +1505,64 @@ exchange.
}
- .. ts:def:: ReserveRecoupTransaction
+ .. ts:def:: ReserveOpenRequestTransaction
- interface ReserveRecoupTransaction {
- type: "RECOUP";
+ interface ReserveOpenRequestTransaction {
+ type: "OPEN";
- // Amount paid back.
- amount: Amount;
+ // Open fee paid from the reserve.
+ open_fee: Amount;
// This is a signature over
- // a struct `TALER_RecoupConfirmationPS` with purpose
- // ``TALER_SIGNATURE_EXCHANGE_CONFIRM_RECOUP``.
- exchange_sig: EddsaSignature;
+ // a struct `TALER_ReserveOpenPS` with purpose
+ // ``TALER_SIGNATURE_WALLET_RESERVE_OPEN``.
+ reserve_sig: EddsaSignature;
- // Public key used to create 'exchange_sig'.
- exchange_pub: EddsaPublicKey;
+ // Timestamp of the open request.
+ request_timestamp: Timestamp;
- // Time when the funds were paid back into the reserve.
- timestamp: Timestamp;
+ // Requested expiration.
+ requested_expiration: Timestamp;
+
+ // Requested number of free open purses.
+ requested_min_purses: Integer;
- // Public key of the coin that was paid back.
- coin_pub: CoinPublicKey;
+ }
+
+ .. ts:def:: ReserveCloseRequestTransaction
+
+ interface ReserveCloseRequestTransaction {
+ type: "CLOSE";
+
+ // This is a signature over
+ // a struct `TALER_ReserveClosePS` with purpose
+ // ``TALER_SIGNATURE_WALLET_RESERVE_CLOSE``.
+ reserve_sig: EddsaSignature;
+
+ // Target account ``payto://``, optional.
+ h_payto?: string;
+
+ // Timestamp of the close request.
+ request_timestamp: Timestamp;
+ }
+
+ .. ts:def:: ReserveCreditTransaction
+
+ interface ReserveCreditTransaction {
+ type: "CREDIT";
+
+ // Amount deposited.
+ amount: Amount;
+
+ // Sender account ``payto://`` URL.
+ sender_account_url: string;
+
+ // Opaque identifier internal to the exchange that
+ // uniquely identifies the wire transfer that credited the reserve.
+ wire_reference: Integer;
+
+ // Timestamp of the incoming wire transfer.
+ timestamp: Timestamp;
}
@@ -2018,12 +2004,20 @@ exchange.
Deposit
-------
-Deposit operations are requested by a merchant during a transaction. For the
-deposit operation, the merchant has to obtain the deposit permission for a coin
-from their customer who owns the coin. When depositing a coin, the merchant is
-credited an amount specified in the deposit permission, possibly a fraction of
-the total coin's value, minus the deposit fee as specified by the coin's
-denomination.
+Deposit operations are requested f.e. by a merchant during a transaction or a
+bidder during an auction.
+
+For the deposit operation during purchase, the merchant has to obtain the
+deposit permission for a coin from their customer who owns the coin. When
+depositing a coin, the merchant is credited an amount specified in the deposit
+permission, possibly a fraction of the total coin's value, minus the deposit
+fee as specified by the coin's denomination.
+
+For auctions, a bidder performs an deposit operation and provides all relevant
+information for the auction policy (such as timeout and public key as bidder)
+and can use the ``exchange_sig`` field from the `DepositSuccess` message as a
+proof to the seller for the escrow of sufficient fund.
+
.. _deposit:
@@ -2081,6 +2075,7 @@ denomination.
contribution: Amount;
// The merchant's account details.
+ // In case of an auction policy, it refers to the seller.
merchant_payto_uri: string;
// The salt is used to hide the ``payto_uri`` from customers
@@ -2107,12 +2102,28 @@ denomination.
// EdDSA `public key of the merchant <merchant-pub>`, so that the client can identify the
// merchant for refund requests.
+ //
+ // THIS FIELD WILL BE DEPRICATED, once the refund mechanism becomes a
+ // policy via extension.
merchant_pub: EddsaPublicKey;
// Date until which the merchant can issue a refund to the customer via the
// exchange, to be omitted if refunds are not allowed.
+ //
+ // THIS FIELD WILL BE DEPRICATED, once the refund mechanism becomes a
+ // policy via extension.
refund_deadline?: Timestamp;
+ // CAVEAT: THIS IS WORK IN PROGRESS
+ // (Optional) policy for the deposit.
+ // This might be a refund, auction or escrow policy.
+ //
+ // Note that support for policies is an optional feature of the exchange.
+ // Optional features are so called "extensions" in Taler. The exchange
+ // provides the list of supported extensions, including policies, in the
+ // `ExtensionsManifestsResponse` response to the ``/keys`` endpoint.
+ policy?: DepositPolicy;
+
// Signature over `TALER_DepositRequestPS`, made by the customer with the
// `coin's private key <coin-priv>`.
coin_sig: EddsaSignature;
@@ -2146,6 +2157,142 @@ denomination.
}
+ .. ts:def:: DepositPolicy
+
+ type DepositPolicy =
+ | PolicyMerchantRefund
+ | PolicyBrandtVickreyAuction
+ | PolicyEscrowedPayment;
+
+ .. ts:def:: PolicyMerchantRefund
+
+ // CAVEAT: THIS IS STILL WORK IN PROGRESS.
+ // This policy is optional and might not be supported by the exchange.
+ // If it does, the exchange MUST show support for this policy in the
+ // ``extensions`` field in the response to ``/keys``.
+ interface PolicyMerchantRefund {
+ type: "merchant_refund";
+
+ // EdDSA `public key of the merchant <merchant-pub>`, so that the client
+ // can identify the merchant for refund requests.
+ merchant_pub: EddsaPublicKey;
+
+ // Date until which the merchant can issue a refund to the customer via
+ // the ``/extensions/policy_refund``-endpoint of the exchange.
+ deadline: Timestamp;
+ }
+
+ .. ts:def:: PolicyBrandtVickreyAuction
+
+ // CAVEAT: THIS IS STILL WORK IN PROGRESS.
+ // This policy is optional and might not be supported by the exchange.
+ // If it does, the exchange MUST show support for this policy in the
+ // ``extensions`` field in the response to ``/keys``.
+ interface PolicyBrandtVickreyAuction {
+ type: "brandt_vickrey_auction";
+
+ // Public key of this bidder.
+ //
+ // The bidder uses this key to sign the auction information and
+ // the messages it sends to the seller during the auction.
+ bidder_pub: EddsaPublicKey;
+
+ // Hash of the auction terms
+ //
+ // The hash should be taken over a normalized JSON object of type
+ // `BrandtVickreyAuction`.
+ h_auction: HashCode;
+
+ // The amount that this bidder commits to for this auction
+ //
+ // This amount can be larger than the contribution of a single coin.
+ // The bidder can increase funding of this auction policy by using
+ // sufficiently many coins during the deposit operation (single or batch)
+ // with the same policy.
+ commitment: Amount;
+
+ // Date until the auction must have been successfully executed and
+ // a valid transcript provided to the
+ // ``/extensions/policy_brandt_vickrey_auction``-endpoint of the
+ // exchange.
+ //
+ // [If the auction has not been executed by then] OR [has been executed
+ // before then, but this bidder did not win], the coin's value doesn't
+ // change and the owner can refresh the coin.
+ //
+ // If this bidder won the auction, the winning price/amount from the
+ // outcome will be substracted from the coin and transfered to the
+ // merchant's ``payout_uri`` from the deposit request (minus a potential
+ // auction fee). For any remaining value, the bidder can refresh the
+ // coin to retrieve change.
+ deadline: Timestamp;
+ }
+
+ .. ts:def:: BrandtVickreyAuction
+
+ // CAVEAT: THIS IS STILL WORK IN PROGRESS.
+ // This structure defines an auction of Brandt-Vickory kind.
+ // It is used for the `PolicyBrandtVickreyAuction`.
+ interface BrandtVickreyAuction {
+ // Start date of the auction
+ time_start: Timestamp;
+
+ // Maximum duration per round. There are four rounds in an auction of
+ // Brandt-Vickrey kind.
+ time_round: RelativeTime;
+
+ // This integer m refers to the (m+1)-type of the Brandt-Vickrey-auction.
+ // - Type 0 refers to an auction with one highest-price winner,
+ // - Type 1 refers to an auction with one winner, paying the second
+ // highest price,
+ // - Type 2 refers to an auction with two winners, paying
+ // the third-highest price,
+ // - etc.
+ auction_type: number;
+
+ // The vector of prices for the Brandt-Vickrey auction. The values MUST
+ // be in strictly increasing order.
+ prices: Amount[];
+
+ // The type of outcome of the auction.
+ // In case the auction is declared public, each bidder can calculate the
+ // winning price. This field is not relevant for the replay of a
+ // transcript, as the transcript must be provided by the seller who sees
+ // the winner(s) and winning price of the auction.
+ outcome_public: boolean;
+
+ // The public key of the seller.
+ pubkey: EddsaPublicKey;
+
+ // The seller's account details.
+ payto_uri: string;
+ }
+
+
+ .. ts:def:: PolicyEscrowedPayment
+
+ // CAVEAT: THIS IS STILL WORK IN PROGRESS
+ // This policy is optional and might not be supported by the exchange.
+ // If it does, the exchange MUST show support for this policy in the
+ // ``extensions`` field in the response to ``/keys``.
+ interface PolicyEscrowedPayment {
+ type: "escrowed_payment";
+
+ // Public key of this trustor, the owner of the coins.
+ //
+ // To claim the deposit, the merchant must provide the valid signature
+ // of the ``h_contract_terms`` field from the deposit, signed by _this_
+ // key, to the ``/extensions/policy_escrow``-endpoint of the exchange,
+ // after the date specified in ``not_before`` and before the date
+ // specified in ``not_after``.
+ trustor_pub: EddsaPublicKey;
+
+ // Latest date by which the deposit must be claimed. If the deposit
+ // has not been claimed by that date, the deposited coins can be
+ // refreshed by the (still) owner.
+ deadline: Timestamp;
+ }
+
The deposit operation succeeds if the coin is valid for making a deposit and
has enough residual value that has not already been deposited or melted.
@@ -2203,7 +2350,8 @@ denomination.
| CoinOldCoinRecoupTransaction
| CoinRecoupRefreshTransaction
| CoinPurseDepositTransaction
- | CoinPurseRefundTransaction;
+ | CoinPurseRefundTransaction
+ | CoinReserveOpenDepositTransaction;
.. ts:def:: CoinDepositTransaction
@@ -2418,7 +2566,7 @@ denomination.
.. ts:def:: CoinPurseDepositTransaction
interface CoinPurseDepositTransaction {
- type: "PURSE_DEPOSIT";
+ type: "PURSE-DEPOSIT";
// The total amount of the coin's value absorbed
// by this transaction.
@@ -2452,7 +2600,7 @@ denomination.
.. ts:def:: CoinPurseRefundTransaction
interface CoinPurseRefundTransaction {
- type: "PURSE_REFUND";
+ type: "PURSE-REFUND";
// The total amount of the coin's value restored
// by this transaction.
@@ -2465,11 +2613,6 @@ denomination.
// fee will be waived.
refund_fee: Amount;
- // Share of the purse fee charged to this coin.
- // The sum of all purse fee shares will match the
- // total purse fee.
- purse_fee_share: Amount;
-
// Public key of the purse that expired.
purse_pub: EddsaPublicKey;
@@ -2478,11 +2621,32 @@ denomination.
// of purpose ``TALER_SIGNATURE_EXCHANGE_CONFIRM_PURSE_REFUND``.
exchange_sig: EddsaSignature;
- // Public key used to sign 'exchange_sig'.
+ // Public key used to sign 'exchange_sig'.
exchange_pub: EddsaPublicKey;
}
+ .. ts:def:: CoinReserveOpenDepositTransaction
+
+ interface CoinReserveOpenDepositTransaction {
+ type: "RESERVE-OPEN-DEPOSIT";
+
+ // The total amount of the coin's value absorbed
+ // by this transaction.
+ // Note that this means the amount given includes
+ // the deposit fee.
+ coin_contribution: Amount;
+
+ // Signature of the reserve open operation being paid for.
+ reserve_sig: EddsaSignature;
+
+ // Signature by the coin over a
+ // `TALER_ReserveOpenDepositSignaturePS` of
+ // purpose ``TALER_SIGNATURE_RESERVE_OPEN_DEPOSIT``.
+ coin_sig: EddsaSignature;
+
+ }
+
.. http:POST:: /batch-deposit
@@ -2530,7 +2694,7 @@ denomination.
.. ts:def:: BatchDepositRequest
- interface DepositRequest {
+ interface BatchDepositRequest {
// The merchant's account details.
merchant_payto_uri: string;
@@ -2543,6 +2707,9 @@ denomination.
// details are never disclosed to the exchange.
h_contract_terms: HashCode;
+ // The list of coins that are going to be deposited with this Request.
+ coins: BatchDepositRequestCoin[];
+
// Timestamp when the contract was finalized.
timestamp: Timestamp;
@@ -2557,12 +2724,20 @@ denomination.
// Date until which the merchant can issue a refund to the customer via the
// exchange, to be omitted if refunds are not allowed.
+ //
+ // THIS FIELD WILL BE DEPRICATED, once the refund mechanism becomes a
+ // policy via extension.
refund_deadline?: Timestamp;
+
+ // CAVEAT: THIS IS WORK IN PROGRESS
+ // (Optional) policy for the batch-deposit.
+ // This might be a refund, auction or escrow policy.
+ policy?: DepositPolicy;
}
- .. ts:def:: DepositRequest
+ .. ts:def:: BatchDepositRequestCoin
- interface DepositRequest {
+ interface BatchDepositRequestCoin {
// EdDSA public key of the coin being deposited.
coin_pub: EddsaPublicKey;
@@ -2611,7 +2786,7 @@ denomination.
// Array of deposit confirmation signatures from the exchange
// Entries must be in the same order the coins were given
// in the batch deposit request.
- exchange_sigs[]: DepositConfirmationSignature;
+ exchange_sigs: DepositConfirmationSignature[];
}
.. ts:def:: DepositConfirmationSignature
@@ -4070,7 +4245,7 @@ Wallet-to-wallet transfers
// AgeCommitment is an array of public keys, one for each age group of the
// age-restricted denomination.
- type AgeCommitment = []Edx25519PublicKey;
+ type AgeCommitment = Edx25519PublicKey[];
.. ts:def:: Attestation
@@ -4285,7 +4460,11 @@ KYC status updates
.. ts:def:: AccountKycStatus
- interface AccountKycStatus {
+ interface AccountKycStatus {
+
+ // Details about the KYC check that the user
+ // passed.
+ kyc_details: KycDetails;
// Current time of the exchange, used as part of
// what the exchange signs over.
@@ -4303,7 +4482,7 @@ KYC status updates
.. ts:def:: AccountKycRedirect
- interface AccountKycRedirect {
+ interface AccountKycRedirect {
// URL that the user should open in a browser to
// proceed with the KYC process.
@@ -4311,6 +4490,15 @@ KYC status updates
}
+ .. ts:def:: KycDetails
+
+ // Object that specifies which KYC checks are satisfied.
+ interface KycDetails {
+
+ // Keys are the names of the check(s).
+ // The values are for now always empty objects.
+
+ }
.. http:GET:: /kyc-proof/$H_PAYTO/$PROVIDER_SECTION
@@ -4406,12 +4594,24 @@ naturally expire and possibly (5) wire the funds to a designated account.
:http:statuscode:`200 OK`:
The exchange responds with a `ReserveOpenResponse` object.
:http:statuscode:`402 Payment Required`:
- The exchange responds with a `ReserveOpenFailure` object.
+ The exchange responds with a `ReserveOpenFailure` object when
+ the payment offered is insufficient for the requested operation.
:http:statuscode:`403 Forbidden`:
The *TALER_SIGNATURE_WALLET_RESERVE_OPEN* signature is invalid.
This response comes with a standard `ErrorDetail` response.
:http:statuscode:`404 Not found`:
The reserve key does not belong to a reserve known to the exchange.
+ :http:statuscode:`409 Conflict`:
+ The balance of the reserve or of a coin was insufficient.
+ Which case it is can be decided by looking at the error code
+ (``TALER_EC_EXCHANGE_GENERIC_INSUFFICIENT_FUNDS`` or
+ ``TALER_EC_EXCHANGE_GENERIC_COIN_CONFLICTING_DENOMINATION_KEY`` or
+ ``TALER_EC_EXCHANGE_OPEN_INSUFFICIENT_FUNDS``).
+ The specific fields of the response depend on the error code
+ and include the signatures (and what was signed over) proving the
+ conflict.
+ The response is `WithdrawError` object or a `DepositDoubleSpendError`
+ depending on the error type.
:http:statuscode:`451 Unavailable For Legal Reasons`:
This account has not yet passed the KYC checks.
The client must pass KYC checks before the reserve can be opened.
@@ -4487,7 +4687,7 @@ naturally expire and possibly (5) wire the funds to a designated account.
// Contribution of this coin to the overall amount.
// Can be a fraciton of the coin's total value.
- contribution: Amount;
+ amount: Amount;
// Hash of denomination RSA key with which the coin is signed.
denom_pub_hash: HashCode;
@@ -4511,7 +4711,7 @@ naturally expire and possibly (5) wire the funds to a designated account.
}
-.. http:get:: /reserves/$RESERVE_PUB/attest
+.. http:get:: /reserves-attest/$RESERVE_PUB
Request list of available KYC attributes about the owner of a reserve.
Used as a preliminary step to find out which subsets of attributes the
@@ -4534,11 +4734,11 @@ naturally expire and possibly (5) wire the funds to a designated account.
// Array of KYC attributes available. The attribute names
// listed are expected to be from the respective GANA
// registry.
- details: String[];
+ details: string[];
}
-.. http:post:: /reserves/$RESERVE_PUB/attest
+.. http:post:: /reserves-attest/$RESERVE_PUB
Request signed KYC information about the owner of a reserve.
This can be used by a reserve owner to include a proof
@@ -4570,8 +4770,11 @@ naturally expire and possibly (5) wire the funds to a designated account.
// a `TALER_WalletReserveAttestRequestSignaturePS`.
reserve_sig: EddsaSignature;
+ // Client's time for the request.
+ request_timestamp: Timestamp;
+
// Array of KYC attributes requested.
- details: String[];
+ details: string[];
}
.. ts:def:: ReserveAttestResponse
@@ -4580,7 +4783,11 @@ naturally expire and possibly (5) wire the funds to a designated account.
// Signature of purpose
// ``TALER_SIGNATURE_EXCHANGE_RESERVE_ATTEST_DETAILS`` over
// a `TALER_ExchangeReserveAttestDetailsSignaturePS`.
- reserve_sig: EddsaSignature;
+ exchange_sig: EddsaSignature;
+
+ // Exchange public key used to create the
+ // signature.
+ exchange_pub: EddsaPublicKey;
// Time when the exchange created the signature.
exchange_timestamp: Timestamp;
diff --git a/core/api-mailbox.rst b/core/api-mailbox.rst
index 4633777..33db482 100644
--- a/core/api-mailbox.rst
+++ b/core/api-mailbox.rst
@@ -29,52 +29,7 @@ for all details not specified in the individual requests.
The `glossary <https://docs.taler.net/glossary.html#glossary>`_
defines all specific terms used in this section.
---------------------
-Terms of service API
---------------------
-
-These APIs allow wallets to obtain the terms of service
-and the privacy policy of the Mailbox.
-
-.. http:get:: /terms
-
- Get the terms of service of the Mailbox.
- The Mailbox will consider the "Accept" and "Accept-Language" and
- "Accept-Encoding" headers when generating a response. Specifically,
- it will try to find a response with an acceptable mime-type, then
- pick the version in the most preferred language of the user, and
- finally apply compression if that is allowed by the client and
- deemed beneficial.
-
- The Mailbox will set an "Etag", and subsequent requests of the
- same client should provide the tag in an "If-None-Match" header
- to detect if the terms of service have changed. If not, a
- "204 Not Modified" response will be returned.
-
- If the "Etag" is missing, the client should not cache the response and
- instead prompt the user again at the next opportunity. This is usually only
- the case if the terms of service were not configured correctly.
-
-
-.. http:get:: /privacy
-
- Get the privacy policy of the Mailbox.
- The Mailbox will consider the "Accept" and "Accept-Language" and
- "Accept-Encoding" headers when generating a response. Specifically,
- it will try to find a response with an acceptable mime-type, then
- pick the version in the most preferred language of the user, and
- finally apply compression if that is allowed by the client and
- deemed beneficial.
-
- The Mailbox will set an "Etag", and subsequent requests of the
- same client should provide the tag in an "If-None-Match" header
- to detect if the privacy policy has changed. If not, a
- "204 Not Modified" response will be returned.
-
- If the "Etag" is missing, the client should not cache the response and
- instead prompt the user again at the next opportunity. This is usually only
- the case if the privacy policy was not configured correctly.
-
+.. include:: tos.rst
-------------------------
Configuration information
diff --git a/core/api-merchant.rst b/core/api-merchant.rst
index d197c07..55a4da0 100644
--- a/core/api-merchant.rst
+++ b/core/api-merchant.rst
@@ -16,6 +16,7 @@
@author Marcello Stanisci
@author Florian Dold
@author Christian Grothoff
+ @author Priscilla Huang
.. _merchant-api:
@@ -25,6 +26,7 @@ Merchant Backend API
.. contents:: Table of Contents
+
-----------------------
Base URLs and Instances
-----------------------
@@ -855,7 +857,7 @@ Instance management
-------------------
Instances allow one merchant backend to be shared by multiple merchants.
-Every backend must have at least one instance, typcially the "default"
+Every backend must have at least one instance, typically the "default"
instance setup before it can be used to manage inventory or process payments.
@@ -2953,7 +2955,7 @@ Checking tip status
.. ts:def:: Tip
- interface Tip {
+ interface Tip {
// ID of the tip in the backend database.
row_id: number;
@@ -2967,6 +2969,447 @@ Checking tip status
+--------
+Template
+--------
+
+The template is a backend feature that is used to create an order. We use the template to have some static information that cannot be changed by the customer.
+The template is private and allows us to be flexible. The private template allows for greater security and allows us to have a minimum information we need for each store.
+
+
+
+Adding templates
+----------------
+
+.. http:post:: [/instances/$INSTANCE]/private/templates
+
+ This is used to create a template.
+
+ **Request:**
+
+ The request must be a `TemplateAddDetails`.
+
+
+ **Response:**
+
+ :http:statuscode:`204 No content`:
+ The creation of the template is successful.
+ :http:statuscode:`404 Not found`:
+ The merchant instance is unknown or it is not in our data.
+
+
+ .. ts:def:: TemplateAddDetails
+
+ interface TemplateAddDetails {
+
+ // Template ID to use.
+ template_id: string;
+
+ // Human-readable description for the template.
+ template_description: string;
+
+ // A base64-encoded image selected by the merchant.
+ // This parameter is optional.
+ // We are not sure about it.
+ image?: ImageDataUrl;
+
+ // Additional information in a separate template.
+ template_contract: TemplateContractDetails;
+ }
+
+
+ .. ts:def:: TemplateContractDetails
+
+ interface TemplateContractDetails {
+
+ // Human-readable summary for the template.
+ summary?: string;
+
+ // The price is imposed by the merchant and cannot be changed by the customer.
+ // This parameter is optional.
+ amount?: Amount;
+
+ // Minimum age buyer must have (in years). Default is 0.
+ minimum_age: Integer;
+
+ // The time the customer need to pay before his order will be deleted.
+ // It is deleted if the customer did not pay and if the duration is over.
+ pay_duration: RelativeTime;
+
+ }
+
+
+
+Editing templates
+-----------------
+
+
+.. http:patch:: [/instances/$INSTANCE]/private/templates/$TEMPLATE_ID
+
+ This is used to update a template.
+
+ **Request:**
+
+ The request must be a `TemplatePatchDetails`.
+
+ **Response:**
+
+ :http:statuscode:`204 No content`:
+ The template has successfully modified.
+ :http:statuscode:`404 Not found`:
+ The template(ID) is unknown to the backend.
+ :http:statuscode:`409 Conflict`:
+ The provided information is inconsistent with the current state of the template. Changes made is the same with
+ another store.
+
+
+ .. ts:def:: TemplatePatchDetails
+
+ interface TemplatePatchDetails {
+
+ // Human-readable description for the template.
+ template_description: string;
+
+ // A base64-encoded image selected by the merchant.
+ // This parameter is optional.
+ // We are not sure about it.
+ image?: ImageDataUrl;
+
+ // Additional information in a separate template.
+ template_contract: TemplateContractDetails;
+
+ }
+
+
+
+Inspecting template
+-------------------
+
+.. http:get:: [/instances/$INSTANCE]/private/templates
+
+ This is used to return the list of all the templates.
+
+
+ **Response:**
+
+ :http:statuscode:`200 OK`:
+ The backend has successfully returned all the templates. Returns a `TemplateSummaryResponse`.
+ :http:statuscode:`404 Not found`:
+ The backend has does not know about the instance.
+
+
+ .. ts:def:: TemplateSummaryResponse
+
+ interface TemplateSummaryResponse {
+
+ // List of templates that are present in our backend.
+ templates_list: TemplateEntry[];
+ }
+
+
+
+ The `TemplatesEntry` object describes a template. It has the following structure:
+
+
+
+ .. ts:def:: TemplateEntry
+
+ interface TemplateEntry {
+
+ // Template identifier, as found in the template.
+ template_id: string;
+
+ // Human-readable description for the template.
+ template_description: string;
+
+ }
+
+
+
+.. http:get:: [/instances/$INSTANCE]/private/templates/$TEMPLATE_ID
+
+ This is used to obtain detailed information about a specific template.
+
+
+ **Response:**
+
+ :http:statuscode:`200 OK`:
+ The backend has successfully returned the detailed information about a specific template.
+ Returns a `TemplateDetails`.
+ :http:statuscode:`404 Not found`:
+ The template(ID) is unknown to the backend.
+
+
+ .. ts:def:: TemplateDetails
+
+ interface TemplateDetails {
+
+ // Human-readable description for the template.
+ template_description: string;
+
+ // A base64-encoded image selected by the merchant.
+ // This parameter is optional.
+ // We are not sure about it.
+ image?: ImageDataUrl;
+
+ // Additional information in a separate template.
+ template_contract: TemplateContractDetails;
+ }
+
+
+
+Removing template
+-----------------
+
+.. http:delete:: [/instances/$INSTANCE]/private/templates/$TEMPLATE_ID
+
+ This is used to delete information about a template.
+
+ **Response:**
+
+ :http:statuscode:`204 No content`:
+ The backend has successfully deleted the template.
+ :http:statuscode:`404 Not found`:
+ The backend does not know the instance or the template.
+
+
+
+Using template
+----------------
+
+.. http:post:: [/instances/$INSTANCES]/templates/$TEMPLATE_ID
+
+ This using template can be modified by everyone and will be used to create order.
+
+
+ **Request:**
+
+ The request must be a `UsingTemplateDetails` and we accept JSON application and URL encoded.
+
+
+ **Response:**
+
+ :http:statuscode:`200 OK`:
+ The using template is successful. Returns a `UsingTemplateResponse`.
+ :http:statuscode:`302 Found`:
+ The client should go to the indicated location. Only returned if the content type was HTML. The target site may allow the client to pay his order.
+ :http:statuscode:`404 Not found`:
+ The merchant instance is unknown or the template is unknown.
+
+
+ .. ts:def:: UsingTemplateDetails
+
+ interface UsingTemplateDetails {
+
+ // Subject of the template
+ subject?: string;
+
+ // The amount entered by the customer.
+ amount?: Amount;
+ }
+
+
+ .. ts:def:: UsingTemplateResponse
+
+ interface UsingTemplateResponse {
+
+ // After enter the request. The user will be pay with a taler URL.
+ taler_url: string;
+ }
+
+
+
+
+
+
+
+--------
+Webhooks
+--------
+
+The webhook is a backend feature that is used to send a confirmation to the merchant. It can be send with a SMS, email or with another method. It will confirm that the
+customer paid the merchant. It will show the date and the price the customer paid.
+
+
+
+Adding webhooks
+---------------
+
+.. http:post:: [/instances/$INSTANCES]/private/webhooks
+
+ This is used to create a webhook.
+
+ **Request:**
+
+ The request must be a `WebhookAddDetails`.
+
+ **Response:**
+
+ :http:statuscode:`204 No content`:
+ The creation of the webhook is successsful.
+
+ :http:statuscode:`404 Not found`:
+ The merchant instance is unknowm or it not in our data.
+
+ .. ts:def:: WebhookAddDetails
+
+ interface WebhookAddDetails {
+
+ // Webhook ID to use.
+ webhook_id: string;
+
+ // The event of the webhook: why the webhook is used.
+ event_type: string;
+
+ // URL of the webhook where the customer will be redirected.
+ url: string;
+
+ // Method used by the webhook
+ http_method: string;
+
+ // Header template of the webhook
+ header_template?: string;
+
+ // Body template by the webhook
+ body_template?: string;
+
+ }
+
+
+Editing webhooks
+----------------
+
+.. http:patch:: [/instances/$INSTANCES]/private/webhooks/$WEBHOOK_ID
+
+ This is used to update a webhook.
+
+ **Request:**
+
+ The request must be a `WebhookPatchDetails`.
+
+ **Response:**
+
+ :http:statuscode:`204 No content`:
+ The webhook has successfully modified.
+ :http:statuscode:`404 Not found`:
+ The webhook(ID) is unknown to the backend.
+ :http:statuscode:`409 Conflict`:
+ The provided information is inconsistent with the current state of the webhook. Changes made is the same with another store.
+
+ .. ts:def:: WebhookPatchDetails
+
+ interface WebhookPatchDetails {
+
+ // The event of the webhook: why the webhook is used.
+ event_type: string;
+
+ // URL of the webhook where the customer will be redirected.
+ url: string;
+
+ // Method used by the webhook
+ http_method: string;
+
+ // Header template of the webhook
+ header_template?: string;
+
+ // Body template by the webhook
+ body_template?: string;
+
+ }
+
+
+
+Inspecting webhook
+------------------
+
+.. http:get:: [/instances/$INSTANCES]/private/webhooks
+
+ This is used to return the list of all the webhooks.
+
+ **Response:**
+
+ :http:statuscode:`200 OK`:
+ The backend has successfully returned all the webhooks. Returns a `WebhookSummaryResponse`.
+
+ :http:statuscode:`404 Not found`:
+ The backend has does not know about the instance.
+
+ .. ts:def:: WebhookSummaryResponse
+
+ interface WebhookSummaryResponse {
+
+ // List of webhooks that are present in our backend.
+ webhooks_list: WebhookEntry[];
+
+ }
+
+ The WebhookEntry object describes a webhook. It has the following structure:
+
+ .. ts:def:: WebhookEntry
+
+ interface WebhookEntry {
+
+ // Webhook identifier, as found in the webhook.
+ webhook_id: string;
+
+ // The event of the webhook: why the webhook is used.
+ event_type: string;
+
+ }
+
+
+.. http:get:: [/instances/$INSTANCES]/private/webhooks/$WEBHOOK_ID
+
+ This is used to obtain detailed information about apecific template.
+
+ **Response:**
+
+ :http:statuscode:`200 OK`:
+ The backend has successfully returned the detailed information about a specific webhook. Returns a `WebhookDetails`.
+
+ :http:statuscode:`404 Not found`:
+ The webhook(ID) is unknown to the backend.
+
+
+ .. ts:def:: WebhookDetails
+
+ interface WebhookDetails {
+
+ // The event of the webhook: why the webhook is used.
+ event_type: string;
+
+ // URL of the webhook where the customer will be redirected.
+ url: string;
+
+ // Method used by the webhook
+ http_method: string;
+
+ // Header template of the webhook
+ header_template?: string;
+
+ // Body template by the webhook
+ body_template?: string;
+
+ }
+
+
+Removing webhook
+-----------------
+
+.. http:delete:: [/instances/$INSTANCES]/private/webhooks/$WEBHOOK_ID
+
+ This is used to delete information about a webhook.
+
+ **Response:**
+
+ :http:statuscode:`204 No content`:
+ The backend has successfully deleted the webhook.
+
+ :http:statuscode:`404 Not found`:
+ The webhook(ID) or the instance is unknown to the backend.
+
+
+
------------------
The Contract Terms
------------------
diff --git a/core/api-sync.rst b/core/api-sync.rst
index 759a4c3..51e429e 100644
--- a/core/api-sync.rst
+++ b/core/api-sync.rst
@@ -103,13 +103,15 @@ user's location profiles by linking client IP addresses and client
keys.
---------------------------
-Receiving Terms of Service
---------------------------
+.. include:: tos.rst
+
+-----------------------
+Receiving Configuration
+-----------------------
.. http:get:: /config
- Obtain the terms of service provided by the storage service.
+ Obtain the key configuration settings of the storage service.
**Response:**
@@ -137,9 +139,12 @@ Receiving Terms of Service
}
-
.. _sync:
+----------------------
+Recovering Backup Data
+----------------------
+
.. http:get:: /backups/${ACCOUNT-KEY}
Download latest version of the backup.
@@ -200,6 +205,10 @@ Receiving Terms of Service
signature validation.
+---------------------
+Uploading Backup Data
+---------------------
+
.. http:post:: /backups/${ACCOUNT-KEY}
Upload a new version of the account's database, or download the
diff --git a/core/api-taldir.rst b/core/api-taldir.rst
index 2e84625..88fe5ce 100644
--- a/core/api-taldir.rst
+++ b/core/api-taldir.rst
@@ -34,48 +34,8 @@ for all details not specified in the individual requests.
The `glossary <https://docs.taler.net/glossary.html#glossary>`_
defines all specific terms used in this section.
---------------------
-Terms of service API
---------------------
-
-These APIs allow wallets to obtain the terms of service
-and the privacy policy of the TalDir.
-
-
-.. http:get:: /terms
-
- Get the terms of service of the TalDir.
- The TalDir will consider the "Accept" and "Accept-Language" and
- "Accept-Encoding" headers when generating a response. Specifically,
- it will try to find a response with an acceptable mime-type, then
- pick the version in the most preferred language of the user, and
- finally apply compression if that is allowed by the client and
- deemed beneficial.
-
- The TalDir will set an "Etag", and subsequent requests of the
- same client should provide the tag in an "If-None-Match" header
- to detect if the terms of service have changed. If not, a
- "204 Not Modified" response will be returned.
-
- If the "Etag" is missing, the client should not cache the response and instead prompt the user again at the next opportunity. This is usually only the case if the terms of service were not configured correctly.
-
-
-.. http:get:: /privacy
-
- Get the privacy policy of the TalDir.
- The TalDir will consider the "Accept" and "Accept-Language" and
- "Accept-Encoding" headers when generating a response. Specifically,
- it will try to find a response with an acceptable mime-type, then
- pick the version in the most preferred language of the user, and
- finally apply compression if that is allowed by the client and
- deemed beneficial.
-
- The TalDir will set an "Etag", and subsequent requests of the
- same client should provide the tag in an "If-None-Match" header
- to detect if the privacy policy has changed. If not, a
- "204 Not Modified" response will be returned.
- If the "Etag" is missing, the client should not cache the response and instead prompt the user again at the next opportunity. This is usually only the case if the privacy policy was not configured correctly.
+.. include:: tos.rst
-------------------------
diff --git a/core/api-wire.rst b/core/api-wire.rst
index 63373f6..34c0a0f 100644
--- a/core/api-wire.rst
+++ b/core/api-wire.rst
@@ -327,6 +327,8 @@ Wire Transfer Test APIs
Endpoints in this section are only used for integration tests and never
exposed by bank gateways in production.
+.. _twg-admin-add-incoming:
+
.. http:post:: ${BASE_URL}/admin/add-incoming
Simulate a transfer from a customer to the exchange. This API is *not*
diff --git a/core/taler-uri.rst b/core/taler-uri.rst
index 80e8c7a..7b897ba 100644
--- a/core/taler-uri.rst
+++ b/core/taler-uri.rst
@@ -68,7 +68,7 @@ The action ``withdraw`` is used to trigger a bank-integrated withdrawal operatio
taler://withdraw/{bank_host}{/bank_prefix_path*}/{withdrawal_uid}{#ssid}
-* ``bank_host`` is the hostname of the merchant.
+* ``bank_host`` is the hostname of the bank.
* ``bank_prefix_path`` is an optional list of path components that identifies the path prefix of the bank integration API base URL.
* ``withdrawal_uid`` is the unique ID of the withdrawal operation.
* ``ssid`` is the optional WLAN SSID that the bank (typically in an ATM scenario) can offer the wallet
@@ -121,8 +121,6 @@ a merchant and ask the user to accept/decline it.
* ``merchant_host`` is the hostname of the merchant.
* ``merchant_prefix_path`` is an optional list of path components that identifies the path prefix of the merchant base URL.
* ``tip_id`` uniquely identifies the tip.
-* ``insecure`` is an optional query parameter. When "1", the ``merchant_host`` is contacted via HTTP.
- When absent or "0", the ``merchant_host`` is contacted via HTTPS.
* ``ssid`` is the optional WLAN SSID that the merchant can offer the wallet to connect to for Internet connectivity.
@@ -130,13 +128,18 @@ a merchant and ask the user to accept/decline it.
Peer-to-peer payments
---------------------
-A ``taler://pay-push/{exchange_host}{/exchange_prefix_path*}/{contract_priv}`` URI
-instructs the wallet to accept a P2P push payment.
+A pay-push URI instructs the wallet to accept a P2P push payment.
+
+.. code:: none
+
+ taler://pay-push/{exchange_host}{/exchange_prefix_path*}/{contract_priv}
* ``exchange_host`` is the hostname of the exchange.
* ``exchange_prefix_path`` is an optional list of path components that identifies the path prefix of the exchange base URL.
* ``contract_priv`` is the private key of the peer push payment contract stored at the exchange
+FIXME: pay-pull URIs missing!
+
----------------
Adding exchanges
----------------
diff --git a/core/tos.rst b/core/tos.rst
new file mode 100644
index 0000000..0cdb898
--- /dev/null
+++ b/core/tos.rst
@@ -0,0 +1,42 @@
+--------------------
+Terms of service API
+--------------------
+
+These APIs allow clients to obtain the terms of service
+and the privacy policy of a service.
+
+
+.. http:get:: /terms
+
+ Get the terms of service of the service.
+ The endpoint will consider the "Accept" and "Accept-Language" and
+ "Accept-Encoding" headers when generating a response. Specifically,
+ it will try to find a response with an acceptable mime-type, then
+ pick the version in the most preferred language of the user, and
+ finally apply compression if that is allowed by the client and
+ deemed beneficial.
+
+ The endpoint will set an "Etag", and subsequent requests of the same client
+ should provide the tag in an "If-None-Match" header to detect if the terms
+ of service have changed. If not, a "304 Not Modified" response will be
+ returned. Note that the "304 Not Modified" will also be returned if the
+ client changed the "Accept-Language" or "Accept-Encoding" header. Thus, if
+ the client would like to download the resource in a different language or
+ format, the "If-None-Match" header must be omitted.
+
+ If the "Etag" is missing, the client should not cache the response and
+ instead prompt the user again at the next opportunity. This is usually only
+ the case if the terms of service were not configured correctly.
+
+ When returning a full response (not a "304 Not Modified"), the server
+ should also include a "Acceptable-Languages" header which includes
+ a space-separated list of the languages in which the terms of service
+ are available in. Clients can use this to generate a language switcher
+ for users that may not have expressed a proper language preference.
+
+
+.. http:get:: /privacy
+
+ Get the privacy policy of the service. Behaves the same way as
+ The "/terms" endpoint, except that it returns the privacy policy
+ instead of the terms of service.
diff --git a/demo-deployment.rst b/demo-deployment.rst
index 820b7d0..2f0b5a0 100644
--- a/demo-deployment.rst
+++ b/demo-deployment.rst
@@ -1,44 +1,10 @@
This document explains how to install Taler+LibEuFin
on gv.taler.net, for demo.taler.net.
-The installation uses deployment.git/bin/taler-gv, which
-offers the following subcommands:
+1. Login as the ``demo`` user on ``gv.taler.net``.
+2. Pull the latest ``deployment.git`` code.
+3. Navigate to the ``deployment.git/docker/demo`` directory.
+4. The README file is the reference about building and running the services.
-* bootstrap
-* build
-* prepare
-* launch
-* stop
-
-How to install
---------------
-1. python3 taler-gv bootstrap
-2. python3 taler-gv build
-3. python3 taler-gv prepare
-
-If everything worked, then launch all the services
-with:
-
-4. python3 taler-gv launch
-
-Configuration files
--------------------
-The 'prepare' subcommand generate all the configuration files
-and put them in $HOME/config. NOTE: at this point, the Python
-demo sites are ignoring the '-c' flag and *still* accessing the
-config file at $HOME/.config/taler.conf, which is now a symlink
-to $HOME/config/taler.conf.
-
-Logging
--------
-Logging files are placed into logs/, but _some_ logging may
-still be found through SystemD.
-
-Sources
--------
-Downloaded by the 'bootstrap' subcommand into $HOME/sources.
-
-Process manager
----------------
-SystemD is the process manager, invoked at prepare/launch/stop
-subcommands.
+Nginx is already configured to reach the services as exported by
+Docker Compose.
diff --git a/design-documents/006-extensions.rst b/design-documents/006-extensions.rst
index 576809a..9dde065 100644
--- a/design-documents/006-extensions.rst
+++ b/design-documents/006-extensions.rst
@@ -18,6 +18,7 @@ of 2021 and 2022:
* Peer-to-peer payments
* Anonymous age-restriction
* Escrow service for anonymous auctions
+* A general escrow service
We call a feature an *extension* when it is *optional* for either the
exchange, wallet or merchant to enable and support it. (However, enabling
@@ -47,17 +48,17 @@ The exchange will add two new *optional* fields in response to ``/keys``:
SHA256-hash of the normalized JSON-string of the ``extensions`` object.
-The necessary changes to ``ExchangeKeysResponse`` are highlighted here:
+The necessary changes to ``ExtensionsManifestsResponse`` are highlighted here:
-.. ts:def:: ExchangeKeysResponse
+.. ts:def:: ExtensionsManifestsResponse
- interface ExchangeKeysResponse {
+ interface ExtensionsManifestsResponse {
//...
// Optional field with a dictionary of (name, object) pairs defining the
// supported and enabled extensions.
// The name MUST be non-empty and unique.
- extensions?: { name: Extension };
+ extensions?: { name: ExtensionManifest };
// Signature by the exchange master key of the SHA-256 hash of the
// normalized JSON-object of field ``extensions``, if it was set.
@@ -80,11 +81,11 @@ GANA_ along with a full description of the extension.
versions of the "same" feature in parallel, multiple unique names MUST be used,
f.e. ``age_restriction`` an ``age_restriction.v2``.)
-Extension object
-----------------
+ExtensionManifest object
+---------------------------
-The definition of ``Extension`` object itself is mostly up to the particular
-feature. **However**, it MUST have
+The definition of ``ExtensionManifest`` object itself is mostly up to the
+particular feature. **However**, it MUST have
#. the boolean field ``critical`` that has the same semantics as as "critical"
has for extensions in X.509_: if true, the client must "understand" the
@@ -98,10 +99,9 @@ feature. **However**, it MUST have
.. _`protocol version ranges notation`: https://docs.taler.net/core/api-common.html#protocol-version-ranges
+.. ts:def:: ExtensionManifest
-.. ts:def:: Extension
-
- interface Extension {
+ interface ExtensionManifest {
// The criticality of the extension MUST be provided. It has the same
// semantics as "critical" has for extensions in X.509:
// - if "true", the client must "understand" the extension before
@@ -180,7 +180,9 @@ this:
AGE_GROUPS = "8:10:12:14:16:18:21"
-* TODO: Add examples for p2p.
+ [exchange-extension-policy_brandt_vickery_auction]
+ ENABLED = true
+ REPLAY_PROGRAM = "/usr/local/bin/taler-exchange-auction_replay"
Merchant
@@ -190,6 +192,16 @@ TODO:
* Needs to express support for particular extensions, too. F.e. age-restriction.
+Extension Plugins
+==================
+
+TODO:
+
+* describe ``struct TALER_Extension``
+* describe the plugin loading mechanism for extensions
+* describe the various handlers
+
+
Alternatives
============
diff --git a/design-documents/024-age-restriction.rst b/design-documents/024-age-restriction.rst
index 6b1004f..b394a42 100644
--- a/design-documents/024-age-restriction.rst
+++ b/design-documents/024-age-restriction.rst
@@ -151,7 +151,7 @@ registering the extension ``age_restriction`` with a value type
interface ConfigAgeRestriction {
// The age groups. This field is mandatory and binding in the sense
// that its value is taken into consideration when signing the
- // denominations in `ExchangeKeysResponse`.``age_restricted_denoms``.
+ // age restricted denominations in the `ExchangeKeysResponse`
age_groups: AgeGroups;
}
diff --git a/design-documents/028-deposit-policies.rst b/design-documents/028-deposit-policies.rst
new file mode 100644
index 0000000..d0a1b10
--- /dev/null
+++ b/design-documents/028-deposit-policies.rst
@@ -0,0 +1,188 @@
+DD28: Deposit Policy Extensions
+###############################
+
+.. note::
+
+ This is Work-In-Progress.
+
+Summary
+*******
+
+We will propose here a plugable mechanism in the exchange to support deposits
+with associated policy. An exchange can enable support for such policies via
+configuration.
+
+The inital set of policy extensions that an exchange might provide consists of
+
+Merchant refunds
+ Merchant can grant customers refundable payments. In this case, the
+ amount of the deposit is put into escrow by the exchange for a certain
+ period until which the customer can claim a refund.
+
+Escrowed payments
+ A trustor puts coins into escrow with the exchange. It can be claimed
+ by a beneficiary until a certain deadline, when the claim is signed by
+ both, the beneficiary's and the trustor's keys.
+
+Brandt-Vickrey auctions
+ A bidder puts coins into escrow with the exhange in order to
+ participate in an Brandt-Vickrey auction. The deposit confirmation is
+ proof to the seller for the escrow and contains a hash of the auction
+ meta-data and a deadline. After successfull execution of the auction,
+ the seller provides a valid transcript to the exchange from which the
+ exchange learns which bidder(s) won the auction for which prices. It
+ then transfers the amounts from the winners' coins to the seller. In
+ case of a timeout and for all losing bidders, the coins can be
+ refreshed.
+
+The policies shall be implemented as *extensions* to the exchange (see
+:doc:`006-extensions`).
+
+Motivation
+**********
+
+TODO
+
+Background and Requirements
+***************************
+
+TODO
+
+Proposed Solution
+*****************
+
+TODO, explain:
+
+- C-structs for policy extensions (esp. the handlers)
+- Naming conventions for policy extensions
+- Deadlines and -handling
+- API-endpoints (``/extensions/policy_...``)
+- Typical choreography of a deposit with policy and its fulfillment
+
+Database-schema
+===============
+
+TODO: Description
+
+.. graphviz::
+
+ digraph deposit_policies {
+ rankdir = LR;
+ splines = false;
+ fontname="monospace"
+ node [
+ fontname="monospace"
+ shape=record
+ ]
+
+ subgraph cluster_deposits {
+ label=<<B>deposits</B>>
+ margin=20
+ deposits [
+ label="...|<ref>policy_details_id (null)\l|...|timestamp\l|..."
+ ]
+ }
+
+ subgraph cluster_policy_details {
+ label=<<B>policy_details</B>>
+ margin=20
+ policy_details [
+ label="<id>id\l|<hash>policy_hash_code (unique)\l|deadline\l|commitment (amount)\l|accumulated_total (amount)\l|fee (amount)\l|transferable (amount)\l|fulfillment_state\l|<fid>fulfillment_id (null)\l"
+ ]
+ }
+
+ subgraph cluster_policy_fulfillments {
+ label=<<B>policy_fulfillments</B>>
+ margin=20
+ rank=min;
+ policy_fulfillments [
+ label="<id>id\l|proof\l|timestamp\l|<codes>policy_hash_codes (blob)\l"
+ ]
+ }
+
+ deposits:ref->policy_details:id [ label="n:1"; fontname="monospace" ];
+ policy_details:fid->policy_fulfillments:id [label="n:1"; fontname="monospace" ];
+ }
+
+
+The field ``policy_hash_codes`` in table ``policy_fulfillments`` is a binary
+blob that consists of the concatenation of the sorted
+``policy_details.policy_hash_code`` entries from all policies that are fulfilled by
+this proof.
+
+
+Policy Fulfillment States
+=========================
+
+The fulfillment of a policy can be in one of the following five states:
+
+Ready
+ The policy is funded and ready. The exchange is waiting for a proof of
+ fulfillment to arrive before the deadline.
+
+Insufficient
+ The policy lacks funding, that is ``accumulated_total`` <
+ ``commitment``, but has otherwise been accepted. Funding can be
+ continued by calling ``/deposit`` or ``/batch-deposit`` with more coins
+ and the same policy details.
+
+Success
+ The policy is provably fulfilled. The amounts for payout, fees and
+ refresh are transfered/can be claimed. Note that a policy fulfillment
+ handler can change the values for the amounts for payout, fees and
+ refresh.
+
+Timeout
+ The policy has timed out. The amounts for payout and refresh are
+ transfered/can be claimed.
+
+Failure
+ The policy is in an failure state. Payouts and refreshes are
+ blocked, timeouts are ignored.
+
+
+
+Invariants
+^^^^^^^^^^
+
+The following invariants need to be fulfilled and be checked by the auditor:
+
+- The fulfillment state of a policy is **Insufficient** IF AND ONLY IF the
+ amount in ``policy_details.commitment`` is equal or larger than the amount in
+ ``policy_details.accumulated_total``.
+
+- The sum of amounts in ``policy_details.fee`` and
+ ``policy_details.transferable`` MUST be equal or less than the amount in
+ ``policy_details.accumulated_total``.
+
+- The amount in ``policy_details.accumulated_total`` MUST be equal to the total
+ sum of contributions of the individual coins of the deposits that reference
+ this policy.
+
+- Each hash code encoded in ``policy_fulfillments.policy_hash_codes`` MUST
+ refer to an existing ``policy_details.hash_code`` AND its ``.fulfillment_id``
+ MUST point to the same ``policy_fulfillments.id``.
+
+- Conversely: If a ``policy_details.fulfillment_id`` points to an entry in
+ ``policy_fulfillment``, the ``policy_details.policy_hash_code`` MUST be
+ present in that entry's ``.policy_hash_codes``.
+
+
+
+Alternatives
+============
+
+TODO
+
+Drawbacks
+=========
+
+TODO
+
+
+Discussion / Q&A
+================
+
+TODO
+
+(This should be filled in with results from discussions on mailing lists / personal communication.)
diff --git a/design-documents/028-proof-of-escrow.rst b/design-documents/028-proof-of-escrow.rst
deleted file mode 100644
index 402ddd2..0000000
--- a/design-documents/028-proof-of-escrow.rst
+++ /dev/null
@@ -1,128 +0,0 @@
-DD28: Proof of escrow in the exchange
-#####################################
-
-.. note::
-
- This design document is currently a draft, it
- does not reflect any implementation decisions yet.
-
-
-Summary
-=======
-
-We propose here an extension to the exchange: An escrow service that can be
-used by other, separate trading services f.e. for online auctions.
-
-
-Motivation
-==========
-
-Certain types of trade, such as auctions or trades with long phases of
-negotiation, require a proof of escrow of money as a guarantee in order to
-participate or perform the trade.
-
-We want to extend GNU Taler to support trades such as anonymous sealed-bid
-auctions. While the auction service will be a separate (from the exchange)
-entity, behaving in parts like a normal merchant in the GNU Taler sense, the
-exchange itself can provide an escrow services.
-
-Background and Requirements
-===========================
-
-An escrow service is a intermediary between two parties and must trusted by
-both. In the GNU Taler payment system, this role is per definition played by
-the exchange for buyers and sellers during purchases. The auditor controls the
-exchange and is also a mediator between buyers and selles.
-
-The role of the exchange can be therefore extended to the specific needs of
-escrow. In contrast to purchase/deposit, for escrow, particular coins are
-locked, but not spent. This prohibits their spending for a specific timespan
-and until a valid order of release is provided.
-
-However, in the context of auctions, we want the parties to be able to verify
-the fairness of the participants. For example, a seller of goods during an
-auction shall only be able to release the money for the winning bidder and not
-for the others. On the other hand, both, sellers and bidders should be able
-provide evidence to the exchange and auditor if the other party wasn't honest,
-f.e. if the winning bidder hasn't released the money.
-
-
-
-Proposed Solution
-=================
-
-We propose a the following endpoints
-
-
-- ``POST /escrows/$ESCROW_ID/register``: Register an escrow account under the
- provided EdDSA public key ``$ESCROW_ID``. The required parameters are:
-
- - a starttime
- - an endttime
- - an interval ``[m, M]`` of minimum and maximum amounts, where ``M`` can also be ``∞``.
-
-- ``GET /escrows/$ESCROW_ID``: Return the terms of the escrow and the current
- list of depositor IDs.
-
-- ``POST /escrows/$ESCROW_ID/deposit/$DEPOSIT_ID``: Deposit a specific amount
- with a particular list of coins. The required parameters are:
-
- - the amount ``a`` to be deposited (must lie in ``[m, M]``)
- - the list of coins to be used for the deposit (the sum of the values must be
- at least ``a``)
- - signatures from each coin over the SHA512 hash of the amount ``a``, the
- ``$DEPOSIT_ID`` and the ``$ESCROW_ID``.
-
- The ``$DEPOSIT_ID`` is the SHA512 hash over all the coins.
-
-
-- ``POST /escrows/$ESCROW_ID/claim/$DEPOSIT_ID``: The owner of the private key for
- ``$ESCROW_ID`` can claim the deposited coins. It has to provide
-
- - the particular amount ``a'`` to be claimed
- - the list of coins to be claimed from the deposit
- - signatures over the SHA512 hash of the amount ``a'``, ``$ESCROW_ID`` and
- the ``$DEPOSIT_ID``, signed by each coin
-
-The following diagram gives an overview of the flow:
-
-.. image:: _svgs/escrow-flow.svg
-
-
-When the ``endtime`` of an escrow has arrived on the exchange, an amount ``a``
-of a deposit of amount ``b ≥ a`` can be claimed by the originator of the escrow
-account. Only *one* successful claim can be made for a particular escrow
-account. After a claim has been made, the remaining coins in the remaining
-deposits are released by the exchange. If no claim is made within a specific
-time interval after ``endtime``, all coins of *all* deposits are released.
-
-The ``GET /escrows/$ESCROWS_ID`` allows to depositors and auditors to confirm
-their deposit. It also allows depositors to compare the list with their
-mentioning at other services, such as the list of bidders in an online auction.
-
-TODOs: Specify
-
-- data structures
-- signatures
-- return values
-- errors
-- terms of contracts
-- default time intervals
-
-Alternatives
-============
-
-TODO
-
-Drawbacks
-=========
-
-TODO
-
-
-Discussion / Q&A
-================
-
-TODO
-
-(This should be filled in with results from discussions on mailing lists / personal communication.)
diff --git a/design-documents/032-auctions.rst b/design-documents/032-brandt-vickrey-auctions.rst
index 0f14498..52a46cc 100644
--- a/design-documents/032-auctions.rst
+++ b/design-documents/032-brandt-vickrey-auctions.rst
@@ -1,5 +1,5 @@
-DD32: Auctions
-##############
+DD32: Brandt-Vickrey Auctions
+#############################
Summary
=======
@@ -9,6 +9,9 @@ funds held in escrow by a Taler exchange. It is taking major inspiration from
Markus Teich's Master's thesis on "Implementing Privacy Preserving Auction
Protocols".
+The support for these types of auctions will be in the form of an extension for
+a deposit policy.
+
Motivation
==========
@@ -98,10 +101,10 @@ the auction:
as paying any other merchant and thus out of scope for this
design document.
- * An exchange that supports the ``auction`` extension and holds
- the funds for bids in escrow for the duration of the auction.
- Upon completion of the auction, the exchange pays the seller
- from the auction's winner and refunds the other bidders.
+ * An exchange that supports the ``policy_vickrey_auction`` extension and
+ holds the funds for bids in escrow for the duration of the auction. Upon
+ completion of the auction, the exchange pays the seller from the auction's
+ winner and refunds the other bidders.
* An auditor that verifies that the exchange made the payments
correctly.
@@ -140,19 +143,20 @@ bid.
The auction operator then runs the auction protocol with all participants
until conclusion. Once the winner and price have been determined, the auction
-operator POSTs the resulting transcript to a new ``/extensions/auction``
-endpoint of the exchange. Here, the extension-specific logic stores the
-transcript in its database (in a new table) and then simulates the auction
-again (using libbrandt), again determining the winner and price. The
-extension configuration (and thus ``/keys``) may stipendulate some fee(s)
-charged by the exchange to handle the ``/extensions/auction`` request. The
-fees should be covered by the seller. We note that the transcript inherently
-contains the deposit confirmations originally issued by the exchange for the
-auction. So, the exchange can identify all of the coins that were escrowed (it
-should also double-check that the coins were escrowed for the correct
-auction). It then refunds the bids from the loosing bidders, pays the price
-to the seller from the winner (minus auction fee), and partially refunds the
-winner the difference between the escrowed amount and the winning bid.
+operator POSTs the resulting transcript to a new
+``/extensions/policy_brandt_vickrey_auction`` endpoint of the exchange. Here,
+the extension-specific logic stores the transcript in its database (in a new
+table) and then simulates the auction again (using libbrandt), again
+determining the winner and price. The extension configuration (and thus
+``/keys``) may stipendulate some fee(s) charged by the exchange to handle the
+``/extensions/policy_brandt_vickrey_auction`` request. The fees should be
+covered by the seller. We note that the transcript inherently contains the
+deposit confirmations originally issued by the exchange for the auction. So,
+the exchange can identify all of the coins that were escrowed (it should also
+double-check that the coins were escrowed for the correct auction). It then
+refunds the bids from the loosing bidders, pays the price to the seller from
+the winner (minus auction fee), and partially refunds the winner the difference
+between the escrowed amount and the winning bid.
.. note::
@@ -174,6 +178,80 @@ transactions.
The auditor of the exchange can again simulate the auction protocol and can
thus confirm that the exchange's ultimate transactions were correct.
+Transcripts
+^^^^^^^^^^^
+
+A transcript of a Brandt-Vickrey auction is the JSON encoding of an object of
+type `BrandtVickreyAuctionTranscript`.
+
+ .. ts:def:: BrandtVickreyAuctionTranscript
+
+ // This structure defines the transcript of an auction of Brandt-Vickrey kind.
+ interface BrandtVickreyAuctionTranscript {
+ // The auction definition.
+ auction: BrandtVickreyAuction;
+
+ // The public keys of the bidders, in Crockford Base32 encoding.
+ bidders: EddsaPublicKey[];
+
+ // Signatures of the auction in Crockford Base32 encoding.
+ // One signature per bidder.
+ signatures: EddsaSignature[];
+
+ // List of policy hash codes that identify policy details associated with
+ // each bidder. Those codes were generated by the policy extension
+ // policy_brandt_vickrey_auction during the deposit of coins for this
+ // auction.
+ policy_hash_codes: HashCode[];
+
+ // The transcript of all messages received by the seller.
+ transcript: BrandtVickreyAuctionMessage[];
+
+ // Optionally, the seller can provide the winners it had calculated.
+ winners?: BrandtVickreyAuctionWinner[];
+
+ // The signature over the hash of this JSON object, without the
+ // key ``sig`` and in normalized form, basically over
+ // H(auction, bidders, signatures, transcripts, winners?)
+ // It is signed by the private key that corresponds to the public key
+ // in `BrandtVickreyAuction`.``pubkey``.
+ // This signature is in Crockford Base32 encoding.
+ sig: EddsaSignature;
+ }
+
+
+ .. ts:def:: BrandtVickreyAuctionMessage
+
+ interface BrandtVickreyAuctionMessage {
+ // The index of the bidder into the
+ // `BrandtVickreyAuctionTranscript`.``bidders`` array.
+ bidder: number;
+
+ // The raw message in Crockford Base32 encoding.
+ msg: string;
+
+ // The signature over the message. The signature is in Crockford Base32
+ // encoding. It must be signed by the private key corresponding to the
+ // bidder's public key in `BrandtVickreyAuctionTranscript`.``bidders``.
+ sig: EddsaSignature;
+ }
+
+
+
+ .. ts:def:: BrandtVickreyAuctionWinner
+
+ interface BrandtVickreyAuctionWinner {
+ // The index of the bidder into the
+ // `BrandtVickreyAuctionTranscript`.bidder array.
+ bidder: number;
+
+ // The index of the winning price into the
+ // `BrandtVickreyAuction`.prices array.
+ price_idx: number;
+
+ // The winning price
+ price: Amount;
+ }
Alternatives
diff --git a/design-documents/033-database.rst b/design-documents/033-database.rst
new file mode 100644
index 0000000..ec91f6d
--- /dev/null
+++ b/design-documents/033-database.rst
@@ -0,0 +1,152 @@
+Database Schema and Versioning
+##############################
+
+Summary
+=======
+
+This document describes how we version database schema in GNU Taler
+and enable migrations.
+
+
+Motivation
+==========
+
+As Taler evolves, it will be necessary to add new tables, change existing
+tables, modify indices and make other changes to the database schema. As
+production systems exist, existing data will need to be migrated to the new
+schema, and we need to do this in a systematic way. While certain major
+changes may require radical or manual interventions, we should have a
+systematic way of dealing with minor or modest modifications to the schema.
+
+
+Requirements
+============
+
+* The approach should be language-independent
+* Schema migration should be reasonably performant
+* Schema migration must be usable, and in particular safe to use for
+ operators without significant risk
+* We need to support key database features we might need to use,
+ such as partitioning or sharding
+
+
+Proposed Solution
+=================
+
+We use the "versioning.sql" system to store the current set of patches that
+have been applied to the database so far in a "_v" schema. This allows us to
+quickly test which version of the database we are on and which migrations may
+still need to be applied.
+
+For each component, all tables are placed into a SCHEMA named after the
+component.
+
+We then use a set of numbered SQL files that create, alter or drop tables and
+indices (like exchange-0001.sql, exchange-0002.sql, ...) to setup the
+database. However, some setups need additional arguments, such as the number
+of partitions. Those setups are then NOT performed explicitly, but by creating
+stored procedures and registering those stored procedures in a general global
+"master" table to be called from the main setup logic with arguments in a
+particular order under certain conditions.
+
+When setting up a database, there is no point in incrementally defining
+ordinary stored procedures that are used at runtime (not the ones to setup the
+tables we talked about above). Thus, all of the stored procedures used by the
+runtime system are placed in a file "procedures.sql" which is loaded
+last. This makes changes to stored procedures particularly easy, as one simply
+edits "procedures.sql". Loading "procedures.sql" also does not change "_v".
+
+A "drop.sql" file is created that DROPs the main SCHEMA of the component and
+additionally unregisters all patches from the "_v" schema. The drop script
+is run during tests to fully reset the database.
+
+Exchange details
+^^^^^^^^^^^^^^^^
+
+The exchange uses "exchange_tables" to create the master
+table mentioned above. In "exchange_tables", entries are
+executed in the order of the "table_serial_id". Each
+entry has a "name", which is the name of the affected table
+(or at least the prefix in the case of partitioned or sharded
+tables). The "version" field stores which "exchange-XXXX.sql"
+file setup the respective table entry, but is for now mostly
+for internal documentation. The "action" defines both the
+condition under which to run a function. Specifically,
+actions can be:
+
+* create --- run on the master table and each shard; used to create or alter the main table
+* constrain --- run only on the partitions/shards, or on master if there are no partitions; used to setup constraints like uniqueness that only apply to the lowest levels of the table
+* master -- run only on the master table; used to setup triggers and other constraints that only apply to the master table
+* foreign -- run only on the master table and only if there are no partition; used to setup foreign key constraints that are not supported on partitioned or sharded tables
+
+The "partitioned" field indicates that this table is partitioned and instructs the functions to create partitions (or shards)
+for this table.
+
+The "by_range" field indicates if the table is partitioned by
+range, which prevents automatic generation of partitions as
+is done if partitioned by hash.
+
+The "finished" field is initially false, but set to TRUE once the respective
+function has been executed.
+
+The main "do_create_tables" function triggers the unfinished actions
+registered in the "exchange_tables" table. It is given arguments to control
+the number of partitions, the use of partitions and (in the future) the use of
+sharding.
+
+The individual actions use helper functions ("create_partitioned_table",
+"comment_partitioned_table" and "comment_partitioned_column") to facilitate
+the creation of tables and associated comments. These functions are used so
+that we can only define the schema or comment once, and have it applied to
+tables with names and creation syntax that changes slightly if we use shards
+or partitions.
+
+Some additional logic will be needed to deal nicely with
+sharding (which is currently not supported), as with
+sharing we will need to detach shards, migrate shards, and
+re-attach shards. So this will require additional stored
+procedures to support operations on shards.
+
+
+Merchant details
+^^^^^^^^^^^^^^^^
+
+The merchant does not (yet) need any type of master table, as we do not
+(yet) use any kind of sharding or partitioning. There are also no
+stored procedures being used by the backend. Hence, it is simply the
+"versioning.sql"-controlled table creation/alteration sequence
+(merchant-0001.sql, etc.) and the "drop.sql" to reset everything.
+
+
+Alternatives
+============
+
+* We might want to consider storing more meta-data
+ in the database, such as the use of sharding, the
+ names of the shard servers, or even just the number
+ of partitions.
+
+* We could require dumping out the old database and
+ loading it in via some explicit importer during each
+ migration; having migration logic in C would enable more
+ powerful migrations, but dumping and reloading the entire
+ database would also be more expensive. It would have the
+ advantage of basically having the old database around in
+ case of migration trouble, so the cost disadvantage might
+ not be so bad (as admins are likely to make a backup anyway).
+ OTOH, doing the migration with the equivalent of a
+ taler-auditor-sync would require quite a bit more code
+ than the simple ALTER/CREATE statements in an SQL file.
+
+
+Drawbacks
+=========
+
+* not exactly trival logic
+* some complexity to implement
+
+
+Discussion / Q&A
+================
+
+(This should be filled in with results from discussions on mailing lists / personal communication.)
diff --git a/design-documents/index.rst b/design-documents/index.rst
index 1ed8fff..2305bbe 100644
--- a/design-documents/index.rst
+++ b/design-documents/index.rst
@@ -36,9 +36,9 @@ and protocol.
025-withdraw-from-wallet
026-refund-fees
027-sandboxing-taler.rst
- 028-proof-of-escrow
+ 028-deposit-policies
029-mobile-ui
030-offline-payments
031-invoicing
- 032-auctions
+ 032-brandt-vickrey-auctions
999-template
diff --git a/extract-tsdefs/.gitignore b/extract-tsdefs/.gitignore
new file mode 100644
index 0000000..fa29880
--- /dev/null
+++ b/extract-tsdefs/.gitignore
@@ -0,0 +1,3 @@
+extract.js
+node_modules/
+dist
diff --git a/extract-tsdefs/README.md b/extract-tsdefs/README.md
new file mode 100644
index 0000000..e668be8
--- /dev/null
+++ b/extract-tsdefs/README.md
@@ -0,0 +1,8 @@
+# Auto-generated wallet-core API docs
+
+Usage:
+```
+pnpm install
+pnpm run compile
+node dist/extract.js $WALLET_CORE_DIR $OUTFILENAME
+```
diff --git a/extract-tsdefs/extract.ts b/extract-tsdefs/extract.ts
new file mode 100644
index 0000000..5be8247
--- /dev/null
+++ b/extract-tsdefs/extract.ts
@@ -0,0 +1,341 @@
+/*
+ This file is part of GNU Taler
+ (C) 2022 Taler Systems S.A.
+
+ GNU Taler is free 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.
+
+ GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNU Taler; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
+ */
+
+import * as ts from "typescript";
+import * as fs from "fs/promises";
+import * as path from "path";
+import * as prettier from "prettier";
+
+if (process.argv.length != 4) {
+ console.log(
+ `usage: ${process.argv[0]} ${process.argv[1]} WALLET_CORE_REPO OUTFILE`
+ );
+ process.exit(2);
+}
+
+const walletRootDir = process.argv[2];
+const outfile = process.argv[3];
+
+const walletCoreDir = path.join(walletRootDir, "packages/taler-wallet-core");
+const excludedNames = new Set([
+ "TalerErrorCode",
+ "WalletBackupContentV1",
+ "Array",
+]);
+
+const configFile = ts.findConfigFile(
+ walletCoreDir,
+ ts.sys.fileExists,
+ "tsconfig.json"
+);
+if (!configFile) throw Error("tsconfig.json not found");
+const { config } = ts.readConfigFile(configFile, ts.sys.readFile);
+
+const { options, fileNames, errors } = ts.parseJsonConfigFileContent(
+ config,
+ ts.sys,
+ walletCoreDir
+);
+
+const program = ts.createProgram({
+ options,
+ rootNames: fileNames,
+ configFileParsingDiagnostics: errors,
+});
+
+const checker = program.getTypeChecker();
+
+const walletApiTypesFiles = `${walletCoreDir}/src/wallet-api-types.ts`;
+console.log("api types file:", walletApiTypesFiles);
+
+const sourceFile = program.getSourceFile(walletApiTypesFiles);
+
+if (!sourceFile) {
+ throw Error();
+}
+
+const printer = ts.createPrinter({ newLine: ts.NewLineKind.LineFeed });
+
+const fileSymbol = program.getTypeChecker().getSymbolAtLocation(sourceFile);
+
+const expo = fileSymbol?.exports;
+if (!expo) {
+ throw Error();
+}
+
+interface PerOpGatherState {
+ opName: string;
+ nameSet: Set<string>;
+ group: string;
+ /**
+ * Enum member declaration in the form 'Foo = "bar"'.
+ */
+ enumMemberDecl: string | undefined;
+}
+
+interface GatherState {
+ declTexts: Map<string, string>;
+}
+
+function gatherDecls(
+ node: ts.Node,
+ gatherState: GatherState,
+ perOpState: PerOpGatherState
+): void {
+ switch (node.kind) {
+ case ts.SyntaxKind.EnumDeclaration:
+ // Always handled via parent
+ return;
+ case ts.SyntaxKind.Identifier:
+ case ts.SyntaxKind.TypeReference: {
+ console.log(`start typeref-or-id ${node.getText()}`);
+ const type = checker.getTypeAtLocation(node);
+ if (type.flags === ts.TypeFlags.String) {
+ console.log("string!");
+ break;
+ }
+ const symbol = type.symbol || type.aliasSymbol;
+ if (!symbol) {
+ console.log(`no type symbol for ${node.getText()}`);
+ break;
+ }
+ const name = symbol.name;
+ console.log(`symbol name: ${type.symbol?.name}`);
+ console.log(`alias symbol name: ${type.aliasSymbol?.name}`);
+ if (perOpState.nameSet.has(name)) {
+ console.log("already found!");
+ break;
+ }
+ perOpState.nameSet.add(name);
+ if (excludedNames.has(name)) {
+ console.log("excluded!");
+ break;
+ }
+ const decls = symbol.getDeclarations();
+ decls?.forEach((decl) => {
+ const sourceFilename = decl.getSourceFile().fileName;
+ if (path.basename(sourceFilename).startsWith("lib.")) {
+ return;
+ }
+ switch (decl.kind) {
+ case ts.SyntaxKind.EnumMember: {
+ gatherDecls(decl.parent, gatherState, perOpState);
+ console.log("enum member", decl.getText());
+ break;
+ }
+ case ts.SyntaxKind.InterfaceDeclaration:
+ case ts.SyntaxKind.EnumDeclaration:
+ case ts.SyntaxKind.TypeAliasDeclaration: {
+ const declText = printer.printNode(
+ ts.EmitHint.Unspecified,
+ decl,
+ decl.getSourceFile()!
+ );
+ gatherState.declTexts.set(name, declText);
+ console.log(declText);
+ break;
+ }
+ default:
+ console.log(`unknown decl kind ${ts.SyntaxKind[decl.kind]}`);
+ break;
+ }
+ gatherDecls(decl, gatherState, perOpState);
+ console.log(`end typeref-or-id ${node.getText()}`);
+ });
+ break;
+ }
+ default:
+ break;
+ }
+ console.log(`syntax children for ${node.getText()}`);
+ node.forEachChild((child) => {
+ console.log(`syntax child: ${ts.SyntaxKind[child.kind]}`);
+ gatherDecls(child, gatherState, perOpState);
+ });
+ //console.log(`// unknown node kind ${ts.SyntaxKind[node.kind]}`);
+ return;
+}
+
+function getOpEnumDecl(decl: ts.Declaration): string | undefined {
+ let enumMemberDecl: undefined | string = undefined;
+ function walk(node: ts.Node) {
+ node.forEachChild((x) => {
+ console.log(`child kind: ${ts.SyntaxKind[x.kind]}`);
+ console.log(x.getText());
+ switch (x.kind) {
+ case ts.SyntaxKind.PropertySignature: {
+ const sig = x as ts.PropertySignature;
+ if (sig.name.getText() == "op") {
+ const type = checker.getTypeFromTypeNode(sig.type!);
+ enumMemberDecl = type.symbol.declarations![0]!.getText();
+ }
+ break;
+ }
+ }
+ walk(x);
+ });
+ }
+ walk(decl);
+ return enumMemberDecl;
+}
+
+const main = async () => {
+ const f = await fs.open(outfile, "w");
+ const gatherState: GatherState = {
+ declTexts: new Map<string, string>(),
+ };
+ const perOpStates: PerOpGatherState[] = [];
+
+ let currentGroup: string = "Unknown Group";
+
+ expo.forEach((v, k) => {
+ if (!v.name.endsWith("Op")) {
+ return;
+ }
+ const decls = v.getDeclarations();
+ decls?.forEach((decl) => {
+ console.log(`export decl, kind ${ts.SyntaxKind[decl.kind]}`);
+
+ const commentRanges = ts.getLeadingCommentRanges(
+ sourceFile.getFullText(),
+ decl.getFullStart()
+ );
+ commentRanges?.forEach((r) => {
+ const text = sourceFile.getFullText().slice(r.pos, r.end);
+ console.log("comment text:", text);
+ const groupPrefix = "group:";
+ const loc = text.indexOf(groupPrefix);
+ if (loc >= 0) {
+ const groupName = text.slice(loc + groupPrefix.length);
+ console.log("got new group", groupName);
+ currentGroup = groupName;
+ }
+ });
+
+ const perOpState: PerOpGatherState = {
+ opName: v.name,
+ nameSet: new Set<string>(),
+ group: currentGroup,
+ enumMemberDecl: getOpEnumDecl(decl),
+ };
+ let declText = printer.printNode(
+ ts.EmitHint.Unspecified,
+ decl,
+ decl.getSourceFile()!
+ );
+ if (perOpState.enumMemberDecl) {
+ declText = declText + `\n// ${perOpState.enumMemberDecl}\n`;
+ }
+ console.log("replacing group in", declText);
+ // Remove group comments
+ declText = declText.replace(/\/\/ group: [^\n]*[\n]/m, "");
+ perOpState.nameSet.add(v.name);
+ gatherState.declTexts.set(v.name, declText);
+ gatherDecls(decl, gatherState, perOpState);
+ perOpStates.push(perOpState);
+ });
+ });
+
+ const allNames: Set<string> = new Set();
+
+ for (const g of perOpStates) {
+ for (const k of g.nameSet.values()) {
+ allNames.add(k);
+ }
+ }
+
+ const commonNames: Set<string> = new Set();
+
+ for (const name of allNames) {
+ let count = 0;
+ for (const g of perOpStates) {
+ for (const k of g.nameSet.values()) {
+ if (name === k) {
+ count++;
+ }
+ }
+ }
+ if (count > 1) {
+ console.log(`common name: ${name}`);
+ commonNames.add(name);
+ }
+ }
+
+ const groups = new Set<string>();
+ for (const g of perOpStates) {
+ groups.add(g.group);
+ }
+
+ await f.write(`# Wallet-Core API Documentation\n`);
+
+ await f.write(
+ `This file is auto-generated from [wallet-core](https://git.taler.net/wallet-core.git/tree/packages/taler-wallet-core/src/wallet-api-types.ts).\n`
+ );
+
+ await f.write(`## Overview\n`);
+ for (const g of groups.values()) {
+ await f.write(`### ${g}\n`);
+ for (const op of perOpStates) {
+ if (op.group !== g) {
+ continue;
+ }
+ await f.write(`* [${op.opName}](#${op.opName.toLowerCase()})\n`);
+ }
+ }
+
+ await f.write(`## Operation Reference\n`);
+ for (const g of perOpStates) {
+ // Not yet supported, switch to myst first!
+ // await f.write(`(${g.opName.toLowerCase()})=\n`);
+ await f.write(`### ${g.opName}\n`);
+ for (const name of g.nameSet.values()) {
+ if (commonNames.has(name)) {
+ continue;
+ }
+ const text = gatherState.declTexts.get(name);
+ if (!text) {
+ continue;
+ }
+ await f.write("```typescript\n");
+ const formatted = prettier.format(text, {
+ semi: true,
+ parser: "typescript",
+ });
+ await f.write(`${formatted}\n`);
+ await f.write("```\n");
+ }
+ await f.write("\n");
+ }
+
+ await f.write(`## Common Declarations\n`);
+ for (const name of commonNames.values()) {
+ const text = gatherState.declTexts.get(name);
+ if (!text) {
+ continue;
+ }
+ await f.write("```typescript\n");
+ const formatted = prettier.format(text, {
+ semi: true,
+ parser: "typescript",
+ });
+ await f.write(`${formatted}`);
+ await f.write("```\n");
+ }
+
+ await f.close();
+};
+
+main();
diff --git a/extract-tsdefs/myout.md b/extract-tsdefs/myout.md
new file mode 100644
index 0000000..abecccf
--- /dev/null
+++ b/extract-tsdefs/myout.md
@@ -0,0 +1,2517 @@
+# Wallet API Documentation
+```{note}
+This file is auto-generated from [wallet-core](https://git.taler.net/wallet-core.git/tree/packages/taler-wallet-core/src/wallet-api-types.ts)
+```
+## Overview
+### Initialization
+* [InitWalletOp](#initwalletop)
+### Basic Wallet Information
+* [GetBalancesOp](#getbalancesop)
+### Managing Transactions
+* [GetTransactionsOp](#gettransactionsop)
+* [DeleteTransactionOp](#deletetransactionop)
+* [RetryTransactionOp](#retrytransactionop)
+### Withdrawals
+* [GetWithdrawalDetailsForAmountOp](#getwithdrawaldetailsforamountop)
+* [GetWithdrawalDetailsForUriOp](#getwithdrawaldetailsforuriop)
+* [AcceptBankIntegratedWithdrawalOp](#acceptbankintegratedwithdrawalop)
+* [AcceptManualWithdrawalOp](#acceptmanualwithdrawalop)
+### Merchant Payments
+* [PreparePayForUriOp](#preparepayforuriop)
+* [ConfirmPayOp](#confirmpayop)
+* [AbortPayWithRefundOp](#abortpaywithrefundop)
+* [ApplyRefundOp](#applyrefundop)
+### Tipping
+* [PrepareTipOp](#preparetipop)
+* [AcceptTipOp](#accepttipop)
+### Exchange Management
+* [ListExchangesOp](#listexchangesop)
+* [AddExchangeOp](#addexchangeop)
+* [SetExchangeTosAcceptedOp](#setexchangetosacceptedop)
+* [GetExchangeTosOp](#getexchangetosop)
+* [ListCurrenciesOp](#listcurrenciesop)
+### Deposits
+* [CreateDepositGroupOp](#createdepositgroupop)
+* [TrackDepositGroupOp](#trackdepositgroupop)
+### Backups
+* [ExportBackupRecoveryOp](#exportbackuprecoveryop)
+* [ImportBackupRecoveryOp](#importbackuprecoveryop)
+* [RunBackupCycleOp](#runbackupcycleop)
+* [AddBackupProviderOp](#addbackupproviderop)
+* [GetBackupInfoOp](#getbackupinfoop)
+* [SetWalletDeviceIdOp](#setwalletdeviceidop)
+* [ExportBackupPlainOp](#exportbackupplainop)
+### Peer Payments
+* [InitiatePeerPushPaymentOp](#initiatepeerpushpaymentop)
+* [CheckPeerPushPaymentOp](#checkpeerpushpaymentop)
+* [AcceptPeerPushPaymentOp](#acceptpeerpushpaymentop)
+* [InitiatePeerPullPaymentOp](#initiatepeerpullpaymentop)
+* [CheckPeerPullPaymentOp](#checkpeerpullpaymentop)
+* [AcceptPeerPullPaymentOp](#acceptpeerpullpaymentop)
+### Database Management
+* [ExportDbOp](#exportdbop)
+* [ClearDbOp](#cleardbop)
+* [RecycleOp](#recycleop)
+### Testing and Debugging
+* [RunIntegrationTestOp](#runintegrationtestop)
+* [WithdrawTestBalanceOp](#withdrawtestbalanceop)
+* [WithdrawTestkudosOp](#withdrawtestkudosop)
+* [TestPayOp](#testpayop)
+* [WithdrawFakebankOp](#withdrawfakebankop)
+* [GetPendingTasksOp](#getpendingtasksop)
+* [DumpCoinsOp](#dumpcoinsop)
+* [SetCoinSuspendedOp](#setcoinsuspendedop)
+* [ForceRefreshOp](#forcerefreshop)
+## Operation Reference
+(initwalletop)=
+### InitWalletOp
+```typescript
+// group: Initialization
+/**
+ * Initialize wallet-core.
+ *
+ * Must be the request before any other operations.
+ */
+export type InitWalletOp = {
+ op: WalletApiOperation.InitWallet;
+ request: {};
+ response: {};
+};
+
+```
+```typescript
+// Enum value:
+// WalletApiOperation.InitWallet = "initWallet"
+
+```
+
+(getbalancesop)=
+### GetBalancesOp
+```typescript
+// group: Basic Wallet Information
+/**
+ * Get current wallet balance.
+ */
+export type GetBalancesOp = {
+ request: {};
+ response: BalancesResponse;
+};
+
+```
+```typescript
+export interface BalancesResponse {
+ balances: Balance[];
+}
+
+```
+```typescript
+export interface Balance {
+ available: AmountString;
+ pendingIncoming: AmountString;
+ pendingOutgoing: AmountString;
+ hasPendingTransactions: boolean;
+ requiresUserInput: boolean;
+}
+
+```
+
+(gettransactionsop)=
+### GetTransactionsOp
+```typescript
+// group: Managing Transactions
+/**
+ * Get transactions.
+ */
+export type GetTransactionsOp = {
+ request: TransactionsRequest;
+ response: TransactionsResponse;
+};
+
+```
+```typescript
+export interface TransactionsRequest {
+ /**
+ * return only transactions in the given currency
+ */
+ currency?: string;
+ /**
+ * if present, results will be limited to transactions related to the given search string
+ */
+ search?: string;
+}
+
+```
+```typescript
+export interface TransactionsResponse {
+ transactions: Transaction[];
+}
+
+```
+```typescript
+export declare type Transaction =
+ | TransactionWithdrawal
+ | TransactionPayment
+ | TransactionRefund
+ | TransactionTip
+ | TransactionRefresh
+ | TransactionDeposit
+ | TransactionPeerPullCredit
+ | TransactionPeerPullDebit
+ | TransactionPeerPushCredit
+ | TransactionPeerPushDebit;
+
+```
+```typescript
+export interface TransactionWithdrawal extends TransactionCommon {
+ type: TransactionType.Withdrawal;
+ /**
+ * Exchange of the withdrawal.
+ */
+ exchangeBaseUrl: string;
+ /**
+ * Amount that got subtracted from the reserve balance.
+ */
+ amountRaw: AmountString;
+ /**
+ * Amount that actually was (or will be) added to the wallet's balance.
+ */
+ amountEffective: AmountString;
+ withdrawalDetails: WithdrawalDetails;
+}
+
+```
+```typescript
+// Enum value:
+// TransactionType.Withdrawal = "withdrawal"
+
+```
+```typescript
+export declare type WithdrawalDetails =
+ | WithdrawalDetailsForManualTransfer
+ | WithdrawalDetailsForTalerBankIntegrationApi;
+
+```
+```typescript
+interface WithdrawalDetailsForManualTransfer {
+ type: WithdrawalType.ManualTransfer;
+ /**
+ * Payto URIs that the exchange supports.
+ *
+ * Already contains the amount and message.
+ */
+ exchangePaytoUris: string[];
+ reservePub: string;
+}
+
+```
+```typescript
+// Enum value:
+// WithdrawalType.ManualTransfer = "manual-transfer"
+
+```
+```typescript
+interface WithdrawalDetailsForTalerBankIntegrationApi {
+ type: WithdrawalType.TalerBankIntegrationApi;
+ /**
+ * Set to true if the bank has confirmed the withdrawal, false if not.
+ * An unconfirmed withdrawal usually requires user-input and should be highlighted in the UI.
+ * See also bankConfirmationUrl below.
+ */
+ confirmed: boolean;
+ /**
+ * If the withdrawal is unconfirmed, this can include a URL for user
+ * initiated confirmation.
+ */
+ bankConfirmationUrl?: string;
+ reservePub: string;
+}
+
+```
+```typescript
+// Enum value:
+// WithdrawalType.TalerBankIntegrationApi = "taler-bank-integration-api"
+
+```
+```typescript
+export interface TransactionPayment extends TransactionCommon {
+ type: TransactionType.Payment;
+ /**
+ * Additional information about the payment.
+ */
+ info: OrderShortInfo;
+ /**
+ * Wallet-internal end-to-end identifier for the payment.
+ */
+ proposalId: string;
+ /**
+ * How far did the wallet get with processing the payment?
+ */
+ status: PaymentStatus;
+ /**
+ * Amount that must be paid for the contract
+ */
+ amountRaw: AmountString;
+ /**
+ * Amount that was paid, including deposit, wire and refresh fees.
+ */
+ amountEffective: AmountString;
+ /**
+ * Amount that has been refunded by the merchant
+ */
+ totalRefundRaw: AmountString;
+ /**
+ * Amount will be added to the wallet's balance after fees and refreshing
+ */
+ totalRefundEffective: AmountString;
+ /**
+ * Amount pending to be picked up
+ */
+ refundPending: AmountString | undefined;
+ /**
+ * Reference to applied refunds
+ */
+ refunds: RefundInfoShort[];
+}
+
+```
+```typescript
+// Enum value:
+// TransactionType.Payment = "payment"
+
+```
+```typescript
+export declare enum PaymentStatus {
+ /**
+ * Explicitly aborted after timeout / failure
+ */
+ Aborted = "aborted",
+ /**
+ * Payment failed, wallet will auto-retry.
+ * User should be given the option to retry now / abort.
+ */
+ Failed = "failed",
+ /**
+ * Paid successfully
+ */
+ Paid = "paid",
+ /**
+ * User accepted, payment is processing.
+ */
+ Accepted = "accepted",
+}
+
+```
+```typescript
+export interface RefundInfoShort {
+ transactionId: string;
+ timestamp: TalerProtocolTimestamp;
+ amountEffective: AmountString;
+ amountRaw: AmountString;
+}
+
+```
+```typescript
+export interface TransactionRefund extends TransactionCommon {
+ type: TransactionType.Refund;
+ refundedTransactionId: string;
+ info: OrderShortInfo;
+ /**
+ * Amount pending to be picked up
+ */
+ refundPending: AmountString | undefined;
+ amountRaw: AmountString;
+ amountEffective: AmountString;
+}
+
+```
+```typescript
+// Enum value:
+// TransactionType.Refund = "refund"
+
+```
+```typescript
+export interface TransactionTip extends TransactionCommon {
+ type: TransactionType.Tip;
+ amountRaw: AmountString;
+ /**
+ * More information about the merchant
+ */
+ amountEffective: AmountString;
+ merchantBaseUrl: string;
+}
+
+```
+```typescript
+// Enum value:
+// TransactionType.Tip = "tip"
+
+```
+```typescript
+export interface TransactionRefresh extends TransactionCommon {
+ type: TransactionType.Refresh;
+ exchangeBaseUrl: string;
+ amountRaw: AmountString;
+ amountEffective: AmountString;
+}
+
+```
+```typescript
+/**
+ * Deposit transaction, which effectively sends
+ * money from this wallet somewhere else.
+ */
+export interface TransactionDeposit extends TransactionCommon {
+ type: TransactionType.Deposit;
+ depositGroupId: string;
+ /**
+ * Target for the deposit.
+ */
+ targetPaytoUri: string;
+ /**
+ * Raw amount that is being deposited
+ */
+ amountRaw: AmountString;
+ /**
+ * Effective amount that is being deposited
+ */
+ amountEffective: AmountString;
+}
+
+```
+```typescript
+/**
+ * Credit because we were paid for a P2P invoice we created.
+ */
+export interface TransactionPeerPullCredit extends TransactionCommon {
+ type: TransactionType.PeerPullCredit;
+ info: PeerInfoShort;
+ /**
+ * Exchange used.
+ */
+ exchangeBaseUrl: string;
+ /**
+ * Amount that got subtracted from the reserve balance.
+ */
+ amountRaw: AmountString;
+ /**
+ * Amount that actually was (or will be) added to the wallet's balance.
+ */
+ amountEffective: AmountString;
+ /**
+ * URI to send to the other party.
+ */
+ talerUri: string;
+}
+
+```
+```typescript
+// Enum value:
+// TransactionType.PeerPullCredit = "peer-pull-credit"
+
+```
+```typescript
+export interface PeerInfoShort {
+ expiration: TalerProtocolTimestamp | undefined;
+ summary: string | undefined;
+}
+
+```
+```typescript
+/**
+ * Debit because we paid someone's invoice.
+ */
+export interface TransactionPeerPullDebit extends TransactionCommon {
+ type: TransactionType.PeerPullDebit;
+ info: PeerInfoShort;
+ /**
+ * Exchange used.
+ */
+ exchangeBaseUrl: string;
+ amountRaw: AmountString;
+ amountEffective: AmountString;
+}
+
+```
+```typescript
+// Enum value:
+// TransactionType.PeerPullDebit = "peer-pull-debit"
+
+```
+```typescript
+/**
+ * We received money via a P2P payment.
+ */
+export interface TransactionPeerPushCredit extends TransactionCommon {
+ type: TransactionType.PeerPushCredit;
+ info: PeerInfoShort;
+ /**
+ * Exchange used.
+ */
+ exchangeBaseUrl: string;
+ /**
+ * Amount that got subtracted from the reserve balance.
+ */
+ amountRaw: AmountString;
+ /**
+ * Amount that actually was (or will be) added to the wallet's balance.
+ */
+ amountEffective: AmountString;
+}
+
+```
+```typescript
+// Enum value:
+// TransactionType.PeerPushCredit = "peer-push-credit"
+
+```
+```typescript
+/**
+ * We sent money via a P2P payment.
+ */
+export interface TransactionPeerPushDebit extends TransactionCommon {
+ type: TransactionType.PeerPushDebit;
+ info: PeerInfoShort;
+ /**
+ * Exchange used.
+ */
+ exchangeBaseUrl: string;
+ /**
+ * Amount that got subtracted from the reserve balance.
+ */
+ amountRaw: AmountString;
+ /**
+ * Amount that actually was (or will be) added to the wallet's balance.
+ */
+ amountEffective: AmountString;
+ /**
+ * URI to accept the payment.
+ */
+ talerUri: string;
+}
+
+```
+```typescript
+// Enum value:
+// TransactionType.PeerPushDebit = "peer-push-debit"
+
+```
+
+(deletetransactionop)=
+### DeleteTransactionOp
+```typescript
+/**
+ * Delete a transaction locally in the wallet.
+ */
+export type DeleteTransactionOp = {
+ request: DeleteTransactionRequest;
+ response: {};
+};
+
+```
+```typescript
+export interface DeleteTransactionRequest {
+ transactionId: string;
+}
+
+```
+
+(retrytransactionop)=
+### RetryTransactionOp
+```typescript
+/**
+ * Immediately retry a transaction.
+ */
+export type RetryTransactionOp = {
+ request: RetryTransactionRequest;
+ response: {};
+};
+
+```
+```typescript
+export interface RetryTransactionRequest {
+ transactionId: string;
+}
+
+```
+
+(getwithdrawaldetailsforamountop)=
+### GetWithdrawalDetailsForAmountOp
+```typescript
+// group: Withdrawals
+/**
+ * Get details for withdrawing a particular amount (manual withdrawal).
+ */
+export type GetWithdrawalDetailsForAmountOp = {
+ request: GetWithdrawalDetailsForAmountRequest;
+ response: ManualWithdrawalDetails;
+};
+
+```
+```typescript
+export interface GetWithdrawalDetailsForAmountRequest {
+ exchangeBaseUrl: string;
+ amount: string;
+ restrictAge?: number;
+}
+
+```
+```typescript
+export interface ManualWithdrawalDetails {
+ /**
+ * Did the user accept the current version of the exchange's
+ * terms of service?
+ */
+ tosAccepted: boolean;
+ /**
+ * Amount that the user will transfer to the exchange.
+ */
+ amountRaw: AmountString;
+ /**
+ * Amount that will be added to the user's wallet balance.
+ */
+ amountEffective: AmountString;
+ /**
+ * Ways to pay the exchange.
+ */
+ paytoUris: string[];
+}
+
+```
+
+(getwithdrawaldetailsforuriop)=
+### GetWithdrawalDetailsForUriOp
+```typescript
+/**
+ * Get details for withdrawing via a particular taler:// URI.
+ */
+export type GetWithdrawalDetailsForUriOp = {
+ request: GetWithdrawalDetailsForUriRequest;
+ response: WithdrawUriInfoResponse;
+};
+
+```
+```typescript
+export interface GetWithdrawalDetailsForUriRequest {
+ talerWithdrawUri: string;
+ restrictAge?: number;
+}
+
+```
+```typescript
+export interface WithdrawUriInfoResponse {
+ amount: AmountString;
+ defaultExchangeBaseUrl?: string;
+ possibleExchanges: ExchangeListItem[];
+}
+
+```
+
+(acceptbankintegratedwithdrawalop)=
+### AcceptBankIntegratedWithdrawalOp
+```typescript
+/**
+ * Accept a bank-integrated withdrawal.
+ */
+export type AcceptBankIntegratedWithdrawalOp = {
+ request: AcceptBankIntegratedWithdrawalRequest;
+ response: AcceptWithdrawalResponse;
+};
+
+```
+```typescript
+export interface AcceptBankIntegratedWithdrawalRequest {
+ talerWithdrawUri: string;
+ exchangeBaseUrl: string;
+ forcedDenomSel?: ForcedDenomSel;
+ restrictAge?: number;
+}
+
+```
+```typescript
+export interface AcceptWithdrawalResponse {
+ reservePub: string;
+ confirmTransferUrl?: string;
+ transactionId: string;
+}
+
+```
+
+(acceptmanualwithdrawalop)=
+### AcceptManualWithdrawalOp
+```typescript
+/**
+ * Create a manual withdrawal.
+ */
+export type AcceptManualWithdrawalOp = {
+ request: AcceptManualWithdrawalRequest;
+ response: AcceptManualWithdrawalResult;
+};
+
+```
+```typescript
+export interface AcceptManualWithdrawalRequest {
+ exchangeBaseUrl: string;
+ amount: string;
+ restrictAge?: number;
+}
+
+```
+```typescript
+export interface AcceptManualWithdrawalResult {
+ /**
+ * Payto URIs that can be used to fund the withdrawal.
+ */
+ exchangePaytoUris: string[];
+ /**
+ * Public key of the newly created reserve.
+ */
+ reservePub: string;
+ transactionId: string;
+}
+
+```
+
+(preparepayforuriop)=
+### PreparePayForUriOp
+```typescript
+// group: Merchant Payments
+/**
+ * Prepare to make a payment
+ */
+export type PreparePayForUriOp = {
+ op: WalletApiOperation.PreparePayForUri;
+ request: PreparePayRequest;
+ response: PreparePayResult;
+};
+
+```
+```typescript
+// Enum value:
+// WalletApiOperation.PreparePayForUri = "preparePayForUri"
+
+```
+```typescript
+export interface PreparePayRequest {
+ talerPayUri: string;
+}
+
+```
+```typescript
+/**
+ * Result of a prepare pay operation.
+ */
+export declare type PreparePayResult =
+ | PreparePayResultInsufficientBalance
+ | PreparePayResultAlreadyConfirmed
+ | PreparePayResultPaymentPossible;
+
+```
+```typescript
+export interface PreparePayResultInsufficientBalance {
+ status: PreparePayResultType.InsufficientBalance;
+ proposalId: string;
+ contractTerms: ContractTerms;
+ amountRaw: string;
+ noncePriv: string;
+}
+
+```
+```typescript
+export interface PreparePayResultAlreadyConfirmed {
+ status: PreparePayResultType.AlreadyConfirmed;
+ contractTerms: ContractTerms;
+ paid: boolean;
+ amountRaw: string;
+ amountEffective: string;
+ contractTermsHash: string;
+ proposalId: string;
+}
+
+```
+```typescript
+// Enum value:
+// PreparePayResultType.AlreadyConfirmed = "already-confirmed"
+
+```
+```typescript
+/**
+ * Payment is possible.
+ */
+export interface PreparePayResultPaymentPossible {
+ status: PreparePayResultType.PaymentPossible;
+ proposalId: string;
+ contractTerms: ContractTerms;
+ contractTermsHash: string;
+ amountRaw: string;
+ amountEffective: string;
+ noncePriv: string;
+}
+
+```
+```typescript
+// Enum value:
+// PreparePayResultType.PaymentPossible = "payment-possible"
+
+```
+
+(confirmpayop)=
+### ConfirmPayOp
+```typescript
+/**
+ * Confirm a payment that was previously prepared with
+ * {@link PreparePayForUriOp}
+ */
+export type ConfirmPayOp = {
+ op: WalletApiOperation.ConfirmPay;
+ request: ConfirmPayRequest;
+ response: ConfirmPayResult;
+};
+
+```
+```typescript
+// Enum value:
+// WalletApiOperation.ConfirmPay = "confirmPay"
+
+```
+```typescript
+export interface ConfirmPayRequest {
+ proposalId: string;
+ sessionId?: string;
+ forcedCoinSel?: ForcedCoinSel;
+}
+
+```
+```typescript
+export declare type ConfirmPayResult =
+ | ConfirmPayResultDone
+ | ConfirmPayResultPending;
+
+```
+```typescript
+/**
+ * Result for confirmPay
+ */
+export interface ConfirmPayResultDone {
+ type: ConfirmPayResultType.Done;
+ contractTerms: ContractTerms;
+ transactionId: string;
+}
+
+```
+```typescript
+// Enum value:
+// ConfirmPayResultType.Done = "done"
+
+```
+```typescript
+export interface ConfirmPayResultPending {
+ type: ConfirmPayResultType.Pending;
+ transactionId: string;
+ lastError: TalerErrorDetail | undefined;
+}
+
+```
+
+(abortpaywithrefundop)=
+### AbortPayWithRefundOp
+```typescript
+/**
+ * Abort a pending payment with a refund.
+ */
+export type AbortPayWithRefundOp = {
+ request: AbortPayWithRefundRequest;
+ response: {};
+};
+
+```
+```typescript
+export interface AbortPayWithRefundRequest {
+ proposalId: string;
+}
+
+```
+
+(applyrefundop)=
+### ApplyRefundOp
+```typescript
+/**
+ * Check for a refund based on a taler://refund URI.
+ */
+export type ApplyRefundOp = {
+ request: ApplyRefundRequest;
+ response: ApplyRefundResponse;
+};
+
+```
+```typescript
+export interface ApplyRefundRequest {
+ talerRefundUri: string;
+}
+
+```
+```typescript
+export interface ApplyRefundResponse {
+ contractTermsHash: string;
+ transactionId: string;
+ proposalId: string;
+ amountEffectivePaid: AmountString;
+ amountRefundGranted: AmountString;
+ amountRefundGone: AmountString;
+ pendingAtExchange: boolean;
+ info: OrderShortInfo;
+}
+
+```
+
+(preparetipop)=
+### PrepareTipOp
+```typescript
+// group: Tipping
+/**
+ * Query and store information about a tip.
+ */
+export type PrepareTipOp = {
+ request: PrepareTipRequest;
+ response: PrepareTipResult;
+};
+
+```
+```typescript
+export interface PrepareTipRequest {
+ talerTipUri: string;
+}
+
+```
+```typescript
+export interface PrepareTipResult {
+ /**
+ * Unique ID for the tip assigned by the wallet.
+ * Typically different from the merchant-generated tip ID.
+ */
+ walletTipId: string;
+ /**
+ * Has the tip already been accepted?
+ */
+ accepted: boolean;
+ /**
+ * Amount that the merchant gave.
+ */
+ tipAmountRaw: AmountString;
+ /**
+ * Amount that arrived at the wallet.
+ * Might be lower than the raw amount due to fees.
+ */
+ tipAmountEffective: AmountString;
+ /**
+ * Base URL of the merchant backend giving then tip.
+ */
+ merchantBaseUrl: string;
+ /**
+ * Base URL of the exchange that is used to withdraw the tip.
+ * Determined by the merchant, the wallet/user has no choice here.
+ */
+ exchangeBaseUrl: string;
+ /**
+ * Time when the tip will expire. After it expired, it can't be picked
+ * up anymore.
+ */
+ expirationTimestamp: TalerProtocolTimestamp;
+}
+
+```
+
+(accepttipop)=
+### AcceptTipOp
+```typescript
+/**
+ * Accept a tip.
+ */
+export type AcceptTipOp = {
+ request: AcceptTipRequest;
+ response: {};
+};
+
+```
+```typescript
+export interface AcceptTipRequest {
+ walletTipId: string;
+}
+
+```
+
+(listexchangesop)=
+### ListExchangesOp
+```typescript
+// group: Exchange Management
+/**
+ * List exchanges known to the wallet.
+ */
+export type ListExchangesOp = {
+ request: {};
+ response: ExchangesListResponse;
+};
+
+```
+```typescript
+export interface ExchangesListResponse {
+ exchanges: ExchangeListItem[];
+}
+
+```
+
+(addexchangeop)=
+### AddExchangeOp
+```typescript
+/**
+ * Add / force-update an exchange.
+ */
+export type AddExchangeOp = {
+ request: AddExchangeRequest;
+ response: {};
+};
+
+```
+```typescript
+export interface AddExchangeRequest {
+ exchangeBaseUrl: string;
+ forceUpdate?: boolean;
+}
+
+```
+
+(setexchangetosacceptedop)=
+### SetExchangeTosAcceptedOp
+```typescript
+/**
+ * Accept a particular version of the exchange terms of service.
+ */
+export type SetExchangeTosAcceptedOp = {
+ request: AcceptExchangeTosRequest;
+ response: {};
+};
+
+```
+```typescript
+export interface AcceptExchangeTosRequest {
+ exchangeBaseUrl: string;
+ etag: string | undefined;
+}
+
+```
+
+(getexchangetosop)=
+### GetExchangeTosOp
+```typescript
+/**
+ * Get the current terms of a service of an exchange.
+ */
+export type GetExchangeTosOp = {
+ request: GetExchangeTosRequest;
+ response: GetExchangeTosResult;
+};
+
+```
+```typescript
+export interface GetExchangeTosRequest {
+ exchangeBaseUrl: string;
+ acceptedFormat?: string[];
+}
+
+```
+```typescript
+export interface GetExchangeTosResult {
+ /**
+ * Markdown version of the current ToS.
+ */
+ content: string;
+ /**
+ * Version tag of the current ToS.
+ */
+ currentEtag: string;
+ /**
+ * Version tag of the last ToS that the user has accepted,
+ * if any.
+ */
+ acceptedEtag: string | undefined;
+ /**
+ * Accepted content type
+ */
+ contentType: string;
+}
+
+```
+
+(listcurrenciesop)=
+### ListCurrenciesOp
+```typescript
+/**
+ * List currencies known to the wallet.
+ */
+export type ListCurrenciesOp = {
+ request: {};
+ response: WalletCurrencyInfo;
+};
+
+```
+```typescript
+export interface WalletCurrencyInfo {
+ trustedAuditors: {
+ currency: string;
+ auditorPub: string;
+ auditorBaseUrl: string;
+ }[];
+ trustedExchanges: {
+ currency: string;
+ exchangeMasterPub: string;
+ exchangeBaseUrl: string;
+ }[];
+}
+
+```
+
+(createdepositgroupop)=
+### CreateDepositGroupOp
+```typescript
+// group: Deposits
+/**
+ * Create a new deposit group.
+ *
+ * Deposit groups are used to deposit multiple coins to a bank
+ * account, usually the wallet user's own bank account.
+ */
+export type CreateDepositGroupOp = {
+ request: CreateDepositGroupRequest;
+ response: CreateDepositGroupResponse;
+};
+
+```
+```typescript
+export interface CreateDepositGroupRequest {
+ depositPaytoUri: string;
+ amount: AmountString;
+}
+
+```
+```typescript
+export interface CreateDepositGroupResponse {
+ depositGroupId: string;
+ transactionId: string;
+}
+
+```
+
+(trackdepositgroupop)=
+### TrackDepositGroupOp
+```typescript
+/**
+ * Track the status of a deposit group by querying the exchange.
+ */
+export type TrackDepositGroupOp = {
+ request: TrackDepositGroupRequest;
+ response: TrackDepositGroupResponse;
+};
+
+```
+```typescript
+export interface TrackDepositGroupRequest {
+ depositGroupId: string;
+}
+
+```
+```typescript
+export interface TrackDepositGroupResponse {
+ responses: {
+ status: number;
+ body: any;
+ }[];
+}
+
+```
+
+(exportbackuprecoveryop)=
+### ExportBackupRecoveryOp
+```typescript
+// group: Backups
+/**
+ * Export the recovery information for the wallet.
+ */
+export type ExportBackupRecoveryOp = {
+ request: {};
+ response: BackupRecovery;
+};
+
+```
+
+(importbackuprecoveryop)=
+### ImportBackupRecoveryOp
+```typescript
+/**
+ * Import recovery information into the wallet.
+ */
+export type ImportBackupRecoveryOp = {
+ request: RecoveryLoadRequest;
+ response: {};
+};
+
+```
+```typescript
+/**
+ * Load recovery information into the wallet.
+ */
+export interface RecoveryLoadRequest {
+ recovery: BackupRecovery;
+ strategy?: RecoveryMergeStrategy;
+}
+
+```
+```typescript
+/**
+ * Strategy for loading recovery information.
+ */
+export declare enum RecoveryMergeStrategy {
+ /**
+ * Keep the local wallet root key, import and take over providers.
+ */
+ Ours = "ours",
+ /**
+ * Migrate to the wallet root key from the recovery information.
+ */
+ Theirs = "theirs",
+}
+
+```
+
+(runbackupcycleop)=
+### RunBackupCycleOp
+```typescript
+/**
+ * Manually make and upload a backup.
+ */
+export type RunBackupCycleOp = {
+ request: {};
+ response: {};
+};
+
+```
+
+(addbackupproviderop)=
+### AddBackupProviderOp
+```typescript
+/**
+ * Add a new backup provider.
+ */
+export type AddBackupProviderOp = {
+ request: AddBackupProviderRequest;
+ response: {};
+};
+
+```
+```typescript
+export interface AddBackupProviderRequest {
+ backupProviderBaseUrl: string;
+ name: string;
+ /**
+ * Activate the provider. Should only be done after
+ * the user has reviewed the provider.
+ */
+ activate?: boolean;
+}
+
+```
+
+(getbackupinfoop)=
+### GetBackupInfoOp
+```typescript
+/**
+ * Get some useful stats about the backup state.
+ */
+export type GetBackupInfoOp = {
+ request: {};
+ response: BackupInfo;
+};
+
+```
+```typescript
+export interface BackupInfo {
+ walletRootPub: string;
+ deviceId: string;
+ providers: ProviderInfo[];
+}
+
+```
+```typescript
+/**
+ * Information about one provider.
+ *
+ * We don't store the account key here,
+ * as that's derived from the wallet root key.
+ */
+export interface ProviderInfo {
+ active: boolean;
+ syncProviderBaseUrl: string;
+ name: string;
+ terms?: BackupProviderTerms;
+ /**
+ * Last communication issue with the provider.
+ */
+ lastError?: TalerErrorDetail;
+ lastSuccessfulBackupTimestamp?: TalerProtocolTimestamp;
+ lastAttemptedBackupTimestamp?: TalerProtocolTimestamp;
+ paymentProposalIds: string[];
+ backupProblem?: BackupProblem;
+ paymentStatus: ProviderPaymentStatus;
+}
+
+```
+```typescript
+export interface BackupProviderTerms {
+ supportedProtocolVersion: string;
+ annualFee: AmountString;
+ storageLimitInMegabytes: number;
+}
+
+```
+```typescript
+export type BackupProblem =
+ | BackupUnreadableProblem
+ | BackupConflictingDeviceProblem;
+
+```
+```typescript
+export interface BackupUnreadableProblem {
+ type: "backup-unreadable";
+}
+
+```
+```typescript
+export interface BackupConflictingDeviceProblem {
+ type: "backup-conflicting-device";
+ otherDeviceId: string;
+ myDeviceId: string;
+ backupTimestamp: AbsoluteTime;
+}
+
+```
+```typescript
+export type ProviderPaymentStatus =
+ | ProviderPaymentTermsChanged
+ | ProviderPaymentPaid
+ | ProviderPaymentInsufficientBalance
+ | ProviderPaymentUnpaid
+ | ProviderPaymentPending;
+
+```
+```typescript
+export interface ProviderPaymentTermsChanged {
+ type: ProviderPaymentType.TermsChanged;
+ paidUntil: AbsoluteTime;
+ oldTerms: BackupProviderTerms;
+ newTerms: BackupProviderTerms;
+}
+
+```
+```typescript
+// Enum value:
+// ProviderPaymentType.TermsChanged = "terms-changed"
+
+```
+```typescript
+export interface ProviderPaymentPaid {
+ type: ProviderPaymentType.Paid;
+ paidUntil: AbsoluteTime;
+}
+
+```
+```typescript
+// Enum value:
+// ProviderPaymentType.Paid = "paid"
+
+```
+```typescript
+export interface ProviderPaymentInsufficientBalance {
+ type: ProviderPaymentType.InsufficientBalance;
+}
+
+```
+```typescript
+export interface ProviderPaymentUnpaid {
+ type: ProviderPaymentType.Unpaid;
+}
+
+```
+```typescript
+// Enum value:
+// ProviderPaymentType.Unpaid = "unpaid"
+
+```
+```typescript
+export interface ProviderPaymentPending {
+ type: ProviderPaymentType.Pending;
+}
+
+```
+
+(setwalletdeviceidop)=
+### SetWalletDeviceIdOp
+```typescript
+/**
+ * Set the internal device ID of the wallet, used to
+ * identify whether a different/new wallet is accessing
+ * the backup of another wallet.
+ */
+export type SetWalletDeviceIdOp = {
+ request: SetWalletDeviceIdRequest;
+ response: {};
+};
+
+```
+```typescript
+export interface SetWalletDeviceIdRequest {
+ /**
+ * New wallet device ID to set.
+ */
+ walletDeviceId: string;
+}
+
+```
+
+(exportbackupplainop)=
+### ExportBackupPlainOp
+```typescript
+/**
+ * Export a backup JSON, mostly useful for testing.
+ */
+export type ExportBackupPlainOp = {
+ request: {};
+ response: WalletBackupContentV1;
+};
+
+```
+
+(initiatepeerpushpaymentop)=
+### InitiatePeerPushPaymentOp
+```typescript
+// group: Peer Payments
+/**
+ * Initiate an outgoing peer push payment.
+ */
+export type InitiatePeerPushPaymentOp = {
+ request: InitiatePeerPushPaymentRequest;
+ response: InitiatePeerPushPaymentResponse;
+};
+
+```
+```typescript
+export interface InitiatePeerPushPaymentRequest {
+ amount: AmountString;
+ partialContractTerms: any;
+}
+
+```
+```typescript
+export interface InitiatePeerPushPaymentResponse {
+ exchangeBaseUrl: string;
+ pursePub: string;
+ mergePriv: string;
+ contractPriv: string;
+ talerUri: string;
+ transactionId: string;
+}
+
+```
+
+(checkpeerpushpaymentop)=
+### CheckPeerPushPaymentOp
+```typescript
+/**
+ * Check an incoming peer push payment.
+ */
+export type CheckPeerPushPaymentOp = {
+ request: CheckPeerPushPaymentRequest;
+ response: CheckPeerPushPaymentResponse;
+};
+
+```
+```typescript
+export interface CheckPeerPushPaymentRequest {
+ talerUri: string;
+}
+
+```
+```typescript
+export interface CheckPeerPushPaymentResponse {
+ contractTerms: any;
+ amount: AmountString;
+ peerPushPaymentIncomingId: string;
+}
+
+```
+
+(acceptpeerpushpaymentop)=
+### AcceptPeerPushPaymentOp
+```typescript
+/**
+ * Accept an incoming peer push payment.
+ */
+export type AcceptPeerPushPaymentOp = {
+ request: AcceptPeerPushPaymentRequest;
+ response: {};
+};
+
+```
+```typescript
+export interface AcceptPeerPushPaymentRequest {
+ /**
+ * Transparent identifier of the incoming peer push payment.
+ */
+ peerPushPaymentIncomingId: string;
+}
+
+```
+
+(initiatepeerpullpaymentop)=
+### InitiatePeerPullPaymentOp
+```typescript
+/**
+ * Initiate an outgoing peer pull payment.
+ */
+export type InitiatePeerPullPaymentOp = {
+ request: InitiatePeerPullPaymentRequest;
+ response: InitiatePeerPullPaymentResponse;
+};
+
+```
+```typescript
+export interface InitiatePeerPullPaymentRequest {
+ /**
+ * FIXME: Make this optional?
+ */
+ exchangeBaseUrl: string;
+ amount: AmountString;
+ partialContractTerms: any;
+}
+
+```
+```typescript
+export interface InitiatePeerPullPaymentResponse {
+ /**
+ * Taler URI for the other party to make the payment
+ * that was requested.
+ */
+ talerUri: string;
+ transactionId: string;
+}
+
+```
+
+(checkpeerpullpaymentop)=
+### CheckPeerPullPaymentOp
+```typescript
+/**
+ * Prepare for an incoming peer pull payment.
+ */
+export type CheckPeerPullPaymentOp = {
+ request: CheckPeerPullPaymentRequest;
+ response: CheckPeerPullPaymentResponse;
+};
+
+```
+```typescript
+export interface CheckPeerPullPaymentRequest {
+ talerUri: string;
+}
+
+```
+```typescript
+export interface CheckPeerPullPaymentResponse {
+ contractTerms: any;
+ amount: AmountString;
+ peerPullPaymentIncomingId: string;
+}
+
+```
+
+(acceptpeerpullpaymentop)=
+### AcceptPeerPullPaymentOp
+```typescript
+/**
+ * Accept an incoming peer pull payment.
+ */
+export type AcceptPeerPullPaymentOp = {
+ request: AcceptPeerPullPaymentRequest;
+ response: {};
+};
+
+```
+```typescript
+export interface AcceptPeerPullPaymentRequest {
+ /**
+ * Transparent identifier of the incoming peer pull payment.
+ */
+ peerPullPaymentIncomingId: string;
+}
+
+```
+
+(exportdbop)=
+### ExportDbOp
+```typescript
+// group: Database Management
+/**
+ * Exoport the wallet database's contents to JSON.
+ */
+export type ExportDbOp = {
+ request: {};
+ response: any;
+};
+
+```
+
+(cleardbop)=
+### ClearDbOp
+```typescript
+/**
+ * Dangerously clear the whole wallet database.
+ */
+export type ClearDbOp = {
+ request: {};
+ response: {};
+};
+
+```
+
+(recycleop)=
+### RecycleOp
+```typescript
+/**
+ * Export a backup, clear the database and re-import it.
+ */
+export type RecycleOp = {
+ request: {};
+ response: {};
+};
+
+```
+
+(runintegrationtestop)=
+### RunIntegrationTestOp
+```typescript
+// group: Testing and Debugging
+/**
+ * Run a simple integration test on a test deployment
+ * of the exchange and merchant.
+ */
+export type RunIntegrationTestOp = {
+ request: IntegrationTestArgs;
+ response: {};
+};
+
+```
+```typescript
+export interface IntegrationTestArgs {
+ exchangeBaseUrl: string;
+ bankBaseUrl: string;
+ bankAccessApiBaseUrl?: string;
+ merchantBaseUrl: string;
+ merchantAuthToken?: string;
+ amountToWithdraw: string;
+ amountToSpend: string;
+}
+
+```
+
+(withdrawtestbalanceop)=
+### WithdrawTestBalanceOp
+```typescript
+/**
+ * Make withdrawal on a test deployment of the exchange
+ * and merchant.
+ */
+export type WithdrawTestBalanceOp = {
+ request: WithdrawTestBalanceRequest;
+ response: {};
+};
+
+```
+```typescript
+export interface WithdrawTestBalanceRequest {
+ amount: string;
+ bankBaseUrl: string;
+ /**
+ * Bank access API base URL. Defaults to the bankBaseUrl.
+ */
+ bankAccessApiBaseUrl?: string;
+ exchangeBaseUrl: string;
+ forcedDenomSel?: ForcedDenomSel;
+}
+
+```
+
+(withdrawtestkudosop)=
+### WithdrawTestkudosOp
+```typescript
+/**
+ * Make a withdrawal of testkudos on test.taler.net.
+ */
+export type WithdrawTestkudosOp = {
+ op: WalletApiOperation.WithdrawTestkudos;
+ request: {};
+ response: {};
+};
+
+```
+```typescript
+// Enum value:
+// WalletApiOperation.WithdrawTestkudos = "withdrawTestkudos"
+
+```
+
+(testpayop)=
+### TestPayOp
+```typescript
+/**
+ * Make a test payment using a test deployment of
+ * the exchange and merchant.
+ */
+export type TestPayOp = {
+ request: TestPayArgs;
+ response: TestPayResult;
+};
+
+```
+```typescript
+export interface TestPayArgs {
+ merchantBaseUrl: string;
+ merchantAuthToken?: string;
+ amount: string;
+ summary: string;
+ forcedCoinSel?: ForcedCoinSel;
+}
+
+```
+```typescript
+export interface TestPayResult {
+ payCoinSelection: PayCoinSelection;
+}
+
+```
+```typescript
+/**
+ * Result of selecting coins, contains the exchange, and selected
+ * coins with their denomination.
+ */
+export interface PayCoinSelection {
+ /**
+ * Amount requested by the merchant.
+ */
+ paymentAmount: AmountJson;
+ /**
+ * Public keys of the coins that were selected.
+ */
+ coinPubs: string[];
+ /**
+ * Amount that each coin contributes.
+ */
+ coinContributions: AmountJson[];
+ /**
+ * How much of the wire fees is the customer paying?
+ */
+ customerWireFees: AmountJson;
+ /**
+ * How much of the deposit fees is the customer paying?
+ */
+ customerDepositFees: AmountJson;
+}
+
+```
+```typescript
+/**
+ * Non-negative financial amount. Fractional values are expressed as multiples
+ * of 1e-8.
+ */
+export interface AmountJson {
+ /**
+ * Value, must be an integer.
+ */
+ readonly value: number;
+ /**
+ * Fraction, must be an integer. Represent 1/1e8 of a unit.
+ */
+ readonly fraction: number;
+ /**
+ * Currency of the amount.
+ */
+ readonly currency: string;
+}
+
+```
+
+(withdrawfakebankop)=
+### WithdrawFakebankOp
+```typescript
+/**
+ * Make a withdrawal from a fakebank, i.e.
+ * a bank where test users can be registered freely
+ * and testing APIs are available.
+ */
+export type WithdrawFakebankOp = {
+ op: WalletApiOperation.WithdrawFakebank;
+ request: WithdrawFakebankRequest;
+ response: {};
+};
+
+```
+```typescript
+// Enum value:
+// WalletApiOperation.WithdrawFakebank = "withdrawFakebank"
+
+```
+```typescript
+export interface WithdrawFakebankRequest {
+ amount: AmountString;
+ exchange: string;
+ bank: string;
+}
+
+```
+
+(getpendingtasksop)=
+### GetPendingTasksOp
+```typescript
+/**
+ * Get wallet-internal pending tasks.
+ */
+export type GetPendingTasksOp = {
+ request: {};
+ response: PendingTasksResponse;
+};
+
+```
+```typescript
+/**
+ * Response returned from the pending operations API.
+ */
+export interface PendingOperationsResponse {
+ /**
+ * List of pending operations.
+ */
+ pendingOperations: PendingTaskInfo[];
+}
+
+```
+```typescript
+/**
+ * Information about a pending operation.
+ */
+export type PendingTaskInfo = PendingTaskInfoCommon &
+ (
+ | PendingExchangeUpdateTask
+ | PendingExchangeCheckRefreshTask
+ | PendingPayTask
+ | PendingProposalDownloadTask
+ | PendingRefreshTask
+ | PendingRefundQueryTask
+ | PendingTipPickupTask
+ | PendingWithdrawTask
+ | PendingRecoupTask
+ | PendingDepositTask
+ | PendingBackupTask
+ );
+
+```
+```typescript
+/**
+ * Fields that are present in every pending operation.
+ */
+export interface PendingTaskInfoCommon {
+ /**
+ * Type of the pending operation.
+ */
+ type: PendingTaskType;
+ /**
+ * Unique identifier for the pending task.
+ */
+ id: string;
+ /**
+ * Set to true if the operation indicates that something is really in progress,
+ * as opposed to some regular scheduled operation that can be tried later.
+ */
+ givesLifeness: boolean;
+ /**
+ * Timestamp when the pending operation should be executed next.
+ */
+ timestampDue: AbsoluteTime;
+ /**
+ * Retry info. Currently used to stop the wallet after any operation
+ * exceeds a number of retries.
+ */
+ retryInfo?: RetryInfo;
+}
+
+```
+```typescript
+export enum PendingTaskType {
+ ExchangeUpdate = "exchange-update",
+ ExchangeCheckRefresh = "exchange-check-refresh",
+ Pay = "pay",
+ ProposalDownload = "proposal-download",
+ Refresh = "refresh",
+ Recoup = "recoup",
+ RefundQuery = "refund-query",
+ TipPickup = "tip-pickup",
+ Withdraw = "withdraw",
+ Deposit = "deposit",
+ Backup = "backup",
+}
+
+```
+```typescript
+export interface RetryInfo {
+ firstTry: AbsoluteTime;
+ nextRetry: AbsoluteTime;
+ retryCounter: number;
+}
+
+```
+```typescript
+export interface RetryPolicy {
+ readonly backoffDelta: Duration;
+ readonly backoffBase: number;
+ readonly maxTimeout: Duration;
+}
+
+```
+```typescript
+/**
+ * The wallet is currently updating information about an exchange.
+ */
+export interface PendingExchangeUpdateTask {
+ type: PendingTaskType.ExchangeUpdate;
+ exchangeBaseUrl: string;
+ lastError: TalerErrorDetail | undefined;
+}
+
+```
+```typescript
+// Enum value:
+// PendingTaskType.ExchangeUpdate = "exchange-update"
+
+```
+```typescript
+/**
+ * The wallet should check whether coins from this exchange
+ * need to be auto-refreshed.
+ */
+export interface PendingExchangeCheckRefreshTask {
+ type: PendingTaskType.ExchangeCheckRefresh;
+ exchangeBaseUrl: string;
+}
+
+```
+```typescript
+// Enum value:
+// PendingTaskType.ExchangeCheckRefresh = "exchange-check-refresh"
+
+```
+```typescript
+/**
+ * The wallet is signing coins and then sending them to
+ * the merchant.
+ */
+export interface PendingPayTask {
+ type: PendingTaskType.Pay;
+ proposalId: string;
+ isReplay: boolean;
+ retryInfo?: RetryInfo;
+ lastError: TalerErrorDetail | undefined;
+}
+
+```
+```typescript
+// Enum value:
+// PendingTaskType.Pay = "pay"
+
+```
+```typescript
+/**
+ * Status of downloading signed contract terms from a merchant.
+ */
+export interface PendingProposalDownloadTask {
+ type: PendingTaskType.ProposalDownload;
+ merchantBaseUrl: string;
+ proposalTimestamp: TalerProtocolTimestamp;
+ proposalId: string;
+ orderId: string;
+ lastError?: TalerErrorDetail;
+ retryInfo?: RetryInfo;
+}
+
+```
+```typescript
+// Enum value:
+// PendingTaskType.ProposalDownload = "proposal-download"
+
+```
+```typescript
+/**
+ * Status of an ongoing withdrawal operation.
+ */
+export interface PendingRefreshTask {
+ type: PendingTaskType.Refresh;
+ lastError?: TalerErrorDetail;
+ refreshGroupId: string;
+ finishedPerCoin: boolean[];
+ retryInfo?: RetryInfo;
+}
+
+```
+```typescript
+/**
+ * The wallet is querying the merchant about whether any refund
+ * permissions are available for a purchase.
+ */
+export interface PendingRefundQueryTask {
+ type: PendingTaskType.RefundQuery;
+ proposalId: string;
+ retryInfo?: RetryInfo;
+ lastError: TalerErrorDetail | undefined;
+}
+
+```
+```typescript
+// Enum value:
+// PendingTaskType.RefundQuery = "refund-query"
+
+```
+```typescript
+/**
+ * The wallet is picking up a tip that the user has accepted.
+ */
+export interface PendingTipPickupTask {
+ type: PendingTaskType.TipPickup;
+ tipId: string;
+ merchantBaseUrl: string;
+ merchantTipId: string;
+}
+
+```
+```typescript
+// Enum value:
+// PendingTaskType.TipPickup = "tip-pickup"
+
+```
+```typescript
+/**
+ * Status of an ongoing withdrawal operation.
+ */
+export interface PendingWithdrawTask {
+ type: PendingTaskType.Withdraw;
+ lastError: TalerErrorDetail | undefined;
+ retryInfo?: RetryInfo;
+ withdrawalGroupId: string;
+}
+
+```
+```typescript
+// Enum value:
+// PendingTaskType.Withdraw = "withdraw"
+
+```
+```typescript
+export interface PendingRecoupTask {
+ type: PendingTaskType.Recoup;
+ recoupGroupId: string;
+ retryInfo?: RetryInfo;
+ lastError: TalerErrorDetail | undefined;
+}
+
+```
+```typescript
+// Enum value:
+// PendingTaskType.Recoup = "recoup"
+
+```
+```typescript
+/**
+ * Status of an ongoing deposit operation.
+ */
+export interface PendingDepositTask {
+ type: PendingTaskType.Deposit;
+ lastError: TalerErrorDetail | undefined;
+ retryInfo: RetryInfo | undefined;
+ depositGroupId: string;
+}
+
+```
+```typescript
+export interface PendingBackupTask {
+ type: PendingTaskType.Backup;
+ backupProviderBaseUrl: string;
+ lastError: TalerErrorDetail | undefined;
+}
+
+```
+```typescript
+// Enum value:
+// PendingTaskType.Backup = "backup"
+
+```
+
+(dumpcoinsop)=
+### DumpCoinsOp
+```typescript
+/**
+ * Dump all coins of the wallet in a simple JSON format.
+ */
+export type DumpCoinsOp = {
+ request: {};
+ response: CoinDumpJson;
+};
+
+```
+```typescript
+/**
+ * Easy to process format for the public data of coins
+ * managed by the wallet.
+ */
+export interface CoinDumpJson {
+ coins: Array<{
+ /**
+ * The coin's denomination's public key.
+ */
+ denom_pub: DenominationPubKey;
+ /**
+ * Hash of denom_pub.
+ */
+ denom_pub_hash: string;
+ /**
+ * Value of the denomination (without any fees).
+ */
+ denom_value: string;
+ /**
+ * Public key of the coin.
+ */
+ coin_pub: string;
+ /**
+ * Base URL of the exchange for the coin.
+ */
+ exchange_base_url: string;
+ /**
+ * Remaining value on the coin, to the knowledge of
+ * the wallet.
+ */
+ remaining_value: string;
+ /**
+ * Public key of the parent coin.
+ * Only present if this coin was obtained via refreshing.
+ */
+ refresh_parent_coin_pub: string | undefined;
+ /**
+ * Public key of the reserve for this coin.
+ * Only present if this coin was obtained via refreshing.
+ */
+ withdrawal_reserve_pub: string | undefined;
+ /**
+ * Is the coin suspended?
+ * Suspended coins are not considered for payments.
+ */
+ coin_suspended: boolean;
+ /**
+ * Information about the age restriction
+ */
+ ageCommitmentProof: AgeCommitmentProof | undefined;
+ }>;
+}
+
+```
+```typescript
+interface Array<T> extends RelativeIndexable<T> {}
+
+```
+
+(setcoinsuspendedop)=
+### SetCoinSuspendedOp
+```typescript
+/**
+ * Set a coin as (un-)suspended.
+ * Suspended coins won't be used for payments.
+ */
+export type SetCoinSuspendedOp = {
+ request: SetCoinSuspendedRequest;
+ response: {};
+};
+
+```
+```typescript
+export interface SetCoinSuspendedRequest {
+ coinPub: string;
+ suspended: boolean;
+}
+
+```
+
+(forcerefreshop)=
+### ForceRefreshOp
+```typescript
+/**
+ * Force a refresh on coins where it would not
+ * be necessary.
+ */
+export type ForceRefreshOp = {
+ request: ForceRefreshRequest;
+ response: {};
+};
+
+```
+```typescript
+export interface ForceRefreshRequest {
+ coinPubList: string[];
+}
+
+```
+
+## Common Declarations
+```typescript
+export interface OrderShortInfo {
+ /**
+ * Order ID, uniquely identifies the order within a merchant instance
+ */
+ orderId: string;
+ /**
+ * Hash of the contract terms.
+ */
+ contractTermsHash: string;
+ /**
+ * More information about the merchant
+ */
+ merchant: MerchantInfo;
+ /**
+ * Summary of the order, given by the merchant
+ */
+ summary: string;
+ /**
+ * Map from IETF BCP 47 language tags to localized summaries
+ */
+ summary_i18n?: InternationalizedString;
+ /**
+ * List of products that are part of the order
+ */
+ products: Product[] | undefined;
+ /**
+ * Time indicating when the order should be delivered.
+ * May be overwritten by individual products.
+ */
+ delivery_date?: TalerProtocolTimestamp;
+ /**
+ * Delivery location for (all!) products.
+ */
+ delivery_location?: Location;
+ /**
+ * URL of the fulfillment, given by the merchant
+ */
+ fulfillmentUrl?: string;
+ /**
+ * Plain text message that should be shown to the user
+ * when the payment is complete.
+ */
+ fulfillmentMessage?: string;
+ /**
+ * Translations of fulfillmentMessage.
+ */
+ fulfillmentMessage_i18n?: InternationalizedString;
+}
+```
+```typescript
+export interface MerchantInfo {
+ name: string;
+ jurisdiction?: Location;
+ address?: Location;
+ logo?: string;
+ website?: string;
+ email?: string;
+}
+```
+```typescript
+export interface Location {
+ country?: string;
+ country_subdivision?: string;
+ district?: string;
+ town?: string;
+ town_location?: string;
+ post_code?: string;
+ street?: string;
+ building_name?: string;
+ building_number?: string;
+ address_lines?: string[];
+}
+```
+```typescript
+export interface InternationalizedString {
+ [lang_tag: string]: string;
+}
+```
+```typescript
+export interface Product {
+ product_id?: string;
+ description: string;
+ description_i18n?: {
+ [lang_tag: string]: string;
+ };
+ quantity?: number;
+ unit?: string;
+ price?: AmountString;
+ image?: string;
+ taxes?: Tax[];
+ delivery_date?: TalerProtocolTimestamp;
+}
+```
+```typescript
+export interface Tax {
+ name: string;
+ tax: AmountString;
+}
+```
+```typescript
+export interface TalerProtocolTimestamp {
+ readonly t_s: number | "never";
+}
+```
+```typescript
+// Enum value:
+// PendingTaskType.Refresh = "refresh"
+```
+```typescript
+// Enum value:
+// PendingTaskType.Deposit = "deposit"
+```
+```typescript
+export interface ExchangeListItem {
+ exchangeBaseUrl: string;
+ currency: string;
+ paytoUris: string[];
+ tos: ExchangeTos;
+}
+```
+```typescript
+export interface ExchangeTos {
+ acceptedVersion?: string;
+ currentVersion?: string;
+ contentType?: string;
+ content?: string;
+}
+```
+```typescript
+export interface ForcedDenomSel {
+ denoms: {
+ value: AmountString;
+ count: number;
+ }[];
+}
+```
+```typescript
+// Enum value:
+// ProviderPaymentType.InsufficientBalance = "insufficient-balance"
+```
+```typescript
+/**
+ * Contract terms from a merchant.
+ */
+export interface ContractTerms {
+ /**
+ * Hash of the merchant's wire details.
+ */
+ h_wire: string;
+ /**
+ * Hash of the merchant's wire details.
+ */
+ auto_refund?: TalerProtocolDuration;
+ /**
+ * Wire method the merchant wants to use.
+ */
+ wire_method: string;
+ /**
+ * Human-readable short summary of the contract.
+ */
+ summary: string;
+ summary_i18n?: InternationalizedString;
+ /**
+ * Nonce used to ensure freshness.
+ */
+ nonce: string;
+ /**
+ * Total amount payable.
+ */
+ amount: string;
+ /**
+ * Auditors accepted by the merchant.
+ */
+ auditors: AuditorHandle[];
+ /**
+ * Deadline to pay for the contract.
+ */
+ pay_deadline: TalerProtocolTimestamp;
+ /**
+ * Maximum deposit fee covered by the merchant.
+ */
+ max_fee: string;
+ /**
+ * Information about the merchant.
+ */
+ merchant: MerchantInfo;
+ /**
+ * Public key of the merchant.
+ */
+ merchant_pub: string;
+ /**
+ * Time indicating when the order should be delivered.
+ * May be overwritten by individual products.
+ */
+ delivery_date?: TalerProtocolTimestamp;
+ /**
+ * Delivery location for (all!) products.
+ */
+ delivery_location?: Location;
+ /**
+ * List of accepted exchanges.
+ */
+ exchanges: ExchangeHandle[];
+ /**
+ * Products that are sold in this contract.
+ */
+ products?: Product[];
+ /**
+ * Deadline for refunds.
+ */
+ refund_deadline: TalerProtocolTimestamp;
+ /**
+ * Deadline for the wire transfer.
+ */
+ wire_transfer_deadline: TalerProtocolTimestamp;
+ /**
+ * Time when the contract was generated by the merchant.
+ */
+ timestamp: TalerProtocolTimestamp;
+ /**
+ * Order id to uniquely identify the purchase within
+ * one merchant instance.
+ */
+ order_id: string;
+ /**
+ * Base URL of the merchant's backend.
+ */
+ merchant_base_url: string;
+ /**
+ * Fulfillment URL to view the product or
+ * delivery status.
+ */
+ fulfillment_url?: string;
+ /**
+ * URL meant to share the shopping cart.
+ */
+ public_reorder_url?: string;
+ /**
+ * Plain text fulfillment message in the merchant's default language.
+ */
+ fulfillment_message?: string;
+ /**
+ * Internationalized fulfillment messages.
+ */
+ fulfillment_message_i18n?: InternationalizedString;
+ /**
+ * Share of the wire fee that must be settled with one payment.
+ */
+ wire_fee_amortization?: number;
+ /**
+ * Maximum wire fee that the merchant agrees to pay for.
+ */
+ max_wire_fee?: string;
+ minimum_age?: number;
+ /**
+ * Extra data, interpreted by the mechant only.
+ */
+ extra?: any;
+}
+```
+```typescript
+export interface TalerProtocolDuration {
+ readonly d_us: number | "forever";
+}
+```
+```typescript
+export interface AuditorHandle {
+ /**
+ * Official name of the auditor.
+ */
+ name: string;
+ /**
+ * Master public signing key of the auditor.
+ */
+ auditor_pub: string;
+ /**
+ * Base URL of the auditor.
+ */
+ url: string;
+}
+```
+```typescript
+/**
+ * Information about an exchange as stored inside a
+ * merchant's contract terms.
+ */
+export interface ExchangeHandle {
+ /**
+ * Master public signing key of the exchange.
+ */
+ master_pub: string;
+ /**
+ * Base URL of the exchange.
+ */
+ url: string;
+}
+```
+```typescript
+/**
+ * Forced coin selection for deposits/payments.
+ */
+export interface ForcedCoinSel {
+ coins: {
+ value: AmountString;
+ contribution: AmountString;
+ }[];
+}
+```
+```typescript
+// Enum value:
+// ProviderPaymentType.Pending = "pending"
+```
+```typescript
+export interface TalerErrorDetail {
+ code: TalerErrorCode;
+ hint?: string;
+ [x: string]: unknown;
+}
+```
+```typescript
+export interface BackupRecovery {
+ walletRootPriv: string;
+ providers: {
+ url: string;
+ }[];
+}
+```
+```typescript
+export interface AbsoluteTime {
+ /**
+ * Timestamp in milliseconds.
+ */
+ readonly t_ms: number | "never";
+}
+```
+```typescript
+export interface Duration {
+ /**
+ * Duration in milliseconds.
+ */
+ readonly d_ms: number | "forever";
+}
+```
diff --git a/extract-tsdefs/package.json b/extract-tsdefs/package.json
new file mode 100644
index 0000000..cf3ba34
--- /dev/null
+++ b/extract-tsdefs/package.json
@@ -0,0 +1,19 @@
+{
+ "name": "extract-tsdefs",
+ "version": "0.0.1",
+ "description": "",
+ "main": "index.js",
+ "scripts": {
+ "compile": "tsc",
+ "test": "echo \"Error: no test specified\" && exit 1"
+ },
+ "keywords": [],
+ "author": "",
+ "license": "GPL-3.0",
+ "devDependencies": {
+ "@types/node": "^18.8.1",
+ "@types/prettier": "^2.7.1",
+ "prettier": "^2.7.1",
+ "typescript": "^4.8.4"
+ }
+}
diff --git a/extract-tsdefs/pnpm-lock.yaml b/extract-tsdefs/pnpm-lock.yaml
new file mode 100644
index 0000000..9de1119
--- /dev/null
+++ b/extract-tsdefs/pnpm-lock.yaml
@@ -0,0 +1,35 @@
+lockfileVersion: 5.4
+
+specifiers:
+ '@types/node': ^18.8.1
+ '@types/prettier': ^2.7.1
+ prettier: ^2.7.1
+ typescript: ^4.8.4
+
+devDependencies:
+ '@types/node': 18.8.1
+ '@types/prettier': 2.7.1
+ prettier: 2.7.1
+ typescript: 4.8.4
+
+packages:
+
+ /@types/node/18.8.1:
+ resolution: {integrity: sha512-vuYaNuEIbOYLTLUAJh50ezEbvxrD43iby+lpUA2aa148Nh5kX/AVO/9m1Ahmbux2iU5uxJTNF9g2Y+31uml7RQ==}
+ dev: true
+
+ /@types/prettier/2.7.1:
+ resolution: {integrity: sha512-ri0UmynRRvZiiUJdiz38MmIblKK+oH30MztdBVR95dv/Ubw6neWSb8u1XpRb72L4qsZOhz+L+z9JD40SJmfWow==}
+ dev: true
+
+ /prettier/2.7.1:
+ resolution: {integrity: sha512-ujppO+MkdPqoVINuDFDRLClm7D78qbDt0/NR+wp5FqEZOoTNAjPHWj17QRhu7geIHJfcNhRk1XVQmF8Bp3ye+g==}
+ engines: {node: '>=10.13.0'}
+ hasBin: true
+ dev: true
+
+ /typescript/4.8.4:
+ resolution: {integrity: sha512-QCh+85mCy+h0IGff8r5XWzOVSbBO+KfeYrMQh7NJ58QujwcE22u+NUSmUxqF+un70P9GXKxa2HCNiTTMJknyjQ==}
+ engines: {node: '>=4.2.0'}
+ hasBin: true
+ dev: true
diff --git a/extract-tsdefs/tsconfig.json b/extract-tsdefs/tsconfig.json
new file mode 100644
index 0000000..83ee9e2
--- /dev/null
+++ b/extract-tsdefs/tsconfig.json
@@ -0,0 +1,103 @@
+{
+ "compilerOptions": {
+ /* Visit https://aka.ms/tsconfig to read more about this file */
+
+ /* Projects */
+ // "incremental": true, /* Save .tsbuildinfo files to allow for incremental compilation of projects. */
+ // "composite": true, /* Enable constraints that allow a TypeScript project to be used with project references. */
+ // "tsBuildInfoFile": "./.tsbuildinfo", /* Specify the path to .tsbuildinfo incremental compilation file. */
+ // "disableSourceOfProjectReferenceRedirect": true, /* Disable preferring source files instead of declaration files when referencing composite projects. */
+ // "disableSolutionSearching": true, /* Opt a project out of multi-project reference checking when editing. */
+ // "disableReferencedProjectLoad": true, /* Reduce the number of projects loaded automatically by TypeScript. */
+
+ /* Language and Environment */
+ "target": "es2016", /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */
+ // "lib": [], /* Specify a set of bundled library declaration files that describe the target runtime environment. */
+ // "jsx": "preserve", /* Specify what JSX code is generated. */
+ // "experimentalDecorators": true, /* Enable experimental support for TC39 stage 2 draft decorators. */
+ // "emitDecoratorMetadata": true, /* Emit design-type metadata for decorated declarations in source files. */
+ // "jsxFactory": "", /* Specify the JSX factory function used when targeting React JSX emit, e.g. 'React.createElement' or 'h'. */
+ // "jsxFragmentFactory": "", /* Specify the JSX Fragment reference used for fragments when targeting React JSX emit e.g. 'React.Fragment' or 'Fragment'. */
+ // "jsxImportSource": "", /* Specify module specifier used to import the JSX factory functions when using 'jsx: react-jsx*'. */
+ // "reactNamespace": "", /* Specify the object invoked for 'createElement'. This only applies when targeting 'react' JSX emit. */
+ // "noLib": true, /* Disable including any library files, including the default lib.d.ts. */
+ // "useDefineForClassFields": true, /* Emit ECMAScript-standard-compliant class fields. */
+ // "moduleDetection": "auto", /* Control what method is used to detect module-format JS files. */
+
+ /* Modules */
+ "module": "commonjs", /* Specify what module code is generated. */
+ // "rootDir": "./", /* Specify the root folder within your source files. */
+ // "moduleResolution": "node", /* Specify how TypeScript looks up a file from a given module specifier. */
+ // "baseUrl": "./", /* Specify the base directory to resolve non-relative module names. */
+ // "paths": {}, /* Specify a set of entries that re-map imports to additional lookup locations. */
+ // "rootDirs": [], /* Allow multiple folders to be treated as one when resolving modules. */
+ // "typeRoots": [], /* Specify multiple folders that act like './node_modules/@types'. */
+ // "types": [], /* Specify type package names to be included without being referenced in a source file. */
+ // "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */
+ // "moduleSuffixes": [], /* List of file name suffixes to search when resolving a module. */
+ // "resolveJsonModule": true, /* Enable importing .json files. */
+ // "noResolve": true, /* Disallow 'import's, 'require's or '<reference>'s from expanding the number of files TypeScript should add to a project. */
+
+ /* JavaScript Support */
+ // "allowJs": true, /* Allow JavaScript files to be a part of your program. Use the 'checkJS' option to get errors from these files. */
+ // "checkJs": true, /* Enable error reporting in type-checked JavaScript files. */
+ // "maxNodeModuleJsDepth": 1, /* Specify the maximum folder depth used for checking JavaScript files from 'node_modules'. Only applicable with 'allowJs'. */
+
+ /* Emit */
+ // "declaration": true, /* Generate .d.ts files from TypeScript and JavaScript files in your project. */
+ // "declarationMap": true, /* Create sourcemaps for d.ts files. */
+ // "emitDeclarationOnly": true, /* Only output d.ts files and not JavaScript files. */
+ // "sourceMap": true, /* Create source map files for emitted JavaScript files. */
+ // "outFile": "./", /* Specify a file that bundles all outputs into one JavaScript file. If 'declaration' is true, also designates a file that bundles all .d.ts output. */
+ "outDir": "./dist", /* Specify an output folder for all emitted files. */
+ // "removeComments": true, /* Disable emitting comments. */
+ // "noEmit": true, /* Disable emitting files from a compilation. */
+ // "importHelpers": true, /* Allow importing helper functions from tslib once per project, instead of including them per-file. */
+ // "importsNotUsedAsValues": "remove", /* Specify emit/checking behavior for imports that are only used for types. */
+ // "downlevelIteration": true, /* Emit more compliant, but verbose and less performant JavaScript for iteration. */
+ // "sourceRoot": "", /* Specify the root path for debuggers to find the reference source code. */
+ // "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */
+ // "inlineSourceMap": true, /* Include sourcemap files inside the emitted JavaScript. */
+ // "inlineSources": true, /* Include source code in the sourcemaps inside the emitted JavaScript. */
+ // "emitBOM": true, /* Emit a UTF-8 Byte Order Mark (BOM) in the beginning of output files. */
+ // "newLine": "crlf", /* Set the newline character for emitting files. */
+ // "stripInternal": true, /* Disable emitting declarations that have '@internal' in their JSDoc comments. */
+ // "noEmitHelpers": true, /* Disable generating custom helper functions like '__extends' in compiled output. */
+ // "noEmitOnError": true, /* Disable emitting files if any type checking errors are reported. */
+ // "preserveConstEnums": true, /* Disable erasing 'const enum' declarations in generated code. */
+ // "declarationDir": "./", /* Specify the output directory for generated declaration files. */
+ // "preserveValueImports": true, /* Preserve unused imported values in the JavaScript output that would otherwise be removed. */
+
+ /* Interop Constraints */
+ // "isolatedModules": true, /* Ensure that each file can be safely transpiled without relying on other imports. */
+ // "allowSyntheticDefaultImports": true, /* Allow 'import x from y' when a module doesn't have a default export. */
+ "esModuleInterop": true, /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables 'allowSyntheticDefaultImports' for type compatibility. */
+ // "preserveSymlinks": true, /* Disable resolving symlinks to their realpath. This correlates to the same flag in node. */
+ "forceConsistentCasingInFileNames": true, /* Ensure that casing is correct in imports. */
+
+ /* Type Checking */
+ "strict": true, /* Enable all strict type-checking options. */
+ // "noImplicitAny": true, /* Enable error reporting for expressions and declarations with an implied 'any' type. */
+ // "strictNullChecks": true, /* When type checking, take into account 'null' and 'undefined'. */
+ // "strictFunctionTypes": true, /* When assigning functions, check to ensure parameters and the return values are subtype-compatible. */
+ // "strictBindCallApply": true, /* Check that the arguments for 'bind', 'call', and 'apply' methods match the original function. */
+ // "strictPropertyInitialization": true, /* Check for class properties that are declared but not set in the constructor. */
+ // "noImplicitThis": true, /* Enable error reporting when 'this' is given the type 'any'. */
+ // "useUnknownInCatchVariables": true, /* Default catch clause variables as 'unknown' instead of 'any'. */
+ // "alwaysStrict": true, /* Ensure 'use strict' is always emitted. */
+ // "noUnusedLocals": true, /* Enable error reporting when local variables aren't read. */
+ // "noUnusedParameters": true, /* Raise an error when a function parameter isn't read. */
+ // "exactOptionalPropertyTypes": true, /* Interpret optional property types as written, rather than adding 'undefined'. */
+ // "noImplicitReturns": true, /* Enable error reporting for codepaths that do not explicitly return in a function. */
+ // "noFallthroughCasesInSwitch": true, /* Enable error reporting for fallthrough cases in switch statements. */
+ // "noUncheckedIndexedAccess": true, /* Add 'undefined' to a type when accessed using an index. */
+ // "noImplicitOverride": true, /* Ensure overriding members in derived classes are marked with an override modifier. */
+ // "noPropertyAccessFromIndexSignature": true, /* Enforces using indexed accessors for keys declared using an indexed type. */
+ // "allowUnusedLabels": true, /* Disable error reporting for unused labels. */
+ // "allowUnreachableCode": true, /* Disable error reporting for unreachable code. */
+
+ /* Completeness */
+ // "skipDefaultLibCheck": true, /* Skip type checking .d.ts files that are included with TypeScript. */
+ "skipLibCheck": true /* Skip type checking all .d.ts files. */
+ }
+}
diff --git a/frags/using-taler-config.rst b/frags/using-taler-config.rst
index c15df84..9e6df14 100644
--- a/frags/using-taler-config.rst
+++ b/frags/using-taler-config.rst
@@ -39,10 +39,8 @@ compare:
.. code-block:: console
- $ taler-config -s ACCOUNT-bank \
- -o WIRE_RESPONSE
- $ taler-config -f -s ACCOUNT-bank \
- -o WIRE_RESPONSE
+ $ taler-config --section exchange-offline --option MASTER_PRIV_FILE
+ $ taler-config -f --section exchange-offline --option MASTER_PRIV_FILE
While the configuration file is typically located at
``$HOME/.config/taler.conf``, an alternative location can be specified
diff --git a/index.rst b/index.rst
index 1d63e79..3d3b305 100644
--- a/index.rst
+++ b/index.rst
@@ -66,6 +66,7 @@ Documentation Overview
taler-auditor-manual
taler-developer-manual
taler-wallet
+ wallet/wallet-core
design-documents/index
libeufin/index
global-licensing
diff --git a/libeufin/api-sandbox-future.rst b/libeufin/api-sandbox-future.rst
new file mode 100644
index 0000000..06dfc68
--- /dev/null
+++ b/libeufin/api-sandbox-future.rst
@@ -0,0 +1,135 @@
+Future Sandbox API
+##################
+
+Resources.
+^^^^^^^^^^
+
+Sandbox serves the following resources:
+
+ - Demobanks.
+ - Bank accounts.
+ - Subscribers.
+ - Transactions.
+ - Customers.
+ - Reports.
+
+The resources are subject to all CRUD operations, via by two
+types of users: the 'admin' and the customers. The admin has
+rights on all of them.
+
+One of the main differences with the previous versions is the
+removal of the "/admin" initial component. If the administrator
+authenticates for one operation, then this one is of type ``admin``:
+no need for a dedicated and extra URI path component.
+
+For example, mocking transactions in the system was a typical
+/admin-operation, but since transactions themselves are resources
+and any resource is subject to CRUD operations, then mocking one
+becomes just a ``C`` operation on the 'transactions' resources. If
+a test case wants to simplify the authentication - by hard-coding
+the credentials, for example - before mocking one transaction, then
+it can impersonate the administrator.
+
+.. note::
+
+ ``POST``\ ing to an endpoint with a trailing ``$id`` means
+ modification of an existing resource.
+
+Demobanks
+^^^^^^^^^
+
+Demobanks are the main containers of all the other resources.
+They take configuration values, like the currency for example.
+
+.. http:get:: /admin/demobanks
+.. http:get:: /admin/demobanks/$id
+.. http:post:: /admin/demobanks
+.. http:post:: /admin/demobanks/$id
+.. http:delete:: /admin/demobanks/$id
+
+Bank accounts.
+^^^^^^^^^^^^^^
+
+Bank accounts collect money of customers and participate
+in transactions.
+
+The ``$base`` is one demobank, in the form ``/demobanks/$id``.
+That is due because a bank account must inherit some defaults
+from the demobank, like the currency.
+
+.. http:get:: $base/bankaccounts
+.. http:get:: $base/bankaccounts/$id
+.. http:post:: $base/bankaccounts
+.. http:post:: $base/bankaccounts/$id
+.. http:delete:: $base/bankaccounts/$id
+
+Subscribers.
+^^^^^^^^^^^^
+
+Subscribers are (optional) customers identities for protocols
+other than the native one.
+
+A subscriber is not required to have a bank account "soon". Therefore,
+it can be created, and later be linked to one bank account. For this
+reason, the ``$base`` should not mention one bank account.
+
+.. note::
+
+ Creating a subscriber is a time-consuming operation that goes often
+ through slow channels, therefore it should basically never be done
+ more than once.
+
+.. http:get:: $base/subscribers
+.. http:get:: $base/subscribers/$id
+.. http:post:: $base/subscribers
+.. http:post:: $base/subscribers/$id
+.. http:delete:: $base/subscribers/$id
+
+Transactions.
+^^^^^^^^^^^^^
+
+Transactions are money movements between bank accounts.
+
+For convenience, ``$base`` **could** mention one bank account
+to let customers see their transactions without defining "history"
+query parameters: like ``$demobank/bankaccounts/$bankaccountId/transactions``.
+
+At the same time, transactions should be easy to query regardless
+of whose bank account they involve -- for administrative reasons, for
+example. Hence, a "global" URI scheme like ``$demobank/transactions?param=XXX``
+should be offered as well.
+
+.. http:get:: $base/transactions
+.. http:get:: $base/transactions/$id
+.. http:post:: $base/transactions
+.. http:post:: $base/transactions/$id
+.. http:delete:: $base/transactions/$id
+
+Customers.
+^^^^^^^^^^
+
+Customers are persons that **can** have one bank account. As
+with subscribers, ``$base`` should not mention any bank account
+so as to leave more flexibility to assign new bank accounts to
+the same customer.
+
+.. http:get:: $base/customers
+.. http:get:: $base/customers/$id
+.. http:post:: $base/customers
+.. http:post:: $base/customers/$id
+.. http:delete:: $base/customers/$id
+
+Reports.
+^^^^^^^^
+
+Reports are persistent documents witnessing transactions.
+A typical example is a Camt.053 statement. A report lives
+even after a bank account gets deleted or a customer leaves
+the bank, therefore ``$base`` should only mention a demobank
+instance.
+
+.. http:get:: $base/reports
+.. http:get:: $base/reports/$id
+.. http:post:: $base/reports
+.. http:post:: $base/reports/$id
+.. http:delete:: $base/reports/$id
diff --git a/libeufin/api-sandbox.rst b/libeufin/api-sandbox.rst
index f6ff682..0149d4d 100644
--- a/libeufin/api-sandbox.rst
+++ b/libeufin/api-sandbox.rst
@@ -2,95 +2,316 @@
.. _sandbox-api:
-Current Sandbox API
-###################
+Sandbox API
+###########
-..
- Current Sandbox endpoints.
+Demobanks.
+==========
- GET /
- Welcome message.
+Sandbox is designed to allow multiple *demobanks* being hosted,
+where every demobank can have its own configuration (including
+a different currency). A demobank has a name, although currently
+only one demobank, named ``default``, is supported. Such demobank
+activates the API segment ``/demobanks/default``, under which several
+APIs are then served. The following sections describe all such APIs.
- ** Camt debug **
+Customer API.
+^^^^^^^^^^^^^
+
+This API allows CRUD operations on the bank's customers (also referred
+as 'users'). All the calls are allowed for the administrator, whereas
+**only** the `password change <customer-password-modification>`_ is allowed
+for ordinary customers.
+
+The following endpoints are served under ``/demobanks/default/customer-api``.
+
+.. http:post:: /customers
+
+ Create a new customer, including their bank account.
+
+ **Request:**
+
+ .. ts:def:: CustomerRequest
+
+ interface CustomerRequest {
+ // Username
+ username: string;
+
+ // Password.
+ password: string;
+
+ // E-Mail address
+ email: string;
+
+ // Phone number.
+ phone: string;
+
+ // Name denoting the legal subject being the customer.
+ name: string;
+
+ // 'payto' address pointing the bank account
+ // where to send payments, in case the customer
+ // wants to convert the local currency back to
+ // fiat.
+ payoutAddress: string;
+
+ // IBAN to assign to this bank account. Randomly
+ // generated, when it is not given.
+ iban?: string;
+ }
+
+ **Response:**
+
+ :http:statuscode:`204 No content`:
+ The customer was successfully created.
+ :http:statuscode:`409 Conflict`:
+ One information was not available, the error message should inform
+ about it.
+ :http:statuscode:`403 Forbidden`:
+ A istitutional username was attempted, like ``admin`` or ``bank``.
+ :http:statuscode:`404 Bad request`:
+ Input data was invalid. For example, the client specified a invalid
+ phone number or e-mail.
+
+
+.. http:delete:: /customers
+
+ Delete a customer *with a zero balance* from the bank.
+
+ **Request:**
+
+ :query username: the username of the customer account to delete.
+
+ **Response:**
+
+ :http:statuscode:`204 No content`:
+ The customer account was successfully deleted.
+ :http:statuscode:`404 Not found`:
+ The customer specified along the parameters was not found.
+ :http:statuscode:`403 Forbidden`:
+ The administrator specified a istitutional username, like
+ ``admin`` or ``bank``.
+ :http:statuscode:`412 Precondition failed`:
+ The balance of the customer to delete was not zero.
+
+.. _customer-password-modification:
- POST /admin/payments/camt
- give last statement of requesting account
+.. http:patch:: /customers
- ** Bank accounting **
+ Allows administrators *and* ordinary customers to
+ change customer password.
- POST /admin/bank-accounts/$accountLabel
- create bank account (no EBICS involved)
+ **Request:**
+
+ .. ts:def:: CustomerPasswordChange
+
+ interface Customer {
+ // Username of the customer whose password is
+ // to be changed. It is optional in case the
+ // customer issues the request, because such information
+ // can be retrieved from the authentication credentials.
+ username?: string;
+
+ // New password.
+ newPassword: string;
+ }
- GET /admin/bank-accounts
- Give summary of all the bank accounts.
+ **Response:**
- GET /admin/bank-accounts/$accountLabel
- give general information about a bank account
+ :http:statuscode:`204 No content`:
+ Operation successful.
+ :http:statuscode:`403 Forbidden`:
+ A ordinary customer tried to change someone else's password.
+ This error should happen *before* checking whether the target
+ username exists, not to leak which usernames are already registered.
+ :http:statuscode:`404 Not found`:
+ The username whose password should be changed was not found.
- ** Transactions **
+.. http:get:: /customers
+
+ Allows the administrator to obtain a list of all the
+ customers registered at the bank. It returns only the
+ customer data (without any business information), because
+ :doc:`Access API </core/api-bank-access>` may already
+ be used for that.
+
+ **Response:**
- POST /admin/bank-accounts/$accountLabel/simulate-incoming-transaction
- Book one incoming transaction for $accountLabel.
- The debtor (not required to be in the same bank)
- information is taken from the request.
+ .. ts:def:: Customers
- GET /admin/bank-accounts/$accountLabel/transactions
- Inform about all the transactions of one bank account.
+ interfaces Customers {
+ customers: CustomerData[];
+ }
- POST /admin/bank-accounts/$accountLabel/generate-transactions
- Generate one incoming and one outgoing transaction
- for one bank account.
+ .. ts:def:: CustomerData
+
+ interface CustomerData {
+ // Username
+ username: string;
- ** EBICS subscribers management **
+ // IBAN hosted at Libeufin Sandbox
+ iban: string;
- POST /admin/ebics/subscribers
- Create a new EBICS subscriber.
+ // E-Mail address
+ email: string;
- GET /admin/ebics/subscribers
- Give details of all the EBICS subscribers in the bank.
+ // Phone number.
+ phone: string;
- POST /admin/ebics/bank-accounts
- Create a *new* bank account and link it with an existing
- EBICS subscriber.
+ // Name denoting the legal subject being the customer.
+ name: string;
- ** EBICS host management **
+ // 'payto' address pointing the bank account
+ // where to send payments, in case the customer
+ // wants to convert the local currency back to
+ // fiat.
+ cashoutAddress: string;
+ }
- POST /admin/ebics/hosts/$hostID/rotate-keys
- Change the bank's keys used in EBICS communication.
- POST /admin/ebics/hosts
- Create a new EBICS host.
+.. http:post:: /cashouts
- GET /admin/ebics/hosts
- Show details of all the EBICS hosts in the bank.
+ Lets the user specify an amount to be converted back
+ to fiat currency. The target account is the one specified
+ at registration time. The account to be debited is extracted
+ from the authentication credentials. The bank sends a TAN
+ to the customer, to let them confirm the operation.
- ** EBICS serving **
+ ..
+ FIXME: TAN first per e-mail, or phone?
- POST /ebicsweb
- Processes a EBICS request.
+ **Request:**
- ** Taler .. **
+ .. ts:def:: CashoutRequest
- GET /taler
- Show one taler://-URI to initiate a withdrawal.
+ interface CashoutRequest {
+ // Amount in the $currency:$value format.
+ amount: string;
+ }
- - Taler integration API.
+ **Response:**
- - Demobank configuration API.
- ToDo.
+ .. ts:def:: CashoutPending
+
+ interface CashoutPending {
+ // UUID identifying the operation being created
+ // and now waiting the TAN confirmation.
+ uuid: string;
+ }
+
+ :http:statuscode:`202 Accepted`:
+ The cashout request was correctly created and
+ the TAN authentication now is pending.
+ :http:statuscode:`412 Precondition failed`:
+ Customer does not have sufficient funds.
+ :http:statuscode:`409 Conflict`:
+ A istitutional user (``admin`` or ``bank``) tried the operation.
+
+
+.. http:post:: /cashouts/$cashoutId
+
+ Confirms the cashout with UUID $cashoutId by
+ accepting its TAN. Please note that the request
+ should still be authenticated with the users credentials.
+
+ **Request:**
+
+ .. ts:def:: CashoutConfirm
+
+ interface CashoutConfirm {
+
+ // the TAN that was shared by the bank that
+ // confirms $cashoutId.
+ tan: string;
+ }
+
+
+ **Response:**
+
+ :http:statuscode:`200 OK`:
+ cashout confirmed.
+ :http:statuscode:`401 Unauthorized`:
+ wrong TAN.
+ :http:statuscode:`409 Conflict`:
+ A istitutional user (``admin`` or ``bank``) tried the operation.
- - Taler access API.
- ToDo.
+Access API.
+^^^^^^^^^^^
-EBICS.
-^^^^^^
+Every endpoint is served under ``/demobanks/default/access-api``.
+See :doc:`/core/api-bank-access`. This API allows users to access
+their bank accounts and trigger Taler withdrawals.
-Hosts.
-++++++
+Integration API.
+^^^^^^^^^^^^^^^^
+
+Every endpoint is served under ``/demobanks/default/integration-api``.
+See :doc:`/core/api-bank-integration`. This API handles the communication
+with Taler wallets.
+
+Taler Wire Gateway API.
+^^^^^^^^^^^^^^^^^^^^^^^
+
+Served under ``/demobanks/default/taler-wire-gateway``. Currently,
+only the :ref:`admin/add-incoming <twg-admin-add-incoming>` endpoint
+is implemented. This endpoint allows testing, but the rest of
+this API does never involve the Sandbox.
+
+EBICS API.
+^^^^^^^^^^
+
+.. _demobank-create-ebics-subscriber:
+
+.. http:post:: /demobanks/default/ebics/subscribers
+
+ Allows (only) the *admin* user to associate a bank account
+ to a EBICS subscriber. If the latter does not exist, it is
+ created.
+
+ **Request:**
+
+ .. ts:def:: SubscriberRequest
+
+ interface SubscriberRequest {
+
+ // hostID
+ hostID: string;
+
+ // userID
+ userID: string;
+
+ // partnerID
+ partnerID: string;
+
+ // systemID, optional.
+ systemID: string;
+
+ // Label of the bank account to associate with
+ // this subscriber.
+ demobankAccountLabel: string;
+ }
+
+.. note::
+
+ The following endpoints are **not** served under the ``/demobank/default`` segment.
+
+Legacy API.
+===========
+
+This was the first API offered by Sandbox. It is used in
+some test cases. One is hosted at the Wallet repository; other
+MAY as well exist.
+
+Except of the main EBICS handler located at "/ebicsweb", all
+the EBICS calls have to authenticate the 'admin' user via
+the HTTP basic auth scheme.
+
+EBICS Hosts.
+^^^^^^^^^^^^
.. http:post:: /admin/ebics/hosts
- Creates a new Ebics host.
+ Create a new EBICS host.
**Request:**
@@ -128,9 +349,8 @@ Hosts.
meant for tests (as the Sandbox itself is) and no backup will be
produced along this operation.
-
-Subscribers.
-++++++++++++
+EBICS Subscribers.
+^^^^^^^^^^^^^^^^^^
.. http:post:: /admin/ebics/bank-accounts
@@ -143,7 +363,11 @@ Subscribers.
interface BankAccountRequest {
// Ebics subscriber
- subscriber: string;
+ subscriber: {
+ userID: string;
+ partnerID: string;
+ systemID: string;
+ };
// IBAN
iban: string;
@@ -157,39 +381,13 @@ Subscribers.
// bank account label
label: string;
- }
-
-
-.. http:post:: /admin/ebics/subscribers
-
- Creates a new Ebics subscriber.
-
- **Request:**
-
- .. ts:def:: SubscriberRequest
-
- interface SubscriberRequest {
-
- // hostID
- hostID: string;
+ // Customer username that owns the bank account.
+ // Currency policy only allows same-named usernames
+ // and bank accounts.
+ owner: string;
- // userID
- userID: string;
-
- // partnerID
- partnerID: string;
-
- // systemID, optional.
- systemID: string;
-
- // Label of the bank account to associate with
- // this subscriber. Note: the demobank name is
- // omitted because every creation should happen
- // under the /demobanks trunk.
- demobankAccountLabel: string;
}
-
.. http:get:: /admin/ebics/subscribers
Shows the list of all the subscribers in the system.
@@ -221,209 +419,258 @@ Subscribers.
demobankAccountLabel: string;
}
+.. http:post:: /admin/ebics/subscribers
+
+ Create a new EBICS subscriber without associating
+ a bank account to it. This call is **deprecated**.
+ Follow `this page <https://bugs.gnunet.org/view.php?id=7507>`_
+ for updates over the EBICS management REST design.
+
+ .. ts:def:: SubscriberRequestDeprecated
+
+ interface SubscriberRequestDeprecated {
+
+ // hostID
+ hostID: string;
+
+ // userID
+ userID: string;
+
+ // partnerID
+ partnerID: string;
+
+ // systemID, optional.
+ systemID: string;
+
+ }
Bank accounts.
^^^^^^^^^^^^^^
+The access to a particular bank account is granted either to the
+owner or to admin, via the HTTP basic auth scheme. A 'owner' is
+a registered customer, who is identified by a username. The
+registration of customers is offered via the :doc:`/core/api-bank-access`.
+
+.. note::
+
+ The current version allows only one bank account per
+ customer, where the bank account name (also called 'label')
+ equals the owner's username.
+
.. http:get:: /admin/bank-accounts
- Give summary of all the bank accounts.
+ Give summary of all the bank accounts. Only admin allowed.
+
+ **Response:**
+
+ .. ts:def:: AdminBankAccount
+
+ interface AdminBankAccount {
+
+ // IBAN
+ iban: string;
+
+ // BIC
+ bic: string;
+
+ // human name
+ name: string;
+
+ // bank account label
+ label: string;
+ }
+
.. http:get:: /admin/bank-accounts/$accountLabel
Give information about a bank account.
-.. http:delete:: /demobanks/$demobankId/$accountLabel
+ **Response:**
- Delete the bank account (and the customer entry) from the database.
- Note, customer usernames and bank accounts have the same value.
+ .. ts:def:: AdminBankAccountBalance
-Main EBICS service.
-^^^^^^^^^^^^^^^^^^^
+ interface AdminBankAccountBalance {
+ // Balance in the $currency:$amount format.
+ balance: string;
+ // IBAN of the bank account identified by $accountLabel
+ iban: string;
+ // BIC of the bank account identified by $accountLabel
+ bic: string;
+ // Mentions $accountLabel
+ label: string;
+ }
-.. http:post:: /ebicsweb
+.. http:post:: /admin/bank-accounts/$accountLabel
- Serves all the Ebics requests.
+ Create bank account. Existing users without a bank account
+ can request too.
+ **Request:** :ts:type:`AdminBankAccount`
Transactions.
^^^^^^^^^^^^^
-JSON.
-+++++
-
.. http:get:: /admin/bank-accounts/$accountLabel/transactions
Inform about all the transactions of one bank account.
-.. http:post:: /admin/bank-accounts/$accountLabel/generate-transactions
+ **Response:**
- Generate one incoming and one outgoing transaction for one bank account.
+ .. ts:def:: AdminTransactions
+
+ interface AdminTransactions {
+ payments: AdminTransaction[];
+ }
-.. http:post:: /admin/bank-accounts/$accountLabel/simulate-incoming-transaction
+ .. ts:def:: AdminTransaction
+
+ interface AdminTransaction {
- Book one incoming transaction for $accountLabel.
- The debtor (not required to be in the same bank)
- information is taken from the request.
+ // Label of the bank account involved in this payment.
+ accountLabel: string;
+ // Creditor IBAN
+ creditorIban: string;
-Camt.
-+++++
+ // Debtor IBAN
+ debtorIban: string;
-.. http:post:: /admin/payments/camt
+ // UID given by one financial institute to this payment.
+ // FIXME: clarify whether that can be also assigned by
+ // the other party's institution.
+ accountServicerReference: string;
- Return the last statement of the requesting account.
+ // ID of the Pain.001 that initiated this payment.
+ paymentInformationId: string;
- **Request**
+ // Unstructured remittance information.
+ subject: string;
- .. code-block:: tsref
+ // Date of the payment in the HTTP header format.
+ date: string;
- interface CamtParams {
+ // The number amount as a string.
+ amount: string;
- // label of the bank account being queried.
- bankaccount: string;
+ // BIC of the creditor IBAN.
+ creditorBic: string;
- // The Camt type to return. Only '53' is allowed
- // at this moment.
- type: number;
+ // Legal name of the creditor.
+ creditorName: string;
+
+ // BIC of the debtor IBAN.
+ debtorBic: string;
+
+ // Legal name of the debtor.
+ debtorName: string;
+
+ // Payment's currency
+ currency: string;
+
+ // Have values 'credit' or 'debit' relative
+ // to the requesting user.
+ creditDebitIndicator: string;
}
- **Response**
+.. http:post:: /admin/bank-accounts/$accountLabel/generate-transactions
- The expected Camt.053 document.
+ Generate one incoming and one outgoing transaction for the bank account
+ identified by ``$accountLabel``. Only admin allowed.
-Future Sandbox API
-##################
+.. http:post:: /admin/bank-accounts/$accountLabel/simulate-incoming-transaction
-Resources.
-^^^^^^^^^^
+ Book one incoming transaction for $accountLabel.
+ The debtor (not required to be in the same bank)
+ information is taken from the request. Only admin allowed.
-Sandbox serves the following resources:
+ **Request:**
+
+ .. ts:def:: AdminSimulateTransaction
- - Demobanks.
- - Bank accounts.
- - Subscribers.
- - Transactions.
- - Customers.
- - Reports.
+ interface AdminSimulateTransaction {
-The resources are subject to all CRUD operations, via by two
-types of users: the 'admin' and the customers. The admin has
-rights on all of them.
+ // Debtor IBAN.
+ debtorIban: string;
-One of the main differences with the previous versions is the
-removal of the "/admin" initial component. If the administrator
-authenticates for one operation, then this one is of type ``admin``:
-no need for a dedicated and extra URI path component.
+ // Debtor BIC.
+ debtorBic: string;
-For example, mocking transactions in the system was a typical
-/admin-operation, but since transactions themselves are resources
-and any resource is subject to CRUD operations, then mocking one
-becomes just a ``C`` operation on the 'transactions' resources. If
-a test case wants to simplify the authentication - by hard-coding
-the credentials, for example - before mocking one transaction, then
-it can impersonate the administrator.
+ // Debtor name.
+ debtorName: string;
-.. note::
+ // Amount number (without currency) as a string.
+ amount: string;
- ``POST``\ ing to an endpoint with a trailing ``$id`` means
- modification of an existing resource.
+ // Payment subject.
+ subject: string;
+ }
-Demobanks
-^^^^^^^^^
-Demobanks are the main containers of all the other resources.
-They take configuration values, like the currency for example.
+.. http:post:: /admin/payments/camt
-.. http:get:: /admin/demobanks
-.. http:get:: /admin/demobanks/$id
-.. http:post:: /admin/demobanks
-.. http:post:: /admin/demobanks/$id
-.. http:delete:: /admin/demobanks/$id
+ Return the last camt.053 document from the requesting account.
-Bank accounts.
-^^^^^^^^^^^^^^
+ **Request**
-Bank accounts collect money of customers and participate
-in transactions.
+ .. code-block:: tsref
-The ``$base`` is one demobank, in the form ``/demobanks/$id``.
-That is due because a bank account must inherit some defaults
-from the demobank, like the currency.
+ interface CamtParams {
-.. http:get:: $base/bankaccounts
-.. http:get:: $base/bankaccounts/$id
-.. http:post:: $base/bankaccounts
-.. http:post:: $base/bankaccounts/$id
-.. http:delete:: $base/bankaccounts/$id
+ // label of the bank account being queried.
+ bankaccount: string;
-Subscribers.
-^^^^^^^^^^^^
+ // The Camt type to return. Only '53' is allowed
+ // at this moment.
+ type: number;
+ }
-Subscribers are (optional) customers identities for protocols
-other than the native one.
+ **Response**
-A subscriber is not required to have a bank account "soon". Therefore,
-it can be created, and later be linked to one bank account. For this
-reason, the ``$base`` should not mention one bank account.
+ The last Camt.053 document related to the bank account
+ mentioned in the request body.
-.. note::
- Creating a subscriber is a time-consuming operation that goes often
- through slow channels, therefore it should basically never be done
- more than once.
+======
+Errors
+======
-.. http:get:: $base/subscribers
-.. http:get:: $base/subscribers/$id
-.. http:post:: $base/subscribers
-.. http:post:: $base/subscribers/$id
-.. http:delete:: $base/subscribers/$id
+The JSON type coming along a non 2xx response is the following:
-Transactions.
-^^^^^^^^^^^^^
+.. ts:def:: SandboxError
-Transactions are money movements between bank accounts.
+ interface SandboxError {
+ error: SandboxErrorDetail;
+ }
-For convenience, ``$base`` **could** mention one bank account
-to let customers see their transactions without defining "history"
-query parameters: like ``$demobank/bankaccounts/$bankaccountId/transactions``.
+.. ts:def:: SandboxErrorDetail
-At the same time, transactions should be easy to query regardless
-of whose bank account they involve -- for administrative reasons, for
-example. Hence, a "global" URI scheme like ``$demobank/transactions?param=XXX``
-should be offered as well.
+ interface SandboxErrorDetail {
-.. http:get:: $base/transactions
-.. http:get:: $base/transactions/$id
-.. http:post:: $base/transactions
-.. http:post:: $base/transactions/$id
-.. http:delete:: $base/transactions/$id
+ // String enum classifying the error.
+ type: ErrorType;
+
+ // Human-readable error description.
+ message: string;
+ }
+
+.. ts:def:: ErrorType
+
+ enum ErrorType {
+ /**
+ * This error can be related to a business operation,
+ * a non-existent object requested by the client, or
+ * even when the bank itself fails.
+ */
+ SandboxError = "sandbox-error",
+
+ /**
+ * It is the error type thrown by helper functions
+ * from the Util library. Those are used by both
+ * Sandbox and Nexus, therefore the actual meaning
+ * must be carried by the error 'message' field.
+ */
+ UtilError = "util-error"
+ }
-Customers.
-^^^^^^^^^^
-Customers are persons that **can** have one bank account. As
-with subscribers, ``$base`` should not mention any bank account
-so as to leave more flexibility to assign new bank accounts to
-the same customer.
-
-.. http:get:: $base/customers
-.. http:get:: $base/customers/$id
-.. http:post:: $base/customers
-.. http:post:: $base/customers/$id
-.. http:delete:: $base/customers/$id
-
-Reports.
-^^^^^^^^
-
-Reports are persistent documents witnessing transactions.
-A typical example is a Camt.053 statement. A report lives
-even after a bank account gets deleted or a customer leaves
-the bank, therefore ``$base`` should only mention a demobank
-instance.
-
-.. http:get:: $base/reports
-.. http:get:: $base/reports/$id
-.. http:post:: $base/reports
-.. http:post:: $base/reports/$id
-.. http:delete:: $base/reports/$id
diff --git a/manpages/taler-exchange-offline.1.rst b/manpages/taler-exchange-offline.1.rst
index 951a77e..f9a380a 100644
--- a/manpages/taler-exchange-offline.1.rst
+++ b/manpages/taler-exchange-offline.1.rst
@@ -296,13 +296,13 @@ format suitable for the ``upload`` subcommand.
wire-fee
--------
-This subcommand informs an exchange about the desired wire fee structure (that is, wire, closing and wad fees)
+This subcommand informs an exchange about the desired wire fee structure (that is, wire, and closing fees)
for particular wire method and a calendar year (!). The tool does not
permit changing wire fees during a calendar year. Also, once the wire fee has been
set for a calendar year, it cannot be changed.
The subcommand takes the year, wire-method (see RFC 8905, examples include
-``x-taler-bank`` or ``iban``), wire fee, closing fee and wad fee as arguments.
+``x-taler-bank`` or ``iban``), wire fee, and closing fee as arguments.
Instead of a year, the string ``now`` can be given for the current year
(this is mostly useful for test cases). The wire-method should follow the
GANA registry as given in RFC 8905. The fees must be given in the usual
@@ -322,8 +322,8 @@ related global configuration options for a calendar year (!). The tool does
not permit changing global fees during a calendar year. Also, once the global
fee structure has been set for a calendar year, it cannot be changed.
-The subcommand takes the year, history fee, kyc fee, account fee, purse fee,
-purse timeout, kyc timeout, history expiration and the (free) purse (per)
+The subcommand takes the year, history fee, account fee, purse fee,
+purse timeout, history expiration and the (free) purse (per)
account limit as arguments. Instead of a year, the string ``now`` can be
given for the current year (this is mostly useful for test cases). The fees
must be given in the usual Taler format of ``CURRENCY:NUMBER.FRACTION``.
diff --git a/manpages/taler-helper-auditor-purses.1.rst b/manpages/taler-helper-auditor-purses.1.rst
new file mode 100644
index 0000000..09d2367
--- /dev/null
+++ b/manpages/taler-helper-auditor-purses.1.rst
@@ -0,0 +1,75 @@
+taler-helper-auditor-purses(1)
+##############################
+
+.. only:: html
+
+ Name
+ ====
+
+ **taler-helper-auditor-purses** - Audit Taler exchange purse handling
+
+
+Synopsis
+========
+
+**taler-helper-auditor-purses**
+[**-c** *FILENAME* | **--config=**\ \ *FILENAME*]
+[**-h** | **--help**]
+[**i** | **--internal**]
+[**-L** *LOGLEVEL* | **--loglevel=**\ ‌\ *LOGLEVEL*]
+[**-l** *FILENAME* | **--logfile=**\ ‌\ *FILENAME*]
+[**-m** *KEY* | **--exchange-key=**\ \ *KEY*]
+[**-T** *USEC* | **--timetravel=**\ \ *USEC*]
+[**-v** | **--version**]
+
+
+Description
+===========
+
+**taler-helper-auditor-purses** is a command-line tool to
+audit Taler exchange purse handling.
+
+FIXME: More detail.
+
+Its options are as follows:
+
+**-c** *FILENAME* \| **--config=**\ ‌\ *FILENAME*
+ Use the configuration and other resources for the auditor to operate
+ from *FILENAME*.
+
+**-h** \| **--help**
+ Print short help on options.
+
+**-i** \| **--internal**
+ Perform checks only applicable for exchange-internal audits.
+
+**-L** *LOGLEVEL* \| **--loglevel=**\ ‌\ *LOGLEVEL*
+ Specifies the log level to use. Accepted values are: ``DEBUG``, ``INFO``,
+ ``WARNING``, ``ERROR``.
+
+**-l** *FILENAME* \| **--logfile=**\ ‌\ *FILENAME*
+ Send logging output to *FILENAME*.
+
+**-m** *KEY* \| **--exchange-key=**\ \ *KEY*
+ Use *KEY* (Crockford base32 encoded) as the public key of the exchange.
+
+**-T** *USEC* \| **--timetravel=**\ \ *USEC*
+ Modify the system time by *USEC* microseconds.
+ *USEC* may be prefixed with ``+`` or ``-`` (e.g. ``-T +300``).
+ This option is intended for debugging/testing only.
+
+**-v** \| **--version**
+ Print version information.
+
+
+See Also
+========
+
+taler-auditor(1), taler.conf(5).
+
+
+Bugs
+====
+
+Report bugs by using https://bugs.taler.net or by sending electronic
+mail to <taler@gnu.org>.
diff --git a/manpages/taler-merchant-httpd.1.rst b/manpages/taler-merchant-httpd.1.rst
index 5ea47c1..cf9192f 100644
--- a/manpages/taler-merchant-httpd.1.rst
+++ b/manpages/taler-merchant-httpd.1.rst
@@ -13,6 +13,7 @@ Synopsis
========
**taler-merchant-httpd**
+[**-a**_|_**--auth**]
[**-C** | **--connection-close**]
[**-c** *FILENAME* | **--config=**\ \ *FILENAME*]
[**-h** | **--help**]
@@ -33,9 +34,9 @@ Options
=======
**-a** *TOKEN* \| **--auth=**\ \ *TOKEN*
- Use TOKEN for initial access control to the merchant backend. The value
+ Use TOKEN for initial access control to the merchant backend. TOKEN must start with the "secret-token:" prefix, as per RFC 8959. The value
given in TOKEN must appear in backoffice requests to the default instance
- of the merchant, i.e. "Authorization: Bearer secret-token:TOKEN" to obtain
+ of the merchant, i.e. "Authorization: Bearer TOKEN" to obtain
access to the merchant backend. Note that setting a passphrase for the
default instance by any means will block future access via TOKEN. This
is basically a way to reset the passphrase protecting access. TOKEN
diff --git a/manpages/taler.conf.5.rst b/manpages/taler.conf.5.rst
index 510fd87..1c70879 100644
--- a/manpages/taler.conf.5.rst
+++ b/manpages/taler.conf.5.rst
@@ -340,6 +340,10 @@ AGGREGATOR_SHIFT
Delay between a deposit being eligible for aggregation and
the aggregator actually triggering.
+DEFAULT_PURSE_LIMIT
+ Number of concurrent purses that a reserve may have active
+ if it is paid to be opened for a year.
+
EXCHANGE POSTGRES BACKEND DATABASE OPTIONS
------------------------------------------
diff --git a/taler-developer-manual.rst b/taler-developer-manual.rst
index 09f38b8..c348a1d 100644
--- a/taler-developer-manual.rst
+++ b/taler-developer-manual.rst
@@ -284,29 +284,63 @@ serve Taler on the Internet:
- ``taler-internal``: serves ``*.int.taler.net``, and does *NOT* get
automatically built.
-The following two users are *never* automatically built, and they both
-serve ``*.demo.taler.net``. At any given time, only one is active and
-serves the HTTP requests from the outside; the other one can so be
-compiled without any downtime. If the compilation succeeds, the inactive
-user can be switched to become active (see next section), and vice versa.
-
-- ``demo-blue``
-- ``demo-green``
+- ``demo``: serves ``*.demo.taler.net``. Never automatically built.
Demo Upgrade Procedure
======================
+#. Login as the ``demo`` user on ``gv.taler.net``.
+#. Pull the latest ``deployment.git`` code.
+#. Navigate to the ``deployment.git/docker/demo`` directory.
+#. Refer to the README, or the smaller cheat sheet below.
+
+The deployment is based on rootless Docker, managed by the
+SystemD unit in userspace: ``docker.service``. The running daemon
+is reached by every Docker command at the address held into the
+``DOCKER_HOST`` environment variable. Normally, it points to
+``unix:///run/user/$(id -u)/docker.sock``. Such variable is automatically
+exported by ``~/.bashrc``.
+
+.. note::
+
+ Should the rootless Docker be installed, run the following command
+ or consult the `official documentation <https://docs.docker.com/engine/security/rootless/>`_.
+
+ .. code-block:: console
+
+ $ curl -fsSL https://get.docker.com/rootless | sh
+
Upgrading the ``demo`` environment should be done with care, and ideally be
coordinated on the mailing list before. It is our goal for ``demo`` to always
run a "working version" that is compatible with various published wallets.
-
-Before deploying on ``demo``, the same version of all components **must**
-be deployed *and* tested on ``int``.
-
Please use the :doc:`demo upgrade checklist <checklist-demo-upgrade>` to make
sure everything is working.
+Nginx is already configured to reach the services as exported by
+Docker Compose.
+
+
+Cheat sheet
+-----------
+All commands run from deployment.git/docker/demo.
+
+.. code-block:: console
+
+ # Start services.
+ $ docker-compose start --remove-orphans -d
+
+ # Stop services.
+ $ docker-compose stop
+
+ # Build base image (without tags-file builds master)
+ $ ./build_base.sh images/base/Dockerfile [tags-file]
+
+ # Build all the services based on the latest base image
+ $ docker-compose build
+
+ # View live logs of the daemonized services.
+ $ docker-compose logs
Tagging components
------------------
@@ -323,100 +357,6 @@ All Taler components must be tagged with git before they are deployed on the
SS = serial
-Environment Layout
-------------------
-
-Environments have the following layout:
-
-.. code-block:: none
-
- $HOME/
- deployment (deployment.git checkout)
- envcfg.py (configuration of the Taler environment)
- activate (bash file, sourced to set environment variables)
- logs/ (log files)
- local/ (locally installed software)
- sources/ (sources repos of locally build components)
- sockets/ (unix domain sockets of running components)
- taler-data (on-disk state, public and private keys)
- .config/taler.conf (main Taler configuration file)
-
-On ``demo-blue`` and ``demo-green``, ``taler-data`` is a symlink pointing to ``$HOME/demo/shared-data``
-instead of a directory.
-
-
-Using envcfg.py
----------------
-
-The ``$HOME/envcfg.py`` file contains (1) the name of the environment and (2) the version
-of all components we build (in the form of a git rev).
-
-The ``envcfg.py`` for demo looks like this:
-
-.. code-block:: python
-
- env = "demo"
- tag = "demo-2019-10-05-01:
- tag_gnunet = tag
- tag_libmicrohttpd = tag
- tag_exchange = tag
- tag_merchant = tag
- tag_bank = tag
- tag_twister = tag
- tag_landing = tag
- tag_donations = tag
- tag_blog = tag
- tag_survey = tag
- tag_backoffice = tag
- tag_sync = tag
-
-Currently only the variables ``env`` and ``tag_${component}`` are used.
-
-When deploying to ``demo``, the ``envcfg.py`` should be committed to ``deployment.git/envcfg/envcfg-demo-YYYY-MM-DD-SS.py``.
-
-
-Bootstrapping an Environment
-----------------------------
-
-.. code-block:: console
-
- $ git clone https://git.taler.net/deployment.git ~/deployment
- $ cp ~/deployment/envcfg/$ENVCFGFILE ~/envcfg.py
- $ ./deployment/bin/taler-deployment bootstrap
- $ source ~/activate
- $ taler-deployment build
- $ taler-deployment-prepare
- $ taler-deployment-start
- $ taler-deployment-arm -I # check everything works
- # The following command sets up the 'blog' and 'donations' instances.
- $ taler-config-instances
-
-
-Upgrading an Existing Environment
----------------------------------
-
-.. code-block:: console
-
- $ rm -rf ~/sources ~/local
- $ git -C ~/deployment pull
- $ cp ~/deployment/envcfg/$ENVCFGFILE ~/envcfg.py
- $ taler-deployment bootstrap
- $ taler-deployment build
- $ taler-deployment-prepare
- $ taler-deployment-restart
- $ taler-deployment-arm -I # check everything works
-
-Switching Demo Colors
----------------------
-
-As the ``demo`` user, to switch to color ``${COLOR}``,
-run the following script from ``deployment/bin``:
-
-.. code-block:: console
-
- $ taler-deployment switch-demo
-
-
Environments and Builders on taler.net
======================================
@@ -448,6 +388,40 @@ Best Practices:
Then make sure there is a WORKER defined in master.cfg like: ``worker.Worker("<username>", "<password>")``
+Test builder
+------------
+
+This builder (``test-builder``) compiles and starts every Taler component.
+The associated worker is run by the ``taler-test`` Gv user, via the SystemD
+unit ``buildbot-worker-taler``. The following commands start/stop/restart
+the worker:
+
+.. code-block::
+
+ systemctl --user start buildbot-worker-taler
+ systemctl --user stop buildbot-worker-taler
+ systemctl --user restart buildbot-worker-taler
+
+.. note::
+ the mentioned unit file can be found at ``deployment.git/systemd-services/``
+
+Wallet builder
+--------------
+
+This builder (``wallet-builder``) compiles every Taler component
+and runs the wallet integration tests. The associated worker is
+run by the ``walletbuilder`` Gv user, via the SystemD unit ``buildbot-worker-wallet``.
+The following commands start/stop/restart the worker:
+
+.. code-block::
+
+ systemctl --user start buildbot-worker-wallet
+ systemctl --user stop buildbot-worker-wallet
+ systemctl --user restart buildbot-worker-wallet
+
+.. note::
+ the mentioned unit file can be found at ``deployment.git/systemd-services/``
+
Documentation Builder
---------------------
@@ -512,47 +486,6 @@ by Buildbot.
The results are then published at ``https://lcov.taler.net/``.
-Service Checker
----------------
-
-The user ``demo-checker`` runs periodic checks to see if all the
-``*.demo.taler.net`` services are up and running. It is driven by
-Buildbot, and can be bootstrapped as follows.
-
-.. code-block:: console
-
- # Log-in as the 'demo-checker' user
-
- $ cd $HOME
- $ git clone git://git.taler.net/deployment
- $ ./deployment/bootstrap-demochecker
-
- # If the previous step worked, the setup is
- # complete and the Buildbot worker can be started.
-
- $ buildbot-worker start worker/
-
-
-Tipping reserve top-up
-----------------------
-
-Both 'test' and 'demo' setups get their tip reserve topped up
-by a Buildbot worker. The following steps get the reserve topper
-prepared.
-
-.. code-block:: console
-
- # Log-in as <env>-topper, with <env> being either 'test' or 'demo'
-
- $ git clone git://git.taler.net/deployment
- $ ./deployment/prepare-reservetopper <env>
-
- # If the previous steps worked, then it should suffice to start
- # the worker, with:
-
- $ buildbot-worker start worker/
-
-
Producing auditor reports
-------------------------
@@ -565,7 +498,7 @@ prepared.
# Log-in as <env>-auditor, with <env> being either 'test' or 'demo'
$ git clone git://git.taler.net/deployment
- $ ./deployment/prepare-auditorreporter <env>
+ $ ./deployment/buildbot/bootstrap-scripts/prepare-auditorreporter <env>
# If the previous steps worked, then it should suffice to start
# the worker, with:
@@ -1281,6 +1214,12 @@ Refreshing
**Use instead**: "Obtaining change"
+Charge
+ Charge has two opposite meanings (charge to a credit card vs. charge a battery).
+ This can confuse users.
+
+ **Use instead**: "Obtain", "Credit", "Debit", "Withdraw"
+
Coin
Coins are an internal construct, the user should never be aware that their balance
is represented by coins if different denominations.
diff --git a/taler-exchange-manual.rst b/taler-exchange-manual.rst
index a45577a..fc06a8e 100644
--- a/taler-exchange-manual.rst
+++ b/taler-exchange-manual.rst
@@ -520,6 +520,9 @@ must then have the following options:
- ``FEE_REFUND``: What does it cost to refund this coin?
Specified using the same format as value.
+- ``CIPHER``: Which cipher to use for this coin? Must be either ``RSA`` or
+ ``CS``.
+
- ``RSA_KEYSIZE``: How many bits should the RSA modulus (product of the two
primes) have for this type of coin.
@@ -717,7 +720,7 @@ using the ``taler-exchange-offline`` tool:
.. code-block:: console
- $ taler-exchange-offline wire-fee iban 2040 EUR:0.05 EUR:0.10 EUR:0.15
+ $ taler-exchange-offline wire-fee 2040 iban EUR:0.05 EUR:0.10 EUR:0.15
The above sets the wire fees for wire transfers involving ``iban`` accounts
(in Euros) in the year 2040 to 5 cents (wire fee) and 10 cents (closing fee).
diff --git a/taler-wallet.rst b/taler-wallet.rst
index 0d889a3..2fa41d9 100644
--- a/taler-wallet.rst
+++ b/taler-wallet.rst
@@ -86,10 +86,6 @@ Please see :ref:`Build-apps-from-source` in the :doc:`taler-developer-manual`.
APIs and Data Formats
=====================
-.. warning::
-
- These APIs are still a work in progress and *not* final.
-
Envelope Format
---------------
@@ -107,7 +103,7 @@ following envelope:
export interface WalletSuccess {
type: "response";
- operation: string,
+ operation: string;
// ID to correlate success response to request
id: string;
// Result type depends on operation
@@ -118,7 +114,7 @@ following envelope:
export interface WalletError {
type: "error";
- operation: string,
+ operation: string;
// ID to correlate error response to request
id: string;
error: WalletErrorInfo;
@@ -153,487 +149,6 @@ following envelope:
details: unknown;
}
-Balances
---------
-
-Balances are the amounts of digital cash held by the wallet.
-
-:name: ``"getBalances"``
-:description: Get a list of balances per currency.
-:response:
- .. ts:def:: BalancesResponse
-
- interface BalancesResponse {
- // a list of balances sorted by currency.
- // (currencies with shorter names first, then lexically ascending).
- //
- // Note: Even when a currency has no balance, but pending or past transactions,
- // it should be included in this list with a balance of zero.
- balances: Balance[];
- }
-
- .. ts:def:: Balance
-
- // Balance for one currency.
- // The currency can be derived from any of the
- // "Amount" fields, as the currency is present even
- // when the amount is zero.
- interface Balance {
- // The total Amount that is currently available to be spent
- // including amounts tied up in ongoing refresh operations. These are hidden from the user.
- // If the user tries to spend coins locked up this way,
- // the wallet will give an error message different from "insufficient balance".
- available: Amount;
-
- // the total incoming amount that will be added to the available balance
- // when all pending transactions succeed (including internal refreshes)
- pendingIncoming: Amount;
-
- // the total outgoing amount that will be subtracted from the available balance
- // when all pending transactions succeed (including internal refreshes)
- pendingOutgoing: Amount;
-
- // true if the balance requires user-interaction, e.g. accepting a tip
- // (DEV: can be left out of a first implementation)
- requiresUserInput: boolean;
- }
-
-Transactions
-------------
-
-Transactions are all operations or events that affect the balance.
-
-:Name: ``"getTransactions"``
-:Description: Get a list of past and pending transactions.
-:Request:
- .. ts:def:: TransactionsRequest
-
- interface TransactionsRequest {
- // return only transactions in the given currency, if present
- currency?: string;
-
- // if present, results will be limited to transactions related to the given search string
- search?: string;
- }
-:Response:
- .. ts:def:: TransactionsResponse
-
- interface TransactionsResponse {
- // a list of past and pending transactions sorted by pending, timestamp and transactionId.
- // In case two events are both pending and have the same timestamp,
- // they are sorted by the transactionId
- // (i.e. pending before non-pending transactions, newer before older
- // and if all equal transactionId lexically ascending).
- transactions: Transaction[];
- }
-
- .. ts:def:: Transaction
-
- interface Transaction {
- // opaque unique ID for the transaction, used as a starting point for paginating queries
- // and for invoking actions on the transaction (e.g. deleting/hiding it from the history)
- transactionId: string;
-
- // the type of the transaction; different types might provide additional information
- type: TransactionType;
-
- // main timestamp of the transaction
- timestamp: Timestamp;
-
- // true if the transaction is still pending, false otherwise
- // If a transaction is not longer pending, its timestamp will be updated,
- // but its transactionId will remain unchanged
- pending: boolean;
-
- // if present, the transaction encountered a fatal error that needs to be shown to the user
- error?: TransactionError;
-
- // Raw amount of the transaction (exclusive of fees or other extra costs)
- amountRaw: Amount;
-
- // Amount added or removed from the wallet's balance (including all fees and other costs)
- amountEffective: Amount;
- }
-
- .. ts:def:: TransactionType
-
- type TransactionType = (
- TransactionWithdrawal |
- TransactionPayment |
- TransactionRefund |
- TransactionTip |
- TransactionRefresh
- )
-
- .. ts:def:: TransactionError
-
- interface TransactionError {
- // TALER_EC_* unique error code.
- // The action(s) offered and message displayed on the transaction item depend on this code.
- ec: number;
-
- // English-only error hint, if available.
- hint?: string;
-
- // Error details specific to "ec", if applicable/available
- details?: any;
- }
-
- .. ts:def:: WithdrawalDetails
-
- export type WithdrawalDetails =
- | WithdrawalDetailsForManualTransfer
- | WithdrawalDetailsForTalerBankIntegrationApi;
-
- .. ts:def:: WithdrawalDetailsForManualTransfer
-
- interface WithdrawalDetailsForManualTransfer {
- type: "manual-transfer";
-
- // Payto URIs that the exchange supports.
- // Already contains the amount and message.
- exchangePaytoUris: string[];
-
- // Public key of the newly created reserve.
- // Not useful for the UI, but required for integration testing.
- reservePub: string;
- }
-
- .. ts:def:: WithdrawalDetailsForTalerBankIntegrationApi
-
- interface WithdrawalDetailsForTalerBankIntegrationApi {
- type: "taler-bank-integration-api";
-
- // Set to true if the bank has confirmed the withdrawal, false if not.
- // An unconfirmed withdrawal usually requires user-input and should be highlighted in the UI.
- // See also bankConfirmationUrl below.
- confirmed: boolean;
-
- // If the withdrawal is unconfirmed, this can include a URL for user
- // initiated confirmation.
- bankConfirmationUrl?: string;
- }
-
- .. ts:def:: TransactionWithdrawal
-
- // This should only be used for actual withdrawals
- // and not for tips that have their own transactions type.
- interface TransactionWithdrawal extends Transaction {
- type: string = "withdrawal",
-
- // Exchange that was withdrawn from.
- exchangeBaseUrl: string;
-
- // Amount that has been subtracted from the reserve's balance for this withdrawal.
- amountRaw: Amount;
-
- // Amount that actually was (or will be) added to the wallet's balance.
- // Should always be shown as a positive amount.
- amountEffective: Amount;
-
- // Further details
- withdrawalDetails: WithdrawalDetails;
- }
-
- .. ts:def:: TransactionPayment
-
- interface TransactionPayment extends Transaction {
- type: string = "payment",
-
- // Additional information about the payment.
- info: OrderShortInfo;
-
- // Wallet-internal end-to-end identifier for the payment
- // (assigned before the order is even downloaded, thus the name).
- proposalId: string;
-
- // The current status of this payment.
- status: PaymentStatus;
-
- // Amount that must be paid for the contract
- amountRaw: Amount;
-
- // Amount that was paid, including deposit, wire and refresh fees.
- // Should always be shown as a negative amount.
- amountEffective: Amount;
- }
-
- .. ts:def:: OrderShortInfo
-
- interface OrderShortInfo {
- // Order ID, uniquely identifies the order within a merchant instance
- orderId: string;
-
- // More information about the merchant
- merchant: Merchant;
-
- // Summary of the order, given by the merchant
- summary: string;
-
- // Map from IETF BCP 47 language tags to localized summaries
- summary_i18n?: { [lang_tag: string]: string };
-
- // List of products that are part of the order
- products: Product[];
-
- // URL of the fulfillment, given by the merchant
- fulfillmentUrl?: string;
-
- // Message shown to the user after the payment is complete.
- fulfillmentMessage?: string;
-
- // Map from IETF BCP 47 language tags to localized fulfillment messages
- fulfillmentMessage_i18n: { [lang_tag: string]: string };
- }
-
- .. ts:def:: PaymentStatus
-
- enum PaymentStatus {
- // Explicitly aborted after timeout / failure
- Aborted = "aborted",
-
- // Payment failed, wallet will auto-retry.
- // User should be given the option to retry now / abort.
- Failed = "failed",
-
- // Paid successfully
- Paid = "paid",
-
- // Only offered, user must accept / decline
- Offered = "offered",
-
- // User accepted, payment is processing.
- Accepted = "accepted",
- }
-
- .. ts:def:: TransactionRefund
-
- interface TransactionRefund extends Transaction {
- type: string = "refund",
-
- // ID for the transaction that is refunded
- refundedTransactionId: string;
-
- // Additional information about the refunded payment
- info: OrderShortInfo;
-
- // Part of the refund that couldn't be applied because the refund permissions were expired
- amountInvalid: Amount;
-
- // Amount that has been refunded by the merchant.
- // Corresponds to amountRefundGranted from the applyRefund response.
- amountRaw: Amount;
-
- // Amount will be added to the wallet's balance after fees and refreshing.
- // Should always be shown as a positive amount.
- amountEffective: Amount;
- }
-
- .. ts:def:: TransactionTip
-
- interface TransactionTip extends Transaction {
- type: string = "tip",
-
- // The current status of this tip.
- status: TipStatus;
-
- // Exchange that the tip will be (or was) withdrawn from
- exchangeBaseUrl: string;
-
- // More information about the merchant that sent the tip
- merchant: Merchant;
-
- // Raw amount of the tip, without extra fees that apply
- amountRaw: Amount;
-
- // Amount will be (or was) added to the wallet's balance after fees and refreshing.
- // Should always be shown as a positive amount.
- amountEffective: Amount;
- }
-
- .. ts:def:: TipStatus
-
- enum TipStatus {
- // Only offered, user must accept / decline
- Offered = "offered",
-
- // User accepted, tip is processing.
- Accepted = "accepted",
-
- // User declined.
- Declined = "declined",
-
- // Received successfully
- Received = "received",
- }
-
- .. ts:def:: TransactionRefresh
-
- // A transaction shown for refreshes that are not associated to other transactions
- // such as a refresh necessary before coin expiration.
- // It should only be returned by the API if the effective amount is different from zero.
- interface TransactionRefresh extends Transaction {
- type: string = "refresh",
-
- // Exchange that the coins are refreshed with
- exchangeBaseUrl: string;
-
- // Raw amount that is refreshed
- amountRaw: Amount;
-
- // Amount that will be paid as fees for the refresh.
- // Should always be shown as a negative amount.
- amountEffective: Amount;
- }
-
-
-:Name: ``"deleteTransaction"``
-:Description: Delete a transaction by ID.
-:Request:
- .. ts:def:: DeleteTransactionRequest
-
- interface DeleteTransactionRequest {
- // Transaction ID (opaque!) as returned in
- // the transaction list response.
- transactionId: string;
- }
-:Response: Returns an empty object
-
-Refunds
--------
-
-:Name: ``"applyRefund"``
-:Description: Process a refund from a ``taler://refund`` URI.
-:Request:
- .. ts:def:: WalletApplyRefundRequest
-
- interface WalletApplyRefundRequest {
- talerRefundUri: string;
- }
-:Response:
- .. ts:def:: WalletApplyRefundResponse
-
- interface WalletApplyRefundResponse {
- // Identifier for the purchase that was refunded
- // DEPRECATED: Will disappear soon.
- contractTermsHash: string;
-
- amountEffectivePaid: Amount;
-
- amountRefundGranted: Amount;
-
- amountRefundGone: Amount;
-
- pendingAtExchange: boolean;
-
- // Short info about the order being refunded.
- info: OrderShortInfo;
- }
-
-Exchange Management
--------------------
-
-List Exchanges
-~~~~~~~~~~~~~~
-
-:Name: ``"listExchanges"``
-:Description:
- List all exchanges.
-:Response:
- .. ts:def:: ExchangesListResponse
-
- interface ExchangesListResponse {
- exchanges: ExchangeListItem[];
- }
-
- .. ts:def:: ExchangeListItem
-
- interface ExchangeListItem {
- exchangeBaseUrl: string;
- currency: string;
- paytoUris: string[];
- }
-
-Add Exchange
-~~~~~~~~~~~~
-
-:Name: ``"addExchange"``
-:Description:
- Add an exchange.
-:Request:
- .. ts:def:: ExchangeAddRequest
-
- interface ExchangeAddRequest {
- exchangeBaseUrl: string;
- }
-:Response:
- On success, the response is an `ExchangeListItem`.
-
-
-Force Exchange Update
-~~~~~~~~~~~~~~~~~~~~~
-
-:Name: ``"forceUpdateExchange"``
-:Description:
- Force updating an exchange.
- Re-queries current cryptographic key material, wire information
- and terms of service from the exchange. Also applies denomination revocations
- if applicable.
-:Request:
- .. ts:def:: ExchangeForceUpdateRequest
-
- interface ExchangeForceUpdateRequest {
- exchangeBaseUrl: string;
- }
-:Response:
- On success, the response is an `ExchangeListItem`.
-
-
-Get Terms of Service
-~~~~~~~~~~~~~~~~~~~~
-
-:Name: ``"getExchangeTos"``
-:Description:
- Get the exchange's current ToS and which version of the ToS (if any)
- the user has accepted.
-:Request:
- .. ts:def:: ExchangeGetTosRequest
-
- interface ExchangeGetTosRequest {
- exchangeBaseUrl: string;
- }
-:Response:
- .. ts:def:: ExchangeGetTosResult
-
- interface GetExchangeTosResult {
- // Markdown version of the current ToS.
- content: string;
-
- // Version tag of the current ToS.
- currentEtag: string;
-
- // Version tag of the last ToS that the user has accepted,
- // if any.
- acceptedEtag: string | undefined;
- }
-
-Set Accepted Terms of Service Version
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-:Name: ``"setExchangeTosAccepted"``
-:Description:
- Store that the user has accepted a version of the exchange's ToS.
-:Request:
- .. ts:def:: ExchangeSetTosAccepted
-
- interface ExchangeGetTosRequest {
- exchangeBaseUrl: string;
- etag: string;
- }
-:Response:
- On success, the response is an empty object.
-
-
Withdrawal
----------
@@ -657,464 +172,6 @@ A typical API sequence for *manual* withdrawals can for example look like this:
#. ``"acceptManualWithdrawal"`` after the user confirmed withdrawal with associated fees
-Get Details For Bank-integrated Withdrawal
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-:Name: ``"getWithdrawalDetailsForUri"``
-:Description:
- Get information about exchanges for a bank-integrated withdrawal from a ``taler://withdraw`` URI.
-:Request:
- .. ts:def:: GetWithdrawalUriDetailsRequest
-
- interface GetWithdrawalUriDetailsRequest {
- talerWithdrawUri: string;
- }
-:Response:
- .. ts:def:: WithdrawalDetailsForUri
-
- interface WithdrawalDetailsForUri {
- // The amount that the user wants to withdraw
- amount: Amount;
-
- // Exchange suggested by the wallet
- defaultExchangeBaseUrl?: string;
-
- // A list of exchanges that can be used for this withdrawal
- possibleExchanges: ExchangeListItem[];
- }
-
-Get Withdrawal Details
-~~~~~~~~~~~~~~~~~~~~~~
-
-:Name: ``"getWithdrawalDetailsForAmount"``
-:Description:
- Get information about fees and exchange for a withdrawal of a given amount.
- Can be used for both bank-integrated and manual withdrawals.
-:Request:
- .. ts:def:: WithdrawalDetailsRequest
-
- interface WithdrawalDetailsRequest {
- exchangeBaseUrl: string;
- amount: Amount;
- }
-:Response:
- .. ts:def:: WithdrawalDetails
-
- interface WithdrawalDetails {
- // Did the user accept the current version of the exchange's terms of service?
- tosAccepted: boolean;
-
- // Amount that will be transferred to the exchange.
- amountRaw: Amount;
-
- // Amount that will be added to the user's wallet balance.
- amountEffective: Amount;
- }
-
-Accept Bank-integrated Withdrawal
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-:Name: ``"acceptWithdrawal"``
-:Description:
- Accept a bank-integrated withdrawal, where the bank transfers funds automatically.
-:Request:
- .. ts:def:: GetManualWithdrawalDetailsRequest
-
- interface AcceptWithdrawalRequest {
- talerWithdrawUri: string;
- exchangeBaseUrl: string;
- }
-:Response:
- .. ts:def:: AcceptWithdrawalResponse
-
- interface AcceptWithdrawalResponse {
- // a URL for user initiated confirmation.
- bankConfirmationUrl?: string;
- }
-
-Accept Manual Withdrawal
-~~~~~~~~~~~~~~~~~~~~~~~~
-
-:Name: ``"acceptManualWithdrawal"``
-:Description:
- Accept a manual withdrawal, where the user has to transfer funds manually.
-:Request:
- .. ts:def:: AcceptManualWithdrawalRequest
-
- interface AcceptManualWithdrawalRequest {
- exchangeBaseUrl: string;
- amount: Amount;
- }
-:Response:
- .. ts:def:: AcceptManualWithdrawalResponse
-
- interface AcceptManualWithdrawalResponse {
- // Payto URIs to fund the withdrawal,
- // with amount and message provided.
- exchangePaytoUris: string[];
- }
-
-Deposits
---------
-
-Deposits are direct payments into a payment target (given via
-a payto URI). They don't involve a merchant.
-
-:Name: ``"createDepositGroup"``
-:Description:
- Deposit funds directly into a payment target.
-:Request:
- .. ts:def:: CreateDepositGroupRequest
-
- interface CreateDepositGroupRequest {
- depositPaytoUri: string;
- amount: Amount;
- }
-:Response:
- .. ts:def:: CreateDepositGroupResponse
-
- interface CreateDepositGroupResponse {
- depositGroupId: string;
- }
-
-
-Payments
---------
-
-Prepare Pay
-~~~~~~~~~~~
-
-:Name: ``"preparePay"``
-:Description:
- Fetch information about a payment request from a merchant.
-:Request:
- .. ts:def:: PreparePayRequest
-
- interface PreparePayRequest {
- talerPayUri: string;
- }
-:Response:
- .. ts:def:: PreparePayResponse
-
- type PreparePayResponse =
- | PreparePayPaymentPossibleResponse
- | PreparePayAlreadyConfirmedResponse
- | PreparePayInsufficientBalanceResponse;
-
- .. ts:def:: PreparePayPaymentPossibleResponse
-
- interface PreparePayPaymentPossibleResponse {
- status: "payment-possible";
-
- proposalId: string;
-
- // Verbatim contract terms as generated by the merchant.
- contractTerms: ContractTerms;
-
- // Amount that the merchant is asking for.
- amountRaw: Amount;
-
- // Amount that will effectively be subtracted from the wallet's
- // balance when accepting this proposal.
- amountEffective: Amount;
- }
-
- .. ts:def:: PreparePayInsufficientBalanceResponse
-
- interface PreparePayInsufficientBalanceResponse {
- status: "insufficient-balance";
-
- proposalId: string;
-
- // Amount that the merchant is asking for.
- amountRaw: Amount;
-
- // Verbatim contract terms as generated by the merchant.
- contractTerms: ContractTerms;
- }
-
- .. ts:def:: PreparePayAlreadyConfirmedResponse
-
- interface PreparePayAlreadyConfirmedResponse {
- status: "already-confirmed";
-
- proposalId: string;
-
- // Did the payment succeed?
- paid: boolean;
-
- // Amount that the merchant is asking for.
- amountRaw: Amount;
-
- // Amount that will be subtracted from the wallet balance
- amountEffective: Amount;
-
- // Verbatim contract terms as generated by the merchant.
- contractTerms: ContractTerms;
- }
-
-
-Confirm Payment
-~~~~~~~~~~~~~~~
-
-:Name: ``"confirmPay"``
-:Description:
- Confirm making a payment.
-
-:Request:
- .. ts:def:: GetManualWithdrawalDetailsRequest
-
- interface ConfirmPayRequest {
- proposalId: string;
- }
-:Response:
- .. ts:def:: ConfirmPayResultDone
-
- interface ConfirmPayResultDone {
- type: "done";
-
- contractTerms: ContractTerms;
- }
-
- .. ts:def:: ConfirmPayResultPending
-
- // Payment was marked as confirmed,
- // but the attempt(s) to pay were not successful yet.
- interface ConfirmPayPending {
- type: "pending";
-
- lastError: TransactionError;
- }
-
- .. ts:def:: ConfirmPayResult
-
- type ConfirmPayResult =
- | ConfirmPayResultDone;
- | ConfirmPayResultPending;
-
-Abort Failed Payment
-~~~~~~~~~~~~~~~~~~~~
-
-:Name: ``"abortFailedPayWithRefund"``
-:Description:
- Abort a failed payment and try to get a refund for the
- partially paid amount.
-:Request:
- .. ts:def:: AbortPayWithRefundRequest
-
- export interface AbortPayWithRefundRequest {
- proposalId: string;
- }
-:Response:
- On success, the response is an empty object.
-
-Tipping API Calls
------------------
-
-Preparing a tip
-~~~~~~~~~~~~~~~
-
-:Name: ``"prepareTip"``
-:Description:
- Prepare to accept a tip based in a ``taler://tip`` URI.
-:Request:
- .. ts:def:: PrepareTipRequest
-
- interface PrepareTipRequest {
- talerTipUri: string;
- }
-:Response:
- .. ts:def:: PrepareTipResult
-
- interface PrepareTipResult {
- // Unique ID for the tip assigned by the wallet.
- // Typically different from the merchant-generated tip ID.
- walletTipId: string;
-
- // Has the tip already been accepted?
- accepted: boolean;
- tipAmountRaw: Amount;
- tipAmountEffective: Amount;
- exchangeBaseUrl: string;
- expirationTimestamp: Timestamp;
- }
-
-
-Accepting a tip
-~~~~~~~~~~~~~~~
-
-:Name: ``"acceptTip"``
-:Description:
- Prepare to accept a tip based in a ``taler://tip`` URI.
-:Request:
- .. ts:def:: AcceptTipRequest
-
- interface AcceptTipRequest {
- walletTipId: string;
- }
-:Response:
- On success, the response is an empty object.
-
-Testing API calls
------------------
-
-The following API calls are useful for testing.
-
-Withdraw balance from the TESTKUDOS environment
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-:Name: ``"withdrawTestkudos"``
-:Description:
- Withdraw a balance from the ``TESTKUDOS`` environment.
-:Request:
- The request parameters are ignored.
-:Response:
- On success, the response is an empty object.
-
-Withdraw balance from a test environment
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-:Name: ``"withdrawTestBalance"``
-:Description:
- Withdraw a balance from a test environment.
-:Request:
- .. ts:def:: WithdrawTestBalanceRequest
-
- interface WithdrawTestBalanceRequest {
- amount: string;
- bankBaseUrl: string;
- exchangeBaseUrl: string;
- }
-:Response:
- On success, the response is an empty object.
-
-Run integration test
-~~~~~~~~~~~~~~~~~~~~
-
-:Name: ``"runIntegrationTest"``
-:Description:
- Run a basic integration test that does a withdrawal, payment,
- refund and again a payment. Useful to generate test data
- in the integration tests of other components.
-:Request:
- .. ts:def:: IntegrationTestArgs
-
- interface IntegrationTestArgs {
- exchangeBaseUrl: string;
- bankBaseUrl: string;
- merchantBaseUrl: string;
- merchantApiKey: string;
- amountToWithdraw: string;
- amountToSpend: string;
- }
-:Response:
- On success, the response is an empty object.
-
-Make a test payment
-~~~~~~~~~~~~~~~~~~~
-
-:Name: ``"testPay"``
-:Description:
- Make a test payment with existing funds.
-:Request:
- .. ts:def:: TestPayArgs
-
- interface TestPayArgs {
- merchantBaseUrl: string;
- merchantApiKey: string;
- amount: string;
- summary: string;
- }
-
-
-Dump all coins to JSON
-~~~~~~~~~~~~~~~~~~~~~~
-
-:Name: ``"dumpCoins"``
-:Description:
- Make a test payment with existing funds.
-:Request:
- The request object is ignored.
-:Response:
- .. code:: ts
-
- interface CoinDumpJson {
- coins: Array<{
- /**
- * The coin's denomination's public key.
- */
- denom_pub: string;
- /**
- * Hash of denom_pub.
- */
- denom_pub_hash: string;
- /**
- * Value of the denomination (without any fees).
- */
- denom_value: string;
- /**
- * Public key of the coin.
- */
- coin_pub: string;
- /**
- * Base URL of the exchange for the coin.
- */
- exchange_base_url: string;
- /**
- * Remaining value on the coin, to the knowledge of
- * the wallet.
- */
- remaining_value: string;
- /**
- * Public key of the parent coin.
- * Only present if this coin was obtained via refreshing.
- */
- refresh_parent_coin_pub: string | undefined;
- /**
- * Public key of the reserve for this coin.
- * Only present if this coin was obtained via refreshing.
- */
- withdrawal_reserve_pub: string | undefined;
- /**
- * Is the coin suspended?
- * Suspended coins are not considered for payments.
- */
- coin_suspended: boolean;
- }>;
- }
-
-
-Suspend/unsuspend a coin
-~~~~~~~~~~~~~~~~~~~~~~~~
-
-A suspended coin will not be used by the wallet for payments.
-This functionality is only used for testing.
-
-:Name: ``"setCoinSuspended"``
-:Description:
- Make a test payment with existing funds.
-:Request:
- .. ts:def:: SetCoinSuspendedRequest
-
- interface SetCoinSuspendedRequest {
- coinPub: string;
- suspended: boolean;
- }
-:Request:
- On success, the response is an empty object.
-
-Global Errors
--------------
-
-* Backup/Sync/Anastasis failed
-* refresh after pay failed for multiple attempts
- (depending on online status)
-* scheduled refresh (to avoid expiration) failed
-* general recoups (?)
-* failed recoup
-* (maybe) fatal errors during withdrawal
-* pending refund failed permanently (?)
-
Integration Tests
=================
diff --git a/wallet/wallet-core.md b/wallet/wallet-core.md
new file mode 100644
index 0000000..ade7def
--- /dev/null
+++ b/wallet/wallet-core.md
@@ -0,0 +1,3124 @@
+# Wallet-Core API Documentation
+This file is auto-generated from [wallet-core](https://git.taler.net/wallet-core.git/tree/packages/taler-wallet-core/src/wallet-api-types.ts).
+## Overview
+### Unknown Group
+* [InitWalletOp](#initwalletop)
+* [GetVersionOp](#getversionop)
+### Basic Wallet Information
+* [GetBalancesOp](#getbalancesop)
+### Managing Transactions
+* [GetTransactionsOp](#gettransactionsop)
+* [GetTransactionByIdOp](#gettransactionbyidop)
+* [RetryPendingNowOp](#retrypendingnowop)
+* [DeleteTransactionOp](#deletetransactionop)
+* [RetryTransactionOp](#retrytransactionop)
+### Withdrawals
+* [GetWithdrawalDetailsForAmountOp](#getwithdrawaldetailsforamountop)
+* [GetWithdrawalDetailsForUriOp](#getwithdrawaldetailsforuriop)
+* [AcceptBankIntegratedWithdrawalOp](#acceptbankintegratedwithdrawalop)
+* [AcceptManualWithdrawalOp](#acceptmanualwithdrawalop)
+### Merchant Payments
+* [PreparePayForUriOp](#preparepayforuriop)
+* [GetContractTermsDetailsOp](#getcontracttermsdetailsop)
+* [ConfirmPayOp](#confirmpayop)
+* [AbortPayWithRefundOp](#abortpaywithrefundop)
+* [ApplyRefundOp](#applyrefundop)
+* [ApplyRefundFromPurchaseIdOp](#applyrefundfrompurchaseidop)
+* [PrepareRefundOp](#preparerefundop)
+### Tipping
+* [PrepareTipOp](#preparetipop)
+* [AcceptTipOp](#accepttipop)
+### Exchange Management
+* [ListExchangesOp](#listexchangesop)
+* [AddExchangeOp](#addexchangeop)
+* [ListKnownBankAccountsOp](#listknownbankaccountsop)
+* [AddKnownBankAccountsOp](#addknownbankaccountsop)
+* [ForgetKnownBankAccountsOp](#forgetknownbankaccountsop)
+* [SetExchangeTosAcceptedOp](#setexchangetosacceptedop)
+* [GetExchangeTosOp](#getexchangetosop)
+* [GetExchangeDetailedInfoOp](#getexchangedetailedinfoop)
+* [ListCurrenciesOp](#listcurrenciesop)
+### Deposits
+* [CreateDepositGroupOp](#createdepositgroupop)
+* [TrackDepositGroupOp](#trackdepositgroupop)
+* [GetFeeForDepositOp](#getfeefordepositop)
+* [PrepareDepositOp](#preparedepositop)
+### Backups
+* [ExportBackupRecoveryOp](#exportbackuprecoveryop)
+* [ImportBackupRecoveryOp](#importbackuprecoveryop)
+* [RunBackupCycleOp](#runbackupcycleop)
+* [ExportBackupOp](#exportbackupop)
+* [AddBackupProviderOp](#addbackupproviderop)
+* [RemoveBackupProviderOp](#removebackupproviderop)
+* [GetBackupInfoOp](#getbackupinfoop)
+* [SetWalletDeviceIdOp](#setwalletdeviceidop)
+* [ExportBackupPlainOp](#exportbackupplainop)
+### Peer Payments
+* [InitiatePeerPushPaymentOp](#initiatepeerpushpaymentop)
+* [CheckPeerPushPaymentOp](#checkpeerpushpaymentop)
+* [AcceptPeerPushPaymentOp](#acceptpeerpushpaymentop)
+* [InitiatePeerPullPaymentOp](#initiatepeerpullpaymentop)
+* [CheckPeerPullPaymentOp](#checkpeerpullpaymentop)
+* [AcceptPeerPullPaymentOp](#acceptpeerpullpaymentop)
+### Database Management
+* [ExportDbOp](#exportdbop)
+* [ImportDbOp](#importdbop)
+* [ClearDbOp](#cleardbop)
+* [RecycleOp](#recycleop)
+### Testing and Debugging
+* [ApplyDevExperimentOp](#applydevexperimentop)
+* [SetDevModeOp](#setdevmodeop)
+* [RunIntegrationTestOp](#runintegrationtestop)
+* [TestCryptoOp](#testcryptoop)
+* [WithdrawTestBalanceOp](#withdrawtestbalanceop)
+* [WithdrawTestkudosOp](#withdrawtestkudosop)
+* [TestPayOp](#testpayop)
+* [WithdrawFakebankOp](#withdrawfakebankop)
+* [GetPendingTasksOp](#getpendingtasksop)
+* [DumpCoinsOp](#dumpcoinsop)
+* [SetCoinSuspendedOp](#setcoinsuspendedop)
+* [ForceRefreshOp](#forcerefreshop)
+## Operation Reference
+### InitWalletOp
+```typescript
+/**
+ * Initialize wallet-core.
+ *
+ * Must be the request before any other operations.
+ */
+export type InitWalletOp = {
+ op: WalletApiOperation.InitWallet;
+ request: EmptyObject;
+ response: InitResponse;
+};
+// InitWallet = "initWallet"
+
+```
+```typescript
+export interface InitResponse {
+ versionInfo: WalletCoreVersion;
+}
+
+```
+
+### GetVersionOp
+```typescript
+export type GetVersionOp = {
+ op: WalletApiOperation.GetVersion;
+ request: EmptyObject;
+ response: WalletCoreVersion;
+};
+// GetVersion = "getVersion"
+
+```
+
+### GetBalancesOp
+```typescript
+/**
+ * Get current wallet balance.
+ */
+export type GetBalancesOp = {
+ op: WalletApiOperation.GetBalances;
+ request: EmptyObject;
+ response: BalancesResponse;
+};
+// GetBalances = "getBalances"
+
+```
+```typescript
+export interface BalancesResponse {
+ balances: Balance[];
+}
+
+```
+```typescript
+export interface Balance {
+ available: AmountString;
+ pendingIncoming: AmountString;
+ pendingOutgoing: AmountString;
+ hasPendingTransactions: boolean;
+ requiresUserInput: boolean;
+}
+
+```
+
+### GetTransactionsOp
+```typescript
+/**
+ * Get transactions.
+ */
+export type GetTransactionsOp = {
+ op: WalletApiOperation.GetTransactions;
+ request: TransactionsRequest;
+ response: TransactionsResponse;
+};
+// GetTransactions = "getTransactions"
+
+```
+```typescript
+export interface TransactionsRequest {
+ /**
+ * return only transactions in the given currency
+ */
+ currency?: string;
+ /**
+ * if present, results will be limited to transactions related to the given search string
+ */
+ search?: string;
+}
+
+```
+```typescript
+export interface TransactionsResponse {
+ transactions: Transaction[];
+}
+
+```
+
+### GetTransactionByIdOp
+```typescript
+export type GetTransactionByIdOp = {
+ op: WalletApiOperation.GetTransactionById;
+ request: TransactionByIdRequest;
+ response: Transaction;
+};
+// GetTransactionById = "getTransactionById"
+
+```
+```typescript
+export interface TransactionByIdRequest {
+ transactionId: string;
+}
+
+```
+
+### RetryPendingNowOp
+```typescript
+export type RetryPendingNowOp = {
+ op: WalletApiOperation.RetryPendingNow;
+ request: EmptyObject;
+ response: EmptyObject;
+};
+// RetryPendingNow = "retryPendingNow"
+
+```
+
+### DeleteTransactionOp
+```typescript
+/**
+ * Delete a transaction locally in the wallet.
+ */
+export type DeleteTransactionOp = {
+ op: WalletApiOperation.DeleteTransaction;
+ request: DeleteTransactionRequest;
+ response: EmptyObject;
+};
+// DeleteTransaction = "deleteTransaction"
+
+```
+```typescript
+export interface DeleteTransactionRequest {
+ transactionId: string;
+}
+
+```
+
+### RetryTransactionOp
+```typescript
+/**
+ * Immediately retry a transaction.
+ */
+export type RetryTransactionOp = {
+ op: WalletApiOperation.RetryTransaction;
+ request: RetryTransactionRequest;
+ response: EmptyObject;
+};
+// RetryTransaction = "retryTransaction"
+
+```
+```typescript
+export interface RetryTransactionRequest {
+ transactionId: string;
+}
+
+```
+
+### GetWithdrawalDetailsForAmountOp
+```typescript
+/**
+ * Get details for withdrawing a particular amount (manual withdrawal).
+ */
+export type GetWithdrawalDetailsForAmountOp = {
+ op: WalletApiOperation.GetWithdrawalDetailsForAmount;
+ request: GetWithdrawalDetailsForAmountRequest;
+ response: ManualWithdrawalDetails;
+};
+// GetWithdrawalDetailsForAmount = "getWithdrawalDetailsForAmount"
+
+```
+```typescript
+export interface GetWithdrawalDetailsForAmountRequest {
+ exchangeBaseUrl: string;
+ amount: string;
+ restrictAge?: number;
+}
+
+```
+```typescript
+export interface ManualWithdrawalDetails {
+ /**
+ * Did the user accept the current version of the exchange's
+ * terms of service?
+ */
+ tosAccepted: boolean;
+ /**
+ * Amount that the user will transfer to the exchange.
+ */
+ amountRaw: AmountString;
+ /**
+ * Amount that will be added to the user's wallet balance.
+ */
+ amountEffective: AmountString;
+ /**
+ * Ways to pay the exchange.
+ */
+ paytoUris: string[];
+ /**
+ * If the exchange supports age-restricted coins it will return
+ * the array of ages.
+ */
+ ageRestrictionOptions?: number[];
+}
+
+```
+
+### GetWithdrawalDetailsForUriOp
+```typescript
+/**
+ * Get details for withdrawing via a particular taler:// URI.
+ */
+export type GetWithdrawalDetailsForUriOp = {
+ op: WalletApiOperation.GetWithdrawalDetailsForUri;
+ request: GetWithdrawalDetailsForUriRequest;
+ response: WithdrawUriInfoResponse;
+};
+// GetWithdrawalDetailsForUri = "getWithdrawalDetailsForUri"
+
+```
+```typescript
+export interface GetWithdrawalDetailsForUriRequest {
+ talerWithdrawUri: string;
+ restrictAge?: number;
+}
+
+```
+```typescript
+export interface WithdrawUriInfoResponse {
+ amount: AmountString;
+ defaultExchangeBaseUrl?: string;
+ possibleExchanges: ExchangeListItem[];
+}
+
+```
+
+### AcceptBankIntegratedWithdrawalOp
+```typescript
+/**
+ * Accept a bank-integrated withdrawal.
+ */
+export type AcceptBankIntegratedWithdrawalOp = {
+ op: WalletApiOperation.AcceptBankIntegratedWithdrawal;
+ request: AcceptBankIntegratedWithdrawalRequest;
+ response: AcceptWithdrawalResponse;
+};
+// AcceptBankIntegratedWithdrawal = "acceptBankIntegratedWithdrawal"
+
+```
+```typescript
+export interface AcceptBankIntegratedWithdrawalRequest {
+ talerWithdrawUri: string;
+ exchangeBaseUrl: string;
+ forcedDenomSel?: ForcedDenomSel;
+ restrictAge?: number;
+}
+
+```
+```typescript
+export interface AcceptWithdrawalResponse {
+ reservePub: string;
+ confirmTransferUrl?: string;
+ transactionId: string;
+}
+
+```
+
+### AcceptManualWithdrawalOp
+```typescript
+/**
+ * Create a manual withdrawal.
+ */
+export type AcceptManualWithdrawalOp = {
+ op: WalletApiOperation.AcceptManualWithdrawal;
+ request: AcceptManualWithdrawalRequest;
+ response: AcceptManualWithdrawalResult;
+};
+// AcceptManualWithdrawal = "acceptManualWithdrawal"
+
+```
+```typescript
+export interface AcceptManualWithdrawalRequest {
+ exchangeBaseUrl: string;
+ amount: string;
+ restrictAge?: number;
+}
+
+```
+```typescript
+export interface AcceptManualWithdrawalResult {
+ /**
+ * Payto URIs that can be used to fund the withdrawal.
+ */
+ exchangePaytoUris: string[];
+ /**
+ * Public key of the newly created reserve.
+ */
+ reservePub: string;
+ transactionId: string;
+}
+
+```
+
+### PreparePayForUriOp
+```typescript
+/**
+ * Prepare to make a payment
+ */
+export type PreparePayForUriOp = {
+ op: WalletApiOperation.PreparePayForUri;
+ request: PreparePayRequest;
+ response: PreparePayResult;
+};
+// PreparePayForUri = "preparePayForUri"
+
+```
+```typescript
+export interface PreparePayRequest {
+ talerPayUri: string;
+}
+
+```
+```typescript
+/**
+ * Result of a prepare pay operation.
+ */
+export declare type PreparePayResult =
+ | PreparePayResultInsufficientBalance
+ | PreparePayResultAlreadyConfirmed
+ | PreparePayResultPaymentPossible;
+
+```
+```typescript
+export interface PreparePayResultInsufficientBalance {
+ status: PreparePayResultType.InsufficientBalance;
+ proposalId: string;
+ contractTerms: MerchantContractTerms;
+ amountRaw: string;
+ noncePriv: string;
+}
+
+```
+```typescript
+export interface PreparePayResultAlreadyConfirmed {
+ status: PreparePayResultType.AlreadyConfirmed;
+ contractTerms: MerchantContractTerms;
+ paid: boolean;
+ amountRaw: string;
+ amountEffective: string;
+ contractTermsHash: string;
+ proposalId: string;
+}
+
+```
+```typescript
+/**
+ * Payment is possible.
+ */
+export interface PreparePayResultPaymentPossible {
+ status: PreparePayResultType.PaymentPossible;
+ proposalId: string;
+ contractTerms: MerchantContractTerms;
+ contractTermsHash: string;
+ amountRaw: string;
+ amountEffective: string;
+ noncePriv: string;
+}
+
+```
+
+### GetContractTermsDetailsOp
+```typescript
+export type GetContractTermsDetailsOp = {
+ op: WalletApiOperation.GetContractTermsDetails;
+ request: GetContractTermsDetailsRequest;
+ response: WalletContractData;
+};
+// GetContractTermsDetails = "getContractTermsDetails"
+
+```
+```typescript
+export interface GetContractTermsDetailsRequest {
+ proposalId: string;
+}
+
+```
+```typescript
+/**
+ * Data extracted from the contract terms that is relevant for payment
+ * processing in the wallet.
+ */
+export interface WalletContractData {
+ products?: Product[];
+ summaryI18n:
+ | {
+ [lang_tag: string]: string;
+ }
+ | undefined;
+ /**
+ * Fulfillment URL, or the empty string if the order has no fulfillment URL.
+ *
+ * Stored as a non-nullable string as we use this field for IndexedDB indexing.
+ */
+ fulfillmentUrl: string;
+ contractTermsHash: string;
+ fulfillmentMessage?: string;
+ fulfillmentMessageI18n?: InternationalizedString;
+ merchantSig: string;
+ merchantPub: string;
+ merchant: MerchantInfo;
+ amount: AmountString;
+ orderId: string;
+ merchantBaseUrl: string;
+ summary: string;
+ autoRefund: TalerProtocolDuration | undefined;
+ maxWireFee: AmountString;
+ wireFeeAmortization: number;
+ payDeadline: TalerProtocolTimestamp;
+ refundDeadline: TalerProtocolTimestamp;
+ allowedAuditors: AllowedAuditorInfo[];
+ allowedExchanges: AllowedExchangeInfo[];
+ timestamp: TalerProtocolTimestamp;
+ wireMethod: string;
+ wireInfoHash: string;
+ maxDepositFee: AmountString;
+ minimumAge?: number;
+ deliveryDate: TalerProtocolTimestamp | undefined;
+ deliveryLocation: Location | undefined;
+}
+
+```
+```typescript
+export interface AllowedAuditorInfo {
+ auditorBaseUrl: string;
+ auditorPub: string;
+}
+
+```
+```typescript
+export interface AllowedExchangeInfo {
+ exchangeBaseUrl: string;
+ exchangePub: string;
+}
+
+```
+
+### ConfirmPayOp
+```typescript
+/**
+ * Confirm a payment that was previously prepared with
+ * {@link PreparePayForUriOp}
+ */
+export type ConfirmPayOp = {
+ op: WalletApiOperation.ConfirmPay;
+ request: ConfirmPayRequest;
+ response: ConfirmPayResult;
+};
+// ConfirmPay = "confirmPay"
+
+```
+```typescript
+export interface ConfirmPayRequest {
+ proposalId: string;
+ sessionId?: string;
+ forcedCoinSel?: ForcedCoinSel;
+}
+
+```
+```typescript
+export declare type ConfirmPayResult =
+ | ConfirmPayResultDone
+ | ConfirmPayResultPending;
+
+```
+```typescript
+/**
+ * Result for confirmPay
+ */
+export interface ConfirmPayResultDone {
+ type: ConfirmPayResultType.Done;
+ contractTerms: MerchantContractTerms;
+ transactionId: string;
+}
+
+```
+```typescript
+export interface ConfirmPayResultPending {
+ type: ConfirmPayResultType.Pending;
+ transactionId: string;
+ lastError: TalerErrorDetail | undefined;
+}
+
+```
+
+### AbortPayWithRefundOp
+```typescript
+/**
+ * Abort a pending payment with a refund.
+ */
+export type AbortPayWithRefundOp = {
+ op: WalletApiOperation.AbortFailedPayWithRefund;
+ request: AbortPayWithRefundRequest;
+ response: EmptyObject;
+};
+// AbortFailedPayWithRefund = "abortFailedPayWithRefund"
+
+```
+```typescript
+export interface AbortPayWithRefundRequest {
+ proposalId: string;
+}
+
+```
+
+### ApplyRefundOp
+```typescript
+/**
+ * Check for a refund based on a taler://refund URI.
+ */
+export type ApplyRefundOp = {
+ op: WalletApiOperation.ApplyRefund;
+ request: ApplyRefundRequest;
+ response: ApplyRefundResponse;
+};
+// ApplyRefund = "applyRefund"
+
+```
+```typescript
+export interface ApplyRefundRequest {
+ talerRefundUri: string;
+}
+
+```
+
+### ApplyRefundFromPurchaseIdOp
+```typescript
+export type ApplyRefundFromPurchaseIdOp = {
+ op: WalletApiOperation.ApplyRefundFromPurchaseId;
+ request: ApplyRefundFromPurchaseIdRequest;
+ response: ApplyRefundResponse;
+};
+// ApplyRefundFromPurchaseId = "applyRefundFromPurchaseId"
+
+```
+```typescript
+export interface ApplyRefundFromPurchaseIdRequest {
+ purchaseId: string;
+}
+
+```
+
+### PrepareRefundOp
+```typescript
+export type PrepareRefundOp = {
+ op: WalletApiOperation.PrepareRefund;
+ request: PrepareRefundRequest;
+ response: PrepareRefundResult;
+};
+// PrepareRefund = "prepareRefund"
+
+```
+```typescript
+export interface PrepareRefundRequest {
+ talerRefundUri: string;
+}
+
+```
+```typescript
+export interface PrepareRefundResult {
+ proposalId: string;
+ effectivePaid: AmountString;
+ gone: AmountString;
+ granted: AmountString;
+ pending: boolean;
+ awaiting: AmountString;
+ info: OrderShortInfo;
+}
+
+```
+
+### PrepareTipOp
+```typescript
+/**
+ * Query and store information about a tip.
+ */
+export type PrepareTipOp = {
+ op: WalletApiOperation.PrepareTip;
+ request: PrepareTipRequest;
+ response: PrepareTipResult;
+};
+// PrepareTip = "prepareTip"
+
+```
+```typescript
+export interface PrepareTipRequest {
+ talerTipUri: string;
+}
+
+```
+```typescript
+export interface PrepareTipResult {
+ /**
+ * Unique ID for the tip assigned by the wallet.
+ * Typically different from the merchant-generated tip ID.
+ */
+ walletTipId: string;
+ /**
+ * Has the tip already been accepted?
+ */
+ accepted: boolean;
+ /**
+ * Amount that the merchant gave.
+ */
+ tipAmountRaw: AmountString;
+ /**
+ * Amount that arrived at the wallet.
+ * Might be lower than the raw amount due to fees.
+ */
+ tipAmountEffective: AmountString;
+ /**
+ * Base URL of the merchant backend giving then tip.
+ */
+ merchantBaseUrl: string;
+ /**
+ * Base URL of the exchange that is used to withdraw the tip.
+ * Determined by the merchant, the wallet/user has no choice here.
+ */
+ exchangeBaseUrl: string;
+ /**
+ * Time when the tip will expire. After it expired, it can't be picked
+ * up anymore.
+ */
+ expirationTimestamp: TalerProtocolTimestamp;
+}
+
+```
+
+### AcceptTipOp
+```typescript
+/**
+ * Accept a tip.
+ */
+export type AcceptTipOp = {
+ op: WalletApiOperation.AcceptTip;
+ request: AcceptTipRequest;
+ response: EmptyObject;
+};
+// AcceptTip = "acceptTip"
+
+```
+```typescript
+export interface AcceptTipRequest {
+ walletTipId: string;
+}
+
+```
+
+### ListExchangesOp
+```typescript
+/**
+ * List exchanges known to the wallet.
+ */
+export type ListExchangesOp = {
+ op: WalletApiOperation.ListExchanges;
+ request: EmptyObject;
+ response: ExchangesListResponse;
+};
+// ListExchanges = "listExchanges"
+
+```
+```typescript
+export interface ExchangesListResponse {
+ exchanges: ExchangeListItem[];
+}
+
+```
+
+### AddExchangeOp
+```typescript
+/**
+ * Add / force-update an exchange.
+ */
+export type AddExchangeOp = {
+ op: WalletApiOperation.AddExchange;
+ request: AddExchangeRequest;
+ response: EmptyObject;
+};
+// AddExchange = "addExchange"
+
+```
+
+### ListKnownBankAccountsOp
+```typescript
+export type ListKnownBankAccountsOp = {
+ op: WalletApiOperation.ListKnownBankAccounts;
+ request: ListKnownBankAccountsRequest;
+ response: KnownBankAccounts;
+};
+// ListKnownBankAccounts = "listKnownBankAccounts"
+
+```
+```typescript
+export interface ListKnownBankAccountsRequest {
+ currency?: string;
+}
+
+```
+```typescript
+export interface KnownBankAccounts {
+ accounts: KnownBankAccountsInfo[];
+}
+
+```
+```typescript
+export interface KnownBankAccountsInfo {
+ uri: PaytoUri;
+ kyc_completed: boolean;
+ currency: string;
+ alias: string;
+}
+
+```
+```typescript
+export declare type PaytoUri =
+ | PaytoUriUnknown
+ | PaytoUriIBAN
+ | PaytoUriTalerBank
+ | PaytoUriBitcoin;
+
+```
+```typescript
+export interface PaytoUriUnknown extends PaytoUriGeneric {
+ isKnown: false;
+}
+
+```
+```typescript
+export interface PaytoUriGeneric {
+ targetType: string;
+ targetPath: string;
+ params: {
+ [name: string]: string;
+ };
+}
+
+```
+```typescript
+export interface PaytoUriIBAN extends PaytoUriGeneric {
+ isKnown: true;
+ targetType: "iban";
+ iban: string;
+}
+
+```
+```typescript
+export interface PaytoUriTalerBank extends PaytoUriGeneric {
+ isKnown: true;
+ targetType: "x-taler-bank";
+ host: string;
+ account: string;
+}
+
+```
+```typescript
+export interface PaytoUriBitcoin extends PaytoUriGeneric {
+ isKnown: true;
+ targetType: "bitcoin";
+ segwitAddrs: Array<string>;
+}
+
+```
+
+### AddKnownBankAccountsOp
+```typescript
+export type AddKnownBankAccountsOp = {
+ op: WalletApiOperation.AddKnownBankAccounts;
+ request: AddKnownBankAccountsRequest;
+ response: EmptyObject;
+};
+// AddKnownBankAccounts = "addKnownBankAccounts"
+
+```
+```typescript
+export interface AddKnownBankAccountsRequest {
+ payto: string;
+ alias: string;
+ currency: string;
+}
+
+```
+
+### ForgetKnownBankAccountsOp
+```typescript
+export type ForgetKnownBankAccountsOp = {
+ op: WalletApiOperation.ForgetKnownBankAccounts;
+ request: ForgetKnownBankAccountsRequest;
+ response: EmptyObject;
+};
+// ForgetKnownBankAccounts = "forgetKnownBankAccounts"
+
+```
+```typescript
+export interface ForgetKnownBankAccountsRequest {
+ payto: string;
+}
+
+```
+
+### SetExchangeTosAcceptedOp
+```typescript
+/**
+ * Accept a particular version of the exchange terms of service.
+ */
+export type SetExchangeTosAcceptedOp = {
+ op: WalletApiOperation.SetExchangeTosAccepted;
+ request: AcceptExchangeTosRequest;
+ response: EmptyObject;
+};
+// SetExchangeTosAccepted = "setExchangeTosAccepted"
+
+```
+```typescript
+export interface AcceptExchangeTosRequest {
+ exchangeBaseUrl: string;
+ etag: string | undefined;
+}
+
+```
+
+### GetExchangeTosOp
+```typescript
+/**
+ * Get the current terms of a service of an exchange.
+ */
+export type GetExchangeTosOp = {
+ op: WalletApiOperation.GetExchangeTos;
+ request: GetExchangeTosRequest;
+ response: GetExchangeTosResult;
+};
+// GetExchangeTos = "getExchangeTos"
+
+```
+```typescript
+export interface GetExchangeTosRequest {
+ exchangeBaseUrl: string;
+ acceptedFormat?: string[];
+}
+
+```
+```typescript
+export interface GetExchangeTosResult {
+ /**
+ * Markdown version of the current ToS.
+ */
+ content: string;
+ /**
+ * Version tag of the current ToS.
+ */
+ currentEtag: string;
+ /**
+ * Version tag of the last ToS that the user has accepted,
+ * if any.
+ */
+ acceptedEtag: string | undefined;
+ /**
+ * Accepted content type
+ */
+ contentType: string;
+ tosStatus: ExchangeTosStatus;
+}
+
+```
+
+### GetExchangeDetailedInfoOp
+```typescript
+/**
+ * Get the current terms of a service of an exchange.
+ */
+export type GetExchangeDetailedInfoOp = {
+ op: WalletApiOperation.GetExchangeDetailedInfo;
+ request: AddExchangeRequest;
+ response: ExchangeDetailedResponse;
+};
+// GetExchangeDetailedInfo = "getExchangeDetailedInfo"
+
+```
+```typescript
+export interface ExchangeDetailedResponse {
+ exchange: ExchangeFullDetails;
+}
+
+```
+```typescript
+export interface ExchangeFullDetails {
+ exchangeBaseUrl: string;
+ currency: string;
+ paytoUris: string[];
+ tos: ExchangeTosStatusDetails;
+ auditors: ExchangeAuditor[];
+ wireInfo: WireInfo;
+ denomFees: DenomOperationMap<FeeDescription[]>;
+ transferFees: Record<string, FeeDescription[]>;
+ globalFees: FeeDescription[];
+}
+
+```
+```typescript
+export interface ExchangeTosStatusDetails {
+ acceptedVersion?: string;
+ currentVersion?: string;
+ contentType?: string;
+ content?: string;
+}
+
+```
+```typescript
+export interface WireInfo {
+ feesForType: WireFeeMap;
+ accounts: ExchangeAccount[];
+}
+
+```
+```typescript
+/**
+ * Information about one of the exchange's bank accounts.
+ */
+export interface ExchangeAccount {
+ payto_uri: string;
+ master_sig: string;
+}
+
+```
+```typescript
+export interface FeeDescription {
+ group: string;
+ from: AbsoluteTime;
+ until: AbsoluteTime;
+ fee?: AmountString;
+}
+
+```
+
+### ListCurrenciesOp
+```typescript
+/**
+ * List currencies known to the wallet.
+ */
+export type ListCurrenciesOp = {
+ op: WalletApiOperation.ListCurrencies;
+ request: EmptyObject;
+ response: WalletCurrencyInfo;
+};
+// ListCurrencies = "listCurrencies"
+
+```
+```typescript
+export interface WalletCurrencyInfo {
+ trustedAuditors: {
+ currency: string;
+ auditorPub: string;
+ auditorBaseUrl: string;
+ }[];
+ trustedExchanges: {
+ currency: string;
+ exchangeMasterPub: string;
+ exchangeBaseUrl: string;
+ }[];
+}
+
+```
+
+### CreateDepositGroupOp
+```typescript
+/**
+ * Create a new deposit group.
+ *
+ * Deposit groups are used to deposit multiple coins to a bank
+ * account, usually the wallet user's own bank account.
+ */
+export type CreateDepositGroupOp = {
+ op: WalletApiOperation.CreateDepositGroup;
+ request: CreateDepositGroupRequest;
+ response: CreateDepositGroupResponse;
+};
+// CreateDepositGroup = "createDepositGroup"
+
+```
+```typescript
+export interface CreateDepositGroupRequest {
+ depositPaytoUri: string;
+ amount: AmountString;
+}
+
+```
+```typescript
+export interface CreateDepositGroupResponse {
+ depositGroupId: string;
+ transactionId: string;
+}
+
+```
+
+### TrackDepositGroupOp
+```typescript
+/**
+ * Track the status of a deposit group by querying the exchange.
+ */
+export type TrackDepositGroupOp = {
+ op: WalletApiOperation.TrackDepositGroup;
+ request: TrackDepositGroupRequest;
+ response: TrackDepositGroupResponse;
+};
+// TrackDepositGroup = "trackDepositGroup"
+
+```
+```typescript
+export interface TrackDepositGroupRequest {
+ depositGroupId: string;
+}
+
+```
+```typescript
+export interface TrackDepositGroupResponse {
+ responses: {
+ status: number;
+ body: any;
+ }[];
+}
+
+```
+
+### GetFeeForDepositOp
+```typescript
+export type GetFeeForDepositOp = {
+ op: WalletApiOperation.GetFeeForDeposit;
+ request: GetFeeForDepositRequest;
+ response: DepositGroupFees;
+};
+// GetFeeForDeposit = "getFeeForDeposit"
+
+```
+```typescript
+export interface GetFeeForDepositRequest {
+ depositPaytoUri: string;
+ amount: AmountString;
+}
+
+```
+```typescript
+export interface DepositGroupFees {
+ coin: AmountString;
+ wire: AmountString;
+ refresh: AmountString;
+}
+
+```
+
+### PrepareDepositOp
+```typescript
+export type PrepareDepositOp = {
+ op: WalletApiOperation.PrepareDeposit;
+ request: PrepareDepositRequest;
+ response: PrepareDepositResponse;
+};
+// PrepareDeposit = "prepareDeposit"
+
+```
+```typescript
+export interface PrepareDepositRequest {
+ depositPaytoUri: string;
+ amount: AmountString;
+}
+
+```
+```typescript
+export interface PrepareDepositResponse {
+ totalDepositCost: AmountString;
+ effectiveDepositAmount: AmountString;
+}
+
+```
+
+### ExportBackupRecoveryOp
+```typescript
+/**
+ * Export the recovery information for the wallet.
+ */
+export type ExportBackupRecoveryOp = {
+ op: WalletApiOperation.ExportBackupRecovery;
+ request: EmptyObject;
+ response: BackupRecovery;
+};
+// ExportBackupRecovery = "exportBackupRecovery"
+
+```
+
+### ImportBackupRecoveryOp
+```typescript
+/**
+ * Import recovery information into the wallet.
+ */
+export type ImportBackupRecoveryOp = {
+ op: WalletApiOperation.ImportBackupRecovery;
+ request: RecoveryLoadRequest;
+ response: EmptyObject;
+};
+// ImportBackupRecovery = "importBackupRecovery"
+
+```
+```typescript
+/**
+ * Load recovery information into the wallet.
+ */
+export interface RecoveryLoadRequest {
+ recovery: BackupRecovery;
+ strategy?: RecoveryMergeStrategy;
+}
+
+```
+```typescript
+/**
+ * Strategy for loading recovery information.
+ */
+export declare enum RecoveryMergeStrategy {
+ /**
+ * Keep the local wallet root key, import and take over providers.
+ */
+ Ours = "ours",
+ /**
+ * Migrate to the wallet root key from the recovery information.
+ */
+ Theirs = "theirs",
+}
+
+```
+
+### RunBackupCycleOp
+```typescript
+/**
+ * Manually make and upload a backup.
+ */
+export type RunBackupCycleOp = {
+ op: WalletApiOperation.RunBackupCycle;
+ request: RunBackupCycleRequest;
+ response: EmptyObject;
+};
+// RunBackupCycle = "runBackupCycle"
+
+```
+```typescript
+export interface RunBackupCycleRequest {
+ /**
+ * List of providers to backup or empty for all known providers.
+ */
+ providers?: Array<string>;
+}
+
+```
+
+### ExportBackupOp
+```typescript
+export type ExportBackupOp = {
+ op: WalletApiOperation.ExportBackup;
+ request: EmptyObject;
+ response: EmptyObject;
+};
+// ExportBackup = "exportBackup"
+
+```
+
+### AddBackupProviderOp
+```typescript
+/**
+ * Add a new backup provider.
+ */
+export type AddBackupProviderOp = {
+ op: WalletApiOperation.AddBackupProvider;
+ request: AddBackupProviderRequest;
+ response: EmptyObject;
+};
+// AddBackupProvider = "addBackupProvider"
+
+```
+```typescript
+export interface AddBackupProviderRequest {
+ backupProviderBaseUrl: string;
+ name: string;
+ /**
+ * Activate the provider. Should only be done after
+ * the user has reviewed the provider.
+ */
+ activate?: boolean;
+}
+
+```
+
+### RemoveBackupProviderOp
+```typescript
+export type RemoveBackupProviderOp = {
+ op: WalletApiOperation.RemoveBackupProvider;
+ request: RemoveBackupProviderRequest;
+ response: EmptyObject;
+};
+// RemoveBackupProvider = "removeBackupProvider"
+
+```
+```typescript
+export interface RemoveBackupProviderRequest {
+ provider: string;
+}
+
+```
+
+### GetBackupInfoOp
+```typescript
+/**
+ * Get some useful stats about the backup state.
+ */
+export type GetBackupInfoOp = {
+ op: WalletApiOperation.GetBackupInfo;
+ request: EmptyObject;
+ response: BackupInfo;
+};
+// GetBackupInfo = "getBackupInfo"
+
+```
+```typescript
+export interface BackupInfo {
+ walletRootPub: string;
+ deviceId: string;
+ providers: ProviderInfo[];
+}
+
+```
+```typescript
+/**
+ * Information about one provider.
+ *
+ * We don't store the account key here,
+ * as that's derived from the wallet root key.
+ */
+export interface ProviderInfo {
+ active: boolean;
+ syncProviderBaseUrl: string;
+ name: string;
+ terms?: BackupProviderTerms;
+ /**
+ * Last communication issue with the provider.
+ */
+ lastError?: TalerErrorDetail;
+ lastSuccessfulBackupTimestamp?: TalerProtocolTimestamp;
+ lastAttemptedBackupTimestamp?: TalerProtocolTimestamp;
+ paymentProposalIds: string[];
+ backupProblem?: BackupProblem;
+ paymentStatus: ProviderPaymentStatus;
+}
+
+```
+```typescript
+export interface BackupProviderTerms {
+ supportedProtocolVersion: string;
+ annualFee: AmountString;
+ storageLimitInMegabytes: number;
+}
+
+```
+```typescript
+export type BackupProblem =
+ | BackupUnreadableProblem
+ | BackupConflictingDeviceProblem;
+
+```
+```typescript
+export interface BackupUnreadableProblem {
+ type: "backup-unreadable";
+}
+
+```
+```typescript
+export interface BackupConflictingDeviceProblem {
+ type: "backup-conflicting-device";
+ otherDeviceId: string;
+ myDeviceId: string;
+ backupTimestamp: AbsoluteTime;
+}
+
+```
+```typescript
+export type ProviderPaymentStatus =
+ | ProviderPaymentTermsChanged
+ | ProviderPaymentPaid
+ | ProviderPaymentInsufficientBalance
+ | ProviderPaymentUnpaid
+ | ProviderPaymentPending;
+
+```
+```typescript
+export interface ProviderPaymentTermsChanged {
+ type: ProviderPaymentType.TermsChanged;
+ paidUntil: AbsoluteTime;
+ oldTerms: BackupProviderTerms;
+ newTerms: BackupProviderTerms;
+}
+
+```
+```typescript
+export interface ProviderPaymentPaid {
+ type: ProviderPaymentType.Paid;
+ paidUntil: AbsoluteTime;
+}
+
+```
+```typescript
+export interface ProviderPaymentInsufficientBalance {
+ type: ProviderPaymentType.InsufficientBalance;
+}
+
+```
+```typescript
+export interface ProviderPaymentUnpaid {
+ type: ProviderPaymentType.Unpaid;
+}
+
+```
+```typescript
+export interface ProviderPaymentPending {
+ type: ProviderPaymentType.Pending;
+}
+
+```
+
+### SetWalletDeviceIdOp
+```typescript
+/**
+ * Set the internal device ID of the wallet, used to
+ * identify whether a different/new wallet is accessing
+ * the backup of another wallet.
+ */
+export type SetWalletDeviceIdOp = {
+ op: WalletApiOperation.SetWalletDeviceId;
+ request: SetWalletDeviceIdRequest;
+ response: EmptyObject;
+};
+// SetWalletDeviceId = "setWalletDeviceId"
+
+```
+```typescript
+export interface SetWalletDeviceIdRequest {
+ /**
+ * New wallet device ID to set.
+ */
+ walletDeviceId: string;
+}
+
+```
+
+### ExportBackupPlainOp
+```typescript
+/**
+ * Export a backup JSON, mostly useful for testing.
+ */
+export type ExportBackupPlainOp = {
+ op: WalletApiOperation.ExportBackupPlain;
+ request: EmptyObject;
+ response: WalletBackupContentV1;
+};
+// ExportBackupPlain = "exportBackupPlain"
+
+```
+
+### InitiatePeerPushPaymentOp
+```typescript
+/**
+ * Initiate an outgoing peer push payment.
+ */
+export type InitiatePeerPushPaymentOp = {
+ op: WalletApiOperation.InitiatePeerPushPayment;
+ request: InitiatePeerPushPaymentRequest;
+ response: InitiatePeerPushPaymentResponse;
+};
+// InitiatePeerPushPayment = "initiatePeerPushPayment"
+
+```
+```typescript
+export interface InitiatePeerPushPaymentRequest {
+ amount: AmountString;
+ partialContractTerms: any;
+}
+
+```
+```typescript
+export interface InitiatePeerPushPaymentResponse {
+ exchangeBaseUrl: string;
+ pursePub: string;
+ mergePriv: string;
+ contractPriv: string;
+ talerUri: string;
+ transactionId: string;
+}
+
+```
+
+### CheckPeerPushPaymentOp
+```typescript
+/**
+ * Check an incoming peer push payment.
+ */
+export type CheckPeerPushPaymentOp = {
+ op: WalletApiOperation.CheckPeerPushPayment;
+ request: CheckPeerPushPaymentRequest;
+ response: CheckPeerPushPaymentResponse;
+};
+// CheckPeerPushPayment = "checkPeerPushPayment"
+
+```
+```typescript
+export interface CheckPeerPushPaymentRequest {
+ talerUri: string;
+}
+
+```
+```typescript
+export interface CheckPeerPushPaymentResponse {
+ contractTerms: any;
+ amount: AmountString;
+ peerPushPaymentIncomingId: string;
+}
+
+```
+
+### AcceptPeerPushPaymentOp
+```typescript
+/**
+ * Accept an incoming peer push payment.
+ */
+export type AcceptPeerPushPaymentOp = {
+ op: WalletApiOperation.AcceptPeerPushPayment;
+ request: AcceptPeerPushPaymentRequest;
+ response: EmptyObject;
+};
+// AcceptPeerPushPayment = "acceptPeerPushPayment"
+
+```
+```typescript
+export interface AcceptPeerPushPaymentRequest {
+ /**
+ * Transparent identifier of the incoming peer push payment.
+ */
+ peerPushPaymentIncomingId: string;
+}
+
+```
+
+### InitiatePeerPullPaymentOp
+```typescript
+/**
+ * Initiate an outgoing peer pull payment.
+ */
+export type InitiatePeerPullPaymentOp = {
+ op: WalletApiOperation.InitiatePeerPullPayment;
+ request: InitiatePeerPullPaymentRequest;
+ response: InitiatePeerPullPaymentResponse;
+};
+// InitiatePeerPullPayment = "initiatePeerPullPayment"
+
+```
+```typescript
+export interface InitiatePeerPullPaymentRequest {
+ /**
+ * FIXME: Make this optional?
+ */
+ exchangeBaseUrl: string;
+ amount: AmountString;
+ partialContractTerms: any;
+}
+
+```
+```typescript
+export interface InitiatePeerPullPaymentResponse {
+ /**
+ * Taler URI for the other party to make the payment
+ * that was requested.
+ */
+ talerUri: string;
+ transactionId: string;
+}
+
+```
+
+### CheckPeerPullPaymentOp
+```typescript
+/**
+ * Prepare for an incoming peer pull payment.
+ */
+export type CheckPeerPullPaymentOp = {
+ op: WalletApiOperation.CheckPeerPullPayment;
+ request: CheckPeerPullPaymentRequest;
+ response: CheckPeerPullPaymentResponse;
+};
+// CheckPeerPullPayment = "checkPeerPullPayment"
+
+```
+```typescript
+export interface CheckPeerPullPaymentRequest {
+ talerUri: string;
+}
+
+```
+```typescript
+export interface CheckPeerPullPaymentResponse {
+ contractTerms: any;
+ amount: AmountString;
+ peerPullPaymentIncomingId: string;
+}
+
+```
+
+### AcceptPeerPullPaymentOp
+```typescript
+/**
+ * Accept an incoming peer pull payment.
+ */
+export type AcceptPeerPullPaymentOp = {
+ op: WalletApiOperation.AcceptPeerPullPayment;
+ request: AcceptPeerPullPaymentRequest;
+ response: EmptyObject;
+};
+// AcceptPeerPullPayment = "acceptPeerPullPayment"
+
+```
+```typescript
+export interface AcceptPeerPullPaymentRequest {
+ /**
+ * Transparent identifier of the incoming peer pull payment.
+ */
+ peerPullPaymentIncomingId: string;
+}
+
+```
+
+### ExportDbOp
+```typescript
+/**
+ * Export the wallet database's contents to JSON.
+ */
+export type ExportDbOp = {
+ op: WalletApiOperation.ExportDb;
+ request: EmptyObject;
+ response: any;
+};
+// ExportDb = "exportDb"
+
+```
+
+### ImportDbOp
+```typescript
+export type ImportDbOp = {
+ op: WalletApiOperation.ImportDb;
+ request: any;
+ response: any;
+};
+// ImportDb = "importDb"
+
+```
+
+### ClearDbOp
+```typescript
+/**
+ * Dangerously clear the whole wallet database.
+ */
+export type ClearDbOp = {
+ op: WalletApiOperation.ClearDb;
+ request: EmptyObject;
+ response: EmptyObject;
+};
+// ClearDb = "clearDb"
+
+```
+
+### RecycleOp
+```typescript
+/**
+ * Export a backup, clear the database and re-import it.
+ */
+export type RecycleOp = {
+ op: WalletApiOperation.Recycle;
+ request: EmptyObject;
+ response: EmptyObject;
+};
+// Recycle = "recycle"
+
+```
+
+### ApplyDevExperimentOp
+```typescript
+/**
+ * Apply a developer experiment to the current wallet state.
+ *
+ * This allows UI developers / testers to play around without
+ * an elaborate test environment.
+ */
+export type ApplyDevExperimentOp = {
+ op: WalletApiOperation.ApplyDevExperiment;
+ request: ApplyDevExperimentRequest;
+ response: EmptyObject;
+};
+// ApplyDevExperiment = "applyDevExperiment"
+
+```
+```typescript
+export interface ApplyDevExperimentRequest {
+ devExperimentUri: string;
+}
+
+```
+
+### SetDevModeOp
+```typescript
+export type SetDevModeOp = {
+ op: WalletApiOperation.SetDevMode;
+ request: SetDevModeRequest;
+ response: EmptyObject;
+};
+// SetDevMode = "setDevMode"
+
+```
+```typescript
+export interface SetDevModeRequest {
+ devModeEnabled: boolean;
+}
+
+```
+
+### RunIntegrationTestOp
+```typescript
+/**
+ * Run a simple integration test on a test deployment
+ * of the exchange and merchant.
+ */
+export type RunIntegrationTestOp = {
+ op: WalletApiOperation.RunIntegrationTest;
+ request: IntegrationTestArgs;
+ response: EmptyObject;
+};
+// RunIntegrationTest = "runIntegrationTest"
+
+```
+```typescript
+export interface IntegrationTestArgs {
+ exchangeBaseUrl: string;
+ bankBaseUrl: string;
+ bankAccessApiBaseUrl?: string;
+ merchantBaseUrl: string;
+ merchantAuthToken?: string;
+ amountToWithdraw: string;
+ amountToSpend: string;
+}
+
+```
+
+### TestCryptoOp
+```typescript
+/**
+ * Test crypto worker.
+ */
+export type TestCryptoOp = {
+ op: WalletApiOperation.TestCrypto;
+ request: EmptyObject;
+ response: any;
+};
+// TestCrypto = "testCrypto"
+
+```
+
+### WithdrawTestBalanceOp
+```typescript
+/**
+ * Make withdrawal on a test deployment of the exchange
+ * and merchant.
+ */
+export type WithdrawTestBalanceOp = {
+ op: WalletApiOperation.WithdrawTestBalance;
+ request: WithdrawTestBalanceRequest;
+ response: EmptyObject;
+};
+// WithdrawTestBalance = "withdrawTestBalance"
+
+```
+```typescript
+export interface WithdrawTestBalanceRequest {
+ amount: string;
+ bankBaseUrl: string;
+ /**
+ * Bank access API base URL. Defaults to the bankBaseUrl.
+ */
+ bankAccessApiBaseUrl?: string;
+ exchangeBaseUrl: string;
+ forcedDenomSel?: ForcedDenomSel;
+}
+
+```
+
+### WithdrawTestkudosOp
+```typescript
+/**
+ * Make a withdrawal of testkudos on test.taler.net.
+ */
+export type WithdrawTestkudosOp = {
+ op: WalletApiOperation.WithdrawTestkudos;
+ request: EmptyObject;
+ response: EmptyObject;
+};
+// WithdrawTestkudos = "withdrawTestkudos"
+
+```
+
+### TestPayOp
+```typescript
+/**
+ * Make a test payment using a test deployment of
+ * the exchange and merchant.
+ */
+export type TestPayOp = {
+ op: WalletApiOperation.TestPay;
+ request: TestPayArgs;
+ response: TestPayResult;
+};
+// TestPay = "testPay"
+
+```
+```typescript
+export interface TestPayArgs {
+ merchantBaseUrl: string;
+ merchantAuthToken?: string;
+ amount: string;
+ summary: string;
+ forcedCoinSel?: ForcedCoinSel;
+}
+
+```
+```typescript
+export interface TestPayResult {
+ payCoinSelection: PayCoinSelection;
+}
+
+```
+```typescript
+/**
+ * Result of selecting coins, contains the exchange, and selected
+ * coins with their denomination.
+ */
+export interface PayCoinSelection {
+ /**
+ * Amount requested by the merchant.
+ */
+ paymentAmount: AmountString;
+ /**
+ * Public keys of the coins that were selected.
+ */
+ coinPubs: string[];
+ /**
+ * Amount that each coin contributes.
+ */
+ coinContributions: AmountString[];
+ /**
+ * How much of the wire fees is the customer paying?
+ */
+ customerWireFees: AmountString;
+ /**
+ * How much of the deposit fees is the customer paying?
+ */
+ customerDepositFees: AmountString;
+}
+
+```
+
+### WithdrawFakebankOp
+```typescript
+/**
+ * Make a withdrawal from a fakebank, i.e.
+ * a bank where test users can be registered freely
+ * and testing APIs are available.
+ */
+export type WithdrawFakebankOp = {
+ op: WalletApiOperation.WithdrawFakebank;
+ request: WithdrawFakebankRequest;
+ response: EmptyObject;
+};
+// WithdrawFakebank = "withdrawFakebank"
+
+```
+```typescript
+export interface WithdrawFakebankRequest {
+ amount: AmountString;
+ exchange: string;
+ bank: string;
+}
+
+```
+
+### GetPendingTasksOp
+```typescript
+/**
+ * Get wallet-internal pending tasks.
+ */
+export type GetPendingTasksOp = {
+ op: WalletApiOperation.GetPendingOperations;
+ request: EmptyObject;
+ response: PendingTasksResponse;
+};
+// GetPendingOperations = "getPendingOperations"
+
+```
+```typescript
+/**
+ * Response returned from the pending operations API.
+ */
+export interface PendingOperationsResponse {
+ /**
+ * List of pending operations.
+ */
+ pendingOperations: PendingTaskInfo[];
+}
+
+```
+```typescript
+/**
+ * Information about a pending operation.
+ */
+export type PendingTaskInfo = PendingTaskInfoCommon &
+ (
+ | PendingExchangeUpdateTask
+ | PendingExchangeCheckRefreshTask
+ | PendingPurchaseTask
+ | PendingRefreshTask
+ | PendingTipPickupTask
+ | PendingWithdrawTask
+ | PendingRecoupTask
+ | PendingDepositTask
+ | PendingBackupTask
+ );
+
+```
+```typescript
+/**
+ * Fields that are present in every pending operation.
+ */
+export interface PendingTaskInfoCommon {
+ /**
+ * Type of the pending operation.
+ */
+ type: PendingTaskType;
+ /**
+ * Unique identifier for the pending task.
+ */
+ id: string;
+ /**
+ * Set to true if the operation indicates that something is really in progress,
+ * as opposed to some regular scheduled operation that can be tried later.
+ */
+ givesLifeness: boolean;
+ /**
+ * Operation is active and waiting for a longpoll result.
+ */
+ isLongpolling: boolean;
+ /**
+ * Operation is waiting to be executed.
+ */
+ isDue: boolean;
+ /**
+ * Timestamp when the pending operation should be executed next.
+ */
+ timestampDue: AbsoluteTime;
+ /**
+ * Retry info. Currently used to stop the wallet after any operation
+ * exceeds a number of retries.
+ */
+ retryInfo?: RetryInfo;
+}
+
+```
+```typescript
+export enum PendingTaskType {
+ ExchangeUpdate = "exchange-update",
+ ExchangeCheckRefresh = "exchange-check-refresh",
+ Purchase = "purchase",
+ Refresh = "refresh",
+ Recoup = "recoup",
+ TipPickup = "tip-pickup",
+ Withdraw = "withdraw",
+ Deposit = "deposit",
+ Backup = "backup",
+}
+
+```
+```typescript
+export interface RetryInfo {
+ firstTry: AbsoluteTime;
+ nextRetry: AbsoluteTime;
+ retryCounter: number;
+}
+
+```
+```typescript
+export interface RetryPolicy {
+ readonly backoffDelta: Duration;
+ readonly backoffBase: number;
+ readonly maxTimeout: Duration;
+}
+
+```
+```typescript
+// Declare "static" methods in Error
+interface ErrorConstructor {
+ /** Create .stack property on a target object */
+ captureStackTrace(targetObject: object, constructorOpt?: Function): void;
+ /**
+ * Optional override for formatting stack traces
+ *
+ * @see https://v8.dev/docs/stack-trace-api#customizing-stack-traces
+ */
+ prepareStackTrace?:
+ | ((err: Error, stackTraces: NodeJS.CallSite[]) => any)
+ | undefined;
+ stackTraceLimit: number;
+}
+
+```
+```typescript
+interface CallSite {
+ /**
+ * Value of "this"
+ */
+ getThis(): unknown;
+ /**
+ * Type of "this" as a string.
+ * This is the name of the function stored in the constructor field of
+ * "this", if available. Otherwise the object's [[Class]] internal
+ * property.
+ */
+ getTypeName(): string | null;
+ /**
+ * Current function
+ */
+ getFunction(): Function | undefined;
+ /**
+ * Name of the current function, typically its name property.
+ * If a name property is not available an attempt will be made to try
+ * to infer a name from the function's context.
+ */
+ getFunctionName(): string | null;
+ /**
+ * Name of the property [of "this" or one of its prototypes] that holds
+ * the current function
+ */
+ getMethodName(): string | null;
+ /**
+ * Name of the script [if this function was defined in a script]
+ */
+ getFileName(): string | null;
+ /**
+ * Current line number [if this function was defined in a script]
+ */
+ getLineNumber(): number | null;
+ /**
+ * Current column number [if this function was defined in a script]
+ */
+ getColumnNumber(): number | null;
+ /**
+ * A call site object representing the location where eval was called
+ * [if this function was created using a call to eval]
+ */
+ getEvalOrigin(): string | undefined;
+ /**
+ * Is this a toplevel invocation, that is, is "this" the global object?
+ */
+ isToplevel(): boolean;
+ /**
+ * Does this call take place in code defined by a call to eval?
+ */
+ isEval(): boolean;
+ /**
+ * Is this call in native V8 code?
+ */
+ isNative(): boolean;
+ /**
+ * Is this a constructor call?
+ */
+ isConstructor(): boolean;
+}
+
+```
+```typescript
+/**
+ * The wallet is currently updating information about an exchange.
+ */
+export interface PendingExchangeUpdateTask {
+ type: PendingTaskType.ExchangeUpdate;
+ exchangeBaseUrl: string;
+ lastError: TalerErrorDetail | undefined;
+}
+
+```
+```typescript
+/**
+ * The wallet should check whether coins from this exchange
+ * need to be auto-refreshed.
+ */
+export interface PendingExchangeCheckRefreshTask {
+ type: PendingTaskType.ExchangeCheckRefresh;
+ exchangeBaseUrl: string;
+}
+
+```
+```typescript
+/**
+ * A purchase needs to be processed (i.e. for download / payment / refund).
+ */
+export interface PendingPurchaseTask {
+ type: PendingTaskType.Purchase;
+ proposalId: string;
+ retryInfo?: RetryInfo;
+ /**
+ * Status of the payment as string, used only for debugging.
+ */
+ statusStr: string;
+ lastError: TalerErrorDetail | undefined;
+}
+
+```
+```typescript
+/**
+ * Status of an ongoing withdrawal operation.
+ */
+export interface PendingRefreshTask {
+ type: PendingTaskType.Refresh;
+ lastError?: TalerErrorDetail;
+ refreshGroupId: string;
+ finishedPerCoin: boolean[];
+ retryInfo?: RetryInfo;
+}
+
+```
+```typescript
+/**
+ * The wallet is picking up a tip that the user has accepted.
+ */
+export interface PendingTipPickupTask {
+ type: PendingTaskType.TipPickup;
+ tipId: string;
+ merchantBaseUrl: string;
+ merchantTipId: string;
+}
+
+```
+```typescript
+/**
+ * Status of an ongoing withdrawal operation.
+ */
+export interface PendingWithdrawTask {
+ type: PendingTaskType.Withdraw;
+ lastError: TalerErrorDetail | undefined;
+ retryInfo?: RetryInfo;
+ withdrawalGroupId: string;
+}
+
+```
+```typescript
+export interface PendingRecoupTask {
+ type: PendingTaskType.Recoup;
+ recoupGroupId: string;
+ retryInfo?: RetryInfo;
+ lastError: TalerErrorDetail | undefined;
+}
+
+```
+```typescript
+/**
+ * Status of an ongoing deposit operation.
+ */
+export interface PendingDepositTask {
+ type: PendingTaskType.Deposit;
+ lastError: TalerErrorDetail | undefined;
+ retryInfo: RetryInfo | undefined;
+ depositGroupId: string;
+}
+
+```
+```typescript
+export interface PendingBackupTask {
+ type: PendingTaskType.Backup;
+ backupProviderBaseUrl: string;
+ lastError: TalerErrorDetail | undefined;
+}
+
+```
+
+### DumpCoinsOp
+```typescript
+/**
+ * Dump all coins of the wallet in a simple JSON format.
+ */
+export type DumpCoinsOp = {
+ op: WalletApiOperation.DumpCoins;
+ request: EmptyObject;
+ response: CoinDumpJson;
+};
+// DumpCoins = "dumpCoins"
+
+```
+```typescript
+/**
+ * Easy to process format for the public data of coins
+ * managed by the wallet.
+ */
+export interface CoinDumpJson {
+ coins: Array<{
+ /**
+ * The coin's denomination's public key.
+ */
+ denom_pub: DenominationPubKey;
+ /**
+ * Hash of denom_pub.
+ */
+ denom_pub_hash: string;
+ /**
+ * Value of the denomination (without any fees).
+ */
+ denom_value: string;
+ /**
+ * Public key of the coin.
+ */
+ coin_pub: string;
+ /**
+ * Base URL of the exchange for the coin.
+ */
+ exchange_base_url: string;
+ /**
+ * Public key of the parent coin.
+ * Only present if this coin was obtained via refreshing.
+ */
+ refresh_parent_coin_pub: string | undefined;
+ /**
+ * Public key of the reserve for this coin.
+ * Only present if this coin was obtained via refreshing.
+ */
+ withdrawal_reserve_pub: string | undefined;
+ coin_status: CoinStatus;
+ spend_allocation:
+ | {
+ id: string;
+ amount: string;
+ }
+ | undefined;
+ /**
+ * Information about the age restriction
+ */
+ ageCommitmentProof: AgeCommitmentProof | undefined;
+ }>;
+}
+
+```
+```typescript
+export declare type DenominationPubKey =
+ | RsaDenominationPubKey
+ | CsDenominationPubKey;
+
+```
+```typescript
+export interface RsaDenominationPubKey {
+ readonly cipher: DenomKeyType.Rsa;
+ readonly rsa_public_key: string;
+ readonly age_mask: number;
+}
+
+```
+```typescript
+export interface CsDenominationPubKey {
+ readonly cipher: DenomKeyType.ClauseSchnorr;
+ readonly age_mask: number;
+ readonly cs_public_key: string;
+}
+
+```
+```typescript
+/**
+ * Status of a coin.
+ */
+export declare enum CoinStatus {
+ /**
+ * Withdrawn and never shown to anybody.
+ */
+ Fresh = "fresh",
+ /**
+ * Fresh, but currently marked as "suspended", thus won't be used
+ * for spending. Used for testing.
+ */
+ FreshSuspended = "fresh-suspended",
+ /**
+ * A coin that has been spent and refreshed.
+ */
+ Dormant = "dormant",
+}
+
+```
+```typescript
+export interface AgeCommitmentProof {
+ commitment: AgeCommitment;
+ proof: AgeProof;
+}
+
+```
+```typescript
+export interface AgeCommitment {
+ mask: number;
+ /**
+ * Public keys, one for each age group specified in the age mask.
+ */
+ publicKeys: Edx25519PublicKeyEnc[];
+}
+
+```
+```typescript
+export declare type Edx25519PublicKeyEnc = FlavorP<
+ string,
+ "Edx25519PublicKeyEnc",
+ 32
+>;
+
+```
+```typescript
+export declare type FlavorP<T, FlavorT extends string, S extends number> = T & {
+ _flavor?: `taler.${FlavorT}`;
+ _size?: S;
+};
+
+```
+```typescript
+export interface AgeProof {
+ /**
+ * Private keys. Typically smaller than the number of public keys,
+ * because we drop private keys from age groups that are restricted.
+ */
+ privateKeys: Edx25519PrivateKeyEnc[];
+}
+
+```
+```typescript
+export declare type Edx25519PrivateKeyEnc = FlavorP<
+ string,
+ "Edx25519PrivateKeyEnc",
+ 64
+>;
+
+```
+
+### SetCoinSuspendedOp
+```typescript
+/**
+ * Set a coin as (un-)suspended.
+ * Suspended coins won't be used for payments.
+ */
+export type SetCoinSuspendedOp = {
+ op: WalletApiOperation.SetCoinSuspended;
+ request: SetCoinSuspendedRequest;
+ response: EmptyObject;
+};
+// SetCoinSuspended = "setCoinSuspended"
+
+```
+```typescript
+export interface SetCoinSuspendedRequest {
+ coinPub: string;
+ suspended: boolean;
+}
+
+```
+
+### ForceRefreshOp
+```typescript
+/**
+ * Force a refresh on coins where it would not
+ * be necessary.
+ */
+export type ForceRefreshOp = {
+ op: WalletApiOperation.ForceRefresh;
+ request: ForceRefreshRequest;
+ response: EmptyObject;
+};
+// ForceRefresh = "forceRefresh"
+
+```
+```typescript
+export interface ForceRefreshRequest {
+ coinPubList: string[];
+}
+
+```
+
+## Common Declarations
+```typescript
+export interface WalletCoreVersion {
+ hash: string | undefined;
+ version: string;
+ exchange: string;
+ merchant: string;
+ bank: string;
+ devMode: boolean;
+}
+```
+```typescript
+export declare type Transaction =
+ | TransactionWithdrawal
+ | TransactionPayment
+ | TransactionRefund
+ | TransactionTip
+ | TransactionRefresh
+ | TransactionDeposit
+ | TransactionPeerPullCredit
+ | TransactionPeerPullDebit
+ | TransactionPeerPushCredit
+ | TransactionPeerPushDebit;
+```
+```typescript
+export interface TransactionWithdrawal extends TransactionCommon {
+ type: TransactionType.Withdrawal;
+ /**
+ * Exchange of the withdrawal.
+ */
+ exchangeBaseUrl: string;
+ /**
+ * Amount that got subtracted from the reserve balance.
+ */
+ amountRaw: AmountString;
+ /**
+ * Amount that actually was (or will be) added to the wallet's balance.
+ */
+ amountEffective: AmountString;
+ withdrawalDetails: WithdrawalDetails;
+}
+```
+```typescript
+export interface TransactionCommon {
+ transactionId: TransactionIdStr;
+ type: TransactionType;
+ timestamp: TalerProtocolTimestamp;
+ pending: boolean;
+ /**
+ * True if the transaction encountered a problem that might be
+ * permanent. A frozen transaction won't be automatically retried.
+ */
+ frozen: boolean;
+ /**
+ * Raw amount of the transaction (exclusive of fees or other extra costs).
+ */
+ amountRaw: AmountString;
+ /**
+ * Amount added or removed from the wallet's balance (including all fees and other costs).
+ */
+ amountEffective: AmountString;
+ error?: TalerErrorDetail;
+}
+```
+```typescript
+export declare enum TransactionType {
+ Withdrawal = "withdrawal",
+ Payment = "payment",
+ Refund = "refund",
+ Refresh = "refresh",
+ Tip = "tip",
+ Deposit = "deposit",
+ PeerPushDebit = "peer-push-debit",
+ PeerPushCredit = "peer-push-credit",
+ PeerPullDebit = "peer-pull-debit",
+ PeerPullCredit = "peer-pull-credit",
+}
+```
+```typescript
+export interface TalerProtocolTimestamp {
+ readonly t_s: number | "never";
+}
+```
+```typescript
+export interface TalerErrorDetail {
+ code: TalerErrorCode;
+ hint?: string;
+ [x: string]: unknown;
+}
+```
+```typescript
+export declare type WithdrawalDetails =
+ | WithdrawalDetailsForManualTransfer
+ | WithdrawalDetailsForTalerBankIntegrationApi;
+```
+```typescript
+interface WithdrawalDetailsForManualTransfer {
+ type: WithdrawalType.ManualTransfer;
+ /**
+ * Payto URIs that the exchange supports.
+ *
+ * Already contains the amount and message.
+ */
+ exchangePaytoUris: string[];
+ reservePub: string;
+}
+```
+```typescript
+interface WithdrawalDetailsForTalerBankIntegrationApi {
+ type: WithdrawalType.TalerBankIntegrationApi;
+ /**
+ * Set to true if the bank has confirmed the withdrawal, false if not.
+ * An unconfirmed withdrawal usually requires user-input and should be highlighted in the UI.
+ * See also bankConfirmationUrl below.
+ */
+ confirmed: boolean;
+ /**
+ * If the withdrawal is unconfirmed, this can include a URL for user
+ * initiated confirmation.
+ */
+ bankConfirmationUrl?: string;
+ reservePub: string;
+}
+```
+```typescript
+export interface TransactionPayment extends TransactionCommon {
+ type: TransactionType.Payment;
+ /**
+ * Additional information about the payment.
+ */
+ info: OrderShortInfo;
+ /**
+ * Wallet-internal end-to-end identifier for the payment.
+ */
+ proposalId: string;
+ /**
+ * How far did the wallet get with processing the payment?
+ */
+ status: PaymentStatus;
+ /**
+ * Amount that must be paid for the contract
+ */
+ amountRaw: AmountString;
+ /**
+ * Amount that was paid, including deposit, wire and refresh fees.
+ */
+ amountEffective: AmountString;
+ /**
+ * Amount that has been refunded by the merchant
+ */
+ totalRefundRaw: AmountString;
+ /**
+ * Amount will be added to the wallet's balance after fees and refreshing
+ */
+ totalRefundEffective: AmountString;
+ /**
+ * Amount pending to be picked up
+ */
+ refundPending: AmountString | undefined;
+ /**
+ * Reference to applied refunds
+ */
+ refunds: RefundInfoShort[];
+}
+```
+```typescript
+export interface OrderShortInfo {
+ /**
+ * Order ID, uniquely identifies the order within a merchant instance
+ */
+ orderId: string;
+ /**
+ * Hash of the contract terms.
+ */
+ contractTermsHash: string;
+ /**
+ * More information about the merchant
+ */
+ merchant: MerchantInfo;
+ /**
+ * Summary of the order, given by the merchant
+ */
+ summary: string;
+ /**
+ * Map from IETF BCP 47 language tags to localized summaries
+ */
+ summary_i18n?: InternationalizedString;
+ /**
+ * List of products that are part of the order
+ */
+ products: Product[] | undefined;
+ /**
+ * Time indicating when the order should be delivered.
+ * May be overwritten by individual products.
+ */
+ delivery_date?: TalerProtocolTimestamp;
+ /**
+ * Delivery location for (all!) products.
+ */
+ delivery_location?: Location;
+ /**
+ * URL of the fulfillment, given by the merchant
+ */
+ fulfillmentUrl?: string;
+ /**
+ * Plain text message that should be shown to the user
+ * when the payment is complete.
+ */
+ fulfillmentMessage?: string;
+ /**
+ * Translations of fulfillmentMessage.
+ */
+ fulfillmentMessage_i18n?: InternationalizedString;
+}
+```
+```typescript
+export interface MerchantInfo {
+ name: string;
+ jurisdiction?: Location;
+ address?: Location;
+ logo?: string;
+ website?: string;
+ email?: string;
+}
+```
+```typescript
+export interface Location {
+ country?: string;
+ country_subdivision?: string;
+ district?: string;
+ town?: string;
+ town_location?: string;
+ post_code?: string;
+ street?: string;
+ building_name?: string;
+ building_number?: string;
+ address_lines?: string[];
+}
+```
+```typescript
+export interface InternationalizedString {
+ [lang_tag: string]: string;
+}
+```
+```typescript
+export interface Product {
+ product_id?: string;
+ description: string;
+ description_i18n?: {
+ [lang_tag: string]: string;
+ };
+ quantity?: number;
+ unit?: string;
+ price?: AmountString;
+ image?: string;
+ taxes?: Tax[];
+ delivery_date?: TalerProtocolTimestamp;
+}
+```
+```typescript
+export interface Tax {
+ name: string;
+ tax: AmountString;
+}
+```
+```typescript
+export declare enum PaymentStatus {
+ /**
+ * Explicitly aborted after timeout / failure
+ */
+ Aborted = "aborted",
+ /**
+ * Payment failed, wallet will auto-retry.
+ * User should be given the option to retry now / abort.
+ */
+ Failed = "failed",
+ /**
+ * Paid successfully
+ */
+ Paid = "paid",
+ /**
+ * User accepted, payment is processing.
+ */
+ Accepted = "accepted",
+}
+```
+```typescript
+export interface RefundInfoShort {
+ transactionId: string;
+ timestamp: TalerProtocolTimestamp;
+ amountEffective: AmountString;
+ amountRaw: AmountString;
+}
+```
+```typescript
+export interface TransactionRefund extends TransactionCommon {
+ type: TransactionType.Refund;
+ refundedTransactionId: string;
+ info: OrderShortInfo;
+ /**
+ * Amount pending to be picked up
+ */
+ refundPending: AmountString | undefined;
+ amountRaw: AmountString;
+ amountEffective: AmountString;
+}
+```
+```typescript
+export interface TransactionTip extends TransactionCommon {
+ type: TransactionType.Tip;
+ amountRaw: AmountString;
+ /**
+ * More information about the merchant
+ */
+ amountEffective: AmountString;
+ merchantBaseUrl: string;
+}
+```
+```typescript
+/**
+ * A transaction shown for refreshes.
+ * Only shown for (1) refreshes not associated with other transactions
+ * and (2) refreshes in an error state.
+ */
+export interface TransactionRefresh extends TransactionCommon {
+ type: TransactionType.Refresh;
+ /**
+ * Exchange that the coins are refreshed with
+ */
+ exchangeBaseUrl: string;
+ refreshReason: RefreshReason;
+ /**
+ * Transaction ID that caused this refresh.
+ */
+ originatingTransactionId?: string;
+ /**
+ * Always zero for refreshes
+ */
+ amountRaw: AmountString;
+ /**
+ * Fees, i.e. the effective, negative effect of the refresh
+ * on the balance.
+ */
+ amountEffective: AmountString;
+}
+```
+```typescript
+/**
+ * Reasons for why a coin is being refreshed.
+ */
+export declare enum RefreshReason {
+ Manual = "manual",
+ PayMerchant = "pay-merchant",
+ PayDeposit = "pay-deposit",
+ PayPeerPush = "pay-peer-push",
+ PayPeerPull = "pay-peer-pull",
+ Refund = "refund",
+ AbortPay = "abort-pay",
+ Recoup = "recoup",
+ BackupRestored = "backup-restored",
+ Scheduled = "scheduled",
+}
+```
+```typescript
+/**
+ * Deposit transaction, which effectively sends
+ * money from this wallet somewhere else.
+ */
+export interface TransactionDeposit extends TransactionCommon {
+ type: TransactionType.Deposit;
+ depositGroupId: string;
+ /**
+ * Target for the deposit.
+ */
+ targetPaytoUri: string;
+ /**
+ * Raw amount that is being deposited
+ */
+ amountRaw: AmountString;
+ /**
+ * Effective amount that is being deposited
+ */
+ amountEffective: AmountString;
+}
+```
+```typescript
+/**
+ * Credit because we were paid for a P2P invoice we created.
+ */
+export interface TransactionPeerPullCredit extends TransactionCommon {
+ type: TransactionType.PeerPullCredit;
+ info: PeerInfoShort;
+ /**
+ * Exchange used.
+ */
+ exchangeBaseUrl: string;
+ /**
+ * Amount that got subtracted from the reserve balance.
+ */
+ amountRaw: AmountString;
+ /**
+ * Amount that actually was (or will be) added to the wallet's balance.
+ */
+ amountEffective: AmountString;
+ /**
+ * URI to send to the other party.
+ */
+ talerUri: string;
+}
+```
+```typescript
+export interface PeerInfoShort {
+ expiration: TalerProtocolTimestamp | undefined;
+ summary: string | undefined;
+}
+```
+```typescript
+/**
+ * Debit because we paid someone's invoice.
+ */
+export interface TransactionPeerPullDebit extends TransactionCommon {
+ type: TransactionType.PeerPullDebit;
+ info: PeerInfoShort;
+ /**
+ * Exchange used.
+ */
+ exchangeBaseUrl: string;
+ amountRaw: AmountString;
+ amountEffective: AmountString;
+}
+```
+```typescript
+/**
+ * We received money via a P2P payment.
+ */
+export interface TransactionPeerPushCredit extends TransactionCommon {
+ type: TransactionType.PeerPushCredit;
+ info: PeerInfoShort;
+ /**
+ * Exchange used.
+ */
+ exchangeBaseUrl: string;
+ /**
+ * Amount that got subtracted from the reserve balance.
+ */
+ amountRaw: AmountString;
+ /**
+ * Amount that actually was (or will be) added to the wallet's balance.
+ */
+ amountEffective: AmountString;
+}
+```
+```typescript
+/**
+ * We sent money via a P2P payment.
+ */
+export interface TransactionPeerPushDebit extends TransactionCommon {
+ type: TransactionType.PeerPushDebit;
+ info: PeerInfoShort;
+ /**
+ * Exchange used.
+ */
+ exchangeBaseUrl: string;
+ /**
+ * Amount that got subtracted from the reserve balance.
+ */
+ amountRaw: AmountString;
+ /**
+ * Amount that actually was (or will be) added to the wallet's balance.
+ */
+ amountEffective: AmountString;
+ /**
+ * URI to accept the payment.
+ */
+ talerUri: string;
+}
+```
+```typescript
+export interface ExchangeListItem {
+ exchangeBaseUrl: string;
+ currency: string | undefined;
+ paytoUris: string[];
+ tosStatus: ExchangeTosStatus;
+ exchangeStatus: ExchangeEntryStatus;
+ ageRestrictionOptions: number[];
+ /**
+ * Permanently added to the wallet, as opposed to just
+ * temporarily queried.
+ */
+ permanent: boolean;
+ /**
+ * Information about the last error that occured when trying
+ * to update the exchange info.
+ */
+ lastUpdateErrorInfo?: OperationErrorInfo;
+}
+```
+```typescript
+export declare enum ExchangeTosStatus {
+ New = "new",
+ Accepted = "accepted",
+ Changed = "changed",
+ NotFound = "not-found",
+ Unknown = "unknown",
+}
+```
+```typescript
+export declare enum ExchangeEntryStatus {
+ Unknown = "unknown",
+ Outdated = "outdated",
+ Ok = "ok",
+}
+```
+```typescript
+export interface OperationErrorInfo {
+ error: TalerErrorDetail;
+}
+```
+```typescript
+export interface ForcedDenomSel {
+ denoms: {
+ value: AmountString;
+ count: number;
+ }[];
+}
+```
+```typescript
+/**
+ * Contract terms from a merchant.
+ * FIXME: Add type field!
+ */
+export interface MerchantContractTerms {
+ /**
+ * Hash of the merchant's wire details.
+ */
+ h_wire: string;
+ /**
+ * Hash of the merchant's wire details.
+ */
+ auto_refund?: TalerProtocolDuration;
+ /**
+ * Wire method the merchant wants to use.
+ */
+ wire_method: string;
+ /**
+ * Human-readable short summary of the contract.
+ */
+ summary: string;
+ summary_i18n?: InternationalizedString;
+ /**
+ * Nonce used to ensure freshness.
+ */
+ nonce: string;
+ /**
+ * Total amount payable.
+ */
+ amount: string;
+ /**
+ * Auditors accepted by the merchant.
+ */
+ auditors: AuditorHandle[];
+ /**
+ * Deadline to pay for the contract.
+ */
+ pay_deadline: TalerProtocolTimestamp;
+ /**
+ * Maximum deposit fee covered by the merchant.
+ */
+ max_fee: string;
+ /**
+ * Information about the merchant.
+ */
+ merchant: MerchantInfo;
+ /**
+ * Public key of the merchant.
+ */
+ merchant_pub: string;
+ /**
+ * Time indicating when the order should be delivered.
+ * May be overwritten by individual products.
+ */
+ delivery_date?: TalerProtocolTimestamp;
+ /**
+ * Delivery location for (all!) products.
+ */
+ delivery_location?: Location;
+ /**
+ * List of accepted exchanges.
+ */
+ exchanges: ExchangeHandle[];
+ /**
+ * Products that are sold in this contract.
+ */
+ products?: Product[];
+ /**
+ * Deadline for refunds.
+ */
+ refund_deadline: TalerProtocolTimestamp;
+ /**
+ * Deadline for the wire transfer.
+ */
+ wire_transfer_deadline: TalerProtocolTimestamp;
+ /**
+ * Time when the contract was generated by the merchant.
+ */
+ timestamp: TalerProtocolTimestamp;
+ /**
+ * Order id to uniquely identify the purchase within
+ * one merchant instance.
+ */
+ order_id: string;
+ /**
+ * Base URL of the merchant's backend.
+ */
+ merchant_base_url: string;
+ /**
+ * Fulfillment URL to view the product or
+ * delivery status.
+ */
+ fulfillment_url?: string;
+ /**
+ * URL meant to share the shopping cart.
+ */
+ public_reorder_url?: string;
+ /**
+ * Plain text fulfillment message in the merchant's default language.
+ */
+ fulfillment_message?: string;
+ /**
+ * Internationalized fulfillment messages.
+ */
+ fulfillment_message_i18n?: InternationalizedString;
+ /**
+ * Share of the wire fee that must be settled with one payment.
+ */
+ wire_fee_amortization?: number;
+ /**
+ * Maximum wire fee that the merchant agrees to pay for.
+ */
+ max_wire_fee?: string;
+ minimum_age?: number;
+ /**
+ * Extra data, interpreted by the mechant only.
+ */
+ extra?: any;
+}
+```
+```typescript
+export interface TalerProtocolDuration {
+ readonly d_us: number | "forever";
+}
+```
+```typescript
+export interface AuditorHandle {
+ /**
+ * Official name of the auditor.
+ */
+ name: string;
+ /**
+ * Master public signing key of the auditor.
+ */
+ auditor_pub: string;
+ /**
+ * Base URL of the auditor.
+ */
+ url: string;
+}
+```
+```typescript
+/**
+ * Information about an exchange as stored inside a
+ * merchant's contract terms.
+ */
+export interface ExchangeHandle {
+ /**
+ * Master public signing key of the exchange.
+ */
+ master_pub: string;
+ /**
+ * Base URL of the exchange.
+ */
+ url: string;
+}
+```
+```typescript
+/**
+ * Forced coin selection for deposits/payments.
+ */
+export interface ForcedCoinSel {
+ coins: {
+ value: AmountString;
+ contribution: AmountString;
+ }[];
+}
+```
+```typescript
+export interface ApplyRefundResponse {
+ contractTermsHash: string;
+ transactionId: string;
+ proposalId: string;
+ amountEffectivePaid: AmountString;
+ amountRefundGranted: AmountString;
+ amountRefundGone: AmountString;
+ pendingAtExchange: boolean;
+ info: OrderShortInfo;
+}
+```
+```typescript
+export interface AddExchangeRequest {
+ exchangeBaseUrl: string;
+ forceUpdate?: boolean;
+}
+```
+```typescript
+export interface AbsoluteTime {
+ /**
+ * Timestamp in milliseconds.
+ */
+ readonly t_ms: number | "never";
+}
+```
+```typescript
+export interface Duration {
+ /**
+ * Duration in milliseconds.
+ */
+ readonly d_ms: number | "forever";
+}
+```
+```typescript
+export interface BackupRecovery {
+ walletRootPriv: string;
+ providers: {
+ name: string;
+ url: string;
+ }[];
+}
+```