summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristian Blättler <blatc2@bfh.ch>2024-03-05 21:37:22 +0100
committerChristian Blättler <blatc2@bfh.ch>2024-03-05 21:37:22 +0100
commitc04429f8b534890ee7a0823c7e56a45655cd6bd3 (patch)
treea7ecae8e6bf4aa0b77cfca0c66d1020d3b2eeb17
parent5f82d484feaa6b41371226cb3239a68a14caa8a3 (diff)
parent6f4f2ca7ef5cea652417ba56bc0eb61ec9c792f5 (diff)
downloaddocs-c04429f8b534890ee7a0823c7e56a45655cd6bd3.tar.gz
docs-c04429f8b534890ee7a0823c7e56a45655cd6bd3.tar.bz2
docs-c04429f8b534890ee7a0823c7e56a45655cd6bd3.zip
Merge branch 'master' into feature/tokens
-rw-r--r--checklist-demo-upgrade.rst122
-rw-r--r--checklist-release.rst142
-rw-r--r--checklists/checklist-demo-upgrade.rst173
-rw-r--r--checklists/checklist-release.rst141
-rw-r--r--checklists/qa-0.9.4.rst229
-rwxr-xr-xci/jobs/0-build/build-docs.sh14
-rw-r--r--conf.py34
-rw-r--r--contrib/ci/Containerfile (renamed from ci/Containerfile)0
-rwxr-xr-xcontrib/ci/jobs/0-build/build-docs.sh17
-rwxr-xr-xcontrib/ci/jobs/0-build/job.sh (renamed from ci/jobs/0-build/job.sh)0
-rw-r--r--core/api-auditor.rst243
-rw-r--r--core/api-bank-conversion-info.rst223
-rw-r--r--core/api-bank-integration.rst145
-rw-r--r--core/api-bank-revenue.rst64
-rw-r--r--core/api-bank-wire.rst134
-rw-r--r--core/api-challenger.rst19
-rw-r--r--core/api-common.rst42
-rw-r--r--core/api-corebank.rst1411
-rw-r--r--core/api-donau.rst44
-rw-r--r--core/api-exchange.rst330
-rw-r--r--core/api-mailbox.rst3
-rw-r--r--core/api-merchant.rst695
-rw-r--r--core/api-sync.rst6
-rw-r--r--core/api-taldir.rst2
-rw-r--r--core/index-bank-apis.rst3
-rw-r--r--core/index.rst2
-rw-r--r--core/intro-bank-apis.rst134
-rw-r--r--design-documents/014-merchant-backoffice-ui.rst8
-rw-r--r--design-documents/020-backoffice-rewards-management.rst2
-rw-r--r--design-documents/023-taler-kyc.rst2
-rw-r--r--design-documents/024-age-restriction.rst4
-rw-r--r--design-documents/028-deposit-policies.rst23
-rw-r--r--design-documents/031-invoicing.rst15
-rw-r--r--design-documents/035-regional-currencies.rst15
-rw-r--r--design-documents/036-currency-conversion-service.rst103
-rw-r--r--design-documents/037-wallet-transactions-lifecycle.rst58
-rw-r--r--design-documents/039-taler-browser-integration.rst109
-rw-r--r--design-documents/041-wallet-balance-amount-definitions.rst14
-rw-r--r--design-documents/044-ci-system.rst81
-rw-r--r--design-documents/046-mumimo-contracts.rst15
-rw-r--r--design-documents/048-wallet-exchange-lifecycle.rst28
-rw-r--r--design-documents/050-libeufin-nexus.rst79
-rw-r--r--design-documents/051-fractional-digits.rst94
-rw-r--r--design-documents/052-libeufin-bank-2fa.rst136
-rw-r--r--design-documents/053-wallet-ui.rst355
-rw-r--r--design-documents/054-dynamic-form.rst201
-rw-r--r--design-documents/055-wallet-problem-report.rst85
-rw-r--r--design-documents/index.rst4
-rw-r--r--design-documents/wallet-screenshots/ios-wallet/withdraw-bankIntegrated/CHF/cta-withdraw-sheet130-withdraw-confirm.pngbin0 -> 193455 bytes
-rw-r--r--design-documents/wallet-screenshots/ios-wallet/withdraw-bankIntegrated/CHF/cta-withdraw-sheet130-withdraw.pngbin0 -> 237544 bytes
-rw-r--r--design-documents/wallet-screenshots/ios-wallet/withdraw-bankIntegrated/CHF/cta-withdraw-sheet133-withdraw-confirm-bank.pngbin0 -> 231969 bytes
-rw-r--r--design-documents/wallet-screenshots/ios-wallet/withdraw-bankIntegrated/CHF/cta-withdraw-view22-balances.pngbin0 -> 234937 bytes
-rw-r--r--design-documents/wallet-screenshots/ios-wallet/withdraw-bankIntegrated/cta-withdraw-bank-confirm.pngbin0 -> 357675 bytes
-rw-r--r--design-documents/wallet-screenshots/ios-wallet/withdraw-bankIntegrated/cta-withdraw-bank-confirmed.pngbin0 -> 357108 bytes
-rw-r--r--design-documents/wallet-screenshots/ios-wallet/withdraw-bankIntegrated/cta-withdraw-bank-register.pngbin0 -> 338618 bytes
-rw-r--r--design-documents/wallet-screenshots/ios-wallet/withdraw-bankIntegrated/cta-withdraw-bank-send-money.pngbin0 -> 464966 bytes
-rw-r--r--design-documents/wallet-screenshots/ios-wallet/withdraw-bankIntegrated/cta-withdraw-bank-withdraw.pngbin0 -> 505046 bytes
-rw-r--r--design-documents/wallet-screenshots/ios-wallet/withdraw-bankIntegrated/cta-withdraw-sheet130-withdraw-confirm.pngbin0 -> 202047 bytes
-rw-r--r--design-documents/wallet-screenshots/ios-wallet/withdraw-bankIntegrated/cta-withdraw-sheet130-withdraw.pngbin0 -> 246405 bytes
-rw-r--r--design-documents/wallet-screenshots/ios-wallet/withdraw-bankIntegrated/cta-withdraw-sheet131-tos.pngbin0 -> 317496 bytes
-rw-r--r--design-documents/wallet-screenshots/ios-wallet/withdraw-bankIntegrated/cta-withdraw-sheet133-withdraw-confirm-bank.pngbin0 -> 230382 bytes
-rw-r--r--design-documents/wallet-screenshots/ios-wallet/withdraw-bankIntegrated/cta-withdraw-view10-empty-wallet.pngbin0 -> 169741 bytes
-rw-r--r--design-documents/wallet-screenshots/ios-wallet/withdraw-bankIntegrated/cta-withdraw-view22-balances.pngbin0 -> 239045 bytes
-rw-r--r--design-documents/wallet-screenshots/ios-wallet/withdraw-exchange/cta-withdrawExchange-sheet-amount.pngbin0 -> 173529 bytes
-rw-r--r--design-documents/wallet-screenshots/ios-wallet/withdraw-exchange/cta-withdrawExchange-sheet-wireTransfer-CHF-1.pngbin0 -> 292949 bytes
-rw-r--r--design-documents/wallet-screenshots/ios-wallet/withdraw-exchange/cta-withdrawExchange-sheet-wireTransfer-CHF-2.pngbin0 -> 407510 bytes
-rw-r--r--design-documents/wallet-screenshots/ios-wallet/withdraw-exchange/cta-withdrawExchange-sheet-wireTransfer-CHF-3.pngbin0 -> 331196 bytes
-rw-r--r--design-documents/wallet-screenshots/ios-wallet/withdraw-exchange/cta-withdrawExchange-sheet135-amount.pngbin0 -> 215793 bytes
-rw-r--r--design-documents/wallet-screenshots/ios-wallet/withdraw-exchange/cta-withdrawExchange-sheet135-amount2.pngbin0 -> 214738 bytes
-rw-r--r--design-documents/wallet-screenshots/ios-wallet/withdraw-exchange/cta-withdrawExchange-sheet135-tos.pngbin0 -> 116707 bytes
-rw-r--r--design-documents/wallet-screenshots/ios-wallet/withdraw-exchange/cta-withdrawExchange-sheet135-wireTransfer-CHF.pngbin0 -> 304402 bytes
-rw-r--r--design-documents/wallet-screenshots/ios-wallet/withdraw-exchange/cta-withdrawExchange-sheet135-wireTransfer-CHF2.pngbin0 -> 420238 bytes
-rw-r--r--design-documents/wallet-screenshots/ios-wallet/withdraw-exchange/cta-withdrawExchange-sheet135-wireTransfer-NETZ.pngbin0 -> 309949 bytes
-rw-r--r--design-documents/wallet-screenshots/ios-wallet/withdraw-exchange/cta-withdrawExchange-sheet135-wireTransfer-NETZ2.pngbin0 -> 413992 bytes
-rw-r--r--design-documents/wallet-screenshots/ios-wallet/withdraw-exchange/cta-withdrawExchange-sheet135-withdraw-tos.pngbin0 -> 170387 bytes
-rw-r--r--extract-tsdefs/pnpm-lock.yaml2
-rw-r--r--frags/apt-install-libeufin-bank.rst6
-rw-r--r--frags/apt-install-libeufin-nexus.rst6
-rw-r--r--frags/configuration-format.rst4
-rw-r--r--frags/ebics-setup.rst0
-rw-r--r--frags/installing-debian.rst2
-rw-r--r--frags/libeufin-config-cli.rst51
-rw-r--r--frags/nexus-ebics-setup.rst87
-rw-r--r--frags/regional-manual-architecture.rst48
-rw-r--r--frags/regional-manual-use.rst99
-rw-r--r--frags/using-taler-config.rst8
-rw-r--r--images/Makefile9
-rw-r--r--images/backoffice-reward-create.confirmation.svg2
-rw-r--r--images/backoffice-reward-create.svg2
-rw-r--r--images/challenger.dot26
-rw-r--r--images/regional-arch.dot36
-rw-r--r--images/transaction-reward-states.dot11
-rw-r--r--index.rst15
-rw-r--r--kyc-process.pdfbin0 -> 24633 bytes
-rw-r--r--kyc-process.pngbin0 -> 44435 bytes
-rw-r--r--kyc-process.tex58
-rw-r--r--libeufin/bank-manual.rst307
-rw-r--r--libeufin/bank-transport-ebics.rst55
-rw-r--r--libeufin/banking-protocols.rst127
-rw-r--r--libeufin/circuit-cli-commands.rst152
-rw-r--r--libeufin/concepts.rst166
-rw-r--r--libeufin/ebics.rst598
-rw-r--r--libeufin/ebics3-test-tutorial.rst217
-rw-r--r--libeufin/frontend.rst47
-rw-r--r--libeufin/index.rst39
-rw-r--r--libeufin/int-deployment-gv.rst71
-rw-r--r--libeufin/iso20022.rst214
-rw-r--r--libeufin/local-currencies-tutorial.rst401
-rw-r--r--libeufin/nexus-manual.rst277
-rw-r--r--libeufin/nexus-tutorial.rst956
-rw-r--r--libeufin/performance.rst114
-rw-r--r--libeufin/regional-automated-manual.rst289
-rw-r--r--libeufin/regional-custom-manual.rst164
-rw-r--r--libeufin/sepa.rst26
-rw-r--r--libeufin/setup-ebics-at-postfinance.rst90
-rw-r--r--libeufin/transaction-identification.rst87
-rw-r--r--manpages/challenger-admin.1.rst9
-rw-r--r--manpages/libeufin-bank.1.rst170
-rw-r--r--manpages/libeufin-bank.conf.5.rst122
-rw-r--r--manpages/libeufin-nexus.1.rst170
-rw-r--r--manpages/libeufin-nexus.conf.5.rst187
-rw-r--r--manpages/libeufin-sandbox.1.rst8
-rw-r--r--manpages/taler-config.1.rst1
-rw-r--r--manpages/taler-exchange-offline.1.rst4
-rw-r--r--manpages/taler-mdb.1.rst73
-rw-r--r--manpages/taler-merchant-depositcheck.1.rst78
-rw-r--r--manpages/taler-merchant-exchange.1.rst73
-rw-r--r--manpages/taler-merchant-setup-reserve.1.rst119
-rw-r--r--manpages/taler-merchant-webhook.1.rst6
-rw-r--r--manpages/taler-merchant-wirewatch.1.rst10
-rw-r--r--manpages/taler-terms-generator.1.rst3
-rw-r--r--manpages/taler-unified-setup.1.rst6
-rw-r--r--manpages/taler-wallet-cli.1.rst2
-rw-r--r--manpages/taler.conf.5.rst81
-rw-r--r--orphaned/taler-nfc-guide.rst4
-rw-r--r--screenshots/create_orders.pngbin0 -> 131092 bytes
-rw-r--r--screenshots/cta-accept-tos-firefox-0.pngbin0 -> 105184 bytes
l---------screenshots/cta-accept-tos-firefox-latest.png1
-rw-r--r--screenshots/cta-payment-firefox-0.pngbin0 -> 43899 bytes
l---------screenshots/cta-payment-firefox-latest.png1
-rw-r--r--screenshots/cta-payment-paid-firefox-0.pngbin0 -> 36529 bytes
l---------screenshots/cta-payment-paid-firefox-latest.png1
-rw-r--r--screenshots/cta-url-entry-firefox-0.pngbin0 -> 37619 bytes
l---------screenshots/cta-url-entry-firefox-latest.png1
-rw-r--r--screenshots/cta-wire-transfer-firefox-0.pngbin0 -> 75735 bytes
l---------screenshots/cta-wire-transfer-firefox-latest.png1
-rw-r--r--screenshots/cta-withdraw-done-firefox-0.pngbin0 -> 30061 bytes
l---------screenshots/cta-withdraw-done-firefox-latest.png1
-rw-r--r--screenshots/cta-withdraw-firefox-0.pngbin0 -> 35550 bytes
l---------screenshots/cta-withdraw-firefox-latest.png1
-rw-r--r--screenshots/enter_instance_details.pngbin0 -> 63262 bytes
-rw-r--r--screenshots/instance_iban_config.pngbin0 -> 59170 bytes
-rw-r--r--screenshots/merchant_first_login.pngbin0 -> 201140 bytes
-rw-r--r--screenshots/no_default_account_yet.pngbin0 -> 54464 bytes
-rw-r--r--screenshots/payment_links.pngbin0 -> 227921 bytes
-rw-r--r--taler-auditor-manual.rst53
-rw-r--r--taler-challenger-manual.rst201
-rw-r--r--taler-developer-manual.rst181
-rw-r--r--taler-exchange-manual.rst890
-rw-r--r--taler-merchant-api-tutorial.rst75
-rw-r--r--taler-merchant-manual.rst563
-rw-r--r--taler-merchant-pos-terminal.rst45
-rw-r--r--taler-monitoring-infrastructure.rst197
-rw-r--r--taler-user-guide.rst194
-rw-r--r--taler-wallet.rst67
-rw-r--r--wallet/wallet-core.md619
166 files changed, 8153 insertions, 6737 deletions
diff --git a/checklist-demo-upgrade.rst b/checklist-demo-upgrade.rst
deleted file mode 100644
index 13a65319..00000000
--- a/checklist-demo-upgrade.rst
+++ /dev/null
@@ -1,122 +0,0 @@
-################################
-GNU Taler Demo Upgrade Checklist
-################################
-
-.. |check| raw:: html
-
- <input type="checkbox">
-
-Domains
--------
-
-The checklist uses the ``demo.taler.net`` domains. However,
-the same sandcastle demo can also be hosted at other domains.
-The same instructions should apply.
-
-Post-upgrade checks
--------------------
-
-- |check| Run the headless wallet to check that services are actually working:
-
- .. code-block:: console
-
- taler-wallet-cli api 'runIntegrationTestV2' '{"exchangeBaseUrl":"https://exchange.demo.taler.net", "corebankApiBaseUrl": "https://bank.demo.taler.net", "merchantBaseUrl": "https://backend.demo.taler.net", "merchantAuthToken":"secret-token:sandbox"}'
-
-
-Wallets
--------
-
-We consider the following published wallets to be "production wallets":
-
-* Browser: Firefox Add-On Store
-* Browser: Chrome Web Store
-* Android: Google Play
-* Android: F-Droid
-
-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
-- |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/
-- |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
- requested.
-- |check| Open the fulfillment page from the previous step in an anonymous browsing session
- (without the wallet installed) and verify that it requests a payment again.
-- |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| 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: rewards
-- |check| TBD: products with previews
-- |check| TBD: inventory management
-- |check| TBD: adding transactions
-- |check| TBD: test various settings
-- |check| TBD: ...
-
-Survey/Rewards
---------------
-
-- |check| Visit https://survey.demo.taler.net/ and receive a reward.
-- |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
deleted file mode 100644
index a9008729..00000000
--- a/checklist-release.rst
+++ /dev/null
@@ -1,142 +0,0 @@
-############################
-GNU Taler Release Checklists
-############################
-
-.. |check| raw:: html
-
- <input type="checkbox">
-
-For exchange:
-
-- |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" 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 Python merchant frontend:
-
-- |check| upgrade 'demo.taler.net'
-- |check| run :doc:`demo upgrade checklist <checklist-demo-upgrade>`
-- |check| change 'demo.taler.net' deployment to use new tag.
-
-Wallet-core:
-
-- |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
-
-Android-Wallet:
-
-- |check| build wallet
-- |check| run :doc:`demo upgrade checklist <checklist-demo-upgrade>`
-- |check| tag repo.
-- |check| upload new wallet release to app store
-
-Webextension-Wallet:
-
-- |check| build wallet
-- |check| run :doc:`demo upgrade checklist <checklist-demo-upgrade>`
-- |check| tag repo.
-- |check| upload new wallet release to app store
-
-Release announcement:
-
-- |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/checklists/checklist-demo-upgrade.rst b/checklists/checklist-demo-upgrade.rst
new file mode 100644
index 00000000..d8724030
--- /dev/null
+++ b/checklists/checklist-demo-upgrade.rst
@@ -0,0 +1,173 @@
+GNU Taler Demo Upgrade Checklist
+--------------------------------
+
+.. |democheck| raw:: html
+
+ <input type="checkbox">
+
+
+Domains
+^^^^^^^
+
+The checklist uses the ``demo.taler.net`` domains. However,
+the same sandcastle demo can also be hosted at other domains.
+The same instructions should apply.
+
+Post-upgrade checks
+^^^^^^^^^^^^^^^^^^^
+
+- |democheck| Run the headless wallet to check that services are actually working:
+
+ .. code-block:: console
+
+ taler-wallet-cli api 'runIntegrationTestV2' '{"exchangeBaseUrl":"https://exchange.demo.taler.net", "corebankApiBaseUrl": "https://bank.demo.taler.net", "merchantBaseUrl": "https://backend.demo.taler.net", "merchantAuthToken":"secret-token:sandbox"}'
+
+
+Wallets
+^^^^^^^
+
+We consider the following published wallets to be "production wallets":
+
+* Browser: Firefox Add-On Store
+* Browser: Chrome Web Store
+* Android: Google Play
+* Android: F-Droid
+* iOS: Apple Store / Testflight
+
+Basics
+^^^^^^
+
+- |democheck| Visit https://demo.taler.net/ to see if the landing page is displayed correctly
+- |democheck| landing language switcher
+- |democheck| Visit the wallet installation page, install the wallet
+- |democheck| see if the wallet presence indicator is updated correctly (in browsers).
+- |democheck| Visit https://bank.demo.taler.net/, register a new user
+- |democheck| bank language switcher
+- |democheck| bank logout
+- |democheck| bank login
+- |democheck| bank-integrated withdraw process, abort in bank
+- |democheck| transaction history: delete pending withdraw
+- |democheck| do bank-integrated withdraw process (5 KUDOS)
+- |democheck| do wallet-initiated withdraw process (5 KUDOS)
+- |democheck| withdraw process of large amount (20 KUDOS) runs into KYC check
+- |democheck| fail KYC check (if possible for the given setup)
+- |democheck| pass KYC check (tests that 2nd attempt is possible)
+- |democheck| withdraw process of very large amount (50 KUDOS) runs into AML check
+- |democheck| visit exchange SPA, create AML officer key
+- |democheck| register AML officer key with offline tool (if possible)
+- |democheck| allow withdraw process blocked on AML to proceed (if possible)
+
+
+Exchange AML SPA
+^^^^^^^^^^^^^^^^
+
+- |democheck| enter non-trivial form, change status to frozen
+- |democheck| check account status in history is now frozen and shows in that category
+- |democheck| enter another form, change status to normal, increase AML threshold
+- |democheck| view forms in history, view previously submitted form
+- |democheck| check account status in history is now normal and shows in that category
+- |democheck| log out
+- |democheck| check log in succeeds with correct password
+- |democheck| check log in fails from different browser with same password
+
+
+Blog demo
+^^^^^^^^^
+
+- |democheck| Visit https://shop.demo.taler.net/
+- |democheck| blog page article list renders
+- |democheck| payment for blog article
+- |democheck| Verify that the balance in the wallet was updated correctly.
+- |democheck| 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
+ requested.
+- |democheck| Open the fulfillment page from the previous step in an anonymous browsing session
+ (without the wallet installed) and verify that it requests a payment again.
+- |democheck| 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.
+- |democheck| payment for other blog article
+- |democheck| refund of 2nd blog article (button at the end)
+- |democheck| wallet transaction history rendering
+- |democheck| delete refund history entry; check original purchase entry was also deleted
+- |democheck| payment for other blog article
+- |democheck| refund of 3rd blog article (button at the end)
+- |democheck| wallet transaction history rendering
+- |democheck| delete 3rd block purchase history entry; check refund entry was also deleted
+
+
+Donation demo
+^^^^^^^^^^^^^
+
+- |democheck| Reset wallet
+- |democheck| Withdraw age-restricted coins (< 14)
+- |democheck| Try to make a donation on https://donations.demo.taler.net/, fail due to age-restriction
+- |democheck| Withdraw age-restricted coins (>= 14)
+- |democheck| Make a donation on https://donations.demo.taler.net/
+- |democheck| Make another donation with the same parameters and verify
+ that the payment is requested again, instead of showing the previous
+ fulfillment page.
+
+
+Merchant SPA
+^^^^^^^^^^^^
+
+- |democheck| test SPA loads
+- |democheck| try to login with wrong password
+- |democheck| try to login with correct password
+- |democheck| create instance, check default is set to cover (STEFAN) fees
+- |democheck| modify instance
+- |democheck| add bank account
+- |democheck| edit bank account
+- |democheck| remove bank account
+- |democheck| check order creation fails without bank account
+- |democheck| add bank account again
+- |democheck| add product with 1 in stock and preview image
+- |democheck| add "advanced" order with inventory product and a 2 minute wire delay
+- |democheck| claim order, check available stock goes down in inventory
+- |democheck| create 2nd order, check this fails due to missing inventory
+- |democheck| pay for 1st order with wallet
+- |democheck| check transaction history for preview image
+- |democheck| trigger partial refund
+- |democheck| accept refund with wallet
+- |democheck| create template with fixed summary, default editable price
+- |democheck| scan template QR code, edit price and pay
+- |democheck| add TOTP device (using some TOTP app to share secret with)
+- |democheck| edit template to add TOTP device, set price to fixed, summary to be entered
+- |democheck| scan template QR code, edit summary and pay
+- |democheck| check displayed TOTP code matches TOTP app
+- |democheck| do manual wire transfer in bank to establish reserve funding
+- |democheck| check that partially refunded order is marked as awaiting wire transfer
+- |democheck| check bank wired funds to merchant (if needed, wait)
+- |democheck| add bank wire transfer manually to backend
+- |democheck| change settings for merchant to not pay for (STEFAN) fees
+- |democheck| create and pay for another order with 1 minute wire transfer delay
+- |democheck| edit bank account details, adding revenue facade with credentials
+- |democheck| wait and check if wire transfer is automatically imported
+- |democheck| check that orders are marked as completed
+
+
+P2P payments
+^^^^^^^^^^^^
+
+- |democheck| generating push payment (to self is OK)
+- |democheck| accepting push payment (from self is OK)
+- |democheck| generating pull payment (to self is OK)
+- |democheck| accepting pull payment (from self is OK)
+- |democheck| sending money back from wallet to bank account
+- |democheck| wallet transaction history rendering
+- |democheck| delete history entry
+
+
+Shutdown
+^^^^^^^^
+
+- |democheck| create two full wallets, fill one only via (a large) P2P transfer
+- |democheck| revoke highest-value denomination
+- |democheck| spend money in a wallet such that the balance falls below highest denomination value
+- |democheck| revoke all remaining denominations
+- |democheck| fail to spend any more money
+- |democheck| if wallet was filled via p2p payments, wallet asks for target deposit account (exchange going out of business)
+- |democheck| enter bank account (if possible)
+- |democheck| wallet balance goes to zero
+- |democheck| specified bank account receives remaining balance
diff --git a/checklists/checklist-release.rst b/checklists/checklist-release.rst
new file mode 100644
index 00000000..eaefd0b9
--- /dev/null
+++ b/checklists/checklist-release.rst
@@ -0,0 +1,141 @@
+GNU Taler Release Checklist
+---------------------------
+
+.. |releasecheck| raw:: html
+
+ <input type="checkbox">
+
+For exchange:
+
+- |releasecheck| no compiler warnings at "-Wall" with gcc
+- |releasecheck| no compiler warnings at "-Wall" with clang
+- |releasecheck| ensure Coverity static analysis passes
+- |releasecheck| make check.
+- |releasecheck| make dist, make check on result of 'make dist'.
+- |releasecheck| Change version number in configure.ac.
+- |releasecheck| update man pages / info page documentation (prebuilt branch)
+- |releasecheck| make dist for release
+- |releasecheck| verify dist builds from source
+- |releasecheck| upgrade 'demo.taler.net'
+- |releasecheck| run :doc:`demo upgrade checklist </checklists/checklist-demo-upgrade>`
+- |releasecheck| tag repo.
+- |releasecheck| use 'deployment.git/packaging/\*-docker/' to build Debian and Ubuntu packages
+- |releasecheck| upload packages to 'deb.taler.net' (note: only Florian/Christian can sign)
+- |releasecheck| change 'demo.taler.net' deployment to use new tag.
+- |releasecheck| Upload triplet to ftp-upload.gnu.org/incoming/ftp or /incoming/alpha
+
+For merchant (C backend):
+
+- |releasecheck| no compiler warnings at "-Wall" with gcc
+- |releasecheck| no compiler warnings at "-Wall" with clang
+- |releasecheck| ensure Coverity static analysis passes
+- |releasecheck| make check.
+- |releasecheck| make dist, make check on result of 'make dist'.
+- |releasecheck| update SPA (prebuilt branch)
+- |releasecheck| Change version number in configure.ac.
+- |releasecheck| make dist for release.
+- |releasecheck| verify dist builds from source
+- |releasecheck| upgrade 'demo.taler.net'
+- |releasecheck| run :doc:`demo upgrade checklist </checklists/checklist-demo-upgrade>`
+- |releasecheck| tag repo.
+- |releasecheck| use 'deployment.git/packaging/\*-docker/' to build Debian and Ubuntu packages
+- |releasecheck| upload packages to 'deb.taler.net' (note: only Florian/Christian can sign)
+- |releasecheck| change 'demo.taler.net' deployment to use new tag.
+- |releasecheck| Upload triplet to ftp-upload.gnu.org/incoming/ftp or /incoming/alpha
+
+For sync:
+
+- |releasecheck| no compiler warnings at "-Wall" with gcc
+- |releasecheck| no compiler warnings at "-Wall" with clang
+- |releasecheck| ensure Coverity static analysis passes
+- |releasecheck| make check.
+- |releasecheck| make dist, make check on result of 'make dist'.
+- |releasecheck| Change version number in configure.ac.
+- |releasecheck| make dist for release
+- |releasecheck| verify dist builds from source
+- |releasecheck| upgrade 'demo.taler.net'
+- |releasecheck| run :doc:`demo upgrade checklist </checklists/checklist-demo-upgrade>`
+- |releasecheck| tag repo.
+- |releasecheck| use 'deployment.git/packaging/\*-docker/' to build Debian and Ubuntu packages
+- |releasecheck| upload packages to 'deb.taler.net' (note: only Florian/Christian can sign)
+- |releasecheck| change 'demo.taler.net' deployment to use new tag.
+- |releasecheck| Upload triplet to ftp-upload.gnu.org/incoming/ftp or /incoming/alpha
+
+For taler-mdb:
+
+- |releasecheck| no compiler warnings at "-Wall" with gcc
+- |releasecheck| ensure Coverity static analysis passes
+- |releasecheck| Change version number in configure.ac.
+- |releasecheck| make dist for release.
+- |releasecheck| tag repo.
+- |releasecheck| use 'deployment.git/packaging/\*-docker/' to build Debian and Ubuntu packages
+- |releasecheck| upload packages to 'deb.taler.net' (note: only Florian/Christian can sign)
+- |releasecheck| Upload triplet to ftp-upload.gnu.org/incoming/ftp or /incoming/alpha
+
+For taler-twister:
+
+- |releasecheck| no compiler warnings at "-Wall" with gcc
+- |releasecheck| no compiler warnings at "-Wall" with clang
+- |releasecheck| ensure Coverity static analysis passes
+- |releasecheck| make check.
+- |releasecheck| make dist, make check on result of 'make dist'.
+- |releasecheck| Change version number in configure.ac.
+- |releasecheck| make dist for release.
+- |releasecheck| verify dist builds from source
+- |releasecheck| upgrade 'demo.taler.net'
+- |releasecheck| run :doc:`demo upgrade checklist </checklists/checklist-demo-upgrade>`
+- |releasecheck| tag repo.
+- |releasecheck| Upload triplet to ftp-upload.gnu.org/incoming/ftp or /incoming/alpha
+
+For libeufin:
+
+- |releasecheck| update SPA of bank
+- |releasecheck| build libeufin
+- |releasecheck| upgrade 'demo.taler.net'
+- |releasecheck| run :doc:`demo upgrade checklist </checklists/checklist-demo-upgrade>`
+- |releasecheck| make dist for release.
+- |releasecheck| verify dist builds from source
+- |releasecheck| tag repo.
+- |releasecheck| use 'deployment.git/packaging/\*-docker/' to build Debian and Ubuntu packages
+- |releasecheck| upload packages to 'deb.taler.net' (note: only Florian/Christian can sign)
+- |releasecheck| change 'demo.taler.net' deployment to use new tag.
+- |releasecheck| Upload triplet to ftp-upload.gnu.org/incoming/ftp or /incoming/alpha
+
+For Python merchant frontend:
+
+- |releasecheck| upgrade 'demo.taler.net'
+- |releasecheck| run :doc:`demo upgrade checklist </checklists/checklist-demo-upgrade>`
+- |releasecheck| change 'demo.taler.net' deployment to use new tag.
+
+Wallet-core:
+
+- |releasecheck| build wallet
+- |releasecheck| run integration test
+- |releasecheck| make dist for release.
+- |releasecheck| verify dist builds from source
+- |releasecheck| tag repo.
+- |releasecheck| use 'deployment.git/packaging/\*-docker/' to build Debian and Ubuntu packages
+- |releasecheck| upload packages to 'deb.taler.net' (note: only Florian/Christian can sign)
+- |releasecheck| change 'demo.taler.net' deployment to use new tag.
+- |releasecheck| Upload triplet to ftp-upload.gnu.org/incoming/ftp or /incoming/alpha
+
+Android-Wallet:
+
+- |releasecheck| build wallet
+- |releasecheck| run :doc:`demo upgrade checklist </checklists/checklist-demo-upgrade>`
+- |releasecheck| tag repo.
+- |releasecheck| upload new wallet release to app store
+
+Webextension-Wallet:
+
+- |releasecheck| build wallet
+- |releasecheck| run :doc:`demo upgrade checklist </checklists/checklist-demo-upgrade>`
+- |releasecheck| tag repo.
+- |releasecheck| upload new wallet release to app store
+
+Release announcement:
+
+- |releasecheck| Update bug tracker (mark release, resolved -> closed)
+- |releasecheck| Send announcement to taler@gnu.org
+- |releasecheck| Send announcement to info-gnu@gnu.org (major releases only)
+- |releasecheck| Send announcement to coordinator@translationproject.org
diff --git a/checklists/qa-0.9.4.rst b/checklists/qa-0.9.4.rst
new file mode 100644
index 00000000..98680c8d
--- /dev/null
+++ b/checklists/qa-0.9.4.rst
@@ -0,0 +1,229 @@
+===================
+Taler 0.9.4 QA Plan
+===================
+
+Wallet Platforms
+================
+
+Platforms listed here are the officially supported platforms for this release.
+
+* Overview / Installation Page
+
+ * https://taler.net/en/wallet.html
+
+* Android
+
+ * Google Play: https://play.google.com/store/apps/details?id=net.taler.wallet
+ * F-Droid: https://f-droid.org/en/packages/net.taler.wallet.fdroid/
+ * APK Download: TBD
+
+* Browser
+
+ * Chrome: https://chromewebstore.google.com/detail/gnu-taler-wallet/millncjiddlpgdmkklmhfadpacifaonc
+ * Firefox: https://addons.mozilla.org/en-US/firefox/addon/taler-wallet/
+
+* iOS
+
+
+Running Deployments
+===================
+
+These deployments are maintained by us and should work for the release:
+
+* Sandcastle-based:
+
+ * demo.taler.net
+
+ * test.taler.net
+
+* Regio-based:
+
+ * regio-taler.fdold.eu
+
+
+Wallet Flows
+============
+
+* Bank-integrated withdrawal
+
+ * webext: "Continue with Mobile Wallet" flow
+
+* Manual withdrawal
+
+ * ``taler://withdraw-exchange`` flow
+
+ * Currency conversion withdrawal
+
+* Peer push payments ("Send Money")
+
+* Peer pull payments ("Receive Money")
+
+* Deposit into bank account
+
+ * Check that deposit arrived
+
+* Payment at merchant
+
+ * on blog merchant
+ * on survey
+ * directly initiated via merchant SPA
+ * webext: "Pay with Mobile Wallet" flow
+
+* Pay templates
+
+ * Payment TOTP codes
+
+* Exchange management
+
+ * Reloading exchange keys
+ * Deleting an exchange
+
+
+libeufin-bank Flows
+===================
+
+* Admin functionality
+
+ * Login
+
+ * Credential change
+
+ * Conversion settings
+
+ * Bank account creation
+
+ * Test transfers
+
+* Normal account functionality
+
+ * Transfers
+
+ * Transfer to the exchange should bounce
+
+ * Withdrawals
+
+ * (conversion-only): Test cash-in
+
+ * (conversion-only): Test cash-out
+
+ * Lower cash-out limit enforced
+
+ * 2FA for withdrawals, cash-out
+
+
+Merchant Backend SPA Flows
+==========================
+
+* Instance creation
+
+* Simple bank account setup
+
+* Order creation
+
+ * Pay order (with short wire transfer deadline)
+
+ * Check that money from order arrive at the bank with the right subject
+
+* Extended bank account setup
+
+ * Add Taler Bank Revenue API
+
+ * Check bank transfer list (for wire transfer of previously paid+wired order)
+
+ * Check order payment status goes to "final" automatically
+
+* TOTP Device Management
+
+ * Add device
+
+ * Edit device (set new secret, export new secret as QR code)
+
+ * Delete device
+
+* Templates
+
+ * Add template
+
+ * Edit template
+
+ * Add TOTP device to template
+
+ * Edit TOTP device associated with template
+
+ * Pay template
+
+ * Check TOTP code matches
+
+ * Remove TOTP device from template
+
+ * Delete template
+
+
+
+Regio Deployment
+================
+
+* Deployment Automation (deployment.git/regional-currency)
+
+ * Test with Debian bookworm
+
+ * Test with Ubuntu mantic
+
+ * Check logs for errors
+
+ * Test with telesign (SMS)
+
+ * Set up EBICS integration
+
+ * Check that ToS is configured
+
+* Deployment Functionality
+
+ * All flows of the wallet should work (see ``Wallet Flows`` above)
+
+ * All flows of libeufin-bank should work (see ``libeufin-bank Flows`` above)
+
+ * Merchant backend should work (see ``Merchant Backend SPA Flows`` above)
+
+ * Check logs
+
+
+Android Merchant PoS
+====================
+
+* Test against demo.taler.net
+
+
+Android Cashier App
+===================
+
+* Test against demo.taler.net
+
+
+CI
+==
+
+* https://buildbot.taler.net/#/waterfall
+* CI should pass
+
+
+Debian Repository
+=================
+
+* Debian
+
+ * repo at https://deb.taler.net/apt/debian/
+ * supported codename(s): bookworm
+
+
+* Ubuntu:
+
+ * repo at https://deb.taler.net/apt/ubuntu/
+ * supported codename(s): mantic
+
+
+GNU Release
+===========
+
+* Release announcement
+* FTP upload
diff --git a/ci/jobs/0-build/build-docs.sh b/ci/jobs/0-build/build-docs.sh
deleted file mode 100755
index 6accee36..00000000
--- a/ci/jobs/0-build/build-docs.sh
+++ /dev/null
@@ -1,14 +0,0 @@
-#!/bin/bash
-
-set -eu
-
-make html
-make latexpdf
-
-rm -rf /artifacts/docs_build
-
-mkdir -p /artifacts/docs_build/docs/html/
-mkdir -p /artifacts/docs_build/docs/pdf/
-
-cp -r _build/html/* /artifacts/docs_build/docs/html/
-cp -r _build/latex/*.pdf /artifacts/docs_build/docs/pdf/
diff --git a/conf.py b/conf.py
index f6897355..9e16a795 100644
--- a/conf.py
+++ b/conf.py
@@ -428,6 +428,13 @@ man_pages = [
1,
),
(
+ "manpages/taler-fakebank-run.1",
+ "taler-fakebank-run",
+ "run in-memory bank service for testing and benchmarking",
+ "GNU Taler contributors",
+ 1,
+ ),
+ (
"manpages/taler-exchange-closer.1",
"taler-exchange-closer",
"close idle reserves",
@@ -568,6 +575,13 @@ man_pages = [
1,
),
(
+ "manpages/taler-merchant-exchange.1",
+ "taler-merchant-exchange",
+ "ask exchange which deposits were aggregated for a particular wire transfer that credited a merchant account",
+ "GNU Taler contributors",
+ 1,
+ ),
+ (
"manpages/taler-merchant-benchmark.1",
"taler-merchant-benchmark",
"generate Taler-style benchmarking payments",
@@ -575,6 +589,13 @@ man_pages = [
1,
),
(
+ "manpages/taler-mdb.1",
+ "taler-mdb",
+ "operate multi drop bus (MDB) based vending machines with Taler payments",
+ "GNU Taler contributors",
+ 1,
+ ),
+ (
"manpages/taler-merchant-dbinit.1",
"taler-merchant-dbinit",
"initialize Taler merchant database",
@@ -610,9 +631,9 @@ man_pages = [
1,
),
(
- "manpages/taler-merchant-setup-reserve.1",
- "taler-merchant-setup-reserve",
- "setup reserve for rewards at a Taler merchant backend",
+ "manpages/taler-merchant-depositcheck.1",
+ "taler-merchant-depositcheck",
+ "check status of deposits with exchange",
"GNU Taler contributors",
1,
),
@@ -721,6 +742,13 @@ man_pages = [
"GNU Taler contributors",
1,
),
+ (
+ "manpages/libeufin-nexus.conf.5",
+ "libeufin-nexus.conf",
+ "LibEuFin Nexus configuration file",
+ "GNU Taler contributors",
+ 5,
+ ),
]
# If true, show URL addresses after external links.
diff --git a/ci/Containerfile b/contrib/ci/Containerfile
index 023d02de..023d02de 100644
--- a/ci/Containerfile
+++ b/contrib/ci/Containerfile
diff --git a/contrib/ci/jobs/0-build/build-docs.sh b/contrib/ci/jobs/0-build/build-docs.sh
new file mode 100755
index 00000000..43152df9
--- /dev/null
+++ b/contrib/ci/jobs/0-build/build-docs.sh
@@ -0,0 +1,17 @@
+#!/bin/bash
+
+set -exou
+
+make html
+make latexpdf
+
+# Publish to docs.taler.net if on master branch
+if [[ ${CI_GIT_BRANCH} = "master" ]]; then
+ rm -rf /artifacts/docs_build
+
+ mkdir -p /artifacts/docs_build/docs/html/
+ mkdir -p /artifacts/docs_build/docs/pdf/
+
+ cp -r _build/html/* /artifacts/docs_build/docs/html/
+ cp -r _build/latex/*.pdf /artifacts/docs_build/docs/pdf/
+fi
diff --git a/ci/jobs/0-build/job.sh b/contrib/ci/jobs/0-build/job.sh
index 627aecf0..627aecf0 100755
--- a/ci/jobs/0-build/job.sh
+++ b/contrib/ci/jobs/0-build/job.sh
diff --git a/core/api-auditor.rst b/core/api-auditor.rst
index 38c1c142..61e448b8 100644
--- a/core/api-auditor.rst
+++ b/core/api-auditor.rst
@@ -25,6 +25,23 @@ The `glossary <https://docs.taler.net/glossary.html#glossary>`_
defines all specific terms used in this section.
.. contents:: Table of Contents
+ :local:
+
+.. _authentication:
+
+--------------
+Authentication
+--------------
+
+Each auditor instance has separate authentication settings for the private API resources
+of that instance.
+
+Currently, the API supports two main authentication methods:
+
+* ``external``: With this method, no checks are done by the auditor backend.
+ Instead, a reverse proxy / API gateway must do all authentication/authorization checks.
+* ``token``: With this method, the client must provide a ``Authorization: Bearer $TOKEN``
+ header, where ``$TOKEN`` is a secret authentication token configured for the instance which must begin with the RFC 8959 prefix.
.. _auditor-version:
@@ -39,6 +56,7 @@ know-your-customer (KYC) registration before issuing contracts.
.. http:get:: /config
Get the protocol version and some meta data about the auditor.
+ This specification corresponds to ``current`` protocol being version **1**.
**Response:**
@@ -58,11 +76,19 @@ know-your-customer (KYC) registration before issuing contracts.
// protocol is versioned independently of the exchange's protocol.
version: string;
+ // URN of the implementation (needed to interpret 'revision' in version).
+ // @since v0, may become mandatory in the future.
+ implementation?: string;
+
// Return which currency this auditor is auditing for.
currency: string;
// EdDSA master public key of the auditor.
auditor_public_key: EddsaPublicKey;
+
+ // EdDSA master public key of the exchange.
+ // Added in protocol v1.
+ exchange_master_public_key: EddsaPublicKey;
}
.. note::
@@ -71,58 +97,63 @@ know-your-customer (KYC) registration before issuing contracts.
time of this writing).
-.. _exchange-list:
+.. _exchange_signkeys-list:
------------------------
-Obtaining Exchange List
------------------------
+------------------------------------
+Obtaining Exchange Signing Keys List
+------------------------------------
-This API is used by merchants to obtain a list of all exchanges audited by
-this auditor. This may be required for the merchant to perform the required
-know-your-customer (KYC) registration before issuing contracts.
+This API is used by auditor to obtain a list of all exchanges signing keys to be audited.
-.. http:get:: /exchanges
+.. http:get:: /exchange-sign-keys
- Get a list of all exchanges audited by the auditor.
+ Get a list of all exchange signing keys to be audited by the auditor.
**Response:**
:http:statuscode:`200 OK`:
- The auditor responds with a :ts:type:`ExchangeList` object. This request should
+ The auditor responds with a :ts:type:`ExchangeSignKeysList` object. This request should
virtually always be successful.
**Details:**
- .. ts:def:: ExchangeList
+ .. ts:def:: ExchangeSignKeysList
- interface ExchangeList {
- // Exchanges audited by this auditor.
- exchanges: ExchangeEntry[];
+ interface ExchangeSignKeysList {
+ // Exchange signing keys to be audited by the auditor.
+ exchange-sign-key: ExchangeSignKeyEntry[];
}
- .. ts:def:: ExchangeEntry
+ .. ts:def:: ExchangeSignKeyEntry
- interface ExchangeEntry {
+ interface ExchangeSignKeyEntry {
- // Master public key of the exchange.
- master_pub: EddsaPublicKey;
+ // Public online signing key of the exchange.
+ exchange_pub: EddsaPublicKey;
// Base URL of the exchange.
- exchange_url: string;
+ master_sig: EddsaSignature;
+
+ // Time when online signing key will first be use.
+ ep_valid_from: Timestamp;
+
+ // Time when this online signing key will no longer be used.
+ ep_expire_sign: Timestamp;
+
+ // Time when this online signing key legally expires.
+ ep_expire_legal: Timestamp;
}
.. note::
This API is still experimental (and is not yet implemented at the
- time of this writing). A key open question is whether the auditor
- should sign the information. We might also want to support more
- delta downloads in the future.
+ time of this writing).
.. _deposit-confirmation:
---------------------------------
-Submitting deposit confirmations
---------------------------------
+---------------------
+Deposit Confirmations
+---------------------
Merchants should probabilistically submit some of the deposit
confirmations they receive from the exchange to auditors to ensure
@@ -204,6 +235,7 @@ paid out first.
// Master public key of the exchange corresponding to ``master_sig``.
// Identifies the exchange this is about.
+ // @deprecated since v1 (now ignored, global per auditor)
master_pub: EddsaPublicKey;
// When does the validity of the exchange_pub end?
@@ -225,6 +257,167 @@ paid out first.
time of this writing). A key open question is whether the auditor
should sign the response information.
+This API is used by the auditor to obtain a list of all deposit confirmations that the auditor
+did not receive by the exchange, only by the merchant.
+
+.. http:get:: /deposit-confirmation
+
+ Get a list of all deposit confirmations that were not received by the auditor from the exchange to be manually audited.
+
+ **Response:**
+
+ :http:statuscode:`200 OK`:
+ The auditor responds with a :ts:type:`DepositConfirmationList` object.
+ :http:statuscode:`204 No Content`:
+ No missing deposit confirmations found.
+
+ **Details:**
+
+ .. ts:def:: DepositConfirmationList
+
+ interface DepositConfirmationList {
+ // Deposit confirmations to be audited.
+ deposit-confirmations: DepositConfirmation[];
+ }
+
+ .. ts:def:: DepositConfirmation
+
+ interface DepositConfirmation {
+
+ // Database row id of entry
+ row_id: Integer;
+
+ // Time when the deposit confirmation confirmation was generated.
+ timestamp: Timestamp;
+
+ // How much time does the merchant have to issue a refund
+ // request? Zero if refunds are not allowed.
+ refund_deadline: Timestamp;
+
+ // By what time does the exchange have to wire the funds?
+ wire_deadline: Timestamp;
+
+ // Amount to be deposited, excluding fee. Calculated from the
+ // amount with fee and the fee from the deposit request.
+ amount_without_fee: Amount;
+ }
+
+ .. note::
+
+ This API is still experimental (and is not yet implemented at the
+ time of this writing).
+
+This API is used by the auditor to delete an audited deposit confirmation.
+
+.. http:delete:: /deposit-confirmation/$SERIAL_ID
+
+ Delete deposit confirmation entry with given serial_id.
+
+ **Response:**
+
+ :http:statuscode:`204 No content`:
+ The deposit confirmation was deleted.
+
+ :http:statuscode:`401 Unauthorized`:
+ Unauthorized request.
+
+ :http:statuscode:`404 Not found`:
+ The deposit confirmation was unknown.
+
+ .. note::
+
+ This API is still experimental (and is not yet implemented at the
+ time of this writing).
+
+.. balances-list:
+
+----------------------------------
+Obtaining list of auditor balances
+----------------------------------
+
+This API is used to obtain a list of all the balances that are stored by the auditor.
+
+.. http:get:: /balances
+
+ Get a list of all balances stored by the auditor.
+
+ **Response:**
+
+ :http:statuscode:`200 OK`:
+ The auditor responds with a :ts:type:`BalanceList` object.
+
+ :http:statuscode:`409 Conflict`:
+ Balance missing or other error occured.
+
+ **Details:**
+
+ .. ts:def:: BalanceList
+
+ interface BalanceList {
+ // Total amount reported
+ auditor_total_reported_balance: Amount;
+
+ // Amount potentially missing
+ auditor_missing_balance: Amount;
+
+ //...
+ }
+
+ .. note::
+
+ This API is still experimental (and is not yet implemented at the
+ time of this writing). The API will be further developed as needed.
+
+.. denominations-pending-list:
+
+---------------------------------------
+Obtaining list of pending denominations
+---------------------------------------
+
+This API is used by the auditor to obtain a list of pending denominations
+
+.. http:get:: /pending-denominations
+
+ Get a list of all pending denominations.
+
+ **Response:**
+
+ :http:statuscode:`200 OK`:
+ The auditor responds with a :ts:type:`PendingDenominationList` object.
+
+ :http:statuscode:`204 No content`:
+ No pending demoninations found.
+
+ **Details:**
+
+ .. ts:def:: PendingDenominationList
+
+ interface PendingDenominationList {
+ // PendingDenominationList of the auditor.
+ pending_denomination: PendingDenomination[];
+ }
+
+ .. ts:def:: PendingDenomination
+
+ interface PendingDenomination {
+
+ // Balance of denomination.
+ denom_balance: Amount;
+
+ // Amount that was lost due to failures by the exchange.
+ denom_loss: Amount;
+
+ // Amount at risk of loss due to recoup operations.
+ denom_risk: Amount;
+
+ // Amount actually lost due to recoup operations after a revocation.
+ recoup_loss: Amount;
+ }
+
+ .. note::
+
+ This API is still experimental (and is not yet implemented at the
+ time of this writing).
----------
Complaints
diff --git a/core/api-bank-conversion-info.rst b/core/api-bank-conversion-info.rst
new file mode 100644
index 00000000..322e9403
--- /dev/null
+++ b/core/api-bank-conversion-info.rst
@@ -0,0 +1,223 @@
+..
+ This file is part of GNU TALER.
+
+ Copyright (C) 2014-2023 Taler Systems SA
+
+ TALER is free software; you can redistribute it and/or modify it under the
+ terms of the GNU Affero General Public License as published by the Free Software
+ Foundation; either version 2.1, or (at your option) any later version.
+
+ TALER is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License along with
+ TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
+
+ @author Marcello Stanisci
+ @author Christian Grothoff
+ @author Florian Dold
+
+=========================
+Taler Conversion Info API
+=========================
+
+This chapter describes the conversion info API. The conversion info API
+is used by wallets for withdrawals that involve a currency conversion.
+
+
+.. contents:: Table of Contents
+
+.. http:get:: /config
+
+ Get configuration information about the bank.
+
+ **Response:**
+
+ :http:statuscode:`200 OK`:
+ Response is a `ConversionConfig`.
+ :http:statuscode:`501 Not implemented`:
+ This server does not support conversion, client should check config response.
+
+ **Details:**
+
+ .. ts:def:: ConversionConfig
+
+ interface ConversionConfig {
+ // libtool-style representation of the Bank protocol version, see
+ // https://www.gnu.org/software/libtool/manual/html_node/Versioning.html#Versioning
+ // The format is "current:revision:age".
+ version: string;
+
+ // Name of the API.
+ name: "taler-conversion-info";
+
+ // URN of the implementation (needed to interpret 'revision' in version).
+ // @since v4, may become mandatory in the future.
+ implementation?: string;
+
+ // Currency used by this bank.
+ regional_currency: string;
+
+ // How the bank SPA should render this currency.
+ regional_currency_specification: CurrencySpecification;
+
+ // External currency used during conversion.
+ fiat_currency: string;
+
+ // How the bank SPA should render this currency.
+ fiat_currency_specification: CurrencySpecification;
+
+ // Additional information on conversion rates.
+ // Those informations should never be used to perform conversions,
+ // use /cashin-rate or /cashout-rate instead.
+ // Conversion rates can change at any time. Clients must deal with
+ // any resulting errors and call /cashin-rate or /cashout-rate again
+ // to use the new rates.
+ conversion_rate: ConversionRate;
+ }
+
+
+.. http:get:: /cashin-rate
+
+ This public endpoint allows clients to calculate
+ the exchange rate between the regional currency
+ and the fiat currency of the banking system.
+
+ This endpoint shows how the bank would apply the cash-in
+ ratio and fee to one input amount. Typically, wallets would
+ request this endpoint before creating withdrawals that involve
+ a currency conversion.
+
+ **Request:**
+
+ :query amount_debit: this is the amount that the user will get
+ deducted from their fiat bank account.
+
+ or
+
+ :query amount_credit: this is the amount that the user will receive
+ in their regional bank account.
+
+ **Response:**
+
+ :http:statuscode:`200 OK`:
+ Response is a `CashinConversionResponse`.
+ :http:statuscode:`400 Bad request`:
+ * ``TALER_EC_GENERIC_PARAMETER_MISSING`` : none of the parameters have been provided.
+ * ``TALER_EC_GENERIC_PARAMETER_MALFORMED`` : both of the parameters have been provided or one of them is not a valid Taler amount.
+ * ``TALER_EC_GENERIC_CURRENCY_MISMATCH`` : the parameter is in the wrong currency.
+ :http:statuscode:`409 Conflict`:
+ The amount is too small to be converted, either because it produces produce an amount less than zero, or because the server requires a higher minimum amount than that supplied.
+ :http:statuscode:`501 Not implemented`:
+ This server does not support conversion, client should check config response.
+
+ **Details:**
+
+ .. ts:def:: CashinConversionResponse
+
+ interface CashinConversionResponse {
+ // Amount that the user will get deducted from their fiat
+ // bank account, according to the 'amount_credit' value.
+ amount_debit: Amount;
+ // Amount that the user will receive in their regional
+ // bank account, according to 'amount_debit'.
+ amount_credit: Amount;
+ }
+
+.. http:get:: /cashout-rate
+
+ This public endpoint allows clients to calculate
+ the exchange rate between the regional currency
+ and the fiat currency of the banking system.
+
+ This endpoint shows how the bank would apply the cash-out
+ ratio and fee to one input amount. Typically, frontends
+ ask this endpoint before creating cash-in operations.
+
+ **Request:**
+
+ :query amount_debit: this is the amount that the user will get
+ deducted from their regional bank account.
+
+ or
+
+ :query amount_credit: this is the amount that the user will receive
+ in their fiat bank account.
+
+ **Response:**
+
+ :http:statuscode:`200 OK`:
+ Response is a `CashoutConversionResponse`.
+ :http:statuscode:`400 Bad request`:
+ * ``TALER_EC_GENERIC_PARAMETER_MISSING`` : none of the parameters have been provided.
+ * ``TALER_EC_GENERIC_PARAMETER_MALFORMED`` : both of the parameters have been provided or one of them is not a valid Taler amount.
+ * ``TALER_EC_GENERIC_CURRENCY_MISMATCH`` : the parameter is in the wrong currency.
+ :http:statuscode:`409 Conflict`:
+ The amount is too small to be converted, either because it produces produce an amount less than zero, or because the server requires a higher minimum amount than that supplied.
+ :http:statuscode:`501 Not implemented`:
+ This server does not support conversion, client should check config response.
+
+ **Details:**
+
+ .. ts:def:: CashoutConversionResponse
+
+ interface CashoutConversionResponse {
+ // Amount that the user will get deducted from their regional
+ // bank account, according to the 'amount_credit' value.
+ amount_debit: Amount;
+ // Amount that the user will receive in their fiat
+ // bank account, according to 'amount_debit'.
+ amount_credit: Amount;
+ }
+
+.. http:post:: /conversion-rate
+
+ This endpoint allows the administrator to update
+ the exchange rate between the regional currency
+ and the fiat currency of the banking system.
+
+ **Request:**
+
+ .. ts:def:: ConversionRate
+
+ interface ConversionRate {
+ // Exchange rate to buy regional currency from fiat
+ cashin_ratio: DecimalNumber;
+
+ // Regional amount fee to subtract after applying the cashin ratio.
+ cashin_fee: Amount;
+
+ // Minimum fiat amount authorised for cashin before conversion
+ cashin_min_amount: Amount;
+
+ // Smallest possible regional amount, converted amount is rounded to this amount
+ cashin_tiny_amount: Amount;
+
+ // Rounding mode used during cashin conversion
+ cashin_rounding_mode: "zero" | "up" | "nearest";
+
+ // Exchange rate to sell regional currency for fiat
+ cashout_ratio: DecimalNumber;
+
+ // Fiat amount fee to subtract after applying the cashout ratio.
+ cashout_fee: Amount;
+
+ // Minimum regional amount authorised for cashout before conversion
+ cashout_min_amount: Amount;
+
+ // Smallest possible fiat amount, converted amount is rounded to this amount
+ cashout_tiny_amount: Amount;
+
+ // Rounding mode used during cashout conversion
+ cashout_rounding_mode: "zero" | "up" | "nearest";
+ }
+
+ **Response:**
+
+ :http:statuscode:`204 No content`:
+ Operation successful.
+ :http:statuscode:`401 Unauthorized`:
+ Invalid credentials or missing rights.
+ :http:statuscode:`501 Not implemented`:
+ This server does not support conversion, client should check config response.
diff --git a/core/api-bank-integration.rst b/core/api-bank-integration.rst
index 630f5bb3..4131a28a 100644
--- a/core/api-bank-integration.rst
+++ b/core/api-bank-integration.rst
@@ -1,7 +1,7 @@
..
This file is part of GNU TALER.
- Copyright (C) 2014-2020 Taler Systems SA
+ Copyright (C) 2014-2023 Taler Systems SA
TALER is free software; you can redistribute it and/or modify it under the
terms of the GNU Affero General Public License as published by the Free Software
@@ -28,34 +28,37 @@ to tightly integrate with GNU Taler.
.. http:get:: /config
- Get configuration information about the bank.
-
- **Request:**
+ Return the protocol version and configuration information about the bank.
+ This specification corresponds to ``current`` protocol being version **2**.
**Response:**
:http:statuscode:`200 OK`:
- The exchange responds with a `BankVersion` object. This request should
+ The exchange responds with a `IntegrationConfig` object. This request should
virtually always be successful.
**Details:**
- .. ts:def:: BankVersion
+ .. ts:def:: IntegrationConfig
+
+ interface IntegrationConfig {
+ // Name of the API.
+ name: "taler-bank-integration";
- interface BankVersion {
// libtool-style representation of the Bank protocol version, see
// https://www.gnu.org/software/libtool/manual/html_node/Versioning.html#Versioning
// The format is "current:revision:age".
version: string;
+ // URN of the implementation (needed to interpret 'revision' in version).
+ // @since v2, may become mandatory in the future.
+ implementation?: string;
+
// Currency used by this bank.
currency: string;
// How the bank SPA should render this currency.
currency_specification: CurrencySpecification;
-
- // Name of the API.
- name: "taler-bank-integration";
}
@@ -66,41 +69,42 @@ Withdrawing
Withdrawals with a Taler-integrated bank are based on withdrawal operations.
Some user interaction (on the bank's website or a Taler-enabled ATM) creates a
withdrawal operation record in the bank's database. The wallet can use a unique identifier
-for the withdrawal operation (the ``wopid``) to interact with the withdrawal operation.
+for the withdrawal operation (the ``WITHDRAWAL_ID``) to interact with the withdrawal operation.
-.. http:get:: ${BANK_API_BASE_URL}/withdrawal-operation/${wopid}
+.. http:get:: /withdrawal-operation/$WITHDRAWAL_ID
- Query information about a withdrawal operation, identified by the ``wopid``.
+ Query information about a withdrawal operation, identified by the ``WITHDRAWAL_ID``.
- **Request**
+ **Request:**
:query long_poll_ms:
*Optional.* If specified, the bank will wait up to ``long_poll_ms``
- milliseconds for completion of the transfer before sending the HTTP
+ milliseconds for operationt state to be different from ``old_state`` before sending the HTTP
response. A client must never rely on this behavior, as the bank may
return a response immediately.
+ :query old_state:
+ *Optional.* Default to "pending".
- **Response**
+ **Response:**
:http:statuscode:`200 OK`:
The withdrawal operation is known to the bank, and details are given
in the `BankWithdrawalOperationStatus` response body.
+ :http:statuscode:`404 Not found`:
+ The operation was not found
+ **Details:**
.. ts:def:: BankWithdrawalOperationStatus
export class BankWithdrawalOperationStatus {
- // Indicates whether the withdrawal was aborted.
- aborted: boolean;
-
- // Has the wallet selected parameters for the withdrawal operation
- // (exchange and reserve public key) and successfully sent it
- // to the bank?
- selection_done: boolean;
-
- // The transfer has been confirmed and registered by the bank.
- // Does not guarantee that the funds have arrived at the exchange already.
- transfer_done: boolean;
+ // Current status of the operation
+ // pending: the operation is pending parameters selection (exchange and reserve public key)
+ // selected: the operations has been selected and is pending confirmation
+ // aborted: the operation has been aborted
+ // confirmed: the transfer has been confirmed and registered by the bank
+ // Since protocol v1.
+ status: "pending" | "selected" | "aborted" | "confirmed";
// Amount that will be withdrawn with this operation
// (raw amount without fee considerations).
@@ -115,33 +119,46 @@ for the withdrawal operation (the ``wopid``) to interact with the withdrawal ope
// URL that the user needs to navigate to in order to
// complete some final confirmation (e.g. 2FA).
+ // Only applicable when ``status`` is ``selected`` or ``pending``.
// It may contain withdrawal operation id
confirm_transfer_url?: string;
// Wire transfer types supported by the bank.
wire_types: string[];
- }
-.. http:post:: ${BANK_API_BASE_URL}/withdrawal-operation/${wopid}
+ // Reserve public key selected by the exchange,
+ // only non-null if ``status`` is ``selected`` or ``confirmed``.
+ // Since protocol v1.
+ selected_reserve_pub?: string;
- **Request** The body of this request must have the format of a `BankWithdrawalOperationPostRequest`.
+ // Exchange account selected by the wallet
+ // only non-null if ``status`` is ``selected`` or ``confirmed``.
+ // Since protocol v1.
+ selected_exchange_account?: string;
- **Response**
+ // Deprecated field since protocol v1 use ``status`` instead
+ // Indicates whether the withdrawal was aborted.
+ aborted: boolean;
- :http:statuscode:`200 OK`:
- The bank has accepted the withdrawal operation parameters chosen by the wallet.
- The response is a `BankWithdrawalOperationPostResponse`.
- :http:statuscode:`404 Not found`:
- The bank does not know about a withdrawal operation with the specified ``wopid``.
- :http:statuscode:`409 Conflict` (New):
- The wallet selected a different exchange or reserve public key under the same withdrawal ID.
+ // Deprecated field since protocol v1 use ``status`` instead
+ // Has the wallet selected parameters for the withdrawal operation
+ // (exchange and reserve public key) and successfully sent it
+ // to the bank?
+ selection_done: boolean;
- **Details**
+ // Deprecated field since protocol v1 use ``status`` instead
+ // The transfer has been confirmed and registered by the bank.
+ // Does not guarantee that the funds have arrived at the exchange already.
+ transfer_done: boolean;
+ }
+
+.. http:post:: /withdrawal-operation/$WITHDRAWAL_ID
+
+ **Request:**
.. ts:def:: BankWithdrawalOperationPostRequest
interface BankWithdrawalOperationPostRequest {
-
// Reserve public key.
reserve_pub: string;
@@ -149,18 +166,56 @@ for the withdrawal operation (the ``wopid``) to interact with the withdrawal ope
selected_exchange: string;
}
+ **Response:**
+
+ :http:statuscode:`200 OK`:
+ The bank has accepted the withdrawal operation parameters chosen by the wallet.
+ The response is a `BankWithdrawalOperationPostResponse`.
+ :http:statuscode:`404 Not found`:
+ The bank does not know about a withdrawal operation with the specified ``WITHDRAWAL_ID``.
+ :http:statuscode:`409 Conflict`:
+ * ``TALER_EC_BANK_WITHDRAWAL_OPERATION_RESERVE_SELECTION_CONFLICT`` :
+ The wallet selected a different exchange or reserve public key under the same withdrawal ID.
+ * ``TALER_EC_BANK_DUPLICATE_RESERVE_PUB_SUBJECT`` : the reserve public key is already used.
+ * ``TALER_EC_BANK_UNKNOWN_ACCOUNT`` : the selected exchange account was not found.
+ * ``TALER_EC_BANK_ACCOUNT_IS_NOT_EXCHANGE`` : the selected account is not an exchange.
+
+ **Details:**
+
.. ts:def:: BankWithdrawalOperationPostResponse
interface BankWithdrawalOperationPostResponse {
-
- // The transfer has been confirmed and registered by the bank.
- // Does not guarantee that the funds have arrived at the exchange already.
- transfer_done: boolean;
+ // Current status of the operation
+ // pending: the operation is pending parameters selection (exchange and reserve public key)
+ // selected: the operations has been selected and is pending confirmation
+ // aborted: the operation has been aborted
+ // confirmed: the transfer has been confirmed and registered by the bank
+ status: "selected" | "aborted" | "confirmed";
// URL that the user needs to navigate to in order to
// complete some final confirmation (e.g. 2FA).
//
- // Only applicable when ``transfer_done`` is ``false``.
+ // Only applicable when ``status`` is ``selected`` or ``pending``.
// It may contain withdrawal operation id
confirm_transfer_url?: string;
+
+ // Deprecated field use ``status`` instead
+ // The transfer has been confirmed and registered by the bank.
+ // Does not guarantee that the funds have arrived at the exchange already.
+ transfer_done: boolean;
}
+
+.. http:post:: /withdrawal-operation/$WITHDRAWAL_ID/abort
+
+ Aborts ``WITHDRAWAL_ID`` operation. Has no effect on an already aborted
+ operation.
+ Since protocol v2.
+
+ **Response:**
+
+ :http:statuscode:`204 No content`:
+ The withdrawal operation has been aborted.
+ :http:statuscode:`404 Not found`:
+ The withdrawal operation was not found.
+ :http:statuscode:`409 Conflict`:
+ The withdrawal operation has been confirmed previously and can't be aborted.
diff --git a/core/api-bank-revenue.rst b/core/api-bank-revenue.rst
index e266bced..a647fb35 100644
--- a/core/api-bank-revenue.rst
+++ b/core/api-bank-revenue.rst
@@ -22,6 +22,38 @@ Taler Bank Revenue HTTP API
This section describes an API offered by libeufin-nexus and libeufin-bank. The API is
used by the merchant (or other parties) to query for incoming transactions to their account.
+.. http:get:: /config
+
+ Return the protocol version and configuration information about the bank.
+ This specification corresponds to ``current`` protocol being version **0**.
+
+ **Response:**
+
+ :http:statuscode:`200 OK`:
+ The exchange responds with a `RevenueConfig` object. This request should
+ virtually always be successful.
+
+ **Details:**
+
+ .. ts:def:: RevenueConfig
+
+ interface RevenueConfig {
+ // Name of the API.
+ name: "taler-revenue";
+
+ // libtool-style representation of the Bank protocol version, see
+ // https://www.gnu.org/software/libtool/manual/html_node/Versioning.html#Versioning
+ // The format is "current:revision:age".
+ version: string;
+
+ // Currency used by this gateway.
+ currency: string;
+
+ // URN of the implementation (needed to interpret 'revision' in version).
+ // @since v0, may become mandatory in the future.
+ implementation?: string;
+ }
+
--------------
Authentication
@@ -34,16 +66,11 @@ The bank library authenticates requests to the bank merchant API using
Querying the transaction history
--------------------------------
-.. http:get:: ${BASE_URL}/history
+.. http:get:: /history
- Return a list of transactions made from an exchange to the merchant.
+ Return a list of transactions made to an account.
- Incoming transactions must contain a valid wire transfer identifier and
- exchange base URL. If a bank transaction does not conform to the right
- syntax, the wire gateway must not report it to the merchant via this
- endpoint.
-
- The bank account of the merchant is determined via the base URL and/or the
+ The bank account is determined via the base URL and/or the
user name in the ``Authorization`` header. In fact, the transaction history
might come from a "virtual" account, where multiple real bank accounts are
merged into one history.
@@ -91,25 +118,23 @@ Querying the transaction history
:http:statuscode:`404 Not found`:
The endpoint is wrong or the user name is unknown. The bank replies with an `ErrorDetail` object.
- .. ts:def:: MerchantIncomingHistory
+ **Details:**
- interface MerchantIncomingHistory {
+ .. ts:def:: RevenueIncomingHistory
+ interface RevenueIncomingHistory {
// Array of incoming transactions.
- incoming_transactions : MerchantIncomingBankTransaction[];
+ incoming_transactions : RevenueIncomingBankTransaction[];
// Payto URI to identify the receiver of funds.
- // This must be one of the merchant's bank accounts.
// Credit account is shared by all incoming transactions
// as per the nature of the request.
credit_account: string;
-
}
- .. ts:def:: MerchantIncomingBankTransaction
-
- interface MerchantIncomingBankTransaction {
+ .. ts:def:: RevenueIncomingBankTransaction
+ interface RevenueIncomingBankTransaction {
// Opaque identifier of the returned record.
row_id: SafeUint64;
@@ -122,9 +147,6 @@ Querying the transaction history
// Payto URI to identify the sender of funds.
debit_account: string;
- // Base URL of the exchange where the transfer originated form.
- exchange_url: string;
-
- // The wire transfer identifier.
- wtid: WireTransferIdentifierRawP;
+ // The wire transfer subject.
+ subject: string;
}
diff --git a/core/api-bank-wire.rst b/core/api-bank-wire.rst
index 441537ca..a76f5195 100644
--- a/core/api-bank-wire.rst
+++ b/core/api-bank-wire.rst
@@ -13,6 +13,8 @@
You should have received a copy of the GNU Affero General Public License along with
TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
+.. _taler-wire-gateway-http-api:
+
===========================
Taler Wire Gateway HTTP API
===========================
@@ -24,6 +26,37 @@ well as by the auditor to query incoming and outgoing transactions.
This API is currently implemented by the Taler Demo Bank, as well as by
LibEuFin (work in progress).
+.. http:get:: /config
+
+ Return the protocol version and configuration information about the bank.
+ This specification corresponds to ``current`` protocol being version **0**.
+
+ **Response:**
+
+ :http:statuscode:`200 OK`:
+ The exchange responds with a `WireConfig` object. This request should
+ virtually always be successful.
+
+ **Details:**
+
+ .. ts:def:: WireConfig
+
+ interface WireConfig {
+ // Name of the API.
+ name: "taler-wire-gateway";
+
+ // libtool-style representation of the Bank protocol version, see
+ // https://www.gnu.org/software/libtool/manual/html_node/Versioning.html#Versioning
+ // The format is "current:revision:age".
+ version: string;
+
+ // Currency used by this gateway.
+ currency: string;
+
+ // URN of the implementation (needed to interpret 'revision' in version).
+ // @since v0, may become mandatory in the future.
+ implementation?: string;
+ }
--------------
Authentication
@@ -36,7 +69,7 @@ The bank library authenticates requests to the wire gateway via
Making Transactions
-------------------
-.. http:post:: ${BASE_URL}/transfer
+.. http:post:: /transfer
This API allows the exchange to make a transaction, typically to a merchant. The bank account
of the exchange is not included in the request, but instead derived from the user name in the
@@ -45,7 +78,31 @@ Making Transactions
To make the API idempotent, the client must include a nonce. Requests with the same nonce
are rejected unless the request is the same.
- **Request:** The body of this request must have the format of a `TransferRequest`.
+ **Request:**
+
+ .. ts:def:: TransferRequest
+
+ interface TransferRequest {
+ // Nonce to make the request idempotent. Requests with the same
+ // ``request_uid`` that differ in any of the other fields
+ // are rejected.
+ request_uid: HashCode;
+
+ // Amount to transfer.
+ amount: Amount;
+
+ // Base URL of the exchange. Shall be included by the bank gateway
+ // in the appropriate section of the wire transfer details.
+ exchange_base_url: string;
+
+ // Wire transfer identifier chosen by the exchange,
+ // used by the merchant to identify the Taler order(s)
+ // associated with this wire transfer.
+ wtid: ShortHashCode;
+
+ // The recipient's account identifier as a payto URI.
+ credit_account: string;
+ }
**Response:**
@@ -59,7 +116,7 @@ Making Transactions
:http:statuscode:`404 Not found`:
The endpoint is wrong or the user name is unknown. The bank replies with an `ErrorDetail` object.
:http:statuscode:`409 Conflict`:
- A transaction with the same ``transaction_uid`` but different transaction details
+ A transaction with the same ``request_uid`` but different transaction details
has been submitted before.
**Details:**
@@ -67,7 +124,6 @@ Making Transactions
.. ts:def:: TransferResponse
interface TransferResponse {
-
// Timestamp that indicates when the wire transfer will be executed.
// In cases where the wire transfer gateway is unable to know when
// the wire transfer will be executed, the time at which the request
@@ -82,37 +138,12 @@ Making Transactions
}
- .. ts:def:: TransferRequest
-
- interface TransferRequest {
- // Nonce to make the request idempotent. Requests with the same
- // ``transaction_uid`` that differ in any of the other fields
- // are rejected.
- request_uid: HashCode;
-
- // Amount to transfer.
- amount: Amount;
-
- // Base URL of the exchange. Shall be included by the bank gateway
- // in the appropriate section of the wire transfer details.
- exchange_base_url: string;
-
- // Wire transfer identifier chosen by the exchange,
- // used by the merchant to identify the Taler order(s)
- // associated with this wire transfer.
- wtid: ShortHashCode;
-
- // The recipient's account identifier as a payto URI.
- credit_account: string;
- }
-
-
--------------------------------
Querying the transaction history
--------------------------------
-.. http:get:: ${BASE_URL}/history/incoming
+.. http:get:: /history/incoming
Return a list of transactions made from or to the exchange.
@@ -170,10 +201,11 @@ Querying the transaction history
:http:statuscode:`404 Not found`:
The endpoint is wrong or the user name is unknown. The bank replies with an `ErrorDetail` object.
+ **Details:**
+
.. ts:def:: IncomingHistory
interface IncomingHistory {
-
// Array of incoming transactions.
incoming_transactions : IncomingBankTransaction[];
@@ -243,7 +275,7 @@ Querying the transaction history
}
-.. http:get:: ${BASE_URL}/history/outgoing
+.. http:get:: /history/outgoing
Return a list of transactions made by the exchange, typically to a merchant.
@@ -297,10 +329,11 @@ Querying the transaction history
:http:statuscode:`404 Not found`:
The endpoint is wrong or the user name is unknown. The bank replies with an `ErrorDetail` object.
+ **Details:**
+
.. ts:def:: OutgoingHistory
interface OutgoingHistory {
-
// Array of outgoing transactions.
outgoing_transactions : OutgoingBankTransaction[];
@@ -315,7 +348,6 @@ Querying the transaction history
.. ts:def:: OutgoingBankTransaction
interface OutgoingBankTransaction {
-
// Opaque identifier of the returned record.
row_id: SafeUint64;
@@ -345,26 +377,12 @@ exposed by bank gateways in production.
.. _twg-admin-add-incoming:
-.. http:post:: ${BASE_URL}/admin/add-incoming
+.. http:post:: /admin/add-incoming
Simulate a transfer from a customer to the exchange. This API is *not*
idempotent since it's only used in testing.
- **Request:** The body of this request must have the format of a `AddIncomingRequest`.
-
- **Response:**
-
- :http:statuscode:`200 OK`:
- The request has been correctly handled, so the funds have been transferred to
- the recipient's account. The body is a `AddIncomingResponse`.
- :http:statuscode:`400 Bad request`:
- The request is malformed. The bank replies with an `ErrorDetail` object.
- :http:statuscode:`401 Unauthorized`:
- Authentication failed, likely the credentials are wrong.
- :http:statuscode:`404 Not found`:
- The endpoint is wrong or the user name is unknown. The bank replies with an `ErrorDetail` object.
- :http:statuscode:`409 Conflict`:
- The 'reserve_pub' argument was used previously in another transfer, and the specification mandates that reserve public keys must not be reused.
+ **Request:**
.. ts:def:: AddIncomingRequest
@@ -383,11 +401,25 @@ exposed by bank gateways in production.
debit_account: string;
}
+ **Response:**
+
+ :http:statuscode:`200 OK`:
+ The request has been correctly handled, so the funds have been transferred to
+ the recipient's account. The body is a `AddIncomingResponse`.
+ :http:statuscode:`400 Bad request`:
+ The request is malformed. The bank replies with an `ErrorDetail` object.
+ :http:statuscode:`401 Unauthorized`:
+ Authentication failed, likely the credentials are wrong.
+ :http:statuscode:`404 Not found`:
+ The endpoint is wrong or the user name is unknown. The bank replies with an `ErrorDetail` object.
+ :http:statuscode:`409 Conflict`:
+ The 'reserve_pub' argument was used previously in another transfer, and the specification mandates that reserve public keys must not be reused.
+
+ **Details:**
.. ts:def:: AddIncomingResponse
interface AddIncomingResponse {
-
// Timestamp that indicates when the wire transfer will be executed.
// In cases where the wire transfer gateway is unable to know when
// the wire transfer will be executed, the time at which the request
diff --git a/core/api-challenger.rst b/core/api-challenger.rst
index 265ad5a6..914d8d01 100644
--- a/core/api-challenger.rst
+++ b/core/api-challenger.rst
@@ -49,9 +49,9 @@ particular address. However, asking a user to prove access to a particular
address can be expensive as it may involve sending an SMS or even postal mail
depending on the type of address. Thus, challenger does not allow a user
agent to begin an address validation process without prior approval by a
-registered client. Thus, the process begins with a ``/setup`` request where a
+registered client. Thus, the process begins with a ``/setup/$CLIENT_ID`` request where a
client requests challenger to begin an address validation request. The
-``/setup`` response contains a ``nonce`` which is then used to construct the
+``/setup/$CLIENT_ID`` response contains a ``nonce`` which is then used to construct the
URL of the endpoint to which the client must redirect the user-agent to begin
the address validation and authorization process.
@@ -88,6 +88,7 @@ Using the ``/info`` endpoint the client can then finally obtain the (now)
verified address of the user.
.. contents:: Table of Contents
+ :local:
.. include:: tos.rst
@@ -98,6 +99,7 @@ Receiving Configuration
.. http:get:: /config
Obtain the key configuration settings of the storage service.
+ This specification corresponds to ``current`` protocol being version **0**.
**Response:**
@@ -114,6 +116,10 @@ Receiving Configuration
// The format is "current:revision:age".
version: string;
+ // URN of the implementation (needed to interpret 'revision' in version).
+ // @since v0, may become mandatory in the future.
+ implementation?: string;
+
}
.. _challenger-setup:
@@ -327,8 +333,15 @@ Info
.. ts:def:: ChallengerInfoResponse
interface ChallengerInfoResponse {
+
+ // Unique ID of the record within Challenger
+ // (identifies the rowid of the token).
+ id: Integer;
+
// Address that was validated.
- address: string;
+ // Key-value pairs, details depend on the
+ // address_type.
+ address: Object;
// Type of the address.
address_type: string;
diff --git a/core/api-common.rst b/core/api-common.rst
index 6e9db257..51f2ab9f 100644
--- a/core/api-common.rst
+++ b/core/api-common.rst
@@ -24,6 +24,8 @@
Conventions for Taler RESTful APIs
==================================
+.. contents:: Table of Contents
+ :local:
-------------------------
HTTP Request and Response
@@ -352,6 +354,14 @@ Integers
// JavaScript numbers restricted to integers.
type Integer = number;
+Floats
+^^^^^^
+
+.. ts:def:: Float
+
+ // JavaScript numbers.
+ type Float = number;
+
Ages
^^^^
@@ -543,7 +553,7 @@ Blinded coin
// coin's `public EdDSA key <eddsa-coin-pub>`.
interface RSACoinEnvelope {
cipher: "RSA" | "RSA+age_restricted";
- rsa_blinded_planchet: string; // Crockford `Base32` encoded
+ rsa_blinded_planchet: BlindedRsaSignature;
}
.. ts:def:: CSCoinEnvelope
@@ -567,6 +577,25 @@ Blinded coin
type DenominationBlindingKeyP = string;
+. _unblinded-coin:
+
+Unblinded coin
+^^^^^^^^^^^^^^
+
+.. ts:def:: UnblindedSignature
+
+ // The type of a coin's unblinded signature depends on the cipher that was used
+ // for signing with a denomination key.
+ // Note that for now, only RSA is supported.
+ type UnblindedSignature = RsaUnblindedSignature;
+
+.. ts:def:: RsaUnblindedSignature
+
+ interface RsaUnblindedSignature {
+ cipher: "RSA";
+ rsa_signature: RsaSignature;
+ }
+
.. _signature:
@@ -1024,10 +1053,9 @@ within the
};
-.. _TALER_DepositRequestPS:
+.. _taler_depositrequestps:
.. sourcecode:: c
- :caption: struct declaration
struct TALER_DepositRequestPS {
/**
@@ -1044,14 +1072,12 @@ within the
struct TALER_AmountNBO amount_with_fee;
struct TALER_AmountNBO deposit_fee;
struct TALER_MerchantPublicKeyP merchant;
- struct TALER_OutputCommitmentHash h_outputs;
struct GNUNET_HashCode wallet_data_hash;
};
.. _TALER_DepositConfirmationPS:
.. sourcecode:: c
- :caption: struct declaration
struct TALER_DepositConfirmationPS {
/**
@@ -1103,7 +1129,6 @@ within the
* purpose.purpose = TALER_SIGNATURE_MASTER_SIGNING_KEY_VALIDITY
*/
struct GNUNET_CRYPTO_EccSignaturePurpose purpose;
- struct TALER_MasterPublicKeyP master_public_key;
struct GNUNET_TIME_AbsoluteNBO start;
struct GNUNET_TIME_AbsoluteNBO expire;
struct GNUNET_TIME_AbsoluteNBO end;
@@ -1174,7 +1199,7 @@ within the
.. _TALER_GlobalFeesPS:
.. sourcecode:: c
- struct TALER_MasterWireFeePS {
+ struct TALER_GlobalFeesPS {
/**
* purpose.purpose = TALER_SIGNATURE_MASTER_GLOBAL_FEES
*/
@@ -1286,10 +1311,7 @@ within the
* purpose.purpose = TALER_SIGNATURE_MERCHANT_CONTRACT
*/
struct GNUNET_CRYPTO_EccSignaturePurpose purpose;
- struct TALER_AmountNBO total_amount;
- struct TALER_AmountNBO max_fee;
struct TALER_PrivateContractHash h_contract_terms;
- struct TALER_MerchantPublicKeyP merchant_pub;
};
.. _TALER_ConfirmWirePS:
diff --git a/core/api-corebank.rst b/core/api-corebank.rst
index 15e91537..e1cb4fb6 100644
--- a/core/api-corebank.rst
+++ b/core/api-corebank.rst
@@ -1,7 +1,7 @@
..
This file is part of GNU TALER.
- Copyright (C) 2014-2020 Taler Systems SA
+ Copyright (C) 2014-2024 Taler Systems SA
TALER is free software; you can redistribute it and/or modify it under the
terms of the GNU Affero General Public License as published by the Free Software
@@ -23,6 +23,7 @@ Taler Core Bank API
====================
.. contents:: Table of Contents
+ :local:
Introduction
------------
@@ -61,53 +62,70 @@ Config
.. http:get:: /config
+ Return the protocol version and configuration information about the bank.
+ This specification corresponds to ``current`` protocol being version **4**.
+
**Response:**
+ :http:statuscode:`200 OK`:
+ Response is a `Config`.
+
+ **Details:**
+
.. ts:def:: Config
interface Config {
- // Name of this API, always "taler-corebank".
- name: string;
+ // Name of the API.
+ name: "taler-corebank";
- // API version in the form $n:$n:$n
+ // libtool-style representation of the Bank protocol version, see
+ // https://www.gnu.org/software/libtool/manual/html_node/Versioning.html#Versioning
+ // The format is "current:revision:age".
version: string;
- // If 'true', the server provides local currency
- // conversion support.
- // If missing or false, some parts of the API
- // are not supported and return 404.
- have_cashout?: boolean;
+ // Bank display name to be used in user interfaces.
+ // For consistency use "Taler Bank" if missing.
+ // @since v4, will become mandatory in the next version.
+ bank_name?: string;
- // How the bank SPA should render the currency.
- currency: CurrencySpecification;
+ // If 'true' the server provides local currency conversion support
+ // If 'false' some parts of the API are not supported and return 501
+ allow_conversion: boolean;
- // Fiat currency. That is the currency in which
- // cash-out operations ultimately wire money.
- // Only applicable if have_cashout=true.
- fiat_currency?: CurrencySpecification;
+ // If 'true' anyone can register
+ // If 'false' only admin can
+ allow_registrations: boolean;
- // Extra conversion rate information.
- // Only present if conversion is supported and the server opts in
- // to report the static conversion rate.
- conversion_info?: {
- // Exchange rate to buy the local currency from the external one
- buy_at_ratio: DecimalNumber;
+ // If 'true' account can delete themselves
+ // If 'false' only admin can delete accounts
+ allow_deletions: boolean;
- // Exchange rate to sell the local currency for the external one
- sell_at_ratio: DecimalNumber;
+ // If 'true' anyone can edit their name
+ // If 'false' only admin can
+ allow_edit_name: boolean;
- // Fee to subtract after applying the buy ratio.
- buy_in_fee: DecimalNumber;
+ // If 'true' anyone can edit their cashout account
+ // If 'false' only admin can
+ allow_edit_cashout_payto_uri: boolean;
- // Fee to subtract after applying the sell ratio.
- sell_out_fee: DecimalNumber;
- }
+ // Default debt limit for newly created accounts
+ default_debit_threshold: Amount;
- }
+ // Currency used by this bank.
+ currency: string;
+ // How the bank SPA should render this currency.
+ currency_specification: CurrencySpecification;
+
+ // TAN channels supported by the server
+ supported_tan_channels: TanChannel[];
+
+ // Wire transfer type supported by the bank.
+ // Default to 'iban' is missing
+ // @since v4, will become mandatory in the next version.
+ wire_type?: string;
+ }
- :http:statuscode:`200 OK`:
- Response is a `Config`.
Account Management
------------------
@@ -116,81 +134,99 @@ Account Management
.. http:post:: /accounts
- Create a new bank account. Depending on the configuration,
- the account creation is self-serve, or only restricted to
- the administrators.
-
- **Request:**
-
- .. ts:def:: RegisterAccountRequest
-
- interface RegisterAccountRequest {
- // Username
- username: string;
-
- // Password.
- password: string;
-
- // Legal name of the account owner
- name: string;
-
- // Defaults to false.
- is_public?: boolean;
-
- // Is this a taler exchange account?
- // If true:
- // - incoming transactions to the account that do not
- // have a valid reserve public key are automatically
- // - the account provides the taler-wire-gateway-api endpoints
- // Defaults to false.
- is_taler_exchange?: boolean;
+ Create a new bank account. Depending on the configuration,
+ the account creation is self-serve, or only restricted to
+ the administrators.
- // Addresses where to send the TAN for transactions.
- // Currently only used for cashouts.
- // If missing, cashouts will fail.
- // In the future, might be used for other transactions
- // as well.
- challenge_contact_data?: ChallengeContactData;
+ **Request:**
- // 'payto' address pointing a bank account
- // external to the bank.
- // Payments will be sent to this bank account
- // when the user wants to convert the local currency
- // back to fiat currency outside bank.
- cashout_payto_uri?: string;
+ .. ts:def:: RegisterAccountRequest
- // Internal payto URI of this bank account.
- // Used mostly for testing.
- internal_payto_uri?: string;
- }
+ interface RegisterAccountRequest {
+ // Username of the account
+ username: string;
- .. ts:def:: ChallengeContactData
+ // Password of the account used for authentication
+ password: string;
- interface ChallengeContactData {
+ // Legal name of the account owner
+ name: string;
- // E-Mail address
- email?: EmailAddress;
+ // Make this account visible to anyone?
+ // Defaults to false.
+ is_public?: boolean;
+
+ // Make this account a taler exchange account?
+ // If true:
+ // - incoming transactions to the account that do not
+ // have a valid reserve public key are automatically
+ // - the account provides the taler-wire-gateway-api endpoints
+ // Defaults to false.
+ is_taler_exchange?: boolean;
+
+ // Addresses where to send the TAN for protected operations.
+ contact_data?: ChallengeContactData;
+
+ // IBAN 'payto' URI of a fiat bank account with a 'receiver-name' parameter.
+ // If 'receiver-name' is missing, ``name`` will be used instead.
+ // Payments will be sent to this bank account
+ // when the user wants to convert the regional currency
+ // back to fiat currency outside bank.
+ cashout_payto_uri?: string;
+
+ // Internal payto URI of this bank account.
+ // Used mostly for testing, this field is ignored if the bank payment
+ // method is not IBAN.
+ payto_uri?: string;
+
+ // If present, set the max debit allowed for this user
+ // Only admin can set this property.
+ debit_threshold?: Amount;
+
+ // If present, enables 2FA and set the TAN channel used for challenges
+ // Only admin can set this property, other user can reconfig their account
+ // after creation.
+ tan_channel?: TanChannel;
+ }
- // Phone number.
- phone?: PhoneNumber;
- }
+ .. ts:def:: ChallengeContactData
+ interface ChallengeContactData {
+ // E-Mail address
+ email?: EmailAddress;
- **Response:**
+ // Phone number.
+ phone?: PhoneNumber;
+ }
- :http:statuscode:`201 Created`:
- The account was successfully created.
- :http:statuscode:`400 Bad request`:
- Input data was invalid. For example, the client specified a invalid
- phone number or e-mail address.
- :http:statuscode:`403 Forbidden`:
- The response should indicate one of the following reasons.
- * A reserved username was attempted, like ``admin`` or ``bank``.
- * An unauthorized user tried to create the account
+ **Response:**
- :http:statuscode:`409 Conflict`:
- The internal account payto URI or username already exists.
+ :http:statuscode:`200 OK`:
+ Response is a `RegisterAccountResponse`.
+ :http:statuscode:`400 Bad request`:
+ Input data was invalid. For example, the client specified a invalid
+ phone number or e-mail address.
+ :http:statuscode:`401 Unauthorized`:
+ Invalid credentials or missing rights.
+ :http:statuscode:`409 Conflict`:
+ * ``TALER_EC_BANK_REGISTER_USERNAME_REUSE`` : username already used.
+ * ``TALER_EC_BANK_REGISTER_PAYTO_URI_REUSE`` : payto URI already used.
+ * ``TALER_EC_BANK_UNALLOWED_DEBIT`` : admin account does not have sufficient funds to grant bonus.
+ * ``TALER_EC_BANK_RESERVED_USERNAME_CONFLICT`` : a reserved username was attempted, like ``admin`` or ``bank``
+ * ``TALER_EC_BANK_NON_ADMIN_PATCH_DEBT_LIMIT`` : a non-admin user has tried to create an account with a customer debt limit.
+ * ``TALER_EC_BANK_NON_ADMIN_SET_TAN_CHANNEL`` : a non-admin user has tried to create an account with 2fa.
+ * ``TALER_EC_BANK_TAN_CHANNEL_NOT_SUPPORTED``: ``tan_channel`` is not supported, check bank config to find supported ones.
+ * ``TALER_EC_BANK_MISSING_TAN_INFO``: the user did not share any contact data where to send the TAN via ``tan_channel``.
+
+ **Details:**
+
+ .. ts:def:: RegisterAccountResponse
+
+ interface RegisterAccountResponse {
+ // Internal payto URI of this bank account.
+ internal_payto_uri: string;
+ }
.. _delete-account:
@@ -202,119 +238,134 @@ Account Management
**Response:**
+ :http:statuscode:`202 Accepted`:
+ 2FA is required for this operation. This returns the `Challenge` response.
:http:statuscode:`204 No content`:
The account was successfully deleted.
- :http:statuscode:`403 Forbidden`:
- Either the request specified a reserved internal username, like
- ``admin`` or ``bank``, or the client didn't have the rights to this
- call.
+ :http:statuscode:`401 Unauthorized`:
+ Invalid credentials or missing rights.
:http:statuscode:`404 Not found`:
- The username was not found.
- :http:statuscode:`412 Precondition failed`:
- The balance was not zero.
-
+ The account pointed by ``$USERNAME`` was not found.
+ :http:statuscode:`409 Conflict`:
+ * ``TALER_EC_BANK_RESERVED_USERNAME_CONFLICT`` : a reserved username was attempted, like ``admin`` or ``bank``.
+ * ``TALER_EC_BANK_ACCOUNT_BALANCE_NOT_ZERO``: the account balance was not zero.
.. _account-reconfig:
.. http:patch:: /accounts/$USERNAME
- Allows reconfiguring the account data of ``$USERNAME``.
+ Allows reconfiguring the account data of ``$USERNAME``.
- **Request:**
-
- .. ts:def:: AccountReconfiguration
+ **Request:**
- interface AccountReconfiguration {
+ .. ts:def:: AccountReconfiguration
- // Addresses where to send the TAN for transactions.
- // Currently only used for cashouts.
- // If missing, cashouts will fail.
- // In the future, might be used for other transactions
- // as well.
- challenge_contact_data?: ChallengeContactData;
+ interface AccountReconfiguration {
+ // Addresses where to send the TAN for protected operations.
+ contact_data?: ChallengeContactData;
- // 'payto' address pointing a bank account
- // external to the bank.
- // Payments will be sent to this bank account
- // when the user wants to convert the local currency
- // back to fiat currency outside the bank.
- cashout_address?: string;
+ // IBAN 'payto' URI of a fiat bank account with a 'receiver-name' parameter.
+ // If 'receiver-name' is missing, ``name`` will be used instead.
+ // Payments will be sent to this bank account
+ // when the user wants to convert the regional currency
+ // back to fiat currency outside bank.
+ // Only admin can change this property if not allowed in config
+ cashout_payto_uri?: string;
- // Legal name associated with $username.
- // When missing, the old name is kept.
- name?: string;
+ // If present, change the legal name associated with $username.
+ // Only admin can change this property if not allowed in config
+ name?: string;
- // If present, change the is_exchange configuration.
- // See `RegisterAccountRequest`
- is_exchange?: boolean;
- }
+ // Make this account visible to anyone?
+ is_public?: boolean;
- **Response:**
+ // If present, change the max debit allowed for this user
+ // Only admin can change this property.
+ debit_threshold?: Amount;
- :http:statuscode:`204 No content`:
- Operation successful.
+ // If present, enables 2FA and set the TAN channel used for challenges
+ tan_channel?: TanChannel;
+ }
- :http:statuscode:`403 Forbidden`:
- The rights to change ``$USERNAME`` are not sufficient.
- That includes the case where a correctly authenticated
- user tries to change their legal name. It also
- includes the case where 'admin' tries to change its
- own account.
+ **Response:**
- :http:statuscode:`404 Not found`:
- The account pointed by ``$USERNAME``
- was not found.
+ :http:statuscode:`202 Accepted`:
+ 2FA is required for this operation. This returns the `Challenge` response.
+ :http:statuscode:`204 No content`:
+ Operation successful.
+ :http:statuscode:`401 Unauthorized`:
+ Invalid credentials or missing rights.
+ :http:statuscode:`404 Not found`:
+ The account pointed by ``$USERNAME`` was not found.
+ :http:statuscode:`409 Conflict`:
+ * ``TALER_EC_BANK_NON_ADMIN_PATCH_LEGAL_NAME`` : a non-admin user has tried to change their legal name.
+ * ``TALER_EC_BANK_NON_ADMIN_PATCH_CASHOUT`` : a non-admin user has tried to change their cashout account.
+ * ``TALER_EC_BANK_NON_ADMIN_PATCH_DEBT_LIMIT`` : a non-admin user has tried to change their debt limit.
+ * ``TALER_EC_BANK_TAN_CHANNEL_NOT_SUPPORTED`` : ``tan_channel`` is not supported, check bank config to find supported ones.
+ * ``TALER_EC_BANK_MISSING_TAN_INFO`` : the user did not share any contact data where to send the TAN via ``tan_channel``.
.. _account-password-reconfig:
.. http:patch:: /accounts/$USERNAME/auth
- Allows changing the account's password.
-
+ Allows changing the account's password.
- **Request:**
- .. ts:def:: AccountPasswordChange
+ **Request:**
- interface AccountPasswordChange {
- // Old password. If present it need to match the current
- // password before updating.
- old_password?: string;
- // New password.
- new_password: string;
- }
+ .. ts:def:: AccountPasswordChange
- **Response:**
+ interface AccountPasswordChange {
+ // Old password. If present it need to match the current
+ // password before updating.
+ old_password?: string;
+ // New password.
+ new_password: string;
+ }
- :http:statuscode:`204 No content`:
- Operation successful.
- :http:statuscode:`404 Not found`:
- The account pointed by ``$USERNAME`` was not found.
- :http:statuscode:`401 Unauthorized`:
- Invalid credentials.
- :http:statuscode:`403 Forbidden`:
- The user is not allowed to change the ``$USERNAME`` password or
- the "old_password" field in the request doesn't match the current pasword.
+ **Response:**
+
+ :http:statuscode:`202 Accepted`:
+ 2FA is required for this operation. This returns the `Challenge` response.
+ :http:statuscode:`204 No content`:
+ Operation successful.
+ :http:statuscode:`404 Not found`:
+ The account pointed by ``$USERNAME`` was not found.
+ :http:statuscode:`401 Unauthorized`:
+ Invalid credentials or missing rights.
+ :http:statuscode:`409 Conflict`:
+ * ``TALER_EC_BANK_NON_ADMIN_PATCH_MISSING_OLD_PASSWORD``: a non-admin user has tried to change their password whihout providing the current one.
+ * ``TALER_EC_BANK_PATCH_BAD_OLD_PASSWORD`` : provided old password does not match current password.
.. _account-list:
-.. http:get:: ${BANK_API_BASE_URL}/public-accounts
+.. http:get:: /public-accounts
Show those accounts whose histories are publicly visible. For example,
accounts from donation receivers. As such, this request is unauthenticated.
-
- **Request:**
- :query start: *Optional.*
- Row identifier to explicitly set the *starting point* of the query.
- :query delta: *Optional.*
- The *delta* value that determines the range of the query.
+ **Request:**
- **Response**
+ :query delta: *Optional.*
+ Takes value of the form ``N (-N)``, so that at most ``N`` values strictly older (younger) than ``start`` are returned. Defaults to ``-20`` to return the last 20 entries.
+ :query start: *Optional.*
+ Row number threshold, see ``delta`` for its interpretation. Defaults to smallest or biggest row id possible according to ``delta`` sign.
+ :query filter_name: *Optional.*
+ Pattern to filter on the account legal name. Given
+ the filter 'foo', all the results will **contain**
+ 'foo' in their legal name. Without this option,
+ all the existing accounts are returned.
+
+ **Response:**
- **Details**
+ :http:statuscode:`200 OK`:
+ Response is a `PublicAccountsResponse`.
+ :http:statuscode:`204 No content`:
+ No public account.
+
+ **Details:**
.. ts:def:: PublicAccountsResponse
@@ -325,245 +376,292 @@ Account Management
.. ts:def:: PublicAccount
interface PublicAccount {
+ // Username of the account
+ username: string;
+
+ // Internal payto URI of this bank account.
payto_uri: string;
+ // Current balance of the account
balance: Balance;
- // The account name (=username) of the
- // bank account.
- account_name: string;
- }
+ // Is this a taler exchange account?
+ is_taler_exchange: boolean;
- :http:statuscode:`200 OK`:
- Response is a `PublicAccountsResponse`.
- :http:statuscode:`204 No content`:
- No public account.
+ // Opaque unique ID used for pagination.
+ // @since v4, will become mandatory in the next version.
+ row_id?: Integer;
+ }
.. http:get:: /accounts
- Obtains a list of the accounts registered at the bank.
- It returns only the information that this API handles, without
- any balance or transactions list.
- This request is only available to the administrator.
+ Obtains a list of the accounts registered at the bank.
+ It returns only the information that this API handles, without
+ any balance or transactions list.
+ This request is only available to the administrator.
+
+ **Request:**
+
+ :query delta: *Optional.*
+ Takes value of the form ``N (-N)``, so that at most ``N`` values strictly older (younger) than ``start`` are returned. Defaults to ``-20`` to return the last 20 entries.
+ :query start: *Optional.*
+ Row number threshold, see ``delta`` for its interpretation. Defaults to smallest or biggest row id possible according to ``delta`` sign.
+ :query filter_name: *Optional.*
+ Pattern to filter on the account legal name. Given
+ the filter 'foo', all the results will **contain**
+ 'foo' in their legal name. Without this option,
+ all the existing accounts are returned.
+
+ **Response:**
+
+ :http:statuscode:`200 OK`:
+ At least one account was found.
+ The server responds with a `ListBankAccountsResponse` object.
+ :http:statuscode:`204 No Content`:
+ No accounts were found for the given request.
+ :http:statuscode:`401 Unauthorized`:
+ Invalid credentials or missing rights.
- **Request:**
+ **Details:**
- :query filter_name: *Optional.*
- Pattern to filter on the account legal name. Given
- the filter 'foo', all the results will **contain**
- 'foo' in their legal name. Without this option,
- all the existing accounts are returned.
+ .. ts:def:: ListBankAccountsResponse
- **Response:**
+ interfaces ListBankAccountsResponse {
+ accounts: AccountMinimalData[];
+ }
- :http:statuscode:`200 OK`:
- At least one account was found.
- The server responds with a `ListBankAccountsResponse` object.
- :http:statuscode:`204 No Content`:
- No accounts were found for the given request.
- :http:statuscode:`403 Forbidden`:
- A ordinary user invoked this call.
+ .. ts:def:: Balance
- **Details:**
+ interface Balance {
+ amount: Amount;
+ credit_debit_indicator: "credit" | "debit";
+ }
- .. ts:def:: ListBankAccountsResponse
+ .. ts:def:: AccountMinimalData
- interfaces ListBankAccountsResponse {
- accounts: AccountMinimalData[];
- }
+ interface AccountMinimalData {
+ // Username of the account
+ username: string;
- .. ts:def:: Balance
+ // Legal name of the account owner.
+ name: string;
- interface Balance {
- amount: Amount;
- credit_debit_indicator: "credit" | "debit";
- }
+ // Internal payto URI of this bank account.
+ payto_uri: string;
- .. ts:def:: AccountMinimalData
+ // Current balance of the account
+ balance: Balance;
- interface AccountMinimalData {
- // Username
- username: string;
+ // Number indicating the max debit allowed for the requesting user.
+ debit_threshold: Amount;
- // Legal name of the account owner.
- name: string;
+ // Is this account visible to anyone?
+ is_public: boolean;
- // current balance of the account
- balance: Balance;
+ // Is this a taler exchange account?
+ is_taler_exchange: boolean;
- // Number indicating the max debit allowed for the requesting user.
- debit_threshold: Amount;
- }
+ // Opaque unique ID used for pagination.
+ // @since v4, will become mandatory in the next version.
+ row_id?: Integer;
+ }
.. _bank-account-info:
.. http:get:: /accounts/$USERNAME
- Obtains information relative to the account owned by
- ``$USERNAME``. The request is available to the administrator
- and ``$USERNAME`` itself.
+ Obtains information relative to the account owned by
+ ``$USERNAME``. The request is available to the administrator
+ and ``$USERNAME`` itself.
- **Response:**
+ **Response:**
:http:statuscode:`200 OK`:
The bank responds with an `AccountData` object.
:http:statuscode:`401 Unauthorized`:
- Invalid credentials.
- :http:statuscode:`403 Forbidden`:
- Credentials are valid but this user has no permission to the
- the account info.
+ Invalid credentials or missing rights.
:http:statuscode:`404 Not found`:
- Username not found
+ The account pointed by ``$USERNAME`` was not found.
- **Details:**
+ **Details:**
- .. ts:def:: AccountData
+ .. ts:def:: AccountData
- interface AccountData {
- // Legal name of the account owner.
- name: string;
+ interface AccountData {
+ // Legal name of the account owner.
+ name: string;
- // Available balance on the account.
- balance: Balance;
+ // Available balance on the account.
+ balance: Balance;
- // payto://-URI of the account.
- payto_uri: string;
+ // payto://-URI of the account.
+ payto_uri: string;
- // Number indicating the max debit allowed for the requesting user.
- debit_threshold: Amount;
+ // Number indicating the max debit allowed for the requesting user.
+ debit_threshold: Amount;
- contact_data?: ChallengeContactData;
+ // Addresses where to send the TAN for transactions.
+ // Currently only used for cashouts.
+ // If missing, cashouts will fail.
+ // In the future, might be used for other transactions
+ // as well.
+ contact_data?: ChallengeContactData;
- // 'payto' address pointing the bank account
- // where to send cashouts. This field is optional
- // because not all the accounts are required to participate
- // in the merchants' circuit. One example is the exchange:
- // that never cashouts. Registering these accounts can
- // be done via the access API.
- cashout_payto_uri?: string;
- }
+ // IBAN 'payto' URI with a 'receiver-name' parameter of a fiat bank
+ // account where to send cashouts. This field is optional
+ // because not all the accounts are required to participate
+ // in the merchants' circuit. One example is the exchange:
+ // that never cashouts. Registering these accounts can
+ // be done via the access API.
+ cashout_payto_uri?: string;
-Transactions
-------------
+ // Is this account visible to anyone?
+ is_public: boolean;
-.. http:get:: ${BANK_API_BASE_URL}/accounts/${account_name}/transactions
+ // Is this a taler exchange account?
+ is_taler_exchange: boolean;
- Retrieve a subset of transactions related to $account_name. Without
- query parameters, it returns the last 5 transactions.
+ // Is 2FA enabled and what channel is used for challenges?
+ tan_channel?: TanChannel;
+ }
- The list of returned transactions is determined by a row ID *starting point*
- and a signed non-zero integer *delta*:
+Transactions
+------------
- * If *delta* is positive, return a list of up to *delta* transactions (all matching
- the filter criteria) strictly **after** the starting point. The transactions are sorted
- in **ascending** order of the row ID.
- * If *delta* is negative, return a list of up to *-delta* transactions (all matching
- the filter criteria) strictly **before** the starting point. The transactions are sorted
- in **descending** order of the row ID.
+.. http:get:: /accounts/$USERNAME/transactions
- If *starting point* is not explicitly given, it defaults to:
+ Retrieve a subset of transactions related to $USERNAME.
- * A value that is **smaller** than all other row IDs if *delta* is **positive**.
- * A value that is **larger** than all other row IDs if *delta* is **negative**.
+ The list of returned transactions is determined by a row ID *starting point*
+ and a signed non-zero integer *delta*:
- **Request**
+ * If *delta* is positive, return a list of up to *delta* transactions (all matching
+ the filter criteria) strictly **after** the starting point. The transactions are sorted
+ in **ascending** order of the row ID.
+ * If *delta* is negative, return a list of up to *-delta* transactions (all matching
+ the filter criteria) strictly **before** the starting point. The transactions are sorted
+ in **descending** order of the row ID.
- :query long_poll_ms: Optional number to express how many milliseconds the server
- should wait for at least one result to be shown. If not given, the server
- responds immediately, regardless of the result.
- :query start: *Optional.*
- Row identifier to explicitly set the *starting point* of the query.
- :query delta: *Optional.*
- The *delta* value that determines the range of the query.
+ If *starting point* is not explicitly given, it defaults to:
- **Response**
+ * A value that is **smaller** than all other row IDs if *delta* is **positive**.
+ * A value that is **larger** than all other row IDs if *delta* is **negative**.
- .. ts:def:: BankAccountTransactionsResponse
+ **Request:**
+
+ :query delta: *Optional.*
+ Takes value of the form ``N (-N)``, so that at most ``N`` values strictly older (younger) than ``start`` are returned. Defaults to ``-20`` to return the last 20 entries.
+ :query start: *Optional.*
+ Row number threshold, see ``delta`` for its interpretation. Defaults to smallest or biggest row id possible according to ``delta`` sign.
+ :query long_poll_ms: Optional number to express how many milliseconds the server
+ should wait for at least one result to be shown. If not given, the server
+ responds immediately, regardless of the result.
- interface BankAccountTransactionsResponse {
- transactions: BankAccountTransactionInfo[];
- }
+ **Response:**
:http:statuscode:`200 OK`:
The bank responds with an `BankAccountTransactionsResponse` object.
:http:statuscode:`204 No content`:
No transaction found.
:http:statuscode:`401 Unauthorized`:
- Invalid credentails
+ Invalid credentials or missing rights.
:http:statuscode:`404 Not found`:
- Username not found
-
-.. http:get:: ${BANK_API_BASE_URL}/accounts/${account_name}/transactions/${transaction_id}
-
- **Response**
+ The account pointed by ``$USERNAME`` was not found.
- Retrieve the transaction whose identifier is ``transaction_id``,
- in the following format:
+ **Details:**
- .. ts:def:: BankAccountTransactionInfo
+ .. ts:def:: BankAccountTransactionsResponse
- interface BankAccountTransactionInfo {
- creditor_payto_uri: string;
- debtor_payto_uri: string;
+ interface BankAccountTransactionsResponse {
+ transactions: BankAccountTransactionInfo[];
+ }
- amount: Amount;
- direction: "debit" | "credit";
+.. http:get:: /accounts/$USERNAME/transactions/$TRANSACTION_ID
- subject: string;
+ Retrieve the transaction whose identifier is ``TRANSACTION_ID``.
- // Transaction unique ID. Matches
- // $transaction_id from the URI.
- row_id: number;
- date: Timestamp;
- }
+ **Response:**
:http:statuscode:`200 OK`:
The bank responds with an `BankAccountTransactionInfo` object.
- :http:statuscode:`404 Not found`:
- Username not found
:http:statuscode:`401 Unauthorized`:
- Invalid credentials.
+ Invalid credentials or missing rights.
+ :http:statuscode:`404 Not found`:
+ The account pointed by ``$USERNAME`` was not found.
+ **Details:**
-.. http:post:: ${BANK_API_BASE_URL}/accounts/${account_name}/transactions
+ .. ts:def:: BankAccountTransactionInfo
- Create a new transaction where the bank account with the label ``account_name`` is **debited**.
+ interface BankAccountTransactionInfo {
+ creditor_payto_uri: string;
+ debtor_payto_uri: string;
- **Request**
+ amount: Amount;
+ direction: "debit" | "credit";
- .. ts:def:: BankAccountTransactionCreate
+ subject: string;
- interface CreateBankAccountTransactionCreate {
+ // Transaction unique ID. Matches
+ // $TRANSACTION_ID from the URI.
+ row_id: Integer;
+ date: Timestamp;
+ }
- // Address in the Payto format of the wire transfer receiver.
- // It needs at least the 'message' query string parameter.
- payto_uri: string;
+.. http:post:: /accounts/$USERNAME/transactions
- // Transaction amount (in the $currency:x.y format), optional.
- // However, when not given, its value must occupy the 'amount'
- // query string parameter of the 'payto' field. In case it
- // is given in both places, the payto_uri's takes the precedence.
- amount: string;
- }
+ Create a new transaction where the bank account with the label ``USERNAME`` is **debited**.
- **Response**
+ **Request:**
- :http:statuscode:`204 No content`:
- the transaction has been created.
+ .. ts:def:: CreateTransactionRequest
+
+ interface CreateTransactionRequest {
+ // Address in the Payto format of the wire transfer receiver.
+ // It needs at least the 'message' query string parameter.
+ payto_uri: string;
+
+ // Transaction amount (in the $currency:x.y format), optional.
+ // However, when not given, its value must occupy the 'amount'
+ // query string parameter of the 'payto' field. In case it
+ // is given in both places, the payto_uri's takes the precedence.
+ amount: string;
+ }
+
+ **Response:**
+
+ :http:statuscode:`200 Ok`:
+ The bank responds with an `CreateTransactionResponse` object.
+ :http:statuscode:`202 Accepted`:
+ 2FA is required for this operation. This returns the `Challenge` response.
:http:statuscode:`400 Bad Request`:
- the request was invalid or the payto://-URI used unacceptable features.
+ The request was invalid or the payto://-URI used unacceptable features.
:http:statuscode:`401 Unauthorized`:
Invalid credentials.
+ :http:statuscode:`404 Not found`:
+ The account pointed by ``$USERNAME`` was not found.
+ :http:statuscode:`409 Conflict`:
+ * ``TALER_EC_BANK_SAME_ACCOUNT`` : creditor account is the same than ``USERNAME``.
+ * ``TALER_EC_BANK_UNKNOWN_CREDITOR`` : creditor account was not found.
+ * ``TALER_EC_BANK_UNALLOWED_DEBIT`` : the account does not have sufficient funds.
+
+ **Details:**
+ .. ts:def:: CreateTransactionResponse
+
+ interface CreateTransactionResponse {
+ // ID identifying the transaction being created
+ row_id: Integer;
+ }
Taler Withdrawals
-----------------
-.. http:post:: ${BANK_API_BASE_URL}/accounts/${account_name}/withdrawals
+.. http:post:: /accounts/$USERNAME/withdrawals
Create a withdrawal operation, resulting in a ``taler://withdraw`` URI.
- **Request**
+ **Request:**
.. ts:def:: BankAccountCreateWithdrawalRequest
@@ -572,91 +670,110 @@ Taler Withdrawals
amount: Amount;
}
- **Response**
+ **Response:**
+
+ :http:statuscode:`200 Ok`:
+ The bank responds with an `BankAccountCreateWithdrawalResponse` object.
+ :http:statuscode:`404 Not found`:
+ The account pointed by ``$USERNAME`` was not found.
+ :http:statuscode:`409 Conflict`:
+ The account does not have sufficient funds.
+
+ **Details:**
.. ts:def:: BankAccountCreateWithdrawalResponse
interface BankAccountCreateWithdrawalResponse {
- // ID of the withdrawal, can be used to view/modify the withdrawal operation.
- // This ID will be globally unique and grant control over the operation to
- // abort or confirm it.
+ // ID identifying the operation being created
withdrawal_id: string;
- // URI that can be passed to the wallet to initiate the withdrawal.
+ // URI that can be passed to the wallet to initiate the withdrawal
taler_withdraw_uri: string;
- }
+ }
- :http:statuscode:`200 Ok`:
- The bank responds with an `BankAccountCreateWithdrawalResponse` object.
- :http:statuscode:`403 Forbidden`:
- The operation was rejected due to insufficient funds.
+.. http:post:: /accounts/$USERNAME/withdrawals/$WITHDRAWAL_ID/confirm
-.. http:get:: ${BANK_API_BASE_URL}/withdrawals/${withdrawal_id}
+ Confirms ``WITHDRAWAL_ID`` operation. Has no effect on an already confirmed
+ withdrawal operation. This call is responsible for wiring the funds to the
+ exchange.
- Query the status of a withdrawal operation. Does not require further
- authentication as knowledge of the withdrawal ID serves as an authenticator.
+ **Response:**
- **Response**
+ :http:statuscode:`202 Accepted`:
+ 2FA is required for this operation. This returns the `Challenge` response.
+ :http:statuscode:`204 No content`:
+ The withdrawal operation has been confirmed.
+ :http:statuscode:`404 Not found`:
+ The operation was not found.
+ :http:statuscode:`409 Conflict`:
+ * ``TALER_EC_BANK_CONFIRM_ABORT_CONFLICT`` : the withdrawal has been aborted previously and can't be confirmed.
+ * ``TALER_EC_BANK_CONFIRM_INCOMPLETE`` : the withdraw operation cannot be confirmed because no exchange and reserve public key selection happened before.
+ * ``TALER_EC_BANK_UNALLOWED_DEBIT`` : the account does not have sufficient funds.
- **Details**
+.. http:post:: /accounts/$USERNAME/withdrawals/$WITHDRAWAL_ID/abort
- .. ts:def:: BankAccountGetWithdrawalResponse
+ Aborts ``WITHDRAWAL_ID`` operation. Has no effect on an already aborted
+ operation.
- interface BankAccountGetWithdrawalResponse {
- // Amount that will be withdrawn with this withdrawal operation.
- amount: Amount;
+ **Response:**
- // Was the withdrawal aborted?
- aborted: boolean;
+ :http:statuscode:`204 No content`:
+ The withdrawal operation has been aborted.
+ :http:statuscode:`404 Not found`:
+ The withdrawal operation was not found.
+ :http:statuscode:`409 Conflict`:
+ The withdrawal operation has been confirmed previously and can't be aborted.
- // Has the withdrawal been confirmed by the bank?
- // The wire transfer for a withdrawal is only executed once
- // both ``confirmation_done`` is ``true`` and ``selection_done`` is ``true``.
- confirmation_done: boolean;
+.. http:get:: /withdrawals/$WITHDRAWAL_ID
- // Did the wallet select reserve details?
- selection_done: boolean;
+ Retrieve public information about ``WITHDRAWAL_ID`` withdrawal operation.
+ Does not require further authentication as knowledge of ``WITHDRAWAL_ID``
+ serves as an authenticator.
- // Reserve public key selected by the exchange,
- // only non-null if ``selection_done`` is ``true``.
- selected_reserve_pub: string | null;
+ **Request:**
- // Exchange account selected by the wallet, or by the bank
- // (with the default exchange) in case the wallet did not provide one
- // through the Integration API.
- selected_exchange_account: string | null;
- }
+ :query long_poll_ms:
+ *Optional.* If specified, the bank will wait up to ``long_poll_ms``
+ milliseconds for operationt state to be different from ``old_state`` before sending the HTTP
+ response. A client must never rely on this behavior, as the bank may
+ return a response immediately.
+ :query old_state:
+ *Optional.* Default to "pending".
+
+ **Response:**
:http:statuscode:`200 Ok`:
- The bank responds with an `BankAccountGetWithdrawalResponse` object.
+ The bank responds with an `WithdrawalPublicInfo` object.
:http:statuscode:`404 Not found`:
The operation was not found.
-.. http:post:: ${BANK_API_BASE_URL}/withdrawals/${withdrawal_id}/abort
+ **Details:**
- Abort a withdrawal operation. Has no effect on an already aborted
- withdrawal operation. Does not require further authentication as knowledge
- of the withdrawal ID serves as an authenticator.
+ .. ts:def:: WithdrawalPublicInfo
- :http:statuscode:`204 No content`: The withdrawal operation has been aborted. The response is an empty JSON object.
- :http:statuscode:`409 Conflict`: The reserve operation has been confirmed previously and can't be aborted.
+ interface WithdrawalPublicInfo {
+ // Current status of the operation
+ // pending: the operation is pending parameters selection (exchange and reserve public key)
+ // selected: the operations has been selected and is pending confirmation
+ // aborted: the operation has been aborted
+ // confirmed: the transfer has been confirmed and registered by the bank
+ status: "pending" | "selected" | "aborted" | "confirmed";
+ // Amount that will be withdrawn with this operation
+ // (raw amount without fee considerations).
+ amount: Amount;
-.. http:post:: ${BANK_API_BASE_URL}/withdrawals/${withdrawal_id}/confirm
-
- Confirm a withdrawal operation. Has no effect on an already confirmed
- withdrawal operation. This call is responsible for wiring the funds to the
- exchange. Does not require further authentication as knowledge of the
- withdrawal ID serves as an authenticator.
+ // Account username
+ username: string;
- **Response**
+ // Reserve public key selected by the exchange,
+ // only non-null if ``status`` is ``selected`` or ``confirmed``.
+ selected_reserve_pub?: string;
- :http:statuscode:`204 No content`:
- The withdrawal operation has been confirmed. The response is an empty JSON object.
- :http:statuscode:`409 Conflict`:
- The withdrawal has been aborted previously and can't be confirmed.
- :http:statuscode:`422 Unprocessable Entity` (New):
- The withdraw operation cannot be confirmed because no exchange and reserve public key selection happened before.
+ // Exchange account selected by the wallet
+ // only non-null if ``status`` is ``selected`` or ``confirmed``.
+ selected_exchange_account?: string;
+ }
Cashouts
--------
@@ -665,223 +782,135 @@ Cashouts
.. http:post:: /accounts/$USERNAME/cashouts
- Initiates a conversion to fiat currency. The external
- bank account to be
- credited is the one specified at registration time via the
- *cashout_address* parameter. The bank internal account
- is specified via ``$USERNAME``.
- The bank sends a TAN to the customer to let them confirm the
- operation. The request is only available to ordinary users, not
- to the administrator.
-
- .. note::
-
- Consult the `cashout rates call <cashout-rates_>`_ to learn
- about any applicable fee or exchange rate.
-
- .. note::
-
- FIXME: Eventually, the env variables will be replaced with
- configuration settings.
-
- To test this operation without relying on any SMS/E-mail provider,
- Libeufin offers two methods: defining an environment variable called
- ``LIBEUFIN_CASHOUT_TEST_TAN`` or specifying the value ``file`` to
- the ``tan_channel`` field of the `request object <cashout-request_>`_.
- Assuming ``LIBEUFIN_CASHOUT_TEST_TAN`` is set to *T*, every */confirm*
- operation can use *T* as the TAN. Setting instead the ``tan_channel``
- field to ``file`` will cause the server to (over)write every TAN to
- ``/tmp/cashout-tan.txt``. If both are used, the environment
- variable takes the precedence.
-
-
- **Request:**
-
- :query start: *Optional.*
- Row identifier to explicitly set the *starting point* of the query.
- :query delta: *Optional.*
- The *delta* value that determines the range of the query.
-
- `CashoutRequest <cashout-request_>`_
-
- .. ts:def:: TanChannel
-
- enum TanChannel {
- SMS = "sms",
- EMAIL = "email",
- FILE = "file"
- }
+ Initiates a conversion to fiat currency. The fiat
+ bank account to be
+ credited is the one specified at registration time via the
+ *cashout_payto_uri* parameter. The regional bank account
+ is specified via ``$USERNAME``.
- .. _cashout-request:
-
- .. ts:def:: CashoutRequest
-
- interface CashoutRequest {
-
- // Optional subject to associate to the
- // cashout operation. This data will appear
- // as the incoming wire transfer subject in
- // the user's external bank account.
- subject?: string;
-
- // That is the plain amount that the user specified
- // to cashout. Its $currency is the (regional) currency of the
- // bank instance.
- amount_debit: Amount;
+ .. note::
- // That is the amount that will effectively be
- // transferred by the bank to the user's bank
- // account, that is external to the regional currency.
- // It is expressed in the fiat currency and
- // is calculated after the cashout fee and the
- // exchange rate. See the /cashout-rates call.
- // The client needs to calculate this amount
- // correctly based on the amount_debit and the cashout rate,
- // otherwise the request will fail.
- amount_credit: Amount;
+ Consult the `cashout rates call <cashout-rates_>`_ to learn
+ about any applicable fee or exchange rate.
- // Which channel the TAN should be sent to. If
- // this field is missing, it defaults to SMS.
- // The default choice prefers to change the communication
- // channel respect to the one used to issue this request.
- tan_channel?: TanChannel;
- }
- **Response:**
+ **Request:**
- :http:statuscode:`202 Accepted`:
- The cashout request was correctly created and
- the TAN authentication now is pending.
- This returns the `CashoutPending` response.
- :http:statuscode:`409 Conflict`:
- The user did not share any contact data where to send the TAN,
- the account does not have sufficient funds, or the
- exchange rate was calculated incorrectly by the client.
- :http:statuscode:`503 Service unavailable`:
- The bank does not support the TAN channel for this operation.
- The bank does not support cashout, client should check config response.
+ .. ts:def:: CashoutRequest
+ interface CashoutRequest {
+ // Nonce to make the request idempotent. Requests with the same
+ // ``request_uid`` that differ in any of the other fields
+ // are rejected.
+ request_uid: ShortHashCode;
- **Details:**
+ // Optional subject to associate to the
+ // cashout operation. This data will appear
+ // as the incoming wire transfer subject in
+ // the user's fiat bank account.
+ subject?: string;
- .. ts:def:: CashoutPending
+ // That is the plain amount that the user specified
+ // to cashout. Its $currency is the (regional) currency of the
+ // bank instance.
+ amount_debit: Amount;
- interface CashoutPending {
- // ID identifying the operation being created
- // and now waiting for the TAN confirmation.
- cashout_id: string;
- }
+ // That is the amount that will effectively be
+ // transferred by the bank to the user's fiat bank
+ // account.
+ // It is expressed in the fiat currency and
+ // is calculated after the cashout fee and the
+ // exchange rate. See the /cashout-rate call.
+ // The client needs to calculate this amount
+ // correctly based on the amount_debit and the cashout rate,
+ // otherwise the request will fail.
+ amount_credit: Amount;
+ }
+ **Response:**
-.. _cashout-abort:
+ :http:statuscode:`200 OK`:
+ The cashout request was correctly created.
+ This returns the `CashoutPending` response.
+ :http:statuscode:`202 Accepted`:
+ 2FA is required for this operation. This returns the `Challenge` response.
+ :http:statuscode:`404 Not found`:
+ The account pointed by ``$USERNAME`` was not found.
+ :http:statuscode:`409 Conflict`:
+ * ``TALER_EC_BANK_TRANSFER_REQUEST_UID_REUSED``: an operation with the same ``request_uid`` but different details has been submitted before.
+ * ``TALER_EC_BANK_BAD_CONVERSION`` : exchange rate was calculated incorrectly by the client.
+ * ``TALER_EC_BANK_UNALLOWED_DEBIT`` : the account does not have sufficient funds.
+ * ``TALER_EC_BANK_CONFIRM_INCOMPLETE`` : the user did not share any cashout payto to uri where to wire funds.
+ :http:statuscode:`501 Not Implemented`:
+ * ``TALER_EC_BANK_TAN_CHANNEL_NOT_SUPPORTED``: the chosen ``tan_channel`` is not currently supported.
+ * This server does not support conversion, client should check config response.
-.. http:post:: /accounts/$USERNAME/cashouts/$CASHOUT_ID/abort
+ **Details:**
- Aborts the ``$CASHOUT_ID`` operation.
+ .. ts:def:: CashoutResponse
- **Response:**
+ interface CashoutResponse {
+ // ID identifying the operation being created
+ cashout_id: Integer;
+ }
- :http:statuscode:`204 No content`:
- ``$CASHOUT_ID`` was found in the *pending* state
- and got successfully aborted.
- :http:statuscode:`404 Not found`:
- ``$CASHOUT_ID`` is not found. Note: that happens
- also when ``$CASHOUT_ID`` got aborted before this request.
- :http:statuscode:`409 Conflict`:
- ``$CASHOUT_ID`` was already confirmed.
- :http:statuscode:`503 Service unavailable`:
- This server does not support cashout, client should check config response.
+.. _circuit-cashout-details:
+.. http:get:: /accounts/$USERNAME/cashouts/$CASHOUT_ID
-.. _cashout-confirm:
+ Returns information about the status of the ``$CASHOUT_ID`` operation.
+ The request is available to the administrator and the account owner.
-.. http:post:: /accounts/$USERNAME/cashouts/$CASHOUT_ID/confirm
+ **Response:**
- Confirms the ``$CASHOUT_ID`` operation by providing its
- TAN. The request should still be authenticated with
- the users credentials.
+ :http:statuscode:`200 OK`:
+ Response is a `CashoutStatusResponse`.
+ :http:statuscode:`404 Not found`:
+ The cashout operation was not found.
+ :http:statuscode:`501 Not implemented`:
+ This server does not support conversion, client should check config response.
- **Request:**
+ **Details:**
- .. ts:def:: CashoutConfirm
+ .. ts:def:: CashoutStatusResponse
- interface CashoutConfirm {
- // the TAN that confirms $CASHOUT_ID.
- tan: string;
- }
+ interface CashoutStatusResponse {
+ // Amount debited to the regional bank account.
+ amount_debit: Amount;
- **Response:**
+ // Amount credited to the fiat bank account.
+ amount_credit: Amount;
- :http:statuscode:`204 No content`:
- The request succeeded, either for the first time, or it already was
- confirmed previously (idempotency!).
- :http:statuscode:`403 Forbidden`:
- Wrong TAN or bad credentials.
- :http:statuscode:`404 Not found`:
- ``$CASHOUT_ID`` is not found. Note: that happens
- also when ``$CASHOUT_ID`` got aborted before this request.
- :http:statuscode:`409 Conflict`:
- The user changed their cash-out address between the creation and the confirmation of ``$CASHOUT_ID``.
- :http:statuscode:`503 Service unavailable`:
- This server does not support cashout, client should check config response.
+ // Transaction subject.
+ subject: string;
-.. _cashout-rates:
+ // Time when the cashout was created.
+ creation_time: Timestamp;
+ }
-.. http:get:: /cashout-rate
+.. _circuit-cashouts:
- This public endpoint allows clients to calculate
- the exchange rate between the regional currency
- and the external banking system.
+.. http:get:: /accounts/$USERNAME/cashouts
- This endpoint shows how the bank would apply the cash-out
- ratio and fee to one input amount. Typically, frontends
- ask this endpoint before creating cash-out operations.
- At least one of the two query parameters must be provided. If both are
- given, then the server checks their correctness. Amounts must include the
- currency.
+ Returns the list of all cash-out operations for an account.
**Request:**
- :query amount_debit: this is the amount that the user will get
- deducted from their regional bank account.
-
- :query amount_credit: this is the amount that the user will receive
- in their fiat bank account.
+ :query delta: *Optional.*
+ Takes value of the form ``N (-N)``, so that at most ``N`` values strictly older (younger) than ``start`` are returned. Defaults to ``-20`` to return the last 20 entries.
+ :query start: *Optional.*
+ Row number threshold, see ``delta`` for its interpretation. Defaults to smallest or biggest row id possible according to ``delta`` sign.
**Response:**
- .. ts:def:: CashoutConversionResponse
-
- interface CashoutConversionResponse {
- // Amount that the user will get deducted from their regional
- // bank account, according to the 'amount_credit' value.
- amount_debit: Amount;
- // Amount that the user will receive in their fiat
- // bank account, according to 'amount_debit'.
- amount_credit: Amount;
- }
-
-
:http:statuscode:`200 OK`:
- Response is a `CashoutConversionResponse`.
- :http:statuscode:`400 Bad request`:
- Both parameters have been provided and the calculation is not correct,
- or none of them has been provided, or the requested currency was not
- supported. The response should clarify which case.
- :http:statuscode:`404 Not found`:
- The server does not support local currency conversion.
- :http:statuscode:`503 Service unavailable`:
- This server does not support cashout, client should check config response.
-
-
-.. _circuit-cashouts:
-
-.. http:get:: /accounts/$USERNAME/cashouts
+ Response is a `Cashouts`.
+ :http:statuscode:`204 No Content`:
+ No cash-out operations were found.
+ :http:statuscode:`501 Not implemented`:
+ This server does not support conversion, client should check config response.
- Returns the list of all the (pending and confirmed) cash-out operations
- for an account.
-
- **Response:**
+ **Details:**
.. ts:def:: Cashouts
@@ -893,25 +922,21 @@ Cashouts
.. ts:def:: CashoutInfo
interface CashoutInfo {
- cashout_id: string;
- status: "pending" | "confirmed";
+ cashout_id: Integer;
}
- :http:statuscode:`200 OK`:
- Response is a `Cashouts`.
- :http:statuscode:`204 No Content`:
- No cash-out operations were found at the bank
- :http:statuscode:`404 Not found`:
- Username not fuond.
- :http:statuscode:`503 Service unavailable`:
- This server does not support cashout, client should check config response.
-
.. http:get:: /cashouts
- Returns the list of all the (pending and confirmed) cash-out operations
- for **all** accounts.
+ Returns the list of all cash-out operations for **all** accounts.
+
+ Can only be used by the administrators.
+
+ **Request:**
- Typically can only be used by the administrators.
+ :query delta: *Optional.*
+ Takes value of the form ``N (-N)``, so that at most ``N`` values strictly older (younger) than ``start`` are returned. Defaults to ``-20`` to return the last 20 entries.
+ :query start: *Optional.*
+ Row number threshold, see ``delta`` for its interpretation. Defaults to smallest or biggest row id possible according to ``delta`` sign.
.. note::
@@ -920,77 +945,106 @@ Cashouts
**Response:**
+ :http:statuscode:`200 OK`:
+ Response is a `GlobalCashouts`.
+ :http:statuscode:`204 No Content`:
+ No cash-out operations were found.
+ :http:statuscode:`501 Not implemented`:
+ This server does not support conversion, client should check config response.
+
+ **Details:**
+
.. ts:def:: GlobalCashouts
interface GlobalCashouts {
- // Every string represents a cash-out operation ID.
- cashouts: { cashout_id: string, username: string}[];
+ cashouts: GlobalCashoutInfo[];
}
.. ts:def:: GlobalCashoutInfo
interface GlobalCashoutInfo {
- cashout_id: string;
+ cashout_id: Integer;
username: string;
- status: "pending" | "confirmed";
}
- :http:statuscode:`200 OK`:
- Response is a `GlobalCashouts`.
- :http:statuscode:`204 No Content`:
- No cash-out operations were found at the bank
- :http:statuscode:`503 Service unavailable`:
- This server does not support cashout, client should check config response.
+.. _cashout-rates:
-.. _circuit-cashout-details:
+2FA
+---
-.. http:get:: /accounts/$USERNAME/cashouts/$CASHOUT_ID
+.. http:post:: /accounts/$USERNAME/challenge/$CHALLENGE_ID
- Returns information about the status of the ``$CASHOUT_ID`` operation.
- The request is available to the administrator and the account owner.
+ Send TAN code for the ``CHALLENGE_ID`` challenge.
+
+ This request can be posted several times to trigger TAN retransmission when the current code has expired or too many confirmation attempts have been made.
**Response:**
- `CashoutStatusResponse <cashout-status_>`_
+ :http:statuscode:`200 OK`:
+ The TAN code have been sent. This returns `TanTransmission` response.
+ :http:statuscode:`401 Unauthorized`:
+ Invalid credentials or missing rights.
+ :http:statuscode:`404 Not Found`:
+ The challenge was not found.
+ :http:statuscode:`502 Bad Gateway`:
+ * ``TALER_EC_BANK_TAN_CHANNEL_SCRIPT_FAILED``: TAN transmition via ``tan_channel`` failed.
- .. _cashout-status:
+ **Details:**
- .. ts:def:: CashoutStatus
+ .. ts:def:: TanTransmission
- interface CashoutStatusResponse {
- status: "pending" | "confirmed";
+ interface TanTransmission {
+ // Channel of the last successful transmission of the TAN challenge.
+ tan_channel: TanChannel;
- // Amount debited to the internal
- // regional currency bank account.
- amount_debit: Amount;
+ // Info of the last successful transmission of the TAN challenge.
+ tan_info: string;
+ }
- // Amount credited to the external bank account.
- amount_credit: Amount;
+ .. ts:def:: Challenge
- // Transaction subject.
- subject: string;
+ interface Challenge {
+ // Unique identifier of the challenge to solve to run this protected
+ // operation.
+ challenge_id: string;
+ }
- // Fiat bank account that will receive the cashed out amount.
- // Specified as a payto URI.
- credit_payto_uri: string;
+ .. ts:def:: TanChannel
- // Time when the cashout was created.
- creation_time: Timestamp;
+ enum TanChannel {
+ SMS = "sms",
+ EMAIL = "email"
+ }
+
+
+.. http:post:: /accounts/$USERNAME/challenge/$CHALLENGE_ID/confirm
+
+ Solves the ``CHALLENGE_ID`` challenge and allows performing the protected operation.
+
+ When the challenge is confirmed, you can call the protected endpoint again with ``CHALLENGE_ID`` in the ``X-Challenge-Id`` HTTP header and an empty request body.
+
+ **Request:**
+
+ .. ts:def:: ChallengeSolve
- // Time when the cashout was confirmed via its TAN.
- // Missing when the operation wasn't confirmed yet.
- confirmation_time?: Timestamp;
+ interface ChallengeSolve {
+ // The TAN code that solves $CHALLENGE_ID
+ tan: string;
}
**Response:**
- :http:statuscode:`200 OK`:
- Response is a `CashoutStatusResponse`.
- :http:statuscode:`404 Not found`:
- The cashout operation was not found.
- Aborted cashout operations will also not be found.
- :http:statuscode:`503 Service unavailable`:
- This server does not support cashout, client should check config response.
+ :http:statuscode:`204 No Content`:
+ The challenge is confirmed.
+ :http:statuscode:`401 Unauthorized`:
+ Invalid credentials or missing rights.
+ :http:statuscode:`404 Not Found`:
+ The challenge was not found.
+ :http:statuscode:`409 Conflict`:
+ * ``TALER_EC_BANK_TAN_CHALLENGE_FAILED`` : wrong TAN.
+ * ``TALER_EC_BANK_TAN_CHALLENGE_EXPIRED`` : expired TAN.
+ :http:statuscode:`429 Too many requests`:
+ Too many failed confirmation attempts, a new TAN must be requested.
Monitor
@@ -1001,8 +1055,8 @@ Monitor
When the bank provides conversion between the local currency and an
external one, this call lets the bank administrator monitor the cashin
and cashout operations that were made from and to the external currency.
- It shows as well figures related to (internal) payments made by a Taler
- exchange component to merchant bank accounts. Timeframes are in UTC.
+ It shows as well figures related to internal payments made by a Taler
+ exchange component to internal bank accounts. Timeframes are in UTC.
**Request:**
@@ -1013,7 +1067,6 @@ Monitor
* day
* month
* year
- * decade
:query which: *Optional*.
This parameter points at a particular element of the *timeframe* parameter.
@@ -1024,18 +1077,15 @@ Monitor
* day: from 1 to the last day of the current month.
* month: from 1 to 12
* year: Gregorian year in the YYYY format.
- * decade: the least Y0 digits of a Gregorian year. Banks should treat such decades as starting from the year 2000. For example, if Y=2, this decade denotes the years 2020 to 2029.
**Response:**
- :http:statuscode:`200 OK`:
+ :http:statuscode:`200 OK`:
The bank responds with `MonitorResponse`.
-
:http:statuscode:`400 Bad Request`:
This error may indicate that the *which* parameter is not appropriate for the selected *timeframe*. For example, timeframe=month and which=20 would result in this error.
- :http:statuscode:`503 Service unavailable`:
- The bank doesn't have the conversion service.
+ **Details:**
.. note::
@@ -1044,49 +1094,84 @@ Monitor
.. ts:def:: MonitorResponse
- interface MonitorResponse {
+ // Union discriminated by the "type" field.
+ type MonitorResponse =
+ | MonitorNoConversion
+ | MonitorWithConversion;
+
+ .. ts:def:: MonitorNoConversion
+
+ // Monitoring stats when conversion is not supported
+ interface MonitorNoConversion {
+ type: "no-conversions";
+
+ // How many payments were made to a Taler exchange by another
+ // bank account.
+ talerInCount: Integer;
- // This number identifies how many cashin operations
- // took place in the timeframe specified in the request.
- // This number corresponds to how many withdrawals have
- // been initiated by a wallet owner. Note: wallet owners
+ // Overall volume that has been paid to a Taler
+ // exchange by another bank account.
+ talerInVolume: Amount;
+
+ // How many payments were made by a Taler exchange to another
+ // bank account.
+ talerOutCount: Integer;
+
+ // Overall volume that has been paid by a Taler
+ // exchange to another bank account.
+ talerOutVolume: Amount;
+ }
+
+ .. ts:def:: MonitorWithConversion
+
+ // Monitoring stats when conversion is supported
+ interface MonitorWithConversion {
+ type: "with-conversions";
+
+ // How many cashin operations were confirmed by a
+ // wallet owner. Note: wallet owners
// are NOT required to be customers of the libeufin-bank.
- // Only present if conversion is supported
- cashinCount?: number;
-
- // This amount accounts how much external currency has been
- // spent to withdraw Taler coins in the internal currency.
- // The exact amount of internal currency being created can be
- // calculated using the advertised conversion rates.
- // Only present if conversion is supported
- cashinExternalVolume?: Amount;
-
- // This number identifies how many cashout operations were
- // confirmed in the timeframe speficied in the request.
- // Only present if conversion is supported
- cashoutCount?: number;
-
- // This amount corresponds to how much *external* currency was
- // paid by the libeufin-bank administrator to fulfill all the
- // confirmed cashouts related to the timeframe specified in the
- // request.
- // Only present if conversion is supported
- cashoutExternalVolume?: Amount;
-
- // This number identifies how many payments were made by a
- // Taler exchange to a merchant bank account in the internal
- // currency, in the timeframe specified in the request.
- talerPayoutCount: number;
-
- // This amount accounts the overall *internal* currency that
- // has been paid by a Taler exchange to a merchant internal
- // bank account, in the timeframe specified in the request.
- talerPayoutInternalVolume: Amount;
+ cashinCount: Integer;
+
+ // Overall regional currency that has been paid by the regional admin account
+ // to regional bank accounts to fulfill all the confirmed cashin operations.
+ cashinRegionalVolume: Amount;
+
+ // Overall fiat currency that has been paid to the fiat admin account
+ // by fiat bank accounts to fulfill all the confirmed cashin operations.
+ cashinFiatVolume: Amount;
+
+ // How many cashout operations were confirmed.
+ cashoutCount: Integer;
+
+ // Overall regional currency that has been paid to the regional admin account
+ // by fiat bank accounts to fulfill all the confirmed cashout operations.
+ cashoutRegionalVolume: Amount;
+
+ // Overall fiat currency that has been paid by the fiat admin account
+ // to fiat bank accounts to fulfill all the confirmed cashout operations.
+ cashoutFiatVolume: Amount;
+
+ // How many payments were made to a Taler exchange by another
+ // bank account.
+ talerInCount: Integer;
+
+ // Overall volume that has been paid to a Taler
+ // exchange by another bank account.
+ talerInVolume: Amount;
+
+ // How many payments were made by a Taler exchange to another
+ // bank account.
+ talerOutCount: Integer;
+
+ // Overall volume that has been paid by a Taler
+ // exchange to another bank account.
+ talerOutVolume: Amount;
}
-Taler Bank Integration API
---------------------------
+Endpoints for Integrated Sub-APIs
+---------------------------------
.. http:any:: /taler-integration/*
@@ -1094,33 +1179,33 @@ Taler Bank Integration API
:doc:`GNU Taler bank integration API </core/api-bank-integration>`.
This API handles the communication with Taler wallets.
-Taler Wire Gateway API
-----------------------
.. http:any:: /accounts/$USERNAME/taler-wire-gateway/*
All endpoints under this prefix are specified
by the :doc:`GNU Taler wire gateway API </core/api-bank-wire>`.
- The endpoints are only available for accounts configured with ``is_exchange=true``.
+ The endpoints are only available for accounts configured with ``is_taler_exchange=true``.
-Taler Revenue API
-----------------------
.. http:any:: /accounts/$USERNAME/taler-revenue/*
All endpoints under this prefix are specified
by the :doc:`GNU Taler Revenue API </core/api-bank-revenue>`.
-EBICS Host
-----------
-The Taler bank can be configured to serve bank account transactions and allow
-payment initiations via the EBICS protocol.
+.. http:any:: /conversion-info/*
+
+ All endpoints under this prefix are specified
+ by the :doc:`GNU Taler Conversion Info API </core/api-bank-conversion-info>`.
-This is an optional feature, not all implementations of the API support it.
.. http:post:: /ebicshost
EBICS base URL. This URL allows clients to make EBICS requests to one of
the configured EBICS hosts.
+
+ The Taler bank can be configured to serve bank account transactions and
+ allow payment initiations via the EBICS protocol.
+
+ This is an optional feature, not all implementations of the API support it.
diff --git a/core/api-donau.rst b/core/api-donau.rst
index 3684bc97..9ef69c92 100644
--- a/core/api-donau.rst
+++ b/core/api-donau.rst
@@ -26,6 +26,7 @@ The `glossary <https://docs.taler.net/glossary.html#glossary>`_
defines all specific terms used in this section.
.. contents:: Table of Contents
+ :local:
.. _donau-overview:
@@ -41,7 +42,7 @@ The chapters group the families of requests frequently encountered when using th
* :ref:`Issue receipts<donau_issue>`: For use by charities: Issue receipts for blinded unique donor ids.
* :ref:`Submit receipts<donau_submit>`: Receive the receipts and, if valid, add all of it's donation units to the donor total. Returns a signature on the total yearly donation amount, hash of taxid+salt and year.
* :ref:`Charity administration and status information<donau_charity>`:
-
+
* For use by administrators to add/modify a charity
* For use by charities to get their remaining donation volume
@@ -265,7 +266,7 @@ Use the :ref:`charity GET route<donau_charity_get>` to see the remaining donatio
All incoming `BDID` are recorded under the corresponding charity_id by the Donau.
.. http:POST:: /batch-issue/$CHARITY_ID
-
+
Send in a `IssueReceiptsRequest` and ask the Donau to sign all it's contained `BDID`.
**Request:** `IssueReceiptsRequest`
@@ -297,7 +298,7 @@ All incoming `BDID` are recorded under the corresponding charity_id by the Donau
interface BDID {
donau_pub_hash: HashCode;
- taxpayer_blinded_id: BDIDEnvelope;
+ taxpayer_blinded_id: BDIDEnvelope;
}
.. ts:def:: BDIDEnvelope
@@ -338,7 +339,7 @@ All incoming `BDID` are recorded under the corresponding charity_id by the Donau
}
.. ts:def:: DonationReceiptSignature
-
+
.. ts:def:: BlindedDonationReceiptSignature
type BlindedDonationReceiptSignature =
@@ -419,7 +420,7 @@ Submit receipts
Inspired by the Taler exchange :ref:`Deposit<deposit-par>`.
.. http:POST:: /submit
-
+
Send in donation receipts for the past fiscal year, receive signed total back.
**Request:** `SubmitDonationReceiptsRequest`
@@ -440,7 +441,7 @@ Inspired by the Taler exchange :ref:`Deposit<deposit-par>`.
.. ts:def:: SubmitDonationReceiptsRequest
interface SubmitDonationReceiptsRequest{
- // hashed taxpayer ID plus salt
+ // hashed taxpayer ID plus salt
taxnr_hashed: HashCode;
// All donation receipts must be for this year.
year: Integer;
@@ -471,7 +472,7 @@ Inspired by the Taler exchange :ref:`Deposit<deposit-par>`.
}
.. ts:def:: CSDonationSignature
-
+
interface CSDonationSignature {
type: "CS";
@@ -500,9 +501,12 @@ Charity administration and status information
---------------------------------------------
The administration requests require an authorized bearer token to be set in the HTTP "Authorization" Header. This token can be set by a proxy validating authentication/authorization (using e.g. LDAP).
+The GET status requests require an authorized bearer token as well.
.. http:GET:: /charities
+ GET all charities. Only allowed if the request comes with the administration bearer token.
+
return all charities
**Request:**
@@ -510,7 +514,7 @@ The administration requests require an authorized bearer token to be set in the
**Reponse:**
:http:statuscode:`200 OK`:
- The request was successful, and the response is a `Charities`.
+ The request was successful, and the response is a `Charities`.
**Details:**
@@ -533,6 +537,8 @@ The administration requests require an authorized bearer token to be set in the
.. http:get:: /charities/$CHARITY_ID
+ GET a specific charity. Only allowed if the request comes with the charity or administration bearer token.
+
Request information about a charity.
**Request:**
@@ -547,20 +553,14 @@ The administration requests require an authorized bearer token to be set in the
.. ts:def:: Charity
interface Charity {
+ charity_pub: EddsaPublicKey;
name: string;
- pub_key: EddsaPublicKey;
max_per_year: Amount;
- donation_history: CharityHistoryYear[];
- }
-
- .. ts:def:: CharityHistoryYear
-
- interface CharityHistoryYear {
- year: Integer;
- final_amout: Amount;
+ receipts_to_date: Amount;
+ current_year: Integer;
}
- .. http:POST:: /charities
+.. http:POST:: /charity
Add a charity. Only allowed if the request comes with the administrator bearer token.
@@ -577,9 +577,9 @@ The administration requests require an authorized bearer token to be set in the
The request did not contain an accepted administrator bearer token in it's header.
.. ts:def:: CharityRequest
-
+
interface CharityRequest{
- pub_key: EddsaPublicKey;
+ charity_pub: EddsaPublicKey;
max_per_year: Amount;
name: string;
}
@@ -589,7 +589,7 @@ The administration requests require an authorized bearer token to be set in the
interface CharityResponse{
id: Integer;
}
-
+
.. http:PATCH:: /charities/{id}
@@ -618,4 +618,4 @@ The administration requests require an authorized bearer token to be set in the
The request was successful.
:http:statuscode:`403 Forbidden`:
- The request did not contain an accepted administrator bearer token in it's header. \ No newline at end of file
+ The request did not contain an accepted administrator bearer token in it's header.
diff --git a/core/api-exchange.rst b/core/api-exchange.rst
index 3992b7e2..429170ce 100644
--- a/core/api-exchange.rst
+++ b/core/api-exchange.rst
@@ -1,6 +1,6 @@
..
This file is part of GNU TALER.
- Copyright (C) 2014-2023 Taler Systems SA
+ Copyright (C) 2014-2024 Taler Systems SA
TALER is free software; you can redistribute it and/or modify it under the
terms of the GNU Affero General Public License as published by the Free Software
@@ -25,6 +25,7 @@ The `glossary <https://docs.taler.net/glossary.html#glossary>`_
defines all specific terms used in this section.
.. contents:: Table of Contents
+ :local:
.. include:: tos.rst
@@ -61,6 +62,7 @@ possibly by using HTTPS.
as well as the list of possible KYC requirements. This endpoint is largely
for the SPA for AML officers. Merchants should use ``/keys`` which also
contains the protocol version and currency.
+ This specification corresponds to ``current`` protocol being version **18**.
**Response:**
@@ -78,7 +80,12 @@ possibly by using HTTPS.
// Name of the protocol.
name: "taler-exchange";
- // Currency supported by this exchange.
+ // URN of the implementation (needed to interpret 'revision' in version).
+ // @since v18, may become mandatory in the future.
+ implementation?: string;
+
+ // Currency supported by this exchange, given
+ // as a currency code ("USD" or "EUR").
currency: string;
// How wallets should render this currency.
@@ -92,12 +99,13 @@ possibly by using HTTPS.
.. ts:def:: CurrencySpecification
interface CurrencySpecification {
-
- // Name of the currency.
+ // Name of the currency. Like "US Dollar".
name: string;
- // Decimal separator for fractional digits.
- decimal_separator: string;
+ // Code of the currency.
+ // Deprecated in protocol v18 for the exchange
+ // and in protocol v6 for the merchant.
+ currency: string;
// how many digits the user may enter after the decimal_separator
num_fractional_input_digits: Integer;
@@ -109,10 +117,6 @@ possibly by using HTTPS.
// padding with zeros.
num_fractional_trailing_zero_digits: Integer;
- // Whether the currency name should be rendered before (true) or
- // after (false) the numeric value
- is_currency_name_leading: boolean;
-
// map of powers of 10 to alternative currency names / symbols, must
// always have an entry under "0" that defines the base name,
// e.g. "0 => €" or "3 => k€". For BTC, would be "0 => BTC, -3 => mBTC".
@@ -170,10 +174,9 @@ possibly by using HTTPS.
// Linear cost factor for the STEFAN curve used
// to (over) approximate fees payable by amount.
//
- // Note that the total to be paid is first to be
- // divided by the smallest denomination to obtain
- // the value to be multiplied with.
- stefan_lin: Amount;
+ // Note that this is a scalar, as it is multiplied
+ // with the actual amount.
+ stefan_lin: Float;
// Type of the asset. "fiat", "crypto", "regional"
// or "stock". Wallets should adjust their UI/UX
@@ -194,7 +197,8 @@ possibly by using HTTPS.
// Set to true if this exchange allows the use
// of reserves for rewards.
- rewards_allowed: boolean;
+ // @deprecated in protocol v18.
+ rewards_allowed: false;
// EdDSA master public key of the exchange, used to sign entries
// in ``denoms`` and ``signkeys``.
@@ -251,6 +255,79 @@ possibly by using HTTPS.
}
+ The specification for the account object is:
+
+ .. ts:def:: WireAccount
+
+ interface WireAccount {
+ // ``payto://`` URI identifying the account and wire method
+ payto_uri: string;
+
+ // URI to convert amounts from or to the currency used by
+ // this wire account of the exchange. Missing if no
+ // conversion is applicable.
+ conversion_url?: string;
+
+ // Restrictions that apply to bank accounts that would send
+ // funds to the exchange (crediting this exchange bank account).
+ // Optional, empty array for unrestricted.
+ credit_restrictions: AccountRestriction[];
+
+ // Restrictions that apply to bank accounts that would receive
+ // funds from the exchange (debiting this exchange bank account).
+ // Optional, empty array for unrestricted.
+ debit_restrictions: AccountRestriction[];
+
+ // Signature using the exchange's offline key over
+ // a `TALER_MasterWireDetailsPS`
+ // with purpose ``TALER_SIGNATURE_MASTER_WIRE_DETAILS``.
+ master_sig: EddsaSignature;
+ }
+
+ .. ts:def:: AccountRestriction
+
+ type AccountRestriction =
+ | RegexAccountRestriction
+ | DenyAllAccountRestriction
+
+ .. ts:def:: DenyAllAccountRestriction
+
+ // Account restriction that disables this type of
+ // account for the indicated operation categorically.
+ interface DenyAllAccountRestriction {
+
+ type: "deny";
+ }
+
+ .. ts:def:: RegexAccountRestriction
+
+ // Accounts interacting with this type of account
+ // restriction must have a payto://-URI matching
+ // the given regex.
+ interface RegexAccountRestriction {
+
+ type: "regex";
+
+ // Regular expression that the payto://-URI of the
+ // partner account must follow. The regular expression
+ // should follow posix-egrep, but without support for character
+ // classes, GNU extensions, back-references or intervals. See
+ // https://www.gnu.org/software/findutils/manual/html_node/find_html/posix_002degrep-regular-expression-syntax.html
+ // for a description of the posix-egrep syntax. Applications
+ // may support regexes with additional features, but exchanges
+ // must not use such regexes.
+ payto_regex: string;
+
+ // Hint for a human to understand the restriction
+ // (that is hopefully easier to comprehend than the regex itself).
+ human_hint: string;
+
+ // Map from IETF BCP 47 language tags to localized
+ // human hints.
+ human_hint_i18n?: { [lang_tag: string]: string };
+
+ }
+
.. ts:def:: GlobalFees
interface GlobalFees {
@@ -538,112 +615,6 @@ possibly by using HTTPS.
Both the individual denominations *and* the denomination list is signed,
allowing customers to prove that they received an inconsistent list.
-.. _wire-req:
-
-.. http:get:: /wire
-
- Returns a list of payment methods supported by the exchange. The idea is that wallets may use this information to instruct users on how to perform wire transfers to top up their wallets.
-
- **Response:**
-
- :http:statuscode:`200 OK`:
- The exchange responds with a `WireResponse` object. This request should virtually always be successful.
-
- **Details:**
-
- .. ts:def:: WireResponse
-
- interface WireResponse {
-
- // Master public key of the exchange, must match the key returned in ``/keys``.
- master_public_key: EddsaPublicKey;
-
- // Array of wire accounts operated by the exchange for
- // incoming wire transfers.
- accounts: WireAccount[];
-
- // Object mapping names of wire methods (i.e. "iban" or "x-taler-bank")
- // to wire fees.
- fees: { method : AggregateTransferFee[] };
-
- // List of exchanges that this exchange is partnering
- // with to enable wallet-to-wallet transfers.
- wads: ExchangePartner[];
- }
-
- The specification for the account object is:
-
- .. ts:def:: WireAccount
-
- interface WireAccount {
- // ``payto://`` URI identifying the account and wire method
- payto_uri: string;
-
- // URI to convert amounts from or to the currency used by
- // this wire account of the exchange. Missing if no
- // conversion is applicable.
- conversion_url?: string;
-
- // Restrictions that apply to bank accounts that would send
- // funds to the exchange (crediting this exchange bank account).
- // Optional, empty array for unrestricted.
- credit_restrictions: AccountRestriction[];
-
- // Restrictions that apply to bank accounts that would receive
- // funds from the exchange (debiting this exchange bank account).
- // Optional, empty array for unrestricted.
- debit_restrictions: AccountRestriction[];
-
- // Signature using the exchange's offline key over
- // a `TALER_MasterWireDetailsPS`
- // with purpose ``TALER_SIGNATURE_MASTER_WIRE_DETAILS``.
- master_sig: EddsaSignature;
- }
-
- .. ts:def:: AccountRestriction
-
- type AccountRestriction =
- | RegexAccountRestriction
- | DenyAllAccountRestriction
-
- .. ts:def:: DenyAllAccountRestriction
-
- // Account restriction that disables this type of
- // account for the indicated operation categorically.
- interface DenyAllAccountRestriction {
-
- type: "deny";
- }
-
- .. ts:def:: RegexAccountRestriction
-
- // Accounts interacting with this type of account
- // restriction must have a payto://-URI matching
- // the given regex.
- interface RegexAccountRestriction {
-
- type: "regex";
-
- // Regular expression that the payto://-URI of the
- // partner account must follow. The regular expression
- // should follow posix-egrep, but without support for character
- // classes, GNU extensions, back-references or intervals. See
- // https://www.gnu.org/software/findutils/manual/html_node/find_html/posix_002degrep-regular-expression-syntax.html
- // for a description of the posix-egrep syntax. Applications
- // may support regexes with additional features, but exchanges
- // must not use such regexes.
- payto_regex: string;
-
- // Hint for a human to understand the restriction
- // (that is hopefully easier to comprehend than the regex itself).
- human_hint: string;
-
- // Map from IETF BCP 47 language tags to localized
- // human hints.
- human_hint_i18n?: { [lang_tag: string]: string };
-
- }
-
Aggregate wire transfer fees representing the fees the exchange
charges per wire transfer to a merchant must be specified as an
array in all wire transfer response objects under ``fees``. The
@@ -658,9 +629,6 @@ possibly by using HTTPS.
// Per transfer closing fee.
closing_fee: Amount;
- // Per exchange-to-exchange transfer (wad) fee.
- wad_fee: Amount;
-
// What date (inclusive) does this fee go into effect?
// The different fees must cover the full time period in which
// any of the denomination keys are valid without overlap.
@@ -685,6 +653,9 @@ possibly by using HTTPS.
// Public master key of the partner exchange.
partner_master_pub: EddsaPublicKey;
+ // Per exchange-to-exchange transfer (wad) fee.
+ wad_fee: Amount;
+
// Exchange-to-exchange wad (wire) transfer frequency.
wad_frequency: RelativeTime;
@@ -1825,7 +1796,7 @@ Batch Withdraw
}
- .. ts:def:: WithdrawResponse
+ .. ts:def:: WithdrawResponse
interface WithdrawResponse {
// The blinded signature over the 'coin_ev', affirms the coin's
@@ -2946,15 +2917,16 @@ proof to the seller for the escrow of sufficient fund.
The deposit operation has either failed because a coin has insufficient
residual value, or because the same public key of a coin has been
previously used with a different denomination.
- Which case it is
- can be decided by looking at the error code
- (``TALER_EC_EXCHANGE_DEPOSIT_CONFLICTING_CONTRACT`` (same coin used in different ways),
- ``TALER_EC_EXCHANGE_GENERIC_INSUFFICIENT_FUNDS`` (balance insufficient) or
- ``TALER_EC_EXCHANGE_GENERIC_COIN_CONFLICTING_DENOMINATION_KEY``
- (same coin public key, but different denomination)).
- The fields of the response are still evolving (see bug 7267),
- for now the format of the response is a `DepositDoubleSpendError`.
- The request should not be repeated again with this coin.
+ Which case it is can be decided by looking at the error code:
+
+ 1. ``TALER_EC_EXCHANGE_DEPOSIT_CONFLICTING_CONTRACT`` (same coin used in different ways),
+ 2. ``TALER_EC_EXCHANGE_GENERIC_INSUFFICIENT_FUNDS`` (balance insufficient),
+ 3. ``TALER_EC_EXCHANGE_GENERIC_COIN_CONFLICTING_DENOMINATION_KEY`` (same coin public key, but different denomination).
+ 4. ``TALER_EC_EXCHANGE_GENERIC_COIN_CONFLICTING_AGE_HASH`` (same coin public key, but different age commitment).
+
+ The request should not be repeated again with this coin. Instead, the client
+ can get from the exchange via the ``/coin/$COIN_PUB/history`` endpoint the record
+ of the transactions known for this coin's public key.
:http:statuscode:`410 Gone`:
The requested denomination key is not yet or no longer valid.
It either before the validity start, past the expiration or was revoked. The response is a
@@ -3391,7 +3363,7 @@ the API during normal operation.
// Melt commitment. Hash over the various coins to be withdrawn.
// See also ``TALER_refresh_get_commitment()``.
- rc: TALER_RefreshCommitmentP;
+ rc: HashCode;
// Master seed for the Clause-schnorr R-value
// creation. Must match the /csr-melt request.
@@ -3538,10 +3510,7 @@ the API during normal operation.
.. ts:def:: RevealResponse
- interface RevealResponse {
- // List of the exchange's blinded RSA signatures on the new coins.
- ev_sigs : Array<{ ev_sig: BlindedDenominationSignature }>;
- }
+ type RevealResponse = BatchWithdrawResponse;
.. ts:def:: RevealConflictResponse
@@ -4863,9 +4832,18 @@ wallet-to-wallet payments. Only another exchange should access this endpoint.
KYC status updates
------------------
+This section describes endpoints used to set up, complete and
+inquire about KYC operations performed by an exchange for
+regulatory compliance.
+
.. http:post:: /kyc-wallet
Setup KYC identification for a wallet. Returns the KYC UUID.
+ This endpoint is used by compliant Taler wallets when they
+ are about to hit the balance threshold and thus need to have
+ the customer provide their personal details to the exchange.
+ The wallet is identified by its long-lived reserve public key
+ (which is used for P2P payments, not for withdrawals).
**Request:**
@@ -4922,15 +4900,18 @@ KYC status updates
.. http:get:: /kyc-check/$REQUIREMENT_ROW/$H_PAYTO/$USERTYPE
- Check or update KYC status of a particular payment target.
- Returns the current KYC status of the account and, if
- negative, returns the URL where the KYC process can be
- initiated. The ``$REQUIREMENT_ROW`` must have been
- returned previously from an exchange API endpoint that
- determined that KYC was needed. The ``$H_PATYO`` must be
- the hash of the payto:// URI of the payment target.
- The ``$USERTYPE`` states whether the entity to perform
- the KYC is an "individual" or "business".
+ Checks the KYC status of a particular payment target and possibly begins the
+ KYC process. This endpoint is used by wallets or merchants that have been
+ told about a KYC requirement and now want to check if the KYC requirement
+ has been fulfilled. Long-polling may be used to instantly observe a change
+ in the KYC requirement status.
+
+ Returns the current KYC status of the requirement process and, if negative,
+ returns the URL where the KYC process can be initiated. The
+ ``$REQUIREMENT_ROW`` must have been returned previously from an exchange API
+ endpoint that determined that KYC was needed. The ``$H_PATYO`` must be the
+ hash of the "payto://" URI of the payment target. The ``$USERTYPE`` states
+ whether the entity to perform the KYC is an "individual" or a "business".
**Request:**
@@ -4949,12 +4930,13 @@ KYC status updates
The response will be an `AccountKycStatus` object.
:http:statuscode:`202 Accepted`:
The user should be redirected to the provided location to perform
- the required KYC checks to open the account. Afterwards, the
- ``/kyc-check/`` request should be repeated.
+ the required KYC checks to satisfy the legal requirements. Afterwards, the
+ ``/kyc-check/`` request should be repeated to check whether the
+ user has completed the process.
The response will be an `AccountKycRedirect` object.
:http:statuscode:`204 No content`:
The exchange is not configured to perform KYC and thus
- generally all accounts are simply considered legitimate.
+ the legal requirements are already satisfied.
:http:statuscode:`402 Payment Required`:
The client must pay the KYC fee for the KYC process.
**This is currently not implemented, see #7365.**
@@ -4964,6 +4946,10 @@ KYC status updates
The payment target is unknown.
:http:statuscode:`451 Unavailable for Legal Reasons`:
The transaction cannot be completed due to AML rules.
+ Thus, the operation is currently not stuck on KYC, but
+ on exchange staff performing their AML review. The user
+ should be told to wait and/or contact the exchange operator
+ if the situation persists.
The response will be a `AccountAmlBlocked` object.
**Details:**
@@ -5034,10 +5020,18 @@ KYC status updates
.. http:get:: /kyc-proof/$PROVIDER_SECTION?state=$H_PAYTO
- Update KYC status of a particular payment target. Provides
+ Endpoint accessed from the user's browser at the *end* of a
+ KYC process, possibly providing the exchange with additional
+ credentials to obtain the results of the KYC process.
+ Specifically, the URL arguments should provide
information to the exchange that allows it to verify that the
user has completed the KYC process. The details depend on
- the logic, which is selected by the $PROVIDER_SECTION.
+ the logic, which is selected by the "$PROVIDER_SECTION".
+
+ While this is a GET (and thus safe, and idempotent), the operation
+ may actually trigger significant changes in the exchange's state.
+ In particular, it may update the KYC status of a particular
+ payment target.
**Request:**
@@ -5056,6 +5050,10 @@ KYC status updates
**Response:**
+ Given that the response is returned to a user using a browser and **not** to
+ a Taler wallet, the response format is in human-readable HTML and not in
+ machine-readable JSON.
+
:http:statuscode:`302 Found`:
The KYC operation succeeded and the
payment target is now authorized to transact.
@@ -5078,11 +5076,11 @@ KYC status updates
.. http:get:: /kyc-webhook/$LOGIC/*
.. http:post:: /kyc-webhook/$LOGIC/*
- Update KYC status of a particular payment target. Provides
- information to the KYC logic of the exchange that allows
- it to verify that the user has completed the KYC process.
- May be a GET or a POST request, depending on $LOGIC or
- $PROVIDER_SECTION.
+ All of the above endpoints can be used to update KYC status of a particular
+ payment target. They provide information to the KYC logic of the exchange
+ that allows it to verify that the user has completed the KYC process. May
+ be a GET or a POST request, depending on the specific "$LOGIC" and/or the
+ "$PROVIDER_SECTION".
**Request:**
@@ -5092,7 +5090,7 @@ KYC status updates
**Response:**
:http:statuscode:`204 No content`:
- The webhook succeeded.
+ The operation succeeded.
:http:statuscode:`404 Not found`:
The specified logic is unknown.
@@ -5102,12 +5100,12 @@ Reserve control
---------------
This section describes the reserve control API which can be used to (1)
-prevent a reserve from expiring (which is useful if the reserve is used for
-rewards), to (2) pay an annual fee to allow a number of purses to be created
-for the respective reserve without paying a purse fee each time, to (3) obtain
-KYC information associated with a reserve to prove the identity of the person
-sending an invoice to the payer, and to (4) close a reserve before it would
-naturally expire and possibly (5) wire the funds to a designated account.
+prevent a reserve from expiring, to (2) pay an annual fee to allow a number of
+purses to be created for the respective reserve without paying a purse fee
+each time, to (3) obtain KYC information associated with a reserve to prove
+the identity of the person sending an invoice to the payer, and to (4) close a
+reserve before it would naturally expire and possibly (5) wire the funds to a
+designated account.
.. note::
@@ -5115,7 +5113,7 @@ naturally expire and possibly (5) wire the funds to a designated account.
.. http:post:: /reserves/$RESERVE_PUB/open
- Request keeping a reserve open for rewards or invoicing.
+ Request keeping a reserve open for invoicing.
**Request:**
diff --git a/core/api-mailbox.rst b/core/api-mailbox.rst
index 33db482d..34d27ded 100644
--- a/core/api-mailbox.rst
+++ b/core/api-mailbox.rst
@@ -29,6 +29,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.
+.. contents:: Table of Contents
+ :local:
+
.. include:: tos.rst
-------------------------
diff --git a/core/api-merchant.rst b/core/api-merchant.rst
index b984819a..7ae29d68 100644
--- a/core/api-merchant.rst
+++ b/core/api-merchant.rst
@@ -1,6 +1,6 @@
..
This file is part of GNU TALER.
- Copyright (C) 2014-2023 Taler Systems SA
+ Copyright (C) 2014-2024 Taler Systems SA
TALER is free software; you can redistribute it and/or modify it under the
terms of the GNU Affero General Public License as published by the Free Software
@@ -25,7 +25,7 @@ Merchant Backend RESTful API
============================
.. contents:: Table of Contents
-
+ :local:
-----------------------
Base URLs and Instances
@@ -36,11 +36,13 @@ This is useful when multiple businesses want to share the same payment
infrastructure.
Merchant backends have one special ``default`` instance. This ``default``
-instance is used when no explicit instance is specified. Despite its name,
-this instance must be created after the installation. In case *no* default
-instance is found - or its credentials got lost -, the administrator can use
-the default instance's rights by resorting on the ``--auth`` command line option,
-or by restarting the service by providing an environment variable called
+instance is used when no explicit instance is specified. Note that using
+``/instances/default/$ANYTHING`` is deprecated and will result in a permanent
+redirect (HTTP status 308) to ``$ANYTHING``. a Despite its name, this instance
+must be created after the installation. In case *no* default instance is
+found - or its credentials got lost -, the administrator can use the default
+instance's rights by resorting on the ``--auth`` command line option, or by
+restarting the service by providing an environment variable called
``TALER_MERCHANT_TOKEN``.
Each instance (default and others) has a base URL. The resources under
@@ -74,10 +76,10 @@ Examples:
https://merchant-backend.example.com/instances/myinst/orders/ABCD
A private endpoint (explicit "default" instance):
- https://merchant-backend.example.com/instances/default/private/orders
+ https://merchant-backend.example.com/private/orders
A public endpoint (explicit "default" instance):
- https://merchant-backend.example.com/instances/default/orders
+ https://merchant-backend.example.com/orders
Endpoints to manage other instances (ONLY for implicit "default" instance):
https://merchant-backend.example.com/management/instances
@@ -121,6 +123,7 @@ such as the implemented version of the protocol and the currency used.
.. http:get:: /config
Return the protocol version and currency supported by this merchant backend.
+ This specification corresponds to ``current`` protocol being version **10**.
**Response:**
@@ -138,6 +141,10 @@ such as the implemented version of the protocol and the currency used.
// Name of the protocol.
name: "taler-merchant";
+ // URN of the implementation (needed to interpret 'revision' in version).
+ // @since **v8**, may become mandatory in the future.
+ implementation?: string;
+
// Default (!) currency supported by this backend.
// This is the currency that the backend should
// suggest by default to the user when entering
@@ -145,14 +152,42 @@ such as the implemented version of the protocol and the currency used.
// supported currencies and how to render them.
currency: string;
- // How wallets should render currencies supported
+ // How services should render currencies supported
// by this backend. Maps
// currency codes (e.g. "EUR" or "KUDOS") to
// the respective currency specification.
// All currencies in this map are supported by
- // the backend.
+ // the backend. Note that the actual currency
+ // specifications are a *hint* for applications
+ // that would like *advice* on how to render amounts.
+ // Applications *may* ignore the currency specification
+ // if they know how to render currencies that they are
+ // used with.
currencies: { currency : CurrencySpecification};
+ // Array of exchanges trusted by the merchant.
+ // Since protocol **v6**.
+ exchanges: ExchangeConfigInfo[];
+
+ }
+
+ .. ts:def:: ExchangeConfigInfo
+
+ interface ExchangeConfigInfo {
+
+ // Base URL of the exchange REST API.
+ base_url: string;
+
+ // Currency for which the merchant is configured
+ // to trust the exchange.
+ // May not be the one the exchange actually uses,
+ // but is the only one we would trust this exchange for.
+ currency: string;
+
+ // Offline master public key of the exchange. The
+ // ``/keys`` data must be signed with this public
+ // key for us to trust it.
+ master_pub: EddsaPublicKey;
}
@@ -164,8 +199,7 @@ This section describes (public) endpoints that wallets must be able
to interact with directly (without HTTP-based authentication). These
endpoints are used to process payments (claiming an order, paying
for the order, checking payment/refund status and aborting payments),
-process refunds (checking refund status, obtaining the refund),
-and to pick up rewards.
+and to process refunds (checking refund status, obtaining the refund).
Claiming an order
@@ -335,7 +369,7 @@ Making the payment
coin_pub: EddsaPublicKey;
// Signature made by the denomination public key.
- ub_sig: RsaSignature;
+ ub_sig: UnblindedSignature;
// The hash of the denomination public key associated with this coin.
h_denom: HashCode;
@@ -378,6 +412,7 @@ Querying payment status
merchant backend may return a response immediately.
:query await_refund_obtained=BOOLEAN: *Optional*. If set to "yes", poll for the order's pending refunds to be picked up. ``timeout_ms`` specifies how long we will wait for the refund.
:query refund=AMOUNT: *Optional*. Indicates that we are polling for a refund above the given AMOUNT. ``timeout_ms`` will specify how long we will wait for the refund.
+ :query allow_refunded_for_repurchase: *Optional*. Since protocol **v9** refunded orders are only returned under "already_paid_order_id" if this flag is set explicitly to "YES".
**Response:**
@@ -802,111 +837,6 @@ the contract. Refunds must be approved by the merchant's business logic.
}
-Picking up rewards
-------------------
-
-Rewards are a way for wallets to obtain e-cash from
-a website.
-
-.. http:get:: [/instances/$INSTANCE]/rewards/$REWARD_ID
-
- Handle request from wallet to provide details about a reward.
-
- This endpoint typically also supports requests with the "Accept" header
- requesting "text/html". In this case, an HTML response suitable for
- triggering the interaction with the wallet is returned. If the backend
- installation does not include the required HTML templates, a 406 status
- code is returned.
-
- **Response:**
-
- :http:statuscode:`200 OK`:
- A reward is being returned. The backend responds with a `RewardInformation`.
- :http:statuscode:`404 Not found`:
- The reward identifier is unknown.
- :http:statuscode:`406 Not acceptable`:
- The merchant backend could not load the template required to generate a reply in the desired format. (Likely HTML templates were not properly installed.)
- :http:statuscode:`410 Gone`:
- A reward has been fully claimed. The JSON reply still contains the `RewardInformation`.
-
- .. ts:def:: RewardInformation
-
- interface RewardInformation {
-
- // Exchange from which the reward will be withdrawn. Needed by the
- // wallet to determine denominations, fees, etc.
- exchange_url: string;
-
- // URL where to go after obtaining the reward.
- next_url: string;
-
- // (Remaining) amount of the reward (including fees).
- reward_amount: Amount;
-
- // Timestamp indicating when the reward is set to expire (may be in the past).
- // Note that rewards that have expired MAY also result in a 404 response.
- expiration: Timestamp;
- }
-
-
-.. http:post:: [/instances/$INSTANCE]/rewards/$REWARD_ID/pickup
-
- Handle request from wallet to pick up a reward.
-
- **Request:**
-
- The request body is a `RewardPickupRequest` object.
-
- **Response:**
-
- :http:statuscode:`200 OK`:
- A reward is being returned. The backend responds with a `RewardResponse`.
- :http:statuscode:`401 Unauthorized`:
- The reward amount requested exceeds the reward.
- :http:statuscode:`404 Not found`:
- The reward identifier is unknown.
- :http:statuscode:`409 Conflict`:
- Some of the denomination key hashes of the request do not match those currently available from the exchange (hence there is a conflict between what the wallet requests and what the merchant believes the exchange can provide).
- :http:statuscode:`410 Gone`:
- The reward has expired.
-
- .. ts:def:: RewardPickupRequest
-
- interface RewardPickupRequest {
-
- // List of planchets the wallet wants to use for the reward.
- planchets: PlanchetDetail[];
- }
-
- .. ts:def:: PlanchetDetail
-
- interface PlanchetDetail {
- // Hash of the denomination's public key (hashed to reduce
- // bandwidth consumption).
- denom_pub_hash: HashCode;
-
- // Coin's blinded public key.
- coin_ev: CoinEnvelope;
- }
-
- .. ts:def:: RewardResponse
-
- interface RewardResponse {
-
- // Blind RSA signatures over the planchets.
- // The order of the signatures matches the planchets list.
- blind_sigs: BlindSignature[];
- }
-
- .. ts:def:: BlindSignature
-
- interface BlindSignature {
-
- // The (blind) RSA signature. Still needs to be unblinded.
- blind_sig: BlindedRsaSignature;
- }
-
-
-------------------
Instance management
-------------------
@@ -2005,6 +1935,11 @@ Creating orders
// to select among the various (active) wire methods supported by the instance.
payment_target?: string;
+ // The session for which the payment is made (or replayed).
+ // Only set for session-based payments.
+ // Since protocol **v6**.
+ session_id?: string;
+
// Specifies that some products are to be included in the
// order from the inventory. For these inventory management
// is performed (so the products must be in stock) and
@@ -2048,11 +1983,14 @@ Creating orders
// Short summary of the order.
summary: string;
- // See documentation of fulfillment_url in ContractTerms.
+ // See documentation of fulfillment_url in `ContractTerms`.
// Either fulfillment_url or fulfillment_message must be specified.
+ // When creating an order, the fulfillment URL can
+ // contain ``${ORDER_ID}`` which will be substituted with the
+ // order ID of the newly created order.
fulfillment_url?: string;
- // See documentation of fulfillment_message in ContractTerms.
+ // See documentation of fulfillment_message in `ContractTerms`.
// Either fulfillment_url or fulfillment_message must be specified.
fulfillment_message?: string;
}
@@ -2132,6 +2070,8 @@ Inspecting orders
:query date_s: *Optional.* Non-negative date in seconds after the UNIX Epoc, see ``delta`` for its interpretation. If not specified, we default to the oldest or most recent entry, depending on ``delta``.
:query start: *Optional*. Row number threshold, see ``delta`` for its interpretation. Defaults to ``INT64_MAX``, namely the biggest row id possible in the database.
:query timeout_ms: *Optional*. Timeout in milliseconds to wait for additional orders if the answer would otherwise be negative (long polling). Only useful if delta is positive. Note that the merchant MAY still return a response that contains fewer than ``delta`` orders.
+ :query session_id: *Optional*. Since protocol **v6**. Filters by session ID.
+ :query fulfillment_url: *Optional*. Since protocol **v6**. Filters by fulfillment URL.
**Response:**
@@ -2188,8 +2128,9 @@ Inspecting orders
**Request:**
:query session_id: *Optional*. Session ID that the payment must be bound to. If not specified, the payment is not session-bound.
- :query transfer: *Optional*. If set to "YES", try to obtain the wire transfer status for this order from the exchange. Otherwise, the wire transfer status MAY be returned if it is available.
+ :query transfer: Deprecated in protocol **V6**. *Optional*. If set to "YES", try to obtain the wire transfer status for this order from the exchange. Otherwise, the wire transfer status MAY be returned if it is available.
:query timeout_ms: *Optional*. Timeout in milliseconds to wait for a payment if the answer would otherwise be negative (long polling).
+ :query allow_refunded_for_repurchase: *Optional*. Since protocol **v9** refunded orders are only returned under "already_paid_order_id" if this flag is set explicitly to "YES".
**Response:**
@@ -2252,6 +2193,7 @@ Inspecting orders
// Reports about trouble obtaining wire transfer details,
// empty array if no trouble were encountered.
+ // @deprecated in protocol **v6**.
wire_reports: TransactionWireReport[];
// The refund details for this order. One entry per
@@ -2652,418 +2594,6 @@ once we got a reply from the exchange.
The transfer cannot be deleted anymore.
------------------------
-Backend: Giving rewards
------------------------
-
-Rewards are a way for websites to give small amounts of e-cash to visitors (for
-example as a financial reward for providing information or viewing
-advertisements). Rewards are non-contractual: neither merchant nor consumer
-have any contractual information about the other party as a result of the
-reward.
-
-
-Create reserve
---------------
-
-Reserves are basically funds a merchant has provided to an exchange for a
-rewards campaign. Each reserve has a limited lifetime (say 2--4 weeks). Any
-funds not used to reward customers will automatically be wired back from the
-exchange to the originating account.
-
-Before handing out rewards, a merchant must tell the backend to set up a
-reserve. The backend will return a reserve public key which must be used as
-the wire transfer subject when wiring the reward campaign funds to the
-exchange.
-
-.. _rewards:
-.. http:post:: [/instances/$INSTANCE]/private/reserves
-
- Create a reserve for rewards.
-
- This request is **not** idempotent. However, while repeating
- it will create another reserve, that is generally pretty harmless
- (assuming only one of the reserves is filled with a wire transfer).
- Clients may want to eventually delete the unused reserves to
- avoid clutter.
-
- **Request:**
-
- The request body is a `ReserveCreateRequest` object.
-
- **Response:**
-
- :http:statuscode:`200 OK`:
- The backend is waiting for the reserve to be established. The merchant
- must now perform the wire transfer indicated in the `ReserveCreateConfirmation`.
- :http:statuscode:`408 Request timeout`:
- The exchange did not respond on time.
- :http:statuscode:`409 Conflict`:
- The exchange does not support the requested wire method or does not allow rewards.
- :http:statuscode:`502 Bad gateway`:
- We could not obtain ``/wire`` details from the specified exchange base URL.
- :http:statuscode:`504 Gateway timeout`:
- The merchant's interaction with the exchange took too long.
- The client might want to try again later.
-
- .. ts:def:: ReserveCreateRequest
-
- interface ReserveCreateRequest {
- // Amount that the merchant promises to put into the reserve.
- initial_balance: Amount;
-
- // Exchange the merchant intends to use for rewards.
- exchange_url: string;
-
- // Desired wire method, for example "iban" or "x-taler-bank".
- wire_method: string;
- }
-
- .. ts:def:: ReserveCreateConfirmation
-
- interface ReserveCreateConfirmation {
- // Public key identifying the reserve.
- reserve_pub: EddsaPublicKey;
-
- // Wire accounts of the exchange where to transfer the funds.
- accounts: WireAccount[];
- }
-
-.. http:get:: [/instances/$INSTANCE]/private/reserves
-
- Obtain list of reserves that have been created for rewards.
-
- **Request:**
-
- :query after: *Optional*. Only return reserves created after the given timestamp in milliseconds.
- :query active: *Optional*. Only return active/inactive reserves depending on the boolean given.
- :query failures: *Optional*. Only return reserves where we disagree with the exchange about the initial balance.
-
- **Response:**
-
- :http:statuscode:`200 OK`:
- Returns a list of known reward reserves.
- The body is a `RewardReserveStatus`.
-
- .. ts:def:: RewardReserveStatus
-
- interface RewardReserveStatus {
- // Array of all known reserves (possibly empty!).
- reserves: ReserveStatusEntry[];
- }
-
- .. ts:def:: ReserveStatusEntry
-
- interface ReserveStatusEntry {
- // Public key of the reserve.
- reserve_pub: EddsaPublicKey;
-
- // Timestamp when it was established.
- creation_time: Timestamp;
-
- // Timestamp when it expires.
- expiration_time: Timestamp;
-
- // Initial amount as per reserve creation call.
- merchant_initial_amount: Amount;
-
- // Initial amount as per exchange, 0 if exchange did
- // not confirm reserve creation yet.
- exchange_initial_amount: Amount;
-
- // Amount picked up so far.
- pickup_amount: Amount;
-
- // Amount approved for rewards that exceeds the pickup_amount.
- committed_amount: Amount;
-
- // Is this reserve active (false if it was deleted but not purged)?
- active: boolean;
- }
-
-
-Query funds remaining
----------------------
-
-.. http:get:: [/instances/$INSTANCE]/private/reserves/$RESERVE_PUB
-
- Obtain information about a specific reserve that have been created for rewards.
-
- **Request:**
-
- :query rewards: *Optional*. If set to "yes", returns also information about all of the rewards created.
-
- **Response:**
-
- :http:statuscode:`200 OK`:
- Returns the `ReserveDetail`.
- :http:statuscode:`404 Not found`:
- The reward reserve is not known.
- :http:statuscode:`502 Bad gateway`:
- We are having trouble with the request because of a problem with the exchange.
- Likely returned with an "exchange_code" in addition to a "code" and
- an "exchange_http_status" in addition to our own HTTP status. Also usually
- includes the full exchange reply to our request under "exchange_reply".
- This is only returned if there was actual trouble with the exchange, not
- if the exchange merely did not respond yet or if it responded that the
- reserve was not yet filled.
- :http:statuscode:`504 Gateway timeout`:
- The merchant's interaction with the exchange took too long.
- The client might want to try again later.
-
- .. ts:def:: ReserveDetail
-
- interface ReserveDetail {
- // Timestamp when it was established.
- creation_time: Timestamp;
-
- // Timestamp when it expires.
- expiration_time: Timestamp;
-
- // Initial amount as per reserve creation call.
- merchant_initial_amount: Amount;
-
- // Initial amount as per exchange, 0 if exchange did
- // not confirm reserve creation yet.
- exchange_initial_amount: Amount;
-
- // Amount picked up so far.
- pickup_amount: Amount;
-
- // Amount approved for rewards that exceeds the pickup_amount.
- committed_amount: Amount;
-
- // Array of all rewards created by this reserves (possibly empty!).
- // Only present if asked for explicitly.
- rewards?: RewardStatusEntry[];
-
- // Is this reserve active (false if it was deleted but not purged)?
- active: boolean;
-
- // Array of wire accounts of the exchange that could
- // be used to fill the reserve, can be NULL
- // if the reserve is inactive or was already filled
- accounts?: WireAccount[];
-
- // URL of the exchange hosting the reserve,
- // NULL if the reserve is inactive
- exchange_url: string;
- }
-
- .. ts:def:: RewardStatusEntry
-
- interface RewardStatusEntry {
-
- // Unique identifier for the reward.
- reward_id: HashCode;
-
- // Total amount of the reward that can be withdrawn.
- total_amount: Amount;
-
- // Human-readable reason for why the reward was granted.
- reason: string;
- }
-
-
-Authorizing rewards
--------------------
-
-.. http:post:: [/instances/$INSTANCE]/private/reserves/$RESERVE_PUB/authorize-reward
-
- Authorize creation of a reward from the given reserve.
-
- **Request:**
-
- The request body is a `RewardCreateRequest` object.
-
- **Response:**
-
- :http:statuscode:`200 OK`:
- A reward has been created. The backend responds with a `RewardCreateConfirmation`.
- :http:statuscode:`404 Not found`:
- The instance or the reserve is unknown to the backend.
- :http:statuscode:`412 Precondition failed`:
- The reward amount requested exceeds the available reserve balance for rewards.
-
- .. ts:def:: RewardCreateRequest
-
- interface RewardCreateRequest {
- // Amount that the customer should be rewarded.
- amount: Amount;
-
- // Justification for giving the reward.
- justification: string;
-
- // URL that the user should be directed to after receiving the reward,
- // will be included in the reward_token.
- next_url: string;
- }
-
- .. ts:def:: RewardCreateConfirmation
-
- interface RewardCreateConfirmation {
- // Unique reward identifier for the reward that was created.
- reward_id: HashCode;
-
- // taler://reward URI for the reward.
- taler_reward_uri: string;
-
- // URL that will directly trigger processing
- // the reward when the browser is redirected to it.
- reward_status_url: string;
-
- // When does the reward expire?
- reward_expiration: Timestamp;
- }
-
-
-.. http:post:: [/instances/$INSTANCE]/private/rewards
-
- Authorize creation of a reward, with
- automatic selection of a working reserve of the instance by the
- backend. Intentionally otherwise identical to the ``/authorize-reward``
- endpoint given above.
-
- **Request:**
-
- The request body is a `RewardCreateRequest` object.
-
- **Response:**
-
- :http:statuscode:`200 OK`:
- A reward has been created. The backend responds with a `RewardCreateConfirmation`.
- :http:statuscode:`404 Not found`:
- The instance is unknown to the backend.
- :http:statuscode:`412 Precondition failed`:
- The reward amount requested exceeds the available reserve balance for rewards
- in all of the reserves of the instance.
-
-
-Deleting reserves
------------------
-
-.. http:delete:: [/instances/$INSTANCE]/private/reserves/$RESERVE_PUB
-
- Delete information about a reserve. Fails if the reserve still has
- committed to rewards that were not yet picked up and that have not yet
- expired.
-
- **Request:**
-
- :query purge: *Optional*. If set to YES, the reserve and all information
- about rewards it issued will be fully deleted.
- Otherwise only the private key would be deleted.
-
- **Response:**
-
- :http:statuscode:`204 No content`:
- The backend has successfully deleted the reserve.
- :http:statuscode:`404 Not found`:
- The backend does not know the instance or the reserve.
- :http:statuscode:`409 Conflict`:
- The backend refuses to delete the reserve (committed rewards awaiting pickup).
-
-
-Checking reward status
-----------------------
-
-.. http:get:: [/instances/$INSTANCE]/private/rewards/$REWARD_ID
-
- Obtain information about a particular reward.
-
- **Request:**
-
- :query pickups: *Optional*. If set to "yes", returns also information about all of the pickups.
- :query min_amount: *Optional*. Minimum pick-up amount the client is interested in.
- :query timeout_ms=NUMBER: *Optional.* If specified, the merchant backend will
- wait up to ``timeout_ms`` milliseconds for rewards of at least min_pick_up to be
- picked up. A client must never rely on this behavior, as the
- merchant backend may return a response immediately.
-
- **Response:**
-
- :http:statuscode:`200 OK`:
- The reward is known. The backend responds with a `RewardDetails` message.
- :http:statuscode:`404 Not found`:
- The reward is unknown to the backend.
-
- .. ts:def:: RewardDetails
-
- interface RewardDetails {
- // Amount that we authorized for this reward.
- total_authorized: Amount;
-
- // Amount that was picked up by the user already.
- total_picked_up: Amount;
-
- // Human-readable reason given when authorizing the reward.
- reason: string;
-
- // Timestamp indicating when the reward is set to expire (may be in the past).
- expiration: Timestamp;
-
- // Reserve public key from which the reward is funded.
- reserve_pub: EddsaPublicKey;
-
- // Array showing the pickup operations of the wallet (possibly empty!).
- // Only present if asked for explicitly.
- pickups?: PickupDetail[];
- }
-
- .. ts:def:: PickupDetail
-
- interface PickupDetail {
- // Unique identifier for the pickup operation.
- pickup_id: HashCode;
-
- // Number of planchets involved.
- num_planchets: Integer;
-
- // Total amount requested for this pickup_id.
- requested_amount: Amount;
- }
-
-
-.. http:get:: [/instances/$INSTANCE]/private/rewards
-
- Return the list of all rewards.
-
- **Request:**
-
- :query include_expired: *Optional*. If set to "yes", the result includes expired rewards also. Otherwise, only active rewards are returned.
-
- :query limit: *Optional*. At most return the given number of results. Negative for descending in database row id, positive for ascending in database row id.
-
- :query offset: *Optional*. Starting ``row_id`` for an iteration.
-
- **Response:**
-
- :http:statuscode:`200 OK`:
- The backend has successfully found the list of rewards. The backend responds
- with a `RewardsResponse`.
-
- .. ts:def:: RewardsResponse
-
- interface RewardsResponse {
-
- // List of rewards that are present in the backend.
- rewards: Reward[];
- }
-
- .. ts:def:: Reward
-
- interface Reward {
-
- // ID of the reward in the backend database.
- row_id: number;
-
- // Unique identifier for the reward.
- reward_id: HashCode;
-
- // (Remaining) amount of the reward (including fees).
- reward_amount: Amount;
- }
-
-----------
OTP Devices
-----------
@@ -3097,11 +2627,19 @@ to validate that a customer made a payment.
// Human-readable description for the device.
otp_device_description: string;
- // A base64-encoded key
+ // A key encoded with RFC 3548 Base32.
+ // IMPORTANT: This is not using the typical
+ // Taler base32-crockford encoding.
+ // Instead it uses the RFC 3548 encoding to
+ // be compatible with the TOTP standard.
otp_key: string;
// Algorithm for computing the POS confirmation.
- otp_algorithm: Integer;
+ // "NONE" or 0: No algorithm (no pos confirmation will be generated)
+ // "TOTP_WITHOUT_PRICE" or 1: Without amounts (typical OTP device)
+ // "TOTP_WITH_PRICE" or 2: With amounts (special-purpose OTP device)
+ // The "String" variants are supported @since protocol **v7**.
+ otp_algorithm: Integer | string;
// Counter for counter-based OTP devices.
otp_ctr?: Integer;
@@ -3133,8 +2671,12 @@ to validate that a customer made a payment.
// Human-readable description for the device.
otp_device_description: string;
- // A base64-encoded key
- otp_key: string;
+ // A key encoded with RFC 3548 Base32.
+ // IMPORTANT: This is not using the typical
+ // Taler base32-crockford encoding.
+ // Instead it uses the RFC 3548 encoding to
+ // be compatible with the TOTP standard.
+ otp_key?: string;
// Algorithm for computing the POS confirmation.
otp_algorithm: Integer;
@@ -3178,6 +2720,17 @@ to validate that a customer made a payment.
This is used to obtain detailed information about a specific OTP device.
+ The client can provide additional inputs in the query to allow the backend
+ to compute and return a sample OTP code. Note that it is not an error if
+ the client provides query arguments that are not being used *or* that are
+ insufficient for the server to compute the ``otp_code``: If the client
+ provides inadequate query parameters, the ``otp_code`` is simply omitted
+ from the response.
+
+ **Query:**
+
+ :query faketime=TIMESTAMP: *Optional*. Timestamp in seconds to use when calculating the current OTP code of the device. Since protocol **v10**.
+ :query price=AMOUNT: *Optional*. Price to use when calculating the current OTP code of the device. Since protocol **v10**.
**Response:**
@@ -3195,11 +2748,49 @@ to validate that a customer made a payment.
device_description: string;
// Algorithm for computing the POS confirmation.
+ //
+ // Currently, the following numbers are defined:
+ // 0: None
+ // 1: TOTP without price
+ // 2: TOTP with price
otp_algorithm: Integer;
// Counter for counter-based OTP devices.
otp_ctr?: Integer;
+ // Current time for time-based OTP devices.
+ // Will match the ``faketime`` argument of the
+ // query if one was present, otherwise the current
+ // time at the backend.
+ //
+ // Available since protocol **v10**.
+ otp_timestamp: Integer;
+
+ // Current OTP confirmation string of the device.
+ // Matches exactly the string that would be returned
+ // as part of a payment confirmation for the given
+ // amount and time (so may contain multiple OTP codes).
+ //
+ // If the ``otp_algorithm`` is time-based, the code is
+ // returned for the current time, or for the ``faketime``
+ // if a TIMESTAMP query argument was provided by the client.
+ //
+ // When using OTP with counters, the counter is **NOT**
+ // increased merely because this endpoint created
+ // an OTP code (this is a GET request, after all!).
+ //
+ // If the ``otp_algorithm`` requires an amount, the
+ // ``amount`` argument must be specified in the
+ // query, otherwise the ``otp_code`` is not
+ // generated.
+ //
+ // This field is *optional* in the response, as it is
+ // only provided if we could compute it based on the
+ // ``otp_algorithm`` and matching client query arguments.
+ //
+ // Available since protocol **v10**.
+ otp_code?: String;
+
}
.. http:delete:: [/instances/$INSTANCE]/private/otp-devices/$DEVICE_ID
@@ -3950,13 +3541,26 @@ The contract terms must have the following structure:
public_reorder_url?: string;
// URL that will show that the order was successful after
- // it has been paid for. Optional. When POSTing to the
- // merchant, the placeholder "${ORDER_ID}" will be
- // replaced with the actual order ID (useful if the
+ // it has been paid for. Optional, but either ``fulfillment_url``
+ // or ``fulfillment_message`` must be specified in every
+ // contract terms.
+ //
+ // If a non-unique fulfillment URL is used, a customer can only
+ // buy the order once and will be redirected to a previous purchase
+ // when trying to buy an order with the same fulfillment URL a second
+ // time. This is useful for digital goods that a customer only needs
+ // to buy once but should be able to repeatedly download.
+ //
+ // For orders where the customer is expected to be able to make
+ // repeated purchases (for equivalent goods), the fulfillment URL
+ // should be made unique for every order. The easiest way to do
+ // this is to include a unique order ID in the fulfillment URL.
+ //
+ // When POSTing to the merchant, the placeholder text "${ORDER_ID}"
+ // is be replaced with the actual order ID (useful if the
// order ID is generated server-side and needs to be
- // in the URL).
- // Note that this placeholder can only be used once.
- // Either fulfillment_url or fulfillment_message must be specified.
+ // in the URL). Note that this placeholder can only be used once.
+ // Front-ends may use other means to generate a unique fulfillment URL.
fulfillment_url?: string;
// Message shown to the customer after paying for the order.
@@ -4043,7 +3647,8 @@ The contract terms must have the following structure:
// Extra data that is only interpreted by the merchant frontend.
// Useful when the merchant needs to store extra information on a
// contract without storing it separately in their database.
- extra?: any;
+ // Must really be an Object (not a string, integer, float or array).
+ extra?: Object;
}
The wallet must select an exchange that either the merchant accepts directly by
diff --git a/core/api-sync.rst b/core/api-sync.rst
index 69f59696..c2c86c23 100644
--- a/core/api-sync.rst
+++ b/core/api-sync.rst
@@ -103,6 +103,7 @@ user's location profiles by linking client IP addresses and client
keys.
.. contents:: Table of Contents
+ :local:
.. include:: tos.rst
@@ -114,6 +115,7 @@ Receiving Configuration
.. http:get:: /config
Obtain the key configuration settings of the storage service.
+ This specification corresponds to ``current`` protocol being version **2**.
**Response:**
@@ -139,6 +141,10 @@ Receiving Configuration
// The format is "current:revision:age".
version: string;
+ // URN of the implementation (needed to interpret 'revision' in version).
+ // @since v2, may become mandatory in the future.
+ implementation?: string;
+
}
.. _sync:
diff --git a/core/api-taldir.rst b/core/api-taldir.rst
index 1639e36d..4da9bb02 100644
--- a/core/api-taldir.rst
+++ b/core/api-taldir.rst
@@ -34,6 +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.
+.. contents:: Table of Contents
+ :local:
.. include:: tos.rst
diff --git a/core/index-bank-apis.rst b/core/index-bank-apis.rst
index ec769162..f108df32 100644
--- a/core/index-bank-apis.rst
+++ b/core/index-bank-apis.rst
@@ -27,11 +27,12 @@ Bank RESTful APIs
.. toctree::
:maxdepth: 1
+ intro-bank-apis
api-corebank
api-bank-wire
api-bank-revenue
api-bank-integration
-
+ api-bank-conversion-info
.. toctree::
:hidden:
diff --git a/core/index.rst b/core/index.rst
index d6a20244..8a764c10 100644
--- a/core/index.rst
+++ b/core/index.rst
@@ -32,7 +32,7 @@ protocols using JSON.
.. toctree::
- :maxdepth: 2
+ :maxdepth: 1
api-overview
api-common
diff --git a/core/intro-bank-apis.rst b/core/intro-bank-apis.rst
new file mode 100644
index 00000000..f4307138
--- /dev/null
+++ b/core/intro-bank-apis.rst
@@ -0,0 +1,134 @@
+################################################
+Introduction to Taler (Core-)Banking Integration
+################################################
+
+This chapter provides an overview of the different ways that a bank or core
+banking system can provide integration with GNU Taler.
+
+
+Settlement Account Access
+#########################
+
+To make a GNU Taler deployment possible, the exchange service needs API access
+to a settlement bank account. The settlement account is used to fund digital
+cash withdrawals into users' Taler wallets, as well as to pay out merchants
+that deposited digital cash with the exchange.
+
+The following two operations need to be supported by the settlement account:
+
+1. Querying transactions on the settlement account.
+2. Initiating payments (simple credit transfer).
+
+Note that there is only **one** settlement account needed per Taler deployment.
+There is no per-user settlement account. Thus, creating or managing bank
+accounts is not a requirement.
+
+A core banking system could directly provide the HTTP/REST APIs
+consumed by the Taler exchange (:doc:`api-bank-integration`). Otherwise, an adapter (typically part
+of the libeufin component) needs to be written.
+
+
+Improved Withdrawal Process
+###########################
+
+In principle, any typical account-based (core-)banking system can be used as
+the underlying account-based financial layer for GNU Taler.
+
+However, without extra support from the bank, withdrawals can be difficult for
+unexperienced users. Thus to make sure that a Taler deployment can achieve
+mass adoption from non-technical users, extra integration by the bank / core
+banking system should be provided.
+
+Withdrawals without any extra support from the core banking system require the
+user to make a transaction to a particular bank account (i.e. the exchange's
+settlement account) with a rather long cryptographic identifier in the subject.
+This identifier is generated by the user's wallet when initiating a withdrawal
+from the wallet application. If the user misspells the identifier, the payment
+will be sent back automatically by the exchange.
+
+However, until the wire transfer is successfully completed, the wallet has no
+information about whether the transfer was already made by the user or if it
+was even made correctly. This makes it hard to show accurate information to
+the user about the status of withdrawing digital cash into their Taler wallet.
+
+
+Withdrawal Bank-Integration API
+===============================
+
+A core banking system can provide better support for GNU Taler withdrawals by
+allowing users to initiate *Taler withdrawal operations* from their bank
+account (e.g. in their banking app or online banking). A Taler withdrawal
+operation has a unique identifier (chosen/generated by the core banking
+system), called the WOPID (Withdrawal Operation Identifier).
+
+The core banking system can provide a (public) API to access withdrawal
+operations (:doc:`api-bank-integration`).
+
+The wallet learns the WOPID and API address via a ``taler://withdraw/...``
+QR-Code or link.
+
+The wallet generates the cryptographic identifiers required for the withdrawal,
+allows the user to choose an exchange (the bank may suggest a default one!),
+and then submits this information (chosen exchange, reserve public key) for the
+respective WOPID to the bank-integration API.
+
+The user can then confirm the withdrawal by completing the 2FA of
+their bank account for the operation. (Alternatively, the user can abort the operation
+in their banking client / 2FA app.)
+
+Upon completion of the 2FA / confirmation step, the core banking system
+initiates a credit transfer for the withdrawal operations (with the chosen
+exchange as the creditor and the cryptographic identifier / reserve pub in the
+subject). Afterwards, the withdrawal operation is marked as done.
+
+The wallet can continuously query the status of the withdrawal operation (via
+the API address and WOPID).
+In the Taler wallet app, the user can now always see the accurate status of
+their withdrawal operation (e.g. bank transfer done, aborted, confirmation/2FA
+pending).
+
+
+Payto-URI Integration
+=====================
+
+When initiating a withdrawal from the Taler wallet, the wallet can generate a
+payto:// link or QR code (see `RFC 8905 <https://www.rfc-editor.org/rfc/rfc8905.txt>`_)
+with the payment information necessary to make a
+credit transfer to the exchange's settlement account.
+
+Banking apps may provide integration here simply by handling payto:// URIs.
+
+Integration based on payto:// URIs prevents mistakes in typing the
+cryptographic identifier and bank account number during withdrawals. However,
+it still does not allow the wallet do accurately show the status of a
+withdrawal to the user.
+
+
+Future: Intent-Based Integration on Android
+===========================================
+
+(This type of integration is currently not specified, but planned for the future.)
+
+On the Android platform, applications can communicate via
+`Intents <https://developer.android.com/guide/components/intents-filters>`_.
+That would allow the Taler wallet to open a credit transfer dialog in a
+supported banking app to fund a withdrawal. The banking app can send the
+status of the credit transfer (confirmed/aborted by the user) back to the
+wallet, which can then show more accurate status information about the
+withdrawal to the user.
+
+
+Integration for Merchants
+#########################
+
+The Taler merchant backend has the option to connect to what
+we call the :doc:`Bank Revenue API <api-bank-revenue>`.
+
+A core banking system may provide this API to merchants that have a business
+account at the that bank. The API provides read-only access to incoming
+transactions on the merchant bank account.
+
+It allows merchants to easily and automatically reconcile incoming bank
+transfers from the Taler exchange's settlement account with the respective
+Taler payments. Usually multiple Taler payments are aggregated into one larger
+payment in the underlying banking layer.
diff --git a/design-documents/014-merchant-backoffice-ui.rst b/design-documents/014-merchant-backoffice-ui.rst
index eaf435a4..1f744a15 100644
--- a/design-documents/014-merchant-backoffice-ui.rst
+++ b/design-documents/014-merchant-backoffice-ui.rst
@@ -139,11 +139,3 @@ Story #4: Manage inventory
- change product description / price / etc.
- delete products from inventory
-
-
-Story #5: Manage rewards
-------------------------
-
-- set up reward reserve
-
-- check reward reserve status
diff --git a/design-documents/020-backoffice-rewards-management.rst b/design-documents/020-backoffice-rewards-management.rst
index 1eef39b1..8345a3b9 100644
--- a/design-documents/020-backoffice-rewards-management.rst
+++ b/design-documents/020-backoffice-rewards-management.rst
@@ -1,4 +1,4 @@
-DD 20: Backoffice Rewards Management
+XX 20: Backoffice Rewards Management
####################################
Summary
diff --git a/design-documents/023-taler-kyc.rst b/design-documents/023-taler-kyc.rst
index 4d8f2cbc..d34241d7 100644
--- a/design-documents/023-taler-kyc.rst
+++ b/design-documents/023-taler-kyc.rst
@@ -40,7 +40,7 @@ Taler needs to run KYC checks in the following circumstances:
* key: IBAN (encoded as payto:// URI)
-* Reserve is "opened" for invoicing or rewards.
+* Reserve is "opened" for invoicing.
* key: reserve (=KYC account) long term public key per wallet (encoded as payto:// URI)
diff --git a/design-documents/024-age-restriction.rst b/design-documents/024-age-restriction.rst
index 280a4f39..ee478ee1 100644
--- a/design-documents/024-age-restriction.rst
+++ b/design-documents/024-age-restriction.rst
@@ -600,9 +600,9 @@ The object ``ContractTerms`` is extended by an optional field
``minimum_age`` that can be any integer greater than 0. In reality
this value will not be smaller than, say, 8, and not larger than, say, 21.
-.. ts:def:: ContractTerms
+.. ts:def:: DD24ContractTerms
- interface ContractTerms {
+ interface DD24ContractTerms {
...
// If the order requires a minimum age greater than 0, this field is set
diff --git a/design-documents/028-deposit-policies.rst b/design-documents/028-deposit-policies.rst
index 956945ee..1bdf4801 100644
--- a/design-documents/028-deposit-policies.rst
+++ b/design-documents/028-deposit-policies.rst
@@ -41,7 +41,19 @@ The policies shall be implemented as *extensions* to the exchange (see
Motivation
**********
-TODO
+GNU Taler's initial set of API's (withdraw, deposit, refresh) support most
+payment situations in which customers pay for goods and services within an
+otherwise unconditioned transaction. (A notable exception from this the
+ability to provide refunds, which will be re-factored into a policy extension).
+
+However, in many payments depend on additional conditions to be met. GNU Taler
+already supports payments with age restriction applied, but there are other
+scenarious that we want to support.
+
+Our aim is to provide an API for extensions of GNU Taler that implement
+particular policies and policy-handling for payments (also called *conditioned
+payments*).
+
Background and Requirements
***************************
@@ -56,9 +68,16 @@ 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
+
+API-Endpoints of the Exchange
+=============================
+
+TODO
+
+
+
Database-schema
===============
diff --git a/design-documents/031-invoicing.rst b/design-documents/031-invoicing.rst
index cfe776ed..0fcc88fd 100644
--- a/design-documents/031-invoicing.rst
+++ b/design-documents/031-invoicing.rst
@@ -4,9 +4,7 @@ DD 31: Invoicing
Summary
=======
-This document proposes new endpoints to support invoicing,
-that incidentally also address the long-standing rewards
-reserve expiration problem.
+This document proposes new endpoints to support invoicing.
Motivation
@@ -36,10 +34,7 @@ Requirements
* Reasonable UX and overall design impact.
* Wallets may want to pay for the reserve with coins
- (reserve fresh, not created via bank transfer), while
- rewarding merchants likely want to pay from the reserve
- balance itself. So both styles of payment should be
- supported.
+ (reserve fresh, not created via bank transfer).
Unclear in the current proposal are:
@@ -62,12 +57,10 @@ charge the ``account_fee``, bump the number of open purses threshold in the
``reserves`` table and stop auto-closing of the reserve. This will ensure that
the users can withdraw the reserve balance into their wallet even after a
longer time period. This helps if the invoice is paid after a significant
-delay, and also addresses the unwanted reward reserve closure
-problem. Introduce a way to force an immediate closure of a reserve, allowing
+delay. Introduce a way to force an immediate closure of a reserve, allowing
P2P reserve from invoices to be send to a bank account (this allows a wallet
to be used for convenient invoicing and not strictly require the wallet to
-receive the funds) and also allowing the user to recover funds from a reward
-reserve after rewards are no longer issued.
+receive the funds).
The solution needs three new tables for:
diff --git a/design-documents/035-regional-currencies.rst b/design-documents/035-regional-currencies.rst
index 0b4553e6..3d62dcc3 100644
--- a/design-documents/035-regional-currencies.rst
+++ b/design-documents/035-regional-currencies.rst
@@ -30,6 +30,11 @@ Requirements
* Regional currencies should be easy to use as well
* It must be easy to integrate regional/official currencies with the existing
Taler auditor/exchange structure
+* Wallet users should be able to see disagregated balance between global currencies
+ and regional currencies supported by different exchanges even if the currency
+ name is equal.
+* Merchants should be able to accept regional and global currencies based on the
+ supported exchange list.
Proposed Solution
=================
@@ -144,6 +149,16 @@ The last part should probably be hidden by default. There might be nicer ways t
this, such as some hoverable (?) icon after the amount that shows details about what currencies the merchant
accepts.
+Wallet-core API for scope management
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+* ``listGlobalCurrencyExchanges`` lists all ``(currency, exchangeUrl, exchangePub)`` triples
+ where funds are considered to be in global scope (i.e. non-regional).
+* ``listGlobalCurrencyAuditors`` lists all ``(currency, auditorUrl, auditorPub)`` triples
+ where funds are considered to be in global scope (i.e. non-regional).
+* ``addGlobalCurrencyExchange`` and ``removeGlobalCurrencyExchange`` adds/removes a ``(currency, exchangeUrl, exchangePub)``
+* ``addGlobalCurrencyAuditor`` and ``removeGlobalCurrencyAuditor`` adds/removes a ``(currency, auditorUrl, auditorPub)``
+
Implementation Breakdown
^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/design-documents/036-currency-conversion-service.rst b/design-documents/036-currency-conversion-service.rst
index 72a504c5..92d88499 100644
--- a/design-documents/036-currency-conversion-service.rst
+++ b/design-documents/036-currency-conversion-service.rst
@@ -35,74 +35,63 @@ currency.
Requirements
============
-* CCS must not impact the Nexus structure.
+* CCS must not impact the libeufin-nexus structure.
* CCS must trigger Taler withdrawls every time a customer buys the
- regional currency ('buy-in' operation).
+ regional currency ('cash-in' operation).
* CCS must offer cash-out operations.
-* CCS should react as soon as possible to buy-in and cash-out operations.
+* CCS should react as soon as possible to cash-in and cash-out operations.
* CCS must show its state to administrators and offer management tools.
* CCS must link every fiat-side of a cash-out to its regional currency
counterpart. In particular, because every cash-out starts with a
payment *P* from regio-user to regio-issuer and ends with another
- payment *Q* from fiat-issuer to fiat-target, CCS must link P and Q.
+ payment *Q* from fiat-issuer to fiat-target, CCS must link P and Q.
Proposed Solution
=================
-The following design assumes that CCS is coded into libeufin Sandbox.
+The following design assumes that CCS is coded in libeufin-bank and that
+libeufin-bank and libeufin-nexus share the same database with separate
+schemas. The solution relies on SQL triggers to atomically synchronise
+cash-in and cash-out operations between the two schemas.
+
+SQL triggers and conversion operations
+--------------------------------------
+
+Libeufin-bank controls the conversion support and sets up or removes
+conversion SQL triggers when necessary. In order for the SQL triggers to
+perform the conversion operations, the configurable rates/fees are stored
+in the database and the conversion operations are performed using stored
+SQL procedures. The SQL triggers and conversion procedures are stored in
+the libeufin-bank schema.
Cash-out operation
------------------
-The libeufin Sandbox component learns instantly about a cash-out
-operation, because it's *the* service offering such feature.
-Therefore, as soon as a cash-out operation gets TAN-confirmed,
-Sandbox performs a first wire transfer from regio-user to regio-issuer
-by specifying the amount without any rates/fees applied. Along
-the same database transaction, Sandbox stores the *instructions*
-of another payment *P* from fiat-issuer to fiat-target, but this time
-**with** the cash-out rates/fees. Notably, P includes the **current**
-fiat-target and the rates/fees, since these are configurable.
-
-Asynchronously, a background task picks P and sends it to the fiat bank.
-Finally, fiat bank conducts P and fiat-target receives the wanted
-amount. The same background task should also retry previous payments
-like P that failed to be submitted to fiat bank.
-
-CCS offers management endpoints for prepared fiat-transactions.
-Through them, adminisrators can see, retry, or cancel every fiat-transaction
-that was prepared to pay fiat-target.
-
-Buy-in operation
-----------------
-
-A buy-in operation starts as soon as the customer sends a fiat
-payment from fiat-customer to fiat-issuer. Sandbox is responsible to
-detect such an incoming payment in a timely fashion. The detection
-happens by long polling on the Nexus JSON API. Nexus is ultimately
-responsible to query the fiat bank via EBICS every X seconds. X
-should match the tightest interval allowed by the bank.
-
-When Sandbox detects one incoming payment on fiat-issuer, it applies the
-**current** buy-in rates/fees and wires the resuling amount from regio-issuer
-to regio-exchange. At this point, Nexus detects the incoming payment on
-regio-exchange and makes the exchange aware via the Taler Wire Gateway API.
-From now on, the system proceeds like it always did in Taler.
-
-Milestones to a MVP
-===================
-
-* Refactor configuration in Sandbox: `7527 <https://bugs.gnunet.org/view.php?id=7527>`_, `7515 <https://bugs.gnunet.org/view.php?id=7515>`_.
-* Make rates/fees and TAN channels configurable in Sandbox: `7694 <https://bugs.gnunet.org/view.php?id=7694>`_.
-* Long polling in Nexus to serve TWG: `6987 <https://bugs.gnunet.org/view.php?id=6987>`_, `6383 <https://bugs.gnunet.org/view.php?id=6383>`_.
-* Long polling in Nexus to serve fiat-transactions via native API: `7693 <https://bugs.gnunet.org/view.php?id=7693>`_.
-* Long polling in Sandbox to ask Nexus fiat-transactions via native API.
-* Serve transactions with date ranges in Sandbox Access API: `7685 <https://bugs.gnunet.org/view.php?id=7685>`_
-* Implement JSON-based "bank connection" in Nexus. That's how Nexus
- gets regio-transactions to serve in the TWG.
-* Implement fiat-bank's EBICS flavor.
-* Ask transactions with date ranges in such flavor in Nexus: `7686 <https://bugs.gnunet.org/view.php?id=7686>`_.
-* Implement fiat-transactions management tools.
-
-.. note::
- The list can be incomplete and not necessarily ordered.
+Libeufin-bank learns instantly about a cash-out operation, because it's
+*the* service offering such feature. Therefore, as soon as a cash-out
+operation gets TAN-confirmed, libeufin-bank performs a wire transfer from
+regio-user to regio-issuer by specifying the amount without any rates/fees
+applied. Along the same database transaction, a SQL trigger store the
+*instructions* of another payment *P* from fiat-issuer to fiat-target,
+but this time **with** the cash-out rates/fees.
+
+Asynchronously, a libeufin-nexus background task picks P and sends it to
+the fiat bank. Finally, fiat bank conducts P and fiat-target receives the
+wanted amount. The same libeufin-nexus background task should also retry
+previous payments like P that failed to be submitted to fiat bank.
+
+Cash-in operation
+-----------------
+
+A cashin-in operation starts as soon as the customer sends a fiat
+payment from fiat-customer to fiat-issuer.
+
+The libeufin-nexus component is responsible to query the fiat bank
+via EBICS every X seconds. X should match the tightest interval allowed
+by the bank.
+
+When libeufin-nexus registers an incoming payment on fiat-issuer in the
+database, a SQL trigger applies the **current** cash-in rates/fees and
+performs a wire transfer from regio-issuer to regio-exchange. Libeufin-bank
+makes the exchange aware via the Taler Wire Gateway API and from now on,
+the system proceeds like it always did in Taler.
diff --git a/design-documents/037-wallet-transactions-lifecycle.rst b/design-documents/037-wallet-transactions-lifecycle.rst
index 9d749595..7a8cfacd 100644
--- a/design-documents/037-wallet-transactions-lifecycle.rst
+++ b/design-documents/037-wallet-transactions-lifecycle.rst
@@ -525,64 +525,6 @@ the same as if the double-spending transaction had been deleted by the user.
.. image:: ../images/transaction-refresh-states.png
-
-Transaction Type: Reward
-------------------------
-
-* ``pending(user)``
-
- We have downloaded the metadata for the reward. This is the initial state for a
- reward transaction. The user needs to accept/refuse the reward.
-
- * ``[reward-expired] => expired``
- * ``[action:accept] => pending(pickup)``
-
-* ``pending(pickup)``
-
- We are picking up the reward.
-
- * ``[failure] => failed``: any type of failure, including expiration.
- * ``[processed-kyc-required] => pending(kyc-required)``
- * ``[success] => done``
- * ``[action:suspend] => suspended(pickup)``
-
-* ``suspended(pickup)``
-
- The user suspended the operation while the reward was being picked up.
-
- * ``[reward-expired] => failed``
- * ``[action:resume] => pending(pickup)``
-
-* ``pending(kyc)``
-
- The user needs to perform a KYC check to continue. This usually should only
- happen if the wallet balance exceeds some threshold.
-
- * ``[poll-success] => pending(pickup)``
- * ``[action:suspend] => suspended(kyc)``
-
-* ``suspended(kyc)``
-
- The user suspended the KYC operation. Note that we do not time out here if
- the reward expires, as the wallet balance threshold KYC likely applies even
- without the reward.
-
- * ``[action:resume] => pending(kyc)``
-
-* ``done``
-
- The reward operation completed.
-
- * ``[action:delete] => deleted``
-
-* ``deleted``
-
- All memory of the reward operation is lost, but of course the resulting fresh
- coins are preserved.
-
-.. image:: ../images/transaction-reward-states.png
-
-
Transaction Type: Deposit
-------------------------
diff --git a/design-documents/039-taler-browser-integration.rst b/design-documents/039-taler-browser-integration.rst
index 71feb1c6..980f3f25 100644
--- a/design-documents/039-taler-browser-integration.rst
+++ b/design-documents/039-taler-browser-integration.rst
@@ -54,13 +54,7 @@ The problems with individual browsers are:
either.
Another issue is that Websites can't easily find out whether a browser
-extension handling the ``taler://`` protocol is installed. To avoid using this
-information for fingerprinting, anchors could provide an alternative ``href``
-in case the main one is not handled, such as:
-
-.. code:: html
-
- <a href="taler://pay/..." handler-unavailable-href="https://wallet.taler.net/">...</a>
+extension handling the ``taler://`` protocol is installed.
Requirements
============
@@ -81,32 +75,87 @@ Requirements
should work smoothly with future browsers that
have native, built-in support for Taler payments.
+Proposed Solution
+=================
-Alternatives
-============
+.. note::
+
+ As of 2023-01-23, we've decided to go ahead with the approach
+ described in this section.
+
+Overview
+^^^^^^^^
+
+The following integration approaches between Websites and the Taler Wallet webextension
+are provided:
+
+1. Directly triggering a ``taler://...`` URI on page load (via a meta tag).
+2. Overriding ``<a href="taler://..." onclick=...>`` tags to trigger the wallet.
+ The onclick handler (which must call preventDefault) can implement behavior
+ that happens only when the webextension is not available.
+3. Future (possibly post-1.0): A ``window.taler`` JavaScript API that is injected
+ into every page that requests it via a meta tag. This is useful for SPAs that
+ want to programmatically trigger the Taler wallet.
+
+
+Usage
+^^^^^
+
+To directly trigger the handling of a ``taler://`` URI on page load, the following meta tag can be used:
+
+.. code::
+
+ <meta name="taler-uri" content="taler://...">
+
+
+To enable additional communication features between a website and the GNU Taler Wallet webextension, the page must
+include the following meta tag:
+
+.. code::
+
+ <meta name="taler-support" content="$features">
-* JavaScript API: The WebExtension could inject a JavaScript API into Websites
- that allow interacting with the Taler wallet. This is the approach taken by
- the MetaMask crypto wallet. It requires excessive permissions, may break
- some Websites (https://github.com/brave/browser-laptop/issues/13711) and
- requires merchants to include extra JavaScript.
-
- * This type of interaction is useful for Single Page Apps and
- might be provided by the GNU Taler wallet reference implementation,
- at least when the user grants additional permissions.
- * Unfortunately, browsers currently do not provide a safe way
- for the communication between a WebExtension and the page
- without excessive permissions. This especially applies
- if the Website does not know the extension's ID. Hard-coding
- the extension IDs would violate the "no vendor lock-in requirement".
-
-* Handling ``taler://`` URIs by overriding the onclick handler of ``a`` HTML elements.
- This requires excessive permissions but would be a viable work-around,
- at least on pages that opt in with a special ``<meta name="taler-support" content="uri">`` tag.
- It does not work in all use-cases, for example when a navigation
+where ``$features`` is a comma-separated list of features.
+
+The following features are supported:
+
+* ``uri`` will hijack anchor elements (``<a href="taler://..." onclick=...>``) and replace their onclick handler
+ with a different handler that lets the webexension wallet handle the ``taler://`` URI.
+
+* (future): ``api`` will inject the ``window.taler`` API into the page
+
+
+Caveats and Comments
+^^^^^^^^^^^^^^^^^^^^
+
+* Anchor tag hijacking does not work in all use-cases, for example when a navigation
to a ``taler://`` URI is initiated programmatically or by pasting
the URI in the browser's address bar.
+* The ``window.taler`` API injection may break some websites
+ (https://github.com/brave/browser-laptop/issues/13711).
+
+* All these approaches require excessive permissions, as unfortunately,
+ browsers currently do not provide a safe way for the communication between a
+ WebExtension and the page without excessive permissions. This especially
+ applies if the Website does not know the extension's ID. Hard-coding the
+ extension IDs would violate the "no vendor lock-in requirement".
+
+* A neat feature of the anchor hijacking is that the ``taler://`` URI can be always be copied
+ in the browser (via "copy link address"). Clicking the link always results in either:
+
+ * The native URI handler, if no Taler Wallet webextension is installed and no onclick handler is defined
+ * The execution of the websites onclick handler if no Taler Wallet webextension is installed
+ * Triggering the webextension wallet to handle the ``taler://`` URI.
+
+* Future ``window.taler`` injection should be based on user preferences on
+ sites where the user has explicitly accepted to disclose that is owner of a
+ Taler wallet.
+
+Other Alternatives
+==================
+
+
* Triggering interactions with the ``taler://`` URI in a ``Taler:`` HTTP
header. This approach would allow browsers with native Taler support
(or a WebExtension) to handle payment/withdrawal initiations directly,
@@ -133,6 +182,10 @@ Alternatives
the Web Payments API would not support the withdrawal flow
(``taler://withdraw`` URIs).
+* Browsers could provide anchor elements with a fallback when the protocol isn't supported, such as
+ ``<a href="taler://pay/..." handler-unavailable-href="https://wallet.taler.net/">...</a>``.
+
+
Related Work and References
===========================
diff --git a/design-documents/041-wallet-balance-amount-definitions.rst b/design-documents/041-wallet-balance-amount-definitions.rst
index 1c89d634..9943d482 100644
--- a/design-documents/041-wallet-balance-amount-definitions.rst
+++ b/design-documents/041-wallet-balance-amount-definitions.rst
@@ -245,20 +245,6 @@ REFUND
Is there a way that the merchant can initiate a refund of purchase + refund_fee so
the wallet will get the same effective_amount?
-REWARD
- raw amount is the amount that the merchant send as reward
-
- ``instructed_amount`` = reward.amount
-
- ``raw_amount`` = instructed_amount + withdrawal_fee
-
- ``effective_amount`` = instructed_amount
-
- .. note::
- We should not show fee for rewards in the wallet since the merchant is the one choosing
- the exchange and we can assume that those rewards are paid by the merchant.
- So the wallet only care about the effective.
-
Coin selection algorithm
------------------------
diff --git a/design-documents/044-ci-system.rst b/design-documents/044-ci-system.rst
index e777f345..e38632c0 100644
--- a/design-documents/044-ci-system.rst
+++ b/design-documents/044-ci-system.rst
@@ -6,7 +6,7 @@ Summary
This documents describes Taler's CI system based on Buildbot.
-This document uses `RFC 2119 <https://tools.ietf.org/html/rfc2119>`_
+This document uses `RFC 2119 <https://tools.ietf.org/html/rfc2119>`_
keywords throughout.
Motivation
@@ -43,27 +43,28 @@ Example directory structure:
::
- ci
- ├── ci.sh
- ├── Containerfile
- └── jobs
- ├── 0-codespell
- │   ├── config.ini
- │   ├── dictionary.txt
- │   └── job.sh
- ├── 1-build
- │   ├── build.sh
- │   └── job.sh
- └── 2-docs
- ├── docs.sh
- └── job.sh
-
-Job directories **MUST** follow this pattern:
-``<repo_root>/ci/jobs/<n-job_name>/``
+ contrib
+ └── ci
+ ├── ci.sh
+ ├── Containerfile
+ └── jobs
+ ├── 0-codespell
+ │   ├── config.ini
+ │   ├── dictionary.txt
+ │   └── job.sh
+ ├── 1-build
+ │   ├── build.sh
+ │   └── job.sh
+ └── 2-docs
+ ├── docs.sh
+ └── job.sh
+
+Job directories **MUST** follow this pattern:
+``<repo_root>/contrib/ci/jobs/<n-job_name>/``
``n`` is an integer used for ordering the build steps.
-Job directories **MUST** contain a script named ``job.sh`` which **MAY**
+Job directories **MUST** contain a script named ``job.sh`` which **MAY**
execute other scripts.
Config files may optionally be created, and MUST be named ``config.ini`` and
@@ -78,11 +79,12 @@ Available config options:
WARN_ON_FAILURE = True|False
CONTAINER_BUILD = True|False
CONTAINER_NAME = <string>
+ CONTAINER_ARCH = <string>
Unless *all* jobs specify a "CONTAINER_NAME" in their custom config a
-container file **MUST** be present at ``<repo_root>/ci/Containerfile``.
-The container file will be built and used to run all of a repo's jobs
+container file **MUST** be present at ``<repo_root>/contrib/ci/Containerfile``.
+The container file will be built and used to run all of a repo's jobs
by default.
All projects SHOULD have a ``build`` step and a ``test`` step, at a minimum.
@@ -92,24 +94,31 @@ Running CI Locally
Running the CI scripts locally can be useful for development and testing.
-*Be aware that custom configs for a given job may specify a alternate
-container.*
-
-
-Example of building the environment and running a job locally:
+Included in each CI directory is a script which simplifies running jobs
+in the same way the CI Worker does, in containers, using ``podman``.
::
- # From root of repo directory, build the container:
- docker build -t <local_name_for_container> -f ci/Containerfile . # <- don't forget the "."
-
- # Then to run one of the job scripts. For example:
- docker run --rm --volume $PWD:/workdir --workdir /workdir <local_name_for_container> ci/jobs/1-build/job.sh
-
- # or to get an interactive shell in the container, with the repo mounted at /workdir:
- docker run -ti --rm --volume $PWD:/workdir --workdir /workdir <local_name_for_container> /bin/bash
-
-
+ # Usage:
+ ./contrib/ci/ci.sh <job-name>
+
+ # For example, if the CI jobs tree looks like this:
+ ./contrib/ci/jobs
+ ├── 0-codespell/
+ ├── 1-build/
+ ├── 2-test/
+ ├── 3-docs/
+ ├── 4-deb-package/
+ └── 5-deploy-package/
+
+ # Then you can run job '0-codespell' as follows:
+ ./contrib/ci/ci.sh 0-codespell
+
+ # If you are using podman and have "qemu-user-binfmt" installed
+ # then you may attempt to run any job under an alternative CPU
+ # architecture by providing a second argument.
+ # For example:
+ ./contrib/ci/ci.sh 0-codespell arm64
Additional Builders
diff --git a/design-documents/046-mumimo-contracts.rst b/design-documents/046-mumimo-contracts.rst
index 5bc3d25a..fcb7f2b1 100644
--- a/design-documents/046-mumimo-contracts.rst
+++ b/design-documents/046-mumimo-contracts.rst
@@ -472,10 +472,7 @@ consumes an available discount token, that contract should be moved up in the
list.
Which specific alternative contract was chosen by the user is indicated in the
-subcontract index field of the :ref:`TALER_DepositRequestPS`.
-
-FIXME-DOLD: Should we also sign over this in the
-:ref:`TALER_DepositConfirmationPS`?
+subcontract index field of the :ref:`TALER_DepositRequestPS <taler_depositrequestps>`.
Output Commitments
@@ -483,8 +480,9 @@ Output Commitments
When a contract has outputs, the wallet must send an array of blinded tokens,
coins or tax receipts together with the payment request. The order in the
-array must match the order in the outputs field of the contract. For currency outputs, one array element must include all of the required planchets for a batch withdrawal,
-but of course not the reserve signature.
+array must match the order in the outputs field of the contract. For currency
+outputs, one array element must include all of the required planchets for a
+batch withdrawal, but of course not the reserve signature.
.. note::
@@ -492,10 +490,7 @@ but of course not the reserve signature.
batch-withdraw API to only use a single reserve signature.
This array of blinded values is hashed to create the output commitment hash
-(``h_outputs``) in the :ref:`TALER_DepositRequestPS`.
-
-FIXME-DOLD: Should we also sign over this in the
-:ref:`TALER_DepositConfirmationPS`?
+(``h_outputs``) in the :ref:`TALER_DepositRequestPS <taler_depositrequestps>`.
diff --git a/design-documents/048-wallet-exchange-lifecycle.rst b/design-documents/048-wallet-exchange-lifecycle.rst
index b3df4d8a..75ec3afb 100644
--- a/design-documents/048-wallet-exchange-lifecycle.rst
+++ b/design-documents/048-wallet-exchange-lifecycle.rst
@@ -67,14 +67,24 @@ Update Status
~~~~~~~~~~~~~
* ``initial``: Not updated, no need to update
-* ``initial(update)``: Update pending, possibly with error
+* ``initial-update``: Update pending, possibly with error
* ``suspended``: Exchange was manually disabled, should not be contacted
anymore, but record is kept in the wallet. Mostly useful for testing.
-* ``failed``: Updating the exchange info failed permanently, the exchange is
- not usable for any operations.
-* ``outdated(update)``
+* ``unavailable-update``: The exchange is currently unavailable to be used for withdrawals,
+ but it is possible that the exchange starts working again in the future.
+ The wallet will re-try contacting the exchange. The wallet will still try
+ operations that *spend* coins, but the user might be warned about the bad
+ exchange status.
+
+ Examples:
+
+ * The exchange updated to a new protocol version that is incompatible with the wallet
+ * The exchange advertises a new master public key. This might be a temporary
+ configuration issue or malicious attack.
+ * The exchange only advertises outdated denomination keys, making new withdrawals
+ impossible.
* ``ready``: Exchange is useable.
-* ``ready(update)``: Exchange is useable, but currently being updated.
+* ``ready-update``: Exchange is useable, but currently being updated.
ToS Status
~~~~~~~~~~
@@ -125,4 +135,10 @@ Definition of Done
Discussion / Q&A
================
-(This should be filled in with results from discussions on mailing lists / personal communication.)
+* Should there be a "permanently failed" update state?
+
+ * dold => I don't think so, as it means that temporary configuration issues on the side of the
+ exchange might *permanently* brick users' wallets.
+ The wallet should always re-try contacting the exchange and of course possibly report
+ information to the auditor.
+
diff --git a/design-documents/050-libeufin-nexus.rst b/design-documents/050-libeufin-nexus.rst
index 779e0b58..6049bda6 100644
--- a/design-documents/050-libeufin-nexus.rst
+++ b/design-documents/050-libeufin-nexus.rst
@@ -59,11 +59,11 @@ Configuration file
HOST_ID = mybank
USER_ID = myuser
PARTNER_ID = myorg
- SYSTEM_ID = banksys
- ACCOUNT_NUMBER = DE1234567890 # This value must identify with how the bank calls the bank account
+ IBAN = MY-IBAN
+ BIC = MY-BIC
+ NAME = MY NAME
BANK_PUBLIC_KEYS_FILE = enc-auth-keys.json
CLIENT_PRIVATE_KEYS_FILE = my-private-keys.json
- ACCOUNT_META_DATA_FILE = ebics-meta.json
BANK_DIALECT = postfinance # EBICS+ISO20022 style used by the bank.
[nexus-postgres]
@@ -112,15 +112,6 @@ JSON with:
* submitted_ini (boolean)
* submitted_hia (boolean)
-File contents: ACCOUNT_META_DATA_FILE
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-JSON with:
-
- * account_holder_iban
- * bank_code
- * account_holder_name
-
Database schema
---------------
@@ -194,15 +185,6 @@ The ebics-setup tool performs the following:
accept them (or auto-accept via --auto-accept-keys). If the user accepted
the public key, update the flag to "accepted".
- * If all of the above has happened and we have accepted public keys from the
- bank, try to download the list of bank accounts associated with the
- connection and check that the configured account number is among them. On
- success, store the associated meta data in the account meta data file. On
- failure, show an error message with the list of available accounts (also
- show this list via --show-associated-accounts). If the configured account
- number is available, show a brief "setup ready" message.
-
-
nexus-ebics-fetch
-----------------
@@ -214,6 +196,23 @@ nexus-ebics-fetch
over (before committing any transactions with the next day!) also fetches a
final statement of the previous day, thus ensuring we get a statement
every day plus intra-day reports.
+
+ .. note::
+
+ (1) "from that day forward (inclusive)" must **not** rely on EBICS returning
+ the unseen messages: that's because they might **already** be downloaded but
+ never made it to the database.
+
+ (2) "and when the day rolls over". When does a day roll over? => A day rolls
+ over when the current time is at least on the day after the transaction with the
+ most recent timestamp that's stored in the database.
+
+ (3) "Afterwards, fetches reports". This must happen **only after** any possible
+ previous statement got downloaded.
+
+ To summarize: at any point in time the database must contain (the content of) any
+ possible statement up to the current time, plus any possible report up to the current
+ time (in case that's not covered by any statement so far).
* Bounces transactions with mal-formed wire transfer subjects.
@@ -315,3 +314,41 @@ Discussion / Q&A
the bank response, may lead double-submission even if the HTTP talk ended
well: it suffices to crash after having received a "200 OK" response but
before setting the submitted flag to the database.
+
+* the ebics-submit section mentions the EBICS order ID. The following excerpt
+ was found however at page 88 of the EBICS 3 specifications:
+
+ ``OrderID is only present if a file is transmitted to the bank relating to an order with an
+ already existing order number (only allowed for AdminOrderType = HVE or HVS)``
+
+ Nexus does not support HVE or HVS.
+
+* As of private communication, the responsibility of submitting idempotent payments
+ relies on the use of ``request_uid`` (a database column of the initiated payment)
+ as the ``MsgId`` value of the corresponding pain.001 document.
+
+* ``submitted`` column of an initiated payment evolved into the following enum:
+
+ .. code-block:: shell-session
+
+ CREATE TYPE submission_state AS ENUM (
+ 'unsubmitted'
+ ,'transient_failure'
+ ,'permanent_failure'
+ ,'success'
+ ,'never_heard_back'
+ );
+
+ * ``unsubmitted``: default state when a payment is initiated
+ * ``transient_failure``: submission failed but can be retried, for example after a network issue.
+ * ``permanent_failure``: EBICS- or bank-technical error codes were not EBICS_OK (nor any tolerated EBICS code like EBICS_NO_DOWNLOAD_DATA_AVAILABLE), never retry.
+ * ``never_heard_back``: the payment initiation submission has **been** ``success`` but it was never confirmed by any outgoing transaction (from a camt.5x document) or any pain.002 report. It is responsability of a garbage collector to set this state after a particular time period.
+
+* the initiated_outgoing_transactions table takes two more columns:
+ ``last_submission_date``, a timestamp in microseconds, and a
+ ``submission_counter``. Both of them would serve to decide retry
+ policies.
+
+* the ``failure_text`` column at the initiated_outgoing_transactions table
+ should contain a JSON object that contains any useful detail about the problem.
+ That *could* be modeled after the Taler `ErrorDetail <https://docs.taler.net/core/api-common.html#tsref-type-ErrorDetail>`_, where at least the error code and the hint fields are provided.
diff --git a/design-documents/051-fractional-digits.rst b/design-documents/051-fractional-digits.rst
index 31e2959d..4321fd53 100644
--- a/design-documents/051-fractional-digits.rst
+++ b/design-documents/051-fractional-digits.rst
@@ -19,33 +19,30 @@ end-user apps should follow these guidelines.
Requirements
============
-There is already a specification for ScopedCurrencyInfo - this needs to change
+There was already a specification for ScopedCurrencyInfo - which got renamed to CurrencySpecification.
We need three core characteristics for fractional digits for each currency:
-e) the number of fractional digits e in [0..8] the user may 'e'nter in a TextInputField
+ e) the number of fractional digits e in [0..8] the user may 'e'nter in a TextInputField
-n) the number of fractional digits n in [0..8] to be rendered as 'n'ormal characters (same font and size as the integer digits).
- All additional fractional digits will be rendered as SuperScriptDigits as known from gas filling stations.
- The UI should never round or truncate any amount, but always render all existing digits (except trailing zeroes, see c).
+ n) the number of fractional digits n in [0..8] to be rendered as 'n'ormal characters (same font and size as the integer digits). All additional fractional digits will be rendered as SuperScriptDigits as known from gas filling stations. The UI should never round or truncate any amount, but always render all existing digits (except trailing zeroes, see c).
-z) the number of fractional digits z in [0..8] to be rendered as trailing 'z'eroes (including SuperScript digits).
- E.g. if z = 2 (and n = 2), then render $5 as “$ 5.00”.
- If z = 3 (and n = 2), then render $5 as “$ 5.00⁰” with two normal trailing zeroes and one superscript trailing zero.
+ z) the number of fractional digits z in [0..8] to be rendered as trailing 'z'eroes (including SuperScript digits). E.g. if z = 2 (and n = 2), then render $5 as ``$ 5.00``. If z = 3 (and n = 2), then render $5 as ``$ 5.00⁰`` with two normal trailing zeroes and one superscript trailing zero.
The values e, n, and z are independent from each other. Each could be any value
from 0 to 8. However, when a user enters an amount, s/he should be able to input
all normal fractionals. Thus e should never be smaller than n.
Usually, all these three numbers have the same value (e = n = z), which means
-that in case of e.g. “2” (used for €,$,£) the user can enter cent/penny values
+that in case of e.g. '2' (used for €,$,£) the user can enter cent/penny values
(but not a fraction of those), these cents/pennies are always shown (even if
they are 0) as two normal digits after the decimal separator, and fractions of
a cent/penny are rendered as SuperScriptDigits, but appear only if they are not
trailing zeroes.
For japanese ¥, all three values could be 0, which means that the user cannot
-enter fractionals at all. Fractions would never be rendered as normal digits
-but always as SuperScript, and appear only if they are not trailing zeroes.
+enter fractions at all. If there are fractions they would never be rendered as
+normal digits but always as SuperScript, and appear only if they are not
+trailing zeroes.
Additionally, some cryptocurrencies have such huge units, that they are
commonly rendered in milli-units, such as mBTC (milliBTC, 1/1000 of a BTC),
@@ -57,20 +54,6 @@ could also make sense for inflated currencies in some cases. So we probably
should also have the ability to ship such a conversion map.
-
-iOS has a built-in currency formatter, which knows how to deal with
-thousands-separators and where to apply them (e.g. India uses a mixture of
-hundreds and thousands instead of putting the separator after each 3 digits
-like western currencies). However, this formatter will round after two (or
-three) fractional digits and thus cannot be used for the whole amount. But it
-could be used to convert the integer part plus the fractional part to be
-rendered as normal digits (n) into a string, and then remaining fractional
-digits (if not zero, or if trailing SuperScript zeroes should be shown)
-could be added as SuperScript digits to this formatted string.
-
-(please add information about Android and WebEx here)
-
-
Proposed Solution
=================
@@ -78,7 +61,7 @@ Protocol considerations
-----------------------
The exchange, bank and merchant backends would need to be configured (via
-their configuration files) to return the following ScopedCurrencyInfo in their
+their configuration files) to return the following CurrencySpecification in their
``/config`` and/or ``/keys`` endpoints. The bank returns this so that the
bank SPA can render amounts correctly, the exchange informs the wallets about
the desired way to render the currency, and the merchant backend informs the
@@ -88,34 +71,37 @@ provisioned by all three services.
.. code-block:: swift
- public struct ScopedCurrencyInfo: Codable, Sendable {
+ public struct CurrencySpecification: Codable, Sendable {
// e.g. “Japanese Yen” or "Bitcoin (Mainnet)"
let name: String
- // e.g. “.” for $ and ¥; “,” for €
- let decimal_separator: String
- // how many digits the user may enter after the decimalSeparator
- let num_fractional_input_digits: Integer
+ // how many digits the user may enter after the decimal separator
+ let fractional_input_digits: Int
// €,$,£: 2; some arabic currencies: 3, ¥: 0
- let num_fractional_normal_digits: Int
- // usually same as numFractionalNormalDigits, but e.g. might be 2 for ¥
- let num_fractional_trailing_zero_digits: Int
- // true for “$ 3.50”; false for “3,50 €”
- let is_currency_name_leading: Bool
- // map of powers of 10 to alternative currency names / symbols, must
- // always have an entry under "0" that defines the base name,
- // e.g. "0 => €" or "3 => k€". For BTC, would be "0 => BTC, -3 => mBTC".
+ let fractional_normal_digits: Int
+ // usually same as fractionalNormalDigits, but e.g. might be 2 for ¥
+ let fractional_trailing_zero_digits: Int
+ // map of powers of 10 to alternative currency names / symbols,
+ // must always have an entry under "0" that defines the base name,
+ // e.g. "0 : €" or "3 : k€". For BTC, would be "0 : BTC, -3 : mBTC".
// This way, we can also communicate the currency symbol to be used.
- let alt_unit_names: Map<Int, String>
+ let alt_unit_names: [Int : String]
}
+(Note: decimal_separator, group_separator and is_currency_name_leading were
+removed from this struct since they should always be taken from the user's
+locale.)
+
+
+
+
For very large (2400000) or very tiny amounts (0.000056) the software would
then first represent the number compactly without any fraction (so for our
examples above, 24 * 10^6 and 56 * 10^-6) and then search for the nearest fit
in the alt_unit_names table. The result might then be 24000 KGELD or 0.056
mGELD, assuming the map had entries for 3 and -3 respectively. Depending on
-the table, the result could also be 24 MGELD (6 => MGELD), or 5.6 nGELD
-(assuming -6 => nGeld). Fractional rendering rules would still be applied
-to the alternative unit name, alas the "num_fractional_input_digits" would
+the table, the result could also be 24 MGELD (6 : MGELD), or 5.6 nGELD
+(assuming -6 : nGeld). Fractional rendering rules would still be applied
+to the alternative unit name, alas the "fractional_input_digits" would
always apply to the unit currency and may need to be adjusted if amounts
are input using an alternative unit name.
@@ -132,52 +118,52 @@ section. The map could be given directly in JSON. For example:
ENABLED = YES
name = "Euro"
code = "EUR"
- decimal_separator = ","
fractional_input_digits = 2
fractional_normal_digits = 2
fractional_trailing_zero_digits = 2
- is_currency_name_leading = NO
alt_unit_names = {"0":"€"}
[currency-japanese-yen]
ENABLED = YES
name = "Japanese Yen"
code = "JPY"
- decimal_separator = "."
fractional_input_digits = 2
fractional_normal_digits = 0
fractional_trailing_zero_digits = 2
- is_currency_name_leading = YES
alt_unit_names = {"0":"¥"}
[currency-bitcoin-mainnet]
ENABLED = NO
name = "Bitcoin (Mainnet)"
code = "BITCOINBTC"
- decimal_separator = "."
fractional_input_digits = 8
fractional_normal_digits = 3
fractional_trailing_zero_digits = 0
- is_currency_name_leading = NO
alt_unit_names = {"0":"BTC","-3":"mBTC"}
[currency-ethereum]
ENABLED = NO
name = "WAI-ETHER (Ethereum)"
code = "EthereumWAI"
- decimal_separator = "."
fractional_input_digits = 0
fractional_normal_digits = 0
fractional_trailing_zero_digits = 0
- is_currency_name_leading = NO
alt_unit_names = {"0":"WAI","3":"KWAI","6":"MWAI","9":"GWAI","12":"Szabo","15":"Finney","18":"Ether","21":"KEther","24":"MEther"}
Implementation considerations
-----------------------------
-For iOS, we plan to format the integer part of the amount with the built-in
-currency formatter, then add the fractional part according to this document.
+iOS has a built-in currency formatter, which can be configured from a locale.
+It knows how to deal with group-separators and where to apply them (e.g. India
+uses a mixture of thousands and hundreds instead of putting the separator after
+each 3 digits like western currencies).
+Set the formatter's parameter 'maximumFractionDigits' to 8, then it will not
+round the value and thus can be used for the whole amount.
+Set its parameter 'minimumFractionDigits' to 'z' (fractionalTrailingZeroDigits)
+to let it automatically add trailing zeroes.
+Then convert all fractional digits after 'n' (fractionalNormalDigits) to
+SuperScript digits.
(please add information about Android and WebEx here)
@@ -213,7 +199,7 @@ Discussion / Q&A
We probably should NOT have the decimalSeparator in this definition. Instead that
should be taken from the locale of the user, so they see currency amounts formatted
like they're used to.
-If we really keep this, then we would also need the thousandsSeparator to ensure it is
+If we really keep this, then we would also need the groupSeparator to ensure it is
not identical to the decimalSeparator.
Better to leave this can of worms to the operating system our app runs on, and render
according to the user's preferences (locale)...
diff --git a/design-documents/052-libeufin-bank-2fa.rst b/design-documents/052-libeufin-bank-2fa.rst
new file mode 100644
index 00000000..3d0900e2
--- /dev/null
+++ b/design-documents/052-libeufin-bank-2fa.rst
@@ -0,0 +1,136 @@
+DD 52: LibEufin Bank Two-factor authentification
+################################################
+
+Summary
+=======
+
+This document proposes designs for supporting 2-FA for more operations in
+libeufin-bank.
+
+Motivation
+==========
+
+Currently, only cashout operations are protected using 2-FA and we want to also
+protects withdrawal, transactions, account reconfiguration and account deletion.
+
+Requirements
+============
+
+* Support future TAN channels (YubiKey, trusted devices, etc) without API-breaking changes
+* Support multiple TAN channels per user
+
+Proposed Solutions
+==================
+
+2 kinds of operations
+^^^^^^^^^^^^^^^^^^^^^
+
+We have two kinds of operations we would like to protect:
+
+* state-machine operations that already have a ``pending`` and ``confirmed`` status and require multiple endpoint calls to complete (cashout and withdrawal).
+* one-shot operations that are currently completed using a single endpoint call (transaction, account reconfiguration and account deletion).
+
+Fine-grained or coarse-grained authentification
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+* Fine-grained authorization is when one challenge is linked to a unique unalterable operation. They are the most secure and have the usability advantage that clients can show users exactly what they are allowing. They are complicated to implement especially for one-shot operations.
+* Coarse-grained authorization is when each challenge allows to perform one or many protected operations of any kind. They are the simplest to implement and might be enough for our needs.
+
+We should also take in consideration how hard it would be to maintain the solution and how hard it would be to protect a new kind of operation in the future.
+
+State machines operations only
+------------------------------
+
+If we transform all operations to become state-machine ones, we can use the same design currently used for cashout operations. All operations are created in a ``pending`` state and need to be confirmed later. The TAN challenge code is sent when the operation is created and checked during confirmation. Operation creation is idempotent and can be used to trigger code retransmission.
+
+The good
+^^^^^^^^
+
++ Fine-grained authorization
+
+The bad
+^^^^^^^
+
+- Requires to store pending operations in the database, requires new tables to store pending state for one-shot ones
+- Requires to add many endpoints to track operations status, list pending operations, confirm operations, etc
+- Requires to mix TAN challenge logic with operation logic, this means asking for TAN channel alongside operation data and returning TAN specific error in all operation creation and confirmation endpoints, therefore TAN logic changes can impact all those endpoints
+- Operation logic rewrite
+- Big backend and database change (new table or column and new API per operation)
+
+
+Centralized 2FA endpoints
+-------------------------
+
+To improve upon the previous design we can separate endpoints to perform TAN challenges from operation ones. When creating operations they return a challenge ID that can be used with TAN-specific endpoints to receive and solve a challenge. Those endpoints will handle the TAN channel choice and TAN-specific errors. Protected endpoints will error when a pending challenge hasn't been solved.
+
+The good
+^^^^^^^^
+
++ Fine-grained authorization
++ Centralized TAN challenge logic and error handling, TAN logic changes only impact TAN-specific endpoints
+
+The bad
+^^^^^^^
+
+- Requires to store pending operations in the database
+- Requires adding many endpoints to track operations status, confirm operations, list pending operations, etc.
+- Operation logic rewrite
+- Big backend and database change (new table or column and new API per operation)
+
+2FA tokens
+----------
+
+To improve upon the previous design, if coarse-grained authorization is enough, we can have a simpler design where a successful challenge produces a one-use 2FA token. Protected endpoints will error when a 2FA token is required and the token is provided through an HTTP header.
+
+We could require a 2FA token when confirming state-machine operations or when performing one-shot ones. Removing the need for new database tables and operation endpoints.
+
+The good
+^^^^^^^^
+
++ Existing database tables stay the same
++ Centralized TAN challenge logic and error handling
++ Most endpoints stay the same except the cashout API
++ Can protect new operations without changing their logic but need to add token consumption logic to the database transaction
++ Small backend and database change per operation (token consumption logic)
+
+The bad
+^^^^^^^
+
+- Using a nonstandard header can be complicated for some clients
+- The pending state of one-shot operations is kept at the client level, this is a simplification for the backend but we do not want to lose this state. This might be easy to do as all oneshot operations are simple ones and the token can be obtained in advance.
+- Coarse-grained authorization, one token for any operation. We could fix this by adding a ``kind`` field and an optional ``operation_id`` (state-machine operation) or ``operation_body`` (one-shot operations) field per challenge but this is ugly.
+
+2FA auth tokens
+---------------
+To improve upon the previous design, we could reuse the existing authentification token logic and create a new scope, ``2fa``, that works as an augmented ``readwrite``. Those auth tokens would be valid for a short amount of time (~3 minute) and would not be refreshable.
+
+The good
+^^^^^^^^
+
++ Existing database tables stay the same
++ Centralized TAN challenge logic and error handling
++ Most endpoints stay the same except the cashout API
++ Can protect new operations without changing their logic
++ Trivial backend and database change per operation (one line of code per operation)
+
+The bad
+^^^^^^^
+
+- Having a short-term token in addition to a long-term refreshable token can be confusing for clients.
+- We still keep the pending state of one-shot operations at the client level.
+- Coarse-grained authorization, one token for any operation for a short amount of time.
+
+Q / A
+=====
+
+* Q: Where do we want to handle TAN challenges logic and error handling, in each operation API or a TAN-specific API?
+
+ * In each operation means fewer API calls and TAN-specific means more API calls but better/cleaner logic separation.
+
+* Q: Where do we want to store pending states for oneshot transactions in the client or the backend database?
+
+ * In the client makes things simpler for the backend but is incompatible with coarse-grained authorization.
+
+* Q: Do we need coarse-grained authorization or fine-grained is enough?
+
+ * Coarse-grained authorization requires that we store pending states for operations even for the ones that are currently oneshot. We could use a different strategy for each kind. \ No newline at end of file
diff --git a/design-documents/053-wallet-ui.rst b/design-documents/053-wallet-ui.rst
new file mode 100644
index 00000000..c36d4759
--- /dev/null
+++ b/design-documents/053-wallet-ui.rst
@@ -0,0 +1,355 @@
+DD 53: Wallet UI Design
+#######################
+
+Summary
+=======
+
+This document proposes designs wallet UI. It defines what Android, iOS and
+WebExtension should follow in order to have a coherent UI between platforms.
+
+Motivation
+==========
+
+We want user to be able to help each others independent of the implementation
+they are using.
+We want user to be able to capitalize the effort of learning how to use one
+wallet and be able to use a different one without the need to learn
+anything new.
+Currently development of different platform specific implementation are independent
+and every developer needs to choose the layout, texts and buttons and navigation.
+
+Requirements
+============
+
+Every screen MUST be defined in a document with the following information:
+
+* **Identifiable UI screens**: every UI should have an unique identifier that will
+ be use for development discussion and bug reports. There should be an option
+ in the application to enable an active rendering of the id.
+
+* **Description**: the reason to be of the screen, should help to define what will
+ be included into, what is going to left for other screens and when and from
+ where should be linked.
+
+The screen MAY also have:
+
+* **Predefined assets**: every implementation should resue the same icons, images,
+ fonts and sounds.
+
+Additionaly the document COULD defined the components of the UI. If one of this
+properties is defined in the spec the implementation must implement it. The specification
+should be minimal to achieve the objective in the description.
+
+* **Info**: Spec of information that the user should have access. The type of info
+ could be a field (id and value) or a banner (information and instructions).
+ The spec will help to reuse the text for i18n across apps and defined
+
+* **Inputs**: Spec of information need to provide in current screen. The type of input,
+ range of values and validation should be defined if necessary.
+
+* **Actions**: Spec of buttons and interactable elements that will have a significant
+ change in the current state. It should also mention navigation when applicable.
+
+* **Layout**: Spec position of elements when needed. The spec should be "soft" in a sense
+ that elements should be easy to find following directions like "close to X" or
+ "at the start/end of the screen".
+
+Screen should be defined using the most relaxed definition that are good enough to
+be clear for the user. Platform will use this definition and adapt to the differences
+on the platform taking advantange of platform API and screen sizes.
+
+When a screen have multiple uses for the same purpose, a substate section should be
+included with the difference with the main definition.
+
+Part of the screens that are reused shoud also be defined in this document as screen.
+
+Common definition:
+ * navigation between screen should not happen if the user didn't take any action
+
+
+Proposed Solutions
+==================
+
+List of all screens with the defined properties.
+
+cta-withdraw
+------------
+
+``Description``: this screen is used for the confirmation of a manual withdrawal,
+bank-integrated witdrawals and exchange withdrawals.
+the success of this operation will be an increase of the balance in the wallet.
+fee, restrictions and ETA should be clear for the user.
+
+``Info``:
+ * exchange to be used showing the URL
+ * table of details of the operation: use the ``operation-table-details`` screen
+ * starting currency: if the exchange has the currency conversion service enabled user should be able to the details based on the wire transfer currency
+ * taler URI: show copy button or QR to complete the operation with another device
+
+``Inputs``:
+ * age restriction: allow the selection of the restriction in the age group possible by the exchange
+ * service provider: allow the selection of different exchange
+
+``Actions``:
+ * confirm operation: on success will be redirected to the ``transaction-details`` screen where the detail of the current transaction will be displayed
+ * review and confirm ToS: if the current selected exchange has a version of ToS that the user didn't yet accepted, use the ``accept-tos`` screen
+ * cancel: user will be redirected to ``balance``
+
+.. attention::
+ User should be able to play with the amount, not possible in the current design
+
+cta-wire-transfer
+-----------------
+
+``Description``: this screen is used to show the user the information for
+the wire transfer to complete a manual withdrawal operation.
+
+``Info``:
+ * wire transfer subject to be used (first, most important)
+ * target bank account to transfer funds to (e.g. IBAN)
+ * total amount to transfer in the wire transfer currency
+ * button to copy ``payto://`` URI with the information to clipboard
+
+``Actions``:
+ * abort: aborts the withdrawal operation
+ * menu: go back to the main balances list (operation continues in background)
+ * automatic: screen changes to "cta-withdraw-done" upon completion
+
+.. image:: ../screenshots/cta-wire-transfer-firefox-latest.png
+
+cta-withdraw-done
+-----------------
+
+``Description``: this screen is used to show the user the information for
+a completed withdraw operation (bank-integrated or manual)
+
+``Info``:
+ * amount wired (hidden if no fees)
+ * fees paid (hidden if no fees)
+ * total amount withdrawn into wallet (effective balance change)
+ * exchange base URL
+ * date
+
+``Actions``:
+ * delete: deletes information about the withdrawal operation
+
+.. image:: ../screenshots/cta-withdraw-done-firefox-latest.png
+
+
+cta-url-entry
+-------------
+
+``Description``: this screen allows the user to scan a QR code, scan an NFC
+tag, or enter a taler://-URL. Its implementation may differ significantly
+between platforms. For example, scanning NFC tags may be fully automated,
+scanning QR codes may involve some system applications, and maybe the dialog
+only allows the URL entry *or* the camera but not both at the same time,
+depending on implementation specifics.
+
+``Info``:
+ * camera with current image to enable user to focus on QR code
+ * current URL, with information if it is not well-formed for GNU Taler
+ * possibly status information on NFC reader (if available)
+
+``Actions``:
+ * open: if entered manually, open URL as-entered (otherwise open is automatic)
+ * back: return to previous view
+
+.. image:: ../screenshots/cta-url-entry-firefox-latest.png
+
+
+cta-payment
+-----------
+
+``Description``: this screen is used for the confirmation of a payment to a merchant.
+the success of this operation will be an decrease of the balance in the wallet
+and save a ticket/invoice of the purchase.
+fee, restrictions and ETA should be clear for the user.
+
+``Info``:
+ * merchant offering the order showing the URL
+ * order summary
+ * table of details of the operation: use the ``operation-table-details`` screen
+ * receipt: order id
+ * payment deadline: absolute time before the claimed order expires
+ * taler URI: show copy button or QR to complete the operation with another device
+ * cant pay desc: if the user has enough balance but unable to use it
+ * payment status: if the
+
+``Actions``:
+ * confirm operation: if the payment is possible, on success will be redirected to the ``transaction-details`` screen where the detail of the current transaction will be displayed
+ * get more cash: if there is not enough balance, it will be redirected to ``cta-witddraw``
+ * cancel: user will be redirected to ``balance``
+
+.. image:: ../screenshots/cta-payment-firefox-latest.png
+
+cta-payment-paid
+----------------
+
+``Description``: this screen is used to show information with details
+about a historic payment.
+
+``Info``:
+ * merchant offering the order showing the URL
+ * order summary
+ * table of details of the operation: use the ``operation-table-details`` screen
+ * receipt: order id
+ * payment status: if the order was refunded
+
+``Actions``:
+ * delete: delete information about the transaction
+ * back: user will be redirected to ``balance``
+
+.. image:: ../screenshots/cta-payment-paid-firefox-latest.png
+
+cta-deposit
+------------
+
+``Description``: this screen is used for the confirmation of a deposit.
+the success of this operation will be an decrease of the balance in the wallet
+and save a deposit ticket for reference.
+fee, restrictions and ETA should be clear for the user.
+
+``Info``:
+ * bank account where the money is going to
+ * table of details of the operation: use the ``operation-table-details`` screen
+
+``Actions``:
+ * confirm operation: on success will be redirected to the ``transaction-details`` screen where the detail of the current transaction will be displayed
+ * cancel: user will be redirected to ``balance``
+
+.. attention::
+ User should be able to play with the amount, not possible in the current design
+
+
+cta-peer-pull-initiate
+----------------------
+
+``Description``: this screen is used for the confirmation of the creation of
+a peer pull transaction or invoice to request money from another wallet.
+the success of this operation will not change the balance immediately in the wallet
+and allow the user to share a taler URI to the payer.
+fee, restrictions and ETA should be clear for the user.
+
+``Info``:
+ * exchange to be used showing the URL
+ * table of details of the operation: use the ``operation-table-details`` screen
+
+``Inputs``:
+ * subject: short description of the transaction
+ * expiration: absolute time/date after which the invoice is not valid anymore
+ * service provider: allow the selection of different exchange
+
+``Actions``:
+ * confirm operation: on success will be redirected to the ``transaction-details`` screen where the detail of the current transaction will be displayed
+ * review and confirm ToS: if the current selected exchange has a version of ToS that the user didn't yet accepted, use the ``accept-tos`` screen
+ * cancel: user will be redirected to ``balance``
+
+.. attention::
+ Is the invoice creation always free of charge or does the exchange have a mechanism
+ to impose a fee to pay on creation?
+
+
+cta-peer-pull-confirm
+---------------------
+
+``Description``: this screen is used for the confirmation of the payment of
+a peer pull transaction or invoice to send money from another wallet.
+the success of this operation will be an will decrease the balance in the wallet.
+fee, restrictions and ETA should be clear for the user.
+
+``Info``:
+ * exchange to be used showing the URL
+ * subject: short description of the transaction
+ * table of details of the operation: use the ``operation-table-details`` screen
+ * expiration: absolute time/date after which the invoice is not valid anymore
+
+``Actions``:
+ * confirm operation: if the payment is possible, on success will be redirected to the ``transaction-details`` screen where the detail of the current transaction will be displayed
+ * get more cash: if there is not enough balance, it will be redirected to ``cta-witddraw``
+ * cancel: user will be redirected to ``balance``
+
+cta-peer-push-initiate
+----------------------
+
+``Description``: this screen is used for the confirmation of the creation of
+a peer push transaction or transfer money to another wallet.
+the success of this operation will reduce the balance immediately in the wallet
+and allow the user to share a taler URI to the receiver.
+fee, restrictions and ETA should be clear for the user.
+
+``Info``:
+ * table of details of the operation: use the ``operation-table-details`` screen
+
+``Inputs``:
+ * subject: short description of the transaction
+ * expiration: absolute time/date after which the transfer is not valid anymore
+
+``Actions``:
+ * confirm operation: on success will be redirected to the ``transaction-details`` screen where the detail of the current transaction will be displayed
+ * cancel: user will be redirected to ``balance``
+
+cta-peer-push-confirm
+---------------------
+
+``Description``: this screen is used for the confirmation of the acceptance of
+a peer push transaction or transfer money to this wallet.
+the success of this operation will be an will decrease the balance in the wallet.
+fee, restrictions and ETA should be clear for the user.
+
+``Info``:
+ * subject: short description of the payment
+ * expiration: absolute time/date after which the invoice is not valid anymore
+ * table of details of the operation: use the ``operation-table-details`` screen
+
+``Actions``:
+ * confirm operation: on success will be redirected to the ``transaction-details`` screen where the detail of the current transaction will be displayed
+ * review and confirm ToS: if the current selected exchange has a version of ToS that the user didn't yet accepted, use the ``accept-tos`` screen
+ * cancel: user will be redirected to ``balance``
+
+
+operation-table-details
+-----------------------
+
+``Description``: with the table it should be clear how much the operation will cost,
+the initial amount and the final amount with all the items related to the operations (like fee)
+
+``labels``: initial amount of the operation, and final amount are always shown.
+Fee should be shown as an extra row in the table if it is non-zero.
+Converted amount should be shown as an extra row if initial amount currency is not the same
+as the final amount currency.
+
+Initial amount label by operation:
+
+ * payment -> Price
+ * deposit -> Send
+ * peer-pull-credit -> Invoice
+ * peer-pull-debit -> Invoice
+ * peer-push-debit -> Send
+ * peer-push-credit -> Transfer
+ * withdrawal -> Transfer
+ * refund -> Refund
+
+
+accept-tos
+----------
+
+``Description``: this screen can be use everytime that the user is going to interact
+with an exchange. since at any moment wallet may find that ToS changed the user needs
+to be prevented from continue before reading/accepting new rules. If possible, this
+screen should be used inplace of other actions and hidden if not required (for example,
+user already accepted ToS)
+
+``Inputs``:
+ * format: allow the selection of a ToS format
+ * languange: allow the selection of a languange different from system lang
+
+``Actions``:
+ * accept tos: will mark this version as accepted in wallet core and redirect the user to the screen from where it was invoked
+ * save/print tos: will save the ToS outside of the wallet
+
+.. image:: ../screenshots/cta-accept-tos-firefox-latest.png
+
+
+Q / A
+=====
diff --git a/design-documents/054-dynamic-form.rst b/design-documents/054-dynamic-form.rst
new file mode 100644
index 00000000..6ff84d41
--- /dev/null
+++ b/design-documents/054-dynamic-form.rst
@@ -0,0 +1,201 @@
+DD 54: Dynamic Web Form
+#######################
+
+Summary
+=======
+
+This document outlines the approach for implementing a dynamic web form feature.
+
+Motivation
+==========
+
+Currently, creating a new form for a web app involves coding a new
+page with HTML, CSS, and JS. Exchange AML requires multiple forms,
+and different instances may have distinct forms based on jurisdiction.
+
+
+Requirements
+============
+
+A form consist of a layout and a set of fields.
+
+Layout requirements
+-------------------
+
+* **editable by system admin**: System admins should be able to create new forms
+ or edit current one shipped with the source.
+
+* **accesibility**: Forms should meet accessibility level AA.
+
+* **responsive**: Forms should be responsive and function on all devices.
+
+* **metadata**: Generated form information should contain enough data
+ to handle multiple form versions.
+
+Fields requirements
+-------------------
+
+* **validations**: Each field may require custom validation
+
+* **custom data type**: A field may consist of a list, string, number, or a
+ complex composite structure.
+
+
+Proposed Solutions
+==================
+
+Forms are initialized using a flexible structure defined by the
+TypeScript interface FormType<T>. This interface comprises properties
+such as value (current form data), initial (initial form data for resetting),
+readOnly (flag to disable input), onUpdate (callback on form data update),
+and computeFormState (function to derive the form state based on current data).
+
+
+.. code-block:: javascript
+
+ interface FormType<T extends object> {
+ value: Partial<T>;
+ initial?: Partial<T>;
+ readOnly?: boolean;
+ onUpdate?: (v: Partial<T>) => void;
+ computeFormState?: (v: Partial<T>) => FormState<T>;
+ }
+
+
+``T``: is the type of the result object
+``value``: is a reference to the current value of the result
+``initial``: data for resetting
+``readOnly``: when true, fields won't allow input
+``onUpdate``: notification of the result update
+``computeFormState``: compute a new state of the form based on the current value
+
+Form state have the same shape of ``T`` but every field type is ``FieldUIOptions``.
+
+Fields type can be:
+ * strings
+ * numbers
+ * boolean
+ * arrays
+ * object
+
+The field type ``AmountJson`` and ``AbsoluteTime`` are opaque since field is used as a whole.
+
+The form can be instanciated using
+
+.. code-block:: javascript
+
+ import { FormProvider } from "@gnu-taler/web-util/browser";
+
+
+Then the field component can access all the properties by the ``useField(name)`` hook,
+which will return
+
+.. code-block:: javascript
+
+ interface InputFieldHandler<Type> {
+ value: Type;
+ onChange: (s: Type) => void;
+ state: FieldUIOptions;
+ isDirty: boolean;
+ }
+
+
+``value``: the current value of the field
+``onChange``: a function to call anytime the user want to change the value
+``state``: the state of the field (hidden, error, etc..)
+``isDirty``: if the user already tried to change the value
+
+A set of common form field exist in ``@gnu-taler/web-util``:
+
+ * InputAbsoluteTime
+ * InputAmount
+ * InputArray
+ * InputFile
+ * InputText
+ * InputToggle
+
+and should be used inside a ``Form`` context.
+
+.. code-block:: javascript
+
+ function MyFormComponent():VNode {
+ return <FormProvider >
+ <InputAmount name="amount" />
+ <InputText name="subject" />
+ <button type="submit"> Confirm </button>
+ </FormProvider>
+ }
+
+
+Example
+--------
+
+Consider a form shape represented by the TypeScript type:
+
+.. code-block:: javascript
+
+ type TheFormType = {
+ name: string,
+ age: number,
+ savings: AmountJson,
+ nextBirthday: AbsoluteTime,
+ pets: string[],
+ addres: {
+ street: string,
+ city: string,
+ }
+ }
+
+An example instance of this form could be:
+
+.. code-block:: javascript
+
+ const theFormValue: TheFormType = {
+ name: "Sebastian",
+ age: 15,
+ pets: ["dog","cat"],
+ address: {
+ street: "long",
+ city: "big",
+ }
+ }
+
+
+For such a form, a valid state can be computed using a function like
+``computeFormStateBasedOnFormValues``, returning an object indicating
+the state of each field, including properties such as ``hidden``,
+``disabled``, and ``required``.
+
+
+.. code-block:: javascript
+
+ function computeFormStateBasedOnFormValues(formValues): {
+ //returning fixed state as an example
+ //the return state will be commonly be computed from the values of the form
+ return {
+ age: {
+ hidden: true,
+ },
+ pets: {
+ disabled: true,
+ elements: [{
+ disabled: false,
+ }],
+ },
+ address: {
+ street: {
+ required: true,
+ error: "the street name was not found",
+ },
+ city: {
+ required: true,
+ },
+ },
+ }
+ }
+
+
+
+
+Q / A
+=====
diff --git a/design-documents/055-wallet-problem-report.rst b/design-documents/055-wallet-problem-report.rst
new file mode 100644
index 00000000..84c6159a
--- /dev/null
+++ b/design-documents/055-wallet-problem-report.rst
@@ -0,0 +1,85 @@
+DD 55: Wallet Problem Reports
+#############################
+
+.. note::
+
+ **Status**: Early work in progress / DD number reservation.
+
+Summary
+=======
+
+This design document specifies global error reports generated/managed by wallet-core
+and rendered by the wallet UIs.
+
+Motivation
+==========
+
+Sometimes the wallet encounters issues that go beyond the scope of single transaction.
+
+Requirements
+============
+
+* problem reports must have a clear lifecycle
+* problem reports must have some type of identification that allows to
+ easily find out if a new problem report needs to be created when an
+ error happens or whether an existing one has been created
+
+Proposed Solution
+=================
+
+Report identification
+---------------------
+
+The report identifier serves multiple purposes:
+
+1. Usage as a reference in wallet-core APIs
+2. De-duplication. The report ID should allow easy identification of an already existing report for a particular problem.
+
+New wallet-core requests
+------------------------
+
+* ``listProblemReports``
+* ``acknowledgeProblemReport``: Mark a problem report as read.
+* ``deleteProblemReport``: Delete the problem report.
+
+New wallet-core notification type
+---------------------------------
+
+* ``problem-report`` to notify clients about status changes or an error report
+ (including creation!)
+
+
+Types of reports
+----------------
+
+* money lost due to the exchange stopping to offer a denomination
+* money locked behind a (long) pending refresh
+* money lost due to a permanently failing refresh
+* money lost due to expired denominations (auto-refresh wasn't done fast enough)
+* exchange changed its master public key
+* a denomination changed its info (expiration, fees)
+
+
+Definition of Done
+==================
+
+TBD.
+
+Alternatives
+============
+
+TBD.
+
+Drawbacks
+=========
+
+TBD.
+
+Discussion / Q&A
+================
+
+* When is a report amended vs a new report created?
+
+ * example: Exchange stops offering denomination D1. Later, it stops offering D2.
+ Are two reports generated or is the first report changed?
+
diff --git a/design-documents/index.rst b/design-documents/index.rst
index eba03307..454564d0 100644
--- a/design-documents/index.rst
+++ b/design-documents/index.rst
@@ -63,4 +63,8 @@ Design documents that start with "XX" are considered deprecated.
049-auth.rst
050-libeufin-nexus.rst
051-fractional-digits.rst
+ 052-libeufin-bank-2fa.rst
+ 053-wallet-ui.rst
+ 054-dynamic-form.rst
+ 055-wallet-problem-report.rst
999-template
diff --git a/design-documents/wallet-screenshots/ios-wallet/withdraw-bankIntegrated/CHF/cta-withdraw-sheet130-withdraw-confirm.png b/design-documents/wallet-screenshots/ios-wallet/withdraw-bankIntegrated/CHF/cta-withdraw-sheet130-withdraw-confirm.png
new file mode 100644
index 00000000..11dd9db0
--- /dev/null
+++ b/design-documents/wallet-screenshots/ios-wallet/withdraw-bankIntegrated/CHF/cta-withdraw-sheet130-withdraw-confirm.png
Binary files differ
diff --git a/design-documents/wallet-screenshots/ios-wallet/withdraw-bankIntegrated/CHF/cta-withdraw-sheet130-withdraw.png b/design-documents/wallet-screenshots/ios-wallet/withdraw-bankIntegrated/CHF/cta-withdraw-sheet130-withdraw.png
new file mode 100644
index 00000000..d46f0e5c
--- /dev/null
+++ b/design-documents/wallet-screenshots/ios-wallet/withdraw-bankIntegrated/CHF/cta-withdraw-sheet130-withdraw.png
Binary files differ
diff --git a/design-documents/wallet-screenshots/ios-wallet/withdraw-bankIntegrated/CHF/cta-withdraw-sheet133-withdraw-confirm-bank.png b/design-documents/wallet-screenshots/ios-wallet/withdraw-bankIntegrated/CHF/cta-withdraw-sheet133-withdraw-confirm-bank.png
new file mode 100644
index 00000000..5d7dd8cd
--- /dev/null
+++ b/design-documents/wallet-screenshots/ios-wallet/withdraw-bankIntegrated/CHF/cta-withdraw-sheet133-withdraw-confirm-bank.png
Binary files differ
diff --git a/design-documents/wallet-screenshots/ios-wallet/withdraw-bankIntegrated/CHF/cta-withdraw-view22-balances.png b/design-documents/wallet-screenshots/ios-wallet/withdraw-bankIntegrated/CHF/cta-withdraw-view22-balances.png
new file mode 100644
index 00000000..473621e8
--- /dev/null
+++ b/design-documents/wallet-screenshots/ios-wallet/withdraw-bankIntegrated/CHF/cta-withdraw-view22-balances.png
Binary files differ
diff --git a/design-documents/wallet-screenshots/ios-wallet/withdraw-bankIntegrated/cta-withdraw-bank-confirm.png b/design-documents/wallet-screenshots/ios-wallet/withdraw-bankIntegrated/cta-withdraw-bank-confirm.png
new file mode 100644
index 00000000..4441777a
--- /dev/null
+++ b/design-documents/wallet-screenshots/ios-wallet/withdraw-bankIntegrated/cta-withdraw-bank-confirm.png
Binary files differ
diff --git a/design-documents/wallet-screenshots/ios-wallet/withdraw-bankIntegrated/cta-withdraw-bank-confirmed.png b/design-documents/wallet-screenshots/ios-wallet/withdraw-bankIntegrated/cta-withdraw-bank-confirmed.png
new file mode 100644
index 00000000..c356eb13
--- /dev/null
+++ b/design-documents/wallet-screenshots/ios-wallet/withdraw-bankIntegrated/cta-withdraw-bank-confirmed.png
Binary files differ
diff --git a/design-documents/wallet-screenshots/ios-wallet/withdraw-bankIntegrated/cta-withdraw-bank-register.png b/design-documents/wallet-screenshots/ios-wallet/withdraw-bankIntegrated/cta-withdraw-bank-register.png
new file mode 100644
index 00000000..e7b7c1f9
--- /dev/null
+++ b/design-documents/wallet-screenshots/ios-wallet/withdraw-bankIntegrated/cta-withdraw-bank-register.png
Binary files differ
diff --git a/design-documents/wallet-screenshots/ios-wallet/withdraw-bankIntegrated/cta-withdraw-bank-send-money.png b/design-documents/wallet-screenshots/ios-wallet/withdraw-bankIntegrated/cta-withdraw-bank-send-money.png
new file mode 100644
index 00000000..788ae7ab
--- /dev/null
+++ b/design-documents/wallet-screenshots/ios-wallet/withdraw-bankIntegrated/cta-withdraw-bank-send-money.png
Binary files differ
diff --git a/design-documents/wallet-screenshots/ios-wallet/withdraw-bankIntegrated/cta-withdraw-bank-withdraw.png b/design-documents/wallet-screenshots/ios-wallet/withdraw-bankIntegrated/cta-withdraw-bank-withdraw.png
new file mode 100644
index 00000000..74e1efff
--- /dev/null
+++ b/design-documents/wallet-screenshots/ios-wallet/withdraw-bankIntegrated/cta-withdraw-bank-withdraw.png
Binary files differ
diff --git a/design-documents/wallet-screenshots/ios-wallet/withdraw-bankIntegrated/cta-withdraw-sheet130-withdraw-confirm.png b/design-documents/wallet-screenshots/ios-wallet/withdraw-bankIntegrated/cta-withdraw-sheet130-withdraw-confirm.png
new file mode 100644
index 00000000..22c57d66
--- /dev/null
+++ b/design-documents/wallet-screenshots/ios-wallet/withdraw-bankIntegrated/cta-withdraw-sheet130-withdraw-confirm.png
Binary files differ
diff --git a/design-documents/wallet-screenshots/ios-wallet/withdraw-bankIntegrated/cta-withdraw-sheet130-withdraw.png b/design-documents/wallet-screenshots/ios-wallet/withdraw-bankIntegrated/cta-withdraw-sheet130-withdraw.png
new file mode 100644
index 00000000..4f893fd4
--- /dev/null
+++ b/design-documents/wallet-screenshots/ios-wallet/withdraw-bankIntegrated/cta-withdraw-sheet130-withdraw.png
Binary files differ
diff --git a/design-documents/wallet-screenshots/ios-wallet/withdraw-bankIntegrated/cta-withdraw-sheet131-tos.png b/design-documents/wallet-screenshots/ios-wallet/withdraw-bankIntegrated/cta-withdraw-sheet131-tos.png
new file mode 100644
index 00000000..1aafc03e
--- /dev/null
+++ b/design-documents/wallet-screenshots/ios-wallet/withdraw-bankIntegrated/cta-withdraw-sheet131-tos.png
Binary files differ
diff --git a/design-documents/wallet-screenshots/ios-wallet/withdraw-bankIntegrated/cta-withdraw-sheet133-withdraw-confirm-bank.png b/design-documents/wallet-screenshots/ios-wallet/withdraw-bankIntegrated/cta-withdraw-sheet133-withdraw-confirm-bank.png
new file mode 100644
index 00000000..94ad63b1
--- /dev/null
+++ b/design-documents/wallet-screenshots/ios-wallet/withdraw-bankIntegrated/cta-withdraw-sheet133-withdraw-confirm-bank.png
Binary files differ
diff --git a/design-documents/wallet-screenshots/ios-wallet/withdraw-bankIntegrated/cta-withdraw-view10-empty-wallet.png b/design-documents/wallet-screenshots/ios-wallet/withdraw-bankIntegrated/cta-withdraw-view10-empty-wallet.png
new file mode 100644
index 00000000..a6737b9f
--- /dev/null
+++ b/design-documents/wallet-screenshots/ios-wallet/withdraw-bankIntegrated/cta-withdraw-view10-empty-wallet.png
Binary files differ
diff --git a/design-documents/wallet-screenshots/ios-wallet/withdraw-bankIntegrated/cta-withdraw-view22-balances.png b/design-documents/wallet-screenshots/ios-wallet/withdraw-bankIntegrated/cta-withdraw-view22-balances.png
new file mode 100644
index 00000000..bd83cb8f
--- /dev/null
+++ b/design-documents/wallet-screenshots/ios-wallet/withdraw-bankIntegrated/cta-withdraw-view22-balances.png
Binary files differ
diff --git a/design-documents/wallet-screenshots/ios-wallet/withdraw-exchange/cta-withdrawExchange-sheet-amount.png b/design-documents/wallet-screenshots/ios-wallet/withdraw-exchange/cta-withdrawExchange-sheet-amount.png
new file mode 100644
index 00000000..9a51cb78
--- /dev/null
+++ b/design-documents/wallet-screenshots/ios-wallet/withdraw-exchange/cta-withdrawExchange-sheet-amount.png
Binary files differ
diff --git a/design-documents/wallet-screenshots/ios-wallet/withdraw-exchange/cta-withdrawExchange-sheet-wireTransfer-CHF-1.png b/design-documents/wallet-screenshots/ios-wallet/withdraw-exchange/cta-withdrawExchange-sheet-wireTransfer-CHF-1.png
new file mode 100644
index 00000000..1d9fdbfd
--- /dev/null
+++ b/design-documents/wallet-screenshots/ios-wallet/withdraw-exchange/cta-withdrawExchange-sheet-wireTransfer-CHF-1.png
Binary files differ
diff --git a/design-documents/wallet-screenshots/ios-wallet/withdraw-exchange/cta-withdrawExchange-sheet-wireTransfer-CHF-2.png b/design-documents/wallet-screenshots/ios-wallet/withdraw-exchange/cta-withdrawExchange-sheet-wireTransfer-CHF-2.png
new file mode 100644
index 00000000..3ea5b9ca
--- /dev/null
+++ b/design-documents/wallet-screenshots/ios-wallet/withdraw-exchange/cta-withdrawExchange-sheet-wireTransfer-CHF-2.png
Binary files differ
diff --git a/design-documents/wallet-screenshots/ios-wallet/withdraw-exchange/cta-withdrawExchange-sheet-wireTransfer-CHF-3.png b/design-documents/wallet-screenshots/ios-wallet/withdraw-exchange/cta-withdrawExchange-sheet-wireTransfer-CHF-3.png
new file mode 100644
index 00000000..c15f9a5e
--- /dev/null
+++ b/design-documents/wallet-screenshots/ios-wallet/withdraw-exchange/cta-withdrawExchange-sheet-wireTransfer-CHF-3.png
Binary files differ
diff --git a/design-documents/wallet-screenshots/ios-wallet/withdraw-exchange/cta-withdrawExchange-sheet135-amount.png b/design-documents/wallet-screenshots/ios-wallet/withdraw-exchange/cta-withdrawExchange-sheet135-amount.png
new file mode 100644
index 00000000..4db97e7c
--- /dev/null
+++ b/design-documents/wallet-screenshots/ios-wallet/withdraw-exchange/cta-withdrawExchange-sheet135-amount.png
Binary files differ
diff --git a/design-documents/wallet-screenshots/ios-wallet/withdraw-exchange/cta-withdrawExchange-sheet135-amount2.png b/design-documents/wallet-screenshots/ios-wallet/withdraw-exchange/cta-withdrawExchange-sheet135-amount2.png
new file mode 100644
index 00000000..8c0d7f2a
--- /dev/null
+++ b/design-documents/wallet-screenshots/ios-wallet/withdraw-exchange/cta-withdrawExchange-sheet135-amount2.png
Binary files differ
diff --git a/design-documents/wallet-screenshots/ios-wallet/withdraw-exchange/cta-withdrawExchange-sheet135-tos.png b/design-documents/wallet-screenshots/ios-wallet/withdraw-exchange/cta-withdrawExchange-sheet135-tos.png
new file mode 100644
index 00000000..b71d7dcf
--- /dev/null
+++ b/design-documents/wallet-screenshots/ios-wallet/withdraw-exchange/cta-withdrawExchange-sheet135-tos.png
Binary files differ
diff --git a/design-documents/wallet-screenshots/ios-wallet/withdraw-exchange/cta-withdrawExchange-sheet135-wireTransfer-CHF.png b/design-documents/wallet-screenshots/ios-wallet/withdraw-exchange/cta-withdrawExchange-sheet135-wireTransfer-CHF.png
new file mode 100644
index 00000000..8a467161
--- /dev/null
+++ b/design-documents/wallet-screenshots/ios-wallet/withdraw-exchange/cta-withdrawExchange-sheet135-wireTransfer-CHF.png
Binary files differ
diff --git a/design-documents/wallet-screenshots/ios-wallet/withdraw-exchange/cta-withdrawExchange-sheet135-wireTransfer-CHF2.png b/design-documents/wallet-screenshots/ios-wallet/withdraw-exchange/cta-withdrawExchange-sheet135-wireTransfer-CHF2.png
new file mode 100644
index 00000000..24bb4881
--- /dev/null
+++ b/design-documents/wallet-screenshots/ios-wallet/withdraw-exchange/cta-withdrawExchange-sheet135-wireTransfer-CHF2.png
Binary files differ
diff --git a/design-documents/wallet-screenshots/ios-wallet/withdraw-exchange/cta-withdrawExchange-sheet135-wireTransfer-NETZ.png b/design-documents/wallet-screenshots/ios-wallet/withdraw-exchange/cta-withdrawExchange-sheet135-wireTransfer-NETZ.png
new file mode 100644
index 00000000..7423411a
--- /dev/null
+++ b/design-documents/wallet-screenshots/ios-wallet/withdraw-exchange/cta-withdrawExchange-sheet135-wireTransfer-NETZ.png
Binary files differ
diff --git a/design-documents/wallet-screenshots/ios-wallet/withdraw-exchange/cta-withdrawExchange-sheet135-wireTransfer-NETZ2.png b/design-documents/wallet-screenshots/ios-wallet/withdraw-exchange/cta-withdrawExchange-sheet135-wireTransfer-NETZ2.png
new file mode 100644
index 00000000..80843838
--- /dev/null
+++ b/design-documents/wallet-screenshots/ios-wallet/withdraw-exchange/cta-withdrawExchange-sheet135-wireTransfer-NETZ2.png
Binary files differ
diff --git a/design-documents/wallet-screenshots/ios-wallet/withdraw-exchange/cta-withdrawExchange-sheet135-withdraw-tos.png b/design-documents/wallet-screenshots/ios-wallet/withdraw-exchange/cta-withdrawExchange-sheet135-withdraw-tos.png
new file mode 100644
index 00000000..21056f08
--- /dev/null
+++ b/design-documents/wallet-screenshots/ios-wallet/withdraw-exchange/cta-withdrawExchange-sheet135-withdraw-tos.png
Binary files differ
diff --git a/extract-tsdefs/pnpm-lock.yaml b/extract-tsdefs/pnpm-lock.yaml
index 0bc6ff8e..6d064c10 100644
--- a/extract-tsdefs/pnpm-lock.yaml
+++ b/extract-tsdefs/pnpm-lock.yaml
@@ -1,4 +1,4 @@
-lockfileVersion: '6.0'
+lockfileVersion: '6.1'
settings:
autoInstallPeers: true
diff --git a/frags/apt-install-libeufin-bank.rst b/frags/apt-install-libeufin-bank.rst
new file mode 100644
index 00000000..97b1bd71
--- /dev/null
+++ b/frags/apt-install-libeufin-bank.rst
@@ -0,0 +1,6 @@
+
+To install libeufin-nexus, you can now simply run:
+
+.. code-block:: console
+
+ # apt install libeufin-bank
diff --git a/frags/apt-install-libeufin-nexus.rst b/frags/apt-install-libeufin-nexus.rst
new file mode 100644
index 00000000..25ff8070
--- /dev/null
+++ b/frags/apt-install-libeufin-nexus.rst
@@ -0,0 +1,6 @@
+
+To install libeufin-nexus, you can now simply run:
+
+.. code-block:: console
+
+ # apt install libeufin-nexus
diff --git a/frags/configuration-format.rst b/frags/configuration-format.rst
index e0fe59df..489e98cb 100644
--- a/frags/configuration-format.rst
+++ b/frags/configuration-format.rst
@@ -11,8 +11,8 @@ In order to override these defaults, the user can write a custom configuration
file and either pass it to the component at execution time using the *-c*
option, or name it taler.conf and place it under $HOME/.config/ which is where
components will look by default. Note that the systemd service files pass ``-c
-/etc/taler.conf``, thus making ``/etc/taler.conf`` the primary location for
-the configuration.
+/etc/taler/taler.conf``, thus making ``/etc/taler/taler.conf``
+the primary location for the configuration.
A config file is a text file containing sections, and each section
contains maps options to their values. Configuration files follow
diff --git a/frags/ebics-setup.rst b/frags/ebics-setup.rst
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/frags/ebics-setup.rst
diff --git a/frags/installing-debian.rst b/frags/installing-debian.rst
index 681db637..0032e65e 100644
--- a/frags/installing-debian.rst
+++ b/frags/installing-debian.rst
@@ -8,7 +8,7 @@ looks like this:
.. code-block::
- deb [signed-by=/etc/apt/keyrings/taler-systems.gpg] https://deb.taler.net/apt/debian stable main
+ deb [signed-by=/etc/apt/keyrings/taler-systems.gpg] https://deb.taler.net/apt/debian bookworm main
Next, you must import the Taler Systems SA public package signing key
into your keyring and update the package lists:
diff --git a/frags/libeufin-config-cli.rst b/frags/libeufin-config-cli.rst
new file mode 100644
index 00000000..5475324e
--- /dev/null
+++ b/frags/libeufin-config-cli.rst
@@ -0,0 +1,51 @@
+config
+------
+
+This command inspect or change the configuration.
+
+**-h** \| **--help**
+ Print short help on options.
+
+Subcommands: **get**, **dump**, **pathsub**
+
+config get
+-----------
+
+This command lookup config value.
+
+It takes two arguments, the section name and the option name
+
+**-h** \| **--help**
+ Print short help on options.
+**-c** \| **--config** *FILENAME*
+ Specifies the configuration file.
+**-L** \| **--log** *LOGLEVEL*
+ Configure logging to use LOGLEVEL.
+**-f** \| **--filename**
+ Interpret value as path with dollar-expansion.
+
+config dump
+-----------
+
+This command dump the configuration.
+
+**-h** \| **--help**
+ Print short help on options.
+**-c** \| **--config** *FILENAME*
+ Specifies the configuration file.
+**-L** \| **--log** *LOGLEVEL*
+ Configure logging to use LOGLEVEL.
+
+config pathsub
+--------------
+
+This command substitute variables in a path.
+
+It takes one argument, a path expression.
+
+**-h** \| **--help**
+ Print short help on options.
+**-c** \| **--config** *FILENAME*
+ Specifies the configuration file.
+**-L** \| **--log** *LOGLEVEL*
+ Configure logging to use LOGLEVEL.
diff --git a/frags/nexus-ebics-setup.rst b/frags/nexus-ebics-setup.rst
new file mode 100644
index 00000000..76f51bfe
--- /dev/null
+++ b/frags/nexus-ebics-setup.rst
@@ -0,0 +1,87 @@
+
+When you sign up for an EBICS-enabled bank account, the bank will provide you
+with various credentials. Those must be provided in the
+``/etc/libeufin/libeufin-nexus.conf`` configuration file together with the
+name of the *fiat* currency.
+
+.. note::
+ As legacy transactions in that bank account would likely confuse the system, it is advisable to use a fresh bank account with an empty transaction history.
+
+The following snippet shows the mandatory configuration values:
+
+.. _core-config:
+
+.. code-block:: ini
+
+ [nexus-ebics]
+ CURRENCY = CHF
+
+ # Bank
+ HOST_BASE_URL = https://ebics.postfinance.ch/ebics/ebics.aspx
+ BANK_DIALECT = postfinance
+
+ # EBICS IDs
+ HOST_ID = PFEBICS
+ USER_ID = PFC00563
+ PARTNER_ID = PFC00563
+
+ # Account information
+ IBAN = CH7789144474425692816
+ BIC = POFICHBEXXX
+ NAME = John Smith S.A.
+
+.. note::
+ Refer to the manpage ``libeufin-nexus.conf(5)``
+ for the full array of configuration values.
+
+.. warning::
+ This combination of HOST_ID, USER_ID and PARTNER_ID must never be used by another instance of libeufin-nexus or by other EBICS clients, otherwise data will be lost.
+
+Reuse existing client keys
+--------------------------
+
+If you have client keys from a previous EBICS setup you can copy the JSON file to the configured path ``CLIENT_PRIVATE_KEYS_FILE`` (``/var/lib/libeufin-nexus/client-ebics-keys.json`` with the default config).
+
+Make sure this file is accessible to the user running ``libeufin-nexus``, for the default services you should run:
+
+.. code-block:: console
+
+ $ chown libeufin-nexus:libeufin-nexus /var/lib/libeufin-nexus/client-ebics-keys.json
+
+Create new client keys
+----------------------
+
+Assuming that the configuration file exists at ``$CONFIG_FILE``, the following
+command should start the EBICS setup process:
+
+.. code-block:: console
+
+ $ libeufin-nexus ebics-setup -c "$CONFIG_FILE"
+
+If the previous command failed when running EBICS INI with an error code of
+``EBICS_INVALID_USER_OR_USER_STATE``, you need to confirm your keys to your bank to
+activate your account.
+
+To that end, the previous run should have left a PDF document that you can
+print, sign and send to the bank. Look for the message that looks like ``PDF
+file with keys created at '/tmp/libeufin-nexus-keys-$TIMESTAMP.pdf'``.
+
+Once the bank has received and processed this document you can continue.
+
+Get bank keys
+-------------
+
+Assuming that the configuration file exists at ``$CONFIG_FILE``, the following
+command will finish the EBICS setup process:
+
+.. code-block:: console
+
+ $ libeufin-nexus ebics-setup -c "$CONFIG_FILE"
+
+The EBICS setup is finished once the bank keys have been accepted.
+
+Make sure this bank keys are accessible to the user running ``libeufin-nexus``, for the default services you should run:
+
+.. code-block:: console
+
+ $ chown libeufin-nexus:libeufin-nexus /var/lib/libeufin-nexus/bank-ebics-keys.json
diff --git a/frags/regional-manual-architecture.rst b/frags/regional-manual-architecture.rst
new file mode 100644
index 00000000..cfb8aacd
--- /dev/null
+++ b/frags/regional-manual-architecture.rst
@@ -0,0 +1,48 @@
+Architecture
+============
+
+There are several key components needed to operate a regional currency based
+on GNU Taler and LibEuFin technology:
+
+- LibEuFin Nexus: is responsible to drive the master (fiat) bank account both to learn
+ about incoming payments and to send fiat cash-out payments
+- LibEuFin Bank: offers basic banking operations, e.g. wire transfers, Taler withdrawals,
+ account management, cash-out's
+- Taler exchange: server side of Taler operations.
+- Taler wallet: client side of Taler operations.
+- Taler merchant backend: abstracts Taler details to the shops.
+
+.. image:: ../images/regional-arch.png
+
+In this model, the regional currency is backed by the fiat currency and users
+are offered two operations: *cash-in* to create regional currency starting
+from fiat money, and *cash-out* to convert regional currency into fiat
+currency.
+
+The design assumes that one single unit of regional currency is always backed
+by one single unit of fiat currency.
+
+
+Cash-in
++++++++
+
+One fundamental entity to create the regional currency is the *master bank account*.
+The master bank account is hosted at one fiat bank and whenever it receives a *valid*
+fiat payment of N units, it triggers the creation of N units of regional currency.
+Such trigger causes the *admin bank account* at the regional bank to wire the N units of
+regional currency to the Taler exchange (regional) bank account. At this point, the
+Taler exchange is ready to issue the regional coins to the Taler wallet that proves
+to own them.
+
+.. note::
+
+ *Valid* fiat payments are those with a Taler-relevant subject that should be generated by a Taler wallet.
+
+
+Cash-out
+++++++++
+
+Once a regional bank user confirms a cash-out operation of N units, the system sends
+a regional payment of N units to the *admin bank account*. This latter triggers then
+a fiat payment of N units to the fiat bank account owned by the user who initiated the
+cash-out. \ No newline at end of file
diff --git a/frags/regional-manual-use.rst b/frags/regional-manual-use.rst
new file mode 100644
index 00000000..f33d9010
--- /dev/null
+++ b/frags/regional-manual-use.rst
@@ -0,0 +1,99 @@
+Using the Regional Currency
+===========================
+
+The very first step you should check afte the installation process has been
+completed successfully, is to make sure all three URLs (bank,backend and exchange),
+are available (this means to see a Website, and not any NGINX error).
+
+
+Bank backend walkthrough
++++++++++++++++++++++++++
+
+- As stated above, please visit before "https://bank.yourdomain.ltd", to make sure it is available.
+
+- Now login with the username "admin" and the password you have choosen during the installation process, or use the one which might
+ have been generated automatically (and shown on your terminal screen), during the installation process.
+ Once inside the Bank Administrator area, please create the "very first" customer account.
+
+- Transfer some funds from the "admin" bank account to this new customer account.
+
+- Now logout from the "admin" account, and login again using the recently "customer" account you have created, and make sure the funds you have transfered from admin, have arrived correctly.
+
+- Now, please choose the option "Send Money to a Taler Wallet", and try to send for example 100 units of your regional currency to the
+ wallet installed on your browser or mobile phone.
+
+- Now try to spend some of these funds from your wallet, and try to buy something somewhere, with the same digital currency you have choosen, during your installation process, let's say Netzbon.
+
+- Lastly, you can also try to transfer funds to another "bank account",for that you will need to know the recipient's username or the bank account ID.
+
+If you have successfully accomplished all the previous steps, for the bank administrator
+backend and your installed Wallet, you can move now to test other components such
+as the Merchant backend (https://backend.yourdomain.ltd).
+
+Wallet Setup
+++++++++++++
+
+This section describes the interaction between the Taler graphical wallet (Android,
+iOS, WebExtensions) and the regional currency system.
+
+You need to add your regional currency exchange to the wallet. This can
+be done by scanning a QR code with a ``taler://withdraw-exchange/exchange.$DOMAIN/$MASTER_PUB``
+URL or by manually entering the URL into the respective ``Add exchange``
+dialogue.
+
+
+Cash-In
++++++++
+
+Next, start the withdraw process in the Taler wallet for the respective
+currency and specify the desired amount. The wallet will then show you the
+details of the fiat wire transfer that must be made for the cash-in to be
+completed. Once the money has arrived at the fiat bank account, Nexus will
+obtain the transaction data and the regional currency bank will create the
+corresponding amount in regional currency, crediting the GNU Taler exchange
+account. In turn, the exchange will issue the respective amount to your
+wallet.
+
+.. note::
+
+ Cash-in operations may be subject to conversion rates, conversion fees and
+ minimum amounts to be transferred.
+
+
+Making payments
++++++++++++++++
+
+For testing, you should be able to *deposit* regional currency directly into
+your regional currency libeufin-bank account directly from the Taler wallet.
+For this, you primarily need to know your bank account details (which should
+be accessible by clicking on your name in the bank Web site after logging in).
+
+.. note::
+
+ There may be a short delay between the wallet making the deposit and
+ the exchange crediting your bank account. This is because the wallet
+ uses a small wire transfer delay by default when initiating a deposit
+ into a bank account.
+
+For production, it is more common for a shop to configure a :ref:`Taler
+merchant backend <taler-merchant-backend-operator-manual>` or at least use an
+instance within such a setup. To configure an instance, you primarily need
+again the bank account details to :ref:`setup instance bank accounts
+<instance-bank-account>`.
+
+
+Cash-Out
+++++++++
+
+Regional currency accounts that have a positive balance could be eligible for
+cash-out. Cash-out operations may again be restricted by the regional
+currency operator and will *only* be made to the respective pre-configured
+fiat currency bank account. To cash-out, simply log into your regional
+currency account, select cash-out, specify the desired amount and pass the
+second-factor authorization challenge by entering the TAN you receive at the
+registered e-mail address or mobile phone number.
+
+.. note::
+
+ Cash-out operations may be subject to conversion rates, conversion fees and
+ minimum amounts to be transferred.
diff --git a/frags/using-taler-config.rst b/frags/using-taler-config.rst
index 5e8ffcaa..ba4febb4 100644
--- a/frags/using-taler-config.rst
+++ b/frags/using-taler-config.rst
@@ -3,7 +3,9 @@ Using taler-config
The tool ``taler-config`` can be used to extract or manipulate configuration
values; however, the configuration use the well-known INI file format and is
-generally better edited by hand to preserve comments and structure.
+generally better edited by hand to preserve comments and structure. Thus, ``taler-config`` should primarily be used
+to inspect or understand a configuration that is in place,
+and not to update it!
Run
@@ -22,7 +24,9 @@ Run
to extract the respective configuration value for option ``$OPTION`` in
section ``$SECTION``.
-Finally, to change a setting, run
+Finally, to change a setting and clobber your entire
+configuration file structure, inlining all values and
+removing all comments, run
.. code-block:: console
diff --git a/images/Makefile b/images/Makefile
index 9ec833e7..ad7a695d 100644
--- a/images/Makefile
+++ b/images/Makefile
@@ -1,7 +1,11 @@
-diagrams: arch-api.png coin.png deposit.png reserve.png transaction-common-states.png transaction-withdrawal-states.png transaction-payment-states.png transaction-refund-states.png transaction-refresh-states.png transaction-reward-states.png transaction-deposit-states.png transaction-push-debit-states.png transaction-push-credit-states.png transaction-pull-credit-states.png transaction-pull-debit-states.png
+diagrams: regional-arch.png arch-api.png coin.png deposit.png reserve.png transaction-common-states.png transaction-withdrawal-states.png transaction-payment-states.png transaction-refund-states.png transaction-refresh-states.png transaction-deposit-states.png transaction-push-debit-states.png transaction-push-credit-states.png transaction-pull-credit-states.png transaction-pull-debit-states.png challenger.png
arch-api.png: arch-api.dot
dot -Tpng arch-api.dot > arch-api.png
+regional-arch.png: regional-arch.dot
+ dot -Tpng regional-arch.dot > regional-arch.png
+challenger.png: challenger.dot
+ dot -Tpng challenger.dot > challenger.png
transaction-common-states.png: transaction-common-states.dot
dot -Tpng transaction-common-states.dot > transaction-common-states.png
transaction-withdrawal-states.png: transaction-withdrawal-states.dot
@@ -12,8 +16,6 @@ transaction-refund-states.png: transaction-refund-states.dot
dot -Tpng transaction-refund-states.dot > transaction-refund-states.png
transaction-refresh-states.png: transaction-refresh-states.dot
dot -Tpng transaction-refresh-states.dot > transaction-refresh-states.png
-transaction-reward-states.png: transaction-reward-states.dot
- dot -Tpng transaction-reward-states.dot > transaction-reward-states.png
transaction-deposit-states.png: transaction-deposit-states.dot
dot -Tpng transaction-deposit-states.dot > transaction-deposit-states.png
transaction-push-debit-states.png: transaction-push-debit-states.dot
@@ -30,4 +32,3 @@ deposit.png: deposit.dot
dot -Tpng deposit.dot > deposit.png
reserve.png: reserve.dot
dot -Tpng reserve.dot > reserve.png
-
diff --git a/images/backoffice-reward-create.confirmation.svg b/images/backoffice-reward-create.confirmation.svg
index 3b8e01d3..90200c1b 100644
--- a/images/backoffice-reward-create.confirmation.svg
+++ b/images/backoffice-reward-create.confirmation.svg
@@ -13,4 +13,4 @@
}
</style>
</defs>
- <rect x="0" y="0" width="571.8889058430991" height="551.2222391764319" fill="#ffffff"></rect><g stroke-linecap="round" transform="translate(10 10) rotate(0 275.94445292154955 265.61111958821596)"><path d="M0 0 C140.46 0, 280.92 0, 551.89 0 M0 0 C204.72 0, 409.45 0, 551.89 0 M551.89 0 C551.89 152.39, 551.89 304.77, 551.89 531.22 M551.89 0 C551.89 107.04, 551.89 214.08, 551.89 531.22 M551.89 531.22 C332.47 531.22, 113.04 531.22, 0 531.22 M551.89 531.22 C417.98 531.22, 284.07 531.22, 0 531.22 M0 531.22 C0 418.2, 0 305.18, 0 0 M0 531.22 C0 346.7, 0 162.17, 0 0" stroke="#000000" stroke-width="1" fill="none"></path></g><g transform="translate(85.44442749023415 48.555572509765625) rotate(0 142 16)"><text x="0" y="26" font-family="Helvetica, Segoe UI Emoji" font-size="28px" fill="#000000" text-anchor="start" style="white-space: pre;" direction="ltr">Tip created successfully</text></g><g transform="translate(65.88732457160927 145.118741350042) rotate(0 33.5 11.5)"><text x="0" y="18" font-family="Helvetica, Segoe UI Emoji" font-size="20px" fill="#000000" text-anchor="start" style="white-space: pre;" direction="ltr">amount</text></g><g stroke-linecap="round" transform="translate(267.5406907399499 142.480934712235) rotate(0 77.99999999999989 14.152236652236752)"><path d="M0 0 C55.83 0, 111.67 0, 156 0 M0 0 C38.38 0, 76.75 0, 156 0 M156 0 C156 7.9, 156 15.79, 156 28.3 M156 0 C156 10.3, 156 20.6, 156 28.3 M156 28.3 C117.29 28.3, 78.59 28.3, 0 28.3 M156 28.3 C96.97 28.3, 37.93 28.3, 0 28.3 M0 28.3 C0 21.43, 0 14.55, 0 0 M0 28.3 C0 22.04, 0 15.77, 0 0" stroke="#000000" stroke-width="1" fill="none"></path></g><g transform="translate(66.88732457160927 204.63380306959152) rotate(0 49.5 11.5)"><text x="0" y="18" font-family="Helvetica, Segoe UI Emoji" font-size="20px" fill="#000000" text-anchor="start" style="white-space: pre;" direction="ltr">justification</text></g><g transform="translate(73.66508539517713 338.18934167093744) rotate(0 33.5 11.5)"><text x="0" y="18" font-family="Helvetica, Segoe UI Emoji" font-size="20px" fill="#000000" text-anchor="start" style="white-space: pre;" direction="ltr">tip URL</text></g><g stroke-linecap="round" transform="translate(206.4295796288386 142.52151912781937) rotate(0 30.5 14.097222222222399)"><path d="M0 0 C14.45 0, 28.9 0, 61 0 M0 0 C13.99 0, 27.98 0, 61 0 M61 0 C61 10.08, 61 20.16, 61 28.19 M61 0 C61 7.45, 61 14.91, 61 28.19 M61 28.19 C41.93 28.19, 22.86 28.19, 0 28.19 M61 28.19 C41.66 28.19, 22.33 28.19, 0 28.19 M0 28.19 C0 21.41, 0 14.63, 0 0 M0 28.19 C0 20.05, 0 11.91, 0 0" stroke="#000000" stroke-width="1" fill="none"></path></g><g transform="translate(213.09624629550513 145.118741350042) rotate(0 21 11.5)"><text x="21" y="18" font-family="Helvetica, Segoe UI Emoji" font-size="20px" fill="#000000" text-anchor="middle" style="white-space: pre;" direction="ltr">USD</text></g><g stroke-linecap="round" transform="translate(206.4295796288386 207.92332482337952) rotate(0 134.84126984126988 51.111111111111086)"><path d="M0 0 C97.82 0, 195.63 0, 269.68 0 M0 0 C87.58 0, 175.15 0, 269.68 0 M269.68 0 C269.68 23.55, 269.68 47.1, 269.68 102.22 M269.68 0 C269.68 38.76, 269.68 77.52, 269.68 102.22 M269.68 102.22 C168.96 102.22, 68.23 102.22, 0 102.22 M269.68 102.22 C192.45 102.22, 115.21 102.22, 0 102.22 M0 102.22 C0 63.99, 0 25.75, 0 0 M0 102.22 C0 69.03, 0 35.84, 0 0" stroke="#000000" stroke-width="1" fill="none"></path></g><g stroke-linecap="round" transform="translate(205.3184685177273 334.0422606998018) rotate(0 85.37038167317712 15)"><path d="M0 0 C58.97 0, 117.94 0, 170.74 0 M0 0 C66.44 0, 132.88 0, 170.74 0 M170.74 0 C170.74 9.84, 170.74 19.67, 170.74 30 M170.74 0 C170.74 11.46, 170.74 22.92, 170.74 30 M170.74 30 C111.07 30, 51.39 30, 0 30 M170.74 30 C121.68 30, 72.63 30, 0 30 M0 30 C0 21.78, 0 13.56, 0 0 M0 30 C0 20.57, 0 11.13, 0 0" stroke="#000000" stroke-width="1" fill="none"></path></g><g transform="translate(76.67993668715121 404.7879712581632) rotate(0 41.5 11.5)"><text x="0" y="18" font-family="Helvetica, Segoe UI Emoji" font-size="20px" fill="#000000" text-anchor="start" style="white-space: pre;" direction="ltr">valid until</text></g><g stroke-linecap="round" transform="translate(212.71710211484606 392.3770074341571) rotate(0 71.39795918367349 18.459183673469397)"><path d="M0.56 1.22 L141.57 0.94 L141.78 38.25 L-1.25 38.38" stroke="none" stroke-width="0" fill="#fff"></path><path d="M-0.98 1.62 C34.12 -1.49, 68.83 -1.89, 142.94 -0.88 M0.57 -0.59 C29.47 0.89, 57.16 -0.08, 142.07 0.14 M142.91 -0.64 C143.04 15.1, 140.92 25.51, 142.3 36.46 M141.87 -0.37 C142.21 8.72, 143.63 15.39, 141.94 37.29 M144.77 37.32 C105.38 36.8, 65.06 35.87, 0.85 37.03 M142.32 37.91 C86.66 35.41, 32.17 35.36, 0.24 37.86 M1.37 35.32 C1.21 25.05, 1.19 10.31, -0.4 -0.05 M-0.02 37.73 C0.2 26.83, -0.88 18.04, -0.59 0.08" stroke="#000000" stroke-width="1" fill="none"></path></g><g transform="translate(247.36506129851932 398.8361911076265) rotate(0 5 12.5)"><text x="0" y="18" font-family="Virgil, Segoe UI Emoji" font-size="20px" fill="#000000" text-anchor="start" style="white-space: pre;" direction="ltr">/</text></g><g transform="translate(277.8650612985193 398.3361911076265) rotate(0 5 12.5)"><text x="0" y="18" font-family="Virgil, Segoe UI Emoji" font-size="20px" fill="#000000" text-anchor="start" style="white-space: pre;" direction="ltr">/</text></g><g stroke-linecap="round" transform="translate(366.8650612985193 391.3361911076265) rotate(0 17.75 17.75)"><path d="M0.94 -1.01 L36.83 -1.25 L36.96 34.45 L-0.83 36.6" stroke="none" stroke-width="0" fill="#868e96"></path><path d="M-1.6 -0.35 C6.91 0.23, 16.94 -1.91, 34.19 0.08 M0.95 -0.04 C12.64 -1.04, 25.48 0.32, 34.73 -0.09 M37.19 -1.59 C34.07 10.35, 34.93 20.04, 35.6 37.4 M36.19 0.82 C34.7 6.51, 35.74 14.48, 34.58 35.73 M35.05 35.71 C19.96 36.63, 7.29 37.51, -0.4 33.62 M35.33 35.31 C26.31 35.42, 18.5 35.89, -0.89 34.55 M1.85 36.37 C1.11 22.03, 0.24 8.62, 1.34 1.61 M-0.36 34.87 C0.29 24.35, -0.21 14.65, 0.61 -0.61" stroke="#000000" stroke-width="1" fill="none"></path></g><g stroke-linecap="round" transform="translate(367.8650612985193 392.3361911076265) rotate(0 17.5 4.5)"><path d="M-1.01 1.33 L33.75 1.46 L33.95 8.17 L1.1 7.74" stroke="none" stroke-width="0" fill="#000"></path><path d="M-0.35 -2 C13.48 -0.6, 24.68 -1.03, 35.08 1.14 M-0.04 -0.02 C7.69 -0.19, 17.48 -1.1, 34.91 0.05 M34.28 -0.59 C34.8 2.2, 34.28 4.86, 35.86 8.17 M35.37 -0.3 C34.56 2.54, 34.82 4.33, 35.1 9.44 M35.21 7.62 C24.64 9.03, 14.32 8.52, -1.88 8.05 M34.81 8.78 C21.27 9.88, 7.77 8.05, -0.95 9.68 M0.39 9.37 C-0.22 7, -0.37 5.64, 0.73 -0.02 M-0.28 9.26 C-0.31 5.6, 0.09 2.41, -0.28 0.21" stroke="#000000" stroke-width="1" fill="none"></path></g><g stroke-linecap="round" transform="translate(375.3650612985193 383.8361911076265) rotate(0 3 7)"><path d="M1.33 -1.25 L7.46 -1.05 L5.17 15.1 L-1.26 12.71" stroke="none" stroke-width="0" fill="#868e96"></path><path d="M-0.6 0.04 C1.4 -0.59, 2.93 0.04, 6.34 -0.36 M-0.01 -0.22 C2.36 0.19, 4.41 -0.02, 6.02 -0.1 M5.08 -0.34 C5.8 3.42, 6.19 10.47, 4.71 13.49 M5.53 -0.6 C6.36 3.16, 5.45 6.86, 6.69 14.14 M5.59 14.26 C3.76 14.53, 1.34 13.44, -0.28 14.6 M5.93 14.07 C5.03 14.2, 3.24 13.7, 0.21 13.76 M0.58 13.72 C-0.16 8.67, 0.81 5.49, -0.03 1.14 M0.41 13.59 C0.11 9.37, 0.48 3.91, 0.33 -0.35" stroke="#000000" stroke-width="1" fill="none"></path></g><g stroke-linecap="round" transform="translate(390.3650612985193 383.8361911076265) rotate(0 3 7)"><path d="M-1.25 1.46 L4.95 -0.83 L7.1 12.74 L-1.29 14.58" stroke="none" stroke-width="0" fill="#868e96"></path><path d="M0.04 -0.26 C0.72 -0.33, 2.67 0.4, 5.64 0.52 M-0.22 0.04 C2.56 -0.23, 4.71 0.02, 5.9 0.08 M5.66 -0.32 C4.73 5.45, 7.22 9.47, 5.49 13.15 M5.4 0.26 C5.93 4.52, 6.28 11.02, 6.14 14.55 M6.26 14.03 C4.85 13.84, 2.11 13.67, 0.6 13.45 M6.07 14.28 C4.52 13.72, 2.32 14.19, -0.24 14.13 M-0.28 13.97 C-0.57 9.44, 1.07 2.97, 1.14 0.63 M-0.41 14.06 C0.28 10.73, -0.34 6.93, -0.35 0.47" stroke="#000000" stroke-width="1" fill="none"></path></g><g stroke-linecap="round"><g transform="translate(383.8650612985193 400.3361911076265) rotate(0 0.6422718642013479 13.197904566302896)"><path d="M-0.88 -1.99 C-1.43 7.57, 1.15 13.78, 2.24 28.39 M0.14 0.63 C-0.63 7.75, 0.34 15.35, 0.76 27.34" stroke="#000000" stroke-width="1" fill="none"></path></g></g><g stroke-linecap="round"><g transform="translate(374.3650612985193 399.3361911076265) rotate(0 0.19790456630289555 13.301320007070899)"><path d="M-1.99 -1.31 C0.2 6.74, -0.97 12.94, 2.39 27.91 M0.63 -0.77 C-0.14 8.39, -0.23 16.93, 1.34 27.2" stroke="#000000" stroke-width="1" fill="none"></path></g></g><g stroke-linecap="round"><g transform="translate(393.8650612985193 400.8361911076265) rotate(0 0.2720004984978459 12.683548028115183)"><path d="M-1.31 0.08 C1.49 6.67, 2.55 17.58, 1.41 25.45 M-0.77 -0.09 C0.43 5.46, 0.98 12.41, 0.7 24.84" stroke="#000000" stroke-width="1" fill="none"></path></g></g><g stroke-linecap="round"><g transform="translate(402.8650612985193 408.8361911076265) rotate(0 -17.287554731126875 -0.13689562075796857)"><path d="M0.08 1.14 C-9.9 1.52, -15.53 -0.31, -34.05 -1.46 M-0.09 0.05 C-10.99 0, -20.5 -1.06, -34.66 -0.25" stroke="#000000" stroke-width="1" fill="none"></path></g></g><g stroke-linecap="round"><g transform="translate(402.3650612985193 417.8361911076265) rotate(0 -18.16205287910998 0.04547248221933842)"><path d="M1.14 -1.19 C-5.48 2.11, -14.51 0.37, -37.46 1.28 M0.05 -0.32 C-12.82 1.18, -26.96 0.04, -36.25 0.77" stroke="#000000" stroke-width="1" fill="none"></path></g></g><g stroke-linecap="round" transform="translate(340.7275521017252 468.94674259140356) rotate(0 68.33333333333326 18.888905843098996)"><path d="M0 0 C0 0, 0 0, 0 0 M0 0 C0 0, 0 0, 0 0 M-0.26 6.4 C1.09 4.84, 2.44 3.29, 4.99 0.36 M-0.26 6.4 C1.46 4.42, 3.17 2.45, 4.99 0.36 M0.13 12.04 C2.6 9.2, 5.07 6.36, 10.63 -0.03 M0.13 12.04 C2.36 9.48, 4.59 6.92, 10.63 -0.03 M-0.13 18.44 C3.98 13.71, 8.09 8.98, 15.62 0.33 M-0.13 18.44 C3.41 14.36, 6.95 10.29, 15.62 0.33 M0.27 24.08 C6 17.49, 11.72 10.9, 21.26 -0.07 M0.27 24.08 C7.46 15.81, 14.65 7.53, 21.26 -0.07 M0 30.48 C5.48 24.19, 10.95 17.89, 26.25 0.29 M0 30.48 C9.05 20.07, 18.1 9.66, 26.25 0.29 M-0.26 36.88 C8.64 26.64, 17.54 16.41, 31.89 -0.1 M-0.26 36.88 C12.31 22.42, 24.88 7.96, 31.89 -0.1 M2.11 40.26 C13.59 27.05, 25.06 13.85, 36.88 0.26 M2.11 40.26 C12.5 28.3, 22.9 16.34, 36.88 0.26 M7.75 39.86 C19.43 26.42, 31.11 12.99, 42.52 -0.14 M7.75 39.86 C18.98 26.94, 30.22 14.01, 42.52 -0.14 M12.74 40.22 C24.86 26.28, 36.98 12.33, 47.51 0.22 M12.74 40.22 C20.81 30.93, 28.89 21.64, 47.51 0.22 M18.38 39.83 C31.65 24.56, 44.91 9.3, 53.15 -0.17 M18.38 39.83 C28.39 28.31, 38.41 16.79, 53.15 -0.17 M23.37 40.19 C36.54 25.03, 49.71 9.88, 58.14 0.19 M23.37 40.19 C34.58 27.29, 45.8 14.38, 58.14 0.19 M29.01 39.79 C38.99 28.31, 48.97 16.82, 63.78 -0.21 M29.01 39.79 C40.04 27.1, 51.07 14.42, 63.78 -0.21 M34 40.15 C41.91 31.05, 49.83 21.94, 68.77 0.15 M34 40.15 C43.74 28.94, 53.49 17.73, 68.77 0.15 M39.64 39.76 C52.44 25.03, 65.24 10.31, 74.41 -0.24 M39.64 39.76 C47.47 30.75, 55.31 21.73, 74.41 -0.24 M44.63 40.12 C54.86 28.34, 65.1 16.57, 79.4 0.12 M44.63 40.12 C53.28 30.16, 61.94 20.2, 79.4 0.12 M50.27 39.72 C60.09 28.43, 69.91 17.13, 85.04 -0.28 M50.27 39.72 C61.03 27.34, 71.8 14.96, 85.04 -0.28 M55.26 40.08 C64.66 29.27, 74.06 18.46, 90.03 0.08 M55.26 40.08 C65.85 27.89, 76.45 15.7, 90.03 0.08 M60.9 39.69 C72.37 26.49, 83.85 13.29, 95.67 -0.31 M60.9 39.69 C69.59 29.69, 78.29 19.68, 95.67 -0.31 M65.89 40.05 C74.2 30.49, 82.51 20.92, 100.66 0.05 M65.89 40.05 C78.29 25.78, 90.69 11.52, 100.66 0.05 M71.53 39.65 C83.8 25.54, 96.08 11.42, 106.3 -0.34 M71.53 39.65 C78.82 31.27, 86.11 22.88, 106.3 -0.34 M76.52 40.01 C89.61 24.96, 102.7 9.9, 111.29 0.02 M76.52 40.01 C85.09 30.16, 93.66 20.3, 111.29 0.02 M82.16 39.62 C90.2 30.37, 98.24 21.12, 116.27 0.38 M82.16 39.62 C93.56 26.5, 104.97 13.38, 116.27 0.38 M87.15 39.98 C95.85 29.97, 104.55 19.96, 121.92 -0.02 M87.15 39.98 C95.8 30.03, 104.45 20.07, 121.92 -0.02 M92.79 39.59 C99.78 31.55, 106.76 23.51, 126.91 0.34 M92.79 39.59 C101.4 29.69, 110 19.78, 126.91 0.34 M97.78 39.95 C108.93 27.11, 120.09 14.28, 132.55 -0.05 M97.78 39.95 C110.68 25.1, 123.59 10.25, 132.55 -0.05 M103.42 39.55 C114.64 26.64, 125.86 13.73, 137.54 0.31 M103.42 39.55 C116.21 24.83, 129.01 10.11, 137.54 0.31 M108.41 39.91 C115.34 31.93, 122.28 23.95, 137.27 6.7 M108.41 39.91 C115.74 31.48, 123.06 23.05, 137.27 6.7 M114.05 39.52 C119.08 33.73, 124.11 27.95, 137.01 13.1 M114.05 39.52 C123.16 29.04, 132.27 18.56, 137.01 13.1 M119.04 39.88 C125.53 32.41, 132.02 24.95, 137.41 18.74 M119.04 39.88 C123.99 34.17, 128.95 28.47, 137.41 18.74 M124.02 40.24 C128.33 35.28, 132.63 30.33, 137.15 25.14 M124.02 40.24 C129.2 34.28, 134.37 28.33, 137.15 25.14 M129.67 39.84 C132.79 36.25, 135.91 32.66, 137.54 30.79 M129.67 39.84 C131.44 37.8, 133.21 35.77, 137.54 30.79" stroke="#82c91e" stroke-width="0.5" fill="none"></path><path d="M0 0 C49.47 0, 98.93 0, 136.67 0 M0 0 C42.29 0, 84.59 0, 136.67 0 M136.67 0 C136.67 8.33, 136.67 16.66, 136.67 37.78 M136.67 0 C136.67 8.06, 136.67 16.12, 136.67 37.78 M136.67 37.78 C93.85 37.78, 51.03 37.78, 0 37.78 M136.67 37.78 C88.21 37.78, 39.74 37.78, 0 37.78 M0 37.78 C0 24.21, 0 10.64, 0 0 M0 37.78 C0 27.5, 0 17.22, 0 0" stroke="#000000" stroke-width="1" fill="none"></path></g><g transform="translate(372.94974041552723 475.50226423853906) rotate(0 37.5 11.5)"><text x="0" y="18" font-family="Helvetica, Segoe UI Emoji" font-size="20px" fill="#000000" text-anchor="start" style="white-space: pre;" direction="ltr">continue</text></g><g stroke-linecap="round" transform="translate(388.95413517850125 333.70723212274766) rotate(0 42.96295166015625 15.66137767973396)"><path d="M0 0 C0 0, 0 0, 0 0 M0 0 C0 0, 0 0, 0 0 M-0.26 6.4 C1.33 4.57, 2.92 2.74, 4.99 0.36 M-0.26 6.4 C1.67 4.17, 3.61 1.95, 4.99 0.36 M0.13 12.04 C4.31 7.24, 8.49 2.43, 10.63 -0.03 M0.13 12.04 C4.25 7.31, 8.36 2.58, 10.63 -0.03 M-0.13 18.44 C4.4 13.23, 8.93 8.02, 15.62 0.33 M-0.13 18.44 C6.09 11.29, 12.3 4.14, 15.62 0.33 M0.27 24.08 C6.1 17.37, 11.93 10.66, 21.26 -0.07 M0.27 24.08 C8.03 15.15, 15.79 6.22, 21.26 -0.07 M0 30.48 C7.44 21.92, 14.88 13.36, 26.25 0.29 M0 30.48 C9.23 19.87, 18.45 9.26, 26.25 0.29 M2.37 33.86 C8.28 27.06, 14.18 20.27, 31.89 -0.1 M2.37 33.86 C11.1 23.81, 19.83 13.77, 31.89 -0.1 M8.01 33.46 C18.87 20.98, 29.72 8.49, 36.88 0.26 M8.01 33.46 C15.44 24.92, 22.87 16.37, 36.88 0.26 M13 33.82 C24.34 20.78, 35.68 7.73, 42.52 -0.14 M13 33.82 C20.91 24.72, 28.83 15.61, 42.52 -0.14 M18.64 33.43 C27.12 23.68, 35.59 13.93, 47.51 0.22 M18.64 33.43 C27.73 22.98, 36.81 12.53, 47.51 0.22 M23.63 33.79 C30.77 25.58, 37.9 17.37, 53.15 -0.17 M23.63 33.79 C30.05 26.4, 36.47 19.01, 53.15 -0.17 M29.27 33.39 C38.11 23.22, 46.96 13.05, 58.14 0.19 M29.27 33.39 C35.28 26.48, 41.29 19.57, 58.14 0.19 M34.26 33.75 C42.43 24.35, 50.6 14.95, 63.78 -0.21 M34.26 33.75 C40.39 26.7, 46.52 19.64, 63.78 -0.21 M39.9 33.36 C49.33 22.51, 58.76 11.66, 68.77 0.15 M39.9 33.36 C45.83 26.54, 51.75 19.73, 68.77 0.15 M44.89 33.72 C56.26 20.63, 67.64 7.55, 74.41 -0.24 M44.89 33.72 C54.79 22.33, 64.69 10.95, 74.41 -0.24 M50.53 33.33 C56.58 26.37, 62.62 19.42, 79.4 0.12 M50.53 33.33 C57.93 24.81, 65.34 16.29, 79.4 0.12 M55.52 33.69 C66.01 21.61, 76.51 9.54, 85.04 -0.28 M55.52 33.69 C62.29 25.89, 69.07 18.1, 85.04 -0.28 M61.16 33.29 C67.92 25.51, 74.68 17.74, 88.06 2.35 M61.16 33.29 C69.1 24.16, 77.03 15.03, 88.06 2.35 M66.15 33.65 C74.36 24.21, 82.56 14.77, 88.45 7.99 M66.15 33.65 C74.01 24.61, 81.87 15.57, 88.45 7.99 M71.79 33.26 C76.57 27.76, 81.35 22.26, 88.19 14.39 M71.79 33.26 C77.32 26.9, 82.85 20.54, 88.19 14.39 M76.78 33.62 C80.26 29.61, 83.75 25.6, 88.59 20.03 M76.78 33.62 C80.31 29.55, 83.84 25.49, 88.59 20.03 M82.42 33.22 C83.67 31.79, 84.91 30.35, 88.33 26.43 M82.42 33.22 C84.67 30.63, 86.92 28.04, 88.33 26.43" stroke="#4c6ef5" stroke-width="0.5" fill="none"></path><path d="M0 0 C34.37 0, 68.73 0, 85.93 0 M0 0 C30.8 0, 61.6 0, 85.93 0 M85.93 0 C85.93 7.3, 85.93 14.59, 85.93 31.32 M85.93 0 C85.93 10.75, 85.93 21.51, 85.93 31.32 M85.93 31.32 C64.61 31.32, 43.3 31.32, 0 31.32 M85.93 31.32 C64.26 31.32, 42.59 31.32, 0 31.32 M0 31.32 C0 19.26, 0 7.2, 0 0 M0 31.32 C0 20.81, 0 10.29, 0 0" stroke="#000000" stroke-width="1" fill="none"></path></g><g transform="translate(396.7054353242104 338.1304988211914) rotate(0 35 11.5)"><text x="0" y="18" font-family="Helvetica, Segoe UI Emoji" font-size="20px" fill="#000000" text-anchor="start" style="white-space: pre;" direction="ltr">copy url</text></g><g transform="translate(78.68102157642033 106.96052345493217) rotate(0 20 11.5)"><text x="0" y="17" font-family="Helvetica, Segoe UI Emoji" font-size="20px" fill="#000000" text-anchor="start" style="white-space: pre;" direction="ltr">from</text></g><g transform="translate(211.63556703096583 97.86961436402316) rotate(0 71.5 11.5)"><text x="0" y="17" font-family="Helvetica, Segoe UI Emoji" font-size="20px" fill="#000000" text-anchor="start" style="white-space: pre;" direction="ltr">video promotion</text></g></svg> \ No newline at end of file
+ <rect x="0" y="0" width="571.8889058430991" height="551.2222391764319" fill="#ffffff"></rect><g stroke-linecap="round" transform="translate(10 10) rotate(0 275.94445292154955 265.61111958821596)"><path d="M0 0 C140.46 0, 280.92 0, 551.89 0 M0 0 C204.72 0, 409.45 0, 551.89 0 M551.89 0 C551.89 152.39, 551.89 304.77, 551.89 531.22 M551.89 0 C551.89 107.04, 551.89 214.08, 551.89 531.22 M551.89 531.22 C332.47 531.22, 113.04 531.22, 0 531.22 M551.89 531.22 C417.98 531.22, 284.07 531.22, 0 531.22 M0 531.22 C0 418.2, 0 305.18, 0 0 M0 531.22 C0 346.7, 0 162.17, 0 0" stroke="#000000" stroke-width="1" fill="none"></path></g><g transform="translate(85.44442749023415 48.555572509765625) rotate(0 142 16)"><text x="0" y="26" font-family="Helvetica, Segoe UI Emoji" font-size="28px" fill="#000000" text-anchor="start" style="white-space: pre;" direction="ltr">Reward created successfully</text></g><g transform="translate(65.88732457160927 145.118741350042) rotate(0 33.5 11.5)"><text x="0" y="18" font-family="Helvetica, Segoe UI Emoji" font-size="20px" fill="#000000" text-anchor="start" style="white-space: pre;" direction="ltr">amount</text></g><g stroke-linecap="round" transform="translate(267.5406907399499 142.480934712235) rotate(0 77.99999999999989 14.152236652236752)"><path d="M0 0 C55.83 0, 111.67 0, 156 0 M0 0 C38.38 0, 76.75 0, 156 0 M156 0 C156 7.9, 156 15.79, 156 28.3 M156 0 C156 10.3, 156 20.6, 156 28.3 M156 28.3 C117.29 28.3, 78.59 28.3, 0 28.3 M156 28.3 C96.97 28.3, 37.93 28.3, 0 28.3 M0 28.3 C0 21.43, 0 14.55, 0 0 M0 28.3 C0 22.04, 0 15.77, 0 0" stroke="#000000" stroke-width="1" fill="none"></path></g><g transform="translate(66.88732457160927 204.63380306959152) rotate(0 49.5 11.5)"><text x="0" y="18" font-family="Helvetica, Segoe UI Emoji" font-size="20px" fill="#000000" text-anchor="start" style="white-space: pre;" direction="ltr">justification</text></g><g transform="translate(73.66508539517713 338.18934167093744) rotate(0 33.5 11.5)"><text x="0" y="18" font-family="Helvetica, Segoe UI Emoji" font-size="20px" fill="#000000" text-anchor="start" style="white-space: pre;" direction="ltr">reward URL</text></g><g stroke-linecap="round" transform="translate(206.4295796288386 142.52151912781937) rotate(0 30.5 14.097222222222399)"><path d="M0 0 C14.45 0, 28.9 0, 61 0 M0 0 C13.99 0, 27.98 0, 61 0 M61 0 C61 10.08, 61 20.16, 61 28.19 M61 0 C61 7.45, 61 14.91, 61 28.19 M61 28.19 C41.93 28.19, 22.86 28.19, 0 28.19 M61 28.19 C41.66 28.19, 22.33 28.19, 0 28.19 M0 28.19 C0 21.41, 0 14.63, 0 0 M0 28.19 C0 20.05, 0 11.91, 0 0" stroke="#000000" stroke-width="1" fill="none"></path></g><g transform="translate(213.09624629550513 145.118741350042) rotate(0 21 11.5)"><text x="21" y="18" font-family="Helvetica, Segoe UI Emoji" font-size="20px" fill="#000000" text-anchor="middle" style="white-space: pre;" direction="ltr">USD</text></g><g stroke-linecap="round" transform="translate(206.4295796288386 207.92332482337952) rotate(0 134.84126984126988 51.111111111111086)"><path d="M0 0 C97.82 0, 195.63 0, 269.68 0 M0 0 C87.58 0, 175.15 0, 269.68 0 M269.68 0 C269.68 23.55, 269.68 47.1, 269.68 102.22 M269.68 0 C269.68 38.76, 269.68 77.52, 269.68 102.22 M269.68 102.22 C168.96 102.22, 68.23 102.22, 0 102.22 M269.68 102.22 C192.45 102.22, 115.21 102.22, 0 102.22 M0 102.22 C0 63.99, 0 25.75, 0 0 M0 102.22 C0 69.03, 0 35.84, 0 0" stroke="#000000" stroke-width="1" fill="none"></path></g><g stroke-linecap="round" transform="translate(205.3184685177273 334.0422606998018) rotate(0 85.37038167317712 15)"><path d="M0 0 C58.97 0, 117.94 0, 170.74 0 M0 0 C66.44 0, 132.88 0, 170.74 0 M170.74 0 C170.74 9.84, 170.74 19.67, 170.74 30 M170.74 0 C170.74 11.46, 170.74 22.92, 170.74 30 M170.74 30 C111.07 30, 51.39 30, 0 30 M170.74 30 C121.68 30, 72.63 30, 0 30 M0 30 C0 21.78, 0 13.56, 0 0 M0 30 C0 20.57, 0 11.13, 0 0" stroke="#000000" stroke-width="1" fill="none"></path></g><g transform="translate(76.67993668715121 404.7879712581632) rotate(0 41.5 11.5)"><text x="0" y="18" font-family="Helvetica, Segoe UI Emoji" font-size="20px" fill="#000000" text-anchor="start" style="white-space: pre;" direction="ltr">valid until</text></g><g stroke-linecap="round" transform="translate(212.71710211484606 392.3770074341571) rotate(0 71.39795918367349 18.459183673469397)"><path d="M0.56 1.22 L141.57 0.94 L141.78 38.25 L-1.25 38.38" stroke="none" stroke-width="0" fill="#fff"></path><path d="M-0.98 1.62 C34.12 -1.49, 68.83 -1.89, 142.94 -0.88 M0.57 -0.59 C29.47 0.89, 57.16 -0.08, 142.07 0.14 M142.91 -0.64 C143.04 15.1, 140.92 25.51, 142.3 36.46 M141.87 -0.37 C142.21 8.72, 143.63 15.39, 141.94 37.29 M144.77 37.32 C105.38 36.8, 65.06 35.87, 0.85 37.03 M142.32 37.91 C86.66 35.41, 32.17 35.36, 0.24 37.86 M1.37 35.32 C1.21 25.05, 1.19 10.31, -0.4 -0.05 M-0.02 37.73 C0.2 26.83, -0.88 18.04, -0.59 0.08" stroke="#000000" stroke-width="1" fill="none"></path></g><g transform="translate(247.36506129851932 398.8361911076265) rotate(0 5 12.5)"><text x="0" y="18" font-family="Virgil, Segoe UI Emoji" font-size="20px" fill="#000000" text-anchor="start" style="white-space: pre;" direction="ltr">/</text></g><g transform="translate(277.8650612985193 398.3361911076265) rotate(0 5 12.5)"><text x="0" y="18" font-family="Virgil, Segoe UI Emoji" font-size="20px" fill="#000000" text-anchor="start" style="white-space: pre;" direction="ltr">/</text></g><g stroke-linecap="round" transform="translate(366.8650612985193 391.3361911076265) rotate(0 17.75 17.75)"><path d="M0.94 -1.01 L36.83 -1.25 L36.96 34.45 L-0.83 36.6" stroke="none" stroke-width="0" fill="#868e96"></path><path d="M-1.6 -0.35 C6.91 0.23, 16.94 -1.91, 34.19 0.08 M0.95 -0.04 C12.64 -1.04, 25.48 0.32, 34.73 -0.09 M37.19 -1.59 C34.07 10.35, 34.93 20.04, 35.6 37.4 M36.19 0.82 C34.7 6.51, 35.74 14.48, 34.58 35.73 M35.05 35.71 C19.96 36.63, 7.29 37.51, -0.4 33.62 M35.33 35.31 C26.31 35.42, 18.5 35.89, -0.89 34.55 M1.85 36.37 C1.11 22.03, 0.24 8.62, 1.34 1.61 M-0.36 34.87 C0.29 24.35, -0.21 14.65, 0.61 -0.61" stroke="#000000" stroke-width="1" fill="none"></path></g><g stroke-linecap="round" transform="translate(367.8650612985193 392.3361911076265) rotate(0 17.5 4.5)"><path d="M-1.01 1.33 L33.75 1.46 L33.95 8.17 L1.1 7.74" stroke="none" stroke-width="0" fill="#000"></path><path d="M-0.35 -2 C13.48 -0.6, 24.68 -1.03, 35.08 1.14 M-0.04 -0.02 C7.69 -0.19, 17.48 -1.1, 34.91 0.05 M34.28 -0.59 C34.8 2.2, 34.28 4.86, 35.86 8.17 M35.37 -0.3 C34.56 2.54, 34.82 4.33, 35.1 9.44 M35.21 7.62 C24.64 9.03, 14.32 8.52, -1.88 8.05 M34.81 8.78 C21.27 9.88, 7.77 8.05, -0.95 9.68 M0.39 9.37 C-0.22 7, -0.37 5.64, 0.73 -0.02 M-0.28 9.26 C-0.31 5.6, 0.09 2.41, -0.28 0.21" stroke="#000000" stroke-width="1" fill="none"></path></g><g stroke-linecap="round" transform="translate(375.3650612985193 383.8361911076265) rotate(0 3 7)"><path d="M1.33 -1.25 L7.46 -1.05 L5.17 15.1 L-1.26 12.71" stroke="none" stroke-width="0" fill="#868e96"></path><path d="M-0.6 0.04 C1.4 -0.59, 2.93 0.04, 6.34 -0.36 M-0.01 -0.22 C2.36 0.19, 4.41 -0.02, 6.02 -0.1 M5.08 -0.34 C5.8 3.42, 6.19 10.47, 4.71 13.49 M5.53 -0.6 C6.36 3.16, 5.45 6.86, 6.69 14.14 M5.59 14.26 C3.76 14.53, 1.34 13.44, -0.28 14.6 M5.93 14.07 C5.03 14.2, 3.24 13.7, 0.21 13.76 M0.58 13.72 C-0.16 8.67, 0.81 5.49, -0.03 1.14 M0.41 13.59 C0.11 9.37, 0.48 3.91, 0.33 -0.35" stroke="#000000" stroke-width="1" fill="none"></path></g><g stroke-linecap="round" transform="translate(390.3650612985193 383.8361911076265) rotate(0 3 7)"><path d="M-1.25 1.46 L4.95 -0.83 L7.1 12.74 L-1.29 14.58" stroke="none" stroke-width="0" fill="#868e96"></path><path d="M0.04 -0.26 C0.72 -0.33, 2.67 0.4, 5.64 0.52 M-0.22 0.04 C2.56 -0.23, 4.71 0.02, 5.9 0.08 M5.66 -0.32 C4.73 5.45, 7.22 9.47, 5.49 13.15 M5.4 0.26 C5.93 4.52, 6.28 11.02, 6.14 14.55 M6.26 14.03 C4.85 13.84, 2.11 13.67, 0.6 13.45 M6.07 14.28 C4.52 13.72, 2.32 14.19, -0.24 14.13 M-0.28 13.97 C-0.57 9.44, 1.07 2.97, 1.14 0.63 M-0.41 14.06 C0.28 10.73, -0.34 6.93, -0.35 0.47" stroke="#000000" stroke-width="1" fill="none"></path></g><g stroke-linecap="round"><g transform="translate(383.8650612985193 400.3361911076265) rotate(0 0.6422718642013479 13.197904566302896)"><path d="M-0.88 -1.99 C-1.43 7.57, 1.15 13.78, 2.24 28.39 M0.14 0.63 C-0.63 7.75, 0.34 15.35, 0.76 27.34" stroke="#000000" stroke-width="1" fill="none"></path></g></g><g stroke-linecap="round"><g transform="translate(374.3650612985193 399.3361911076265) rotate(0 0.19790456630289555 13.301320007070899)"><path d="M-1.99 -1.31 C0.2 6.74, -0.97 12.94, 2.39 27.91 M0.63 -0.77 C-0.14 8.39, -0.23 16.93, 1.34 27.2" stroke="#000000" stroke-width="1" fill="none"></path></g></g><g stroke-linecap="round"><g transform="translate(393.8650612985193 400.8361911076265) rotate(0 0.2720004984978459 12.683548028115183)"><path d="M-1.31 0.08 C1.49 6.67, 2.55 17.58, 1.41 25.45 M-0.77 -0.09 C0.43 5.46, 0.98 12.41, 0.7 24.84" stroke="#000000" stroke-width="1" fill="none"></path></g></g><g stroke-linecap="round"><g transform="translate(402.8650612985193 408.8361911076265) rotate(0 -17.287554731126875 -0.13689562075796857)"><path d="M0.08 1.14 C-9.9 1.52, -15.53 -0.31, -34.05 -1.46 M-0.09 0.05 C-10.99 0, -20.5 -1.06, -34.66 -0.25" stroke="#000000" stroke-width="1" fill="none"></path></g></g><g stroke-linecap="round"><g transform="translate(402.3650612985193 417.8361911076265) rotate(0 -18.16205287910998 0.04547248221933842)"><path d="M1.14 -1.19 C-5.48 2.11, -14.51 0.37, -37.46 1.28 M0.05 -0.32 C-12.82 1.18, -26.96 0.04, -36.25 0.77" stroke="#000000" stroke-width="1" fill="none"></path></g></g><g stroke-linecap="round" transform="translate(340.7275521017252 468.94674259140356) rotate(0 68.33333333333326 18.888905843098996)"><path d="M0 0 C0 0, 0 0, 0 0 M0 0 C0 0, 0 0, 0 0 M-0.26 6.4 C1.09 4.84, 2.44 3.29, 4.99 0.36 M-0.26 6.4 C1.46 4.42, 3.17 2.45, 4.99 0.36 M0.13 12.04 C2.6 9.2, 5.07 6.36, 10.63 -0.03 M0.13 12.04 C2.36 9.48, 4.59 6.92, 10.63 -0.03 M-0.13 18.44 C3.98 13.71, 8.09 8.98, 15.62 0.33 M-0.13 18.44 C3.41 14.36, 6.95 10.29, 15.62 0.33 M0.27 24.08 C6 17.49, 11.72 10.9, 21.26 -0.07 M0.27 24.08 C7.46 15.81, 14.65 7.53, 21.26 -0.07 M0 30.48 C5.48 24.19, 10.95 17.89, 26.25 0.29 M0 30.48 C9.05 20.07, 18.1 9.66, 26.25 0.29 M-0.26 36.88 C8.64 26.64, 17.54 16.41, 31.89 -0.1 M-0.26 36.88 C12.31 22.42, 24.88 7.96, 31.89 -0.1 M2.11 40.26 C13.59 27.05, 25.06 13.85, 36.88 0.26 M2.11 40.26 C12.5 28.3, 22.9 16.34, 36.88 0.26 M7.75 39.86 C19.43 26.42, 31.11 12.99, 42.52 -0.14 M7.75 39.86 C18.98 26.94, 30.22 14.01, 42.52 -0.14 M12.74 40.22 C24.86 26.28, 36.98 12.33, 47.51 0.22 M12.74 40.22 C20.81 30.93, 28.89 21.64, 47.51 0.22 M18.38 39.83 C31.65 24.56, 44.91 9.3, 53.15 -0.17 M18.38 39.83 C28.39 28.31, 38.41 16.79, 53.15 -0.17 M23.37 40.19 C36.54 25.03, 49.71 9.88, 58.14 0.19 M23.37 40.19 C34.58 27.29, 45.8 14.38, 58.14 0.19 M29.01 39.79 C38.99 28.31, 48.97 16.82, 63.78 -0.21 M29.01 39.79 C40.04 27.1, 51.07 14.42, 63.78 -0.21 M34 40.15 C41.91 31.05, 49.83 21.94, 68.77 0.15 M34 40.15 C43.74 28.94, 53.49 17.73, 68.77 0.15 M39.64 39.76 C52.44 25.03, 65.24 10.31, 74.41 -0.24 M39.64 39.76 C47.47 30.75, 55.31 21.73, 74.41 -0.24 M44.63 40.12 C54.86 28.34, 65.1 16.57, 79.4 0.12 M44.63 40.12 C53.28 30.16, 61.94 20.2, 79.4 0.12 M50.27 39.72 C60.09 28.43, 69.91 17.13, 85.04 -0.28 M50.27 39.72 C61.03 27.34, 71.8 14.96, 85.04 -0.28 M55.26 40.08 C64.66 29.27, 74.06 18.46, 90.03 0.08 M55.26 40.08 C65.85 27.89, 76.45 15.7, 90.03 0.08 M60.9 39.69 C72.37 26.49, 83.85 13.29, 95.67 -0.31 M60.9 39.69 C69.59 29.69, 78.29 19.68, 95.67 -0.31 M65.89 40.05 C74.2 30.49, 82.51 20.92, 100.66 0.05 M65.89 40.05 C78.29 25.78, 90.69 11.52, 100.66 0.05 M71.53 39.65 C83.8 25.54, 96.08 11.42, 106.3 -0.34 M71.53 39.65 C78.82 31.27, 86.11 22.88, 106.3 -0.34 M76.52 40.01 C89.61 24.96, 102.7 9.9, 111.29 0.02 M76.52 40.01 C85.09 30.16, 93.66 20.3, 111.29 0.02 M82.16 39.62 C90.2 30.37, 98.24 21.12, 116.27 0.38 M82.16 39.62 C93.56 26.5, 104.97 13.38, 116.27 0.38 M87.15 39.98 C95.85 29.97, 104.55 19.96, 121.92 -0.02 M87.15 39.98 C95.8 30.03, 104.45 20.07, 121.92 -0.02 M92.79 39.59 C99.78 31.55, 106.76 23.51, 126.91 0.34 M92.79 39.59 C101.4 29.69, 110 19.78, 126.91 0.34 M97.78 39.95 C108.93 27.11, 120.09 14.28, 132.55 -0.05 M97.78 39.95 C110.68 25.1, 123.59 10.25, 132.55 -0.05 M103.42 39.55 C114.64 26.64, 125.86 13.73, 137.54 0.31 M103.42 39.55 C116.21 24.83, 129.01 10.11, 137.54 0.31 M108.41 39.91 C115.34 31.93, 122.28 23.95, 137.27 6.7 M108.41 39.91 C115.74 31.48, 123.06 23.05, 137.27 6.7 M114.05 39.52 C119.08 33.73, 124.11 27.95, 137.01 13.1 M114.05 39.52 C123.16 29.04, 132.27 18.56, 137.01 13.1 M119.04 39.88 C125.53 32.41, 132.02 24.95, 137.41 18.74 M119.04 39.88 C123.99 34.17, 128.95 28.47, 137.41 18.74 M124.02 40.24 C128.33 35.28, 132.63 30.33, 137.15 25.14 M124.02 40.24 C129.2 34.28, 134.37 28.33, 137.15 25.14 M129.67 39.84 C132.79 36.25, 135.91 32.66, 137.54 30.79 M129.67 39.84 C131.44 37.8, 133.21 35.77, 137.54 30.79" stroke="#82c91e" stroke-width="0.5" fill="none"></path><path d="M0 0 C49.47 0, 98.93 0, 136.67 0 M0 0 C42.29 0, 84.59 0, 136.67 0 M136.67 0 C136.67 8.33, 136.67 16.66, 136.67 37.78 M136.67 0 C136.67 8.06, 136.67 16.12, 136.67 37.78 M136.67 37.78 C93.85 37.78, 51.03 37.78, 0 37.78 M136.67 37.78 C88.21 37.78, 39.74 37.78, 0 37.78 M0 37.78 C0 24.21, 0 10.64, 0 0 M0 37.78 C0 27.5, 0 17.22, 0 0" stroke="#000000" stroke-width="1" fill="none"></path></g><g transform="translate(372.94974041552723 475.50226423853906) rotate(0 37.5 11.5)"><text x="0" y="18" font-family="Helvetica, Segoe UI Emoji" font-size="20px" fill="#000000" text-anchor="start" style="white-space: pre;" direction="ltr">continue</text></g><g stroke-linecap="round" transform="translate(388.95413517850125 333.70723212274766) rotate(0 42.96295166015625 15.66137767973396)"><path d="M0 0 C0 0, 0 0, 0 0 M0 0 C0 0, 0 0, 0 0 M-0.26 6.4 C1.33 4.57, 2.92 2.74, 4.99 0.36 M-0.26 6.4 C1.67 4.17, 3.61 1.95, 4.99 0.36 M0.13 12.04 C4.31 7.24, 8.49 2.43, 10.63 -0.03 M0.13 12.04 C4.25 7.31, 8.36 2.58, 10.63 -0.03 M-0.13 18.44 C4.4 13.23, 8.93 8.02, 15.62 0.33 M-0.13 18.44 C6.09 11.29, 12.3 4.14, 15.62 0.33 M0.27 24.08 C6.1 17.37, 11.93 10.66, 21.26 -0.07 M0.27 24.08 C8.03 15.15, 15.79 6.22, 21.26 -0.07 M0 30.48 C7.44 21.92, 14.88 13.36, 26.25 0.29 M0 30.48 C9.23 19.87, 18.45 9.26, 26.25 0.29 M2.37 33.86 C8.28 27.06, 14.18 20.27, 31.89 -0.1 M2.37 33.86 C11.1 23.81, 19.83 13.77, 31.89 -0.1 M8.01 33.46 C18.87 20.98, 29.72 8.49, 36.88 0.26 M8.01 33.46 C15.44 24.92, 22.87 16.37, 36.88 0.26 M13 33.82 C24.34 20.78, 35.68 7.73, 42.52 -0.14 M13 33.82 C20.91 24.72, 28.83 15.61, 42.52 -0.14 M18.64 33.43 C27.12 23.68, 35.59 13.93, 47.51 0.22 M18.64 33.43 C27.73 22.98, 36.81 12.53, 47.51 0.22 M23.63 33.79 C30.77 25.58, 37.9 17.37, 53.15 -0.17 M23.63 33.79 C30.05 26.4, 36.47 19.01, 53.15 -0.17 M29.27 33.39 C38.11 23.22, 46.96 13.05, 58.14 0.19 M29.27 33.39 C35.28 26.48, 41.29 19.57, 58.14 0.19 M34.26 33.75 C42.43 24.35, 50.6 14.95, 63.78 -0.21 M34.26 33.75 C40.39 26.7, 46.52 19.64, 63.78 -0.21 M39.9 33.36 C49.33 22.51, 58.76 11.66, 68.77 0.15 M39.9 33.36 C45.83 26.54, 51.75 19.73, 68.77 0.15 M44.89 33.72 C56.26 20.63, 67.64 7.55, 74.41 -0.24 M44.89 33.72 C54.79 22.33, 64.69 10.95, 74.41 -0.24 M50.53 33.33 C56.58 26.37, 62.62 19.42, 79.4 0.12 M50.53 33.33 C57.93 24.81, 65.34 16.29, 79.4 0.12 M55.52 33.69 C66.01 21.61, 76.51 9.54, 85.04 -0.28 M55.52 33.69 C62.29 25.89, 69.07 18.1, 85.04 -0.28 M61.16 33.29 C67.92 25.51, 74.68 17.74, 88.06 2.35 M61.16 33.29 C69.1 24.16, 77.03 15.03, 88.06 2.35 M66.15 33.65 C74.36 24.21, 82.56 14.77, 88.45 7.99 M66.15 33.65 C74.01 24.61, 81.87 15.57, 88.45 7.99 M71.79 33.26 C76.57 27.76, 81.35 22.26, 88.19 14.39 M71.79 33.26 C77.32 26.9, 82.85 20.54, 88.19 14.39 M76.78 33.62 C80.26 29.61, 83.75 25.6, 88.59 20.03 M76.78 33.62 C80.31 29.55, 83.84 25.49, 88.59 20.03 M82.42 33.22 C83.67 31.79, 84.91 30.35, 88.33 26.43 M82.42 33.22 C84.67 30.63, 86.92 28.04, 88.33 26.43" stroke="#4c6ef5" stroke-width="0.5" fill="none"></path><path d="M0 0 C34.37 0, 68.73 0, 85.93 0 M0 0 C30.8 0, 61.6 0, 85.93 0 M85.93 0 C85.93 7.3, 85.93 14.59, 85.93 31.32 M85.93 0 C85.93 10.75, 85.93 21.51, 85.93 31.32 M85.93 31.32 C64.61 31.32, 43.3 31.32, 0 31.32 M85.93 31.32 C64.26 31.32, 42.59 31.32, 0 31.32 M0 31.32 C0 19.26, 0 7.2, 0 0 M0 31.32 C0 20.81, 0 10.29, 0 0" stroke="#000000" stroke-width="1" fill="none"></path></g><g transform="translate(396.7054353242104 338.1304988211914) rotate(0 35 11.5)"><text x="0" y="18" font-family="Helvetica, Segoe UI Emoji" font-size="20px" fill="#000000" text-anchor="start" style="white-space: pre;" direction="ltr">copy url</text></g><g transform="translate(78.68102157642033 106.96052345493217) rotate(0 20 11.5)"><text x="0" y="17" font-family="Helvetica, Segoe UI Emoji" font-size="20px" fill="#000000" text-anchor="start" style="white-space: pre;" direction="ltr">from</text></g><g transform="translate(211.63556703096583 97.86961436402316) rotate(0 71.5 11.5)"><text x="0" y="17" font-family="Helvetica, Segoe UI Emoji" font-size="20px" fill="#000000" text-anchor="start" style="white-space: pre;" direction="ltr">video promotion</text></g></svg> \ No newline at end of file
diff --git a/images/backoffice-reward-create.svg b/images/backoffice-reward-create.svg
index a5c53faa..acdbf0e6 100644
--- a/images/backoffice-reward-create.svg
+++ b/images/backoffice-reward-create.svg
@@ -13,4 +13,4 @@
}
</style>
</defs>
- <rect x="0" y="0" width="493" height="527.3333587646484" fill="#ffffff"></rect><g stroke-linecap="round" transform="translate(10 10) rotate(0 236.5 253.66667938232422)"><path d="M0 0 C131.16 0, 262.31 0, 473 0 M0 0 C111.95 0, 223.9 0, 473 0 M473 0 C473 107.96, 473 215.91, 473 507.33 M473 0 C473 117.77, 473 235.54, 473 507.33 M473 507.33 C367.62 507.33, 262.25 507.33, 0 507.33 M473 507.33 C343.17 507.33, 213.33 507.33, 0 507.33 M0 507.33 C0 342.58, 0 177.83, 0 0 M0 507.33 C0 399.36, 0 291.39, 0 0" stroke="#000000" stroke-width="1" fill="none"></path></g><g transform="translate(85.44442749023438 48.555572509765625) rotate(0 81.5 16)"><text x="0" y="25" font-family="Helvetica, Segoe UI Emoji" font-size="28px" fill="#000000" text-anchor="start" style="white-space: pre;" direction="ltr">Authorize Tip</text></g><g transform="translate(65.8873245716095 145.11874135004155) rotate(0 33.5 11.5)"><text x="0" y="18" font-family="Helvetica, Segoe UI Emoji" font-size="20px" fill="#000000" text-anchor="start" style="white-space: pre;" direction="ltr">amount</text></g><g stroke-linecap="round" transform="translate(267.5406907399498 142.48093471223478) rotate(0 77.99999999999983 14.152236652236752)"><path d="M0 0 C59.79 0, 119.57 0, 156 0 M0 0 C43.47 0, 86.93 0, 156 0 M156 0 C156 6.15, 156 12.31, 156 28.3 M156 0 C156 10.96, 156 21.92, 156 28.3 M156 28.3 C104.75 28.3, 53.51 28.3, 0 28.3 M156 28.3 C108.41 28.3, 60.82 28.3, 0 28.3 M0 28.3 C0 20.46, 0 12.62, 0 0 M0 28.3 C0 20.37, 0 12.43, 0 0" stroke="#000000" stroke-width="1" fill="none"></path></g><g transform="translate(66.8873245716095 204.63380306959152) rotate(0 49.5 11.5)"><text x="0" y="18" font-family="Helvetica, Segoe UI Emoji" font-size="20px" fill="#000000" text-anchor="start" style="white-space: pre;" direction="ltr">justification</text></g><g transform="translate(69.22065790494287 337.0782475140361) rotate(0 55.5 11.5)"><text x="0" y="18" font-family="Helvetica, Segoe UI Emoji" font-size="20px" fill="#000000" text-anchor="start" style="white-space: pre;" direction="ltr">URL after tip</text></g><g stroke-linecap="round" transform="translate(206.4295796288386 142.52151912781915) rotate(0 30.5 14.097222222222399)"><path d="M0 0 C21.91 0, 43.82 0, 61 0 M0 0 C15.53 0, 31.06 0, 61 0 M61 0 C61 7.5, 61 15.01, 61 28.19 M61 0 C61 8.02, 61 16.03, 61 28.19 M61 28.19 C42.22 28.19, 23.45 28.19, 0 28.19 M61 28.19 C45.87 28.19, 30.75 28.19, 0 28.19 M0 28.19 C0 17.6, 0 7, 0 0 M0 28.19 C0 20.22, 0 12.24, 0 0" stroke="#000000" stroke-width="1" fill="none"></path></g><g transform="translate(213.09624629550524 145.11874135004155) rotate(0 21 11.5)"><text x="21" y="18" font-family="Helvetica, Segoe UI Emoji" font-size="20px" fill="#000000" text-anchor="middle" style="white-space: pre;" direction="ltr">USD</text></g><g stroke-linecap="round" transform="translate(206.4295796288386 207.9233248233793) rotate(0 110.55555555555554 51.111111111111086)"><path d="M0 0 C44.54 0, 89.08 0, 221.11 0 M0 0 C71.21 0, 142.42 0, 221.11 0 M221.11 0 C221.11 37.99, 221.11 75.97, 221.11 102.22 M221.11 0 C221.11 30.08, 221.11 60.16, 221.11 102.22 M221.11 102.22 C157.92 102.22, 94.74 102.22, 0 102.22 M221.11 102.22 C136.25 102.22, 51.39 102.22, 0 102.22 M0 102.22 C0 70.18, 0 38.13, 0 0 M0 102.22 C0 65.3, 0 28.38, 0 0" stroke="#000000" stroke-width="1" fill="none"></path></g><g stroke-linecap="round" transform="translate(205.3184685177274 334.0422606998013) rotate(0 108.88888888888886 15)"><path d="M0 0 C60.68 0, 121.36 0, 217.78 0 M0 0 C47.35 0, 94.7 0, 217.78 0 M217.78 0 C217.78 11.62, 217.78 23.23, 217.78 30 M217.78 0 C217.78 9.86, 217.78 19.71, 217.78 30 M217.78 30 C151.34 30, 84.91 30, 0 30 M217.78 30 C157.45 30, 97.12 30, 0 30 M0 30 C0 21.59, 0 13.18, 0 0 M0 30 C0 19.86, 0 9.71, 0 0" stroke="#000000" stroke-width="1" fill="none"></path></g><g stroke-linecap="round" transform="translate(289.1572037707465 446.8971981070499) rotate(0 68.33333333333326 18.888905843098996)"><path d="M0 0 C0 0, 0 0, 0 0 M0 0 C0 0, 0 0, 0 0 M-0.26 6.4 C0.87 5.1, 2 3.79, 4.99 0.36 M-0.26 6.4 C1.41 4.48, 3.08 2.56, 4.99 0.36 M0.13 12.04 C3.51 8.15, 6.89 4.27, 10.63 -0.03 M0.13 12.04 C3.27 8.43, 6.41 4.82, 10.63 -0.03 M-0.13 18.44 C4.49 13.13, 9.1 7.82, 15.62 0.33 M-0.13 18.44 C5.98 11.41, 12.1 4.37, 15.62 0.33 M0.27 24.08 C6.99 16.35, 13.71 8.62, 21.26 -0.07 M0.27 24.08 C6.62 16.77, 12.97 9.46, 21.26 -0.07 M0 30.48 C6.13 23.43, 12.26 16.38, 26.25 0.29 M0 30.48 C7.11 22.31, 14.22 14.13, 26.25 0.29 M-0.26 36.88 C8.61 26.67, 17.48 16.47, 31.89 -0.1 M-0.26 36.88 C9.73 25.39, 19.72 13.9, 31.89 -0.1 M2.11 40.26 C15.11 25.29, 28.12 10.33, 36.88 0.26 M2.11 40.26 C9.34 31.93, 16.58 23.61, 36.88 0.26 M7.75 39.86 C18.54 27.45, 29.32 15.04, 42.52 -0.14 M7.75 39.86 C21.47 24.07, 35.2 8.29, 42.52 -0.14 M12.74 40.22 C26.45 24.44, 40.17 8.66, 47.51 0.22 M12.74 40.22 C24.07 27.19, 35.39 14.16, 47.51 0.22 M18.38 39.83 C26.6 30.37, 34.82 20.92, 53.15 -0.17 M18.38 39.83 C30.86 25.47, 43.35 11.1, 53.15 -0.17 M23.37 40.19 C30.9 31.52, 38.44 22.85, 58.14 0.19 M23.37 40.19 C34.91 26.91, 46.46 13.62, 58.14 0.19 M29.01 39.79 C38.04 29.4, 47.08 19.01, 63.78 -0.21 M29.01 39.79 C37.38 30.16, 45.76 20.53, 63.78 -0.21 M34 40.15 C44.6 27.96, 55.19 15.77, 68.77 0.15 M34 40.15 C41.57 31.44, 49.14 22.73, 68.77 0.15 M39.64 39.76 C49.31 28.63, 58.98 17.51, 74.41 -0.24 M39.64 39.76 C46.94 31.36, 54.24 22.96, 74.41 -0.24 M44.63 40.12 C57.31 25.52, 70 10.93, 79.4 0.12 M44.63 40.12 C57.04 25.84, 69.45 11.56, 79.4 0.12 M50.27 39.72 C63.52 24.48, 76.77 9.23, 85.04 -0.28 M50.27 39.72 C59.63 28.95, 69 18.18, 85.04 -0.28 M55.26 40.08 C63.79 30.27, 72.32 20.45, 90.03 0.08 M55.26 40.08 C62.43 31.83, 69.6 23.58, 90.03 0.08 M60.9 39.69 C73.1 25.65, 85.3 11.62, 95.67 -0.31 M60.9 39.69 C73.22 25.52, 85.54 11.34, 95.67 -0.31 M65.89 40.05 C74.13 30.57, 82.37 21.09, 100.66 0.05 M65.89 40.05 C73.02 31.84, 80.15 23.64, 100.66 0.05 M71.53 39.65 C84.1 25.19, 96.67 10.73, 106.3 -0.34 M71.53 39.65 C79.65 30.32, 87.77 20.98, 106.3 -0.34 M76.52 40.01 C89.46 25.12, 102.41 10.23, 111.29 0.02 M76.52 40.01 C86.11 28.98, 95.7 17.95, 111.29 0.02 M82.16 39.62 C91.69 28.65, 101.23 17.69, 116.27 0.38 M82.16 39.62 C89.25 31.46, 96.35 23.3, 116.27 0.38 M87.15 39.98 C98.5 26.92, 109.86 13.86, 121.92 -0.02 M87.15 39.98 C98.39 27.04, 109.64 14.11, 121.92 -0.02 M92.79 39.59 C105.18 25.33, 117.58 11.07, 126.91 0.34 M92.79 39.59 C100.01 31.28, 107.23 22.97, 126.91 0.34 M97.78 39.95 C108.79 27.28, 119.8 14.61, 132.55 -0.05 M97.78 39.95 C109.46 26.51, 121.14 13.07, 132.55 -0.05 M103.42 39.55 C115.83 25.28, 128.23 11.01, 137.54 0.31 M103.42 39.55 C114.05 27.32, 124.68 15.1, 137.54 0.31 M108.41 39.91 C114.24 33.2, 120.08 26.48, 137.27 6.7 M108.41 39.91 C116.61 30.48, 124.8 21.05, 137.27 6.7 M114.05 39.52 C119.19 33.61, 124.32 27.7, 137.01 13.1 M114.05 39.52 C118.81 34.04, 123.56 28.57, 137.01 13.1 M119.04 39.88 C126.1 31.75, 133.17 23.62, 137.41 18.74 M119.04 39.88 C123.1 35.2, 127.17 30.53, 137.41 18.74 M124.02 40.24 C128.99 34.53, 133.95 28.81, 137.15 25.14 M124.02 40.24 C128.37 35.24, 132.71 30.24, 137.15 25.14 M129.67 39.84 C132.09 37.06, 134.51 34.27, 137.54 30.79 M129.67 39.84 C132.69 36.36, 135.71 32.89, 137.54 30.79" stroke="#82c91e" stroke-width="0.5" fill="none"></path><path d="M0 0 C47.02 0, 94.04 0, 136.67 0 M0 0 C39.95 0, 79.91 0, 136.67 0 M136.67 0 C136.67 7.93, 136.67 15.86, 136.67 37.78 M136.67 0 C136.67 9.75, 136.67 19.5, 136.67 37.78 M136.67 37.78 C85.5 37.78, 34.33 37.78, 0 37.78 M136.67 37.78 C97.93 37.78, 59.2 37.78, 0 37.78 M0 37.78 C0 26.23, 0 14.69, 0 0 M0 37.78 C0 30.21, 0 22.65, 0 0" stroke="#000000" stroke-width="1" fill="none"></path></g><g transform="translate(321.3793920845483 453.45271975418564) rotate(0 27.5 11.5)"><text x="0" y="18" font-family="Helvetica, Segoe UI Emoji" font-size="20px" fill="#000000" text-anchor="start" style="white-space: pre;" direction="ltr">create</text></g><g stroke-linecap="round" transform="translate(109.15720377074649 446.0638393424015) rotate(0 68.33333333333326 18.888905843098996)"><path d="M0 0 C49.19 0, 98.37 0, 136.67 0 M0 0 C38.88 0, 77.76 0, 136.67 0 M136.67 0 C136.67 10.58, 136.67 21.17, 136.67 37.78 M136.67 0 C136.67 11.28, 136.67 22.55, 136.67 37.78 M136.67 37.78 C97.37 37.78, 58.07 37.78, 0 37.78 M136.67 37.78 C107.23 37.78, 77.8 37.78, 0 37.78 M0 37.78 C0 27.01, 0 16.24, 0 0 M0 37.78 C0 24.17, 0 10.57, 0 0" stroke="#000000" stroke-width="1" fill="none"></path></g><g transform="translate(141.37939208454827 452.6193609895372) rotate(0 29 11.5)"><text x="0" y="18" font-family="Helvetica, Segoe UI Emoji" font-size="20px" fill="#000000" text-anchor="start" style="white-space: pre;" direction="ltr">cancel</text></g><g transform="translate(62.3386848521759 102.39751456586987) rotate(0 20 11.5)"><text x="0" y="17" font-family="Helvetica, Segoe UI Emoji" font-size="20px" fill="#000000" text-anchor="start" style="white-space: pre;" direction="ltr">from</text></g><g transform="translate(211.2023212158124 103.76115092950636) rotate(0 71.5 11.5)"><text x="0" y="17" font-family="Helvetica, Segoe UI Emoji" font-size="20px" fill="#000000" text-anchor="start" style="white-space: pre;" direction="ltr">video promotion</text></g></svg> \ No newline at end of file
+ <rect x="0" y="0" width="493" height="527.3333587646484" fill="#ffffff"></rect><g stroke-linecap="round" transform="translate(10 10) rotate(0 236.5 253.66667938232422)"><path d="M0 0 C131.16 0, 262.31 0, 473 0 M0 0 C111.95 0, 223.9 0, 473 0 M473 0 C473 107.96, 473 215.91, 473 507.33 M473 0 C473 117.77, 473 235.54, 473 507.33 M473 507.33 C367.62 507.33, 262.25 507.33, 0 507.33 M473 507.33 C343.17 507.33, 213.33 507.33, 0 507.33 M0 507.33 C0 342.58, 0 177.83, 0 0 M0 507.33 C0 399.36, 0 291.39, 0 0" stroke="#000000" stroke-width="1" fill="none"></path></g><g transform="translate(85.44442749023438 48.555572509765625) rotate(0 81.5 16)"><text x="0" y="25" font-family="Helvetica, Segoe UI Emoji" font-size="28px" fill="#000000" text-anchor="start" style="white-space: pre;" direction="ltr">Authorize Reward</text></g><g transform="translate(65.8873245716095 145.11874135004155) rotate(0 33.5 11.5)"><text x="0" y="18" font-family="Helvetica, Segoe UI Emoji" font-size="20px" fill="#000000" text-anchor="start" style="white-space: pre;" direction="ltr">amount</text></g><g stroke-linecap="round" transform="translate(267.5406907399498 142.48093471223478) rotate(0 77.99999999999983 14.152236652236752)"><path d="M0 0 C59.79 0, 119.57 0, 156 0 M0 0 C43.47 0, 86.93 0, 156 0 M156 0 C156 6.15, 156 12.31, 156 28.3 M156 0 C156 10.96, 156 21.92, 156 28.3 M156 28.3 C104.75 28.3, 53.51 28.3, 0 28.3 M156 28.3 C108.41 28.3, 60.82 28.3, 0 28.3 M0 28.3 C0 20.46, 0 12.62, 0 0 M0 28.3 C0 20.37, 0 12.43, 0 0" stroke="#000000" stroke-width="1" fill="none"></path></g><g transform="translate(66.8873245716095 204.63380306959152) rotate(0 49.5 11.5)"><text x="0" y="18" font-family="Helvetica, Segoe UI Emoji" font-size="20px" fill="#000000" text-anchor="start" style="white-space: pre;" direction="ltr">justification</text></g><g transform="translate(69.22065790494287 337.0782475140361) rotate(0 55.5 11.5)"><text x="0" y="18" font-family="Helvetica, Segoe UI Emoji" font-size="20px" fill="#000000" text-anchor="start" style="white-space: pre;" direction="ltr">URL after reward</text></g><g stroke-linecap="round" transform="translate(206.4295796288386 142.52151912781915) rotate(0 30.5 14.097222222222399)"><path d="M0 0 C21.91 0, 43.82 0, 61 0 M0 0 C15.53 0, 31.06 0, 61 0 M61 0 C61 7.5, 61 15.01, 61 28.19 M61 0 C61 8.02, 61 16.03, 61 28.19 M61 28.19 C42.22 28.19, 23.45 28.19, 0 28.19 M61 28.19 C45.87 28.19, 30.75 28.19, 0 28.19 M0 28.19 C0 17.6, 0 7, 0 0 M0 28.19 C0 20.22, 0 12.24, 0 0" stroke="#000000" stroke-width="1" fill="none"></path></g><g transform="translate(213.09624629550524 145.11874135004155) rotate(0 21 11.5)"><text x="21" y="18" font-family="Helvetica, Segoe UI Emoji" font-size="20px" fill="#000000" text-anchor="middle" style="white-space: pre;" direction="ltr">USD</text></g><g stroke-linecap="round" transform="translate(206.4295796288386 207.9233248233793) rotate(0 110.55555555555554 51.111111111111086)"><path d="M0 0 C44.54 0, 89.08 0, 221.11 0 M0 0 C71.21 0, 142.42 0, 221.11 0 M221.11 0 C221.11 37.99, 221.11 75.97, 221.11 102.22 M221.11 0 C221.11 30.08, 221.11 60.16, 221.11 102.22 M221.11 102.22 C157.92 102.22, 94.74 102.22, 0 102.22 M221.11 102.22 C136.25 102.22, 51.39 102.22, 0 102.22 M0 102.22 C0 70.18, 0 38.13, 0 0 M0 102.22 C0 65.3, 0 28.38, 0 0" stroke="#000000" stroke-width="1" fill="none"></path></g><g stroke-linecap="round" transform="translate(205.3184685177274 334.0422606998013) rotate(0 108.88888888888886 15)"><path d="M0 0 C60.68 0, 121.36 0, 217.78 0 M0 0 C47.35 0, 94.7 0, 217.78 0 M217.78 0 C217.78 11.62, 217.78 23.23, 217.78 30 M217.78 0 C217.78 9.86, 217.78 19.71, 217.78 30 M217.78 30 C151.34 30, 84.91 30, 0 30 M217.78 30 C157.45 30, 97.12 30, 0 30 M0 30 C0 21.59, 0 13.18, 0 0 M0 30 C0 19.86, 0 9.71, 0 0" stroke="#000000" stroke-width="1" fill="none"></path></g><g stroke-linecap="round" transform="translate(289.1572037707465 446.8971981070499) rotate(0 68.33333333333326 18.888905843098996)"><path d="M0 0 C0 0, 0 0, 0 0 M0 0 C0 0, 0 0, 0 0 M-0.26 6.4 C0.87 5.1, 2 3.79, 4.99 0.36 M-0.26 6.4 C1.41 4.48, 3.08 2.56, 4.99 0.36 M0.13 12.04 C3.51 8.15, 6.89 4.27, 10.63 -0.03 M0.13 12.04 C3.27 8.43, 6.41 4.82, 10.63 -0.03 M-0.13 18.44 C4.49 13.13, 9.1 7.82, 15.62 0.33 M-0.13 18.44 C5.98 11.41, 12.1 4.37, 15.62 0.33 M0.27 24.08 C6.99 16.35, 13.71 8.62, 21.26 -0.07 M0.27 24.08 C6.62 16.77, 12.97 9.46, 21.26 -0.07 M0 30.48 C6.13 23.43, 12.26 16.38, 26.25 0.29 M0 30.48 C7.11 22.31, 14.22 14.13, 26.25 0.29 M-0.26 36.88 C8.61 26.67, 17.48 16.47, 31.89 -0.1 M-0.26 36.88 C9.73 25.39, 19.72 13.9, 31.89 -0.1 M2.11 40.26 C15.11 25.29, 28.12 10.33, 36.88 0.26 M2.11 40.26 C9.34 31.93, 16.58 23.61, 36.88 0.26 M7.75 39.86 C18.54 27.45, 29.32 15.04, 42.52 -0.14 M7.75 39.86 C21.47 24.07, 35.2 8.29, 42.52 -0.14 M12.74 40.22 C26.45 24.44, 40.17 8.66, 47.51 0.22 M12.74 40.22 C24.07 27.19, 35.39 14.16, 47.51 0.22 M18.38 39.83 C26.6 30.37, 34.82 20.92, 53.15 -0.17 M18.38 39.83 C30.86 25.47, 43.35 11.1, 53.15 -0.17 M23.37 40.19 C30.9 31.52, 38.44 22.85, 58.14 0.19 M23.37 40.19 C34.91 26.91, 46.46 13.62, 58.14 0.19 M29.01 39.79 C38.04 29.4, 47.08 19.01, 63.78 -0.21 M29.01 39.79 C37.38 30.16, 45.76 20.53, 63.78 -0.21 M34 40.15 C44.6 27.96, 55.19 15.77, 68.77 0.15 M34 40.15 C41.57 31.44, 49.14 22.73, 68.77 0.15 M39.64 39.76 C49.31 28.63, 58.98 17.51, 74.41 -0.24 M39.64 39.76 C46.94 31.36, 54.24 22.96, 74.41 -0.24 M44.63 40.12 C57.31 25.52, 70 10.93, 79.4 0.12 M44.63 40.12 C57.04 25.84, 69.45 11.56, 79.4 0.12 M50.27 39.72 C63.52 24.48, 76.77 9.23, 85.04 -0.28 M50.27 39.72 C59.63 28.95, 69 18.18, 85.04 -0.28 M55.26 40.08 C63.79 30.27, 72.32 20.45, 90.03 0.08 M55.26 40.08 C62.43 31.83, 69.6 23.58, 90.03 0.08 M60.9 39.69 C73.1 25.65, 85.3 11.62, 95.67 -0.31 M60.9 39.69 C73.22 25.52, 85.54 11.34, 95.67 -0.31 M65.89 40.05 C74.13 30.57, 82.37 21.09, 100.66 0.05 M65.89 40.05 C73.02 31.84, 80.15 23.64, 100.66 0.05 M71.53 39.65 C84.1 25.19, 96.67 10.73, 106.3 -0.34 M71.53 39.65 C79.65 30.32, 87.77 20.98, 106.3 -0.34 M76.52 40.01 C89.46 25.12, 102.41 10.23, 111.29 0.02 M76.52 40.01 C86.11 28.98, 95.7 17.95, 111.29 0.02 M82.16 39.62 C91.69 28.65, 101.23 17.69, 116.27 0.38 M82.16 39.62 C89.25 31.46, 96.35 23.3, 116.27 0.38 M87.15 39.98 C98.5 26.92, 109.86 13.86, 121.92 -0.02 M87.15 39.98 C98.39 27.04, 109.64 14.11, 121.92 -0.02 M92.79 39.59 C105.18 25.33, 117.58 11.07, 126.91 0.34 M92.79 39.59 C100.01 31.28, 107.23 22.97, 126.91 0.34 M97.78 39.95 C108.79 27.28, 119.8 14.61, 132.55 -0.05 M97.78 39.95 C109.46 26.51, 121.14 13.07, 132.55 -0.05 M103.42 39.55 C115.83 25.28, 128.23 11.01, 137.54 0.31 M103.42 39.55 C114.05 27.32, 124.68 15.1, 137.54 0.31 M108.41 39.91 C114.24 33.2, 120.08 26.48, 137.27 6.7 M108.41 39.91 C116.61 30.48, 124.8 21.05, 137.27 6.7 M114.05 39.52 C119.19 33.61, 124.32 27.7, 137.01 13.1 M114.05 39.52 C118.81 34.04, 123.56 28.57, 137.01 13.1 M119.04 39.88 C126.1 31.75, 133.17 23.62, 137.41 18.74 M119.04 39.88 C123.1 35.2, 127.17 30.53, 137.41 18.74 M124.02 40.24 C128.99 34.53, 133.95 28.81, 137.15 25.14 M124.02 40.24 C128.37 35.24, 132.71 30.24, 137.15 25.14 M129.67 39.84 C132.09 37.06, 134.51 34.27, 137.54 30.79 M129.67 39.84 C132.69 36.36, 135.71 32.89, 137.54 30.79" stroke="#82c91e" stroke-width="0.5" fill="none"></path><path d="M0 0 C47.02 0, 94.04 0, 136.67 0 M0 0 C39.95 0, 79.91 0, 136.67 0 M136.67 0 C136.67 7.93, 136.67 15.86, 136.67 37.78 M136.67 0 C136.67 9.75, 136.67 19.5, 136.67 37.78 M136.67 37.78 C85.5 37.78, 34.33 37.78, 0 37.78 M136.67 37.78 C97.93 37.78, 59.2 37.78, 0 37.78 M0 37.78 C0 26.23, 0 14.69, 0 0 M0 37.78 C0 30.21, 0 22.65, 0 0" stroke="#000000" stroke-width="1" fill="none"></path></g><g transform="translate(321.3793920845483 453.45271975418564) rotate(0 27.5 11.5)"><text x="0" y="18" font-family="Helvetica, Segoe UI Emoji" font-size="20px" fill="#000000" text-anchor="start" style="white-space: pre;" direction="ltr">create</text></g><g stroke-linecap="round" transform="translate(109.15720377074649 446.0638393424015) rotate(0 68.33333333333326 18.888905843098996)"><path d="M0 0 C49.19 0, 98.37 0, 136.67 0 M0 0 C38.88 0, 77.76 0, 136.67 0 M136.67 0 C136.67 10.58, 136.67 21.17, 136.67 37.78 M136.67 0 C136.67 11.28, 136.67 22.55, 136.67 37.78 M136.67 37.78 C97.37 37.78, 58.07 37.78, 0 37.78 M136.67 37.78 C107.23 37.78, 77.8 37.78, 0 37.78 M0 37.78 C0 27.01, 0 16.24, 0 0 M0 37.78 C0 24.17, 0 10.57, 0 0" stroke="#000000" stroke-width="1" fill="none"></path></g><g transform="translate(141.37939208454827 452.6193609895372) rotate(0 29 11.5)"><text x="0" y="18" font-family="Helvetica, Segoe UI Emoji" font-size="20px" fill="#000000" text-anchor="start" style="white-space: pre;" direction="ltr">cancel</text></g><g transform="translate(62.3386848521759 102.39751456586987) rotate(0 20 11.5)"><text x="0" y="17" font-family="Helvetica, Segoe UI Emoji" font-size="20px" fill="#000000" text-anchor="start" style="white-space: pre;" direction="ltr">from</text></g><g transform="translate(211.2023212158124 103.76115092950636) rotate(0 71.5 11.5)"><text x="0" y="17" font-family="Helvetica, Segoe UI Emoji" font-size="20px" fill="#000000" text-anchor="start" style="white-space: pre;" direction="ltr">video promotion</text></g></svg> \ No newline at end of file
diff --git a/images/challenger.dot b/images/challenger.dot
new file mode 100644
index 00000000..d3072fc7
--- /dev/null
+++ b/images/challenger.dot
@@ -0,0 +1,26 @@
+digraph G {
+
+ user[label="Resource\nOwner"];
+ exchange[label="Client"];
+ messenger[label="Messaging service"];
+ challenger [label="Challenger HTTPD"];
+ helper [label="Helper script"];
+ DBMS [label="Postgres\nDBMS"];
+ subgraph cluster_0 {
+ challenger;
+ helper;
+ DBMS;
+ label="Challenger OAuth 2.0 service";
+ }
+ user->exchange[label="0. request that\nrequires\nvalidated\naddress"];
+ exchange->challenger[label="1. authorize\naddress\nvalidation"];
+ user->challenger[label="2. Claimed\naddress"];
+ challenger->DBMS;
+ DBMS->challenger;
+ challenger->helper[label="3. TAN code\n+ address"];
+ helper->messenger[label="4. TAN code\n+ address"];
+ messenger->user[label="5. TAN code"];
+ user->challenger[label="6. TAN\ncode"];
+ user->exchange[label="7. Token"];
+ exchange->challenger[label="8. Get\nvalidated\naddress"];
+}
diff --git a/images/regional-arch.dot b/images/regional-arch.dot
new file mode 100644
index 00000000..8a61ed5e
--- /dev/null
+++ b/images/regional-arch.dot
@@ -0,0 +1,36 @@
+digraph G {
+ subgraph cluster_2 {
+ ubank;
+ nexus;
+ rank="same"; ebank; mbank;
+ label="Fiat currency";
+ };
+ subgraph cluster_1 {
+ user;
+ exchange;
+ shop;
+ rbank;
+ label="Regional currency";
+ };
+ subgraph cluster_2b {
+ }
+ user[label="Customer (Wallet)"];
+ shop[label="Merchant (Backend)"];
+ exchange[label="Exchange"];
+ ubank[label="Customer Fiat Bank"];
+ ebank[label="Exchange Fiat Bank"];
+ mbank[label="Merchant Fiat Bank"];
+ rbank[label="Regional Currency Bank"];
+ user->ubank [label="1. Initiate withdraw"];
+ ubank->ebank [label="2. Wire transfer"];
+ ebank->nexus [label="3. EBICS (CAMT)"];
+ nexus->rbank [label="4. Conversion (Cash-in)"];
+ rbank->exchange [label="5. Wirewatch"];
+ exchange->user [label="6. Withdraw E-Cash"];
+ user->shop [label="7. Spend E-Cash"];
+ shop->exchange [label="8. Deposit E-Cash"];
+ exchange->rbank [label="9. Credit Shop"];
+ rbank->nexus [xlabel="10. Conversion (Cash-out)"];
+ nexus->ebank [label="11. EBICS (PAIN)"];
+ ebank->mbank [label="12. Wire-transfer"];
+}
diff --git a/images/transaction-reward-states.dot b/images/transaction-reward-states.dot
deleted file mode 100644
index 476c8c74..00000000
--- a/images/transaction-reward-states.dot
+++ /dev/null
@@ -1,11 +0,0 @@
-digraph G {
- initial[label="", shape="circle"];
- dialog_user[label="dialog(user)"];
- pending_pickup[label="pickup"];
- done[label="done", shape="box"];
-
- initial -> dialog_user;
-
- dialog_user -> pending_pickup [color=blue, label="OK"];
- pending_pickup -> done [color=green];
-}
diff --git a/index.rst b/index.rst
index f562b2e8..bd3b30d6 100644
--- a/index.rst
+++ b/index.rst
@@ -37,23 +37,20 @@ practice a fraudulent Exchange might go bankrupt instead of paying the
Merchants and thus the Exchange will need to be audited regularly like
any other banking institution.
-The system will be based on free software and open protocols.
+The system is based on free software and open protocols.
+
+In this documentation, we describe the REST-based APIs between the various
+components, how to use the system, the internal architecture of key
+components, and how to get them installed and configured.
-In this document, we describe the REST-based APIs between the various
-components, internal architecture of key components, and how to get them
-installed. In addition to this documentation, we have source-level
-documentation which you can find converted to HTML at these pages:
-* `Exchange <https://docs.taler.net/doxygen/exchange/>`_
-* `Merchant <https://docs.taler.net/doxygen/merchant/>`_
-* `Wallet-core <https://docs.taler.net/doxygen/wallet-core/>`_
Documentation Overview
----------------------
.. toctree::
:numbered:
- :maxdepth: 2
+ :maxdepth: 1
core/index
taler-user-guide
diff --git a/kyc-process.pdf b/kyc-process.pdf
new file mode 100644
index 00000000..8b178c02
--- /dev/null
+++ b/kyc-process.pdf
Binary files differ
diff --git a/kyc-process.png b/kyc-process.png
new file mode 100644
index 00000000..563418b1
--- /dev/null
+++ b/kyc-process.png
Binary files differ
diff --git a/kyc-process.tex b/kyc-process.tex
new file mode 100644
index 00000000..c10dd8d9
--- /dev/null
+++ b/kyc-process.tex
@@ -0,0 +1,58 @@
+\documentclass[fleqn]{article}
+\usepackage{amsmath}
+\usepackage{multimedia}
+\usepackage[utf8]{inputenc}
+\usepackage{framed,color,ragged2e}
+\usepackage[absolute,overlay]{textpos}
+\usepackage{xcolor}
+\usepackage{relsize}
+\usepackage{graphicx}
+\usepackage{tikz,eurosym,calc}
+\usetikzlibrary{tikzmark}
+\usetikzlibrary{shapes,arrows,arrows.meta}
+\usetikzlibrary{positioning,fit,patterns}
+\usetikzlibrary{calc}
+\usepackage{pgf-umlsd}
+\usepackage{relsize}
+
+\pagestyle{empty}
+\begin{document}
+
+\begin{sequencediagram}
+ \newinst{customer}{Customer}
+ \newinst[4]{ex}{Exchange}
+ \newinst[4]{kyc}{KYC Provider}
+ \postlevel
+ \mess[0]{customer}{POST: payment request}{ex}
+ \mess[0]{ex}{POST: initiate KYC}{kyc}
+ \mess[0]{kyc}{KYC-Start-URL}{ex}
+ \mess[0]{ex}{KYC-Start-URL}{customer}
+ \postlevel
+ \mess[0]{customer}{GET: KYC-Start-URL}{kyc}
+ \mess[0]{kyc}{KYC Web Form}{customer}
+ \mess[0]{customer}{POST: KYC data}{kyc}
+ \mess[0]{kyc}{redirect URL or pending}{customer}
+ \postlevel
+ \begin{sdblock}{alternative}{}
+ \mess[0]{customer}{GET: redirect URL}{ex}
+ \mess[0]{ex}{Thanks!}{customer}
+ \end{sdblock}
+ \prelevel
+ \prelevel
+ \prelevel
+ \prelevel
+ \prelevel
+ \begin{sdblock}{alternative}{}
+ \mess[0]{kyc}{Async validation finished Webhook}{ex}
+ \mess[0]{ex}{Thanks!}{kyc}
+ \end{sdblock}
+ \postlevel
+ \mess[0]{ex}{GET: KYC status?}{kyc}
+ \mess[0]{kyc}{KYC data}{ex}
+ \mess[0]{customer}{POST: payment request}{ex}
+ \mess[0]{ex}{normal response}{customer}
+\end{sequencediagram}
+
+\end{document}
+
+
diff --git a/libeufin/bank-manual.rst b/libeufin/bank-manual.rst
new file mode 100644
index 00000000..ab793b2b
--- /dev/null
+++ b/libeufin/bank-manual.rst
@@ -0,0 +1,307 @@
+..
+ This file is part of GNU TALER.
+ Copyright (C) 2014-2024 Taler Systems SA
+
+ TALER is free software; you can redistribute it and/or modify it under the
+ terms of the GNU Affero General Public License as published by the Free Software
+ Foundation; either version 2.1, or (at your option) any later version.
+
+ TALER is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License along with
+ TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
+
+ @author Florian Dold
+ @author Marcello Stanisci
+ @author Christian Grothoff
+
+.. target audience: operator, developer
+
+.. _libeufin-bank:
+
+Bank Setup Manual
+#################
+
+libeufin-bank implements a simple core banking system with
+account and REST APIs, including REST APIs for a Web interface
+and REST APIs to interact with GNU Taler components.
+
+In this manual, we explain how to setup a bank.
+
+.. contents:: Table of Contents
+ :local:
+
+
+Installing LibEuFin Bank
+========================
+
+The following section was tested on an *OpenJDK 17* environment.
+
+Installing the libeufin-bank binary packages on Debian
+------------------------------------------------------
+
+.. include:: ../frags/installing-debian.rst
+
+.. include:: ../frags/apt-install-libeufin-bank.rst
+
+
+Installing the libeufin-bank binary packages on Ubuntu
+------------------------------------------------------
+
+.. include:: ../frags/installing-ubuntu.rst
+
+.. include:: ../frags/apt-install-libeufin-bank.rst
+
+
+Building from source
+--------------------
+
+Bank belongs to the LibEuFin project, and can be downloaded via Git:
+
+.. code-block:: console
+
+ $ git clone git://git.taler.net/libeufin
+
+Note that Kotlin and Gradle should already work on the host system.
+
+Navigate into the *libeufin* local repository, and from top-level run:
+
+.. code-block:: console
+
+ $ ./bootstrap
+ $ ./configure --prefix=$PREFIX
+ $ make install
+
+If the previous steps succeeded, the ``libeufin-bank`` command should
+be found in the $PATH.
+
+
+Minimal Configuration for LibEuFin Bank
+=======================================
+
+The following snippet shows the mandatory configuration values:
+
+.. code-block:: ini
+
+ [libeufin-bank]
+ CURRENCY = KUDOS
+
+ # Supported payment target type
+ WIRE_TYPE = iban or x-taler-bank
+ # If WIRE_TYPE = iban
+ IBAN_PAYTO_BIC = SANDBOXX
+ # If WIRE_TYPE = x-taler-bank
+ X_TALER_BANK_PAYTO_HOSTNAME = https://bank.taler.net
+
+.. note::
+ Refer to the manpage ``libeufin-man.conf(5)``
+ for the full array of configuration values.
+
+.. _libeufin-mfa:
+
+Configuring multi-factor authentication
+---------------------------------------
+
+libeufin-bank supports two-factor authentication. libeufin-bank uses helper scripts to send challenge codes to addresses for multi-factor authentication. We provide two default helper scripts: ``libeufin-tan-email.sh`` to send e-mails and ``libeufin-tan-sms.sh`` to send SMS. To enable two-factor authentication you need to configure at least one TAN channel.
+
+SMS TAN channel
++++++++++++++++
+
+The default ``libeufin-tan-sms.sh`` script is based on the `Telesign <https://www.telesign.com>`_ SMS provider. It requires an additional ``AUTH_TOKEN`` environment variable for `Telesign Basic authentication <https://developer.telesign.com/enterprise/docs/authentication#basic-authentication>`_.
+
+To test your setup run:
+
+.. code-block:: console
+
+ $ AUTH_TOKEN=$TELESIGN_TOKEN
+ $ echo "Test 1234" | libeufin-tan-sms.sh $PHONE
+
+If you received an SMS containing "Test 1234" you can enable this channel in the config:
+
+.. code-block:: ini
+
+ [libeufin-bank]
+ TAN_SMS = libeufin-tan-sms.sh
+ TAN_SMS_ENV = "AUTH_TOKEN=$TELESIGN_TOKEN"
+
+Mail TAN channel
+++++++++++++++++
+
+The default ``libeufin-tan-email.sh`` script is based on the ``mail`` Linux command. It requires a working local mail transfer agent.
+
+To test your setup run:
+
+.. code-block:: console
+
+ $ echo "Test 1234" | libeufin-tan-email.sh $EMAIL
+
+If you received an email containing "Test 1234" you can enable this channel in the config:
+
+.. code-block:: ini
+
+ [libeufin-bank]
+ TAN_EMAIL = libeufin-tan-email.sh
+
+Custom TAN channel scripts
+++++++++++++++++++++++++++
+
+It is possible to replace these scripts with use custom scripts to send
+the e-mail or SMS TAN. Such alternative scripts must accept the phone number / e-mail address as the ``$1`` parameter and the message content to be transmitted in their standard input. They should return 0 to indicate successful transmission of the challenge and non-zero on failure.
+
+To change the scripts used for multi-factor authentication, change the following
+options in the configuration file:
+
+.. code-block:: ini
+
+ [libeufin-bank]
+ TAN_SMS = custom-tan-sms.sh
+ TAN_SMS_ENV =
+ TAN_EMAIL = custom-tan-email.sh
+ TAN_EMAIL_ENV =
+
+Launching libeufin-bank
+=======================
+
+Assuming that the configuration file exists at ``$CONFIG_FILE``, the following
+command initializes (or upgrades) the database schema:
+
+.. code-block:: console
+
+ $ libeufin-bank-dbinit -c "$CONFIG_FILE"
+
+Once this is done, you can start the libeufin-bank HTTP server:
+
+.. code-block:: console
+
+ $ libeufin-bank serve -c "$CONFIG_FILE"
+
+
+
+Using the bank Web interface
+============================
+
+To be able to use the Web interface, you must set a password for the "admin"
+account. You can set (or reset) the account password to ``$PASSWORD`` using
+the following command:
+
+.. code-block:: console
+
+ $ libeufin-bank passwd -c "$CONFIG_FILE admin "$PASSWORD"
+
+You can also use the same command to reset the passwords of other accounts by
+replacing "admin" with the respective login.
+
+
+Setting up accounts
+-------------------
+
+Using the above "$PASSWORD", log into the Web interface as "admin". To setup
+regular accounts, search for the button "Create account" near the list of all
+existing bank accounts in the Web interface of libeufin-bank.
+
+You will be asked to specify:
+
+Username
+ A unique account name the user will use to access the bank account.
+
+Name
+ Legal name of the user or business owning the account.
+
+Email
+ E-mail address of the account owner. Can be used to send a TAN message for 2-factor authentication (if enabled).
+
+Phone
+ Mobile phone number of the account owner. Can be used to send a TAN message for 2-factor authentication (if enabled).
+
+Max debt
+ Maximum amount the account is allowed to go into debt. Non-zero settings **must** be used for the "admin" account where this setting effectively creates a limit on the amount of money managed by the bank.
+
+Is this a Taler Exchange?
+ Should be disabled except if you are setting up an account for a GNU Taler exchange. If enabled, transactions that are not compatible with a GNU Taler exchange will be automatically refused by the bank.
+
+XXX Cashout channel
+ Used in a regional currency setup to specify the external account number of a bank account in fiat currency that belongs the merchant. Allows the merchant to exchange its regional currency money for wire transfers in fiat currency into this account. Optional. Not available unless the bank is configured for regional currencies.
+
+Is this account public?
+ Public accounts can be viewed without access control, their balance and transaction history becomes public.
+
+After submitting the form, a randomly created password for the new account
+will be shown in a notification. The administrator can also change passwords
+for any account in the system using the "change password" link in the account
+list. To change other details about an account, select the "Username" in the
+account list.
+
+
+Account introspection
+---------------------
+
+Users can see (and possibly change) the settings of their bank account and
+also their IBAN by clicking on the "Welcome, $USERNAME" text after logging
+into their bank account using their username and password.
+
+The IBAN field has a convenient "copy to clipboard" button next to it.
+
+
+Making transfers between accounts
+---------------------------------
+
+First, you need to know the IBAN of the account to credit, and log in as the
+user of the account to be debited. Then select "Using a form", enter the IBAN
+under "Recipient" and specify a wire transfer subject and the total amount to
+be wired. After pressing "Send", you may have to pass a 2-FA check.
+
+
+Integration with the Taler Exchange
+===================================
+
+.. note::
+
+ This step is fully automated if you use the :doc:`automated setup manual<regional-automated-manual>`.
+
+You must have an exchange account with username ``exchange`` for conversion to work.
+Assuming that the configuration file exists at ``$CONFIG_FILE``, the following
+command would create one:
+
+.. code-block:: console
+
+ $ libeufin-bank create-account '{"username":"exchange","password":"$EXCHANGE_PASSWORD","name":"Cashout Exchange","is_taler_exchange":true}' -c "$CONFIG_FILE"
+
+.. note::
+
+ You can also set up the exchange account as "admin" using the Web interface of libeufin-bank.
+
+Having done so, take note of two key pieces of information, namely the ``$EXCHANGE_PASSWORD`` and the "payto://"-URI of the exchange bank account. This information must then be used to configure the exchange as described in
+:ref:`exchange bank account configuration <exchange-account-signing>`. When using the libeufin-bank in the context
+of a regional currency with conversion, you must
+additionally specify a "conversion-url" when setting
+up the exchange account. See the section on :ref:`conversion setup <regional-conversion-setup>` in the regional currency setup chapter for details.
+
+
+Withdrawing e-cash to a Taler wallet
+====================================
+
+.. note::
+
+ This step is fully automated if you use the :doc:`automated setup manual<regional-automated-manual>`.
+
+Users can withdraw digital cash from their bank account starting from their
+online banking as implemented by the libeufin-bank. However, in this scenario,
+the Taler wallet may not already know about an exchange that works with the
+respective currency. Thus, the protocol includes the possibility of the bank
+*recommending* an exchange service to the wallet, thus providing a sane
+default for the wallet to suggest to the user. To do so, the base URL of the
+exchange API must be specified in the libeufin-bank configuration:
+
+.. code-block:: ini
+
+ [libeufin-bank]
+ DEFAULT_EXCHANGE=${PROTO}://exchange.${DOMAIN_NAME}
+
+After changing this value, the libeufin-bank service needs to be restarted
+to make the change effective.
+
+.. note::
+
+ The user may change the default exchange from within the wallet, assuming they know of an alternative exchanges for the currency.
diff --git a/libeufin/bank-transport-ebics.rst b/libeufin/bank-transport-ebics.rst
deleted file mode 100644
index 7d26cbc3..00000000
--- a/libeufin/bank-transport-ebics.rst
+++ /dev/null
@@ -1,55 +0,0 @@
-.. target audience: core developer
-
-The EBICS Bank Transport
-========================
-
-An EBICS bank transport in LibEuFin conceptually corresponds
-to the "EBICS Subscriber" in EBICS terminology.
-
-
-Bank Transport Setup
---------------------
-
-The following steps are required to set up an EBICS bank transport:
-
-1. The bank must set up the EBICS access for the user.
- The bank will notify the user of the following parameters:
-
- * the URL of the EBICS server used by the bank
- * the HostID of the bank within the EBICS server (sometimes one EBICS server hosts multiple banks)
- * the PartnerID (typically identifies the owner of the bank account within the banking system)
- * the UserID (typically identifies the person that accesses the bank account, can be different from the owner)
- * the SystemID (optional and rarely used, basically a "sub-identity" of a subscriber when multiple technical
- systems have access to the account via EBICS)
-
-2. The user enters the information from the list above in the setup dialog in the LibEuFin nexus (UI/CLI).
-
-3. The LibEuFin nexus generates cryptographic key material (3 RSA key pairs).
-
-4. The nexus sends the public keys electronically to the bank's EBICS server, together with the information
- identifying the subscriber (PartnerID, UserID, SystemID).
-
-5. The user prints a document that contains the public key and hashes for all three key pairs.
- The user then signs this document and sends it to the bank (physically/scanned).
-
-6. The bank receives the letter and verifies that the keys from the letter correspond
- to the electronically sent keys. If they match, the bank sets the state of the
- subscriber to "ready".
-
-7. The user now has to wait until the bank has set the EBICS subscriber state to "ready".
- There is no in-band notification for this, but the Nexus can try downloading the bank's
- cryptographic parameters. This will only succeed once the EBICS subscriber is set to "ready"
- by the bank.
-
-8. The user should confirm the public keys of the bank received in the previous step.
- Typically the bank gives the value of these public keys in an out-of-band channel.
-
-9. Now the user can finally use the EBICS bank transport. The first step after finishing
- the setup should be to import the bank accounts accessible for this EBICS subscriber.
-
-
-Alternative ways of setting up the EBICS bank transport are:
-
-* Importing from a backup. The backup contains metadata (EBICS URL, HostID,
- UserId, ...) and the three passphrase-protected subscriber keys.
-* Certificate-based setup (currently not supported by LibEuFin, only used in France)
diff --git a/libeufin/banking-protocols.rst b/libeufin/banking-protocols.rst
deleted file mode 100644
index 2eaffb3d..00000000
--- a/libeufin/banking-protocols.rst
+++ /dev/null
@@ -1,127 +0,0 @@
-.. target audience: core developer
-
-Banking Protocols
-#################
-
-This page collects information we have about banking protocols available around
-the world.
-
-
-Open Financial Exchange (OFX) Direct Connect
-============================================
-
-`OFX <https://www.ofx.net/>`__ is widely used in the US. It defines a completely
-custom protocol (based on HTTP) and data formats (**not** based on ISO20022) for banking.
-
-
-Electronic Banking Internet Communication Standard (EBICS)
-==========================================================
-
-EBICS is used primarily in Germany, France and Switzerland. Some banks (such as BNPParibas
-with their `Global Ebics <https://cashmanagement.bnpparibas.com/our-solutions/solution/global-ebics>`__)
-also allow EBICS access to accounts in other countries.
-
-EBICS is just a transfer layer for communicating with banks. Banks define what
-messages they support. In practice, EBICS is very often used to transfer
-ISO20022 messages.
-
-German banks that are part of the German Banking Industry Committee all must offer EBICS access.
-Thus this protocol is a good choice for the German market.
-
-
-FinTS / HBCI
-============
-
-German home-banking standard. FinTS is the successor of the Home Banking
-Computer Interface (HBCI), but older versions of FinTS are often still called
-HBCI.
-
-The current version, FinTS 4.0, is not widely supported by banks yet. Starting with FinTS,
-XML is used as a data format. Previous versions used a custom text/binary format.
-
-Only some banks allow authentication based on key pairs.
-Due to different interpretation of PSD2, other banks now only allow authentication
-methods that require interaction from the customer (SCA / Strong Customer Authentication).
-
-Payloads these days can be ISO20022 messages.
-
-Examples:
- * `GLS <https://www.gls.de/geschaefts-firmenkunden/zahlungsverkehr/onlinebankingverfahren-und-programme/daten-zum-onlinebanking/>`__
-
-
-PSD2
-====
-
-PSD2 is not a technical standard, but high-level legal requirements on (amongst other things) APIs
-that banks have to offer.
-
-There are many implementations of PSD2 APIs. The `Berlin Group <https://www.berlin-group.org/>`__
-provides a framework that somewhat standardizes technical details, but the use of this standard
-is by no means necessary.
-
-Unfortunately, it focuses on *other* parties accessing *your* bank account. It
-does not give customers access to their own bank account. Customers can manage
-third party access they give to their bank account in their online banking
-system. That mechanism is conceptually similar to OAuth2. In fact, some
-implementations of PSD2 even use OAuth2 directly.
-
-PSD2 APIs usually use JSON as a data format. Often the schema and terminology is "inspired" by ISO20022
-messages, but no actual ISO20022 XML message formats are used.
-
-PSD2 requires two main services to be available via an API:
-
-* AIS (Account Information Service).
-* PIS (Payment Initiation Service).
-
-Together, they're often called XS2A ("access to account").
-
-An entity that wants to use AIS has to be registered with the financial
-oversight authority in its country (BAFIN in Germany). PIS has even stronger
-legal prerequisites.
-
-On a technical level, using PSD2 APIs usually requires having an `EIDAS <https://en.wikipedia.org/wiki/EIDAS>`__ certificate.
-
-Examples (bank offerings):
- * `Sparkasse <https://xs2a.sparkassen-hub.com/home>`__ (Berlin Group based)
- * `Deutsche Bank <https://developer.db.com/products/psd2>`__
-
-Examples (standards):
- * `STET PSD2 API <https://www.stet.eu/en/psd2/>`__
- * `Berlin Group NextGenPSD2 <https://www.berlin-group.org/nextgenpsd2-downloads>`__
-
-
-
-Bank-Proprietary APIs
-=====================
-
-Some banks offer completely custom APIs to access services of the bank. These often include services
-not available via more standardized APIs, such as account creation.
-
-Often banks frame PSD2 as just another API available in their portfolio of API offerings.
-
-Examples:
-
-* `Deutsche Bank <https://developer.db.com/products>`__
-* `ING Group <https://developer.ing.com/api-marketplace/marketplace>`__
-* `Revolut <https://revolut-engineering.github.io/api-docs/business-api/>`__
-* `PayPal <https://developer.paypal.com/classic-home/>`__
-
-
-Open Bank Project
-=================
-
-The `Open Bank Project <https://www.openbankproject.com/>`__ provides a free software implementation of
-banking middleware that supports various APIs, including PSD2-compatible APIs (based on Berlin Group).
-
-API Docs: `<https://github.com/OpenBankProject/OBP-API/wiki/Open-Bank-Project-Architecture>`__
-
-
-UK Open Banking
-===============
-
-Open Banking is the (quite confusing!) name of a UK-based open banking initiative.
-
-What's nice about Open Banking is that their APIs are really close to ISO 20022, unlike many
-similar HTTP+JSON APIs.
-
-`<https://openbanking.atlassian.net/wiki/spaces/DZ/pages/16385802/Specifications>`__
diff --git a/libeufin/circuit-cli-commands.rst b/libeufin/circuit-cli-commands.rst
deleted file mode 100644
index 611922ee..00000000
--- a/libeufin/circuit-cli-commands.rst
+++ /dev/null
@@ -1,152 +0,0 @@
-CLI commands for the circuit API
-################################
-
-The following list shows all the CLI subcommands
-acting as the Circuit API's client side. Each section
-name is one subcommand available in this pattern:
-``libeufin-cli sandbox demobank $subcommand``.
-
-Finally, each section name links to the related API
-documentation of the endpoint being addressed.
-
-circuit-account-info
-^^^^^^^^^^^^^^^^^^^^
-
-Retrieve Circuit information about one account. Useful to get cash-out
-address and contact details.
-
-Options:
- --username TEXT Username of the account to retrieve. It defaults to
- LIBEUFIN_SANDBOX_USERNAME and doesn't accept 'admin'.
- --help Show this message and exit.
-
-circuit-accounts
-^^^^^^^^^^^^^^^^
-
- Gets the list of all the accounts managed by the Circuit. Only 'admin'
- allowed
-
-Options:
- --help Show this message and exit.
-
-circuit-cashout
-^^^^^^^^^^^^^^^
-
-Create a cash-out operation. If successful, the user gets a TAN.
-
-Options:
- --subject TEXT Payment subject to associate to the outgoing and
- incoming payments that are associated with this cash-
- out operation.
- --amount-debit TEXT Amount that will debited to the local currency
- account, in the <currency>:X.Y format. [required]
- --amount-credit TEXT Amount that will credited to the fiat currency
- account, in the <currency>:X.Y format. [required]
- --tan-channel TEXT Indicates how to send the TAN to the user: 'sms',
- 'email' and 'file' are valid values. If missing, the
- bank defaults to SMS. 'file' makes the server write
- the TAN to /tmp/libeufin-cashout-tan.txt, normally
- used for testing.
- --help Show this message and exit.
-
-
-circuit-cashout-abort
-^^^^^^^^^^^^^^^^^^^^^
-
-Abort a cash-out operation. Admin and author are allowed to request.
-
-Options:
- --uuid TEXT UUID of the cash-out operation to abort. [required]
- --help Show this message and exit.
-
-
-circuit-cashout-confirm
-^^^^^^^^^^^^^^^^^^^^^^^
-
-Confirm a cash-out operation. Only the author is allowed (no admin).
-
-Options:
- --tan TEXT TAN that authorizes the cash-out operaion. [required]
- --uuid TEXT UUID of the cash-out operation to confirm. [required]
- --help Show this message and exit.
-
-
-circuit-cashout-details
-^^^^^^^^^^^^^^^^^^^^^^^
-
-Retrieve status information about one cash-out operation. Admin and author
-are allowed to request.
-
-Options:
- --uuid TEXT UUID of the cash-out operation to retrieve. [required]
- --help Show this message and exit.
-
-
-circuit-cashouts
-^^^^^^^^^^^^^^^^
-
-Gets the list of all the pending and confirmed cash-out operations.
-
-Options:
- --help Show this message and exit.
-
-
-circuit-delete-account
-^^^^^^^^^^^^^^^^^^^^^^
-
-Delete one account. Only available to the administrator and for accounts
-with zero balance.
-
-Options:
- --username TEXT account to delete [required]
- --help Show this message and exit.
-
-
-circuit-password-reconfig
-^^^^^^^^^^^^^^^^^^^^^^^^^
-
-Ask interactively to change the password. It needs administrator or owner
-credentials
-
-Options:
- --username TEXT Username whose password will change. Defaults to
- LIBEUFIN_SANDBOX_USERNAME and doesn't accept 'admin' as a
- value.
- --help Show this message and exit.
-
-
-circuit-reconfig
-^^^^^^^^^^^^^^^^
-
-Reconfigure an account with cash-out capabilities. It needs administrator
-or owner credentials
-
-Options:
- --phone TEXT Phone number for the SMS TAN
- --email TEXT E-mail address for receiving the TAN
- --cashout-address TEXT Payto address where to send fiat payments on cash-
- outs [required]
- --username TEXT Username associated with the account to reconfigure.
- It defaults to LIBEUFIN_SANDBOX_USERNAME and doesn't
- accept 'admin'.
- --help Show this message and exit.
-
-
-circuit-register
-^^^^^^^^^^^^^^^^
-
-Register a new account with cash-out capabilities. It needs administrator
-credentials, and the new account password exported in
-LIBEUFIN_NEW_CIRCUIT_ACCOUNT_PASSWORD.
-
-Options:
- --username TEXT new account username [required]
- --cashout-address TEXT Payto address where to send fiat payments on cash-
- outs [required]
- --name TEXT Legal name associated to the account. [required]
- --phone TEXT SMS where to send the cash-out TAN.
- --email TEXT E-mail address where to send the cash-out TAN.
- --internal-iban TEXT Which IBAN to associate to this account. The IBAN
- participates only in the local currency circuit. If
- missing, the bank generates one.
- --help Show this message and exit.
diff --git a/libeufin/concepts.rst b/libeufin/concepts.rst
deleted file mode 100644
index 6a251991..00000000
--- a/libeufin/concepts.rst
+++ /dev/null
@@ -1,166 +0,0 @@
-.. target audience: operator, developer
-
-###################
-Conceptual Overview
-###################
-
-
-What is LibEuFin
-================
-
-The goal of LibEuFin is to make the development and testing of
-FinTech applications easier. It hides implementation details
-of complex legacy banking APIs behind a simple interface.
-
-LibEuFin Nexus and Sandbox
---------------------------
-
-LibEuFin has two main components:
-
-1. The LibEuFin nexus receives banking-related requests in a LibEuFin-specific
- format via an HTTP API. It then translates those requests into interactions
- with other banking APIs, abstracting away different underlying protocols and
- hiding the complexity of the legacy protocols used by some banks.
-
-2. The LibEuFin sandbox implements the server side of protocols
- that banks speak. It also emulates a *very*, *very* simple
- core banking system to manage accounts and their balance.
- The main use case for the sandbox is testing LibEuFin itself,
- as well as applications developed with LibEuFin.
- The sandbox has a JSON API to set it up for tests (creating bank
- hosts, bank accounts, fake transactions).
-
-
-High-Level Concepts
-===================
-
-Nexus Users
------------
-
-The concept of a *nexus user* is used to implement access control to the
-operations that the nexus provides.
-
-A user has a login name and a (salted, hashed) password.
-This is the `HTTP basic auth <https://tools.ietf.org/html/rfc7617>`_ method.
-(Other authentication methods could be added in the future.)
-
-A nexus user can be marked as *superuser*. All permission checks are skipped
-for superusers. Only superusers are allowed to create/modify other users.
-
-Bank Accounts
--------------
-
-A *bank account* is the local representation of some bank account.
-The information stored about it includes:
-
-* Local alias ("nickname") of the bank account
-* Account identification (IBAN / BIC / account holder)
-* A local mirror of the bank transaction history
-* Payment requests, i.e. payments that have been locally requested, together
- with their state (sent or not sent, acknowledged in bank statement or not)
-* Error reports (e.g. failed payment requests, bank statement items that were not understood
- by LibEuFin)
-* A default bank connection (if configured) that is used by default
- for operations on the account
-* Other enabled "bank connections" (see definition below)
-
-Examples:
-
-.. code-block:: console
-
- # Download latest transactions via the default bank connection and store them locally
- $ http -a $USER:$PASSWORD POST \
- https://example1.libeufin.tech/bank-accounts/my-acct/fetch-transactions
-
-Bank Connections
-----------------
-
-Bank connections connect the local LibEuFin bank account to the real bank.
-The *bank connection* includes the following data:
-
-* Local alias ("nickname") of the bank connection
-* The type of connection, i.e. the protocol used (EBICS, FinTS, loopback, sandbox)
-* Protocol configuration (hostname, port, protocol sub-version/flags)
-* Credentials to use the connection (e.g. password, EBICS subscriber keys)
-
-Bank connections provide the following actions:
-
-* Initial setup of the connection
-
-* Execute protocol-specific actions (e.g. EBICS: C53, C52, CCT, CRZ)
-
- * These actions do not have any effect on the LibEuFin local bank account.
- To persist changes to the local bank account (transaction history, payment request status),
- the bank connection must be invoked via the bank account.
-
-* Import bank accounts
-
- * Some bank connection protocols allow LibEuFin to query a list of bank
- accounts that the connection has access to. This makes setup easier,
- as the user doesn't have to create the local bank account manually.
-
-Examples:
-
-.. code-block:: console
-
- # Manually request the inter-day account report via the EBICS C52 order
- $ http -a $USER:$PASSWORD POST \
- https://example1.libeufin.tech/bank-connections/my-ebics-testacct/ebics/download/C52
-
- # Download available bank accounts that can be accessed through this connection,
- # according to the bank server (with EBICS, does a HTD request).
- # For each of them, create a bank account resource in LibEuFin.
- $ http -a $USER:$PASSWORD POST \
- https://example1.libeufin.tech/bank-connection/my-ebics-testacct/fetch-accounts
-
-Facades
--------
-
-Facades allow extra domain-specific functionality to be implemented on top of users, bank accounts
-and bank connections. A *facade* stores the following information:
-
-* Local name of the facade
-* Facade type and options specific to the type
-* Associated bank accounts and bank connections that can be accessed by the facade
-* Internal tables used by the facade (i.e. facades are stateful)
-
-The only facade currently supported by LibEuFin is the "Taler Wire Gateway API" layer.
-It provides a filtered view on the transaction history, a more restricted API to create payment
-requests, and a mechanism to create a counter-transaction for incoming transactions that do
-not conform to a certain format.
-
-Examples:
-
-.. code-block:: console
-
- # Request the Taler-specific history through the facade
- $ http -a $USER:$PASSWORD \
- https://example1.libeufin.tech/facades/my-taler-wire-gw/taler/history/incoming
-
-Access Control
-==============
-
-The goal of *access control* in LibEuFin is to allow the following scenarios:
-
-* The Nexus can be used by multiple clients for different bank accounts/connections
- and these users can't access each other's bank accounts
-* For monitoring / dashboard (e.g. Taler rejected transactions, blacklists),
- some users should only be able to have read-only access.
-
-It is currently not planned to have more fine-grained permissions, such as
-spending limits or more fine-grained read/write permissions.
-
-Users can be normal users or superusers. Permission checks do not apply to superusers,
-and only superusers can create other users.
-
-Each top-level object (bank account, bank connection, facade) has a list of
-nexus users with write access, and a list of users with read access.
-
-When using a bank connection through a bank account, permission checks must
-succeed for both the bank account and the bank connection.
-
-This works differently for facades: A facade has a set of associated bank connections
-and bank accounts it can access. Permissions on these associated objects
-are checked when the facade is *created*. When invoking operations on the facade,
-the nexus only checks if the current nexus user can access the facade and *not* the
-underlying objects abstracted by the facade.
diff --git a/libeufin/ebics.rst b/libeufin/ebics.rst
deleted file mode 100644
index 7c1fa2ae..00000000
--- a/libeufin/ebics.rst
+++ /dev/null
@@ -1,598 +0,0 @@
-.. target audience: core developer
-
-EBICS Implementation Notes
-##########################
-
-.. warning::
-
- This document summarizes and clarifies some aspects of the EBICS protocol
- that are important to LibEuFin. Both version 3.0 and 2.5 are discussed here.
-
- It is not a specification, and it does not replace the official EBICS specification.
-
-.. contents:: Table of Contents
-
-EBICS Glossary
-==============
-
-.. glossary::
- :sorted:
-
- A004
- Electronic signature process, used in :term:`H004`, deprecated in :term:`H005` with EBICS 3.0.
-
- A005
- Electronic signature process. Used in :term:`H004` and :term:`H005`.
-
- A006
- Electronic signature process. Used in :term:`H004` and :term:`H005`.
-
- BTF
- *Business Transaction Formats.* Before EBICS 3.0, many different order types were
- used for business-related messages. With EBICS 3.0, the more generic BTU and BTD
- order types are used for all business-related messages.
-
- EBICS
- The *Electronic Banking Internet Communication Standard*.
-
- ES
- Electronic Signature. This abbreviation is commonly used in the context of EBICS.
-
- The following signature classes are defined (in descending order from
- strongest to weakest):
-
- E
- Single signature (German "Einzeln").
- A
- First signature.
- B
- Second signature.
- T
- Transport signature. Only used to verify authorized submission,
- but not to verify the bank-technical authorization.
-
- In H004 and H005, the ES of the bank is specified as a "planned feature" that
- is not actually implemented yet. Thus banks in practice only use their
- encryption key pair and authentication/identity key pair.
-
- EDS
- Distributed Electronic Signature. Allows multiple subscribers to authorize an existing order.
-
- FTAM
- Historical predecessor protocol to EBICS (*file transfer, access and management*).
-
- HEV
- The *Host EBICS Version*. Queried by the client with an HEV request message.
-
- Human Subscriber
-
- See :term:`Subscriber`.
-
- H004
- Host protocol version 4. Refers to the XML Schema defined in *EBICS 2.5*.
-
- H005
- Host protocol version 5. Refers to the XML Schema defined in *EBICS 3.0*.
-
- Host ID
- Alphanumeric identifier for the EBICS Host. One EBICS server can
- host multiple banks, and each bank is identified by the Host ID.
- This concept is similar to Taler's merchant backend instance identifiers.
-
- Order Number
- Interchangeably called "Order ID".
-
- Each upload transaction gets a unique order number assigned by the bank server.
- The Order Number is used to match VEUs in a second upload to the original order.
- An Order Number matches the format ``[A-Z][A-Z0-9]{3}`` (and is not really a number!).
-
- Must be unique per customer ID and per order type.
-
- Transaction ID
- A transaction ID is a 128-bit cryptographically strong random number.
- It is assigned by the bank server for every transaction, i.e. upload or download
- of an order.
-
- The transaction ID must not be guessable, as it would allow a potential
- attacker to upload segments of an upload that do not match the whole message's digest.
-
- Transaction key
- Symmetric encryption key for the data uploaded/downloaded in a transaction.
-
- Partner ID
- In German, this is called "Kunden ID" (= Customer ID).
- One partner can have multiple "participants", which are identified by user IDs.
-
- Practical example: A company has one Partner ID. Each person at the company
- that can access the company's bank accounts gets their own User ID.
- When the person is indirectly accessing the bank server (for example via
- a client server application), an additional "System ID" is created for this
- "technical subscriber". When there is no technical subscriber, the System ID
- must be the same as the User ID. Usually the System ID is optional though.
-
- The ``(partner, user, system)`` triple uniquely identifies a subscriber.
-
- User ID
- See :term:`Partner ID`.
-
- System ID
- See :term:`Partner ID`.
-
- ISO 20022
- *ISO 20022: Financial Services - Universal financial industry message scheme*. Rather important
- standard for financial industry **business-related** messages. In contrast, EBICS takes
- care of message transmission, segmentation, authentication, key management, etc.
-
- The full catalogue of messages is `available gratis <https://www.iso20022.org/full_catalogue.page>`_.
-
- UNIFI
- UNIversal Financial Industry message scheme. Sometimes used to refer to
- :term:`ISO 20022`.
-
- Segmentation
- EBICS implements its own protocol-level segmentation of business-related messages.
- The segmentation can be seen as an alternative to the HTTP facilities of ``Accept-Ranges``.
-
- The order data of an EBICS message may not exceed 1 MB. The segmentation applies both
- to requests and responses.
-
- Subscriber
- Entity that wishes to communicate with the financial institution via EBICS.
-
- Subscribers can be *technical* or *human*. Technical subscribers are typically
- a server in client-server applications, where the server talks to a financial institution
- via EBICS.
-
- Requests from technical subscribers have a ``SystemID`` in addition to a ``PartnerID``
- and ``UserId``. A technical subscriber cannot sign a bank-technical request.
-
- Technical Subscriber
- See :term:`Subscriber`.
-
- TLS
- *Transport Layer Security*. All messages in EBICS are sent over HTTP with TLS.
- In the current version of the standard, only server certificates are required.
-
- VEU
- Distributed Electronic Signature (from German "Verteilte Elektronische Unterschrift").
-
- V001
- FTAM encryption algorithm ("Verschlüsselung"), superseded in EBICS by E002.
-
- E002
- EBICS encryption process, used to encrypt the order payload.
-
- X002
- Identification and authentication signature in H004 and H005.
-
-
-Order Types
-===========
-
-By convention, order types beginning with "H" are administrative order types, and other ones are
-bank-technical order types. This convention isn't always followed consistently by EBICS.
-
-Relevant Order Types
---------------------
-
-.. ebics:orders::
- :sorted:
-
- BTD
- **Only EBICS3.0+**. Business Transaction Format Download.
- Administrative order type to download a file, described in more detail by the BTF structure.
-
- BTU
- **Only EBICS3.0+**. Business Transaction Format Upload.
- Administrative order type to upload a file, described in more detail by the BTF structure.
-
- C52
- **Before EBICS 3.0**. Download bank-to-customer account report (intra-day information).
-
- C53
- **Before EBICS 3.0**. Download bank-to-customer statement report (prior day bank statement).
-
- CRZ
- Type: Download.
-
- Fetch payment status report (pain.002).
-
- CCC
- Type: Upload.
-
- Send SEPA Credit Transfer Initiation (pain.001) via XML container.
- This is the DFÜ variant (Appendix 3 DFÜ-Agreement).
-
- CCT
- Type: Upload.
-
- Send SEPA Credit Transfer Initiation (pain.001) directly.
- This is the DFÜ variant (Appendix 3 DFÜ-Agreement).
-
- CIZ
- Type: Download.
-
- Payment Status Report for Credit Transfer Instant.
-
- FUL
- **Before EBICS 3.0, France**. File Upload. Mainly used by France-style EBICS.
-
- FDL
- **Before EBICS 3.0, France**. File Download. Mainly used by France-style EBICS.
-
- HAA
- Type: Download, Optional.
-
- Download order types for which there is new data available.
-
- HTD
- Type: Download.
-
- Download information about a subscriber. From German "Teilnehmerdaten".
-
- HKD
- Type: Download, Optional.
-
- Download information about a customer (=partner). From German "Kundendaten".
-
- HIA
- Transmission of the subscriber keys for (1) identification and authentication and (2)
- encryption within the framework of subscriber initialisation.
-
- HPB
- Query the three RSA keys of the financial institute.
-
- HPD
- Host Parameter Data. Used to query the capabilities of the financial institution.
-
- INI
- Transmission of the subscriber keys for bank-technical electronic signatures.
-
- HAC
- Customer acknowledgement. Allows downloading a detailed "log" of the activities
- done via EBICS, in the pain.002 XML format.
-
- HCS
- Change keys without having to send a new INI/HIA letter.
-
- SPR
- From German "sperren". Suspend a subscriber. Used when a key compromise is
- suspected.
-
- HCS
- Change the subscribers keys (``K_SIG``, ``K_IA`` and ``K_ENC``).
-
-Other Order Types
------------------
-
-The following order types are, for now, not relevant for LibEuFin:
-
-
-.. ebics:orders::
- :sorted:
-
- AZV
- Type: Upload.
-
- From German "Auslandszahlungsverkehr". Used to submit
- cross-border payments in a legacy format.
-
- CDZ
- Type: Download.
-
- Download payment status report for direct debit.
-
- CCU
- Type: Upload.
-
- German "Eilüberweisung".
-
- H3K
- Type: Upload.
-
- Send all three RSA key pairs for initialization at once, accompanied
- by a CA certificate for the keys. This is (as far as we know) used in France,
- but not used by any German banks. When initializing a subscriber with H3K,
- no INI and HIA letters are required.
-
- HVE
- Type: Upload.
-
- Host Verification of Electronic Signature. Used to submit an electronic signature separately
- from a previously uploaded order.
-
- HVD
- Type: Download.
-
- Retrieve VEU state.
-
- HVU
- Type: Download.
-
- Retrieve VEU overview.
-
- HVU
- Type: Download.
-
- Retrieve VEU extra information. From German "Zusatzinformationen".
-
- HVS
- Type: Upload.
-
- Cancel Previous Order (from German "Storno"). Used to submit an electronic signature separately
- from a previously uploaded order.
-
- HSA
- Type: Optional
-
- Order to migrate from FTAM to EBICS. **Removed in EBICS 3.0**.
-
- PUB
- Type: Upload.
-
- Change of the bank-technical key (``K_SIG``).
- Superseded by HSA.
-
- HCA
- Type: Upload.
-
- Change the identification and authentication key as well as the encryption key (``K_IA`` and ``K_ENC``).
- Superseded by HCS.
-
- PTK
- Type: Download.
-
- Download a human-readable protocol of operations done via EBICS.
- Mandatory for German banks. Superseded by the machine-readable
- HAC order type.
-
-
-EBICS Message Format
-====================
-
-The following elements are the allowed root elements of EBICS request/response messages:
-
-* ``ebicsHEVRequest`` / ``ebicsHEVResponse``: Always unauthenticated and unencrypted. Used
- **only** for query/response of the host's EBICS version.
-* ``ebicsUnsecuredRequest``: Request without signature or encryption (beyond TLS). Used for INI and HIA.
-* ``ebicsKeyManagementResponse``: Unauthenticated response. Used for key management responses and
- sometimes **also** to deliver error messages that are not signed by the bank (such as "invalid request").
-* ``ebicsNoPubKeyDigestsRequest``: Signed request that *does not* contain the hash of the bank's
- public key that the client expects. Used for key management, specifically only the HPB order type.
-* ``ebicsRequest`` / ``ebicsResponse``
-* ``ebicsUnsignedRequest``: Not used anymore. Was used in FTAM migration with the HSA order type.
-
-
-Order ID Allocation
-===================
-
-In practice, the Order ID seems to be allocated via number of counters at the level of the **PartnerID**.
-
-
-EBICS Transaction
-=================
-
-A transaction in EBICS simply refers to the process of uploading or downloading
-a file. Whether it is an upload or download transaction depends on the order
-type. Each transaction is either an upload transaction or a download
-transaction, neither both.
-
-Uploads and downloads must proceed in segments of at most ``1 MB``. The
-segmentation happens after (1) encryption, (2) zipping, and (3) base64-encoding
-of the order data.
-
-The number of segments is always fixed starting from the first message sent
-(for uploads) or received (for downloads) by the subscriber. The digest of the
-whole message is also sent/received with the first message of a transaction.
-The EBICS host generates a 128-bit transaction ID. This ID is used to
-correlate uploads/downloads of segments for the same transaction.
-
-If an attacker would be able to guess the transaction ID, they could upload a
-bogus segment. This would only be detected after the whole file has been
-transmitted.
-
-An upload transaction is finished when the subscriber has sent the last
-segment. A download transaction is only finished when the subscriber has sent
-an additional acknowledgement message to the EBICS host.
-
-When upload/download of a segment fails, the client can always re-try. There
-are some conditions for that:
-
-* Segment ``n`` can only be downloaded/uploaded when segments ``[0..n-1]`` have
- been downloaded/uploaded.
-* The (implementation-defined) retry limit may not be exceeded.
-
-
-Formats
-=======
-
-ISO 20022
----------
-
-`ISO 20022 <https://www.iso20022.org/>`_
-is XML-based and defines the message format for many finance-related activities.
-
-ISO 20022 messages are identified by a message identifier in the following format:
-
- <business area> . <message identifier> . <variant> . <version>
-
-Some financial instututions (such as the Deutsche Kreditwirtschaft) have decided to use
-a subset of elements/attributes in a message, this is what the ``<variant>`` part is for.
-"Standard" ISO20022 have variant ``001``.
-
-The most important message types for LibEuFin are:
-
-camt - Cash Management
- Particularly camt.053 (BankToCustomerStatement)
-
-pain - Payment Initiation
- Particularly pain.001 (CustomerCreditTransferInitiation) to initiate a payment and
- pain.002 (CustomerPaymentStatus) to get the status of a payment.
-
-
-SWIFT Proprietary
-=================
-
-SWIFT Proprietary messages are in a custom textual format.
-The relevant messages are MT940 and MT942.
-
-* MT940 contains *pre-advice*, in the sense that transactions in it might still
- change or be reversed.
-* MT942 contains the settled transactions by the end of the day.
-
-SWIFT will eventually transition from MT messages to ISO20022,
-but some banks might still only give us account statements in the old
-SWIFT format.
-
-
-
-Key Management
-==============
-
-RSA key pairs are used for three purposes:
-
-1. Authorization of requests by signing the order data. Called the *bank-technical key pair*,
- abbreviated here as ``K_SIG``.
-2. Identification/authentication of the subscriber. Called the *identification and authentication key pair*,
- abbreviated here as ``K_IA``.
-3. Decryption of the symmetric key used to decrypt the bank's response. Called the *encryption key pair*,
- abbreviated here as ``K_ENC``.
-
-One subscriber *may* use three different key pairs for these purposes.
-The identification and authentication key pair may be the same as the encryption key pair.
-The bank-technical key pair may not be used for any other purpose.
-
-
-Real-time Transactions
-======================
-
-Real-time transactions will be supported with EBICS starting November 2019.
-That's the earliest date, some banks may offer it later or not at all.
-
-For us, :ebics:order:`CIZ` is the relevant order type that we need to ask banks
-for.
-
-
-Payment Reversal
-================
-
-It looks like there is no way to "reject" payments, unless you are the bank.
-
-There is a concept of payment reversal (with ``pain.007`` for direct debit and ``camt.055`` for SEPA Credit Transfer),
-but they are a way for the *payer / sender* to reverse a payment before it is finalized.
-
-
-Bank Support
-============
-
-All German banks that are part of the Deutsche Kreditwirtschaft *must* support EBICS.
-
-The exact subset of EBICS order types must be agreed on contractually by the bank and customer.
-The following subsections list the message types that we know are supported by particular banks.
-
-GLS Bank
---------
-
-According to publicly available `forms
-<https://www.gls-laden.de/media/pdf/f1/c6/f2/nderungsauftrag.pdf>`_, GLS Bank
-supports the following order types:
-
-* :ebics:order:`AZV`
-* :ebics:order:`PTK`
-* :ebics:order:`CDZ`
-* :ebics:order:`CRZ`
-* :ebics:order:`CCC`
-* :ebics:order:`CCT`
-* :ebics:order:`CCU`
-* :ebics:order:`HVE`
-* :ebics:order:`HVS`
-* ... and mandatory administrative messages
-
-Sparkasse München
------------------
-
-See `this document <https://www.sskm.de/content/dam/myif/ssk-muenchen/work/dokumente/pdf/allgemein/ebics-default-geschaeftsvorfaelle.pdf>`__.
-
-
-HypoVereinsbank
----------------
-
-See `this document <https://www.hypovereinsbank.de/content/dam/hypovereinsbank/shared/pdf/Auftragsarten_Internet_Nov2018_181118.pdf>`__.
-
-
-Cryptography
-============
-
-EBICS uses the XML Signature standard for signatures. It does *not* use XML encryption.
-
-The EBICS specification doesn't directly reference the standardized URIs for the various
-signing algorithms. Some of these URIs are defined
-in `RFC 6931 <https://tools.ietf.org/html/rfc6931>`__.
-
-* A005 is `<http://www.w3.org/2001/04/xmldsig-more#rsa-sha256>`__.
-
- * The ``RSASSA-PKCS1-v1_5`` signature scheme contains the ``EMSA-PKCS1-v1_5`` encoding scheme
- mentioned in the EBICS spec.
-
-* A006 is `<http://www.w3.org/2007/05/xmldsig-more#rsa-pss>`__ as defined in RFC 6931.
-
-XML Signatures
---------------
-
-XML Signatures can be a combination of:
-
-* detached (referencing another document)
-* enveloping (signs over ``Object`` tags *within* the ``Signature`` elements)
-* enveloped (signs over arbitrary data (via XPath expression) in other parts of the document
- that contains the signature).
-
-In EBICS, only **enveloped** signatures are used.
-
-In the XML Signature standard, the element for a signature is ``Signature``. EBICS violates this
-standard by always mandating ``AuthSignature`` as the name. ``AuthSignature`` is an alias to
-the ``SignatureType`` XSD type in the XML Schema.
-
-Canonicalization vs transforms:
- * Canonicalization refers to the processing of the ``SignedInfo`` element.
- * Transformations apply to the data that ``Reference`` elements reference. Canonicalization
- algorithms can be used as a transformation on referenced data.
-
-Standards and Resources
-=======================
-
-EBICS
------
-
-The EBICS standard documents are available at `<http://www.ebics.org>`_.
-
-EBICS 3.0:
-
-* The main EBICS 3.0 specification
- (``2017-03-29-EBICS_V_3.0-FinalVersion.pdf``).
-* Annex 1 specifies EBICS return codes, as EBICS doesn't use HTTP status codes directly
- (``2017-03-29-EBICS_V_3.0_Annex1_ReturnCodes-FinalVersion.pdf``) .
-* Annex BTF contains the registry of BTF codes.
-
-DFÜ Agreement
--------------
-
-The DFÜ Agreement is the set of standards used by the German Banking Industry Committee (Deutsche Kreditwirtschaft).
-
-The following Annexes (also see the `DK Website <https://die-dk.de/zahlungsverkehr/electronic-banking/dfu-verfahren-ebics/>`_) are
-relevant for implementing EBICS:
-
-* Annex 1 is the EBICS specification
-* (Annex 2 is deprecated)
-* Annex 3 describes the data formats used by German banks within EBICS.
-
-EBICS Compendium
-----------------
-
-The `EBICS Compendium <https://www.ppi.de/en/payments/ebics/ebics-compendium/>`_ has some additional info on EBICS.
-It is published by a company that sells a proprietary EBICS server implementation.
-
-Others
-------
-
-* `<https://wiki.windata.de/index.php?title=EBICS-Auftragsarten>`_
-* `<https://www.gls-laden.de/media/pdf/f1/c6/f2/nderungsauftrag.pdf>`_
diff --git a/libeufin/ebics3-test-tutorial.rst b/libeufin/ebics3-test-tutorial.rst
deleted file mode 100644
index fba32a5b..00000000
--- a/libeufin/ebics3-test-tutorial.rst
+++ /dev/null
@@ -1,217 +0,0 @@
-EBICS 3.0 with PostFinance
-##########################
-
-This tutorial shows how LibEuFin and the PostFinance test platform
-communicate via EBICS 3. LibEuFin acts as the client via the Nexus
-component. To hide the configuration details to the user, all the
-client activity is handled by a Docker image.
-
-The main EBICS 3 operations that the client is expected to complete
-are the following:
-
-* Key exchange: the customer sends their keys to the bank, and then downloads the bank keys.
-* Uploading a payment instruction: the customer sends a payment to another fictional IBAN.
-* Downloading banking records: the customer downloads the banking records that confirm the previous outgoing payment.
-
-Setting up the test platform at PostFinance
--------------------------------------------
-
-Because the test is based on the PostFinance test platform, the first
-requirement is to create one account `there <https://isotest.postfinance.ch>`_.
-It is advised to set the language as English, as this tutorial is meant
-for the international audience.
-
-Set the language in the drop-down menu and navigate to the registration
-section as it is shown below:
-
-.. image:: set-english-and-register.png
-
-Even if the above page doesn't welcome you in English, the two boxes in the
-screenshot will still hold their position, so please look for box #1 to
-set the language and for box #2 to get the page that offers to register.
-
-After a successful registration, an IBAN needs to be associated with
-the user just created. Likely after the first login, the following
-page should appear. Click then on box #2.
-
-.. note::
-
- The navigation bar in the screenshot below is ubiquitous,
- so click on box #1 if the depicted page did not show up automatically.
-
-.. image:: no-accounts.png
-
-If the following page appears, please obtain a checksum-valid but fictitious
-Swiss IBAN and enter it as indicated by box #1 and then save it (box #2).
-
-.. _my-iban:
-
-.. image:: set-IBAN.png
-
-If the bank responds with a successful message, the next step is to enable
-EBICS 3 and set the format of the ISO20022 documents.
-
-.. note::
-
- There is no "use EBICS 3" setting since EBICS 3 is a "side effect"
- of choosing one particular ISO format for banking records.
-
-To use EBICS 3, click the navigation bar item highlighted in the
-following screenshot.
-
-.. image:: set-ISO-2019-0.png
-
-The following page should appear, where the ISO format can be specified
-as it is depicted in the following screenshot.
-
-.. image:: set-ISO-2019-1.png
-
-After having saved the setting, proceed now to set the flavor
-of payment confirmations. This setting instructs the bank to define
-particular XML nodes when it releases the payment confirmations. Even
-if each document is ISO20022, this step is essential because ISO20022
-has many optional fields and client and bank must agree on which fields
-appear in the documents.
-
-Hover on box #1 and then click on box #2.
-
-.. image:: camt.054-style-0.png
-
-If the following page appears, please set everything as it is shown below:
-
-.. FIXME: now trying by NOT selecting the incoming confirmation.
- Change it here if that works (screenshot taken already)!
-
-.. image:: camt.054-style-1.png
-
-.. _get-ebics-ids:
-
-The last step is to retrieve the user's EBICS identifiers, namely the
-EBICS user and partner IDs. Hover on box #1 and then click on box #2.
-
-.. image:: get-EBICS-IDs-0.png
-
-At the first access, the following page should appear. Simply create
-EBICS access and continue to the next step.
-
-.. image:: enable-EBICS.png
-
-After having obtained the following page, finally the EBICS identifiers
-are shown in box #1. The test runner needs them. **Note**: the terms
-'customer' and 'partner' are used as **synonyms** in this tutorial (and
-in the EBICS specifications too).
-
-.. image:: get-EBICS-IDs-1.png
-
-Interestingly, box #2 contains the bank keys fingerprints. These are
-important to check that the client, along the keying process, has obtained
-the right bank keys. The test runner will pause the execution to let
-the user check them.
-
-Setting up the local Docker and run the test
---------------------------------------------
-
-This section shows how to run the test and explains how to interact
-with the test runner.
-
-Clone the following repository:
-
-.. code-block:: shell-session
-
- git://git.taler.net/deployment
-
-navigate in the following directory
-
-.. code-block:: shell-session
-
- deployment/nlnet/task3
-
-and build the Docker image with the following command:
-
-.. code-block:: shell-session
-
- docker build -t pofi .
-
-If the previous steps succeeded, the *pofi* image is ready to be run.
-
-The test runner needs the following three values: EBICS user ID, EBICS
-partner ID and IBAN. The `previous section <get-ebics-ids_>`_ explains how
-to get the EBICS IDs. The IBAN is the one entered `here <my-iban_>`_.
-
-.. code-block:: shell-session
-
- docker run -it pofi $EBICS_USER_ID $EBICS_PARTNER_ID $MY_IBAN
-
-Right after the start, the test runner needs the user intervention to
-confirm the user keys at the bank side. For this reason, it will pause
-the execution until the user is done. The following screenshot shows
-how to navigate to the page where the user has to intervene:
-
-.. image:: get-EBICS-IDs-0.png
-
-Once obtaining the page below, box #1 resets potential previous uploaded
-keys (only required when running the test more than once), and box #2 confirms
-the newly uploaded keys. Note: in production cases, such confirmation happens
-via the traditional paper mail.
-
-.. image:: set-EBICS-keys.png
-
-After having confirmed the new keys, the execution can be resumed to
-for the uploading and downloading operations.
-
-Upload
-======
-
-After the key exchange, the test runner continues by uploading one
-payment instruction. The payment instruction is a ``pain.001`` document
-that complies with the ISO20022 specification, and EBICS is responsible
-to transport the pain.001 from the client to the bank.
-
-The payment instruction causes one outgoing payment from the user
-test platform account to another fictional IBAN and has a random subject.
-A chance to specify a custom subject is also offered by the test runner.
-
-After the upload to the bank, the execution pauses to let the user
-check whether the test platform has received the payment instruction.
-
-To this purpose, click on the following navigation item:
-
-.. image:: check-payment-subject-0.png
-
-the opened page should contain the following view:
-
-.. image:: check-payment-subject-1.png
-
-in this case, open the (archive) file whose timestamp corresponds to the
-test execution and look for one XML file whose name contains "pain.001"
-(likely, this XML file is named after the archive's name). If found,
-the pain.001 file is expected to contain one node called ``Ustrd``: that
-is the payment subject and must match the one that was specified right
-before the upload. If they match, the upload succeeded and the execution
-can be resumed for the `Download`_ operation.
-
-Download
-========
-
-The download tries to get one ``camt.054`` (as well
-ISO20022) document from the bank; this document is expected to account
-for the previous outgoing payment that was created via the pain.001. As
-in the pain.001 case, EBICS is responsible to transport the camt.054 from
-the bank to the client.
-
-The download operation logs its activity to the screen, and if the execution
-is correct, the payment subject that was initially specified in the pain.001
-document must appear.
-
-Please, look for the following line:
-
-.. code-block:: shell-session
-
- $TIME [main] DEBUG tech.libeufin.nexus - Camt NOTIFICATION '$MSG_ID' has new payments:
- - $PAYMENT_SUBJECT
-
-.. note::
- Replace $TIME, $PAYMENT_SUBJECT and $MSG_ID with the particular case.
-
-If $PAYMENT_SUBJECT equals the initial payment subject from the pain.001,
-then the download operation succeeded.
diff --git a/libeufin/frontend.rst b/libeufin/frontend.rst
deleted file mode 100644
index 1fe1c83f..00000000
--- a/libeufin/frontend.rst
+++ /dev/null
@@ -1,47 +0,0 @@
-.. target audience: core developer
-
-###################
-LibEuFin Frontend
-###################
-
-Introduction
-================
-
-LibEuFin Frontend is a Single Page Application (SPA) built using React that facilitates setting up access to bank accounts, querying/displaying the transaction history of bank accounts and initiating payments.
-
-Architecture
-===============
-
-The frontend code sits in the */frontend* folder. Files in the subfolders are highlighted below.
-
-/actions, /reducers folder
---------------------------
-Contains code that uses Redux to store the login state. Prevents user from relogging in every time they closed the browser or browser tab.
-
-/routes folder
---------------
-Directs the user to the respective pages according to the URL route. Routes are broken down into *UnauthenticatedRoute* and *AuthenticatedRoute*, which corresponds to the user's login state.
-
-/components/login
------------------
-The login page for the user.
-
-/components/navbar
-------------------
-Reusable navbar component that appears on every page of the project.
-
-/components/footer
-------------------
-Reusable footer component that appears on every page of the project.
-
-components/home
----------------
-The home page showing general information of the users for e.g. bank accounts set up.
-
-/components/activity
---------------------
-Shows activity of payments and its transaction history (WIP).
-
-/components/bank-accounts
--------------------------
-Shows bank accounts that are imported. A bank account drawer is shown to facilitate setting up of bank accounts. Each bank account is displayed in a card to display extra details for e.g its print document.
diff --git a/libeufin/index.rst b/libeufin/index.rst
index d139ca3b..c77255b0 100644
--- a/libeufin/index.rst
+++ b/libeufin/index.rst
@@ -1,3 +1,23 @@
+..
+ This file is part of GNU TALER.
+ Copyright (C) 2014-2023 Taler Systems SA
+
+ TALER is free software; you can redistribute it and/or modify it under the
+ terms of the GNU Affero General Public License as published by the Free Software
+ Foundation; either version 2.1, or (at your option) any later version.
+
+ TALER is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License along with
+ TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
+
+ @author Florian Dold
+ @author Marcello Stanisci
+ @author Christian Grothoff
+
+
LibEuFin
########
@@ -7,17 +27,8 @@ LibEuFin is a project providing free software tooling for European FinTech.
:maxdepth: 1
:glob:
- concepts
- bank-transport-ebics
- ebics
- sepa
- iso20022
- banking-protocols
- transaction-identification
- frontend
- nexus-tutorial
- local-currencies-tutorial
- circuit-cli-commands
- int-deployment-gv
- ebics3-test-tutorial
- performance
+ nexus-manual
+ bank-manual
+ regional-automated-manual
+ regional-custom-manual
+ setup-ebics-at-postfinance
diff --git a/libeufin/int-deployment-gv.rst b/libeufin/int-deployment-gv.rst
deleted file mode 100644
index b3a12935..00000000
--- a/libeufin/int-deployment-gv.rst
+++ /dev/null
@@ -1,71 +0,0 @@
-.. target audience: operator, developer
-
-Deploying Taler with libEufin
-#############################
-
-.. contents:: Table of Contents
-
-This document shows how to compile and run all
-the Taler services (including libEuFin).
-
-Deployment on Gv
-----------------
-
-After having pulled the latest code of deployment.git:
-
-.. code-block:: console
-
- $ python3 deployment/bin/WIP/taler-local bootstrap
- $ python3 deployment/bin/WIP/taler-local build
- $ python3 deployment/bin/WIP/taler-local prepare
-
-The last step offers also a way to specify the database
-name -- only the PostgreSQL at this time -- and the hostname
-of the reverse proxy. See ``--help`` for more information.
-
-At this point, the services can be launched, and will be
-served at ``$hostname/$service``. The following command
-will launch all the services and show what ``$service``
-can be:
-
-.. code-block:: console
-
- $ python3 deployment/bin/WIP/taler-local launch
-
-.. note::
-
- In this context, one reverse proxy gets launched
- along all the Taler services and will dispatch any request
- to ``$service`` to the respective Unix domain socket.
-
-Withdraw with Taler
--------------------
-
-The following command withdraws a fixed amount of 5 units of currency
-to the CLI wallet:
-
-.. code-block:: console
-
- $ python3 deployment/bin/WIP/taler-local withdraw
-
-The requests will be addressed to the default Sandbox, unless
-``--bank-host`` (and ``--bank-proto``) were given; see ``--help``
-for more information.
-
-.. note::
-
- To test phone wallets, the option ``--with-qr-code``
- can be specified. That will print a QR code on screen, and
- wait for the user's input before confirming the payment to
- the Exchange.
-
-Taler Internal deployment
--------------------------
-
-One deployment is currently hosted at ``int.taler.net``.
-
-Withdraw:
-
-.. code-block:: console
-
- $ python3 deployment/bin/WIP/taler-local withdraw --bank-host int.taler.net --bank-proto https
diff --git a/libeufin/iso20022.rst b/libeufin/iso20022.rst
deleted file mode 100644
index 7b1fed8c..00000000
--- a/libeufin/iso20022.rst
+++ /dev/null
@@ -1,214 +0,0 @@
-.. target audience: core developer
-
-ISO 20022
-#########
-
-ISO 20022 is the standard that defines many XML messages for FinTech. It is
-very general, and often countries/orgs define subsets (TVS, technical
-validation subset) of the schema.
-
-Documentation for message fields can be viewed at `<https://www.iso20022.org/standardsrepository>`__.
-
-The primary syntax for ISO 20022 messages is XML. To avoid LibEuFin clients
-having to deal with XML, we define a mapping from ISO 20022 messages into JSON.
-
-The specifics of this mapping are:
-
- * The JSON should be "idiomatic" and easy to process.
- * When possible, the highly nested structures of ISO 20022 should be flattened.
- * It must be possible round-trip between the LibEuFin JSON and ISO 20022
- XML messages. The mapping of message types is not 1-to-1, as some ISO 20022 messages are
- very similar and can be mapped to the same JSON structure.
- * JSON-mapped messages are not explicitly versioned. Instead, changes
- are made in a backwards-compatible way, possibly preserving old versions
- of message elements in the same schema.
-
-
-How does LibEuFin leverage ISO 20022?
-=====================================
-
-While LibEuFin can communicate ISO 20022 messages (camt.05x, pain.001) to
-other parties, it does **not** model its own authored API and internal data
-after the ISO 20022 standard.
-
-Objections to ISO20022:
-
-1. Impedance mismatch. ISO 20022 messages do not map well to query/response
- APIs.
-2. Cumbersome to use. Even when ISO 20022 messages are directly mapped
- to JSON, they are difficult to use due to their verbosity.
-3. Underspecification. Messages like camt.05x leave many "degrees of freedom"
- when translating the underlying data into a message.
-4. No interoperability. As a result of underspecification, different countries/organizations
- define their own subset and interpretation rules for ISO 20022 messages. This can
- lead to even contradictory usage rules. An example for this is how the Swiss and EPC
- interpretations handle transaction amounts in the presence of multiple currencies.
-5. Redundancy. ISO 20022 are redundant, and often mix aspects of the "presentation logic"
- with the underlying data model. An example of this is the optional "summary" information
- in camt.05x messages.
-
-Instead of using ISO 20022 messages directly, LibEuFin leverages the standard in other ways:
-
-* As the data exchange format with banks
-* As a guideline for naming in data formats
-* As a guideline for which concepts need to be understood by LibEuFin
-
-
-Implementation notes for camt.05x
-=================================
-
-Types of amounts in camt messages
----------------------------------
-
-* Entry amount
-
- * ISO 20022: Mandatory, with debit/credit indicator. Indicates money
- moving in/out of the account in the account's currency.
- * LibEuFin: Same.
-
-* Entry transaction amount
-
- * ISO 20022: Optional, direction-less. Amount of money
- moving between the debtor and creditor bank, may not be
- in the account's currency (but the "native" currency between
- the two banks).
- * LibEuFin: Same.
-
-* Entry instructed amount
-
- * ISO 20022: Optional, direction-less. Amount of money specified in the
- payment initiation message. Usually only specified when the amount is in a
- different currency than the account currency.
- * LibEuFin: Same.
-
-* Entry counter value amount
-
- * ISO 20022: Optional, direction-less. Amount in the account's
- currency before charges.
- * LibEuFin: Same.
-
-* Entry announced posting amount
-
- * (not used by LibEuFin)
-
-* EntryDetails amount
-
- * ISO 20022: Optional, with debit-credit indicator. Same as "Entry amount"
- but for EntryDetails (= logical transactions).
- * LibEuFin: Always present. In Swiss camt messages, the element is always
- present. In German/Swedish/... camt, we take the "Entry amount" for
- non-batch entries, whereas in batch entries we use the "EntryDetails
- transaction amount" with the same debit credit indicator as the whole
- entry, which by local rules is always in the bank account currency.
-
-* EntryDetails (transaction / instructed / counter value) amount
-
- * ISO 20022: Optional, direction-less. Same as "Entry ... amount"
- but for EntryDetails (= logical transactions).
- * Same.
-
-* EntryDetails announced posting amount
-
- * (not used by LibEuFin)
-
-
-LibEuFin schema for account history
------------------------------------
-
-FIXME: This is not complete yet.
-
-.. code-block:: typescript
-
- interface NexusTransactionsReponse {
- entries: NexusAccountEntryItem[];
- }
-
- interface NexusAccountEntryItem {
- nexusEntryId: string;
-
- // Serial number that will increase with each update
- // to the entry.
- nexusStatusSequenceId: number;
-
- entry: AccountEntryItem;
- }
-
- interface AccountEntryItem {
-
- // At least one of entryId or accountServicerRef
- // must be non-null
- entryId?: string;
- accountServicerRef?: string;
-
- creditDebitIndicator: "credit" | "debit";
- amount: string;
- currency: string;
- instructedAmountDetails?: {
- amount: string;
- currency: string;
- currencyExchange?: {
- sourceCurrency: string;
- targetCurrency: string;
- unitCurrency: string;
- exchangeRate: string;
- contractId: string;
- quotationDate: string;
- };
- };
- status: "booked" | "pending" | "info";
- valueDate?: string;
- bookingDate?: string;
- mandateId?: string;
- endToEndId?: string;
- messageId?: string;
-
- creditor?: Party
- creditorAgent?: FinancialInstitution;
- creditorAccount?: FinancialInstitution;
-
- debtor?: Party
- debtorAgent?: FinancialInstitution;
- debtorAccount?: FinancialInstitution;
-
- unstructuredRemittanceInformation?: string;
- bankTransactionCode: BankTransactionCode;
- }
-
- interface Party {
- name?: string;
- partyType: "private" | "organization";
- otherId?: {
- id: string;
- schemeName?: string;
- issuer?: string;
- };
- }
-
- interface Account {
- name?: string;
- currency?: string;
- otherId?: {
- id: string;
- schemeName?: string;
- issuer?: string;
- };
- }
-
- interface FinancialInstitution {
- type: "financial-institution";
- name?: string;
- bic?: string;
- otherId?: {
- id: string;
- schemeName?: string;
- issuer?: string;
- };
- }
-
- interface BankTransactionCode {
- domain?: string;
- family?: string;
- subfamily?: string;
- proprietaryIssuer?: string;
- proprietaryCode?: string;
- }
diff --git a/libeufin/local-currencies-tutorial.rst b/libeufin/local-currencies-tutorial.rst
deleted file mode 100644
index 9fa8be99..00000000
--- a/libeufin/local-currencies-tutorial.rst
+++ /dev/null
@@ -1,401 +0,0 @@
-Create a local currency (experimental)
-######################################
-
-This tutorial shows how to setup LibEuFin to act as the
-bank of a local currency. The main features include the
-registration and removal of user accounts *(only) by the
-admin*, and the possibility to convert the local currency
-into fiat (a.k.a. cashing out).
-
-The banking capabilities are offered by a LibEuFin service
-called *Sandbox*. In particular, the tutorial relies on the
-:ref:`Core Bank API <corebank-api>`. More information about libEufin
-can be found in the :doc:`How-To page </libeufin/nexus-tutorial>`.
-
-The following sections show how to install and launch Sandbox
-either `from sources <install-from-sources_>`_, or `with Docker <docker-setup_>`_.
-
-
-.. _install-from-sources:
-
-Install and config from sources
-===============================
-
-First :ref:`build LibEuFin <building-from-source>`.
-
-If the installation succeeded, configure *Sandbox* with the
-following command.
-
-.. code-block:: console
-
- $ export LIBEUFIN_SANDBOX_DB_CONNECTION=postgres:///libeufin
- $ libeufin-sandbox config --currency NB --without-registrations default
-
-.. note::
-
- The ``--without-registrations`` option allows *only the administrator*
- to add new accounts. Without this option, other APIs may offer
- unrestricted registrations.
-
-If the configuration step succeeded, Sandbox should be ready to serve the
-bank for a currency named *NB*.
-
-In following step, we launch Sandbox by setting the administrator
-password as ``secret``.
-
-.. note::
-
- The following command launches Sandbox so that it writes
- TANs on the filesystem to ease the cash-out operations without
- relying on an `actual e-mail or SMS provider <email-sms-setup_>`_.
-.. code-block:: console
-
- $ export LIBEUFIN_SANDBOX_ADMIN_PASSWORD=secret
- $ libeufin-sandbox serve --port 5016
-
-If Sandbox is running, jump to `this part <after-installation_>`_.
-
-.. _docker-setup:
-
-
-Install and config with Docker
-==============================
-
-First, clone the deployment repository:
-
-.. code-block:: console
-
- $ git clone git://git.taler.net/deployment
-
-Then navigate to the Docker image location:
-
-.. code-block:: console
-
- $ cd deployment/nlnet/task1
-
-Now build the image with the following command.
-
-.. code-block:: console
-
- $ docker build -t nlnet .
-
-If the build step went well, the following command
-should suffice to start Sandbox and NGINX, by mapping
-the host's 8080 port to the container's 80.
-
-.. code-block:: console
-
- $ export LIBEUFIN_EXPOSED_PORT=8080
- $ docker run \
- -e LIBEUFIN_EXPOSED_PORT=$LIBEUFIN_EXPOSED_PORT \
- -p $LIBEUFIN_EXPOSED_PORT:80 \
- -it nlnet
-
-The previous command uses a default admin password of 'admin'.
-Do **CHANGE** the admin password in a production scenario. The
-following command shows how to start the services with custom
-values.
-
-.. note::
-
- Start the services this way to provide the environment
- suitable for this tutorial.
-
-.. code-block:: console
-
- $ export MY_ADMIN_PASSWORD=secret
- $ export LIBEUFIN_EXPOSED_PORT=8080
- $ docker run \
- -e LIBEUFIN_SANDBOX_ADMIN_PASSWORD=$MY_ADMIN_PASSWORD \
- -e CURRENCY=NB \
- -e LIBEUFIN_EXPOSED_PORT=$LIBEUFIN_EXPOSED_PORT \
- -v libeufin_data:/libeufin-data \
- -v /tmp:/tmp \
- -p $LIBEUFIN_EXPOSED_PORT:80 \
- -p 5016:5016 \
- -it nlnet
-
-In the example above, Docker:
-
-0. Sets the admin password to *secret*
-1. Sets the currency to *NB*
-2. Stores the database in a *volume*. This helps to
- share the database between containers.
-3. Mounts container's ``/tmp`` to the host's, to let
- the reader obtain the file TAN in the same way the
- source-based installation does.
-4. Maps the host's 8080 to the container's 80 port.
-5. Maps the host's 5016 to the container's 5016 port.
- That lets the CLI reach Sandbox inside the container,
- and therefore run the tutorial.
-
-By success, Web browsers get the UI by visiting **http://localhost:8080**
-
-The following command shows how to delete the database,
-by deleting its volume.
-
-.. code-block:: console
-
- $ docker volume rm libeufin_data
-
-Note: the removal might fail because the exited containers
-are seen as still using the container. Please refer to the Docker
-documentation for further information.
-
-.. _after-installation:
-
-If Sandbox is running
-=====================
-
-Sandbox should now be reachable on the port 5016. Check it with:
-
-.. code-block:: console
-
- $ curl http://localhost:5016
-
-If Sandbox is correctly running, it should respond with a greeting message.
-At this point, the administrator can add a new merchant to the bank with the
-following command.
-
-.. note::
-
- Consult :doc:`this document </libeufin/circuit-cli-commands>`,
- to learn all the CLI commands that address the (Circuit) API
- used in this tutorial.
-
-.. code-block:: console
-
- export LIBEUFIN_SANDBOX_USERNAME=admin
- export LIBEUFIN_SANDBOX_PASSWORD=secret
- export LIBEUFIN_SANDBOX_URL=http://localhost:5016/
- export LIBEUFIN_NEW_CIRCUIT_ACCOUNT_PASSWORD=shop-secret
-
- libeufin-cli \
- sandbox \
- demobank \
- circuit-register \
- --name "Circuit Shop" \
- --username circuit-shop \
- --cashout-address payto://iban/CH463312 \
- --internal-iban INT940993
-
-If the previous step succeeded, the merchant should have
-access to their bank account with the *circuit-shop* username
-and *shop-secret* password.
-
-Check it by asking the merchant balance with the following command.
-The two environment variables LIBEUFIN_SANDBOX_USERNAME and
-LIBEUFIN_SANDBOX_PASSWORD instruct the CLI to authenticate as the
-merchant.
-
-
-.. _check-balance:
-
-.. code-block:: console
-
- export LIBEUFIN_SANDBOX_USERNAME=circuit-shop
- export LIBEUFIN_SANDBOX_PASSWORD=shop-secret
-
- libeufin-cli sandbox demobank info --bank-account circuit-shop
-
-The expected response looks like the following one:
-
-
-.. code-block:: console
-
- {
- "balance" : {
- "amount" : "NB:0",
- "credit_debit_indicator" : "credit"
- },
- "paytoUri" : "payto://iban/SANDBOXX/INT940993?receiver-name=Circuit+Shop",
- "iban" : "INT940993"
- }
-
-In the following example, the merchant creates a cash-out operation,
-trying to convert 1 NB back to the fiat currency. The ``--amount-debit``
-option takes the amount that the merchant wants to be debited
-in their local currency bank account, whereas the ``--amount-credit``
-option is the calculation of the conversion rates as expected
-by the merchant. The two values will be checked by the bank along
-this request, to make sure that both parties agree.
-
-.. note::
-
- The current version has a fixed **0.95** conversion rate for cashing
- out. Future version will make this value configurable.
-
-.. code-block:: console
-
- libeufin-cli \
- sandbox \
- demobank \
- circuit-cashout \
- --amount-debit=NB:1 \
- --amount-credit=CHF:0.95 \
- --tan-channel=file
-
-If the previous command succeeded, it returned a JSON looking
-like the following, although most likely having a **different**
-UUID.
-
-.. code-block:: console
-
- {
- "uuid" : "de12389b-e477-4a0c-829e-f779c1cfb3a0"
- }
-
-The *uuid* represents the cash-out operation being just created
-and waiting to be confirmed with a TAN.
-
-.. note::
-
- The current version provides **only** the local currency
- side of such operation. In other words, the merchant can
- now only see a deduction on their local currency bank account
- but no incoming payment in their fiat bank account. Future
- versions will implement this.
-
-Confirm now the cash-out operation by sending to the
-bank the TAN found in the file ``/tmp/libeufin-cashout-tan.txt``.
-Assuming that the TAN for it is ``WXYZ``, the next command will confirm
-it to the bank (please, use **your** UUID).
-
-.. code-block:: console
-
- libeufin-cli \
- sandbox demobank circuit-cashout-confirm \
- --uuid de12389b-e477-4a0c-829e-f779c1cfb3a0 \
- --tan WXYZ
-
-Check now that the cash-out operation appears as a outgoing
-transaction for the merchant:
-
-.. code-block:: console
-
- libeufin-cli \
- sandbox demobank list-transactions \
- --bank-account circuit-shop
-
-The expected output should contain one line like the
-following. That witnesses that the cash-out was correctly
-confirmed and scheduled to be transferred to the fiat
-account.
-
-.. code-block:: console
-
- "subject" : "Cash-out of NB:1 to CHF:0.95"
-
-The next commands show how to delete one account from
-the local currency circuit. For the deletion to succeed,
-the account must have a balance of zero NB. Because
-of the cash-out operation, the merchant has now -1 NB
-to their account, therefore the deletion will fail. Check
-it, as the administrator, with the following command
-
-
-.. _delete-account:
-
-.. code-block:: console
-
- export LIBEUFIN_SANDBOX_USERNAME=admin
- export LIBEUFIN_SANDBOX_PASSWORD=secret
-
- libeufin-cli \
- sandbox demobank \
- circuit-delete-account --username circuit-shop
-
-The expected output is:
-
-.. code-block:: console
-
- Unexpected response status: 412
- Response: {
- "error" : {
- "type" : "sandbox-error",
- "description" : "Account circuit-shop doesn't have zero balance. Won't delete it"
- }
- }
-
-
-The bank may now award 1 NB to the merchant to bring their
-balance to zero and finally delete the account. With the following
-command, the administrator awards 1 NB to the merchant.
-
-.. code-block:: console
-
- libeufin-cli \
- sandbox demobank new-transaction \
- --bank-account admin \
- --payto-with-subject "payto://iban/SANDBOXX/INT940993?message=bring-to-zero" \
- --amount NB:1
-
-Check if the balance returned to zero with `this command <check-balance_>`_,
-and try again to delete the account `like already done <delete-account_>`_
-
-Now the deletion command should have succeeded!
-Try to `ask the balance <check-balance_>`_ again, and expect one
-error like the following:
-
-
-.. code-block:: console
-
- {
- "error" : {
- "type" : "util-error",
- "description" : "Customer 'circuit-shop' not found"
- }
- }
-
-
-.. note::
-
- Every Circuit API endpoint is addressed by a CLI subcommand
- whose name starts with ``circuit-``. The following command
- shows them.
-
- .. code-block:: console
-
- libeufin-cli sandbox demobank | grep circuit
-
-.. _email-sms-setup:
-
-E-mail or SMS TAN setup
------------------------
-
-SMS and E-mail TANs get sent via commands that
-are invoked by the Sandbox. Sandbox learns about those commands
-via optional parameters to the ``serve`` command.
-
-.. note::
-
- Future versions will allow setting the external commands
- via the configuration; follow `#7527 <https://bugs.gnunet.org/view.php?id=7527>`_.
-
-Hence, starting Sandbox as shown in the following commands is
-the **only** requirement to use the aforementioned TAN channels.
-
-For the SMS TAN:
-
-.. code-block:: console
-
- libeufin-sandbox serve --sms-tan sms_provider_command
-
-Alternatively, for the e-mail TAN:
-
-.. code-block:: console
-
- libeufin-sandbox serve --email-tan email_provider_command
-
-Both commands will be passed the TAN to STDIN and the target
-phone number / e-mail address as their first command line argument.
-
-.. note::
-
- The way the invoked commands interact with their providers
- is out of the Sandbox scope.
-
-Finally, Libeufin ships two TAN commands as example. The e-mail
-command relies on `GNU mail <mailutils.org>`_ and the SMS command
-on the service offered by `<telesign.com>`_. Check ``contrib/libeufin-tan-sms.sh``
-and ``contrib/libeufin-tan-email.sh`` in the Libeufin repository.
diff --git a/libeufin/nexus-manual.rst b/libeufin/nexus-manual.rst
new file mode 100644
index 00000000..de2f4bae
--- /dev/null
+++ b/libeufin/nexus-manual.rst
@@ -0,0 +1,277 @@
+..
+ This file is part of GNU TALER.
+ Copyright (C) 2014-2024 Taler Systems SA
+
+ TALER is free software; you can redistribute it and/or modify it under the
+ terms of the GNU Affero General Public License as published by the Free Software
+ Foundation; either version 2.1, or (at your option) any later version.
+
+ TALER is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License along with
+ TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
+
+ @author Florian Dold
+ @author Marcello Stanisci
+ @author Christian Grothoff
+
+.. target audience: operator, developer
+
+.. _libeufin-nexus:
+
+Nexus Manual
+############
+
+LibEuFin Nexus is an EBICS facilitator. It offers a command line interface to
+setup EBICS access, download banking records, and submit payments. Today, the
+LibEuFin implementation supports EBICS 2.5 and 3.0 and has been tested with
+the Postfinance (CHF). Please note that banks tend to have their own dialects
+of finance messages and thus other retail banks may or may not work. Contact
+us if you need support for another bank or core banking protocol.
+
+Future versions will offer a Web API to allow Taler exchanges to talk to their
+banks.
+
+In this manual, we explain how to setup an EBICS subscriber. We assume that
+the bank has already granted EBICS access to the subscriber.
+
+.. contents:: Table of Contents
+ :local:
+
+
+Installing Nexus
+================
+
+The following section was tested on an *OpenJDK 17* environment.
+
+
+Installing the libeufin-nexus binary packages on Debian
+-------------------------------------------------------
+
+.. include:: ../frags/installing-debian.rst
+
+.. include:: ../frags/apt-install-libeufin-nexus.rst
+
+
+Installing the libeufin-nexus binary packages on Ubuntu
+-------------------------------------------------------
+
+.. include:: ../frags/installing-ubuntu.rst
+
+.. include:: ../frags/apt-install-libeufin-nexus.rst
+
+
+Building from source
+--------------------
+
+Nexus belongs to the LibEuFin project, and can be downloaded via Git:
+
+.. code-block:: console
+
+ $ git clone git://git.taler.net/libeufin
+
+Note that Kotlin and Gradle should already work on the host system.
+
+Navigate into the *libeufin* local repository, and from top-level run:
+
+.. code-block:: console
+
+ $ ./bootstrap
+ $ ./configure --prefix=$PREFIX
+ $ make install
+
+If the previous steps succeeded, the ``libeufin-nexus`` command should
+be found in the $PATH.
+
+.. _ebics-setup:
+
+Setting up the EBICS subscriber
+===============================
+
+.. include:: ../frags/nexus-ebics-setup.rst
+
+Database setup
+==============
+
+The configuration file must include a connection string that
+tells Nexus how it should connect to the database. The default
+is:
+
+.. code-block:: ini
+
+ [nexus-postgres]
+ config = postgres:///nexus
+
+You must make sure that this database exists and is accessible to the user
+running Nexus before continuing. Then, the Nexus database schema must be
+created (or updated) to the current Nexus version using the following command:
+
+.. code-block:: console
+
+ $ libeufin-nexus-dbinit -c "$CONFIG_FILE"
+
+where ``$CONFIG_FILE`` is again the path to a configuration that contains at
+least the above ``[nexus-postgres]`` section.
+
+.. _sending-payments:
+
+Sending payments
+================
+
+Sending payments must follow a successful `EBICS subscriber setup
+<ebics-setup>`_, where the bank obtained the subscriber keys, and the
+subscriber accepted the bank keys. Furthermore, the database has to
+be set up. Right now, some other process must queue payments to be
+submitted to the database, so this section only discusses how such
+queued payments will be executed.
+
+The responsible subcommand for sending payments is ``ebics-submit``, and its
+configuration is a **superset** of core-config_. On top of that, it expects
+the database connection string and *optionally* a frequency at which it will
+check for submittable payments in the database.
+
+The frequency **may** be specified as
+
+.. code-block:: ini
+
+ [nexus-submit]
+ FREQUENCY = 5m
+
+The supported time units are ``s`` (seconds), ``m`` (minutes), ``h`` (hours).
+
+
+For testing
+-----------
+
+The ``ebics-submit`` subcommand is **not** suitable to send arbitrary
+payments, but rather to submit initiated payments that are already queued for
+submission in the Nexus database.
+
+Such queued payments may originate from bounces of incoming payments with a
+subject that would be invalid for a Taler withdrawal, or from a Taler exchange
+that needs to send a payment to a merchant.
+
+For testing purposes it is possible to manually initiate a payment using the
+``initiate-payment`` subcommand.
+The following invocation pays 1 CHF to the CH987654321 with an "Hello, Nexus!"
+subject:
+
+.. code-block:: console
+
+ $ libeufin-nexus initiate-payment -c "$CONFIG_FILE" --subject "Hello, Nexus!" "payto://iban/CH987654321?receiver-name=Name&amount=CHF:1"
+
+``$CONFIG_FILE`` is the path to Nexus' configuration file and it does not need
+the FREQUENCY value. If the previous command worked, now the database should
+contain a new row in the ``initiated_outgoing_transactions`` table, with an
+``unsubmitted`` submission state.
+
+The following command would now pick such an unsubmitted initiated payment and
+send it to the bank.
+
+
+.. code-block:: console
+
+ $ libeufin-nexus ebics-submit -c "$CONFIG_FILE" --transient
+
+The ``--transient`` flag instructs the software to perform only one pass on
+the database, submit what is submittable, and return.
+
+The ``--debug-ebics $SAVEDIR`` flag will cause the files to be stored in
+``$SAVEDIR/$YYYY-MM-DD/submit`` where ``$YYYY-MM-DD`` represents the
+date when the upload took place. This is mostly useful for debugging.
+
+For production
+--------------
+
+The ``ebics-submit`` subcommand can run in fixed frequency, or transient mode.
+
+The fixed frequency mode causes the command to check the database every time the
+frequency period expires. To activate this mode, and -- for example -- set a frequency
+of five minutes, set the configuration value ``FREQUENCY`` to ``5m``. Assuming that
+``FREQUENCY`` is set as described above, the following invocation would
+make ``ebics-submit`` check the database every five minutes, and submit any initiated
+payment according to their submission state.
+
+.. code-block:: console
+
+ $ libeufin-nexus ebics-submit -c "$CONFIG_FILE"
+
+Transient mode causes ``ebics-submit`` to check the database only once, submit any
+initiated payment according to their submission state, and return.
+
+.. code-block:: console
+
+ $ libeufin-nexus ebics-submit -c "$CONFIG_FILE"
+
+
+.. _receive-transaction-data:
+
+Downloading payment records
+===========================
+
+Downloading payments must follow a successful `EBICS subscriber setup
+<ebics-setup>`_, where the bank obtained the subscriber keys, and the
+subscriber accepted the bank keys. Furthermore, the database has to
+be set up.
+
+The responsible subcommand for sending payments is ``ebics-fetch``, and its
+configuration is a **superset** of core-config_. On top of that, it expects
+the database connection string and *optionally* a frequency at which it will
+downloads any new EBICS files and ingest them in the database.
+
+The frequency **may** be specified as
+
+.. code-block:: ini
+
+ [nexus-fetch]
+ FREQUENCY = 5m
+
+The supported time units are ``s`` (seconds), ``m`` (minutes), ``h`` (hours).
+
+Assuming that ``$CONFIG_FILE`` contains all required options, the following
+command would download any unseen EBICS files:
+
+.. code-block:: console
+
+ $ libeufin-nexus ebics-fetch -c "$CONFIG_FILE" --transient
+
+The ``ebics-fetch`` subcommand will always cause libeufin-nexus to download
+then parse EBICS files and ingest their content statements into its local
+database.
+
+The files type can be given as an argument to select what will be fetched. If no argument is given, all supported files are fetched. The following files are supported:
+
+* ``acknowledgement``: EBICS acknowledgement, retrieves the status of EBICS orders.
+* ``status``: Payment status, retrieves status of pending debits.
+* ``notification``: Debit & credit notifications, retrieves the history of confirmed debits and credits.
+
+The ``--transient`` flag makes the command download and import EBICS files only
+once and return immediately afterwards. Without the flag, Nexus
+will download at the frequency specified in the configuration.
+
+The ``--debug-ebics $SAVEDIR`` flag will cause the files to be stored in
+``$SAVEDIR/$YYYY-MM-DD/fetch`` where ``$YYYY-MM-DD`` represents the
+date when the download took place. This is mostly useful for debugging.
+
+
+For Testing
+-----------
+
+If the bank account history has transactions that are useful for testing, it is
+possible to re-download them via the ``--pinned-start`` argument.
+
+The following command redownloads transactions *from* the pinned start until
+the present:
+
+.. code-block:: console
+
+ $ libeufin-nexus ebics-fetch -c "$CONFIG_FILE" --pinned-start 2023-11-01
+
+.. note::
+
+ If the Nexus database already contains the bank account history, you might need
+ to **reset** the database in order to have the re-downloaded transactions be
+ properly ingested. Be careful when resetting the database: resetting the wrong
+ database might cause DATA LOSS!
diff --git a/libeufin/nexus-tutorial.rst b/libeufin/nexus-tutorial.rst
deleted file mode 100644
index aeea4667..00000000
--- a/libeufin/nexus-tutorial.rst
+++ /dev/null
@@ -1,956 +0,0 @@
-.. target audience: operator, developer
-
-LibEuFin How-To
-###############
-
-.. contents:: Table of Contents
-
-The LibEuFin Nexus is a Web service that provides a JSON abstraction layer to
-access bank accounts. It does **not** itself offer banking services, but is a
-translator between JSON requests and other banking protocols (such as EBICS),
-that are offered by banks.
-
-This document explains how to set up Nexus to access a bank account
-via the EBICS protocol.
-
-In order to follow all the steps below, the reader should either
-have access to a bank account with EBICS support or follow the
-steps in :ref:`Configuring the Sandbox <configuring-the-sandbox>`.
-
-
-Installing LibEuFin
-===================
-
-Installation on Debian
-----------------------
-
-.. include:: ../frags/installing-debian.rst
-
-To install LibEuFin, you can now simply run:
-
-.. code-block:: console
-
- # apt install libeufin-nexus libeufin-sandbox
-
-Administration via SystemD
---------------------------
-
-After the Debian installation, the installed unit files
-should be listed by the following command:
-
-.. code-block:: console
-
- # systemctl list-unit-files | egrep '(nexus|sandbox)'
-
-Both ``nexus.service`` and ``sandbox.service`` should appear.
-
-At this point, the services can be started on boot:
-
-.. code-block:: console
-
- # systemctl enable libeufin-nexus # use 'disable' to rollback
- # systemctl enable libeufin-sandbox # only if you want the sandbox
-
-Or just manually:
-
-.. code-block:: console
-
- # systemctl start libeufin-nexus # use 'stop' to terminate.
- # systemctl start libeufin-sandbox # only if you want the sandbox
-
-The following command should inform the user about the status
-of the running / terminated service:
-
-.. code-block:: console
-
- # systemctl status libeufin-nexus
-
-For more diagnostics, use:
-
-.. code-block:: console
-
- # journalctl -u libeufin-nexus
-
-Run-time dependencies
----------------------
-
-LibEuFin has the following run-time dependencies:
-
-* OpenJDK 11
-* Python 3.8
-* python3-click (can be installed via ``pip3 install click``)
-* python3-requests (can be installed via ``pip3 install requests``)
-
-These dependencies only need to be installed manually when building from source
-or using the prebuilt binaries.
-
-Downloading prebuilt binaries
------------------------------
-
-Pre-built packages can be obtained from the `taler.net website
-<https://taler.net/files/libeufin>`__.
-
-Unpack the ``libeufin-$version.zip`` file to
-your desired location (typically ``/opt`` or ``~/opt``) and make sure that your ``PATH``
-environment variable contains the ``bin/`` directory of the unpacked archive.
-
-
-.. _building-from-source:
-
-Building from source
---------------------
-
-Nexus belongs to the LibEuFin project, and can be downloaded via Git:
-
-.. code-block:: console
-
- $ git clone git://git.taler.net/libeufin
-
-It is recommended to run the ``v0.9.1`` version, hence
-the following command may now be given.
-
-.. code-block:: console
-
- $ git checkout v0.9.1
-
-Note that Kotlin and Gradle should already work on the host system.
-
-Navigate into the *libeufin* local repository, and from top-level run:
-
-.. code-block:: console
-
- $ ./bootstrap
- $ ./configure --prefix=$PREFIX
- $ make install # Note: This may require Java=18; Java=17 had errors, Java>=19 is unsupported by Gradle
-
-Verifying your installation
----------------------------
-
-In case of success, the three following commands should be found:
-
-.. code-block:: console
-
- $ which libeufin-nexus
- $ which libeufin-sandbox
- $ which libeufin-cli
-
-
-.. _configuring-the-sandbox:
-
-Configuring the Sandbox (Optional)
-==================================
-
-If you don't have access to a real bank account with an EBICS API, you can set
-up the sandbox. The sandbox is a simplistic and incomplete implementation of a
-core banking system with EBICS access to bank accounts.
-
-The sandbox uses HTTP Basic auth, with username ``admin``.
-Choose a password and set env var ``LIBEUFIN_SANDBOX_ADMIN_PASSWORD`` to it.
-
-The sandbox relies on a database, which you must specify using a Postgres
-connection URI with the ``LIBEUFIN_SANDBOX_DB_CONNECTION`` environment
-variable, before invoking any commands.
-If this variable is not set, ``libeufin-sandbox`` complains and exits:
-
-.. code-block:: console
-
- $ export LIBEUFIN_SANDBOX_ADMIN_PASSWORD=secret
- $ libeufin-sandbox serve
- DB connection string not found in the env variable LIBEUFIN_SANDBOX_DB_CONNECTION.
- The following two examples are valid connection strings:
- postgresql://localhost:5432/libeufindb?user=Foo&password=secret
- postgres:///libeufindb
-
-Before being usable, a Sandbox needs to be configured. This is done
-by creating the ``default`` demobank. A demobank is a set of configuration
-values associated to one name; in the example below, we'll create one
-named ``default``, that is mandatory to have.
-
-.. note::
-
- By design, many demobanks can be hosted by one running Sandbox,
- although at the time of writing only the ``default`` one is supported.
-
-A default demobank having the EUR currency is created with the following command:
-
-.. code-block:: console
-
- $ export LIBEUFIN_SANDBOX_DB_CONNECTION=postgres:///libeufintestdb
- $ libeufin-sandbox config --currency EUR default
-
-In order to use Taler, a default exchange needs to be configured.
-
-.. code-block:: console
-
- $ export LIBEUFIN_SANDBOX_DB_CONNECTION=postgres:///libeufintestdb
- $ libeufin-sandbox default-exchange --demobank default $exchange_base_url $exchange_payto_address
-
-The sandbox service can now be started with the following command:
-
-.. code-block:: console
-
- $ export LIBEUFIN_SANDBOX_ADMIN_PASSWORD=secret
- $ export LIBEUFIN_SANDBOX_DB_CONNECTION=postgres:///libeufintestdb
- $ libeufin-sandbox serve --port 5016
-
-The instructions below hook Nginx to the Sandbox:
-
-.. code-block:: nginx
-
- redirect / to /demobanks/default;
- rewrite ^/$ https://$host/demobanks/default;
- location / {
- proxy_set_header Host $host;
- proxy_set_header X-Forwarded-Host $host;
- proxy_set_header X-Forwarded-Proto "https";
- proxy_set_header X-Forwarded-Prefix "/";
- proxy_pass http://localhost:5016/;
- }
-
-To reset the state of the sandbox, delete the database.
-
-For invocations of the LibEuFin command-line interface tool (``libeufin-cli``),
-the following environment variables must be set to the authentication
-information, and the URL of the sandbox service:
-
-.. code-block:: console
-
- $ export LIBEUFIN_SANDBOX_USERNAME=admin
- $ export LIBEUFIN_SANDBOX_PASSWORD=secret
- $ export LIBEUFIN_SANDBOX_URL=http://localhost:5016
-
-Note that the password is the same as for ``LIBEUFIN_SANDBOX_ADMIN_PASSWORD``.
-Verify that the sandbox is running:
-
-.. code-block:: console
-
- $ libeufin-cli sandbox check
- Hello, this is the Sandbox
-
-Now an EBICS host can be created:
-
-.. code-block:: console
-
- $ libeufin-cli sandbox ebicshost create --host-id testhost
- $ libeufin-cli sandbox ebicshost list
- {
- "ebicsHosts" : [ "testhost" ]
- }
-
-Note that most ``libeufin-cli`` subcommands will ask for input interactively if
-the respective value is not specified on the command line.
-
-Next, register a user. For the ``libeufin-cli sandbox demobank register``
-command, the ``LIBEUFIN_SANDBOX_USERNAME`` and ``LIBEUFIN_SANDBOX_PASSWORD``
-are assumed to be ``jrluser`` and ``easy``, respectively.
-
-.. note::
-
- All the following commands address the ``default`` demobank, see ``libeufin-cli sandbox demobank --help``.
-
-.. code-block:: console
-
- $ export LIBEUFIN_SANDBOX_USERNAME=jrluser
- $ export LIBEUFIN_SANDBOX_PASSWORD=easy
- $ libeufin-cli sandbox demobank register
-
-Check the balance of the user just created:
-
-.. code-block:: console
-
- $ libeufin-cli sandbox \
- demobank info --bank-account jrluser
-
-With a user registered, we can now create an EBICS subscriber (identified by
-the partner ID and user ID) for the host. This command requires admin
-privileges, so ``LIBEUFIN_SANDBOX_USERNAME`` and ``LIBEUFIN_SANDBOX_PASSWORD``
-are reset back to ``admin`` and ``secret``, respectively.
-
-.. The plan is to replace the ‘sandbox ebicssubscriber list’ command
- below with a ‘sandbox demobank show-ebicssubscriber’ command.
- Need to implement it first!
-
-.. code-block:: console
-
- $ export LIBEUFIN_SANDBOX_USERNAME=admin
- $ export LIBEUFIN_SANDBOX_PASSWORD=secret
- $ libeufin-cli sandbox \
- demobank new-ebicssubscriber \
- --host-id testhost \
- --partner-id partner01 \
- --user-id user02 \
- --bank-account jrluser
- $ libeufin-cli sandbox ebicssubscriber list
- {
- "subscribers" : [ {
- "host_id" : "testhost",
- "partner_id" : "partner01",
- "user_id" : "user02",
- "system_id" : null,
- "demobank_account_label" : "jrluser"
- } ]
- }
-
-The ``libeufin-cli sandbox demobank new-ebicssubscriber`` command
-also creates an associated bank account. You can see it with command:
-
-.. code-block:: console
-
- $ libeufin-cli sandbox bankaccount list
- [ {
- "label" : "bank",
- "name" : "Bank account owner's name",
- "iban" : "DE895351",
- "bic" : "SANDBOXX"
- }, {
- "label" : "jrluser",
- "name" : "Bank account owner's name",
- "iban" : "DE724881",
- "bic" : "SANDBOXX"
- } ]
-
-The account name ``jrluser`` is the unique identifier of the account within
-the sandbox. The EBICS parameters identify the subscriber that should have
-access to the bank account via EBICS.
-
-The account already has one transaction, the "Sign-up bonus" from the bank.
-Note that in the following examples we transition to using the ``bankaccount``
-subcommand, because there is no need to rely on EBICS:
-
-.. code-block:: console
-
- $ libeufin-cli sandbox bankaccount transactions jrluser
- {
- "payments" : [ {
- "account_label" : "jrluser",
- "creditor_iban" : "DE724881",
- "creditor_bic" : "SANDBOXX",
- "creditor_name" : "Unknown",
- "debtor_iban" : "DE895351",
- "debtor_bic" : "SANDBOXX",
- "debtor_name" : "The Bank",
- "amount" : "100",
- "currency" : "EUR",
- "subject" : "Sign-up bonus",
- "date" : "Tue, 22 Feb 2022 00:04:15 GMT",
- "credit_debit_indicator" : "credit",
- "account_servicer_reference" : "2NG75I0O",
- "payment_information_id" : null
- } ]
- }
-
-To populate the account with some more transactions, run the following command:
-
-.. code-block:: console
-
- $ libeufin-cli sandbox bankaccount generate-transactions jrluser
-
-.. code-block:: console
-
- $ libeufin-cli sandbox bankaccount simulate-incoming-transaction jrluser \
- --debtor-iban DE06500105174526623718 \
- --debtor-bic INGDDEFFXXX \
- --debtor-name "Joe Foo" \
- --subject "Hello World" \
- --amount 10.50
-
-Now the list of transactions has grown by several entries:
-
-.. code-block:: console
-
- $ libeufin-cli sandbox bankaccount transactions jrluser
- {
- "payments" : [ {
- "account_label" : "jrluser",
- "creditor_iban" : "DE724881",
- "creditor_bic" : "SANDBOXX",
- "creditor_name" : "Unknown",
- "debtor_iban" : "DE895351",
- "debtor_bic" : "SANDBOXX",
- "debtor_name" : "The Bank",
- "amount" : "100",
- "currency" : "EUR",
- "subject" : "Sign-up bonus",
- "date" : "Tue, 22 Feb 2022 00:04:15 GMT",
- "credit_debit_indicator" : "credit",
- "account_servicer_reference" : "2NG75I0O",
- "payment_information_id" : null
- }, {
- "account_label" : "jrluser",
- "creditor_iban" : "DE724881",
- "creditor_bic" : "SANDBOXX",
- "creditor_name" : "Creditor Name",
- "debtor_iban" : "DE64500105178797276788",
- "debtor_bic" : "DEUTDEBB101",
- "debtor_name" : "Max Mustermann",
- "amount" : "22",
- "currency" : "EUR",
- "subject" : "sample transaction GSF7S5LC",
- "date" : "Tue, 22 Feb 2022 01:26:18 GMT",
- "credit_debit_indicator" : "credit",
- "account_servicer_reference" : "GSF7S5LC",
- "payment_information_id" : null
- }, {
- "account_label" : "jrluser",
- "creditor_iban" : "DE64500105178797276788",
- "creditor_bic" : "DEUTDEBB101",
- "creditor_name" : "Max Mustermann",
- "debtor_iban" : "DE724881",
- "debtor_bic" : "SANDBOXX",
- "debtor_name" : "Debitor Name",
- "amount" : "10",
- "currency" : "EUR",
- "subject" : "sample transaction 1WUP303Q",
- "date" : "Tue, 22 Feb 2022 01:26:18 GMT",
- "credit_debit_indicator" : "debit",
- "account_servicer_reference" : "1WUP303Q",
- "payment_information_id" : null
- }, {
- "account_label" : "jrluser",
- "creditor_iban" : "DE724881",
- "creditor_bic" : "SANDBOXX",
- "creditor_name" : "Creditor Name",
- "debtor_iban" : "DE06500105174526623718",
- "debtor_bic" : "INGDDEFFXXX",
- "debtor_name" : "Joe Foo",
- "amount" : "10.50",
- "currency" : "EUR",
- "subject" : "Hello World",
- "date" : "Tue, 22 Feb 2022 01:26:41 GMT",
- "credit_debit_indicator" : "credit",
- "account_servicer_reference" : "sandbox-ALQP8TXKJWRVKMAH",
- "payment_information_id" : null
- } ]
- }
-
-.. note::
-
- The sandbox is intended as a testing tool and thus not stable.
-
-.. _disable-registrations:
-
-Disable registrations (experimental)
-------------------------------------
-
-Demobanks can disable/enable registrations for new users.
-The responsible options are
-``--with-registrations`` / ``--without-registrations``.
-
-For more information on the available commands, use the built-in ``--help`` flag.
-The full functionality of the sandbox is available via
-the :ref:`Core Bank API <corebank-api>`.
-
-Connect Nexus with the bank.
-============================
-
-Nexus relies on a database, which you must specify using a Postgres
-connection URI with the ``LIBEUFIN_NEXUS_DB_CONNECTION`` environment
-variable, before invoking any commands.
-(If this variable is not set, ``libeufin-nexus`` complains and exits.)
-
-Use the following command to run the Nexus service:
-
- Neuxs defaults to *not* storing the messages that it downloads
- from the bank. To revert this behaviour, export also the environment
- variable ``LIBEUFIN_NEXUS_KEEP_BANK_MESSAGES`` to ``yes`` before
- running the following command.
-
-.. code-block:: console
-
- $ export LIBEUFIN_NEXUS_DB_CONNECTION=postgresql://localhost:5433/libeufindb?user=foo&password=secret
- $ libeufin-nexus serve --port 5017
-
-This assumes that the PostgreSQL service with a database
-called ``libeufindb`` listens on port 5433
-for requests from the Nexus service.
-The Nexus service itself listens on port 5017.
-Note that you must have the ``LIBEUFIN_NEXUS_DB_CONNECTION``
-environment variable set for most uses of the libeufin-nexus
-command.
-
-At this point a superuser account needs to be created:
-
-.. code-block:: console
-
- $ libeufin-nexus superuser foo --password secret
-
-If you omit ``--password secret``, you will interactively be asked for a password.
-For simplicity, a superuser can as well act as a normal user, but an API
-to create less privileged users is offered.
-
-.. note::
-
- User and permissions management in LibEuFin is still under development.
- In particular, permissions for non-superusers are very limited at the moment.
-
-The command line interface needs the following three values
-to be defined in the environment: ``LIBEUFIN_NEXUS_URL``, ``LIBEUFIN_NEXUS_USERNAME``,
-and ``LIBEUFIN_NEXUS_PASSWORD``. In this example, ``LIBEUFIN_NEXUS_USERNAME`` should be
-set to ``foo``, and ``LIBEUFIN_NEXUS_PASSWORD`` to the value given for its password
-in the previous step (with the ``libeufin-nexus superuser`` command). The
-``LIBEUFIN_NEXUS_URL`` could be given as ``http://localhost:5017``.
-
-Nexus speaks two protocols to reach the bank: EBICS and x-libeufin-bank.
-In Nexus speech, each protocol is also known as a *bank connection*.
-The following two sections show how to setup such bank connections. Note:
-only one is needed to operate!
-
-EBICS
------
-
-.. note::
-
- For the sandbox setup in this guide, the ``EBICS_BASE_URL``
- should be ``http://localhost:5016/ebicsweb``.
- This is the value of environment variable
- ``LIBEUFIN_SANDBOX_URL`` suffixed with ``/ebicsweb``,
- since the sandbox will be providing EBICS services.
-
- Similarly, ``EBICS_HOST_ID`` should be ``testhost``,
- and ``EBICS_PARTNER_ID`` should be ``partner01``.
- For ``EBICS_USER_ID`` we will use ``user02`` (for account ``jrluser``),
- and for ``CONNECTION_NAME``, we will use ``conn01``.
-
-.. code-block:: console
-
- $ libeufin-cli \
- connections \
- new-ebics-connection \
- --ebics-url $EBICS_BASE_URL \
- --host-id $EBICS_HOST_ID \
- --partner-id $EBICS_PARTNER_ID \
- --ebics-user-id $EBICS_USER_ID \
- $CONNECTION_NAME
-
-If this step executes correctly
-(use ``libeufin-cli connections list-connections``
-and ``libeufin-cli connections show-connection`` to check),
-Nexus will have created all the cryptographic
-material that is needed on the client side; in this EBICS example, it created
-the signature and identification keys. It is therefore advisable to *make
-a backup copy* of such keys.
-
-.. code-block:: console
-
- $ libeufin-cli \
- connections \
- export-backup \
- --passphrase $SECRET \
- --output-file $BACKUP_FILE \
- $CONNECTION_NAME
-
-At this point, Nexus needs to both communicate its keys to the bank, and
-download the bank's keys. This synchronization happens through the INI,
-HIA, and finally, HPB message types.
-
-After the electronic synchronization, the subscriber must confirm their keys
-by sending a physical mail to the bank. The following command helps generating
-such letter:
-
-.. code-block:: console
-
- $ libeufin-cli connections get-key-letter $CONNECTION_NAME out.pdf
-
-.. note::
-
- When using the LibEuFin sandbox, subscribers are automatically
- activated after keys are received electronically.
-
-.. code-block:: console
-
- $ libeufin-cli \
- connections \
- connect \
- $CONNECTION_NAME
-
-Once the connection is synchronized, Nexus needs to import locally the data
-corresponding to the bank accounts offered by the bank connection just made.
-The command below downloads the list of the bank accounts offered by ``$CONNECTION_NAME``.
-
-.. code-block:: console
-
- $ libeufin-cli \
- connections \
- download-bank-accounts \
- $CONNECTION_NAME
-
-It is now possible to list the accounts offered by the connection.
-
-.. _list-connections:
-
-.. code-block:: console
-
- $ libeufin-cli \
- connections \
- list-offered-bank-accounts \
- $CONNECTION_NAME
-
-.. note::
-
- The ``nexusBankAccountId`` field should at this step be ``null``,
- as we have not yet imported the bank account and thus the account
- does not yet have a local name.
-
-Nexus now needs an explicit import of the accounts it should manage. This
-step is needed to let the user pick a custom name for such accounts.
-
-.. code-block:: console
-
- $ libeufin-cli \
- connections \
- import-bank-account \
- --offered-account-id testacct01 \
- --nexus-bank-account-id $LOCAL_ACCOUNT_NAME \
- $CONNECTION_NAME
-
-Once a Nexus user imported a bank account (``$LOCAL_ACCOUNT_NAME``)
-under a certain connection (``$CONNECTION_NAME``), it is possible
-to accomplish the usual operations for any bank account: asking for the
-list of transactions, and making a payment.
-
-The last step is to create background tasks that fetch and submit
-the information from and to the bank. The following command submits
-the prepared payments to the bank each second.
-
-.. _submit-task:
-
-.. code-block:: console
-
- $ libeufin-cli accounts task-schedule $LOCAL_ACCOUNT_NAME \
- --task-type submit \
- --task-name submit-payments-each-second \
- --task-cronspec "* * *"
-
-The following step downloads from the bank all the new transactions,
-each second. The ``report`` value indicates that Nexus is interested
-in the transactions which did reach already the booked state, in order
-to provide faster times to its users.
-
-.. code-block:: console
-
- $ libeufin-cli accounts task-schedule $LOCAL_ACCOUNT_NAME \
- --task-type fetch \
- --task-name fetch-reports-each-second \
- --task-cronspec "* * *" \
- --task-param-level report \
- --task-param-range-type latest
-
-For example, the cronspec can be changed to every five seconds by the
-following value: ``"*/5 * *"`` (remember to quote, to protect from shell
-filename expansion).
-
-x-libeufin-bank
----------------
-
-This is a faster bank connection, because it relies on JSON and HTTP basic
-auth, as oppsed to EBICS XML and RSA cryptography. It is also planned to equip
-the server side with long-polling, in order to loop more slowly when asking
-for new data.
-
-The first step is to create one x-libeufin-bank connection. Make sure that
-the usual env variables LIBEUFIN_NEXUS_USERNAME, LIBEUFIN_NEXUS_PASSWORD, and
-LIBEUFIN_NEXUS_URL are set. The following command instructs Nexus about
-the bank URL and the credentials it needs
-
-.. code-block:: console
-
- libeufin-cli connections new-xlibeufinbank-connection \
- --bank-url "http://localhost:5016/demobanks/default/access-api" \
- --username jrluser \
- --password easy \
- $CONNECTION_NAME
-
-The ``--password`` option can be omitted, and in this case the CLI will
-prompt to collect it.
-
- The credentials are exactly the same as the ones used to register a
- new bank account at Sandbox.
-
-Once the connection is created, we need -- just as in the EBICS case --
-the "connect" step. In this case, the connect step will check if the
-credentials and URL are correct and (as a side effect) download basic
-information about the bank account.
-
-.. code-block:: console
-
- libeufin-cli connections connect $CONNECTION_NAME
-
-As a proof, you can `list <list-connections_>`_ which bank account
-arrived at Nexus after the connect command succeeds. Now the bank
-account can be imported under a local name at Nexus, just as it was
-in the EBICS case.
-
-.. note::
-
- One main difference with EBICS is that now we don't need the
- ``download-bank-accounts`` step, because ``connect`` carried
- it out as a side effect of checking the credentials.
-
-
-.. code-block:: console
-
- libeufin-cli connections import-bank-account \
- --offered-account-id jrluser \
- --nexus-bank-account-id $LOCAL_ACCOUNT_NAME \
- $CONNECTION_NAME
-
-
-Now that the account is imported, the background tasks need to
-be setup, to provide always the most updated information from the
-bank.
-
-The submit task can be `the same <submit-task_>`_ as EBICS. The fetch
-task however needs one different setting, and namely it has to require
-``statement`` instead of 'report' because x-libeufin-bank has only the
-booked state for transactions. The time range is also different, because
-x-libeufin-bank does NOT offer ``latest``. Any unsupported setting should
-however generate one error and therefore not create wrong background tasks.
-
-.. code-block:: console
-
- libeufin-cli accounts task-schedule \
- --task-type fetch \
- --task-name fetch-every-second \
- --task-cronspec "* * *" \
- --task-param-level statement \
- --task-param-range-type since-last \
- $LOCAL_ACCOUNT_NAME
-
-Request history of transactions
-===============================
-
-The LibEuFin Nexus keeps a local copy of the bank account's transaction
-history. Before querying transactions locally, it is necessary
-to request transactions for the bank account via the bank connection.
-
-This command asks Nexus to download the latest transaction reports/statements
-through the bank connection:
-
-.. code-block:: console
-
- $ libeufin-cli accounts fetch-transactions $LOCAL_ACCOUNT_NAME
-
-.. note::
-
- By default, the latest available transactions are fetched. It is also
- possible to specify a custom date range (or even all available transactions)
- and the type of transactions to fetch (inter-day statements or intra-day
- reports).
-
-Once Nexus has stored all the information in the database, the
-client can ask to actually see the transactions:
-
-.. code-block:: console
-
- $ libeufin-cli accounts transactions $LOCAL_ACCOUNT_NAME
-
-Make a payment
-==============
-
-Payments pass through two phases: preparation and submission. The preparation
-phase assigns the payment initiation a unique ID, which prevents accidental
-double submissions of payments in case of network failures or other
-disruptions.
-
-
-The following command prepares a payment:
-
-.. code-block:: console
-
- $ libeufin-cli accounts prepare-payment \
- --creditor-iban=$IBAN_TO_SEND_MONEY_TO \
- --creditor-bic=$BIC_TO_SEND_MONEY_TO \
- --creditor-name=$CREDITOR_NAME \
- --payment-amount=$AMOUNT \
- --payment-subject=$SUBJECT \
- $LOCAL_ACCOUNT_NAME
-
-Note: the ``$AMOUNT`` value needs the format ``CURRENCY:X.Y``; for example
-``EUR:10``, or ``EUR:1.01``.
-
-The previous command should return a value (``$UUID``) that uniquely
-identifies the prepared payment in the Nexus system. That is needed
-in the next step, to **send the payment instructions to the bank**:
-
-.. code-block:: console
-
- $ libeufin-cli accounts submit-payments \
- --payment-uuid $UUID \
- $LOCAL_ACCOUNT_NAME
-
-Automatic scheduling
-====================
-
-With an EBICS bank connection, the LibEuFin Nexus needs to regularly query for
-new transactions and (re-)submit prepared payments.
-
-It is possible to schedule these tasks via an external task scheduler such as
-cron(8). However, the Nexus also has an internal task scheduling mechanism for
-accounts.
-
-
-The following three commands create a schedule for submitting payments hourly,
-fetching transactions (intra-day reports) every 5 minutes, and (inter-day statements)
-once at 11pm every day :
-
-.. code-block:: console
-
- $ libeufin-cli accounts task-schedule myacct \
- --task-type="submit" \
- --task-name='submit-payments-hourly' \
- --task-cronspec='0 0 *'
-
- $ libeufin-cli accounts task-schedule myacct \
- --task-type="fetch" \
- --task-name='fetch-5min' \
- --task-cronspec='0 */5 *' \
- --task-param-level=report \
- --task-param-range-type=latest
-
- $ libeufin-cli accounts task-schedule myacct \
- --task-type="fetch" \
- --task-name='fetch-daily' \
- --task-cronspec='0 0 23' \
- --task-param-level=statement \
- --task-param-range-type=latest
-
-The cronspec has the following format, which is slightly non-standard due to
-the ``SECONDS`` field
-
-.. code-block:: none
-
- SECONDS MINUTES HOURS DAY-OF-MONTH[optional] MONTH[optional] DAY-OF-WEEK[optional]
-
-
-Restore the backup
-==================
-
-The following command restores all the details associated with
-one bank connection subscription. For EBICS, this means that the
-INI and HIA secret keys will be restored for the requesting user.
-
-.. code-block:: console
-
- $ libeufin-cli connections \
- restore-backup \
- --passphrase=$SECRET \
- --backup-file=$BACKUP_FILE \
- $CONNECTION_NAME
-
-..
- FIXME:
- On a bad password given, Nexus responds
- "bad backup given" instead of "authentication failed".
-
-
-Creating a Taler facade
-=======================
-
-Facades are additional abstraction layers that can serve
-specific purposes. For example, one application might need
-a filtered version of the transaction history, or it might
-want to refuse payments that do not conform to certain rules.
-
-At this moment, only the *Taler facade type* is implemented
-in the Nexus, and the command below instantiates one under a
-existing bank account / connection pair. You can freely
-assign an identifier for the ``$FACADE_NAME`` below:
-
-.. code-block:: console
-
- $ libeufin-cli facades new-taler-wire-gateway-facade \
- --currency EUR \
- --facade-name $FACADE_NAME \
- $CONNECTION_NAME \
- $LOCAL_ACCOUNT_NAME
-
-At this point, the additional *taler-wire-gateway* (FIXME: link
-here to API here) API becomes offered by the Nexus. The purpose
-is to let a Taler exchange rely on Nexus to manage its bank account.
-
-The base URL of the facade that can be used by the Taler exchange
-as the Taler Wire Gateway base URL located when listing the facades:
-
-.. code-block:: console
-
- $ libeufin-cli facades list
-
-Creating a Anastasis facade
-===========================
-
-The following command creates a Anastasis facade. At this point, *only*
-the superuser is able to create facades; please set the environment variables
-``LIBEUFIN_NEXUS_USERNAME`` and ``LIBEUFIN_NEXUS_PASSWORD`` accordingly.
-
-.. code-block:: console
-
- $ libeufin-cli facades new-anastasis-facade \
- --currency EUR \
- --facade-name $FACADE_NAME \
- $CONNECTION_NAME \
- $LOCAL_ACCOUNT_NAME
-
-If the previous command succeeded, it is possible to see the
-facade's base URL with:
-
-.. code-block:: console
-
- $ libeufin-cli facades list
-
-At this point, to allow a non superuser to use the facade, a history
-permission needs to be set:
-
-.. code-block:: console
-
- $ libeufin-cli permissions grant \
- user $USERNAME \
- facade $FACADENAME \
- facade.anastasis.history
-
-.. note::
-
- There is no need to set/unset a transfer permission on the facade
- since this one does not offer any endpoint to issue wire transfers.
-
-Managing Permissions and Users
-==============================
-
-This guide has so far assumed that a superuser is accessing the LibEuFin Nexus.
-However, it is advisable that the Nexus is accessed with users that only have a
-minimal set of permissions.
-
-The Nexus currently only has support for giving non-superusers access to Taler
-wire gateway facades.
-
-To create a new user, use the ``users`` subcommand of the CLI:
-
-.. code-block:: console
-
- $ libeufin-cli users list
- # [ ... shows available users ... ]
-
- $ libeufin-cli users create $USERNAME
- # [ ... will prompt for password ... ]
-
-Permissions are managed with the ``permissions`` subcommand.
-The following commands grant permissions to view the transaction history
-and create payment initiations with a Taler wire gateway facade:
-
-
-.. code-block:: console
-
- $ libeufin-cli permissions grant \
- user $USERNAME \
- facade $FACADENAME \
- facade.talerWireGateway.history
-
- $ libeufin-cli permissions grant \
- user $USERNAME \
- facade $FACADENAME \
- facade.talerWireGateway.transfer
-
-The list of all granted permissions can be reviewed:
-
-.. code-block:: console
-
- $ libeufin-cli permissions list
diff --git a/libeufin/performance.rst b/libeufin/performance.rst
deleted file mode 100644
index a0af25a8..00000000
--- a/libeufin/performance.rst
+++ /dev/null
@@ -1,114 +0,0 @@
-Performance demonstrators
-#########################
-
-This document explains how to prove the following performance
-requirements implemented in LibEuFin.
-
-1. Long-polling offered by Nexus to the Exchange Wirewatch.
-2. Reduced usage of disk space by the database.
-3. PostgreSQL short-lived database sessions.
-4. Participation in the Taler benchmark.
-
-It is worth noting that point 2 and 3 will be proved *via*
-point 4. In particular, because the benchmark is a resource
-demanding activity, its impact on the database should be
-enough to reflect a worst case scenario with regard to points
-2 and 3.
-
-The following two sections will describe how to run
-`point 1 <Long-polling>`_, and `points 2, 3, 4 <Benchmark>`_
-altogether.
-
-Long-polling
-^^^^^^^^^^^^
-
-This demonstrator is a Docker image that installs LibEuFin
-and registers one user at both Sandbox and Nexus. The Nexus
-user is set up to use the Taler Wire Gateway, to let ``curl``
-emulate the Taler exchange (wire-watch).
-
-To run the demonstrator, clone the following repository:
-
-.. code-block:: shell-session
-
- git://git.taler.net/deployment
-
-and build the Docker image:
-
-.. code-block:: shell-session
-
- $ cd deployment/nlnet/task5/long-poll
- $ docker build -t long-poller .
-
-Start the ``long-poller`` image and wait after the installation
-and configuration complete. The completion should end with a message
-starting by ``Services are online!``. At this point, it is possible
-to request Taler incoming payments and observe how such request returns
-**only after** we manually send Taler money to the long-polling client.
-
-Give the following command to request Taler incoming payment
-with the long-polling feature:
-
-.. code-block:: shell-session
-
- $ curl -v -u test-user:x 'http://localhost:5001/facades/test-facade/taler-wire-gateway/history/incoming?delta=5&long_poll_ms=100000'
-
-After having observed that the previous command *actually*
-long-polls, send it to the background by pressing CTRL-Z. Send
-now a Taler payment to ``test-user`` with the following command.
-
-.. code-block:: shell-session
-
- $ wire_transfer
-
-Bring now the ``curl`` process again in the foreground, and if
-it got the payment, now it shows the payment data.
-
-Benchmark
-^^^^^^^^^
-
-This demonstrator runs the Taler benchmark that relies on LibEuFin.
-
-Clone the following repository:
-
-.. code-block:: shell-session
-
- git://git.taler.net/deployment
-
-and build the Docker image:
-
-.. code-block:: shell-session
-
- $ cd deployment/nlnet/task5/benchmark
- $ docker build -t benchmark .
-
-Run the ``benchmark`` image and wait for its completion. At this
-point, the demonstrator prints the benchmark result regarding all
-the components, and lastly the database disk usage and the LibEuFin
-database session(s) duration(s).
-
-The database disk usage is complessive, therefore it shows how all
-the services occupy database disk space. Hence if this quantity is
-acceptable, then also LibEuFin's share is.
-
-On the other hand, the database session duration concerns only LibEuFin,
-and compares the *longest* database session with the whole benchmark
-duration. In particular, it shows what percentage of the whole benchmark
-duration is represented by the longest LibEuFin session. Therefore
-'low' percentages mean 'short' database sessions, as it is requested
-in point 3.
-
-..
- Clone the following repository:
-
- .. code-block:: shell-session
-
- git://git.taler.net/deployment
-
- and build the Docker image:
-
- .. code-block:: shell-session
-
- $ cd deployment/nlnet/task5/date-range
- $ docker build -t date-range .
-
diff --git a/libeufin/regional-automated-manual.rst b/libeufin/regional-automated-manual.rst
new file mode 100644
index 00000000..4fe492ab
--- /dev/null
+++ b/libeufin/regional-automated-manual.rst
@@ -0,0 +1,289 @@
+..
+ This file is part of GNU TALER.
+ Copyright (C) 2014-2024 Taler Systems SA
+
+ TALER is free software; you can redistribute it and/or modify it under the
+ terms of the GNU Affero General Public License as published by the Free Software
+ Foundation; either version 2.1, or (at your option) any later version.
+
+ TALER is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License along with
+ TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
+
+ @author Florian Dold
+ @author Marcello Stanisci
+ @author Christian Grothoff
+
+
+.. target audience: operator
+
+Regional Currency Automated Setup Manual
+########################################
+
+This manual describes how to setup a regional currency using a script that largely automates the process. If you want to do a custom setup you can follow the :doc:`custom setup manual<regional-custom-manual>`.
+
+
+.. contents:: Table of Contents
+ :local:
+
+.. include:: ../frags/regional-manual-architecture.rst
+
+Guided Automated Setup
+======================
+
+Prerequisites
++++++++++++++
+
+For this manual, we assume that the system is deployed on a contemporary
+Debian GNU/Linux Bookworm or Ubuntu Mantic system using the binary packages provided.
+Furthermore, you should run the process on a system with one or more globally
+reachable IP address(es) *and* with various DNS names already pointing to
+these IPs.
+
+Preparing the required subdomain names
+++++++++++++++++++++++++++++++++++++++
+
+The GNU Taler program needs to have three subdomains pointing to your server IP address, in order to let NGINX to accommodate each component.
+These are "bank", "exchange" and "backend", this said, you need to have a registered top level domain name,
+where you can create type (A) entries, as subdomains pointing to your own server public IP address.
+A very good advice when creating these subdomains, and if your domain panel lets you specify the TTL (time to live) figure, is
+to specify a very low value (such as 300), so in case of future changes, its value (the IP address), will be propagated quickly.
+
+Once you have added the three required subdomains in your domain control panel, you have to make sure as well, these subdomains have
+propagated over the Internet correctly, and they are currently publicly available.
+
+You can check this from your terminal very easily with the "ping" command, as this:
+
+.. code-block:: console
+
+ $ ping -c1 bank.domainname.ltd
+ $ ping -c1 exchange.domainname.ltd
+ $ ping -c1 backend.domainname.ltd
+
+You can also use `this tool <https://toolbox.googleapps.com/apps/dig/>`_ for the same purpose, and to check the propagation status.
+
+.. warning::
+ Take into account some hosting providers providing virtualized servers (VPS or VDS) can enable by default the firewall program "UFW", blocking by default the port number 443. So you have to either disable this firewall program, or open to this 443 port number to allow https.
+
+Now you are ready to go with the next step.
+
+Obtaining the Scripts
++++++++++++++++++++++
+
+First, download the deployment scripts via Git:
+
+.. code-block:: console
+
+ # apt update && apt install git
+ $ git clone git://git.taler.net/deployment
+
+Running the Guided Configuration
+++++++++++++++++++++++++++++++++
+
+Navigate into the *regional-currency/* directory and run *main.sh* as **root**:
+
+.. code-block:: console
+
+ $ cd deployment/regional-currency/
+ # ./main.sh
+
+The script will start by installing the required packages and then asking you fundamental questions about the desired setup, in particular:
+
+#. The name of the regional currency. It must have 3 to 11 letters.
+#. Whether to setup the regional currency to be backed by a fiat currency. You'll need a bank account at a fiat currency bank offering an online banking protocol supported by LibEuFin Nexus. If you answer ``y``, you will also need to provide the following information:
+
+ #. The ISO code of the fiat currency. Use 'CHF' or 'EUR'.
+ #. The IBAN of the fiat bank account.
+ #. The BIC of the fiat bank account.
+ #. The legal name of the fiat bank account.
+
+#. The name of the regional currency bank. It will be shown to business users when they interact with the system.
+#. The DNS domain name of your setup (i.e: domain.tld). The installer will create by itself all the needed subdomains for your domain name, as (``bank.$DOMAIN_NAME``, ``exchange.$DOMAIN_NAME`` and ``backend.$DOMAIN_NAME``). But, these subdomain names as explained before, must have been added beforehand to your DNS domain control panel, and they must be pointing to the IP address of the server on which you are running the installation (before you execute the installer).
+#. Whether to use TLS or not. You should answer ``y`` in most cases.
+#. Whether to setup SMS two-factor authentication using `Telesign <https://www.telesign.com>`_, multi-factor authentication is strongly recommended, especially when regional currency can be converted to fiat currency. This requires `a Customer ID and an API Key <https://developer.telesign.com/enterprise/docs/authentication#basic-authentication>`_. You should answer ``y`` in most cases.
+#. The admin password for the bank. Be absolutely sure to enter a very, very long and high-entropy password, preferably using the autogenerated one.
+#. Whether to generate terms of service (ToS) for the exchange from default templates.
+#. Whether to generate a privacy policy for the exchange from default templates.
+
+The information you entered as well as the generated bank admin password will
+be stored in a file called ``config/user.conf``. If you run the script in
+the future again (for example, to upgrade the installation), you will not be asked
+these questions a second time.
+
+After answering all of the questions, the actual installation will start. The
+scripts will download and configure various packages, which may take some time.
+Grab a coffee.
+
+.. note::
+
+ At this point, the setup is NOT connected to any fiat bank account! The next
+ steps must always be done manually!
+
+Running the script again from scratch
++++++++++++++++++++++++++++++++++++++
+
+If for some reason your installation doesn't work because you have answered erroneously
+some of the interactive questions, or you just want to reset the current installation and to re-deploy
+the script again for having its latest changes, you will have to proceed as follows:
+
+In brief, you need to wipe completely the "content" of the file config/user.conf, this doesn't mean
+to remove the file itself, but only its content. Even though you can do this manually by editing the file manually
+with your preferred text editor, you can also do this in one single command.
+
+.. code-block:: console
+
+ # rm config/user.conf
+
+.. note::
+
+ In future versions of the program when executed for the second time, the program itself will
+ show an option to offer wiping the content of this config/user.conf file, automatically.
+
+Multi-factor authentication
++++++++++++++++++++++++++++
+
+The script allows you to configure multi-factor authentication via SMS using Telesign as a provider. You can also configure multi-factor authentication via email or use providers other than Telesign for SMS. You will need to configure these channels manually as described in :ref:`multi-factor authentication <libeufin-mfa>`.
+
+If you choose not to back your regional currency with a fiat currency, you can stop here.
+
+Web-based Configuration
++++++++++++++++++++++++
+
+By default, the regional currency conversion rates are 1:1. You can change the conversion rates and the ``admin`` debt limit via the bank's web interface as the ``admin`` user.
+
+Connecting to a Fiat Bank: the EBICS setup
+++++++++++++++++++++++++++++++++++++++++++
+
+To complete the conversion setup, you have to set up an EBICS subscriber using the fiat bank account you specified during the automated setup.
+
+When you sign up for an EBICS-enabled bank account, the bank will provide you
+with various credentials. Those must be provided in the
+``/etc/libeufin/libeufin-nexus.conf`` configuration file.
+
+.. note::
+ As legacy transactions in that bank account would likely confuse the system, it is advisable to use a fresh bank account with an empty transaction history.
+
+The following snippet shows the mandatory configuration values:
+
+.. _core-config:
+
+.. code-block:: ini
+
+ [nexus-ebics]
+ # Bank
+ HOST_BASE_URL = https://ebics.postfinance.ch/ebics/ebics.aspx
+ BANK_DIALECT = postfinance
+
+ # EBICS IDs
+ HOST_ID = PFEBICS
+ USER_ID = PFC00563
+ PARTNER_ID = PFC00563
+
+.. warning::
+ This combination of HOST_ID, USER_ID and PARTNER_ID must never be used by another instance of libeufin-nexus or by other EBICS clients, otherwise data will be lost.
+
+Reuse existing client keys
+^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+If you have client keys from a previous EBICS setup you can copy the JSON file to ``/var/lib/libeufin-nexus/client-ebics-keys.json``.
+
+Make sure this file is accessible to the user running ``libeufin-nexus``, you should run:
+
+.. code-block:: console
+
+ $ chown libeufin-nexus:libeufin-nexus /var/lib/libeufin-nexus/client-ebics-keys.json
+
+Create new client keys
+^^^^^^^^^^^^^^^^^^^^^^
+
+Run the following command to start the EBICS setup process:
+
+.. code-block:: console
+
+ $ sudo -u libeufin-nexus libeufin-nexus ebics-setup
+
+If the previous command failed when running EBICS INI with an error code of
+``EBICS_INVALID_USER_OR_USER_STATE``, you need to confirm your keys to your bank to
+activate your account.
+
+To that end, the previous run should have left a PDF document that you can
+print, sign and send to the bank. Look for the message that looks like ``PDF
+file with keys created at '/tmp/libeufin-nexus-keys-$TIMESTAMP.pdf'``.
+
+Once the bank has received and processed this document you can continue.
+
+Get bank keys
+^^^^^^^^^^^^^
+
+Run the following command to finish the EBICS setup process:
+
+.. code-block:: console
+
+ $ sudo -u libeufin-nexus libeufin-nexus ebics-setup
+
+The EBICS setup is finished once the bank keys have been accepted.
+
+
+Configuring the Exchange for Conversion
++++++++++++++++++++++++++++++++++++++++
+
+By default, the exchange is setup to perform conversion without any restrictions. You may configure restrictions on the bank accounts that may originate the funds, for example, to prevent international wire transfers that may expose you to additional compliance risks:
+
+.. code-block:: console
+
+ $ . config/user.conf
+ $ sudo -u taler-exchange-offline taler-exchange-offline \
+ enable-account \
+ "${CONVERSION_PAYTO}" \
+ conversion-url "${PROTO}://bank.$DOMAIN_NAME/conversion-info/" \
+ # restrictions ...
+ upload
+
+.. note::
+ Refer to the manpage ``taler-exchange-offline`` for a full array of possible restrictions.
+
+System ON!
+++++++++++
+
+The last step is to enable libeufin-nexus to :ref:`import incoming bank
+transactions <receive-transaction-data>` (cash in) and to :ref:`trigger
+outgoing bank transactions <sending-payments>` (cash out).
+
+.. code-block:: console
+
+ # systemctl enable --now libeufin-nexus.target
+
+Configuring exchange terms
+++++++++++++++++++++++++++
+
+You can use your own terms of service and privacy policy. You can use the default templates in ``/usr/share/taler/terms`` as a guide.
+Assuming you have custom terms of service and privacy policy ``rst`` teamplte files at ``TOS_PATH`` and ``PRIVACY_PATH``, the following commands generate the terms files:
+
+.. code-block:: console
+
+ # taler-terms-generator -i "$TOS_PATH"
+ # taler-terms-generator -i "$PRIVACY_PATH"
+
+You now have to specify the terms file names in the exchange config:
+
+.. code-block:: console
+
+ # TERMS_ETAG="$(basename "$TOS_PATH" .rst)"
+ # PRIVACY_ETAG="$(basename "$PRIVACY_PATH" .rst)"
+
+.. code-block:: ini
+
+ [exchange]
+ TERMS_ETAG=${TERMS_ETAG}
+ PRIVACY_ETAG=${PRIVACY_ETAG}
+
+Make sure to restart taler-exchange after changing these configuration options:
+
+.. code-block:: console
+
+ # systemctl restart taler-exchange.target
+
+.. include:: ../frags/regional-manual-use.rst
diff --git a/libeufin/regional-custom-manual.rst b/libeufin/regional-custom-manual.rst
new file mode 100644
index 00000000..8477c18d
--- /dev/null
+++ b/libeufin/regional-custom-manual.rst
@@ -0,0 +1,164 @@
+..
+ This file is part of GNU TALER.
+ Copyright (C) 2014-2024 Taler Systems SA
+
+ TALER is free software; you can redistribute it and/or modify it under the
+ terms of the GNU Affero General Public License as published by the Free Software
+ Foundation; either version 2.1, or (at your option) any later version.
+
+ TALER is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License along with
+ TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
+
+ @author Florian Dold
+ @author Marcello Stanisci
+ @author Christian Grothoff
+
+
+.. target audience: operator
+
+Regional Currency Custom Setup Manual
+#####################################
+
+This manual describes how to setup a regional currency manually. If you want a guided setup you can follow the :doc:`automated setup manual<regional-automated-manual>`.
+
+.. contents:: Table of Contents
+ :local:
+
+.. include:: ../frags/regional-manual-architecture.rst
+
+Custom Manual Setup
+===================
+
+You first need to setup the :ref:`libeufin-bank<libeufin-bank>` and integrate it with a Taler exchange.
+
+If you don't want your regional currency to be backed by a fiat currency, you can stop here.
+
+Enabling Currency Conversion
+++++++++++++++++++++++++++++
+
+You need to setup the :ref:`libeufin-nexus<libeufin-nexus>` using a bank account at a bank dealing in fiat currency that
+offers an online banking protocol supported by LibEuFin Nexus.
+
+Next, you have to enable conversion and should ensure that at least one TAN
+channel for :ref:`multi-factor authentication <libeufin-mfa>` is configured.
+
+The following snippet shows how to enable conversion in ``libeufin-bank`` configuration:
+
+.. code-block:: ini
+
+ [libeufin-bank]
+ ALLOW_CONVERSION = YES
+ FIAT_CURRENCY = EUR
+
+Make sure to (re)start the libeufin-bank after changing
+these configuration options:
+
+.. code-block:: console
+
+ # systemctl restart libeufin-bank
+
+
+Web-based Configuration
++++++++++++++++++++++++
+
+Now you have to set the conversion rates and the ``admin`` debt limit via the bank's web interface as the ``admin`` user.
+
+.. _regional-conversion-setup:
+
+Configuring the Exchange for Conversion
++++++++++++++++++++++++++++++++++++++++
+
+This section explains how to enable currency conversion at the exchange,
+which is critical for wallets to know how to wire fiat currency to an
+exchange to obtain regional currency.
+
+You will need to use the ``taler-exchange-offline`` tool to inform the
+exchange about the **fiat** bank account that can be used for cash in
+operations and also specify the URL for currency conversion. Additionally,
+you may also configure restrictions on the bank accounts that may originate
+the funds, for example, to prevent international wire transfers that may expose
+you to additional compliance risks.
+
+Given the ``$IBAN`` of the fiat currency bank account and ``$NAME`` as
+the (URL-encoded) name of the exchange-account owner, the following
+``taler-exchange-offline`` invocation can be used to notify wallets about
+the possibility of currency conversion (cash in):
+
+.. code-block:: console
+
+ # taler-exchange-offline \
+ enable-account \
+ payto://iban/$IBAN?receiver-name=$NAME \
+ conversion-url "$CONVERSION_URL" \
+ debit-restriction \
+ deny \
+ credit-restriction \
+ regex \
+ 'payto://iban/.*/CH.*?receiver-name=.*' \
+ 'Swiss only' \
+ '{ "de" : "nur Schweiz", \
+ "fr" : "Suisse uniquement" }'
+ upload
+
+Here, the ``$CONVERSION_URL`` must be set to the base URL of the conversion
+endpoint of the bank, which should be
+``https://bank.$DOMAIN/conversion-info/`` in our setup. Note that you can
+leave out the "credit-restriction" if you want to allow international inbound
+wire transfers. The "debit-restriction" is largely mandatory as in this setup
+the taler-exchange-transfer is only configured to deal with the regional
+currency bank. Crediting fiat bank accounts must thus be done via the
+cash-out functionality of the regional currency bank account.
+
+.. note::
+
+ The above command adds a **second** bank account to the exchange.
+ You (or the guided setup script) should have already enabled the
+ regional currency bank account (without any "conversion-url").
+
+System ON!
+++++++++++
+
+The last step is to enable libeufin-nexus to :ref:`import incoming bank
+transactions <receive-transaction-data>` (cash in) and to :ref:`trigger
+outgoing bank transactions <sending-payments>` (cash out).
+
+.. code-block:: console
+
+ # systemctl enable --now libeufin-nexus.target
+
+
+Configuring exchange terms
+++++++++++++++++++++++++++
+
+You can use your own terms of service and privacy policy. You can use the default templates in ``/usr/share/taler/terms`` as a guide.
+Assuming you have custom terms of service and privacy policy ``rst`` teamplte files at ``TOS_PATH`` and ``PRIVACY_PATH``, the following commands generate the terms files:
+
+.. code-block:: console
+
+ # taler-terms-generator -i "$TOS_PATH"
+ # taler-terms-generator -i "$PRIVACY_PATH"
+
+You now have to specify the terms file names in the exchange config:
+
+.. code-block:: console
+
+ # TERMS_ETAG="$(basename "$TOS_PATH" .rst)"
+ # PRIVACY_ETAG="$(basename "$PRIVACY_PATH" .rst)"
+
+.. code-block:: ini
+
+ [exchange]
+ TERMS_ETAG=${TERMS_ETAG}
+ PRIVACY_ETAG=${PRIVACY_ETAG}
+
+Make sure to restart taler-exchange after changing these configuration options:
+
+.. code-block:: console
+
+ # systemctl restart taler-exchange.target
+
+.. include:: ../frags/regional-manual-use.rst
diff --git a/libeufin/sepa.rst b/libeufin/sepa.rst
deleted file mode 100644
index 29baca00..00000000
--- a/libeufin/sepa.rst
+++ /dev/null
@@ -1,26 +0,0 @@
-.. target audience: core developer
-
-SEPA Payments
-#############
-
-This page collects reference materials and details for specifics of SEPA payments.
-
-SEPA Credit Transfer (SCT)
-==========================
-
-SCT is a "normal" bank transfer. Details (terminology, data definitions, flow diagrams) can be found in the EPC's
-`SCT rulebook <https://www.europeanpaymentscouncil.eu/document-library/rulebooks/sepa-credit-transfer-rulebook>`__.
-
-
-Reject vs Return vs Recall
---------------------------
-
-* A **rejected** payment is refused by the originator bank or the
- clearing and settlement layer.
-* A **returned** payment is refused by the beneficiary's bank via a
- counter-transaction over the settlement layer.
-* A payment is **recalled** when the originator's bank (potentially
- requested by the originator) wants to "undo" a SCT.
-
-SEPA currently does **not** directly support a mechanism for the **beneficiary** to return
-a payment.
diff --git a/libeufin/setup-ebics-at-postfinance.rst b/libeufin/setup-ebics-at-postfinance.rst
new file mode 100644
index 00000000..161bc6d3
--- /dev/null
+++ b/libeufin/setup-ebics-at-postfinance.rst
@@ -0,0 +1,90 @@
+Setup EBICS at PostFinance test platform
+########################################
+
+In this tutorial, we will set up one EBICS 3 account at the PostFinance
+test platform, in order to test the ``postfinance`` dialect from ``libeufin-nexus``.
+
+The first requirement is to create one account `there <https://isotest.postfinance.ch>`_.
+It is advised to set the language as English, as this tutorial is meant
+for the international audience.
+
+Set the language in the drop-down menu and navigate to the registration
+section as it is shown below:
+
+.. image:: set-english-and-register.png
+
+Even if the above page doesn't welcome you in English, the two boxes in the
+screenshot will still hold their position, so please look for box #1 to
+set the language and for box #2 to get the page that offers to register.
+
+After a successful registration, an IBAN needs to be associated with
+the user just created. Likely after the first login, the following
+page should appear. Click then on box #2.
+
+.. note::
+
+ The navigation bar in the screenshot below is ubiquitous,
+ so click on box #1 if the depicted page did not show up automatically.
+
+.. image:: no-accounts.png
+
+If the following page appears, please obtain a checksum-valid but fictitious
+Swiss IBAN and enter it as indicated by box #1 and then save it (box #2).
+
+.. _my-iban:
+
+.. image:: set-IBAN.png
+
+If the bank responds with a successful message, the next step is to enable
+EBICS 3 and set the format of the ISO20022 documents.
+
+.. note::
+
+ There is no "use EBICS 3" setting since EBICS 3 is a "side effect"
+ of choosing one particular ISO format for banking records.
+
+To use EBICS 3, click the navigation bar item highlighted in the
+following screenshot.
+
+.. image:: set-ISO-2019-0.png
+
+The following page should appear, where the ISO format can be specified
+as it is depicted in the following screenshot.
+
+.. image:: set-ISO-2019-1.png
+
+After having saved the setting, proceed now to set the flavor
+of payment confirmations. This setting instructs the bank to define
+particular XML nodes when it releases the payment confirmations. Even
+if each document is ISO20022, this step is essential because ISO20022
+has many optional fields and client and bank must agree on which fields
+appear in the documents.
+
+Hover on box #1 and then click on box #2.
+
+.. image:: camt.054-style-0.png
+
+If the following page appears, please set everything as it is shown below:
+
+.. image:: camt.054-style-1.png
+
+.. _get-ebics-ids:
+
+The last step is to retrieve the user's EBICS identifiers, namely the
+EBICS user and partner IDs. Hover on box #1 and then click on box #2.
+
+.. image:: get-EBICS-IDs-0.png
+
+At the first access, the following page should appear. Simply create
+EBICS access and continue to the next step.
+
+.. image:: enable-EBICS.png
+
+After having obtained the following page, finally the EBICS identifiers
+are shown in box #1.
+
+.. image:: get-EBICS-IDs-1.png
+
+Finally, box #2 contains the bank keys fingerprints. These are
+important to check that the client, along the keying process, has obtained
+the right bank keys.
diff --git a/libeufin/transaction-identification.rst b/libeufin/transaction-identification.rst
deleted file mode 100644
index 6c88a727..00000000
--- a/libeufin/transaction-identification.rst
+++ /dev/null
@@ -1,87 +0,0 @@
-.. target audience: developer, core developer
-
-Transaction Identification
-##########################
-
-This page describes how bank transactions are **identified** in various banking protocols and
-data formats.
-
-**Why is transaction identification necessary?**
-When a client downloads the transaction history from some data source, it has to know
-whether a transaction is new, or whether the transaction is already part of the
-client's local records.
-
-Protocol-specific Details
-=========================
-
-ISO 20022 camt.05X
-------------------
-
-The camt52/53/54 messages defined by ISO 20022 do not have a mandatory transaction
-identifier. Instead it defines a handful of optional references.
-
-Two identifiers seem to be used in practice: The *Account Servicer Reference* and the
-*Entry Reference*. Of these, only the *Account Servicer Reference* seems to be useful
-for transaction identification.
-
-The Account Servicer Reference is assigned by the bank to a transaction. In
-practice, all banks assign the **same** Account Servicer Reference to the same
-transaction showing up in camt52 (the account report), camt53 (the account
-statement) and camt53 (credit notifications).
-
-The Account Servicer Reference is assigned by the bank that reports the transaction,
-and does **not** serve as a globally unique identifier for the transaction.
-
-However, in rare cases, a transaction can be reported that does not yet have an
-Account Servicer Reference assigned to it by the bank yet. This can happen
-when the bank only received a (SWIFT) pre-notification for the transaction, but decides
-to already pass on this information to the customer. In this case, banks seem to
-assign an *Entry Reference* to the corresponding entry.
-
-Most other transactions, however, do **not** have an *Entry Reference* assigned to it.
-Some banks document that the *Entry Reference* is only unique within one report for one account.
-
-OFX
----
-
-OFX assigns a transaction identifier to each reported transactions, allowing the client
-to know which transactions it has already seen.
-
-Problems and Possible Solutions
-===============================
-
-Sometimes the same bank can offer **multiple** ways to download transactions.
-In Germany, most banks offer EBICS and FinTS access, which delivers transactions
-in the camt.52/53 format. However, some also offer access via PSD2 APIs and completely custom APIs.
-
-Two APIs from the same bank do not necessarily need to support the same transaction identification scheme.
-This could lead to the same transaction showing up multiple times in the account transaction history, which
-is clearly bad!
-
-LibEuFin intends to solve this problem in the following ways:
-
-1. Each local account has a single "transaction identification scheme".
- Importing transactions via a bank connection that has a different transaction
- identifier scheme will fail.
-2. When a bank connection reports a transaction that is missing the expected transaction identifier,
- the status (booked, pending, info) is examined:
-
- 1. When the status is booked, an error is reported, and corresponding bank message
- will be made available for review.
- 2. When the status is "pending" or "info", the entry will simply be ignored.
-
-In the future, this might be extended to be less restrictive:
-
-* An account could be configured to do transaction identification based on a "core attributes hash",
- i.e. a cryptographic hash of core attributes of the transactions that are expected to not change.
- This should only apply to booked transactions.
-* Un-identifiable pending/info transactions could be managed in a separate
- "informational" transactions table that is purged as soon as a *booked statement closing transaction*
- is reported with a higher booking date.
-
-Others
-======
-
-* `UETR <https://www.swift.com/your-needs/industry-themes/unique-end-to-end-transaction-reference-uetr>`__ is
- a unique identifier used on the SWIFT level. It doesn't help for transaction identification
- as not every transaction goes over SWIFT, even for SEPA accounts.
diff --git a/manpages/challenger-admin.1.rst b/manpages/challenger-admin.1.rst
index af4508ea..bdb7687c 100644
--- a/manpages/challenger-admin.1.rst
+++ b/manpages/challenger-admin.1.rst
@@ -19,7 +19,9 @@ Synopsis
[**-h** | **--help**]
[**-L** *LOGLEVEL* | **--log=**\ \ *LOGLEVEL*]
[**-l** *FILENAME* | **--logfile=**\ \ *FILENAME*]
-[**-v** | **--version**] CLIENT_URL
+[**-q** | **--quiet**]
+[**-v** | **--version**]
+CLIENT_URL
Description
@@ -48,7 +50,10 @@ Its options are as follows:
**-l** *FILENAME* \| **--logfile=**\ \ *FILENAME*
Configure logging to write logs to *FILENAME*.
-**-v** \| **–version**
+**-q** \| **–-quiet**
+ Be less verbose in the output. Useful in shell scripts.
+
+**-v** \| **–-version**
Print version information.
diff --git a/manpages/libeufin-bank.1.rst b/manpages/libeufin-bank.1.rst
new file mode 100644
index 00000000..5b8c3721
--- /dev/null
+++ b/manpages/libeufin-bank.1.rst
@@ -0,0 +1,170 @@
+libeufin-bank(1)
+#################
+
+.. only:: html
+
+ Name
+ ====
+
+ **libeufin-bank** - LibEuFin Bank
+
+
+Synopsis
+========
+
+**libeufin-bank**
+[**-h** | **--help**]
+[**--version**]
+COMMAND [ARGS...]
+
+Subcommands: **serve**, **dbinit**, **create-account**, **passwd**, **config**
+
+
+Description
+===========
+
+**libeufin-bank** is a program that implements a simple core banking system with
+account and REST APIs, including REST APIs for a Web interface
+and REST APIs to interact with GNU Taler components.
+
+Its options are as follows:
+
+**-h** \| **--help**
+ Print short help on options.
+
+**–version**
+ Print version information.
+
+The interaction model is as follows:
+
+- Configure the database with commands ``dbinit``.
+
+- Set admin account password with commands ``passwd``.
+
+- Start the HTTP server with command ``serve``.
+ Let this run in a shell, writing logs to stderr.
+
+The following sections describe each command in detail.
+
+dbinit
+------
+
+This command defines the database schema for LibEuFin Bank. It is mandatory to run this command before invoking the ``serve`` command.
+
+Its options are as follows:
+
+**-h** \| **--help**
+ Print short help on options.
+**-c** \| **--config** *FILENAME*
+ Specifies the configuration file.
+**-L** \| **--log** *LOGLEVEL*
+ Configure logging to use LOGLEVEL.
+**-r** \| **--reset**
+ If present, deletes any database table (WARNING: potential data loss)
+
+
+serve
+-----
+
+This command starts the HTTP server.
+
+Its options are as follows:
+
+**-h** \| **--help**
+ Print short help on options.
+**-c** \| **--config** *FILENAME*
+ Specifies the configuration file.
+**-L** \| **--log** *LOGLEVEL*
+ Configure logging to use LOGLEVEL.
+
+create-account
+--------------
+
+This command create a bank account and prints its payto://-URI to STDOUT.
+
+Its options are as follows:
+
+**-h** \| **--help**
+ Print short help on options.
+**-c** \| **--config** *FILENAME*
+ Specifies the configuration file.
+**-L** \| **--log** *LOGLEVEL*
+ Configure logging to use LOGLEVEL.
+**-u** \| **--username** *USERNAME*
+ Account unique username.
+**-p** \| **--password** *PASSWORD*
+ Account password used for authentication.
+**--name** *NAME*
+ Legal name of the account owner.
+**--public**
+ Make this account visible to anyone.
+**--exchange**
+ Make this account a taler exchange.
+**--email** *EMAIL*
+ E-Mail address used for TAN transmission.
+**--phone** *PHONE_NUMBER*
+ Phone number used for TAN transmission.
+**--cashout_payto_uri** *PAYTO_URI*
+ Payto URI of a fiant account who receive cashout amount.
+**--payto_uri** *PAYTO_URI*
+ Payto URI of this account.
+**--debit_threshold** *AMOUNT*
+ Max debit allowed for this account.
+
+
+edit-account
+--------------
+
+This command edit an existing account.
+
+It takes one argument, the account username.
+
+Its options are as follows:
+
+**-h** \| **--help**
+ Print short help on options.
+**-c** \| **--config** *FILENAME*
+ Specifies the configuration file.
+**-L** \| **--log** *LOGLEVEL*
+ Configure logging to use LOGLEVEL.
+**--name** *NAME*
+ Legal name of the account owner.
+**--public** *true|false*
+ Make this account visible to anyone.
+**--email** *EMAIL*
+ E-Mail address used for TAN transmission.
+**--phone** *PHONE_NUMBER*
+ Phone number used for TAN transmission.
+**--cashout_payto_uri** *PAYTO_URI*
+ Payto URI of this account.
+**--debit_threshold** *AMOUNT*
+ Max debit allowed for this account.
+
+passwd
+------
+
+This command change any account password.
+
+It takes two arguments, the account username and the account new password.
+
+Its options are as follows:
+
+**-h** \| **--help**
+ Print short help on options.
+**-c** \| **--config** *FILENAME*
+ Specifies the configuration file.
+**-L** \| **--log** *LOGLEVEL*
+ Configure logging to use LOGLEVEL.
+
+.. include:: ../frags/libeufin-config-cli.rst
+
+
+SEE ALSO
+========
+
+libeufin-bank.conf(5)
+
+Bugs
+====
+
+Report bugs by using https://bugs.taler.net or by sending electronic mail to <taler@gnu.org>.
diff --git a/manpages/libeufin-bank.conf.5.rst b/manpages/libeufin-bank.conf.5.rst
new file mode 100644
index 00000000..35103760
--- /dev/null
+++ b/manpages/libeufin-bank.conf.5.rst
@@ -0,0 +1,122 @@
+libeufin-bank.conf(5)
+######################
+
+.. only:: html
+
+ Name
+ ====
+
+ **libeufin-bank.conf** - LibEuFin Bank configuration file
+
+
+Description
+===========
+
+.. include:: ../frags/common-conf-syntax.rst
+
+Files containing default values for many of the options described below
+are installed under ``$TALER_PREFIX/share/libeufin-bank/config.d/``.
+The configuration file given with **-c** to Taler binaries
+overrides these defaults.
+
+A configuration file may include another, by using the ``@INLINE@`` directive,
+for example, in ``main.conf``, you could write ``@INLINE@ sub.conf`` to
+include the entirety of ``sub.conf`` at that point in ``main.conf``.
+
+Be extra careful when using ``taler-config -V VALUE`` to change configuration
+values: it will destroy all uses of ``@INLINE@`` and furthermore remove all
+comments from the configuration file!
+
+GLOBAL OPTIONS
+--------------
+
+The following options are from the “[libeufin-bank]” section.
+
+CURRENCY
+ Internal currency of the libeufin-bank, e.g. “EUR” for Euro.
+
+WIRE_TYPE
+ Supported payment target type, this can either be ``iban`` or ``x-taler-bank``
+
+IBAN_PAYTO_BIC
+ Bank BIC used in generated iban payto URI. Required if WIRE_TYPE = iban
+
+X_TALER_BANK_PAYTO_HOSTNAME
+ Bank hostname used in generated x-taler-bank payto URI. Required if WIRE_TYPE = x-taler-bank
+
+DEFAULT_DEBT_LIMIT
+ Default debt limit for newly created accounts. Defaults to CURRENCY:0 if not specified.
+
+REGISTRATION_BONUS
+ Value of the registration bonus for new users. Defaults to CURRENCY:0 if not specified.
+
+ALLOW_REGISTRATION
+ Whether anyone can create a new account or whether this action is reserved for the admin. Defaults to no if not specified.
+
+ALLOW_ACCOUNT_DELETION
+ Whether anyone can delete its account or whether this action is reserved for the admin. Defaults to no if not specified.
+
+ALLOW_CONVERSION
+ Whether regional currency conversion is enabled. Defaults to no if not specified.
+
+FIAT_CURRENCY
+ External currency used during cashin and cashout.
+ Only used if ``ALLOW_CONVERSION`` is ``YES``.
+
+TAN_SMS
+ Path to TAN challenge transmission script via sms. If not specified, this TAN channel will not be supported.
+ Only used if ``ALLOW_CONVERSION`` is ``YES``.
+
+TAN_EMAIL
+ Path to TAN challenge transmission script via email. If not specified, this TAN channel will not be supported.
+ Only used if ``ALLOW_CONVERSION`` is ``YES``.
+
+TAN_SMS_ENV
+ Environment variables for the sms TAN script.
+ Only used if ``TAN_SMS`` is set.
+
+TAN_EMAIL_ENV
+ Environment variables for the email TAN script.
+ Only used if ``TAN_EMAIL`` is set.
+
+SERVE
+ This can either be ``tcp`` or ``unix``.
+
+PORT
+ Port on which the HTTP server listens, e.g. 9967.
+ Only used if ``SERVE`` is ``tcp``.
+
+BIND_TO
+ Which IP address should we bind to? E.g. ``127.0.0.1`` or ``::1``for loopback. Can also be given as a hostname.
+ Only used if ``SERVE`` is ``tcp``.
+
+UNIXPATH
+ Which unix domain path should we bind to?
+ Only used if ``SERVE`` is ``unix``.
+
+UNIXPATH_MODE
+ What should be the file access permissions for ``UNIXPATH``?
+ Only used if ``SERVE`` is ``unix``.
+
+DATABASE OPTIONS
+----------------
+
+Setting the database belongs to the “[libeufin-bankdb-postgres]” section and the
+following value.
+
+CONFIG
+ PostgreSQL connection string.
+
+SQL_DIR
+ Where are the SQL files to setup our tables?
+
+SEE ALSO
+========
+
+libeufin-bank(1).
+
+BUGS
+====
+
+Report bugs by using https://bugs.taler.net/ or by sending electronic
+mail to <taler@gnu.org>.
diff --git a/manpages/libeufin-nexus.1.rst b/manpages/libeufin-nexus.1.rst
index 792c1de6..a0ed99ff 100644
--- a/manpages/libeufin-nexus.1.rst
+++ b/manpages/libeufin-nexus.1.rst
@@ -6,7 +6,7 @@ libeufin-nexus(1)
Name
====
- **libeufin-nexus** - Service to interface to various bank access APIs
+ **libeufin-nexus** - EBICS client.
Synopsis
@@ -17,21 +17,14 @@ Synopsis
[**--version**]
COMMAND [ARGS...]
-Commands: serve, superuser, parse-camt, reset-tables
+Subcommands: **dbinit**, **ebics-setup**, **ebics-submit**, **ebics-fetch**, **config**
Description
===========
**libeufin-nexus** is a program that provides a service to interface to
-various bank access APIs, using JSON as the response format.
-It maintains state in its own private database.
-You interact with it through HTTP
-requests either over the network or via a Unix domain socket.
-Related program **libeufin-cli** is the preferred front end
-for that mode of operation.
-There is also a mode where **libeufin-nexus** accepts commands directly,
-useful for doing administrative tasks.
+various bank access APIs
Its options are as follows:
@@ -43,108 +36,119 @@ Its options are as follows:
The interaction model is as follows:
-- Configure the nexus with command ``superuser``.
-
-- Start the HTTP server with command ``serve``.
- Let this run in a shell, writing logs to stderr.
-
-- Interact with **libeufin-nexus**.
-
-- When finished, interrupt the ``serve`` process and clean up with command
- ``reset-tables``.
+In order to operate any EBICS communication with ``libeufin-nexus``, it is necessary to setup EBICS access via the ``ebics-setup`` subcommand. Setting the access means to share the client keys with the bank and downloading the bank keys. After a successful setup, the subcommands ``ebics-submit`` and ``ebics-fetch`` can be run to respectively send payments and download the bank account history.
The following sections describe each command in detail.
+ebics-setup
+-----------
-superuser
----------
-
-This command adds a superuser, or changes the password.
-It takes argument ``USERNAME``.
-Option ``--password TEXT`` specifies the password.
-If omitted, **libeufin-nexus** will query interactively for it.
-
-For example:
-
-.. code-block:: console
+This command creates the client keys, if they aren't found already on the disk, and sends them to the bank if they were not sent yet. In case of sending, it ejects the PDF document that contains the keys fingerprints, so that the user can send it to the bank to confirm their keys. The process continues by checking if the bank keys exist already on disk, and proceeds with downloading them in case they are not. It checks then if the bank keys were accepted by the user; if yes, the setup terminates, otherwise it interactively asks the user to mark the keys as accepted. By accepting the bank keys, the setup terminates successfully.
- $ libeufin-nexus superuser joe
+Its options are as follows:
-This creates superuser ``joe`` and interactively queries for the password.
+**-h** \| **--help**
+ Print short help on options.
+**-c** \| **--config** *FILENAME*
+ Specifies the configuration file.
+**-L** \| **--log** *LOGLEVEL*
+ Configure logging to use LOGLEVEL.
+**--force-keys-resubmission**
+ Resubmits the client keys. If no keys were found, it creates and submits them.
+**--auto-accept-keys**
+ Accepts the bank keys without interactively asking the user.
+**--generate-registration-pdf**
+ Generates the PDF with the client keys fingerprints, if the keys have the submitted state. That's useful in case the PDF went lost after the first submission and the user needs a new PDF.
-parse-camt
-----------
+dbinit
+------
-This command parses a camt file and displays the result to stdout.
-It takes argument ``FILENAME``, which names a file in CAMT format.
-Parsing may also display log information to stderr.
-The normal log level is ``DEBUG``.
-To change it, use ``--log-level LEVEL``, where ``LEVEL`` is one of:
-``ERROR``, ``WARN``, ``INFO``, ``DEBUG``, ``TRACE``.
+This subcommand defines the database schema for Nexus. It is mandatory to run this command before invoking the ``ebics-submit`` or ``ebics-fetch`` subcommands.
-For example:
+Its options are as follows:
-.. code-block:: console
+**-h** \| **--help**
+ Print short help on options.
+**-c** \| **--config** *FILENAME*
+ Specifies the configuration file.
+**-L** \| **--log** *LOGLEVEL*
+ Configure logging to use LOGLEVEL.
+**-r** \| **--reset**
+ If present, deletes any database table (WARNING: potential data loss)
- $ libeufin-nexus parse-camt camt53-gls-style-0.xml
- {
- "transactions" : [ {
- "amount" : "EUR:2.35",
- "creditDebitIndicator" : "DBIT",
- ...
- } ]
- }
+ebics-submit
+------------
-serve
------
+This subcommand submits any initiated payment that was not already sent to the bank. In the current version, initiated payments may come from a cash-out operation or from a bounced incoming payment. ebics-submit is Taler friendly, therefore bounced payments are those that do not contain a valid subject to start a Taler withdrawal. Cash-out operations come from a tightly integrated bank that offers their customers to convert their currency to the currency whose the EBICS subscriber bank account is tied to.
-This command starts the HTTP server, listening on port 5001.
-To use a different port, use option ``--port INT``.
-To listen, instead, on a Unix domain socket,
-use option ``--with-unix-socket PATH``.
-When both ``--port`` and ``--with-unix-socket`` are given,
-``--with-unix-socket`` takes precedence.
+Its options are as follows:
-The process runs in the foreground, writing its logs to standard error.
-The normal log level is ``DEBUG``.
-To change it, use ``--log-level LEVEL``, where ``LEVEL`` is one of:
-``ERROR``, ``WARN``, ``INFO``, ``DEBUG``, ``TRACE``.
+**-h** \| **--help**
+ Print short help on options.
+**-c** \| **--config** *FILENAME*
+ Specifies the configuration file.
+**-L** \| **--log** *LOGLEVEL*
+ Configure logging to use LOGLEVEL.
+ Uploaded documents will be stored *before* being submitted to the bank. This directory would contain several directories, each named after the ``YYYY-MM-DD/submit`` format. The pain.001 file would then be named in the following schema: ``$microseconds_pain.001.xml``.
+**--transient**
+ This flag, enabled by default, causes the command to check the database and submit only once, and then return.
-Before invoking ``serve``, the following environment variable needs to be set:
-``LIBEUFIN_NEXUS_DB_CONNECTION``
- This specifies the database **libeufin-nexus** uses to maintain state.
- Currently, both Sqlite and PostgreSQL are supported.
- (Only one needs to be specified.)
- Examples:
+ebics-fetch
+-----------
- - ``jdbc:sqlite:/tmp/libeufin-nexus.db``
- - ``jdbc:postgresql://localhost:5432/libeufindb?user=Foo&password=secret``
+This subcommand downloads and parse EBICS files and ingest them into the database. Along the download, ebics-fetch would bounce incoming payments that do not have a valid Taler subject, or as well those with an already existing valid subject. Valid incoming payments are then stored in the database so that they can trigger Taler withdrawals. Along this process, ebics-submit would as well reconcile initiated outgoing payments with any outgoing transactions that show up in the downloaded records.
-Normally, the ``serve`` command runs until interrupted.
-When run in a shell, you can use ``Control-C`` for that.
+The files type can be given as an argument to select what will be fetched. If no argument is given, all supported files are fetched. The following files are supported:
+* ``acknowledgement``: EBICS acknowledgement, retrieves the status of EBICS orders.
+* ``status``: Payment status, retrieves status of pending debits.
+* ``notification``: Debit & credit notifications, retrieves the history of confirmed debits and credits.
-reset-tables
-------------
+**-h** \| **--help**
+ Print short help on options.
+**-c** \| **--config** *FILENAME*
+ Specifies the configuration file.
+**-L** \| **--log** *LOGLEVEL*
+ Configure logging to use LOGLEVEL.
+**--debug-ebics** *SAVEDIR*
+ Log EBICS content at SAVEDIR.
+ Downloaded documents will be stored *before* being ingested in the database. This directory would contain several directories, each named after the ``YYYY-MM-DD/fetch`` format. The stored files would then be named after the following schema: ``$microseconds_$filename``. Exception to this naming scheme are the HAC responses, since they do not get any filename assigned by the ZIP archive (they are sent unzipped). Their naming scheme is: ``$microseconds_HAC_response.pain.002.xml``.
+**--transient**
+ This flag, enabled by default, causes the command to perform one download and return.
+**--pinned-start**
+ Only supported in --transient mode, this option lets specify the earliest timestamp of the downloaded documents. The latest timestamp is always the current time.
-This command drops all the tables in the internal database.
-(The next time the tables are needed, **libeufin-nexus** creates them
-again, automatically.)
+initiate-payment
+----------------
-It should only be used when the nexus is quiescent.
+This subcommand initiates an outgoing payment. The pending payment is stored in the database and will be performed the next time ``ebics-submit`` run.
+It takes one argument, the creditor IBAN payto URI, which must contain a 'receiver-name' and may contain an 'amount' and a 'message' if they have not been defined using CLI options.
-See Also
+**-h** \| **--help**
+ Print short help on options.
+**-c** \| **--config** *FILENAME*
+ Specifies the configuration file.
+**-L** \| **--log** *LOGLEVEL*
+ Configure logging to use LOGLEVEL.
+**--amount** *AMOUNT*
+ The amount to transfer, payto 'amount' parameter takes the precedence
+**--subject** *TEXT*
+ The payment subject, payto 'message' parameter takes the precedence
+**--request-uid** *TEXT*
+ The payment request UID, will be randomly generated if missing.
+
+.. include:: ../frags/libeufin-config-cli.rst
+
+SEE ALSO
========
-.. TODO: libeufin-sandbox(1), libeufin-cli(1).
-
+libeufin-nexus.conf(5)
Bugs
====
-Report bugs by using https://bugs.taler.net or by sending electronic
-mail to <taler@gnu.org>.
+Report bugs by using https://bugs.taler.net or by sending electronic mail to <taler@gnu.org>.
diff --git a/manpages/libeufin-nexus.conf.5.rst b/manpages/libeufin-nexus.conf.5.rst
new file mode 100644
index 00000000..e70ff7b3
--- /dev/null
+++ b/manpages/libeufin-nexus.conf.5.rst
@@ -0,0 +1,187 @@
+libeufin-nexus.conf(5)
+######################
+
+.. only:: html
+
+ Name
+ ====
+
+ **libeufin-nexus.conf** - LibEuFin Nexus configuration file
+
+
+Description
+===========
+
+The configuration file is line-oriented. Blank lines and whitespace at the
+beginning and end of a line are ignored. Comments start with ``#`` or ``%``
+in the first column (after any beginning-of-line whitespace) and go to the end
+of the line.
+
+The file is split into sections. Every section begins with ``[SECTIONNAME]``
+and contains a number of options of the form ``OPTION=VALUE``. There may be
+whitespace around the ``=`` (equal sign). Section names and options are
+*case-insensitive*.
+
+The values, however, are *case-sensitive*. In particular, boolean values are
+one of ``YES`` or ``NO``. Values can include whitespace by surrounding the
+entire value with ``"`` (double quote). Note, however, that there are no
+escape characters in such strings; all characters between the double quotes
+(including other double quotes) are taken verbatim.
+
+Durations must be expressed with a number followed by the time unit. The following
+time units are supported: 's' (seconds), 'm' (minutes), 'h' (hours). For example,
+the value *5m* denotes a duration of *five minutes*.
+
+Values that represent filenames can begin with a ``/bin/sh``-like variable
+reference. This can be simple, such as ``$TMPDIR/foo``, or complex, such as
+``${TMPDIR:-${TMP:-/tmp}}/foo``. The variables are expanded either using
+key-values from the ``[PATHS]`` section (see below) or from the environment
+(``getenv()``). The values from ``[PATHS]`` take precedence over those from
+the environment. If the variable name is found in neither ``[PATHS]`` nor the
+environment, a warning is printed and the value is left unchanged. Variables (including those from the environment) are expanded recursively, so if ``FOO=$BAR`` and ``BAR=buzz`` then the result is ``FOO=buzz``. Recursion is bounded to at most 128 levels to avoid undefined behavior for mutually recursive expansions like if ``BAR=$FOO`` in the example above.
+
+The ``[PATHS]`` section is special in that it contains paths that can be
+referenced using ``$`` in other configuration values that specify
+*filenames*. Note that configuration options that are not specifically
+retrieved by the application as *filenames* will not see “$”-expressions
+expanded. To expand ``$``-expressions when using ``taler-config``, you must pass
+the ``-f`` command-line option.
+
+The system automatically pre-populates the ``[PATHS]`` section with a few values
+at run-time (in addition to the values that are in the actual configuration
+file and automatically overwriting those values if they are present).
+These automatically generated values refer to installation properties
+from `GNU autoconf
+<https://www.gnu.org/prep/standards/html_node/Directory-Variables.html>`_. The
+values are usually dependent on an ``INSTALL_PREFIX`` which is determined by
+the ``--prefix`` option given to configure. The canonical values are:
+
+ * LIBEXECDIR = $INSTALL_PREFIX/taler/libexec/
+ * DOCDIR = $INSTALL_PREFIX/share/doc/taler/
+ * ICONDIR = $INSTALL_PREFIX/share/icons/
+ * LOCALEDIR = $INSTALL_PREFIX/share/locale/
+ * PREFIX = $INSTALL_PREFIX/
+ * BINDIR = $INSTALL_PREFIX/bin/
+ * LIBDIR = $INSTALL_PREFIX/lib/taler/
+ * DATADIR = $INSTALL_PREFIX/share/taler/
+
+Note that on some platforms, the given paths may differ depending
+on how the system was compiled or installed, the above are just the
+canonical locations of the various resources. These
+automatically generated values are never written to disk.
+
+Files containing default values for many of the options described below
+are installed under ``$TALER_PREFIX/share/libeufin-nexus/config.d/``.
+The configuration file given with **-c** to Taler binaries
+overrides these defaults.
+
+A configuration file may include another, by using the ``@INLINE@`` directive,
+for example, in ``main.conf``, you could write ``@INLINE@ sub.conf`` to
+include the entirety of ``sub.conf`` at that point in ``main.conf``.
+
+Be extra careful when using ``taler-config -V VALUE`` to change configuration
+values: it will destroy all uses of ``@INLINE@`` and furthermore remove all
+comments from the configuration file!
+
+GLOBAL OPTIONS
+--------------
+
+Setting the database belongs to the “[nexus-postgres]” section and the
+following value.
+
+CONFIG
+ PostgreSQL connection string. Note: this option is NOT used by the
+ ebics-setup subcommand, as it stores the key files directly on the
+ filesystem.
+
+The “[paths]” section is special in that it contains paths that can be
+referenced using “$” in other configuration values that specify
+filenames. For Taler, it commonly contains the following paths:
+
+LIBEUFIN_HOME
+ Home directory of the user, usually “${HOME}”. Can be overwritten by
+ testcases by setting ${LIBEUFIN_TEST_HOME}.
+
+EBICS SETUP OPTIONS
+-------------------
+
+The following options are from the “[nexus-ebics]” section and used by
+the ``libeufin-nexus ebics-setup`` command.
+
+CURRENCY
+ Name of the currency, e.g. “EUR” for Euro.
+
+HOST_BASE_URL
+ URL of the EBICS server
+
+BANK_DIALECT
+ Name of the following combination: EBICS version and ISO20022 recommendations
+ that Nexus would honor in the communication with the bank. Currently only the
+ 'postfinance' value is supported.
+
+HOST_ID
+ EBICS specific: name of the EBICS host
+
+USER_ID
+ EBICS specific: user ID of the EBICS subscriber. This value must be assigned
+ by the bank after having activated a new EBICS subscriber.
+
+PARTNER_ID
+ EBICS specific: partner ID of the EBICS subscriber. This value must be assigned
+ by the bank after having activated a new EBICS subscriber.
+
+BANK_PUBLIC_KEYS_FILE
+ Filesystem location where Nexus should store the bank public keys.
+
+CLIENT_PRIVATE_KEYS_FILE
+ Filesystem location where Nexus should store the subscriber private keys.
+
+IBAN
+ IBAN of the bank account that is associated with the EBICS subscriber.
+
+BIC
+ BIC of the bank account that is associated with the EBICS subscriber.
+
+NAME
+ Legal entity that is associated with the EBICS subscriber.
+
+
+EBICS SUBMIT OPTIONS
+--------------------
+
+The following configuration value(s) belong to the “[nexus-submit]” section.
+
+FREQUENCY
+ Duration value to instruct the ``ebics-submit`` subcommand how much to wait
+ before checking the database again to find new unsubmitted payments.
+
+EBICS FETCH OPTIONS
+-------------------
+
+The following configuration value(s) belong to the “[nexus-fetch]” section.
+
+FREQUENCY
+ Duration value to instruct the ``ebics-fetch`` subcommand how often it should
+ download from the bank.
+
+DATABASE OPTIONS
+----------------
+
+Setting the database belongs to the “[libeufin-nexusdb-postgres]” section and the following value.
+
+CONFIG
+ PostgreSQL connection string.
+
+SQL_DIR
+ Where are the SQL files to setup our tables?
+
+SEE ALSO
+========
+
+libeufin-nexus(1)
+
+BUGS
+====
+
+Report bugs by using https://bugs.taler.net/ or by sending electronic
+mail to <taler@gnu.org>.
diff --git a/manpages/libeufin-sandbox.1.rst b/manpages/libeufin-sandbox.1.rst
index e073500e..6f0948d0 100644
--- a/manpages/libeufin-sandbox.1.rst
+++ b/manpages/libeufin-sandbox.1.rst
@@ -70,16 +70,16 @@ config
This command takes argument ``NAME`` and creates a demobank with that name.
-Option ``--currency CUR`` (default: ``EUR``) specifes another currency.
+Option ``--currency CUR`` (default: ``EUR``) specifies another currency.
Option ``--captcha-url $URL`` specifies where the wallet user is going
-to be redirected to confirm the withdrawal operation. This $URL should
+to be redirected to confirm the withdrawal operation. This $URL should
point to the bank frontend. More precisely to the UI that let the user
finish a withdrawal operation that needs to be confirmed. Example of
-this value may be "https://bank.domain/#/operation/{wopid}" where
+this value may be "https://bank.domain/#/operation/{wopid}" where
"https://bank.domain" returns the demobank SPA and the demobank view under
the route "/operation/{wopid}" will show the status of the operation id {wopid}.
Note that "{wopid}" is literally in the --captcha-url config and replaced at
-runtime by the sandbox server.
+runtime by the sandbox server.
Option ``--bank-debt-limit N`` (default: 1000000) specifies that
the bank debt limit should be N (units of currency).
Similarly, option ``--users-debt-limit N`` (default: 1000) specifies
diff --git a/manpages/taler-config.1.rst b/manpages/taler-config.1.rst
index 14a8959b..abc10dd6 100644
--- a/manpages/taler-config.1.rst
+++ b/manpages/taler-config.1.rst
@@ -83,6 +83,7 @@ Description
Note:
Changing the configuration file with ``-V`` will remove comments
and may reorder sections and remove ``@INLINE@`` directives.
+ Using **-V** is thus dangerous! Use with extreme caution!
**-v** \| **--version**
Print GNU Taler version number.
diff --git a/manpages/taler-exchange-offline.1.rst b/manpages/taler-exchange-offline.1.rst
index f14e29e8..378c6312 100644
--- a/manpages/taler-exchange-offline.1.rst
+++ b/manpages/taler-exchange-offline.1.rst
@@ -259,7 +259,7 @@ enable-account
--------------
This subcommand informs an exchange that it should advertise a bank account as
-belonging to the exchange on its ``/wire`` endpoint. Note that this does
+belonging to the exchange on its ``/keys`` endpoint. Note that this does
*not* ensure that the exchange will use this bank account for incoming or
outgoing wire transfers! For this, the **taler-exchange-transfer** and
**taler-exchange-wirewatch** tools must be configured. Furthermore, the bank
@@ -316,7 +316,7 @@ disable-account
This subcommand
informs an exchange that it should stop advertising a bank account as
-belonging to the exchange on its ``/wire`` endpoint.
+belonging to the exchange on its ``/keys`` endpoint.
The ``payto://`` URI (RFC 8905) of the exchange's (former) bank account must be
given as the first argument to the subcommand.
diff --git a/manpages/taler-mdb.1.rst b/manpages/taler-mdb.1.rst
new file mode 100644
index 00000000..5e6f86d2
--- /dev/null
+++ b/manpages/taler-mdb.1.rst
@@ -0,0 +1,73 @@
+taler-mdb(1)
+############
+
+.. only:: html
+
+ Name
+ ====
+
+ **taler-mdb** - Taler multi-drop bus vending machine integration
+
+
+Synopsis
+========
+
+**taler-mdb**
+[**-c** *FILENAME* | **--config=**\ ‌\ *FILENAME*]
+[**-d** | **--disable-mdb**]
+[**-h** | **--help**]
+[**-i** | **--backlight-invert**]
+[**-L** _*LOGLEVEL* | **--log=**\ \ *LOGLEVEL*]
+[**-l** _*FILENAME* | **--logfile=**\ \ *FILENAME*]
+[**-s** | **--enable-soldout**]
+[**-t** | **--disable-tty**]
+[**-v** | **--version**]
+
+
+Description
+===========
+
+**taler-mdb** is a command-line tool to operate a vending machine using GNU Taler for payments.
+
+Its options are as follows:
+
+**-c** *FILENAME* \| **--config=**\ ‌\ *FILENAME*
+ Use the configuration and other resources for the Sync commands
+ to operate from *FILENAME*.
+
+**-d** \| **--disable-mdb**
+ Disable interaction with the MDB bus (for testing).
+
+**-h** \| **--help**
+ Print short help on options.
+
+**-i** \| **--backlight-invert**
+ Invert the bit for turning on/off the backlight.
+
+**-L** *LOGLEVEL* \| **--log=**\ \ *LOGLEVEL*
+ Configure logging to use *LOGLEVEL*.
+
+**-l** *FILENAME* \| **--logfile=**\ \ *FILENAME*
+ Configure logging to write logs to *FILENAME*.
+
+**-s** \| **--enable-soldout**
+ When the machine fails to dispense a product, internally set the product to "sold out" and refuse future orders until restarted.
+
+**-t** \| **--disable-tty**
+ Disable interactive command-line use.
+
+**-v** \| **–version**
+ Print version information.
+
+
+See Also
+========
+
+taler-merchant-httpd(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-depositcheck.1.rst b/manpages/taler-merchant-depositcheck.1.rst
new file mode 100644
index 00000000..e243f0d2
--- /dev/null
+++ b/manpages/taler-merchant-depositcheck.1.rst
@@ -0,0 +1,78 @@
+taler-merchant-depositcheck(1)
+##############################
+
+.. only:: html
+
+ Name
+ ====
+
+ **taler-merchant-depositcheck** - check if deposits are associated with wire transfers
+
+
+Synopsis
+========
+
+**taler-merchant-depositcheck**
+[**-c** *FILENAME* | **--config=**\ ‌\ *FILENAME*]
+[**-e** *BASE_URL* | **--exchange=**\ \ *BASE_URL*]
+[**-h** | **--help**]
+[**-L** *LOGLEVEL* | **--loglevel=**\ ‌\ *LOGLEVEL*]
+[**-l** *FILENAME* | **--logfile=**\ ‌\ *FILENAME*]
+[**-T** *USEC* | **--timetravel**\ \ *USEC*]
+[**-t** | **--test**]
+[**-v** | **--version**]
+
+Description
+===========
+
+**taler-merchant-depositcheck** is a command-line tool to inquire with exchanges about whether they completed
+bank transfers in response to deposits made by the
+merchant backend. This will allow the merchant backend to detect deposit issues, for example if a KYC is blocking
+a wire transfer.
+
+Its options are as follows:
+
+**-c** *FILENAME* \| **--config=**\ ‌\ *FILENAME*
+ Use the configuration and other resources for the merchant to operate
+ from *FILENAME*.
+
+**-e** *BASE_URL* \| **--exchange=**\ ‌\ *BASE_URL*
+ Base URL of the exchange to monitor. If not given, a worker process will be spawned for each exchange in the configuration ("merchant-exchange-" sections).
+
+**-h** \| **--help**
+ Print short help on options.
+
+**-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*.
+
+**-s** *SECTION* \| **--section=**\ \ *SECTION*
+ Configuration section to use. Default is taler-merchant-depositcheck. Needed
+ if different processes are used to watch multiple bank accounts (for the
+ same instance or different instances).
+
+**-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.
+
+**-t** \| **--test**
+ Run in test mode. Only runs until the current list of bank
+ transactions are all imported.
+
+**-v** \| **–version**
+ Print version information.
+
+See Also
+========
+
+taler-merchant-httpd(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-exchange.1.rst b/manpages/taler-merchant-exchange.1.rst
new file mode 100644
index 00000000..de2b571f
--- /dev/null
+++ b/manpages/taler-merchant-exchange.1.rst
@@ -0,0 +1,73 @@
+taler-merchant-exchange(1)
+##########################
+
+.. only:: html
+
+ Name
+ ====
+
+ **taler-merchant-exchange** - reconcile bank transfers with Taler exchange
+
+
+Synopsis
+========
+
+**taler-merchant-exchange**
+[**-c** *FILENAME* | **--config=**\ ‌\ *FILENAME*]
+[**-h** | **--help**]
+[**-L** *LOGLEVEL* | **--loglevel=**\ ‌\ *LOGLEVEL*]
+[**-l** *FILENAME* | **--logfile=**\ ‌\ *FILENAME*]
+[**-T** *USEC* | **--timetravel**\ \ *USEC*]
+[**-t** | **--test**]
+[**-v** | **--version**]
+
+Description
+===========
+
+**taler-merchant-exchange** is a background job that reconciles
+wire transfers that credit the merchant's bank account with
+the respective contracts that have been paid by asking the
+exchange to provide a list of all deposits that were aggregated
+into a wire transfer.
+
+The tool is part of a set of processes that allow a merchant backend to
+validate that the exchange paid the merchant correctly.
+
+Its options are as follows:
+
+**-c** *FILENAME* \| **--config=**\ ‌\ *FILENAME*
+ Use the configuration and other resources for the merchant to operate
+ from *FILENAME*.
+
+**-h** \| **--help**
+ Print short help on options.
+
+**-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*.
+
+**-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.
+
+**-t** \| **--test**
+ Run in test mode. Only runs until the current list of bank
+ transactions have all been checked.
+
+**-v** \| **–version**
+ Print version information.
+
+See Also
+========
+
+taler-merchant-depositcheck(1), taler-merchant-wirewatch(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-setup-reserve.1.rst b/manpages/taler-merchant-setup-reserve.1.rst
deleted file mode 100644
index 73fa2a0c..00000000
--- a/manpages/taler-merchant-setup-reserve.1.rst
+++ /dev/null
@@ -1,119 +0,0 @@
-taler-merchant-setup-reserve(1)
-###############################
-
-
-.. only:: html
-
- Name
- ====
-
- **taler-merchant-setup-reserve** - setup reserve for rewards
-
-
-Synopsis
-========
-
-**taler-merchant-setup-reserve**
-[**-A** *USERNAME:PASSWORD* | **--auth=**\ \ *USERNAME:PASSWORD*]
-[**-a** *VALUE* | **--amount=**\ \ *VALUE*]
-[**-C** *CERTFILE* | **--cert=**\ \ *CERTFILE*]
-[**-c** *FILENAME* | **--config=**\ \ *FILENAME*]
-[**-e** *URL* | **--exchange-url=**\ \ *URL*]
-[**-h** | **--help**]
-[**-k** *KEYFILE* | **--key=**\ \ *KEYFILE*]
-[**-L** *LOGLEVEL* | **--loglevel=**\ ‌\ *LOGLEVEL*]
-[**-l** *FILENAME* | **--logfile=**\ ‌\ *FILENAME*]
-[**-m** *URL* | **--merchant-url=**\ \ *URL*]
-[**-p** *KEYFILEPASSPHRASE* | **--pass=**\ \ *KEYFILEPASSPHRASE*]
-[**-t** *CERTTYPE* | **--type=**\ \ *CERTTYPE*]
-[**-w** *METHOD* | **--wire-method=**\ \ *METHOD*]
-[**-v** | **--version**]
-
-
-Description
-===========
-
-**taler-merchant-setup-reserve** is a command-line tool to setup a reserve
-(creating the private reserve key) and obtaining the wire transfer information
-from the exchange needed to fill the reserve.
-
-
-Options
-=======
-
-**-A** *USERNAME:PASSWORD* \| **--auth=**\ \ *USERNAME:PASSWORD*
- Use ``USERNAME`` and ``PASSWORD`` for HTTP client authentication.
- The ":" must be present as a separator.
- Note that this form of authentication has nothing to do with the TLS client
- certificate authentication supported with the ``-C``, ``-k`` and ``-p`` options.
- The ``PASSWORD`` given to this option is given to the server!
-
-**-a** *VALUE* \| **--amount=**\ \ *VALUE*
- Mandatory.
- Amount to be transferred to the reserve.
-
-**-C** *CERTFILE* \| **--cert=**\ \ *CERTFILE*
- The specified ``CERTFILE`` contains a TLS client certificate to be used to
- authenticate the client. See also ``-t``.
-
-**-c** *FILENAME* \| **--config=**\ \ *FILENAME*
- Use the configuration and other resources for the merchant to
- operate from ``FILENAME``.
-
-**-e** *URL* \| **--exchange-url=**\ \ *URL*
- Mandatory.
- Use ``URL`` for the exchange base URL.
- This is the exchange where the reserve will be created.
- The currency used in the amount specification must be offered by this exchange.
-
-**-h** \| **--help**
- Print short help on options.
-
-**-k** *KEYFILE* \| **--key=**\ \ *KEYFILE*
- The specified ``KEYFILE`` contains a TLS client private key to be used to
- authenticate the client. See also ``-p`` and ``-C``.
-
-**-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** *URL* \| **--merchant-url=**\ \ *URL*
- Mandatory.
- Use ``URL`` as the merchant base URL.
- Should include the path to the instance if the reserve is to be
- created for a non-default instance.
-
-**-p** *KEYFILEPASSPHRASE* \| **--pass=**\ \ *KEYFILEPASSPHRASE*
- The specified ``KEYFILEPASSPHRASE`` is to be used to decrypt the KEYFILE.
- See also ``-k``. Not to be confused with ``-A``.
- The ``KEYFILEPASSPHRASE`` given here is only used locally to decrypt the KEYFILE.
-
-**-t** *CERTTYPE* \| **--type=**\ \ *CERTTYPE*
- The specified CERTFILE contains a TLS client certificate of ``CERTTYPE``.
- Default is ``PEM``. See also ``-C``.
-
-**-w** *METHOD* \| **--wire-method=**\ \ *METHOD*
- Mandatory.
- Which wire method should be used.
- Needed to select the wire transfer method of the exchange.
- The method must be supported by the exchange.
- Typical values would be ``iban`` or ``x-taler-bank``.
-
-**-v** \| **--version**
- Print version information.
-
-
-See Also
-========
-
-taler-merchant-dbinit(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-webhook.1.rst b/manpages/taler-merchant-webhook.1.rst
index 314c574a..c3a71509 100644
--- a/manpages/taler-merchant-webhook.1.rst
+++ b/manpages/taler-merchant-webhook.1.rst
@@ -17,6 +17,7 @@ Synopsis
[**-h** | **--help**]
[**-L** *LOGLEVEL* | **--loglevel=**\ ‌\ *LOGLEVEL*]
[**-l** *FILENAME* | **--logfile=**\ ‌\ *FILENAME*]
+[**-T** *USEC* | **--timetravel**\ \ *USEC*]
[**-t** | **--test**]
[**-v** | **--version**]
@@ -43,6 +44,11 @@ Its options are as follows:
**-l** *FILENAME* \| **--logfile=**\ ‌\ *FILENAME*
Send logging output to *FILENAME*.
+**-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.
+
**-t** \| **--test**
Run in test mode. Only runs until there are no more webhooks
to be executed.
diff --git a/manpages/taler-merchant-wirewatch.1.rst b/manpages/taler-merchant-wirewatch.1.rst
index 54daa767..e2f9d1df 100644
--- a/manpages/taler-merchant-wirewatch.1.rst
+++ b/manpages/taler-merchant-wirewatch.1.rst
@@ -17,6 +17,8 @@ Synopsis
[**-h** | **--help**]
[**-L** *LOGLEVEL* | **--loglevel=**\ ‌\ *LOGLEVEL*]
[**-l** *FILENAME* | **--logfile=**\ ‌\ *FILENAME*]
+[**-p** | **--persist**]
+[**-T** *USEC* | **--timetravel**\ \ *USEC*]
[**-t** | **--test**]
[**-v** | **--version**]
@@ -44,11 +46,19 @@ Its options are as follows:
**-l** *FILENAME* \| **--logfile=**\ ‌\ *FILENAME*
Send logging output to *FILENAME*.
+**-p** \| **--persist**
+ Run in persist mode. Does not exit when the account configuration changes. Useful when not running under systemd.
+
**-s** *SECTION* \| **--section=**\ \ *SECTION*
Configuration section to use. Default is taler-merchant-wirewatch. Needed
if different processes are used to watch multiple bank accounts (for the
same instance or different instances).
+**-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.
+
**-t** \| **--test**
Run in test mode. Only runs until the current list of bank
transactions are all imported.
diff --git a/manpages/taler-terms-generator.1.rst b/manpages/taler-terms-generator.1.rst
index c95221d5..d6c22411 100644
--- a/manpages/taler-terms-generator.1.rst
+++ b/manpages/taler-terms-generator.1.rst
@@ -47,6 +47,9 @@ Description
**-l** *LANGUAGE*
Add the given *LANGUAGE* to the list of translations for the current *INPUT*. *LANGUAGE* must be a two-letter language code (like "de" or "it"). This will generate or update the respective ".po" files to translate the *INPUT* terms to this *LANGUAGE*.
+**-L** *LOCALE_DIR*
+ Specify locale/ directory where GNU gettext resources for translating the input are located. If "-l" is given, this directory is where fresh or updated ".po" files will be placed, and otherwise this directory will be scanned for translations of the ".rst" input file.
+
**-o** *OUTPUT*
Specifies where to write the output. This should be the directory where the service expects to find the generated resources. Unless you changed the default configuration, you probably do not have to specify this value.
diff --git a/manpages/taler-unified-setup.1.rst b/manpages/taler-unified-setup.1.rst
index 02d09879..fe60d1e5 100644
--- a/manpages/taler-unified-setup.1.rst
+++ b/manpages/taler-unified-setup.1.rst
@@ -21,6 +21,7 @@ Synopsis
[**-e**]
[**-f**]
[**-h**]
+[**-k**]
[**-l** *FILENAME*]
[**-m**]
[**-n**]
@@ -64,6 +65,9 @@ systemd and not via this tool.
**-h** \| **--help**
Prints a compiled-in help text.
+**-k**
+ Start challenger (KYC service)
+
**-L** *LOGLEVEL*
Specifies the log level to use. Accepted values are: ``DEBUG``, ``INFO``,
``WARNING``, ``ERROR``.
@@ -97,7 +101,7 @@ See Also
========
taler-exchange-dbinit(1), taler-exchange-offline(1), taler-merchant-benchmark(1),
-taler-exchange-httpd(1), taler-unified-setup(1), taler.conf(5)
+taler-exchange-httpd(1), taler.conf(5)
Bugs
====
diff --git a/manpages/taler-wallet-cli.1.rst b/manpages/taler-wallet-cli.1.rst
index 2d35bb87..dad790f5 100644
--- a/manpages/taler-wallet-cli.1.rst
+++ b/manpages/taler-wallet-cli.1.rst
@@ -46,8 +46,6 @@ for testing.
**withdraw-uri** URI
-**reward-uri** URI
-
**refund-uri** URI
**pay-uri** [**-y** | **--yes**] URI
diff --git a/manpages/taler.conf.5.rst b/manpages/taler.conf.5.rst
index fb443f80..3748b673 100644
--- a/manpages/taler.conf.5.rst
+++ b/manpages/taler.conf.5.rst
@@ -98,10 +98,6 @@ NAME
Long human-readable name for the currency. No restrictions,
but should match the official name in English.
-DECIMAL_SEPARATOR
- What symbol should be used to separate fractional digits.
- Typical values are "." or ",".
-
FRACTIONAL_INPUT_DIGITS
Number of fractional digits that users are allowed to enter
manually in the user interface.
@@ -117,11 +113,6 @@ FRACTIONAL_TRAILING_ZERO_DIGITS
even if these digits are all zero. For example, use 2 to
render 1 USD as $1.00.
-IS_CURRENCY_NAME_LEADING
- When rendering amounts, should the currency name or symbol
- be before the amount ("$10") or after ("3,50 €"). Use "YES"
- to render the symbol before, "NO" to render it afterwards.
-
ALT_UNIT_NAMES
JSON map determining how to encode very large or very tiny
amounts in this currency. Maps a base10 logarithm to the
@@ -160,7 +151,9 @@ BIND_TO
MASTER_PUBLIC_KEY
Crockford Base32-encoded master public key, public version of the
- exchange's long-time offline signing key.
+ exchange's long-time offline signing key. This configuration option
+ is also used by the **auditor** to determine the public key of the
+ exchange which it is auditing.
AML_THRESHOLD
Largest amount in this currency that can be transferred per month without
@@ -169,15 +162,8 @@ AML_THRESHOLD
KYC_AML_TRIGGER
Program to run on KYC attribute data to decide whether we should immediately flag an account for AML review. Program must return 0 if a manual AML review is not needed, and non-zero to trigger an AML review. The KYC attribute data of the new user will be passed on standard-input.
-ENABLE_REWARDS
- This option can be used to announce that an exchange does not allow
- the use of the reserves for rewards. The default is YES which means
- that rewards are allowed. The option merely announces that
- rewards is enabled or disabled, and protocol-compliant merchant
- backends will then enable or disable the feature accordingly.
-
STEFAN_ABS
- Absolte amount to add as an offset in the STEFAN fee approximation
+ Absolute amount to add as an offset in the STEFAN fee approximation
curve (see DD47). Defaults to CURRENCY:0 if not specified.
STEFAN_LOG
@@ -287,7 +273,7 @@ KYC_OAUTH2_VALIDITY
Duration (e.g. "12 months") of the validity of the performed KYC check. Can be "forever".
KYC_OAUTH2_AUTHORIZE_URL
- URL of the OAuth2 endpoint to be used for KYC checks. The authorize URL is where the exchange will redirect the client to begin the authorization process. Example: "http://localhost:8888/oauth/v2/authorize". To use the plugin in combination with the Challenger service's ``/setup`` step, append "#setup", thus "https://challenger.example.com/authorize#setup". Here, "#setup" is not a fragment but merely a hint to the logic to determine the full authorization URL via the ``/setup`` handler.
+ URL of the OAuth2 endpoint to be used for KYC checks. The authorize URL is where the exchange will redirect the client to begin the authorization process. Example: "http://localhost:8888/oauth/v2/authorize". To use the plugin in combination with the Challenger service's ``/setup`` step, append "#setup", thus "https://challenger.example.com/authorize#setup". Here, "#setup" is not a fragment but merely a hint to the logic to determine the full authorization URL via the ``/setup/$CLIENT_ID`` handler.
KYC_OAUTH2_TOKEN_URL
URL of the OAuth2 endpoint to be used for KYC checks. This is where the server will ultimately send the authorization token from the client and obtain its access token (which currently must be a "bearer" token). Example: "http://localhost:8888/oauth/v2/token" (or just "/token")
@@ -304,6 +290,15 @@ KYC_OAUTH2_CLIENT_SECRET
KYC_OAUTH2_POST_URL
URL to which the exchange will redirect the client's browser after successful authorization/login for the KYC process. Example: "http://example.com/thank-you"
+KYC_OAUTH2_CONVERTER_HELPER
+ Helper to convert JSON with KYC data returned by the OAuth2.0 info endpoint into GNU Taler internal format. Specific to the OAuth 2.0 provider.
+
+KYC_OAUTH2_DEBUG_MODE
+ Set to YES to allow error responses to include potentially
+ sensitive private information (such as full responses
+ from the OAuth 2.0 server) that might aid in debugging
+ problems. Should be set to "NO" in production.
+
EXCHANGE KYC KYCAID OPTIONS
^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -664,6 +659,9 @@ DB
SERVE
Should the HTTP server listen on a UNIX domain socket (set option to "unix") or on a TCP socket (set option to "tcp")?
+BASE_URL
+ Which base URL should the merchant backend assume for itself in the protocol. Optional. If not given, the base URL will be constructed from X-Forwarded-Host, X-Forwarded-Port and X-Forwarded-Prefix headers that a reverse-proxy should be setting.
+
UNIXPATH
Path to listen on if we "SERVE" is set to "unix".
@@ -787,6 +785,51 @@ RAM_LIMIT
This gives the number of transactions to keep in memory. Older transactions will be overwritten and history requests for overwritten transactions will fail.
+Taler-mdb Options
+-----------------
+
+Taler-mdb is a component to run GNU Taler as a payment system on
+vending machines using the multi-drop bus protocol. These options
+are thus not useful for most users. Note that right now, the
+cancel button is hard-coded to be using GPIO pin 23.
+
+ADVERTISEMENT_COMMAND
+ Program to run while not vending, possibly useful to show advertisements on the screen (optional).
+ESSID
+ ESSID to advertise to wallets for use as an open WiFi to make payments (optional).
+FULFILLMENT_MSG
+ Message shown to users by their wallets upon successful payment. If "${PRODUCT_DESCRIPTION}" appears in the message, it will be replaced with the description of the product that was sold.
+BACKEND_BASE_URL
+ Base URL (possibly including instance) for the Taler merchant backend used to process payments.
+BACKEND_AUTHORIZATION
+ Full HTTP "Authorization" header (usually with a Bearer token) to be send to the merchant backend for authorization of requests. Mandatory.
+FRAMEBUFFER_BACKLIGHT
+ Name of the file used to control brightness of the display. Optional. Defaults to "/sys/class/backlight/soc:backlight/brightness" if not given.
+FRAMEBUFFER_DEVICE
+ Name of the framebuffer device to use. Defaults to "/dev/fb1" if not given.
+UART_DEVICE
+ Name of the UART device to use. Defaults to "/dev/ttyAMA0" if not given.
+FAIL_COMMAND
+ Command to run to display a failure to the user. If not given, errors will not be properly shown.
+
+Each products being sold must be configured in a section where the name starts with "product-".
+In these sections, the options that must be provided are:
+
+NUMBER
+ Number identifying the slot in the vending machine that corresponds to this product.
+INSTANCE
+ Instance to use for the payment. Optional. If not given, the BACKEND_BASE_URL from "[taler-mdb]" will be used.
+BACKEND_AUTHORIZATION
+ Full HTTP "Authorization" header (usually with a Bearer token) to be send to the merchant backend for authorization of requests. Optional, will use global BACKEND_AUTHORIZATION setting from "[taler-mdb]" if missing.
+DESCRIPTION
+ Human-readable description of the product. Use "empty" if the product is known to be sold out (only effective if selling out is enabled via command-line).
+PRICE
+ Actual price of the product, as a Taler amount ("$CURRENCY:$VALUE.$FRACTION").
+KEY
+ Key used to select the product from the console during testing. Optional.
+THUMBNAIL
+ Name of a filename with a preview image of the product to be given to the wallet. Optional. Only ".png", ".jpg", ".jpeg" and ".svg" are supported at this time.
+
SEE ALSO
========
diff --git a/orphaned/taler-nfc-guide.rst b/orphaned/taler-nfc-guide.rst
index aa961d31..d025d347 100644
--- a/orphaned/taler-nfc-guide.rst
+++ b/orphaned/taler-nfc-guide.rst
@@ -231,8 +231,8 @@ to dereference the ``taler://pay`` URI from the example above:
# success response with no data
m<-w 9000
-(Note that this process works analogously for communication between a bank/ATM
-terminal or "reward provider".)
+(Note that this process works analogously for communication with a bank/ATM
+terminal.)
Request tunneling
diff --git a/screenshots/create_orders.png b/screenshots/create_orders.png
new file mode 100644
index 00000000..74814c72
--- /dev/null
+++ b/screenshots/create_orders.png
Binary files differ
diff --git a/screenshots/cta-accept-tos-firefox-0.png b/screenshots/cta-accept-tos-firefox-0.png
new file mode 100644
index 00000000..6809d775
--- /dev/null
+++ b/screenshots/cta-accept-tos-firefox-0.png
Binary files differ
diff --git a/screenshots/cta-accept-tos-firefox-latest.png b/screenshots/cta-accept-tos-firefox-latest.png
new file mode 120000
index 00000000..f1b6f069
--- /dev/null
+++ b/screenshots/cta-accept-tos-firefox-latest.png
@@ -0,0 +1 @@
+cta-accept-tos-firefox-0.png \ No newline at end of file
diff --git a/screenshots/cta-payment-firefox-0.png b/screenshots/cta-payment-firefox-0.png
new file mode 100644
index 00000000..c9d01380
--- /dev/null
+++ b/screenshots/cta-payment-firefox-0.png
Binary files differ
diff --git a/screenshots/cta-payment-firefox-latest.png b/screenshots/cta-payment-firefox-latest.png
new file mode 120000
index 00000000..26b0f16e
--- /dev/null
+++ b/screenshots/cta-payment-firefox-latest.png
@@ -0,0 +1 @@
+cta-payment-firefox-0.png \ No newline at end of file
diff --git a/screenshots/cta-payment-paid-firefox-0.png b/screenshots/cta-payment-paid-firefox-0.png
new file mode 100644
index 00000000..f67e2af3
--- /dev/null
+++ b/screenshots/cta-payment-paid-firefox-0.png
Binary files differ
diff --git a/screenshots/cta-payment-paid-firefox-latest.png b/screenshots/cta-payment-paid-firefox-latest.png
new file mode 120000
index 00000000..22dd4530
--- /dev/null
+++ b/screenshots/cta-payment-paid-firefox-latest.png
@@ -0,0 +1 @@
+cta-payment-paid-firefox-0.png \ No newline at end of file
diff --git a/screenshots/cta-url-entry-firefox-0.png b/screenshots/cta-url-entry-firefox-0.png
new file mode 100644
index 00000000..ba98a8e4
--- /dev/null
+++ b/screenshots/cta-url-entry-firefox-0.png
Binary files differ
diff --git a/screenshots/cta-url-entry-firefox-latest.png b/screenshots/cta-url-entry-firefox-latest.png
new file mode 120000
index 00000000..f24b6cb8
--- /dev/null
+++ b/screenshots/cta-url-entry-firefox-latest.png
@@ -0,0 +1 @@
+cta-url-entry-firefox-0.png \ No newline at end of file
diff --git a/screenshots/cta-wire-transfer-firefox-0.png b/screenshots/cta-wire-transfer-firefox-0.png
new file mode 100644
index 00000000..7301cedc
--- /dev/null
+++ b/screenshots/cta-wire-transfer-firefox-0.png
Binary files differ
diff --git a/screenshots/cta-wire-transfer-firefox-latest.png b/screenshots/cta-wire-transfer-firefox-latest.png
new file mode 120000
index 00000000..202edda1
--- /dev/null
+++ b/screenshots/cta-wire-transfer-firefox-latest.png
@@ -0,0 +1 @@
+cta-wire-transfer-firefox-0.png \ No newline at end of file
diff --git a/screenshots/cta-withdraw-done-firefox-0.png b/screenshots/cta-withdraw-done-firefox-0.png
new file mode 100644
index 00000000..3a3fc2f6
--- /dev/null
+++ b/screenshots/cta-withdraw-done-firefox-0.png
Binary files differ
diff --git a/screenshots/cta-withdraw-done-firefox-latest.png b/screenshots/cta-withdraw-done-firefox-latest.png
new file mode 120000
index 00000000..f707ff77
--- /dev/null
+++ b/screenshots/cta-withdraw-done-firefox-latest.png
@@ -0,0 +1 @@
+cta-withdraw-done-firefox-0.png \ No newline at end of file
diff --git a/screenshots/cta-withdraw-firefox-0.png b/screenshots/cta-withdraw-firefox-0.png
new file mode 100644
index 00000000..e75fb875
--- /dev/null
+++ b/screenshots/cta-withdraw-firefox-0.png
Binary files differ
diff --git a/screenshots/cta-withdraw-firefox-latest.png b/screenshots/cta-withdraw-firefox-latest.png
new file mode 120000
index 00000000..4ed704c3
--- /dev/null
+++ b/screenshots/cta-withdraw-firefox-latest.png
@@ -0,0 +1 @@
+cta-withdraw-firefox-0.png \ No newline at end of file
diff --git a/screenshots/enter_instance_details.png b/screenshots/enter_instance_details.png
new file mode 100644
index 00000000..f2177091
--- /dev/null
+++ b/screenshots/enter_instance_details.png
Binary files differ
diff --git a/screenshots/instance_iban_config.png b/screenshots/instance_iban_config.png
new file mode 100644
index 00000000..03fa8f36
--- /dev/null
+++ b/screenshots/instance_iban_config.png
Binary files differ
diff --git a/screenshots/merchant_first_login.png b/screenshots/merchant_first_login.png
new file mode 100644
index 00000000..0baa0801
--- /dev/null
+++ b/screenshots/merchant_first_login.png
Binary files differ
diff --git a/screenshots/no_default_account_yet.png b/screenshots/no_default_account_yet.png
new file mode 100644
index 00000000..c97c231d
--- /dev/null
+++ b/screenshots/no_default_account_yet.png
Binary files differ
diff --git a/screenshots/payment_links.png b/screenshots/payment_links.png
new file mode 100644
index 00000000..0c58b286
--- /dev/null
+++ b/screenshots/payment_links.png
Binary files differ
diff --git a/taler-auditor-manual.rst b/taler-auditor-manual.rst
index feaf7783..94e86a8d 100644
--- a/taler-auditor-manual.rst
+++ b/taler-auditor-manual.rst
@@ -17,8 +17,13 @@
@author Christian Grothoff
-GNU Taler Auditor Operator Manual
-#################################
+Auditor Operator Manual
+#######################
+
+.. contents:: Table of Contents
+ :depth: 1
+ :local:
+
Introduction
============
@@ -309,9 +314,6 @@ This section discusses configuration options related to the auditor.
.. include:: frags/configuration-format.rst
-.. include:: frags/using-taler-config.rst
-
-
.. _SetupBaseUrl:
Initial configuration
@@ -320,10 +322,11 @@ Initial configuration
You need to tell the Taler auditor configuration where the
REST API of the auditor will be available to the public:
-.. code-block:: console
+.. code-block:: ini
# Both for the 'offline' *and* the 'auditor' user:
- $ taler-config -s auditor -o BASE_URL -V https://auditor.example.com/
+ [auditor]
+ BASE_URL = https://auditor.example.com/
The ``helper`` user that is used to download information from the exchange
needs to know details about the exchange. Similarly, the ``offline`` user
@@ -332,11 +335,12 @@ need to obtain the ``MASTER_PUBLIC_KEY`` from the exchange operator (they need
to run ``taler-exchange-offline setup``) and the REST endpoint of the exchange
and configure these:
-.. code-block:: console
+.. code-block:: ini
# As the 'helper' and 'offline' users:
- $ taler-config -s exchange -o BASE_URL -V https://exchange.example.com/
- $ taler-config -s exchange -o MASTER_PUBLIC_KEY -V $SOMELONGBASE32VALUEHERE
+ [exchange]
+ BASE_URL = https://exchange.example.com/
+ MASTER_PUBLIC_KEY = $SOMELONGBASE32VALUEHERE
.. _AuditorKeys:
@@ -372,10 +376,11 @@ of the ``auditor`` user in the ``[auditor]]`` configuration section:
You can set this configuration value using:
-.. code-block:: console
+.. code-block:: ini
# As the 'auditor' and 'helper' users:
- $ taler-config -s auditor -o PUBLIC_KEY -V $SOMELONGBASE32VALUEHERE
+ [auditor]
+ PUBLIC_KEY = $SOMELONGBASE32VALUEHERE
.. _AuditorServing:
@@ -658,11 +663,17 @@ PostgreSQL configuration:
Next, the ``postgres`` user of the auditor's system must first initialize the
local tables:
+.. code-block:: ini
+
+ # Configure database:
+ [exchange]
+ DB = "postgres"
+ [exchangedb-postgres]
+ CONFIG = "postgres:///taler-ingress"
+
.. code-block:: console
# As the 'ingress' user of the exchange:
- $ taler-config -s exchange -o DB -V "postgres"
- $ taler-config -s exchangedb-postgres -o CONFIG -V "postgres:///taler-ingress"
$ taler-exchange-dbinit
To complete the replication, the ``postgres`` user of the auditor's
@@ -722,11 +733,17 @@ needs to be changed.
To run ``taler-auditor-sync``, you must first configure two configuration
files that identify the source and destination databases:
-.. code-block:: console
+.. code-block:: ini
- # As the 'sync' user:
- $ taler-config -c src.conf -s exchangedb -o CONFIG -V "postgres:///auditor-ingres/"
- $ taler-config -c dst.conf -s exchangedb -o CONFIG -V "postgres:///auditor/"
+ # src.conf
+ [exchangedb]
+ CONFIG = "postgres:///auditor-ingres/"
+
+.. code-block:: ini
+
+ # dst.conf
+ [exchangedb]
+ CONFIG = "postgres:///auditor/"
Now you should be able to launch the synchronization process. You can run
the process via systemd in the background. For a first one-off test, you should
diff --git a/taler-challenger-manual.rst b/taler-challenger-manual.rst
index ae7eb047..a7a7169f 100644
--- a/taler-challenger-manual.rst
+++ b/taler-challenger-manual.rst
@@ -17,8 +17,13 @@
@author Christian Grothoff
@author Florian Dold
-GNU Taler Challenger Operator Manual
-####################################
+Challenger Operator Manual
+##########################
+
+.. contents:: Table of Contents
+ :depth: 2
+ :local:
+
Introduction
============
@@ -45,7 +50,37 @@ or learn about known limitations, please check our
Architecture overview
---------------------
-TBC.
+The following picture gives an overview of the Challenger
+architecture and the main interactions:
+
+.. image:: images/challenger.png
+
+Here, the *resource owner* is a user that is in control
+of some *address* at a messaging service. This could be
+an e-mail account, a mobile phone number (for SMS), or
+a physical mail address (using the post office as the
+messaging service).
+
+The *resource owner* makes some request that requires
+some *client* to be in need of address validation. The
+*client* is registered with the Challenger OAuth 2.0
+service and first authorizes an address validation to
+be initiated. The client then redirects the resource
+owner to the Challenger service. In step (2), the resource
+owner submits the address that they claim to own.
+
+The Challenger service then creates a TAN code and
+submits it to the given address via a configurable
+*helper script* that is specific to the type of address
+being validated. When the resource owner submits the
+correct TAN code in step (6), they are given a token
+that they can provide to the client. Using this token
+the client can then finally obtain the now validated
+address in step (8).
+
+Address data, TAN codes and meta-data such as the number
+of failed attempts to submit a TAN code are recorded
+in a Postgres database by the Challenger service.
.. _ChallengerInstallation:
@@ -423,7 +458,7 @@ three options from the previous section, but also the authorization, token and
info endpoints. For Challenger, these are ``/authorize``, ``/token`` and
``/info``. However, the ``/authorize`` endpoint is special, as it is actually
``/authorize/$NONCE`` where ``$NONCE`` is a nonce that must be first requested
-by the client using the ``/setup`` endpoint!
+by the client using the ``/setup/$CLIENT_ID`` endpoint!
..note::
@@ -433,7 +468,7 @@ by the client using the ``/setup`` endpoint!
validation could be expensive.
Thus, to generate the authorization URL, a client must first POST to
-``/setup`` using their client secret in an ``Authorization: Bearer $SECRET``
+``/setup/$CLIENT_ID`` using their client secret in an ``Authorization: Bearer $SECRET``
HTTP header to obtain a fresh ``$NONCE``.
In the GNU Taler exchange configuration, this is indicated by appending
@@ -489,3 +524,159 @@ The Challenger database can be re-initialized using:
However, running this command will result in all data in the database
being lost.
+
+
+.. _ChallengerCustomization:
+
+Template Customization
+======================
+
+The Challenger service comes with various HTML templates that are shown to
+guide users through the process. Challenger uses `Mustach
+<https://gitlab.com/jbol/mustach>`__ as the templating engine. This section
+describes the various templates. In general, the templates must be installed
+to the ``share/challenger/templates/`` directory. The file names must be of
+the form ``$NAME.$LANG.must`` where ``$NAME`` is the name of the template and
+``$LANG`` is the 2-letter language code of the template. English templates
+must exist and will be used as a fallback. If the browser (user-agent) has
+provided language preferences in the HTTP header and the respective language
+exists, the correct language will be automatically served.
+
+The following subsections give details about each of the templates. The
+subsection title is the ``$NAME`` of the respective template.
+
+enter-$ADDRESS_TYPE-form
+------------------------
+
+These templates are used to ask the user to enter the address that challenger
+is expected to validate. Here, ``$ADDRESS_TYPE`` will be replaced by the
+``ADDRESS_TYPE`` configuration option in the ``[challenger]`` section of the
+configuration file. Typical values include ``address`` (for physical mailing
+addresses), ``phone`` (for mobile phone numbers) and ``email`` (for email
+addresses). For testing, ``file`` (where the TAN code is written into a local
+file) is also supported.
+
+The template is instantiated using the following information:
+
+ * fix_address: boolean; indicates if the given address cannot be changed
+ anymore, the form should be read-only if set to true.
+
+ * nonce: String; unique value identifying the challenge, should be shown
+ to the user so that they can recognize it when they receive the TAN code
+
+ * last_address: Object; form values from the previous submission if available,
+ details depend on the ``ADDRESS_TYPE``, should be used to pre-populate the form
+
+ * changes_left: Integer; number of times the address can still be changed,
+ may or may not be shown to the user
+
+enter-tan-form
+--------------
+
+This page should generate the HTML form for the user to enter the TAN code
+that they received at the respective address.
+
+The template is instantiated using the following information:
+
+ * nonce: String; unique value identifying the challenge, should be shown
+ to the user so that they can match it to the TAN code they received
+
+ * attempts_left: Integer; how many more attempts are allowed, might be
+ shown to the user, highlighting might be appropriate for low values
+ such as 1 or 2 (the form will never be used if the value is zero)
+
+ * address: Object; the address that is being validated, might be shown
+ or not
+
+ * transmitted: boolean; true if we just retransmitted the challenge,
+ false if we sent a challenge recently and thus refused to transmit it
+ again this time; might make a useful hint to the user
+
+ * next_tx_time: String; timestamp explaining when we would re-transmit
+ the challenge the next time (at the earliest) if requested by the user
+
+
+invalid-pin
+-----------
+
+The user has provided an invalid TAN code (HTTP 403 Forbidden).
+
+The template is instantiated using the following information:
+
+ * ec: Integer; numeric Taler error code, should be shown to indicate the
+ error compactly for reporting to developers
+
+ * hint: String; human-readable Taler error code, should be shown for the
+ user to understand the error
+
+ * addresses_left: Integer; how many times is the user still allowed to
+ change the address; if 0, the user should not be shown a link to jump
+ to the address entry form
+
+ * pin_transmissions_left: Integer; how many times might the PIN still
+ be retransmitted
+
+ * auth_attempts_left: Integer; how many times might the user still try
+ entering the PIN code
+
+ * exhausted: Bool; if true, the PIN was not even evaluated as the user previously exhausted the number of attempts
+
+ * no_challenge: Bool; if true, the PIN was not even evaluated as no challenge was ever issued (the user must have skipped the step of providing their address first!)
+
+If both *pin_transmissions_left* and *auth_attempts_left* are zero, the link
+to re-enter the PIN should be hidden and the user should only be allowed to
+specify a different address. The form will never be generated if all three
+values are zero. (Thus there is always at least one valid choice when the form
+is shown.)
+
+
+validation-unknown
+------------------
+
+The user has tried to access a validation process that is not known to the
+backend (HTTP 404 Not Found).
+
+The template is instantiated using the following information:
+
+ * ec: Integer; numeric Taler error code, should be shown to indicate the
+ error compactly for reporting to developers
+
+ * hint: String; human-readable Taler error code, should be shown for the
+ user to understand the error
+
+ * detail: String; optional, extended human-readable text provided to elaborate
+ on the error, should be shown to provide additional context
+
+
+invalid-request
+---------------
+
+The request of the client is invalid (HTTP 400 Bad Request).
+
+The template is instantiated using the following information:
+
+ * ec: Integer; numeric Taler error code, should be shown to indicate the
+ error compactly for reporting to developers
+
+ * hint: String; human-readable Taler error code, should be shown for the
+ user to understand the error
+
+ * detail: String; optional, extended human-readable text provided to elaborate
+ on the error, should be shown to provide additional context
+
+
+internal-error
+--------------
+
+The service experienced an internal error (HTTP 500 Internal Server Error).
+
+The template is instantiated using the following information:
+
+ * ec: Integer; numeric Taler error code, should be shown to indicate the
+ error compactly for reporting to developers
+
+ * hint: String; human-readable Taler error code, should be shown for the
+ user to understand the error
+
+ * detail: String; optional, extended human-readable text provided to elaborate
+ on the error, should be shown to provide additional context
diff --git a/taler-developer-manual.rst b/taler-developer-manual.rst
index a5a73ba9..1aa5cc8d 100644
--- a/taler-developer-manual.rst
+++ b/taler-developer-manual.rst
@@ -1,7 +1,7 @@
..
This file is part of GNU TALER.
- Copyright (C) 2014-2021 Taler Systems SA
+ Copyright (C) 2014-2023 Taler Systems SA
TALER is free software; you can redistribute it and/or modify it under the
terms of the GNU Affero General Public License as published by the Free Software
@@ -20,12 +20,6 @@ Developer's Manual
##################
.. toctree::
- :hidden:
-
- checklist-release
- checklist-demo-upgrade
- python-guidelines
-
.. note::
@@ -34,6 +28,7 @@ Developer's Manual
.. contents:: Table of Contents
:depth: 2
+ :local:
Project Overview
@@ -98,8 +93,7 @@ overview:
sending invoices or payments to other wallets.
* taler-merchant-demos: various demonstration services operated at
- 'demo.taler.net', including a simple shop, donation page and a
- survey with reward functionality.
+ 'demo.taler.net', including a simple shop and a donation page.
There are other important repositories without code, including:
@@ -118,6 +112,55 @@ There are other important repositories without code, including:
Fundamentals
============
+Versioning
+----------
+
+A central rule is to never break anything for any dependency. To accomplish
+this, we use versioning, of the APIs, database schema and the protocol. The
+database versioning approach is described in the :ref:`Database schema
+versioning <DatabaseVersioning>` section. Here, we will focus on API and
+protocol versioning.
+
+The key issue we need to solve with protocols and APIs (and that does not
+apply to database versioning) is being able to introduce and remove features
+without requiring a flag day where all components must update at the same
+time. For this, we use GNU libtool style versioning with MAJOR:REVISION:AGE
+and *not* semantic versioning (SEMVER). With GNU libtool style versioning,
+first the REVISION should be increased on every change to the respective code.
+Then, each time a feature is introduced or deprecated, the MAJOR and AGE
+numbers are increased. Whenever an API is actually removed the AGE number is
+reduced to match the distance since the removed API was deprecated. Thus, if
+some client implements version X of the protocol (including not using any APIs
+that have been deprecated), it is compatible for any implementation where
+MAJOR is larger or equal to X, and MAJOR minus AGE is smaller or equal to X.
+REVISION is not used for expected compatibility issues and merely serves to
+uniquely identify each version (in combination with MAJOR).
+
+To evolve any implementation, it is thus critical to first of all never
+just break an existing API or endpoint. The only acceptable modifications
+are to return additional information (being aware of binary compatibility!)
+or to accept additional optional arguments (again, in a way that does not
+break existing users). Thus, the most common way to introduce changes will
+be the addition of new endpoints. Breaking existing endpoints is only ever
+at best acceptable while in the process of introducing it and if you are
+absolutely sure that there are zero users in other components.
+
+When removing endpoints (or fields being returned), you must first deprecate
+the existing API (incrementing MAJOR and AGE) and then wait for all clients,
+including all clients in operation (e.g. Android and iOS Apps, e-commerce
+integrations, etc.) to upgrade to a protocol implementation above the
+deprecated MAJOR revision. Only then you should remove the endpoint and reduce
+AGE.
+
+To document these changes, please try to use ``@since`` annotations in the API
+specifications to explain the MAJOR revision when a feature became available,
+but most importantly use ``@deprecated X`` annotations to indicate that an API
+was deprecated and will be removed once MAJOR minus AGE is above X. When using
+an API, use the ``/config`` endpoints to check for compatibility and show a
+warning if the version(s) you support and the version(s) offered by the server
+are incompatible.
+
+
Testing Tools
-------------
@@ -391,7 +434,7 @@ exported by ``~/.bashrc``.
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.
-Please use the :doc:`demo upgrade checklist <checklist-demo-upgrade>` to make
+Please use the :doc:`demo upgrade checklist <checklists/checklist-demo-upgrade>` to make
sure everything is working.
Nginx is already configured to reach the services as exported by
Docker Compose.
@@ -433,6 +476,8 @@ All Taler components must be tagged with git before they are deployed on the
DD = day
SS = serial
+.. include:: checklists/checklist-demo-upgrade.rst
+
Environments and Builders on taler.net
======================================
@@ -583,6 +628,8 @@ prepared.
$ buildbot-worker start worker/
+.. _DatabaseVersioning:
+
Database schema versioning
--------------------------
@@ -598,14 +645,19 @@ Developers and operators MUST NOT make changes to database schema
outside of this versioning. All tables of a GNU Taler component should live in their own schema.
+QA Plans
+========
+
+.. include:: checklists/qa-0.9.4.rst
+
Releases
========
-Release Process and Checklists
-------------------------------
+.. include:: checklists/checklist-release.rst
-Please use the :doc:`release checklist <checklist-release>`
+Release Process
+---------------
This document describes the process for releasing a new version of the
various Taler components to the official GNU mirrors.
@@ -614,10 +666,11 @@ The following components are published on the GNU mirrors
- taler-exchange (exchange.git)
- taler-merchant (merchant.git)
-- talerdonations (donations.git)
-- talerblog (blog.git)
-- taler-bank (bank.git)
-- taler-wallet-webex (wallet-webex.git)
+- sync (sync.git)
+- taler-mdb (taler-mdb.git)
+- libeufin (libeufin.git)
+- challenger (challenger.git)
+- wallet-core (wallet-core.git)
Tagging
-------
@@ -720,6 +773,7 @@ Directive file:
version: 1.2
directory: taler
filename: taler-exchange-0.1.0.tar.gz
+ symlink: taler-exchange-0.1.0.tar.gz taler-exchange-latest.tar.gz
Upload the files in **binary mode** to the ftp servers.
@@ -909,8 +963,13 @@ Taler.xcworkspace expects the QuickJS framework sub-project to be at
``../quickjs-tart/QuickJS-rt.xcodeproj``.
Build wallet-core first:
- cd ~/Developer/GNU_Taler/wallet-core
- date; time make embedded; open packages/taler-wallet-embedded/dist
+
+.. code-block:: shell-session
+
+ $ cd wallet-core
+ $ make embedded
+ $ open packages/taler-wallet-embedded/dist
+
then drag or move its product "taler-wallet-core-qjs.mjs"
into your quickjs-tart folder right at the top level.
@@ -1775,84 +1834,12 @@ This section describes various internal programs to make life easier for the
developer.
-taler-config-generate
----------------------
-
-**taler-config-generate** - tool to simplify Taler configuration generation
-
-
-**taler-config-generate**
-[**-C** *CURRENCY* | **--currency=**\ ‌\ *CURRENCY*]
-[**-c** *FILENAME* | **--config=**\ ‌\ *FILENAME*]
-[**-e** | **--exchange**]
-[**-f** *AMOUNT* | *--wirefee=*\ ‌\ *AMOUNT*]
-[**-h** | **--help**]
-[**-J** *JSON* | **--wire-json-exchange=**\ ‌\ *JSON*]
-[**-j** *JSON* | **--wire-json-merchant=**\ ‌\ *JSON*]
-[**-L** *LOGLEVEL* | **--loglevel=**\ ‌\ *LOGLEVEL*]
-[**-m** | **--merchant**]
-[**-t** | **--trusted**]
-[**-v** | **--version**]
-[**-w** *WIREFORMAT* | **--wire** *WIREFORMAT*]
-[**--bank-uri**]
-[**--exchange-bank-account**]
-[**--merchant-bank-account**]
-
-
-**taler-config-generate** can be used to generate configuration files
-for the Taler exchange or Taler merchants.
-
-**-C** *CURRENCY* \| **--currency=**\ ‌\ *CURRENCY*
- Which currency should we use in the configuration.
-
-**-c** *FILENAME* \| **--config=**\ ‌\ *FILENAME*
- Location where to write the generated configuration. Existing file
- will be updated, not overwritten.
-
-**-e** \| **--exchange**
- Generate configuration for a Taler exchange.
-
-**-f** *AMOUNT* \| *-wirefee=*\ ‌\ *AMOUNT*
- Setup wire transfer fees for the next 5 years for the exchange (for
- all wire methods).
-
-**-h** \| **--help**
- Shows this man page.
-
-**-J** *JSON* \| **--wire-json-exchange=**\ ‌\ *JSON*
- Wire configuration to use for the exchange.
-
-**-j** *JSON* \| **--wire-json-merchant=**\ ‌\ *JSON*
- Wire configuration to use for the merchant.
-
-**-L** *LOGLEVEL* \| **--loglevel=**\ ‌\ *LOGLEVEL*
- Use LOGLEVEL for logging. Valid values are DEBUG, INFO, WARNING and
- ERROR.
-
-**-m** \| **--merchant**
- Generate configuration for a Taler merchant.
-
-**-t** \| **--trusted**
- Setup current exchange as trusted with current merchant. Generally
- only useful when configuring for testcases.
-
-**-v** \| **--version**
- Print version information.
-
-**-w** *WIREFORMAT* \| **--wire** *WIREFORMAT*
- Specifies which wire format to use (i.e. “x-talerbank” or “iban”)
+taler-harness
+-------------
-**--bank-uri**
- Alternative to specify wire configuration to use for the exchange and
- merchant for the “test” wire method. Only useful if WIREFORMAT was
- set to “test”. Specifies the URI of the bank.
+**taler-harness deployment gen-coin-config** is a tool to simplify Taler configuration generation.
-**--exchange-bank-account**
- Alternative to specify wire configuration to use for the exchange for
- the “test” wire method. Only useful if WIREFORMAT was set to “test”.
- Specifies the bank account number of the exchange.
-**--merchant-bank-account**
- Alternative to specify wire configuration to use for the merchant for
- the “test” wire method. Only useful if WIREFORMAT was set to “test”.
- Specifies the bank account number of the merchant.
+**taler-harness deployment gen-coin-config**
+[**-min-amount**=**\ ‌\ *VALUE*]
+[**-max-amount**=**\ ‌\ *VALUE*]
diff --git a/taler-exchange-manual.rst b/taler-exchange-manual.rst
index df05fbfc..57db7095 100644
--- a/taler-exchange-manual.rst
+++ b/taler-exchange-manual.rst
@@ -1,7 +1,7 @@
..
This file is part of GNU TALER.
- Copyright (C) 2014-2023 Taler Systems SA
+ Copyright (C) 2014-2024 Taler Systems SA
TALER is free software; you can redistribute it and/or modify it under the
terms of the GNU Affero General Public License as published by the Free Software
@@ -17,8 +17,13 @@
@author Christian Grothoff
@author Florian Dold
-GNU Taler Exchange Operator Manual
-##################################
+Exchange Operator Manual
+########################
+
+.. contents:: Table of Contents
+ :depth: 1
+ :local:
+
Introduction
============
@@ -35,6 +40,7 @@ About this manual
This manual targets system administrators who want to install and
operate a GNU Taler exchange.
+
Organizational prerequisites
----------------------------
@@ -449,7 +455,7 @@ to compartmentalize different parts of the system:
The exchange setup uses the following system groups:
-* ``taler-exchange-db``: group for all Taler users with direct database access, specifically taler-exchange-httpd, taler-exchange-wire, taler-exchange-closer and taler-exchange-aggregator.
+* ``taler-exchange-db``: group for all Taler users with direct database access, specifically taler-exchange-httpd, taler-exchange-wirewatch, taler-exchange-closer and taler-exchange-aggregator.
* ``taler-exchange-secmod``: group for processes with access to online signing keys; this group must have four users: taler-exchange-secmod-rsa, taler-exchange-secmod-cs, taler-exchange-secmod-eddsa and taler-exchange-httpd.
* ``taler-exchange-offline``: group for the access to the offline private key (only used on the offline host and not used on the online system).
@@ -521,11 +527,6 @@ can use the ``taler-config`` helper:
.. include:: frags/configuration-format.rst
-.. _Using-taler_002dconfig-exchange:
-
-.. include:: frags/using-taler-config.rst
-
-
Exchange Database Setup
=======================
@@ -827,375 +828,32 @@ configuration of the online machine:
Wire Gateway Setup
==================
-The Taler Wire Gateway is an API that connects the Taler exchange to
-the underlying core banking system.
-
-LibEuFin is an implementation of the Wire Gateway API for the EBICS protocol.
-This section will walk through (1) installing and configuring LibEuFin and
-(2) connecting the Taler Exchange to LibEuFin.
-
-.. note::
-
- If you do not have a bank account with EBICS but want to test these instructions,
- you can use the EBICS sandbox as described in the
- :doc:`LibEuFin Tutorial <libeufin/nexus-tutorial>`.
-
-
-Installation and Basic Configuration
-------------------------------------
-
-First, install the ``libeufin`` package. This can be done on the ``exchange-online``
-machine or a different one.
-
-.. code-block:: shell-session
-
- [root@exchange-online]# apt-get install -y libeufin
-
-The main component of LibEuFin is called the Nexus. It implements a Web
-service that provides a JSON abstraction layer to access bank accounts.
-
-The HTTP port and database connection string can be edited in the configuration:
-
-.. code-block:: ini
- :caption: /etc/libeufin/nexus.env
-
- LIBEUFIN_NEXUS_PORT=5017
- LIBEUFIN_NEXUS_DB_CONNECTION=jdbc:sqlite:/var/lib/libeufin/nexus/nexus-db.sqlite3
-
-After configuring the database, you can start the service.
-The database is initialized automatically.
-
-
-.. code-block:: shell-session
-
- [root@exchange-online]# systemctl enable libeufin-nexus
- [root@exchange-online]# systemctl start libeufin-nexus
-
-You can now create a superuser account. The command to
-create the superuser needs direct database access, thus
-the configuration file is sourced first, and the relevant
-environment variable is exported.
-
-.. code-block:: console
-
- [root@exchange-online]# source /etc/libeufin/nexus.env
- [root@exchange-online]# export LIBEUFIN_NEXUS_DB_CONNECTION
- [root@exchange-online]# NEXUS_ADMIN_PW=$(tr -dc A-Za-z0-9 </dev/urandom | head -c 13)
- [root@exchange-online]# libeufin-nexus superuser admin --password $NEXUS_ADMIN_PW
-
-If you omit ``--password $NEXUS_ADMIN_PW``, you will interactively be asked for a password.
-For simplicity, a superuser can as well act as a normal user, but an API
-to create less privileged users is offered.
-
-.. note::
-
- User and permissions management in LibEuFin is still under development.
- In particular, permissions for non-superusers are very limited at the moment.
-
-
-Connecting Nexus with an EBICS account
---------------------------------------
-
-The command line interface of the LibEuFin Nexus needs the following three
-values to be defined in the environment: ``LIBEUFIN_NEXUS_URL``,
-``LIBEUFIN_NEXUS_USERNAME``, and ``LIBEUFIN_NEXUS_PASSWORD``. In this example,
-``LIBEUFIN_NEXUS_USERNAME`` should be set to ``admin``, and
-``LIBEUFIN_NEXUS_PASSWORD`` to the value hold in ``NEXUS_ADMIN_PW`` from the
-previous step (the ``libeufin-nexus superuser`` command). The
-``LIBEUFIN_NEXUS_URL`` could be given as ``http://localhost:5017/``.
-
-Next, we create a EBICS *bank connection* that Nexus can use to communicate with the bank.
-
-.. code-block:: console
-
- [root@exchange-online]# libeufin-cli \
- connections \
- new-ebics-connection \
- --ebics-url $EBICS_BASE_URL \
- --host-id $EBICS_HOST_ID \
- --partner-id $EBICS_PARTNER_ID \
- --ebics-user-id $EBICS_USER_ID \
- $CONNECTION_NAME
-
-If this step executes correctly, Nexus will have created all the cryptographic
-material that is needed on the client side; in this EBICS example, it created
-the signature and identification keys. It is therefore advisable to *make
-a backup copy* of such keys.
-
-.. code-block:: console
-
- [root@exchange-online]# libeufin-cli \
- connections \
- export-backup \
- --passphrase $SECRET \
- --output-file $BACKUP_FILE \
- $CONNECTION_NAME
-
-At this point, Nexus needs to both communicate its keys to the bank, and
-download the bank's keys. This synchronization happens through the INI, HIA, and
-finally, HPB message types.
-
-After the electronic synchronization, the subscriber must confirm their keys
-by sending a physical mail to the bank. The following command helps generating
-such letter:
-
-.. code-block:: console
-
- [root@exchange-online]# libeufin-cli connections get-key-letter $CONNECTION_NAME out.pdf
-
-.. code-block:: console
-
- [root@exchange-online]# libeufin-cli \
- connections \
- connect \
- $CONNECTION_NAME
-
-..
- FIXME: Maybe is not 100% clear that 'connecting' means exchanging keys
- with the bank?
-
-Once the connection is synchronized, Nexus needs to import locally the data
-corresponding to the bank accounts offered by the bank connection just made.
-The command below downloads the list of the bank accounts offered by ``$CONNECTION_NAME``.
-
-.. code-block:: console
-
- [root@exchange-online]# libeufin-cli \
- connections \
- download-bank-accounts \
- $CONNECTION_NAME
-
-It is now possible to list the accounts offered by the connection.
+The :ref:`Taler Wire Gateway <taler-wire-gateway-http-api>` is an API that
+connects the Taler exchange to the underlying core banking system. There are
+several implementations of wire gateways:
-.. code-block:: console
-
- [root@exchange-online]# libeufin-cli \
- connections \
- list-offered-bank-accounts \
- $CONNECTION_NAME
-
-.. note::
-
- The ``nexusBankAccountId`` field should at this step be ``null``,
- as we have not yet imported the bank account and thus the account
- does not yet have a local name.
-
-Nexus now needs an explicit import of the accounts it should manage. This
-step is needed to let the user pick a custom name for such accounts.
-
-.. code-block:: console
-
- [root@exchange-online]# libeufin-cli \
- connections \
- import-bank-account \
- --offered-account-id testacct01 \
- --nexus-bank-account-id $LOCAL_ACCOUNT_NAME \
- $CONNECTION_NAME
-
-Once a Nexus user imported a bank account (``$LOCAL_ACCOUNT_NAME``)
-under a certain connection (``$CONNECTION_NAME``), it is possible
-to accomplish the usual operations for any bank account: asking for the
-list of transactions, and making a payment.
-
-Testing: Requesting the transaction history
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ * `Project deploymerization <https://git.taler.net/depolymerization.git>`_ implements a wire gateway on top of Bitcoin or Ethereum
+ * The :ref:`libeufin-bank <libeufin-bank>` provides a wire gateway interface on top of a regional currency bank
+ * The **taler-fakebank-run** command is an in-memory bank simulator with a wire gateway interface for testing
-The LibEuFin Nexus keeps a local copy of the bank account's transaction
-history. Before querying transactions locally, it is necessary
-to request transactions for the bank account via the bank connection.
+.. FIXME :ref:`libeufin-nexus <libeufin-nexus>` is an implementation of the Wire Gateway API for the EBICS protocol. Add to list above once nexus implements the TWG directly!
-This command asks Nexus to download the latest transaction reports/statements
-through the bank connection:
+Before continuing, you need to decide which wire gateway you want to use,
+and install and configure it on your system. Afterwards, you need to
+have two key pieces of information from that setup:
-.. code-block:: console
-
- [root@exchange-online]# libeufin-cli accounts fetch-transactions $LOCAL_ACCOUNT_NAME
-
-.. note::
-
- By default, the latest available transactions are fetched. It is also
- possible to specify a custom date range (or even all available transactions)
- and the type of transactions to fetch (inter-day statements or intra-day
- reports).
-
-..
- FIXME: Possibly the date range filter is still missing, see #6243.
-
-Once Nexus has stored all the information in the database, the
-client can ask to actually see the transactions:
-
-.. code-block:: console
+ * The username and password to access the exchange's account in the system.
+ * The ``payto://`` URI of that account (see `RFC 8905 <https://www.rfc-editor.org/rfc/rfc8905>`_).
- [root@exchange-online]# libeufin-cli accounts transactions $LOCAL_ACCOUNT_NAME
-
-Testing: Making payments
-^^^^^^^^^^^^^^^^^^^^^^^^
-
-Payments pass through two phases: preparation and submission. The preparation
-phase assigns the payment initiation a unique ID, which prevents accidental
-double submissions of payments in case of network failures or other
-disruptions.
-
-
-The following command prepares a payment:
-
-.. code-block:: console
-
- [root@exchange-online]# libeufin-cli accounts prepare-payment \
- --creditor-iban=$IBAN_TO_SEND_MONEY_TO \
- --creditor-bic=$BIC_TO_SEND_MONEY_TO \
- --creditor-name=$CREDITOR_NAME \
- --payment-amount=$AMOUNT \
- --payment-subject=$SUBJECT \
- $LOCAL_ACCOUNT_NAME
-
-Note: the ``$AMOUNT`` value needs the format ``X.Y:CURRENCY``; for example
-``EUR:10``, or ``EUR:1.01``.
-
-The previous command should return a value (``$UUID``) that uniquely
-identifies the prepared payment in the Nexus system. That is needed
-in the next step, to **send the payment instructions to the bank**:
-
-.. code-block:: console
-
- [root@exchange-online]# libeufin-cli accounts submit-payments \
- --payment-uuid $UUID \
- $LOCAL_ACCOUNT_NAME
-
-Automatic scheduling
-^^^^^^^^^^^^^^^^^^^^
-
-With an EBICS bank connection, the LibEuFin Nexus needs to regularly query for
-new transactions and (re-)submit prepared payments.
-
-It is possible to schedule these tasks via an external task scheduler such as
-cron(8). However, the nexus also has an internal task scheduling mechanism for
-accounts.
-
-
-The following three commands create a schedule for submitting payments hourly,
-fetching transactions (intra-day reports) every 5 minutes, and (inter-day statements)
-once at 11pm every day:
-
-.. code-block:: console
-
- [root@exchange-online]# libeufin-cli accounts task-schedule $LOCAL_ACCOUNT_NAME \
- --task-type="submit" \
- --task-name='submit-payments-hourly' \
- --task-cronspec='0 0 *'
-
- [root@exchange-online]# libeufin-cli accounts task-schedule $LOCAL_ACCOUNT_NAME \
- --task-type="fetch" \
- --task-name='fetch-5min' \
- --task-cronspec='0 */5 *' \
- --task-param-level=report \
- --task-param-range-type=latest
-
- [root@exchange-online]# libeufin-cli accounts task-schedule $LOCAL_ACCOUNT_NAME \
- --task-type="fetch" \
- --task-name='fetch-daily' \
- --task-cronspec='0 0 23' \
- --task-param-level=statement \
- --task-param-range-type=latest
-
-The cronspec has the following format, which is slightly non-standard due to
-the ``SECONDS`` field
-
-.. code-block:: none
-
- SECONDS MINUTES HOURS DAY-OF-MONTH[optional] MONTH[optional] DAY-OF-WEEK[optional]
-
-
-Creating a Taler facade
-^^^^^^^^^^^^^^^^^^^^^^^
-
-Facades are additional abstraction layers that can serve
-specific purposes. For example, one application might need
-a filtered version of the transaction history, or it might
-want to refuse payments that do not conform to certain rules.
-
-At this moment, only the *Taler facade type* is implemented
-in the Nexus, and the command below instantiates one under a
-existing bank account / connection pair. You can freely
-assign an identifier for the ``$FACADE_NAME`` below:
-
-.. code-block:: console
-
- [root@exchange-online]# libeufin-cli facades new-taler-wire-gateway-facade \
- --currency EUR \
- --facade-name $FACADE_NAME \
- $CONNECTION_NAME \
- $LOCAL_ACCOUNT_NAME
-
-At this point, the additional :doc:`taler-wire-gateway API <core/api-bank-wire>`
-becomes offered by the Nexus. The purpose is to let a Taler exchange rely on
-Nexus to manage its bank account.
-
-The base URL of the facade that can be used by the Taler exchange
-as the Taler Wire Gateway base URL can be seen by listing the facades:
-
-.. code-block:: console
-
- [root@exchange-online]# libeufin-cli facades list
-
-Managing Permissions and Users
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-This guide has so far assumed that a superuser is accessing the LibEuFin Nexus.
-However, it is advisable that the Nexus is accessed with users that only have a
-minimal set of permissions.
-
-The Nexus currently only has support for giving non-superusers access to Taler
-wire gateway facades.
-
-To create a new user, use the ``users`` subcommand of the CLI:
-
-.. code-block:: console
-
- [root@exchange-online]# libeufin-cli users list
- # [ ... shows available users ... ]
-
- [root@exchange-online]# libeufin-cli users create $USERNAME
- # [ ... will prompt for password ... ]
-
-Permissions are managed with the ``permissions`` subcommand.
-The following commands grant permissions to view the transaction history
-and create payment initiations with a Taler wire gateway facade:
-
-
-.. code-block:: console
-
- [root@exchange-online]# libeufin-cli permissions grant \
- user $USERNAME \
- facade $FACADENAME \
- facade.talerwiregateway.history
-
- [root@exchange-online]# libeufin-cli permissions grant \
- user $USERNAME \
- facade $FACADENAME \
- facade.talerwiregateway.transfer
-
-..
- FIXME: The two commands above output an empty JSON object
- when successful. Possibly, we should suppress that (just like
- the other commands do).
-
-The list of all granted permissions can be reviewed:
-
-.. code-block:: console
-
- [root@exchange-online]# libeufin-cli permissions list
-
-
-.. _Bank-account:
+.. _exchange-bank-account-configuration:
Exchange Bank Account Configuration
-----------------------------------
An exchange must be configured with the right settings to access its bank
-account via a Taler Wire Gateway. An exchange can be configured to use
-multiple bank accounts by using multiple Wire Gateways. Typically only one
-Wire Gateway is used.
+account via a :ref:`Taler wire gateway <taler-wire-gateway-http-api>`. An
+exchange can be configured to use multiple bank accounts by using multiple
+wire gateways. Typically only one wire gateway is used.
To configure a bank account in Taler, we need to furnish two pieces of
information:
@@ -1206,8 +864,8 @@ information:
an IBAN or
``payto://x-taler-bank/localhost:8080/2`` for the 2nd bank account a
the Taler bank demonstrator running at ``localhost`` on port 8080.
- The first part of the URI following ``payto://`` (“iban” or
- “x-taler-bank”) is called the wire method.
+ The first part of the URI following ``payto://`` (``iban`` or
+ ``x-taler-bank``) is called the wire method.
- The ``taler-exchange-wirewatch`` and ``taler-exchange-transfer``
tools needs to be provided resources for authentication
@@ -1216,20 +874,22 @@ information:
for HTTP basic authentication.
-A Taler Wire Gateway is configured in a configuration section that follows the
-pattern ``exchange-account-$id``, where ``$id`` is an internal identifier for
-the bank account accessed by the exchange. The basic information for an
+Each Taler wire gateway is configured in a configuration section that follows
+the pattern ``exchange-account-$id``, where ``$id`` is an internal identifier
+for the bank account accessed by the exchange. The basic information for an
account should be put in ``/etc/taler/conf.d/exchange-business.conf``. The
secret credentials to access the Taler Wire Gateway API should be put into a
corresponding ``exchange-accountcredentials-$id`` section in
``/etc/taler/secrets/exchange-accountcredentials.conf``. The latter file
-should already be only readable for the ``taler-exchange-wire`` user. Other
-exchange processes should not have access to this information.
+should be only readable for the ``taler-exchange-wire`` user. Only the
+``taler-exchange-wirewatch`` and ``taler-exchange-transfer`` services should
+run as the ``taler-exchange-wire`` user. Other exchange processes do not need
+to have access to the account credentials.
You can configure multiple accounts for an exchange by creating sections
-starting with “exchange-account-” for the section name. You can ENABLE for
-each account whether it should be used, and for what (incoming or outgoing
-wire transfers):
+starting with ``exchange-account-`` for the section name. You must specify
+``ENABLE_``-settings for each account whether it should be used, and for what
+(incoming or outgoing wire transfers):
.. code-block:: ini
:caption: /etc/taler/conf.d/exchange-business.conf
@@ -1264,15 +924,15 @@ wire transfers):
# LibEuFin expects basic auth.
WIRE_GATEWAY_AUTH_METHOD = basic
- # Username and password set in LibEuFin.
+ # Username and password to access the Taler wire gateway.
USERNAME = ...
PASSWORD = ...
- # Base URL of the wire gateway set up with LibEuFin.
+ # Base URL of the Taler wire gateway.
WIRE_GATEWAY_URL = ...
-Such a Wire Gateway configuration can be tested with the following commands:
+Such a wire gateway configuration can be tested with the following commands:
.. code-block:: shell-session
@@ -1281,7 +941,8 @@ Such a Wire Gateway configuration can be tested with the following commands:
[root@exchange-online]# taler-exchange-wire-gateway-client \
--section exchange-accountcredentials-1 --credit-history
-
+On success, you will see some of your account's transaction history (or an
+empty history), while on failure you should see an error message.
.. _LegalSetup:
@@ -1300,7 +961,7 @@ Legal conditions for using the service
KYC Configuration
------------------
+=================
To legally operate, Taler exchange operators may have to comply with KYC
regulation that requires financial institutions to identify parties involved
@@ -1312,11 +973,20 @@ Taler permits an exchange to require KYC data under the following circumstances:
* Wallet receives (via refunds) money resulting in a balance over a threshold
* Wallet receives money via P2P payments over a threshold
* Merchant receives money over a threshold
- * Reserve is "opened" for invoicing or rewards (**planned feature**)
+ * Reserve is "opened" for invoicing (**planned feature**)
+
+Any of the above requests can trigger the KYC process,
+which can be illustrated as follows:
+
+.. image:: kyc-process.png
+
+At the end of the KYC process, the wallet re-tries the
+original request, and assuming KYC was successful, the
+request should then succeed.
Taler KYC Terminology
-^^^^^^^^^^^^^^^^^^^^^
+---------------------
* **Check**: A check establishes a particular attribute of a user, such as
their name based on an ID document and lifeness, mailing address, phone
@@ -1355,7 +1025,7 @@ Taler KYC Terminology
KYC Configuration Options
-^^^^^^^^^^^^^^^^^^^^^^^^^
+-------------------------
The KYC configuration determines the *legitimization rules*, and specifies
which providers offer which *checks* at what *cost*.
@@ -1412,7 +1082,7 @@ per configuration section:
OAuth 2.0 specifics
-^^^^^^^^^^^^^^^^^^^
+-------------------
In terms of configuration, the OAuth 2.0 logic requires the respective client
credentials to be configured apriori to enable access to the legitimization
@@ -1443,11 +1113,15 @@ service. The OAuth 2.0 configuration options are:
# Mustach template that converts OAuth2.0 data about the user
# into GNU Taler standardized attribute data.
- #
- KYC_OAUTH2_ATTRIBUTE_TEMPLATE = "{"fullname":"{{last_name}}, {{first_name}}","phone":"{{phone}}"}"
+ KYC_OAUTH2_CONVERTER_HELPER = taler-exchange-kyc-oauth2-challenger.sh
-The ``KYC_OAUTH2_ATTRIBUTE_TEMPLATE`` provides a generic way to convert data
-returned by an OAuth-provider into the internal format used by the exchange.
+The converter helper is expected to be customized to the selected OAuth2.0
+service: different services may return different details about the user or
+business, hence there cannot be a universal converter for all purposes. The
+default shell script uses the ``jq`` tool to convert the JSON returned by the
+service into the KYC attributes (also in JSON) expected by the exchange. The
+script will need to be adjusted based on the attributes collected by the
+specific backend.
The Challenger service for address validation supports OAuth2.0, but does not
have a static AUTHORIZE_URL. Instead, the AUTHORIZE_URL must be enabled by the client
@@ -1475,15 +1149,20 @@ configuration above and an exchange running on the host
Persona specifics
-^^^^^^^^^^^^^^^^^
+-----------------
We use the hosted flow. The Persona endpoints return a ``request-id``, which
we log for diagnosis.
Persona should be configured to use the ``/kyc-webhook/`` endpoint of the
-exchange to notify the exchange about the completion of KYC processes.
-The webhook is authenticated using a shared secret, which should
-be in the configuration.
+exchange to notify the exchange about the completion of KYC processes. The
+webhook is authenticated using a shared secret, which should be in the
+configuration. To use the Persona webhook, you must set the webhook URL in
+the Persona service to ``$EXCHANGE_BASE_URL/kyc-webhook/$SECTION_NAME/`` where
+``$SECTION_NAME`` is the name of the configuration section. You should also
+extract the authentication token for the webhook and put it into the
+configuration as shown above.
+
.. code-block:: ini
:caption: /etc/taler/conf.d/exchange-persona.conf
@@ -1503,29 +1182,31 @@ be in the configuration.
# Which subdomain is used for our API?
KYC_PERSONA_SUBDOMAIN = taler
- # Helper to convert JSON with KYC data returned by Persona into GNU Taler
- # internal format. Should probably always be set to
- # "taler-exchange-kyc-persona-converter.sh".
- KYC_PERSONA_CONVERTER_HELPER = "taler-exchange-kyc-persona-converter.sh"
-
# Authentication token to use.
- KYC_PERSONA_AUTH_TOKEN = persona_sandbox_42
+ KYC_PERSONA_AUTH_TOKEN = persona_sandbox_42XXXX
# Form to use.
KYC_PERSONA_TEMPLATE_ID = itempl_Uj6Xxxxx
# Where do we redirect to after KYC finished successfully.
- KYC_PERSONA_POST_URL = "https://taler.net/"
+ KYC_PERSONA_POST_URL = "https://taler.net/kyc-done"
# Salt to give to requests for idempotency.
# Optional.
# KYC_PERSONA_SALT = salt
-To use the Persona webhook, you must set the webhook URL in the
-Persona service to ``$EXCHANGE_BASE_URL/kyc-webhook/$SECTION_NAME/``
-where ``$SECTION_NAME`` is the name of the configuration section.
-You should also extract the authentication token for the webhook
-and put it into the configuration as shown above.
+ # Helper to convert JSON with KYC data returned by Persona into GNU Taler
+ # internal format. Should probably always be set to some variant of
+ # "taler-exchange-kyc-persona-converter.sh".
+ KYC_PERSONA_CONVERTER_HELPER = "taler-exchange-kyc-persona-converter.sh"
+
+The converter helper is expected to be customized to the
+selected template: different templates may return different details
+about the user or business, hence there cannot be a universal converter
+for all purposes. The default shell script uses the ``jq`` tool to
+convert the JSON returned by Persona into the KYC attributes (also
+in JSON) expected by the exchange. The script will need to be adjusted
+based on the attributes collected by the specific template.
KYC AID specifics
@@ -1533,8 +1214,8 @@ KYC AID specifics
We use the hosted flow.
-KYCAID should be configured to use the ``/kyc-webhook/`` endpoint of the
-exchange to notify the exchange about the completion of KYC processes.
+KYCAID must be configured to use the ``/kyc-webhook/$SECTION_NAME/`` endpoint
+of the exchange to notify the exchange about the completion of KYC processes.
.. code-block:: ini
:caption: /etc/taler/conf.d/exchange-kycaid.conf
@@ -1553,7 +1234,19 @@ exchange to notify the exchange about the completion of KYC processes.
KYC_KYCAID_FORM_ID = XXX
# URL to go to after the process is complete.
- KYC_KYCAID_POST_URL = "https://taler.net/"
+ KYC_KYCAID_POST_URL = "https://taler.net/kyc-done"
+
+ # Script to convert the KYCAID data into the Taler format.
+ KYC_KYCAID_CONVERTER_HELPER = taler-exchange-kyc-kycaid-converter.sh
+
+
+The converter helper is expected to be customized to the selected template:
+different templates may return different details about the user or business,
+hence there cannot be a universal converter for all purposes. The default
+shell script uses the ``jq`` tool to convert the JSON returned by Persona into
+the KYC attributes (also in JSON) expected by the exchange. The script will
+need to be adjusted based on the attributes collected by the specific
+template.
.. _Deployment:
@@ -1695,7 +1388,7 @@ started using a simple command:
At this point, the exchange service is not yet fully operational.
-To check whether the exchange is running correctly under the advertized
+To check whether the exchange is running correctly under the advertised
base URL, run:
.. code-block:: shell-session
@@ -1790,6 +1483,8 @@ periodically, as it signs the various online signing keys of the exchange
which periodically expire.
+.. _exchange-account-signing:
+
Account signing
---------------
@@ -1798,7 +1493,7 @@ The ``enable-account`` step is important to must be used to sign the
correct address to wire funds to. Note that for each bank account, additional
options **must** be set in the configuration file to tell the exchange how to
access the bank account. The offline tool *only* configures the externally
-visible portions of the setup. The chapter on `Bank account <_Bank-account>`_ configuration has further details.
+visible portions of the setup. The chapter on `bank account configuration <_exchange-bank-account-configuration>`_ has further details.
taler-exchange-offline accepts additional options to configure the use of the
account. For example, additional options can be used to add currency
@@ -1907,7 +1602,7 @@ of ``taler-exchange-offline``.
operation.
AML Configuration
------------------
+=================
The AML configuration steps are used to add or remove keys of exchange
operator staff that are responsible for anti-money laundering (AML)
@@ -1918,7 +1613,7 @@ request additional KYC data from the consumer and can change the threshold
amount above which a further AML review is triggered.
AML Officer Setup
-^^^^^^^^^^^^^^^^^
+-----------------
To begin the AML setup, AML staff should launch the GNU Taler
exchange AML SPA Web interface. (FIXME-Sebastian: how?). The
@@ -1953,7 +1648,7 @@ Access rights can be revoked at any time using:
AML Triggers
-^^^^^^^^^^^^
+------------
AML decision processes are automatically triggered under certain configurable
conditions. The primary condition that *must* be configured is the
@@ -1984,10 +1679,49 @@ makes the decision given the KYC attributes:
The given program will be given the KYC attributes in JSON format on standard
input, and must return 0 to continue without AML and non-zero to flag the
-account for manual review. To disable this triger, simply leave the option to
+account for manual review. To disable this trigger, simply leave the option to
its default value of '[/usr/bin/]true'. To flag all new users for manual
review, simply set the program to '[/usr/bin/]false'.
+AML Forms
+---------
+
+AML forms are defined by the DD 54 dynamic forms.
+The shipped implementation with of the exchange is installed in
+
+.. code-block:: shell-session
+
+ ${INSTALL_PREFIX}/share/taler/exchange/spa/forms.js
+
+
+The variable ``form`` contains the list of all form available. For
+every entry in the list the next properties are expected to be present:
+
+``label``: used in the UI as the name of the form
+
+``id``: identification name, this will be saved in the exchange database
+along with the values to correctly render the form again.
+It should simple, short and without any character outside numbers,
+letters and underscore.
+
+``version``: when editing a form, instead of just replacing fields
+it will be better to create a new form with the same id and new version.
+That way old forms in the database will used old definition of the form.
+It should be a number.
+
+``impl`` : a function that returns the design and behavior of form.
+See DD 54 dynamic forms.
+
+.. attention::
+
+ do not remove a form the list if it has been used. Otherwise you
+ won't be able to see the information save in the exchange database.
+
+To add a new one you can simply copy and paste one element, and edit it.
+
+It is much easier to download ``@gnu-taler/aml-backoffice-ui`` source
+from ``https://git.taler.net/wallet-core.git/``, compile and copy the file
+from the ``dist/prod``.
Setup Linting
@@ -2104,6 +1838,13 @@ After enough time has passed, the money should arrive at the specified IBAN.
For more information on the taler-wallet-cli tool, see
:doc:`taler-wallet`.
+taler-config
+------------
+
+.. _Using-taler_002dconfig-exchange:
+
+.. include:: frags/using-taler-config.rst
+
Private key storage
-------------------
@@ -2201,6 +1942,323 @@ grant the permissions to the other exchange processes again.
+.. _ExchangeTemplateCustomization:
+
+Template Customization
+======================
+
+The Exchange comes with various HTML templates that are shown to
+guide users through the KYC process. The Exchange uses `Mustach
+<https://gitlab.com/jbol/mustach>`__ as the templating engine. This section
+describes the various templates. In general, the templates must be installed
+to the ``share/taler/exchange/templates/`` directory. The file names must be of
+the form ``$NAME.$LANG.must`` where ``$NAME`` is the name of the template and
+``$LANG`` is the 2-letter language code of the template. English templates
+must exist and will be used as a fallback. If the browser (user-agent) has
+provided language preferences in the HTTP header and the respective language
+exists, the correct language will be automatically served.
+
+The following subsections give details about each of the templates. Most
+subsection titles are the ``$NAME`` of the respective template.
+
+
+Generic Errors Templates
+------------------------
+
+A number of templates are used for generic errors. These are:
+
+ * kyc-proof-already-done (KYC process already completed)
+ * kyc-bad-request (400 Bad Request)
+ * kyc-proof-endpoint-unknown (404 Not Found for KYC logic)
+ * kyc-proof-internal-error (500 Internal Server Error)
+ * kyc-proof-target-unknown (404 Not Found for KYC operation)
+
+All of these templates are instantiated using the following information:
+
+ * ec: Integer; numeric Taler error code, should be shown to indicate the
+ error compactly for reporting to developers
+
+ * hint: String; human-readable Taler error code, should be shown for the
+ user to understand the error
+
+ * message: String; optional, extended human-readable text provided to elaborate
+ on the error, should be shown to provide additional context
+
+
+kycaid-invalid-request
+----------------------
+
+The KYCaid plugin does not support requests to the
+``/kyc-proof/`` endpoint (HTTP 400 bad request).
+
+This template is instantiated using the following information:
+
+ * ec: Integer; numeric Taler error code, should be shown to indicate the
+ error compactly for reporting to developers
+
+ * hint: String; human-readable Taler error code, should be shown for the
+ user to understand the error
+
+ * error: String; error code from the server
+
+ * error_details: String; optional error description from the server
+
+ * error_uri: optional URI with further details about the error from the server
+
+
+
+oauth2-authentication-failure
+-----------------------------
+
+The OAuth2 server said that the request was not
+properly authenticated (HTTP 403 Forbidden).
+
+
+This template is instantiated using the following information:
+
+ * ec: Integer; numeric Taler error code, should be shown to indicate the
+ error compactly for reporting to developers
+
+ * hint: String; human-readable Taler error code, should be shown for the
+ user to understand the error
+
+
+oauth2-authorization-failure
+----------------------------
+
+The OAuth2 server refused to return the KYC data
+because the authorization code provided was
+invalid (HTTP 403 Forbidden).
+
+This template is instantiated using the following information:
+
+ * ec: Integer; numeric Taler error code, should be shown to indicate the
+ error compactly for reporting to developers
+
+ * hint: String; human-readable Taler error code, should be shown for the
+ user to understand the error
+
+ * error: String; error code from the server
+
+ * error_message: String; error message from the server
+
+
+oauth2-authorization-failure-malformed
+--------------------------------------
+
+The server refused the authorization, but then provided
+a malformed response (HTTP 502 Bad Gateway).
+
+This template is instantiated using the following information:
+
+ * ec: Integer; numeric Taler error code, should be shown to indicate the
+ error compactly for reporting to developers
+
+ * hint: String; human-readable Taler error code, should be shown for the
+ user to understand the error
+
+ * debug: Bool; true if we are running in debug mode and are allowed to return HTML with potentially sensitive information
+
+ * server_response: Object; could be NULL; this includes the (malformed) OAuth2 server response, it should be shown to the use if "debug" is true
+
+
+oauth2-bad-request
+------------------
+
+The client made an invalid request (HTTP 400 Bad Request).
+
+This template is instantiated using the following information:
+
+ * ec: Integer; numeric Taler error code, should be shown to indicate the
+ error compactly for reporting to developers
+
+ * hint: String; human-readable Taler error code, should be shown for the
+ user to understand the error
+
+ * message: String; additional error message elaborating on what was bad about the request
+
+
+oauth2-conversion-failure
+-------------------------
+
+Converting the KYC data into the exchange's internal
+format failed (HTTP 502 Bad Gateway).
+
+This template is instantiated using the following information:
+
+ * ec: Integer; numeric Taler error code, should be shown to indicate the
+ error compactly for reporting to developers
+
+ * hint: String; human-readable Taler error code, should be shown for the
+ user to understand the error
+
+ * debug: Bool; true if we are running in debug mode and are allowed to return HTML with potentially sensitive information
+
+ * converter: String; name of the conversion command that failed which was used by the Exchange
+
+ * attributes: Object; attributes returned by the conversion command, often NULL (after all, conversion failed)
+
+ * message: error message elaborating on the conversion failure
+
+
+oauth2-provider-failure
+-----------------------
+
+We did not get an acceptable response from the OAuth2
+provider (HTTP 502 Bad Gateway).
+
+This template is instantiated using the following information:
+
+ * ec: Integer; numeric Taler error code, should be shown to indicate the
+ error compactly for reporting to developers
+
+ * hint: String; human-readable Taler error code, should be shown for the
+ user to understand the error
+
+ * message: String; could be NULL; text elaborating on the details of the failure
+
+
+persona-exchange-unauthorized
+-----------------------------
+
+The Persona server refused our request (HTTP 403 Forbidden from Persona, returned as a HTTP 502 Bad Gateway).
+
+This template is instantiated using the following information:
+
+ * ec: Integer; numeric Taler error code, should be shown to indicate the
+ error compactly for reporting to developers
+
+ * hint: String; human-readable Taler error code, should be shown for the
+ user to understand the error
+
+ * data: Object; data returned from Persona service, optional
+
+ * persona_http_status: Integer; HTTP status code returned by Persona
+
+
+persona-load-failure
+--------------------
+
+The Persona server refused our request (HTTP 429 Too Many Requests from Persona, returned as a HTTP 503 Service Unavailable).
+
+This template is instantiated using the following information:
+
+ * ec: Integer; numeric Taler error code, should be shown to indicate the
+ error compactly for reporting to developers
+
+ * hint: String; human-readable Taler error code, should be shown for the
+ user to understand the error
+
+ * data: Object; data returned from Persona service, optional
+
+ * persona_http_status: Integer; HTTP status code returned by Persona
+
+
+persona-exchange-unpaid
+-----------------------
+
+The Persona server refused our request (HTTP 402 Payment REquired from Persona, returned as a HTTP 503 Service Unavailable).
+
+This template is instantiated using the following information:
+
+ * ec: Integer; numeric Taler error code, should be shown to indicate the
+ error compactly for reporting to developers
+
+ * hint: String; human-readable Taler error code, should be shown for the
+ user to understand the error
+
+ * data: Object; data returned from Persona service, optional
+
+ * persona_http_status: Integer; HTTP status code returned by Persona
+
+
+
+persona-logic-failure
+---------------------
+
+The Persona server refused our request (HTTP 400, 403, 409, 422 from Persona, returned as a HTTP 502 Bad Gateway).
+
+This template is instantiated using the following information:
+
+ * ec: Integer; numeric Taler error code, should be shown to indicate the
+ error compactly for reporting to developers
+
+ * hint: String; human-readable Taler error code, should be shown for the
+ user to understand the error
+
+ * data: Object; data returned from Persona service, optional
+
+ * persona_http_status: Integer; HTTP status code returned by Persona
+
+
+persona-invalid-response
+------------------------
+
+The Persona server refused our request in an
+unexpected way; returned as a HTTP 502 Bad Gateway.
+
+This template is instantiated using the following information:
+
+ * ec: Integer; numeric Taler error code, should be shown to indicate the
+ error compactly for reporting to developers
+
+ * hint: String; human-readable Taler error code, should be shown for the
+ user to understand the error
+
+ * debug: Bool; true if we are running in debug mode and are allowed to return HTML with potentially sensitive information
+
+ * server_response: Object; could be NULL; this includes the (malformed) OAuth2 server response, it should be shown to the use if "debug" is true
+
+
+persona-network-timeout
+-----------------------
+
+The Persona server refused our request (HTTP 408 from Persona, returned as a HTTP 504 Gateway Timeout).
+
+This template is instantiated using the following information:
+
+ * ec: Integer; numeric Taler error code, should be shown to indicate the
+ error compactly for reporting to developers
+
+ * hint: String; human-readable Taler error code, should be shown for the
+ user to understand the error
+
+ * data: Object; data returned from Persona service, optional
+
+ * persona_http_status: Integer; HTTP status code returned by Persona
+
+
+persona-kyc-failed
+------------------
+
+The Persona server indicated a problem with the KYC process, saying it was not completed.
+
+This template is instantiated using the following information:
+
+ * persona_inquiry_id: String; internal ID of the inquiry within Persona, useful for further diagnostics by staff
+
+ * data: Object; could be NULL; this includes the server response, it contains extensive diagnostics, see Persona documentation on their ``/api/v1/inquiries/$ID``.
+
+ * persona_http_status: Integer; HTTP status code returned by Persona
+
+persona-provider-failure
+------------------------
+
+The Persona server refused our request (HTTP 500 from Persona, returned as a HTTP 502 Bad Gateway).
+
+This template is instantiated using the following information:
+
+ * ec: Integer; numeric Taler error code, should be shown to indicate the
+ error compactly for reporting to developers
+
+ * hint: String; human-readable Taler error code, should be shown for the
+ user to understand the error
+
+ * data: Object; data returned from Persona service, optional
+
+ * persona_http_status: Integer; HTTP status code returned by Persona
+
+
.. _ExchangeBenchmarking:
Benchmarking
diff --git a/taler-merchant-api-tutorial.rst b/taler-merchant-api-tutorial.rst
index 739cf07f..15e21e21 100644
--- a/taler-merchant-api-tutorial.rst
+++ b/taler-merchant-api-tutorial.rst
@@ -19,8 +19,12 @@
.. _merchant-api-tutorial:
-GNU Taler Merchant API Tutorial
-###############################
+Merchant API Tutorial
+#####################
+
+.. contents:: Table of Contents
+ :depth: 2
+ :local:
Introduction
============
@@ -63,10 +67,6 @@ If you want to look at some simple, running examples, check out these:
that accepts donations for software projects and gives donation
receipts.
-- The
- `survey <https://git.taler.net/taler-merchant-demos.git/tree/talermerchantdemos/survey>`__
- that gives users who answer a question a small reward.
-
- The `WooCommerce plugin <https://git.taler.net/gnu-taler-payment-for-woocommerce.git/>`__
which is a comprehensive integration into a Web shop including the refund business
process.
@@ -413,69 +413,6 @@ considered to identify a resource you can pay for and thus do not have to be
unique.
-.. _Giving-Customers-Rewards:
-.. index:: rewards
-
-Giving Customers Rewards
-========================
-
-GNU Taler allows Web sites to grant digital cash directly to a visitor. The
-idea is that some sites may want incentivize actions such as filling out a
-survey or trying a new feature. It is important to note that receiving rewards is
-not enforceable for the visitor, as there is no contract. It is simply a
-voluntary gesture of appreciation of the site to its visitor. However, once a
-reward has been granted, the visitor obtains full control over the funds provided
-by the site.
-
-The merchant backend of the site must be properly configured for rewards, and
-sufficient funds must be made available for rewards. See the :ref:`Taler User
-Guide <Rewarding-visitors>` for details.
-
-To check if rewards are configured properly and if there are sufficient
-funds available for granting rewards, query the ``/private/reserves`` endpoint:
-
-.. code-block:: python
-
- >>> import requests
- >>> requests.get("https://backend.demo.taler.net/private/reserves",
- ... headers={"Authorization": "Bearer secret-token:sandbox"})
- <Response [200]>
-
-Check that a reserve exists where the ``merchant_initial_amount`` is below the
-``committed_amount`` and that the reserve is ``active``.
-
-.. _authorize-reward:
-
-To authorize a reward, ``POST`` to ``/private/rewards``. The following fields
-are recognized in the JSON request object:
-
-- ``amount``: Amount that should be given to the visitor as a reward.
-
-- ``justification``: Description of why the reward was granted. Human-readable
- text not exposed to the customer, but used by the Back Office.
-
-- ``next_url``: The URL that the user’s browser should be redirected to by
- the wallet, once the reward has been processed.
-
-The response from the backend contains a ``taler_reward_url``. The
-customer’s browser must be redirected to this URL for the wallet to pick
-up the reward.
-
-.. _pick-up-reward:
-
-This code snipped illustrates giving a reward:
-
-.. code-block:: python
-
- >>> import requests
- >>> reward_req = dict(amount="KUDOS:0.5",
- ... justification="User filled out survey",
- ... next_url="https://merchant.com/thanks.html")
- >>> requests.post("https://backend.demo.taler.net/private/rewards", json=reward_req,
- ... headers={"Authorization": "Bearer secret-token:sandbox"})
- <Response [200]>
-
-
.. _Advanced-topics:
Advanced topics
diff --git a/taler-merchant-manual.rst b/taler-merchant-manual.rst
index 0ad9bb30..48605a55 100644
--- a/taler-merchant-manual.rst
+++ b/taler-merchant-manual.rst
@@ -18,8 +18,13 @@
.. _taler-merchant-backend-operator-manual:
-GNU Taler Merchant Backend Operator Manual
-##########################################
+Merchant Backend Operator Manual
+################################
+
+.. contents:: Table of Contents
+ :depth: 1
+ :local:
+
Introduction
============
@@ -42,17 +47,6 @@ We expect some moderate familiarity with the compilation and
installation of Free Software packages. An understanding of cryptography
is not required.
-This first chapter of the manual will give a brief overview of the
-overall Taler architecture, describing the environment in which the
-Taler backend operates. The second chapter then explains how to install
-the software, including key dependencies. The third chapter will explain
-how to configure the backend, including in particular the configuration
-of the bank account details of the merchant.
-
-The last chapter gives some additional information about advanced topics
-which will be useful for system administrators but are not necessary for
-operating a basic backend.
-
.. _Architecture-overview:
Architecture overview
@@ -152,11 +146,12 @@ main Taler configuration (especially the accepted *currency* and *exchanges*).
acceptable to consider instances to be the "users" or "accounts" of a
merchant backend and the bearer token is equivalent to a passphrase.
+.. _instance-bank-account:
Instance Bank Accounts
----------------------
-.. index:: instance-bank-account
+.. index:: Bank account
To receive payments, an instance must have configured one or more bank
*accounts*. When configuring the bank account of an instance, one should
@@ -260,6 +255,61 @@ After the *legal expiration* (by default: a decade), contract information is
deleted when running the garbage collector using ``taler-merchant-dbinit``.
+.. _template:
+
+Templates
+---------
+
+.. index:: Template
+
+Usually, a merchant must use an authenticated endpoint to create an order and
+then share the link to the order with a wallet. Templates are a mechanism that
+allows wallets to create their own orders directly, using a public endpoint.
+The template fixes some properties of the contracts created from it, while
+other details may be left for the customer to provide. Templates are useful
+in cases where the point-of-sale of a merchant is offline (and thus cannot
+setup an order), or even in cases where a simple static QR code is desired to
+accept payments or donations.
+
+When generating a template, the "summary" text of the contract and the
+"amount" to be paid by the customer can be fixed or left for the customer to
+specify. If the customer is expected to provide either or both of these
+values, the template link (or QR code) can specify a default value. For
+example, a cafeteria with a fixed price lunch may use a "lunch" template with
+both values fixed to the lunch price and the "lunch" product, a bakery might
+fix the summary to "baked goods" but allow the customer to enter the amount
+based on the total price of the items being bought, and a charity may allow
+donating an arbitrary amount and summary message while also suggesting default
+values.
+
+If an offline merchant wants to confirm that a customer did actually pay the
+agreed amount using an order derived from a template, they can associate an
+OTP device with the template.
+
+
+.. _otp-device:
+
+OTP Devices
+-----------
+
+.. index:: OTP
+.. index:: TOTP
+
+A One-Time-Password (OTP) generator is a device or application that generates
+a 4 to 8 digit code typically used for authentication. The widely used TOTP
+standard is described in `RFC 6238 <https://www.rfc-editor.org/rfc/rfc6238>`_.
+For GNU Taler merchant backends, OTP devices are used as a way to assure a
+merchant without network connectivity that a customer made a digital
+payment. The idea is described in depth in our `SUERF Policy Brief
+<https://www.suerf.org/suer-policy-brief/69851/practical-offline-payments-using-one-time-passcodes>`_.
+To use this method, a merchant must configure the OTP device's shared secret
+in the merchant backend, and then associate the OTP device with a
+:ref:`template`. Once the customer has paid, they are given a list of OTP
+codes which must be shown to the merchant who can check that at least one of
+the codes matches their OTP device, proving that the customer made the
+payment.
+
+
Transfers
---------
@@ -273,55 +323,51 @@ the backend does not have access to the incoming wire transfers of the
merchant's bank account. In this case, merchants should manually provide the
backend with wire *transfer* data that specifies the *wire transfer subject*
and the amount that was received. Given this information, the backend can
-detect and report any irregularities that might arise.
+detect and report any irregularities that might arise.
-Rewards
--------
-.. index:: reward
-.. index:: pick up
+Webhooks
+--------
-Taler does not only allow a Website to be paid, but also to make voluntary,
-non-contractual payments to visitors, called *rewards*. Such rewards could be
-granted as a reward for filling in surveys or watching advertizements. For
-rewards, there is no contract, rewards are always voluntary actions by the Web
-site that do not arise from a contractual obligation. Before a Web site
-can create rewards, it must establish a reserve. Once a reserve has been
-established, the merchant can *grant* rewards, allowing wallets to *pick up*
-the reward.
+.. index:: webhook
+
+A webhook is a pre-defined HTTP request that the GNU Taler merchant backend
+will make upon certain events, such as an order being paid or refunded. When
+the configured event happens, the merchant backend will make an HTTP request
+to the endpoint configured in the webhook configuration, possibly sending
+selected data about the event to the respective Web service. Webhooks can be
+used to trigger additional business logic outside of the GNU Taler merchant
+backend.
-.. note::
- Rewards are an optional feature, and exchanges may disable rewards (usually
- if they see compliance issues). In this case, the reward feature will
- not be available.
+Installation
+============
+This chapter describes how to install the GNU Taler merchant backend.
-Reserves
---------
+.. _Generic-instructions:
-.. index:: reserve
-.. index:: close
+Installing the GNU Taler binary packages on Debian
+--------------------------------------------------
-A *reserve* is a pool of electronic cash at an exchange under the control of
-a private key. Merchants withdraw coins from a reserve when granting
-rewards. A reserve is established by first generating the required key material
-in the merchant backend, and then wiring the desired amount of funds to the
-exchange.
+.. include:: frags/installing-debian.rst
-An exchange will automatically *close* a reserve after a fixed period of time
-(typically about a month), wiring any remaining funds back to the merchant.
-While exchange APIs exists to (1) explicitly *open* a reserve to prevent it
-from being automatically closed and to (2) explicitly *close* a reserve at any
-time, the current merchant backend does not make use of these APIs.
+.. include:: frags/apt-install-taler-merchant.rst
-Installation
-============
+Installing the GNU Taler binary packages on Trisquel
+----------------------------------------------------
-This chapter describes how to install the GNU Taler merchant backend.
+.. include:: frags/installing-trisquel.rst
+
+
+Installing the GNU Taler binary packages on Ubuntu
+--------------------------------------------------
+
+.. include:: frags/installing-ubuntu.rst
+
+.. include:: frags/apt-install-taler-merchant.rst
-.. _Generic-instructions:
Installing from source
----------------------
@@ -360,32 +406,10 @@ libraries!
.. include:: frags/install-before-check.rst
-Installing the GNU Taler binary packages on Debian
---------------------------------------------------
-
-.. include:: frags/installing-debian.rst
-
-.. include:: frags/apt-install-taler-merchant.rst
-
-
-Installing the GNU Taler binary packages on Trisquel
-----------------------------------------------------
-
-.. include:: frags/installing-trisquel.rst
-
-
-Installing the GNU Taler binary packages on Ubuntu
---------------------------------------------------
-
-.. include:: frags/installing-ubuntu.rst
-
-.. include:: frags/apt-install-taler-merchant.rst
+How to configure the merchant backend
+=====================================
-How to configure the merchant’s backend
-=======================================
-
-.. index:: taler-config
.. index:: taler.conf
The installation already provides reasonable defaults for most of the
@@ -394,13 +418,11 @@ database that the backend should use. By default, the file
``$HOME/.config/taler.conf`` is where the Web shop administrator specifies
configuration values that augment or override the defaults.
Note that when using our binary packages, the systemd service files
-force the use of ``/etc/taler.conf`` as the main configuration file.
+force the use of ``/etc/taler/taler.conf`` as the main configuration file.
.. include:: frags/configuration-format.rst
-.. include:: frags/using-taler-config.rst
-
.. _Backend-options:
@@ -426,12 +448,17 @@ modified. Here, the notation ``[$SECTION]/$OPTION`` denotes the option
Service address
^^^^^^^^^^^^^^^
-The following option sets the transport layer address used by the
-merchant backend:
+The service address specifies where the taler-merchant-httpd should listen for
+requests. When using the Debian/Ubuntu packages, these options will already be
+configured correctly for the included Nginx and Apache configurations and will
+not need any changes.
+
+The following option sets the transport protocol used by the merchant backend:
.. code-block:: ini
- [MERCHANT]/SERVE = tcp | unix
+ [MERCHANT]
+ SERVE = unix # or tcp
If this option is set to
@@ -449,23 +476,27 @@ the backend to the network.
To run the Taler backend on TCP port 8888, use:
-.. code-block:: console
+.. code-block:: ini
- $ taler-config -s MERCHANT -o SERVE -V tcp
- $ taler-config -s MERCHANT -o PORT -V 8888
+ [MERCHANT]
+ SERVE = tcp
+ PORT = 8888
.. note::
- When using the Debian/Ubuntu packages, these options are already
- configured in the ``/etc/taler/conf.d/merchant.conf`` configuration file.
-
- If you need to change them, you should edit
- ``/etc/taler/merchant-overrides.conf``. By default, the Taler merchant
- package will use a UNIX domain socket at
+ If you need to change where the taler-merchant-httpd listens for requests,
+ you should edit ``/etc/taler/merchant-overrides.conf``. By default, the
+ Taler merchant package will use a UNIX domain socket at
``/run/taler/merchant-httpd/merchant-http.sock``. For the best possible
security it is recommended to leave this in place and configure a reverse
proxy (Nginx or Apache) as described below.
+ When using the Debian/Ubuntu packages, the use of a UNIX domain socket
+ is already pre-configured in the ``/etc/taler/conf.d/merchant.conf``
+ configuration file. Suitable reverse proxy configuration
+ file templates (``taler-merchant``) are be installed in the
+ respective ``sites-available`` directories of Apache and Nginx.
+
Currency
@@ -476,15 +507,17 @@ specified using the option
.. code-block:: ini
- [TALER]/CURRENCY
+ [TALER]
+ CURRENCY = EUR # or USD, ...
When testing with the Taler demonstration exchange at
https://exchange.demo.taler.net/ you must set this
value to ``KUDOS``:
-.. code-block:: console
+.. code-block:: ini
- $ taler-config -s TALER -o CURRENCY -V KUDOS
+ [TALER]
+ CURRENCY = KUDOS
.. note::
@@ -504,7 +537,8 @@ The option
.. code-block:: ini
- [MERCHANT]/DB
+ [MERCHANT]
+ DB = postgres
specifies which DBMS is to be used. However, currently only the value
``postgres`` is supported. This is also the default.
@@ -524,14 +558,14 @@ For the ``postgres`` backend, you need to specify:
.. code-block:: ini
- [MERCHANTDB-postgres]
- CONFIG = "postgres://..."
+ [merchantdb-postgres]
+ CONFIG = "postgres:///taler-merchant"
-This option specifies a PostgreSQL access path, typicallly using the format
+This option specifies a PostgreSQL access path, typically using the format
``postgres:///$DBNAME``, where ``$DBNAME`` is the name of the PostgreSQL
-database you want to use. Suppose ``$USER`` is the name of the user who will
-run the backend process (usually ``taler-merchant-httpd``). Then, you need to
-first run:
+database you want to use (here, ``taler-merchant`` on the local machine).
+Suppose ``$USER`` is the name of the user who will run the backend process
+(usually ``taler-merchant-httpd``). Then, you need to first run:
.. code-block:: console
@@ -578,7 +612,7 @@ section, the following options need to be configured:
.. code-block:: ini
- [MERCHANT-EXCHANGE-demo]
+ [merchant-exchange-kudos]
EXCHANGE_BASE_URL = "https://exchange.demo.taler.net/"
- The ``MASTER_KEY`` option specifies the exchange’s master public key
@@ -586,25 +620,30 @@ section, the following options need to be configured:
.. code-block:: ini
- [MERCHANT-EXCHANGE-demo]
- MASTER_KEY = "FH1Y8ZMHCTPQ0YFSZECDH8C9407JR3YN0MF1706PTG24Q4NEWGV0"
+ [merchant-exchange-kudos]
+ MASTER_KEY = "GNRJCH0HYKN59939JC0CJ2JDC7ZNEBSATJFF00CVS3WPG4TQEA7G"
+
+ You can find out this key by running ``curl https://exchange.demo.taler.net/keys | jq .master_public_key``.
- The ``CURRENCY`` option specifies the exchange’s currency.
For the Taler demonstrator, use:
.. code-block:: ini
- [MERCHANT-EXCHANGE-demo]
+ [merchant-exchange-kudos]
CURRENCY = "KUDOS"
Note that multiple exchanges can be added to the system by using different
-identifiers in place of ``demo`` in the example above. Note that all of the
+identifiers in place of ``KUDOS`` in the example above. Note that all of the
exchanges actually used will use the same currency: If the currency does not
-match the main ``CURRENCY`` option from the ``TALER`` section, the respective
-``MERCHANT-EXCHANGE-`` section is automatically ignored. If you need support
+match the main ``CURRENCY`` option from the ``taler`` section, the respective
+``merchant-exchange-`` section is automatically ignored. If you need support
for multiple currencies, you need to deploy one backend per currency.
+The merchant already ships with a default configuration that contains the
+``merchant-exchange-kudos`` section from above.
+
.. note::
Manually setting up exchanges is only recommended under special
@@ -625,21 +664,21 @@ The following is an example for a complete backend configuration:
.. code-block:: ini
- [TALER]
+ [taler]
CURRENCY = KUDOS
- [MERCHANT]
+ [merchant]
SERVE = TCP
PORT = 8888
DATABASE = postgres
- [MERCHANTDB-postgres]
- CONFIG = postgres:///donations
+ [merchantdb-postgres]
+ CONFIG = postgres:///taler-merchant
- [merchant-exchange-NAME]
+ [merchant-exchange-kudos]
EXCHANGE_BASE_URL = https://exchange.demo.taler.net/
MASTER_KEY = FH1Y8ZMHCTPQ0YFSZECDH8C9407JR3YN0MF1706PTG24Q4NEWGV0
- # If currency does not match [TALER] section, the exchange
+ # If currency does not match [taler] section, the exchange
# will be ignored!
CURRENCY = KUDOS
@@ -660,20 +699,17 @@ Launching the backend
.. index:: taler-merchant-httpd
Assuming you have configured everything correctly, you can launch the
-merchant backend as ``$USER`` using
+merchant backend as ``$USER`` using (to provide a trivial example):
.. code-block:: console
$ taler-merchant-httpd &
$ taler-merchant-webhook &
$ taler-merchant-wirewatch &
+ $ taler-merchant-depositcheck &
+ $ taler-merchant-exchange &
-You only need to run ``taler-merchant-webhook`` if one of the instances is
-configured to trigger web hooks. Similarly, ``taler-merchant-wirewatch`` is
-only required if instances have accounts configured with automatic import of
-wire transfers via a bank wire gateway.
-
-To ensure these processes runs always in the background and also after
+To ensure these processes run always in the background and also after
rebooting, you should use systemd, cron or some other init system of your
operating system to launch the process. You should also periodically re-start
these services to prevent them from exhausing the memory utilization of the
@@ -684,8 +720,8 @@ how to start and stop daemons.
When using the Debian/Ubuntu packages, the systemd configuration
will already exist. You only need to enable and start the service
- using ``systemctl enable taler-merchant-httpd`` and
- ``systemctl start taler-merchant-httpd``. Additionally, you should
+ using ``systemctl enable taler-merchant.target`` and
+ ``systemctl start taler-merchant.target``. Additionally, you should
review the ``/etc/apache2/sites-available/taler-merchant.conf``
or ``/etc/nginx/sites-available/taler-merchant`` (these files
contain additional instructions to follow), symlink it to
@@ -693,7 +729,6 @@ how to start and stop daemons.
should be able to visit the merchant backend at the respective
HTTP(S) endpoint.
-
If everything worked as expected, the command
.. code-block:: console
@@ -705,7 +740,7 @@ should return some basic configuration status data about the service.
Please note that your backend might then be globally reachable without
any access control. You can either:
- * Use the ``--auth=$TOKEN`` command-line option to set an access token to be provided in an ``Authorize: Bearer $TOKEN`` HTTP header. Note that this can be used at anytime to override access control, but remains only in effect until a first instance is created or an existing instance authentication setting is modified.
+ * Use the ``--auth=$TOKEN`` command-line option to **taler-merchant-httpd** to set an access token to be provided in an ``Authorize: Bearer $TOKEN`` HTTP header. Note that this can be used at anytime to override access control, but remains only in effect until a first instance is created or an existing instance authentication setting is modified.
* Set the ``TALER_MERCHANT_TOKEN`` environment variable to ``$TOKEN`` for the same effect. This method has the advantage of ``$TOKEN`` not being visible as a command-line interface to other local users on the same machine.
* Set up an instance with an authentication token before some unauthorized person has a chance to access the backend. As the backend is useless without any instance and the chances of remote attackers during the initial configuration is low, this is probably sufficient for most use-cases. Still, keep the first two scenarios in mind in case you ever forget your access token!
@@ -720,15 +755,14 @@ and use TLS for improved network privacy, see :ref:`Secure setup <Secure-setup>`
Instance setup
==============
-First of all, we recommend the use of the single-page administration
-application (SPA) that is served by default at the base URL of the merchant
-backend. You can use it to perform all steps described in this section (and
-more!), using a simple Web interface instead of the ``wget`` commands given
-below.
+We recommend the use of the single-page administration application (SPA) that
+is served by default at the base URL of the merchant backend. You can use it
+to perform all steps described in this section (and more!), using a simple Web
+interface. Alternatively, you can also use the ``wget`` commands given below.
-Regardless of which tool you use, the first step for using the backend
+Regardless of which approach you use, the first step for using the backend
involves the creation of a ``default`` instance. The ``default`` instance can
-also create / delete / configure other instances, similar to the ``root``
+also create, configure or delete other instances, similar to the ``root``
account on UNIX. When no instance exists and ``taler-merchant-httpd`` was
started without the ``--auth`` option, then the backend is reachable without
any access control (unless you configured some in the reverse proxy).
@@ -747,8 +781,33 @@ times, once for each instance.
:ref:`reverse proxy <reverse-proxy-configuration>`.
-Setup without the Web interface
--------------------------------
+Instance setup with the SPA
+---------------------------
+
+In order to setup an instance, you need the merchant backend to already be
+running, and you must either have the credentials for the "default" instance,
+or no instance must be configured at all yet.
+
+To start, point your browser to ``$PROTO://backend.$DOMAIN_NAME/``, replacing
+"$PROTO" with "https" or (rarely) "http" and "$DOMAIN_NAME" with your
+organizations DNS domain or subdomain.
+
+.. note::
+
+ The label "backend" here is also just a suggestion, your administrator
+ can in principle choose any name.
+
+You should be welcomed by the following merchant backoffice page:
+
+.. image:: screenshots/merchant_first_login.png
+
+After supplying the required fields, primarily the name of your organization
+and the desired access token, click ``confirm``. You can change the instance
+settings later via the ``Settings`` entry in the menu on the left.
+
+
+Instance setup without the Web interface
+----------------------------------------
Instances can be created by POSTing a request to ``/management/instances``
without using the Web interface. This could be useful if you want to create
@@ -759,9 +818,8 @@ interface create a file ``instance.json`` with an
.. code-block:: json
{
- "accounts" : [{"payto_uri":"$PAYTO_URI"}],
"id" : "default",
- "name": "example.com",
+ "name": "Example Inc.",
"address": { "country" : "zz" },
"auth": { "method" : "external"} ,
"jurisdiction": { "country" : "zz" },
@@ -770,12 +828,7 @@ interface create a file ``instance.json`` with an
"default_pay_delay": { "d_ms" : 1209600000 }
}
-In the text above, you must replace ``$PAYTO_URI`` with your actual
-``payto://``-URI. You may also leave the account array empty. The instance
-owner must then configure the accounts before the instance becomes usable.
-
-Be sure to replace ``KUDOS`` with the fiat currency if the setup is for an
-actual bank. The ``name`` field will be shown as the name of your shop. The
+The ``name`` field will be shown as the name of your shop. The
``address`` field is expected to contain your shop's physical address. The
various defaults specify defaults for transaction fees your shop is willing to
cover, how long offers made to the customer are valid, and how long the
@@ -797,6 +850,125 @@ Endpoints to modify (reconfigure), permanently disable (while keeping the data)
or purge (deleting all associated data) instances exist as well and are documented
in the :ref:`Merchant Backend API documentation <merchant-api>`.
+.. _instance-account-setup:
+
+Instance account setup
+======================
+
+Before you can use an instance productively, you need to configure one or more
+bank accounts. These bank accounts will be provided to the Taler exchange
+operator to tell it where to wire the income from your sales. Every bank
+account has an associated *wire method* which determines how an exchange can
+transfer the funds. The most commonly supported wire method is *iban*, which
+implies that bank accounts are identified by IBAN numbers and wire transfers
+are to be executed between IBAN accounts. For regional currency setups, the
+wire method could also be *x-taler-bank*.
+
+.. note::
+
+ When using a regional currency, you need to first create a bank account at
+ the regional bank. You may need to contact the respective administrator who
+ can set one up. After being able to login to the new bank account, you can
+ see your bank account number by clicking on the ``Welcome, $USERNAME``
+ message in the profile page. Next to the bank account number, you can find
+ a convenient button to copy the number to the clipboard.
+
+Not every exchange will support every *wire method*, and if you do not add a
+bank account with a wire method that is supported by a particular exchange,
+then you will not be able to receive payments via that exchange even if you
+configured the merchant backend to trust that exchange.
+
+The simplest way to configure an account is to use the Web interface which has
+specific forms for different wire methods. First, select ``Bank account`` at
+the left of the page. The following page should be shown:
+
+.. image:: screenshots/no_default_account_yet.png
+
+Click on the blue "+" sign on the top right of the page to add a new
+bank account. The following page should appear:
+
+.. image:: screenshots/enter_instance_details.png
+
+First, you should select the wire method, after which the dialog will show you
+additional fields specific to the wire method. For example, if youchoose
+``iban`` as the account type, the following page should appear:
+
+.. image:: screenshots/instance_iban_config.png
+
+Specifying the revenue gateway with username and password is optional and
+discussed in section :ref:`automatic-settlement-data-import` below.
+
+After providing the details and confirming, the shop is ready to generate orders
+and accept payments.
+
+
+
+Detecting Settlement: Manually Adding Transfers
+-----------------------------------------------
+
+The exchange may aggregate many small amounts into one larger wire transfer.
+If you want to safely determine for which orders have been settled (final
+payment from the exchange has been received), the backend must learn about the
+wire transfers made into your bank account. Basically, as a secure system, we
+do not simply trust a claim by the exchange that it would transfer the money,
+but we allow each merchant to check settlements.
+
+An easy (but somewhat tedious) way to check settlements is to manually add
+every wire transfer that a merchant bank account has received from the
+exchange with the total amount and the wire transfer subject. Given this
+information, the merchant backend will inquire with the exchange which
+individual payments were aggregated, check that the total amount is correct,
+and will then flag the respective contracts as wired.
+
+You can manually enter wire transfers under ``Transfers``. However, this is
+tedious, and so if your banking setup supports it, we highly recommend
+using the automatic settlement data import.
+
+.. _automatic-settlement-data-import:
+
+Automatic Settlement Data Import
+--------------------------------
+
+To automatically import settlement data, you need to provide the merchant
+backend with the address and access credentials of a
+:ref:`taler-bank-merchant-http-api` for each bank account of an instance. The
+revenue API endpoint will allow the merchant backend to obtain a list of all
+incoming wire transfers into your bank account and automatically import them
+into the list of confirmed wire transfers.
+
+Note that setting up a revenue API endpoint will usually require you to first
+ask your bank for EBICS access and to set up :ref:`libeufin-nexus` to provide
+the revenue API endpoint. The :ref:`libeufin-bank` used by regional currency
+setups also provides a revenue API endpoint at
+``$BANK_URL/accounts/$ACCOUNT_NAME/taler-revenue/``. Thus, when using a
+regional currency setup, simply use the ``$BANK_URL`` of your bank and specify
+your bank login name and password in the :ref:`instance-account-setup` dialog.
+
+
+Manually creating an order using the SPA
+========================================
+
+Click on ``Orders`` at the top left corner of the merchant backoffice page; the
+following page should appear
+
+.. image:: screenshots/create_orders.png
+
+After having filled the required fields, the interface should show the
+following page with the related links to check the status of the order and let
+wallets pay for it.
+
+.. image:: screenshots/payment_links.png
+
+In order to test the setup, it should be now possible to use the command line wallet
+to withdraw Taler coins and spend them to pay for the order we just created.
+
+In practice, you will rarely if ever setup orders manually like this. Instead,
+a `GNU Taler e-commerce front-end
+<https://taler.net/en/docs.html#extensions>`_ or the
+:ref:`taler-merchant-pos-app` will do this on-demand. Here, you will only need
+to provide the respective front-ends with the URL of your instance
+(e.g. ``https://backend.$DOMAIN/instances/$NAME``) and your access token.
+
.. _Secure-setup:
@@ -806,11 +978,12 @@ Secure setup
.. index:: security
.. index:: TLS
-The Taler backend does not include even the most basic forms of access control
-or transport layer security. Thus, production setups **must** deploy the
-Taler backend behind an HTTP(S) server that acts as a *reverse proxy*,
-performs TLS termination and authentication and then forwards requests to the
-backend.
+The Taler backend is deliberately simple in terms of support for access
+control or transport layer security (TLS). Thus, production setups **must**
+deploy the Taler backend behind an HTTP(S) server that acts as a *reverse
+proxy*, performs TLS termination and authentication and then forwards requests
+to the backend.
+
Using UNIX domain sockets
-------------------------
@@ -818,10 +991,11 @@ Using UNIX domain sockets
To ensure that the merchant backend is not exposed directly to the network,
you *should* bind the backend to a UNIX domain socket:
-.. code-block:: console
+.. code-block:: ini
- $ taler-config -s MERCHANT -o SERVE -V unix
- $ taler-config -s MERCHANT -o UNIXPATH -V "/some/path/here.sock"
+ [MERCHANT]
+ SERVE = unix
+ UNIXPATH = "/some/path/here.sock"
Do not use a UNIX domain socket path in "/tmp": systemd (or other init
systems) may give Web servers a private "/tmp" thereby hiding UNIX domain
@@ -934,15 +1108,83 @@ Legal conditions for using the service
.. include:: frags/legal.rst
+.. _MerchantTemplateCustomization:
-Mustach HTML Templates
+Template Customization
----------------------
-The installation process will install various HTML templates to be served
-to trigger the wallet interaction. You may change those templates to your
-own design. The templating language used is Mustach, and the templates
-are in the ``share/taler/merchant/templates/`` directory.
+The installation process will install various HTML templates to be served to
+trigger the wallet interaction. You may change those templates to your own
+design. The templating language used is `Mustach
+<https://gitlab.com/jbol/mustach>`__, and the templates are in the
+``share/taler/merchant/templates/`` directory.
+
+The file names must be of the form ``$NAME.$LANG.must`` where ``$NAME`` is the
+name of the template and ``$LANG`` is the 2-letter language code of the
+template. English templates must exist and will be used as a fallback. If the
+browser (user-agent) has provided language preferences in the HTTP header and
+the respective language exists, the correct language will be automatically
+served.
+
+The following subsections give details about each of the templates. The
+subsection titles are the ``$NAME`` of the respective template.
+
+request_payment
+^^^^^^^^^^^^^^^
+
+Page shown to request the user to make a payment.
+
+This template is instantiated using the following information:
+
+ * taler_pay_uri: String; the ``taler://pay/`` URI that must be given
+ to the wallet to initiate the payment
+
+ * taler_pay_qrcode_svg: Image; an SVG image of the QR code with the
+ ``taler_pay_uri``.
+
+ * order_summary: String; a text summarizing the order
+
+ * order_status_url: URL of the merchant backend where the order status
+ can be found, useful for long-polling to check if the order has been paid
+
+
+offer_refund
+^^^^^^^^^^^^
+
+Page shown to offer a customer a refund.
+
+This template is instantiated using the following information:
+
+ * taler_refund_uri: String; the ``taler://pay/`` URI that must be given
+ to the wallet to initiate the payment
+
+ * taler_refund_qrcode_svg: Image; an SVG image of the QR code with the
+ ``taler_pay_uri``.
+
+ * refund_amount: Amount; how much did the merchant refund
+
+ * refund_taken: Amount; how much did the customer already take back in refunds
+ * order_summary: String; a text summarizing the order
+
+
+
+show_order_details
+^^^^^^^^^^^^^^^^^^
+
+Page shown to the user when they go back to the payment page but
+no payment is required and no refund is present.
+
+This template is instantiated using the following information:
+
+ * order_summary: String; a text summarizing the order
+
+ * contract_terms: Object; the full contract terms (shoud probably
+ not be shown in full!)
+
+ * refund_amount: Amount; how much did the merchant refund
+
+ * refund_taken: Amount; how much did the customer already take back in refunds
Static files
------------
@@ -1018,6 +1260,13 @@ processes, either via your systemd or init system, or directly.
Advanced topics
===============
+taler-config
+------------
+
+.. index:: taler-config
+
+.. include:: frags/using-taler-config.rst
+
.. _MerchantDatabaseScheme:
Database Scheme
@@ -1062,6 +1311,7 @@ runtime by the setup logic provided by ``taler-unified-setup.sh``.
See :ref:`Taler Exchange Manual <Benchmark-choose-bank>` for how to use ``taler-unified-setup.sh`` to setup the system and in particular on how to specify the bank to be used.
+
Running taler-merchant-benchmark
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -1098,8 +1348,10 @@ second gives the chance to leave some payments unaggregated, and also to
use merchant instances other than the default (which is, actually, the
one used by default by the tool).
-Note: the ability of driving the aggregation policy is useful for testing
-the back-office facility.
+.. note::
+
+ The ability to drive the aggregation policy is useful for testing
+ the back-office facility.
Any subcommand is also equipped with the canonical ``--help`` option, so
feel free to issue the following command in order to explore all the
@@ -1126,9 +1378,6 @@ option:
-
-
-
Temporarily Abandoned Features
==============================
diff --git a/taler-merchant-pos-terminal.rst b/taler-merchant-pos-terminal.rst
index b5833369..efc487cb 100644
--- a/taler-merchant-pos-terminal.rst
+++ b/taler-merchant-pos-terminal.rst
@@ -15,15 +15,22 @@
@author Torsten Grote
-GNU Taler Merchant POS Manual
-#############################
+.. _taler-merchant-pos-app:
-The GNU Taler merchant POS (point of sale) terminal allows sellers to
+Merchant Point of Sale App
+##########################
+
+The GNU Taler merchant point of sale (POS) App allows sellers to
* process customers' orders by adding or removing products
* calculate the amount owed by the customer
* let the customer make a Taler payment via QR code or NFC
+.. contents:: Table of Contents
+ :depth: 1
+ :local:
+
+
Android App
===========
@@ -64,38 +71,6 @@ Clicking this opens a menu with these items:
* Settings: Allows you to change the app configuration settings (URL and username/password)
and to forget the password (for locking the app).
-Testing nightly builds
-----------------------
-
-Every change to the app's source code triggers an automatic build
-that gets published in a F-Droid repository.
-If you don't have it already, download the `F-Droid app <https://f-droid.org/>`_
-and then click the following link (on your phone) to add the nightly repository.
-
- `GNU Taler Nightly F-Droid Repository <fdroidrepos://gnu-taler.gitlab.io/fdroid-repo-nightly/fdroid/repo?fingerprint=55F8A24F97FAB7B0960016AF393B7E57E7A0B13C2D2D36BAC50E1205923A7843>`_
-
-.. note::
- Nightly apps can be installed alongside official releases
- and thus are meant **only for testing purposes**.
- Use at your own risk!
-
-While not recommended, APKs can also be
-`downloaded directly <https://gitlab.com/gnu-taler/fdroid-repo-nightly/-/tree/master/fdroid%2Frepo>`__.
-
-Building from source
---------------------
-
-Import in and build with Android Studio or run on the command line:
-
-.. code-block:: console
-
- $ git clone https://git.taler.net/merchant-terminal-android.git
- $ cd merchant-terminal-android
- $ ./gradlew assembleRelease
-
-If you do not have the proprietary Android SDK installed,
-see the :doc:`taler-developer-manual`
-for :ref:`build instructions using free SDK rebuilds <Build-apps-from-source>`.
APIs and Data Formats
=====================
diff --git a/taler-monitoring-infrastructure.rst b/taler-monitoring-infrastructure.rst
new file mode 100644
index 00000000..3b809fb3
--- /dev/null
+++ b/taler-monitoring-infrastructure.rst
@@ -0,0 +1,197 @@
+..
+ This file is part of GNU TALER.
+
+ Copyright (C) 2014-2023 Taler Systems SA
+
+ TALER is free software; you can redistribute it and/or modify it under the
+ terms of the GNU Affero General Public License as published by the Free Software
+ Foundation; either version 2.1, or (at your option) any later version.
+
+ TALER is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License along with
+ TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
+
+ @author Javier Sepulveda
+.. _taler-merchant-monitoring:
+
+GNU Taler monitoring
+####################
+
+.. image:: images/taler-monitoring-infrastructure.png
+
+In order to check the availability of our server infrastructure, we use the Grafana and Uptime KUMA monitoring programs.
+
+On the one hand Grafana let us to see *graphically* the server consumption resources, and even alert us of some specific situations.
+On the other hand with a more basic tool such as Uptime KUMA (which does mostly ping and https checks),
+we get the very first status information, as the very first countermeasure.
+
+Grafana
+=======
+
+- Our grafana instance can be reached at https://grafana.taler.net
+
+User accounts:
+--------------
+
+We have only two main user accounts:
+
+- One "admin" account for server administrators.
+- One general "read-only" account, for the rest of the team.
+
+How to install Grafana
+----------------------
+
+Please refer to the Grafana official website for installation instructions for your specific operating system. For the
+specific case of the GNU/Linux distribution Debian 12 (bookworm), you can use the next set of instructions.
+
+.. code-block:: console
+
+ # apt-get install -y apt-transport-https
+ # apt-get install -y software-properties-common wget
+ # wget -q -O /usr/share/keyrings/grafana.key https://apt.grafana.com/gpg.key
+ # echo "deb [signed-by=/usr/share/keyrings/grafana.key] https://apt.grafana.com stable main" | tee -a /etc/apt/sources.list.d/grafana.list
+ # apt update
+ # apt-get install grafana
+ # systemctl daemon-reload
+ # systemctl enable --now grafana-server
+
+.. note::
+
+ If you want to deploy grafana automatically, and if you have access to the --private git repository "migration-exercise-stable.git",
+ please clone it, and execute from Grafana subfolder the grafana.sh file. This script will install for you Grafana and will leave it up and running on port 3000 of your server.
+
+Grafana Dashboards
+------------------
+
+As we understand creating tailored Grafana dashboards, is very time consuming thing to do, and in the top of that
+you really have to to be very proficient to do that, we use the available and pre-built `Grafana dashboards <https://grafana.com/grafana/dashboards/>`_, which eventually we can also tweak a little, to fit our needs.
+
+Node Exporter
+++++++++++++++
+
+- More information can be found on the `Node Exporter <https://grafana.com/grafana/dashboards/1860-node-exporter-full/>`_ website.
+- Dashboard ID: 1860
+
+.. note::
+
+ If you want to deploy Postgres Exporter automatically and have access to the --private git repository "migration-exercise-stable.git", please clone it,
+ and execute from the subfolder taler.net/grafana/node-exporter.sh, this script will install for you Node Exporter and will leave it running on port 9100.
+ This script also will create, start, and enable on reboot a new service.
+
+Postgres Exporter
++++++++++++++++++
+
+- More information can be found on the `PostgreSQL exporter <https://grafana.com/grafana/dashboards/12485-postgresql-exporter/>`_ website.
+- Dashboard ID: 12485
+
+.. image:: images/grafana-postgres-exporter.png
+
+.. note::
+
+ If you want to deploy Postgres Exporter automatically and have access to the --private git repository "migration-exercise-stable.git", please clone it,
+ and execute from the subfolder taler.net/grafana/postgres-exporter.sh, this script will install for you Grafana and will leave it running on port 9187.
+
+Uptime Kuma from Grafana
+++++++++++++++++++++++++
+
+This is an easy to way to integrate all monitored websites from Uptime Kuma, into Grafana. Thus,
+from the same place (Grafana), you can check also the status of the website and the expiration date of the
+certificates.
+
+- More information can be found on the `Uptime Kuma for Grafana <https://grafana.com/grafana/dashboards/18278-uptime-kuma/>`_ website.
+- Dashboard ID: 18278
+
+.. image:: images/uptime-kuma-from-grafana.png
+
+Grafana Data Sources
+---------------------
+As a data source connector we use Prometheus.
+
+Prometheus
+++++++++++
+More information can be found in the `Grafana and Prometheus <https://grafana.com/docs/grafana/latest/getting-started/get-started-grafana-prometheus/>`_ website.
+
+.. note::
+
+ If you want to deploy Prometheus automatically and have access to the --private git repository "migration-exercise-stable.git", please clone it,
+ and execute from the subfolder taler.net/grafana/prometheus.sh, this script will install for you Grafana and will leave it running on port 9090.
+
+Managing logs
+-------------
+
+In order to manage logs, we use Loki + Promtail (Debian packages), which are very easy to integrate with Grafana and Prometheus.
+
+.. code-block:: console
+
+ # Install
+ # apt-get install loki promtail
+ # Start services
+ # systemctl start loki promtail
+ # Enable services on reboot
+ # systemctl enable loki
+ # systemctl enable promtail
+
+Loki and Promtail services in Grafana
+----------------------------------------------
+
+1) Make sure you have prometheus running on port 9090
+2) Make sure you have loki running on port 3100
+
+.. code-block:: console
+
+ systemctl status prometheus loki
+
+
+.. note::
+
+ We still don't have Loki and Promtail installed in production (taler.net), and neither
+ configured to track certain log files.
+
+Grafana Alerting
+----------------
+
+#. In order to use the Grafana alerting system rules, you need first to configure working SMTP service of your server.
+#. Once you have done the necessary changes on the Grafana configuration file, you have to either restart or reload the "grafana-server" service with the systemctl command as usual.
+#. Then go to the Grafana admin panel Alerting -> Contact points, and within the email address you are using for this purpose, check if SMTP is indeed working by pressing the "test" button.
+#. If that works, you will receive an email in your mailbox with the Grafana logo confirming that the server can satisfactorily send email messages.
+
+
+Uptime Kuma
+===========
+
+- URL: http://139.162.254.179:3001/dashboard
+- Users: One single administration account with full privileges.
+- Installation: With Docker
+
+.. image:: images/kuma.png
+
+.. note::
+
+ 1) In order to guarantee the KUMA is doing its work, it needs to be install 100% externally from the servers you want to monitor. (Server Kuma 1)
+ 2) Also, it is important to monitor the KUMA server itself, so you don't endup without a monitoring system. (Server Kuma 2)
+
+In our case, we do both. We have the two Uptime KUMA servers completely outside our server infrastructure, so one monitors the other, and
+the latter one, monitors our own Taler servers.
+
+Kuma monitor types
+-------------------
+
+Kuma counts with quite a few monitor types, such as https, TCP port or ping. In our case, we use mainly https requests,
+and pings, to make sure as a first check that our servers are responsive.
+
+Another handy feature that Kuma has, is the "Certificate Expiry Notification feature, which we also use, and eventually warn us about a certificate
+expiration dates.
+
+So in brief in our KUMA main server, we use these 3 monitor types (ping,https,certificate expiration) for each website that we monitor.
+
+Exceptionally for additional notifications, and specifically due of the importance of the Taler Operations server,
+we use in addition SMS notifications (clicksend provider). This way in case of KUMA detecting the Taler Operations unavailability,
+a SMS message will be sent to at the very least two persons from the deployment and operations department.
+
+How to edit notifications:
+
+.. image:: images/uptime-kuma-edit.png
+
diff --git a/taler-user-guide.rst b/taler-user-guide.rst
index e685ede4..127218fb 100644
--- a/taler-user-guide.rst
+++ b/taler-user-guide.rst
@@ -16,8 +16,12 @@
@author Christian Grothoff
-GNU Taler User Guide
-####################
+User Guide
+##########
+
+.. contents:: Table of Contents
+ :depth: 1
+ :local:
Introduction
============
@@ -38,8 +42,8 @@ an account at the bank. Some operations also require access to the merchant
backend.
-Withdrawing
-===========
+Withdrawing from bank accounts
+==============================
Withdrawing is the step where money is moved from a bank account into
a GNU Taler wallet. There are two main ways to do this.
@@ -70,7 +74,8 @@ Wallet initiated withdrawal
In this case, you will start the withdraw process from the GNU Taler wallet.
Under "Settings", you will find a list of exchanges. If the list is empty or
does not contain the desired exchange, you may have to first add the exchange
-by providing the respective URL.
+by providing the respective URL. The payment service provider operating the
+exchange service should have such a QR code on their Web site.
Next to the exchange, there is a drop-down menu with an option to "withdraw".
(If you already have money in your wallet, you will also find the same button
@@ -86,16 +91,16 @@ as instructed by the wallet. Once the money has arrived at the exchange, the
wallet will automatically withdraw the funds.
-Depositing
-==========
+Depositing into bank accounts
+=============================
If you have money in your wallet, you can use the "deposit" button to deposit
the funds into a bank account. The wallet will ask you to specify the amount
and the target bank account.
-Sending cash
-============
+Sending digital cash
+====================
Once you have digital cash, you can send it to another GNU Taler
wallet. Simply specify the amount and a human-readable reason for the
@@ -109,19 +114,19 @@ clicking the QR code scan button). Afterwards, review the reason text and
accept the funds to complete the transaction.
-Invoicing
-=========
+Receiving digital cash
+======================
-To receive funds from another user, you can send an invoice to another GNU
+To receive funds from another user, you can send a payment request to another GNU
Taler wallet. Simply specify the amount and a human-readable reason for the
-invoice. The wallet will then show a QR code (and give the option to export
-the invoice as a taler://-URL). Send the image of the QR code to the payer
+payment request. The wallet will then show a QR code (and give the option to export
+the payment request as a taler://-URL). Send the image of the QR code to the payer
wallet (or send the taler://-URL to the target wallet).
The target wallet should scan the QR code (or enter the text of the
taler://-URL into the URL import dialog which is available by holding or
clicking the QR code scan button). Afterwards, review the reason for
-the invoice and decide whether or not to pay the invoice. Selecting
+the payment request and decide whether or not to pay it. Selecting
"pay" will complete the transaction.
Depending on the configuration of the exchange, the receiving wallet may have
@@ -178,18 +183,18 @@ A simple way for merchants to accept GNU Taler payments is the use of the
point-of-sale app. The app can be installed on an Android phone or tablet
and is configured via a simple JSON file on a Web site:
- * In the app settings you need to specify the URL of the Web site where
- the app can download the categories, products and prices from which
- orders are to be compiled. You can optionally specify a username and
- password to authenticate to the Web server.
+* In the app settings you need to specify the URL of the Web site where
+ the app can download the categories, products and prices from which
+ orders are to be compiled. You can optionally specify a username and
+ password to authenticate to the Web server.
- * The syntax of the JSON file is described in the point-of-sale app
- manual. However, you may simply want to download the sample JSON
- file from our documentation and use it as a starting point.
+* The syntax of the JSON file is described in the point-of-sale app
+ manual. However, you may simply want to download the sample JSON
+ file from our documentation and use it as a starting point.
- * A key option is the merchant backend with the authorization key
- which must be included in this JSON configuration. You may point
- the point-of-sale app to any instance of a merchant backend.
+* A key option is the merchant backend with the authorization key
+ which must be included in this JSON configuration. You may point
+ the point-of-sale app to any instance of a merchant backend.
Once configured, the point-of-sale app allows the user to select a product
category and then to quickly add products from that category to an order. You
@@ -270,9 +275,8 @@ template does not specify a fixed amount, the payer will be prompted to enter
the amount to be paid (and possibly given the opportunity to specify or alter
the summary). Selecting "pay" will complete the transaction. If payment
confirmations are configured by the merchant backend, the wallet will then
-display a confirmation code that can be shown to the merchant as a proof of
-payment.
-
+display a TOTP confirmation code that can be shown to the merchant as a proof
+of payment.
@@ -294,9 +298,10 @@ you can specify which URL, which HTTP headers, which HTTP method and what HTTP
body to send to the Webhook. Webhooks are automatically retried (with
increasing delays) when the target server returns a temporary error.
-Mustach templates are used when defining the contents of Webhooks. Depending
-on the triggering event, the templates will be expanded with event-specific
-data.
+`Mustach templates <https://mustache.github.io/mustache.5.html>`__ are used
+when defining the contents of Webhooks. Depending on the triggering event,
+the templates will be expanded with event-specific data.
+
Pay events
----------
@@ -304,8 +309,8 @@ Pay events
For "pay" events, the backend will provide the following
information to the Mustach templating engine:
- * contract_terms: the contract terms of the paid order
- * order_id: the ID of the order that received the refund
+* :ref:`contract_terms <contract-terms>`: the contract terms of the paid order
+* order_id: the ID of the order that received the refund
Refund events
@@ -314,119 +319,10 @@ Refund events
For "refund" events, the backend will provide the following information to the
Mustach templating engine:
- * timestamp: time of the refund (in nanoseconds since 1970)
- * order_id: the ID of the order that received the refund
- * contract_terms: the full JSON of the contract terms of the refunded order
- * refund_amout: the amount that was being refunded
- * reason: the reason entered by the merchant staff for granting the refund;
- be careful, you probably want to inform your staff if a webhook may expose
- this information to the consumer
-
-
-.. _Rewarding-visitors:
-
-Rewarding visitors
-==================
-
-.. index:: rewards
-
-Taler can also be used to reward digital cash to Web site visitors. For
-example, you may be running an online survey, and you want to reward those
-people that have dutifully completed the survey. If they have installed a
-Taler wallet, you can provide them with a reward for their deeds. This section
-describes how to setup the Taler merchant backend for rewarding.
-
-There are three basic steps that must happen to reward a visitor.
-
-.. _Fund-the-reserve:
-
-Fund the reserve
-----------------
-
-.. index:: reserve
-
-First, the reserve must be setup in the merchant backend. A reserve
-is always tied to a particular instance. To create a reserve with
-10 KUDOS at instance ``default`` using the demo exchange, use:
-
-.. code-block:: console
-
- $ taler-merchant-setup-reserve \
- -a KUDOS:10 \
- -e https://exchange.demo.taler.net/ \
- -m http://localhost:8888/instances/default
-
-The above command assumes that the merchant runs on localhost on
-port 8888.
-For more information, including how to transmit authentication information
-to the backend, see :doc:`manpages/taler-merchant-setup-reserve.1`.
-
-The command will output a ``payto://`` URI which specifies where to
-wire the funds and which wire transfer subject to use.
-
- .. note::
-
- FIXME: add full example output.
-
-In our example, the output for the wire transfer subject is:
-
-.. code-block:: none
-
- QPE24X8PBX3BZ6E7GQ5VAVHV32FWTTCADR0TRQ183MSSJD2CHNEG
-
-You now need to make a wire transfer to the exchange’s bank account
-using the given wire transfer subject.
-
-Make your wire transfer and (optionally) check at
-“https://exchange/reserves/QPE24X...” whether your transfer has arrived at the
-exchange.
-
-Once the funds have arrived, you can start to use the reserve for
-rewarding.
-
-Note that an exchange will typically close a reserve after four weeks, wiring
-all remaining funds back to the sender’s account. Thus, you should plan to
-wire funds corresponding to a campaign of about two weeks to the exchange
-initially. If your campaign runs longer, you should setup another reserve
-every other week to ensure one is always ready.
-
-.. _Authorize-a-reward:
-
-Authorize a reward
-------------------
-
-When your frontend has reached the point where a client is supposed to receive
-a reward, it needs to first authorize the reward. For this, the frontend must use
-a POST to ``/private/reserves/$RESERVE_PUB/authorize-reward``. To authorize a
-reward, the frontend has to provide the following information in the body of the
-POST request:
-
-- The amount of the reward
-
-- The justification (only used internally for the back-office)
-
-- The URL where the wallet should navigate next after the reward was
- processed
-
-- The reward-pickup URL (see next section)
-
-In response to this request, the backend will return a reward token, an
-expiration time and the exchange URL. The expiration time will indicate
-how long the reward is valid (when the reserve expires). The reward token is
-an opaque string that contains all the information needed by the wallet
-to process the reward. The frontend must send this reward token to the browser
-in a special “402 Payment Required” response inside the ``Taler``
-header.
-
-The frontend should handle errors returned by the backend, such as
-misconfigured instances or a lack of remaining funds for rewarding.
-
-.. _Picking-up-of-the-reward:
-
-Picking up of the reward
-------------------------
-
-The wallet will POST a JSON object to the shop’s
-``/rewards/$REWARD_ID/pickup`` handler.
-The frontend must then forward this request to the backend. The response
-generated by the backend can then be forwarded directly to the wallet.
+* timestamp: time of the refund (in nanoseconds since 1970)
+* order_id: the ID of the order that received the refund
+* :ref:`contract_terms <contract-terms>`: the full JSON of the contract terms of the refunded order
+* refund_amout: the amount that was being refunded
+* reason: the reason entered by the merchant staff for granting the refund;
+ be careful, you probably want to inform your staff if a webhook may expose
+ this information to the consumer
diff --git a/taler-wallet.rst b/taler-wallet.rst
index 04a77e7d..1d1a3991 100644
--- a/taler-wallet.rst
+++ b/taler-wallet.rst
@@ -1,8 +1,28 @@
-GNU Taler Wallet Manual
-#######################
+..
+ This file is part of GNU TALER.
+ Copyright (C) 2014-2024 Taler Systems SA
+
+ TALER is free software; you can redistribute it and/or modify it under the
+ terms of the GNU Affero General Public License as published by the Free Software
+ Foundation; either version 2.1, or (at your option) any later version.
+
+ TALER is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License along with
+ TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
+
+
+Wallet Manual
+#############
The GNU Taler wallet allows customers to withdraw and spend digital cash.
+.. contents:: Table of Contents
+ :depth: 1
+ :local:
+
WebExtension Wallet
===================
@@ -207,6 +227,48 @@ is functional:
# The "deposit group id" can be found in the output of the transactions list.
$ taler-wallet-cli deposit track $DEPOSIT_GROUP_ID
+.. _withdraw-simulation:
+
+
+Paying for an order
+===================
+
+.. note::
+
+ This section is in dire need for some editing...
+
+This section explains how to pay for an order in a scenario where the fiat bank
+is simulated. The simulation takes place by crafting ad-hoc XML files as if the
+bank would have issued them. Such XML files carry information about incoming payments
+to the regional currency master bank account. Finally, the XML files are passed
+to LibEuFin nexus via a convenient CLI method. The responsible script for such
+simulation is ``withdraw.sh``.
+
+Run ``./withdraw.sh`` without any arguments. Assuming that you ran the command
+as the ``test-user``, after the execution, 5 units of the regional currency should
+be found in the CLI wallet owned by ``test-user``.
+
+
+Check it with:
+
+.. code-block:: console
+
+ $ taler-wallet-cli balance
+
+If so, call the wallet in the following way to finally pay for the order just created:
+
+.. code-block:: console
+
+ $ taler-wallet-cli handle-uri "$TALER_PAY_URI"
+
+.. note::
+
+ Reset the state before going to production, as it impacts the way nexus
+ asks records to the bank. In particular, delete: any database and the
+ files ``config/user.conf`` and ``config/internal.conf``, and finally run
+ ``./main.sh`` again.
+
+
@@ -389,7 +451,6 @@ Things we still need tests for:
Or when the merchant is not reachable? Or the bank?
This can be tested by temporarily killing those services.
* How does the wallet deal with processing the same ``taler://(pay|withdraw)`` URI twice?
-* Test rewards (accepting/refusing a reward)
* Test refunds
* Test for :ref:`session-based payments <repurchase>`
* Test case for auto-refunds
diff --git a/wallet/wallet-core.md b/wallet/wallet-core.md
index 4f83f743..977e100d 100644
--- a/wallet/wallet-core.md
+++ b/wallet/wallet-core.md
@@ -15,8 +15,10 @@ This file is auto-generated from [wallet-core](https://git.taler.net/wallet-core
* [ConvertWithdrawalAmountOp](#convertwithdrawalamountop)
### Managing Transactions
* [GetTransactionsOp](#gettransactionsop)
+* [ListAssociatedRefreshesOp](#listassociatedrefreshesop)
* [TestingGetSampleTransactionsOp](#testinggetsampletransactionsop)
* [GetTransactionByIdOp](#gettransactionbyidop)
+* [GetWithdrawalTransactionByUriOp](#getwithdrawaltransactionbyuriop)
* [RetryPendingNowOp](#retrypendingnowop)
* [DeleteTransactionOp](#deletetransactionop)
* [RetryTransactionOp](#retrytransactionop)
@@ -37,12 +39,17 @@ This file is auto-generated from [wallet-core](https://git.taler.net/wallet-core
* [ConfirmPayOp](#confirmpayop)
* [StartRefundQueryForUriOp](#startrefundqueryforuriop)
* [StartRefundQueryOp](#startrefundqueryop)
-### Rewards
-* [PrepareTipOp](#preparetipop)
-* [AcceptTipOp](#accepttipop)
+### Global Currency management
+* [ListGlobalCurrencyAuditorsOp](#listglobalcurrencyauditorsop)
+* [ListGlobalCurrencyExchangesOp](#listglobalcurrencyexchangesop)
+* [AddGlobalCurrencyExchangeOp](#addglobalcurrencyexchangeop)
+* [AddGlobalCurrencyAuditorOp](#addglobalcurrencyauditorop)
+* [RemoveGlobalCurrencyExchangeOp](#removeglobalcurrencyexchangeop)
+* [RemoveGlobalCurrencyAuditorOp](#removeglobalcurrencyauditorop)
### Exchange Management
* [ListExchangesOp](#listexchangesop)
* [ListExchangesForScopedCurrencyOp](#listexchangesforscopedcurrencyop)
+* [PrepareWithdrawExchangeOp](#preparewithdrawexchangeop)
* [AddExchangeOp](#addexchangeop)
* [UpdateExchangeEntryOp](#updateexchangeentryop)
* [ListKnownBankAccountsOp](#listknownbankaccountsop)
@@ -51,7 +58,9 @@ This file is auto-generated from [wallet-core](https://git.taler.net/wallet-core
* [SetExchangeTosAcceptedOp](#setexchangetosacceptedop)
* [GetExchangeTosOp](#getexchangetosop)
* [GetExchangeDetailedInfoOp](#getexchangedetailedinfoop)
-* [ListCurrenciesOp](#listcurrenciesop)
+* [GetExchangeEntryByUrlOp](#getexchangeentrybyurlop)
+* [GetExchangeResourcesOp](#getexchangeresourcesop)
+* [DeleteExchangeOp](#deleteexchangeop)
* [GetCurrencySpecificationOp](#getcurrencyspecificationop)
### Deposits
* [GenerateDepositGroupTxIdOp](#generatedepositgrouptxidop)
@@ -168,8 +177,29 @@ export interface WalletBalance {
available: AmountString;
pendingIncoming: AmountString;
pendingOutgoing: AmountString;
+ /**
+ * Does the balance for this currency have a pending
+ * transaction?
+ *
+ * @deprecated use flags and pendingIncoming/pendingOutgoing instead
+ */
hasPendingTransactions: boolean;
+ /**
+ * Is there a transaction that requires user input?
+ *
+ * @deprecated use flags instead
+ */
requiresUserInput: boolean;
+ flags: BalanceFlag[];
+}
+
+```
+```typescript
+export declare enum BalanceFlag {
+ IncomingKyc = "incoming-kyc",
+ IncomingAml = "incoming-aml",
+ IncomingConfirmation = "incoming-confirmation",
+ OutgoingKyc = "outgoing-kyc",
}
```
@@ -356,9 +386,17 @@ export type GetTransactionsOp = {
export interface TransactionsRequest {
/**
* return only transactions in the given currency
+ *
+ * it will be removed in next release
+ *
+ * @deprecated use scopeInfo
*/
currency?: string;
/**
+ * return only transactions in the given scopeInfo
+ */
+ scopeInfo?: ScopeInfo;
+ /**
* if present, results will be limited to transactions related to the given search string
*/
search?: string;
@@ -377,6 +415,32 @@ export interface TransactionsRequest {
```
+### ListAssociatedRefreshesOp
+```typescript
+/**
+ * List refresh transactions associated with another transaction.
+ */
+export type ListAssociatedRefreshesOp = {
+ op: WalletApiOperation.ListAssociatedRefreshes;
+ request: ListAssociatedRefreshesRequest;
+ response: ListAssociatedRefreshesResponse;
+};
+// ListAssociatedRefreshes = "listAssociatedRefreshes"
+
+```
+```typescript
+export interface ListAssociatedRefreshesRequest {
+ transactionId: string;
+}
+
+```
+```typescript
+export interface ListAssociatedRefreshesResponse {
+ transactionIds: string[];
+}
+
+```
+
### TestingGetSampleTransactionsOp
```typescript
/**
@@ -408,6 +472,23 @@ export interface TransactionByIdRequest {
```
+### GetWithdrawalTransactionByUriOp
+```typescript
+export type GetWithdrawalTransactionByUriOp = {
+ op: WalletApiOperation.GetWithdrawalTransactionByUri;
+ request: WithdrawalTransactionByURIRequest;
+ response: TransactionWithdrawal | undefined;
+};
+// GetWithdrawalTransactionByUri = "getWithdrawalTransactionByUri"
+
+```
+```typescript
+export interface WithdrawalTransactionByURIRequest {
+ talerWithdrawUri: string;
+}
+
+```
+
### RetryPendingNowOp
```typescript
export type RetryPendingNowOp = {
@@ -533,7 +614,7 @@ export type ResumeTransactionOp = {
export type GetWithdrawalDetailsForAmountOp = {
op: WalletApiOperation.GetWithdrawalDetailsForAmount;
request: GetWithdrawalDetailsForAmountRequest;
- response: ManualWithdrawalDetails;
+ response: WithdrawalDetailsForAmount;
};
// GetWithdrawalDetailsForAmount = "getWithdrawalDetailsForAmount"
@@ -547,10 +628,12 @@ export interface GetWithdrawalDetailsForAmountRequest {
```
```typescript
-export interface ManualWithdrawalDetails {
+export interface WithdrawalDetailsForAmount {
/**
* Did the user accept the current version of the exchange's
* terms of service?
+ *
+ * @deprecated the client should query the exchange entry instead
*/
tosAccepted: boolean;
/**
@@ -569,13 +652,23 @@ export interface ManualWithdrawalDetails {
numCoins: number;
/**
* Ways to pay the exchange.
+ *
+ * @deprecated in favor of withdrawalAccountsList
*/
paytoUris: string[];
/**
+ * Ways to pay the exchange, including accounts that require currency conversion.
+ */
+ withdrawalAccountsList: WithdrawalExchangeAccountDetails[];
+ /**
* If the exchange supports age-restricted coins it will return
* the array of ages.
*/
ageRestrictionOptions?: number[];
+ /**
+ * Scope info of the currency withdrawn.
+ */
+ scopeInfo: ScopeInfo;
}
```
@@ -597,17 +690,29 @@ export type GetWithdrawalDetailsForUriOp = {
export interface GetWithdrawalDetailsForUriRequest {
talerWithdrawUri: string;
restrictAge?: number;
+ notifyChangeFromPendingTimeoutMs?: number;
}
```
```typescript
export interface WithdrawUriInfoResponse {
+ operationId: string;
+ status: WithdrawalOperationStatus;
+ confirmTransferUrl?: string;
amount: AmountString;
defaultExchangeBaseUrl?: string;
possibleExchanges: ExchangeListItem[];
}
```
+```typescript
+export type WithdrawalOperationStatus =
+ | "pending"
+ | "selected"
+ | "aborted"
+ | "confirmed";
+
+```
### AcceptBankIntegratedWithdrawalOp
```typescript
@@ -665,12 +770,15 @@ export interface AcceptManualWithdrawalRequest {
export interface AcceptManualWithdrawalResult {
/**
* Payto URIs that can be used to fund the withdrawal.
+ *
+ * @deprecated in favor of withdrawalAccountsList
*/
exchangePaytoUris: string[];
/**
* Public key of the newly created reserve.
*/
reservePub: string;
+ withdrawalAccountsList: WithdrawalExchangeAccountDetails[];
transactionId: TransactionIdStr;
}
@@ -826,7 +934,7 @@ export interface ConfirmPayRequest {
* @deprecated use transactionId instead
*/
proposalId?: string;
- transactionId?: string;
+ transactionId?: TransactionIdStr;
sessionId?: string;
forcedCoinSel?: ForcedCoinSel;
}
@@ -877,6 +985,9 @@ export interface PrepareRefundRequest {
```
```typescript
export interface StartRefundQueryForUriResponse {
+ /**
+ * Transaction id of the *payment* where the refund query was started.
+ */
transactionId: TransactionIdStr;
}
@@ -899,92 +1010,120 @@ export interface StartRefundQueryRequest {
```
-### PrepareTipOp
+### ListGlobalCurrencyAuditorsOp
```typescript
-/**
- * Query and store information about a reward.
- */
-export type PrepareTipOp = {
- op: WalletApiOperation.PrepareReward;
- request: PrepareRewardRequest;
- response: PrepareRewardResult;
+export type ListGlobalCurrencyAuditorsOp = {
+ op: WalletApiOperation.ListGlobalCurrencyAuditors;
+ request: EmptyObject;
+ response: ListGlobalCurrencyAuditorsResponse;
};
-// PrepareReward = "prepareReward"
+// ListGlobalCurrencyAuditors = "listGlobalCurrencyAuditors"
```
```typescript
-export interface PrepareRewardRequest {
- talerRewardUri: string;
+export interface ListGlobalCurrencyAuditorsResponse {
+ auditors: {
+ currency: string;
+ auditorBaseUrl: string;
+ auditorPub: string;
+ }[];
}
```
+
+### ListGlobalCurrencyExchangesOp
```typescript
-export interface PrepareTipResult {
- /**
- * Unique ID for the tip assigned by the wallet.
- * Typically different from the merchant-generated tip ID.
- *
- * @deprecated use transactionId instead
- */
- walletRewardId: string;
- /**
- * Tip transaction ID.
- */
- transactionId: string;
- /**
- * Has the tip already been accepted?
- */
- accepted: boolean;
- /**
- * Amount that the merchant gave.
- */
- rewardAmountRaw: AmountString;
- /**
- * Amount that arrived at the wallet.
- * Might be lower than the raw amount due to fees.
- */
- rewardAmountEffective: 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.
- */
+export type ListGlobalCurrencyExchangesOp = {
+ op: WalletApiOperation.ListGlobalCurrencyExchanges;
+ request: EmptyObject;
+ response: ListGlobalCurrencyExchangesResponse;
+};
+// ListGlobalCurrencyExchanges = "listGlobalCurrencyExchanges"
+
+```
+```typescript
+export interface ListGlobalCurrencyExchangesResponse {
+ exchanges: {
+ currency: string;
+ exchangeBaseUrl: string;
+ exchangeMasterPub: string;
+ }[];
+}
+
+```
+
+### AddGlobalCurrencyExchangeOp
+```typescript
+export type AddGlobalCurrencyExchangeOp = {
+ op: WalletApiOperation.AddGlobalCurrencyExchange;
+ request: AddGlobalCurrencyExchangeRequest;
+ response: EmptyObject;
+};
+// AddGlobalCurrencyExchange = "addGlobalCurrencyExchange"
+
+```
+```typescript
+export interface AddGlobalCurrencyExchangeRequest {
+ currency: string;
exchangeBaseUrl: string;
- /**
- * Time when the tip will expire. After it expired, it can't be picked
- * up anymore.
- */
- expirationTimestamp: TalerProtocolTimestamp;
+ exchangeMasterPub: string;
}
```
-### AcceptTipOp
+### AddGlobalCurrencyAuditorOp
```typescript
-/**
- * Accept a reward.
- */
-export type AcceptTipOp = {
- op: WalletApiOperation.AcceptReward;
- request: AcceptRewardRequest;
- response: AcceptTipResponse;
+export type AddGlobalCurrencyAuditorOp = {
+ op: WalletApiOperation.AddGlobalCurrencyAuditor;
+ request: AddGlobalCurrencyAuditorRequest;
+ response: EmptyObject;
};
-// AcceptReward = "acceptReward"
+// AddGlobalCurrencyAuditor = "addGlobalCurrencyAuditor"
```
```typescript
-export interface AcceptRewardRequest {
- walletRewardId: string;
+export interface AddGlobalCurrencyAuditorRequest {
+ currency: string;
+ auditorBaseUrl: string;
+ auditorPub: string;
}
```
+
+### RemoveGlobalCurrencyExchangeOp
```typescript
-export interface AcceptTipResponse {
- transactionId: TransactionIdStr;
- next_url?: string;
+export type RemoveGlobalCurrencyExchangeOp = {
+ op: WalletApiOperation.RemoveGlobalCurrencyExchange;
+ request: RemoveGlobalCurrencyExchangeRequest;
+ response: EmptyObject;
+};
+// RemoveGlobalCurrencyExchange = "removeGlobalCurrencyExchange"
+
+```
+```typescript
+export interface RemoveGlobalCurrencyExchangeRequest {
+ currency: string;
+ exchangeBaseUrl: string;
+ exchangeMasterPub: string;
+}
+
+```
+
+### RemoveGlobalCurrencyAuditorOp
+```typescript
+export type RemoveGlobalCurrencyAuditorOp = {
+ op: WalletApiOperation.RemoveGlobalCurrencyAuditor;
+ request: RemoveGlobalCurrencyAuditorRequest;
+ response: EmptyObject;
+};
+// RemoveGlobalCurrencyAuditor = "removeGlobalCurrencyAuditor"
+
+```
+```typescript
+export interface RemoveGlobalCurrencyAuditorRequest {
+ currency: string;
+ auditorBaseUrl: string;
+ auditorPub: string;
}
```
@@ -1042,6 +1181,45 @@ export interface ShortExchangeListItem {
```
+### PrepareWithdrawExchangeOp
+```typescript
+/**
+ * Prepare for withdrawing via a taler://withdraw-exchange URI.
+ */
+export type PrepareWithdrawExchangeOp = {
+ op: WalletApiOperation.PrepareWithdrawExchange;
+ request: PrepareWithdrawExchangeRequest;
+ response: PrepareWithdrawExchangeResponse;
+};
+// PrepareWithdrawExchange = "prepareWithdrawExchange"
+
+```
+```typescript
+export interface PrepareWithdrawExchangeRequest {
+ /**
+ * A taler://withdraw-exchange URI.
+ */
+ talerUri: string;
+}
+
+```
+```typescript
+export interface PrepareWithdrawExchangeResponse {
+ /**
+ * Base URL of the exchange that already existed
+ * or was ephemerally added as an exchange entry to
+ * the wallet.
+ */
+ exchangeBaseUrl: string;
+ /**
+ * Amount from the taler://withdraw-exchange URI.
+ * Only present if specified in the URI.
+ */
+ amount?: AmountString;
+}
+
+```
+
### AddExchangeOp
```typescript
/**
@@ -1072,6 +1250,7 @@ export type UpdateExchangeEntryOp = {
```typescript
export interface UpdateExchangeEntryRequest {
exchangeBaseUrl: string;
+ force?: boolean;
}
```
@@ -1236,6 +1415,7 @@ export type GetExchangeTosOp = {
export interface GetExchangeTosRequest {
exchangeBaseUrl: string;
acceptedFormat?: string[];
+ acceptLanguage?: string;
}
```
@@ -1258,6 +1438,16 @@ export interface GetExchangeTosResult {
* Accepted content type
*/
contentType: string;
+ /**
+ * Language of the returned content.
+ *
+ * If missing, language is unknown.
+ */
+ contentLanguage: string | undefined;
+ /**
+ * Available languages as advertised by the exchange.
+ */
+ tosAvailableLanguages: string[];
tosStatus: ExchangeTosStatus;
}
@@ -1298,17 +1488,17 @@ export interface ExchangeFullDetails {
```typescript
export interface WireInfo {
feesForType: WireFeeMap;
- accounts: ExchangeAccount[];
+ accounts: ExchangeWireAccount[];
}
```
```typescript
-/**
- * Information about one of the exchange's bank accounts.
- */
-export interface ExchangeAccount {
+export interface ExchangeWireAccount {
payto_uri: string;
- master_sig: string;
+ conversion_url?: string;
+ credit_restrictions: AccountRestriction[];
+ debit_restrictions: AccountRestriction[];
+ master_sig: EddsaSignatureString;
}
```
@@ -1322,31 +1512,69 @@ export interface FeeDescription {
```
-### ListCurrenciesOp
+### GetExchangeEntryByUrlOp
```typescript
/**
- * List currencies known to the wallet.
+ * Get the current terms of a service of an exchange.
*/
-export type ListCurrenciesOp = {
- op: WalletApiOperation.ListCurrencies;
- request: EmptyObject;
- response: WalletCurrencyInfo;
+export type GetExchangeEntryByUrlOp = {
+ op: WalletApiOperation.GetExchangeEntryByUrl;
+ request: GetExchangeEntryByUrlRequest;
+ response: GetExchangeEntryByUrlResponse;
};
-// ListCurrencies = "listCurrencies"
+// GetExchangeEntryByUrl = "getExchangeEntryByUrl"
```
```typescript
-export interface WalletCurrencyInfo {
- trustedAuditors: {
- currency: string;
- auditorPub: string;
- auditorBaseUrl: string;
- }[];
- trustedExchanges: {
- currency: string;
- exchangeMasterPub: string;
- exchangeBaseUrl: string;
- }[];
+export interface GetExchangeEntryByUrlRequest {
+ exchangeBaseUrl: string;
+}
+
+```
+
+### GetExchangeResourcesOp
+```typescript
+/**
+ * Get resources associated with an exchange.
+ */
+export type GetExchangeResourcesOp = {
+ op: WalletApiOperation.GetExchangeResources;
+ request: GetExchangeResourcesRequest;
+ response: GetExchangeResourcesResponse;
+};
+// GetExchangeResources = "getExchangeResources"
+
+```
+```typescript
+export interface GetExchangeResourcesRequest {
+ exchangeBaseUrl: string;
+}
+
+```
+```typescript
+export interface GetExchangeResourcesResponse {
+ hasResources: boolean;
+}
+
+```
+
+### DeleteExchangeOp
+```typescript
+/**
+ * Get resources associated with an exchange.
+ */
+export type DeleteExchangeOp = {
+ op: WalletApiOperation.GetExchangeResources;
+ request: DeleteExchangeRequest;
+ response: EmptyObject;
+};
+// GetExchangeResources = "getExchangeResources"
+
+```
+```typescript
+export interface DeleteExchangeRequest {
+ exchangeBaseUrl: string;
+ purge?: boolean;
}
```
@@ -1373,20 +1601,6 @@ export interface GetCurrencySpecificationResponse {
}
```
-```typescript
-export interface CurrencySpecification {
- name: string;
- decimal_separator: string;
- num_fractional_input_digits: Integer;
- num_fractional_normal_digits: Integer;
- num_fractional_trailing_zero_digits: Integer;
- is_currency_name_leading: boolean;
- alt_unit_names: {
- [log10: string]: string;
- };
-}
-
-```
### GenerateDepositGroupTxIdOp
```typescript
@@ -1436,7 +1650,7 @@ export interface CreateDepositGroupRequest {
* that occur while the operation has been created but
* before the creation request has returned.
*/
- transactionId?: string;
+ transactionId?: TransactionIdStr;
depositPaytoUri: string;
amount: AmountString;
}
@@ -1882,6 +2096,17 @@ export interface CheckPeerPushDebitRequest {
export interface CheckPeerPushDebitResponse {
amountRaw: AmountString;
amountEffective: AmountString;
+ exchangeBaseUrl: string;
+ /**
+ * Maximum expiration date, based on how close the coins
+ * used for the payment are to expiry.
+ *
+ * The value is based on when the wallet would typically
+ * automatically refresh the coins on its own, leaving enough
+ * time to get a refund for the push payment and refresh the
+ * coin.
+ */
+ maxExpirationDate: TalerProtocolTimestamp;
}
```
@@ -1912,7 +2137,6 @@ export interface InitiatePeerPushDebitResponse {
pursePub: string;
mergePriv: string;
contractPriv: string;
- talerUri: string;
transactionId: TransactionIdStr;
}
@@ -1940,14 +2164,18 @@ export interface PreparePeerPushCreditRequest {
```typescript
export interface PreparePeerPushCreditResponse {
contractTerms: PeerContractTerms;
+ amountRaw: AmountString;
+ amountEffective: AmountString;
+ transactionId: TransactionIdStr;
+ exchangeBaseUrl: string;
+ /**
+ * @deprecated use transaction ID instead.
+ */
+ peerPushCreditId: string;
/**
* @deprecated
*/
amount: AmountString;
- amountRaw: AmountString;
- amountEffective: AmountString;
- peerPushCreditId: string;
- transactionId: string;
}
```
@@ -2075,7 +2303,7 @@ export interface PreparePeerPullDebitResponse {
amountRaw: AmountString;
amountEffective: AmountString;
peerPullDebitId: string;
- transactionId: string;
+ transactionId: TransactionIdStr;
}
```
@@ -2101,7 +2329,7 @@ export interface ConfirmPeerPullDebitRequest {
* @deprecated use transactionId instead
*/
peerPullDebitId?: string;
- transactionId?: string;
+ transactionId?: TransactionIdStr;
}
```
@@ -2147,12 +2375,18 @@ export type ExportDbOp = {
```typescript
export type ImportDbOp = {
op: WalletApiOperation.ImportDb;
- request: any;
- response: any;
+ request: ImportDbRequest;
+ response: EmptyObject;
};
// ImportDb = "importDb"
```
+```typescript
+export interface ImportDbRequest {
+ dump: any;
+}
+
+```
### ClearDbOp
```typescript
@@ -2432,6 +2666,10 @@ export interface PendingTaskInfoCommon {
* exceeds a number of retries.
*/
retryInfo?: DbRetryInfo;
+ /**
+ * Internal operation status for debugging.
+ */
+ internalOperationStatus?: string;
}
```
@@ -2939,7 +3177,7 @@ export type TestingWaitTransactionStateOp = {
```
```typescript
export interface TestingWaitTransactionRequest {
- transactionId: string;
+ transactionId: TransactionIdStr;
txState: TransactionState;
}
@@ -2991,15 +3229,27 @@ export interface ForceRefreshRequest {
## Common Declarations
```typescript
export interface WalletCoreVersion {
+ implementationSemver: string;
+ implementationGitHash: string;
/**
- * @deprecated
+ * Wallet-core protocol version supported by this implementation
+ * of the API ("server" version).
*/
- hash: string | undefined;
version: string;
exchange: string;
merchant: string;
+ bankIntegrationApiRange: string;
+ bankConversionApiRange: string;
+ corebankApiRange: string;
+ /**
+ * @deprecated as bank was split into multiple APIs with separate versioning
+ */
bank: string;
/**
+ * @deprecated
+ */
+ hash: string | undefined;
+ /**
* @deprecated will be removed
*/
devMode: boolean;
@@ -3060,7 +3310,8 @@ export type Transaction =
| TransactionPeerPullDebit
| TransactionPeerPushCredit
| TransactionPeerPushDebit
- | TransactionInternalWithdrawal;
+ | TransactionInternalWithdrawal
+ | TransactionRecoup;
```
```typescript
/**
@@ -3130,6 +3381,7 @@ export declare enum TransactionType {
PeerPushCredit = "peer-push-credit",
PeerPullDebit = "peer-pull-debit",
PeerPullCredit = "peer-pull-credit",
+ Recoup = "recoup",
}
```
```typescript
@@ -3199,6 +3451,7 @@ export declare enum TransactionMinorState {
CheckRefund = "check-refund",
CreatePurse = "create-purse",
DeletePurse = "delete-purse",
+ RefreshExpired = "refresh-expired",
Ready = "ready",
Merge = "merge",
Repurchase = "repurchase",
@@ -3269,8 +3522,11 @@ interface WithdrawalDetailsForManualTransfer {
* Payto URIs that the exchange supports.
*
* Already contains the amount and message.
+ *
+ * @deprecated in favor of exchangeCreditAccounts
*/
exchangePaytoUris: string[];
+ exchangeCreditAccountDetails?: WithdrawalExchangeAccountDetails[];
reservePub: string;
/**
* Is the reserve ready for withdrawal?
@@ -3279,6 +3535,85 @@ interface WithdrawalDetailsForManualTransfer {
}
```
```typescript
+export interface WithdrawalExchangeAccountDetails {
+ /**
+ * Payto URI to credit the exchange.
+ *
+ * Depending on whether the (manual!) withdrawal is accepted or just
+ * being checked, this already includes the subject with the
+ * reserve public key.
+ */
+ paytoUri: string;
+ /**
+ * Status that indicates whether the account can be used
+ * by the user to send funds for a withdrawal.
+ *
+ * ok: account should be shown to the user
+ * error: account should not be shown to the user, UIs might render the error (in conversionError),
+ * especially in dev mode.
+ */
+ status: "ok" | "error";
+ /**
+ * Transfer amount. Might be in a different currency than the requested
+ * amount for withdrawal.
+ *
+ * Redundant with the amount in paytoUri, just included to avoid parsing.
+ *
+ * Only included if this account does a currency conversion.
+ */
+ transferAmount?: AmountString;
+ /**
+ * Currency specification for the external currency.
+ *
+ * Only included if this account requires a currency conversion.
+ */
+ currencySpecification?: CurrencySpecification;
+ /**
+ * Further restrictions for sending money to the
+ * exchange.
+ */
+ creditRestrictions?: AccountRestriction[];
+ /**
+ * Error that happened when attempting to request the conversion rate.
+ */
+ conversionError?: TalerErrorDetail;
+}
+```
+```typescript
+export interface CurrencySpecification {
+ name: string;
+ num_fractional_input_digits: Integer;
+ num_fractional_normal_digits: Integer;
+ num_fractional_trailing_zero_digits: Integer;
+ alt_unit_names: {
+ [log10: string]: string;
+ };
+}
+```
+```typescript
+export type AccountRestriction =
+ | RegexAccountRestriction
+ | DenyAllAccountRestriction;
+```
+```typescript
+export interface RegexAccountRestriction {
+ type: "regex";
+ payto_regex: string;
+ human_hint: string;
+ human_hint_i18n?: InternationalizedString;
+}
+```
+```typescript
+export interface InternationalizedString {
+ [lang_tag: string]: string;
+}
+```
+```typescript
+export interface DenyAllAccountRestriction {
+ type: "deny";
+}
+```
+```typescript
interface WithdrawalDetailsForTalerBankIntegrationApi {
type: WithdrawalType.TalerBankIntegrationApi;
/**
@@ -3297,6 +3632,7 @@ interface WithdrawalDetailsForTalerBankIntegrationApi {
* Is the reserve ready for withdrawal?
*/
reserveIsReady: boolean;
+ exchangeCreditAccountDetails?: WithdrawalExchangeAccountDetails[];
}
```
```typescript
@@ -3406,11 +3742,6 @@ export interface Location {
}
```
```typescript
-export interface InternationalizedString {
- [lang_tag: string]: string;
-}
-```
-```typescript
export interface RefundInfoShort {
transactionId: string;
timestamp: TalerProtocolTimestamp;
@@ -3495,6 +3826,7 @@ export declare enum RefreshReason {
AbortPay = "abort-pay",
AbortDeposit = "abort-deposit",
AbortPeerPushDebit = "abort-peer-push-debit",
+ AbortPeerPullDebit = "abort-peer-pull-debit",
Recoup = "recoup",
BackupRestored = "backup-restored",
Scheduled = "scheduled",
@@ -3558,8 +3890,10 @@ export interface TransactionPeerPullCredit extends TransactionCommon {
amountEffective: AmountString;
/**
* URI to send to the other party.
+ *
+ * Only available in the right state.
*/
- talerUri: string;
+ talerUri: string | undefined;
}
```
```typescript
@@ -3625,8 +3959,11 @@ export interface TransactionPeerPushDebit extends TransactionCommon {
amountEffective: AmountString;
/**
* URI to accept the payment.
+ *
+ * Only present if the transaction is in a state where the other party can
+ * accept the payment.
*/
- talerUri: string;
+ talerUri?: string;
}
```
```typescript
@@ -3661,11 +3998,22 @@ export interface TransactionInternalWithdrawal extends TransactionCommon {
}
```
```typescript
+/**
+ * The exchange revoked a key and the wallet recoups funds.
+ */
+export interface TransactionRecoup extends TransactionCommon {
+ type: TransactionType.Recoup;
+}
+```
+```typescript
export interface AbortTransactionRequest {
transactionId: TransactionIdStr;
}
```
```typescript
+/**
+ * Info about an exchange entry in the wallet.
+ */
export interface ExchangeListItem {
exchangeBaseUrl: string;
currency: string | undefined;
@@ -3674,6 +4022,7 @@ export interface ExchangeListItem {
exchangeEntryStatus: ExchangeEntryStatus;
exchangeUpdateStatus: ExchangeUpdateStatus;
ageRestrictionOptions: number[];
+ scopeInfo: ScopeInfo | undefined;
/**
* Information about the last error that occurred when trying
* to update the exchange info.
@@ -3698,12 +4047,11 @@ export declare enum ExchangeEntryStatus {
```typescript
export declare enum ExchangeUpdateStatus {
Initial = "initial",
- InitialUpdate = "initial(update)",
+ InitialUpdate = "initial-update",
Suspended = "suspended",
- Failed = "failed",
- OutdatedUpdate = "outdated(update)",
+ UnavailableUpdate = "unavailable-update",
Ready = "ready",
- ReadyUpdate = "ready(update)",
+ ReadyUpdate = "ready-update",
}
```
```typescript
@@ -3985,8 +4333,11 @@ export interface ForcedCoinSel {
```typescript
export interface AddExchangeRequest {
exchangeBaseUrl: string;
- masterPub?: string;
+ /**
+ * @deprecated use a separate API call to start a forced exchange update instead
+ */
forceUpdate?: boolean;
+ masterPub?: string;
}
```
```typescript